/* * Copyright 2008 Haiku Inc. All rights reserved. * Distributed under the terms of the MIT License. * * Authors: * Julun, #include #include #include #include namespace BPrivate { namespace Print { // TODO: remove, after pr_server.h cleanup // mime file types #define PSRV_PRINTER_MIMETYPE "application/x-vnd.Be.printer" // printer attributes #define PSRV_PRINTER_ATTR_STATE "state" #define PSRV_PRINTER_ATTR_COMMENTS "Comments" #define PSRV_PRINTER_ATTR_TRANSPORT "transport" #define PSRV_PRINTER_ATTR_DRIVER_NAME "Driver Name" #define PSRV_PRINTER_ATTR_PRINTER_NAME "Printer Name" #define PSRV_PRINTER_ATTR_DEFAULT_PRINTER "Default Printer" #define PSRV_PRINTER_ATTR_TRANSPORT_ADDRESS "transport_address" // message fields #define PSRV_FIELD_CURRENT_PRINTER "current_printer" BPrinter::BPrinter() : fListener(NULL) { memset(&fPrinterEntryRef, 0, sizeof(entry_ref)); } BPrinter::BPrinter(const BEntry& entry) : fListener(NULL) { SetTo(entry); } BPrinter::BPrinter(const BPrinter& printer) { *this = printer; } BPrinter::BPrinter(const node_ref& nodeRef) : fListener(NULL) { SetTo(nodeRef); } BPrinter::BPrinter(const entry_ref& entryRef) : fListener(NULL) , fPrinterEntryRef(entryRef) { } BPrinter::BPrinter(const BDirectory& directory) : fListener(NULL) { SetTo(directory); } BPrinter::~BPrinter() { StopWatching(); } status_t BPrinter::SetTo(const BEntry& entry) { StopWatching(); entry.GetRef(&fPrinterEntryRef); return InitCheck(); } status_t BPrinter::SetTo(const node_ref& nodeRef) { SetTo(BDirectory(&nodeRef)); return InitCheck(); } status_t BPrinter::SetTo(const entry_ref& entryRef) { StopWatching(); fPrinterEntryRef = entryRef; return InitCheck(); } status_t BPrinter::SetTo(const BDirectory& directory) { StopWatching(); BEntry entry; directory.GetEntry(&entry); entry.GetRef(&fPrinterEntryRef); return InitCheck(); } void BPrinter::Unset() { StopWatching(); memset(&fPrinterEntryRef, 0, sizeof(entry_ref)); } bool BPrinter::IsValid() const { BDirectory spoolDir(&fPrinterEntryRef); if (spoolDir.InitCheck() != B_OK) return false; BNode node(spoolDir); char type[B_MIME_TYPE_LENGTH]; BNodeInfo(&node).GetType(type); if (strcmp(type, PSRV_PRINTER_MIMETYPE) != 0) return false; return true; } status_t BPrinter::InitCheck() const { BDirectory spoolDir(&fPrinterEntryRef); return spoolDir.InitCheck(); } bool BPrinter::IsFree() const { return (State() == "free"); } bool BPrinter::IsDefault() const { bool isDefault = false; BDirectory spoolDir(&fPrinterEntryRef); if (spoolDir.InitCheck() == B_OK) spoolDir.ReadAttr(PSRV_PRINTER_ATTR_DEFAULT_PRINTER, B_BOOL_TYPE, 0, &isDefault, sizeof(bool)); return isDefault; } bool BPrinter::IsShareable() const { if (Name() == "Preview") return true; return false; } BString BPrinter::Name() const { return _ReadAttribute(PSRV_PRINTER_ATTR_PRINTER_NAME); } BString BPrinter::State() const { return _ReadAttribute(PSRV_PRINTER_ATTR_STATE); } BString BPrinter::Driver() const { return _ReadAttribute(PSRV_PRINTER_ATTR_DRIVER_NAME); } BString BPrinter::Comments() const { return _ReadAttribute(PSRV_PRINTER_ATTR_COMMENTS); } BString BPrinter::Transport() const { return _ReadAttribute(PSRV_PRINTER_ATTR_TRANSPORT); } BString BPrinter::TransportAddress() const { return _ReadAttribute(PSRV_PRINTER_ATTR_TRANSPORT_ADDRESS); } status_t BPrinter::DefaultSettings(BMessage& settings) { status_t status = B_ERROR; image_id id = _LoadDriver(); if (id < 0) return status; typedef BMessage* (*default_settings_func_t)(BNode*); default_settings_func_t default_settings; if (get_image_symbol(id, "default_settings", B_SYMBOL_TYPE_TEXT , (void**)&default_settings) == B_OK) { BNode printerNode(&fPrinterEntryRef); BMessage *newSettings = default_settings(&printerNode); if (newSettings) { status = B_OK; settings = *newSettings; _AddPrinterName(settings); } delete newSettings; } unload_add_on(id); return status; } status_t BPrinter::StartWatching(const BMessenger& listener) { StopWatching(); if (!listener.IsValid()) return B_BAD_VALUE; fListener = new(std::nothrow) BMessenger(listener); if (!fListener) return B_NO_MEMORY; node_ref nodeRef; nodeRef.device = fPrinterEntryRef.device; nodeRef.node = fPrinterEntryRef.directory; return watch_node(&nodeRef, B_WATCH_DIRECTORY, *fListener); } void BPrinter::StopWatching() { if (fListener) { stop_watching(*fListener); delete fListener; fListener = NULL; } } BPrinter& BPrinter::operator=(const BPrinter& printer) { if (this != &printer) { Unset(); fPrinterEntryRef = printer.fPrinterEntryRef; if (printer.fListener) StartWatching(*printer.fListener); } return *this; } bool BPrinter::operator==(const BPrinter& printer) const { return (fPrinterEntryRef == printer.fPrinterEntryRef); } bool BPrinter::operator!=(const BPrinter& printer) const { return (fPrinterEntryRef != printer.fPrinterEntryRef); } status_t BPrinter::_Configure() const { status_t status = B_ERROR; image_id id = _LoadDriver(); if (id < 0) return status; BString printerName(_ReadAttribute(PSRV_PRINTER_ATTR_PRINTER_NAME)); if (printerName.Length() > 0) { typedef char* (*add_printer_func_t)(const char*); add_printer_func_t add_printer; if (get_image_symbol(id, "add_printer", B_SYMBOL_TYPE_TEXT , (void**)&add_printer) == B_OK) { if (add_printer(printerName.String()) != NULL) status = B_OK; } } else { status = B_ERROR; } unload_add_on(id); return status; } status_t BPrinter::_ConfigureJob(BMessage& settings) { status_t status = B_ERROR; image_id id = _LoadDriver(); if (id < 0) return status; typedef BMessage* (*config_job_func_t)(BNode*, const BMessage*); config_job_func_t configure_job; if (get_image_symbol(id, "config_job", B_SYMBOL_TYPE_TEXT , (void**)&configure_job) == B_OK) { BNode printerNode(&fPrinterEntryRef); BMessage *newSettings = configure_job(&printerNode, &settings); if (newSettings && (newSettings->what == 'okok')) { status = B_OK; settings = *newSettings; _AddPrinterName(settings); } delete newSettings; } unload_add_on(id); return status; } status_t BPrinter::_ConfigurePage(BMessage& settings) { status_t status = B_ERROR; image_id id = _LoadDriver(); if (id < 0) return status; typedef BMessage* (*config_page_func_t)(BNode*, const BMessage*); config_page_func_t configure_page; if (get_image_symbol(id, "config_page", B_SYMBOL_TYPE_TEXT , (void**)&configure_page) == B_OK) { BNode printerNode(&fPrinterEntryRef); BMessage *newSettings = configure_page(&printerNode, &settings); if (newSettings && (newSettings->what == 'okok')) { status = B_OK; settings = *newSettings; _AddPrinterName(settings); } delete newSettings; } unload_add_on(id); return status; } BPath BPrinter::_DriverPath() const { BString driverName(_ReadAttribute(PSRV_PRINTER_ATTR_DRIVER_NAME)); if (driverName.Length() <= 0) return BPath(); directory_which directories[] = { B_USER_NONPACKAGED_ADDONS_DIRECTORY, B_USER_ADDONS_DIRECTORY, B_SYSTEM_NONPACKAGED_ADDONS_DIRECTORY, B_SYSTEM_ADDONS_DIRECTORY }; BPath path; driverName.Prepend("Print/"); for (int32 i = 0; i < sizeof(directories) / sizeof(directories[0]); ++i) { if (find_directory(directories[i], &path) == B_OK) { path.Append(driverName.String()); BEntry driver(path.Path()); if (driver.InitCheck() == B_OK && driver.Exists() && driver.IsFile()) return path; } } return BPath(); } image_id BPrinter::_LoadDriver() const { BPath driverPath(_DriverPath()); if (driverPath.InitCheck() != B_OK) return -1; return load_add_on(driverPath.Path()); } void BPrinter::_AddPrinterName(BMessage& settings) { settings.RemoveName(PSRV_FIELD_CURRENT_PRINTER); settings.AddString(PSRV_FIELD_CURRENT_PRINTER, Name()); } BString BPrinter::_ReadAttribute(const char* attribute) const { BString value; BDirectory spoolDir(&fPrinterEntryRef); if (spoolDir.InitCheck() == B_OK) spoolDir.ReadAttrString(attribute, &value); return value; } } // namespace Print } // namespace BPrivate