1255a01c7Sbeveloper /* 265b73ae4SMarcus Overhagen * Copyright (c) 2002-2006 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 */ 3165b73ae4SMarcus Overhagen char __dont_remove_copyright_from_binary[] = "Copyright (c) 2002-2006 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> 424d2d96e0Sbeveloper #include <BufferProducer.h> 434d2d96e0Sbeveloper #include <BufferConsumer.h> 4452a38012Sejakowatz #include "debug.h" 458b04ffc1Sbeveloper #include "MediaRosterEx.h" 4640f36b03Sbeveloper #include "MediaMisc.h" 4752a38012Sejakowatz #include "PortPool.h" 480a483e72SIngo Weinhold #include "ServerInterface.h" 49f4925104Sbeveloper #include "DataExchange.h" 5016b7eea4Sbeveloper #include "DormantNodeManager.h" 51f4925104Sbeveloper #include "Notifications.h" 52835140c8Sbeveloper #include "TimeSourceObjectManager.h" 5352a38012Sejakowatz 54f4925104Sbeveloper namespace BPrivate { namespace media { 5552a38012Sejakowatz 5652a38012Sejakowatz // the BMediaRoster destructor is private, 5752a38012Sejakowatz // but _DefaultDeleter is a friend class of 5852a38012Sejakowatz // the BMediaRoster an thus can delete it 598b04ffc1Sbeveloper class DefaultDeleter 6052a38012Sejakowatz { 6152a38012Sejakowatz public: 628b04ffc1Sbeveloper ~DefaultDeleter() 636396865dSbeveloper { 646396865dSbeveloper if (BMediaRoster::_sDefault) { 656396865dSbeveloper BMediaRoster::_sDefault->Lock(); 666396865dSbeveloper BMediaRoster::_sDefault->Quit(); 676396865dSbeveloper } 686396865dSbeveloper } 698b04ffc1Sbeveloper }; 7052a38012Sejakowatz 718b04ffc1Sbeveloper } } // BPrivate::media 728b04ffc1Sbeveloper using namespace BPrivate::media; 7352a38012Sejakowatz 748b04ffc1Sbeveloper // DefaultDeleter will delete the BMediaRoster object in it's destructor. 758b04ffc1Sbeveloper DefaultDeleter _deleter; 7652a38012Sejakowatz 77dcfb6bfcSJérôme Duval BMediaRosterEx::BMediaRosterEx(status_t * out_error) 78dcfb6bfcSJérôme Duval : BMediaRoster() 79dcfb6bfcSJérôme Duval { 80dcfb6bfcSJérôme Duval status_t rv; 81dcfb6bfcSJérôme Duval // register this application with the media server 82dcfb6bfcSJérôme Duval server_register_app_request request; 83dcfb6bfcSJérôme Duval server_register_app_reply reply; 84dcfb6bfcSJérôme Duval request.team = team; 85dcfb6bfcSJérôme Duval request.messenger = BMessenger(NULL, this); 86dcfb6bfcSJérôme Duval rv = QueryServer(SERVER_REGISTER_APP, &request, sizeof(request), &reply, sizeof(reply)); 878496c38aSbeveloper *out_error = (rv != B_OK) ? B_MEDIA_SYSTEM_FAILURE : B_OK; 88dcfb6bfcSJérôme Duval } 89dcfb6bfcSJérôme Duval 903620737cSbeveloper status_t 9154187cc6Sbeveloper BMediaRosterEx::SaveNodeConfiguration(BMediaNode *node) 9254187cc6Sbeveloper { 9354187cc6Sbeveloper BMediaAddOn *addon; 9454187cc6Sbeveloper media_addon_id addonid; 9554187cc6Sbeveloper int32 flavorid; 9654187cc6Sbeveloper addon = node->AddOn(&flavorid); 9754187cc6Sbeveloper if (!addon) { 9860f15390Sbeveloper // XXX this check incorrectly triggers on BeOS R5 BT848 node 995ac4fbd7Sbeveloper ERROR("BMediaRosterEx::SaveNodeConfiguration node %ld not instantiated from BMediaAddOn!\n", node->ID()); 10054187cc6Sbeveloper return B_ERROR; 10154187cc6Sbeveloper } 10254187cc6Sbeveloper addonid = addon->AddonID(); 10354187cc6Sbeveloper 10454187cc6Sbeveloper // XXX fix this 10554187cc6Sbeveloper printf("### BMediaRosterEx::SaveNodeConfiguration should save addon-id %ld, flavor-id %ld config NOW!\n", addonid, flavorid); 10654187cc6Sbeveloper return B_OK; 10754187cc6Sbeveloper } 10854187cc6Sbeveloper 10954187cc6Sbeveloper status_t 11054187cc6Sbeveloper BMediaRosterEx::LoadNodeConfiguration(media_addon_id addonid, int32 flavorid, BMessage *out_msg) 11154187cc6Sbeveloper { 11254187cc6Sbeveloper // XXX fix this 11354187cc6Sbeveloper out_msg->MakeEmpty(); // to be fully R5 compliant 11454187cc6Sbeveloper printf("### BMediaRosterEx::LoadNodeConfiguration should load addon-id %ld, flavor-id %ld config NOW!\n", addonid, flavorid); 11554187cc6Sbeveloper return B_OK; 11654187cc6Sbeveloper } 11754187cc6Sbeveloper 11854187cc6Sbeveloper status_t 11973794717Sbeveloper BMediaRosterEx::IncrementAddonFlavorInstancesCount(media_addon_id addonid, int32 flavorid) 12054187cc6Sbeveloper { 12173794717Sbeveloper server_change_addon_flavor_instances_count_request request; 12273794717Sbeveloper server_change_addon_flavor_instances_count_reply reply; 12373794717Sbeveloper 12473794717Sbeveloper request.addonid = addonid; 12573794717Sbeveloper request.flavorid = flavorid; 12673794717Sbeveloper request.delta = 1; 12773794717Sbeveloper request.team = team; 12873794717Sbeveloper return QueryServer(SERVER_CHANGE_ADDON_FLAVOR_INSTANCES_COUNT, &request, sizeof(request), &reply, sizeof(reply)); 12954187cc6Sbeveloper } 13054187cc6Sbeveloper 13154187cc6Sbeveloper status_t 13273794717Sbeveloper BMediaRosterEx::DecrementAddonFlavorInstancesCount(media_addon_id addonid, int32 flavorid) 13354187cc6Sbeveloper { 13473794717Sbeveloper server_change_addon_flavor_instances_count_request request; 13573794717Sbeveloper server_change_addon_flavor_instances_count_reply reply; 13673794717Sbeveloper 13773794717Sbeveloper request.addonid = addonid; 13873794717Sbeveloper request.flavorid = flavorid; 13973794717Sbeveloper request.delta = -1; 14073794717Sbeveloper request.team = team; 14173794717Sbeveloper return QueryServer(SERVER_CHANGE_ADDON_FLAVOR_INSTANCES_COUNT, &request, sizeof(request), &reply, sizeof(reply)); 14254187cc6Sbeveloper } 14354187cc6Sbeveloper 14454187cc6Sbeveloper status_t 14554187cc6Sbeveloper BMediaRosterEx::SetNodeCreator(media_node_id node, team_id creator) 14654187cc6Sbeveloper { 14754187cc6Sbeveloper server_set_node_creator_request request; 14854187cc6Sbeveloper server_set_node_creator_reply reply; 14954187cc6Sbeveloper 15054187cc6Sbeveloper request.node = node; 15154187cc6Sbeveloper request.creator = creator; 15254187cc6Sbeveloper return QueryServer(SERVER_SET_NODE_CREATOR, &request, sizeof(request), &reply, sizeof(reply)); 15354187cc6Sbeveloper } 15454187cc6Sbeveloper 15554187cc6Sbeveloper status_t 1568b04ffc1Sbeveloper BMediaRosterEx::GetNode(node_type type, media_node * out_node, int32 * out_input_id, BString * out_input_name) 15752a38012Sejakowatz { 15852a38012Sejakowatz if (out_node == NULL) 15952a38012Sejakowatz return B_BAD_VALUE; 16052a38012Sejakowatz 1618c6a6096Sbeveloper server_get_node_request request; 1628c6a6096Sbeveloper server_get_node_reply reply; 16352a38012Sejakowatz status_t rv; 16452a38012Sejakowatz 1658c6a6096Sbeveloper request.type = type; 1669e9417d2Sbeveloper request.team = team; 1678c6a6096Sbeveloper rv = QueryServer(SERVER_GET_NODE, &request, sizeof(request), &reply, sizeof(reply)); 1688c6a6096Sbeveloper if (rv != B_OK) 1698c6a6096Sbeveloper return rv; 17052a38012Sejakowatz 17152a38012Sejakowatz *out_node = reply.node; 17252a38012Sejakowatz if (out_input_id) 17352a38012Sejakowatz *out_input_id = reply.input_id; 17452a38012Sejakowatz if (out_input_name) 17552a38012Sejakowatz *out_input_name = reply.input_name; 1768c6a6096Sbeveloper return rv; 17752a38012Sejakowatz } 17852a38012Sejakowatz 1793620737cSbeveloper status_t 1808b04ffc1Sbeveloper BMediaRosterEx::SetNode(node_type type, const media_node *node, const dormant_node_info *info, const media_input *input) 18152a38012Sejakowatz { 1828c6a6096Sbeveloper server_set_node_request request; 1838c6a6096Sbeveloper server_set_node_reply reply; 18452a38012Sejakowatz 1858c6a6096Sbeveloper request.type = type; 1868c6a6096Sbeveloper request.use_node = node ? true : false; 18752a38012Sejakowatz if (node) 1888c6a6096Sbeveloper request.node = *node; 1898c6a6096Sbeveloper request.use_dni = info ? true : false; 19052a38012Sejakowatz if (info) 1918c6a6096Sbeveloper request.dni = *info; 1928c6a6096Sbeveloper request.use_input = input ? true : false; 19352a38012Sejakowatz if (input) 1948c6a6096Sbeveloper request.input = *input; 19552a38012Sejakowatz 1968c6a6096Sbeveloper return QueryServer(SERVER_SET_NODE, &request, sizeof(request), &reply, sizeof(reply)); 19752a38012Sejakowatz } 19852a38012Sejakowatz 1993620737cSbeveloper status_t 2008b04ffc1Sbeveloper BMediaRosterEx::GetAllOutputs(const media_node & node, List<media_output> *list) 2013620737cSbeveloper { 2023620737cSbeveloper int32 cookie; 2033620737cSbeveloper status_t rv; 2043620737cSbeveloper status_t result; 2053620737cSbeveloper 2065ac4fbd7Sbeveloper PRINT(4, "BMediaRosterEx::GetAllOutputs() node %ld, port %ld\n", node.node, node.port); 2075ac4fbd7Sbeveloper 20865b73ae4SMarcus Overhagen if (!(node.kind & B_BUFFER_PRODUCER)) { 20965b73ae4SMarcus Overhagen ERROR("BMediaRosterEx::GetAllOutputs: node %ld is not a B_BUFFER_PRODUCER\n", node.node); 21065b73ae4SMarcus Overhagen return B_MEDIA_BAD_NODE; 21165b73ae4SMarcus Overhagen } 21265b73ae4SMarcus Overhagen 2133620737cSbeveloper result = B_OK; 2143620737cSbeveloper cookie = 0; 21576669a29Sbeveloper list->MakeEmpty(); 2163620737cSbeveloper for (;;) { 2173620737cSbeveloper producer_get_next_output_request request; 2183620737cSbeveloper producer_get_next_output_reply reply; 2193620737cSbeveloper request.cookie = cookie; 2200caff283Sbeveloper rv = QueryPort(node.port, PRODUCER_GET_NEXT_OUTPUT, &request, sizeof(request), &reply, sizeof(reply)); 2213620737cSbeveloper if (rv != B_OK) 2223620737cSbeveloper break; 2233620737cSbeveloper cookie = reply.cookie; 22476669a29Sbeveloper if (!list->Insert(reply.output)) { 2255ac4fbd7Sbeveloper ERROR("GetAllOutputs: list->Insert failed\n"); 2263620737cSbeveloper result = B_ERROR; 2273620737cSbeveloper } 2285ac4fbd7Sbeveloper #if DEBUG >= 3 2295ac4fbd7Sbeveloper PRINT(3," next cookie %ld, ", cookie); 2305ac4fbd7Sbeveloper PRINT_OUTPUT("output ", reply.output); 2315ac4fbd7Sbeveloper #endif 2323620737cSbeveloper } 2333620737cSbeveloper 2343620737cSbeveloper producer_dispose_output_cookie_request request; 2353620737cSbeveloper producer_dispose_output_cookie_reply reply; 2360caff283Sbeveloper QueryPort(node.port, PRODUCER_DISPOSE_OUTPUT_COOKIE, &request, sizeof(request), &reply, sizeof(reply)); 2373620737cSbeveloper 2383620737cSbeveloper return result; 2393620737cSbeveloper } 2403620737cSbeveloper 2413620737cSbeveloper status_t 2424d2d96e0Sbeveloper BMediaRosterEx::GetAllOutputs(BBufferProducer *node, List<media_output> *list) 2434d2d96e0Sbeveloper { 2444d2d96e0Sbeveloper int32 cookie; 2454d2d96e0Sbeveloper status_t result; 2464d2d96e0Sbeveloper 2474d2d96e0Sbeveloper PRINT(4, "BMediaRosterEx::GetAllOutputs() (by pointer) node %ld, port %ld\n", node->ID(), node->ControlPort()); 2484d2d96e0Sbeveloper 2494d2d96e0Sbeveloper result = B_OK; 2504d2d96e0Sbeveloper cookie = 0; 2514d2d96e0Sbeveloper list->MakeEmpty(); 2524d2d96e0Sbeveloper for (;;) { 2534d2d96e0Sbeveloper media_output output; 2544d2d96e0Sbeveloper if (B_OK != node->GetNextOutput(&cookie, &output)) 2554d2d96e0Sbeveloper break; 2564d2d96e0Sbeveloper if (!list->Insert(output)) { 2574d2d96e0Sbeveloper ERROR("GetAllOutputs: list->Insert failed\n"); 2584d2d96e0Sbeveloper result = B_ERROR; 2594d2d96e0Sbeveloper } 2604d2d96e0Sbeveloper #if DEBUG >= 3 2614d2d96e0Sbeveloper PRINT(3," next cookie %ld, ", cookie); 2624d2d96e0Sbeveloper PRINT_OUTPUT("output ", output); 2634d2d96e0Sbeveloper #endif 2644d2d96e0Sbeveloper } 2654d2d96e0Sbeveloper node->DisposeOutputCookie(cookie); 2664d2d96e0Sbeveloper return result; 2674d2d96e0Sbeveloper } 2684d2d96e0Sbeveloper 2694d2d96e0Sbeveloper status_t 2708b04ffc1Sbeveloper BMediaRosterEx::GetAllInputs(const media_node & node, List<media_input> *list) 2713620737cSbeveloper { 2723620737cSbeveloper int32 cookie; 2733620737cSbeveloper status_t rv; 2743620737cSbeveloper status_t result; 2753620737cSbeveloper 2765ac4fbd7Sbeveloper PRINT(4, "BMediaRosterEx::GetAllInputs() node %ld, port %ld\n", node.node, node.port); 2775ac4fbd7Sbeveloper 27865b73ae4SMarcus Overhagen if (!(node.kind & B_BUFFER_CONSUMER)) { 27965b73ae4SMarcus Overhagen ERROR("BMediaRosterEx::GetAllInputs: node %ld is not a B_BUFFER_CONSUMER\n", node.node); 28065b73ae4SMarcus Overhagen return B_MEDIA_BAD_NODE; 28165b73ae4SMarcus Overhagen } 28265b73ae4SMarcus Overhagen 2833620737cSbeveloper result = B_OK; 2843620737cSbeveloper cookie = 0; 28576669a29Sbeveloper list->MakeEmpty(); 2863620737cSbeveloper for (;;) { 2873620737cSbeveloper consumer_get_next_input_request request; 2883620737cSbeveloper consumer_get_next_input_reply reply; 2893620737cSbeveloper request.cookie = cookie; 2900caff283Sbeveloper rv = QueryPort(node.port, CONSUMER_GET_NEXT_INPUT, &request, sizeof(request), &reply, sizeof(reply)); 2913620737cSbeveloper if (rv != B_OK) 2923620737cSbeveloper break; 2933620737cSbeveloper cookie = reply.cookie; 29476669a29Sbeveloper if (!list->Insert(reply.input)) { 2955ac4fbd7Sbeveloper ERROR("GetAllInputs: list->Insert failed\n"); 2963620737cSbeveloper result = B_ERROR; 2973620737cSbeveloper } 2985ac4fbd7Sbeveloper #if DEBUG >= 3 2995ac4fbd7Sbeveloper PRINT(3," next cookie %ld, ", cookie); 3005ac4fbd7Sbeveloper PRINT_OUTPUT("input ", reply.input); 3015ac4fbd7Sbeveloper #endif 3023620737cSbeveloper } 3033620737cSbeveloper 3043620737cSbeveloper consumer_dispose_input_cookie_request request; 3053620737cSbeveloper consumer_dispose_input_cookie_reply reply; 3060caff283Sbeveloper QueryPort(node.port, CONSUMER_DISPOSE_INPUT_COOKIE, &request, sizeof(request), &reply, sizeof(reply)); 3073620737cSbeveloper 3083620737cSbeveloper return result; 3093620737cSbeveloper } 3103620737cSbeveloper 3113620737cSbeveloper status_t 3124d2d96e0Sbeveloper BMediaRosterEx::GetAllInputs(BBufferConsumer *node, List<media_input> *list) 3134d2d96e0Sbeveloper { 3144d2d96e0Sbeveloper int32 cookie; 3154d2d96e0Sbeveloper status_t result; 3164d2d96e0Sbeveloper 3174d2d96e0Sbeveloper PRINT(4, "BMediaRosterEx::GetAllInputs() (by pointer) node %ld, port %ld\n", node->ID(), node->ControlPort()); 3184d2d96e0Sbeveloper 3194d2d96e0Sbeveloper result = B_OK; 3204d2d96e0Sbeveloper cookie = 0; 3214d2d96e0Sbeveloper list->MakeEmpty(); 3224d2d96e0Sbeveloper for (;;) { 3234d2d96e0Sbeveloper media_input input; 3244d2d96e0Sbeveloper if (B_OK != node->GetNextInput(&cookie, &input)) 3254d2d96e0Sbeveloper break; 3264d2d96e0Sbeveloper if (!list->Insert(input)) { 3274d2d96e0Sbeveloper ERROR("GetAllInputs: list->Insert failed\n"); 3284d2d96e0Sbeveloper result = B_ERROR; 3294d2d96e0Sbeveloper } 3304d2d96e0Sbeveloper #if DEBUG >= 3 3314d2d96e0Sbeveloper PRINT(3," next cookie %ld, ", cookie); 3324d2d96e0Sbeveloper PRINT_INPUT("input ", input); 3334d2d96e0Sbeveloper #endif 3344d2d96e0Sbeveloper } 3354d2d96e0Sbeveloper node->DisposeInputCookie(cookie); 3364d2d96e0Sbeveloper return result; 3374d2d96e0Sbeveloper } 3384d2d96e0Sbeveloper 3394d2d96e0Sbeveloper status_t 3408b04ffc1Sbeveloper BMediaRosterEx::PublishOutputs(const media_node & node, List<media_output> *list) 3413620737cSbeveloper { 3423620737cSbeveloper server_publish_outputs_request request; 3433620737cSbeveloper server_publish_outputs_reply reply; 3443620737cSbeveloper media_output *output; 3453620737cSbeveloper media_output *outputs; 3463620737cSbeveloper int32 count; 347a7b41a96Sbeveloper status_t rv; 3483620737cSbeveloper 34976669a29Sbeveloper count = list->CountItems(); 3503620737cSbeveloper TRACE("PublishOutputs: publishing %ld\n", count); 3513620737cSbeveloper 3523620737cSbeveloper request.node = node; 3533620737cSbeveloper request.count = count; 3543620737cSbeveloper if (count > MAX_OUTPUTS) { 3553620737cSbeveloper void *start_addr; 3563620737cSbeveloper size_t size; 35740f36b03Sbeveloper size = ROUND_UP_TO_PAGE(count * sizeof(media_output)); 3583620737cSbeveloper request.area = create_area("publish outputs", &start_addr, B_ANY_ADDRESS, size, B_NO_LOCK, B_READ_AREA | B_WRITE_AREA); 3593620737cSbeveloper if (request.area < B_OK) { 3605ac4fbd7Sbeveloper ERROR("PublishOutputs: failed to create area, %#lx\n", request.area); 3613620737cSbeveloper return (status_t)request.area; 3623620737cSbeveloper } 3633620737cSbeveloper outputs = static_cast<media_output *>(start_addr); 3643620737cSbeveloper } else { 3653620737cSbeveloper request.area = -1; 3663620737cSbeveloper outputs = request.outputs; 3673620737cSbeveloper } 36876669a29Sbeveloper TRACE("PublishOutputs: area %ld\n", request.area); 3693620737cSbeveloper 37076669a29Sbeveloper int i; 37176669a29Sbeveloper for (i = 0, list->Rewind(); list->GetNext(&output); i++) { 37276669a29Sbeveloper ASSERT(i < count); 3733620737cSbeveloper outputs[i] = *output; 3743620737cSbeveloper } 3753620737cSbeveloper 376a7b41a96Sbeveloper rv = QueryServer(SERVER_PUBLISH_OUTPUTS, &request, sizeof(request), &reply, sizeof(reply)); 377a7b41a96Sbeveloper 378a7b41a96Sbeveloper if (request.area != -1) 379a7b41a96Sbeveloper delete_area(request.area); 380a7b41a96Sbeveloper 381a7b41a96Sbeveloper return rv; 3823620737cSbeveloper } 3833620737cSbeveloper 3843620737cSbeveloper status_t 3858b04ffc1Sbeveloper BMediaRosterEx::PublishInputs(const media_node & node, List<media_input> *list) 3863620737cSbeveloper { 3873620737cSbeveloper server_publish_inputs_request request; 3883620737cSbeveloper server_publish_inputs_reply reply; 3893620737cSbeveloper media_input *input; 3903620737cSbeveloper media_input *inputs; 3913620737cSbeveloper int32 count; 392a7b41a96Sbeveloper status_t rv; 3933620737cSbeveloper 39476669a29Sbeveloper count = list->CountItems(); 3953620737cSbeveloper TRACE("PublishInputs: publishing %ld\n", count); 3963620737cSbeveloper 3973620737cSbeveloper request.node = node; 3983620737cSbeveloper request.count = count; 3993620737cSbeveloper if (count > MAX_INPUTS) { 4003620737cSbeveloper void *start_addr; 4013620737cSbeveloper size_t size; 40240f36b03Sbeveloper size = ROUND_UP_TO_PAGE(count * sizeof(media_input)); 4033620737cSbeveloper request.area = create_area("publish inputs", &start_addr, B_ANY_ADDRESS, size, B_NO_LOCK, B_READ_AREA | B_WRITE_AREA); 4043620737cSbeveloper if (request.area < B_OK) { 4055ac4fbd7Sbeveloper ERROR("PublishInputs: failed to create area, %#lx\n", request.area); 4063620737cSbeveloper return (status_t)request.area; 4073620737cSbeveloper } 4083620737cSbeveloper inputs = static_cast<media_input *>(start_addr); 4093620737cSbeveloper } else { 4103620737cSbeveloper request.area = -1; 4113620737cSbeveloper inputs = request.inputs; 4123620737cSbeveloper } 41376669a29Sbeveloper TRACE("PublishInputs: area %ld\n", request.area); 4143620737cSbeveloper 41576669a29Sbeveloper int i; 41676669a29Sbeveloper for (i = 0, list->Rewind(); list->GetNext(&input); i++) { 41776669a29Sbeveloper ASSERT(i < count); 4183620737cSbeveloper inputs[i] = *input; 4193620737cSbeveloper } 4203620737cSbeveloper 421a7b41a96Sbeveloper rv = QueryServer(SERVER_PUBLISH_INPUTS, &request, sizeof(request), &reply, sizeof(reply)); 422a7b41a96Sbeveloper 423a7b41a96Sbeveloper if (request.area != -1) 424a7b41a96Sbeveloper delete_area(request.area); 425a7b41a96Sbeveloper 426a7b41a96Sbeveloper return rv; 4273620737cSbeveloper } 4283620737cSbeveloper 42952a38012Sejakowatz /************************************************************* 43052a38012Sejakowatz * public BMediaRoster 43152a38012Sejakowatz *************************************************************/ 43252a38012Sejakowatz 43352a38012Sejakowatz status_t 43452a38012Sejakowatz BMediaRoster::GetVideoInput(media_node * out_node) 43552a38012Sejakowatz { 43652a38012Sejakowatz CALLED(); 4378b04ffc1Sbeveloper return MediaRosterEx(this)->GetNode(VIDEO_INPUT, out_node); 43852a38012Sejakowatz } 43952a38012Sejakowatz 44052a38012Sejakowatz 44152a38012Sejakowatz status_t 44252a38012Sejakowatz BMediaRoster::GetAudioInput(media_node * out_node) 44352a38012Sejakowatz { 44452a38012Sejakowatz CALLED(); 4458b04ffc1Sbeveloper return MediaRosterEx(this)->GetNode(AUDIO_INPUT, out_node); 44652a38012Sejakowatz } 44752a38012Sejakowatz 44852a38012Sejakowatz 44952a38012Sejakowatz status_t 45052a38012Sejakowatz BMediaRoster::GetVideoOutput(media_node * out_node) 45152a38012Sejakowatz { 45252a38012Sejakowatz CALLED(); 4538b04ffc1Sbeveloper return MediaRosterEx(this)->GetNode(VIDEO_OUTPUT, out_node); 45452a38012Sejakowatz } 45552a38012Sejakowatz 45652a38012Sejakowatz 45752a38012Sejakowatz status_t 45852a38012Sejakowatz BMediaRoster::GetAudioMixer(media_node * out_node) 45952a38012Sejakowatz { 46052a38012Sejakowatz CALLED(); 4618b04ffc1Sbeveloper return MediaRosterEx(this)->GetNode(AUDIO_MIXER, out_node); 46252a38012Sejakowatz } 46352a38012Sejakowatz 46452a38012Sejakowatz 46552a38012Sejakowatz status_t 46652a38012Sejakowatz BMediaRoster::GetAudioOutput(media_node * out_node) 46752a38012Sejakowatz { 46852a38012Sejakowatz CALLED(); 4698b04ffc1Sbeveloper return MediaRosterEx(this)->GetNode(AUDIO_OUTPUT, out_node); 47052a38012Sejakowatz } 47152a38012Sejakowatz 47252a38012Sejakowatz 47352a38012Sejakowatz status_t 47452a38012Sejakowatz BMediaRoster::GetAudioOutput(media_node * out_node, 47552a38012Sejakowatz int32 * out_input_id, 47652a38012Sejakowatz BString * out_input_name) 47752a38012Sejakowatz { 47852a38012Sejakowatz CALLED(); 4798b04ffc1Sbeveloper return MediaRosterEx(this)->GetNode(AUDIO_OUTPUT_EX, out_node, out_input_id, out_input_name); 48052a38012Sejakowatz } 48152a38012Sejakowatz 48252a38012Sejakowatz 48352a38012Sejakowatz status_t 48452a38012Sejakowatz BMediaRoster::GetTimeSource(media_node * out_node) 48552a38012Sejakowatz { 48652a38012Sejakowatz CALLED(); 48786bce45bSbeveloper status_t rv; 48886bce45bSbeveloper 48986bce45bSbeveloper // XXX need to do this in a nicer way. 49086bce45bSbeveloper 49186bce45bSbeveloper rv = MediaRosterEx(this)->GetNode(TIME_SOURCE, out_node); 49286bce45bSbeveloper if (rv != B_OK) 49386bce45bSbeveloper return rv; 49486bce45bSbeveloper 49586bce45bSbeveloper // We don't do reference counting for timesources, that's why we 49686bce45bSbeveloper // release the node immediately. 49786bce45bSbeveloper ReleaseNode(*out_node); 49886bce45bSbeveloper 49986bce45bSbeveloper // we need to remember to not use this node with server side reference counting 50086bce45bSbeveloper out_node->kind |= NODE_KIND_NO_REFCOUNTING; 50186bce45bSbeveloper 50286bce45bSbeveloper return B_OK; 50352a38012Sejakowatz } 50452a38012Sejakowatz 50552a38012Sejakowatz 50652a38012Sejakowatz status_t 50752a38012Sejakowatz BMediaRoster::SetVideoInput(const media_node & producer) 50852a38012Sejakowatz { 50952a38012Sejakowatz CALLED(); 5108b04ffc1Sbeveloper return MediaRosterEx(this)->SetNode(VIDEO_INPUT, &producer); 51152a38012Sejakowatz } 51252a38012Sejakowatz 51352a38012Sejakowatz 51452a38012Sejakowatz status_t 51552a38012Sejakowatz BMediaRoster::SetVideoInput(const dormant_node_info & producer) 51652a38012Sejakowatz { 51752a38012Sejakowatz CALLED(); 5188b04ffc1Sbeveloper return MediaRosterEx(this)->SetNode(VIDEO_INPUT, NULL, &producer); 51952a38012Sejakowatz } 52052a38012Sejakowatz 52152a38012Sejakowatz 52252a38012Sejakowatz status_t 52352a38012Sejakowatz BMediaRoster::SetAudioInput(const media_node & producer) 52452a38012Sejakowatz { 52552a38012Sejakowatz CALLED(); 5268b04ffc1Sbeveloper return MediaRosterEx(this)->SetNode(AUDIO_INPUT, &producer); 52752a38012Sejakowatz } 52852a38012Sejakowatz 52952a38012Sejakowatz 53052a38012Sejakowatz status_t 53152a38012Sejakowatz BMediaRoster::SetAudioInput(const dormant_node_info & producer) 53252a38012Sejakowatz { 53352a38012Sejakowatz CALLED(); 5348b04ffc1Sbeveloper return MediaRosterEx(this)->SetNode(AUDIO_INPUT, NULL, &producer); 53552a38012Sejakowatz } 53652a38012Sejakowatz 53752a38012Sejakowatz 53852a38012Sejakowatz status_t 53952a38012Sejakowatz BMediaRoster::SetVideoOutput(const media_node & consumer) 54052a38012Sejakowatz { 54152a38012Sejakowatz CALLED(); 5428b04ffc1Sbeveloper return MediaRosterEx(this)->SetNode(VIDEO_OUTPUT, &consumer); 54352a38012Sejakowatz } 54452a38012Sejakowatz 54552a38012Sejakowatz 54652a38012Sejakowatz status_t 54752a38012Sejakowatz BMediaRoster::SetVideoOutput(const dormant_node_info & consumer) 54852a38012Sejakowatz { 54952a38012Sejakowatz CALLED(); 5508b04ffc1Sbeveloper return MediaRosterEx(this)->SetNode(VIDEO_OUTPUT, NULL, &consumer); 55152a38012Sejakowatz } 55252a38012Sejakowatz 55352a38012Sejakowatz 55452a38012Sejakowatz status_t 55552a38012Sejakowatz BMediaRoster::SetAudioOutput(const media_node & consumer) 55652a38012Sejakowatz { 55752a38012Sejakowatz CALLED(); 5588b04ffc1Sbeveloper return MediaRosterEx(this)->SetNode(AUDIO_OUTPUT, &consumer); 55952a38012Sejakowatz } 56052a38012Sejakowatz 56152a38012Sejakowatz 56252a38012Sejakowatz status_t 56352a38012Sejakowatz BMediaRoster::SetAudioOutput(const media_input & input_to_output) 56452a38012Sejakowatz { 56552a38012Sejakowatz CALLED(); 5668b04ffc1Sbeveloper return MediaRosterEx(this)->SetNode(AUDIO_OUTPUT, NULL, NULL, &input_to_output); 56752a38012Sejakowatz } 56852a38012Sejakowatz 56952a38012Sejakowatz 57052a38012Sejakowatz status_t 57152a38012Sejakowatz BMediaRoster::SetAudioOutput(const dormant_node_info & consumer) 57252a38012Sejakowatz { 57352a38012Sejakowatz CALLED(); 5748b04ffc1Sbeveloper return MediaRosterEx(this)->SetNode(AUDIO_OUTPUT, NULL, &consumer); 57552a38012Sejakowatz } 57652a38012Sejakowatz 57752a38012Sejakowatz 57852a38012Sejakowatz status_t 57952a38012Sejakowatz BMediaRoster::GetNodeFor(media_node_id node, 58052a38012Sejakowatz media_node * clone) 58152a38012Sejakowatz { 5829e9417d2Sbeveloper CALLED(); 5839e9417d2Sbeveloper if (clone == NULL) 5849e9417d2Sbeveloper return B_BAD_VALUE; 58565b73ae4SMarcus Overhagen if (IS_INVALID_NODEID(node)) 5869e9417d2Sbeveloper return B_MEDIA_BAD_NODE; 5879e9417d2Sbeveloper 5889e9417d2Sbeveloper server_get_node_for_request request; 5899e9417d2Sbeveloper server_get_node_for_reply reply; 5909e9417d2Sbeveloper status_t rv; 5919e9417d2Sbeveloper 5929e9417d2Sbeveloper request.nodeid = node; 5939e9417d2Sbeveloper request.team = team; 5949e9417d2Sbeveloper 5959e9417d2Sbeveloper rv = QueryServer(SERVER_GET_NODE_FOR, &request, sizeof(request), &reply, sizeof(reply)); 5969e9417d2Sbeveloper if (rv != B_OK) 5979e9417d2Sbeveloper return rv; 5989e9417d2Sbeveloper 5999e9417d2Sbeveloper *clone = reply.clone; 6009e9417d2Sbeveloper return B_OK; 60152a38012Sejakowatz } 60252a38012Sejakowatz 60352a38012Sejakowatz 60452a38012Sejakowatz status_t 60552a38012Sejakowatz BMediaRoster::GetSystemTimeSource(media_node * clone) 60652a38012Sejakowatz { 60752a38012Sejakowatz CALLED(); 60886bce45bSbeveloper status_t rv; 60986bce45bSbeveloper 61086bce45bSbeveloper // XXX need to do this in a nicer way. 61186bce45bSbeveloper 61286bce45bSbeveloper rv = MediaRosterEx(this)->GetNode(SYSTEM_TIME_SOURCE, clone); 61386bce45bSbeveloper if (rv != B_OK) 61486bce45bSbeveloper return rv; 61586bce45bSbeveloper 61686bce45bSbeveloper // We don't do reference counting for timesources, that's why we 61786bce45bSbeveloper // release the node immediately. 61886bce45bSbeveloper ReleaseNode(*clone); 61986bce45bSbeveloper 62086bce45bSbeveloper // we need to remember to not use this node with server side reference counting 62186bce45bSbeveloper clone->kind |= NODE_KIND_NO_REFCOUNTING; 62286bce45bSbeveloper 62386bce45bSbeveloper return B_OK; 62452a38012Sejakowatz } 62552a38012Sejakowatz 62652a38012Sejakowatz 62752a38012Sejakowatz status_t 62852a38012Sejakowatz BMediaRoster::ReleaseNode(const media_node & node) 62952a38012Sejakowatz { 6309e9417d2Sbeveloper CALLED(); 63140f36b03Sbeveloper if (IS_INVALID_NODE(node)) 6329e9417d2Sbeveloper return B_MEDIA_BAD_NODE; 63352a38012Sejakowatz 63486bce45bSbeveloper if (node.kind & NODE_KIND_NO_REFCOUNTING) { 63586bce45bSbeveloper printf("BMediaRoster::ReleaseNode, trying to release reference counting disabled timesource, node %ld, port %ld, team %ld\n", node.node, node.port, team); 63686bce45bSbeveloper return B_OK; 63786bce45bSbeveloper } 63886bce45bSbeveloper 6399e9417d2Sbeveloper server_release_node_request request; 6409e9417d2Sbeveloper server_release_node_reply reply; 641cf4e2277Sbeveloper status_t rv; 6429e9417d2Sbeveloper 6439e9417d2Sbeveloper request.node = node; 6449e9417d2Sbeveloper request.team = team; 6459e9417d2Sbeveloper 64660f15390Sbeveloper TRACE("BMediaRoster::ReleaseNode, node %ld, port %ld, team %ld\n", node.node, node.port, team); 647cf4e2277Sbeveloper 648cf4e2277Sbeveloper rv = QueryServer(SERVER_RELEASE_NODE, &request, sizeof(request), &reply, sizeof(reply)); 649cf4e2277Sbeveloper if (rv != B_OK) { 6505ac4fbd7Sbeveloper ERROR("BMediaRoster::ReleaseNode FAILED, node %ld, port %ld, team %ld!\n", node.node, node.port, team); 651cf4e2277Sbeveloper } 652cf4e2277Sbeveloper return rv; 6539e9417d2Sbeveloper } 65452a38012Sejakowatz 65552a38012Sejakowatz BTimeSource * 65652a38012Sejakowatz BMediaRoster::MakeTimeSourceFor(const media_node & for_node) 65752a38012Sejakowatz { 658f180ef79Sbeveloper // MakeTimeSourceFor() returns a BTimeSource object 659f180ef79Sbeveloper // corresponding to the specified node's time source. 660f180ef79Sbeveloper 661835140c8Sbeveloper CALLED(); 662f180ef79Sbeveloper 66392e575c1Sbeveloper if (IS_SYSTEM_TIMESOURCE(for_node)) { 664f180ef79Sbeveloper // special handling for the system time source 665f180ef79Sbeveloper TRACE("BMediaRoster::MakeTimeSourceFor, asked for system time source\n"); 666f180ef79Sbeveloper return MediaRosterEx(this)->MakeTimeSourceObject(NODE_SYSTEM_TIMESOURCE_ID); 667f180ef79Sbeveloper } 668f180ef79Sbeveloper 6695917dd5bSbeveloper if (IS_INVALID_NODE(for_node)) { 6705ac4fbd7Sbeveloper ERROR("BMediaRoster::MakeTimeSourceFor: for_node invalid, node %ld, port %ld, kinds 0x%lx\n", for_node.node, for_node.port, for_node.kind); 6715917dd5bSbeveloper return NULL; 6720e21b167Sbeveloper } 6730e21b167Sbeveloper 674f180ef79Sbeveloper TRACE("BMediaRoster::MakeTimeSourceFor: node %ld enter\n", for_node.node); 6755917dd5bSbeveloper 6765917dd5bSbeveloper node_get_timesource_request request; 6775917dd5bSbeveloper node_get_timesource_reply reply; 6785917dd5bSbeveloper BTimeSource *source; 6795917dd5bSbeveloper status_t rv; 6805917dd5bSbeveloper 68192e575c1Sbeveloper // ask the node to get it's current timesource id 6825917dd5bSbeveloper rv = QueryPort(for_node.port, NODE_GET_TIMESOURCE, &request, sizeof(request), &reply, sizeof(reply)); 6835917dd5bSbeveloper if (rv != B_OK) { 6845ac4fbd7Sbeveloper ERROR("BMediaRoster::MakeTimeSourceFor: request failed\n"); 6855917dd5bSbeveloper return NULL; 6865917dd5bSbeveloper } 6875917dd5bSbeveloper 6885917dd5bSbeveloper source = MediaRosterEx(this)->MakeTimeSourceObject(reply.timesource_id); 6895917dd5bSbeveloper 690f180ef79Sbeveloper TRACE("BMediaRoster::MakeTimeSourceFor: node %ld leave\n", for_node.node); 6915917dd5bSbeveloper 6925917dd5bSbeveloper return source; 6935917dd5bSbeveloper } 6945917dd5bSbeveloper 6955917dd5bSbeveloper BTimeSource * 6965917dd5bSbeveloper BMediaRosterEx::MakeTimeSourceObject(media_node_id timesource_id) 6975917dd5bSbeveloper { 6985917dd5bSbeveloper BTimeSource *source; 6995917dd5bSbeveloper media_node clone; 7005917dd5bSbeveloper status_t rv; 7015917dd5bSbeveloper 7025917dd5bSbeveloper rv = GetNodeFor(timesource_id, &clone); 7035917dd5bSbeveloper if (rv != B_OK) { 7045ac4fbd7Sbeveloper ERROR("BMediaRosterEx::MakeTimeSourceObject: GetNodeFor failed\n"); 7055917dd5bSbeveloper return NULL; 7065917dd5bSbeveloper } 7075917dd5bSbeveloper 7085917dd5bSbeveloper source = _TimeSourceObjectManager->GetTimeSource(clone); 7095917dd5bSbeveloper if (source == NULL) { 7105ac4fbd7Sbeveloper ERROR("BMediaRosterEx::MakeTimeSourceObject: GetTimeSource failed\n"); 7115917dd5bSbeveloper return NULL; 7125917dd5bSbeveloper } 7135917dd5bSbeveloper 71492e575c1Sbeveloper // XXX release? 71592e575c1Sbeveloper ReleaseNode(clone); 716287f7492Sbeveloper 717835140c8Sbeveloper return source; 71852a38012Sejakowatz } 71952a38012Sejakowatz 72052a38012Sejakowatz 72152a38012Sejakowatz status_t 72252a38012Sejakowatz BMediaRoster::Connect(const media_source & from, 72352a38012Sejakowatz const media_destination & to, 72452a38012Sejakowatz media_format * io_format, 72552a38012Sejakowatz media_output * out_output, 72652a38012Sejakowatz media_input * out_input) 72752a38012Sejakowatz { 728eae26d3dSbeveloper return BMediaRoster::Connect(from, to, io_format, out_output, out_input, 0); 729eae26d3dSbeveloper } 730eae26d3dSbeveloper 731eae26d3dSbeveloper 732eae26d3dSbeveloper status_t 733eae26d3dSbeveloper BMediaRoster::Connect(const media_source & from, 734eae26d3dSbeveloper const media_destination & to, 735eae26d3dSbeveloper media_format * io_format, 736eae26d3dSbeveloper media_output * out_output, 737eae26d3dSbeveloper media_input * out_input, 738eae26d3dSbeveloper uint32 in_flags, 739eae26d3dSbeveloper void * _reserved) 740eae26d3dSbeveloper { 74152a38012Sejakowatz CALLED(); 74252a38012Sejakowatz if (io_format == NULL || out_output == NULL || out_input == NULL) 74352a38012Sejakowatz return B_BAD_VALUE; 74440f36b03Sbeveloper if (IS_INVALID_SOURCE(from)) { 7455ac4fbd7Sbeveloper ERROR("BMediaRoster::Connect: media_source invalid\n"); 74652a38012Sejakowatz return B_MEDIA_BAD_SOURCE; 7479e9417d2Sbeveloper } 74840f36b03Sbeveloper if (IS_INVALID_DESTINATION(to)) { 7495ac4fbd7Sbeveloper ERROR("BMediaRoster::Connect: media_destination invalid\n"); 75052a38012Sejakowatz return B_MEDIA_BAD_DESTINATION; 7519e9417d2Sbeveloper } 75252a38012Sejakowatz 75352a38012Sejakowatz status_t rv; 75465b73ae4SMarcus Overhagen 75565b73ae4SMarcus Overhagen // find the output and input nodes 75665b73ae4SMarcus Overhagen // XXX isn't there a easier way? 75765b73ae4SMarcus Overhagen media_node sourcenode; 75865b73ae4SMarcus Overhagen media_node destnode; 75965b73ae4SMarcus Overhagen rv = GetNodeFor(NodeIDFor(from.port), &sourcenode); 76065b73ae4SMarcus Overhagen if (rv != B_OK) { 76165b73ae4SMarcus Overhagen ERROR("BMediaRoster::Connect: Can't find source node for port %ld\n", from.port); 76265b73ae4SMarcus Overhagen return B_MEDIA_BAD_SOURCE; 76365b73ae4SMarcus Overhagen } 76465b73ae4SMarcus Overhagen ReleaseNode(sourcenode); 76565b73ae4SMarcus Overhagen rv = GetNodeFor(NodeIDFor(to.port), &destnode); 76665b73ae4SMarcus Overhagen if (rv != B_OK) { 76765b73ae4SMarcus Overhagen ERROR("BMediaRoster::Connect: Can't find destination node for port %ld\n", to.port); 76865b73ae4SMarcus Overhagen return B_MEDIA_BAD_DESTINATION; 76965b73ae4SMarcus Overhagen } 77065b73ae4SMarcus Overhagen ReleaseNode(destnode); 77165b73ae4SMarcus Overhagen 77265b73ae4SMarcus Overhagen if (!(sourcenode.kind & B_BUFFER_PRODUCER)) { 77365b73ae4SMarcus Overhagen ERROR("BMediaRoster::Connect: source node %ld is not a B_BUFFER_PRODUCER\n", sourcenode.node); 77465b73ae4SMarcus Overhagen return B_MEDIA_BAD_SOURCE; 77565b73ae4SMarcus Overhagen } 77665b73ae4SMarcus Overhagen if (!(destnode.kind & B_BUFFER_CONSUMER)) { 77765b73ae4SMarcus Overhagen ERROR("BMediaRoster::Connect: destination node %ld is not a B_BUFFER_CONSUMER\n", destnode.node); 77865b73ae4SMarcus Overhagen return B_MEDIA_BAD_DESTINATION; 77965b73ae4SMarcus Overhagen } 78065b73ae4SMarcus Overhagen 7818c6a6096Sbeveloper producer_format_proposal_request request1; 7828c6a6096Sbeveloper producer_format_proposal_reply reply1; 78352a38012Sejakowatz 78469983609Sbeveloper PRINT_FORMAT("BMediaRoster::Connect calling BBufferProducer::FormatProposal with format ", *io_format); 78569983609Sbeveloper 78652a38012Sejakowatz // BBufferProducer::FormatProposal 7878c6a6096Sbeveloper request1.output = from; 7888c6a6096Sbeveloper request1.format = *io_format; 7898c6a6096Sbeveloper rv = QueryPort(from.port, PRODUCER_FORMAT_PROPOSAL, &request1, sizeof(request1), &reply1, sizeof(reply1)); 7908c6a6096Sbeveloper if (rv != B_OK) { 7915ac4fbd7Sbeveloper ERROR("BMediaRoster::Connect: aborted after BBufferProducer::FormatProposal, status = %#lx\n",rv); 79252a38012Sejakowatz return rv; 79352a38012Sejakowatz } 7948c6a6096Sbeveloper // reply1.format now contains the format proposed by the producer 7958c6a6096Sbeveloper 7968c6a6096Sbeveloper consumer_accept_format_request request2; 7978c6a6096Sbeveloper consumer_accept_format_reply reply2; 7988c6a6096Sbeveloper 79969983609Sbeveloper PRINT_FORMAT("BMediaRoster::Connect calling BBufferConsumer::AcceptFormat with format ", reply1.format); 80069983609Sbeveloper 8018c6a6096Sbeveloper // BBufferConsumer::AcceptFormat 8028c6a6096Sbeveloper request2.dest = to; 8038c6a6096Sbeveloper request2.format = reply1.format; 8048c6a6096Sbeveloper rv = QueryPort(to.port, CONSUMER_ACCEPT_FORMAT, &request2, sizeof(request2), &reply2, sizeof(reply2)); 8058c6a6096Sbeveloper if (rv != B_OK) { 8065ac4fbd7Sbeveloper ERROR("BMediaRoster::Connect: aborted after BBufferConsumer::AcceptFormat, status = %#lx\n",rv); 8078c6a6096Sbeveloper return rv; 8088c6a6096Sbeveloper } 8098c6a6096Sbeveloper // reply2.format now contains the format accepted by the consumer 8108c6a6096Sbeveloper 8118c6a6096Sbeveloper // BBufferProducer::PrepareToConnect 8128c6a6096Sbeveloper producer_prepare_to_connect_request request3; 8138c6a6096Sbeveloper producer_prepare_to_connect_reply reply3; 8148c6a6096Sbeveloper 81569983609Sbeveloper PRINT_FORMAT("BMediaRoster::Connect calling BBufferProducer::PrepareToConnect with format", reply2.format); 81669983609Sbeveloper 8178c6a6096Sbeveloper request3.source = from; 8188c6a6096Sbeveloper request3.destination = to; 8198c6a6096Sbeveloper request3.format = reply2.format; 8208c6a6096Sbeveloper strcpy(request3.name, "XXX some default name"); // XXX fix this 8218c6a6096Sbeveloper rv = QueryPort(from.port, PRODUCER_PREPARE_TO_CONNECT, &request3, sizeof(request3), &reply3, sizeof(reply3)); 8228c6a6096Sbeveloper if (rv != B_OK) { 8235ac4fbd7Sbeveloper ERROR("BMediaRoster::Connect: aborted after BBufferProducer::PrepareToConnect, status = %#lx\n",rv); 8248c6a6096Sbeveloper return rv; 8258c6a6096Sbeveloper } 8268c6a6096Sbeveloper // reply3.format is still our pretty media format 8278c6a6096Sbeveloper // reply3.out_source the real source to be used for the connection 8288c6a6096Sbeveloper // reply3.name the name BBufferConsumer::Connected will see in the outInput->name argument 8298c6a6096Sbeveloper 8308c6a6096Sbeveloper // BBufferConsumer::Connected 8318c6a6096Sbeveloper consumer_connected_request request4; 8328c6a6096Sbeveloper consumer_connected_reply reply4; 8338c6a6096Sbeveloper status_t con_status; 8348c6a6096Sbeveloper 83569983609Sbeveloper PRINT_FORMAT("BMediaRoster::Connect calling BBufferConsumer::Connected with format ", reply3.format); 83669983609Sbeveloper 83769983609Sbeveloper request4.input.node = destnode; 83869983609Sbeveloper request4.input.source = reply3.out_source; 83969983609Sbeveloper request4.input.destination = to; 84069983609Sbeveloper request4.input.format = reply3.format; 84169983609Sbeveloper strcpy(request4.input.name, reply3.name); 84269983609Sbeveloper 8438c6a6096Sbeveloper con_status = QueryPort(to.port, CONSUMER_CONNECTED, &request4, sizeof(request4), &reply4, sizeof(reply4)); 8448c6a6096Sbeveloper if (con_status != B_OK) { 8455ac4fbd7Sbeveloper ERROR("BMediaRoster::Connect: aborting after BBufferConsumer::Connected, status = %#lx\n",con_status); 8468c6a6096Sbeveloper // we do NOT return here! 8478c6a6096Sbeveloper } 8488c6a6096Sbeveloper // con_status contains the status code to be supplied to BBufferProducer::Connect's status argument 8498c6a6096Sbeveloper // reply4.input contains the media_input that describes the connection from the consumer point of view 8508c6a6096Sbeveloper 8518c6a6096Sbeveloper // BBufferProducer::Connect 8528c6a6096Sbeveloper producer_connect_request request5; 8538c6a6096Sbeveloper producer_connect_reply reply5; 8548c6a6096Sbeveloper 85569983609Sbeveloper PRINT_FORMAT("BMediaRoster::Connect calling BBufferProducer::Connect with format ", reply4.input.format); 85669983609Sbeveloper 8578c6a6096Sbeveloper request5.error = con_status; 8588c6a6096Sbeveloper request5.source = reply3.out_source; 8598c6a6096Sbeveloper request5.destination = reply4.input.destination; 86069983609Sbeveloper request5.format = reply4.input.format; 8618c6a6096Sbeveloper strcpy(request5.name, reply4.input.name); 8620caff283Sbeveloper rv = QueryPort(reply4.input.source.port, PRODUCER_CONNECT, &request5, sizeof(request5), &reply5, sizeof(reply5)); 8638c6a6096Sbeveloper if (con_status != B_OK) { 8645ac4fbd7Sbeveloper ERROR("BMediaRoster::Connect: aborted\n"); 8658c6a6096Sbeveloper return con_status; 8668c6a6096Sbeveloper } 8678c6a6096Sbeveloper if (rv != B_OK) { 8685ac4fbd7Sbeveloper ERROR("BMediaRoster::Connect: aborted after BBufferProducer::Connect, status = %#lx\n",rv); 8698c6a6096Sbeveloper return rv; 8708c6a6096Sbeveloper } 8718c6a6096Sbeveloper // reply5.name contains the name assigned to the connection by the producer 8728c6a6096Sbeveloper 8738c6a6096Sbeveloper // initilize connection info 87469983609Sbeveloper *io_format = reply4.input.format; 8758c6a6096Sbeveloper *out_input = reply4.input; 8768c6a6096Sbeveloper out_output->node = sourcenode; 8778c6a6096Sbeveloper out_output->source = reply4.input.source; 8788c6a6096Sbeveloper out_output->destination = reply4.input.destination; 8798c6a6096Sbeveloper out_output->format = reply4.input.format; 8808c6a6096Sbeveloper strcpy(out_output->name, reply5.name); 8818c6a6096Sbeveloper 8828c6a6096Sbeveloper // the connection is now made 88369983609Sbeveloper printf("BMediaRoster::Connect connection established!\n"); 88469983609Sbeveloper PRINT_FORMAT(" format", *io_format); 88569983609Sbeveloper PRINT_INPUT(" input", *out_input); 88669983609Sbeveloper PRINT_OUTPUT(" output", *out_output); 8878c6a6096Sbeveloper 8888c6a6096Sbeveloper // XXX register connection with server 8899e9417d2Sbeveloper // XXX we should just send a notification, instead of republishing all endpoints 89076669a29Sbeveloper List<media_output> outlist; 89176669a29Sbeveloper List<media_input> inlist; 8928b04ffc1Sbeveloper if (B_OK == MediaRosterEx(this)->GetAllOutputs(out_output->node , &outlist)) 8938b04ffc1Sbeveloper MediaRosterEx(this)->PublishOutputs(out_output->node , &outlist); 8948b04ffc1Sbeveloper if (B_OK == MediaRosterEx(this)->GetAllInputs(out_input->node , &inlist)) 8958b04ffc1Sbeveloper MediaRosterEx(this)->PublishInputs(out_input->node, &inlist); 8968c6a6096Sbeveloper 8978c6a6096Sbeveloper 8988c6a6096Sbeveloper // XXX if (mute) BBufferProducer::EnableOutput(false) 8999e9417d2Sbeveloper if (in_flags & B_CONNECT_MUTED) { 9009e9417d2Sbeveloper } 9018c6a6096Sbeveloper 9028c6a6096Sbeveloper 9039e9417d2Sbeveloper // send a notification 9049e9417d2Sbeveloper BPrivate::media::notifications::ConnectionMade(*out_input, *out_output, *io_format); 9059e9417d2Sbeveloper 9068c6a6096Sbeveloper return B_OK; 9078c6a6096Sbeveloper }; 90852a38012Sejakowatz 90952a38012Sejakowatz 91052a38012Sejakowatz status_t 9119e9417d2Sbeveloper BMediaRoster::Disconnect(media_node_id source_nodeid, 91252a38012Sejakowatz const media_source & source, 9139e9417d2Sbeveloper media_node_id destination_nodeid, 91452a38012Sejakowatz const media_destination & destination) 91552a38012Sejakowatz { 9169e9417d2Sbeveloper CALLED(); 91740f36b03Sbeveloper if (IS_INVALID_NODEID(source_nodeid)) { 9185ac4fbd7Sbeveloper ERROR("BMediaRoster::Disconnect: source media_node_id invalid\n"); 9199e9417d2Sbeveloper return B_MEDIA_BAD_SOURCE; 9209e9417d2Sbeveloper } 92140f36b03Sbeveloper if (IS_INVALID_NODEID(destination_nodeid)) { 9225ac4fbd7Sbeveloper ERROR("BMediaRoster::Disconnect: destination media_node_id invalid\n"); 9239e9417d2Sbeveloper return B_MEDIA_BAD_DESTINATION; 9249e9417d2Sbeveloper } 92540f36b03Sbeveloper if (IS_INVALID_SOURCE(source)) { 9265ac4fbd7Sbeveloper ERROR("BMediaRoster::Disconnect: media_source invalid\n"); 9279e9417d2Sbeveloper return B_MEDIA_BAD_SOURCE; 9289e9417d2Sbeveloper } 92940f36b03Sbeveloper if (IS_INVALID_DESTINATION(destination)) { 9305ac4fbd7Sbeveloper ERROR("BMediaRoster::Disconnect: media_destination invalid\n"); 9319e9417d2Sbeveloper return B_MEDIA_BAD_DESTINATION; 9329e9417d2Sbeveloper } 9339e9417d2Sbeveloper 9349e9417d2Sbeveloper producer_disconnect_request request2; 9359e9417d2Sbeveloper producer_disconnect_reply reply2; 9369e9417d2Sbeveloper consumer_disconnected_request request1; 9379e9417d2Sbeveloper consumer_disconnected_reply reply1; 9389e9417d2Sbeveloper status_t rv1, rv2; 9399e9417d2Sbeveloper 9409e9417d2Sbeveloper // XXX we should ask the server if this connection really exists 9419e9417d2Sbeveloper 9429e9417d2Sbeveloper request1.source = source; 9439e9417d2Sbeveloper request1.destination = destination; 9449e9417d2Sbeveloper request2.source = source; 9459e9417d2Sbeveloper request2.destination = destination; 9469e9417d2Sbeveloper 9479e9417d2Sbeveloper rv1 = QueryPort(source.port, PRODUCER_DISCONNECT, &request1, sizeof(request1), &reply1, sizeof(reply1)); 9489e9417d2Sbeveloper rv2 = QueryPort(destination.port, CONSUMER_DISCONNECTED, &request2, sizeof(request2), &reply2, sizeof(reply2)); 9499e9417d2Sbeveloper 9509e9417d2Sbeveloper // XXX unregister connection with server 9519e9417d2Sbeveloper // XXX we should just send a notification, instead of republishing all endpoints 95276669a29Sbeveloper List<media_output> outlist; 95376669a29Sbeveloper List<media_input> inlist; 9549e9417d2Sbeveloper media_node sourcenode; 9559e9417d2Sbeveloper media_node destnode; 9569e9417d2Sbeveloper if (B_OK == GetNodeFor(source_nodeid, &sourcenode)) { 95765b73ae4SMarcus Overhagen if (!(sourcenode.kind & B_BUFFER_PRODUCER)) { 95865b73ae4SMarcus Overhagen ERROR("BMediaRoster::Disconnect: source_nodeid %ld is not a B_BUFFER_PRODUCER\n", source_nodeid); 95965b73ae4SMarcus Overhagen } 9608b04ffc1Sbeveloper if (B_OK == MediaRosterEx(this)->GetAllOutputs(sourcenode , &outlist)) 9618b04ffc1Sbeveloper MediaRosterEx(this)->PublishOutputs(sourcenode , &outlist); 9629e9417d2Sbeveloper ReleaseNode(sourcenode); 9634f09fa2fSbeveloper } else { 96465b73ae4SMarcus Overhagen ERROR("BMediaRoster::Disconnect: GetNodeFor source_nodeid %ld failed\n", source_nodeid); 9654f09fa2fSbeveloper } 9669e9417d2Sbeveloper if (B_OK == GetNodeFor(destination_nodeid, &destnode)) { 96765b73ae4SMarcus Overhagen if (!(destnode.kind & B_BUFFER_CONSUMER)) { 96865b73ae4SMarcus Overhagen ERROR("BMediaRoster::Disconnect: destination_nodeid %ld is not a B_BUFFER_CONSUMER\n", destination_nodeid); 96965b73ae4SMarcus Overhagen } 9708b04ffc1Sbeveloper if (B_OK == MediaRosterEx(this)->GetAllInputs(destnode , &inlist)) 9718b04ffc1Sbeveloper MediaRosterEx(this)->PublishInputs(destnode, &inlist); 9729e9417d2Sbeveloper ReleaseNode(destnode); 9734f09fa2fSbeveloper } else { 97465b73ae4SMarcus Overhagen ERROR("BMediaRoster::Disconnect: GetNodeFor destination_nodeid %ld failed\n", destination_nodeid); 9754f09fa2fSbeveloper } 9769e9417d2Sbeveloper 9779e9417d2Sbeveloper 9789e9417d2Sbeveloper // send a notification 9799e9417d2Sbeveloper BPrivate::media::notifications::ConnectionBroken(source, destination); 9809e9417d2Sbeveloper 9819e9417d2Sbeveloper return (rv1 != B_OK || rv2 != B_OK) ? B_ERROR : B_OK; 98252a38012Sejakowatz } 98352a38012Sejakowatz 98465b73ae4SMarcus Overhagen status_t 98565b73ae4SMarcus Overhagen BMediaRoster::Disconnect(const media_output &output, const media_input &input) 98665b73ae4SMarcus Overhagen { 98765b73ae4SMarcus Overhagen if (IS_INVALID_NODEID(output.node.node)) { 98865b73ae4SMarcus Overhagen printf("BMediaRoster::Disconnect: output.node.node %ld invalid\n", 98965b73ae4SMarcus Overhagen output.node.node); 99065b73ae4SMarcus Overhagen return B_MEDIA_BAD_SOURCE; 99165b73ae4SMarcus Overhagen } 99265b73ae4SMarcus Overhagen if (IS_INVALID_NODEID(input.node.node)) { 99365b73ae4SMarcus Overhagen printf("BMediaRoster::Disconnect: input.node.node %ld invalid\n", 99465b73ae4SMarcus Overhagen input.node.node); 99565b73ae4SMarcus Overhagen return B_MEDIA_BAD_DESTINATION; 99665b73ae4SMarcus Overhagen } 99765b73ae4SMarcus Overhagen if (!(output.node.kind & B_BUFFER_PRODUCER)) { 99865b73ae4SMarcus Overhagen printf("BMediaRoster::Disconnect: output.node.kind 0x%lx is no B_BUFFER_PRODUCER\n", 99965b73ae4SMarcus Overhagen output.node.kind); 100065b73ae4SMarcus Overhagen return B_MEDIA_BAD_SOURCE; 100165b73ae4SMarcus Overhagen } 100265b73ae4SMarcus Overhagen if (!(input.node.kind & B_BUFFER_CONSUMER)) { 100365b73ae4SMarcus Overhagen printf("BMediaRoster::Disconnect: input.node.kind 0x%lx is no B_BUFFER_PRODUCER\n", 100465b73ae4SMarcus Overhagen input.node.kind); 100565b73ae4SMarcus Overhagen return B_MEDIA_BAD_DESTINATION; 100665b73ae4SMarcus Overhagen } 100765b73ae4SMarcus Overhagen if (input.source.port != output.source.port) { 100865b73ae4SMarcus Overhagen printf("BMediaRoster::Disconnect: input.source.port %ld doesn't match output.source.port %ld\n", 100965b73ae4SMarcus Overhagen input.source.port, output.source.port); 101065b73ae4SMarcus Overhagen return B_MEDIA_BAD_SOURCE; 101165b73ae4SMarcus Overhagen } 101265b73ae4SMarcus Overhagen if (input.source.id != output.source.id) { 101365b73ae4SMarcus Overhagen printf("BMediaRoster::Disconnect: input.source.id %ld doesn't match output.source.id %ld\n", 101465b73ae4SMarcus Overhagen input.source.id, output.source.id); 101565b73ae4SMarcus Overhagen return B_MEDIA_BAD_SOURCE; 101665b73ae4SMarcus Overhagen } 101765b73ae4SMarcus Overhagen if (input.destination.port != output.destination.port) { 101865b73ae4SMarcus Overhagen printf("BMediaRoster::Disconnect: input.destination.port %ld doesn't match output.destination.port %ld\n", 101965b73ae4SMarcus Overhagen input.destination.port, output.destination.port); 102065b73ae4SMarcus Overhagen return B_MEDIA_BAD_DESTINATION; 102165b73ae4SMarcus Overhagen } 102265b73ae4SMarcus Overhagen if (input.destination.id != output.destination.id) { 102365b73ae4SMarcus Overhagen printf("BMediaRoster::Disconnect: input.destination.id %ld doesn't match output.destination.id %ld\n", 102465b73ae4SMarcus Overhagen input.destination.id, output.destination.id); 102565b73ae4SMarcus Overhagen return B_MEDIA_BAD_DESTINATION; 102665b73ae4SMarcus Overhagen } 102765b73ae4SMarcus Overhagen return Disconnect(output.node.node, output.source, input.node.node, input.destination); 102865b73ae4SMarcus Overhagen } 102965b73ae4SMarcus Overhagen 103052a38012Sejakowatz 103152a38012Sejakowatz status_t 103252a38012Sejakowatz BMediaRoster::StartNode(const media_node & node, 103352a38012Sejakowatz bigtime_t at_performance_time) 103452a38012Sejakowatz { 103552a38012Sejakowatz CALLED(); 10369e9417d2Sbeveloper if (node.node <= 0) 103752a38012Sejakowatz return B_MEDIA_BAD_NODE; 103852a38012Sejakowatz 103960f15390Sbeveloper TRACE("BMediaRoster::StartNode, node %ld, at perf %Ld\n", node.node, at_performance_time); 10400e21b167Sbeveloper 10416396865dSbeveloper node_start_command command; 10426396865dSbeveloper command.performance_time = at_performance_time; 104352a38012Sejakowatz 10446396865dSbeveloper return SendToPort(node.port, NODE_START, &command, sizeof(command)); 104552a38012Sejakowatz } 104652a38012Sejakowatz 104752a38012Sejakowatz 104852a38012Sejakowatz status_t 104952a38012Sejakowatz BMediaRoster::StopNode(const media_node & node, 105052a38012Sejakowatz bigtime_t at_performance_time, 105152a38012Sejakowatz bool immediate) 105252a38012Sejakowatz { 105352a38012Sejakowatz CALLED(); 105440f36b03Sbeveloper if (IS_INVALID_NODE(node)) 105552a38012Sejakowatz return B_MEDIA_BAD_NODE; 105652a38012Sejakowatz 105760f15390Sbeveloper TRACE("BMediaRoster::StopNode, node %ld, at perf %Ld %s\n", node.node, at_performance_time, immediate ? "NOW" : ""); 10580e21b167Sbeveloper 10596396865dSbeveloper node_stop_command command; 10606396865dSbeveloper command.performance_time = at_performance_time; 10616396865dSbeveloper command.immediate = immediate; 106252a38012Sejakowatz 10636396865dSbeveloper return SendToPort(node.port, NODE_STOP, &command, sizeof(command)); 106452a38012Sejakowatz } 106552a38012Sejakowatz 106652a38012Sejakowatz 106752a38012Sejakowatz status_t 106852a38012Sejakowatz BMediaRoster::SeekNode(const media_node & node, 106952a38012Sejakowatz bigtime_t to_media_time, 107052a38012Sejakowatz bigtime_t at_performance_time) 107152a38012Sejakowatz { 107252a38012Sejakowatz CALLED(); 107340f36b03Sbeveloper if (IS_INVALID_NODE(node)) 107452a38012Sejakowatz return B_MEDIA_BAD_NODE; 107552a38012Sejakowatz 107660f15390Sbeveloper TRACE("BMediaRoster::SeekNode, node %ld, at perf %Ld, to perf %Ld\n", node.node, at_performance_time, to_media_time); 10770e21b167Sbeveloper 10786396865dSbeveloper node_seek_command command; 10796396865dSbeveloper command.media_time = to_media_time; 10806396865dSbeveloper command.performance_time = at_performance_time; 108152a38012Sejakowatz 10826396865dSbeveloper return SendToPort(node.port, NODE_SEEK, &command, sizeof(command)); 108352a38012Sejakowatz } 108452a38012Sejakowatz 108552a38012Sejakowatz 108652a38012Sejakowatz status_t 108752a38012Sejakowatz BMediaRoster::StartTimeSource(const media_node & node, 108852a38012Sejakowatz bigtime_t at_real_time) 108952a38012Sejakowatz { 109052a38012Sejakowatz CALLED(); 109160f15390Sbeveloper if (IS_SYSTEM_TIMESOURCE(node)) { 109260f15390Sbeveloper // XXX debug this 10935ac4fbd7Sbeveloper //ERROR("BMediaRoster::StartTimeSource node %ld is system timesource\n", node.node); 109460f15390Sbeveloper return B_OK; 109560f15390Sbeveloper } 109692e575c1Sbeveloper // if (IS_SHADOW_TIMESOURCE(node)) { 109792e575c1Sbeveloper // // XXX debug this 109892e575c1Sbeveloper // ERROR("BMediaRoster::StartTimeSource node %ld is shadow timesource\n", node.node); 109992e575c1Sbeveloper // return B_OK; 110092e575c1Sbeveloper // } 110140f36b03Sbeveloper if (IS_INVALID_NODE(node)) { 11025ac4fbd7Sbeveloper ERROR("BMediaRoster::StartTimeSource node %ld invalid\n", node.node); 110352a38012Sejakowatz return B_MEDIA_BAD_NODE; 11040e21b167Sbeveloper } 11050e21b167Sbeveloper if ((node.kind & B_TIME_SOURCE) == 0) { 11065ac4fbd7Sbeveloper ERROR("BMediaRoster::StartTimeSource node %ld is no timesource\n", node.node); 110752a38012Sejakowatz return B_MEDIA_BAD_NODE; 11080e21b167Sbeveloper } 11090e21b167Sbeveloper 111060f15390Sbeveloper TRACE("BMediaRoster::StartTimeSource, node %ld, at real %Ld\n", node.node, at_real_time); 111152a38012Sejakowatz 111252a38012Sejakowatz BTimeSource::time_source_op_info msg; 111352a38012Sejakowatz msg.op = BTimeSource::B_TIMESOURCE_START; 111452a38012Sejakowatz msg.real_time = at_real_time; 111552a38012Sejakowatz 111652a38012Sejakowatz return write_port(node.port, TIMESOURCE_OP, &msg, sizeof(msg)); 111752a38012Sejakowatz } 111852a38012Sejakowatz 111952a38012Sejakowatz 112052a38012Sejakowatz status_t 112152a38012Sejakowatz BMediaRoster::StopTimeSource(const media_node & node, 112252a38012Sejakowatz bigtime_t at_real_time, 112352a38012Sejakowatz bool immediate) 112452a38012Sejakowatz { 112552a38012Sejakowatz CALLED(); 112660f15390Sbeveloper if (IS_SYSTEM_TIMESOURCE(node)) { 112760f15390Sbeveloper // XXX debug this 11285ac4fbd7Sbeveloper //ERROR("BMediaRoster::StopTimeSource node %ld is system timesource\n", node.node); 112960f15390Sbeveloper return B_OK; 113060f15390Sbeveloper } 113192e575c1Sbeveloper // if (IS_SHADOW_TIMESOURCE(node)) { 113292e575c1Sbeveloper // // XXX debug this 113392e575c1Sbeveloper // ERROR("BMediaRoster::StopTimeSource node %ld is shadow timesource\n", node.node); 113492e575c1Sbeveloper // return B_OK; 113592e575c1Sbeveloper // } 113640f36b03Sbeveloper if (IS_INVALID_NODE(node)) { 11375ac4fbd7Sbeveloper ERROR("BMediaRoster::StopTimeSource node %ld invalid\n", node.node); 113852a38012Sejakowatz return B_MEDIA_BAD_NODE; 11390e21b167Sbeveloper } 11400e21b167Sbeveloper if ((node.kind & B_TIME_SOURCE) == 0) { 11415ac4fbd7Sbeveloper ERROR("BMediaRoster::StopTimeSource node %ld is no timesource\n", node.node); 114252a38012Sejakowatz return B_MEDIA_BAD_NODE; 11430e21b167Sbeveloper } 11440e21b167Sbeveloper 114560f15390Sbeveloper TRACE("BMediaRoster::StopTimeSource, node %ld, at real %Ld %s\n", node.node, at_real_time, immediate ? "NOW" : ""); 114652a38012Sejakowatz 114752a38012Sejakowatz BTimeSource::time_source_op_info msg; 114852a38012Sejakowatz msg.op = immediate ? BTimeSource::B_TIMESOURCE_STOP_IMMEDIATELY : BTimeSource::B_TIMESOURCE_STOP; 114952a38012Sejakowatz msg.real_time = at_real_time; 115052a38012Sejakowatz 115152a38012Sejakowatz return write_port(node.port, TIMESOURCE_OP, &msg, sizeof(msg)); 115252a38012Sejakowatz } 115352a38012Sejakowatz 115452a38012Sejakowatz 115552a38012Sejakowatz status_t 115652a38012Sejakowatz BMediaRoster::SeekTimeSource(const media_node & node, 115752a38012Sejakowatz bigtime_t to_performance_time, 115852a38012Sejakowatz bigtime_t at_real_time) 115952a38012Sejakowatz { 116052a38012Sejakowatz CALLED(); 116160f15390Sbeveloper if (IS_SYSTEM_TIMESOURCE(node)) { 116260f15390Sbeveloper // XXX debug this 11635ac4fbd7Sbeveloper // ERROR("BMediaRoster::SeekTimeSource node %ld is system timesource\n", node.node); 116460f15390Sbeveloper // you can't seek the system time source, but 116560f15390Sbeveloper // returning B_ERROR would break StampTV 116660f15390Sbeveloper return B_OK; 116760f15390Sbeveloper } 116892e575c1Sbeveloper // if (IS_SHADOW_TIMESOURCE(node)) { 116992e575c1Sbeveloper // // XXX debug this 117092e575c1Sbeveloper // ERROR("BMediaRoster::SeekTimeSource node %ld is shadow timesource\n", node.node); 117192e575c1Sbeveloper // return B_OK; 117292e575c1Sbeveloper // } 117340f36b03Sbeveloper if (IS_INVALID_NODE(node)) { 11745ac4fbd7Sbeveloper ERROR("BMediaRoster::SeekTimeSource node %ld invalid\n", node.node); 117552a38012Sejakowatz return B_MEDIA_BAD_NODE; 11760e21b167Sbeveloper } 11770e21b167Sbeveloper if ((node.kind & B_TIME_SOURCE) == 0) { 11785ac4fbd7Sbeveloper ERROR("BMediaRoster::SeekTimeSource node %ld is no timesource\n", node.node); 117952a38012Sejakowatz return B_MEDIA_BAD_NODE; 11800e21b167Sbeveloper } 11810e21b167Sbeveloper 118260f15390Sbeveloper TRACE("BMediaRoster::SeekTimeSource, node %ld, at real %Ld, to perf %Ld\n", node.node, at_real_time, to_performance_time); 118352a38012Sejakowatz 118452a38012Sejakowatz BTimeSource::time_source_op_info msg; 118552a38012Sejakowatz msg.op = BTimeSource::B_TIMESOURCE_SEEK; 118652a38012Sejakowatz msg.real_time = at_real_time; 118752a38012Sejakowatz msg.performance_time = to_performance_time; 118852a38012Sejakowatz 118952a38012Sejakowatz return write_port(node.port, TIMESOURCE_OP, &msg, sizeof(msg)); 119052a38012Sejakowatz } 119152a38012Sejakowatz 119252a38012Sejakowatz 119352a38012Sejakowatz status_t 119452a38012Sejakowatz BMediaRoster::SyncToNode(const media_node & node, 119552a38012Sejakowatz bigtime_t at_time, 119652a38012Sejakowatz bigtime_t timeout) 119752a38012Sejakowatz { 119852a38012Sejakowatz UNIMPLEMENTED(); 119960f15390Sbeveloper return B_OK; 120052a38012Sejakowatz } 120152a38012Sejakowatz 120252a38012Sejakowatz 120352a38012Sejakowatz status_t 120452a38012Sejakowatz BMediaRoster::SetRunModeNode(const media_node & node, 120552a38012Sejakowatz BMediaNode::run_mode mode) 120652a38012Sejakowatz { 120752a38012Sejakowatz CALLED(); 120840f36b03Sbeveloper if (IS_INVALID_NODE(node)) 120952a38012Sejakowatz return B_MEDIA_BAD_NODE; 121052a38012Sejakowatz 1211dfb2ad61Sbeveloper node_set_run_mode_command msg; 121252a38012Sejakowatz msg.mode = mode; 121352a38012Sejakowatz 121452a38012Sejakowatz return write_port(node.port, NODE_SET_RUN_MODE, &msg, sizeof(msg)); 121552a38012Sejakowatz } 121652a38012Sejakowatz 121752a38012Sejakowatz 121852a38012Sejakowatz status_t 121952a38012Sejakowatz BMediaRoster::PrerollNode(const media_node & node) 122052a38012Sejakowatz { 122152a38012Sejakowatz CALLED(); 122240f36b03Sbeveloper if (IS_INVALID_NODE(node)) 122352a38012Sejakowatz return B_MEDIA_BAD_NODE; 122452a38012Sejakowatz 122552a38012Sejakowatz char dummy; 122652a38012Sejakowatz return write_port(node.port, NODE_PREROLL, &dummy, sizeof(dummy)); 122752a38012Sejakowatz } 122852a38012Sejakowatz 122952a38012Sejakowatz 123052a38012Sejakowatz status_t 123152a38012Sejakowatz BMediaRoster::RollNode(const media_node & node, 123252a38012Sejakowatz bigtime_t startPerformance, 123352a38012Sejakowatz bigtime_t stopPerformance, 123452a38012Sejakowatz bigtime_t atMediaTime) 123552a38012Sejakowatz { 123652a38012Sejakowatz UNIMPLEMENTED(); 123752a38012Sejakowatz return B_ERROR; 123852a38012Sejakowatz } 123952a38012Sejakowatz 124052a38012Sejakowatz 124152a38012Sejakowatz status_t 124252a38012Sejakowatz BMediaRoster::SetProducerRunModeDelay(const media_node & node, 124352a38012Sejakowatz bigtime_t delay, 124452a38012Sejakowatz BMediaNode::run_mode mode) 124552a38012Sejakowatz { 124660f15390Sbeveloper CALLED(); 124760f15390Sbeveloper if (IS_INVALID_NODE(node)) 124860f15390Sbeveloper return B_MEDIA_BAD_NODE; 124960f15390Sbeveloper if ((node.kind & B_BUFFER_PRODUCER) == 0) 125060f15390Sbeveloper return B_MEDIA_BAD_NODE; 125160f15390Sbeveloper 125260f15390Sbeveloper producer_set_run_mode_delay_command command; 125360f15390Sbeveloper command.mode = mode; 125460f15390Sbeveloper command.delay = delay; 125560f15390Sbeveloper 125660f15390Sbeveloper return SendToPort(node.port, PRODUCER_SET_RUN_MODE_DELAY, &command, sizeof(command)); 125752a38012Sejakowatz } 125852a38012Sejakowatz 125952a38012Sejakowatz 126052a38012Sejakowatz status_t 126152a38012Sejakowatz BMediaRoster::SetProducerRate(const media_node & producer, 126252a38012Sejakowatz int32 numer, 126352a38012Sejakowatz int32 denom) 126452a38012Sejakowatz { 126552a38012Sejakowatz CALLED(); 126640f36b03Sbeveloper if (IS_INVALID_NODE(producer)) 126752a38012Sejakowatz return B_MEDIA_BAD_NODE; 126852a38012Sejakowatz if ((producer.kind & B_BUFFER_PRODUCER) == 0) 126952a38012Sejakowatz return B_MEDIA_BAD_NODE; 127052a38012Sejakowatz 1271dfb2ad61Sbeveloper producer_set_play_rate_request msg; 1272dfb2ad61Sbeveloper producer_set_play_rate_reply reply; 127352a38012Sejakowatz status_t rv; 127452a38012Sejakowatz int32 code; 127552a38012Sejakowatz 127652a38012Sejakowatz msg.numer = numer; 127752a38012Sejakowatz msg.denom = denom; 127852a38012Sejakowatz msg.reply_port = _PortPool->GetPort(); 127952a38012Sejakowatz rv = write_port(producer.node, PRODUCER_SET_PLAY_RATE, &msg, sizeof(msg)); 128052a38012Sejakowatz if (rv != B_OK) { 128152a38012Sejakowatz _PortPool->PutPort(msg.reply_port); 128252a38012Sejakowatz return rv; 128352a38012Sejakowatz } 128452a38012Sejakowatz rv = read_port(msg.reply_port, &code, &reply, sizeof(reply)); 128552a38012Sejakowatz _PortPool->PutPort(msg.reply_port); 128652a38012Sejakowatz return (rv < B_OK) ? rv : reply.result; 128752a38012Sejakowatz } 128852a38012Sejakowatz 128952a38012Sejakowatz 129052a38012Sejakowatz /* Nodes will have available inputs/outputs as long as they are capable */ 129152a38012Sejakowatz /* of accepting more connections. The node may create an additional */ 129252a38012Sejakowatz /* output or input as the currently available is taken into usage. */ 129352a38012Sejakowatz status_t 129452a38012Sejakowatz BMediaRoster::GetLiveNodeInfo(const media_node & node, 129552a38012Sejakowatz live_node_info * out_live_info) 129652a38012Sejakowatz { 12979e9417d2Sbeveloper CALLED(); 12989e9417d2Sbeveloper if (out_live_info == NULL) 12999e9417d2Sbeveloper return B_BAD_VALUE; 130040f36b03Sbeveloper if (IS_INVALID_NODE(node)) 13019e9417d2Sbeveloper return B_MEDIA_BAD_NODE; 13029e9417d2Sbeveloper 13039e9417d2Sbeveloper server_get_live_node_info_request request; 13049e9417d2Sbeveloper server_get_live_node_info_reply reply; 13059e9417d2Sbeveloper status_t rv; 13069e9417d2Sbeveloper 13079e9417d2Sbeveloper request.node = node; 13089e9417d2Sbeveloper 13091299bfb2Sbeveloper rv = QueryServer(SERVER_GET_LIVE_NODE_INFO, &request, sizeof(request), &reply, sizeof(reply)); 13109e9417d2Sbeveloper if (rv != B_OK) 13119e9417d2Sbeveloper return rv; 13129e9417d2Sbeveloper 13139e9417d2Sbeveloper *out_live_info = reply.live_info; 13149e9417d2Sbeveloper return B_OK; 131552a38012Sejakowatz } 131652a38012Sejakowatz 131752a38012Sejakowatz 131852a38012Sejakowatz status_t 131952a38012Sejakowatz BMediaRoster::GetLiveNodes(live_node_info * out_live_nodes, 132052a38012Sejakowatz int32 * io_total_count, 132152a38012Sejakowatz const media_format * has_input, 132252a38012Sejakowatz const media_format * has_output, 132352a38012Sejakowatz const char * name, 132452a38012Sejakowatz uint64 node_kinds) 132552a38012Sejakowatz { 13269e9417d2Sbeveloper CALLED(); 13279e9417d2Sbeveloper if (out_live_nodes == NULL || io_total_count == NULL) 13289e9417d2Sbeveloper return B_BAD_VALUE; 13299e9417d2Sbeveloper if (*io_total_count <= 0) 13309e9417d2Sbeveloper return B_BAD_VALUE; 13319e9417d2Sbeveloper 13329e9417d2Sbeveloper // XXX we also support the wildcard search as GetDormantNodes does. This needs to be documented 13339e9417d2Sbeveloper 13349e9417d2Sbeveloper server_get_live_nodes_request request; 13359e9417d2Sbeveloper server_get_live_nodes_reply reply; 13369e9417d2Sbeveloper status_t rv; 13379e9417d2Sbeveloper 13389e9417d2Sbeveloper request.maxcount = *io_total_count; 13399e9417d2Sbeveloper request.has_input = (bool) has_input; 13409e9417d2Sbeveloper if (has_input) 13419e9417d2Sbeveloper request.inputformat = *has_input; // XXX we should not make a flat copy of media_format 13429e9417d2Sbeveloper request.has_output = (bool) has_output; 13439e9417d2Sbeveloper if (has_output) 13449e9417d2Sbeveloper request.outputformat = *has_output; // XXX we should not make a flat copy of media_format 13459e9417d2Sbeveloper request.has_name = (bool) name; 13469e9417d2Sbeveloper if (name) { 13479e9417d2Sbeveloper int len = strlen(name); 13489e9417d2Sbeveloper len = min_c(len, (int)sizeof(request.name) - 1); 13499e9417d2Sbeveloper memcpy(request.name, name, len); 13509e9417d2Sbeveloper request.name[len] = 0; 13519e9417d2Sbeveloper } 13529e9417d2Sbeveloper request.require_kinds = node_kinds; 13539e9417d2Sbeveloper 13549e9417d2Sbeveloper rv = QueryServer(SERVER_GET_LIVE_NODES, &request, sizeof(request), &reply, sizeof(reply)); 13559e9417d2Sbeveloper if (rv != B_OK) { 13565ac4fbd7Sbeveloper ERROR("BMediaRoster::GetLiveNodes failed querying server\n"); 13571299bfb2Sbeveloper *io_total_count = 0; 13589e9417d2Sbeveloper return rv; 13599e9417d2Sbeveloper } 13609e9417d2Sbeveloper 13619e9417d2Sbeveloper if (reply.count > MAX_LIVE_INFO) { 13629e9417d2Sbeveloper live_node_info *live_info; 13639e9417d2Sbeveloper area_id clone; 13649e9417d2Sbeveloper 13659e9417d2Sbeveloper clone = clone_area("live_node_info clone", reinterpret_cast<void **>(&live_info), B_ANY_ADDRESS, B_READ_AREA | B_WRITE_AREA, reply.area); 13669e9417d2Sbeveloper if (clone < B_OK) { 13675ac4fbd7Sbeveloper ERROR("BMediaRoster::GetLiveNodes failed to clone area, %#lx\n", clone); 13689e9417d2Sbeveloper delete_area(reply.area); 13691299bfb2Sbeveloper *io_total_count = 0; 137052a38012Sejakowatz return B_ERROR; 137152a38012Sejakowatz } 137252a38012Sejakowatz 13739e9417d2Sbeveloper for (int32 i = 0; i < reply.count; i++) { 13749e9417d2Sbeveloper out_live_nodes[i] = live_info[i]; 13759e9417d2Sbeveloper } 13769e9417d2Sbeveloper 13779e9417d2Sbeveloper delete_area(clone); 13789e9417d2Sbeveloper delete_area(reply.area); 13799e9417d2Sbeveloper } else { 13809e9417d2Sbeveloper for (int32 i = 0; i < reply.count; i++) { 13819e9417d2Sbeveloper out_live_nodes[i] = reply.live_info[i]; 13829e9417d2Sbeveloper } 13839e9417d2Sbeveloper } 13849e9417d2Sbeveloper *io_total_count = reply.count; 13859e9417d2Sbeveloper 13869e9417d2Sbeveloper return B_OK; 13879e9417d2Sbeveloper } 13889e9417d2Sbeveloper 138952a38012Sejakowatz 139052a38012Sejakowatz status_t 139152a38012Sejakowatz BMediaRoster::GetFreeInputsFor(const media_node & node, 139252a38012Sejakowatz media_input * out_free_inputs, 139352a38012Sejakowatz int32 buf_num_inputs, 139452a38012Sejakowatz int32 * out_total_count, 139552a38012Sejakowatz media_type filter_type) 139652a38012Sejakowatz { 13973620737cSbeveloper CALLED(); 13985ac4fbd7Sbeveloper if (IS_INVALID_NODE(node)) { 13995ac4fbd7Sbeveloper ERROR("BMediaRoster::GetFreeInputsFor: node %ld, port %ld invalid\n", node.node, node.port); 14003620737cSbeveloper return B_MEDIA_BAD_NODE; 14015ac4fbd7Sbeveloper } 14025ac4fbd7Sbeveloper if ((node.kind & B_BUFFER_CONSUMER) == 0) { 14035ac4fbd7Sbeveloper ERROR("BMediaRoster::GetFreeInputsFor: node %ld, port %ld is not a consumer\n", node.node, node.port); 14045ac4fbd7Sbeveloper return B_MEDIA_BAD_NODE; 14055ac4fbd7Sbeveloper } 14063620737cSbeveloper if (out_free_inputs == NULL || out_total_count == NULL) 14073620737cSbeveloper return B_BAD_VALUE; 14083620737cSbeveloper 140976669a29Sbeveloper List<media_input> list; 14103620737cSbeveloper media_input *input; 14113620737cSbeveloper status_t rv; 14123620737cSbeveloper 14131299bfb2Sbeveloper *out_total_count = 0; 14141299bfb2Sbeveloper 14158b04ffc1Sbeveloper rv = MediaRosterEx(this)->GetAllInputs(node, &list); 14163620737cSbeveloper if (B_OK != rv) 14173620737cSbeveloper return rv; 14183620737cSbeveloper 14195ac4fbd7Sbeveloper PRINT(4, "BMediaRoster::GetFreeInputsFor node %ld, max %ld, filter-type %ld\n", node.node, buf_num_inputs, filter_type); 14205ac4fbd7Sbeveloper 142176669a29Sbeveloper int32 i; 1422b65a0ac5SJérôme Duval for (i = 0, list.Rewind(); list.GetNext(&input);) { 14233620737cSbeveloper if (filter_type != B_MEDIA_UNKNOWN_TYPE && filter_type != input->format.type) 14243620737cSbeveloper continue; // media_type used, but doesn't match 14253620737cSbeveloper if (input->source != media_source::null) 14263620737cSbeveloper continue; // consumer source already connected 14273620737cSbeveloper out_free_inputs[i] = *input; 14283620737cSbeveloper *out_total_count += 1; 14293620737cSbeveloper buf_num_inputs -= 1; 14305ac4fbd7Sbeveloper #if DEBUG >= 3 14315ac4fbd7Sbeveloper PRINT_OUTPUT(" input", out_free_inputs[i]); 14325ac4fbd7Sbeveloper #endif 14333620737cSbeveloper if (buf_num_inputs == 0) 14343620737cSbeveloper break; 1435b65a0ac5SJérôme Duval i++; 14363620737cSbeveloper } 14373620737cSbeveloper 14388b04ffc1Sbeveloper MediaRosterEx(this)->PublishInputs(node, &list); 14393620737cSbeveloper return B_OK; 144052a38012Sejakowatz } 144152a38012Sejakowatz 144252a38012Sejakowatz 144352a38012Sejakowatz status_t 144452a38012Sejakowatz BMediaRoster::GetConnectedInputsFor(const media_node & node, 144552a38012Sejakowatz media_input * out_active_inputs, 144652a38012Sejakowatz int32 buf_num_inputs, 144752a38012Sejakowatz int32 * out_total_count) 144852a38012Sejakowatz { 14493620737cSbeveloper CALLED(); 145040f36b03Sbeveloper if (IS_INVALID_NODE(node) || (node.kind & B_BUFFER_CONSUMER) == 0) 14513620737cSbeveloper return B_MEDIA_BAD_NODE; 14523620737cSbeveloper if (out_active_inputs == NULL || out_total_count == NULL) 14533620737cSbeveloper return B_BAD_VALUE; 14543620737cSbeveloper 145576669a29Sbeveloper List<media_input> list; 14563620737cSbeveloper media_input *input; 14573620737cSbeveloper status_t rv; 14583620737cSbeveloper 14591299bfb2Sbeveloper *out_total_count = 0; 14601299bfb2Sbeveloper 14618b04ffc1Sbeveloper rv = MediaRosterEx(this)->GetAllInputs(node, &list); 14623620737cSbeveloper if (B_OK != rv) 14633620737cSbeveloper return rv; 14643620737cSbeveloper 14655ac4fbd7Sbeveloper PRINT(4, "BMediaRoster::GetConnectedInputsFor node %ld, max %ld\n", node.node, buf_num_inputs); 14665ac4fbd7Sbeveloper 146776669a29Sbeveloper int32 i; 1468b65a0ac5SJérôme Duval for (i = 0, list.Rewind(); list.GetNext(&input);) { 14693620737cSbeveloper if (input->source == media_source::null) 14703620737cSbeveloper continue; // consumer source not connected 14713620737cSbeveloper out_active_inputs[i] = *input; 14723620737cSbeveloper *out_total_count += 1; 14733620737cSbeveloper buf_num_inputs -= 1; 14745ac4fbd7Sbeveloper #if DEBUG >= 3 14755ac4fbd7Sbeveloper PRINT_OUTPUT(" input ", out_active_inputs[i]); 14765ac4fbd7Sbeveloper #endif 14773620737cSbeveloper if (buf_num_inputs == 0) 14783620737cSbeveloper break; 1479b65a0ac5SJérôme Duval i++; 14803620737cSbeveloper } 14813620737cSbeveloper 14828b04ffc1Sbeveloper MediaRosterEx(this)->PublishInputs(node, &list); 14833620737cSbeveloper return B_OK; 148452a38012Sejakowatz } 148552a38012Sejakowatz 148652a38012Sejakowatz 148752a38012Sejakowatz status_t 148852a38012Sejakowatz BMediaRoster::GetAllInputsFor(const media_node & node, 148952a38012Sejakowatz media_input * out_inputs, 149052a38012Sejakowatz int32 buf_num_inputs, 149152a38012Sejakowatz int32 * out_total_count) 149252a38012Sejakowatz { 149352a38012Sejakowatz CALLED(); 149440f36b03Sbeveloper if (IS_INVALID_NODE(node) || (node.kind & B_BUFFER_CONSUMER) == 0) 149552a38012Sejakowatz return B_MEDIA_BAD_NODE; 149652a38012Sejakowatz if (out_inputs == NULL || out_total_count == NULL) 149752a38012Sejakowatz return B_BAD_VALUE; 149852a38012Sejakowatz 149976669a29Sbeveloper List<media_input> list; 15003620737cSbeveloper media_input *input; 150152a38012Sejakowatz status_t rv; 150252a38012Sejakowatz 15031299bfb2Sbeveloper *out_total_count = 0; 15041299bfb2Sbeveloper 15058b04ffc1Sbeveloper rv = MediaRosterEx(this)->GetAllInputs(node, &list); 15063620737cSbeveloper if (B_OK != rv) 15073620737cSbeveloper return rv; 15083620737cSbeveloper 15095ac4fbd7Sbeveloper PRINT(4, "BMediaRoster::GetAllInputsFor node %ld, max %ld\n", node.node, buf_num_inputs); 15105ac4fbd7Sbeveloper 151176669a29Sbeveloper int32 i; 151276669a29Sbeveloper for (i = 0, list.Rewind(); list.GetNext(&input); i++) { 15133620737cSbeveloper out_inputs[i] = *input; 151452a38012Sejakowatz *out_total_count += 1; 15153620737cSbeveloper buf_num_inputs -= 1; 15165ac4fbd7Sbeveloper #if DEBUG >= 3 15175ac4fbd7Sbeveloper PRINT_OUTPUT(" input ", out_inputs[i]); 15185ac4fbd7Sbeveloper #endif 15193620737cSbeveloper if (buf_num_inputs == 0) 15203620737cSbeveloper break; 152152a38012Sejakowatz } 152252a38012Sejakowatz 15238b04ffc1Sbeveloper MediaRosterEx(this)->PublishInputs(node, &list); 15243620737cSbeveloper return B_OK; 152552a38012Sejakowatz } 152652a38012Sejakowatz 152752a38012Sejakowatz 152852a38012Sejakowatz status_t 152952a38012Sejakowatz BMediaRoster::GetFreeOutputsFor(const media_node & node, 153052a38012Sejakowatz media_output * out_free_outputs, 153152a38012Sejakowatz int32 buf_num_outputs, 153252a38012Sejakowatz int32 * out_total_count, 153352a38012Sejakowatz media_type filter_type) 153452a38012Sejakowatz { 15353620737cSbeveloper CALLED(); 153640f36b03Sbeveloper if (IS_INVALID_NODE(node) || (node.kind & B_BUFFER_PRODUCER) == 0) 15373620737cSbeveloper return B_MEDIA_BAD_NODE; 15383620737cSbeveloper if (out_free_outputs == NULL || out_total_count == NULL) 15393620737cSbeveloper return B_BAD_VALUE; 15403620737cSbeveloper 154176669a29Sbeveloper List<media_output> list; 15423620737cSbeveloper media_output *output; 15433620737cSbeveloper status_t rv; 15443620737cSbeveloper 15451299bfb2Sbeveloper *out_total_count = 0; 15461299bfb2Sbeveloper 15478b04ffc1Sbeveloper rv = MediaRosterEx(this)->GetAllOutputs(node, &list); 15483620737cSbeveloper if (B_OK != rv) 15493620737cSbeveloper return rv; 15503620737cSbeveloper 15515ac4fbd7Sbeveloper PRINT(4, "BMediaRoster::GetFreeOutputsFor node %ld, max %ld, filter-type %ld\n", node.node, buf_num_outputs, filter_type); 15525ac4fbd7Sbeveloper 155376669a29Sbeveloper int32 i; 1554b65a0ac5SJérôme Duval for (i = 0, list.Rewind(); list.GetNext(&output);) { 15553620737cSbeveloper if (filter_type != B_MEDIA_UNKNOWN_TYPE && filter_type != output->format.type) 15563620737cSbeveloper continue; // media_type used, but doesn't match 15573620737cSbeveloper if (output->destination != media_destination::null) 15583620737cSbeveloper continue; // producer destination already connected 15593620737cSbeveloper out_free_outputs[i] = *output; 15603620737cSbeveloper *out_total_count += 1; 15613620737cSbeveloper buf_num_outputs -= 1; 15625ac4fbd7Sbeveloper #if DEBUG >= 3 15635ac4fbd7Sbeveloper PRINT_OUTPUT(" output ", out_free_outputs[i]); 15645ac4fbd7Sbeveloper #endif 15653620737cSbeveloper if (buf_num_outputs == 0) 15663620737cSbeveloper break; 1567b65a0ac5SJérôme Duval i++; 15683620737cSbeveloper } 15693620737cSbeveloper 15708b04ffc1Sbeveloper MediaRosterEx(this)->PublishOutputs(node, &list); 15713620737cSbeveloper return B_OK; 157252a38012Sejakowatz } 157352a38012Sejakowatz 157452a38012Sejakowatz 157552a38012Sejakowatz status_t 157652a38012Sejakowatz BMediaRoster::GetConnectedOutputsFor(const media_node & node, 157752a38012Sejakowatz media_output * out_active_outputs, 157852a38012Sejakowatz int32 buf_num_outputs, 157952a38012Sejakowatz int32 * out_total_count) 158052a38012Sejakowatz { 15813620737cSbeveloper CALLED(); 158240f36b03Sbeveloper if (IS_INVALID_NODE(node) || (node.kind & B_BUFFER_PRODUCER) == 0) 15833620737cSbeveloper return B_MEDIA_BAD_NODE; 15843620737cSbeveloper if (out_active_outputs == NULL || out_total_count == NULL) 15853620737cSbeveloper return B_BAD_VALUE; 15863620737cSbeveloper 158776669a29Sbeveloper List<media_output> list; 15883620737cSbeveloper media_output *output; 15893620737cSbeveloper status_t rv; 15903620737cSbeveloper 15911299bfb2Sbeveloper *out_total_count = 0; 15921299bfb2Sbeveloper 15938b04ffc1Sbeveloper rv = MediaRosterEx(this)->GetAllOutputs(node, &list); 15943620737cSbeveloper if (B_OK != rv) 15953620737cSbeveloper return rv; 15963620737cSbeveloper 15975ac4fbd7Sbeveloper PRINT(4, "BMediaRoster::GetConnectedOutputsFor node %ld, max %ld\n", node.node, buf_num_outputs); 15985ac4fbd7Sbeveloper 159976669a29Sbeveloper int32 i; 1600b65a0ac5SJérôme Duval for (i = 0, list.Rewind(); list.GetNext(&output);) { 16013620737cSbeveloper if (output->destination == media_destination::null) 16023620737cSbeveloper continue; // producer destination not connected 16033620737cSbeveloper out_active_outputs[i] = *output; 16043620737cSbeveloper *out_total_count += 1; 16053620737cSbeveloper buf_num_outputs -= 1; 16065ac4fbd7Sbeveloper #if DEBUG >= 3 16075ac4fbd7Sbeveloper PRINT_OUTPUT(" output ", out_active_outputs[i]); 16085ac4fbd7Sbeveloper #endif 16093620737cSbeveloper if (buf_num_outputs == 0) 16103620737cSbeveloper break; 1611b65a0ac5SJérôme Duval i++; 16123620737cSbeveloper } 16133620737cSbeveloper 16148b04ffc1Sbeveloper MediaRosterEx(this)->PublishOutputs(node, &list); 16153620737cSbeveloper return B_OK; 161652a38012Sejakowatz } 161752a38012Sejakowatz 161852a38012Sejakowatz 161952a38012Sejakowatz status_t 162052a38012Sejakowatz BMediaRoster::GetAllOutputsFor(const media_node & node, 162152a38012Sejakowatz media_output * out_outputs, 162252a38012Sejakowatz int32 buf_num_outputs, 162352a38012Sejakowatz int32 * out_total_count) 162452a38012Sejakowatz { 162552a38012Sejakowatz CALLED(); 162640f36b03Sbeveloper if (IS_INVALID_NODE(node) || (node.kind & B_BUFFER_PRODUCER) == 0) 162752a38012Sejakowatz return B_MEDIA_BAD_NODE; 162852a38012Sejakowatz if (out_outputs == NULL || out_total_count == NULL) 162952a38012Sejakowatz return B_BAD_VALUE; 163052a38012Sejakowatz 163176669a29Sbeveloper List<media_output> list; 16323620737cSbeveloper media_output *output; 163352a38012Sejakowatz status_t rv; 163452a38012Sejakowatz 16351299bfb2Sbeveloper *out_total_count = 0; 16361299bfb2Sbeveloper 16378b04ffc1Sbeveloper rv = MediaRosterEx(this)->GetAllOutputs(node, &list); 16383620737cSbeveloper if (B_OK != rv) 16393620737cSbeveloper return rv; 16403620737cSbeveloper 16415ac4fbd7Sbeveloper PRINT(4, "BMediaRoster::GetAllOutputsFor node %ld, max %ld\n", node.node, buf_num_outputs); 16425ac4fbd7Sbeveloper 164376669a29Sbeveloper int32 i; 164476669a29Sbeveloper for (i = 0, list.Rewind(); list.GetNext(&output); i++) { 16453620737cSbeveloper out_outputs[i] = *output; 164652a38012Sejakowatz *out_total_count += 1; 16473620737cSbeveloper buf_num_outputs -= 1; 16485ac4fbd7Sbeveloper #if DEBUG >= 3 16495ac4fbd7Sbeveloper PRINT_OUTPUT(" output ", out_outputs[i]); 16505ac4fbd7Sbeveloper #endif 16513620737cSbeveloper if (buf_num_outputs == 0) 16523620737cSbeveloper break; 165352a38012Sejakowatz } 165452a38012Sejakowatz 16558b04ffc1Sbeveloper MediaRosterEx(this)->PublishOutputs(node, &list); 16563620737cSbeveloper return B_OK; 165752a38012Sejakowatz } 165852a38012Sejakowatz 165952a38012Sejakowatz 166052a38012Sejakowatz status_t 166152a38012Sejakowatz BMediaRoster::StartWatching(const BMessenger & where) 166252a38012Sejakowatz { 1663eae26d3dSbeveloper CALLED(); 1664eae26d3dSbeveloper if (!where.IsValid()) { 16655ac4fbd7Sbeveloper ERROR("BMediaRoster::StartWatching: messenger invalid!\n"); 1666eae26d3dSbeveloper return B_BAD_VALUE; 1667eae26d3dSbeveloper } 1668f4925104Sbeveloper return BPrivate::media::notifications::Register(where, media_node::null, B_MEDIA_WILDCARD); 166952a38012Sejakowatz } 167052a38012Sejakowatz 167152a38012Sejakowatz 167252a38012Sejakowatz status_t 167352a38012Sejakowatz BMediaRoster::StartWatching(const BMessenger & where, 167452a38012Sejakowatz int32 notificationType) 167552a38012Sejakowatz { 1676eae26d3dSbeveloper CALLED(); 1677eae26d3dSbeveloper if (!where.IsValid()) { 16785ac4fbd7Sbeveloper ERROR("BMediaRoster::StartWatching: messenger invalid!\n"); 1679eae26d3dSbeveloper return B_BAD_VALUE; 1680eae26d3dSbeveloper } 1681f4925104Sbeveloper if (false == BPrivate::media::notifications::IsValidNotificationRequest(false, notificationType)) { 16825ac4fbd7Sbeveloper ERROR("BMediaRoster::StartWatching: notificationType invalid!\n"); 1683eae26d3dSbeveloper return B_BAD_VALUE; 1684eae26d3dSbeveloper } 1685f4925104Sbeveloper return BPrivate::media::notifications::Register(where, media_node::null, notificationType); 168652a38012Sejakowatz } 168752a38012Sejakowatz 168852a38012Sejakowatz 168952a38012Sejakowatz status_t 169052a38012Sejakowatz BMediaRoster::StartWatching(const BMessenger & where, 169152a38012Sejakowatz const media_node & node, 169252a38012Sejakowatz int32 notificationType) 169352a38012Sejakowatz { 1694eae26d3dSbeveloper CALLED(); 1695eae26d3dSbeveloper if (!where.IsValid()) { 16965ac4fbd7Sbeveloper ERROR("BMediaRoster::StartWatching: messenger invalid!\n"); 1697eae26d3dSbeveloper return B_BAD_VALUE; 1698eae26d3dSbeveloper } 169940f36b03Sbeveloper if (IS_INVALID_NODE(node)) { 17005ac4fbd7Sbeveloper ERROR("BMediaRoster::StartWatching: node invalid!\n"); 1701eae26d3dSbeveloper return B_MEDIA_BAD_NODE; 1702eae26d3dSbeveloper } 1703f4925104Sbeveloper if (false == BPrivate::media::notifications::IsValidNotificationRequest(true, notificationType)) { 17045ac4fbd7Sbeveloper ERROR("BMediaRoster::StartWatching: notificationType invalid!\n"); 1705eae26d3dSbeveloper return B_BAD_VALUE; 1706eae26d3dSbeveloper } 1707f4925104Sbeveloper return BPrivate::media::notifications::Register(where, node, notificationType); 170852a38012Sejakowatz } 170952a38012Sejakowatz 171052a38012Sejakowatz 171152a38012Sejakowatz status_t 171252a38012Sejakowatz BMediaRoster::StopWatching(const BMessenger & where) 171352a38012Sejakowatz { 1714eae26d3dSbeveloper CALLED(); 1715eae26d3dSbeveloper // messenger may already be invalid, so we don't check this 1716f4925104Sbeveloper return BPrivate::media::notifications::Unregister(where, media_node::null, B_MEDIA_WILDCARD); 171752a38012Sejakowatz } 171852a38012Sejakowatz 171952a38012Sejakowatz 172052a38012Sejakowatz status_t 172152a38012Sejakowatz BMediaRoster::StopWatching(const BMessenger & where, 172252a38012Sejakowatz int32 notificationType) 172352a38012Sejakowatz { 1724eae26d3dSbeveloper CALLED(); 1725eae26d3dSbeveloper // messenger may already be invalid, so we don't check this 1726f4925104Sbeveloper if (false == BPrivate::media::notifications::IsValidNotificationRequest(false, notificationType)) { 17275ac4fbd7Sbeveloper ERROR("BMediaRoster::StopWatching: notificationType invalid!\n"); 1728eae26d3dSbeveloper return B_BAD_VALUE; 1729eae26d3dSbeveloper } 1730f4925104Sbeveloper return BPrivate::media::notifications::Unregister(where, media_node::null, notificationType); 173152a38012Sejakowatz } 173252a38012Sejakowatz 173352a38012Sejakowatz 173452a38012Sejakowatz status_t 173552a38012Sejakowatz BMediaRoster::StopWatching(const BMessenger & where, 173652a38012Sejakowatz const media_node & node, 173752a38012Sejakowatz int32 notificationType) 173852a38012Sejakowatz { 1739eae26d3dSbeveloper CALLED(); 1740eae26d3dSbeveloper // messenger may already be invalid, so we don't check this 174140f36b03Sbeveloper if (IS_INVALID_NODE(node)) { 17425ac4fbd7Sbeveloper ERROR("BMediaRoster::StopWatching: node invalid!\n"); 1743eae26d3dSbeveloper return B_MEDIA_BAD_NODE; 1744eae26d3dSbeveloper } 1745f4925104Sbeveloper if (false == BPrivate::media::notifications::IsValidNotificationRequest(true, notificationType)) { 17465ac4fbd7Sbeveloper ERROR("BMediaRoster::StopWatching: notificationType invalid!\n"); 1747eae26d3dSbeveloper return B_BAD_VALUE; 1748eae26d3dSbeveloper } 1749f4925104Sbeveloper return BPrivate::media::notifications::Unregister(where, node, notificationType); 175052a38012Sejakowatz } 175152a38012Sejakowatz 175252a38012Sejakowatz 175352a38012Sejakowatz status_t 175452a38012Sejakowatz BMediaRoster::RegisterNode(BMediaNode * node) 175552a38012Sejakowatz { 175654187cc6Sbeveloper CALLED(); 175754187cc6Sbeveloper // addon-id = -1 (unused), addon-flavor-id = 0 (unused, too) 175854187cc6Sbeveloper return MediaRosterEx(this)->RegisterNode(node, -1, 0); 175954187cc6Sbeveloper } 176054187cc6Sbeveloper 176154187cc6Sbeveloper 176254187cc6Sbeveloper status_t 176354187cc6Sbeveloper BMediaRosterEx::RegisterNode(BMediaNode * node, media_addon_id addonid, int32 flavorid) 176454187cc6Sbeveloper { 176552a38012Sejakowatz CALLED(); 176652a38012Sejakowatz if (node == NULL) 176752a38012Sejakowatz return B_BAD_VALUE; 176852a38012Sejakowatz 176954187cc6Sbeveloper // some sanity check 177054187cc6Sbeveloper // I'm not sure if the media kit warrants to call BMediaNode::AddOn() here. 177154187cc6Sbeveloper // Perhaps we don't need it. 177254187cc6Sbeveloper { 17739e9417d2Sbeveloper BMediaAddOn *addon; 17749e9417d2Sbeveloper int32 addon_flavor_id; 17759e9417d2Sbeveloper media_addon_id addon_id; 17769e9417d2Sbeveloper addon_flavor_id = 0; 17779e9417d2Sbeveloper addon = node->AddOn(&addon_flavor_id); 17789e9417d2Sbeveloper addon_id = addon ? addon->AddonID() : -1; 177954187cc6Sbeveloper ASSERT(addonid == addon_id); 178054187cc6Sbeveloper ASSERT(flavorid == addon_flavor_id); 178154187cc6Sbeveloper } 178252a38012Sejakowatz 178354187cc6Sbeveloper status_t rv; 17849e9417d2Sbeveloper server_register_node_request request; 17859e9417d2Sbeveloper server_register_node_reply reply; 17869e9417d2Sbeveloper 178754187cc6Sbeveloper request.addon_id = addonid; 178854187cc6Sbeveloper request.addon_flavor_id = flavorid; 17899e9417d2Sbeveloper strcpy(request.name, node->Name()); 17909e9417d2Sbeveloper request.kinds = node->Kinds(); 17919e9417d2Sbeveloper request.port = node->ControlPort(); 17929e9417d2Sbeveloper request.team = team; 17939e9417d2Sbeveloper 17948b04ffc1Sbeveloper 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); 17951299bfb2Sbeveloper 17969e9417d2Sbeveloper rv = QueryServer(SERVER_REGISTER_NODE, &request, sizeof(request), &reply, sizeof(reply)); 17979e9417d2Sbeveloper if (rv != B_OK) { 17985ac4fbd7Sbeveloper ERROR("BMediaRoster::RegisterNode: failed to register node %s (error %#lx)\n", node->Name(), rv); 17999e9417d2Sbeveloper return rv; 18009e9417d2Sbeveloper } 18019e9417d2Sbeveloper 18024295907bSbeveloper TRACE("BMediaRoster::RegisterNode: QueryServer SERVER_REGISTER_NODE finished\n"); 18034295907bSbeveloper 18048b04ffc1Sbeveloper // we are a friend class of BMediaNode and initialize this member variable 18059e9417d2Sbeveloper node->fNodeID = reply.nodeid; 18069e9417d2Sbeveloper ASSERT(reply.nodeid == node->Node().node); 18079e9417d2Sbeveloper ASSERT(reply.nodeid == node->ID()); 18089e9417d2Sbeveloper 18099e9417d2Sbeveloper // call the callback 18109e9417d2Sbeveloper node->NodeRegistered(); 18113620737cSbeveloper 18124295907bSbeveloper TRACE("BMediaRoster::RegisterNode: NodeRegistered callback finished\n"); 18134295907bSbeveloper 18140e21b167Sbeveloper // if the BMediaNode also inherits from BTimeSource, we need to call BTimeSource::FinishCreate() 18150e21b167Sbeveloper if (node->Kinds() & B_TIME_SOURCE) { 18160e21b167Sbeveloper BTimeSource *ts; 18170e21b167Sbeveloper ts = dynamic_cast<BTimeSource *>(node); 18180e21b167Sbeveloper if (ts) 18190e21b167Sbeveloper ts->FinishCreate(); 18200e21b167Sbeveloper } 18210e21b167Sbeveloper 18224295907bSbeveloper TRACE("BMediaRoster::RegisterNode: publishing inputs/outputs\n"); 18234295907bSbeveloper 18243620737cSbeveloper // register existing inputs and outputs with the 18253620737cSbeveloper // media_server, this allows GetLiveNodes() to work 18263620737cSbeveloper // with created, but unconnected nodes. 18274d2d96e0Sbeveloper // The node control loop might not be running, or might deadlock 18284d2d96e0Sbeveloper // if we send a message and wait for a reply here. 18294d2d96e0Sbeveloper // We have a pointer to the node, and thus call the functions directly 18304295907bSbeveloper 18313620737cSbeveloper if (node->Kinds() & B_BUFFER_PRODUCER) { 18324d2d96e0Sbeveloper BBufferProducer *bp; 18334d2d96e0Sbeveloper bp = dynamic_cast<BBufferProducer *>(node); 18344d2d96e0Sbeveloper if (bp) { 1835359ac306Sbeveloper List<media_output> list; 18364d2d96e0Sbeveloper if (B_OK == GetAllOutputs(bp, &list)) 1837359ac306Sbeveloper PublishOutputs(node->Node(), &list); 183821871f38Sbeveloper } 18394d2d96e0Sbeveloper } 184021871f38Sbeveloper if (node->Kinds() & B_BUFFER_CONSUMER) { 18414d2d96e0Sbeveloper BBufferConsumer *bc; 18424d2d96e0Sbeveloper bc = dynamic_cast<BBufferConsumer *>(node); 18434d2d96e0Sbeveloper if (bc) { 1844359ac306Sbeveloper List<media_input> list; 18454d2d96e0Sbeveloper if (B_OK == GetAllInputs(bc, &list)) 1846359ac306Sbeveloper PublishInputs(node->Node(), &list); 18473620737cSbeveloper } 18484d2d96e0Sbeveloper } 184921871f38Sbeveloper 18504295907bSbeveloper TRACE("BMediaRoster::RegisterNode: sending NodesCreated\n"); 18514295907bSbeveloper 18521299bfb2Sbeveloper BPrivate::media::notifications::NodesCreated(&reply.nodeid, 1); 18534295907bSbeveloper 18544295907bSbeveloper TRACE("BMediaRoster::RegisterNode: finished\n"); 18554295907bSbeveloper 1856570f7d04Sbeveloper /* 1857570f7d04Sbeveloper TRACE("BMediaRoster::RegisterNode: registered node name '%s', id %ld, addon %ld, flavor %ld\n", node->Name(), node->ID(), addon_id, addon_flavor_id); 1858570f7d04Sbeveloper TRACE("BMediaRoster::RegisterNode: node this %p\n", node); 1859570f7d04Sbeveloper TRACE("BMediaRoster::RegisterNode: node fConsumerThis %p\n", node->fConsumerThis); 1860570f7d04Sbeveloper TRACE("BMediaRoster::RegisterNode: node fProducerThis %p\n", node->fProducerThis); 1861570f7d04Sbeveloper TRACE("BMediaRoster::RegisterNode: node fFileInterfaceThis %p\n", node->fFileInterfaceThis); 1862570f7d04Sbeveloper TRACE("BMediaRoster::RegisterNode: node fControllableThis %p\n", node->fControllableThis); 1863570f7d04Sbeveloper TRACE("BMediaRoster::RegisterNode: node fTimeSourceThis %p\n", node->fTimeSourceThis); 1864570f7d04Sbeveloper */ 18659e9417d2Sbeveloper return B_OK; 186652a38012Sejakowatz } 186752a38012Sejakowatz 186852a38012Sejakowatz 186952a38012Sejakowatz status_t 187052a38012Sejakowatz BMediaRoster::UnregisterNode(BMediaNode * node) 187152a38012Sejakowatz { 18729e9417d2Sbeveloper CALLED(); 18739e9417d2Sbeveloper if (node == NULL) 18749e9417d2Sbeveloper return B_BAD_VALUE; 18759e9417d2Sbeveloper 187660f15390Sbeveloper TRACE("BMediaRoster::UnregisterNode %ld (%p)\n", node->ID(), node); 187760f15390Sbeveloper 187886bce45bSbeveloper if (node->fKinds & NODE_KIND_NO_REFCOUNTING) { 187986bce45bSbeveloper printf("BMediaRoster::UnregisterNode, trying to unregister reference counting disabled timesource, node %ld, port %ld, team %ld\n", node->ID(), node->ControlPort(), team); 188086bce45bSbeveloper return B_OK; 188186bce45bSbeveloper } 18828b04ffc1Sbeveloper if (node->ID() == NODE_UNREGISTERED_ID) { 18835ac4fbd7Sbeveloper PRINT(1, "Warning: BMediaRoster::UnregisterNode: node id %ld, name '%s' already unregistered\n", node->ID(), node->Name()); 18849e9417d2Sbeveloper return B_OK; 18859e9417d2Sbeveloper } 188654187cc6Sbeveloper if (node->fRefCount != 0) { 18875ac4fbd7Sbeveloper PRINT(1, "Warning: BMediaRoster::UnregisterNode: node id %ld, name '%s' has local reference count of %ld\n", node->ID(), node->Name(), node->fRefCount); 188854187cc6Sbeveloper // no return here, we continue and unregister! 188954187cc6Sbeveloper } 189054187cc6Sbeveloper 189154187cc6Sbeveloper // Calling BMediaAddOn::GetConfigurationFor(BMediaNode *node, BMessage *config) 189254187cc6Sbeveloper // if this node was instanciated by an add-on needs to be done *somewhere* 189354187cc6Sbeveloper // We can't do it here because it is already to late (destructor of the node 189454187cc6Sbeveloper // might have been called). 18959e9417d2Sbeveloper 18969e9417d2Sbeveloper server_unregister_node_request request; 18979e9417d2Sbeveloper server_unregister_node_reply reply; 18989e9417d2Sbeveloper status_t rv; 18999e9417d2Sbeveloper 19009e9417d2Sbeveloper request.nodeid = node->ID(); 19019e9417d2Sbeveloper request.team = team; 19029e9417d2Sbeveloper 19031299bfb2Sbeveloper // send a notification 19041299bfb2Sbeveloper BPrivate::media::notifications::NodesDeleted(&request.nodeid, 1); 19051299bfb2Sbeveloper 19069e9417d2Sbeveloper rv = QueryServer(SERVER_UNREGISTER_NODE, &request, sizeof(request), &reply, sizeof(reply)); 19079e9417d2Sbeveloper if (rv != B_OK) { 19085ac4fbd7Sbeveloper ERROR("BMediaRoster::UnregisterNode: failed to unregister node id %ld, name '%s' (error %#lx)\n", node->ID(), node->Name(), rv); 19099e9417d2Sbeveloper return rv; 19109e9417d2Sbeveloper } 19119e9417d2Sbeveloper 191254187cc6Sbeveloper if (reply.addonid != -1) { 191354187cc6Sbeveloper // Small problem here, we can't use DormantNodeManager::PutAddon(), as 191454187cc6Sbeveloper // UnregisterNode() is called by a dormant node itself (by the destructor). 191554187cc6Sbeveloper // The add-on that contains the node needs to remain in memory until the 191654187cc6Sbeveloper // destructor execution is finished. 191754187cc6Sbeveloper // DormantNodeManager::PutAddonDelayed() will delay unloading. 191854187cc6Sbeveloper _DormantNodeManager->PutAddonDelayed(reply.addonid); 1919cf4e2277Sbeveloper 192073794717Sbeveloper rv = MediaRosterEx(this)->DecrementAddonFlavorInstancesCount(reply.addonid, reply.flavorid); 192154187cc6Sbeveloper if (rv != B_OK) { 19225ac4fbd7Sbeveloper ERROR("BMediaRoster::UnregisterNode: DecrementAddonFlavorInstancesCount failed\n"); 192354187cc6Sbeveloper // this is really a problem, but we can't fail now 192454187cc6Sbeveloper } 19258b04ffc1Sbeveloper } 19269e9417d2Sbeveloper 19271299bfb2Sbeveloper // we are a friend class of BMediaNode and invalidate this member variable 19288b04ffc1Sbeveloper node->fNodeID = NODE_UNREGISTERED_ID; 19299e9417d2Sbeveloper 19309e9417d2Sbeveloper return B_OK; 193152a38012Sejakowatz } 193252a38012Sejakowatz 193352a38012Sejakowatz 193452a38012Sejakowatz // thread safe for multiple calls to Roster() 193552a38012Sejakowatz /* static */ BMediaRoster * 193652a38012Sejakowatz BMediaRoster::Roster(status_t *out_error) 193752a38012Sejakowatz { 193852a38012Sejakowatz static BLocker locker("BMediaRoster::Roster locker"); 193952a38012Sejakowatz locker.Lock(); 19408496c38aSbeveloper if (out_error) 19418496c38aSbeveloper *out_error = B_OK; 194252a38012Sejakowatz if (_sDefault == NULL) { 19438496c38aSbeveloper status_t err; 1944dcfb6bfcSJérôme Duval _sDefault = new BMediaRosterEx(&err); 1945dcfb6bfcSJérôme Duval if (err != B_OK) { 1946dcfb6bfcSJérôme Duval if (_sDefault) { 1947dcfb6bfcSJérôme Duval _sDefault->Lock(); 1948dcfb6bfcSJérôme Duval _sDefault->Quit(); 1949dcfb6bfcSJérôme Duval _sDefault = NULL; 1950dcfb6bfcSJérôme Duval } 19518496c38aSbeveloper if (out_error) 19528496c38aSbeveloper *out_error = err; 19538496c38aSbeveloper } 195452a38012Sejakowatz } 195552a38012Sejakowatz locker.Unlock(); 195652a38012Sejakowatz return _sDefault; 195752a38012Sejakowatz } 195852a38012Sejakowatz 195952a38012Sejakowatz 196052a38012Sejakowatz // won't create it if there isn't one 196152a38012Sejakowatz // not thread safe if you call Roster() at the same time 196252a38012Sejakowatz /* static */ BMediaRoster * 196352a38012Sejakowatz BMediaRoster::CurrentRoster() 196452a38012Sejakowatz { 196552a38012Sejakowatz return _sDefault; 196652a38012Sejakowatz } 196752a38012Sejakowatz 196852a38012Sejakowatz 196952a38012Sejakowatz status_t 197052a38012Sejakowatz BMediaRoster::SetTimeSourceFor(media_node_id node, 197152a38012Sejakowatz media_node_id time_source) 197252a38012Sejakowatz { 1973aac800c2Sbeveloper CALLED(); 197440f36b03Sbeveloper if (IS_INVALID_NODEID(node) || IS_INVALID_NODEID(time_source)) 1975aac800c2Sbeveloper return B_BAD_VALUE; 1976aac800c2Sbeveloper 1977aac800c2Sbeveloper media_node clone; 1978aac800c2Sbeveloper status_t rv, result; 1979aac800c2Sbeveloper 19805917dd5bSbeveloper TRACE("BMediaRoster::SetTimeSourceFor: node %ld will be assigned time source %ld\n", node, time_source); 19815917dd5bSbeveloper 19825917dd5bSbeveloper printf("BMediaRoster::SetTimeSourceFor: node %ld time source %ld enter\n", node, time_source); 19835917dd5bSbeveloper 198486bce45bSbeveloper // we need to get a clone of the node to have a port id 1985aac800c2Sbeveloper rv = GetNodeFor(node, &clone); 1986aac800c2Sbeveloper if (rv != B_OK) { 19875ac4fbd7Sbeveloper ERROR("BMediaRoster::SetTimeSourceFor, GetNodeFor failed, node id %ld\n", node); 198852a38012Sejakowatz return B_ERROR; 198952a38012Sejakowatz } 199052a38012Sejakowatz 199186bce45bSbeveloper // we just send the request to set time_source-id as timesource to the node, 199286bce45bSbeveloper // the NODE_SET_TIMESOURCE handler code will do the real assignment 1993aac800c2Sbeveloper result = B_OK; 1994aac800c2Sbeveloper node_set_timesource_command cmd; 1995aac800c2Sbeveloper cmd.timesource_id = time_source; 1996aac800c2Sbeveloper rv = SendToPort(clone.port, NODE_SET_TIMESOURCE, &cmd, sizeof(cmd)); 1997aac800c2Sbeveloper if (rv != B_OK) { 19985ac4fbd7Sbeveloper ERROR("BMediaRoster::SetTimeSourceFor, sending NODE_SET_TIMESOURCE failed, node id %ld\n", node); 1999aac800c2Sbeveloper result = B_ERROR; 2000aac800c2Sbeveloper } 2001aac800c2Sbeveloper 200260f15390Sbeveloper // we release the clone 2003aac800c2Sbeveloper rv = ReleaseNode(clone); 2004aac800c2Sbeveloper if (rv != B_OK) { 20055ac4fbd7Sbeveloper ERROR("BMediaRoster::SetTimeSourceFor, ReleaseNode failed, node id %ld\n", node); 2006aac800c2Sbeveloper result = B_ERROR; 2007aac800c2Sbeveloper } 2008aac800c2Sbeveloper 20095917dd5bSbeveloper printf("BMediaRoster::SetTimeSourceFor: node %ld time source %ld leave\n", node, time_source); 20105917dd5bSbeveloper 2011aac800c2Sbeveloper return result; 2012aac800c2Sbeveloper } 2013aac800c2Sbeveloper 201452a38012Sejakowatz 201552a38012Sejakowatz status_t 201652a38012Sejakowatz BMediaRoster::GetParameterWebFor(const media_node & node, 201752a38012Sejakowatz BParameterWeb ** out_web) 201852a38012Sejakowatz { 201928ad138aSbeveloper CALLED(); 202028ad138aSbeveloper if (out_web == NULL) 202128ad138aSbeveloper return B_BAD_VALUE; 202228ad138aSbeveloper if (IS_INVALID_NODE(node)) 202328ad138aSbeveloper return B_MEDIA_BAD_NODE; 202428ad138aSbeveloper if ((node.kind & B_CONTROLLABLE) == 0) 202528ad138aSbeveloper return B_MEDIA_BAD_NODE; 202628ad138aSbeveloper 202728ad138aSbeveloper controllable_get_parameter_web_request request; 202828ad138aSbeveloper controllable_get_parameter_web_reply reply; 202928ad138aSbeveloper 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}; 203028ad138aSbeveloper int32 size; 203128ad138aSbeveloper 203228ad138aSbeveloper // XXX it might be better to query the node for the (current) parameter size first 203328ad138aSbeveloper for (int i = 0; (size = requestsize[i]) != 0; i++) { 203428ad138aSbeveloper status_t rv; 203528ad138aSbeveloper area_id area; 203628ad138aSbeveloper void *data; 203728ad138aSbeveloper area = create_area("parameter web data", &data, B_ANY_ADDRESS, size, B_NO_LOCK, B_READ_AREA | B_WRITE_AREA); 203828ad138aSbeveloper if (area < B_OK) { 20395ac4fbd7Sbeveloper ERROR("BMediaRoster::GetParameterWebFor couldn't create area of size %ld\n", size); 204028ad138aSbeveloper return B_ERROR; 204128ad138aSbeveloper } 204228ad138aSbeveloper request.maxsize = size; 204328ad138aSbeveloper request.area = area; 204428ad138aSbeveloper rv = QueryPort(node.port, CONTROLLABLE_GET_PARAMETER_WEB, &request, sizeof(request), &reply, sizeof(reply)); 204528ad138aSbeveloper if (rv != B_OK) { 20465ac4fbd7Sbeveloper ERROR("BMediaRoster::GetParameterWebFor CONTROLLABLE_GET_PARAMETER_WEB failed\n"); 204728ad138aSbeveloper delete_area(area); 204828ad138aSbeveloper return B_ERROR; 204928ad138aSbeveloper } 205028ad138aSbeveloper if (reply.size == 0) { 205128ad138aSbeveloper // no parameter web available 205228ad138aSbeveloper // XXX should we return an error? 20535ac4fbd7Sbeveloper ERROR("BMediaRoster::GetParameterWebFor node %ld has no parameter web\n", node.node); 205428ad138aSbeveloper *out_web = new BParameterWeb(); 205528ad138aSbeveloper delete_area(area); 205660f15390Sbeveloper return B_OK; 205752a38012Sejakowatz } 205828ad138aSbeveloper if (reply.size > 0) { 205928ad138aSbeveloper // we got a flattened parameter web! 206028ad138aSbeveloper *out_web = new BParameterWeb(); 206128ad138aSbeveloper 2062d91580cdSbeveloper printf("BMediaRoster::GetParameterWebFor Unflattening %ld bytes, 0x%08lx, 0x%08lx, 0x%08lx, 0x%08lx\n", 206328ad138aSbeveloper reply.size, ((uint32*)data)[0], ((uint32*)data)[1], ((uint32*)data)[2], ((uint32*)data)[3]); 206428ad138aSbeveloper 206528ad138aSbeveloper rv = (*out_web)->Unflatten(reply.code, data, reply.size); 206628ad138aSbeveloper if (rv != B_OK) { 20675ac4fbd7Sbeveloper ERROR("BMediaRoster::GetParameterWebFor Unflatten failed, %s\n", strerror(rv)); 206828ad138aSbeveloper delete_area(area); 206928ad138aSbeveloper delete *out_web; 207028ad138aSbeveloper return B_ERROR; 207128ad138aSbeveloper } 207228ad138aSbeveloper delete_area(area); 207328ad138aSbeveloper return B_OK; 207428ad138aSbeveloper } 207528ad138aSbeveloper delete_area(area); 207628ad138aSbeveloper ASSERT(reply.size == -1); 207728ad138aSbeveloper // parameter web data was too large 207828ad138aSbeveloper // loop and try a larger size 207928ad138aSbeveloper } 20805ac4fbd7Sbeveloper ERROR("BMediaRoster::GetParameterWebFor node %ld has no parameter web larger than %ld\n", node.node, size); 208128ad138aSbeveloper return B_ERROR; 208228ad138aSbeveloper } 208352a38012Sejakowatz 208452a38012Sejakowatz 208552a38012Sejakowatz status_t 208652a38012Sejakowatz BMediaRoster::StartControlPanel(const media_node & node, 208752a38012Sejakowatz BMessenger * out_messenger) 208852a38012Sejakowatz { 208952a38012Sejakowatz UNIMPLEMENTED(); 209052a38012Sejakowatz return B_ERROR; 209152a38012Sejakowatz } 209252a38012Sejakowatz 209352a38012Sejakowatz 209452a38012Sejakowatz status_t 209552a38012Sejakowatz BMediaRoster::GetDormantNodes(dormant_node_info * out_info, 209652a38012Sejakowatz int32 * io_count, 209752a38012Sejakowatz const media_format * has_input /* = NULL */, 209852a38012Sejakowatz const media_format * has_output /* = NULL */, 209952a38012Sejakowatz const char * name /* = NULL */, 210052a38012Sejakowatz uint64 require_kinds /* = NULL */, 210152a38012Sejakowatz uint64 deny_kinds /* = NULL */) 210252a38012Sejakowatz { 210352a38012Sejakowatz CALLED(); 210452a38012Sejakowatz if (out_info == NULL) 210552a38012Sejakowatz return B_BAD_VALUE; 210652a38012Sejakowatz if (io_count == NULL) 210752a38012Sejakowatz return B_BAD_VALUE; 210852a38012Sejakowatz if (*io_count <= 0) 210952a38012Sejakowatz return B_BAD_VALUE; 211052a38012Sejakowatz 211152a38012Sejakowatz xfer_server_get_dormant_nodes msg; 211252a38012Sejakowatz port_id port; 211352a38012Sejakowatz status_t rv; 211452a38012Sejakowatz 21154295907bSbeveloper port = find_port(MEDIA_SERVER_PORT_NAME); 211652a38012Sejakowatz if (port <= B_OK) 211752a38012Sejakowatz return B_ERROR; 211852a38012Sejakowatz 211952a38012Sejakowatz msg.maxcount = *io_count; 212052a38012Sejakowatz msg.has_input = (bool) has_input; 212152a38012Sejakowatz if (has_input) 212252a38012Sejakowatz msg.inputformat = *has_input; // XXX we should not make a flat copy of media_format 212352a38012Sejakowatz msg.has_output = (bool) has_output; 212452a38012Sejakowatz if (has_output) 212552a38012Sejakowatz msg.outputformat = *has_output;; // XXX we should not make a flat copy of media_format 212652a38012Sejakowatz msg.has_name = (bool) name; 212752a38012Sejakowatz if (name) { 21289e9417d2Sbeveloper int len = strlen(name); 21299e9417d2Sbeveloper len = min_c(len, (int)sizeof(msg.name) - 1); 213052a38012Sejakowatz memcpy(msg.name, name, len); 213152a38012Sejakowatz msg.name[len] = 0; 213252a38012Sejakowatz } 213352a38012Sejakowatz msg.require_kinds = require_kinds; 213452a38012Sejakowatz msg.deny_kinds = deny_kinds; 213552a38012Sejakowatz msg.reply_port = _PortPool->GetPort(); 213652a38012Sejakowatz 213752a38012Sejakowatz rv = write_port(port, SERVER_GET_DORMANT_NODES, &msg, sizeof(msg)); 213852a38012Sejakowatz if (rv != B_OK) { 213952a38012Sejakowatz _PortPool->PutPort(msg.reply_port); 214052a38012Sejakowatz return rv; 214152a38012Sejakowatz } 214252a38012Sejakowatz 214352a38012Sejakowatz xfer_server_get_dormant_nodes_reply reply; 214452a38012Sejakowatz int32 code; 214552a38012Sejakowatz 214652a38012Sejakowatz rv = read_port(msg.reply_port, &code, &reply, sizeof(reply)); 214752a38012Sejakowatz if (rv < B_OK) { 214852a38012Sejakowatz _PortPool->PutPort(msg.reply_port); 214952a38012Sejakowatz return rv; 215052a38012Sejakowatz } 215152a38012Sejakowatz 215252a38012Sejakowatz *io_count = reply.count; 215352a38012Sejakowatz 215452a38012Sejakowatz if (*io_count > 0) { 215552a38012Sejakowatz rv = read_port(msg.reply_port, &code, out_info, *io_count * sizeof(dormant_node_info)); 215652a38012Sejakowatz if (rv < B_OK) 215752a38012Sejakowatz reply.result = rv; 215852a38012Sejakowatz } 215952a38012Sejakowatz _PortPool->PutPort(msg.reply_port); 216052a38012Sejakowatz 216152a38012Sejakowatz return reply.result; 216252a38012Sejakowatz } 216352a38012Sejakowatz 21648b04ffc1Sbeveloper /* This function is used to do the real work of instantiating a dormant node. It is either 21658b04ffc1Sbeveloper * called by the media_addon_server to instantiate a global node, or it gets called from 21668b04ffc1Sbeveloper * BMediaRoster::InstantiateDormantNode() to create a local one. 21678b04ffc1Sbeveloper * 21688b04ffc1Sbeveloper * Checks concerning global/local are not done here. 21698b04ffc1Sbeveloper */ 217052a38012Sejakowatz status_t 217154187cc6Sbeveloper BMediaRosterEx::InstantiateDormantNode(media_addon_id addonid, int32 flavorid, team_id creator, media_node *out_node) 217252a38012Sejakowatz { 217354187cc6Sbeveloper // This function is always called from the correct context, if the node 217454187cc6Sbeveloper // is supposed to be global, it is called from the media_addon_server. 217554187cc6Sbeveloper 217652a38012Sejakowatz // if B_FLAVOR_IS_GLOBAL, we need to use the BMediaAddOn object that 217752a38012Sejakowatz // resides in the media_addon_server 217852a38012Sejakowatz 21798b04ffc1Sbeveloper // RegisterNode() must be called for nodes instantiated from add-ons, 21808b04ffc1Sbeveloper // since the media kit warrants that it's done automatically. 218152a38012Sejakowatz 218254187cc6Sbeveloper // addonid Indicates the ID number of the media add-on in which the node resides. 218354187cc6Sbeveloper // flavorid Indicates the internal ID number that the add-on uses to identify the flavor, 218454187cc6Sbeveloper // this is the number that was published by BMediaAddOn::GetFlavorAt() in the 21858b04ffc1Sbeveloper // flavor_info::internal_id field. 218654187cc6Sbeveloper // creator The creator team is -1 if nodes are created locally. If created globally, 218754187cc6Sbeveloper // it will contain (while called in media_addon_server context) the team-id of 218854187cc6Sbeveloper // the team that requested the instantiation. 21898b04ffc1Sbeveloper 219060f15390Sbeveloper TRACE("BMediaRosterEx::InstantiateDormantNode: addon-id %ld, flavor_id %ld\n", addonid, flavorid); 21918b04ffc1Sbeveloper 21928b04ffc1Sbeveloper // Get flavor_info from the server 21938b04ffc1Sbeveloper dormant_flavor_info node_info; 21948c6a6096Sbeveloper status_t rv; 21958b04ffc1Sbeveloper rv = GetDormantFlavorInfo(addonid, flavorid, &node_info); 21968b04ffc1Sbeveloper if (rv != B_OK) { 21975ac4fbd7Sbeveloper ERROR("BMediaRosterEx::InstantiateDormantNode error: failed to get dormant_flavor_info for addon-id %ld, flavor-id %ld\n", addonid, flavorid); 219852a38012Sejakowatz return B_ERROR; 219952a38012Sejakowatz } 22008b04ffc1Sbeveloper 2201908eaf85Sbeveloper //ASSERT(node_info.internal_id == flavorid); 2202908eaf85Sbeveloper if (node_info.internal_id != flavorid) { 22034d2d96e0Sbeveloper ERROR("############# BMediaRosterEx::InstantiateDormantNode failed: ID mismatch for addon-id %ld, flavor-id %ld, node_info.internal_id %ld, node_info.name %s\n", addonid, flavorid, node_info.internal_id, node_info.name); 2204908eaf85Sbeveloper return B_ERROR; 2205908eaf85Sbeveloper } 22068b04ffc1Sbeveloper 22078b04ffc1Sbeveloper // load the BMediaAddOn object 22088b04ffc1Sbeveloper BMediaAddOn *addon; 22098b04ffc1Sbeveloper addon = _DormantNodeManager->GetAddon(addonid); 22108b04ffc1Sbeveloper if (!addon) { 22115ac4fbd7Sbeveloper ERROR("BMediaRosterEx::InstantiateDormantNode: GetAddon failed\n"); 22128b04ffc1Sbeveloper return B_ERROR; 22138b04ffc1Sbeveloper } 22148b04ffc1Sbeveloper 221554187cc6Sbeveloper // Now we need to try to increment the use count of this addon flavor 221654187cc6Sbeveloper // in the server. This can fail if the total number instances of this 221754187cc6Sbeveloper // flavor is limited. 221873794717Sbeveloper rv = IncrementAddonFlavorInstancesCount(addonid, flavorid); 221954187cc6Sbeveloper if (rv != B_OK) { 22205ac4fbd7Sbeveloper ERROR("BMediaRosterEx::InstantiateDormantNode error: can't create more nodes for addon-id %ld, flavor-id %ld\n", addonid, flavorid); 222154187cc6Sbeveloper // Put the addon back into the pool 222254187cc6Sbeveloper _DormantNodeManager->PutAddon(addonid); 222354187cc6Sbeveloper return B_ERROR; 222454187cc6Sbeveloper } 222554187cc6Sbeveloper 22268b04ffc1Sbeveloper BMessage config; 222754187cc6Sbeveloper rv = LoadNodeConfiguration(addonid, flavorid, &config); 222854187cc6Sbeveloper if (rv != B_OK) { 22295ac4fbd7Sbeveloper ERROR("BMediaRosterEx::InstantiateDormantNode: couldn't load configuration for addon-id %ld, flavor-id %ld\n", addonid, flavorid); 223054187cc6Sbeveloper // do not return, this is a minor problem, not a reason to fail 223154187cc6Sbeveloper } 22328b04ffc1Sbeveloper 22338b04ffc1Sbeveloper BMediaNode *node; 22348b04ffc1Sbeveloper status_t out_error; 22358b04ffc1Sbeveloper 223654187cc6Sbeveloper out_error = B_OK; 22378b04ffc1Sbeveloper node = addon->InstantiateNodeFor(&node_info, &config, &out_error); 223816b7eea4Sbeveloper if (!node) { 22395ac4fbd7Sbeveloper ERROR("BMediaRosterEx::InstantiateDormantNode: InstantiateNodeFor failed\n"); 224054187cc6Sbeveloper // Put the addon back into the pool 22418b04ffc1Sbeveloper _DormantNodeManager->PutAddon(addonid); 224254187cc6Sbeveloper // We must decrement the use count of this addon flavor in the 224354187cc6Sbeveloper // server to compensate the increment done in the beginning. 224473794717Sbeveloper rv = DecrementAddonFlavorInstancesCount(addonid, flavorid); 224554187cc6Sbeveloper if (rv != B_OK) { 22465ac4fbd7Sbeveloper ERROR("BMediaRosterEx::InstantiateDormantNode: DecrementAddonFlavorInstancesCount failed\n"); 224716b7eea4Sbeveloper } 224854187cc6Sbeveloper return (out_error != B_OK) ? out_error : B_ERROR; 224954187cc6Sbeveloper } 225054187cc6Sbeveloper 225154187cc6Sbeveloper rv = RegisterNode(node, addonid, flavorid); 22528c6a6096Sbeveloper if (rv != B_OK) { 22535ac4fbd7Sbeveloper ERROR("BMediaRosterEx::InstantiateDormantNode: RegisterNode failed\n"); 22548c6a6096Sbeveloper delete node; 225554187cc6Sbeveloper // Put the addon back into the pool 22568b04ffc1Sbeveloper _DormantNodeManager->PutAddon(addonid); 225754187cc6Sbeveloper // We must decrement the use count of this addon flavor in the 225854187cc6Sbeveloper // server to compensate the increment done in the beginning. 225973794717Sbeveloper rv = DecrementAddonFlavorInstancesCount(addonid, flavorid); 226054187cc6Sbeveloper if (rv != B_OK) { 22615ac4fbd7Sbeveloper ERROR("BMediaRosterEx::InstantiateDormantNode: DecrementAddonFlavorInstancesCount failed\n"); 226254187cc6Sbeveloper } 22638c6a6096Sbeveloper return B_ERROR; 22648c6a6096Sbeveloper } 22658c6a6096Sbeveloper 226654187cc6Sbeveloper if (creator != -1) { 226754187cc6Sbeveloper // send a message to the server to assign team "creator" as creator of node "node->ID()" 226854187cc6Sbeveloper printf("!!! BMediaRosterEx::InstantiateDormantNode assigning team %ld as creator of node %ld\n", creator, node->ID()); 226954187cc6Sbeveloper rv = MediaRosterEx(this)->SetNodeCreator(node->ID(), creator); 227054187cc6Sbeveloper if (rv != B_OK) { 22715ac4fbd7Sbeveloper ERROR("BMediaRosterEx::InstantiateDormantNode failed to assign team %ld as creator of node %ld\n", creator, node->ID()); 227254187cc6Sbeveloper // do not return, this is a minor problem, not a reason to fail 227354187cc6Sbeveloper } 227454187cc6Sbeveloper } 227554187cc6Sbeveloper 227654187cc6Sbeveloper // RegisterNode() does remember the add-on id in the server 227754187cc6Sbeveloper // and UnregisterNode() will call DormantNodeManager::PutAddon() 227854187cc6Sbeveloper // when the node is unregistered. 22798c6a6096Sbeveloper 228016b7eea4Sbeveloper *out_node = node->Node(); 2281cf4e2277Sbeveloper 228260f15390Sbeveloper 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); 2283cf4e2277Sbeveloper 228416b7eea4Sbeveloper return B_OK; 228516b7eea4Sbeveloper } 228652a38012Sejakowatz 228752a38012Sejakowatz 228852a38012Sejakowatz status_t 22898b04ffc1Sbeveloper BMediaRoster::InstantiateDormantNode(const dormant_node_info & in_info, 22908b04ffc1Sbeveloper media_node * out_node, 22918b04ffc1Sbeveloper uint32 flags /* currently 0 or B_FLAVOR_IS_GLOBAL or B_FLAVOR_IS_LOCAL */ ) 22928b04ffc1Sbeveloper { 22938b04ffc1Sbeveloper CALLED(); 22948b04ffc1Sbeveloper if (out_node == 0) 22958b04ffc1Sbeveloper return B_BAD_VALUE; 22968b04ffc1Sbeveloper if (in_info.addon <= 0) { 22975ac4fbd7Sbeveloper ERROR("BMediaRoster::InstantiateDormantNode error: addon-id %ld invalid.\n", in_info.addon); 22988b04ffc1Sbeveloper return B_BAD_VALUE; 22998b04ffc1Sbeveloper } 23008b04ffc1Sbeveloper 2301d91580cdSbeveloper printf("BMediaRoster::InstantiateDormantNode: addon-id %ld, flavor_id %ld, flags 0x%lX\n", in_info.addon, in_info.flavor_id, flags); 23028b04ffc1Sbeveloper 23038b04ffc1Sbeveloper // Get flavor_info from the server 23048b04ffc1Sbeveloper // XXX this is a little overhead, as we get the full blown dormant_flavor_info, 23058b04ffc1Sbeveloper // XXX but only need the flags. 23068b04ffc1Sbeveloper dormant_flavor_info node_info; 23078b04ffc1Sbeveloper status_t rv; 23088b04ffc1Sbeveloper rv = MediaRosterEx(this)->GetDormantFlavorInfo(in_info.addon, in_info.flavor_id, &node_info); 23098b04ffc1Sbeveloper if (rv != B_OK) { 23105ac4fbd7Sbeveloper ERROR("BMediaRoster::InstantiateDormantNode: failed to get dormant_flavor_info for addon-id %ld, flavor-id %ld\n", in_info.addon, in_info.flavor_id); 2311626824eaSbeveloper return B_NAME_NOT_FOUND; 23128b04ffc1Sbeveloper } 23138b04ffc1Sbeveloper 23148b04ffc1Sbeveloper ASSERT(node_info.internal_id == in_info.flavor_id); 23158b04ffc1Sbeveloper 2316d91580cdSbeveloper printf("BMediaRoster::InstantiateDormantNode: name \"%s\", info \"%s\", flavor_flags 0x%lX, internal_id %ld, possible_count %ld\n", 23178b04ffc1Sbeveloper node_info.name, node_info.info, node_info.flavor_flags, node_info.internal_id, node_info.possible_count); 23188b04ffc1Sbeveloper 23198b04ffc1Sbeveloper #if DEBUG 23208b04ffc1Sbeveloper if (flags & B_FLAVOR_IS_LOCAL) 23218b04ffc1Sbeveloper printf("BMediaRoster::InstantiateDormantNode: caller requested B_FLAVOR_IS_LOCAL\n"); 23228b04ffc1Sbeveloper if (flags & B_FLAVOR_IS_GLOBAL) 23238b04ffc1Sbeveloper printf("BMediaRoster::InstantiateDormantNode: caller requested B_FLAVOR_IS_GLOBAL\n"); 23248b04ffc1Sbeveloper if (node_info.flavor_flags & B_FLAVOR_IS_LOCAL) 23258b04ffc1Sbeveloper printf("BMediaRoster::InstantiateDormantNode: node requires B_FLAVOR_IS_LOCAL\n"); 23268b04ffc1Sbeveloper if (node_info.flavor_flags & B_FLAVOR_IS_GLOBAL) 23278b04ffc1Sbeveloper printf("BMediaRoster::InstantiateDormantNode: node requires B_FLAVOR_IS_GLOBAL\n"); 23288b04ffc1Sbeveloper #endif 23298b04ffc1Sbeveloper 23308b04ffc1Sbeveloper // Make sure that flags demanded by the dormant node and those requested 23318b04ffc1Sbeveloper // by the caller are not incompatible. 23328b04ffc1Sbeveloper if ((node_info.flavor_flags & B_FLAVOR_IS_GLOBAL) && (flags & B_FLAVOR_IS_LOCAL)) { 23335ac4fbd7Sbeveloper ERROR("BMediaRoster::InstantiateDormantNode: requested B_FLAVOR_IS_LOCAL, but dormant node has B_FLAVOR_IS_GLOBAL\n"); 2334626824eaSbeveloper return B_NAME_NOT_FOUND; 23358b04ffc1Sbeveloper } 23368b04ffc1Sbeveloper if ((node_info.flavor_flags & B_FLAVOR_IS_LOCAL) && (flags & B_FLAVOR_IS_GLOBAL)) { 23375ac4fbd7Sbeveloper ERROR("BMediaRoster::InstantiateDormantNode: requested B_FLAVOR_IS_GLOBAL, but dormant node has B_FLAVOR_IS_LOCAL\n"); 2338626824eaSbeveloper return B_NAME_NOT_FOUND; 23398b04ffc1Sbeveloper } 234054187cc6Sbeveloper 23418b04ffc1Sbeveloper // If either the node, or the caller requested to make the instance global 23428b04ffc1Sbeveloper // we will do it by forwarding this request into the media_addon_server, which 23438b04ffc1Sbeveloper // in turn will call BMediaRosterEx::InstantiateDormantNode to create the node 23448b04ffc1Sbeveloper // there and make it globally available. 23458b04ffc1Sbeveloper if ((node_info.flavor_flags & B_FLAVOR_IS_GLOBAL) || (flags & B_FLAVOR_IS_GLOBAL)) { 23468b04ffc1Sbeveloper 2347cf4e2277Sbeveloper printf("BMediaRoster::InstantiateDormantNode: creating global object in media_addon_server\n"); 2348cf4e2277Sbeveloper 23498b04ffc1Sbeveloper addonserver_instantiate_dormant_node_request request; 23508b04ffc1Sbeveloper addonserver_instantiate_dormant_node_reply reply; 23518b04ffc1Sbeveloper request.addonid = in_info.addon; 23528b04ffc1Sbeveloper request.flavorid = in_info.flavor_id; 235354187cc6Sbeveloper request.creator_team = team; // creator team is allowed to also release global nodes 23548b04ffc1Sbeveloper rv = QueryAddonServer(ADDONSERVER_INSTANTIATE_DORMANT_NODE, &request, sizeof(request), &reply, sizeof(reply)); 23558b04ffc1Sbeveloper if (rv == B_OK) { 23568b04ffc1Sbeveloper *out_node = reply.node; 23578b04ffc1Sbeveloper } 23588b04ffc1Sbeveloper 23598b04ffc1Sbeveloper } else { 23608b04ffc1Sbeveloper 236154187cc6Sbeveloper // creator team = -1, as this is a local node 2362626824eaSbeveloper rv = MediaRosterEx(this)->InstantiateDormantNode(in_info.addon, in_info.flavor_id, -1, out_node); 2363626824eaSbeveloper 23648b04ffc1Sbeveloper } 2365626824eaSbeveloper if (rv != B_OK) { 2366626824eaSbeveloper *out_node = media_node::null; 2367626824eaSbeveloper return B_NAME_NOT_FOUND; 2368626824eaSbeveloper } 2369626824eaSbeveloper return B_OK; 23708b04ffc1Sbeveloper } 23718b04ffc1Sbeveloper 23728b04ffc1Sbeveloper 23738b04ffc1Sbeveloper status_t 23748b04ffc1Sbeveloper BMediaRoster::InstantiateDormantNode(const dormant_node_info & in_info, 23758b04ffc1Sbeveloper media_node * out_node) 23768b04ffc1Sbeveloper { 23778b04ffc1Sbeveloper return InstantiateDormantNode(in_info, out_node, 0); 23788b04ffc1Sbeveloper } 23798b04ffc1Sbeveloper 23808b04ffc1Sbeveloper 23818b04ffc1Sbeveloper status_t 238252a38012Sejakowatz BMediaRoster::GetDormantNodeFor(const media_node & node, 238352a38012Sejakowatz dormant_node_info * out_info) 238452a38012Sejakowatz { 238585dfab2bSbeveloper CALLED(); 238685dfab2bSbeveloper if (out_info == NULL) 238785dfab2bSbeveloper return B_BAD_VALUE; 238840f36b03Sbeveloper if (IS_INVALID_NODE(node)) 238985dfab2bSbeveloper return B_MEDIA_BAD_NODE; 239052a38012Sejakowatz 239185dfab2bSbeveloper server_get_dormant_node_for_request request; 239285dfab2bSbeveloper server_get_dormant_node_for_reply reply; 239385dfab2bSbeveloper status_t rv; 239485dfab2bSbeveloper 239585dfab2bSbeveloper request.node = node; 239685dfab2bSbeveloper 23971299bfb2Sbeveloper rv = QueryServer(SERVER_GET_DORMANT_NODE_FOR, &request, sizeof(request), &reply, sizeof(reply)); 239885dfab2bSbeveloper if (rv != B_OK) 239985dfab2bSbeveloper return rv; 240085dfab2bSbeveloper 240185dfab2bSbeveloper *out_info = reply.node_info; 240285dfab2bSbeveloper return B_OK; 240352a38012Sejakowatz } 240452a38012Sejakowatz 240552a38012Sejakowatz status_t 24068b04ffc1Sbeveloper BMediaRosterEx::GetDormantFlavorInfo(media_addon_id addonid, 24078b04ffc1Sbeveloper int32 flavorid, 240852a38012Sejakowatz dormant_flavor_info * out_flavor) 240952a38012Sejakowatz { 241052a38012Sejakowatz CALLED(); 24119bedd42cSbeveloper if (out_flavor == NULL) 24129bedd42cSbeveloper return B_BAD_VALUE; 241352a38012Sejakowatz 241452a38012Sejakowatz xfer_server_get_dormant_flavor_info msg; 241552a38012Sejakowatz xfer_server_get_dormant_flavor_info_reply *reply; 241652a38012Sejakowatz port_id port; 241752a38012Sejakowatz status_t rv; 241852a38012Sejakowatz int32 code; 241952a38012Sejakowatz 24204295907bSbeveloper port = find_port(MEDIA_SERVER_PORT_NAME); 242152a38012Sejakowatz if (port <= B_OK) 242252a38012Sejakowatz return B_ERROR; 242352a38012Sejakowatz 242452a38012Sejakowatz reply = (xfer_server_get_dormant_flavor_info_reply *) malloc(16000); 242552a38012Sejakowatz if (reply == 0) 242652a38012Sejakowatz return B_ERROR; 242752a38012Sejakowatz 24288b04ffc1Sbeveloper msg.addon = addonid; 24298b04ffc1Sbeveloper msg.flavor_id = flavorid; 243052a38012Sejakowatz msg.reply_port = _PortPool->GetPort(); 243152a38012Sejakowatz rv = write_port(port, SERVER_GET_DORMANT_FLAVOR_INFO, &msg, sizeof(msg)); 243252a38012Sejakowatz if (rv != B_OK) { 243352a38012Sejakowatz free(reply); 243452a38012Sejakowatz _PortPool->PutPort(msg.reply_port); 243552a38012Sejakowatz return rv; 243652a38012Sejakowatz } 243752a38012Sejakowatz rv = read_port(msg.reply_port, &code, reply, 16000); 243852a38012Sejakowatz _PortPool->PutPort(msg.reply_port); 243952a38012Sejakowatz 244052a38012Sejakowatz if (rv < B_OK) { 244152a38012Sejakowatz free(reply); 244252a38012Sejakowatz return rv; 244352a38012Sejakowatz } 244452a38012Sejakowatz 244552a38012Sejakowatz if (reply->result == B_OK) 244652a38012Sejakowatz rv = out_flavor->Unflatten(reply->dfi_type, &reply->dfi, reply->dfi_size); 244752a38012Sejakowatz else 244852a38012Sejakowatz rv = reply->result; 244952a38012Sejakowatz 245052a38012Sejakowatz free(reply); 245152a38012Sejakowatz return rv; 245252a38012Sejakowatz } 245352a38012Sejakowatz 24548b04ffc1Sbeveloper status_t 24558b04ffc1Sbeveloper BMediaRoster::GetDormantFlavorInfoFor(const dormant_node_info & in_dormant, 24568b04ffc1Sbeveloper dormant_flavor_info * out_flavor) 24578b04ffc1Sbeveloper { 24588b04ffc1Sbeveloper return MediaRosterEx(this)->GetDormantFlavorInfo(in_dormant.addon, in_dormant.flavor_id, out_flavor); 24598b04ffc1Sbeveloper } 246052a38012Sejakowatz 246160f15390Sbeveloper // Reports in outLatency the maximum latency found downstream from 246260f15390Sbeveloper // the specified BBufferProducer, producer, given the current connections. 246352a38012Sejakowatz status_t 246452a38012Sejakowatz BMediaRoster::GetLatencyFor(const media_node & producer, 246552a38012Sejakowatz bigtime_t * out_latency) 246652a38012Sejakowatz { 246760f15390Sbeveloper CALLED(); 246860f15390Sbeveloper if (out_latency == NULL) 246960f15390Sbeveloper return B_BAD_VALUE; 247060f15390Sbeveloper if (IS_INVALID_NODE(producer)) 247160f15390Sbeveloper return B_MEDIA_BAD_NODE; 247260f15390Sbeveloper if ((producer.kind & B_BUFFER_PRODUCER) == 0) 247360f15390Sbeveloper return B_MEDIA_BAD_NODE; 247460f15390Sbeveloper 247560f15390Sbeveloper producer_get_latency_request request; 247660f15390Sbeveloper producer_get_latency_reply reply; 247760f15390Sbeveloper status_t rv; 247860f15390Sbeveloper 247960f15390Sbeveloper rv = QueryPort(producer.port, PRODUCER_GET_LATENCY, &request, sizeof(request), &reply, sizeof(reply)); 248060f15390Sbeveloper if (rv != B_OK) 248160f15390Sbeveloper return rv; 248260f15390Sbeveloper 248360f15390Sbeveloper *out_latency = reply.latency; 248460f15390Sbeveloper 2485*ab9afde3SMarcus Overhagen // printf("BMediaRoster::GetLatencyFor producer %ld has maximum latency %Ld\n", producer.node, *out_latency); 2486aac800c2Sbeveloper return B_OK; 248752a38012Sejakowatz } 248852a38012Sejakowatz 248952a38012Sejakowatz 249052a38012Sejakowatz status_t 249152a38012Sejakowatz BMediaRoster::GetInitialLatencyFor(const media_node & producer, 249252a38012Sejakowatz bigtime_t * out_latency, 2493aac800c2Sbeveloper uint32 * out_flags /* = NULL */) 249452a38012Sejakowatz { 2495b65a0ac5SJérôme Duval CALLED(); 2496b65a0ac5SJérôme Duval if (out_latency == NULL) 2497b65a0ac5SJérôme Duval return B_BAD_VALUE; 2498b65a0ac5SJérôme Duval if (IS_INVALID_NODE(producer)) 2499b65a0ac5SJérôme Duval return B_MEDIA_BAD_NODE; 2500b65a0ac5SJérôme Duval if ((producer.kind & B_BUFFER_PRODUCER) == 0) 2501b65a0ac5SJérôme Duval return B_MEDIA_BAD_NODE; 2502b65a0ac5SJérôme Duval 2503b65a0ac5SJérôme Duval producer_get_initial_latency_request request; 2504b65a0ac5SJérôme Duval producer_get_initial_latency_reply reply; 2505b65a0ac5SJérôme Duval status_t rv; 2506b65a0ac5SJérôme Duval 2507b65a0ac5SJérôme Duval rv = QueryPort(producer.port, PRODUCER_GET_INITIAL_LATENCY, &request, sizeof(request), &reply, sizeof(reply)); 2508b65a0ac5SJérôme Duval if (rv != B_OK) 2509b65a0ac5SJérôme Duval return rv; 2510b65a0ac5SJérôme Duval 2511b65a0ac5SJérôme Duval *out_latency = reply.initial_latency; 2512aac800c2Sbeveloper if (out_flags) 2513b65a0ac5SJérôme Duval *out_flags = reply.flags; 2514b65a0ac5SJérôme Duval 2515b65a0ac5SJérôme Duval printf("BMediaRoster::GetInitialLatencyFor producer %ld has maximum initial latency %Ld\n", producer.node, *out_latency); 2516aac800c2Sbeveloper return B_OK; 251752a38012Sejakowatz } 251852a38012Sejakowatz 251952a38012Sejakowatz 252052a38012Sejakowatz status_t 252152a38012Sejakowatz BMediaRoster::GetStartLatencyFor(const media_node & time_source, 252252a38012Sejakowatz bigtime_t * out_latency) 252352a38012Sejakowatz { 2524fc8b28b6SJérôme Duval CALLED(); 2525fc8b28b6SJérôme Duval if (out_latency == NULL) 2526fc8b28b6SJérôme Duval return B_BAD_VALUE; 2527fc8b28b6SJérôme Duval if (IS_INVALID_NODE(time_source)) 2528fc8b28b6SJérôme Duval return B_MEDIA_BAD_NODE; 2529fc8b28b6SJérôme Duval if ((time_source.kind & B_TIME_SOURCE) == 0) 2530fc8b28b6SJérôme Duval return B_MEDIA_BAD_NODE; 2531fc8b28b6SJérôme Duval 2532fc8b28b6SJérôme Duval timesource_get_start_latency_request request; 2533fc8b28b6SJérôme Duval timesource_get_start_latency_reply reply; 2534fc8b28b6SJérôme Duval status_t rv; 2535fc8b28b6SJérôme Duval 2536fc8b28b6SJérôme Duval rv = QueryPort(time_source.port, TIMESOURCE_GET_START_LATENCY, &request, sizeof(request), &reply, sizeof(reply)); 2537fc8b28b6SJérôme Duval if (rv != B_OK) 2538fc8b28b6SJérôme Duval return rv; 2539fc8b28b6SJérôme Duval 2540fc8b28b6SJérôme Duval *out_latency = reply.start_latency; 2541fc8b28b6SJérôme Duval 2542fc8b28b6SJérôme Duval printf("BMediaRoster::GetStartLatencyFor timesource %ld has maximum initial latency %Ld\n", time_source.node, *out_latency); 2543aac800c2Sbeveloper return B_OK; 254452a38012Sejakowatz } 254552a38012Sejakowatz 254652a38012Sejakowatz 254752a38012Sejakowatz status_t 254852a38012Sejakowatz BMediaRoster::GetFileFormatsFor(const media_node & file_interface, 254952a38012Sejakowatz media_file_format * out_formats, 255052a38012Sejakowatz int32 * io_num_infos) 255152a38012Sejakowatz { 255252a38012Sejakowatz UNIMPLEMENTED(); 255352a38012Sejakowatz return B_ERROR; 255452a38012Sejakowatz } 255552a38012Sejakowatz 255652a38012Sejakowatz 255752a38012Sejakowatz status_t 255852a38012Sejakowatz BMediaRoster::SetRefFor(const media_node & file_interface, 255952a38012Sejakowatz const entry_ref & file, 256052a38012Sejakowatz bool create_and_truncate, 256152a38012Sejakowatz bigtime_t * out_length) /* if create is false */ 256252a38012Sejakowatz { 256352a38012Sejakowatz UNIMPLEMENTED(); 256452a38012Sejakowatz return B_ERROR; 256552a38012Sejakowatz } 256652a38012Sejakowatz 256752a38012Sejakowatz 256852a38012Sejakowatz status_t 256952a38012Sejakowatz BMediaRoster::GetRefFor(const media_node & node, 257052a38012Sejakowatz entry_ref * out_file, 257152a38012Sejakowatz BMimeType * mime_type) 257252a38012Sejakowatz { 257352a38012Sejakowatz UNIMPLEMENTED(); 257452a38012Sejakowatz return B_ERROR; 257552a38012Sejakowatz } 257652a38012Sejakowatz 257752a38012Sejakowatz 257852a38012Sejakowatz status_t 257952a38012Sejakowatz BMediaRoster::SniffRefFor(const media_node & file_interface, 258052a38012Sejakowatz const entry_ref & file, 258152a38012Sejakowatz BMimeType * mime_type, 258252a38012Sejakowatz float * out_capability) 258352a38012Sejakowatz { 258452a38012Sejakowatz UNIMPLEMENTED(); 258552a38012Sejakowatz return B_ERROR; 258652a38012Sejakowatz } 258752a38012Sejakowatz 258852a38012Sejakowatz 258952a38012Sejakowatz /* This is the generic "here's a file, now can someone please play it" interface */ 259052a38012Sejakowatz status_t 259152a38012Sejakowatz BMediaRoster::SniffRef(const entry_ref & file, 259252a38012Sejakowatz uint64 require_node_kinds, /* if you need an EntityInterface or BufferConsumer or something */ 259352a38012Sejakowatz dormant_node_info * out_node, 259452a38012Sejakowatz BMimeType * mime_type) 259552a38012Sejakowatz { 259652a38012Sejakowatz UNIMPLEMENTED(); 259752a38012Sejakowatz return B_ERROR; 259852a38012Sejakowatz } 259952a38012Sejakowatz 260052a38012Sejakowatz 260152a38012Sejakowatz status_t 260252a38012Sejakowatz BMediaRoster::GetDormantNodeForType(const BMimeType & type, 260352a38012Sejakowatz uint64 require_node_kinds, 260452a38012Sejakowatz dormant_node_info * out_node) 260552a38012Sejakowatz { 260652a38012Sejakowatz UNIMPLEMENTED(); 260752a38012Sejakowatz return B_ERROR; 260852a38012Sejakowatz } 260952a38012Sejakowatz 261052a38012Sejakowatz 261152a38012Sejakowatz status_t 261252a38012Sejakowatz BMediaRoster::GetReadFileFormatsFor(const dormant_node_info & in_node, 261352a38012Sejakowatz media_file_format * out_read_formats, 261452a38012Sejakowatz int32 in_read_count, 261552a38012Sejakowatz int32 * out_read_count) 261652a38012Sejakowatz { 261752a38012Sejakowatz UNIMPLEMENTED(); 261852a38012Sejakowatz return B_ERROR; 261952a38012Sejakowatz } 262052a38012Sejakowatz 262152a38012Sejakowatz 262252a38012Sejakowatz status_t 262352a38012Sejakowatz BMediaRoster::GetWriteFileFormatsFor(const dormant_node_info & in_node, 262452a38012Sejakowatz media_file_format * out_write_formats, 262552a38012Sejakowatz int32 in_write_count, 262652a38012Sejakowatz int32 * out_write_count) 262752a38012Sejakowatz { 262852a38012Sejakowatz UNIMPLEMENTED(); 262952a38012Sejakowatz return B_ERROR; 263052a38012Sejakowatz } 263152a38012Sejakowatz 263252a38012Sejakowatz 263352a38012Sejakowatz status_t 263452a38012Sejakowatz BMediaRoster::GetFormatFor(const media_output & output, 263552a38012Sejakowatz media_format * io_format, 263652a38012Sejakowatz uint32 flags) 263752a38012Sejakowatz { 26389bedd42cSbeveloper CALLED(); 26399bedd42cSbeveloper if (io_format == NULL) 26409bedd42cSbeveloper return B_BAD_VALUE; 26419bedd42cSbeveloper if ((output.node.kind & B_BUFFER_PRODUCER) == 0) 26429bedd42cSbeveloper return B_MEDIA_BAD_NODE; 26439bedd42cSbeveloper if (IS_INVALID_SOURCE(output.source)) 26449bedd42cSbeveloper return B_MEDIA_BAD_SOURCE; 26459bedd42cSbeveloper 26469bedd42cSbeveloper producer_format_suggestion_requested_request request; 26479bedd42cSbeveloper producer_format_suggestion_requested_reply reply; 26489bedd42cSbeveloper status_t rv; 26499bedd42cSbeveloper 26509bedd42cSbeveloper request.type = B_MEDIA_UNKNOWN_TYPE; 26519bedd42cSbeveloper request.quality = 0; // XXX what should this be? 26529bedd42cSbeveloper 26539bedd42cSbeveloper rv = QueryPort(output.source.port, PRODUCER_FORMAT_SUGGESTION_REQUESTED, &request, sizeof(request), &reply, sizeof(reply)); 26549bedd42cSbeveloper if (rv != B_OK) 26559bedd42cSbeveloper return rv; 26569bedd42cSbeveloper 26579bedd42cSbeveloper *io_format = reply.format; 26589bedd42cSbeveloper return B_OK; 265952a38012Sejakowatz } 266052a38012Sejakowatz 266152a38012Sejakowatz 266252a38012Sejakowatz status_t 266352a38012Sejakowatz BMediaRoster::GetFormatFor(const media_input & input, 266452a38012Sejakowatz media_format * io_format, 266552a38012Sejakowatz uint32 flags) 266652a38012Sejakowatz { 26679bedd42cSbeveloper CALLED(); 26689bedd42cSbeveloper if (io_format == NULL) 26699bedd42cSbeveloper return B_BAD_VALUE; 26709bedd42cSbeveloper if ((input.node.kind & B_BUFFER_CONSUMER) == 0) 26719bedd42cSbeveloper return B_MEDIA_BAD_NODE; 26729bedd42cSbeveloper if (IS_INVALID_DESTINATION(input.destination)) 26739bedd42cSbeveloper return B_MEDIA_BAD_DESTINATION; 26749bedd42cSbeveloper 26759bedd42cSbeveloper consumer_accept_format_request request; 26769bedd42cSbeveloper consumer_accept_format_reply reply; 26779bedd42cSbeveloper status_t rv; 26789bedd42cSbeveloper 26799bedd42cSbeveloper request.dest = input.destination; 26809bedd42cSbeveloper memset(&request.format, 0, sizeof(request.format)); // wildcard 26819bedd42cSbeveloper 26829bedd42cSbeveloper rv = QueryPort(input.destination.port, CONSUMER_ACCEPT_FORMAT, &request, sizeof(request), &reply, sizeof(reply)); 26839bedd42cSbeveloper if (rv != B_OK) 26849bedd42cSbeveloper return rv; 26859bedd42cSbeveloper 26869bedd42cSbeveloper *io_format = reply.format; 26879bedd42cSbeveloper return B_OK; 268852a38012Sejakowatz } 268952a38012Sejakowatz 269052a38012Sejakowatz 269152a38012Sejakowatz status_t 269252a38012Sejakowatz BMediaRoster::GetFormatFor(const media_node & node, 269352a38012Sejakowatz media_format * io_format, 269452a38012Sejakowatz float quality) 269552a38012Sejakowatz { 269652a38012Sejakowatz UNIMPLEMENTED(); 26979bedd42cSbeveloper if (io_format == NULL) 26989bedd42cSbeveloper return B_BAD_VALUE; 26999bedd42cSbeveloper if (IS_INVALID_NODE(node)) 27009bedd42cSbeveloper return B_MEDIA_BAD_NODE; 27019bedd42cSbeveloper if ((node.kind & (B_BUFFER_CONSUMER | B_BUFFER_PRODUCER)) == 0) 27029bedd42cSbeveloper return B_MEDIA_BAD_NODE; 27039bedd42cSbeveloper 27049bedd42cSbeveloper 270552a38012Sejakowatz return B_ERROR; 270652a38012Sejakowatz } 270752a38012Sejakowatz 270852a38012Sejakowatz 270952a38012Sejakowatz ssize_t 271052a38012Sejakowatz BMediaRoster::GetNodeAttributesFor(const media_node & node, 271152a38012Sejakowatz media_node_attribute * outArray, 271252a38012Sejakowatz size_t inMaxCount) 271352a38012Sejakowatz { 271452a38012Sejakowatz UNIMPLEMENTED(); 271552a38012Sejakowatz return B_ERROR; 271652a38012Sejakowatz } 271752a38012Sejakowatz 271852a38012Sejakowatz 271952a38012Sejakowatz media_node_id 272052a38012Sejakowatz BMediaRoster::NodeIDFor(port_id source_or_destination_port) 272152a38012Sejakowatz { 27229e9417d2Sbeveloper CALLED(); 27239e9417d2Sbeveloper 27249e9417d2Sbeveloper server_node_id_for_request request; 27259e9417d2Sbeveloper server_node_id_for_reply reply; 27269e9417d2Sbeveloper status_t rv; 27279e9417d2Sbeveloper 27289e9417d2Sbeveloper request.port = source_or_destination_port; 27299e9417d2Sbeveloper 27309e9417d2Sbeveloper rv = QueryServer(SERVER_NODE_ID_FOR, &request, sizeof(request), &reply, sizeof(reply)); 27319e9417d2Sbeveloper if (rv != B_OK) { 27325ac4fbd7Sbeveloper ERROR("BMediaRoster::NodeIDFor: failed (error %#lx)\n", rv); 27339e9417d2Sbeveloper return -1; 27349e9417d2Sbeveloper } 27359e9417d2Sbeveloper 27369e9417d2Sbeveloper return reply.nodeid; 273752a38012Sejakowatz } 273852a38012Sejakowatz 273952a38012Sejakowatz 274052a38012Sejakowatz status_t 274152a38012Sejakowatz BMediaRoster::GetInstancesFor(media_addon_id addon, 274252a38012Sejakowatz int32 flavor, 274352a38012Sejakowatz media_node_id * out_id, 274452a38012Sejakowatz int32 * io_count) 274552a38012Sejakowatz { 274685dfab2bSbeveloper CALLED(); 27478b9700adSJérôme Duval if (out_id == NULL) 274885dfab2bSbeveloper return B_BAD_VALUE; 27498b9700adSJérôme Duval if (io_count && *io_count <= 0) 275085dfab2bSbeveloper return B_BAD_VALUE; 275185dfab2bSbeveloper 275285dfab2bSbeveloper server_get_instances_for_request request; 275385dfab2bSbeveloper server_get_instances_for_reply reply; 275485dfab2bSbeveloper status_t rv; 275585dfab2bSbeveloper 27568b9700adSJérôme Duval request.maxcount = (io_count ? *io_count : 1); 275785dfab2bSbeveloper request.addon_id = addon; 275885dfab2bSbeveloper request.addon_flavor_id = flavor; 275985dfab2bSbeveloper 276085dfab2bSbeveloper rv = QueryServer(SERVER_GET_INSTANCES_FOR, &request, sizeof(request), &reply, sizeof(reply)); 276185dfab2bSbeveloper if (rv != B_OK) { 27625ac4fbd7Sbeveloper ERROR("BMediaRoster::GetLiveNodes failed\n"); 276385dfab2bSbeveloper return rv; 276452a38012Sejakowatz } 276552a38012Sejakowatz 27668b9700adSJérôme Duval if(io_count) 276785dfab2bSbeveloper *io_count = reply.count; 276885dfab2bSbeveloper if (reply.count > 0) 276985dfab2bSbeveloper memcpy(out_id, reply.node_id, sizeof(media_node_id) * reply.count); 277085dfab2bSbeveloper 277185dfab2bSbeveloper return B_OK; 277285dfab2bSbeveloper } 277352a38012Sejakowatz 277452a38012Sejakowatz 277552a38012Sejakowatz status_t 277652a38012Sejakowatz BMediaRoster::SetRealtimeFlags(uint32 in_enabled) 277752a38012Sejakowatz { 277852a38012Sejakowatz UNIMPLEMENTED(); 277952a38012Sejakowatz return B_ERROR; 278052a38012Sejakowatz } 278152a38012Sejakowatz 278252a38012Sejakowatz 278352a38012Sejakowatz status_t 278452a38012Sejakowatz BMediaRoster::GetRealtimeFlags(uint32 * out_enabled) 278552a38012Sejakowatz { 278652a38012Sejakowatz UNIMPLEMENTED(); 278752a38012Sejakowatz return B_ERROR; 278852a38012Sejakowatz } 278952a38012Sejakowatz 279052a38012Sejakowatz 279152a38012Sejakowatz ssize_t 279252a38012Sejakowatz BMediaRoster::AudioBufferSizeFor(int32 channel_count, 279352a38012Sejakowatz uint32 sample_format, 279452a38012Sejakowatz float frame_rate, 279552a38012Sejakowatz bus_type bus_kind) 279652a38012Sejakowatz { 2797df6c2e83Sbeveloper bigtime_t buffer_duration; 2798df6c2e83Sbeveloper ssize_t buffer_size; 2799df6c2e83Sbeveloper 2800df6c2e83Sbeveloper system_info info; 2801df6c2e83Sbeveloper get_system_info(&info); 2802df6c2e83Sbeveloper 2803df6c2e83Sbeveloper if (info.cpu_clock_speed > 2000000000) 2804df6c2e83Sbeveloper buffer_duration = 2500; 2805df6c2e83Sbeveloper else if (info.cpu_clock_speed > 1000000000) 2806df6c2e83Sbeveloper buffer_duration = 5000; 2807df6c2e83Sbeveloper else if (info.cpu_clock_speed > 600000000) 2808df6c2e83Sbeveloper buffer_duration = 10000; 2809df6c2e83Sbeveloper else if (info.cpu_clock_speed > 200000000) 2810df6c2e83Sbeveloper buffer_duration = 20000; 2811df6c2e83Sbeveloper else if (info.cpu_clock_speed > 100000000) 2812df6c2e83Sbeveloper buffer_duration = 30000; 2813df6c2e83Sbeveloper else 2814df6c2e83Sbeveloper buffer_duration = 50000; 2815df6c2e83Sbeveloper 2816df6c2e83Sbeveloper if ((bus_kind == B_ISA_BUS || bus_kind == B_PCMCIA_BUS) && buffer_duration < 25000) 2817df6c2e83Sbeveloper buffer_duration = 25000; 2818df6c2e83Sbeveloper 2819df6c2e83Sbeveloper buffer_size = (sample_format & 0xf) * channel_count * (ssize_t)((frame_rate * buffer_duration) / 1000000.0); 2820df6c2e83Sbeveloper 2821df6c2e83Sbeveloper printf("Suggested buffer duration %Ld, size %ld\n", buffer_duration, buffer_size); 2822df6c2e83Sbeveloper 2823df6c2e83Sbeveloper return buffer_size; 282452a38012Sejakowatz } 282552a38012Sejakowatz 282652a38012Sejakowatz 282752a38012Sejakowatz /* Use MediaFlags to inquire about specific features of the Media Kit. */ 282852a38012Sejakowatz /* Returns < 0 for "not present", positive size for output data size. */ 282952a38012Sejakowatz /* 0 means that the capability is present, but no data about it. */ 283052a38012Sejakowatz /* static */ ssize_t 283152a38012Sejakowatz BMediaRoster::MediaFlags(media_flags cap, 283252a38012Sejakowatz void * buf, 283352a38012Sejakowatz size_t maxSize) 283452a38012Sejakowatz { 283552a38012Sejakowatz UNIMPLEMENTED(); 283652a38012Sejakowatz return 0; 283752a38012Sejakowatz } 283852a38012Sejakowatz 283952a38012Sejakowatz 284052a38012Sejakowatz /* BLooper overrides */ 284152a38012Sejakowatz /* virtual */ void 284252a38012Sejakowatz BMediaRoster::MessageReceived(BMessage * message) 284352a38012Sejakowatz { 2844cf4e2277Sbeveloper switch (message->what) { 2845cf4e2277Sbeveloper case 'PING': 2846cf4e2277Sbeveloper { 28476396865dSbeveloper // media_server plays ping-pong with the BMediaRosters 28486396865dSbeveloper // to detect dead teams. Normal communication uses ports. 28496396865dSbeveloper static BMessage pong('PONG'); 28506396865dSbeveloper message->SendReply(&pong, static_cast<BHandler *>(NULL), 2000000); 28516396865dSbeveloper return; 28526396865dSbeveloper } 28536396865dSbeveloper 2854cf4e2277Sbeveloper case NODE_FINAL_RELEASE: 2855cf4e2277Sbeveloper { 2856cf4e2277Sbeveloper // this function is called by a BMediaNode to delete 2857cf4e2277Sbeveloper // itself, as this needs to be done from another thread 2858cf4e2277Sbeveloper // context, it is done here. 2859cf4e2277Sbeveloper // XXX If a node is released using BMediaRoster::ReleaseNode() 2860cf4e2277Sbeveloper // XXX instead of using BMediaNode::Release() / BMediaNode::Acquire() 2861cf4e2277Sbeveloper // XXX fRefCount of the BMediaNode will not be correct. 2862cf4e2277Sbeveloper 2863cf4e2277Sbeveloper BMediaNode *node; 2864cf4e2277Sbeveloper message->FindPointer("node", reinterpret_cast<void **>(&node)); 2865cf4e2277Sbeveloper 286654187cc6Sbeveloper TRACE("BMediaRoster::MessageReceived NODE_FINAL_RELEASE saving node %ld configuration\n", node->ID()); 286754187cc6Sbeveloper MediaRosterEx(BMediaRoster::Roster())->SaveNodeConfiguration(node); 2868cf4e2277Sbeveloper 286954187cc6Sbeveloper TRACE("BMediaRoster::MessageReceived NODE_FINAL_RELEASE releasing node %ld\n", node->ID()); 2870cf4e2277Sbeveloper node->DeleteHook(node); // we don't call Release(), see above! 2871cf4e2277Sbeveloper return; 2872cf4e2277Sbeveloper } 2873cf4e2277Sbeveloper } 28746396865dSbeveloper printf("BMediaRoster::MessageReceived: unknown message!\n"); 28756396865dSbeveloper message->PrintToStream(); 287652a38012Sejakowatz } 287752a38012Sejakowatz 287852a38012Sejakowatz /* virtual */ bool 287952a38012Sejakowatz BMediaRoster::QuitRequested() 288052a38012Sejakowatz { 288152a38012Sejakowatz UNIMPLEMENTED(); 288252a38012Sejakowatz return true; 288352a38012Sejakowatz } 288452a38012Sejakowatz 288552a38012Sejakowatz /* virtual */ BHandler * 288652a38012Sejakowatz BMediaRoster::ResolveSpecifier(BMessage *msg, 288752a38012Sejakowatz int32 index, 288852a38012Sejakowatz BMessage *specifier, 288952a38012Sejakowatz int32 form, 289052a38012Sejakowatz const char *property) 289152a38012Sejakowatz { 289252a38012Sejakowatz UNIMPLEMENTED(); 289352a38012Sejakowatz return 0; 289452a38012Sejakowatz } 289552a38012Sejakowatz 289652a38012Sejakowatz 289752a38012Sejakowatz /* virtual */ status_t 289852a38012Sejakowatz BMediaRoster::GetSupportedSuites(BMessage *data) 289952a38012Sejakowatz { 290052a38012Sejakowatz UNIMPLEMENTED(); 290152a38012Sejakowatz return B_ERROR; 290252a38012Sejakowatz } 290352a38012Sejakowatz 290452a38012Sejakowatz 290552a38012Sejakowatz BMediaRoster::~BMediaRoster() 290652a38012Sejakowatz { 290752a38012Sejakowatz CALLED(); 29086396865dSbeveloper 29096396865dSbeveloper // unregister this application with the media server 29106396865dSbeveloper server_unregister_app_request request; 29116396865dSbeveloper server_unregister_app_reply reply; 29126396865dSbeveloper request.team = team; 29136396865dSbeveloper QueryServer(SERVER_UNREGISTER_APP, &request, sizeof(request), &reply, sizeof(reply)); 291452a38012Sejakowatz } 291552a38012Sejakowatz 291652a38012Sejakowatz 291752a38012Sejakowatz /************************************************************* 291852a38012Sejakowatz * private BMediaRoster 291952a38012Sejakowatz *************************************************************/ 292052a38012Sejakowatz 292152a38012Sejakowatz // deprecated call 292252a38012Sejakowatz status_t 292352a38012Sejakowatz BMediaRoster::SetOutputBuffersFor(const media_source & output, 292452a38012Sejakowatz BBufferGroup * group, 292552a38012Sejakowatz bool will_reclaim ) 292652a38012Sejakowatz { 292752a38012Sejakowatz UNIMPLEMENTED(); 29289e9417d2Sbeveloper debugger("BMediaRoster::SetOutputBuffersFor missing\n"); 292952a38012Sejakowatz return B_ERROR; 293052a38012Sejakowatz } 293152a38012Sejakowatz 293252a38012Sejakowatz 293352a38012Sejakowatz /* FBC stuffing (Mmmh, Stuffing!) */ 293452a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_0(void *) { return B_ERROR; } 293552a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_1(void *) { return B_ERROR; } 293652a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_2(void *) { return B_ERROR; } 293752a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_3(void *) { return B_ERROR; } 293852a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_4(void *) { return B_ERROR; } 293952a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_5(void *) { return B_ERROR; } 294052a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_6(void *) { return B_ERROR; } 294152a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_7(void *) { return B_ERROR; } 294252a38012Sejakowatz 294352a38012Sejakowatz 294452a38012Sejakowatz BMediaRoster::BMediaRoster() : 29456396865dSbeveloper BLooper("_BMediaRoster_", B_URGENT_DISPLAY_PRIORITY, B_LOOPER_PORT_DEFAULT_CAPACITY) 294652a38012Sejakowatz { 294752a38012Sejakowatz CALLED(); 29486396865dSbeveloper 29496396865dSbeveloper // start the looper 29506396865dSbeveloper Run(); 295152a38012Sejakowatz } 295252a38012Sejakowatz 29536396865dSbeveloper 295452a38012Sejakowatz /* static */ status_t 295552a38012Sejakowatz BMediaRoster::ParseCommand(BMessage & reply) 295652a38012Sejakowatz { 295752a38012Sejakowatz UNIMPLEMENTED(); 295852a38012Sejakowatz return B_ERROR; 295952a38012Sejakowatz } 296052a38012Sejakowatz 296152a38012Sejakowatz 296252a38012Sejakowatz status_t 296352a38012Sejakowatz BMediaRoster::GetDefaultInfo(media_node_id for_default, 296452a38012Sejakowatz BMessage & out_config) 296552a38012Sejakowatz { 296652a38012Sejakowatz UNIMPLEMENTED(); 296752a38012Sejakowatz return B_ERROR; 296852a38012Sejakowatz } 296952a38012Sejakowatz 297052a38012Sejakowatz 297152a38012Sejakowatz 297252a38012Sejakowatz status_t 297352a38012Sejakowatz BMediaRoster::SetRunningDefault(media_node_id for_default, 297452a38012Sejakowatz const media_node & node) 297552a38012Sejakowatz { 297652a38012Sejakowatz UNIMPLEMENTED(); 297752a38012Sejakowatz return B_ERROR; 297852a38012Sejakowatz } 297952a38012Sejakowatz 298052a38012Sejakowatz 298152a38012Sejakowatz /************************************************************* 298252a38012Sejakowatz * static BMediaRoster variables 298352a38012Sejakowatz *************************************************************/ 298452a38012Sejakowatz 298552a38012Sejakowatz bool BMediaRoster::_isMediaServer; 298652a38012Sejakowatz port_id BMediaRoster::_mReplyPort; 298752a38012Sejakowatz int32 BMediaRoster::_mReplyPortRes; 298852a38012Sejakowatz int32 BMediaRoster::_mReplyPortUnavailCount; 298952a38012Sejakowatz BMediaRoster * BMediaRoster::_sDefault = NULL; 299052a38012Sejakowatz 2991