Bug Summary

File:src/kits/media/PluginManager.cpp
Warning:line 240, column 10
Potential leak of memory pointed to by 'buffered_source'

Annotated Source Code

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