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
This commit is contained in:
Ithamar R. Adema 2008-02-08 00:34:53 +00:00
parent cfc9593fa8
commit 62cb58a8ef
8 changed files with 384 additions and 1 deletions

View File

@ -35,8 +35,18 @@ THE SOFTWARE.
#include <Directory.h>
#include <Message.h>
// 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

View File

@ -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

View File

@ -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;
}

View File

@ -11,6 +11,7 @@
#include "BeUtils.h"
#include "Printer.h"
#include "pr_server.h"
#include "Transport.h"
// BeOS API
#include <Alert.h>
@ -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();

View File

@ -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:

View File

@ -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 <PropertyInfo.h>
#include <Messenger.h>
#include <Message.h>
#include <AppDefs.h>
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);
}

View File

@ -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 <PrintTransportAddOn.h>
#include <Application.h>
#include <image.h>
#include <Entry.h>
// ---------------------------------------------------------------
BObjectList<Transport> 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);
}
}

View File

@ -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 <FindDirectory.h>
#include <Handler.h>
#include <String.h>
#include <Path.h>
#include <ObjectList.h>
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<Transport> sTransports;
};
#endif