1255a01c7Sbeveloper /* 234c72144SAxel Dörfler * Copyright 2008 Maurice Kalinowski, haiku@kaldience.com 334c72144SAxel Dörfler * Copyright 2009, 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 <PortPool.h> 672f9ed888SAxel Dörfler #include <ServerInterface.h> 682f9ed888SAxel Dörfler #include <SharedBufferList.h> 692f9ed888SAxel Dörfler 70835140c8Sbeveloper #include "TimeSourceObjectManager.h" 7152a38012Sejakowatz 722f9ed888SAxel Dörfler 73f4925104Sbeveloper namespace BPrivate { namespace media { 7452a38012Sejakowatz 7552a38012Sejakowatz // the BMediaRoster destructor is private, 7652a38012Sejakowatz // but _DefaultDeleter is a friend class of 7752a38012Sejakowatz // the BMediaRoster an thus can delete it 789dec2310SAxel Dörfler class DefaultDeleter { 7952a38012Sejakowatz public: 808b04ffc1Sbeveloper ~DefaultDeleter() 816396865dSbeveloper { 829dec2310SAxel Dörfler if (BMediaRoster::sDefaultInstance != NULL) { 839def3bf7SStephan Aßmus BMediaRoster::sDefaultInstance->Lock(); 849def3bf7SStephan Aßmus BMediaRoster::sDefaultInstance->Quit(); 856396865dSbeveloper } 866396865dSbeveloper } 878b04ffc1Sbeveloper }; 8852a38012Sejakowatz 899dec2310SAxel Dörfler } // namespace media 909dec2310SAxel Dörfler } // namespace BPrivate 919dec2310SAxel Dörfler 928b04ffc1Sbeveloper using namespace BPrivate::media; 9352a38012Sejakowatz 949dec2310SAxel Dörfler 958b04ffc1Sbeveloper // DefaultDeleter will delete the BMediaRoster object in it's destructor. 968b04ffc1Sbeveloper DefaultDeleter _deleter; 9752a38012Sejakowatz 989dec2310SAxel Dörfler 9934c72144SAxel Dörfler BMediaRosterEx::BMediaRosterEx(status_t* _error) 1009dec2310SAxel Dörfler : 1019dec2310SAxel Dörfler BMediaRoster() 102dcfb6bfcSJérôme Duval { 103dcfb6bfcSJérôme Duval // register this application with the media server 104dcfb6bfcSJérôme Duval server_register_app_request request; 105dcfb6bfcSJérôme Duval server_register_app_reply reply; 1069dec2310SAxel Dörfler request.team = BPrivate::current_team(); 107dcfb6bfcSJérôme Duval request.messenger = BMessenger(NULL, this); 1089dec2310SAxel Dörfler 1099dec2310SAxel Dörfler status_t status = QueryServer(SERVER_REGISTER_APP, &request, 1109dec2310SAxel Dörfler sizeof(request), &reply, sizeof(reply)); 1119dec2310SAxel Dörfler if (status != B_OK) 11234c72144SAxel Dörfler *_error = B_MEDIA_SYSTEM_FAILURE; 113a7fb4c16SMaurice Kalinowski else 11434c72144SAxel Dörfler *_error = B_OK; 115dcfb6bfcSJérôme Duval } 116dcfb6bfcSJérôme Duval 11734c72144SAxel Dörfler 1183620737cSbeveloper status_t 11954187cc6Sbeveloper BMediaRosterEx::SaveNodeConfiguration(BMediaNode* node) 12054187cc6Sbeveloper { 1219dec2310SAxel Dörfler int32 flavorID; 1229dec2310SAxel Dörfler BMediaAddOn* addon = node->AddOn(&flavorID); 1239dec2310SAxel Dörfler if (addon == NULL) { 1248056f0dbSStephan Aßmus // NOTE: This node could have been created by an application, 1258056f0dbSStephan Aßmus // it does not mean there is an error. 12634c72144SAxel Dörfler // TODO: this check incorrectly triggers on BeOS R5 BT848 node 1278056f0dbSStephan Aßmus TRACE("BMediaRosterEx::SaveNodeConfiguration node %ld not instantiated " 1288056f0dbSStephan Aßmus "from BMediaAddOn!\n", node->ID()); 12954187cc6Sbeveloper return B_ERROR; 13054187cc6Sbeveloper } 1319dec2310SAxel Dörfler 1329dec2310SAxel Dörfler media_addon_id addonID = addon->AddonID(); 13354187cc6Sbeveloper 13434c72144SAxel Dörfler // TODO: fix this 1358056f0dbSStephan Aßmus printf("### BMediaRosterEx::SaveNodeConfiguration should save addon-id " 1369dec2310SAxel Dörfler "%ld, flavor-id %ld config NOW!\n", addonID, flavorID); 13754187cc6Sbeveloper return B_OK; 13854187cc6Sbeveloper } 13954187cc6Sbeveloper 14034c72144SAxel Dörfler 14154187cc6Sbeveloper status_t 1429dec2310SAxel Dörfler BMediaRosterEx::LoadNodeConfiguration(media_addon_id addonID, int32 flavorID, 1439dec2310SAxel Dörfler BMessage *_msg) 14454187cc6Sbeveloper { 14534c72144SAxel Dörfler // TODO: fix this 1469dec2310SAxel Dörfler _msg->MakeEmpty(); // to be fully R5 compliant 1478b940bb4SStephan Aßmus printf("### BMediaRosterEx::LoadNodeConfiguration should load addon-id " 1489dec2310SAxel Dörfler "%ld, flavor-id %ld config NOW!\n", addonID, flavorID); 14954187cc6Sbeveloper return B_OK; 15054187cc6Sbeveloper } 15154187cc6Sbeveloper 15234c72144SAxel Dörfler 15354187cc6Sbeveloper status_t 1549dec2310SAxel Dörfler BMediaRosterEx::IncrementAddonFlavorInstancesCount(media_addon_id addonID, 1559dec2310SAxel Dörfler int32 flavorID) 15654187cc6Sbeveloper { 1579c3b4706SAxel Dörfler server_change_flavor_instances_count_request request; 1589c3b4706SAxel Dörfler server_change_flavor_instances_count_reply reply; 15973794717Sbeveloper 1609c3b4706SAxel Dörfler request.add_on_id = addonID; 1619dec2310SAxel Dörfler request.flavor_id = flavorID; 16273794717Sbeveloper request.delta = 1; 1639dec2310SAxel Dörfler request.team = BPrivate::current_team(); 1649c3b4706SAxel Dörfler return QueryServer(SERVER_CHANGE_FLAVOR_INSTANCES_COUNT, &request, 16534c72144SAxel Dörfler sizeof(request), &reply, sizeof(reply)); 16654187cc6Sbeveloper } 16754187cc6Sbeveloper 16834c72144SAxel Dörfler 16954187cc6Sbeveloper status_t 1709dec2310SAxel Dörfler BMediaRosterEx::DecrementAddonFlavorInstancesCount(media_addon_id addonID, 1719dec2310SAxel Dörfler int32 flavorID) 17254187cc6Sbeveloper { 1739c3b4706SAxel Dörfler server_change_flavor_instances_count_request request; 1749c3b4706SAxel Dörfler server_change_flavor_instances_count_reply reply; 17573794717Sbeveloper 1769c3b4706SAxel Dörfler request.add_on_id = addonID; 1779dec2310SAxel Dörfler request.flavor_id = flavorID; 17873794717Sbeveloper request.delta = -1; 1799dec2310SAxel Dörfler request.team = BPrivate::current_team(); 1809c3b4706SAxel Dörfler return QueryServer(SERVER_CHANGE_FLAVOR_INSTANCES_COUNT, &request, 18134c72144SAxel Dörfler sizeof(request), &reply, sizeof(reply)); 18254187cc6Sbeveloper } 18354187cc6Sbeveloper 18434c72144SAxel Dörfler 18554187cc6Sbeveloper status_t 18654187cc6Sbeveloper BMediaRosterEx::SetNodeCreator(media_node_id node, team_id creator) 18754187cc6Sbeveloper { 18854187cc6Sbeveloper server_set_node_creator_request request; 18954187cc6Sbeveloper server_set_node_creator_reply reply; 19054187cc6Sbeveloper 19154187cc6Sbeveloper request.node = node; 19254187cc6Sbeveloper request.creator = creator; 19334c72144SAxel Dörfler return QueryServer(SERVER_SET_NODE_CREATOR, &request, sizeof(request), 19434c72144SAxel Dörfler &reply, sizeof(reply)); 19554187cc6Sbeveloper } 19654187cc6Sbeveloper 19734c72144SAxel Dörfler 19854187cc6Sbeveloper status_t 19934c72144SAxel Dörfler BMediaRosterEx::GetNode(node_type type, media_node* out_node, 20034c72144SAxel Dörfler int32* out_input_id, BString* out_input_name) 20152a38012Sejakowatz { 20252a38012Sejakowatz if (out_node == NULL) 20352a38012Sejakowatz return B_BAD_VALUE; 20452a38012Sejakowatz 2058c6a6096Sbeveloper server_get_node_request request; 2068c6a6096Sbeveloper server_get_node_reply reply; 20752a38012Sejakowatz status_t rv; 20852a38012Sejakowatz 2098c6a6096Sbeveloper request.type = type; 2109dec2310SAxel Dörfler request.team = BPrivate::current_team(); 21134c72144SAxel Dörfler rv = QueryServer(SERVER_GET_NODE, &request, sizeof(request), &reply, 21234c72144SAxel Dörfler sizeof(reply)); 2138c6a6096Sbeveloper if (rv != B_OK) 2148c6a6096Sbeveloper return rv; 21552a38012Sejakowatz 21652a38012Sejakowatz *out_node = reply.node; 21752a38012Sejakowatz if (out_input_id) 21852a38012Sejakowatz *out_input_id = reply.input_id; 21952a38012Sejakowatz if (out_input_name) 22052a38012Sejakowatz *out_input_name = reply.input_name; 2218c6a6096Sbeveloper return rv; 22252a38012Sejakowatz } 22352a38012Sejakowatz 22434c72144SAxel Dörfler 2253620737cSbeveloper status_t 22634c72144SAxel Dörfler BMediaRosterEx::SetNode(node_type type, const media_node* node, 22734c72144SAxel Dörfler const dormant_node_info* info, const media_input* input) 22852a38012Sejakowatz { 2298c6a6096Sbeveloper server_set_node_request request; 2308c6a6096Sbeveloper server_set_node_reply reply; 23152a38012Sejakowatz 2328c6a6096Sbeveloper request.type = type; 23334c72144SAxel Dörfler request.use_node = node != NULL; 23434c72144SAxel Dörfler if (node != NULL) 2358c6a6096Sbeveloper request.node = *node; 23634c72144SAxel Dörfler request.use_dni = info != NULL; 23734c72144SAxel Dörfler if (info != NULL) 2388c6a6096Sbeveloper request.dni = *info; 23934c72144SAxel Dörfler request.use_input = input != NULL; 24034c72144SAxel Dörfler if (input != NULL) 2418c6a6096Sbeveloper request.input = *input; 24252a38012Sejakowatz 24334c72144SAxel Dörfler return QueryServer(SERVER_SET_NODE, &request, sizeof(request), &reply, 24434c72144SAxel Dörfler sizeof(reply)); 24552a38012Sejakowatz } 24652a38012Sejakowatz 24734c72144SAxel Dörfler 2483620737cSbeveloper status_t 2498b04ffc1Sbeveloper BMediaRosterEx::GetAllOutputs(const media_node& node, List<media_output>* list) 2503620737cSbeveloper { 2513620737cSbeveloper int32 cookie; 2523620737cSbeveloper status_t rv; 2533620737cSbeveloper status_t result; 2543620737cSbeveloper 25534c72144SAxel Dörfler PRINT(4, "BMediaRosterEx::GetAllOutputs() node %ld, port %ld\n", node.node, 25634c72144SAxel Dörfler node.port); 2575ac4fbd7Sbeveloper 25865b73ae4SMarcus Overhagen if (!(node.kind & B_BUFFER_PRODUCER)) { 25934c72144SAxel Dörfler ERROR("BMediaRosterEx::GetAllOutputs: node %ld is not a " 26034c72144SAxel Dörfler "B_BUFFER_PRODUCER\n", node.node); 26165b73ae4SMarcus Overhagen return B_MEDIA_BAD_NODE; 26265b73ae4SMarcus Overhagen } 26365b73ae4SMarcus Overhagen 2643620737cSbeveloper result = B_OK; 2653620737cSbeveloper cookie = 0; 26676669a29Sbeveloper list->MakeEmpty(); 2673620737cSbeveloper for (;;) { 2683620737cSbeveloper producer_get_next_output_request request; 2693620737cSbeveloper producer_get_next_output_reply reply; 2703620737cSbeveloper request.cookie = cookie; 27134c72144SAxel Dörfler rv = QueryPort(node.port, PRODUCER_GET_NEXT_OUTPUT, &request, 27234c72144SAxel Dörfler sizeof(request), &reply, sizeof(reply)); 2733620737cSbeveloper if (rv != B_OK) 2743620737cSbeveloper break; 2753620737cSbeveloper cookie = reply.cookie; 27676669a29Sbeveloper if (!list->Insert(reply.output)) { 2775ac4fbd7Sbeveloper ERROR("GetAllOutputs: list->Insert failed\n"); 2783620737cSbeveloper result = B_ERROR; 2793620737cSbeveloper } 2805ac4fbd7Sbeveloper #if DEBUG >= 3 2815ac4fbd7Sbeveloper PRINT(3," next cookie %ld, ", cookie); 2825ac4fbd7Sbeveloper PRINT_OUTPUT("output ", reply.output); 2835ac4fbd7Sbeveloper #endif 2843620737cSbeveloper } 2853620737cSbeveloper 2863620737cSbeveloper producer_dispose_output_cookie_request request; 2873620737cSbeveloper producer_dispose_output_cookie_reply reply; 28834c72144SAxel Dörfler QueryPort(node.port, PRODUCER_DISPOSE_OUTPUT_COOKIE, &request, 28934c72144SAxel Dörfler sizeof(request), &reply, sizeof(reply)); 2903620737cSbeveloper 2913620737cSbeveloper return result; 2923620737cSbeveloper } 2933620737cSbeveloper 29434c72144SAxel Dörfler 2953620737cSbeveloper status_t 2964d2d96e0Sbeveloper BMediaRosterEx::GetAllOutputs(BBufferProducer* node, List<media_output>* list) 2974d2d96e0Sbeveloper { 2984d2d96e0Sbeveloper int32 cookie; 2994d2d96e0Sbeveloper status_t result; 3004d2d96e0Sbeveloper 3014d2d96e0Sbeveloper PRINT(4, "BMediaRosterEx::GetAllOutputs() (by pointer) node %ld, port %ld\n", node->ID(), node->ControlPort()); 3024d2d96e0Sbeveloper 3034d2d96e0Sbeveloper result = B_OK; 3044d2d96e0Sbeveloper cookie = 0; 3054d2d96e0Sbeveloper list->MakeEmpty(); 3064d2d96e0Sbeveloper for (;;) { 3074d2d96e0Sbeveloper media_output output; 3084d2d96e0Sbeveloper if (B_OK != node->GetNextOutput(&cookie, &output)) 3094d2d96e0Sbeveloper break; 3104d2d96e0Sbeveloper if (!list->Insert(output)) { 3114d2d96e0Sbeveloper ERROR("GetAllOutputs: list->Insert failed\n"); 3124d2d96e0Sbeveloper result = B_ERROR; 3134d2d96e0Sbeveloper } 3144d2d96e0Sbeveloper #if DEBUG >= 3 3154d2d96e0Sbeveloper PRINT(3," next cookie %ld, ", cookie); 3164d2d96e0Sbeveloper PRINT_OUTPUT("output ", output); 3174d2d96e0Sbeveloper #endif 3184d2d96e0Sbeveloper } 3194d2d96e0Sbeveloper node->DisposeOutputCookie(cookie); 3204d2d96e0Sbeveloper return result; 3214d2d96e0Sbeveloper } 3224d2d96e0Sbeveloper 32334c72144SAxel Dörfler 3244d2d96e0Sbeveloper status_t 3258b04ffc1Sbeveloper BMediaRosterEx::GetAllInputs(const media_node& node, List<media_input>* list) 3263620737cSbeveloper { 3273620737cSbeveloper int32 cookie; 3283620737cSbeveloper status_t rv; 3293620737cSbeveloper status_t result; 3303620737cSbeveloper 33134c72144SAxel Dörfler PRINT(4, "BMediaRosterEx::GetAllInputs() node %ld, port %ld\n", node.node, 33234c72144SAxel Dörfler node.port); 3335ac4fbd7Sbeveloper 33465b73ae4SMarcus Overhagen if (!(node.kind & B_BUFFER_CONSUMER)) { 33534c72144SAxel Dörfler ERROR("BMediaRosterEx::GetAllInputs: node %ld is not a " 33634c72144SAxel Dörfler "B_BUFFER_CONSUMER\n", node.node); 33765b73ae4SMarcus Overhagen return B_MEDIA_BAD_NODE; 33865b73ae4SMarcus Overhagen } 33965b73ae4SMarcus Overhagen 3403620737cSbeveloper result = B_OK; 3413620737cSbeveloper cookie = 0; 34276669a29Sbeveloper list->MakeEmpty(); 3433620737cSbeveloper for (;;) { 3443620737cSbeveloper consumer_get_next_input_request request; 3453620737cSbeveloper consumer_get_next_input_reply reply; 3463620737cSbeveloper request.cookie = cookie; 34734c72144SAxel Dörfler rv = QueryPort(node.port, CONSUMER_GET_NEXT_INPUT, &request, 34834c72144SAxel Dörfler sizeof(request), &reply, sizeof(reply)); 3493620737cSbeveloper if (rv != B_OK) 3503620737cSbeveloper break; 3513620737cSbeveloper cookie = reply.cookie; 35276669a29Sbeveloper if (!list->Insert(reply.input)) { 3535ac4fbd7Sbeveloper ERROR("GetAllInputs: list->Insert failed\n"); 3543620737cSbeveloper result = B_ERROR; 3553620737cSbeveloper } 3565ac4fbd7Sbeveloper #if DEBUG >= 3 3575ac4fbd7Sbeveloper PRINT(3," next cookie %ld, ", cookie); 3585ac4fbd7Sbeveloper PRINT_OUTPUT("input ", reply.input); 3595ac4fbd7Sbeveloper #endif 3603620737cSbeveloper } 3613620737cSbeveloper 3623620737cSbeveloper consumer_dispose_input_cookie_request request; 3633620737cSbeveloper consumer_dispose_input_cookie_reply reply; 36434c72144SAxel Dörfler QueryPort(node.port, CONSUMER_DISPOSE_INPUT_COOKIE, &request, 36534c72144SAxel Dörfler sizeof(request), &reply, sizeof(reply)); 3663620737cSbeveloper 3673620737cSbeveloper return result; 3683620737cSbeveloper } 3693620737cSbeveloper 37034c72144SAxel Dörfler 3713620737cSbeveloper status_t 3724d2d96e0Sbeveloper BMediaRosterEx::GetAllInputs(BBufferConsumer* node, List<media_input>* list) 3734d2d96e0Sbeveloper { 3744d2d96e0Sbeveloper int32 cookie; 3754d2d96e0Sbeveloper status_t result; 3764d2d96e0Sbeveloper 3774d2d96e0Sbeveloper PRINT(4, "BMediaRosterEx::GetAllInputs() (by pointer) node %ld, port %ld\n", node->ID(), node->ControlPort()); 3784d2d96e0Sbeveloper 3794d2d96e0Sbeveloper result = B_OK; 3804d2d96e0Sbeveloper cookie = 0; 3814d2d96e0Sbeveloper list->MakeEmpty(); 3824d2d96e0Sbeveloper for (;;) { 3834d2d96e0Sbeveloper media_input input; 3844d2d96e0Sbeveloper if (B_OK != node->GetNextInput(&cookie, &input)) 3854d2d96e0Sbeveloper break; 3864d2d96e0Sbeveloper if (!list->Insert(input)) { 3874d2d96e0Sbeveloper ERROR("GetAllInputs: list->Insert failed\n"); 3884d2d96e0Sbeveloper result = B_ERROR; 3894d2d96e0Sbeveloper } 3904d2d96e0Sbeveloper #if DEBUG >= 3 3914d2d96e0Sbeveloper PRINT(3," next cookie %ld, ", cookie); 3924d2d96e0Sbeveloper PRINT_INPUT("input ", input); 3934d2d96e0Sbeveloper #endif 3944d2d96e0Sbeveloper } 3954d2d96e0Sbeveloper node->DisposeInputCookie(cookie); 3964d2d96e0Sbeveloper return result; 3974d2d96e0Sbeveloper } 3984d2d96e0Sbeveloper 39934c72144SAxel Dörfler 4004d2d96e0Sbeveloper status_t 4018b04ffc1Sbeveloper BMediaRosterEx::PublishOutputs(const media_node& node, List<media_output>* list) 4023620737cSbeveloper { 4033620737cSbeveloper server_publish_outputs_request request; 4043620737cSbeveloper server_publish_outputs_reply reply; 4053620737cSbeveloper media_output* output; 4063620737cSbeveloper media_output* outputs; 4073620737cSbeveloper int32 count; 408a7b41a96Sbeveloper status_t rv; 4093620737cSbeveloper 41076669a29Sbeveloper count = list->CountItems(); 4113620737cSbeveloper TRACE("PublishOutputs: publishing %ld\n", count); 4123620737cSbeveloper 4133620737cSbeveloper request.node = node; 4143620737cSbeveloper request.count = count; 4153620737cSbeveloper if (count > MAX_OUTPUTS) { 4163620737cSbeveloper void *start_addr; 4173620737cSbeveloper size_t size; 41840f36b03Sbeveloper size = ROUND_UP_TO_PAGE(count * sizeof(media_output)); 41934c72144SAxel Dörfler request.area = create_area("publish outputs", &start_addr, 42034c72144SAxel Dörfler B_ANY_ADDRESS, size, B_NO_LOCK, B_READ_AREA | B_WRITE_AREA); 4213620737cSbeveloper if (request.area < B_OK) { 42234c72144SAxel Dörfler ERROR("PublishOutputs: failed to create area, %#lx\n", 42334c72144SAxel Dörfler request.area); 4243620737cSbeveloper return (status_t)request.area; 4253620737cSbeveloper } 4263620737cSbeveloper outputs = static_cast<media_output *>(start_addr); 4273620737cSbeveloper } else { 4283620737cSbeveloper request.area = -1; 4293620737cSbeveloper outputs = request.outputs; 4303620737cSbeveloper } 43176669a29Sbeveloper TRACE("PublishOutputs: area %ld\n", request.area); 4323620737cSbeveloper 43376669a29Sbeveloper int i; 43476669a29Sbeveloper for (i = 0, list->Rewind(); list->GetNext(&output); i++) { 43576669a29Sbeveloper ASSERT(i < count); 4363620737cSbeveloper outputs[i] = *output; 4373620737cSbeveloper } 4383620737cSbeveloper 43934c72144SAxel Dörfler rv = QueryServer(SERVER_PUBLISH_OUTPUTS, &request, sizeof(request), 44034c72144SAxel Dörfler &reply, sizeof(reply)); 441a7b41a96Sbeveloper 442a7b41a96Sbeveloper if (request.area != -1) 443a7b41a96Sbeveloper delete_area(request.area); 444a7b41a96Sbeveloper 445a7b41a96Sbeveloper return rv; 4463620737cSbeveloper } 4473620737cSbeveloper 44834c72144SAxel Dörfler 4493620737cSbeveloper status_t 4508b04ffc1Sbeveloper BMediaRosterEx::PublishInputs(const media_node& node, List<media_input>* list) 4513620737cSbeveloper { 4523620737cSbeveloper server_publish_inputs_request request; 4533620737cSbeveloper server_publish_inputs_reply reply; 4543620737cSbeveloper media_input* input; 4553620737cSbeveloper media_input* inputs; 4563620737cSbeveloper int32 count; 457a7b41a96Sbeveloper status_t rv; 4583620737cSbeveloper 45976669a29Sbeveloper count = list->CountItems(); 4603620737cSbeveloper TRACE("PublishInputs: publishing %ld\n", count); 4613620737cSbeveloper 4623620737cSbeveloper request.node = node; 4633620737cSbeveloper request.count = count; 4643620737cSbeveloper if (count > MAX_INPUTS) { 4653620737cSbeveloper void* start_addr; 4663620737cSbeveloper size_t size; 46740f36b03Sbeveloper size = ROUND_UP_TO_PAGE(count * sizeof(media_input)); 46834c72144SAxel Dörfler request.area = create_area("publish inputs", &start_addr, 46934c72144SAxel Dörfler B_ANY_ADDRESS, size, B_NO_LOCK, B_READ_AREA | B_WRITE_AREA); 4703620737cSbeveloper if (request.area < B_OK) { 4715ac4fbd7Sbeveloper ERROR("PublishInputs: failed to create area, %#lx\n", request.area); 4723620737cSbeveloper return (status_t)request.area; 4733620737cSbeveloper } 4743620737cSbeveloper inputs = static_cast<media_input *>(start_addr); 4753620737cSbeveloper } else { 4763620737cSbeveloper request.area = -1; 4773620737cSbeveloper inputs = request.inputs; 4783620737cSbeveloper } 47976669a29Sbeveloper TRACE("PublishInputs: area %ld\n", request.area); 4803620737cSbeveloper 48176669a29Sbeveloper int i; 48276669a29Sbeveloper for (i = 0, list->Rewind(); list->GetNext(&input); i++) { 48376669a29Sbeveloper ASSERT(i < count); 4843620737cSbeveloper inputs[i] = *input; 4853620737cSbeveloper } 4863620737cSbeveloper 48734c72144SAxel Dörfler rv = QueryServer(SERVER_PUBLISH_INPUTS, &request, sizeof(request), 48834c72144SAxel Dörfler &reply, sizeof(reply)); 489a7b41a96Sbeveloper 490a7b41a96Sbeveloper if (request.area != -1) 491a7b41a96Sbeveloper delete_area(request.area); 492a7b41a96Sbeveloper 493a7b41a96Sbeveloper return rv; 4943620737cSbeveloper } 4953620737cSbeveloper 49634c72144SAxel Dörfler 49734c72144SAxel Dörfler BTimeSource* 498f4ec236cSAxel Dörfler BMediaRosterEx::MakeTimeSourceObject(media_node_id timeSourceID) 49934c72144SAxel Dörfler { 50034c72144SAxel Dörfler media_node clone; 501f4ec236cSAxel Dörfler status_t status = GetNodeFor(timeSourceID, &clone); 502f4ec236cSAxel Dörfler if (status != B_OK) { 503f4ec236cSAxel Dörfler ERROR("BMediaRosterEx::MakeTimeSourceObject: GetNodeFor failed: %s\n", 504f4ec236cSAxel Dörfler strerror(status)); 50534c72144SAxel Dörfler return NULL; 50634c72144SAxel Dörfler } 50734c72144SAxel Dörfler 508f4ec236cSAxel Dörfler BTimeSource* source = gTimeSourceObjectManager->GetTimeSource(clone); 50934c72144SAxel Dörfler if (source == NULL) { 51034c72144SAxel Dörfler ERROR("BMediaRosterEx::MakeTimeSourceObject: GetTimeSource failed\n"); 51134c72144SAxel Dörfler return NULL; 51234c72144SAxel Dörfler } 51334c72144SAxel Dörfler 51434c72144SAxel Dörfler // TODO: release? 51534c72144SAxel Dörfler ReleaseNode(clone); 51634c72144SAxel Dörfler 51734c72144SAxel Dörfler return source; 51834c72144SAxel Dörfler } 51934c72144SAxel Dörfler 52034c72144SAxel Dörfler 52134c72144SAxel Dörfler // #pragma mark - public BMediaRoster 52234c72144SAxel Dörfler 52352a38012Sejakowatz 52452a38012Sejakowatz status_t 52534c72144SAxel Dörfler BMediaRoster::GetVideoInput(media_node* _node) 52652a38012Sejakowatz { 52752a38012Sejakowatz CALLED(); 52834c72144SAxel Dörfler return MediaRosterEx(this)->GetNode(VIDEO_INPUT, _node); 52952a38012Sejakowatz } 53052a38012Sejakowatz 53152a38012Sejakowatz 53252a38012Sejakowatz status_t 53334c72144SAxel Dörfler BMediaRoster::GetAudioInput(media_node* _node) 53452a38012Sejakowatz { 53552a38012Sejakowatz CALLED(); 53634c72144SAxel Dörfler return MediaRosterEx(this)->GetNode(AUDIO_INPUT, _node); 53752a38012Sejakowatz } 53852a38012Sejakowatz 53952a38012Sejakowatz 54052a38012Sejakowatz status_t 54134c72144SAxel Dörfler BMediaRoster::GetVideoOutput(media_node* _node) 54252a38012Sejakowatz { 54352a38012Sejakowatz CALLED(); 54434c72144SAxel Dörfler return MediaRosterEx(this)->GetNode(VIDEO_OUTPUT, _node); 54552a38012Sejakowatz } 54652a38012Sejakowatz 54752a38012Sejakowatz 54852a38012Sejakowatz status_t 54934c72144SAxel Dörfler BMediaRoster::GetAudioMixer(media_node* _node) 55052a38012Sejakowatz { 55152a38012Sejakowatz CALLED(); 55234c72144SAxel Dörfler return MediaRosterEx(this)->GetNode(AUDIO_MIXER, _node); 55352a38012Sejakowatz } 55452a38012Sejakowatz 55552a38012Sejakowatz 55652a38012Sejakowatz status_t 55734c72144SAxel Dörfler BMediaRoster::GetAudioOutput(media_node* _node) 55852a38012Sejakowatz { 55952a38012Sejakowatz CALLED(); 56034c72144SAxel Dörfler return MediaRosterEx(this)->GetNode(AUDIO_OUTPUT, _node); 56152a38012Sejakowatz } 56252a38012Sejakowatz 56352a38012Sejakowatz 56452a38012Sejakowatz status_t 56534c72144SAxel Dörfler BMediaRoster::GetAudioOutput(media_node* _node, int32* _inputID, 56634c72144SAxel Dörfler BString* _inputName) 56752a38012Sejakowatz { 56852a38012Sejakowatz CALLED(); 56934c72144SAxel Dörfler return MediaRosterEx(this)->GetNode(AUDIO_OUTPUT_EX, _node, _inputID, 57034c72144SAxel Dörfler _inputName); 57152a38012Sejakowatz } 57252a38012Sejakowatz 57352a38012Sejakowatz 57452a38012Sejakowatz status_t 57534c72144SAxel Dörfler BMediaRoster::GetTimeSource(media_node* _node) 57652a38012Sejakowatz { 57752a38012Sejakowatz CALLED(); 57886bce45bSbeveloper status_t rv; 57986bce45bSbeveloper 58034c72144SAxel Dörfler // TODO: need to do this in a nicer way. 58186bce45bSbeveloper 58234c72144SAxel Dörfler rv = MediaRosterEx(this)->GetNode(TIME_SOURCE, _node); 58386bce45bSbeveloper if (rv != B_OK) 58486bce45bSbeveloper return rv; 58586bce45bSbeveloper 58686bce45bSbeveloper // We don't do reference counting for timesources, that's why we 58786bce45bSbeveloper // release the node immediately. 58834c72144SAxel Dörfler ReleaseNode(*_node); 58986bce45bSbeveloper 59086bce45bSbeveloper // we need to remember to not use this node with server side reference counting 59134c72144SAxel Dörfler _node->kind |= NODE_KIND_NO_REFCOUNTING; 59286bce45bSbeveloper return B_OK; 59352a38012Sejakowatz } 59452a38012Sejakowatz 59552a38012Sejakowatz 59652a38012Sejakowatz status_t 59752a38012Sejakowatz BMediaRoster::SetVideoInput(const media_node& producer) 59852a38012Sejakowatz { 59952a38012Sejakowatz CALLED(); 6008b04ffc1Sbeveloper return MediaRosterEx(this)->SetNode(VIDEO_INPUT, &producer); 60152a38012Sejakowatz } 60252a38012Sejakowatz 60352a38012Sejakowatz 60452a38012Sejakowatz status_t 60552a38012Sejakowatz BMediaRoster::SetVideoInput(const dormant_node_info& producer) 60652a38012Sejakowatz { 60752a38012Sejakowatz CALLED(); 6088b04ffc1Sbeveloper return MediaRosterEx(this)->SetNode(VIDEO_INPUT, NULL, &producer); 60952a38012Sejakowatz } 61052a38012Sejakowatz 61152a38012Sejakowatz 61252a38012Sejakowatz status_t 61352a38012Sejakowatz BMediaRoster::SetAudioInput(const media_node& producer) 61452a38012Sejakowatz { 61552a38012Sejakowatz CALLED(); 6168b04ffc1Sbeveloper return MediaRosterEx(this)->SetNode(AUDIO_INPUT, &producer); 61752a38012Sejakowatz } 61852a38012Sejakowatz 61952a38012Sejakowatz 62052a38012Sejakowatz status_t 62152a38012Sejakowatz BMediaRoster::SetAudioInput(const dormant_node_info& producer) 62252a38012Sejakowatz { 62352a38012Sejakowatz CALLED(); 6248b04ffc1Sbeveloper return MediaRosterEx(this)->SetNode(AUDIO_INPUT, NULL, &producer); 62552a38012Sejakowatz } 62652a38012Sejakowatz 62752a38012Sejakowatz 62852a38012Sejakowatz status_t 62952a38012Sejakowatz BMediaRoster::SetVideoOutput(const media_node& consumer) 63052a38012Sejakowatz { 63152a38012Sejakowatz CALLED(); 6328b04ffc1Sbeveloper return MediaRosterEx(this)->SetNode(VIDEO_OUTPUT, &consumer); 63352a38012Sejakowatz } 63452a38012Sejakowatz 63552a38012Sejakowatz 63652a38012Sejakowatz status_t 63752a38012Sejakowatz BMediaRoster::SetVideoOutput(const dormant_node_info& consumer) 63852a38012Sejakowatz { 63952a38012Sejakowatz CALLED(); 6408b04ffc1Sbeveloper return MediaRosterEx(this)->SetNode(VIDEO_OUTPUT, NULL, &consumer); 64152a38012Sejakowatz } 64252a38012Sejakowatz 64352a38012Sejakowatz 64452a38012Sejakowatz status_t 64552a38012Sejakowatz BMediaRoster::SetAudioOutput(const media_node& consumer) 64652a38012Sejakowatz { 64752a38012Sejakowatz CALLED(); 6488b04ffc1Sbeveloper return MediaRosterEx(this)->SetNode(AUDIO_OUTPUT, &consumer); 64952a38012Sejakowatz } 65052a38012Sejakowatz 65152a38012Sejakowatz 65252a38012Sejakowatz status_t 65334c72144SAxel Dörfler BMediaRoster::SetAudioOutput(const media_input& input) 65452a38012Sejakowatz { 65552a38012Sejakowatz CALLED(); 65634c72144SAxel Dörfler return MediaRosterEx(this)->SetNode(AUDIO_OUTPUT, NULL, NULL, &input); 65752a38012Sejakowatz } 65852a38012Sejakowatz 65952a38012Sejakowatz 66052a38012Sejakowatz status_t 66152a38012Sejakowatz BMediaRoster::SetAudioOutput(const dormant_node_info& consumer) 66252a38012Sejakowatz { 66352a38012Sejakowatz CALLED(); 6648b04ffc1Sbeveloper return MediaRosterEx(this)->SetNode(AUDIO_OUTPUT, NULL, &consumer); 66552a38012Sejakowatz } 66652a38012Sejakowatz 66752a38012Sejakowatz 66852a38012Sejakowatz status_t 66934c72144SAxel Dörfler BMediaRoster::GetNodeFor(media_node_id node, media_node* clone) 67052a38012Sejakowatz { 6719e9417d2Sbeveloper CALLED(); 6729e9417d2Sbeveloper if (clone == NULL) 6739e9417d2Sbeveloper return B_BAD_VALUE; 67465b73ae4SMarcus Overhagen if (IS_INVALID_NODEID(node)) 6759e9417d2Sbeveloper return B_MEDIA_BAD_NODE; 6769e9417d2Sbeveloper 6779e9417d2Sbeveloper server_get_node_for_request request; 6789e9417d2Sbeveloper server_get_node_for_reply reply; 6799e9417d2Sbeveloper status_t rv; 6809e9417d2Sbeveloper 6819dec2310SAxel Dörfler request.node_id = node; 6829dec2310SAxel Dörfler request.team = BPrivate::current_team(); 6839e9417d2Sbeveloper 68434c72144SAxel Dörfler rv = QueryServer(SERVER_GET_NODE_FOR, &request, sizeof(request), &reply, 68534c72144SAxel Dörfler sizeof(reply)); 6869e9417d2Sbeveloper if (rv != B_OK) 6879e9417d2Sbeveloper return rv; 6889e9417d2Sbeveloper 6899e9417d2Sbeveloper *clone = reply.clone; 6909e9417d2Sbeveloper return B_OK; 69152a38012Sejakowatz } 69252a38012Sejakowatz 69352a38012Sejakowatz 69452a38012Sejakowatz status_t 69552a38012Sejakowatz BMediaRoster::GetSystemTimeSource(media_node* clone) 69652a38012Sejakowatz { 69752a38012Sejakowatz CALLED(); 69886bce45bSbeveloper status_t rv; 69986bce45bSbeveloper 70034c72144SAxel Dörfler // TODO: need to do this in a nicer way. 70186bce45bSbeveloper 70286bce45bSbeveloper rv = MediaRosterEx(this)->GetNode(SYSTEM_TIME_SOURCE, clone); 70386bce45bSbeveloper if (rv != B_OK) 70486bce45bSbeveloper return rv; 70586bce45bSbeveloper 70686bce45bSbeveloper // We don't do reference counting for timesources, that's why we 70786bce45bSbeveloper // release the node immediately. 70886bce45bSbeveloper ReleaseNode(*clone); 70986bce45bSbeveloper 71034c72144SAxel Dörfler // we need to remember to not use this node with server side reference 71134c72144SAxel Dörfler // counting 71286bce45bSbeveloper clone->kind |= NODE_KIND_NO_REFCOUNTING; 71386bce45bSbeveloper 71486bce45bSbeveloper return B_OK; 71552a38012Sejakowatz } 71652a38012Sejakowatz 71752a38012Sejakowatz 71852a38012Sejakowatz status_t 71952a38012Sejakowatz BMediaRoster::ReleaseNode(const media_node& node) 72052a38012Sejakowatz { 7219e9417d2Sbeveloper CALLED(); 72240f36b03Sbeveloper if (IS_INVALID_NODE(node)) 7239e9417d2Sbeveloper return B_MEDIA_BAD_NODE; 72452a38012Sejakowatz 72586bce45bSbeveloper if (node.kind & NODE_KIND_NO_REFCOUNTING) { 72634c72144SAxel Dörfler printf("BMediaRoster::ReleaseNode, trying to release reference " 72734c72144SAxel Dörfler "counting disabled timesource, node %ld, port %ld, team %ld\n", 7289dec2310SAxel Dörfler node.node, node.port, BPrivate::current_team()); 72986bce45bSbeveloper return B_OK; 73086bce45bSbeveloper } 73186bce45bSbeveloper 7329e9417d2Sbeveloper server_release_node_request request; 7339e9417d2Sbeveloper server_release_node_reply reply; 734cf4e2277Sbeveloper status_t rv; 7359e9417d2Sbeveloper 7369e9417d2Sbeveloper request.node = node; 7379dec2310SAxel Dörfler request.team = BPrivate::current_team(); 7389e9417d2Sbeveloper 73934c72144SAxel Dörfler TRACE("BMediaRoster::ReleaseNode, node %ld, port %ld, team %ld\n", 7409dec2310SAxel Dörfler node.node, node.port, BPrivate::current_team()); 741cf4e2277Sbeveloper 74234c72144SAxel Dörfler rv = QueryServer(SERVER_RELEASE_NODE, &request, sizeof(request), &reply, 74334c72144SAxel Dörfler sizeof(reply)); 744cf4e2277Sbeveloper if (rv != B_OK) { 74534c72144SAxel Dörfler ERROR("BMediaRoster::ReleaseNode FAILED, node %ld, port %ld, team " 7469dec2310SAxel Dörfler "%ld!\n", node.node, node.port, BPrivate::current_team()); 747cf4e2277Sbeveloper } 748cf4e2277Sbeveloper return rv; 7499e9417d2Sbeveloper } 75052a38012Sejakowatz 75134c72144SAxel Dörfler 75252a38012Sejakowatz BTimeSource* 75334c72144SAxel Dörfler BMediaRoster::MakeTimeSourceFor(const media_node& forNode) 75452a38012Sejakowatz { 755f180ef79Sbeveloper // MakeTimeSourceFor() returns a BTimeSource object 756f180ef79Sbeveloper // corresponding to the specified node's time source. 757f180ef79Sbeveloper 758835140c8Sbeveloper CALLED(); 759f180ef79Sbeveloper 76034c72144SAxel Dörfler if (IS_SYSTEM_TIMESOURCE(forNode)) { 761f180ef79Sbeveloper // special handling for the system time source 76234c72144SAxel Dörfler TRACE("BMediaRoster::MakeTimeSourceFor, asked for system time " 76334c72144SAxel Dörfler "source\n"); 76434c72144SAxel Dörfler return MediaRosterEx(this)->MakeTimeSourceObject( 76534c72144SAxel Dörfler NODE_SYSTEM_TIMESOURCE_ID); 766f180ef79Sbeveloper } 767f180ef79Sbeveloper 76834c72144SAxel Dörfler if (IS_INVALID_NODE(forNode)) { 76934c72144SAxel Dörfler ERROR("BMediaRoster::MakeTimeSourceFor: for_node invalid, node %ld, " 77034c72144SAxel Dörfler "port %ld, kinds 0x%lx\n", forNode.node, forNode.port, 77134c72144SAxel Dörfler forNode.kind); 7725917dd5bSbeveloper return NULL; 7730e21b167Sbeveloper } 7740e21b167Sbeveloper 77534c72144SAxel Dörfler TRACE("BMediaRoster::MakeTimeSourceFor: node %ld enter\n", forNode.node); 7765917dd5bSbeveloper 7775917dd5bSbeveloper node_get_timesource_request request; 7785917dd5bSbeveloper node_get_timesource_reply reply; 7795917dd5bSbeveloper BTimeSource *source; 7805917dd5bSbeveloper status_t rv; 7815917dd5bSbeveloper 78292e575c1Sbeveloper // ask the node to get it's current timesource id 78334c72144SAxel Dörfler rv = QueryPort(forNode.port, NODE_GET_TIMESOURCE, &request, 78434c72144SAxel Dörfler sizeof(request), &reply, sizeof(reply)); 7855917dd5bSbeveloper if (rv != B_OK) { 7865ac4fbd7Sbeveloper ERROR("BMediaRoster::MakeTimeSourceFor: request failed\n"); 7875917dd5bSbeveloper return NULL; 7885917dd5bSbeveloper } 7895917dd5bSbeveloper 7905917dd5bSbeveloper source = MediaRosterEx(this)->MakeTimeSourceObject(reply.timesource_id); 7915917dd5bSbeveloper 79234c72144SAxel Dörfler TRACE("BMediaRoster::MakeTimeSourceFor: node %ld leave\n", forNode.node); 793287f7492Sbeveloper 794835140c8Sbeveloper return source; 79552a38012Sejakowatz } 79652a38012Sejakowatz 79752a38012Sejakowatz 79852a38012Sejakowatz status_t 79934c72144SAxel Dörfler BMediaRoster::Connect(const media_source& from, const media_destination& to, 80034c72144SAxel Dörfler media_format* _format, media_output* _output, media_input* _input) 80152a38012Sejakowatz { 80234c72144SAxel Dörfler return BMediaRoster::Connect(from, to, _format, _output, _input, 0); 803eae26d3dSbeveloper } 804eae26d3dSbeveloper 805eae26d3dSbeveloper 806eae26d3dSbeveloper status_t 80734c72144SAxel Dörfler BMediaRoster::Connect(const media_source& from, const media_destination& to, 80834c72144SAxel Dörfler media_format* io_format, media_output* out_output, media_input* out_input, 80934c72144SAxel Dörfler uint32 in_flags, void* _reserved) 810eae26d3dSbeveloper { 81152a38012Sejakowatz CALLED(); 81252a38012Sejakowatz if (io_format == NULL || out_output == NULL || out_input == NULL) 81352a38012Sejakowatz return B_BAD_VALUE; 81440f36b03Sbeveloper if (IS_INVALID_SOURCE(from)) { 8155ac4fbd7Sbeveloper ERROR("BMediaRoster::Connect: media_source invalid\n"); 81652a38012Sejakowatz return B_MEDIA_BAD_SOURCE; 8179e9417d2Sbeveloper } 81840f36b03Sbeveloper if (IS_INVALID_DESTINATION(to)) { 8195ac4fbd7Sbeveloper ERROR("BMediaRoster::Connect: media_destination invalid\n"); 82052a38012Sejakowatz return B_MEDIA_BAD_DESTINATION; 8219e9417d2Sbeveloper } 82252a38012Sejakowatz 82352a38012Sejakowatz status_t rv; 82465b73ae4SMarcus Overhagen 82565b73ae4SMarcus Overhagen // find the output and input nodes 82634c72144SAxel Dörfler // TODO: isn't there a easier way? 82765b73ae4SMarcus Overhagen media_node sourcenode; 82865b73ae4SMarcus Overhagen media_node destnode; 82965b73ae4SMarcus Overhagen rv = GetNodeFor(NodeIDFor(from.port), &sourcenode); 83065b73ae4SMarcus Overhagen if (rv != B_OK) { 83134c72144SAxel Dörfler ERROR("BMediaRoster::Connect: Can't find source node for port %ld\n", 83234c72144SAxel Dörfler from.port); 83365b73ae4SMarcus Overhagen return B_MEDIA_BAD_SOURCE; 83465b73ae4SMarcus Overhagen } 83565b73ae4SMarcus Overhagen ReleaseNode(sourcenode); 83665b73ae4SMarcus Overhagen rv = GetNodeFor(NodeIDFor(to.port), &destnode); 83765b73ae4SMarcus Overhagen if (rv != B_OK) { 83834c72144SAxel Dörfler ERROR("BMediaRoster::Connect: Can't find destination node for port " 83934c72144SAxel Dörfler "%ld\n", to.port); 84065b73ae4SMarcus Overhagen return B_MEDIA_BAD_DESTINATION; 84165b73ae4SMarcus Overhagen } 84265b73ae4SMarcus Overhagen ReleaseNode(destnode); 84365b73ae4SMarcus Overhagen 84465b73ae4SMarcus Overhagen if (!(sourcenode.kind & B_BUFFER_PRODUCER)) { 84534c72144SAxel Dörfler ERROR("BMediaRoster::Connect: source node %ld is not a " 84634c72144SAxel Dörfler "B_BUFFER_PRODUCER\n", sourcenode.node); 84765b73ae4SMarcus Overhagen return B_MEDIA_BAD_SOURCE; 84865b73ae4SMarcus Overhagen } 84965b73ae4SMarcus Overhagen if (!(destnode.kind & B_BUFFER_CONSUMER)) { 85034c72144SAxel Dörfler ERROR("BMediaRoster::Connect: destination node %ld is not a " 85134c72144SAxel Dörfler "B_BUFFER_CONSUMER\n", destnode.node); 85265b73ae4SMarcus Overhagen return B_MEDIA_BAD_DESTINATION; 85365b73ae4SMarcus Overhagen } 85465b73ae4SMarcus Overhagen 8558c6a6096Sbeveloper producer_format_proposal_request request1; 8568c6a6096Sbeveloper producer_format_proposal_reply reply1; 85752a38012Sejakowatz 85834c72144SAxel Dörfler PRINT_FORMAT("BMediaRoster::Connect calling " 85934c72144SAxel Dörfler "BBufferProducer::FormatProposal with format ", *io_format); 86069983609Sbeveloper 86152a38012Sejakowatz // BBufferProducer::FormatProposal 8628c6a6096Sbeveloper request1.output = from; 8638c6a6096Sbeveloper request1.format = *io_format; 86434c72144SAxel Dörfler rv = QueryPort(from.port, PRODUCER_FORMAT_PROPOSAL, &request1, 86534c72144SAxel Dörfler sizeof(request1), &reply1, sizeof(reply1)); 8668c6a6096Sbeveloper if (rv != B_OK) { 86734c72144SAxel Dörfler ERROR("BMediaRoster::Connect: aborted after " 86834c72144SAxel Dörfler "BBufferProducer::FormatProposal, status = %#lx\n",rv); 86952a38012Sejakowatz return rv; 87052a38012Sejakowatz } 8718c6a6096Sbeveloper // reply1.format now contains the format proposed by the producer 8728c6a6096Sbeveloper 8738c6a6096Sbeveloper consumer_accept_format_request request2; 8748c6a6096Sbeveloper consumer_accept_format_reply reply2; 8758c6a6096Sbeveloper 87634c72144SAxel Dörfler PRINT_FORMAT("BMediaRoster::Connect calling " 87734c72144SAxel Dörfler "BBufferConsumer::AcceptFormat with format ", reply1.format); 87869983609Sbeveloper 8798c6a6096Sbeveloper // BBufferConsumer::AcceptFormat 8808c6a6096Sbeveloper request2.dest = to; 8818c6a6096Sbeveloper request2.format = reply1.format; 88234c72144SAxel Dörfler rv = QueryPort(to.port, CONSUMER_ACCEPT_FORMAT, &request2, 88334c72144SAxel Dörfler sizeof(request2), &reply2, sizeof(reply2)); 8848c6a6096Sbeveloper if (rv != B_OK) { 88534c72144SAxel Dörfler ERROR("BMediaRoster::Connect: aborted after " 88634c72144SAxel Dörfler "BBufferConsumer::AcceptFormat, status = %#lx\n",rv); 8878c6a6096Sbeveloper return rv; 8888c6a6096Sbeveloper } 8898c6a6096Sbeveloper // reply2.format now contains the format accepted by the consumer 8908c6a6096Sbeveloper 8918c6a6096Sbeveloper // BBufferProducer::PrepareToConnect 8928c6a6096Sbeveloper producer_prepare_to_connect_request request3; 8938c6a6096Sbeveloper producer_prepare_to_connect_reply reply3; 8948c6a6096Sbeveloper 89534c72144SAxel Dörfler PRINT_FORMAT("BMediaRoster::Connect calling " 89634c72144SAxel Dörfler "BBufferProducer::PrepareToConnect with format", reply2.format); 89769983609Sbeveloper 8988c6a6096Sbeveloper request3.source = from; 8998c6a6096Sbeveloper request3.destination = to; 9008c6a6096Sbeveloper request3.format = reply2.format; 90134c72144SAxel Dörfler strcpy(request3.name, "XXX some default name"); // TODO: fix this 90234c72144SAxel Dörfler rv = QueryPort(from.port, PRODUCER_PREPARE_TO_CONNECT, &request3, 90334c72144SAxel Dörfler sizeof(request3), &reply3, sizeof(reply3)); 9048c6a6096Sbeveloper if (rv != B_OK) { 90534c72144SAxel Dörfler ERROR("BMediaRoster::Connect: aborted after " 90634c72144SAxel Dörfler "BBufferProducer::PrepareToConnect, status = %#lx\n",rv); 9078c6a6096Sbeveloper return rv; 9088c6a6096Sbeveloper } 9098c6a6096Sbeveloper // reply3.format is still our pretty media format 9108c6a6096Sbeveloper // reply3.out_source the real source to be used for the connection 91134c72144SAxel Dörfler // reply3.name the name BBufferConsumer::Connected will see in the 91234c72144SAxel Dörfler // outInput->name argument 9138c6a6096Sbeveloper 9148c6a6096Sbeveloper // BBufferConsumer::Connected 9158c6a6096Sbeveloper consumer_connected_request request4; 9168c6a6096Sbeveloper consumer_connected_reply reply4; 9178c6a6096Sbeveloper status_t con_status; 9188c6a6096Sbeveloper 91934c72144SAxel Dörfler PRINT_FORMAT("BMediaRoster::Connect calling BBufferConsumer::Connected() " 92034c72144SAxel Dörfler "with format ", reply3.format); 92169983609Sbeveloper 92269983609Sbeveloper request4.input.node = destnode; 92369983609Sbeveloper request4.input.source = reply3.out_source; 92469983609Sbeveloper request4.input.destination = to; 92569983609Sbeveloper request4.input.format = reply3.format; 92669983609Sbeveloper strcpy(request4.input.name, reply3.name); 92769983609Sbeveloper 92834c72144SAxel Dörfler con_status = QueryPort(to.port, CONSUMER_CONNECTED, &request4, 92934c72144SAxel Dörfler sizeof(request4), &reply4, sizeof(reply4)); 9308c6a6096Sbeveloper if (con_status != B_OK) { 93134c72144SAxel Dörfler ERROR("BMediaRoster::Connect: aborting after " 93234c72144SAxel Dörfler "BBufferConsumer::Connected, status = %#lx\n",con_status); 9338c6a6096Sbeveloper // we do NOT return here! 9348c6a6096Sbeveloper } 93534c72144SAxel Dörfler // con_status contains the status code to be supplied to 93634c72144SAxel Dörfler // BBufferProducer::Connect's status argument 93734c72144SAxel Dörfler // reply4.input contains the media_input that describes the connection 93834c72144SAxel Dörfler // from the consumer point of view 9398c6a6096Sbeveloper 9408c6a6096Sbeveloper // BBufferProducer::Connect 9418c6a6096Sbeveloper producer_connect_request request5; 9428c6a6096Sbeveloper producer_connect_reply reply5; 9438c6a6096Sbeveloper 94434c72144SAxel Dörfler PRINT_FORMAT("BMediaRoster::Connect calling BBufferProducer::Connect with " 94534c72144SAxel Dörfler "format ", reply4.input.format); 94669983609Sbeveloper 9478c6a6096Sbeveloper request5.error = con_status; 9488c6a6096Sbeveloper request5.source = reply3.out_source; 9498c6a6096Sbeveloper request5.destination = reply4.input.destination; 95069983609Sbeveloper request5.format = reply4.input.format; 9518c6a6096Sbeveloper strcpy(request5.name, reply4.input.name); 95234c72144SAxel Dörfler rv = QueryPort(reply4.input.source.port, PRODUCER_CONNECT, &request5, 95334c72144SAxel Dörfler sizeof(request5), &reply5, sizeof(reply5)); 9548c6a6096Sbeveloper if (con_status != B_OK) { 9555ac4fbd7Sbeveloper ERROR("BMediaRoster::Connect: aborted\n"); 9568c6a6096Sbeveloper return con_status; 9578c6a6096Sbeveloper } 9588c6a6096Sbeveloper if (rv != B_OK) { 95934c72144SAxel Dörfler ERROR("BMediaRoster::Connect: aborted after BBufferProducer::Connect()" 96034c72144SAxel Dörfler ", status = %#lx\n",rv); 9618c6a6096Sbeveloper return rv; 9628c6a6096Sbeveloper } 9638c6a6096Sbeveloper // reply5.name contains the name assigned to the connection by the producer 9648c6a6096Sbeveloper 9658c6a6096Sbeveloper // initilize connection info 96669983609Sbeveloper *io_format = reply4.input.format; 9678c6a6096Sbeveloper *out_input = reply4.input; 9688c6a6096Sbeveloper out_output->node = sourcenode; 9698c6a6096Sbeveloper out_output->source = reply4.input.source; 9708c6a6096Sbeveloper out_output->destination = reply4.input.destination; 9718c6a6096Sbeveloper out_output->format = reply4.input.format; 9728c6a6096Sbeveloper strcpy(out_output->name, reply5.name); 9738c6a6096Sbeveloper 9748c6a6096Sbeveloper // the connection is now made 97569983609Sbeveloper printf("BMediaRoster::Connect connection established!\n"); 97669983609Sbeveloper PRINT_FORMAT(" format", *io_format); 97769983609Sbeveloper PRINT_INPUT(" input", *out_input); 97869983609Sbeveloper PRINT_OUTPUT(" output", *out_output); 9798c6a6096Sbeveloper 98034c72144SAxel Dörfler // TODO: register connection with server 98134c72144SAxel Dörfler // TODO: we should just send a notification, instead of republishing all 98234c72144SAxel Dörfler // endpoints 98376669a29Sbeveloper List<media_output> outlist; 98476669a29Sbeveloper List<media_input> inlist; 98534c72144SAxel Dörfler if (MediaRosterEx(this)->GetAllOutputs(out_output->node , &outlist) == B_OK) 9868b04ffc1Sbeveloper MediaRosterEx(this)->PublishOutputs(out_output->node , &outlist); 98734c72144SAxel Dörfler if (MediaRosterEx(this)->GetAllInputs(out_input->node , &inlist) == B_OK) 9888b04ffc1Sbeveloper MediaRosterEx(this)->PublishInputs(out_input->node, &inlist); 9898c6a6096Sbeveloper 99034c72144SAxel Dörfler // TODO: if (mute) BBufferProducer::EnableOutput(false) 9919e9417d2Sbeveloper if (in_flags & B_CONNECT_MUTED) { 9929e9417d2Sbeveloper } 9938c6a6096Sbeveloper 9949e9417d2Sbeveloper // send a notification 99534c72144SAxel Dörfler BPrivate::media::notifications::ConnectionMade(*out_input, *out_output, 99634c72144SAxel Dörfler *io_format); 9979e9417d2Sbeveloper 9988c6a6096Sbeveloper return B_OK; 9998c6a6096Sbeveloper }; 100052a38012Sejakowatz 100152a38012Sejakowatz 100252a38012Sejakowatz status_t 10039e9417d2Sbeveloper BMediaRoster::Disconnect(media_node_id source_nodeid, 100434c72144SAxel Dörfler const media_source& source, media_node_id destination_nodeid, 100552a38012Sejakowatz const media_destination& destination) 100652a38012Sejakowatz { 10079e9417d2Sbeveloper CALLED(); 100840f36b03Sbeveloper if (IS_INVALID_NODEID(source_nodeid)) { 10095ac4fbd7Sbeveloper ERROR("BMediaRoster::Disconnect: source media_node_id invalid\n"); 10109e9417d2Sbeveloper return B_MEDIA_BAD_SOURCE; 10119e9417d2Sbeveloper } 101240f36b03Sbeveloper if (IS_INVALID_NODEID(destination_nodeid)) { 10135ac4fbd7Sbeveloper ERROR("BMediaRoster::Disconnect: destination media_node_id invalid\n"); 10149e9417d2Sbeveloper return B_MEDIA_BAD_DESTINATION; 10159e9417d2Sbeveloper } 101640f36b03Sbeveloper if (IS_INVALID_SOURCE(source)) { 10175ac4fbd7Sbeveloper ERROR("BMediaRoster::Disconnect: media_source invalid\n"); 10189e9417d2Sbeveloper return B_MEDIA_BAD_SOURCE; 10199e9417d2Sbeveloper } 102040f36b03Sbeveloper if (IS_INVALID_DESTINATION(destination)) { 10215ac4fbd7Sbeveloper ERROR("BMediaRoster::Disconnect: media_destination invalid\n"); 10229e9417d2Sbeveloper return B_MEDIA_BAD_DESTINATION; 10239e9417d2Sbeveloper } 10249e9417d2Sbeveloper 10259e9417d2Sbeveloper producer_disconnect_request request2; 10269e9417d2Sbeveloper producer_disconnect_reply reply2; 10279e9417d2Sbeveloper consumer_disconnected_request request1; 10289e9417d2Sbeveloper consumer_disconnected_reply reply1; 10299e9417d2Sbeveloper status_t rv1, rv2; 10309e9417d2Sbeveloper 103134c72144SAxel Dörfler // TODO: we should ask the server if this connection really exists 10329e9417d2Sbeveloper 10339e9417d2Sbeveloper request1.source = source; 10349e9417d2Sbeveloper request1.destination = destination; 10359e9417d2Sbeveloper request2.source = source; 10369e9417d2Sbeveloper request2.destination = destination; 10379e9417d2Sbeveloper 103834c72144SAxel Dörfler rv1 = QueryPort(source.port, PRODUCER_DISCONNECT, &request1, 103934c72144SAxel Dörfler sizeof(request1), &reply1, sizeof(reply1)); 104034c72144SAxel Dörfler rv2 = QueryPort(destination.port, CONSUMER_DISCONNECTED, &request2, 104134c72144SAxel Dörfler sizeof(request2), &reply2, sizeof(reply2)); 10429e9417d2Sbeveloper 104334c72144SAxel Dörfler // TODO: unregister connection with server 104434c72144SAxel Dörfler // TODO: we should just send a notification, instead of republishing all 104534c72144SAxel Dörfler // endpoints 104676669a29Sbeveloper List<media_output> outlist; 104776669a29Sbeveloper List<media_input> inlist; 10489e9417d2Sbeveloper media_node sourcenode; 10499e9417d2Sbeveloper media_node destnode; 105034c72144SAxel Dörfler if (GetNodeFor(source_nodeid, &sourcenode) == B_OK) { 105165b73ae4SMarcus Overhagen if (!(sourcenode.kind & B_BUFFER_PRODUCER)) { 105234c72144SAxel Dörfler ERROR("BMediaRoster::Disconnect: source_nodeid %ld is not a " 105334c72144SAxel Dörfler "B_BUFFER_PRODUCER\n", source_nodeid); 105465b73ae4SMarcus Overhagen } 105534c72144SAxel Dörfler if (MediaRosterEx(this)->GetAllOutputs(sourcenode , &outlist) == B_OK) 10568b04ffc1Sbeveloper MediaRosterEx(this)->PublishOutputs(sourcenode , &outlist); 10579e9417d2Sbeveloper ReleaseNode(sourcenode); 10584f09fa2fSbeveloper } else { 105965b73ae4SMarcus Overhagen ERROR("BMediaRoster::Disconnect: GetNodeFor source_nodeid %ld failed\n", source_nodeid); 10604f09fa2fSbeveloper } 106134c72144SAxel Dörfler if (GetNodeFor(destination_nodeid, &destnode) == B_OK) { 106265b73ae4SMarcus Overhagen if (!(destnode.kind & B_BUFFER_CONSUMER)) { 106334c72144SAxel Dörfler ERROR("BMediaRoster::Disconnect: destination_nodeid %ld is not a " 106434c72144SAxel Dörfler "B_BUFFER_CONSUMER\n", destination_nodeid); 106565b73ae4SMarcus Overhagen } 106634c72144SAxel Dörfler if (MediaRosterEx(this)->GetAllInputs(destnode , &inlist) == B_OK) 10678b04ffc1Sbeveloper MediaRosterEx(this)->PublishInputs(destnode, &inlist); 10689e9417d2Sbeveloper ReleaseNode(destnode); 10694f09fa2fSbeveloper } else { 107034c72144SAxel Dörfler ERROR("BMediaRoster::Disconnect: GetNodeFor destination_nodeid %ld " 107134c72144SAxel Dörfler "failed\n", destination_nodeid); 10724f09fa2fSbeveloper } 10739e9417d2Sbeveloper 10749e9417d2Sbeveloper // send a notification 10759e9417d2Sbeveloper BPrivate::media::notifications::ConnectionBroken(source, destination); 10769e9417d2Sbeveloper 107734c72144SAxel Dörfler return rv1 != B_OK || rv2 != B_OK ? B_ERROR : B_OK; 107852a38012Sejakowatz } 107952a38012Sejakowatz 108034c72144SAxel Dörfler 108165b73ae4SMarcus Overhagen status_t 108265b73ae4SMarcus Overhagen BMediaRoster::Disconnect(const media_output& output, const media_input& input) 108365b73ae4SMarcus Overhagen { 108465b73ae4SMarcus Overhagen if (IS_INVALID_NODEID(output.node.node)) { 108565b73ae4SMarcus Overhagen printf("BMediaRoster::Disconnect: output.node.node %ld invalid\n", 108665b73ae4SMarcus Overhagen output.node.node); 108765b73ae4SMarcus Overhagen return B_MEDIA_BAD_SOURCE; 108865b73ae4SMarcus Overhagen } 108965b73ae4SMarcus Overhagen if (IS_INVALID_NODEID(input.node.node)) { 109065b73ae4SMarcus Overhagen printf("BMediaRoster::Disconnect: input.node.node %ld invalid\n", 109165b73ae4SMarcus Overhagen input.node.node); 109265b73ae4SMarcus Overhagen return B_MEDIA_BAD_DESTINATION; 109365b73ae4SMarcus Overhagen } 109465b73ae4SMarcus Overhagen if (!(output.node.kind & B_BUFFER_PRODUCER)) { 109534c72144SAxel Dörfler printf("BMediaRoster::Disconnect: output.node.kind 0x%lx is no " 109634c72144SAxel Dörfler "B_BUFFER_PRODUCER\n", output.node.kind); 109765b73ae4SMarcus Overhagen return B_MEDIA_BAD_SOURCE; 109865b73ae4SMarcus Overhagen } 109965b73ae4SMarcus Overhagen if (!(input.node.kind & B_BUFFER_CONSUMER)) { 110034c72144SAxel Dörfler printf("BMediaRoster::Disconnect: input.node.kind 0x%lx is no " 110134c72144SAxel Dörfler "B_BUFFER_PRODUCER\n", input.node.kind); 110265b73ae4SMarcus Overhagen return B_MEDIA_BAD_DESTINATION; 110365b73ae4SMarcus Overhagen } 110465b73ae4SMarcus Overhagen if (input.source.port != output.source.port) { 110534c72144SAxel Dörfler printf("BMediaRoster::Disconnect: input.source.port %ld doesn't match " 110634c72144SAxel Dörfler "output.source.port %ld\n", input.source.port, output.source.port); 110765b73ae4SMarcus Overhagen return B_MEDIA_BAD_SOURCE; 110865b73ae4SMarcus Overhagen } 110965b73ae4SMarcus Overhagen if (input.source.id != output.source.id) { 111034c72144SAxel Dörfler printf("BMediaRoster::Disconnect: input.source.id %ld doesn't match " 111134c72144SAxel Dörfler "output.source.id %ld\n", input.source.id, output.source.id); 111265b73ae4SMarcus Overhagen return B_MEDIA_BAD_SOURCE; 111365b73ae4SMarcus Overhagen } 111465b73ae4SMarcus Overhagen if (input.destination.port != output.destination.port) { 111534c72144SAxel Dörfler printf("BMediaRoster::Disconnect: input.destination.port %ld doesn't " 111634c72144SAxel Dörfler "match output.destination.port %ld\n", input.destination.port, 111734c72144SAxel Dörfler output.destination.port); 111865b73ae4SMarcus Overhagen return B_MEDIA_BAD_DESTINATION; 111965b73ae4SMarcus Overhagen } 112065b73ae4SMarcus Overhagen if (input.destination.id != output.destination.id) { 112134c72144SAxel Dörfler printf("BMediaRoster::Disconnect: input.destination.id %ld doesn't " 112234c72144SAxel Dörfler "match output.destination.id %ld\n", input.destination.id, 112334c72144SAxel Dörfler output.destination.id); 112465b73ae4SMarcus Overhagen return B_MEDIA_BAD_DESTINATION; 112565b73ae4SMarcus Overhagen } 112634c72144SAxel Dörfler 112734c72144SAxel Dörfler return Disconnect(output.node.node, output.source, input.node.node, 112834c72144SAxel Dörfler input.destination); 112965b73ae4SMarcus Overhagen } 113065b73ae4SMarcus Overhagen 113152a38012Sejakowatz 113252a38012Sejakowatz status_t 113334c72144SAxel Dörfler BMediaRoster::StartNode(const media_node& node, bigtime_t atPerformanceTime) 113452a38012Sejakowatz { 113552a38012Sejakowatz CALLED(); 11369e9417d2Sbeveloper if (node.node <= 0) 113752a38012Sejakowatz return B_MEDIA_BAD_NODE; 113852a38012Sejakowatz 113934c72144SAxel Dörfler TRACE("BMediaRoster::StartNode, node %ld, at perf %Ld\n", node.node, 114034c72144SAxel Dörfler atPerformanceTime); 11410e21b167Sbeveloper 11426396865dSbeveloper node_start_command command; 114334c72144SAxel Dörfler command.performance_time = atPerformanceTime; 114452a38012Sejakowatz 11456396865dSbeveloper return SendToPort(node.port, NODE_START, &command, sizeof(command)); 114652a38012Sejakowatz } 114752a38012Sejakowatz 114852a38012Sejakowatz 114952a38012Sejakowatz status_t 115034c72144SAxel Dörfler BMediaRoster::StopNode(const media_node& node, bigtime_t atPerformanceTime, 115152a38012Sejakowatz bool immediate) 115252a38012Sejakowatz { 115352a38012Sejakowatz CALLED(); 115440f36b03Sbeveloper if (IS_INVALID_NODE(node)) 115552a38012Sejakowatz return B_MEDIA_BAD_NODE; 115652a38012Sejakowatz 115734c72144SAxel Dörfler TRACE("BMediaRoster::StopNode, node %ld, at perf %Ld %s\n", node.node, 115834c72144SAxel Dörfler atPerformanceTime, immediate ? "NOW" : ""); 11590e21b167Sbeveloper 11606396865dSbeveloper node_stop_command command; 116134c72144SAxel Dörfler command.performance_time = atPerformanceTime; 11626396865dSbeveloper command.immediate = immediate; 116352a38012Sejakowatz 11646396865dSbeveloper return SendToPort(node.port, NODE_STOP, &command, sizeof(command)); 116552a38012Sejakowatz } 116652a38012Sejakowatz 116752a38012Sejakowatz 116852a38012Sejakowatz status_t 116934c72144SAxel Dörfler BMediaRoster::SeekNode(const media_node& node, bigtime_t toMediaTime, 117034c72144SAxel Dörfler bigtime_t atPerformanceTime) 117152a38012Sejakowatz { 117252a38012Sejakowatz CALLED(); 117340f36b03Sbeveloper if (IS_INVALID_NODE(node)) 117452a38012Sejakowatz return B_MEDIA_BAD_NODE; 117552a38012Sejakowatz 117634c72144SAxel Dörfler TRACE("BMediaRoster::SeekNode, node %ld, at perf %Ld, to perf %Ld\n", 117734c72144SAxel Dörfler node.node, atPerformanceTime, toMediaTime); 11780e21b167Sbeveloper 11796396865dSbeveloper node_seek_command command; 118034c72144SAxel Dörfler command.media_time = toMediaTime; 118134c72144SAxel Dörfler command.performance_time = atPerformanceTime; 118252a38012Sejakowatz 11836396865dSbeveloper return SendToPort(node.port, NODE_SEEK, &command, sizeof(command)); 118452a38012Sejakowatz } 118552a38012Sejakowatz 118652a38012Sejakowatz 118752a38012Sejakowatz status_t 118834c72144SAxel Dörfler BMediaRoster::StartTimeSource(const media_node& node, bigtime_t atRealTime) 118952a38012Sejakowatz { 119052a38012Sejakowatz CALLED(); 119160f15390Sbeveloper if (IS_SYSTEM_TIMESOURCE(node)) { 119234c72144SAxel Dörfler // TODO: debug this 11935ac4fbd7Sbeveloper //ERROR("BMediaRoster::StartTimeSource node %ld is system timesource\n", node.node); 119460f15390Sbeveloper return B_OK; 119560f15390Sbeveloper } 119692e575c1Sbeveloper // if (IS_SHADOW_TIMESOURCE(node)) { 119734c72144SAxel Dörfler // // TODO: debug this 119892e575c1Sbeveloper // ERROR("BMediaRoster::StartTimeSource node %ld is shadow timesource\n", node.node); 119992e575c1Sbeveloper // return B_OK; 120092e575c1Sbeveloper // } 120140f36b03Sbeveloper if (IS_INVALID_NODE(node)) { 12025ac4fbd7Sbeveloper ERROR("BMediaRoster::StartTimeSource node %ld invalid\n", node.node); 120352a38012Sejakowatz return B_MEDIA_BAD_NODE; 12040e21b167Sbeveloper } 12050e21b167Sbeveloper if ((node.kind & B_TIME_SOURCE) == 0) { 120634c72144SAxel Dörfler ERROR("BMediaRoster::StartTimeSource node %ld is no timesource\n", 120734c72144SAxel Dörfler node.node); 120852a38012Sejakowatz return B_MEDIA_BAD_NODE; 12090e21b167Sbeveloper } 12100e21b167Sbeveloper 121134c72144SAxel Dörfler TRACE("BMediaRoster::StartTimeSource, node %ld, at real %Ld\n", node.node, 1212791a4a77SStephan Aßmus atRealTime); 121352a38012Sejakowatz 121452a38012Sejakowatz BTimeSource::time_source_op_info msg; 121552a38012Sejakowatz msg.op = BTimeSource::B_TIMESOURCE_START; 121634c72144SAxel Dörfler msg.real_time = atRealTime; 121752a38012Sejakowatz 121852a38012Sejakowatz return write_port(node.port, TIMESOURCE_OP, &msg, sizeof(msg)); 121952a38012Sejakowatz } 122052a38012Sejakowatz 122152a38012Sejakowatz 122252a38012Sejakowatz status_t 122334c72144SAxel Dörfler BMediaRoster::StopTimeSource(const media_node& node, bigtime_t atRealTime, 122452a38012Sejakowatz bool immediate) 122552a38012Sejakowatz { 122652a38012Sejakowatz CALLED(); 122760f15390Sbeveloper if (IS_SYSTEM_TIMESOURCE(node)) { 122834c72144SAxel Dörfler // TODO: debug this 12295ac4fbd7Sbeveloper //ERROR("BMediaRoster::StopTimeSource node %ld is system timesource\n", node.node); 123060f15390Sbeveloper return B_OK; 123160f15390Sbeveloper } 123292e575c1Sbeveloper // if (IS_SHADOW_TIMESOURCE(node)) { 123334c72144SAxel Dörfler // // TODO: debug this 123492e575c1Sbeveloper // ERROR("BMediaRoster::StopTimeSource node %ld is shadow timesource\n", node.node); 123592e575c1Sbeveloper // return B_OK; 123692e575c1Sbeveloper // } 123740f36b03Sbeveloper if (IS_INVALID_NODE(node)) { 12385ac4fbd7Sbeveloper ERROR("BMediaRoster::StopTimeSource node %ld invalid\n", node.node); 123952a38012Sejakowatz return B_MEDIA_BAD_NODE; 12400e21b167Sbeveloper } 12410e21b167Sbeveloper if ((node.kind & B_TIME_SOURCE) == 0) { 124234c72144SAxel Dörfler ERROR("BMediaRoster::StopTimeSource node %ld is no timesource\n", 124334c72144SAxel Dörfler node.node); 124452a38012Sejakowatz return B_MEDIA_BAD_NODE; 12450e21b167Sbeveloper } 12460e21b167Sbeveloper 124734c72144SAxel Dörfler TRACE("BMediaRoster::StopTimeSource, node %ld, at real %Ld %s\n", 124834c72144SAxel Dörfler node.node, atRealTime, immediate ? "NOW" : ""); 124952a38012Sejakowatz 125052a38012Sejakowatz BTimeSource::time_source_op_info msg; 125134c72144SAxel Dörfler msg.op = immediate ? BTimeSource::B_TIMESOURCE_STOP_IMMEDIATELY 125234c72144SAxel Dörfler : BTimeSource::B_TIMESOURCE_STOP; 125334c72144SAxel Dörfler msg.real_time = atRealTime; 125452a38012Sejakowatz 125552a38012Sejakowatz return write_port(node.port, TIMESOURCE_OP, &msg, sizeof(msg)); 125652a38012Sejakowatz } 125752a38012Sejakowatz 125852a38012Sejakowatz 125952a38012Sejakowatz status_t 126052a38012Sejakowatz BMediaRoster::SeekTimeSource(const media_node& node, 126134c72144SAxel Dörfler bigtime_t toPerformanceTime, bigtime_t atRealTime) 126252a38012Sejakowatz { 126352a38012Sejakowatz CALLED(); 126460f15390Sbeveloper if (IS_SYSTEM_TIMESOURCE(node)) { 126534c72144SAxel Dörfler // TODO: debug this 12665ac4fbd7Sbeveloper // ERROR("BMediaRoster::SeekTimeSource node %ld is system timesource\n", node.node); 126760f15390Sbeveloper // you can't seek the system time source, but 126860f15390Sbeveloper // returning B_ERROR would break StampTV 126960f15390Sbeveloper return B_OK; 127060f15390Sbeveloper } 127192e575c1Sbeveloper // if (IS_SHADOW_TIMESOURCE(node)) { 127234c72144SAxel Dörfler // // TODO: debug this 127392e575c1Sbeveloper // ERROR("BMediaRoster::SeekTimeSource node %ld is shadow timesource\n", node.node); 127492e575c1Sbeveloper // return B_OK; 127592e575c1Sbeveloper // } 127640f36b03Sbeveloper if (IS_INVALID_NODE(node)) { 12775ac4fbd7Sbeveloper ERROR("BMediaRoster::SeekTimeSource node %ld invalid\n", node.node); 127852a38012Sejakowatz return B_MEDIA_BAD_NODE; 12790e21b167Sbeveloper } 12800e21b167Sbeveloper if ((node.kind & B_TIME_SOURCE) == 0) { 128134c72144SAxel Dörfler ERROR("BMediaRoster::SeekTimeSource node %ld is no timesource\n", 128234c72144SAxel Dörfler node.node); 128352a38012Sejakowatz return B_MEDIA_BAD_NODE; 12840e21b167Sbeveloper } 12850e21b167Sbeveloper 128634c72144SAxel Dörfler TRACE("BMediaRoster::SeekTimeSource, node %ld, at real %Ld, to perf %Ld\n", 128734c72144SAxel Dörfler node.node, atRealTime, toPerformanceTime); 128852a38012Sejakowatz 128952a38012Sejakowatz BTimeSource::time_source_op_info msg; 129052a38012Sejakowatz msg.op = BTimeSource::B_TIMESOURCE_SEEK; 129134c72144SAxel Dörfler msg.real_time = atRealTime; 129234c72144SAxel Dörfler msg.performance_time = toPerformanceTime; 129352a38012Sejakowatz 129452a38012Sejakowatz return write_port(node.port, TIMESOURCE_OP, &msg, sizeof(msg)); 129552a38012Sejakowatz } 129652a38012Sejakowatz 129752a38012Sejakowatz 129852a38012Sejakowatz status_t 129934c72144SAxel Dörfler BMediaRoster::SyncToNode(const media_node& node, bigtime_t atTime, 130052a38012Sejakowatz bigtime_t timeout) 130152a38012Sejakowatz { 130252a38012Sejakowatz UNIMPLEMENTED(); 130360f15390Sbeveloper return B_OK; 130452a38012Sejakowatz } 130552a38012Sejakowatz 130652a38012Sejakowatz 130752a38012Sejakowatz status_t 130834c72144SAxel Dörfler BMediaRoster::SetRunModeNode(const media_node& node, BMediaNode::run_mode mode) 130952a38012Sejakowatz { 131031cf24c1SMarcus Overhagen TRACE("BMediaRoster::SetRunModeNode, node %ld, mode %d\n", node.node, mode); 131140f36b03Sbeveloper if (IS_INVALID_NODE(node)) 131252a38012Sejakowatz return B_MEDIA_BAD_NODE; 131352a38012Sejakowatz 1314dfb2ad61Sbeveloper node_set_run_mode_command msg; 131552a38012Sejakowatz msg.mode = mode; 131652a38012Sejakowatz 131752a38012Sejakowatz return write_port(node.port, NODE_SET_RUN_MODE, &msg, sizeof(msg)); 131852a38012Sejakowatz } 131952a38012Sejakowatz 132052a38012Sejakowatz 132152a38012Sejakowatz status_t 132252a38012Sejakowatz BMediaRoster::PrerollNode(const media_node& node) 132352a38012Sejakowatz { 132452a38012Sejakowatz CALLED(); 132540f36b03Sbeveloper if (IS_INVALID_NODE(node)) 132652a38012Sejakowatz return B_MEDIA_BAD_NODE; 132752a38012Sejakowatz 132852a38012Sejakowatz char dummy; 132952a38012Sejakowatz return write_port(node.port, NODE_PREROLL, &dummy, sizeof(dummy)); 133052a38012Sejakowatz } 133152a38012Sejakowatz 133252a38012Sejakowatz 133352a38012Sejakowatz status_t 133434c72144SAxel Dörfler BMediaRoster::RollNode(const media_node& node, bigtime_t startPerformance, 133534c72144SAxel Dörfler bigtime_t stopPerformance, bigtime_t atMediaTime) 133652a38012Sejakowatz { 133752a38012Sejakowatz UNIMPLEMENTED(); 133852a38012Sejakowatz return B_ERROR; 133952a38012Sejakowatz } 134052a38012Sejakowatz 134152a38012Sejakowatz 134252a38012Sejakowatz status_t 134352a38012Sejakowatz BMediaRoster::SetProducerRunModeDelay(const media_node& node, 134434c72144SAxel Dörfler bigtime_t delay, BMediaNode::run_mode mode) 134552a38012Sejakowatz { 134634c72144SAxel Dörfler TRACE("BMediaRoster::SetProducerRunModeDelay, node %ld, delay %Ld, " 134734c72144SAxel Dörfler "mode %d\n", node.node, delay, mode); 134860f15390Sbeveloper if (IS_INVALID_NODE(node)) 134960f15390Sbeveloper return B_MEDIA_BAD_NODE; 135060f15390Sbeveloper if ((node.kind & B_BUFFER_PRODUCER) == 0) 135160f15390Sbeveloper return B_MEDIA_BAD_NODE; 135260f15390Sbeveloper 135360f15390Sbeveloper producer_set_run_mode_delay_command command; 135460f15390Sbeveloper command.mode = mode; 135560f15390Sbeveloper command.delay = delay; 135660f15390Sbeveloper 135734c72144SAxel Dörfler return SendToPort(node.port, PRODUCER_SET_RUN_MODE_DELAY, &command, 135834c72144SAxel Dörfler sizeof(command)); 135952a38012Sejakowatz } 136052a38012Sejakowatz 136152a38012Sejakowatz 136252a38012Sejakowatz status_t 136334c72144SAxel Dörfler BMediaRoster::SetProducerRate(const media_node& producer, int32 numer, 136452a38012Sejakowatz int32 denom) 136552a38012Sejakowatz { 136652a38012Sejakowatz CALLED(); 136740f36b03Sbeveloper if (IS_INVALID_NODE(producer)) 136852a38012Sejakowatz return B_MEDIA_BAD_NODE; 136952a38012Sejakowatz if ((producer.kind & B_BUFFER_PRODUCER) == 0) 137052a38012Sejakowatz return B_MEDIA_BAD_NODE; 137152a38012Sejakowatz 1372dfb2ad61Sbeveloper producer_set_play_rate_request msg; 1373dfb2ad61Sbeveloper producer_set_play_rate_reply reply; 137452a38012Sejakowatz status_t rv; 137552a38012Sejakowatz int32 code; 137652a38012Sejakowatz 137752a38012Sejakowatz msg.numer = numer; 137852a38012Sejakowatz msg.denom = denom; 13799834d875SAxel Dörfler msg.reply_port = gPortPool->GetPort(); 138052a38012Sejakowatz rv = write_port(producer.node, PRODUCER_SET_PLAY_RATE, &msg, sizeof(msg)); 138152a38012Sejakowatz if (rv != B_OK) { 13829834d875SAxel Dörfler gPortPool->PutPort(msg.reply_port); 138352a38012Sejakowatz return rv; 138452a38012Sejakowatz } 138552a38012Sejakowatz rv = read_port(msg.reply_port, &code, &reply, sizeof(reply)); 13869834d875SAxel Dörfler gPortPool->PutPort(msg.reply_port); 138752a38012Sejakowatz return (rv < B_OK) ? rv : reply.result; 138852a38012Sejakowatz } 138952a38012Sejakowatz 139052a38012Sejakowatz 139134c72144SAxel Dörfler /*! Nodes will have available inputs/outputs as long as they are capable 139234c72144SAxel Dörfler of accepting more connections. The node may create an additional 139334c72144SAxel Dörfler output or input as the currently available is taken into usage. 139434c72144SAxel Dörfler */ 139552a38012Sejakowatz status_t 139652a38012Sejakowatz BMediaRoster::GetLiveNodeInfo(const media_node& node, 139752a38012Sejakowatz live_node_info* out_live_info) 139852a38012Sejakowatz { 13999e9417d2Sbeveloper CALLED(); 14009e9417d2Sbeveloper if (out_live_info == NULL) 14019e9417d2Sbeveloper return B_BAD_VALUE; 140240f36b03Sbeveloper if (IS_INVALID_NODE(node)) 14039e9417d2Sbeveloper return B_MEDIA_BAD_NODE; 14049e9417d2Sbeveloper 14059e9417d2Sbeveloper server_get_live_node_info_request request; 14069e9417d2Sbeveloper server_get_live_node_info_reply reply; 14079e9417d2Sbeveloper status_t rv; 14089e9417d2Sbeveloper 14099e9417d2Sbeveloper request.node = node; 14109e9417d2Sbeveloper 141134c72144SAxel Dörfler rv = QueryServer(SERVER_GET_LIVE_NODE_INFO, &request, sizeof(request), 141234c72144SAxel Dörfler &reply, sizeof(reply)); 14139e9417d2Sbeveloper if (rv != B_OK) 14149e9417d2Sbeveloper return rv; 14159e9417d2Sbeveloper 14169e9417d2Sbeveloper *out_live_info = reply.live_info; 14179e9417d2Sbeveloper return B_OK; 141852a38012Sejakowatz } 141952a38012Sejakowatz 142052a38012Sejakowatz 142152a38012Sejakowatz status_t 14229c3b4706SAxel Dörfler BMediaRoster::GetLiveNodes(live_node_info* liveNodes, int32* _totalCount, 142334c72144SAxel Dörfler const media_format* hasInput, const media_format* hasOutput, 142434c72144SAxel Dörfler const char* name, uint64 nodeKinds) 142552a38012Sejakowatz { 14269e9417d2Sbeveloper CALLED(); 14279c3b4706SAxel Dörfler if (liveNodes == NULL || _totalCount == NULL || *_totalCount <= 0) 14289e9417d2Sbeveloper return B_BAD_VALUE; 14299e9417d2Sbeveloper 143034c72144SAxel Dörfler // TODO: we also support the wildcard search as GetDormantNodes does. 143134c72144SAxel Dörfler // This needs to be documented 14329e9417d2Sbeveloper 14339e9417d2Sbeveloper server_get_live_nodes_request request; 14349c3b4706SAxel Dörfler request.team = BPrivate::current_team(); 14359e9417d2Sbeveloper 14369c3b4706SAxel Dörfler request.max_count = *_totalCount; 143734c72144SAxel Dörfler request.has_input = hasInput != NULL; 143834c72144SAxel Dörfler if (hasInput != NULL) { 143934c72144SAxel Dörfler // TODO: we should not make a flat copy of media_format 14409c3b4706SAxel Dörfler request.input_format = *hasInput; 144134c72144SAxel Dörfler } 144234c72144SAxel Dörfler request.has_output = hasOutput != NULL; 144334c72144SAxel Dörfler if (hasOutput != NULL) { 144434c72144SAxel Dörfler // TODO: we should not make a flat copy of media_format 14459c3b4706SAxel Dörfler request.output_format = *hasOutput; 144634c72144SAxel Dörfler } 144734c72144SAxel Dörfler request.has_name = name != NULL; 14489c3b4706SAxel Dörfler if (name != NULL) 14499c3b4706SAxel Dörfler strlcpy(request.name, name, sizeof(request.name)); 145034c72144SAxel Dörfler request.require_kinds = nodeKinds; 14519e9417d2Sbeveloper 14529c3b4706SAxel Dörfler server_get_live_nodes_reply reply; 14539c3b4706SAxel Dörfler status_t status = QueryServer(SERVER_GET_LIVE_NODES, &request, 14549c3b4706SAxel Dörfler sizeof(request), &reply, sizeof(reply)); 14559c3b4706SAxel Dörfler if (status != B_OK) { 14569c3b4706SAxel Dörfler ERROR("BMediaRoster::GetLiveNodes failed querying server: %s\n", 14579c3b4706SAxel Dörfler strerror(status)); 145834c72144SAxel Dörfler *_totalCount = 0; 14599c3b4706SAxel Dörfler return status; 14609e9417d2Sbeveloper } 14619e9417d2Sbeveloper 14629c3b4706SAxel Dörfler const live_node_info* info; 14639c3b4706SAxel Dörfler if (reply.area >= 0) 14649c3b4706SAxel Dörfler info = (live_node_info*)reply.address; 14659c3b4706SAxel Dörfler else 14669c3b4706SAxel Dörfler info = reply.live_info; 14679e9417d2Sbeveloper 14689c3b4706SAxel Dörfler for (int32 i = 0; i < reply.count; i++) 14699c3b4706SAxel Dörfler liveNodes[i] = info[i]; 14709c3b4706SAxel Dörfler 14719c3b4706SAxel Dörfler if (reply.area >= 0) 14729e9417d2Sbeveloper delete_area(reply.area); 147352a38012Sejakowatz 147434c72144SAxel Dörfler *_totalCount = reply.count; 14759e9417d2Sbeveloper return B_OK; 14769e9417d2Sbeveloper } 14779e9417d2Sbeveloper 147852a38012Sejakowatz 147952a38012Sejakowatz status_t 148052a38012Sejakowatz BMediaRoster::GetFreeInputsFor(const media_node& node, 148134c72144SAxel Dörfler media_input * out_free_inputs, int32 buf_num_inputs, 148234c72144SAxel Dörfler int32 * out_total_count, media_type filter_type) 148352a38012Sejakowatz { 14843620737cSbeveloper CALLED(); 14855ac4fbd7Sbeveloper if (IS_INVALID_NODE(node)) { 148634c72144SAxel Dörfler ERROR("BMediaRoster::GetFreeInputsFor: node %ld, port %ld invalid\n", 148734c72144SAxel Dörfler node.node, node.port); 14883620737cSbeveloper return B_MEDIA_BAD_NODE; 14895ac4fbd7Sbeveloper } 14905ac4fbd7Sbeveloper if ((node.kind & B_BUFFER_CONSUMER) == 0) { 149134c72144SAxel Dörfler ERROR("BMediaRoster::GetFreeInputsFor: node %ld, port %ld is not a " 149234c72144SAxel Dörfler "consumer\n", node.node, node.port); 14935ac4fbd7Sbeveloper return B_MEDIA_BAD_NODE; 14945ac4fbd7Sbeveloper } 14953620737cSbeveloper if (out_free_inputs == NULL || out_total_count == NULL) 14963620737cSbeveloper return B_BAD_VALUE; 14973620737cSbeveloper 149876669a29Sbeveloper List<media_input> list; 14993620737cSbeveloper media_input *input; 15003620737cSbeveloper status_t rv; 15013620737cSbeveloper 15021299bfb2Sbeveloper *out_total_count = 0; 15031299bfb2Sbeveloper 15048b04ffc1Sbeveloper rv = MediaRosterEx(this)->GetAllInputs(node, &list); 15053620737cSbeveloper if (B_OK != rv) 15063620737cSbeveloper return rv; 15073620737cSbeveloper 150834c72144SAxel Dörfler PRINT(4, "BMediaRoster::GetFreeInputsFor node %ld, max %ld, filter-type " 150934c72144SAxel Dörfler "%ld\n", node.node, buf_num_inputs, filter_type); 15105ac4fbd7Sbeveloper 151176669a29Sbeveloper int32 i; 1512b65a0ac5SJérôme Duval for (i = 0, list.Rewind(); list.GetNext(&input);) { 151334c72144SAxel Dörfler if (filter_type != B_MEDIA_UNKNOWN_TYPE 151434c72144SAxel Dörfler && filter_type != input->format.type) { 151534c72144SAxel Dörfler // media_type used, but doesn't match 151634c72144SAxel Dörfler continue; 151734c72144SAxel Dörfler } 151834c72144SAxel Dörfler if (input->source != media_source::null) { 151934c72144SAxel Dörfler // consumer source already connected 152034c72144SAxel Dörfler continue; 152134c72144SAxel Dörfler } 152234c72144SAxel Dörfler 15233620737cSbeveloper out_free_inputs[i] = *input; 15243620737cSbeveloper *out_total_count += 1; 15253620737cSbeveloper buf_num_inputs -= 1; 15265ac4fbd7Sbeveloper #if DEBUG >= 3 15275ac4fbd7Sbeveloper PRINT_OUTPUT(" input", out_free_inputs[i]); 15285ac4fbd7Sbeveloper #endif 15293620737cSbeveloper if (buf_num_inputs == 0) 15303620737cSbeveloper break; 1531b65a0ac5SJérôme Duval i++; 15323620737cSbeveloper } 15333620737cSbeveloper 15348b04ffc1Sbeveloper MediaRosterEx(this)->PublishInputs(node, &list); 15353620737cSbeveloper return B_OK; 153652a38012Sejakowatz } 153752a38012Sejakowatz 153852a38012Sejakowatz 153952a38012Sejakowatz status_t 154052a38012Sejakowatz BMediaRoster::GetConnectedInputsFor(const media_node& node, 154134c72144SAxel Dörfler media_input* out_active_inputs, int32 buf_num_inputs, 154252a38012Sejakowatz int32* out_total_count) 154352a38012Sejakowatz { 15443620737cSbeveloper CALLED(); 154540f36b03Sbeveloper if (IS_INVALID_NODE(node) || (node.kind & B_BUFFER_CONSUMER) == 0) 15463620737cSbeveloper return B_MEDIA_BAD_NODE; 15473620737cSbeveloper if (out_active_inputs == NULL || out_total_count == NULL) 15483620737cSbeveloper return B_BAD_VALUE; 15493620737cSbeveloper 155076669a29Sbeveloper List<media_input> list; 15513620737cSbeveloper media_input *input; 15523620737cSbeveloper status_t rv; 15533620737cSbeveloper 15541299bfb2Sbeveloper *out_total_count = 0; 15551299bfb2Sbeveloper 15568b04ffc1Sbeveloper rv = MediaRosterEx(this)->GetAllInputs(node, &list); 15573620737cSbeveloper if (B_OK != rv) 15583620737cSbeveloper return rv; 15593620737cSbeveloper 156034c72144SAxel Dörfler PRINT(4, "BMediaRoster::GetConnectedInputsFor node %ld, max %ld\n", 156134c72144SAxel Dörfler node.node, buf_num_inputs); 15625ac4fbd7Sbeveloper 156376669a29Sbeveloper int32 i; 1564b65a0ac5SJérôme Duval for (i = 0, list.Rewind(); list.GetNext(&input);) { 15653620737cSbeveloper if (input->source == media_source::null) 15663620737cSbeveloper continue; // consumer source not connected 15673620737cSbeveloper out_active_inputs[i] = *input; 15683620737cSbeveloper *out_total_count += 1; 15693620737cSbeveloper buf_num_inputs -= 1; 15705ac4fbd7Sbeveloper #if DEBUG >= 3 15715ac4fbd7Sbeveloper PRINT_OUTPUT(" input ", out_active_inputs[i]); 15725ac4fbd7Sbeveloper #endif 15733620737cSbeveloper if (buf_num_inputs == 0) 15743620737cSbeveloper break; 1575b65a0ac5SJérôme Duval i++; 15763620737cSbeveloper } 15773620737cSbeveloper 15788b04ffc1Sbeveloper MediaRosterEx(this)->PublishInputs(node, &list); 15793620737cSbeveloper return B_OK; 158052a38012Sejakowatz } 158152a38012Sejakowatz 158252a38012Sejakowatz 158352a38012Sejakowatz status_t 158434c72144SAxel Dörfler BMediaRoster::GetAllInputsFor(const media_node& node, media_input* out_inputs, 158534c72144SAxel Dörfler int32 buf_num_inputs, int32* out_total_count) 158652a38012Sejakowatz { 158752a38012Sejakowatz CALLED(); 158840f36b03Sbeveloper if (IS_INVALID_NODE(node) || (node.kind & B_BUFFER_CONSUMER) == 0) 158952a38012Sejakowatz return B_MEDIA_BAD_NODE; 159052a38012Sejakowatz if (out_inputs == NULL || out_total_count == NULL) 159152a38012Sejakowatz return B_BAD_VALUE; 159252a38012Sejakowatz 159376669a29Sbeveloper List<media_input> list; 15943620737cSbeveloper media_input *input; 159552a38012Sejakowatz status_t rv; 159652a38012Sejakowatz 15971299bfb2Sbeveloper *out_total_count = 0; 15981299bfb2Sbeveloper 15998b04ffc1Sbeveloper rv = MediaRosterEx(this)->GetAllInputs(node, &list); 16003620737cSbeveloper if (B_OK != rv) 16013620737cSbeveloper return rv; 16023620737cSbeveloper 160334c72144SAxel Dörfler PRINT(4, "BMediaRoster::GetAllInputsFor node %ld, max %ld\n", node.node, 160434c72144SAxel Dörfler buf_num_inputs); 16055ac4fbd7Sbeveloper 160676669a29Sbeveloper int32 i; 160776669a29Sbeveloper for (i = 0, list.Rewind(); list.GetNext(&input); i++) { 16083620737cSbeveloper out_inputs[i] = *input; 160952a38012Sejakowatz *out_total_count += 1; 16103620737cSbeveloper buf_num_inputs -= 1; 16115ac4fbd7Sbeveloper #if DEBUG >= 3 16125ac4fbd7Sbeveloper PRINT_OUTPUT(" input ", out_inputs[i]); 16135ac4fbd7Sbeveloper #endif 16143620737cSbeveloper if (buf_num_inputs == 0) 16153620737cSbeveloper break; 161652a38012Sejakowatz } 161752a38012Sejakowatz 16188b04ffc1Sbeveloper MediaRosterEx(this)->PublishInputs(node, &list); 16193620737cSbeveloper return B_OK; 162052a38012Sejakowatz } 162152a38012Sejakowatz 162252a38012Sejakowatz 162352a38012Sejakowatz status_t 162452a38012Sejakowatz BMediaRoster::GetFreeOutputsFor(const media_node& node, 162534c72144SAxel Dörfler media_output* out_free_outputs, int32 buf_num_outputs, 162634c72144SAxel Dörfler int32* out_total_count, media_type filter_type) 162752a38012Sejakowatz { 16283620737cSbeveloper CALLED(); 162940f36b03Sbeveloper if (IS_INVALID_NODE(node) || (node.kind & B_BUFFER_PRODUCER) == 0) 16303620737cSbeveloper return B_MEDIA_BAD_NODE; 16313620737cSbeveloper if (out_free_outputs == NULL || out_total_count == NULL) 16323620737cSbeveloper return B_BAD_VALUE; 16333620737cSbeveloper 163476669a29Sbeveloper List<media_output> list; 16353620737cSbeveloper media_output *output; 16363620737cSbeveloper status_t rv; 16373620737cSbeveloper 16381299bfb2Sbeveloper *out_total_count = 0; 16391299bfb2Sbeveloper 16408b04ffc1Sbeveloper rv = MediaRosterEx(this)->GetAllOutputs(node, &list); 16413620737cSbeveloper if (B_OK != rv) 16423620737cSbeveloper return rv; 16433620737cSbeveloper 164434c72144SAxel Dörfler PRINT(4, "BMediaRoster::GetFreeOutputsFor node %ld, max %ld, filter-type " 164534c72144SAxel Dörfler "%ld\n", node.node, buf_num_outputs, filter_type); 16465ac4fbd7Sbeveloper 164776669a29Sbeveloper int32 i; 1648b65a0ac5SJérôme Duval for (i = 0, list.Rewind(); list.GetNext(&output);) { 164934c72144SAxel Dörfler if (filter_type != B_MEDIA_UNKNOWN_TYPE 165034c72144SAxel Dörfler && filter_type != output->format.type) { 165134c72144SAxel Dörfler // media_type used, but doesn't match 165234c72144SAxel Dörfler continue; 165334c72144SAxel Dörfler } 165434c72144SAxel Dörfler if (output->destination != media_destination::null) { 165534c72144SAxel Dörfler // producer destination already connected 165634c72144SAxel Dörfler continue; 165734c72144SAxel Dörfler } 165834c72144SAxel Dörfler 16593620737cSbeveloper out_free_outputs[i] = *output; 16603620737cSbeveloper *out_total_count += 1; 16613620737cSbeveloper buf_num_outputs -= 1; 16625ac4fbd7Sbeveloper #if DEBUG >= 3 16635ac4fbd7Sbeveloper PRINT_OUTPUT(" output ", out_free_outputs[i]); 16645ac4fbd7Sbeveloper #endif 16653620737cSbeveloper if (buf_num_outputs == 0) 16663620737cSbeveloper break; 1667b65a0ac5SJérôme Duval i++; 16683620737cSbeveloper } 16693620737cSbeveloper 16708b04ffc1Sbeveloper MediaRosterEx(this)->PublishOutputs(node, &list); 16713620737cSbeveloper return B_OK; 167252a38012Sejakowatz } 167352a38012Sejakowatz 167452a38012Sejakowatz 167552a38012Sejakowatz status_t 167652a38012Sejakowatz BMediaRoster::GetConnectedOutputsFor(const media_node& node, 167734c72144SAxel Dörfler media_output* out_active_outputs, int32 buf_num_outputs, 167852a38012Sejakowatz int32* out_total_count) 167952a38012Sejakowatz { 16803620737cSbeveloper CALLED(); 168140f36b03Sbeveloper if (IS_INVALID_NODE(node) || (node.kind & B_BUFFER_PRODUCER) == 0) 16823620737cSbeveloper return B_MEDIA_BAD_NODE; 16833620737cSbeveloper if (out_active_outputs == NULL || out_total_count == NULL) 16843620737cSbeveloper return B_BAD_VALUE; 16853620737cSbeveloper 168676669a29Sbeveloper List<media_output> list; 16873620737cSbeveloper media_output *output; 16883620737cSbeveloper status_t rv; 16893620737cSbeveloper 16901299bfb2Sbeveloper *out_total_count = 0; 16911299bfb2Sbeveloper 16928b04ffc1Sbeveloper rv = MediaRosterEx(this)->GetAllOutputs(node, &list); 16933620737cSbeveloper if (B_OK != rv) 16943620737cSbeveloper return rv; 16953620737cSbeveloper 169634c72144SAxel Dörfler PRINT(4, "BMediaRoster::GetConnectedOutputsFor node %ld, max %ld\n", 169734c72144SAxel Dörfler node.node, buf_num_outputs); 16985ac4fbd7Sbeveloper 169976669a29Sbeveloper int32 i; 1700b65a0ac5SJérôme Duval for (i = 0, list.Rewind(); list.GetNext(&output);) { 170134c72144SAxel Dörfler if (output->destination == media_destination::null) { 170234c72144SAxel Dörfler // producer destination not connected 170334c72144SAxel Dörfler continue; 170434c72144SAxel Dörfler } 17053620737cSbeveloper out_active_outputs[i] = *output; 17063620737cSbeveloper *out_total_count += 1; 17073620737cSbeveloper buf_num_outputs -= 1; 17085ac4fbd7Sbeveloper #if DEBUG >= 3 17095ac4fbd7Sbeveloper PRINT_OUTPUT(" output ", out_active_outputs[i]); 17105ac4fbd7Sbeveloper #endif 17113620737cSbeveloper if (buf_num_outputs == 0) 17123620737cSbeveloper break; 1713b65a0ac5SJérôme Duval i++; 17143620737cSbeveloper } 17153620737cSbeveloper 17168b04ffc1Sbeveloper MediaRosterEx(this)->PublishOutputs(node, &list); 17173620737cSbeveloper return B_OK; 171852a38012Sejakowatz } 171952a38012Sejakowatz 172052a38012Sejakowatz 172152a38012Sejakowatz status_t 172252a38012Sejakowatz BMediaRoster::GetAllOutputsFor(const media_node& node, 172334c72144SAxel Dörfler media_output* out_outputs, int32 buf_num_outputs, int32* out_total_count) 172452a38012Sejakowatz { 172552a38012Sejakowatz CALLED(); 172640f36b03Sbeveloper if (IS_INVALID_NODE(node) || (node.kind & B_BUFFER_PRODUCER) == 0) 172752a38012Sejakowatz return B_MEDIA_BAD_NODE; 172852a38012Sejakowatz if (out_outputs == NULL || out_total_count == NULL) 172952a38012Sejakowatz return B_BAD_VALUE; 173052a38012Sejakowatz 173176669a29Sbeveloper List<media_output> list; 17323620737cSbeveloper media_output *output; 173352a38012Sejakowatz status_t rv; 173452a38012Sejakowatz 17351299bfb2Sbeveloper *out_total_count = 0; 17361299bfb2Sbeveloper 17378b04ffc1Sbeveloper rv = MediaRosterEx(this)->GetAllOutputs(node, &list); 17383620737cSbeveloper if (B_OK != rv) 17393620737cSbeveloper return rv; 17403620737cSbeveloper 174134c72144SAxel Dörfler PRINT(4, "BMediaRoster::GetAllOutputsFor node %ld, max %ld\n", node.node, 174234c72144SAxel Dörfler buf_num_outputs); 17435ac4fbd7Sbeveloper 174476669a29Sbeveloper int32 i; 174576669a29Sbeveloper for (i = 0, list.Rewind(); list.GetNext(&output); i++) { 17463620737cSbeveloper out_outputs[i] = *output; 174752a38012Sejakowatz *out_total_count += 1; 17483620737cSbeveloper buf_num_outputs -= 1; 17495ac4fbd7Sbeveloper #if DEBUG >= 3 17505ac4fbd7Sbeveloper PRINT_OUTPUT(" output ", out_outputs[i]); 17515ac4fbd7Sbeveloper #endif 17523620737cSbeveloper if (buf_num_outputs == 0) 17533620737cSbeveloper break; 175452a38012Sejakowatz } 175552a38012Sejakowatz 17568b04ffc1Sbeveloper MediaRosterEx(this)->PublishOutputs(node, &list); 17573620737cSbeveloper return B_OK; 175852a38012Sejakowatz } 175952a38012Sejakowatz 176052a38012Sejakowatz 176152a38012Sejakowatz status_t 176252a38012Sejakowatz BMediaRoster::StartWatching(const BMessenger& where) 176352a38012Sejakowatz { 1764eae26d3dSbeveloper CALLED(); 1765eae26d3dSbeveloper if (!where.IsValid()) { 17665ac4fbd7Sbeveloper ERROR("BMediaRoster::StartWatching: messenger invalid!\n"); 1767eae26d3dSbeveloper return B_BAD_VALUE; 1768eae26d3dSbeveloper } 176934c72144SAxel Dörfler return BPrivate::media::notifications::Register(where, media_node::null, 177034c72144SAxel Dörfler B_MEDIA_WILDCARD); 177152a38012Sejakowatz } 177252a38012Sejakowatz 177352a38012Sejakowatz 177452a38012Sejakowatz status_t 177534c72144SAxel Dörfler BMediaRoster::StartWatching(const BMessenger & where, int32 notificationType) 177652a38012Sejakowatz { 1777eae26d3dSbeveloper CALLED(); 1778eae26d3dSbeveloper if (!where.IsValid()) { 17795ac4fbd7Sbeveloper ERROR("BMediaRoster::StartWatching: messenger invalid!\n"); 1780eae26d3dSbeveloper return B_BAD_VALUE; 1781eae26d3dSbeveloper } 178234c72144SAxel Dörfler if (!BPrivate::media::notifications::IsValidNotificationRequest(false, 178334c72144SAxel Dörfler notificationType)) { 17845ac4fbd7Sbeveloper ERROR("BMediaRoster::StartWatching: notificationType invalid!\n"); 1785eae26d3dSbeveloper return B_BAD_VALUE; 1786eae26d3dSbeveloper } 178734c72144SAxel Dörfler return BPrivate::media::notifications::Register(where, media_node::null, 178834c72144SAxel Dörfler notificationType); 178952a38012Sejakowatz } 179052a38012Sejakowatz 179152a38012Sejakowatz 179252a38012Sejakowatz status_t 179334c72144SAxel Dörfler BMediaRoster::StartWatching(const BMessenger& where, const media_node& node, 179452a38012Sejakowatz int32 notificationType) 179552a38012Sejakowatz { 1796eae26d3dSbeveloper CALLED(); 1797eae26d3dSbeveloper if (!where.IsValid()) { 17985ac4fbd7Sbeveloper ERROR("BMediaRoster::StartWatching: messenger invalid!\n"); 1799eae26d3dSbeveloper return B_BAD_VALUE; 1800eae26d3dSbeveloper } 180140f36b03Sbeveloper if (IS_INVALID_NODE(node)) { 18025ac4fbd7Sbeveloper ERROR("BMediaRoster::StartWatching: node invalid!\n"); 1803eae26d3dSbeveloper return B_MEDIA_BAD_NODE; 1804eae26d3dSbeveloper } 180534c72144SAxel Dörfler if (!BPrivate::media::notifications::IsValidNotificationRequest(true, 180634c72144SAxel Dörfler notificationType)) { 18075ac4fbd7Sbeveloper ERROR("BMediaRoster::StartWatching: notificationType invalid!\n"); 1808eae26d3dSbeveloper return B_BAD_VALUE; 1809eae26d3dSbeveloper } 181034c72144SAxel Dörfler return BPrivate::media::notifications::Register(where, node, 181134c72144SAxel Dörfler notificationType); 181252a38012Sejakowatz } 181352a38012Sejakowatz 181452a38012Sejakowatz 181552a38012Sejakowatz status_t 181652a38012Sejakowatz BMediaRoster::StopWatching(const BMessenger& where) 181752a38012Sejakowatz { 1818eae26d3dSbeveloper CALLED(); 1819eae26d3dSbeveloper // messenger may already be invalid, so we don't check this 182034c72144SAxel Dörfler return BPrivate::media::notifications::Unregister(where, media_node::null, 182134c72144SAxel Dörfler B_MEDIA_WILDCARD); 182252a38012Sejakowatz } 182352a38012Sejakowatz 182452a38012Sejakowatz 182552a38012Sejakowatz status_t 182634c72144SAxel Dörfler BMediaRoster::StopWatching(const BMessenger& where, int32 notificationType) 182752a38012Sejakowatz { 1828eae26d3dSbeveloper CALLED(); 1829eae26d3dSbeveloper // messenger may already be invalid, so we don't check this 183034c72144SAxel Dörfler if (!BPrivate::media::notifications::IsValidNotificationRequest(false, 183134c72144SAxel Dörfler notificationType)) { 18325ac4fbd7Sbeveloper ERROR("BMediaRoster::StopWatching: notificationType invalid!\n"); 1833eae26d3dSbeveloper return B_BAD_VALUE; 1834eae26d3dSbeveloper } 183534c72144SAxel Dörfler return BPrivate::media::notifications::Unregister(where, media_node::null, 183634c72144SAxel Dörfler notificationType); 183752a38012Sejakowatz } 183852a38012Sejakowatz 183952a38012Sejakowatz 184052a38012Sejakowatz status_t 184134c72144SAxel Dörfler BMediaRoster::StopWatching(const BMessenger& where, const media_node& node, 184252a38012Sejakowatz int32 notificationType) 184352a38012Sejakowatz { 1844eae26d3dSbeveloper CALLED(); 1845eae26d3dSbeveloper // messenger may already be invalid, so we don't check this 184640f36b03Sbeveloper if (IS_INVALID_NODE(node)) { 18475ac4fbd7Sbeveloper ERROR("BMediaRoster::StopWatching: node invalid!\n"); 1848eae26d3dSbeveloper return B_MEDIA_BAD_NODE; 1849eae26d3dSbeveloper } 185034c72144SAxel Dörfler if (!BPrivate::media::notifications::IsValidNotificationRequest(true, 185134c72144SAxel Dörfler notificationType)) { 18525ac4fbd7Sbeveloper ERROR("BMediaRoster::StopWatching: notificationType invalid!\n"); 1853eae26d3dSbeveloper return B_BAD_VALUE; 1854eae26d3dSbeveloper } 185534c72144SAxel Dörfler return BPrivate::media::notifications::Unregister(where, node, 185634c72144SAxel Dörfler notificationType); 185752a38012Sejakowatz } 185852a38012Sejakowatz 185952a38012Sejakowatz 186052a38012Sejakowatz status_t 186152a38012Sejakowatz BMediaRoster::RegisterNode(BMediaNode* node) 186252a38012Sejakowatz { 186354187cc6Sbeveloper CALLED(); 186454187cc6Sbeveloper // addon-id = -1 (unused), addon-flavor-id = 0 (unused, too) 186554187cc6Sbeveloper return MediaRosterEx(this)->RegisterNode(node, -1, 0); 186654187cc6Sbeveloper } 186754187cc6Sbeveloper 186854187cc6Sbeveloper 186954187cc6Sbeveloper status_t 18709c3b4706SAxel Dörfler BMediaRosterEx::RegisterNode(BMediaNode* node, media_addon_id addOnID, 18719dec2310SAxel Dörfler int32 flavorID) 187254187cc6Sbeveloper { 187352a38012Sejakowatz CALLED(); 187452a38012Sejakowatz if (node == NULL) 187552a38012Sejakowatz return B_BAD_VALUE; 187652a38012Sejakowatz 187754187cc6Sbeveloper // some sanity check 187854187cc6Sbeveloper // I'm not sure if the media kit warrants to call BMediaNode::AddOn() here. 187954187cc6Sbeveloper // Perhaps we don't need it. 18809dec2310SAxel Dörfler DEBUG_ONLY( 18819dec2310SAxel Dörfler int32 testFlavorID; 18829dec2310SAxel Dörfler BMediaAddOn* addon = node->AddOn(&testFlavorID); 18839dec2310SAxel Dörfler 18849c3b4706SAxel Dörfler ASSERT(addOnID == addon != NULL ? addon->AddonID() : -1); 18859dec2310SAxel Dörfler ASSERT(flavorID == testFlavorID); 18869dec2310SAxel Dörfler ); 188752a38012Sejakowatz 18889e9417d2Sbeveloper server_register_node_request request; 18899e9417d2Sbeveloper server_register_node_reply reply; 18909e9417d2Sbeveloper 18919c3b4706SAxel Dörfler request.add_on_id = addOnID; 18929c3b4706SAxel Dörfler request.flavor_id = flavorID; 18939e9417d2Sbeveloper strcpy(request.name, node->Name()); 18949e9417d2Sbeveloper request.kinds = node->Kinds(); 18959e9417d2Sbeveloper request.port = node->ControlPort(); 18969dec2310SAxel Dörfler request.team = BPrivate::current_team(); 18979e9417d2Sbeveloper 189834c72144SAxel Dörfler TRACE("BMediaRoster::RegisterNode: sending SERVER_REGISTER_NODE: port " 189934c72144SAxel Dörfler "%ld, kinds 0x%Lx, team %ld, name '%s'\n", request.port, request.kinds, 190034c72144SAxel Dörfler request.team, request.name); 19011299bfb2Sbeveloper 19029c3b4706SAxel Dörfler status_t status = QueryServer(SERVER_REGISTER_NODE, &request, 19039c3b4706SAxel Dörfler sizeof(request), &reply, sizeof(reply)); 19049c3b4706SAxel Dörfler if (status != B_OK) { 19059c3b4706SAxel Dörfler ERROR("BMediaRoster::RegisterNode: failed to register node %s: %s\n", 19069c3b4706SAxel Dörfler node->Name(), strerror(status)); 19079c3b4706SAxel Dörfler return status; 19089e9417d2Sbeveloper } 19099e9417d2Sbeveloper 191034c72144SAxel Dörfler TRACE("BMediaRoster::RegisterNode: QueryServer SERVER_REGISTER_NODE " 191134c72144SAxel Dörfler "finished\n"); 19124295907bSbeveloper 19138b04ffc1Sbeveloper // we are a friend class of BMediaNode and initialize this member variable 19149dec2310SAxel Dörfler node->fNodeID = reply.node_id; 19159dec2310SAxel Dörfler ASSERT(reply.node_id == node->Node().node); 19169dec2310SAxel Dörfler ASSERT(reply.node_id == node->ID()); 19179e9417d2Sbeveloper 19189e9417d2Sbeveloper // call the callback 19199e9417d2Sbeveloper node->NodeRegistered(); 19203620737cSbeveloper 19214295907bSbeveloper TRACE("BMediaRoster::RegisterNode: NodeRegistered callback finished\n"); 19224295907bSbeveloper 192334c72144SAxel Dörfler // if the BMediaNode also inherits from BTimeSource, we need to call 192434c72144SAxel Dörfler // BTimeSource::FinishCreate() 19259c3b4706SAxel Dörfler if ((node->Kinds() & B_TIME_SOURCE) != 0) { 19269c3b4706SAxel Dörfler if (BTimeSource* timeSource = dynamic_cast<BTimeSource*>(node)) 19279c3b4706SAxel Dörfler timeSource->FinishCreate(); 19280e21b167Sbeveloper } 19290e21b167Sbeveloper 19304295907bSbeveloper TRACE("BMediaRoster::RegisterNode: publishing inputs/outputs\n"); 19314295907bSbeveloper 19323620737cSbeveloper // register existing inputs and outputs with the 19333620737cSbeveloper // media_server, this allows GetLiveNodes() to work 19343620737cSbeveloper // with created, but unconnected nodes. 19354d2d96e0Sbeveloper // The node control loop might not be running, or might deadlock 19364d2d96e0Sbeveloper // if we send a message and wait for a reply here. 19374d2d96e0Sbeveloper // We have a pointer to the node, and thus call the functions directly 19384295907bSbeveloper 19399c3b4706SAxel Dörfler if ((node->Kinds() & B_BUFFER_PRODUCER) != 0) { 19409c3b4706SAxel Dörfler if (BBufferProducer* producer = dynamic_cast<BBufferProducer*>(node)) { 1941359ac306Sbeveloper List<media_output> list; 19429c3b4706SAxel Dörfler if (GetAllOutputs(producer, &list) == B_OK) 1943359ac306Sbeveloper PublishOutputs(node->Node(), &list); 194421871f38Sbeveloper } 19454d2d96e0Sbeveloper } 19469dec2310SAxel Dörfler if ((node->Kinds() & B_BUFFER_CONSUMER) != 0) { 19479c3b4706SAxel Dörfler if (BBufferConsumer* consumer = dynamic_cast<BBufferConsumer*>(node)) { 1948359ac306Sbeveloper List<media_input> list; 19499dec2310SAxel Dörfler if (GetAllInputs(consumer, &list) == B_OK) 1950359ac306Sbeveloper PublishInputs(node->Node(), &list); 19513620737cSbeveloper } 19524d2d96e0Sbeveloper } 195321871f38Sbeveloper 19544295907bSbeveloper TRACE("BMediaRoster::RegisterNode: sending NodesCreated\n"); 19554295907bSbeveloper 19569dec2310SAxel Dörfler BPrivate::media::notifications::NodesCreated(&reply.node_id, 1); 19574295907bSbeveloper 19584295907bSbeveloper TRACE("BMediaRoster::RegisterNode: finished\n"); 19594295907bSbeveloper 1960570f7d04Sbeveloper /* 19619c3b4706SAxel Dörfler TRACE("BMediaRoster::RegisterNode: registered node name '%s', id %ld, 19629c3b4706SAxel Dörfler addon %ld, flavor %ld\n", node->Name(), node->ID(), addOnID, flavorID); 1963570f7d04Sbeveloper TRACE("BMediaRoster::RegisterNode: node this %p\n", node); 19649c3b4706SAxel Dörfler TRACE("BMediaRoster::RegisterNode: node fConsumerThis %p\n", 19659c3b4706SAxel Dörfler node->fConsumerThis); 19669c3b4706SAxel Dörfler TRACE("BMediaRoster::RegisterNode: node fProducerThis %p\n", 19679c3b4706SAxel Dörfler node->fProducerThis); 19689c3b4706SAxel Dörfler TRACE("BMediaRoster::RegisterNode: node fFileInterfaceThis %p\n", 19699c3b4706SAxel Dörfler node->fFileInterfaceThis); 19709c3b4706SAxel Dörfler TRACE("BMediaRoster::RegisterNode: node fControllableThis %p\n", 19719c3b4706SAxel Dörfler node->fControllableThis); 19729c3b4706SAxel Dörfler TRACE("BMediaRoster::RegisterNode: node fTimeSourceThis %p\n", 19739c3b4706SAxel Dörfler node->fTimeSourceThis); 1974570f7d04Sbeveloper */ 19759e9417d2Sbeveloper return B_OK; 197652a38012Sejakowatz } 197752a38012Sejakowatz 197852a38012Sejakowatz 197952a38012Sejakowatz status_t 198052a38012Sejakowatz BMediaRoster::UnregisterNode(BMediaNode* node) 198152a38012Sejakowatz { 19829e9417d2Sbeveloper CALLED(); 19839e9417d2Sbeveloper if (node == NULL) 19849e9417d2Sbeveloper return B_BAD_VALUE; 19859e9417d2Sbeveloper 198660f15390Sbeveloper TRACE("BMediaRoster::UnregisterNode %ld (%p)\n", node->ID(), node); 198760f15390Sbeveloper 198829bb91d6SAxel Dörfler if ((node->fKinds & NODE_KIND_NO_REFCOUNTING) !=0) { 198934c72144SAxel Dörfler TRACE("BMediaRoster::UnregisterNode, trying to unregister reference " 199034c72144SAxel Dörfler "counting disabled timesource, node %ld, port %ld, team %ld\n", 19919dec2310SAxel Dörfler node->ID(), node->ControlPort(), BPrivate::current_team()); 199286bce45bSbeveloper return B_OK; 199386bce45bSbeveloper } 19948b04ffc1Sbeveloper if (node->ID() == NODE_UNREGISTERED_ID) { 199534c72144SAxel Dörfler PRINT(1, "Warning: BMediaRoster::UnregisterNode: node id %ld, name " 199634c72144SAxel Dörfler "'%s' already unregistered\n", node->ID(), node->Name()); 19979e9417d2Sbeveloper return B_OK; 19989e9417d2Sbeveloper } 199954187cc6Sbeveloper if (node->fRefCount != 0) { 200034c72144SAxel Dörfler PRINT(1, "Warning: BMediaRoster::UnregisterNode: node id %ld, name " 200134c72144SAxel Dörfler "'%s' has local reference count of %ld\n", node->ID(), node->Name(), 200234c72144SAxel Dörfler node->fRefCount); 200354187cc6Sbeveloper // no return here, we continue and unregister! 200454187cc6Sbeveloper } 200554187cc6Sbeveloper 200634c72144SAxel Dörfler // Calling BMediaAddOn::GetConfigurationFor(BMediaNode *node, 200734c72144SAxel Dörfler // BMessage *config) if this node was instanciated by an add-on needs to 200834c72144SAxel Dörfler // be done *somewhere* 200954187cc6Sbeveloper // We can't do it here because it is already to late (destructor of the node 201054187cc6Sbeveloper // might have been called). 20119e9417d2Sbeveloper 20129e9417d2Sbeveloper server_unregister_node_request request; 20139dec2310SAxel Dörfler request.node_id = node->ID(); 20149dec2310SAxel Dörfler request.team = BPrivate::current_team(); 20159e9417d2Sbeveloper 20161299bfb2Sbeveloper // send a notification 20179dec2310SAxel Dörfler BPrivate::media::notifications::NodesDeleted(&request.node_id, 1); 20181299bfb2Sbeveloper 201929bb91d6SAxel Dörfler server_unregister_node_reply reply; 202029bb91d6SAxel Dörfler status_t status = QueryServer(SERVER_UNREGISTER_NODE, &request, 202129bb91d6SAxel Dörfler sizeof(request), &reply, sizeof(reply)); 202229bb91d6SAxel Dörfler if (status != B_OK) { 202334c72144SAxel Dörfler ERROR("BMediaRoster::UnregisterNode: failed to unregister node id %ld, " 202429bb91d6SAxel Dörfler "name '%s': %s\n", node->ID(), node->Name(), strerror(status)); 202529bb91d6SAxel Dörfler return status; 20269e9417d2Sbeveloper } 20279e9417d2Sbeveloper 20289c3b4706SAxel Dörfler if (reply.add_on_id != -1) { 202929bb91d6SAxel Dörfler // TODO: this doesn't look right 203029bb91d6SAxel Dörfler // Small problem here, we can't use DormantNodeManager::PutAddOn(), as 203134c72144SAxel Dörfler // UnregisterNode() is called by a dormant node itself (by the 203234c72144SAxel Dörfler // destructor). 203354187cc6Sbeveloper // The add-on that contains the node needs to remain in memory until the 203454187cc6Sbeveloper // destructor execution is finished. 203529bb91d6SAxel Dörfler // DormantNodeManager::PutAddOnDelayed() will delay unloading. 20369c3b4706SAxel Dörfler gDormantNodeManager->PutAddOnDelayed(reply.add_on_id); 2037cf4e2277Sbeveloper 203829bb91d6SAxel Dörfler status = MediaRosterEx(this)->DecrementAddonFlavorInstancesCount( 20399c3b4706SAxel Dörfler reply.add_on_id, reply.flavor_id); 204029bb91d6SAxel Dörfler if (status != B_OK) { 204134c72144SAxel Dörfler ERROR("BMediaRoster::UnregisterNode: " 204234c72144SAxel Dörfler "DecrementAddonFlavorInstancesCount() failed\n"); 204354187cc6Sbeveloper // this is really a problem, but we can't fail now 204454187cc6Sbeveloper } 20458b04ffc1Sbeveloper } 20469e9417d2Sbeveloper 20471299bfb2Sbeveloper // we are a friend class of BMediaNode and invalidate this member variable 20488b04ffc1Sbeveloper node->fNodeID = NODE_UNREGISTERED_ID; 20499e9417d2Sbeveloper 20509e9417d2Sbeveloper return B_OK; 205152a38012Sejakowatz } 205252a38012Sejakowatz 205352a38012Sejakowatz 205434c72144SAxel Dörfler //! Thread safe for multiple calls to Roster() 205552a38012Sejakowatz /*static*/ BMediaRoster* 205652a38012Sejakowatz BMediaRoster::Roster(status_t* out_error) 205752a38012Sejakowatz { 205852a38012Sejakowatz static BLocker locker("BMediaRoster::Roster locker"); 205952a38012Sejakowatz locker.Lock(); 20608496c38aSbeveloper if (out_error) 20618496c38aSbeveloper *out_error = B_OK; 20629def3bf7SStephan Aßmus if (sDefaultInstance == NULL) { 20638496c38aSbeveloper status_t err; 20649def3bf7SStephan Aßmus sDefaultInstance = new (std::nothrow) BMediaRosterEx(&err); 20659def3bf7SStephan Aßmus if (sDefaultInstance == NULL) 2066a715f908SStephan Aßmus err = B_NO_MEMORY; 2067a715f908SStephan Aßmus else if (err != B_OK) { 20689def3bf7SStephan Aßmus if (sDefaultInstance) { 20699def3bf7SStephan Aßmus sDefaultInstance->Lock(); 20709def3bf7SStephan Aßmus sDefaultInstance->Quit(); 20719def3bf7SStephan Aßmus sDefaultInstance = NULL; 2072dcfb6bfcSJérôme Duval } 20738496c38aSbeveloper if (out_error) 20748496c38aSbeveloper *out_error = err; 20758496c38aSbeveloper } 207652a38012Sejakowatz } 207752a38012Sejakowatz locker.Unlock(); 20789def3bf7SStephan Aßmus return sDefaultInstance; 207952a38012Sejakowatz } 208052a38012Sejakowatz 208152a38012Sejakowatz 208252a38012Sejakowatz /*static*/ BMediaRoster* 208352a38012Sejakowatz BMediaRoster::CurrentRoster() 208452a38012Sejakowatz { 20859def3bf7SStephan Aßmus return sDefaultInstance; 208652a38012Sejakowatz } 208752a38012Sejakowatz 208852a38012Sejakowatz 208952a38012Sejakowatz status_t 209034c72144SAxel Dörfler BMediaRoster::SetTimeSourceFor(media_node_id node, media_node_id time_source) 209152a38012Sejakowatz { 2092aac800c2Sbeveloper CALLED(); 209340f36b03Sbeveloper if (IS_INVALID_NODEID(node) || IS_INVALID_NODEID(time_source)) 2094aac800c2Sbeveloper return B_BAD_VALUE; 2095aac800c2Sbeveloper 2096aac800c2Sbeveloper media_node clone; 2097aac800c2Sbeveloper status_t rv, result; 2098aac800c2Sbeveloper 209934c72144SAxel Dörfler TRACE("BMediaRoster::SetTimeSourceFor: node %ld will be assigned time " 210034c72144SAxel Dörfler "source %ld\n", node, time_source); 210134c72144SAxel Dörfler TRACE("BMediaRoster::SetTimeSourceFor: node %ld time source %ld enter\n", 210234c72144SAxel Dörfler node, time_source); 21035917dd5bSbeveloper 210486bce45bSbeveloper // we need to get a clone of the node to have a port id 2105aac800c2Sbeveloper rv = GetNodeFor(node, &clone); 2106aac800c2Sbeveloper if (rv != B_OK) { 210734c72144SAxel Dörfler ERROR("BMediaRoster::SetTimeSourceFor, GetNodeFor failed, node id " 210834c72144SAxel Dörfler "%ld\n", node); 210952a38012Sejakowatz return B_ERROR; 211052a38012Sejakowatz } 211152a38012Sejakowatz 211286bce45bSbeveloper // we just send the request to set time_source-id as timesource to the node, 211386bce45bSbeveloper // the NODE_SET_TIMESOURCE handler code will do the real assignment 2114aac800c2Sbeveloper result = B_OK; 2115aac800c2Sbeveloper node_set_timesource_command cmd; 2116aac800c2Sbeveloper cmd.timesource_id = time_source; 2117aac800c2Sbeveloper rv = SendToPort(clone.port, NODE_SET_TIMESOURCE, &cmd, sizeof(cmd)); 2118aac800c2Sbeveloper if (rv != B_OK) { 211934c72144SAxel Dörfler ERROR("BMediaRoster::SetTimeSourceFor, sending NODE_SET_TIMESOURCE " 212034c72144SAxel Dörfler "failed, node id %ld\n", node); 2121aac800c2Sbeveloper result = B_ERROR; 2122aac800c2Sbeveloper } 2123aac800c2Sbeveloper 212460f15390Sbeveloper // we release the clone 2125aac800c2Sbeveloper rv = ReleaseNode(clone); 2126aac800c2Sbeveloper if (rv != B_OK) { 212734c72144SAxel Dörfler ERROR("BMediaRoster::SetTimeSourceFor, ReleaseNode failed, node id " 212834c72144SAxel Dörfler "%ld\n", node); 2129aac800c2Sbeveloper result = B_ERROR; 2130aac800c2Sbeveloper } 2131aac800c2Sbeveloper 213234c72144SAxel Dörfler TRACE("BMediaRoster::SetTimeSourceFor: node %ld time source %ld leave\n", 213334c72144SAxel Dörfler node, time_source); 21345917dd5bSbeveloper 2135aac800c2Sbeveloper return result; 2136aac800c2Sbeveloper } 2137aac800c2Sbeveloper 213852a38012Sejakowatz 213952a38012Sejakowatz status_t 214034c72144SAxel Dörfler BMediaRoster::GetParameterWebFor(const media_node& node, BParameterWeb** _web) 214152a38012Sejakowatz { 214228ad138aSbeveloper CALLED(); 214334c72144SAxel Dörfler if (_web == NULL) 214428ad138aSbeveloper return B_BAD_VALUE; 214528ad138aSbeveloper if (IS_INVALID_NODE(node)) 214628ad138aSbeveloper return B_MEDIA_BAD_NODE; 214728ad138aSbeveloper if ((node.kind & B_CONTROLLABLE) == 0) 214828ad138aSbeveloper return B_MEDIA_BAD_NODE; 214928ad138aSbeveloper 215028ad138aSbeveloper controllable_get_parameter_web_request request; 215128ad138aSbeveloper controllable_get_parameter_web_reply reply; 215234c72144SAxel Dörfler int32 requestsize[] = {B_PAGE_SIZE, 4 * B_PAGE_SIZE, 16 * B_PAGE_SIZE, 215334c72144SAxel Dörfler 64 * B_PAGE_SIZE, 128 * B_PAGE_SIZE, 256 * B_PAGE_SIZE, 0}; 215428ad138aSbeveloper int32 size; 215528ad138aSbeveloper 215634c72144SAxel Dörfler // TODO: it might be better to query the node for the (current) parameter 215734c72144SAxel Dörfler // size first 215828ad138aSbeveloper for (int i = 0; (size = requestsize[i]) != 0; i++) { 215928ad138aSbeveloper status_t rv; 216028ad138aSbeveloper area_id area; 216128ad138aSbeveloper void *data; 216234c72144SAxel Dörfler area = create_area("parameter web data", &data, B_ANY_ADDRESS, size, 216334c72144SAxel Dörfler B_NO_LOCK, B_READ_AREA | B_WRITE_AREA); 216428ad138aSbeveloper if (area < B_OK) { 216534c72144SAxel Dörfler ERROR("BMediaRoster::GetParameterWebFor couldn't create area of " 216634c72144SAxel Dörfler "size %ld\n", size); 216728ad138aSbeveloper return B_ERROR; 216828ad138aSbeveloper } 216934c72144SAxel Dörfler request.max_size = size; 217028ad138aSbeveloper request.area = area; 217134c72144SAxel Dörfler rv = QueryPort(node.port, CONTROLLABLE_GET_PARAMETER_WEB, &request, 217234c72144SAxel Dörfler sizeof(request), &reply, sizeof(reply)); 217328ad138aSbeveloper if (rv != B_OK) { 217434c72144SAxel Dörfler ERROR("BMediaRoster::GetParameterWebFor " 217534c72144SAxel Dörfler "CONTROLLABLE_GET_PARAMETER_WEB failed\n"); 217628ad138aSbeveloper delete_area(area); 217728ad138aSbeveloper return B_ERROR; 217828ad138aSbeveloper } 217928ad138aSbeveloper if (reply.size == 0) { 218028ad138aSbeveloper // no parameter web available 218134c72144SAxel Dörfler // TODO: should we return an error? 218234c72144SAxel Dörfler ERROR("BMediaRoster::GetParameterWebFor node %ld has no parameter " 218334c72144SAxel Dörfler "web\n", node.node); 218434c72144SAxel Dörfler *_web = new (std::nothrow) BParameterWeb(); 218528ad138aSbeveloper delete_area(area); 218634c72144SAxel Dörfler return *_web != NULL ? B_OK : B_NO_MEMORY; 218752a38012Sejakowatz } 218828ad138aSbeveloper if (reply.size > 0) { 218928ad138aSbeveloper // we got a flattened parameter web! 219034c72144SAxel Dörfler *_web = new (std::nothrow) BParameterWeb(); 219134c72144SAxel Dörfler if (*_web == NULL) 2192a715f908SStephan Aßmus rv = B_NO_MEMORY; 2193a715f908SStephan Aßmus else { 219434c72144SAxel Dörfler printf("BMediaRoster::GetParameterWebFor Unflattening %ld " 219534c72144SAxel Dörfler "bytes, 0x%08lx, 0x%08lx, 0x%08lx, 0x%08lx\n", 219634c72144SAxel Dörfler reply.size, ((uint32*)data)[0], ((uint32*)data)[1], 219734c72144SAxel Dörfler ((uint32*)data)[2], ((uint32*)data)[3]); 219828ad138aSbeveloper 219934c72144SAxel Dörfler rv = (*_web)->Unflatten(reply.code, data, reply.size); 2200a715f908SStephan Aßmus } 220128ad138aSbeveloper if (rv != B_OK) { 220234c72144SAxel Dörfler ERROR("BMediaRoster::GetParameterWebFor Unflatten failed, " 220334c72144SAxel Dörfler "%s\n", strerror(rv)); 220434c72144SAxel Dörfler delete *_web; 220528ad138aSbeveloper } 220628ad138aSbeveloper delete_area(area); 2207a715f908SStephan Aßmus return rv; 220828ad138aSbeveloper } 220928ad138aSbeveloper delete_area(area); 221028ad138aSbeveloper ASSERT(reply.size == -1); 221128ad138aSbeveloper // parameter web data was too large 221228ad138aSbeveloper // loop and try a larger size 221328ad138aSbeveloper } 221434c72144SAxel Dörfler ERROR("BMediaRoster::GetParameterWebFor node %ld has no parameter web " 221534c72144SAxel Dörfler "larger than %ld\n", node.node, size); 221628ad138aSbeveloper return B_ERROR; 221728ad138aSbeveloper } 221852a38012Sejakowatz 221952a38012Sejakowatz 222052a38012Sejakowatz status_t 222134c72144SAxel Dörfler BMediaRoster::StartControlPanel(const media_node& node, BMessenger* _messenger) 222252a38012Sejakowatz { 2223999cd0acSMaurice Kalinowski CALLED(); 2224999cd0acSMaurice Kalinowski 2225999cd0acSMaurice Kalinowski controllable_start_control_panel_request request; 2226999cd0acSMaurice Kalinowski controllable_start_control_panel_reply reply; 2227999cd0acSMaurice Kalinowski 2228999cd0acSMaurice Kalinowski request.node = node; 2229999cd0acSMaurice Kalinowski 2230999cd0acSMaurice Kalinowski status_t rv; 223134c72144SAxel Dörfler rv = QueryPort(node.port, CONTROLLABLE_START_CONTROL_PANEL, &request, 223234c72144SAxel Dörfler sizeof(request), &reply, sizeof(reply)); 2233999cd0acSMaurice Kalinowski if (rv != B_OK) 2234999cd0acSMaurice Kalinowski return rv; 2235999cd0acSMaurice Kalinowski 223634c72144SAxel Dörfler if (reply.team != -1 && _messenger != NULL) 223734c72144SAxel Dörfler *_messenger = BMessenger(NULL, reply.team); 2238999cd0acSMaurice Kalinowski 2239999cd0acSMaurice Kalinowski return B_OK; 224052a38012Sejakowatz } 224152a38012Sejakowatz 224252a38012Sejakowatz 224352a38012Sejakowatz status_t 224434c72144SAxel Dörfler BMediaRoster::GetDormantNodes(dormant_node_info* _info, int32* _count, 224534c72144SAxel Dörfler const media_format* hasInput, const media_format* hasOutput, 224634c72144SAxel Dörfler const char* name, uint64 requireKinds, uint64 denyKinds) 224752a38012Sejakowatz { 224852a38012Sejakowatz CALLED(); 224934c72144SAxel Dörfler if (_info == NULL || _count == NULL || *_count <= 0) 225052a38012Sejakowatz return B_BAD_VALUE; 225152a38012Sejakowatz 2252*e4c87231SAxel Dörfler server_get_dormant_nodes_request request; 2253*e4c87231SAxel Dörfler request.max_count = *_count; 2254*e4c87231SAxel Dörfler request.has_input = hasInput != NULL; 225534c72144SAxel Dörfler if (hasInput != NULL) { 225634c72144SAxel Dörfler // TODO: we should not make a flat copy of media_format 2257*e4c87231SAxel Dörfler request.input_format = *hasInput; 225834c72144SAxel Dörfler } 2259*e4c87231SAxel Dörfler request.has_output = hasOutput != NULL; 226034c72144SAxel Dörfler if (hasOutput != NULL) { 226134c72144SAxel Dörfler // TODO: we should not make a flat copy of media_format 2262*e4c87231SAxel Dörfler request.output_format = *hasOutput; 226334c72144SAxel Dörfler } 226434c72144SAxel Dörfler 2265*e4c87231SAxel Dörfler request.has_name = name != NULL; 2266*e4c87231SAxel Dörfler if (name != NULL) 2267*e4c87231SAxel Dörfler strlcpy(request.name, name, sizeof(request.name)); 226852a38012Sejakowatz 2269*e4c87231SAxel Dörfler request.require_kinds = requireKinds; 2270*e4c87231SAxel Dörfler request.deny_kinds = denyKinds; 2271*e4c87231SAxel Dörfler request.reply_port = gPortPool->GetPort(); 227252a38012Sejakowatz 2273*e4c87231SAxel Dörfler server_get_dormant_nodes_reply reply; 2274*e4c87231SAxel Dörfler status_t status = QueryServer(SERVER_GET_DORMANT_NODES, &request, 2275*e4c87231SAxel Dörfler sizeof(request), &reply, sizeof(reply)); 2276*e4c87231SAxel Dörfler if (status != B_OK) { 2277*e4c87231SAxel Dörfler gPortPool->PutPort(request.reply_port); 2278*e4c87231SAxel Dörfler return status; 227952a38012Sejakowatz } 228052a38012Sejakowatz 228134c72144SAxel Dörfler *_count = reply.count; 228252a38012Sejakowatz 2283*e4c87231SAxel Dörfler if (reply.count > 0) { 2284*e4c87231SAxel Dörfler int32 code; 2285*e4c87231SAxel Dörfler status = read_port(request.reply_port, &code, _info, 2286*e4c87231SAxel Dörfler reply.count * sizeof(dormant_node_info)); 2287*e4c87231SAxel Dörfler if (status < B_OK) 2288*e4c87231SAxel Dörfler reply.result = status; 228952a38012Sejakowatz } 2290*e4c87231SAxel Dörfler gPortPool->PutPort(request.reply_port); 229152a38012Sejakowatz 229252a38012Sejakowatz return reply.result; 229352a38012Sejakowatz } 229452a38012Sejakowatz 2295*e4c87231SAxel Dörfler 229634c72144SAxel Dörfler /*! This function is used to do the real work of instantiating a dormant node. 229734c72144SAxel Dörfler It is either called by the media_addon_server to instantiate a global node, 229834c72144SAxel Dörfler or it gets called from BMediaRoster::InstantiateDormantNode() to create a 229934c72144SAxel Dörfler local one. 230034c72144SAxel Dörfler 230134c72144SAxel Dörfler Checks concerning global/local are not done here. 23028b04ffc1Sbeveloper */ 230352a38012Sejakowatz status_t 230434c72144SAxel Dörfler BMediaRosterEx::InstantiateDormantNode(media_addon_id addonID, int32 flavorID, 230534c72144SAxel Dörfler team_id creator, media_node *_node) 230652a38012Sejakowatz { 230754187cc6Sbeveloper // This function is always called from the correct context, if the node 230854187cc6Sbeveloper // is supposed to be global, it is called from the media_addon_server. 230954187cc6Sbeveloper 231052a38012Sejakowatz // if B_FLAVOR_IS_GLOBAL, we need to use the BMediaAddOn object that 231152a38012Sejakowatz // resides in the media_addon_server 231252a38012Sejakowatz 23138b04ffc1Sbeveloper // RegisterNode() must be called for nodes instantiated from add-ons, 23148b04ffc1Sbeveloper // since the media kit warrants that it's done automatically. 231552a38012Sejakowatz 231634c72144SAxel Dörfler // addonID Indicates the ID number of the media add-on in which the 231734c72144SAxel Dörfler // node resides. 231834c72144SAxel Dörfler // flavorID Indicates the internal ID number that the add-on uses to 231934c72144SAxel Dörfler // identify the flavor, this is the number that was published 232034c72144SAxel Dörfler // by BMediaAddOn::GetFlavorAt() in the 23218b04ffc1Sbeveloper // flavor_info::internal_id field. 232234c72144SAxel Dörfler // creator The creator team is -1 if nodes are created locally. If 232334c72144SAxel Dörfler // created globally, it will contain (while called in 232434c72144SAxel Dörfler // media_addon_server context) the team-id of the team that 232534c72144SAxel Dörfler // requested the instantiation. 23268b04ffc1Sbeveloper 232734c72144SAxel Dörfler TRACE("BMediaRosterEx::InstantiateDormantNode: addonID %ld, flavorID " 232834c72144SAxel Dörfler "%ld\n", addonID, flavorID); 23298b04ffc1Sbeveloper 23308b04ffc1Sbeveloper // Get flavor_info from the server 233134c72144SAxel Dörfler dormant_flavor_info info; 23328c6a6096Sbeveloper status_t rv; 233334c72144SAxel Dörfler rv = GetDormantFlavorInfo(addonID, flavorID, &info); 23348b04ffc1Sbeveloper if (rv != B_OK) { 233534c72144SAxel Dörfler ERROR("BMediaRosterEx::InstantiateDormantNode error: failed to get " 233634c72144SAxel Dörfler "dormant_flavor_info for addon-id %ld, flavor-id %ld\n", addonID, 233734c72144SAxel Dörfler flavorID); 233852a38012Sejakowatz return B_ERROR; 233952a38012Sejakowatz } 23408b04ffc1Sbeveloper 23411ecccf18SFrançois Revol ASSERT(info.internal_id == flavorID); 23428b04ffc1Sbeveloper 23438b04ffc1Sbeveloper // load the BMediaAddOn object 234429bb91d6SAxel Dörfler BMediaAddOn* addon = gDormantNodeManager->GetAddOn(addonID); 234534c72144SAxel Dörfler if (addon == NULL) { 23465ac4fbd7Sbeveloper ERROR("BMediaRosterEx::InstantiateDormantNode: GetAddon failed\n"); 23478b04ffc1Sbeveloper return B_ERROR; 23488b04ffc1Sbeveloper } 23498b04ffc1Sbeveloper 235054187cc6Sbeveloper // Now we need to try to increment the use count of this addon flavor 235154187cc6Sbeveloper // in the server. This can fail if the total number instances of this 235254187cc6Sbeveloper // flavor is limited. 235334c72144SAxel Dörfler rv = IncrementAddonFlavorInstancesCount(addonID, flavorID); 235454187cc6Sbeveloper if (rv != B_OK) { 235534c72144SAxel Dörfler ERROR("BMediaRosterEx::InstantiateDormantNode error: can't create " 235634c72144SAxel Dörfler "more nodes for addon-id %ld, flavor-id %ld\n", addonID, flavorID); 235754187cc6Sbeveloper // Put the addon back into the pool 235829bb91d6SAxel Dörfler gDormantNodeManager->PutAddOn(addonID); 235954187cc6Sbeveloper return B_ERROR; 236054187cc6Sbeveloper } 236154187cc6Sbeveloper 23628b04ffc1Sbeveloper BMessage config; 236334c72144SAxel Dörfler rv = LoadNodeConfiguration(addonID, flavorID, &config); 236454187cc6Sbeveloper if (rv != B_OK) { 236534c72144SAxel Dörfler ERROR("BMediaRosterEx::InstantiateDormantNode: couldn't load " 236634c72144SAxel Dörfler "configuration for addon-id %ld, flavor-id %ld\n", addonID, 236734c72144SAxel Dörfler flavorID); 236854187cc6Sbeveloper // do not return, this is a minor problem, not a reason to fail 236954187cc6Sbeveloper } 23708b04ffc1Sbeveloper 237134c72144SAxel Dörfler status_t status = B_OK; 237234c72144SAxel Dörfler BMediaNode* node = addon->InstantiateNodeFor(&info, &config, &status); 237334c72144SAxel Dörfler if (node == NULL) { 237434c72144SAxel Dörfler ERROR("BMediaRosterEx::InstantiateDormantNode: InstantiateNodeFor " 237534c72144SAxel Dörfler "failed\n"); 23768b04ffc1Sbeveloper 237754187cc6Sbeveloper // Put the addon back into the pool 237829bb91d6SAxel Dörfler gDormantNodeManager->PutAddOn(addonID); 237934c72144SAxel Dörfler 238054187cc6Sbeveloper // We must decrement the use count of this addon flavor in the 238154187cc6Sbeveloper // server to compensate the increment done in the beginning. 238234c72144SAxel Dörfler rv = DecrementAddonFlavorInstancesCount(addonID, flavorID); 238354187cc6Sbeveloper if (rv != B_OK) { 238434c72144SAxel Dörfler ERROR("BMediaRosterEx::InstantiateDormantNode: DecrementAddon" 238534c72144SAxel Dörfler "FlavorInstancesCount failed\n"); 238616b7eea4Sbeveloper } 238734c72144SAxel Dörfler return status != B_OK ? status : B_ERROR; 238854187cc6Sbeveloper } 238954187cc6Sbeveloper 239034c72144SAxel Dörfler rv = RegisterNode(node, addonID, flavorID); 23918c6a6096Sbeveloper if (rv != B_OK) { 23925ac4fbd7Sbeveloper ERROR("BMediaRosterEx::InstantiateDormantNode: RegisterNode failed\n"); 23938c6a6096Sbeveloper delete node; 239454187cc6Sbeveloper // Put the addon back into the pool 239529bb91d6SAxel Dörfler gDormantNodeManager->PutAddOn(addonID); 239654187cc6Sbeveloper // We must decrement the use count of this addon flavor in the 239754187cc6Sbeveloper // server to compensate the increment done in the beginning. 239834c72144SAxel Dörfler rv = DecrementAddonFlavorInstancesCount(addonID, flavorID); 239954187cc6Sbeveloper if (rv != B_OK) { 240034c72144SAxel Dörfler ERROR("BMediaRosterEx::InstantiateDormantNode: DecrementAddon" 240134c72144SAxel Dörfler "FlavorInstancesCount failed\n"); 240254187cc6Sbeveloper } 24038c6a6096Sbeveloper return B_ERROR; 24048c6a6096Sbeveloper } 24058c6a6096Sbeveloper 240654187cc6Sbeveloper if (creator != -1) { 240734c72144SAxel Dörfler // send a message to the server to assign team "creator" as creator 240834c72144SAxel Dörfler // of node "node->ID()" 240934c72144SAxel Dörfler printf("!!! BMediaRosterEx::InstantiateDormantNode assigning team " 241034c72144SAxel Dörfler "%ld as creator of node %ld\n", creator, node->ID()); 241134c72144SAxel Dörfler 241254187cc6Sbeveloper rv = MediaRosterEx(this)->SetNodeCreator(node->ID(), creator); 241354187cc6Sbeveloper if (rv != B_OK) { 241434c72144SAxel Dörfler ERROR("BMediaRosterEx::InstantiateDormantNode failed to assign " 241534c72144SAxel Dörfler "team %ld as creator of node %ld\n", creator, node->ID()); 241654187cc6Sbeveloper // do not return, this is a minor problem, not a reason to fail 241754187cc6Sbeveloper } 241854187cc6Sbeveloper } 241954187cc6Sbeveloper 242054187cc6Sbeveloper // RegisterNode() does remember the add-on id in the server 242154187cc6Sbeveloper // and UnregisterNode() will call DormantNodeManager::PutAddon() 242254187cc6Sbeveloper // when the node is unregistered. 24238c6a6096Sbeveloper 242434c72144SAxel Dörfler *_node = node->Node(); 2425cf4e2277Sbeveloper 242634c72144SAxel Dörfler TRACE("BMediaRosterEx::InstantiateDormantNode: addon-id %ld, flavor_id " 242734c72144SAxel Dörfler "%ld instanciated as node %ld, port %ld in team %ld\n", addonID, 24289dec2310SAxel Dörfler flavorID, _node->node, _node->port, BPrivate::current_team()); 2429cf4e2277Sbeveloper 243016b7eea4Sbeveloper return B_OK; 243116b7eea4Sbeveloper } 243252a38012Sejakowatz 243352a38012Sejakowatz 243452a38012Sejakowatz status_t 243534c72144SAxel Dörfler BMediaRoster::InstantiateDormantNode(const dormant_node_info& info, 243634c72144SAxel Dörfler media_node* _node, uint32 flags) 24378b04ffc1Sbeveloper { 24388b04ffc1Sbeveloper CALLED(); 243934c72144SAxel Dörfler if (_node == NULL) 24408b04ffc1Sbeveloper return B_BAD_VALUE; 244134c72144SAxel Dörfler if (info.addon <= B_OK) { 244234c72144SAxel Dörfler ERROR("BMediaRoster::InstantiateDormantNode error: addon-id %ld " 244334c72144SAxel Dörfler "invalid.\n", info.addon); 24448b04ffc1Sbeveloper return B_BAD_VALUE; 24458b04ffc1Sbeveloper } 24468b04ffc1Sbeveloper 244734c72144SAxel Dörfler printf("BMediaRoster::InstantiateDormantNode: addon-id %ld, flavor_id " 244834c72144SAxel Dörfler "%ld, flags 0x%lX\n", info.addon, info.flavor_id, flags); 24498b04ffc1Sbeveloper 24508b04ffc1Sbeveloper // Get flavor_info from the server 245134c72144SAxel Dörfler // TODO: this is a little overhead, as we get the full blown 245234c72144SAxel Dörfler // dormant_flavor_info, 245334c72144SAxel Dörfler // TODO: but only need the flags. 245434c72144SAxel Dörfler dormant_flavor_info flavorInfo; 24558b04ffc1Sbeveloper status_t rv; 245634c72144SAxel Dörfler rv = MediaRosterEx(this)->GetDormantFlavorInfo(info.addon, info.flavor_id, 245734c72144SAxel Dörfler &flavorInfo); 24588b04ffc1Sbeveloper if (rv != B_OK) { 245934c72144SAxel Dörfler ERROR("BMediaRoster::InstantiateDormantNode: failed to get " 246034c72144SAxel Dörfler "dormant_flavor_info for addon-id %ld, flavor-id %ld\n", 246134c72144SAxel Dörfler info.addon, info.flavor_id); 2462626824eaSbeveloper return B_NAME_NOT_FOUND; 24638b04ffc1Sbeveloper } 24648b04ffc1Sbeveloper 246534c72144SAxel Dörfler ASSERT(flavorInfo.internal_id == info.flavor_id); 24668b04ffc1Sbeveloper 24678b04ffc1Sbeveloper #if DEBUG 246834c72144SAxel Dörfler printf("BMediaRoster::InstantiateDormantNode: name \"%s\", info \"%s\", " 246934c72144SAxel Dörfler "flavor_flags 0x%lX, internal_id %ld, possible_count %ld\n", 247034c72144SAxel Dörfler flavorInfo.name, flavorInfo.info, flavorInfo.flavor_flags, 247134c72144SAxel Dörfler flavorInfo.internal_id, flavorInfo.possible_count); 247234c72144SAxel Dörfler 247334c72144SAxel Dörfler if ((flags & B_FLAVOR_IS_LOCAL) != 0) { 247434c72144SAxel Dörfler printf("BMediaRoster::InstantiateDormantNode: caller requested " 247534c72144SAxel Dörfler "B_FLAVOR_IS_LOCAL\n"); 247634c72144SAxel Dörfler } 247734c72144SAxel Dörfler if ((flags & B_FLAVOR_IS_GLOBAL) != 0) { 247834c72144SAxel Dörfler printf("BMediaRoster::InstantiateDormantNode: caller requested " 247934c72144SAxel Dörfler "B_FLAVOR_IS_GLOBAL\n"); 248034c72144SAxel Dörfler } 248134c72144SAxel Dörfler if ((flavorInfo.flavor_flags & B_FLAVOR_IS_LOCAL) != 0) { 248234c72144SAxel Dörfler printf("BMediaRoster::InstantiateDormantNode: node requires " 248334c72144SAxel Dörfler "B_FLAVOR_IS_LOCAL\n"); 248434c72144SAxel Dörfler } 248534c72144SAxel Dörfler if ((flavorInfo.flavor_flags & B_FLAVOR_IS_GLOBAL) != 0) { 248634c72144SAxel Dörfler printf("BMediaRoster::InstantiateDormantNode: node requires " 248734c72144SAxel Dörfler "B_FLAVOR_IS_GLOBAL\n"); 248834c72144SAxel Dörfler } 24898b04ffc1Sbeveloper #endif 24908b04ffc1Sbeveloper 24918b04ffc1Sbeveloper // Make sure that flags demanded by the dormant node and those requested 24928b04ffc1Sbeveloper // by the caller are not incompatible. 249334c72144SAxel Dörfler if ((flavorInfo.flavor_flags & B_FLAVOR_IS_GLOBAL) != 0 249434c72144SAxel Dörfler && (flags & B_FLAVOR_IS_LOCAL) != 0) { 249534c72144SAxel Dörfler ERROR("BMediaRoster::InstantiateDormantNode: requested " 249634c72144SAxel Dörfler "B_FLAVOR_IS_LOCAL, but dormant node has B_FLAVOR_IS_GLOBAL\n"); 2497626824eaSbeveloper return B_NAME_NOT_FOUND; 24988b04ffc1Sbeveloper } 249934c72144SAxel Dörfler if ((flavorInfo.flavor_flags & B_FLAVOR_IS_LOCAL) != 0 250034c72144SAxel Dörfler && (flags & B_FLAVOR_IS_GLOBAL) != 0) { 250134c72144SAxel Dörfler ERROR("BMediaRoster::InstantiateDormantNode: requested " 250234c72144SAxel Dörfler "B_FLAVOR_IS_GLOBAL, but dormant node has B_FLAVOR_IS_LOCAL\n"); 2503626824eaSbeveloper return B_NAME_NOT_FOUND; 25048b04ffc1Sbeveloper } 250554187cc6Sbeveloper 25068b04ffc1Sbeveloper // If either the node, or the caller requested to make the instance global 250734c72144SAxel Dörfler // we will do it by forwarding this request into the media_addon_server, 250834c72144SAxel Dörfler // which in turn will call BMediaRosterEx::InstantiateDormantNode to create 250934c72144SAxel Dörfler // the node there and make it globally available. 251034c72144SAxel Dörfler if ((flavorInfo.flavor_flags & B_FLAVOR_IS_GLOBAL) != 0 251134c72144SAxel Dörfler || (flags & B_FLAVOR_IS_GLOBAL) != 0) { 251234c72144SAxel Dörfler TRACE("BMediaRoster::InstantiateDormantNode: creating global object " 251334c72144SAxel Dörfler "in media_addon_server\n"); 2514cf4e2277Sbeveloper 25159c3b4706SAxel Dörfler add_on_server_instantiate_dormant_node_request request; 25169c3b4706SAxel Dörfler add_on_server_instantiate_dormant_node_reply reply; 25179c3b4706SAxel Dörfler request.add_on_id = info.addon; 25189dec2310SAxel Dörfler request.flavor_id = info.flavor_id; 25199dec2310SAxel Dörfler request.creator_team = BPrivate::current_team(); 252034c72144SAxel Dörfler // creator team is allowed to also release global nodes 25219c3b4706SAxel Dörfler rv = QueryAddOnServer(ADD_ON_SERVER_INSTANTIATE_DORMANT_NODE, &request, 252234c72144SAxel Dörfler sizeof(request), &reply, sizeof(reply)); 252334c72144SAxel Dörfler if (rv == B_OK) 252434c72144SAxel Dörfler *_node = reply.node; 25258b04ffc1Sbeveloper } else { 252654187cc6Sbeveloper // creator team = -1, as this is a local node 252734c72144SAxel Dörfler rv = MediaRosterEx(this)->InstantiateDormantNode(info.addon, 252834c72144SAxel Dörfler info.flavor_id, -1, _node); 25298b04ffc1Sbeveloper } 2530626824eaSbeveloper if (rv != B_OK) { 253134c72144SAxel Dörfler *_node = media_node::null; 2532626824eaSbeveloper return B_NAME_NOT_FOUND; 2533626824eaSbeveloper } 2534626824eaSbeveloper return B_OK; 25358b04ffc1Sbeveloper } 25368b04ffc1Sbeveloper 25378b04ffc1Sbeveloper 25388b04ffc1Sbeveloper status_t 253934c72144SAxel Dörfler BMediaRoster::InstantiateDormantNode(const dormant_node_info& info, 254034c72144SAxel Dörfler media_node* _node) 25418b04ffc1Sbeveloper { 254234c72144SAxel Dörfler return InstantiateDormantNode(info, _node, 0); 25438b04ffc1Sbeveloper } 25448b04ffc1Sbeveloper 25458b04ffc1Sbeveloper 25468b04ffc1Sbeveloper status_t 254752a38012Sejakowatz BMediaRoster::GetDormantNodeFor(const media_node& node, 254834c72144SAxel Dörfler dormant_node_info* _info) 254952a38012Sejakowatz { 255085dfab2bSbeveloper CALLED(); 255134c72144SAxel Dörfler if (_info == NULL) 255285dfab2bSbeveloper return B_BAD_VALUE; 255340f36b03Sbeveloper if (IS_INVALID_NODE(node)) 255485dfab2bSbeveloper return B_MEDIA_BAD_NODE; 255552a38012Sejakowatz 255685dfab2bSbeveloper server_get_dormant_node_for_request request; 255785dfab2bSbeveloper server_get_dormant_node_for_reply reply; 255885dfab2bSbeveloper status_t rv; 255985dfab2bSbeveloper 256085dfab2bSbeveloper request.node = node; 256185dfab2bSbeveloper 256234c72144SAxel Dörfler rv = QueryServer(SERVER_GET_DORMANT_NODE_FOR, &request, sizeof(request), 256334c72144SAxel Dörfler &reply, sizeof(reply)); 256485dfab2bSbeveloper if (rv != B_OK) 256585dfab2bSbeveloper return rv; 256685dfab2bSbeveloper 256734c72144SAxel Dörfler *_info = reply.node_info; 256885dfab2bSbeveloper return B_OK; 256952a38012Sejakowatz } 257052a38012Sejakowatz 257134c72144SAxel Dörfler 257252a38012Sejakowatz status_t 257334c72144SAxel Dörfler BMediaRosterEx::GetDormantFlavorInfo(media_addon_id addonID, int32 flavorID, 257434c72144SAxel Dörfler dormant_flavor_info* _flavor) 257552a38012Sejakowatz { 257652a38012Sejakowatz CALLED(); 257734c72144SAxel Dörfler if (_flavor == NULL) 25789bedd42cSbeveloper return B_BAD_VALUE; 257952a38012Sejakowatz 2580*e4c87231SAxel Dörfler // TODO: better use an area here as well! 258152a38012Sejakowatz 2582*e4c87231SAxel Dörfler server_get_dormant_flavor_info_reply* reply 2583*e4c87231SAxel Dörfler = (server_get_dormant_flavor_info_reply*)malloc(16300); 258434c72144SAxel Dörfler if (reply == NULL) 258534c72144SAxel Dörfler return B_NO_MEMORY; 258652a38012Sejakowatz 2587*e4c87231SAxel Dörfler server_get_dormant_flavor_info_request request; 2588*e4c87231SAxel Dörfler request.add_on_id = addonID; 2589*e4c87231SAxel Dörfler request.flavor_id = flavorID; 2590*e4c87231SAxel Dörfler request.reply_port = gPortPool->GetPort(); 2591*e4c87231SAxel Dörfler 2592*e4c87231SAxel Dörfler status_t status = QueryServer(SERVER_GET_DORMANT_FLAVOR_INFO, &request, 2593*e4c87231SAxel Dörfler sizeof(request), reply, 16300); 2594*e4c87231SAxel Dörfler 2595*e4c87231SAxel Dörfler gPortPool->PutPort(request.reply_port); 2596*e4c87231SAxel Dörfler 25979dec2310SAxel Dörfler if (status != B_OK) { 259852a38012Sejakowatz free(reply); 25999dec2310SAxel Dörfler return status; 260052a38012Sejakowatz } 260152a38012Sejakowatz 26029dec2310SAxel Dörfler if (reply->result == B_OK) { 26039dec2310SAxel Dörfler status = _flavor->Unflatten(reply->type, &reply->flattened_data, 26049dec2310SAxel Dörfler reply->flattened_size); 26059dec2310SAxel Dörfler } else 26069dec2310SAxel Dörfler status = reply->result; 260752a38012Sejakowatz 260852a38012Sejakowatz free(reply); 26099dec2310SAxel Dörfler return status; 261052a38012Sejakowatz } 261152a38012Sejakowatz 261234c72144SAxel Dörfler 26138b04ffc1Sbeveloper status_t 261434c72144SAxel Dörfler BMediaRoster::GetDormantFlavorInfoFor(const dormant_node_info& dormant, 261534c72144SAxel Dörfler dormant_flavor_info* _flavor) 26168b04ffc1Sbeveloper { 261734c72144SAxel Dörfler return MediaRosterEx(this)->GetDormantFlavorInfo(dormant.addon, 261834c72144SAxel Dörfler dormant.flavor_id, _flavor); 26198b04ffc1Sbeveloper } 262052a38012Sejakowatz 262134c72144SAxel Dörfler 262260f15390Sbeveloper // Reports in outLatency the maximum latency found downstream from 262360f15390Sbeveloper // the specified BBufferProducer, producer, given the current connections. 262452a38012Sejakowatz status_t 262534c72144SAxel Dörfler BMediaRoster::GetLatencyFor(const media_node& producer, bigtime_t* _latency) 262652a38012Sejakowatz { 262760f15390Sbeveloper CALLED(); 262834c72144SAxel Dörfler if (_latency == NULL) 262960f15390Sbeveloper return B_BAD_VALUE; 263034c72144SAxel Dörfler if (IS_INVALID_NODE(producer) 263134c72144SAxel Dörfler || (producer.kind & B_BUFFER_PRODUCER) == 0) 263260f15390Sbeveloper return B_MEDIA_BAD_NODE; 263360f15390Sbeveloper 263460f15390Sbeveloper producer_get_latency_request request; 263560f15390Sbeveloper producer_get_latency_reply reply; 263660f15390Sbeveloper status_t rv; 263760f15390Sbeveloper 263834c72144SAxel Dörfler rv = QueryPort(producer.port, PRODUCER_GET_LATENCY, &request, 263934c72144SAxel Dörfler sizeof(request), &reply, sizeof(reply)); 264060f15390Sbeveloper if (rv != B_OK) 264160f15390Sbeveloper return rv; 264260f15390Sbeveloper 264334c72144SAxel Dörfler *_latency = reply.latency; 264460f15390Sbeveloper 2645ab9afde3SMarcus Overhagen // printf("BMediaRoster::GetLatencyFor producer %ld has maximum latency %Ld\n", producer.node, *out_latency); 2646aac800c2Sbeveloper return B_OK; 264752a38012Sejakowatz } 264852a38012Sejakowatz 264952a38012Sejakowatz 265052a38012Sejakowatz status_t 265152a38012Sejakowatz BMediaRoster::GetInitialLatencyFor(const media_node& producer, 265234c72144SAxel Dörfler bigtime_t* _latency, uint32* _flags) 265352a38012Sejakowatz { 2654b65a0ac5SJérôme Duval CALLED(); 265534c72144SAxel Dörfler if (_latency == NULL) 2656b65a0ac5SJérôme Duval return B_BAD_VALUE; 265734c72144SAxel Dörfler if (IS_INVALID_NODE(producer) 265834c72144SAxel Dörfler || (producer.kind & B_BUFFER_PRODUCER) == 0) 2659b65a0ac5SJérôme Duval return B_MEDIA_BAD_NODE; 2660b65a0ac5SJérôme Duval 2661b65a0ac5SJérôme Duval producer_get_initial_latency_request request; 2662b65a0ac5SJérôme Duval producer_get_initial_latency_reply reply; 2663b65a0ac5SJérôme Duval status_t rv; 2664b65a0ac5SJérôme Duval 266534c72144SAxel Dörfler rv = QueryPort(producer.port, PRODUCER_GET_INITIAL_LATENCY, &request, 266634c72144SAxel Dörfler sizeof(request), &reply, sizeof(reply)); 2667b65a0ac5SJérôme Duval if (rv != B_OK) 2668b65a0ac5SJérôme Duval return rv; 2669b65a0ac5SJérôme Duval 267034c72144SAxel Dörfler *_latency = reply.initial_latency; 267134c72144SAxel Dörfler if (_flags != NULL) 267234c72144SAxel Dörfler *_flags = reply.flags; 2673b65a0ac5SJérôme Duval 267434c72144SAxel Dörfler TRACE("BMediaRoster::GetInitialLatencyFor producer %ld has maximum " 267534c72144SAxel Dörfler "initial latency %Ld\n", producer.node, *_latency); 2676aac800c2Sbeveloper return B_OK; 267752a38012Sejakowatz } 267852a38012Sejakowatz 267952a38012Sejakowatz 268052a38012Sejakowatz status_t 268134c72144SAxel Dörfler BMediaRoster::GetStartLatencyFor(const media_node& timeSource, 268234c72144SAxel Dörfler bigtime_t* _latency) 268352a38012Sejakowatz { 2684fc8b28b6SJérôme Duval CALLED(); 268534c72144SAxel Dörfler if (_latency == NULL) 2686fc8b28b6SJérôme Duval return B_BAD_VALUE; 268734c72144SAxel Dörfler if (IS_INVALID_NODE(timeSource) 268834c72144SAxel Dörfler || (timeSource.kind & B_TIME_SOURCE) == 0) 2689fc8b28b6SJérôme Duval return B_MEDIA_BAD_NODE; 2690fc8b28b6SJérôme Duval 2691fc8b28b6SJérôme Duval timesource_get_start_latency_request request; 2692fc8b28b6SJérôme Duval timesource_get_start_latency_reply reply; 2693fc8b28b6SJérôme Duval status_t rv; 2694fc8b28b6SJérôme Duval 269534c72144SAxel Dörfler rv = QueryPort(timeSource.port, TIMESOURCE_GET_START_LATENCY, &request, 269634c72144SAxel Dörfler sizeof(request), &reply, sizeof(reply)); 2697fc8b28b6SJérôme Duval if (rv != B_OK) 2698fc8b28b6SJérôme Duval return rv; 2699fc8b28b6SJérôme Duval 270034c72144SAxel Dörfler *_latency = reply.start_latency; 2701fc8b28b6SJérôme Duval 270234c72144SAxel Dörfler TRACE("BMediaRoster::GetStartLatencyFor timesource %ld has maximum " 270334c72144SAxel Dörfler "initial latency %Ld\n", timeSource.node, *_latency); 2704aac800c2Sbeveloper return B_OK; 270552a38012Sejakowatz } 270652a38012Sejakowatz 270752a38012Sejakowatz 270852a38012Sejakowatz status_t 270934c72144SAxel Dörfler BMediaRoster::GetFileFormatsFor(const media_node& fileInterface, 271034c72144SAxel Dörfler media_file_format* _formats, int32* _numFormats) 271152a38012Sejakowatz { 271252a38012Sejakowatz UNIMPLEMENTED(); 271352a38012Sejakowatz return B_ERROR; 271452a38012Sejakowatz } 271552a38012Sejakowatz 271652a38012Sejakowatz 271752a38012Sejakowatz status_t 271834c72144SAxel Dörfler BMediaRoster::SetRefFor(const media_node& file_interface, const entry_ref& file, 271934c72144SAxel Dörfler bool createAndTruncate, bigtime_t* _length) 272052a38012Sejakowatz { 27216938364bSMaurice Kalinowski CALLED(); 27226938364bSMaurice Kalinowski 27236938364bSMaurice Kalinowski fileinterface_set_ref_request request; 27246938364bSMaurice Kalinowski fileinterface_set_ref_reply reply; 27256938364bSMaurice Kalinowski status_t rv; 27266938364bSMaurice Kalinowski 27276938364bSMaurice Kalinowski request.device = file.device; 27286938364bSMaurice Kalinowski request.directory = file.directory; 27296938364bSMaurice Kalinowski strcpy(request.name, file.name); 273034c72144SAxel Dörfler request.create = createAndTruncate; 273134c72144SAxel Dörfler if (_length != NULL) 273234c72144SAxel Dörfler request.duration = *_length; 27336938364bSMaurice Kalinowski 273434c72144SAxel Dörfler rv = QueryPort(file_interface.port, FILEINTERFACE_SET_REF, &request, 273534c72144SAxel Dörfler sizeof(request), &reply, sizeof(reply)); 27366938364bSMaurice Kalinowski if (rv != B_OK) 27376938364bSMaurice Kalinowski return rv; 27386938364bSMaurice Kalinowski 273934c72144SAxel Dörfler if (!createAndTruncate && _length) 274034c72144SAxel Dörfler *_length = reply.duration; 27416938364bSMaurice Kalinowski 27426938364bSMaurice Kalinowski return B_OK; 274352a38012Sejakowatz } 274452a38012Sejakowatz 274552a38012Sejakowatz 274652a38012Sejakowatz status_t 274734c72144SAxel Dörfler BMediaRoster::GetRefFor(const media_node& node, entry_ref* _file, 274834c72144SAxel Dörfler BMimeType* mimeType) 274952a38012Sejakowatz { 27506938364bSMaurice Kalinowski CALLED(); 27516938364bSMaurice Kalinowski 275234c72144SAxel Dörfler if (!_file) 27536938364bSMaurice Kalinowski return B_BAD_VALUE; 27546938364bSMaurice Kalinowski 27556938364bSMaurice Kalinowski fileinterface_get_ref_request request; 27566938364bSMaurice Kalinowski fileinterface_get_ref_reply reply; 27576938364bSMaurice Kalinowski status_t rv; 27586938364bSMaurice Kalinowski 275934c72144SAxel Dörfler rv = QueryPort(node.port, FILEINTERFACE_GET_REF, &request, sizeof(request), 276034c72144SAxel Dörfler &reply, sizeof(reply)); 27616938364bSMaurice Kalinowski if (rv != B_OK) 27626938364bSMaurice Kalinowski return rv; 27636938364bSMaurice Kalinowski 276434c72144SAxel Dörfler *_file = entry_ref(reply.device, reply.directory, reply.name); 27656938364bSMaurice Kalinowski 276634c72144SAxel Dörfler if (mimeType) 276734c72144SAxel Dörfler mimeType->SetTo(reply.mimetype); 27686938364bSMaurice Kalinowski 27696938364bSMaurice Kalinowski return B_OK; 277052a38012Sejakowatz } 277152a38012Sejakowatz 277252a38012Sejakowatz 277352a38012Sejakowatz status_t 277452a38012Sejakowatz BMediaRoster::SniffRefFor(const media_node& file_interface, 277534c72144SAxel Dörfler const entry_ref& file, BMimeType* mimeType, float* _capability) 277652a38012Sejakowatz { 27776938364bSMaurice Kalinowski CALLED(); 277834c72144SAxel Dörfler if (mimeType == NULL || _capability == NULL) 27796938364bSMaurice Kalinowski return B_BAD_VALUE; 27806938364bSMaurice Kalinowski 27816938364bSMaurice Kalinowski fileinterface_sniff_ref_request request; 27826938364bSMaurice Kalinowski fileinterface_sniff_ref_reply reply; 27836938364bSMaurice Kalinowski status_t rv; 27846938364bSMaurice Kalinowski 27856938364bSMaurice Kalinowski request.device = file.device; 27866938364bSMaurice Kalinowski request.directory = file.directory; 27876938364bSMaurice Kalinowski strcpy(request.name, file.name); 27886938364bSMaurice Kalinowski 278934c72144SAxel Dörfler rv = QueryPort(file_interface.port, FILEINTERFACE_SNIFF_REF, &request, 279034c72144SAxel Dörfler sizeof(request), &reply, sizeof(reply)); 27916938364bSMaurice Kalinowski if (rv != B_OK) 27926938364bSMaurice Kalinowski return rv; 27936938364bSMaurice Kalinowski 279434c72144SAxel Dörfler mimeType->SetTo(reply.mimetype); 279534c72144SAxel Dörfler *_capability = reply.capability; 27966938364bSMaurice Kalinowski 27976938364bSMaurice Kalinowski return B_OK; 279852a38012Sejakowatz } 279952a38012Sejakowatz 280052a38012Sejakowatz 280134c72144SAxel Dörfler /*! This is the generic "here's a file, now can someone please play it" 280234c72144SAxel Dörfler interface. 280334c72144SAxel Dörfler */ 280452a38012Sejakowatz status_t 280534c72144SAxel Dörfler BMediaRoster::SniffRef(const entry_ref& file, uint64 requireNodeKinds, 280634c72144SAxel Dörfler dormant_node_info* _node, BMimeType* mimeType) 280752a38012Sejakowatz { 280805f452c3SDavid McPaul CALLED(); 280905f452c3SDavid McPaul 281005f452c3SDavid McPaul TRACE("BMediaRoster::SniffRef looking for a node to handle %s : %Ld\n",file.name, requireNodeKinds); 281105f452c3SDavid McPaul 281205f452c3SDavid McPaul if (_node == NULL) 281305f452c3SDavid McPaul return B_BAD_VALUE; 281405f452c3SDavid McPaul 281505f452c3SDavid McPaul BMimeType aMimeType; 281605f452c3SDavid McPaul 281705f452c3SDavid McPaul dormant_node_info nodes[30]; 281805f452c3SDavid McPaul int32 count = 30; 281905f452c3SDavid McPaul int32 highestCapability = -1; 282005f452c3SDavid McPaul float capability; 282105f452c3SDavid McPaul 282205f452c3SDavid McPaul media_node node; 282305f452c3SDavid McPaul 282405f452c3SDavid McPaul // Get all dormant nodes using GetDormantNodes 28256f7f87a2SDavid McPaul if (GetDormantNodes(nodes, &count, NULL, NULL, NULL, requireNodeKinds | B_FILE_INTERFACE, 0) == B_OK) { 282605f452c3SDavid McPaul // Call SniffRefFor on each node that matches requireNodeKinds 282705f452c3SDavid McPaul for (int32 i=0;i<count;i++) { 28286f7f87a2SDavid McPaul if (InstantiateDormantNode(nodes[i], &node) == B_OK) { 282905f452c3SDavid McPaul 28306f7f87a2SDavid McPaul if (SniffRefFor(node, file, &aMimeType, &capability) == B_OK) { 283105f452c3SDavid McPaul // find the first node that has 100% capability 283205f452c3SDavid McPaul TRACE("%s has a %f%% chance of playing file\n",nodes[i].name, capability * 100.0); 283305f452c3SDavid McPaul if (capability == 1.0) { 283405f452c3SDavid McPaul highestCapability = i; 283505f452c3SDavid McPaul break; 283605f452c3SDavid McPaul } 283705f452c3SDavid McPaul } 283805f452c3SDavid McPaul ReleaseNode(node); 283905f452c3SDavid McPaul } 284005f452c3SDavid McPaul } 284105f452c3SDavid McPaul 284205f452c3SDavid McPaul if (highestCapability != -1) { 284305f452c3SDavid McPaul *_node = nodes[highestCapability]; 284405f452c3SDavid McPaul 284505f452c3SDavid McPaul TRACE("BMediaRoster::SniffRef: found a node %s addon-id %ld, flavor_id %ld\n", 284605f452c3SDavid McPaul nodes[highestCapability].name, nodes[highestCapability].addon, nodes[highestCapability].flavor_id); 284705f452c3SDavid McPaul 284805f452c3SDavid McPaul if (mimeType != NULL) { 284905f452c3SDavid McPaul //*mimeType = aMimeType; -- need a copy constructor 285005f452c3SDavid McPaul } 285105f452c3SDavid McPaul 285205f452c3SDavid McPaul return B_OK; 285305f452c3SDavid McPaul } 285405f452c3SDavid McPaul 285505f452c3SDavid McPaul } 285605f452c3SDavid McPaul 285752a38012Sejakowatz return B_ERROR; 285852a38012Sejakowatz } 285952a38012Sejakowatz 286052a38012Sejakowatz 286152a38012Sejakowatz status_t 286252a38012Sejakowatz BMediaRoster::GetDormantNodeForType(const BMimeType& type, 286334c72144SAxel Dörfler uint64 requireNodeKinds, dormant_node_info* _node) 286452a38012Sejakowatz { 286552a38012Sejakowatz UNIMPLEMENTED(); 286652a38012Sejakowatz return B_ERROR; 286752a38012Sejakowatz } 286852a38012Sejakowatz 286952a38012Sejakowatz 287052a38012Sejakowatz status_t 287134c72144SAxel Dörfler BMediaRoster::GetReadFileFormatsFor(const dormant_node_info& node, 287234c72144SAxel Dörfler media_file_format* _readFormats, int32 readCount, int32* _readCount) 287352a38012Sejakowatz { 287452a38012Sejakowatz UNIMPLEMENTED(); 287552a38012Sejakowatz return B_ERROR; 287652a38012Sejakowatz } 287752a38012Sejakowatz 287852a38012Sejakowatz 287952a38012Sejakowatz status_t 288034c72144SAxel Dörfler BMediaRoster::GetWriteFileFormatsFor(const dormant_node_info& node, 288134c72144SAxel Dörfler media_file_format* _write_formats, int32 writeCount, int32* _writeCount) 288252a38012Sejakowatz { 288352a38012Sejakowatz UNIMPLEMENTED(); 288452a38012Sejakowatz return B_ERROR; 288552a38012Sejakowatz } 288652a38012Sejakowatz 288752a38012Sejakowatz 288852a38012Sejakowatz status_t 288934c72144SAxel Dörfler BMediaRoster::GetFormatFor(const media_output& output, media_format* _format, 289052a38012Sejakowatz uint32 flags) 289152a38012Sejakowatz { 28929bedd42cSbeveloper CALLED(); 289334c72144SAxel Dörfler if (_format == NULL) 28949bedd42cSbeveloper return B_BAD_VALUE; 28959bedd42cSbeveloper if ((output.node.kind & B_BUFFER_PRODUCER) == 0) 28969bedd42cSbeveloper return B_MEDIA_BAD_NODE; 28979bedd42cSbeveloper if (IS_INVALID_SOURCE(output.source)) 28989bedd42cSbeveloper return B_MEDIA_BAD_SOURCE; 28999bedd42cSbeveloper 29009bedd42cSbeveloper producer_format_suggestion_requested_request request; 29019bedd42cSbeveloper producer_format_suggestion_requested_reply reply; 29029bedd42cSbeveloper status_t rv; 29039bedd42cSbeveloper 29049bedd42cSbeveloper request.type = B_MEDIA_UNKNOWN_TYPE; 290534c72144SAxel Dörfler request.quality = 0; // TODO: what should this be? 29069bedd42cSbeveloper 290734c72144SAxel Dörfler rv = QueryPort(output.source.port, PRODUCER_FORMAT_SUGGESTION_REQUESTED, 290834c72144SAxel Dörfler &request, sizeof(request), &reply, sizeof(reply)); 29099bedd42cSbeveloper if (rv != B_OK) 29109bedd42cSbeveloper return rv; 29119bedd42cSbeveloper 291234c72144SAxel Dörfler *_format = reply.format; 29139bedd42cSbeveloper return B_OK; 291452a38012Sejakowatz } 291552a38012Sejakowatz 291652a38012Sejakowatz 291752a38012Sejakowatz status_t 291834c72144SAxel Dörfler BMediaRoster::GetFormatFor(const media_input& input, media_format* _format, 291952a38012Sejakowatz uint32 flags) 292052a38012Sejakowatz { 29219bedd42cSbeveloper CALLED(); 292234c72144SAxel Dörfler if (_format == NULL) 29239bedd42cSbeveloper return B_BAD_VALUE; 29249bedd42cSbeveloper if ((input.node.kind & B_BUFFER_CONSUMER) == 0) 29259bedd42cSbeveloper return B_MEDIA_BAD_NODE; 29269bedd42cSbeveloper if (IS_INVALID_DESTINATION(input.destination)) 29279bedd42cSbeveloper return B_MEDIA_BAD_DESTINATION; 29289bedd42cSbeveloper 29299bedd42cSbeveloper consumer_accept_format_request request; 29309bedd42cSbeveloper consumer_accept_format_reply reply; 29319bedd42cSbeveloper status_t rv; 29329bedd42cSbeveloper 29339bedd42cSbeveloper request.dest = input.destination; 29349bedd42cSbeveloper memset(&request.format, 0, sizeof(request.format)); // wildcard 29359bedd42cSbeveloper 293634c72144SAxel Dörfler rv = QueryPort(input.destination.port, CONSUMER_ACCEPT_FORMAT, &request, 293734c72144SAxel Dörfler sizeof(request), &reply, sizeof(reply)); 29389bedd42cSbeveloper if (rv != B_OK) 29399bedd42cSbeveloper return rv; 29409bedd42cSbeveloper 294134c72144SAxel Dörfler *_format = reply.format; 29429bedd42cSbeveloper return B_OK; 294352a38012Sejakowatz } 294452a38012Sejakowatz 294552a38012Sejakowatz 294652a38012Sejakowatz status_t 294734c72144SAxel Dörfler BMediaRoster::GetFormatFor(const media_node& node, media_format* _format, 294852a38012Sejakowatz float quality) 294952a38012Sejakowatz { 295052a38012Sejakowatz UNIMPLEMENTED(); 295134c72144SAxel Dörfler if (_format == NULL) 29529bedd42cSbeveloper return B_BAD_VALUE; 29539bedd42cSbeveloper if (IS_INVALID_NODE(node)) 29549bedd42cSbeveloper return B_MEDIA_BAD_NODE; 29559bedd42cSbeveloper if ((node.kind & (B_BUFFER_CONSUMER | B_BUFFER_PRODUCER)) == 0) 29569bedd42cSbeveloper return B_MEDIA_BAD_NODE; 29579bedd42cSbeveloper 295852a38012Sejakowatz return B_ERROR; 295952a38012Sejakowatz } 296052a38012Sejakowatz 296152a38012Sejakowatz 296252a38012Sejakowatz ssize_t 296352a38012Sejakowatz BMediaRoster::GetNodeAttributesFor(const media_node& node, 296434c72144SAxel Dörfler media_node_attribute* _array, size_t maxCount) 296552a38012Sejakowatz { 296652a38012Sejakowatz UNIMPLEMENTED(); 296752a38012Sejakowatz return B_ERROR; 296852a38012Sejakowatz } 296952a38012Sejakowatz 297052a38012Sejakowatz 297152a38012Sejakowatz media_node_id 297234c72144SAxel Dörfler BMediaRoster::NodeIDFor(port_id port) 297352a38012Sejakowatz { 29749e9417d2Sbeveloper CALLED(); 29759e9417d2Sbeveloper 29769e9417d2Sbeveloper server_node_id_for_request request; 29779e9417d2Sbeveloper server_node_id_for_reply reply; 29789e9417d2Sbeveloper status_t rv; 29799e9417d2Sbeveloper 298034c72144SAxel Dörfler request.port = port; 29819e9417d2Sbeveloper 298234c72144SAxel Dörfler rv = QueryServer(SERVER_NODE_ID_FOR, &request, sizeof(request), &reply, 298334c72144SAxel Dörfler sizeof(reply)); 29849e9417d2Sbeveloper if (rv != B_OK) { 29855ac4fbd7Sbeveloper ERROR("BMediaRoster::NodeIDFor: failed (error %#lx)\n", rv); 29869e9417d2Sbeveloper return -1; 29879e9417d2Sbeveloper } 29889e9417d2Sbeveloper 29899dec2310SAxel Dörfler return reply.node_id; 299052a38012Sejakowatz } 299152a38012Sejakowatz 299252a38012Sejakowatz 299352a38012Sejakowatz status_t 299434c72144SAxel Dörfler BMediaRoster::GetInstancesFor(media_addon_id addon, int32 flavor, 299534c72144SAxel Dörfler media_node_id* _id, int32* _count) 299652a38012Sejakowatz { 299785dfab2bSbeveloper CALLED(); 299834c72144SAxel Dörfler if (_id == NULL) 299985dfab2bSbeveloper return B_BAD_VALUE; 300034c72144SAxel Dörfler if (_count && *_count <= 0) 300185dfab2bSbeveloper return B_BAD_VALUE; 300285dfab2bSbeveloper 300385dfab2bSbeveloper server_get_instances_for_request request; 300485dfab2bSbeveloper server_get_instances_for_reply reply; 300585dfab2bSbeveloper status_t rv; 300685dfab2bSbeveloper 30079c3b4706SAxel Dörfler request.max_count = (_count ? *_count : 1); 30089c3b4706SAxel Dörfler request.add_on_id = addon; 30099c3b4706SAxel Dörfler request.flavor_id = flavor; 301085dfab2bSbeveloper 301134c72144SAxel Dörfler rv = QueryServer(SERVER_GET_INSTANCES_FOR, &request, sizeof(request), 301234c72144SAxel Dörfler &reply, sizeof(reply)); 301385dfab2bSbeveloper if (rv != B_OK) { 30145ac4fbd7Sbeveloper ERROR("BMediaRoster::GetLiveNodes failed\n"); 301585dfab2bSbeveloper return rv; 301652a38012Sejakowatz } 301752a38012Sejakowatz 301834c72144SAxel Dörfler if (_count) 301934c72144SAxel Dörfler *_count = reply.count; 302085dfab2bSbeveloper if (reply.count > 0) 302134c72144SAxel Dörfler memcpy(_id, reply.node_id, sizeof(media_node_id) * reply.count); 302285dfab2bSbeveloper 302385dfab2bSbeveloper return B_OK; 302485dfab2bSbeveloper } 302552a38012Sejakowatz 302652a38012Sejakowatz 302752a38012Sejakowatz status_t 302834c72144SAxel Dörfler BMediaRoster::SetRealtimeFlags(uint32 enabled) 302952a38012Sejakowatz { 303052a38012Sejakowatz UNIMPLEMENTED(); 303152a38012Sejakowatz return B_ERROR; 303252a38012Sejakowatz } 303352a38012Sejakowatz 303452a38012Sejakowatz 303552a38012Sejakowatz status_t 303634c72144SAxel Dörfler BMediaRoster::GetRealtimeFlags(uint32* _enabled) 303752a38012Sejakowatz { 303852a38012Sejakowatz UNIMPLEMENTED(); 303952a38012Sejakowatz return B_ERROR; 304052a38012Sejakowatz } 304152a38012Sejakowatz 304252a38012Sejakowatz 304352a38012Sejakowatz ssize_t 304434c72144SAxel Dörfler BMediaRoster::AudioBufferSizeFor(int32 channelCount, uint32 sampleFormat, 304534c72144SAxel Dörfler float frameRate, bus_type busKind) 304652a38012Sejakowatz { 304734c72144SAxel Dörfler bigtime_t bufferDuration; 304834c72144SAxel Dörfler ssize_t bufferSize; 3049df6c2e83Sbeveloper 3050df6c2e83Sbeveloper system_info info; 3051df6c2e83Sbeveloper get_system_info(&info); 3052df6c2e83Sbeveloper 305334c72144SAxel Dörfler if (info.cpu_clock_speed > 2000000000) // 2 GHz 305434c72144SAxel Dörfler bufferDuration = 2500; 3055df6c2e83Sbeveloper else if (info.cpu_clock_speed > 1000000000) 305634c72144SAxel Dörfler bufferDuration = 5000; 3057df6c2e83Sbeveloper else if (info.cpu_clock_speed > 600000000) 305834c72144SAxel Dörfler bufferDuration = 10000; 3059df6c2e83Sbeveloper else if (info.cpu_clock_speed > 200000000) 306034c72144SAxel Dörfler bufferDuration = 20000; 3061df6c2e83Sbeveloper else if (info.cpu_clock_speed > 100000000) 306234c72144SAxel Dörfler bufferDuration = 30000; 3063df6c2e83Sbeveloper else 306434c72144SAxel Dörfler bufferDuration = 50000; 3065df6c2e83Sbeveloper 306634c72144SAxel Dörfler if ((busKind == B_ISA_BUS || busKind == B_PCMCIA_BUS) 306734c72144SAxel Dörfler && bufferDuration < 25000) 306834c72144SAxel Dörfler bufferDuration = 25000; 3069df6c2e83Sbeveloper 307034c72144SAxel Dörfler bufferSize = (sampleFormat & 0xf) * channelCount 307134c72144SAxel Dörfler * (ssize_t)((frameRate * bufferDuration) / 1000000.0); 3072df6c2e83Sbeveloper 307334c72144SAxel Dörfler printf("Suggested buffer duration %Ld, size %ld\n", bufferDuration, 307434c72144SAxel Dörfler bufferSize); 3075df6c2e83Sbeveloper 307634c72144SAxel Dörfler return bufferSize; 307752a38012Sejakowatz } 307852a38012Sejakowatz 307952a38012Sejakowatz 308034c72144SAxel Dörfler /*! Use MediaFlags to inquire about specific features of the Media Kit. 308134c72144SAxel Dörfler Returns < 0 for "not present", positive size for output data size. 308234c72144SAxel Dörfler 0 means that the capability is present, but no data about it. 308334c72144SAxel Dörfler */ 308452a38012Sejakowatz /*static*/ ssize_t 308534c72144SAxel Dörfler BMediaRoster::MediaFlags(media_flags cap, void* buffer, size_t maxSize) 308652a38012Sejakowatz { 308752a38012Sejakowatz UNIMPLEMENTED(); 308852a38012Sejakowatz return 0; 308952a38012Sejakowatz } 309052a38012Sejakowatz 309152a38012Sejakowatz 309234c72144SAxel Dörfler // #pragma mark - BLooper overrides 309334c72144SAxel Dörfler 309434c72144SAxel Dörfler 309534c72144SAxel Dörfler void 309652a38012Sejakowatz BMediaRoster::MessageReceived(BMessage* message) 309752a38012Sejakowatz { 3098cf4e2277Sbeveloper switch (message->what) { 3099cf4e2277Sbeveloper case 'PING': 3100cf4e2277Sbeveloper { 31016396865dSbeveloper // media_server plays ping-pong with the BMediaRosters 31026396865dSbeveloper // to detect dead teams. Normal communication uses ports. 31036396865dSbeveloper static BMessage pong('PONG'); 31046396865dSbeveloper message->SendReply(&pong, static_cast<BHandler *>(NULL), 2000000); 31056396865dSbeveloper return; 31066396865dSbeveloper } 31076396865dSbeveloper 3108cf4e2277Sbeveloper case NODE_FINAL_RELEASE: 3109cf4e2277Sbeveloper { 3110cf4e2277Sbeveloper // this function is called by a BMediaNode to delete 3111cf4e2277Sbeveloper // itself, as this needs to be done from another thread 3112cf4e2277Sbeveloper // context, it is done here. 311334c72144SAxel Dörfler // TODO: If a node is released using BMediaRoster::ReleaseNode() 311434c72144SAxel Dörfler // TODO: instead of using BMediaNode::Release() / BMediaNode::Acquire() 311534c72144SAxel Dörfler // TODO: fRefCount of the BMediaNode will not be correct. 3116cf4e2277Sbeveloper 3117cf4e2277Sbeveloper BMediaNode *node; 3118cf4e2277Sbeveloper message->FindPointer("node", reinterpret_cast<void **>(&node)); 3119cf4e2277Sbeveloper 312054187cc6Sbeveloper TRACE("BMediaRoster::MessageReceived NODE_FINAL_RELEASE saving node %ld configuration\n", node->ID()); 312154187cc6Sbeveloper MediaRosterEx(BMediaRoster::Roster())->SaveNodeConfiguration(node); 3122cf4e2277Sbeveloper 312354187cc6Sbeveloper TRACE("BMediaRoster::MessageReceived NODE_FINAL_RELEASE releasing node %ld\n", node->ID()); 3124cf4e2277Sbeveloper node->DeleteHook(node); // we don't call Release(), see above! 3125cf4e2277Sbeveloper return; 3126cf4e2277Sbeveloper } 3127cf4e2277Sbeveloper } 31286396865dSbeveloper printf("BMediaRoster::MessageReceived: unknown message!\n"); 31296396865dSbeveloper message->PrintToStream(); 313052a38012Sejakowatz } 313152a38012Sejakowatz 313234c72144SAxel Dörfler 313334c72144SAxel Dörfler bool 313452a38012Sejakowatz BMediaRoster::QuitRequested() 313552a38012Sejakowatz { 313652a38012Sejakowatz UNIMPLEMENTED(); 313752a38012Sejakowatz return true; 313852a38012Sejakowatz } 313952a38012Sejakowatz 314034c72144SAxel Dörfler 314134c72144SAxel Dörfler BHandler* 314234c72144SAxel Dörfler BMediaRoster::ResolveSpecifier(BMessage* msg, int32 index, BMessage* specifier, 314334c72144SAxel Dörfler int32 form, const char* property) 314452a38012Sejakowatz { 3145286a3c91SJérôme Duval return BLooper::ResolveSpecifier(msg, index, specifier, form, property); 314652a38012Sejakowatz } 314752a38012Sejakowatz 314852a38012Sejakowatz 314934c72144SAxel Dörfler status_t 315052a38012Sejakowatz BMediaRoster::GetSupportedSuites(BMessage* data) 315152a38012Sejakowatz { 3152286a3c91SJérôme Duval return BLooper::GetSupportedSuites(data); 315352a38012Sejakowatz } 315452a38012Sejakowatz 315552a38012Sejakowatz 315652a38012Sejakowatz BMediaRoster::~BMediaRoster() 315752a38012Sejakowatz { 315852a38012Sejakowatz CALLED(); 31596396865dSbeveloper 31606396865dSbeveloper // unregister this application with the media server 31616396865dSbeveloper server_unregister_app_request request; 31626396865dSbeveloper server_unregister_app_reply reply; 31639dec2310SAxel Dörfler request.team = BPrivate::current_team(); 316434c72144SAxel Dörfler QueryServer(SERVER_UNREGISTER_APP, &request, sizeof(request), &reply, 316534c72144SAxel Dörfler sizeof(reply)); 31668b940bb4SStephan Aßmus 31672f9ed888SAxel Dörfler BPrivate::SharedBufferList::Invalidate(); 31682f9ed888SAxel Dörfler 31698b940bb4SStephan Aßmus // Unset the global instance pointer, the destructor is also called 31708b940bb4SStephan Aßmus // if a client app calls Lock(); and Quit(); directly. 31719def3bf7SStephan Aßmus sDefaultInstance = NULL; 317252a38012Sejakowatz } 317352a38012Sejakowatz 317452a38012Sejakowatz 317534c72144SAxel Dörfler // #pragma mark - private BMediaRoster 317634c72144SAxel Dörfler 317752a38012Sejakowatz 317852a38012Sejakowatz // deprecated call 317952a38012Sejakowatz status_t 318052a38012Sejakowatz BMediaRoster::SetOutputBuffersFor(const media_source& output, 318134c72144SAxel Dörfler BBufferGroup* group, bool willReclaim) 318252a38012Sejakowatz { 318352a38012Sejakowatz UNIMPLEMENTED(); 31849e9417d2Sbeveloper debugger("BMediaRoster::SetOutputBuffersFor missing\n"); 318552a38012Sejakowatz return B_ERROR; 318652a38012Sejakowatz } 318752a38012Sejakowatz 318852a38012Sejakowatz 318934c72144SAxel Dörfler /* FBC reserved virtuals */ 319052a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_0(void *) { return B_ERROR; } 319152a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_1(void *) { return B_ERROR; } 319252a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_2(void *) { return B_ERROR; } 319352a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_3(void *) { return B_ERROR; } 319452a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_4(void *) { return B_ERROR; } 319552a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_5(void *) { return B_ERROR; } 319652a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_6(void *) { return B_ERROR; } 319752a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_7(void *) { return B_ERROR; } 319852a38012Sejakowatz 319952a38012Sejakowatz 320034c72144SAxel Dörfler BMediaRoster::BMediaRoster() 32012f9ed888SAxel Dörfler : 32022f9ed888SAxel Dörfler BLooper("_BMediaRoster_", B_URGENT_DISPLAY_PRIORITY, 320334c72144SAxel Dörfler B_LOOPER_PORT_DEFAULT_CAPACITY) 320452a38012Sejakowatz { 320552a38012Sejakowatz CALLED(); 32066396865dSbeveloper 32076396865dSbeveloper // start the looper 32086396865dSbeveloper Run(); 320952a38012Sejakowatz } 321052a38012Sejakowatz 32116396865dSbeveloper 32129def3bf7SStephan Aßmus // TODO: Looks like these can be safely removed: 321352a38012Sejakowatz /*static*/ status_t 321452a38012Sejakowatz BMediaRoster::ParseCommand(BMessage& reply) 321552a38012Sejakowatz { 321652a38012Sejakowatz UNIMPLEMENTED(); 321752a38012Sejakowatz return B_ERROR; 321852a38012Sejakowatz } 321952a38012Sejakowatz 322052a38012Sejakowatz 322152a38012Sejakowatz status_t 322234c72144SAxel Dörfler BMediaRoster::GetDefaultInfo(media_node_id forDefault, BMessage& config) 322352a38012Sejakowatz { 322452a38012Sejakowatz UNIMPLEMENTED(); 322552a38012Sejakowatz return B_ERROR; 322652a38012Sejakowatz } 322752a38012Sejakowatz 322852a38012Sejakowatz 322952a38012Sejakowatz status_t 323034c72144SAxel Dörfler BMediaRoster::SetRunningDefault(media_node_id forDefault, 323152a38012Sejakowatz const media_node& node) 323252a38012Sejakowatz { 323352a38012Sejakowatz UNIMPLEMENTED(); 323452a38012Sejakowatz return B_ERROR; 323552a38012Sejakowatz } 323652a38012Sejakowatz 323752a38012Sejakowatz 32389def3bf7SStephan Aßmus // #pragma mark - static variables 323952a38012Sejakowatz 32409def3bf7SStephan Aßmus 32419def3bf7SStephan Aßmus BMediaRoster* BMediaRoster::sDefaultInstance = NULL; 324252a38012Sejakowatz 3243