1255a01c7Sbeveloper /* 27bcdb362SDario Casalinuovo * Copyright 2015 Dario Casalinuovo 3332cc6bcSAxel Dörfler * Copyright 2009-2012, Axel Dörfler, axeld@pinc-software.de. 47bcdb362SDario Casalinuovo * Copyright 2008 Maurice Kalinowski, haiku@kaldience.com 534c72144SAxel Dörfler * 634c72144SAxel Dörfler * All rights reserved. Distributed under the terms of the MIT License. 734c72144SAxel Dörfler */ 834c72144SAxel Dörfler 934c72144SAxel Dörfler /* 1065b73ae4SMarcus Overhagen * Copyright (c) 2002-2006 Marcus Overhagen <Marcus@Overhagen.de> 11255a01c7Sbeveloper * 12255a01c7Sbeveloper * Permission is hereby granted, free of charge, to any person obtaining 13255a01c7Sbeveloper * a copy of this software and associated documentation files or portions 14255a01c7Sbeveloper * thereof (the "Software"), to deal in the Software without restriction, 15255a01c7Sbeveloper * including without limitation the rights to use, copy, modify, merge, 16255a01c7Sbeveloper * publish, distribute, sublicense, and/or sell copies of the Software, 17255a01c7Sbeveloper * and to permit persons to whom the Software is furnished to do so, subject 18255a01c7Sbeveloper * to the following conditions: 19255a01c7Sbeveloper * 20255a01c7Sbeveloper * * Redistributions of source code must retain the above copyright notice, 21255a01c7Sbeveloper * this list of conditions and the following disclaimer. 22255a01c7Sbeveloper * 23255a01c7Sbeveloper * * Redistributions in binary form must reproduce the above copyright notice 24255a01c7Sbeveloper * in the binary, as well as this list of conditions and the following 25255a01c7Sbeveloper * disclaimer in the documentation and/or other materials provided with 26255a01c7Sbeveloper * the distribution. 27255a01c7Sbeveloper * 28255a01c7Sbeveloper * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 29255a01c7Sbeveloper * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 30255a01c7Sbeveloper * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 31255a01c7Sbeveloper * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 32255a01c7Sbeveloper * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 33255a01c7Sbeveloper * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 34255a01c7Sbeveloper * THE SOFTWARE. 35255a01c7Sbeveloper */ 366938364bSMaurice Kalinowski 37255a01c7Sbeveloper 38255a01c7Sbeveloper /* to comply with the license above, do not remove the following line */ 398b940bb4SStephan Aßmus char __dont_remove_copyright_from_binary[] = "Copyright (c) 2002-2006 Marcus " 408b940bb4SStephan Aßmus "Overhagen <Marcus@Overhagen.de>"; 41255a01c7Sbeveloper 429dec2310SAxel Dörfler 4352a38012Sejakowatz #include <MediaRoster.h> 448b940bb4SStephan Aßmus 4505962bb1SDario Casalinuovo #include <Application.h> 46d15321ffSDario Casalinuovo #include <Autolock.h> 476938364bSMaurice Kalinowski #include <BufferConsumer.h> 486938364bSMaurice Kalinowski #include <BufferProducer.h> 4952a38012Sejakowatz #include <Locker.h> 5052a38012Sejakowatz #include <Message.h> 5152a38012Sejakowatz #include <Messenger.h> 526938364bSMaurice Kalinowski #include <MimeType.h> 5352a38012Sejakowatz #include <OS.h> 546938364bSMaurice Kalinowski #include <ParameterWeb.h> 5567483edaSDario Casalinuovo #include <Roster.h> 566938364bSMaurice Kalinowski #include <StopWatch.h> 5752a38012Sejakowatz #include <String.h> 5852a38012Sejakowatz #include <TimeSource.h> 598b940bb4SStephan Aßmus 6005962bb1SDario Casalinuovo #include <new> 619dec2310SAxel Dörfler 6205962bb1SDario Casalinuovo #include <AppMisc.h> 632f9ed888SAxel Dörfler #include <DataExchange.h> 64b84955d4SBarrett17 #include <MediaDebug.h> 652f9ed888SAxel Dörfler #include <DormantNodeManager.h> 662f9ed888SAxel Dörfler #include <MediaMisc.h> 6732afe10aSDario Casalinuovo #include <MediaRosterEx.h> 682f9ed888SAxel Dörfler #include <Notifications.h> 692f9ed888SAxel Dörfler #include <ServerInterface.h> 702f9ed888SAxel Dörfler #include <SharedBufferList.h> 7132afe10aSDario Casalinuovo #include <TList.h> 722f9ed888SAxel Dörfler 73835140c8Sbeveloper #include "TimeSourceObjectManager.h" 7452a38012Sejakowatz 752f9ed888SAxel Dörfler 76f0a1eb2dSAxel Dörfler namespace BPrivate { 77f0a1eb2dSAxel Dörfler namespace media { 7852a38012Sejakowatz 79f0a1eb2dSAxel Dörfler 8032afe10aSDario Casalinuovo struct RosterNotification { 8132afe10aSDario Casalinuovo BMessenger messenger; 8232afe10aSDario Casalinuovo int32 what; 8332afe10aSDario Casalinuovo }; 8432afe10aSDario Casalinuovo 8505962bb1SDario Casalinuovo 8676889670SDario Casalinuovo struct SyncedMessage { 8776889670SDario Casalinuovo BMessage* message; 8876889670SDario Casalinuovo }; 8976889670SDario Casalinuovo 9076889670SDario Casalinuovo 9167060664SDario Casalinuovo struct LocalNode { 9267060664SDario Casalinuovo LocalNode(BMediaNode* local_node) 9367060664SDario Casalinuovo : 9467060664SDario Casalinuovo node(local_node) {} 9567060664SDario Casalinuovo 9667060664SDario Casalinuovo LocalNode() 9767060664SDario Casalinuovo : 9867060664SDario Casalinuovo node(NULL) {} 9967060664SDario Casalinuovo 10067060664SDario Casalinuovo bool operator==(const LocalNode& a) 10167060664SDario Casalinuovo { 10267060664SDario Casalinuovo if (a.node == this->node) 10367060664SDario Casalinuovo return true; 10467060664SDario Casalinuovo return false; 10567060664SDario Casalinuovo } 10667060664SDario Casalinuovo 10767060664SDario Casalinuovo BMediaNode* node; 10867060664SDario Casalinuovo }; 10967060664SDario Casalinuovo 11067060664SDario Casalinuovo 11132afe10aSDario Casalinuovo static bool sServerIsUp = false; 11232afe10aSDario Casalinuovo static List<RosterNotification> sNotificationList; 113d15321ffSDario Casalinuovo static BLocker sInitLocker("BMediaRoster::Roster locker"); 11467060664SDario Casalinuovo static List<LocalNode> sRegisteredNodes; 11532afe10aSDario Casalinuovo 1167d337b23SDario Casalinuovo 1177d337b23SDario Casalinuovo class MediaRosterUndertaker { 1187d337b23SDario Casalinuovo public: 1197d337b23SDario Casalinuovo ~MediaRosterUndertaker() 1207d337b23SDario Casalinuovo { 1217d337b23SDario Casalinuovo BAutolock _(sInitLocker); 122ad7255c8SDario Casalinuovo if (BMediaRoster::CurrentRoster() != NULL) { 12305962bb1SDario Casalinuovo 12467060664SDario Casalinuovo // Detect any forgotten node 12567060664SDario Casalinuovo if (sRegisteredNodes.CountItems() > 0) { 12667060664SDario Casalinuovo for (int32 i = 0; i < sRegisteredNodes.CountItems(); i++) { 12767060664SDario Casalinuovo LocalNode* node = NULL; 12867060664SDario Casalinuovo sRegisteredNodes.Get(i, &node); 12967060664SDario Casalinuovo if (node != NULL) { 13067060664SDario Casalinuovo ERROR("BMediaRoster: Node with ID %" B_PRId32 13167060664SDario Casalinuovo " was not released correctly\n", node->node->ID()); 13267060664SDario Casalinuovo } 13367060664SDario Casalinuovo } 13467060664SDario Casalinuovo } 13567060664SDario Casalinuovo 13605962bb1SDario Casalinuovo if (be_app != NULL) 13705962bb1SDario Casalinuovo be_app->UnregisterLooper(BMediaRoster::CurrentRoster()); 13805962bb1SDario Casalinuovo 139ad7255c8SDario Casalinuovo status_t err = B_ERROR; 140ad7255c8SDario Casalinuovo thread_id roster = BMediaRoster::CurrentRoster()->Thread(); 141ad7255c8SDario Casalinuovo 142ad7255c8SDario Casalinuovo BMediaRoster::CurrentRoster()->PostMessage(B_QUIT_REQUESTED); 143ad7255c8SDario Casalinuovo 144ad7255c8SDario Casalinuovo wait_for_thread(roster, &err); 145ad7255c8SDario Casalinuovo if (err != B_OK) 146ad7255c8SDario Casalinuovo ERROR("BMediaRoster: wait_for_thread returned error"); 1477d337b23SDario Casalinuovo } 1487d337b23SDario Casalinuovo } 1497d337b23SDario Casalinuovo }; 1507d337b23SDario Casalinuovo 1517d337b23SDario Casalinuovo 1527d337b23SDario Casalinuovo static MediaRosterUndertaker sMediaRosterUndertaker; 1537d337b23SDario Casalinuovo 1549dec2310SAxel Dörfler } // namespace media 1559dec2310SAxel Dörfler } // namespace BPrivate 1569dec2310SAxel Dörfler 1578b04ffc1Sbeveloper using namespace BPrivate::media; 15852a38012Sejakowatz 1599dec2310SAxel Dörfler 16034c72144SAxel Dörfler BMediaRosterEx::BMediaRosterEx(status_t* _error) 1619dec2310SAxel Dörfler : 16276889670SDario Casalinuovo BMediaRoster(), 16376889670SDario Casalinuovo fLaunchNotification(false), 16476889670SDario Casalinuovo fAutoExit(false) 165dcfb6bfcSJérôme Duval { 1667d337b23SDario Casalinuovo gDormantNodeManager = new DormantNodeManager(); 1677d337b23SDario Casalinuovo gTimeSourceObjectManager = new TimeSourceObjectManager(); 168f0a1eb2dSAxel Dörfler 16932afe10aSDario Casalinuovo *_error = BuildConnections(); 17032afe10aSDario Casalinuovo 17132afe10aSDario Casalinuovo InitRosterDataExchange(BMessenger(this, this)); 17232afe10aSDario Casalinuovo 17332afe10aSDario Casalinuovo if (be_roster->StartWatching(BMessenger(this, this), 174d009f286SDario Casalinuovo B_REQUEST_LAUNCHED | B_REQUEST_QUIT) != B_OK) { 17532afe10aSDario Casalinuovo *_error = B_ERROR; 176d009f286SDario Casalinuovo } 17732afe10aSDario Casalinuovo sServerIsUp = BMediaRoster::IsRunning(); 17832afe10aSDario Casalinuovo } 17932afe10aSDario Casalinuovo 18032afe10aSDario Casalinuovo 1817d337b23SDario Casalinuovo void 1827d337b23SDario Casalinuovo BMediaRosterEx::Quit() 1837d337b23SDario Casalinuovo { 1847d337b23SDario Casalinuovo if (be_roster->StopWatching(BMessenger(this, this)) != B_OK) 1857d337b23SDario Casalinuovo TRACE("Can't unregister roster notifications"); 1867d337b23SDario Casalinuovo 1877d337b23SDario Casalinuovo if (sNotificationList.CountItems() != 0) 1887d337b23SDario Casalinuovo sNotificationList.MakeEmpty(); 1897d337b23SDario Casalinuovo 1907d337b23SDario Casalinuovo BMediaRoster::Quit(); 1917d337b23SDario Casalinuovo } 1927d337b23SDario Casalinuovo 1937d337b23SDario Casalinuovo 19432afe10aSDario Casalinuovo status_t 19532afe10aSDario Casalinuovo BMediaRosterEx::BuildConnections() 19632afe10aSDario Casalinuovo { 19732afe10aSDario Casalinuovo InitServerDataExchange(); 198dcfb6bfcSJérôme Duval // register this application with the media server 199dcfb6bfcSJérôme Duval server_register_app_request request; 200dcfb6bfcSJérôme Duval server_register_app_reply reply; 2019dec2310SAxel Dörfler request.team = BPrivate::current_team(); 202dcfb6bfcSJérôme Duval request.messenger = BMessenger(NULL, this); 2039dec2310SAxel Dörfler status_t status = QueryServer(SERVER_REGISTER_APP, &request, 2049dec2310SAxel Dörfler sizeof(request), &reply, sizeof(reply)); 2059dec2310SAxel Dörfler if (status != B_OK) 20632afe10aSDario Casalinuovo return B_MEDIA_SYSTEM_FAILURE; 20732afe10aSDario Casalinuovo 20832afe10aSDario Casalinuovo return B_OK; 209dcfb6bfcSJérôme Duval } 210dcfb6bfcSJérôme Duval 21134c72144SAxel Dörfler 212e57acc3aSDario Casalinuovo BMediaRosterEx::~BMediaRosterEx() 213e57acc3aSDario Casalinuovo { 214e57acc3aSDario Casalinuovo CALLED(); 215e57acc3aSDario Casalinuovo 216e57acc3aSDario Casalinuovo delete gTimeSourceObjectManager; 217e57acc3aSDario Casalinuovo delete gDormantNodeManager; 218e57acc3aSDario Casalinuovo 219e57acc3aSDario Casalinuovo // unregister this application with the media server 220e57acc3aSDario Casalinuovo server_unregister_app_request request; 221e57acc3aSDario Casalinuovo server_unregister_app_reply reply; 222e57acc3aSDario Casalinuovo request.team = BPrivate::current_team(); 223e57acc3aSDario Casalinuovo QueryServer(SERVER_UNREGISTER_APP, &request, sizeof(request), &reply, 224e57acc3aSDario Casalinuovo sizeof(reply)); 225e57acc3aSDario Casalinuovo 226e57acc3aSDario Casalinuovo BPrivate::SharedBufferList::Invalidate(); 227e57acc3aSDario Casalinuovo } 228e57acc3aSDario Casalinuovo 229e57acc3aSDario Casalinuovo 23067060664SDario Casalinuovo void 23167060664SDario Casalinuovo BMediaRosterEx::RegisterLocalNode(BMediaNode* node) 23267060664SDario Casalinuovo { 23367060664SDario Casalinuovo sRegisteredNodes.Insert(LocalNode(node)); 23467060664SDario Casalinuovo } 23567060664SDario Casalinuovo 23667060664SDario Casalinuovo 23767060664SDario Casalinuovo void 23867060664SDario Casalinuovo BMediaRosterEx::UnregisterLocalNode(BMediaNode* node) 23967060664SDario Casalinuovo { 24067060664SDario Casalinuovo int32 index = sRegisteredNodes.Find(LocalNode(node)); 24167060664SDario Casalinuovo if (index != -1) 24267060664SDario Casalinuovo sRegisteredNodes.Remove(index); 24367060664SDario Casalinuovo } 24467060664SDario Casalinuovo 24567060664SDario Casalinuovo 24676889670SDario Casalinuovo void 24776889670SDario Casalinuovo BMediaRosterEx::EnableLaunchNotification(bool enable, bool autoExit) 24876889670SDario Casalinuovo { 24976889670SDario Casalinuovo // NOTE: in theory, we should personalize it depending on each 25076889670SDario Casalinuovo // request, but we are using it just in launch/shutdown_media_server, 25176889670SDario Casalinuovo // so we are enough safe to don't care about that. 25276889670SDario Casalinuovo fLaunchNotification = enable; 25376889670SDario Casalinuovo fAutoExit = autoExit; 25476889670SDario Casalinuovo } 25576889670SDario Casalinuovo 25676889670SDario Casalinuovo 2573620737cSbeveloper status_t 25854187cc6Sbeveloper BMediaRosterEx::SaveNodeConfiguration(BMediaNode* node) 25954187cc6Sbeveloper { 2609dec2310SAxel Dörfler int32 flavorID; 2619dec2310SAxel Dörfler BMediaAddOn* addon = node->AddOn(&flavorID); 2629dec2310SAxel Dörfler if (addon == NULL) { 2638056f0dbSStephan Aßmus // NOTE: This node could have been created by an application, 2648056f0dbSStephan Aßmus // it does not mean there is an error. 26534c72144SAxel Dörfler // TODO: this check incorrectly triggers on BeOS R5 BT848 node 266332cc6bcSAxel Dörfler TRACE("BMediaRosterEx::SaveNodeConfiguration node %" B_PRId32 " not " 267332cc6bcSAxel Dörfler "instantiated from BMediaAddOn!\n", node->ID()); 26854187cc6Sbeveloper return B_ERROR; 26954187cc6Sbeveloper } 2709dec2310SAxel Dörfler 2719dec2310SAxel Dörfler media_addon_id addonID = addon->AddonID(); 27254187cc6Sbeveloper 27334c72144SAxel Dörfler // TODO: fix this 2748056f0dbSStephan Aßmus printf("### BMediaRosterEx::SaveNodeConfiguration should save addon-id " 275332cc6bcSAxel Dörfler "%" B_PRId32 ", flavor-id %" B_PRId32 " config NOW!\n", addonID, 276332cc6bcSAxel Dörfler flavorID); 27754187cc6Sbeveloper return B_OK; 27854187cc6Sbeveloper } 27954187cc6Sbeveloper 28034c72144SAxel Dörfler 28154187cc6Sbeveloper status_t 2829dec2310SAxel Dörfler BMediaRosterEx::LoadNodeConfiguration(media_addon_id addonID, int32 flavorID, 2839dec2310SAxel Dörfler BMessage *_msg) 28454187cc6Sbeveloper { 28534c72144SAxel Dörfler // TODO: fix this 2869dec2310SAxel Dörfler _msg->MakeEmpty(); // to be fully R5 compliant 2878b940bb4SStephan Aßmus printf("### BMediaRosterEx::LoadNodeConfiguration should load addon-id " 288332cc6bcSAxel Dörfler "%" B_PRId32 ", flavor-id %" B_PRId32 " config NOW!\n", addonID, 289332cc6bcSAxel Dörfler flavorID); 29054187cc6Sbeveloper return B_OK; 29154187cc6Sbeveloper } 29254187cc6Sbeveloper 29334c72144SAxel Dörfler 29454187cc6Sbeveloper status_t 2959dec2310SAxel Dörfler BMediaRosterEx::IncrementAddonFlavorInstancesCount(media_addon_id addonID, 2969dec2310SAxel Dörfler int32 flavorID) 29754187cc6Sbeveloper { 2989c3b4706SAxel Dörfler server_change_flavor_instances_count_request request; 2999c3b4706SAxel Dörfler server_change_flavor_instances_count_reply reply; 30073794717Sbeveloper 3019c3b4706SAxel Dörfler request.add_on_id = addonID; 3029dec2310SAxel Dörfler request.flavor_id = flavorID; 30373794717Sbeveloper request.delta = 1; 3049dec2310SAxel Dörfler request.team = BPrivate::current_team(); 3059c3b4706SAxel Dörfler return QueryServer(SERVER_CHANGE_FLAVOR_INSTANCES_COUNT, &request, 30634c72144SAxel Dörfler sizeof(request), &reply, sizeof(reply)); 30754187cc6Sbeveloper } 30854187cc6Sbeveloper 30934c72144SAxel Dörfler 31054187cc6Sbeveloper status_t 3119dec2310SAxel Dörfler BMediaRosterEx::DecrementAddonFlavorInstancesCount(media_addon_id addonID, 3129dec2310SAxel Dörfler int32 flavorID) 31354187cc6Sbeveloper { 3149c3b4706SAxel Dörfler server_change_flavor_instances_count_request request; 3159c3b4706SAxel Dörfler server_change_flavor_instances_count_reply reply; 31673794717Sbeveloper 3179c3b4706SAxel Dörfler request.add_on_id = addonID; 3189dec2310SAxel Dörfler request.flavor_id = flavorID; 31973794717Sbeveloper request.delta = -1; 3209dec2310SAxel Dörfler request.team = BPrivate::current_team(); 3219c3b4706SAxel Dörfler return QueryServer(SERVER_CHANGE_FLAVOR_INSTANCES_COUNT, &request, 32234c72144SAxel Dörfler sizeof(request), &reply, sizeof(reply)); 32354187cc6Sbeveloper } 32454187cc6Sbeveloper 32534c72144SAxel Dörfler 32654187cc6Sbeveloper status_t 3276aee58a4SJérôme Duval BMediaRosterEx::ReleaseNodeAll(const media_node& node) 3286aee58a4SJérôme Duval { 3296aee58a4SJérôme Duval CALLED(); 3306aee58a4SJérôme Duval if (IS_INVALID_NODE(node)) 3316aee58a4SJérôme Duval return B_MEDIA_BAD_NODE; 3326aee58a4SJérôme Duval 33384da57fdSAdrien Destugues if (node.kind & NODE_KIND_NO_REFCOUNTING) 3346aee58a4SJérôme Duval return B_OK; 3356aee58a4SJérôme Duval 3366aee58a4SJérôme Duval server_release_node_request request; 3376aee58a4SJérôme Duval server_release_node_reply reply; 3386aee58a4SJérôme Duval status_t rv; 3396aee58a4SJérôme Duval 3406aee58a4SJérôme Duval request.node = node; 3416aee58a4SJérôme Duval request.team = BPrivate::current_team(); 3426aee58a4SJérôme Duval 343332cc6bcSAxel Dörfler TRACE("BMediaRoster::ReleaseNodeAll, node %" B_PRId32 ", port %" B_PRId32 344332cc6bcSAxel Dörfler ", team %" B_PRId32 "\n", 3456aee58a4SJérôme Duval node.node, node.port, BPrivate::current_team()); 3466aee58a4SJérôme Duval 3476aee58a4SJérôme Duval rv = QueryServer(SERVER_RELEASE_NODE_ALL, &request, sizeof(request), &reply, 3486aee58a4SJérôme Duval sizeof(reply)); 3496aee58a4SJérôme Duval if (rv != B_OK) { 350c74afb57SJérôme Duval ERROR("BMediaRoster::ReleaseNodeAll failed to query media_server, " 351c74afb57SJérôme Duval "retrying local, node %" B_PRId32 ", port %" 352c74afb57SJérôme Duval B_PRId32 ", team %" B_PRId32 "!\n", node.node, node.port, 353c74afb57SJérôme Duval BPrivate::current_team()); 354c74afb57SJérôme Duval node_final_release_command command; 355c74afb57SJérôme Duval rv = SendToPort(node.port, NODE_FINAL_RELEASE, &command, 356c74afb57SJérôme Duval sizeof(command)); 357c74afb57SJérôme Duval if (rv != B_OK) { 358332cc6bcSAxel Dörfler ERROR("BMediaRoster::ReleaseNodeAll FAILED, node %" B_PRId32 ", port %" 359332cc6bcSAxel Dörfler B_PRId32 ", team %" B_PRId32 "!\n", node.node, node.port, 360332cc6bcSAxel Dörfler BPrivate::current_team()); 3616aee58a4SJérôme Duval } 362c74afb57SJérôme Duval } 3636aee58a4SJérôme Duval return rv; 3646aee58a4SJérôme Duval } 3656aee58a4SJérôme Duval 3666aee58a4SJérôme Duval 3676aee58a4SJérôme Duval status_t 36854187cc6Sbeveloper BMediaRosterEx::SetNodeCreator(media_node_id node, team_id creator) 36954187cc6Sbeveloper { 37054187cc6Sbeveloper server_set_node_creator_request request; 37154187cc6Sbeveloper server_set_node_creator_reply reply; 37254187cc6Sbeveloper 37354187cc6Sbeveloper request.node = node; 37454187cc6Sbeveloper request.creator = creator; 37534c72144SAxel Dörfler return QueryServer(SERVER_SET_NODE_CREATOR, &request, sizeof(request), 37634c72144SAxel Dörfler &reply, sizeof(reply)); 37754187cc6Sbeveloper } 37854187cc6Sbeveloper 37934c72144SAxel Dörfler 38054187cc6Sbeveloper status_t 38134c72144SAxel Dörfler BMediaRosterEx::GetNode(node_type type, media_node* out_node, 38234c72144SAxel Dörfler int32* out_input_id, BString* out_input_name) 38352a38012Sejakowatz { 38452a38012Sejakowatz if (out_node == NULL) 38552a38012Sejakowatz return B_BAD_VALUE; 38652a38012Sejakowatz 3878c6a6096Sbeveloper server_get_node_request request; 3888c6a6096Sbeveloper server_get_node_reply reply; 38952a38012Sejakowatz status_t rv; 39052a38012Sejakowatz 3918c6a6096Sbeveloper request.type = type; 3929dec2310SAxel Dörfler request.team = BPrivate::current_team(); 39334c72144SAxel Dörfler rv = QueryServer(SERVER_GET_NODE, &request, sizeof(request), &reply, 39434c72144SAxel Dörfler sizeof(reply)); 3958c6a6096Sbeveloper if (rv != B_OK) 3968c6a6096Sbeveloper return rv; 39752a38012Sejakowatz 39852a38012Sejakowatz *out_node = reply.node; 39952a38012Sejakowatz if (out_input_id) 40052a38012Sejakowatz *out_input_id = reply.input_id; 40152a38012Sejakowatz if (out_input_name) 40252a38012Sejakowatz *out_input_name = reply.input_name; 4038c6a6096Sbeveloper return rv; 40452a38012Sejakowatz } 40552a38012Sejakowatz 40634c72144SAxel Dörfler 4073620737cSbeveloper status_t 40834c72144SAxel Dörfler BMediaRosterEx::SetNode(node_type type, const media_node* node, 40934c72144SAxel Dörfler const dormant_node_info* info, const media_input* input) 41052a38012Sejakowatz { 4118c6a6096Sbeveloper server_set_node_request request; 4128c6a6096Sbeveloper server_set_node_reply reply; 41352a38012Sejakowatz 4148c6a6096Sbeveloper request.type = type; 41534c72144SAxel Dörfler request.use_node = node != NULL; 41634c72144SAxel Dörfler if (node != NULL) 4178c6a6096Sbeveloper request.node = *node; 41834c72144SAxel Dörfler request.use_dni = info != NULL; 41934c72144SAxel Dörfler if (info != NULL) 4208c6a6096Sbeveloper request.dni = *info; 42134c72144SAxel Dörfler request.use_input = input != NULL; 42234c72144SAxel Dörfler if (input != NULL) 4238c6a6096Sbeveloper request.input = *input; 42452a38012Sejakowatz 42534c72144SAxel Dörfler return QueryServer(SERVER_SET_NODE, &request, sizeof(request), &reply, 42634c72144SAxel Dörfler sizeof(reply)); 42752a38012Sejakowatz } 42852a38012Sejakowatz 42934c72144SAxel Dörfler 4303620737cSbeveloper status_t 4318b04ffc1Sbeveloper BMediaRosterEx::GetAllOutputs(const media_node& node, List<media_output>* list) 4323620737cSbeveloper { 4333620737cSbeveloper int32 cookie; 4343620737cSbeveloper status_t rv; 4353620737cSbeveloper status_t result; 4363620737cSbeveloper 437332cc6bcSAxel Dörfler PRINT(4, "BMediaRosterEx::GetAllOutputs() node %" B_PRId32 ", port %" 438332cc6bcSAxel Dörfler B_PRId32 "\n", node.node, node.port); 4395ac4fbd7Sbeveloper 44065b73ae4SMarcus Overhagen if (!(node.kind & B_BUFFER_PRODUCER)) { 441332cc6bcSAxel Dörfler ERROR("BMediaRosterEx::GetAllOutputs: node %" B_PRId32 " is not a " 44234c72144SAxel Dörfler "B_BUFFER_PRODUCER\n", node.node); 44365b73ae4SMarcus Overhagen return B_MEDIA_BAD_NODE; 44465b73ae4SMarcus Overhagen } 44565b73ae4SMarcus Overhagen 4463620737cSbeveloper result = B_OK; 4473620737cSbeveloper cookie = 0; 44876669a29Sbeveloper list->MakeEmpty(); 4493620737cSbeveloper for (;;) { 4503620737cSbeveloper producer_get_next_output_request request; 4513620737cSbeveloper producer_get_next_output_reply reply; 4523620737cSbeveloper request.cookie = cookie; 45334c72144SAxel Dörfler rv = QueryPort(node.port, PRODUCER_GET_NEXT_OUTPUT, &request, 45434c72144SAxel Dörfler sizeof(request), &reply, sizeof(reply)); 4553620737cSbeveloper if (rv != B_OK) 4563620737cSbeveloper break; 4573620737cSbeveloper cookie = reply.cookie; 45876669a29Sbeveloper if (!list->Insert(reply.output)) { 4595ac4fbd7Sbeveloper ERROR("GetAllOutputs: list->Insert failed\n"); 4603620737cSbeveloper result = B_ERROR; 4613620737cSbeveloper } 4625ac4fbd7Sbeveloper #if DEBUG >= 3 463332cc6bcSAxel Dörfler PRINT(3," next cookie %" B_PRId32 ", ", cookie); 4645ac4fbd7Sbeveloper PRINT_OUTPUT("output ", reply.output); 4655ac4fbd7Sbeveloper #endif 4663620737cSbeveloper } 4673620737cSbeveloper 4683620737cSbeveloper producer_dispose_output_cookie_request request; 4693620737cSbeveloper producer_dispose_output_cookie_reply reply; 47034c72144SAxel Dörfler QueryPort(node.port, PRODUCER_DISPOSE_OUTPUT_COOKIE, &request, 47134c72144SAxel Dörfler sizeof(request), &reply, sizeof(reply)); 4723620737cSbeveloper 4733620737cSbeveloper return result; 4743620737cSbeveloper } 4753620737cSbeveloper 47634c72144SAxel Dörfler 4773620737cSbeveloper status_t 4784d2d96e0Sbeveloper BMediaRosterEx::GetAllOutputs(BBufferProducer* node, List<media_output>* list) 4794d2d96e0Sbeveloper { 4804d2d96e0Sbeveloper int32 cookie; 4814d2d96e0Sbeveloper status_t result; 4824d2d96e0Sbeveloper 483332cc6bcSAxel Dörfler PRINT(4, "BMediaRosterEx::GetAllOutputs() (by pointer) node %" B_PRId32 484332cc6bcSAxel Dörfler ", port %" B_PRId32 "\n", node->ID(), node->ControlPort()); 4854d2d96e0Sbeveloper 4864d2d96e0Sbeveloper result = B_OK; 4874d2d96e0Sbeveloper cookie = 0; 4884d2d96e0Sbeveloper list->MakeEmpty(); 4894d2d96e0Sbeveloper for (;;) { 4904d2d96e0Sbeveloper media_output output; 4914d2d96e0Sbeveloper if (B_OK != node->GetNextOutput(&cookie, &output)) 4924d2d96e0Sbeveloper break; 4934d2d96e0Sbeveloper if (!list->Insert(output)) { 4944d2d96e0Sbeveloper ERROR("GetAllOutputs: list->Insert failed\n"); 4954d2d96e0Sbeveloper result = B_ERROR; 4964d2d96e0Sbeveloper } 4974d2d96e0Sbeveloper #if DEBUG >= 3 498332cc6bcSAxel Dörfler PRINT(3," next cookie %" B_PRId32 ", ", cookie); 4994d2d96e0Sbeveloper PRINT_OUTPUT("output ", output); 5004d2d96e0Sbeveloper #endif 5014d2d96e0Sbeveloper } 5024d2d96e0Sbeveloper node->DisposeOutputCookie(cookie); 5034d2d96e0Sbeveloper return result; 5044d2d96e0Sbeveloper } 5054d2d96e0Sbeveloper 50634c72144SAxel Dörfler 5074d2d96e0Sbeveloper status_t 5088b04ffc1Sbeveloper BMediaRosterEx::GetAllInputs(const media_node& node, List<media_input>* list) 5093620737cSbeveloper { 5103620737cSbeveloper int32 cookie; 5113620737cSbeveloper status_t rv; 5123620737cSbeveloper status_t result; 5133620737cSbeveloper 514332cc6bcSAxel Dörfler PRINT(4, "BMediaRosterEx::GetAllInputs() node %" B_PRId32 ", port %" 515332cc6bcSAxel Dörfler B_PRId32 "\n", node.node, node.port); 5165ac4fbd7Sbeveloper 51765b73ae4SMarcus Overhagen if (!(node.kind & B_BUFFER_CONSUMER)) { 518332cc6bcSAxel Dörfler ERROR("BMediaRosterEx::GetAllInputs: node %" B_PRId32 " is not a " 51934c72144SAxel Dörfler "B_BUFFER_CONSUMER\n", node.node); 52065b73ae4SMarcus Overhagen return B_MEDIA_BAD_NODE; 52165b73ae4SMarcus Overhagen } 52265b73ae4SMarcus Overhagen 5233620737cSbeveloper result = B_OK; 5243620737cSbeveloper cookie = 0; 52576669a29Sbeveloper list->MakeEmpty(); 5263620737cSbeveloper for (;;) { 5273620737cSbeveloper consumer_get_next_input_request request; 5283620737cSbeveloper consumer_get_next_input_reply reply; 5293620737cSbeveloper request.cookie = cookie; 53034c72144SAxel Dörfler rv = QueryPort(node.port, CONSUMER_GET_NEXT_INPUT, &request, 53134c72144SAxel Dörfler sizeof(request), &reply, sizeof(reply)); 5323620737cSbeveloper if (rv != B_OK) 5333620737cSbeveloper break; 5343620737cSbeveloper cookie = reply.cookie; 53576669a29Sbeveloper if (!list->Insert(reply.input)) { 5365ac4fbd7Sbeveloper ERROR("GetAllInputs: list->Insert failed\n"); 5373620737cSbeveloper result = B_ERROR; 5383620737cSbeveloper } 5395ac4fbd7Sbeveloper #if DEBUG >= 3 540332cc6bcSAxel Dörfler PRINT(3," next cookie %" B_PRId32 ", ", cookie); 5415ac4fbd7Sbeveloper PRINT_OUTPUT("input ", reply.input); 5425ac4fbd7Sbeveloper #endif 5433620737cSbeveloper } 5443620737cSbeveloper 5453620737cSbeveloper consumer_dispose_input_cookie_request request; 5463620737cSbeveloper consumer_dispose_input_cookie_reply reply; 54734c72144SAxel Dörfler QueryPort(node.port, CONSUMER_DISPOSE_INPUT_COOKIE, &request, 54834c72144SAxel Dörfler sizeof(request), &reply, sizeof(reply)); 5493620737cSbeveloper 5503620737cSbeveloper return result; 5513620737cSbeveloper } 5523620737cSbeveloper 55334c72144SAxel Dörfler 5543620737cSbeveloper status_t 5554d2d96e0Sbeveloper BMediaRosterEx::GetAllInputs(BBufferConsumer* node, List<media_input>* list) 5564d2d96e0Sbeveloper { 5574d2d96e0Sbeveloper int32 cookie; 5584d2d96e0Sbeveloper status_t result; 5594d2d96e0Sbeveloper 560332cc6bcSAxel Dörfler PRINT(4, "BMediaRosterEx::GetAllInputs() (by pointer) node %" B_PRId32 561332cc6bcSAxel Dörfler ", port %" B_PRId32 "\n", node->ID(), node->ControlPort()); 5624d2d96e0Sbeveloper 5634d2d96e0Sbeveloper result = B_OK; 5644d2d96e0Sbeveloper cookie = 0; 5654d2d96e0Sbeveloper list->MakeEmpty(); 5664d2d96e0Sbeveloper for (;;) { 5674d2d96e0Sbeveloper media_input input; 5684d2d96e0Sbeveloper if (B_OK != node->GetNextInput(&cookie, &input)) 5694d2d96e0Sbeveloper break; 5704d2d96e0Sbeveloper if (!list->Insert(input)) { 5714d2d96e0Sbeveloper ERROR("GetAllInputs: list->Insert failed\n"); 5724d2d96e0Sbeveloper result = B_ERROR; 5734d2d96e0Sbeveloper } 5744d2d96e0Sbeveloper #if DEBUG >= 3 575332cc6bcSAxel Dörfler PRINT(3," next cookie %" B_PRId32 ", ", cookie); 5764d2d96e0Sbeveloper PRINT_INPUT("input ", input); 5774d2d96e0Sbeveloper #endif 5784d2d96e0Sbeveloper } 5794d2d96e0Sbeveloper node->DisposeInputCookie(cookie); 5804d2d96e0Sbeveloper return result; 5814d2d96e0Sbeveloper } 5824d2d96e0Sbeveloper 58334c72144SAxel Dörfler 5844d2d96e0Sbeveloper status_t 5858b04ffc1Sbeveloper BMediaRosterEx::PublishOutputs(const media_node& node, List<media_output>* list) 5863620737cSbeveloper { 5873620737cSbeveloper server_publish_outputs_request request; 5883620737cSbeveloper server_publish_outputs_reply reply; 5893620737cSbeveloper media_output* output; 5903620737cSbeveloper media_output* outputs; 5913620737cSbeveloper int32 count; 592a7b41a96Sbeveloper status_t rv; 5933620737cSbeveloper 59476669a29Sbeveloper count = list->CountItems(); 595332cc6bcSAxel Dörfler TRACE("PublishOutputs: publishing %" B_PRId32 "\n", count); 5963620737cSbeveloper 5973620737cSbeveloper request.node = node; 5983620737cSbeveloper request.count = count; 5993620737cSbeveloper if (count > MAX_OUTPUTS) { 6003620737cSbeveloper void *start_addr; 6013620737cSbeveloper size_t size; 60240f36b03Sbeveloper size = ROUND_UP_TO_PAGE(count * sizeof(media_output)); 60334c72144SAxel Dörfler request.area = create_area("publish outputs", &start_addr, 60434c72144SAxel Dörfler B_ANY_ADDRESS, size, B_NO_LOCK, B_READ_AREA | B_WRITE_AREA); 6053620737cSbeveloper if (request.area < B_OK) { 606332cc6bcSAxel Dörfler ERROR("PublishOutputs: failed to create area, %#" B_PRIx32 "\n", 60734c72144SAxel Dörfler request.area); 6083620737cSbeveloper return (status_t)request.area; 6093620737cSbeveloper } 6103620737cSbeveloper outputs = static_cast<media_output *>(start_addr); 6113620737cSbeveloper } else { 6123620737cSbeveloper request.area = -1; 6133620737cSbeveloper outputs = request.outputs; 6143620737cSbeveloper } 615332cc6bcSAxel Dörfler TRACE("PublishOutputs: area %" B_PRId32 "\n", request.area); 6163620737cSbeveloper 61776669a29Sbeveloper int i; 61876669a29Sbeveloper for (i = 0, list->Rewind(); list->GetNext(&output); i++) { 61976669a29Sbeveloper ASSERT(i < count); 6203620737cSbeveloper outputs[i] = *output; 6213620737cSbeveloper } 6223620737cSbeveloper 62334c72144SAxel Dörfler rv = QueryServer(SERVER_PUBLISH_OUTPUTS, &request, sizeof(request), 62434c72144SAxel Dörfler &reply, sizeof(reply)); 625a7b41a96Sbeveloper 626a7b41a96Sbeveloper if (request.area != -1) 627a7b41a96Sbeveloper delete_area(request.area); 628a7b41a96Sbeveloper 629a7b41a96Sbeveloper return rv; 6303620737cSbeveloper } 6313620737cSbeveloper 63234c72144SAxel Dörfler 6333620737cSbeveloper status_t 6348b04ffc1Sbeveloper BMediaRosterEx::PublishInputs(const media_node& node, List<media_input>* list) 6353620737cSbeveloper { 6363620737cSbeveloper server_publish_inputs_request request; 6373620737cSbeveloper server_publish_inputs_reply reply; 6383620737cSbeveloper media_input* input; 6393620737cSbeveloper media_input* inputs; 6403620737cSbeveloper int32 count; 641a7b41a96Sbeveloper status_t rv; 6423620737cSbeveloper 64376669a29Sbeveloper count = list->CountItems(); 644332cc6bcSAxel Dörfler TRACE("PublishInputs: publishing %" B_PRId32 "\n", count); 6453620737cSbeveloper 6463620737cSbeveloper request.node = node; 6473620737cSbeveloper request.count = count; 6483620737cSbeveloper if (count > MAX_INPUTS) { 6493620737cSbeveloper void* start_addr; 6503620737cSbeveloper size_t size; 65140f36b03Sbeveloper size = ROUND_UP_TO_PAGE(count * sizeof(media_input)); 65234c72144SAxel Dörfler request.area = create_area("publish inputs", &start_addr, 65334c72144SAxel Dörfler B_ANY_ADDRESS, size, B_NO_LOCK, B_READ_AREA | B_WRITE_AREA); 6543620737cSbeveloper if (request.area < B_OK) { 655332cc6bcSAxel Dörfler ERROR("PublishInputs: failed to create area, %#" B_PRIx32 "\n", 656332cc6bcSAxel Dörfler request.area); 6573620737cSbeveloper return (status_t)request.area; 6583620737cSbeveloper } 6593620737cSbeveloper inputs = static_cast<media_input *>(start_addr); 6603620737cSbeveloper } else { 6613620737cSbeveloper request.area = -1; 6623620737cSbeveloper inputs = request.inputs; 6633620737cSbeveloper } 664332cc6bcSAxel Dörfler TRACE("PublishInputs: area %" B_PRId32 "\n", request.area); 6653620737cSbeveloper 66676669a29Sbeveloper int i; 66776669a29Sbeveloper for (i = 0, list->Rewind(); list->GetNext(&input); i++) { 66876669a29Sbeveloper ASSERT(i < count); 6693620737cSbeveloper inputs[i] = *input; 6703620737cSbeveloper } 6713620737cSbeveloper 67234c72144SAxel Dörfler rv = QueryServer(SERVER_PUBLISH_INPUTS, &request, sizeof(request), 67334c72144SAxel Dörfler &reply, sizeof(reply)); 674a7b41a96Sbeveloper 675a7b41a96Sbeveloper if (request.area != -1) 676a7b41a96Sbeveloper delete_area(request.area); 677a7b41a96Sbeveloper 678a7b41a96Sbeveloper return rv; 6793620737cSbeveloper } 6803620737cSbeveloper 68134c72144SAxel Dörfler 68234c72144SAxel Dörfler BTimeSource* 683f4ec236cSAxel Dörfler BMediaRosterEx::MakeTimeSourceObject(media_node_id timeSourceID) 68434c72144SAxel Dörfler { 68534c72144SAxel Dörfler media_node clone; 686f4ec236cSAxel Dörfler status_t status = GetNodeFor(timeSourceID, &clone); 687f4ec236cSAxel Dörfler if (status != B_OK) { 688f4ec236cSAxel Dörfler ERROR("BMediaRosterEx::MakeTimeSourceObject: GetNodeFor failed: %s\n", 689f4ec236cSAxel Dörfler strerror(status)); 69034c72144SAxel Dörfler return NULL; 69134c72144SAxel Dörfler } 69234c72144SAxel Dörfler 693f4ec236cSAxel Dörfler BTimeSource* source = gTimeSourceObjectManager->GetTimeSource(clone); 69434c72144SAxel Dörfler if (source == NULL) { 69534c72144SAxel Dörfler ERROR("BMediaRosterEx::MakeTimeSourceObject: GetTimeSource failed\n"); 69634c72144SAxel Dörfler return NULL; 69734c72144SAxel Dörfler } 69834c72144SAxel Dörfler 69934c72144SAxel Dörfler // TODO: release? 70034c72144SAxel Dörfler ReleaseNode(clone); 70134c72144SAxel Dörfler 70234c72144SAxel Dörfler return source; 70334c72144SAxel Dörfler } 70434c72144SAxel Dörfler 70534c72144SAxel Dörfler 70634c72144SAxel Dörfler // #pragma mark - public BMediaRoster 70734c72144SAxel Dörfler 70852a38012Sejakowatz 70952a38012Sejakowatz status_t 71034c72144SAxel Dörfler BMediaRoster::GetVideoInput(media_node* _node) 71152a38012Sejakowatz { 71252a38012Sejakowatz CALLED(); 71334c72144SAxel Dörfler return MediaRosterEx(this)->GetNode(VIDEO_INPUT, _node); 71452a38012Sejakowatz } 71552a38012Sejakowatz 71652a38012Sejakowatz 71752a38012Sejakowatz status_t 71834c72144SAxel Dörfler BMediaRoster::GetAudioInput(media_node* _node) 71952a38012Sejakowatz { 72052a38012Sejakowatz CALLED(); 72134c72144SAxel Dörfler return MediaRosterEx(this)->GetNode(AUDIO_INPUT, _node); 72252a38012Sejakowatz } 72352a38012Sejakowatz 72452a38012Sejakowatz 72552a38012Sejakowatz status_t 72634c72144SAxel Dörfler BMediaRoster::GetVideoOutput(media_node* _node) 72752a38012Sejakowatz { 72852a38012Sejakowatz CALLED(); 72934c72144SAxel Dörfler return MediaRosterEx(this)->GetNode(VIDEO_OUTPUT, _node); 73052a38012Sejakowatz } 73152a38012Sejakowatz 73252a38012Sejakowatz 73352a38012Sejakowatz status_t 73434c72144SAxel Dörfler BMediaRoster::GetAudioMixer(media_node* _node) 73552a38012Sejakowatz { 73652a38012Sejakowatz CALLED(); 73734c72144SAxel Dörfler return MediaRosterEx(this)->GetNode(AUDIO_MIXER, _node); 73852a38012Sejakowatz } 73952a38012Sejakowatz 74052a38012Sejakowatz 74152a38012Sejakowatz status_t 74234c72144SAxel Dörfler BMediaRoster::GetAudioOutput(media_node* _node) 74352a38012Sejakowatz { 74452a38012Sejakowatz CALLED(); 74534c72144SAxel Dörfler return MediaRosterEx(this)->GetNode(AUDIO_OUTPUT, _node); 74652a38012Sejakowatz } 74752a38012Sejakowatz 74852a38012Sejakowatz 74952a38012Sejakowatz status_t 75034c72144SAxel Dörfler BMediaRoster::GetAudioOutput(media_node* _node, int32* _inputID, 75134c72144SAxel Dörfler BString* _inputName) 75252a38012Sejakowatz { 75352a38012Sejakowatz CALLED(); 75434c72144SAxel Dörfler return MediaRosterEx(this)->GetNode(AUDIO_OUTPUT_EX, _node, _inputID, 75534c72144SAxel Dörfler _inputName); 75652a38012Sejakowatz } 75752a38012Sejakowatz 75852a38012Sejakowatz 75952a38012Sejakowatz status_t 76034c72144SAxel Dörfler BMediaRoster::GetTimeSource(media_node* _node) 76152a38012Sejakowatz { 76252a38012Sejakowatz CALLED(); 76386bce45bSbeveloper status_t rv; 76486bce45bSbeveloper 76534c72144SAxel Dörfler // TODO: need to do this in a nicer way. 76686bce45bSbeveloper 76734c72144SAxel Dörfler rv = MediaRosterEx(this)->GetNode(TIME_SOURCE, _node); 76886bce45bSbeveloper if (rv != B_OK) 76986bce45bSbeveloper return rv; 77086bce45bSbeveloper 77186bce45bSbeveloper // We don't do reference counting for timesources, that's why we 77286bce45bSbeveloper // release the node immediately. 77334c72144SAxel Dörfler ReleaseNode(*_node); 77486bce45bSbeveloper 77586bce45bSbeveloper // we need to remember to not use this node with server side reference counting 77634c72144SAxel Dörfler _node->kind |= NODE_KIND_NO_REFCOUNTING; 77786bce45bSbeveloper return B_OK; 77852a38012Sejakowatz } 77952a38012Sejakowatz 78052a38012Sejakowatz 78152a38012Sejakowatz status_t 78252a38012Sejakowatz BMediaRoster::SetVideoInput(const media_node& producer) 78352a38012Sejakowatz { 78452a38012Sejakowatz CALLED(); 7858b04ffc1Sbeveloper return MediaRosterEx(this)->SetNode(VIDEO_INPUT, &producer); 78652a38012Sejakowatz } 78752a38012Sejakowatz 78852a38012Sejakowatz 78952a38012Sejakowatz status_t 79052a38012Sejakowatz BMediaRoster::SetVideoInput(const dormant_node_info& producer) 79152a38012Sejakowatz { 79252a38012Sejakowatz CALLED(); 7938b04ffc1Sbeveloper return MediaRosterEx(this)->SetNode(VIDEO_INPUT, NULL, &producer); 79452a38012Sejakowatz } 79552a38012Sejakowatz 79652a38012Sejakowatz 79752a38012Sejakowatz status_t 79852a38012Sejakowatz BMediaRoster::SetAudioInput(const media_node& producer) 79952a38012Sejakowatz { 80052a38012Sejakowatz CALLED(); 8018b04ffc1Sbeveloper return MediaRosterEx(this)->SetNode(AUDIO_INPUT, &producer); 80252a38012Sejakowatz } 80352a38012Sejakowatz 80452a38012Sejakowatz 80552a38012Sejakowatz status_t 80652a38012Sejakowatz BMediaRoster::SetAudioInput(const dormant_node_info& producer) 80752a38012Sejakowatz { 80852a38012Sejakowatz CALLED(); 8098b04ffc1Sbeveloper return MediaRosterEx(this)->SetNode(AUDIO_INPUT, NULL, &producer); 81052a38012Sejakowatz } 81152a38012Sejakowatz 81252a38012Sejakowatz 81352a38012Sejakowatz status_t 81452a38012Sejakowatz BMediaRoster::SetVideoOutput(const media_node& consumer) 81552a38012Sejakowatz { 81652a38012Sejakowatz CALLED(); 8178b04ffc1Sbeveloper return MediaRosterEx(this)->SetNode(VIDEO_OUTPUT, &consumer); 81852a38012Sejakowatz } 81952a38012Sejakowatz 82052a38012Sejakowatz 82152a38012Sejakowatz status_t 82252a38012Sejakowatz BMediaRoster::SetVideoOutput(const dormant_node_info& consumer) 82352a38012Sejakowatz { 82452a38012Sejakowatz CALLED(); 8258b04ffc1Sbeveloper return MediaRosterEx(this)->SetNode(VIDEO_OUTPUT, NULL, &consumer); 82652a38012Sejakowatz } 82752a38012Sejakowatz 82852a38012Sejakowatz 82952a38012Sejakowatz status_t 83052a38012Sejakowatz BMediaRoster::SetAudioOutput(const media_node& consumer) 83152a38012Sejakowatz { 83252a38012Sejakowatz CALLED(); 8338b04ffc1Sbeveloper return MediaRosterEx(this)->SetNode(AUDIO_OUTPUT, &consumer); 83452a38012Sejakowatz } 83552a38012Sejakowatz 83652a38012Sejakowatz 83752a38012Sejakowatz status_t 83834c72144SAxel Dörfler BMediaRoster::SetAudioOutput(const media_input& input) 83952a38012Sejakowatz { 84052a38012Sejakowatz CALLED(); 84134c72144SAxel Dörfler return MediaRosterEx(this)->SetNode(AUDIO_OUTPUT, NULL, NULL, &input); 84252a38012Sejakowatz } 84352a38012Sejakowatz 84452a38012Sejakowatz 84552a38012Sejakowatz status_t 84652a38012Sejakowatz BMediaRoster::SetAudioOutput(const dormant_node_info& consumer) 84752a38012Sejakowatz { 84852a38012Sejakowatz CALLED(); 8498b04ffc1Sbeveloper return MediaRosterEx(this)->SetNode(AUDIO_OUTPUT, NULL, &consumer); 85052a38012Sejakowatz } 85152a38012Sejakowatz 85252a38012Sejakowatz 85352a38012Sejakowatz status_t 85434c72144SAxel Dörfler BMediaRoster::GetNodeFor(media_node_id node, media_node* clone) 85552a38012Sejakowatz { 8569e9417d2Sbeveloper CALLED(); 8579e9417d2Sbeveloper if (clone == NULL) 8589e9417d2Sbeveloper return B_BAD_VALUE; 85965b73ae4SMarcus Overhagen if (IS_INVALID_NODEID(node)) 8609e9417d2Sbeveloper return B_MEDIA_BAD_NODE; 8619e9417d2Sbeveloper 8629e9417d2Sbeveloper server_get_node_for_request request; 8639e9417d2Sbeveloper server_get_node_for_reply reply; 8649e9417d2Sbeveloper status_t rv; 8659e9417d2Sbeveloper 8669dec2310SAxel Dörfler request.node_id = node; 8679dec2310SAxel Dörfler request.team = BPrivate::current_team(); 8689e9417d2Sbeveloper 86934c72144SAxel Dörfler rv = QueryServer(SERVER_GET_NODE_FOR, &request, sizeof(request), &reply, 87034c72144SAxel Dörfler sizeof(reply)); 8719e9417d2Sbeveloper if (rv != B_OK) 8729e9417d2Sbeveloper return rv; 8739e9417d2Sbeveloper 8749e9417d2Sbeveloper *clone = reply.clone; 8759e9417d2Sbeveloper return B_OK; 87652a38012Sejakowatz } 87752a38012Sejakowatz 87852a38012Sejakowatz 87952a38012Sejakowatz status_t 88052a38012Sejakowatz BMediaRoster::GetSystemTimeSource(media_node* clone) 88152a38012Sejakowatz { 88252a38012Sejakowatz CALLED(); 88386bce45bSbeveloper status_t rv; 88486bce45bSbeveloper 88534c72144SAxel Dörfler // TODO: need to do this in a nicer way. 88686bce45bSbeveloper 88786bce45bSbeveloper rv = MediaRosterEx(this)->GetNode(SYSTEM_TIME_SOURCE, clone); 88886bce45bSbeveloper if (rv != B_OK) 88986bce45bSbeveloper return rv; 89086bce45bSbeveloper 89186bce45bSbeveloper // We don't do reference counting for timesources, that's why we 89286bce45bSbeveloper // release the node immediately. 89386bce45bSbeveloper ReleaseNode(*clone); 89486bce45bSbeveloper 89534c72144SAxel Dörfler // we need to remember to not use this node with server side reference 89634c72144SAxel Dörfler // counting 89786bce45bSbeveloper clone->kind |= NODE_KIND_NO_REFCOUNTING; 89886bce45bSbeveloper 89986bce45bSbeveloper return B_OK; 90052a38012Sejakowatz } 90152a38012Sejakowatz 90252a38012Sejakowatz 90352a38012Sejakowatz status_t 90452a38012Sejakowatz BMediaRoster::ReleaseNode(const media_node& node) 90552a38012Sejakowatz { 9069e9417d2Sbeveloper CALLED(); 90740f36b03Sbeveloper if (IS_INVALID_NODE(node)) 9089e9417d2Sbeveloper return B_MEDIA_BAD_NODE; 90952a38012Sejakowatz 91086bce45bSbeveloper if (node.kind & NODE_KIND_NO_REFCOUNTING) { 911cb2c4f8dSAdrien Destugues TRACE("BMediaRoster::ReleaseNode, trying to release reference " 912332cc6bcSAxel Dörfler "counting disabled timesource, node %" B_PRId32 ", port %" B_PRId32 913332cc6bcSAxel Dörfler ", team %" B_PRId32 "\n", node.node, node.port, 914332cc6bcSAxel Dörfler BPrivate::current_team()); 91586bce45bSbeveloper return B_OK; 91686bce45bSbeveloper } 91786bce45bSbeveloper 9189e9417d2Sbeveloper server_release_node_request request; 9199e9417d2Sbeveloper server_release_node_reply reply; 920cf4e2277Sbeveloper status_t rv; 9219e9417d2Sbeveloper 9229e9417d2Sbeveloper request.node = node; 9239dec2310SAxel Dörfler request.team = BPrivate::current_team(); 9249e9417d2Sbeveloper 925332cc6bcSAxel Dörfler TRACE("BMediaRoster::ReleaseNode, node %" B_PRId32 ", port %" B_PRId32 926332cc6bcSAxel Dörfler ", team %" B_PRId32 "\n", node.node, node.port, 927332cc6bcSAxel Dörfler BPrivate::current_team()); 928cf4e2277Sbeveloper 92934c72144SAxel Dörfler rv = QueryServer(SERVER_RELEASE_NODE, &request, sizeof(request), &reply, 93034c72144SAxel Dörfler sizeof(reply)); 931cf4e2277Sbeveloper if (rv != B_OK) { 932332cc6bcSAxel Dörfler ERROR("BMediaRoster::ReleaseNode FAILED, node %" B_PRId32 ", port %" 933332cc6bcSAxel Dörfler B_PRId32 ", team %" B_PRId32 "!\n", node.node, node.port, 934332cc6bcSAxel Dörfler BPrivate::current_team()); 935cf4e2277Sbeveloper } 936cf4e2277Sbeveloper return rv; 9379e9417d2Sbeveloper } 93852a38012Sejakowatz 93934c72144SAxel Dörfler 94052a38012Sejakowatz BTimeSource* 94134c72144SAxel Dörfler BMediaRoster::MakeTimeSourceFor(const media_node& forNode) 94252a38012Sejakowatz { 943f180ef79Sbeveloper // MakeTimeSourceFor() returns a BTimeSource object 944f180ef79Sbeveloper // corresponding to the specified node's time source. 945f180ef79Sbeveloper 946835140c8Sbeveloper CALLED(); 947f180ef79Sbeveloper 94834c72144SAxel Dörfler if (IS_SYSTEM_TIMESOURCE(forNode)) { 949f180ef79Sbeveloper // special handling for the system time source 95034c72144SAxel Dörfler TRACE("BMediaRoster::MakeTimeSourceFor, asked for system time " 95134c72144SAxel Dörfler "source\n"); 95234c72144SAxel Dörfler return MediaRosterEx(this)->MakeTimeSourceObject( 95334c72144SAxel Dörfler NODE_SYSTEM_TIMESOURCE_ID); 954f180ef79Sbeveloper } 955f180ef79Sbeveloper 95634c72144SAxel Dörfler if (IS_INVALID_NODE(forNode)) { 957332cc6bcSAxel Dörfler ERROR("BMediaRoster::MakeTimeSourceFor: for_node invalid, node %" 958332cc6bcSAxel Dörfler B_PRId32 ", port %" B_PRId32 ", kinds 0x%" B_PRIx32 "\n", 959332cc6bcSAxel Dörfler forNode.node, forNode.port, forNode.kind); 9605917dd5bSbeveloper return NULL; 9610e21b167Sbeveloper } 9620e21b167Sbeveloper 963332cc6bcSAxel Dörfler TRACE("BMediaRoster::MakeTimeSourceFor: node %" B_PRId32 " enter\n", 964332cc6bcSAxel Dörfler forNode.node); 9655917dd5bSbeveloper 9665917dd5bSbeveloper node_get_timesource_request request; 9675917dd5bSbeveloper node_get_timesource_reply reply; 9685917dd5bSbeveloper BTimeSource *source; 9695917dd5bSbeveloper status_t rv; 9705917dd5bSbeveloper 97192e575c1Sbeveloper // ask the node to get it's current timesource id 97234c72144SAxel Dörfler rv = QueryPort(forNode.port, NODE_GET_TIMESOURCE, &request, 97334c72144SAxel Dörfler sizeof(request), &reply, sizeof(reply)); 9745917dd5bSbeveloper if (rv != B_OK) { 9755ac4fbd7Sbeveloper ERROR("BMediaRoster::MakeTimeSourceFor: request failed\n"); 9765917dd5bSbeveloper return NULL; 9775917dd5bSbeveloper } 9785917dd5bSbeveloper 9795917dd5bSbeveloper source = MediaRosterEx(this)->MakeTimeSourceObject(reply.timesource_id); 9805917dd5bSbeveloper 981332cc6bcSAxel Dörfler TRACE("BMediaRoster::MakeTimeSourceFor: node %" B_PRId32 " leave\n", 982332cc6bcSAxel Dörfler forNode.node); 983287f7492Sbeveloper 984835140c8Sbeveloper return source; 98552a38012Sejakowatz } 98652a38012Sejakowatz 98752a38012Sejakowatz 98852a38012Sejakowatz status_t 98934c72144SAxel Dörfler BMediaRoster::Connect(const media_source& from, const media_destination& to, 99034c72144SAxel Dörfler media_format* _format, media_output* _output, media_input* _input) 99152a38012Sejakowatz { 99234c72144SAxel Dörfler return BMediaRoster::Connect(from, to, _format, _output, _input, 0); 993eae26d3dSbeveloper } 994eae26d3dSbeveloper 995eae26d3dSbeveloper 996eae26d3dSbeveloper status_t 99734c72144SAxel Dörfler BMediaRoster::Connect(const media_source& from, const media_destination& to, 99834c72144SAxel Dörfler media_format* io_format, media_output* out_output, media_input* out_input, 99934c72144SAxel Dörfler uint32 in_flags, void* _reserved) 1000eae26d3dSbeveloper { 100152a38012Sejakowatz CALLED(); 100252a38012Sejakowatz if (io_format == NULL || out_output == NULL || out_input == NULL) 100352a38012Sejakowatz return B_BAD_VALUE; 100440f36b03Sbeveloper if (IS_INVALID_SOURCE(from)) { 10055ac4fbd7Sbeveloper ERROR("BMediaRoster::Connect: media_source invalid\n"); 100652a38012Sejakowatz return B_MEDIA_BAD_SOURCE; 10079e9417d2Sbeveloper } 100840f36b03Sbeveloper if (IS_INVALID_DESTINATION(to)) { 10095ac4fbd7Sbeveloper ERROR("BMediaRoster::Connect: media_destination invalid\n"); 101052a38012Sejakowatz return B_MEDIA_BAD_DESTINATION; 10119e9417d2Sbeveloper } 101252a38012Sejakowatz 101352a38012Sejakowatz status_t rv; 101465b73ae4SMarcus Overhagen 101565b73ae4SMarcus Overhagen // find the output and input nodes 101634c72144SAxel Dörfler // TODO: isn't there a easier way? 101765b73ae4SMarcus Overhagen media_node sourcenode; 101865b73ae4SMarcus Overhagen media_node destnode; 101965b73ae4SMarcus Overhagen rv = GetNodeFor(NodeIDFor(from.port), &sourcenode); 102065b73ae4SMarcus Overhagen if (rv != B_OK) { 1021332cc6bcSAxel Dörfler ERROR("BMediaRoster::Connect: Can't find source node for port %" 1022332cc6bcSAxel Dörfler B_PRId32 "\n", from.port); 102365b73ae4SMarcus Overhagen return B_MEDIA_BAD_SOURCE; 102465b73ae4SMarcus Overhagen } 102565b73ae4SMarcus Overhagen ReleaseNode(sourcenode); 102665b73ae4SMarcus Overhagen rv = GetNodeFor(NodeIDFor(to.port), &destnode); 102765b73ae4SMarcus Overhagen if (rv != B_OK) { 102834c72144SAxel Dörfler ERROR("BMediaRoster::Connect: Can't find destination node for port " 1029332cc6bcSAxel Dörfler "%" B_PRId32 "\n", to.port); 103065b73ae4SMarcus Overhagen return B_MEDIA_BAD_DESTINATION; 103165b73ae4SMarcus Overhagen } 103265b73ae4SMarcus Overhagen ReleaseNode(destnode); 103365b73ae4SMarcus Overhagen 103465b73ae4SMarcus Overhagen if (!(sourcenode.kind & B_BUFFER_PRODUCER)) { 1035332cc6bcSAxel Dörfler ERROR("BMediaRoster::Connect: source node %" B_PRId32 " is not a " 103634c72144SAxel Dörfler "B_BUFFER_PRODUCER\n", sourcenode.node); 103765b73ae4SMarcus Overhagen return B_MEDIA_BAD_SOURCE; 103865b73ae4SMarcus Overhagen } 103965b73ae4SMarcus Overhagen if (!(destnode.kind & B_BUFFER_CONSUMER)) { 1040332cc6bcSAxel Dörfler ERROR("BMediaRoster::Connect: destination node %" B_PRId32 " is not a " 104134c72144SAxel Dörfler "B_BUFFER_CONSUMER\n", destnode.node); 104265b73ae4SMarcus Overhagen return B_MEDIA_BAD_DESTINATION; 104365b73ae4SMarcus Overhagen } 104465b73ae4SMarcus Overhagen 10458c6a6096Sbeveloper producer_format_proposal_request request1; 10468c6a6096Sbeveloper producer_format_proposal_reply reply1; 104752a38012Sejakowatz 104834c72144SAxel Dörfler PRINT_FORMAT("BMediaRoster::Connect calling " 104934c72144SAxel Dörfler "BBufferProducer::FormatProposal with format ", *io_format); 105069983609Sbeveloper 105152a38012Sejakowatz // BBufferProducer::FormatProposal 10528c6a6096Sbeveloper request1.output = from; 10538c6a6096Sbeveloper request1.format = *io_format; 105434c72144SAxel Dörfler rv = QueryPort(from.port, PRODUCER_FORMAT_PROPOSAL, &request1, 105534c72144SAxel Dörfler sizeof(request1), &reply1, sizeof(reply1)); 10568c6a6096Sbeveloper if (rv != B_OK) { 105734c72144SAxel Dörfler ERROR("BMediaRoster::Connect: aborted after " 1058332cc6bcSAxel Dörfler "BBufferProducer::FormatProposal, status = %#" B_PRIx32 "\n",rv); 105952a38012Sejakowatz return rv; 106052a38012Sejakowatz } 10618c6a6096Sbeveloper // reply1.format now contains the format proposed by the producer 10628c6a6096Sbeveloper 10638c6a6096Sbeveloper consumer_accept_format_request request2; 10648c6a6096Sbeveloper consumer_accept_format_reply reply2; 10658c6a6096Sbeveloper 106634c72144SAxel Dörfler PRINT_FORMAT("BMediaRoster::Connect calling " 106734c72144SAxel Dörfler "BBufferConsumer::AcceptFormat with format ", reply1.format); 106869983609Sbeveloper 10698c6a6096Sbeveloper // BBufferConsumer::AcceptFormat 10708c6a6096Sbeveloper request2.dest = to; 10718c6a6096Sbeveloper request2.format = reply1.format; 107234c72144SAxel Dörfler rv = QueryPort(to.port, CONSUMER_ACCEPT_FORMAT, &request2, 107334c72144SAxel Dörfler sizeof(request2), &reply2, sizeof(reply2)); 10748c6a6096Sbeveloper if (rv != B_OK) { 107534c72144SAxel Dörfler ERROR("BMediaRoster::Connect: aborted after " 1076332cc6bcSAxel Dörfler "BBufferConsumer::AcceptFormat, status = %#" B_PRIx32 "\n",rv); 10778c6a6096Sbeveloper return rv; 10788c6a6096Sbeveloper } 10798c6a6096Sbeveloper // reply2.format now contains the format accepted by the consumer 10808c6a6096Sbeveloper 10818c6a6096Sbeveloper // BBufferProducer::PrepareToConnect 10828c6a6096Sbeveloper producer_prepare_to_connect_request request3; 10838c6a6096Sbeveloper producer_prepare_to_connect_reply reply3; 10848c6a6096Sbeveloper 108534c72144SAxel Dörfler PRINT_FORMAT("BMediaRoster::Connect calling " 108634c72144SAxel Dörfler "BBufferProducer::PrepareToConnect with format", reply2.format); 108769983609Sbeveloper 10888c6a6096Sbeveloper request3.source = from; 10898c6a6096Sbeveloper request3.destination = to; 10908c6a6096Sbeveloper request3.format = reply2.format; 109134c72144SAxel Dörfler strcpy(request3.name, "XXX some default name"); // TODO: fix this 109234c72144SAxel Dörfler rv = QueryPort(from.port, PRODUCER_PREPARE_TO_CONNECT, &request3, 109334c72144SAxel Dörfler sizeof(request3), &reply3, sizeof(reply3)); 10948c6a6096Sbeveloper if (rv != B_OK) { 109534c72144SAxel Dörfler ERROR("BMediaRoster::Connect: aborted after " 1096332cc6bcSAxel Dörfler "BBufferProducer::PrepareToConnect, status = %#" B_PRIx32 "\n", rv); 10978c6a6096Sbeveloper return rv; 10988c6a6096Sbeveloper } 10998c6a6096Sbeveloper // reply3.format is still our pretty media format 11008c6a6096Sbeveloper // reply3.out_source the real source to be used for the connection 110134c72144SAxel Dörfler // reply3.name the name BBufferConsumer::Connected will see in the 110234c72144SAxel Dörfler // outInput->name argument 11038c6a6096Sbeveloper 11048c6a6096Sbeveloper // BBufferConsumer::Connected 11058c6a6096Sbeveloper consumer_connected_request request4; 11068c6a6096Sbeveloper consumer_connected_reply reply4; 11078c6a6096Sbeveloper status_t con_status; 11088c6a6096Sbeveloper 110934c72144SAxel Dörfler PRINT_FORMAT("BMediaRoster::Connect calling BBufferConsumer::Connected() " 111034c72144SAxel Dörfler "with format ", reply3.format); 111169983609Sbeveloper 111269983609Sbeveloper request4.input.node = destnode; 111369983609Sbeveloper request4.input.source = reply3.out_source; 111469983609Sbeveloper request4.input.destination = to; 111569983609Sbeveloper request4.input.format = reply3.format; 111669983609Sbeveloper strcpy(request4.input.name, reply3.name); 111769983609Sbeveloper 111834c72144SAxel Dörfler con_status = QueryPort(to.port, CONSUMER_CONNECTED, &request4, 111934c72144SAxel Dörfler sizeof(request4), &reply4, sizeof(reply4)); 11208c6a6096Sbeveloper if (con_status != B_OK) { 112134c72144SAxel Dörfler ERROR("BMediaRoster::Connect: aborting after " 1122332cc6bcSAxel Dörfler "BBufferConsumer::Connected, status = %#" B_PRIx32 "\n", 1123332cc6bcSAxel Dörfler con_status); 11248c6a6096Sbeveloper // we do NOT return here! 11258c6a6096Sbeveloper } 112634c72144SAxel Dörfler // con_status contains the status code to be supplied to 112734c72144SAxel Dörfler // BBufferProducer::Connect's status argument 112834c72144SAxel Dörfler // reply4.input contains the media_input that describes the connection 112934c72144SAxel Dörfler // from the consumer point of view 11308c6a6096Sbeveloper 11318c6a6096Sbeveloper // BBufferProducer::Connect 11328c6a6096Sbeveloper producer_connect_request request5; 11338c6a6096Sbeveloper producer_connect_reply reply5; 11348c6a6096Sbeveloper 113534c72144SAxel Dörfler PRINT_FORMAT("BMediaRoster::Connect calling BBufferProducer::Connect with " 113634c72144SAxel Dörfler "format ", reply4.input.format); 113769983609Sbeveloper 11388c6a6096Sbeveloper request5.error = con_status; 11398c6a6096Sbeveloper request5.source = reply3.out_source; 11408c6a6096Sbeveloper request5.destination = reply4.input.destination; 114169983609Sbeveloper request5.format = reply4.input.format; 11428c6a6096Sbeveloper strcpy(request5.name, reply4.input.name); 114334c72144SAxel Dörfler rv = QueryPort(reply4.input.source.port, PRODUCER_CONNECT, &request5, 114434c72144SAxel Dörfler sizeof(request5), &reply5, sizeof(reply5)); 11458c6a6096Sbeveloper if (con_status != B_OK) { 11465ac4fbd7Sbeveloper ERROR("BMediaRoster::Connect: aborted\n"); 11478c6a6096Sbeveloper return con_status; 11488c6a6096Sbeveloper } 11498c6a6096Sbeveloper if (rv != B_OK) { 115034c72144SAxel Dörfler ERROR("BMediaRoster::Connect: aborted after BBufferProducer::Connect()" 1151332cc6bcSAxel Dörfler ", status = %#" B_PRIx32 "\n", rv); 11528c6a6096Sbeveloper return rv; 11538c6a6096Sbeveloper } 11548c6a6096Sbeveloper // reply5.name contains the name assigned to the connection by the producer 11558c6a6096Sbeveloper 11568c6a6096Sbeveloper // initilize connection info 115769983609Sbeveloper *io_format = reply4.input.format; 11588c6a6096Sbeveloper *out_input = reply4.input; 11598c6a6096Sbeveloper out_output->node = sourcenode; 11608c6a6096Sbeveloper out_output->source = reply4.input.source; 11618c6a6096Sbeveloper out_output->destination = reply4.input.destination; 11628c6a6096Sbeveloper out_output->format = reply4.input.format; 11638c6a6096Sbeveloper strcpy(out_output->name, reply5.name); 11648c6a6096Sbeveloper 11658c6a6096Sbeveloper // the connection is now made 116669983609Sbeveloper PRINT_FORMAT(" format", *io_format); 116769983609Sbeveloper PRINT_INPUT(" input", *out_input); 116869983609Sbeveloper PRINT_OUTPUT(" output", *out_output); 11698c6a6096Sbeveloper 117034c72144SAxel Dörfler // TODO: register connection with server 117134c72144SAxel Dörfler // TODO: we should just send a notification, instead of republishing all 117234c72144SAxel Dörfler // endpoints 117376669a29Sbeveloper List<media_output> outlist; 117476669a29Sbeveloper List<media_input> inlist; 117534c72144SAxel Dörfler if (MediaRosterEx(this)->GetAllOutputs(out_output->node , &outlist) == B_OK) 11768b04ffc1Sbeveloper MediaRosterEx(this)->PublishOutputs(out_output->node , &outlist); 117734c72144SAxel Dörfler if (MediaRosterEx(this)->GetAllInputs(out_input->node , &inlist) == B_OK) 11788b04ffc1Sbeveloper MediaRosterEx(this)->PublishInputs(out_input->node, &inlist); 11798c6a6096Sbeveloper 118034c72144SAxel Dörfler // TODO: if (mute) BBufferProducer::EnableOutput(false) 11819e9417d2Sbeveloper if (in_flags & B_CONNECT_MUTED) { 11829e9417d2Sbeveloper } 11838c6a6096Sbeveloper 11849e9417d2Sbeveloper // send a notification 118534c72144SAxel Dörfler BPrivate::media::notifications::ConnectionMade(*out_input, *out_output, 118634c72144SAxel Dörfler *io_format); 11879e9417d2Sbeveloper 11888c6a6096Sbeveloper return B_OK; 11898c6a6096Sbeveloper }; 119052a38012Sejakowatz 119152a38012Sejakowatz 119252a38012Sejakowatz status_t 11939e9417d2Sbeveloper BMediaRoster::Disconnect(media_node_id source_nodeid, 119434c72144SAxel Dörfler const media_source& source, media_node_id destination_nodeid, 119552a38012Sejakowatz const media_destination& destination) 119652a38012Sejakowatz { 11979e9417d2Sbeveloper CALLED(); 119840f36b03Sbeveloper if (IS_INVALID_NODEID(source_nodeid)) { 11995ac4fbd7Sbeveloper ERROR("BMediaRoster::Disconnect: source media_node_id invalid\n"); 12009e9417d2Sbeveloper return B_MEDIA_BAD_SOURCE; 12019e9417d2Sbeveloper } 120240f36b03Sbeveloper if (IS_INVALID_NODEID(destination_nodeid)) { 12035ac4fbd7Sbeveloper ERROR("BMediaRoster::Disconnect: destination media_node_id invalid\n"); 12049e9417d2Sbeveloper return B_MEDIA_BAD_DESTINATION; 12059e9417d2Sbeveloper } 120640f36b03Sbeveloper if (IS_INVALID_SOURCE(source)) { 12075ac4fbd7Sbeveloper ERROR("BMediaRoster::Disconnect: media_source invalid\n"); 12089e9417d2Sbeveloper return B_MEDIA_BAD_SOURCE; 12099e9417d2Sbeveloper } 121040f36b03Sbeveloper if (IS_INVALID_DESTINATION(destination)) { 12115ac4fbd7Sbeveloper ERROR("BMediaRoster::Disconnect: media_destination invalid\n"); 12129e9417d2Sbeveloper return B_MEDIA_BAD_DESTINATION; 12139e9417d2Sbeveloper } 12149e9417d2Sbeveloper 12159e9417d2Sbeveloper producer_disconnect_request request2; 12169e9417d2Sbeveloper producer_disconnect_reply reply2; 12179e9417d2Sbeveloper consumer_disconnected_request request1; 12189e9417d2Sbeveloper consumer_disconnected_reply reply1; 12199e9417d2Sbeveloper status_t rv1, rv2; 12209e9417d2Sbeveloper 122134c72144SAxel Dörfler // TODO: we should ask the server if this connection really exists 12229e9417d2Sbeveloper 12239e9417d2Sbeveloper request1.source = source; 12249e9417d2Sbeveloper request1.destination = destination; 12259e9417d2Sbeveloper request2.source = source; 12269e9417d2Sbeveloper request2.destination = destination; 12279e9417d2Sbeveloper 122834c72144SAxel Dörfler rv1 = QueryPort(source.port, PRODUCER_DISCONNECT, &request1, 122934c72144SAxel Dörfler sizeof(request1), &reply1, sizeof(reply1)); 123034c72144SAxel Dörfler rv2 = QueryPort(destination.port, CONSUMER_DISCONNECTED, &request2, 123134c72144SAxel Dörfler sizeof(request2), &reply2, sizeof(reply2)); 12329e9417d2Sbeveloper 123334c72144SAxel Dörfler // TODO: unregister connection with server 123434c72144SAxel Dörfler // TODO: we should just send a notification, instead of republishing all 123534c72144SAxel Dörfler // endpoints 123676669a29Sbeveloper List<media_output> outlist; 123776669a29Sbeveloper List<media_input> inlist; 12389e9417d2Sbeveloper media_node sourcenode; 12399e9417d2Sbeveloper media_node destnode; 124034c72144SAxel Dörfler if (GetNodeFor(source_nodeid, &sourcenode) == B_OK) { 124165b73ae4SMarcus Overhagen if (!(sourcenode.kind & B_BUFFER_PRODUCER)) { 1242332cc6bcSAxel Dörfler ERROR("BMediaRoster::Disconnect: source_nodeid %" B_PRId32 1243332cc6bcSAxel Dörfler " is not a B_BUFFER_PRODUCER\n", source_nodeid); 124465b73ae4SMarcus Overhagen } 124534c72144SAxel Dörfler if (MediaRosterEx(this)->GetAllOutputs(sourcenode , &outlist) == B_OK) 12468b04ffc1Sbeveloper MediaRosterEx(this)->PublishOutputs(sourcenode , &outlist); 12479e9417d2Sbeveloper ReleaseNode(sourcenode); 12484f09fa2fSbeveloper } else { 1249332cc6bcSAxel Dörfler ERROR("BMediaRoster::Disconnect: GetNodeFor source_nodeid %" B_PRId32 1250332cc6bcSAxel Dörfler " failed\n", source_nodeid); 12514f09fa2fSbeveloper } 125234c72144SAxel Dörfler if (GetNodeFor(destination_nodeid, &destnode) == B_OK) { 125365b73ae4SMarcus Overhagen if (!(destnode.kind & B_BUFFER_CONSUMER)) { 1254332cc6bcSAxel Dörfler ERROR("BMediaRoster::Disconnect: destination_nodeid %" B_PRId32 1255332cc6bcSAxel Dörfler " is not a B_BUFFER_CONSUMER\n", destination_nodeid); 125665b73ae4SMarcus Overhagen } 125734c72144SAxel Dörfler if (MediaRosterEx(this)->GetAllInputs(destnode , &inlist) == B_OK) 12588b04ffc1Sbeveloper MediaRosterEx(this)->PublishInputs(destnode, &inlist); 12599e9417d2Sbeveloper ReleaseNode(destnode); 12604f09fa2fSbeveloper } else { 1261332cc6bcSAxel Dörfler ERROR("BMediaRoster::Disconnect: GetNodeFor destination_nodeid %" 1262332cc6bcSAxel Dörfler B_PRId32 " failed\n", destination_nodeid); 12634f09fa2fSbeveloper } 12649e9417d2Sbeveloper 12659e9417d2Sbeveloper // send a notification 12669e9417d2Sbeveloper BPrivate::media::notifications::ConnectionBroken(source, destination); 12679e9417d2Sbeveloper 126834c72144SAxel Dörfler return rv1 != B_OK || rv2 != B_OK ? B_ERROR : B_OK; 126952a38012Sejakowatz } 127052a38012Sejakowatz 127134c72144SAxel Dörfler 127265b73ae4SMarcus Overhagen status_t 127365b73ae4SMarcus Overhagen BMediaRoster::Disconnect(const media_output& output, const media_input& input) 127465b73ae4SMarcus Overhagen { 127565b73ae4SMarcus Overhagen if (IS_INVALID_NODEID(output.node.node)) { 1276332cc6bcSAxel Dörfler printf("BMediaRoster::Disconnect: output.node.node %" B_PRId32 1277332cc6bcSAxel Dörfler " invalid\n", output.node.node); 127865b73ae4SMarcus Overhagen return B_MEDIA_BAD_SOURCE; 127965b73ae4SMarcus Overhagen } 128065b73ae4SMarcus Overhagen if (IS_INVALID_NODEID(input.node.node)) { 1281332cc6bcSAxel Dörfler printf("BMediaRoster::Disconnect: input.node.node %" B_PRId32 1282332cc6bcSAxel Dörfler " invalid\n", input.node.node); 128365b73ae4SMarcus Overhagen return B_MEDIA_BAD_DESTINATION; 128465b73ae4SMarcus Overhagen } 128565b73ae4SMarcus Overhagen if (!(output.node.kind & B_BUFFER_PRODUCER)) { 1286332cc6bcSAxel Dörfler printf("BMediaRoster::Disconnect: output.node.kind 0x%" B_PRIx32 1287332cc6bcSAxel Dörfler " is no B_BUFFER_PRODUCER\n", output.node.kind); 128865b73ae4SMarcus Overhagen return B_MEDIA_BAD_SOURCE; 128965b73ae4SMarcus Overhagen } 129065b73ae4SMarcus Overhagen if (!(input.node.kind & B_BUFFER_CONSUMER)) { 1291332cc6bcSAxel Dörfler printf("BMediaRoster::Disconnect: input.node.kind 0x%" B_PRIx32 1292332cc6bcSAxel Dörfler " is no B_BUFFER_PRODUCER\n", input.node.kind); 129365b73ae4SMarcus Overhagen return B_MEDIA_BAD_DESTINATION; 129465b73ae4SMarcus Overhagen } 129565b73ae4SMarcus Overhagen if (input.source.port != output.source.port) { 1296332cc6bcSAxel Dörfler printf("BMediaRoster::Disconnect: input.source.port %" B_PRId32 1297332cc6bcSAxel Dörfler " doesn't match output.source.port %" B_PRId32 "\n", 1298332cc6bcSAxel Dörfler input.source.port, output.source.port); 129965b73ae4SMarcus Overhagen return B_MEDIA_BAD_SOURCE; 130065b73ae4SMarcus Overhagen } 130165b73ae4SMarcus Overhagen if (input.source.id != output.source.id) { 1302332cc6bcSAxel Dörfler printf("BMediaRoster::Disconnect: input.source.id %" B_PRId32 1303332cc6bcSAxel Dörfler " doesn't match output.source.id %" B_PRId32 "\n", input.source.id, 1304332cc6bcSAxel Dörfler output.source.id); 130565b73ae4SMarcus Overhagen return B_MEDIA_BAD_SOURCE; 130665b73ae4SMarcus Overhagen } 130765b73ae4SMarcus Overhagen if (input.destination.port != output.destination.port) { 1308332cc6bcSAxel Dörfler printf("BMediaRoster::Disconnect: input.destination.port %" B_PRId32 1309332cc6bcSAxel Dörfler " doesn't match output.destination.port %" B_PRId32 "\n", 1310332cc6bcSAxel Dörfler input.destination.port, output.destination.port); 131165b73ae4SMarcus Overhagen return B_MEDIA_BAD_DESTINATION; 131265b73ae4SMarcus Overhagen } 131365b73ae4SMarcus Overhagen if (input.destination.id != output.destination.id) { 1314332cc6bcSAxel Dörfler printf("BMediaRoster::Disconnect: input.destination.id %" B_PRId32 1315332cc6bcSAxel Dörfler " doesn't match output.destination.id %" B_PRId32 "\n", 1316332cc6bcSAxel Dörfler input.destination.id, output.destination.id); 131765b73ae4SMarcus Overhagen return B_MEDIA_BAD_DESTINATION; 131865b73ae4SMarcus Overhagen } 131934c72144SAxel Dörfler 132034c72144SAxel Dörfler return Disconnect(output.node.node, output.source, input.node.node, 132134c72144SAxel Dörfler input.destination); 132265b73ae4SMarcus Overhagen } 132365b73ae4SMarcus Overhagen 132452a38012Sejakowatz 132552a38012Sejakowatz status_t 132634c72144SAxel Dörfler BMediaRoster::StartNode(const media_node& node, bigtime_t atPerformanceTime) 132752a38012Sejakowatz { 132852a38012Sejakowatz CALLED(); 13299e9417d2Sbeveloper if (node.node <= 0) 133052a38012Sejakowatz return B_MEDIA_BAD_NODE; 133152a38012Sejakowatz 1332332cc6bcSAxel Dörfler TRACE("BMediaRoster::StartNode, node %" B_PRId32 ", at perf %" B_PRId64 1333332cc6bcSAxel Dörfler "\n", node.node, atPerformanceTime); 13340e21b167Sbeveloper 13356396865dSbeveloper node_start_command command; 133634c72144SAxel Dörfler command.performance_time = atPerformanceTime; 133752a38012Sejakowatz 13386396865dSbeveloper return SendToPort(node.port, NODE_START, &command, sizeof(command)); 133952a38012Sejakowatz } 134052a38012Sejakowatz 134152a38012Sejakowatz 134252a38012Sejakowatz status_t 134334c72144SAxel Dörfler BMediaRoster::StopNode(const media_node& node, bigtime_t atPerformanceTime, 134452a38012Sejakowatz bool immediate) 134552a38012Sejakowatz { 134652a38012Sejakowatz CALLED(); 134740f36b03Sbeveloper if (IS_INVALID_NODE(node)) 134852a38012Sejakowatz return B_MEDIA_BAD_NODE; 134952a38012Sejakowatz 1350332cc6bcSAxel Dörfler TRACE("BMediaRoster::StopNode, node %" B_PRId32 ", at perf %" B_PRId64 1351332cc6bcSAxel Dörfler " %s\n", node.node, atPerformanceTime, immediate ? "NOW" : ""); 13520e21b167Sbeveloper 13536396865dSbeveloper node_stop_command command; 135434c72144SAxel Dörfler command.performance_time = atPerformanceTime; 13556396865dSbeveloper command.immediate = immediate; 135652a38012Sejakowatz 13576396865dSbeveloper return SendToPort(node.port, NODE_STOP, &command, sizeof(command)); 135852a38012Sejakowatz } 135952a38012Sejakowatz 136052a38012Sejakowatz 136152a38012Sejakowatz status_t 136234c72144SAxel Dörfler BMediaRoster::SeekNode(const media_node& node, bigtime_t toMediaTime, 136334c72144SAxel Dörfler bigtime_t atPerformanceTime) 136452a38012Sejakowatz { 136552a38012Sejakowatz CALLED(); 136640f36b03Sbeveloper if (IS_INVALID_NODE(node)) 136752a38012Sejakowatz return B_MEDIA_BAD_NODE; 136852a38012Sejakowatz 1369332cc6bcSAxel Dörfler TRACE("BMediaRoster::SeekNode, node %" B_PRId32 ", at perf %" B_PRId64 1370332cc6bcSAxel Dörfler ", to perf %" B_PRId64 "\n", node.node, atPerformanceTime, toMediaTime); 13710e21b167Sbeveloper 13726396865dSbeveloper node_seek_command command; 137334c72144SAxel Dörfler command.media_time = toMediaTime; 137434c72144SAxel Dörfler command.performance_time = atPerformanceTime; 137552a38012Sejakowatz 13766396865dSbeveloper return SendToPort(node.port, NODE_SEEK, &command, sizeof(command)); 137752a38012Sejakowatz } 137852a38012Sejakowatz 137952a38012Sejakowatz 138052a38012Sejakowatz status_t 138134c72144SAxel Dörfler BMediaRoster::StartTimeSource(const media_node& node, bigtime_t atRealTime) 138252a38012Sejakowatz { 138352a38012Sejakowatz CALLED(); 138460f15390Sbeveloper if (IS_SYSTEM_TIMESOURCE(node)) { 138534c72144SAxel Dörfler // TODO: debug this 1386332cc6bcSAxel Dörfler //ERROR("BMediaRoster::StartTimeSource node %" B_PRId32 " is system timesource\n", node.node); 138760f15390Sbeveloper return B_OK; 138860f15390Sbeveloper } 138992e575c1Sbeveloper // if (IS_SHADOW_TIMESOURCE(node)) { 139034c72144SAxel Dörfler // // TODO: debug this 1391332cc6bcSAxel Dörfler // ERROR("BMediaRoster::StartTimeSource node %" B_PRId32 " is shadow timesource\n", node.node); 139292e575c1Sbeveloper // return B_OK; 139392e575c1Sbeveloper // } 139440f36b03Sbeveloper if (IS_INVALID_NODE(node)) { 1395332cc6bcSAxel Dörfler ERROR("BMediaRoster::StartTimeSource node %" B_PRId32 " invalid\n", 139634c72144SAxel Dörfler node.node); 139752a38012Sejakowatz return B_MEDIA_BAD_NODE; 13980e21b167Sbeveloper } 1399332cc6bcSAxel Dörfler if ((node.kind & B_TIME_SOURCE) == 0) { 1400332cc6bcSAxel Dörfler ERROR("BMediaRoster::StartTimeSource node %" B_PRId32 1401332cc6bcSAxel Dörfler " is no timesource\n", node.node); 1402332cc6bcSAxel Dörfler return B_MEDIA_BAD_NODE; 1403332cc6bcSAxel Dörfler } 14040e21b167Sbeveloper 1405332cc6bcSAxel Dörfler TRACE("BMediaRoster::StartTimeSource, node %" B_PRId32 ", at real %" 1406332cc6bcSAxel Dörfler B_PRId64 "\n", node.node, atRealTime); 140752a38012Sejakowatz 140852a38012Sejakowatz BTimeSource::time_source_op_info msg; 140952a38012Sejakowatz msg.op = BTimeSource::B_TIMESOURCE_START; 141034c72144SAxel Dörfler msg.real_time = atRealTime; 141152a38012Sejakowatz 141252a38012Sejakowatz return write_port(node.port, TIMESOURCE_OP, &msg, sizeof(msg)); 141352a38012Sejakowatz } 141452a38012Sejakowatz 141552a38012Sejakowatz 141652a38012Sejakowatz status_t 141734c72144SAxel Dörfler BMediaRoster::StopTimeSource(const media_node& node, bigtime_t atRealTime, 141852a38012Sejakowatz bool immediate) 141952a38012Sejakowatz { 142052a38012Sejakowatz CALLED(); 142160f15390Sbeveloper if (IS_SYSTEM_TIMESOURCE(node)) { 142234c72144SAxel Dörfler // TODO: debug this 14235ac4fbd7Sbeveloper //ERROR("BMediaRoster::StopTimeSource node %ld is system timesource\n", node.node); 142460f15390Sbeveloper return B_OK; 142560f15390Sbeveloper } 142692e575c1Sbeveloper // if (IS_SHADOW_TIMESOURCE(node)) { 142734c72144SAxel Dörfler // // TODO: debug this 142892e575c1Sbeveloper // ERROR("BMediaRoster::StopTimeSource node %ld is shadow timesource\n", node.node); 142992e575c1Sbeveloper // return B_OK; 143092e575c1Sbeveloper // } 143140f36b03Sbeveloper if (IS_INVALID_NODE(node)) { 1432332cc6bcSAxel Dörfler ERROR("BMediaRoster::StopTimeSource node %" B_PRId32 " invalid\n", 143334c72144SAxel Dörfler node.node); 143452a38012Sejakowatz return B_MEDIA_BAD_NODE; 14350e21b167Sbeveloper } 1436332cc6bcSAxel Dörfler if ((node.kind & B_TIME_SOURCE) == 0) { 1437332cc6bcSAxel Dörfler ERROR("BMediaRoster::StopTimeSource node %" B_PRId32 " is no " 1438332cc6bcSAxel Dörfler "timesource\n", node.node); 1439332cc6bcSAxel Dörfler return B_MEDIA_BAD_NODE; 1440332cc6bcSAxel Dörfler } 14410e21b167Sbeveloper 1442332cc6bcSAxel Dörfler TRACE("BMediaRoster::StopTimeSource, node %" B_PRId32 ", at real %" B_PRId64 1443332cc6bcSAxel Dörfler " %s\n", node.node, atRealTime, immediate ? "NOW" : ""); 144452a38012Sejakowatz 144552a38012Sejakowatz BTimeSource::time_source_op_info msg; 144634c72144SAxel Dörfler msg.op = immediate ? BTimeSource::B_TIMESOURCE_STOP_IMMEDIATELY 144734c72144SAxel Dörfler : BTimeSource::B_TIMESOURCE_STOP; 144834c72144SAxel Dörfler msg.real_time = atRealTime; 144952a38012Sejakowatz 145052a38012Sejakowatz return write_port(node.port, TIMESOURCE_OP, &msg, sizeof(msg)); 145152a38012Sejakowatz } 145252a38012Sejakowatz 145352a38012Sejakowatz 145452a38012Sejakowatz status_t 145552a38012Sejakowatz BMediaRoster::SeekTimeSource(const media_node& node, 145634c72144SAxel Dörfler bigtime_t toPerformanceTime, bigtime_t atRealTime) 145752a38012Sejakowatz { 145852a38012Sejakowatz CALLED(); 145960f15390Sbeveloper if (IS_SYSTEM_TIMESOURCE(node)) { 146034c72144SAxel Dörfler // TODO: debug this 14615ac4fbd7Sbeveloper // ERROR("BMediaRoster::SeekTimeSource node %ld is system timesource\n", node.node); 146260f15390Sbeveloper // you can't seek the system time source, but 146360f15390Sbeveloper // returning B_ERROR would break StampTV 146460f15390Sbeveloper return B_OK; 146560f15390Sbeveloper } 146692e575c1Sbeveloper // if (IS_SHADOW_TIMESOURCE(node)) { 146734c72144SAxel Dörfler // // TODO: debug this 146892e575c1Sbeveloper // ERROR("BMediaRoster::SeekTimeSource node %ld is shadow timesource\n", node.node); 146992e575c1Sbeveloper // return B_OK; 147092e575c1Sbeveloper // } 147140f36b03Sbeveloper if (IS_INVALID_NODE(node)) { 1472332cc6bcSAxel Dörfler ERROR("BMediaRoster::SeekTimeSource node %" B_PRId32 " invalid\n", 147334c72144SAxel Dörfler node.node); 147452a38012Sejakowatz return B_MEDIA_BAD_NODE; 14750e21b167Sbeveloper } 1476332cc6bcSAxel Dörfler if ((node.kind & B_TIME_SOURCE) == 0) { 1477332cc6bcSAxel Dörfler ERROR("BMediaRoster::SeekTimeSource node %" B_PRId32 1478332cc6bcSAxel Dörfler " is no timesource\n", node.node); 1479332cc6bcSAxel Dörfler return B_MEDIA_BAD_NODE; 1480332cc6bcSAxel Dörfler } 14810e21b167Sbeveloper 1482332cc6bcSAxel Dörfler TRACE("BMediaRoster::SeekTimeSource, node %" B_PRId32 ", at real %" B_PRId64 1483332cc6bcSAxel Dörfler ", to perf %" B_PRId64 "\n", node.node, atRealTime, toPerformanceTime); 148452a38012Sejakowatz 148552a38012Sejakowatz BTimeSource::time_source_op_info msg; 148652a38012Sejakowatz msg.op = BTimeSource::B_TIMESOURCE_SEEK; 148734c72144SAxel Dörfler msg.real_time = atRealTime; 148834c72144SAxel Dörfler msg.performance_time = toPerformanceTime; 148952a38012Sejakowatz 149052a38012Sejakowatz return write_port(node.port, TIMESOURCE_OP, &msg, sizeof(msg)); 149152a38012Sejakowatz } 149252a38012Sejakowatz 149352a38012Sejakowatz 149452a38012Sejakowatz status_t 149534c72144SAxel Dörfler BMediaRoster::SyncToNode(const media_node& node, bigtime_t atTime, 149652a38012Sejakowatz bigtime_t timeout) 149752a38012Sejakowatz { 149875486484SDario Casalinuovo TRACE("BMediaRoster::SyncToNode, node %" B_PRId32 ", at real %" B_PRId64 149975486484SDario Casalinuovo ", at timeout %" B_PRId64 "\n", node.node, atTime, timeout); 150075486484SDario Casalinuovo if (IS_INVALID_NODE(node)) 150175486484SDario Casalinuovo return B_MEDIA_BAD_NODE; 150275486484SDario Casalinuovo 150375486484SDario Casalinuovo port_id waitPort = create_port(1, "SyncToNode wait port"); 150475486484SDario Casalinuovo if (waitPort < B_OK) 150575486484SDario Casalinuovo return waitPort; 150675486484SDario Casalinuovo 150775486484SDario Casalinuovo node_sync_to_request request; 150875486484SDario Casalinuovo node_sync_to_reply reply; 150975486484SDario Casalinuovo request.performance_time = atTime; 151075486484SDario Casalinuovo request.port = waitPort; 151175486484SDario Casalinuovo 151275486484SDario Casalinuovo status_t status = QueryPort(node.port, NODE_SYNC_TO, &request, 151375486484SDario Casalinuovo sizeof(request), &reply, sizeof(reply)); 151475486484SDario Casalinuovo 151575486484SDario Casalinuovo if (status == B_OK) { 151675486484SDario Casalinuovo ssize_t readSize = read_port_etc(waitPort, NULL, &status, 151775486484SDario Casalinuovo sizeof(status), B_TIMEOUT, timeout); 151875486484SDario Casalinuovo if (readSize < 0) 151975486484SDario Casalinuovo status = readSize; 152075486484SDario Casalinuovo } 152175486484SDario Casalinuovo close_port(waitPort); 152275486484SDario Casalinuovo delete_port(waitPort); 152375486484SDario Casalinuovo return status; 152452a38012Sejakowatz } 152552a38012Sejakowatz 152652a38012Sejakowatz 152752a38012Sejakowatz status_t 152834c72144SAxel Dörfler BMediaRoster::SetRunModeNode(const media_node& node, BMediaNode::run_mode mode) 152952a38012Sejakowatz { 1530332cc6bcSAxel Dörfler TRACE("BMediaRoster::SetRunModeNode, node %" B_PRId32 ", mode %d\n", 1531332cc6bcSAxel Dörfler node.node, mode); 153240f36b03Sbeveloper if (IS_INVALID_NODE(node)) 153352a38012Sejakowatz return B_MEDIA_BAD_NODE; 153452a38012Sejakowatz 1535dfb2ad61Sbeveloper node_set_run_mode_command msg; 153652a38012Sejakowatz msg.mode = mode; 153752a38012Sejakowatz 153852a38012Sejakowatz return write_port(node.port, NODE_SET_RUN_MODE, &msg, sizeof(msg)); 153952a38012Sejakowatz } 154052a38012Sejakowatz 154152a38012Sejakowatz 154252a38012Sejakowatz status_t 154352a38012Sejakowatz BMediaRoster::PrerollNode(const media_node& node) 154452a38012Sejakowatz { 154552a38012Sejakowatz CALLED(); 154640f36b03Sbeveloper if (IS_INVALID_NODE(node)) 154752a38012Sejakowatz return B_MEDIA_BAD_NODE; 154852a38012Sejakowatz 154952a38012Sejakowatz char dummy; 155052a38012Sejakowatz return write_port(node.port, NODE_PREROLL, &dummy, sizeof(dummy)); 155152a38012Sejakowatz } 155252a38012Sejakowatz 155352a38012Sejakowatz 155452a38012Sejakowatz status_t 155534c72144SAxel Dörfler BMediaRoster::RollNode(const media_node& node, bigtime_t startPerformance, 155634c72144SAxel Dörfler bigtime_t stopPerformance, bigtime_t atMediaTime) 155752a38012Sejakowatz { 155814896b93SDario Casalinuovo CALLED(); 155914896b93SDario Casalinuovo if (IS_INVALID_NODE(node)) 156014896b93SDario Casalinuovo return B_MEDIA_BAD_NODE; 156114896b93SDario Casalinuovo 156214896b93SDario Casalinuovo TRACE("BMediaRoster::RollNode, node %" B_PRId32 ", at start perf %" 156314896b93SDario Casalinuovo B_PRId64 ", at stop perf %" B_PRId64 ", at media time %" 156414896b93SDario Casalinuovo B_PRId64 "\n", node.node, startPerformance, 156514896b93SDario Casalinuovo stopPerformance, atMediaTime); 156614896b93SDario Casalinuovo 156714896b93SDario Casalinuovo node_roll_command command; 156814896b93SDario Casalinuovo command.start_performance_time = startPerformance; 156914896b93SDario Casalinuovo command.stop_performance_time = stopPerformance; 157014896b93SDario Casalinuovo command.seek_media_time = atMediaTime; 157114896b93SDario Casalinuovo 157214896b93SDario Casalinuovo return write_port(node.port, NODE_ROLL, &command, sizeof(command)); 157352a38012Sejakowatz } 157452a38012Sejakowatz 157552a38012Sejakowatz 157652a38012Sejakowatz status_t 157752a38012Sejakowatz BMediaRoster::SetProducerRunModeDelay(const media_node& node, 157834c72144SAxel Dörfler bigtime_t delay, BMediaNode::run_mode mode) 157952a38012Sejakowatz { 1580332cc6bcSAxel Dörfler TRACE("BMediaRoster::SetProducerRunModeDelay, node %" B_PRId32 ", delay %" 1581332cc6bcSAxel Dörfler B_PRId64 ", mode %d\n", node.node, delay, mode); 158260f15390Sbeveloper if (IS_INVALID_NODE(node)) 158360f15390Sbeveloper return B_MEDIA_BAD_NODE; 158460f15390Sbeveloper if ((node.kind & B_BUFFER_PRODUCER) == 0) 158560f15390Sbeveloper return B_MEDIA_BAD_NODE; 158660f15390Sbeveloper 158760f15390Sbeveloper producer_set_run_mode_delay_command command; 158860f15390Sbeveloper command.mode = mode; 158960f15390Sbeveloper command.delay = delay; 159060f15390Sbeveloper 159134c72144SAxel Dörfler return SendToPort(node.port, PRODUCER_SET_RUN_MODE_DELAY, &command, 159234c72144SAxel Dörfler sizeof(command)); 159352a38012Sejakowatz } 159452a38012Sejakowatz 159552a38012Sejakowatz 159652a38012Sejakowatz status_t 159734c72144SAxel Dörfler BMediaRoster::SetProducerRate(const media_node& producer, int32 numer, 159852a38012Sejakowatz int32 denom) 159952a38012Sejakowatz { 160052a38012Sejakowatz CALLED(); 160140f36b03Sbeveloper if (IS_INVALID_NODE(producer)) 160252a38012Sejakowatz return B_MEDIA_BAD_NODE; 160352a38012Sejakowatz if ((producer.kind & B_BUFFER_PRODUCER) == 0) 160452a38012Sejakowatz return B_MEDIA_BAD_NODE; 160552a38012Sejakowatz 16066cafce94SAxel Dörfler producer_set_play_rate_request request; 16076cafce94SAxel Dörfler request.numer = numer; 16086cafce94SAxel Dörfler request.denom = denom; 16096cafce94SAxel Dörfler status_t status = write_port(producer.node, PRODUCER_SET_PLAY_RATE, 16106cafce94SAxel Dörfler &request, sizeof(request)); 16116cafce94SAxel Dörfler if (status != B_OK) 16126cafce94SAxel Dörfler return status; 161352a38012Sejakowatz 16146cafce94SAxel Dörfler producer_set_play_rate_reply reply; 16156cafce94SAxel Dörfler int32 code; 16166cafce94SAxel Dörfler status = read_port(request.reply_port, &code, &reply, sizeof(reply)); 16176cafce94SAxel Dörfler 16186cafce94SAxel Dörfler return status < B_OK ? status : reply.result; 161952a38012Sejakowatz } 162052a38012Sejakowatz 162152a38012Sejakowatz 162234c72144SAxel Dörfler /*! Nodes will have available inputs/outputs as long as they are capable 162334c72144SAxel Dörfler of accepting more connections. The node may create an additional 162434c72144SAxel Dörfler output or input as the currently available is taken into usage. 162534c72144SAxel Dörfler */ 162652a38012Sejakowatz status_t 162752a38012Sejakowatz BMediaRoster::GetLiveNodeInfo(const media_node& node, 162852a38012Sejakowatz live_node_info* out_live_info) 162952a38012Sejakowatz { 16309e9417d2Sbeveloper CALLED(); 16319e9417d2Sbeveloper if (out_live_info == NULL) 16329e9417d2Sbeveloper return B_BAD_VALUE; 163340f36b03Sbeveloper if (IS_INVALID_NODE(node)) 16349e9417d2Sbeveloper return B_MEDIA_BAD_NODE; 16359e9417d2Sbeveloper 16369e9417d2Sbeveloper server_get_live_node_info_request request; 16379e9417d2Sbeveloper server_get_live_node_info_reply reply; 16389e9417d2Sbeveloper status_t rv; 16399e9417d2Sbeveloper 16409e9417d2Sbeveloper request.node = node; 16419e9417d2Sbeveloper 164234c72144SAxel Dörfler rv = QueryServer(SERVER_GET_LIVE_NODE_INFO, &request, sizeof(request), 164334c72144SAxel Dörfler &reply, sizeof(reply)); 16449e9417d2Sbeveloper if (rv != B_OK) 16459e9417d2Sbeveloper return rv; 16469e9417d2Sbeveloper 16479e9417d2Sbeveloper *out_live_info = reply.live_info; 16489e9417d2Sbeveloper return B_OK; 164952a38012Sejakowatz } 165052a38012Sejakowatz 165152a38012Sejakowatz 165252a38012Sejakowatz status_t 16539c3b4706SAxel Dörfler BMediaRoster::GetLiveNodes(live_node_info* liveNodes, int32* _totalCount, 165434c72144SAxel Dörfler const media_format* hasInput, const media_format* hasOutput, 165534c72144SAxel Dörfler const char* name, uint64 nodeKinds) 165652a38012Sejakowatz { 16579e9417d2Sbeveloper CALLED(); 16589c3b4706SAxel Dörfler if (liveNodes == NULL || _totalCount == NULL || *_totalCount <= 0) 16599e9417d2Sbeveloper return B_BAD_VALUE; 16609e9417d2Sbeveloper 166134c72144SAxel Dörfler // TODO: we also support the wildcard search as GetDormantNodes does. 166234c72144SAxel Dörfler // This needs to be documented 16639e9417d2Sbeveloper 16649e9417d2Sbeveloper server_get_live_nodes_request request; 16659c3b4706SAxel Dörfler request.team = BPrivate::current_team(); 16669e9417d2Sbeveloper 16679c3b4706SAxel Dörfler request.max_count = *_totalCount; 166834c72144SAxel Dörfler request.has_input = hasInput != NULL; 166934c72144SAxel Dörfler if (hasInput != NULL) { 167034c72144SAxel Dörfler // TODO: we should not make a flat copy of media_format 16719c3b4706SAxel Dörfler request.input_format = *hasInput; 167234c72144SAxel Dörfler } 167334c72144SAxel Dörfler request.has_output = hasOutput != NULL; 167434c72144SAxel Dörfler if (hasOutput != NULL) { 167534c72144SAxel Dörfler // TODO: we should not make a flat copy of media_format 16769c3b4706SAxel Dörfler request.output_format = *hasOutput; 167734c72144SAxel Dörfler } 167834c72144SAxel Dörfler request.has_name = name != NULL; 16799c3b4706SAxel Dörfler if (name != NULL) 16809c3b4706SAxel Dörfler strlcpy(request.name, name, sizeof(request.name)); 168134c72144SAxel Dörfler request.require_kinds = nodeKinds; 16829e9417d2Sbeveloper 16839c3b4706SAxel Dörfler server_get_live_nodes_reply reply; 16849c3b4706SAxel Dörfler status_t status = QueryServer(SERVER_GET_LIVE_NODES, &request, 16859c3b4706SAxel Dörfler sizeof(request), &reply, sizeof(reply)); 16869c3b4706SAxel Dörfler if (status != B_OK) { 16879c3b4706SAxel Dörfler ERROR("BMediaRoster::GetLiveNodes failed querying server: %s\n", 16889c3b4706SAxel Dörfler strerror(status)); 168934c72144SAxel Dörfler *_totalCount = 0; 16909c3b4706SAxel Dörfler return status; 16919e9417d2Sbeveloper } 16929e9417d2Sbeveloper 16939c3b4706SAxel Dörfler const live_node_info* info; 16949c3b4706SAxel Dörfler if (reply.area >= 0) 16959c3b4706SAxel Dörfler info = (live_node_info*)reply.address; 16969c3b4706SAxel Dörfler else 16979c3b4706SAxel Dörfler info = reply.live_info; 16989e9417d2Sbeveloper 16999c3b4706SAxel Dörfler for (int32 i = 0; i < reply.count; i++) 17009c3b4706SAxel Dörfler liveNodes[i] = info[i]; 17019c3b4706SAxel Dörfler 17029c3b4706SAxel Dörfler if (reply.area >= 0) 17039e9417d2Sbeveloper delete_area(reply.area); 170452a38012Sejakowatz 170534c72144SAxel Dörfler *_totalCount = reply.count; 17069e9417d2Sbeveloper return B_OK; 17079e9417d2Sbeveloper } 17089e9417d2Sbeveloper 170952a38012Sejakowatz 171052a38012Sejakowatz status_t 171152a38012Sejakowatz BMediaRoster::GetFreeInputsFor(const media_node& node, 171234c72144SAxel Dörfler media_input * out_free_inputs, int32 buf_num_inputs, 171334c72144SAxel Dörfler int32 * out_total_count, media_type filter_type) 171452a38012Sejakowatz { 17153620737cSbeveloper CALLED(); 17165ac4fbd7Sbeveloper if (IS_INVALID_NODE(node)) { 1717332cc6bcSAxel Dörfler ERROR("BMediaRoster::GetFreeInputsFor: node %" B_PRId32 ", port %" 1718332cc6bcSAxel Dörfler B_PRId32 " invalid\n", node.node, node.port); 17193620737cSbeveloper return B_MEDIA_BAD_NODE; 17205ac4fbd7Sbeveloper } 17215ac4fbd7Sbeveloper if ((node.kind & B_BUFFER_CONSUMER) == 0) { 1722332cc6bcSAxel Dörfler ERROR("BMediaRoster::GetFreeInputsFor: node %" B_PRId32 ", port %" 1723332cc6bcSAxel Dörfler B_PRId32 " is not a consumer\n", node.node, node.port); 17245ac4fbd7Sbeveloper return B_MEDIA_BAD_NODE; 17255ac4fbd7Sbeveloper } 17263620737cSbeveloper if (out_free_inputs == NULL || out_total_count == NULL) 17273620737cSbeveloper return B_BAD_VALUE; 17283620737cSbeveloper 172976669a29Sbeveloper List<media_input> list; 17303620737cSbeveloper media_input *input; 17313620737cSbeveloper status_t rv; 17323620737cSbeveloper 17331299bfb2Sbeveloper *out_total_count = 0; 17341299bfb2Sbeveloper 17358b04ffc1Sbeveloper rv = MediaRosterEx(this)->GetAllInputs(node, &list); 17363620737cSbeveloper if (B_OK != rv) 17373620737cSbeveloper return rv; 17383620737cSbeveloper 1739332cc6bcSAxel Dörfler PRINT(4, "BMediaRoster::GetFreeInputsFor node %" B_PRId32 ", max %" B_PRId32 1740332cc6bcSAxel Dörfler ", filter-type %" B_PRId32 "\n", node.node, buf_num_inputs, 1741332cc6bcSAxel Dörfler filter_type); 17425ac4fbd7Sbeveloper 174376669a29Sbeveloper int32 i; 1744b65a0ac5SJérôme Duval for (i = 0, list.Rewind(); list.GetNext(&input);) { 174534c72144SAxel Dörfler if (filter_type != B_MEDIA_UNKNOWN_TYPE 174634c72144SAxel Dörfler && filter_type != input->format.type) { 174734c72144SAxel Dörfler // media_type used, but doesn't match 174834c72144SAxel Dörfler continue; 174934c72144SAxel Dörfler } 175034c72144SAxel Dörfler if (input->source != media_source::null) { 175134c72144SAxel Dörfler // consumer source already connected 175234c72144SAxel Dörfler continue; 175334c72144SAxel Dörfler } 175434c72144SAxel Dörfler 17553620737cSbeveloper out_free_inputs[i] = *input; 17563620737cSbeveloper *out_total_count += 1; 17573620737cSbeveloper buf_num_inputs -= 1; 17585ac4fbd7Sbeveloper #if DEBUG >= 3 17595ac4fbd7Sbeveloper PRINT_OUTPUT(" input", out_free_inputs[i]); 17605ac4fbd7Sbeveloper #endif 17613620737cSbeveloper if (buf_num_inputs == 0) 17623620737cSbeveloper break; 1763b65a0ac5SJérôme Duval i++; 17643620737cSbeveloper } 17653620737cSbeveloper 17668b04ffc1Sbeveloper MediaRosterEx(this)->PublishInputs(node, &list); 17673620737cSbeveloper return B_OK; 176852a38012Sejakowatz } 176952a38012Sejakowatz 177052a38012Sejakowatz 177152a38012Sejakowatz status_t 177252a38012Sejakowatz BMediaRoster::GetConnectedInputsFor(const media_node& node, 177334c72144SAxel Dörfler media_input* out_active_inputs, int32 buf_num_inputs, 177452a38012Sejakowatz int32* out_total_count) 177552a38012Sejakowatz { 17763620737cSbeveloper CALLED(); 177740f36b03Sbeveloper if (IS_INVALID_NODE(node) || (node.kind & B_BUFFER_CONSUMER) == 0) 17783620737cSbeveloper return B_MEDIA_BAD_NODE; 17793620737cSbeveloper if (out_active_inputs == NULL || out_total_count == NULL) 17803620737cSbeveloper return B_BAD_VALUE; 17813620737cSbeveloper 178276669a29Sbeveloper List<media_input> list; 17833620737cSbeveloper media_input *input; 17843620737cSbeveloper status_t rv; 17853620737cSbeveloper 17861299bfb2Sbeveloper *out_total_count = 0; 17871299bfb2Sbeveloper 17888b04ffc1Sbeveloper rv = MediaRosterEx(this)->GetAllInputs(node, &list); 17893620737cSbeveloper if (B_OK != rv) 17903620737cSbeveloper return rv; 17913620737cSbeveloper 1792332cc6bcSAxel Dörfler PRINT(4, "BMediaRoster::GetConnectedInputsFor node %" B_PRId32 ", max %" 1793332cc6bcSAxel Dörfler B_PRId32 "\n", node.node, buf_num_inputs); 17945ac4fbd7Sbeveloper 179576669a29Sbeveloper int32 i; 1796b65a0ac5SJérôme Duval for (i = 0, list.Rewind(); list.GetNext(&input);) { 17973620737cSbeveloper if (input->source == media_source::null) 17983620737cSbeveloper continue; // consumer source not connected 17993620737cSbeveloper out_active_inputs[i] = *input; 18003620737cSbeveloper *out_total_count += 1; 18013620737cSbeveloper buf_num_inputs -= 1; 18025ac4fbd7Sbeveloper #if DEBUG >= 3 18035ac4fbd7Sbeveloper PRINT_OUTPUT(" input ", out_active_inputs[i]); 18045ac4fbd7Sbeveloper #endif 18053620737cSbeveloper if (buf_num_inputs == 0) 18063620737cSbeveloper break; 1807b65a0ac5SJérôme Duval i++; 18083620737cSbeveloper } 18093620737cSbeveloper 18108b04ffc1Sbeveloper MediaRosterEx(this)->PublishInputs(node, &list); 18113620737cSbeveloper return B_OK; 181252a38012Sejakowatz } 181352a38012Sejakowatz 181452a38012Sejakowatz 181552a38012Sejakowatz status_t 181634c72144SAxel Dörfler BMediaRoster::GetAllInputsFor(const media_node& node, media_input* out_inputs, 181734c72144SAxel Dörfler int32 buf_num_inputs, int32* out_total_count) 181852a38012Sejakowatz { 181952a38012Sejakowatz CALLED(); 182040f36b03Sbeveloper if (IS_INVALID_NODE(node) || (node.kind & B_BUFFER_CONSUMER) == 0) 182152a38012Sejakowatz return B_MEDIA_BAD_NODE; 182252a38012Sejakowatz if (out_inputs == NULL || out_total_count == NULL) 182352a38012Sejakowatz return B_BAD_VALUE; 182452a38012Sejakowatz 182576669a29Sbeveloper List<media_input> list; 18263620737cSbeveloper media_input *input; 182752a38012Sejakowatz status_t rv; 182852a38012Sejakowatz 18291299bfb2Sbeveloper *out_total_count = 0; 18301299bfb2Sbeveloper 18318b04ffc1Sbeveloper rv = MediaRosterEx(this)->GetAllInputs(node, &list); 18323620737cSbeveloper if (B_OK != rv) 18333620737cSbeveloper return rv; 18343620737cSbeveloper 1835332cc6bcSAxel Dörfler PRINT(4, "BMediaRoster::GetAllInputsFor node %" B_PRId32 ", max %" B_PRId32 1836332cc6bcSAxel Dörfler "\n", node.node, buf_num_inputs); 18375ac4fbd7Sbeveloper 183876669a29Sbeveloper int32 i; 183976669a29Sbeveloper for (i = 0, list.Rewind(); list.GetNext(&input); i++) { 18403620737cSbeveloper out_inputs[i] = *input; 184152a38012Sejakowatz *out_total_count += 1; 18423620737cSbeveloper buf_num_inputs -= 1; 18435ac4fbd7Sbeveloper #if DEBUG >= 3 18445ac4fbd7Sbeveloper PRINT_OUTPUT(" input ", out_inputs[i]); 18455ac4fbd7Sbeveloper #endif 18463620737cSbeveloper if (buf_num_inputs == 0) 18473620737cSbeveloper break; 184852a38012Sejakowatz } 184952a38012Sejakowatz 18508b04ffc1Sbeveloper MediaRosterEx(this)->PublishInputs(node, &list); 18513620737cSbeveloper return B_OK; 185252a38012Sejakowatz } 185352a38012Sejakowatz 185452a38012Sejakowatz 185552a38012Sejakowatz status_t 185652a38012Sejakowatz BMediaRoster::GetFreeOutputsFor(const media_node& node, 185734c72144SAxel Dörfler media_output* out_free_outputs, int32 buf_num_outputs, 185834c72144SAxel Dörfler int32* out_total_count, media_type filter_type) 185952a38012Sejakowatz { 18603620737cSbeveloper CALLED(); 186140f36b03Sbeveloper if (IS_INVALID_NODE(node) || (node.kind & B_BUFFER_PRODUCER) == 0) 18623620737cSbeveloper return B_MEDIA_BAD_NODE; 18633620737cSbeveloper if (out_free_outputs == NULL || out_total_count == NULL) 18643620737cSbeveloper return B_BAD_VALUE; 18653620737cSbeveloper 186676669a29Sbeveloper List<media_output> list; 18673620737cSbeveloper media_output *output; 18683620737cSbeveloper status_t rv; 18693620737cSbeveloper 18701299bfb2Sbeveloper *out_total_count = 0; 18711299bfb2Sbeveloper 18728b04ffc1Sbeveloper rv = MediaRosterEx(this)->GetAllOutputs(node, &list); 18733620737cSbeveloper if (B_OK != rv) 18743620737cSbeveloper return rv; 18753620737cSbeveloper 1876332cc6bcSAxel Dörfler PRINT(4, "BMediaRoster::GetFreeOutputsFor node %" B_PRId32 ", max %" 1877332cc6bcSAxel Dörfler B_PRId32 ", filter-type %" B_PRId32 "\n", node.node, buf_num_outputs, 1878332cc6bcSAxel Dörfler filter_type); 18795ac4fbd7Sbeveloper 188076669a29Sbeveloper int32 i; 1881b65a0ac5SJérôme Duval for (i = 0, list.Rewind(); list.GetNext(&output);) { 188234c72144SAxel Dörfler if (filter_type != B_MEDIA_UNKNOWN_TYPE 188334c72144SAxel Dörfler && filter_type != output->format.type) { 188434c72144SAxel Dörfler // media_type used, but doesn't match 188534c72144SAxel Dörfler continue; 188634c72144SAxel Dörfler } 188734c72144SAxel Dörfler if (output->destination != media_destination::null) { 188834c72144SAxel Dörfler // producer destination already connected 188934c72144SAxel Dörfler continue; 189034c72144SAxel Dörfler } 189134c72144SAxel Dörfler 18923620737cSbeveloper out_free_outputs[i] = *output; 18933620737cSbeveloper *out_total_count += 1; 18943620737cSbeveloper buf_num_outputs -= 1; 18955ac4fbd7Sbeveloper #if DEBUG >= 3 18965ac4fbd7Sbeveloper PRINT_OUTPUT(" output ", out_free_outputs[i]); 18975ac4fbd7Sbeveloper #endif 18983620737cSbeveloper if (buf_num_outputs == 0) 18993620737cSbeveloper break; 1900b65a0ac5SJérôme Duval i++; 19013620737cSbeveloper } 19023620737cSbeveloper 19038b04ffc1Sbeveloper MediaRosterEx(this)->PublishOutputs(node, &list); 19043620737cSbeveloper return B_OK; 190552a38012Sejakowatz } 190652a38012Sejakowatz 190752a38012Sejakowatz 190852a38012Sejakowatz status_t 190952a38012Sejakowatz BMediaRoster::GetConnectedOutputsFor(const media_node& node, 191034c72144SAxel Dörfler media_output* out_active_outputs, int32 buf_num_outputs, 191152a38012Sejakowatz int32* out_total_count) 191252a38012Sejakowatz { 19133620737cSbeveloper CALLED(); 191440f36b03Sbeveloper if (IS_INVALID_NODE(node) || (node.kind & B_BUFFER_PRODUCER) == 0) 19153620737cSbeveloper return B_MEDIA_BAD_NODE; 19163620737cSbeveloper if (out_active_outputs == NULL || out_total_count == NULL) 19173620737cSbeveloper return B_BAD_VALUE; 19183620737cSbeveloper 191976669a29Sbeveloper List<media_output> list; 19203620737cSbeveloper media_output *output; 19213620737cSbeveloper status_t rv; 19223620737cSbeveloper 19231299bfb2Sbeveloper *out_total_count = 0; 19241299bfb2Sbeveloper 19258b04ffc1Sbeveloper rv = MediaRosterEx(this)->GetAllOutputs(node, &list); 19263620737cSbeveloper if (B_OK != rv) 19273620737cSbeveloper return rv; 19283620737cSbeveloper 1929332cc6bcSAxel Dörfler PRINT(4, "BMediaRoster::GetConnectedOutputsFor node %" B_PRId32 ", max %" 1930332cc6bcSAxel Dörfler B_PRId32 "\n", node.node, buf_num_outputs); 19315ac4fbd7Sbeveloper 193276669a29Sbeveloper int32 i; 1933b65a0ac5SJérôme Duval for (i = 0, list.Rewind(); list.GetNext(&output);) { 193434c72144SAxel Dörfler if (output->destination == media_destination::null) { 193534c72144SAxel Dörfler // producer destination not connected 193634c72144SAxel Dörfler continue; 193734c72144SAxel Dörfler } 19383620737cSbeveloper out_active_outputs[i] = *output; 19393620737cSbeveloper *out_total_count += 1; 19403620737cSbeveloper buf_num_outputs -= 1; 19415ac4fbd7Sbeveloper #if DEBUG >= 3 19425ac4fbd7Sbeveloper PRINT_OUTPUT(" output ", out_active_outputs[i]); 19435ac4fbd7Sbeveloper #endif 19443620737cSbeveloper if (buf_num_outputs == 0) 19453620737cSbeveloper break; 1946b65a0ac5SJérôme Duval i++; 19473620737cSbeveloper } 19483620737cSbeveloper 19498b04ffc1Sbeveloper MediaRosterEx(this)->PublishOutputs(node, &list); 19503620737cSbeveloper return B_OK; 195152a38012Sejakowatz } 195252a38012Sejakowatz 195352a38012Sejakowatz 195452a38012Sejakowatz status_t 195552a38012Sejakowatz BMediaRoster::GetAllOutputsFor(const media_node& node, 195634c72144SAxel Dörfler media_output* out_outputs, int32 buf_num_outputs, int32* out_total_count) 195752a38012Sejakowatz { 195852a38012Sejakowatz CALLED(); 195940f36b03Sbeveloper if (IS_INVALID_NODE(node) || (node.kind & B_BUFFER_PRODUCER) == 0) 196052a38012Sejakowatz return B_MEDIA_BAD_NODE; 196152a38012Sejakowatz if (out_outputs == NULL || out_total_count == NULL) 196252a38012Sejakowatz return B_BAD_VALUE; 196352a38012Sejakowatz 196476669a29Sbeveloper List<media_output> list; 19653620737cSbeveloper media_output *output; 196652a38012Sejakowatz status_t rv; 196752a38012Sejakowatz 19681299bfb2Sbeveloper *out_total_count = 0; 19691299bfb2Sbeveloper 19708b04ffc1Sbeveloper rv = MediaRosterEx(this)->GetAllOutputs(node, &list); 19713620737cSbeveloper if (B_OK != rv) 19723620737cSbeveloper return rv; 19733620737cSbeveloper 1974332cc6bcSAxel Dörfler PRINT(4, "BMediaRoster::GetAllOutputsFor node %" B_PRId32 ", max %" B_PRId32 1975332cc6bcSAxel Dörfler "\n", node.node, buf_num_outputs); 19765ac4fbd7Sbeveloper 197776669a29Sbeveloper int32 i; 197876669a29Sbeveloper for (i = 0, list.Rewind(); list.GetNext(&output); i++) { 19793620737cSbeveloper out_outputs[i] = *output; 198052a38012Sejakowatz *out_total_count += 1; 19813620737cSbeveloper buf_num_outputs -= 1; 19825ac4fbd7Sbeveloper #if DEBUG >= 3 19835ac4fbd7Sbeveloper PRINT_OUTPUT(" output ", out_outputs[i]); 19845ac4fbd7Sbeveloper #endif 19853620737cSbeveloper if (buf_num_outputs == 0) 19863620737cSbeveloper break; 198752a38012Sejakowatz } 198852a38012Sejakowatz 19898b04ffc1Sbeveloper MediaRosterEx(this)->PublishOutputs(node, &list); 19903620737cSbeveloper return B_OK; 199152a38012Sejakowatz } 199252a38012Sejakowatz 199352a38012Sejakowatz 199452a38012Sejakowatz status_t 199552a38012Sejakowatz BMediaRoster::StartWatching(const BMessenger& where) 199652a38012Sejakowatz { 1997eae26d3dSbeveloper CALLED(); 1998eae26d3dSbeveloper if (!where.IsValid()) { 19995ac4fbd7Sbeveloper ERROR("BMediaRoster::StartWatching: messenger invalid!\n"); 2000eae26d3dSbeveloper return B_BAD_VALUE; 2001eae26d3dSbeveloper } 200234c72144SAxel Dörfler return BPrivate::media::notifications::Register(where, media_node::null, 200334c72144SAxel Dörfler B_MEDIA_WILDCARD); 200452a38012Sejakowatz } 200552a38012Sejakowatz 200652a38012Sejakowatz 200752a38012Sejakowatz status_t 200834c72144SAxel Dörfler BMediaRoster::StartWatching(const BMessenger & where, int32 notificationType) 200952a38012Sejakowatz { 2010eae26d3dSbeveloper CALLED(); 2011eae26d3dSbeveloper if (!where.IsValid()) { 20125ac4fbd7Sbeveloper ERROR("BMediaRoster::StartWatching: messenger invalid!\n"); 2013eae26d3dSbeveloper return B_BAD_VALUE; 2014eae26d3dSbeveloper } 201534c72144SAxel Dörfler if (!BPrivate::media::notifications::IsValidNotificationRequest(false, 201634c72144SAxel Dörfler notificationType)) { 20175ac4fbd7Sbeveloper ERROR("BMediaRoster::StartWatching: notificationType invalid!\n"); 2018eae26d3dSbeveloper return B_BAD_VALUE; 2019eae26d3dSbeveloper } 202032afe10aSDario Casalinuovo 202132afe10aSDario Casalinuovo // NOTE: we support only explicitly B_MEDIA_SERVER_STARTED/QUIT 202232afe10aSDario Casalinuovo // notifications. This should be cleared in documentation. 202332afe10aSDario Casalinuovo 202434c72144SAxel Dörfler return BPrivate::media::notifications::Register(where, media_node::null, 202534c72144SAxel Dörfler notificationType); 202652a38012Sejakowatz } 202752a38012Sejakowatz 202852a38012Sejakowatz 202952a38012Sejakowatz status_t 203034c72144SAxel Dörfler BMediaRoster::StartWatching(const BMessenger& where, const media_node& node, 203152a38012Sejakowatz int32 notificationType) 203252a38012Sejakowatz { 2033eae26d3dSbeveloper CALLED(); 2034eae26d3dSbeveloper if (!where.IsValid()) { 20355ac4fbd7Sbeveloper ERROR("BMediaRoster::StartWatching: messenger invalid!\n"); 2036eae26d3dSbeveloper return B_BAD_VALUE; 2037eae26d3dSbeveloper } 203840f36b03Sbeveloper if (IS_INVALID_NODE(node)) { 20395ac4fbd7Sbeveloper ERROR("BMediaRoster::StartWatching: node invalid!\n"); 2040eae26d3dSbeveloper return B_MEDIA_BAD_NODE; 2041eae26d3dSbeveloper } 204234c72144SAxel Dörfler if (!BPrivate::media::notifications::IsValidNotificationRequest(true, 204334c72144SAxel Dörfler notificationType)) { 20445ac4fbd7Sbeveloper ERROR("BMediaRoster::StartWatching: notificationType invalid!\n"); 2045eae26d3dSbeveloper return B_BAD_VALUE; 2046eae26d3dSbeveloper } 204734c72144SAxel Dörfler return BPrivate::media::notifications::Register(where, node, 204834c72144SAxel Dörfler notificationType); 204952a38012Sejakowatz } 205052a38012Sejakowatz 205152a38012Sejakowatz 205252a38012Sejakowatz status_t 205352a38012Sejakowatz BMediaRoster::StopWatching(const BMessenger& where) 205452a38012Sejakowatz { 2055eae26d3dSbeveloper CALLED(); 2056eae26d3dSbeveloper // messenger may already be invalid, so we don't check this 205734c72144SAxel Dörfler return BPrivate::media::notifications::Unregister(where, media_node::null, 205834c72144SAxel Dörfler B_MEDIA_WILDCARD); 205952a38012Sejakowatz } 206052a38012Sejakowatz 206152a38012Sejakowatz 206252a38012Sejakowatz status_t 206334c72144SAxel Dörfler BMediaRoster::StopWatching(const BMessenger& where, int32 notificationType) 206452a38012Sejakowatz { 2065eae26d3dSbeveloper CALLED(); 2066eae26d3dSbeveloper // messenger may already be invalid, so we don't check this 206734c72144SAxel Dörfler if (!BPrivate::media::notifications::IsValidNotificationRequest(false, 206834c72144SAxel Dörfler notificationType)) { 20695ac4fbd7Sbeveloper ERROR("BMediaRoster::StopWatching: notificationType invalid!\n"); 2070eae26d3dSbeveloper return B_BAD_VALUE; 2071eae26d3dSbeveloper } 207234c72144SAxel Dörfler return BPrivate::media::notifications::Unregister(where, media_node::null, 207334c72144SAxel Dörfler notificationType); 207452a38012Sejakowatz } 207552a38012Sejakowatz 207652a38012Sejakowatz 207752a38012Sejakowatz status_t 207834c72144SAxel Dörfler BMediaRoster::StopWatching(const BMessenger& where, const media_node& node, 207952a38012Sejakowatz int32 notificationType) 208052a38012Sejakowatz { 2081eae26d3dSbeveloper CALLED(); 2082eae26d3dSbeveloper // messenger may already be invalid, so we don't check this 208340f36b03Sbeveloper if (IS_INVALID_NODE(node)) { 20845ac4fbd7Sbeveloper ERROR("BMediaRoster::StopWatching: node invalid!\n"); 2085eae26d3dSbeveloper return B_MEDIA_BAD_NODE; 2086eae26d3dSbeveloper } 208734c72144SAxel Dörfler if (!BPrivate::media::notifications::IsValidNotificationRequest(true, 208834c72144SAxel Dörfler notificationType)) { 20895ac4fbd7Sbeveloper ERROR("BMediaRoster::StopWatching: notificationType invalid!\n"); 2090eae26d3dSbeveloper return B_BAD_VALUE; 2091eae26d3dSbeveloper } 209234c72144SAxel Dörfler return BPrivate::media::notifications::Unregister(where, node, 209334c72144SAxel Dörfler notificationType); 209452a38012Sejakowatz } 209552a38012Sejakowatz 209652a38012Sejakowatz 209752a38012Sejakowatz status_t 209852a38012Sejakowatz BMediaRoster::RegisterNode(BMediaNode* node) 209952a38012Sejakowatz { 210054187cc6Sbeveloper CALLED(); 210154187cc6Sbeveloper // addon-id = -1 (unused), addon-flavor-id = 0 (unused, too) 210254187cc6Sbeveloper return MediaRosterEx(this)->RegisterNode(node, -1, 0); 210354187cc6Sbeveloper } 210454187cc6Sbeveloper 210554187cc6Sbeveloper 210654187cc6Sbeveloper status_t 21079c3b4706SAxel Dörfler BMediaRosterEx::RegisterNode(BMediaNode* node, media_addon_id addOnID, 21089dec2310SAxel Dörfler int32 flavorID) 210954187cc6Sbeveloper { 211052a38012Sejakowatz CALLED(); 211152a38012Sejakowatz if (node == NULL) 211252a38012Sejakowatz return B_BAD_VALUE; 211352a38012Sejakowatz 211454187cc6Sbeveloper // some sanity check 211554187cc6Sbeveloper // I'm not sure if the media kit warrants to call BMediaNode::AddOn() here. 211654187cc6Sbeveloper // Perhaps we don't need it. 21179dec2310SAxel Dörfler DEBUG_ONLY( 21189dec2310SAxel Dörfler int32 testFlavorID; 21199dec2310SAxel Dörfler BMediaAddOn* addon = node->AddOn(&testFlavorID); 21209dec2310SAxel Dörfler 21216813f2c7SIngo Weinhold ASSERT(addOnID == (addon != NULL ? addon->AddonID() : -1)); 2122e817f41eSFredrik Modéen // ASSERT(flavorID == testFlavorID); 21239dec2310SAxel Dörfler ); 212452a38012Sejakowatz 21259e9417d2Sbeveloper server_register_node_request request; 21269e9417d2Sbeveloper server_register_node_reply reply; 21279e9417d2Sbeveloper 21289c3b4706SAxel Dörfler request.add_on_id = addOnID; 21299c3b4706SAxel Dörfler request.flavor_id = flavorID; 21309e9417d2Sbeveloper strcpy(request.name, node->Name()); 21319e9417d2Sbeveloper request.kinds = node->Kinds(); 21329e9417d2Sbeveloper request.port = node->ControlPort(); 21339dec2310SAxel Dörfler request.team = BPrivate::current_team(); 21347bcdb362SDario Casalinuovo request.timesource_id = node->fTimeSourceID; 21359e9417d2Sbeveloper 213634c72144SAxel Dörfler TRACE("BMediaRoster::RegisterNode: sending SERVER_REGISTER_NODE: port " 2137332cc6bcSAxel Dörfler "%" B_PRId32 ", kinds 0x%" B_PRIx64 ", team %" B_PRId32 ", name '%s'\n", 2138332cc6bcSAxel Dörfler request.port, request.kinds, request.team, request.name); 21391299bfb2Sbeveloper 21409c3b4706SAxel Dörfler status_t status = QueryServer(SERVER_REGISTER_NODE, &request, 21419c3b4706SAxel Dörfler sizeof(request), &reply, sizeof(reply)); 21429c3b4706SAxel Dörfler if (status != B_OK) { 21439c3b4706SAxel Dörfler ERROR("BMediaRoster::RegisterNode: failed to register node %s: %s\n", 21449c3b4706SAxel Dörfler node->Name(), strerror(status)); 21459c3b4706SAxel Dörfler return status; 21469e9417d2Sbeveloper } 21479e9417d2Sbeveloper 214834c72144SAxel Dörfler TRACE("BMediaRoster::RegisterNode: QueryServer SERVER_REGISTER_NODE " 214934c72144SAxel Dörfler "finished\n"); 21504295907bSbeveloper 21518b04ffc1Sbeveloper // we are a friend class of BMediaNode and initialize this member variable 21529dec2310SAxel Dörfler node->fNodeID = reply.node_id; 21539dec2310SAxel Dörfler ASSERT(reply.node_id == node->Node().node); 21549dec2310SAxel Dörfler ASSERT(reply.node_id == node->ID()); 21559e9417d2Sbeveloper 215634c72144SAxel Dörfler // if the BMediaNode also inherits from BTimeSource, we need to call 215734c72144SAxel Dörfler // BTimeSource::FinishCreate() 21589c3b4706SAxel Dörfler if ((node->Kinds() & B_TIME_SOURCE) != 0) { 21599c3b4706SAxel Dörfler if (BTimeSource* timeSource = dynamic_cast<BTimeSource*>(node)) 21609c3b4706SAxel Dörfler timeSource->FinishCreate(); 21610e21b167Sbeveloper } 21620e21b167Sbeveloper 216311ed4f9fSDario Casalinuovo // call the callback 216411ed4f9fSDario Casalinuovo node->NodeRegistered(); 216511ed4f9fSDario Casalinuovo 216611ed4f9fSDario Casalinuovo TRACE("BMediaRoster::RegisterNode: NodeRegistered callback finished\n"); 216711ed4f9fSDario Casalinuovo 21684295907bSbeveloper TRACE("BMediaRoster::RegisterNode: publishing inputs/outputs\n"); 21694295907bSbeveloper 21703620737cSbeveloper // register existing inputs and outputs with the 21713620737cSbeveloper // media_server, this allows GetLiveNodes() to work 21723620737cSbeveloper // with created, but unconnected nodes. 21734d2d96e0Sbeveloper // The node control loop might not be running, or might deadlock 21744d2d96e0Sbeveloper // if we send a message and wait for a reply here. 21754d2d96e0Sbeveloper // We have a pointer to the node, and thus call the functions directly 21764295907bSbeveloper 21779c3b4706SAxel Dörfler if ((node->Kinds() & B_BUFFER_PRODUCER) != 0) { 21789c3b4706SAxel Dörfler if (BBufferProducer* producer = dynamic_cast<BBufferProducer*>(node)) { 2179359ac306Sbeveloper List<media_output> list; 21809c3b4706SAxel Dörfler if (GetAllOutputs(producer, &list) == B_OK) 2181359ac306Sbeveloper PublishOutputs(node->Node(), &list); 218221871f38Sbeveloper } 21834d2d96e0Sbeveloper } 21849dec2310SAxel Dörfler if ((node->Kinds() & B_BUFFER_CONSUMER) != 0) { 21859c3b4706SAxel Dörfler if (BBufferConsumer* consumer = dynamic_cast<BBufferConsumer*>(node)) { 2186359ac306Sbeveloper List<media_input> list; 21879dec2310SAxel Dörfler if (GetAllInputs(consumer, &list) == B_OK) 2188359ac306Sbeveloper PublishInputs(node->Node(), &list); 21893620737cSbeveloper } 21904d2d96e0Sbeveloper } 219121871f38Sbeveloper 21924295907bSbeveloper TRACE("BMediaRoster::RegisterNode: sending NodesCreated\n"); 21934295907bSbeveloper 21949dec2310SAxel Dörfler BPrivate::media::notifications::NodesCreated(&reply.node_id, 1); 21954295907bSbeveloper 21964295907bSbeveloper TRACE("BMediaRoster::RegisterNode: finished\n"); 21974295907bSbeveloper 2198570f7d04Sbeveloper /* 21999c3b4706SAxel Dörfler TRACE("BMediaRoster::RegisterNode: registered node name '%s', id %ld, 22009c3b4706SAxel Dörfler addon %ld, flavor %ld\n", node->Name(), node->ID(), addOnID, flavorID); 2201570f7d04Sbeveloper TRACE("BMediaRoster::RegisterNode: node this %p\n", node); 22029c3b4706SAxel Dörfler TRACE("BMediaRoster::RegisterNode: node fConsumerThis %p\n", 22039c3b4706SAxel Dörfler node->fConsumerThis); 22049c3b4706SAxel Dörfler TRACE("BMediaRoster::RegisterNode: node fProducerThis %p\n", 22059c3b4706SAxel Dörfler node->fProducerThis); 22069c3b4706SAxel Dörfler TRACE("BMediaRoster::RegisterNode: node fFileInterfaceThis %p\n", 22079c3b4706SAxel Dörfler node->fFileInterfaceThis); 22089c3b4706SAxel Dörfler TRACE("BMediaRoster::RegisterNode: node fControllableThis %p\n", 22099c3b4706SAxel Dörfler node->fControllableThis); 22109c3b4706SAxel Dörfler TRACE("BMediaRoster::RegisterNode: node fTimeSourceThis %p\n", 22119c3b4706SAxel Dörfler node->fTimeSourceThis); 2212570f7d04Sbeveloper */ 22139e9417d2Sbeveloper return B_OK; 221452a38012Sejakowatz } 221552a38012Sejakowatz 221652a38012Sejakowatz 221752a38012Sejakowatz status_t 221852a38012Sejakowatz BMediaRoster::UnregisterNode(BMediaNode* node) 221952a38012Sejakowatz { 22209e9417d2Sbeveloper CALLED(); 22219e9417d2Sbeveloper if (node == NULL) 22229e9417d2Sbeveloper return B_BAD_VALUE; 22239e9417d2Sbeveloper 22242ceb090fSDario Casalinuovo TRACE("BMediaRoster::UnregisterNode %" 22252ceb090fSDario Casalinuovo B_PRId32 " (%p)\n", node->ID(), node); 222660f15390Sbeveloper 222729bb91d6SAxel Dörfler if ((node->fKinds & NODE_KIND_NO_REFCOUNTING) !=0) { 222834c72144SAxel Dörfler TRACE("BMediaRoster::UnregisterNode, trying to unregister reference " 22292ceb090fSDario Casalinuovo "counting disabled timesource, node %" 22302ceb090fSDario Casalinuovo B_PRId32 " , port %" B_PRId32 " , team %" B_PRId32 "\n", 22319dec2310SAxel Dörfler node->ID(), node->ControlPort(), BPrivate::current_team()); 223286bce45bSbeveloper return B_OK; 223386bce45bSbeveloper } 22348b04ffc1Sbeveloper if (node->ID() == NODE_UNREGISTERED_ID) { 223534c72144SAxel Dörfler PRINT(1, "Warning: BMediaRoster::UnregisterNode: node id %ld, name " 223634c72144SAxel Dörfler "'%s' already unregistered\n", node->ID(), node->Name()); 22379e9417d2Sbeveloper return B_OK; 22389e9417d2Sbeveloper } 223954187cc6Sbeveloper if (node->fRefCount != 0) { 224034c72144SAxel Dörfler PRINT(1, "Warning: BMediaRoster::UnregisterNode: node id %ld, name " 224134c72144SAxel Dörfler "'%s' has local reference count of %ld\n", node->ID(), node->Name(), 224234c72144SAxel Dörfler node->fRefCount); 224354187cc6Sbeveloper // no return here, we continue and unregister! 224454187cc6Sbeveloper } 224554187cc6Sbeveloper 224634c72144SAxel Dörfler // Calling BMediaAddOn::GetConfigurationFor(BMediaNode *node, 224734c72144SAxel Dörfler // BMessage *config) if this node was instanciated by an add-on needs to 224834c72144SAxel Dörfler // be done *somewhere* 224954187cc6Sbeveloper // We can't do it here because it is already to late (destructor of the node 225054187cc6Sbeveloper // might have been called). 22519e9417d2Sbeveloper 22529e9417d2Sbeveloper server_unregister_node_request request; 22539dec2310SAxel Dörfler request.node_id = node->ID(); 22549dec2310SAxel Dörfler request.team = BPrivate::current_team(); 22559e9417d2Sbeveloper 22561299bfb2Sbeveloper // send a notification 22579dec2310SAxel Dörfler BPrivate::media::notifications::NodesDeleted(&request.node_id, 1); 22581299bfb2Sbeveloper 225929bb91d6SAxel Dörfler server_unregister_node_reply reply; 2260c74afb57SJérôme Duval reply.add_on_id = -1; 226129bb91d6SAxel Dörfler status_t status = QueryServer(SERVER_UNREGISTER_NODE, &request, 226229bb91d6SAxel Dörfler sizeof(request), &reply, sizeof(reply)); 226329bb91d6SAxel Dörfler if (status != B_OK) { 2264332cc6bcSAxel Dörfler ERROR("BMediaRoster::UnregisterNode: failed to unregister node id %" 2265332cc6bcSAxel Dörfler B_PRId32 ", name '%s': %s\n", node->ID(), node->Name(), 2266332cc6bcSAxel Dörfler strerror(status)); 2267c74afb57SJérôme Duval BMediaAddOn *addon = node->AddOn(&reply.flavor_id); 2268c74afb57SJérôme Duval if (addon != NULL) 2269c74afb57SJérôme Duval reply.add_on_id = addon->AddonID(); 22709e9417d2Sbeveloper } 22719e9417d2Sbeveloper 22729c3b4706SAxel Dörfler if (reply.add_on_id != -1) { 227329bb91d6SAxel Dörfler // TODO: this doesn't look right 227429bb91d6SAxel Dörfler // Small problem here, we can't use DormantNodeManager::PutAddOn(), as 227534c72144SAxel Dörfler // UnregisterNode() is called by a dormant node itself (by the 227634c72144SAxel Dörfler // destructor). 227754187cc6Sbeveloper // The add-on that contains the node needs to remain in memory until the 227854187cc6Sbeveloper // destructor execution is finished. 227929bb91d6SAxel Dörfler // DormantNodeManager::PutAddOnDelayed() will delay unloading. 22809c3b4706SAxel Dörfler gDormantNodeManager->PutAddOnDelayed(reply.add_on_id); 2281cf4e2277Sbeveloper 228229bb91d6SAxel Dörfler status = MediaRosterEx(this)->DecrementAddonFlavorInstancesCount( 22839c3b4706SAxel Dörfler reply.add_on_id, reply.flavor_id); 228429bb91d6SAxel Dörfler if (status != B_OK) { 228534c72144SAxel Dörfler ERROR("BMediaRoster::UnregisterNode: " 228634c72144SAxel Dörfler "DecrementAddonFlavorInstancesCount() failed\n"); 228754187cc6Sbeveloper // this is really a problem, but we can't fail now 228854187cc6Sbeveloper } 22898b04ffc1Sbeveloper } 22909e9417d2Sbeveloper 22911299bfb2Sbeveloper // we are a friend class of BMediaNode and invalidate this member variable 22928b04ffc1Sbeveloper node->fNodeID = NODE_UNREGISTERED_ID; 22939e9417d2Sbeveloper 2294c74afb57SJérôme Duval return status; 229552a38012Sejakowatz } 229652a38012Sejakowatz 229752a38012Sejakowatz 229834c72144SAxel Dörfler //! Thread safe for multiple calls to Roster() 229952a38012Sejakowatz /*static*/ BMediaRoster* 230052a38012Sejakowatz BMediaRoster::Roster(status_t* out_error) 230152a38012Sejakowatz { 2302d15321ffSDario Casalinuovo BAutolock lock(sInitLocker); 2303d15321ffSDario Casalinuovo 230405962bb1SDario Casalinuovo if (be_app == NULL) 230534619a6fSDario Casalinuovo TRACE("Warning! You should have a valid BApplication."); 230605962bb1SDario Casalinuovo 2307d15321ffSDario Casalinuovo if (!lock.IsLocked()) 2308d15321ffSDario Casalinuovo return NULL; 2309d15321ffSDario Casalinuovo 23108496c38aSbeveloper if (out_error) 23118496c38aSbeveloper *out_error = B_OK; 2312d15321ffSDario Casalinuovo 23139def3bf7SStephan Aßmus if (sDefaultInstance == NULL) { 23148496c38aSbeveloper status_t err; 23159def3bf7SStephan Aßmus sDefaultInstance = new (std::nothrow) BMediaRosterEx(&err); 23169def3bf7SStephan Aßmus if (sDefaultInstance == NULL) 2317a715f908SStephan Aßmus err = B_NO_MEMORY; 2318a715f908SStephan Aßmus else if (err != B_OK) { 23199def3bf7SStephan Aßmus if (sDefaultInstance) { 23209def3bf7SStephan Aßmus sDefaultInstance->Lock(); 23219def3bf7SStephan Aßmus sDefaultInstance->Quit(); 23229def3bf7SStephan Aßmus sDefaultInstance = NULL; 2323dcfb6bfcSJérôme Duval } 23248496c38aSbeveloper if (out_error) 23258496c38aSbeveloper *out_error = err; 232605962bb1SDario Casalinuovo } else if (be_app != NULL) { 232705962bb1SDario Casalinuovo be_app->RegisterLooper(sDefaultInstance); 23288496c38aSbeveloper } 232952a38012Sejakowatz } 233005962bb1SDario Casalinuovo 23319def3bf7SStephan Aßmus return sDefaultInstance; 233252a38012Sejakowatz } 233352a38012Sejakowatz 233452a38012Sejakowatz 233552a38012Sejakowatz /*static*/ BMediaRoster* 233652a38012Sejakowatz BMediaRoster::CurrentRoster() 233752a38012Sejakowatz { 23389def3bf7SStephan Aßmus return sDefaultInstance; 233952a38012Sejakowatz } 234052a38012Sejakowatz 234152a38012Sejakowatz 234252a38012Sejakowatz status_t 234334c72144SAxel Dörfler BMediaRoster::SetTimeSourceFor(media_node_id node, media_node_id time_source) 234452a38012Sejakowatz { 2345aac800c2Sbeveloper CALLED(); 234640f36b03Sbeveloper if (IS_INVALID_NODEID(node) || IS_INVALID_NODEID(time_source)) 2347aac800c2Sbeveloper return B_BAD_VALUE; 2348aac800c2Sbeveloper 2349aac800c2Sbeveloper media_node clone; 23507bcdb362SDario Casalinuovo // We need to get a clone of the node to have a port id 23517bcdb362SDario Casalinuovo status_t result = GetNodeFor(node, &clone); 23527bcdb362SDario Casalinuovo if (result == B_OK) { 23537bcdb362SDario Casalinuovo // We just send the request to set time_source-id as 23547bcdb362SDario Casalinuovo // timesource to the node, the NODE_SET_TIMESOURCE handler 23557bcdb362SDario Casalinuovo // code will do the real assignment. 2356aac800c2Sbeveloper result = B_OK; 2357aac800c2Sbeveloper node_set_timesource_command cmd; 2358aac800c2Sbeveloper cmd.timesource_id = time_source; 23597bcdb362SDario Casalinuovo result = SendToPort(clone.port, NODE_SET_TIMESOURCE, 23607bcdb362SDario Casalinuovo &cmd, sizeof(cmd)); 23617bcdb362SDario Casalinuovo if (result != B_OK) { 23627bcdb362SDario Casalinuovo ERROR("BMediaRoster::SetTimeSourceFor" 23637bcdb362SDario Casalinuovo "sending NODE_SET_TIMESOURCE failed, node id %" 23647bcdb362SDario Casalinuovo B_PRId32 "\n", clone.node); 23657bcdb362SDario Casalinuovo } 23667bcdb362SDario Casalinuovo // We release the clone 23677bcdb362SDario Casalinuovo result = ReleaseNode(clone); 23687bcdb362SDario Casalinuovo if (result != B_OK) { 23697bcdb362SDario Casalinuovo ERROR("BMediaRoster::SetTimeSourceFor, ReleaseNode failed," 23707bcdb362SDario Casalinuovo " node id %" B_PRId32 "\n", clone.node); 23717bcdb362SDario Casalinuovo } 23727bcdb362SDario Casalinuovo } else { 23737bcdb362SDario Casalinuovo ERROR("BMediaRoster::SetTimeSourceFor GetCloneForID failed, " 23747bcdb362SDario Casalinuovo "node id %" B_PRId32 "\n", node); 23757bcdb362SDario Casalinuovo } 23767bcdb362SDario Casalinuovo 23777bcdb362SDario Casalinuovo if (result == B_OK) { 23787bcdb362SDario Casalinuovo // Notify the server 23797bcdb362SDario Casalinuovo server_set_node_timesource_request request; 23807bcdb362SDario Casalinuovo server_set_node_timesource_reply reply; 23817bcdb362SDario Casalinuovo 23827bcdb362SDario Casalinuovo request.node_id = node; 23837bcdb362SDario Casalinuovo request.timesource_id = time_source; 23847bcdb362SDario Casalinuovo 23857bcdb362SDario Casalinuovo result = QueryServer(SERVER_SET_NODE_TIMESOURCE, &request, 23867bcdb362SDario Casalinuovo sizeof(request), &reply, sizeof(reply)); 23877bcdb362SDario Casalinuovo if (result != B_OK) { 238834c72144SAxel Dörfler ERROR("BMediaRoster::SetTimeSourceFor, sending NODE_SET_TIMESOURCE " 2389332cc6bcSAxel Dörfler "failed, node id %" B_PRId32 "\n", node); 23907bcdb362SDario Casalinuovo } else { 2391332cc6bcSAxel Dörfler TRACE("BMediaRoster::SetTimeSourceFor: node %" B_PRId32 " time source %" 23927bcdb362SDario Casalinuovo B_PRId32 " OK\n", node, time_source); 23937bcdb362SDario Casalinuovo } 23947bcdb362SDario Casalinuovo } 2395aac800c2Sbeveloper return result; 2396aac800c2Sbeveloper } 2397aac800c2Sbeveloper 239852a38012Sejakowatz 239952a38012Sejakowatz status_t 240034c72144SAxel Dörfler BMediaRoster::GetParameterWebFor(const media_node& node, BParameterWeb** _web) 240152a38012Sejakowatz { 240228ad138aSbeveloper CALLED(); 240334c72144SAxel Dörfler if (_web == NULL) 240428ad138aSbeveloper return B_BAD_VALUE; 240528ad138aSbeveloper if (IS_INVALID_NODE(node)) 240628ad138aSbeveloper return B_MEDIA_BAD_NODE; 240728ad138aSbeveloper if ((node.kind & B_CONTROLLABLE) == 0) 240828ad138aSbeveloper return B_MEDIA_BAD_NODE; 240928ad138aSbeveloper 241028ad138aSbeveloper controllable_get_parameter_web_request request; 241128ad138aSbeveloper controllable_get_parameter_web_reply reply; 241234c72144SAxel Dörfler int32 requestsize[] = {B_PAGE_SIZE, 4 * B_PAGE_SIZE, 16 * B_PAGE_SIZE, 241334c72144SAxel Dörfler 64 * B_PAGE_SIZE, 128 * B_PAGE_SIZE, 256 * B_PAGE_SIZE, 0}; 241428ad138aSbeveloper int32 size; 241528ad138aSbeveloper 241634c72144SAxel Dörfler // TODO: it might be better to query the node for the (current) parameter 241734c72144SAxel Dörfler // size first 241828ad138aSbeveloper for (int i = 0; (size = requestsize[i]) != 0; i++) { 241928ad138aSbeveloper status_t rv; 242028ad138aSbeveloper area_id area; 242128ad138aSbeveloper void *data; 242234c72144SAxel Dörfler area = create_area("parameter web data", &data, B_ANY_ADDRESS, size, 2423*964cab46SAugustin Cavalier B_NO_LOCK, B_READ_AREA | B_WRITE_AREA | B_CLONEABLE_AREA); 242428ad138aSbeveloper if (area < B_OK) { 242534c72144SAxel Dörfler ERROR("BMediaRoster::GetParameterWebFor couldn't create area of " 2426332cc6bcSAxel Dörfler "size %" B_PRId32 "\n", size); 242728ad138aSbeveloper return B_ERROR; 242828ad138aSbeveloper } 242934c72144SAxel Dörfler request.max_size = size; 243028ad138aSbeveloper request.area = area; 243134c72144SAxel Dörfler rv = QueryPort(node.port, CONTROLLABLE_GET_PARAMETER_WEB, &request, 243234c72144SAxel Dörfler sizeof(request), &reply, sizeof(reply)); 243328ad138aSbeveloper if (rv != B_OK) { 243434c72144SAxel Dörfler ERROR("BMediaRoster::GetParameterWebFor " 243534c72144SAxel Dörfler "CONTROLLABLE_GET_PARAMETER_WEB failed\n"); 243628ad138aSbeveloper delete_area(area); 243728ad138aSbeveloper return B_ERROR; 243828ad138aSbeveloper } 243928ad138aSbeveloper if (reply.size == 0) { 244028ad138aSbeveloper // no parameter web available 244134c72144SAxel Dörfler // TODO: should we return an error? 2442332cc6bcSAxel Dörfler ERROR("BMediaRoster::GetParameterWebFor node %" B_PRId32 2443332cc6bcSAxel Dörfler " has no parameter web\n", node.node); 244434c72144SAxel Dörfler *_web = new (std::nothrow) BParameterWeb(); 244528ad138aSbeveloper delete_area(area); 244634c72144SAxel Dörfler return *_web != NULL ? B_OK : B_NO_MEMORY; 244752a38012Sejakowatz } 244828ad138aSbeveloper if (reply.size > 0) { 244928ad138aSbeveloper // we got a flattened parameter web! 2450df612ac9SRene Gollent BParameterWeb* web = new (std::nothrow) BParameterWeb(); 2451df612ac9SRene Gollent if (web == NULL) 2452a715f908SStephan Aßmus rv = B_NO_MEMORY; 2453a715f908SStephan Aßmus else { 2454df612ac9SRene Gollent rv = web->Unflatten(reply.code, data, reply.size); 245528ad138aSbeveloper if (rv != B_OK) { 245634c72144SAxel Dörfler ERROR("BMediaRoster::GetParameterWebFor Unflatten failed, " 245734c72144SAxel Dörfler "%s\n", strerror(rv)); 2458df612ac9SRene Gollent delete web; 2459df612ac9SRene Gollent } else 2460df612ac9SRene Gollent *_web = web; 246128ad138aSbeveloper } 2462df612ac9SRene Gollent 246328ad138aSbeveloper delete_area(area); 2464a715f908SStephan Aßmus return rv; 246528ad138aSbeveloper } 246628ad138aSbeveloper delete_area(area); 246728ad138aSbeveloper ASSERT(reply.size == -1); 246828ad138aSbeveloper // parameter web data was too large 246928ad138aSbeveloper // loop and try a larger size 247028ad138aSbeveloper } 2471332cc6bcSAxel Dörfler ERROR("BMediaRoster::GetParameterWebFor node %" B_PRId32 " has no " 2472332cc6bcSAxel Dörfler "parameter web larger than %" B_PRId32 "\n", node.node, size); 247328ad138aSbeveloper return B_ERROR; 247428ad138aSbeveloper } 247552a38012Sejakowatz 247652a38012Sejakowatz 247752a38012Sejakowatz status_t 247834c72144SAxel Dörfler BMediaRoster::StartControlPanel(const media_node& node, BMessenger* _messenger) 247952a38012Sejakowatz { 2480999cd0acSMaurice Kalinowski CALLED(); 2481999cd0acSMaurice Kalinowski 2482999cd0acSMaurice Kalinowski controllable_start_control_panel_request request; 2483999cd0acSMaurice Kalinowski controllable_start_control_panel_reply reply; 2484999cd0acSMaurice Kalinowski 2485999cd0acSMaurice Kalinowski request.node = node; 2486999cd0acSMaurice Kalinowski 2487999cd0acSMaurice Kalinowski status_t rv; 248834c72144SAxel Dörfler rv = QueryPort(node.port, CONTROLLABLE_START_CONTROL_PANEL, &request, 248934c72144SAxel Dörfler sizeof(request), &reply, sizeof(reply)); 2490999cd0acSMaurice Kalinowski if (rv != B_OK) 2491999cd0acSMaurice Kalinowski return rv; 2492999cd0acSMaurice Kalinowski 249334c72144SAxel Dörfler if (reply.team != -1 && _messenger != NULL) 249434c72144SAxel Dörfler *_messenger = BMessenger(NULL, reply.team); 2495999cd0acSMaurice Kalinowski 2496999cd0acSMaurice Kalinowski return B_OK; 249752a38012Sejakowatz } 249852a38012Sejakowatz 249952a38012Sejakowatz 250052a38012Sejakowatz status_t 250134c72144SAxel Dörfler BMediaRoster::GetDormantNodes(dormant_node_info* _info, int32* _count, 250234c72144SAxel Dörfler const media_format* hasInput, const media_format* hasOutput, 250334c72144SAxel Dörfler const char* name, uint64 requireKinds, uint64 denyKinds) 250452a38012Sejakowatz { 250552a38012Sejakowatz CALLED(); 250634c72144SAxel Dörfler if (_info == NULL || _count == NULL || *_count <= 0) 250752a38012Sejakowatz return B_BAD_VALUE; 250852a38012Sejakowatz 2509e4c87231SAxel Dörfler server_get_dormant_nodes_request request; 2510e4c87231SAxel Dörfler request.max_count = *_count; 2511e4c87231SAxel Dörfler request.has_input = hasInput != NULL; 251234c72144SAxel Dörfler if (hasInput != NULL) { 251334c72144SAxel Dörfler // TODO: we should not make a flat copy of media_format 2514e4c87231SAxel Dörfler request.input_format = *hasInput; 251534c72144SAxel Dörfler } 2516e4c87231SAxel Dörfler request.has_output = hasOutput != NULL; 251734c72144SAxel Dörfler if (hasOutput != NULL) { 251834c72144SAxel Dörfler // TODO: we should not make a flat copy of media_format 2519e4c87231SAxel Dörfler request.output_format = *hasOutput; 252034c72144SAxel Dörfler } 252134c72144SAxel Dörfler 2522e4c87231SAxel Dörfler request.has_name = name != NULL; 2523e4c87231SAxel Dörfler if (name != NULL) 2524e4c87231SAxel Dörfler strlcpy(request.name, name, sizeof(request.name)); 252552a38012Sejakowatz 2526e4c87231SAxel Dörfler request.require_kinds = requireKinds; 2527e4c87231SAxel Dörfler request.deny_kinds = denyKinds; 252852a38012Sejakowatz 2529e4c87231SAxel Dörfler server_get_dormant_nodes_reply reply; 2530e4c87231SAxel Dörfler status_t status = QueryServer(SERVER_GET_DORMANT_NODES, &request, 2531e4c87231SAxel Dörfler sizeof(request), &reply, sizeof(reply)); 25326cafce94SAxel Dörfler if (status != B_OK) 2533e4c87231SAxel Dörfler return status; 253452a38012Sejakowatz 253534c72144SAxel Dörfler *_count = reply.count; 253652a38012Sejakowatz 2537e4c87231SAxel Dörfler if (reply.count > 0) { 2538e4c87231SAxel Dörfler int32 code; 2539e4c87231SAxel Dörfler status = read_port(request.reply_port, &code, _info, 2540e4c87231SAxel Dörfler reply.count * sizeof(dormant_node_info)); 2541e4c87231SAxel Dörfler if (status < B_OK) 2542e4c87231SAxel Dörfler reply.result = status; 254352a38012Sejakowatz } 254452a38012Sejakowatz 254552a38012Sejakowatz return reply.result; 254652a38012Sejakowatz } 254752a38012Sejakowatz 2548e4c87231SAxel Dörfler 254934c72144SAxel Dörfler /*! This function is used to do the real work of instantiating a dormant node. 255034c72144SAxel Dörfler It is either called by the media_addon_server to instantiate a global node, 255134c72144SAxel Dörfler or it gets called from BMediaRoster::InstantiateDormantNode() to create a 255234c72144SAxel Dörfler local one. 255334c72144SAxel Dörfler 255434c72144SAxel Dörfler Checks concerning global/local are not done here. 25558b04ffc1Sbeveloper */ 255652a38012Sejakowatz status_t 255734c72144SAxel Dörfler BMediaRosterEx::InstantiateDormantNode(media_addon_id addonID, int32 flavorID, 255834c72144SAxel Dörfler team_id creator, media_node *_node) 255952a38012Sejakowatz { 256054187cc6Sbeveloper // This function is always called from the correct context, if the node 256154187cc6Sbeveloper // is supposed to be global, it is called from the media_addon_server. 256254187cc6Sbeveloper 256352a38012Sejakowatz // if B_FLAVOR_IS_GLOBAL, we need to use the BMediaAddOn object that 256452a38012Sejakowatz // resides in the media_addon_server 256552a38012Sejakowatz 25668b04ffc1Sbeveloper // RegisterNode() must be called for nodes instantiated from add-ons, 25678b04ffc1Sbeveloper // since the media kit warrants that it's done automatically. 256852a38012Sejakowatz 256934c72144SAxel Dörfler // addonID Indicates the ID number of the media add-on in which the 257034c72144SAxel Dörfler // node resides. 257134c72144SAxel Dörfler // flavorID Indicates the internal ID number that the add-on uses to 257234c72144SAxel Dörfler // identify the flavor, this is the number that was published 257334c72144SAxel Dörfler // by BMediaAddOn::GetFlavorAt() in the 25748b04ffc1Sbeveloper // flavor_info::internal_id field. 257534c72144SAxel Dörfler // creator The creator team is -1 if nodes are created locally. If 257634c72144SAxel Dörfler // created globally, it will contain (while called in 257734c72144SAxel Dörfler // media_addon_server context) the team-id of the team that 257834c72144SAxel Dörfler // requested the instantiation. 25798b04ffc1Sbeveloper 2580332cc6bcSAxel Dörfler TRACE("BMediaRosterEx::InstantiateDormantNode: addonID %" B_PRId32 2581332cc6bcSAxel Dörfler ", flavorID %" B_PRId32 "\n", addonID, flavorID); 25828b04ffc1Sbeveloper 25838b04ffc1Sbeveloper // Get flavor_info from the server 258434c72144SAxel Dörfler dormant_flavor_info info; 25858c6a6096Sbeveloper status_t rv; 258634c72144SAxel Dörfler rv = GetDormantFlavorInfo(addonID, flavorID, &info); 25878b04ffc1Sbeveloper if (rv != B_OK) { 258834c72144SAxel Dörfler ERROR("BMediaRosterEx::InstantiateDormantNode error: failed to get " 2589332cc6bcSAxel Dörfler "dormant_flavor_info for addon-id %" B_PRId32 ", flavor-id %" 2590332cc6bcSAxel Dörfler B_PRId32 "\n", addonID, flavorID); 259152a38012Sejakowatz return B_ERROR; 259252a38012Sejakowatz } 25938b04ffc1Sbeveloper 25941ecccf18SFrançois Revol ASSERT(info.internal_id == flavorID); 25958b04ffc1Sbeveloper 25968b04ffc1Sbeveloper // load the BMediaAddOn object 259729bb91d6SAxel Dörfler BMediaAddOn* addon = gDormantNodeManager->GetAddOn(addonID); 259834c72144SAxel Dörfler if (addon == NULL) { 25995ac4fbd7Sbeveloper ERROR("BMediaRosterEx::InstantiateDormantNode: GetAddon failed\n"); 26008b04ffc1Sbeveloper return B_ERROR; 26018b04ffc1Sbeveloper } 26028b04ffc1Sbeveloper 260354187cc6Sbeveloper // Now we need to try to increment the use count of this addon flavor 260454187cc6Sbeveloper // in the server. This can fail if the total number instances of this 260554187cc6Sbeveloper // flavor is limited. 260634c72144SAxel Dörfler rv = IncrementAddonFlavorInstancesCount(addonID, flavorID); 260754187cc6Sbeveloper if (rv != B_OK) { 260834c72144SAxel Dörfler ERROR("BMediaRosterEx::InstantiateDormantNode error: can't create " 2609332cc6bcSAxel Dörfler "more nodes for addon-id %" B_PRId32 ", flavor-id %" B_PRId32 "\n", 2610332cc6bcSAxel Dörfler addonID, flavorID); 261154187cc6Sbeveloper // Put the addon back into the pool 261229bb91d6SAxel Dörfler gDormantNodeManager->PutAddOn(addonID); 261354187cc6Sbeveloper return B_ERROR; 261454187cc6Sbeveloper } 261554187cc6Sbeveloper 26168b04ffc1Sbeveloper BMessage config; 261734c72144SAxel Dörfler rv = LoadNodeConfiguration(addonID, flavorID, &config); 261854187cc6Sbeveloper if (rv != B_OK) { 261934c72144SAxel Dörfler ERROR("BMediaRosterEx::InstantiateDormantNode: couldn't load " 2620332cc6bcSAxel Dörfler "configuration for addon-id %" B_PRId32 ", flavor-id %" B_PRId32 2621332cc6bcSAxel Dörfler "\n", addonID, flavorID); 262254187cc6Sbeveloper // do not return, this is a minor problem, not a reason to fail 262354187cc6Sbeveloper } 26248b04ffc1Sbeveloper 262534c72144SAxel Dörfler status_t status = B_OK; 262634c72144SAxel Dörfler BMediaNode* node = addon->InstantiateNodeFor(&info, &config, &status); 262734c72144SAxel Dörfler if (node == NULL) { 262834c72144SAxel Dörfler ERROR("BMediaRosterEx::InstantiateDormantNode: InstantiateNodeFor " 262934c72144SAxel Dörfler "failed\n"); 26308b04ffc1Sbeveloper 263154187cc6Sbeveloper // Put the addon back into the pool 263229bb91d6SAxel Dörfler gDormantNodeManager->PutAddOn(addonID); 263334c72144SAxel Dörfler 263454187cc6Sbeveloper // We must decrement the use count of this addon flavor in the 263554187cc6Sbeveloper // server to compensate the increment done in the beginning. 263634c72144SAxel Dörfler rv = DecrementAddonFlavorInstancesCount(addonID, flavorID); 263754187cc6Sbeveloper if (rv != B_OK) { 263834c72144SAxel Dörfler ERROR("BMediaRosterEx::InstantiateDormantNode: DecrementAddon" 263934c72144SAxel Dörfler "FlavorInstancesCount failed\n"); 264016b7eea4Sbeveloper } 264134c72144SAxel Dörfler return status != B_OK ? status : B_ERROR; 264254187cc6Sbeveloper } 264354187cc6Sbeveloper 264434c72144SAxel Dörfler rv = RegisterNode(node, addonID, flavorID); 26458c6a6096Sbeveloper if (rv != B_OK) { 26465ac4fbd7Sbeveloper ERROR("BMediaRosterEx::InstantiateDormantNode: RegisterNode failed\n"); 26478c6a6096Sbeveloper delete node; 264854187cc6Sbeveloper // Put the addon back into the pool 264929bb91d6SAxel Dörfler gDormantNodeManager->PutAddOn(addonID); 265054187cc6Sbeveloper // We must decrement the use count of this addon flavor in the 265154187cc6Sbeveloper // server to compensate the increment done in the beginning. 265234c72144SAxel Dörfler rv = DecrementAddonFlavorInstancesCount(addonID, flavorID); 265354187cc6Sbeveloper if (rv != B_OK) { 265434c72144SAxel Dörfler ERROR("BMediaRosterEx::InstantiateDormantNode: DecrementAddon" 265534c72144SAxel Dörfler "FlavorInstancesCount failed\n"); 265654187cc6Sbeveloper } 26578c6a6096Sbeveloper return B_ERROR; 26588c6a6096Sbeveloper } 26598c6a6096Sbeveloper 266054187cc6Sbeveloper if (creator != -1) { 266134c72144SAxel Dörfler // send a message to the server to assign team "creator" as creator 266234c72144SAxel Dörfler // of node "node->ID()" 2663332cc6bcSAxel Dörfler printf("!!! BMediaRosterEx::InstantiateDormantNode assigning team %" 2664332cc6bcSAxel Dörfler B_PRId32 " as creator of node %" B_PRId32 "\n", creator, 2665332cc6bcSAxel Dörfler node->ID()); 266634c72144SAxel Dörfler 266754187cc6Sbeveloper rv = MediaRosterEx(this)->SetNodeCreator(node->ID(), creator); 266854187cc6Sbeveloper if (rv != B_OK) { 266934c72144SAxel Dörfler ERROR("BMediaRosterEx::InstantiateDormantNode failed to assign " 2670332cc6bcSAxel Dörfler "team %" B_PRId32 " as creator of node %" B_PRId32 "\n", 2671332cc6bcSAxel Dörfler creator, node->ID()); 267254187cc6Sbeveloper // do not return, this is a minor problem, not a reason to fail 267354187cc6Sbeveloper } 267454187cc6Sbeveloper } 267554187cc6Sbeveloper 267654187cc6Sbeveloper // RegisterNode() does remember the add-on id in the server 267754187cc6Sbeveloper // and UnregisterNode() will call DormantNodeManager::PutAddon() 267854187cc6Sbeveloper // when the node is unregistered. 26798c6a6096Sbeveloper 268034c72144SAxel Dörfler *_node = node->Node(); 2681cf4e2277Sbeveloper 2682332cc6bcSAxel Dörfler TRACE("BMediaRosterEx::InstantiateDormantNode: addon-id %" B_PRId32 2683332cc6bcSAxel Dörfler ", flavor_id %" B_PRId32 " instanciated as node %" B_PRId32 ", port %" 2684332cc6bcSAxel Dörfler B_PRId32 " in team %" B_PRId32 "\n", addonID, flavorID, _node->node, 2685332cc6bcSAxel Dörfler _node->port, BPrivate::current_team()); 2686cf4e2277Sbeveloper 268716b7eea4Sbeveloper return B_OK; 268816b7eea4Sbeveloper } 268952a38012Sejakowatz 269052a38012Sejakowatz 269152a38012Sejakowatz status_t 269234c72144SAxel Dörfler BMediaRoster::InstantiateDormantNode(const dormant_node_info& info, 269334c72144SAxel Dörfler media_node* _node, uint32 flags) 26948b04ffc1Sbeveloper { 26958b04ffc1Sbeveloper CALLED(); 269634c72144SAxel Dörfler if (_node == NULL) 26978b04ffc1Sbeveloper return B_BAD_VALUE; 269834c72144SAxel Dörfler if (info.addon <= B_OK) { 2699332cc6bcSAxel Dörfler ERROR("BMediaRoster::InstantiateDormantNode error: addon-id %" B_PRId32 270034c72144SAxel Dörfler " invalid.\n", info.addon); 27018b04ffc1Sbeveloper return B_BAD_VALUE; 27028b04ffc1Sbeveloper } 27038b04ffc1Sbeveloper 2704332cc6bcSAxel Dörfler printf("BMediaRoster::InstantiateDormantNode: addon-id %" B_PRId32 2705332cc6bcSAxel Dörfler ", flavor_id %" B_PRId32 ", flags 0x%" B_PRIx32 "\n", info.addon, 2706332cc6bcSAxel Dörfler info.flavor_id, flags); 27078b04ffc1Sbeveloper 27088b04ffc1Sbeveloper // Get flavor_info from the server 270934c72144SAxel Dörfler // TODO: this is a little overhead, as we get the full blown 271034c72144SAxel Dörfler // dormant_flavor_info, 271134c72144SAxel Dörfler // TODO: but only need the flags. 271234c72144SAxel Dörfler dormant_flavor_info flavorInfo; 27138b04ffc1Sbeveloper status_t rv; 271434c72144SAxel Dörfler rv = MediaRosterEx(this)->GetDormantFlavorInfo(info.addon, info.flavor_id, 271534c72144SAxel Dörfler &flavorInfo); 27168b04ffc1Sbeveloper if (rv != B_OK) { 271734c72144SAxel Dörfler ERROR("BMediaRoster::InstantiateDormantNode: failed to get " 2718332cc6bcSAxel Dörfler "dormant_flavor_info for addon-id %" B_PRId32 ", flavor-id %" 2719332cc6bcSAxel Dörfler B_PRId32 "\n", info.addon, info.flavor_id); 2720626824eaSbeveloper return B_NAME_NOT_FOUND; 27218b04ffc1Sbeveloper } 27228b04ffc1Sbeveloper 272334c72144SAxel Dörfler ASSERT(flavorInfo.internal_id == info.flavor_id); 27248b04ffc1Sbeveloper 27258b04ffc1Sbeveloper #if DEBUG 272634c72144SAxel Dörfler printf("BMediaRoster::InstantiateDormantNode: name \"%s\", info \"%s\", " 2727332cc6bcSAxel Dörfler "flavor_flags 0x%" B_PRIx32 ", internal_id %" B_PRId32 2728332cc6bcSAxel Dörfler ", possible_count %" B_PRId32 "\n", flavorInfo.name, flavorInfo.info, 2729332cc6bcSAxel Dörfler flavorInfo.flavor_flags, flavorInfo.internal_id, 2730332cc6bcSAxel Dörfler flavorInfo.possible_count); 273134c72144SAxel Dörfler 273234c72144SAxel Dörfler if ((flags & B_FLAVOR_IS_LOCAL) != 0) { 273334c72144SAxel Dörfler printf("BMediaRoster::InstantiateDormantNode: caller requested " 273434c72144SAxel Dörfler "B_FLAVOR_IS_LOCAL\n"); 273534c72144SAxel Dörfler } 273634c72144SAxel Dörfler if ((flags & B_FLAVOR_IS_GLOBAL) != 0) { 273734c72144SAxel Dörfler printf("BMediaRoster::InstantiateDormantNode: caller requested " 273834c72144SAxel Dörfler "B_FLAVOR_IS_GLOBAL\n"); 273934c72144SAxel Dörfler } 274034c72144SAxel Dörfler if ((flavorInfo.flavor_flags & B_FLAVOR_IS_LOCAL) != 0) { 274134c72144SAxel Dörfler printf("BMediaRoster::InstantiateDormantNode: node requires " 274234c72144SAxel Dörfler "B_FLAVOR_IS_LOCAL\n"); 274334c72144SAxel Dörfler } 274434c72144SAxel Dörfler if ((flavorInfo.flavor_flags & B_FLAVOR_IS_GLOBAL) != 0) { 274534c72144SAxel Dörfler printf("BMediaRoster::InstantiateDormantNode: node requires " 274634c72144SAxel Dörfler "B_FLAVOR_IS_GLOBAL\n"); 274734c72144SAxel Dörfler } 27488b04ffc1Sbeveloper #endif 27498b04ffc1Sbeveloper 27508b04ffc1Sbeveloper // Make sure that flags demanded by the dormant node and those requested 27518b04ffc1Sbeveloper // by the caller are not incompatible. 275234c72144SAxel Dörfler if ((flavorInfo.flavor_flags & B_FLAVOR_IS_GLOBAL) != 0 275334c72144SAxel Dörfler && (flags & B_FLAVOR_IS_LOCAL) != 0) { 275434c72144SAxel Dörfler ERROR("BMediaRoster::InstantiateDormantNode: requested " 275534c72144SAxel Dörfler "B_FLAVOR_IS_LOCAL, but dormant node has B_FLAVOR_IS_GLOBAL\n"); 2756626824eaSbeveloper return B_NAME_NOT_FOUND; 27578b04ffc1Sbeveloper } 275834c72144SAxel Dörfler if ((flavorInfo.flavor_flags & B_FLAVOR_IS_LOCAL) != 0 275934c72144SAxel Dörfler && (flags & B_FLAVOR_IS_GLOBAL) != 0) { 276034c72144SAxel Dörfler ERROR("BMediaRoster::InstantiateDormantNode: requested " 276134c72144SAxel Dörfler "B_FLAVOR_IS_GLOBAL, but dormant node has B_FLAVOR_IS_LOCAL\n"); 2762626824eaSbeveloper return B_NAME_NOT_FOUND; 27638b04ffc1Sbeveloper } 276454187cc6Sbeveloper 27658b04ffc1Sbeveloper // If either the node, or the caller requested to make the instance global 276634c72144SAxel Dörfler // we will do it by forwarding this request into the media_addon_server, 276734c72144SAxel Dörfler // which in turn will call BMediaRosterEx::InstantiateDormantNode to create 276834c72144SAxel Dörfler // the node there and make it globally available. 276934c72144SAxel Dörfler if ((flavorInfo.flavor_flags & B_FLAVOR_IS_GLOBAL) != 0 277034c72144SAxel Dörfler || (flags & B_FLAVOR_IS_GLOBAL) != 0) { 277134c72144SAxel Dörfler TRACE("BMediaRoster::InstantiateDormantNode: creating global object " 277234c72144SAxel Dörfler "in media_addon_server\n"); 2773cf4e2277Sbeveloper 27749c3b4706SAxel Dörfler add_on_server_instantiate_dormant_node_request request; 27759c3b4706SAxel Dörfler add_on_server_instantiate_dormant_node_reply reply; 27769c3b4706SAxel Dörfler request.add_on_id = info.addon; 27779dec2310SAxel Dörfler request.flavor_id = info.flavor_id; 27789dec2310SAxel Dörfler request.creator_team = BPrivate::current_team(); 277934c72144SAxel Dörfler // creator team is allowed to also release global nodes 27809c3b4706SAxel Dörfler rv = QueryAddOnServer(ADD_ON_SERVER_INSTANTIATE_DORMANT_NODE, &request, 278134c72144SAxel Dörfler sizeof(request), &reply, sizeof(reply)); 278234c72144SAxel Dörfler if (rv == B_OK) 278334c72144SAxel Dörfler *_node = reply.node; 27848b04ffc1Sbeveloper } else { 278554187cc6Sbeveloper // creator team = -1, as this is a local node 278634c72144SAxel Dörfler rv = MediaRosterEx(this)->InstantiateDormantNode(info.addon, 278734c72144SAxel Dörfler info.flavor_id, -1, _node); 27888b04ffc1Sbeveloper } 2789626824eaSbeveloper if (rv != B_OK) { 279034c72144SAxel Dörfler *_node = media_node::null; 2791626824eaSbeveloper return B_NAME_NOT_FOUND; 2792626824eaSbeveloper } 2793626824eaSbeveloper return B_OK; 27948b04ffc1Sbeveloper } 27958b04ffc1Sbeveloper 27968b04ffc1Sbeveloper 27978b04ffc1Sbeveloper status_t 279834c72144SAxel Dörfler BMediaRoster::InstantiateDormantNode(const dormant_node_info& info, 279934c72144SAxel Dörfler media_node* _node) 28008b04ffc1Sbeveloper { 280134c72144SAxel Dörfler return InstantiateDormantNode(info, _node, 0); 28028b04ffc1Sbeveloper } 28038b04ffc1Sbeveloper 28048b04ffc1Sbeveloper 28058b04ffc1Sbeveloper status_t 280652a38012Sejakowatz BMediaRoster::GetDormantNodeFor(const media_node& node, 280734c72144SAxel Dörfler dormant_node_info* _info) 280852a38012Sejakowatz { 280985dfab2bSbeveloper CALLED(); 281034c72144SAxel Dörfler if (_info == NULL) 281185dfab2bSbeveloper return B_BAD_VALUE; 281240f36b03Sbeveloper if (IS_INVALID_NODE(node)) 281385dfab2bSbeveloper return B_MEDIA_BAD_NODE; 281452a38012Sejakowatz 281585dfab2bSbeveloper server_get_dormant_node_for_request request; 281685dfab2bSbeveloper server_get_dormant_node_for_reply reply; 281785dfab2bSbeveloper status_t rv; 281885dfab2bSbeveloper 281985dfab2bSbeveloper request.node = node; 282085dfab2bSbeveloper 282134c72144SAxel Dörfler rv = QueryServer(SERVER_GET_DORMANT_NODE_FOR, &request, sizeof(request), 282234c72144SAxel Dörfler &reply, sizeof(reply)); 282385dfab2bSbeveloper if (rv != B_OK) 282485dfab2bSbeveloper return rv; 282585dfab2bSbeveloper 282634c72144SAxel Dörfler *_info = reply.node_info; 282785dfab2bSbeveloper return B_OK; 282852a38012Sejakowatz } 282952a38012Sejakowatz 283034c72144SAxel Dörfler 283152a38012Sejakowatz status_t 283234c72144SAxel Dörfler BMediaRosterEx::GetDormantFlavorInfo(media_addon_id addonID, int32 flavorID, 283334c72144SAxel Dörfler dormant_flavor_info* _flavor) 283452a38012Sejakowatz { 283552a38012Sejakowatz CALLED(); 283634c72144SAxel Dörfler if (_flavor == NULL) 28379bedd42cSbeveloper return B_BAD_VALUE; 283852a38012Sejakowatz 2839e4c87231SAxel Dörfler // TODO: better use an area here as well! 284052a38012Sejakowatz 2841e4c87231SAxel Dörfler server_get_dormant_flavor_info_reply* reply 2842e4c87231SAxel Dörfler = (server_get_dormant_flavor_info_reply*)malloc(16300); 284334c72144SAxel Dörfler if (reply == NULL) 284434c72144SAxel Dörfler return B_NO_MEMORY; 284552a38012Sejakowatz 2846e4c87231SAxel Dörfler server_get_dormant_flavor_info_request request; 2847e4c87231SAxel Dörfler request.add_on_id = addonID; 2848e4c87231SAxel Dörfler request.flavor_id = flavorID; 2849e4c87231SAxel Dörfler 2850e4c87231SAxel Dörfler status_t status = QueryServer(SERVER_GET_DORMANT_FLAVOR_INFO, &request, 2851e4c87231SAxel Dörfler sizeof(request), reply, 16300); 28529dec2310SAxel Dörfler if (status != B_OK) { 285352a38012Sejakowatz free(reply); 28549dec2310SAxel Dörfler return status; 285552a38012Sejakowatz } 285652a38012Sejakowatz 28579dec2310SAxel Dörfler if (reply->result == B_OK) { 28589dec2310SAxel Dörfler status = _flavor->Unflatten(reply->type, &reply->flattened_data, 28599dec2310SAxel Dörfler reply->flattened_size); 28609dec2310SAxel Dörfler } else 28619dec2310SAxel Dörfler status = reply->result; 286252a38012Sejakowatz 286352a38012Sejakowatz free(reply); 28649dec2310SAxel Dörfler return status; 286552a38012Sejakowatz } 286652a38012Sejakowatz 286734c72144SAxel Dörfler 28688b04ffc1Sbeveloper status_t 286934c72144SAxel Dörfler BMediaRoster::GetDormantFlavorInfoFor(const dormant_node_info& dormant, 287034c72144SAxel Dörfler dormant_flavor_info* _flavor) 28718b04ffc1Sbeveloper { 287234c72144SAxel Dörfler return MediaRosterEx(this)->GetDormantFlavorInfo(dormant.addon, 287334c72144SAxel Dörfler dormant.flavor_id, _flavor); 28748b04ffc1Sbeveloper } 287552a38012Sejakowatz 287634c72144SAxel Dörfler 287760f15390Sbeveloper // Reports in outLatency the maximum latency found downstream from 287860f15390Sbeveloper // the specified BBufferProducer, producer, given the current connections. 287952a38012Sejakowatz status_t 288034c72144SAxel Dörfler BMediaRoster::GetLatencyFor(const media_node& producer, bigtime_t* _latency) 288152a38012Sejakowatz { 288260f15390Sbeveloper CALLED(); 288334c72144SAxel Dörfler if (_latency == NULL) 288460f15390Sbeveloper return B_BAD_VALUE; 288534c72144SAxel Dörfler if (IS_INVALID_NODE(producer) 288634c72144SAxel Dörfler || (producer.kind & B_BUFFER_PRODUCER) == 0) 288760f15390Sbeveloper return B_MEDIA_BAD_NODE; 288860f15390Sbeveloper 288960f15390Sbeveloper producer_get_latency_request request; 289060f15390Sbeveloper producer_get_latency_reply reply; 289160f15390Sbeveloper status_t rv; 289260f15390Sbeveloper 289334c72144SAxel Dörfler rv = QueryPort(producer.port, PRODUCER_GET_LATENCY, &request, 289434c72144SAxel Dörfler sizeof(request), &reply, sizeof(reply)); 289560f15390Sbeveloper if (rv != B_OK) 289660f15390Sbeveloper return rv; 289760f15390Sbeveloper 289834c72144SAxel Dörfler *_latency = reply.latency; 289960f15390Sbeveloper 2900ab9afde3SMarcus Overhagen // printf("BMediaRoster::GetLatencyFor producer %ld has maximum latency %Ld\n", producer.node, *out_latency); 2901aac800c2Sbeveloper return B_OK; 290252a38012Sejakowatz } 290352a38012Sejakowatz 290452a38012Sejakowatz 290552a38012Sejakowatz status_t 290652a38012Sejakowatz BMediaRoster::GetInitialLatencyFor(const media_node& producer, 290734c72144SAxel Dörfler bigtime_t* _latency, uint32* _flags) 290852a38012Sejakowatz { 2909b65a0ac5SJérôme Duval CALLED(); 291034c72144SAxel Dörfler if (_latency == NULL) 2911b65a0ac5SJérôme Duval return B_BAD_VALUE; 291234c72144SAxel Dörfler if (IS_INVALID_NODE(producer) 291334c72144SAxel Dörfler || (producer.kind & B_BUFFER_PRODUCER) == 0) 2914b65a0ac5SJérôme Duval return B_MEDIA_BAD_NODE; 2915b65a0ac5SJérôme Duval 2916b65a0ac5SJérôme Duval producer_get_initial_latency_request request; 2917b65a0ac5SJérôme Duval producer_get_initial_latency_reply reply; 2918b65a0ac5SJérôme Duval status_t rv; 2919b65a0ac5SJérôme Duval 292034c72144SAxel Dörfler rv = QueryPort(producer.port, PRODUCER_GET_INITIAL_LATENCY, &request, 292134c72144SAxel Dörfler sizeof(request), &reply, sizeof(reply)); 2922b65a0ac5SJérôme Duval if (rv != B_OK) 2923b65a0ac5SJérôme Duval return rv; 2924b65a0ac5SJérôme Duval 292534c72144SAxel Dörfler *_latency = reply.initial_latency; 292634c72144SAxel Dörfler if (_flags != NULL) 292734c72144SAxel Dörfler *_flags = reply.flags; 2928b65a0ac5SJérôme Duval 2929332cc6bcSAxel Dörfler TRACE("BMediaRoster::GetInitialLatencyFor producer %" B_PRId32 " has " 2930332cc6bcSAxel Dörfler "maximum initial latency %" B_PRId64 "\n", producer.node, *_latency); 2931aac800c2Sbeveloper return B_OK; 293252a38012Sejakowatz } 293352a38012Sejakowatz 293452a38012Sejakowatz 293552a38012Sejakowatz status_t 293634c72144SAxel Dörfler BMediaRoster::GetStartLatencyFor(const media_node& timeSource, 293734c72144SAxel Dörfler bigtime_t* _latency) 293852a38012Sejakowatz { 2939fc8b28b6SJérôme Duval CALLED(); 294034c72144SAxel Dörfler if (_latency == NULL) 2941fc8b28b6SJérôme Duval return B_BAD_VALUE; 294234c72144SAxel Dörfler if (IS_INVALID_NODE(timeSource) 294334c72144SAxel Dörfler || (timeSource.kind & B_TIME_SOURCE) == 0) 2944fc8b28b6SJérôme Duval return B_MEDIA_BAD_NODE; 2945fc8b28b6SJérôme Duval 2946fc8b28b6SJérôme Duval timesource_get_start_latency_request request; 2947fc8b28b6SJérôme Duval timesource_get_start_latency_reply reply; 2948fc8b28b6SJérôme Duval status_t rv; 2949fc8b28b6SJérôme Duval 295034c72144SAxel Dörfler rv = QueryPort(timeSource.port, TIMESOURCE_GET_START_LATENCY, &request, 295134c72144SAxel Dörfler sizeof(request), &reply, sizeof(reply)); 2952fc8b28b6SJérôme Duval if (rv != B_OK) 2953fc8b28b6SJérôme Duval return rv; 2954fc8b28b6SJérôme Duval 295534c72144SAxel Dörfler *_latency = reply.start_latency; 2956fc8b28b6SJérôme Duval 2957332cc6bcSAxel Dörfler TRACE("BMediaRoster::GetStartLatencyFor timesource %" B_PRId32 " has " 2958332cc6bcSAxel Dörfler "maximum initial latency %" B_PRId64 "\n", timeSource.node, *_latency); 2959aac800c2Sbeveloper return B_OK; 296052a38012Sejakowatz } 296152a38012Sejakowatz 296252a38012Sejakowatz 296352a38012Sejakowatz status_t 296434c72144SAxel Dörfler BMediaRoster::GetFileFormatsFor(const media_node& fileInterface, 296534c72144SAxel Dörfler media_file_format* _formats, int32* _numFormats) 296652a38012Sejakowatz { 2967b6f0f884SDario Casalinuovo CALLED(); 2968b6f0f884SDario Casalinuovo 2969b6f0f884SDario Casalinuovo if (IS_INVALID_NODE(fileInterface) 2970b6f0f884SDario Casalinuovo || (fileInterface.kind & B_FILE_INTERFACE) == 0) 2971b6f0f884SDario Casalinuovo return B_MEDIA_BAD_NODE; 2972b6f0f884SDario Casalinuovo 2973b6f0f884SDario Casalinuovo if (_numFormats == NULL || *_numFormats < 1) 2974b6f0f884SDario Casalinuovo return B_BAD_VALUE; 2975b6f0f884SDario Casalinuovo 2976b6f0f884SDario Casalinuovo fileinterface_get_formats_request request; 2977b6f0f884SDario Casalinuovo fileinterface_get_formats_reply reply; 2978b6f0f884SDario Casalinuovo 2979b6f0f884SDario Casalinuovo media_file_format* formats; 2980b6f0f884SDario Casalinuovo size_t needSize = sizeof(media_file_format) * *_numFormats; 2981b6f0f884SDario Casalinuovo size_t size = (needSize + (B_PAGE_SIZE - 1)) & ~(B_PAGE_SIZE - 1); 2982b6f0f884SDario Casalinuovo 2983b6f0f884SDario Casalinuovo area_id area = create_area("formats area", (void**)&formats, 2984b6f0f884SDario Casalinuovo B_ANY_ADDRESS, size, B_NO_LOCK, 2985b6f0f884SDario Casalinuovo B_READ_AREA | B_WRITE_AREA); 2986b6f0f884SDario Casalinuovo 2987b6f0f884SDario Casalinuovo if (area < 0) 2988b6f0f884SDario Casalinuovo return B_NO_MEMORY; 2989b6f0f884SDario Casalinuovo 2990b6f0f884SDario Casalinuovo request.num_formats = *_numFormats; 2991b6f0f884SDario Casalinuovo request.data_area = area; 2992b6f0f884SDario Casalinuovo 2993b6f0f884SDario Casalinuovo status_t status = QueryPort(fileInterface.port, 2994b6f0f884SDario Casalinuovo FILEINTERFACE_GET_FORMATS, &request, 2995b6f0f884SDario Casalinuovo sizeof(request), &reply, sizeof(reply)); 2996b6f0f884SDario Casalinuovo 2997b6f0f884SDario Casalinuovo if (status == B_OK) { 2998b6f0f884SDario Casalinuovo memcpy(_formats, formats, sizeof(media_file_format)*reply.filled_slots); 2999b6f0f884SDario Casalinuovo *_numFormats = reply.filled_slots; 3000b6f0f884SDario Casalinuovo } 3001b6f0f884SDario Casalinuovo delete_area(area); 3002b6f0f884SDario Casalinuovo return status; 300352a38012Sejakowatz } 300452a38012Sejakowatz 300552a38012Sejakowatz 300652a38012Sejakowatz status_t 300734c72144SAxel Dörfler BMediaRoster::SetRefFor(const media_node& file_interface, const entry_ref& file, 300834c72144SAxel Dörfler bool createAndTruncate, bigtime_t* _length) 300952a38012Sejakowatz { 30106938364bSMaurice Kalinowski CALLED(); 30116938364bSMaurice Kalinowski 301242d17c1aSDario Casalinuovo if (IS_INVALID_NODE(file_interface) 301342d17c1aSDario Casalinuovo || (file_interface.kind & B_FILE_INTERFACE) == 0) 301442d17c1aSDario Casalinuovo return B_MEDIA_BAD_NODE; 301542d17c1aSDario Casalinuovo 30166938364bSMaurice Kalinowski fileinterface_set_ref_request request; 30176938364bSMaurice Kalinowski fileinterface_set_ref_reply reply; 30186938364bSMaurice Kalinowski status_t rv; 30196938364bSMaurice Kalinowski 30206938364bSMaurice Kalinowski request.device = file.device; 30216938364bSMaurice Kalinowski request.directory = file.directory; 30226938364bSMaurice Kalinowski strcpy(request.name, file.name); 302334c72144SAxel Dörfler request.create = createAndTruncate; 302434c72144SAxel Dörfler if (_length != NULL) 302534c72144SAxel Dörfler request.duration = *_length; 30266938364bSMaurice Kalinowski 302734c72144SAxel Dörfler rv = QueryPort(file_interface.port, FILEINTERFACE_SET_REF, &request, 302834c72144SAxel Dörfler sizeof(request), &reply, sizeof(reply)); 30296938364bSMaurice Kalinowski if (rv != B_OK) 30306938364bSMaurice Kalinowski return rv; 30316938364bSMaurice Kalinowski 303234c72144SAxel Dörfler if (!createAndTruncate && _length) 303334c72144SAxel Dörfler *_length = reply.duration; 30346938364bSMaurice Kalinowski 30356938364bSMaurice Kalinowski return B_OK; 303652a38012Sejakowatz } 303752a38012Sejakowatz 303852a38012Sejakowatz 303952a38012Sejakowatz status_t 304034c72144SAxel Dörfler BMediaRoster::GetRefFor(const media_node& node, entry_ref* _file, 304134c72144SAxel Dörfler BMimeType* mimeType) 304252a38012Sejakowatz { 30436938364bSMaurice Kalinowski CALLED(); 30446938364bSMaurice Kalinowski 304542d17c1aSDario Casalinuovo if (IS_INVALID_NODE(node) 304642d17c1aSDario Casalinuovo || (node.kind & B_FILE_INTERFACE) == 0) 304742d17c1aSDario Casalinuovo return B_MEDIA_BAD_NODE; 304842d17c1aSDario Casalinuovo 304934c72144SAxel Dörfler if (!_file) 30506938364bSMaurice Kalinowski return B_BAD_VALUE; 30516938364bSMaurice Kalinowski 30526938364bSMaurice Kalinowski fileinterface_get_ref_request request; 30536938364bSMaurice Kalinowski fileinterface_get_ref_reply reply; 30546938364bSMaurice Kalinowski status_t rv; 30556938364bSMaurice Kalinowski 305634c72144SAxel Dörfler rv = QueryPort(node.port, FILEINTERFACE_GET_REF, &request, sizeof(request), 305734c72144SAxel Dörfler &reply, sizeof(reply)); 30586938364bSMaurice Kalinowski if (rv != B_OK) 30596938364bSMaurice Kalinowski return rv; 30606938364bSMaurice Kalinowski 306134c72144SAxel Dörfler *_file = entry_ref(reply.device, reply.directory, reply.name); 30626938364bSMaurice Kalinowski 306334c72144SAxel Dörfler if (mimeType) 306434c72144SAxel Dörfler mimeType->SetTo(reply.mimetype); 30656938364bSMaurice Kalinowski 30666938364bSMaurice Kalinowski return B_OK; 306752a38012Sejakowatz } 306852a38012Sejakowatz 306952a38012Sejakowatz 307052a38012Sejakowatz status_t 307152a38012Sejakowatz BMediaRoster::SniffRefFor(const media_node& file_interface, 307234c72144SAxel Dörfler const entry_ref& file, BMimeType* mimeType, float* _capability) 307352a38012Sejakowatz { 30746938364bSMaurice Kalinowski CALLED(); 307542d17c1aSDario Casalinuovo 307642d17c1aSDario Casalinuovo if (IS_INVALID_NODE(file_interface) 307742d17c1aSDario Casalinuovo || (file_interface.kind & B_FILE_INTERFACE) == 0) 307842d17c1aSDario Casalinuovo return B_MEDIA_BAD_NODE; 307942d17c1aSDario Casalinuovo 308034c72144SAxel Dörfler if (mimeType == NULL || _capability == NULL) 30816938364bSMaurice Kalinowski return B_BAD_VALUE; 30826938364bSMaurice Kalinowski 30836938364bSMaurice Kalinowski fileinterface_sniff_ref_request request; 30846938364bSMaurice Kalinowski fileinterface_sniff_ref_reply reply; 30856938364bSMaurice Kalinowski status_t rv; 30866938364bSMaurice Kalinowski 30876938364bSMaurice Kalinowski request.device = file.device; 30886938364bSMaurice Kalinowski request.directory = file.directory; 30896938364bSMaurice Kalinowski strcpy(request.name, file.name); 30906938364bSMaurice Kalinowski 309134c72144SAxel Dörfler rv = QueryPort(file_interface.port, FILEINTERFACE_SNIFF_REF, &request, 309234c72144SAxel Dörfler sizeof(request), &reply, sizeof(reply)); 30936938364bSMaurice Kalinowski if (rv != B_OK) 30946938364bSMaurice Kalinowski return rv; 30956938364bSMaurice Kalinowski 309634c72144SAxel Dörfler mimeType->SetTo(reply.mimetype); 309734c72144SAxel Dörfler *_capability = reply.capability; 30986938364bSMaurice Kalinowski 30996938364bSMaurice Kalinowski return B_OK; 310052a38012Sejakowatz } 310152a38012Sejakowatz 310252a38012Sejakowatz 310334c72144SAxel Dörfler /*! This is the generic "here's a file, now can someone please play it" 310434c72144SAxel Dörfler interface. 310534c72144SAxel Dörfler */ 310652a38012Sejakowatz status_t 310734c72144SAxel Dörfler BMediaRoster::SniffRef(const entry_ref& file, uint64 requireNodeKinds, 310834c72144SAxel Dörfler dormant_node_info* _node, BMimeType* mimeType) 310952a38012Sejakowatz { 311005f452c3SDavid McPaul CALLED(); 311105f452c3SDavid McPaul 3112332cc6bcSAxel Dörfler TRACE("BMediaRoster::SniffRef looking for a node to handle %s: 0x%" B_PRIx64 3113332cc6bcSAxel Dörfler "\n", file.name, requireNodeKinds); 311405f452c3SDavid McPaul 311505f452c3SDavid McPaul if (_node == NULL) 311605f452c3SDavid McPaul return B_BAD_VALUE; 311705f452c3SDavid McPaul 311805f452c3SDavid McPaul BMimeType aMimeType; 311905f452c3SDavid McPaul 312005f452c3SDavid McPaul dormant_node_info nodes[30]; 312105f452c3SDavid McPaul int32 count = 30; 312205f452c3SDavid McPaul int32 highestCapability = -1; 312305f452c3SDavid McPaul float capability; 312405f452c3SDavid McPaul 312505f452c3SDavid McPaul media_node node; 312605f452c3SDavid McPaul 312705f452c3SDavid McPaul // Get all dormant nodes using GetDormantNodes 31286f7f87a2SDavid McPaul if (GetDormantNodes(nodes, &count, NULL, NULL, NULL, requireNodeKinds | B_FILE_INTERFACE, 0) == B_OK) { 312905f452c3SDavid McPaul // Call SniffRefFor on each node that matches requireNodeKinds 313005f452c3SDavid McPaul for (int32 i=0;i<count;i++) { 31316f7f87a2SDavid McPaul if (InstantiateDormantNode(nodes[i], &node) == B_OK) { 313205f452c3SDavid McPaul 31336f7f87a2SDavid McPaul if (SniffRefFor(node, file, &aMimeType, &capability) == B_OK) { 313405f452c3SDavid McPaul // find the first node that has 100% capability 313505f452c3SDavid McPaul TRACE("%s has a %f%% chance of playing file\n",nodes[i].name, capability * 100.0); 313605f452c3SDavid McPaul if (capability == 1.0) { 313705f452c3SDavid McPaul highestCapability = i; 313805f452c3SDavid McPaul break; 313905f452c3SDavid McPaul } 314005f452c3SDavid McPaul } 314105f452c3SDavid McPaul ReleaseNode(node); 314205f452c3SDavid McPaul } 314305f452c3SDavid McPaul } 314405f452c3SDavid McPaul 314505f452c3SDavid McPaul if (highestCapability != -1) { 314605f452c3SDavid McPaul *_node = nodes[highestCapability]; 314705f452c3SDavid McPaul 3148332cc6bcSAxel Dörfler TRACE("BMediaRoster::SniffRef: found a node %s addon-id %" B_PRId32 3149332cc6bcSAxel Dörfler ", flavor_id %" B_PRId32 "\n", 3150332cc6bcSAxel Dörfler nodes[highestCapability].name, nodes[highestCapability].addon, 3151332cc6bcSAxel Dörfler nodes[highestCapability].flavor_id); 315205f452c3SDavid McPaul 315305f452c3SDavid McPaul if (mimeType != NULL) { 315405f452c3SDavid McPaul //*mimeType = aMimeType; -- need a copy constructor 315505f452c3SDavid McPaul } 315605f452c3SDavid McPaul 315705f452c3SDavid McPaul return B_OK; 315805f452c3SDavid McPaul } 315905f452c3SDavid McPaul 316005f452c3SDavid McPaul } 316105f452c3SDavid McPaul 316252a38012Sejakowatz return B_ERROR; 316352a38012Sejakowatz } 316452a38012Sejakowatz 316552a38012Sejakowatz 316652a38012Sejakowatz status_t 316752a38012Sejakowatz BMediaRoster::GetDormantNodeForType(const BMimeType& type, 316834c72144SAxel Dörfler uint64 requireNodeKinds, dormant_node_info* _node) 316952a38012Sejakowatz { 317052a38012Sejakowatz UNIMPLEMENTED(); 317152a38012Sejakowatz return B_ERROR; 317252a38012Sejakowatz } 317352a38012Sejakowatz 317452a38012Sejakowatz 317552a38012Sejakowatz status_t 317634c72144SAxel Dörfler BMediaRoster::GetReadFileFormatsFor(const dormant_node_info& node, 317734c72144SAxel Dörfler media_file_format* _readFormats, int32 readCount, int32* _readCount) 317852a38012Sejakowatz { 317952a38012Sejakowatz UNIMPLEMENTED(); 318052a38012Sejakowatz return B_ERROR; 318152a38012Sejakowatz } 318252a38012Sejakowatz 318352a38012Sejakowatz 318452a38012Sejakowatz status_t 318534c72144SAxel Dörfler BMediaRoster::GetWriteFileFormatsFor(const dormant_node_info& node, 318634c72144SAxel Dörfler media_file_format* _write_formats, int32 writeCount, int32* _writeCount) 318752a38012Sejakowatz { 318852a38012Sejakowatz UNIMPLEMENTED(); 318952a38012Sejakowatz return B_ERROR; 319052a38012Sejakowatz } 319152a38012Sejakowatz 319252a38012Sejakowatz 319352a38012Sejakowatz status_t 319434c72144SAxel Dörfler BMediaRoster::GetFormatFor(const media_output& output, media_format* _format, 319552a38012Sejakowatz uint32 flags) 319652a38012Sejakowatz { 31979bedd42cSbeveloper CALLED(); 319834c72144SAxel Dörfler if (_format == NULL) 31999bedd42cSbeveloper return B_BAD_VALUE; 32009bedd42cSbeveloper if ((output.node.kind & B_BUFFER_PRODUCER) == 0) 32019bedd42cSbeveloper return B_MEDIA_BAD_NODE; 32029bedd42cSbeveloper if (IS_INVALID_SOURCE(output.source)) 32039bedd42cSbeveloper return B_MEDIA_BAD_SOURCE; 32049bedd42cSbeveloper 32059bedd42cSbeveloper producer_format_suggestion_requested_request request; 32069bedd42cSbeveloper producer_format_suggestion_requested_reply reply; 32079bedd42cSbeveloper status_t rv; 32089bedd42cSbeveloper 32099bedd42cSbeveloper request.type = B_MEDIA_UNKNOWN_TYPE; 321034c72144SAxel Dörfler request.quality = 0; // TODO: what should this be? 32119bedd42cSbeveloper 321234c72144SAxel Dörfler rv = QueryPort(output.source.port, PRODUCER_FORMAT_SUGGESTION_REQUESTED, 321334c72144SAxel Dörfler &request, sizeof(request), &reply, sizeof(reply)); 32149bedd42cSbeveloper if (rv != B_OK) 32159bedd42cSbeveloper return rv; 32169bedd42cSbeveloper 321734c72144SAxel Dörfler *_format = reply.format; 32189bedd42cSbeveloper return B_OK; 321952a38012Sejakowatz } 322052a38012Sejakowatz 322152a38012Sejakowatz 322252a38012Sejakowatz status_t 322334c72144SAxel Dörfler BMediaRoster::GetFormatFor(const media_input& input, media_format* _format, 322452a38012Sejakowatz uint32 flags) 322552a38012Sejakowatz { 32269bedd42cSbeveloper CALLED(); 322734c72144SAxel Dörfler if (_format == NULL) 32289bedd42cSbeveloper return B_BAD_VALUE; 32299bedd42cSbeveloper if ((input.node.kind & B_BUFFER_CONSUMER) == 0) 32309bedd42cSbeveloper return B_MEDIA_BAD_NODE; 32319bedd42cSbeveloper if (IS_INVALID_DESTINATION(input.destination)) 32329bedd42cSbeveloper return B_MEDIA_BAD_DESTINATION; 32339bedd42cSbeveloper 32349bedd42cSbeveloper consumer_accept_format_request request; 32359bedd42cSbeveloper consumer_accept_format_reply reply; 32369bedd42cSbeveloper status_t rv; 32379bedd42cSbeveloper 32389bedd42cSbeveloper request.dest = input.destination; 323912ed45b6SMurai Takashi request.format.Clear(); // wildcard 32409bedd42cSbeveloper 324134c72144SAxel Dörfler rv = QueryPort(input.destination.port, CONSUMER_ACCEPT_FORMAT, &request, 324234c72144SAxel Dörfler sizeof(request), &reply, sizeof(reply)); 32439bedd42cSbeveloper if (rv != B_OK) 32449bedd42cSbeveloper return rv; 32459bedd42cSbeveloper 324634c72144SAxel Dörfler *_format = reply.format; 32479bedd42cSbeveloper return B_OK; 324852a38012Sejakowatz } 324952a38012Sejakowatz 325052a38012Sejakowatz 325152a38012Sejakowatz status_t 325234c72144SAxel Dörfler BMediaRoster::GetFormatFor(const media_node& node, media_format* _format, 325352a38012Sejakowatz float quality) 325452a38012Sejakowatz { 325552a38012Sejakowatz UNIMPLEMENTED(); 325634c72144SAxel Dörfler if (_format == NULL) 32579bedd42cSbeveloper return B_BAD_VALUE; 32589bedd42cSbeveloper if (IS_INVALID_NODE(node)) 32599bedd42cSbeveloper return B_MEDIA_BAD_NODE; 32609bedd42cSbeveloper if ((node.kind & (B_BUFFER_CONSUMER | B_BUFFER_PRODUCER)) == 0) 32619bedd42cSbeveloper return B_MEDIA_BAD_NODE; 32629bedd42cSbeveloper 326352a38012Sejakowatz return B_ERROR; 326452a38012Sejakowatz } 326552a38012Sejakowatz 326652a38012Sejakowatz 326752a38012Sejakowatz ssize_t 326852a38012Sejakowatz BMediaRoster::GetNodeAttributesFor(const media_node& node, 326934c72144SAxel Dörfler media_node_attribute* _array, size_t maxCount) 327052a38012Sejakowatz { 3271c079d8d6SDario Casalinuovo CALLED(); 3272c079d8d6SDario Casalinuovo 3273c079d8d6SDario Casalinuovo if (IS_INVALID_NODE(node)) 3274c079d8d6SDario Casalinuovo return B_MEDIA_BAD_NODE; 3275c079d8d6SDario Casalinuovo 3276c079d8d6SDario Casalinuovo node_get_attributes_for_request request; 3277c079d8d6SDario Casalinuovo node_get_attributes_for_reply reply; 3278c079d8d6SDario Casalinuovo status_t status; 3279c079d8d6SDario Casalinuovo 3280c079d8d6SDario Casalinuovo media_node_attribute* addr = NULL; 3281c079d8d6SDario Casalinuovo size_t totalSize = maxCount*sizeof(media_node_attribute); 3282c079d8d6SDario Casalinuovo size_t size = (totalSize + (B_PAGE_SIZE - 1)) & ~(B_PAGE_SIZE - 1); 3283c079d8d6SDario Casalinuovo 3284c079d8d6SDario Casalinuovo area_id dataArea = create_area("attributes area", (void**)&addr, 3285c079d8d6SDario Casalinuovo B_ANY_ADDRESS, size, B_NO_LOCK, 3286c079d8d6SDario Casalinuovo B_READ_AREA | B_WRITE_AREA); 3287c079d8d6SDario Casalinuovo // No need to memset the padding 3288c079d8d6SDario Casalinuovo memset(addr, 0, totalSize); 3289c079d8d6SDario Casalinuovo 3290c079d8d6SDario Casalinuovo if (dataArea < 0) 3291c079d8d6SDario Casalinuovo return B_NO_MEMORY; 3292c079d8d6SDario Casalinuovo 3293c079d8d6SDario Casalinuovo request.count = maxCount; 3294c079d8d6SDario Casalinuovo request.area = dataArea; 3295c079d8d6SDario Casalinuovo 3296c079d8d6SDario Casalinuovo status = QueryPort(node.port, NODE_GET_ATTRIBUTES_FOR, &request, 3297c079d8d6SDario Casalinuovo sizeof(request), &reply, sizeof(reply)); 3298c079d8d6SDario Casalinuovo if (status != B_OK) 3299c079d8d6SDario Casalinuovo return status; 3300c079d8d6SDario Casalinuovo 3301c079d8d6SDario Casalinuovo memcpy(_array, addr, reply.filled_count 3302c079d8d6SDario Casalinuovo * sizeof(media_node_attribute)); 3303c079d8d6SDario Casalinuovo 3304c079d8d6SDario Casalinuovo delete_area(dataArea); 3305c079d8d6SDario Casalinuovo return reply.filled_count; 330652a38012Sejakowatz } 330752a38012Sejakowatz 330852a38012Sejakowatz 330952a38012Sejakowatz media_node_id 331034c72144SAxel Dörfler BMediaRoster::NodeIDFor(port_id port) 331152a38012Sejakowatz { 33129e9417d2Sbeveloper CALLED(); 33139e9417d2Sbeveloper 33149e9417d2Sbeveloper server_node_id_for_request request; 33159e9417d2Sbeveloper server_node_id_for_reply reply; 33169e9417d2Sbeveloper status_t rv; 33179e9417d2Sbeveloper 331834c72144SAxel Dörfler request.port = port; 33199e9417d2Sbeveloper 332034c72144SAxel Dörfler rv = QueryServer(SERVER_NODE_ID_FOR, &request, sizeof(request), &reply, 332134c72144SAxel Dörfler sizeof(reply)); 33229e9417d2Sbeveloper if (rv != B_OK) { 3323332cc6bcSAxel Dörfler ERROR("BMediaRoster::NodeIDFor: failed (error %#" B_PRIx32 ")\n", rv); 33249e9417d2Sbeveloper return -1; 33259e9417d2Sbeveloper } 33269e9417d2Sbeveloper 33279dec2310SAxel Dörfler return reply.node_id; 332852a38012Sejakowatz } 332952a38012Sejakowatz 333052a38012Sejakowatz 333152a38012Sejakowatz status_t 333234c72144SAxel Dörfler BMediaRoster::GetInstancesFor(media_addon_id addon, int32 flavor, 333334c72144SAxel Dörfler media_node_id* _id, int32* _count) 333452a38012Sejakowatz { 333585dfab2bSbeveloper CALLED(); 333634c72144SAxel Dörfler if (_id == NULL) 333785dfab2bSbeveloper return B_BAD_VALUE; 333834c72144SAxel Dörfler if (_count && *_count <= 0) 333985dfab2bSbeveloper return B_BAD_VALUE; 334085dfab2bSbeveloper 334185dfab2bSbeveloper server_get_instances_for_request request; 334285dfab2bSbeveloper server_get_instances_for_reply reply; 334385dfab2bSbeveloper status_t rv; 334485dfab2bSbeveloper 33459c3b4706SAxel Dörfler request.max_count = (_count ? *_count : 1); 33469c3b4706SAxel Dörfler request.add_on_id = addon; 33479c3b4706SAxel Dörfler request.flavor_id = flavor; 334885dfab2bSbeveloper 334934c72144SAxel Dörfler rv = QueryServer(SERVER_GET_INSTANCES_FOR, &request, sizeof(request), 335034c72144SAxel Dörfler &reply, sizeof(reply)); 335185dfab2bSbeveloper if (rv != B_OK) { 33525ac4fbd7Sbeveloper ERROR("BMediaRoster::GetLiveNodes failed\n"); 335385dfab2bSbeveloper return rv; 335452a38012Sejakowatz } 335552a38012Sejakowatz 335634c72144SAxel Dörfler if (_count) 335734c72144SAxel Dörfler *_count = reply.count; 335885dfab2bSbeveloper if (reply.count > 0) 335934c72144SAxel Dörfler memcpy(_id, reply.node_id, sizeof(media_node_id) * reply.count); 336085dfab2bSbeveloper 336185dfab2bSbeveloper return B_OK; 336285dfab2bSbeveloper } 336352a38012Sejakowatz 336452a38012Sejakowatz 336567483edaSDario Casalinuovo bool 336667483edaSDario Casalinuovo BMediaRoster::IsRunning() 336767483edaSDario Casalinuovo { 3368d009f286SDario Casalinuovo return be_roster->IsRunning(B_MEDIA_SERVER_SIGNATURE) 3369d009f286SDario Casalinuovo && be_roster->IsRunning(B_MEDIA_ADDON_SERVER_SIGNATURE); 337067483edaSDario Casalinuovo } 337167483edaSDario Casalinuovo 337267483edaSDario Casalinuovo 337352a38012Sejakowatz ssize_t 337434c72144SAxel Dörfler BMediaRoster::AudioBufferSizeFor(int32 channelCount, uint32 sampleFormat, 337534c72144SAxel Dörfler float frameRate, bus_type busKind) 337652a38012Sejakowatz { 337734c72144SAxel Dörfler bigtime_t bufferDuration; 337834c72144SAxel Dörfler ssize_t bufferSize; 3379df6c2e83Sbeveloper 33804c125ccaSPawel Dziepak if (busKind == B_ISA_BUS || busKind == B_PCMCIA_BUS) 338134c72144SAxel Dörfler bufferDuration = 25000; 33824c125ccaSPawel Dziepak else 33834c125ccaSPawel Dziepak bufferDuration = 10000; 3384df6c2e83Sbeveloper 338534c72144SAxel Dörfler bufferSize = (sampleFormat & 0xf) * channelCount 338634c72144SAxel Dörfler * (ssize_t)((frameRate * bufferDuration) / 1000000.0); 3387df6c2e83Sbeveloper 3388332cc6bcSAxel Dörfler printf("Suggested buffer duration %" B_PRId64 ", size %" B_PRIdSSIZE "\n", 3389332cc6bcSAxel Dörfler bufferDuration, bufferSize); 3390df6c2e83Sbeveloper 339134c72144SAxel Dörfler return bufferSize; 339252a38012Sejakowatz } 339352a38012Sejakowatz 339452a38012Sejakowatz 339534c72144SAxel Dörfler /*! Use MediaFlags to inquire about specific features of the Media Kit. 339634c72144SAxel Dörfler Returns < 0 for "not present", positive size for output data size. 339734c72144SAxel Dörfler 0 means that the capability is present, but no data about it. 339834c72144SAxel Dörfler */ 339952a38012Sejakowatz /*static*/ ssize_t 340034c72144SAxel Dörfler BMediaRoster::MediaFlags(media_flags cap, void* buffer, size_t maxSize) 340152a38012Sejakowatz { 340252a38012Sejakowatz UNIMPLEMENTED(); 340352a38012Sejakowatz return 0; 340452a38012Sejakowatz } 340552a38012Sejakowatz 340652a38012Sejakowatz 340734c72144SAxel Dörfler // #pragma mark - BLooper overrides 340834c72144SAxel Dörfler 340934c72144SAxel Dörfler 341034c72144SAxel Dörfler void 341152a38012Sejakowatz BMediaRoster::MessageReceived(BMessage* message) 341252a38012Sejakowatz { 3413cf4e2277Sbeveloper switch (message->what) { 341432afe10aSDario Casalinuovo case MEDIA_ROSTER_REQUEST_NOTIFICATIONS: 341532afe10aSDario Casalinuovo { 341632afe10aSDario Casalinuovo RosterNotification notification; 341732afe10aSDario Casalinuovo if (message->FindInt32(NOTIFICATION_PARAM_WHAT, ¬ification.what) 341832afe10aSDario Casalinuovo != B_OK) { 341932afe10aSDario Casalinuovo TRACE("BMediaRoster MEDIA_ROSTER_REQUEST_NOTIFICATIONS can't" 342032afe10aSDario Casalinuovo "find what parameter"); 342132afe10aSDario Casalinuovo return; 342232afe10aSDario Casalinuovo } 342332afe10aSDario Casalinuovo if (message->FindMessenger(NOTIFICATION_PARAM_MESSENGER, 342432afe10aSDario Casalinuovo ¬ification.messenger) != B_OK) { 342532afe10aSDario Casalinuovo TRACE("BMediaRoster MEDIA_ROSTER_REQUEST_NOTIFICATIONS can't" 342632afe10aSDario Casalinuovo "find messenger"); 342732afe10aSDario Casalinuovo return; 342832afe10aSDario Casalinuovo } 342932afe10aSDario Casalinuovo sNotificationList.Insert(notification); 343032afe10aSDario Casalinuovo return; 343132afe10aSDario Casalinuovo } 343232afe10aSDario Casalinuovo 343332afe10aSDario Casalinuovo case MEDIA_ROSTER_CANCEL_NOTIFICATIONS: 343432afe10aSDario Casalinuovo { 343532afe10aSDario Casalinuovo RosterNotification notification; 343632afe10aSDario Casalinuovo if (message->FindInt32(NOTIFICATION_PARAM_WHAT, ¬ification.what) 343732afe10aSDario Casalinuovo != B_OK) { 343832afe10aSDario Casalinuovo TRACE("BMediaRoster MEDIA_ROSTER_CANCEL_NOTIFICATIONS can't" 343932afe10aSDario Casalinuovo "find what parameter"); 344032afe10aSDario Casalinuovo return; 344132afe10aSDario Casalinuovo } 344232afe10aSDario Casalinuovo if (message->FindMessenger(NOTIFICATION_PARAM_MESSENGER, 344332afe10aSDario Casalinuovo ¬ification.messenger) != B_OK) { 344432afe10aSDario Casalinuovo TRACE("BMediaRoster MEDIA_ROSTER_CANCEL_NOTIFICATIONS can't" 344532afe10aSDario Casalinuovo "find messenger"); 344632afe10aSDario Casalinuovo return; 344732afe10aSDario Casalinuovo } 344832afe10aSDario Casalinuovo for (int32 i = 0; i < sNotificationList.CountItems(); i++) { 344932afe10aSDario Casalinuovo RosterNotification* current; 345032afe10aSDario Casalinuovo if (sNotificationList.Get(i, ¤t) != true) 345132afe10aSDario Casalinuovo return; 345232afe10aSDario Casalinuovo if (current->what == notification.what 345332afe10aSDario Casalinuovo && current->messenger == notification.messenger) { 345432afe10aSDario Casalinuovo sNotificationList.Remove(i); 345532afe10aSDario Casalinuovo return; 345632afe10aSDario Casalinuovo } 345732afe10aSDario Casalinuovo } 345832afe10aSDario Casalinuovo return; 345932afe10aSDario Casalinuovo } 346032afe10aSDario Casalinuovo 346132afe10aSDario Casalinuovo case B_SOME_APP_LAUNCHED: 346232afe10aSDario Casalinuovo { 346332afe10aSDario Casalinuovo BString mimeSig; 346432afe10aSDario Casalinuovo if (message->FindString("be:signature", &mimeSig) != B_OK) 346532afe10aSDario Casalinuovo return; 346632afe10aSDario Casalinuovo if (mimeSig != B_MEDIA_ADDON_SERVER_SIGNATURE 346732afe10aSDario Casalinuovo && mimeSig != B_MEDIA_SERVER_SIGNATURE) 346832afe10aSDario Casalinuovo return; 346932afe10aSDario Casalinuovo 347032afe10aSDario Casalinuovo TRACE("BMediaRoster::MessageReceived media services are going up."); 347132afe10aSDario Casalinuovo 347232afe10aSDario Casalinuovo if (BMediaRoster::IsRunning()) { 347311c7bd86SDario Casalinuovo // Wait for media services to wake up and restore our friendship 347432afe10aSDario Casalinuovo if (MediaRosterEx(this)->BuildConnections() != B_OK) { 347532afe10aSDario Casalinuovo TRACE("BMediaRoster::MessageReceived can't reconnect" 347632afe10aSDario Casalinuovo "to media_server."); 347732afe10aSDario Casalinuovo } 347832afe10aSDario Casalinuovo } 347932afe10aSDario Casalinuovo return; 348032afe10aSDario Casalinuovo } 348132afe10aSDario Casalinuovo 348232afe10aSDario Casalinuovo case B_SOME_APP_QUIT: 348332afe10aSDario Casalinuovo { 348432afe10aSDario Casalinuovo BString mimeSig; 348532afe10aSDario Casalinuovo if (message->FindString("be:signature", &mimeSig) != B_OK) 348632afe10aSDario Casalinuovo return; 348732afe10aSDario Casalinuovo if (mimeSig != B_MEDIA_ADDON_SERVER_SIGNATURE 348832afe10aSDario Casalinuovo && mimeSig != B_MEDIA_SERVER_SIGNATURE) 348932afe10aSDario Casalinuovo return; 349032afe10aSDario Casalinuovo 349132afe10aSDario Casalinuovo TRACE("BMediaRoster::MessageReceived media services are down."); 349232afe10aSDario Casalinuovo 349332afe10aSDario Casalinuovo // Send the notification to our subscribers 349432afe10aSDario Casalinuovo if (!BMediaRoster::IsRunning() && sServerIsUp == true) { 349532afe10aSDario Casalinuovo sServerIsUp = false; 349632afe10aSDario Casalinuovo for (int32 i = 0; i < sNotificationList.CountItems(); i++) { 349732afe10aSDario Casalinuovo RosterNotification* current; 349832afe10aSDario Casalinuovo if (sNotificationList.Get(i, ¤t) != true) 349932afe10aSDario Casalinuovo return; 350032afe10aSDario Casalinuovo if (current->what == B_MEDIA_SERVER_QUIT) { 350132afe10aSDario Casalinuovo if (current->messenger.SendMessage( 350232afe10aSDario Casalinuovo B_MEDIA_SERVER_QUIT) != B_OK) { 350332afe10aSDario Casalinuovo if(!current->messenger.IsValid()) 350432afe10aSDario Casalinuovo sNotificationList.Remove(i); 350532afe10aSDario Casalinuovo } 350632afe10aSDario Casalinuovo } 350732afe10aSDario Casalinuovo } 350832afe10aSDario Casalinuovo } 350932afe10aSDario Casalinuovo return; 351032afe10aSDario Casalinuovo } 351132afe10aSDario Casalinuovo 351211c7bd86SDario Casalinuovo case MEDIA_SERVER_ALIVE: 351311c7bd86SDario Casalinuovo { 351411c7bd86SDario Casalinuovo if (!BMediaRoster::IsRunning()) 351511c7bd86SDario Casalinuovo return; 351611c7bd86SDario Casalinuovo 351711c7bd86SDario Casalinuovo sServerIsUp = true; 351811c7bd86SDario Casalinuovo 351911c7bd86SDario Casalinuovo TRACE("BMediaRoster::MessageReceived media services are" 352011c7bd86SDario Casalinuovo " finally up."); 352111c7bd86SDario Casalinuovo 352276889670SDario Casalinuovo if (MediaRosterEx(this)->fLaunchNotification) { 352376889670SDario Casalinuovo progress_startup(100, NULL, NULL); 352476889670SDario Casalinuovo if (MediaRosterEx(this)->fAutoExit) 352576889670SDario Casalinuovo MediaRosterEx(this)->fLaunchNotification = false; 352676889670SDario Casalinuovo } 352776889670SDario Casalinuovo 352811c7bd86SDario Casalinuovo // Send the notification to our subscribers 352911c7bd86SDario Casalinuovo for (int32 i = 0; i < sNotificationList.CountItems(); i++) { 353011c7bd86SDario Casalinuovo RosterNotification* current; 353111c7bd86SDario Casalinuovo if (sNotificationList.Get(i, ¤t) != true) 353211c7bd86SDario Casalinuovo return; 353311c7bd86SDario Casalinuovo if (current->what == B_MEDIA_SERVER_STARTED) { 353411c7bd86SDario Casalinuovo if (current->messenger.SendMessage( 353511c7bd86SDario Casalinuovo B_MEDIA_SERVER_STARTED) != B_OK) { 353611c7bd86SDario Casalinuovo if(!current->messenger.IsValid()) 353711c7bd86SDario Casalinuovo sNotificationList.Remove(i); 353811c7bd86SDario Casalinuovo } 353911c7bd86SDario Casalinuovo } 354011c7bd86SDario Casalinuovo } 354176889670SDario Casalinuovo return; 354211c7bd86SDario Casalinuovo } 354311c7bd86SDario Casalinuovo 3544cf4e2277Sbeveloper case NODE_FINAL_RELEASE: 3545cf4e2277Sbeveloper { 35466423f87fSDario Casalinuovo // This function is called by a BMediaNode to delete 3547cf4e2277Sbeveloper // itself, as this needs to be done from another thread 3548cf4e2277Sbeveloper // context, it is done here. 3549cf4e2277Sbeveloper 35506423f87fSDario Casalinuovo BMediaNode* node = NULL; 35516423f87fSDario Casalinuovo status_t err = message->FindPointer("node", 35526423f87fSDario Casalinuovo reinterpret_cast<void **>(&node)); 35536423f87fSDario Casalinuovo if (err == B_OK && node != NULL) 35546423f87fSDario Casalinuovo node->Release(); 35556423f87fSDario Casalinuovo else { 35566423f87fSDario Casalinuovo TRACE("BMediaRoster::MessageReceived: CRITICAL! received" 35576423f87fSDario Casalinuovo "a release request but the node can't be found."); 35586423f87fSDario Casalinuovo } 3559cf4e2277Sbeveloper return; 3560cf4e2277Sbeveloper } 356148b2cb37SDario Casalinuovo 356248b2cb37SDario Casalinuovo default: 356348b2cb37SDario Casalinuovo BLooper::MessageReceived(message); 356448b2cb37SDario Casalinuovo break; 356548b2cb37SDario Casalinuovo } 356652a38012Sejakowatz } 356752a38012Sejakowatz 356834c72144SAxel Dörfler 356934c72144SAxel Dörfler bool 357052a38012Sejakowatz BMediaRoster::QuitRequested() 357152a38012Sejakowatz { 357232afe10aSDario Casalinuovo CALLED(); 357352a38012Sejakowatz return true; 357452a38012Sejakowatz } 357552a38012Sejakowatz 357634c72144SAxel Dörfler 357734c72144SAxel Dörfler BHandler* 357834c72144SAxel Dörfler BMediaRoster::ResolveSpecifier(BMessage* msg, int32 index, BMessage* specifier, 357934c72144SAxel Dörfler int32 form, const char* property) 358052a38012Sejakowatz { 3581286a3c91SJérôme Duval return BLooper::ResolveSpecifier(msg, index, specifier, form, property); 358252a38012Sejakowatz } 358352a38012Sejakowatz 358452a38012Sejakowatz 358534c72144SAxel Dörfler status_t 358652a38012Sejakowatz BMediaRoster::GetSupportedSuites(BMessage* data) 358752a38012Sejakowatz { 3588286a3c91SJérôme Duval return BLooper::GetSupportedSuites(data); 358952a38012Sejakowatz } 359052a38012Sejakowatz 359152a38012Sejakowatz 359252a38012Sejakowatz BMediaRoster::~BMediaRoster() 359352a38012Sejakowatz { 359452a38012Sejakowatz CALLED(); 35956396865dSbeveloper 35968b940bb4SStephan Aßmus // Unset the global instance pointer, the destructor is also called 35978b940bb4SStephan Aßmus // if a client app calls Lock(); and Quit(); directly. 35989def3bf7SStephan Aßmus sDefaultInstance = NULL; 359952a38012Sejakowatz } 360052a38012Sejakowatz 360134c72144SAxel Dörfler // #pragma mark - private BMediaRoster 360234c72144SAxel Dörfler 3603f0a1eb2dSAxel Dörfler // FBC reserved virtuals 360452a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_0(void*) { return B_ERROR; } 360552a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_1(void*) { return B_ERROR; } 360652a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_2(void*) { return B_ERROR; } 360752a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_3(void*) { return B_ERROR; } 360852a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_4(void*) { return B_ERROR; } 360952a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_5(void*) { return B_ERROR; } 361052a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_6(void*) { return B_ERROR; } 361152a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_7(void*) { return B_ERROR; } 361252a38012Sejakowatz 361352a38012Sejakowatz 361434c72144SAxel Dörfler BMediaRoster::BMediaRoster() 36152f9ed888SAxel Dörfler : 36162f9ed888SAxel Dörfler BLooper("_BMediaRoster_", B_URGENT_DISPLAY_PRIORITY, 361734c72144SAxel Dörfler B_LOOPER_PORT_DEFAULT_CAPACITY) 361852a38012Sejakowatz { 361952a38012Sejakowatz CALLED(); 36206396865dSbeveloper 36216396865dSbeveloper // start the looper 36226396865dSbeveloper Run(); 362352a38012Sejakowatz } 362452a38012Sejakowatz 36259def3bf7SStephan Aßmus // #pragma mark - static variables 362652a38012Sejakowatz 36279def3bf7SStephan Aßmus BMediaRoster* BMediaRoster::sDefaultInstance = NULL; 3628