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_NONPACKAGED_ADDONS_DIRECTORY,
46		B_USER_ADDONS_DIRECTORY,
47		B_SYSTEM_NONPACKAGED_ADDONS_DIRECTORY,
48		B_BEOS_ADDONS_DIRECTORY,
49	};
50	BPath path;
51	for (uint32 i = 0; i < sizeof(paths) / sizeof(paths[0]); ++i) {
52		if (find_directory(paths[i], &path) != B_OK)
53			continue;
54		path.Append("Print/transport");
55		path.Append(printerData->GetTransport().c_str());
56		DBGMSG(("load_add_on: %s\n", path.Path()));
57		fImage = load_add_on(path.Path());
58		if (fImage >= 0)
59			break;
60	}
61
62	if (fImage < 0) {
63		SetLastError("cannot load a transport add-on");
64		return;
65	}
66
67	DBGMSG(("image id = %d\n", (int)fImage));
68
69	get_image_symbol(fImage, "init_transport", B_SYMBOL_TYPE_TEXT, (void **)&fInitTransport);
70	get_image_symbol(fImage, "exit_transport", B_SYMBOL_TYPE_TEXT, (void **)&fExitTransport);
71
72	if (fInitTransport == NULL) {
73		SetLastError("get_image_symbol failed.");
74		DBGMSG(("init_transport is NULL\n"));
75	}
76
77	if (fExitTransport == NULL) {
78		SetLastError("get_image_symbol failed.");
79		DBGMSG(("exit_transport is NULL\n"));
80	}
81
82	if (fInitTransport) {
83		string spool_path;
84		printerData->GetPath(spool_path);
85		BMessage *msg = new BMessage('TRIN');
86		msg->AddString("printer_file", spool_path.c_str());
87		fDataStream = (*fInitTransport)(msg);
88		delete msg;
89		if (fDataStream == 0) {
90			SetLastError("init_transport failed.");
91		}
92	}
93}
94
95
96Transport::~Transport()
97{
98	if (fExitTransport) {
99		(*fExitTransport)();
100	}
101	if (fImage >= 0) {
102		unload_add_on(fImage);
103	}
104}
105
106
107bool
108Transport::CheckAbort() const
109{
110	return fDataStream == 0;
111}
112
113
114const
115string &Transport::LastError() const
116{
117	return fLastErrorString;
118}
119
120
121bool
122Transport::IsPrintToFileCanceled() const
123{
124	// The BeOS "Print To File" transport add-on returns a non-NULL BDataIO *
125	// even after user filepanel cancellation!
126	BFile* file = dynamic_cast<BFile*>(fDataStream);
127	return file != NULL && file->InitCheck() != B_OK;
128}
129
130
131void
132Transport::SetLastError(const char *e)
133{
134	fLastErrorString = e;
135	fAbort = true;
136}
137
138
139void
140Transport::Write(const void* buffer, size_t size)
141{
142	if (fDataStream) {
143		if (size == (size_t)fDataStream->Write(buffer, size)) {
144			return;
145		}
146		SetLastError("BDataIO::Write failed.");
147	}
148	throw TransportException(LastError());
149}
150
151
152void
153Transport::Read(void* buffer, size_t size)
154{
155	if (fDataStream) {
156		if (size == (size_t)fDataStream->Read(buffer, size)) {
157			return;
158		}
159		SetLastError("BDataIO::Read failed.");
160	}
161	throw TransportException(LastError());
162}
163