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