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 #define DEBUG 3 159e9417d2Sbeveloper #include <Debug.h> 1652a38012Sejakowatz #include "debug.h" 173620737cSbeveloper #include "TStack.h" 1852a38012Sejakowatz #include "PortPool.h" 191299bfb2Sbeveloper #include "SystemTimeSource.h" 200a483e72SIngo Weinhold #include "ServerInterface.h" 21f4925104Sbeveloper #include "DataExchange.h" 2216b7eea4Sbeveloper #include "DormantNodeManager.h" 23f4925104Sbeveloper #include "Notifications.h" 2452a38012Sejakowatz 25f4925104Sbeveloper namespace BPrivate { namespace media { 26f4925104Sbeveloper extern team_id team; 273620737cSbeveloper } } // BPrivate::media 283620737cSbeveloper 293620737cSbeveloper using namespace BPrivate::media; 3052a38012Sejakowatz 3152a38012Sejakowatz // the BMediaRoster destructor is private, 3252a38012Sejakowatz // but _DefaultDeleter is a friend class of 3352a38012Sejakowatz // the BMediaRoster an thus can delete it 3452a38012Sejakowatz class _DefaultDeleter 3552a38012Sejakowatz { 3652a38012Sejakowatz public: 37*6396865dSbeveloper ~_DefaultDeleter() 38*6396865dSbeveloper { 39*6396865dSbeveloper if (BMediaRoster::_sDefault) { 40*6396865dSbeveloper BMediaRoster::_sDefault->Lock(); 41*6396865dSbeveloper BMediaRoster::_sDefault->Quit(); 42*6396865dSbeveloper } 43*6396865dSbeveloper } 44*6396865dSbeveloper } _deleter; 4552a38012Sejakowatz 463620737cSbeveloper namespace BPrivate { namespace media { namespace mediaroster { 4752a38012Sejakowatz 4852a38012Sejakowatz status_t GetNode(node_type type, media_node * out_node, int32 * out_input_id = NULL, BString * out_input_name = NULL); 4952a38012Sejakowatz status_t SetNode(node_type type, const media_node *node, const dormant_node_info *info = NULL, const media_input *input = NULL); 503620737cSbeveloper status_t GetAllOutputs(const media_node & node, Stack<media_output> *stack); 513620737cSbeveloper status_t GetAllInputs(const media_node & node, Stack<media_input> *stack); 523620737cSbeveloper status_t PublishOutputs(const media_node & node, Stack<media_output> *stack); 533620737cSbeveloper status_t PublishInputs(const media_node & node, Stack<media_input> *stack); 5452a38012Sejakowatz 553620737cSbeveloper status_t 563620737cSbeveloper GetNode(node_type type, media_node * out_node, int32 * out_input_id, BString * out_input_name) 5752a38012Sejakowatz { 5852a38012Sejakowatz if (out_node == NULL) 5952a38012Sejakowatz return B_BAD_VALUE; 6052a38012Sejakowatz 618c6a6096Sbeveloper server_get_node_request request; 628c6a6096Sbeveloper server_get_node_reply reply; 6352a38012Sejakowatz status_t rv; 6452a38012Sejakowatz 658c6a6096Sbeveloper request.type = type; 669e9417d2Sbeveloper request.team = team; 678c6a6096Sbeveloper rv = QueryServer(SERVER_GET_NODE, &request, sizeof(request), &reply, sizeof(reply)); 688c6a6096Sbeveloper if (rv != B_OK) 698c6a6096Sbeveloper return rv; 7052a38012Sejakowatz 7152a38012Sejakowatz *out_node = reply.node; 7252a38012Sejakowatz if (out_input_id) 7352a38012Sejakowatz *out_input_id = reply.input_id; 7452a38012Sejakowatz if (out_input_name) 7552a38012Sejakowatz *out_input_name = reply.input_name; 768c6a6096Sbeveloper return rv; 7752a38012Sejakowatz } 7852a38012Sejakowatz 793620737cSbeveloper status_t 803620737cSbeveloper SetNode(node_type type, const media_node *node, const dormant_node_info *info, const media_input *input) 8152a38012Sejakowatz { 828c6a6096Sbeveloper server_set_node_request request; 838c6a6096Sbeveloper server_set_node_reply reply; 8452a38012Sejakowatz 858c6a6096Sbeveloper request.type = type; 868c6a6096Sbeveloper request.use_node = node ? true : false; 8752a38012Sejakowatz if (node) 888c6a6096Sbeveloper request.node = *node; 898c6a6096Sbeveloper request.use_dni = info ? true : false; 9052a38012Sejakowatz if (info) 918c6a6096Sbeveloper request.dni = *info; 928c6a6096Sbeveloper request.use_input = input ? true : false; 9352a38012Sejakowatz if (input) 948c6a6096Sbeveloper request.input = *input; 9552a38012Sejakowatz 968c6a6096Sbeveloper return QueryServer(SERVER_SET_NODE, &request, sizeof(request), &reply, sizeof(reply)); 9752a38012Sejakowatz } 9852a38012Sejakowatz 993620737cSbeveloper status_t 1003620737cSbeveloper GetAllOutputs(const media_node & node, Stack<media_output> *stack) 1013620737cSbeveloper { 1023620737cSbeveloper int32 cookie; 1033620737cSbeveloper status_t rv; 1043620737cSbeveloper status_t result; 1053620737cSbeveloper 1063620737cSbeveloper result = B_OK; 1073620737cSbeveloper cookie = 0; 1083620737cSbeveloper for (;;) { 1093620737cSbeveloper producer_get_next_output_request request; 1103620737cSbeveloper producer_get_next_output_reply reply; 1113620737cSbeveloper request.cookie = cookie; 1120caff283Sbeveloper rv = QueryPort(node.port, PRODUCER_GET_NEXT_OUTPUT, &request, sizeof(request), &reply, sizeof(reply)); 1133620737cSbeveloper if (rv != B_OK) 1143620737cSbeveloper break; 1153620737cSbeveloper cookie = reply.cookie; 1163620737cSbeveloper if (!stack->Push(reply.output)) { 1173620737cSbeveloper TRACE("GetAllOutputs: stack->Push failed\n"); 1183620737cSbeveloper result = B_ERROR; 1193620737cSbeveloper } 1203620737cSbeveloper } 1213620737cSbeveloper 1223620737cSbeveloper producer_dispose_output_cookie_request request; 1233620737cSbeveloper producer_dispose_output_cookie_reply reply; 1240caff283Sbeveloper QueryPort(node.port, PRODUCER_DISPOSE_OUTPUT_COOKIE, &request, sizeof(request), &reply, sizeof(reply)); 1253620737cSbeveloper 1263620737cSbeveloper return result; 1273620737cSbeveloper } 1283620737cSbeveloper 1293620737cSbeveloper status_t 1303620737cSbeveloper GetAllInputs(const media_node & node, Stack<media_input> *stack) 1313620737cSbeveloper { 1323620737cSbeveloper int32 cookie; 1333620737cSbeveloper status_t rv; 1343620737cSbeveloper status_t result; 1353620737cSbeveloper 1363620737cSbeveloper result = B_OK; 1373620737cSbeveloper cookie = 0; 1383620737cSbeveloper for (;;) { 1393620737cSbeveloper consumer_get_next_input_request request; 1403620737cSbeveloper consumer_get_next_input_reply reply; 1413620737cSbeveloper request.cookie = cookie; 1420caff283Sbeveloper rv = QueryPort(node.port, CONSUMER_GET_NEXT_INPUT, &request, sizeof(request), &reply, sizeof(reply)); 1433620737cSbeveloper if (rv != B_OK) 1443620737cSbeveloper break; 1453620737cSbeveloper cookie = reply.cookie; 1463620737cSbeveloper if (!stack->Push(reply.input)) { 1473620737cSbeveloper TRACE("GetAllInputs: stack->Push failed\n"); 1483620737cSbeveloper result = B_ERROR; 1493620737cSbeveloper } 1503620737cSbeveloper } 1513620737cSbeveloper 1523620737cSbeveloper consumer_dispose_input_cookie_request request; 1533620737cSbeveloper consumer_dispose_input_cookie_reply reply; 1540caff283Sbeveloper QueryPort(node.port, CONSUMER_DISPOSE_INPUT_COOKIE, &request, sizeof(request), &reply, sizeof(reply)); 1553620737cSbeveloper 1563620737cSbeveloper return result; 1573620737cSbeveloper } 1583620737cSbeveloper 1593620737cSbeveloper status_t 1603620737cSbeveloper PublishOutputs(const media_node & node, Stack<media_output> *stack) 1613620737cSbeveloper { 1623620737cSbeveloper server_publish_outputs_request request; 1633620737cSbeveloper server_publish_outputs_reply reply; 1643620737cSbeveloper media_output *output; 1653620737cSbeveloper media_output *outputs; 1663620737cSbeveloper int32 count; 167a7b41a96Sbeveloper status_t rv; 1683620737cSbeveloper 1693620737cSbeveloper count = stack->CountItems(); 1703620737cSbeveloper TRACE("PublishOutputs: publishing %ld\n", count); 1713620737cSbeveloper 1723620737cSbeveloper request.node = node; 1733620737cSbeveloper request.count = count; 1743620737cSbeveloper if (count > MAX_OUTPUTS) { 1753620737cSbeveloper void *start_addr; 1763620737cSbeveloper size_t size; 1773620737cSbeveloper size = ((count * sizeof(media_output)) + B_PAGE_SIZE - 1) & ~(B_PAGE_SIZE - 1); 1783620737cSbeveloper request.area = create_area("publish outputs", &start_addr, B_ANY_ADDRESS, size, B_NO_LOCK, B_READ_AREA | B_WRITE_AREA); 1793620737cSbeveloper if (request.area < B_OK) { 1803620737cSbeveloper TRACE("PublishOutputs: failed to create area, %#lx\n", request.area); 1813620737cSbeveloper return (status_t)request.area; 1823620737cSbeveloper } 1833620737cSbeveloper outputs = static_cast<media_output *>(start_addr); 1843620737cSbeveloper } else { 1853620737cSbeveloper request.area = -1; 1863620737cSbeveloper outputs = request.outputs; 1873620737cSbeveloper } 1883620737cSbeveloper TRACE("PublishOutputs: area %#lx\n", request.area); 1893620737cSbeveloper 1903620737cSbeveloper for (int32 i = 0; i != count; i++) { 1913620737cSbeveloper stack->GetPointerAt(i, &output); 1923620737cSbeveloper outputs[i] = *output; 1933620737cSbeveloper } 1943620737cSbeveloper 195a7b41a96Sbeveloper rv = QueryServer(SERVER_PUBLISH_OUTPUTS, &request, sizeof(request), &reply, sizeof(reply)); 196a7b41a96Sbeveloper 197a7b41a96Sbeveloper if (request.area != -1) 198a7b41a96Sbeveloper delete_area(request.area); 199a7b41a96Sbeveloper 200a7b41a96Sbeveloper return rv; 2013620737cSbeveloper } 2023620737cSbeveloper 2033620737cSbeveloper status_t 2043620737cSbeveloper PublishInputs(const media_node & node, Stack<media_input> *stack) 2053620737cSbeveloper { 2063620737cSbeveloper server_publish_inputs_request request; 2073620737cSbeveloper server_publish_inputs_reply reply; 2083620737cSbeveloper media_input *input; 2093620737cSbeveloper media_input *inputs; 2103620737cSbeveloper int32 count; 211a7b41a96Sbeveloper status_t rv; 2123620737cSbeveloper 2133620737cSbeveloper count = stack->CountItems(); 2143620737cSbeveloper TRACE("PublishInputs: publishing %ld\n", count); 2153620737cSbeveloper 2163620737cSbeveloper request.node = node; 2173620737cSbeveloper request.count = count; 2183620737cSbeveloper if (count > MAX_INPUTS) { 2193620737cSbeveloper void *start_addr; 2203620737cSbeveloper size_t size; 2213620737cSbeveloper size = ((count * sizeof(media_input)) + B_PAGE_SIZE - 1) & ~(B_PAGE_SIZE - 1); 2223620737cSbeveloper request.area = create_area("publish inputs", &start_addr, B_ANY_ADDRESS, size, B_NO_LOCK, B_READ_AREA | B_WRITE_AREA); 2233620737cSbeveloper if (request.area < B_OK) { 2243620737cSbeveloper TRACE("PublishInputs: failed to create area, %#lx\n", request.area); 2253620737cSbeveloper return (status_t)request.area; 2263620737cSbeveloper } 2273620737cSbeveloper inputs = static_cast<media_input *>(start_addr); 2283620737cSbeveloper } else { 2293620737cSbeveloper request.area = -1; 2303620737cSbeveloper inputs = request.inputs; 2313620737cSbeveloper } 2323620737cSbeveloper TRACE("PublishInputs: area %#lx\n", request.area); 2333620737cSbeveloper 2343620737cSbeveloper for (int32 i = 0; i != count; i++) { 2353620737cSbeveloper stack->GetPointerAt(i, &input); 2363620737cSbeveloper inputs[i] = *input; 2373620737cSbeveloper } 2383620737cSbeveloper 239a7b41a96Sbeveloper rv = QueryServer(SERVER_PUBLISH_INPUTS, &request, sizeof(request), &reply, sizeof(reply)); 240a7b41a96Sbeveloper 241a7b41a96Sbeveloper if (request.area != -1) 242a7b41a96Sbeveloper delete_area(request.area); 243a7b41a96Sbeveloper 244a7b41a96Sbeveloper return rv; 2453620737cSbeveloper } 2463620737cSbeveloper 2473620737cSbeveloper } } } // namespace BPrivate::media::mediaroster 2483620737cSbeveloper 2493620737cSbeveloper using namespace BPrivate::media::mediaroster; 25052a38012Sejakowatz 25152a38012Sejakowatz /************************************************************* 25252a38012Sejakowatz * public BMediaRoster 25352a38012Sejakowatz *************************************************************/ 25452a38012Sejakowatz 25552a38012Sejakowatz status_t 25652a38012Sejakowatz BMediaRoster::GetVideoInput(media_node * out_node) 25752a38012Sejakowatz { 25852a38012Sejakowatz CALLED(); 2593620737cSbeveloper return GetNode(VIDEO_INPUT, out_node); 26052a38012Sejakowatz } 26152a38012Sejakowatz 26252a38012Sejakowatz 26352a38012Sejakowatz status_t 26452a38012Sejakowatz BMediaRoster::GetAudioInput(media_node * out_node) 26552a38012Sejakowatz { 26652a38012Sejakowatz CALLED(); 2673620737cSbeveloper return GetNode(AUDIO_INPUT, out_node); 26852a38012Sejakowatz } 26952a38012Sejakowatz 27052a38012Sejakowatz 27152a38012Sejakowatz status_t 27252a38012Sejakowatz BMediaRoster::GetVideoOutput(media_node * out_node) 27352a38012Sejakowatz { 27452a38012Sejakowatz CALLED(); 2753620737cSbeveloper return GetNode(VIDEO_OUTPUT, out_node); 27652a38012Sejakowatz } 27752a38012Sejakowatz 27852a38012Sejakowatz 27952a38012Sejakowatz status_t 28052a38012Sejakowatz BMediaRoster::GetAudioMixer(media_node * out_node) 28152a38012Sejakowatz { 28252a38012Sejakowatz CALLED(); 2833620737cSbeveloper return GetNode(AUDIO_MIXER, out_node); 28452a38012Sejakowatz } 28552a38012Sejakowatz 28652a38012Sejakowatz 28752a38012Sejakowatz status_t 28852a38012Sejakowatz BMediaRoster::GetAudioOutput(media_node * out_node) 28952a38012Sejakowatz { 29052a38012Sejakowatz CALLED(); 2913620737cSbeveloper return GetNode(AUDIO_OUTPUT, out_node); 29252a38012Sejakowatz } 29352a38012Sejakowatz 29452a38012Sejakowatz 29552a38012Sejakowatz status_t 29652a38012Sejakowatz BMediaRoster::GetAudioOutput(media_node * out_node, 29752a38012Sejakowatz int32 * out_input_id, 29852a38012Sejakowatz BString * out_input_name) 29952a38012Sejakowatz { 30052a38012Sejakowatz CALLED(); 3013620737cSbeveloper return GetNode(AUDIO_OUTPUT_EX, out_node, out_input_id, out_input_name); 30252a38012Sejakowatz } 30352a38012Sejakowatz 30452a38012Sejakowatz 30552a38012Sejakowatz status_t 30652a38012Sejakowatz BMediaRoster::GetTimeSource(media_node * out_node) 30752a38012Sejakowatz { 30852a38012Sejakowatz CALLED(); 3093620737cSbeveloper return GetNode(TIME_SOURCE, out_node); 31052a38012Sejakowatz } 31152a38012Sejakowatz 31252a38012Sejakowatz 31352a38012Sejakowatz status_t 31452a38012Sejakowatz BMediaRoster::SetVideoInput(const media_node & producer) 31552a38012Sejakowatz { 31652a38012Sejakowatz CALLED(); 3173620737cSbeveloper return SetNode(VIDEO_INPUT, &producer); 31852a38012Sejakowatz } 31952a38012Sejakowatz 32052a38012Sejakowatz 32152a38012Sejakowatz status_t 32252a38012Sejakowatz BMediaRoster::SetVideoInput(const dormant_node_info & producer) 32352a38012Sejakowatz { 32452a38012Sejakowatz CALLED(); 3253620737cSbeveloper return SetNode(VIDEO_INPUT, NULL, &producer); 32652a38012Sejakowatz } 32752a38012Sejakowatz 32852a38012Sejakowatz 32952a38012Sejakowatz status_t 33052a38012Sejakowatz BMediaRoster::SetAudioInput(const media_node & producer) 33152a38012Sejakowatz { 33252a38012Sejakowatz CALLED(); 3333620737cSbeveloper return SetNode(AUDIO_INPUT, &producer); 33452a38012Sejakowatz } 33552a38012Sejakowatz 33652a38012Sejakowatz 33752a38012Sejakowatz status_t 33852a38012Sejakowatz BMediaRoster::SetAudioInput(const dormant_node_info & producer) 33952a38012Sejakowatz { 34052a38012Sejakowatz CALLED(); 3413620737cSbeveloper return SetNode(AUDIO_INPUT, NULL, &producer); 34252a38012Sejakowatz } 34352a38012Sejakowatz 34452a38012Sejakowatz 34552a38012Sejakowatz status_t 34652a38012Sejakowatz BMediaRoster::SetVideoOutput(const media_node & consumer) 34752a38012Sejakowatz { 34852a38012Sejakowatz CALLED(); 3493620737cSbeveloper return SetNode(VIDEO_OUTPUT, &consumer); 35052a38012Sejakowatz } 35152a38012Sejakowatz 35252a38012Sejakowatz 35352a38012Sejakowatz status_t 35452a38012Sejakowatz BMediaRoster::SetVideoOutput(const dormant_node_info & consumer) 35552a38012Sejakowatz { 35652a38012Sejakowatz CALLED(); 3573620737cSbeveloper return SetNode(VIDEO_OUTPUT, NULL, &consumer); 35852a38012Sejakowatz } 35952a38012Sejakowatz 36052a38012Sejakowatz 36152a38012Sejakowatz status_t 36252a38012Sejakowatz BMediaRoster::SetAudioOutput(const media_node & consumer) 36352a38012Sejakowatz { 36452a38012Sejakowatz CALLED(); 3653620737cSbeveloper return SetNode(AUDIO_OUTPUT, &consumer); 36652a38012Sejakowatz } 36752a38012Sejakowatz 36852a38012Sejakowatz 36952a38012Sejakowatz status_t 37052a38012Sejakowatz BMediaRoster::SetAudioOutput(const media_input & input_to_output) 37152a38012Sejakowatz { 37252a38012Sejakowatz CALLED(); 3733620737cSbeveloper return SetNode(AUDIO_OUTPUT, NULL, NULL, &input_to_output); 37452a38012Sejakowatz } 37552a38012Sejakowatz 37652a38012Sejakowatz 37752a38012Sejakowatz status_t 37852a38012Sejakowatz BMediaRoster::SetAudioOutput(const dormant_node_info & consumer) 37952a38012Sejakowatz { 38052a38012Sejakowatz CALLED(); 3813620737cSbeveloper return SetNode(AUDIO_OUTPUT, NULL, &consumer); 38252a38012Sejakowatz } 38352a38012Sejakowatz 38452a38012Sejakowatz 38552a38012Sejakowatz status_t 38652a38012Sejakowatz BMediaRoster::GetNodeFor(media_node_id node, 38752a38012Sejakowatz media_node * clone) 38852a38012Sejakowatz { 3899e9417d2Sbeveloper CALLED(); 3909e9417d2Sbeveloper if (clone == NULL) 3919e9417d2Sbeveloper return B_BAD_VALUE; 3929e9417d2Sbeveloper if (node <= 0) 3939e9417d2Sbeveloper return B_MEDIA_BAD_NODE; 3949e9417d2Sbeveloper 3959e9417d2Sbeveloper server_get_node_for_request request; 3969e9417d2Sbeveloper server_get_node_for_reply reply; 3979e9417d2Sbeveloper status_t rv; 3989e9417d2Sbeveloper 3999e9417d2Sbeveloper request.nodeid = node; 4009e9417d2Sbeveloper request.team = team; 4019e9417d2Sbeveloper 4029e9417d2Sbeveloper rv = QueryServer(SERVER_GET_NODE_FOR, &request, sizeof(request), &reply, sizeof(reply)); 4039e9417d2Sbeveloper if (rv != B_OK) 4049e9417d2Sbeveloper return rv; 4059e9417d2Sbeveloper 4069e9417d2Sbeveloper *clone = reply.clone; 4079e9417d2Sbeveloper return B_OK; 40852a38012Sejakowatz } 40952a38012Sejakowatz 41052a38012Sejakowatz 41152a38012Sejakowatz status_t 41252a38012Sejakowatz BMediaRoster::GetSystemTimeSource(media_node * clone) 41352a38012Sejakowatz { 41452a38012Sejakowatz CALLED(); 4153620737cSbeveloper return GetNode(SYSTEM_TIME_SOURCE, clone); 41652a38012Sejakowatz } 41752a38012Sejakowatz 41852a38012Sejakowatz 41952a38012Sejakowatz status_t 42052a38012Sejakowatz BMediaRoster::ReleaseNode(const media_node & node) 42152a38012Sejakowatz { 4229e9417d2Sbeveloper CALLED(); 4239e9417d2Sbeveloper if (node.node <= 0) 4249e9417d2Sbeveloper return B_MEDIA_BAD_NODE; 42552a38012Sejakowatz 4269e9417d2Sbeveloper server_release_node_request request; 4279e9417d2Sbeveloper server_release_node_reply reply; 4289e9417d2Sbeveloper 4299e9417d2Sbeveloper request.node = node; 4309e9417d2Sbeveloper request.team = team; 4319e9417d2Sbeveloper 4329e9417d2Sbeveloper return QueryServer(SERVER_RELEASE_NODE, &request, sizeof(request), &reply, sizeof(reply)); 4339e9417d2Sbeveloper } 43452a38012Sejakowatz 43552a38012Sejakowatz 43652a38012Sejakowatz BTimeSource * 43752a38012Sejakowatz BMediaRoster::MakeTimeSourceFor(const media_node & for_node) 43852a38012Sejakowatz { 4391299bfb2Sbeveloper BROKEN(); 4401299bfb2Sbeveloper return new _SysTimeSource(); // XXX fix this 44152a38012Sejakowatz } 44252a38012Sejakowatz 44352a38012Sejakowatz 44452a38012Sejakowatz status_t 44552a38012Sejakowatz BMediaRoster::Connect(const media_source & from, 44652a38012Sejakowatz const media_destination & to, 44752a38012Sejakowatz media_format * io_format, 44852a38012Sejakowatz media_output * out_output, 44952a38012Sejakowatz media_input * out_input) 45052a38012Sejakowatz { 451eae26d3dSbeveloper return BMediaRoster::Connect(from, to, io_format, out_output, out_input, 0); 452eae26d3dSbeveloper } 453eae26d3dSbeveloper 454eae26d3dSbeveloper 455eae26d3dSbeveloper status_t 456eae26d3dSbeveloper BMediaRoster::Connect(const media_source & from, 457eae26d3dSbeveloper const media_destination & to, 458eae26d3dSbeveloper media_format * io_format, 459eae26d3dSbeveloper media_output * out_output, 460eae26d3dSbeveloper media_input * out_input, 461eae26d3dSbeveloper uint32 in_flags, 462eae26d3dSbeveloper void * _reserved) 463eae26d3dSbeveloper { 46452a38012Sejakowatz CALLED(); 46552a38012Sejakowatz if (io_format == NULL || out_output == NULL || out_input == NULL) 46652a38012Sejakowatz return B_BAD_VALUE; 4679e9417d2Sbeveloper if (from == media_source::null) { 4689e9417d2Sbeveloper TRACE("BMediaRoster::Connect: media_source invalid\n"); 46952a38012Sejakowatz return B_MEDIA_BAD_SOURCE; 4709e9417d2Sbeveloper } 4719e9417d2Sbeveloper if (to == media_destination::null) { 4729e9417d2Sbeveloper TRACE("BMediaRoster::Connect: media_destination invalid\n"); 47352a38012Sejakowatz return B_MEDIA_BAD_DESTINATION; 4749e9417d2Sbeveloper } 47552a38012Sejakowatz 47652a38012Sejakowatz status_t rv; 4778c6a6096Sbeveloper producer_format_proposal_request request1; 4788c6a6096Sbeveloper producer_format_proposal_reply reply1; 47952a38012Sejakowatz 48052a38012Sejakowatz // BBufferProducer::FormatProposal 4818c6a6096Sbeveloper request1.output = from; 4828c6a6096Sbeveloper request1.format = *io_format; 4838c6a6096Sbeveloper rv = QueryPort(from.port, PRODUCER_FORMAT_PROPOSAL, &request1, sizeof(request1), &reply1, sizeof(reply1)); 4848c6a6096Sbeveloper if (rv != B_OK) { 4855edd2016Sbeveloper TRACE("BMediaRoster::Connect: aborted after BBufferProducer::FormatProposal, status = %#lx\n",rv); 48652a38012Sejakowatz return rv; 48752a38012Sejakowatz } 4888c6a6096Sbeveloper // reply1.format now contains the format proposed by the producer 4898c6a6096Sbeveloper 4908c6a6096Sbeveloper consumer_accept_format_request request2; 4918c6a6096Sbeveloper consumer_accept_format_reply reply2; 4928c6a6096Sbeveloper 4938c6a6096Sbeveloper // BBufferConsumer::AcceptFormat 4948c6a6096Sbeveloper request2.dest = to; 4958c6a6096Sbeveloper request2.format = reply1.format; 4968c6a6096Sbeveloper rv = QueryPort(to.port, CONSUMER_ACCEPT_FORMAT, &request2, sizeof(request2), &reply2, sizeof(reply2)); 4978c6a6096Sbeveloper if (rv != B_OK) { 4985edd2016Sbeveloper TRACE("BMediaRoster::Connect: aborted after BBufferConsumer::AcceptFormat, status = %#lx\n",rv); 4998c6a6096Sbeveloper return rv; 5008c6a6096Sbeveloper } 5018c6a6096Sbeveloper // reply2.format now contains the format accepted by the consumer 5028c6a6096Sbeveloper 5038c6a6096Sbeveloper // BBufferProducer::PrepareToConnect 5048c6a6096Sbeveloper producer_prepare_to_connect_request request3; 5058c6a6096Sbeveloper producer_prepare_to_connect_reply reply3; 5068c6a6096Sbeveloper 5078c6a6096Sbeveloper request3.source = from; 5088c6a6096Sbeveloper request3.destination = to; 5098c6a6096Sbeveloper request3.format = reply2.format; 5108c6a6096Sbeveloper strcpy(request3.name, "XXX some default name"); // XXX fix this 5118c6a6096Sbeveloper rv = QueryPort(from.port, PRODUCER_PREPARE_TO_CONNECT, &request3, sizeof(request3), &reply3, sizeof(reply3)); 5128c6a6096Sbeveloper if (rv != B_OK) { 5135edd2016Sbeveloper TRACE("BMediaRoster::Connect: aborted after BBufferProducer::PrepareToConnect, status = %#lx\n",rv); 5148c6a6096Sbeveloper return rv; 5158c6a6096Sbeveloper } 5168c6a6096Sbeveloper // reply3.format is still our pretty media format 5178c6a6096Sbeveloper // reply3.out_source the real source to be used for the connection 5188c6a6096Sbeveloper // reply3.name the name BBufferConsumer::Connected will see in the outInput->name argument 5198c6a6096Sbeveloper 5208c6a6096Sbeveloper // BBufferConsumer::Connected 5218c6a6096Sbeveloper consumer_connected_request request4; 5228c6a6096Sbeveloper consumer_connected_reply reply4; 5238c6a6096Sbeveloper status_t con_status; 5248c6a6096Sbeveloper 5258c6a6096Sbeveloper request4.producer = reply3.out_source; 5268c6a6096Sbeveloper request4.where = to; 5278c6a6096Sbeveloper request4.with_format = reply3.format; 5288c6a6096Sbeveloper con_status = QueryPort(to.port, CONSUMER_CONNECTED, &request4, sizeof(request4), &reply4, sizeof(reply4)); 5298c6a6096Sbeveloper if (con_status != B_OK) { 5305edd2016Sbeveloper TRACE("BMediaRoster::Connect: aborting after BBufferConsumer::Connected, status = %#lx\n",con_status); 5318c6a6096Sbeveloper // we do NOT return here! 5328c6a6096Sbeveloper } 5338c6a6096Sbeveloper // con_status contains the status code to be supplied to BBufferProducer::Connect's status argument 5348c6a6096Sbeveloper // reply4.input contains the media_input that describes the connection from the consumer point of view 5358c6a6096Sbeveloper 5368c6a6096Sbeveloper // BBufferProducer::Connect 5378c6a6096Sbeveloper producer_connect_request request5; 5388c6a6096Sbeveloper producer_connect_reply reply5; 5398c6a6096Sbeveloper 5408c6a6096Sbeveloper request5.error = con_status; 5418c6a6096Sbeveloper request5.source = reply3.out_source; 5428c6a6096Sbeveloper request5.destination = reply4.input.destination; 5438c6a6096Sbeveloper request5.format = reply3.format; // XXX reply4.input.format ??? 5448c6a6096Sbeveloper strcpy(request5.name, reply4.input.name); 5450caff283Sbeveloper rv = QueryPort(reply4.input.source.port, PRODUCER_CONNECT, &request5, sizeof(request5), &reply5, sizeof(reply5)); 5468c6a6096Sbeveloper if (con_status != B_OK) { 5478c6a6096Sbeveloper TRACE("BMediaRoster::Connect: aborted\n"); 5488c6a6096Sbeveloper return con_status; 5498c6a6096Sbeveloper } 5508c6a6096Sbeveloper if (rv != B_OK) { 5515edd2016Sbeveloper TRACE("BMediaRoster::Connect: aborted after BBufferProducer::Connect, status = %#lx\n",rv); 5528c6a6096Sbeveloper return rv; 5538c6a6096Sbeveloper } 5548c6a6096Sbeveloper // reply5.name contains the name assigned to the connection by the producer 5558c6a6096Sbeveloper 5568c6a6096Sbeveloper // find the output node 5578c6a6096Sbeveloper // XXX isn't there a easier way? 5588c6a6096Sbeveloper media_node sourcenode; 5598c6a6096Sbeveloper GetNodeFor(NodeIDFor(from.port), &sourcenode); 5608c6a6096Sbeveloper ReleaseNode(sourcenode); 5618c6a6096Sbeveloper 5628c6a6096Sbeveloper // initilize connection info 5638c6a6096Sbeveloper *io_format = reply3.format; 5648c6a6096Sbeveloper *out_input = reply4.input; 5658c6a6096Sbeveloper out_output->node = sourcenode; 5668c6a6096Sbeveloper out_output->source = reply4.input.source; 5678c6a6096Sbeveloper out_output->destination = reply4.input.destination; 5688c6a6096Sbeveloper out_output->format = reply4.input.format; 5698c6a6096Sbeveloper strcpy(out_output->name, reply5.name); 5708c6a6096Sbeveloper 5718c6a6096Sbeveloper // the connection is now made 5728c6a6096Sbeveloper 5738c6a6096Sbeveloper 5748c6a6096Sbeveloper // XXX register connection with server 5759e9417d2Sbeveloper // XXX we should just send a notification, instead of republishing all endpoints 5769e9417d2Sbeveloper Stack<media_output> outstack; 5779e9417d2Sbeveloper Stack<media_input> instack; 5789e9417d2Sbeveloper if (B_OK == GetAllOutputs(out_output->node , &outstack)) 5799e9417d2Sbeveloper PublishOutputs(out_output->node , &outstack); 5809e9417d2Sbeveloper if (B_OK == GetAllInputs(out_input->node , &instack)) 5819e9417d2Sbeveloper PublishInputs(out_input->node, &instack); 5828c6a6096Sbeveloper 5838c6a6096Sbeveloper 5848c6a6096Sbeveloper // XXX if (mute) BBufferProducer::EnableOutput(false) 5859e9417d2Sbeveloper if (in_flags & B_CONNECT_MUTED) { 5869e9417d2Sbeveloper } 5878c6a6096Sbeveloper 5888c6a6096Sbeveloper 5899e9417d2Sbeveloper // send a notification 5909e9417d2Sbeveloper BPrivate::media::notifications::ConnectionMade(*out_input, *out_output, *io_format); 5919e9417d2Sbeveloper 5928c6a6096Sbeveloper return B_OK; 5938c6a6096Sbeveloper }; 59452a38012Sejakowatz 59552a38012Sejakowatz 59652a38012Sejakowatz status_t 5979e9417d2Sbeveloper BMediaRoster::Disconnect(media_node_id source_nodeid, 59852a38012Sejakowatz const media_source & source, 5999e9417d2Sbeveloper media_node_id destination_nodeid, 60052a38012Sejakowatz const media_destination & destination) 60152a38012Sejakowatz { 6029e9417d2Sbeveloper CALLED(); 6039e9417d2Sbeveloper if (source_nodeid <= 0) { 6049e9417d2Sbeveloper TRACE("BMediaRoster::Disconnect: source media_node_id invalid\n"); 6059e9417d2Sbeveloper return B_MEDIA_BAD_SOURCE; 6069e9417d2Sbeveloper } 6079e9417d2Sbeveloper if (destination_nodeid <= 0) { 6089e9417d2Sbeveloper TRACE("BMediaRoster::Disconnect: source media_node_id invalid\n"); 6099e9417d2Sbeveloper return B_MEDIA_BAD_DESTINATION; 6109e9417d2Sbeveloper } 6119e9417d2Sbeveloper if (source == media_source::null) { 6129e9417d2Sbeveloper TRACE("BMediaRoster::Disconnect: media_source invalid\n"); 6139e9417d2Sbeveloper return B_MEDIA_BAD_SOURCE; 6149e9417d2Sbeveloper } 6159e9417d2Sbeveloper if (destination == media_destination::null) { 6169e9417d2Sbeveloper TRACE("BMediaRoster::Disconnect: media_destination invalid\n"); 6179e9417d2Sbeveloper return B_MEDIA_BAD_DESTINATION; 6189e9417d2Sbeveloper } 6199e9417d2Sbeveloper 6209e9417d2Sbeveloper producer_disconnect_request request2; 6219e9417d2Sbeveloper producer_disconnect_reply reply2; 6229e9417d2Sbeveloper consumer_disconnected_request request1; 6239e9417d2Sbeveloper consumer_disconnected_reply reply1; 6249e9417d2Sbeveloper status_t rv1, rv2; 6259e9417d2Sbeveloper 6269e9417d2Sbeveloper // XXX we should ask the server if this connection really exists 6279e9417d2Sbeveloper 6289e9417d2Sbeveloper request1.source = source; 6299e9417d2Sbeveloper request1.destination = destination; 6309e9417d2Sbeveloper request2.source = source; 6319e9417d2Sbeveloper request2.destination = destination; 6329e9417d2Sbeveloper 6339e9417d2Sbeveloper rv1 = QueryPort(source.port, PRODUCER_DISCONNECT, &request1, sizeof(request1), &reply1, sizeof(reply1)); 6349e9417d2Sbeveloper rv2 = QueryPort(destination.port, CONSUMER_DISCONNECTED, &request2, sizeof(request2), &reply2, sizeof(reply2)); 6359e9417d2Sbeveloper 6369e9417d2Sbeveloper // XXX unregister connection with server 6379e9417d2Sbeveloper // XXX we should just send a notification, instead of republishing all endpoints 6389e9417d2Sbeveloper Stack<media_output> outstack; 6399e9417d2Sbeveloper Stack<media_input> instack; 6409e9417d2Sbeveloper media_node sourcenode; 6419e9417d2Sbeveloper media_node destnode; 6429e9417d2Sbeveloper if (B_OK == GetNodeFor(source_nodeid, &sourcenode)) { 6439e9417d2Sbeveloper if (B_OK == GetAllOutputs(sourcenode , &outstack)) 6449e9417d2Sbeveloper PublishOutputs(sourcenode , &outstack); 6459e9417d2Sbeveloper ReleaseNode(sourcenode); 6469e9417d2Sbeveloper } else TRACE("BMediaRoster::Disconnect: source GetNodeFor failed\n"); 6479e9417d2Sbeveloper if (B_OK == GetNodeFor(destination_nodeid, &destnode)) { 6489e9417d2Sbeveloper if (B_OK == GetAllInputs(destnode , &instack)) 6499e9417d2Sbeveloper PublishInputs(destnode, &instack); 6509e9417d2Sbeveloper ReleaseNode(destnode); 6519e9417d2Sbeveloper } else TRACE("BMediaRoster::Disconnect: dest GetNodeFor failed\n"); 6529e9417d2Sbeveloper 6539e9417d2Sbeveloper 6549e9417d2Sbeveloper // send a notification 6559e9417d2Sbeveloper BPrivate::media::notifications::ConnectionBroken(source, destination); 6569e9417d2Sbeveloper 6579e9417d2Sbeveloper return (rv1 != B_OK || rv2 != B_OK) ? B_ERROR : B_OK; 65852a38012Sejakowatz } 65952a38012Sejakowatz 66052a38012Sejakowatz 66152a38012Sejakowatz status_t 66252a38012Sejakowatz BMediaRoster::StartNode(const media_node & node, 66352a38012Sejakowatz bigtime_t at_performance_time) 66452a38012Sejakowatz { 66552a38012Sejakowatz CALLED(); 6669e9417d2Sbeveloper if (node.node <= 0) 66752a38012Sejakowatz return B_MEDIA_BAD_NODE; 66852a38012Sejakowatz 669*6396865dSbeveloper node_start_command command; 670*6396865dSbeveloper command.performance_time = at_performance_time; 67152a38012Sejakowatz 672*6396865dSbeveloper return SendToPort(node.port, NODE_START, &command, sizeof(command)); 67352a38012Sejakowatz } 67452a38012Sejakowatz 67552a38012Sejakowatz 67652a38012Sejakowatz status_t 67752a38012Sejakowatz BMediaRoster::StopNode(const media_node & node, 67852a38012Sejakowatz bigtime_t at_performance_time, 67952a38012Sejakowatz bool immediate) 68052a38012Sejakowatz { 68152a38012Sejakowatz CALLED(); 6829e9417d2Sbeveloper if (node.node <= 0) 68352a38012Sejakowatz return B_MEDIA_BAD_NODE; 68452a38012Sejakowatz 685*6396865dSbeveloper node_stop_command command; 686*6396865dSbeveloper command.performance_time = at_performance_time; 687*6396865dSbeveloper command.immediate = immediate; 68852a38012Sejakowatz 689*6396865dSbeveloper return SendToPort(node.port, NODE_STOP, &command, sizeof(command)); 69052a38012Sejakowatz } 69152a38012Sejakowatz 69252a38012Sejakowatz 69352a38012Sejakowatz status_t 69452a38012Sejakowatz BMediaRoster::SeekNode(const media_node & node, 69552a38012Sejakowatz bigtime_t to_media_time, 69652a38012Sejakowatz bigtime_t at_performance_time) 69752a38012Sejakowatz { 69852a38012Sejakowatz CALLED(); 6999e9417d2Sbeveloper if (node.node <= 0) 70052a38012Sejakowatz return B_MEDIA_BAD_NODE; 70152a38012Sejakowatz 702*6396865dSbeveloper node_seek_command command; 703*6396865dSbeveloper command.media_time = to_media_time; 704*6396865dSbeveloper command.performance_time = at_performance_time; 70552a38012Sejakowatz 706*6396865dSbeveloper return SendToPort(node.port, NODE_SEEK, &command, sizeof(command)); 70752a38012Sejakowatz } 70852a38012Sejakowatz 70952a38012Sejakowatz 71052a38012Sejakowatz status_t 71152a38012Sejakowatz BMediaRoster::StartTimeSource(const media_node & node, 71252a38012Sejakowatz bigtime_t at_real_time) 71352a38012Sejakowatz { 71452a38012Sejakowatz CALLED(); 7159e9417d2Sbeveloper if (node.node <= 0) 71652a38012Sejakowatz return B_MEDIA_BAD_NODE; 71752a38012Sejakowatz if ((node.kind & B_TIME_SOURCE) == 0) 71852a38012Sejakowatz return B_MEDIA_BAD_NODE; 71952a38012Sejakowatz 72052a38012Sejakowatz BTimeSource::time_source_op_info msg; 72152a38012Sejakowatz msg.op = BTimeSource::B_TIMESOURCE_START; 72252a38012Sejakowatz msg.real_time = at_real_time; 72352a38012Sejakowatz 72452a38012Sejakowatz return write_port(node.port, TIMESOURCE_OP, &msg, sizeof(msg)); 72552a38012Sejakowatz } 72652a38012Sejakowatz 72752a38012Sejakowatz 72852a38012Sejakowatz status_t 72952a38012Sejakowatz BMediaRoster::StopTimeSource(const media_node & node, 73052a38012Sejakowatz bigtime_t at_real_time, 73152a38012Sejakowatz bool immediate) 73252a38012Sejakowatz { 73352a38012Sejakowatz CALLED(); 7349e9417d2Sbeveloper if (node.node <= 0) 73552a38012Sejakowatz return B_MEDIA_BAD_NODE; 73652a38012Sejakowatz if ((node.kind & B_TIME_SOURCE) == 0) 73752a38012Sejakowatz return B_MEDIA_BAD_NODE; 73852a38012Sejakowatz 73952a38012Sejakowatz BTimeSource::time_source_op_info msg; 74052a38012Sejakowatz msg.op = immediate ? BTimeSource::B_TIMESOURCE_STOP_IMMEDIATELY : BTimeSource::B_TIMESOURCE_STOP; 74152a38012Sejakowatz msg.real_time = at_real_time; 74252a38012Sejakowatz 74352a38012Sejakowatz return write_port(node.port, TIMESOURCE_OP, &msg, sizeof(msg)); 74452a38012Sejakowatz } 74552a38012Sejakowatz 74652a38012Sejakowatz 74752a38012Sejakowatz status_t 74852a38012Sejakowatz BMediaRoster::SeekTimeSource(const media_node & node, 74952a38012Sejakowatz bigtime_t to_performance_time, 75052a38012Sejakowatz bigtime_t at_real_time) 75152a38012Sejakowatz { 75252a38012Sejakowatz CALLED(); 7539e9417d2Sbeveloper if (node.node <= 0) 75452a38012Sejakowatz return B_MEDIA_BAD_NODE; 75552a38012Sejakowatz if ((node.kind & B_TIME_SOURCE) == 0) 75652a38012Sejakowatz return B_MEDIA_BAD_NODE; 75752a38012Sejakowatz 75852a38012Sejakowatz BTimeSource::time_source_op_info msg; 75952a38012Sejakowatz msg.op = BTimeSource::B_TIMESOURCE_SEEK; 76052a38012Sejakowatz msg.real_time = at_real_time; 76152a38012Sejakowatz msg.performance_time = to_performance_time; 76252a38012Sejakowatz 76352a38012Sejakowatz return write_port(node.port, TIMESOURCE_OP, &msg, sizeof(msg)); 76452a38012Sejakowatz } 76552a38012Sejakowatz 76652a38012Sejakowatz 76752a38012Sejakowatz status_t 76852a38012Sejakowatz BMediaRoster::SyncToNode(const media_node & node, 76952a38012Sejakowatz bigtime_t at_time, 77052a38012Sejakowatz bigtime_t timeout) 77152a38012Sejakowatz { 77252a38012Sejakowatz UNIMPLEMENTED(); 77352a38012Sejakowatz return B_ERROR; 77452a38012Sejakowatz } 77552a38012Sejakowatz 77652a38012Sejakowatz 77752a38012Sejakowatz status_t 77852a38012Sejakowatz BMediaRoster::SetRunModeNode(const media_node & node, 77952a38012Sejakowatz BMediaNode::run_mode mode) 78052a38012Sejakowatz { 78152a38012Sejakowatz CALLED(); 7829e9417d2Sbeveloper if (node.node <= 0) 78352a38012Sejakowatz return B_MEDIA_BAD_NODE; 78452a38012Sejakowatz 785dfb2ad61Sbeveloper node_set_run_mode_command msg; 78652a38012Sejakowatz msg.mode = mode; 78752a38012Sejakowatz 78852a38012Sejakowatz return write_port(node.port, NODE_SET_RUN_MODE, &msg, sizeof(msg)); 78952a38012Sejakowatz } 79052a38012Sejakowatz 79152a38012Sejakowatz 79252a38012Sejakowatz status_t 79352a38012Sejakowatz BMediaRoster::PrerollNode(const media_node & node) 79452a38012Sejakowatz { 79552a38012Sejakowatz CALLED(); 7969e9417d2Sbeveloper if (node.node <= 0) 79752a38012Sejakowatz return B_MEDIA_BAD_NODE; 79852a38012Sejakowatz 79952a38012Sejakowatz char dummy; 80052a38012Sejakowatz return write_port(node.port, NODE_PREROLL, &dummy, sizeof(dummy)); 80152a38012Sejakowatz } 80252a38012Sejakowatz 80352a38012Sejakowatz 80452a38012Sejakowatz status_t 80552a38012Sejakowatz BMediaRoster::RollNode(const media_node & node, 80652a38012Sejakowatz bigtime_t startPerformance, 80752a38012Sejakowatz bigtime_t stopPerformance, 80852a38012Sejakowatz bigtime_t atMediaTime) 80952a38012Sejakowatz { 81052a38012Sejakowatz UNIMPLEMENTED(); 81152a38012Sejakowatz return B_ERROR; 81252a38012Sejakowatz } 81352a38012Sejakowatz 81452a38012Sejakowatz 81552a38012Sejakowatz status_t 81652a38012Sejakowatz BMediaRoster::SetProducerRunModeDelay(const media_node & node, 81752a38012Sejakowatz bigtime_t delay, 81852a38012Sejakowatz BMediaNode::run_mode mode) 81952a38012Sejakowatz { 82052a38012Sejakowatz UNIMPLEMENTED(); 82152a38012Sejakowatz return B_ERROR; 82252a38012Sejakowatz } 82352a38012Sejakowatz 82452a38012Sejakowatz 82552a38012Sejakowatz status_t 82652a38012Sejakowatz BMediaRoster::SetProducerRate(const media_node & producer, 82752a38012Sejakowatz int32 numer, 82852a38012Sejakowatz int32 denom) 82952a38012Sejakowatz { 83052a38012Sejakowatz CALLED(); 83152a38012Sejakowatz if (producer.node == 0) 83252a38012Sejakowatz return B_MEDIA_BAD_NODE; 83352a38012Sejakowatz if ((producer.kind & B_BUFFER_PRODUCER) == 0) 83452a38012Sejakowatz return B_MEDIA_BAD_NODE; 83552a38012Sejakowatz 836dfb2ad61Sbeveloper producer_set_play_rate_request msg; 837dfb2ad61Sbeveloper producer_set_play_rate_reply reply; 83852a38012Sejakowatz status_t rv; 83952a38012Sejakowatz int32 code; 84052a38012Sejakowatz 84152a38012Sejakowatz msg.numer = numer; 84252a38012Sejakowatz msg.denom = denom; 84352a38012Sejakowatz msg.reply_port = _PortPool->GetPort(); 84452a38012Sejakowatz rv = write_port(producer.node, PRODUCER_SET_PLAY_RATE, &msg, sizeof(msg)); 84552a38012Sejakowatz if (rv != B_OK) { 84652a38012Sejakowatz _PortPool->PutPort(msg.reply_port); 84752a38012Sejakowatz return rv; 84852a38012Sejakowatz } 84952a38012Sejakowatz rv = read_port(msg.reply_port, &code, &reply, sizeof(reply)); 85052a38012Sejakowatz _PortPool->PutPort(msg.reply_port); 85152a38012Sejakowatz return (rv < B_OK) ? rv : reply.result; 85252a38012Sejakowatz } 85352a38012Sejakowatz 85452a38012Sejakowatz 85552a38012Sejakowatz /* Nodes will have available inputs/outputs as long as they are capable */ 85652a38012Sejakowatz /* of accepting more connections. The node may create an additional */ 85752a38012Sejakowatz /* output or input as the currently available is taken into usage. */ 85852a38012Sejakowatz status_t 85952a38012Sejakowatz BMediaRoster::GetLiveNodeInfo(const media_node & node, 86052a38012Sejakowatz live_node_info * out_live_info) 86152a38012Sejakowatz { 8629e9417d2Sbeveloper CALLED(); 8639e9417d2Sbeveloper if (out_live_info == NULL) 8649e9417d2Sbeveloper return B_BAD_VALUE; 8659e9417d2Sbeveloper if (node.node <= 0) 8669e9417d2Sbeveloper return B_MEDIA_BAD_NODE; 8679e9417d2Sbeveloper 8689e9417d2Sbeveloper server_get_live_node_info_request request; 8699e9417d2Sbeveloper server_get_live_node_info_reply reply; 8709e9417d2Sbeveloper status_t rv; 8719e9417d2Sbeveloper 8729e9417d2Sbeveloper request.node = node; 8739e9417d2Sbeveloper 8741299bfb2Sbeveloper rv = QueryServer(SERVER_GET_LIVE_NODE_INFO, &request, sizeof(request), &reply, sizeof(reply)); 8759e9417d2Sbeveloper if (rv != B_OK) 8769e9417d2Sbeveloper return rv; 8779e9417d2Sbeveloper 8789e9417d2Sbeveloper *out_live_info = reply.live_info; 8799e9417d2Sbeveloper return B_OK; 88052a38012Sejakowatz } 88152a38012Sejakowatz 88252a38012Sejakowatz 88352a38012Sejakowatz status_t 88452a38012Sejakowatz BMediaRoster::GetLiveNodes(live_node_info * out_live_nodes, 88552a38012Sejakowatz int32 * io_total_count, 88652a38012Sejakowatz const media_format * has_input, 88752a38012Sejakowatz const media_format * has_output, 88852a38012Sejakowatz const char * name, 88952a38012Sejakowatz uint64 node_kinds) 89052a38012Sejakowatz { 8919e9417d2Sbeveloper CALLED(); 8929e9417d2Sbeveloper if (out_live_nodes == NULL || io_total_count == NULL) 8939e9417d2Sbeveloper return B_BAD_VALUE; 8949e9417d2Sbeveloper if (*io_total_count <= 0) 8959e9417d2Sbeveloper return B_BAD_VALUE; 8969e9417d2Sbeveloper 8979e9417d2Sbeveloper // XXX we also support the wildcard search as GetDormantNodes does. This needs to be documented 8989e9417d2Sbeveloper 8999e9417d2Sbeveloper server_get_live_nodes_request request; 9009e9417d2Sbeveloper server_get_live_nodes_reply reply; 9019e9417d2Sbeveloper status_t rv; 9029e9417d2Sbeveloper 9039e9417d2Sbeveloper request.maxcount = *io_total_count; 9049e9417d2Sbeveloper request.has_input = (bool) has_input; 9059e9417d2Sbeveloper if (has_input) 9069e9417d2Sbeveloper request.inputformat = *has_input; // XXX we should not make a flat copy of media_format 9079e9417d2Sbeveloper request.has_output = (bool) has_output; 9089e9417d2Sbeveloper if (has_output) 9099e9417d2Sbeveloper request.outputformat = *has_output; // XXX we should not make a flat copy of media_format 9109e9417d2Sbeveloper request.has_name = (bool) name; 9119e9417d2Sbeveloper if (name) { 9129e9417d2Sbeveloper int len = strlen(name); 9139e9417d2Sbeveloper len = min_c(len, (int)sizeof(request.name) - 1); 9149e9417d2Sbeveloper memcpy(request.name, name, len); 9159e9417d2Sbeveloper request.name[len] = 0; 9169e9417d2Sbeveloper } 9179e9417d2Sbeveloper request.require_kinds = node_kinds; 9189e9417d2Sbeveloper 9199e9417d2Sbeveloper rv = QueryServer(SERVER_GET_LIVE_NODES, &request, sizeof(request), &reply, sizeof(reply)); 9209e9417d2Sbeveloper if (rv != B_OK) { 9219e9417d2Sbeveloper TRACE("BMediaRoster::GetLiveNodes failed\n"); 9221299bfb2Sbeveloper *io_total_count = 0; 9239e9417d2Sbeveloper return rv; 9249e9417d2Sbeveloper } 9259e9417d2Sbeveloper 9269e9417d2Sbeveloper if (reply.count > MAX_LIVE_INFO) { 9279e9417d2Sbeveloper live_node_info *live_info; 9289e9417d2Sbeveloper area_id clone; 9299e9417d2Sbeveloper 9309e9417d2Sbeveloper clone = clone_area("live_node_info clone", reinterpret_cast<void **>(&live_info), B_ANY_ADDRESS, B_READ_AREA | B_WRITE_AREA, reply.area); 9319e9417d2Sbeveloper if (clone < B_OK) { 9329e9417d2Sbeveloper TRACE("BMediaRoster::GetLiveNodes failed to clone area, %#lx\n", clone); 9339e9417d2Sbeveloper delete_area(reply.area); 9341299bfb2Sbeveloper *io_total_count = 0; 93552a38012Sejakowatz return B_ERROR; 93652a38012Sejakowatz } 93752a38012Sejakowatz 9389e9417d2Sbeveloper for (int32 i = 0; i < reply.count; i++) { 9399e9417d2Sbeveloper out_live_nodes[i] = live_info[i]; 9409e9417d2Sbeveloper } 9419e9417d2Sbeveloper 9429e9417d2Sbeveloper delete_area(clone); 9439e9417d2Sbeveloper delete_area(reply.area); 9449e9417d2Sbeveloper } else { 9459e9417d2Sbeveloper for (int32 i = 0; i < reply.count; i++) { 9469e9417d2Sbeveloper out_live_nodes[i] = reply.live_info[i]; 9479e9417d2Sbeveloper } 9489e9417d2Sbeveloper } 9499e9417d2Sbeveloper *io_total_count = reply.count; 9509e9417d2Sbeveloper 9519e9417d2Sbeveloper return B_OK; 9529e9417d2Sbeveloper } 9539e9417d2Sbeveloper 95452a38012Sejakowatz 95552a38012Sejakowatz status_t 95652a38012Sejakowatz BMediaRoster::GetFreeInputsFor(const media_node & node, 95752a38012Sejakowatz media_input * out_free_inputs, 95852a38012Sejakowatz int32 buf_num_inputs, 95952a38012Sejakowatz int32 * out_total_count, 96052a38012Sejakowatz media_type filter_type) 96152a38012Sejakowatz { 9623620737cSbeveloper CALLED(); 9639e9417d2Sbeveloper if (node.node <= 0 || (node.kind & B_BUFFER_CONSUMER) == 0) 9643620737cSbeveloper return B_MEDIA_BAD_NODE; 9653620737cSbeveloper if (out_free_inputs == NULL || out_total_count == NULL) 9663620737cSbeveloper return B_BAD_VALUE; 9673620737cSbeveloper 9683620737cSbeveloper Stack<media_input> stack; 9693620737cSbeveloper media_input *input; 9703620737cSbeveloper status_t rv; 9713620737cSbeveloper 9721299bfb2Sbeveloper *out_total_count = 0; 9731299bfb2Sbeveloper 9743620737cSbeveloper rv = GetAllInputs(node, &stack); 9753620737cSbeveloper if (B_OK != rv) 9763620737cSbeveloper return rv; 9773620737cSbeveloper 9783620737cSbeveloper for (int32 i = 0; stack.GetPointerAt(i, &input); i++) { 9793620737cSbeveloper if (filter_type != B_MEDIA_UNKNOWN_TYPE && filter_type != input->format.type) 9803620737cSbeveloper continue; // media_type used, but doesn't match 9813620737cSbeveloper if (input->source != media_source::null) 9823620737cSbeveloper continue; // consumer source already connected 9833620737cSbeveloper out_free_inputs[i] = *input; 9843620737cSbeveloper *out_total_count += 1; 9853620737cSbeveloper buf_num_inputs -= 1; 9863620737cSbeveloper if (buf_num_inputs == 0) 9873620737cSbeveloper break; 9883620737cSbeveloper } 9893620737cSbeveloper 9903620737cSbeveloper PublishInputs(node, &stack); 9913620737cSbeveloper return B_OK; 99252a38012Sejakowatz } 99352a38012Sejakowatz 99452a38012Sejakowatz 99552a38012Sejakowatz status_t 99652a38012Sejakowatz BMediaRoster::GetConnectedInputsFor(const media_node & node, 99752a38012Sejakowatz media_input * out_active_inputs, 99852a38012Sejakowatz int32 buf_num_inputs, 99952a38012Sejakowatz int32 * out_total_count) 100052a38012Sejakowatz { 10013620737cSbeveloper CALLED(); 10029e9417d2Sbeveloper if (node.node <= 0 || (node.kind & B_BUFFER_CONSUMER) == 0) 10033620737cSbeveloper return B_MEDIA_BAD_NODE; 10043620737cSbeveloper if (out_active_inputs == NULL || out_total_count == NULL) 10053620737cSbeveloper return B_BAD_VALUE; 10063620737cSbeveloper 10073620737cSbeveloper Stack<media_input> stack; 10083620737cSbeveloper media_input *input; 10093620737cSbeveloper status_t rv; 10103620737cSbeveloper 10111299bfb2Sbeveloper *out_total_count = 0; 10121299bfb2Sbeveloper 10133620737cSbeveloper rv = GetAllInputs(node, &stack); 10143620737cSbeveloper if (B_OK != rv) 10153620737cSbeveloper return rv; 10163620737cSbeveloper 10173620737cSbeveloper for (int32 i = 0; stack.GetPointerAt(i, &input); i++) { 10183620737cSbeveloper if (input->source == media_source::null) 10193620737cSbeveloper continue; // consumer source not connected 10203620737cSbeveloper out_active_inputs[i] = *input; 10213620737cSbeveloper *out_total_count += 1; 10223620737cSbeveloper buf_num_inputs -= 1; 10233620737cSbeveloper if (buf_num_inputs == 0) 10243620737cSbeveloper break; 10253620737cSbeveloper } 10263620737cSbeveloper 10273620737cSbeveloper PublishInputs(node, &stack); 10283620737cSbeveloper return B_OK; 102952a38012Sejakowatz } 103052a38012Sejakowatz 103152a38012Sejakowatz 103252a38012Sejakowatz status_t 103352a38012Sejakowatz BMediaRoster::GetAllInputsFor(const media_node & node, 103452a38012Sejakowatz media_input * out_inputs, 103552a38012Sejakowatz int32 buf_num_inputs, 103652a38012Sejakowatz int32 * out_total_count) 103752a38012Sejakowatz { 103852a38012Sejakowatz CALLED(); 10399e9417d2Sbeveloper if (node.node <= 0 || (node.kind & B_BUFFER_CONSUMER) == 0) 104052a38012Sejakowatz return B_MEDIA_BAD_NODE; 104152a38012Sejakowatz if (out_inputs == NULL || out_total_count == NULL) 104252a38012Sejakowatz return B_BAD_VALUE; 104352a38012Sejakowatz 10443620737cSbeveloper Stack<media_input> stack; 10453620737cSbeveloper media_input *input; 104652a38012Sejakowatz status_t rv; 104752a38012Sejakowatz 10481299bfb2Sbeveloper *out_total_count = 0; 10491299bfb2Sbeveloper 10503620737cSbeveloper rv = GetAllInputs(node, &stack); 10513620737cSbeveloper if (B_OK != rv) 10523620737cSbeveloper return rv; 10533620737cSbeveloper 10543620737cSbeveloper for (int32 i = 0; stack.GetPointerAt(i, &input); i++) { 10553620737cSbeveloper out_inputs[i] = *input; 105652a38012Sejakowatz *out_total_count += 1; 10573620737cSbeveloper buf_num_inputs -= 1; 10583620737cSbeveloper if (buf_num_inputs == 0) 10593620737cSbeveloper break; 106052a38012Sejakowatz } 106152a38012Sejakowatz 10623620737cSbeveloper PublishInputs(node, &stack); 10633620737cSbeveloper return B_OK; 106452a38012Sejakowatz } 106552a38012Sejakowatz 106652a38012Sejakowatz 106752a38012Sejakowatz status_t 106852a38012Sejakowatz BMediaRoster::GetFreeOutputsFor(const media_node & node, 106952a38012Sejakowatz media_output * out_free_outputs, 107052a38012Sejakowatz int32 buf_num_outputs, 107152a38012Sejakowatz int32 * out_total_count, 107252a38012Sejakowatz media_type filter_type) 107352a38012Sejakowatz { 10743620737cSbeveloper CALLED(); 10759e9417d2Sbeveloper if (node.node <= 0 || (node.kind & B_BUFFER_PRODUCER) == 0) 10763620737cSbeveloper return B_MEDIA_BAD_NODE; 10773620737cSbeveloper if (out_free_outputs == NULL || out_total_count == NULL) 10783620737cSbeveloper return B_BAD_VALUE; 10793620737cSbeveloper 10803620737cSbeveloper Stack<media_output> stack; 10813620737cSbeveloper media_output *output; 10823620737cSbeveloper status_t rv; 10833620737cSbeveloper 10841299bfb2Sbeveloper *out_total_count = 0; 10851299bfb2Sbeveloper 10863620737cSbeveloper rv = GetAllOutputs(node, &stack); 10873620737cSbeveloper if (B_OK != rv) 10883620737cSbeveloper return rv; 10893620737cSbeveloper 10903620737cSbeveloper for (int32 i = 0; stack.GetPointerAt(i, &output); i++) { 10913620737cSbeveloper if (filter_type != B_MEDIA_UNKNOWN_TYPE && filter_type != output->format.type) 10923620737cSbeveloper continue; // media_type used, but doesn't match 10933620737cSbeveloper if (output->destination != media_destination::null) 10943620737cSbeveloper continue; // producer destination already connected 10953620737cSbeveloper out_free_outputs[i] = *output; 10963620737cSbeveloper *out_total_count += 1; 10973620737cSbeveloper buf_num_outputs -= 1; 10983620737cSbeveloper if (buf_num_outputs == 0) 10993620737cSbeveloper break; 11003620737cSbeveloper } 11013620737cSbeveloper 11023620737cSbeveloper PublishOutputs(node, &stack); 11033620737cSbeveloper return B_OK; 110452a38012Sejakowatz } 110552a38012Sejakowatz 110652a38012Sejakowatz 110752a38012Sejakowatz status_t 110852a38012Sejakowatz BMediaRoster::GetConnectedOutputsFor(const media_node & node, 110952a38012Sejakowatz media_output * out_active_outputs, 111052a38012Sejakowatz int32 buf_num_outputs, 111152a38012Sejakowatz int32 * out_total_count) 111252a38012Sejakowatz { 11133620737cSbeveloper CALLED(); 11149e9417d2Sbeveloper if (node.node <= 0 || (node.kind & B_BUFFER_PRODUCER) == 0) 11153620737cSbeveloper return B_MEDIA_BAD_NODE; 11163620737cSbeveloper if (out_active_outputs == NULL || out_total_count == NULL) 11173620737cSbeveloper return B_BAD_VALUE; 11183620737cSbeveloper 11193620737cSbeveloper Stack<media_output> stack; 11203620737cSbeveloper media_output *output; 11213620737cSbeveloper status_t rv; 11223620737cSbeveloper 11231299bfb2Sbeveloper *out_total_count = 0; 11241299bfb2Sbeveloper 11253620737cSbeveloper rv = GetAllOutputs(node, &stack); 11263620737cSbeveloper if (B_OK != rv) 11273620737cSbeveloper return rv; 11283620737cSbeveloper 11293620737cSbeveloper for (int32 i = 0; stack.GetPointerAt(i, &output); i++) { 11303620737cSbeveloper if (output->destination == media_destination::null) 11313620737cSbeveloper continue; // producer destination not connected 11323620737cSbeveloper out_active_outputs[i] = *output; 11333620737cSbeveloper *out_total_count += 1; 11343620737cSbeveloper buf_num_outputs -= 1; 11353620737cSbeveloper if (buf_num_outputs == 0) 11363620737cSbeveloper break; 11373620737cSbeveloper } 11383620737cSbeveloper 11393620737cSbeveloper PublishOutputs(node, &stack); 11403620737cSbeveloper return B_OK; 114152a38012Sejakowatz } 114252a38012Sejakowatz 114352a38012Sejakowatz 114452a38012Sejakowatz status_t 114552a38012Sejakowatz BMediaRoster::GetAllOutputsFor(const media_node & node, 114652a38012Sejakowatz media_output * out_outputs, 114752a38012Sejakowatz int32 buf_num_outputs, 114852a38012Sejakowatz int32 * out_total_count) 114952a38012Sejakowatz { 115052a38012Sejakowatz CALLED(); 11519e9417d2Sbeveloper if (node.node <= 0 || (node.kind & B_BUFFER_PRODUCER) == 0) 115252a38012Sejakowatz return B_MEDIA_BAD_NODE; 115352a38012Sejakowatz if (out_outputs == NULL || out_total_count == NULL) 115452a38012Sejakowatz return B_BAD_VALUE; 115552a38012Sejakowatz 11563620737cSbeveloper Stack<media_output> stack; 11573620737cSbeveloper media_output *output; 115852a38012Sejakowatz status_t rv; 115952a38012Sejakowatz 11601299bfb2Sbeveloper *out_total_count = 0; 11611299bfb2Sbeveloper 11623620737cSbeveloper rv = GetAllOutputs(node, &stack); 11633620737cSbeveloper if (B_OK != rv) 11643620737cSbeveloper return rv; 11653620737cSbeveloper 11663620737cSbeveloper for (int32 i = 0; stack.GetPointerAt(i, &output); i++) { 11673620737cSbeveloper out_outputs[i] = *output; 116852a38012Sejakowatz *out_total_count += 1; 11693620737cSbeveloper buf_num_outputs -= 1; 11703620737cSbeveloper if (buf_num_outputs == 0) 11713620737cSbeveloper break; 117252a38012Sejakowatz } 117352a38012Sejakowatz 11743620737cSbeveloper PublishOutputs(node, &stack); 11753620737cSbeveloper return B_OK; 117652a38012Sejakowatz } 117752a38012Sejakowatz 117852a38012Sejakowatz 117952a38012Sejakowatz status_t 118052a38012Sejakowatz BMediaRoster::StartWatching(const BMessenger & where) 118152a38012Sejakowatz { 1182eae26d3dSbeveloper CALLED(); 1183eae26d3dSbeveloper if (!where.IsValid()) { 1184eae26d3dSbeveloper TRACE("BMediaRoster::StartWatching: messenger invalid!\n"); 1185eae26d3dSbeveloper return B_BAD_VALUE; 1186eae26d3dSbeveloper } 1187f4925104Sbeveloper return BPrivate::media::notifications::Register(where, media_node::null, B_MEDIA_WILDCARD); 118852a38012Sejakowatz } 118952a38012Sejakowatz 119052a38012Sejakowatz 119152a38012Sejakowatz status_t 119252a38012Sejakowatz BMediaRoster::StartWatching(const BMessenger & where, 119352a38012Sejakowatz int32 notificationType) 119452a38012Sejakowatz { 1195eae26d3dSbeveloper CALLED(); 1196eae26d3dSbeveloper if (!where.IsValid()) { 1197eae26d3dSbeveloper TRACE("BMediaRoster::StartWatching: messenger invalid!\n"); 1198eae26d3dSbeveloper return B_BAD_VALUE; 1199eae26d3dSbeveloper } 1200f4925104Sbeveloper if (false == BPrivate::media::notifications::IsValidNotificationRequest(false, notificationType)) { 1201eae26d3dSbeveloper TRACE("BMediaRoster::StartWatching: notificationType invalid!\n"); 1202eae26d3dSbeveloper return B_BAD_VALUE; 1203eae26d3dSbeveloper } 1204f4925104Sbeveloper return BPrivate::media::notifications::Register(where, media_node::null, notificationType); 120552a38012Sejakowatz } 120652a38012Sejakowatz 120752a38012Sejakowatz 120852a38012Sejakowatz status_t 120952a38012Sejakowatz BMediaRoster::StartWatching(const BMessenger & where, 121052a38012Sejakowatz const media_node & node, 121152a38012Sejakowatz int32 notificationType) 121252a38012Sejakowatz { 1213eae26d3dSbeveloper CALLED(); 1214eae26d3dSbeveloper if (!where.IsValid()) { 1215eae26d3dSbeveloper TRACE("BMediaRoster::StartWatching: messenger invalid!\n"); 1216eae26d3dSbeveloper return B_BAD_VALUE; 1217eae26d3dSbeveloper } 12189e9417d2Sbeveloper if (node.node <= 0) { 1219eae26d3dSbeveloper TRACE("BMediaRoster::StartWatching: node invalid!\n"); 1220eae26d3dSbeveloper return B_MEDIA_BAD_NODE; 1221eae26d3dSbeveloper } 1222f4925104Sbeveloper if (false == BPrivate::media::notifications::IsValidNotificationRequest(true, notificationType)) { 1223eae26d3dSbeveloper TRACE("BMediaRoster::StartWatching: notificationType invalid!\n"); 1224eae26d3dSbeveloper return B_BAD_VALUE; 1225eae26d3dSbeveloper } 1226f4925104Sbeveloper return BPrivate::media::notifications::Register(where, node, notificationType); 122752a38012Sejakowatz } 122852a38012Sejakowatz 122952a38012Sejakowatz 123052a38012Sejakowatz status_t 123152a38012Sejakowatz BMediaRoster::StopWatching(const BMessenger & where) 123252a38012Sejakowatz { 1233eae26d3dSbeveloper CALLED(); 1234eae26d3dSbeveloper // messenger may already be invalid, so we don't check this 1235f4925104Sbeveloper return BPrivate::media::notifications::Unregister(where, media_node::null, B_MEDIA_WILDCARD); 123652a38012Sejakowatz } 123752a38012Sejakowatz 123852a38012Sejakowatz 123952a38012Sejakowatz status_t 124052a38012Sejakowatz BMediaRoster::StopWatching(const BMessenger & where, 124152a38012Sejakowatz int32 notificationType) 124252a38012Sejakowatz { 1243eae26d3dSbeveloper CALLED(); 1244eae26d3dSbeveloper // messenger may already be invalid, so we don't check this 1245f4925104Sbeveloper if (false == BPrivate::media::notifications::IsValidNotificationRequest(false, notificationType)) { 1246eae26d3dSbeveloper TRACE("BMediaRoster::StopWatching: notificationType invalid!\n"); 1247eae26d3dSbeveloper return B_BAD_VALUE; 1248eae26d3dSbeveloper } 1249f4925104Sbeveloper return BPrivate::media::notifications::Unregister(where, media_node::null, notificationType); 125052a38012Sejakowatz } 125152a38012Sejakowatz 125252a38012Sejakowatz 125352a38012Sejakowatz status_t 125452a38012Sejakowatz BMediaRoster::StopWatching(const BMessenger & where, 125552a38012Sejakowatz const media_node & node, 125652a38012Sejakowatz int32 notificationType) 125752a38012Sejakowatz { 1258eae26d3dSbeveloper CALLED(); 1259eae26d3dSbeveloper // messenger may already be invalid, so we don't check this 12609e9417d2Sbeveloper if (node.node <= 0) { 1261eae26d3dSbeveloper TRACE("BMediaRoster::StopWatching: node invalid!\n"); 1262eae26d3dSbeveloper return B_MEDIA_BAD_NODE; 1263eae26d3dSbeveloper } 1264f4925104Sbeveloper if (false == BPrivate::media::notifications::IsValidNotificationRequest(true, notificationType)) { 1265eae26d3dSbeveloper TRACE("BMediaRoster::StopWatching: notificationType invalid!\n"); 1266eae26d3dSbeveloper return B_BAD_VALUE; 1267eae26d3dSbeveloper } 1268f4925104Sbeveloper return BPrivate::media::notifications::Unregister(where, node, notificationType); 126952a38012Sejakowatz } 127052a38012Sejakowatz 127152a38012Sejakowatz 127252a38012Sejakowatz status_t 127352a38012Sejakowatz BMediaRoster::RegisterNode(BMediaNode * node) 127452a38012Sejakowatz { 127552a38012Sejakowatz CALLED(); 127652a38012Sejakowatz if (node == NULL) 127752a38012Sejakowatz return B_BAD_VALUE; 127852a38012Sejakowatz 12793620737cSbeveloper status_t rv; 12809e9417d2Sbeveloper BMediaAddOn *addon; 12819e9417d2Sbeveloper int32 addon_flavor_id; 12829e9417d2Sbeveloper media_addon_id addon_id; 12833620737cSbeveloper 12849e9417d2Sbeveloper addon_flavor_id = 0; 12859e9417d2Sbeveloper addon = node->AddOn(&addon_flavor_id); 12869e9417d2Sbeveloper addon_id = addon ? addon->AddonID() : -1; 128752a38012Sejakowatz 12889e9417d2Sbeveloper server_register_node_request request; 12899e9417d2Sbeveloper server_register_node_reply reply; 12909e9417d2Sbeveloper 12919e9417d2Sbeveloper request.addon_id = addon_id; 12929e9417d2Sbeveloper request.addon_flavor_id = addon_flavor_id; 12939e9417d2Sbeveloper strcpy(request.name, node->Name()); 12949e9417d2Sbeveloper request.kinds = node->Kinds(); 12959e9417d2Sbeveloper request.port = node->ControlPort(); 12969e9417d2Sbeveloper request.team = team; 12979e9417d2Sbeveloper 12981299bfb2Sbeveloper TRACE("BMediaRoster::RegisterNode: sending SERVER_REGISTER_NODE: port %ld, kinds %#Lx, team %ld, name '%s'\n", request.port, request.kinds, request.team, request.name); 12991299bfb2Sbeveloper 13009e9417d2Sbeveloper rv = QueryServer(SERVER_REGISTER_NODE, &request, sizeof(request), &reply, sizeof(reply)); 13019e9417d2Sbeveloper if (rv != B_OK) { 13029e9417d2Sbeveloper TRACE("BMediaRoster::RegisterNode: failed to register node %s (error %#lx)\n", node->Name(), rv); 13039e9417d2Sbeveloper return rv; 13049e9417d2Sbeveloper } 13059e9417d2Sbeveloper 13069e9417d2Sbeveloper // we are a friend class of BMediaNode and initilize this member variable 13079e9417d2Sbeveloper node->fNodeID = reply.nodeid; 13089e9417d2Sbeveloper ASSERT(reply.nodeid == node->Node().node); 13099e9417d2Sbeveloper ASSERT(reply.nodeid == node->ID()); 13109e9417d2Sbeveloper 13119e9417d2Sbeveloper // call the callback 13129e9417d2Sbeveloper node->NodeRegistered(); 13133620737cSbeveloper 1314570f7d04Sbeveloper /* 13153620737cSbeveloper // register existing inputs and outputs with the 13163620737cSbeveloper // media_server, this allows GetLiveNodes() to work 13173620737cSbeveloper // with created, but unconnected nodes. 13183620737cSbeveloper if (node->Kinds() & B_BUFFER_PRODUCER) { 13193620737cSbeveloper Stack<media_output> stack; 13203620737cSbeveloper if (B_OK == GetAllOutputs(node->Node(), &stack)) 13213620737cSbeveloper PublishOutputs(node->Node(), &stack); 13223620737cSbeveloper } else if (node->Kinds() & B_BUFFER_CONSUMER) { 13233620737cSbeveloper Stack<media_input> stack; 13243620737cSbeveloper if (B_OK == GetAllInputs(node->Node(), &stack)) 13253620737cSbeveloper PublishInputs(node->Node(), &stack); 13263620737cSbeveloper } 1327570f7d04Sbeveloper */ 1328570f7d04Sbeveloper 13291299bfb2Sbeveloper BPrivate::media::notifications::NodesCreated(&reply.nodeid, 1); 1330570f7d04Sbeveloper /* 1331570f7d04Sbeveloper TRACE("BMediaRoster::RegisterNode: registered node name '%s', id %ld, addon %ld, flavor %ld\n", node->Name(), node->ID(), addon_id, addon_flavor_id); 1332570f7d04Sbeveloper TRACE("BMediaRoster::RegisterNode: node this %p\n", node); 1333570f7d04Sbeveloper TRACE("BMediaRoster::RegisterNode: node fConsumerThis %p\n", node->fConsumerThis); 1334570f7d04Sbeveloper TRACE("BMediaRoster::RegisterNode: node fProducerThis %p\n", node->fProducerThis); 1335570f7d04Sbeveloper TRACE("BMediaRoster::RegisterNode: node fFileInterfaceThis %p\n", node->fFileInterfaceThis); 1336570f7d04Sbeveloper TRACE("BMediaRoster::RegisterNode: node fControllableThis %p\n", node->fControllableThis); 1337570f7d04Sbeveloper TRACE("BMediaRoster::RegisterNode: node fTimeSourceThis %p\n", node->fTimeSourceThis); 1338570f7d04Sbeveloper */ 13399e9417d2Sbeveloper 13409e9417d2Sbeveloper return B_OK; 134152a38012Sejakowatz } 134252a38012Sejakowatz 134352a38012Sejakowatz 134452a38012Sejakowatz status_t 134552a38012Sejakowatz BMediaRoster::UnregisterNode(BMediaNode * node) 134652a38012Sejakowatz { 13479e9417d2Sbeveloper CALLED(); 13489e9417d2Sbeveloper if (node == NULL) 13499e9417d2Sbeveloper return B_BAD_VALUE; 13509e9417d2Sbeveloper 13519e9417d2Sbeveloper if (node->fRefCount != 0) { 1352570f7d04Sbeveloper TRACE("BMediaRoster::UnregisterNode: Warning node name '%s' has local reference count of %ld\n", node->Name(), node->fRefCount); 13539e9417d2Sbeveloper // no return here, we continue and unregister! 13549e9417d2Sbeveloper } 13559e9417d2Sbeveloper if (node->ID() == -2) { 1356570f7d04Sbeveloper TRACE("BMediaRoster::UnregisterNode: Warning node name '%s' already unregistered\n", node->Name()); 13579e9417d2Sbeveloper return B_OK; 13589e9417d2Sbeveloper } 13599e9417d2Sbeveloper 13609e9417d2Sbeveloper server_unregister_node_request request; 13619e9417d2Sbeveloper server_unregister_node_reply reply; 13629e9417d2Sbeveloper status_t rv; 13639e9417d2Sbeveloper 13649e9417d2Sbeveloper request.nodeid = node->ID(); 13659e9417d2Sbeveloper request.team = team; 13669e9417d2Sbeveloper 13671299bfb2Sbeveloper // send a notification 13681299bfb2Sbeveloper BPrivate::media::notifications::NodesDeleted(&request.nodeid, 1); 13691299bfb2Sbeveloper 13709e9417d2Sbeveloper rv = QueryServer(SERVER_UNREGISTER_NODE, &request, sizeof(request), &reply, sizeof(reply)); 13719e9417d2Sbeveloper if (rv != B_OK) { 1372570f7d04Sbeveloper TRACE("BMediaRoster::UnregisterNode: failed to unregister node name '%s' (error %#lx)\n", node->Name(), rv); 13739e9417d2Sbeveloper return rv; 13749e9417d2Sbeveloper } 13759e9417d2Sbeveloper 13769e9417d2Sbeveloper if (reply.addon_id != -1) 13779e9417d2Sbeveloper _DormantNodeManager->PutAddon(reply.addon_id); 13789e9417d2Sbeveloper 13791299bfb2Sbeveloper // we are a friend class of BMediaNode and invalidate this member variable 13809e9417d2Sbeveloper node->fNodeID = -2; 13819e9417d2Sbeveloper 13829e9417d2Sbeveloper return B_OK; 138352a38012Sejakowatz } 138452a38012Sejakowatz 138552a38012Sejakowatz 138652a38012Sejakowatz // thread safe for multiple calls to Roster() 138752a38012Sejakowatz /* static */ BMediaRoster * 138852a38012Sejakowatz BMediaRoster::Roster(status_t* out_error) 138952a38012Sejakowatz { 139052a38012Sejakowatz static BLocker locker("BMediaRoster::Roster locker"); 139152a38012Sejakowatz locker.Lock(); 139252a38012Sejakowatz if (_sDefault == NULL) { 139352a38012Sejakowatz _sDefault = new BMediaRoster(); 139452a38012Sejakowatz if (out_error != NULL) 139552a38012Sejakowatz *out_error = B_OK; 139652a38012Sejakowatz } else { 139752a38012Sejakowatz if (out_error != NULL) 139852a38012Sejakowatz *out_error = B_OK; 139952a38012Sejakowatz } 140052a38012Sejakowatz locker.Unlock(); 140152a38012Sejakowatz return _sDefault; 140252a38012Sejakowatz } 140352a38012Sejakowatz 140452a38012Sejakowatz 140552a38012Sejakowatz // won't create it if there isn't one 140652a38012Sejakowatz // not thread safe if you call Roster() at the same time 140752a38012Sejakowatz /* static */ BMediaRoster * 140852a38012Sejakowatz BMediaRoster::CurrentRoster() 140952a38012Sejakowatz { 141052a38012Sejakowatz return _sDefault; 141152a38012Sejakowatz } 141252a38012Sejakowatz 141352a38012Sejakowatz 141452a38012Sejakowatz status_t 141552a38012Sejakowatz BMediaRoster::SetTimeSourceFor(media_node_id node, 141652a38012Sejakowatz media_node_id time_source) 141752a38012Sejakowatz { 141852a38012Sejakowatz UNIMPLEMENTED(); 141952a38012Sejakowatz return B_ERROR; 142052a38012Sejakowatz } 142152a38012Sejakowatz 142252a38012Sejakowatz 142352a38012Sejakowatz status_t 142452a38012Sejakowatz BMediaRoster::GetParameterWebFor(const media_node & node, 142552a38012Sejakowatz BParameterWeb ** out_web) 142652a38012Sejakowatz { 142752a38012Sejakowatz UNIMPLEMENTED(); 142852a38012Sejakowatz return B_ERROR; 142952a38012Sejakowatz } 143052a38012Sejakowatz 143152a38012Sejakowatz 143252a38012Sejakowatz status_t 143352a38012Sejakowatz BMediaRoster::StartControlPanel(const media_node & node, 143452a38012Sejakowatz BMessenger * out_messenger) 143552a38012Sejakowatz { 143652a38012Sejakowatz UNIMPLEMENTED(); 143752a38012Sejakowatz return B_ERROR; 143852a38012Sejakowatz } 143952a38012Sejakowatz 144052a38012Sejakowatz 144152a38012Sejakowatz status_t 144252a38012Sejakowatz BMediaRoster::GetDormantNodes(dormant_node_info * out_info, 144352a38012Sejakowatz int32 * io_count, 144452a38012Sejakowatz const media_format * has_input /* = NULL */, 144552a38012Sejakowatz const media_format * has_output /* = NULL */, 144652a38012Sejakowatz const char * name /* = NULL */, 144752a38012Sejakowatz uint64 require_kinds /* = NULL */, 144852a38012Sejakowatz uint64 deny_kinds /* = NULL */) 144952a38012Sejakowatz { 145052a38012Sejakowatz CALLED(); 145152a38012Sejakowatz if (out_info == NULL) 145252a38012Sejakowatz return B_BAD_VALUE; 145352a38012Sejakowatz if (io_count == NULL) 145452a38012Sejakowatz return B_BAD_VALUE; 145552a38012Sejakowatz if (*io_count <= 0) 145652a38012Sejakowatz return B_BAD_VALUE; 145752a38012Sejakowatz 145852a38012Sejakowatz xfer_server_get_dormant_nodes msg; 145952a38012Sejakowatz port_id port; 146052a38012Sejakowatz status_t rv; 146152a38012Sejakowatz 146252a38012Sejakowatz port = find_port("media_server port"); 146352a38012Sejakowatz if (port <= B_OK) 146452a38012Sejakowatz return B_ERROR; 146552a38012Sejakowatz 146652a38012Sejakowatz msg.maxcount = *io_count; 146752a38012Sejakowatz msg.has_input = (bool) has_input; 146852a38012Sejakowatz if (has_input) 146952a38012Sejakowatz msg.inputformat = *has_input; // XXX we should not make a flat copy of media_format 147052a38012Sejakowatz msg.has_output = (bool) has_output; 147152a38012Sejakowatz if (has_output) 147252a38012Sejakowatz msg.outputformat = *has_output;; // XXX we should not make a flat copy of media_format 147352a38012Sejakowatz msg.has_name = (bool) name; 147452a38012Sejakowatz if (name) { 14759e9417d2Sbeveloper int len = strlen(name); 14769e9417d2Sbeveloper len = min_c(len, (int)sizeof(msg.name) - 1); 147752a38012Sejakowatz memcpy(msg.name, name, len); 147852a38012Sejakowatz msg.name[len] = 0; 147952a38012Sejakowatz } 148052a38012Sejakowatz msg.require_kinds = require_kinds; 148152a38012Sejakowatz msg.deny_kinds = deny_kinds; 148252a38012Sejakowatz msg.reply_port = _PortPool->GetPort(); 148352a38012Sejakowatz 148452a38012Sejakowatz rv = write_port(port, SERVER_GET_DORMANT_NODES, &msg, sizeof(msg)); 148552a38012Sejakowatz if (rv != B_OK) { 148652a38012Sejakowatz _PortPool->PutPort(msg.reply_port); 148752a38012Sejakowatz return rv; 148852a38012Sejakowatz } 148952a38012Sejakowatz 149052a38012Sejakowatz xfer_server_get_dormant_nodes_reply reply; 149152a38012Sejakowatz int32 code; 149252a38012Sejakowatz 149352a38012Sejakowatz rv = read_port(msg.reply_port, &code, &reply, sizeof(reply)); 149452a38012Sejakowatz if (rv < B_OK) { 149552a38012Sejakowatz _PortPool->PutPort(msg.reply_port); 149652a38012Sejakowatz return rv; 149752a38012Sejakowatz } 149852a38012Sejakowatz 149952a38012Sejakowatz *io_count = reply.count; 150052a38012Sejakowatz 150152a38012Sejakowatz if (*io_count > 0) { 150252a38012Sejakowatz rv = read_port(msg.reply_port, &code, out_info, *io_count * sizeof(dormant_node_info)); 150352a38012Sejakowatz if (rv < B_OK) 150452a38012Sejakowatz reply.result = rv; 150552a38012Sejakowatz } 150652a38012Sejakowatz _PortPool->PutPort(msg.reply_port); 150752a38012Sejakowatz 150852a38012Sejakowatz return reply.result; 150952a38012Sejakowatz } 151052a38012Sejakowatz 151152a38012Sejakowatz 151252a38012Sejakowatz status_t 151352a38012Sejakowatz BMediaRoster::InstantiateDormantNode(const dormant_node_info & in_info, 151452a38012Sejakowatz media_node * out_node, 151552a38012Sejakowatz uint32 flags /* currently B_FLAVOR_IS_GLOBAL or B_FLAVOR_IS_LOCAL */ ) 151652a38012Sejakowatz { 151752a38012Sejakowatz CALLED(); 151852a38012Sejakowatz if ((flags & (B_FLAVOR_IS_GLOBAL | B_FLAVOR_IS_LOCAL)) == 0) { 151952a38012Sejakowatz printf("Error: BMediaRoster::InstantiateDormantNode called without flags\n"); 152052a38012Sejakowatz return B_BAD_VALUE; 152152a38012Sejakowatz } 152252a38012Sejakowatz if (out_node == 0) 152352a38012Sejakowatz return B_BAD_VALUE; 152452a38012Sejakowatz 152552a38012Sejakowatz // XXX we should not trust the values passed in by the user, 152652a38012Sejakowatz // XXX and ask the server to determine where to insta 152752a38012Sejakowatz 1528e0207628Sbeveloper 1529e0207628Sbeveloper // XXX SOMETHING IS VERY WRONG HERE 1530e0207628Sbeveloper // if ((in_info.flavor_flags & B_FLAVOR_IS_GLOBAL) == 0 && (flags & B_FLAVOR_IS_LOCAL)) { 1531e0207628Sbeveloper if (flags & B_FLAVOR_IS_LOCAL) { 153252a38012Sejakowatz return InstantiateDormantNode(in_info,out_node); 153352a38012Sejakowatz } 153452a38012Sejakowatz 1535e0207628Sbeveloper // XXX SOMETHING IS VERY WRONG HERE 1536e0207628Sbeveloper // if ((in_info.flavor_flags & B_FLAVOR_IS_GLOBAL) || (flags & B_FLAVOR_IS_GLOBAL)) { 1537e0207628Sbeveloper if (flags & B_FLAVOR_IS_GLOBAL) { 153852a38012Sejakowatz // forward this request into the media_addon_server, 153952a38012Sejakowatz // which in turn will call InstantiateDormantNode() 154052a38012Sejakowatz // to create it there localy 15418c6a6096Sbeveloper addonserver_instantiate_dormant_node_request request; 15428c6a6096Sbeveloper addonserver_instantiate_dormant_node_reply reply; 154352a38012Sejakowatz status_t rv; 1544f4925104Sbeveloper 1545f4925104Sbeveloper request.info = in_info; 1546f4925104Sbeveloper rv = QueryAddonServer(ADDONSERVER_INSTANTIATE_DORMANT_NODE, &request, sizeof(request), &reply, sizeof(reply)); 1547f4925104Sbeveloper if (rv == B_OK) { 154852a38012Sejakowatz *out_node = reply.node; 1549f4925104Sbeveloper } 1550f4925104Sbeveloper return rv; 155152a38012Sejakowatz } 155252a38012Sejakowatz 1553e0207628Sbeveloper // XXX SOMETHING IS VERY WRONG HERE 15545edd2016Sbeveloper printf("Error: BMediaRoster::InstantiateDormantNode addon_id %d, flavor_id %d, flags %#08lx\n", (int)in_info.addon, (int)in_info.flavor_id, flags); 155552a38012Sejakowatz 155652a38012Sejakowatz return B_ERROR; 155752a38012Sejakowatz } 155852a38012Sejakowatz 155952a38012Sejakowatz 156052a38012Sejakowatz status_t 156152a38012Sejakowatz BMediaRoster::InstantiateDormantNode(const dormant_node_info & in_info, 156252a38012Sejakowatz media_node * out_node) 156352a38012Sejakowatz { 156416b7eea4Sbeveloper CALLED(); 156552a38012Sejakowatz 156652a38012Sejakowatz // to instantiate a dormant node in the current address space, we need to 156752a38012Sejakowatz // either load the add-on from file and create a new BMediaAddOn class, or 156852a38012Sejakowatz // reuse the cached BMediaAddOn from a previous call 156952a38012Sejakowatz // call BMediaAddOn::InstantiateNodeFor() 157052a38012Sejakowatz // and cache the BMediaAddOn after that for later reuse. 157152a38012Sejakowatz // BeOS R5 does not seem to delete it when the application quits 157252a38012Sejakowatz // if B_FLAVOR_IS_GLOBAL, we need to use the BMediaAddOn object that 157352a38012Sejakowatz // resides in the media_addon_server 157452a38012Sejakowatz 157552a38012Sejakowatz // RegisterNode() is called automatically for nodes instantiated from add-ons 157652a38012Sejakowatz 157716b7eea4Sbeveloper //XXX TEST! 157816b7eea4Sbeveloper BMediaAddOn *addon; 157916b7eea4Sbeveloper BMediaNode *node; 158016b7eea4Sbeveloper BMessage config; 158116b7eea4Sbeveloper status_t out_error; 15828c6a6096Sbeveloper status_t rv; 158316b7eea4Sbeveloper addon = _DormantNodeManager->GetAddon(in_info.addon); 158416b7eea4Sbeveloper if (!addon) { 158516b7eea4Sbeveloper printf("BMediaRoster::InstantiateDormantNode: GetAddon failed\n"); 158652a38012Sejakowatz return B_ERROR; 158752a38012Sejakowatz } 15881299bfb2Sbeveloper flavor_info temp; // XXX fix this! 15891299bfb2Sbeveloper temp.name = "XXX flavor_info name"; 15901299bfb2Sbeveloper temp.info = "XXX flavor_info info"; 159116b7eea4Sbeveloper temp.internal_id = in_info.flavor_id; 159216b7eea4Sbeveloper node = addon->InstantiateNodeFor(&temp, &config, &out_error); 159316b7eea4Sbeveloper if (!node) { 159416b7eea4Sbeveloper printf("BMediaRoster::InstantiateDormantNode: InstantiateNodeFor failed\n"); 159516b7eea4Sbeveloper _DormantNodeManager->PutAddon(in_info.addon); 159616b7eea4Sbeveloper return B_ERROR; 159716b7eea4Sbeveloper } 15988c6a6096Sbeveloper rv = RegisterNode(node); 15998c6a6096Sbeveloper if (rv != B_OK) { 16008c6a6096Sbeveloper printf("BMediaRoster::InstantiateDormantNode: RegisterNode failed\n"); 16018c6a6096Sbeveloper delete node; 16028c6a6096Sbeveloper _DormantNodeManager->PutAddon(in_info.addon); 16038c6a6096Sbeveloper return B_ERROR; 16048c6a6096Sbeveloper } 16058c6a6096Sbeveloper 16068c6a6096Sbeveloper // XXX we must remember in_info.addon and call 16078c6a6096Sbeveloper // XXX _DormantNodeManager->PutAddon when the 16088c6a6096Sbeveloper // XXX node is unregistered 16099e9417d2Sbeveloper // should be handled by RegisterNode() and UnegisterNode() now 16108c6a6096Sbeveloper 161116b7eea4Sbeveloper *out_node = node->Node(); 161216b7eea4Sbeveloper return B_OK; 161316b7eea4Sbeveloper } 161452a38012Sejakowatz 161552a38012Sejakowatz 161652a38012Sejakowatz status_t 161752a38012Sejakowatz BMediaRoster::GetDormantNodeFor(const media_node & node, 161852a38012Sejakowatz dormant_node_info * out_info) 161952a38012Sejakowatz { 162085dfab2bSbeveloper CALLED(); 162185dfab2bSbeveloper if (out_info == NULL) 162285dfab2bSbeveloper return B_BAD_VALUE; 162385dfab2bSbeveloper if (node.node <= 0) 162485dfab2bSbeveloper return B_MEDIA_BAD_NODE; 162552a38012Sejakowatz 162685dfab2bSbeveloper server_get_dormant_node_for_request request; 162785dfab2bSbeveloper server_get_dormant_node_for_reply reply; 162885dfab2bSbeveloper status_t rv; 162985dfab2bSbeveloper 163085dfab2bSbeveloper request.node = node; 163185dfab2bSbeveloper 16321299bfb2Sbeveloper rv = QueryServer(SERVER_GET_DORMANT_NODE_FOR, &request, sizeof(request), &reply, sizeof(reply)); 163385dfab2bSbeveloper if (rv != B_OK) 163485dfab2bSbeveloper return rv; 163585dfab2bSbeveloper 163685dfab2bSbeveloper *out_info = reply.node_info; 163785dfab2bSbeveloper return B_OK; 163852a38012Sejakowatz } 163952a38012Sejakowatz 164052a38012Sejakowatz 164152a38012Sejakowatz status_t 164252a38012Sejakowatz BMediaRoster::GetDormantFlavorInfoFor(const dormant_node_info & in_dormant, 164352a38012Sejakowatz dormant_flavor_info * out_flavor) 164452a38012Sejakowatz { 164552a38012Sejakowatz CALLED(); 164652a38012Sejakowatz 164752a38012Sejakowatz xfer_server_get_dormant_flavor_info msg; 164852a38012Sejakowatz xfer_server_get_dormant_flavor_info_reply *reply; 164952a38012Sejakowatz port_id port; 165052a38012Sejakowatz status_t rv; 165152a38012Sejakowatz int32 code; 165252a38012Sejakowatz 165352a38012Sejakowatz port = find_port("media_server port"); 165452a38012Sejakowatz if (port <= B_OK) 165552a38012Sejakowatz return B_ERROR; 165652a38012Sejakowatz 165752a38012Sejakowatz reply = (xfer_server_get_dormant_flavor_info_reply *) malloc(16000); 165852a38012Sejakowatz if (reply == 0) 165952a38012Sejakowatz return B_ERROR; 166052a38012Sejakowatz 166152a38012Sejakowatz msg.addon = in_dormant.addon; 166252a38012Sejakowatz msg.flavor_id = in_dormant.flavor_id; 166352a38012Sejakowatz msg.reply_port = _PortPool->GetPort(); 166452a38012Sejakowatz rv = write_port(port, SERVER_GET_DORMANT_FLAVOR_INFO, &msg, sizeof(msg)); 166552a38012Sejakowatz if (rv != B_OK) { 166652a38012Sejakowatz free(reply); 166752a38012Sejakowatz _PortPool->PutPort(msg.reply_port); 166852a38012Sejakowatz return rv; 166952a38012Sejakowatz } 167052a38012Sejakowatz rv = read_port(msg.reply_port, &code, reply, 16000); 167152a38012Sejakowatz _PortPool->PutPort(msg.reply_port); 167252a38012Sejakowatz 167352a38012Sejakowatz if (rv < B_OK) { 167452a38012Sejakowatz free(reply); 167552a38012Sejakowatz return rv; 167652a38012Sejakowatz } 167752a38012Sejakowatz 167852a38012Sejakowatz if (reply->result == B_OK) 167952a38012Sejakowatz rv = out_flavor->Unflatten(reply->dfi_type, &reply->dfi, reply->dfi_size); 168052a38012Sejakowatz else 168152a38012Sejakowatz rv = reply->result; 168252a38012Sejakowatz 168352a38012Sejakowatz free(reply); 168452a38012Sejakowatz return rv; 168552a38012Sejakowatz } 168652a38012Sejakowatz 168752a38012Sejakowatz 168852a38012Sejakowatz status_t 168952a38012Sejakowatz BMediaRoster::GetLatencyFor(const media_node & producer, 169052a38012Sejakowatz bigtime_t * out_latency) 169152a38012Sejakowatz { 169252a38012Sejakowatz UNIMPLEMENTED(); 169352a38012Sejakowatz *out_latency = 0; 169452a38012Sejakowatz return B_ERROR; 169552a38012Sejakowatz } 169652a38012Sejakowatz 169752a38012Sejakowatz 169852a38012Sejakowatz status_t 169952a38012Sejakowatz BMediaRoster::GetInitialLatencyFor(const media_node & producer, 170052a38012Sejakowatz bigtime_t * out_latency, 170152a38012Sejakowatz uint32 * out_flags) 170252a38012Sejakowatz { 170352a38012Sejakowatz UNIMPLEMENTED(); 170452a38012Sejakowatz *out_latency = 0; 170552a38012Sejakowatz *out_flags = 0; 170652a38012Sejakowatz return B_ERROR; 170752a38012Sejakowatz } 170852a38012Sejakowatz 170952a38012Sejakowatz 171052a38012Sejakowatz status_t 171152a38012Sejakowatz BMediaRoster::GetStartLatencyFor(const media_node & time_source, 171252a38012Sejakowatz bigtime_t * out_latency) 171352a38012Sejakowatz { 171452a38012Sejakowatz UNIMPLEMENTED(); 171552a38012Sejakowatz *out_latency = 0; 171652a38012Sejakowatz return B_ERROR; 171752a38012Sejakowatz } 171852a38012Sejakowatz 171952a38012Sejakowatz 172052a38012Sejakowatz status_t 172152a38012Sejakowatz BMediaRoster::GetFileFormatsFor(const media_node & file_interface, 172252a38012Sejakowatz media_file_format * out_formats, 172352a38012Sejakowatz int32 * io_num_infos) 172452a38012Sejakowatz { 172552a38012Sejakowatz UNIMPLEMENTED(); 172652a38012Sejakowatz return B_ERROR; 172752a38012Sejakowatz } 172852a38012Sejakowatz 172952a38012Sejakowatz 173052a38012Sejakowatz status_t 173152a38012Sejakowatz BMediaRoster::SetRefFor(const media_node & file_interface, 173252a38012Sejakowatz const entry_ref & file, 173352a38012Sejakowatz bool create_and_truncate, 173452a38012Sejakowatz bigtime_t * out_length) /* if create is false */ 173552a38012Sejakowatz { 173652a38012Sejakowatz UNIMPLEMENTED(); 173752a38012Sejakowatz return B_ERROR; 173852a38012Sejakowatz } 173952a38012Sejakowatz 174052a38012Sejakowatz 174152a38012Sejakowatz status_t 174252a38012Sejakowatz BMediaRoster::GetRefFor(const media_node & node, 174352a38012Sejakowatz entry_ref * out_file, 174452a38012Sejakowatz BMimeType * mime_type) 174552a38012Sejakowatz { 174652a38012Sejakowatz UNIMPLEMENTED(); 174752a38012Sejakowatz return B_ERROR; 174852a38012Sejakowatz } 174952a38012Sejakowatz 175052a38012Sejakowatz 175152a38012Sejakowatz status_t 175252a38012Sejakowatz BMediaRoster::SniffRefFor(const media_node & file_interface, 175352a38012Sejakowatz const entry_ref & file, 175452a38012Sejakowatz BMimeType * mime_type, 175552a38012Sejakowatz float * out_capability) 175652a38012Sejakowatz { 175752a38012Sejakowatz UNIMPLEMENTED(); 175852a38012Sejakowatz return B_ERROR; 175952a38012Sejakowatz } 176052a38012Sejakowatz 176152a38012Sejakowatz 176252a38012Sejakowatz /* This is the generic "here's a file, now can someone please play it" interface */ 176352a38012Sejakowatz status_t 176452a38012Sejakowatz BMediaRoster::SniffRef(const entry_ref & file, 176552a38012Sejakowatz uint64 require_node_kinds, /* if you need an EntityInterface or BufferConsumer or something */ 176652a38012Sejakowatz dormant_node_info * out_node, 176752a38012Sejakowatz BMimeType * mime_type) 176852a38012Sejakowatz { 176952a38012Sejakowatz UNIMPLEMENTED(); 177052a38012Sejakowatz return B_ERROR; 177152a38012Sejakowatz } 177252a38012Sejakowatz 177352a38012Sejakowatz 177452a38012Sejakowatz status_t 177552a38012Sejakowatz BMediaRoster::GetDormantNodeForType(const BMimeType & type, 177652a38012Sejakowatz uint64 require_node_kinds, 177752a38012Sejakowatz dormant_node_info * out_node) 177852a38012Sejakowatz { 177952a38012Sejakowatz UNIMPLEMENTED(); 178052a38012Sejakowatz return B_ERROR; 178152a38012Sejakowatz } 178252a38012Sejakowatz 178352a38012Sejakowatz 178452a38012Sejakowatz status_t 178552a38012Sejakowatz BMediaRoster::GetReadFileFormatsFor(const dormant_node_info & in_node, 178652a38012Sejakowatz media_file_format * out_read_formats, 178752a38012Sejakowatz int32 in_read_count, 178852a38012Sejakowatz int32 * out_read_count) 178952a38012Sejakowatz { 179052a38012Sejakowatz UNIMPLEMENTED(); 179152a38012Sejakowatz return B_ERROR; 179252a38012Sejakowatz } 179352a38012Sejakowatz 179452a38012Sejakowatz 179552a38012Sejakowatz status_t 179652a38012Sejakowatz BMediaRoster::GetWriteFileFormatsFor(const dormant_node_info & in_node, 179752a38012Sejakowatz media_file_format * out_write_formats, 179852a38012Sejakowatz int32 in_write_count, 179952a38012Sejakowatz int32 * out_write_count) 180052a38012Sejakowatz { 180152a38012Sejakowatz UNIMPLEMENTED(); 180252a38012Sejakowatz return B_ERROR; 180352a38012Sejakowatz } 180452a38012Sejakowatz 180552a38012Sejakowatz 180652a38012Sejakowatz status_t 180752a38012Sejakowatz BMediaRoster::GetFormatFor(const media_output & output, 180852a38012Sejakowatz media_format * io_format, 180952a38012Sejakowatz uint32 flags) 181052a38012Sejakowatz { 181152a38012Sejakowatz UNIMPLEMENTED(); 181252a38012Sejakowatz return B_ERROR; 181352a38012Sejakowatz } 181452a38012Sejakowatz 181552a38012Sejakowatz 181652a38012Sejakowatz status_t 181752a38012Sejakowatz BMediaRoster::GetFormatFor(const media_input & input, 181852a38012Sejakowatz media_format * io_format, 181952a38012Sejakowatz uint32 flags) 182052a38012Sejakowatz { 182152a38012Sejakowatz UNIMPLEMENTED(); 182252a38012Sejakowatz return B_ERROR; 182352a38012Sejakowatz } 182452a38012Sejakowatz 182552a38012Sejakowatz 182652a38012Sejakowatz status_t 182752a38012Sejakowatz BMediaRoster::GetFormatFor(const media_node & node, 182852a38012Sejakowatz media_format * io_format, 182952a38012Sejakowatz float quality) 183052a38012Sejakowatz { 183152a38012Sejakowatz UNIMPLEMENTED(); 183252a38012Sejakowatz return B_ERROR; 183352a38012Sejakowatz } 183452a38012Sejakowatz 183552a38012Sejakowatz 183652a38012Sejakowatz ssize_t 183752a38012Sejakowatz BMediaRoster::GetNodeAttributesFor(const media_node & node, 183852a38012Sejakowatz media_node_attribute * outArray, 183952a38012Sejakowatz size_t inMaxCount) 184052a38012Sejakowatz { 184152a38012Sejakowatz UNIMPLEMENTED(); 184252a38012Sejakowatz return B_ERROR; 184352a38012Sejakowatz } 184452a38012Sejakowatz 184552a38012Sejakowatz 184652a38012Sejakowatz media_node_id 184752a38012Sejakowatz BMediaRoster::NodeIDFor(port_id source_or_destination_port) 184852a38012Sejakowatz { 18499e9417d2Sbeveloper CALLED(); 18509e9417d2Sbeveloper 18519e9417d2Sbeveloper server_node_id_for_request request; 18529e9417d2Sbeveloper server_node_id_for_reply reply; 18539e9417d2Sbeveloper status_t rv; 18549e9417d2Sbeveloper 18559e9417d2Sbeveloper request.port = source_or_destination_port; 18569e9417d2Sbeveloper 18579e9417d2Sbeveloper rv = QueryServer(SERVER_NODE_ID_FOR, &request, sizeof(request), &reply, sizeof(reply)); 18589e9417d2Sbeveloper if (rv != B_OK) { 18599e9417d2Sbeveloper TRACE("BMediaRoster::NodeIDFor: failed (error %#lx)\n", rv); 18609e9417d2Sbeveloper return -1; 18619e9417d2Sbeveloper } 18629e9417d2Sbeveloper 18639e9417d2Sbeveloper return reply.nodeid; 186452a38012Sejakowatz } 186552a38012Sejakowatz 186652a38012Sejakowatz 186752a38012Sejakowatz status_t 186852a38012Sejakowatz BMediaRoster::GetInstancesFor(media_addon_id addon, 186952a38012Sejakowatz int32 flavor, 187052a38012Sejakowatz media_node_id * out_id, 187152a38012Sejakowatz int32 * io_count) 187252a38012Sejakowatz { 187385dfab2bSbeveloper CALLED(); 187485dfab2bSbeveloper if (out_id == NULL || io_count == NULL) 187585dfab2bSbeveloper return B_BAD_VALUE; 187685dfab2bSbeveloper if (*io_count <= 0) 187785dfab2bSbeveloper return B_BAD_VALUE; 187885dfab2bSbeveloper 187985dfab2bSbeveloper server_get_instances_for_request request; 188085dfab2bSbeveloper server_get_instances_for_reply reply; 188185dfab2bSbeveloper status_t rv; 188285dfab2bSbeveloper 188385dfab2bSbeveloper request.maxcount = *io_count; 188485dfab2bSbeveloper request.addon_id = addon; 188585dfab2bSbeveloper request.addon_flavor_id = flavor; 188685dfab2bSbeveloper 188785dfab2bSbeveloper rv = QueryServer(SERVER_GET_INSTANCES_FOR, &request, sizeof(request), &reply, sizeof(reply)); 188885dfab2bSbeveloper if (rv != B_OK) { 188985dfab2bSbeveloper TRACE("BMediaRoster::GetLiveNodes failed\n"); 189085dfab2bSbeveloper return rv; 189152a38012Sejakowatz } 189252a38012Sejakowatz 189385dfab2bSbeveloper *io_count = reply.count; 189485dfab2bSbeveloper if (reply.count > 0) 189585dfab2bSbeveloper memcpy(out_id, reply.node_id, sizeof(media_node_id) * reply.count); 189685dfab2bSbeveloper 189785dfab2bSbeveloper return B_OK; 189885dfab2bSbeveloper } 189952a38012Sejakowatz 190052a38012Sejakowatz 190152a38012Sejakowatz status_t 190252a38012Sejakowatz BMediaRoster::SetRealtimeFlags(uint32 in_enabled) 190352a38012Sejakowatz { 190452a38012Sejakowatz UNIMPLEMENTED(); 190552a38012Sejakowatz return B_ERROR; 190652a38012Sejakowatz } 190752a38012Sejakowatz 190852a38012Sejakowatz 190952a38012Sejakowatz status_t 191052a38012Sejakowatz BMediaRoster::GetRealtimeFlags(uint32 * out_enabled) 191152a38012Sejakowatz { 191252a38012Sejakowatz UNIMPLEMENTED(); 191352a38012Sejakowatz return B_ERROR; 191452a38012Sejakowatz } 191552a38012Sejakowatz 191652a38012Sejakowatz 191752a38012Sejakowatz ssize_t 191852a38012Sejakowatz BMediaRoster::AudioBufferSizeFor(int32 channel_count, 191952a38012Sejakowatz uint32 sample_format, 192052a38012Sejakowatz float frame_rate, 192152a38012Sejakowatz bus_type bus_kind) 192252a38012Sejakowatz { 192352a38012Sejakowatz UNIMPLEMENTED(); 192452a38012Sejakowatz return 4096; 192552a38012Sejakowatz } 192652a38012Sejakowatz 192752a38012Sejakowatz 192852a38012Sejakowatz /* Use MediaFlags to inquire about specific features of the Media Kit. */ 192952a38012Sejakowatz /* Returns < 0 for "not present", positive size for output data size. */ 193052a38012Sejakowatz /* 0 means that the capability is present, but no data about it. */ 193152a38012Sejakowatz /* static */ ssize_t 193252a38012Sejakowatz BMediaRoster::MediaFlags(media_flags cap, 193352a38012Sejakowatz void * buf, 193452a38012Sejakowatz size_t maxSize) 193552a38012Sejakowatz { 193652a38012Sejakowatz UNIMPLEMENTED(); 193752a38012Sejakowatz return 0; 193852a38012Sejakowatz } 193952a38012Sejakowatz 194052a38012Sejakowatz 194152a38012Sejakowatz /* BLooper overrides */ 194252a38012Sejakowatz /* virtual */ void 194352a38012Sejakowatz BMediaRoster::MessageReceived(BMessage * message) 194452a38012Sejakowatz { 1945*6396865dSbeveloper // media_server plays ping-pong with the BMediaRosters 1946*6396865dSbeveloper // to detect dead teams. Normal communication uses ports. 1947*6396865dSbeveloper static BMessage pong('PONG'); 1948*6396865dSbeveloper if (message->what == 'PING') { 1949*6396865dSbeveloper message->SendReply(&pong, static_cast<BHandler *>(NULL), 2000000); 1950*6396865dSbeveloper return; 1951*6396865dSbeveloper } 1952*6396865dSbeveloper 1953*6396865dSbeveloper printf("BMediaRoster::MessageReceived: unknown message!\n"); 1954*6396865dSbeveloper message->PrintToStream(); 195552a38012Sejakowatz } 195652a38012Sejakowatz 195752a38012Sejakowatz /* virtual */ bool 195852a38012Sejakowatz BMediaRoster::QuitRequested() 195952a38012Sejakowatz { 196052a38012Sejakowatz UNIMPLEMENTED(); 196152a38012Sejakowatz return true; 196252a38012Sejakowatz } 196352a38012Sejakowatz 196452a38012Sejakowatz /* virtual */ BHandler * 196552a38012Sejakowatz BMediaRoster::ResolveSpecifier(BMessage *msg, 196652a38012Sejakowatz int32 index, 196752a38012Sejakowatz BMessage *specifier, 196852a38012Sejakowatz int32 form, 196952a38012Sejakowatz const char *property) 197052a38012Sejakowatz { 197152a38012Sejakowatz UNIMPLEMENTED(); 197252a38012Sejakowatz return 0; 197352a38012Sejakowatz } 197452a38012Sejakowatz 197552a38012Sejakowatz 197652a38012Sejakowatz /* virtual */ status_t 197752a38012Sejakowatz BMediaRoster::GetSupportedSuites(BMessage *data) 197852a38012Sejakowatz { 197952a38012Sejakowatz UNIMPLEMENTED(); 198052a38012Sejakowatz return B_ERROR; 198152a38012Sejakowatz } 198252a38012Sejakowatz 198352a38012Sejakowatz 198452a38012Sejakowatz BMediaRoster::~BMediaRoster() 198552a38012Sejakowatz { 198652a38012Sejakowatz CALLED(); 1987*6396865dSbeveloper 1988*6396865dSbeveloper // unregister this application with the media server 1989*6396865dSbeveloper server_unregister_app_request request; 1990*6396865dSbeveloper server_unregister_app_reply reply; 1991*6396865dSbeveloper request.team = team; 1992*6396865dSbeveloper QueryServer(SERVER_UNREGISTER_APP, &request, sizeof(request), &reply, sizeof(reply)); 199352a38012Sejakowatz } 199452a38012Sejakowatz 199552a38012Sejakowatz 199652a38012Sejakowatz /************************************************************* 199752a38012Sejakowatz * private BMediaRoster 199852a38012Sejakowatz *************************************************************/ 199952a38012Sejakowatz 200052a38012Sejakowatz // deprecated call 200152a38012Sejakowatz status_t 200252a38012Sejakowatz BMediaRoster::SetOutputBuffersFor(const media_source & output, 200352a38012Sejakowatz BBufferGroup * group, 200452a38012Sejakowatz bool will_reclaim ) 200552a38012Sejakowatz { 200652a38012Sejakowatz UNIMPLEMENTED(); 20079e9417d2Sbeveloper debugger("BMediaRoster::SetOutputBuffersFor missing\n"); 200852a38012Sejakowatz return B_ERROR; 200952a38012Sejakowatz } 201052a38012Sejakowatz 201152a38012Sejakowatz 201252a38012Sejakowatz /* FBC stuffing (Mmmh, Stuffing!) */ 201352a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_0(void *) { return B_ERROR; } 201452a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_1(void *) { return B_ERROR; } 201552a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_2(void *) { return B_ERROR; } 201652a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_3(void *) { return B_ERROR; } 201752a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_4(void *) { return B_ERROR; } 201852a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_5(void *) { return B_ERROR; } 201952a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_6(void *) { return B_ERROR; } 202052a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_7(void *) { return B_ERROR; } 202152a38012Sejakowatz 202252a38012Sejakowatz 202352a38012Sejakowatz BMediaRoster::BMediaRoster() : 2024*6396865dSbeveloper BLooper("_BMediaRoster_", B_URGENT_DISPLAY_PRIORITY, B_LOOPER_PORT_DEFAULT_CAPACITY) 202552a38012Sejakowatz { 202652a38012Sejakowatz CALLED(); 2027*6396865dSbeveloper 2028*6396865dSbeveloper // start the looper 2029*6396865dSbeveloper Run(); 2030*6396865dSbeveloper 2031*6396865dSbeveloper // register this application with the media server 2032*6396865dSbeveloper server_register_app_request request; 2033*6396865dSbeveloper server_register_app_reply reply; 2034*6396865dSbeveloper request.team = team; 2035*6396865dSbeveloper request.messenger = BMessenger(NULL, this); 2036*6396865dSbeveloper QueryServer(SERVER_REGISTER_APP, &request, sizeof(request), &reply, sizeof(reply)); 203752a38012Sejakowatz } 203852a38012Sejakowatz 2039*6396865dSbeveloper 204052a38012Sejakowatz /* static */ status_t 204152a38012Sejakowatz BMediaRoster::ParseCommand(BMessage & reply) 204252a38012Sejakowatz { 204352a38012Sejakowatz UNIMPLEMENTED(); 204452a38012Sejakowatz return B_ERROR; 204552a38012Sejakowatz } 204652a38012Sejakowatz 204752a38012Sejakowatz 204852a38012Sejakowatz status_t 204952a38012Sejakowatz BMediaRoster::GetDefaultInfo(media_node_id for_default, 205052a38012Sejakowatz BMessage & out_config) 205152a38012Sejakowatz { 205252a38012Sejakowatz UNIMPLEMENTED(); 205352a38012Sejakowatz return B_ERROR; 205452a38012Sejakowatz } 205552a38012Sejakowatz 205652a38012Sejakowatz 205752a38012Sejakowatz 205852a38012Sejakowatz status_t 205952a38012Sejakowatz BMediaRoster::SetRunningDefault(media_node_id for_default, 206052a38012Sejakowatz const media_node & node) 206152a38012Sejakowatz { 206252a38012Sejakowatz UNIMPLEMENTED(); 206352a38012Sejakowatz return B_ERROR; 206452a38012Sejakowatz } 206552a38012Sejakowatz 206652a38012Sejakowatz 206752a38012Sejakowatz /************************************************************* 206852a38012Sejakowatz * static BMediaRoster variables 206952a38012Sejakowatz *************************************************************/ 207052a38012Sejakowatz 207152a38012Sejakowatz bool BMediaRoster::_isMediaServer; 207252a38012Sejakowatz port_id BMediaRoster::_mReplyPort; 207352a38012Sejakowatz int32 BMediaRoster::_mReplyPortRes; 207452a38012Sejakowatz int32 BMediaRoster::_mReplyPortUnavailCount; 207552a38012Sejakowatz BMediaRoster * BMediaRoster::_sDefault = NULL; 207652a38012Sejakowatz 2077