From 9e9417d20596827f8c375ffd90b7a01cae1c0c4c Mon Sep 17 00:00:00 2001 From: beveloper Date: Sat, 5 Oct 2002 13:02:26 +0000 Subject: [PATCH] more BMediaRoster functionality git-svn-id: file:///srv/svn/repos/haiku/trunk/current@1381 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- headers/private/media/DataExchange.h | 128 ++++++++++- src/kits/media/BufferConsumer.cpp | 6 +- src/kits/media/BufferProducer.cpp | 4 +- src/kits/media/MediaNode.cpp | 40 ++-- src/kits/media/MediaRoster.cpp | 330 +++++++++++++++++++++++---- src/servers/media/ServerInterface.h | 21 -- src/servers/media/media_server.cpp | 81 ++++++- 7 files changed, 510 insertions(+), 100 deletions(-) diff --git a/headers/private/media/DataExchange.h b/headers/private/media/DataExchange.h index 733c03db49..c5b1d86625 100644 --- a/headers/private/media/DataExchange.h +++ b/headers/private/media/DataExchange.h @@ -71,15 +71,24 @@ enum { SERVER_SET_NODE, SERVER_PUBLISH_INPUTS, SERVER_PUBLISH_OUTPUTS, + SERVER_NODE_ID_FOR, + SERVER_GET_LIVE_NODE_INFO, + SERVER_GET_LIVE_NODES, + SERVER_GET_NODE_FOR, + SERVER_RELEASE_NODE, + SERVER_REGISTER_NODE, + SERVER_UNREGISTER_NODE, CONSUMER_GET_NEXT_INPUT = 0x2000, CONSUMER_DISPOSE_INPUT_COOKIE, CONSUMER_ACCEPT_FORMAT, CONSUMER_CONNECTED, + CONSUMER_DISCONNECTED, PRODUCER_GET_NEXT_OUTPUT = 0x3000, PRODUCER_DISPOSE_OUTPUT_COOKIE, PRODUCER_FORMAT_PROPOSAL, PRODUCER_PREPARE_TO_CONNECT, PRODUCER_CONNECT, + PRODUCER_DISCONNECT, }; // used by SERVER_GET_NODE and SERVER_SET_NODE @@ -102,6 +111,12 @@ enum MAX_INPUTS = 48, }; +// used by SERVER_GET_LIVE_NODES +enum +{ + MAX_LIVE_INFO = 62, +}; + struct addonserver_instantiate_dormant_node_request : public request_data { dormant_node_info info; @@ -130,6 +145,7 @@ struct server_set_node_reply : public reply_data struct server_get_node_request : public request_data { node_type type; + team_id team; }; struct server_get_node_reply : public reply_data @@ -208,7 +224,9 @@ struct server_publish_inputs_request : public request_data { media_node node; int32 count; - area_id area; // if count > MAX_INPUTS, inputs are in the area + area_id area; // if count > MAX_INPUTS, inputs are in the area + // area is created in the server, and also deleted + // in the server after the reply has been received media_input inputs[MAX_INPUTS]; }; @@ -268,4 +286,112 @@ struct consumer_dispose_input_cookie_reply : public reply_data { }; +struct consumer_disconnected_request : public request_data +{ + media_source source; + media_destination destination; +}; + +struct consumer_disconnected_reply : public reply_data +{ +}; + +struct producer_disconnect_request : public request_data +{ + media_source source; + media_destination destination; +}; + +struct producer_disconnect_reply : public reply_data +{ +}; + +struct server_register_node_request : public request_data +{ + media_addon_id addon_id; + int32 addon_flavor_id; + char name[B_MEDIA_NAME_LENGTH]; + uint64 kinds; + port_id port; + team_id team; +}; + +struct server_register_node_reply : public reply_data +{ + media_node_id nodeid; +}; + +struct server_unregister_node_request : public request_data +{ + media_node_id nodeid; + team_id team; +}; + +struct server_unregister_node_reply : public reply_data +{ + media_addon_id addon_id; +}; + +struct server_get_live_node_info_request : public request_data +{ + media_node node; +}; + +struct server_get_live_node_info_reply : public reply_data +{ + live_node_info live_info; +}; + +struct server_get_live_nodes_request : public request_data +{ + int32 maxcount; + bool has_input; + bool has_output; + bool has_name; + media_format inputformat; + media_format outputformat; + char name[B_MEDIA_NAME_LENGTH + 1]; // 1 for a trailing "*" + uint64 require_kinds; +}; + +struct server_get_live_nodes_reply : public reply_data +{ + int32 count; + area_id area; // if count > MAX_LIVE_INFO, live_node_infos are in the area + // area is created in the server, but deleted in the application + live_node_info live_info[MAX_LIVE_INFO]; +}; + +struct server_node_id_for_request : public request_data +{ + port_id port; +}; + +struct server_node_id_for_reply : public reply_data +{ + media_node_id nodeid; +}; + +struct server_get_node_for_request : public request_data +{ + media_node_id nodeid; + team_id team; +}; + +struct server_get_node_for_reply : public reply_data +{ + media_node clone; +}; + +struct server_release_node_request : public request_data +{ + media_node node; + team_id team; +}; + +struct server_release_node_reply : public reply_data +{ +}; + + #endif // _DATA_EXCHANGE_H diff --git a/src/kits/media/BufferConsumer.cpp b/src/kits/media/BufferConsumer.cpp index 5443497ed3..bed3f24adf 100644 --- a/src/kits/media/BufferConsumer.cpp +++ b/src/kits/media/BufferConsumer.cpp @@ -395,8 +395,10 @@ BBufferConsumer::HandleMessage(int32 message, case CONSUMER_DISCONNECTED: { - const xfer_consumer_disconnected *request = (const xfer_consumer_disconnected *)rawdata; - Disconnected(request->producer, request->where); + const consumer_disconnected_request *request = (const consumer_disconnected_request *)rawdata; + consumer_disconnected_reply reply; + Disconnected(request->source, request->destination); + request->SendReply(B_OK, &reply, sizeof(reply)); return B_OK; } diff --git a/src/kits/media/BufferProducer.cpp b/src/kits/media/BufferProducer.cpp index 8246d44234..fa6aae600f 100644 --- a/src/kits/media/BufferProducer.cpp +++ b/src/kits/media/BufferProducer.cpp @@ -149,8 +149,10 @@ BBufferProducer::HandleMessage(int32 message, case PRODUCER_DISCONNECT: { - const xfer_producer_disconnect *request = (const xfer_producer_disconnect *)rawdata; + const producer_disconnect_request *request = (const producer_disconnect_request *)rawdata; + producer_disconnect_reply reply; Disconnect(request->source, request->destination); + request->SendReply(B_OK, &reply, sizeof(reply)); return B_OK; } diff --git a/src/kits/media/MediaNode.cpp b/src/kits/media/MediaNode.cpp index f0f7970d82..2d6f976f5f 100644 --- a/src/kits/media/MediaNode.cpp +++ b/src/kits/media/MediaNode.cpp @@ -277,7 +277,7 @@ extern "C" void __10BMediaNodePCclUl(BMediaNode *self, const char *name, media_n BMediaNode::BMediaNode(const char *name) { CALLED(); - __10BMediaNodePCclUl(this,name,0,0); + __10BMediaNodePCclUl(this,name,-1,0); } @@ -415,44 +415,44 @@ BMediaNode::SetTimeSource(BTimeSource *time_source) /* virtual */ status_t BMediaNode::HandleMessage(int32 message, - const void *rawdata, + const void *data, size_t size) { CALLED(); switch (message) { case NODE_START: { - const xfer_node_start *data = (const xfer_node_start *)rawdata; - Start(data->performance_time); + const xfer_node_start *request = (const xfer_node_start *)data; + Start(request->performance_time); return B_OK; } case NODE_STOP: { - const xfer_node_stop *data = (const xfer_node_stop *)rawdata; - Stop(data->performance_time, data->immediate); + const xfer_node_stop *request = (const xfer_node_stop *)data; + Stop(request->performance_time, request->immediate); return B_OK; } case NODE_SEEK: { - const xfer_node_seek *data = (const xfer_node_seek *)rawdata; - Seek(data->media_time, data->performance_time); + const xfer_node_seek *request = (const xfer_node_seek *)data; + Seek(request->media_time, request->performance_time); return B_OK; } case NODE_SET_RUN_MODE: { - const xfer_node_set_run_mode *data = (const xfer_node_set_run_mode *)rawdata; - fRunMode = data->mode; + const xfer_node_set_run_mode *request = (const xfer_node_set_run_mode *)data; + fRunMode = request->mode; SetRunMode(fRunMode); return B_OK; } case NODE_TIME_WARP: { - const xfer_node_time_warp *data = (const xfer_node_time_warp *)rawdata; - TimeWarp(data->at_real_time,data->to_performance_time); + const xfer_node_time_warp *request = (const xfer_node_time_warp *)data; + TimeWarp(request->at_real_time,request->to_performance_time); return B_OK; } @@ -461,22 +461,14 @@ BMediaNode::HandleMessage(int32 message, Preroll(); return B_OK; } - - case NODE_REGISTERED: - { - const xfer_node_registered *data = (const xfer_node_registered *)rawdata; - fNodeID = data->node_id; - NodeRegistered(); - return B_OK; - } case NODE_SET_TIMESOURCE: { - const xfer_node_set_timesource *data = (const xfer_node_set_timesource *)rawdata; + const xfer_node_set_timesource *request = (const xfer_node_set_timesource *)data; bool first = (fTimeSourceID == 0); if (fTimeSource) fTimeSource->Release(); - fTimeSourceID = data->timesource_id; + fTimeSourceID = request->timesource_id; fTimeSource = 0; // XXX create timesource object here fTimeSource = new _SysTimeSource; if (!first) @@ -486,8 +478,8 @@ BMediaNode::HandleMessage(int32 message, case NODE_REQUEST_COMPLETED: { - const xfer_node_request_completed *data = (const xfer_node_request_completed *)rawdata; - RequestCompleted(data->info); + const xfer_node_request_completed *request = (const xfer_node_request_completed *)data; + RequestCompleted(request->info); return B_OK; } diff --git a/src/kits/media/MediaRoster.cpp b/src/kits/media/MediaRoster.cpp index e7a85c5b47..83cf11108a 100644 --- a/src/kits/media/MediaRoster.cpp +++ b/src/kits/media/MediaRoster.cpp @@ -13,6 +13,7 @@ #include #undef DEBUG #define DEBUG 3 +#include #include "debug.h" #include "TStack.h" #include "PortPool.h" @@ -58,6 +59,7 @@ GetNode(node_type type, media_node * out_node, int32 * out_input_id, BString * o status_t rv; request.type = type; + request.team = team; rv = QueryServer(SERVER_GET_NODE, &request, sizeof(request), &reply, sizeof(reply)); if (rv != B_OK) return rv; @@ -380,8 +382,25 @@ status_t BMediaRoster::GetNodeFor(media_node_id node, media_node * clone) { - UNIMPLEMENTED(); - return B_ERROR; + CALLED(); + if (clone == NULL) + return B_BAD_VALUE; + if (node <= 0) + return B_MEDIA_BAD_NODE; + + server_get_node_for_request request; + server_get_node_for_reply reply; + status_t rv; + + request.nodeid = node; + request.team = team; + + rv = QueryServer(SERVER_GET_NODE_FOR, &request, sizeof(request), &reply, sizeof(reply)); + if (rv != B_OK) + return rv; + + *clone = reply.clone; + return B_OK; } @@ -396,10 +415,18 @@ BMediaRoster::GetSystemTimeSource(media_node * clone) status_t BMediaRoster::ReleaseNode(const media_node & node) { - UNIMPLEMENTED(); - return B_ERROR; -} + CALLED(); + if (node.node <= 0) + return B_MEDIA_BAD_NODE; + server_release_node_request request; + server_release_node_reply reply; + + request.node = node; + request.team = team; + + return QueryServer(SERVER_RELEASE_NODE, &request, sizeof(request), &reply, sizeof(reply)); +} BTimeSource * @@ -433,10 +460,14 @@ BMediaRoster::Connect(const media_source & from, CALLED(); if (io_format == NULL || out_output == NULL || out_input == NULL) return B_BAD_VALUE; - if (from == media_source::null) + if (from == media_source::null) { + TRACE("BMediaRoster::Connect: media_source invalid\n"); return B_MEDIA_BAD_SOURCE; - if (to == media_destination::null) + } + if (to == media_destination::null) { + TRACE("BMediaRoster::Connect: media_destination invalid\n"); return B_MEDIA_BAD_DESTINATION; + } status_t rv; producer_format_proposal_request request1; @@ -537,23 +568,89 @@ BMediaRoster::Connect(const media_source & from, // XXX register connection with server + // XXX we should just send a notification, instead of republishing all endpoints + Stack outstack; + Stack instack; + if (B_OK == GetAllOutputs(out_output->node , &outstack)) + PublishOutputs(out_output->node , &outstack); + if (B_OK == GetAllInputs(out_input->node , &instack)) + PublishInputs(out_input->node, &instack); // XXX if (mute) BBufferProducer::EnableOutput(false) + if (in_flags & B_CONNECT_MUTED) { + } + // send a notification + BPrivate::media::notifications::ConnectionMade(*out_input, *out_output, *io_format); + return B_OK; }; status_t -BMediaRoster::Disconnect(media_node_id source_node, +BMediaRoster::Disconnect(media_node_id source_nodeid, const media_source & source, - media_node_id destination_node, + media_node_id destination_nodeid, const media_destination & destination) { - UNIMPLEMENTED(); - return B_ERROR; + CALLED(); + if (source_nodeid <= 0) { + TRACE("BMediaRoster::Disconnect: source media_node_id invalid\n"); + return B_MEDIA_BAD_SOURCE; + } + if (destination_nodeid <= 0) { + TRACE("BMediaRoster::Disconnect: source media_node_id invalid\n"); + return B_MEDIA_BAD_DESTINATION; + } + if (source == media_source::null) { + TRACE("BMediaRoster::Disconnect: media_source invalid\n"); + return B_MEDIA_BAD_SOURCE; + } + if (destination == media_destination::null) { + TRACE("BMediaRoster::Disconnect: media_destination invalid\n"); + return B_MEDIA_BAD_DESTINATION; + } + + producer_disconnect_request request2; + producer_disconnect_reply reply2; + consumer_disconnected_request request1; + consumer_disconnected_reply reply1; + status_t rv1, rv2; + + // XXX we should ask the server if this connection really exists + + request1.source = source; + request1.destination = destination; + request2.source = source; + request2.destination = destination; + + rv1 = QueryPort(source.port, PRODUCER_DISCONNECT, &request1, sizeof(request1), &reply1, sizeof(reply1)); + rv2 = QueryPort(destination.port, CONSUMER_DISCONNECTED, &request2, sizeof(request2), &reply2, sizeof(reply2)); + + // XXX unregister connection with server + // XXX we should just send a notification, instead of republishing all endpoints + Stack outstack; + Stack instack; + media_node sourcenode; + media_node destnode; + if (B_OK == GetNodeFor(source_nodeid, &sourcenode)) { + if (B_OK == GetAllOutputs(sourcenode , &outstack)) + PublishOutputs(sourcenode , &outstack); + ReleaseNode(sourcenode); + } else TRACE("BMediaRoster::Disconnect: source GetNodeFor failed\n"); + if (B_OK == GetNodeFor(destination_nodeid, &destnode)) { + if (B_OK == GetAllInputs(destnode , &instack)) + PublishInputs(destnode, &instack); + ReleaseNode(destnode); + } else TRACE("BMediaRoster::Disconnect: dest GetNodeFor failed\n"); + + + // send a notification + BPrivate::media::notifications::ConnectionBroken(source, destination); + + return (rv1 != B_OK || rv2 != B_OK) ? B_ERROR : B_OK; } @@ -562,7 +659,7 @@ BMediaRoster::StartNode(const media_node & node, bigtime_t at_performance_time) { CALLED(); - if (node.node == 0) + if (node.node <= 0) return B_MEDIA_BAD_NODE; xfer_node_start msg; @@ -578,7 +675,7 @@ BMediaRoster::StopNode(const media_node & node, bool immediate) { CALLED(); - if (node.node == 0) + if (node.node <= 0) return B_MEDIA_BAD_NODE; xfer_node_stop msg; @@ -595,7 +692,7 @@ BMediaRoster::SeekNode(const media_node & node, bigtime_t at_performance_time) { CALLED(); - if (node.node == 0) + if (node.node <= 0) return B_MEDIA_BAD_NODE; xfer_node_seek msg; @@ -611,7 +708,7 @@ BMediaRoster::StartTimeSource(const media_node & node, bigtime_t at_real_time) { CALLED(); - if (node.node == 0) + if (node.node <= 0) return B_MEDIA_BAD_NODE; if ((node.kind & B_TIME_SOURCE) == 0) return B_MEDIA_BAD_NODE; @@ -630,7 +727,7 @@ BMediaRoster::StopTimeSource(const media_node & node, bool immediate) { CALLED(); - if (node.node == 0) + if (node.node <= 0) return B_MEDIA_BAD_NODE; if ((node.kind & B_TIME_SOURCE) == 0) return B_MEDIA_BAD_NODE; @@ -649,7 +746,7 @@ BMediaRoster::SeekTimeSource(const media_node & node, bigtime_t at_real_time) { CALLED(); - if (node.node == 0) + if (node.node <= 0) return B_MEDIA_BAD_NODE; if ((node.kind & B_TIME_SOURCE) == 0) return B_MEDIA_BAD_NODE; @@ -678,7 +775,7 @@ BMediaRoster::SetRunModeNode(const media_node & node, BMediaNode::run_mode mode) { CALLED(); - if (node.node == 0) + if (node.node <= 0) return B_MEDIA_BAD_NODE; xfer_node_set_run_mode msg; @@ -692,7 +789,7 @@ status_t BMediaRoster::PrerollNode(const media_node & node) { CALLED(); - if (node.node == 0) + if (node.node <= 0) return B_MEDIA_BAD_NODE; char dummy; @@ -751,7 +848,6 @@ BMediaRoster::SetProducerRate(const media_node & producer, } - /* Nodes will have available inputs/outputs as long as they are capable */ /* of accepting more connections. The node may create an additional */ /* output or input as the currently available is taken into usage. */ @@ -759,8 +855,24 @@ status_t BMediaRoster::GetLiveNodeInfo(const media_node & node, live_node_info * out_live_info) { - UNIMPLEMENTED(); - return B_ERROR; + CALLED(); + if (out_live_info == NULL) + return B_BAD_VALUE; + if (node.node <= 0) + return B_MEDIA_BAD_NODE; + + server_get_live_node_info_request request; + server_get_live_node_info_reply reply; + status_t rv; + + request.node = node; + + rv = QueryAddonServer(SERVER_GET_LIVE_NODE_INFO, &request, sizeof(request), &reply, sizeof(reply)); + if (rv != B_OK) + return rv; + + *out_live_info = reply.live_info; + return B_OK; } @@ -772,8 +884,65 @@ BMediaRoster::GetLiveNodes(live_node_info * out_live_nodes, const char * name, uint64 node_kinds) { - UNIMPLEMENTED(); - return B_ERROR; + CALLED(); + if (out_live_nodes == NULL || io_total_count == NULL) + return B_BAD_VALUE; + if (*io_total_count <= 0) + return B_BAD_VALUE; + + // XXX we also support the wildcard search as GetDormantNodes does. This needs to be documented + + server_get_live_nodes_request request; + server_get_live_nodes_reply reply; + status_t rv; + + request.maxcount = *io_total_count; + request.has_input = (bool) has_input; + if (has_input) + request.inputformat = *has_input; // XXX we should not make a flat copy of media_format + request.has_output = (bool) has_output; + if (has_output) + request.outputformat = *has_output; // XXX we should not make a flat copy of media_format + request.has_name = (bool) name; + if (name) { + int len = strlen(name); + len = min_c(len, (int)sizeof(request.name) - 1); + memcpy(request.name, name, len); + request.name[len] = 0; + } + request.require_kinds = node_kinds; + + rv = QueryServer(SERVER_GET_LIVE_NODES, &request, sizeof(request), &reply, sizeof(reply)); + if (rv != B_OK) { + TRACE("BMediaRoster::GetLiveNodes failed\n"); + return rv; + } + + if (reply.count > MAX_LIVE_INFO) { + live_node_info *live_info; + area_id clone; + + clone = clone_area("live_node_info clone", reinterpret_cast(&live_info), B_ANY_ADDRESS, B_READ_AREA | B_WRITE_AREA, reply.area); + if (clone < B_OK) { + TRACE("BMediaRoster::GetLiveNodes failed to clone area, %#lx\n", clone); + delete_area(reply.area); + return B_ERROR; + } + + for (int32 i = 0; i < reply.count; i++) { + out_live_nodes[i] = live_info[i]; + } + + delete_area(clone); + delete_area(reply.area); + } else { + for (int32 i = 0; i < reply.count; i++) { + out_live_nodes[i] = reply.live_info[i]; + } + } + *io_total_count = reply.count; + + return B_OK; } @@ -785,7 +954,7 @@ BMediaRoster::GetFreeInputsFor(const media_node & node, media_type filter_type) { CALLED(); - if (node.node == 0 || (node.kind & B_BUFFER_CONSUMER) == 0) + if (node.node <= 0 || (node.kind & B_BUFFER_CONSUMER) == 0) return B_MEDIA_BAD_NODE; if (out_free_inputs == NULL || out_total_count == NULL) return B_BAD_VALUE; @@ -823,7 +992,7 @@ BMediaRoster::GetConnectedInputsFor(const media_node & node, int32 * out_total_count) { CALLED(); - if (node.node == 0 || (node.kind & B_BUFFER_CONSUMER) == 0) + if (node.node <= 0 || (node.kind & B_BUFFER_CONSUMER) == 0) return B_MEDIA_BAD_NODE; if (out_active_inputs == NULL || out_total_count == NULL) return B_BAD_VALUE; @@ -859,7 +1028,7 @@ BMediaRoster::GetAllInputsFor(const media_node & node, int32 * out_total_count) { CALLED(); - if (node.node == 0 || (node.kind & B_BUFFER_CONSUMER) == 0) + if (node.node <= 0 || (node.kind & B_BUFFER_CONSUMER) == 0) return B_MEDIA_BAD_NODE; if (out_inputs == NULL || out_total_count == NULL) return B_BAD_VALUE; @@ -894,7 +1063,7 @@ BMediaRoster::GetFreeOutputsFor(const media_node & node, media_type filter_type) { CALLED(); - if (node.node == 0 || (node.kind & B_BUFFER_PRODUCER) == 0) + if (node.node <= 0 || (node.kind & B_BUFFER_PRODUCER) == 0) return B_MEDIA_BAD_NODE; if (out_free_outputs == NULL || out_total_count == NULL) return B_BAD_VALUE; @@ -932,7 +1101,7 @@ BMediaRoster::GetConnectedOutputsFor(const media_node & node, int32 * out_total_count) { CALLED(); - if (node.node == 0 || (node.kind & B_BUFFER_PRODUCER) == 0) + if (node.node <= 0 || (node.kind & B_BUFFER_PRODUCER) == 0) return B_MEDIA_BAD_NODE; if (out_active_outputs == NULL || out_total_count == NULL) return B_BAD_VALUE; @@ -968,7 +1137,7 @@ BMediaRoster::GetAllOutputsFor(const media_node & node, int32 * out_total_count) { CALLED(); - if (node.node == 0 || (node.kind & B_BUFFER_PRODUCER) == 0) + if (node.node <= 0 || (node.kind & B_BUFFER_PRODUCER) == 0) return B_MEDIA_BAD_NODE; if (out_outputs == NULL || out_total_count == NULL) return B_BAD_VALUE; @@ -1034,7 +1203,7 @@ BMediaRoster::StartWatching(const BMessenger & where, TRACE("BMediaRoster::StartWatching: messenger invalid!\n"); return B_BAD_VALUE; } - if (node.node == 0) { + if (node.node <= 0) { TRACE("BMediaRoster::StartWatching: node invalid!\n"); return B_MEDIA_BAD_NODE; } @@ -1076,7 +1245,7 @@ BMediaRoster::StopWatching(const BMessenger & where, { CALLED(); // messenger may already be invalid, so we don't check this - if (node.node == 0) { + if (node.node <= 0) { TRACE("BMediaRoster::StopWatching: node invalid!\n"); return B_MEDIA_BAD_NODE; } @@ -1096,13 +1265,38 @@ BMediaRoster::RegisterNode(BMediaNode * node) return B_BAD_VALUE; status_t rv; + 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; - // XXX fix node registration - xfer_node_registered msg; - msg.node_id = 1; + server_register_node_request request; + server_register_node_reply reply; - rv = node->HandleMessage(NODE_REGISTERED,&msg,sizeof(msg)); + request.addon_id = addon_id; + request.addon_flavor_id = addon_flavor_id; + strcpy(request.name, node->Name()); + request.kinds = node->Kinds(); + request.port = node->ControlPort(); + request.team = team; + rv = QueryServer(SERVER_REGISTER_NODE, &request, sizeof(request), &reply, sizeof(reply)); + if (rv != B_OK) { + TRACE("BMediaRoster::RegisterNode: failed to register node %s (error %#lx)\n", node->Name(), rv); + return rv; + } + + // we are a friend class of BMediaNode and initilize this member variable + node->fNodeID = reply.nodeid; + ASSERT(reply.nodeid == node->Node().node); + ASSERT(reply.nodeid == node->ID()); + + // call the callback + node->NodeRegistered(); + // register existing inputs and outputs with the // media_server, this allows GetLiveNodes() to work // with created, but unconnected nodes. @@ -1116,15 +1310,48 @@ BMediaRoster::RegisterNode(BMediaNode * node) PublishInputs(node->Node(), &stack); } - return rv; + TRACE("BMediaRoster::RegisterNode: registered node %s, id %ld, addon %ld, flavor %ld\n", node->Name(), node->ID(), addon_id, addon_flavor_id); + + return B_OK; } status_t BMediaRoster::UnregisterNode(BMediaNode * node) { - UNIMPLEMENTED(); - return B_ERROR; + CALLED(); + if (node == NULL) + return B_BAD_VALUE; + + if (node->fRefCount != 0) { + TRACE("BMediaRoster::UnregisterNode: Warning node %s has local reference count of %ld\n", node->Name(), node->fRefCount); + // no return here, we continue and unregister! + } + if (node->ID() == -2) { + TRACE("BMediaRoster::UnregisterNode: Warning node %s already unregistered\n", node->Name()); + return B_OK; + } + + server_unregister_node_request request; + server_unregister_node_reply reply; + status_t rv; + + request.nodeid = node->ID(); + request.team = team; + + rv = QueryServer(SERVER_UNREGISTER_NODE, &request, sizeof(request), &reply, sizeof(reply)); + if (rv != B_OK) { + TRACE("BMediaRoster::UnregisterNode: failed to unregister node %s (error %#lx)\n", node->Name(), rv); + return rv; + } + + if (reply.addon_id != -1) + _DormantNodeManager->PutAddon(reply.addon_id); + + // we are a friend class of BMediaNode and initilize this member variable + node->fNodeID = -2; + + return B_OK; } @@ -1219,8 +1446,9 @@ BMediaRoster::GetDormantNodes(dormant_node_info * out_info, msg.outputformat = *has_output;; // XXX we should not make a flat copy of media_format msg.has_name = (bool) name; if (name) { - int len = min_c(strlen(name),sizeof(msg.name) - 1); - memcpy(msg.name,name,len); + int len = strlen(name); + len = min_c(len, (int)sizeof(msg.name) - 1); + memcpy(msg.name, name, len); msg.name[len] = 0; } msg.require_kinds = require_kinds; @@ -1350,6 +1578,7 @@ BMediaRoster::InstantiateDormantNode(const dormant_node_info & in_info, // XXX we must remember in_info.addon and call // XXX _DormantNodeManager->PutAddon when the // XXX node is unregistered + // should be handled by RegisterNode() and UnegisterNode() now *out_node = node->Node(); return B_OK; @@ -1574,8 +1803,21 @@ BMediaRoster::GetNodeAttributesFor(const media_node & node, media_node_id BMediaRoster::NodeIDFor(port_id source_or_destination_port) { - UNIMPLEMENTED(); - return B_ERROR; + CALLED(); + + server_node_id_for_request request; + server_node_id_for_reply reply; + status_t rv; + + request.port = source_or_destination_port; + + rv = QueryServer(SERVER_NODE_ID_FOR, &request, sizeof(request), &reply, sizeof(reply)); + if (rv != B_OK) { + TRACE("BMediaRoster::NodeIDFor: failed (error %#lx)\n", rv); + return -1; + } + + return reply.nodeid; } @@ -1586,6 +1828,7 @@ BMediaRoster::GetInstancesFor(media_addon_id addon, int32 * io_count) { UNIMPLEMENTED(); + // flavor return B_ERROR; } @@ -1687,6 +1930,7 @@ BMediaRoster::SetOutputBuffersFor(const media_source & output, bool will_reclaim ) { UNIMPLEMENTED(); + debugger("BMediaRoster::SetOutputBuffersFor missing\n"); return B_ERROR; } diff --git a/src/servers/media/ServerInterface.h b/src/servers/media/ServerInterface.h index 02a701d695..70466f544c 100644 --- a/src/servers/media/ServerInterface.h +++ b/src/servers/media/ServerInterface.h @@ -59,13 +59,11 @@ enum { NODE_SET_RUN_MODE, NODE_TIME_WARP, NODE_PREROLL, - NODE_REGISTERED, NODE_SET_TIMESOURCE, NODE_REQUEST_COMPLETED, CONSUMER_BUFFER_RECEIVED, CONSUMER_PRODUCER_DATA_STATUS, CONSUMER_GET_LATENCY_FOR, - CONSUMER_DISCONNECTED, CONSUMER_FORMAT_CHANGED, CONSUMER_SEEK_TAG_REQUESTED, PRODUCER_LATE_NOTICE_RECEIVED, @@ -77,7 +75,6 @@ enum { PRODUCER_GET_LATENCY, PRODUCER_GET_INITIAL_LATENCY, PRODUCER_FORMAT_SUGGESTION_REQUESTED, - PRODUCER_DISCONNECT, PRODUCER_SET_PLAY_RATE, PRODUCER_ENABLE_OUTPUT, ADDONSERVER_INSTANTIATE_DORMANT_NODE, @@ -213,12 +210,6 @@ struct xfer_producer_format_suggestion_requested_reply status_t result; }; -struct xfer_producer_disconnect -{ - media_source source; - media_destination destination; -}; - struct xfer_producer_set_play_rate { int32 numer; @@ -349,11 +340,6 @@ struct xfer_node_time_warp bigtime_t to_performance_time; }; -struct xfer_node_registered -{ - media_node_id node_id; -}; - struct xfer_node_set_timesource { media_node_id timesource_id; @@ -385,13 +371,6 @@ struct xfer_consumer_get_latency_for_reply status_t result; }; - -struct xfer_consumer_disconnected -{ - media_source producer; - media_destination where; -}; - struct xfer_consumer_format_changed { media_source producer; diff --git a/src/servers/media/media_server.cpp b/src/servers/media/media_server.cpp index 95e2b6a9e5..1bd82c53dc 100644 --- a/src/servers/media/media_server.cpp +++ b/src/servers/media/media_server.cpp @@ -157,6 +157,7 @@ void ServerApp::HandleMessage(int32 code, void *data, size_t size) { status_t rv; + printf("ServerApp::HandleMessage %#lx\n", code); switch (code) { case SERVER_GET_MEDIAADDON_REF: { @@ -169,39 +170,103 @@ ServerApp::HandleMessage(int32 code, void *data, size_t size) break; } + case SERVER_NODE_ID_FOR: + { + const server_node_id_for_request *request = reinterpret_cast(data); + server_node_id_for_reply reply; + // XXX do something here + request->SendReply(B_OK, &reply, sizeof(reply)); + break; + } + + case SERVER_GET_LIVE_NODE_INFO: + { + const server_get_live_node_info_request *request = reinterpret_cast(data); + server_get_live_node_info_reply reply; + // XXX do something here + request->SendReply(B_OK, &reply, sizeof(reply)); + break; + } + + case SERVER_GET_LIVE_NODES: + { + const server_get_live_nodes_request *request = reinterpret_cast(data); + server_get_live_nodes_reply reply; + // XXX do something here + request->SendReply(B_OK, &reply, sizeof(reply)); + break; + } + + case SERVER_GET_NODE_FOR: + { + const server_get_node_for_request *request = reinterpret_cast(data); + server_get_node_for_reply reply; + // XXX do something here + request->SendReply(B_OK, &reply, sizeof(reply)); + break; + } + + case SERVER_RELEASE_NODE: + { + const server_release_node_request *request = reinterpret_cast(data); + server_release_node_reply reply; + // XXX do something here + request->SendReply(B_OK, &reply, sizeof(reply)); + break; + } + + case SERVER_REGISTER_NODE: + { + const server_register_node_request *request = reinterpret_cast(data); + server_register_node_reply reply; + reply.nodeid = 1234; + // XXX do something here + request->SendReply(B_OK, &reply, sizeof(reply)); + break; + } + + case SERVER_UNREGISTER_NODE: + { + const server_unregister_node_request *request = reinterpret_cast(data); + server_unregister_node_reply reply; + // XXX do something here + request->SendReply(B_OK, &reply, sizeof(reply)); + break; + } + case SERVER_PUBLISH_INPUTS: { - server_publish_inputs_request *request = (server_publish_inputs_request *)data; + const server_publish_inputs_request *request = reinterpret_cast(data); server_publish_inputs_reply reply; // XXX do something here - request->SendReply(B_ERROR, &reply, sizeof(reply)); + request->SendReply(B_OK, &reply, sizeof(reply)); break; } case SERVER_PUBLISH_OUTPUTS: { - server_publish_outputs_request *request = (server_publish_outputs_request *)data; + const server_publish_outputs_request *request = reinterpret_cast(data); server_publish_outputs_reply reply; // XXX do something here - request->SendReply(B_ERROR, &reply, sizeof(reply)); + request->SendReply(B_OK, &reply, sizeof(reply)); break; } case SERVER_GET_NODE: { - server_get_node_request *request = (server_get_node_request *)data; + const server_get_node_request *request = reinterpret_cast(data); server_get_node_reply reply; // XXX do something here - request->SendReply(B_ERROR, &reply, sizeof(reply)); + request->SendReply(B_OK, &reply, sizeof(reply)); break; } case SERVER_SET_NODE: { - server_set_node_request *request = (server_set_node_request *)data; + const server_set_node_request *request = reinterpret_cast(data); server_set_node_reply reply; // XXX do something here - request->SendReply(B_ERROR, &reply, sizeof(reply)); + request->SendReply(B_OK, &reply, sizeof(reply)); break; }