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:
parent
cfc9593fa8
commit
62cb58a8ef
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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
|
Loading…
Reference in New Issue