1/*
2 * Copyright 2008, Haiku. All rights reserved.
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 *		Ithamar R. Adema
7 */
8
9#include "Transport.h"
10
11// BeOS API
12#include <PrintTransportAddOn.h>
13#include <Application.h>
14#include <image.h>
15#include <Entry.h>
16
17
18BObjectList<Transport> Transport::sTransports;
19
20
21// ---------------------------------------------------------------
22// Find [static]
23//
24// Searches the static object list for a transport object with the
25// specified name.
26//
27// Parameters:
28//    name - Printer definition name we're looking for.
29//
30// Returns:
31//    Pointer to Transport object, or NULL if not found.
32// ---------------------------------------------------------------
33Transport*
34Transport::Find(const BString& name)
35{
36		// Look in list to find printer definition
37	for (int32 index = 0; index < sTransports.CountItems(); index++) {
38		if (name == sTransports.ItemAt(index)->Name())
39			return sTransports.ItemAt(index);
40	}
41
42		// None found, so return NULL
43	return NULL;
44}
45
46
47Transport*
48Transport::At(int32 index)
49{
50	return sTransports.ItemAt(index);
51}
52
53
54void
55Transport::Remove(Transport* transport)
56{
57	sTransports.RemoveItem(transport);
58}
59
60
61int32
62Transport::CountTransports()
63{
64	return sTransports.CountItems();
65}
66
67
68status_t
69Transport::Scan(directory_which which)
70{
71	status_t result;
72	BPath path;
73
74	// Try to find specified transport addon directory
75	if ((result = find_directory(which, &path)) != B_OK)
76		return result;
77
78	if ((result = path.Append("Print/transport")) != B_OK)
79		return result;
80
81	BDirectory dir;
82	if ((result = dir.SetTo(path.Path())) != B_OK)
83		return result;
84
85	// Walk over all entries in directory
86	BEntry entry;
87	while(dir.GetNextEntry(&entry) == B_OK) {
88		if (!entry.IsFile())
89			continue;
90
91		if (entry.GetPath(&path) != B_OK)
92			continue;
93
94		// If we have loaded the transport from a previous scanned directory,
95		// ignore this one.
96		if (Transport::Find(path.Leaf()) != NULL)
97			continue;
98
99		be_app->AddHandler(new Transport(path));
100	}
101
102	return B_OK;
103}
104
105
106// ---------------------------------------------------------------
107// Transport [constructor]
108//
109// Initializes the transport object with data read from the
110// attributes attached to the printer definition node.
111//
112// Parameters:
113//    node - Printer definition node for this printer.
114//
115// Returns:
116//    none.
117// ---------------------------------------------------------------
118Transport::Transport(const BPath& path)
119	: BHandler(B_EMPTY_STRING),
120	fPath(path),
121	fImageID(-1),
122	fFeatures(0)
123{
124	// Load transport addon
125	image_id id = ::load_add_on(path.Path());
126	if (id < B_OK)
127		return;
128
129	// Find transport_features symbol, to determine if we need to keep
130	// this transport loaded
131	int* transportFeaturesPointer;
132	if (get_image_symbol(id, B_TRANSPORT_FEATURES_SYMBOL,
133			B_SYMBOL_TYPE_DATA, (void**)&transportFeaturesPointer) != B_OK) {
134		unload_add_on(id);
135	} else {
136		fFeatures = *transportFeaturesPointer;
137
138		if (fFeatures & B_TRANSPORT_IS_HOTPLUG) {
139			// We are hotpluggable; so keep us loaded!
140			fImageID = id;
141		} else {
142			// No extended Transport support; so no need to keep loaded
143			::unload_add_on(id);
144		}
145	}
146
147	sTransports.AddItem(this);
148}
149
150
151Transport::~Transport()
152{
153	sTransports.RemoveItem(this);
154}
155
156
157status_t
158Transport::ListAvailablePorts(BMessage* msg)
159{
160	status_t (*list_ports)(BMessage*);
161	image_id id = fImageID;
162	status_t rc = B_OK;
163
164	// Load image if not loaded yet
165	if (id == -1 && (id = load_add_on(fPath.Path())) < 0)
166		return id;
167
168	// Get pointer to addon function
169	if ((rc = get_image_symbol(id, B_TRANSPORT_LIST_PORTS_SYMBOL,
170			B_SYMBOL_TYPE_TEXT, (void**)&list_ports)) != B_OK)
171		goto done;
172
173	// run addon...
174	rc = (*list_ports)(msg);
175
176done:
177	// clean up if needed
178	if (fImageID != id)
179		unload_add_on(id);
180
181	return rc;
182}
183
184
185// ---------------------------------------------------------------
186// MessageReceived
187//
188// Handle scripting messages.
189//
190// Parameters:
191//    msg - message.
192// ---------------------------------------------------------------
193void
194Transport::MessageReceived(BMessage* msg)
195{
196	switch(msg->what) {
197		case B_GET_PROPERTY:
198		case B_SET_PROPERTY:
199		case B_CREATE_PROPERTY:
200		case B_DELETE_PROPERTY:
201		case B_COUNT_PROPERTIES:
202		case B_EXECUTE_PROPERTY:
203			HandleScriptingCommand(msg);
204			break;
205
206		default:
207			Inherited::MessageReceived(msg);
208	}
209}
210