1255a01c7Sbeveloper /* 234c72144SAxel Dörfler * Copyright 2008 Maurice Kalinowski, haiku@kaldience.com 3332cc6bcSAxel Dörfler * Copyright 2009-2012, Axel Dörfler, axeld@pinc-software.de. 434c72144SAxel Dörfler * 534c72144SAxel Dörfler * All rights reserved. Distributed under the terms of the MIT License. 634c72144SAxel Dörfler */ 734c72144SAxel Dörfler 834c72144SAxel 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 */ 356938364bSMaurice Kalinowski 36255a01c7Sbeveloper 37255a01c7Sbeveloper /* to comply with the license above, do not remove the following line */ 388b940bb4SStephan Aßmus char __dont_remove_copyright_from_binary[] = "Copyright (c) 2002-2006 Marcus " 398b940bb4SStephan Aßmus "Overhagen <Marcus@Overhagen.de>"; 40255a01c7Sbeveloper 419dec2310SAxel Dörfler 4252a38012Sejakowatz #include <MediaRoster.h> 438b940bb4SStephan Aßmus 44a715f908SStephan Aßmus #include <new> 45a715f908SStephan Aßmus 466938364bSMaurice Kalinowski #include <BufferConsumer.h> 476938364bSMaurice Kalinowski #include <BufferProducer.h> 4852a38012Sejakowatz #include <Locker.h> 4952a38012Sejakowatz #include <Message.h> 5052a38012Sejakowatz #include <Messenger.h> 516938364bSMaurice Kalinowski #include <MimeType.h> 5252a38012Sejakowatz #include <OS.h> 536938364bSMaurice Kalinowski #include <ParameterWeb.h> 546938364bSMaurice Kalinowski #include <StopWatch.h> 5552a38012Sejakowatz #include <String.h> 5652a38012Sejakowatz #include <TimeSource.h> 578b940bb4SStephan Aßmus 589dec2310SAxel Dörfler #include <AppMisc.h> 599dec2310SAxel Dörfler 602f9ed888SAxel Dörfler #include <debug.h> 612f9ed888SAxel Dörfler #include <DataExchange.h> 622f9ed888SAxel Dörfler #include <DormantNodeManager.h> 632f9ed888SAxel Dörfler #include <MediaRosterEx.h> 642f9ed888SAxel Dörfler #include <MediaMisc.h> 652f9ed888SAxel Dörfler #include <Notifications.h> 662f9ed888SAxel Dörfler #include <ServerInterface.h> 672f9ed888SAxel Dörfler #include <SharedBufferList.h> 682f9ed888SAxel Dörfler 69835140c8Sbeveloper #include "TimeSourceObjectManager.h" 7052a38012Sejakowatz 712f9ed888SAxel Dörfler 72f0a1eb2dSAxel Dörfler namespace BPrivate { 73f0a1eb2dSAxel Dörfler namespace media { 7452a38012Sejakowatz 75f0a1eb2dSAxel Dörfler 76f0a1eb2dSAxel Dörfler class MediaInitializer { 7752a38012Sejakowatz public: 78f0a1eb2dSAxel Dörfler MediaInitializer() 796396865dSbeveloper { 80f0a1eb2dSAxel Dörfler InitDataExchange(); 81f0a1eb2dSAxel Dörfler } 82f0a1eb2dSAxel Dörfler 83f0a1eb2dSAxel Dörfler ~MediaInitializer() 84f0a1eb2dSAxel Dörfler { 85f0a1eb2dSAxel Dörfler if (BMediaRoster::CurrentRoster() != NULL) { 86f0a1eb2dSAxel Dörfler BMediaRoster::CurrentRoster()->Lock(); 87f0a1eb2dSAxel Dörfler BMediaRoster::CurrentRoster()->Quit(); 886396865dSbeveloper } 896396865dSbeveloper } 908b04ffc1Sbeveloper }; 9152a38012Sejakowatz 92f0a1eb2dSAxel Dörfler 939dec2310SAxel Dörfler } // namespace media 949dec2310SAxel Dörfler } // namespace BPrivate 959dec2310SAxel Dörfler 968b04ffc1Sbeveloper using namespace BPrivate::media; 9752a38012Sejakowatz 989dec2310SAxel Dörfler 99f0a1eb2dSAxel Dörfler static MediaInitializer sInitializer; 10052a38012Sejakowatz 1019dec2310SAxel Dörfler 10234c72144SAxel Dörfler BMediaRosterEx::BMediaRosterEx(status_t* _error) 1039dec2310SAxel Dörfler : 1049dec2310SAxel Dörfler BMediaRoster() 105dcfb6bfcSJérôme Duval { 106f0a1eb2dSAxel Dörfler InitDataExchange(); 107f0a1eb2dSAxel Dörfler 108f0a1eb2dSAxel Dörfler gDormantNodeManager = new DormantNodeManager; 109f0a1eb2dSAxel Dörfler gTimeSourceObjectManager = new TimeSourceObjectManager; 110f0a1eb2dSAxel Dörfler 111dcfb6bfcSJérôme Duval // register this application with the media server 112dcfb6bfcSJérôme Duval server_register_app_request request; 113dcfb6bfcSJérôme Duval server_register_app_reply reply; 1149dec2310SAxel Dörfler request.team = BPrivate::current_team(); 115dcfb6bfcSJérôme Duval request.messenger = BMessenger(NULL, this); 1169dec2310SAxel Dörfler 1179dec2310SAxel Dörfler status_t status = QueryServer(SERVER_REGISTER_APP, &request, 1189dec2310SAxel Dörfler sizeof(request), &reply, sizeof(reply)); 1199dec2310SAxel Dörfler if (status != B_OK) 12034c72144SAxel Dörfler *_error = B_MEDIA_SYSTEM_FAILURE; 121a7fb4c16SMaurice Kalinowski else 12234c72144SAxel Dörfler *_error = B_OK; 123dcfb6bfcSJérôme Duval } 124dcfb6bfcSJérôme Duval 12534c72144SAxel Dörfler 1263620737cSbeveloper status_t 12754187cc6Sbeveloper BMediaRosterEx::SaveNodeConfiguration(BMediaNode* node) 12854187cc6Sbeveloper { 1299dec2310SAxel Dörfler int32 flavorID; 1309dec2310SAxel Dörfler BMediaAddOn* addon = node->AddOn(&flavorID); 1319dec2310SAxel Dörfler if (addon == NULL) { 1328056f0dbSStephan Aßmus // NOTE: This node could have been created by an application, 1338056f0dbSStephan Aßmus // it does not mean there is an error. 13434c72144SAxel Dörfler // TODO: this check incorrectly triggers on BeOS R5 BT848 node 135332cc6bcSAxel Dörfler TRACE("BMediaRosterEx::SaveNodeConfiguration node %" B_PRId32 " not " 136332cc6bcSAxel Dörfler "instantiated from BMediaAddOn!\n", node->ID()); 13754187cc6Sbeveloper return B_ERROR; 13854187cc6Sbeveloper } 1399dec2310SAxel Dörfler 1409dec2310SAxel Dörfler media_addon_id addonID = addon->AddonID(); 14154187cc6Sbeveloper 14234c72144SAxel Dörfler // TODO: fix this 1438056f0dbSStephan Aßmus printf("### BMediaRosterEx::SaveNodeConfiguration should save addon-id " 144332cc6bcSAxel Dörfler "%" B_PRId32 ", flavor-id %" B_PRId32 " config NOW!\n", addonID, 145332cc6bcSAxel Dörfler flavorID); 14654187cc6Sbeveloper return B_OK; 14754187cc6Sbeveloper } 14854187cc6Sbeveloper 14934c72144SAxel Dörfler 15054187cc6Sbeveloper status_t 1519dec2310SAxel Dörfler BMediaRosterEx::LoadNodeConfiguration(media_addon_id addonID, int32 flavorID, 1529dec2310SAxel Dörfler BMessage *_msg) 15354187cc6Sbeveloper { 15434c72144SAxel Dörfler // TODO: fix this 1559dec2310SAxel Dörfler _msg->MakeEmpty(); // to be fully R5 compliant 1568b940bb4SStephan Aßmus printf("### BMediaRosterEx::LoadNodeConfiguration should load addon-id " 157332cc6bcSAxel Dörfler "%" B_PRId32 ", flavor-id %" B_PRId32 " config NOW!\n", addonID, 158332cc6bcSAxel Dörfler flavorID); 15954187cc6Sbeveloper return B_OK; 16054187cc6Sbeveloper } 16154187cc6Sbeveloper 16234c72144SAxel Dörfler 16354187cc6Sbeveloper status_t 1649dec2310SAxel Dörfler BMediaRosterEx::IncrementAddonFlavorInstancesCount(media_addon_id addonID, 1659dec2310SAxel Dörfler int32 flavorID) 16654187cc6Sbeveloper { 1679c3b4706SAxel Dörfler server_change_flavor_instances_count_request request; 1689c3b4706SAxel Dörfler server_change_flavor_instances_count_reply reply; 16973794717Sbeveloper 1709c3b4706SAxel Dörfler request.add_on_id = addonID; 1719dec2310SAxel Dörfler request.flavor_id = flavorID; 17273794717Sbeveloper request.delta = 1; 1739dec2310SAxel Dörfler request.team = BPrivate::current_team(); 1749c3b4706SAxel Dörfler return QueryServer(SERVER_CHANGE_FLAVOR_INSTANCES_COUNT, &request, 17534c72144SAxel Dörfler sizeof(request), &reply, sizeof(reply)); 17654187cc6Sbeveloper } 17754187cc6Sbeveloper 17834c72144SAxel Dörfler 17954187cc6Sbeveloper status_t 1809dec2310SAxel Dörfler BMediaRosterEx::DecrementAddonFlavorInstancesCount(media_addon_id addonID, 1819dec2310SAxel Dörfler int32 flavorID) 18254187cc6Sbeveloper { 1839c3b4706SAxel Dörfler server_change_flavor_instances_count_request request; 1849c3b4706SAxel Dörfler server_change_flavor_instances_count_reply reply; 18573794717Sbeveloper 1869c3b4706SAxel Dörfler request.add_on_id = addonID; 1879dec2310SAxel Dörfler request.flavor_id = flavorID; 18873794717Sbeveloper request.delta = -1; 1899dec2310SAxel Dörfler request.team = BPrivate::current_team(); 1909c3b4706SAxel Dörfler return QueryServer(SERVER_CHANGE_FLAVOR_INSTANCES_COUNT, &request, 19134c72144SAxel Dörfler sizeof(request), &reply, sizeof(reply)); 19254187cc6Sbeveloper } 19354187cc6Sbeveloper 19434c72144SAxel Dörfler 19554187cc6Sbeveloper status_t 1966aee58a4SJérôme Duval BMediaRosterEx::ReleaseNodeAll(const media_node& node) 1976aee58a4SJérôme Duval { 1986aee58a4SJérôme Duval CALLED(); 1996aee58a4SJérôme Duval if (IS_INVALID_NODE(node)) 2006aee58a4SJérôme Duval return B_MEDIA_BAD_NODE; 2016aee58a4SJérôme Duval 2026aee58a4SJérôme Duval if (node.kind & NODE_KIND_NO_REFCOUNTING) { 2036aee58a4SJérôme Duval printf("BMediaRoster::ReleaseNodeAll, trying to release reference " 204332cc6bcSAxel Dörfler "counting disabled timesource, node %" B_PRId32 ", port %" B_PRId32 205332cc6bcSAxel Dörfler ", team %" B_PRId32 "\n", 2066aee58a4SJérôme Duval node.node, node.port, BPrivate::current_team()); 2076aee58a4SJérôme Duval return B_OK; 2086aee58a4SJérôme Duval } 2096aee58a4SJérôme Duval 2106aee58a4SJérôme Duval server_release_node_request request; 2116aee58a4SJérôme Duval server_release_node_reply reply; 2126aee58a4SJérôme Duval status_t rv; 2136aee58a4SJérôme Duval 2146aee58a4SJérôme Duval request.node = node; 2156aee58a4SJérôme Duval request.team = BPrivate::current_team(); 2166aee58a4SJérôme Duval 217332cc6bcSAxel Dörfler TRACE("BMediaRoster::ReleaseNodeAll, node %" B_PRId32 ", port %" B_PRId32 218332cc6bcSAxel Dörfler ", team %" B_PRId32 "\n", 2196aee58a4SJérôme Duval node.node, node.port, BPrivate::current_team()); 2206aee58a4SJérôme Duval 2216aee58a4SJérôme Duval rv = QueryServer(SERVER_RELEASE_NODE_ALL, &request, sizeof(request), &reply, 2226aee58a4SJérôme Duval sizeof(reply)); 2236aee58a4SJérôme Duval if (rv != B_OK) { 224c74afb57SJérôme Duval ERROR("BMediaRoster::ReleaseNodeAll failed to query media_server, " 225c74afb57SJérôme Duval "retrying local, node %" B_PRId32 ", port %" 226c74afb57SJérôme Duval B_PRId32 ", team %" B_PRId32 "!\n", node.node, node.port, 227c74afb57SJérôme Duval BPrivate::current_team()); 228c74afb57SJérôme Duval node_final_release_command command; 229c74afb57SJérôme Duval rv = SendToPort(node.port, NODE_FINAL_RELEASE, &command, 230c74afb57SJérôme Duval sizeof(command)); 231c74afb57SJérôme Duval if (rv != B_OK) { 232332cc6bcSAxel Dörfler ERROR("BMediaRoster::ReleaseNodeAll FAILED, node %" B_PRId32 ", port %" 233332cc6bcSAxel Dörfler B_PRId32 ", team %" B_PRId32 "!\n", node.node, node.port, 234332cc6bcSAxel Dörfler BPrivate::current_team()); 2356aee58a4SJérôme Duval } 236c74afb57SJérôme Duval } 2376aee58a4SJérôme Duval return rv; 2386aee58a4SJérôme Duval } 2396aee58a4SJérôme Duval 2406aee58a4SJérôme Duval 2416aee58a4SJérôme Duval status_t 24254187cc6Sbeveloper BMediaRosterEx::SetNodeCreator(media_node_id node, team_id creator) 24354187cc6Sbeveloper { 24454187cc6Sbeveloper server_set_node_creator_request request; 24554187cc6Sbeveloper server_set_node_creator_reply reply; 24654187cc6Sbeveloper 24754187cc6Sbeveloper request.node = node; 24854187cc6Sbeveloper request.creator = creator; 24934c72144SAxel Dörfler return QueryServer(SERVER_SET_NODE_CREATOR, &request, sizeof(request), 25034c72144SAxel Dörfler &reply, sizeof(reply)); 25154187cc6Sbeveloper } 25254187cc6Sbeveloper 25334c72144SAxel Dörfler 25454187cc6Sbeveloper status_t 25534c72144SAxel Dörfler BMediaRosterEx::GetNode(node_type type, media_node* out_node, 25634c72144SAxel Dörfler int32* out_input_id, BString* out_input_name) 25752a38012Sejakowatz { 25852a38012Sejakowatz if (out_node == NULL) 25952a38012Sejakowatz return B_BAD_VALUE; 26052a38012Sejakowatz 2618c6a6096Sbeveloper server_get_node_request request; 2628c6a6096Sbeveloper server_get_node_reply reply; 26352a38012Sejakowatz status_t rv; 26452a38012Sejakowatz 2658c6a6096Sbeveloper request.type = type; 2669dec2310SAxel Dörfler request.team = BPrivate::current_team(); 26734c72144SAxel Dörfler rv = QueryServer(SERVER_GET_NODE, &request, sizeof(request), &reply, 26834c72144SAxel Dörfler sizeof(reply)); 2698c6a6096Sbeveloper if (rv != B_OK) 2708c6a6096Sbeveloper return rv; 27152a38012Sejakowatz 27252a38012Sejakowatz *out_node = reply.node; 27352a38012Sejakowatz if (out_input_id) 27452a38012Sejakowatz *out_input_id = reply.input_id; 27552a38012Sejakowatz if (out_input_name) 27652a38012Sejakowatz *out_input_name = reply.input_name; 2778c6a6096Sbeveloper return rv; 27852a38012Sejakowatz } 27952a38012Sejakowatz 28034c72144SAxel Dörfler 2813620737cSbeveloper status_t 28234c72144SAxel Dörfler BMediaRosterEx::SetNode(node_type type, const media_node* node, 28334c72144SAxel Dörfler const dormant_node_info* info, const media_input* input) 28452a38012Sejakowatz { 2858c6a6096Sbeveloper server_set_node_request request; 2868c6a6096Sbeveloper server_set_node_reply reply; 28752a38012Sejakowatz 2888c6a6096Sbeveloper request.type = type; 28934c72144SAxel Dörfler request.use_node = node != NULL; 29034c72144SAxel Dörfler if (node != NULL) 2918c6a6096Sbeveloper request.node = *node; 29234c72144SAxel Dörfler request.use_dni = info != NULL; 29334c72144SAxel Dörfler if (info != NULL) 2948c6a6096Sbeveloper request.dni = *info; 29534c72144SAxel Dörfler request.use_input = input != NULL; 29634c72144SAxel Dörfler if (input != NULL) 2978c6a6096Sbeveloper request.input = *input; 29852a38012Sejakowatz 29934c72144SAxel Dörfler return QueryServer(SERVER_SET_NODE, &request, sizeof(request), &reply, 30034c72144SAxel Dörfler sizeof(reply)); 30152a38012Sejakowatz } 30252a38012Sejakowatz 30334c72144SAxel Dörfler 3043620737cSbeveloper status_t 3058b04ffc1Sbeveloper BMediaRosterEx::GetAllOutputs(const media_node& node, List<media_output>* list) 3063620737cSbeveloper { 3073620737cSbeveloper int32 cookie; 3083620737cSbeveloper status_t rv; 3093620737cSbeveloper status_t result; 3103620737cSbeveloper 311332cc6bcSAxel Dörfler PRINT(4, "BMediaRosterEx::GetAllOutputs() node %" B_PRId32 ", port %" 312332cc6bcSAxel Dörfler B_PRId32 "\n", node.node, node.port); 3135ac4fbd7Sbeveloper 31465b73ae4SMarcus Overhagen if (!(node.kind & B_BUFFER_PRODUCER)) { 315332cc6bcSAxel Dörfler ERROR("BMediaRosterEx::GetAllOutputs: node %" B_PRId32 " is not a " 31634c72144SAxel Dörfler "B_BUFFER_PRODUCER\n", node.node); 31765b73ae4SMarcus Overhagen return B_MEDIA_BAD_NODE; 31865b73ae4SMarcus Overhagen } 31965b73ae4SMarcus Overhagen 3203620737cSbeveloper result = B_OK; 3213620737cSbeveloper cookie = 0; 32276669a29Sbeveloper list->MakeEmpty(); 3233620737cSbeveloper for (;;) { 3243620737cSbeveloper producer_get_next_output_request request; 3253620737cSbeveloper producer_get_next_output_reply reply; 3263620737cSbeveloper request.cookie = cookie; 32734c72144SAxel Dörfler rv = QueryPort(node.port, PRODUCER_GET_NEXT_OUTPUT, &request, 32834c72144SAxel Dörfler sizeof(request), &reply, sizeof(reply)); 3293620737cSbeveloper if (rv != B_OK) 3303620737cSbeveloper break; 3313620737cSbeveloper cookie = reply.cookie; 33276669a29Sbeveloper if (!list->Insert(reply.output)) { 3335ac4fbd7Sbeveloper ERROR("GetAllOutputs: list->Insert failed\n"); 3343620737cSbeveloper result = B_ERROR; 3353620737cSbeveloper } 3365ac4fbd7Sbeveloper #if DEBUG >= 3 337332cc6bcSAxel Dörfler PRINT(3," next cookie %" B_PRId32 ", ", cookie); 3385ac4fbd7Sbeveloper PRINT_OUTPUT("output ", reply.output); 3395ac4fbd7Sbeveloper #endif 3403620737cSbeveloper } 3413620737cSbeveloper 3423620737cSbeveloper producer_dispose_output_cookie_request request; 3433620737cSbeveloper producer_dispose_output_cookie_reply reply; 34434c72144SAxel Dörfler QueryPort(node.port, PRODUCER_DISPOSE_OUTPUT_COOKIE, &request, 34534c72144SAxel Dörfler sizeof(request), &reply, sizeof(reply)); 3463620737cSbeveloper 3473620737cSbeveloper return result; 3483620737cSbeveloper } 3493620737cSbeveloper 35034c72144SAxel Dörfler 3513620737cSbeveloper status_t 3524d2d96e0Sbeveloper BMediaRosterEx::GetAllOutputs(BBufferProducer* node, List<media_output>* list) 3534d2d96e0Sbeveloper { 3544d2d96e0Sbeveloper int32 cookie; 3554d2d96e0Sbeveloper status_t result; 3564d2d96e0Sbeveloper 357332cc6bcSAxel Dörfler PRINT(4, "BMediaRosterEx::GetAllOutputs() (by pointer) node %" B_PRId32 358332cc6bcSAxel Dörfler ", port %" B_PRId32 "\n", node->ID(), node->ControlPort()); 3594d2d96e0Sbeveloper 3604d2d96e0Sbeveloper result = B_OK; 3614d2d96e0Sbeveloper cookie = 0; 3624d2d96e0Sbeveloper list->MakeEmpty(); 3634d2d96e0Sbeveloper for (;;) { 3644d2d96e0Sbeveloper media_output output; 3654d2d96e0Sbeveloper if (B_OK != node->GetNextOutput(&cookie, &output)) 3664d2d96e0Sbeveloper break; 3674d2d96e0Sbeveloper if (!list->Insert(output)) { 3684d2d96e0Sbeveloper ERROR("GetAllOutputs: list->Insert failed\n"); 3694d2d96e0Sbeveloper result = B_ERROR; 3704d2d96e0Sbeveloper } 3714d2d96e0Sbeveloper #if DEBUG >= 3 372332cc6bcSAxel Dörfler PRINT(3," next cookie %" B_PRId32 ", ", cookie); 3734d2d96e0Sbeveloper PRINT_OUTPUT("output ", output); 3744d2d96e0Sbeveloper #endif 3754d2d96e0Sbeveloper } 3764d2d96e0Sbeveloper node->DisposeOutputCookie(cookie); 3774d2d96e0Sbeveloper return result; 3784d2d96e0Sbeveloper } 3794d2d96e0Sbeveloper 38034c72144SAxel Dörfler 3814d2d96e0Sbeveloper status_t 3828b04ffc1Sbeveloper BMediaRosterEx::GetAllInputs(const media_node& node, List<media_input>* list) 3833620737cSbeveloper { 3843620737cSbeveloper int32 cookie; 3853620737cSbeveloper status_t rv; 3863620737cSbeveloper status_t result; 3873620737cSbeveloper 388332cc6bcSAxel Dörfler PRINT(4, "BMediaRosterEx::GetAllInputs() node %" B_PRId32 ", port %" 389332cc6bcSAxel Dörfler B_PRId32 "\n", node.node, node.port); 3905ac4fbd7Sbeveloper 39165b73ae4SMarcus Overhagen if (!(node.kind & B_BUFFER_CONSUMER)) { 392332cc6bcSAxel Dörfler ERROR("BMediaRosterEx::GetAllInputs: node %" B_PRId32 " is not a " 39334c72144SAxel Dörfler "B_BUFFER_CONSUMER\n", node.node); 39465b73ae4SMarcus Overhagen return B_MEDIA_BAD_NODE; 39565b73ae4SMarcus Overhagen } 39665b73ae4SMarcus Overhagen 3973620737cSbeveloper result = B_OK; 3983620737cSbeveloper cookie = 0; 39976669a29Sbeveloper list->MakeEmpty(); 4003620737cSbeveloper for (;;) { 4013620737cSbeveloper consumer_get_next_input_request request; 4023620737cSbeveloper consumer_get_next_input_reply reply; 4033620737cSbeveloper request.cookie = cookie; 40434c72144SAxel Dörfler rv = QueryPort(node.port, CONSUMER_GET_NEXT_INPUT, &request, 40534c72144SAxel Dörfler sizeof(request), &reply, sizeof(reply)); 4063620737cSbeveloper if (rv != B_OK) 4073620737cSbeveloper break; 4083620737cSbeveloper cookie = reply.cookie; 40976669a29Sbeveloper if (!list->Insert(reply.input)) { 4105ac4fbd7Sbeveloper ERROR("GetAllInputs: list->Insert failed\n"); 4113620737cSbeveloper result = B_ERROR; 4123620737cSbeveloper } 4135ac4fbd7Sbeveloper #if DEBUG >= 3 414332cc6bcSAxel Dörfler PRINT(3," next cookie %" B_PRId32 ", ", cookie); 4155ac4fbd7Sbeveloper PRINT_OUTPUT("input ", reply.input); 4165ac4fbd7Sbeveloper #endif 4173620737cSbeveloper } 4183620737cSbeveloper 4193620737cSbeveloper consumer_dispose_input_cookie_request request; 4203620737cSbeveloper consumer_dispose_input_cookie_reply reply; 42134c72144SAxel Dörfler QueryPort(node.port, CONSUMER_DISPOSE_INPUT_COOKIE, &request, 42234c72144SAxel Dörfler sizeof(request), &reply, sizeof(reply)); 4233620737cSbeveloper 4243620737cSbeveloper return result; 4253620737cSbeveloper } 4263620737cSbeveloper 42734c72144SAxel Dörfler 4283620737cSbeveloper status_t 4294d2d96e0Sbeveloper BMediaRosterEx::GetAllInputs(BBufferConsumer* node, List<media_input>* list) 4304d2d96e0Sbeveloper { 4314d2d96e0Sbeveloper int32 cookie; 4324d2d96e0Sbeveloper status_t result; 4334d2d96e0Sbeveloper 434332cc6bcSAxel Dörfler PRINT(4, "BMediaRosterEx::GetAllInputs() (by pointer) node %" B_PRId32 435332cc6bcSAxel Dörfler ", port %" B_PRId32 "\n", node->ID(), node->ControlPort()); 4364d2d96e0Sbeveloper 4374d2d96e0Sbeveloper result = B_OK; 4384d2d96e0Sbeveloper cookie = 0; 4394d2d96e0Sbeveloper list->MakeEmpty(); 4404d2d96e0Sbeveloper for (;;) { 4414d2d96e0Sbeveloper media_input input; 4424d2d96e0Sbeveloper if (B_OK != node->GetNextInput(&cookie, &input)) 4434d2d96e0Sbeveloper break; 4444d2d96e0Sbeveloper if (!list->Insert(input)) { 4454d2d96e0Sbeveloper ERROR("GetAllInputs: list->Insert failed\n"); 4464d2d96e0Sbeveloper result = B_ERROR; 4474d2d96e0Sbeveloper } 4484d2d96e0Sbeveloper #if DEBUG >= 3 449332cc6bcSAxel Dörfler PRINT(3," next cookie %" B_PRId32 ", ", cookie); 4504d2d96e0Sbeveloper PRINT_INPUT("input ", input); 4514d2d96e0Sbeveloper #endif 4524d2d96e0Sbeveloper } 4534d2d96e0Sbeveloper node->DisposeInputCookie(cookie); 4544d2d96e0Sbeveloper return result; 4554d2d96e0Sbeveloper } 4564d2d96e0Sbeveloper 45734c72144SAxel Dörfler 4584d2d96e0Sbeveloper status_t 4598b04ffc1Sbeveloper BMediaRosterEx::PublishOutputs(const media_node& node, List<media_output>* list) 4603620737cSbeveloper { 4613620737cSbeveloper server_publish_outputs_request request; 4623620737cSbeveloper server_publish_outputs_reply reply; 4633620737cSbeveloper media_output* output; 4643620737cSbeveloper media_output* outputs; 4653620737cSbeveloper int32 count; 466a7b41a96Sbeveloper status_t rv; 4673620737cSbeveloper 46876669a29Sbeveloper count = list->CountItems(); 469332cc6bcSAxel Dörfler TRACE("PublishOutputs: publishing %" B_PRId32 "\n", count); 4703620737cSbeveloper 4713620737cSbeveloper request.node = node; 4723620737cSbeveloper request.count = count; 4733620737cSbeveloper if (count > MAX_OUTPUTS) { 4743620737cSbeveloper void *start_addr; 4753620737cSbeveloper size_t size; 47640f36b03Sbeveloper size = ROUND_UP_TO_PAGE(count * sizeof(media_output)); 47734c72144SAxel Dörfler request.area = create_area("publish outputs", &start_addr, 47834c72144SAxel Dörfler B_ANY_ADDRESS, size, B_NO_LOCK, B_READ_AREA | B_WRITE_AREA); 4793620737cSbeveloper if (request.area < B_OK) { 480332cc6bcSAxel Dörfler ERROR("PublishOutputs: failed to create area, %#" B_PRIx32 "\n", 48134c72144SAxel Dörfler request.area); 4823620737cSbeveloper return (status_t)request.area; 4833620737cSbeveloper } 4843620737cSbeveloper outputs = static_cast<media_output *>(start_addr); 4853620737cSbeveloper } else { 4863620737cSbeveloper request.area = -1; 4873620737cSbeveloper outputs = request.outputs; 4883620737cSbeveloper } 489332cc6bcSAxel Dörfler TRACE("PublishOutputs: area %" B_PRId32 "\n", request.area); 4903620737cSbeveloper 49176669a29Sbeveloper int i; 49276669a29Sbeveloper for (i = 0, list->Rewind(); list->GetNext(&output); i++) { 49376669a29Sbeveloper ASSERT(i < count); 4943620737cSbeveloper outputs[i] = *output; 4953620737cSbeveloper } 4963620737cSbeveloper 49734c72144SAxel Dörfler rv = QueryServer(SERVER_PUBLISH_OUTPUTS, &request, sizeof(request), 49834c72144SAxel Dörfler &reply, sizeof(reply)); 499a7b41a96Sbeveloper 500a7b41a96Sbeveloper if (request.area != -1) 501a7b41a96Sbeveloper delete_area(request.area); 502a7b41a96Sbeveloper 503a7b41a96Sbeveloper return rv; 5043620737cSbeveloper } 5053620737cSbeveloper 50634c72144SAxel Dörfler 5073620737cSbeveloper status_t 5088b04ffc1Sbeveloper BMediaRosterEx::PublishInputs(const media_node& node, List<media_input>* list) 5093620737cSbeveloper { 5103620737cSbeveloper server_publish_inputs_request request; 5113620737cSbeveloper server_publish_inputs_reply reply; 5123620737cSbeveloper media_input* input; 5133620737cSbeveloper media_input* inputs; 5143620737cSbeveloper int32 count; 515a7b41a96Sbeveloper status_t rv; 5163620737cSbeveloper 51776669a29Sbeveloper count = list->CountItems(); 518332cc6bcSAxel Dörfler TRACE("PublishInputs: publishing %" B_PRId32 "\n", count); 5193620737cSbeveloper 5203620737cSbeveloper request.node = node; 5213620737cSbeveloper request.count = count; 5223620737cSbeveloper if (count > MAX_INPUTS) { 5233620737cSbeveloper void* start_addr; 5243620737cSbeveloper size_t size; 52540f36b03Sbeveloper size = ROUND_UP_TO_PAGE(count * sizeof(media_input)); 52634c72144SAxel Dörfler request.area = create_area("publish inputs", &start_addr, 52734c72144SAxel Dörfler B_ANY_ADDRESS, size, B_NO_LOCK, B_READ_AREA | B_WRITE_AREA); 5283620737cSbeveloper if (request.area < B_OK) { 529332cc6bcSAxel Dörfler ERROR("PublishInputs: failed to create area, %#" B_PRIx32 "\n", 530332cc6bcSAxel Dörfler request.area); 5313620737cSbeveloper return (status_t)request.area; 5323620737cSbeveloper } 5333620737cSbeveloper inputs = static_cast<media_input *>(start_addr); 5343620737cSbeveloper } else { 5353620737cSbeveloper request.area = -1; 5363620737cSbeveloper inputs = request.inputs; 5373620737cSbeveloper } 538332cc6bcSAxel Dörfler TRACE("PublishInputs: area %" B_PRId32 "\n", request.area); 5393620737cSbeveloper 54076669a29Sbeveloper int i; 54176669a29Sbeveloper for (i = 0, list->Rewind(); list->GetNext(&input); i++) { 54276669a29Sbeveloper ASSERT(i < count); 5433620737cSbeveloper inputs[i] = *input; 5443620737cSbeveloper } 5453620737cSbeveloper 54634c72144SAxel Dörfler rv = QueryServer(SERVER_PUBLISH_INPUTS, &request, sizeof(request), 54734c72144SAxel Dörfler &reply, sizeof(reply)); 548a7b41a96Sbeveloper 549a7b41a96Sbeveloper if (request.area != -1) 550a7b41a96Sbeveloper delete_area(request.area); 551a7b41a96Sbeveloper 552a7b41a96Sbeveloper return rv; 5533620737cSbeveloper } 5543620737cSbeveloper 55534c72144SAxel Dörfler 55634c72144SAxel Dörfler BTimeSource* 557f4ec236cSAxel Dörfler BMediaRosterEx::MakeTimeSourceObject(media_node_id timeSourceID) 55834c72144SAxel Dörfler { 55934c72144SAxel Dörfler media_node clone; 560f4ec236cSAxel Dörfler status_t status = GetNodeFor(timeSourceID, &clone); 561f4ec236cSAxel Dörfler if (status != B_OK) { 562f4ec236cSAxel Dörfler ERROR("BMediaRosterEx::MakeTimeSourceObject: GetNodeFor failed: %s\n", 563f4ec236cSAxel Dörfler strerror(status)); 56434c72144SAxel Dörfler return NULL; 56534c72144SAxel Dörfler } 56634c72144SAxel Dörfler 567f4ec236cSAxel Dörfler BTimeSource* source = gTimeSourceObjectManager->GetTimeSource(clone); 56834c72144SAxel Dörfler if (source == NULL) { 56934c72144SAxel Dörfler ERROR("BMediaRosterEx::MakeTimeSourceObject: GetTimeSource failed\n"); 57034c72144SAxel Dörfler return NULL; 57134c72144SAxel Dörfler } 57234c72144SAxel Dörfler 57334c72144SAxel Dörfler // TODO: release? 57434c72144SAxel Dörfler ReleaseNode(clone); 57534c72144SAxel Dörfler 57634c72144SAxel Dörfler return source; 57734c72144SAxel Dörfler } 57834c72144SAxel Dörfler 57934c72144SAxel Dörfler 58034c72144SAxel Dörfler // #pragma mark - public BMediaRoster 58134c72144SAxel Dörfler 58252a38012Sejakowatz 58352a38012Sejakowatz status_t 58434c72144SAxel Dörfler BMediaRoster::GetVideoInput(media_node* _node) 58552a38012Sejakowatz { 58652a38012Sejakowatz CALLED(); 58734c72144SAxel Dörfler return MediaRosterEx(this)->GetNode(VIDEO_INPUT, _node); 58852a38012Sejakowatz } 58952a38012Sejakowatz 59052a38012Sejakowatz 59152a38012Sejakowatz status_t 59234c72144SAxel Dörfler BMediaRoster::GetAudioInput(media_node* _node) 59352a38012Sejakowatz { 59452a38012Sejakowatz CALLED(); 59534c72144SAxel Dörfler return MediaRosterEx(this)->GetNode(AUDIO_INPUT, _node); 59652a38012Sejakowatz } 59752a38012Sejakowatz 59852a38012Sejakowatz 59952a38012Sejakowatz status_t 60034c72144SAxel Dörfler BMediaRoster::GetVideoOutput(media_node* _node) 60152a38012Sejakowatz { 60252a38012Sejakowatz CALLED(); 60334c72144SAxel Dörfler return MediaRosterEx(this)->GetNode(VIDEO_OUTPUT, _node); 60452a38012Sejakowatz } 60552a38012Sejakowatz 60652a38012Sejakowatz 60752a38012Sejakowatz status_t 60834c72144SAxel Dörfler BMediaRoster::GetAudioMixer(media_node* _node) 60952a38012Sejakowatz { 61052a38012Sejakowatz CALLED(); 61134c72144SAxel Dörfler return MediaRosterEx(this)->GetNode(AUDIO_MIXER, _node); 61252a38012Sejakowatz } 61352a38012Sejakowatz 61452a38012Sejakowatz 61552a38012Sejakowatz status_t 61634c72144SAxel Dörfler BMediaRoster::GetAudioOutput(media_node* _node) 61752a38012Sejakowatz { 61852a38012Sejakowatz CALLED(); 61934c72144SAxel Dörfler return MediaRosterEx(this)->GetNode(AUDIO_OUTPUT, _node); 62052a38012Sejakowatz } 62152a38012Sejakowatz 62252a38012Sejakowatz 62352a38012Sejakowatz status_t 62434c72144SAxel Dörfler BMediaRoster::GetAudioOutput(media_node* _node, int32* _inputID, 62534c72144SAxel Dörfler BString* _inputName) 62652a38012Sejakowatz { 62752a38012Sejakowatz CALLED(); 62834c72144SAxel Dörfler return MediaRosterEx(this)->GetNode(AUDIO_OUTPUT_EX, _node, _inputID, 62934c72144SAxel Dörfler _inputName); 63052a38012Sejakowatz } 63152a38012Sejakowatz 63252a38012Sejakowatz 63352a38012Sejakowatz status_t 63434c72144SAxel Dörfler BMediaRoster::GetTimeSource(media_node* _node) 63552a38012Sejakowatz { 63652a38012Sejakowatz CALLED(); 63786bce45bSbeveloper status_t rv; 63886bce45bSbeveloper 63934c72144SAxel Dörfler // TODO: need to do this in a nicer way. 64086bce45bSbeveloper 64134c72144SAxel Dörfler rv = MediaRosterEx(this)->GetNode(TIME_SOURCE, _node); 64286bce45bSbeveloper if (rv != B_OK) 64386bce45bSbeveloper return rv; 64486bce45bSbeveloper 64586bce45bSbeveloper // We don't do reference counting for timesources, that's why we 64686bce45bSbeveloper // release the node immediately. 64734c72144SAxel Dörfler ReleaseNode(*_node); 64886bce45bSbeveloper 64986bce45bSbeveloper // we need to remember to not use this node with server side reference counting 65034c72144SAxel Dörfler _node->kind |= NODE_KIND_NO_REFCOUNTING; 65186bce45bSbeveloper return B_OK; 65252a38012Sejakowatz } 65352a38012Sejakowatz 65452a38012Sejakowatz 65552a38012Sejakowatz status_t 65652a38012Sejakowatz BMediaRoster::SetVideoInput(const media_node& producer) 65752a38012Sejakowatz { 65852a38012Sejakowatz CALLED(); 6598b04ffc1Sbeveloper return MediaRosterEx(this)->SetNode(VIDEO_INPUT, &producer); 66052a38012Sejakowatz } 66152a38012Sejakowatz 66252a38012Sejakowatz 66352a38012Sejakowatz status_t 66452a38012Sejakowatz BMediaRoster::SetVideoInput(const dormant_node_info& producer) 66552a38012Sejakowatz { 66652a38012Sejakowatz CALLED(); 6678b04ffc1Sbeveloper return MediaRosterEx(this)->SetNode(VIDEO_INPUT, NULL, &producer); 66852a38012Sejakowatz } 66952a38012Sejakowatz 67052a38012Sejakowatz 67152a38012Sejakowatz status_t 67252a38012Sejakowatz BMediaRoster::SetAudioInput(const media_node& producer) 67352a38012Sejakowatz { 67452a38012Sejakowatz CALLED(); 6758b04ffc1Sbeveloper return MediaRosterEx(this)->SetNode(AUDIO_INPUT, &producer); 67652a38012Sejakowatz } 67752a38012Sejakowatz 67852a38012Sejakowatz 67952a38012Sejakowatz status_t 68052a38012Sejakowatz BMediaRoster::SetAudioInput(const dormant_node_info& producer) 68152a38012Sejakowatz { 68252a38012Sejakowatz CALLED(); 6838b04ffc1Sbeveloper return MediaRosterEx(this)->SetNode(AUDIO_INPUT, NULL, &producer); 68452a38012Sejakowatz } 68552a38012Sejakowatz 68652a38012Sejakowatz 68752a38012Sejakowatz status_t 68852a38012Sejakowatz BMediaRoster::SetVideoOutput(const media_node& consumer) 68952a38012Sejakowatz { 69052a38012Sejakowatz CALLED(); 6918b04ffc1Sbeveloper return MediaRosterEx(this)->SetNode(VIDEO_OUTPUT, &consumer); 69252a38012Sejakowatz } 69352a38012Sejakowatz 69452a38012Sejakowatz 69552a38012Sejakowatz status_t 69652a38012Sejakowatz BMediaRoster::SetVideoOutput(const dormant_node_info& consumer) 69752a38012Sejakowatz { 69852a38012Sejakowatz CALLED(); 6998b04ffc1Sbeveloper return MediaRosterEx(this)->SetNode(VIDEO_OUTPUT, NULL, &consumer); 70052a38012Sejakowatz } 70152a38012Sejakowatz 70252a38012Sejakowatz 70352a38012Sejakowatz status_t 70452a38012Sejakowatz BMediaRoster::SetAudioOutput(const media_node& consumer) 70552a38012Sejakowatz { 70652a38012Sejakowatz CALLED(); 7078b04ffc1Sbeveloper return MediaRosterEx(this)->SetNode(AUDIO_OUTPUT, &consumer); 70852a38012Sejakowatz } 70952a38012Sejakowatz 71052a38012Sejakowatz 71152a38012Sejakowatz status_t 71234c72144SAxel Dörfler BMediaRoster::SetAudioOutput(const media_input& input) 71352a38012Sejakowatz { 71452a38012Sejakowatz CALLED(); 71534c72144SAxel Dörfler return MediaRosterEx(this)->SetNode(AUDIO_OUTPUT, NULL, NULL, &input); 71652a38012Sejakowatz } 71752a38012Sejakowatz 71852a38012Sejakowatz 71952a38012Sejakowatz status_t 72052a38012Sejakowatz BMediaRoster::SetAudioOutput(const dormant_node_info& consumer) 72152a38012Sejakowatz { 72252a38012Sejakowatz CALLED(); 7238b04ffc1Sbeveloper return MediaRosterEx(this)->SetNode(AUDIO_OUTPUT, NULL, &consumer); 72452a38012Sejakowatz } 72552a38012Sejakowatz 72652a38012Sejakowatz 72752a38012Sejakowatz status_t 72834c72144SAxel Dörfler BMediaRoster::GetNodeFor(media_node_id node, media_node* clone) 72952a38012Sejakowatz { 7309e9417d2Sbeveloper CALLED(); 7319e9417d2Sbeveloper if (clone == NULL) 7329e9417d2Sbeveloper return B_BAD_VALUE; 73365b73ae4SMarcus Overhagen if (IS_INVALID_NODEID(node)) 7349e9417d2Sbeveloper return B_MEDIA_BAD_NODE; 7359e9417d2Sbeveloper 7369e9417d2Sbeveloper server_get_node_for_request request; 7379e9417d2Sbeveloper server_get_node_for_reply reply; 7389e9417d2Sbeveloper status_t rv; 7399e9417d2Sbeveloper 7409dec2310SAxel Dörfler request.node_id = node; 7419dec2310SAxel Dörfler request.team = BPrivate::current_team(); 7429e9417d2Sbeveloper 74334c72144SAxel Dörfler rv = QueryServer(SERVER_GET_NODE_FOR, &request, sizeof(request), &reply, 74434c72144SAxel Dörfler sizeof(reply)); 7459e9417d2Sbeveloper if (rv != B_OK) 7469e9417d2Sbeveloper return rv; 7479e9417d2Sbeveloper 7489e9417d2Sbeveloper *clone = reply.clone; 7499e9417d2Sbeveloper return B_OK; 75052a38012Sejakowatz } 75152a38012Sejakowatz 75252a38012Sejakowatz 75352a38012Sejakowatz status_t 75452a38012Sejakowatz BMediaRoster::GetSystemTimeSource(media_node* clone) 75552a38012Sejakowatz { 75652a38012Sejakowatz CALLED(); 75786bce45bSbeveloper status_t rv; 75886bce45bSbeveloper 75934c72144SAxel Dörfler // TODO: need to do this in a nicer way. 76086bce45bSbeveloper 76186bce45bSbeveloper rv = MediaRosterEx(this)->GetNode(SYSTEM_TIME_SOURCE, clone); 76286bce45bSbeveloper if (rv != B_OK) 76386bce45bSbeveloper return rv; 76486bce45bSbeveloper 76586bce45bSbeveloper // We don't do reference counting for timesources, that's why we 76686bce45bSbeveloper // release the node immediately. 76786bce45bSbeveloper ReleaseNode(*clone); 76886bce45bSbeveloper 76934c72144SAxel Dörfler // we need to remember to not use this node with server side reference 77034c72144SAxel Dörfler // counting 77186bce45bSbeveloper clone->kind |= NODE_KIND_NO_REFCOUNTING; 77286bce45bSbeveloper 77386bce45bSbeveloper return B_OK; 77452a38012Sejakowatz } 77552a38012Sejakowatz 77652a38012Sejakowatz 77752a38012Sejakowatz status_t 77852a38012Sejakowatz BMediaRoster::ReleaseNode(const media_node& node) 77952a38012Sejakowatz { 7809e9417d2Sbeveloper CALLED(); 78140f36b03Sbeveloper if (IS_INVALID_NODE(node)) 7829e9417d2Sbeveloper return B_MEDIA_BAD_NODE; 78352a38012Sejakowatz 78486bce45bSbeveloper if (node.kind & NODE_KIND_NO_REFCOUNTING) { 78534c72144SAxel Dörfler printf("BMediaRoster::ReleaseNode, trying to release reference " 786332cc6bcSAxel Dörfler "counting disabled timesource, node %" B_PRId32 ", port %" B_PRId32 787332cc6bcSAxel Dörfler ", team %" B_PRId32 "\n", node.node, node.port, 788332cc6bcSAxel Dörfler BPrivate::current_team()); 78986bce45bSbeveloper return B_OK; 79086bce45bSbeveloper } 79186bce45bSbeveloper 7929e9417d2Sbeveloper server_release_node_request request; 7939e9417d2Sbeveloper server_release_node_reply reply; 794cf4e2277Sbeveloper status_t rv; 7959e9417d2Sbeveloper 7969e9417d2Sbeveloper request.node = node; 7979dec2310SAxel Dörfler request.team = BPrivate::current_team(); 7989e9417d2Sbeveloper 799332cc6bcSAxel Dörfler TRACE("BMediaRoster::ReleaseNode, node %" B_PRId32 ", port %" B_PRId32 800332cc6bcSAxel Dörfler ", team %" B_PRId32 "\n", node.node, node.port, 801332cc6bcSAxel Dörfler BPrivate::current_team()); 802cf4e2277Sbeveloper 80334c72144SAxel Dörfler rv = QueryServer(SERVER_RELEASE_NODE, &request, sizeof(request), &reply, 80434c72144SAxel Dörfler sizeof(reply)); 805cf4e2277Sbeveloper if (rv != B_OK) { 806332cc6bcSAxel Dörfler ERROR("BMediaRoster::ReleaseNode FAILED, node %" B_PRId32 ", port %" 807332cc6bcSAxel Dörfler B_PRId32 ", team %" B_PRId32 "!\n", node.node, node.port, 808332cc6bcSAxel Dörfler BPrivate::current_team()); 809cf4e2277Sbeveloper } 810cf4e2277Sbeveloper return rv; 8119e9417d2Sbeveloper } 81252a38012Sejakowatz 81334c72144SAxel Dörfler 81452a38012Sejakowatz BTimeSource* 81534c72144SAxel Dörfler BMediaRoster::MakeTimeSourceFor(const media_node& forNode) 81652a38012Sejakowatz { 817f180ef79Sbeveloper // MakeTimeSourceFor() returns a BTimeSource object 818f180ef79Sbeveloper // corresponding to the specified node's time source. 819f180ef79Sbeveloper 820835140c8Sbeveloper CALLED(); 821f180ef79Sbeveloper 82234c72144SAxel Dörfler if (IS_SYSTEM_TIMESOURCE(forNode)) { 823f180ef79Sbeveloper // special handling for the system time source 82434c72144SAxel Dörfler TRACE("BMediaRoster::MakeTimeSourceFor, asked for system time " 82534c72144SAxel Dörfler "source\n"); 82634c72144SAxel Dörfler return MediaRosterEx(this)->MakeTimeSourceObject( 82734c72144SAxel Dörfler NODE_SYSTEM_TIMESOURCE_ID); 828f180ef79Sbeveloper } 829f180ef79Sbeveloper 83034c72144SAxel Dörfler if (IS_INVALID_NODE(forNode)) { 831332cc6bcSAxel Dörfler ERROR("BMediaRoster::MakeTimeSourceFor: for_node invalid, node %" 832332cc6bcSAxel Dörfler B_PRId32 ", port %" B_PRId32 ", kinds 0x%" B_PRIx32 "\n", 833332cc6bcSAxel Dörfler forNode.node, forNode.port, forNode.kind); 8345917dd5bSbeveloper return NULL; 8350e21b167Sbeveloper } 8360e21b167Sbeveloper 837332cc6bcSAxel Dörfler TRACE("BMediaRoster::MakeTimeSourceFor: node %" B_PRId32 " enter\n", 838332cc6bcSAxel Dörfler forNode.node); 8395917dd5bSbeveloper 8405917dd5bSbeveloper node_get_timesource_request request; 8415917dd5bSbeveloper node_get_timesource_reply reply; 8425917dd5bSbeveloper BTimeSource *source; 8435917dd5bSbeveloper status_t rv; 8445917dd5bSbeveloper 84592e575c1Sbeveloper // ask the node to get it's current timesource id 84634c72144SAxel Dörfler rv = QueryPort(forNode.port, NODE_GET_TIMESOURCE, &request, 84734c72144SAxel Dörfler sizeof(request), &reply, sizeof(reply)); 8485917dd5bSbeveloper if (rv != B_OK) { 8495ac4fbd7Sbeveloper ERROR("BMediaRoster::MakeTimeSourceFor: request failed\n"); 8505917dd5bSbeveloper return NULL; 8515917dd5bSbeveloper } 8525917dd5bSbeveloper 8535917dd5bSbeveloper source = MediaRosterEx(this)->MakeTimeSourceObject(reply.timesource_id); 8545917dd5bSbeveloper 855332cc6bcSAxel Dörfler TRACE("BMediaRoster::MakeTimeSourceFor: node %" B_PRId32 " leave\n", 856332cc6bcSAxel Dörfler forNode.node); 857287f7492Sbeveloper 858835140c8Sbeveloper return source; 85952a38012Sejakowatz } 86052a38012Sejakowatz 86152a38012Sejakowatz 86252a38012Sejakowatz status_t 86334c72144SAxel Dörfler BMediaRoster::Connect(const media_source& from, const media_destination& to, 86434c72144SAxel Dörfler media_format* _format, media_output* _output, media_input* _input) 86552a38012Sejakowatz { 86634c72144SAxel Dörfler return BMediaRoster::Connect(from, to, _format, _output, _input, 0); 867eae26d3dSbeveloper } 868eae26d3dSbeveloper 869eae26d3dSbeveloper 870eae26d3dSbeveloper status_t 87134c72144SAxel Dörfler BMediaRoster::Connect(const media_source& from, const media_destination& to, 87234c72144SAxel Dörfler media_format* io_format, media_output* out_output, media_input* out_input, 87334c72144SAxel Dörfler uint32 in_flags, void* _reserved) 874eae26d3dSbeveloper { 87552a38012Sejakowatz CALLED(); 87652a38012Sejakowatz if (io_format == NULL || out_output == NULL || out_input == NULL) 87752a38012Sejakowatz return B_BAD_VALUE; 87840f36b03Sbeveloper if (IS_INVALID_SOURCE(from)) { 8795ac4fbd7Sbeveloper ERROR("BMediaRoster::Connect: media_source invalid\n"); 88052a38012Sejakowatz return B_MEDIA_BAD_SOURCE; 8819e9417d2Sbeveloper } 88240f36b03Sbeveloper if (IS_INVALID_DESTINATION(to)) { 8835ac4fbd7Sbeveloper ERROR("BMediaRoster::Connect: media_destination invalid\n"); 88452a38012Sejakowatz return B_MEDIA_BAD_DESTINATION; 8859e9417d2Sbeveloper } 88652a38012Sejakowatz 88752a38012Sejakowatz status_t rv; 88865b73ae4SMarcus Overhagen 88965b73ae4SMarcus Overhagen // find the output and input nodes 89034c72144SAxel Dörfler // TODO: isn't there a easier way? 89165b73ae4SMarcus Overhagen media_node sourcenode; 89265b73ae4SMarcus Overhagen media_node destnode; 89365b73ae4SMarcus Overhagen rv = GetNodeFor(NodeIDFor(from.port), &sourcenode); 89465b73ae4SMarcus Overhagen if (rv != B_OK) { 895332cc6bcSAxel Dörfler ERROR("BMediaRoster::Connect: Can't find source node for port %" 896332cc6bcSAxel Dörfler B_PRId32 "\n", from.port); 89765b73ae4SMarcus Overhagen return B_MEDIA_BAD_SOURCE; 89865b73ae4SMarcus Overhagen } 89965b73ae4SMarcus Overhagen ReleaseNode(sourcenode); 90065b73ae4SMarcus Overhagen rv = GetNodeFor(NodeIDFor(to.port), &destnode); 90165b73ae4SMarcus Overhagen if (rv != B_OK) { 90234c72144SAxel Dörfler ERROR("BMediaRoster::Connect: Can't find destination node for port " 903332cc6bcSAxel Dörfler "%" B_PRId32 "\n", to.port); 90465b73ae4SMarcus Overhagen return B_MEDIA_BAD_DESTINATION; 90565b73ae4SMarcus Overhagen } 90665b73ae4SMarcus Overhagen ReleaseNode(destnode); 90765b73ae4SMarcus Overhagen 90865b73ae4SMarcus Overhagen if (!(sourcenode.kind & B_BUFFER_PRODUCER)) { 909332cc6bcSAxel Dörfler ERROR("BMediaRoster::Connect: source node %" B_PRId32 " is not a " 91034c72144SAxel Dörfler "B_BUFFER_PRODUCER\n", sourcenode.node); 91165b73ae4SMarcus Overhagen return B_MEDIA_BAD_SOURCE; 91265b73ae4SMarcus Overhagen } 91365b73ae4SMarcus Overhagen if (!(destnode.kind & B_BUFFER_CONSUMER)) { 914332cc6bcSAxel Dörfler ERROR("BMediaRoster::Connect: destination node %" B_PRId32 " is not a " 91534c72144SAxel Dörfler "B_BUFFER_CONSUMER\n", destnode.node); 91665b73ae4SMarcus Overhagen return B_MEDIA_BAD_DESTINATION; 91765b73ae4SMarcus Overhagen } 91865b73ae4SMarcus Overhagen 9198c6a6096Sbeveloper producer_format_proposal_request request1; 9208c6a6096Sbeveloper producer_format_proposal_reply reply1; 92152a38012Sejakowatz 92234c72144SAxel Dörfler PRINT_FORMAT("BMediaRoster::Connect calling " 92334c72144SAxel Dörfler "BBufferProducer::FormatProposal with format ", *io_format); 92469983609Sbeveloper 92552a38012Sejakowatz // BBufferProducer::FormatProposal 9268c6a6096Sbeveloper request1.output = from; 9278c6a6096Sbeveloper request1.format = *io_format; 92834c72144SAxel Dörfler rv = QueryPort(from.port, PRODUCER_FORMAT_PROPOSAL, &request1, 92934c72144SAxel Dörfler sizeof(request1), &reply1, sizeof(reply1)); 9308c6a6096Sbeveloper if (rv != B_OK) { 93134c72144SAxel Dörfler ERROR("BMediaRoster::Connect: aborted after " 932332cc6bcSAxel Dörfler "BBufferProducer::FormatProposal, status = %#" B_PRIx32 "\n",rv); 93352a38012Sejakowatz return rv; 93452a38012Sejakowatz } 9358c6a6096Sbeveloper // reply1.format now contains the format proposed by the producer 9368c6a6096Sbeveloper 9378c6a6096Sbeveloper consumer_accept_format_request request2; 9388c6a6096Sbeveloper consumer_accept_format_reply reply2; 9398c6a6096Sbeveloper 94034c72144SAxel Dörfler PRINT_FORMAT("BMediaRoster::Connect calling " 94134c72144SAxel Dörfler "BBufferConsumer::AcceptFormat with format ", reply1.format); 94269983609Sbeveloper 9438c6a6096Sbeveloper // BBufferConsumer::AcceptFormat 9448c6a6096Sbeveloper request2.dest = to; 9458c6a6096Sbeveloper request2.format = reply1.format; 94634c72144SAxel Dörfler rv = QueryPort(to.port, CONSUMER_ACCEPT_FORMAT, &request2, 94734c72144SAxel Dörfler sizeof(request2), &reply2, sizeof(reply2)); 9488c6a6096Sbeveloper if (rv != B_OK) { 94934c72144SAxel Dörfler ERROR("BMediaRoster::Connect: aborted after " 950332cc6bcSAxel Dörfler "BBufferConsumer::AcceptFormat, status = %#" B_PRIx32 "\n",rv); 9518c6a6096Sbeveloper return rv; 9528c6a6096Sbeveloper } 9538c6a6096Sbeveloper // reply2.format now contains the format accepted by the consumer 9548c6a6096Sbeveloper 9558c6a6096Sbeveloper // BBufferProducer::PrepareToConnect 9568c6a6096Sbeveloper producer_prepare_to_connect_request request3; 9578c6a6096Sbeveloper producer_prepare_to_connect_reply reply3; 9588c6a6096Sbeveloper 95934c72144SAxel Dörfler PRINT_FORMAT("BMediaRoster::Connect calling " 96034c72144SAxel Dörfler "BBufferProducer::PrepareToConnect with format", reply2.format); 96169983609Sbeveloper 9628c6a6096Sbeveloper request3.source = from; 9638c6a6096Sbeveloper request3.destination = to; 9648c6a6096Sbeveloper request3.format = reply2.format; 96534c72144SAxel Dörfler strcpy(request3.name, "XXX some default name"); // TODO: fix this 96634c72144SAxel Dörfler rv = QueryPort(from.port, PRODUCER_PREPARE_TO_CONNECT, &request3, 96734c72144SAxel Dörfler sizeof(request3), &reply3, sizeof(reply3)); 9688c6a6096Sbeveloper if (rv != B_OK) { 96934c72144SAxel Dörfler ERROR("BMediaRoster::Connect: aborted after " 970332cc6bcSAxel Dörfler "BBufferProducer::PrepareToConnect, status = %#" B_PRIx32 "\n", rv); 9718c6a6096Sbeveloper return rv; 9728c6a6096Sbeveloper } 9738c6a6096Sbeveloper // reply3.format is still our pretty media format 9748c6a6096Sbeveloper // reply3.out_source the real source to be used for the connection 97534c72144SAxel Dörfler // reply3.name the name BBufferConsumer::Connected will see in the 97634c72144SAxel Dörfler // outInput->name argument 9778c6a6096Sbeveloper 9788c6a6096Sbeveloper // BBufferConsumer::Connected 9798c6a6096Sbeveloper consumer_connected_request request4; 9808c6a6096Sbeveloper consumer_connected_reply reply4; 9818c6a6096Sbeveloper status_t con_status; 9828c6a6096Sbeveloper 98334c72144SAxel Dörfler PRINT_FORMAT("BMediaRoster::Connect calling BBufferConsumer::Connected() " 98434c72144SAxel Dörfler "with format ", reply3.format); 98569983609Sbeveloper 98669983609Sbeveloper request4.input.node = destnode; 98769983609Sbeveloper request4.input.source = reply3.out_source; 98869983609Sbeveloper request4.input.destination = to; 98969983609Sbeveloper request4.input.format = reply3.format; 99069983609Sbeveloper strcpy(request4.input.name, reply3.name); 99169983609Sbeveloper 99234c72144SAxel Dörfler con_status = QueryPort(to.port, CONSUMER_CONNECTED, &request4, 99334c72144SAxel Dörfler sizeof(request4), &reply4, sizeof(reply4)); 9948c6a6096Sbeveloper if (con_status != B_OK) { 99534c72144SAxel Dörfler ERROR("BMediaRoster::Connect: aborting after " 996332cc6bcSAxel Dörfler "BBufferConsumer::Connected, status = %#" B_PRIx32 "\n", 997332cc6bcSAxel Dörfler con_status); 9988c6a6096Sbeveloper // we do NOT return here! 9998c6a6096Sbeveloper } 100034c72144SAxel Dörfler // con_status contains the status code to be supplied to 100134c72144SAxel Dörfler // BBufferProducer::Connect's status argument 100234c72144SAxel Dörfler // reply4.input contains the media_input that describes the connection 100334c72144SAxel Dörfler // from the consumer point of view 10048c6a6096Sbeveloper 10058c6a6096Sbeveloper // BBufferProducer::Connect 10068c6a6096Sbeveloper producer_connect_request request5; 10078c6a6096Sbeveloper producer_connect_reply reply5; 10088c6a6096Sbeveloper 100934c72144SAxel Dörfler PRINT_FORMAT("BMediaRoster::Connect calling BBufferProducer::Connect with " 101034c72144SAxel Dörfler "format ", reply4.input.format); 101169983609Sbeveloper 10128c6a6096Sbeveloper request5.error = con_status; 10138c6a6096Sbeveloper request5.source = reply3.out_source; 10148c6a6096Sbeveloper request5.destination = reply4.input.destination; 101569983609Sbeveloper request5.format = reply4.input.format; 10168c6a6096Sbeveloper strcpy(request5.name, reply4.input.name); 101734c72144SAxel Dörfler rv = QueryPort(reply4.input.source.port, PRODUCER_CONNECT, &request5, 101834c72144SAxel Dörfler sizeof(request5), &reply5, sizeof(reply5)); 10198c6a6096Sbeveloper if (con_status != B_OK) { 10205ac4fbd7Sbeveloper ERROR("BMediaRoster::Connect: aborted\n"); 10218c6a6096Sbeveloper return con_status; 10228c6a6096Sbeveloper } 10238c6a6096Sbeveloper if (rv != B_OK) { 102434c72144SAxel Dörfler ERROR("BMediaRoster::Connect: aborted after BBufferProducer::Connect()" 1025332cc6bcSAxel Dörfler ", status = %#" B_PRIx32 "\n", rv); 10268c6a6096Sbeveloper return rv; 10278c6a6096Sbeveloper } 10288c6a6096Sbeveloper // reply5.name contains the name assigned to the connection by the producer 10298c6a6096Sbeveloper 10308c6a6096Sbeveloper // initilize connection info 103169983609Sbeveloper *io_format = reply4.input.format; 10328c6a6096Sbeveloper *out_input = reply4.input; 10338c6a6096Sbeveloper out_output->node = sourcenode; 10348c6a6096Sbeveloper out_output->source = reply4.input.source; 10358c6a6096Sbeveloper out_output->destination = reply4.input.destination; 10368c6a6096Sbeveloper out_output->format = reply4.input.format; 10378c6a6096Sbeveloper strcpy(out_output->name, reply5.name); 10388c6a6096Sbeveloper 10398c6a6096Sbeveloper // the connection is now made 104069983609Sbeveloper printf("BMediaRoster::Connect connection established!\n"); 104169983609Sbeveloper PRINT_FORMAT(" format", *io_format); 104269983609Sbeveloper PRINT_INPUT(" input", *out_input); 104369983609Sbeveloper PRINT_OUTPUT(" output", *out_output); 10448c6a6096Sbeveloper 104534c72144SAxel Dörfler // TODO: register connection with server 104634c72144SAxel Dörfler // TODO: we should just send a notification, instead of republishing all 104734c72144SAxel Dörfler // endpoints 104876669a29Sbeveloper List<media_output> outlist; 104976669a29Sbeveloper List<media_input> inlist; 105034c72144SAxel Dörfler if (MediaRosterEx(this)->GetAllOutputs(out_output->node , &outlist) == B_OK) 10518b04ffc1Sbeveloper MediaRosterEx(this)->PublishOutputs(out_output->node , &outlist); 105234c72144SAxel Dörfler if (MediaRosterEx(this)->GetAllInputs(out_input->node , &inlist) == B_OK) 10538b04ffc1Sbeveloper MediaRosterEx(this)->PublishInputs(out_input->node, &inlist); 10548c6a6096Sbeveloper 105534c72144SAxel Dörfler // TODO: if (mute) BBufferProducer::EnableOutput(false) 10569e9417d2Sbeveloper if (in_flags & B_CONNECT_MUTED) { 10579e9417d2Sbeveloper } 10588c6a6096Sbeveloper 10599e9417d2Sbeveloper // send a notification 106034c72144SAxel Dörfler BPrivate::media::notifications::ConnectionMade(*out_input, *out_output, 106134c72144SAxel Dörfler *io_format); 10629e9417d2Sbeveloper 10638c6a6096Sbeveloper return B_OK; 10648c6a6096Sbeveloper }; 106552a38012Sejakowatz 106652a38012Sejakowatz 106752a38012Sejakowatz status_t 10689e9417d2Sbeveloper BMediaRoster::Disconnect(media_node_id source_nodeid, 106934c72144SAxel Dörfler const media_source& source, media_node_id destination_nodeid, 107052a38012Sejakowatz const media_destination& destination) 107152a38012Sejakowatz { 10729e9417d2Sbeveloper CALLED(); 107340f36b03Sbeveloper if (IS_INVALID_NODEID(source_nodeid)) { 10745ac4fbd7Sbeveloper ERROR("BMediaRoster::Disconnect: source media_node_id invalid\n"); 10759e9417d2Sbeveloper return B_MEDIA_BAD_SOURCE; 10769e9417d2Sbeveloper } 107740f36b03Sbeveloper if (IS_INVALID_NODEID(destination_nodeid)) { 10785ac4fbd7Sbeveloper ERROR("BMediaRoster::Disconnect: destination media_node_id invalid\n"); 10799e9417d2Sbeveloper return B_MEDIA_BAD_DESTINATION; 10809e9417d2Sbeveloper } 108140f36b03Sbeveloper if (IS_INVALID_SOURCE(source)) { 10825ac4fbd7Sbeveloper ERROR("BMediaRoster::Disconnect: media_source invalid\n"); 10839e9417d2Sbeveloper return B_MEDIA_BAD_SOURCE; 10849e9417d2Sbeveloper } 108540f36b03Sbeveloper if (IS_INVALID_DESTINATION(destination)) { 10865ac4fbd7Sbeveloper ERROR("BMediaRoster::Disconnect: media_destination invalid\n"); 10879e9417d2Sbeveloper return B_MEDIA_BAD_DESTINATION; 10889e9417d2Sbeveloper } 10899e9417d2Sbeveloper 10909e9417d2Sbeveloper producer_disconnect_request request2; 10919e9417d2Sbeveloper producer_disconnect_reply reply2; 10929e9417d2Sbeveloper consumer_disconnected_request request1; 10939e9417d2Sbeveloper consumer_disconnected_reply reply1; 10949e9417d2Sbeveloper status_t rv1, rv2; 10959e9417d2Sbeveloper 109634c72144SAxel Dörfler // TODO: we should ask the server if this connection really exists 10979e9417d2Sbeveloper 10989e9417d2Sbeveloper request1.source = source; 10999e9417d2Sbeveloper request1.destination = destination; 11009e9417d2Sbeveloper request2.source = source; 11019e9417d2Sbeveloper request2.destination = destination; 11029e9417d2Sbeveloper 110334c72144SAxel Dörfler rv1 = QueryPort(source.port, PRODUCER_DISCONNECT, &request1, 110434c72144SAxel Dörfler sizeof(request1), &reply1, sizeof(reply1)); 110534c72144SAxel Dörfler rv2 = QueryPort(destination.port, CONSUMER_DISCONNECTED, &request2, 110634c72144SAxel Dörfler sizeof(request2), &reply2, sizeof(reply2)); 11079e9417d2Sbeveloper 110834c72144SAxel Dörfler // TODO: unregister connection with server 110934c72144SAxel Dörfler // TODO: we should just send a notification, instead of republishing all 111034c72144SAxel Dörfler // endpoints 111176669a29Sbeveloper List<media_output> outlist; 111276669a29Sbeveloper List<media_input> inlist; 11139e9417d2Sbeveloper media_node sourcenode; 11149e9417d2Sbeveloper media_node destnode; 111534c72144SAxel Dörfler if (GetNodeFor(source_nodeid, &sourcenode) == B_OK) { 111665b73ae4SMarcus Overhagen if (!(sourcenode.kind & B_BUFFER_PRODUCER)) { 1117332cc6bcSAxel Dörfler ERROR("BMediaRoster::Disconnect: source_nodeid %" B_PRId32 1118332cc6bcSAxel Dörfler " is not a B_BUFFER_PRODUCER\n", source_nodeid); 111965b73ae4SMarcus Overhagen } 112034c72144SAxel Dörfler if (MediaRosterEx(this)->GetAllOutputs(sourcenode , &outlist) == B_OK) 11218b04ffc1Sbeveloper MediaRosterEx(this)->PublishOutputs(sourcenode , &outlist); 11229e9417d2Sbeveloper ReleaseNode(sourcenode); 11234f09fa2fSbeveloper } else { 1124332cc6bcSAxel Dörfler ERROR("BMediaRoster::Disconnect: GetNodeFor source_nodeid %" B_PRId32 1125332cc6bcSAxel Dörfler " failed\n", source_nodeid); 11264f09fa2fSbeveloper } 112734c72144SAxel Dörfler if (GetNodeFor(destination_nodeid, &destnode) == B_OK) { 112865b73ae4SMarcus Overhagen if (!(destnode.kind & B_BUFFER_CONSUMER)) { 1129332cc6bcSAxel Dörfler ERROR("BMediaRoster::Disconnect: destination_nodeid %" B_PRId32 1130332cc6bcSAxel Dörfler " is not a B_BUFFER_CONSUMER\n", destination_nodeid); 113165b73ae4SMarcus Overhagen } 113234c72144SAxel Dörfler if (MediaRosterEx(this)->GetAllInputs(destnode , &inlist) == B_OK) 11338b04ffc1Sbeveloper MediaRosterEx(this)->PublishInputs(destnode, &inlist); 11349e9417d2Sbeveloper ReleaseNode(destnode); 11354f09fa2fSbeveloper } else { 1136332cc6bcSAxel Dörfler ERROR("BMediaRoster::Disconnect: GetNodeFor destination_nodeid %" 1137332cc6bcSAxel Dörfler B_PRId32 " failed\n", destination_nodeid); 11384f09fa2fSbeveloper } 11399e9417d2Sbeveloper 11409e9417d2Sbeveloper // send a notification 11419e9417d2Sbeveloper BPrivate::media::notifications::ConnectionBroken(source, destination); 11429e9417d2Sbeveloper 114334c72144SAxel Dörfler return rv1 != B_OK || rv2 != B_OK ? B_ERROR : B_OK; 114452a38012Sejakowatz } 114552a38012Sejakowatz 114634c72144SAxel Dörfler 114765b73ae4SMarcus Overhagen status_t 114865b73ae4SMarcus Overhagen BMediaRoster::Disconnect(const media_output& output, const media_input& input) 114965b73ae4SMarcus Overhagen { 115065b73ae4SMarcus Overhagen if (IS_INVALID_NODEID(output.node.node)) { 1151332cc6bcSAxel Dörfler printf("BMediaRoster::Disconnect: output.node.node %" B_PRId32 1152332cc6bcSAxel Dörfler " invalid\n", output.node.node); 115365b73ae4SMarcus Overhagen return B_MEDIA_BAD_SOURCE; 115465b73ae4SMarcus Overhagen } 115565b73ae4SMarcus Overhagen if (IS_INVALID_NODEID(input.node.node)) { 1156332cc6bcSAxel Dörfler printf("BMediaRoster::Disconnect: input.node.node %" B_PRId32 1157332cc6bcSAxel Dörfler " invalid\n", input.node.node); 115865b73ae4SMarcus Overhagen return B_MEDIA_BAD_DESTINATION; 115965b73ae4SMarcus Overhagen } 116065b73ae4SMarcus Overhagen if (!(output.node.kind & B_BUFFER_PRODUCER)) { 1161332cc6bcSAxel Dörfler printf("BMediaRoster::Disconnect: output.node.kind 0x%" B_PRIx32 1162332cc6bcSAxel Dörfler " is no B_BUFFER_PRODUCER\n", output.node.kind); 116365b73ae4SMarcus Overhagen return B_MEDIA_BAD_SOURCE; 116465b73ae4SMarcus Overhagen } 116565b73ae4SMarcus Overhagen if (!(input.node.kind & B_BUFFER_CONSUMER)) { 1166332cc6bcSAxel Dörfler printf("BMediaRoster::Disconnect: input.node.kind 0x%" B_PRIx32 1167332cc6bcSAxel Dörfler " is no B_BUFFER_PRODUCER\n", input.node.kind); 116865b73ae4SMarcus Overhagen return B_MEDIA_BAD_DESTINATION; 116965b73ae4SMarcus Overhagen } 117065b73ae4SMarcus Overhagen if (input.source.port != output.source.port) { 1171332cc6bcSAxel Dörfler printf("BMediaRoster::Disconnect: input.source.port %" B_PRId32 1172332cc6bcSAxel Dörfler " doesn't match output.source.port %" B_PRId32 "\n", 1173332cc6bcSAxel Dörfler input.source.port, output.source.port); 117465b73ae4SMarcus Overhagen return B_MEDIA_BAD_SOURCE; 117565b73ae4SMarcus Overhagen } 117665b73ae4SMarcus Overhagen if (input.source.id != output.source.id) { 1177332cc6bcSAxel Dörfler printf("BMediaRoster::Disconnect: input.source.id %" B_PRId32 1178332cc6bcSAxel Dörfler " doesn't match output.source.id %" B_PRId32 "\n", input.source.id, 1179332cc6bcSAxel Dörfler output.source.id); 118065b73ae4SMarcus Overhagen return B_MEDIA_BAD_SOURCE; 118165b73ae4SMarcus Overhagen } 118265b73ae4SMarcus Overhagen if (input.destination.port != output.destination.port) { 1183332cc6bcSAxel Dörfler printf("BMediaRoster::Disconnect: input.destination.port %" B_PRId32 1184332cc6bcSAxel Dörfler " doesn't match output.destination.port %" B_PRId32 "\n", 1185332cc6bcSAxel Dörfler input.destination.port, output.destination.port); 118665b73ae4SMarcus Overhagen return B_MEDIA_BAD_DESTINATION; 118765b73ae4SMarcus Overhagen } 118865b73ae4SMarcus Overhagen if (input.destination.id != output.destination.id) { 1189332cc6bcSAxel Dörfler printf("BMediaRoster::Disconnect: input.destination.id %" B_PRId32 1190332cc6bcSAxel Dörfler " doesn't match output.destination.id %" B_PRId32 "\n", 1191332cc6bcSAxel Dörfler input.destination.id, output.destination.id); 119265b73ae4SMarcus Overhagen return B_MEDIA_BAD_DESTINATION; 119365b73ae4SMarcus Overhagen } 119434c72144SAxel Dörfler 119534c72144SAxel Dörfler return Disconnect(output.node.node, output.source, input.node.node, 119634c72144SAxel Dörfler input.destination); 119765b73ae4SMarcus Overhagen } 119865b73ae4SMarcus Overhagen 119952a38012Sejakowatz 120052a38012Sejakowatz status_t 120134c72144SAxel Dörfler BMediaRoster::StartNode(const media_node& node, bigtime_t atPerformanceTime) 120252a38012Sejakowatz { 120352a38012Sejakowatz CALLED(); 12049e9417d2Sbeveloper if (node.node <= 0) 120552a38012Sejakowatz return B_MEDIA_BAD_NODE; 120652a38012Sejakowatz 1207332cc6bcSAxel Dörfler TRACE("BMediaRoster::StartNode, node %" B_PRId32 ", at perf %" B_PRId64 1208332cc6bcSAxel Dörfler "\n", node.node, atPerformanceTime); 12090e21b167Sbeveloper 12106396865dSbeveloper node_start_command command; 121134c72144SAxel Dörfler command.performance_time = atPerformanceTime; 121252a38012Sejakowatz 12136396865dSbeveloper return SendToPort(node.port, NODE_START, &command, sizeof(command)); 121452a38012Sejakowatz } 121552a38012Sejakowatz 121652a38012Sejakowatz 121752a38012Sejakowatz status_t 121834c72144SAxel Dörfler BMediaRoster::StopNode(const media_node& node, bigtime_t atPerformanceTime, 121952a38012Sejakowatz bool immediate) 122052a38012Sejakowatz { 122152a38012Sejakowatz CALLED(); 122240f36b03Sbeveloper if (IS_INVALID_NODE(node)) 122352a38012Sejakowatz return B_MEDIA_BAD_NODE; 122452a38012Sejakowatz 1225332cc6bcSAxel Dörfler TRACE("BMediaRoster::StopNode, node %" B_PRId32 ", at perf %" B_PRId64 1226332cc6bcSAxel Dörfler " %s\n", node.node, atPerformanceTime, immediate ? "NOW" : ""); 12270e21b167Sbeveloper 12286396865dSbeveloper node_stop_command command; 122934c72144SAxel Dörfler command.performance_time = atPerformanceTime; 12306396865dSbeveloper command.immediate = immediate; 123152a38012Sejakowatz 12326396865dSbeveloper return SendToPort(node.port, NODE_STOP, &command, sizeof(command)); 123352a38012Sejakowatz } 123452a38012Sejakowatz 123552a38012Sejakowatz 123652a38012Sejakowatz status_t 123734c72144SAxel Dörfler BMediaRoster::SeekNode(const media_node& node, bigtime_t toMediaTime, 123834c72144SAxel Dörfler bigtime_t atPerformanceTime) 123952a38012Sejakowatz { 124052a38012Sejakowatz CALLED(); 124140f36b03Sbeveloper if (IS_INVALID_NODE(node)) 124252a38012Sejakowatz return B_MEDIA_BAD_NODE; 124352a38012Sejakowatz 1244332cc6bcSAxel Dörfler TRACE("BMediaRoster::SeekNode, node %" B_PRId32 ", at perf %" B_PRId64 1245332cc6bcSAxel Dörfler ", to perf %" B_PRId64 "\n", node.node, atPerformanceTime, toMediaTime); 12460e21b167Sbeveloper 12476396865dSbeveloper node_seek_command command; 124834c72144SAxel Dörfler command.media_time = toMediaTime; 124934c72144SAxel Dörfler command.performance_time = atPerformanceTime; 125052a38012Sejakowatz 12516396865dSbeveloper return SendToPort(node.port, NODE_SEEK, &command, sizeof(command)); 125252a38012Sejakowatz } 125352a38012Sejakowatz 125452a38012Sejakowatz 125552a38012Sejakowatz status_t 125634c72144SAxel Dörfler BMediaRoster::StartTimeSource(const media_node& node, bigtime_t atRealTime) 125752a38012Sejakowatz { 125852a38012Sejakowatz CALLED(); 125960f15390Sbeveloper if (IS_SYSTEM_TIMESOURCE(node)) { 126034c72144SAxel Dörfler // TODO: debug this 1261332cc6bcSAxel Dörfler //ERROR("BMediaRoster::StartTimeSource node %" B_PRId32 " is system timesource\n", node.node); 126260f15390Sbeveloper return B_OK; 126360f15390Sbeveloper } 126492e575c1Sbeveloper // if (IS_SHADOW_TIMESOURCE(node)) { 126534c72144SAxel Dörfler // // TODO: debug this 1266332cc6bcSAxel Dörfler // ERROR("BMediaRoster::StartTimeSource node %" B_PRId32 " is shadow timesource\n", node.node); 126792e575c1Sbeveloper // return B_OK; 126892e575c1Sbeveloper // } 126940f36b03Sbeveloper if (IS_INVALID_NODE(node)) { 1270332cc6bcSAxel Dörfler ERROR("BMediaRoster::StartTimeSource node %" B_PRId32 " invalid\n", 127134c72144SAxel Dörfler node.node); 127252a38012Sejakowatz return B_MEDIA_BAD_NODE; 12730e21b167Sbeveloper } 1274332cc6bcSAxel Dörfler if ((node.kind & B_TIME_SOURCE) == 0) { 1275332cc6bcSAxel Dörfler ERROR("BMediaRoster::StartTimeSource node %" B_PRId32 1276332cc6bcSAxel Dörfler " is no timesource\n", node.node); 1277332cc6bcSAxel Dörfler return B_MEDIA_BAD_NODE; 1278332cc6bcSAxel Dörfler } 12790e21b167Sbeveloper 1280332cc6bcSAxel Dörfler TRACE("BMediaRoster::StartTimeSource, node %" B_PRId32 ", at real %" 1281332cc6bcSAxel Dörfler B_PRId64 "\n", node.node, atRealTime); 128252a38012Sejakowatz 128352a38012Sejakowatz BTimeSource::time_source_op_info msg; 128452a38012Sejakowatz msg.op = BTimeSource::B_TIMESOURCE_START; 128534c72144SAxel Dörfler msg.real_time = atRealTime; 128652a38012Sejakowatz 128752a38012Sejakowatz return write_port(node.port, TIMESOURCE_OP, &msg, sizeof(msg)); 128852a38012Sejakowatz } 128952a38012Sejakowatz 129052a38012Sejakowatz 129152a38012Sejakowatz status_t 129234c72144SAxel Dörfler BMediaRoster::StopTimeSource(const media_node& node, bigtime_t atRealTime, 129352a38012Sejakowatz bool immediate) 129452a38012Sejakowatz { 129552a38012Sejakowatz CALLED(); 129660f15390Sbeveloper if (IS_SYSTEM_TIMESOURCE(node)) { 129734c72144SAxel Dörfler // TODO: debug this 12985ac4fbd7Sbeveloper //ERROR("BMediaRoster::StopTimeSource node %ld is system timesource\n", node.node); 129960f15390Sbeveloper return B_OK; 130060f15390Sbeveloper } 130192e575c1Sbeveloper // if (IS_SHADOW_TIMESOURCE(node)) { 130234c72144SAxel Dörfler // // TODO: debug this 130392e575c1Sbeveloper // ERROR("BMediaRoster::StopTimeSource node %ld is shadow timesource\n", node.node); 130492e575c1Sbeveloper // return B_OK; 130592e575c1Sbeveloper // } 130640f36b03Sbeveloper if (IS_INVALID_NODE(node)) { 1307332cc6bcSAxel Dörfler ERROR("BMediaRoster::StopTimeSource node %" B_PRId32 " invalid\n", 130834c72144SAxel Dörfler node.node); 130952a38012Sejakowatz return B_MEDIA_BAD_NODE; 13100e21b167Sbeveloper } 1311332cc6bcSAxel Dörfler if ((node.kind & B_TIME_SOURCE) == 0) { 1312332cc6bcSAxel Dörfler ERROR("BMediaRoster::StopTimeSource node %" B_PRId32 " is no " 1313332cc6bcSAxel Dörfler "timesource\n", node.node); 1314332cc6bcSAxel Dörfler return B_MEDIA_BAD_NODE; 1315332cc6bcSAxel Dörfler } 13160e21b167Sbeveloper 1317332cc6bcSAxel Dörfler TRACE("BMediaRoster::StopTimeSource, node %" B_PRId32 ", at real %" B_PRId64 1318332cc6bcSAxel Dörfler " %s\n", node.node, atRealTime, immediate ? "NOW" : ""); 131952a38012Sejakowatz 132052a38012Sejakowatz BTimeSource::time_source_op_info msg; 132134c72144SAxel Dörfler msg.op = immediate ? BTimeSource::B_TIMESOURCE_STOP_IMMEDIATELY 132234c72144SAxel Dörfler : BTimeSource::B_TIMESOURCE_STOP; 132334c72144SAxel Dörfler msg.real_time = atRealTime; 132452a38012Sejakowatz 132552a38012Sejakowatz return write_port(node.port, TIMESOURCE_OP, &msg, sizeof(msg)); 132652a38012Sejakowatz } 132752a38012Sejakowatz 132852a38012Sejakowatz 132952a38012Sejakowatz status_t 133052a38012Sejakowatz BMediaRoster::SeekTimeSource(const media_node& node, 133134c72144SAxel Dörfler bigtime_t toPerformanceTime, bigtime_t atRealTime) 133252a38012Sejakowatz { 133352a38012Sejakowatz CALLED(); 133460f15390Sbeveloper if (IS_SYSTEM_TIMESOURCE(node)) { 133534c72144SAxel Dörfler // TODO: debug this 13365ac4fbd7Sbeveloper // ERROR("BMediaRoster::SeekTimeSource node %ld is system timesource\n", node.node); 133760f15390Sbeveloper // you can't seek the system time source, but 133860f15390Sbeveloper // returning B_ERROR would break StampTV 133960f15390Sbeveloper return B_OK; 134060f15390Sbeveloper } 134192e575c1Sbeveloper // if (IS_SHADOW_TIMESOURCE(node)) { 134234c72144SAxel Dörfler // // TODO: debug this 134392e575c1Sbeveloper // ERROR("BMediaRoster::SeekTimeSource node %ld is shadow timesource\n", node.node); 134492e575c1Sbeveloper // return B_OK; 134592e575c1Sbeveloper // } 134640f36b03Sbeveloper if (IS_INVALID_NODE(node)) { 1347332cc6bcSAxel Dörfler ERROR("BMediaRoster::SeekTimeSource node %" B_PRId32 " invalid\n", 134834c72144SAxel Dörfler node.node); 134952a38012Sejakowatz return B_MEDIA_BAD_NODE; 13500e21b167Sbeveloper } 1351332cc6bcSAxel Dörfler if ((node.kind & B_TIME_SOURCE) == 0) { 1352332cc6bcSAxel Dörfler ERROR("BMediaRoster::SeekTimeSource node %" B_PRId32 1353332cc6bcSAxel Dörfler " is no timesource\n", node.node); 1354332cc6bcSAxel Dörfler return B_MEDIA_BAD_NODE; 1355332cc6bcSAxel Dörfler } 13560e21b167Sbeveloper 1357332cc6bcSAxel Dörfler TRACE("BMediaRoster::SeekTimeSource, node %" B_PRId32 ", at real %" B_PRId64 1358332cc6bcSAxel Dörfler ", to perf %" B_PRId64 "\n", node.node, atRealTime, toPerformanceTime); 135952a38012Sejakowatz 136052a38012Sejakowatz BTimeSource::time_source_op_info msg; 136152a38012Sejakowatz msg.op = BTimeSource::B_TIMESOURCE_SEEK; 136234c72144SAxel Dörfler msg.real_time = atRealTime; 136334c72144SAxel Dörfler msg.performance_time = toPerformanceTime; 136452a38012Sejakowatz 136552a38012Sejakowatz return write_port(node.port, TIMESOURCE_OP, &msg, sizeof(msg)); 136652a38012Sejakowatz } 136752a38012Sejakowatz 136852a38012Sejakowatz 136952a38012Sejakowatz status_t 137034c72144SAxel Dörfler BMediaRoster::SyncToNode(const media_node& node, bigtime_t atTime, 137152a38012Sejakowatz bigtime_t timeout) 137252a38012Sejakowatz { 137352a38012Sejakowatz UNIMPLEMENTED(); 137460f15390Sbeveloper return B_OK; 137552a38012Sejakowatz } 137652a38012Sejakowatz 137752a38012Sejakowatz 137852a38012Sejakowatz status_t 137934c72144SAxel Dörfler BMediaRoster::SetRunModeNode(const media_node& node, BMediaNode::run_mode mode) 138052a38012Sejakowatz { 1381332cc6bcSAxel Dörfler TRACE("BMediaRoster::SetRunModeNode, node %" B_PRId32 ", mode %d\n", 1382332cc6bcSAxel Dörfler node.node, mode); 138340f36b03Sbeveloper if (IS_INVALID_NODE(node)) 138452a38012Sejakowatz return B_MEDIA_BAD_NODE; 138552a38012Sejakowatz 1386dfb2ad61Sbeveloper node_set_run_mode_command msg; 138752a38012Sejakowatz msg.mode = mode; 138852a38012Sejakowatz 138952a38012Sejakowatz return write_port(node.port, NODE_SET_RUN_MODE, &msg, sizeof(msg)); 139052a38012Sejakowatz } 139152a38012Sejakowatz 139252a38012Sejakowatz 139352a38012Sejakowatz status_t 139452a38012Sejakowatz BMediaRoster::PrerollNode(const media_node& node) 139552a38012Sejakowatz { 139652a38012Sejakowatz CALLED(); 139740f36b03Sbeveloper if (IS_INVALID_NODE(node)) 139852a38012Sejakowatz return B_MEDIA_BAD_NODE; 139952a38012Sejakowatz 140052a38012Sejakowatz char dummy; 140152a38012Sejakowatz return write_port(node.port, NODE_PREROLL, &dummy, sizeof(dummy)); 140252a38012Sejakowatz } 140352a38012Sejakowatz 140452a38012Sejakowatz 140552a38012Sejakowatz status_t 140634c72144SAxel Dörfler BMediaRoster::RollNode(const media_node& node, bigtime_t startPerformance, 140734c72144SAxel Dörfler bigtime_t stopPerformance, bigtime_t atMediaTime) 140852a38012Sejakowatz { 140952a38012Sejakowatz UNIMPLEMENTED(); 141052a38012Sejakowatz return B_ERROR; 141152a38012Sejakowatz } 141252a38012Sejakowatz 141352a38012Sejakowatz 141452a38012Sejakowatz status_t 141552a38012Sejakowatz BMediaRoster::SetProducerRunModeDelay(const media_node& node, 141634c72144SAxel Dörfler bigtime_t delay, BMediaNode::run_mode mode) 141752a38012Sejakowatz { 1418332cc6bcSAxel Dörfler TRACE("BMediaRoster::SetProducerRunModeDelay, node %" B_PRId32 ", delay %" 1419332cc6bcSAxel Dörfler B_PRId64 ", mode %d\n", node.node, delay, mode); 142060f15390Sbeveloper if (IS_INVALID_NODE(node)) 142160f15390Sbeveloper return B_MEDIA_BAD_NODE; 142260f15390Sbeveloper if ((node.kind & B_BUFFER_PRODUCER) == 0) 142360f15390Sbeveloper return B_MEDIA_BAD_NODE; 142460f15390Sbeveloper 142560f15390Sbeveloper producer_set_run_mode_delay_command command; 142660f15390Sbeveloper command.mode = mode; 142760f15390Sbeveloper command.delay = delay; 142860f15390Sbeveloper 142934c72144SAxel Dörfler return SendToPort(node.port, PRODUCER_SET_RUN_MODE_DELAY, &command, 143034c72144SAxel Dörfler sizeof(command)); 143152a38012Sejakowatz } 143252a38012Sejakowatz 143352a38012Sejakowatz 143452a38012Sejakowatz status_t 143534c72144SAxel Dörfler BMediaRoster::SetProducerRate(const media_node& producer, int32 numer, 143652a38012Sejakowatz int32 denom) 143752a38012Sejakowatz { 143852a38012Sejakowatz CALLED(); 143940f36b03Sbeveloper if (IS_INVALID_NODE(producer)) 144052a38012Sejakowatz return B_MEDIA_BAD_NODE; 144152a38012Sejakowatz if ((producer.kind & B_BUFFER_PRODUCER) == 0) 144252a38012Sejakowatz return B_MEDIA_BAD_NODE; 144352a38012Sejakowatz 14446cafce94SAxel Dörfler producer_set_play_rate_request request; 14456cafce94SAxel Dörfler request.numer = numer; 14466cafce94SAxel Dörfler request.denom = denom; 14476cafce94SAxel Dörfler status_t status = write_port(producer.node, PRODUCER_SET_PLAY_RATE, 14486cafce94SAxel Dörfler &request, sizeof(request)); 14496cafce94SAxel Dörfler if (status != B_OK) 14506cafce94SAxel Dörfler return status; 145152a38012Sejakowatz 14526cafce94SAxel Dörfler producer_set_play_rate_reply reply; 14536cafce94SAxel Dörfler int32 code; 14546cafce94SAxel Dörfler status = read_port(request.reply_port, &code, &reply, sizeof(reply)); 14556cafce94SAxel Dörfler 14566cafce94SAxel Dörfler return status < B_OK ? status : reply.result; 145752a38012Sejakowatz } 145852a38012Sejakowatz 145952a38012Sejakowatz 146034c72144SAxel Dörfler /*! Nodes will have available inputs/outputs as long as they are capable 146134c72144SAxel Dörfler of accepting more connections. The node may create an additional 146234c72144SAxel Dörfler output or input as the currently available is taken into usage. 146334c72144SAxel Dörfler */ 146452a38012Sejakowatz status_t 146552a38012Sejakowatz BMediaRoster::GetLiveNodeInfo(const media_node& node, 146652a38012Sejakowatz live_node_info* out_live_info) 146752a38012Sejakowatz { 14689e9417d2Sbeveloper CALLED(); 14699e9417d2Sbeveloper if (out_live_info == NULL) 14709e9417d2Sbeveloper return B_BAD_VALUE; 147140f36b03Sbeveloper if (IS_INVALID_NODE(node)) 14729e9417d2Sbeveloper return B_MEDIA_BAD_NODE; 14739e9417d2Sbeveloper 14749e9417d2Sbeveloper server_get_live_node_info_request request; 14759e9417d2Sbeveloper server_get_live_node_info_reply reply; 14769e9417d2Sbeveloper status_t rv; 14779e9417d2Sbeveloper 14789e9417d2Sbeveloper request.node = node; 14799e9417d2Sbeveloper 148034c72144SAxel Dörfler rv = QueryServer(SERVER_GET_LIVE_NODE_INFO, &request, sizeof(request), 148134c72144SAxel Dörfler &reply, sizeof(reply)); 14829e9417d2Sbeveloper if (rv != B_OK) 14839e9417d2Sbeveloper return rv; 14849e9417d2Sbeveloper 14859e9417d2Sbeveloper *out_live_info = reply.live_info; 14869e9417d2Sbeveloper return B_OK; 148752a38012Sejakowatz } 148852a38012Sejakowatz 148952a38012Sejakowatz 149052a38012Sejakowatz status_t 14919c3b4706SAxel Dörfler BMediaRoster::GetLiveNodes(live_node_info* liveNodes, int32* _totalCount, 149234c72144SAxel Dörfler const media_format* hasInput, const media_format* hasOutput, 149334c72144SAxel Dörfler const char* name, uint64 nodeKinds) 149452a38012Sejakowatz { 14959e9417d2Sbeveloper CALLED(); 14969c3b4706SAxel Dörfler if (liveNodes == NULL || _totalCount == NULL || *_totalCount <= 0) 14979e9417d2Sbeveloper return B_BAD_VALUE; 14989e9417d2Sbeveloper 149934c72144SAxel Dörfler // TODO: we also support the wildcard search as GetDormantNodes does. 150034c72144SAxel Dörfler // This needs to be documented 15019e9417d2Sbeveloper 15029e9417d2Sbeveloper server_get_live_nodes_request request; 15039c3b4706SAxel Dörfler request.team = BPrivate::current_team(); 15049e9417d2Sbeveloper 15059c3b4706SAxel Dörfler request.max_count = *_totalCount; 150634c72144SAxel Dörfler request.has_input = hasInput != NULL; 150734c72144SAxel Dörfler if (hasInput != NULL) { 150834c72144SAxel Dörfler // TODO: we should not make a flat copy of media_format 15099c3b4706SAxel Dörfler request.input_format = *hasInput; 151034c72144SAxel Dörfler } 151134c72144SAxel Dörfler request.has_output = hasOutput != NULL; 151234c72144SAxel Dörfler if (hasOutput != NULL) { 151334c72144SAxel Dörfler // TODO: we should not make a flat copy of media_format 15149c3b4706SAxel Dörfler request.output_format = *hasOutput; 151534c72144SAxel Dörfler } 151634c72144SAxel Dörfler request.has_name = name != NULL; 15179c3b4706SAxel Dörfler if (name != NULL) 15189c3b4706SAxel Dörfler strlcpy(request.name, name, sizeof(request.name)); 151934c72144SAxel Dörfler request.require_kinds = nodeKinds; 15209e9417d2Sbeveloper 15219c3b4706SAxel Dörfler server_get_live_nodes_reply reply; 15229c3b4706SAxel Dörfler status_t status = QueryServer(SERVER_GET_LIVE_NODES, &request, 15239c3b4706SAxel Dörfler sizeof(request), &reply, sizeof(reply)); 15249c3b4706SAxel Dörfler if (status != B_OK) { 15259c3b4706SAxel Dörfler ERROR("BMediaRoster::GetLiveNodes failed querying server: %s\n", 15269c3b4706SAxel Dörfler strerror(status)); 152734c72144SAxel Dörfler *_totalCount = 0; 15289c3b4706SAxel Dörfler return status; 15299e9417d2Sbeveloper } 15309e9417d2Sbeveloper 15319c3b4706SAxel Dörfler const live_node_info* info; 15329c3b4706SAxel Dörfler if (reply.area >= 0) 15339c3b4706SAxel Dörfler info = (live_node_info*)reply.address; 15349c3b4706SAxel Dörfler else 15359c3b4706SAxel Dörfler info = reply.live_info; 15369e9417d2Sbeveloper 15379c3b4706SAxel Dörfler for (int32 i = 0; i < reply.count; i++) 15389c3b4706SAxel Dörfler liveNodes[i] = info[i]; 15399c3b4706SAxel Dörfler 15409c3b4706SAxel Dörfler if (reply.area >= 0) 15419e9417d2Sbeveloper delete_area(reply.area); 154252a38012Sejakowatz 154334c72144SAxel Dörfler *_totalCount = reply.count; 15449e9417d2Sbeveloper return B_OK; 15459e9417d2Sbeveloper } 15469e9417d2Sbeveloper 154752a38012Sejakowatz 154852a38012Sejakowatz status_t 154952a38012Sejakowatz BMediaRoster::GetFreeInputsFor(const media_node& node, 155034c72144SAxel Dörfler media_input * out_free_inputs, int32 buf_num_inputs, 155134c72144SAxel Dörfler int32 * out_total_count, media_type filter_type) 155252a38012Sejakowatz { 15533620737cSbeveloper CALLED(); 15545ac4fbd7Sbeveloper if (IS_INVALID_NODE(node)) { 1555332cc6bcSAxel Dörfler ERROR("BMediaRoster::GetFreeInputsFor: node %" B_PRId32 ", port %" 1556332cc6bcSAxel Dörfler B_PRId32 " invalid\n", node.node, node.port); 15573620737cSbeveloper return B_MEDIA_BAD_NODE; 15585ac4fbd7Sbeveloper } 15595ac4fbd7Sbeveloper if ((node.kind & B_BUFFER_CONSUMER) == 0) { 1560332cc6bcSAxel Dörfler ERROR("BMediaRoster::GetFreeInputsFor: node %" B_PRId32 ", port %" 1561332cc6bcSAxel Dörfler B_PRId32 " is not a consumer\n", node.node, node.port); 15625ac4fbd7Sbeveloper return B_MEDIA_BAD_NODE; 15635ac4fbd7Sbeveloper } 15643620737cSbeveloper if (out_free_inputs == NULL || out_total_count == NULL) 15653620737cSbeveloper return B_BAD_VALUE; 15663620737cSbeveloper 156776669a29Sbeveloper List<media_input> list; 15683620737cSbeveloper media_input *input; 15693620737cSbeveloper status_t rv; 15703620737cSbeveloper 15711299bfb2Sbeveloper *out_total_count = 0; 15721299bfb2Sbeveloper 15738b04ffc1Sbeveloper rv = MediaRosterEx(this)->GetAllInputs(node, &list); 15743620737cSbeveloper if (B_OK != rv) 15753620737cSbeveloper return rv; 15763620737cSbeveloper 1577332cc6bcSAxel Dörfler PRINT(4, "BMediaRoster::GetFreeInputsFor node %" B_PRId32 ", max %" B_PRId32 1578332cc6bcSAxel Dörfler ", filter-type %" B_PRId32 "\n", node.node, buf_num_inputs, 1579332cc6bcSAxel Dörfler filter_type); 15805ac4fbd7Sbeveloper 158176669a29Sbeveloper int32 i; 1582b65a0ac5SJérôme Duval for (i = 0, list.Rewind(); list.GetNext(&input);) { 158334c72144SAxel Dörfler if (filter_type != B_MEDIA_UNKNOWN_TYPE 158434c72144SAxel Dörfler && filter_type != input->format.type) { 158534c72144SAxel Dörfler // media_type used, but doesn't match 158634c72144SAxel Dörfler continue; 158734c72144SAxel Dörfler } 158834c72144SAxel Dörfler if (input->source != media_source::null) { 158934c72144SAxel Dörfler // consumer source already connected 159034c72144SAxel Dörfler continue; 159134c72144SAxel Dörfler } 159234c72144SAxel Dörfler 15933620737cSbeveloper out_free_inputs[i] = *input; 15943620737cSbeveloper *out_total_count += 1; 15953620737cSbeveloper buf_num_inputs -= 1; 15965ac4fbd7Sbeveloper #if DEBUG >= 3 15975ac4fbd7Sbeveloper PRINT_OUTPUT(" input", out_free_inputs[i]); 15985ac4fbd7Sbeveloper #endif 15993620737cSbeveloper if (buf_num_inputs == 0) 16003620737cSbeveloper break; 1601b65a0ac5SJérôme Duval i++; 16023620737cSbeveloper } 16033620737cSbeveloper 16048b04ffc1Sbeveloper MediaRosterEx(this)->PublishInputs(node, &list); 16053620737cSbeveloper return B_OK; 160652a38012Sejakowatz } 160752a38012Sejakowatz 160852a38012Sejakowatz 160952a38012Sejakowatz status_t 161052a38012Sejakowatz BMediaRoster::GetConnectedInputsFor(const media_node& node, 161134c72144SAxel Dörfler media_input* out_active_inputs, int32 buf_num_inputs, 161252a38012Sejakowatz int32* out_total_count) 161352a38012Sejakowatz { 16143620737cSbeveloper CALLED(); 161540f36b03Sbeveloper if (IS_INVALID_NODE(node) || (node.kind & B_BUFFER_CONSUMER) == 0) 16163620737cSbeveloper return B_MEDIA_BAD_NODE; 16173620737cSbeveloper if (out_active_inputs == NULL || out_total_count == NULL) 16183620737cSbeveloper return B_BAD_VALUE; 16193620737cSbeveloper 162076669a29Sbeveloper List<media_input> list; 16213620737cSbeveloper media_input *input; 16223620737cSbeveloper status_t rv; 16233620737cSbeveloper 16241299bfb2Sbeveloper *out_total_count = 0; 16251299bfb2Sbeveloper 16268b04ffc1Sbeveloper rv = MediaRosterEx(this)->GetAllInputs(node, &list); 16273620737cSbeveloper if (B_OK != rv) 16283620737cSbeveloper return rv; 16293620737cSbeveloper 1630332cc6bcSAxel Dörfler PRINT(4, "BMediaRoster::GetConnectedInputsFor node %" B_PRId32 ", max %" 1631332cc6bcSAxel Dörfler B_PRId32 "\n", node.node, buf_num_inputs); 16325ac4fbd7Sbeveloper 163376669a29Sbeveloper int32 i; 1634b65a0ac5SJérôme Duval for (i = 0, list.Rewind(); list.GetNext(&input);) { 16353620737cSbeveloper if (input->source == media_source::null) 16363620737cSbeveloper continue; // consumer source not connected 16373620737cSbeveloper out_active_inputs[i] = *input; 16383620737cSbeveloper *out_total_count += 1; 16393620737cSbeveloper buf_num_inputs -= 1; 16405ac4fbd7Sbeveloper #if DEBUG >= 3 16415ac4fbd7Sbeveloper PRINT_OUTPUT(" input ", out_active_inputs[i]); 16425ac4fbd7Sbeveloper #endif 16433620737cSbeveloper if (buf_num_inputs == 0) 16443620737cSbeveloper break; 1645b65a0ac5SJérôme Duval i++; 16463620737cSbeveloper } 16473620737cSbeveloper 16488b04ffc1Sbeveloper MediaRosterEx(this)->PublishInputs(node, &list); 16493620737cSbeveloper return B_OK; 165052a38012Sejakowatz } 165152a38012Sejakowatz 165252a38012Sejakowatz 165352a38012Sejakowatz status_t 165434c72144SAxel Dörfler BMediaRoster::GetAllInputsFor(const media_node& node, media_input* out_inputs, 165534c72144SAxel Dörfler int32 buf_num_inputs, int32* out_total_count) 165652a38012Sejakowatz { 165752a38012Sejakowatz CALLED(); 165840f36b03Sbeveloper if (IS_INVALID_NODE(node) || (node.kind & B_BUFFER_CONSUMER) == 0) 165952a38012Sejakowatz return B_MEDIA_BAD_NODE; 166052a38012Sejakowatz if (out_inputs == NULL || out_total_count == NULL) 166152a38012Sejakowatz return B_BAD_VALUE; 166252a38012Sejakowatz 166376669a29Sbeveloper List<media_input> list; 16643620737cSbeveloper media_input *input; 166552a38012Sejakowatz status_t rv; 166652a38012Sejakowatz 16671299bfb2Sbeveloper *out_total_count = 0; 16681299bfb2Sbeveloper 16698b04ffc1Sbeveloper rv = MediaRosterEx(this)->GetAllInputs(node, &list); 16703620737cSbeveloper if (B_OK != rv) 16713620737cSbeveloper return rv; 16723620737cSbeveloper 1673332cc6bcSAxel Dörfler PRINT(4, "BMediaRoster::GetAllInputsFor node %" B_PRId32 ", max %" B_PRId32 1674332cc6bcSAxel Dörfler "\n", node.node, buf_num_inputs); 16755ac4fbd7Sbeveloper 167676669a29Sbeveloper int32 i; 167776669a29Sbeveloper for (i = 0, list.Rewind(); list.GetNext(&input); i++) { 16783620737cSbeveloper out_inputs[i] = *input; 167952a38012Sejakowatz *out_total_count += 1; 16803620737cSbeveloper buf_num_inputs -= 1; 16815ac4fbd7Sbeveloper #if DEBUG >= 3 16825ac4fbd7Sbeveloper PRINT_OUTPUT(" input ", out_inputs[i]); 16835ac4fbd7Sbeveloper #endif 16843620737cSbeveloper if (buf_num_inputs == 0) 16853620737cSbeveloper break; 168652a38012Sejakowatz } 168752a38012Sejakowatz 16888b04ffc1Sbeveloper MediaRosterEx(this)->PublishInputs(node, &list); 16893620737cSbeveloper return B_OK; 169052a38012Sejakowatz } 169152a38012Sejakowatz 169252a38012Sejakowatz 169352a38012Sejakowatz status_t 169452a38012Sejakowatz BMediaRoster::GetFreeOutputsFor(const media_node& node, 169534c72144SAxel Dörfler media_output* out_free_outputs, int32 buf_num_outputs, 169634c72144SAxel Dörfler int32* out_total_count, media_type filter_type) 169752a38012Sejakowatz { 16983620737cSbeveloper CALLED(); 169940f36b03Sbeveloper if (IS_INVALID_NODE(node) || (node.kind & B_BUFFER_PRODUCER) == 0) 17003620737cSbeveloper return B_MEDIA_BAD_NODE; 17013620737cSbeveloper if (out_free_outputs == NULL || out_total_count == NULL) 17023620737cSbeveloper return B_BAD_VALUE; 17033620737cSbeveloper 170476669a29Sbeveloper List<media_output> list; 17053620737cSbeveloper media_output *output; 17063620737cSbeveloper status_t rv; 17073620737cSbeveloper 17081299bfb2Sbeveloper *out_total_count = 0; 17091299bfb2Sbeveloper 17108b04ffc1Sbeveloper rv = MediaRosterEx(this)->GetAllOutputs(node, &list); 17113620737cSbeveloper if (B_OK != rv) 17123620737cSbeveloper return rv; 17133620737cSbeveloper 1714332cc6bcSAxel Dörfler PRINT(4, "BMediaRoster::GetFreeOutputsFor node %" B_PRId32 ", max %" 1715332cc6bcSAxel Dörfler B_PRId32 ", filter-type %" B_PRId32 "\n", node.node, buf_num_outputs, 1716332cc6bcSAxel Dörfler filter_type); 17175ac4fbd7Sbeveloper 171876669a29Sbeveloper int32 i; 1719b65a0ac5SJérôme Duval for (i = 0, list.Rewind(); list.GetNext(&output);) { 172034c72144SAxel Dörfler if (filter_type != B_MEDIA_UNKNOWN_TYPE 172134c72144SAxel Dörfler && filter_type != output->format.type) { 172234c72144SAxel Dörfler // media_type used, but doesn't match 172334c72144SAxel Dörfler continue; 172434c72144SAxel Dörfler } 172534c72144SAxel Dörfler if (output->destination != media_destination::null) { 172634c72144SAxel Dörfler // producer destination already connected 172734c72144SAxel Dörfler continue; 172834c72144SAxel Dörfler } 172934c72144SAxel Dörfler 17303620737cSbeveloper out_free_outputs[i] = *output; 17313620737cSbeveloper *out_total_count += 1; 17323620737cSbeveloper buf_num_outputs -= 1; 17335ac4fbd7Sbeveloper #if DEBUG >= 3 17345ac4fbd7Sbeveloper PRINT_OUTPUT(" output ", out_free_outputs[i]); 17355ac4fbd7Sbeveloper #endif 17363620737cSbeveloper if (buf_num_outputs == 0) 17373620737cSbeveloper break; 1738b65a0ac5SJérôme Duval i++; 17393620737cSbeveloper } 17403620737cSbeveloper 17418b04ffc1Sbeveloper MediaRosterEx(this)->PublishOutputs(node, &list); 17423620737cSbeveloper return B_OK; 174352a38012Sejakowatz } 174452a38012Sejakowatz 174552a38012Sejakowatz 174652a38012Sejakowatz status_t 174752a38012Sejakowatz BMediaRoster::GetConnectedOutputsFor(const media_node& node, 174834c72144SAxel Dörfler media_output* out_active_outputs, int32 buf_num_outputs, 174952a38012Sejakowatz int32* out_total_count) 175052a38012Sejakowatz { 17513620737cSbeveloper CALLED(); 175240f36b03Sbeveloper if (IS_INVALID_NODE(node) || (node.kind & B_BUFFER_PRODUCER) == 0) 17533620737cSbeveloper return B_MEDIA_BAD_NODE; 17543620737cSbeveloper if (out_active_outputs == NULL || out_total_count == NULL) 17553620737cSbeveloper return B_BAD_VALUE; 17563620737cSbeveloper 175776669a29Sbeveloper List<media_output> list; 17583620737cSbeveloper media_output *output; 17593620737cSbeveloper status_t rv; 17603620737cSbeveloper 17611299bfb2Sbeveloper *out_total_count = 0; 17621299bfb2Sbeveloper 17638b04ffc1Sbeveloper rv = MediaRosterEx(this)->GetAllOutputs(node, &list); 17643620737cSbeveloper if (B_OK != rv) 17653620737cSbeveloper return rv; 17663620737cSbeveloper 1767332cc6bcSAxel Dörfler PRINT(4, "BMediaRoster::GetConnectedOutputsFor node %" B_PRId32 ", max %" 1768332cc6bcSAxel Dörfler B_PRId32 "\n", node.node, buf_num_outputs); 17695ac4fbd7Sbeveloper 177076669a29Sbeveloper int32 i; 1771b65a0ac5SJérôme Duval for (i = 0, list.Rewind(); list.GetNext(&output);) { 177234c72144SAxel Dörfler if (output->destination == media_destination::null) { 177334c72144SAxel Dörfler // producer destination not connected 177434c72144SAxel Dörfler continue; 177534c72144SAxel Dörfler } 17763620737cSbeveloper out_active_outputs[i] = *output; 17773620737cSbeveloper *out_total_count += 1; 17783620737cSbeveloper buf_num_outputs -= 1; 17795ac4fbd7Sbeveloper #if DEBUG >= 3 17805ac4fbd7Sbeveloper PRINT_OUTPUT(" output ", out_active_outputs[i]); 17815ac4fbd7Sbeveloper #endif 17823620737cSbeveloper if (buf_num_outputs == 0) 17833620737cSbeveloper break; 1784b65a0ac5SJérôme Duval i++; 17853620737cSbeveloper } 17863620737cSbeveloper 17878b04ffc1Sbeveloper MediaRosterEx(this)->PublishOutputs(node, &list); 17883620737cSbeveloper return B_OK; 178952a38012Sejakowatz } 179052a38012Sejakowatz 179152a38012Sejakowatz 179252a38012Sejakowatz status_t 179352a38012Sejakowatz BMediaRoster::GetAllOutputsFor(const media_node& node, 179434c72144SAxel Dörfler media_output* out_outputs, int32 buf_num_outputs, int32* out_total_count) 179552a38012Sejakowatz { 179652a38012Sejakowatz CALLED(); 179740f36b03Sbeveloper if (IS_INVALID_NODE(node) || (node.kind & B_BUFFER_PRODUCER) == 0) 179852a38012Sejakowatz return B_MEDIA_BAD_NODE; 179952a38012Sejakowatz if (out_outputs == NULL || out_total_count == NULL) 180052a38012Sejakowatz return B_BAD_VALUE; 180152a38012Sejakowatz 180276669a29Sbeveloper List<media_output> list; 18033620737cSbeveloper media_output *output; 180452a38012Sejakowatz status_t rv; 180552a38012Sejakowatz 18061299bfb2Sbeveloper *out_total_count = 0; 18071299bfb2Sbeveloper 18088b04ffc1Sbeveloper rv = MediaRosterEx(this)->GetAllOutputs(node, &list); 18093620737cSbeveloper if (B_OK != rv) 18103620737cSbeveloper return rv; 18113620737cSbeveloper 1812332cc6bcSAxel Dörfler PRINT(4, "BMediaRoster::GetAllOutputsFor node %" B_PRId32 ", max %" B_PRId32 1813332cc6bcSAxel Dörfler "\n", node.node, buf_num_outputs); 18145ac4fbd7Sbeveloper 181576669a29Sbeveloper int32 i; 181676669a29Sbeveloper for (i = 0, list.Rewind(); list.GetNext(&output); i++) { 18173620737cSbeveloper out_outputs[i] = *output; 181852a38012Sejakowatz *out_total_count += 1; 18193620737cSbeveloper buf_num_outputs -= 1; 18205ac4fbd7Sbeveloper #if DEBUG >= 3 18215ac4fbd7Sbeveloper PRINT_OUTPUT(" output ", out_outputs[i]); 18225ac4fbd7Sbeveloper #endif 18233620737cSbeveloper if (buf_num_outputs == 0) 18243620737cSbeveloper break; 182552a38012Sejakowatz } 182652a38012Sejakowatz 18278b04ffc1Sbeveloper MediaRosterEx(this)->PublishOutputs(node, &list); 18283620737cSbeveloper return B_OK; 182952a38012Sejakowatz } 183052a38012Sejakowatz 183152a38012Sejakowatz 183252a38012Sejakowatz status_t 183352a38012Sejakowatz BMediaRoster::StartWatching(const BMessenger& where) 183452a38012Sejakowatz { 1835eae26d3dSbeveloper CALLED(); 1836eae26d3dSbeveloper if (!where.IsValid()) { 18375ac4fbd7Sbeveloper ERROR("BMediaRoster::StartWatching: messenger invalid!\n"); 1838eae26d3dSbeveloper return B_BAD_VALUE; 1839eae26d3dSbeveloper } 184034c72144SAxel Dörfler return BPrivate::media::notifications::Register(where, media_node::null, 184134c72144SAxel Dörfler B_MEDIA_WILDCARD); 184252a38012Sejakowatz } 184352a38012Sejakowatz 184452a38012Sejakowatz 184552a38012Sejakowatz status_t 184634c72144SAxel Dörfler BMediaRoster::StartWatching(const BMessenger & where, int32 notificationType) 184752a38012Sejakowatz { 1848eae26d3dSbeveloper CALLED(); 1849eae26d3dSbeveloper if (!where.IsValid()) { 18505ac4fbd7Sbeveloper ERROR("BMediaRoster::StartWatching: messenger invalid!\n"); 1851eae26d3dSbeveloper return B_BAD_VALUE; 1852eae26d3dSbeveloper } 185334c72144SAxel Dörfler if (!BPrivate::media::notifications::IsValidNotificationRequest(false, 185434c72144SAxel Dörfler notificationType)) { 18555ac4fbd7Sbeveloper ERROR("BMediaRoster::StartWatching: notificationType invalid!\n"); 1856eae26d3dSbeveloper return B_BAD_VALUE; 1857eae26d3dSbeveloper } 185834c72144SAxel Dörfler return BPrivate::media::notifications::Register(where, media_node::null, 185934c72144SAxel Dörfler notificationType); 186052a38012Sejakowatz } 186152a38012Sejakowatz 186252a38012Sejakowatz 186352a38012Sejakowatz status_t 186434c72144SAxel Dörfler BMediaRoster::StartWatching(const BMessenger& where, const media_node& node, 186552a38012Sejakowatz int32 notificationType) 186652a38012Sejakowatz { 1867eae26d3dSbeveloper CALLED(); 1868eae26d3dSbeveloper if (!where.IsValid()) { 18695ac4fbd7Sbeveloper ERROR("BMediaRoster::StartWatching: messenger invalid!\n"); 1870eae26d3dSbeveloper return B_BAD_VALUE; 1871eae26d3dSbeveloper } 187240f36b03Sbeveloper if (IS_INVALID_NODE(node)) { 18735ac4fbd7Sbeveloper ERROR("BMediaRoster::StartWatching: node invalid!\n"); 1874eae26d3dSbeveloper return B_MEDIA_BAD_NODE; 1875eae26d3dSbeveloper } 187634c72144SAxel Dörfler if (!BPrivate::media::notifications::IsValidNotificationRequest(true, 187734c72144SAxel Dörfler notificationType)) { 18785ac4fbd7Sbeveloper ERROR("BMediaRoster::StartWatching: notificationType invalid!\n"); 1879eae26d3dSbeveloper return B_BAD_VALUE; 1880eae26d3dSbeveloper } 188134c72144SAxel Dörfler return BPrivate::media::notifications::Register(where, node, 188234c72144SAxel Dörfler notificationType); 188352a38012Sejakowatz } 188452a38012Sejakowatz 188552a38012Sejakowatz 188652a38012Sejakowatz status_t 188752a38012Sejakowatz BMediaRoster::StopWatching(const BMessenger& where) 188852a38012Sejakowatz { 1889eae26d3dSbeveloper CALLED(); 1890eae26d3dSbeveloper // messenger may already be invalid, so we don't check this 189134c72144SAxel Dörfler return BPrivate::media::notifications::Unregister(where, media_node::null, 189234c72144SAxel Dörfler B_MEDIA_WILDCARD); 189352a38012Sejakowatz } 189452a38012Sejakowatz 189552a38012Sejakowatz 189652a38012Sejakowatz status_t 189734c72144SAxel Dörfler BMediaRoster::StopWatching(const BMessenger& where, int32 notificationType) 189852a38012Sejakowatz { 1899eae26d3dSbeveloper CALLED(); 1900eae26d3dSbeveloper // messenger may already be invalid, so we don't check this 190134c72144SAxel Dörfler if (!BPrivate::media::notifications::IsValidNotificationRequest(false, 190234c72144SAxel Dörfler notificationType)) { 19035ac4fbd7Sbeveloper ERROR("BMediaRoster::StopWatching: notificationType invalid!\n"); 1904eae26d3dSbeveloper return B_BAD_VALUE; 1905eae26d3dSbeveloper } 190634c72144SAxel Dörfler return BPrivate::media::notifications::Unregister(where, media_node::null, 190734c72144SAxel Dörfler notificationType); 190852a38012Sejakowatz } 190952a38012Sejakowatz 191052a38012Sejakowatz 191152a38012Sejakowatz status_t 191234c72144SAxel Dörfler BMediaRoster::StopWatching(const BMessenger& where, const media_node& node, 191352a38012Sejakowatz int32 notificationType) 191452a38012Sejakowatz { 1915eae26d3dSbeveloper CALLED(); 1916eae26d3dSbeveloper // messenger may already be invalid, so we don't check this 191740f36b03Sbeveloper if (IS_INVALID_NODE(node)) { 19185ac4fbd7Sbeveloper ERROR("BMediaRoster::StopWatching: node invalid!\n"); 1919eae26d3dSbeveloper return B_MEDIA_BAD_NODE; 1920eae26d3dSbeveloper } 192134c72144SAxel Dörfler if (!BPrivate::media::notifications::IsValidNotificationRequest(true, 192234c72144SAxel Dörfler notificationType)) { 19235ac4fbd7Sbeveloper ERROR("BMediaRoster::StopWatching: notificationType invalid!\n"); 1924eae26d3dSbeveloper return B_BAD_VALUE; 1925eae26d3dSbeveloper } 192634c72144SAxel Dörfler return BPrivate::media::notifications::Unregister(where, node, 192734c72144SAxel Dörfler notificationType); 192852a38012Sejakowatz } 192952a38012Sejakowatz 193052a38012Sejakowatz 193152a38012Sejakowatz status_t 193252a38012Sejakowatz BMediaRoster::RegisterNode(BMediaNode* node) 193352a38012Sejakowatz { 193454187cc6Sbeveloper CALLED(); 193554187cc6Sbeveloper // addon-id = -1 (unused), addon-flavor-id = 0 (unused, too) 193654187cc6Sbeveloper return MediaRosterEx(this)->RegisterNode(node, -1, 0); 193754187cc6Sbeveloper } 193854187cc6Sbeveloper 193954187cc6Sbeveloper 194054187cc6Sbeveloper status_t 19419c3b4706SAxel Dörfler BMediaRosterEx::RegisterNode(BMediaNode* node, media_addon_id addOnID, 19429dec2310SAxel Dörfler int32 flavorID) 194354187cc6Sbeveloper { 194452a38012Sejakowatz CALLED(); 194552a38012Sejakowatz if (node == NULL) 194652a38012Sejakowatz return B_BAD_VALUE; 194752a38012Sejakowatz 194854187cc6Sbeveloper // some sanity check 194954187cc6Sbeveloper // I'm not sure if the media kit warrants to call BMediaNode::AddOn() here. 195054187cc6Sbeveloper // Perhaps we don't need it. 19519dec2310SAxel Dörfler DEBUG_ONLY( 19529dec2310SAxel Dörfler int32 testFlavorID; 19539dec2310SAxel Dörfler BMediaAddOn* addon = node->AddOn(&testFlavorID); 19549dec2310SAxel Dörfler 19556813f2c7SIngo Weinhold ASSERT(addOnID == (addon != NULL ? addon->AddonID() : -1)); 1956e817f41eSFredrik Modéen // ASSERT(flavorID == testFlavorID); 19579dec2310SAxel Dörfler ); 195852a38012Sejakowatz 19599e9417d2Sbeveloper server_register_node_request request; 19609e9417d2Sbeveloper server_register_node_reply reply; 19619e9417d2Sbeveloper 19629c3b4706SAxel Dörfler request.add_on_id = addOnID; 19639c3b4706SAxel Dörfler request.flavor_id = flavorID; 19649e9417d2Sbeveloper strcpy(request.name, node->Name()); 19659e9417d2Sbeveloper request.kinds = node->Kinds(); 19669e9417d2Sbeveloper request.port = node->ControlPort(); 19679dec2310SAxel Dörfler request.team = BPrivate::current_team(); 19689e9417d2Sbeveloper 196934c72144SAxel Dörfler TRACE("BMediaRoster::RegisterNode: sending SERVER_REGISTER_NODE: port " 1970332cc6bcSAxel Dörfler "%" B_PRId32 ", kinds 0x%" B_PRIx64 ", team %" B_PRId32 ", name '%s'\n", 1971332cc6bcSAxel Dörfler request.port, request.kinds, request.team, request.name); 19721299bfb2Sbeveloper 19739c3b4706SAxel Dörfler status_t status = QueryServer(SERVER_REGISTER_NODE, &request, 19749c3b4706SAxel Dörfler sizeof(request), &reply, sizeof(reply)); 19759c3b4706SAxel Dörfler if (status != B_OK) { 19769c3b4706SAxel Dörfler ERROR("BMediaRoster::RegisterNode: failed to register node %s: %s\n", 19779c3b4706SAxel Dörfler node->Name(), strerror(status)); 19789c3b4706SAxel Dörfler return status; 19799e9417d2Sbeveloper } 19809e9417d2Sbeveloper 198134c72144SAxel Dörfler TRACE("BMediaRoster::RegisterNode: QueryServer SERVER_REGISTER_NODE " 198234c72144SAxel Dörfler "finished\n"); 19834295907bSbeveloper 19848b04ffc1Sbeveloper // we are a friend class of BMediaNode and initialize this member variable 19859dec2310SAxel Dörfler node->fNodeID = reply.node_id; 19869dec2310SAxel Dörfler ASSERT(reply.node_id == node->Node().node); 19879dec2310SAxel Dörfler ASSERT(reply.node_id == node->ID()); 19889e9417d2Sbeveloper 19899e9417d2Sbeveloper // call the callback 19909e9417d2Sbeveloper node->NodeRegistered(); 19913620737cSbeveloper 19924295907bSbeveloper TRACE("BMediaRoster::RegisterNode: NodeRegistered callback finished\n"); 19934295907bSbeveloper 199434c72144SAxel Dörfler // if the BMediaNode also inherits from BTimeSource, we need to call 199534c72144SAxel Dörfler // BTimeSource::FinishCreate() 19969c3b4706SAxel Dörfler if ((node->Kinds() & B_TIME_SOURCE) != 0) { 19979c3b4706SAxel Dörfler if (BTimeSource* timeSource = dynamic_cast<BTimeSource*>(node)) 19989c3b4706SAxel Dörfler timeSource->FinishCreate(); 19990e21b167Sbeveloper } 20000e21b167Sbeveloper 20014295907bSbeveloper TRACE("BMediaRoster::RegisterNode: publishing inputs/outputs\n"); 20024295907bSbeveloper 20033620737cSbeveloper // register existing inputs and outputs with the 20043620737cSbeveloper // media_server, this allows GetLiveNodes() to work 20053620737cSbeveloper // with created, but unconnected nodes. 20064d2d96e0Sbeveloper // The node control loop might not be running, or might deadlock 20074d2d96e0Sbeveloper // if we send a message and wait for a reply here. 20084d2d96e0Sbeveloper // We have a pointer to the node, and thus call the functions directly 20094295907bSbeveloper 20109c3b4706SAxel Dörfler if ((node->Kinds() & B_BUFFER_PRODUCER) != 0) { 20119c3b4706SAxel Dörfler if (BBufferProducer* producer = dynamic_cast<BBufferProducer*>(node)) { 2012359ac306Sbeveloper List<media_output> list; 20139c3b4706SAxel Dörfler if (GetAllOutputs(producer, &list) == B_OK) 2014359ac306Sbeveloper PublishOutputs(node->Node(), &list); 201521871f38Sbeveloper } 20164d2d96e0Sbeveloper } 20179dec2310SAxel Dörfler if ((node->Kinds() & B_BUFFER_CONSUMER) != 0) { 20189c3b4706SAxel Dörfler if (BBufferConsumer* consumer = dynamic_cast<BBufferConsumer*>(node)) { 2019359ac306Sbeveloper List<media_input> list; 20209dec2310SAxel Dörfler if (GetAllInputs(consumer, &list) == B_OK) 2021359ac306Sbeveloper PublishInputs(node->Node(), &list); 20223620737cSbeveloper } 20234d2d96e0Sbeveloper } 202421871f38Sbeveloper 20254295907bSbeveloper TRACE("BMediaRoster::RegisterNode: sending NodesCreated\n"); 20264295907bSbeveloper 20279dec2310SAxel Dörfler BPrivate::media::notifications::NodesCreated(&reply.node_id, 1); 20284295907bSbeveloper 20294295907bSbeveloper TRACE("BMediaRoster::RegisterNode: finished\n"); 20304295907bSbeveloper 2031570f7d04Sbeveloper /* 20329c3b4706SAxel Dörfler TRACE("BMediaRoster::RegisterNode: registered node name '%s', id %ld, 20339c3b4706SAxel Dörfler addon %ld, flavor %ld\n", node->Name(), node->ID(), addOnID, flavorID); 2034570f7d04Sbeveloper TRACE("BMediaRoster::RegisterNode: node this %p\n", node); 20359c3b4706SAxel Dörfler TRACE("BMediaRoster::RegisterNode: node fConsumerThis %p\n", 20369c3b4706SAxel Dörfler node->fConsumerThis); 20379c3b4706SAxel Dörfler TRACE("BMediaRoster::RegisterNode: node fProducerThis %p\n", 20389c3b4706SAxel Dörfler node->fProducerThis); 20399c3b4706SAxel Dörfler TRACE("BMediaRoster::RegisterNode: node fFileInterfaceThis %p\n", 20409c3b4706SAxel Dörfler node->fFileInterfaceThis); 20419c3b4706SAxel Dörfler TRACE("BMediaRoster::RegisterNode: node fControllableThis %p\n", 20429c3b4706SAxel Dörfler node->fControllableThis); 20439c3b4706SAxel Dörfler TRACE("BMediaRoster::RegisterNode: node fTimeSourceThis %p\n", 20449c3b4706SAxel Dörfler node->fTimeSourceThis); 2045570f7d04Sbeveloper */ 20469e9417d2Sbeveloper return B_OK; 204752a38012Sejakowatz } 204852a38012Sejakowatz 204952a38012Sejakowatz 205052a38012Sejakowatz status_t 205152a38012Sejakowatz BMediaRoster::UnregisterNode(BMediaNode* node) 205252a38012Sejakowatz { 20539e9417d2Sbeveloper CALLED(); 20549e9417d2Sbeveloper if (node == NULL) 20559e9417d2Sbeveloper return B_BAD_VALUE; 20569e9417d2Sbeveloper 205760f15390Sbeveloper TRACE("BMediaRoster::UnregisterNode %ld (%p)\n", node->ID(), node); 205860f15390Sbeveloper 205929bb91d6SAxel Dörfler if ((node->fKinds & NODE_KIND_NO_REFCOUNTING) !=0) { 206034c72144SAxel Dörfler TRACE("BMediaRoster::UnregisterNode, trying to unregister reference " 206134c72144SAxel Dörfler "counting disabled timesource, node %ld, port %ld, team %ld\n", 20629dec2310SAxel Dörfler node->ID(), node->ControlPort(), BPrivate::current_team()); 206386bce45bSbeveloper return B_OK; 206486bce45bSbeveloper } 20658b04ffc1Sbeveloper if (node->ID() == NODE_UNREGISTERED_ID) { 206634c72144SAxel Dörfler PRINT(1, "Warning: BMediaRoster::UnregisterNode: node id %ld, name " 206734c72144SAxel Dörfler "'%s' already unregistered\n", node->ID(), node->Name()); 20689e9417d2Sbeveloper return B_OK; 20699e9417d2Sbeveloper } 207054187cc6Sbeveloper if (node->fRefCount != 0) { 207134c72144SAxel Dörfler PRINT(1, "Warning: BMediaRoster::UnregisterNode: node id %ld, name " 207234c72144SAxel Dörfler "'%s' has local reference count of %ld\n", node->ID(), node->Name(), 207334c72144SAxel Dörfler node->fRefCount); 207454187cc6Sbeveloper // no return here, we continue and unregister! 207554187cc6Sbeveloper } 207654187cc6Sbeveloper 207734c72144SAxel Dörfler // Calling BMediaAddOn::GetConfigurationFor(BMediaNode *node, 207834c72144SAxel Dörfler // BMessage *config) if this node was instanciated by an add-on needs to 207934c72144SAxel Dörfler // be done *somewhere* 208054187cc6Sbeveloper // We can't do it here because it is already to late (destructor of the node 208154187cc6Sbeveloper // might have been called). 20829e9417d2Sbeveloper 20839e9417d2Sbeveloper server_unregister_node_request request; 20849dec2310SAxel Dörfler request.node_id = node->ID(); 20859dec2310SAxel Dörfler request.team = BPrivate::current_team(); 20869e9417d2Sbeveloper 20871299bfb2Sbeveloper // send a notification 20889dec2310SAxel Dörfler BPrivate::media::notifications::NodesDeleted(&request.node_id, 1); 20891299bfb2Sbeveloper 209029bb91d6SAxel Dörfler server_unregister_node_reply reply; 2091c74afb57SJérôme Duval reply.add_on_id = -1; 209229bb91d6SAxel Dörfler status_t status = QueryServer(SERVER_UNREGISTER_NODE, &request, 209329bb91d6SAxel Dörfler sizeof(request), &reply, sizeof(reply)); 209429bb91d6SAxel Dörfler if (status != B_OK) { 2095332cc6bcSAxel Dörfler ERROR("BMediaRoster::UnregisterNode: failed to unregister node id %" 2096332cc6bcSAxel Dörfler B_PRId32 ", name '%s': %s\n", node->ID(), node->Name(), 2097332cc6bcSAxel Dörfler strerror(status)); 2098c74afb57SJérôme Duval BMediaAddOn *addon = node->AddOn(&reply.flavor_id); 2099c74afb57SJérôme Duval if (addon != NULL) 2100c74afb57SJérôme Duval reply.add_on_id = addon->AddonID(); 21019e9417d2Sbeveloper } 21029e9417d2Sbeveloper 21039c3b4706SAxel Dörfler if (reply.add_on_id != -1) { 210429bb91d6SAxel Dörfler // TODO: this doesn't look right 210529bb91d6SAxel Dörfler // Small problem here, we can't use DormantNodeManager::PutAddOn(), as 210634c72144SAxel Dörfler // UnregisterNode() is called by a dormant node itself (by the 210734c72144SAxel Dörfler // destructor). 210854187cc6Sbeveloper // The add-on that contains the node needs to remain in memory until the 210954187cc6Sbeveloper // destructor execution is finished. 211029bb91d6SAxel Dörfler // DormantNodeManager::PutAddOnDelayed() will delay unloading. 21119c3b4706SAxel Dörfler gDormantNodeManager->PutAddOnDelayed(reply.add_on_id); 2112cf4e2277Sbeveloper 211329bb91d6SAxel Dörfler status = MediaRosterEx(this)->DecrementAddonFlavorInstancesCount( 21149c3b4706SAxel Dörfler reply.add_on_id, reply.flavor_id); 211529bb91d6SAxel Dörfler if (status != B_OK) { 211634c72144SAxel Dörfler ERROR("BMediaRoster::UnregisterNode: " 211734c72144SAxel Dörfler "DecrementAddonFlavorInstancesCount() failed\n"); 211854187cc6Sbeveloper // this is really a problem, but we can't fail now 211954187cc6Sbeveloper } 21208b04ffc1Sbeveloper } 21219e9417d2Sbeveloper 21221299bfb2Sbeveloper // we are a friend class of BMediaNode and invalidate this member variable 21238b04ffc1Sbeveloper node->fNodeID = NODE_UNREGISTERED_ID; 21249e9417d2Sbeveloper 2125c74afb57SJérôme Duval return status; 212652a38012Sejakowatz } 212752a38012Sejakowatz 212852a38012Sejakowatz 212934c72144SAxel Dörfler //! Thread safe for multiple calls to Roster() 213052a38012Sejakowatz /*static*/ BMediaRoster* 213152a38012Sejakowatz BMediaRoster::Roster(status_t* out_error) 213252a38012Sejakowatz { 213352a38012Sejakowatz static BLocker locker("BMediaRoster::Roster locker"); 213452a38012Sejakowatz locker.Lock(); 21358496c38aSbeveloper if (out_error) 21368496c38aSbeveloper *out_error = B_OK; 21379def3bf7SStephan Aßmus if (sDefaultInstance == NULL) { 21388496c38aSbeveloper status_t err; 21399def3bf7SStephan Aßmus sDefaultInstance = new (std::nothrow) BMediaRosterEx(&err); 21409def3bf7SStephan Aßmus if (sDefaultInstance == NULL) 2141a715f908SStephan Aßmus err = B_NO_MEMORY; 2142a715f908SStephan Aßmus else if (err != B_OK) { 21439def3bf7SStephan Aßmus if (sDefaultInstance) { 21449def3bf7SStephan Aßmus sDefaultInstance->Lock(); 21459def3bf7SStephan Aßmus sDefaultInstance->Quit(); 21469def3bf7SStephan Aßmus sDefaultInstance = NULL; 2147dcfb6bfcSJérôme Duval } 21488496c38aSbeveloper if (out_error) 21498496c38aSbeveloper *out_error = err; 21508496c38aSbeveloper } 215152a38012Sejakowatz } 215252a38012Sejakowatz locker.Unlock(); 21539def3bf7SStephan Aßmus return sDefaultInstance; 215452a38012Sejakowatz } 215552a38012Sejakowatz 215652a38012Sejakowatz 215752a38012Sejakowatz /*static*/ BMediaRoster* 215852a38012Sejakowatz BMediaRoster::CurrentRoster() 215952a38012Sejakowatz { 21609def3bf7SStephan Aßmus return sDefaultInstance; 216152a38012Sejakowatz } 216252a38012Sejakowatz 216352a38012Sejakowatz 216452a38012Sejakowatz status_t 216534c72144SAxel Dörfler BMediaRoster::SetTimeSourceFor(media_node_id node, media_node_id time_source) 216652a38012Sejakowatz { 2167aac800c2Sbeveloper CALLED(); 216840f36b03Sbeveloper if (IS_INVALID_NODEID(node) || IS_INVALID_NODEID(time_source)) 2169aac800c2Sbeveloper return B_BAD_VALUE; 2170aac800c2Sbeveloper 2171aac800c2Sbeveloper media_node clone; 2172aac800c2Sbeveloper status_t rv, result; 2173aac800c2Sbeveloper 2174332cc6bcSAxel Dörfler TRACE("BMediaRoster::SetTimeSourceFor: node %" B_PRId32 " will be assigned " 2175332cc6bcSAxel Dörfler "time source %" B_PRId32 "\n", node, time_source); 2176332cc6bcSAxel Dörfler TRACE("BMediaRoster::SetTimeSourceFor: node %" B_PRId32 " time source %" 2177332cc6bcSAxel Dörfler B_PRId32 " enter\n", node, time_source); 21785917dd5bSbeveloper 217986bce45bSbeveloper // we need to get a clone of the node to have a port id 2180aac800c2Sbeveloper rv = GetNodeFor(node, &clone); 2181aac800c2Sbeveloper if (rv != B_OK) { 2182332cc6bcSAxel Dörfler ERROR("BMediaRoster::SetTimeSourceFor, GetNodeFor failed, node id %" 2183332cc6bcSAxel Dörfler B_PRId32 "\n", node); 218452a38012Sejakowatz return B_ERROR; 218552a38012Sejakowatz } 218652a38012Sejakowatz 218786bce45bSbeveloper // we just send the request to set time_source-id as timesource to the node, 218886bce45bSbeveloper // the NODE_SET_TIMESOURCE handler code will do the real assignment 2189aac800c2Sbeveloper result = B_OK; 2190aac800c2Sbeveloper node_set_timesource_command cmd; 2191aac800c2Sbeveloper cmd.timesource_id = time_source; 2192aac800c2Sbeveloper rv = SendToPort(clone.port, NODE_SET_TIMESOURCE, &cmd, sizeof(cmd)); 2193aac800c2Sbeveloper if (rv != B_OK) { 219434c72144SAxel Dörfler ERROR("BMediaRoster::SetTimeSourceFor, sending NODE_SET_TIMESOURCE " 2195332cc6bcSAxel Dörfler "failed, node id %" B_PRId32 "\n", node); 2196aac800c2Sbeveloper result = B_ERROR; 2197aac800c2Sbeveloper } 2198aac800c2Sbeveloper 219960f15390Sbeveloper // we release the clone 2200aac800c2Sbeveloper rv = ReleaseNode(clone); 2201aac800c2Sbeveloper if (rv != B_OK) { 2202332cc6bcSAxel Dörfler ERROR("BMediaRoster::SetTimeSourceFor, ReleaseNode failed, node id %" 2203332cc6bcSAxel Dörfler B_PRId32 "\n", node); 2204aac800c2Sbeveloper result = B_ERROR; 2205aac800c2Sbeveloper } 2206aac800c2Sbeveloper 2207332cc6bcSAxel Dörfler TRACE("BMediaRoster::SetTimeSourceFor: node %" B_PRId32 " time source %" 2208332cc6bcSAxel Dörfler B_PRId32 " leave\n", node, time_source); 22095917dd5bSbeveloper 2210aac800c2Sbeveloper return result; 2211aac800c2Sbeveloper } 2212aac800c2Sbeveloper 221352a38012Sejakowatz 221452a38012Sejakowatz status_t 221534c72144SAxel Dörfler BMediaRoster::GetParameterWebFor(const media_node& node, BParameterWeb** _web) 221652a38012Sejakowatz { 221728ad138aSbeveloper CALLED(); 221834c72144SAxel Dörfler if (_web == NULL) 221928ad138aSbeveloper return B_BAD_VALUE; 222028ad138aSbeveloper if (IS_INVALID_NODE(node)) 222128ad138aSbeveloper return B_MEDIA_BAD_NODE; 222228ad138aSbeveloper if ((node.kind & B_CONTROLLABLE) == 0) 222328ad138aSbeveloper return B_MEDIA_BAD_NODE; 222428ad138aSbeveloper 222528ad138aSbeveloper controllable_get_parameter_web_request request; 222628ad138aSbeveloper controllable_get_parameter_web_reply reply; 222734c72144SAxel Dörfler int32 requestsize[] = {B_PAGE_SIZE, 4 * B_PAGE_SIZE, 16 * B_PAGE_SIZE, 222834c72144SAxel Dörfler 64 * B_PAGE_SIZE, 128 * B_PAGE_SIZE, 256 * B_PAGE_SIZE, 0}; 222928ad138aSbeveloper int32 size; 223028ad138aSbeveloper 223134c72144SAxel Dörfler // TODO: it might be better to query the node for the (current) parameter 223234c72144SAxel Dörfler // size first 223328ad138aSbeveloper for (int i = 0; (size = requestsize[i]) != 0; i++) { 223428ad138aSbeveloper status_t rv; 223528ad138aSbeveloper area_id area; 223628ad138aSbeveloper void *data; 223734c72144SAxel Dörfler area = create_area("parameter web data", &data, B_ANY_ADDRESS, size, 223834c72144SAxel Dörfler B_NO_LOCK, B_READ_AREA | B_WRITE_AREA); 223928ad138aSbeveloper if (area < B_OK) { 224034c72144SAxel Dörfler ERROR("BMediaRoster::GetParameterWebFor couldn't create area of " 2241332cc6bcSAxel Dörfler "size %" B_PRId32 "\n", size); 224228ad138aSbeveloper return B_ERROR; 224328ad138aSbeveloper } 224434c72144SAxel Dörfler request.max_size = size; 224528ad138aSbeveloper request.area = area; 224634c72144SAxel Dörfler rv = QueryPort(node.port, CONTROLLABLE_GET_PARAMETER_WEB, &request, 224734c72144SAxel Dörfler sizeof(request), &reply, sizeof(reply)); 224828ad138aSbeveloper if (rv != B_OK) { 224934c72144SAxel Dörfler ERROR("BMediaRoster::GetParameterWebFor " 225034c72144SAxel Dörfler "CONTROLLABLE_GET_PARAMETER_WEB failed\n"); 225128ad138aSbeveloper delete_area(area); 225228ad138aSbeveloper return B_ERROR; 225328ad138aSbeveloper } 225428ad138aSbeveloper if (reply.size == 0) { 225528ad138aSbeveloper // no parameter web available 225634c72144SAxel Dörfler // TODO: should we return an error? 2257332cc6bcSAxel Dörfler ERROR("BMediaRoster::GetParameterWebFor node %" B_PRId32 2258332cc6bcSAxel Dörfler " has no parameter web\n", node.node); 225934c72144SAxel Dörfler *_web = new (std::nothrow) BParameterWeb(); 226028ad138aSbeveloper delete_area(area); 226134c72144SAxel Dörfler return *_web != NULL ? B_OK : B_NO_MEMORY; 226252a38012Sejakowatz } 226328ad138aSbeveloper if (reply.size > 0) { 226428ad138aSbeveloper // we got a flattened parameter web! 2265*df612ac9SRene Gollent BParameterWeb* web = new (std::nothrow) BParameterWeb(); 2266*df612ac9SRene Gollent if (web == NULL) 2267a715f908SStephan Aßmus rv = B_NO_MEMORY; 2268a715f908SStephan Aßmus else { 2269332cc6bcSAxel Dörfler printf("BMediaRoster::GetParameterWebFor Unflattening %" 2270332cc6bcSAxel Dörfler B_PRId32 " bytes, %#" B_PRIx32 ", %#" B_PRIx32 ", %#" 2271332cc6bcSAxel Dörfler B_PRIx32 ", %#" B_PRIx32 "\n", reply.size, 2272332cc6bcSAxel Dörfler ((uint32*)data)[0], ((uint32*)data)[1], ((uint32*)data)[2], 2273332cc6bcSAxel Dörfler ((uint32*)data)[3]); 227428ad138aSbeveloper 2275*df612ac9SRene Gollent rv = web->Unflatten(reply.code, data, reply.size); 227628ad138aSbeveloper if (rv != B_OK) { 227734c72144SAxel Dörfler ERROR("BMediaRoster::GetParameterWebFor Unflatten failed, " 227834c72144SAxel Dörfler "%s\n", strerror(rv)); 2279*df612ac9SRene Gollent delete web; 2280*df612ac9SRene Gollent } else 2281*df612ac9SRene Gollent *_web = web; 228228ad138aSbeveloper } 2283*df612ac9SRene Gollent 228428ad138aSbeveloper delete_area(area); 2285a715f908SStephan Aßmus return rv; 228628ad138aSbeveloper } 228728ad138aSbeveloper delete_area(area); 228828ad138aSbeveloper ASSERT(reply.size == -1); 228928ad138aSbeveloper // parameter web data was too large 229028ad138aSbeveloper // loop and try a larger size 229128ad138aSbeveloper } 2292332cc6bcSAxel Dörfler ERROR("BMediaRoster::GetParameterWebFor node %" B_PRId32 " has no " 2293332cc6bcSAxel Dörfler "parameter web larger than %" B_PRId32 "\n", node.node, size); 229428ad138aSbeveloper return B_ERROR; 229528ad138aSbeveloper } 229652a38012Sejakowatz 229752a38012Sejakowatz 229852a38012Sejakowatz status_t 229934c72144SAxel Dörfler BMediaRoster::StartControlPanel(const media_node& node, BMessenger* _messenger) 230052a38012Sejakowatz { 2301999cd0acSMaurice Kalinowski CALLED(); 2302999cd0acSMaurice Kalinowski 2303999cd0acSMaurice Kalinowski controllable_start_control_panel_request request; 2304999cd0acSMaurice Kalinowski controllable_start_control_panel_reply reply; 2305999cd0acSMaurice Kalinowski 2306999cd0acSMaurice Kalinowski request.node = node; 2307999cd0acSMaurice Kalinowski 2308999cd0acSMaurice Kalinowski status_t rv; 230934c72144SAxel Dörfler rv = QueryPort(node.port, CONTROLLABLE_START_CONTROL_PANEL, &request, 231034c72144SAxel Dörfler sizeof(request), &reply, sizeof(reply)); 2311999cd0acSMaurice Kalinowski if (rv != B_OK) 2312999cd0acSMaurice Kalinowski return rv; 2313999cd0acSMaurice Kalinowski 231434c72144SAxel Dörfler if (reply.team != -1 && _messenger != NULL) 231534c72144SAxel Dörfler *_messenger = BMessenger(NULL, reply.team); 2316999cd0acSMaurice Kalinowski 2317999cd0acSMaurice Kalinowski return B_OK; 231852a38012Sejakowatz } 231952a38012Sejakowatz 232052a38012Sejakowatz 232152a38012Sejakowatz status_t 232234c72144SAxel Dörfler BMediaRoster::GetDormantNodes(dormant_node_info* _info, int32* _count, 232334c72144SAxel Dörfler const media_format* hasInput, const media_format* hasOutput, 232434c72144SAxel Dörfler const char* name, uint64 requireKinds, uint64 denyKinds) 232552a38012Sejakowatz { 232652a38012Sejakowatz CALLED(); 232734c72144SAxel Dörfler if (_info == NULL || _count == NULL || *_count <= 0) 232852a38012Sejakowatz return B_BAD_VALUE; 232952a38012Sejakowatz 2330e4c87231SAxel Dörfler server_get_dormant_nodes_request request; 2331e4c87231SAxel Dörfler request.max_count = *_count; 2332e4c87231SAxel Dörfler request.has_input = hasInput != NULL; 233334c72144SAxel Dörfler if (hasInput != NULL) { 233434c72144SAxel Dörfler // TODO: we should not make a flat copy of media_format 2335e4c87231SAxel Dörfler request.input_format = *hasInput; 233634c72144SAxel Dörfler } 2337e4c87231SAxel Dörfler request.has_output = hasOutput != NULL; 233834c72144SAxel Dörfler if (hasOutput != NULL) { 233934c72144SAxel Dörfler // TODO: we should not make a flat copy of media_format 2340e4c87231SAxel Dörfler request.output_format = *hasOutput; 234134c72144SAxel Dörfler } 234234c72144SAxel Dörfler 2343e4c87231SAxel Dörfler request.has_name = name != NULL; 2344e4c87231SAxel Dörfler if (name != NULL) 2345e4c87231SAxel Dörfler strlcpy(request.name, name, sizeof(request.name)); 234652a38012Sejakowatz 2347e4c87231SAxel Dörfler request.require_kinds = requireKinds; 2348e4c87231SAxel Dörfler request.deny_kinds = denyKinds; 234952a38012Sejakowatz 2350e4c87231SAxel Dörfler server_get_dormant_nodes_reply reply; 2351e4c87231SAxel Dörfler status_t status = QueryServer(SERVER_GET_DORMANT_NODES, &request, 2352e4c87231SAxel Dörfler sizeof(request), &reply, sizeof(reply)); 23536cafce94SAxel Dörfler if (status != B_OK) 2354e4c87231SAxel Dörfler return status; 235552a38012Sejakowatz 235634c72144SAxel Dörfler *_count = reply.count; 235752a38012Sejakowatz 2358e4c87231SAxel Dörfler if (reply.count > 0) { 2359e4c87231SAxel Dörfler int32 code; 2360e4c87231SAxel Dörfler status = read_port(request.reply_port, &code, _info, 2361e4c87231SAxel Dörfler reply.count * sizeof(dormant_node_info)); 2362e4c87231SAxel Dörfler if (status < B_OK) 2363e4c87231SAxel Dörfler reply.result = status; 236452a38012Sejakowatz } 236552a38012Sejakowatz 236652a38012Sejakowatz return reply.result; 236752a38012Sejakowatz } 236852a38012Sejakowatz 2369e4c87231SAxel Dörfler 237034c72144SAxel Dörfler /*! This function is used to do the real work of instantiating a dormant node. 237134c72144SAxel Dörfler It is either called by the media_addon_server to instantiate a global node, 237234c72144SAxel Dörfler or it gets called from BMediaRoster::InstantiateDormantNode() to create a 237334c72144SAxel Dörfler local one. 237434c72144SAxel Dörfler 237534c72144SAxel Dörfler Checks concerning global/local are not done here. 23768b04ffc1Sbeveloper */ 237752a38012Sejakowatz status_t 237834c72144SAxel Dörfler BMediaRosterEx::InstantiateDormantNode(media_addon_id addonID, int32 flavorID, 237934c72144SAxel Dörfler team_id creator, media_node *_node) 238052a38012Sejakowatz { 238154187cc6Sbeveloper // This function is always called from the correct context, if the node 238254187cc6Sbeveloper // is supposed to be global, it is called from the media_addon_server. 238354187cc6Sbeveloper 238452a38012Sejakowatz // if B_FLAVOR_IS_GLOBAL, we need to use the BMediaAddOn object that 238552a38012Sejakowatz // resides in the media_addon_server 238652a38012Sejakowatz 23878b04ffc1Sbeveloper // RegisterNode() must be called for nodes instantiated from add-ons, 23888b04ffc1Sbeveloper // since the media kit warrants that it's done automatically. 238952a38012Sejakowatz 239034c72144SAxel Dörfler // addonID Indicates the ID number of the media add-on in which the 239134c72144SAxel Dörfler // node resides. 239234c72144SAxel Dörfler // flavorID Indicates the internal ID number that the add-on uses to 239334c72144SAxel Dörfler // identify the flavor, this is the number that was published 239434c72144SAxel Dörfler // by BMediaAddOn::GetFlavorAt() in the 23958b04ffc1Sbeveloper // flavor_info::internal_id field. 239634c72144SAxel Dörfler // creator The creator team is -1 if nodes are created locally. If 239734c72144SAxel Dörfler // created globally, it will contain (while called in 239834c72144SAxel Dörfler // media_addon_server context) the team-id of the team that 239934c72144SAxel Dörfler // requested the instantiation. 24008b04ffc1Sbeveloper 2401332cc6bcSAxel Dörfler TRACE("BMediaRosterEx::InstantiateDormantNode: addonID %" B_PRId32 2402332cc6bcSAxel Dörfler ", flavorID %" B_PRId32 "\n", addonID, flavorID); 24038b04ffc1Sbeveloper 24048b04ffc1Sbeveloper // Get flavor_info from the server 240534c72144SAxel Dörfler dormant_flavor_info info; 24068c6a6096Sbeveloper status_t rv; 240734c72144SAxel Dörfler rv = GetDormantFlavorInfo(addonID, flavorID, &info); 24088b04ffc1Sbeveloper if (rv != B_OK) { 240934c72144SAxel Dörfler ERROR("BMediaRosterEx::InstantiateDormantNode error: failed to get " 2410332cc6bcSAxel Dörfler "dormant_flavor_info for addon-id %" B_PRId32 ", flavor-id %" 2411332cc6bcSAxel Dörfler B_PRId32 "\n", addonID, flavorID); 241252a38012Sejakowatz return B_ERROR; 241352a38012Sejakowatz } 24148b04ffc1Sbeveloper 24151ecccf18SFrançois Revol ASSERT(info.internal_id == flavorID); 24168b04ffc1Sbeveloper 24178b04ffc1Sbeveloper // load the BMediaAddOn object 241829bb91d6SAxel Dörfler BMediaAddOn* addon = gDormantNodeManager->GetAddOn(addonID); 241934c72144SAxel Dörfler if (addon == NULL) { 24205ac4fbd7Sbeveloper ERROR("BMediaRosterEx::InstantiateDormantNode: GetAddon failed\n"); 24218b04ffc1Sbeveloper return B_ERROR; 24228b04ffc1Sbeveloper } 24238b04ffc1Sbeveloper 242454187cc6Sbeveloper // Now we need to try to increment the use count of this addon flavor 242554187cc6Sbeveloper // in the server. This can fail if the total number instances of this 242654187cc6Sbeveloper // flavor is limited. 242734c72144SAxel Dörfler rv = IncrementAddonFlavorInstancesCount(addonID, flavorID); 242854187cc6Sbeveloper if (rv != B_OK) { 242934c72144SAxel Dörfler ERROR("BMediaRosterEx::InstantiateDormantNode error: can't create " 2430332cc6bcSAxel Dörfler "more nodes for addon-id %" B_PRId32 ", flavor-id %" B_PRId32 "\n", 2431332cc6bcSAxel Dörfler addonID, flavorID); 243254187cc6Sbeveloper // Put the addon back into the pool 243329bb91d6SAxel Dörfler gDormantNodeManager->PutAddOn(addonID); 243454187cc6Sbeveloper return B_ERROR; 243554187cc6Sbeveloper } 243654187cc6Sbeveloper 24378b04ffc1Sbeveloper BMessage config; 243834c72144SAxel Dörfler rv = LoadNodeConfiguration(addonID, flavorID, &config); 243954187cc6Sbeveloper if (rv != B_OK) { 244034c72144SAxel Dörfler ERROR("BMediaRosterEx::InstantiateDormantNode: couldn't load " 2441332cc6bcSAxel Dörfler "configuration for addon-id %" B_PRId32 ", flavor-id %" B_PRId32 2442332cc6bcSAxel Dörfler "\n", addonID, flavorID); 244354187cc6Sbeveloper // do not return, this is a minor problem, not a reason to fail 244454187cc6Sbeveloper } 24458b04ffc1Sbeveloper 244634c72144SAxel Dörfler status_t status = B_OK; 244734c72144SAxel Dörfler BMediaNode* node = addon->InstantiateNodeFor(&info, &config, &status); 244834c72144SAxel Dörfler if (node == NULL) { 244934c72144SAxel Dörfler ERROR("BMediaRosterEx::InstantiateDormantNode: InstantiateNodeFor " 245034c72144SAxel Dörfler "failed\n"); 24518b04ffc1Sbeveloper 245254187cc6Sbeveloper // Put the addon back into the pool 245329bb91d6SAxel Dörfler gDormantNodeManager->PutAddOn(addonID); 245434c72144SAxel Dörfler 245554187cc6Sbeveloper // We must decrement the use count of this addon flavor in the 245654187cc6Sbeveloper // server to compensate the increment done in the beginning. 245734c72144SAxel Dörfler rv = DecrementAddonFlavorInstancesCount(addonID, flavorID); 245854187cc6Sbeveloper if (rv != B_OK) { 245934c72144SAxel Dörfler ERROR("BMediaRosterEx::InstantiateDormantNode: DecrementAddon" 246034c72144SAxel Dörfler "FlavorInstancesCount failed\n"); 246116b7eea4Sbeveloper } 246234c72144SAxel Dörfler return status != B_OK ? status : B_ERROR; 246354187cc6Sbeveloper } 246454187cc6Sbeveloper 246534c72144SAxel Dörfler rv = RegisterNode(node, addonID, flavorID); 24668c6a6096Sbeveloper if (rv != B_OK) { 24675ac4fbd7Sbeveloper ERROR("BMediaRosterEx::InstantiateDormantNode: RegisterNode failed\n"); 24688c6a6096Sbeveloper delete node; 246954187cc6Sbeveloper // Put the addon back into the pool 247029bb91d6SAxel Dörfler gDormantNodeManager->PutAddOn(addonID); 247154187cc6Sbeveloper // We must decrement the use count of this addon flavor in the 247254187cc6Sbeveloper // server to compensate the increment done in the beginning. 247334c72144SAxel Dörfler rv = DecrementAddonFlavorInstancesCount(addonID, flavorID); 247454187cc6Sbeveloper if (rv != B_OK) { 247534c72144SAxel Dörfler ERROR("BMediaRosterEx::InstantiateDormantNode: DecrementAddon" 247634c72144SAxel Dörfler "FlavorInstancesCount failed\n"); 247754187cc6Sbeveloper } 24788c6a6096Sbeveloper return B_ERROR; 24798c6a6096Sbeveloper } 24808c6a6096Sbeveloper 248154187cc6Sbeveloper if (creator != -1) { 248234c72144SAxel Dörfler // send a message to the server to assign team "creator" as creator 248334c72144SAxel Dörfler // of node "node->ID()" 2484332cc6bcSAxel Dörfler printf("!!! BMediaRosterEx::InstantiateDormantNode assigning team %" 2485332cc6bcSAxel Dörfler B_PRId32 " as creator of node %" B_PRId32 "\n", creator, 2486332cc6bcSAxel Dörfler node->ID()); 248734c72144SAxel Dörfler 248854187cc6Sbeveloper rv = MediaRosterEx(this)->SetNodeCreator(node->ID(), creator); 248954187cc6Sbeveloper if (rv != B_OK) { 249034c72144SAxel Dörfler ERROR("BMediaRosterEx::InstantiateDormantNode failed to assign " 2491332cc6bcSAxel Dörfler "team %" B_PRId32 " as creator of node %" B_PRId32 "\n", 2492332cc6bcSAxel Dörfler creator, node->ID()); 249354187cc6Sbeveloper // do not return, this is a minor problem, not a reason to fail 249454187cc6Sbeveloper } 249554187cc6Sbeveloper } 249654187cc6Sbeveloper 249754187cc6Sbeveloper // RegisterNode() does remember the add-on id in the server 249854187cc6Sbeveloper // and UnregisterNode() will call DormantNodeManager::PutAddon() 249954187cc6Sbeveloper // when the node is unregistered. 25008c6a6096Sbeveloper 250134c72144SAxel Dörfler *_node = node->Node(); 2502cf4e2277Sbeveloper 2503332cc6bcSAxel Dörfler TRACE("BMediaRosterEx::InstantiateDormantNode: addon-id %" B_PRId32 2504332cc6bcSAxel Dörfler ", flavor_id %" B_PRId32 " instanciated as node %" B_PRId32 ", port %" 2505332cc6bcSAxel Dörfler B_PRId32 " in team %" B_PRId32 "\n", addonID, flavorID, _node->node, 2506332cc6bcSAxel Dörfler _node->port, BPrivate::current_team()); 2507cf4e2277Sbeveloper 250816b7eea4Sbeveloper return B_OK; 250916b7eea4Sbeveloper } 251052a38012Sejakowatz 251152a38012Sejakowatz 251252a38012Sejakowatz status_t 251334c72144SAxel Dörfler BMediaRoster::InstantiateDormantNode(const dormant_node_info& info, 251434c72144SAxel Dörfler media_node* _node, uint32 flags) 25158b04ffc1Sbeveloper { 25168b04ffc1Sbeveloper CALLED(); 251734c72144SAxel Dörfler if (_node == NULL) 25188b04ffc1Sbeveloper return B_BAD_VALUE; 251934c72144SAxel Dörfler if (info.addon <= B_OK) { 2520332cc6bcSAxel Dörfler ERROR("BMediaRoster::InstantiateDormantNode error: addon-id %" B_PRId32 252134c72144SAxel Dörfler " invalid.\n", info.addon); 25228b04ffc1Sbeveloper return B_BAD_VALUE; 25238b04ffc1Sbeveloper } 25248b04ffc1Sbeveloper 2525332cc6bcSAxel Dörfler printf("BMediaRoster::InstantiateDormantNode: addon-id %" B_PRId32 2526332cc6bcSAxel Dörfler ", flavor_id %" B_PRId32 ", flags 0x%" B_PRIx32 "\n", info.addon, 2527332cc6bcSAxel Dörfler info.flavor_id, flags); 25288b04ffc1Sbeveloper 25298b04ffc1Sbeveloper // Get flavor_info from the server 253034c72144SAxel Dörfler // TODO: this is a little overhead, as we get the full blown 253134c72144SAxel Dörfler // dormant_flavor_info, 253234c72144SAxel Dörfler // TODO: but only need the flags. 253334c72144SAxel Dörfler dormant_flavor_info flavorInfo; 25348b04ffc1Sbeveloper status_t rv; 253534c72144SAxel Dörfler rv = MediaRosterEx(this)->GetDormantFlavorInfo(info.addon, info.flavor_id, 253634c72144SAxel Dörfler &flavorInfo); 25378b04ffc1Sbeveloper if (rv != B_OK) { 253834c72144SAxel Dörfler ERROR("BMediaRoster::InstantiateDormantNode: failed to get " 2539332cc6bcSAxel Dörfler "dormant_flavor_info for addon-id %" B_PRId32 ", flavor-id %" 2540332cc6bcSAxel Dörfler B_PRId32 "\n", info.addon, info.flavor_id); 2541626824eaSbeveloper return B_NAME_NOT_FOUND; 25428b04ffc1Sbeveloper } 25438b04ffc1Sbeveloper 254434c72144SAxel Dörfler ASSERT(flavorInfo.internal_id == info.flavor_id); 25458b04ffc1Sbeveloper 25468b04ffc1Sbeveloper #if DEBUG 254734c72144SAxel Dörfler printf("BMediaRoster::InstantiateDormantNode: name \"%s\", info \"%s\", " 2548332cc6bcSAxel Dörfler "flavor_flags 0x%" B_PRIx32 ", internal_id %" B_PRId32 2549332cc6bcSAxel Dörfler ", possible_count %" B_PRId32 "\n", flavorInfo.name, flavorInfo.info, 2550332cc6bcSAxel Dörfler flavorInfo.flavor_flags, flavorInfo.internal_id, 2551332cc6bcSAxel Dörfler flavorInfo.possible_count); 255234c72144SAxel Dörfler 255334c72144SAxel Dörfler if ((flags & B_FLAVOR_IS_LOCAL) != 0) { 255434c72144SAxel Dörfler printf("BMediaRoster::InstantiateDormantNode: caller requested " 255534c72144SAxel Dörfler "B_FLAVOR_IS_LOCAL\n"); 255634c72144SAxel Dörfler } 255734c72144SAxel Dörfler if ((flags & B_FLAVOR_IS_GLOBAL) != 0) { 255834c72144SAxel Dörfler printf("BMediaRoster::InstantiateDormantNode: caller requested " 255934c72144SAxel Dörfler "B_FLAVOR_IS_GLOBAL\n"); 256034c72144SAxel Dörfler } 256134c72144SAxel Dörfler if ((flavorInfo.flavor_flags & B_FLAVOR_IS_LOCAL) != 0) { 256234c72144SAxel Dörfler printf("BMediaRoster::InstantiateDormantNode: node requires " 256334c72144SAxel Dörfler "B_FLAVOR_IS_LOCAL\n"); 256434c72144SAxel Dörfler } 256534c72144SAxel Dörfler if ((flavorInfo.flavor_flags & B_FLAVOR_IS_GLOBAL) != 0) { 256634c72144SAxel Dörfler printf("BMediaRoster::InstantiateDormantNode: node requires " 256734c72144SAxel Dörfler "B_FLAVOR_IS_GLOBAL\n"); 256834c72144SAxel Dörfler } 25698b04ffc1Sbeveloper #endif 25708b04ffc1Sbeveloper 25718b04ffc1Sbeveloper // Make sure that flags demanded by the dormant node and those requested 25728b04ffc1Sbeveloper // by the caller are not incompatible. 257334c72144SAxel Dörfler if ((flavorInfo.flavor_flags & B_FLAVOR_IS_GLOBAL) != 0 257434c72144SAxel Dörfler && (flags & B_FLAVOR_IS_LOCAL) != 0) { 257534c72144SAxel Dörfler ERROR("BMediaRoster::InstantiateDormantNode: requested " 257634c72144SAxel Dörfler "B_FLAVOR_IS_LOCAL, but dormant node has B_FLAVOR_IS_GLOBAL\n"); 2577626824eaSbeveloper return B_NAME_NOT_FOUND; 25788b04ffc1Sbeveloper } 257934c72144SAxel Dörfler if ((flavorInfo.flavor_flags & B_FLAVOR_IS_LOCAL) != 0 258034c72144SAxel Dörfler && (flags & B_FLAVOR_IS_GLOBAL) != 0) { 258134c72144SAxel Dörfler ERROR("BMediaRoster::InstantiateDormantNode: requested " 258234c72144SAxel Dörfler "B_FLAVOR_IS_GLOBAL, but dormant node has B_FLAVOR_IS_LOCAL\n"); 2583626824eaSbeveloper return B_NAME_NOT_FOUND; 25848b04ffc1Sbeveloper } 258554187cc6Sbeveloper 25868b04ffc1Sbeveloper // If either the node, or the caller requested to make the instance global 258734c72144SAxel Dörfler // we will do it by forwarding this request into the media_addon_server, 258834c72144SAxel Dörfler // which in turn will call BMediaRosterEx::InstantiateDormantNode to create 258934c72144SAxel Dörfler // the node there and make it globally available. 259034c72144SAxel Dörfler if ((flavorInfo.flavor_flags & B_FLAVOR_IS_GLOBAL) != 0 259134c72144SAxel Dörfler || (flags & B_FLAVOR_IS_GLOBAL) != 0) { 259234c72144SAxel Dörfler TRACE("BMediaRoster::InstantiateDormantNode: creating global object " 259334c72144SAxel Dörfler "in media_addon_server\n"); 2594cf4e2277Sbeveloper 25959c3b4706SAxel Dörfler add_on_server_instantiate_dormant_node_request request; 25969c3b4706SAxel Dörfler add_on_server_instantiate_dormant_node_reply reply; 25979c3b4706SAxel Dörfler request.add_on_id = info.addon; 25989dec2310SAxel Dörfler request.flavor_id = info.flavor_id; 25999dec2310SAxel Dörfler request.creator_team = BPrivate::current_team(); 260034c72144SAxel Dörfler // creator team is allowed to also release global nodes 26019c3b4706SAxel Dörfler rv = QueryAddOnServer(ADD_ON_SERVER_INSTANTIATE_DORMANT_NODE, &request, 260234c72144SAxel Dörfler sizeof(request), &reply, sizeof(reply)); 260334c72144SAxel Dörfler if (rv == B_OK) 260434c72144SAxel Dörfler *_node = reply.node; 26058b04ffc1Sbeveloper } else { 260654187cc6Sbeveloper // creator team = -1, as this is a local node 260734c72144SAxel Dörfler rv = MediaRosterEx(this)->InstantiateDormantNode(info.addon, 260834c72144SAxel Dörfler info.flavor_id, -1, _node); 26098b04ffc1Sbeveloper } 2610626824eaSbeveloper if (rv != B_OK) { 261134c72144SAxel Dörfler *_node = media_node::null; 2612626824eaSbeveloper return B_NAME_NOT_FOUND; 2613626824eaSbeveloper } 2614626824eaSbeveloper return B_OK; 26158b04ffc1Sbeveloper } 26168b04ffc1Sbeveloper 26178b04ffc1Sbeveloper 26188b04ffc1Sbeveloper status_t 261934c72144SAxel Dörfler BMediaRoster::InstantiateDormantNode(const dormant_node_info& info, 262034c72144SAxel Dörfler media_node* _node) 26218b04ffc1Sbeveloper { 262234c72144SAxel Dörfler return InstantiateDormantNode(info, _node, 0); 26238b04ffc1Sbeveloper } 26248b04ffc1Sbeveloper 26258b04ffc1Sbeveloper 26268b04ffc1Sbeveloper status_t 262752a38012Sejakowatz BMediaRoster::GetDormantNodeFor(const media_node& node, 262834c72144SAxel Dörfler dormant_node_info* _info) 262952a38012Sejakowatz { 263085dfab2bSbeveloper CALLED(); 263134c72144SAxel Dörfler if (_info == NULL) 263285dfab2bSbeveloper return B_BAD_VALUE; 263340f36b03Sbeveloper if (IS_INVALID_NODE(node)) 263485dfab2bSbeveloper return B_MEDIA_BAD_NODE; 263552a38012Sejakowatz 263685dfab2bSbeveloper server_get_dormant_node_for_request request; 263785dfab2bSbeveloper server_get_dormant_node_for_reply reply; 263885dfab2bSbeveloper status_t rv; 263985dfab2bSbeveloper 264085dfab2bSbeveloper request.node = node; 264185dfab2bSbeveloper 264234c72144SAxel Dörfler rv = QueryServer(SERVER_GET_DORMANT_NODE_FOR, &request, sizeof(request), 264334c72144SAxel Dörfler &reply, sizeof(reply)); 264485dfab2bSbeveloper if (rv != B_OK) 264585dfab2bSbeveloper return rv; 264685dfab2bSbeveloper 264734c72144SAxel Dörfler *_info = reply.node_info; 264885dfab2bSbeveloper return B_OK; 264952a38012Sejakowatz } 265052a38012Sejakowatz 265134c72144SAxel Dörfler 265252a38012Sejakowatz status_t 265334c72144SAxel Dörfler BMediaRosterEx::GetDormantFlavorInfo(media_addon_id addonID, int32 flavorID, 265434c72144SAxel Dörfler dormant_flavor_info* _flavor) 265552a38012Sejakowatz { 265652a38012Sejakowatz CALLED(); 265734c72144SAxel Dörfler if (_flavor == NULL) 26589bedd42cSbeveloper return B_BAD_VALUE; 265952a38012Sejakowatz 2660e4c87231SAxel Dörfler // TODO: better use an area here as well! 266152a38012Sejakowatz 2662e4c87231SAxel Dörfler server_get_dormant_flavor_info_reply* reply 2663e4c87231SAxel Dörfler = (server_get_dormant_flavor_info_reply*)malloc(16300); 266434c72144SAxel Dörfler if (reply == NULL) 266534c72144SAxel Dörfler return B_NO_MEMORY; 266652a38012Sejakowatz 2667e4c87231SAxel Dörfler server_get_dormant_flavor_info_request request; 2668e4c87231SAxel Dörfler request.add_on_id = addonID; 2669e4c87231SAxel Dörfler request.flavor_id = flavorID; 2670e4c87231SAxel Dörfler 2671e4c87231SAxel Dörfler status_t status = QueryServer(SERVER_GET_DORMANT_FLAVOR_INFO, &request, 2672e4c87231SAxel Dörfler sizeof(request), reply, 16300); 26739dec2310SAxel Dörfler if (status != B_OK) { 267452a38012Sejakowatz free(reply); 26759dec2310SAxel Dörfler return status; 267652a38012Sejakowatz } 267752a38012Sejakowatz 26789dec2310SAxel Dörfler if (reply->result == B_OK) { 26799dec2310SAxel Dörfler status = _flavor->Unflatten(reply->type, &reply->flattened_data, 26809dec2310SAxel Dörfler reply->flattened_size); 26819dec2310SAxel Dörfler } else 26829dec2310SAxel Dörfler status = reply->result; 268352a38012Sejakowatz 268452a38012Sejakowatz free(reply); 26859dec2310SAxel Dörfler return status; 268652a38012Sejakowatz } 268752a38012Sejakowatz 268834c72144SAxel Dörfler 26898b04ffc1Sbeveloper status_t 269034c72144SAxel Dörfler BMediaRoster::GetDormantFlavorInfoFor(const dormant_node_info& dormant, 269134c72144SAxel Dörfler dormant_flavor_info* _flavor) 26928b04ffc1Sbeveloper { 269334c72144SAxel Dörfler return MediaRosterEx(this)->GetDormantFlavorInfo(dormant.addon, 269434c72144SAxel Dörfler dormant.flavor_id, _flavor); 26958b04ffc1Sbeveloper } 269652a38012Sejakowatz 269734c72144SAxel Dörfler 269860f15390Sbeveloper // Reports in outLatency the maximum latency found downstream from 269960f15390Sbeveloper // the specified BBufferProducer, producer, given the current connections. 270052a38012Sejakowatz status_t 270134c72144SAxel Dörfler BMediaRoster::GetLatencyFor(const media_node& producer, bigtime_t* _latency) 270252a38012Sejakowatz { 270360f15390Sbeveloper CALLED(); 270434c72144SAxel Dörfler if (_latency == NULL) 270560f15390Sbeveloper return B_BAD_VALUE; 270634c72144SAxel Dörfler if (IS_INVALID_NODE(producer) 270734c72144SAxel Dörfler || (producer.kind & B_BUFFER_PRODUCER) == 0) 270860f15390Sbeveloper return B_MEDIA_BAD_NODE; 270960f15390Sbeveloper 271060f15390Sbeveloper producer_get_latency_request request; 271160f15390Sbeveloper producer_get_latency_reply reply; 271260f15390Sbeveloper status_t rv; 271360f15390Sbeveloper 271434c72144SAxel Dörfler rv = QueryPort(producer.port, PRODUCER_GET_LATENCY, &request, 271534c72144SAxel Dörfler sizeof(request), &reply, sizeof(reply)); 271660f15390Sbeveloper if (rv != B_OK) 271760f15390Sbeveloper return rv; 271860f15390Sbeveloper 271934c72144SAxel Dörfler *_latency = reply.latency; 272060f15390Sbeveloper 2721ab9afde3SMarcus Overhagen // printf("BMediaRoster::GetLatencyFor producer %ld has maximum latency %Ld\n", producer.node, *out_latency); 2722aac800c2Sbeveloper return B_OK; 272352a38012Sejakowatz } 272452a38012Sejakowatz 272552a38012Sejakowatz 272652a38012Sejakowatz status_t 272752a38012Sejakowatz BMediaRoster::GetInitialLatencyFor(const media_node& producer, 272834c72144SAxel Dörfler bigtime_t* _latency, uint32* _flags) 272952a38012Sejakowatz { 2730b65a0ac5SJérôme Duval CALLED(); 273134c72144SAxel Dörfler if (_latency == NULL) 2732b65a0ac5SJérôme Duval return B_BAD_VALUE; 273334c72144SAxel Dörfler if (IS_INVALID_NODE(producer) 273434c72144SAxel Dörfler || (producer.kind & B_BUFFER_PRODUCER) == 0) 2735b65a0ac5SJérôme Duval return B_MEDIA_BAD_NODE; 2736b65a0ac5SJérôme Duval 2737b65a0ac5SJérôme Duval producer_get_initial_latency_request request; 2738b65a0ac5SJérôme Duval producer_get_initial_latency_reply reply; 2739b65a0ac5SJérôme Duval status_t rv; 2740b65a0ac5SJérôme Duval 274134c72144SAxel Dörfler rv = QueryPort(producer.port, PRODUCER_GET_INITIAL_LATENCY, &request, 274234c72144SAxel Dörfler sizeof(request), &reply, sizeof(reply)); 2743b65a0ac5SJérôme Duval if (rv != B_OK) 2744b65a0ac5SJérôme Duval return rv; 2745b65a0ac5SJérôme Duval 274634c72144SAxel Dörfler *_latency = reply.initial_latency; 274734c72144SAxel Dörfler if (_flags != NULL) 274834c72144SAxel Dörfler *_flags = reply.flags; 2749b65a0ac5SJérôme Duval 2750332cc6bcSAxel Dörfler TRACE("BMediaRoster::GetInitialLatencyFor producer %" B_PRId32 " has " 2751332cc6bcSAxel Dörfler "maximum initial latency %" B_PRId64 "\n", producer.node, *_latency); 2752aac800c2Sbeveloper return B_OK; 275352a38012Sejakowatz } 275452a38012Sejakowatz 275552a38012Sejakowatz 275652a38012Sejakowatz status_t 275734c72144SAxel Dörfler BMediaRoster::GetStartLatencyFor(const media_node& timeSource, 275834c72144SAxel Dörfler bigtime_t* _latency) 275952a38012Sejakowatz { 2760fc8b28b6SJérôme Duval CALLED(); 276134c72144SAxel Dörfler if (_latency == NULL) 2762fc8b28b6SJérôme Duval return B_BAD_VALUE; 276334c72144SAxel Dörfler if (IS_INVALID_NODE(timeSource) 276434c72144SAxel Dörfler || (timeSource.kind & B_TIME_SOURCE) == 0) 2765fc8b28b6SJérôme Duval return B_MEDIA_BAD_NODE; 2766fc8b28b6SJérôme Duval 2767fc8b28b6SJérôme Duval timesource_get_start_latency_request request; 2768fc8b28b6SJérôme Duval timesource_get_start_latency_reply reply; 2769fc8b28b6SJérôme Duval status_t rv; 2770fc8b28b6SJérôme Duval 277134c72144SAxel Dörfler rv = QueryPort(timeSource.port, TIMESOURCE_GET_START_LATENCY, &request, 277234c72144SAxel Dörfler sizeof(request), &reply, sizeof(reply)); 2773fc8b28b6SJérôme Duval if (rv != B_OK) 2774fc8b28b6SJérôme Duval return rv; 2775fc8b28b6SJérôme Duval 277634c72144SAxel Dörfler *_latency = reply.start_latency; 2777fc8b28b6SJérôme Duval 2778332cc6bcSAxel Dörfler TRACE("BMediaRoster::GetStartLatencyFor timesource %" B_PRId32 " has " 2779332cc6bcSAxel Dörfler "maximum initial latency %" B_PRId64 "\n", timeSource.node, *_latency); 2780aac800c2Sbeveloper return B_OK; 278152a38012Sejakowatz } 278252a38012Sejakowatz 278352a38012Sejakowatz 278452a38012Sejakowatz status_t 278534c72144SAxel Dörfler BMediaRoster::GetFileFormatsFor(const media_node& fileInterface, 278634c72144SAxel Dörfler media_file_format* _formats, int32* _numFormats) 278752a38012Sejakowatz { 278852a38012Sejakowatz UNIMPLEMENTED(); 278952a38012Sejakowatz return B_ERROR; 279052a38012Sejakowatz } 279152a38012Sejakowatz 279252a38012Sejakowatz 279352a38012Sejakowatz status_t 279434c72144SAxel Dörfler BMediaRoster::SetRefFor(const media_node& file_interface, const entry_ref& file, 279534c72144SAxel Dörfler bool createAndTruncate, bigtime_t* _length) 279652a38012Sejakowatz { 27976938364bSMaurice Kalinowski CALLED(); 27986938364bSMaurice Kalinowski 27996938364bSMaurice Kalinowski fileinterface_set_ref_request request; 28006938364bSMaurice Kalinowski fileinterface_set_ref_reply reply; 28016938364bSMaurice Kalinowski status_t rv; 28026938364bSMaurice Kalinowski 28036938364bSMaurice Kalinowski request.device = file.device; 28046938364bSMaurice Kalinowski request.directory = file.directory; 28056938364bSMaurice Kalinowski strcpy(request.name, file.name); 280634c72144SAxel Dörfler request.create = createAndTruncate; 280734c72144SAxel Dörfler if (_length != NULL) 280834c72144SAxel Dörfler request.duration = *_length; 28096938364bSMaurice Kalinowski 281034c72144SAxel Dörfler rv = QueryPort(file_interface.port, FILEINTERFACE_SET_REF, &request, 281134c72144SAxel Dörfler sizeof(request), &reply, sizeof(reply)); 28126938364bSMaurice Kalinowski if (rv != B_OK) 28136938364bSMaurice Kalinowski return rv; 28146938364bSMaurice Kalinowski 281534c72144SAxel Dörfler if (!createAndTruncate && _length) 281634c72144SAxel Dörfler *_length = reply.duration; 28176938364bSMaurice Kalinowski 28186938364bSMaurice Kalinowski return B_OK; 281952a38012Sejakowatz } 282052a38012Sejakowatz 282152a38012Sejakowatz 282252a38012Sejakowatz status_t 282334c72144SAxel Dörfler BMediaRoster::GetRefFor(const media_node& node, entry_ref* _file, 282434c72144SAxel Dörfler BMimeType* mimeType) 282552a38012Sejakowatz { 28266938364bSMaurice Kalinowski CALLED(); 28276938364bSMaurice Kalinowski 282834c72144SAxel Dörfler if (!_file) 28296938364bSMaurice Kalinowski return B_BAD_VALUE; 28306938364bSMaurice Kalinowski 28316938364bSMaurice Kalinowski fileinterface_get_ref_request request; 28326938364bSMaurice Kalinowski fileinterface_get_ref_reply reply; 28336938364bSMaurice Kalinowski status_t rv; 28346938364bSMaurice Kalinowski 283534c72144SAxel Dörfler rv = QueryPort(node.port, FILEINTERFACE_GET_REF, &request, sizeof(request), 283634c72144SAxel Dörfler &reply, sizeof(reply)); 28376938364bSMaurice Kalinowski if (rv != B_OK) 28386938364bSMaurice Kalinowski return rv; 28396938364bSMaurice Kalinowski 284034c72144SAxel Dörfler *_file = entry_ref(reply.device, reply.directory, reply.name); 28416938364bSMaurice Kalinowski 284234c72144SAxel Dörfler if (mimeType) 284334c72144SAxel Dörfler mimeType->SetTo(reply.mimetype); 28446938364bSMaurice Kalinowski 28456938364bSMaurice Kalinowski return B_OK; 284652a38012Sejakowatz } 284752a38012Sejakowatz 284852a38012Sejakowatz 284952a38012Sejakowatz status_t 285052a38012Sejakowatz BMediaRoster::SniffRefFor(const media_node& file_interface, 285134c72144SAxel Dörfler const entry_ref& file, BMimeType* mimeType, float* _capability) 285252a38012Sejakowatz { 28536938364bSMaurice Kalinowski CALLED(); 285434c72144SAxel Dörfler if (mimeType == NULL || _capability == NULL) 28556938364bSMaurice Kalinowski return B_BAD_VALUE; 28566938364bSMaurice Kalinowski 28576938364bSMaurice Kalinowski fileinterface_sniff_ref_request request; 28586938364bSMaurice Kalinowski fileinterface_sniff_ref_reply reply; 28596938364bSMaurice Kalinowski status_t rv; 28606938364bSMaurice Kalinowski 28616938364bSMaurice Kalinowski request.device = file.device; 28626938364bSMaurice Kalinowski request.directory = file.directory; 28636938364bSMaurice Kalinowski strcpy(request.name, file.name); 28646938364bSMaurice Kalinowski 286534c72144SAxel Dörfler rv = QueryPort(file_interface.port, FILEINTERFACE_SNIFF_REF, &request, 286634c72144SAxel Dörfler sizeof(request), &reply, sizeof(reply)); 28676938364bSMaurice Kalinowski if (rv != B_OK) 28686938364bSMaurice Kalinowski return rv; 28696938364bSMaurice Kalinowski 287034c72144SAxel Dörfler mimeType->SetTo(reply.mimetype); 287134c72144SAxel Dörfler *_capability = reply.capability; 28726938364bSMaurice Kalinowski 28736938364bSMaurice Kalinowski return B_OK; 287452a38012Sejakowatz } 287552a38012Sejakowatz 287652a38012Sejakowatz 287734c72144SAxel Dörfler /*! This is the generic "here's a file, now can someone please play it" 287834c72144SAxel Dörfler interface. 287934c72144SAxel Dörfler */ 288052a38012Sejakowatz status_t 288134c72144SAxel Dörfler BMediaRoster::SniffRef(const entry_ref& file, uint64 requireNodeKinds, 288234c72144SAxel Dörfler dormant_node_info* _node, BMimeType* mimeType) 288352a38012Sejakowatz { 288405f452c3SDavid McPaul CALLED(); 288505f452c3SDavid McPaul 2886332cc6bcSAxel Dörfler TRACE("BMediaRoster::SniffRef looking for a node to handle %s: 0x%" B_PRIx64 2887332cc6bcSAxel Dörfler "\n", file.name, requireNodeKinds); 288805f452c3SDavid McPaul 288905f452c3SDavid McPaul if (_node == NULL) 289005f452c3SDavid McPaul return B_BAD_VALUE; 289105f452c3SDavid McPaul 289205f452c3SDavid McPaul BMimeType aMimeType; 289305f452c3SDavid McPaul 289405f452c3SDavid McPaul dormant_node_info nodes[30]; 289505f452c3SDavid McPaul int32 count = 30; 289605f452c3SDavid McPaul int32 highestCapability = -1; 289705f452c3SDavid McPaul float capability; 289805f452c3SDavid McPaul 289905f452c3SDavid McPaul media_node node; 290005f452c3SDavid McPaul 290105f452c3SDavid McPaul // Get all dormant nodes using GetDormantNodes 29026f7f87a2SDavid McPaul if (GetDormantNodes(nodes, &count, NULL, NULL, NULL, requireNodeKinds | B_FILE_INTERFACE, 0) == B_OK) { 290305f452c3SDavid McPaul // Call SniffRefFor on each node that matches requireNodeKinds 290405f452c3SDavid McPaul for (int32 i=0;i<count;i++) { 29056f7f87a2SDavid McPaul if (InstantiateDormantNode(nodes[i], &node) == B_OK) { 290605f452c3SDavid McPaul 29076f7f87a2SDavid McPaul if (SniffRefFor(node, file, &aMimeType, &capability) == B_OK) { 290805f452c3SDavid McPaul // find the first node that has 100% capability 290905f452c3SDavid McPaul TRACE("%s has a %f%% chance of playing file\n",nodes[i].name, capability * 100.0); 291005f452c3SDavid McPaul if (capability == 1.0) { 291105f452c3SDavid McPaul highestCapability = i; 291205f452c3SDavid McPaul break; 291305f452c3SDavid McPaul } 291405f452c3SDavid McPaul } 291505f452c3SDavid McPaul ReleaseNode(node); 291605f452c3SDavid McPaul } 291705f452c3SDavid McPaul } 291805f452c3SDavid McPaul 291905f452c3SDavid McPaul if (highestCapability != -1) { 292005f452c3SDavid McPaul *_node = nodes[highestCapability]; 292105f452c3SDavid McPaul 2922332cc6bcSAxel Dörfler TRACE("BMediaRoster::SniffRef: found a node %s addon-id %" B_PRId32 2923332cc6bcSAxel Dörfler ", flavor_id %" B_PRId32 "\n", 2924332cc6bcSAxel Dörfler nodes[highestCapability].name, nodes[highestCapability].addon, 2925332cc6bcSAxel Dörfler nodes[highestCapability].flavor_id); 292605f452c3SDavid McPaul 292705f452c3SDavid McPaul if (mimeType != NULL) { 292805f452c3SDavid McPaul //*mimeType = aMimeType; -- need a copy constructor 292905f452c3SDavid McPaul } 293005f452c3SDavid McPaul 293105f452c3SDavid McPaul return B_OK; 293205f452c3SDavid McPaul } 293305f452c3SDavid McPaul 293405f452c3SDavid McPaul } 293505f452c3SDavid McPaul 293652a38012Sejakowatz return B_ERROR; 293752a38012Sejakowatz } 293852a38012Sejakowatz 293952a38012Sejakowatz 294052a38012Sejakowatz status_t 294152a38012Sejakowatz BMediaRoster::GetDormantNodeForType(const BMimeType& type, 294234c72144SAxel Dörfler uint64 requireNodeKinds, dormant_node_info* _node) 294352a38012Sejakowatz { 294452a38012Sejakowatz UNIMPLEMENTED(); 294552a38012Sejakowatz return B_ERROR; 294652a38012Sejakowatz } 294752a38012Sejakowatz 294852a38012Sejakowatz 294952a38012Sejakowatz status_t 295034c72144SAxel Dörfler BMediaRoster::GetReadFileFormatsFor(const dormant_node_info& node, 295134c72144SAxel Dörfler media_file_format* _readFormats, int32 readCount, int32* _readCount) 295252a38012Sejakowatz { 295352a38012Sejakowatz UNIMPLEMENTED(); 295452a38012Sejakowatz return B_ERROR; 295552a38012Sejakowatz } 295652a38012Sejakowatz 295752a38012Sejakowatz 295852a38012Sejakowatz status_t 295934c72144SAxel Dörfler BMediaRoster::GetWriteFileFormatsFor(const dormant_node_info& node, 296034c72144SAxel Dörfler media_file_format* _write_formats, int32 writeCount, int32* _writeCount) 296152a38012Sejakowatz { 296252a38012Sejakowatz UNIMPLEMENTED(); 296352a38012Sejakowatz return B_ERROR; 296452a38012Sejakowatz } 296552a38012Sejakowatz 296652a38012Sejakowatz 296752a38012Sejakowatz status_t 296834c72144SAxel Dörfler BMediaRoster::GetFormatFor(const media_output& output, media_format* _format, 296952a38012Sejakowatz uint32 flags) 297052a38012Sejakowatz { 29719bedd42cSbeveloper CALLED(); 297234c72144SAxel Dörfler if (_format == NULL) 29739bedd42cSbeveloper return B_BAD_VALUE; 29749bedd42cSbeveloper if ((output.node.kind & B_BUFFER_PRODUCER) == 0) 29759bedd42cSbeveloper return B_MEDIA_BAD_NODE; 29769bedd42cSbeveloper if (IS_INVALID_SOURCE(output.source)) 29779bedd42cSbeveloper return B_MEDIA_BAD_SOURCE; 29789bedd42cSbeveloper 29799bedd42cSbeveloper producer_format_suggestion_requested_request request; 29809bedd42cSbeveloper producer_format_suggestion_requested_reply reply; 29819bedd42cSbeveloper status_t rv; 29829bedd42cSbeveloper 29839bedd42cSbeveloper request.type = B_MEDIA_UNKNOWN_TYPE; 298434c72144SAxel Dörfler request.quality = 0; // TODO: what should this be? 29859bedd42cSbeveloper 298634c72144SAxel Dörfler rv = QueryPort(output.source.port, PRODUCER_FORMAT_SUGGESTION_REQUESTED, 298734c72144SAxel Dörfler &request, sizeof(request), &reply, sizeof(reply)); 29889bedd42cSbeveloper if (rv != B_OK) 29899bedd42cSbeveloper return rv; 29909bedd42cSbeveloper 299134c72144SAxel Dörfler *_format = reply.format; 29929bedd42cSbeveloper return B_OK; 299352a38012Sejakowatz } 299452a38012Sejakowatz 299552a38012Sejakowatz 299652a38012Sejakowatz status_t 299734c72144SAxel Dörfler BMediaRoster::GetFormatFor(const media_input& input, media_format* _format, 299852a38012Sejakowatz uint32 flags) 299952a38012Sejakowatz { 30009bedd42cSbeveloper CALLED(); 300134c72144SAxel Dörfler if (_format == NULL) 30029bedd42cSbeveloper return B_BAD_VALUE; 30039bedd42cSbeveloper if ((input.node.kind & B_BUFFER_CONSUMER) == 0) 30049bedd42cSbeveloper return B_MEDIA_BAD_NODE; 30059bedd42cSbeveloper if (IS_INVALID_DESTINATION(input.destination)) 30069bedd42cSbeveloper return B_MEDIA_BAD_DESTINATION; 30079bedd42cSbeveloper 30089bedd42cSbeveloper consumer_accept_format_request request; 30099bedd42cSbeveloper consumer_accept_format_reply reply; 30109bedd42cSbeveloper status_t rv; 30119bedd42cSbeveloper 30129bedd42cSbeveloper request.dest = input.destination; 30139bedd42cSbeveloper memset(&request.format, 0, sizeof(request.format)); // wildcard 30149bedd42cSbeveloper 301534c72144SAxel Dörfler rv = QueryPort(input.destination.port, CONSUMER_ACCEPT_FORMAT, &request, 301634c72144SAxel Dörfler sizeof(request), &reply, sizeof(reply)); 30179bedd42cSbeveloper if (rv != B_OK) 30189bedd42cSbeveloper return rv; 30199bedd42cSbeveloper 302034c72144SAxel Dörfler *_format = reply.format; 30219bedd42cSbeveloper return B_OK; 302252a38012Sejakowatz } 302352a38012Sejakowatz 302452a38012Sejakowatz 302552a38012Sejakowatz status_t 302634c72144SAxel Dörfler BMediaRoster::GetFormatFor(const media_node& node, media_format* _format, 302752a38012Sejakowatz float quality) 302852a38012Sejakowatz { 302952a38012Sejakowatz UNIMPLEMENTED(); 303034c72144SAxel Dörfler if (_format == NULL) 30319bedd42cSbeveloper return B_BAD_VALUE; 30329bedd42cSbeveloper if (IS_INVALID_NODE(node)) 30339bedd42cSbeveloper return B_MEDIA_BAD_NODE; 30349bedd42cSbeveloper if ((node.kind & (B_BUFFER_CONSUMER | B_BUFFER_PRODUCER)) == 0) 30359bedd42cSbeveloper return B_MEDIA_BAD_NODE; 30369bedd42cSbeveloper 303752a38012Sejakowatz return B_ERROR; 303852a38012Sejakowatz } 303952a38012Sejakowatz 304052a38012Sejakowatz 304152a38012Sejakowatz ssize_t 304252a38012Sejakowatz BMediaRoster::GetNodeAttributesFor(const media_node& node, 304334c72144SAxel Dörfler media_node_attribute* _array, size_t maxCount) 304452a38012Sejakowatz { 304552a38012Sejakowatz UNIMPLEMENTED(); 304652a38012Sejakowatz return B_ERROR; 304752a38012Sejakowatz } 304852a38012Sejakowatz 304952a38012Sejakowatz 305052a38012Sejakowatz media_node_id 305134c72144SAxel Dörfler BMediaRoster::NodeIDFor(port_id port) 305252a38012Sejakowatz { 30539e9417d2Sbeveloper CALLED(); 30549e9417d2Sbeveloper 30559e9417d2Sbeveloper server_node_id_for_request request; 30569e9417d2Sbeveloper server_node_id_for_reply reply; 30579e9417d2Sbeveloper status_t rv; 30589e9417d2Sbeveloper 305934c72144SAxel Dörfler request.port = port; 30609e9417d2Sbeveloper 306134c72144SAxel Dörfler rv = QueryServer(SERVER_NODE_ID_FOR, &request, sizeof(request), &reply, 306234c72144SAxel Dörfler sizeof(reply)); 30639e9417d2Sbeveloper if (rv != B_OK) { 3064332cc6bcSAxel Dörfler ERROR("BMediaRoster::NodeIDFor: failed (error %#" B_PRIx32 ")\n", rv); 30659e9417d2Sbeveloper return -1; 30669e9417d2Sbeveloper } 30679e9417d2Sbeveloper 30689dec2310SAxel Dörfler return reply.node_id; 306952a38012Sejakowatz } 307052a38012Sejakowatz 307152a38012Sejakowatz 307252a38012Sejakowatz status_t 307334c72144SAxel Dörfler BMediaRoster::GetInstancesFor(media_addon_id addon, int32 flavor, 307434c72144SAxel Dörfler media_node_id* _id, int32* _count) 307552a38012Sejakowatz { 307685dfab2bSbeveloper CALLED(); 307734c72144SAxel Dörfler if (_id == NULL) 307885dfab2bSbeveloper return B_BAD_VALUE; 307934c72144SAxel Dörfler if (_count && *_count <= 0) 308085dfab2bSbeveloper return B_BAD_VALUE; 308185dfab2bSbeveloper 308285dfab2bSbeveloper server_get_instances_for_request request; 308385dfab2bSbeveloper server_get_instances_for_reply reply; 308485dfab2bSbeveloper status_t rv; 308585dfab2bSbeveloper 30869c3b4706SAxel Dörfler request.max_count = (_count ? *_count : 1); 30879c3b4706SAxel Dörfler request.add_on_id = addon; 30889c3b4706SAxel Dörfler request.flavor_id = flavor; 308985dfab2bSbeveloper 309034c72144SAxel Dörfler rv = QueryServer(SERVER_GET_INSTANCES_FOR, &request, sizeof(request), 309134c72144SAxel Dörfler &reply, sizeof(reply)); 309285dfab2bSbeveloper if (rv != B_OK) { 30935ac4fbd7Sbeveloper ERROR("BMediaRoster::GetLiveNodes failed\n"); 309485dfab2bSbeveloper return rv; 309552a38012Sejakowatz } 309652a38012Sejakowatz 309734c72144SAxel Dörfler if (_count) 309834c72144SAxel Dörfler *_count = reply.count; 309985dfab2bSbeveloper if (reply.count > 0) 310034c72144SAxel Dörfler memcpy(_id, reply.node_id, sizeof(media_node_id) * reply.count); 310185dfab2bSbeveloper 310285dfab2bSbeveloper return B_OK; 310385dfab2bSbeveloper } 310452a38012Sejakowatz 310552a38012Sejakowatz 310652a38012Sejakowatz status_t 310734c72144SAxel Dörfler BMediaRoster::SetRealtimeFlags(uint32 enabled) 310852a38012Sejakowatz { 310952a38012Sejakowatz UNIMPLEMENTED(); 311052a38012Sejakowatz return B_ERROR; 311152a38012Sejakowatz } 311252a38012Sejakowatz 311352a38012Sejakowatz 311452a38012Sejakowatz status_t 311534c72144SAxel Dörfler BMediaRoster::GetRealtimeFlags(uint32* _enabled) 311652a38012Sejakowatz { 311752a38012Sejakowatz UNIMPLEMENTED(); 311852a38012Sejakowatz return B_ERROR; 311952a38012Sejakowatz } 312052a38012Sejakowatz 312152a38012Sejakowatz 312252a38012Sejakowatz ssize_t 312334c72144SAxel Dörfler BMediaRoster::AudioBufferSizeFor(int32 channelCount, uint32 sampleFormat, 312434c72144SAxel Dörfler float frameRate, bus_type busKind) 312552a38012Sejakowatz { 312634c72144SAxel Dörfler bigtime_t bufferDuration; 312734c72144SAxel Dörfler ssize_t bufferSize; 3128df6c2e83Sbeveloper 3129df6c2e83Sbeveloper system_info info; 3130df6c2e83Sbeveloper get_system_info(&info); 3131df6c2e83Sbeveloper 313234c72144SAxel Dörfler if (info.cpu_clock_speed > 2000000000) // 2 GHz 313334c72144SAxel Dörfler bufferDuration = 2500; 3134df6c2e83Sbeveloper else if (info.cpu_clock_speed > 1000000000) 313534c72144SAxel Dörfler bufferDuration = 5000; 3136df6c2e83Sbeveloper else if (info.cpu_clock_speed > 600000000) 313734c72144SAxel Dörfler bufferDuration = 10000; 3138df6c2e83Sbeveloper else if (info.cpu_clock_speed > 200000000) 313934c72144SAxel Dörfler bufferDuration = 20000; 3140df6c2e83Sbeveloper else if (info.cpu_clock_speed > 100000000) 314134c72144SAxel Dörfler bufferDuration = 30000; 3142df6c2e83Sbeveloper else 314334c72144SAxel Dörfler bufferDuration = 50000; 3144df6c2e83Sbeveloper 314534c72144SAxel Dörfler if ((busKind == B_ISA_BUS || busKind == B_PCMCIA_BUS) 314634c72144SAxel Dörfler && bufferDuration < 25000) 314734c72144SAxel Dörfler bufferDuration = 25000; 3148df6c2e83Sbeveloper 314934c72144SAxel Dörfler bufferSize = (sampleFormat & 0xf) * channelCount 315034c72144SAxel Dörfler * (ssize_t)((frameRate * bufferDuration) / 1000000.0); 3151df6c2e83Sbeveloper 3152332cc6bcSAxel Dörfler printf("Suggested buffer duration %" B_PRId64 ", size %" B_PRIdSSIZE "\n", 3153332cc6bcSAxel Dörfler bufferDuration, bufferSize); 3154df6c2e83Sbeveloper 315534c72144SAxel Dörfler return bufferSize; 315652a38012Sejakowatz } 315752a38012Sejakowatz 315852a38012Sejakowatz 315934c72144SAxel Dörfler /*! Use MediaFlags to inquire about specific features of the Media Kit. 316034c72144SAxel Dörfler Returns < 0 for "not present", positive size for output data size. 316134c72144SAxel Dörfler 0 means that the capability is present, but no data about it. 316234c72144SAxel Dörfler */ 316352a38012Sejakowatz /*static*/ ssize_t 316434c72144SAxel Dörfler BMediaRoster::MediaFlags(media_flags cap, void* buffer, size_t maxSize) 316552a38012Sejakowatz { 316652a38012Sejakowatz UNIMPLEMENTED(); 316752a38012Sejakowatz return 0; 316852a38012Sejakowatz } 316952a38012Sejakowatz 317052a38012Sejakowatz 317134c72144SAxel Dörfler // #pragma mark - BLooper overrides 317234c72144SAxel Dörfler 317334c72144SAxel Dörfler 317434c72144SAxel Dörfler void 317552a38012Sejakowatz BMediaRoster::MessageReceived(BMessage* message) 317652a38012Sejakowatz { 3177cf4e2277Sbeveloper switch (message->what) { 3178cf4e2277Sbeveloper case 'PING': 3179cf4e2277Sbeveloper { 31806396865dSbeveloper // media_server plays ping-pong with the BMediaRosters 31816396865dSbeveloper // to detect dead teams. Normal communication uses ports. 31826396865dSbeveloper static BMessage pong('PONG'); 31836396865dSbeveloper message->SendReply(&pong, static_cast<BHandler *>(NULL), 2000000); 31846396865dSbeveloper return; 31856396865dSbeveloper } 31866396865dSbeveloper 3187cf4e2277Sbeveloper case NODE_FINAL_RELEASE: 3188cf4e2277Sbeveloper { 3189cf4e2277Sbeveloper // this function is called by a BMediaNode to delete 3190cf4e2277Sbeveloper // itself, as this needs to be done from another thread 3191cf4e2277Sbeveloper // context, it is done here. 319234c72144SAxel Dörfler // TODO: If a node is released using BMediaRoster::ReleaseNode() 319334c72144SAxel Dörfler // TODO: instead of using BMediaNode::Release() / BMediaNode::Acquire() 319434c72144SAxel Dörfler // TODO: fRefCount of the BMediaNode will not be correct. 3195cf4e2277Sbeveloper 3196cf4e2277Sbeveloper BMediaNode *node; 3197cf4e2277Sbeveloper message->FindPointer("node", reinterpret_cast<void **>(&node)); 3198cf4e2277Sbeveloper 3199332cc6bcSAxel Dörfler TRACE("BMediaRoster::MessageReceived NODE_FINAL_RELEASE saving " 3200332cc6bcSAxel Dörfler "node %" B_PRId32 " configuration\n", node->ID()); 320154187cc6Sbeveloper MediaRosterEx(BMediaRoster::Roster())->SaveNodeConfiguration(node); 3202cf4e2277Sbeveloper 3203332cc6bcSAxel Dörfler TRACE("BMediaRoster::MessageReceived NODE_FINAL_RELEASE releasing " 3204332cc6bcSAxel Dörfler "node %" B_PRId32 "\n", node->ID()); 3205cf4e2277Sbeveloper node->DeleteHook(node); // we don't call Release(), see above! 3206cf4e2277Sbeveloper return; 3207cf4e2277Sbeveloper } 3208cf4e2277Sbeveloper } 32096396865dSbeveloper printf("BMediaRoster::MessageReceived: unknown message!\n"); 32106396865dSbeveloper message->PrintToStream(); 321152a38012Sejakowatz } 321252a38012Sejakowatz 321334c72144SAxel Dörfler 321434c72144SAxel Dörfler bool 321552a38012Sejakowatz BMediaRoster::QuitRequested() 321652a38012Sejakowatz { 321752a38012Sejakowatz UNIMPLEMENTED(); 321852a38012Sejakowatz return true; 321952a38012Sejakowatz } 322052a38012Sejakowatz 322134c72144SAxel Dörfler 322234c72144SAxel Dörfler BHandler* 322334c72144SAxel Dörfler BMediaRoster::ResolveSpecifier(BMessage* msg, int32 index, BMessage* specifier, 322434c72144SAxel Dörfler int32 form, const char* property) 322552a38012Sejakowatz { 3226286a3c91SJérôme Duval return BLooper::ResolveSpecifier(msg, index, specifier, form, property); 322752a38012Sejakowatz } 322852a38012Sejakowatz 322952a38012Sejakowatz 323034c72144SAxel Dörfler status_t 323152a38012Sejakowatz BMediaRoster::GetSupportedSuites(BMessage* data) 323252a38012Sejakowatz { 3233286a3c91SJérôme Duval return BLooper::GetSupportedSuites(data); 323452a38012Sejakowatz } 323552a38012Sejakowatz 323652a38012Sejakowatz 323752a38012Sejakowatz BMediaRoster::~BMediaRoster() 323852a38012Sejakowatz { 323952a38012Sejakowatz CALLED(); 32406396865dSbeveloper 3241f0a1eb2dSAxel Dörfler delete gTimeSourceObjectManager; 3242f0a1eb2dSAxel Dörfler delete gDormantNodeManager; 3243f0a1eb2dSAxel Dörfler 32446396865dSbeveloper // unregister this application with the media server 32456396865dSbeveloper server_unregister_app_request request; 32466396865dSbeveloper server_unregister_app_reply reply; 32479dec2310SAxel Dörfler request.team = BPrivate::current_team(); 324834c72144SAxel Dörfler QueryServer(SERVER_UNREGISTER_APP, &request, sizeof(request), &reply, 324934c72144SAxel Dörfler sizeof(reply)); 32508b940bb4SStephan Aßmus 32512f9ed888SAxel Dörfler BPrivate::SharedBufferList::Invalidate(); 32522f9ed888SAxel Dörfler 32538b940bb4SStephan Aßmus // Unset the global instance pointer, the destructor is also called 32548b940bb4SStephan Aßmus // if a client app calls Lock(); and Quit(); directly. 32559def3bf7SStephan Aßmus sDefaultInstance = NULL; 325652a38012Sejakowatz } 325752a38012Sejakowatz 325852a38012Sejakowatz 325934c72144SAxel Dörfler // #pragma mark - private BMediaRoster 326034c72144SAxel Dörfler 326152a38012Sejakowatz 3262f0a1eb2dSAxel Dörfler //! Deprecated call. 326352a38012Sejakowatz status_t 326452a38012Sejakowatz BMediaRoster::SetOutputBuffersFor(const media_source& output, 326534c72144SAxel Dörfler BBufferGroup* group, bool willReclaim) 326652a38012Sejakowatz { 326752a38012Sejakowatz UNIMPLEMENTED(); 32689e9417d2Sbeveloper debugger("BMediaRoster::SetOutputBuffersFor missing\n"); 326952a38012Sejakowatz return B_ERROR; 327052a38012Sejakowatz } 327152a38012Sejakowatz 327252a38012Sejakowatz 3273f0a1eb2dSAxel Dörfler // FBC reserved virtuals 327452a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_0(void*) { return B_ERROR; } 327552a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_1(void*) { return B_ERROR; } 327652a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_2(void*) { return B_ERROR; } 327752a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_3(void*) { return B_ERROR; } 327852a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_4(void*) { return B_ERROR; } 327952a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_5(void*) { return B_ERROR; } 328052a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_6(void*) { return B_ERROR; } 328152a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_7(void*) { return B_ERROR; } 328252a38012Sejakowatz 328352a38012Sejakowatz 328434c72144SAxel Dörfler BMediaRoster::BMediaRoster() 32852f9ed888SAxel Dörfler : 32862f9ed888SAxel Dörfler BLooper("_BMediaRoster_", B_URGENT_DISPLAY_PRIORITY, 328734c72144SAxel Dörfler B_LOOPER_PORT_DEFAULT_CAPACITY) 328852a38012Sejakowatz { 328952a38012Sejakowatz CALLED(); 32906396865dSbeveloper 32916396865dSbeveloper // start the looper 32926396865dSbeveloper Run(); 329352a38012Sejakowatz } 329452a38012Sejakowatz 32956396865dSbeveloper 32969def3bf7SStephan Aßmus // TODO: Looks like these can be safely removed: 329752a38012Sejakowatz /*static*/ status_t 329852a38012Sejakowatz BMediaRoster::ParseCommand(BMessage& reply) 329952a38012Sejakowatz { 330052a38012Sejakowatz UNIMPLEMENTED(); 330152a38012Sejakowatz return B_ERROR; 330252a38012Sejakowatz } 330352a38012Sejakowatz 330452a38012Sejakowatz 330552a38012Sejakowatz status_t 330634c72144SAxel Dörfler BMediaRoster::GetDefaultInfo(media_node_id forDefault, BMessage& config) 330752a38012Sejakowatz { 330852a38012Sejakowatz UNIMPLEMENTED(); 330952a38012Sejakowatz return B_ERROR; 331052a38012Sejakowatz } 331152a38012Sejakowatz 331252a38012Sejakowatz 331352a38012Sejakowatz status_t 331434c72144SAxel Dörfler BMediaRoster::SetRunningDefault(media_node_id forDefault, 331552a38012Sejakowatz const media_node& node) 331652a38012Sejakowatz { 331752a38012Sejakowatz UNIMPLEMENTED(); 331852a38012Sejakowatz return B_ERROR; 331952a38012Sejakowatz } 332052a38012Sejakowatz 332152a38012Sejakowatz 33229def3bf7SStephan Aßmus // #pragma mark - static variables 332352a38012Sejakowatz 33249def3bf7SStephan Aßmus 33259def3bf7SStephan Aßmus BMediaRoster* BMediaRoster::sDefaultInstance = NULL; 3326