xref: /haiku/src/libs/print/libprint/Transport.cpp (revision 820dca4df6c7bf955c46e8f6521b9408f50b2900)
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_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 
95 Transport::~Transport()
96 {
97 	if (fExitTransport) {
98 		(*fExitTransport)();
99 	}
100 	if (fImage >= 0) {
101 		unload_add_on(fImage);
102 	}
103 }
104 
105 
106 bool
107 Transport::CheckAbort() const
108 {
109 	return fDataStream == 0;
110 }
111 
112 
113 const
114 string &Transport::LastError() const
115 {
116 	return fLastErrorString;
117 }
118 
119 
120 bool
121 Transport::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 
130 void
131 Transport::SetLastError(const char *e)
132 {
133 	fLastErrorString = e;
134 	fAbort = true;
135 }
136 
137 
138 void
139 Transport::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