haiku/src/servers/print/Transport.cpp

210 lines
4.2 KiB
C++

/*
* 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 index = 0; index < sTransports.CountItems(); index++) {
if (name == sTransports.ItemAt(index)->Name())
return sTransports.ItemAt(index);
}
// None found, so return NULL
return NULL;
}
Transport*
Transport::At(int32 index)
{
return sTransports.ItemAt(index);
}
void
Transport::Remove(Transport* transport)
{
sTransports.RemoveItem(transport);
}
int32
Transport::CountTransports()
{
return sTransports.CountItems();
}
status_t
Transport::Scan(directory_which which)
{
status_t result;
BPath path;
// Try to find specified transport addon directory
if ((result = find_directory(which, &path)) != B_OK)
return result;
if ((result = path.Append("Print/transport")) != B_OK)
return result;
BDirectory dir;
if ((result = dir.SetTo(path.Path())) != B_OK)
return result;
// 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),
fPath(path),
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* transportFeaturesPointer;
if (get_image_symbol(id, B_TRANSPORT_FEATURES_SYMBOL,
B_SYMBOL_TYPE_DATA, (void**)&transportFeaturesPointer) != B_OK) {
unload_add_on(id);
} else {
fFeatures = *transportFeaturesPointer;
if (fFeatures & B_TRANSPORT_IS_HOTPLUG) {
// We are hotpluggable; so keep us loaded!
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);
}
status_t
Transport::ListAvailablePorts(BMessage* msg)
{
status_t (*list_ports)(BMessage*);
image_id id = fImageID;
status_t rc = B_OK;
// Load image if not loaded yet
if (id == -1 && (id = load_add_on(fPath.Path())) < 0)
return id;
// Get pointer to addon function
if ((rc = get_image_symbol(id, B_TRANSPORT_LIST_PORTS_SYMBOL,
B_SYMBOL_TYPE_TEXT, (void**)&list_ports)) != B_OK)
goto done;
// run addon...
rc = (*list_ports)(msg);
done:
// clean up if needed
if (fImageID != id)
unload_add_on(id);
return rc;
}
// ---------------------------------------------------------------
// 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);
}
}