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:
parent
be345b9c46
commit
19cd5c15d2
@ -49,7 +49,7 @@ public:
|
||||
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; }
|
||||
|
||||
private:
|
||||
@ -64,13 +64,20 @@ AddOnManager::AddOnManager()
|
||||
:
|
||||
fLock("add-on manager"),
|
||||
fNextWriterFormatFamilyID(0),
|
||||
fNextEncoderCodecInfoID(0)
|
||||
fNextEncoderCodecInfoID(0),
|
||||
fAddOnMonitorHandler(NULL),
|
||||
fAddOnMonitor(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
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 -
|
||||
|
||||
|
||||
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
|
||||
AddOnManager::_RegisterAddOn(BEntry& entry)
|
||||
{
|
||||
@ -237,7 +327,7 @@ AddOnManager::_RegisterAddOn(BEntry& entry)
|
||||
path.Path());
|
||||
|
||||
ImageLoader loader(path);
|
||||
if ((status = loader.InitCheck()) < B_OK)
|
||||
if ((status = loader.InitCheck()) != B_OK)
|
||||
return status;
|
||||
|
||||
MediaPlugin* (*instantiate_plugin_func)();
|
||||
@ -280,78 +370,68 @@ AddOnManager::_RegisterAddOn(BEntry& entry)
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
AddOnManager::_RegisterAddOns()
|
||||
status_t
|
||||
AddOnManager::_UnregisterAddOn(BEntry& entry)
|
||||
{
|
||||
class CodecHandler : public AddOnMonitorHandler {
|
||||
private:
|
||||
AddOnManager* fManager;
|
||||
BPath path(&entry);
|
||||
printf("AddOnManager::_UnregisterAddOn(): trying to unload \"%s\"\n",
|
||||
path.Path());
|
||||
|
||||
public:
|
||||
CodecHandler(AddOnManager* manager)
|
||||
{
|
||||
fManager = manager;
|
||||
}
|
||||
BAutolock locker(fLock);
|
||||
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
}
|
||||
|
||||
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 Readers exported by this add-on
|
||||
reader_info* readerInfo;
|
||||
for (fReaderList.Rewind(); fReaderList.GetNext(&readerInfo);) {
|
||||
if (readerInfo->ref == ref) {
|
||||
printf("removing reader '%s'\n", readerInfo->ref.name);
|
||||
fReaderList.RemoveCurrent();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// 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);
|
||||
|
||||
private:
|
||||
status_t _RegisterAddOn(BEntry& entry);
|
||||
void _RegisterAddOns();
|
||||
|
||||
status_t _RegisterAddOn(BEntry& entry);
|
||||
status_t _UnregisterAddOn(BEntry& entry);
|
||||
|
||||
void _RegisterReader(ReaderPlugin* reader,
|
||||
const entry_ref& ref);
|
||||
void _RegisterDecoder(DecoderPlugin* decoder,
|
||||
@ -99,7 +101,7 @@ private:
|
||||
uint32 fNextWriterFormatFamilyID;
|
||||
uint32 fNextEncoderCodecInfoID;
|
||||
|
||||
AddOnMonitorHandler* fHandler;
|
||||
AddOnMonitorHandler* fAddOnMonitorHandler;
|
||||
AddOnMonitor* fAddOnMonitor;
|
||||
};
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user