1121336Sharti/*
2121336Sharti * Transport.cpp
3121336Sharti * Copyright 1999-2000 Y.Takagi. All Rights Reserved.
4121336Sharti */
5121336Sharti
6195767Skensmith#include <FindDirectory.h>
7131834Sharti#include <Message.h>
8121336Sharti#include <Directory.h>
9121336Sharti#include <DataIO.h>
10121336Sharti#include <File.h>
11121336Sharti#include <Path.h>
12121336Sharti#include <image.h>
13121336Sharti
14121336Sharti#include "Transport.h"
15131834Sharti#include "PrinterData.h"
16121336Sharti#include "DbgMsg.h"
17121950Sharti
18131834Sharti
19121336Shartiusing namespace std;
20121336Sharti
21121950Sharti
22121950ShartiTransportException::TransportException(const string& what)
23122217Sharti	:
24122217Sharti	fWhat(what)
25131834Sharti{
26131834Sharti}
27131834Sharti
28121336Sharti
29121336Sharticonst char*
30131834ShartiTransportException::What() const
31121336Sharti{
32121336Sharti	return fWhat.c_str();
33121336Sharti}
34121950Sharti
35121336Sharti
36121336ShartiTransport::Transport(const PrinterData *printerData)
37121336Sharti	:
38121336Sharti	fImage(-1),
39121336Sharti	fInitTransport(0),
40121950Sharti	fExitTransport(0),
41121950Sharti	fDataStream(0),
42121950Sharti	fAbort(false)
43121950Sharti{
44121950Sharti	const directory_which paths[] = {
45122217Sharti		B_USER_ADDONS_DIRECTORY,
46122217Sharti		B_COMMON_ADDONS_DIRECTORY,
47122217Sharti		B_BEOS_ADDONS_DIRECTORY,
48122217Sharti	};
49131834Sharti	BPath path;
50131834Sharti	for (uint32 i = 0; i < sizeof(paths) / sizeof(paths[0]); ++i) {
51131834Sharti		if (find_directory(paths[i], &path) != B_OK)
52131834Sharti			continue;
53121336Sharti		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