The media_server supports updates to add-ons now.
It unloads any media_format mappings when an add-on becomes unavailable, and consequently reloads the supported formats and similar when the same add-on becomes available again. Previously it would only load previously unkown add-ons by node-monitor events (unkown name). What also works is that user add-ons shadow/hide system add-ons when installed, and the system add-on will become effective immediately when removing the user add-on again. One thing to note is that certain IDs will not stay consistent. I am not aware of an application for which it could be a problem, most should rememeber codecs by name. In any case, I only tested add-on events a lot, and not so much the effects of unstable media_file_format IDs, so it's possible there are regressions, though only when installing new versions of add-ons, which previously mostly required a media_server restart anyway. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@38282 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -49,7 +49,7 @@ public:
|
|||||||
unload_add_on(fImage);
|
unload_add_on(fImage);
|
||||||
}
|
}
|
||||||
|
|
||||||
status_t InitCheck() const { return fImage; }
|
status_t InitCheck() const { return fImage >= 0 ? B_OK : fImage; }
|
||||||
image_id Image() const { return fImage; }
|
image_id Image() const { return fImage; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -64,13 +64,20 @@ AddOnManager::AddOnManager()
|
|||||||
:
|
:
|
||||||
fLock("add-on manager"),
|
fLock("add-on manager"),
|
||||||
fNextWriterFormatFamilyID(0),
|
fNextWriterFormatFamilyID(0),
|
||||||
fNextEncoderCodecInfoID(0)
|
fNextEncoderCodecInfoID(0),
|
||||||
|
fAddOnMonitorHandler(NULL),
|
||||||
|
fAddOnMonitor(NULL)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
AddOnManager::~AddOnManager()
|
AddOnManager::~AddOnManager()
|
||||||
{
|
{
|
||||||
|
if (fAddOnMonitor != NULL && fAddOnMonitor->Lock()) {
|
||||||
|
fAddOnMonitor->RemoveHandler(fAddOnMonitorHandler);
|
||||||
|
delete fAddOnMonitorHandler;
|
||||||
|
fAddOnMonitor->Quit();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -223,6 +230,89 @@ AddOnManager::GetCodecInfo(media_codec_info* _codecInfo,
|
|||||||
// #pragma mark -
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
|
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);
|
||||||
|
BEntry entry(&ref, false);
|
||||||
|
if (entry.InitCheck() == B_OK)
|
||||||
|
fManager->_RegisterAddOn(entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
BEntry entry(&ref, false);
|
||||||
|
if (entry.InitCheck() == B_OK)
|
||||||
|
fManager->_UnregisterAddOn(entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void AddOnRemoved(const add_on_entry_info* entryInfo)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const directory_which directories[] = {
|
||||||
|
B_USER_ADDONS_DIRECTORY,
|
||||||
|
B_COMMON_ADDONS_DIRECTORY,
|
||||||
|
B_BEOS_ADDONS_DIRECTORY,
|
||||||
|
};
|
||||||
|
|
||||||
|
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"));
|
||||||
|
|
||||||
|
node_ref nref;
|
||||||
|
BDirectory directory;
|
||||||
|
BPath path;
|
||||||
|
for (uint i = 0 ; i < sizeof(directories) / sizeof(directory_which) ; i++) {
|
||||||
|
if (disableUserAddOns && i <= 1)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (find_directory(directories[i], &path) == B_OK
|
||||||
|
&& path.Append("media/plugins") == B_OK
|
||||||
|
&& directory.SetTo(path.Path()) == 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!
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
AddOnManager::_RegisterAddOn(BEntry& entry)
|
AddOnManager::_RegisterAddOn(BEntry& entry)
|
||||||
{
|
{
|
||||||
@@ -237,7 +327,7 @@ AddOnManager::_RegisterAddOn(BEntry& entry)
|
|||||||
path.Path());
|
path.Path());
|
||||||
|
|
||||||
ImageLoader loader(path);
|
ImageLoader loader(path);
|
||||||
if ((status = loader.InitCheck()) < B_OK)
|
if ((status = loader.InitCheck()) != B_OK)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
MediaPlugin* (*instantiate_plugin_func)();
|
MediaPlugin* (*instantiate_plugin_func)();
|
||||||
@@ -280,78 +370,68 @@ AddOnManager::_RegisterAddOn(BEntry& entry)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
status_t
|
||||||
AddOnManager::_RegisterAddOns()
|
AddOnManager::_UnregisterAddOn(BEntry& entry)
|
||||||
{
|
{
|
||||||
class CodecHandler : public AddOnMonitorHandler {
|
BPath path(&entry);
|
||||||
private:
|
printf("AddOnManager::_UnregisterAddOn(): trying to unload \"%s\"\n",
|
||||||
AddOnManager* fManager;
|
path.Path());
|
||||||
|
|
||||||
public:
|
BAutolock locker(fLock);
|
||||||
CodecHandler(AddOnManager* manager)
|
|
||||||
{
|
|
||||||
fManager = manager;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void AddOnCreated(const add_on_entry_info* entryInfo)
|
entry_ref ref;
|
||||||
{
|
status_t status = entry.GetRef(&ref);
|
||||||
}
|
if (status != B_OK)
|
||||||
|
return status;
|
||||||
|
|
||||||
virtual void AddOnEnabled(const add_on_entry_info* entryInfo)
|
// Remove any Readers exported by this add-on
|
||||||
{
|
reader_info* readerInfo;
|
||||||
entry_ref ref;
|
for (fReaderList.Rewind(); fReaderList.GetNext(&readerInfo);) {
|
||||||
make_entry_ref(entryInfo->dir_nref.device,
|
if (readerInfo->ref == ref) {
|
||||||
entryInfo->dir_nref.node, entryInfo->name, &ref);
|
printf("removing reader '%s'\n", readerInfo->ref.name);
|
||||||
BEntry entry(&ref, false);
|
fReaderList.RemoveCurrent();
|
||||||
if (entry.InitCheck() == B_OK)
|
break;
|
||||||
fManager->_RegisterAddOn(entry);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void AddOnDisabled(const add_on_entry_info* entryInfo)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void AddOnRemoved(const add_on_entry_info* entryInfo)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const directory_which directories[] = {
|
|
||||||
B_USER_ADDONS_DIRECTORY,
|
|
||||||
B_COMMON_ADDONS_DIRECTORY,
|
|
||||||
B_BEOS_ADDONS_DIRECTORY,
|
|
||||||
};
|
|
||||||
|
|
||||||
fHandler = new CodecHandler(this);
|
|
||||||
fAddOnMonitor = new AddOnMonitor(fHandler);
|
|
||||||
|
|
||||||
// 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"));
|
|
||||||
|
|
||||||
node_ref nref;
|
|
||||||
BDirectory directory;
|
|
||||||
BPath path;
|
|
||||||
for (uint i = 0 ; i < sizeof(directories) / sizeof(directory_which) ; i++) {
|
|
||||||
if (disableUserAddOns && i <= 1)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (find_directory(directories[i], &path) == B_OK
|
|
||||||
&& path.Append("media/plugins") == B_OK
|
|
||||||
&& directory.SetTo(path.Path()) == B_OK
|
|
||||||
&& directory.GetNodeRef(&nref) == B_OK) {
|
|
||||||
fHandler->AddDirectory(&nref);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Remove any Decoders exported by this add-on
|
||||||
|
decoder_info* decoderInfo;
|
||||||
|
for (fDecoderList.Rewind(); fDecoderList.GetNext(&decoderInfo);) {
|
||||||
|
if (decoderInfo->ref == ref) {
|
||||||
|
printf("removing decoder '%s'\n", decoderInfo->ref.name);
|
||||||
|
fDecoderList.RemoveCurrent();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove any Writers exported by this add-on
|
||||||
|
writer_info* writerInfo;
|
||||||
|
for (fWriterList.Rewind(); fWriterList.GetNext(&writerInfo);) {
|
||||||
|
if (writerInfo->ref == ref) {
|
||||||
|
// Remove any formats from this writer
|
||||||
|
media_file_format* writerFormat;
|
||||||
|
for (fWriterFileFormats.Rewind();
|
||||||
|
fWriterFileFormats.GetNext(&writerFormat);) {
|
||||||
|
if (writerFormat->id.internal_id == writerInfo->internalID)
|
||||||
|
fWriterFileFormats.RemoveCurrent();
|
||||||
|
}
|
||||||
|
printf("removing writer '%s'\n", writerInfo->ref.name);
|
||||||
|
fWriterList.RemoveCurrent();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
encoder_info* encoderInfo;
|
||||||
|
for (fEncoderList.Rewind(); fEncoderList.GetNext(&encoderInfo);) {
|
||||||
|
if (encoderInfo->ref == ref) {
|
||||||
|
printf("removing encoder '%s', id %lu\n", encoderInfo->ref.name,
|
||||||
|
encoderInfo->internalID);
|
||||||
|
fEncoderList.RemoveCurrent();
|
||||||
|
// Keep going, since we add multiple encoder infos per add-on.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -54,9 +54,11 @@ public:
|
|||||||
media_format* _outputFormat, int32 cookie);
|
media_format* _outputFormat, int32 cookie);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
status_t _RegisterAddOn(BEntry& entry);
|
|
||||||
void _RegisterAddOns();
|
void _RegisterAddOns();
|
||||||
|
|
||||||
|
status_t _RegisterAddOn(BEntry& entry);
|
||||||
|
status_t _UnregisterAddOn(BEntry& entry);
|
||||||
|
|
||||||
void _RegisterReader(ReaderPlugin* reader,
|
void _RegisterReader(ReaderPlugin* reader,
|
||||||
const entry_ref& ref);
|
const entry_ref& ref);
|
||||||
void _RegisterDecoder(DecoderPlugin* decoder,
|
void _RegisterDecoder(DecoderPlugin* decoder,
|
||||||
@@ -99,7 +101,7 @@ private:
|
|||||||
uint32 fNextWriterFormatFamilyID;
|
uint32 fNextWriterFormatFamilyID;
|
||||||
uint32 fNextEncoderCodecInfoID;
|
uint32 fNextEncoderCodecInfoID;
|
||||||
|
|
||||||
AddOnMonitorHandler* fHandler;
|
AddOnMonitorHandler* fAddOnMonitorHandler;
|
||||||
AddOnMonitor* fAddOnMonitor;
|
AddOnMonitor* fAddOnMonitor;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user