1 | |
2 | |
3 | |
4 | |
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 | |
23 | PluginManager gPluginManager; |
24 | |
25 | #define BLOCK_SIZE4096 4096 |
26 | #define MAX_STREAMERS40 40 |
27 | |
28 | |
29 | class DataIOAdapter : public BAdapterIO { |
30 | public: |
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 | |
75 | private: |
76 | BDataIO* fDataIO; |
77 | BInputAdapter* fDataInputAdapter; |
78 | }; |
79 | |
80 | |
81 | class BMediaIOWrapper : public BMediaIO { |
82 | public: |
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 | |
100 | |
101 | if (!IsMedia() && fBufferIO == NULL__null) { |
102 | |
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 | |
110 | fPosition = dynamic_cast<BPositionIO*>(fBufferIO); |
111 | fData = dynamic_cast<BDataIO*>(fPosition); |
112 | } else { |
113 | |
114 | |
115 | |
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 | |
140 | |
141 | virtual void GetFlags(int32* flags) const |
142 | { |
143 | *flags = fFlags; |
144 | } |
145 | |
146 | |
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 | |
194 | |
195 | status_t InitCheck() const |
196 | { |
197 | return fErr; |
198 | } |
199 | |
200 | protected: |
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 | |
212 | private: |
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 | |
226 | |
227 | |
228 | status_t |
229 | PluginManager::CreateReader(Reader** reader, int32* streamCount, |
230 | media_file_format* mff, BDataIO* source) |
231 | { |
232 | TRACE("PluginManager::CreateReader enter\n")((void)0); |
233 | |
234 | |
235 | |
236 | |
237 | BMediaIOWrapper* buffered_source = new BMediaIOWrapper(source); |
| |
238 | status_t ret = buffered_source->InitCheck(); |
239 | if (ret != B_OK((int)0)) |
| 2 | | Assuming 'ret' is not equal to B_OK | |
|
| |
240 | return ret; |
| 4 | | Potential leak of memory pointed to by 'buffered_source' |
|
241 | |
242 | |
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 | |
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 | |
297 | void |
298 | PluginManager::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 | |
304 | |
305 | |
306 | MediaPlugin* plugin = reader->fMediaPlugin; |
307 | delete reader; |
308 | PutPlugin(plugin); |
309 | } |
310 | } |
311 | |
312 | |
313 | status_t |
314 | PluginManager::CreateDecoder(Decoder** _decoder, const media_format& format) |
315 | { |
316 | TRACE("PluginManager::CreateDecoder enter\n")((void)0); |
317 | |
318 | |
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 | |
342 | |
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 | |
358 | status_t |
359 | PluginManager::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 | |
381 | |
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 | |
398 | status_t |
399 | PluginManager::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 | |
406 | |
407 | |
408 | return B_OK((int)0); |
409 | } |
410 | |
411 | |
412 | void |
413 | PluginManager::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 | |
419 | |
420 | |
421 | MediaPlugin* plugin = decoder->fMediaPlugin; |
422 | delete decoder; |
423 | PutPlugin(plugin); |
424 | } |
425 | } |
426 | |
427 | |
428 | |
429 | |
430 | |
431 | status_t |
432 | PluginManager::CreateWriter(Writer** writer, const media_file_format& mff, |
433 | BDataIO* target) |
434 | { |
435 | TRACE("PluginManager::CreateWriter enter\n")((void)0); |
436 | |
437 | |
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 | |
475 | void |
476 | PluginManager::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 | |
482 | |
483 | |
484 | MediaPlugin* plugin = writer->fMediaPlugin; |
485 | delete writer; |
486 | PutPlugin(plugin); |
487 | } |
488 | } |
489 | |
490 | |
491 | status_t |
492 | PluginManager::CreateEncoder(Encoder** _encoder, |
493 | const media_codec_info* codecInfo, uint32 flags) |
494 | { |
495 | TRACE("PluginManager::CreateEncoder enter\n")((void)0); |
496 | |
497 | |
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 | |
535 | status_t |
536 | PluginManager::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 | |
580 | void |
581 | PluginManager::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 | |
587 | |
588 | |
589 | MediaPlugin* plugin = encoder->fMediaPlugin; |
590 | delete encoder; |
591 | PutPlugin(plugin); |
592 | } |
593 | } |
594 | |
595 | |
596 | status_t |
597 | PluginManager::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 | |
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 | |
656 | void |
657 | PluginManager::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 | |
666 | |
667 | |
668 | MediaPlugin* plugin = streamer->fMediaPlugin; |
669 | delete streamer; |
670 | |
671 | |
672 | if (plugin->fRefCount == 1) { |
673 | plugin->fRefCount = 0; |
674 | PutPlugin(plugin); |
675 | } else |
676 | plugin->fRefCount--; |
677 | } |
678 | } |
679 | |
680 | |
681 | |
682 | |
683 | |
684 | PluginManager::PluginManager() |
685 | : |
686 | fPluginList(), |
687 | fLocker("media plugin manager") |
688 | { |
689 | CALLED()((void)0); |
690 | } |
691 | |
692 | |
693 | PluginManager::~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 | |
707 | MediaPlugin* |
708 | PluginManager::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 | |
747 | void |
748 | PluginManager::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 | |
776 | status_t |
777 | PluginManager::_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 | } |