Global nodes can mow be released by the teams which created them.
git-svn-id: file:///srv/svn/repos/haiku/trunk/current@2923 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
2937222250
commit
54187cc6e8
@ -19,6 +19,7 @@
|
||||
class _BSlaveNodeStorageP;
|
||||
|
||||
namespace BPrivate { namespace media {
|
||||
class BMediaRosterEx;
|
||||
class TimeSourceObject;
|
||||
class SystemTimeSourceObject;
|
||||
struct TimeSourceTransmit;
|
||||
@ -100,12 +101,9 @@ virtual status_t TimeSourceOp(
|
||||
|
||||
private:
|
||||
|
||||
friend class _BMediaRosterP;
|
||||
friend class _BTimeSourceP;
|
||||
friend class _SysTimeSource;
|
||||
friend class BMediaNode;
|
||||
friend class BMediaRoster;
|
||||
friend class _ServerApp;
|
||||
friend class BPrivate::media::BMediaRosterEx;
|
||||
friend class BPrivate::media::TimeSourceObject;
|
||||
friend class BPrivate::media::SystemTimeSourceObject;
|
||||
|
||||
|
@ -97,6 +97,8 @@ enum {
|
||||
SERVER_REGISTER_BUFFER,
|
||||
SERVER_UNREGISTER_BUFFER,
|
||||
SERVER_RESCAN_DEFAULTS,
|
||||
SERVER_SET_NODE_CREATOR,
|
||||
SERVER_CHANGE_DORMANT_NODE_USECOUNT,
|
||||
SERVER_MESSAGE_END,
|
||||
NODE_MESSAGE_START = 0x200,
|
||||
|
||||
@ -228,6 +230,7 @@ struct addonserver_instantiate_dormant_node_request : public request_data
|
||||
{
|
||||
media_addon_id addonid;
|
||||
int32 flavorid;
|
||||
team_id creator_team;
|
||||
};
|
||||
|
||||
struct addonserver_instantiate_dormant_node_reply : public reply_data
|
||||
@ -665,7 +668,26 @@ struct server_unregister_app_reply : public reply_data
|
||||
{
|
||||
};
|
||||
|
||||
struct server_set_node_creator_request : public request_data
|
||||
{
|
||||
media_node_id node;
|
||||
team_id creator;
|
||||
};
|
||||
|
||||
struct server_set_node_creator_reply : public reply_data
|
||||
{
|
||||
};
|
||||
|
||||
struct server_change_dormant_node_usecount_request : public request_data
|
||||
{
|
||||
media_addon_id addon_id;
|
||||
int32 addon_flavor_id;
|
||||
int32 delta;
|
||||
};
|
||||
|
||||
struct server_change_dormant_node_usecount_reply : public reply_data
|
||||
{
|
||||
};
|
||||
|
||||
struct server_register_node_request : public request_data
|
||||
{
|
||||
@ -690,7 +712,8 @@ struct server_unregister_node_request : public request_data
|
||||
|
||||
struct server_unregister_node_reply : public reply_data
|
||||
{
|
||||
media_addon_id addon_id;
|
||||
media_addon_id addonid;
|
||||
int32 flavorid;
|
||||
};
|
||||
|
||||
struct server_get_live_node_info_request : public request_data
|
||||
|
@ -11,17 +11,27 @@
|
||||
namespace BPrivate {
|
||||
namespace media {
|
||||
|
||||
// To instantiate a dormant node in the current address space, we need to
|
||||
// either load the add-on from file and create a new BMediaAddOn class and
|
||||
// cache the BMediaAddOn after that for later reuse, or reuse the cached
|
||||
// BMediaAddOn if we already have one.
|
||||
// This is handled by the DormantNodeManager.
|
||||
//
|
||||
// GetAddon() will provide a ready to use BMediaAddOn, while
|
||||
// PutAddonDelayed() will unload it when it's no longer needed,
|
||||
// but will delay the unloading slightly, because it is called
|
||||
// from a node destructor of the loaded add-on.
|
||||
|
||||
class DormantNodeManager
|
||||
{
|
||||
public:
|
||||
DormantNodeManager();
|
||||
~DormantNodeManager();
|
||||
|
||||
// InstantiateDormantNode(const dormant_node_info & in_info, bool global, media_node * out_node);
|
||||
|
||||
// Be careful, GetAddon and PutAddon must be balanced.
|
||||
// Be careful, GetAddon and PutAddon[Delayed] must be balanced.
|
||||
BMediaAddOn *GetAddon(media_addon_id id);
|
||||
void PutAddon(media_addon_id id);
|
||||
void PutAddonDelayed(media_addon_id id);
|
||||
|
||||
// For use by media_addon_server only
|
||||
media_addon_id RegisterAddon(const char *path);
|
||||
|
@ -32,7 +32,16 @@ namespace BPrivate { namespace media {
|
||||
class BMediaRosterEx : public BMediaRoster
|
||||
{
|
||||
public:
|
||||
status_t InstantiateDormantNode(media_addon_id addonid, int32 flavorid, media_node *out_node);
|
||||
status_t SaveNodeConfiguration(BMediaNode *node);
|
||||
status_t LoadNodeConfiguration(media_addon_id addonid, int32 flavorid, BMessage *out_msg);
|
||||
|
||||
status_t IncrementDormantNodeUseCount(media_addon_id addonid, int32 flavorid);
|
||||
status_t DecrementDormantNodeUseCount(media_addon_id addonid, int32 flavorid);
|
||||
|
||||
status_t SetNodeCreator(media_node_id node, team_id creator);
|
||||
|
||||
status_t RegisterNode(BMediaNode * node, media_addon_id addonid, int32 flavorid);
|
||||
status_t InstantiateDormantNode(media_addon_id addonid, int32 flavorid, team_id creator, media_node *out_node);
|
||||
status_t GetDormantFlavorInfo(media_addon_id addonid, int32 flavorid, dormant_flavor_info *out_flavor);
|
||||
status_t GetNode(node_type type, media_node * out_node, int32 * out_input_id = NULL, BString * out_input_name = NULL);
|
||||
status_t SetNode(node_type type, const media_node *node, const dormant_node_info *info = NULL, const media_input *input = NULL);
|
||||
|
@ -130,6 +130,15 @@ DormantNodeManager::GetAddon(media_addon_id id)
|
||||
return addon;
|
||||
}
|
||||
|
||||
void
|
||||
DormantNodeManager::PutAddonDelayed(media_addon_id id)
|
||||
{
|
||||
// Called from a node destructor of the loaded media-add-on.
|
||||
// We must make sure that the media-add-on stays in memory
|
||||
// a couple of seconds longer.
|
||||
|
||||
UNIMPLEMENTED();
|
||||
}
|
||||
|
||||
void
|
||||
DormantNodeManager::PutAddon(media_addon_id id)
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include <FileInterface.h>
|
||||
#include <string.h>
|
||||
#include "debug.h"
|
||||
#include "MediaRosterEx.h"
|
||||
#include "DataExchange.h"
|
||||
#include "ServerInterface.h"
|
||||
#include "Notifications.h"
|
||||
@ -106,6 +107,7 @@ BMediaNode::~BMediaNode()
|
||||
if (fTimeSource) {
|
||||
fTimeSource->RemoveMe(this);
|
||||
fTimeSource->Release();
|
||||
fTimeSource = NULL;
|
||||
}
|
||||
|
||||
// Attention! We do not unregister TimeSourceObject nodes,
|
||||
@ -136,7 +138,9 @@ BMediaNode *
|
||||
BMediaNode::Release()
|
||||
{
|
||||
CALLED();
|
||||
if (atomic_add(&fRefCount,-1) == 1) {
|
||||
if (atomic_add(&fRefCount, -1) == 1) {
|
||||
TRACE("BMediaNode::Release() saving node %ld configuration\n", fNodeID);
|
||||
MediaRosterEx(BMediaRoster::Roster())->SaveNodeConfiguration(this);
|
||||
if (DeleteHook(this) != B_OK) {
|
||||
FATAL("BMediaNode::Release(): DeleteHook failed\n");
|
||||
return Acquire();
|
||||
@ -203,8 +207,8 @@ BMediaNode::TimeSource() const
|
||||
// If the node hasn't been assigned a time source
|
||||
// so far, we assign the system time source. This
|
||||
// can't be done in the BMediaNode constructor, since
|
||||
// a BTimeSource is also a BMediaNode that would be
|
||||
// a infinite loop... loop... loop... loop...
|
||||
// a BTimeSource is also a BMediaNode and that would be
|
||||
// an infinite loop... loop... loop... loop...
|
||||
|
||||
BMediaRoster *roster = BMediaRoster::Roster();
|
||||
status_t rv;
|
||||
|
@ -44,6 +44,57 @@ using namespace BPrivate::media;
|
||||
// DefaultDeleter will delete the BMediaRoster object in it's destructor.
|
||||
DefaultDeleter _deleter;
|
||||
|
||||
status_t
|
||||
BMediaRosterEx::SaveNodeConfiguration(BMediaNode *node)
|
||||
{
|
||||
BMediaAddOn *addon;
|
||||
media_addon_id addonid;
|
||||
int32 flavorid;
|
||||
addon = node->AddOn(&flavorid);
|
||||
if (!addon) {
|
||||
FATAL("BMediaRosterEx::SaveNodeConfiguration node %ld not instantiated from BMediaAddOn!\n");
|
||||
return B_ERROR;
|
||||
}
|
||||
addonid = addon->AddonID();
|
||||
|
||||
// XXX fix this
|
||||
printf("### BMediaRosterEx::SaveNodeConfiguration should save addon-id %ld, flavor-id %ld config NOW!\n", addonid, flavorid);
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
status_t
|
||||
BMediaRosterEx::LoadNodeConfiguration(media_addon_id addonid, int32 flavorid, BMessage *out_msg)
|
||||
{
|
||||
// XXX fix this
|
||||
out_msg->MakeEmpty(); // to be fully R5 compliant
|
||||
printf("### BMediaRosterEx::LoadNodeConfiguration should load addon-id %ld, flavor-id %ld config NOW!\n", addonid, flavorid);
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
status_t
|
||||
BMediaRosterEx::IncrementDormantNodeUseCount(media_addon_id addonid, int32 flavorid)
|
||||
{
|
||||
//perhaps rename all this from dormantnode into addon-flavor or instance
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
status_t
|
||||
BMediaRosterEx::DecrementDormantNodeUseCount(media_addon_id addonid, int32 flavorid)
|
||||
{
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
status_t
|
||||
BMediaRosterEx::SetNodeCreator(media_node_id node, team_id creator)
|
||||
{
|
||||
server_set_node_creator_request request;
|
||||
server_set_node_creator_reply reply;
|
||||
|
||||
request.node = node;
|
||||
request.creator = creator;
|
||||
return QueryServer(SERVER_SET_NODE_CREATOR, &request, sizeof(request), &reply, sizeof(reply));
|
||||
}
|
||||
|
||||
status_t
|
||||
BMediaRosterEx::GetNode(node_type type, media_node * out_node, int32 * out_input_id, BString * out_input_name)
|
||||
{
|
||||
@ -1354,25 +1405,39 @@ BMediaRoster::StopWatching(const BMessenger & where,
|
||||
status_t
|
||||
BMediaRoster::RegisterNode(BMediaNode * node)
|
||||
{
|
||||
printf("BMediaRoster::RegisterNode %p\n", node);
|
||||
CALLED();
|
||||
// addon-id = -1 (unused), addon-flavor-id = 0 (unused, too)
|
||||
return MediaRosterEx(this)->RegisterNode(node, -1, 0);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
BMediaRosterEx::RegisterNode(BMediaNode * node, media_addon_id addonid, int32 flavorid)
|
||||
{
|
||||
CALLED();
|
||||
if (node == NULL)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
status_t rv;
|
||||
BMediaAddOn *addon;
|
||||
int32 addon_flavor_id;
|
||||
media_addon_id addon_id;
|
||||
// some sanity check
|
||||
// I'm not sure if the media kit warrants to call BMediaNode::AddOn() here.
|
||||
// Perhaps we don't need it.
|
||||
{
|
||||
BMediaAddOn *addon;
|
||||
int32 addon_flavor_id;
|
||||
media_addon_id addon_id;
|
||||
addon_flavor_id = 0;
|
||||
addon = node->AddOn(&addon_flavor_id);
|
||||
addon_id = addon ? addon->AddonID() : -1;
|
||||
ASSERT(addonid == addon_id);
|
||||
ASSERT(flavorid == addon_flavor_id);
|
||||
}
|
||||
|
||||
addon_flavor_id = 0;
|
||||
addon = node->AddOn(&addon_flavor_id);
|
||||
addon_id = addon ? addon->AddonID() : -1;
|
||||
|
||||
status_t rv;
|
||||
server_register_node_request request;
|
||||
server_register_node_reply reply;
|
||||
|
||||
request.addon_id = addon_id;
|
||||
request.addon_flavor_id = addon_flavor_id;
|
||||
request.addon_id = addonid;
|
||||
request.addon_flavor_id = flavorid;
|
||||
strcpy(request.name, node->Name());
|
||||
request.kinds = node->Kinds();
|
||||
request.port = node->ControlPort();
|
||||
@ -1444,16 +1509,20 @@ BMediaRoster::UnregisterNode(BMediaNode * node)
|
||||
printf("BMediaRoster::UnregisterNode, trying to unregister reference counting disabled timesource, node %ld, port %ld, team %ld\n", node->ID(), node->ControlPort(), team);
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
if (node->fRefCount != 0) {
|
||||
FATAL("BMediaRoster::UnregisterNode: Warning node id %ld, name '%s' has local reference count of %ld\n", node->ID(), node->Name(), node->fRefCount);
|
||||
// no return here, we continue and unregister!
|
||||
}
|
||||
if (node->ID() == NODE_UNREGISTERED_ID) {
|
||||
FATAL("BMediaRoster::UnregisterNode: Warning node id %ld, name '%s' already unregistered\n", node->ID(), node->Name());
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
if (node->fRefCount != 0) {
|
||||
FATAL("BMediaRoster::UnregisterNode: Warning node id %ld, name '%s' has local reference count of %ld\n", node->ID(), node->Name(), node->fRefCount);
|
||||
// no return here, we continue and unregister!
|
||||
}
|
||||
|
||||
// Calling BMediaAddOn::GetConfigurationFor(BMediaNode *node, BMessage *config)
|
||||
// if this node was instanciated by an add-on needs to be done *somewhere*
|
||||
// We can't do it here because it is already to late (destructor of the node
|
||||
// might have been called).
|
||||
|
||||
server_unregister_node_request request;
|
||||
server_unregister_node_reply reply;
|
||||
status_t rv;
|
||||
@ -1470,13 +1539,19 @@ BMediaRoster::UnregisterNode(BMediaNode * node)
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (reply.addon_id != -1) {
|
||||
// XXX This is a real big problem!
|
||||
// XXX UnregisterNode is called by a dormant node itself, but UnregisterNode will
|
||||
// XXX unload the dormant node image from memory when calling PutAddon
|
||||
// _DormantNodeManager->PutAddon(reply.addon_id);
|
||||
if (reply.addonid != -1) {
|
||||
// Small problem here, we can't use DormantNodeManager::PutAddon(), as
|
||||
// UnregisterNode() is called by a dormant node itself (by the destructor).
|
||||
// The add-on that contains the node needs to remain in memory until the
|
||||
// destructor execution is finished.
|
||||
// DormantNodeManager::PutAddonDelayed() will delay unloading.
|
||||
_DormantNodeManager->PutAddonDelayed(reply.addonid);
|
||||
|
||||
// XXX do "possible_count" increment in the server.
|
||||
rv = MediaRosterEx(this)->DecrementDormantNodeUseCount(reply.addonid, reply.flavorid);
|
||||
if (rv != B_OK) {
|
||||
FATAL("BMediaRoster::UnregisterNode: DecrementDormantNodeUseCount failed\n");
|
||||
// this is really a problem, but we can't fail now
|
||||
}
|
||||
}
|
||||
|
||||
// we are a friend class of BMediaNode and invalidate this member variable
|
||||
@ -1651,25 +1726,25 @@ BMediaRoster::GetDormantNodes(dormant_node_info * out_info,
|
||||
* Checks concerning global/local are not done here.
|
||||
*/
|
||||
status_t
|
||||
BMediaRosterEx::InstantiateDormantNode(media_addon_id addonid, int32 flavorid, media_node *out_node)
|
||||
BMediaRosterEx::InstantiateDormantNode(media_addon_id addonid, int32 flavorid, team_id creator, media_node *out_node)
|
||||
{
|
||||
// to instantiate a dormant node in the current address space, we need to
|
||||
// either load the add-on from file and create a new BMediaAddOn class, or
|
||||
// reuse the cached BMediaAddOn from a previous call
|
||||
// call BMediaAddOn::InstantiateNodeFor()
|
||||
// and cache the BMediaAddOn after that for later reuse.
|
||||
// BeOS R5 does not seem to delete it when the application quits
|
||||
// This function is always called from the correct context, if the node
|
||||
// is supposed to be global, it is called from the media_addon_server.
|
||||
|
||||
// if B_FLAVOR_IS_GLOBAL, we need to use the BMediaAddOn object that
|
||||
// resides in the media_addon_server
|
||||
|
||||
// RegisterNode() must be called for nodes instantiated from add-ons,
|
||||
// since the media kit warrants that it's done automatically.
|
||||
|
||||
// dormant_node_info::addon Indicates the ID number of the media add-on in which the node resides.
|
||||
// dormant_node_info::flavor_id Indicates the internal ID number that the add-on uses to identify the flavor,
|
||||
// this is the number that was published by BMediaAddOn::GetFlavorAt() int the
|
||||
// flavor_info::internal_id field.
|
||||
|
||||
// addonid Indicates the ID number of the media add-on in which the node resides.
|
||||
// flavorid Indicates the internal ID number that the add-on uses to identify the flavor,
|
||||
// this is the number that was published by BMediaAddOn::GetFlavorAt() in the
|
||||
// flavor_info::internal_id field.
|
||||
// creator The creator team is -1 if nodes are created locally. If created globally,
|
||||
// it will contain (while called in media_addon_server context) the team-id of
|
||||
// the team that requested the instantiation.
|
||||
|
||||
printf("BMediaRosterEx::InstantiateDormantNode: addon-id %ld, flavor_id %ld\n", addonid, flavorid);
|
||||
|
||||
// Get flavor_info from the server
|
||||
@ -1691,32 +1766,70 @@ BMediaRosterEx::InstantiateDormantNode(media_addon_id addonid, int32 flavorid, m
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
// Now we need to try to increment the use count of this addon flavor
|
||||
// in the server. This can fail if the total number instances of this
|
||||
// flavor is limited.
|
||||
rv = IncrementDormantNodeUseCount(addonid, flavorid);
|
||||
if (rv != B_OK) {
|
||||
FATAL("BMediaRosterEx::InstantiateDormantNode error: can't create more nodes for addon-id %ld, flavour-id %ld\n", addonid, flavorid);
|
||||
// Put the addon back into the pool
|
||||
_DormantNodeManager->PutAddon(addonid);
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
BMessage config;
|
||||
// XXX get configuration from server and do "possible_count" decrement in the server.
|
||||
rv = LoadNodeConfiguration(addonid, flavorid, &config);
|
||||
if (rv != B_OK) {
|
||||
FATAL("BMediaRosterEx::InstantiateDormantNode: couldn't load configuration for addon-id %ld, flavor-id %ld\n", addonid, flavorid);
|
||||
// do not return, this is a minor problem, not a reason to fail
|
||||
}
|
||||
|
||||
BMediaNode *node;
|
||||
status_t out_error;
|
||||
|
||||
out_error = B_OK;
|
||||
node = addon->InstantiateNodeFor(&node_info, &config, &out_error);
|
||||
if (!node) {
|
||||
FATAL("BMediaRosterEx::InstantiateDormantNode: InstantiateNodeFor failed\n");
|
||||
// XXX do "possible_count" increment in the server.
|
||||
// Put the addon back into the pool
|
||||
_DormantNodeManager->PutAddon(addonid);
|
||||
return B_ERROR;
|
||||
// We must decrement the use count of this addon flavor in the
|
||||
// server to compensate the increment done in the beginning.
|
||||
rv = DecrementDormantNodeUseCount(addonid, flavorid);
|
||||
if (rv != B_OK) {
|
||||
FATAL("BMediaRosterEx::InstantiateDormantNode: DecrementDormantNodeUseCount failed\n");
|
||||
}
|
||||
return (out_error != B_OK) ? out_error : B_ERROR;
|
||||
}
|
||||
rv = RegisterNode(node);
|
||||
|
||||
rv = RegisterNode(node, addonid, flavorid);
|
||||
if (rv != B_OK) {
|
||||
FATAL("BMediaRosterEx::InstantiateDormantNode: RegisterNode failed\n");
|
||||
delete node;
|
||||
// XXX do "possible_count" increment in the server.
|
||||
// Put the addon back into the pool
|
||||
_DormantNodeManager->PutAddon(addonid);
|
||||
// We must decrement the use count of this addon flavor in the
|
||||
// server to compensate the increment done in the beginning.
|
||||
rv = DecrementDormantNodeUseCount(addonid, flavorid);
|
||||
if (rv != B_OK) {
|
||||
FATAL("BMediaRosterEx::InstantiateDormantNode: DecrementDormantNodeUseCount failed\n");
|
||||
}
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
// XXX we must remember in_info.addon and call
|
||||
// XXX _DormantNodeManager->PutAddon when the
|
||||
// XXX node is unregistered
|
||||
// should be handled by RegisterNode() and UnregisterNode() now
|
||||
if (creator != -1) {
|
||||
// send a message to the server to assign team "creator" as creator of node "node->ID()"
|
||||
printf("!!! BMediaRosterEx::InstantiateDormantNode assigning team %ld as creator of node %ld\n", creator, node->ID());
|
||||
rv = MediaRosterEx(this)->SetNodeCreator(node->ID(), creator);
|
||||
if (rv != B_OK) {
|
||||
FATAL("BMediaRosterEx::InstantiateDormantNode failed to assign team %ld as creator of node %ld\n", creator, node->ID());
|
||||
// do not return, this is a minor problem, not a reason to fail
|
||||
}
|
||||
}
|
||||
|
||||
// RegisterNode() does remember the add-on id in the server
|
||||
// and UnregisterNode() will call DormantNodeManager::PutAddon()
|
||||
// when the node is unregistered.
|
||||
|
||||
*out_node = node->Node();
|
||||
|
||||
@ -1778,7 +1891,7 @@ BMediaRoster::InstantiateDormantNode(const dormant_node_info & in_info,
|
||||
FATAL("BMediaRoster::InstantiateDormantNode Error: requested B_FLAVOR_IS_GLOBAL, but dormant node has B_FLAVOR_IS_LOCAL\n");
|
||||
return B_BAD_VALUE;
|
||||
}
|
||||
//#if 0
|
||||
|
||||
// If either the node, or the caller requested to make the instance global
|
||||
// we will do it by forwarding this request into the media_addon_server, which
|
||||
// in turn will call BMediaRosterEx::InstantiateDormantNode to create the node
|
||||
@ -1792,6 +1905,7 @@ BMediaRoster::InstantiateDormantNode(const dormant_node_info & in_info,
|
||||
status_t rv;
|
||||
request.addonid = in_info.addon;
|
||||
request.flavorid = in_info.flavor_id;
|
||||
request.creator_team = team; // creator team is allowed to also release global nodes
|
||||
rv = QueryAddonServer(ADDONSERVER_INSTANTIATE_DORMANT_NODE, &request, sizeof(request), &reply, sizeof(reply));
|
||||
if (rv == B_OK) {
|
||||
*out_node = reply.node;
|
||||
@ -1802,10 +1916,9 @@ BMediaRoster::InstantiateDormantNode(const dormant_node_info & in_info,
|
||||
|
||||
} else {
|
||||
|
||||
return MediaRosterEx(this)->InstantiateDormantNode(in_info.addon, in_info.flavor_id, out_node);
|
||||
// creator team = -1, as this is a local node
|
||||
return MediaRosterEx(this)->InstantiateDormantNode(in_info.addon, in_info.flavor_id, -1, out_node);
|
||||
}
|
||||
//#endif
|
||||
// return MediaRosterEx(this)->InstantiateDormantNode(in_info.addon, in_info.flavor_id, out_node);
|
||||
}
|
||||
|
||||
|
||||
@ -2175,8 +2288,10 @@ BMediaRoster::MessageReceived(BMessage * message)
|
||||
BMediaNode *node;
|
||||
message->FindPointer("node", reinterpret_cast<void **>(&node));
|
||||
|
||||
TRACE("BMediaRoster::MessageReceived NODE_FINAL_RELEASE releasing node %p\n", node);
|
||||
TRACE("BMediaRoster::MessageReceived NODE_FINAL_RELEASE saving node %ld configuration\n", node->ID());
|
||||
MediaRosterEx(BMediaRoster::Roster())->SaveNodeConfiguration(node);
|
||||
|
||||
TRACE("BMediaRoster::MessageReceived NODE_FINAL_RELEASE releasing node %ld\n", node->ID());
|
||||
node->DeleteHook(node); // we don't call Release(), see above!
|
||||
return;
|
||||
}
|
||||
|
@ -217,6 +217,13 @@ void AppManager::TerminateAddonServer()
|
||||
}
|
||||
}
|
||||
|
||||
team_id
|
||||
AppManager::AddonServer()
|
||||
{
|
||||
// XXX not sure about locking
|
||||
return fAddonServer;
|
||||
}
|
||||
|
||||
void AppManager::Dump()
|
||||
{
|
||||
BAutolock lock(fLocker);
|
||||
|
@ -17,6 +17,7 @@ public:
|
||||
bool HasTeam(team_id);
|
||||
void StartAddonServer();
|
||||
void TerminateAddonServer();
|
||||
team_id AddonServer();
|
||||
|
||||
void Dump();
|
||||
|
||||
|
@ -13,6 +13,9 @@
|
||||
#include <MediaAddOn.h>
|
||||
#include "debug.h"
|
||||
#include "NodeManager.h"
|
||||
#include "AppManager.h"
|
||||
|
||||
extern AppManager *gAppManager;
|
||||
|
||||
const char *get_node_type(node_type t);
|
||||
|
||||
@ -51,6 +54,7 @@ NodeManager::RegisterNode(media_node_id *nodeid, media_addon_id addon_id, int32
|
||||
rn.kinds = kinds;
|
||||
rn.port = port;
|
||||
rn.team = team;
|
||||
rn.creator = -1; // will be set later
|
||||
rn.globalrefcount = 1;
|
||||
rn.teamrefcount.Insert(team, 1);
|
||||
|
||||
@ -64,7 +68,7 @@ NodeManager::RegisterNode(media_node_id *nodeid, media_addon_id addon_id, int32
|
||||
|
||||
|
||||
status_t
|
||||
NodeManager::UnregisterNode(media_addon_id *addon_id, media_node_id nodeid, team_id team)
|
||||
NodeManager::UnregisterNode(media_addon_id *addonid, int32 *flavorid, media_node_id nodeid, team_id team)
|
||||
{
|
||||
BAutolock lock(fLocker);
|
||||
bool b;
|
||||
@ -83,10 +87,11 @@ NodeManager::UnregisterNode(media_addon_id *addon_id, media_node_id nodeid, team
|
||||
FATAL("!!! NodeManager::UnregisterNode: Error: node %ld, team %ld, globalrefcount %ld\n", nodeid, team, rn->globalrefcount);
|
||||
//return B_ERROR;
|
||||
}
|
||||
*addon_id = rn->addon_id;
|
||||
*addonid = rn->addon_id;
|
||||
*flavorid = rn->addon_flavor_id;
|
||||
b = fRegisteredNodeMap->Remove(nodeid);
|
||||
ASSERT(b);
|
||||
TRACE("NodeManager::UnregisterNode leave: node %ld, addon_id %ld, team %ld\n", nodeid, *addon_id, team);
|
||||
TRACE("NodeManager::UnregisterNode leave: node %ld, addon_id %ld, flavor_id %ld team %ld\n", nodeid, *addonid, *flavorid, team);
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
@ -135,8 +140,20 @@ NodeManager::DecrementGlobalRefCount(media_node_id nodeid, team_id team)
|
||||
int32 *count;
|
||||
b = rn->teamrefcount.Get(team, &count);
|
||||
if (!b) {
|
||||
FATAL("!!! NodeManager::DecrementGlobalRefCount: Error: node %ld has no team %ld references\n", nodeid, team);
|
||||
return B_ERROR;
|
||||
// Normally it is an error to release a node in another team. But we make one
|
||||
// exception. If the node is global, and the creator team tries to release it,
|
||||
// we will release it in the the media_addon_server.
|
||||
team_id addon_server_team;
|
||||
addon_server_team = gAppManager->AddonServer();
|
||||
if (rn->creator == team && rn->teamrefcount.Get(addon_server_team, &count)) {
|
||||
printf("!!! NodeManager::DecrementGlobalRefCount doing global release!\n");
|
||||
rn->creator = -1; //invalidate!
|
||||
team = addon_server_team; //redirect!
|
||||
// the count variable was already redirected in if() statement above.
|
||||
} else {
|
||||
FATAL("!!! NodeManager::DecrementGlobalRefCount: Error: node %ld has no team %ld references\n", nodeid, team);
|
||||
return B_ERROR;
|
||||
}
|
||||
}
|
||||
*count -= 1;
|
||||
int32 debug_count = *count;
|
||||
@ -155,6 +172,30 @@ NodeManager::DecrementGlobalRefCount(media_node_id nodeid, team_id team)
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
status_t
|
||||
NodeManager::SetNodeCreator(media_node_id nodeid, team_id creator)
|
||||
{
|
||||
BAutolock lock(fLocker);
|
||||
registered_node *rn;
|
||||
bool b;
|
||||
status_t rv;
|
||||
|
||||
TRACE("NodeManager::SetNodeCreator node %ld, creator %ld\n", nodeid, creator);
|
||||
|
||||
b = fRegisteredNodeMap->Get(nodeid, &rn);
|
||||
if (!b) {
|
||||
FATAL("NodeManager::SetNodeCreator: Error: node %ld not found\n", nodeid);
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
if (rn->creator != -1) {
|
||||
FATAL("NodeManager::SetNodeCreator: Error: node %ld is already assigned creator %ld\n", nodeid, rn->creator);
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
rn->creator = creator;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
void
|
||||
NodeManager::FinalReleaseNode(media_node_id nodeid)
|
||||
@ -658,6 +699,11 @@ NodeManager::CleanupTeam(team_id team)
|
||||
|
||||
registered_node *rn;
|
||||
for (fRegisteredNodeMap->Rewind(); fRegisteredNodeMap->GetNext(&rn); ) {
|
||||
// if the gone team was the creator of some global dormant node instance, we now invalidate that
|
||||
if (rn->creator == team) {
|
||||
rn->creator = -1;
|
||||
// fall through
|
||||
}
|
||||
// if the team hosting this node is gone, remove node from database
|
||||
if (rn->team == team) {
|
||||
FATAL("NodeManager::CleanupTeam: removing node id %ld, team %ld\n", rn->nodeid, team);
|
||||
|
@ -16,7 +16,8 @@ struct registered_node
|
||||
char name[B_MEDIA_NAME_LENGTH];
|
||||
uint64 kinds;
|
||||
port_id port;
|
||||
team_id team;
|
||||
team_id creator; // team that created the node
|
||||
team_id team; // team that contains the node object
|
||||
int32 globalrefcount;
|
||||
Map<team_id, int32> teamrefcount;
|
||||
List<media_input> inputlist;
|
||||
@ -55,7 +56,7 @@ public:
|
||||
|
||||
/* Management of live nodes */
|
||||
status_t RegisterNode(media_node_id *nodeid, media_addon_id addon_id, int32 addon_flavor_id, const char *name, uint64 kinds, port_id port, team_id team);
|
||||
status_t UnregisterNode(media_addon_id *addon_id, media_node_id nodeid, team_id team);
|
||||
status_t UnregisterNode(media_addon_id *addonid, int32 *flavorid, media_node_id nodeid, team_id team);
|
||||
status_t GetCloneForId(media_node *node, media_node_id nodeid, team_id team);
|
||||
status_t GetClone(media_node *node, char *input_name, int32 *input_id, node_type type, team_id team);
|
||||
status_t ReleaseNode(const media_node &node, team_id team);
|
||||
@ -68,6 +69,7 @@ public:
|
||||
status_t GetDormantNodeInfo(dormant_node_info *node_info, const media_node &node);
|
||||
status_t IncrementGlobalRefCount(media_node_id nodeid, team_id team);
|
||||
status_t DecrementGlobalRefCount(media_node_id nodeid, team_id team);
|
||||
status_t SetNodeCreator(media_node_id nodeid, team_id creator);
|
||||
void FinalReleaseNode(media_node_id nodeid);
|
||||
|
||||
/* Add media_node_id of all live nodes to the message
|
||||
|
@ -306,7 +306,7 @@ ServerApp::HandleMessage(int32 code, void *data, size_t size)
|
||||
{
|
||||
const server_unregister_node_request *request = reinterpret_cast<const server_unregister_node_request *>(data);
|
||||
server_unregister_node_reply reply;
|
||||
rv = gNodeManager->UnregisterNode(&reply.addon_id, request->nodeid, request->team);
|
||||
rv = gNodeManager->UnregisterNode(&reply.addonid, &reply.flavorid, request->nodeid, request->team);
|
||||
request->SendReply(rv, &reply, sizeof(reply));
|
||||
break;
|
||||
}
|
||||
@ -471,6 +471,15 @@ ServerApp::HandleMessage(int32 code, void *data, size_t size)
|
||||
break;
|
||||
}
|
||||
|
||||
case SERVER_SET_NODE_CREATOR:
|
||||
{
|
||||
const server_set_node_creator_request *request = reinterpret_cast<const server_set_node_creator_request *>(data);
|
||||
server_set_node_creator_reply reply;
|
||||
rv = gNodeManager->SetNodeCreator(request->node, request->creator);
|
||||
request->SendReply(rv, &reply, sizeof(reply));
|
||||
break;
|
||||
}
|
||||
|
||||
case SERVER_GET_SHARED_BUFFER_AREA:
|
||||
{
|
||||
const server_get_shared_buffer_area_request *request = reinterpret_cast<const server_get_shared_buffer_area_request *>(data);
|
||||
|
@ -86,7 +86,7 @@ MediaAddonServer::HandleMessage(int32 code, const void *data, size_t size)
|
||||
const addonserver_instantiate_dormant_node_request *request = static_cast<const addonserver_instantiate_dormant_node_request *>(data);
|
||||
addonserver_instantiate_dormant_node_reply reply;
|
||||
status_t rv;
|
||||
rv = MediaRosterEx(mediaroster)->InstantiateDormantNode(request->addonid, request->flavorid, &reply.node);
|
||||
rv = MediaRosterEx(mediaroster)->InstantiateDormantNode(request->addonid, request->flavorid, request->creator_team, &reply.node);
|
||||
request->SendReply(rv, &reply, sizeof(reply));
|
||||
break;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user