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:
@@ -35,8 +35,18 @@ THE SOFTWARE.
|
|||||||
#include <Directory.h>
|
#include <Directory.h>
|
||||||
#include <Message.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
|
// to be implemented by the transport add-on
|
||||||
extern "C" BDataIO* instantiate_transport(BDirectory* printer, BMessage* msg);
|
extern "C" BDataIO* instantiate_transport(BDirectory* printer, BMessage* msg);
|
||||||
|
extern "C" status_t install_transport_probe(void);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ SubInclude HAIKU_TOP src servers print shared ;
|
|||||||
SubDir HAIKU_TOP src servers print ;
|
SubDir HAIKU_TOP src servers print ;
|
||||||
|
|
||||||
UsePrivateHeaders shared interface print ;
|
UsePrivateHeaders shared interface print ;
|
||||||
|
UsePrivateHeaders print ;
|
||||||
|
|
||||||
AddResources
|
AddResources
|
||||||
print_server
|
print_server
|
||||||
@@ -22,6 +23,8 @@ Server
|
|||||||
PrintServerApp.Scripting.cpp
|
PrintServerApp.Scripting.cpp
|
||||||
Printer.Scripting.cpp
|
Printer.Scripting.cpp
|
||||||
Printer.cpp
|
Printer.cpp
|
||||||
|
Transport.Scripting.cpp
|
||||||
|
Transport.cpp
|
||||||
ResourceManager.cpp
|
ResourceManager.cpp
|
||||||
Settings.cpp
|
Settings.cpp
|
||||||
ConfigWindow.cpp
|
ConfigWindow.cpp
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
*/
|
*/
|
||||||
#include "PrintServerApp.h"
|
#include "PrintServerApp.h"
|
||||||
|
|
||||||
|
#include "Transport.h"
|
||||||
#include "Printer.h"
|
#include "Printer.h"
|
||||||
|
|
||||||
// BeOS API
|
// BeOS API
|
||||||
@@ -26,6 +27,10 @@ static property_info prop_list[] = {
|
|||||||
"Delete a specific printer" },
|
"Delete a specific printer" },
|
||||||
{ "Printers", { B_COUNT_PROPERTIES }, { B_DIRECT_SPECIFIER },
|
{ "Printers", { B_COUNT_PROPERTIES }, { B_DIRECT_SPECIFIER },
|
||||||
"Return the number of available printers" },
|
"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 },
|
{ "UseConfigWindow", { B_GET_PROPERTY, B_SET_PROPERTY }, { B_DIRECT_SPECIFIER },
|
||||||
"Show configuration window" },
|
"Show configuration window" },
|
||||||
{ 0 } // terminate list
|
{ 0 } // terminate list
|
||||||
@@ -110,6 +115,11 @@ PrintServerApp::HandleScriptingCommand(BMessage* msg)
|
|||||||
reply.AddInt32("result", Printer::CountPrinters());
|
reply.AddInt32("result", Printer::CountPrinters());
|
||||||
reply.AddInt32("error", B_OK);
|
reply.AddInt32("error", B_OK);
|
||||||
msg->SendReply(&reply);
|
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;
|
break;
|
||||||
}
|
}
|
||||||
@@ -147,6 +157,37 @@ Printer* PrintServerApp::GetPrinterFromSpecifier(BMessage* msg)
|
|||||||
return NULL;
|
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*
|
BHandler*
|
||||||
PrintServerApp::ResolveSpecifier(BMessage* msg, int32 index, BMessage* spec,
|
PrintServerApp::ResolveSpecifier(BMessage* msg, int32 index, BMessage* spec,
|
||||||
int32 form, const char* prop)
|
int32 form, const char* prop)
|
||||||
@@ -170,6 +211,17 @@ PrintServerApp::ResolveSpecifier(BMessage* msg, int32 index, BMessage* spec,
|
|||||||
msg->PopSpecifier();
|
msg->PopSpecifier();
|
||||||
break;
|
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:
|
default:
|
||||||
rc = this;
|
rc = this;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
#include "BeUtils.h"
|
#include "BeUtils.h"
|
||||||
#include "Printer.h"
|
#include "Printer.h"
|
||||||
#include "pr_server.h"
|
#include "pr_server.h"
|
||||||
|
#include "Transport.h"
|
||||||
|
|
||||||
// BeOS API
|
// BeOS API
|
||||||
#include <Alert.h>
|
#include <Alert.h>
|
||||||
@@ -90,6 +91,11 @@ PrintServerApp::PrintServerApp(status_t* err)
|
|||||||
|
|
||||||
fHasReferences = create_sem(1, "has_references");
|
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();
|
SetupPrinterList();
|
||||||
RetrieveDefaultPrinter();
|
RetrieveDefaultPrinter();
|
||||||
|
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
#include "Settings.h"
|
#include "Settings.h"
|
||||||
|
|
||||||
class Printer;
|
class Printer;
|
||||||
|
class Transport;
|
||||||
|
|
||||||
// The global BLocker for synchronisation.
|
// The global BLocker for synchronisation.
|
||||||
extern BLocker *gLock;
|
extern BLocker *gLock;
|
||||||
@@ -43,6 +44,7 @@ class PrintServerApp : public BApplication, public FolderListener {
|
|||||||
status_t GetSupportedSuites(BMessage *msg);
|
status_t GetSupportedSuites(BMessage *msg);
|
||||||
void HandleScriptingCommand(BMessage *msg);
|
void HandleScriptingCommand(BMessage *msg);
|
||||||
Printer *GetPrinterFromSpecifier(BMessage *msg);
|
Printer *GetPrinterFromSpecifier(BMessage *msg);
|
||||||
|
Transport *GetTransportFromSpecifier(BMessage *msg);
|
||||||
BHandler *ResolveSpecifier(BMessage *msg, int32 index, BMessage *spec,
|
BHandler *ResolveSpecifier(BMessage *msg, int32 index, BMessage *spec,
|
||||||
int32 form, const char *prop);
|
int32 form, const char *prop);
|
||||||
private:
|
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
|
||||||
Reference in New Issue
Block a user