tcp: Fix 64 bit build with debugging features enabled.
[haiku.git] / src / kits / media / PluginManager.cpp
blob367607f4ec06ca35fc8e235f7388c1949f22a9fa
1 /*
2 * Copyright 2004-2010, Marcus Overhagen. All rights reserved.
3 * Distributed under the terms of the OpenBeOS License.
4 */
6 #include <Path.h>
7 #include <image.h>
8 #include <string.h>
10 #include "AddOnManager.h"
11 #include "PluginManager.h"
12 #include "DataExchange.h"
13 #include "debug.h"
16 PluginManager gPluginManager;
19 // #pragma mark - Readers/Decoders
22 status_t
23 PluginManager::CreateReader(Reader** reader, int32* streamCount,
24 media_file_format* mff, BDataIO* source)
26 TRACE("PluginManager::CreateReader enter\n");
28 BPositionIO *seekable_source = dynamic_cast<BPositionIO *>(source);
29 if (seekable_source == 0) {
30 printf("PluginManager::CreateReader: non-seekable sources not "
31 "supported yet\n");
32 return B_ERROR;
35 // get list of available readers from the server
36 entry_ref refs[MAX_READERS];
37 int32 count;
39 status_t ret = AddOnManager::GetInstance()->GetReaders(refs, &count,
40 MAX_READERS);
41 if (ret != B_OK) {
42 printf("PluginManager::CreateReader: can't get list of readers: %s\n",
43 strerror(ret));
44 return ret;
47 // try each reader by calling it's Sniff function...
48 for (int32 i = 0; i < count; i++) {
49 entry_ref ref = refs[i];
50 MediaPlugin* plugin = GetPlugin(ref);
51 if (plugin == NULL) {
52 printf("PluginManager::CreateReader: GetPlugin failed\n");
53 return B_ERROR;
56 ReaderPlugin* readerPlugin = dynamic_cast<ReaderPlugin*>(plugin);
57 if (readerPlugin == NULL) {
58 printf("PluginManager::CreateReader: dynamic_cast failed\n");
59 PutPlugin(plugin);
60 return B_ERROR;
63 *reader = readerPlugin->NewReader();
64 if (*reader == NULL) {
65 printf("PluginManager::CreateReader: NewReader failed\n");
66 PutPlugin(plugin);
67 return B_ERROR;
70 seekable_source->Seek(0, SEEK_SET);
71 (*reader)->Setup(seekable_source);
72 (*reader)->fMediaPlugin = plugin;
74 if ((*reader)->Sniff(streamCount) == B_OK) {
75 TRACE("PluginManager::CreateReader: Sniff success "
76 "(%ld stream(s))\n", *streamCount);
77 (*reader)->GetFileFormatInfo(mff);
78 return B_OK;
81 DestroyReader(*reader);
82 *reader = NULL;
85 TRACE("PluginManager::CreateReader leave\n");
86 return B_MEDIA_NO_HANDLER;
90 void
91 PluginManager::DestroyReader(Reader* reader)
93 if (reader != NULL) {
94 TRACE("PluginManager::DestroyReader(%p (plugin: %p))\n", reader,
95 reader->fMediaPlugin);
96 // NOTE: We have to put the plug-in after deleting the reader,
97 // since otherwise we may actually unload the code for the
98 // destructor...
99 MediaPlugin* plugin = reader->fMediaPlugin;
100 delete reader;
101 PutPlugin(plugin);
106 status_t
107 PluginManager::CreateDecoder(Decoder** _decoder, const media_format& format)
109 TRACE("PluginManager::CreateDecoder enter\n");
111 // get decoder for this format
112 entry_ref ref;
113 status_t ret = AddOnManager::GetInstance()->GetDecoderForFormat(
114 &ref, format);
115 if (ret != B_OK) {
116 printf("PluginManager::CreateDecoder: can't get decoder for format: "
117 "%s\n", strerror(ret));
118 return ret;
121 MediaPlugin* plugin = GetPlugin(ref);
122 if (plugin == NULL) {
123 printf("PluginManager::CreateDecoder: GetPlugin failed\n");
124 return B_ERROR;
127 DecoderPlugin* decoderPlugin = dynamic_cast<DecoderPlugin*>(plugin);
128 if (decoderPlugin == NULL) {
129 printf("PluginManager::CreateDecoder: dynamic_cast failed\n");
130 PutPlugin(plugin);
131 return B_ERROR;
134 // TODO: In theory, one DecoderPlugin could support multiple Decoders,
135 // but this is not yet handled (passing "0" as index/ID).
136 *_decoder = decoderPlugin->NewDecoder(0);
137 if (*_decoder == NULL) {
138 printf("PluginManager::CreateDecoder: NewDecoder() failed\n");
139 PutPlugin(plugin);
140 return B_ERROR;
142 TRACE(" created decoder: %p\n", *_decoder);
143 (*_decoder)->fMediaPlugin = plugin;
145 TRACE("PluginManager::CreateDecoder leave\n");
147 return B_OK;
151 status_t
152 PluginManager::CreateDecoder(Decoder** decoder, const media_codec_info& mci)
154 // TODO
155 debugger("not implemented");
156 return B_ERROR;
160 status_t
161 PluginManager::GetDecoderInfo(Decoder* decoder, media_codec_info* _info) const
163 if (decoder == NULL)
164 return B_BAD_VALUE;
166 decoder->GetCodecInfo(_info);
167 // TODO:
168 // out_info->id =
169 // out_info->sub_id =
170 return B_OK;
174 void
175 PluginManager::DestroyDecoder(Decoder* decoder)
177 if (decoder != NULL) {
178 TRACE("PluginManager::DestroyDecoder(%p, plugin: %p)\n", decoder,
179 decoder->fMediaPlugin);
180 // NOTE: We have to put the plug-in after deleting the decoder,
181 // since otherwise we may actually unload the code for the
182 // destructor...
183 MediaPlugin* plugin = decoder->fMediaPlugin;
184 delete decoder;
185 PutPlugin(plugin);
190 // #pragma mark - Writers/Encoders
193 status_t
194 PluginManager::CreateWriter(Writer** writer, const media_file_format& mff,
195 BDataIO* target)
197 TRACE("PluginManager::CreateWriter enter\n");
199 // Get the Writer responsible for this media_file_format from the server.
200 entry_ref ref;
201 status_t ret = AddOnManager::GetInstance()->GetWriter(&ref,
202 mff.id.internal_id);
203 if (ret != B_OK) {
204 printf("PluginManager::CreateWriter: can't get writer for file "
205 "family: %s\n", strerror(ret));
206 return ret;
209 MediaPlugin* plugin = GetPlugin(ref);
210 if (plugin == NULL) {
211 printf("PluginManager::CreateWriter: GetPlugin failed\n");
212 return B_ERROR;
215 WriterPlugin* writerPlugin = dynamic_cast<WriterPlugin*>(plugin);
216 if (writerPlugin == NULL) {
217 printf("PluginManager::CreateWriter: dynamic_cast failed\n");
218 PutPlugin(plugin);
219 return B_ERROR;
222 *writer = writerPlugin->NewWriter();
223 if (*writer == NULL) {
224 printf("PluginManager::CreateWriter: NewWriter failed\n");
225 PutPlugin(plugin);
226 return B_ERROR;
229 (*writer)->Setup(target);
230 (*writer)->fMediaPlugin = plugin;
232 TRACE("PluginManager::CreateWriter leave\n");
233 return B_OK;
237 void
238 PluginManager::DestroyWriter(Writer* writer)
240 if (writer != NULL) {
241 TRACE("PluginManager::DestroyWriter(%p (plugin: %p))\n", writer,
242 writer->fMediaPlugin);
243 // NOTE: We have to put the plug-in after deleting the writer,
244 // since otherwise we may actually unload the code for the
245 // destructor...
246 MediaPlugin* plugin = writer->fMediaPlugin;
247 delete writer;
248 PutPlugin(plugin);
253 status_t
254 PluginManager::CreateEncoder(Encoder** _encoder,
255 const media_codec_info* codecInfo, uint32 flags)
257 TRACE("PluginManager::CreateEncoder enter\n");
259 // Get encoder for this codec info from the server
260 entry_ref ref;
261 status_t ret = AddOnManager::GetInstance()->GetEncoder(&ref,
262 codecInfo->id);
263 if (ret != B_OK) {
264 printf("PluginManager::CreateEncoder: can't get encoder for codec %s: "
265 "%s\n", codecInfo->pretty_name, strerror(ret));
266 return ret;
269 MediaPlugin* plugin = GetPlugin(ref);
270 if (!plugin) {
271 printf("PluginManager::CreateEncoder: GetPlugin failed\n");
272 return B_ERROR;
275 EncoderPlugin* encoderPlugin = dynamic_cast<EncoderPlugin*>(plugin);
276 if (encoderPlugin == NULL) {
277 printf("PluginManager::CreateEncoder: dynamic_cast failed\n");
278 PutPlugin(plugin);
279 return B_ERROR;
282 *_encoder = encoderPlugin->NewEncoder(*codecInfo);
283 if (*_encoder == NULL) {
284 printf("PluginManager::CreateEncoder: NewEncoder() failed\n");
285 PutPlugin(plugin);
286 return B_ERROR;
288 TRACE(" created encoder: %p\n", *_encoder);
289 (*_encoder)->fMediaPlugin = plugin;
291 TRACE("PluginManager::CreateEncoder leave\n");
293 return B_OK;
297 void
298 PluginManager::DestroyEncoder(Encoder* encoder)
300 if (encoder != NULL) {
301 TRACE("PluginManager::DestroyEncoder(%p, plugin: %p)\n", encoder,
302 encoder->fMediaPlugin);
303 // NOTE: We have to put the plug-in after deleting the encoder,
304 // since otherwise we may actually unload the code for the
305 // destructor...
306 MediaPlugin* plugin = encoder->fMediaPlugin;
307 delete encoder;
308 PutPlugin(plugin);
313 // #pragma mark -
316 PluginManager::PluginManager()
318 fPluginList(),
319 fLocker("media plugin manager")
321 CALLED();
325 PluginManager::~PluginManager()
327 CALLED();
328 for (int i = fPluginList.CountItems() - 1; i >= 0; i--) {
329 plugin_info* info = NULL;
330 fPluginList.Get(i, &info);
331 TRACE("PluginManager: Error, unloading PlugIn %s with usecount "
332 "%d\n", info->name, info->usecount);
333 delete info->plugin;
334 unload_add_on(info->image);
339 MediaPlugin*
340 PluginManager::GetPlugin(const entry_ref& ref)
342 TRACE("PluginManager::GetPlugin(%s)\n", ref.name);
343 fLocker.Lock();
345 MediaPlugin* plugin;
346 plugin_info* pinfo;
347 plugin_info info;
349 for (fPluginList.Rewind(); fPluginList.GetNext(&pinfo); ) {
350 if (0 == strcmp(ref.name, pinfo->name)) {
351 plugin = pinfo->plugin;
352 pinfo->usecount++;
353 TRACE(" found existing plugin: %p\n", pinfo->plugin);
354 fLocker.Unlock();
355 return plugin;
359 if (_LoadPlugin(ref, &info.plugin, &info.image) < B_OK) {
360 printf("PluginManager: Error, loading PlugIn %s failed\n", ref.name);
361 fLocker.Unlock();
362 return NULL;
365 strcpy(info.name, ref.name);
366 info.usecount = 1;
367 fPluginList.Insert(info);
369 TRACE("PluginManager: PlugIn %s loaded\n", ref.name);
371 plugin = info.plugin;
372 TRACE(" loaded plugin: %p\n", plugin);
374 fLocker.Unlock();
375 return plugin;
379 void
380 PluginManager::PutPlugin(MediaPlugin* plugin)
382 TRACE("PluginManager::PutPlugin()\n");
383 fLocker.Lock();
385 plugin_info* pinfo;
387 for (fPluginList.Rewind(); fPluginList.GetNext(&pinfo); ) {
388 if (plugin == pinfo->plugin) {
389 pinfo->usecount--;
390 if (pinfo->usecount == 0) {
391 TRACE(" deleting %p\n", pinfo->plugin);
392 delete pinfo->plugin;
393 TRACE(" unloading add-on: %ld\n\n", pinfo->image);
394 unload_add_on(pinfo->image);
395 fPluginList.RemoveCurrent();
397 fLocker.Unlock();
398 return;
402 printf("PluginManager: Error, can't put PlugIn %p\n", plugin);
404 fLocker.Unlock();
408 status_t
409 PluginManager::_LoadPlugin(const entry_ref& ref, MediaPlugin** plugin,
410 image_id* image)
412 BPath p(&ref);
414 TRACE("PluginManager: _LoadPlugin trying to load %s\n", p.Path());
416 image_id id;
417 id = load_add_on(p.Path());
418 if (id < 0) {
419 printf("PluginManager: Error, load_add_on(): %s\n", strerror(id));
420 return B_ERROR;
423 MediaPlugin* (*instantiate_plugin_func)();
425 if (get_image_symbol(id, "instantiate_plugin", B_SYMBOL_TYPE_TEXT,
426 (void**)&instantiate_plugin_func) < B_OK) {
427 printf("PluginManager: Error, _LoadPlugin can't find "
428 "instantiate_plugin in %s\n", p.Path());
429 unload_add_on(id);
430 return B_ERROR;
433 MediaPlugin *pl;
435 pl = (*instantiate_plugin_func)();
436 if (pl == NULL) {
437 printf("PluginManager: Error, _LoadPlugin instantiate_plugin in %s "
438 "returned NULL\n", p.Path());
439 unload_add_on(id);
440 return B_ERROR;
443 *plugin = pl;
444 *image = id;
445 return B_OK;