From 62cb58a8ef1cf63329b2ab6277655c9a866697cd Mon Sep 17 00:00:00 2001 From: "Ithamar R. Adema" Date: Fri, 8 Feb 2008 00:34:53 +0000 Subject: [PATCH] Make print_server track Transport addons too. This is because some of the NewTransportAddOns(tm) can also autodetect devices, e.g. USB printers. For this, the print_server needs to keep those transport addons loaded at all times. This code now also enables dynamic Transport discovery for the Printer prefs, e.g. 'hey print_server GET Transport 0' or 'hey print_server GET Transport 'USB Port'' will now work too ;) git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@23927 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- headers/private/print/PrintTransportAddOn.h | 10 + src/servers/print/Jamfile | 3 + .../print/PrintServerApp.Scripting.cpp | 54 +++++- src/servers/print/PrintServerApp.cpp | 6 + src/servers/print/PrintServerApp.h | 2 + src/servers/print/Transport.Scripting.cpp | 84 +++++++++ src/servers/print/Transport.cpp | 174 ++++++++++++++++++ src/servers/print/Transport.h | 52 ++++++ 8 files changed, 384 insertions(+), 1 deletion(-) create mode 100644 src/servers/print/Transport.Scripting.cpp create mode 100644 src/servers/print/Transport.cpp create mode 100644 src/servers/print/Transport.h diff --git a/headers/private/print/PrintTransportAddOn.h b/headers/private/print/PrintTransportAddOn.h index 57c66185d2..d3ef474fcb 100644 --- a/headers/private/print/PrintTransportAddOn.h +++ b/headers/private/print/PrintTransportAddOn.h @@ -35,8 +35,18 @@ THE SOFTWARE. #include #include +// int transport_features; symbol name +#define B_TRANSPORT_FEATURES_SYMBOL "transport_features" + +// Bit values for 'transport_features' +enum { + B_TRANSPORT_SUPPORTS_PROBE = 1, + B_TRANSPORT_SUPPORTS_SHARING = 2, +}; + // to be implemented by the transport add-on extern "C" BDataIO* instantiate_transport(BDirectory* printer, BMessage* msg); +extern "C" status_t install_transport_probe(void); #endif diff --git a/src/servers/print/Jamfile b/src/servers/print/Jamfile index f460a0bf44..f87cff36b3 100644 --- a/src/servers/print/Jamfile +++ b/src/servers/print/Jamfile @@ -7,6 +7,7 @@ SubInclude HAIKU_TOP src servers print shared ; SubDir HAIKU_TOP src servers print ; UsePrivateHeaders shared interface print ; +UsePrivateHeaders print ; AddResources print_server @@ -22,6 +23,8 @@ Server PrintServerApp.Scripting.cpp Printer.Scripting.cpp Printer.cpp + Transport.Scripting.cpp + Transport.cpp ResourceManager.cpp Settings.cpp ConfigWindow.cpp diff --git a/src/servers/print/PrintServerApp.Scripting.cpp b/src/servers/print/PrintServerApp.Scripting.cpp index 6f57efde18..0e8b0a2857 100644 --- a/src/servers/print/PrintServerApp.Scripting.cpp +++ b/src/servers/print/PrintServerApp.Scripting.cpp @@ -7,6 +7,7 @@ */ #include "PrintServerApp.h" +#include "Transport.h" #include "Printer.h" // BeOS API @@ -26,6 +27,10 @@ static property_info prop_list[] = { "Delete a specific printer" }, { "Printers", { B_COUNT_PROPERTIES }, { B_DIRECT_SPECIFIER }, "Return the number of available printers" }, + { "Transport", { B_GET_PROPERTY }, { B_INDEX_SPECIFIER, B_NAME_SPECIFIER, B_REVERSE_INDEX_SPECIFIER }, + "Retrieve a specific transport" }, + { "Transports", { B_COUNT_PROPERTIES }, { B_DIRECT_SPECIFIER }, + "Return the number of available transports" }, { "UseConfigWindow", { B_GET_PROPERTY, B_SET_PROPERTY }, { B_DIRECT_SPECIFIER }, "Show configuration window" }, { 0 } // terminate list @@ -110,6 +115,11 @@ PrintServerApp::HandleScriptingCommand(BMessage* msg) reply.AddInt32("result", Printer::CountPrinters()); reply.AddInt32("error", B_OK); msg->SendReply(&reply); + } else if (propName == "Transports") { + BMessage reply(B_REPLY); + reply.AddInt32("result", Transport::CountTransports()); + reply.AddInt32("error", B_OK); + msg->SendReply(&reply); } break; } @@ -147,13 +157,44 @@ Printer* PrintServerApp::GetPrinterFromSpecifier(BMessage* msg) return NULL; } +Transport* PrintServerApp::GetTransportFromSpecifier(BMessage* msg) +{ + switch(msg->what) { + case B_NAME_SPECIFIER: { + BString name; + if (msg->FindString("name", &name) == B_OK) { + return Transport::Find(name); + } + break; + } + + case B_INDEX_SPECIFIER: { + int32 idx; + if (msg->FindInt32("index", &idx) == B_OK) { + return Transport::At(idx); + } + break; + } + + case B_REVERSE_INDEX_SPECIFIER: { + int32 idx; + if (msg->FindInt32("index", &idx) == B_OK) { + return Transport::At(Transport::CountTransports() - idx); + } + break; + } + } + + return NULL; +} + BHandler* PrintServerApp::ResolveSpecifier(BMessage* msg, int32 index, BMessage* spec, int32 form, const char* prop) { BPropertyInfo prop_info(prop_list); BHandler* rc = NULL; - + int32 idx; switch( idx=prop_info.FindMatch(msg,0,spec,form,prop) ) { case B_ERROR: @@ -170,6 +211,17 @@ PrintServerApp::ResolveSpecifier(BMessage* msg, int32 index, BMessage* spec, msg->PopSpecifier(); break; + // GET Transport [arg] + case 5: + if ((rc=GetTransportFromSpecifier(spec)) == NULL) { + BMessage reply(B_REPLY); + reply.AddInt32("error", B_BAD_INDEX); + msg->SendReply(&reply); + } + else + msg->PopSpecifier(); + break; + default: rc = this; } diff --git a/src/servers/print/PrintServerApp.cpp b/src/servers/print/PrintServerApp.cpp index 8c32dce397..26c39686c1 100644 --- a/src/servers/print/PrintServerApp.cpp +++ b/src/servers/print/PrintServerApp.cpp @@ -11,6 +11,7 @@ #include "BeUtils.h" #include "Printer.h" #include "pr_server.h" +#include "Transport.h" // BeOS API #include @@ -90,6 +91,11 @@ PrintServerApp::PrintServerApp(status_t* err) fHasReferences = create_sem(1, "has_references"); + // Build list of transport addons + Transport::Scan(B_USER_ADDONS_DIRECTORY); + Transport::Scan(B_COMMON_ADDONS_DIRECTORY); + Transport::Scan(B_BEOS_ADDONS_DIRECTORY); + SetupPrinterList(); RetrieveDefaultPrinter(); diff --git a/src/servers/print/PrintServerApp.h b/src/servers/print/PrintServerApp.h index cc177d5231..39c54f73aa 100644 --- a/src/servers/print/PrintServerApp.h +++ b/src/servers/print/PrintServerApp.h @@ -19,6 +19,7 @@ #include "Settings.h" class Printer; +class Transport; // The global BLocker for synchronisation. extern BLocker *gLock; @@ -43,6 +44,7 @@ class PrintServerApp : public BApplication, public FolderListener { status_t GetSupportedSuites(BMessage *msg); void HandleScriptingCommand(BMessage *msg); Printer *GetPrinterFromSpecifier(BMessage *msg); + Transport *GetTransportFromSpecifier(BMessage *msg); BHandler *ResolveSpecifier(BMessage *msg, int32 index, BMessage *spec, int32 form, const char *prop); private: diff --git a/src/servers/print/Transport.Scripting.cpp b/src/servers/print/Transport.Scripting.cpp new file mode 100644 index 0000000000..277c246374 --- /dev/null +++ b/src/servers/print/Transport.Scripting.cpp @@ -0,0 +1,84 @@ +/* + * Copyright 2008, Haiku. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Ithamar R. Adema + */ + +#include "Transport.h" + +// BeOS API +#include +#include +#include +#include + +static property_info prop_list[] = { + { "Name", { B_GET_PROPERTY }, { B_DIRECT_SPECIFIER }, + "Get name of transport" }, + { 0 } // terminate list +}; + +void Transport::HandleScriptingCommand(BMessage* msg) +{ + status_t rc = B_ERROR; + BString propName; + BString result; + BMessage spec; + int32 idx; + + if ((rc=msg->GetCurrentSpecifier(&idx,&spec)) == B_OK && + (rc=spec.FindString("property",&propName)) == B_OK) { + switch(msg->what) { + case B_GET_PROPERTY: + if (propName == "Name") + result = fName; + else { // If unknown scripting request, let superclas handle it + Inherited::MessageReceived(msg); + break; + } + + BMessage reply(B_REPLY); + reply.AddString("result", result); + reply.AddInt32("error", rc); + msg->SendReply(&reply); + break; + } + } + else { + // If GetSpecifier failed + if (idx == -1) { + BMessage reply(B_REPLY); + reply.AddMessenger("result", BMessenger(this)); + reply.AddInt32("error", B_OK); + msg->SendReply(&reply); + } + } +} + +BHandler* Transport::ResolveSpecifier(BMessage* msg, int32 index, BMessage* spec, + int32 form, const char* prop) +{ + BPropertyInfo prop_info(prop_list); + BHandler* rc = this; + + int32 idx; + switch( idx=prop_info.FindMatch(msg,0,spec,form,prop) ) { + case B_ERROR: + rc = Inherited::ResolveSpecifier(msg,index,spec,form,prop); + break; + } + + return rc; +} + +status_t Transport::GetSupportedSuites(BMessage* msg) +{ + msg->AddString("suites", "application/x-vnd.OpenBeOS-transport"); + + BPropertyInfo prop_info(prop_list); + msg->AddFlat("messages", &prop_info); + + return Inherited::GetSupportedSuites(msg); +} diff --git a/src/servers/print/Transport.cpp b/src/servers/print/Transport.cpp new file mode 100644 index 0000000000..eb53fb2729 --- /dev/null +++ b/src/servers/print/Transport.cpp @@ -0,0 +1,174 @@ +/* + * Copyright 2008, Haiku. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Ithamar R. Adema + */ + +#include "Transport.h" + +// BeOS API +#include +#include +#include +#include + +// --------------------------------------------------------------- +BObjectList Transport::sTransports; + +// --------------------------------------------------------------- +// Find [static] +// +// Searches the static object list for a transport object with the +// specified name. +// +// Parameters: +// name - Printer definition name we're looking for. +// +// Returns: +// Pointer to Transport object, or NULL if not found. +// --------------------------------------------------------------- +Transport* Transport::Find(const BString& name) +{ + // Look in list to find printer definition + for (int32 idx=0; idx < sTransports.CountItems(); idx++) { + if (name == sTransports.ItemAt(idx)->Name()) { + return sTransports.ItemAt(idx); + } + } + + // None found, so return NULL + return NULL; +} + +// --------------------------------------------------------------- +Transport* Transport::At(int32 idx) +{ + return sTransports.ItemAt(idx); +} + +// --------------------------------------------------------------- +void Transport::Remove(Transport* transport) +{ + sTransports.RemoveItem(transport); +} + +// --------------------------------------------------------------- +int32 Transport::CountTransports() +{ + return sTransports.CountItems(); +} + +// --------------------------------------------------------------- +status_t Transport::Scan(directory_which which) +{ + BDirectory dir; + status_t rc; + BPath path; + + // Try to find specified transport addon directory + if ((rc=find_directory(which,&path)) != B_OK) + return rc; + + if ((rc=path.Append("Print/transport")) != B_OK) + return rc; + + if ((rc=dir.SetTo(path.Path())) != B_OK) + return rc; + + // Walk over all entries in directory + BEntry entry; + while(dir.GetNextEntry(&entry) == B_OK) { + if (!entry.IsFile()) + continue; + + if (entry.GetPath(&path) != B_OK) + continue; + + // If we have loaded the transport from a previous scanned directory, + // ignore this one. + if (Transport::Find(path.Leaf()) != NULL) + continue; + + be_app->AddHandler(new Transport(path)); + } + + return B_OK; + +} + +// --------------------------------------------------------------- +// Transport [constructor] +// +// Initializes the transport object with data read from the +// attributes attached to the printer definition node. +// +// Parameters: +// node - Printer definition node for this printer. +// +// Returns: +// none. +// --------------------------------------------------------------- +Transport::Transport(const BPath& path) + : BHandler(B_EMPTY_STRING), + fName(path.Leaf()), + fImageID(-1), + fFeatures(0) +{ + // Load transport addon + image_id id = ::load_add_on(path.Path()); + if (id < B_OK) + return; + + // Find transport_features symbol, to determine if we need to keep + // this transport loaded + int* transport_features_ptr; + if (get_image_symbol(id, B_TRANSPORT_FEATURES_SYMBOL, + B_SYMBOL_TYPE_DATA, (void**)&transport_features_ptr) != B_OK) { + unload_add_on(id); + } else { + fFeatures = *transport_features_ptr; + + if (*transport_features_ptr & B_TRANSPORT_SUPPORTS_PROBE) { + // Transport supports probing, so it needs to stay loaded... + printf("IRA: Transport %s supports probing!\n", path.Path()); + fImageID = id; + } + else // No extended Transport support; so no need to keep loaded + ::unload_add_on(id); + } + + sTransports.AddItem(this); +} + +// --------------------------------------------------------------- +Transport::~Transport() +{ + sTransports.RemoveItem(this); +} + +// --------------------------------------------------------------- +// MessageReceived +// +// Handle scripting messages. +// +// Parameters: +// msg - message. +// --------------------------------------------------------------- +void Transport::MessageReceived(BMessage* msg) +{ + switch(msg->what) { + case B_GET_PROPERTY: + case B_SET_PROPERTY: + case B_CREATE_PROPERTY: + case B_DELETE_PROPERTY: + case B_COUNT_PROPERTIES: + case B_EXECUTE_PROPERTY: + HandleScriptingCommand(msg); + break; + + default: + Inherited::MessageReceived(msg); + } +} diff --git a/src/servers/print/Transport.h b/src/servers/print/Transport.h new file mode 100644 index 0000000000..2bbbfe3442 --- /dev/null +++ b/src/servers/print/Transport.h @@ -0,0 +1,52 @@ +/* + * Copyright 2008, Haiku. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Ithamar R. Adema + */ +#ifndef TRANSPORT_H +#define TRANSPORT_H + +class Transport; + +#include +#include +#include +#include + +#include + +class Transport : public BHandler +{ + typedef BHandler Inherited; +public: + Transport(const BPath& path); + ~Transport(); + + const BString& Name() const { return fName; } + + static status_t Scan(directory_which which); + + static Transport* Find(const BString& name); + static void Remove(Transport* transport); + static Transport* At(int32 idx); + static int32 CountTransports(); + + void MessageReceived(BMessage* msg); + + // Scripting support, see Printer.Scripting.cpp + status_t GetSupportedSuites(BMessage* msg); + void HandleScriptingCommand(BMessage* msg); + BHandler* ResolveSpecifier(BMessage* msg, int32 index, BMessage* spec, + int32 form, const char* prop); + +private: + BString fName; + long fImageID; + int fFeatures; + + static BObjectList sTransports; +}; + +#endif