xref: /haiku/src/kits/print/Printer.cpp (revision 4b7e219688450694efc9d1890f83f816758c16d3)
1 /*
2  * Copyright 2008 Haiku Inc. All rights reserved.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *		Julun, <host.haiku@gmx.de
7  */
8 
9 #include <Printer.h>
10 
11 #include <FindDirectory.h>
12 #include <NodeInfo.h>
13 #include <NodeMonitor.h>
14 
15 
16 #include <new>
17 
18 
19 namespace BPrivate {
20 	namespace Print {
21 
22 
23 // TODO: remove, after pr_server.h cleanup
24 
25 // mime file types
26 #define PSRV_PRINTER_MIMETYPE					"application/x-vnd.Be.printer"
27 
28 
29 // printer attributes
30 #define PSRV_PRINTER_ATTR_STATE					"state"
31 #define PSRV_PRINTER_ATTR_COMMENTS				"Comments"
32 #define PSRV_PRINTER_ATTR_TRANSPORT				"transport"
33 #define PSRV_PRINTER_ATTR_DRIVER_NAME			"Driver Name"
34 #define PSRV_PRINTER_ATTR_PRINTER_NAME			"Printer Name"
35 #define PSRV_PRINTER_ATTR_DEFAULT_PRINTER		"Default Printer"
36 #define PSRV_PRINTER_ATTR_TRANSPORT_ADDRESS		"transport_address"
37 
38 
39 // message fields
40 #define PSRV_FIELD_CURRENT_PRINTER				"current_printer"
41 
42 
BPrinter()43 BPrinter::BPrinter()
44 	: fListener(NULL)
45 {
46 	memset(&fPrinterEntryRef, 0, sizeof(entry_ref));
47 }
48 
49 
BPrinter(const BEntry & entry)50 BPrinter::BPrinter(const BEntry& entry)
51 	: fListener(NULL)
52 {
53 	SetTo(entry);
54 }
55 
56 
BPrinter(const BPrinter & printer)57 BPrinter::BPrinter(const BPrinter& printer)
58 {
59 	*this = printer;
60 }
61 
62 
BPrinter(const node_ref & nodeRef)63 BPrinter::BPrinter(const node_ref& nodeRef)
64 	: fListener(NULL)
65 {
66 	SetTo(nodeRef);
67 }
68 
69 
BPrinter(const entry_ref & entryRef)70 BPrinter::BPrinter(const entry_ref& entryRef)
71 	: fListener(NULL)
72 	, fPrinterEntryRef(entryRef)
73 {
74 }
75 
76 
BPrinter(const BDirectory & directory)77 BPrinter::BPrinter(const BDirectory& directory)
78 	: fListener(NULL)
79 {
80 	SetTo(directory);
81 }
82 
83 
~BPrinter()84 BPrinter::~BPrinter()
85 {
86 	StopWatching();
87 }
88 
89 
90 status_t
SetTo(const BEntry & entry)91 BPrinter::SetTo(const BEntry& entry)
92 {
93 	StopWatching();
94 	entry.GetRef(&fPrinterEntryRef);
95 
96 	return InitCheck();
97 }
98 
99 
100 status_t
SetTo(const node_ref & nodeRef)101 BPrinter::SetTo(const node_ref& nodeRef)
102 {
103 	SetTo(BDirectory(&nodeRef));
104 	return InitCheck();
105 }
106 
107 
108 status_t
SetTo(const entry_ref & entryRef)109 BPrinter::SetTo(const entry_ref& entryRef)
110 {
111 	StopWatching();
112 	fPrinterEntryRef = entryRef;
113 
114 	return InitCheck();
115 }
116 
117 
118 status_t
SetTo(const BDirectory & directory)119 BPrinter::SetTo(const BDirectory& directory)
120 {
121 	StopWatching();
122 
123 	BEntry entry;
124 	directory.GetEntry(&entry);
125 	entry.GetRef(&fPrinterEntryRef);
126 
127 	return InitCheck();
128 }
129 
130 
131 void
Unset()132 BPrinter::Unset()
133 {
134 	StopWatching();
135 	memset(&fPrinterEntryRef, 0, sizeof(entry_ref));
136 }
137 
138 
139 bool
IsValid() const140 BPrinter::IsValid() const
141 {
142 	BDirectory spoolDir(&fPrinterEntryRef);
143 	if (spoolDir.InitCheck() != B_OK)
144 		return false;
145 
146 	BNode node(spoolDir);
147 	char type[B_MIME_TYPE_LENGTH];
148 	BNodeInfo(&node).GetType(type);
149 
150 	if (strcmp(type, PSRV_PRINTER_MIMETYPE) != 0)
151 		return false;
152 
153 	return true;
154 }
155 
156 
157 status_t
InitCheck() const158 BPrinter::InitCheck() const
159 {
160 	BDirectory spoolDir(&fPrinterEntryRef);
161 	return spoolDir.InitCheck();
162 }
163 
164 
165 bool
IsFree() const166 BPrinter::IsFree() const
167 {
168 	return (State() == "free");
169 }
170 
171 
172 bool
IsDefault() const173 BPrinter::IsDefault() const
174 {
175 	bool isDefault = false;
176 
177 	BDirectory spoolDir(&fPrinterEntryRef);
178 	if (spoolDir.InitCheck() == B_OK)
179 		spoolDir.ReadAttr(PSRV_PRINTER_ATTR_DEFAULT_PRINTER, B_BOOL_TYPE, 0,
180 			&isDefault, sizeof(bool));
181 
182 	return isDefault;
183 }
184 
185 
186 bool
IsShareable() const187 BPrinter::IsShareable() const
188 {
189 	if (Name() == "Preview")
190 		return true;
191 
192 	return false;
193 }
194 
195 
196 BString
Name() const197 BPrinter::Name() const
198 {
199 	return _ReadAttribute(PSRV_PRINTER_ATTR_PRINTER_NAME);
200 }
201 
202 
203 BString
State() const204 BPrinter::State() const
205 {
206 	return _ReadAttribute(PSRV_PRINTER_ATTR_STATE);
207 }
208 
209 
210 BString
Driver() const211 BPrinter::Driver() const
212 {
213 	return _ReadAttribute(PSRV_PRINTER_ATTR_DRIVER_NAME);
214 }
215 
216 
217 BString
Comments() const218 BPrinter::Comments() const
219 {
220 	return _ReadAttribute(PSRV_PRINTER_ATTR_COMMENTS);
221 }
222 
223 
224 BString
Transport() const225 BPrinter::Transport() const
226 {
227 	return _ReadAttribute(PSRV_PRINTER_ATTR_TRANSPORT);
228 }
229 
230 
231 BString
TransportAddress() const232 BPrinter::TransportAddress() const
233 {
234 	return _ReadAttribute(PSRV_PRINTER_ATTR_TRANSPORT_ADDRESS);
235 }
236 
237 
238 status_t
DefaultSettings(BMessage & settings)239 BPrinter::DefaultSettings(BMessage& settings)
240 {
241 	status_t status = B_ERROR;
242 	image_id id = _LoadDriver();
243 	if (id < 0)
244 		return status;
245 
246 	typedef BMessage* (*default_settings_func_t)(BNode*);
247 	default_settings_func_t default_settings;
248 	if (get_image_symbol(id, "default_settings", B_SYMBOL_TYPE_TEXT
249 		, (void**)&default_settings) == B_OK) {
250 		BNode printerNode(&fPrinterEntryRef);
251 		BMessage *newSettings = default_settings(&printerNode);
252 		if (newSettings) {
253 			status = B_OK;
254 			settings = *newSettings;
255 			_AddPrinterName(settings);
256 		}
257 		delete newSettings;
258 	}
259 	unload_add_on(id);
260 	return status;
261 }
262 
263 
264 status_t
StartWatching(const BMessenger & listener)265 BPrinter::StartWatching(const BMessenger& listener)
266 {
267 	StopWatching();
268 
269 	if (!listener.IsValid())
270 		return B_BAD_VALUE;
271 
272 	fListener = new(std::nothrow) BMessenger(listener);
273 	if (!fListener)
274 		return B_NO_MEMORY;
275 
276 	node_ref nodeRef;
277 	nodeRef.device = fPrinterEntryRef.device;
278 	nodeRef.node = fPrinterEntryRef.directory;
279 
280 	return watch_node(&nodeRef, B_WATCH_DIRECTORY, *fListener);
281 }
282 
283 
284 void
StopWatching()285 BPrinter::StopWatching()
286 {
287 	if (fListener) {
288 		stop_watching(*fListener);
289 		delete fListener;
290 		fListener = NULL;
291 	}
292 }
293 
294 
295 BPrinter&
operator =(const BPrinter & printer)296 BPrinter::operator=(const BPrinter& printer)
297 {
298 	if (this != &printer) {
299 		Unset();
300 		fPrinterEntryRef = printer.fPrinterEntryRef;
301 		if (printer.fListener)
302 			StartWatching(*printer.fListener);
303 	}
304 	return *this;
305 }
306 
307 
308 bool
operator ==(const BPrinter & printer) const309 BPrinter::operator==(const BPrinter& printer) const
310 {
311 	return (fPrinterEntryRef == printer.fPrinterEntryRef);
312 }
313 
314 
315 bool
operator !=(const BPrinter & printer) const316 BPrinter::operator!=(const BPrinter& printer) const
317 {
318 	return (fPrinterEntryRef != printer.fPrinterEntryRef);
319 }
320 
321 
322 status_t
_Configure() const323 BPrinter::_Configure() const
324 {
325 	status_t status = B_ERROR;
326 	image_id id = _LoadDriver();
327 	if (id < 0)
328 		return status;
329 
330 	BString printerName(_ReadAttribute(PSRV_PRINTER_ATTR_PRINTER_NAME));
331 	if (printerName.Length() > 0) {
332 		typedef char* (*add_printer_func_t)(const char*);
333 		add_printer_func_t add_printer;
334 		if (get_image_symbol(id, "add_printer", B_SYMBOL_TYPE_TEXT
335 			, (void**)&add_printer) == B_OK) {
336 				if (add_printer(printerName.String()) != NULL)
337 					status = B_OK;
338 		}
339 	} else {
340 		status = B_ERROR;
341 	}
342 	unload_add_on(id);
343 	return status;
344 }
345 
346 
347 status_t
_ConfigureJob(BMessage & settings)348 BPrinter::_ConfigureJob(BMessage& settings)
349 {
350 	status_t status = B_ERROR;
351 	image_id id = _LoadDriver();
352 	if (id < 0)
353 		return status;
354 
355 	typedef BMessage* (*config_job_func_t)(BNode*, const BMessage*);
356 	config_job_func_t configure_job;
357 	if (get_image_symbol(id, "config_job", B_SYMBOL_TYPE_TEXT
358 		, (void**)&configure_job) == B_OK) {
359 		BNode printerNode(&fPrinterEntryRef);
360 		BMessage *newSettings = configure_job(&printerNode, &settings);
361 		if (newSettings && (newSettings->what == 'okok')) {
362 			status = B_OK;
363 			settings = *newSettings;
364 			_AddPrinterName(settings);
365 		}
366 		delete newSettings;
367 	}
368 	unload_add_on(id);
369 	return status;
370 }
371 
372 
373 status_t
_ConfigurePage(BMessage & settings)374 BPrinter::_ConfigurePage(BMessage& settings)
375 {
376 	status_t status = B_ERROR;
377 	image_id id = _LoadDriver();
378 	if (id < 0)
379 		return status;
380 
381 	typedef BMessage* (*config_page_func_t)(BNode*, const BMessage*);
382 	config_page_func_t configure_page;
383 	if (get_image_symbol(id, "config_page", B_SYMBOL_TYPE_TEXT
384 		, (void**)&configure_page) == B_OK) {
385 		BNode printerNode(&fPrinterEntryRef);
386 		BMessage *newSettings = configure_page(&printerNode, &settings);
387 		if (newSettings && (newSettings->what == 'okok')) {
388 			status = B_OK;
389 			settings = *newSettings;
390 			_AddPrinterName(settings);
391 		}
392 		delete newSettings;
393 	}
394 	unload_add_on(id);
395 	return status;
396 }
397 
398 
399 BPath
_DriverPath() const400 BPrinter::_DriverPath() const
401 {
402 	BString driverName(_ReadAttribute(PSRV_PRINTER_ATTR_DRIVER_NAME));
403 	if (driverName.Length() <= 0)
404 		return BPath();
405 
406 	directory_which directories[] = {
407 		B_USER_NONPACKAGED_ADDONS_DIRECTORY,
408 		B_USER_ADDONS_DIRECTORY,
409 		B_SYSTEM_NONPACKAGED_ADDONS_DIRECTORY,
410 		B_SYSTEM_ADDONS_DIRECTORY
411 	};
412 
413 	BPath path;
414 	driverName.Prepend("Print/");
415 	for (int32 i = 0; i < sizeof(directories) / sizeof(directories[0]); ++i) {
416 		if (find_directory(directories[i], &path) == B_OK) {
417 			path.Append(driverName.String());
418 
419 			BEntry driver(path.Path());
420 			if (driver.InitCheck() == B_OK && driver.Exists() && driver.IsFile())
421 				return path;
422 		}
423 	}
424 	return BPath();
425 }
426 
427 
428 image_id
_LoadDriver() const429 BPrinter::_LoadDriver() const
430 {
431 	BPath driverPath(_DriverPath());
432 	if (driverPath.InitCheck() != B_OK)
433 		return -1;
434 
435 	return load_add_on(driverPath.Path());
436 }
437 
438 
439 void
_AddPrinterName(BMessage & settings)440 BPrinter::_AddPrinterName(BMessage& settings)
441 {
442 	settings.RemoveName(PSRV_FIELD_CURRENT_PRINTER);
443 	settings.AddString(PSRV_FIELD_CURRENT_PRINTER, Name());
444 }
445 
446 
447 BString
_ReadAttribute(const char * attribute) const448 BPrinter::_ReadAttribute(const char* attribute) const
449 {
450 	BString value;
451 
452 	BDirectory spoolDir(&fPrinterEntryRef);
453 	if (spoolDir.InitCheck() == B_OK)
454 		spoolDir.ReadAttrString(attribute, &value);
455 
456 	return value;
457 }
458 
459 
460 	}	// namespace Print
461 }	// namespace BPrivate
462