1255a01c7Sbeveloper /* 2*34c72144SAxel Dörfler * Copyright 2008 Maurice Kalinowski, haiku@kaldience.com 3*34c72144SAxel Dörfler * Copyright 2009, Axel Dörfler, axeld@pinc-software.de. 4*34c72144SAxel Dörfler * 5*34c72144SAxel Dörfler * All rights reserved. Distributed under the terms of the MIT License. 6*34c72144SAxel Dörfler */ 7*34c72144SAxel Dörfler 8*34c72144SAxel Dörfler /* 965b73ae4SMarcus Overhagen * Copyright (c) 2002-2006 Marcus Overhagen <Marcus@Overhagen.de> 10255a01c7Sbeveloper * 11255a01c7Sbeveloper * Permission is hereby granted, free of charge, to any person obtaining 12255a01c7Sbeveloper * a copy of this software and associated documentation files or portions 13255a01c7Sbeveloper * thereof (the "Software"), to deal in the Software without restriction, 14255a01c7Sbeveloper * including without limitation the rights to use, copy, modify, merge, 15255a01c7Sbeveloper * publish, distribute, sublicense, and/or sell copies of the Software, 16255a01c7Sbeveloper * and to permit persons to whom the Software is furnished to do so, subject 17255a01c7Sbeveloper * to the following conditions: 18255a01c7Sbeveloper * 19255a01c7Sbeveloper * * Redistributions of source code must retain the above copyright notice, 20255a01c7Sbeveloper * this list of conditions and the following disclaimer. 21255a01c7Sbeveloper * 22255a01c7Sbeveloper * * Redistributions in binary form must reproduce the above copyright notice 23255a01c7Sbeveloper * in the binary, as well as this list of conditions and the following 24255a01c7Sbeveloper * disclaimer in the documentation and/or other materials provided with 25255a01c7Sbeveloper * the distribution. 26255a01c7Sbeveloper * 27255a01c7Sbeveloper * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 28255a01c7Sbeveloper * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 29255a01c7Sbeveloper * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 30255a01c7Sbeveloper * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 31255a01c7Sbeveloper * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 32255a01c7Sbeveloper * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 33255a01c7Sbeveloper * THE SOFTWARE. 34255a01c7Sbeveloper * 35255a01c7Sbeveloper */ 366938364bSMaurice Kalinowski 37255a01c7Sbeveloper 38255a01c7Sbeveloper /* to comply with the license above, do not remove the following line */ 398b940bb4SStephan Aßmus char __dont_remove_copyright_from_binary[] = "Copyright (c) 2002-2006 Marcus " 408b940bb4SStephan Aßmus "Overhagen <Marcus@Overhagen.de>"; 41255a01c7Sbeveloper 4231cf24c1SMarcus Overhagen //#define DEBUG 7 4352a38012Sejakowatz #include <MediaRoster.h> 448b940bb4SStephan Aßmus 45a715f908SStephan Aßmus #include <new> 46a715f908SStephan Aßmus 476938364bSMaurice Kalinowski #include <BufferConsumer.h> 486938364bSMaurice Kalinowski #include <BufferProducer.h> 4952a38012Sejakowatz #include <Locker.h> 5052a38012Sejakowatz #include <Message.h> 5152a38012Sejakowatz #include <Messenger.h> 526938364bSMaurice Kalinowski #include <MimeType.h> 5352a38012Sejakowatz #include <OS.h> 546938364bSMaurice Kalinowski #include <ParameterWeb.h> 556938364bSMaurice Kalinowski #include <StopWatch.h> 5652a38012Sejakowatz #include <String.h> 5752a38012Sejakowatz #include <TimeSource.h> 588b940bb4SStephan Aßmus 5952a38012Sejakowatz #include "debug.h" 608b04ffc1Sbeveloper #include "MediaRosterEx.h" 6140f36b03Sbeveloper #include "MediaMisc.h" 6252a38012Sejakowatz #include "PortPool.h" 630a483e72SIngo Weinhold #include "ServerInterface.h" 64f4925104Sbeveloper #include "DataExchange.h" 6516b7eea4Sbeveloper #include "DormantNodeManager.h" 66f4925104Sbeveloper #include "Notifications.h" 67835140c8Sbeveloper #include "TimeSourceObjectManager.h" 6852a38012Sejakowatz 69f4925104Sbeveloper namespace BPrivate { namespace media { 7052a38012Sejakowatz 7152a38012Sejakowatz // the BMediaRoster destructor is private, 7252a38012Sejakowatz // but _DefaultDeleter is a friend class of 7352a38012Sejakowatz // the BMediaRoster an thus can delete it 748b04ffc1Sbeveloper class DefaultDeleter 7552a38012Sejakowatz { 7652a38012Sejakowatz public: 778b04ffc1Sbeveloper ~DefaultDeleter() 786396865dSbeveloper { 799def3bf7SStephan Aßmus if (BMediaRoster::sDefaultInstance) { 809def3bf7SStephan Aßmus BMediaRoster::sDefaultInstance->Lock(); 819def3bf7SStephan Aßmus BMediaRoster::sDefaultInstance->Quit(); 826396865dSbeveloper } 836396865dSbeveloper } 848b04ffc1Sbeveloper }; 8552a38012Sejakowatz 868b04ffc1Sbeveloper } } // BPrivate::media 878b04ffc1Sbeveloper using namespace BPrivate::media; 8852a38012Sejakowatz 898b04ffc1Sbeveloper // DefaultDeleter will delete the BMediaRoster object in it's destructor. 908b04ffc1Sbeveloper DefaultDeleter _deleter; 9152a38012Sejakowatz 92*34c72144SAxel Dörfler BMediaRosterEx::BMediaRosterEx(status_t* _error) 93dcfb6bfcSJérôme Duval : BMediaRoster() 94dcfb6bfcSJérôme Duval { 95dcfb6bfcSJérôme Duval status_t rv; 96dcfb6bfcSJérôme Duval // register this application with the media server 97dcfb6bfcSJérôme Duval server_register_app_request request; 98dcfb6bfcSJérôme Duval server_register_app_reply reply; 99dcfb6bfcSJérôme Duval request.team = team; 100dcfb6bfcSJérôme Duval request.messenger = BMessenger(NULL, this); 101*34c72144SAxel Dörfler rv = QueryServer(SERVER_REGISTER_APP, &request, sizeof(request), &reply, 102*34c72144SAxel Dörfler sizeof(reply)); 103a7fb4c16SMaurice Kalinowski if (rv != B_OK) 104*34c72144SAxel Dörfler *_error = B_MEDIA_SYSTEM_FAILURE; 105a7fb4c16SMaurice Kalinowski else 106*34c72144SAxel Dörfler *_error = B_OK; 107dcfb6bfcSJérôme Duval } 108dcfb6bfcSJérôme Duval 109*34c72144SAxel Dörfler 1103620737cSbeveloper status_t 11154187cc6Sbeveloper BMediaRosterEx::SaveNodeConfiguration(BMediaNode* node) 11254187cc6Sbeveloper { 11354187cc6Sbeveloper BMediaAddOn *addon; 11454187cc6Sbeveloper media_addon_id addonid; 11554187cc6Sbeveloper int32 flavorid; 11654187cc6Sbeveloper addon = node->AddOn(&flavorid); 11754187cc6Sbeveloper if (!addon) { 1188056f0dbSStephan Aßmus // NOTE: This node could have been created by an application, 1198056f0dbSStephan Aßmus // it does not mean there is an error. 120*34c72144SAxel Dörfler // TODO: this check incorrectly triggers on BeOS R5 BT848 node 1218056f0dbSStephan Aßmus TRACE("BMediaRosterEx::SaveNodeConfiguration node %ld not instantiated " 1228056f0dbSStephan Aßmus "from BMediaAddOn!\n", node->ID()); 12354187cc6Sbeveloper return B_ERROR; 12454187cc6Sbeveloper } 12554187cc6Sbeveloper addonid = addon->AddonID(); 12654187cc6Sbeveloper 127*34c72144SAxel Dörfler // TODO: fix this 1288056f0dbSStephan Aßmus printf("### BMediaRosterEx::SaveNodeConfiguration should save addon-id " 1298056f0dbSStephan Aßmus "%ld, flavor-id %ld config NOW!\n", addonid, flavorid); 13054187cc6Sbeveloper return B_OK; 13154187cc6Sbeveloper } 13254187cc6Sbeveloper 133*34c72144SAxel Dörfler 13454187cc6Sbeveloper status_t 1358b940bb4SStephan Aßmus BMediaRosterEx::LoadNodeConfiguration(media_addon_id addonid, int32 flavorid, 1368b940bb4SStephan Aßmus BMessage *out_msg) 13754187cc6Sbeveloper { 138*34c72144SAxel Dörfler // TODO: fix this 13954187cc6Sbeveloper out_msg->MakeEmpty(); // to be fully R5 compliant 1408b940bb4SStephan Aßmus printf("### BMediaRosterEx::LoadNodeConfiguration should load addon-id " 1418b940bb4SStephan Aßmus "%ld, flavor-id %ld config NOW!\n", addonid, flavorid); 14254187cc6Sbeveloper return B_OK; 14354187cc6Sbeveloper } 14454187cc6Sbeveloper 145*34c72144SAxel Dörfler 14654187cc6Sbeveloper status_t 147*34c72144SAxel Dörfler BMediaRosterEx::IncrementAddonFlavorInstancesCount(media_addon_id addonid, 148*34c72144SAxel Dörfler int32 flavorid) 14954187cc6Sbeveloper { 15073794717Sbeveloper server_change_addon_flavor_instances_count_request request; 15173794717Sbeveloper server_change_addon_flavor_instances_count_reply reply; 15273794717Sbeveloper 15373794717Sbeveloper request.addonid = addonid; 15473794717Sbeveloper request.flavorid = flavorid; 15573794717Sbeveloper request.delta = 1; 15673794717Sbeveloper request.team = team; 157*34c72144SAxel Dörfler return QueryServer(SERVER_CHANGE_ADDON_FLAVOR_INSTANCES_COUNT, &request, 158*34c72144SAxel Dörfler sizeof(request), &reply, sizeof(reply)); 15954187cc6Sbeveloper } 16054187cc6Sbeveloper 161*34c72144SAxel Dörfler 16254187cc6Sbeveloper status_t 163*34c72144SAxel Dörfler BMediaRosterEx::DecrementAddonFlavorInstancesCount(media_addon_id addonid, 164*34c72144SAxel Dörfler int32 flavorid) 16554187cc6Sbeveloper { 16673794717Sbeveloper server_change_addon_flavor_instances_count_request request; 16773794717Sbeveloper server_change_addon_flavor_instances_count_reply reply; 16873794717Sbeveloper 16973794717Sbeveloper request.addonid = addonid; 17073794717Sbeveloper request.flavorid = flavorid; 17173794717Sbeveloper request.delta = -1; 17273794717Sbeveloper request.team = team; 173*34c72144SAxel Dörfler return QueryServer(SERVER_CHANGE_ADDON_FLAVOR_INSTANCES_COUNT, &request, 174*34c72144SAxel Dörfler sizeof(request), &reply, sizeof(reply)); 17554187cc6Sbeveloper } 17654187cc6Sbeveloper 177*34c72144SAxel Dörfler 17854187cc6Sbeveloper status_t 17954187cc6Sbeveloper BMediaRosterEx::SetNodeCreator(media_node_id node, team_id creator) 18054187cc6Sbeveloper { 18154187cc6Sbeveloper server_set_node_creator_request request; 18254187cc6Sbeveloper server_set_node_creator_reply reply; 18354187cc6Sbeveloper 18454187cc6Sbeveloper request.node = node; 18554187cc6Sbeveloper request.creator = creator; 186*34c72144SAxel Dörfler return QueryServer(SERVER_SET_NODE_CREATOR, &request, sizeof(request), 187*34c72144SAxel Dörfler &reply, sizeof(reply)); 18854187cc6Sbeveloper } 18954187cc6Sbeveloper 190*34c72144SAxel Dörfler 19154187cc6Sbeveloper status_t 192*34c72144SAxel Dörfler BMediaRosterEx::GetNode(node_type type, media_node* out_node, 193*34c72144SAxel Dörfler int32* out_input_id, BString* out_input_name) 19452a38012Sejakowatz { 19552a38012Sejakowatz if (out_node == NULL) 19652a38012Sejakowatz return B_BAD_VALUE; 19752a38012Sejakowatz 1988c6a6096Sbeveloper server_get_node_request request; 1998c6a6096Sbeveloper server_get_node_reply reply; 20052a38012Sejakowatz status_t rv; 20152a38012Sejakowatz 2028c6a6096Sbeveloper request.type = type; 2039e9417d2Sbeveloper request.team = team; 204*34c72144SAxel Dörfler rv = QueryServer(SERVER_GET_NODE, &request, sizeof(request), &reply, 205*34c72144SAxel Dörfler sizeof(reply)); 2068c6a6096Sbeveloper if (rv != B_OK) 2078c6a6096Sbeveloper return rv; 20852a38012Sejakowatz 20952a38012Sejakowatz *out_node = reply.node; 21052a38012Sejakowatz if (out_input_id) 21152a38012Sejakowatz *out_input_id = reply.input_id; 21252a38012Sejakowatz if (out_input_name) 21352a38012Sejakowatz *out_input_name = reply.input_name; 2148c6a6096Sbeveloper return rv; 21552a38012Sejakowatz } 21652a38012Sejakowatz 217*34c72144SAxel Dörfler 2183620737cSbeveloper status_t 219*34c72144SAxel Dörfler BMediaRosterEx::SetNode(node_type type, const media_node* node, 220*34c72144SAxel Dörfler const dormant_node_info* info, const media_input* input) 22152a38012Sejakowatz { 2228c6a6096Sbeveloper server_set_node_request request; 2238c6a6096Sbeveloper server_set_node_reply reply; 22452a38012Sejakowatz 2258c6a6096Sbeveloper request.type = type; 226*34c72144SAxel Dörfler request.use_node = node != NULL; 227*34c72144SAxel Dörfler if (node != NULL) 2288c6a6096Sbeveloper request.node = *node; 229*34c72144SAxel Dörfler request.use_dni = info != NULL; 230*34c72144SAxel Dörfler if (info != NULL) 2318c6a6096Sbeveloper request.dni = *info; 232*34c72144SAxel Dörfler request.use_input = input != NULL; 233*34c72144SAxel Dörfler if (input != NULL) 2348c6a6096Sbeveloper request.input = *input; 23552a38012Sejakowatz 236*34c72144SAxel Dörfler return QueryServer(SERVER_SET_NODE, &request, sizeof(request), &reply, 237*34c72144SAxel Dörfler sizeof(reply)); 23852a38012Sejakowatz } 23952a38012Sejakowatz 240*34c72144SAxel Dörfler 2413620737cSbeveloper status_t 2428b04ffc1Sbeveloper BMediaRosterEx::GetAllOutputs(const media_node& node, List<media_output>* list) 2433620737cSbeveloper { 2443620737cSbeveloper int32 cookie; 2453620737cSbeveloper status_t rv; 2463620737cSbeveloper status_t result; 2473620737cSbeveloper 248*34c72144SAxel Dörfler PRINT(4, "BMediaRosterEx::GetAllOutputs() node %ld, port %ld\n", node.node, 249*34c72144SAxel Dörfler node.port); 2505ac4fbd7Sbeveloper 25165b73ae4SMarcus Overhagen if (!(node.kind & B_BUFFER_PRODUCER)) { 252*34c72144SAxel Dörfler ERROR("BMediaRosterEx::GetAllOutputs: node %ld is not a " 253*34c72144SAxel Dörfler "B_BUFFER_PRODUCER\n", node.node); 25465b73ae4SMarcus Overhagen return B_MEDIA_BAD_NODE; 25565b73ae4SMarcus Overhagen } 25665b73ae4SMarcus Overhagen 2573620737cSbeveloper result = B_OK; 2583620737cSbeveloper cookie = 0; 25976669a29Sbeveloper list->MakeEmpty(); 2603620737cSbeveloper for (;;) { 2613620737cSbeveloper producer_get_next_output_request request; 2623620737cSbeveloper producer_get_next_output_reply reply; 2633620737cSbeveloper request.cookie = cookie; 264*34c72144SAxel Dörfler rv = QueryPort(node.port, PRODUCER_GET_NEXT_OUTPUT, &request, 265*34c72144SAxel Dörfler sizeof(request), &reply, sizeof(reply)); 2663620737cSbeveloper if (rv != B_OK) 2673620737cSbeveloper break; 2683620737cSbeveloper cookie = reply.cookie; 26976669a29Sbeveloper if (!list->Insert(reply.output)) { 2705ac4fbd7Sbeveloper ERROR("GetAllOutputs: list->Insert failed\n"); 2713620737cSbeveloper result = B_ERROR; 2723620737cSbeveloper } 2735ac4fbd7Sbeveloper #if DEBUG >= 3 2745ac4fbd7Sbeveloper PRINT(3," next cookie %ld, ", cookie); 2755ac4fbd7Sbeveloper PRINT_OUTPUT("output ", reply.output); 2765ac4fbd7Sbeveloper #endif 2773620737cSbeveloper } 2783620737cSbeveloper 2793620737cSbeveloper producer_dispose_output_cookie_request request; 2803620737cSbeveloper producer_dispose_output_cookie_reply reply; 281*34c72144SAxel Dörfler QueryPort(node.port, PRODUCER_DISPOSE_OUTPUT_COOKIE, &request, 282*34c72144SAxel Dörfler sizeof(request), &reply, sizeof(reply)); 2833620737cSbeveloper 2843620737cSbeveloper return result; 2853620737cSbeveloper } 2863620737cSbeveloper 287*34c72144SAxel Dörfler 2883620737cSbeveloper status_t 2894d2d96e0Sbeveloper BMediaRosterEx::GetAllOutputs(BBufferProducer* node, List<media_output>* list) 2904d2d96e0Sbeveloper { 2914d2d96e0Sbeveloper int32 cookie; 2924d2d96e0Sbeveloper status_t result; 2934d2d96e0Sbeveloper 2944d2d96e0Sbeveloper PRINT(4, "BMediaRosterEx::GetAllOutputs() (by pointer) node %ld, port %ld\n", node->ID(), node->ControlPort()); 2954d2d96e0Sbeveloper 2964d2d96e0Sbeveloper result = B_OK; 2974d2d96e0Sbeveloper cookie = 0; 2984d2d96e0Sbeveloper list->MakeEmpty(); 2994d2d96e0Sbeveloper for (;;) { 3004d2d96e0Sbeveloper media_output output; 3014d2d96e0Sbeveloper if (B_OK != node->GetNextOutput(&cookie, &output)) 3024d2d96e0Sbeveloper break; 3034d2d96e0Sbeveloper if (!list->Insert(output)) { 3044d2d96e0Sbeveloper ERROR("GetAllOutputs: list->Insert failed\n"); 3054d2d96e0Sbeveloper result = B_ERROR; 3064d2d96e0Sbeveloper } 3074d2d96e0Sbeveloper #if DEBUG >= 3 3084d2d96e0Sbeveloper PRINT(3," next cookie %ld, ", cookie); 3094d2d96e0Sbeveloper PRINT_OUTPUT("output ", output); 3104d2d96e0Sbeveloper #endif 3114d2d96e0Sbeveloper } 3124d2d96e0Sbeveloper node->DisposeOutputCookie(cookie); 3134d2d96e0Sbeveloper return result; 3144d2d96e0Sbeveloper } 3154d2d96e0Sbeveloper 316*34c72144SAxel Dörfler 3174d2d96e0Sbeveloper status_t 3188b04ffc1Sbeveloper BMediaRosterEx::GetAllInputs(const media_node& node, List<media_input>* list) 3193620737cSbeveloper { 3203620737cSbeveloper int32 cookie; 3213620737cSbeveloper status_t rv; 3223620737cSbeveloper status_t result; 3233620737cSbeveloper 324*34c72144SAxel Dörfler PRINT(4, "BMediaRosterEx::GetAllInputs() node %ld, port %ld\n", node.node, 325*34c72144SAxel Dörfler node.port); 3265ac4fbd7Sbeveloper 32765b73ae4SMarcus Overhagen if (!(node.kind & B_BUFFER_CONSUMER)) { 328*34c72144SAxel Dörfler ERROR("BMediaRosterEx::GetAllInputs: node %ld is not a " 329*34c72144SAxel Dörfler "B_BUFFER_CONSUMER\n", node.node); 33065b73ae4SMarcus Overhagen return B_MEDIA_BAD_NODE; 33165b73ae4SMarcus Overhagen } 33265b73ae4SMarcus Overhagen 3333620737cSbeveloper result = B_OK; 3343620737cSbeveloper cookie = 0; 33576669a29Sbeveloper list->MakeEmpty(); 3363620737cSbeveloper for (;;) { 3373620737cSbeveloper consumer_get_next_input_request request; 3383620737cSbeveloper consumer_get_next_input_reply reply; 3393620737cSbeveloper request.cookie = cookie; 340*34c72144SAxel Dörfler rv = QueryPort(node.port, CONSUMER_GET_NEXT_INPUT, &request, 341*34c72144SAxel Dörfler sizeof(request), &reply, sizeof(reply)); 3423620737cSbeveloper if (rv != B_OK) 3433620737cSbeveloper break; 3443620737cSbeveloper cookie = reply.cookie; 34576669a29Sbeveloper if (!list->Insert(reply.input)) { 3465ac4fbd7Sbeveloper ERROR("GetAllInputs: list->Insert failed\n"); 3473620737cSbeveloper result = B_ERROR; 3483620737cSbeveloper } 3495ac4fbd7Sbeveloper #if DEBUG >= 3 3505ac4fbd7Sbeveloper PRINT(3," next cookie %ld, ", cookie); 3515ac4fbd7Sbeveloper PRINT_OUTPUT("input ", reply.input); 3525ac4fbd7Sbeveloper #endif 3533620737cSbeveloper } 3543620737cSbeveloper 3553620737cSbeveloper consumer_dispose_input_cookie_request request; 3563620737cSbeveloper consumer_dispose_input_cookie_reply reply; 357*34c72144SAxel Dörfler QueryPort(node.port, CONSUMER_DISPOSE_INPUT_COOKIE, &request, 358*34c72144SAxel Dörfler sizeof(request), &reply, sizeof(reply)); 3593620737cSbeveloper 3603620737cSbeveloper return result; 3613620737cSbeveloper } 3623620737cSbeveloper 363*34c72144SAxel Dörfler 3643620737cSbeveloper status_t 3654d2d96e0Sbeveloper BMediaRosterEx::GetAllInputs(BBufferConsumer* node, List<media_input>* list) 3664d2d96e0Sbeveloper { 3674d2d96e0Sbeveloper int32 cookie; 3684d2d96e0Sbeveloper status_t result; 3694d2d96e0Sbeveloper 3704d2d96e0Sbeveloper PRINT(4, "BMediaRosterEx::GetAllInputs() (by pointer) node %ld, port %ld\n", node->ID(), node->ControlPort()); 3714d2d96e0Sbeveloper 3724d2d96e0Sbeveloper result = B_OK; 3734d2d96e0Sbeveloper cookie = 0; 3744d2d96e0Sbeveloper list->MakeEmpty(); 3754d2d96e0Sbeveloper for (;;) { 3764d2d96e0Sbeveloper media_input input; 3774d2d96e0Sbeveloper if (B_OK != node->GetNextInput(&cookie, &input)) 3784d2d96e0Sbeveloper break; 3794d2d96e0Sbeveloper if (!list->Insert(input)) { 3804d2d96e0Sbeveloper ERROR("GetAllInputs: list->Insert failed\n"); 3814d2d96e0Sbeveloper result = B_ERROR; 3824d2d96e0Sbeveloper } 3834d2d96e0Sbeveloper #if DEBUG >= 3 3844d2d96e0Sbeveloper PRINT(3," next cookie %ld, ", cookie); 3854d2d96e0Sbeveloper PRINT_INPUT("input ", input); 3864d2d96e0Sbeveloper #endif 3874d2d96e0Sbeveloper } 3884d2d96e0Sbeveloper node->DisposeInputCookie(cookie); 3894d2d96e0Sbeveloper return result; 3904d2d96e0Sbeveloper } 3914d2d96e0Sbeveloper 392*34c72144SAxel Dörfler 3934d2d96e0Sbeveloper status_t 3948b04ffc1Sbeveloper BMediaRosterEx::PublishOutputs(const media_node& node, List<media_output>* list) 3953620737cSbeveloper { 3963620737cSbeveloper server_publish_outputs_request request; 3973620737cSbeveloper server_publish_outputs_reply reply; 3983620737cSbeveloper media_output* output; 3993620737cSbeveloper media_output* outputs; 4003620737cSbeveloper int32 count; 401a7b41a96Sbeveloper status_t rv; 4023620737cSbeveloper 40376669a29Sbeveloper count = list->CountItems(); 4043620737cSbeveloper TRACE("PublishOutputs: publishing %ld\n", count); 4053620737cSbeveloper 4063620737cSbeveloper request.node = node; 4073620737cSbeveloper request.count = count; 4083620737cSbeveloper if (count > MAX_OUTPUTS) { 4093620737cSbeveloper void *start_addr; 4103620737cSbeveloper size_t size; 41140f36b03Sbeveloper size = ROUND_UP_TO_PAGE(count * sizeof(media_output)); 412*34c72144SAxel Dörfler request.area = create_area("publish outputs", &start_addr, 413*34c72144SAxel Dörfler B_ANY_ADDRESS, size, B_NO_LOCK, B_READ_AREA | B_WRITE_AREA); 4143620737cSbeveloper if (request.area < B_OK) { 415*34c72144SAxel Dörfler ERROR("PublishOutputs: failed to create area, %#lx\n", 416*34c72144SAxel Dörfler request.area); 4173620737cSbeveloper return (status_t)request.area; 4183620737cSbeveloper } 4193620737cSbeveloper outputs = static_cast<media_output *>(start_addr); 4203620737cSbeveloper } else { 4213620737cSbeveloper request.area = -1; 4223620737cSbeveloper outputs = request.outputs; 4233620737cSbeveloper } 42476669a29Sbeveloper TRACE("PublishOutputs: area %ld\n", request.area); 4253620737cSbeveloper 42676669a29Sbeveloper int i; 42776669a29Sbeveloper for (i = 0, list->Rewind(); list->GetNext(&output); i++) { 42876669a29Sbeveloper ASSERT(i < count); 4293620737cSbeveloper outputs[i] = *output; 4303620737cSbeveloper } 4313620737cSbeveloper 432*34c72144SAxel Dörfler rv = QueryServer(SERVER_PUBLISH_OUTPUTS, &request, sizeof(request), 433*34c72144SAxel Dörfler &reply, sizeof(reply)); 434a7b41a96Sbeveloper 435a7b41a96Sbeveloper if (request.area != -1) 436a7b41a96Sbeveloper delete_area(request.area); 437a7b41a96Sbeveloper 438a7b41a96Sbeveloper return rv; 4393620737cSbeveloper } 4403620737cSbeveloper 441*34c72144SAxel Dörfler 4423620737cSbeveloper status_t 4438b04ffc1Sbeveloper BMediaRosterEx::PublishInputs(const media_node& node, List<media_input>* list) 4443620737cSbeveloper { 4453620737cSbeveloper server_publish_inputs_request request; 4463620737cSbeveloper server_publish_inputs_reply reply; 4473620737cSbeveloper media_input* input; 4483620737cSbeveloper media_input* inputs; 4493620737cSbeveloper int32 count; 450a7b41a96Sbeveloper status_t rv; 4513620737cSbeveloper 45276669a29Sbeveloper count = list->CountItems(); 4533620737cSbeveloper TRACE("PublishInputs: publishing %ld\n", count); 4543620737cSbeveloper 4553620737cSbeveloper request.node = node; 4563620737cSbeveloper request.count = count; 4573620737cSbeveloper if (count > MAX_INPUTS) { 4583620737cSbeveloper void* start_addr; 4593620737cSbeveloper size_t size; 46040f36b03Sbeveloper size = ROUND_UP_TO_PAGE(count * sizeof(media_input)); 461*34c72144SAxel Dörfler request.area = create_area("publish inputs", &start_addr, 462*34c72144SAxel Dörfler B_ANY_ADDRESS, size, B_NO_LOCK, B_READ_AREA | B_WRITE_AREA); 4633620737cSbeveloper if (request.area < B_OK) { 4645ac4fbd7Sbeveloper ERROR("PublishInputs: failed to create area, %#lx\n", request.area); 4653620737cSbeveloper return (status_t)request.area; 4663620737cSbeveloper } 4673620737cSbeveloper inputs = static_cast<media_input *>(start_addr); 4683620737cSbeveloper } else { 4693620737cSbeveloper request.area = -1; 4703620737cSbeveloper inputs = request.inputs; 4713620737cSbeveloper } 47276669a29Sbeveloper TRACE("PublishInputs: area %ld\n", request.area); 4733620737cSbeveloper 47476669a29Sbeveloper int i; 47576669a29Sbeveloper for (i = 0, list->Rewind(); list->GetNext(&input); i++) { 47676669a29Sbeveloper ASSERT(i < count); 4773620737cSbeveloper inputs[i] = *input; 4783620737cSbeveloper } 4793620737cSbeveloper 480*34c72144SAxel Dörfler rv = QueryServer(SERVER_PUBLISH_INPUTS, &request, sizeof(request), 481*34c72144SAxel Dörfler &reply, sizeof(reply)); 482a7b41a96Sbeveloper 483a7b41a96Sbeveloper if (request.area != -1) 484a7b41a96Sbeveloper delete_area(request.area); 485a7b41a96Sbeveloper 486a7b41a96Sbeveloper return rv; 4873620737cSbeveloper } 4883620737cSbeveloper 489*34c72144SAxel Dörfler 490*34c72144SAxel Dörfler BTimeSource* 491*34c72144SAxel Dörfler BMediaRosterEx::MakeTimeSourceObject(media_node_id timesourceID) 492*34c72144SAxel Dörfler { 493*34c72144SAxel Dörfler BTimeSource* source; 494*34c72144SAxel Dörfler media_node clone; 495*34c72144SAxel Dörfler status_t rv; 496*34c72144SAxel Dörfler 497*34c72144SAxel Dörfler rv = GetNodeFor(timesourceID, &clone); 498*34c72144SAxel Dörfler if (rv != B_OK) { 499*34c72144SAxel Dörfler ERROR("BMediaRosterEx::MakeTimeSourceObject: GetNodeFor failed\n"); 500*34c72144SAxel Dörfler return NULL; 501*34c72144SAxel Dörfler } 502*34c72144SAxel Dörfler 503*34c72144SAxel Dörfler source = _TimeSourceObjectManager->GetTimeSource(clone); 504*34c72144SAxel Dörfler if (source == NULL) { 505*34c72144SAxel Dörfler ERROR("BMediaRosterEx::MakeTimeSourceObject: GetTimeSource failed\n"); 506*34c72144SAxel Dörfler return NULL; 507*34c72144SAxel Dörfler } 508*34c72144SAxel Dörfler 509*34c72144SAxel Dörfler // TODO: release? 510*34c72144SAxel Dörfler ReleaseNode(clone); 511*34c72144SAxel Dörfler 512*34c72144SAxel Dörfler return source; 513*34c72144SAxel Dörfler } 514*34c72144SAxel Dörfler 515*34c72144SAxel Dörfler 516*34c72144SAxel Dörfler // #pragma mark - public BMediaRoster 517*34c72144SAxel Dörfler 51852a38012Sejakowatz 51952a38012Sejakowatz status_t 520*34c72144SAxel Dörfler BMediaRoster::GetVideoInput(media_node* _node) 52152a38012Sejakowatz { 52252a38012Sejakowatz CALLED(); 523*34c72144SAxel Dörfler return MediaRosterEx(this)->GetNode(VIDEO_INPUT, _node); 52452a38012Sejakowatz } 52552a38012Sejakowatz 52652a38012Sejakowatz 52752a38012Sejakowatz status_t 528*34c72144SAxel Dörfler BMediaRoster::GetAudioInput(media_node* _node) 52952a38012Sejakowatz { 53052a38012Sejakowatz CALLED(); 531*34c72144SAxel Dörfler return MediaRosterEx(this)->GetNode(AUDIO_INPUT, _node); 53252a38012Sejakowatz } 53352a38012Sejakowatz 53452a38012Sejakowatz 53552a38012Sejakowatz status_t 536*34c72144SAxel Dörfler BMediaRoster::GetVideoOutput(media_node* _node) 53752a38012Sejakowatz { 53852a38012Sejakowatz CALLED(); 539*34c72144SAxel Dörfler return MediaRosterEx(this)->GetNode(VIDEO_OUTPUT, _node); 54052a38012Sejakowatz } 54152a38012Sejakowatz 54252a38012Sejakowatz 54352a38012Sejakowatz status_t 544*34c72144SAxel Dörfler BMediaRoster::GetAudioMixer(media_node* _node) 54552a38012Sejakowatz { 54652a38012Sejakowatz CALLED(); 547*34c72144SAxel Dörfler return MediaRosterEx(this)->GetNode(AUDIO_MIXER, _node); 54852a38012Sejakowatz } 54952a38012Sejakowatz 55052a38012Sejakowatz 55152a38012Sejakowatz status_t 552*34c72144SAxel Dörfler BMediaRoster::GetAudioOutput(media_node* _node) 55352a38012Sejakowatz { 55452a38012Sejakowatz CALLED(); 555*34c72144SAxel Dörfler return MediaRosterEx(this)->GetNode(AUDIO_OUTPUT, _node); 55652a38012Sejakowatz } 55752a38012Sejakowatz 55852a38012Sejakowatz 55952a38012Sejakowatz status_t 560*34c72144SAxel Dörfler BMediaRoster::GetAudioOutput(media_node* _node, int32* _inputID, 561*34c72144SAxel Dörfler BString* _inputName) 56252a38012Sejakowatz { 56352a38012Sejakowatz CALLED(); 564*34c72144SAxel Dörfler return MediaRosterEx(this)->GetNode(AUDIO_OUTPUT_EX, _node, _inputID, 565*34c72144SAxel Dörfler _inputName); 56652a38012Sejakowatz } 56752a38012Sejakowatz 56852a38012Sejakowatz 56952a38012Sejakowatz status_t 570*34c72144SAxel Dörfler BMediaRoster::GetTimeSource(media_node* _node) 57152a38012Sejakowatz { 57252a38012Sejakowatz CALLED(); 57386bce45bSbeveloper status_t rv; 57486bce45bSbeveloper 575*34c72144SAxel Dörfler // TODO: need to do this in a nicer way. 57686bce45bSbeveloper 577*34c72144SAxel Dörfler rv = MediaRosterEx(this)->GetNode(TIME_SOURCE, _node); 57886bce45bSbeveloper if (rv != B_OK) 57986bce45bSbeveloper return rv; 58086bce45bSbeveloper 58186bce45bSbeveloper // We don't do reference counting for timesources, that's why we 58286bce45bSbeveloper // release the node immediately. 583*34c72144SAxel Dörfler ReleaseNode(*_node); 58486bce45bSbeveloper 58586bce45bSbeveloper // we need to remember to not use this node with server side reference counting 586*34c72144SAxel Dörfler _node->kind |= NODE_KIND_NO_REFCOUNTING; 58786bce45bSbeveloper return B_OK; 58852a38012Sejakowatz } 58952a38012Sejakowatz 59052a38012Sejakowatz 59152a38012Sejakowatz status_t 59252a38012Sejakowatz BMediaRoster::SetVideoInput(const media_node& producer) 59352a38012Sejakowatz { 59452a38012Sejakowatz CALLED(); 5958b04ffc1Sbeveloper return MediaRosterEx(this)->SetNode(VIDEO_INPUT, &producer); 59652a38012Sejakowatz } 59752a38012Sejakowatz 59852a38012Sejakowatz 59952a38012Sejakowatz status_t 60052a38012Sejakowatz BMediaRoster::SetVideoInput(const dormant_node_info& producer) 60152a38012Sejakowatz { 60252a38012Sejakowatz CALLED(); 6038b04ffc1Sbeveloper return MediaRosterEx(this)->SetNode(VIDEO_INPUT, NULL, &producer); 60452a38012Sejakowatz } 60552a38012Sejakowatz 60652a38012Sejakowatz 60752a38012Sejakowatz status_t 60852a38012Sejakowatz BMediaRoster::SetAudioInput(const media_node& producer) 60952a38012Sejakowatz { 61052a38012Sejakowatz CALLED(); 6118b04ffc1Sbeveloper return MediaRosterEx(this)->SetNode(AUDIO_INPUT, &producer); 61252a38012Sejakowatz } 61352a38012Sejakowatz 61452a38012Sejakowatz 61552a38012Sejakowatz status_t 61652a38012Sejakowatz BMediaRoster::SetAudioInput(const dormant_node_info& producer) 61752a38012Sejakowatz { 61852a38012Sejakowatz CALLED(); 6198b04ffc1Sbeveloper return MediaRosterEx(this)->SetNode(AUDIO_INPUT, NULL, &producer); 62052a38012Sejakowatz } 62152a38012Sejakowatz 62252a38012Sejakowatz 62352a38012Sejakowatz status_t 62452a38012Sejakowatz BMediaRoster::SetVideoOutput(const media_node& consumer) 62552a38012Sejakowatz { 62652a38012Sejakowatz CALLED(); 6278b04ffc1Sbeveloper return MediaRosterEx(this)->SetNode(VIDEO_OUTPUT, &consumer); 62852a38012Sejakowatz } 62952a38012Sejakowatz 63052a38012Sejakowatz 63152a38012Sejakowatz status_t 63252a38012Sejakowatz BMediaRoster::SetVideoOutput(const dormant_node_info& consumer) 63352a38012Sejakowatz { 63452a38012Sejakowatz CALLED(); 6358b04ffc1Sbeveloper return MediaRosterEx(this)->SetNode(VIDEO_OUTPUT, NULL, &consumer); 63652a38012Sejakowatz } 63752a38012Sejakowatz 63852a38012Sejakowatz 63952a38012Sejakowatz status_t 64052a38012Sejakowatz BMediaRoster::SetAudioOutput(const media_node& consumer) 64152a38012Sejakowatz { 64252a38012Sejakowatz CALLED(); 6438b04ffc1Sbeveloper return MediaRosterEx(this)->SetNode(AUDIO_OUTPUT, &consumer); 64452a38012Sejakowatz } 64552a38012Sejakowatz 64652a38012Sejakowatz 64752a38012Sejakowatz status_t 648*34c72144SAxel Dörfler BMediaRoster::SetAudioOutput(const media_input& input) 64952a38012Sejakowatz { 65052a38012Sejakowatz CALLED(); 651*34c72144SAxel Dörfler return MediaRosterEx(this)->SetNode(AUDIO_OUTPUT, NULL, NULL, &input); 65252a38012Sejakowatz } 65352a38012Sejakowatz 65452a38012Sejakowatz 65552a38012Sejakowatz status_t 65652a38012Sejakowatz BMediaRoster::SetAudioOutput(const dormant_node_info& consumer) 65752a38012Sejakowatz { 65852a38012Sejakowatz CALLED(); 6598b04ffc1Sbeveloper return MediaRosterEx(this)->SetNode(AUDIO_OUTPUT, NULL, &consumer); 66052a38012Sejakowatz } 66152a38012Sejakowatz 66252a38012Sejakowatz 66352a38012Sejakowatz status_t 664*34c72144SAxel Dörfler BMediaRoster::GetNodeFor(media_node_id node, media_node* clone) 66552a38012Sejakowatz { 6669e9417d2Sbeveloper CALLED(); 6679e9417d2Sbeveloper if (clone == NULL) 6689e9417d2Sbeveloper return B_BAD_VALUE; 66965b73ae4SMarcus Overhagen if (IS_INVALID_NODEID(node)) 6709e9417d2Sbeveloper return B_MEDIA_BAD_NODE; 6719e9417d2Sbeveloper 6729e9417d2Sbeveloper server_get_node_for_request request; 6739e9417d2Sbeveloper server_get_node_for_reply reply; 6749e9417d2Sbeveloper status_t rv; 6759e9417d2Sbeveloper 6769e9417d2Sbeveloper request.nodeid = node; 6779e9417d2Sbeveloper request.team = team; 6789e9417d2Sbeveloper 679*34c72144SAxel Dörfler rv = QueryServer(SERVER_GET_NODE_FOR, &request, sizeof(request), &reply, 680*34c72144SAxel Dörfler sizeof(reply)); 6819e9417d2Sbeveloper if (rv != B_OK) 6829e9417d2Sbeveloper return rv; 6839e9417d2Sbeveloper 6849e9417d2Sbeveloper *clone = reply.clone; 6859e9417d2Sbeveloper return B_OK; 68652a38012Sejakowatz } 68752a38012Sejakowatz 68852a38012Sejakowatz 68952a38012Sejakowatz status_t 69052a38012Sejakowatz BMediaRoster::GetSystemTimeSource(media_node* clone) 69152a38012Sejakowatz { 69252a38012Sejakowatz CALLED(); 69386bce45bSbeveloper status_t rv; 69486bce45bSbeveloper 695*34c72144SAxel Dörfler // TODO: need to do this in a nicer way. 69686bce45bSbeveloper 69786bce45bSbeveloper rv = MediaRosterEx(this)->GetNode(SYSTEM_TIME_SOURCE, clone); 69886bce45bSbeveloper if (rv != B_OK) 69986bce45bSbeveloper return rv; 70086bce45bSbeveloper 70186bce45bSbeveloper // We don't do reference counting for timesources, that's why we 70286bce45bSbeveloper // release the node immediately. 70386bce45bSbeveloper ReleaseNode(*clone); 70486bce45bSbeveloper 705*34c72144SAxel Dörfler // we need to remember to not use this node with server side reference 706*34c72144SAxel Dörfler // counting 70786bce45bSbeveloper clone->kind |= NODE_KIND_NO_REFCOUNTING; 70886bce45bSbeveloper 70986bce45bSbeveloper return B_OK; 71052a38012Sejakowatz } 71152a38012Sejakowatz 71252a38012Sejakowatz 71352a38012Sejakowatz status_t 71452a38012Sejakowatz BMediaRoster::ReleaseNode(const media_node& node) 71552a38012Sejakowatz { 7169e9417d2Sbeveloper CALLED(); 71740f36b03Sbeveloper if (IS_INVALID_NODE(node)) 7189e9417d2Sbeveloper return B_MEDIA_BAD_NODE; 71952a38012Sejakowatz 72086bce45bSbeveloper if (node.kind & NODE_KIND_NO_REFCOUNTING) { 721*34c72144SAxel Dörfler printf("BMediaRoster::ReleaseNode, trying to release reference " 722*34c72144SAxel Dörfler "counting disabled timesource, node %ld, port %ld, team %ld\n", 723*34c72144SAxel Dörfler node.node, node.port, team); 72486bce45bSbeveloper return B_OK; 72586bce45bSbeveloper } 72686bce45bSbeveloper 7279e9417d2Sbeveloper server_release_node_request request; 7289e9417d2Sbeveloper server_release_node_reply reply; 729cf4e2277Sbeveloper status_t rv; 7309e9417d2Sbeveloper 7319e9417d2Sbeveloper request.node = node; 7329e9417d2Sbeveloper request.team = team; 7339e9417d2Sbeveloper 734*34c72144SAxel Dörfler TRACE("BMediaRoster::ReleaseNode, node %ld, port %ld, team %ld\n", 735*34c72144SAxel Dörfler node.node, node.port, team); 736cf4e2277Sbeveloper 737*34c72144SAxel Dörfler rv = QueryServer(SERVER_RELEASE_NODE, &request, sizeof(request), &reply, 738*34c72144SAxel Dörfler sizeof(reply)); 739cf4e2277Sbeveloper if (rv != B_OK) { 740*34c72144SAxel Dörfler ERROR("BMediaRoster::ReleaseNode FAILED, node %ld, port %ld, team " 741*34c72144SAxel Dörfler "%ld!\n", node.node, node.port, team); 742cf4e2277Sbeveloper } 743cf4e2277Sbeveloper return rv; 7449e9417d2Sbeveloper } 74552a38012Sejakowatz 746*34c72144SAxel Dörfler 74752a38012Sejakowatz BTimeSource* 748*34c72144SAxel Dörfler BMediaRoster::MakeTimeSourceFor(const media_node& forNode) 74952a38012Sejakowatz { 750f180ef79Sbeveloper // MakeTimeSourceFor() returns a BTimeSource object 751f180ef79Sbeveloper // corresponding to the specified node's time source. 752f180ef79Sbeveloper 753835140c8Sbeveloper CALLED(); 754f180ef79Sbeveloper 755*34c72144SAxel Dörfler if (IS_SYSTEM_TIMESOURCE(forNode)) { 756f180ef79Sbeveloper // special handling for the system time source 757*34c72144SAxel Dörfler TRACE("BMediaRoster::MakeTimeSourceFor, asked for system time " 758*34c72144SAxel Dörfler "source\n"); 759*34c72144SAxel Dörfler return MediaRosterEx(this)->MakeTimeSourceObject( 760*34c72144SAxel Dörfler NODE_SYSTEM_TIMESOURCE_ID); 761f180ef79Sbeveloper } 762f180ef79Sbeveloper 763*34c72144SAxel Dörfler if (IS_INVALID_NODE(forNode)) { 764*34c72144SAxel Dörfler ERROR("BMediaRoster::MakeTimeSourceFor: for_node invalid, node %ld, " 765*34c72144SAxel Dörfler "port %ld, kinds 0x%lx\n", forNode.node, forNode.port, 766*34c72144SAxel Dörfler forNode.kind); 7675917dd5bSbeveloper return NULL; 7680e21b167Sbeveloper } 7690e21b167Sbeveloper 770*34c72144SAxel Dörfler TRACE("BMediaRoster::MakeTimeSourceFor: node %ld enter\n", forNode.node); 7715917dd5bSbeveloper 7725917dd5bSbeveloper node_get_timesource_request request; 7735917dd5bSbeveloper node_get_timesource_reply reply; 7745917dd5bSbeveloper BTimeSource *source; 7755917dd5bSbeveloper status_t rv; 7765917dd5bSbeveloper 77792e575c1Sbeveloper // ask the node to get it's current timesource id 778*34c72144SAxel Dörfler rv = QueryPort(forNode.port, NODE_GET_TIMESOURCE, &request, 779*34c72144SAxel Dörfler sizeof(request), &reply, sizeof(reply)); 7805917dd5bSbeveloper if (rv != B_OK) { 7815ac4fbd7Sbeveloper ERROR("BMediaRoster::MakeTimeSourceFor: request failed\n"); 7825917dd5bSbeveloper return NULL; 7835917dd5bSbeveloper } 7845917dd5bSbeveloper 7855917dd5bSbeveloper source = MediaRosterEx(this)->MakeTimeSourceObject(reply.timesource_id); 7865917dd5bSbeveloper 787*34c72144SAxel Dörfler TRACE("BMediaRoster::MakeTimeSourceFor: node %ld leave\n", forNode.node); 788287f7492Sbeveloper 789835140c8Sbeveloper return source; 79052a38012Sejakowatz } 79152a38012Sejakowatz 79252a38012Sejakowatz 79352a38012Sejakowatz status_t 794*34c72144SAxel Dörfler BMediaRoster::Connect(const media_source& from, const media_destination& to, 795*34c72144SAxel Dörfler media_format* _format, media_output* _output, media_input* _input) 79652a38012Sejakowatz { 797*34c72144SAxel Dörfler return BMediaRoster::Connect(from, to, _format, _output, _input, 0); 798eae26d3dSbeveloper } 799eae26d3dSbeveloper 800eae26d3dSbeveloper 801eae26d3dSbeveloper status_t 802*34c72144SAxel Dörfler BMediaRoster::Connect(const media_source& from, const media_destination& to, 803*34c72144SAxel Dörfler media_format* io_format, media_output* out_output, media_input* out_input, 804*34c72144SAxel Dörfler uint32 in_flags, void* _reserved) 805eae26d3dSbeveloper { 80652a38012Sejakowatz CALLED(); 80752a38012Sejakowatz if (io_format == NULL || out_output == NULL || out_input == NULL) 80852a38012Sejakowatz return B_BAD_VALUE; 80940f36b03Sbeveloper if (IS_INVALID_SOURCE(from)) { 8105ac4fbd7Sbeveloper ERROR("BMediaRoster::Connect: media_source invalid\n"); 81152a38012Sejakowatz return B_MEDIA_BAD_SOURCE; 8129e9417d2Sbeveloper } 81340f36b03Sbeveloper if (IS_INVALID_DESTINATION(to)) { 8145ac4fbd7Sbeveloper ERROR("BMediaRoster::Connect: media_destination invalid\n"); 81552a38012Sejakowatz return B_MEDIA_BAD_DESTINATION; 8169e9417d2Sbeveloper } 81752a38012Sejakowatz 81852a38012Sejakowatz status_t rv; 81965b73ae4SMarcus Overhagen 82065b73ae4SMarcus Overhagen // find the output and input nodes 821*34c72144SAxel Dörfler // TODO: isn't there a easier way? 82265b73ae4SMarcus Overhagen media_node sourcenode; 82365b73ae4SMarcus Overhagen media_node destnode; 82465b73ae4SMarcus Overhagen rv = GetNodeFor(NodeIDFor(from.port), &sourcenode); 82565b73ae4SMarcus Overhagen if (rv != B_OK) { 826*34c72144SAxel Dörfler ERROR("BMediaRoster::Connect: Can't find source node for port %ld\n", 827*34c72144SAxel Dörfler from.port); 82865b73ae4SMarcus Overhagen return B_MEDIA_BAD_SOURCE; 82965b73ae4SMarcus Overhagen } 83065b73ae4SMarcus Overhagen ReleaseNode(sourcenode); 83165b73ae4SMarcus Overhagen rv = GetNodeFor(NodeIDFor(to.port), &destnode); 83265b73ae4SMarcus Overhagen if (rv != B_OK) { 833*34c72144SAxel Dörfler ERROR("BMediaRoster::Connect: Can't find destination node for port " 834*34c72144SAxel Dörfler "%ld\n", to.port); 83565b73ae4SMarcus Overhagen return B_MEDIA_BAD_DESTINATION; 83665b73ae4SMarcus Overhagen } 83765b73ae4SMarcus Overhagen ReleaseNode(destnode); 83865b73ae4SMarcus Overhagen 83965b73ae4SMarcus Overhagen if (!(sourcenode.kind & B_BUFFER_PRODUCER)) { 840*34c72144SAxel Dörfler ERROR("BMediaRoster::Connect: source node %ld is not a " 841*34c72144SAxel Dörfler "B_BUFFER_PRODUCER\n", sourcenode.node); 84265b73ae4SMarcus Overhagen return B_MEDIA_BAD_SOURCE; 84365b73ae4SMarcus Overhagen } 84465b73ae4SMarcus Overhagen if (!(destnode.kind & B_BUFFER_CONSUMER)) { 845*34c72144SAxel Dörfler ERROR("BMediaRoster::Connect: destination node %ld is not a " 846*34c72144SAxel Dörfler "B_BUFFER_CONSUMER\n", destnode.node); 84765b73ae4SMarcus Overhagen return B_MEDIA_BAD_DESTINATION; 84865b73ae4SMarcus Overhagen } 84965b73ae4SMarcus Overhagen 8508c6a6096Sbeveloper producer_format_proposal_request request1; 8518c6a6096Sbeveloper producer_format_proposal_reply reply1; 85252a38012Sejakowatz 853*34c72144SAxel Dörfler PRINT_FORMAT("BMediaRoster::Connect calling " 854*34c72144SAxel Dörfler "BBufferProducer::FormatProposal with format ", *io_format); 85569983609Sbeveloper 85652a38012Sejakowatz // BBufferProducer::FormatProposal 8578c6a6096Sbeveloper request1.output = from; 8588c6a6096Sbeveloper request1.format = *io_format; 859*34c72144SAxel Dörfler rv = QueryPort(from.port, PRODUCER_FORMAT_PROPOSAL, &request1, 860*34c72144SAxel Dörfler sizeof(request1), &reply1, sizeof(reply1)); 8618c6a6096Sbeveloper if (rv != B_OK) { 862*34c72144SAxel Dörfler ERROR("BMediaRoster::Connect: aborted after " 863*34c72144SAxel Dörfler "BBufferProducer::FormatProposal, status = %#lx\n",rv); 86452a38012Sejakowatz return rv; 86552a38012Sejakowatz } 8668c6a6096Sbeveloper // reply1.format now contains the format proposed by the producer 8678c6a6096Sbeveloper 8688c6a6096Sbeveloper consumer_accept_format_request request2; 8698c6a6096Sbeveloper consumer_accept_format_reply reply2; 8708c6a6096Sbeveloper 871*34c72144SAxel Dörfler PRINT_FORMAT("BMediaRoster::Connect calling " 872*34c72144SAxel Dörfler "BBufferConsumer::AcceptFormat with format ", reply1.format); 87369983609Sbeveloper 8748c6a6096Sbeveloper // BBufferConsumer::AcceptFormat 8758c6a6096Sbeveloper request2.dest = to; 8768c6a6096Sbeveloper request2.format = reply1.format; 877*34c72144SAxel Dörfler rv = QueryPort(to.port, CONSUMER_ACCEPT_FORMAT, &request2, 878*34c72144SAxel Dörfler sizeof(request2), &reply2, sizeof(reply2)); 8798c6a6096Sbeveloper if (rv != B_OK) { 880*34c72144SAxel Dörfler ERROR("BMediaRoster::Connect: aborted after " 881*34c72144SAxel Dörfler "BBufferConsumer::AcceptFormat, status = %#lx\n",rv); 8828c6a6096Sbeveloper return rv; 8838c6a6096Sbeveloper } 8848c6a6096Sbeveloper // reply2.format now contains the format accepted by the consumer 8858c6a6096Sbeveloper 8868c6a6096Sbeveloper // BBufferProducer::PrepareToConnect 8878c6a6096Sbeveloper producer_prepare_to_connect_request request3; 8888c6a6096Sbeveloper producer_prepare_to_connect_reply reply3; 8898c6a6096Sbeveloper 890*34c72144SAxel Dörfler PRINT_FORMAT("BMediaRoster::Connect calling " 891*34c72144SAxel Dörfler "BBufferProducer::PrepareToConnect with format", reply2.format); 89269983609Sbeveloper 8938c6a6096Sbeveloper request3.source = from; 8948c6a6096Sbeveloper request3.destination = to; 8958c6a6096Sbeveloper request3.format = reply2.format; 896*34c72144SAxel Dörfler strcpy(request3.name, "XXX some default name"); // TODO: fix this 897*34c72144SAxel Dörfler rv = QueryPort(from.port, PRODUCER_PREPARE_TO_CONNECT, &request3, 898*34c72144SAxel Dörfler sizeof(request3), &reply3, sizeof(reply3)); 8998c6a6096Sbeveloper if (rv != B_OK) { 900*34c72144SAxel Dörfler ERROR("BMediaRoster::Connect: aborted after " 901*34c72144SAxel Dörfler "BBufferProducer::PrepareToConnect, status = %#lx\n",rv); 9028c6a6096Sbeveloper return rv; 9038c6a6096Sbeveloper } 9048c6a6096Sbeveloper // reply3.format is still our pretty media format 9058c6a6096Sbeveloper // reply3.out_source the real source to be used for the connection 906*34c72144SAxel Dörfler // reply3.name the name BBufferConsumer::Connected will see in the 907*34c72144SAxel Dörfler // outInput->name argument 9088c6a6096Sbeveloper 9098c6a6096Sbeveloper // BBufferConsumer::Connected 9108c6a6096Sbeveloper consumer_connected_request request4; 9118c6a6096Sbeveloper consumer_connected_reply reply4; 9128c6a6096Sbeveloper status_t con_status; 9138c6a6096Sbeveloper 914*34c72144SAxel Dörfler PRINT_FORMAT("BMediaRoster::Connect calling BBufferConsumer::Connected() " 915*34c72144SAxel Dörfler "with format ", reply3.format); 91669983609Sbeveloper 91769983609Sbeveloper request4.input.node = destnode; 91869983609Sbeveloper request4.input.source = reply3.out_source; 91969983609Sbeveloper request4.input.destination = to; 92069983609Sbeveloper request4.input.format = reply3.format; 92169983609Sbeveloper strcpy(request4.input.name, reply3.name); 92269983609Sbeveloper 923*34c72144SAxel Dörfler con_status = QueryPort(to.port, CONSUMER_CONNECTED, &request4, 924*34c72144SAxel Dörfler sizeof(request4), &reply4, sizeof(reply4)); 9258c6a6096Sbeveloper if (con_status != B_OK) { 926*34c72144SAxel Dörfler ERROR("BMediaRoster::Connect: aborting after " 927*34c72144SAxel Dörfler "BBufferConsumer::Connected, status = %#lx\n",con_status); 9288c6a6096Sbeveloper // we do NOT return here! 9298c6a6096Sbeveloper } 930*34c72144SAxel Dörfler // con_status contains the status code to be supplied to 931*34c72144SAxel Dörfler // BBufferProducer::Connect's status argument 932*34c72144SAxel Dörfler // reply4.input contains the media_input that describes the connection 933*34c72144SAxel Dörfler // from the consumer point of view 9348c6a6096Sbeveloper 9358c6a6096Sbeveloper // BBufferProducer::Connect 9368c6a6096Sbeveloper producer_connect_request request5; 9378c6a6096Sbeveloper producer_connect_reply reply5; 9388c6a6096Sbeveloper 939*34c72144SAxel Dörfler PRINT_FORMAT("BMediaRoster::Connect calling BBufferProducer::Connect with " 940*34c72144SAxel Dörfler "format ", reply4.input.format); 94169983609Sbeveloper 9428c6a6096Sbeveloper request5.error = con_status; 9438c6a6096Sbeveloper request5.source = reply3.out_source; 9448c6a6096Sbeveloper request5.destination = reply4.input.destination; 94569983609Sbeveloper request5.format = reply4.input.format; 9468c6a6096Sbeveloper strcpy(request5.name, reply4.input.name); 947*34c72144SAxel Dörfler rv = QueryPort(reply4.input.source.port, PRODUCER_CONNECT, &request5, 948*34c72144SAxel Dörfler sizeof(request5), &reply5, sizeof(reply5)); 9498c6a6096Sbeveloper if (con_status != B_OK) { 9505ac4fbd7Sbeveloper ERROR("BMediaRoster::Connect: aborted\n"); 9518c6a6096Sbeveloper return con_status; 9528c6a6096Sbeveloper } 9538c6a6096Sbeveloper if (rv != B_OK) { 954*34c72144SAxel Dörfler ERROR("BMediaRoster::Connect: aborted after BBufferProducer::Connect()" 955*34c72144SAxel Dörfler ", status = %#lx\n",rv); 9568c6a6096Sbeveloper return rv; 9578c6a6096Sbeveloper } 9588c6a6096Sbeveloper // reply5.name contains the name assigned to the connection by the producer 9598c6a6096Sbeveloper 9608c6a6096Sbeveloper // initilize connection info 96169983609Sbeveloper *io_format = reply4.input.format; 9628c6a6096Sbeveloper *out_input = reply4.input; 9638c6a6096Sbeveloper out_output->node = sourcenode; 9648c6a6096Sbeveloper out_output->source = reply4.input.source; 9658c6a6096Sbeveloper out_output->destination = reply4.input.destination; 9668c6a6096Sbeveloper out_output->format = reply4.input.format; 9678c6a6096Sbeveloper strcpy(out_output->name, reply5.name); 9688c6a6096Sbeveloper 9698c6a6096Sbeveloper // the connection is now made 97069983609Sbeveloper printf("BMediaRoster::Connect connection established!\n"); 97169983609Sbeveloper PRINT_FORMAT(" format", *io_format); 97269983609Sbeveloper PRINT_INPUT(" input", *out_input); 97369983609Sbeveloper PRINT_OUTPUT(" output", *out_output); 9748c6a6096Sbeveloper 975*34c72144SAxel Dörfler // TODO: register connection with server 976*34c72144SAxel Dörfler // TODO: we should just send a notification, instead of republishing all 977*34c72144SAxel Dörfler // endpoints 97876669a29Sbeveloper List<media_output> outlist; 97976669a29Sbeveloper List<media_input> inlist; 980*34c72144SAxel Dörfler if (MediaRosterEx(this)->GetAllOutputs(out_output->node , &outlist) == B_OK) 9818b04ffc1Sbeveloper MediaRosterEx(this)->PublishOutputs(out_output->node , &outlist); 982*34c72144SAxel Dörfler if (MediaRosterEx(this)->GetAllInputs(out_input->node , &inlist) == B_OK) 9838b04ffc1Sbeveloper MediaRosterEx(this)->PublishInputs(out_input->node, &inlist); 9848c6a6096Sbeveloper 985*34c72144SAxel Dörfler // TODO: if (mute) BBufferProducer::EnableOutput(false) 9869e9417d2Sbeveloper if (in_flags & B_CONNECT_MUTED) { 9879e9417d2Sbeveloper } 9888c6a6096Sbeveloper 9899e9417d2Sbeveloper // send a notification 990*34c72144SAxel Dörfler BPrivate::media::notifications::ConnectionMade(*out_input, *out_output, 991*34c72144SAxel Dörfler *io_format); 9929e9417d2Sbeveloper 9938c6a6096Sbeveloper return B_OK; 9948c6a6096Sbeveloper }; 99552a38012Sejakowatz 99652a38012Sejakowatz 99752a38012Sejakowatz status_t 9989e9417d2Sbeveloper BMediaRoster::Disconnect(media_node_id source_nodeid, 999*34c72144SAxel Dörfler const media_source& source, media_node_id destination_nodeid, 100052a38012Sejakowatz const media_destination& destination) 100152a38012Sejakowatz { 10029e9417d2Sbeveloper CALLED(); 100340f36b03Sbeveloper if (IS_INVALID_NODEID(source_nodeid)) { 10045ac4fbd7Sbeveloper ERROR("BMediaRoster::Disconnect: source media_node_id invalid\n"); 10059e9417d2Sbeveloper return B_MEDIA_BAD_SOURCE; 10069e9417d2Sbeveloper } 100740f36b03Sbeveloper if (IS_INVALID_NODEID(destination_nodeid)) { 10085ac4fbd7Sbeveloper ERROR("BMediaRoster::Disconnect: destination media_node_id invalid\n"); 10099e9417d2Sbeveloper return B_MEDIA_BAD_DESTINATION; 10109e9417d2Sbeveloper } 101140f36b03Sbeveloper if (IS_INVALID_SOURCE(source)) { 10125ac4fbd7Sbeveloper ERROR("BMediaRoster::Disconnect: media_source invalid\n"); 10139e9417d2Sbeveloper return B_MEDIA_BAD_SOURCE; 10149e9417d2Sbeveloper } 101540f36b03Sbeveloper if (IS_INVALID_DESTINATION(destination)) { 10165ac4fbd7Sbeveloper ERROR("BMediaRoster::Disconnect: media_destination invalid\n"); 10179e9417d2Sbeveloper return B_MEDIA_BAD_DESTINATION; 10189e9417d2Sbeveloper } 10199e9417d2Sbeveloper 10209e9417d2Sbeveloper producer_disconnect_request request2; 10219e9417d2Sbeveloper producer_disconnect_reply reply2; 10229e9417d2Sbeveloper consumer_disconnected_request request1; 10239e9417d2Sbeveloper consumer_disconnected_reply reply1; 10249e9417d2Sbeveloper status_t rv1, rv2; 10259e9417d2Sbeveloper 1026*34c72144SAxel Dörfler // TODO: we should ask the server if this connection really exists 10279e9417d2Sbeveloper 10289e9417d2Sbeveloper request1.source = source; 10299e9417d2Sbeveloper request1.destination = destination; 10309e9417d2Sbeveloper request2.source = source; 10319e9417d2Sbeveloper request2.destination = destination; 10329e9417d2Sbeveloper 1033*34c72144SAxel Dörfler rv1 = QueryPort(source.port, PRODUCER_DISCONNECT, &request1, 1034*34c72144SAxel Dörfler sizeof(request1), &reply1, sizeof(reply1)); 1035*34c72144SAxel Dörfler rv2 = QueryPort(destination.port, CONSUMER_DISCONNECTED, &request2, 1036*34c72144SAxel Dörfler sizeof(request2), &reply2, sizeof(reply2)); 10379e9417d2Sbeveloper 1038*34c72144SAxel Dörfler // TODO: unregister connection with server 1039*34c72144SAxel Dörfler // TODO: we should just send a notification, instead of republishing all 1040*34c72144SAxel Dörfler // endpoints 104176669a29Sbeveloper List<media_output> outlist; 104276669a29Sbeveloper List<media_input> inlist; 10439e9417d2Sbeveloper media_node sourcenode; 10449e9417d2Sbeveloper media_node destnode; 1045*34c72144SAxel Dörfler if (GetNodeFor(source_nodeid, &sourcenode) == B_OK) { 104665b73ae4SMarcus Overhagen if (!(sourcenode.kind & B_BUFFER_PRODUCER)) { 1047*34c72144SAxel Dörfler ERROR("BMediaRoster::Disconnect: source_nodeid %ld is not a " 1048*34c72144SAxel Dörfler "B_BUFFER_PRODUCER\n", source_nodeid); 104965b73ae4SMarcus Overhagen } 1050*34c72144SAxel Dörfler if (MediaRosterEx(this)->GetAllOutputs(sourcenode , &outlist) == B_OK) 10518b04ffc1Sbeveloper MediaRosterEx(this)->PublishOutputs(sourcenode , &outlist); 10529e9417d2Sbeveloper ReleaseNode(sourcenode); 10534f09fa2fSbeveloper } else { 105465b73ae4SMarcus Overhagen ERROR("BMediaRoster::Disconnect: GetNodeFor source_nodeid %ld failed\n", source_nodeid); 10554f09fa2fSbeveloper } 1056*34c72144SAxel Dörfler if (GetNodeFor(destination_nodeid, &destnode) == B_OK) { 105765b73ae4SMarcus Overhagen if (!(destnode.kind & B_BUFFER_CONSUMER)) { 1058*34c72144SAxel Dörfler ERROR("BMediaRoster::Disconnect: destination_nodeid %ld is not a " 1059*34c72144SAxel Dörfler "B_BUFFER_CONSUMER\n", destination_nodeid); 106065b73ae4SMarcus Overhagen } 1061*34c72144SAxel Dörfler if (MediaRosterEx(this)->GetAllInputs(destnode , &inlist) == B_OK) 10628b04ffc1Sbeveloper MediaRosterEx(this)->PublishInputs(destnode, &inlist); 10639e9417d2Sbeveloper ReleaseNode(destnode); 10644f09fa2fSbeveloper } else { 1065*34c72144SAxel Dörfler ERROR("BMediaRoster::Disconnect: GetNodeFor destination_nodeid %ld " 1066*34c72144SAxel Dörfler "failed\n", destination_nodeid); 10674f09fa2fSbeveloper } 10689e9417d2Sbeveloper 10699e9417d2Sbeveloper // send a notification 10709e9417d2Sbeveloper BPrivate::media::notifications::ConnectionBroken(source, destination); 10719e9417d2Sbeveloper 1072*34c72144SAxel Dörfler return rv1 != B_OK || rv2 != B_OK ? B_ERROR : B_OK; 107352a38012Sejakowatz } 107452a38012Sejakowatz 1075*34c72144SAxel Dörfler 107665b73ae4SMarcus Overhagen status_t 107765b73ae4SMarcus Overhagen BMediaRoster::Disconnect(const media_output& output, const media_input& input) 107865b73ae4SMarcus Overhagen { 107965b73ae4SMarcus Overhagen if (IS_INVALID_NODEID(output.node.node)) { 108065b73ae4SMarcus Overhagen printf("BMediaRoster::Disconnect: output.node.node %ld invalid\n", 108165b73ae4SMarcus Overhagen output.node.node); 108265b73ae4SMarcus Overhagen return B_MEDIA_BAD_SOURCE; 108365b73ae4SMarcus Overhagen } 108465b73ae4SMarcus Overhagen if (IS_INVALID_NODEID(input.node.node)) { 108565b73ae4SMarcus Overhagen printf("BMediaRoster::Disconnect: input.node.node %ld invalid\n", 108665b73ae4SMarcus Overhagen input.node.node); 108765b73ae4SMarcus Overhagen return B_MEDIA_BAD_DESTINATION; 108865b73ae4SMarcus Overhagen } 108965b73ae4SMarcus Overhagen if (!(output.node.kind & B_BUFFER_PRODUCER)) { 1090*34c72144SAxel Dörfler printf("BMediaRoster::Disconnect: output.node.kind 0x%lx is no " 1091*34c72144SAxel Dörfler "B_BUFFER_PRODUCER\n", output.node.kind); 109265b73ae4SMarcus Overhagen return B_MEDIA_BAD_SOURCE; 109365b73ae4SMarcus Overhagen } 109465b73ae4SMarcus Overhagen if (!(input.node.kind & B_BUFFER_CONSUMER)) { 1095*34c72144SAxel Dörfler printf("BMediaRoster::Disconnect: input.node.kind 0x%lx is no " 1096*34c72144SAxel Dörfler "B_BUFFER_PRODUCER\n", input.node.kind); 109765b73ae4SMarcus Overhagen return B_MEDIA_BAD_DESTINATION; 109865b73ae4SMarcus Overhagen } 109965b73ae4SMarcus Overhagen if (input.source.port != output.source.port) { 1100*34c72144SAxel Dörfler printf("BMediaRoster::Disconnect: input.source.port %ld doesn't match " 1101*34c72144SAxel Dörfler "output.source.port %ld\n", input.source.port, output.source.port); 110265b73ae4SMarcus Overhagen return B_MEDIA_BAD_SOURCE; 110365b73ae4SMarcus Overhagen } 110465b73ae4SMarcus Overhagen if (input.source.id != output.source.id) { 1105*34c72144SAxel Dörfler printf("BMediaRoster::Disconnect: input.source.id %ld doesn't match " 1106*34c72144SAxel Dörfler "output.source.id %ld\n", input.source.id, output.source.id); 110765b73ae4SMarcus Overhagen return B_MEDIA_BAD_SOURCE; 110865b73ae4SMarcus Overhagen } 110965b73ae4SMarcus Overhagen if (input.destination.port != output.destination.port) { 1110*34c72144SAxel Dörfler printf("BMediaRoster::Disconnect: input.destination.port %ld doesn't " 1111*34c72144SAxel Dörfler "match output.destination.port %ld\n", input.destination.port, 1112*34c72144SAxel Dörfler output.destination.port); 111365b73ae4SMarcus Overhagen return B_MEDIA_BAD_DESTINATION; 111465b73ae4SMarcus Overhagen } 111565b73ae4SMarcus Overhagen if (input.destination.id != output.destination.id) { 1116*34c72144SAxel Dörfler printf("BMediaRoster::Disconnect: input.destination.id %ld doesn't " 1117*34c72144SAxel Dörfler "match output.destination.id %ld\n", input.destination.id, 1118*34c72144SAxel Dörfler output.destination.id); 111965b73ae4SMarcus Overhagen return B_MEDIA_BAD_DESTINATION; 112065b73ae4SMarcus Overhagen } 1121*34c72144SAxel Dörfler 1122*34c72144SAxel Dörfler return Disconnect(output.node.node, output.source, input.node.node, 1123*34c72144SAxel Dörfler input.destination); 112465b73ae4SMarcus Overhagen } 112565b73ae4SMarcus Overhagen 112652a38012Sejakowatz 112752a38012Sejakowatz status_t 1128*34c72144SAxel Dörfler BMediaRoster::StartNode(const media_node& node, bigtime_t atPerformanceTime) 112952a38012Sejakowatz { 113052a38012Sejakowatz CALLED(); 11319e9417d2Sbeveloper if (node.node <= 0) 113252a38012Sejakowatz return B_MEDIA_BAD_NODE; 113352a38012Sejakowatz 1134*34c72144SAxel Dörfler TRACE("BMediaRoster::StartNode, node %ld, at perf %Ld\n", node.node, 1135*34c72144SAxel Dörfler atPerformanceTime); 11360e21b167Sbeveloper 11376396865dSbeveloper node_start_command command; 1138*34c72144SAxel Dörfler command.performance_time = atPerformanceTime; 113952a38012Sejakowatz 11406396865dSbeveloper return SendToPort(node.port, NODE_START, &command, sizeof(command)); 114152a38012Sejakowatz } 114252a38012Sejakowatz 114352a38012Sejakowatz 114452a38012Sejakowatz status_t 1145*34c72144SAxel Dörfler BMediaRoster::StopNode(const media_node& node, bigtime_t atPerformanceTime, 114652a38012Sejakowatz bool immediate) 114752a38012Sejakowatz { 114852a38012Sejakowatz CALLED(); 114940f36b03Sbeveloper if (IS_INVALID_NODE(node)) 115052a38012Sejakowatz return B_MEDIA_BAD_NODE; 115152a38012Sejakowatz 1152*34c72144SAxel Dörfler TRACE("BMediaRoster::StopNode, node %ld, at perf %Ld %s\n", node.node, 1153*34c72144SAxel Dörfler atPerformanceTime, immediate ? "NOW" : ""); 11540e21b167Sbeveloper 11556396865dSbeveloper node_stop_command command; 1156*34c72144SAxel Dörfler command.performance_time = atPerformanceTime; 11576396865dSbeveloper command.immediate = immediate; 115852a38012Sejakowatz 11596396865dSbeveloper return SendToPort(node.port, NODE_STOP, &command, sizeof(command)); 116052a38012Sejakowatz } 116152a38012Sejakowatz 116252a38012Sejakowatz 116352a38012Sejakowatz status_t 1164*34c72144SAxel Dörfler BMediaRoster::SeekNode(const media_node& node, bigtime_t toMediaTime, 1165*34c72144SAxel Dörfler bigtime_t atPerformanceTime) 116652a38012Sejakowatz { 116752a38012Sejakowatz CALLED(); 116840f36b03Sbeveloper if (IS_INVALID_NODE(node)) 116952a38012Sejakowatz return B_MEDIA_BAD_NODE; 117052a38012Sejakowatz 1171*34c72144SAxel Dörfler TRACE("BMediaRoster::SeekNode, node %ld, at perf %Ld, to perf %Ld\n", 1172*34c72144SAxel Dörfler node.node, atPerformanceTime, toMediaTime); 11730e21b167Sbeveloper 11746396865dSbeveloper node_seek_command command; 1175*34c72144SAxel Dörfler command.media_time = toMediaTime; 1176*34c72144SAxel Dörfler command.performance_time = atPerformanceTime; 117752a38012Sejakowatz 11786396865dSbeveloper return SendToPort(node.port, NODE_SEEK, &command, sizeof(command)); 117952a38012Sejakowatz } 118052a38012Sejakowatz 118152a38012Sejakowatz 118252a38012Sejakowatz status_t 1183*34c72144SAxel Dörfler BMediaRoster::StartTimeSource(const media_node& node, bigtime_t atRealTime) 118452a38012Sejakowatz { 118552a38012Sejakowatz CALLED(); 118660f15390Sbeveloper if (IS_SYSTEM_TIMESOURCE(node)) { 1187*34c72144SAxel Dörfler // TODO: debug this 11885ac4fbd7Sbeveloper //ERROR("BMediaRoster::StartTimeSource node %ld is system timesource\n", node.node); 118960f15390Sbeveloper return B_OK; 119060f15390Sbeveloper } 119192e575c1Sbeveloper // if (IS_SHADOW_TIMESOURCE(node)) { 1192*34c72144SAxel Dörfler // // TODO: debug this 119392e575c1Sbeveloper // ERROR("BMediaRoster::StartTimeSource node %ld is shadow timesource\n", node.node); 119492e575c1Sbeveloper // return B_OK; 119592e575c1Sbeveloper // } 119640f36b03Sbeveloper if (IS_INVALID_NODE(node)) { 11975ac4fbd7Sbeveloper ERROR("BMediaRoster::StartTimeSource node %ld invalid\n", node.node); 119852a38012Sejakowatz return B_MEDIA_BAD_NODE; 11990e21b167Sbeveloper } 12000e21b167Sbeveloper if ((node.kind & B_TIME_SOURCE) == 0) { 1201*34c72144SAxel Dörfler ERROR("BMediaRoster::StartTimeSource node %ld is no timesource\n", 1202*34c72144SAxel Dörfler node.node); 120352a38012Sejakowatz return B_MEDIA_BAD_NODE; 12040e21b167Sbeveloper } 12050e21b167Sbeveloper 1206*34c72144SAxel Dörfler TRACE("BMediaRoster::StartTimeSource, node %ld, at real %Ld\n", node.node, 1207*34c72144SAxel Dörfler at_real_time); 120852a38012Sejakowatz 120952a38012Sejakowatz BTimeSource::time_source_op_info msg; 121052a38012Sejakowatz msg.op = BTimeSource::B_TIMESOURCE_START; 1211*34c72144SAxel Dörfler msg.real_time = atRealTime; 121252a38012Sejakowatz 121352a38012Sejakowatz return write_port(node.port, TIMESOURCE_OP, &msg, sizeof(msg)); 121452a38012Sejakowatz } 121552a38012Sejakowatz 121652a38012Sejakowatz 121752a38012Sejakowatz status_t 1218*34c72144SAxel Dörfler BMediaRoster::StopTimeSource(const media_node& node, bigtime_t atRealTime, 121952a38012Sejakowatz bool immediate) 122052a38012Sejakowatz { 122152a38012Sejakowatz CALLED(); 122260f15390Sbeveloper if (IS_SYSTEM_TIMESOURCE(node)) { 1223*34c72144SAxel Dörfler // TODO: debug this 12245ac4fbd7Sbeveloper //ERROR("BMediaRoster::StopTimeSource node %ld is system timesource\n", node.node); 122560f15390Sbeveloper return B_OK; 122660f15390Sbeveloper } 122792e575c1Sbeveloper // if (IS_SHADOW_TIMESOURCE(node)) { 1228*34c72144SAxel Dörfler // // TODO: debug this 122992e575c1Sbeveloper // ERROR("BMediaRoster::StopTimeSource node %ld is shadow timesource\n", node.node); 123092e575c1Sbeveloper // return B_OK; 123192e575c1Sbeveloper // } 123240f36b03Sbeveloper if (IS_INVALID_NODE(node)) { 12335ac4fbd7Sbeveloper ERROR("BMediaRoster::StopTimeSource node %ld invalid\n", node.node); 123452a38012Sejakowatz return B_MEDIA_BAD_NODE; 12350e21b167Sbeveloper } 12360e21b167Sbeveloper if ((node.kind & B_TIME_SOURCE) == 0) { 1237*34c72144SAxel Dörfler ERROR("BMediaRoster::StopTimeSource node %ld is no timesource\n", 1238*34c72144SAxel Dörfler node.node); 123952a38012Sejakowatz return B_MEDIA_BAD_NODE; 12400e21b167Sbeveloper } 12410e21b167Sbeveloper 1242*34c72144SAxel Dörfler TRACE("BMediaRoster::StopTimeSource, node %ld, at real %Ld %s\n", 1243*34c72144SAxel Dörfler node.node, atRealTime, immediate ? "NOW" : ""); 124452a38012Sejakowatz 124552a38012Sejakowatz BTimeSource::time_source_op_info msg; 1246*34c72144SAxel Dörfler msg.op = immediate ? BTimeSource::B_TIMESOURCE_STOP_IMMEDIATELY 1247*34c72144SAxel Dörfler : BTimeSource::B_TIMESOURCE_STOP; 1248*34c72144SAxel Dörfler msg.real_time = atRealTime; 124952a38012Sejakowatz 125052a38012Sejakowatz return write_port(node.port, TIMESOURCE_OP, &msg, sizeof(msg)); 125152a38012Sejakowatz } 125252a38012Sejakowatz 125352a38012Sejakowatz 125452a38012Sejakowatz status_t 125552a38012Sejakowatz BMediaRoster::SeekTimeSource(const media_node& node, 1256*34c72144SAxel Dörfler bigtime_t toPerformanceTime, bigtime_t atRealTime) 125752a38012Sejakowatz { 125852a38012Sejakowatz CALLED(); 125960f15390Sbeveloper if (IS_SYSTEM_TIMESOURCE(node)) { 1260*34c72144SAxel Dörfler // TODO: debug this 12615ac4fbd7Sbeveloper // ERROR("BMediaRoster::SeekTimeSource node %ld is system timesource\n", node.node); 126260f15390Sbeveloper // you can't seek the system time source, but 126360f15390Sbeveloper // returning B_ERROR would break StampTV 126460f15390Sbeveloper return B_OK; 126560f15390Sbeveloper } 126692e575c1Sbeveloper // if (IS_SHADOW_TIMESOURCE(node)) { 1267*34c72144SAxel Dörfler // // TODO: debug this 126892e575c1Sbeveloper // ERROR("BMediaRoster::SeekTimeSource node %ld is shadow timesource\n", node.node); 126992e575c1Sbeveloper // return B_OK; 127092e575c1Sbeveloper // } 127140f36b03Sbeveloper if (IS_INVALID_NODE(node)) { 12725ac4fbd7Sbeveloper ERROR("BMediaRoster::SeekTimeSource node %ld invalid\n", node.node); 127352a38012Sejakowatz return B_MEDIA_BAD_NODE; 12740e21b167Sbeveloper } 12750e21b167Sbeveloper if ((node.kind & B_TIME_SOURCE) == 0) { 1276*34c72144SAxel Dörfler ERROR("BMediaRoster::SeekTimeSource node %ld is no timesource\n", 1277*34c72144SAxel Dörfler node.node); 127852a38012Sejakowatz return B_MEDIA_BAD_NODE; 12790e21b167Sbeveloper } 12800e21b167Sbeveloper 1281*34c72144SAxel Dörfler TRACE("BMediaRoster::SeekTimeSource, node %ld, at real %Ld, to perf %Ld\n", 1282*34c72144SAxel Dörfler node.node, atRealTime, toPerformanceTime); 128352a38012Sejakowatz 128452a38012Sejakowatz BTimeSource::time_source_op_info msg; 128552a38012Sejakowatz msg.op = BTimeSource::B_TIMESOURCE_SEEK; 1286*34c72144SAxel Dörfler msg.real_time = atRealTime; 1287*34c72144SAxel Dörfler msg.performance_time = toPerformanceTime; 128852a38012Sejakowatz 128952a38012Sejakowatz return write_port(node.port, TIMESOURCE_OP, &msg, sizeof(msg)); 129052a38012Sejakowatz } 129152a38012Sejakowatz 129252a38012Sejakowatz 129352a38012Sejakowatz status_t 1294*34c72144SAxel Dörfler BMediaRoster::SyncToNode(const media_node& node, bigtime_t atTime, 129552a38012Sejakowatz bigtime_t timeout) 129652a38012Sejakowatz { 129752a38012Sejakowatz UNIMPLEMENTED(); 129860f15390Sbeveloper return B_OK; 129952a38012Sejakowatz } 130052a38012Sejakowatz 130152a38012Sejakowatz 130252a38012Sejakowatz status_t 1303*34c72144SAxel Dörfler BMediaRoster::SetRunModeNode(const media_node& node, BMediaNode::run_mode mode) 130452a38012Sejakowatz { 130531cf24c1SMarcus Overhagen TRACE("BMediaRoster::SetRunModeNode, node %ld, mode %d\n", node.node, mode); 130640f36b03Sbeveloper if (IS_INVALID_NODE(node)) 130752a38012Sejakowatz return B_MEDIA_BAD_NODE; 130852a38012Sejakowatz 1309dfb2ad61Sbeveloper node_set_run_mode_command msg; 131052a38012Sejakowatz msg.mode = mode; 131152a38012Sejakowatz 131252a38012Sejakowatz return write_port(node.port, NODE_SET_RUN_MODE, &msg, sizeof(msg)); 131352a38012Sejakowatz } 131452a38012Sejakowatz 131552a38012Sejakowatz 131652a38012Sejakowatz status_t 131752a38012Sejakowatz BMediaRoster::PrerollNode(const media_node& node) 131852a38012Sejakowatz { 131952a38012Sejakowatz CALLED(); 132040f36b03Sbeveloper if (IS_INVALID_NODE(node)) 132152a38012Sejakowatz return B_MEDIA_BAD_NODE; 132252a38012Sejakowatz 132352a38012Sejakowatz char dummy; 132452a38012Sejakowatz return write_port(node.port, NODE_PREROLL, &dummy, sizeof(dummy)); 132552a38012Sejakowatz } 132652a38012Sejakowatz 132752a38012Sejakowatz 132852a38012Sejakowatz status_t 1329*34c72144SAxel Dörfler BMediaRoster::RollNode(const media_node& node, bigtime_t startPerformance, 1330*34c72144SAxel Dörfler bigtime_t stopPerformance, bigtime_t atMediaTime) 133152a38012Sejakowatz { 133252a38012Sejakowatz UNIMPLEMENTED(); 133352a38012Sejakowatz return B_ERROR; 133452a38012Sejakowatz } 133552a38012Sejakowatz 133652a38012Sejakowatz 133752a38012Sejakowatz status_t 133852a38012Sejakowatz BMediaRoster::SetProducerRunModeDelay(const media_node& node, 1339*34c72144SAxel Dörfler bigtime_t delay, BMediaNode::run_mode mode) 134052a38012Sejakowatz { 1341*34c72144SAxel Dörfler TRACE("BMediaRoster::SetProducerRunModeDelay, node %ld, delay %Ld, " 1342*34c72144SAxel Dörfler "mode %d\n", node.node, delay, mode); 134360f15390Sbeveloper if (IS_INVALID_NODE(node)) 134460f15390Sbeveloper return B_MEDIA_BAD_NODE; 134560f15390Sbeveloper if ((node.kind & B_BUFFER_PRODUCER) == 0) 134660f15390Sbeveloper return B_MEDIA_BAD_NODE; 134760f15390Sbeveloper 134860f15390Sbeveloper producer_set_run_mode_delay_command command; 134960f15390Sbeveloper command.mode = mode; 135060f15390Sbeveloper command.delay = delay; 135160f15390Sbeveloper 1352*34c72144SAxel Dörfler return SendToPort(node.port, PRODUCER_SET_RUN_MODE_DELAY, &command, 1353*34c72144SAxel Dörfler sizeof(command)); 135452a38012Sejakowatz } 135552a38012Sejakowatz 135652a38012Sejakowatz 135752a38012Sejakowatz status_t 1358*34c72144SAxel Dörfler BMediaRoster::SetProducerRate(const media_node& producer, int32 numer, 135952a38012Sejakowatz int32 denom) 136052a38012Sejakowatz { 136152a38012Sejakowatz CALLED(); 136240f36b03Sbeveloper if (IS_INVALID_NODE(producer)) 136352a38012Sejakowatz return B_MEDIA_BAD_NODE; 136452a38012Sejakowatz if ((producer.kind & B_BUFFER_PRODUCER) == 0) 136552a38012Sejakowatz return B_MEDIA_BAD_NODE; 136652a38012Sejakowatz 1367dfb2ad61Sbeveloper producer_set_play_rate_request msg; 1368dfb2ad61Sbeveloper producer_set_play_rate_reply reply; 136952a38012Sejakowatz status_t rv; 137052a38012Sejakowatz int32 code; 137152a38012Sejakowatz 137252a38012Sejakowatz msg.numer = numer; 137352a38012Sejakowatz msg.denom = denom; 137452a38012Sejakowatz msg.reply_port = _PortPool->GetPort(); 137552a38012Sejakowatz rv = write_port(producer.node, PRODUCER_SET_PLAY_RATE, &msg, sizeof(msg)); 137652a38012Sejakowatz if (rv != B_OK) { 137752a38012Sejakowatz _PortPool->PutPort(msg.reply_port); 137852a38012Sejakowatz return rv; 137952a38012Sejakowatz } 138052a38012Sejakowatz rv = read_port(msg.reply_port, &code, &reply, sizeof(reply)); 138152a38012Sejakowatz _PortPool->PutPort(msg.reply_port); 138252a38012Sejakowatz return (rv < B_OK) ? rv : reply.result; 138352a38012Sejakowatz } 138452a38012Sejakowatz 138552a38012Sejakowatz 1386*34c72144SAxel Dörfler /*! Nodes will have available inputs/outputs as long as they are capable 1387*34c72144SAxel Dörfler of accepting more connections. The node may create an additional 1388*34c72144SAxel Dörfler output or input as the currently available is taken into usage. 1389*34c72144SAxel Dörfler */ 139052a38012Sejakowatz status_t 139152a38012Sejakowatz BMediaRoster::GetLiveNodeInfo(const media_node& node, 139252a38012Sejakowatz live_node_info* out_live_info) 139352a38012Sejakowatz { 13949e9417d2Sbeveloper CALLED(); 13959e9417d2Sbeveloper if (out_live_info == NULL) 13969e9417d2Sbeveloper return B_BAD_VALUE; 139740f36b03Sbeveloper if (IS_INVALID_NODE(node)) 13989e9417d2Sbeveloper return B_MEDIA_BAD_NODE; 13999e9417d2Sbeveloper 14009e9417d2Sbeveloper server_get_live_node_info_request request; 14019e9417d2Sbeveloper server_get_live_node_info_reply reply; 14029e9417d2Sbeveloper status_t rv; 14039e9417d2Sbeveloper 14049e9417d2Sbeveloper request.node = node; 14059e9417d2Sbeveloper 1406*34c72144SAxel Dörfler rv = QueryServer(SERVER_GET_LIVE_NODE_INFO, &request, sizeof(request), 1407*34c72144SAxel Dörfler &reply, sizeof(reply)); 14089e9417d2Sbeveloper if (rv != B_OK) 14099e9417d2Sbeveloper return rv; 14109e9417d2Sbeveloper 14119e9417d2Sbeveloper *out_live_info = reply.live_info; 14129e9417d2Sbeveloper return B_OK; 141352a38012Sejakowatz } 141452a38012Sejakowatz 141552a38012Sejakowatz 141652a38012Sejakowatz status_t 1417*34c72144SAxel Dörfler BMediaRoster::GetLiveNodes(live_node_info* _liveNodes, int32* _totalCount, 1418*34c72144SAxel Dörfler const media_format* hasInput, const media_format* hasOutput, 1419*34c72144SAxel Dörfler const char* name, uint64 nodeKinds) 142052a38012Sejakowatz { 14219e9417d2Sbeveloper CALLED(); 1422*34c72144SAxel Dörfler if (_liveNodes == NULL || _totalCount == NULL || *_totalCount <= 0) 14239e9417d2Sbeveloper return B_BAD_VALUE; 14249e9417d2Sbeveloper 1425*34c72144SAxel Dörfler // TODO: we also support the wildcard search as GetDormantNodes does. 1426*34c72144SAxel Dörfler // This needs to be documented 14279e9417d2Sbeveloper 14289e9417d2Sbeveloper server_get_live_nodes_request request; 14299e9417d2Sbeveloper server_get_live_nodes_reply reply; 14309e9417d2Sbeveloper status_t rv; 14319e9417d2Sbeveloper 1432*34c72144SAxel Dörfler request.maxcount = *_totalCount; 1433*34c72144SAxel Dörfler request.has_input = hasInput != NULL; 1434*34c72144SAxel Dörfler if (hasInput != NULL) { 1435*34c72144SAxel Dörfler // TODO: we should not make a flat copy of media_format 1436*34c72144SAxel Dörfler request.inputformat = *hasInput; 1437*34c72144SAxel Dörfler } 1438*34c72144SAxel Dörfler request.has_output = hasOutput != NULL; 1439*34c72144SAxel Dörfler if (hasOutput != NULL) { 1440*34c72144SAxel Dörfler // TODO: we should not make a flat copy of media_format 1441*34c72144SAxel Dörfler request.outputformat = *hasOutput; 1442*34c72144SAxel Dörfler } 1443*34c72144SAxel Dörfler request.has_name = name != NULL; 1444*34c72144SAxel Dörfler if (name != NULL) { 14459e9417d2Sbeveloper int len = strlen(name); 14469e9417d2Sbeveloper len = min_c(len, (int)sizeof(request.name) - 1); 14479e9417d2Sbeveloper memcpy(request.name, name, len); 14489e9417d2Sbeveloper request.name[len] = 0; 14499e9417d2Sbeveloper } 1450*34c72144SAxel Dörfler request.require_kinds = nodeKinds; 14519e9417d2Sbeveloper 1452*34c72144SAxel Dörfler rv = QueryServer(SERVER_GET_LIVE_NODES, &request, sizeof(request), 1453*34c72144SAxel Dörfler &reply, sizeof(reply)); 14549e9417d2Sbeveloper if (rv != B_OK) { 14555ac4fbd7Sbeveloper ERROR("BMediaRoster::GetLiveNodes failed querying server\n"); 1456*34c72144SAxel Dörfler *_totalCount = 0; 14579e9417d2Sbeveloper return rv; 14589e9417d2Sbeveloper } 14599e9417d2Sbeveloper 14609e9417d2Sbeveloper if (reply.count > MAX_LIVE_INFO) { 1461*34c72144SAxel Dörfler live_node_info* liveInfo; 14629e9417d2Sbeveloper area_id clone; 14639e9417d2Sbeveloper 1464*34c72144SAxel Dörfler clone = clone_area("live_node_info clone", 1465*34c72144SAxel Dörfler reinterpret_cast<void **>(&liveInfo), B_ANY_ADDRESS, 1466*34c72144SAxel Dörfler B_READ_AREA | B_WRITE_AREA, reply.area); 14679e9417d2Sbeveloper if (clone < B_OK) { 1468*34c72144SAxel Dörfler ERROR("BMediaRoster::GetLiveNodes failed to clone area, %#lx\n", 1469*34c72144SAxel Dörfler clone); 14709e9417d2Sbeveloper delete_area(reply.area); 1471*34c72144SAxel Dörfler *_totalCount = 0; 147252a38012Sejakowatz return B_ERROR; 147352a38012Sejakowatz } 147452a38012Sejakowatz 14759e9417d2Sbeveloper for (int32 i = 0; i < reply.count; i++) { 1476*34c72144SAxel Dörfler _liveNodes[i] = liveInfo[i]; 14779e9417d2Sbeveloper } 14789e9417d2Sbeveloper 14799e9417d2Sbeveloper delete_area(clone); 14809e9417d2Sbeveloper delete_area(reply.area); 14819e9417d2Sbeveloper } else { 14829e9417d2Sbeveloper for (int32 i = 0; i < reply.count; i++) { 1483*34c72144SAxel Dörfler _liveNodes[i] = reply.live_info[i]; 14849e9417d2Sbeveloper } 14859e9417d2Sbeveloper } 1486*34c72144SAxel Dörfler *_totalCount = reply.count; 14879e9417d2Sbeveloper 14889e9417d2Sbeveloper return B_OK; 14899e9417d2Sbeveloper } 14909e9417d2Sbeveloper 149152a38012Sejakowatz 149252a38012Sejakowatz status_t 149352a38012Sejakowatz BMediaRoster::GetFreeInputsFor(const media_node& node, 1494*34c72144SAxel Dörfler media_input * out_free_inputs, int32 buf_num_inputs, 1495*34c72144SAxel Dörfler int32 * out_total_count, media_type filter_type) 149652a38012Sejakowatz { 14973620737cSbeveloper CALLED(); 14985ac4fbd7Sbeveloper if (IS_INVALID_NODE(node)) { 1499*34c72144SAxel Dörfler ERROR("BMediaRoster::GetFreeInputsFor: node %ld, port %ld invalid\n", 1500*34c72144SAxel Dörfler node.node, node.port); 15013620737cSbeveloper return B_MEDIA_BAD_NODE; 15025ac4fbd7Sbeveloper } 15035ac4fbd7Sbeveloper if ((node.kind & B_BUFFER_CONSUMER) == 0) { 1504*34c72144SAxel Dörfler ERROR("BMediaRoster::GetFreeInputsFor: node %ld, port %ld is not a " 1505*34c72144SAxel Dörfler "consumer\n", node.node, node.port); 15065ac4fbd7Sbeveloper return B_MEDIA_BAD_NODE; 15075ac4fbd7Sbeveloper } 15083620737cSbeveloper if (out_free_inputs == NULL || out_total_count == NULL) 15093620737cSbeveloper return B_BAD_VALUE; 15103620737cSbeveloper 151176669a29Sbeveloper List<media_input> list; 15123620737cSbeveloper media_input *input; 15133620737cSbeveloper status_t rv; 15143620737cSbeveloper 15151299bfb2Sbeveloper *out_total_count = 0; 15161299bfb2Sbeveloper 15178b04ffc1Sbeveloper rv = MediaRosterEx(this)->GetAllInputs(node, &list); 15183620737cSbeveloper if (B_OK != rv) 15193620737cSbeveloper return rv; 15203620737cSbeveloper 1521*34c72144SAxel Dörfler PRINT(4, "BMediaRoster::GetFreeInputsFor node %ld, max %ld, filter-type " 1522*34c72144SAxel Dörfler "%ld\n", node.node, buf_num_inputs, filter_type); 15235ac4fbd7Sbeveloper 152476669a29Sbeveloper int32 i; 1525b65a0ac5SJérôme Duval for (i = 0, list.Rewind(); list.GetNext(&input);) { 1526*34c72144SAxel Dörfler if (filter_type != B_MEDIA_UNKNOWN_TYPE 1527*34c72144SAxel Dörfler && filter_type != input->format.type) { 1528*34c72144SAxel Dörfler // media_type used, but doesn't match 1529*34c72144SAxel Dörfler continue; 1530*34c72144SAxel Dörfler } 1531*34c72144SAxel Dörfler if (input->source != media_source::null) { 1532*34c72144SAxel Dörfler // consumer source already connected 1533*34c72144SAxel Dörfler continue; 1534*34c72144SAxel Dörfler } 1535*34c72144SAxel Dörfler 15363620737cSbeveloper out_free_inputs[i] = *input; 15373620737cSbeveloper *out_total_count += 1; 15383620737cSbeveloper buf_num_inputs -= 1; 15395ac4fbd7Sbeveloper #if DEBUG >= 3 15405ac4fbd7Sbeveloper PRINT_OUTPUT(" input", out_free_inputs[i]); 15415ac4fbd7Sbeveloper #endif 15423620737cSbeveloper if (buf_num_inputs == 0) 15433620737cSbeveloper break; 1544b65a0ac5SJérôme Duval i++; 15453620737cSbeveloper } 15463620737cSbeveloper 15478b04ffc1Sbeveloper MediaRosterEx(this)->PublishInputs(node, &list); 15483620737cSbeveloper return B_OK; 154952a38012Sejakowatz } 155052a38012Sejakowatz 155152a38012Sejakowatz 155252a38012Sejakowatz status_t 155352a38012Sejakowatz BMediaRoster::GetConnectedInputsFor(const media_node& node, 1554*34c72144SAxel Dörfler media_input* out_active_inputs, int32 buf_num_inputs, 155552a38012Sejakowatz int32* out_total_count) 155652a38012Sejakowatz { 15573620737cSbeveloper CALLED(); 155840f36b03Sbeveloper if (IS_INVALID_NODE(node) || (node.kind & B_BUFFER_CONSUMER) == 0) 15593620737cSbeveloper return B_MEDIA_BAD_NODE; 15603620737cSbeveloper if (out_active_inputs == NULL || out_total_count == NULL) 15613620737cSbeveloper return B_BAD_VALUE; 15623620737cSbeveloper 156376669a29Sbeveloper List<media_input> list; 15643620737cSbeveloper media_input *input; 15653620737cSbeveloper status_t rv; 15663620737cSbeveloper 15671299bfb2Sbeveloper *out_total_count = 0; 15681299bfb2Sbeveloper 15698b04ffc1Sbeveloper rv = MediaRosterEx(this)->GetAllInputs(node, &list); 15703620737cSbeveloper if (B_OK != rv) 15713620737cSbeveloper return rv; 15723620737cSbeveloper 1573*34c72144SAxel Dörfler PRINT(4, "BMediaRoster::GetConnectedInputsFor node %ld, max %ld\n", 1574*34c72144SAxel Dörfler node.node, buf_num_inputs); 15755ac4fbd7Sbeveloper 157676669a29Sbeveloper int32 i; 1577b65a0ac5SJérôme Duval for (i = 0, list.Rewind(); list.GetNext(&input);) { 15783620737cSbeveloper if (input->source == media_source::null) 15793620737cSbeveloper continue; // consumer source not connected 15803620737cSbeveloper out_active_inputs[i] = *input; 15813620737cSbeveloper *out_total_count += 1; 15823620737cSbeveloper buf_num_inputs -= 1; 15835ac4fbd7Sbeveloper #if DEBUG >= 3 15845ac4fbd7Sbeveloper PRINT_OUTPUT(" input ", out_active_inputs[i]); 15855ac4fbd7Sbeveloper #endif 15863620737cSbeveloper if (buf_num_inputs == 0) 15873620737cSbeveloper break; 1588b65a0ac5SJérôme Duval i++; 15893620737cSbeveloper } 15903620737cSbeveloper 15918b04ffc1Sbeveloper MediaRosterEx(this)->PublishInputs(node, &list); 15923620737cSbeveloper return B_OK; 159352a38012Sejakowatz } 159452a38012Sejakowatz 159552a38012Sejakowatz 159652a38012Sejakowatz status_t 1597*34c72144SAxel Dörfler BMediaRoster::GetAllInputsFor(const media_node& node, media_input* out_inputs, 1598*34c72144SAxel Dörfler int32 buf_num_inputs, int32* out_total_count) 159952a38012Sejakowatz { 160052a38012Sejakowatz CALLED(); 160140f36b03Sbeveloper if (IS_INVALID_NODE(node) || (node.kind & B_BUFFER_CONSUMER) == 0) 160252a38012Sejakowatz return B_MEDIA_BAD_NODE; 160352a38012Sejakowatz if (out_inputs == NULL || out_total_count == NULL) 160452a38012Sejakowatz return B_BAD_VALUE; 160552a38012Sejakowatz 160676669a29Sbeveloper List<media_input> list; 16073620737cSbeveloper media_input *input; 160852a38012Sejakowatz status_t rv; 160952a38012Sejakowatz 16101299bfb2Sbeveloper *out_total_count = 0; 16111299bfb2Sbeveloper 16128b04ffc1Sbeveloper rv = MediaRosterEx(this)->GetAllInputs(node, &list); 16133620737cSbeveloper if (B_OK != rv) 16143620737cSbeveloper return rv; 16153620737cSbeveloper 1616*34c72144SAxel Dörfler PRINT(4, "BMediaRoster::GetAllInputsFor node %ld, max %ld\n", node.node, 1617*34c72144SAxel Dörfler buf_num_inputs); 16185ac4fbd7Sbeveloper 161976669a29Sbeveloper int32 i; 162076669a29Sbeveloper for (i = 0, list.Rewind(); list.GetNext(&input); i++) { 16213620737cSbeveloper out_inputs[i] = *input; 162252a38012Sejakowatz *out_total_count += 1; 16233620737cSbeveloper buf_num_inputs -= 1; 16245ac4fbd7Sbeveloper #if DEBUG >= 3 16255ac4fbd7Sbeveloper PRINT_OUTPUT(" input ", out_inputs[i]); 16265ac4fbd7Sbeveloper #endif 16273620737cSbeveloper if (buf_num_inputs == 0) 16283620737cSbeveloper break; 162952a38012Sejakowatz } 163052a38012Sejakowatz 16318b04ffc1Sbeveloper MediaRosterEx(this)->PublishInputs(node, &list); 16323620737cSbeveloper return B_OK; 163352a38012Sejakowatz } 163452a38012Sejakowatz 163552a38012Sejakowatz 163652a38012Sejakowatz status_t 163752a38012Sejakowatz BMediaRoster::GetFreeOutputsFor(const media_node& node, 1638*34c72144SAxel Dörfler media_output* out_free_outputs, int32 buf_num_outputs, 1639*34c72144SAxel Dörfler int32* out_total_count, media_type filter_type) 164052a38012Sejakowatz { 16413620737cSbeveloper CALLED(); 164240f36b03Sbeveloper if (IS_INVALID_NODE(node) || (node.kind & B_BUFFER_PRODUCER) == 0) 16433620737cSbeveloper return B_MEDIA_BAD_NODE; 16443620737cSbeveloper if (out_free_outputs == NULL || out_total_count == NULL) 16453620737cSbeveloper return B_BAD_VALUE; 16463620737cSbeveloper 164776669a29Sbeveloper List<media_output> list; 16483620737cSbeveloper media_output *output; 16493620737cSbeveloper status_t rv; 16503620737cSbeveloper 16511299bfb2Sbeveloper *out_total_count = 0; 16521299bfb2Sbeveloper 16538b04ffc1Sbeveloper rv = MediaRosterEx(this)->GetAllOutputs(node, &list); 16543620737cSbeveloper if (B_OK != rv) 16553620737cSbeveloper return rv; 16563620737cSbeveloper 1657*34c72144SAxel Dörfler PRINT(4, "BMediaRoster::GetFreeOutputsFor node %ld, max %ld, filter-type " 1658*34c72144SAxel Dörfler "%ld\n", node.node, buf_num_outputs, filter_type); 16595ac4fbd7Sbeveloper 166076669a29Sbeveloper int32 i; 1661b65a0ac5SJérôme Duval for (i = 0, list.Rewind(); list.GetNext(&output);) { 1662*34c72144SAxel Dörfler if (filter_type != B_MEDIA_UNKNOWN_TYPE 1663*34c72144SAxel Dörfler && filter_type != output->format.type) { 1664*34c72144SAxel Dörfler // media_type used, but doesn't match 1665*34c72144SAxel Dörfler continue; 1666*34c72144SAxel Dörfler } 1667*34c72144SAxel Dörfler if (output->destination != media_destination::null) { 1668*34c72144SAxel Dörfler // producer destination already connected 1669*34c72144SAxel Dörfler continue; 1670*34c72144SAxel Dörfler } 1671*34c72144SAxel Dörfler 16723620737cSbeveloper out_free_outputs[i] = *output; 16733620737cSbeveloper *out_total_count += 1; 16743620737cSbeveloper buf_num_outputs -= 1; 16755ac4fbd7Sbeveloper #if DEBUG >= 3 16765ac4fbd7Sbeveloper PRINT_OUTPUT(" output ", out_free_outputs[i]); 16775ac4fbd7Sbeveloper #endif 16783620737cSbeveloper if (buf_num_outputs == 0) 16793620737cSbeveloper break; 1680b65a0ac5SJérôme Duval i++; 16813620737cSbeveloper } 16823620737cSbeveloper 16838b04ffc1Sbeveloper MediaRosterEx(this)->PublishOutputs(node, &list); 16843620737cSbeveloper return B_OK; 168552a38012Sejakowatz } 168652a38012Sejakowatz 168752a38012Sejakowatz 168852a38012Sejakowatz status_t 168952a38012Sejakowatz BMediaRoster::GetConnectedOutputsFor(const media_node& node, 1690*34c72144SAxel Dörfler media_output* out_active_outputs, int32 buf_num_outputs, 169152a38012Sejakowatz int32* out_total_count) 169252a38012Sejakowatz { 16933620737cSbeveloper CALLED(); 169440f36b03Sbeveloper if (IS_INVALID_NODE(node) || (node.kind & B_BUFFER_PRODUCER) == 0) 16953620737cSbeveloper return B_MEDIA_BAD_NODE; 16963620737cSbeveloper if (out_active_outputs == NULL || out_total_count == NULL) 16973620737cSbeveloper return B_BAD_VALUE; 16983620737cSbeveloper 169976669a29Sbeveloper List<media_output> list; 17003620737cSbeveloper media_output *output; 17013620737cSbeveloper status_t rv; 17023620737cSbeveloper 17031299bfb2Sbeveloper *out_total_count = 0; 17041299bfb2Sbeveloper 17058b04ffc1Sbeveloper rv = MediaRosterEx(this)->GetAllOutputs(node, &list); 17063620737cSbeveloper if (B_OK != rv) 17073620737cSbeveloper return rv; 17083620737cSbeveloper 1709*34c72144SAxel Dörfler PRINT(4, "BMediaRoster::GetConnectedOutputsFor node %ld, max %ld\n", 1710*34c72144SAxel Dörfler node.node, buf_num_outputs); 17115ac4fbd7Sbeveloper 171276669a29Sbeveloper int32 i; 1713b65a0ac5SJérôme Duval for (i = 0, list.Rewind(); list.GetNext(&output);) { 1714*34c72144SAxel Dörfler if (output->destination == media_destination::null) { 1715*34c72144SAxel Dörfler // producer destination not connected 1716*34c72144SAxel Dörfler continue; 1717*34c72144SAxel Dörfler } 17183620737cSbeveloper out_active_outputs[i] = *output; 17193620737cSbeveloper *out_total_count += 1; 17203620737cSbeveloper buf_num_outputs -= 1; 17215ac4fbd7Sbeveloper #if DEBUG >= 3 17225ac4fbd7Sbeveloper PRINT_OUTPUT(" output ", out_active_outputs[i]); 17235ac4fbd7Sbeveloper #endif 17243620737cSbeveloper if (buf_num_outputs == 0) 17253620737cSbeveloper break; 1726b65a0ac5SJérôme Duval i++; 17273620737cSbeveloper } 17283620737cSbeveloper 17298b04ffc1Sbeveloper MediaRosterEx(this)->PublishOutputs(node, &list); 17303620737cSbeveloper return B_OK; 173152a38012Sejakowatz } 173252a38012Sejakowatz 173352a38012Sejakowatz 173452a38012Sejakowatz status_t 173552a38012Sejakowatz BMediaRoster::GetAllOutputsFor(const media_node& node, 1736*34c72144SAxel Dörfler media_output* out_outputs, int32 buf_num_outputs, int32* out_total_count) 173752a38012Sejakowatz { 173852a38012Sejakowatz CALLED(); 173940f36b03Sbeveloper if (IS_INVALID_NODE(node) || (node.kind & B_BUFFER_PRODUCER) == 0) 174052a38012Sejakowatz return B_MEDIA_BAD_NODE; 174152a38012Sejakowatz if (out_outputs == NULL || out_total_count == NULL) 174252a38012Sejakowatz return B_BAD_VALUE; 174352a38012Sejakowatz 174476669a29Sbeveloper List<media_output> list; 17453620737cSbeveloper media_output *output; 174652a38012Sejakowatz status_t rv; 174752a38012Sejakowatz 17481299bfb2Sbeveloper *out_total_count = 0; 17491299bfb2Sbeveloper 17508b04ffc1Sbeveloper rv = MediaRosterEx(this)->GetAllOutputs(node, &list); 17513620737cSbeveloper if (B_OK != rv) 17523620737cSbeveloper return rv; 17533620737cSbeveloper 1754*34c72144SAxel Dörfler PRINT(4, "BMediaRoster::GetAllOutputsFor node %ld, max %ld\n", node.node, 1755*34c72144SAxel Dörfler buf_num_outputs); 17565ac4fbd7Sbeveloper 175776669a29Sbeveloper int32 i; 175876669a29Sbeveloper for (i = 0, list.Rewind(); list.GetNext(&output); i++) { 17593620737cSbeveloper out_outputs[i] = *output; 176052a38012Sejakowatz *out_total_count += 1; 17613620737cSbeveloper buf_num_outputs -= 1; 17625ac4fbd7Sbeveloper #if DEBUG >= 3 17635ac4fbd7Sbeveloper PRINT_OUTPUT(" output ", out_outputs[i]); 17645ac4fbd7Sbeveloper #endif 17653620737cSbeveloper if (buf_num_outputs == 0) 17663620737cSbeveloper break; 176752a38012Sejakowatz } 176852a38012Sejakowatz 17698b04ffc1Sbeveloper MediaRosterEx(this)->PublishOutputs(node, &list); 17703620737cSbeveloper return B_OK; 177152a38012Sejakowatz } 177252a38012Sejakowatz 177352a38012Sejakowatz 177452a38012Sejakowatz status_t 177552a38012Sejakowatz BMediaRoster::StartWatching(const BMessenger& where) 177652a38012Sejakowatz { 1777eae26d3dSbeveloper CALLED(); 1778eae26d3dSbeveloper if (!where.IsValid()) { 17795ac4fbd7Sbeveloper ERROR("BMediaRoster::StartWatching: messenger invalid!\n"); 1780eae26d3dSbeveloper return B_BAD_VALUE; 1781eae26d3dSbeveloper } 1782*34c72144SAxel Dörfler return BPrivate::media::notifications::Register(where, media_node::null, 1783*34c72144SAxel Dörfler B_MEDIA_WILDCARD); 178452a38012Sejakowatz } 178552a38012Sejakowatz 178652a38012Sejakowatz 178752a38012Sejakowatz status_t 1788*34c72144SAxel Dörfler BMediaRoster::StartWatching(const BMessenger & where, int32 notificationType) 178952a38012Sejakowatz { 1790eae26d3dSbeveloper CALLED(); 1791eae26d3dSbeveloper if (!where.IsValid()) { 17925ac4fbd7Sbeveloper ERROR("BMediaRoster::StartWatching: messenger invalid!\n"); 1793eae26d3dSbeveloper return B_BAD_VALUE; 1794eae26d3dSbeveloper } 1795*34c72144SAxel Dörfler if (!BPrivate::media::notifications::IsValidNotificationRequest(false, 1796*34c72144SAxel Dörfler notificationType)) { 17975ac4fbd7Sbeveloper ERROR("BMediaRoster::StartWatching: notificationType invalid!\n"); 1798eae26d3dSbeveloper return B_BAD_VALUE; 1799eae26d3dSbeveloper } 1800*34c72144SAxel Dörfler return BPrivate::media::notifications::Register(where, media_node::null, 1801*34c72144SAxel Dörfler notificationType); 180252a38012Sejakowatz } 180352a38012Sejakowatz 180452a38012Sejakowatz 180552a38012Sejakowatz status_t 1806*34c72144SAxel Dörfler BMediaRoster::StartWatching(const BMessenger& where, const media_node& node, 180752a38012Sejakowatz int32 notificationType) 180852a38012Sejakowatz { 1809eae26d3dSbeveloper CALLED(); 1810eae26d3dSbeveloper if (!where.IsValid()) { 18115ac4fbd7Sbeveloper ERROR("BMediaRoster::StartWatching: messenger invalid!\n"); 1812eae26d3dSbeveloper return B_BAD_VALUE; 1813eae26d3dSbeveloper } 181440f36b03Sbeveloper if (IS_INVALID_NODE(node)) { 18155ac4fbd7Sbeveloper ERROR("BMediaRoster::StartWatching: node invalid!\n"); 1816eae26d3dSbeveloper return B_MEDIA_BAD_NODE; 1817eae26d3dSbeveloper } 1818*34c72144SAxel Dörfler if (!BPrivate::media::notifications::IsValidNotificationRequest(true, 1819*34c72144SAxel Dörfler notificationType)) { 18205ac4fbd7Sbeveloper ERROR("BMediaRoster::StartWatching: notificationType invalid!\n"); 1821eae26d3dSbeveloper return B_BAD_VALUE; 1822eae26d3dSbeveloper } 1823*34c72144SAxel Dörfler return BPrivate::media::notifications::Register(where, node, 1824*34c72144SAxel Dörfler notificationType); 182552a38012Sejakowatz } 182652a38012Sejakowatz 182752a38012Sejakowatz 182852a38012Sejakowatz status_t 182952a38012Sejakowatz BMediaRoster::StopWatching(const BMessenger& where) 183052a38012Sejakowatz { 1831eae26d3dSbeveloper CALLED(); 1832eae26d3dSbeveloper // messenger may already be invalid, so we don't check this 1833*34c72144SAxel Dörfler return BPrivate::media::notifications::Unregister(where, media_node::null, 1834*34c72144SAxel Dörfler B_MEDIA_WILDCARD); 183552a38012Sejakowatz } 183652a38012Sejakowatz 183752a38012Sejakowatz 183852a38012Sejakowatz status_t 1839*34c72144SAxel Dörfler BMediaRoster::StopWatching(const BMessenger& where, int32 notificationType) 184052a38012Sejakowatz { 1841eae26d3dSbeveloper CALLED(); 1842eae26d3dSbeveloper // messenger may already be invalid, so we don't check this 1843*34c72144SAxel Dörfler if (!BPrivate::media::notifications::IsValidNotificationRequest(false, 1844*34c72144SAxel Dörfler notificationType)) { 18455ac4fbd7Sbeveloper ERROR("BMediaRoster::StopWatching: notificationType invalid!\n"); 1846eae26d3dSbeveloper return B_BAD_VALUE; 1847eae26d3dSbeveloper } 1848*34c72144SAxel Dörfler return BPrivate::media::notifications::Unregister(where, media_node::null, 1849*34c72144SAxel Dörfler notificationType); 185052a38012Sejakowatz } 185152a38012Sejakowatz 185252a38012Sejakowatz 185352a38012Sejakowatz status_t 1854*34c72144SAxel Dörfler BMediaRoster::StopWatching(const BMessenger& where, const media_node& node, 185552a38012Sejakowatz int32 notificationType) 185652a38012Sejakowatz { 1857eae26d3dSbeveloper CALLED(); 1858eae26d3dSbeveloper // messenger may already be invalid, so we don't check this 185940f36b03Sbeveloper if (IS_INVALID_NODE(node)) { 18605ac4fbd7Sbeveloper ERROR("BMediaRoster::StopWatching: node invalid!\n"); 1861eae26d3dSbeveloper return B_MEDIA_BAD_NODE; 1862eae26d3dSbeveloper } 1863*34c72144SAxel Dörfler if (!BPrivate::media::notifications::IsValidNotificationRequest(true, 1864*34c72144SAxel Dörfler notificationType)) { 18655ac4fbd7Sbeveloper ERROR("BMediaRoster::StopWatching: notificationType invalid!\n"); 1866eae26d3dSbeveloper return B_BAD_VALUE; 1867eae26d3dSbeveloper } 1868*34c72144SAxel Dörfler return BPrivate::media::notifications::Unregister(where, node, 1869*34c72144SAxel Dörfler notificationType); 187052a38012Sejakowatz } 187152a38012Sejakowatz 187252a38012Sejakowatz 187352a38012Sejakowatz status_t 187452a38012Sejakowatz BMediaRoster::RegisterNode(BMediaNode* node) 187552a38012Sejakowatz { 187654187cc6Sbeveloper CALLED(); 187754187cc6Sbeveloper // addon-id = -1 (unused), addon-flavor-id = 0 (unused, too) 187854187cc6Sbeveloper return MediaRosterEx(this)->RegisterNode(node, -1, 0); 187954187cc6Sbeveloper } 188054187cc6Sbeveloper 188154187cc6Sbeveloper 188254187cc6Sbeveloper status_t 1883*34c72144SAxel Dörfler BMediaRosterEx::RegisterNode(BMediaNode* node, media_addon_id addonid, 1884*34c72144SAxel Dörfler int32 flavorid) 188554187cc6Sbeveloper { 188652a38012Sejakowatz CALLED(); 188752a38012Sejakowatz if (node == NULL) 188852a38012Sejakowatz return B_BAD_VALUE; 188952a38012Sejakowatz 189054187cc6Sbeveloper // some sanity check 189154187cc6Sbeveloper // I'm not sure if the media kit warrants to call BMediaNode::AddOn() here. 189254187cc6Sbeveloper // Perhaps we don't need it. 189354187cc6Sbeveloper { 18949e9417d2Sbeveloper BMediaAddOn *addon; 18959e9417d2Sbeveloper int32 addon_flavor_id; 18969e9417d2Sbeveloper media_addon_id addon_id; 18979e9417d2Sbeveloper addon_flavor_id = 0; 18989e9417d2Sbeveloper addon = node->AddOn(&addon_flavor_id); 18999e9417d2Sbeveloper addon_id = addon ? addon->AddonID() : -1; 190054187cc6Sbeveloper ASSERT(addonid == addon_id); 190154187cc6Sbeveloper ASSERT(flavorid == addon_flavor_id); 190254187cc6Sbeveloper } 190352a38012Sejakowatz 190454187cc6Sbeveloper status_t rv; 19059e9417d2Sbeveloper server_register_node_request request; 19069e9417d2Sbeveloper server_register_node_reply reply; 19079e9417d2Sbeveloper 190854187cc6Sbeveloper request.addon_id = addonid; 190954187cc6Sbeveloper request.addon_flavor_id = flavorid; 19109e9417d2Sbeveloper strcpy(request.name, node->Name()); 19119e9417d2Sbeveloper request.kinds = node->Kinds(); 19129e9417d2Sbeveloper request.port = node->ControlPort(); 19139e9417d2Sbeveloper request.team = team; 19149e9417d2Sbeveloper 1915*34c72144SAxel Dörfler TRACE("BMediaRoster::RegisterNode: sending SERVER_REGISTER_NODE: port " 1916*34c72144SAxel Dörfler "%ld, kinds 0x%Lx, team %ld, name '%s'\n", request.port, request.kinds, 1917*34c72144SAxel Dörfler request.team, request.name); 19181299bfb2Sbeveloper 1919*34c72144SAxel Dörfler rv = QueryServer(SERVER_REGISTER_NODE, &request, sizeof(request), &reply, 1920*34c72144SAxel Dörfler sizeof(reply)); 19219e9417d2Sbeveloper if (rv != B_OK) { 1922*34c72144SAxel Dörfler ERROR("BMediaRoster::RegisterNode: failed to register node %s (error " 1923*34c72144SAxel Dörfler "%#lx)\n", node->Name(), rv); 19249e9417d2Sbeveloper return rv; 19259e9417d2Sbeveloper } 19269e9417d2Sbeveloper 1927*34c72144SAxel Dörfler TRACE("BMediaRoster::RegisterNode: QueryServer SERVER_REGISTER_NODE " 1928*34c72144SAxel Dörfler "finished\n"); 19294295907bSbeveloper 19308b04ffc1Sbeveloper // we are a friend class of BMediaNode and initialize this member variable 19319e9417d2Sbeveloper node->fNodeID = reply.nodeid; 19329e9417d2Sbeveloper ASSERT(reply.nodeid == node->Node().node); 19339e9417d2Sbeveloper ASSERT(reply.nodeid == node->ID()); 19349e9417d2Sbeveloper 19359e9417d2Sbeveloper // call the callback 19369e9417d2Sbeveloper node->NodeRegistered(); 19373620737cSbeveloper 19384295907bSbeveloper TRACE("BMediaRoster::RegisterNode: NodeRegistered callback finished\n"); 19394295907bSbeveloper 1940*34c72144SAxel Dörfler // if the BMediaNode also inherits from BTimeSource, we need to call 1941*34c72144SAxel Dörfler // BTimeSource::FinishCreate() 19420e21b167Sbeveloper if (node->Kinds() & B_TIME_SOURCE) { 19430e21b167Sbeveloper BTimeSource *ts; 19440e21b167Sbeveloper ts = dynamic_cast<BTimeSource *>(node); 19450e21b167Sbeveloper if (ts) 19460e21b167Sbeveloper ts->FinishCreate(); 19470e21b167Sbeveloper } 19480e21b167Sbeveloper 19494295907bSbeveloper TRACE("BMediaRoster::RegisterNode: publishing inputs/outputs\n"); 19504295907bSbeveloper 19513620737cSbeveloper // register existing inputs and outputs with the 19523620737cSbeveloper // media_server, this allows GetLiveNodes() to work 19533620737cSbeveloper // with created, but unconnected nodes. 19544d2d96e0Sbeveloper // The node control loop might not be running, or might deadlock 19554d2d96e0Sbeveloper // if we send a message and wait for a reply here. 19564d2d96e0Sbeveloper // We have a pointer to the node, and thus call the functions directly 19574295907bSbeveloper 19583620737cSbeveloper if (node->Kinds() & B_BUFFER_PRODUCER) { 19594d2d96e0Sbeveloper BBufferProducer *bp; 19604d2d96e0Sbeveloper bp = dynamic_cast<BBufferProducer *>(node); 19614d2d96e0Sbeveloper if (bp) { 1962359ac306Sbeveloper List<media_output> list; 19634d2d96e0Sbeveloper if (B_OK == GetAllOutputs(bp, &list)) 1964359ac306Sbeveloper PublishOutputs(node->Node(), &list); 196521871f38Sbeveloper } 19664d2d96e0Sbeveloper } 196721871f38Sbeveloper if (node->Kinds() & B_BUFFER_CONSUMER) { 19684d2d96e0Sbeveloper BBufferConsumer *bc; 19694d2d96e0Sbeveloper bc = dynamic_cast<BBufferConsumer *>(node); 19704d2d96e0Sbeveloper if (bc) { 1971359ac306Sbeveloper List<media_input> list; 19724d2d96e0Sbeveloper if (B_OK == GetAllInputs(bc, &list)) 1973359ac306Sbeveloper PublishInputs(node->Node(), &list); 19743620737cSbeveloper } 19754d2d96e0Sbeveloper } 197621871f38Sbeveloper 19774295907bSbeveloper TRACE("BMediaRoster::RegisterNode: sending NodesCreated\n"); 19784295907bSbeveloper 19791299bfb2Sbeveloper BPrivate::media::notifications::NodesCreated(&reply.nodeid, 1); 19804295907bSbeveloper 19814295907bSbeveloper TRACE("BMediaRoster::RegisterNode: finished\n"); 19824295907bSbeveloper 1983570f7d04Sbeveloper /* 1984570f7d04Sbeveloper TRACE("BMediaRoster::RegisterNode: registered node name '%s', id %ld, addon %ld, flavor %ld\n", node->Name(), node->ID(), addon_id, addon_flavor_id); 1985570f7d04Sbeveloper TRACE("BMediaRoster::RegisterNode: node this %p\n", node); 1986570f7d04Sbeveloper TRACE("BMediaRoster::RegisterNode: node fConsumerThis %p\n", node->fConsumerThis); 1987570f7d04Sbeveloper TRACE("BMediaRoster::RegisterNode: node fProducerThis %p\n", node->fProducerThis); 1988570f7d04Sbeveloper TRACE("BMediaRoster::RegisterNode: node fFileInterfaceThis %p\n", node->fFileInterfaceThis); 1989570f7d04Sbeveloper TRACE("BMediaRoster::RegisterNode: node fControllableThis %p\n", node->fControllableThis); 1990570f7d04Sbeveloper TRACE("BMediaRoster::RegisterNode: node fTimeSourceThis %p\n", node->fTimeSourceThis); 1991570f7d04Sbeveloper */ 19929e9417d2Sbeveloper return B_OK; 199352a38012Sejakowatz } 199452a38012Sejakowatz 199552a38012Sejakowatz 199652a38012Sejakowatz status_t 199752a38012Sejakowatz BMediaRoster::UnregisterNode(BMediaNode* node) 199852a38012Sejakowatz { 19999e9417d2Sbeveloper CALLED(); 20009e9417d2Sbeveloper if (node == NULL) 20019e9417d2Sbeveloper return B_BAD_VALUE; 20029e9417d2Sbeveloper 200360f15390Sbeveloper TRACE("BMediaRoster::UnregisterNode %ld (%p)\n", node->ID(), node); 200460f15390Sbeveloper 200586bce45bSbeveloper if (node->fKinds & NODE_KIND_NO_REFCOUNTING) { 2006*34c72144SAxel Dörfler TRACE("BMediaRoster::UnregisterNode, trying to unregister reference " 2007*34c72144SAxel Dörfler "counting disabled timesource, node %ld, port %ld, team %ld\n", 2008*34c72144SAxel Dörfler node->ID(), node->ControlPort(), team); 200986bce45bSbeveloper return B_OK; 201086bce45bSbeveloper } 20118b04ffc1Sbeveloper if (node->ID() == NODE_UNREGISTERED_ID) { 2012*34c72144SAxel Dörfler PRINT(1, "Warning: BMediaRoster::UnregisterNode: node id %ld, name " 2013*34c72144SAxel Dörfler "'%s' already unregistered\n", node->ID(), node->Name()); 20149e9417d2Sbeveloper return B_OK; 20159e9417d2Sbeveloper } 201654187cc6Sbeveloper if (node->fRefCount != 0) { 2017*34c72144SAxel Dörfler PRINT(1, "Warning: BMediaRoster::UnregisterNode: node id %ld, name " 2018*34c72144SAxel Dörfler "'%s' has local reference count of %ld\n", node->ID(), node->Name(), 2019*34c72144SAxel Dörfler node->fRefCount); 202054187cc6Sbeveloper // no return here, we continue and unregister! 202154187cc6Sbeveloper } 202254187cc6Sbeveloper 2023*34c72144SAxel Dörfler // Calling BMediaAddOn::GetConfigurationFor(BMediaNode *node, 2024*34c72144SAxel Dörfler // BMessage *config) if this node was instanciated by an add-on needs to 2025*34c72144SAxel Dörfler // be done *somewhere* 202654187cc6Sbeveloper // We can't do it here because it is already to late (destructor of the node 202754187cc6Sbeveloper // might have been called). 20289e9417d2Sbeveloper 20299e9417d2Sbeveloper server_unregister_node_request request; 20309e9417d2Sbeveloper server_unregister_node_reply reply; 20319e9417d2Sbeveloper status_t rv; 20329e9417d2Sbeveloper 20339e9417d2Sbeveloper request.nodeid = node->ID(); 20349e9417d2Sbeveloper request.team = team; 20359e9417d2Sbeveloper 20361299bfb2Sbeveloper // send a notification 20371299bfb2Sbeveloper BPrivate::media::notifications::NodesDeleted(&request.nodeid, 1); 20381299bfb2Sbeveloper 2039*34c72144SAxel Dörfler rv = QueryServer(SERVER_UNREGISTER_NODE, &request, sizeof(request), &reply, 2040*34c72144SAxel Dörfler sizeof(reply)); 20419e9417d2Sbeveloper if (rv != B_OK) { 2042*34c72144SAxel Dörfler ERROR("BMediaRoster::UnregisterNode: failed to unregister node id %ld, " 2043*34c72144SAxel Dörfler "name '%s' (error %#lx)\n", node->ID(), node->Name(), rv); 20449e9417d2Sbeveloper return rv; 20459e9417d2Sbeveloper } 20469e9417d2Sbeveloper 204754187cc6Sbeveloper if (reply.addonid != -1) { 204854187cc6Sbeveloper // Small problem here, we can't use DormantNodeManager::PutAddon(), as 2049*34c72144SAxel Dörfler // UnregisterNode() is called by a dormant node itself (by the 2050*34c72144SAxel Dörfler // destructor). 205154187cc6Sbeveloper // The add-on that contains the node needs to remain in memory until the 205254187cc6Sbeveloper // destructor execution is finished. 205354187cc6Sbeveloper // DormantNodeManager::PutAddonDelayed() will delay unloading. 205454187cc6Sbeveloper _DormantNodeManager->PutAddonDelayed(reply.addonid); 2055cf4e2277Sbeveloper 2056*34c72144SAxel Dörfler rv = MediaRosterEx(this)->DecrementAddonFlavorInstancesCount( 2057*34c72144SAxel Dörfler reply.addonid, reply.flavorid); 205854187cc6Sbeveloper if (rv != B_OK) { 2059*34c72144SAxel Dörfler ERROR("BMediaRoster::UnregisterNode: " 2060*34c72144SAxel Dörfler "DecrementAddonFlavorInstancesCount() failed\n"); 206154187cc6Sbeveloper // this is really a problem, but we can't fail now 206254187cc6Sbeveloper } 20638b04ffc1Sbeveloper } 20649e9417d2Sbeveloper 20651299bfb2Sbeveloper // we are a friend class of BMediaNode and invalidate this member variable 20668b04ffc1Sbeveloper node->fNodeID = NODE_UNREGISTERED_ID; 20679e9417d2Sbeveloper 20689e9417d2Sbeveloper return B_OK; 206952a38012Sejakowatz } 207052a38012Sejakowatz 207152a38012Sejakowatz 2072*34c72144SAxel Dörfler //! Thread safe for multiple calls to Roster() 207352a38012Sejakowatz /*static*/ BMediaRoster* 207452a38012Sejakowatz BMediaRoster::Roster(status_t* out_error) 207552a38012Sejakowatz { 207652a38012Sejakowatz static BLocker locker("BMediaRoster::Roster locker"); 207752a38012Sejakowatz locker.Lock(); 20788496c38aSbeveloper if (out_error) 20798496c38aSbeveloper *out_error = B_OK; 20809def3bf7SStephan Aßmus if (sDefaultInstance == NULL) { 20818496c38aSbeveloper status_t err; 20829def3bf7SStephan Aßmus sDefaultInstance = new (std::nothrow) BMediaRosterEx(&err); 20839def3bf7SStephan Aßmus if (sDefaultInstance == NULL) 2084a715f908SStephan Aßmus err = B_NO_MEMORY; 2085a715f908SStephan Aßmus else if (err != B_OK) { 20869def3bf7SStephan Aßmus if (sDefaultInstance) { 20879def3bf7SStephan Aßmus sDefaultInstance->Lock(); 20889def3bf7SStephan Aßmus sDefaultInstance->Quit(); 20899def3bf7SStephan Aßmus sDefaultInstance = NULL; 2090dcfb6bfcSJérôme Duval } 20918496c38aSbeveloper if (out_error) 20928496c38aSbeveloper *out_error = err; 20938496c38aSbeveloper } 209452a38012Sejakowatz } 209552a38012Sejakowatz locker.Unlock(); 20969def3bf7SStephan Aßmus return sDefaultInstance; 209752a38012Sejakowatz } 209852a38012Sejakowatz 209952a38012Sejakowatz 210052a38012Sejakowatz /*static*/ BMediaRoster* 210152a38012Sejakowatz BMediaRoster::CurrentRoster() 210252a38012Sejakowatz { 21039def3bf7SStephan Aßmus return sDefaultInstance; 210452a38012Sejakowatz } 210552a38012Sejakowatz 210652a38012Sejakowatz 210752a38012Sejakowatz status_t 2108*34c72144SAxel Dörfler BMediaRoster::SetTimeSourceFor(media_node_id node, media_node_id time_source) 210952a38012Sejakowatz { 2110aac800c2Sbeveloper CALLED(); 211140f36b03Sbeveloper if (IS_INVALID_NODEID(node) || IS_INVALID_NODEID(time_source)) 2112aac800c2Sbeveloper return B_BAD_VALUE; 2113aac800c2Sbeveloper 2114aac800c2Sbeveloper media_node clone; 2115aac800c2Sbeveloper status_t rv, result; 2116aac800c2Sbeveloper 2117*34c72144SAxel Dörfler TRACE("BMediaRoster::SetTimeSourceFor: node %ld will be assigned time " 2118*34c72144SAxel Dörfler "source %ld\n", node, time_source); 2119*34c72144SAxel Dörfler TRACE("BMediaRoster::SetTimeSourceFor: node %ld time source %ld enter\n", 2120*34c72144SAxel Dörfler node, time_source); 21215917dd5bSbeveloper 212286bce45bSbeveloper // we need to get a clone of the node to have a port id 2123aac800c2Sbeveloper rv = GetNodeFor(node, &clone); 2124aac800c2Sbeveloper if (rv != B_OK) { 2125*34c72144SAxel Dörfler ERROR("BMediaRoster::SetTimeSourceFor, GetNodeFor failed, node id " 2126*34c72144SAxel Dörfler "%ld\n", node); 212752a38012Sejakowatz return B_ERROR; 212852a38012Sejakowatz } 212952a38012Sejakowatz 213086bce45bSbeveloper // we just send the request to set time_source-id as timesource to the node, 213186bce45bSbeveloper // the NODE_SET_TIMESOURCE handler code will do the real assignment 2132aac800c2Sbeveloper result = B_OK; 2133aac800c2Sbeveloper node_set_timesource_command cmd; 2134aac800c2Sbeveloper cmd.timesource_id = time_source; 2135aac800c2Sbeveloper rv = SendToPort(clone.port, NODE_SET_TIMESOURCE, &cmd, sizeof(cmd)); 2136aac800c2Sbeveloper if (rv != B_OK) { 2137*34c72144SAxel Dörfler ERROR("BMediaRoster::SetTimeSourceFor, sending NODE_SET_TIMESOURCE " 2138*34c72144SAxel Dörfler "failed, node id %ld\n", node); 2139aac800c2Sbeveloper result = B_ERROR; 2140aac800c2Sbeveloper } 2141aac800c2Sbeveloper 214260f15390Sbeveloper // we release the clone 2143aac800c2Sbeveloper rv = ReleaseNode(clone); 2144aac800c2Sbeveloper if (rv != B_OK) { 2145*34c72144SAxel Dörfler ERROR("BMediaRoster::SetTimeSourceFor, ReleaseNode failed, node id " 2146*34c72144SAxel Dörfler "%ld\n", node); 2147aac800c2Sbeveloper result = B_ERROR; 2148aac800c2Sbeveloper } 2149aac800c2Sbeveloper 2150*34c72144SAxel Dörfler TRACE("BMediaRoster::SetTimeSourceFor: node %ld time source %ld leave\n", 2151*34c72144SAxel Dörfler node, time_source); 21525917dd5bSbeveloper 2153aac800c2Sbeveloper return result; 2154aac800c2Sbeveloper } 2155aac800c2Sbeveloper 215652a38012Sejakowatz 215752a38012Sejakowatz status_t 2158*34c72144SAxel Dörfler BMediaRoster::GetParameterWebFor(const media_node& node, BParameterWeb** _web) 215952a38012Sejakowatz { 216028ad138aSbeveloper CALLED(); 2161*34c72144SAxel Dörfler if (_web == NULL) 216228ad138aSbeveloper return B_BAD_VALUE; 216328ad138aSbeveloper if (IS_INVALID_NODE(node)) 216428ad138aSbeveloper return B_MEDIA_BAD_NODE; 216528ad138aSbeveloper if ((node.kind & B_CONTROLLABLE) == 0) 216628ad138aSbeveloper return B_MEDIA_BAD_NODE; 216728ad138aSbeveloper 216828ad138aSbeveloper controllable_get_parameter_web_request request; 216928ad138aSbeveloper controllable_get_parameter_web_reply reply; 2170*34c72144SAxel Dörfler int32 requestsize[] = {B_PAGE_SIZE, 4 * B_PAGE_SIZE, 16 * B_PAGE_SIZE, 2171*34c72144SAxel Dörfler 64 * B_PAGE_SIZE, 128 * B_PAGE_SIZE, 256 * B_PAGE_SIZE, 0}; 217228ad138aSbeveloper int32 size; 217328ad138aSbeveloper 2174*34c72144SAxel Dörfler // TODO: it might be better to query the node for the (current) parameter 2175*34c72144SAxel Dörfler // size first 217628ad138aSbeveloper for (int i = 0; (size = requestsize[i]) != 0; i++) { 217728ad138aSbeveloper status_t rv; 217828ad138aSbeveloper area_id area; 217928ad138aSbeveloper void *data; 2180*34c72144SAxel Dörfler area = create_area("parameter web data", &data, B_ANY_ADDRESS, size, 2181*34c72144SAxel Dörfler B_NO_LOCK, B_READ_AREA | B_WRITE_AREA); 218228ad138aSbeveloper if (area < B_OK) { 2183*34c72144SAxel Dörfler ERROR("BMediaRoster::GetParameterWebFor couldn't create area of " 2184*34c72144SAxel Dörfler "size %ld\n", size); 218528ad138aSbeveloper return B_ERROR; 218628ad138aSbeveloper } 2187*34c72144SAxel Dörfler request.max_size = size; 218828ad138aSbeveloper request.area = area; 2189*34c72144SAxel Dörfler rv = QueryPort(node.port, CONTROLLABLE_GET_PARAMETER_WEB, &request, 2190*34c72144SAxel Dörfler sizeof(request), &reply, sizeof(reply)); 219128ad138aSbeveloper if (rv != B_OK) { 2192*34c72144SAxel Dörfler ERROR("BMediaRoster::GetParameterWebFor " 2193*34c72144SAxel Dörfler "CONTROLLABLE_GET_PARAMETER_WEB failed\n"); 219428ad138aSbeveloper delete_area(area); 219528ad138aSbeveloper return B_ERROR; 219628ad138aSbeveloper } 219728ad138aSbeveloper if (reply.size == 0) { 219828ad138aSbeveloper // no parameter web available 2199*34c72144SAxel Dörfler // TODO: should we return an error? 2200*34c72144SAxel Dörfler ERROR("BMediaRoster::GetParameterWebFor node %ld has no parameter " 2201*34c72144SAxel Dörfler "web\n", node.node); 2202*34c72144SAxel Dörfler *_web = new (std::nothrow) BParameterWeb(); 220328ad138aSbeveloper delete_area(area); 2204*34c72144SAxel Dörfler return *_web != NULL ? B_OK : B_NO_MEMORY; 220552a38012Sejakowatz } 220628ad138aSbeveloper if (reply.size > 0) { 220728ad138aSbeveloper // we got a flattened parameter web! 2208*34c72144SAxel Dörfler *_web = new (std::nothrow) BParameterWeb(); 2209*34c72144SAxel Dörfler if (*_web == NULL) 2210a715f908SStephan Aßmus rv = B_NO_MEMORY; 2211a715f908SStephan Aßmus else { 2212*34c72144SAxel Dörfler printf("BMediaRoster::GetParameterWebFor Unflattening %ld " 2213*34c72144SAxel Dörfler "bytes, 0x%08lx, 0x%08lx, 0x%08lx, 0x%08lx\n", 2214*34c72144SAxel Dörfler reply.size, ((uint32*)data)[0], ((uint32*)data)[1], 2215*34c72144SAxel Dörfler ((uint32*)data)[2], ((uint32*)data)[3]); 221628ad138aSbeveloper 2217*34c72144SAxel Dörfler rv = (*_web)->Unflatten(reply.code, data, reply.size); 2218a715f908SStephan Aßmus } 221928ad138aSbeveloper if (rv != B_OK) { 2220*34c72144SAxel Dörfler ERROR("BMediaRoster::GetParameterWebFor Unflatten failed, " 2221*34c72144SAxel Dörfler "%s\n", strerror(rv)); 2222*34c72144SAxel Dörfler delete *_web; 222328ad138aSbeveloper } 222428ad138aSbeveloper delete_area(area); 2225a715f908SStephan Aßmus return rv; 222628ad138aSbeveloper } 222728ad138aSbeveloper delete_area(area); 222828ad138aSbeveloper ASSERT(reply.size == -1); 222928ad138aSbeveloper // parameter web data was too large 223028ad138aSbeveloper // loop and try a larger size 223128ad138aSbeveloper } 2232*34c72144SAxel Dörfler ERROR("BMediaRoster::GetParameterWebFor node %ld has no parameter web " 2233*34c72144SAxel Dörfler "larger than %ld\n", node.node, size); 223428ad138aSbeveloper return B_ERROR; 223528ad138aSbeveloper } 223652a38012Sejakowatz 223752a38012Sejakowatz 223852a38012Sejakowatz status_t 2239*34c72144SAxel Dörfler BMediaRoster::StartControlPanel(const media_node& node, BMessenger* _messenger) 224052a38012Sejakowatz { 2241999cd0acSMaurice Kalinowski CALLED(); 2242999cd0acSMaurice Kalinowski 2243999cd0acSMaurice Kalinowski controllable_start_control_panel_request request; 2244999cd0acSMaurice Kalinowski controllable_start_control_panel_reply reply; 2245999cd0acSMaurice Kalinowski 2246999cd0acSMaurice Kalinowski request.node = node; 2247999cd0acSMaurice Kalinowski 2248999cd0acSMaurice Kalinowski status_t rv; 2249*34c72144SAxel Dörfler rv = QueryPort(node.port, CONTROLLABLE_START_CONTROL_PANEL, &request, 2250*34c72144SAxel Dörfler sizeof(request), &reply, sizeof(reply)); 2251999cd0acSMaurice Kalinowski if (rv != B_OK) 2252999cd0acSMaurice Kalinowski return rv; 2253999cd0acSMaurice Kalinowski 2254*34c72144SAxel Dörfler if (reply.team != -1 && _messenger != NULL) 2255*34c72144SAxel Dörfler *_messenger = BMessenger(NULL, reply.team); 2256999cd0acSMaurice Kalinowski 2257999cd0acSMaurice Kalinowski return B_OK; 225852a38012Sejakowatz } 225952a38012Sejakowatz 226052a38012Sejakowatz 226152a38012Sejakowatz status_t 2262*34c72144SAxel Dörfler BMediaRoster::GetDormantNodes(dormant_node_info* _info, int32* _count, 2263*34c72144SAxel Dörfler const media_format* hasInput, const media_format* hasOutput, 2264*34c72144SAxel Dörfler const char* name, uint64 requireKinds, uint64 denyKinds) 226552a38012Sejakowatz { 226652a38012Sejakowatz CALLED(); 2267*34c72144SAxel Dörfler if (_info == NULL || _count == NULL || *_count <= 0) 226852a38012Sejakowatz return B_BAD_VALUE; 226952a38012Sejakowatz 227052a38012Sejakowatz xfer_server_get_dormant_nodes msg; 227152a38012Sejakowatz port_id port; 227252a38012Sejakowatz status_t rv; 227352a38012Sejakowatz 22744295907bSbeveloper port = find_port(MEDIA_SERVER_PORT_NAME); 227552a38012Sejakowatz if (port <= B_OK) 227652a38012Sejakowatz return B_ERROR; 227752a38012Sejakowatz 2278*34c72144SAxel Dörfler msg.maxcount = *_count; 2279*34c72144SAxel Dörfler msg.has_input = hasInput != NULL; 2280*34c72144SAxel Dörfler if (hasInput != NULL) { 2281*34c72144SAxel Dörfler // TODO: we should not make a flat copy of media_format 2282*34c72144SAxel Dörfler msg.inputformat = *hasInput; 2283*34c72144SAxel Dörfler } 2284*34c72144SAxel Dörfler msg.has_output = hasOutput != NULL; 2285*34c72144SAxel Dörfler if (hasOutput != NULL) { 2286*34c72144SAxel Dörfler // TODO: we should not make a flat copy of media_format 2287*34c72144SAxel Dörfler msg.outputformat = *hasOutput; 2288*34c72144SAxel Dörfler } 2289*34c72144SAxel Dörfler 2290*34c72144SAxel Dörfler msg.has_name = name != NULL; 2291*34c72144SAxel Dörfler if (name != NULL) { 22929e9417d2Sbeveloper int len = strlen(name); 22939e9417d2Sbeveloper len = min_c(len, (int)sizeof(msg.name) - 1); 229452a38012Sejakowatz memcpy(msg.name, name, len); 229552a38012Sejakowatz msg.name[len] = 0; 229652a38012Sejakowatz } 2297*34c72144SAxel Dörfler msg.require_kinds = requireKinds; 2298*34c72144SAxel Dörfler msg.deny_kinds = denyKinds; 229952a38012Sejakowatz msg.reply_port = _PortPool->GetPort(); 230052a38012Sejakowatz 230152a38012Sejakowatz rv = write_port(port, SERVER_GET_DORMANT_NODES, &msg, sizeof(msg)); 230252a38012Sejakowatz if (rv != B_OK) { 230352a38012Sejakowatz _PortPool->PutPort(msg.reply_port); 230452a38012Sejakowatz return rv; 230552a38012Sejakowatz } 230652a38012Sejakowatz 230752a38012Sejakowatz xfer_server_get_dormant_nodes_reply reply; 230852a38012Sejakowatz int32 code; 230952a38012Sejakowatz 231052a38012Sejakowatz rv = read_port(msg.reply_port, &code, &reply, sizeof(reply)); 231152a38012Sejakowatz if (rv < B_OK) { 231252a38012Sejakowatz _PortPool->PutPort(msg.reply_port); 231352a38012Sejakowatz return rv; 231452a38012Sejakowatz } 231552a38012Sejakowatz 2316*34c72144SAxel Dörfler *_count = reply.count; 231752a38012Sejakowatz 2318*34c72144SAxel Dörfler if (*_count > 0) { 2319*34c72144SAxel Dörfler rv = read_port(msg.reply_port, &code, _info, 2320*34c72144SAxel Dörfler *_count * sizeof(dormant_node_info)); 232152a38012Sejakowatz if (rv < B_OK) 232252a38012Sejakowatz reply.result = rv; 232352a38012Sejakowatz } 232452a38012Sejakowatz _PortPool->PutPort(msg.reply_port); 232552a38012Sejakowatz 232652a38012Sejakowatz return reply.result; 232752a38012Sejakowatz } 232852a38012Sejakowatz 2329*34c72144SAxel Dörfler /*! This function is used to do the real work of instantiating a dormant node. 2330*34c72144SAxel Dörfler It is either called by the media_addon_server to instantiate a global node, 2331*34c72144SAxel Dörfler or it gets called from BMediaRoster::InstantiateDormantNode() to create a 2332*34c72144SAxel Dörfler local one. 2333*34c72144SAxel Dörfler 2334*34c72144SAxel Dörfler Checks concerning global/local are not done here. 23358b04ffc1Sbeveloper */ 233652a38012Sejakowatz status_t 2337*34c72144SAxel Dörfler BMediaRosterEx::InstantiateDormantNode(media_addon_id addonID, int32 flavorID, 2338*34c72144SAxel Dörfler team_id creator, media_node *_node) 233952a38012Sejakowatz { 234054187cc6Sbeveloper // This function is always called from the correct context, if the node 234154187cc6Sbeveloper // is supposed to be global, it is called from the media_addon_server. 234254187cc6Sbeveloper 234352a38012Sejakowatz // if B_FLAVOR_IS_GLOBAL, we need to use the BMediaAddOn object that 234452a38012Sejakowatz // resides in the media_addon_server 234552a38012Sejakowatz 23468b04ffc1Sbeveloper // RegisterNode() must be called for nodes instantiated from add-ons, 23478b04ffc1Sbeveloper // since the media kit warrants that it's done automatically. 234852a38012Sejakowatz 2349*34c72144SAxel Dörfler // addonID Indicates the ID number of the media add-on in which the 2350*34c72144SAxel Dörfler // node resides. 2351*34c72144SAxel Dörfler // flavorID Indicates the internal ID number that the add-on uses to 2352*34c72144SAxel Dörfler // identify the flavor, this is the number that was published 2353*34c72144SAxel Dörfler // by BMediaAddOn::GetFlavorAt() in the 23548b04ffc1Sbeveloper // flavor_info::internal_id field. 2355*34c72144SAxel Dörfler // creator The creator team is -1 if nodes are created locally. If 2356*34c72144SAxel Dörfler // created globally, it will contain (while called in 2357*34c72144SAxel Dörfler // media_addon_server context) the team-id of the team that 2358*34c72144SAxel Dörfler // requested the instantiation. 23598b04ffc1Sbeveloper 2360*34c72144SAxel Dörfler TRACE("BMediaRosterEx::InstantiateDormantNode: addonID %ld, flavorID " 2361*34c72144SAxel Dörfler "%ld\n", addonID, flavorID); 23628b04ffc1Sbeveloper 23638b04ffc1Sbeveloper // Get flavor_info from the server 2364*34c72144SAxel Dörfler dormant_flavor_info info; 23658c6a6096Sbeveloper status_t rv; 2366*34c72144SAxel Dörfler rv = GetDormantFlavorInfo(addonID, flavorID, &info); 23678b04ffc1Sbeveloper if (rv != B_OK) { 2368*34c72144SAxel Dörfler ERROR("BMediaRosterEx::InstantiateDormantNode error: failed to get " 2369*34c72144SAxel Dörfler "dormant_flavor_info for addon-id %ld, flavor-id %ld\n", addonID, 2370*34c72144SAxel Dörfler flavorID); 237152a38012Sejakowatz return B_ERROR; 237252a38012Sejakowatz } 23738b04ffc1Sbeveloper 2374*34c72144SAxel Dörfler ASSERT(node_info.internal_id == flavorID); 23758b04ffc1Sbeveloper 23768b04ffc1Sbeveloper // load the BMediaAddOn object 23778b04ffc1Sbeveloper BMediaAddOn* addon; 2378*34c72144SAxel Dörfler addon = _DormantNodeManager->GetAddon(addonID); 2379*34c72144SAxel Dörfler if (addon == NULL) { 23805ac4fbd7Sbeveloper ERROR("BMediaRosterEx::InstantiateDormantNode: GetAddon failed\n"); 23818b04ffc1Sbeveloper return B_ERROR; 23828b04ffc1Sbeveloper } 23838b04ffc1Sbeveloper 238454187cc6Sbeveloper // Now we need to try to increment the use count of this addon flavor 238554187cc6Sbeveloper // in the server. This can fail if the total number instances of this 238654187cc6Sbeveloper // flavor is limited. 2387*34c72144SAxel Dörfler rv = IncrementAddonFlavorInstancesCount(addonID, flavorID); 238854187cc6Sbeveloper if (rv != B_OK) { 2389*34c72144SAxel Dörfler ERROR("BMediaRosterEx::InstantiateDormantNode error: can't create " 2390*34c72144SAxel Dörfler "more nodes for addon-id %ld, flavor-id %ld\n", addonID, flavorID); 239154187cc6Sbeveloper // Put the addon back into the pool 2392*34c72144SAxel Dörfler _DormantNodeManager->PutAddon(addonID); 239354187cc6Sbeveloper return B_ERROR; 239454187cc6Sbeveloper } 239554187cc6Sbeveloper 23968b04ffc1Sbeveloper BMessage config; 2397*34c72144SAxel Dörfler rv = LoadNodeConfiguration(addonID, flavorID, &config); 239854187cc6Sbeveloper if (rv != B_OK) { 2399*34c72144SAxel Dörfler ERROR("BMediaRosterEx::InstantiateDormantNode: couldn't load " 2400*34c72144SAxel Dörfler "configuration for addon-id %ld, flavor-id %ld\n", addonID, 2401*34c72144SAxel Dörfler flavorID); 240254187cc6Sbeveloper // do not return, this is a minor problem, not a reason to fail 240354187cc6Sbeveloper } 24048b04ffc1Sbeveloper 2405*34c72144SAxel Dörfler status_t status = B_OK; 2406*34c72144SAxel Dörfler BMediaNode* node = addon->InstantiateNodeFor(&info, &config, &status); 2407*34c72144SAxel Dörfler if (node == NULL) { 2408*34c72144SAxel Dörfler ERROR("BMediaRosterEx::InstantiateDormantNode: InstantiateNodeFor " 2409*34c72144SAxel Dörfler "failed\n"); 24108b04ffc1Sbeveloper 241154187cc6Sbeveloper // Put the addon back into the pool 2412*34c72144SAxel Dörfler _DormantNodeManager->PutAddon(addonID); 2413*34c72144SAxel Dörfler 241454187cc6Sbeveloper // We must decrement the use count of this addon flavor in the 241554187cc6Sbeveloper // server to compensate the increment done in the beginning. 2416*34c72144SAxel Dörfler rv = DecrementAddonFlavorInstancesCount(addonID, flavorID); 241754187cc6Sbeveloper if (rv != B_OK) { 2418*34c72144SAxel Dörfler ERROR("BMediaRosterEx::InstantiateDormantNode: DecrementAddon" 2419*34c72144SAxel Dörfler "FlavorInstancesCount failed\n"); 242016b7eea4Sbeveloper } 2421*34c72144SAxel Dörfler return status != B_OK ? status : B_ERROR; 242254187cc6Sbeveloper } 242354187cc6Sbeveloper 2424*34c72144SAxel Dörfler rv = RegisterNode(node, addonID, flavorID); 24258c6a6096Sbeveloper if (rv != B_OK) { 24265ac4fbd7Sbeveloper ERROR("BMediaRosterEx::InstantiateDormantNode: RegisterNode failed\n"); 24278c6a6096Sbeveloper delete node; 242854187cc6Sbeveloper // Put the addon back into the pool 2429*34c72144SAxel Dörfler _DormantNodeManager->PutAddon(addonID); 243054187cc6Sbeveloper // We must decrement the use count of this addon flavor in the 243154187cc6Sbeveloper // server to compensate the increment done in the beginning. 2432*34c72144SAxel Dörfler rv = DecrementAddonFlavorInstancesCount(addonID, flavorID); 243354187cc6Sbeveloper if (rv != B_OK) { 2434*34c72144SAxel Dörfler ERROR("BMediaRosterEx::InstantiateDormantNode: DecrementAddon" 2435*34c72144SAxel Dörfler "FlavorInstancesCount failed\n"); 243654187cc6Sbeveloper } 24378c6a6096Sbeveloper return B_ERROR; 24388c6a6096Sbeveloper } 24398c6a6096Sbeveloper 244054187cc6Sbeveloper if (creator != -1) { 2441*34c72144SAxel Dörfler // send a message to the server to assign team "creator" as creator 2442*34c72144SAxel Dörfler // of node "node->ID()" 2443*34c72144SAxel Dörfler printf("!!! BMediaRosterEx::InstantiateDormantNode assigning team " 2444*34c72144SAxel Dörfler "%ld as creator of node %ld\n", creator, node->ID()); 2445*34c72144SAxel Dörfler 244654187cc6Sbeveloper rv = MediaRosterEx(this)->SetNodeCreator(node->ID(), creator); 244754187cc6Sbeveloper if (rv != B_OK) { 2448*34c72144SAxel Dörfler ERROR("BMediaRosterEx::InstantiateDormantNode failed to assign " 2449*34c72144SAxel Dörfler "team %ld as creator of node %ld\n", creator, node->ID()); 245054187cc6Sbeveloper // do not return, this is a minor problem, not a reason to fail 245154187cc6Sbeveloper } 245254187cc6Sbeveloper } 245354187cc6Sbeveloper 245454187cc6Sbeveloper // RegisterNode() does remember the add-on id in the server 245554187cc6Sbeveloper // and UnregisterNode() will call DormantNodeManager::PutAddon() 245654187cc6Sbeveloper // when the node is unregistered. 24578c6a6096Sbeveloper 2458*34c72144SAxel Dörfler *_node = node->Node(); 2459cf4e2277Sbeveloper 2460*34c72144SAxel Dörfler TRACE("BMediaRosterEx::InstantiateDormantNode: addon-id %ld, flavor_id " 2461*34c72144SAxel Dörfler "%ld instanciated as node %ld, port %ld in team %ld\n", addonID, 2462*34c72144SAxel Dörfler flavorID, _node->node, _node->port, team); 2463cf4e2277Sbeveloper 246416b7eea4Sbeveloper return B_OK; 246516b7eea4Sbeveloper } 246652a38012Sejakowatz 246752a38012Sejakowatz 246852a38012Sejakowatz status_t 2469*34c72144SAxel Dörfler BMediaRoster::InstantiateDormantNode(const dormant_node_info& info, 2470*34c72144SAxel Dörfler media_node* _node, uint32 flags) 24718b04ffc1Sbeveloper { 24728b04ffc1Sbeveloper CALLED(); 2473*34c72144SAxel Dörfler if (_node == NULL) 24748b04ffc1Sbeveloper return B_BAD_VALUE; 2475*34c72144SAxel Dörfler if (info.addon <= B_OK) { 2476*34c72144SAxel Dörfler ERROR("BMediaRoster::InstantiateDormantNode error: addon-id %ld " 2477*34c72144SAxel Dörfler "invalid.\n", info.addon); 24788b04ffc1Sbeveloper return B_BAD_VALUE; 24798b04ffc1Sbeveloper } 24808b04ffc1Sbeveloper 2481*34c72144SAxel Dörfler printf("BMediaRoster::InstantiateDormantNode: addon-id %ld, flavor_id " 2482*34c72144SAxel Dörfler "%ld, flags 0x%lX\n", info.addon, info.flavor_id, flags); 24838b04ffc1Sbeveloper 24848b04ffc1Sbeveloper // Get flavor_info from the server 2485*34c72144SAxel Dörfler // TODO: this is a little overhead, as we get the full blown 2486*34c72144SAxel Dörfler // dormant_flavor_info, 2487*34c72144SAxel Dörfler // TODO: but only need the flags. 2488*34c72144SAxel Dörfler dormant_flavor_info flavorInfo; 24898b04ffc1Sbeveloper status_t rv; 2490*34c72144SAxel Dörfler rv = MediaRosterEx(this)->GetDormantFlavorInfo(info.addon, info.flavor_id, 2491*34c72144SAxel Dörfler &flavorInfo); 24928b04ffc1Sbeveloper if (rv != B_OK) { 2493*34c72144SAxel Dörfler ERROR("BMediaRoster::InstantiateDormantNode: failed to get " 2494*34c72144SAxel Dörfler "dormant_flavor_info for addon-id %ld, flavor-id %ld\n", 2495*34c72144SAxel Dörfler info.addon, info.flavor_id); 2496626824eaSbeveloper return B_NAME_NOT_FOUND; 24978b04ffc1Sbeveloper } 24988b04ffc1Sbeveloper 2499*34c72144SAxel Dörfler ASSERT(flavorInfo.internal_id == info.flavor_id); 25008b04ffc1Sbeveloper 25018b04ffc1Sbeveloper #if DEBUG 2502*34c72144SAxel Dörfler printf("BMediaRoster::InstantiateDormantNode: name \"%s\", info \"%s\", " 2503*34c72144SAxel Dörfler "flavor_flags 0x%lX, internal_id %ld, possible_count %ld\n", 2504*34c72144SAxel Dörfler flavorInfo.name, flavorInfo.info, flavorInfo.flavor_flags, 2505*34c72144SAxel Dörfler flavorInfo.internal_id, flavorInfo.possible_count); 2506*34c72144SAxel Dörfler 2507*34c72144SAxel Dörfler if ((flags & B_FLAVOR_IS_LOCAL) != 0) { 2508*34c72144SAxel Dörfler printf("BMediaRoster::InstantiateDormantNode: caller requested " 2509*34c72144SAxel Dörfler "B_FLAVOR_IS_LOCAL\n"); 2510*34c72144SAxel Dörfler } 2511*34c72144SAxel Dörfler if ((flags & B_FLAVOR_IS_GLOBAL) != 0) { 2512*34c72144SAxel Dörfler printf("BMediaRoster::InstantiateDormantNode: caller requested " 2513*34c72144SAxel Dörfler "B_FLAVOR_IS_GLOBAL\n"); 2514*34c72144SAxel Dörfler } 2515*34c72144SAxel Dörfler if ((flavorInfo.flavor_flags & B_FLAVOR_IS_LOCAL) != 0) { 2516*34c72144SAxel Dörfler printf("BMediaRoster::InstantiateDormantNode: node requires " 2517*34c72144SAxel Dörfler "B_FLAVOR_IS_LOCAL\n"); 2518*34c72144SAxel Dörfler } 2519*34c72144SAxel Dörfler if ((flavorInfo.flavor_flags & B_FLAVOR_IS_GLOBAL) != 0) { 2520*34c72144SAxel Dörfler printf("BMediaRoster::InstantiateDormantNode: node requires " 2521*34c72144SAxel Dörfler "B_FLAVOR_IS_GLOBAL\n"); 2522*34c72144SAxel Dörfler } 25238b04ffc1Sbeveloper #endif 25248b04ffc1Sbeveloper 25258b04ffc1Sbeveloper // Make sure that flags demanded by the dormant node and those requested 25268b04ffc1Sbeveloper // by the caller are not incompatible. 2527*34c72144SAxel Dörfler if ((flavorInfo.flavor_flags & B_FLAVOR_IS_GLOBAL) != 0 2528*34c72144SAxel Dörfler && (flags & B_FLAVOR_IS_LOCAL) != 0) { 2529*34c72144SAxel Dörfler ERROR("BMediaRoster::InstantiateDormantNode: requested " 2530*34c72144SAxel Dörfler "B_FLAVOR_IS_LOCAL, but dormant node has B_FLAVOR_IS_GLOBAL\n"); 2531626824eaSbeveloper return B_NAME_NOT_FOUND; 25328b04ffc1Sbeveloper } 2533*34c72144SAxel Dörfler if ((flavorInfo.flavor_flags & B_FLAVOR_IS_LOCAL) != 0 2534*34c72144SAxel Dörfler && (flags & B_FLAVOR_IS_GLOBAL) != 0) { 2535*34c72144SAxel Dörfler ERROR("BMediaRoster::InstantiateDormantNode: requested " 2536*34c72144SAxel Dörfler "B_FLAVOR_IS_GLOBAL, but dormant node has B_FLAVOR_IS_LOCAL\n"); 2537626824eaSbeveloper return B_NAME_NOT_FOUND; 25388b04ffc1Sbeveloper } 253954187cc6Sbeveloper 25408b04ffc1Sbeveloper // If either the node, or the caller requested to make the instance global 2541*34c72144SAxel Dörfler // we will do it by forwarding this request into the media_addon_server, 2542*34c72144SAxel Dörfler // which in turn will call BMediaRosterEx::InstantiateDormantNode to create 2543*34c72144SAxel Dörfler // the node there and make it globally available. 2544*34c72144SAxel Dörfler if ((flavorInfo.flavor_flags & B_FLAVOR_IS_GLOBAL) != 0 2545*34c72144SAxel Dörfler || (flags & B_FLAVOR_IS_GLOBAL) != 0) { 2546*34c72144SAxel Dörfler TRACE("BMediaRoster::InstantiateDormantNode: creating global object " 2547*34c72144SAxel Dörfler "in media_addon_server\n"); 2548cf4e2277Sbeveloper 25498b04ffc1Sbeveloper addonserver_instantiate_dormant_node_request request; 25508b04ffc1Sbeveloper addonserver_instantiate_dormant_node_reply reply; 2551*34c72144SAxel Dörfler request.addonid = info.addon; 2552*34c72144SAxel Dörfler request.flavorid = info.flavor_id; 2553*34c72144SAxel Dörfler request.creator_team = team; 2554*34c72144SAxel Dörfler // creator team is allowed to also release global nodes 2555*34c72144SAxel Dörfler rv = QueryAddonServer(ADDONSERVER_INSTANTIATE_DORMANT_NODE, &request, 2556*34c72144SAxel Dörfler sizeof(request), &reply, sizeof(reply)); 2557*34c72144SAxel Dörfler if (rv == B_OK) 2558*34c72144SAxel Dörfler *_node = reply.node; 25598b04ffc1Sbeveloper } else { 256054187cc6Sbeveloper // creator team = -1, as this is a local node 2561*34c72144SAxel Dörfler rv = MediaRosterEx(this)->InstantiateDormantNode(info.addon, 2562*34c72144SAxel Dörfler info.flavor_id, -1, _node); 25638b04ffc1Sbeveloper } 2564626824eaSbeveloper if (rv != B_OK) { 2565*34c72144SAxel Dörfler *_node = media_node::null; 2566626824eaSbeveloper return B_NAME_NOT_FOUND; 2567626824eaSbeveloper } 2568626824eaSbeveloper return B_OK; 25698b04ffc1Sbeveloper } 25708b04ffc1Sbeveloper 25718b04ffc1Sbeveloper 25728b04ffc1Sbeveloper status_t 2573*34c72144SAxel Dörfler BMediaRoster::InstantiateDormantNode(const dormant_node_info& info, 2574*34c72144SAxel Dörfler media_node* _node) 25758b04ffc1Sbeveloper { 2576*34c72144SAxel Dörfler return InstantiateDormantNode(info, _node, 0); 25778b04ffc1Sbeveloper } 25788b04ffc1Sbeveloper 25798b04ffc1Sbeveloper 25808b04ffc1Sbeveloper status_t 258152a38012Sejakowatz BMediaRoster::GetDormantNodeFor(const media_node& node, 2582*34c72144SAxel Dörfler dormant_node_info* _info) 258352a38012Sejakowatz { 258485dfab2bSbeveloper CALLED(); 2585*34c72144SAxel Dörfler if (_info == NULL) 258685dfab2bSbeveloper return B_BAD_VALUE; 258740f36b03Sbeveloper if (IS_INVALID_NODE(node)) 258885dfab2bSbeveloper return B_MEDIA_BAD_NODE; 258952a38012Sejakowatz 259085dfab2bSbeveloper server_get_dormant_node_for_request request; 259185dfab2bSbeveloper server_get_dormant_node_for_reply reply; 259285dfab2bSbeveloper status_t rv; 259385dfab2bSbeveloper 259485dfab2bSbeveloper request.node = node; 259585dfab2bSbeveloper 2596*34c72144SAxel Dörfler rv = QueryServer(SERVER_GET_DORMANT_NODE_FOR, &request, sizeof(request), 2597*34c72144SAxel Dörfler &reply, sizeof(reply)); 259885dfab2bSbeveloper if (rv != B_OK) 259985dfab2bSbeveloper return rv; 260085dfab2bSbeveloper 2601*34c72144SAxel Dörfler *_info = reply.node_info; 260285dfab2bSbeveloper return B_OK; 260352a38012Sejakowatz } 260452a38012Sejakowatz 2605*34c72144SAxel Dörfler 260652a38012Sejakowatz status_t 2607*34c72144SAxel Dörfler BMediaRosterEx::GetDormantFlavorInfo(media_addon_id addonID, int32 flavorID, 2608*34c72144SAxel Dörfler dormant_flavor_info* _flavor) 260952a38012Sejakowatz { 261052a38012Sejakowatz CALLED(); 2611*34c72144SAxel Dörfler if (_flavor == NULL) 26129bedd42cSbeveloper return B_BAD_VALUE; 261352a38012Sejakowatz 261452a38012Sejakowatz xfer_server_get_dormant_flavor_info msg; 261552a38012Sejakowatz xfer_server_get_dormant_flavor_info_reply *reply; 261652a38012Sejakowatz port_id port; 261752a38012Sejakowatz status_t rv; 261852a38012Sejakowatz int32 code; 261952a38012Sejakowatz 26204295907bSbeveloper port = find_port(MEDIA_SERVER_PORT_NAME); 2621*34c72144SAxel Dörfler if (port < B_OK) 262252a38012Sejakowatz return B_ERROR; 262352a38012Sejakowatz 262452a38012Sejakowatz reply = (xfer_server_get_dormant_flavor_info_reply*)malloc(16000); 2625*34c72144SAxel Dörfler if (reply == NULL) 2626*34c72144SAxel Dörfler return B_NO_MEMORY; 262752a38012Sejakowatz 2628*34c72144SAxel Dörfler msg.addon = addonID; 2629*34c72144SAxel Dörfler msg.flavor_id = flavorID; 263052a38012Sejakowatz msg.reply_port = _PortPool->GetPort(); 263152a38012Sejakowatz rv = write_port(port, SERVER_GET_DORMANT_FLAVOR_INFO, &msg, sizeof(msg)); 263252a38012Sejakowatz if (rv != B_OK) { 263352a38012Sejakowatz free(reply); 263452a38012Sejakowatz _PortPool->PutPort(msg.reply_port); 263552a38012Sejakowatz return rv; 263652a38012Sejakowatz } 263752a38012Sejakowatz rv = read_port(msg.reply_port, &code, reply, 16000); 263852a38012Sejakowatz _PortPool->PutPort(msg.reply_port); 263952a38012Sejakowatz 264052a38012Sejakowatz if (rv < B_OK) { 264152a38012Sejakowatz free(reply); 264252a38012Sejakowatz return rv; 264352a38012Sejakowatz } 264452a38012Sejakowatz 264552a38012Sejakowatz if (reply->result == B_OK) 2646*34c72144SAxel Dörfler rv = _flavor->Unflatten(reply->dfi_type, &reply->dfi, reply->dfi_size); 264752a38012Sejakowatz else 264852a38012Sejakowatz rv = reply->result; 264952a38012Sejakowatz 265052a38012Sejakowatz free(reply); 265152a38012Sejakowatz return rv; 265252a38012Sejakowatz } 265352a38012Sejakowatz 2654*34c72144SAxel Dörfler 26558b04ffc1Sbeveloper status_t 2656*34c72144SAxel Dörfler BMediaRoster::GetDormantFlavorInfoFor(const dormant_node_info& dormant, 2657*34c72144SAxel Dörfler dormant_flavor_info* _flavor) 26588b04ffc1Sbeveloper { 2659*34c72144SAxel Dörfler return MediaRosterEx(this)->GetDormantFlavorInfo(dormant.addon, 2660*34c72144SAxel Dörfler dormant.flavor_id, _flavor); 26618b04ffc1Sbeveloper } 266252a38012Sejakowatz 2663*34c72144SAxel Dörfler 266460f15390Sbeveloper // Reports in outLatency the maximum latency found downstream from 266560f15390Sbeveloper // the specified BBufferProducer, producer, given the current connections. 266652a38012Sejakowatz status_t 2667*34c72144SAxel Dörfler BMediaRoster::GetLatencyFor(const media_node& producer, bigtime_t* _latency) 266852a38012Sejakowatz { 266960f15390Sbeveloper CALLED(); 2670*34c72144SAxel Dörfler if (_latency == NULL) 267160f15390Sbeveloper return B_BAD_VALUE; 2672*34c72144SAxel Dörfler if (IS_INVALID_NODE(producer) 2673*34c72144SAxel Dörfler || (producer.kind & B_BUFFER_PRODUCER) == 0) 267460f15390Sbeveloper return B_MEDIA_BAD_NODE; 267560f15390Sbeveloper 267660f15390Sbeveloper producer_get_latency_request request; 267760f15390Sbeveloper producer_get_latency_reply reply; 267860f15390Sbeveloper status_t rv; 267960f15390Sbeveloper 2680*34c72144SAxel Dörfler rv = QueryPort(producer.port, PRODUCER_GET_LATENCY, &request, 2681*34c72144SAxel Dörfler sizeof(request), &reply, sizeof(reply)); 268260f15390Sbeveloper if (rv != B_OK) 268360f15390Sbeveloper return rv; 268460f15390Sbeveloper 2685*34c72144SAxel Dörfler *_latency = reply.latency; 268660f15390Sbeveloper 2687ab9afde3SMarcus Overhagen // printf("BMediaRoster::GetLatencyFor producer %ld has maximum latency %Ld\n", producer.node, *out_latency); 2688aac800c2Sbeveloper return B_OK; 268952a38012Sejakowatz } 269052a38012Sejakowatz 269152a38012Sejakowatz 269252a38012Sejakowatz status_t 269352a38012Sejakowatz BMediaRoster::GetInitialLatencyFor(const media_node& producer, 2694*34c72144SAxel Dörfler bigtime_t* _latency, uint32* _flags) 269552a38012Sejakowatz { 2696b65a0ac5SJérôme Duval CALLED(); 2697*34c72144SAxel Dörfler if (_latency == NULL) 2698b65a0ac5SJérôme Duval return B_BAD_VALUE; 2699*34c72144SAxel Dörfler if (IS_INVALID_NODE(producer) 2700*34c72144SAxel Dörfler || (producer.kind & B_BUFFER_PRODUCER) == 0) 2701b65a0ac5SJérôme Duval return B_MEDIA_BAD_NODE; 2702b65a0ac5SJérôme Duval 2703b65a0ac5SJérôme Duval producer_get_initial_latency_request request; 2704b65a0ac5SJérôme Duval producer_get_initial_latency_reply reply; 2705b65a0ac5SJérôme Duval status_t rv; 2706b65a0ac5SJérôme Duval 2707*34c72144SAxel Dörfler rv = QueryPort(producer.port, PRODUCER_GET_INITIAL_LATENCY, &request, 2708*34c72144SAxel Dörfler sizeof(request), &reply, sizeof(reply)); 2709b65a0ac5SJérôme Duval if (rv != B_OK) 2710b65a0ac5SJérôme Duval return rv; 2711b65a0ac5SJérôme Duval 2712*34c72144SAxel Dörfler *_latency = reply.initial_latency; 2713*34c72144SAxel Dörfler if (_flags != NULL) 2714*34c72144SAxel Dörfler *_flags = reply.flags; 2715b65a0ac5SJérôme Duval 2716*34c72144SAxel Dörfler TRACE("BMediaRoster::GetInitialLatencyFor producer %ld has maximum " 2717*34c72144SAxel Dörfler "initial latency %Ld\n", producer.node, *_latency); 2718aac800c2Sbeveloper return B_OK; 271952a38012Sejakowatz } 272052a38012Sejakowatz 272152a38012Sejakowatz 272252a38012Sejakowatz status_t 2723*34c72144SAxel Dörfler BMediaRoster::GetStartLatencyFor(const media_node& timeSource, 2724*34c72144SAxel Dörfler bigtime_t* _latency) 272552a38012Sejakowatz { 2726fc8b28b6SJérôme Duval CALLED(); 2727*34c72144SAxel Dörfler if (_latency == NULL) 2728fc8b28b6SJérôme Duval return B_BAD_VALUE; 2729*34c72144SAxel Dörfler if (IS_INVALID_NODE(timeSource) 2730*34c72144SAxel Dörfler || (timeSource.kind & B_TIME_SOURCE) == 0) 2731fc8b28b6SJérôme Duval return B_MEDIA_BAD_NODE; 2732fc8b28b6SJérôme Duval 2733fc8b28b6SJérôme Duval timesource_get_start_latency_request request; 2734fc8b28b6SJérôme Duval timesource_get_start_latency_reply reply; 2735fc8b28b6SJérôme Duval status_t rv; 2736fc8b28b6SJérôme Duval 2737*34c72144SAxel Dörfler rv = QueryPort(timeSource.port, TIMESOURCE_GET_START_LATENCY, &request, 2738*34c72144SAxel Dörfler sizeof(request), &reply, sizeof(reply)); 2739fc8b28b6SJérôme Duval if (rv != B_OK) 2740fc8b28b6SJérôme Duval return rv; 2741fc8b28b6SJérôme Duval 2742*34c72144SAxel Dörfler *_latency = reply.start_latency; 2743fc8b28b6SJérôme Duval 2744*34c72144SAxel Dörfler TRACE("BMediaRoster::GetStartLatencyFor timesource %ld has maximum " 2745*34c72144SAxel Dörfler "initial latency %Ld\n", timeSource.node, *_latency); 2746aac800c2Sbeveloper return B_OK; 274752a38012Sejakowatz } 274852a38012Sejakowatz 274952a38012Sejakowatz 275052a38012Sejakowatz status_t 2751*34c72144SAxel Dörfler BMediaRoster::GetFileFormatsFor(const media_node& fileInterface, 2752*34c72144SAxel Dörfler media_file_format* _formats, int32* _numFormats) 275352a38012Sejakowatz { 275452a38012Sejakowatz UNIMPLEMENTED(); 275552a38012Sejakowatz return B_ERROR; 275652a38012Sejakowatz } 275752a38012Sejakowatz 275852a38012Sejakowatz 275952a38012Sejakowatz status_t 2760*34c72144SAxel Dörfler BMediaRoster::SetRefFor(const media_node& file_interface, const entry_ref& file, 2761*34c72144SAxel Dörfler bool createAndTruncate, bigtime_t* _length) 276252a38012Sejakowatz { 27636938364bSMaurice Kalinowski CALLED(); 27646938364bSMaurice Kalinowski 27656938364bSMaurice Kalinowski fileinterface_set_ref_request request; 27666938364bSMaurice Kalinowski fileinterface_set_ref_reply reply; 27676938364bSMaurice Kalinowski status_t rv; 27686938364bSMaurice Kalinowski 27696938364bSMaurice Kalinowski request.device = file.device; 27706938364bSMaurice Kalinowski request.directory = file.directory; 27716938364bSMaurice Kalinowski strcpy(request.name, file.name); 2772*34c72144SAxel Dörfler request.create = createAndTruncate; 2773*34c72144SAxel Dörfler if (_length != NULL) 2774*34c72144SAxel Dörfler request.duration = *_length; 27756938364bSMaurice Kalinowski 2776*34c72144SAxel Dörfler rv = QueryPort(file_interface.port, FILEINTERFACE_SET_REF, &request, 2777*34c72144SAxel Dörfler sizeof(request), &reply, sizeof(reply)); 27786938364bSMaurice Kalinowski if (rv != B_OK) 27796938364bSMaurice Kalinowski return rv; 27806938364bSMaurice Kalinowski 2781*34c72144SAxel Dörfler if (!createAndTruncate && _length) 2782*34c72144SAxel Dörfler *_length = reply.duration; 27836938364bSMaurice Kalinowski 27846938364bSMaurice Kalinowski return B_OK; 278552a38012Sejakowatz } 278652a38012Sejakowatz 278752a38012Sejakowatz 278852a38012Sejakowatz status_t 2789*34c72144SAxel Dörfler BMediaRoster::GetRefFor(const media_node& node, entry_ref* _file, 2790*34c72144SAxel Dörfler BMimeType* mimeType) 279152a38012Sejakowatz { 27926938364bSMaurice Kalinowski CALLED(); 27936938364bSMaurice Kalinowski 2794*34c72144SAxel Dörfler if (!_file) 27956938364bSMaurice Kalinowski return B_BAD_VALUE; 27966938364bSMaurice Kalinowski 27976938364bSMaurice Kalinowski fileinterface_get_ref_request request; 27986938364bSMaurice Kalinowski fileinterface_get_ref_reply reply; 27996938364bSMaurice Kalinowski status_t rv; 28006938364bSMaurice Kalinowski 2801*34c72144SAxel Dörfler rv = QueryPort(node.port, FILEINTERFACE_GET_REF, &request, sizeof(request), 2802*34c72144SAxel Dörfler &reply, sizeof(reply)); 28036938364bSMaurice Kalinowski if (rv != B_OK) 28046938364bSMaurice Kalinowski return rv; 28056938364bSMaurice Kalinowski 2806*34c72144SAxel Dörfler *_file = entry_ref(reply.device, reply.directory, reply.name); 28076938364bSMaurice Kalinowski 2808*34c72144SAxel Dörfler if (mimeType) 2809*34c72144SAxel Dörfler mimeType->SetTo(reply.mimetype); 28106938364bSMaurice Kalinowski 28116938364bSMaurice Kalinowski return B_OK; 281252a38012Sejakowatz } 281352a38012Sejakowatz 281452a38012Sejakowatz 281552a38012Sejakowatz status_t 281652a38012Sejakowatz BMediaRoster::SniffRefFor(const media_node& file_interface, 2817*34c72144SAxel Dörfler const entry_ref& file, BMimeType* mimeType, float* _capability) 281852a38012Sejakowatz { 28196938364bSMaurice Kalinowski CALLED(); 2820*34c72144SAxel Dörfler if (mimeType == NULL || _capability == NULL) 28216938364bSMaurice Kalinowski return B_BAD_VALUE; 28226938364bSMaurice Kalinowski 28236938364bSMaurice Kalinowski fileinterface_sniff_ref_request request; 28246938364bSMaurice Kalinowski fileinterface_sniff_ref_reply reply; 28256938364bSMaurice Kalinowski status_t rv; 28266938364bSMaurice Kalinowski 28276938364bSMaurice Kalinowski request.device = file.device; 28286938364bSMaurice Kalinowski request.directory = file.directory; 28296938364bSMaurice Kalinowski strcpy(request.name, file.name); 28306938364bSMaurice Kalinowski 2831*34c72144SAxel Dörfler rv = QueryPort(file_interface.port, FILEINTERFACE_SNIFF_REF, &request, 2832*34c72144SAxel Dörfler sizeof(request), &reply, sizeof(reply)); 28336938364bSMaurice Kalinowski if (rv != B_OK) 28346938364bSMaurice Kalinowski return rv; 28356938364bSMaurice Kalinowski 2836*34c72144SAxel Dörfler mimeType->SetTo(reply.mimetype); 2837*34c72144SAxel Dörfler *_capability = reply.capability; 28386938364bSMaurice Kalinowski 28396938364bSMaurice Kalinowski return B_OK; 284052a38012Sejakowatz } 284152a38012Sejakowatz 284252a38012Sejakowatz 2843*34c72144SAxel Dörfler /*! This is the generic "here's a file, now can someone please play it" 2844*34c72144SAxel Dörfler interface. 2845*34c72144SAxel Dörfler */ 284652a38012Sejakowatz status_t 2847*34c72144SAxel Dörfler BMediaRoster::SniffRef(const entry_ref& file, uint64 requireNodeKinds, 2848*34c72144SAxel Dörfler dormant_node_info* _node, BMimeType* mimeType) 284952a38012Sejakowatz { 285052a38012Sejakowatz UNIMPLEMENTED(); 285152a38012Sejakowatz return B_ERROR; 285252a38012Sejakowatz } 285352a38012Sejakowatz 285452a38012Sejakowatz 285552a38012Sejakowatz status_t 285652a38012Sejakowatz BMediaRoster::GetDormantNodeForType(const BMimeType& type, 2857*34c72144SAxel Dörfler uint64 requireNodeKinds, dormant_node_info* _node) 285852a38012Sejakowatz { 285952a38012Sejakowatz UNIMPLEMENTED(); 286052a38012Sejakowatz return B_ERROR; 286152a38012Sejakowatz } 286252a38012Sejakowatz 286352a38012Sejakowatz 286452a38012Sejakowatz status_t 2865*34c72144SAxel Dörfler BMediaRoster::GetReadFileFormatsFor(const dormant_node_info& node, 2866*34c72144SAxel Dörfler media_file_format* _readFormats, int32 readCount, int32* _readCount) 286752a38012Sejakowatz { 286852a38012Sejakowatz UNIMPLEMENTED(); 286952a38012Sejakowatz return B_ERROR; 287052a38012Sejakowatz } 287152a38012Sejakowatz 287252a38012Sejakowatz 287352a38012Sejakowatz status_t 2874*34c72144SAxel Dörfler BMediaRoster::GetWriteFileFormatsFor(const dormant_node_info& node, 2875*34c72144SAxel Dörfler media_file_format* _write_formats, int32 writeCount, int32* _writeCount) 287652a38012Sejakowatz { 287752a38012Sejakowatz UNIMPLEMENTED(); 287852a38012Sejakowatz return B_ERROR; 287952a38012Sejakowatz } 288052a38012Sejakowatz 288152a38012Sejakowatz 288252a38012Sejakowatz status_t 2883*34c72144SAxel Dörfler BMediaRoster::GetFormatFor(const media_output& output, media_format* _format, 288452a38012Sejakowatz uint32 flags) 288552a38012Sejakowatz { 28869bedd42cSbeveloper CALLED(); 2887*34c72144SAxel Dörfler if (_format == NULL) 28889bedd42cSbeveloper return B_BAD_VALUE; 28899bedd42cSbeveloper if ((output.node.kind & B_BUFFER_PRODUCER) == 0) 28909bedd42cSbeveloper return B_MEDIA_BAD_NODE; 28919bedd42cSbeveloper if (IS_INVALID_SOURCE(output.source)) 28929bedd42cSbeveloper return B_MEDIA_BAD_SOURCE; 28939bedd42cSbeveloper 28949bedd42cSbeveloper producer_format_suggestion_requested_request request; 28959bedd42cSbeveloper producer_format_suggestion_requested_reply reply; 28969bedd42cSbeveloper status_t rv; 28979bedd42cSbeveloper 28989bedd42cSbeveloper request.type = B_MEDIA_UNKNOWN_TYPE; 2899*34c72144SAxel Dörfler request.quality = 0; // TODO: what should this be? 29009bedd42cSbeveloper 2901*34c72144SAxel Dörfler rv = QueryPort(output.source.port, PRODUCER_FORMAT_SUGGESTION_REQUESTED, 2902*34c72144SAxel Dörfler &request, sizeof(request), &reply, sizeof(reply)); 29039bedd42cSbeveloper if (rv != B_OK) 29049bedd42cSbeveloper return rv; 29059bedd42cSbeveloper 2906*34c72144SAxel Dörfler *_format = reply.format; 29079bedd42cSbeveloper return B_OK; 290852a38012Sejakowatz } 290952a38012Sejakowatz 291052a38012Sejakowatz 291152a38012Sejakowatz status_t 2912*34c72144SAxel Dörfler BMediaRoster::GetFormatFor(const media_input& input, media_format* _format, 291352a38012Sejakowatz uint32 flags) 291452a38012Sejakowatz { 29159bedd42cSbeveloper CALLED(); 2916*34c72144SAxel Dörfler if (_format == NULL) 29179bedd42cSbeveloper return B_BAD_VALUE; 29189bedd42cSbeveloper if ((input.node.kind & B_BUFFER_CONSUMER) == 0) 29199bedd42cSbeveloper return B_MEDIA_BAD_NODE; 29209bedd42cSbeveloper if (IS_INVALID_DESTINATION(input.destination)) 29219bedd42cSbeveloper return B_MEDIA_BAD_DESTINATION; 29229bedd42cSbeveloper 29239bedd42cSbeveloper consumer_accept_format_request request; 29249bedd42cSbeveloper consumer_accept_format_reply reply; 29259bedd42cSbeveloper status_t rv; 29269bedd42cSbeveloper 29279bedd42cSbeveloper request.dest = input.destination; 29289bedd42cSbeveloper memset(&request.format, 0, sizeof(request.format)); // wildcard 29299bedd42cSbeveloper 2930*34c72144SAxel Dörfler rv = QueryPort(input.destination.port, CONSUMER_ACCEPT_FORMAT, &request, 2931*34c72144SAxel Dörfler sizeof(request), &reply, sizeof(reply)); 29329bedd42cSbeveloper if (rv != B_OK) 29339bedd42cSbeveloper return rv; 29349bedd42cSbeveloper 2935*34c72144SAxel Dörfler *_format = reply.format; 29369bedd42cSbeveloper return B_OK; 293752a38012Sejakowatz } 293852a38012Sejakowatz 293952a38012Sejakowatz 294052a38012Sejakowatz status_t 2941*34c72144SAxel Dörfler BMediaRoster::GetFormatFor(const media_node& node, media_format* _format, 294252a38012Sejakowatz float quality) 294352a38012Sejakowatz { 294452a38012Sejakowatz UNIMPLEMENTED(); 2945*34c72144SAxel Dörfler if (_format == NULL) 29469bedd42cSbeveloper return B_BAD_VALUE; 29479bedd42cSbeveloper if (IS_INVALID_NODE(node)) 29489bedd42cSbeveloper return B_MEDIA_BAD_NODE; 29499bedd42cSbeveloper if ((node.kind & (B_BUFFER_CONSUMER | B_BUFFER_PRODUCER)) == 0) 29509bedd42cSbeveloper return B_MEDIA_BAD_NODE; 29519bedd42cSbeveloper 295252a38012Sejakowatz return B_ERROR; 295352a38012Sejakowatz } 295452a38012Sejakowatz 295552a38012Sejakowatz 295652a38012Sejakowatz ssize_t 295752a38012Sejakowatz BMediaRoster::GetNodeAttributesFor(const media_node& node, 2958*34c72144SAxel Dörfler media_node_attribute* _array, size_t maxCount) 295952a38012Sejakowatz { 296052a38012Sejakowatz UNIMPLEMENTED(); 296152a38012Sejakowatz return B_ERROR; 296252a38012Sejakowatz } 296352a38012Sejakowatz 296452a38012Sejakowatz 296552a38012Sejakowatz media_node_id 2966*34c72144SAxel Dörfler BMediaRoster::NodeIDFor(port_id port) 296752a38012Sejakowatz { 29689e9417d2Sbeveloper CALLED(); 29699e9417d2Sbeveloper 29709e9417d2Sbeveloper server_node_id_for_request request; 29719e9417d2Sbeveloper server_node_id_for_reply reply; 29729e9417d2Sbeveloper status_t rv; 29739e9417d2Sbeveloper 2974*34c72144SAxel Dörfler request.port = port; 29759e9417d2Sbeveloper 2976*34c72144SAxel Dörfler rv = QueryServer(SERVER_NODE_ID_FOR, &request, sizeof(request), &reply, 2977*34c72144SAxel Dörfler sizeof(reply)); 29789e9417d2Sbeveloper if (rv != B_OK) { 29795ac4fbd7Sbeveloper ERROR("BMediaRoster::NodeIDFor: failed (error %#lx)\n", rv); 29809e9417d2Sbeveloper return -1; 29819e9417d2Sbeveloper } 29829e9417d2Sbeveloper 29839e9417d2Sbeveloper return reply.nodeid; 298452a38012Sejakowatz } 298552a38012Sejakowatz 298652a38012Sejakowatz 298752a38012Sejakowatz status_t 2988*34c72144SAxel Dörfler BMediaRoster::GetInstancesFor(media_addon_id addon, int32 flavor, 2989*34c72144SAxel Dörfler media_node_id* _id, int32* _count) 299052a38012Sejakowatz { 299185dfab2bSbeveloper CALLED(); 2992*34c72144SAxel Dörfler if (_id == NULL) 299385dfab2bSbeveloper return B_BAD_VALUE; 2994*34c72144SAxel Dörfler if (_count && *_count <= 0) 299585dfab2bSbeveloper return B_BAD_VALUE; 299685dfab2bSbeveloper 299785dfab2bSbeveloper server_get_instances_for_request request; 299885dfab2bSbeveloper server_get_instances_for_reply reply; 299985dfab2bSbeveloper status_t rv; 300085dfab2bSbeveloper 3001*34c72144SAxel Dörfler request.maxcount = (_count ? *_count : 1); 300285dfab2bSbeveloper request.addon_id = addon; 300385dfab2bSbeveloper request.addon_flavor_id = flavor; 300485dfab2bSbeveloper 3005*34c72144SAxel Dörfler rv = QueryServer(SERVER_GET_INSTANCES_FOR, &request, sizeof(request), 3006*34c72144SAxel Dörfler &reply, sizeof(reply)); 300785dfab2bSbeveloper if (rv != B_OK) { 30085ac4fbd7Sbeveloper ERROR("BMediaRoster::GetLiveNodes failed\n"); 300985dfab2bSbeveloper return rv; 301052a38012Sejakowatz } 301152a38012Sejakowatz 3012*34c72144SAxel Dörfler if (_count) 3013*34c72144SAxel Dörfler *_count = reply.count; 301485dfab2bSbeveloper if (reply.count > 0) 3015*34c72144SAxel Dörfler memcpy(_id, reply.node_id, sizeof(media_node_id) * reply.count); 301685dfab2bSbeveloper 301785dfab2bSbeveloper return B_OK; 301885dfab2bSbeveloper } 301952a38012Sejakowatz 302052a38012Sejakowatz 302152a38012Sejakowatz status_t 3022*34c72144SAxel Dörfler BMediaRoster::SetRealtimeFlags(uint32 enabled) 302352a38012Sejakowatz { 302452a38012Sejakowatz UNIMPLEMENTED(); 302552a38012Sejakowatz return B_ERROR; 302652a38012Sejakowatz } 302752a38012Sejakowatz 302852a38012Sejakowatz 302952a38012Sejakowatz status_t 3030*34c72144SAxel Dörfler BMediaRoster::GetRealtimeFlags(uint32* _enabled) 303152a38012Sejakowatz { 303252a38012Sejakowatz UNIMPLEMENTED(); 303352a38012Sejakowatz return B_ERROR; 303452a38012Sejakowatz } 303552a38012Sejakowatz 303652a38012Sejakowatz 303752a38012Sejakowatz ssize_t 3038*34c72144SAxel Dörfler BMediaRoster::AudioBufferSizeFor(int32 channelCount, uint32 sampleFormat, 3039*34c72144SAxel Dörfler float frameRate, bus_type busKind) 304052a38012Sejakowatz { 3041*34c72144SAxel Dörfler bigtime_t bufferDuration; 3042*34c72144SAxel Dörfler ssize_t bufferSize; 3043df6c2e83Sbeveloper 3044df6c2e83Sbeveloper system_info info; 3045df6c2e83Sbeveloper get_system_info(&info); 3046df6c2e83Sbeveloper 3047*34c72144SAxel Dörfler if (info.cpu_clock_speed > 2000000000) // 2 GHz 3048*34c72144SAxel Dörfler bufferDuration = 2500; 3049df6c2e83Sbeveloper else if (info.cpu_clock_speed > 1000000000) 3050*34c72144SAxel Dörfler bufferDuration = 5000; 3051df6c2e83Sbeveloper else if (info.cpu_clock_speed > 600000000) 3052*34c72144SAxel Dörfler bufferDuration = 10000; 3053df6c2e83Sbeveloper else if (info.cpu_clock_speed > 200000000) 3054*34c72144SAxel Dörfler bufferDuration = 20000; 3055df6c2e83Sbeveloper else if (info.cpu_clock_speed > 100000000) 3056*34c72144SAxel Dörfler bufferDuration = 30000; 3057df6c2e83Sbeveloper else 3058*34c72144SAxel Dörfler bufferDuration = 50000; 3059df6c2e83Sbeveloper 3060*34c72144SAxel Dörfler if ((busKind == B_ISA_BUS || busKind == B_PCMCIA_BUS) 3061*34c72144SAxel Dörfler && bufferDuration < 25000) 3062*34c72144SAxel Dörfler bufferDuration = 25000; 3063df6c2e83Sbeveloper 3064*34c72144SAxel Dörfler bufferSize = (sampleFormat & 0xf) * channelCount 3065*34c72144SAxel Dörfler * (ssize_t)((frameRate * bufferDuration) / 1000000.0); 3066df6c2e83Sbeveloper 3067*34c72144SAxel Dörfler printf("Suggested buffer duration %Ld, size %ld\n", bufferDuration, 3068*34c72144SAxel Dörfler bufferSize); 3069df6c2e83Sbeveloper 3070*34c72144SAxel Dörfler return bufferSize; 307152a38012Sejakowatz } 307252a38012Sejakowatz 307352a38012Sejakowatz 3074*34c72144SAxel Dörfler /*! Use MediaFlags to inquire about specific features of the Media Kit. 3075*34c72144SAxel Dörfler Returns < 0 for "not present", positive size for output data size. 3076*34c72144SAxel Dörfler 0 means that the capability is present, but no data about it. 3077*34c72144SAxel Dörfler */ 307852a38012Sejakowatz /*static*/ ssize_t 3079*34c72144SAxel Dörfler BMediaRoster::MediaFlags(media_flags cap, void* buffer, size_t maxSize) 308052a38012Sejakowatz { 308152a38012Sejakowatz UNIMPLEMENTED(); 308252a38012Sejakowatz return 0; 308352a38012Sejakowatz } 308452a38012Sejakowatz 308552a38012Sejakowatz 3086*34c72144SAxel Dörfler // #pragma mark - BLooper overrides 3087*34c72144SAxel Dörfler 3088*34c72144SAxel Dörfler 3089*34c72144SAxel Dörfler void 309052a38012Sejakowatz BMediaRoster::MessageReceived(BMessage* message) 309152a38012Sejakowatz { 3092cf4e2277Sbeveloper switch (message->what) { 3093cf4e2277Sbeveloper case 'PING': 3094cf4e2277Sbeveloper { 30956396865dSbeveloper // media_server plays ping-pong with the BMediaRosters 30966396865dSbeveloper // to detect dead teams. Normal communication uses ports. 30976396865dSbeveloper static BMessage pong('PONG'); 30986396865dSbeveloper message->SendReply(&pong, static_cast<BHandler *>(NULL), 2000000); 30996396865dSbeveloper return; 31006396865dSbeveloper } 31016396865dSbeveloper 3102cf4e2277Sbeveloper case NODE_FINAL_RELEASE: 3103cf4e2277Sbeveloper { 3104cf4e2277Sbeveloper // this function is called by a BMediaNode to delete 3105cf4e2277Sbeveloper // itself, as this needs to be done from another thread 3106cf4e2277Sbeveloper // context, it is done here. 3107*34c72144SAxel Dörfler // TODO: If a node is released using BMediaRoster::ReleaseNode() 3108*34c72144SAxel Dörfler // TODO: instead of using BMediaNode::Release() / BMediaNode::Acquire() 3109*34c72144SAxel Dörfler // TODO: fRefCount of the BMediaNode will not be correct. 3110cf4e2277Sbeveloper 3111cf4e2277Sbeveloper BMediaNode *node; 3112cf4e2277Sbeveloper message->FindPointer("node", reinterpret_cast<void **>(&node)); 3113cf4e2277Sbeveloper 311454187cc6Sbeveloper TRACE("BMediaRoster::MessageReceived NODE_FINAL_RELEASE saving node %ld configuration\n", node->ID()); 311554187cc6Sbeveloper MediaRosterEx(BMediaRoster::Roster())->SaveNodeConfiguration(node); 3116cf4e2277Sbeveloper 311754187cc6Sbeveloper TRACE("BMediaRoster::MessageReceived NODE_FINAL_RELEASE releasing node %ld\n", node->ID()); 3118cf4e2277Sbeveloper node->DeleteHook(node); // we don't call Release(), see above! 3119cf4e2277Sbeveloper return; 3120cf4e2277Sbeveloper } 3121cf4e2277Sbeveloper } 31226396865dSbeveloper printf("BMediaRoster::MessageReceived: unknown message!\n"); 31236396865dSbeveloper message->PrintToStream(); 312452a38012Sejakowatz } 312552a38012Sejakowatz 3126*34c72144SAxel Dörfler 3127*34c72144SAxel Dörfler bool 312852a38012Sejakowatz BMediaRoster::QuitRequested() 312952a38012Sejakowatz { 313052a38012Sejakowatz UNIMPLEMENTED(); 313152a38012Sejakowatz return true; 313252a38012Sejakowatz } 313352a38012Sejakowatz 3134*34c72144SAxel Dörfler 3135*34c72144SAxel Dörfler BHandler* 3136*34c72144SAxel Dörfler BMediaRoster::ResolveSpecifier(BMessage* msg, int32 index, BMessage* specifier, 3137*34c72144SAxel Dörfler int32 form, const char* property) 313852a38012Sejakowatz { 3139286a3c91SJérôme Duval return BLooper::ResolveSpecifier(msg, index, specifier, form, property); 314052a38012Sejakowatz } 314152a38012Sejakowatz 314252a38012Sejakowatz 3143*34c72144SAxel Dörfler status_t 314452a38012Sejakowatz BMediaRoster::GetSupportedSuites(BMessage* data) 314552a38012Sejakowatz { 3146286a3c91SJérôme Duval return BLooper::GetSupportedSuites(data); 314752a38012Sejakowatz } 314852a38012Sejakowatz 314952a38012Sejakowatz 315052a38012Sejakowatz BMediaRoster::~BMediaRoster() 315152a38012Sejakowatz { 315252a38012Sejakowatz CALLED(); 31536396865dSbeveloper 31546396865dSbeveloper // unregister this application with the media server 31556396865dSbeveloper server_unregister_app_request request; 31566396865dSbeveloper server_unregister_app_reply reply; 31576396865dSbeveloper request.team = team; 3158*34c72144SAxel Dörfler QueryServer(SERVER_UNREGISTER_APP, &request, sizeof(request), &reply, 3159*34c72144SAxel Dörfler sizeof(reply)); 31608b940bb4SStephan Aßmus 31618b940bb4SStephan Aßmus // Unset the global instance pointer, the destructor is also called 31628b940bb4SStephan Aßmus // if a client app calls Lock(); and Quit(); directly. 31639def3bf7SStephan Aßmus sDefaultInstance = NULL; 316452a38012Sejakowatz } 316552a38012Sejakowatz 316652a38012Sejakowatz 3167*34c72144SAxel Dörfler // #pragma mark - private BMediaRoster 3168*34c72144SAxel Dörfler 316952a38012Sejakowatz 317052a38012Sejakowatz // deprecated call 317152a38012Sejakowatz status_t 317252a38012Sejakowatz BMediaRoster::SetOutputBuffersFor(const media_source& output, 3173*34c72144SAxel Dörfler BBufferGroup* group, bool willReclaim) 317452a38012Sejakowatz { 317552a38012Sejakowatz UNIMPLEMENTED(); 31769e9417d2Sbeveloper debugger("BMediaRoster::SetOutputBuffersFor missing\n"); 317752a38012Sejakowatz return B_ERROR; 317852a38012Sejakowatz } 317952a38012Sejakowatz 318052a38012Sejakowatz 3181*34c72144SAxel Dörfler /* FBC reserved virtuals */ 318252a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_0(void *) { return B_ERROR; } 318352a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_1(void *) { return B_ERROR; } 318452a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_2(void *) { return B_ERROR; } 318552a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_3(void *) { return B_ERROR; } 318652a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_4(void *) { return B_ERROR; } 318752a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_5(void *) { return B_ERROR; } 318852a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_6(void *) { return B_ERROR; } 318952a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_7(void *) { return B_ERROR; } 319052a38012Sejakowatz 319152a38012Sejakowatz 3192*34c72144SAxel Dörfler BMediaRoster::BMediaRoster() 3193*34c72144SAxel Dörfler : BLooper("_BMediaRoster_", B_URGENT_DISPLAY_PRIORITY, 3194*34c72144SAxel Dörfler B_LOOPER_PORT_DEFAULT_CAPACITY) 319552a38012Sejakowatz { 319652a38012Sejakowatz CALLED(); 31976396865dSbeveloper 31986396865dSbeveloper // start the looper 31996396865dSbeveloper Run(); 320052a38012Sejakowatz } 320152a38012Sejakowatz 32026396865dSbeveloper 32039def3bf7SStephan Aßmus // TODO: Looks like these can be safely removed: 320452a38012Sejakowatz /*static*/ status_t 320552a38012Sejakowatz BMediaRoster::ParseCommand(BMessage& reply) 320652a38012Sejakowatz { 320752a38012Sejakowatz UNIMPLEMENTED(); 320852a38012Sejakowatz return B_ERROR; 320952a38012Sejakowatz } 321052a38012Sejakowatz 321152a38012Sejakowatz 321252a38012Sejakowatz status_t 3213*34c72144SAxel Dörfler BMediaRoster::GetDefaultInfo(media_node_id forDefault, BMessage& config) 321452a38012Sejakowatz { 321552a38012Sejakowatz UNIMPLEMENTED(); 321652a38012Sejakowatz return B_ERROR; 321752a38012Sejakowatz } 321852a38012Sejakowatz 321952a38012Sejakowatz 322052a38012Sejakowatz status_t 3221*34c72144SAxel Dörfler BMediaRoster::SetRunningDefault(media_node_id forDefault, 322252a38012Sejakowatz const media_node& node) 322352a38012Sejakowatz { 322452a38012Sejakowatz UNIMPLEMENTED(); 322552a38012Sejakowatz return B_ERROR; 322652a38012Sejakowatz } 322752a38012Sejakowatz 322852a38012Sejakowatz 32299def3bf7SStephan Aßmus // #pragma mark - static variables 323052a38012Sejakowatz 32319def3bf7SStephan Aßmus 32329def3bf7SStephan Aßmus BMediaRoster* BMediaRoster::sDefaultInstance = NULL; 323352a38012Sejakowatz 3234