1/*
2 * Transport.cpp
3 * Copyright 1999-2000 Y.Takagi. All Rights Reserved.
4 */
5
6#include <FindDirectory.h>
7#include <Message.h>
8#include <Directory.h>
9#include <DataIO.h>
10#include <File.h>
11#include <Path.h>
12#include <image.h>
13
14#include "Transport.h"
15#include "PrinterData.h"
16#include "DbgMsg.h"
17
18
19using namespace std;
20
21
22TransportException::TransportException(const string& what)
23	:
24	fWhat(what)
25{
26}
27
28
29const char*
30TransportException::What() const
31{
32	return fWhat.c_str();
33}
34
35
36Transport::Transport(const PrinterData *printerData)
37	:
38	fImage(-1),
39	fInitTransport(0),
40	fExitTransport(0),
41	fDataStream(0),
42	fAbort(false)
43{
44	const directory_which paths[] = {
45		B_USER_ADDONS_DIRECTORY,
46		B_COMMON_ADDONS_DIRECTORY,
47		B_BEOS_ADDONS_DIRECTORY,
48	};
49	BPath path;
50	for (uint32 i = 0; i < sizeof(paths) / sizeof(paths[0]); ++i) {
51		if (find_directory(paths[i], &path) != B_OK)
52			continue;
53		path.Append("Print/transport");
54		path.Append(printerData->GetTransport().c_str());
55		DBGMSG(("load_add_on: %s\n", path.Path()));
56		fImage = load_add_on(path.Path());
57		if (fImage >= 0)
58			break;
59	}
60
61	if (fImage < 0) {
62		SetLastError("cannot load a transport add-on");
63		return;
64	}
65
66	DBGMSG(("image id = %d\n", (int)fImage));
67
68	get_image_symbol(fImage, "init_transport", B_SYMBOL_TYPE_TEXT, (void **)&fInitTransport);
69	get_image_symbol(fImage, "exit_transport", B_SYMBOL_TYPE_TEXT, (void **)&fExitTransport);
70
71	if (fInitTransport == NULL) {
72		SetLastError("get_image_symbol failed.");
73		DBGMSG(("init_transport is NULL\n"));
74	}
75
76	if (fExitTransport == NULL) {
77		SetLastError("get_image_symbol failed.");
78		DBGMSG(("exit_transport is NULL\n"));
79	}
80
81	if (fInitTransport) {
82		string spool_path;
83		printerData->GetPath(spool_path);
84		BMessage *msg = new BMessage('TRIN');
85		msg->AddString("printer_file", spool_path.c_str());
86		fDataStream = (*fInitTransport)(msg);
87		delete msg;
88		if (fDataStream == 0) {
89			SetLastError("init_transport failed.");
90		}
91	}
92}
93
94
95Transport::~Transport()
96{
97	if (fExitTransport) {
98		(*fExitTransport)();
99	}
100	if (fImage >= 0) {
101		unload_add_on(fImage);
102	}
103}
104
105
106bool
107Transport::CheckAbort() const
108{
109	return fDataStream == 0;
110}
111
112
113const
114string &Transport::LastError() const
115{
116	return fLastErrorString;
117}
118
119
120bool
121Transport::IsPrintToFileCanceled() const
122{
123	// The BeOS "Print To File" transport add-on returns a non-NULL BDataIO *
124	// even after user filepanel cancellation!
125	BFile* file = dynamic_cast<BFile*>(fDataStream);
126	return file != NULL && file->InitCheck() != B_OK;
127}
128
129
130void
131Transport::SetLastError(const char *e)
132{
133	fLastErrorString = e;
134	fAbort = true;
135}
136
137
138void
139Transport::Write(const void* buffer, size_t size) throw(TransportException)
140{
141	if (fDataStream) {
142		if (size == (size_t)fDataStream->Write(buffer, size)) {
143			return;
144		}
145		SetLastError("BDataIO::Write failed.");
146	}
147	throw TransportException(LastError());
148}
149