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