Urpdate AddOnManager and FormatManager for Media Kit

* These classes were moved from Media Server, making the use of ports
and messages to communicate with the app irrelevant.
* Split in a separate commit to help git keep track of moved files.

Fixes #4893.
This commit is contained in:
Adrien Destugues 2014-04-02 09:41:09 +02:00
parent 2feaa37f24
commit bf3b475c38
5 changed files with 98 additions and 226 deletions

View File

@ -22,13 +22,8 @@
#include <image.h>
#include <Path.h>
#include <safemode_defs.h>
#include <syscalls.h>
#include "debug.h"
#include "media_server.h"
#include "FormatManager.h"
#include "MetaFormat.h"
@ -65,38 +60,28 @@ AddOnManager::AddOnManager()
:
fLock("add-on manager"),
fNextWriterFormatFamilyID(0),
fNextEncoderCodecInfoID(0),
fAddOnMonitorHandler(NULL),
fAddOnMonitor(NULL)
fNextEncoderCodecInfoID(0)
{
}
AddOnManager::~AddOnManager()
{
if (fAddOnMonitor != NULL && fAddOnMonitor->Lock()) {
fAddOnMonitor->RemoveHandler(fAddOnMonitorHandler);
delete fAddOnMonitorHandler;
fAddOnMonitor->Quit();
}
}
void
AddOnManager::LoadState()
{
_RegisterAddOns();
}
AddOnManager AddOnManager::sInstance;
void
AddOnManager::SaveState()
/* static */ AddOnManager*
AddOnManager::GetInstance()
{
return &sInstance;
}
status_t
AddOnManager::GetDecoderForFormat(xfer_entry_ref* _decoderRef,
AddOnManager::GetDecoderForFormat(entry_ref* _decoderRef,
const media_format& format)
{
if ((format.type == B_MEDIA_ENCODED_VIDEO
@ -109,6 +94,7 @@ AddOnManager::GetDecoderForFormat(xfer_entry_ref* _decoderRef,
return B_MEDIA_BAD_FORMAT;
BAutolock locker(fLock);
_RegisterAddOns();
printf("AddOnManager::GetDecoderForFormat: searching decoder for encoding "
"%" B_PRIu32 "\n", format.Encoding());
@ -140,10 +126,11 @@ AddOnManager::GetDecoderForFormat(xfer_entry_ref* _decoderRef,
status_t
AddOnManager::GetReaders(xfer_entry_ref* outRefs, int32* outCount,
AddOnManager::GetReaders(entry_ref* outRefs, int32* outCount,
int32 maxCount)
{
BAutolock locker(fLock);
_RegisterAddOns();
*outCount = 0;
@ -170,9 +157,10 @@ AddOnManager::GetReaders(xfer_entry_ref* outRefs, int32* outCount,
status_t
AddOnManager::GetEncoder(xfer_entry_ref* _encoderRef, int32 id)
AddOnManager::GetEncoder(entry_ref* _encoderRef, int32 id)
{
BAutolock locker(fLock);
_RegisterAddOns();
encoder_info* info;
for (fEncoderList.Rewind(); fEncoderList.GetNext(&info);) {
@ -194,9 +182,10 @@ AddOnManager::GetEncoder(xfer_entry_ref* _encoderRef, int32 id)
status_t
AddOnManager::GetWriter(xfer_entry_ref* _ref, uint32 internalID)
AddOnManager::GetWriter(entry_ref* _ref, uint32 internalID)
{
BAutolock locker(fLock);
_RegisterAddOns();
writer_info* info;
for (fWriterList.Rewind(); fWriterList.GetNext(&info);) {
@ -217,6 +206,7 @@ status_t
AddOnManager::GetFileFormat(media_file_format* _fileFormat, int32 cookie)
{
BAutolock locker(fLock);
_RegisterAddOns();
media_file_format* fileFormat;
if (fWriterFileFormats.Get(cookie, &fileFormat)) {
@ -234,6 +224,7 @@ AddOnManager::GetCodecInfo(media_codec_info* _codecInfo,
media_format* _inputFormat, media_format* _outputFormat, int32 cookie)
{
BAutolock locker(fLock);
_RegisterAddOns();
encoder_info* info;
if (fEncoderList.Get(cookie, &info)) {
@ -254,56 +245,10 @@ AddOnManager::GetCodecInfo(media_codec_info* _codecInfo,
void
AddOnManager::_RegisterAddOns()
{
class CodecHandler : public AddOnMonitorHandler {
private:
AddOnManager* fManager;
public:
CodecHandler(AddOnManager* manager)
{
fManager = manager;
}
virtual void AddOnCreated(const add_on_entry_info* entryInfo)
{
}
virtual void AddOnEnabled(const add_on_entry_info* entryInfo)
{
entry_ref ref;
make_entry_ref(entryInfo->dir_nref.device,
entryInfo->dir_nref.node, entryInfo->name, &ref);
fManager->_RegisterAddOn(ref);
}
virtual void AddOnDisabled(const add_on_entry_info* entryInfo)
{
entry_ref ref;
make_entry_ref(entryInfo->dir_nref.device,
entryInfo->dir_nref.node, entryInfo->name, &ref);
fManager->_UnregisterAddOn(ref);
}
virtual void AddOnRemoved(const add_on_entry_info* entryInfo)
{
}
};
fAddOnMonitorHandler = new CodecHandler(this);
fAddOnMonitor = new AddOnMonitor(fAddOnMonitorHandler);
// get safemode option for disabling user add-ons
char buffer[16];
size_t size = sizeof(buffer);
bool disableUserAddOns = _kern_get_safemode_option(
B_SAFEMODE_DISABLE_USER_ADD_ONS, buffer, &size) == B_OK
&& (!strcasecmp(buffer, "true")
|| !strcasecmp(buffer, "yes")
|| !strcasecmp(buffer, "on")
|| !strcasecmp(buffer, "enabled")
|| !strcmp(buffer, "1"));
// Check if add-ons are already registered.
if(!fReaderList.IsEmpty() || !fWriterList.IsEmpty()
|| !fDecoderList.IsEmpty() || !fEncoderList.IsEmpty())
return;
char** directories = NULL;
size_t directoryCount = 0;
@ -311,22 +256,16 @@ AddOnManager::_RegisterAddOns()
if (find_paths_etc(get_architecture(), B_FIND_PATH_ADD_ONS_DIRECTORY,
"media/plugins", B_FIND_PATH_EXISTING_ONLY, &directories,
&directoryCount) != B_OK) {
printf("AddOnManager::RegisterAddOns: failed to locate plugins\n");
return;
}
node_ref nref;
BDirectory directory;
BPath path;
for (uint i = 0; i < directoryCount; i++) {
if (disableUserAddOns && i <= 1)
continue;
if (directory.SetTo(directories[i]) == B_OK
&& directory.GetNodeRef(&nref) == B_OK) {
fAddOnMonitorHandler->AddDirectory(&nref);
// NOTE: This may already start registering add-ons in the
// AddOnMonitor looper thread after the call returns!
BDirectory directory;
if (directory.SetTo(directories[i]) == B_OK) {
entry_ref ref;
while(directory.GetNextRef(&ref) == B_OK)
_RegisterAddOn(ref);
}
}
}
@ -410,7 +349,6 @@ printf("removing decoder '%s'\n", decoderInfo->ref.name);
media_format* format;
for (decoderInfo->formats.Rewind();
decoderInfo->formats.GetNext(&format);) {
gFormatManager->RemoveFormat(*format);
}
fDecoderList.RemoveCurrent();
break;
@ -591,7 +529,7 @@ AddOnManager::_RegisterEncoder(EncoderPlugin* plugin, const entry_ref& ref)
bool
AddOnManager::_FindDecoder(const media_format& format, const BPath& path,
xfer_entry_ref* _decoderRef)
entry_ref* _decoderRef)
{
node_ref nref;
BDirectory directory;
@ -624,7 +562,7 @@ AddOnManager::_FindDecoder(const media_format& format, const BPath& path,
void
AddOnManager::_GetReaders(const BPath& path, xfer_entry_ref* outRefs,
AddOnManager::_GetReaders(const BPath& path, entry_ref* outRefs,
int32* outCount, int32 maxCount)
{
node_ref nref;

View File

@ -19,8 +19,6 @@
#include "DataExchange.h"
#include "TList.h"
#include "AddOnMonitor.h"
#include "AddOnMonitorHandler.h"
#include "DecoderPlugin.h"
#include "EncoderPlugin.h"
#include "ReaderPlugin.h"
@ -32,18 +30,17 @@ public:
AddOnManager();
~AddOnManager();
void LoadState();
void SaveState();
static AddOnManager* GetInstance();
status_t GetDecoderForFormat(xfer_entry_ref* _ref,
status_t GetDecoderForFormat(entry_ref* _ref,
const media_format& format);
status_t GetReaders(xfer_entry_ref* _ref,
status_t GetReaders(entry_ref* _ref,
int32* _count, int32 maxCount);
status_t GetEncoder(xfer_entry_ref* _ref, int32 id);
status_t GetEncoder(entry_ref* _ref, int32 id);
status_t GetWriter(xfer_entry_ref* _ref,
status_t GetWriter(entry_ref* _ref,
uint32 internalID);
status_t GetFileFormat(media_file_format* _fileFormat,
@ -71,9 +68,9 @@ private:
bool _FindDecoder(const media_format& format,
const BPath& path,
xfer_entry_ref* _decoderRef);
entry_ref* _decoderRef);
void _GetReaders(const BPath& path,
xfer_entry_ref* outRefs, int32* outCount,
entry_ref* outRefs, int32* outCount,
int32 maxCount);
private:
@ -108,8 +105,7 @@ private:
uint32 fNextWriterFormatFamilyID;
uint32 fNextEncoderCodecInfoID;
AddOnMonitorHandler* fAddOnMonitorHandler;
AddOnMonitor* fAddOnMonitor;
static AddOnManager sInstance;
};
#endif // _ADD_ON_MANAGER_H

View File

@ -134,41 +134,24 @@ FormatManager::~FormatManager()
}
void
FormatManager::LoadState()
{
}
void
FormatManager::SaveState()
{
}
/*! This method is called when BMediaFormats asks for any updates
made to our format list.
If there were any changes since the last time, the whole
list will be sent back.
*/
void
FormatManager::GetFormats(BMessage& message)
FormatManager::GetFormats(bigtime_t lastUpdate, BMessage& reply)
{
BAutolock locker(fLock);
bigtime_t lastUpdate;
if (message.FindInt64("last_timestamp", &lastUpdate) == B_OK
&& lastUpdate >= fLastUpdate) {
if (lastUpdate >= fLastUpdate) {
// There weren't any changes since last time.
BMessage reply;
reply.AddBool("need_update", false);
message.SendReply(&reply, (BHandler*)NULL, TIMEOUT);
return;
}
// Add all meta formats to the list
BMessage reply;
reply.AddBool("need_update", true);
reply.AddInt64("timestamp", system_time());
@ -180,30 +163,15 @@ FormatManager::GetFormats(BMessage& message)
reply.AddData("formats", MEDIA_META_FORMAT_TYPE, format,
sizeof(meta_format));
}
message.SendReply(&reply, (BHandler*)NULL, TIMEOUT);
}
void
FormatManager::MakeFormatFor(BMessage& message)
status_t
FormatManager::MakeFormatFor(const media_format_description* descriptions,
int32 descriptionCount, media_format& format, uint32 flags, void* _reserved)
{
BAutolock locker(fLock);
media_format format;
const void* data;
ssize_t size;
if (message.FindData("format", B_RAW_TYPE, 0, &data, &size) != B_OK
|| size != sizeof(format)) {
// Couldn't get the format
BMessage reply;
reply.AddInt32("result", B_ERROR);
message.SendReply(&reply, (BHandler*)NULL, TIMEOUT);
return;
}
// Copy the BMessage's data into our format
format = *(media_format*)data;
int codec = fNextCodecID;
switch (format.type) {
case B_MEDIA_RAW_AUDIO:
@ -246,22 +214,16 @@ FormatManager::MakeFormatFor(BMessage& message)
break;
default:
// nothing to do
BMessage reply;
reply.AddInt32("result", B_OK);
reply.AddData("format", B_RAW_TYPE, &format, sizeof(format));
message.SendReply(&reply, (BHandler*)NULL, TIMEOUT);
return;
return B_OK;
}
fLastUpdate = system_time();
status_t result = B_OK;
// TODO: Support "flags" (B_SET_DEFAULT, B_EXCLUSIVE, B_NO_MERGE)!
int32 i = 0;
while (message.FindData("description", B_RAW_TYPE, i++, &data, &size)
== B_OK && size == sizeof(media_format_description)) {
meta_format* metaFormat
= new(std::nothrow) meta_format(*(media_format_description*)data,
format, codec);
for(i = 0; i < descriptionCount; i++) {
meta_format* metaFormat = new(std::nothrow) meta_format(
descriptions[i], format, codec);
if (metaFormat == NULL
|| !fList.BinaryInsert(metaFormat, meta_format::Compare)) {
delete metaFormat;
@ -270,11 +232,7 @@ FormatManager::MakeFormatFor(BMessage& message)
}
}
BMessage reply;
reply.AddInt32("result", result);
if (result == B_OK)
reply.AddData("format", B_RAW_TYPE, &format, sizeof(format));
message.SendReply(&reply, (BHandler*)NULL, TIMEOUT);
return B_OK;
}

View File

@ -21,11 +21,12 @@ public:
FormatManager();
~FormatManager();
void LoadState();
void SaveState();
void GetFormats(BMessage& message);
void MakeFormatFor(BMessage& message);
void GetFormats(bigtime_t lastUpdate, BMessage& reply);
status_t MakeFormatFor(
const media_format_description* descriptions,
int32 descriptionCount,
media_format& format, uint32 flags,
void* _reserved);
void RemoveFormat(const media_format& format);
private:

View File

@ -8,7 +8,9 @@
*/
#include "AddOnManager.h"
#include "DataExchange.h"
#include "FormatManager.h"
#include "MetaFormat.h"
#include "debug.h"
@ -40,29 +42,32 @@ get_next_encoder(int32* cookie, const media_file_format* fileFormat,
return B_BAD_VALUE;
while (true) {
server_get_codec_info_request request;
request.cookie = *cookie;
server_get_codec_info_reply reply;
status_t ret = QueryServer(SERVER_GET_CODEC_INFO_FOR_COOKIE, &request,
sizeof(request), &reply, sizeof(reply));
media_codec_info codec_info;
media_format_family format_family;
media_format input_format;
media_format output_format;
status_t ret = AddOnManager::GetInstance()->GetCodecInfo(&codec_info,
&format_family, &input_format, &output_format, *cookie);
if (ret != B_OK)
return ret;
*cookie = *cookie + 1;
if (fileFormat != NULL && reply.format_family != B_ANY_FORMAT_FAMILY
if (fileFormat != NULL && format_family != B_ANY_FORMAT_FAMILY
&& fileFormat->family != B_ANY_FORMAT_FAMILY
&& fileFormat->family != reply.format_family) {
&& fileFormat->family != format_family) {
continue;
}
if (!reply.input_format.Matches(inputFormat))
if (!input_format.Matches(inputFormat))
continue;
if (_outputFormat != NULL)
*_outputFormat = reply.output_format;
*_outputFormat = output_format;
*_codecInfo = reply.codec_info;
*_codecInfo = codec_info;
break;
}
@ -86,24 +91,27 @@ get_next_encoder(int32* cookie, const media_file_format* fileFormat,
}
while (true) {
server_get_codec_info_request request;
request.cookie = *cookie;
server_get_codec_info_reply reply;
status_t ret = QueryServer(SERVER_GET_CODEC_INFO_FOR_COOKIE, &request,
sizeof(request), &reply, sizeof(reply));
media_codec_info codec_info;
media_format_family format_family;
media_format input_format;
media_format output_format;
status_t ret = AddOnManager::GetInstance()->GetCodecInfo(&codec_info,
&format_family, &input_format, &output_format, *cookie);
if (ret != B_OK)
return ret;
*cookie = *cookie + 1;
if (fileFormat != NULL && reply.format_family != B_ANY_FORMAT_FAMILY
if (fileFormat != NULL && format_family != B_ANY_FORMAT_FAMILY
&& fileFormat->family != B_ANY_FORMAT_FAMILY
&& fileFormat->family != reply.format_family) {
&& fileFormat->family != format_family) {
continue;
}
if (!reply.input_format.Matches(inputFormat)
|| !reply.output_format.Matches(outputFormat)) {
if (!input_format.Matches(inputFormat)
|| !output_format.Matches(outputFormat)) {
continue;
}
@ -113,11 +121,11 @@ get_next_encoder(int32* cookie, const media_file_format* fileFormat,
// possible, we actually have to instantiate an Encoder here and
// ask it to specifiy the format.
if (_acceptedInputFormat != NULL)
*_acceptedInputFormat = reply.input_format;
*_acceptedInputFormat = input_format;
if (_acceptedOutputFormat != NULL)
*_acceptedOutputFormat = reply.output_format;
*_acceptedOutputFormat = output_format;
*_codecInfo = reply.codec_info;
*_codecInfo = codec_info;
break;
}
@ -131,16 +139,18 @@ get_next_encoder(int32* cookie, media_codec_info* _codecInfo)
if (cookie == NULL || _codecInfo == NULL)
return B_BAD_VALUE;
server_get_codec_info_request request;
request.cookie = *cookie;
server_get_codec_info_reply reply;
status_t ret = QueryServer(SERVER_GET_CODEC_INFO_FOR_COOKIE, &request,
sizeof(request), &reply, sizeof(reply));
media_codec_info codec_info;
media_format_family format_family;
media_format input_format;
media_format output_format;
status_t ret = AddOnManager::GetInstance()->GetCodecInfo(&codec_info,
&format_family, &input_format, &output_format, *cookie);
if (ret != B_OK)
return ret;
*cookie = *cookie + 1;
*_codecInfo = reply.codec_info;
*_codecInfo = codec_info;
return B_OK;
}
@ -350,22 +360,18 @@ meta_format::Compare(const meta_format* a, const meta_format* b)
* The formats lock has to be hold when you call this function.
*/
FormatManager* gFormatManager = NULL;
static status_t
update_media_formats()
{
if (!sLock.IsLocked())
return B_NOT_ALLOWED;
BMessage request(MEDIA_SERVER_GET_FORMATS);
request.AddInt64("last_timestamp", sLastFormatsUpdate);
BMessage reply;
status_t status = QueryServer(request, reply);
if (status < B_OK) {
ERROR("BMediaFormats: Could not update formats: %s\n",
strerror(status));
return status;
}
if (gFormatManager == NULL)
gFormatManager = new FormatManager;
gFormatManager->GetFormats(sLastFormatsUpdate, reply);
// do we need an update at all?
bool needUpdate;
@ -616,40 +622,13 @@ BMediaFormats::MakeFormatFor(const media_format_description* descriptions,
int32 descriptionCount, media_format* format, uint32 flags,
void* _reserved)
{
BMessage request(MEDIA_SERVER_MAKE_FORMAT_FOR);
for (int32 i = 0 ; i < descriptionCount ; i++) {
request.AddData("description", B_RAW_TYPE, &descriptions[i],
sizeof(descriptions[i]));
}
request.AddData("format", B_RAW_TYPE, format, sizeof(*format));
request.AddData("flags", B_UINT32_TYPE, &flags, sizeof(flags));
request.AddPointer("_reserved", _reserved);
if (gFormatManager == NULL)
gFormatManager = new FormatManager;
BMessage reply;
status_t status = QueryServer(request, reply);
if (status != B_OK) {
ERROR("BMediaFormats: Could not make a format: %s\n", strerror(status));
return status;
}
status_t status = gFormatManager->MakeFormatFor(descriptions,
descriptionCount, *format, flags, _reserved);
// check the status
if (reply.FindInt32("result", &status) < B_OK)
return B_ERROR;
if (status != B_OK)
return status;
// get the format
const void* data;
ssize_t size;
if (reply.FindData("format", B_RAW_TYPE, 0, &data, &size) != B_OK)
return B_ERROR;
if (size != sizeof(*format))
return B_ERROR;
// copy the BMessage's data into our format
*format = *(media_format*)data;
return B_OK;
return status;
}