1 /*
2 * Copyright 2004-2010, Marcus Overhagen. All rights reserved.
3 * Copyright 2016, Dario Casalinuovo. All rights reserved.
4 * Distributed under the terms of the MIT License.
5 */
6
7
8 #include <AdapterIO.h>
9 #include <AutoDeleter.h>
10 #include <Autolock.h>
11 #include <BufferIO.h>
12 #include <DataIO.h>
13 #include <image.h>
14 #include <Path.h>
15
16 #include <string.h>
17
18 #include "AddOnManager.h"
19 #include "PluginManager.h"
20 #include "DataExchange.h"
21 #include "MediaDebug.h"
22
23
24 PluginManager gPluginManager;
25
26 #define BLOCK_SIZE 4096
27 #define MAX_STREAMERS 40
28
29
30 class DataIOAdapter : public BAdapterIO {
31 public:
DataIOAdapter(BDataIO * dataIO)32 DataIOAdapter(BDataIO* dataIO)
33 :
34 BAdapterIO(B_MEDIA_SEEK_BACKWARD | B_MEDIA_MUTABLE_SIZE,
35 B_INFINITE_TIMEOUT),
36 fDataIO(dataIO)
37 {
38 fDataInputAdapter = BuildInputAdapter();
39 }
40
~DataIOAdapter()41 virtual ~DataIOAdapter()
42 {
43 }
44
ReadAt(off_t position,void * buffer,size_t size)45 virtual ssize_t ReadAt(off_t position, void* buffer,
46 size_t size)
47 {
48 if (position == Position()) {
49 ssize_t ret = fDataIO->Read(buffer, size);
50 fDataInputAdapter->Write(buffer, ret);
51 return ret;
52 }
53
54 off_t totalSize = 0;
55 if (GetSize(&totalSize) != B_OK)
56 return B_UNSUPPORTED;
57
58 if (position+size < (size_t)totalSize)
59 return ReadAt(position, buffer, size);
60
61 return B_NOT_SUPPORTED;
62 }
63
WriteAt(off_t position,const void * buffer,size_t size)64 virtual ssize_t WriteAt(off_t position, const void* buffer,
65 size_t size)
66 {
67 if (position == Position()) {
68 ssize_t ret = fDataIO->Write(buffer, size);
69 fDataInputAdapter->Write(buffer, ret);
70 return ret;
71 }
72
73 return B_NOT_SUPPORTED;
74 }
75
76 private:
77 BDataIO* fDataIO;
78 BInputAdapter* fDataInputAdapter;
79 };
80
81
82 class BMediaIOWrapper : public BMediaIO {
83 public:
BMediaIOWrapper(BDataIO * source)84 BMediaIOWrapper(BDataIO* source)
85 :
86 fData(NULL),
87 fPosition(NULL),
88 fMedia(NULL),
89 fDataIOAdapter(NULL),
90 fErr(B_NO_ERROR)
91 {
92 CALLED();
93
94 fPosition = dynamic_cast<BPositionIO*>(source);
95 fMedia = dynamic_cast<BMediaIO*>(source);
96 fData = source;
97
98 if (!IsPosition()) {
99 // In this case we have to supply our own form
100 // of pseudo-seekable object from a non-seekable
101 // BDataIO.
102 fDataIOAdapter = new DataIOAdapter(source);
103 fMedia = dynamic_cast<BMediaIO*>(fDataIOAdapter);
104 fPosition = dynamic_cast<BPositionIO*>(fDataIOAdapter);
105 fData = dynamic_cast<BDataIO*>(fDataIOAdapter);
106 TRACE("Unable to improve performance with a BufferIO\n");
107 }
108
109 if (IsMedia())
110 fMedia->GetFlags(&fFlags);
111 else if (IsPosition())
112 fFlags = B_MEDIA_SEEKABLE;
113 }
114
~BMediaIOWrapper()115 virtual ~BMediaIOWrapper()
116 {
117 if (fDataIOAdapter != NULL)
118 delete fDataIOAdapter;
119 }
120
InitCheck() const121 status_t InitCheck() const
122 {
123 return fErr;
124 }
125
126 // BMediaIO interface
127
GetFlags(int32 * flags) const128 virtual void GetFlags(int32* flags) const
129 {
130 *flags = fFlags;
131 }
132
133 // BPositionIO interface
134
ReadAt(off_t position,void * buffer,size_t size)135 virtual ssize_t ReadAt(off_t position, void* buffer,
136 size_t size)
137 {
138 CALLED();
139
140 return fPosition->ReadAt(position, buffer, size);
141 }
142
WriteAt(off_t position,const void * buffer,size_t size)143 virtual ssize_t WriteAt(off_t position, const void* buffer,
144 size_t size)
145 {
146 CALLED();
147
148 return fPosition->WriteAt(position, buffer, size);
149 }
150
Seek(off_t position,uint32 seekMode)151 virtual off_t Seek(off_t position, uint32 seekMode)
152 {
153 CALLED();
154
155 return fPosition->Seek(position, seekMode);
156
157 }
158
Position() const159 virtual off_t Position() const
160 {
161 CALLED();
162
163 return fPosition->Position();
164 }
165
SetSize(off_t size)166 virtual status_t SetSize(off_t size)
167 {
168 CALLED();
169
170 return fPosition->SetSize(size);
171 }
172
GetSize(off_t * size) const173 virtual status_t GetSize(off_t* size) const
174 {
175 CALLED();
176
177 return fPosition->GetSize(size);
178 }
179
180 protected:
181
IsMedia() const182 bool IsMedia() const
183 {
184 return fMedia != NULL;
185 }
186
IsPosition() const187 bool IsPosition() const
188 {
189 return fPosition != NULL;
190 }
191
192 private:
193 BDataIO* fData;
194 BPositionIO* fPosition;
195 BMediaIO* fMedia;
196 DataIOAdapter* fDataIOAdapter;
197
198 int32 fFlags;
199
200 status_t fErr;
201 };
202
203
204 // #pragma mark - Readers/Decoders
205
206
207 status_t
CreateReader(Reader ** reader,int32 * streamCount,media_file_format * mff,BDataIO * source)208 PluginManager::CreateReader(Reader** reader, int32* streamCount,
209 media_file_format* mff, BDataIO* source)
210 {
211 TRACE("PluginManager::CreateReader enter\n");
212
213 // The wrapper class will present our source in a more useful
214 // way, we create an instance which is buffering our reads and
215 // writes.
216 BMediaIOWrapper* buffered_source = new BMediaIOWrapper(source);
217 ObjectDeleter<BMediaIOWrapper> ioDeleter(buffered_source);
218
219 status_t ret = buffered_source->InitCheck();
220 if (ret != B_OK)
221 return ret;
222
223 // get list of available readers from the server
224 entry_ref refs[MAX_READERS];
225 int32 count;
226
227 ret = AddOnManager::GetInstance()->GetReaders(refs, &count,
228 MAX_READERS);
229 if (ret != B_OK) {
230 printf("PluginManager::CreateReader: can't get list of readers: %s\n",
231 strerror(ret));
232 return ret;
233 }
234
235 // try each reader by calling it's Sniff function...
236 for (int32 i = 0; i < count; i++) {
237 const entry_ref& ref = refs[i];
238 MediaPlugin* plugin = GetPlugin(ref);
239 if (plugin == NULL) {
240 printf("PluginManager::CreateReader: GetPlugin failed\n");
241 return B_ERROR;
242 }
243
244 ReaderPlugin* readerPlugin = dynamic_cast<ReaderPlugin*>(plugin);
245 if (readerPlugin == NULL) {
246 printf("PluginManager::CreateReader: dynamic_cast failed\n");
247 PutPlugin(plugin);
248 return B_ERROR;
249 }
250
251 *reader = readerPlugin->NewReader();
252 if (*reader == NULL) {
253 printf("PluginManager::CreateReader: NewReader failed\n");
254 PutPlugin(plugin);
255 return B_ERROR;
256 }
257
258 buffered_source->Seek(0, SEEK_SET);
259 (*reader)->Setup(buffered_source);
260 (*reader)->fMediaPlugin = plugin;
261
262 if ((*reader)->Sniff(streamCount) == B_OK) {
263 TRACE("PluginManager::CreateReader: Sniff success "
264 "(%" B_PRId32 " stream(s))\n", *streamCount);
265 (*reader)->GetFileFormatInfo(mff);
266 ioDeleter.Detach();
267 return B_OK;
268 }
269
270 DestroyReader(*reader);
271 *reader = NULL;
272 }
273
274 TRACE("PluginManager::CreateReader leave\n");
275 return B_MEDIA_NO_HANDLER;
276 }
277
278
279 void
DestroyReader(Reader * reader)280 PluginManager::DestroyReader(Reader* reader)
281 {
282 if (reader != NULL) {
283 TRACE("PluginManager::DestroyReader(%p (plugin: %p))\n", reader,
284 reader->fMediaPlugin);
285 // NOTE: We have to put the plug-in after deleting the reader,
286 // since otherwise we may actually unload the code for the
287 // destructor...
288 MediaPlugin* plugin = reader->fMediaPlugin;
289 delete reader;
290 PutPlugin(plugin);
291 }
292 }
293
294
295 status_t
CreateDecoder(Decoder ** _decoder,const media_format & format)296 PluginManager::CreateDecoder(Decoder** _decoder, const media_format& format)
297 {
298 TRACE("PluginManager::CreateDecoder enter\n");
299
300 // get decoder for this format
301 entry_ref ref;
302 status_t ret = AddOnManager::GetInstance()->GetDecoderForFormat(
303 &ref, format);
304 if (ret != B_OK) {
305 printf("PluginManager::CreateDecoder: can't get decoder for format: "
306 "%s\n", strerror(ret));
307 return ret;
308 }
309
310 MediaPlugin* plugin = GetPlugin(ref);
311 if (plugin == NULL) {
312 printf("PluginManager::CreateDecoder: GetPlugin failed\n");
313 return B_ERROR;
314 }
315
316 DecoderPlugin* decoderPlugin = dynamic_cast<DecoderPlugin*>(plugin);
317 if (decoderPlugin == NULL) {
318 printf("PluginManager::CreateDecoder: dynamic_cast failed\n");
319 PutPlugin(plugin);
320 return B_ERROR;
321 }
322
323 // TODO: In theory, one DecoderPlugin could support multiple Decoders,
324 // but this is not yet handled (passing "0" as index/ID).
325 *_decoder = decoderPlugin->NewDecoder(0);
326 if (*_decoder == NULL) {
327 printf("PluginManager::CreateDecoder: NewDecoder() failed\n");
328 PutPlugin(plugin);
329 return B_ERROR;
330 }
331 TRACE(" created decoder: %p\n", *_decoder);
332 (*_decoder)->fMediaPlugin = plugin;
333
334 TRACE("PluginManager::CreateDecoder leave\n");
335
336 return B_OK;
337 }
338
339
340 status_t
CreateDecoder(Decoder ** decoder,const media_codec_info & mci)341 PluginManager::CreateDecoder(Decoder** decoder, const media_codec_info& mci)
342 {
343 TRACE("PluginManager::CreateDecoder enter\n");
344 entry_ref ref;
345 status_t status = AddOnManager::GetInstance()->GetEncoder(&ref, mci.id);
346 if (status != B_OK)
347 return status;
348
349 MediaPlugin* plugin = GetPlugin(ref);
350 if (plugin == NULL) {
351 ERROR("PluginManager::CreateDecoder: GetPlugin failed\n");
352 return B_ERROR;
353 }
354
355 DecoderPlugin* decoderPlugin = dynamic_cast<DecoderPlugin*>(plugin);
356 if (decoderPlugin == NULL) {
357 ERROR("PluginManager::CreateDecoder: dynamic_cast failed\n");
358 PutPlugin(plugin);
359 return B_ERROR;
360 }
361
362 // TODO: In theory, one DecoderPlugin could support multiple Decoders,
363 // but this is not yet handled (passing "0" as index/ID).
364 *decoder = decoderPlugin->NewDecoder(0);
365 if (*decoder == NULL) {
366 ERROR("PluginManager::CreateDecoder: NewDecoder() failed\n");
367 PutPlugin(plugin);
368 return B_ERROR;
369 }
370 TRACE(" created decoder: %p\n", *decoder);
371 (*decoder)->fMediaPlugin = plugin;
372
373 TRACE("PluginManager::CreateDecoder leave\n");
374
375 return B_OK;
376
377 }
378
379
380 status_t
GetDecoderInfo(Decoder * decoder,media_codec_info * _info) const381 PluginManager::GetDecoderInfo(Decoder* decoder, media_codec_info* _info) const
382 {
383 if (decoder == NULL)
384 return B_BAD_VALUE;
385
386 decoder->GetCodecInfo(_info);
387 // TODO:
388 // out_info->id =
389 // out_info->sub_id =
390 return B_OK;
391 }
392
393
394 void
DestroyDecoder(Decoder * decoder)395 PluginManager::DestroyDecoder(Decoder* decoder)
396 {
397 if (decoder != NULL) {
398 TRACE("PluginManager::DestroyDecoder(%p, plugin: %p)\n", decoder,
399 decoder->fMediaPlugin);
400 // NOTE: We have to put the plug-in after deleting the decoder,
401 // since otherwise we may actually unload the code for the
402 // destructor...
403 MediaPlugin* plugin = decoder->fMediaPlugin;
404 delete decoder;
405 PutPlugin(plugin);
406 }
407 }
408
409
410 // #pragma mark - Writers/Encoders
411
412
413 status_t
CreateWriter(Writer ** writer,const media_file_format & mff,BDataIO * target)414 PluginManager::CreateWriter(Writer** writer, const media_file_format& mff,
415 BDataIO* target)
416 {
417 TRACE("PluginManager::CreateWriter enter\n");
418
419 // Get the Writer responsible for this media_file_format from the server.
420 entry_ref ref;
421 status_t ret = AddOnManager::GetInstance()->GetWriter(&ref,
422 mff.id.internal_id);
423 if (ret != B_OK) {
424 printf("PluginManager::CreateWriter: can't get writer for file "
425 "family: %s\n", strerror(ret));
426 return ret;
427 }
428
429 MediaPlugin* plugin = GetPlugin(ref);
430 if (plugin == NULL) {
431 printf("PluginManager::CreateWriter: GetPlugin failed\n");
432 return B_ERROR;
433 }
434
435 WriterPlugin* writerPlugin = dynamic_cast<WriterPlugin*>(plugin);
436 if (writerPlugin == NULL) {
437 printf("PluginManager::CreateWriter: dynamic_cast failed\n");
438 PutPlugin(plugin);
439 return B_ERROR;
440 }
441
442 *writer = writerPlugin->NewWriter();
443 if (*writer == NULL) {
444 printf("PluginManager::CreateWriter: NewWriter failed\n");
445 PutPlugin(plugin);
446 return B_ERROR;
447 }
448
449 (*writer)->Setup(target);
450 (*writer)->fMediaPlugin = plugin;
451
452 TRACE("PluginManager::CreateWriter leave\n");
453 return B_OK;
454 }
455
456
457 void
DestroyWriter(Writer * writer)458 PluginManager::DestroyWriter(Writer* writer)
459 {
460 if (writer != NULL) {
461 TRACE("PluginManager::DestroyWriter(%p (plugin: %p))\n", writer,
462 writer->fMediaPlugin);
463 // NOTE: We have to put the plug-in after deleting the writer,
464 // since otherwise we may actually unload the code for the
465 // destructor...
466 MediaPlugin* plugin = writer->fMediaPlugin;
467 delete writer;
468 PutPlugin(plugin);
469 }
470 }
471
472
473 status_t
CreateEncoder(Encoder ** _encoder,const media_codec_info * codecInfo,uint32 flags)474 PluginManager::CreateEncoder(Encoder** _encoder,
475 const media_codec_info* codecInfo, uint32 flags)
476 {
477 TRACE("PluginManager::CreateEncoder enter\n");
478
479 // Get encoder for this codec info from the server
480 entry_ref ref;
481 status_t ret = AddOnManager::GetInstance()->GetEncoder(&ref,
482 codecInfo->id);
483 if (ret != B_OK) {
484 printf("PluginManager::CreateEncoder: can't get encoder for codec %s: "
485 "%s\n", codecInfo->pretty_name, strerror(ret));
486 return ret;
487 }
488
489 MediaPlugin* plugin = GetPlugin(ref);
490 if (!plugin) {
491 printf("PluginManager::CreateEncoder: GetPlugin failed\n");
492 return B_ERROR;
493 }
494
495 EncoderPlugin* encoderPlugin = dynamic_cast<EncoderPlugin*>(plugin);
496 if (encoderPlugin == NULL) {
497 printf("PluginManager::CreateEncoder: dynamic_cast failed\n");
498 PutPlugin(plugin);
499 return B_ERROR;
500 }
501
502 *_encoder = encoderPlugin->NewEncoder(*codecInfo);
503 if (*_encoder == NULL) {
504 printf("PluginManager::CreateEncoder: NewEncoder() failed\n");
505 PutPlugin(plugin);
506 return B_ERROR;
507 }
508 TRACE(" created encoder: %p\n", *_encoder);
509 (*_encoder)->fMediaPlugin = plugin;
510
511 TRACE("PluginManager::CreateEncoder leave\n");
512
513 return B_OK;
514 }
515
516
517 status_t
CreateEncoder(Encoder ** encoder,const media_format & format)518 PluginManager::CreateEncoder(Encoder** encoder, const media_format& format)
519 {
520 TRACE("PluginManager::CreateEncoder enter nr2\n");
521
522 entry_ref ref;
523
524 status_t ret = AddOnManager::GetInstance()->GetEncoderForFormat(
525 &ref, format);
526
527 if (ret != B_OK) {
528 ERROR("PluginManager::CreateEncoder: can't get decoder for format: "
529 "%s\n", strerror(ret));
530 return ret;
531 }
532
533 MediaPlugin* plugin = GetPlugin(ref);
534 if (plugin == NULL) {
535 ERROR("PluginManager::CreateEncoder: GetPlugin failed\n");
536 return B_ERROR;
537 }
538
539 EncoderPlugin* encoderPlugin = dynamic_cast<EncoderPlugin*>(plugin);
540 if (encoderPlugin == NULL) {
541 ERROR("PluginManager::CreateEncoder: dynamic_cast failed\n");
542 PutPlugin(plugin);
543 return B_ERROR;
544 }
545
546
547 *encoder = encoderPlugin->NewEncoder(format);
548 if (*encoder == NULL) {
549 ERROR("PluginManager::CreateEncoder: NewEncoder() failed\n");
550 PutPlugin(plugin);
551 return B_ERROR;
552 }
553 TRACE(" created encoder: %p\n", *encoder);
554 (*encoder)->fMediaPlugin = plugin;
555
556 TRACE("PluginManager::CreateEncoder leave nr2\n");
557
558 return B_OK;
559 }
560
561
562 void
DestroyEncoder(Encoder * encoder)563 PluginManager::DestroyEncoder(Encoder* encoder)
564 {
565 if (encoder != NULL) {
566 TRACE("PluginManager::DestroyEncoder(%p, plugin: %p)\n", encoder,
567 encoder->fMediaPlugin);
568 // NOTE: We have to put the plug-in after deleting the encoder,
569 // since otherwise we may actually unload the code for the
570 // destructor...
571 MediaPlugin* plugin = encoder->fMediaPlugin;
572 delete encoder;
573 PutPlugin(plugin);
574 }
575 }
576
577
578 status_t
CreateStreamer(Streamer ** streamer,BUrl url,BDataIO ** source)579 PluginManager::CreateStreamer(Streamer** streamer, BUrl url, BDataIO** source)
580 {
581 BAutolock _(fLocker);
582
583 TRACE("PluginManager::CreateStreamer enter\n");
584
585 entry_ref refs[MAX_STREAMERS];
586 int32 count;
587
588 status_t ret = AddOnManager::GetInstance()->GetStreamers(refs, &count,
589 MAX_STREAMERS);
590 if (ret != B_OK) {
591 printf("PluginManager::CreateStreamer: can't get list of streamers:"
592 " %s\n", strerror(ret));
593 return ret;
594 }
595
596 // try each reader by calling it's Sniff function...
597 for (int32 i = 0; i < count; i++) {
598 entry_ref ref = refs[i];
599 MediaPlugin* plugin = GetPlugin(ref);
600 if (plugin == NULL) {
601 printf("PluginManager::CreateStreamer: GetPlugin failed\n");
602 return B_ERROR;
603 }
604
605 StreamerPlugin* streamerPlugin = dynamic_cast<StreamerPlugin*>(plugin);
606 if (streamerPlugin == NULL) {
607 printf("PluginManager::CreateStreamer: dynamic_cast failed\n");
608 PutPlugin(plugin);
609 return B_ERROR;
610 }
611
612 *streamer = streamerPlugin->NewStreamer();
613 if (*streamer == NULL) {
614 printf("PluginManager::CreateStreamer: NewReader failed\n");
615 PutPlugin(plugin);
616 return B_ERROR;
617 }
618
619 (*streamer)->fMediaPlugin = plugin;
620 plugin->fRefCount++;
621
622 BDataIO* streamSource = NULL;
623 if ((*streamer)->Sniff(url, &streamSource) == B_OK) {
624 TRACE("PluginManager::CreateStreamer: Sniff success\n");
625 *source = streamSource;
626 return B_OK;
627 }
628
629 DestroyStreamer(*streamer);
630 *streamer = NULL;
631 }
632
633 TRACE("PluginManager::CreateStreamer leave\n");
634 return B_MEDIA_NO_HANDLER;
635 }
636
637
638 void
DestroyStreamer(Streamer * streamer)639 PluginManager::DestroyStreamer(Streamer* streamer)
640 {
641 BAutolock _(fLocker);
642
643 if (streamer != NULL) {
644 TRACE("PluginManager::DestroyStreamer(%p, plugin: %p)\n", streamer,
645 streamer->fMediaPlugin);
646
647 // NOTE: We have to put the plug-in after deleting the streamer,
648 // since otherwise we may actually unload the code for the
649 // destructor...
650 MediaPlugin* plugin = streamer->fMediaPlugin;
651 delete streamer;
652
653 // Delete the plugin only when every reference is released
654 if (plugin->fRefCount == 1) {
655 plugin->fRefCount = 0;
656 PutPlugin(plugin);
657 } else
658 plugin->fRefCount--;
659 }
660 }
661
662
663 // #pragma mark -
664
665
PluginManager()666 PluginManager::PluginManager()
667 :
668 fPluginList(),
669 fLocker("media plugin manager")
670 {
671 CALLED();
672 }
673
674
~PluginManager()675 PluginManager::~PluginManager()
676 {
677 CALLED();
678 for (int i = fPluginList.CountItems() - 1; i >= 0; i--) {
679 plugin_info* info = NULL;
680 fPluginList.Get(i, &info);
681 TRACE("PluginManager: Error, unloading PlugIn %s with usecount "
682 "%d\n", info->name, info->usecount);
683 delete info->plugin;
684 unload_add_on(info->image);
685 }
686 }
687
688
689 MediaPlugin*
GetPlugin(const entry_ref & ref)690 PluginManager::GetPlugin(const entry_ref& ref)
691 {
692 TRACE("PluginManager::GetPlugin(%s)\n", ref.name);
693 fLocker.Lock();
694
695 MediaPlugin* plugin;
696 plugin_info* pinfo;
697 plugin_info info;
698
699 for (fPluginList.Rewind(); fPluginList.GetNext(&pinfo); ) {
700 if (0 == strcmp(ref.name, pinfo->name)) {
701 plugin = pinfo->plugin;
702 pinfo->usecount++;
703 TRACE(" found existing plugin: %p\n", pinfo->plugin);
704 fLocker.Unlock();
705 return plugin;
706 }
707 }
708
709 if (_LoadPlugin(ref, &info.plugin, &info.image) < B_OK) {
710 printf("PluginManager: Error, loading PlugIn %s failed\n", ref.name);
711 fLocker.Unlock();
712 return NULL;
713 }
714
715 strcpy(info.name, ref.name);
716 info.usecount = 1;
717 fPluginList.Insert(info);
718
719 TRACE("PluginManager: PlugIn %s loaded\n", ref.name);
720
721 plugin = info.plugin;
722 TRACE(" loaded plugin: %p\n", plugin);
723
724 fLocker.Unlock();
725 return plugin;
726 }
727
728
729 void
PutPlugin(MediaPlugin * plugin)730 PluginManager::PutPlugin(MediaPlugin* plugin)
731 {
732 TRACE("PluginManager::PutPlugin()\n");
733 fLocker.Lock();
734
735 plugin_info* pinfo;
736
737 for (fPluginList.Rewind(); fPluginList.GetNext(&pinfo); ) {
738 if (plugin == pinfo->plugin) {
739 pinfo->usecount--;
740 if (pinfo->usecount == 0) {
741 TRACE(" deleting %p\n", pinfo->plugin);
742 delete pinfo->plugin;
743 TRACE(" unloading add-on: %" B_PRId32 "\n\n", pinfo->image);
744 unload_add_on(pinfo->image);
745 fPluginList.RemoveCurrent();
746 }
747 fLocker.Unlock();
748 return;
749 }
750 }
751
752 printf("PluginManager: Error, can't put PlugIn %p\n", plugin);
753
754 fLocker.Unlock();
755 }
756
757
758 status_t
_LoadPlugin(const entry_ref & ref,MediaPlugin ** plugin,image_id * image)759 PluginManager::_LoadPlugin(const entry_ref& ref, MediaPlugin** plugin,
760 image_id* image)
761 {
762 BPath p(&ref);
763
764 TRACE("PluginManager: _LoadPlugin trying to load %s\n", p.Path());
765
766 image_id id;
767 id = load_add_on(p.Path());
768 if (id < 0) {
769 printf("PluginManager: Error, load_add_on(): %s\n", strerror(id));
770 return B_ERROR;
771 }
772
773 MediaPlugin* (*instantiate_plugin_func)();
774
775 if (get_image_symbol(id, "instantiate_plugin", B_SYMBOL_TYPE_TEXT,
776 (void**)&instantiate_plugin_func) < B_OK) {
777 printf("PluginManager: Error, _LoadPlugin can't find "
778 "instantiate_plugin in %s\n", p.Path());
779 unload_add_on(id);
780 return B_ERROR;
781 }
782
783 MediaPlugin *pl;
784
785 pl = (*instantiate_plugin_func)();
786 if (pl == NULL) {
787 printf("PluginManager: Error, _LoadPlugin instantiate_plugin in %s "
788 "returned NULL\n", p.Path());
789 unload_add_on(id);
790 return B_ERROR;
791 }
792
793 *plugin = pl;
794 *image = id;
795 return B_OK;
796 }
797