1/*
2 * Copyright 2001-2010, Haiku, Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 *		Ithamar R. Adema
7 *		Michael Pfeiffer
8 */
9#include "PrinterDriverAddOn.h"
10
11#include <File.h>
12
13#include "BeUtils.h"
14#include "pr_server.h"
15
16
17typedef BMessage* (*config_func_t)(BNode*, const BMessage*);
18typedef BMessage* (*take_job_func_t)(BFile*, BNode*, const BMessage*);
19typedef char* (*add_printer_func_t)(const char* printer_name);
20typedef BMessage* (*default_settings_t)(BNode*);
21
22static const char* kPrinterDriverFolderName = "Print";
23
24
25PrinterDriverAddOn::PrinterDriverAddOn(const char* driver)
26	:
27	fAddOnID(-1)
28{
29	BPath path;
30	status_t result;
31	result = FindPathToDriver(driver, &path);
32	if (result != B_OK)
33		return;
34
35	fAddOnID = ::load_add_on(path.Path());
36}
37
38
39PrinterDriverAddOn::~PrinterDriverAddOn()
40{
41	if (IsLoaded()) {
42		unload_add_on(fAddOnID);
43		fAddOnID = -1;
44	}
45}
46
47
48status_t
49PrinterDriverAddOn::AddPrinter(const char* spoolFolderName)
50{
51	if (!IsLoaded())
52		return B_ERROR;
53
54	add_printer_func_t func;
55	status_t result = get_image_symbol(fAddOnID, "add_printer",
56		B_SYMBOL_TYPE_TEXT, (void**)&func);
57	if (result != B_OK)
58		return result;
59
60	if ((*func)(spoolFolderName) == NULL)
61		return B_ERROR;
62	return B_OK;
63}
64
65
66status_t
67PrinterDriverAddOn::ConfigPage(BDirectory* spoolFolder, BMessage* settings)
68{
69	if (!IsLoaded())
70		return B_ERROR;
71
72	config_func_t func;
73	status_t result = get_image_symbol(fAddOnID, "config_page",
74		B_SYMBOL_TYPE_TEXT, (void**)&func);
75	if (result != B_OK)
76		return result;
77
78	BMessage* newSettings = (*func)(spoolFolder, settings);
79	result = CopyValidSettings(settings, newSettings);
80	delete newSettings;
81
82	return result;
83}
84
85
86status_t
87PrinterDriverAddOn::ConfigJob(BDirectory* spoolFolder, BMessage* settings)
88{
89	if (!IsLoaded())
90		return B_ERROR;
91
92	config_func_t func;
93	status_t result = get_image_symbol(fAddOnID, "config_job",
94		B_SYMBOL_TYPE_TEXT, (void**)&func);
95	if (result != B_OK)
96		return result;
97
98	BMessage* newSettings = (*func)(spoolFolder, settings);
99	result = CopyValidSettings(settings, newSettings);
100	delete newSettings;
101
102	return result;
103}
104
105
106status_t
107PrinterDriverAddOn::DefaultSettings(BDirectory* spoolFolder, BMessage* settings)
108{
109	if (!IsLoaded())
110		return B_ERROR;
111
112	default_settings_t func;
113	status_t result = get_image_symbol(fAddOnID, "default_settings",
114		B_SYMBOL_TYPE_TEXT, (void**)&func);
115	if (result != B_OK)
116		return result;
117
118	BMessage* newSettings = (*func)(spoolFolder);
119	if (newSettings != NULL) {
120		*settings = *newSettings;
121		settings->what = 'okok';
122	} else
123		result = B_ERROR;
124	delete newSettings;
125
126	return result;
127}
128
129
130status_t
131PrinterDriverAddOn::TakeJob(const char* spoolFile, BDirectory* spoolFolder)
132{
133	if (!IsLoaded())
134		return B_ERROR;
135
136	BFile file(spoolFile, B_READ_WRITE);
137	take_job_func_t func;
138	status_t result = get_image_symbol(fAddOnID, "take_job", B_SYMBOL_TYPE_TEXT,
139		(void**)&func);
140	if (result != B_OK)
141		return result;
142
143	// This seems to be required for legacy?
144	// HP PCL3 add-on crashes without it!
145	BMessage parameters(B_REFS_RECEIVED);
146	parameters.AddInt32("file", (addr_t)&file);
147	parameters.AddInt32("printer", (addr_t)spoolFolder);
148
149	BMessage* message = (*func)(&file, spoolFolder, &parameters);
150	if (message == NULL || message->what != 'okok')
151		result = B_ERROR;
152	delete message;
153
154	return result;
155}
156
157
158status_t
159PrinterDriverAddOn::FindPathToDriver(const char* driver, BPath* path)
160{
161	status_t result;
162	result = ::TestForAddonExistence(driver,
163		B_USER_NONPACKAGED_ADDONS_DIRECTORY, kPrinterDriverFolderName, *path);
164	if (result == B_OK)
165		return B_OK;
166
167	result = ::TestForAddonExistence(driver, B_USER_ADDONS_DIRECTORY,
168		kPrinterDriverFolderName, *path);
169	if (result == B_OK)
170		return B_OK;
171
172	result = ::TestForAddonExistence(driver,
173		B_SYSTEM_NONPACKAGED_ADDONS_DIRECTORY, kPrinterDriverFolderName, *path);
174	if (result == B_OK)
175		return B_OK;
176
177	result = ::TestForAddonExistence(driver, B_SYSTEM_ADDONS_DIRECTORY,
178		kPrinterDriverFolderName, *path);
179	return result;
180}
181
182
183bool
184PrinterDriverAddOn::IsLoaded() const
185{
186	return fAddOnID > 0;
187}
188
189
190status_t
191PrinterDriverAddOn::CopyValidSettings(BMessage* settings, BMessage* newSettings)
192{
193	if (newSettings != NULL && newSettings->what != 'baad') {
194		*settings = *newSettings;
195		settings->what = 'okok';
196		return B_OK;
197	}
198	return B_ERROR;
199}
200