1255a01c7Sbeveloper /* 2255a01c7Sbeveloper * Copyright (c) 2002, 2003 Marcus Overhagen <Marcus@Overhagen.de> 3255a01c7Sbeveloper * 4255a01c7Sbeveloper * Permission is hereby granted, free of charge, to any person obtaining 5255a01c7Sbeveloper * a copy of this software and associated documentation files or portions 6255a01c7Sbeveloper * thereof (the "Software"), to deal in the Software without restriction, 7255a01c7Sbeveloper * including without limitation the rights to use, copy, modify, merge, 8255a01c7Sbeveloper * publish, distribute, sublicense, and/or sell copies of the Software, 9255a01c7Sbeveloper * and to permit persons to whom the Software is furnished to do so, subject 10255a01c7Sbeveloper * to the following conditions: 11255a01c7Sbeveloper * 12255a01c7Sbeveloper * * Redistributions of source code must retain the above copyright notice, 13255a01c7Sbeveloper * this list of conditions and the following disclaimer. 14255a01c7Sbeveloper * 15255a01c7Sbeveloper * * Redistributions in binary form must reproduce the above copyright notice 16255a01c7Sbeveloper * in the binary, as well as this list of conditions and the following 17255a01c7Sbeveloper * disclaimer in the documentation and/or other materials provided with 18255a01c7Sbeveloper * the distribution. 19255a01c7Sbeveloper * 20255a01c7Sbeveloper * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 21255a01c7Sbeveloper * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22255a01c7Sbeveloper * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 23255a01c7Sbeveloper * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24255a01c7Sbeveloper * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25255a01c7Sbeveloper * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 26255a01c7Sbeveloper * THE SOFTWARE. 27255a01c7Sbeveloper * 28255a01c7Sbeveloper */ 29255a01c7Sbeveloper 30255a01c7Sbeveloper /* to comply with the license above, do not remove the following line */ 31255a01c7Sbeveloper static char __copyright[] = "Copyright (c) 2002, 2003 Marcus Overhagen <Marcus@Overhagen.de>"; 32255a01c7Sbeveloper 3352a38012Sejakowatz #include <MediaRoster.h> 3452a38012Sejakowatz #include <Locker.h> 3552a38012Sejakowatz #include <Message.h> 3652a38012Sejakowatz #include <Messenger.h> 3752a38012Sejakowatz #include <StopWatch.h> 3852a38012Sejakowatz #include <OS.h> 3952a38012Sejakowatz #include <String.h> 4052a38012Sejakowatz #include <TimeSource.h> 4160f15390Sbeveloper #include <ParameterWeb.h> 4252a38012Sejakowatz #include "debug.h" 438b04ffc1Sbeveloper #include "MediaRosterEx.h" 4440f36b03Sbeveloper #include "MediaMisc.h" 4552a38012Sejakowatz #include "PortPool.h" 460a483e72SIngo Weinhold #include "ServerInterface.h" 47f4925104Sbeveloper #include "DataExchange.h" 4816b7eea4Sbeveloper #include "DormantNodeManager.h" 49f4925104Sbeveloper #include "Notifications.h" 50835140c8Sbeveloper #include "TimeSourceObjectManager.h" 5152a38012Sejakowatz 52f4925104Sbeveloper namespace BPrivate { namespace media { 5352a38012Sejakowatz 5452a38012Sejakowatz // the BMediaRoster destructor is private, 5552a38012Sejakowatz // but _DefaultDeleter is a friend class of 5652a38012Sejakowatz // the BMediaRoster an thus can delete it 578b04ffc1Sbeveloper class DefaultDeleter 5852a38012Sejakowatz { 5952a38012Sejakowatz public: 608b04ffc1Sbeveloper ~DefaultDeleter() 616396865dSbeveloper { 626396865dSbeveloper if (BMediaRoster::_sDefault) { 636396865dSbeveloper BMediaRoster::_sDefault->Lock(); 646396865dSbeveloper BMediaRoster::_sDefault->Quit(); 656396865dSbeveloper } 666396865dSbeveloper } 678b04ffc1Sbeveloper }; 6852a38012Sejakowatz 698b04ffc1Sbeveloper } } // BPrivate::media 708b04ffc1Sbeveloper using namespace BPrivate::media; 7152a38012Sejakowatz 728b04ffc1Sbeveloper // DefaultDeleter will delete the BMediaRoster object in it's destructor. 738b04ffc1Sbeveloper DefaultDeleter _deleter; 7452a38012Sejakowatz 753620737cSbeveloper status_t 7654187cc6Sbeveloper BMediaRosterEx::SaveNodeConfiguration(BMediaNode *node) 7754187cc6Sbeveloper { 7854187cc6Sbeveloper BMediaAddOn *addon; 7954187cc6Sbeveloper media_addon_id addonid; 8054187cc6Sbeveloper int32 flavorid; 8154187cc6Sbeveloper addon = node->AddOn(&flavorid); 8254187cc6Sbeveloper if (!addon) { 8360f15390Sbeveloper // XXX this check incorrectly triggers on BeOS R5 BT848 node 8460f15390Sbeveloper FATAL("BMediaRosterEx::SaveNodeConfiguration node %ld not instantiated from BMediaAddOn!\n", node->ID()); 8554187cc6Sbeveloper return B_ERROR; 8654187cc6Sbeveloper } 8754187cc6Sbeveloper addonid = addon->AddonID(); 8854187cc6Sbeveloper 8954187cc6Sbeveloper // XXX fix this 9054187cc6Sbeveloper printf("### BMediaRosterEx::SaveNodeConfiguration should save addon-id %ld, flavor-id %ld config NOW!\n", addonid, flavorid); 9154187cc6Sbeveloper return B_OK; 9254187cc6Sbeveloper } 9354187cc6Sbeveloper 9454187cc6Sbeveloper status_t 9554187cc6Sbeveloper BMediaRosterEx::LoadNodeConfiguration(media_addon_id addonid, int32 flavorid, BMessage *out_msg) 9654187cc6Sbeveloper { 9754187cc6Sbeveloper // XXX fix this 9854187cc6Sbeveloper out_msg->MakeEmpty(); // to be fully R5 compliant 9954187cc6Sbeveloper printf("### BMediaRosterEx::LoadNodeConfiguration should load addon-id %ld, flavor-id %ld config NOW!\n", addonid, flavorid); 10054187cc6Sbeveloper return B_OK; 10154187cc6Sbeveloper } 10254187cc6Sbeveloper 10354187cc6Sbeveloper status_t 10473794717Sbeveloper BMediaRosterEx::IncrementAddonFlavorInstancesCount(media_addon_id addonid, int32 flavorid) 10554187cc6Sbeveloper { 10673794717Sbeveloper server_change_addon_flavor_instances_count_request request; 10773794717Sbeveloper server_change_addon_flavor_instances_count_reply reply; 10873794717Sbeveloper 10973794717Sbeveloper request.addonid = addonid; 11073794717Sbeveloper request.flavorid = flavorid; 11173794717Sbeveloper request.delta = 1; 11273794717Sbeveloper request.team = team; 11373794717Sbeveloper return QueryServer(SERVER_CHANGE_ADDON_FLAVOR_INSTANCES_COUNT, &request, sizeof(request), &reply, sizeof(reply)); 11454187cc6Sbeveloper } 11554187cc6Sbeveloper 11654187cc6Sbeveloper status_t 11773794717Sbeveloper BMediaRosterEx::DecrementAddonFlavorInstancesCount(media_addon_id addonid, int32 flavorid) 11854187cc6Sbeveloper { 11973794717Sbeveloper server_change_addon_flavor_instances_count_request request; 12073794717Sbeveloper server_change_addon_flavor_instances_count_reply reply; 12173794717Sbeveloper 12273794717Sbeveloper request.addonid = addonid; 12373794717Sbeveloper request.flavorid = flavorid; 12473794717Sbeveloper request.delta = -1; 12573794717Sbeveloper request.team = team; 12673794717Sbeveloper return QueryServer(SERVER_CHANGE_ADDON_FLAVOR_INSTANCES_COUNT, &request, sizeof(request), &reply, sizeof(reply)); 12754187cc6Sbeveloper } 12854187cc6Sbeveloper 12954187cc6Sbeveloper status_t 13054187cc6Sbeveloper BMediaRosterEx::SetNodeCreator(media_node_id node, team_id creator) 13154187cc6Sbeveloper { 13254187cc6Sbeveloper server_set_node_creator_request request; 13354187cc6Sbeveloper server_set_node_creator_reply reply; 13454187cc6Sbeveloper 13554187cc6Sbeveloper request.node = node; 13654187cc6Sbeveloper request.creator = creator; 13754187cc6Sbeveloper return QueryServer(SERVER_SET_NODE_CREATOR, &request, sizeof(request), &reply, sizeof(reply)); 13854187cc6Sbeveloper } 13954187cc6Sbeveloper 14054187cc6Sbeveloper status_t 1418b04ffc1Sbeveloper BMediaRosterEx::GetNode(node_type type, media_node * out_node, int32 * out_input_id, BString * out_input_name) 14252a38012Sejakowatz { 14352a38012Sejakowatz if (out_node == NULL) 14452a38012Sejakowatz return B_BAD_VALUE; 14552a38012Sejakowatz 1468c6a6096Sbeveloper server_get_node_request request; 1478c6a6096Sbeveloper server_get_node_reply reply; 14852a38012Sejakowatz status_t rv; 14952a38012Sejakowatz 1508c6a6096Sbeveloper request.type = type; 1519e9417d2Sbeveloper request.team = team; 1528c6a6096Sbeveloper rv = QueryServer(SERVER_GET_NODE, &request, sizeof(request), &reply, sizeof(reply)); 1538c6a6096Sbeveloper if (rv != B_OK) 1548c6a6096Sbeveloper return rv; 15552a38012Sejakowatz 15652a38012Sejakowatz *out_node = reply.node; 15752a38012Sejakowatz if (out_input_id) 15852a38012Sejakowatz *out_input_id = reply.input_id; 15952a38012Sejakowatz if (out_input_name) 16052a38012Sejakowatz *out_input_name = reply.input_name; 1618c6a6096Sbeveloper return rv; 16252a38012Sejakowatz } 16352a38012Sejakowatz 1643620737cSbeveloper status_t 1658b04ffc1Sbeveloper BMediaRosterEx::SetNode(node_type type, const media_node *node, const dormant_node_info *info, const media_input *input) 16652a38012Sejakowatz { 1678c6a6096Sbeveloper server_set_node_request request; 1688c6a6096Sbeveloper server_set_node_reply reply; 16952a38012Sejakowatz 1708c6a6096Sbeveloper request.type = type; 1718c6a6096Sbeveloper request.use_node = node ? true : false; 17252a38012Sejakowatz if (node) 1738c6a6096Sbeveloper request.node = *node; 1748c6a6096Sbeveloper request.use_dni = info ? true : false; 17552a38012Sejakowatz if (info) 1768c6a6096Sbeveloper request.dni = *info; 1778c6a6096Sbeveloper request.use_input = input ? true : false; 17852a38012Sejakowatz if (input) 1798c6a6096Sbeveloper request.input = *input; 18052a38012Sejakowatz 1818c6a6096Sbeveloper return QueryServer(SERVER_SET_NODE, &request, sizeof(request), &reply, sizeof(reply)); 18252a38012Sejakowatz } 18352a38012Sejakowatz 1843620737cSbeveloper status_t 1858b04ffc1Sbeveloper BMediaRosterEx::GetAllOutputs(const media_node & node, List<media_output> *list) 1863620737cSbeveloper { 1873620737cSbeveloper int32 cookie; 1883620737cSbeveloper status_t rv; 1893620737cSbeveloper status_t result; 1903620737cSbeveloper 1913620737cSbeveloper result = B_OK; 1923620737cSbeveloper cookie = 0; 19376669a29Sbeveloper list->MakeEmpty(); 1943620737cSbeveloper for (;;) { 1953620737cSbeveloper producer_get_next_output_request request; 1963620737cSbeveloper producer_get_next_output_reply reply; 1973620737cSbeveloper request.cookie = cookie; 1980caff283Sbeveloper rv = QueryPort(node.port, PRODUCER_GET_NEXT_OUTPUT, &request, sizeof(request), &reply, sizeof(reply)); 1993620737cSbeveloper if (rv != B_OK) 2003620737cSbeveloper break; 2013620737cSbeveloper cookie = reply.cookie; 20276669a29Sbeveloper if (!list->Insert(reply.output)) { 20376669a29Sbeveloper FATAL("GetAllOutputs: list->Insert failed\n"); 2043620737cSbeveloper result = B_ERROR; 2053620737cSbeveloper } 2063620737cSbeveloper } 2073620737cSbeveloper 2083620737cSbeveloper producer_dispose_output_cookie_request request; 2093620737cSbeveloper producer_dispose_output_cookie_reply reply; 2100caff283Sbeveloper QueryPort(node.port, PRODUCER_DISPOSE_OUTPUT_COOKIE, &request, sizeof(request), &reply, sizeof(reply)); 2113620737cSbeveloper 2123620737cSbeveloper return result; 2133620737cSbeveloper } 2143620737cSbeveloper 2153620737cSbeveloper status_t 2168b04ffc1Sbeveloper BMediaRosterEx::GetAllInputs(const media_node & node, List<media_input> *list) 2173620737cSbeveloper { 2183620737cSbeveloper int32 cookie; 2193620737cSbeveloper status_t rv; 2203620737cSbeveloper status_t result; 2213620737cSbeveloper 2223620737cSbeveloper result = B_OK; 2233620737cSbeveloper cookie = 0; 22476669a29Sbeveloper list->MakeEmpty(); 2253620737cSbeveloper for (;;) { 2263620737cSbeveloper consumer_get_next_input_request request; 2273620737cSbeveloper consumer_get_next_input_reply reply; 2283620737cSbeveloper request.cookie = cookie; 2290caff283Sbeveloper rv = QueryPort(node.port, CONSUMER_GET_NEXT_INPUT, &request, sizeof(request), &reply, sizeof(reply)); 2303620737cSbeveloper if (rv != B_OK) 2313620737cSbeveloper break; 2323620737cSbeveloper cookie = reply.cookie; 23376669a29Sbeveloper if (!list->Insert(reply.input)) { 23476669a29Sbeveloper FATAL("GetAllInputs: list->Insert failed\n"); 2353620737cSbeveloper result = B_ERROR; 2363620737cSbeveloper } 2373620737cSbeveloper } 2383620737cSbeveloper 2393620737cSbeveloper consumer_dispose_input_cookie_request request; 2403620737cSbeveloper consumer_dispose_input_cookie_reply reply; 2410caff283Sbeveloper QueryPort(node.port, CONSUMER_DISPOSE_INPUT_COOKIE, &request, sizeof(request), &reply, sizeof(reply)); 2423620737cSbeveloper 2433620737cSbeveloper return result; 2443620737cSbeveloper } 2453620737cSbeveloper 2463620737cSbeveloper status_t 2478b04ffc1Sbeveloper BMediaRosterEx::PublishOutputs(const media_node & node, List<media_output> *list) 2483620737cSbeveloper { 2493620737cSbeveloper server_publish_outputs_request request; 2503620737cSbeveloper server_publish_outputs_reply reply; 2513620737cSbeveloper media_output *output; 2523620737cSbeveloper media_output *outputs; 2533620737cSbeveloper int32 count; 254a7b41a96Sbeveloper status_t rv; 2553620737cSbeveloper 25676669a29Sbeveloper count = list->CountItems(); 2573620737cSbeveloper TRACE("PublishOutputs: publishing %ld\n", count); 2583620737cSbeveloper 2593620737cSbeveloper request.node = node; 2603620737cSbeveloper request.count = count; 2613620737cSbeveloper if (count > MAX_OUTPUTS) { 2623620737cSbeveloper void *start_addr; 2633620737cSbeveloper size_t size; 26440f36b03Sbeveloper size = ROUND_UP_TO_PAGE(count * sizeof(media_output)); 2653620737cSbeveloper request.area = create_area("publish outputs", &start_addr, B_ANY_ADDRESS, size, B_NO_LOCK, B_READ_AREA | B_WRITE_AREA); 2663620737cSbeveloper if (request.area < B_OK) { 267353b9f6bSbeveloper FATAL("PublishOutputs: failed to create area, %#lx\n", request.area); 2683620737cSbeveloper return (status_t)request.area; 2693620737cSbeveloper } 2703620737cSbeveloper outputs = static_cast<media_output *>(start_addr); 2713620737cSbeveloper } else { 2723620737cSbeveloper request.area = -1; 2733620737cSbeveloper outputs = request.outputs; 2743620737cSbeveloper } 27576669a29Sbeveloper TRACE("PublishOutputs: area %ld\n", request.area); 2763620737cSbeveloper 27776669a29Sbeveloper int i; 27876669a29Sbeveloper for (i = 0, list->Rewind(); list->GetNext(&output); i++) { 27976669a29Sbeveloper ASSERT(i < count); 2803620737cSbeveloper outputs[i] = *output; 2813620737cSbeveloper } 2823620737cSbeveloper 283a7b41a96Sbeveloper rv = QueryServer(SERVER_PUBLISH_OUTPUTS, &request, sizeof(request), &reply, sizeof(reply)); 284a7b41a96Sbeveloper 285a7b41a96Sbeveloper if (request.area != -1) 286a7b41a96Sbeveloper delete_area(request.area); 287a7b41a96Sbeveloper 288a7b41a96Sbeveloper return rv; 2893620737cSbeveloper } 2903620737cSbeveloper 2913620737cSbeveloper status_t 2928b04ffc1Sbeveloper BMediaRosterEx::PublishInputs(const media_node & node, List<media_input> *list) 2933620737cSbeveloper { 2943620737cSbeveloper server_publish_inputs_request request; 2953620737cSbeveloper server_publish_inputs_reply reply; 2963620737cSbeveloper media_input *input; 2973620737cSbeveloper media_input *inputs; 2983620737cSbeveloper int32 count; 299a7b41a96Sbeveloper status_t rv; 3003620737cSbeveloper 30176669a29Sbeveloper count = list->CountItems(); 3023620737cSbeveloper TRACE("PublishInputs: publishing %ld\n", count); 3033620737cSbeveloper 3043620737cSbeveloper request.node = node; 3053620737cSbeveloper request.count = count; 3063620737cSbeveloper if (count > MAX_INPUTS) { 3073620737cSbeveloper void *start_addr; 3083620737cSbeveloper size_t size; 30940f36b03Sbeveloper size = ROUND_UP_TO_PAGE(count * sizeof(media_input)); 3103620737cSbeveloper request.area = create_area("publish inputs", &start_addr, B_ANY_ADDRESS, size, B_NO_LOCK, B_READ_AREA | B_WRITE_AREA); 3113620737cSbeveloper if (request.area < B_OK) { 312353b9f6bSbeveloper FATAL("PublishInputs: failed to create area, %#lx\n", request.area); 3133620737cSbeveloper return (status_t)request.area; 3143620737cSbeveloper } 3153620737cSbeveloper inputs = static_cast<media_input *>(start_addr); 3163620737cSbeveloper } else { 3173620737cSbeveloper request.area = -1; 3183620737cSbeveloper inputs = request.inputs; 3193620737cSbeveloper } 32076669a29Sbeveloper TRACE("PublishInputs: area %ld\n", request.area); 3213620737cSbeveloper 32276669a29Sbeveloper int i; 32376669a29Sbeveloper for (i = 0, list->Rewind(); list->GetNext(&input); i++) { 32476669a29Sbeveloper ASSERT(i < count); 3253620737cSbeveloper inputs[i] = *input; 3263620737cSbeveloper } 3273620737cSbeveloper 328a7b41a96Sbeveloper rv = QueryServer(SERVER_PUBLISH_INPUTS, &request, sizeof(request), &reply, sizeof(reply)); 329a7b41a96Sbeveloper 330a7b41a96Sbeveloper if (request.area != -1) 331a7b41a96Sbeveloper delete_area(request.area); 332a7b41a96Sbeveloper 333a7b41a96Sbeveloper return rv; 3343620737cSbeveloper } 3353620737cSbeveloper 33652a38012Sejakowatz /************************************************************* 33752a38012Sejakowatz * public BMediaRoster 33852a38012Sejakowatz *************************************************************/ 33952a38012Sejakowatz 34052a38012Sejakowatz status_t 34152a38012Sejakowatz BMediaRoster::GetVideoInput(media_node * out_node) 34252a38012Sejakowatz { 34352a38012Sejakowatz CALLED(); 3448b04ffc1Sbeveloper return MediaRosterEx(this)->GetNode(VIDEO_INPUT, out_node); 34552a38012Sejakowatz } 34652a38012Sejakowatz 34752a38012Sejakowatz 34852a38012Sejakowatz status_t 34952a38012Sejakowatz BMediaRoster::GetAudioInput(media_node * out_node) 35052a38012Sejakowatz { 35152a38012Sejakowatz CALLED(); 3528b04ffc1Sbeveloper return MediaRosterEx(this)->GetNode(AUDIO_INPUT, out_node); 35352a38012Sejakowatz } 35452a38012Sejakowatz 35552a38012Sejakowatz 35652a38012Sejakowatz status_t 35752a38012Sejakowatz BMediaRoster::GetVideoOutput(media_node * out_node) 35852a38012Sejakowatz { 35952a38012Sejakowatz CALLED(); 3608b04ffc1Sbeveloper return MediaRosterEx(this)->GetNode(VIDEO_OUTPUT, out_node); 36152a38012Sejakowatz } 36252a38012Sejakowatz 36352a38012Sejakowatz 36452a38012Sejakowatz status_t 36552a38012Sejakowatz BMediaRoster::GetAudioMixer(media_node * out_node) 36652a38012Sejakowatz { 36752a38012Sejakowatz CALLED(); 3688b04ffc1Sbeveloper return MediaRosterEx(this)->GetNode(AUDIO_MIXER, out_node); 36952a38012Sejakowatz } 37052a38012Sejakowatz 37152a38012Sejakowatz 37252a38012Sejakowatz status_t 37352a38012Sejakowatz BMediaRoster::GetAudioOutput(media_node * out_node) 37452a38012Sejakowatz { 37552a38012Sejakowatz CALLED(); 3768b04ffc1Sbeveloper return MediaRosterEx(this)->GetNode(AUDIO_OUTPUT, out_node); 37752a38012Sejakowatz } 37852a38012Sejakowatz 37952a38012Sejakowatz 38052a38012Sejakowatz status_t 38152a38012Sejakowatz BMediaRoster::GetAudioOutput(media_node * out_node, 38252a38012Sejakowatz int32 * out_input_id, 38352a38012Sejakowatz BString * out_input_name) 38452a38012Sejakowatz { 38552a38012Sejakowatz CALLED(); 3868b04ffc1Sbeveloper return MediaRosterEx(this)->GetNode(AUDIO_OUTPUT_EX, out_node, out_input_id, out_input_name); 38752a38012Sejakowatz } 38852a38012Sejakowatz 38952a38012Sejakowatz 39052a38012Sejakowatz status_t 39152a38012Sejakowatz BMediaRoster::GetTimeSource(media_node * out_node) 39252a38012Sejakowatz { 39352a38012Sejakowatz CALLED(); 39486bce45bSbeveloper status_t rv; 39586bce45bSbeveloper 39686bce45bSbeveloper // XXX need to do this in a nicer way. 39786bce45bSbeveloper 39886bce45bSbeveloper rv = MediaRosterEx(this)->GetNode(TIME_SOURCE, out_node); 39986bce45bSbeveloper if (rv != B_OK) 40086bce45bSbeveloper return rv; 40186bce45bSbeveloper 40286bce45bSbeveloper // We don't do reference counting for timesources, that's why we 40386bce45bSbeveloper // release the node immediately. 40486bce45bSbeveloper ReleaseNode(*out_node); 40586bce45bSbeveloper 40686bce45bSbeveloper // we need to remember to not use this node with server side reference counting 40786bce45bSbeveloper out_node->kind |= NODE_KIND_NO_REFCOUNTING; 40886bce45bSbeveloper 40986bce45bSbeveloper return B_OK; 41052a38012Sejakowatz } 41152a38012Sejakowatz 41252a38012Sejakowatz 41352a38012Sejakowatz status_t 41452a38012Sejakowatz BMediaRoster::SetVideoInput(const media_node & producer) 41552a38012Sejakowatz { 41652a38012Sejakowatz CALLED(); 4178b04ffc1Sbeveloper return MediaRosterEx(this)->SetNode(VIDEO_INPUT, &producer); 41852a38012Sejakowatz } 41952a38012Sejakowatz 42052a38012Sejakowatz 42152a38012Sejakowatz status_t 42252a38012Sejakowatz BMediaRoster::SetVideoInput(const dormant_node_info & producer) 42352a38012Sejakowatz { 42452a38012Sejakowatz CALLED(); 4258b04ffc1Sbeveloper return MediaRosterEx(this)->SetNode(VIDEO_INPUT, NULL, &producer); 42652a38012Sejakowatz } 42752a38012Sejakowatz 42852a38012Sejakowatz 42952a38012Sejakowatz status_t 43052a38012Sejakowatz BMediaRoster::SetAudioInput(const media_node & producer) 43152a38012Sejakowatz { 43252a38012Sejakowatz CALLED(); 4338b04ffc1Sbeveloper return MediaRosterEx(this)->SetNode(AUDIO_INPUT, &producer); 43452a38012Sejakowatz } 43552a38012Sejakowatz 43652a38012Sejakowatz 43752a38012Sejakowatz status_t 43852a38012Sejakowatz BMediaRoster::SetAudioInput(const dormant_node_info & producer) 43952a38012Sejakowatz { 44052a38012Sejakowatz CALLED(); 4418b04ffc1Sbeveloper return MediaRosterEx(this)->SetNode(AUDIO_INPUT, NULL, &producer); 44252a38012Sejakowatz } 44352a38012Sejakowatz 44452a38012Sejakowatz 44552a38012Sejakowatz status_t 44652a38012Sejakowatz BMediaRoster::SetVideoOutput(const media_node & consumer) 44752a38012Sejakowatz { 44852a38012Sejakowatz CALLED(); 4498b04ffc1Sbeveloper return MediaRosterEx(this)->SetNode(VIDEO_OUTPUT, &consumer); 45052a38012Sejakowatz } 45152a38012Sejakowatz 45252a38012Sejakowatz 45352a38012Sejakowatz status_t 45452a38012Sejakowatz BMediaRoster::SetVideoOutput(const dormant_node_info & consumer) 45552a38012Sejakowatz { 45652a38012Sejakowatz CALLED(); 4578b04ffc1Sbeveloper return MediaRosterEx(this)->SetNode(VIDEO_OUTPUT, NULL, &consumer); 45852a38012Sejakowatz } 45952a38012Sejakowatz 46052a38012Sejakowatz 46152a38012Sejakowatz status_t 46252a38012Sejakowatz BMediaRoster::SetAudioOutput(const media_node & consumer) 46352a38012Sejakowatz { 46452a38012Sejakowatz CALLED(); 4658b04ffc1Sbeveloper return MediaRosterEx(this)->SetNode(AUDIO_OUTPUT, &consumer); 46652a38012Sejakowatz } 46752a38012Sejakowatz 46852a38012Sejakowatz 46952a38012Sejakowatz status_t 47052a38012Sejakowatz BMediaRoster::SetAudioOutput(const media_input & input_to_output) 47152a38012Sejakowatz { 47252a38012Sejakowatz CALLED(); 4738b04ffc1Sbeveloper return MediaRosterEx(this)->SetNode(AUDIO_OUTPUT, NULL, NULL, &input_to_output); 47452a38012Sejakowatz } 47552a38012Sejakowatz 47652a38012Sejakowatz 47752a38012Sejakowatz status_t 47852a38012Sejakowatz BMediaRoster::SetAudioOutput(const dormant_node_info & consumer) 47952a38012Sejakowatz { 48052a38012Sejakowatz CALLED(); 4818b04ffc1Sbeveloper return MediaRosterEx(this)->SetNode(AUDIO_OUTPUT, NULL, &consumer); 48252a38012Sejakowatz } 48352a38012Sejakowatz 48452a38012Sejakowatz 48552a38012Sejakowatz status_t 48652a38012Sejakowatz BMediaRoster::GetNodeFor(media_node_id node, 48752a38012Sejakowatz media_node * clone) 48852a38012Sejakowatz { 4899e9417d2Sbeveloper CALLED(); 4909e9417d2Sbeveloper if (clone == NULL) 4919e9417d2Sbeveloper return B_BAD_VALUE; 4929e9417d2Sbeveloper if (node <= 0) 4939e9417d2Sbeveloper return B_MEDIA_BAD_NODE; 4949e9417d2Sbeveloper 4959e9417d2Sbeveloper server_get_node_for_request request; 4969e9417d2Sbeveloper server_get_node_for_reply reply; 4979e9417d2Sbeveloper status_t rv; 4989e9417d2Sbeveloper 4999e9417d2Sbeveloper request.nodeid = node; 5009e9417d2Sbeveloper request.team = team; 5019e9417d2Sbeveloper 5029e9417d2Sbeveloper rv = QueryServer(SERVER_GET_NODE_FOR, &request, sizeof(request), &reply, sizeof(reply)); 5039e9417d2Sbeveloper if (rv != B_OK) 5049e9417d2Sbeveloper return rv; 5059e9417d2Sbeveloper 5069e9417d2Sbeveloper *clone = reply.clone; 5079e9417d2Sbeveloper return B_OK; 50852a38012Sejakowatz } 50952a38012Sejakowatz 51052a38012Sejakowatz 51152a38012Sejakowatz status_t 51252a38012Sejakowatz BMediaRoster::GetSystemTimeSource(media_node * clone) 51352a38012Sejakowatz { 51452a38012Sejakowatz CALLED(); 51586bce45bSbeveloper status_t rv; 51686bce45bSbeveloper 51786bce45bSbeveloper // XXX need to do this in a nicer way. 51886bce45bSbeveloper 51986bce45bSbeveloper rv = MediaRosterEx(this)->GetNode(SYSTEM_TIME_SOURCE, clone); 52086bce45bSbeveloper if (rv != B_OK) 52186bce45bSbeveloper return rv; 52286bce45bSbeveloper 52386bce45bSbeveloper // We don't do reference counting for timesources, that's why we 52486bce45bSbeveloper // release the node immediately. 52586bce45bSbeveloper ReleaseNode(*clone); 52686bce45bSbeveloper 52786bce45bSbeveloper // we need to remember to not use this node with server side reference counting 52886bce45bSbeveloper clone->kind |= NODE_KIND_NO_REFCOUNTING; 52986bce45bSbeveloper 53086bce45bSbeveloper return B_OK; 53152a38012Sejakowatz } 53252a38012Sejakowatz 53352a38012Sejakowatz 53452a38012Sejakowatz status_t 53552a38012Sejakowatz BMediaRoster::ReleaseNode(const media_node & node) 53652a38012Sejakowatz { 5379e9417d2Sbeveloper CALLED(); 53840f36b03Sbeveloper if (IS_INVALID_NODE(node)) 5399e9417d2Sbeveloper return B_MEDIA_BAD_NODE; 54052a38012Sejakowatz 54186bce45bSbeveloper if (node.kind & NODE_KIND_NO_REFCOUNTING) { 54286bce45bSbeveloper printf("BMediaRoster::ReleaseNode, trying to release reference counting disabled timesource, node %ld, port %ld, team %ld\n", node.node, node.port, team); 54386bce45bSbeveloper return B_OK; 54486bce45bSbeveloper } 54586bce45bSbeveloper 5469e9417d2Sbeveloper server_release_node_request request; 5479e9417d2Sbeveloper server_release_node_reply reply; 548cf4e2277Sbeveloper status_t rv; 5499e9417d2Sbeveloper 5509e9417d2Sbeveloper request.node = node; 5519e9417d2Sbeveloper request.team = team; 5529e9417d2Sbeveloper 55360f15390Sbeveloper TRACE("BMediaRoster::ReleaseNode, node %ld, port %ld, team %ld\n", node.node, node.port, team); 554cf4e2277Sbeveloper 555cf4e2277Sbeveloper rv = QueryServer(SERVER_RELEASE_NODE, &request, sizeof(request), &reply, sizeof(reply)); 556cf4e2277Sbeveloper if (rv != B_OK) { 557cf4e2277Sbeveloper FATAL("BMediaRoster::ReleaseNode FAILED, node %ld, port %ld, team %ld!\n", node.node, node.port, team); 558cf4e2277Sbeveloper } 559cf4e2277Sbeveloper return rv; 5609e9417d2Sbeveloper } 56152a38012Sejakowatz 56252a38012Sejakowatz BTimeSource * 56352a38012Sejakowatz BMediaRoster::MakeTimeSourceFor(const media_node & for_node) 56452a38012Sejakowatz { 565835140c8Sbeveloper CALLED(); 566287f7492Sbeveloper 5670e21b167Sbeveloper BTimeSource *source; 568287f7492Sbeveloper 56960f15390Sbeveloper TRACE("BMediaRoster::MakeTimeSourceFor enter, node %ld, port %ld, kind %#lx\n", for_node.node, for_node.port, for_node.kind); 570287f7492Sbeveloper 5710e21b167Sbeveloper if (0 == (for_node.kind & B_TIME_SOURCE)) { 57260f15390Sbeveloper //FATAL("BMediaRoster::MakeTimeSourceFor, node %ld is not a timesource!\n", for_node.node); 5730e21b167Sbeveloper // XXX It appears that Cortex calls this function on every node, and expects 5740e21b167Sbeveloper // XXX to be returned a system time source if the for_node is not a timesource 5750e21b167Sbeveloper media_node clone; 5760e21b167Sbeveloper GetSystemTimeSource(&clone); 5770e21b167Sbeveloper source = _TimeSourceObjectManager->GetTimeSource(clone); 57886bce45bSbeveloper // ReleaseNode(clone); 5790e21b167Sbeveloper } else { 5800e21b167Sbeveloper source = _TimeSourceObjectManager->GetTimeSource(for_node); 5810e21b167Sbeveloper } 5820e21b167Sbeveloper 58360f15390Sbeveloper TRACE("BMediaRoster::MakeTimeSourceFor leave, node %ld, port %ld, kind %#lx\n", source->Node().node, source->Node().port, source->Node().kind); 584287f7492Sbeveloper 585835140c8Sbeveloper return source; 58652a38012Sejakowatz } 58752a38012Sejakowatz 58852a38012Sejakowatz 58952a38012Sejakowatz status_t 59052a38012Sejakowatz BMediaRoster::Connect(const media_source & from, 59152a38012Sejakowatz const media_destination & to, 59252a38012Sejakowatz media_format * io_format, 59352a38012Sejakowatz media_output * out_output, 59452a38012Sejakowatz media_input * out_input) 59552a38012Sejakowatz { 596eae26d3dSbeveloper return BMediaRoster::Connect(from, to, io_format, out_output, out_input, 0); 597eae26d3dSbeveloper } 598eae26d3dSbeveloper 599eae26d3dSbeveloper 600eae26d3dSbeveloper status_t 601eae26d3dSbeveloper BMediaRoster::Connect(const media_source & from, 602eae26d3dSbeveloper const media_destination & to, 603eae26d3dSbeveloper media_format * io_format, 604eae26d3dSbeveloper media_output * out_output, 605eae26d3dSbeveloper media_input * out_input, 606eae26d3dSbeveloper uint32 in_flags, 607eae26d3dSbeveloper void * _reserved) 608eae26d3dSbeveloper { 60952a38012Sejakowatz CALLED(); 61052a38012Sejakowatz if (io_format == NULL || out_output == NULL || out_input == NULL) 61152a38012Sejakowatz return B_BAD_VALUE; 61240f36b03Sbeveloper if (IS_INVALID_SOURCE(from)) { 613353b9f6bSbeveloper FATAL("BMediaRoster::Connect: media_source invalid\n"); 61452a38012Sejakowatz return B_MEDIA_BAD_SOURCE; 6159e9417d2Sbeveloper } 61640f36b03Sbeveloper if (IS_INVALID_DESTINATION(to)) { 617353b9f6bSbeveloper FATAL("BMediaRoster::Connect: media_destination invalid\n"); 61852a38012Sejakowatz return B_MEDIA_BAD_DESTINATION; 6199e9417d2Sbeveloper } 62052a38012Sejakowatz 62152a38012Sejakowatz status_t rv; 6228c6a6096Sbeveloper producer_format_proposal_request request1; 6238c6a6096Sbeveloper producer_format_proposal_reply reply1; 62452a38012Sejakowatz 62552a38012Sejakowatz // BBufferProducer::FormatProposal 6268c6a6096Sbeveloper request1.output = from; 6278c6a6096Sbeveloper request1.format = *io_format; 6288c6a6096Sbeveloper rv = QueryPort(from.port, PRODUCER_FORMAT_PROPOSAL, &request1, sizeof(request1), &reply1, sizeof(reply1)); 6298c6a6096Sbeveloper if (rv != B_OK) { 630353b9f6bSbeveloper FATAL("BMediaRoster::Connect: aborted after BBufferProducer::FormatProposal, status = %#lx\n",rv); 63152a38012Sejakowatz return rv; 63252a38012Sejakowatz } 6338c6a6096Sbeveloper // reply1.format now contains the format proposed by the producer 6348c6a6096Sbeveloper 6358c6a6096Sbeveloper consumer_accept_format_request request2; 6368c6a6096Sbeveloper consumer_accept_format_reply reply2; 6378c6a6096Sbeveloper 6388c6a6096Sbeveloper // BBufferConsumer::AcceptFormat 6398c6a6096Sbeveloper request2.dest = to; 6408c6a6096Sbeveloper request2.format = reply1.format; 6418c6a6096Sbeveloper rv = QueryPort(to.port, CONSUMER_ACCEPT_FORMAT, &request2, sizeof(request2), &reply2, sizeof(reply2)); 6428c6a6096Sbeveloper if (rv != B_OK) { 643353b9f6bSbeveloper FATAL("BMediaRoster::Connect: aborted after BBufferConsumer::AcceptFormat, status = %#lx\n",rv); 6448c6a6096Sbeveloper return rv; 6458c6a6096Sbeveloper } 6468c6a6096Sbeveloper // reply2.format now contains the format accepted by the consumer 6478c6a6096Sbeveloper 6488c6a6096Sbeveloper // BBufferProducer::PrepareToConnect 6498c6a6096Sbeveloper producer_prepare_to_connect_request request3; 6508c6a6096Sbeveloper producer_prepare_to_connect_reply reply3; 6518c6a6096Sbeveloper 6528c6a6096Sbeveloper request3.source = from; 6538c6a6096Sbeveloper request3.destination = to; 6548c6a6096Sbeveloper request3.format = reply2.format; 6558c6a6096Sbeveloper strcpy(request3.name, "XXX some default name"); // XXX fix this 6568c6a6096Sbeveloper rv = QueryPort(from.port, PRODUCER_PREPARE_TO_CONNECT, &request3, sizeof(request3), &reply3, sizeof(reply3)); 6578c6a6096Sbeveloper if (rv != B_OK) { 658353b9f6bSbeveloper FATAL("BMediaRoster::Connect: aborted after BBufferProducer::PrepareToConnect, status = %#lx\n",rv); 6598c6a6096Sbeveloper return rv; 6608c6a6096Sbeveloper } 6618c6a6096Sbeveloper // reply3.format is still our pretty media format 6628c6a6096Sbeveloper // reply3.out_source the real source to be used for the connection 6638c6a6096Sbeveloper // reply3.name the name BBufferConsumer::Connected will see in the outInput->name argument 6648c6a6096Sbeveloper 6658c6a6096Sbeveloper // BBufferConsumer::Connected 6668c6a6096Sbeveloper consumer_connected_request request4; 6678c6a6096Sbeveloper consumer_connected_reply reply4; 6688c6a6096Sbeveloper status_t con_status; 6698c6a6096Sbeveloper 6708c6a6096Sbeveloper request4.producer = reply3.out_source; 6718c6a6096Sbeveloper request4.where = to; 6728c6a6096Sbeveloper request4.with_format = reply3.format; 6738c6a6096Sbeveloper con_status = QueryPort(to.port, CONSUMER_CONNECTED, &request4, sizeof(request4), &reply4, sizeof(reply4)); 6748c6a6096Sbeveloper if (con_status != B_OK) { 675353b9f6bSbeveloper FATAL("BMediaRoster::Connect: aborting after BBufferConsumer::Connected, status = %#lx\n",con_status); 6768c6a6096Sbeveloper // we do NOT return here! 6778c6a6096Sbeveloper } 6788c6a6096Sbeveloper // con_status contains the status code to be supplied to BBufferProducer::Connect's status argument 6798c6a6096Sbeveloper // reply4.input contains the media_input that describes the connection from the consumer point of view 6808c6a6096Sbeveloper 6818c6a6096Sbeveloper // BBufferProducer::Connect 6828c6a6096Sbeveloper producer_connect_request request5; 6838c6a6096Sbeveloper producer_connect_reply reply5; 6848c6a6096Sbeveloper 6858c6a6096Sbeveloper request5.error = con_status; 6868c6a6096Sbeveloper request5.source = reply3.out_source; 6878c6a6096Sbeveloper request5.destination = reply4.input.destination; 6888c6a6096Sbeveloper request5.format = reply3.format; // XXX reply4.input.format ??? 6898c6a6096Sbeveloper strcpy(request5.name, reply4.input.name); 6900caff283Sbeveloper rv = QueryPort(reply4.input.source.port, PRODUCER_CONNECT, &request5, sizeof(request5), &reply5, sizeof(reply5)); 6918c6a6096Sbeveloper if (con_status != B_OK) { 692353b9f6bSbeveloper FATAL("BMediaRoster::Connect: aborted\n"); 6938c6a6096Sbeveloper return con_status; 6948c6a6096Sbeveloper } 6958c6a6096Sbeveloper if (rv != B_OK) { 696353b9f6bSbeveloper FATAL("BMediaRoster::Connect: aborted after BBufferProducer::Connect, status = %#lx\n",rv); 6978c6a6096Sbeveloper return rv; 6988c6a6096Sbeveloper } 6998c6a6096Sbeveloper // reply5.name contains the name assigned to the connection by the producer 7008c6a6096Sbeveloper 7018c6a6096Sbeveloper // find the output node 7028c6a6096Sbeveloper // XXX isn't there a easier way? 7038c6a6096Sbeveloper media_node sourcenode; 7048c6a6096Sbeveloper GetNodeFor(NodeIDFor(from.port), &sourcenode); 7058c6a6096Sbeveloper ReleaseNode(sourcenode); 7068c6a6096Sbeveloper 7078c6a6096Sbeveloper // initilize connection info 7088c6a6096Sbeveloper *io_format = reply3.format; 7098c6a6096Sbeveloper *out_input = reply4.input; 7108c6a6096Sbeveloper out_output->node = sourcenode; 7118c6a6096Sbeveloper out_output->source = reply4.input.source; 7128c6a6096Sbeveloper out_output->destination = reply4.input.destination; 7138c6a6096Sbeveloper out_output->format = reply4.input.format; 7148c6a6096Sbeveloper strcpy(out_output->name, reply5.name); 7158c6a6096Sbeveloper 7168c6a6096Sbeveloper // the connection is now made 7178c6a6096Sbeveloper 7188c6a6096Sbeveloper 7198c6a6096Sbeveloper // XXX register connection with server 7209e9417d2Sbeveloper // XXX we should just send a notification, instead of republishing all endpoints 72176669a29Sbeveloper List<media_output> outlist; 72276669a29Sbeveloper List<media_input> inlist; 7238b04ffc1Sbeveloper if (B_OK == MediaRosterEx(this)->GetAllOutputs(out_output->node , &outlist)) 7248b04ffc1Sbeveloper MediaRosterEx(this)->PublishOutputs(out_output->node , &outlist); 7258b04ffc1Sbeveloper if (B_OK == MediaRosterEx(this)->GetAllInputs(out_input->node , &inlist)) 7268b04ffc1Sbeveloper MediaRosterEx(this)->PublishInputs(out_input->node, &inlist); 7278c6a6096Sbeveloper 7288c6a6096Sbeveloper 7298c6a6096Sbeveloper // XXX if (mute) BBufferProducer::EnableOutput(false) 7309e9417d2Sbeveloper if (in_flags & B_CONNECT_MUTED) { 7319e9417d2Sbeveloper } 7328c6a6096Sbeveloper 7338c6a6096Sbeveloper 7349e9417d2Sbeveloper // send a notification 7359e9417d2Sbeveloper BPrivate::media::notifications::ConnectionMade(*out_input, *out_output, *io_format); 7369e9417d2Sbeveloper 7378c6a6096Sbeveloper return B_OK; 7388c6a6096Sbeveloper }; 73952a38012Sejakowatz 74052a38012Sejakowatz 74152a38012Sejakowatz status_t 7429e9417d2Sbeveloper BMediaRoster::Disconnect(media_node_id source_nodeid, 74352a38012Sejakowatz const media_source & source, 7449e9417d2Sbeveloper media_node_id destination_nodeid, 74552a38012Sejakowatz const media_destination & destination) 74652a38012Sejakowatz { 7479e9417d2Sbeveloper CALLED(); 74840f36b03Sbeveloper if (IS_INVALID_NODEID(source_nodeid)) { 749353b9f6bSbeveloper FATAL("BMediaRoster::Disconnect: source media_node_id invalid\n"); 7509e9417d2Sbeveloper return B_MEDIA_BAD_SOURCE; 7519e9417d2Sbeveloper } 75240f36b03Sbeveloper if (IS_INVALID_NODEID(destination_nodeid)) { 75340f36b03Sbeveloper FATAL("BMediaRoster::Disconnect: destination media_node_id invalid\n"); 7549e9417d2Sbeveloper return B_MEDIA_BAD_DESTINATION; 7559e9417d2Sbeveloper } 75640f36b03Sbeveloper if (IS_INVALID_SOURCE(source)) { 757353b9f6bSbeveloper FATAL("BMediaRoster::Disconnect: media_source invalid\n"); 7589e9417d2Sbeveloper return B_MEDIA_BAD_SOURCE; 7599e9417d2Sbeveloper } 76040f36b03Sbeveloper if (IS_INVALID_DESTINATION(destination)) { 761353b9f6bSbeveloper FATAL("BMediaRoster::Disconnect: media_destination invalid\n"); 7629e9417d2Sbeveloper return B_MEDIA_BAD_DESTINATION; 7639e9417d2Sbeveloper } 7649e9417d2Sbeveloper 7659e9417d2Sbeveloper producer_disconnect_request request2; 7669e9417d2Sbeveloper producer_disconnect_reply reply2; 7679e9417d2Sbeveloper consumer_disconnected_request request1; 7689e9417d2Sbeveloper consumer_disconnected_reply reply1; 7699e9417d2Sbeveloper status_t rv1, rv2; 7709e9417d2Sbeveloper 7719e9417d2Sbeveloper // XXX we should ask the server if this connection really exists 7729e9417d2Sbeveloper 7739e9417d2Sbeveloper request1.source = source; 7749e9417d2Sbeveloper request1.destination = destination; 7759e9417d2Sbeveloper request2.source = source; 7769e9417d2Sbeveloper request2.destination = destination; 7779e9417d2Sbeveloper 7789e9417d2Sbeveloper rv1 = QueryPort(source.port, PRODUCER_DISCONNECT, &request1, sizeof(request1), &reply1, sizeof(reply1)); 7799e9417d2Sbeveloper rv2 = QueryPort(destination.port, CONSUMER_DISCONNECTED, &request2, sizeof(request2), &reply2, sizeof(reply2)); 7809e9417d2Sbeveloper 7819e9417d2Sbeveloper // XXX unregister connection with server 7829e9417d2Sbeveloper // XXX we should just send a notification, instead of republishing all endpoints 78376669a29Sbeveloper List<media_output> outlist; 78476669a29Sbeveloper List<media_input> inlist; 7859e9417d2Sbeveloper media_node sourcenode; 7869e9417d2Sbeveloper media_node destnode; 7879e9417d2Sbeveloper if (B_OK == GetNodeFor(source_nodeid, &sourcenode)) { 7888b04ffc1Sbeveloper if (B_OK == MediaRosterEx(this)->GetAllOutputs(sourcenode , &outlist)) 7898b04ffc1Sbeveloper MediaRosterEx(this)->PublishOutputs(sourcenode , &outlist); 7909e9417d2Sbeveloper ReleaseNode(sourcenode); 791353b9f6bSbeveloper } else FATAL("BMediaRoster::Disconnect: source GetNodeFor failed\n"); 7929e9417d2Sbeveloper if (B_OK == GetNodeFor(destination_nodeid, &destnode)) { 7938b04ffc1Sbeveloper if (B_OK == MediaRosterEx(this)->GetAllInputs(destnode , &inlist)) 7948b04ffc1Sbeveloper MediaRosterEx(this)->PublishInputs(destnode, &inlist); 7959e9417d2Sbeveloper ReleaseNode(destnode); 796353b9f6bSbeveloper } else FATAL("BMediaRoster::Disconnect: dest GetNodeFor failed\n"); 7979e9417d2Sbeveloper 7989e9417d2Sbeveloper 7999e9417d2Sbeveloper // send a notification 8009e9417d2Sbeveloper BPrivate::media::notifications::ConnectionBroken(source, destination); 8019e9417d2Sbeveloper 8029e9417d2Sbeveloper return (rv1 != B_OK || rv2 != B_OK) ? B_ERROR : B_OK; 80352a38012Sejakowatz } 80452a38012Sejakowatz 80552a38012Sejakowatz 80652a38012Sejakowatz status_t 80752a38012Sejakowatz BMediaRoster::StartNode(const media_node & node, 80852a38012Sejakowatz bigtime_t at_performance_time) 80952a38012Sejakowatz { 81052a38012Sejakowatz CALLED(); 8119e9417d2Sbeveloper if (node.node <= 0) 81252a38012Sejakowatz return B_MEDIA_BAD_NODE; 81352a38012Sejakowatz 81460f15390Sbeveloper TRACE("BMediaRoster::StartNode, node %ld, at perf %Ld\n", node.node, at_performance_time); 8150e21b167Sbeveloper 8166396865dSbeveloper node_start_command command; 8176396865dSbeveloper command.performance_time = at_performance_time; 81852a38012Sejakowatz 8196396865dSbeveloper return SendToPort(node.port, NODE_START, &command, sizeof(command)); 82052a38012Sejakowatz } 82152a38012Sejakowatz 82252a38012Sejakowatz 82352a38012Sejakowatz status_t 82452a38012Sejakowatz BMediaRoster::StopNode(const media_node & node, 82552a38012Sejakowatz bigtime_t at_performance_time, 82652a38012Sejakowatz bool immediate) 82752a38012Sejakowatz { 82852a38012Sejakowatz CALLED(); 82940f36b03Sbeveloper if (IS_INVALID_NODE(node)) 83052a38012Sejakowatz return B_MEDIA_BAD_NODE; 83152a38012Sejakowatz 83260f15390Sbeveloper TRACE("BMediaRoster::StopNode, node %ld, at perf %Ld %s\n", node.node, at_performance_time, immediate ? "NOW" : ""); 8330e21b167Sbeveloper 8346396865dSbeveloper node_stop_command command; 8356396865dSbeveloper command.performance_time = at_performance_time; 8366396865dSbeveloper command.immediate = immediate; 83752a38012Sejakowatz 8386396865dSbeveloper return SendToPort(node.port, NODE_STOP, &command, sizeof(command)); 83952a38012Sejakowatz } 84052a38012Sejakowatz 84152a38012Sejakowatz 84252a38012Sejakowatz status_t 84352a38012Sejakowatz BMediaRoster::SeekNode(const media_node & node, 84452a38012Sejakowatz bigtime_t to_media_time, 84552a38012Sejakowatz bigtime_t at_performance_time) 84652a38012Sejakowatz { 84752a38012Sejakowatz CALLED(); 84840f36b03Sbeveloper if (IS_INVALID_NODE(node)) 84952a38012Sejakowatz return B_MEDIA_BAD_NODE; 85052a38012Sejakowatz 85160f15390Sbeveloper TRACE("BMediaRoster::SeekNode, node %ld, at perf %Ld, to perf %Ld\n", node.node, at_performance_time, to_media_time); 8520e21b167Sbeveloper 8536396865dSbeveloper node_seek_command command; 8546396865dSbeveloper command.media_time = to_media_time; 8556396865dSbeveloper command.performance_time = at_performance_time; 85652a38012Sejakowatz 8576396865dSbeveloper return SendToPort(node.port, NODE_SEEK, &command, sizeof(command)); 85852a38012Sejakowatz } 85952a38012Sejakowatz 86052a38012Sejakowatz 86152a38012Sejakowatz status_t 86252a38012Sejakowatz BMediaRoster::StartTimeSource(const media_node & node, 86352a38012Sejakowatz bigtime_t at_real_time) 86452a38012Sejakowatz { 86552a38012Sejakowatz CALLED(); 86660f15390Sbeveloper if (IS_SYSTEM_TIMESOURCE(node)) { 86760f15390Sbeveloper // XXX debug this 86860f15390Sbeveloper //FATAL("BMediaRoster::StartTimeSource node %ld is system timesource\n", node.node); 86960f15390Sbeveloper return B_OK; 87060f15390Sbeveloper } 87160f15390Sbeveloper if (IS_SHADOW_TIMESOURCE(node)) { 87260f15390Sbeveloper // XXX debug this 87360f15390Sbeveloper FATAL("BMediaRoster::StartTimeSource node %ld is shadow timesource\n", node.node); 87460f15390Sbeveloper return B_OK; 87560f15390Sbeveloper } 87640f36b03Sbeveloper if (IS_INVALID_NODE(node)) { 87760f15390Sbeveloper FATAL("BMediaRoster::StartTimeSource node %ld invalid\n", node.node); 87852a38012Sejakowatz return B_MEDIA_BAD_NODE; 8790e21b167Sbeveloper } 8800e21b167Sbeveloper if ((node.kind & B_TIME_SOURCE) == 0) { 88160f15390Sbeveloper FATAL("BMediaRoster::StartTimeSource node %ld is no timesource\n", node.node); 88252a38012Sejakowatz return B_MEDIA_BAD_NODE; 8830e21b167Sbeveloper } 8840e21b167Sbeveloper 88560f15390Sbeveloper TRACE("BMediaRoster::StartTimeSource, node %ld, at real %Ld\n", node.node, at_real_time); 88652a38012Sejakowatz 88752a38012Sejakowatz BTimeSource::time_source_op_info msg; 88852a38012Sejakowatz msg.op = BTimeSource::B_TIMESOURCE_START; 88952a38012Sejakowatz msg.real_time = at_real_time; 89052a38012Sejakowatz 89152a38012Sejakowatz return write_port(node.port, TIMESOURCE_OP, &msg, sizeof(msg)); 89252a38012Sejakowatz } 89352a38012Sejakowatz 89452a38012Sejakowatz 89552a38012Sejakowatz status_t 89652a38012Sejakowatz BMediaRoster::StopTimeSource(const media_node & node, 89752a38012Sejakowatz bigtime_t at_real_time, 89852a38012Sejakowatz bool immediate) 89952a38012Sejakowatz { 90052a38012Sejakowatz CALLED(); 90160f15390Sbeveloper if (IS_SYSTEM_TIMESOURCE(node)) { 90260f15390Sbeveloper // XXX debug this 90360f15390Sbeveloper //FATAL("BMediaRoster::StopTimeSource node %ld is system timesource\n", node.node); 90460f15390Sbeveloper return B_OK; 90560f15390Sbeveloper } 90660f15390Sbeveloper if (IS_SHADOW_TIMESOURCE(node)) { 90760f15390Sbeveloper // XXX debug this 90860f15390Sbeveloper FATAL("BMediaRoster::StopTimeSource node %ld is shadow timesource\n", node.node); 90960f15390Sbeveloper return B_OK; 91060f15390Sbeveloper } 91140f36b03Sbeveloper if (IS_INVALID_NODE(node)) { 91260f15390Sbeveloper FATAL("BMediaRoster::StopTimeSource node %ld invalid\n", node.node); 91352a38012Sejakowatz return B_MEDIA_BAD_NODE; 9140e21b167Sbeveloper } 9150e21b167Sbeveloper if ((node.kind & B_TIME_SOURCE) == 0) { 91660f15390Sbeveloper FATAL("BMediaRoster::StopTimeSource node %ld is no timesource\n", node.node); 91752a38012Sejakowatz return B_MEDIA_BAD_NODE; 9180e21b167Sbeveloper } 9190e21b167Sbeveloper 92060f15390Sbeveloper TRACE("BMediaRoster::StopTimeSource, node %ld, at real %Ld %s\n", node.node, at_real_time, immediate ? "NOW" : ""); 92152a38012Sejakowatz 92252a38012Sejakowatz BTimeSource::time_source_op_info msg; 92352a38012Sejakowatz msg.op = immediate ? BTimeSource::B_TIMESOURCE_STOP_IMMEDIATELY : BTimeSource::B_TIMESOURCE_STOP; 92452a38012Sejakowatz msg.real_time = at_real_time; 92552a38012Sejakowatz 92652a38012Sejakowatz return write_port(node.port, TIMESOURCE_OP, &msg, sizeof(msg)); 92752a38012Sejakowatz } 92852a38012Sejakowatz 92952a38012Sejakowatz 93052a38012Sejakowatz status_t 93152a38012Sejakowatz BMediaRoster::SeekTimeSource(const media_node & node, 93252a38012Sejakowatz bigtime_t to_performance_time, 93352a38012Sejakowatz bigtime_t at_real_time) 93452a38012Sejakowatz { 93552a38012Sejakowatz CALLED(); 93660f15390Sbeveloper if (IS_SYSTEM_TIMESOURCE(node)) { 93760f15390Sbeveloper // XXX debug this 93860f15390Sbeveloper // FATAL("BMediaRoster::SeekTimeSource node %ld is system timesource\n", node.node); 93960f15390Sbeveloper // you can't seek the system time source, but 94060f15390Sbeveloper // returning B_ERROR would break StampTV 94160f15390Sbeveloper return B_OK; 94260f15390Sbeveloper } 94360f15390Sbeveloper if (IS_SHADOW_TIMESOURCE(node)) { 94460f15390Sbeveloper // XXX debug this 94560f15390Sbeveloper FATAL("BMediaRoster::SeekTimeSource node %ld is shadow timesource\n", node.node); 94660f15390Sbeveloper return B_OK; 94760f15390Sbeveloper } 94840f36b03Sbeveloper if (IS_INVALID_NODE(node)) { 94960f15390Sbeveloper FATAL("BMediaRoster::SeekTimeSource node %ld invalid\n", node.node); 95052a38012Sejakowatz return B_MEDIA_BAD_NODE; 9510e21b167Sbeveloper } 9520e21b167Sbeveloper if ((node.kind & B_TIME_SOURCE) == 0) { 95360f15390Sbeveloper FATAL("BMediaRoster::SeekTimeSource node %ld is no timesource\n", node.node); 95452a38012Sejakowatz return B_MEDIA_BAD_NODE; 9550e21b167Sbeveloper } 9560e21b167Sbeveloper 95760f15390Sbeveloper TRACE("BMediaRoster::SeekTimeSource, node %ld, at real %Ld, to perf %Ld\n", node.node, at_real_time, to_performance_time); 95852a38012Sejakowatz 95952a38012Sejakowatz BTimeSource::time_source_op_info msg; 96052a38012Sejakowatz msg.op = BTimeSource::B_TIMESOURCE_SEEK; 96152a38012Sejakowatz msg.real_time = at_real_time; 96252a38012Sejakowatz msg.performance_time = to_performance_time; 96352a38012Sejakowatz 96452a38012Sejakowatz return write_port(node.port, TIMESOURCE_OP, &msg, sizeof(msg)); 96552a38012Sejakowatz } 96652a38012Sejakowatz 96752a38012Sejakowatz 96852a38012Sejakowatz status_t 96952a38012Sejakowatz BMediaRoster::SyncToNode(const media_node & node, 97052a38012Sejakowatz bigtime_t at_time, 97152a38012Sejakowatz bigtime_t timeout) 97252a38012Sejakowatz { 97352a38012Sejakowatz UNIMPLEMENTED(); 97460f15390Sbeveloper return B_OK; 97552a38012Sejakowatz } 97652a38012Sejakowatz 97752a38012Sejakowatz 97852a38012Sejakowatz status_t 97952a38012Sejakowatz BMediaRoster::SetRunModeNode(const media_node & node, 98052a38012Sejakowatz BMediaNode::run_mode mode) 98152a38012Sejakowatz { 98252a38012Sejakowatz CALLED(); 98340f36b03Sbeveloper if (IS_INVALID_NODE(node)) 98452a38012Sejakowatz return B_MEDIA_BAD_NODE; 98552a38012Sejakowatz 986dfb2ad61Sbeveloper node_set_run_mode_command msg; 98752a38012Sejakowatz msg.mode = mode; 98852a38012Sejakowatz 98952a38012Sejakowatz return write_port(node.port, NODE_SET_RUN_MODE, &msg, sizeof(msg)); 99052a38012Sejakowatz } 99152a38012Sejakowatz 99252a38012Sejakowatz 99352a38012Sejakowatz status_t 99452a38012Sejakowatz BMediaRoster::PrerollNode(const media_node & node) 99552a38012Sejakowatz { 99652a38012Sejakowatz CALLED(); 99740f36b03Sbeveloper if (IS_INVALID_NODE(node)) 99852a38012Sejakowatz return B_MEDIA_BAD_NODE; 99952a38012Sejakowatz 100052a38012Sejakowatz char dummy; 100152a38012Sejakowatz return write_port(node.port, NODE_PREROLL, &dummy, sizeof(dummy)); 100252a38012Sejakowatz } 100352a38012Sejakowatz 100452a38012Sejakowatz 100552a38012Sejakowatz status_t 100652a38012Sejakowatz BMediaRoster::RollNode(const media_node & node, 100752a38012Sejakowatz bigtime_t startPerformance, 100852a38012Sejakowatz bigtime_t stopPerformance, 100952a38012Sejakowatz bigtime_t atMediaTime) 101052a38012Sejakowatz { 101152a38012Sejakowatz UNIMPLEMENTED(); 101252a38012Sejakowatz return B_ERROR; 101352a38012Sejakowatz } 101452a38012Sejakowatz 101552a38012Sejakowatz 101652a38012Sejakowatz status_t 101752a38012Sejakowatz BMediaRoster::SetProducerRunModeDelay(const media_node & node, 101852a38012Sejakowatz bigtime_t delay, 101952a38012Sejakowatz BMediaNode::run_mode mode) 102052a38012Sejakowatz { 102160f15390Sbeveloper CALLED(); 102260f15390Sbeveloper if (IS_INVALID_NODE(node)) 102360f15390Sbeveloper return B_MEDIA_BAD_NODE; 102460f15390Sbeveloper if ((node.kind & B_BUFFER_PRODUCER) == 0) 102560f15390Sbeveloper return B_MEDIA_BAD_NODE; 102660f15390Sbeveloper 102760f15390Sbeveloper producer_set_run_mode_delay_command command; 102860f15390Sbeveloper command.mode = mode; 102960f15390Sbeveloper command.delay = delay; 103060f15390Sbeveloper 103160f15390Sbeveloper return SendToPort(node.port, PRODUCER_SET_RUN_MODE_DELAY, &command, sizeof(command)); 103252a38012Sejakowatz } 103352a38012Sejakowatz 103452a38012Sejakowatz 103552a38012Sejakowatz status_t 103652a38012Sejakowatz BMediaRoster::SetProducerRate(const media_node & producer, 103752a38012Sejakowatz int32 numer, 103852a38012Sejakowatz int32 denom) 103952a38012Sejakowatz { 104052a38012Sejakowatz CALLED(); 104140f36b03Sbeveloper if (IS_INVALID_NODE(producer)) 104252a38012Sejakowatz return B_MEDIA_BAD_NODE; 104352a38012Sejakowatz if ((producer.kind & B_BUFFER_PRODUCER) == 0) 104452a38012Sejakowatz return B_MEDIA_BAD_NODE; 104552a38012Sejakowatz 1046dfb2ad61Sbeveloper producer_set_play_rate_request msg; 1047dfb2ad61Sbeveloper producer_set_play_rate_reply reply; 104852a38012Sejakowatz status_t rv; 104952a38012Sejakowatz int32 code; 105052a38012Sejakowatz 105152a38012Sejakowatz msg.numer = numer; 105252a38012Sejakowatz msg.denom = denom; 105352a38012Sejakowatz msg.reply_port = _PortPool->GetPort(); 105452a38012Sejakowatz rv = write_port(producer.node, PRODUCER_SET_PLAY_RATE, &msg, sizeof(msg)); 105552a38012Sejakowatz if (rv != B_OK) { 105652a38012Sejakowatz _PortPool->PutPort(msg.reply_port); 105752a38012Sejakowatz return rv; 105852a38012Sejakowatz } 105952a38012Sejakowatz rv = read_port(msg.reply_port, &code, &reply, sizeof(reply)); 106052a38012Sejakowatz _PortPool->PutPort(msg.reply_port); 106152a38012Sejakowatz return (rv < B_OK) ? rv : reply.result; 106252a38012Sejakowatz } 106352a38012Sejakowatz 106452a38012Sejakowatz 106552a38012Sejakowatz /* Nodes will have available inputs/outputs as long as they are capable */ 106652a38012Sejakowatz /* of accepting more connections. The node may create an additional */ 106752a38012Sejakowatz /* output or input as the currently available is taken into usage. */ 106852a38012Sejakowatz status_t 106952a38012Sejakowatz BMediaRoster::GetLiveNodeInfo(const media_node & node, 107052a38012Sejakowatz live_node_info * out_live_info) 107152a38012Sejakowatz { 10729e9417d2Sbeveloper CALLED(); 10739e9417d2Sbeveloper if (out_live_info == NULL) 10749e9417d2Sbeveloper return B_BAD_VALUE; 107540f36b03Sbeveloper if (IS_INVALID_NODE(node)) 10769e9417d2Sbeveloper return B_MEDIA_BAD_NODE; 10779e9417d2Sbeveloper 10789e9417d2Sbeveloper server_get_live_node_info_request request; 10799e9417d2Sbeveloper server_get_live_node_info_reply reply; 10809e9417d2Sbeveloper status_t rv; 10819e9417d2Sbeveloper 10829e9417d2Sbeveloper request.node = node; 10839e9417d2Sbeveloper 10841299bfb2Sbeveloper rv = QueryServer(SERVER_GET_LIVE_NODE_INFO, &request, sizeof(request), &reply, sizeof(reply)); 10859e9417d2Sbeveloper if (rv != B_OK) 10869e9417d2Sbeveloper return rv; 10879e9417d2Sbeveloper 10889e9417d2Sbeveloper *out_live_info = reply.live_info; 10899e9417d2Sbeveloper return B_OK; 109052a38012Sejakowatz } 109152a38012Sejakowatz 109252a38012Sejakowatz 109352a38012Sejakowatz status_t 109452a38012Sejakowatz BMediaRoster::GetLiveNodes(live_node_info * out_live_nodes, 109552a38012Sejakowatz int32 * io_total_count, 109652a38012Sejakowatz const media_format * has_input, 109752a38012Sejakowatz const media_format * has_output, 109852a38012Sejakowatz const char * name, 109952a38012Sejakowatz uint64 node_kinds) 110052a38012Sejakowatz { 11019e9417d2Sbeveloper CALLED(); 11029e9417d2Sbeveloper if (out_live_nodes == NULL || io_total_count == NULL) 11039e9417d2Sbeveloper return B_BAD_VALUE; 11049e9417d2Sbeveloper if (*io_total_count <= 0) 11059e9417d2Sbeveloper return B_BAD_VALUE; 11069e9417d2Sbeveloper 11079e9417d2Sbeveloper // XXX we also support the wildcard search as GetDormantNodes does. This needs to be documented 11089e9417d2Sbeveloper 11099e9417d2Sbeveloper server_get_live_nodes_request request; 11109e9417d2Sbeveloper server_get_live_nodes_reply reply; 11119e9417d2Sbeveloper status_t rv; 11129e9417d2Sbeveloper 11139e9417d2Sbeveloper request.maxcount = *io_total_count; 11149e9417d2Sbeveloper request.has_input = (bool) has_input; 11159e9417d2Sbeveloper if (has_input) 11169e9417d2Sbeveloper request.inputformat = *has_input; // XXX we should not make a flat copy of media_format 11179e9417d2Sbeveloper request.has_output = (bool) has_output; 11189e9417d2Sbeveloper if (has_output) 11199e9417d2Sbeveloper request.outputformat = *has_output; // XXX we should not make a flat copy of media_format 11209e9417d2Sbeveloper request.has_name = (bool) name; 11219e9417d2Sbeveloper if (name) { 11229e9417d2Sbeveloper int len = strlen(name); 11239e9417d2Sbeveloper len = min_c(len, (int)sizeof(request.name) - 1); 11249e9417d2Sbeveloper memcpy(request.name, name, len); 11259e9417d2Sbeveloper request.name[len] = 0; 11269e9417d2Sbeveloper } 11279e9417d2Sbeveloper request.require_kinds = node_kinds; 11289e9417d2Sbeveloper 11299e9417d2Sbeveloper rv = QueryServer(SERVER_GET_LIVE_NODES, &request, sizeof(request), &reply, sizeof(reply)); 11309e9417d2Sbeveloper if (rv != B_OK) { 1131353b9f6bSbeveloper FATAL("BMediaRoster::GetLiveNodes failed\n"); 11321299bfb2Sbeveloper *io_total_count = 0; 11339e9417d2Sbeveloper return rv; 11349e9417d2Sbeveloper } 11359e9417d2Sbeveloper 11369e9417d2Sbeveloper if (reply.count > MAX_LIVE_INFO) { 11379e9417d2Sbeveloper live_node_info *live_info; 11389e9417d2Sbeveloper area_id clone; 11399e9417d2Sbeveloper 11409e9417d2Sbeveloper clone = clone_area("live_node_info clone", reinterpret_cast<void **>(&live_info), B_ANY_ADDRESS, B_READ_AREA | B_WRITE_AREA, reply.area); 11419e9417d2Sbeveloper if (clone < B_OK) { 1142353b9f6bSbeveloper FATAL("BMediaRoster::GetLiveNodes failed to clone area, %#lx\n", clone); 11439e9417d2Sbeveloper delete_area(reply.area); 11441299bfb2Sbeveloper *io_total_count = 0; 114552a38012Sejakowatz return B_ERROR; 114652a38012Sejakowatz } 114752a38012Sejakowatz 11489e9417d2Sbeveloper for (int32 i = 0; i < reply.count; i++) { 11499e9417d2Sbeveloper out_live_nodes[i] = live_info[i]; 11509e9417d2Sbeveloper } 11519e9417d2Sbeveloper 11529e9417d2Sbeveloper delete_area(clone); 11539e9417d2Sbeveloper delete_area(reply.area); 11549e9417d2Sbeveloper } else { 11559e9417d2Sbeveloper for (int32 i = 0; i < reply.count; i++) { 11569e9417d2Sbeveloper out_live_nodes[i] = reply.live_info[i]; 11579e9417d2Sbeveloper } 11589e9417d2Sbeveloper } 11599e9417d2Sbeveloper *io_total_count = reply.count; 11609e9417d2Sbeveloper 11619e9417d2Sbeveloper return B_OK; 11629e9417d2Sbeveloper } 11639e9417d2Sbeveloper 116452a38012Sejakowatz 116552a38012Sejakowatz status_t 116652a38012Sejakowatz BMediaRoster::GetFreeInputsFor(const media_node & node, 116752a38012Sejakowatz media_input * out_free_inputs, 116852a38012Sejakowatz int32 buf_num_inputs, 116952a38012Sejakowatz int32 * out_total_count, 117052a38012Sejakowatz media_type filter_type) 117152a38012Sejakowatz { 11723620737cSbeveloper CALLED(); 117340f36b03Sbeveloper if (IS_INVALID_NODE(node) || (node.kind & B_BUFFER_CONSUMER) == 0) 11743620737cSbeveloper return B_MEDIA_BAD_NODE; 11753620737cSbeveloper if (out_free_inputs == NULL || out_total_count == NULL) 11763620737cSbeveloper return B_BAD_VALUE; 11773620737cSbeveloper 117876669a29Sbeveloper List<media_input> list; 11793620737cSbeveloper media_input *input; 11803620737cSbeveloper status_t rv; 11813620737cSbeveloper 11821299bfb2Sbeveloper *out_total_count = 0; 11831299bfb2Sbeveloper 11848b04ffc1Sbeveloper rv = MediaRosterEx(this)->GetAllInputs(node, &list); 11853620737cSbeveloper if (B_OK != rv) 11863620737cSbeveloper return rv; 11873620737cSbeveloper 118876669a29Sbeveloper int32 i; 118976669a29Sbeveloper for (i = 0, list.Rewind(); list.GetNext(&input); i++) { 11903620737cSbeveloper if (filter_type != B_MEDIA_UNKNOWN_TYPE && filter_type != input->format.type) 11913620737cSbeveloper continue; // media_type used, but doesn't match 11923620737cSbeveloper if (input->source != media_source::null) 11933620737cSbeveloper continue; // consumer source already connected 11943620737cSbeveloper out_free_inputs[i] = *input; 11953620737cSbeveloper *out_total_count += 1; 11963620737cSbeveloper buf_num_inputs -= 1; 11973620737cSbeveloper if (buf_num_inputs == 0) 11983620737cSbeveloper break; 11993620737cSbeveloper } 12003620737cSbeveloper 12018b04ffc1Sbeveloper MediaRosterEx(this)->PublishInputs(node, &list); 12023620737cSbeveloper return B_OK; 120352a38012Sejakowatz } 120452a38012Sejakowatz 120552a38012Sejakowatz 120652a38012Sejakowatz status_t 120752a38012Sejakowatz BMediaRoster::GetConnectedInputsFor(const media_node & node, 120852a38012Sejakowatz media_input * out_active_inputs, 120952a38012Sejakowatz int32 buf_num_inputs, 121052a38012Sejakowatz int32 * out_total_count) 121152a38012Sejakowatz { 12123620737cSbeveloper CALLED(); 121340f36b03Sbeveloper if (IS_INVALID_NODE(node) || (node.kind & B_BUFFER_CONSUMER) == 0) 12143620737cSbeveloper return B_MEDIA_BAD_NODE; 12153620737cSbeveloper if (out_active_inputs == NULL || out_total_count == NULL) 12163620737cSbeveloper return B_BAD_VALUE; 12173620737cSbeveloper 121876669a29Sbeveloper List<media_input> list; 12193620737cSbeveloper media_input *input; 12203620737cSbeveloper status_t rv; 12213620737cSbeveloper 12221299bfb2Sbeveloper *out_total_count = 0; 12231299bfb2Sbeveloper 12248b04ffc1Sbeveloper rv = MediaRosterEx(this)->GetAllInputs(node, &list); 12253620737cSbeveloper if (B_OK != rv) 12263620737cSbeveloper return rv; 12273620737cSbeveloper 122876669a29Sbeveloper int32 i; 122976669a29Sbeveloper for (i = 0, list.Rewind(); list.GetNext(&input); i++) { 12303620737cSbeveloper if (input->source == media_source::null) 12313620737cSbeveloper continue; // consumer source not connected 12323620737cSbeveloper out_active_inputs[i] = *input; 12333620737cSbeveloper *out_total_count += 1; 12343620737cSbeveloper buf_num_inputs -= 1; 12353620737cSbeveloper if (buf_num_inputs == 0) 12363620737cSbeveloper break; 12373620737cSbeveloper } 12383620737cSbeveloper 12398b04ffc1Sbeveloper MediaRosterEx(this)->PublishInputs(node, &list); 12403620737cSbeveloper return B_OK; 124152a38012Sejakowatz } 124252a38012Sejakowatz 124352a38012Sejakowatz 124452a38012Sejakowatz status_t 124552a38012Sejakowatz BMediaRoster::GetAllInputsFor(const media_node & node, 124652a38012Sejakowatz media_input * out_inputs, 124752a38012Sejakowatz int32 buf_num_inputs, 124852a38012Sejakowatz int32 * out_total_count) 124952a38012Sejakowatz { 125052a38012Sejakowatz CALLED(); 125140f36b03Sbeveloper if (IS_INVALID_NODE(node) || (node.kind & B_BUFFER_CONSUMER) == 0) 125252a38012Sejakowatz return B_MEDIA_BAD_NODE; 125352a38012Sejakowatz if (out_inputs == NULL || out_total_count == NULL) 125452a38012Sejakowatz return B_BAD_VALUE; 125552a38012Sejakowatz 125676669a29Sbeveloper List<media_input> list; 12573620737cSbeveloper media_input *input; 125852a38012Sejakowatz status_t rv; 125952a38012Sejakowatz 12601299bfb2Sbeveloper *out_total_count = 0; 12611299bfb2Sbeveloper 12628b04ffc1Sbeveloper rv = MediaRosterEx(this)->GetAllInputs(node, &list); 12633620737cSbeveloper if (B_OK != rv) 12643620737cSbeveloper return rv; 12653620737cSbeveloper 126676669a29Sbeveloper int32 i; 126776669a29Sbeveloper for (i = 0, list.Rewind(); list.GetNext(&input); i++) { 12683620737cSbeveloper out_inputs[i] = *input; 126952a38012Sejakowatz *out_total_count += 1; 12703620737cSbeveloper buf_num_inputs -= 1; 12713620737cSbeveloper if (buf_num_inputs == 0) 12723620737cSbeveloper break; 127352a38012Sejakowatz } 127452a38012Sejakowatz 12758b04ffc1Sbeveloper MediaRosterEx(this)->PublishInputs(node, &list); 12763620737cSbeveloper return B_OK; 127752a38012Sejakowatz } 127852a38012Sejakowatz 127952a38012Sejakowatz 128052a38012Sejakowatz status_t 128152a38012Sejakowatz BMediaRoster::GetFreeOutputsFor(const media_node & node, 128252a38012Sejakowatz media_output * out_free_outputs, 128352a38012Sejakowatz int32 buf_num_outputs, 128452a38012Sejakowatz int32 * out_total_count, 128552a38012Sejakowatz media_type filter_type) 128652a38012Sejakowatz { 12873620737cSbeveloper CALLED(); 128840f36b03Sbeveloper if (IS_INVALID_NODE(node) || (node.kind & B_BUFFER_PRODUCER) == 0) 12893620737cSbeveloper return B_MEDIA_BAD_NODE; 12903620737cSbeveloper if (out_free_outputs == NULL || out_total_count == NULL) 12913620737cSbeveloper return B_BAD_VALUE; 12923620737cSbeveloper 129376669a29Sbeveloper List<media_output> list; 12943620737cSbeveloper media_output *output; 12953620737cSbeveloper status_t rv; 12963620737cSbeveloper 12971299bfb2Sbeveloper *out_total_count = 0; 12981299bfb2Sbeveloper 12998b04ffc1Sbeveloper rv = MediaRosterEx(this)->GetAllOutputs(node, &list); 13003620737cSbeveloper if (B_OK != rv) 13013620737cSbeveloper return rv; 13023620737cSbeveloper 130376669a29Sbeveloper int32 i; 130476669a29Sbeveloper for (i = 0, list.Rewind(); list.GetNext(&output); i++) { 13053620737cSbeveloper if (filter_type != B_MEDIA_UNKNOWN_TYPE && filter_type != output->format.type) 13063620737cSbeveloper continue; // media_type used, but doesn't match 13073620737cSbeveloper if (output->destination != media_destination::null) 13083620737cSbeveloper continue; // producer destination already connected 13093620737cSbeveloper out_free_outputs[i] = *output; 13103620737cSbeveloper *out_total_count += 1; 13113620737cSbeveloper buf_num_outputs -= 1; 13123620737cSbeveloper if (buf_num_outputs == 0) 13133620737cSbeveloper break; 13143620737cSbeveloper } 13153620737cSbeveloper 13168b04ffc1Sbeveloper MediaRosterEx(this)->PublishOutputs(node, &list); 13173620737cSbeveloper return B_OK; 131852a38012Sejakowatz } 131952a38012Sejakowatz 132052a38012Sejakowatz 132152a38012Sejakowatz status_t 132252a38012Sejakowatz BMediaRoster::GetConnectedOutputsFor(const media_node & node, 132352a38012Sejakowatz media_output * out_active_outputs, 132452a38012Sejakowatz int32 buf_num_outputs, 132552a38012Sejakowatz int32 * out_total_count) 132652a38012Sejakowatz { 13273620737cSbeveloper CALLED(); 132840f36b03Sbeveloper if (IS_INVALID_NODE(node) || (node.kind & B_BUFFER_PRODUCER) == 0) 13293620737cSbeveloper return B_MEDIA_BAD_NODE; 13303620737cSbeveloper if (out_active_outputs == NULL || out_total_count == NULL) 13313620737cSbeveloper return B_BAD_VALUE; 13323620737cSbeveloper 133376669a29Sbeveloper List<media_output> list; 13343620737cSbeveloper media_output *output; 13353620737cSbeveloper status_t rv; 13363620737cSbeveloper 13371299bfb2Sbeveloper *out_total_count = 0; 13381299bfb2Sbeveloper 13398b04ffc1Sbeveloper rv = MediaRosterEx(this)->GetAllOutputs(node, &list); 13403620737cSbeveloper if (B_OK != rv) 13413620737cSbeveloper return rv; 13423620737cSbeveloper 134376669a29Sbeveloper int32 i; 134476669a29Sbeveloper for (i = 0, list.Rewind(); list.GetNext(&output); i++) { 13453620737cSbeveloper if (output->destination == media_destination::null) 13463620737cSbeveloper continue; // producer destination not connected 13473620737cSbeveloper out_active_outputs[i] = *output; 13483620737cSbeveloper *out_total_count += 1; 13493620737cSbeveloper buf_num_outputs -= 1; 13503620737cSbeveloper if (buf_num_outputs == 0) 13513620737cSbeveloper break; 13523620737cSbeveloper } 13533620737cSbeveloper 13548b04ffc1Sbeveloper MediaRosterEx(this)->PublishOutputs(node, &list); 13553620737cSbeveloper return B_OK; 135652a38012Sejakowatz } 135752a38012Sejakowatz 135852a38012Sejakowatz 135952a38012Sejakowatz status_t 136052a38012Sejakowatz BMediaRoster::GetAllOutputsFor(const media_node & node, 136152a38012Sejakowatz media_output * out_outputs, 136252a38012Sejakowatz int32 buf_num_outputs, 136352a38012Sejakowatz int32 * out_total_count) 136452a38012Sejakowatz { 136552a38012Sejakowatz CALLED(); 136640f36b03Sbeveloper if (IS_INVALID_NODE(node) || (node.kind & B_BUFFER_PRODUCER) == 0) 136752a38012Sejakowatz return B_MEDIA_BAD_NODE; 136852a38012Sejakowatz if (out_outputs == NULL || out_total_count == NULL) 136952a38012Sejakowatz return B_BAD_VALUE; 137052a38012Sejakowatz 137176669a29Sbeveloper List<media_output> list; 13723620737cSbeveloper media_output *output; 137352a38012Sejakowatz status_t rv; 137452a38012Sejakowatz 13751299bfb2Sbeveloper *out_total_count = 0; 13761299bfb2Sbeveloper 13778b04ffc1Sbeveloper rv = MediaRosterEx(this)->GetAllOutputs(node, &list); 13783620737cSbeveloper if (B_OK != rv) 13793620737cSbeveloper return rv; 13803620737cSbeveloper 138176669a29Sbeveloper int32 i; 138276669a29Sbeveloper for (i = 0, list.Rewind(); list.GetNext(&output); i++) { 13833620737cSbeveloper out_outputs[i] = *output; 138452a38012Sejakowatz *out_total_count += 1; 13853620737cSbeveloper buf_num_outputs -= 1; 13863620737cSbeveloper if (buf_num_outputs == 0) 13873620737cSbeveloper break; 138852a38012Sejakowatz } 138952a38012Sejakowatz 13908b04ffc1Sbeveloper MediaRosterEx(this)->PublishOutputs(node, &list); 13913620737cSbeveloper return B_OK; 139252a38012Sejakowatz } 139352a38012Sejakowatz 139452a38012Sejakowatz 139552a38012Sejakowatz status_t 139652a38012Sejakowatz BMediaRoster::StartWatching(const BMessenger & where) 139752a38012Sejakowatz { 1398eae26d3dSbeveloper CALLED(); 1399eae26d3dSbeveloper if (!where.IsValid()) { 1400353b9f6bSbeveloper FATAL("BMediaRoster::StartWatching: messenger invalid!\n"); 1401eae26d3dSbeveloper return B_BAD_VALUE; 1402eae26d3dSbeveloper } 1403f4925104Sbeveloper return BPrivate::media::notifications::Register(where, media_node::null, B_MEDIA_WILDCARD); 140452a38012Sejakowatz } 140552a38012Sejakowatz 140652a38012Sejakowatz 140752a38012Sejakowatz status_t 140852a38012Sejakowatz BMediaRoster::StartWatching(const BMessenger & where, 140952a38012Sejakowatz int32 notificationType) 141052a38012Sejakowatz { 1411eae26d3dSbeveloper CALLED(); 1412eae26d3dSbeveloper if (!where.IsValid()) { 1413353b9f6bSbeveloper FATAL("BMediaRoster::StartWatching: messenger invalid!\n"); 1414eae26d3dSbeveloper return B_BAD_VALUE; 1415eae26d3dSbeveloper } 1416f4925104Sbeveloper if (false == BPrivate::media::notifications::IsValidNotificationRequest(false, notificationType)) { 1417353b9f6bSbeveloper FATAL("BMediaRoster::StartWatching: notificationType invalid!\n"); 1418eae26d3dSbeveloper return B_BAD_VALUE; 1419eae26d3dSbeveloper } 1420f4925104Sbeveloper return BPrivate::media::notifications::Register(where, media_node::null, notificationType); 142152a38012Sejakowatz } 142252a38012Sejakowatz 142352a38012Sejakowatz 142452a38012Sejakowatz status_t 142552a38012Sejakowatz BMediaRoster::StartWatching(const BMessenger & where, 142652a38012Sejakowatz const media_node & node, 142752a38012Sejakowatz int32 notificationType) 142852a38012Sejakowatz { 1429eae26d3dSbeveloper CALLED(); 1430eae26d3dSbeveloper if (!where.IsValid()) { 1431353b9f6bSbeveloper FATAL("BMediaRoster::StartWatching: messenger invalid!\n"); 1432eae26d3dSbeveloper return B_BAD_VALUE; 1433eae26d3dSbeveloper } 143440f36b03Sbeveloper if (IS_INVALID_NODE(node)) { 1435353b9f6bSbeveloper FATAL("BMediaRoster::StartWatching: node invalid!\n"); 1436eae26d3dSbeveloper return B_MEDIA_BAD_NODE; 1437eae26d3dSbeveloper } 1438f4925104Sbeveloper if (false == BPrivate::media::notifications::IsValidNotificationRequest(true, notificationType)) { 1439353b9f6bSbeveloper FATAL("BMediaRoster::StartWatching: notificationType invalid!\n"); 1440eae26d3dSbeveloper return B_BAD_VALUE; 1441eae26d3dSbeveloper } 1442f4925104Sbeveloper return BPrivate::media::notifications::Register(where, node, notificationType); 144352a38012Sejakowatz } 144452a38012Sejakowatz 144552a38012Sejakowatz 144652a38012Sejakowatz status_t 144752a38012Sejakowatz BMediaRoster::StopWatching(const BMessenger & where) 144852a38012Sejakowatz { 1449eae26d3dSbeveloper CALLED(); 1450eae26d3dSbeveloper // messenger may already be invalid, so we don't check this 1451f4925104Sbeveloper return BPrivate::media::notifications::Unregister(where, media_node::null, B_MEDIA_WILDCARD); 145252a38012Sejakowatz } 145352a38012Sejakowatz 145452a38012Sejakowatz 145552a38012Sejakowatz status_t 145652a38012Sejakowatz BMediaRoster::StopWatching(const BMessenger & where, 145752a38012Sejakowatz int32 notificationType) 145852a38012Sejakowatz { 1459eae26d3dSbeveloper CALLED(); 1460eae26d3dSbeveloper // messenger may already be invalid, so we don't check this 1461f4925104Sbeveloper if (false == BPrivate::media::notifications::IsValidNotificationRequest(false, notificationType)) { 1462353b9f6bSbeveloper FATAL("BMediaRoster::StopWatching: notificationType invalid!\n"); 1463eae26d3dSbeveloper return B_BAD_VALUE; 1464eae26d3dSbeveloper } 1465f4925104Sbeveloper return BPrivate::media::notifications::Unregister(where, media_node::null, notificationType); 146652a38012Sejakowatz } 146752a38012Sejakowatz 146852a38012Sejakowatz 146952a38012Sejakowatz status_t 147052a38012Sejakowatz BMediaRoster::StopWatching(const BMessenger & where, 147152a38012Sejakowatz const media_node & node, 147252a38012Sejakowatz int32 notificationType) 147352a38012Sejakowatz { 1474eae26d3dSbeveloper CALLED(); 1475eae26d3dSbeveloper // messenger may already be invalid, so we don't check this 147640f36b03Sbeveloper if (IS_INVALID_NODE(node)) { 1477353b9f6bSbeveloper FATAL("BMediaRoster::StopWatching: node invalid!\n"); 1478eae26d3dSbeveloper return B_MEDIA_BAD_NODE; 1479eae26d3dSbeveloper } 1480f4925104Sbeveloper if (false == BPrivate::media::notifications::IsValidNotificationRequest(true, notificationType)) { 1481353b9f6bSbeveloper FATAL("BMediaRoster::StopWatching: notificationType invalid!\n"); 1482eae26d3dSbeveloper return B_BAD_VALUE; 1483eae26d3dSbeveloper } 1484f4925104Sbeveloper return BPrivate::media::notifications::Unregister(where, node, notificationType); 148552a38012Sejakowatz } 148652a38012Sejakowatz 148752a38012Sejakowatz 148852a38012Sejakowatz status_t 148952a38012Sejakowatz BMediaRoster::RegisterNode(BMediaNode * node) 149052a38012Sejakowatz { 149154187cc6Sbeveloper CALLED(); 149254187cc6Sbeveloper // addon-id = -1 (unused), addon-flavor-id = 0 (unused, too) 149354187cc6Sbeveloper return MediaRosterEx(this)->RegisterNode(node, -1, 0); 149454187cc6Sbeveloper } 149554187cc6Sbeveloper 149654187cc6Sbeveloper 149754187cc6Sbeveloper status_t 149854187cc6Sbeveloper BMediaRosterEx::RegisterNode(BMediaNode * node, media_addon_id addonid, int32 flavorid) 149954187cc6Sbeveloper { 150052a38012Sejakowatz CALLED(); 150152a38012Sejakowatz if (node == NULL) 150252a38012Sejakowatz return B_BAD_VALUE; 150352a38012Sejakowatz 150454187cc6Sbeveloper // some sanity check 150554187cc6Sbeveloper // I'm not sure if the media kit warrants to call BMediaNode::AddOn() here. 150654187cc6Sbeveloper // Perhaps we don't need it. 150754187cc6Sbeveloper { 15089e9417d2Sbeveloper BMediaAddOn *addon; 15099e9417d2Sbeveloper int32 addon_flavor_id; 15109e9417d2Sbeveloper media_addon_id addon_id; 15119e9417d2Sbeveloper addon_flavor_id = 0; 15129e9417d2Sbeveloper addon = node->AddOn(&addon_flavor_id); 15139e9417d2Sbeveloper addon_id = addon ? addon->AddonID() : -1; 151454187cc6Sbeveloper ASSERT(addonid == addon_id); 151554187cc6Sbeveloper ASSERT(flavorid == addon_flavor_id); 151654187cc6Sbeveloper } 151752a38012Sejakowatz 151854187cc6Sbeveloper status_t rv; 15199e9417d2Sbeveloper server_register_node_request request; 15209e9417d2Sbeveloper server_register_node_reply reply; 15219e9417d2Sbeveloper 152254187cc6Sbeveloper request.addon_id = addonid; 152354187cc6Sbeveloper request.addon_flavor_id = flavorid; 15249e9417d2Sbeveloper strcpy(request.name, node->Name()); 15259e9417d2Sbeveloper request.kinds = node->Kinds(); 15269e9417d2Sbeveloper request.port = node->ControlPort(); 15279e9417d2Sbeveloper request.team = team; 15289e9417d2Sbeveloper 15298b04ffc1Sbeveloper TRACE("BMediaRoster::RegisterNode: sending SERVER_REGISTER_NODE: port %ld, kinds 0x%Lx, team %ld, name '%s'\n", request.port, request.kinds, request.team, request.name); 15301299bfb2Sbeveloper 15319e9417d2Sbeveloper rv = QueryServer(SERVER_REGISTER_NODE, &request, sizeof(request), &reply, sizeof(reply)); 15329e9417d2Sbeveloper if (rv != B_OK) { 1533353b9f6bSbeveloper FATAL("BMediaRoster::RegisterNode: failed to register node %s (error %#lx)\n", node->Name(), rv); 15349e9417d2Sbeveloper return rv; 15359e9417d2Sbeveloper } 15369e9417d2Sbeveloper 15378b04ffc1Sbeveloper // we are a friend class of BMediaNode and initialize this member variable 15389e9417d2Sbeveloper node->fNodeID = reply.nodeid; 15399e9417d2Sbeveloper ASSERT(reply.nodeid == node->Node().node); 15409e9417d2Sbeveloper ASSERT(reply.nodeid == node->ID()); 15419e9417d2Sbeveloper 15429e9417d2Sbeveloper // call the callback 15439e9417d2Sbeveloper node->NodeRegistered(); 15443620737cSbeveloper 15450e21b167Sbeveloper // if the BMediaNode also inherits from BTimeSource, we need to call BTimeSource::FinishCreate() 15460e21b167Sbeveloper if (node->Kinds() & B_TIME_SOURCE) { 15470e21b167Sbeveloper BTimeSource *ts; 15480e21b167Sbeveloper ts = dynamic_cast<BTimeSource *>(node); 15490e21b167Sbeveloper if (ts) 15500e21b167Sbeveloper ts->FinishCreate(); 15510e21b167Sbeveloper } 15520e21b167Sbeveloper 1553*359ac306Sbeveloper // XXX XXX XXX 1554*359ac306Sbeveloper // Calling GetAllOutputs and GetAllInputs here, 1555*359ac306Sbeveloper // followed by PublishOutputs and PublishInputs, 1556*359ac306Sbeveloper // does not work, it is too early, and in some 1557*359ac306Sbeveloper // cases it will deadlock the node control thread. 1558*359ac306Sbeveloper 1559*359ac306Sbeveloper // Posting a message to the roster thread here 1560*359ac306Sbeveloper // is also to early, the multi_audio add-on will 1561*359ac306Sbeveloper // no list any inputs 1562*359ac306Sbeveloper // XXX XXX XXX 1563*359ac306Sbeveloper 1564*359ac306Sbeveloper /* 1565*359ac306Sbeveloper BMessage msg(NODE_PUBLISH_CONNECTIONS); 1566*359ac306Sbeveloper media_node tempnode; 1567*359ac306Sbeveloper tempnode = node->Node(); 1568*359ac306Sbeveloper msg.AddData("node", B_RAW_TYPE, &tempnode, sizeof(tempnode)); 1569*359ac306Sbeveloper PostMessage(&msg); 1570*359ac306Sbeveloper */ 1571570f7d04Sbeveloper /* 15723620737cSbeveloper // register existing inputs and outputs with the 15733620737cSbeveloper // media_server, this allows GetLiveNodes() to work 15743620737cSbeveloper // with created, but unconnected nodes. 15753620737cSbeveloper if (node->Kinds() & B_BUFFER_PRODUCER) { 1576*359ac306Sbeveloper List<media_output> list; 1577*359ac306Sbeveloper if (B_OK == GetAllOutputs(node->Node(), &list)) 1578*359ac306Sbeveloper PublishOutputs(node->Node(), &list); 15793620737cSbeveloper } else if (node->Kinds() & B_BUFFER_CONSUMER) { 1580*359ac306Sbeveloper List<media_input> list; 1581*359ac306Sbeveloper if (B_OK == GetAllInputs(node->Node(), &list)) 1582*359ac306Sbeveloper PublishInputs(node->Node(), &list); 15833620737cSbeveloper } 1584570f7d04Sbeveloper */ 15851299bfb2Sbeveloper BPrivate::media::notifications::NodesCreated(&reply.nodeid, 1); 1586570f7d04Sbeveloper /* 1587570f7d04Sbeveloper TRACE("BMediaRoster::RegisterNode: registered node name '%s', id %ld, addon %ld, flavor %ld\n", node->Name(), node->ID(), addon_id, addon_flavor_id); 1588570f7d04Sbeveloper TRACE("BMediaRoster::RegisterNode: node this %p\n", node); 1589570f7d04Sbeveloper TRACE("BMediaRoster::RegisterNode: node fConsumerThis %p\n", node->fConsumerThis); 1590570f7d04Sbeveloper TRACE("BMediaRoster::RegisterNode: node fProducerThis %p\n", node->fProducerThis); 1591570f7d04Sbeveloper TRACE("BMediaRoster::RegisterNode: node fFileInterfaceThis %p\n", node->fFileInterfaceThis); 1592570f7d04Sbeveloper TRACE("BMediaRoster::RegisterNode: node fControllableThis %p\n", node->fControllableThis); 1593570f7d04Sbeveloper TRACE("BMediaRoster::RegisterNode: node fTimeSourceThis %p\n", node->fTimeSourceThis); 1594570f7d04Sbeveloper */ 15959e9417d2Sbeveloper 15969e9417d2Sbeveloper return B_OK; 159752a38012Sejakowatz } 159852a38012Sejakowatz 159952a38012Sejakowatz 160052a38012Sejakowatz status_t 160152a38012Sejakowatz BMediaRoster::UnregisterNode(BMediaNode * node) 160252a38012Sejakowatz { 16039e9417d2Sbeveloper CALLED(); 16049e9417d2Sbeveloper if (node == NULL) 16059e9417d2Sbeveloper return B_BAD_VALUE; 16069e9417d2Sbeveloper 160760f15390Sbeveloper TRACE("BMediaRoster::UnregisterNode %ld (%p)\n", node->ID(), node); 160860f15390Sbeveloper 160986bce45bSbeveloper if (node->fKinds & NODE_KIND_NO_REFCOUNTING) { 161086bce45bSbeveloper printf("BMediaRoster::UnregisterNode, trying to unregister reference counting disabled timesource, node %ld, port %ld, team %ld\n", node->ID(), node->ControlPort(), team); 161186bce45bSbeveloper return B_OK; 161286bce45bSbeveloper } 16138b04ffc1Sbeveloper if (node->ID() == NODE_UNREGISTERED_ID) { 16148b04ffc1Sbeveloper FATAL("BMediaRoster::UnregisterNode: Warning node id %ld, name '%s' already unregistered\n", node->ID(), node->Name()); 16159e9417d2Sbeveloper return B_OK; 16169e9417d2Sbeveloper } 161754187cc6Sbeveloper if (node->fRefCount != 0) { 161854187cc6Sbeveloper FATAL("BMediaRoster::UnregisterNode: Warning node id %ld, name '%s' has local reference count of %ld\n", node->ID(), node->Name(), node->fRefCount); 161954187cc6Sbeveloper // no return here, we continue and unregister! 162054187cc6Sbeveloper } 162154187cc6Sbeveloper 162254187cc6Sbeveloper // Calling BMediaAddOn::GetConfigurationFor(BMediaNode *node, BMessage *config) 162354187cc6Sbeveloper // if this node was instanciated by an add-on needs to be done *somewhere* 162454187cc6Sbeveloper // We can't do it here because it is already to late (destructor of the node 162554187cc6Sbeveloper // might have been called). 16269e9417d2Sbeveloper 16279e9417d2Sbeveloper server_unregister_node_request request; 16289e9417d2Sbeveloper server_unregister_node_reply reply; 16299e9417d2Sbeveloper status_t rv; 16309e9417d2Sbeveloper 16319e9417d2Sbeveloper request.nodeid = node->ID(); 16329e9417d2Sbeveloper request.team = team; 16339e9417d2Sbeveloper 16341299bfb2Sbeveloper // send a notification 16351299bfb2Sbeveloper BPrivate::media::notifications::NodesDeleted(&request.nodeid, 1); 16361299bfb2Sbeveloper 16379e9417d2Sbeveloper rv = QueryServer(SERVER_UNREGISTER_NODE, &request, sizeof(request), &reply, sizeof(reply)); 16389e9417d2Sbeveloper if (rv != B_OK) { 16398b04ffc1Sbeveloper FATAL("BMediaRoster::UnregisterNode: failed to unregister node id %ld, name '%s' (error %#lx)\n", node->ID(), node->Name(), rv); 16409e9417d2Sbeveloper return rv; 16419e9417d2Sbeveloper } 16429e9417d2Sbeveloper 164354187cc6Sbeveloper if (reply.addonid != -1) { 164454187cc6Sbeveloper // Small problem here, we can't use DormantNodeManager::PutAddon(), as 164554187cc6Sbeveloper // UnregisterNode() is called by a dormant node itself (by the destructor). 164654187cc6Sbeveloper // The add-on that contains the node needs to remain in memory until the 164754187cc6Sbeveloper // destructor execution is finished. 164854187cc6Sbeveloper // DormantNodeManager::PutAddonDelayed() will delay unloading. 164954187cc6Sbeveloper _DormantNodeManager->PutAddonDelayed(reply.addonid); 1650cf4e2277Sbeveloper 165173794717Sbeveloper rv = MediaRosterEx(this)->DecrementAddonFlavorInstancesCount(reply.addonid, reply.flavorid); 165254187cc6Sbeveloper if (rv != B_OK) { 165373794717Sbeveloper FATAL("BMediaRoster::UnregisterNode: DecrementAddonFlavorInstancesCount failed\n"); 165454187cc6Sbeveloper // this is really a problem, but we can't fail now 165554187cc6Sbeveloper } 16568b04ffc1Sbeveloper } 16579e9417d2Sbeveloper 16581299bfb2Sbeveloper // we are a friend class of BMediaNode and invalidate this member variable 16598b04ffc1Sbeveloper node->fNodeID = NODE_UNREGISTERED_ID; 16609e9417d2Sbeveloper 16619e9417d2Sbeveloper return B_OK; 166252a38012Sejakowatz } 166352a38012Sejakowatz 166452a38012Sejakowatz 166552a38012Sejakowatz // thread safe for multiple calls to Roster() 166652a38012Sejakowatz /* static */ BMediaRoster * 166752a38012Sejakowatz BMediaRoster::Roster(status_t* out_error) 166852a38012Sejakowatz { 166952a38012Sejakowatz static BLocker locker("BMediaRoster::Roster locker"); 167052a38012Sejakowatz locker.Lock(); 167152a38012Sejakowatz if (_sDefault == NULL) { 16728b04ffc1Sbeveloper _sDefault = new BMediaRosterEx(); 167352a38012Sejakowatz if (out_error != NULL) 167452a38012Sejakowatz *out_error = B_OK; 167552a38012Sejakowatz } else { 167652a38012Sejakowatz if (out_error != NULL) 167752a38012Sejakowatz *out_error = B_OK; 167852a38012Sejakowatz } 167952a38012Sejakowatz locker.Unlock(); 168052a38012Sejakowatz return _sDefault; 168152a38012Sejakowatz } 168252a38012Sejakowatz 168352a38012Sejakowatz 168452a38012Sejakowatz // won't create it if there isn't one 168552a38012Sejakowatz // not thread safe if you call Roster() at the same time 168652a38012Sejakowatz /* static */ BMediaRoster * 168752a38012Sejakowatz BMediaRoster::CurrentRoster() 168852a38012Sejakowatz { 168952a38012Sejakowatz return _sDefault; 169052a38012Sejakowatz } 169152a38012Sejakowatz 169252a38012Sejakowatz 169352a38012Sejakowatz status_t 169452a38012Sejakowatz BMediaRoster::SetTimeSourceFor(media_node_id node, 169552a38012Sejakowatz media_node_id time_source) 169652a38012Sejakowatz { 1697aac800c2Sbeveloper CALLED(); 169840f36b03Sbeveloper if (IS_INVALID_NODEID(node) || IS_INVALID_NODEID(time_source)) 1699aac800c2Sbeveloper return B_BAD_VALUE; 1700aac800c2Sbeveloper 1701aac800c2Sbeveloper media_node clone; 1702aac800c2Sbeveloper status_t rv, result; 1703aac800c2Sbeveloper 170486bce45bSbeveloper // we need to get a clone of the node to have a port id 1705aac800c2Sbeveloper rv = GetNodeFor(node, &clone); 1706aac800c2Sbeveloper if (rv != B_OK) { 1707aac800c2Sbeveloper FATAL("BMediaRoster::SetTimeSourceFor, GetNodeFor failed, node id %ld\n", node); 170852a38012Sejakowatz return B_ERROR; 170952a38012Sejakowatz } 171052a38012Sejakowatz 171160f15390Sbeveloper TRACE("BMediaRoster::SetTimeSourceFor: node %ld will be assigned time source %ld\n", node, time_source); 171286bce45bSbeveloper 171386bce45bSbeveloper // we just send the request to set time_source-id as timesource to the node, 171486bce45bSbeveloper // the NODE_SET_TIMESOURCE handler code will do the real assignment 1715aac800c2Sbeveloper result = B_OK; 1716aac800c2Sbeveloper node_set_timesource_command cmd; 1717aac800c2Sbeveloper cmd.timesource_id = time_source; 1718aac800c2Sbeveloper rv = SendToPort(clone.port, NODE_SET_TIMESOURCE, &cmd, sizeof(cmd)); 1719aac800c2Sbeveloper if (rv != B_OK) { 1720aac800c2Sbeveloper FATAL("BMediaRoster::SetTimeSourceFor, sending NODE_SET_TIMESOURCE failed, node id %ld\n", node); 1721aac800c2Sbeveloper result = B_ERROR; 1722aac800c2Sbeveloper } 1723aac800c2Sbeveloper 172460f15390Sbeveloper // we release the clone 1725aac800c2Sbeveloper rv = ReleaseNode(clone); 1726aac800c2Sbeveloper if (rv != B_OK) { 1727aac800c2Sbeveloper FATAL("BMediaRoster::SetTimeSourceFor, ReleaseNode failed, node id %ld\n", node); 1728aac800c2Sbeveloper result = B_ERROR; 1729aac800c2Sbeveloper } 1730aac800c2Sbeveloper 1731aac800c2Sbeveloper return result; 1732aac800c2Sbeveloper } 1733aac800c2Sbeveloper 173452a38012Sejakowatz 173552a38012Sejakowatz status_t 173652a38012Sejakowatz BMediaRoster::GetParameterWebFor(const media_node & node, 173752a38012Sejakowatz BParameterWeb ** out_web) 173852a38012Sejakowatz { 173928ad138aSbeveloper CALLED(); 174028ad138aSbeveloper if (out_web == NULL) 174128ad138aSbeveloper return B_BAD_VALUE; 174228ad138aSbeveloper if (IS_INVALID_NODE(node)) 174328ad138aSbeveloper return B_MEDIA_BAD_NODE; 174428ad138aSbeveloper if ((node.kind & B_CONTROLLABLE) == 0) 174528ad138aSbeveloper return B_MEDIA_BAD_NODE; 174628ad138aSbeveloper 174728ad138aSbeveloper controllable_get_parameter_web_request request; 174828ad138aSbeveloper controllable_get_parameter_web_reply reply; 174928ad138aSbeveloper int32 requestsize[] = {B_PAGE_SIZE, 4*B_PAGE_SIZE, 16*B_PAGE_SIZE, 64*B_PAGE_SIZE, 128*B_PAGE_SIZE, 256*B_PAGE_SIZE, 0}; 175028ad138aSbeveloper int32 size; 175128ad138aSbeveloper 175228ad138aSbeveloper // XXX it might be better to query the node for the (current) parameter size first 175328ad138aSbeveloper for (int i = 0; (size = requestsize[i]) != 0; i++) { 175428ad138aSbeveloper status_t rv; 175528ad138aSbeveloper area_id area; 175628ad138aSbeveloper void *data; 175728ad138aSbeveloper area = create_area("parameter web data", &data, B_ANY_ADDRESS, size, B_NO_LOCK, B_READ_AREA | B_WRITE_AREA); 175828ad138aSbeveloper if (area < B_OK) { 175928ad138aSbeveloper FATAL("BMediaRoster::GetParameterWebFor couldn't create area of size %ld\n", size); 176028ad138aSbeveloper return B_ERROR; 176128ad138aSbeveloper } 176228ad138aSbeveloper request.maxsize = size; 176328ad138aSbeveloper request.area = area; 176428ad138aSbeveloper rv = QueryPort(node.port, CONTROLLABLE_GET_PARAMETER_WEB, &request, sizeof(request), &reply, sizeof(reply)); 176528ad138aSbeveloper if (rv != B_OK) { 176628ad138aSbeveloper FATAL("BMediaRoster::GetParameterWebFor CONTROLLABLE_GET_PARAMETER_WEB failed\n"); 176728ad138aSbeveloper delete_area(area); 176828ad138aSbeveloper return B_ERROR; 176928ad138aSbeveloper } 177028ad138aSbeveloper if (reply.size == 0) { 177128ad138aSbeveloper // no parameter web available 177228ad138aSbeveloper // XXX should we return an error? 177328ad138aSbeveloper FATAL("BMediaRoster::GetParameterWebFor node %ld has no parameter web\n", node.node); 177428ad138aSbeveloper *out_web = new BParameterWeb(); 177528ad138aSbeveloper delete_area(area); 177660f15390Sbeveloper return B_OK; 177752a38012Sejakowatz } 177828ad138aSbeveloper if (reply.size > 0) { 177928ad138aSbeveloper // we got a flattened parameter web! 178028ad138aSbeveloper *out_web = new BParameterWeb(); 178128ad138aSbeveloper 178228ad138aSbeveloper printf("BMediaRoster::GetParameterWebFor Unflattening %ld bytes, 0x%08x, 0x%08x, 0x%08x, 0x%08x\n", 178328ad138aSbeveloper reply.size, ((uint32*)data)[0], ((uint32*)data)[1], ((uint32*)data)[2], ((uint32*)data)[3]); 178428ad138aSbeveloper 178528ad138aSbeveloper rv = (*out_web)->Unflatten(reply.code, data, reply.size); 178628ad138aSbeveloper if (rv != B_OK) { 178728ad138aSbeveloper FATAL("BMediaRoster::GetParameterWebFor Unflatten failed, %s\n", strerror(rv)); 178828ad138aSbeveloper delete_area(area); 178928ad138aSbeveloper delete *out_web; 179028ad138aSbeveloper return B_ERROR; 179128ad138aSbeveloper } 179228ad138aSbeveloper delete_area(area); 179328ad138aSbeveloper return B_OK; 179428ad138aSbeveloper } 179528ad138aSbeveloper delete_area(area); 179628ad138aSbeveloper ASSERT(reply.size == -1); 179728ad138aSbeveloper // parameter web data was too large 179828ad138aSbeveloper // loop and try a larger size 179928ad138aSbeveloper } 180028ad138aSbeveloper FATAL("BMediaRoster::GetParameterWebFor node %ld has no parameter web larger than %ld\n", node.node, size); 180128ad138aSbeveloper return B_ERROR; 180228ad138aSbeveloper } 180352a38012Sejakowatz 180452a38012Sejakowatz 180552a38012Sejakowatz status_t 180652a38012Sejakowatz BMediaRoster::StartControlPanel(const media_node & node, 180752a38012Sejakowatz BMessenger * out_messenger) 180852a38012Sejakowatz { 180952a38012Sejakowatz UNIMPLEMENTED(); 181052a38012Sejakowatz return B_ERROR; 181152a38012Sejakowatz } 181252a38012Sejakowatz 181352a38012Sejakowatz 181452a38012Sejakowatz status_t 181552a38012Sejakowatz BMediaRoster::GetDormantNodes(dormant_node_info * out_info, 181652a38012Sejakowatz int32 * io_count, 181752a38012Sejakowatz const media_format * has_input /* = NULL */, 181852a38012Sejakowatz const media_format * has_output /* = NULL */, 181952a38012Sejakowatz const char * name /* = NULL */, 182052a38012Sejakowatz uint64 require_kinds /* = NULL */, 182152a38012Sejakowatz uint64 deny_kinds /* = NULL */) 182252a38012Sejakowatz { 182352a38012Sejakowatz CALLED(); 182452a38012Sejakowatz if (out_info == NULL) 182552a38012Sejakowatz return B_BAD_VALUE; 182652a38012Sejakowatz if (io_count == NULL) 182752a38012Sejakowatz return B_BAD_VALUE; 182852a38012Sejakowatz if (*io_count <= 0) 182952a38012Sejakowatz return B_BAD_VALUE; 183052a38012Sejakowatz 183152a38012Sejakowatz xfer_server_get_dormant_nodes msg; 183252a38012Sejakowatz port_id port; 183352a38012Sejakowatz status_t rv; 183452a38012Sejakowatz 183552a38012Sejakowatz port = find_port("media_server port"); 183652a38012Sejakowatz if (port <= B_OK) 183752a38012Sejakowatz return B_ERROR; 183852a38012Sejakowatz 183952a38012Sejakowatz msg.maxcount = *io_count; 184052a38012Sejakowatz msg.has_input = (bool) has_input; 184152a38012Sejakowatz if (has_input) 184252a38012Sejakowatz msg.inputformat = *has_input; // XXX we should not make a flat copy of media_format 184352a38012Sejakowatz msg.has_output = (bool) has_output; 184452a38012Sejakowatz if (has_output) 184552a38012Sejakowatz msg.outputformat = *has_output;; // XXX we should not make a flat copy of media_format 184652a38012Sejakowatz msg.has_name = (bool) name; 184752a38012Sejakowatz if (name) { 18489e9417d2Sbeveloper int len = strlen(name); 18499e9417d2Sbeveloper len = min_c(len, (int)sizeof(msg.name) - 1); 185052a38012Sejakowatz memcpy(msg.name, name, len); 185152a38012Sejakowatz msg.name[len] = 0; 185252a38012Sejakowatz } 185352a38012Sejakowatz msg.require_kinds = require_kinds; 185452a38012Sejakowatz msg.deny_kinds = deny_kinds; 185552a38012Sejakowatz msg.reply_port = _PortPool->GetPort(); 185652a38012Sejakowatz 185752a38012Sejakowatz rv = write_port(port, SERVER_GET_DORMANT_NODES, &msg, sizeof(msg)); 185852a38012Sejakowatz if (rv != B_OK) { 185952a38012Sejakowatz _PortPool->PutPort(msg.reply_port); 186052a38012Sejakowatz return rv; 186152a38012Sejakowatz } 186252a38012Sejakowatz 186352a38012Sejakowatz xfer_server_get_dormant_nodes_reply reply; 186452a38012Sejakowatz int32 code; 186552a38012Sejakowatz 186652a38012Sejakowatz rv = read_port(msg.reply_port, &code, &reply, sizeof(reply)); 186752a38012Sejakowatz if (rv < B_OK) { 186852a38012Sejakowatz _PortPool->PutPort(msg.reply_port); 186952a38012Sejakowatz return rv; 187052a38012Sejakowatz } 187152a38012Sejakowatz 187252a38012Sejakowatz *io_count = reply.count; 187352a38012Sejakowatz 187452a38012Sejakowatz if (*io_count > 0) { 187552a38012Sejakowatz rv = read_port(msg.reply_port, &code, out_info, *io_count * sizeof(dormant_node_info)); 187652a38012Sejakowatz if (rv < B_OK) 187752a38012Sejakowatz reply.result = rv; 187852a38012Sejakowatz } 187952a38012Sejakowatz _PortPool->PutPort(msg.reply_port); 188052a38012Sejakowatz 188152a38012Sejakowatz return reply.result; 188252a38012Sejakowatz } 188352a38012Sejakowatz 18848b04ffc1Sbeveloper /* This function is used to do the real work of instantiating a dormant node. It is either 18858b04ffc1Sbeveloper * called by the media_addon_server to instantiate a global node, or it gets called from 18868b04ffc1Sbeveloper * BMediaRoster::InstantiateDormantNode() to create a local one. 18878b04ffc1Sbeveloper * 18888b04ffc1Sbeveloper * Checks concerning global/local are not done here. 18898b04ffc1Sbeveloper */ 189052a38012Sejakowatz status_t 189154187cc6Sbeveloper BMediaRosterEx::InstantiateDormantNode(media_addon_id addonid, int32 flavorid, team_id creator, media_node *out_node) 189252a38012Sejakowatz { 189354187cc6Sbeveloper // This function is always called from the correct context, if the node 189454187cc6Sbeveloper // is supposed to be global, it is called from the media_addon_server. 189554187cc6Sbeveloper 189652a38012Sejakowatz // if B_FLAVOR_IS_GLOBAL, we need to use the BMediaAddOn object that 189752a38012Sejakowatz // resides in the media_addon_server 189852a38012Sejakowatz 18998b04ffc1Sbeveloper // RegisterNode() must be called for nodes instantiated from add-ons, 19008b04ffc1Sbeveloper // since the media kit warrants that it's done automatically. 190152a38012Sejakowatz 190254187cc6Sbeveloper // addonid Indicates the ID number of the media add-on in which the node resides. 190354187cc6Sbeveloper // flavorid Indicates the internal ID number that the add-on uses to identify the flavor, 190454187cc6Sbeveloper // this is the number that was published by BMediaAddOn::GetFlavorAt() in the 19058b04ffc1Sbeveloper // flavor_info::internal_id field. 190654187cc6Sbeveloper // creator The creator team is -1 if nodes are created locally. If created globally, 190754187cc6Sbeveloper // it will contain (while called in media_addon_server context) the team-id of 190854187cc6Sbeveloper // the team that requested the instantiation. 19098b04ffc1Sbeveloper 191060f15390Sbeveloper TRACE("BMediaRosterEx::InstantiateDormantNode: addon-id %ld, flavor_id %ld\n", addonid, flavorid); 19118b04ffc1Sbeveloper 19128b04ffc1Sbeveloper // Get flavor_info from the server 19138b04ffc1Sbeveloper dormant_flavor_info node_info; 19148c6a6096Sbeveloper status_t rv; 19158b04ffc1Sbeveloper rv = GetDormantFlavorInfo(addonid, flavorid, &node_info); 19168b04ffc1Sbeveloper if (rv != B_OK) { 1917626824eaSbeveloper FATAL("BMediaRosterEx::InstantiateDormantNode error: failed to get dormant_flavor_info for addon-id %ld, flavor-id %ld\n", addonid, flavorid); 191852a38012Sejakowatz return B_ERROR; 191952a38012Sejakowatz } 19208b04ffc1Sbeveloper 19218b04ffc1Sbeveloper ASSERT(node_info.internal_id == flavorid); 19228b04ffc1Sbeveloper 19238b04ffc1Sbeveloper // load the BMediaAddOn object 19248b04ffc1Sbeveloper BMediaAddOn *addon; 19258b04ffc1Sbeveloper addon = _DormantNodeManager->GetAddon(addonid); 19268b04ffc1Sbeveloper if (!addon) { 19278b04ffc1Sbeveloper FATAL("BMediaRosterEx::InstantiateDormantNode: GetAddon failed\n"); 19288b04ffc1Sbeveloper return B_ERROR; 19298b04ffc1Sbeveloper } 19308b04ffc1Sbeveloper 193154187cc6Sbeveloper // Now we need to try to increment the use count of this addon flavor 193254187cc6Sbeveloper // in the server. This can fail if the total number instances of this 193354187cc6Sbeveloper // flavor is limited. 193473794717Sbeveloper rv = IncrementAddonFlavorInstancesCount(addonid, flavorid); 193554187cc6Sbeveloper if (rv != B_OK) { 1936626824eaSbeveloper FATAL("BMediaRosterEx::InstantiateDormantNode error: can't create more nodes for addon-id %ld, flavor-id %ld\n", addonid, flavorid); 193754187cc6Sbeveloper // Put the addon back into the pool 193854187cc6Sbeveloper _DormantNodeManager->PutAddon(addonid); 193954187cc6Sbeveloper return B_ERROR; 194054187cc6Sbeveloper } 194154187cc6Sbeveloper 19428b04ffc1Sbeveloper BMessage config; 194354187cc6Sbeveloper rv = LoadNodeConfiguration(addonid, flavorid, &config); 194454187cc6Sbeveloper if (rv != B_OK) { 194554187cc6Sbeveloper FATAL("BMediaRosterEx::InstantiateDormantNode: couldn't load configuration for addon-id %ld, flavor-id %ld\n", addonid, flavorid); 194654187cc6Sbeveloper // do not return, this is a minor problem, not a reason to fail 194754187cc6Sbeveloper } 19488b04ffc1Sbeveloper 19498b04ffc1Sbeveloper BMediaNode *node; 19508b04ffc1Sbeveloper status_t out_error; 19518b04ffc1Sbeveloper 195254187cc6Sbeveloper out_error = B_OK; 19538b04ffc1Sbeveloper node = addon->InstantiateNodeFor(&node_info, &config, &out_error); 195416b7eea4Sbeveloper if (!node) { 19558b04ffc1Sbeveloper FATAL("BMediaRosterEx::InstantiateDormantNode: InstantiateNodeFor failed\n"); 195654187cc6Sbeveloper // Put the addon back into the pool 19578b04ffc1Sbeveloper _DormantNodeManager->PutAddon(addonid); 195854187cc6Sbeveloper // We must decrement the use count of this addon flavor in the 195954187cc6Sbeveloper // server to compensate the increment done in the beginning. 196073794717Sbeveloper rv = DecrementAddonFlavorInstancesCount(addonid, flavorid); 196154187cc6Sbeveloper if (rv != B_OK) { 196273794717Sbeveloper FATAL("BMediaRosterEx::InstantiateDormantNode: DecrementAddonFlavorInstancesCount failed\n"); 196316b7eea4Sbeveloper } 196454187cc6Sbeveloper return (out_error != B_OK) ? out_error : B_ERROR; 196554187cc6Sbeveloper } 196654187cc6Sbeveloper 196754187cc6Sbeveloper rv = RegisterNode(node, addonid, flavorid); 19688c6a6096Sbeveloper if (rv != B_OK) { 19698b04ffc1Sbeveloper FATAL("BMediaRosterEx::InstantiateDormantNode: RegisterNode failed\n"); 19708c6a6096Sbeveloper delete node; 197154187cc6Sbeveloper // Put the addon back into the pool 19728b04ffc1Sbeveloper _DormantNodeManager->PutAddon(addonid); 197354187cc6Sbeveloper // We must decrement the use count of this addon flavor in the 197454187cc6Sbeveloper // server to compensate the increment done in the beginning. 197573794717Sbeveloper rv = DecrementAddonFlavorInstancesCount(addonid, flavorid); 197654187cc6Sbeveloper if (rv != B_OK) { 197773794717Sbeveloper FATAL("BMediaRosterEx::InstantiateDormantNode: DecrementAddonFlavorInstancesCount failed\n"); 197854187cc6Sbeveloper } 19798c6a6096Sbeveloper return B_ERROR; 19808c6a6096Sbeveloper } 19818c6a6096Sbeveloper 198254187cc6Sbeveloper if (creator != -1) { 198354187cc6Sbeveloper // send a message to the server to assign team "creator" as creator of node "node->ID()" 198454187cc6Sbeveloper printf("!!! BMediaRosterEx::InstantiateDormantNode assigning team %ld as creator of node %ld\n", creator, node->ID()); 198554187cc6Sbeveloper rv = MediaRosterEx(this)->SetNodeCreator(node->ID(), creator); 198654187cc6Sbeveloper if (rv != B_OK) { 198754187cc6Sbeveloper FATAL("BMediaRosterEx::InstantiateDormantNode failed to assign team %ld as creator of node %ld\n", creator, node->ID()); 198854187cc6Sbeveloper // do not return, this is a minor problem, not a reason to fail 198954187cc6Sbeveloper } 199054187cc6Sbeveloper } 199154187cc6Sbeveloper 199254187cc6Sbeveloper // RegisterNode() does remember the add-on id in the server 199354187cc6Sbeveloper // and UnregisterNode() will call DormantNodeManager::PutAddon() 199454187cc6Sbeveloper // when the node is unregistered. 19958c6a6096Sbeveloper 199616b7eea4Sbeveloper *out_node = node->Node(); 1997cf4e2277Sbeveloper 199860f15390Sbeveloper TRACE("BMediaRosterEx::InstantiateDormantNode: addon-id %ld, flavor_id %ld instanciated as node %ld, port %ld in team %ld\n", addonid, flavorid, out_node->node, out_node->port, team); 1999cf4e2277Sbeveloper 200016b7eea4Sbeveloper return B_OK; 200116b7eea4Sbeveloper } 200252a38012Sejakowatz 200352a38012Sejakowatz 200452a38012Sejakowatz status_t 20058b04ffc1Sbeveloper BMediaRoster::InstantiateDormantNode(const dormant_node_info & in_info, 20068b04ffc1Sbeveloper media_node * out_node, 20078b04ffc1Sbeveloper uint32 flags /* currently 0 or B_FLAVOR_IS_GLOBAL or B_FLAVOR_IS_LOCAL */ ) 20088b04ffc1Sbeveloper { 20098b04ffc1Sbeveloper CALLED(); 20108b04ffc1Sbeveloper if (out_node == 0) 20118b04ffc1Sbeveloper return B_BAD_VALUE; 20128b04ffc1Sbeveloper if (in_info.addon <= 0) { 20138b04ffc1Sbeveloper FATAL("BMediaRoster::InstantiateDormantNode error: addon-id %ld invalid.\n", in_info.addon); 20148b04ffc1Sbeveloper return B_BAD_VALUE; 20158b04ffc1Sbeveloper } 20168b04ffc1Sbeveloper 20178b04ffc1Sbeveloper printf("BMediaRoster::InstantiateDormantNode: addon-id %ld, flavor_id %ld, flags 0x%X\n", in_info.addon, in_info.flavor_id, flags); 20188b04ffc1Sbeveloper 20198b04ffc1Sbeveloper // Get flavor_info from the server 20208b04ffc1Sbeveloper // XXX this is a little overhead, as we get the full blown dormant_flavor_info, 20218b04ffc1Sbeveloper // XXX but only need the flags. 20228b04ffc1Sbeveloper dormant_flavor_info node_info; 20238b04ffc1Sbeveloper status_t rv; 20248b04ffc1Sbeveloper rv = MediaRosterEx(this)->GetDormantFlavorInfo(in_info.addon, in_info.flavor_id, &node_info); 20258b04ffc1Sbeveloper if (rv != B_OK) { 2026626824eaSbeveloper FATAL("BMediaRoster::InstantiateDormantNode error: failed to get dormant_flavor_info for addon-id %ld, flavor-id %ld\n", in_info.addon, in_info.flavor_id); 2027626824eaSbeveloper return B_NAME_NOT_FOUND; 20288b04ffc1Sbeveloper } 20298b04ffc1Sbeveloper 20308b04ffc1Sbeveloper ASSERT(node_info.internal_id == in_info.flavor_id); 20318b04ffc1Sbeveloper 20328b04ffc1Sbeveloper printf("BMediaRoster::InstantiateDormantNode: name \"%s\", info \"%s\", flavor_flags 0x%X, internal_id %ld, possible_count %ld\n", 20338b04ffc1Sbeveloper node_info.name, node_info.info, node_info.flavor_flags, node_info.internal_id, node_info.possible_count); 20348b04ffc1Sbeveloper 20358b04ffc1Sbeveloper #if DEBUG 20368b04ffc1Sbeveloper if (flags & B_FLAVOR_IS_LOCAL) 20378b04ffc1Sbeveloper printf("BMediaRoster::InstantiateDormantNode: caller requested B_FLAVOR_IS_LOCAL\n"); 20388b04ffc1Sbeveloper if (flags & B_FLAVOR_IS_GLOBAL) 20398b04ffc1Sbeveloper printf("BMediaRoster::InstantiateDormantNode: caller requested B_FLAVOR_IS_GLOBAL\n"); 20408b04ffc1Sbeveloper if (node_info.flavor_flags & B_FLAVOR_IS_LOCAL) 20418b04ffc1Sbeveloper printf("BMediaRoster::InstantiateDormantNode: node requires B_FLAVOR_IS_LOCAL\n"); 20428b04ffc1Sbeveloper if (node_info.flavor_flags & B_FLAVOR_IS_GLOBAL) 20438b04ffc1Sbeveloper printf("BMediaRoster::InstantiateDormantNode: node requires B_FLAVOR_IS_GLOBAL\n"); 20448b04ffc1Sbeveloper #endif 20458b04ffc1Sbeveloper 20468b04ffc1Sbeveloper // Make sure that flags demanded by the dormant node and those requested 20478b04ffc1Sbeveloper // by the caller are not incompatible. 20488b04ffc1Sbeveloper if ((node_info.flavor_flags & B_FLAVOR_IS_GLOBAL) && (flags & B_FLAVOR_IS_LOCAL)) { 20498b04ffc1Sbeveloper FATAL("BMediaRoster::InstantiateDormantNode Error: requested B_FLAVOR_IS_LOCAL, but dormant node has B_FLAVOR_IS_GLOBAL\n"); 2050626824eaSbeveloper return B_NAME_NOT_FOUND; 20518b04ffc1Sbeveloper } 20528b04ffc1Sbeveloper if ((node_info.flavor_flags & B_FLAVOR_IS_LOCAL) && (flags & B_FLAVOR_IS_GLOBAL)) { 20538b04ffc1Sbeveloper FATAL("BMediaRoster::InstantiateDormantNode Error: requested B_FLAVOR_IS_GLOBAL, but dormant node has B_FLAVOR_IS_LOCAL\n"); 2054626824eaSbeveloper return B_NAME_NOT_FOUND; 20558b04ffc1Sbeveloper } 205654187cc6Sbeveloper 20578b04ffc1Sbeveloper // If either the node, or the caller requested to make the instance global 20588b04ffc1Sbeveloper // we will do it by forwarding this request into the media_addon_server, which 20598b04ffc1Sbeveloper // in turn will call BMediaRosterEx::InstantiateDormantNode to create the node 20608b04ffc1Sbeveloper // there and make it globally available. 20618b04ffc1Sbeveloper if ((node_info.flavor_flags & B_FLAVOR_IS_GLOBAL) || (flags & B_FLAVOR_IS_GLOBAL)) { 20628b04ffc1Sbeveloper 2063cf4e2277Sbeveloper printf("BMediaRoster::InstantiateDormantNode: creating global object in media_addon_server\n"); 2064cf4e2277Sbeveloper 20658b04ffc1Sbeveloper addonserver_instantiate_dormant_node_request request; 20668b04ffc1Sbeveloper addonserver_instantiate_dormant_node_reply reply; 20678b04ffc1Sbeveloper request.addonid = in_info.addon; 20688b04ffc1Sbeveloper request.flavorid = in_info.flavor_id; 206954187cc6Sbeveloper request.creator_team = team; // creator team is allowed to also release global nodes 20708b04ffc1Sbeveloper rv = QueryAddonServer(ADDONSERVER_INSTANTIATE_DORMANT_NODE, &request, sizeof(request), &reply, sizeof(reply)); 20718b04ffc1Sbeveloper if (rv == B_OK) { 20728b04ffc1Sbeveloper *out_node = reply.node; 20738b04ffc1Sbeveloper } 20748b04ffc1Sbeveloper 20758b04ffc1Sbeveloper } else { 20768b04ffc1Sbeveloper 207754187cc6Sbeveloper // creator team = -1, as this is a local node 2078626824eaSbeveloper rv = MediaRosterEx(this)->InstantiateDormantNode(in_info.addon, in_info.flavor_id, -1, out_node); 2079626824eaSbeveloper 20808b04ffc1Sbeveloper } 2081626824eaSbeveloper if (rv != B_OK) { 2082626824eaSbeveloper *out_node = media_node::null; 2083626824eaSbeveloper return B_NAME_NOT_FOUND; 2084626824eaSbeveloper } 2085626824eaSbeveloper return B_OK; 20868b04ffc1Sbeveloper } 20878b04ffc1Sbeveloper 20888b04ffc1Sbeveloper 20898b04ffc1Sbeveloper status_t 20908b04ffc1Sbeveloper BMediaRoster::InstantiateDormantNode(const dormant_node_info & in_info, 20918b04ffc1Sbeveloper media_node * out_node) 20928b04ffc1Sbeveloper { 20938b04ffc1Sbeveloper return InstantiateDormantNode(in_info, out_node, 0); 20948b04ffc1Sbeveloper } 20958b04ffc1Sbeveloper 20968b04ffc1Sbeveloper 20978b04ffc1Sbeveloper status_t 209852a38012Sejakowatz BMediaRoster::GetDormantNodeFor(const media_node & node, 209952a38012Sejakowatz dormant_node_info * out_info) 210052a38012Sejakowatz { 210185dfab2bSbeveloper CALLED(); 210285dfab2bSbeveloper if (out_info == NULL) 210385dfab2bSbeveloper return B_BAD_VALUE; 210440f36b03Sbeveloper if (IS_INVALID_NODE(node)) 210585dfab2bSbeveloper return B_MEDIA_BAD_NODE; 210652a38012Sejakowatz 210785dfab2bSbeveloper server_get_dormant_node_for_request request; 210885dfab2bSbeveloper server_get_dormant_node_for_reply reply; 210985dfab2bSbeveloper status_t rv; 211085dfab2bSbeveloper 211185dfab2bSbeveloper request.node = node; 211285dfab2bSbeveloper 21131299bfb2Sbeveloper rv = QueryServer(SERVER_GET_DORMANT_NODE_FOR, &request, sizeof(request), &reply, sizeof(reply)); 211485dfab2bSbeveloper if (rv != B_OK) 211585dfab2bSbeveloper return rv; 211685dfab2bSbeveloper 211785dfab2bSbeveloper *out_info = reply.node_info; 211885dfab2bSbeveloper return B_OK; 211952a38012Sejakowatz } 212052a38012Sejakowatz 212152a38012Sejakowatz status_t 21228b04ffc1Sbeveloper BMediaRosterEx::GetDormantFlavorInfo(media_addon_id addonid, 21238b04ffc1Sbeveloper int32 flavorid, 212452a38012Sejakowatz dormant_flavor_info * out_flavor) 212552a38012Sejakowatz { 212652a38012Sejakowatz CALLED(); 212752a38012Sejakowatz 212852a38012Sejakowatz xfer_server_get_dormant_flavor_info msg; 212952a38012Sejakowatz xfer_server_get_dormant_flavor_info_reply *reply; 213052a38012Sejakowatz port_id port; 213152a38012Sejakowatz status_t rv; 213252a38012Sejakowatz int32 code; 213352a38012Sejakowatz 213452a38012Sejakowatz port = find_port("media_server port"); 213552a38012Sejakowatz if (port <= B_OK) 213652a38012Sejakowatz return B_ERROR; 213752a38012Sejakowatz 213852a38012Sejakowatz reply = (xfer_server_get_dormant_flavor_info_reply *) malloc(16000); 213952a38012Sejakowatz if (reply == 0) 214052a38012Sejakowatz return B_ERROR; 214152a38012Sejakowatz 21428b04ffc1Sbeveloper msg.addon = addonid; 21438b04ffc1Sbeveloper msg.flavor_id = flavorid; 214452a38012Sejakowatz msg.reply_port = _PortPool->GetPort(); 214552a38012Sejakowatz rv = write_port(port, SERVER_GET_DORMANT_FLAVOR_INFO, &msg, sizeof(msg)); 214652a38012Sejakowatz if (rv != B_OK) { 214752a38012Sejakowatz free(reply); 214852a38012Sejakowatz _PortPool->PutPort(msg.reply_port); 214952a38012Sejakowatz return rv; 215052a38012Sejakowatz } 215152a38012Sejakowatz rv = read_port(msg.reply_port, &code, reply, 16000); 215252a38012Sejakowatz _PortPool->PutPort(msg.reply_port); 215352a38012Sejakowatz 215452a38012Sejakowatz if (rv < B_OK) { 215552a38012Sejakowatz free(reply); 215652a38012Sejakowatz return rv; 215752a38012Sejakowatz } 215852a38012Sejakowatz 215952a38012Sejakowatz if (reply->result == B_OK) 216052a38012Sejakowatz rv = out_flavor->Unflatten(reply->dfi_type, &reply->dfi, reply->dfi_size); 216152a38012Sejakowatz else 216252a38012Sejakowatz rv = reply->result; 216352a38012Sejakowatz 216452a38012Sejakowatz free(reply); 216552a38012Sejakowatz return rv; 216652a38012Sejakowatz } 216752a38012Sejakowatz 21688b04ffc1Sbeveloper status_t 21698b04ffc1Sbeveloper BMediaRoster::GetDormantFlavorInfoFor(const dormant_node_info & in_dormant, 21708b04ffc1Sbeveloper dormant_flavor_info * out_flavor) 21718b04ffc1Sbeveloper { 21728b04ffc1Sbeveloper return MediaRosterEx(this)->GetDormantFlavorInfo(in_dormant.addon, in_dormant.flavor_id, out_flavor); 21738b04ffc1Sbeveloper } 217452a38012Sejakowatz 217560f15390Sbeveloper // Reports in outLatency the maximum latency found downstream from 217660f15390Sbeveloper // the specified BBufferProducer, producer, given the current connections. 217752a38012Sejakowatz status_t 217852a38012Sejakowatz BMediaRoster::GetLatencyFor(const media_node & producer, 217952a38012Sejakowatz bigtime_t * out_latency) 218052a38012Sejakowatz { 218160f15390Sbeveloper CALLED(); 218260f15390Sbeveloper if (out_latency == NULL) 218360f15390Sbeveloper return B_BAD_VALUE; 218460f15390Sbeveloper if (IS_INVALID_NODE(producer)) 218560f15390Sbeveloper return B_MEDIA_BAD_NODE; 218660f15390Sbeveloper if ((producer.kind & B_BUFFER_PRODUCER) == 0) 218760f15390Sbeveloper return B_MEDIA_BAD_NODE; 218860f15390Sbeveloper 218960f15390Sbeveloper producer_get_latency_request request; 219060f15390Sbeveloper producer_get_latency_reply reply; 219160f15390Sbeveloper status_t rv; 219260f15390Sbeveloper 219360f15390Sbeveloper rv = QueryPort(producer.port, PRODUCER_GET_LATENCY, &request, sizeof(request), &reply, sizeof(reply)); 219460f15390Sbeveloper if (rv != B_OK) 219560f15390Sbeveloper return rv; 219660f15390Sbeveloper 219760f15390Sbeveloper *out_latency = reply.latency; 219860f15390Sbeveloper 219960f15390Sbeveloper printf("BMediaRoster::GetLatencyFor producer %ld has maximum latency %Ld\n", producer.node, *out_latency); 2200aac800c2Sbeveloper return B_OK; 220152a38012Sejakowatz } 220252a38012Sejakowatz 220352a38012Sejakowatz 220452a38012Sejakowatz status_t 220552a38012Sejakowatz BMediaRoster::GetInitialLatencyFor(const media_node & producer, 220652a38012Sejakowatz bigtime_t * out_latency, 2207aac800c2Sbeveloper uint32 * out_flags /* = NULL */) 220852a38012Sejakowatz { 220952a38012Sejakowatz UNIMPLEMENTED(); 221060f15390Sbeveloper *out_latency = 5000; 2211aac800c2Sbeveloper if (out_flags) 221252a38012Sejakowatz *out_flags = 0; 2213aac800c2Sbeveloper return B_OK; 221452a38012Sejakowatz } 221552a38012Sejakowatz 221652a38012Sejakowatz 221752a38012Sejakowatz status_t 221852a38012Sejakowatz BMediaRoster::GetStartLatencyFor(const media_node & time_source, 221952a38012Sejakowatz bigtime_t * out_latency) 222052a38012Sejakowatz { 222152a38012Sejakowatz UNIMPLEMENTED(); 2222aac800c2Sbeveloper *out_latency = 5000; 2223aac800c2Sbeveloper return B_OK; 222452a38012Sejakowatz } 222552a38012Sejakowatz 222652a38012Sejakowatz 222752a38012Sejakowatz status_t 222852a38012Sejakowatz BMediaRoster::GetFileFormatsFor(const media_node & file_interface, 222952a38012Sejakowatz media_file_format * out_formats, 223052a38012Sejakowatz int32 * io_num_infos) 223152a38012Sejakowatz { 223252a38012Sejakowatz UNIMPLEMENTED(); 223352a38012Sejakowatz return B_ERROR; 223452a38012Sejakowatz } 223552a38012Sejakowatz 223652a38012Sejakowatz 223752a38012Sejakowatz status_t 223852a38012Sejakowatz BMediaRoster::SetRefFor(const media_node & file_interface, 223952a38012Sejakowatz const entry_ref & file, 224052a38012Sejakowatz bool create_and_truncate, 224152a38012Sejakowatz bigtime_t * out_length) /* if create is false */ 224252a38012Sejakowatz { 224352a38012Sejakowatz UNIMPLEMENTED(); 224452a38012Sejakowatz return B_ERROR; 224552a38012Sejakowatz } 224652a38012Sejakowatz 224752a38012Sejakowatz 224852a38012Sejakowatz status_t 224952a38012Sejakowatz BMediaRoster::GetRefFor(const media_node & node, 225052a38012Sejakowatz entry_ref * out_file, 225152a38012Sejakowatz BMimeType * mime_type) 225252a38012Sejakowatz { 225352a38012Sejakowatz UNIMPLEMENTED(); 225452a38012Sejakowatz return B_ERROR; 225552a38012Sejakowatz } 225652a38012Sejakowatz 225752a38012Sejakowatz 225852a38012Sejakowatz status_t 225952a38012Sejakowatz BMediaRoster::SniffRefFor(const media_node & file_interface, 226052a38012Sejakowatz const entry_ref & file, 226152a38012Sejakowatz BMimeType * mime_type, 226252a38012Sejakowatz float * out_capability) 226352a38012Sejakowatz { 226452a38012Sejakowatz UNIMPLEMENTED(); 226552a38012Sejakowatz return B_ERROR; 226652a38012Sejakowatz } 226752a38012Sejakowatz 226852a38012Sejakowatz 226952a38012Sejakowatz /* This is the generic "here's a file, now can someone please play it" interface */ 227052a38012Sejakowatz status_t 227152a38012Sejakowatz BMediaRoster::SniffRef(const entry_ref & file, 227252a38012Sejakowatz uint64 require_node_kinds, /* if you need an EntityInterface or BufferConsumer or something */ 227352a38012Sejakowatz dormant_node_info * out_node, 227452a38012Sejakowatz BMimeType * mime_type) 227552a38012Sejakowatz { 227652a38012Sejakowatz UNIMPLEMENTED(); 227752a38012Sejakowatz return B_ERROR; 227852a38012Sejakowatz } 227952a38012Sejakowatz 228052a38012Sejakowatz 228152a38012Sejakowatz status_t 228252a38012Sejakowatz BMediaRoster::GetDormantNodeForType(const BMimeType & type, 228352a38012Sejakowatz uint64 require_node_kinds, 228452a38012Sejakowatz dormant_node_info * out_node) 228552a38012Sejakowatz { 228652a38012Sejakowatz UNIMPLEMENTED(); 228752a38012Sejakowatz return B_ERROR; 228852a38012Sejakowatz } 228952a38012Sejakowatz 229052a38012Sejakowatz 229152a38012Sejakowatz status_t 229252a38012Sejakowatz BMediaRoster::GetReadFileFormatsFor(const dormant_node_info & in_node, 229352a38012Sejakowatz media_file_format * out_read_formats, 229452a38012Sejakowatz int32 in_read_count, 229552a38012Sejakowatz int32 * out_read_count) 229652a38012Sejakowatz { 229752a38012Sejakowatz UNIMPLEMENTED(); 229852a38012Sejakowatz return B_ERROR; 229952a38012Sejakowatz } 230052a38012Sejakowatz 230152a38012Sejakowatz 230252a38012Sejakowatz status_t 230352a38012Sejakowatz BMediaRoster::GetWriteFileFormatsFor(const dormant_node_info & in_node, 230452a38012Sejakowatz media_file_format * out_write_formats, 230552a38012Sejakowatz int32 in_write_count, 230652a38012Sejakowatz int32 * out_write_count) 230752a38012Sejakowatz { 230852a38012Sejakowatz UNIMPLEMENTED(); 230952a38012Sejakowatz return B_ERROR; 231052a38012Sejakowatz } 231152a38012Sejakowatz 231252a38012Sejakowatz 231352a38012Sejakowatz status_t 231452a38012Sejakowatz BMediaRoster::GetFormatFor(const media_output & output, 231552a38012Sejakowatz media_format * io_format, 231652a38012Sejakowatz uint32 flags) 231752a38012Sejakowatz { 231852a38012Sejakowatz UNIMPLEMENTED(); 231952a38012Sejakowatz return B_ERROR; 232052a38012Sejakowatz } 232152a38012Sejakowatz 232252a38012Sejakowatz 232352a38012Sejakowatz status_t 232452a38012Sejakowatz BMediaRoster::GetFormatFor(const media_input & input, 232552a38012Sejakowatz media_format * io_format, 232652a38012Sejakowatz uint32 flags) 232752a38012Sejakowatz { 232852a38012Sejakowatz UNIMPLEMENTED(); 232952a38012Sejakowatz return B_ERROR; 233052a38012Sejakowatz } 233152a38012Sejakowatz 233252a38012Sejakowatz 233352a38012Sejakowatz status_t 233452a38012Sejakowatz BMediaRoster::GetFormatFor(const media_node & node, 233552a38012Sejakowatz media_format * io_format, 233652a38012Sejakowatz float quality) 233752a38012Sejakowatz { 233852a38012Sejakowatz UNIMPLEMENTED(); 233952a38012Sejakowatz return B_ERROR; 234052a38012Sejakowatz } 234152a38012Sejakowatz 234252a38012Sejakowatz 234352a38012Sejakowatz ssize_t 234452a38012Sejakowatz BMediaRoster::GetNodeAttributesFor(const media_node & node, 234552a38012Sejakowatz media_node_attribute * outArray, 234652a38012Sejakowatz size_t inMaxCount) 234752a38012Sejakowatz { 234852a38012Sejakowatz UNIMPLEMENTED(); 234952a38012Sejakowatz return B_ERROR; 235052a38012Sejakowatz } 235152a38012Sejakowatz 235252a38012Sejakowatz 235352a38012Sejakowatz media_node_id 235452a38012Sejakowatz BMediaRoster::NodeIDFor(port_id source_or_destination_port) 235552a38012Sejakowatz { 23569e9417d2Sbeveloper CALLED(); 23579e9417d2Sbeveloper 23589e9417d2Sbeveloper server_node_id_for_request request; 23599e9417d2Sbeveloper server_node_id_for_reply reply; 23609e9417d2Sbeveloper status_t rv; 23619e9417d2Sbeveloper 23629e9417d2Sbeveloper request.port = source_or_destination_port; 23639e9417d2Sbeveloper 23649e9417d2Sbeveloper rv = QueryServer(SERVER_NODE_ID_FOR, &request, sizeof(request), &reply, sizeof(reply)); 23659e9417d2Sbeveloper if (rv != B_OK) { 2366353b9f6bSbeveloper FATAL("BMediaRoster::NodeIDFor: failed (error %#lx)\n", rv); 23679e9417d2Sbeveloper return -1; 23689e9417d2Sbeveloper } 23699e9417d2Sbeveloper 23709e9417d2Sbeveloper return reply.nodeid; 237152a38012Sejakowatz } 237252a38012Sejakowatz 237352a38012Sejakowatz 237452a38012Sejakowatz status_t 237552a38012Sejakowatz BMediaRoster::GetInstancesFor(media_addon_id addon, 237652a38012Sejakowatz int32 flavor, 237752a38012Sejakowatz media_node_id * out_id, 237852a38012Sejakowatz int32 * io_count) 237952a38012Sejakowatz { 238085dfab2bSbeveloper CALLED(); 238185dfab2bSbeveloper if (out_id == NULL || io_count == NULL) 238285dfab2bSbeveloper return B_BAD_VALUE; 238385dfab2bSbeveloper if (*io_count <= 0) 238485dfab2bSbeveloper return B_BAD_VALUE; 238585dfab2bSbeveloper 238685dfab2bSbeveloper server_get_instances_for_request request; 238785dfab2bSbeveloper server_get_instances_for_reply reply; 238885dfab2bSbeveloper status_t rv; 238985dfab2bSbeveloper 239085dfab2bSbeveloper request.maxcount = *io_count; 239185dfab2bSbeveloper request.addon_id = addon; 239285dfab2bSbeveloper request.addon_flavor_id = flavor; 239385dfab2bSbeveloper 239485dfab2bSbeveloper rv = QueryServer(SERVER_GET_INSTANCES_FOR, &request, sizeof(request), &reply, sizeof(reply)); 239585dfab2bSbeveloper if (rv != B_OK) { 2396353b9f6bSbeveloper FATAL("BMediaRoster::GetLiveNodes failed\n"); 239785dfab2bSbeveloper return rv; 239852a38012Sejakowatz } 239952a38012Sejakowatz 240085dfab2bSbeveloper *io_count = reply.count; 240185dfab2bSbeveloper if (reply.count > 0) 240285dfab2bSbeveloper memcpy(out_id, reply.node_id, sizeof(media_node_id) * reply.count); 240385dfab2bSbeveloper 240485dfab2bSbeveloper return B_OK; 240585dfab2bSbeveloper } 240652a38012Sejakowatz 240752a38012Sejakowatz 240852a38012Sejakowatz status_t 240952a38012Sejakowatz BMediaRoster::SetRealtimeFlags(uint32 in_enabled) 241052a38012Sejakowatz { 241152a38012Sejakowatz UNIMPLEMENTED(); 241252a38012Sejakowatz return B_ERROR; 241352a38012Sejakowatz } 241452a38012Sejakowatz 241552a38012Sejakowatz 241652a38012Sejakowatz status_t 241752a38012Sejakowatz BMediaRoster::GetRealtimeFlags(uint32 * out_enabled) 241852a38012Sejakowatz { 241952a38012Sejakowatz UNIMPLEMENTED(); 242052a38012Sejakowatz return B_ERROR; 242152a38012Sejakowatz } 242252a38012Sejakowatz 242352a38012Sejakowatz 242452a38012Sejakowatz ssize_t 242552a38012Sejakowatz BMediaRoster::AudioBufferSizeFor(int32 channel_count, 242652a38012Sejakowatz uint32 sample_format, 242752a38012Sejakowatz float frame_rate, 242852a38012Sejakowatz bus_type bus_kind) 242952a38012Sejakowatz { 243052a38012Sejakowatz UNIMPLEMENTED(); 243152a38012Sejakowatz return 4096; 243252a38012Sejakowatz } 243352a38012Sejakowatz 243452a38012Sejakowatz 243552a38012Sejakowatz /* Use MediaFlags to inquire about specific features of the Media Kit. */ 243652a38012Sejakowatz /* Returns < 0 for "not present", positive size for output data size. */ 243752a38012Sejakowatz /* 0 means that the capability is present, but no data about it. */ 243852a38012Sejakowatz /* static */ ssize_t 243952a38012Sejakowatz BMediaRoster::MediaFlags(media_flags cap, 244052a38012Sejakowatz void * buf, 244152a38012Sejakowatz size_t maxSize) 244252a38012Sejakowatz { 244352a38012Sejakowatz UNIMPLEMENTED(); 244452a38012Sejakowatz return 0; 244552a38012Sejakowatz } 244652a38012Sejakowatz 244752a38012Sejakowatz 244852a38012Sejakowatz /* BLooper overrides */ 244952a38012Sejakowatz /* virtual */ void 245052a38012Sejakowatz BMediaRoster::MessageReceived(BMessage * message) 245152a38012Sejakowatz { 2452cf4e2277Sbeveloper switch (message->what) { 2453cf4e2277Sbeveloper case 'PING': 2454cf4e2277Sbeveloper { 24556396865dSbeveloper // media_server plays ping-pong with the BMediaRosters 24566396865dSbeveloper // to detect dead teams. Normal communication uses ports. 24576396865dSbeveloper static BMessage pong('PONG'); 24586396865dSbeveloper message->SendReply(&pong, static_cast<BHandler *>(NULL), 2000000); 24596396865dSbeveloper return; 24606396865dSbeveloper } 24616396865dSbeveloper 2462*359ac306Sbeveloper case NODE_PUBLISH_CONNECTIONS: 2463*359ac306Sbeveloper { 2464*359ac306Sbeveloper const void *data; 2465*359ac306Sbeveloper ssize_t numBytes; 2466*359ac306Sbeveloper media_node node; 2467*359ac306Sbeveloper 2468*359ac306Sbeveloper printf("NODE_PUBLISH_CONNECTIONS enter\n"); 2469*359ac306Sbeveloper 2470*359ac306Sbeveloper message->FindData("node", B_RAW_TYPE, &data, &numBytes); 2471*359ac306Sbeveloper node = *(const media_node *)data; 2472*359ac306Sbeveloper 2473*359ac306Sbeveloper // register existing inputs and outputs with the 2474*359ac306Sbeveloper // media_server, this allows GetLiveNodes() to work 2475*359ac306Sbeveloper // with created, but unconnected nodes. 2476*359ac306Sbeveloper if (node.kind & B_BUFFER_PRODUCER) { 2477*359ac306Sbeveloper List<media_output> outputlist; 2478*359ac306Sbeveloper if (B_OK == MediaRosterEx(this)->GetAllOutputs(node, &outputlist)) 2479*359ac306Sbeveloper MediaRosterEx(this)->PublishOutputs(node, &outputlist); 2480*359ac306Sbeveloper } else if (node.kind & B_BUFFER_CONSUMER) { 2481*359ac306Sbeveloper List<media_input> inputlist; 2482*359ac306Sbeveloper if (B_OK == MediaRosterEx(this)->GetAllInputs(node, &inputlist)) 2483*359ac306Sbeveloper MediaRosterEx(this)->PublishInputs(node, &inputlist); 2484*359ac306Sbeveloper } 2485*359ac306Sbeveloper printf("NODE_PUBLISH_CONNECTIONS leave\n"); 2486*359ac306Sbeveloper return; 2487*359ac306Sbeveloper } 2488*359ac306Sbeveloper 2489cf4e2277Sbeveloper case NODE_FINAL_RELEASE: 2490cf4e2277Sbeveloper { 2491cf4e2277Sbeveloper // this function is called by a BMediaNode to delete 2492cf4e2277Sbeveloper // itself, as this needs to be done from another thread 2493cf4e2277Sbeveloper // context, it is done here. 2494cf4e2277Sbeveloper // XXX If a node is released using BMediaRoster::ReleaseNode() 2495cf4e2277Sbeveloper // XXX instead of using BMediaNode::Release() / BMediaNode::Acquire() 2496cf4e2277Sbeveloper // XXX fRefCount of the BMediaNode will not be correct. 2497cf4e2277Sbeveloper 2498cf4e2277Sbeveloper BMediaNode *node; 2499cf4e2277Sbeveloper message->FindPointer("node", reinterpret_cast<void **>(&node)); 2500cf4e2277Sbeveloper 250154187cc6Sbeveloper TRACE("BMediaRoster::MessageReceived NODE_FINAL_RELEASE saving node %ld configuration\n", node->ID()); 250254187cc6Sbeveloper MediaRosterEx(BMediaRoster::Roster())->SaveNodeConfiguration(node); 2503cf4e2277Sbeveloper 250454187cc6Sbeveloper TRACE("BMediaRoster::MessageReceived NODE_FINAL_RELEASE releasing node %ld\n", node->ID()); 2505cf4e2277Sbeveloper node->DeleteHook(node); // we don't call Release(), see above! 2506cf4e2277Sbeveloper return; 2507cf4e2277Sbeveloper } 2508cf4e2277Sbeveloper } 25096396865dSbeveloper printf("BMediaRoster::MessageReceived: unknown message!\n"); 25106396865dSbeveloper message->PrintToStream(); 251152a38012Sejakowatz } 251252a38012Sejakowatz 251352a38012Sejakowatz /* virtual */ bool 251452a38012Sejakowatz BMediaRoster::QuitRequested() 251552a38012Sejakowatz { 251652a38012Sejakowatz UNIMPLEMENTED(); 251752a38012Sejakowatz return true; 251852a38012Sejakowatz } 251952a38012Sejakowatz 252052a38012Sejakowatz /* virtual */ BHandler * 252152a38012Sejakowatz BMediaRoster::ResolveSpecifier(BMessage *msg, 252252a38012Sejakowatz int32 index, 252352a38012Sejakowatz BMessage *specifier, 252452a38012Sejakowatz int32 form, 252552a38012Sejakowatz const char *property) 252652a38012Sejakowatz { 252752a38012Sejakowatz UNIMPLEMENTED(); 252852a38012Sejakowatz return 0; 252952a38012Sejakowatz } 253052a38012Sejakowatz 253152a38012Sejakowatz 253252a38012Sejakowatz /* virtual */ status_t 253352a38012Sejakowatz BMediaRoster::GetSupportedSuites(BMessage *data) 253452a38012Sejakowatz { 253552a38012Sejakowatz UNIMPLEMENTED(); 253652a38012Sejakowatz return B_ERROR; 253752a38012Sejakowatz } 253852a38012Sejakowatz 253952a38012Sejakowatz 254052a38012Sejakowatz BMediaRoster::~BMediaRoster() 254152a38012Sejakowatz { 254252a38012Sejakowatz CALLED(); 25436396865dSbeveloper 25446396865dSbeveloper // unregister this application with the media server 25456396865dSbeveloper server_unregister_app_request request; 25466396865dSbeveloper server_unregister_app_reply reply; 25476396865dSbeveloper request.team = team; 25486396865dSbeveloper QueryServer(SERVER_UNREGISTER_APP, &request, sizeof(request), &reply, sizeof(reply)); 254952a38012Sejakowatz } 255052a38012Sejakowatz 255152a38012Sejakowatz 255252a38012Sejakowatz /************************************************************* 255352a38012Sejakowatz * private BMediaRoster 255452a38012Sejakowatz *************************************************************/ 255552a38012Sejakowatz 255652a38012Sejakowatz // deprecated call 255752a38012Sejakowatz status_t 255852a38012Sejakowatz BMediaRoster::SetOutputBuffersFor(const media_source & output, 255952a38012Sejakowatz BBufferGroup * group, 256052a38012Sejakowatz bool will_reclaim ) 256152a38012Sejakowatz { 256252a38012Sejakowatz UNIMPLEMENTED(); 25639e9417d2Sbeveloper debugger("BMediaRoster::SetOutputBuffersFor missing\n"); 256452a38012Sejakowatz return B_ERROR; 256552a38012Sejakowatz } 256652a38012Sejakowatz 256752a38012Sejakowatz 256852a38012Sejakowatz /* FBC stuffing (Mmmh, Stuffing!) */ 256952a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_0(void *) { return B_ERROR; } 257052a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_1(void *) { return B_ERROR; } 257152a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_2(void *) { return B_ERROR; } 257252a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_3(void *) { return B_ERROR; } 257352a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_4(void *) { return B_ERROR; } 257452a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_5(void *) { return B_ERROR; } 257552a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_6(void *) { return B_ERROR; } 257652a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_7(void *) { return B_ERROR; } 257752a38012Sejakowatz 257852a38012Sejakowatz 257952a38012Sejakowatz BMediaRoster::BMediaRoster() : 25806396865dSbeveloper BLooper("_BMediaRoster_", B_URGENT_DISPLAY_PRIORITY, B_LOOPER_PORT_DEFAULT_CAPACITY) 258152a38012Sejakowatz { 258252a38012Sejakowatz CALLED(); 25836396865dSbeveloper 25846396865dSbeveloper // start the looper 25856396865dSbeveloper Run(); 25866396865dSbeveloper 25876396865dSbeveloper // register this application with the media server 25886396865dSbeveloper server_register_app_request request; 25896396865dSbeveloper server_register_app_reply reply; 25906396865dSbeveloper request.team = team; 25916396865dSbeveloper request.messenger = BMessenger(NULL, this); 25926396865dSbeveloper QueryServer(SERVER_REGISTER_APP, &request, sizeof(request), &reply, sizeof(reply)); 259352a38012Sejakowatz } 259452a38012Sejakowatz 25956396865dSbeveloper 259652a38012Sejakowatz /* static */ status_t 259752a38012Sejakowatz BMediaRoster::ParseCommand(BMessage & reply) 259852a38012Sejakowatz { 259952a38012Sejakowatz UNIMPLEMENTED(); 260052a38012Sejakowatz return B_ERROR; 260152a38012Sejakowatz } 260252a38012Sejakowatz 260352a38012Sejakowatz 260452a38012Sejakowatz status_t 260552a38012Sejakowatz BMediaRoster::GetDefaultInfo(media_node_id for_default, 260652a38012Sejakowatz BMessage & out_config) 260752a38012Sejakowatz { 260852a38012Sejakowatz UNIMPLEMENTED(); 260952a38012Sejakowatz return B_ERROR; 261052a38012Sejakowatz } 261152a38012Sejakowatz 261252a38012Sejakowatz 261352a38012Sejakowatz 261452a38012Sejakowatz status_t 261552a38012Sejakowatz BMediaRoster::SetRunningDefault(media_node_id for_default, 261652a38012Sejakowatz const media_node & node) 261752a38012Sejakowatz { 261852a38012Sejakowatz UNIMPLEMENTED(); 261952a38012Sejakowatz return B_ERROR; 262052a38012Sejakowatz } 262152a38012Sejakowatz 262252a38012Sejakowatz 262352a38012Sejakowatz /************************************************************* 262452a38012Sejakowatz * static BMediaRoster variables 262552a38012Sejakowatz *************************************************************/ 262652a38012Sejakowatz 262752a38012Sejakowatz bool BMediaRoster::_isMediaServer; 262852a38012Sejakowatz port_id BMediaRoster::_mReplyPort; 262952a38012Sejakowatz int32 BMediaRoster::_mReplyPortRes; 263052a38012Sejakowatz int32 BMediaRoster::_mReplyPortUnavailCount; 263152a38012Sejakowatz BMediaRoster * BMediaRoster::_sDefault = NULL; 263252a38012Sejakowatz 2633