xref: /haiku/src/libs/print/libprint/Transport.cpp (revision 427edfcf0ddc74fc461c9355484d33fd4b027b70)
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 
19 using namespace std;
20 
21 
22 TransportException::TransportException(const string& what)
23 	:
24 	fWhat(what)
25 {
26 }
27 
28 
29 const char*
30 TransportException::What() const
31 {
32 	return fWhat.c_str();
33 }
34 
35 
36 Transport::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 
96 Transport::~Transport()
97 {
98 	if (fExitTransport) {
99 		(*fExitTransport)();
100 	}
101 	if (fImage >= 0) {
102 		unload_add_on(fImage);
103 	}
104 }
105 
106 
107 bool
108 Transport::CheckAbort() const
109 {
110 	return fDataStream == 0;
111 }
112 
113 
114 const
115 string &Transport::LastError() const
116 {
117 	return fLastErrorString;
118 }
119 
120 
121 bool
122 Transport::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 
131 void
132 Transport::SetLastError(const char *e)
133 {
134 	fLastErrorString = e;
135 	fAbort = true;
136 }
137 
138 
139 void
140 Transport::Write(const void* buffer, size_t size) throw(TransportException)
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 
152 void
153 Transport::Read(void* buffer, size_t size) throw(TransportException)
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