* Cleaned up DormantNodeManager.
* Renamed global variable _DormantNodeManager to gDormantNodeManager. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@34538 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
522c2f19d4
commit
29bb91d6e5
@ -2,11 +2,18 @@
|
|||||||
* Copyright 2002, Marcus Overhagen. All rights reserved.
|
* Copyright 2002, Marcus Overhagen. All rights reserved.
|
||||||
* Distributed under the terms of the MIT License.
|
* Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _DORMANT_NODE_MANAGER_H
|
#ifndef _DORMANT_NODE_MANAGER_H
|
||||||
#define _DORMANT_NODE_MANAGER_H
|
#define _DORMANT_NODE_MANAGER_H
|
||||||
|
|
||||||
#include "TMap.h"
|
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
#include <Locker.h>
|
||||||
|
#include <MediaAddOn.h>
|
||||||
|
|
||||||
|
|
||||||
|
class BPath;
|
||||||
|
|
||||||
|
|
||||||
namespace BPrivate {
|
namespace BPrivate {
|
||||||
namespace media {
|
namespace media {
|
||||||
@ -22,48 +29,50 @@ namespace media {
|
|||||||
// but will delay the unloading slightly, because it is called
|
// but will delay the unloading slightly, because it is called
|
||||||
// from a node destructor of the loaded add-on.
|
// from a node destructor of the loaded add-on.
|
||||||
|
|
||||||
class DormantNodeManager
|
class DormantNodeManager {
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
DormantNodeManager();
|
DormantNodeManager();
|
||||||
~DormantNodeManager();
|
~DormantNodeManager();
|
||||||
|
|
||||||
// Be careful, GetAddon and PutAddon[Delayed] must be balanced.
|
// Be careful, GetAddon and PutAddon[Delayed] must be balanced.
|
||||||
BMediaAddOn *GetAddon(media_addon_id id);
|
BMediaAddOn* GetAddOn(media_addon_id id);
|
||||||
void PutAddon(media_addon_id id);
|
void PutAddOn(media_addon_id id);
|
||||||
void PutAddonDelayed(media_addon_id id);
|
void PutAddOnDelayed(media_addon_id id);
|
||||||
|
|
||||||
// For use by media_addon_server only
|
// For use by media_addon_server only
|
||||||
media_addon_id RegisterAddon(const char *path);
|
media_addon_id RegisterAddOn(const char* path);
|
||||||
void UnregisterAddon(media_addon_id id);
|
void UnregisterAddOn(media_addon_id id);
|
||||||
|
|
||||||
// query the server for the path
|
// query the server for the path
|
||||||
status_t FindAddonPath(BPath *path, media_addon_id id);
|
status_t FindAddOnPath(BPath* path, media_addon_id id);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct loaded_addon_info
|
struct loaded_add_on_info {
|
||||||
{
|
BMediaAddOn* add_on;
|
||||||
BMediaAddOn *addon;
|
image_id image;
|
||||||
image_id image;
|
int32 use_count;
|
||||||
int32 usecount;
|
};
|
||||||
};
|
|
||||||
|
|
||||||
// returns the addon or NULL if it needs to be loaded
|
// returns the addon or NULL if it needs to be loaded
|
||||||
BMediaAddOn *TryGetAddon(media_addon_id id);
|
BMediaAddOn* _LookupAddOn(media_addon_id id);
|
||||||
|
|
||||||
// manage loading and unloading add-ons from images
|
// manage loading and unloading add-ons from images
|
||||||
status_t LoadAddon(BMediaAddOn **newaddon, image_id *newimage, const char *path, media_addon_id id);
|
status_t _LoadAddOn(const char* path, media_addon_id id,
|
||||||
void UnloadAddon(BMediaAddOn *addon, image_id image);
|
BMediaAddOn** _newAddOn,
|
||||||
|
image_id* _newImage);
|
||||||
|
void _UnloadAddOn(BMediaAddOn* addOn,
|
||||||
|
image_id image);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
typedef std::map<media_addon_id, loaded_add_on_info> AddOnMap;
|
||||||
|
|
||||||
Map<media_addon_id,loaded_addon_info> *fAddonmap;
|
BLocker fLock;
|
||||||
BLocker *fLock;
|
AddOnMap fAddOnMap;
|
||||||
};
|
};
|
||||||
|
|
||||||
}; // namespace media
|
} // namespace media
|
||||||
}; // namespace BPrivate
|
} // namespace BPrivate
|
||||||
|
|
||||||
extern BPrivate::media::DormantNodeManager *_DormantNodeManager;
|
extern BPrivate::media::DormantNodeManager* gDormantNodeManager;
|
||||||
|
|
||||||
#endif /* _DORMANT_NODE_MANAGER_H */
|
#endif /* _DORMANT_NODE_MANAGER_H */
|
||||||
|
@ -27,136 +27,161 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* This is a management class for dormant media nodes.
|
|
||||||
* It is private to the media kit and only accessed by the BMediaRoster class
|
/*! This is a management class for dormant media nodes.
|
||||||
* and the media_addon_server.
|
It is private to the media kit and only accessed by the BMediaRoster class
|
||||||
* It handles loading/unloading of dormant nodes.
|
and the media_addon_server.
|
||||||
*
|
It handles loading/unloading of dormant nodes.
|
||||||
* Dormant media nodes can be instantiated on demand. The reside on harddisk in the
|
|
||||||
* directories /boot/beos/system/add-ons/media and /boot/home/config/add-ons/media
|
Dormant media nodes can be instantiated on demand. The reside on harddisk in
|
||||||
* Multiple media nodes can be included in one file, they can be accessed using the
|
the directories /boot/beos/system/add-ons/media, /boot/common/add-ons/media,
|
||||||
* BMediaAddOn that each file implements.
|
and /boot/home/config/add-ons/media.
|
||||||
* The BMediaAddOn allows getting a list of supported flavors. Each flavor represents
|
Multiple media nodes can be included in one file, they can be accessed using
|
||||||
* a media node.
|
the BMediaAddOn that each file implements.
|
||||||
* The media_addon_server does the initial scanning of files and getting the list
|
The BMediaAddOn allows getting a list of supported flavors. Each flavor
|
||||||
* of supported flavors. It uses the flavor_info to do this, and reports the list
|
represents a media node.
|
||||||
* of flavors to the media_server packed into individual dormant_media_node
|
The media_addon_server does the initial scanning of files and getting the
|
||||||
* structures.
|
list of supported flavors. It uses the flavor_info to do this, and reports
|
||||||
*/
|
the list of flavors to the media_server packed into individual
|
||||||
|
dormant_media_node structures.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "DormantNodeManager.h"
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <Locker.h>
|
|
||||||
#include <Path.h>
|
#include <Autolock.h>
|
||||||
#include <Entry.h>
|
#include <Entry.h>
|
||||||
#include <MediaAddOn.h>
|
#include <Path.h>
|
||||||
#include "debug.h"
|
|
||||||
#include "PortPool.h"
|
#include <debug.h>
|
||||||
#include "MediaMisc.h"
|
#include <PortPool.h>
|
||||||
#include "ServerInterface.h"
|
#include <MediaMisc.h>
|
||||||
#include "DataExchange.h"
|
#include <ServerInterface.h>
|
||||||
#include "DormantNodeManager.h"
|
#include <DataExchange.h>
|
||||||
|
|
||||||
|
|
||||||
static BPrivate::media::DormantNodeManager manager;
|
static BPrivate::media::DormantNodeManager manager;
|
||||||
BPrivate::media::DormantNodeManager *_DormantNodeManager = &manager;
|
BPrivate::media::DormantNodeManager* gDormantNodeManager = &manager;
|
||||||
|
|
||||||
|
|
||||||
namespace BPrivate {
|
namespace BPrivate {
|
||||||
namespace media {
|
namespace media {
|
||||||
|
|
||||||
|
|
||||||
DormantNodeManager::DormantNodeManager()
|
DormantNodeManager::DormantNodeManager()
|
||||||
|
:
|
||||||
|
fLock("dormant node manager locker")
|
||||||
{
|
{
|
||||||
fLock = new BLocker("dormant node manager locker");
|
|
||||||
fAddonmap = new Map<media_addon_id,loaded_addon_info>;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
DormantNodeManager::~DormantNodeManager()
|
DormantNodeManager::~DormantNodeManager()
|
||||||
{
|
{
|
||||||
delete fLock;
|
|
||||||
|
|
||||||
// force unloading all currently loaded images
|
// force unloading all currently loaded images
|
||||||
loaded_addon_info *info;
|
|
||||||
for (fAddonmap->Rewind(); fAddonmap->GetNext(&info); ) {
|
|
||||||
ERROR("Forcing unload of add-on id %ld with usecount %ld\n", info->addon->AddonID(), info->usecount);
|
|
||||||
UnloadAddon(info->addon, info->image);
|
|
||||||
}
|
|
||||||
|
|
||||||
delete fAddonmap;
|
AddOnMap::iterator iterator = fAddOnMap.begin();
|
||||||
|
for (; iterator != fAddOnMap.end(); iterator++) {
|
||||||
|
loaded_add_on_info& info = iterator->second;
|
||||||
|
|
||||||
|
ERROR("Forcing unload of add-on id %ld with usecount %ld\n",
|
||||||
|
info.add_on->AddonID(), info.use_count);
|
||||||
|
_UnloadAddOn(info.add_on, info.image);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
BMediaAddOn *
|
BMediaAddOn*
|
||||||
DormantNodeManager::TryGetAddon(media_addon_id id)
|
DormantNodeManager::GetAddOn(media_addon_id id)
|
||||||
{
|
{
|
||||||
loaded_addon_info *info;
|
TRACE("DormantNodeManager::GetAddon, id %ld\n", id);
|
||||||
BMediaAddOn *addon;
|
|
||||||
|
|
||||||
fLock->Lock();
|
|
||||||
if (fAddonmap->Get(id, &info)) {
|
|
||||||
info->usecount += 1;
|
|
||||||
addon = info->addon;
|
|
||||||
ASSERT(id == addon->AddonID());
|
|
||||||
} else {
|
|
||||||
addon = NULL;
|
|
||||||
}
|
|
||||||
fLock->Unlock();
|
|
||||||
return addon;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
BMediaAddOn *
|
|
||||||
DormantNodeManager::GetAddon(media_addon_id id)
|
|
||||||
{
|
|
||||||
BMediaAddOn *addon;
|
|
||||||
|
|
||||||
TRACE("DormantNodeManager::GetAddon, id %ld\n",id);
|
|
||||||
|
|
||||||
// first try to use a already loaded add-on
|
// first try to use a already loaded add-on
|
||||||
addon = TryGetAddon(id);
|
BMediaAddOn* addOn = _LookupAddOn(id);
|
||||||
if (addon)
|
if (addOn != NULL)
|
||||||
return addon;
|
return addOn;
|
||||||
|
|
||||||
// Be careful, we avoid locking here!
|
// Be careful, we avoid locking here!
|
||||||
|
|
||||||
// ok, it's not loaded, try to get the path
|
// ok, it's not loaded, try to get the path
|
||||||
BPath path;
|
BPath path;
|
||||||
if (B_OK != FindAddonPath(&path, id)) {
|
if (FindAddOnPath(&path, id) != B_OK) {
|
||||||
ERROR("DormantNodeManager::GetAddon: can't find path for add-on %ld\n",id);
|
ERROR("DormantNodeManager::GetAddon: can't find path for add-on "
|
||||||
|
"%ld\n", id);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// try to load it
|
// try to load it
|
||||||
BMediaAddOn *newaddon;
|
BMediaAddOn* newAddOn;
|
||||||
image_id image;
|
image_id image;
|
||||||
if (B_OK != LoadAddon(&newaddon, &image, path.Path(), id)) {
|
if (_LoadAddOn(path.Path(), id, &newAddOn, &image) != B_OK) {
|
||||||
ERROR("DormantNodeManager::GetAddon: can't load add-on %ld from path %s\n",id, path.Path());
|
ERROR("DormantNodeManager::GetAddon: can't load add-on %ld from path "
|
||||||
|
"%s\n",id, path.Path());
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ok, we successfully loaded it. Now lock and insert it into the map,
|
// ok, we successfully loaded it. Now lock and insert it into the map,
|
||||||
// or unload it if the map already contains one that was loaded by another
|
// or unload it if the map already contains one that was loaded by another
|
||||||
// thread at the same time
|
// thread at the same time
|
||||||
fLock->Lock();
|
|
||||||
addon = TryGetAddon(id);
|
BAutolock _(fLock);
|
||||||
if (addon) {
|
|
||||||
UnloadAddon(newaddon, image);
|
addOn = _LookupAddOn(id);
|
||||||
} else {
|
if (addOn == NULL) {
|
||||||
// we use the loaded one
|
// we use the loaded one
|
||||||
addon = newaddon;
|
addOn = newAddOn;
|
||||||
|
|
||||||
// and save it into the list
|
// and save it into the list
|
||||||
loaded_addon_info info;
|
loaded_add_on_info info;
|
||||||
info.addon = newaddon;
|
info.add_on = newAddOn;
|
||||||
info.image = image;
|
info.image = image;
|
||||||
info.usecount = 1;
|
info.use_count = 1;
|
||||||
fAddonmap->Insert(id, info);
|
try {
|
||||||
}
|
fAddOnMap.insert(std::make_pair(id, info));
|
||||||
fLock->Unlock();
|
} catch (std::bad_alloc& exception) {
|
||||||
ASSERT(addon->AddonID() == id);
|
_UnloadAddOn(newAddOn, image);
|
||||||
return addon;
|
return NULL;
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
_UnloadAddOn(newAddOn, image);
|
||||||
|
|
||||||
|
ASSERT(addOn->AddonID() == id);
|
||||||
|
return addOn;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
DormantNodeManager::PutAddonDelayed(media_addon_id id)
|
DormantNodeManager::PutAddOn(media_addon_id id)
|
||||||
|
{
|
||||||
|
TRACE("DormantNodeManager::PutAddon, id %ld\n", id);
|
||||||
|
|
||||||
|
BAutolock locker(fLock);
|
||||||
|
|
||||||
|
AddOnMap::iterator found = fAddOnMap.find(id);
|
||||||
|
if (found == fAddOnMap.end()) {
|
||||||
|
ERROR("DormantNodeManager::PutAddon: failed to find add-on %ld\n", id);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
loaded_add_on_info& info = found->second;
|
||||||
|
|
||||||
|
if (--info.use_count == 0) {
|
||||||
|
// unload add-on
|
||||||
|
|
||||||
|
BMediaAddOn* addOn = info.add_on;
|
||||||
|
image_id image = info.image;
|
||||||
|
fAddOnMap.erase(found);
|
||||||
|
|
||||||
|
locker.Unlock();
|
||||||
|
_UnloadAddOn(addOn, image);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
DormantNodeManager::PutAddOnDelayed(media_addon_id id)
|
||||||
{
|
{
|
||||||
// Called from a node destructor of the loaded media-add-on.
|
// Called from a node destructor of the loaded media-add-on.
|
||||||
// We must make sure that the media-add-on stays in memory
|
// We must make sure that the media-add-on stays in memory
|
||||||
@ -165,70 +190,49 @@ DormantNodeManager::PutAddonDelayed(media_addon_id id)
|
|||||||
UNIMPLEMENTED();
|
UNIMPLEMENTED();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
DormantNodeManager::PutAddon(media_addon_id id)
|
|
||||||
{
|
|
||||||
loaded_addon_info *info;
|
|
||||||
BMediaAddOn *addon = 0; /* avoid compiler warning */
|
|
||||||
image_id image = 0; /* avoid compiler warning */
|
|
||||||
bool unload;
|
|
||||||
|
|
||||||
TRACE("DormantNodeManager::PutAddon, id %ld\n",id);
|
//! For use by media_addon_server only
|
||||||
|
|
||||||
fLock->Lock();
|
|
||||||
if (!fAddonmap->Get(id, &info)) {
|
|
||||||
ERROR("DormantNodeManager::PutAddon: failed to find add-on %ld\n",id);
|
|
||||||
fLock->Unlock();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
info->usecount -= 1;
|
|
||||||
unload = (info->usecount == 0);
|
|
||||||
if (unload) {
|
|
||||||
addon = info->addon;
|
|
||||||
image = info->image;
|
|
||||||
fAddonmap->Remove(id);
|
|
||||||
}
|
|
||||||
fLock->Unlock();
|
|
||||||
|
|
||||||
if (unload)
|
|
||||||
UnloadAddon(addon, image);
|
|
||||||
}
|
|
||||||
|
|
||||||
// For use by media_addon_server only
|
|
||||||
media_addon_id
|
media_addon_id
|
||||||
DormantNodeManager::RegisterAddon(const char *path)
|
DormantNodeManager::RegisterAddOn(const char* path)
|
||||||
{
|
{
|
||||||
server_register_mediaaddon_request msg;
|
|
||||||
server_register_mediaaddon_reply reply;
|
|
||||||
port_id port;
|
|
||||||
status_t rv;
|
|
||||||
int32 code;
|
|
||||||
entry_ref tempref;
|
|
||||||
|
|
||||||
TRACE("DormantNodeManager::RegisterAddon, path %s\n",path);
|
TRACE("DormantNodeManager::RegisterAddon, path %s\n",path);
|
||||||
|
|
||||||
rv = get_ref_for_path(path, &tempref);
|
server_register_mediaaddon_request msg;
|
||||||
if (rv != B_OK) {
|
entry_ref ref;
|
||||||
ERROR("DormantNodeManager::RegisterAddon failed, couldn't get ref for path %s\n",path);
|
status_t status = get_ref_for_path(path, &ref);
|
||||||
|
if (status != B_OK) {
|
||||||
|
ERROR("DormantNodeManager::RegisterAddon failed, couldn't get ref "
|
||||||
|
"for path %s: %s\n", path, strerror(status));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
msg.ref = tempref;
|
|
||||||
port = find_port(MEDIA_SERVER_PORT_NAME);
|
port_id port = find_port(MEDIA_SERVER_PORT_NAME);
|
||||||
if (port <= B_OK) {
|
if (port < 0) {
|
||||||
ERROR("DormantNodeManager::RegisterAddon failed, couldn't find media server\n");
|
ERROR("DormantNodeManager::RegisterAddon failed, couldn't find media "
|
||||||
|
"server\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
msg.reply_port = _PortPool->GetPort();
|
msg.reply_port = _PortPool->GetPort();
|
||||||
rv = write_port(port, SERVER_REGISTER_MEDIAADDON, &msg, sizeof(msg));
|
msg.ref = ref;
|
||||||
if (rv != B_OK) {
|
|
||||||
|
status = write_port(port, SERVER_REGISTER_MEDIAADDON, &msg, sizeof(msg));
|
||||||
|
if (status != B_OK) {
|
||||||
_PortPool->PutPort(msg.reply_port);
|
_PortPool->PutPort(msg.reply_port);
|
||||||
ERROR("DormantNodeManager::RegisterAddon failed, couldn't talk to media server\n");
|
ERROR("DormantNodeManager::RegisterAddon failed, couldn't talk to "
|
||||||
|
"media server\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
rv = read_port(msg.reply_port, &code, &reply, sizeof(reply));
|
|
||||||
|
server_register_mediaaddon_reply reply;
|
||||||
|
int32 code;
|
||||||
|
status = read_port(msg.reply_port, &code, &reply, sizeof(reply));
|
||||||
|
|
||||||
_PortPool->PutPort(msg.reply_port);
|
_PortPool->PutPort(msg.reply_port);
|
||||||
if (rv < B_OK) {
|
|
||||||
ERROR("DormantNodeManager::RegisterAddon failed, couldn't talk to media server (2)\n");
|
if (status < B_OK) {
|
||||||
|
ERROR("DormantNodeManager::RegisterAddon failed, couldn't talk to "
|
||||||
|
"media server: %s\n", strerror(status));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -238,104 +242,128 @@ DormantNodeManager::RegisterAddon(const char *path)
|
|||||||
return reply.addon_id;
|
return reply.addon_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
// For use by media_addon_server only
|
|
||||||
|
//! For use by media_addon_server only
|
||||||
void
|
void
|
||||||
DormantNodeManager::UnregisterAddon(media_addon_id id)
|
DormantNodeManager::UnregisterAddOn(media_addon_id id)
|
||||||
{
|
{
|
||||||
ASSERT(id > 0);
|
|
||||||
server_unregister_mediaaddon_command msg;
|
|
||||||
|
|
||||||
TRACE("DormantNodeManager::UnregisterAddon id %ld\n",id);
|
TRACE("DormantNodeManager::UnregisterAddon id %ld\n",id);
|
||||||
|
ASSERT(id > 0);
|
||||||
|
|
||||||
port_id port;
|
port_id port = find_port(MEDIA_SERVER_PORT_NAME);
|
||||||
port = find_port(MEDIA_SERVER_PORT_NAME);
|
if (port < 0)
|
||||||
if (port <= B_OK)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
server_unregister_mediaaddon_command msg;
|
||||||
msg.addon_id = id;
|
msg.addon_id = id;
|
||||||
write_port(port, SERVER_UNREGISTER_MEDIAADDON, &msg, sizeof(msg));
|
write_port(port, SERVER_UNREGISTER_MEDIAADDON, &msg, sizeof(msg));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
DormantNodeManager::FindAddonPath(BPath *path, media_addon_id id)
|
DormantNodeManager::FindAddOnPath(BPath* path, media_addon_id id)
|
||||||
{
|
{
|
||||||
server_get_mediaaddon_ref_request msg;
|
port_id port = find_port(MEDIA_SERVER_PORT_NAME);
|
||||||
server_get_mediaaddon_ref_reply reply;
|
if (port < 0)
|
||||||
port_id port;
|
|
||||||
entry_ref tempref;
|
|
||||||
status_t rv;
|
|
||||||
int32 code;
|
|
||||||
port = find_port(MEDIA_SERVER_PORT_NAME);
|
|
||||||
if (port <= B_OK)
|
|
||||||
return B_ERROR;
|
|
||||||
msg.addon_id = id;
|
|
||||||
msg.reply_port = _PortPool->GetPort();
|
|
||||||
rv = write_port(port, SERVER_GET_MEDIAADDON_REF, &msg, sizeof(msg));
|
|
||||||
if (rv != B_OK) {
|
|
||||||
_PortPool->PutPort(msg.reply_port);
|
|
||||||
return B_ERROR;
|
|
||||||
}
|
|
||||||
rv = read_port(msg.reply_port, &code, &reply, sizeof(reply));
|
|
||||||
_PortPool->PutPort(msg.reply_port);
|
|
||||||
if (rv < B_OK)
|
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
|
|
||||||
tempref = reply.ref;
|
server_get_mediaaddon_ref_request msg;
|
||||||
return path->SetTo(&tempref);
|
msg.addon_id = id;
|
||||||
|
msg.reply_port = _PortPool->GetPort();
|
||||||
|
status_t status = write_port(port, SERVER_GET_MEDIAADDON_REF, &msg,
|
||||||
|
sizeof(msg));
|
||||||
|
if (status != B_OK) {
|
||||||
|
_PortPool->PutPort(msg.reply_port);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
server_get_mediaaddon_ref_reply reply;
|
||||||
|
int32 code;
|
||||||
|
status = read_port(msg.reply_port, &code, &reply, sizeof(reply));
|
||||||
|
|
||||||
|
_PortPool->PutPort(msg.reply_port);
|
||||||
|
|
||||||
|
if (status < B_OK)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
entry_ref ref = reply.ref;
|
||||||
|
return path->SetTo(&ref);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BMediaAddOn*
|
||||||
|
DormantNodeManager::_LookupAddOn(media_addon_id id)
|
||||||
|
{
|
||||||
|
BAutolock _(fLock);
|
||||||
|
|
||||||
|
AddOnMap::iterator found = fAddOnMap.find(id);
|
||||||
|
if (found == fAddOnMap.end())
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
loaded_add_on_info& info = found->second;
|
||||||
|
|
||||||
|
ASSERT(id == info.add_on->AddonID());
|
||||||
|
info.use_count++;
|
||||||
|
|
||||||
|
return info.add_on;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
DormantNodeManager::LoadAddon(BMediaAddOn **newaddon, image_id *newimage, const char *path, media_addon_id id)
|
DormantNodeManager::_LoadAddOn(const char* path, media_addon_id id,
|
||||||
|
BMediaAddOn** _newAddOn, image_id* _newImage)
|
||||||
{
|
{
|
||||||
BMediaAddOn *(*make_addon)(image_id you);
|
image_id image = load_add_on(path);
|
||||||
BMediaAddOn *addon;
|
if (image < 0) {
|
||||||
image_id image;
|
ERROR("DormantNodeManager::LoadAddon: loading \"%s\" failed: %s\n",
|
||||||
status_t rv;
|
path, strerror(image));
|
||||||
|
return image;
|
||||||
image = load_add_on(path);
|
|
||||||
if (image < B_OK) {
|
|
||||||
ERROR("DormantNodeManager::LoadAddon: loading failed, error %lx (%s), path %s\n", image, strerror(image), path);
|
|
||||||
return B_ERROR;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
rv = get_image_symbol(image, "make_media_addon", B_SYMBOL_TYPE_TEXT, (void**)&make_addon);
|
BMediaAddOn* (*makeAddOn)(image_id);
|
||||||
if (rv < B_OK) {
|
status_t status = get_image_symbol(image, "make_media_addon",
|
||||||
ERROR("DormantNodeManager::LoadAddon: loading failed, function not found, error %lx (%s)\n", rv, strerror(rv));
|
B_SYMBOL_TYPE_TEXT, (void**)&makeAddOn);
|
||||||
|
if (status != B_OK) {
|
||||||
|
ERROR("DormantNodeManager::LoadAddon: loading failed, function not "
|
||||||
|
"found: %s\n", strerror(status));
|
||||||
unload_add_on(image);
|
unload_add_on(image);
|
||||||
return B_ERROR;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
addon = make_addon(image);
|
BMediaAddOn* addOn = makeAddOn(image);
|
||||||
if (addon == 0) {
|
if (addOn == NULL) {
|
||||||
ERROR("DormantNodeManager::LoadAddon: creating BMediaAddOn failed\n");
|
ERROR("DormantNodeManager::LoadAddon: creating BMediaAddOn failed\n");
|
||||||
unload_add_on(image);
|
unload_add_on(image);
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
ASSERT(addon->ImageID() == image); // this should be true for a well behaving add-on
|
ASSERT(addOn->ImageID() == image);
|
||||||
|
// this should be true for a well behaving add-ons
|
||||||
|
|
||||||
|
// We are a friend class of BMediaAddOn and initialize these member
|
||||||
|
// variables
|
||||||
|
addOn->fAddon = id;
|
||||||
|
addOn->fImage = image;
|
||||||
|
|
||||||
// everything ok
|
// everything ok
|
||||||
*newaddon = addon;
|
*_newAddOn = addOn;
|
||||||
*newimage = image;
|
*_newImage = image;
|
||||||
|
|
||||||
// we are a friend class of BMediaAddOn and initialize these member variables
|
|
||||||
addon->fAddon = id;
|
|
||||||
addon->fImage = image;
|
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
DormantNodeManager::UnloadAddon(BMediaAddOn *addon, image_id image)
|
DormantNodeManager::_UnloadAddOn(BMediaAddOn* addOn, image_id image)
|
||||||
{
|
{
|
||||||
ASSERT(addon);
|
ASSERT(addOn != NULL);
|
||||||
ASSERT(addon->ImageID() == image); // if this failes, something bad happened to the add-on
|
ASSERT(addOn->ImageID() == image);
|
||||||
delete addon;
|
// if this fails, something bad happened to the add-on
|
||||||
|
|
||||||
|
delete addOn;
|
||||||
unload_add_on(image);
|
unload_add_on(image);
|
||||||
}
|
}
|
||||||
|
|
||||||
}; // namespace media
|
|
||||||
}; // namespace BPrivate
|
|
||||||
|
|
||||||
|
} // namespace media
|
||||||
|
} // namespace BPrivate
|
||||||
|
@ -2005,7 +2005,7 @@ BMediaRoster::UnregisterNode(BMediaNode* node)
|
|||||||
|
|
||||||
TRACE("BMediaRoster::UnregisterNode %ld (%p)\n", node->ID(), node);
|
TRACE("BMediaRoster::UnregisterNode %ld (%p)\n", node->ID(), node);
|
||||||
|
|
||||||
if (node->fKinds & NODE_KIND_NO_REFCOUNTING) {
|
if ((node->fKinds & NODE_KIND_NO_REFCOUNTING) !=0) {
|
||||||
TRACE("BMediaRoster::UnregisterNode, trying to unregister reference "
|
TRACE("BMediaRoster::UnregisterNode, trying to unregister reference "
|
||||||
"counting disabled timesource, node %ld, port %ld, team %ld\n",
|
"counting disabled timesource, node %ld, port %ld, team %ld\n",
|
||||||
node->ID(), node->ControlPort(), BPrivate::current_team());
|
node->ID(), node->ControlPort(), BPrivate::current_team());
|
||||||
@ -2030,35 +2030,34 @@ BMediaRoster::UnregisterNode(BMediaNode* node)
|
|||||||
// might have been called).
|
// might have been called).
|
||||||
|
|
||||||
server_unregister_node_request request;
|
server_unregister_node_request request;
|
||||||
server_unregister_node_reply reply;
|
|
||||||
status_t rv;
|
|
||||||
|
|
||||||
request.node_id = node->ID();
|
request.node_id = node->ID();
|
||||||
request.team = BPrivate::current_team();
|
request.team = BPrivate::current_team();
|
||||||
|
|
||||||
// send a notification
|
// send a notification
|
||||||
BPrivate::media::notifications::NodesDeleted(&request.node_id, 1);
|
BPrivate::media::notifications::NodesDeleted(&request.node_id, 1);
|
||||||
|
|
||||||
rv = QueryServer(SERVER_UNREGISTER_NODE, &request, sizeof(request), &reply,
|
server_unregister_node_reply reply;
|
||||||
sizeof(reply));
|
status_t status = QueryServer(SERVER_UNREGISTER_NODE, &request,
|
||||||
if (rv != B_OK) {
|
sizeof(request), &reply, sizeof(reply));
|
||||||
|
if (status != B_OK) {
|
||||||
ERROR("BMediaRoster::UnregisterNode: failed to unregister node id %ld, "
|
ERROR("BMediaRoster::UnregisterNode: failed to unregister node id %ld, "
|
||||||
"name '%s' (error %#lx)\n", node->ID(), node->Name(), rv);
|
"name '%s': %s\n", node->ID(), node->Name(), strerror(status));
|
||||||
return rv;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (reply.addon_id != -1) {
|
if (reply.addon_id != -1) {
|
||||||
// Small problem here, we can't use DormantNodeManager::PutAddon(), as
|
// TODO: this doesn't look right
|
||||||
|
// Small problem here, we can't use DormantNodeManager::PutAddOn(), as
|
||||||
// UnregisterNode() is called by a dormant node itself (by the
|
// UnregisterNode() is called by a dormant node itself (by the
|
||||||
// destructor).
|
// destructor).
|
||||||
// The add-on that contains the node needs to remain in memory until the
|
// The add-on that contains the node needs to remain in memory until the
|
||||||
// destructor execution is finished.
|
// destructor execution is finished.
|
||||||
// DormantNodeManager::PutAddonDelayed() will delay unloading.
|
// DormantNodeManager::PutAddOnDelayed() will delay unloading.
|
||||||
_DormantNodeManager->PutAddonDelayed(reply.addon_id);
|
gDormantNodeManager->PutAddOnDelayed(reply.addon_id);
|
||||||
|
|
||||||
rv = MediaRosterEx(this)->DecrementAddonFlavorInstancesCount(
|
status = MediaRosterEx(this)->DecrementAddonFlavorInstancesCount(
|
||||||
reply.addon_id, reply.flavor_id);
|
reply.addon_id, reply.flavor_id);
|
||||||
if (rv != B_OK) {
|
if (status != B_OK) {
|
||||||
ERROR("BMediaRoster::UnregisterNode: "
|
ERROR("BMediaRoster::UnregisterNode: "
|
||||||
"DecrementAddonFlavorInstancesCount() failed\n");
|
"DecrementAddonFlavorInstancesCount() failed\n");
|
||||||
// this is really a problem, but we can't fail now
|
// this is really a problem, but we can't fail now
|
||||||
@ -2377,8 +2376,7 @@ BMediaRosterEx::InstantiateDormantNode(media_addon_id addonID, int32 flavorID,
|
|||||||
ASSERT(info.internal_id == flavorID);
|
ASSERT(info.internal_id == flavorID);
|
||||||
|
|
||||||
// load the BMediaAddOn object
|
// load the BMediaAddOn object
|
||||||
BMediaAddOn* addon;
|
BMediaAddOn* addon = gDormantNodeManager->GetAddOn(addonID);
|
||||||
addon = _DormantNodeManager->GetAddon(addonID);
|
|
||||||
if (addon == NULL) {
|
if (addon == NULL) {
|
||||||
ERROR("BMediaRosterEx::InstantiateDormantNode: GetAddon failed\n");
|
ERROR("BMediaRosterEx::InstantiateDormantNode: GetAddon failed\n");
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
@ -2392,7 +2390,7 @@ BMediaRosterEx::InstantiateDormantNode(media_addon_id addonID, int32 flavorID,
|
|||||||
ERROR("BMediaRosterEx::InstantiateDormantNode error: can't create "
|
ERROR("BMediaRosterEx::InstantiateDormantNode error: can't create "
|
||||||
"more nodes for addon-id %ld, flavor-id %ld\n", addonID, flavorID);
|
"more nodes for addon-id %ld, flavor-id %ld\n", addonID, flavorID);
|
||||||
// Put the addon back into the pool
|
// Put the addon back into the pool
|
||||||
_DormantNodeManager->PutAddon(addonID);
|
gDormantNodeManager->PutAddOn(addonID);
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2412,7 +2410,7 @@ BMediaRosterEx::InstantiateDormantNode(media_addon_id addonID, int32 flavorID,
|
|||||||
"failed\n");
|
"failed\n");
|
||||||
|
|
||||||
// Put the addon back into the pool
|
// Put the addon back into the pool
|
||||||
_DormantNodeManager->PutAddon(addonID);
|
gDormantNodeManager->PutAddOn(addonID);
|
||||||
|
|
||||||
// We must decrement the use count of this addon flavor in the
|
// We must decrement the use count of this addon flavor in the
|
||||||
// server to compensate the increment done in the beginning.
|
// server to compensate the increment done in the beginning.
|
||||||
@ -2429,7 +2427,7 @@ BMediaRosterEx::InstantiateDormantNode(media_addon_id addonID, int32 flavorID,
|
|||||||
ERROR("BMediaRosterEx::InstantiateDormantNode: RegisterNode failed\n");
|
ERROR("BMediaRosterEx::InstantiateDormantNode: RegisterNode failed\n");
|
||||||
delete node;
|
delete node;
|
||||||
// Put the addon back into the pool
|
// Put the addon back into the pool
|
||||||
_DormantNodeManager->PutAddon(addonID);
|
gDormantNodeManager->PutAddOn(addonID);
|
||||||
// We must decrement the use count of this addon flavor in the
|
// We must decrement the use count of this addon flavor in the
|
||||||
// server to compensate the increment done in the beginning.
|
// server to compensate the increment done in the beginning.
|
||||||
rv = DecrementAddonFlavorInstancesCount(addonID, flavorID);
|
rv = DecrementAddonFlavorInstancesCount(addonID, flavorID);
|
||||||
|
@ -368,9 +368,9 @@ DefaultManager::FindPhysical(volatile media_node_id *id, uint32 default_type, bo
|
|||||||
msg->FindInt32(kDefaultManagerInput, &input_id);
|
msg->FindInt32(kDefaultManagerInput, &input_id);
|
||||||
msg->FindString(kDefaultManagerFlavorName, &name);
|
msg->FindString(kDefaultManagerFlavorName, &name);
|
||||||
msg->FindString(kDefaultManagerPath, &path);
|
msg->FindString(kDefaultManagerPath, &path);
|
||||||
if(name)
|
if (name)
|
||||||
strcpy(msgDninfo.name, name);
|
strcpy(msgDninfo.name, name);
|
||||||
if(path)
|
if (path)
|
||||||
msgPath = BPath(path);
|
msgPath = BPath(path);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -411,28 +411,30 @@ DefaultManager::FindPhysical(volatile media_node_id *id, uint32 default_type, bo
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(msg) { // we have a default info msg
|
if (msg) { // we have a default info msg
|
||||||
dormant_node_info dninfo;
|
dormant_node_info dninfo;
|
||||||
if(BMediaRoster::Roster()->GetDormantNodeFor(info[i].node, &dninfo) != B_OK) {
|
if (BMediaRoster::Roster()->GetDormantNodeFor(info[i].node,
|
||||||
|
&dninfo) != B_OK) {
|
||||||
ERROR("Couldn't GetDormantNodeFor\n");
|
ERROR("Couldn't GetDormantNodeFor\n");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if(dninfo.flavor_id!=msgDninfo.flavor_id
|
if (dninfo.flavor_id != msgDninfo.flavor_id
|
||||||
|| strcmp(dninfo.name, msgDninfo.name)!=0) {
|
|| strcmp(dninfo.name, msgDninfo.name) != 0) {
|
||||||
ERROR("Doesn't match flavor or name\n");
|
ERROR("Doesn't match flavor or name\n");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
BPath path;
|
BPath path;
|
||||||
if((_DormantNodeManager->FindAddonPath(&path, dninfo.addon)!=B_OK)
|
if (gDormantNodeManager->FindAddOnPath(&path, dninfo.addon) != B_OK
|
||||||
|| (path != msgPath)) {
|
|| path != msgPath) {
|
||||||
ERROR("Doesn't match : path\n");
|
ERROR("Doesn't match : path\n");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TRACE("Default physical %s %s \"%s\" created!\n",
|
TRACE("Default physical %s %s \"%s\" created!\n",
|
||||||
isAudio ? "audio" : "video", isInput ? "input" : "output", info[i].name);
|
isAudio ? "audio" : "video", isInput ? "input" : "output",
|
||||||
|
info[i].name);
|
||||||
*id = info[i].node.node;
|
*id = info[i].node.node;
|
||||||
if(msg && isAudio && !isInput)
|
if (msg && isAudio && !isInput)
|
||||||
fPhysicalAudioOutInputID = input_id;
|
fPhysicalAudioOutInputID = input_id;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -78,7 +78,7 @@ struct AddOnInfo {
|
|||||||
NodeVector active_flavors;
|
NodeVector active_flavors;
|
||||||
|
|
||||||
BMediaAddOn* addon;
|
BMediaAddOn* addon;
|
||||||
// if != NULL, need to call _DormantNodeManager->PutAddon(id)
|
// if != NULL, need to call gDormantNodeManager->PutAddOn(id)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -226,7 +226,7 @@ MediaAddonServer::~MediaAddonServer()
|
|||||||
// unregister all media add-ons
|
// unregister all media add-ons
|
||||||
FileMap::iterator iterator = fFileMap.begin();
|
FileMap::iterator iterator = fFileMap.begin();
|
||||||
for (; iterator != fFileMap.end(); iterator++)
|
for (; iterator != fFileMap.end(); iterator++)
|
||||||
_DormantNodeManager->UnregisterAddon(iterator->second);
|
gDormantNodeManager->UnregisterAddOn(iterator->second);
|
||||||
|
|
||||||
// TODO: unregister system time source
|
// TODO: unregister system time source
|
||||||
}
|
}
|
||||||
@ -402,14 +402,14 @@ MediaAddonServer::_HandleMessage(int32 code, const void* data, size_t size)
|
|||||||
= static_cast<
|
= static_cast<
|
||||||
const addonserver_rescan_mediaaddon_flavors_command*>(data);
|
const addonserver_rescan_mediaaddon_flavors_command*>(data);
|
||||||
BMediaAddOn* addon
|
BMediaAddOn* addon
|
||||||
= _DormantNodeManager->GetAddon(command->addon_id);
|
= gDormantNodeManager->GetAddOn(command->addon_id);
|
||||||
if (addon == NULL) {
|
if (addon == NULL) {
|
||||||
ERROR("rescan flavors: Can't find a addon object for id %d\n",
|
ERROR("rescan flavors: Can't find a addon object for id %d\n",
|
||||||
(int)command->addon_id);
|
(int)command->addon_id);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
_ScanAddOnFlavors(addon);
|
_ScanAddOnFlavors(addon);
|
||||||
_DormantNodeManager->PutAddon(command->addon_id);
|
gDormantNodeManager->PutAddOn(command->addon_id);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -533,7 +533,7 @@ MediaAddonServer::_AddOnAdded(const char* path, ino_t fileNode)
|
|||||||
{
|
{
|
||||||
TRACE("\n\nMediaAddonServer::_AddOnAdded: path %s\n", path);
|
TRACE("\n\nMediaAddonServer::_AddOnAdded: path %s\n", path);
|
||||||
|
|
||||||
media_addon_id id = _DormantNodeManager->RegisterAddon(path);
|
media_addon_id id = gDormantNodeManager->RegisterAddOn(path);
|
||||||
if (id <= 0) {
|
if (id <= 0) {
|
||||||
ERROR("MediaAddonServer::_AddOnAdded: failed to register add-on %s\n",
|
ERROR("MediaAddonServer::_AddOnAdded: failed to register add-on %s\n",
|
||||||
path);
|
path);
|
||||||
@ -542,10 +542,10 @@ MediaAddonServer::_AddOnAdded(const char* path, ino_t fileNode)
|
|||||||
|
|
||||||
TRACE("MediaAddonServer::_AddOnAdded: loading addon %ld now...\n", id);
|
TRACE("MediaAddonServer::_AddOnAdded: loading addon %ld now...\n", id);
|
||||||
|
|
||||||
BMediaAddOn* addon = _DormantNodeManager->GetAddon(id);
|
BMediaAddOn* addon = gDormantNodeManager->GetAddOn(id);
|
||||||
if (addon == NULL) {
|
if (addon == NULL) {
|
||||||
ERROR("MediaAddonServer::_AddOnAdded: failed to get add-on %s\n", path);
|
ERROR("MediaAddonServer::_AddOnAdded: failed to get add-on %s\n", path);
|
||||||
_DormantNodeManager->UnregisterAddon(id);
|
gDormantNodeManager->UnregisterAddOn(id);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -598,7 +598,7 @@ MediaAddonServer::_AddOnAdded(const char* path, ino_t fileNode)
|
|||||||
SendToServer(SERVER_RESCAN_DEFAULTS, &cmd, sizeof(cmd));
|
SendToServer(SERVER_RESCAN_DEFAULTS, &cmd, sizeof(cmd));
|
||||||
}
|
}
|
||||||
|
|
||||||
// we do not call _DormantNodeManager->PutAddon(id)
|
// we do not call gDormantNodeManager->PutAddOn(id)
|
||||||
// since it is done by _PutAddonIfPossible()
|
// since it is done by _PutAddonIfPossible()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -689,7 +689,7 @@ void
|
|||||||
MediaAddonServer::_PutAddonIfPossible(AddOnInfo& info)
|
MediaAddonServer::_PutAddonIfPossible(AddOnInfo& info)
|
||||||
{
|
{
|
||||||
if (info.addon && info.active_flavors.empty()) {
|
if (info.addon && info.active_flavors.empty()) {
|
||||||
_DormantNodeManager->PutAddon(info.id);
|
gDormantNodeManager->PutAddOn(info.id);
|
||||||
info.addon = NULL;
|
info.addon = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -809,7 +809,7 @@ MediaAddonServer::_AddOnRemoved(ino_t fileNode)
|
|||||||
fInfoMap.erase(foundInfo);
|
fInfoMap.erase(foundInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
_DormantNodeManager->UnregisterAddon(id);
|
gDormantNodeManager->UnregisterAddOn(id);
|
||||||
|
|
||||||
BPrivate::media::notifications::FlavorsChanged(id, 0, oldFlavorCount);
|
BPrivate::media::notifications::FlavorsChanged(id, 0, oldFlavorCount);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user