diff --git a/src/servers/print/Jamfile b/src/servers/print/Jamfile index e1ede39e33..1319ac6bd9 100644 --- a/src/servers/print/Jamfile +++ b/src/servers/print/Jamfile @@ -8,6 +8,7 @@ AddResources print_server : ; Server print_server : + PrinterDriverAddOn.cpp PrintServerApp.cpp PrintServerApp.R5.cpp PrintServerApp.Scripting.cpp diff --git a/src/servers/print/PrintServerApp.cpp b/src/servers/print/PrintServerApp.cpp index f61c54ad24..66a654e8b2 100644 --- a/src/servers/print/PrintServerApp.cpp +++ b/src/servers/print/PrintServerApp.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2001-2008, Haiku. All rights reserved. + * Copyright 2001-2010, Haiku, Inc. All rights reserved. * Distributed under the terms of the MIT License. * * Authors: @@ -46,10 +46,6 @@ typedef struct _printer_data { } printer_data_t; -typedef BMessage* (*config_func_t)(BNode*, const BMessage*); -typedef BMessage* (*take_job_func_t)(BFile*, BNode*, const BMessage*); -typedef char* (*add_printer_func_t)(const char* printer_name); - static const char* kSettingsName = "print_server_settings"; @@ -423,8 +419,8 @@ PrintServerApp::CreatePrinter(const char* printerName, const char* driverName, char type[B_MIME_TYPE_LENGTH]; BNodeInfo(&printer).GetType(type); if (strcmp(PSRV_PRINTER_FILETYPE, type) == 0) { - BPath tmp; - if (FindPrinterDriver(printerName, tmp) == B_OK) { + BPath path; + if (Printer::FindPathToDriver(printerName, &path) == B_OK) { if (fDefaultPrinter) { // the printer exists, but is not the default printer if (strcmp(fDefaultPrinter->Name(), printerName) != 0) @@ -471,42 +467,20 @@ PrintServerApp::CreatePrinter(const char* printerName, const char* driverName, printer.WriteAttr(PSRV_PRINTER_ATTR_CNX, B_STRING_TYPE, 0, connection, ::strlen(connection) + 1); - // Notify printer driver that a new printer definition node - // has been created. - image_id id = -1; - add_printer_func_t func; - - rc = FindPrinterDriver(driverName, path); - if (rc != B_OK) - goto error; - - id = ::load_add_on(path.Path()); - if (id <= 0) { - rc = B_ERROR; - goto error; - } - - rc = get_image_symbol(id, "add_printer", B_SYMBOL_TYPE_TEXT, (void**)&func); - if (rc != B_OK) - goto error; - - // call the function and check its result - if ((*func)(printerName) == NULL) - rc = B_ERROR; - else + rc = Printer::ConfigurePrinter(driverName, printerName); + if (rc == B_OK) { + // Notify printer driver that a new printer definition node + // has been created. printer.WriteAttr(PSRV_PRINTER_ATTR_STATE, B_STRING_TYPE, 0, "free", ::strlen("free")+1); + } -error: if (rc != B_OK) { BEntry entry; if (printer.GetEntry(&entry) == B_OK) entry.Remove(); } - if (id > 0) - ::unload_add_on(id); - return rc; } @@ -650,35 +624,6 @@ PrintServerApp::FindPrinterNode(const char* name, BNode& node) } -// --------------------------------------------------------------- -// FindPrinterDriver(const char* name, BPath& outPath) -// -// Finds the path to a specific printer driver. It searches all 3 -// places add-ons can be stored: the user's private directory, the -// directory common to all users, and the system directory, in that -// order. -// -// Parameters: -// name - Name of the printer driver to look for. -// outPath - BPath to store the path to the driver in. -// -// Returns: -// B_OK if the driver was found, otherwise an error code. -// --------------------------------------------------------------- -status_t -PrintServerApp::FindPrinterDriver(const char* name, BPath& outPath) -{ - if (::TestForAddonExistence(name, B_USER_ADDONS_DIRECTORY, "Print", outPath) - != B_OK - && TestForAddonExistence(name, B_COMMON_ADDONS_DIRECTORY, "Print", - outPath) != B_OK) - return ::TestForAddonExistence(name, B_BEOS_ADDONS_DIRECTORY, "Print", - outPath); - - return B_OK; -} - - bool PrintServerApp::OpenSettings(BFile& file, const char* name, bool forReading) diff --git a/src/servers/print/PrintServerApp.h b/src/servers/print/PrintServerApp.h index ed64ca2b74..55e8447d99 100644 --- a/src/servers/print/PrintServerApp.h +++ b/src/servers/print/PrintServerApp.h @@ -1,5 +1,5 @@ /* - * Copyright 2001-2007, Haiku. All rights reserved. + * Copyright 2001-2010, Haiku, Inc. All rights reserved. * Distributed under the terms of the MIT License. * * Authors: @@ -74,7 +74,6 @@ class PrintServerApp : public BApplication, public FolderListener { status_t RetrieveDefaultPrinter(); status_t FindPrinterNode(const char *name, BNode &node); - status_t FindPrinterDriver(const char *name, BPath &outPath); // "Classic" BeOS R5 support, see PrintServerApp.R5.cpp static status_t async_thread(void *data); diff --git a/src/servers/print/Printer.cpp b/src/servers/print/Printer.cpp index d139813a55..29ecf186b0 100644 --- a/src/servers/print/Printer.cpp +++ b/src/servers/print/Printer.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2001-2008, Haiku. All rights reserved. + * Copyright 2001-2010, Haiku, Inc. All rights reserved. * Distributed under the terms of the MIT License. * * Authors: @@ -8,8 +8,9 @@ */ #include "Printer.h" -#include "pr_server.h" #include "BeUtils.h" +#include "pr_server.h" +#include "PrinterDriverAddOn.h" #include "PrintServerApp.h" // posix @@ -44,12 +45,6 @@ void SpoolFolder::Notify(Job* job, int kind) } -// --------------------------------------------------------------- -typedef BMessage* (*config_func_t)(BNode*, const BMessage*); -typedef BMessage* (*take_job_func_t)(BFile*, BNode*, const BMessage*); -typedef char* (*add_printer_func_t)(const char* printer_name); -typedef BMessage* (*default_settings_t)(BNode*); - // --------------------------------------------------------------- BObjectList Printer::sPrinters; @@ -182,34 +177,30 @@ status_t Printer::Remove() } +status_t +Printer::FindPathToDriver(const char* driverName, BPath* path) +{ + return PrinterDriverAddOn::FindPathToDriver(driverName, path); +} + + // --------------------------------------------------------------- // ConfigurePrinter // // Handles calling the printer addon's add_printer function. // // Parameters: -// none. +// driverName - the name of the printer driver add-on +// printerName - the name of the printer spool folder // // Returns: // B_OK if successful or errorcode otherwise. // --------------------------------------------------------------- -status_t Printer::ConfigurePrinter() +status_t Printer::ConfigurePrinter(const char* driverName, + const char* printerName) { - status_t rc; - image_id id; - if ((rc = LoadPrinterAddon(id)) == B_OK) { - // Addon was loaded, so try and get the add_printer symbol - add_printer_func_t func; - if (get_image_symbol(id, "add_printer", B_SYMBOL_TYPE_TEXT, - (void**)&func) == B_OK) { - // call the function and check its result - rc = ((*func)(Name()) == NULL) ? B_ERROR : B_OK; - } - - ::unload_add_on(id); - } - - return rc; + PrinterDriverAddOn addOn(driverName); + return addOn.AddPrinter(printerName); } @@ -229,29 +220,17 @@ status_t Printer::ConfigurePrinter() status_t Printer::ConfigurePage(BMessage& settings) { - status_t rc; - image_id id; - if ((rc = LoadPrinterAddon(id)) == B_OK) { - // Addon was loaded, so try and get the config_page symbol - config_func_t func; - if ((rc=get_image_symbol(id, "config_page", B_SYMBOL_TYPE_TEXT, - (void**)&func)) == B_OK) { - // call the function and check its result - BMessage* new_settings = (*func)(SpoolDir(), &settings); - if (new_settings != NULL && new_settings->what != 'baad') { - settings = *new_settings; - settings.what = 'okok'; - AddCurrentPrinter(settings); - } else { - rc = B_ERROR; - } - delete new_settings; - } + BString driver; + status_t result = GetDriverName(&driver); + if (result != B_OK) + return result; - ::unload_add_on(id); + PrinterDriverAddOn addOn(driver.String()); + result = addOn.ConfigPage(SpoolDir(), &settings); + if (result == B_OK) { + AddCurrentPrinter(settings); } - - return rc; + return result; } @@ -271,29 +250,17 @@ Printer::ConfigurePage(BMessage& settings) status_t Printer::ConfigureJob(BMessage& settings) { - status_t rc; - image_id id; - if ((rc = LoadPrinterAddon(id)) == B_OK) { - // Addon was loaded, so try and get the config_job symbol - config_func_t func; - if ((rc = get_image_symbol(id, "config_job", B_SYMBOL_TYPE_TEXT, - (void**)&func)) == B_OK) { - // call the function and check its result - BMessage* new_settings = (*func)(SpoolDir(), &settings); - if ((new_settings != NULL) && (new_settings->what != 'baad')) { - settings = *new_settings; - settings.what = 'okok'; - AddCurrentPrinter(settings); - } else { - rc = B_ERROR; - } - delete new_settings; - } + BString driver; + status_t result = GetDriverName(&driver); + if (result != B_OK) + return result; - ::unload_add_on(id); + PrinterDriverAddOn addOn(driver.String()); + result = addOn.ConfigJob(SpoolDir(), &settings); + if (result == B_OK) { + AddCurrentPrinter(settings); } - - return rc; + return result; } @@ -327,28 +294,17 @@ Printer::HandleSpooledJob() status_t Printer::GetDefaultSettings(BMessage& settings) { - status_t rc; - image_id id; - if ((rc = LoadPrinterAddon(id)) == B_OK) { - // Addon was loaded, so try and get the default_settings symbol - default_settings_t func; - if ((rc = get_image_symbol(id, "default_settings", B_SYMBOL_TYPE_TEXT, - (void**)&func)) == B_OK) { - // call the function and check its result - BMessage* new_settings = (*func)(SpoolDir()); - if (new_settings) { - settings = *new_settings; - settings.what = 'okok'; - AddCurrentPrinter(settings); - } else { - rc = B_ERROR; - } - delete new_settings; - } + BString driver; + status_t result = GetDriverName(&driver); + if (result != B_OK) + return result; - ::unload_add_on(id); + PrinterDriverAddOn addOn(driver.String()); + result = addOn.DefaultSettings(SpoolDir(), &settings); + if (result == B_OK) { + AddCurrentPrinter(settings); } - return rc; + return result; } @@ -359,42 +315,10 @@ Printer::AbortPrintThread() } -// --------------------------------------------------------------- -// LoadPrinterAddon -// -// Try to load the printer addon into memory. -// -// Parameters: -// id - image_id set to the image id of the loaded addon. -// -// Returns: -// B_OK if successful or errorcode otherwise. -// --------------------------------------------------------------- -status_t -Printer::LoadPrinterAddon(image_id& id) +status_t +Printer::GetDriverName(BString* name) { - status_t rc; - BString drName; - if ((rc = SpoolDir()->ReadAttrString(PSRV_PRINTER_ATTR_DRV_NAME, &drName)) == B_OK) { - // try to locate the driver - BPath path; - if ((rc= ::TestForAddonExistence(drName.String(), B_USER_ADDONS_DIRECTORY, - "Print", path)) != B_OK) { - if ((rc = ::TestForAddonExistence(drName.String(), B_COMMON_ADDONS_DIRECTORY, - "Print", path)) != B_OK) { - rc = ::TestForAddonExistence(drName.String(), B_BEOS_ADDONS_DIRECTORY, - "Print", path); - } - } - - // If the driver was found - if (rc == B_OK) { - // If we cannot load the addon - if ((id=::load_add_on(path.Path())) < 0) - rc = id; - } - } - return rc; + return SpoolDir()->ReadAttrString(PSRV_PRINTER_ATTR_DRV_NAME, name); } @@ -556,29 +480,13 @@ Printer::FindSpooledJob() status_t Printer::PrintSpooledJob(BFile* spoolFile) { - status_t rc; - image_id id; - if ((rc = LoadPrinterAddon(id)) == B_OK) { - take_job_func_t func; - // Addon was loaded, so try and get the take_job symbol - if ((rc = get_image_symbol(id, "take_job", B_SYMBOL_TYPE_TEXT, - (void**)&func)) == B_OK) { - // This seems to be required for legacy? - // HP PCL3 add-on crashes without it! - BMessage params(B_REFS_RECEIVED); - params.AddInt32("file", (int32)spoolFile); - params.AddInt32("printer", (int32)SpoolDir()); - // call the function and check its result - BMessage* result = (*func)(spoolFile, SpoolDir(), ¶ms); + BString driver; + status_t result = GetDriverName(&driver); + if (result != B_OK) + return result; - if (result == NULL || result->what != 'okok') - rc = B_ERROR; - delete result; - } - - ::unload_add_on(id); - } - return rc; + PrinterDriverAddOn addOn(driver.String()); + return addOn.TakeJob(spoolFile, SpoolDir()); } diff --git a/src/servers/print/Printer.h b/src/servers/print/Printer.h index aa02d0c7db..17a176508a 100644 --- a/src/servers/print/Printer.h +++ b/src/servers/print/Printer.h @@ -1,5 +1,5 @@ /* - * Copyright 2001-2008, Haiku. All rights reserved. + * Copyright 2001-2010, Haiku, Inc. All rights reserved. * Distributed under the terms of the MIT License. * * Authors: @@ -62,7 +62,10 @@ public: static int32 CountPrinters(); status_t Remove(); - status_t ConfigurePrinter(); + static status_t FindPathToDriver(const char* driver, + BPath* path); + static status_t ConfigurePrinter(const char* driverName, + const char* printerName); status_t ConfigureJob(BMessage& ioSettings); status_t ConfigurePage(BMessage& ioSettings); status_t GetDefaultSettings(BMessage& configuration); @@ -80,10 +83,9 @@ public: Resource* GetResource() { return fResource; } private: - status_t LoadPrinterAddon(image_id& id); + status_t GetDriverName(BString* name); void AddCurrentPrinter(BMessage& message); - // Accessor BDirectory* SpoolDir() { return fPrinter.GetSpoolDir(); } void ResetJobStatus(); diff --git a/src/servers/print/PrinterDriverAddOn.cpp b/src/servers/print/PrinterDriverAddOn.cpp new file mode 100644 index 0000000000..1c8f32f66a --- /dev/null +++ b/src/servers/print/PrinterDriverAddOn.cpp @@ -0,0 +1,190 @@ +/* + * Copyright 2001-2010, Haiku, Inc. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Ithamar R. Adema + * Michael Pfeiffer + */ +#include "PrinterDriverAddOn.h" + +#include "BeUtils.h" +#include "pr_server.h" + + +typedef BMessage* (*config_func_t)(BNode*, const BMessage*); +typedef BMessage* (*take_job_func_t)(BFile*, BNode*, const BMessage*); +typedef char* (*add_printer_func_t)(const char* printer_name); +typedef BMessage* (*default_settings_t)(BNode*); + +static const char* kPrinterDriverFolderName = "Print"; + + +PrinterDriverAddOn::PrinterDriverAddOn(const char* driver) + : fAddOnID(-1) +{ + BPath path; + status_t result; + result = FindPathToDriver(driver, &path); + if (result != B_OK) + return; + + fAddOnID = ::load_add_on(path.Path()); +} + + +PrinterDriverAddOn::~PrinterDriverAddOn() +{ + if (IsLoaded()) { + unload_add_on(fAddOnID); + fAddOnID = -1; + } +} + + +status_t +PrinterDriverAddOn::AddPrinter(const char* spoolFolderName) +{ + if (!IsLoaded()) + return B_ERROR; + + add_printer_func_t func; + status_t result = get_image_symbol(fAddOnID, "add_printer", + B_SYMBOL_TYPE_TEXT, (void**)&func); + if (result != B_OK) + return result; + + if ((*func)(spoolFolderName) == NULL) + return B_ERROR; + return B_OK; +} + + +status_t +PrinterDriverAddOn::ConfigPage(BDirectory* spoolFolder, BMessage* settings) +{ + if (!IsLoaded()) + return B_ERROR; + + config_func_t func; + status_t result = get_image_symbol(fAddOnID, "config_page", + B_SYMBOL_TYPE_TEXT, (void**)&func); + if (result != B_OK) + return result; + + BMessage* newSettings = (*func)(spoolFolder, settings); + result = CopyValidSettings(settings, newSettings); + delete newSettings; + + return result; +} + + +status_t +PrinterDriverAddOn::ConfigJob(BDirectory* spoolFolder, BMessage* settings) +{ + if (!IsLoaded()) + return B_ERROR; + + config_func_t func; + status_t result = get_image_symbol(fAddOnID, "config_job", + B_SYMBOL_TYPE_TEXT, (void**)&func); + if (result != B_OK) + return result; + + BMessage* newSettings = (*func)(spoolFolder, settings); + result = CopyValidSettings(settings, newSettings); + delete newSettings; + + return result; +} + + +status_t +PrinterDriverAddOn::DefaultSettings(BDirectory* spoolFolder, BMessage* settings) +{ + if (!IsLoaded()) + return B_ERROR; + + default_settings_t func; + status_t result = get_image_symbol(fAddOnID, "default_settings", + B_SYMBOL_TYPE_TEXT, (void**)&func); + if (result != B_OK) + return result; + + BMessage* newSettings = (*func)(spoolFolder); + if (newSettings != NULL) { + *settings = *newSettings; + settings->what = 'okok'; + } else + result = B_ERROR; + delete newSettings; + + return result; +} + + +status_t +PrinterDriverAddOn::TakeJob(BFile* spoolFile, BDirectory* spoolFolder) +{ + if (!IsLoaded()) + return B_ERROR; + + take_job_func_t func; + status_t result = get_image_symbol(fAddOnID, "take_job", B_SYMBOL_TYPE_TEXT, + (void**)&func); + if (result != B_OK) + return result; + + // This seems to be required for legacy? + // HP PCL3 add-on crashes without it! + BMessage parameters(B_REFS_RECEIVED); + parameters.AddInt32("file", (int32)spoolFile); + parameters.AddInt32("printer", (int32)spoolFolder); + + BMessage* message = (*func)(spoolFile, spoolFolder, ¶meters); + if (message == NULL || message->what != 'okok') + result = B_ERROR; + delete message; + + return result; +} + + +status_t +PrinterDriverAddOn::FindPathToDriver(const char* driver, BPath* path) +{ + status_t result; + result = ::TestForAddonExistence(driver, B_USER_ADDONS_DIRECTORY, + kPrinterDriverFolderName, *path); + if (result == B_OK) + return B_OK; + + result = ::TestForAddonExistence(driver, B_COMMON_ADDONS_DIRECTORY, + kPrinterDriverFolderName, *path); + if (result == B_OK) + return B_OK; + + result = ::TestForAddonExistence(driver, B_BEOS_ADDONS_DIRECTORY, + kPrinterDriverFolderName, *path); + return result; +} + + +bool +PrinterDriverAddOn::IsLoaded() const +{ + return fAddOnID > 0; +} + + +status_t +PrinterDriverAddOn::CopyValidSettings(BMessage* settings, BMessage* newSettings) +{ + if (newSettings != NULL && newSettings->what != 'baad') { + *settings = *newSettings; + settings->what = 'okok'; + return B_OK; + } + return B_ERROR; +} diff --git a/src/servers/print/PrinterDriverAddOn.h b/src/servers/print/PrinterDriverAddOn.h new file mode 100644 index 0000000000..68fe223eb5 --- /dev/null +++ b/src/servers/print/PrinterDriverAddOn.h @@ -0,0 +1,48 @@ +/* + * Copyright 2001-2010, Haiku, Inc. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Ithamar R. Adema + * Michael Pfeiffer + */ +#ifndef PRINTER_DRIVER_ADD_ON_H +#define PRINTER_DRIVER_ADD_ON_H + + +#include +#include +#include +#include +#include +#include + + +class PrinterDriverAddOn +{ +public: + PrinterDriverAddOn(const char* driver); + ~PrinterDriverAddOn(); + + status_t AddPrinter(const char* spoolFolderName); + status_t ConfigPage(BDirectory* spoolFolder, + BMessage* settings); + status_t ConfigJob(BDirectory* spoolFolder, + BMessage* settings); + status_t DefaultSettings(BDirectory* spoolFolder, + BMessage* settings); + status_t TakeJob(BFile* spoolFile, + BDirectory* spoolFolder); + + static status_t FindPathToDriver(const char* driver, BPath* path); + +private: + bool IsLoaded() const; + status_t CopyValidSettings(BMessage* settings, + BMessage* newSettings); + + image_id fAddOnID; +}; + + +#endif