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