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:
Stephan Aßmus
2010-08-19 19:59:37 +00:00
parent be345b9c46
commit 19cd5c15d2
2 changed files with 153 additions and 71 deletions
+149 -69
View File
@@ -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;
} }
+4 -2
View File
@@ -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;
}; };