152a38012Sejakowatz /*********************************************************************** 252a38012Sejakowatz * AUTHOR: Marcus Overhagen 352a38012Sejakowatz * FILE: MediaRoster.cpp 452a38012Sejakowatz * DESCR: 552a38012Sejakowatz ***********************************************************************/ 652a38012Sejakowatz #include <MediaRoster.h> 752a38012Sejakowatz #include <Locker.h> 852a38012Sejakowatz #include <Message.h> 952a38012Sejakowatz #include <Messenger.h> 1052a38012Sejakowatz #include <StopWatch.h> 1152a38012Sejakowatz #include <OS.h> 1252a38012Sejakowatz #include <String.h> 1352a38012Sejakowatz #include <TimeSource.h> 1452a38012Sejakowatz #undef DEBUG 1552a38012Sejakowatz #define DEBUG 3 1652a38012Sejakowatz #include "debug.h" 173620737cSbeveloper #include "TStack.h" 1852a38012Sejakowatz #include "PortPool.h" 190a483e72SIngo Weinhold #include "ServerInterface.h" 20f4925104Sbeveloper #include "DataExchange.h" 2116b7eea4Sbeveloper #include "DormantNodeManager.h" 22f4925104Sbeveloper #include "Notifications.h" 2352a38012Sejakowatz 24f4925104Sbeveloper namespace BPrivate { namespace media { 25f4925104Sbeveloper extern team_id team; 263620737cSbeveloper } } // BPrivate::media 273620737cSbeveloper 283620737cSbeveloper using namespace BPrivate::media; 2952a38012Sejakowatz 3052a38012Sejakowatz // the BMediaRoster destructor is private, 3152a38012Sejakowatz // but _DefaultDeleter is a friend class of 3252a38012Sejakowatz // the BMediaRoster an thus can delete it 3352a38012Sejakowatz class _DefaultDeleter 3452a38012Sejakowatz { 3552a38012Sejakowatz public: 36e66fda40Sbeveloper ~_DefaultDeleter() { delete BMediaRoster::_sDefault; } 3752a38012Sejakowatz }; 3852a38012Sejakowatz 39f4925104Sbeveloper _DefaultDeleter _deleter; 4052a38012Sejakowatz 413620737cSbeveloper namespace BPrivate { namespace media { namespace mediaroster { 4252a38012Sejakowatz 4352a38012Sejakowatz status_t GetNode(node_type type, media_node * out_node, int32 * out_input_id = NULL, BString * out_input_name = NULL); 4452a38012Sejakowatz status_t SetNode(node_type type, const media_node *node, const dormant_node_info *info = NULL, const media_input *input = NULL); 453620737cSbeveloper status_t GetAllOutputs(const media_node & node, Stack<media_output> *stack); 463620737cSbeveloper status_t GetAllInputs(const media_node & node, Stack<media_input> *stack); 473620737cSbeveloper status_t PublishOutputs(const media_node & node, Stack<media_output> *stack); 483620737cSbeveloper status_t PublishInputs(const media_node & node, Stack<media_input> *stack); 4952a38012Sejakowatz 503620737cSbeveloper status_t 513620737cSbeveloper GetNode(node_type type, media_node * out_node, int32 * out_input_id, BString * out_input_name) 5252a38012Sejakowatz { 5352a38012Sejakowatz if (out_node == NULL) 5452a38012Sejakowatz return B_BAD_VALUE; 5552a38012Sejakowatz 568c6a6096Sbeveloper server_get_node_request request; 578c6a6096Sbeveloper server_get_node_reply reply; 5852a38012Sejakowatz status_t rv; 5952a38012Sejakowatz 608c6a6096Sbeveloper request.type = type; 618c6a6096Sbeveloper rv = QueryServer(SERVER_GET_NODE, &request, sizeof(request), &reply, sizeof(reply)); 628c6a6096Sbeveloper if (rv != B_OK) 638c6a6096Sbeveloper return rv; 6452a38012Sejakowatz 6552a38012Sejakowatz *out_node = reply.node; 6652a38012Sejakowatz if (out_input_id) 6752a38012Sejakowatz *out_input_id = reply.input_id; 6852a38012Sejakowatz if (out_input_name) 6952a38012Sejakowatz *out_input_name = reply.input_name; 708c6a6096Sbeveloper return rv; 7152a38012Sejakowatz } 7252a38012Sejakowatz 733620737cSbeveloper status_t 743620737cSbeveloper SetNode(node_type type, const media_node *node, const dormant_node_info *info, const media_input *input) 7552a38012Sejakowatz { 768c6a6096Sbeveloper server_set_node_request request; 778c6a6096Sbeveloper server_set_node_reply reply; 7852a38012Sejakowatz 798c6a6096Sbeveloper request.type = type; 808c6a6096Sbeveloper request.use_node = node ? true : false; 8152a38012Sejakowatz if (node) 828c6a6096Sbeveloper request.node = *node; 838c6a6096Sbeveloper request.use_dni = info ? true : false; 8452a38012Sejakowatz if (info) 858c6a6096Sbeveloper request.dni = *info; 868c6a6096Sbeveloper request.use_input = input ? true : false; 8752a38012Sejakowatz if (input) 888c6a6096Sbeveloper request.input = *input; 8952a38012Sejakowatz 908c6a6096Sbeveloper return QueryServer(SERVER_SET_NODE, &request, sizeof(request), &reply, sizeof(reply)); 9152a38012Sejakowatz } 9252a38012Sejakowatz 933620737cSbeveloper status_t 943620737cSbeveloper GetAllOutputs(const media_node & node, Stack<media_output> *stack) 953620737cSbeveloper { 963620737cSbeveloper int32 cookie; 973620737cSbeveloper status_t rv; 983620737cSbeveloper status_t result; 993620737cSbeveloper 1003620737cSbeveloper result = B_OK; 1013620737cSbeveloper cookie = 0; 1023620737cSbeveloper for (;;) { 1033620737cSbeveloper producer_get_next_output_request request; 1043620737cSbeveloper producer_get_next_output_reply reply; 1053620737cSbeveloper request.cookie = cookie; 106*0caff283Sbeveloper rv = QueryPort(node.port, PRODUCER_GET_NEXT_OUTPUT, &request, sizeof(request), &reply, sizeof(reply)); 1073620737cSbeveloper if (rv != B_OK) 1083620737cSbeveloper break; 1093620737cSbeveloper cookie = reply.cookie; 1103620737cSbeveloper if (!stack->Push(reply.output)) { 1113620737cSbeveloper TRACE("GetAllOutputs: stack->Push failed\n"); 1123620737cSbeveloper result = B_ERROR; 1133620737cSbeveloper } 1143620737cSbeveloper } 1153620737cSbeveloper 1163620737cSbeveloper producer_dispose_output_cookie_request request; 1173620737cSbeveloper producer_dispose_output_cookie_reply reply; 118*0caff283Sbeveloper QueryPort(node.port, PRODUCER_DISPOSE_OUTPUT_COOKIE, &request, sizeof(request), &reply, sizeof(reply)); 1193620737cSbeveloper 1203620737cSbeveloper return result; 1213620737cSbeveloper } 1223620737cSbeveloper 1233620737cSbeveloper status_t 1243620737cSbeveloper GetAllInputs(const media_node & node, Stack<media_input> *stack) 1253620737cSbeveloper { 1263620737cSbeveloper int32 cookie; 1273620737cSbeveloper status_t rv; 1283620737cSbeveloper status_t result; 1293620737cSbeveloper 1303620737cSbeveloper result = B_OK; 1313620737cSbeveloper cookie = 0; 1323620737cSbeveloper for (;;) { 1333620737cSbeveloper consumer_get_next_input_request request; 1343620737cSbeveloper consumer_get_next_input_reply reply; 1353620737cSbeveloper request.cookie = cookie; 136*0caff283Sbeveloper rv = QueryPort(node.port, CONSUMER_GET_NEXT_INPUT, &request, sizeof(request), &reply, sizeof(reply)); 1373620737cSbeveloper if (rv != B_OK) 1383620737cSbeveloper break; 1393620737cSbeveloper cookie = reply.cookie; 1403620737cSbeveloper if (!stack->Push(reply.input)) { 1413620737cSbeveloper TRACE("GetAllInputs: stack->Push failed\n"); 1423620737cSbeveloper result = B_ERROR; 1433620737cSbeveloper } 1443620737cSbeveloper } 1453620737cSbeveloper 1463620737cSbeveloper consumer_dispose_input_cookie_request request; 1473620737cSbeveloper consumer_dispose_input_cookie_reply reply; 148*0caff283Sbeveloper QueryPort(node.port, CONSUMER_DISPOSE_INPUT_COOKIE, &request, sizeof(request), &reply, sizeof(reply)); 1493620737cSbeveloper 1503620737cSbeveloper return result; 1513620737cSbeveloper } 1523620737cSbeveloper 1533620737cSbeveloper status_t 1543620737cSbeveloper PublishOutputs(const media_node & node, Stack<media_output> *stack) 1553620737cSbeveloper { 1563620737cSbeveloper server_publish_outputs_request request; 1573620737cSbeveloper server_publish_outputs_reply reply; 1583620737cSbeveloper media_output *output; 1593620737cSbeveloper media_output *outputs; 1603620737cSbeveloper int32 count; 1613620737cSbeveloper 1623620737cSbeveloper count = stack->CountItems(); 1633620737cSbeveloper TRACE("PublishOutputs: publishing %ld\n", count); 1643620737cSbeveloper 1653620737cSbeveloper request.node = node; 1663620737cSbeveloper request.count = count; 1673620737cSbeveloper if (count > MAX_OUTPUTS) { 1683620737cSbeveloper void *start_addr; 1693620737cSbeveloper size_t size; 1703620737cSbeveloper size = ((count * sizeof(media_output)) + B_PAGE_SIZE - 1) & ~(B_PAGE_SIZE - 1); 1713620737cSbeveloper request.area = create_area("publish outputs", &start_addr, B_ANY_ADDRESS, size, B_NO_LOCK, B_READ_AREA | B_WRITE_AREA); 1723620737cSbeveloper if (request.area < B_OK) { 1733620737cSbeveloper TRACE("PublishOutputs: failed to create area, %#lx\n", request.area); 1743620737cSbeveloper return (status_t)request.area; 1753620737cSbeveloper } 1763620737cSbeveloper outputs = static_cast<media_output *>(start_addr); 1773620737cSbeveloper } else { 1783620737cSbeveloper request.area = -1; 1793620737cSbeveloper outputs = request.outputs; 1803620737cSbeveloper } 1813620737cSbeveloper TRACE("PublishOutputs: area %#lx\n", request.area); 1823620737cSbeveloper 1833620737cSbeveloper for (int32 i = 0; i != count; i++) { 1843620737cSbeveloper stack->GetPointerAt(i, &output); 1853620737cSbeveloper outputs[i] = *output; 1863620737cSbeveloper } 1873620737cSbeveloper 1883620737cSbeveloper return QueryServer(SERVER_PUBLISH_OUTPUTS, &request, sizeof(request), &reply, sizeof(reply)); 1893620737cSbeveloper } 1903620737cSbeveloper 1913620737cSbeveloper status_t 1923620737cSbeveloper PublishInputs(const media_node & node, Stack<media_input> *stack) 1933620737cSbeveloper { 1943620737cSbeveloper server_publish_inputs_request request; 1953620737cSbeveloper server_publish_inputs_reply reply; 1963620737cSbeveloper media_input *input; 1973620737cSbeveloper media_input *inputs; 1983620737cSbeveloper int32 count; 1993620737cSbeveloper 2003620737cSbeveloper count = stack->CountItems(); 2013620737cSbeveloper TRACE("PublishInputs: publishing %ld\n", count); 2023620737cSbeveloper 2033620737cSbeveloper request.node = node; 2043620737cSbeveloper request.count = count; 2053620737cSbeveloper if (count > MAX_INPUTS) { 2063620737cSbeveloper void *start_addr; 2073620737cSbeveloper size_t size; 2083620737cSbeveloper size = ((count * sizeof(media_input)) + B_PAGE_SIZE - 1) & ~(B_PAGE_SIZE - 1); 2093620737cSbeveloper request.area = create_area("publish inputs", &start_addr, B_ANY_ADDRESS, size, B_NO_LOCK, B_READ_AREA | B_WRITE_AREA); 2103620737cSbeveloper if (request.area < B_OK) { 2113620737cSbeveloper TRACE("PublishInputs: failed to create area, %#lx\n", request.area); 2123620737cSbeveloper return (status_t)request.area; 2133620737cSbeveloper } 2143620737cSbeveloper inputs = static_cast<media_input *>(start_addr); 2153620737cSbeveloper } else { 2163620737cSbeveloper request.area = -1; 2173620737cSbeveloper inputs = request.inputs; 2183620737cSbeveloper } 2193620737cSbeveloper TRACE("PublishInputs: area %#lx\n", request.area); 2203620737cSbeveloper 2213620737cSbeveloper for (int32 i = 0; i != count; i++) { 2223620737cSbeveloper stack->GetPointerAt(i, &input); 2233620737cSbeveloper inputs[i] = *input; 2243620737cSbeveloper } 2253620737cSbeveloper 2263620737cSbeveloper return QueryServer(SERVER_PUBLISH_INPUTS, &request, sizeof(request), &reply, sizeof(reply)); 2273620737cSbeveloper } 2283620737cSbeveloper 2293620737cSbeveloper } } } // namespace BPrivate::media::mediaroster 2303620737cSbeveloper 2313620737cSbeveloper using namespace BPrivate::media::mediaroster; 23252a38012Sejakowatz 23352a38012Sejakowatz /************************************************************* 23452a38012Sejakowatz * public BMediaRoster 23552a38012Sejakowatz *************************************************************/ 23652a38012Sejakowatz 23752a38012Sejakowatz status_t 23852a38012Sejakowatz BMediaRoster::GetVideoInput(media_node * out_node) 23952a38012Sejakowatz { 24052a38012Sejakowatz CALLED(); 2413620737cSbeveloper return GetNode(VIDEO_INPUT, out_node); 24252a38012Sejakowatz } 24352a38012Sejakowatz 24452a38012Sejakowatz 24552a38012Sejakowatz status_t 24652a38012Sejakowatz BMediaRoster::GetAudioInput(media_node * out_node) 24752a38012Sejakowatz { 24852a38012Sejakowatz CALLED(); 2493620737cSbeveloper return GetNode(AUDIO_INPUT, out_node); 25052a38012Sejakowatz } 25152a38012Sejakowatz 25252a38012Sejakowatz 25352a38012Sejakowatz status_t 25452a38012Sejakowatz BMediaRoster::GetVideoOutput(media_node * out_node) 25552a38012Sejakowatz { 25652a38012Sejakowatz CALLED(); 2573620737cSbeveloper return GetNode(VIDEO_OUTPUT, out_node); 25852a38012Sejakowatz } 25952a38012Sejakowatz 26052a38012Sejakowatz 26152a38012Sejakowatz status_t 26252a38012Sejakowatz BMediaRoster::GetAudioMixer(media_node * out_node) 26352a38012Sejakowatz { 26452a38012Sejakowatz CALLED(); 2653620737cSbeveloper return GetNode(AUDIO_MIXER, out_node); 26652a38012Sejakowatz } 26752a38012Sejakowatz 26852a38012Sejakowatz 26952a38012Sejakowatz status_t 27052a38012Sejakowatz BMediaRoster::GetAudioOutput(media_node * out_node) 27152a38012Sejakowatz { 27252a38012Sejakowatz CALLED(); 2733620737cSbeveloper return GetNode(AUDIO_OUTPUT, out_node); 27452a38012Sejakowatz } 27552a38012Sejakowatz 27652a38012Sejakowatz 27752a38012Sejakowatz status_t 27852a38012Sejakowatz BMediaRoster::GetAudioOutput(media_node * out_node, 27952a38012Sejakowatz int32 * out_input_id, 28052a38012Sejakowatz BString * out_input_name) 28152a38012Sejakowatz { 28252a38012Sejakowatz CALLED(); 2833620737cSbeveloper return GetNode(AUDIO_OUTPUT_EX, out_node, out_input_id, out_input_name); 28452a38012Sejakowatz } 28552a38012Sejakowatz 28652a38012Sejakowatz 28752a38012Sejakowatz status_t 28852a38012Sejakowatz BMediaRoster::GetTimeSource(media_node * out_node) 28952a38012Sejakowatz { 29052a38012Sejakowatz CALLED(); 2913620737cSbeveloper return GetNode(TIME_SOURCE, out_node); 29252a38012Sejakowatz } 29352a38012Sejakowatz 29452a38012Sejakowatz 29552a38012Sejakowatz status_t 29652a38012Sejakowatz BMediaRoster::SetVideoInput(const media_node & producer) 29752a38012Sejakowatz { 29852a38012Sejakowatz CALLED(); 2993620737cSbeveloper return SetNode(VIDEO_INPUT, &producer); 30052a38012Sejakowatz } 30152a38012Sejakowatz 30252a38012Sejakowatz 30352a38012Sejakowatz status_t 30452a38012Sejakowatz BMediaRoster::SetVideoInput(const dormant_node_info & producer) 30552a38012Sejakowatz { 30652a38012Sejakowatz CALLED(); 3073620737cSbeveloper return SetNode(VIDEO_INPUT, NULL, &producer); 30852a38012Sejakowatz } 30952a38012Sejakowatz 31052a38012Sejakowatz 31152a38012Sejakowatz status_t 31252a38012Sejakowatz BMediaRoster::SetAudioInput(const media_node & producer) 31352a38012Sejakowatz { 31452a38012Sejakowatz CALLED(); 3153620737cSbeveloper return SetNode(AUDIO_INPUT, &producer); 31652a38012Sejakowatz } 31752a38012Sejakowatz 31852a38012Sejakowatz 31952a38012Sejakowatz status_t 32052a38012Sejakowatz BMediaRoster::SetAudioInput(const dormant_node_info & producer) 32152a38012Sejakowatz { 32252a38012Sejakowatz CALLED(); 3233620737cSbeveloper return SetNode(AUDIO_INPUT, NULL, &producer); 32452a38012Sejakowatz } 32552a38012Sejakowatz 32652a38012Sejakowatz 32752a38012Sejakowatz status_t 32852a38012Sejakowatz BMediaRoster::SetVideoOutput(const media_node & consumer) 32952a38012Sejakowatz { 33052a38012Sejakowatz CALLED(); 3313620737cSbeveloper return SetNode(VIDEO_OUTPUT, &consumer); 33252a38012Sejakowatz } 33352a38012Sejakowatz 33452a38012Sejakowatz 33552a38012Sejakowatz status_t 33652a38012Sejakowatz BMediaRoster::SetVideoOutput(const dormant_node_info & consumer) 33752a38012Sejakowatz { 33852a38012Sejakowatz CALLED(); 3393620737cSbeveloper return SetNode(VIDEO_OUTPUT, NULL, &consumer); 34052a38012Sejakowatz } 34152a38012Sejakowatz 34252a38012Sejakowatz 34352a38012Sejakowatz status_t 34452a38012Sejakowatz BMediaRoster::SetAudioOutput(const media_node & consumer) 34552a38012Sejakowatz { 34652a38012Sejakowatz CALLED(); 3473620737cSbeveloper return SetNode(AUDIO_OUTPUT, &consumer); 34852a38012Sejakowatz } 34952a38012Sejakowatz 35052a38012Sejakowatz 35152a38012Sejakowatz status_t 35252a38012Sejakowatz BMediaRoster::SetAudioOutput(const media_input & input_to_output) 35352a38012Sejakowatz { 35452a38012Sejakowatz CALLED(); 3553620737cSbeveloper return SetNode(AUDIO_OUTPUT, NULL, NULL, &input_to_output); 35652a38012Sejakowatz } 35752a38012Sejakowatz 35852a38012Sejakowatz 35952a38012Sejakowatz status_t 36052a38012Sejakowatz BMediaRoster::SetAudioOutput(const dormant_node_info & consumer) 36152a38012Sejakowatz { 36252a38012Sejakowatz CALLED(); 3633620737cSbeveloper return SetNode(AUDIO_OUTPUT, NULL, &consumer); 36452a38012Sejakowatz } 36552a38012Sejakowatz 36652a38012Sejakowatz 36752a38012Sejakowatz status_t 36852a38012Sejakowatz BMediaRoster::GetNodeFor(media_node_id node, 36952a38012Sejakowatz media_node * clone) 37052a38012Sejakowatz { 37152a38012Sejakowatz UNIMPLEMENTED(); 37252a38012Sejakowatz return B_ERROR; 37352a38012Sejakowatz } 37452a38012Sejakowatz 37552a38012Sejakowatz 37652a38012Sejakowatz status_t 37752a38012Sejakowatz BMediaRoster::GetSystemTimeSource(media_node * clone) 37852a38012Sejakowatz { 37952a38012Sejakowatz CALLED(); 3803620737cSbeveloper return GetNode(SYSTEM_TIME_SOURCE, clone); 38152a38012Sejakowatz } 38252a38012Sejakowatz 38352a38012Sejakowatz 38452a38012Sejakowatz status_t 38552a38012Sejakowatz BMediaRoster::ReleaseNode(const media_node & node) 38652a38012Sejakowatz { 38752a38012Sejakowatz UNIMPLEMENTED(); 38852a38012Sejakowatz return B_ERROR; 38952a38012Sejakowatz } 39052a38012Sejakowatz 39152a38012Sejakowatz 39252a38012Sejakowatz 39352a38012Sejakowatz BTimeSource * 39452a38012Sejakowatz BMediaRoster::MakeTimeSourceFor(const media_node & for_node) 39552a38012Sejakowatz { 39652a38012Sejakowatz UNIMPLEMENTED(); 39752a38012Sejakowatz return 0; 39852a38012Sejakowatz } 39952a38012Sejakowatz 40052a38012Sejakowatz 40152a38012Sejakowatz status_t 40252a38012Sejakowatz BMediaRoster::Connect(const media_source & from, 40352a38012Sejakowatz const media_destination & to, 40452a38012Sejakowatz media_format * io_format, 40552a38012Sejakowatz media_output * out_output, 40652a38012Sejakowatz media_input * out_input) 40752a38012Sejakowatz { 408eae26d3dSbeveloper return BMediaRoster::Connect(from, to, io_format, out_output, out_input, 0); 409eae26d3dSbeveloper } 410eae26d3dSbeveloper 411eae26d3dSbeveloper 412eae26d3dSbeveloper status_t 413eae26d3dSbeveloper BMediaRoster::Connect(const media_source & from, 414eae26d3dSbeveloper const media_destination & to, 415eae26d3dSbeveloper media_format * io_format, 416eae26d3dSbeveloper media_output * out_output, 417eae26d3dSbeveloper media_input * out_input, 418eae26d3dSbeveloper uint32 in_flags, 419eae26d3dSbeveloper void * _reserved) 420eae26d3dSbeveloper { 42152a38012Sejakowatz CALLED(); 42252a38012Sejakowatz if (io_format == NULL || out_output == NULL || out_input == NULL) 42352a38012Sejakowatz return B_BAD_VALUE; 42452a38012Sejakowatz if (from == media_source::null) 42552a38012Sejakowatz return B_MEDIA_BAD_SOURCE; 42652a38012Sejakowatz if (to == media_destination::null) 42752a38012Sejakowatz return B_MEDIA_BAD_DESTINATION; 42852a38012Sejakowatz 42952a38012Sejakowatz status_t rv; 4308c6a6096Sbeveloper producer_format_proposal_request request1; 4318c6a6096Sbeveloper producer_format_proposal_reply reply1; 43252a38012Sejakowatz 43352a38012Sejakowatz // BBufferProducer::FormatProposal 4348c6a6096Sbeveloper request1.output = from; 4358c6a6096Sbeveloper request1.format = *io_format; 4368c6a6096Sbeveloper rv = QueryPort(from.port, PRODUCER_FORMAT_PROPOSAL, &request1, sizeof(request1), &reply1, sizeof(reply1)); 4378c6a6096Sbeveloper if (rv != B_OK) { 4385edd2016Sbeveloper TRACE("BMediaRoster::Connect: aborted after BBufferProducer::FormatProposal, status = %#lx\n",rv); 43952a38012Sejakowatz return rv; 44052a38012Sejakowatz } 4418c6a6096Sbeveloper // reply1.format now contains the format proposed by the producer 4428c6a6096Sbeveloper 4438c6a6096Sbeveloper consumer_accept_format_request request2; 4448c6a6096Sbeveloper consumer_accept_format_reply reply2; 4458c6a6096Sbeveloper 4468c6a6096Sbeveloper // BBufferConsumer::AcceptFormat 4478c6a6096Sbeveloper request2.dest = to; 4488c6a6096Sbeveloper request2.format = reply1.format; 4498c6a6096Sbeveloper rv = QueryPort(to.port, CONSUMER_ACCEPT_FORMAT, &request2, sizeof(request2), &reply2, sizeof(reply2)); 4508c6a6096Sbeveloper if (rv != B_OK) { 4515edd2016Sbeveloper TRACE("BMediaRoster::Connect: aborted after BBufferConsumer::AcceptFormat, status = %#lx\n",rv); 4528c6a6096Sbeveloper return rv; 4538c6a6096Sbeveloper } 4548c6a6096Sbeveloper // reply2.format now contains the format accepted by the consumer 4558c6a6096Sbeveloper 4568c6a6096Sbeveloper // BBufferProducer::PrepareToConnect 4578c6a6096Sbeveloper producer_prepare_to_connect_request request3; 4588c6a6096Sbeveloper producer_prepare_to_connect_reply reply3; 4598c6a6096Sbeveloper 4608c6a6096Sbeveloper request3.source = from; 4618c6a6096Sbeveloper request3.destination = to; 4628c6a6096Sbeveloper request3.format = reply2.format; 4638c6a6096Sbeveloper strcpy(request3.name, "XXX some default name"); // XXX fix this 4648c6a6096Sbeveloper rv = QueryPort(from.port, PRODUCER_PREPARE_TO_CONNECT, &request3, sizeof(request3), &reply3, sizeof(reply3)); 4658c6a6096Sbeveloper if (rv != B_OK) { 4665edd2016Sbeveloper TRACE("BMediaRoster::Connect: aborted after BBufferProducer::PrepareToConnect, status = %#lx\n",rv); 4678c6a6096Sbeveloper return rv; 4688c6a6096Sbeveloper } 4698c6a6096Sbeveloper // reply3.format is still our pretty media format 4708c6a6096Sbeveloper // reply3.out_source the real source to be used for the connection 4718c6a6096Sbeveloper // reply3.name the name BBufferConsumer::Connected will see in the outInput->name argument 4728c6a6096Sbeveloper 4738c6a6096Sbeveloper // BBufferConsumer::Connected 4748c6a6096Sbeveloper consumer_connected_request request4; 4758c6a6096Sbeveloper consumer_connected_reply reply4; 4768c6a6096Sbeveloper status_t con_status; 4778c6a6096Sbeveloper 4788c6a6096Sbeveloper request4.producer = reply3.out_source; 4798c6a6096Sbeveloper request4.where = to; 4808c6a6096Sbeveloper request4.with_format = reply3.format; 4818c6a6096Sbeveloper con_status = QueryPort(to.port, CONSUMER_CONNECTED, &request4, sizeof(request4), &reply4, sizeof(reply4)); 4828c6a6096Sbeveloper if (con_status != B_OK) { 4835edd2016Sbeveloper TRACE("BMediaRoster::Connect: aborting after BBufferConsumer::Connected, status = %#lx\n",con_status); 4848c6a6096Sbeveloper // we do NOT return here! 4858c6a6096Sbeveloper } 4868c6a6096Sbeveloper // con_status contains the status code to be supplied to BBufferProducer::Connect's status argument 4878c6a6096Sbeveloper // reply4.input contains the media_input that describes the connection from the consumer point of view 4888c6a6096Sbeveloper 4898c6a6096Sbeveloper // BBufferProducer::Connect 4908c6a6096Sbeveloper producer_connect_request request5; 4918c6a6096Sbeveloper producer_connect_reply reply5; 4928c6a6096Sbeveloper 4938c6a6096Sbeveloper request5.error = con_status; 4948c6a6096Sbeveloper request5.source = reply3.out_source; 4958c6a6096Sbeveloper request5.destination = reply4.input.destination; 4968c6a6096Sbeveloper request5.format = reply3.format; // XXX reply4.input.format ??? 4978c6a6096Sbeveloper strcpy(request5.name, reply4.input.name); 498*0caff283Sbeveloper rv = QueryPort(reply4.input.source.port, PRODUCER_CONNECT, &request5, sizeof(request5), &reply5, sizeof(reply5)); 4998c6a6096Sbeveloper if (con_status != B_OK) { 5008c6a6096Sbeveloper TRACE("BMediaRoster::Connect: aborted\n"); 5018c6a6096Sbeveloper return con_status; 5028c6a6096Sbeveloper } 5038c6a6096Sbeveloper if (rv != B_OK) { 5045edd2016Sbeveloper TRACE("BMediaRoster::Connect: aborted after BBufferProducer::Connect, status = %#lx\n",rv); 5058c6a6096Sbeveloper return rv; 5068c6a6096Sbeveloper } 5078c6a6096Sbeveloper // reply5.name contains the name assigned to the connection by the producer 5088c6a6096Sbeveloper 5098c6a6096Sbeveloper // find the output node 5108c6a6096Sbeveloper // XXX isn't there a easier way? 5118c6a6096Sbeveloper media_node sourcenode; 5128c6a6096Sbeveloper GetNodeFor(NodeIDFor(from.port), &sourcenode); 5138c6a6096Sbeveloper ReleaseNode(sourcenode); 5148c6a6096Sbeveloper 5158c6a6096Sbeveloper // initilize connection info 5168c6a6096Sbeveloper *io_format = reply3.format; 5178c6a6096Sbeveloper *out_input = reply4.input; 5188c6a6096Sbeveloper out_output->node = sourcenode; 5198c6a6096Sbeveloper out_output->source = reply4.input.source; 5208c6a6096Sbeveloper out_output->destination = reply4.input.destination; 5218c6a6096Sbeveloper out_output->format = reply4.input.format; 5228c6a6096Sbeveloper strcpy(out_output->name, reply5.name); 5238c6a6096Sbeveloper 5248c6a6096Sbeveloper // the connection is now made 5258c6a6096Sbeveloper 5268c6a6096Sbeveloper 5278c6a6096Sbeveloper // XXX register connection with server 5288c6a6096Sbeveloper 5298c6a6096Sbeveloper 5308c6a6096Sbeveloper // XXX if (mute) BBufferProducer::EnableOutput(false) 5318c6a6096Sbeveloper 5328c6a6096Sbeveloper 5338c6a6096Sbeveloper return B_OK; 5348c6a6096Sbeveloper }; 53552a38012Sejakowatz 53652a38012Sejakowatz 53752a38012Sejakowatz status_t 53852a38012Sejakowatz BMediaRoster::Disconnect(media_node_id source_node, 53952a38012Sejakowatz const media_source & source, 54052a38012Sejakowatz media_node_id destination_node, 54152a38012Sejakowatz const media_destination & destination) 54252a38012Sejakowatz { 54352a38012Sejakowatz UNIMPLEMENTED(); 54452a38012Sejakowatz return B_ERROR; 54552a38012Sejakowatz } 54652a38012Sejakowatz 54752a38012Sejakowatz 54852a38012Sejakowatz status_t 54952a38012Sejakowatz BMediaRoster::StartNode(const media_node & node, 55052a38012Sejakowatz bigtime_t at_performance_time) 55152a38012Sejakowatz { 55252a38012Sejakowatz CALLED(); 55352a38012Sejakowatz if (node.node == 0) 55452a38012Sejakowatz return B_MEDIA_BAD_NODE; 55552a38012Sejakowatz 55652a38012Sejakowatz xfer_node_start msg; 55752a38012Sejakowatz msg.performance_time = at_performance_time; 55852a38012Sejakowatz 55952a38012Sejakowatz return write_port(node.port, NODE_START, &msg, sizeof(msg)); 56052a38012Sejakowatz } 56152a38012Sejakowatz 56252a38012Sejakowatz 56352a38012Sejakowatz status_t 56452a38012Sejakowatz BMediaRoster::StopNode(const media_node & node, 56552a38012Sejakowatz bigtime_t at_performance_time, 56652a38012Sejakowatz bool immediate) 56752a38012Sejakowatz { 56852a38012Sejakowatz CALLED(); 56952a38012Sejakowatz if (node.node == 0) 57052a38012Sejakowatz return B_MEDIA_BAD_NODE; 57152a38012Sejakowatz 57252a38012Sejakowatz xfer_node_stop msg; 57352a38012Sejakowatz msg.performance_time = at_performance_time; 57452a38012Sejakowatz msg.immediate = immediate; 57552a38012Sejakowatz 57652a38012Sejakowatz return write_port(node.port, NODE_STOP, &msg, sizeof(msg)); 57752a38012Sejakowatz } 57852a38012Sejakowatz 57952a38012Sejakowatz 58052a38012Sejakowatz status_t 58152a38012Sejakowatz BMediaRoster::SeekNode(const media_node & node, 58252a38012Sejakowatz bigtime_t to_media_time, 58352a38012Sejakowatz bigtime_t at_performance_time) 58452a38012Sejakowatz { 58552a38012Sejakowatz CALLED(); 58652a38012Sejakowatz if (node.node == 0) 58752a38012Sejakowatz return B_MEDIA_BAD_NODE; 58852a38012Sejakowatz 58952a38012Sejakowatz xfer_node_seek msg; 59052a38012Sejakowatz msg.media_time = to_media_time; 59152a38012Sejakowatz msg.performance_time = at_performance_time; 59252a38012Sejakowatz 59352a38012Sejakowatz return write_port(node.port, NODE_SEEK, &msg, sizeof(msg)); 59452a38012Sejakowatz } 59552a38012Sejakowatz 59652a38012Sejakowatz 59752a38012Sejakowatz status_t 59852a38012Sejakowatz BMediaRoster::StartTimeSource(const media_node & node, 59952a38012Sejakowatz bigtime_t at_real_time) 60052a38012Sejakowatz { 60152a38012Sejakowatz CALLED(); 60252a38012Sejakowatz if (node.node == 0) 60352a38012Sejakowatz return B_MEDIA_BAD_NODE; 60452a38012Sejakowatz if ((node.kind & B_TIME_SOURCE) == 0) 60552a38012Sejakowatz return B_MEDIA_BAD_NODE; 60652a38012Sejakowatz 60752a38012Sejakowatz BTimeSource::time_source_op_info msg; 60852a38012Sejakowatz msg.op = BTimeSource::B_TIMESOURCE_START; 60952a38012Sejakowatz msg.real_time = at_real_time; 61052a38012Sejakowatz 61152a38012Sejakowatz return write_port(node.port, TIMESOURCE_OP, &msg, sizeof(msg)); 61252a38012Sejakowatz } 61352a38012Sejakowatz 61452a38012Sejakowatz 61552a38012Sejakowatz status_t 61652a38012Sejakowatz BMediaRoster::StopTimeSource(const media_node & node, 61752a38012Sejakowatz bigtime_t at_real_time, 61852a38012Sejakowatz bool immediate) 61952a38012Sejakowatz { 62052a38012Sejakowatz CALLED(); 62152a38012Sejakowatz if (node.node == 0) 62252a38012Sejakowatz return B_MEDIA_BAD_NODE; 62352a38012Sejakowatz if ((node.kind & B_TIME_SOURCE) == 0) 62452a38012Sejakowatz return B_MEDIA_BAD_NODE; 62552a38012Sejakowatz 62652a38012Sejakowatz BTimeSource::time_source_op_info msg; 62752a38012Sejakowatz msg.op = immediate ? BTimeSource::B_TIMESOURCE_STOP_IMMEDIATELY : BTimeSource::B_TIMESOURCE_STOP; 62852a38012Sejakowatz msg.real_time = at_real_time; 62952a38012Sejakowatz 63052a38012Sejakowatz return write_port(node.port, TIMESOURCE_OP, &msg, sizeof(msg)); 63152a38012Sejakowatz } 63252a38012Sejakowatz 63352a38012Sejakowatz 63452a38012Sejakowatz status_t 63552a38012Sejakowatz BMediaRoster::SeekTimeSource(const media_node & node, 63652a38012Sejakowatz bigtime_t to_performance_time, 63752a38012Sejakowatz bigtime_t at_real_time) 63852a38012Sejakowatz { 63952a38012Sejakowatz CALLED(); 64052a38012Sejakowatz if (node.node == 0) 64152a38012Sejakowatz return B_MEDIA_BAD_NODE; 64252a38012Sejakowatz if ((node.kind & B_TIME_SOURCE) == 0) 64352a38012Sejakowatz return B_MEDIA_BAD_NODE; 64452a38012Sejakowatz 64552a38012Sejakowatz BTimeSource::time_source_op_info msg; 64652a38012Sejakowatz msg.op = BTimeSource::B_TIMESOURCE_SEEK; 64752a38012Sejakowatz msg.real_time = at_real_time; 64852a38012Sejakowatz msg.performance_time = to_performance_time; 64952a38012Sejakowatz 65052a38012Sejakowatz return write_port(node.port, TIMESOURCE_OP, &msg, sizeof(msg)); 65152a38012Sejakowatz } 65252a38012Sejakowatz 65352a38012Sejakowatz 65452a38012Sejakowatz status_t 65552a38012Sejakowatz BMediaRoster::SyncToNode(const media_node & node, 65652a38012Sejakowatz bigtime_t at_time, 65752a38012Sejakowatz bigtime_t timeout) 65852a38012Sejakowatz { 65952a38012Sejakowatz UNIMPLEMENTED(); 66052a38012Sejakowatz return B_ERROR; 66152a38012Sejakowatz } 66252a38012Sejakowatz 66352a38012Sejakowatz 66452a38012Sejakowatz status_t 66552a38012Sejakowatz BMediaRoster::SetRunModeNode(const media_node & node, 66652a38012Sejakowatz BMediaNode::run_mode mode) 66752a38012Sejakowatz { 66852a38012Sejakowatz CALLED(); 66952a38012Sejakowatz if (node.node == 0) 67052a38012Sejakowatz return B_MEDIA_BAD_NODE; 67152a38012Sejakowatz 67252a38012Sejakowatz xfer_node_set_run_mode msg; 67352a38012Sejakowatz msg.mode = mode; 67452a38012Sejakowatz 67552a38012Sejakowatz return write_port(node.port, NODE_SET_RUN_MODE, &msg, sizeof(msg)); 67652a38012Sejakowatz } 67752a38012Sejakowatz 67852a38012Sejakowatz 67952a38012Sejakowatz status_t 68052a38012Sejakowatz BMediaRoster::PrerollNode(const media_node & node) 68152a38012Sejakowatz { 68252a38012Sejakowatz CALLED(); 68352a38012Sejakowatz if (node.node == 0) 68452a38012Sejakowatz return B_MEDIA_BAD_NODE; 68552a38012Sejakowatz 68652a38012Sejakowatz char dummy; 68752a38012Sejakowatz return write_port(node.port, NODE_PREROLL, &dummy, sizeof(dummy)); 68852a38012Sejakowatz } 68952a38012Sejakowatz 69052a38012Sejakowatz 69152a38012Sejakowatz status_t 69252a38012Sejakowatz BMediaRoster::RollNode(const media_node & node, 69352a38012Sejakowatz bigtime_t startPerformance, 69452a38012Sejakowatz bigtime_t stopPerformance, 69552a38012Sejakowatz bigtime_t atMediaTime) 69652a38012Sejakowatz { 69752a38012Sejakowatz UNIMPLEMENTED(); 69852a38012Sejakowatz return B_ERROR; 69952a38012Sejakowatz } 70052a38012Sejakowatz 70152a38012Sejakowatz 70252a38012Sejakowatz status_t 70352a38012Sejakowatz BMediaRoster::SetProducerRunModeDelay(const media_node & node, 70452a38012Sejakowatz bigtime_t delay, 70552a38012Sejakowatz BMediaNode::run_mode mode) 70652a38012Sejakowatz { 70752a38012Sejakowatz UNIMPLEMENTED(); 70852a38012Sejakowatz return B_ERROR; 70952a38012Sejakowatz } 71052a38012Sejakowatz 71152a38012Sejakowatz 71252a38012Sejakowatz status_t 71352a38012Sejakowatz BMediaRoster::SetProducerRate(const media_node & producer, 71452a38012Sejakowatz int32 numer, 71552a38012Sejakowatz int32 denom) 71652a38012Sejakowatz { 71752a38012Sejakowatz CALLED(); 71852a38012Sejakowatz if (producer.node == 0) 71952a38012Sejakowatz return B_MEDIA_BAD_NODE; 72052a38012Sejakowatz if ((producer.kind & B_BUFFER_PRODUCER) == 0) 72152a38012Sejakowatz return B_MEDIA_BAD_NODE; 72252a38012Sejakowatz 72352a38012Sejakowatz xfer_producer_set_play_rate msg; 72452a38012Sejakowatz xfer_producer_set_play_rate_reply reply; 72552a38012Sejakowatz status_t rv; 72652a38012Sejakowatz int32 code; 72752a38012Sejakowatz 72852a38012Sejakowatz msg.numer = numer; 72952a38012Sejakowatz msg.denom = denom; 73052a38012Sejakowatz msg.reply_port = _PortPool->GetPort(); 73152a38012Sejakowatz rv = write_port(producer.node, PRODUCER_SET_PLAY_RATE, &msg, sizeof(msg)); 73252a38012Sejakowatz if (rv != B_OK) { 73352a38012Sejakowatz _PortPool->PutPort(msg.reply_port); 73452a38012Sejakowatz return rv; 73552a38012Sejakowatz } 73652a38012Sejakowatz rv = read_port(msg.reply_port, &code, &reply, sizeof(reply)); 73752a38012Sejakowatz _PortPool->PutPort(msg.reply_port); 73852a38012Sejakowatz return (rv < B_OK) ? rv : reply.result; 73952a38012Sejakowatz } 74052a38012Sejakowatz 74152a38012Sejakowatz 74252a38012Sejakowatz 74352a38012Sejakowatz /* Nodes will have available inputs/outputs as long as they are capable */ 74452a38012Sejakowatz /* of accepting more connections. The node may create an additional */ 74552a38012Sejakowatz /* output or input as the currently available is taken into usage. */ 74652a38012Sejakowatz status_t 74752a38012Sejakowatz BMediaRoster::GetLiveNodeInfo(const media_node & node, 74852a38012Sejakowatz live_node_info * out_live_info) 74952a38012Sejakowatz { 75052a38012Sejakowatz UNIMPLEMENTED(); 75152a38012Sejakowatz return B_ERROR; 75252a38012Sejakowatz } 75352a38012Sejakowatz 75452a38012Sejakowatz 75552a38012Sejakowatz status_t 75652a38012Sejakowatz BMediaRoster::GetLiveNodes(live_node_info * out_live_nodes, 75752a38012Sejakowatz int32 * io_total_count, 75852a38012Sejakowatz const media_format * has_input, 75952a38012Sejakowatz const media_format * has_output, 76052a38012Sejakowatz const char * name, 76152a38012Sejakowatz uint64 node_kinds) 76252a38012Sejakowatz { 76352a38012Sejakowatz UNIMPLEMENTED(); 76452a38012Sejakowatz return B_ERROR; 76552a38012Sejakowatz } 76652a38012Sejakowatz 76752a38012Sejakowatz 76852a38012Sejakowatz status_t 76952a38012Sejakowatz BMediaRoster::GetFreeInputsFor(const media_node & node, 77052a38012Sejakowatz media_input * out_free_inputs, 77152a38012Sejakowatz int32 buf_num_inputs, 77252a38012Sejakowatz int32 * out_total_count, 77352a38012Sejakowatz media_type filter_type) 77452a38012Sejakowatz { 7753620737cSbeveloper CALLED(); 776*0caff283Sbeveloper if (node.node == 0 || (node.kind & B_BUFFER_CONSUMER) == 0) 7773620737cSbeveloper return B_MEDIA_BAD_NODE; 7783620737cSbeveloper if (out_free_inputs == NULL || out_total_count == NULL) 7793620737cSbeveloper return B_BAD_VALUE; 7803620737cSbeveloper 7813620737cSbeveloper Stack<media_input> stack; 7823620737cSbeveloper media_input *input; 7833620737cSbeveloper status_t rv; 7843620737cSbeveloper 7853620737cSbeveloper rv = GetAllInputs(node, &stack); 7863620737cSbeveloper if (B_OK != rv) 7873620737cSbeveloper return rv; 7883620737cSbeveloper 7893620737cSbeveloper *out_total_count = 0; 7903620737cSbeveloper for (int32 i = 0; stack.GetPointerAt(i, &input); i++) { 7913620737cSbeveloper if (filter_type != B_MEDIA_UNKNOWN_TYPE && filter_type != input->format.type) 7923620737cSbeveloper continue; // media_type used, but doesn't match 7933620737cSbeveloper if (input->source != media_source::null) 7943620737cSbeveloper continue; // consumer source already connected 7953620737cSbeveloper out_free_inputs[i] = *input; 7963620737cSbeveloper *out_total_count += 1; 7973620737cSbeveloper buf_num_inputs -= 1; 7983620737cSbeveloper if (buf_num_inputs == 0) 7993620737cSbeveloper break; 8003620737cSbeveloper } 8013620737cSbeveloper 8023620737cSbeveloper PublishInputs(node, &stack); 8033620737cSbeveloper return B_OK; 80452a38012Sejakowatz } 80552a38012Sejakowatz 80652a38012Sejakowatz 80752a38012Sejakowatz status_t 80852a38012Sejakowatz BMediaRoster::GetConnectedInputsFor(const media_node & node, 80952a38012Sejakowatz media_input * out_active_inputs, 81052a38012Sejakowatz int32 buf_num_inputs, 81152a38012Sejakowatz int32 * out_total_count) 81252a38012Sejakowatz { 8133620737cSbeveloper CALLED(); 814*0caff283Sbeveloper if (node.node == 0 || (node.kind & B_BUFFER_CONSUMER) == 0) 8153620737cSbeveloper return B_MEDIA_BAD_NODE; 8163620737cSbeveloper if (out_active_inputs == NULL || out_total_count == NULL) 8173620737cSbeveloper return B_BAD_VALUE; 8183620737cSbeveloper 8193620737cSbeveloper Stack<media_input> stack; 8203620737cSbeveloper media_input *input; 8213620737cSbeveloper status_t rv; 8223620737cSbeveloper 8233620737cSbeveloper rv = GetAllInputs(node, &stack); 8243620737cSbeveloper if (B_OK != rv) 8253620737cSbeveloper return rv; 8263620737cSbeveloper 8273620737cSbeveloper *out_total_count = 0; 8283620737cSbeveloper for (int32 i = 0; stack.GetPointerAt(i, &input); i++) { 8293620737cSbeveloper if (input->source == media_source::null) 8303620737cSbeveloper continue; // consumer source not connected 8313620737cSbeveloper out_active_inputs[i] = *input; 8323620737cSbeveloper *out_total_count += 1; 8333620737cSbeveloper buf_num_inputs -= 1; 8343620737cSbeveloper if (buf_num_inputs == 0) 8353620737cSbeveloper break; 8363620737cSbeveloper } 8373620737cSbeveloper 8383620737cSbeveloper PublishInputs(node, &stack); 8393620737cSbeveloper return B_OK; 84052a38012Sejakowatz } 84152a38012Sejakowatz 84252a38012Sejakowatz 84352a38012Sejakowatz status_t 84452a38012Sejakowatz BMediaRoster::GetAllInputsFor(const media_node & node, 84552a38012Sejakowatz media_input * out_inputs, 84652a38012Sejakowatz int32 buf_num_inputs, 84752a38012Sejakowatz int32 * out_total_count) 84852a38012Sejakowatz { 84952a38012Sejakowatz CALLED(); 85052a38012Sejakowatz if (node.node == 0 || (node.kind & B_BUFFER_CONSUMER) == 0) 85152a38012Sejakowatz return B_MEDIA_BAD_NODE; 85252a38012Sejakowatz if (out_inputs == NULL || out_total_count == NULL) 85352a38012Sejakowatz return B_BAD_VALUE; 85452a38012Sejakowatz 8553620737cSbeveloper Stack<media_input> stack; 8563620737cSbeveloper media_input *input; 85752a38012Sejakowatz status_t rv; 85852a38012Sejakowatz 8593620737cSbeveloper rv = GetAllInputs(node, &stack); 8603620737cSbeveloper if (B_OK != rv) 8613620737cSbeveloper return rv; 8623620737cSbeveloper 86352a38012Sejakowatz *out_total_count = 0; 8643620737cSbeveloper for (int32 i = 0; stack.GetPointerAt(i, &input); i++) { 8653620737cSbeveloper out_inputs[i] = *input; 86652a38012Sejakowatz *out_total_count += 1; 8673620737cSbeveloper buf_num_inputs -= 1; 8683620737cSbeveloper if (buf_num_inputs == 0) 8693620737cSbeveloper break; 87052a38012Sejakowatz } 87152a38012Sejakowatz 8723620737cSbeveloper PublishInputs(node, &stack); 8733620737cSbeveloper return B_OK; 87452a38012Sejakowatz } 87552a38012Sejakowatz 87652a38012Sejakowatz 87752a38012Sejakowatz status_t 87852a38012Sejakowatz BMediaRoster::GetFreeOutputsFor(const media_node & node, 87952a38012Sejakowatz media_output * out_free_outputs, 88052a38012Sejakowatz int32 buf_num_outputs, 88152a38012Sejakowatz int32 * out_total_count, 88252a38012Sejakowatz media_type filter_type) 88352a38012Sejakowatz { 8843620737cSbeveloper CALLED(); 8853620737cSbeveloper if (node.node == 0 || (node.kind & B_BUFFER_PRODUCER) == 0) 8863620737cSbeveloper return B_MEDIA_BAD_NODE; 8873620737cSbeveloper if (out_free_outputs == NULL || out_total_count == NULL) 8883620737cSbeveloper return B_BAD_VALUE; 8893620737cSbeveloper 8903620737cSbeveloper Stack<media_output> stack; 8913620737cSbeveloper media_output *output; 8923620737cSbeveloper status_t rv; 8933620737cSbeveloper 8943620737cSbeveloper rv = GetAllOutputs(node, &stack); 8953620737cSbeveloper if (B_OK != rv) 8963620737cSbeveloper return rv; 8973620737cSbeveloper 8983620737cSbeveloper *out_total_count = 0; 8993620737cSbeveloper for (int32 i = 0; stack.GetPointerAt(i, &output); i++) { 9003620737cSbeveloper if (filter_type != B_MEDIA_UNKNOWN_TYPE && filter_type != output->format.type) 9013620737cSbeveloper continue; // media_type used, but doesn't match 9023620737cSbeveloper if (output->destination != media_destination::null) 9033620737cSbeveloper continue; // producer destination already connected 9043620737cSbeveloper out_free_outputs[i] = *output; 9053620737cSbeveloper *out_total_count += 1; 9063620737cSbeveloper buf_num_outputs -= 1; 9073620737cSbeveloper if (buf_num_outputs == 0) 9083620737cSbeveloper break; 9093620737cSbeveloper } 9103620737cSbeveloper 9113620737cSbeveloper PublishOutputs(node, &stack); 9123620737cSbeveloper return B_OK; 91352a38012Sejakowatz } 91452a38012Sejakowatz 91552a38012Sejakowatz 91652a38012Sejakowatz status_t 91752a38012Sejakowatz BMediaRoster::GetConnectedOutputsFor(const media_node & node, 91852a38012Sejakowatz media_output * out_active_outputs, 91952a38012Sejakowatz int32 buf_num_outputs, 92052a38012Sejakowatz int32 * out_total_count) 92152a38012Sejakowatz { 9223620737cSbeveloper CALLED(); 9233620737cSbeveloper if (node.node == 0 || (node.kind & B_BUFFER_PRODUCER) == 0) 9243620737cSbeveloper return B_MEDIA_BAD_NODE; 9253620737cSbeveloper if (out_active_outputs == NULL || out_total_count == NULL) 9263620737cSbeveloper return B_BAD_VALUE; 9273620737cSbeveloper 9283620737cSbeveloper Stack<media_output> stack; 9293620737cSbeveloper media_output *output; 9303620737cSbeveloper status_t rv; 9313620737cSbeveloper 9323620737cSbeveloper rv = GetAllOutputs(node, &stack); 9333620737cSbeveloper if (B_OK != rv) 9343620737cSbeveloper return rv; 9353620737cSbeveloper 9363620737cSbeveloper *out_total_count = 0; 9373620737cSbeveloper for (int32 i = 0; stack.GetPointerAt(i, &output); i++) { 9383620737cSbeveloper if (output->destination == media_destination::null) 9393620737cSbeveloper continue; // producer destination not connected 9403620737cSbeveloper out_active_outputs[i] = *output; 9413620737cSbeveloper *out_total_count += 1; 9423620737cSbeveloper buf_num_outputs -= 1; 9433620737cSbeveloper if (buf_num_outputs == 0) 9443620737cSbeveloper break; 9453620737cSbeveloper } 9463620737cSbeveloper 9473620737cSbeveloper PublishOutputs(node, &stack); 9483620737cSbeveloper return B_OK; 94952a38012Sejakowatz } 95052a38012Sejakowatz 95152a38012Sejakowatz 95252a38012Sejakowatz status_t 95352a38012Sejakowatz BMediaRoster::GetAllOutputsFor(const media_node & node, 95452a38012Sejakowatz media_output * out_outputs, 95552a38012Sejakowatz int32 buf_num_outputs, 95652a38012Sejakowatz int32 * out_total_count) 95752a38012Sejakowatz { 95852a38012Sejakowatz CALLED(); 95952a38012Sejakowatz if (node.node == 0 || (node.kind & B_BUFFER_PRODUCER) == 0) 96052a38012Sejakowatz return B_MEDIA_BAD_NODE; 96152a38012Sejakowatz if (out_outputs == NULL || out_total_count == NULL) 96252a38012Sejakowatz return B_BAD_VALUE; 96352a38012Sejakowatz 9643620737cSbeveloper Stack<media_output> stack; 9653620737cSbeveloper media_output *output; 96652a38012Sejakowatz status_t rv; 96752a38012Sejakowatz 9683620737cSbeveloper rv = GetAllOutputs(node, &stack); 9693620737cSbeveloper if (B_OK != rv) 9703620737cSbeveloper return rv; 9713620737cSbeveloper 97252a38012Sejakowatz *out_total_count = 0; 9733620737cSbeveloper for (int32 i = 0; stack.GetPointerAt(i, &output); i++) { 9743620737cSbeveloper out_outputs[i] = *output; 97552a38012Sejakowatz *out_total_count += 1; 9763620737cSbeveloper buf_num_outputs -= 1; 9773620737cSbeveloper if (buf_num_outputs == 0) 9783620737cSbeveloper break; 97952a38012Sejakowatz } 98052a38012Sejakowatz 9813620737cSbeveloper PublishOutputs(node, &stack); 9823620737cSbeveloper return B_OK; 98352a38012Sejakowatz } 98452a38012Sejakowatz 98552a38012Sejakowatz 98652a38012Sejakowatz status_t 98752a38012Sejakowatz BMediaRoster::StartWatching(const BMessenger & where) 98852a38012Sejakowatz { 989eae26d3dSbeveloper CALLED(); 990eae26d3dSbeveloper if (!where.IsValid()) { 991eae26d3dSbeveloper TRACE("BMediaRoster::StartWatching: messenger invalid!\n"); 992eae26d3dSbeveloper return B_BAD_VALUE; 993eae26d3dSbeveloper } 994f4925104Sbeveloper return BPrivate::media::notifications::Register(where, media_node::null, B_MEDIA_WILDCARD); 99552a38012Sejakowatz } 99652a38012Sejakowatz 99752a38012Sejakowatz 99852a38012Sejakowatz status_t 99952a38012Sejakowatz BMediaRoster::StartWatching(const BMessenger & where, 100052a38012Sejakowatz int32 notificationType) 100152a38012Sejakowatz { 1002eae26d3dSbeveloper CALLED(); 1003eae26d3dSbeveloper if (!where.IsValid()) { 1004eae26d3dSbeveloper TRACE("BMediaRoster::StartWatching: messenger invalid!\n"); 1005eae26d3dSbeveloper return B_BAD_VALUE; 1006eae26d3dSbeveloper } 1007f4925104Sbeveloper if (false == BPrivate::media::notifications::IsValidNotificationRequest(false, notificationType)) { 1008eae26d3dSbeveloper TRACE("BMediaRoster::StartWatching: notificationType invalid!\n"); 1009eae26d3dSbeveloper return B_BAD_VALUE; 1010eae26d3dSbeveloper } 1011f4925104Sbeveloper return BPrivate::media::notifications::Register(where, media_node::null, notificationType); 101252a38012Sejakowatz } 101352a38012Sejakowatz 101452a38012Sejakowatz 101552a38012Sejakowatz status_t 101652a38012Sejakowatz BMediaRoster::StartWatching(const BMessenger & where, 101752a38012Sejakowatz const media_node & node, 101852a38012Sejakowatz int32 notificationType) 101952a38012Sejakowatz { 1020eae26d3dSbeveloper CALLED(); 1021eae26d3dSbeveloper if (!where.IsValid()) { 1022eae26d3dSbeveloper TRACE("BMediaRoster::StartWatching: messenger invalid!\n"); 1023eae26d3dSbeveloper return B_BAD_VALUE; 1024eae26d3dSbeveloper } 1025eae26d3dSbeveloper if (node.node == 0) { 1026eae26d3dSbeveloper TRACE("BMediaRoster::StartWatching: node invalid!\n"); 1027eae26d3dSbeveloper return B_MEDIA_BAD_NODE; 1028eae26d3dSbeveloper } 1029f4925104Sbeveloper if (false == BPrivate::media::notifications::IsValidNotificationRequest(true, notificationType)) { 1030eae26d3dSbeveloper TRACE("BMediaRoster::StartWatching: notificationType invalid!\n"); 1031eae26d3dSbeveloper return B_BAD_VALUE; 1032eae26d3dSbeveloper } 1033f4925104Sbeveloper return BPrivate::media::notifications::Register(where, node, notificationType); 103452a38012Sejakowatz } 103552a38012Sejakowatz 103652a38012Sejakowatz 103752a38012Sejakowatz status_t 103852a38012Sejakowatz BMediaRoster::StopWatching(const BMessenger & where) 103952a38012Sejakowatz { 1040eae26d3dSbeveloper CALLED(); 1041eae26d3dSbeveloper // messenger may already be invalid, so we don't check this 1042f4925104Sbeveloper return BPrivate::media::notifications::Unregister(where, media_node::null, B_MEDIA_WILDCARD); 104352a38012Sejakowatz } 104452a38012Sejakowatz 104552a38012Sejakowatz 104652a38012Sejakowatz status_t 104752a38012Sejakowatz BMediaRoster::StopWatching(const BMessenger & where, 104852a38012Sejakowatz int32 notificationType) 104952a38012Sejakowatz { 1050eae26d3dSbeveloper CALLED(); 1051eae26d3dSbeveloper // messenger may already be invalid, so we don't check this 1052f4925104Sbeveloper if (false == BPrivate::media::notifications::IsValidNotificationRequest(false, notificationType)) { 1053eae26d3dSbeveloper TRACE("BMediaRoster::StopWatching: notificationType invalid!\n"); 1054eae26d3dSbeveloper return B_BAD_VALUE; 1055eae26d3dSbeveloper } 1056f4925104Sbeveloper return BPrivate::media::notifications::Unregister(where, media_node::null, notificationType); 105752a38012Sejakowatz } 105852a38012Sejakowatz 105952a38012Sejakowatz 106052a38012Sejakowatz status_t 106152a38012Sejakowatz BMediaRoster::StopWatching(const BMessenger & where, 106252a38012Sejakowatz const media_node & node, 106352a38012Sejakowatz int32 notificationType) 106452a38012Sejakowatz { 1065eae26d3dSbeveloper CALLED(); 1066eae26d3dSbeveloper // messenger may already be invalid, so we don't check this 1067eae26d3dSbeveloper if (node.node == 0) { 1068eae26d3dSbeveloper TRACE("BMediaRoster::StopWatching: node invalid!\n"); 1069eae26d3dSbeveloper return B_MEDIA_BAD_NODE; 1070eae26d3dSbeveloper } 1071f4925104Sbeveloper if (false == BPrivate::media::notifications::IsValidNotificationRequest(true, notificationType)) { 1072eae26d3dSbeveloper TRACE("BMediaRoster::StopWatching: notificationType invalid!\n"); 1073eae26d3dSbeveloper return B_BAD_VALUE; 1074eae26d3dSbeveloper } 1075f4925104Sbeveloper return BPrivate::media::notifications::Unregister(where, node, notificationType); 107652a38012Sejakowatz } 107752a38012Sejakowatz 107852a38012Sejakowatz 107952a38012Sejakowatz status_t 108052a38012Sejakowatz BMediaRoster::RegisterNode(BMediaNode * node) 108152a38012Sejakowatz { 108252a38012Sejakowatz CALLED(); 108352a38012Sejakowatz if (node == NULL) 108452a38012Sejakowatz return B_BAD_VALUE; 108552a38012Sejakowatz 10863620737cSbeveloper status_t rv; 10873620737cSbeveloper 10883620737cSbeveloper // XXX fix node registration 108952a38012Sejakowatz xfer_node_registered msg; 109052a38012Sejakowatz msg.node_id = 1; 109152a38012Sejakowatz 10923620737cSbeveloper rv = node->HandleMessage(NODE_REGISTERED,&msg,sizeof(msg)); 10933620737cSbeveloper 10943620737cSbeveloper // register existing inputs and outputs with the 10953620737cSbeveloper // media_server, this allows GetLiveNodes() to work 10963620737cSbeveloper // with created, but unconnected nodes. 10973620737cSbeveloper if (node->Kinds() & B_BUFFER_PRODUCER) { 10983620737cSbeveloper Stack<media_output> stack; 10993620737cSbeveloper if (B_OK == GetAllOutputs(node->Node(), &stack)) 11003620737cSbeveloper PublishOutputs(node->Node(), &stack); 11013620737cSbeveloper } else if (node->Kinds() & B_BUFFER_CONSUMER) { 11023620737cSbeveloper Stack<media_input> stack; 11033620737cSbeveloper if (B_OK == GetAllInputs(node->Node(), &stack)) 11043620737cSbeveloper PublishInputs(node->Node(), &stack); 11053620737cSbeveloper } 11063620737cSbeveloper 11073620737cSbeveloper return rv; 110852a38012Sejakowatz } 110952a38012Sejakowatz 111052a38012Sejakowatz 111152a38012Sejakowatz status_t 111252a38012Sejakowatz BMediaRoster::UnregisterNode(BMediaNode * node) 111352a38012Sejakowatz { 111452a38012Sejakowatz UNIMPLEMENTED(); 111552a38012Sejakowatz return B_ERROR; 111652a38012Sejakowatz } 111752a38012Sejakowatz 111852a38012Sejakowatz 111952a38012Sejakowatz // thread safe for multiple calls to Roster() 112052a38012Sejakowatz /* static */ BMediaRoster * 112152a38012Sejakowatz BMediaRoster::Roster(status_t* out_error) 112252a38012Sejakowatz { 112352a38012Sejakowatz CALLED(); 112452a38012Sejakowatz static BLocker locker("BMediaRoster::Roster locker"); 112552a38012Sejakowatz locker.Lock(); 112652a38012Sejakowatz if (_sDefault == NULL) { 112752a38012Sejakowatz _sDefault = new BMediaRoster(); 112852a38012Sejakowatz if (out_error != NULL) 112952a38012Sejakowatz *out_error = B_OK; 113052a38012Sejakowatz } else { 113152a38012Sejakowatz if (out_error != NULL) 113252a38012Sejakowatz *out_error = B_OK; 113352a38012Sejakowatz } 113452a38012Sejakowatz locker.Unlock(); 113552a38012Sejakowatz return _sDefault; 113652a38012Sejakowatz } 113752a38012Sejakowatz 113852a38012Sejakowatz 113952a38012Sejakowatz // won't create it if there isn't one 114052a38012Sejakowatz // not thread safe if you call Roster() at the same time 114152a38012Sejakowatz /* static */ BMediaRoster * 114252a38012Sejakowatz BMediaRoster::CurrentRoster() 114352a38012Sejakowatz { 114452a38012Sejakowatz CALLED(); 114552a38012Sejakowatz return _sDefault; 114652a38012Sejakowatz } 114752a38012Sejakowatz 114852a38012Sejakowatz 114952a38012Sejakowatz status_t 115052a38012Sejakowatz BMediaRoster::SetTimeSourceFor(media_node_id node, 115152a38012Sejakowatz media_node_id time_source) 115252a38012Sejakowatz { 115352a38012Sejakowatz UNIMPLEMENTED(); 115452a38012Sejakowatz return B_ERROR; 115552a38012Sejakowatz } 115652a38012Sejakowatz 115752a38012Sejakowatz 115852a38012Sejakowatz status_t 115952a38012Sejakowatz BMediaRoster::GetParameterWebFor(const media_node & node, 116052a38012Sejakowatz BParameterWeb ** out_web) 116152a38012Sejakowatz { 116252a38012Sejakowatz UNIMPLEMENTED(); 116352a38012Sejakowatz return B_ERROR; 116452a38012Sejakowatz } 116552a38012Sejakowatz 116652a38012Sejakowatz 116752a38012Sejakowatz status_t 116852a38012Sejakowatz BMediaRoster::StartControlPanel(const media_node & node, 116952a38012Sejakowatz BMessenger * out_messenger) 117052a38012Sejakowatz { 117152a38012Sejakowatz UNIMPLEMENTED(); 117252a38012Sejakowatz return B_ERROR; 117352a38012Sejakowatz } 117452a38012Sejakowatz 117552a38012Sejakowatz 117652a38012Sejakowatz status_t 117752a38012Sejakowatz BMediaRoster::GetDormantNodes(dormant_node_info * out_info, 117852a38012Sejakowatz int32 * io_count, 117952a38012Sejakowatz const media_format * has_input /* = NULL */, 118052a38012Sejakowatz const media_format * has_output /* = NULL */, 118152a38012Sejakowatz const char * name /* = NULL */, 118252a38012Sejakowatz uint64 require_kinds /* = NULL */, 118352a38012Sejakowatz uint64 deny_kinds /* = NULL */) 118452a38012Sejakowatz { 118552a38012Sejakowatz CALLED(); 118652a38012Sejakowatz if (out_info == NULL) 118752a38012Sejakowatz return B_BAD_VALUE; 118852a38012Sejakowatz if (io_count == NULL) 118952a38012Sejakowatz return B_BAD_VALUE; 119052a38012Sejakowatz if (*io_count <= 0) 119152a38012Sejakowatz return B_BAD_VALUE; 119252a38012Sejakowatz 119352a38012Sejakowatz xfer_server_get_dormant_nodes msg; 119452a38012Sejakowatz port_id port; 119552a38012Sejakowatz status_t rv; 119652a38012Sejakowatz 119752a38012Sejakowatz port = find_port("media_server port"); 119852a38012Sejakowatz if (port <= B_OK) 119952a38012Sejakowatz return B_ERROR; 120052a38012Sejakowatz 120152a38012Sejakowatz msg.maxcount = *io_count; 120252a38012Sejakowatz msg.has_input = (bool) has_input; 120352a38012Sejakowatz if (has_input) 120452a38012Sejakowatz msg.inputformat = *has_input; // XXX we should not make a flat copy of media_format 120552a38012Sejakowatz msg.has_output = (bool) has_output; 120652a38012Sejakowatz if (has_output) 120752a38012Sejakowatz msg.outputformat = *has_output;; // XXX we should not make a flat copy of media_format 120852a38012Sejakowatz msg.has_name = (bool) name; 120952a38012Sejakowatz if (name) { 121052a38012Sejakowatz int len = min_c(strlen(name),sizeof(msg.name) - 1); 121152a38012Sejakowatz memcpy(msg.name,name,len); 121252a38012Sejakowatz msg.name[len] = 0; 121352a38012Sejakowatz } 121452a38012Sejakowatz msg.require_kinds = require_kinds; 121552a38012Sejakowatz msg.deny_kinds = deny_kinds; 121652a38012Sejakowatz msg.reply_port = _PortPool->GetPort(); 121752a38012Sejakowatz 121852a38012Sejakowatz rv = write_port(port, SERVER_GET_DORMANT_NODES, &msg, sizeof(msg)); 121952a38012Sejakowatz if (rv != B_OK) { 122052a38012Sejakowatz _PortPool->PutPort(msg.reply_port); 122152a38012Sejakowatz return rv; 122252a38012Sejakowatz } 122352a38012Sejakowatz 122452a38012Sejakowatz xfer_server_get_dormant_nodes_reply reply; 122552a38012Sejakowatz int32 code; 122652a38012Sejakowatz 122752a38012Sejakowatz rv = read_port(msg.reply_port, &code, &reply, sizeof(reply)); 122852a38012Sejakowatz if (rv < B_OK) { 122952a38012Sejakowatz _PortPool->PutPort(msg.reply_port); 123052a38012Sejakowatz return rv; 123152a38012Sejakowatz } 123252a38012Sejakowatz 123352a38012Sejakowatz *io_count = reply.count; 123452a38012Sejakowatz 123552a38012Sejakowatz if (*io_count > 0) { 123652a38012Sejakowatz rv = read_port(msg.reply_port, &code, out_info, *io_count * sizeof(dormant_node_info)); 123752a38012Sejakowatz if (rv < B_OK) 123852a38012Sejakowatz reply.result = rv; 123952a38012Sejakowatz } 124052a38012Sejakowatz _PortPool->PutPort(msg.reply_port); 124152a38012Sejakowatz 124252a38012Sejakowatz return reply.result; 124352a38012Sejakowatz } 124452a38012Sejakowatz 124552a38012Sejakowatz 124652a38012Sejakowatz status_t 124752a38012Sejakowatz BMediaRoster::InstantiateDormantNode(const dormant_node_info & in_info, 124852a38012Sejakowatz media_node * out_node, 124952a38012Sejakowatz uint32 flags /* currently B_FLAVOR_IS_GLOBAL or B_FLAVOR_IS_LOCAL */ ) 125052a38012Sejakowatz { 125152a38012Sejakowatz CALLED(); 125252a38012Sejakowatz if ((flags & (B_FLAVOR_IS_GLOBAL | B_FLAVOR_IS_LOCAL)) == 0) { 125352a38012Sejakowatz printf("Error: BMediaRoster::InstantiateDormantNode called without flags\n"); 125452a38012Sejakowatz return B_BAD_VALUE; 125552a38012Sejakowatz } 125652a38012Sejakowatz if (out_node == 0) 125752a38012Sejakowatz return B_BAD_VALUE; 125852a38012Sejakowatz 125952a38012Sejakowatz // XXX we should not trust the values passed in by the user, 126052a38012Sejakowatz // XXX and ask the server to determine where to insta 126152a38012Sejakowatz 1262e0207628Sbeveloper 1263e0207628Sbeveloper // XXX SOMETHING IS VERY WRONG HERE 1264e0207628Sbeveloper // if ((in_info.flavor_flags & B_FLAVOR_IS_GLOBAL) == 0 && (flags & B_FLAVOR_IS_LOCAL)) { 1265e0207628Sbeveloper if (flags & B_FLAVOR_IS_LOCAL) { 126652a38012Sejakowatz return InstantiateDormantNode(in_info,out_node); 126752a38012Sejakowatz } 126852a38012Sejakowatz 1269e0207628Sbeveloper // XXX SOMETHING IS VERY WRONG HERE 1270e0207628Sbeveloper // if ((in_info.flavor_flags & B_FLAVOR_IS_GLOBAL) || (flags & B_FLAVOR_IS_GLOBAL)) { 1271e0207628Sbeveloper if (flags & B_FLAVOR_IS_GLOBAL) { 127252a38012Sejakowatz // forward this request into the media_addon_server, 127352a38012Sejakowatz // which in turn will call InstantiateDormantNode() 127452a38012Sejakowatz // to create it there localy 12758c6a6096Sbeveloper addonserver_instantiate_dormant_node_request request; 12768c6a6096Sbeveloper addonserver_instantiate_dormant_node_reply reply; 127752a38012Sejakowatz status_t rv; 1278f4925104Sbeveloper 1279f4925104Sbeveloper request.info = in_info; 1280f4925104Sbeveloper rv = QueryAddonServer(ADDONSERVER_INSTANTIATE_DORMANT_NODE, &request, sizeof(request), &reply, sizeof(reply)); 1281f4925104Sbeveloper if (rv == B_OK) { 128252a38012Sejakowatz *out_node = reply.node; 1283f4925104Sbeveloper } 1284f4925104Sbeveloper return rv; 128552a38012Sejakowatz } 128652a38012Sejakowatz 1287e0207628Sbeveloper // XXX SOMETHING IS VERY WRONG HERE 12885edd2016Sbeveloper printf("Error: BMediaRoster::InstantiateDormantNode addon_id %d, flavor_id %d, flags %#08lx\n", (int)in_info.addon, (int)in_info.flavor_id, flags); 128952a38012Sejakowatz 129052a38012Sejakowatz return B_ERROR; 129152a38012Sejakowatz } 129252a38012Sejakowatz 129352a38012Sejakowatz 129452a38012Sejakowatz status_t 129552a38012Sejakowatz BMediaRoster::InstantiateDormantNode(const dormant_node_info & in_info, 129652a38012Sejakowatz media_node * out_node) 129752a38012Sejakowatz { 129816b7eea4Sbeveloper CALLED(); 129952a38012Sejakowatz 130052a38012Sejakowatz // to instantiate a dormant node in the current address space, we need to 130152a38012Sejakowatz // either load the add-on from file and create a new BMediaAddOn class, or 130252a38012Sejakowatz // reuse the cached BMediaAddOn from a previous call 130352a38012Sejakowatz // call BMediaAddOn::InstantiateNodeFor() 130452a38012Sejakowatz // and cache the BMediaAddOn after that for later reuse. 130552a38012Sejakowatz // BeOS R5 does not seem to delete it when the application quits 130652a38012Sejakowatz // if B_FLAVOR_IS_GLOBAL, we need to use the BMediaAddOn object that 130752a38012Sejakowatz // resides in the media_addon_server 130852a38012Sejakowatz 130952a38012Sejakowatz // RegisterNode() is called automatically for nodes instantiated from add-ons 131052a38012Sejakowatz 131116b7eea4Sbeveloper //XXX TEST! 131216b7eea4Sbeveloper BMediaAddOn *addon; 131316b7eea4Sbeveloper BMediaNode *node; 131416b7eea4Sbeveloper BMessage config; 131516b7eea4Sbeveloper status_t out_error; 13168c6a6096Sbeveloper status_t rv; 131716b7eea4Sbeveloper addon = _DormantNodeManager->GetAddon(in_info.addon); 131816b7eea4Sbeveloper if (!addon) { 131916b7eea4Sbeveloper printf("BMediaRoster::InstantiateDormantNode: GetAddon failed\n"); 132052a38012Sejakowatz return B_ERROR; 132152a38012Sejakowatz } 132216b7eea4Sbeveloper flavor_info temp; 132316b7eea4Sbeveloper temp.internal_id = in_info.flavor_id; 132416b7eea4Sbeveloper node = addon->InstantiateNodeFor(&temp, &config, &out_error); 132516b7eea4Sbeveloper if (!node) { 132616b7eea4Sbeveloper printf("BMediaRoster::InstantiateDormantNode: InstantiateNodeFor failed\n"); 132716b7eea4Sbeveloper _DormantNodeManager->PutAddon(in_info.addon); 132816b7eea4Sbeveloper return B_ERROR; 132916b7eea4Sbeveloper } 13308c6a6096Sbeveloper rv = RegisterNode(node); 13318c6a6096Sbeveloper if (rv != B_OK) { 13328c6a6096Sbeveloper printf("BMediaRoster::InstantiateDormantNode: RegisterNode failed\n"); 13338c6a6096Sbeveloper delete node; 13348c6a6096Sbeveloper _DormantNodeManager->PutAddon(in_info.addon); 13358c6a6096Sbeveloper return B_ERROR; 13368c6a6096Sbeveloper } 13378c6a6096Sbeveloper 13388c6a6096Sbeveloper // XXX we must remember in_info.addon and call 13398c6a6096Sbeveloper // XXX _DormantNodeManager->PutAddon when the 13408c6a6096Sbeveloper // XXX node is unregistered 13418c6a6096Sbeveloper 134216b7eea4Sbeveloper *out_node = node->Node(); 134316b7eea4Sbeveloper return B_OK; 134416b7eea4Sbeveloper } 134552a38012Sejakowatz 134652a38012Sejakowatz 134752a38012Sejakowatz status_t 134852a38012Sejakowatz BMediaRoster::GetDormantNodeFor(const media_node & node, 134952a38012Sejakowatz dormant_node_info * out_info) 135052a38012Sejakowatz { 135152a38012Sejakowatz UNIMPLEMENTED(); 135252a38012Sejakowatz 135352a38012Sejakowatz return B_ERROR; 135452a38012Sejakowatz } 135552a38012Sejakowatz 135652a38012Sejakowatz 135752a38012Sejakowatz status_t 135852a38012Sejakowatz BMediaRoster::GetDormantFlavorInfoFor(const dormant_node_info & in_dormant, 135952a38012Sejakowatz dormant_flavor_info * out_flavor) 136052a38012Sejakowatz { 136152a38012Sejakowatz CALLED(); 136252a38012Sejakowatz 136352a38012Sejakowatz xfer_server_get_dormant_flavor_info msg; 136452a38012Sejakowatz xfer_server_get_dormant_flavor_info_reply *reply; 136552a38012Sejakowatz port_id port; 136652a38012Sejakowatz status_t rv; 136752a38012Sejakowatz int32 code; 136852a38012Sejakowatz 136952a38012Sejakowatz port = find_port("media_server port"); 137052a38012Sejakowatz if (port <= B_OK) 137152a38012Sejakowatz return B_ERROR; 137252a38012Sejakowatz 137352a38012Sejakowatz reply = (xfer_server_get_dormant_flavor_info_reply *) malloc(16000); 137452a38012Sejakowatz if (reply == 0) 137552a38012Sejakowatz return B_ERROR; 137652a38012Sejakowatz 137752a38012Sejakowatz msg.addon = in_dormant.addon; 137852a38012Sejakowatz msg.flavor_id = in_dormant.flavor_id; 137952a38012Sejakowatz msg.reply_port = _PortPool->GetPort(); 138052a38012Sejakowatz rv = write_port(port, SERVER_GET_DORMANT_FLAVOR_INFO, &msg, sizeof(msg)); 138152a38012Sejakowatz if (rv != B_OK) { 138252a38012Sejakowatz free(reply); 138352a38012Sejakowatz _PortPool->PutPort(msg.reply_port); 138452a38012Sejakowatz return rv; 138552a38012Sejakowatz } 138652a38012Sejakowatz rv = read_port(msg.reply_port, &code, reply, 16000); 138752a38012Sejakowatz _PortPool->PutPort(msg.reply_port); 138852a38012Sejakowatz 138952a38012Sejakowatz if (rv < B_OK) { 139052a38012Sejakowatz free(reply); 139152a38012Sejakowatz return rv; 139252a38012Sejakowatz } 139352a38012Sejakowatz 139452a38012Sejakowatz if (reply->result == B_OK) 139552a38012Sejakowatz rv = out_flavor->Unflatten(reply->dfi_type, &reply->dfi, reply->dfi_size); 139652a38012Sejakowatz else 139752a38012Sejakowatz rv = reply->result; 139852a38012Sejakowatz 139952a38012Sejakowatz free(reply); 140052a38012Sejakowatz return rv; 140152a38012Sejakowatz } 140252a38012Sejakowatz 140352a38012Sejakowatz 140452a38012Sejakowatz status_t 140552a38012Sejakowatz BMediaRoster::GetLatencyFor(const media_node & producer, 140652a38012Sejakowatz bigtime_t * out_latency) 140752a38012Sejakowatz { 140852a38012Sejakowatz UNIMPLEMENTED(); 140952a38012Sejakowatz *out_latency = 0; 141052a38012Sejakowatz return B_ERROR; 141152a38012Sejakowatz } 141252a38012Sejakowatz 141352a38012Sejakowatz 141452a38012Sejakowatz status_t 141552a38012Sejakowatz BMediaRoster::GetInitialLatencyFor(const media_node & producer, 141652a38012Sejakowatz bigtime_t * out_latency, 141752a38012Sejakowatz uint32 * out_flags) 141852a38012Sejakowatz { 141952a38012Sejakowatz UNIMPLEMENTED(); 142052a38012Sejakowatz *out_latency = 0; 142152a38012Sejakowatz *out_flags = 0; 142252a38012Sejakowatz return B_ERROR; 142352a38012Sejakowatz } 142452a38012Sejakowatz 142552a38012Sejakowatz 142652a38012Sejakowatz status_t 142752a38012Sejakowatz BMediaRoster::GetStartLatencyFor(const media_node & time_source, 142852a38012Sejakowatz bigtime_t * out_latency) 142952a38012Sejakowatz { 143052a38012Sejakowatz UNIMPLEMENTED(); 143152a38012Sejakowatz *out_latency = 0; 143252a38012Sejakowatz return B_ERROR; 143352a38012Sejakowatz } 143452a38012Sejakowatz 143552a38012Sejakowatz 143652a38012Sejakowatz status_t 143752a38012Sejakowatz BMediaRoster::GetFileFormatsFor(const media_node & file_interface, 143852a38012Sejakowatz media_file_format * out_formats, 143952a38012Sejakowatz int32 * io_num_infos) 144052a38012Sejakowatz { 144152a38012Sejakowatz UNIMPLEMENTED(); 144252a38012Sejakowatz return B_ERROR; 144352a38012Sejakowatz } 144452a38012Sejakowatz 144552a38012Sejakowatz 144652a38012Sejakowatz status_t 144752a38012Sejakowatz BMediaRoster::SetRefFor(const media_node & file_interface, 144852a38012Sejakowatz const entry_ref & file, 144952a38012Sejakowatz bool create_and_truncate, 145052a38012Sejakowatz bigtime_t * out_length) /* if create is false */ 145152a38012Sejakowatz { 145252a38012Sejakowatz UNIMPLEMENTED(); 145352a38012Sejakowatz return B_ERROR; 145452a38012Sejakowatz } 145552a38012Sejakowatz 145652a38012Sejakowatz 145752a38012Sejakowatz status_t 145852a38012Sejakowatz BMediaRoster::GetRefFor(const media_node & node, 145952a38012Sejakowatz entry_ref * out_file, 146052a38012Sejakowatz BMimeType * mime_type) 146152a38012Sejakowatz { 146252a38012Sejakowatz UNIMPLEMENTED(); 146352a38012Sejakowatz return B_ERROR; 146452a38012Sejakowatz } 146552a38012Sejakowatz 146652a38012Sejakowatz 146752a38012Sejakowatz status_t 146852a38012Sejakowatz BMediaRoster::SniffRefFor(const media_node & file_interface, 146952a38012Sejakowatz const entry_ref & file, 147052a38012Sejakowatz BMimeType * mime_type, 147152a38012Sejakowatz float * out_capability) 147252a38012Sejakowatz { 147352a38012Sejakowatz UNIMPLEMENTED(); 147452a38012Sejakowatz return B_ERROR; 147552a38012Sejakowatz } 147652a38012Sejakowatz 147752a38012Sejakowatz 147852a38012Sejakowatz /* This is the generic "here's a file, now can someone please play it" interface */ 147952a38012Sejakowatz status_t 148052a38012Sejakowatz BMediaRoster::SniffRef(const entry_ref & file, 148152a38012Sejakowatz uint64 require_node_kinds, /* if you need an EntityInterface or BufferConsumer or something */ 148252a38012Sejakowatz dormant_node_info * out_node, 148352a38012Sejakowatz BMimeType * mime_type) 148452a38012Sejakowatz { 148552a38012Sejakowatz UNIMPLEMENTED(); 148652a38012Sejakowatz return B_ERROR; 148752a38012Sejakowatz } 148852a38012Sejakowatz 148952a38012Sejakowatz 149052a38012Sejakowatz status_t 149152a38012Sejakowatz BMediaRoster::GetDormantNodeForType(const BMimeType & type, 149252a38012Sejakowatz uint64 require_node_kinds, 149352a38012Sejakowatz dormant_node_info * out_node) 149452a38012Sejakowatz { 149552a38012Sejakowatz UNIMPLEMENTED(); 149652a38012Sejakowatz return B_ERROR; 149752a38012Sejakowatz } 149852a38012Sejakowatz 149952a38012Sejakowatz 150052a38012Sejakowatz status_t 150152a38012Sejakowatz BMediaRoster::GetReadFileFormatsFor(const dormant_node_info & in_node, 150252a38012Sejakowatz media_file_format * out_read_formats, 150352a38012Sejakowatz int32 in_read_count, 150452a38012Sejakowatz int32 * out_read_count) 150552a38012Sejakowatz { 150652a38012Sejakowatz UNIMPLEMENTED(); 150752a38012Sejakowatz return B_ERROR; 150852a38012Sejakowatz } 150952a38012Sejakowatz 151052a38012Sejakowatz 151152a38012Sejakowatz status_t 151252a38012Sejakowatz BMediaRoster::GetWriteFileFormatsFor(const dormant_node_info & in_node, 151352a38012Sejakowatz media_file_format * out_write_formats, 151452a38012Sejakowatz int32 in_write_count, 151552a38012Sejakowatz int32 * out_write_count) 151652a38012Sejakowatz { 151752a38012Sejakowatz UNIMPLEMENTED(); 151852a38012Sejakowatz return B_ERROR; 151952a38012Sejakowatz } 152052a38012Sejakowatz 152152a38012Sejakowatz 152252a38012Sejakowatz status_t 152352a38012Sejakowatz BMediaRoster::GetFormatFor(const media_output & output, 152452a38012Sejakowatz media_format * io_format, 152552a38012Sejakowatz uint32 flags) 152652a38012Sejakowatz { 152752a38012Sejakowatz UNIMPLEMENTED(); 152852a38012Sejakowatz return B_ERROR; 152952a38012Sejakowatz } 153052a38012Sejakowatz 153152a38012Sejakowatz 153252a38012Sejakowatz status_t 153352a38012Sejakowatz BMediaRoster::GetFormatFor(const media_input & input, 153452a38012Sejakowatz media_format * io_format, 153552a38012Sejakowatz uint32 flags) 153652a38012Sejakowatz { 153752a38012Sejakowatz UNIMPLEMENTED(); 153852a38012Sejakowatz return B_ERROR; 153952a38012Sejakowatz } 154052a38012Sejakowatz 154152a38012Sejakowatz 154252a38012Sejakowatz status_t 154352a38012Sejakowatz BMediaRoster::GetFormatFor(const media_node & node, 154452a38012Sejakowatz media_format * io_format, 154552a38012Sejakowatz float quality) 154652a38012Sejakowatz { 154752a38012Sejakowatz UNIMPLEMENTED(); 154852a38012Sejakowatz return B_ERROR; 154952a38012Sejakowatz } 155052a38012Sejakowatz 155152a38012Sejakowatz 155252a38012Sejakowatz ssize_t 155352a38012Sejakowatz BMediaRoster::GetNodeAttributesFor(const media_node & node, 155452a38012Sejakowatz media_node_attribute * outArray, 155552a38012Sejakowatz size_t inMaxCount) 155652a38012Sejakowatz { 155752a38012Sejakowatz UNIMPLEMENTED(); 155852a38012Sejakowatz return B_ERROR; 155952a38012Sejakowatz } 156052a38012Sejakowatz 156152a38012Sejakowatz 156252a38012Sejakowatz media_node_id 156352a38012Sejakowatz BMediaRoster::NodeIDFor(port_id source_or_destination_port) 156452a38012Sejakowatz { 156552a38012Sejakowatz UNIMPLEMENTED(); 156652a38012Sejakowatz return B_ERROR; 156752a38012Sejakowatz } 156852a38012Sejakowatz 156952a38012Sejakowatz 157052a38012Sejakowatz status_t 157152a38012Sejakowatz BMediaRoster::GetInstancesFor(media_addon_id addon, 157252a38012Sejakowatz int32 flavor, 157352a38012Sejakowatz media_node_id * out_id, 157452a38012Sejakowatz int32 * io_count) 157552a38012Sejakowatz { 157652a38012Sejakowatz UNIMPLEMENTED(); 157752a38012Sejakowatz return B_ERROR; 157852a38012Sejakowatz } 157952a38012Sejakowatz 158052a38012Sejakowatz 158152a38012Sejakowatz 158252a38012Sejakowatz status_t 158352a38012Sejakowatz BMediaRoster::SetRealtimeFlags(uint32 in_enabled) 158452a38012Sejakowatz { 158552a38012Sejakowatz UNIMPLEMENTED(); 158652a38012Sejakowatz return B_ERROR; 158752a38012Sejakowatz } 158852a38012Sejakowatz 158952a38012Sejakowatz 159052a38012Sejakowatz status_t 159152a38012Sejakowatz BMediaRoster::GetRealtimeFlags(uint32 * out_enabled) 159252a38012Sejakowatz { 159352a38012Sejakowatz UNIMPLEMENTED(); 159452a38012Sejakowatz return B_ERROR; 159552a38012Sejakowatz } 159652a38012Sejakowatz 159752a38012Sejakowatz 159852a38012Sejakowatz ssize_t 159952a38012Sejakowatz BMediaRoster::AudioBufferSizeFor(int32 channel_count, 160052a38012Sejakowatz uint32 sample_format, 160152a38012Sejakowatz float frame_rate, 160252a38012Sejakowatz bus_type bus_kind) 160352a38012Sejakowatz { 160452a38012Sejakowatz UNIMPLEMENTED(); 160552a38012Sejakowatz return 4096; 160652a38012Sejakowatz } 160752a38012Sejakowatz 160852a38012Sejakowatz 160952a38012Sejakowatz /* Use MediaFlags to inquire about specific features of the Media Kit. */ 161052a38012Sejakowatz /* Returns < 0 for "not present", positive size for output data size. */ 161152a38012Sejakowatz /* 0 means that the capability is present, but no data about it. */ 161252a38012Sejakowatz /* static */ ssize_t 161352a38012Sejakowatz BMediaRoster::MediaFlags(media_flags cap, 161452a38012Sejakowatz void * buf, 161552a38012Sejakowatz size_t maxSize) 161652a38012Sejakowatz { 161752a38012Sejakowatz UNIMPLEMENTED(); 161852a38012Sejakowatz return 0; 161952a38012Sejakowatz } 162052a38012Sejakowatz 162152a38012Sejakowatz 162252a38012Sejakowatz 162352a38012Sejakowatz /* BLooper overrides */ 162452a38012Sejakowatz /* virtual */ void 162552a38012Sejakowatz BMediaRoster::MessageReceived(BMessage * message) 162652a38012Sejakowatz { 162752a38012Sejakowatz UNIMPLEMENTED(); 162852a38012Sejakowatz } 162952a38012Sejakowatz 163052a38012Sejakowatz /* virtual */ bool 163152a38012Sejakowatz BMediaRoster::QuitRequested() 163252a38012Sejakowatz { 163352a38012Sejakowatz UNIMPLEMENTED(); 163452a38012Sejakowatz return true; 163552a38012Sejakowatz } 163652a38012Sejakowatz 163752a38012Sejakowatz /* virtual */ BHandler * 163852a38012Sejakowatz BMediaRoster::ResolveSpecifier(BMessage *msg, 163952a38012Sejakowatz int32 index, 164052a38012Sejakowatz BMessage *specifier, 164152a38012Sejakowatz int32 form, 164252a38012Sejakowatz const char *property) 164352a38012Sejakowatz { 164452a38012Sejakowatz UNIMPLEMENTED(); 164552a38012Sejakowatz return 0; 164652a38012Sejakowatz } 164752a38012Sejakowatz 164852a38012Sejakowatz 164952a38012Sejakowatz /* virtual */ status_t 165052a38012Sejakowatz BMediaRoster::GetSupportedSuites(BMessage *data) 165152a38012Sejakowatz { 165252a38012Sejakowatz UNIMPLEMENTED(); 165352a38012Sejakowatz return B_ERROR; 165452a38012Sejakowatz } 165552a38012Sejakowatz 165652a38012Sejakowatz 165752a38012Sejakowatz BMediaRoster::~BMediaRoster() 165852a38012Sejakowatz { 165952a38012Sejakowatz CALLED(); 166052a38012Sejakowatz BMessage msg(MEDIA_SERVER_UNREGISTER_APP); 166152a38012Sejakowatz BMessage reply; 166252a38012Sejakowatz msg.AddInt32("team",team); 1663f4925104Sbeveloper QueryServer(&msg, &reply); 166452a38012Sejakowatz } 166552a38012Sejakowatz 166652a38012Sejakowatz 166752a38012Sejakowatz /************************************************************* 166852a38012Sejakowatz * private BMediaRoster 166952a38012Sejakowatz *************************************************************/ 167052a38012Sejakowatz 167152a38012Sejakowatz // deprecated call 167252a38012Sejakowatz status_t 167352a38012Sejakowatz BMediaRoster::SetOutputBuffersFor(const media_source & output, 167452a38012Sejakowatz BBufferGroup * group, 167552a38012Sejakowatz bool will_reclaim ) 167652a38012Sejakowatz { 167752a38012Sejakowatz UNIMPLEMENTED(); 167852a38012Sejakowatz return B_ERROR; 167952a38012Sejakowatz } 168052a38012Sejakowatz 168152a38012Sejakowatz 168252a38012Sejakowatz /* FBC stuffing (Mmmh, Stuffing!) */ 168352a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_0(void *) { return B_ERROR; } 168452a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_1(void *) { return B_ERROR; } 168552a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_2(void *) { return B_ERROR; } 168652a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_3(void *) { return B_ERROR; } 168752a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_4(void *) { return B_ERROR; } 168852a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_5(void *) { return B_ERROR; } 168952a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_6(void *) { return B_ERROR; } 169052a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_7(void *) { return B_ERROR; } 169152a38012Sejakowatz 169252a38012Sejakowatz 169352a38012Sejakowatz BMediaRoster::BMediaRoster() : 169452a38012Sejakowatz BLooper("BMediaRoster looper",B_NORMAL_PRIORITY,B_LOOPER_PORT_DEFAULT_CAPACITY) 169552a38012Sejakowatz { 169652a38012Sejakowatz CALLED(); 169752a38012Sejakowatz BMessage msg(MEDIA_SERVER_REGISTER_APP); 169852a38012Sejakowatz BMessage reply; 169952a38012Sejakowatz msg.AddInt32("team",team); 1700f4925104Sbeveloper QueryServer(&msg,&reply); 170152a38012Sejakowatz } 170252a38012Sejakowatz 170352a38012Sejakowatz /* static */ status_t 170452a38012Sejakowatz BMediaRoster::ParseCommand(BMessage & reply) 170552a38012Sejakowatz { 170652a38012Sejakowatz UNIMPLEMENTED(); 170752a38012Sejakowatz return B_ERROR; 170852a38012Sejakowatz } 170952a38012Sejakowatz 171052a38012Sejakowatz 171152a38012Sejakowatz 171252a38012Sejakowatz status_t 171352a38012Sejakowatz BMediaRoster::GetDefaultInfo(media_node_id for_default, 171452a38012Sejakowatz BMessage & out_config) 171552a38012Sejakowatz { 171652a38012Sejakowatz UNIMPLEMENTED(); 171752a38012Sejakowatz return B_ERROR; 171852a38012Sejakowatz } 171952a38012Sejakowatz 172052a38012Sejakowatz 172152a38012Sejakowatz 172252a38012Sejakowatz status_t 172352a38012Sejakowatz BMediaRoster::SetRunningDefault(media_node_id for_default, 172452a38012Sejakowatz const media_node & node) 172552a38012Sejakowatz { 172652a38012Sejakowatz UNIMPLEMENTED(); 172752a38012Sejakowatz return B_ERROR; 172852a38012Sejakowatz } 172952a38012Sejakowatz 173052a38012Sejakowatz 173152a38012Sejakowatz /************************************************************* 173252a38012Sejakowatz * static BMediaRoster variables 173352a38012Sejakowatz *************************************************************/ 173452a38012Sejakowatz 173552a38012Sejakowatz bool BMediaRoster::_isMediaServer; 173652a38012Sejakowatz port_id BMediaRoster::_mReplyPort; 173752a38012Sejakowatz int32 BMediaRoster::_mReplyPortRes; 173852a38012Sejakowatz int32 BMediaRoster::_mReplyPortUnavailCount; 173952a38012Sejakowatz BMediaRoster * BMediaRoster::_sDefault = NULL; 174052a38012Sejakowatz 1741