xref: /haiku/src/kits/media/PluginManager.cpp (revision db10640de90f7f9519ba2da9577b7c1af3c64f6b)
1 /*
2 ** Copyright 2004, Marcus Overhagen. All rights reserved.
3 ** Distributed under the terms of the OpenBeOS License.
4 */
5 
6 
7 #include <Path.h>
8 #include <image.h>
9 #include <string.h>
10 
11 #include "PluginManager.h"
12 #include "DataExchange.h"
13 #include "debug.h"
14 
15 PluginManager _plugin_manager;
16 
17 
18 status_t
19 _CreateReader(Reader **reader, int32 *streamCount, media_file_format *mff, BDataIO *source)
20 {
21 	TRACE("_CreateReader enter\n");
22 
23 	BPositionIO *seekable_source = dynamic_cast<BPositionIO *>(source);
24 	if (seekable_source == 0) {
25 		printf("_CreateReader: non-seekable sources not supported yet\n");
26 		return B_ERROR;
27 	}
28 
29 	// get list of available readers from, the server
30 	server_get_readers_request request;
31 	server_get_readers_reply reply;
32 	if (B_OK != QueryServer(SERVER_GET_READERS, &request, sizeof(request), &reply, sizeof(reply))) {
33 		printf("_CreateReader: can't get list of readers\n");
34 		return B_ERROR;
35 	}
36 
37 	// try each reader by calling it's Sniff function...
38 	for (int32 i = 0; i < reply.count; i++) {
39 		entry_ref ref = reply.ref[i];
40 		MediaPlugin *plugin = _plugin_manager.GetPlugin(ref);
41 		if (!plugin) {
42 			printf("_CreateReader: GetPlugin failed\n");
43 			return B_ERROR;
44 		}
45 
46 		ReaderPlugin *readerPlugin = dynamic_cast<ReaderPlugin *>(plugin);
47 		if (!readerPlugin) {
48 			printf("_CreateReader: dynamic_cast failed\n");
49 			return B_ERROR;
50 		}
51 
52 		*reader = readerPlugin->NewReader();
53 		if (! *reader) {
54 			printf("_CreateReader: NewReader failed\n");
55 			return B_ERROR;
56 		}
57 
58 		seekable_source->Seek(0, SEEK_SET);
59 		(*reader)->Setup(seekable_source);
60 
61 		if (B_OK == (*reader)->Sniff(streamCount)) {
62 			TRACE("_CreateReader: Sniff success (%ld stream(s))\n", *streamCount);
63 			(*reader)->GetFileFormatInfo(mff);
64 			return B_OK;
65 		}
66 
67 		// _DestroyReader(*reader);
68 		delete *reader;
69 		_plugin_manager.PutPlugin(plugin);
70 	}
71 
72 	TRACE("_CreateReader leave\n");
73 	return B_MEDIA_NO_HANDLER;
74 }
75 
76 
77 status_t
78 _CreateDecoder(Decoder **_decoder, const media_format &format)
79 {
80 	TRACE("_CreateDecoder enter\n");
81 
82 	// get decoder for this format from the server
83 	server_get_decoder_for_format_request request;
84 	server_get_decoder_for_format_reply reply;
85 	request.format = format;
86 	if (B_OK != QueryServer(SERVER_GET_DECODER_FOR_FORMAT, &request, sizeof(request), &reply, sizeof(reply))) {
87 		printf("_CreateReader: can't get decoder for format\n");
88 		return B_ERROR;
89 	}
90 
91 	MediaPlugin *plugin = _plugin_manager.GetPlugin(reply.ref);
92 	if (!plugin) {
93 		printf("_CreateDecoder: GetPlugin failed\n");
94 		return B_ERROR;
95 	}
96 
97 	DecoderPlugin *decoderPlugin = dynamic_cast<DecoderPlugin *>(plugin);
98 	if (!decoderPlugin) {
99 		printf("_CreateDecoder: dynamic_cast failed\n");
100 		return B_ERROR;
101 	}
102 
103 	*_decoder = decoderPlugin->NewDecoder(0);
104 	if (*_decoder == NULL) {
105 		printf("_CreateDecoder: NewDecoder() failed\n");
106 		return B_ERROR;
107 	}
108 
109 	TRACE("_CreateDecoder leave\n");
110 
111 	return B_OK;
112 }
113 
114 
115 void
116 _DestroyReader(Reader *reader)
117 {
118 	// ToDo: must call put plugin
119 	delete reader;
120 }
121 
122 
123 void
124 _DestroyDecoder(Decoder *decoder)
125 {
126 	// ToDo: must call put plugin
127 	delete decoder;
128 }
129 
130 
131 //	#pragma mark -
132 
133 
134 PluginManager::PluginManager()
135 {
136 	CALLED();
137 	fLocker = new BLocker;
138 	fPluginList = new List<plugin_info>;
139 }
140 
141 
142 PluginManager::~PluginManager()
143 {
144 	CALLED();
145 	while (!fPluginList->IsEmpty()) {
146 		plugin_info *info;
147 		fPluginList->Get(fPluginList->CountItems() - 1, &info);
148 		printf("PluginManager: Error, unloading PlugIn %s with usecount %d\n", info->name, info->usecount);
149 		delete info->plugin;
150 		unload_add_on(info->image);
151 		fPluginList->Remove(fPluginList->CountItems() - 1);
152 	}
153 	delete fLocker;
154 }
155 
156 
157 MediaPlugin *
158 PluginManager::GetPlugin(const entry_ref &ref)
159 {
160 	fLocker->Lock();
161 
162 	MediaPlugin *plugin;
163 	plugin_info *pinfo;
164 	plugin_info info;
165 
166 	for (fPluginList->Rewind(); fPluginList->GetNext(&pinfo); ) {
167 		if (0 == strcmp(ref.name, pinfo->name)) {
168 			plugin = pinfo->plugin;
169 			pinfo->usecount++;
170 			fLocker->Unlock();
171 			return plugin;
172 		}
173 	}
174 
175 	if (!LoadPlugin(ref, &info.plugin, &info.image)) {
176 		printf("PluginManager: Error, loading PlugIn %s failed\n", ref.name);
177 		fLocker->Unlock();
178 		return 0;
179 	}
180 
181 	strcpy(info.name, ref.name);
182 	info.usecount = 1;
183 	fPluginList->Insert(info);
184 
185 	TRACE("PluginManager: PlugIn %s loaded\n", ref.name);
186 
187 	plugin = info.plugin;
188 
189 	fLocker->Unlock();
190 	return plugin;
191 }
192 
193 
194 void
195 PluginManager::PutPlugin(MediaPlugin *plugin)
196 {
197 	fLocker->Lock();
198 
199 	plugin_info *pinfo;
200 
201 	for (fPluginList->Rewind(); fPluginList->GetNext(&pinfo); ) {
202 		if (plugin == pinfo->plugin) {
203 			pinfo->usecount--;
204 			if (pinfo->usecount == 0) {
205 				delete pinfo->plugin;
206 				unload_add_on(pinfo->image);
207 			}
208 			fPluginList->RemoveCurrent();
209 			fLocker->Unlock();
210 			return;
211 		}
212 	}
213 
214 	printf("PluginManager: Error, can't put PlugIn %p\n", plugin);
215 
216 	fLocker->Unlock();
217 }
218 
219 
220 bool
221 PluginManager::LoadPlugin(const entry_ref &ref, MediaPlugin **plugin, image_id *image)
222 {
223 	BPath p(&ref);
224 
225 	TRACE("PluginManager: LoadPlugin trying to load %s\n", p.Path());
226 
227 	image_id id;
228 	id = load_add_on(p.Path());
229 	if (id < 0)
230 		return false;
231 
232 	MediaPlugin *(*instantiate_plugin_func)();
233 
234 	if (get_image_symbol(id, "instantiate_plugin", B_SYMBOL_TYPE_TEXT, (void**)&instantiate_plugin_func) < B_OK) {
235 		printf("PluginManager: Error, LoadPlugin can't find instantiate_plugin in %s\n", p.Path());
236 		unload_add_on(id);
237 		return false;
238 	}
239 
240 	MediaPlugin *pl;
241 
242 	pl = (*instantiate_plugin_func)();
243 	if (pl == 0) {
244 		printf("PluginManager: Error, LoadPlugin instantiate_plugin in %s returned 0\n", p.Path());
245 		unload_add_on(id);
246 		return false;
247 	}
248 
249 	*plugin = pl;
250 	*image = id;
251 	return true;
252 }
253