174462Salfred/*
274462Salfred * Copyright 2008 Haiku Inc. All rights reserved.
3258578Shrs * Distributed under the terms of the MIT License.
4258578Shrs *
5258578Shrs * Authors:
6258578Shrs *		Julun, <host.haiku@gmx.de
7258578Shrs */
8258578Shrs
9258578Shrs#include <Printer.h>
10258578Shrs
11258578Shrs#include <FindDirectory.h>
12258578Shrs#include <NodeInfo.h>
13258578Shrs#include <NodeMonitor.h>
14258578Shrs
15258578Shrs
16258578Shrs#include <new>
1774462Salfred
18258578Shrs
19258578Shrsnamespace BPrivate {
20258578Shrs	namespace Print {
21258578Shrs
22258578Shrs
23258578Shrs// TODO: remove, after pr_server.h cleanup
24258578Shrs
25258578Shrs// mime file types
26258578Shrs#define PSRV_PRINTER_MIMETYPE					"application/x-vnd.Be.printer"
27258578Shrs
28258578Shrs
2974462Salfred// printer attributes
3074462Salfred#define PSRV_PRINTER_ATTR_STATE					"state"
3174462Salfred#define PSRV_PRINTER_ATTR_COMMENTS				"Comments"
3274462Salfred#define PSRV_PRINTER_ATTR_TRANSPORT				"transport"
3374462Salfred#define PSRV_PRINTER_ATTR_DRIVER_NAME			"Driver Name"
34136581Sobrien#define PSRV_PRINTER_ATTR_PRINTER_NAME			"Printer Name"
35136581Sobrien#define PSRV_PRINTER_ATTR_DEFAULT_PRINTER		"Default Printer"
3674462Salfred#define PSRV_PRINTER_ATTR_TRANSPORT_ADDRESS		"transport_address"
3774462Salfred
3892990Sobrien
3992990Sobrien// message fields
4074462Salfred#define PSRV_FIELD_CURRENT_PRINTER				"current_printer"
4174462Salfred
4274462Salfred
4374462SalfredBPrinter::BPrinter()
4474462Salfred	: fListener(NULL)
4575094Siedowse{
4674462Salfred	memset(&fPrinterEntryRef, 0, sizeof(entry_ref));
4774462Salfred}
48105189Siedowse
4974462Salfred
5074462SalfredBPrinter::BPrinter(const BEntry& entry)
5174462Salfred	: fListener(NULL)
5290868Smike{
5374462Salfred	SetTo(entry);
54181344Sdfr}
5574462Salfred
5674462Salfred
5774462SalfredBPrinter::BPrinter(const BPrinter& printer)
5874462Salfred{
5974462Salfred	*this = printer;
6074462Salfred}
6174462Salfred
6274462Salfred
63156090SdeischenBPrinter::BPrinter(const node_ref& nodeRef)
6474462Salfred	: fListener(NULL)
6574462Salfred{
66167199Ssimon	SetTo(nodeRef);
67167199Ssimon}
68167199Ssimon
69167199Ssimon
70167199SsimonBPrinter::BPrinter(const entry_ref& entryRef)
71167199Ssimon	: fListener(NULL)
7274462Salfred	, fPrinterEntryRef(entryRef)
73167199Ssimon{
7474462Salfred}
7574462Salfred
7692905Sobrien
7792905SobrienBPrinter::BPrinter(const BDirectory& directory)
7895658Sdes	: fListener(NULL)
7995658Sdes{
8092905Sobrien	SetTo(directory);
8195658Sdes}
8292905Sobrien
8399996Salfred
8492905SobrienBPrinter::~BPrinter()
8574462Salfred{
8674462Salfred	StopWatching();
8774462Salfred}
8874462Salfred
8974462Salfred
9074462Salfredstatus_t
9174462SalfredBPrinter::SetTo(const BEntry& entry)
9274462Salfred{
9374462Salfred	StopWatching();
9474462Salfred	entry.GetRef(&fPrinterEntryRef);
9574462Salfred
9674462Salfred	return InitCheck();
9774462Salfred}
9874462Salfred
9974462Salfred
10074462Salfredstatus_t
10174462SalfredBPrinter::SetTo(const node_ref& nodeRef)
10274462Salfred{
10374462Salfred	SetTo(BDirectory(&nodeRef));
10474462Salfred	return InitCheck();
10574462Salfred}
10675144Siedowse
10774462Salfred
108105189Siedowsestatus_t
10974462SalfredBPrinter::SetTo(const entry_ref& entryRef)
11074462Salfred{
11174462Salfred	StopWatching();
11274462Salfred	fPrinterEntryRef = entryRef;
11374462Salfred
11474462Salfred	return InitCheck();
11574462Salfred}
116181344Sdfr
117181344Sdfr
11874462Salfredstatus_t
11974462SalfredBPrinter::SetTo(const BDirectory& directory)
12074462Salfred{
12174462Salfred	StopWatching();
12274462Salfred
12374462Salfred	BEntry entry;
12474462Salfred	directory.GetEntry(&entry);
12574462Salfred	entry.GetRef(&fPrinterEntryRef);
12674462Salfred
12774462Salfred	return InitCheck();
12874462Salfred}
12974462Salfred
13074462Salfred
13174462Salfredvoid
132181344SdfrBPrinter::Unset()
13374462Salfred{
13474462Salfred	StopWatching();
13574879Swpaul	memset(&fPrinterEntryRef, 0, sizeof(entry_ref));
13678678Siedowse}
13778678Siedowse
138105189Siedowse
139105189Siedowsebool
14074462SalfredBPrinter::IsValid() const
14174462Salfred{
14274462Salfred	BDirectory spoolDir(&fPrinterEntryRef);
14374462Salfred	if (spoolDir.InitCheck() != B_OK)
14474462Salfred		return false;
14574462Salfred
14674462Salfred	BNode node(spoolDir);
14774462Salfred	char type[B_MIME_TYPE_LENGTH];
14874462Salfred	BNodeInfo(&node).GetType(type);
14974462Salfred
15074462Salfred	if (strcmp(type, PSRV_PRINTER_MIMETYPE) != 0)
15174462Salfred		return false;
15274462Salfred
15374462Salfred	return true;
15474462Salfred}
15574462Salfred
156287341Srodrigc
157287341Srodrigcstatus_t
158287341SrodrigcBPrinter::InitCheck() const
159287341Srodrigc{
160287341Srodrigc	BDirectory spoolDir(&fPrinterEntryRef);
161287341Srodrigc	return spoolDir.InitCheck();
162287341Srodrigc}
16374462Salfred
16474462Salfred
165287341Srodrigcbool
166287341SrodrigcBPrinter::IsFree() const
16774462Salfred{
16874462Salfred	return (State() == "free");
16974462Salfred}
17074462Salfred
17174462Salfred
17274462Salfredbool
17374462SalfredBPrinter::IsDefault() const
17474462Salfred{
17574462Salfred	bool isDefault = false;
17674462Salfred
17774462Salfred	BDirectory spoolDir(&fPrinterEntryRef);
17874462Salfred	if (spoolDir.InitCheck() == B_OK)
17974462Salfred		spoolDir.ReadAttr(PSRV_PRINTER_ATTR_DEFAULT_PRINTER, B_BOOL_TYPE, 0,
18074462Salfred			&isDefault, sizeof(bool));
18174462Salfred
18274462Salfred	return isDefault;
18374462Salfred}
18474462Salfred
18574462Salfred
18674462Salfredbool
18774462SalfredBPrinter::IsShareable() const
18874462Salfred{
18974462Salfred	if (Name() == "Preview")
19074462Salfred		return true;
19174462Salfred
19274462Salfred	return false;
19374462Salfred}
19474462Salfred
19574462Salfred
19674462SalfredBString
19774462SalfredBPrinter::Name() const
19874462Salfred{
19974462Salfred	return _ReadAttribute(PSRV_PRINTER_ATTR_PRINTER_NAME);
20074462Salfred}
20174462Salfred
20274462Salfred
20374462SalfredBString
20474462SalfredBPrinter::State() const
20574462Salfred{
20674462Salfred	return _ReadAttribute(PSRV_PRINTER_ATTR_STATE);
20774462Salfred}
20874462Salfred
20974462Salfred
21074462SalfredBString
21174462SalfredBPrinter::Driver() const
21274462Salfred{
21374462Salfred	return _ReadAttribute(PSRV_PRINTER_ATTR_DRIVER_NAME);
21474462Salfred}
21574462Salfred
21674462Salfred
21774462SalfredBString
21874462SalfredBPrinter::Comments() const
21974462Salfred{
22074462Salfred	return _ReadAttribute(PSRV_PRINTER_ATTR_COMMENTS);
22174462Salfred}
22274462Salfred
22374462Salfred
22474462SalfredBString
22574462SalfredBPrinter::Transport() const
22674462Salfred{
22774462Salfred	return _ReadAttribute(PSRV_PRINTER_ATTR_TRANSPORT);
22874462Salfred}
22974462Salfred
23074462Salfred
23174462SalfredBString
23274462SalfredBPrinter::TransportAddress() const
23374462Salfred{
23474462Salfred	return _ReadAttribute(PSRV_PRINTER_ATTR_TRANSPORT_ADDRESS);
23574462Salfred}
23674462Salfred
23774462Salfred
23874462Salfredstatus_t
23974462SalfredBPrinter::DefaultSettings(BMessage& settings)
24074462Salfred{
24174462Salfred	status_t status = B_ERROR;
24274462Salfred	image_id id = _LoadDriver();
24374462Salfred	if (id < 0)
24474462Salfred		return status;
24574462Salfred
24674462Salfred	typedef BMessage* (*default_settings_func_t)(BNode*);
24774462Salfred	default_settings_func_t default_settings;
24874462Salfred	if (get_image_symbol(id, "default_settings", B_SYMBOL_TYPE_TEXT
24974462Salfred		, (void**)&default_settings) == B_OK) {
25074462Salfred		BNode printerNode(&fPrinterEntryRef);
25174462Salfred		BMessage *newSettings = default_settings(&printerNode);
25274462Salfred		if (newSettings) {
25374462Salfred			status = B_OK;
25474879Swpaul			settings = *newSettings;
25578678Siedowse			_AddPrinterName(settings);
25678678Siedowse		}
25774462Salfred		delete newSettings;
25874462Salfred	}
25974462Salfred	unload_add_on(id);
26074462Salfred	return status;
261181344Sdfr}
262181344Sdfr
263181344Sdfr
26474462Salfredstatus_t
26574462SalfredBPrinter::StartWatching(const BMessenger& listener)
26674462Salfred{
26774462Salfred	StopWatching();
26874462Salfred
269181344Sdfr	if (!listener.IsValid())
270181344Sdfr		return B_BAD_VALUE;
27174462Salfred
27274462Salfred	fListener = new(std::nothrow) BMessenger(listener);
27374462Salfred	if (!fListener)
27474462Salfred		return B_NO_MEMORY;
27574462Salfred
27674462Salfred	node_ref nodeRef;
27774462Salfred	nodeRef.device = fPrinterEntryRef.device;
27874462Salfred	nodeRef.node = fPrinterEntryRef.directory;
27974462Salfred
28074462Salfred	return watch_node(&nodeRef, B_WATCH_DIRECTORY, *fListener);
28174462Salfred}
28274462Salfred
28374462Salfred
28474462Salfredvoid
28574462SalfredBPrinter::StopWatching()
28674462Salfred{
28774462Salfred	if (fListener) {
28874462Salfred		stop_watching(*fListener);
28974462Salfred		delete fListener;
290105189Siedowse		fListener = NULL;
291105189Siedowse	}
29274462Salfred}
29374462Salfred
29474462Salfred
29574462SalfredBPrinter&
29674462SalfredBPrinter::operator=(const BPrinter& printer)
29774462Salfred{
29874462Salfred	if (this != &printer) {
29974462Salfred		Unset();
30074462Salfred		fPrinterEntryRef = printer.fPrinterEntryRef;
30174462Salfred		if (printer.fListener)
30274462Salfred			StartWatching(*printer.fListener);
30374462Salfred	}
30474462Salfred	return *this;
30574462Salfred}
306287341Srodrigc
307287341Srodrigc
308287341Srodrigcbool
309287341SrodrigcBPrinter::operator==(const BPrinter& printer) const
310287341Srodrigc{
311287341Srodrigc	return (fPrinterEntryRef == printer.fPrinterEntryRef);
312287341Srodrigc}
313287341Srodrigc
314287341Srodrigc
31574462Salfredbool
316287341SrodrigcBPrinter::operator!=(const BPrinter& printer) const
317287341Srodrigc{
31874462Salfred	return (fPrinterEntryRef != printer.fPrinterEntryRef);
31974462Salfred}
32074462Salfred
321105189Siedowse
32274462Salfredstatus_t
32374462SalfredBPrinter::_Configure() const
32474462Salfred{
32574462Salfred	status_t status = B_ERROR;
326181344Sdfr	image_id id = _LoadDriver();
32774462Salfred	if (id < 0)
32874462Salfred		return status;
329105189Siedowse
330105189Siedowse	BString printerName(_ReadAttribute(PSRV_PRINTER_ATTR_PRINTER_NAME));
331105189Siedowse	if (printerName.Length() > 0) {
33278678Siedowse		typedef char* (*add_printer_func_t)(const char*);
33374462Salfred		add_printer_func_t add_printer;
33474462Salfred		if (get_image_symbol(id, "add_printer", B_SYMBOL_TYPE_TEXT
335278932Spfg			, (void**)&add_printer) == B_OK) {
33674462Salfred				if (add_printer(printerName.String()) != NULL)
337105189Siedowse					status = B_OK;
33874879Swpaul		}
33974462Salfred	} else {
34090271Salfred		status = B_ERROR;
34174462Salfred	}
34274462Salfred	unload_add_on(id);
34374462Salfred	return status;
34474462Salfred}
34574462Salfred
34674462Salfred
34774462Salfredstatus_t
34874462SalfredBPrinter::_ConfigureJob(BMessage& settings)
34974462Salfred{
35074462Salfred	status_t status = B_ERROR;
35174462Salfred	image_id id = _LoadDriver();
35274462Salfred	if (id < 0)
35374462Salfred		return status;
35474462Salfred
35574462Salfred	typedef BMessage* (*config_job_func_t)(BNode*, const BMessage*);
35674462Salfred	config_job_func_t configure_job;
35774462Salfred	if (get_image_symbol(id, "config_job", B_SYMBOL_TYPE_TEXT
35878678Siedowse		, (void**)&configure_job) == B_OK) {
35978678Siedowse		BNode printerNode(&fPrinterEntryRef);
36078678Siedowse		BMessage *newSettings = configure_job(&printerNode, &settings);
36178678Siedowse		if (newSettings && (newSettings->what == 'okok')) {
362105189Siedowse			status = B_OK;
363105189Siedowse			settings = *newSettings;
36478678Siedowse			_AddPrinterName(settings);
36578678Siedowse		}
36678678Siedowse		delete newSettings;
36778678Siedowse	}
36878678Siedowse	unload_add_on(id);
36978678Siedowse	return status;
37078678Siedowse}
37178678Siedowse
37278678Siedowse
37378678Siedowsestatus_t
37474462SalfredBPrinter::_ConfigurePage(BMessage& settings)
37574462Salfred{
376105189Siedowse	status_t status = B_ERROR;
377105189Siedowse	image_id id = _LoadDriver();
37874462Salfred	if (id < 0)
379105189Siedowse		return status;
380105189Siedowse
381105189Siedowse	typedef BMessage* (*config_page_func_t)(BNode*, const BMessage*);
382105189Siedowse	config_page_func_t configure_page;
383105189Siedowse	if (get_image_symbol(id, "config_page", B_SYMBOL_TYPE_TEXT
384105189Siedowse		, (void**)&configure_page) == B_OK) {
385105189Siedowse		BNode printerNode(&fPrinterEntryRef);
386105189Siedowse		BMessage *newSettings = configure_page(&printerNode, &settings);
387105189Siedowse		if (newSettings && (newSettings->what == 'okok')) {
388105189Siedowse			status = B_OK;
38974462Salfred			settings = *newSettings;
390183039Sdfr			_AddPrinterName(settings);
391183039Sdfr		}
39274462Salfred		delete newSettings;
39374462Salfred	}
39474879Swpaul	unload_add_on(id);
39574879Swpaul	return status;
39674462Salfred}
397181344Sdfr
39874879Swpaul
399181344SdfrBPath
400181344SdfrBPrinter::_DriverPath() const
401181344Sdfr{
402181344Sdfr	BString driverName(_ReadAttribute(PSRV_PRINTER_ATTR_DRIVER_NAME));
403181344Sdfr	if (driverName.Length() <= 0)
40474879Swpaul		return BPath();
405181344Sdfr
406181344Sdfr	directory_which directories[] = {
407181344Sdfr		B_USER_ADDONS_DIRECTORY,
408181344Sdfr		B_COMMON_ADDONS_DIRECTORY,
409181344Sdfr		B_SYSTEM_ADDONS_DIRECTORY
410181344Sdfr	};
411181344Sdfr
412181344Sdfr	BPath path;
413181344Sdfr	driverName.Prepend("Print/");
414181344Sdfr	for (int32 i = 0; i < sizeof(directories) / sizeof(directories[0]); ++i) {
415181344Sdfr		if (find_directory(directories[i], &path) == B_OK) {
416181344Sdfr			path.Append(driverName.String());
417181344Sdfr
418181344Sdfr			BEntry driver(path.Path());
419181344Sdfr			if (driver.InitCheck() == B_OK && driver.Exists() && driver.IsFile())
420181344Sdfr				return path;
42174462Salfred		}
42274462Salfred	}
42374462Salfred	return BPath();
42474462Salfred}
42578678Siedowse
42674462Salfred
427105189Siedowseimage_id
428105189SiedowseBPrinter::_LoadDriver() const
42974462Salfred{
43074462Salfred	BPath driverPath(_DriverPath());
43174462Salfred	if (driverPath.InitCheck() != B_OK)
43274462Salfred		return -1;
43374462Salfred
43474462Salfred	return load_add_on(driverPath.Path());
435105189Siedowse}
436105189Siedowse
43774462Salfred
43874879Swpaulvoid
43974879SwpaulBPrinter::_AddPrinterName(BMessage& settings)
44074879Swpaul{
44174462Salfred	settings.RemoveName(PSRV_FIELD_CURRENT_PRINTER);
44274462Salfred	settings.AddString(PSRV_FIELD_CURRENT_PRINTER, Name());
44374462Salfred}
44474462Salfred
44574462Salfred
44674462SalfredBString
447181344SdfrBPrinter::_ReadAttribute(const char* attribute) const
448181344Sdfr{
449181344Sdfr	BString value;
450181344Sdfr
451181344Sdfr	BDirectory spoolDir(&fPrinterEntryRef);
452181344Sdfr	if (spoolDir.InitCheck() == B_OK)
453181344Sdfr		spoolDir.ReadAttrString(attribute, &value);
45474462Salfred
45574462Salfred	return value;
456105189Siedowse}
457105189Siedowse
458105189Siedowse
459105189Siedowse	}	// namespace Print
460105189Siedowse}	// namespace BPrivate
461105189Siedowse