Almost rewritten the AddOnManager. It now works together with the new
media decoder detection code and the FormatManager. It now stores all registered formats from a decoder, and uses this information to implement GetDecoderForFormat(). git-svn-id: file:///srv/svn/repos/haiku/trunk/current@6245 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
61dec6a5c7
commit
20e3dd9dbe
@ -1,260 +1,315 @@
|
||||
#include <MediaFormats.h>
|
||||
#include <Locker.h>
|
||||
/*
|
||||
** Copyright 2004, the OpenBeOS project. All rights reserved.
|
||||
** Distributed under the terms of the OpenBeOS License.
|
||||
**
|
||||
** Authors: Marcus Overhagen, Axel Dörfler
|
||||
*/
|
||||
|
||||
|
||||
#include "AddOnManager.h"
|
||||
#include "FormatManager.h"
|
||||
#include "MetaFormat.h"
|
||||
#include "media_server.h"
|
||||
#include "debug.h"
|
||||
|
||||
#include <FindDirectory.h>
|
||||
#include <Path.h>
|
||||
#include <Entry.h>
|
||||
#include <Directory.h>
|
||||
#include <Autolock.h>
|
||||
#include <image.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "AddOnManager.h"
|
||||
#include "FormatManager.h"
|
||||
#include "debug.h"
|
||||
|
||||
extern FormatManager *gFormatManager;
|
||||
extern AddOnManager *gAddOnManager;
|
||||
|
||||
status_t
|
||||
_PublishDecoder(DecoderPlugin *decoderplugin,
|
||||
const char *meta_description,
|
||||
const char *short_name,
|
||||
const char *pretty_name,
|
||||
const char *default_mapping /* = 0 */);
|
||||
// #pragma mark ImageLoader
|
||||
|
||||
/** The ImageLoader class is a convenience class to temporarily load
|
||||
* an image file, and unload it on deconstruction automatically.
|
||||
*/
|
||||
|
||||
class ImageLoader {
|
||||
public:
|
||||
ImageLoader(BPath &path)
|
||||
{
|
||||
fImage = load_add_on(path.Path());
|
||||
}
|
||||
|
||||
~ImageLoader()
|
||||
{
|
||||
if (fImage >= B_OK)
|
||||
unload_add_on(fImage);
|
||||
}
|
||||
|
||||
status_t InitCheck() const { return fImage; }
|
||||
image_id Image() const { return fImage; }
|
||||
|
||||
private:
|
||||
image_id fImage;
|
||||
};
|
||||
|
||||
|
||||
static status_t
|
||||
register_decoder(const media_format_description *descriptions,
|
||||
int32 descriptionCount, media_format *format, uint32 flags)
|
||||
{
|
||||
return gAddOnManager->MakeDecoderFormats(descriptions, descriptionCount, format, flags);
|
||||
}
|
||||
|
||||
/* not yet used
|
||||
static status_t
|
||||
register_encoder(const media_format_description *descriptions,
|
||||
int32 descriptionCount, media_format *format, uint32 flags)
|
||||
{
|
||||
return gAddOnManager->MakeEncoderFormats(descriptions, descriptionCount, format, flags);
|
||||
}
|
||||
*/
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
bool operator==(const media_meta_description & a, const media_meta_description & b);
|
||||
|
||||
AddOnManager::AddOnManager()
|
||||
: fLocker(new BLocker),
|
||||
fReaderList(new List<reader_info>),
|
||||
fWriterList(new List<writer_info>),
|
||||
fDecoderList(new List<decoder_info>),
|
||||
fEncoderList(new List<encoder_info>),
|
||||
fReaderInfo(0),
|
||||
fWriterInfo(0),
|
||||
fDecoderInfo(0),
|
||||
fEncoderInfo(0)
|
||||
:
|
||||
fLock("add-on manager")
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
AddOnManager::~AddOnManager()
|
||||
{
|
||||
delete fLocker;
|
||||
delete fReaderList;
|
||||
delete fWriterList;
|
||||
delete fDecoderList;
|
||||
delete fEncoderList;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
AddOnManager::LoadState()
|
||||
{
|
||||
RegisterAddOns();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
AddOnManager::SaveState()
|
||||
{
|
||||
}
|
||||
|
||||
status_t
|
||||
AddOnManager::GetDecoderForFormat(xfer_entry_ref *out_ref,
|
||||
const media_format &in_format)
|
||||
{
|
||||
media_format_description desc;
|
||||
|
||||
if (B_OK != gFormatManager->GetDescriptionForFormat(&desc, in_format, B_META_FORMAT_FAMILY)) {
|
||||
printf("AddOnManager::GetDecoderForFormat: Error, meta format description unknown\n");
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
fLocker->Lock();
|
||||
|
||||
status_t
|
||||
AddOnManager::GetDecoderForFormat(xfer_entry_ref *_decoderRef,
|
||||
const media_format &format)
|
||||
{
|
||||
if ((format.type == B_MEDIA_ENCODED_VIDEO
|
||||
|| format.type == B_MEDIA_ENCODED_AUDIO
|
||||
|| format.type == B_MEDIA_MULTISTREAM)
|
||||
&& format.Encoding() == 0)
|
||||
return B_MEDIA_BAD_FORMAT;
|
||||
|
||||
BAutolock locker(fLock);
|
||||
|
||||
decoder_info *info;
|
||||
for (fDecoderList->Rewind(); fDecoderList->GetNext(&info); ) {
|
||||
media_meta_description *meta_desc;
|
||||
for (info->meta_desc.Rewind(); info->meta_desc.GetNext(&meta_desc); ) {
|
||||
if (desc.u.meta == *meta_desc) {
|
||||
printf("AddOnManager::GetDecoderForFormat: found decoder %s for format %s\n", info->ref.name, meta_desc->description);
|
||||
*out_ref = info->ref;
|
||||
fLocker->Unlock();
|
||||
return B_OK;
|
||||
}
|
||||
for (fDecoderList.Rewind(); fDecoderList.GetNext(&info);) {
|
||||
media_format *decoderFormat;
|
||||
for (info->formats.Rewind(); info->formats.GetNext(&decoderFormat);) {
|
||||
// check if the decoder matches the supplied format
|
||||
if (!decoderFormat->Matches(&format))
|
||||
continue;
|
||||
|
||||
printf("AddOnManager::GetDecoderForFormat: found decoder %s for encoding %ld\n",
|
||||
info->ref.name, decoderFormat->Encoding());
|
||||
|
||||
*_decoderRef = info->ref;
|
||||
return B_OK;
|
||||
}
|
||||
}
|
||||
fLocker->Unlock();
|
||||
return B_ERROR;
|
||||
return B_ENTRY_NOT_FOUND;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
AddOnManager::GetReaders(xfer_entry_ref *out_res, int32 *out_count, int32 max_count)
|
||||
{
|
||||
fLocker->Lock();
|
||||
|
||||
BAutolock locker(fLock);
|
||||
|
||||
*out_count = 0;
|
||||
|
||||
|
||||
fReaderList.Rewind();
|
||||
reader_info *info;
|
||||
for (*out_count = 0, fReaderList->Rewind(); fReaderList->GetNext(&info) && *out_count <= max_count; *out_count += 1)
|
||||
for (*out_count = 0; fReaderList.GetNext(&info) && *out_count <= max_count; *out_count += 1)
|
||||
out_res[*out_count] = info->ref;
|
||||
|
||||
fLocker->Unlock();
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
AddOnManager::RegisterAddOn(BEntry &entry)
|
||||
{
|
||||
BPath path(&entry);
|
||||
|
||||
entry_ref ref;
|
||||
status_t status = entry.GetRef(&ref);
|
||||
if (status < B_OK)
|
||||
return status;
|
||||
|
||||
printf("AddOnManager::RegisterAddOn(): trying to load \"%s\"\n", path.Path());
|
||||
|
||||
ImageLoader loader(path);
|
||||
if ((status = loader.InitCheck()) < B_OK)
|
||||
return status;
|
||||
|
||||
MediaPlugin *(*instantiate_plugin_func)();
|
||||
|
||||
if (get_image_symbol(loader.Image(), "instantiate_plugin",
|
||||
B_SYMBOL_TYPE_TEXT, (void **)&instantiate_plugin_func) < B_OK) {
|
||||
printf("AddOnManager::RegisterAddOn(): can't find instantiate_plugin in \"%s\"\n",
|
||||
path.Path());
|
||||
return B_BAD_TYPE;
|
||||
}
|
||||
|
||||
MediaPlugin *plugin = (*instantiate_plugin_func)();
|
||||
if (plugin == NULL) {
|
||||
printf("AddOnManager::RegisterAddOn(): instantiate_plugin in \"%s\" returned NULL\n",
|
||||
path.Path());
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
// ToDo: remove any old formats describing this add-on!!
|
||||
|
||||
ReaderPlugin *reader = dynamic_cast<ReaderPlugin *>(plugin);
|
||||
if (reader != NULL)
|
||||
RegisterReader(reader, ref);
|
||||
|
||||
DecoderPlugin *decoder = dynamic_cast<DecoderPlugin *>(plugin);
|
||||
if (decoder != NULL)
|
||||
RegisterDecoder(decoder, ref);
|
||||
|
||||
delete plugin;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
AddOnManager::RegisterAddOnsFor(BPath path)
|
||||
{
|
||||
path.Append("media/plugins");
|
||||
|
||||
BDirectory directory(path.Path());
|
||||
if (directory.InitCheck() != B_OK)
|
||||
return;
|
||||
|
||||
BEntry entry;
|
||||
while (directory.GetNextEntry(&entry) == B_OK)
|
||||
RegisterAddOn(entry);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
AddOnManager::RegisterAddOns()
|
||||
{
|
||||
const char *searchdir[] = {
|
||||
"/boot/home/config/add-ons/media/plugins",
|
||||
"/boot/beos/system/add-ons/media/plugins",
|
||||
"/boot/home/develop/openbeos/current/distro/x86.R1/beos/system/add-ons/media/plugins",
|
||||
NULL
|
||||
BPath path;
|
||||
|
||||
// user add-ons come first, so that they can lay over system
|
||||
// add-ons (add-ons are identified by name for registration)
|
||||
|
||||
const directory_which directories[] = {
|
||||
B_USER_ADDONS_DIRECTORY,
|
||||
B_COMMON_ADDONS_DIRECTORY,
|
||||
B_BEOS_ADDONS_DIRECTORY,
|
||||
};
|
||||
|
||||
for (int i = 0; searchdir[i]; i++) {
|
||||
BDirectory dir(searchdir[i]);
|
||||
BEntry e;
|
||||
while (B_OK == dir.GetNextEntry(&e)) {
|
||||
BPath p(&e);
|
||||
entry_ref ref;
|
||||
e.GetRef(&ref);
|
||||
|
||||
printf("AddOnManager: RegisterAddOns trying to load %s\n", p.Path());
|
||||
|
||||
image_id id;
|
||||
id = load_add_on(p.Path());
|
||||
if (id < 0)
|
||||
continue;
|
||||
|
||||
MediaPlugin *(*instantiate_plugin_func)();
|
||||
|
||||
if (get_image_symbol(id, "instantiate_plugin", B_SYMBOL_TYPE_TEXT, (void**)&instantiate_plugin_func) < B_OK) {
|
||||
printf("AddOnManager: Error, RegisterAddOns can't find instantiate_plugin in %s\n", p.Path());
|
||||
unload_add_on(id);
|
||||
continue;
|
||||
}
|
||||
|
||||
MediaPlugin *pl;
|
||||
|
||||
pl = (*instantiate_plugin_func)();
|
||||
if (pl == 0) {
|
||||
printf("AddOnManager: Error, RegisterAddOns instantiate_plugin in %s returned 0\n", p.Path());
|
||||
unload_add_on(id);
|
||||
continue;
|
||||
}
|
||||
|
||||
ReaderPlugin *rp = dynamic_cast<ReaderPlugin *>(pl);
|
||||
if (rp)
|
||||
RegisterReader(rp, ref);
|
||||
|
||||
DecoderPlugin *dp = dynamic_cast<DecoderPlugin *>(pl);
|
||||
if (dp)
|
||||
RegisterDecoder(dp, ref);
|
||||
|
||||
delete pl;
|
||||
unload_add_on(id);
|
||||
}
|
||||
for (uint32 i = 0; i < sizeof(directories) / sizeof(directory_which); i++) {
|
||||
if (find_directory(directories[i], &path) == B_OK)
|
||||
RegisterAddOnsFor(path);
|
||||
}
|
||||
|
||||
// ToDo: this is for our own convenience only, and should be removed
|
||||
// in the final release
|
||||
path.SetTo("/boot/home/develop/openbeos/current/distro/x86.R1/beos/system/add-ons");
|
||||
RegisterAddOnsFor(path);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
AddOnManager::RegisterReader(ReaderPlugin *reader, const entry_ref &ref)
|
||||
{
|
||||
bool already_found;
|
||||
BAutolock locker(fLock);
|
||||
|
||||
reader_info *pinfo;
|
||||
|
||||
fLocker->Lock();
|
||||
for (already_found = false, fReaderList->Rewind(); fReaderList->GetNext(&pinfo); )
|
||||
if (0 == strcmp(pinfo->ref.name, ref.name)) {
|
||||
already_found = true;
|
||||
break;
|
||||
for (fReaderList.Rewind(); fReaderList.GetNext(&pinfo);) {
|
||||
if (!strcmp(pinfo->ref.name, ref.name)) {
|
||||
// we already know this reader
|
||||
return;
|
||||
}
|
||||
fLocker->Unlock();
|
||||
if (already_found)
|
||||
return;
|
||||
}
|
||||
|
||||
printf("AddOnManager::RegisterReader, name %s\n", ref.name);
|
||||
|
||||
reader_info info;
|
||||
info.ref = ref;
|
||||
|
||||
if (B_OK != reader->RegisterPlugin()) {
|
||||
printf("AddOnManager::RegisterReader(): reader->RegisterPlugin() failed!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
fLocker->Lock();
|
||||
fReaderList->Insert(info);
|
||||
fLocker->Unlock();
|
||||
fReaderList.Insert(info);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
AddOnManager::RegisterDecoder(DecoderPlugin *decoder, const entry_ref &ref)
|
||||
{
|
||||
bool already_found;
|
||||
BAutolock locker(fLock);
|
||||
|
||||
decoder_info *pinfo;
|
||||
|
||||
fLocker->Lock();
|
||||
for (already_found = false, fDecoderList->Rewind(); fDecoderList->GetNext(&pinfo); )
|
||||
if (0 == strcmp(pinfo->ref.name, ref.name)) {
|
||||
already_found = true;
|
||||
break;
|
||||
for (fDecoderList.Rewind(); fDecoderList.GetNext(&pinfo);) {
|
||||
if (!strcmp(pinfo->ref.name, ref.name)) {
|
||||
// we already know this decoder
|
||||
return;
|
||||
}
|
||||
fLocker->Unlock();
|
||||
if (already_found)
|
||||
return;
|
||||
}
|
||||
|
||||
printf("AddOnManager::RegisterDecoder, name %s\n", ref.name);
|
||||
|
||||
decoder->Setup((void*)&_PublishDecoder);
|
||||
|
||||
|
||||
decoder_info info;
|
||||
info.ref = ref;
|
||||
fDecoderInfo = &info;
|
||||
|
||||
if (B_OK != decoder->RegisterPlugin())
|
||||
fCurrentDecoder = &info;
|
||||
BPrivate::media::_gMakeFormatHook = register_decoder;
|
||||
|
||||
if (decoder->RegisterDecoder() != B_OK) {
|
||||
printf("AddOnManager::RegisterDecoder(): decoder->RegisterDecoder() failed!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
fLocker->Lock();
|
||||
fDecoderList->Insert(info);
|
||||
fLocker->Unlock();
|
||||
fDecoderInfo = 0;
|
||||
fDecoderList.Insert(info);
|
||||
fCurrentDecoder = NULL;
|
||||
BPrivate::media::_gMakeFormatHook = NULL;
|
||||
}
|
||||
|
||||
status_t
|
||||
AddOnManager::PublishDecoderCallback(DecoderPlugin *decoderplugin,
|
||||
const char *meta_description,
|
||||
const char *short_name,
|
||||
const char *pretty_name,
|
||||
const char *default_mapping /* = 0 */)
|
||||
{
|
||||
|
||||
printf("AddOnManager::PublishDecoderCallback: meta_description \"%s\", short_name \"%s\", pretty_name \"%s\", default_mapping \"%s\"\n",
|
||||
meta_description, short_name, pretty_name, default_mapping);
|
||||
|
||||
media_meta_description meta_desc;
|
||||
snprintf(meta_desc.description, sizeof(meta_desc), "%s", meta_description);
|
||||
|
||||
fDecoderInfo->meta_desc.Insert(meta_desc);
|
||||
|
||||
status_t
|
||||
AddOnManager::MakeEncoderFormats(const media_format_description *descriptions,
|
||||
int32 descriptionCount, media_format *format, uint32 flags)
|
||||
{
|
||||
//ASSERT(fCurrentEncoder != NULL);
|
||||
|
||||
status_t status = gFormatManager->RegisterEncoder(descriptions,
|
||||
descriptionCount, format, flags);
|
||||
if (status < B_OK)
|
||||
return status;
|
||||
|
||||
//fCurrentEncoder->format = *format;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
//typedef status_t *(*publish_func)(DecoderPlugin *, const char *, const char *, const char *, const char *);
|
||||
status_t
|
||||
_PublishDecoder(DecoderPlugin *decoderplugin,
|
||||
const char *meta_description,
|
||||
const char *short_name,
|
||||
const char *pretty_name,
|
||||
const char *default_mapping /* = 0 */)
|
||||
status_t
|
||||
AddOnManager::MakeDecoderFormats(const media_format_description *descriptions,
|
||||
int32 descriptionCount, media_format *format, uint32 flags)
|
||||
{
|
||||
return gAddOnManager->PublishDecoderCallback(decoderplugin,
|
||||
meta_description,
|
||||
short_name,
|
||||
pretty_name,
|
||||
default_mapping);
|
||||
ASSERT(fCurrentDecoder != NULL);
|
||||
|
||||
status_t status = gFormatManager->RegisterDecoder(descriptions,
|
||||
descriptionCount, format, flags);
|
||||
if (status < B_OK)
|
||||
return status;
|
||||
|
||||
fCurrentDecoder->formats.Insert(*format);
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
bool
|
||||
operator==(const media_meta_description & a, const media_meta_description & b)
|
||||
{
|
||||
return 0 == strcmp(a.description, b.description);
|
||||
}
|
||||
|
@ -1,72 +1,70 @@
|
||||
/*
|
||||
** Copyright 2004, the OpenBeOS project. All rights reserved.
|
||||
** Distributed under the terms of the OpenBeOS License.
|
||||
**
|
||||
** Authors: Marcus Overhagen, Axel Dörfler
|
||||
*/
|
||||
#ifndef _ADD_ON_MANAGER_H
|
||||
#define _ADD_ON_MANAGER_H
|
||||
|
||||
// Manager for codec add-ons (reader, writer, encoder, decoder)
|
||||
// BMediaAddOn are handled in the NodeManager
|
||||
|
||||
#include "TList.h"
|
||||
#include "ReaderPlugin.h"
|
||||
#include "DecoderPlugin.h"
|
||||
#include "DataExchange.h"
|
||||
|
||||
class AddOnManager
|
||||
{
|
||||
public:
|
||||
AddOnManager();
|
||||
~AddOnManager();
|
||||
|
||||
void LoadState();
|
||||
void SaveState();
|
||||
|
||||
status_t GetDecoderForFormat(xfer_entry_ref *out_ref,
|
||||
const media_format &in_format);
|
||||
|
||||
status_t GetReaders(xfer_entry_ref *out_res, int32 *out_count, int32 max_count);
|
||||
|
||||
status_t PublishDecoderCallback(DecoderPlugin *decoderplugin,
|
||||
const char *meta_description,
|
||||
const char *short_name,
|
||||
const char *pretty_name,
|
||||
const char *default_mapping /* = 0 */);
|
||||
|
||||
private:
|
||||
void RegisterAddOns();
|
||||
void RegisterReader(ReaderPlugin *reader, const entry_ref &ref);
|
||||
void RegisterDecoder(DecoderPlugin *decoder, const entry_ref &ref);
|
||||
#include "TList.h"
|
||||
|
||||
|
||||
|
||||
private:
|
||||
struct reader_info
|
||||
{
|
||||
entry_ref ref;
|
||||
};
|
||||
struct writer_info
|
||||
{
|
||||
entry_ref ref;
|
||||
};
|
||||
struct decoder_info
|
||||
{
|
||||
entry_ref ref;
|
||||
List<media_meta_description> meta_desc;
|
||||
};
|
||||
struct encoder_info
|
||||
{
|
||||
entry_ref ref;
|
||||
};
|
||||
class AddOnManager {
|
||||
public:
|
||||
AddOnManager();
|
||||
~AddOnManager();
|
||||
|
||||
BLocker *fLocker;
|
||||
List<reader_info> *fReaderList;
|
||||
List<writer_info> *fWriterList;
|
||||
List<decoder_info> *fDecoderList;
|
||||
List<encoder_info> *fEncoderList;
|
||||
void LoadState();
|
||||
void SaveState();
|
||||
|
||||
reader_info *fReaderInfo;
|
||||
writer_info *fWriterInfo;
|
||||
decoder_info *fDecoderInfo;
|
||||
encoder_info *fEncoderInfo;
|
||||
status_t GetDecoderForFormat(xfer_entry_ref *out_ref,
|
||||
const media_format &in_format);
|
||||
|
||||
status_t GetReaders(xfer_entry_ref *out_res, int32 *out_count,
|
||||
int32 max_count);
|
||||
|
||||
status_t MakeEncoderFormats(const media_format_description *descriptions,
|
||||
int32 descriptionCount, media_format *format, uint32 flags);
|
||||
status_t MakeDecoderFormats(const media_format_description *descriptions,
|
||||
int32 descriptionCount, media_format *format, uint32 flags);
|
||||
|
||||
private:
|
||||
status_t RegisterAddOn(BEntry &entry);
|
||||
void RegisterAddOnsFor(BPath path);
|
||||
void RegisterAddOns();
|
||||
|
||||
void RegisterReader(ReaderPlugin *reader, const entry_ref &ref);
|
||||
void RegisterDecoder(DecoderPlugin *decoder, const entry_ref &ref);
|
||||
|
||||
private:
|
||||
struct reader_info {
|
||||
entry_ref ref;
|
||||
};
|
||||
struct writer_info {
|
||||
entry_ref ref;
|
||||
};
|
||||
struct decoder_info {
|
||||
entry_ref ref;
|
||||
List<media_format> formats;
|
||||
};
|
||||
struct encoder_info {
|
||||
entry_ref ref;
|
||||
};
|
||||
|
||||
BLocker fLock;
|
||||
List<reader_info> fReaderList;
|
||||
List<writer_info> fWriterList;
|
||||
List<decoder_info> fDecoderList;
|
||||
List<encoder_info> fEncoderList;
|
||||
|
||||
decoder_info *fCurrentDecoder;
|
||||
};
|
||||
|
||||
|
||||
#endif // _ADD_ON_MANAGER_H
|
||||
|
Loading…
x
Reference in New Issue
Block a user