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 73472d26a3SRyan Leavengood #include "PortPool.h" 74835140c8Sbeveloper #include "TimeSourceObjectManager.h" 7552a38012Sejakowatz 762f9ed888SAxel Dörfler 77f0a1eb2dSAxel Dörfler namespace BPrivate { 78f0a1eb2dSAxel Dörfler namespace media { 7952a38012Sejakowatz 80f0a1eb2dSAxel Dörfler 8132afe10aSDario Casalinuovo struct RosterNotification { 8232afe10aSDario Casalinuovo BMessenger messenger; 8332afe10aSDario Casalinuovo int32 what; 8432afe10aSDario Casalinuovo }; 8532afe10aSDario Casalinuovo 8605962bb1SDario Casalinuovo 8776889670SDario Casalinuovo struct SyncedMessage { 8876889670SDario Casalinuovo BMessage* message; 8976889670SDario Casalinuovo }; 9076889670SDario Casalinuovo 9176889670SDario Casalinuovo 9267060664SDario Casalinuovo struct LocalNode { 9367060664SDario Casalinuovo LocalNode(BMediaNode* local_node) 9467060664SDario Casalinuovo : 9567060664SDario Casalinuovo node(local_node) {} 9667060664SDario Casalinuovo 9767060664SDario Casalinuovo LocalNode() 9867060664SDario Casalinuovo : 9967060664SDario Casalinuovo node(NULL) {} 10067060664SDario Casalinuovo 10167060664SDario Casalinuovo bool operator==(const LocalNode& a) 10267060664SDario Casalinuovo { 10367060664SDario Casalinuovo if (a.node == this->node) 10467060664SDario Casalinuovo return true; 10567060664SDario Casalinuovo return false; 10667060664SDario Casalinuovo } 10767060664SDario Casalinuovo 10867060664SDario Casalinuovo BMediaNode* node; 10967060664SDario Casalinuovo }; 11067060664SDario Casalinuovo 11167060664SDario Casalinuovo 11232afe10aSDario Casalinuovo static bool sServerIsUp = false; 11332afe10aSDario Casalinuovo static List<RosterNotification> sNotificationList; 114d15321ffSDario Casalinuovo static BLocker sInitLocker("BMediaRoster::Roster locker"); 11567060664SDario Casalinuovo static List<LocalNode> sRegisteredNodes; 11632afe10aSDario Casalinuovo 1177d337b23SDario Casalinuovo 118*083314c2SAdrien Destugues // This class takes care of all static initialization and destruction of 119*083314c2SAdrien Destugues // libmedia objects. It guarantees that things are created and destroyed in 120*083314c2SAdrien Destugues // the correct order, as well as performing some "garbage collecting" by being 121*083314c2SAdrien Destugues // destructed automatically on application exit. 1227d337b23SDario Casalinuovo class MediaRosterUndertaker { 1237d337b23SDario Casalinuovo public: 124*083314c2SAdrien Destugues MediaRosterUndertaker() 125*083314c2SAdrien Destugues { 126*083314c2SAdrien Destugues gPortPool = new PortPool(); 127*083314c2SAdrien Destugues } 128*083314c2SAdrien Destugues 1297d337b23SDario Casalinuovo ~MediaRosterUndertaker() 1307d337b23SDario Casalinuovo { 1317d337b23SDario Casalinuovo BAutolock _(sInitLocker); 132ad7255c8SDario Casalinuovo if (BMediaRoster::CurrentRoster() != NULL) { 13305962bb1SDario Casalinuovo 13467060664SDario Casalinuovo // Detect any forgotten node 13567060664SDario Casalinuovo if (sRegisteredNodes.CountItems() > 0) { 13667060664SDario Casalinuovo for (int32 i = 0; i < sRegisteredNodes.CountItems(); i++) { 13767060664SDario Casalinuovo LocalNode* node = NULL; 13867060664SDario Casalinuovo sRegisteredNodes.Get(i, &node); 13967060664SDario Casalinuovo if (node != NULL) { 14067060664SDario Casalinuovo ERROR("BMediaRoster: Node with ID %" B_PRId32 14167060664SDario Casalinuovo " was not released correctly\n", node->node->ID()); 14267060664SDario Casalinuovo } 14367060664SDario Casalinuovo } 14467060664SDario Casalinuovo } 14567060664SDario Casalinuovo 14605962bb1SDario Casalinuovo if (be_app != NULL) 14705962bb1SDario Casalinuovo be_app->UnregisterLooper(BMediaRoster::CurrentRoster()); 14805962bb1SDario Casalinuovo 149ad7255c8SDario Casalinuovo status_t err = B_ERROR; 150ad7255c8SDario Casalinuovo thread_id roster = BMediaRoster::CurrentRoster()->Thread(); 151ad7255c8SDario Casalinuovo 152ad7255c8SDario Casalinuovo BMediaRoster::CurrentRoster()->PostMessage(B_QUIT_REQUESTED); 153ad7255c8SDario Casalinuovo 154ad7255c8SDario Casalinuovo wait_for_thread(roster, &err); 155ad7255c8SDario Casalinuovo if (err != B_OK) 156ad7255c8SDario Casalinuovo ERROR("BMediaRoster: wait_for_thread returned error"); 157472d26a3SRyan Leavengood 158472d26a3SRyan Leavengood // Only now delete the port pool 159472d26a3SRyan Leavengood delete gPortPool; 1607d337b23SDario Casalinuovo } 1617d337b23SDario Casalinuovo } 1627d337b23SDario Casalinuovo }; 1637d337b23SDario Casalinuovo 1647d337b23SDario Casalinuovo 1657d337b23SDario Casalinuovo static MediaRosterUndertaker sMediaRosterUndertaker; 1667d337b23SDario Casalinuovo 1679dec2310SAxel Dörfler } // namespace media 1689dec2310SAxel Dörfler } // namespace BPrivate 1699dec2310SAxel Dörfler 1708b04ffc1Sbeveloper using namespace BPrivate::media; 17152a38012Sejakowatz 1729dec2310SAxel Dörfler 17334c72144SAxel Dörfler BMediaRosterEx::BMediaRosterEx(status_t* _error) 1749dec2310SAxel Dörfler : 17576889670SDario Casalinuovo BMediaRoster(), 17676889670SDario Casalinuovo fLaunchNotification(false), 17776889670SDario Casalinuovo fAutoExit(false) 178dcfb6bfcSJérôme Duval { 1797d337b23SDario Casalinuovo gDormantNodeManager = new DormantNodeManager(); 1807d337b23SDario Casalinuovo gTimeSourceObjectManager = new TimeSourceObjectManager(); 181f0a1eb2dSAxel Dörfler 18232afe10aSDario Casalinuovo *_error = BuildConnections(); 18332afe10aSDario Casalinuovo 18432afe10aSDario Casalinuovo InitRosterDataExchange(BMessenger(this, this)); 18532afe10aSDario Casalinuovo 18632afe10aSDario Casalinuovo if (be_roster->StartWatching(BMessenger(this, this), 187d009f286SDario Casalinuovo B_REQUEST_LAUNCHED | B_REQUEST_QUIT) != B_OK) { 18832afe10aSDario Casalinuovo *_error = B_ERROR; 189d009f286SDario Casalinuovo } 19032afe10aSDario Casalinuovo sServerIsUp = BMediaRoster::IsRunning(); 19132afe10aSDario Casalinuovo } 19232afe10aSDario Casalinuovo 19332afe10aSDario Casalinuovo 1947d337b23SDario Casalinuovo void 1957d337b23SDario Casalinuovo BMediaRosterEx::Quit() 1967d337b23SDario Casalinuovo { 1977d337b23SDario Casalinuovo if (be_roster->StopWatching(BMessenger(this, this)) != B_OK) 1987d337b23SDario Casalinuovo TRACE("Can't unregister roster notifications"); 1997d337b23SDario Casalinuovo 2007d337b23SDario Casalinuovo if (sNotificationList.CountItems() != 0) 2017d337b23SDario Casalinuovo sNotificationList.MakeEmpty(); 2027d337b23SDario Casalinuovo 2037d337b23SDario Casalinuovo BMediaRoster::Quit(); 2047d337b23SDario Casalinuovo } 2057d337b23SDario Casalinuovo 2067d337b23SDario Casalinuovo 20732afe10aSDario Casalinuovo status_t 20832afe10aSDario Casalinuovo BMediaRosterEx::BuildConnections() 20932afe10aSDario Casalinuovo { 21032afe10aSDario Casalinuovo InitServerDataExchange(); 211dcfb6bfcSJérôme Duval // register this application with the media server 212dcfb6bfcSJérôme Duval server_register_app_request request; 213dcfb6bfcSJérôme Duval server_register_app_reply reply; 2149dec2310SAxel Dörfler request.team = BPrivate::current_team(); 215dcfb6bfcSJérôme Duval request.messenger = BMessenger(NULL, this); 2169dec2310SAxel Dörfler status_t status = QueryServer(SERVER_REGISTER_APP, &request, 2179dec2310SAxel Dörfler sizeof(request), &reply, sizeof(reply)); 2189dec2310SAxel Dörfler if (status != B_OK) 21932afe10aSDario Casalinuovo return B_MEDIA_SYSTEM_FAILURE; 22032afe10aSDario Casalinuovo 22132afe10aSDario Casalinuovo return B_OK; 222dcfb6bfcSJérôme Duval } 223dcfb6bfcSJérôme Duval 22434c72144SAxel Dörfler 225e57acc3aSDario Casalinuovo BMediaRosterEx::~BMediaRosterEx() 226e57acc3aSDario Casalinuovo { 227e57acc3aSDario Casalinuovo CALLED(); 228e57acc3aSDario Casalinuovo 229e57acc3aSDario Casalinuovo delete gTimeSourceObjectManager; 230e57acc3aSDario Casalinuovo delete gDormantNodeManager; 231e57acc3aSDario Casalinuovo 232e57acc3aSDario Casalinuovo // unregister this application with the media server 233e57acc3aSDario Casalinuovo server_unregister_app_request request; 234e57acc3aSDario Casalinuovo server_unregister_app_reply reply; 235e57acc3aSDario Casalinuovo request.team = BPrivate::current_team(); 236e57acc3aSDario Casalinuovo QueryServer(SERVER_UNREGISTER_APP, &request, sizeof(request), &reply, 237e57acc3aSDario Casalinuovo sizeof(reply)); 238e57acc3aSDario Casalinuovo 239e57acc3aSDario Casalinuovo BPrivate::SharedBufferList::Invalidate(); 240e57acc3aSDario Casalinuovo } 241e57acc3aSDario Casalinuovo 242e57acc3aSDario Casalinuovo 24367060664SDario Casalinuovo void 24467060664SDario Casalinuovo BMediaRosterEx::RegisterLocalNode(BMediaNode* node) 24567060664SDario Casalinuovo { 24667060664SDario Casalinuovo sRegisteredNodes.Insert(LocalNode(node)); 24767060664SDario Casalinuovo } 24867060664SDario Casalinuovo 24967060664SDario Casalinuovo 25067060664SDario Casalinuovo void 25167060664SDario Casalinuovo BMediaRosterEx::UnregisterLocalNode(BMediaNode* node) 25267060664SDario Casalinuovo { 25367060664SDario Casalinuovo int32 index = sRegisteredNodes.Find(LocalNode(node)); 25467060664SDario Casalinuovo if (index != -1) 25567060664SDario Casalinuovo sRegisteredNodes.Remove(index); 25667060664SDario Casalinuovo } 25767060664SDario Casalinuovo 25867060664SDario Casalinuovo 25976889670SDario Casalinuovo void 26076889670SDario Casalinuovo BMediaRosterEx::EnableLaunchNotification(bool enable, bool autoExit) 26176889670SDario Casalinuovo { 26276889670SDario Casalinuovo // NOTE: in theory, we should personalize it depending on each 26376889670SDario Casalinuovo // request, but we are using it just in launch/shutdown_media_server, 26476889670SDario Casalinuovo // so we are enough safe to don't care about that. 26576889670SDario Casalinuovo fLaunchNotification = enable; 26676889670SDario Casalinuovo fAutoExit = autoExit; 26776889670SDario Casalinuovo } 26876889670SDario Casalinuovo 26976889670SDario Casalinuovo 2703620737cSbeveloper status_t 27154187cc6Sbeveloper BMediaRosterEx::SaveNodeConfiguration(BMediaNode* node) 27254187cc6Sbeveloper { 2739dec2310SAxel Dörfler int32 flavorID; 2749dec2310SAxel Dörfler BMediaAddOn* addon = node->AddOn(&flavorID); 2759dec2310SAxel Dörfler if (addon == NULL) { 2768056f0dbSStephan Aßmus // NOTE: This node could have been created by an application, 2778056f0dbSStephan Aßmus // it does not mean there is an error. 27834c72144SAxel Dörfler // TODO: this check incorrectly triggers on BeOS R5 BT848 node 279332cc6bcSAxel Dörfler TRACE("BMediaRosterEx::SaveNodeConfiguration node %" B_PRId32 " not " 280332cc6bcSAxel Dörfler "instantiated from BMediaAddOn!\n", node->ID()); 28154187cc6Sbeveloper return B_ERROR; 28254187cc6Sbeveloper } 2839dec2310SAxel Dörfler 2849dec2310SAxel Dörfler media_addon_id addonID = addon->AddonID(); 28554187cc6Sbeveloper 28634c72144SAxel Dörfler // TODO: fix this 2878056f0dbSStephan Aßmus printf("### BMediaRosterEx::SaveNodeConfiguration should save 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::LoadNodeConfiguration(media_addon_id addonID, int32 flavorID, 2969dec2310SAxel Dörfler BMessage *_msg) 29754187cc6Sbeveloper { 29834c72144SAxel Dörfler // TODO: fix this 2999dec2310SAxel Dörfler _msg->MakeEmpty(); // to be fully R5 compliant 3008b940bb4SStephan Aßmus printf("### BMediaRosterEx::LoadNodeConfiguration should load addon-id " 301332cc6bcSAxel Dörfler "%" B_PRId32 ", flavor-id %" B_PRId32 " config NOW!\n", addonID, 302332cc6bcSAxel Dörfler flavorID); 30354187cc6Sbeveloper return B_OK; 30454187cc6Sbeveloper } 30554187cc6Sbeveloper 30634c72144SAxel Dörfler 30754187cc6Sbeveloper status_t 3089dec2310SAxel Dörfler BMediaRosterEx::IncrementAddonFlavorInstancesCount(media_addon_id addonID, 3099dec2310SAxel Dörfler int32 flavorID) 31054187cc6Sbeveloper { 3119c3b4706SAxel Dörfler server_change_flavor_instances_count_request request; 3129c3b4706SAxel Dörfler server_change_flavor_instances_count_reply reply; 31373794717Sbeveloper 3149c3b4706SAxel Dörfler request.add_on_id = addonID; 3159dec2310SAxel Dörfler request.flavor_id = flavorID; 31673794717Sbeveloper request.delta = 1; 3179dec2310SAxel Dörfler request.team = BPrivate::current_team(); 3189c3b4706SAxel Dörfler return QueryServer(SERVER_CHANGE_FLAVOR_INSTANCES_COUNT, &request, 31934c72144SAxel Dörfler sizeof(request), &reply, sizeof(reply)); 32054187cc6Sbeveloper } 32154187cc6Sbeveloper 32234c72144SAxel Dörfler 32354187cc6Sbeveloper status_t 3249dec2310SAxel Dörfler BMediaRosterEx::DecrementAddonFlavorInstancesCount(media_addon_id addonID, 3259dec2310SAxel Dörfler int32 flavorID) 32654187cc6Sbeveloper { 3279c3b4706SAxel Dörfler server_change_flavor_instances_count_request request; 3289c3b4706SAxel Dörfler server_change_flavor_instances_count_reply reply; 32973794717Sbeveloper 3309c3b4706SAxel Dörfler request.add_on_id = addonID; 3319dec2310SAxel Dörfler request.flavor_id = flavorID; 33273794717Sbeveloper request.delta = -1; 3339dec2310SAxel Dörfler request.team = BPrivate::current_team(); 3349c3b4706SAxel Dörfler return QueryServer(SERVER_CHANGE_FLAVOR_INSTANCES_COUNT, &request, 33534c72144SAxel Dörfler sizeof(request), &reply, sizeof(reply)); 33654187cc6Sbeveloper } 33754187cc6Sbeveloper 33834c72144SAxel Dörfler 33954187cc6Sbeveloper status_t 3406aee58a4SJérôme Duval BMediaRosterEx::ReleaseNodeAll(const media_node& node) 3416aee58a4SJérôme Duval { 3426aee58a4SJérôme Duval CALLED(); 3436aee58a4SJérôme Duval if (IS_INVALID_NODE(node)) 3446aee58a4SJérôme Duval return B_MEDIA_BAD_NODE; 3456aee58a4SJérôme Duval 34684da57fdSAdrien Destugues if (node.kind & NODE_KIND_NO_REFCOUNTING) 3476aee58a4SJérôme Duval return B_OK; 3486aee58a4SJérôme Duval 3496aee58a4SJérôme Duval server_release_node_request request; 3506aee58a4SJérôme Duval server_release_node_reply reply; 3516aee58a4SJérôme Duval status_t rv; 3526aee58a4SJérôme Duval 3536aee58a4SJérôme Duval request.node = node; 3546aee58a4SJérôme Duval request.team = BPrivate::current_team(); 3556aee58a4SJérôme Duval 356332cc6bcSAxel Dörfler TRACE("BMediaRoster::ReleaseNodeAll, node %" B_PRId32 ", port %" B_PRId32 357332cc6bcSAxel Dörfler ", team %" B_PRId32 "\n", 3586aee58a4SJérôme Duval node.node, node.port, BPrivate::current_team()); 3596aee58a4SJérôme Duval 3606aee58a4SJérôme Duval rv = QueryServer(SERVER_RELEASE_NODE_ALL, &request, sizeof(request), &reply, 3616aee58a4SJérôme Duval sizeof(reply)); 3626aee58a4SJérôme Duval if (rv != B_OK) { 363c74afb57SJérôme Duval ERROR("BMediaRoster::ReleaseNodeAll failed to query media_server, " 364c74afb57SJérôme Duval "retrying local, node %" B_PRId32 ", port %" 365c74afb57SJérôme Duval B_PRId32 ", team %" B_PRId32 "!\n", node.node, node.port, 366c74afb57SJérôme Duval BPrivate::current_team()); 367c74afb57SJérôme Duval node_final_release_command command; 368c74afb57SJérôme Duval rv = SendToPort(node.port, NODE_FINAL_RELEASE, &command, 369c74afb57SJérôme Duval sizeof(command)); 370c74afb57SJérôme Duval if (rv != B_OK) { 371332cc6bcSAxel Dörfler ERROR("BMediaRoster::ReleaseNodeAll FAILED, node %" B_PRId32 ", port %" 372332cc6bcSAxel Dörfler B_PRId32 ", team %" B_PRId32 "!\n", node.node, node.port, 373332cc6bcSAxel Dörfler BPrivate::current_team()); 3746aee58a4SJérôme Duval } 375c74afb57SJérôme Duval } 3766aee58a4SJérôme Duval return rv; 3776aee58a4SJérôme Duval } 3786aee58a4SJérôme Duval 3796aee58a4SJérôme Duval 3806aee58a4SJérôme Duval status_t 38154187cc6Sbeveloper BMediaRosterEx::SetNodeCreator(media_node_id node, team_id creator) 38254187cc6Sbeveloper { 38354187cc6Sbeveloper server_set_node_creator_request request; 38454187cc6Sbeveloper server_set_node_creator_reply reply; 38554187cc6Sbeveloper 38654187cc6Sbeveloper request.node = node; 38754187cc6Sbeveloper request.creator = creator; 38834c72144SAxel Dörfler return QueryServer(SERVER_SET_NODE_CREATOR, &request, sizeof(request), 38934c72144SAxel Dörfler &reply, sizeof(reply)); 39054187cc6Sbeveloper } 39154187cc6Sbeveloper 39234c72144SAxel Dörfler 39354187cc6Sbeveloper status_t 39434c72144SAxel Dörfler BMediaRosterEx::GetNode(node_type type, media_node* out_node, 39534c72144SAxel Dörfler int32* out_input_id, BString* out_input_name) 39652a38012Sejakowatz { 39752a38012Sejakowatz if (out_node == NULL) 39852a38012Sejakowatz return B_BAD_VALUE; 39952a38012Sejakowatz 4008c6a6096Sbeveloper server_get_node_request request; 4018c6a6096Sbeveloper server_get_node_reply reply; 40252a38012Sejakowatz status_t rv; 40352a38012Sejakowatz 4048c6a6096Sbeveloper request.type = type; 4059dec2310SAxel Dörfler request.team = BPrivate::current_team(); 40634c72144SAxel Dörfler rv = QueryServer(SERVER_GET_NODE, &request, sizeof(request), &reply, 40734c72144SAxel Dörfler sizeof(reply)); 4088c6a6096Sbeveloper if (rv != B_OK) 4098c6a6096Sbeveloper return rv; 41052a38012Sejakowatz 41152a38012Sejakowatz *out_node = reply.node; 41252a38012Sejakowatz if (out_input_id) 41352a38012Sejakowatz *out_input_id = reply.input_id; 41452a38012Sejakowatz if (out_input_name) 41552a38012Sejakowatz *out_input_name = reply.input_name; 4168c6a6096Sbeveloper return rv; 41752a38012Sejakowatz } 41852a38012Sejakowatz 41934c72144SAxel Dörfler 4203620737cSbeveloper status_t 42134c72144SAxel Dörfler BMediaRosterEx::SetNode(node_type type, const media_node* node, 42234c72144SAxel Dörfler const dormant_node_info* info, const media_input* input) 42352a38012Sejakowatz { 4248c6a6096Sbeveloper server_set_node_request request; 4258c6a6096Sbeveloper server_set_node_reply reply; 42652a38012Sejakowatz 4278c6a6096Sbeveloper request.type = type; 42834c72144SAxel Dörfler request.use_node = node != NULL; 42934c72144SAxel Dörfler if (node != NULL) 4308c6a6096Sbeveloper request.node = *node; 43134c72144SAxel Dörfler request.use_dni = info != NULL; 43234c72144SAxel Dörfler if (info != NULL) 4338c6a6096Sbeveloper request.dni = *info; 43434c72144SAxel Dörfler request.use_input = input != NULL; 43534c72144SAxel Dörfler if (input != NULL) 4368c6a6096Sbeveloper request.input = *input; 43752a38012Sejakowatz 43834c72144SAxel Dörfler return QueryServer(SERVER_SET_NODE, &request, sizeof(request), &reply, 43934c72144SAxel Dörfler sizeof(reply)); 44052a38012Sejakowatz } 44152a38012Sejakowatz 44234c72144SAxel Dörfler 4433620737cSbeveloper status_t 4448b04ffc1Sbeveloper BMediaRosterEx::GetAllOutputs(const media_node& node, List<media_output>* list) 4453620737cSbeveloper { 4463620737cSbeveloper int32 cookie; 4473620737cSbeveloper status_t rv; 4483620737cSbeveloper status_t result; 4493620737cSbeveloper 450332cc6bcSAxel Dörfler PRINT(4, "BMediaRosterEx::GetAllOutputs() node %" B_PRId32 ", port %" 451332cc6bcSAxel Dörfler B_PRId32 "\n", node.node, node.port); 4525ac4fbd7Sbeveloper 45365b73ae4SMarcus Overhagen if (!(node.kind & B_BUFFER_PRODUCER)) { 454332cc6bcSAxel Dörfler ERROR("BMediaRosterEx::GetAllOutputs: node %" B_PRId32 " is not a " 45534c72144SAxel Dörfler "B_BUFFER_PRODUCER\n", node.node); 45665b73ae4SMarcus Overhagen return B_MEDIA_BAD_NODE; 45765b73ae4SMarcus Overhagen } 45865b73ae4SMarcus Overhagen 4593620737cSbeveloper result = B_OK; 4603620737cSbeveloper cookie = 0; 46176669a29Sbeveloper list->MakeEmpty(); 4623620737cSbeveloper for (;;) { 4633620737cSbeveloper producer_get_next_output_request request; 4643620737cSbeveloper producer_get_next_output_reply reply; 4653620737cSbeveloper request.cookie = cookie; 46634c72144SAxel Dörfler rv = QueryPort(node.port, PRODUCER_GET_NEXT_OUTPUT, &request, 46734c72144SAxel Dörfler sizeof(request), &reply, sizeof(reply)); 4683620737cSbeveloper if (rv != B_OK) 4693620737cSbeveloper break; 4703620737cSbeveloper cookie = reply.cookie; 47176669a29Sbeveloper if (!list->Insert(reply.output)) { 4725ac4fbd7Sbeveloper ERROR("GetAllOutputs: list->Insert failed\n"); 4733620737cSbeveloper result = B_ERROR; 4743620737cSbeveloper } 4755ac4fbd7Sbeveloper #if DEBUG >= 3 476332cc6bcSAxel Dörfler PRINT(3," next cookie %" B_PRId32 ", ", cookie); 4775ac4fbd7Sbeveloper PRINT_OUTPUT("output ", reply.output); 4785ac4fbd7Sbeveloper #endif 4793620737cSbeveloper } 4803620737cSbeveloper 4813620737cSbeveloper producer_dispose_output_cookie_request request; 4823620737cSbeveloper producer_dispose_output_cookie_reply reply; 48334c72144SAxel Dörfler QueryPort(node.port, PRODUCER_DISPOSE_OUTPUT_COOKIE, &request, 48434c72144SAxel Dörfler sizeof(request), &reply, sizeof(reply)); 4853620737cSbeveloper 4863620737cSbeveloper return result; 4873620737cSbeveloper } 4883620737cSbeveloper 48934c72144SAxel Dörfler 4903620737cSbeveloper status_t 4914d2d96e0Sbeveloper BMediaRosterEx::GetAllOutputs(BBufferProducer* node, List<media_output>* list) 4924d2d96e0Sbeveloper { 4934d2d96e0Sbeveloper int32 cookie; 4944d2d96e0Sbeveloper status_t result; 4954d2d96e0Sbeveloper 496332cc6bcSAxel Dörfler PRINT(4, "BMediaRosterEx::GetAllOutputs() (by pointer) node %" B_PRId32 497332cc6bcSAxel Dörfler ", port %" B_PRId32 "\n", node->ID(), node->ControlPort()); 4984d2d96e0Sbeveloper 4994d2d96e0Sbeveloper result = B_OK; 5004d2d96e0Sbeveloper cookie = 0; 5014d2d96e0Sbeveloper list->MakeEmpty(); 5024d2d96e0Sbeveloper for (;;) { 5034d2d96e0Sbeveloper media_output output; 5044d2d96e0Sbeveloper if (B_OK != node->GetNextOutput(&cookie, &output)) 5054d2d96e0Sbeveloper break; 5064d2d96e0Sbeveloper if (!list->Insert(output)) { 5074d2d96e0Sbeveloper ERROR("GetAllOutputs: list->Insert failed\n"); 5084d2d96e0Sbeveloper result = B_ERROR; 5094d2d96e0Sbeveloper } 5104d2d96e0Sbeveloper #if DEBUG >= 3 511332cc6bcSAxel Dörfler PRINT(3," next cookie %" B_PRId32 ", ", cookie); 5124d2d96e0Sbeveloper PRINT_OUTPUT("output ", output); 5134d2d96e0Sbeveloper #endif 5144d2d96e0Sbeveloper } 5154d2d96e0Sbeveloper node->DisposeOutputCookie(cookie); 5164d2d96e0Sbeveloper return result; 5174d2d96e0Sbeveloper } 5184d2d96e0Sbeveloper 51934c72144SAxel Dörfler 5204d2d96e0Sbeveloper status_t 5218b04ffc1Sbeveloper BMediaRosterEx::GetAllInputs(const media_node& node, List<media_input>* list) 5223620737cSbeveloper { 5233620737cSbeveloper int32 cookie; 5243620737cSbeveloper status_t rv; 5253620737cSbeveloper status_t result; 5263620737cSbeveloper 527332cc6bcSAxel Dörfler PRINT(4, "BMediaRosterEx::GetAllInputs() node %" B_PRId32 ", port %" 528332cc6bcSAxel Dörfler B_PRId32 "\n", node.node, node.port); 5295ac4fbd7Sbeveloper 53065b73ae4SMarcus Overhagen if (!(node.kind & B_BUFFER_CONSUMER)) { 531332cc6bcSAxel Dörfler ERROR("BMediaRosterEx::GetAllInputs: node %" B_PRId32 " is not a " 53234c72144SAxel Dörfler "B_BUFFER_CONSUMER\n", node.node); 53365b73ae4SMarcus Overhagen return B_MEDIA_BAD_NODE; 53465b73ae4SMarcus Overhagen } 53565b73ae4SMarcus Overhagen 5363620737cSbeveloper result = B_OK; 5373620737cSbeveloper cookie = 0; 53876669a29Sbeveloper list->MakeEmpty(); 5393620737cSbeveloper for (;;) { 5403620737cSbeveloper consumer_get_next_input_request request; 5413620737cSbeveloper consumer_get_next_input_reply reply; 5423620737cSbeveloper request.cookie = cookie; 54334c72144SAxel Dörfler rv = QueryPort(node.port, CONSUMER_GET_NEXT_INPUT, &request, 54434c72144SAxel Dörfler sizeof(request), &reply, sizeof(reply)); 5453620737cSbeveloper if (rv != B_OK) 5463620737cSbeveloper break; 5473620737cSbeveloper cookie = reply.cookie; 54876669a29Sbeveloper if (!list->Insert(reply.input)) { 5495ac4fbd7Sbeveloper ERROR("GetAllInputs: list->Insert failed\n"); 5503620737cSbeveloper result = B_ERROR; 5513620737cSbeveloper } 5525ac4fbd7Sbeveloper #if DEBUG >= 3 553332cc6bcSAxel Dörfler PRINT(3," next cookie %" B_PRId32 ", ", cookie); 5545ac4fbd7Sbeveloper PRINT_OUTPUT("input ", reply.input); 5555ac4fbd7Sbeveloper #endif 5563620737cSbeveloper } 5573620737cSbeveloper 5583620737cSbeveloper consumer_dispose_input_cookie_request request; 5593620737cSbeveloper consumer_dispose_input_cookie_reply reply; 56034c72144SAxel Dörfler QueryPort(node.port, CONSUMER_DISPOSE_INPUT_COOKIE, &request, 56134c72144SAxel Dörfler sizeof(request), &reply, sizeof(reply)); 5623620737cSbeveloper 5633620737cSbeveloper return result; 5643620737cSbeveloper } 5653620737cSbeveloper 56634c72144SAxel Dörfler 5673620737cSbeveloper status_t 5684d2d96e0Sbeveloper BMediaRosterEx::GetAllInputs(BBufferConsumer* node, List<media_input>* list) 5694d2d96e0Sbeveloper { 5704d2d96e0Sbeveloper int32 cookie; 5714d2d96e0Sbeveloper status_t result; 5724d2d96e0Sbeveloper 573332cc6bcSAxel Dörfler PRINT(4, "BMediaRosterEx::GetAllInputs() (by pointer) node %" B_PRId32 574332cc6bcSAxel Dörfler ", port %" B_PRId32 "\n", node->ID(), node->ControlPort()); 5754d2d96e0Sbeveloper 5764d2d96e0Sbeveloper result = B_OK; 5774d2d96e0Sbeveloper cookie = 0; 5784d2d96e0Sbeveloper list->MakeEmpty(); 5794d2d96e0Sbeveloper for (;;) { 5804d2d96e0Sbeveloper media_input input; 5814d2d96e0Sbeveloper if (B_OK != node->GetNextInput(&cookie, &input)) 5824d2d96e0Sbeveloper break; 5834d2d96e0Sbeveloper if (!list->Insert(input)) { 5844d2d96e0Sbeveloper ERROR("GetAllInputs: list->Insert failed\n"); 5854d2d96e0Sbeveloper result = B_ERROR; 5864d2d96e0Sbeveloper } 5874d2d96e0Sbeveloper #if DEBUG >= 3 588332cc6bcSAxel Dörfler PRINT(3," next cookie %" B_PRId32 ", ", cookie); 5894d2d96e0Sbeveloper PRINT_INPUT("input ", input); 5904d2d96e0Sbeveloper #endif 5914d2d96e0Sbeveloper } 5924d2d96e0Sbeveloper node->DisposeInputCookie(cookie); 5934d2d96e0Sbeveloper return result; 5944d2d96e0Sbeveloper } 5954d2d96e0Sbeveloper 59634c72144SAxel Dörfler 5974d2d96e0Sbeveloper status_t 5988b04ffc1Sbeveloper BMediaRosterEx::PublishOutputs(const media_node& node, List<media_output>* list) 5993620737cSbeveloper { 6003620737cSbeveloper server_publish_outputs_request request; 6013620737cSbeveloper server_publish_outputs_reply reply; 6023620737cSbeveloper media_output* output; 6033620737cSbeveloper media_output* outputs; 6043620737cSbeveloper int32 count; 605a7b41a96Sbeveloper status_t rv; 6063620737cSbeveloper 60776669a29Sbeveloper count = list->CountItems(); 608332cc6bcSAxel Dörfler TRACE("PublishOutputs: publishing %" B_PRId32 "\n", count); 6093620737cSbeveloper 6103620737cSbeveloper request.node = node; 6113620737cSbeveloper request.count = count; 6123620737cSbeveloper if (count > MAX_OUTPUTS) { 6133620737cSbeveloper void *start_addr; 6143620737cSbeveloper size_t size; 61540f36b03Sbeveloper size = ROUND_UP_TO_PAGE(count * sizeof(media_output)); 61634c72144SAxel Dörfler request.area = create_area("publish outputs", &start_addr, 6172c4232b8SAugustin Cavalier B_ANY_ADDRESS, size, B_NO_LOCK, 6182c4232b8SAugustin Cavalier B_READ_AREA | B_WRITE_AREA | B_CLONEABLE_AREA); 6193620737cSbeveloper if (request.area < B_OK) { 620332cc6bcSAxel Dörfler ERROR("PublishOutputs: failed to create area, %#" B_PRIx32 "\n", 62134c72144SAxel Dörfler request.area); 6223620737cSbeveloper return (status_t)request.area; 6233620737cSbeveloper } 6243620737cSbeveloper outputs = static_cast<media_output *>(start_addr); 6253620737cSbeveloper } else { 6263620737cSbeveloper request.area = -1; 6273620737cSbeveloper outputs = request.outputs; 6283620737cSbeveloper } 629332cc6bcSAxel Dörfler TRACE("PublishOutputs: area %" B_PRId32 "\n", request.area); 6303620737cSbeveloper 63176669a29Sbeveloper int i; 63276669a29Sbeveloper for (i = 0, list->Rewind(); list->GetNext(&output); i++) { 63376669a29Sbeveloper ASSERT(i < count); 6343620737cSbeveloper outputs[i] = *output; 6353620737cSbeveloper } 6363620737cSbeveloper 63734c72144SAxel Dörfler rv = QueryServer(SERVER_PUBLISH_OUTPUTS, &request, sizeof(request), 63834c72144SAxel Dörfler &reply, sizeof(reply)); 639a7b41a96Sbeveloper 640a7b41a96Sbeveloper if (request.area != -1) 641a7b41a96Sbeveloper delete_area(request.area); 642a7b41a96Sbeveloper 643a7b41a96Sbeveloper return rv; 6443620737cSbeveloper } 6453620737cSbeveloper 64634c72144SAxel Dörfler 6473620737cSbeveloper status_t 6488b04ffc1Sbeveloper BMediaRosterEx::PublishInputs(const media_node& node, List<media_input>* list) 6493620737cSbeveloper { 6503620737cSbeveloper server_publish_inputs_request request; 6513620737cSbeveloper server_publish_inputs_reply reply; 6523620737cSbeveloper media_input* input; 6533620737cSbeveloper media_input* inputs; 6543620737cSbeveloper int32 count; 655a7b41a96Sbeveloper status_t rv; 6563620737cSbeveloper 65776669a29Sbeveloper count = list->CountItems(); 658332cc6bcSAxel Dörfler TRACE("PublishInputs: publishing %" B_PRId32 "\n", count); 6593620737cSbeveloper 6603620737cSbeveloper request.node = node; 6613620737cSbeveloper request.count = count; 6623620737cSbeveloper if (count > MAX_INPUTS) { 6633620737cSbeveloper void* start_addr; 6643620737cSbeveloper size_t size; 66540f36b03Sbeveloper size = ROUND_UP_TO_PAGE(count * sizeof(media_input)); 66634c72144SAxel Dörfler request.area = create_area("publish inputs", &start_addr, 6672c4232b8SAugustin Cavalier B_ANY_ADDRESS, size, B_NO_LOCK, 6682c4232b8SAugustin Cavalier B_READ_AREA | B_WRITE_AREA | B_CLONEABLE_AREA); 6693620737cSbeveloper if (request.area < B_OK) { 670332cc6bcSAxel Dörfler ERROR("PublishInputs: failed to create area, %#" B_PRIx32 "\n", 671332cc6bcSAxel Dörfler request.area); 6723620737cSbeveloper return (status_t)request.area; 6733620737cSbeveloper } 6743620737cSbeveloper inputs = static_cast<media_input *>(start_addr); 6753620737cSbeveloper } else { 6763620737cSbeveloper request.area = -1; 6773620737cSbeveloper inputs = request.inputs; 6783620737cSbeveloper } 679332cc6bcSAxel Dörfler TRACE("PublishInputs: area %" B_PRId32 "\n", request.area); 6803620737cSbeveloper 68176669a29Sbeveloper int i; 68276669a29Sbeveloper for (i = 0, list->Rewind(); list->GetNext(&input); i++) { 68376669a29Sbeveloper ASSERT(i < count); 6843620737cSbeveloper inputs[i] = *input; 6853620737cSbeveloper } 6863620737cSbeveloper 68734c72144SAxel Dörfler rv = QueryServer(SERVER_PUBLISH_INPUTS, &request, sizeof(request), 68834c72144SAxel Dörfler &reply, sizeof(reply)); 689a7b41a96Sbeveloper 690a7b41a96Sbeveloper if (request.area != -1) 691a7b41a96Sbeveloper delete_area(request.area); 692a7b41a96Sbeveloper 693a7b41a96Sbeveloper return rv; 6943620737cSbeveloper } 6953620737cSbeveloper 69634c72144SAxel Dörfler 69734c72144SAxel Dörfler BTimeSource* 698f4ec236cSAxel Dörfler BMediaRosterEx::MakeTimeSourceObject(media_node_id timeSourceID) 69934c72144SAxel Dörfler { 70034c72144SAxel Dörfler media_node clone; 701f4ec236cSAxel Dörfler status_t status = GetNodeFor(timeSourceID, &clone); 702f4ec236cSAxel Dörfler if (status != B_OK) { 703f4ec236cSAxel Dörfler ERROR("BMediaRosterEx::MakeTimeSourceObject: GetNodeFor failed: %s\n", 704f4ec236cSAxel Dörfler strerror(status)); 70534c72144SAxel Dörfler return NULL; 70634c72144SAxel Dörfler } 70734c72144SAxel Dörfler 708f4ec236cSAxel Dörfler BTimeSource* source = gTimeSourceObjectManager->GetTimeSource(clone); 70934c72144SAxel Dörfler if (source == NULL) { 71034c72144SAxel Dörfler ERROR("BMediaRosterEx::MakeTimeSourceObject: GetTimeSource failed\n"); 71134c72144SAxel Dörfler return NULL; 71234c72144SAxel Dörfler } 71334c72144SAxel Dörfler 71434c72144SAxel Dörfler // TODO: release? 71534c72144SAxel Dörfler ReleaseNode(clone); 71634c72144SAxel Dörfler 71734c72144SAxel Dörfler return source; 71834c72144SAxel Dörfler } 71934c72144SAxel Dörfler 72034c72144SAxel Dörfler 72134c72144SAxel Dörfler // #pragma mark - public BMediaRoster 72234c72144SAxel Dörfler 72352a38012Sejakowatz 72452a38012Sejakowatz status_t 72534c72144SAxel Dörfler BMediaRoster::GetVideoInput(media_node* _node) 72652a38012Sejakowatz { 72752a38012Sejakowatz CALLED(); 72834c72144SAxel Dörfler return MediaRosterEx(this)->GetNode(VIDEO_INPUT, _node); 72952a38012Sejakowatz } 73052a38012Sejakowatz 73152a38012Sejakowatz 73252a38012Sejakowatz status_t 73334c72144SAxel Dörfler BMediaRoster::GetAudioInput(media_node* _node) 73452a38012Sejakowatz { 73552a38012Sejakowatz CALLED(); 73634c72144SAxel Dörfler return MediaRosterEx(this)->GetNode(AUDIO_INPUT, _node); 73752a38012Sejakowatz } 73852a38012Sejakowatz 73952a38012Sejakowatz 74052a38012Sejakowatz status_t 74134c72144SAxel Dörfler BMediaRoster::GetVideoOutput(media_node* _node) 74252a38012Sejakowatz { 74352a38012Sejakowatz CALLED(); 74434c72144SAxel Dörfler return MediaRosterEx(this)->GetNode(VIDEO_OUTPUT, _node); 74552a38012Sejakowatz } 74652a38012Sejakowatz 74752a38012Sejakowatz 74852a38012Sejakowatz status_t 74934c72144SAxel Dörfler BMediaRoster::GetAudioMixer(media_node* _node) 75052a38012Sejakowatz { 75152a38012Sejakowatz CALLED(); 75234c72144SAxel Dörfler return MediaRosterEx(this)->GetNode(AUDIO_MIXER, _node); 75352a38012Sejakowatz } 75452a38012Sejakowatz 75552a38012Sejakowatz 75652a38012Sejakowatz status_t 75734c72144SAxel Dörfler BMediaRoster::GetAudioOutput(media_node* _node) 75852a38012Sejakowatz { 75952a38012Sejakowatz CALLED(); 76034c72144SAxel Dörfler return MediaRosterEx(this)->GetNode(AUDIO_OUTPUT, _node); 76152a38012Sejakowatz } 76252a38012Sejakowatz 76352a38012Sejakowatz 76452a38012Sejakowatz status_t 76534c72144SAxel Dörfler BMediaRoster::GetAudioOutput(media_node* _node, int32* _inputID, 76634c72144SAxel Dörfler BString* _inputName) 76752a38012Sejakowatz { 76852a38012Sejakowatz CALLED(); 76934c72144SAxel Dörfler return MediaRosterEx(this)->GetNode(AUDIO_OUTPUT_EX, _node, _inputID, 77034c72144SAxel Dörfler _inputName); 77152a38012Sejakowatz } 77252a38012Sejakowatz 77352a38012Sejakowatz 77452a38012Sejakowatz status_t 77534c72144SAxel Dörfler BMediaRoster::GetTimeSource(media_node* _node) 77652a38012Sejakowatz { 77752a38012Sejakowatz CALLED(); 77886bce45bSbeveloper status_t rv; 77986bce45bSbeveloper 78034c72144SAxel Dörfler // TODO: need to do this in a nicer way. 78186bce45bSbeveloper 78234c72144SAxel Dörfler rv = MediaRosterEx(this)->GetNode(TIME_SOURCE, _node); 78386bce45bSbeveloper if (rv != B_OK) 78486bce45bSbeveloper return rv; 78586bce45bSbeveloper 78686bce45bSbeveloper // We don't do reference counting for timesources, that's why we 78786bce45bSbeveloper // release the node immediately. 78834c72144SAxel Dörfler ReleaseNode(*_node); 78986bce45bSbeveloper 79086bce45bSbeveloper // we need to remember to not use this node with server side reference counting 79134c72144SAxel Dörfler _node->kind |= NODE_KIND_NO_REFCOUNTING; 79286bce45bSbeveloper return B_OK; 79352a38012Sejakowatz } 79452a38012Sejakowatz 79552a38012Sejakowatz 79652a38012Sejakowatz status_t 79752a38012Sejakowatz BMediaRoster::SetVideoInput(const media_node& producer) 79852a38012Sejakowatz { 79952a38012Sejakowatz CALLED(); 8008b04ffc1Sbeveloper return MediaRosterEx(this)->SetNode(VIDEO_INPUT, &producer); 80152a38012Sejakowatz } 80252a38012Sejakowatz 80352a38012Sejakowatz 80452a38012Sejakowatz status_t 80552a38012Sejakowatz BMediaRoster::SetVideoInput(const dormant_node_info& producer) 80652a38012Sejakowatz { 80752a38012Sejakowatz CALLED(); 8088b04ffc1Sbeveloper return MediaRosterEx(this)->SetNode(VIDEO_INPUT, NULL, &producer); 80952a38012Sejakowatz } 81052a38012Sejakowatz 81152a38012Sejakowatz 81252a38012Sejakowatz status_t 81352a38012Sejakowatz BMediaRoster::SetAudioInput(const media_node& producer) 81452a38012Sejakowatz { 81552a38012Sejakowatz CALLED(); 8168b04ffc1Sbeveloper return MediaRosterEx(this)->SetNode(AUDIO_INPUT, &producer); 81752a38012Sejakowatz } 81852a38012Sejakowatz 81952a38012Sejakowatz 82052a38012Sejakowatz status_t 82152a38012Sejakowatz BMediaRoster::SetAudioInput(const dormant_node_info& producer) 82252a38012Sejakowatz { 82352a38012Sejakowatz CALLED(); 8248b04ffc1Sbeveloper return MediaRosterEx(this)->SetNode(AUDIO_INPUT, NULL, &producer); 82552a38012Sejakowatz } 82652a38012Sejakowatz 82752a38012Sejakowatz 82852a38012Sejakowatz status_t 82952a38012Sejakowatz BMediaRoster::SetVideoOutput(const media_node& consumer) 83052a38012Sejakowatz { 83152a38012Sejakowatz CALLED(); 8328b04ffc1Sbeveloper return MediaRosterEx(this)->SetNode(VIDEO_OUTPUT, &consumer); 83352a38012Sejakowatz } 83452a38012Sejakowatz 83552a38012Sejakowatz 83652a38012Sejakowatz status_t 83752a38012Sejakowatz BMediaRoster::SetVideoOutput(const dormant_node_info& consumer) 83852a38012Sejakowatz { 83952a38012Sejakowatz CALLED(); 8408b04ffc1Sbeveloper return MediaRosterEx(this)->SetNode(VIDEO_OUTPUT, NULL, &consumer); 84152a38012Sejakowatz } 84252a38012Sejakowatz 84352a38012Sejakowatz 84452a38012Sejakowatz status_t 84552a38012Sejakowatz BMediaRoster::SetAudioOutput(const media_node& consumer) 84652a38012Sejakowatz { 84752a38012Sejakowatz CALLED(); 8488b04ffc1Sbeveloper return MediaRosterEx(this)->SetNode(AUDIO_OUTPUT, &consumer); 84952a38012Sejakowatz } 85052a38012Sejakowatz 85152a38012Sejakowatz 85252a38012Sejakowatz status_t 85334c72144SAxel Dörfler BMediaRoster::SetAudioOutput(const media_input& input) 85452a38012Sejakowatz { 85552a38012Sejakowatz CALLED(); 85634c72144SAxel Dörfler return MediaRosterEx(this)->SetNode(AUDIO_OUTPUT, NULL, NULL, &input); 85752a38012Sejakowatz } 85852a38012Sejakowatz 85952a38012Sejakowatz 86052a38012Sejakowatz status_t 86152a38012Sejakowatz BMediaRoster::SetAudioOutput(const dormant_node_info& consumer) 86252a38012Sejakowatz { 86352a38012Sejakowatz CALLED(); 8648b04ffc1Sbeveloper return MediaRosterEx(this)->SetNode(AUDIO_OUTPUT, NULL, &consumer); 86552a38012Sejakowatz } 86652a38012Sejakowatz 86752a38012Sejakowatz 86852a38012Sejakowatz status_t 86934c72144SAxel Dörfler BMediaRoster::GetNodeFor(media_node_id node, media_node* clone) 87052a38012Sejakowatz { 8719e9417d2Sbeveloper CALLED(); 8729e9417d2Sbeveloper if (clone == NULL) 8739e9417d2Sbeveloper return B_BAD_VALUE; 87465b73ae4SMarcus Overhagen if (IS_INVALID_NODEID(node)) 8759e9417d2Sbeveloper return B_MEDIA_BAD_NODE; 8769e9417d2Sbeveloper 8779e9417d2Sbeveloper server_get_node_for_request request; 8789e9417d2Sbeveloper server_get_node_for_reply reply; 8799e9417d2Sbeveloper status_t rv; 8809e9417d2Sbeveloper 8819dec2310SAxel Dörfler request.node_id = node; 8829dec2310SAxel Dörfler request.team = BPrivate::current_team(); 8839e9417d2Sbeveloper 88434c72144SAxel Dörfler rv = QueryServer(SERVER_GET_NODE_FOR, &request, sizeof(request), &reply, 88534c72144SAxel Dörfler sizeof(reply)); 8869e9417d2Sbeveloper if (rv != B_OK) 8879e9417d2Sbeveloper return rv; 8889e9417d2Sbeveloper 8899e9417d2Sbeveloper *clone = reply.clone; 8909e9417d2Sbeveloper return B_OK; 89152a38012Sejakowatz } 89252a38012Sejakowatz 89352a38012Sejakowatz 89452a38012Sejakowatz status_t 89552a38012Sejakowatz BMediaRoster::GetSystemTimeSource(media_node* clone) 89652a38012Sejakowatz { 89752a38012Sejakowatz CALLED(); 89886bce45bSbeveloper status_t rv; 89986bce45bSbeveloper 90034c72144SAxel Dörfler // TODO: need to do this in a nicer way. 90186bce45bSbeveloper 90286bce45bSbeveloper rv = MediaRosterEx(this)->GetNode(SYSTEM_TIME_SOURCE, clone); 90386bce45bSbeveloper if (rv != B_OK) 90486bce45bSbeveloper return rv; 90586bce45bSbeveloper 90686bce45bSbeveloper // We don't do reference counting for timesources, that's why we 90786bce45bSbeveloper // release the node immediately. 90886bce45bSbeveloper ReleaseNode(*clone); 90986bce45bSbeveloper 91034c72144SAxel Dörfler // we need to remember to not use this node with server side reference 91134c72144SAxel Dörfler // counting 91286bce45bSbeveloper clone->kind |= NODE_KIND_NO_REFCOUNTING; 91386bce45bSbeveloper 91486bce45bSbeveloper return B_OK; 91552a38012Sejakowatz } 91652a38012Sejakowatz 91752a38012Sejakowatz 91852a38012Sejakowatz status_t 91952a38012Sejakowatz BMediaRoster::ReleaseNode(const media_node& node) 92052a38012Sejakowatz { 9219e9417d2Sbeveloper CALLED(); 92240f36b03Sbeveloper if (IS_INVALID_NODE(node)) 9239e9417d2Sbeveloper return B_MEDIA_BAD_NODE; 92452a38012Sejakowatz 92586bce45bSbeveloper if (node.kind & NODE_KIND_NO_REFCOUNTING) { 926cb2c4f8dSAdrien Destugues TRACE("BMediaRoster::ReleaseNode, trying to release reference " 927332cc6bcSAxel Dörfler "counting disabled timesource, node %" B_PRId32 ", port %" B_PRId32 928332cc6bcSAxel Dörfler ", team %" B_PRId32 "\n", node.node, node.port, 929332cc6bcSAxel Dörfler BPrivate::current_team()); 93086bce45bSbeveloper return B_OK; 93186bce45bSbeveloper } 93286bce45bSbeveloper 9339e9417d2Sbeveloper server_release_node_request request; 9349e9417d2Sbeveloper server_release_node_reply reply; 935cf4e2277Sbeveloper status_t rv; 9369e9417d2Sbeveloper 9379e9417d2Sbeveloper request.node = node; 9389dec2310SAxel Dörfler request.team = BPrivate::current_team(); 9399e9417d2Sbeveloper 940332cc6bcSAxel Dörfler TRACE("BMediaRoster::ReleaseNode, node %" B_PRId32 ", port %" B_PRId32 941332cc6bcSAxel Dörfler ", team %" B_PRId32 "\n", node.node, node.port, 942332cc6bcSAxel Dörfler BPrivate::current_team()); 943cf4e2277Sbeveloper 94434c72144SAxel Dörfler rv = QueryServer(SERVER_RELEASE_NODE, &request, sizeof(request), &reply, 94534c72144SAxel Dörfler sizeof(reply)); 946cf4e2277Sbeveloper if (rv != B_OK) { 947332cc6bcSAxel Dörfler ERROR("BMediaRoster::ReleaseNode FAILED, node %" B_PRId32 ", port %" 948332cc6bcSAxel Dörfler B_PRId32 ", team %" B_PRId32 "!\n", node.node, node.port, 949332cc6bcSAxel Dörfler BPrivate::current_team()); 950cf4e2277Sbeveloper } 951cf4e2277Sbeveloper return rv; 9529e9417d2Sbeveloper } 95352a38012Sejakowatz 95434c72144SAxel Dörfler 95552a38012Sejakowatz BTimeSource* 95634c72144SAxel Dörfler BMediaRoster::MakeTimeSourceFor(const media_node& forNode) 95752a38012Sejakowatz { 958f180ef79Sbeveloper // MakeTimeSourceFor() returns a BTimeSource object 959f180ef79Sbeveloper // corresponding to the specified node's time source. 960f180ef79Sbeveloper 961835140c8Sbeveloper CALLED(); 962f180ef79Sbeveloper 96334c72144SAxel Dörfler if (IS_SYSTEM_TIMESOURCE(forNode)) { 964f180ef79Sbeveloper // special handling for the system time source 96534c72144SAxel Dörfler TRACE("BMediaRoster::MakeTimeSourceFor, asked for system time " 96634c72144SAxel Dörfler "source\n"); 96734c72144SAxel Dörfler return MediaRosterEx(this)->MakeTimeSourceObject( 96834c72144SAxel Dörfler NODE_SYSTEM_TIMESOURCE_ID); 969f180ef79Sbeveloper } 970f180ef79Sbeveloper 97134c72144SAxel Dörfler if (IS_INVALID_NODE(forNode)) { 972332cc6bcSAxel Dörfler ERROR("BMediaRoster::MakeTimeSourceFor: for_node invalid, node %" 973332cc6bcSAxel Dörfler B_PRId32 ", port %" B_PRId32 ", kinds 0x%" B_PRIx32 "\n", 974332cc6bcSAxel Dörfler forNode.node, forNode.port, forNode.kind); 9755917dd5bSbeveloper return NULL; 9760e21b167Sbeveloper } 9770e21b167Sbeveloper 978332cc6bcSAxel Dörfler TRACE("BMediaRoster::MakeTimeSourceFor: node %" B_PRId32 " enter\n", 979332cc6bcSAxel Dörfler forNode.node); 9805917dd5bSbeveloper 9815917dd5bSbeveloper node_get_timesource_request request; 9825917dd5bSbeveloper node_get_timesource_reply reply; 9835917dd5bSbeveloper BTimeSource *source; 9845917dd5bSbeveloper status_t rv; 9855917dd5bSbeveloper 98692e575c1Sbeveloper // ask the node to get it's current timesource id 98734c72144SAxel Dörfler rv = QueryPort(forNode.port, NODE_GET_TIMESOURCE, &request, 98834c72144SAxel Dörfler sizeof(request), &reply, sizeof(reply)); 9895917dd5bSbeveloper if (rv != B_OK) { 9905ac4fbd7Sbeveloper ERROR("BMediaRoster::MakeTimeSourceFor: request failed\n"); 9915917dd5bSbeveloper return NULL; 9925917dd5bSbeveloper } 9935917dd5bSbeveloper 9945917dd5bSbeveloper source = MediaRosterEx(this)->MakeTimeSourceObject(reply.timesource_id); 9955917dd5bSbeveloper 996332cc6bcSAxel Dörfler TRACE("BMediaRoster::MakeTimeSourceFor: node %" B_PRId32 " leave\n", 997332cc6bcSAxel Dörfler forNode.node); 998287f7492Sbeveloper 999835140c8Sbeveloper return source; 100052a38012Sejakowatz } 100152a38012Sejakowatz 100252a38012Sejakowatz 100352a38012Sejakowatz status_t 100434c72144SAxel Dörfler BMediaRoster::Connect(const media_source& from, const media_destination& to, 100534c72144SAxel Dörfler media_format* _format, media_output* _output, media_input* _input) 100652a38012Sejakowatz { 100734c72144SAxel Dörfler return BMediaRoster::Connect(from, to, _format, _output, _input, 0); 1008eae26d3dSbeveloper } 1009eae26d3dSbeveloper 1010eae26d3dSbeveloper 1011eae26d3dSbeveloper status_t 101234c72144SAxel Dörfler BMediaRoster::Connect(const media_source& from, const media_destination& to, 101334c72144SAxel Dörfler media_format* io_format, media_output* out_output, media_input* out_input, 101434c72144SAxel Dörfler uint32 in_flags, void* _reserved) 1015eae26d3dSbeveloper { 101652a38012Sejakowatz CALLED(); 101752a38012Sejakowatz if (io_format == NULL || out_output == NULL || out_input == NULL) 101852a38012Sejakowatz return B_BAD_VALUE; 101940f36b03Sbeveloper if (IS_INVALID_SOURCE(from)) { 10205ac4fbd7Sbeveloper ERROR("BMediaRoster::Connect: media_source invalid\n"); 102152a38012Sejakowatz return B_MEDIA_BAD_SOURCE; 10229e9417d2Sbeveloper } 102340f36b03Sbeveloper if (IS_INVALID_DESTINATION(to)) { 10245ac4fbd7Sbeveloper ERROR("BMediaRoster::Connect: media_destination invalid\n"); 102552a38012Sejakowatz return B_MEDIA_BAD_DESTINATION; 10269e9417d2Sbeveloper } 102752a38012Sejakowatz 102852a38012Sejakowatz status_t rv; 102965b73ae4SMarcus Overhagen 103065b73ae4SMarcus Overhagen // find the output and input nodes 103134c72144SAxel Dörfler // TODO: isn't there a easier way? 103265b73ae4SMarcus Overhagen media_node sourcenode; 103365b73ae4SMarcus Overhagen media_node destnode; 103465b73ae4SMarcus Overhagen rv = GetNodeFor(NodeIDFor(from.port), &sourcenode); 103565b73ae4SMarcus Overhagen if (rv != B_OK) { 1036332cc6bcSAxel Dörfler ERROR("BMediaRoster::Connect: Can't find source node for port %" 1037332cc6bcSAxel Dörfler B_PRId32 "\n", from.port); 103865b73ae4SMarcus Overhagen return B_MEDIA_BAD_SOURCE; 103965b73ae4SMarcus Overhagen } 104065b73ae4SMarcus Overhagen ReleaseNode(sourcenode); 104165b73ae4SMarcus Overhagen rv = GetNodeFor(NodeIDFor(to.port), &destnode); 104265b73ae4SMarcus Overhagen if (rv != B_OK) { 104334c72144SAxel Dörfler ERROR("BMediaRoster::Connect: Can't find destination node for port " 1044332cc6bcSAxel Dörfler "%" B_PRId32 "\n", to.port); 104565b73ae4SMarcus Overhagen return B_MEDIA_BAD_DESTINATION; 104665b73ae4SMarcus Overhagen } 104765b73ae4SMarcus Overhagen ReleaseNode(destnode); 104865b73ae4SMarcus Overhagen 104965b73ae4SMarcus Overhagen if (!(sourcenode.kind & B_BUFFER_PRODUCER)) { 1050332cc6bcSAxel Dörfler ERROR("BMediaRoster::Connect: source node %" B_PRId32 " is not a " 105134c72144SAxel Dörfler "B_BUFFER_PRODUCER\n", sourcenode.node); 105265b73ae4SMarcus Overhagen return B_MEDIA_BAD_SOURCE; 105365b73ae4SMarcus Overhagen } 105465b73ae4SMarcus Overhagen if (!(destnode.kind & B_BUFFER_CONSUMER)) { 1055332cc6bcSAxel Dörfler ERROR("BMediaRoster::Connect: destination node %" B_PRId32 " is not a " 105634c72144SAxel Dörfler "B_BUFFER_CONSUMER\n", destnode.node); 105765b73ae4SMarcus Overhagen return B_MEDIA_BAD_DESTINATION; 105865b73ae4SMarcus Overhagen } 105965b73ae4SMarcus Overhagen 10608c6a6096Sbeveloper producer_format_proposal_request request1; 10618c6a6096Sbeveloper producer_format_proposal_reply reply1; 106252a38012Sejakowatz 106334c72144SAxel Dörfler PRINT_FORMAT("BMediaRoster::Connect calling " 106434c72144SAxel Dörfler "BBufferProducer::FormatProposal with format ", *io_format); 106569983609Sbeveloper 106652a38012Sejakowatz // BBufferProducer::FormatProposal 10678c6a6096Sbeveloper request1.output = from; 10688c6a6096Sbeveloper request1.format = *io_format; 106934c72144SAxel Dörfler rv = QueryPort(from.port, PRODUCER_FORMAT_PROPOSAL, &request1, 107034c72144SAxel Dörfler sizeof(request1), &reply1, sizeof(reply1)); 10718c6a6096Sbeveloper if (rv != B_OK) { 107234c72144SAxel Dörfler ERROR("BMediaRoster::Connect: aborted after " 1073332cc6bcSAxel Dörfler "BBufferProducer::FormatProposal, status = %#" B_PRIx32 "\n",rv); 107452a38012Sejakowatz return rv; 107552a38012Sejakowatz } 10768c6a6096Sbeveloper // reply1.format now contains the format proposed by the producer 10778c6a6096Sbeveloper 10788c6a6096Sbeveloper consumer_accept_format_request request2; 10798c6a6096Sbeveloper consumer_accept_format_reply reply2; 10808c6a6096Sbeveloper 108134c72144SAxel Dörfler PRINT_FORMAT("BMediaRoster::Connect calling " 108234c72144SAxel Dörfler "BBufferConsumer::AcceptFormat with format ", reply1.format); 108369983609Sbeveloper 10848c6a6096Sbeveloper // BBufferConsumer::AcceptFormat 10858c6a6096Sbeveloper request2.dest = to; 10868c6a6096Sbeveloper request2.format = reply1.format; 108734c72144SAxel Dörfler rv = QueryPort(to.port, CONSUMER_ACCEPT_FORMAT, &request2, 108834c72144SAxel Dörfler sizeof(request2), &reply2, sizeof(reply2)); 10898c6a6096Sbeveloper if (rv != B_OK) { 109034c72144SAxel Dörfler ERROR("BMediaRoster::Connect: aborted after " 1091332cc6bcSAxel Dörfler "BBufferConsumer::AcceptFormat, status = %#" B_PRIx32 "\n",rv); 10928c6a6096Sbeveloper return rv; 10938c6a6096Sbeveloper } 10948c6a6096Sbeveloper // reply2.format now contains the format accepted by the consumer 10958c6a6096Sbeveloper 10968c6a6096Sbeveloper // BBufferProducer::PrepareToConnect 10978c6a6096Sbeveloper producer_prepare_to_connect_request request3; 10988c6a6096Sbeveloper producer_prepare_to_connect_reply reply3; 10998c6a6096Sbeveloper 110034c72144SAxel Dörfler PRINT_FORMAT("BMediaRoster::Connect calling " 110134c72144SAxel Dörfler "BBufferProducer::PrepareToConnect with format", reply2.format); 110269983609Sbeveloper 11038c6a6096Sbeveloper request3.source = from; 11048c6a6096Sbeveloper request3.destination = to; 11058c6a6096Sbeveloper request3.format = reply2.format; 110634c72144SAxel Dörfler strcpy(request3.name, "XXX some default name"); // TODO: fix this 110734c72144SAxel Dörfler rv = QueryPort(from.port, PRODUCER_PREPARE_TO_CONNECT, &request3, 110834c72144SAxel Dörfler sizeof(request3), &reply3, sizeof(reply3)); 11098c6a6096Sbeveloper if (rv != B_OK) { 111034c72144SAxel Dörfler ERROR("BMediaRoster::Connect: aborted after " 1111332cc6bcSAxel Dörfler "BBufferProducer::PrepareToConnect, status = %#" B_PRIx32 "\n", rv); 11128c6a6096Sbeveloper return rv; 11138c6a6096Sbeveloper } 11148c6a6096Sbeveloper // reply3.format is still our pretty media format 11158c6a6096Sbeveloper // reply3.out_source the real source to be used for the connection 111634c72144SAxel Dörfler // reply3.name the name BBufferConsumer::Connected will see in the 111734c72144SAxel Dörfler // outInput->name argument 11188c6a6096Sbeveloper 11198c6a6096Sbeveloper // BBufferConsumer::Connected 11208c6a6096Sbeveloper consumer_connected_request request4; 11218c6a6096Sbeveloper consumer_connected_reply reply4; 11228c6a6096Sbeveloper status_t con_status; 11238c6a6096Sbeveloper 112434c72144SAxel Dörfler PRINT_FORMAT("BMediaRoster::Connect calling BBufferConsumer::Connected() " 112534c72144SAxel Dörfler "with format ", reply3.format); 112669983609Sbeveloper 112769983609Sbeveloper request4.input.node = destnode; 112869983609Sbeveloper request4.input.source = reply3.out_source; 112969983609Sbeveloper request4.input.destination = to; 113069983609Sbeveloper request4.input.format = reply3.format; 113169983609Sbeveloper strcpy(request4.input.name, reply3.name); 113269983609Sbeveloper 113334c72144SAxel Dörfler con_status = QueryPort(to.port, CONSUMER_CONNECTED, &request4, 113434c72144SAxel Dörfler sizeof(request4), &reply4, sizeof(reply4)); 11358c6a6096Sbeveloper if (con_status != B_OK) { 113634c72144SAxel Dörfler ERROR("BMediaRoster::Connect: aborting after " 1137332cc6bcSAxel Dörfler "BBufferConsumer::Connected, status = %#" B_PRIx32 "\n", 1138332cc6bcSAxel Dörfler con_status); 11398c6a6096Sbeveloper // we do NOT return here! 11408c6a6096Sbeveloper } 114134c72144SAxel Dörfler // con_status contains the status code to be supplied to 114234c72144SAxel Dörfler // BBufferProducer::Connect's status argument 114334c72144SAxel Dörfler // reply4.input contains the media_input that describes the connection 114434c72144SAxel Dörfler // from the consumer point of view 11458c6a6096Sbeveloper 11468c6a6096Sbeveloper // BBufferProducer::Connect 11478c6a6096Sbeveloper producer_connect_request request5; 11488c6a6096Sbeveloper producer_connect_reply reply5; 11498c6a6096Sbeveloper 115034c72144SAxel Dörfler PRINT_FORMAT("BMediaRoster::Connect calling BBufferProducer::Connect with " 115134c72144SAxel Dörfler "format ", reply4.input.format); 115269983609Sbeveloper 11538c6a6096Sbeveloper request5.error = con_status; 11548c6a6096Sbeveloper request5.source = reply3.out_source; 11558c6a6096Sbeveloper request5.destination = reply4.input.destination; 115669983609Sbeveloper request5.format = reply4.input.format; 11578c6a6096Sbeveloper strcpy(request5.name, reply4.input.name); 115834c72144SAxel Dörfler rv = QueryPort(reply4.input.source.port, PRODUCER_CONNECT, &request5, 115934c72144SAxel Dörfler sizeof(request5), &reply5, sizeof(reply5)); 11608c6a6096Sbeveloper if (con_status != B_OK) { 11615ac4fbd7Sbeveloper ERROR("BMediaRoster::Connect: aborted\n"); 11628c6a6096Sbeveloper return con_status; 11638c6a6096Sbeveloper } 11648c6a6096Sbeveloper if (rv != B_OK) { 116534c72144SAxel Dörfler ERROR("BMediaRoster::Connect: aborted after BBufferProducer::Connect()" 1166332cc6bcSAxel Dörfler ", status = %#" B_PRIx32 "\n", rv); 11678c6a6096Sbeveloper return rv; 11688c6a6096Sbeveloper } 11698c6a6096Sbeveloper // reply5.name contains the name assigned to the connection by the producer 11708c6a6096Sbeveloper 11718c6a6096Sbeveloper // initilize connection info 117269983609Sbeveloper *io_format = reply4.input.format; 11738c6a6096Sbeveloper *out_input = reply4.input; 11748c6a6096Sbeveloper out_output->node = sourcenode; 11758c6a6096Sbeveloper out_output->source = reply4.input.source; 11768c6a6096Sbeveloper out_output->destination = reply4.input.destination; 11778c6a6096Sbeveloper out_output->format = reply4.input.format; 11788c6a6096Sbeveloper strcpy(out_output->name, reply5.name); 11798c6a6096Sbeveloper 11808c6a6096Sbeveloper // the connection is now made 118169983609Sbeveloper PRINT_FORMAT(" format", *io_format); 118269983609Sbeveloper PRINT_INPUT(" input", *out_input); 118369983609Sbeveloper PRINT_OUTPUT(" output", *out_output); 11848c6a6096Sbeveloper 118534c72144SAxel Dörfler // TODO: register connection with server 118634c72144SAxel Dörfler // TODO: we should just send a notification, instead of republishing all 118734c72144SAxel Dörfler // endpoints 118876669a29Sbeveloper List<media_output> outlist; 118976669a29Sbeveloper List<media_input> inlist; 119034c72144SAxel Dörfler if (MediaRosterEx(this)->GetAllOutputs(out_output->node , &outlist) == B_OK) 11918b04ffc1Sbeveloper MediaRosterEx(this)->PublishOutputs(out_output->node , &outlist); 119234c72144SAxel Dörfler if (MediaRosterEx(this)->GetAllInputs(out_input->node , &inlist) == B_OK) 11938b04ffc1Sbeveloper MediaRosterEx(this)->PublishInputs(out_input->node, &inlist); 11948c6a6096Sbeveloper 119534c72144SAxel Dörfler // TODO: if (mute) BBufferProducer::EnableOutput(false) 11969e9417d2Sbeveloper if (in_flags & B_CONNECT_MUTED) { 11979e9417d2Sbeveloper } 11988c6a6096Sbeveloper 11999e9417d2Sbeveloper // send a notification 120034c72144SAxel Dörfler BPrivate::media::notifications::ConnectionMade(*out_input, *out_output, 120134c72144SAxel Dörfler *io_format); 12029e9417d2Sbeveloper 12038c6a6096Sbeveloper return B_OK; 12048c6a6096Sbeveloper }; 120552a38012Sejakowatz 120652a38012Sejakowatz 120752a38012Sejakowatz status_t 12089e9417d2Sbeveloper BMediaRoster::Disconnect(media_node_id source_nodeid, 120934c72144SAxel Dörfler const media_source& source, media_node_id destination_nodeid, 121052a38012Sejakowatz const media_destination& destination) 121152a38012Sejakowatz { 12129e9417d2Sbeveloper CALLED(); 121340f36b03Sbeveloper if (IS_INVALID_NODEID(source_nodeid)) { 12145ac4fbd7Sbeveloper ERROR("BMediaRoster::Disconnect: source media_node_id invalid\n"); 12159e9417d2Sbeveloper return B_MEDIA_BAD_SOURCE; 12169e9417d2Sbeveloper } 121740f36b03Sbeveloper if (IS_INVALID_NODEID(destination_nodeid)) { 12185ac4fbd7Sbeveloper ERROR("BMediaRoster::Disconnect: destination media_node_id invalid\n"); 12199e9417d2Sbeveloper return B_MEDIA_BAD_DESTINATION; 12209e9417d2Sbeveloper } 122140f36b03Sbeveloper if (IS_INVALID_SOURCE(source)) { 12225ac4fbd7Sbeveloper ERROR("BMediaRoster::Disconnect: media_source invalid\n"); 12239e9417d2Sbeveloper return B_MEDIA_BAD_SOURCE; 12249e9417d2Sbeveloper } 122540f36b03Sbeveloper if (IS_INVALID_DESTINATION(destination)) { 12265ac4fbd7Sbeveloper ERROR("BMediaRoster::Disconnect: media_destination invalid\n"); 12279e9417d2Sbeveloper return B_MEDIA_BAD_DESTINATION; 12289e9417d2Sbeveloper } 12299e9417d2Sbeveloper 12309e9417d2Sbeveloper producer_disconnect_request request2; 12319e9417d2Sbeveloper producer_disconnect_reply reply2; 12329e9417d2Sbeveloper consumer_disconnected_request request1; 12339e9417d2Sbeveloper consumer_disconnected_reply reply1; 12349e9417d2Sbeveloper status_t rv1, rv2; 12359e9417d2Sbeveloper 123634c72144SAxel Dörfler // TODO: we should ask the server if this connection really exists 12379e9417d2Sbeveloper 12389e9417d2Sbeveloper request1.source = source; 12399e9417d2Sbeveloper request1.destination = destination; 12409e9417d2Sbeveloper request2.source = source; 12419e9417d2Sbeveloper request2.destination = destination; 12429e9417d2Sbeveloper 124334c72144SAxel Dörfler rv1 = QueryPort(source.port, PRODUCER_DISCONNECT, &request1, 124434c72144SAxel Dörfler sizeof(request1), &reply1, sizeof(reply1)); 124534c72144SAxel Dörfler rv2 = QueryPort(destination.port, CONSUMER_DISCONNECTED, &request2, 124634c72144SAxel Dörfler sizeof(request2), &reply2, sizeof(reply2)); 12479e9417d2Sbeveloper 124834c72144SAxel Dörfler // TODO: unregister connection with server 124934c72144SAxel Dörfler // TODO: we should just send a notification, instead of republishing all 125034c72144SAxel Dörfler // endpoints 125176669a29Sbeveloper List<media_output> outlist; 125276669a29Sbeveloper List<media_input> inlist; 12539e9417d2Sbeveloper media_node sourcenode; 12549e9417d2Sbeveloper media_node destnode; 125534c72144SAxel Dörfler if (GetNodeFor(source_nodeid, &sourcenode) == B_OK) { 125665b73ae4SMarcus Overhagen if (!(sourcenode.kind & B_BUFFER_PRODUCER)) { 1257332cc6bcSAxel Dörfler ERROR("BMediaRoster::Disconnect: source_nodeid %" B_PRId32 1258332cc6bcSAxel Dörfler " is not a B_BUFFER_PRODUCER\n", source_nodeid); 125965b73ae4SMarcus Overhagen } 126034c72144SAxel Dörfler if (MediaRosterEx(this)->GetAllOutputs(sourcenode , &outlist) == B_OK) 12618b04ffc1Sbeveloper MediaRosterEx(this)->PublishOutputs(sourcenode , &outlist); 12629e9417d2Sbeveloper ReleaseNode(sourcenode); 12634f09fa2fSbeveloper } else { 1264332cc6bcSAxel Dörfler ERROR("BMediaRoster::Disconnect: GetNodeFor source_nodeid %" B_PRId32 1265332cc6bcSAxel Dörfler " failed\n", source_nodeid); 12664f09fa2fSbeveloper } 126734c72144SAxel Dörfler if (GetNodeFor(destination_nodeid, &destnode) == B_OK) { 126865b73ae4SMarcus Overhagen if (!(destnode.kind & B_BUFFER_CONSUMER)) { 1269332cc6bcSAxel Dörfler ERROR("BMediaRoster::Disconnect: destination_nodeid %" B_PRId32 1270332cc6bcSAxel Dörfler " is not a B_BUFFER_CONSUMER\n", destination_nodeid); 127165b73ae4SMarcus Overhagen } 127234c72144SAxel Dörfler if (MediaRosterEx(this)->GetAllInputs(destnode , &inlist) == B_OK) 12738b04ffc1Sbeveloper MediaRosterEx(this)->PublishInputs(destnode, &inlist); 12749e9417d2Sbeveloper ReleaseNode(destnode); 12754f09fa2fSbeveloper } else { 1276332cc6bcSAxel Dörfler ERROR("BMediaRoster::Disconnect: GetNodeFor destination_nodeid %" 1277332cc6bcSAxel Dörfler B_PRId32 " failed\n", destination_nodeid); 12784f09fa2fSbeveloper } 12799e9417d2Sbeveloper 12809e9417d2Sbeveloper // send a notification 12819e9417d2Sbeveloper BPrivate::media::notifications::ConnectionBroken(source, destination); 12829e9417d2Sbeveloper 128334c72144SAxel Dörfler return rv1 != B_OK || rv2 != B_OK ? B_ERROR : B_OK; 128452a38012Sejakowatz } 128552a38012Sejakowatz 128634c72144SAxel Dörfler 128765b73ae4SMarcus Overhagen status_t 128865b73ae4SMarcus Overhagen BMediaRoster::Disconnect(const media_output& output, const media_input& input) 128965b73ae4SMarcus Overhagen { 129065b73ae4SMarcus Overhagen if (IS_INVALID_NODEID(output.node.node)) { 1291332cc6bcSAxel Dörfler printf("BMediaRoster::Disconnect: output.node.node %" B_PRId32 1292332cc6bcSAxel Dörfler " invalid\n", output.node.node); 129365b73ae4SMarcus Overhagen return B_MEDIA_BAD_SOURCE; 129465b73ae4SMarcus Overhagen } 129565b73ae4SMarcus Overhagen if (IS_INVALID_NODEID(input.node.node)) { 1296332cc6bcSAxel Dörfler printf("BMediaRoster::Disconnect: input.node.node %" B_PRId32 1297332cc6bcSAxel Dörfler " invalid\n", input.node.node); 129865b73ae4SMarcus Overhagen return B_MEDIA_BAD_DESTINATION; 129965b73ae4SMarcus Overhagen } 130065b73ae4SMarcus Overhagen if (!(output.node.kind & B_BUFFER_PRODUCER)) { 1301332cc6bcSAxel Dörfler printf("BMediaRoster::Disconnect: output.node.kind 0x%" B_PRIx32 1302332cc6bcSAxel Dörfler " is no B_BUFFER_PRODUCER\n", output.node.kind); 130365b73ae4SMarcus Overhagen return B_MEDIA_BAD_SOURCE; 130465b73ae4SMarcus Overhagen } 130565b73ae4SMarcus Overhagen if (!(input.node.kind & B_BUFFER_CONSUMER)) { 1306332cc6bcSAxel Dörfler printf("BMediaRoster::Disconnect: input.node.kind 0x%" B_PRIx32 1307332cc6bcSAxel Dörfler " is no B_BUFFER_PRODUCER\n", input.node.kind); 130865b73ae4SMarcus Overhagen return B_MEDIA_BAD_DESTINATION; 130965b73ae4SMarcus Overhagen } 131065b73ae4SMarcus Overhagen if (input.source.port != output.source.port) { 1311332cc6bcSAxel Dörfler printf("BMediaRoster::Disconnect: input.source.port %" B_PRId32 1312332cc6bcSAxel Dörfler " doesn't match output.source.port %" B_PRId32 "\n", 1313332cc6bcSAxel Dörfler input.source.port, output.source.port); 131465b73ae4SMarcus Overhagen return B_MEDIA_BAD_SOURCE; 131565b73ae4SMarcus Overhagen } 131665b73ae4SMarcus Overhagen if (input.source.id != output.source.id) { 1317332cc6bcSAxel Dörfler printf("BMediaRoster::Disconnect: input.source.id %" B_PRId32 1318332cc6bcSAxel Dörfler " doesn't match output.source.id %" B_PRId32 "\n", input.source.id, 1319332cc6bcSAxel Dörfler output.source.id); 132065b73ae4SMarcus Overhagen return B_MEDIA_BAD_SOURCE; 132165b73ae4SMarcus Overhagen } 132265b73ae4SMarcus Overhagen if (input.destination.port != output.destination.port) { 1323332cc6bcSAxel Dörfler printf("BMediaRoster::Disconnect: input.destination.port %" B_PRId32 1324332cc6bcSAxel Dörfler " doesn't match output.destination.port %" B_PRId32 "\n", 1325332cc6bcSAxel Dörfler input.destination.port, output.destination.port); 132665b73ae4SMarcus Overhagen return B_MEDIA_BAD_DESTINATION; 132765b73ae4SMarcus Overhagen } 132865b73ae4SMarcus Overhagen if (input.destination.id != output.destination.id) { 1329332cc6bcSAxel Dörfler printf("BMediaRoster::Disconnect: input.destination.id %" B_PRId32 1330332cc6bcSAxel Dörfler " doesn't match output.destination.id %" B_PRId32 "\n", 1331332cc6bcSAxel Dörfler input.destination.id, output.destination.id); 133265b73ae4SMarcus Overhagen return B_MEDIA_BAD_DESTINATION; 133365b73ae4SMarcus Overhagen } 133434c72144SAxel Dörfler 133534c72144SAxel Dörfler return Disconnect(output.node.node, output.source, input.node.node, 133634c72144SAxel Dörfler input.destination); 133765b73ae4SMarcus Overhagen } 133865b73ae4SMarcus Overhagen 133952a38012Sejakowatz 134052a38012Sejakowatz status_t 134134c72144SAxel Dörfler BMediaRoster::StartNode(const media_node& node, bigtime_t atPerformanceTime) 134252a38012Sejakowatz { 134352a38012Sejakowatz CALLED(); 13449e9417d2Sbeveloper if (node.node <= 0) 134552a38012Sejakowatz return B_MEDIA_BAD_NODE; 134652a38012Sejakowatz 1347332cc6bcSAxel Dörfler TRACE("BMediaRoster::StartNode, node %" B_PRId32 ", at perf %" B_PRId64 1348332cc6bcSAxel Dörfler "\n", node.node, atPerformanceTime); 13490e21b167Sbeveloper 13506396865dSbeveloper node_start_command command; 135134c72144SAxel Dörfler command.performance_time = atPerformanceTime; 135252a38012Sejakowatz 13536396865dSbeveloper return SendToPort(node.port, NODE_START, &command, sizeof(command)); 135452a38012Sejakowatz } 135552a38012Sejakowatz 135652a38012Sejakowatz 135752a38012Sejakowatz status_t 135834c72144SAxel Dörfler BMediaRoster::StopNode(const media_node& node, bigtime_t atPerformanceTime, 135952a38012Sejakowatz bool immediate) 136052a38012Sejakowatz { 136152a38012Sejakowatz CALLED(); 136240f36b03Sbeveloper if (IS_INVALID_NODE(node)) 136352a38012Sejakowatz return B_MEDIA_BAD_NODE; 136452a38012Sejakowatz 1365332cc6bcSAxel Dörfler TRACE("BMediaRoster::StopNode, node %" B_PRId32 ", at perf %" B_PRId64 1366332cc6bcSAxel Dörfler " %s\n", node.node, atPerformanceTime, immediate ? "NOW" : ""); 13670e21b167Sbeveloper 13686396865dSbeveloper node_stop_command command; 136934c72144SAxel Dörfler command.performance_time = atPerformanceTime; 13706396865dSbeveloper command.immediate = immediate; 137152a38012Sejakowatz 13726396865dSbeveloper return SendToPort(node.port, NODE_STOP, &command, sizeof(command)); 137352a38012Sejakowatz } 137452a38012Sejakowatz 137552a38012Sejakowatz 137652a38012Sejakowatz status_t 137734c72144SAxel Dörfler BMediaRoster::SeekNode(const media_node& node, bigtime_t toMediaTime, 137834c72144SAxel Dörfler bigtime_t atPerformanceTime) 137952a38012Sejakowatz { 138052a38012Sejakowatz CALLED(); 138140f36b03Sbeveloper if (IS_INVALID_NODE(node)) 138252a38012Sejakowatz return B_MEDIA_BAD_NODE; 138352a38012Sejakowatz 1384332cc6bcSAxel Dörfler TRACE("BMediaRoster::SeekNode, node %" B_PRId32 ", at perf %" B_PRId64 1385332cc6bcSAxel Dörfler ", to perf %" B_PRId64 "\n", node.node, atPerformanceTime, toMediaTime); 13860e21b167Sbeveloper 13876396865dSbeveloper node_seek_command command; 138834c72144SAxel Dörfler command.media_time = toMediaTime; 138934c72144SAxel Dörfler command.performance_time = atPerformanceTime; 139052a38012Sejakowatz 13916396865dSbeveloper return SendToPort(node.port, NODE_SEEK, &command, sizeof(command)); 139252a38012Sejakowatz } 139352a38012Sejakowatz 139452a38012Sejakowatz 139552a38012Sejakowatz status_t 139634c72144SAxel Dörfler BMediaRoster::StartTimeSource(const media_node& node, bigtime_t atRealTime) 139752a38012Sejakowatz { 139852a38012Sejakowatz CALLED(); 139960f15390Sbeveloper if (IS_SYSTEM_TIMESOURCE(node)) { 140034c72144SAxel Dörfler // TODO: debug this 1401332cc6bcSAxel Dörfler //ERROR("BMediaRoster::StartTimeSource node %" B_PRId32 " is system timesource\n", node.node); 140260f15390Sbeveloper return B_OK; 140360f15390Sbeveloper } 140492e575c1Sbeveloper // if (IS_SHADOW_TIMESOURCE(node)) { 140534c72144SAxel Dörfler // // TODO: debug this 1406332cc6bcSAxel Dörfler // ERROR("BMediaRoster::StartTimeSource node %" B_PRId32 " is shadow timesource\n", node.node); 140792e575c1Sbeveloper // return B_OK; 140892e575c1Sbeveloper // } 140940f36b03Sbeveloper if (IS_INVALID_NODE(node)) { 1410332cc6bcSAxel Dörfler ERROR("BMediaRoster::StartTimeSource node %" B_PRId32 " invalid\n", 141134c72144SAxel Dörfler node.node); 141252a38012Sejakowatz return B_MEDIA_BAD_NODE; 14130e21b167Sbeveloper } 1414332cc6bcSAxel Dörfler if ((node.kind & B_TIME_SOURCE) == 0) { 1415332cc6bcSAxel Dörfler ERROR("BMediaRoster::StartTimeSource node %" B_PRId32 1416332cc6bcSAxel Dörfler " is no timesource\n", node.node); 1417332cc6bcSAxel Dörfler return B_MEDIA_BAD_NODE; 1418332cc6bcSAxel Dörfler } 14190e21b167Sbeveloper 1420332cc6bcSAxel Dörfler TRACE("BMediaRoster::StartTimeSource, node %" B_PRId32 ", at real %" 1421332cc6bcSAxel Dörfler B_PRId64 "\n", node.node, atRealTime); 142252a38012Sejakowatz 142352a38012Sejakowatz BTimeSource::time_source_op_info msg; 142452a38012Sejakowatz msg.op = BTimeSource::B_TIMESOURCE_START; 142534c72144SAxel Dörfler msg.real_time = atRealTime; 142652a38012Sejakowatz 142752a38012Sejakowatz return write_port(node.port, TIMESOURCE_OP, &msg, sizeof(msg)); 142852a38012Sejakowatz } 142952a38012Sejakowatz 143052a38012Sejakowatz 143152a38012Sejakowatz status_t 143234c72144SAxel Dörfler BMediaRoster::StopTimeSource(const media_node& node, bigtime_t atRealTime, 143352a38012Sejakowatz bool immediate) 143452a38012Sejakowatz { 143552a38012Sejakowatz CALLED(); 143660f15390Sbeveloper if (IS_SYSTEM_TIMESOURCE(node)) { 143734c72144SAxel Dörfler // TODO: debug this 14385ac4fbd7Sbeveloper //ERROR("BMediaRoster::StopTimeSource node %ld is system timesource\n", node.node); 143960f15390Sbeveloper return B_OK; 144060f15390Sbeveloper } 144192e575c1Sbeveloper // if (IS_SHADOW_TIMESOURCE(node)) { 144234c72144SAxel Dörfler // // TODO: debug this 144392e575c1Sbeveloper // ERROR("BMediaRoster::StopTimeSource node %ld is shadow timesource\n", node.node); 144492e575c1Sbeveloper // return B_OK; 144592e575c1Sbeveloper // } 144640f36b03Sbeveloper if (IS_INVALID_NODE(node)) { 1447332cc6bcSAxel Dörfler ERROR("BMediaRoster::StopTimeSource node %" B_PRId32 " invalid\n", 144834c72144SAxel Dörfler node.node); 144952a38012Sejakowatz return B_MEDIA_BAD_NODE; 14500e21b167Sbeveloper } 1451332cc6bcSAxel Dörfler if ((node.kind & B_TIME_SOURCE) == 0) { 1452332cc6bcSAxel Dörfler ERROR("BMediaRoster::StopTimeSource node %" B_PRId32 " is no " 1453332cc6bcSAxel Dörfler "timesource\n", node.node); 1454332cc6bcSAxel Dörfler return B_MEDIA_BAD_NODE; 1455332cc6bcSAxel Dörfler } 14560e21b167Sbeveloper 1457332cc6bcSAxel Dörfler TRACE("BMediaRoster::StopTimeSource, node %" B_PRId32 ", at real %" B_PRId64 1458332cc6bcSAxel Dörfler " %s\n", node.node, atRealTime, immediate ? "NOW" : ""); 145952a38012Sejakowatz 146052a38012Sejakowatz BTimeSource::time_source_op_info msg; 146134c72144SAxel Dörfler msg.op = immediate ? BTimeSource::B_TIMESOURCE_STOP_IMMEDIATELY 146234c72144SAxel Dörfler : BTimeSource::B_TIMESOURCE_STOP; 146334c72144SAxel Dörfler msg.real_time = atRealTime; 146452a38012Sejakowatz 146552a38012Sejakowatz return write_port(node.port, TIMESOURCE_OP, &msg, sizeof(msg)); 146652a38012Sejakowatz } 146752a38012Sejakowatz 146852a38012Sejakowatz 146952a38012Sejakowatz status_t 147052a38012Sejakowatz BMediaRoster::SeekTimeSource(const media_node& node, 147134c72144SAxel Dörfler bigtime_t toPerformanceTime, bigtime_t atRealTime) 147252a38012Sejakowatz { 147352a38012Sejakowatz CALLED(); 147460f15390Sbeveloper if (IS_SYSTEM_TIMESOURCE(node)) { 147534c72144SAxel Dörfler // TODO: debug this 14765ac4fbd7Sbeveloper // ERROR("BMediaRoster::SeekTimeSource node %ld is system timesource\n", node.node); 147760f15390Sbeveloper // you can't seek the system time source, but 147860f15390Sbeveloper // returning B_ERROR would break StampTV 147960f15390Sbeveloper return B_OK; 148060f15390Sbeveloper } 148192e575c1Sbeveloper // if (IS_SHADOW_TIMESOURCE(node)) { 148234c72144SAxel Dörfler // // TODO: debug this 148392e575c1Sbeveloper // ERROR("BMediaRoster::SeekTimeSource node %ld is shadow timesource\n", node.node); 148492e575c1Sbeveloper // return B_OK; 148592e575c1Sbeveloper // } 148640f36b03Sbeveloper if (IS_INVALID_NODE(node)) { 1487332cc6bcSAxel Dörfler ERROR("BMediaRoster::SeekTimeSource node %" B_PRId32 " invalid\n", 148834c72144SAxel Dörfler node.node); 148952a38012Sejakowatz return B_MEDIA_BAD_NODE; 14900e21b167Sbeveloper } 1491332cc6bcSAxel Dörfler if ((node.kind & B_TIME_SOURCE) == 0) { 1492332cc6bcSAxel Dörfler ERROR("BMediaRoster::SeekTimeSource node %" B_PRId32 1493332cc6bcSAxel Dörfler " is no timesource\n", node.node); 1494332cc6bcSAxel Dörfler return B_MEDIA_BAD_NODE; 1495332cc6bcSAxel Dörfler } 14960e21b167Sbeveloper 1497332cc6bcSAxel Dörfler TRACE("BMediaRoster::SeekTimeSource, node %" B_PRId32 ", at real %" B_PRId64 1498332cc6bcSAxel Dörfler ", to perf %" B_PRId64 "\n", node.node, atRealTime, toPerformanceTime); 149952a38012Sejakowatz 150052a38012Sejakowatz BTimeSource::time_source_op_info msg; 150152a38012Sejakowatz msg.op = BTimeSource::B_TIMESOURCE_SEEK; 150234c72144SAxel Dörfler msg.real_time = atRealTime; 150334c72144SAxel Dörfler msg.performance_time = toPerformanceTime; 150452a38012Sejakowatz 150552a38012Sejakowatz return write_port(node.port, TIMESOURCE_OP, &msg, sizeof(msg)); 150652a38012Sejakowatz } 150752a38012Sejakowatz 150852a38012Sejakowatz 150952a38012Sejakowatz status_t 151034c72144SAxel Dörfler BMediaRoster::SyncToNode(const media_node& node, bigtime_t atTime, 151152a38012Sejakowatz bigtime_t timeout) 151252a38012Sejakowatz { 151375486484SDario Casalinuovo TRACE("BMediaRoster::SyncToNode, node %" B_PRId32 ", at real %" B_PRId64 151475486484SDario Casalinuovo ", at timeout %" B_PRId64 "\n", node.node, atTime, timeout); 151575486484SDario Casalinuovo if (IS_INVALID_NODE(node)) 151675486484SDario Casalinuovo return B_MEDIA_BAD_NODE; 151775486484SDario Casalinuovo 151875486484SDario Casalinuovo port_id waitPort = create_port(1, "SyncToNode wait port"); 151975486484SDario Casalinuovo if (waitPort < B_OK) 152075486484SDario Casalinuovo return waitPort; 152175486484SDario Casalinuovo 152275486484SDario Casalinuovo node_sync_to_request request; 152375486484SDario Casalinuovo node_sync_to_reply reply; 152475486484SDario Casalinuovo request.performance_time = atTime; 152575486484SDario Casalinuovo request.port = waitPort; 152675486484SDario Casalinuovo 152775486484SDario Casalinuovo status_t status = QueryPort(node.port, NODE_SYNC_TO, &request, 152875486484SDario Casalinuovo sizeof(request), &reply, sizeof(reply)); 152975486484SDario Casalinuovo 153075486484SDario Casalinuovo if (status == B_OK) { 153175486484SDario Casalinuovo ssize_t readSize = read_port_etc(waitPort, NULL, &status, 153275486484SDario Casalinuovo sizeof(status), B_TIMEOUT, timeout); 153375486484SDario Casalinuovo if (readSize < 0) 153475486484SDario Casalinuovo status = readSize; 153575486484SDario Casalinuovo } 153675486484SDario Casalinuovo close_port(waitPort); 153775486484SDario Casalinuovo delete_port(waitPort); 153875486484SDario Casalinuovo return status; 153952a38012Sejakowatz } 154052a38012Sejakowatz 154152a38012Sejakowatz 154252a38012Sejakowatz status_t 154334c72144SAxel Dörfler BMediaRoster::SetRunModeNode(const media_node& node, BMediaNode::run_mode mode) 154452a38012Sejakowatz { 1545332cc6bcSAxel Dörfler TRACE("BMediaRoster::SetRunModeNode, node %" B_PRId32 ", mode %d\n", 1546332cc6bcSAxel Dörfler node.node, mode); 154740f36b03Sbeveloper if (IS_INVALID_NODE(node)) 154852a38012Sejakowatz return B_MEDIA_BAD_NODE; 154952a38012Sejakowatz 1550dfb2ad61Sbeveloper node_set_run_mode_command msg; 155152a38012Sejakowatz msg.mode = mode; 155252a38012Sejakowatz 155352a38012Sejakowatz return write_port(node.port, NODE_SET_RUN_MODE, &msg, sizeof(msg)); 155452a38012Sejakowatz } 155552a38012Sejakowatz 155652a38012Sejakowatz 155752a38012Sejakowatz status_t 155852a38012Sejakowatz BMediaRoster::PrerollNode(const media_node& node) 155952a38012Sejakowatz { 156052a38012Sejakowatz CALLED(); 156140f36b03Sbeveloper if (IS_INVALID_NODE(node)) 156252a38012Sejakowatz return B_MEDIA_BAD_NODE; 156352a38012Sejakowatz 156452a38012Sejakowatz char dummy; 156552a38012Sejakowatz return write_port(node.port, NODE_PREROLL, &dummy, sizeof(dummy)); 156652a38012Sejakowatz } 156752a38012Sejakowatz 156852a38012Sejakowatz 156952a38012Sejakowatz status_t 157034c72144SAxel Dörfler BMediaRoster::RollNode(const media_node& node, bigtime_t startPerformance, 157134c72144SAxel Dörfler bigtime_t stopPerformance, bigtime_t atMediaTime) 157252a38012Sejakowatz { 157314896b93SDario Casalinuovo CALLED(); 157414896b93SDario Casalinuovo if (IS_INVALID_NODE(node)) 157514896b93SDario Casalinuovo return B_MEDIA_BAD_NODE; 157614896b93SDario Casalinuovo 157714896b93SDario Casalinuovo TRACE("BMediaRoster::RollNode, node %" B_PRId32 ", at start perf %" 157814896b93SDario Casalinuovo B_PRId64 ", at stop perf %" B_PRId64 ", at media time %" 157914896b93SDario Casalinuovo B_PRId64 "\n", node.node, startPerformance, 158014896b93SDario Casalinuovo stopPerformance, atMediaTime); 158114896b93SDario Casalinuovo 158214896b93SDario Casalinuovo node_roll_command command; 158314896b93SDario Casalinuovo command.start_performance_time = startPerformance; 158414896b93SDario Casalinuovo command.stop_performance_time = stopPerformance; 158514896b93SDario Casalinuovo command.seek_media_time = atMediaTime; 158614896b93SDario Casalinuovo 158714896b93SDario Casalinuovo return write_port(node.port, NODE_ROLL, &command, sizeof(command)); 158852a38012Sejakowatz } 158952a38012Sejakowatz 159052a38012Sejakowatz 159152a38012Sejakowatz status_t 159252a38012Sejakowatz BMediaRoster::SetProducerRunModeDelay(const media_node& node, 159334c72144SAxel Dörfler bigtime_t delay, BMediaNode::run_mode mode) 159452a38012Sejakowatz { 1595332cc6bcSAxel Dörfler TRACE("BMediaRoster::SetProducerRunModeDelay, node %" B_PRId32 ", delay %" 1596332cc6bcSAxel Dörfler B_PRId64 ", mode %d\n", node.node, delay, mode); 159760f15390Sbeveloper if (IS_INVALID_NODE(node)) 159860f15390Sbeveloper return B_MEDIA_BAD_NODE; 159960f15390Sbeveloper if ((node.kind & B_BUFFER_PRODUCER) == 0) 160060f15390Sbeveloper return B_MEDIA_BAD_NODE; 160160f15390Sbeveloper 160260f15390Sbeveloper producer_set_run_mode_delay_command command; 160360f15390Sbeveloper command.mode = mode; 160460f15390Sbeveloper command.delay = delay; 160560f15390Sbeveloper 160634c72144SAxel Dörfler return SendToPort(node.port, PRODUCER_SET_RUN_MODE_DELAY, &command, 160734c72144SAxel Dörfler sizeof(command)); 160852a38012Sejakowatz } 160952a38012Sejakowatz 161052a38012Sejakowatz 161152a38012Sejakowatz status_t 161234c72144SAxel Dörfler BMediaRoster::SetProducerRate(const media_node& producer, int32 numer, 161352a38012Sejakowatz int32 denom) 161452a38012Sejakowatz { 161552a38012Sejakowatz CALLED(); 161640f36b03Sbeveloper if (IS_INVALID_NODE(producer)) 161752a38012Sejakowatz return B_MEDIA_BAD_NODE; 161852a38012Sejakowatz if ((producer.kind & B_BUFFER_PRODUCER) == 0) 161952a38012Sejakowatz return B_MEDIA_BAD_NODE; 162052a38012Sejakowatz 16216cafce94SAxel Dörfler producer_set_play_rate_request request; 16226cafce94SAxel Dörfler request.numer = numer; 16236cafce94SAxel Dörfler request.denom = denom; 16246cafce94SAxel Dörfler status_t status = write_port(producer.node, PRODUCER_SET_PLAY_RATE, 16256cafce94SAxel Dörfler &request, sizeof(request)); 16266cafce94SAxel Dörfler if (status != B_OK) 16276cafce94SAxel Dörfler return status; 162852a38012Sejakowatz 16296cafce94SAxel Dörfler producer_set_play_rate_reply reply; 16306cafce94SAxel Dörfler int32 code; 16316cafce94SAxel Dörfler status = read_port(request.reply_port, &code, &reply, sizeof(reply)); 16326cafce94SAxel Dörfler 16336cafce94SAxel Dörfler return status < B_OK ? status : reply.result; 163452a38012Sejakowatz } 163552a38012Sejakowatz 163652a38012Sejakowatz 163734c72144SAxel Dörfler /*! Nodes will have available inputs/outputs as long as they are capable 163834c72144SAxel Dörfler of accepting more connections. The node may create an additional 163934c72144SAxel Dörfler output or input as the currently available is taken into usage. 164034c72144SAxel Dörfler */ 164152a38012Sejakowatz status_t 164252a38012Sejakowatz BMediaRoster::GetLiveNodeInfo(const media_node& node, 164352a38012Sejakowatz live_node_info* out_live_info) 164452a38012Sejakowatz { 16459e9417d2Sbeveloper CALLED(); 16469e9417d2Sbeveloper if (out_live_info == NULL) 16479e9417d2Sbeveloper return B_BAD_VALUE; 164840f36b03Sbeveloper if (IS_INVALID_NODE(node)) 16499e9417d2Sbeveloper return B_MEDIA_BAD_NODE; 16509e9417d2Sbeveloper 16519e9417d2Sbeveloper server_get_live_node_info_request request; 16529e9417d2Sbeveloper server_get_live_node_info_reply reply; 16539e9417d2Sbeveloper status_t rv; 16549e9417d2Sbeveloper 16559e9417d2Sbeveloper request.node = node; 16569e9417d2Sbeveloper 165734c72144SAxel Dörfler rv = QueryServer(SERVER_GET_LIVE_NODE_INFO, &request, sizeof(request), 165834c72144SAxel Dörfler &reply, sizeof(reply)); 16599e9417d2Sbeveloper if (rv != B_OK) 16609e9417d2Sbeveloper return rv; 16619e9417d2Sbeveloper 16629e9417d2Sbeveloper *out_live_info = reply.live_info; 16639e9417d2Sbeveloper return B_OK; 166452a38012Sejakowatz } 166552a38012Sejakowatz 166652a38012Sejakowatz 166752a38012Sejakowatz status_t 16689c3b4706SAxel Dörfler BMediaRoster::GetLiveNodes(live_node_info* liveNodes, int32* _totalCount, 166934c72144SAxel Dörfler const media_format* hasInput, const media_format* hasOutput, 167034c72144SAxel Dörfler const char* name, uint64 nodeKinds) 167152a38012Sejakowatz { 16729e9417d2Sbeveloper CALLED(); 16739c3b4706SAxel Dörfler if (liveNodes == NULL || _totalCount == NULL || *_totalCount <= 0) 16749e9417d2Sbeveloper return B_BAD_VALUE; 16759e9417d2Sbeveloper 167634c72144SAxel Dörfler // TODO: we also support the wildcard search as GetDormantNodes does. 167734c72144SAxel Dörfler // This needs to be documented 16789e9417d2Sbeveloper 16799e9417d2Sbeveloper server_get_live_nodes_request request; 16809c3b4706SAxel Dörfler request.team = BPrivate::current_team(); 16819e9417d2Sbeveloper 16829c3b4706SAxel Dörfler request.max_count = *_totalCount; 168334c72144SAxel Dörfler request.has_input = hasInput != NULL; 168434c72144SAxel Dörfler if (hasInput != NULL) { 168534c72144SAxel Dörfler // TODO: we should not make a flat copy of media_format 16869c3b4706SAxel Dörfler request.input_format = *hasInput; 168734c72144SAxel Dörfler } 168834c72144SAxel Dörfler request.has_output = hasOutput != NULL; 168934c72144SAxel Dörfler if (hasOutput != NULL) { 169034c72144SAxel Dörfler // TODO: we should not make a flat copy of media_format 16919c3b4706SAxel Dörfler request.output_format = *hasOutput; 169234c72144SAxel Dörfler } 169334c72144SAxel Dörfler request.has_name = name != NULL; 16949c3b4706SAxel Dörfler if (name != NULL) 16959c3b4706SAxel Dörfler strlcpy(request.name, name, sizeof(request.name)); 169634c72144SAxel Dörfler request.require_kinds = nodeKinds; 16979e9417d2Sbeveloper 16989c3b4706SAxel Dörfler server_get_live_nodes_reply reply; 16999c3b4706SAxel Dörfler status_t status = QueryServer(SERVER_GET_LIVE_NODES, &request, 17009c3b4706SAxel Dörfler sizeof(request), &reply, sizeof(reply)); 17019c3b4706SAxel Dörfler if (status != B_OK) { 17029c3b4706SAxel Dörfler ERROR("BMediaRoster::GetLiveNodes failed querying server: %s\n", 17039c3b4706SAxel Dörfler strerror(status)); 170434c72144SAxel Dörfler *_totalCount = 0; 17059c3b4706SAxel Dörfler return status; 17069e9417d2Sbeveloper } 17079e9417d2Sbeveloper 17089c3b4706SAxel Dörfler const live_node_info* info; 17099c3b4706SAxel Dörfler if (reply.area >= 0) 17109c3b4706SAxel Dörfler info = (live_node_info*)reply.address; 17119c3b4706SAxel Dörfler else 17129c3b4706SAxel Dörfler info = reply.live_info; 17139e9417d2Sbeveloper 17149c3b4706SAxel Dörfler for (int32 i = 0; i < reply.count; i++) 17159c3b4706SAxel Dörfler liveNodes[i] = info[i]; 17169c3b4706SAxel Dörfler 17179c3b4706SAxel Dörfler if (reply.area >= 0) 17189e9417d2Sbeveloper delete_area(reply.area); 171952a38012Sejakowatz 172034c72144SAxel Dörfler *_totalCount = reply.count; 17219e9417d2Sbeveloper return B_OK; 17229e9417d2Sbeveloper } 17239e9417d2Sbeveloper 172452a38012Sejakowatz 172552a38012Sejakowatz status_t 172652a38012Sejakowatz BMediaRoster::GetFreeInputsFor(const media_node& node, 172734c72144SAxel Dörfler media_input * out_free_inputs, int32 buf_num_inputs, 172834c72144SAxel Dörfler int32 * out_total_count, media_type filter_type) 172952a38012Sejakowatz { 17303620737cSbeveloper CALLED(); 17315ac4fbd7Sbeveloper if (IS_INVALID_NODE(node)) { 1732332cc6bcSAxel Dörfler ERROR("BMediaRoster::GetFreeInputsFor: node %" B_PRId32 ", port %" 1733332cc6bcSAxel Dörfler B_PRId32 " invalid\n", node.node, node.port); 17343620737cSbeveloper return B_MEDIA_BAD_NODE; 17355ac4fbd7Sbeveloper } 17365ac4fbd7Sbeveloper if ((node.kind & B_BUFFER_CONSUMER) == 0) { 1737332cc6bcSAxel Dörfler ERROR("BMediaRoster::GetFreeInputsFor: node %" B_PRId32 ", port %" 1738332cc6bcSAxel Dörfler B_PRId32 " is not a consumer\n", node.node, node.port); 17395ac4fbd7Sbeveloper return B_MEDIA_BAD_NODE; 17405ac4fbd7Sbeveloper } 17413620737cSbeveloper if (out_free_inputs == NULL || out_total_count == NULL) 17423620737cSbeveloper return B_BAD_VALUE; 17433620737cSbeveloper 174476669a29Sbeveloper List<media_input> list; 17453620737cSbeveloper media_input *input; 17463620737cSbeveloper status_t rv; 17473620737cSbeveloper 17481299bfb2Sbeveloper *out_total_count = 0; 17491299bfb2Sbeveloper 17508b04ffc1Sbeveloper rv = MediaRosterEx(this)->GetAllInputs(node, &list); 17513620737cSbeveloper if (B_OK != rv) 17523620737cSbeveloper return rv; 17533620737cSbeveloper 1754332cc6bcSAxel Dörfler PRINT(4, "BMediaRoster::GetFreeInputsFor node %" B_PRId32 ", max %" B_PRId32 1755332cc6bcSAxel Dörfler ", filter-type %" B_PRId32 "\n", node.node, buf_num_inputs, 1756332cc6bcSAxel Dörfler filter_type); 17575ac4fbd7Sbeveloper 175876669a29Sbeveloper int32 i; 1759b65a0ac5SJérôme Duval for (i = 0, list.Rewind(); list.GetNext(&input);) { 176034c72144SAxel Dörfler if (filter_type != B_MEDIA_UNKNOWN_TYPE 176134c72144SAxel Dörfler && filter_type != input->format.type) { 176234c72144SAxel Dörfler // media_type used, but doesn't match 176334c72144SAxel Dörfler continue; 176434c72144SAxel Dörfler } 176534c72144SAxel Dörfler if (input->source != media_source::null) { 176634c72144SAxel Dörfler // consumer source already connected 176734c72144SAxel Dörfler continue; 176834c72144SAxel Dörfler } 176934c72144SAxel Dörfler 17703620737cSbeveloper out_free_inputs[i] = *input; 17713620737cSbeveloper *out_total_count += 1; 17723620737cSbeveloper buf_num_inputs -= 1; 17735ac4fbd7Sbeveloper #if DEBUG >= 3 17745ac4fbd7Sbeveloper PRINT_OUTPUT(" input", out_free_inputs[i]); 17755ac4fbd7Sbeveloper #endif 17763620737cSbeveloper if (buf_num_inputs == 0) 17773620737cSbeveloper break; 1778b65a0ac5SJérôme Duval i++; 17793620737cSbeveloper } 17803620737cSbeveloper 17818b04ffc1Sbeveloper MediaRosterEx(this)->PublishInputs(node, &list); 17823620737cSbeveloper return B_OK; 178352a38012Sejakowatz } 178452a38012Sejakowatz 178552a38012Sejakowatz 178652a38012Sejakowatz status_t 178752a38012Sejakowatz BMediaRoster::GetConnectedInputsFor(const media_node& node, 178834c72144SAxel Dörfler media_input* out_active_inputs, int32 buf_num_inputs, 178952a38012Sejakowatz int32* out_total_count) 179052a38012Sejakowatz { 17913620737cSbeveloper CALLED(); 179240f36b03Sbeveloper if (IS_INVALID_NODE(node) || (node.kind & B_BUFFER_CONSUMER) == 0) 17933620737cSbeveloper return B_MEDIA_BAD_NODE; 17943620737cSbeveloper if (out_active_inputs == NULL || out_total_count == NULL) 17953620737cSbeveloper return B_BAD_VALUE; 17963620737cSbeveloper 179776669a29Sbeveloper List<media_input> list; 17983620737cSbeveloper media_input *input; 17993620737cSbeveloper status_t rv; 18003620737cSbeveloper 18011299bfb2Sbeveloper *out_total_count = 0; 18021299bfb2Sbeveloper 18038b04ffc1Sbeveloper rv = MediaRosterEx(this)->GetAllInputs(node, &list); 18043620737cSbeveloper if (B_OK != rv) 18053620737cSbeveloper return rv; 18063620737cSbeveloper 1807332cc6bcSAxel Dörfler PRINT(4, "BMediaRoster::GetConnectedInputsFor node %" B_PRId32 ", max %" 1808332cc6bcSAxel Dörfler B_PRId32 "\n", node.node, buf_num_inputs); 18095ac4fbd7Sbeveloper 181076669a29Sbeveloper int32 i; 1811b65a0ac5SJérôme Duval for (i = 0, list.Rewind(); list.GetNext(&input);) { 18123620737cSbeveloper if (input->source == media_source::null) 18133620737cSbeveloper continue; // consumer source not connected 18143620737cSbeveloper out_active_inputs[i] = *input; 18153620737cSbeveloper *out_total_count += 1; 18163620737cSbeveloper buf_num_inputs -= 1; 18175ac4fbd7Sbeveloper #if DEBUG >= 3 18185ac4fbd7Sbeveloper PRINT_OUTPUT(" input ", out_active_inputs[i]); 18195ac4fbd7Sbeveloper #endif 18203620737cSbeveloper if (buf_num_inputs == 0) 18213620737cSbeveloper break; 1822b65a0ac5SJérôme Duval i++; 18233620737cSbeveloper } 18243620737cSbeveloper 18258b04ffc1Sbeveloper MediaRosterEx(this)->PublishInputs(node, &list); 18263620737cSbeveloper return B_OK; 182752a38012Sejakowatz } 182852a38012Sejakowatz 182952a38012Sejakowatz 183052a38012Sejakowatz status_t 183134c72144SAxel Dörfler BMediaRoster::GetAllInputsFor(const media_node& node, media_input* out_inputs, 183234c72144SAxel Dörfler int32 buf_num_inputs, int32* out_total_count) 183352a38012Sejakowatz { 183452a38012Sejakowatz CALLED(); 183540f36b03Sbeveloper if (IS_INVALID_NODE(node) || (node.kind & B_BUFFER_CONSUMER) == 0) 183652a38012Sejakowatz return B_MEDIA_BAD_NODE; 183752a38012Sejakowatz if (out_inputs == NULL || out_total_count == NULL) 183852a38012Sejakowatz return B_BAD_VALUE; 183952a38012Sejakowatz 184076669a29Sbeveloper List<media_input> list; 18413620737cSbeveloper media_input *input; 184252a38012Sejakowatz status_t rv; 184352a38012Sejakowatz 18441299bfb2Sbeveloper *out_total_count = 0; 18451299bfb2Sbeveloper 18468b04ffc1Sbeveloper rv = MediaRosterEx(this)->GetAllInputs(node, &list); 18473620737cSbeveloper if (B_OK != rv) 18483620737cSbeveloper return rv; 18493620737cSbeveloper 1850332cc6bcSAxel Dörfler PRINT(4, "BMediaRoster::GetAllInputsFor node %" B_PRId32 ", max %" B_PRId32 1851332cc6bcSAxel Dörfler "\n", node.node, buf_num_inputs); 18525ac4fbd7Sbeveloper 185376669a29Sbeveloper int32 i; 185476669a29Sbeveloper for (i = 0, list.Rewind(); list.GetNext(&input); i++) { 18553620737cSbeveloper out_inputs[i] = *input; 185652a38012Sejakowatz *out_total_count += 1; 18573620737cSbeveloper buf_num_inputs -= 1; 18585ac4fbd7Sbeveloper #if DEBUG >= 3 18595ac4fbd7Sbeveloper PRINT_OUTPUT(" input ", out_inputs[i]); 18605ac4fbd7Sbeveloper #endif 18613620737cSbeveloper if (buf_num_inputs == 0) 18623620737cSbeveloper break; 186352a38012Sejakowatz } 186452a38012Sejakowatz 18658b04ffc1Sbeveloper MediaRosterEx(this)->PublishInputs(node, &list); 18663620737cSbeveloper return B_OK; 186752a38012Sejakowatz } 186852a38012Sejakowatz 186952a38012Sejakowatz 187052a38012Sejakowatz status_t 187152a38012Sejakowatz BMediaRoster::GetFreeOutputsFor(const media_node& node, 187234c72144SAxel Dörfler media_output* out_free_outputs, int32 buf_num_outputs, 187334c72144SAxel Dörfler int32* out_total_count, media_type filter_type) 187452a38012Sejakowatz { 18753620737cSbeveloper CALLED(); 187640f36b03Sbeveloper if (IS_INVALID_NODE(node) || (node.kind & B_BUFFER_PRODUCER) == 0) 18773620737cSbeveloper return B_MEDIA_BAD_NODE; 18783620737cSbeveloper if (out_free_outputs == NULL || out_total_count == NULL) 18793620737cSbeveloper return B_BAD_VALUE; 18803620737cSbeveloper 188176669a29Sbeveloper List<media_output> list; 18823620737cSbeveloper media_output *output; 18833620737cSbeveloper status_t rv; 18843620737cSbeveloper 18851299bfb2Sbeveloper *out_total_count = 0; 18861299bfb2Sbeveloper 18878b04ffc1Sbeveloper rv = MediaRosterEx(this)->GetAllOutputs(node, &list); 18883620737cSbeveloper if (B_OK != rv) 18893620737cSbeveloper return rv; 18903620737cSbeveloper 1891332cc6bcSAxel Dörfler PRINT(4, "BMediaRoster::GetFreeOutputsFor node %" B_PRId32 ", max %" 1892332cc6bcSAxel Dörfler B_PRId32 ", filter-type %" B_PRId32 "\n", node.node, buf_num_outputs, 1893332cc6bcSAxel Dörfler filter_type); 18945ac4fbd7Sbeveloper 189576669a29Sbeveloper int32 i; 1896b65a0ac5SJérôme Duval for (i = 0, list.Rewind(); list.GetNext(&output);) { 189734c72144SAxel Dörfler if (filter_type != B_MEDIA_UNKNOWN_TYPE 189834c72144SAxel Dörfler && filter_type != output->format.type) { 189934c72144SAxel Dörfler // media_type used, but doesn't match 190034c72144SAxel Dörfler continue; 190134c72144SAxel Dörfler } 190234c72144SAxel Dörfler if (output->destination != media_destination::null) { 190334c72144SAxel Dörfler // producer destination already connected 190434c72144SAxel Dörfler continue; 190534c72144SAxel Dörfler } 190634c72144SAxel Dörfler 19073620737cSbeveloper out_free_outputs[i] = *output; 19083620737cSbeveloper *out_total_count += 1; 19093620737cSbeveloper buf_num_outputs -= 1; 19105ac4fbd7Sbeveloper #if DEBUG >= 3 19115ac4fbd7Sbeveloper PRINT_OUTPUT(" output ", out_free_outputs[i]); 19125ac4fbd7Sbeveloper #endif 19133620737cSbeveloper if (buf_num_outputs == 0) 19143620737cSbeveloper break; 1915b65a0ac5SJérôme Duval i++; 19163620737cSbeveloper } 19173620737cSbeveloper 19188b04ffc1Sbeveloper MediaRosterEx(this)->PublishOutputs(node, &list); 19193620737cSbeveloper return B_OK; 192052a38012Sejakowatz } 192152a38012Sejakowatz 192252a38012Sejakowatz 192352a38012Sejakowatz status_t 192452a38012Sejakowatz BMediaRoster::GetConnectedOutputsFor(const media_node& node, 192534c72144SAxel Dörfler media_output* out_active_outputs, int32 buf_num_outputs, 192652a38012Sejakowatz int32* out_total_count) 192752a38012Sejakowatz { 19283620737cSbeveloper CALLED(); 192940f36b03Sbeveloper if (IS_INVALID_NODE(node) || (node.kind & B_BUFFER_PRODUCER) == 0) 19303620737cSbeveloper return B_MEDIA_BAD_NODE; 19313620737cSbeveloper if (out_active_outputs == NULL || out_total_count == NULL) 19323620737cSbeveloper return B_BAD_VALUE; 19333620737cSbeveloper 193476669a29Sbeveloper List<media_output> list; 19353620737cSbeveloper media_output *output; 19363620737cSbeveloper status_t rv; 19373620737cSbeveloper 19381299bfb2Sbeveloper *out_total_count = 0; 19391299bfb2Sbeveloper 19408b04ffc1Sbeveloper rv = MediaRosterEx(this)->GetAllOutputs(node, &list); 19413620737cSbeveloper if (B_OK != rv) 19423620737cSbeveloper return rv; 19433620737cSbeveloper 1944332cc6bcSAxel Dörfler PRINT(4, "BMediaRoster::GetConnectedOutputsFor node %" B_PRId32 ", max %" 1945332cc6bcSAxel Dörfler B_PRId32 "\n", node.node, buf_num_outputs); 19465ac4fbd7Sbeveloper 194776669a29Sbeveloper int32 i; 1948b65a0ac5SJérôme Duval for (i = 0, list.Rewind(); list.GetNext(&output);) { 194934c72144SAxel Dörfler if (output->destination == media_destination::null) { 195034c72144SAxel Dörfler // producer destination not connected 195134c72144SAxel Dörfler continue; 195234c72144SAxel Dörfler } 19533620737cSbeveloper out_active_outputs[i] = *output; 19543620737cSbeveloper *out_total_count += 1; 19553620737cSbeveloper buf_num_outputs -= 1; 19565ac4fbd7Sbeveloper #if DEBUG >= 3 19575ac4fbd7Sbeveloper PRINT_OUTPUT(" output ", out_active_outputs[i]); 19585ac4fbd7Sbeveloper #endif 19593620737cSbeveloper if (buf_num_outputs == 0) 19603620737cSbeveloper break; 1961b65a0ac5SJérôme Duval i++; 19623620737cSbeveloper } 19633620737cSbeveloper 19648b04ffc1Sbeveloper MediaRosterEx(this)->PublishOutputs(node, &list); 19653620737cSbeveloper return B_OK; 196652a38012Sejakowatz } 196752a38012Sejakowatz 196852a38012Sejakowatz 196952a38012Sejakowatz status_t 197052a38012Sejakowatz BMediaRoster::GetAllOutputsFor(const media_node& node, 197134c72144SAxel Dörfler media_output* out_outputs, int32 buf_num_outputs, int32* out_total_count) 197252a38012Sejakowatz { 197352a38012Sejakowatz CALLED(); 197440f36b03Sbeveloper if (IS_INVALID_NODE(node) || (node.kind & B_BUFFER_PRODUCER) == 0) 197552a38012Sejakowatz return B_MEDIA_BAD_NODE; 197652a38012Sejakowatz if (out_outputs == NULL || out_total_count == NULL) 197752a38012Sejakowatz return B_BAD_VALUE; 197852a38012Sejakowatz 197976669a29Sbeveloper List<media_output> list; 19803620737cSbeveloper media_output *output; 198152a38012Sejakowatz status_t rv; 198252a38012Sejakowatz 19831299bfb2Sbeveloper *out_total_count = 0; 19841299bfb2Sbeveloper 19858b04ffc1Sbeveloper rv = MediaRosterEx(this)->GetAllOutputs(node, &list); 19863620737cSbeveloper if (B_OK != rv) 19873620737cSbeveloper return rv; 19883620737cSbeveloper 1989332cc6bcSAxel Dörfler PRINT(4, "BMediaRoster::GetAllOutputsFor node %" B_PRId32 ", max %" B_PRId32 1990332cc6bcSAxel Dörfler "\n", node.node, buf_num_outputs); 19915ac4fbd7Sbeveloper 199276669a29Sbeveloper int32 i; 199376669a29Sbeveloper for (i = 0, list.Rewind(); list.GetNext(&output); i++) { 19943620737cSbeveloper out_outputs[i] = *output; 199552a38012Sejakowatz *out_total_count += 1; 19963620737cSbeveloper buf_num_outputs -= 1; 19975ac4fbd7Sbeveloper #if DEBUG >= 3 19985ac4fbd7Sbeveloper PRINT_OUTPUT(" output ", out_outputs[i]); 19995ac4fbd7Sbeveloper #endif 20003620737cSbeveloper if (buf_num_outputs == 0) 20013620737cSbeveloper break; 200252a38012Sejakowatz } 200352a38012Sejakowatz 20048b04ffc1Sbeveloper MediaRosterEx(this)->PublishOutputs(node, &list); 20053620737cSbeveloper return B_OK; 200652a38012Sejakowatz } 200752a38012Sejakowatz 200852a38012Sejakowatz 200952a38012Sejakowatz status_t 201052a38012Sejakowatz BMediaRoster::StartWatching(const BMessenger& where) 201152a38012Sejakowatz { 2012eae26d3dSbeveloper CALLED(); 2013eae26d3dSbeveloper if (!where.IsValid()) { 20145ac4fbd7Sbeveloper ERROR("BMediaRoster::StartWatching: messenger invalid!\n"); 2015eae26d3dSbeveloper return B_BAD_VALUE; 2016eae26d3dSbeveloper } 201734c72144SAxel Dörfler return BPrivate::media::notifications::Register(where, media_node::null, 201834c72144SAxel Dörfler B_MEDIA_WILDCARD); 201952a38012Sejakowatz } 202052a38012Sejakowatz 202152a38012Sejakowatz 202252a38012Sejakowatz status_t 202334c72144SAxel Dörfler BMediaRoster::StartWatching(const BMessenger & where, int32 notificationType) 202452a38012Sejakowatz { 2025eae26d3dSbeveloper CALLED(); 2026eae26d3dSbeveloper if (!where.IsValid()) { 20275ac4fbd7Sbeveloper ERROR("BMediaRoster::StartWatching: messenger invalid!\n"); 2028eae26d3dSbeveloper return B_BAD_VALUE; 2029eae26d3dSbeveloper } 203034c72144SAxel Dörfler if (!BPrivate::media::notifications::IsValidNotificationRequest(false, 203134c72144SAxel Dörfler notificationType)) { 20325ac4fbd7Sbeveloper ERROR("BMediaRoster::StartWatching: notificationType invalid!\n"); 2033eae26d3dSbeveloper return B_BAD_VALUE; 2034eae26d3dSbeveloper } 203532afe10aSDario Casalinuovo 203632afe10aSDario Casalinuovo // NOTE: we support only explicitly B_MEDIA_SERVER_STARTED/QUIT 203732afe10aSDario Casalinuovo // notifications. This should be cleared in documentation. 203832afe10aSDario Casalinuovo 203934c72144SAxel Dörfler return BPrivate::media::notifications::Register(where, media_node::null, 204034c72144SAxel Dörfler notificationType); 204152a38012Sejakowatz } 204252a38012Sejakowatz 204352a38012Sejakowatz 204452a38012Sejakowatz status_t 204534c72144SAxel Dörfler BMediaRoster::StartWatching(const BMessenger& where, const media_node& node, 204652a38012Sejakowatz int32 notificationType) 204752a38012Sejakowatz { 2048eae26d3dSbeveloper CALLED(); 2049eae26d3dSbeveloper if (!where.IsValid()) { 20505ac4fbd7Sbeveloper ERROR("BMediaRoster::StartWatching: messenger invalid!\n"); 2051eae26d3dSbeveloper return B_BAD_VALUE; 2052eae26d3dSbeveloper } 205340f36b03Sbeveloper if (IS_INVALID_NODE(node)) { 20545ac4fbd7Sbeveloper ERROR("BMediaRoster::StartWatching: node invalid!\n"); 2055eae26d3dSbeveloper return B_MEDIA_BAD_NODE; 2056eae26d3dSbeveloper } 205734c72144SAxel Dörfler if (!BPrivate::media::notifications::IsValidNotificationRequest(true, 205834c72144SAxel Dörfler notificationType)) { 20595ac4fbd7Sbeveloper ERROR("BMediaRoster::StartWatching: notificationType invalid!\n"); 2060eae26d3dSbeveloper return B_BAD_VALUE; 2061eae26d3dSbeveloper } 206234c72144SAxel Dörfler return BPrivate::media::notifications::Register(where, node, 206334c72144SAxel Dörfler notificationType); 206452a38012Sejakowatz } 206552a38012Sejakowatz 206652a38012Sejakowatz 206752a38012Sejakowatz status_t 206852a38012Sejakowatz BMediaRoster::StopWatching(const BMessenger& where) 206952a38012Sejakowatz { 2070eae26d3dSbeveloper CALLED(); 2071eae26d3dSbeveloper // messenger may already be invalid, so we don't check this 207234c72144SAxel Dörfler return BPrivate::media::notifications::Unregister(where, media_node::null, 207334c72144SAxel Dörfler B_MEDIA_WILDCARD); 207452a38012Sejakowatz } 207552a38012Sejakowatz 207652a38012Sejakowatz 207752a38012Sejakowatz status_t 207834c72144SAxel Dörfler BMediaRoster::StopWatching(const BMessenger& where, int32 notificationType) 207952a38012Sejakowatz { 2080eae26d3dSbeveloper CALLED(); 2081eae26d3dSbeveloper // messenger may already be invalid, so we don't check this 208234c72144SAxel Dörfler if (!BPrivate::media::notifications::IsValidNotificationRequest(false, 208334c72144SAxel Dörfler notificationType)) { 20845ac4fbd7Sbeveloper ERROR("BMediaRoster::StopWatching: notificationType invalid!\n"); 2085eae26d3dSbeveloper return B_BAD_VALUE; 2086eae26d3dSbeveloper } 208734c72144SAxel Dörfler return BPrivate::media::notifications::Unregister(where, media_node::null, 208834c72144SAxel Dörfler notificationType); 208952a38012Sejakowatz } 209052a38012Sejakowatz 209152a38012Sejakowatz 209252a38012Sejakowatz status_t 209334c72144SAxel Dörfler BMediaRoster::StopWatching(const BMessenger& where, const media_node& node, 209452a38012Sejakowatz int32 notificationType) 209552a38012Sejakowatz { 2096eae26d3dSbeveloper CALLED(); 2097eae26d3dSbeveloper // messenger may already be invalid, so we don't check this 209840f36b03Sbeveloper if (IS_INVALID_NODE(node)) { 20995ac4fbd7Sbeveloper ERROR("BMediaRoster::StopWatching: node invalid!\n"); 2100eae26d3dSbeveloper return B_MEDIA_BAD_NODE; 2101eae26d3dSbeveloper } 210234c72144SAxel Dörfler if (!BPrivate::media::notifications::IsValidNotificationRequest(true, 210334c72144SAxel Dörfler notificationType)) { 21045ac4fbd7Sbeveloper ERROR("BMediaRoster::StopWatching: notificationType invalid!\n"); 2105eae26d3dSbeveloper return B_BAD_VALUE; 2106eae26d3dSbeveloper } 210734c72144SAxel Dörfler return BPrivate::media::notifications::Unregister(where, node, 210834c72144SAxel Dörfler notificationType); 210952a38012Sejakowatz } 211052a38012Sejakowatz 211152a38012Sejakowatz 211252a38012Sejakowatz status_t 211352a38012Sejakowatz BMediaRoster::RegisterNode(BMediaNode* node) 211452a38012Sejakowatz { 211554187cc6Sbeveloper CALLED(); 211654187cc6Sbeveloper // addon-id = -1 (unused), addon-flavor-id = 0 (unused, too) 211754187cc6Sbeveloper return MediaRosterEx(this)->RegisterNode(node, -1, 0); 211854187cc6Sbeveloper } 211954187cc6Sbeveloper 212054187cc6Sbeveloper 212154187cc6Sbeveloper status_t 21229c3b4706SAxel Dörfler BMediaRosterEx::RegisterNode(BMediaNode* node, media_addon_id addOnID, 21239dec2310SAxel Dörfler int32 flavorID) 212454187cc6Sbeveloper { 212552a38012Sejakowatz CALLED(); 212652a38012Sejakowatz if (node == NULL) 212752a38012Sejakowatz return B_BAD_VALUE; 212852a38012Sejakowatz 212954187cc6Sbeveloper // some sanity check 213054187cc6Sbeveloper // I'm not sure if the media kit warrants to call BMediaNode::AddOn() here. 213154187cc6Sbeveloper // Perhaps we don't need it. 21329dec2310SAxel Dörfler DEBUG_ONLY( 21339dec2310SAxel Dörfler int32 testFlavorID; 21349dec2310SAxel Dörfler BMediaAddOn* addon = node->AddOn(&testFlavorID); 21359dec2310SAxel Dörfler 21366813f2c7SIngo Weinhold ASSERT(addOnID == (addon != NULL ? addon->AddonID() : -1)); 2137e817f41eSFredrik Modéen // ASSERT(flavorID == testFlavorID); 21389dec2310SAxel Dörfler ); 213952a38012Sejakowatz 21409e9417d2Sbeveloper server_register_node_request request; 21419e9417d2Sbeveloper server_register_node_reply reply; 21429e9417d2Sbeveloper 21439c3b4706SAxel Dörfler request.add_on_id = addOnID; 21449c3b4706SAxel Dörfler request.flavor_id = flavorID; 21459e9417d2Sbeveloper strcpy(request.name, node->Name()); 21469e9417d2Sbeveloper request.kinds = node->Kinds(); 21479e9417d2Sbeveloper request.port = node->ControlPort(); 21489dec2310SAxel Dörfler request.team = BPrivate::current_team(); 21497bcdb362SDario Casalinuovo request.timesource_id = node->fTimeSourceID; 21509e9417d2Sbeveloper 215134c72144SAxel Dörfler TRACE("BMediaRoster::RegisterNode: sending SERVER_REGISTER_NODE: port " 2152332cc6bcSAxel Dörfler "%" B_PRId32 ", kinds 0x%" B_PRIx64 ", team %" B_PRId32 ", name '%s'\n", 2153332cc6bcSAxel Dörfler request.port, request.kinds, request.team, request.name); 21541299bfb2Sbeveloper 21559c3b4706SAxel Dörfler status_t status = QueryServer(SERVER_REGISTER_NODE, &request, 21569c3b4706SAxel Dörfler sizeof(request), &reply, sizeof(reply)); 21579c3b4706SAxel Dörfler if (status != B_OK) { 21589c3b4706SAxel Dörfler ERROR("BMediaRoster::RegisterNode: failed to register node %s: %s\n", 21599c3b4706SAxel Dörfler node->Name(), strerror(status)); 21609c3b4706SAxel Dörfler return status; 21619e9417d2Sbeveloper } 21629e9417d2Sbeveloper 216334c72144SAxel Dörfler TRACE("BMediaRoster::RegisterNode: QueryServer SERVER_REGISTER_NODE " 216434c72144SAxel Dörfler "finished\n"); 21654295907bSbeveloper 21668b04ffc1Sbeveloper // we are a friend class of BMediaNode and initialize this member variable 21679dec2310SAxel Dörfler node->fNodeID = reply.node_id; 21689dec2310SAxel Dörfler ASSERT(reply.node_id == node->Node().node); 21699dec2310SAxel Dörfler ASSERT(reply.node_id == node->ID()); 21709e9417d2Sbeveloper 217134c72144SAxel Dörfler // if the BMediaNode also inherits from BTimeSource, we need to call 217234c72144SAxel Dörfler // BTimeSource::FinishCreate() 21739c3b4706SAxel Dörfler if ((node->Kinds() & B_TIME_SOURCE) != 0) { 21749c3b4706SAxel Dörfler if (BTimeSource* timeSource = dynamic_cast<BTimeSource*>(node)) 21759c3b4706SAxel Dörfler timeSource->FinishCreate(); 21760e21b167Sbeveloper } 21770e21b167Sbeveloper 217811ed4f9fSDario Casalinuovo // call the callback 217911ed4f9fSDario Casalinuovo node->NodeRegistered(); 218011ed4f9fSDario Casalinuovo 218111ed4f9fSDario Casalinuovo TRACE("BMediaRoster::RegisterNode: NodeRegistered callback finished\n"); 218211ed4f9fSDario Casalinuovo 21834295907bSbeveloper TRACE("BMediaRoster::RegisterNode: publishing inputs/outputs\n"); 21844295907bSbeveloper 21853620737cSbeveloper // register existing inputs and outputs with the 21863620737cSbeveloper // media_server, this allows GetLiveNodes() to work 21873620737cSbeveloper // with created, but unconnected nodes. 21884d2d96e0Sbeveloper // The node control loop might not be running, or might deadlock 21894d2d96e0Sbeveloper // if we send a message and wait for a reply here. 21904d2d96e0Sbeveloper // We have a pointer to the node, and thus call the functions directly 21914295907bSbeveloper 21929c3b4706SAxel Dörfler if ((node->Kinds() & B_BUFFER_PRODUCER) != 0) { 21939c3b4706SAxel Dörfler if (BBufferProducer* producer = dynamic_cast<BBufferProducer*>(node)) { 2194359ac306Sbeveloper List<media_output> list; 21959c3b4706SAxel Dörfler if (GetAllOutputs(producer, &list) == B_OK) 2196359ac306Sbeveloper PublishOutputs(node->Node(), &list); 219721871f38Sbeveloper } 21984d2d96e0Sbeveloper } 21999dec2310SAxel Dörfler if ((node->Kinds() & B_BUFFER_CONSUMER) != 0) { 22009c3b4706SAxel Dörfler if (BBufferConsumer* consumer = dynamic_cast<BBufferConsumer*>(node)) { 2201359ac306Sbeveloper List<media_input> list; 22029dec2310SAxel Dörfler if (GetAllInputs(consumer, &list) == B_OK) 2203359ac306Sbeveloper PublishInputs(node->Node(), &list); 22043620737cSbeveloper } 22054d2d96e0Sbeveloper } 220621871f38Sbeveloper 22074295907bSbeveloper TRACE("BMediaRoster::RegisterNode: sending NodesCreated\n"); 22084295907bSbeveloper 22099dec2310SAxel Dörfler BPrivate::media::notifications::NodesCreated(&reply.node_id, 1); 22104295907bSbeveloper 22114295907bSbeveloper TRACE("BMediaRoster::RegisterNode: finished\n"); 22124295907bSbeveloper 2213570f7d04Sbeveloper /* 22149c3b4706SAxel Dörfler TRACE("BMediaRoster::RegisterNode: registered node name '%s', id %ld, 22159c3b4706SAxel Dörfler addon %ld, flavor %ld\n", node->Name(), node->ID(), addOnID, flavorID); 2216570f7d04Sbeveloper TRACE("BMediaRoster::RegisterNode: node this %p\n", node); 22179c3b4706SAxel Dörfler TRACE("BMediaRoster::RegisterNode: node fConsumerThis %p\n", 22189c3b4706SAxel Dörfler node->fConsumerThis); 22199c3b4706SAxel Dörfler TRACE("BMediaRoster::RegisterNode: node fProducerThis %p\n", 22209c3b4706SAxel Dörfler node->fProducerThis); 22219c3b4706SAxel Dörfler TRACE("BMediaRoster::RegisterNode: node fFileInterfaceThis %p\n", 22229c3b4706SAxel Dörfler node->fFileInterfaceThis); 22239c3b4706SAxel Dörfler TRACE("BMediaRoster::RegisterNode: node fControllableThis %p\n", 22249c3b4706SAxel Dörfler node->fControllableThis); 22259c3b4706SAxel Dörfler TRACE("BMediaRoster::RegisterNode: node fTimeSourceThis %p\n", 22269c3b4706SAxel Dörfler node->fTimeSourceThis); 2227570f7d04Sbeveloper */ 22289e9417d2Sbeveloper return B_OK; 222952a38012Sejakowatz } 223052a38012Sejakowatz 223152a38012Sejakowatz 223252a38012Sejakowatz status_t 223352a38012Sejakowatz BMediaRoster::UnregisterNode(BMediaNode* node) 223452a38012Sejakowatz { 22359e9417d2Sbeveloper CALLED(); 22369e9417d2Sbeveloper if (node == NULL) 22379e9417d2Sbeveloper return B_BAD_VALUE; 22389e9417d2Sbeveloper 22392ceb090fSDario Casalinuovo TRACE("BMediaRoster::UnregisterNode %" 22402ceb090fSDario Casalinuovo B_PRId32 " (%p)\n", node->ID(), node); 224160f15390Sbeveloper 224229bb91d6SAxel Dörfler if ((node->fKinds & NODE_KIND_NO_REFCOUNTING) !=0) { 224334c72144SAxel Dörfler TRACE("BMediaRoster::UnregisterNode, trying to unregister reference " 22442ceb090fSDario Casalinuovo "counting disabled timesource, node %" 22452ceb090fSDario Casalinuovo B_PRId32 " , port %" B_PRId32 " , team %" B_PRId32 "\n", 22469dec2310SAxel Dörfler node->ID(), node->ControlPort(), BPrivate::current_team()); 224786bce45bSbeveloper return B_OK; 224886bce45bSbeveloper } 22498b04ffc1Sbeveloper if (node->ID() == NODE_UNREGISTERED_ID) { 225034c72144SAxel Dörfler PRINT(1, "Warning: BMediaRoster::UnregisterNode: node id %ld, name " 225134c72144SAxel Dörfler "'%s' already unregistered\n", node->ID(), node->Name()); 22529e9417d2Sbeveloper return B_OK; 22539e9417d2Sbeveloper } 225454187cc6Sbeveloper if (node->fRefCount != 0) { 225534c72144SAxel Dörfler PRINT(1, "Warning: BMediaRoster::UnregisterNode: node id %ld, name " 225634c72144SAxel Dörfler "'%s' has local reference count of %ld\n", node->ID(), node->Name(), 225734c72144SAxel Dörfler node->fRefCount); 225854187cc6Sbeveloper // no return here, we continue and unregister! 225954187cc6Sbeveloper } 226054187cc6Sbeveloper 226134c72144SAxel Dörfler // Calling BMediaAddOn::GetConfigurationFor(BMediaNode *node, 226234c72144SAxel Dörfler // BMessage *config) if this node was instanciated by an add-on needs to 226334c72144SAxel Dörfler // be done *somewhere* 226454187cc6Sbeveloper // We can't do it here because it is already to late (destructor of the node 226554187cc6Sbeveloper // might have been called). 22669e9417d2Sbeveloper 22679e9417d2Sbeveloper server_unregister_node_request request; 22689dec2310SAxel Dörfler request.node_id = node->ID(); 22699dec2310SAxel Dörfler request.team = BPrivate::current_team(); 22709e9417d2Sbeveloper 22711299bfb2Sbeveloper // send a notification 22729dec2310SAxel Dörfler BPrivate::media::notifications::NodesDeleted(&request.node_id, 1); 22731299bfb2Sbeveloper 227429bb91d6SAxel Dörfler server_unregister_node_reply reply; 2275c74afb57SJérôme Duval reply.add_on_id = -1; 227629bb91d6SAxel Dörfler status_t status = QueryServer(SERVER_UNREGISTER_NODE, &request, 227729bb91d6SAxel Dörfler sizeof(request), &reply, sizeof(reply)); 227829bb91d6SAxel Dörfler if (status != B_OK) { 2279332cc6bcSAxel Dörfler ERROR("BMediaRoster::UnregisterNode: failed to unregister node id %" 2280332cc6bcSAxel Dörfler B_PRId32 ", name '%s': %s\n", node->ID(), node->Name(), 2281332cc6bcSAxel Dörfler strerror(status)); 2282c74afb57SJérôme Duval BMediaAddOn *addon = node->AddOn(&reply.flavor_id); 2283c74afb57SJérôme Duval if (addon != NULL) 2284c74afb57SJérôme Duval reply.add_on_id = addon->AddonID(); 22859e9417d2Sbeveloper } 22869e9417d2Sbeveloper 22879c3b4706SAxel Dörfler if (reply.add_on_id != -1) { 228829bb91d6SAxel Dörfler // TODO: this doesn't look right 228929bb91d6SAxel Dörfler // Small problem here, we can't use DormantNodeManager::PutAddOn(), as 229034c72144SAxel Dörfler // UnregisterNode() is called by a dormant node itself (by the 229134c72144SAxel Dörfler // destructor). 229254187cc6Sbeveloper // The add-on that contains the node needs to remain in memory until the 229354187cc6Sbeveloper // destructor execution is finished. 229429bb91d6SAxel Dörfler // DormantNodeManager::PutAddOnDelayed() will delay unloading. 22959c3b4706SAxel Dörfler gDormantNodeManager->PutAddOnDelayed(reply.add_on_id); 2296cf4e2277Sbeveloper 229729bb91d6SAxel Dörfler status = MediaRosterEx(this)->DecrementAddonFlavorInstancesCount( 22989c3b4706SAxel Dörfler reply.add_on_id, reply.flavor_id); 229929bb91d6SAxel Dörfler if (status != B_OK) { 230034c72144SAxel Dörfler ERROR("BMediaRoster::UnregisterNode: " 230134c72144SAxel Dörfler "DecrementAddonFlavorInstancesCount() failed\n"); 230254187cc6Sbeveloper // this is really a problem, but we can't fail now 230354187cc6Sbeveloper } 23048b04ffc1Sbeveloper } 23059e9417d2Sbeveloper 23061299bfb2Sbeveloper // we are a friend class of BMediaNode and invalidate this member variable 23078b04ffc1Sbeveloper node->fNodeID = NODE_UNREGISTERED_ID; 23089e9417d2Sbeveloper 2309c74afb57SJérôme Duval return status; 231052a38012Sejakowatz } 231152a38012Sejakowatz 231252a38012Sejakowatz 231334c72144SAxel Dörfler //! Thread safe for multiple calls to Roster() 231452a38012Sejakowatz /*static*/ BMediaRoster* 231552a38012Sejakowatz BMediaRoster::Roster(status_t* out_error) 231652a38012Sejakowatz { 2317d15321ffSDario Casalinuovo BAutolock lock(sInitLocker); 2318d15321ffSDario Casalinuovo 231905962bb1SDario Casalinuovo if (be_app == NULL) 232034619a6fSDario Casalinuovo TRACE("Warning! You should have a valid BApplication."); 232105962bb1SDario Casalinuovo 2322d15321ffSDario Casalinuovo if (!lock.IsLocked()) 2323d15321ffSDario Casalinuovo return NULL; 2324d15321ffSDario Casalinuovo 23258496c38aSbeveloper if (out_error) 23268496c38aSbeveloper *out_error = B_OK; 2327d15321ffSDario Casalinuovo 23289def3bf7SStephan Aßmus if (sDefaultInstance == NULL) { 23298496c38aSbeveloper status_t err; 23309def3bf7SStephan Aßmus sDefaultInstance = new (std::nothrow) BMediaRosterEx(&err); 23319def3bf7SStephan Aßmus if (sDefaultInstance == NULL) 2332a715f908SStephan Aßmus err = B_NO_MEMORY; 2333a715f908SStephan Aßmus else if (err != B_OK) { 23349def3bf7SStephan Aßmus if (sDefaultInstance) { 23359def3bf7SStephan Aßmus sDefaultInstance->Lock(); 23369def3bf7SStephan Aßmus sDefaultInstance->Quit(); 23379def3bf7SStephan Aßmus sDefaultInstance = NULL; 2338dcfb6bfcSJérôme Duval } 23398496c38aSbeveloper if (out_error) 23408496c38aSbeveloper *out_error = err; 234105962bb1SDario Casalinuovo } else if (be_app != NULL) { 234205962bb1SDario Casalinuovo be_app->RegisterLooper(sDefaultInstance); 23438496c38aSbeveloper } 234452a38012Sejakowatz } 234505962bb1SDario Casalinuovo 23469def3bf7SStephan Aßmus return sDefaultInstance; 234752a38012Sejakowatz } 234852a38012Sejakowatz 234952a38012Sejakowatz 235052a38012Sejakowatz /*static*/ BMediaRoster* 235152a38012Sejakowatz BMediaRoster::CurrentRoster() 235252a38012Sejakowatz { 23539def3bf7SStephan Aßmus return sDefaultInstance; 235452a38012Sejakowatz } 235552a38012Sejakowatz 235652a38012Sejakowatz 235752a38012Sejakowatz status_t 235834c72144SAxel Dörfler BMediaRoster::SetTimeSourceFor(media_node_id node, media_node_id time_source) 235952a38012Sejakowatz { 2360aac800c2Sbeveloper CALLED(); 236140f36b03Sbeveloper if (IS_INVALID_NODEID(node) || IS_INVALID_NODEID(time_source)) 2362aac800c2Sbeveloper return B_BAD_VALUE; 2363aac800c2Sbeveloper 2364aac800c2Sbeveloper media_node clone; 23657bcdb362SDario Casalinuovo // We need to get a clone of the node to have a port id 23667bcdb362SDario Casalinuovo status_t result = GetNodeFor(node, &clone); 23677bcdb362SDario Casalinuovo if (result == B_OK) { 23687bcdb362SDario Casalinuovo // We just send the request to set time_source-id as 23697bcdb362SDario Casalinuovo // timesource to the node, the NODE_SET_TIMESOURCE handler 23707bcdb362SDario Casalinuovo // code will do the real assignment. 2371aac800c2Sbeveloper result = B_OK; 2372aac800c2Sbeveloper node_set_timesource_command cmd; 2373aac800c2Sbeveloper cmd.timesource_id = time_source; 23747bcdb362SDario Casalinuovo result = SendToPort(clone.port, NODE_SET_TIMESOURCE, 23757bcdb362SDario Casalinuovo &cmd, sizeof(cmd)); 23767bcdb362SDario Casalinuovo if (result != B_OK) { 23777bcdb362SDario Casalinuovo ERROR("BMediaRoster::SetTimeSourceFor" 23787bcdb362SDario Casalinuovo "sending NODE_SET_TIMESOURCE failed, node id %" 23797bcdb362SDario Casalinuovo B_PRId32 "\n", clone.node); 23807bcdb362SDario Casalinuovo } 23817bcdb362SDario Casalinuovo // We release the clone 23827bcdb362SDario Casalinuovo result = ReleaseNode(clone); 23837bcdb362SDario Casalinuovo if (result != B_OK) { 23847bcdb362SDario Casalinuovo ERROR("BMediaRoster::SetTimeSourceFor, ReleaseNode failed," 23857bcdb362SDario Casalinuovo " node id %" B_PRId32 "\n", clone.node); 23867bcdb362SDario Casalinuovo } 23877bcdb362SDario Casalinuovo } else { 23887bcdb362SDario Casalinuovo ERROR("BMediaRoster::SetTimeSourceFor GetCloneForID failed, " 23897bcdb362SDario Casalinuovo "node id %" B_PRId32 "\n", node); 23907bcdb362SDario Casalinuovo } 23917bcdb362SDario Casalinuovo 23927bcdb362SDario Casalinuovo if (result == B_OK) { 23937bcdb362SDario Casalinuovo // Notify the server 23947bcdb362SDario Casalinuovo server_set_node_timesource_request request; 23957bcdb362SDario Casalinuovo server_set_node_timesource_reply reply; 23967bcdb362SDario Casalinuovo 23977bcdb362SDario Casalinuovo request.node_id = node; 23987bcdb362SDario Casalinuovo request.timesource_id = time_source; 23997bcdb362SDario Casalinuovo 24007bcdb362SDario Casalinuovo result = QueryServer(SERVER_SET_NODE_TIMESOURCE, &request, 24017bcdb362SDario Casalinuovo sizeof(request), &reply, sizeof(reply)); 24027bcdb362SDario Casalinuovo if (result != B_OK) { 240334c72144SAxel Dörfler ERROR("BMediaRoster::SetTimeSourceFor, sending NODE_SET_TIMESOURCE " 2404332cc6bcSAxel Dörfler "failed, node id %" B_PRId32 "\n", node); 24057bcdb362SDario Casalinuovo } else { 2406332cc6bcSAxel Dörfler TRACE("BMediaRoster::SetTimeSourceFor: node %" B_PRId32 " time source %" 24077bcdb362SDario Casalinuovo B_PRId32 " OK\n", node, time_source); 24087bcdb362SDario Casalinuovo } 24097bcdb362SDario Casalinuovo } 2410aac800c2Sbeveloper return result; 2411aac800c2Sbeveloper } 2412aac800c2Sbeveloper 241352a38012Sejakowatz 241452a38012Sejakowatz status_t 241534c72144SAxel Dörfler BMediaRoster::GetParameterWebFor(const media_node& node, BParameterWeb** _web) 241652a38012Sejakowatz { 241728ad138aSbeveloper CALLED(); 241834c72144SAxel Dörfler if (_web == NULL) 241928ad138aSbeveloper return B_BAD_VALUE; 242028ad138aSbeveloper if (IS_INVALID_NODE(node)) 242128ad138aSbeveloper return B_MEDIA_BAD_NODE; 242228ad138aSbeveloper if ((node.kind & B_CONTROLLABLE) == 0) 242328ad138aSbeveloper return B_MEDIA_BAD_NODE; 242428ad138aSbeveloper 242528ad138aSbeveloper controllable_get_parameter_web_request request; 242628ad138aSbeveloper controllable_get_parameter_web_reply reply; 242734c72144SAxel Dörfler int32 requestsize[] = {B_PAGE_SIZE, 4 * B_PAGE_SIZE, 16 * B_PAGE_SIZE, 242834c72144SAxel Dörfler 64 * B_PAGE_SIZE, 128 * B_PAGE_SIZE, 256 * B_PAGE_SIZE, 0}; 242928ad138aSbeveloper int32 size; 243028ad138aSbeveloper 243134c72144SAxel Dörfler // TODO: it might be better to query the node for the (current) parameter 243234c72144SAxel Dörfler // size first 243328ad138aSbeveloper for (int i = 0; (size = requestsize[i]) != 0; i++) { 243428ad138aSbeveloper status_t rv; 243528ad138aSbeveloper area_id area; 243628ad138aSbeveloper void *data; 243734c72144SAxel Dörfler area = create_area("parameter web data", &data, B_ANY_ADDRESS, size, 2438964cab46SAugustin Cavalier B_NO_LOCK, B_READ_AREA | B_WRITE_AREA | B_CLONEABLE_AREA); 243928ad138aSbeveloper if (area < B_OK) { 244034c72144SAxel Dörfler ERROR("BMediaRoster::GetParameterWebFor couldn't create area of " 2441332cc6bcSAxel Dörfler "size %" B_PRId32 "\n", size); 244228ad138aSbeveloper return B_ERROR; 244328ad138aSbeveloper } 244434c72144SAxel Dörfler request.max_size = size; 244528ad138aSbeveloper request.area = area; 244634c72144SAxel Dörfler rv = QueryPort(node.port, CONTROLLABLE_GET_PARAMETER_WEB, &request, 244734c72144SAxel Dörfler sizeof(request), &reply, sizeof(reply)); 244828ad138aSbeveloper if (rv != B_OK) { 244934c72144SAxel Dörfler ERROR("BMediaRoster::GetParameterWebFor " 245034c72144SAxel Dörfler "CONTROLLABLE_GET_PARAMETER_WEB failed\n"); 245128ad138aSbeveloper delete_area(area); 245228ad138aSbeveloper return B_ERROR; 245328ad138aSbeveloper } 245428ad138aSbeveloper if (reply.size == 0) { 245528ad138aSbeveloper // no parameter web available 245634c72144SAxel Dörfler // TODO: should we return an error? 2457332cc6bcSAxel Dörfler ERROR("BMediaRoster::GetParameterWebFor node %" B_PRId32 2458332cc6bcSAxel Dörfler " has no parameter web\n", node.node); 245934c72144SAxel Dörfler *_web = new (std::nothrow) BParameterWeb(); 246028ad138aSbeveloper delete_area(area); 246134c72144SAxel Dörfler return *_web != NULL ? B_OK : B_NO_MEMORY; 246252a38012Sejakowatz } 246328ad138aSbeveloper if (reply.size > 0) { 246428ad138aSbeveloper // we got a flattened parameter web! 2465df612ac9SRene Gollent BParameterWeb* web = new (std::nothrow) BParameterWeb(); 2466df612ac9SRene Gollent if (web == NULL) 2467a715f908SStephan Aßmus rv = B_NO_MEMORY; 2468a715f908SStephan Aßmus else { 2469df612ac9SRene Gollent rv = web->Unflatten(reply.code, data, reply.size); 247028ad138aSbeveloper if (rv != B_OK) { 247134c72144SAxel Dörfler ERROR("BMediaRoster::GetParameterWebFor Unflatten failed, " 247234c72144SAxel Dörfler "%s\n", strerror(rv)); 2473df612ac9SRene Gollent delete web; 2474df612ac9SRene Gollent } else 2475df612ac9SRene Gollent *_web = web; 247628ad138aSbeveloper } 2477df612ac9SRene Gollent 247828ad138aSbeveloper delete_area(area); 2479a715f908SStephan Aßmus return rv; 248028ad138aSbeveloper } 248128ad138aSbeveloper delete_area(area); 248228ad138aSbeveloper ASSERT(reply.size == -1); 248328ad138aSbeveloper // parameter web data was too large 248428ad138aSbeveloper // loop and try a larger size 248528ad138aSbeveloper } 2486332cc6bcSAxel Dörfler ERROR("BMediaRoster::GetParameterWebFor node %" B_PRId32 " has no " 2487332cc6bcSAxel Dörfler "parameter web larger than %" B_PRId32 "\n", node.node, size); 248828ad138aSbeveloper return B_ERROR; 248928ad138aSbeveloper } 249052a38012Sejakowatz 249152a38012Sejakowatz 249252a38012Sejakowatz status_t 249334c72144SAxel Dörfler BMediaRoster::StartControlPanel(const media_node& node, BMessenger* _messenger) 249452a38012Sejakowatz { 2495999cd0acSMaurice Kalinowski CALLED(); 2496999cd0acSMaurice Kalinowski 2497999cd0acSMaurice Kalinowski controllable_start_control_panel_request request; 2498999cd0acSMaurice Kalinowski controllable_start_control_panel_reply reply; 2499999cd0acSMaurice Kalinowski 2500999cd0acSMaurice Kalinowski request.node = node; 2501999cd0acSMaurice Kalinowski 2502999cd0acSMaurice Kalinowski status_t rv; 250334c72144SAxel Dörfler rv = QueryPort(node.port, CONTROLLABLE_START_CONTROL_PANEL, &request, 250434c72144SAxel Dörfler sizeof(request), &reply, sizeof(reply)); 2505999cd0acSMaurice Kalinowski if (rv != B_OK) 2506999cd0acSMaurice Kalinowski return rv; 2507999cd0acSMaurice Kalinowski 250834c72144SAxel Dörfler if (reply.team != -1 && _messenger != NULL) 250934c72144SAxel Dörfler *_messenger = BMessenger(NULL, reply.team); 2510999cd0acSMaurice Kalinowski 2511999cd0acSMaurice Kalinowski return B_OK; 251252a38012Sejakowatz } 251352a38012Sejakowatz 251452a38012Sejakowatz 251552a38012Sejakowatz status_t 251634c72144SAxel Dörfler BMediaRoster::GetDormantNodes(dormant_node_info* _info, int32* _count, 251734c72144SAxel Dörfler const media_format* hasInput, const media_format* hasOutput, 251834c72144SAxel Dörfler const char* name, uint64 requireKinds, uint64 denyKinds) 251952a38012Sejakowatz { 252052a38012Sejakowatz CALLED(); 252134c72144SAxel Dörfler if (_info == NULL || _count == NULL || *_count <= 0) 252252a38012Sejakowatz return B_BAD_VALUE; 252352a38012Sejakowatz 2524e4c87231SAxel Dörfler server_get_dormant_nodes_request request; 2525e4c87231SAxel Dörfler request.max_count = *_count; 2526e4c87231SAxel Dörfler request.has_input = hasInput != NULL; 252734c72144SAxel Dörfler if (hasInput != NULL) { 252834c72144SAxel Dörfler // TODO: we should not make a flat copy of media_format 2529e4c87231SAxel Dörfler request.input_format = *hasInput; 253034c72144SAxel Dörfler } 2531e4c87231SAxel Dörfler request.has_output = hasOutput != NULL; 253234c72144SAxel Dörfler if (hasOutput != NULL) { 253334c72144SAxel Dörfler // TODO: we should not make a flat copy of media_format 2534e4c87231SAxel Dörfler request.output_format = *hasOutput; 253534c72144SAxel Dörfler } 253634c72144SAxel Dörfler 2537e4c87231SAxel Dörfler request.has_name = name != NULL; 2538e4c87231SAxel Dörfler if (name != NULL) 2539e4c87231SAxel Dörfler strlcpy(request.name, name, sizeof(request.name)); 254052a38012Sejakowatz 2541e4c87231SAxel Dörfler request.require_kinds = requireKinds; 2542e4c87231SAxel Dörfler request.deny_kinds = denyKinds; 254352a38012Sejakowatz 2544e4c87231SAxel Dörfler server_get_dormant_nodes_reply reply; 2545e4c87231SAxel Dörfler status_t status = QueryServer(SERVER_GET_DORMANT_NODES, &request, 2546e4c87231SAxel Dörfler sizeof(request), &reply, sizeof(reply)); 25476cafce94SAxel Dörfler if (status != B_OK) 2548e4c87231SAxel Dörfler return status; 254952a38012Sejakowatz 255034c72144SAxel Dörfler *_count = reply.count; 255152a38012Sejakowatz 2552e4c87231SAxel Dörfler if (reply.count > 0) { 2553e4c87231SAxel Dörfler int32 code; 2554e4c87231SAxel Dörfler status = read_port(request.reply_port, &code, _info, 2555e4c87231SAxel Dörfler reply.count * sizeof(dormant_node_info)); 2556e4c87231SAxel Dörfler if (status < B_OK) 2557e4c87231SAxel Dörfler reply.result = status; 255852a38012Sejakowatz } 255952a38012Sejakowatz 256052a38012Sejakowatz return reply.result; 256152a38012Sejakowatz } 256252a38012Sejakowatz 2563e4c87231SAxel Dörfler 256434c72144SAxel Dörfler /*! This function is used to do the real work of instantiating a dormant node. 256534c72144SAxel Dörfler It is either called by the media_addon_server to instantiate a global node, 256634c72144SAxel Dörfler or it gets called from BMediaRoster::InstantiateDormantNode() to create a 256734c72144SAxel Dörfler local one. 256834c72144SAxel Dörfler 256934c72144SAxel Dörfler Checks concerning global/local are not done here. 25708b04ffc1Sbeveloper */ 257152a38012Sejakowatz status_t 257234c72144SAxel Dörfler BMediaRosterEx::InstantiateDormantNode(media_addon_id addonID, int32 flavorID, 257334c72144SAxel Dörfler team_id creator, media_node *_node) 257452a38012Sejakowatz { 257554187cc6Sbeveloper // This function is always called from the correct context, if the node 257654187cc6Sbeveloper // is supposed to be global, it is called from the media_addon_server. 257754187cc6Sbeveloper 257852a38012Sejakowatz // if B_FLAVOR_IS_GLOBAL, we need to use the BMediaAddOn object that 257952a38012Sejakowatz // resides in the media_addon_server 258052a38012Sejakowatz 25818b04ffc1Sbeveloper // RegisterNode() must be called for nodes instantiated from add-ons, 25828b04ffc1Sbeveloper // since the media kit warrants that it's done automatically. 258352a38012Sejakowatz 258434c72144SAxel Dörfler // addonID Indicates the ID number of the media add-on in which the 258534c72144SAxel Dörfler // node resides. 258634c72144SAxel Dörfler // flavorID Indicates the internal ID number that the add-on uses to 258734c72144SAxel Dörfler // identify the flavor, this is the number that was published 258834c72144SAxel Dörfler // by BMediaAddOn::GetFlavorAt() in the 25898b04ffc1Sbeveloper // flavor_info::internal_id field. 259034c72144SAxel Dörfler // creator The creator team is -1 if nodes are created locally. If 259134c72144SAxel Dörfler // created globally, it will contain (while called in 259234c72144SAxel Dörfler // media_addon_server context) the team-id of the team that 259334c72144SAxel Dörfler // requested the instantiation. 25948b04ffc1Sbeveloper 2595332cc6bcSAxel Dörfler TRACE("BMediaRosterEx::InstantiateDormantNode: addonID %" B_PRId32 2596332cc6bcSAxel Dörfler ", flavorID %" B_PRId32 "\n", addonID, flavorID); 25978b04ffc1Sbeveloper 25988b04ffc1Sbeveloper // Get flavor_info from the server 259934c72144SAxel Dörfler dormant_flavor_info info; 26008c6a6096Sbeveloper status_t rv; 260134c72144SAxel Dörfler rv = GetDormantFlavorInfo(addonID, flavorID, &info); 26028b04ffc1Sbeveloper if (rv != B_OK) { 260334c72144SAxel Dörfler ERROR("BMediaRosterEx::InstantiateDormantNode error: failed to get " 2604332cc6bcSAxel Dörfler "dormant_flavor_info for addon-id %" B_PRId32 ", flavor-id %" 2605332cc6bcSAxel Dörfler B_PRId32 "\n", addonID, flavorID); 260652a38012Sejakowatz return B_ERROR; 260752a38012Sejakowatz } 26088b04ffc1Sbeveloper 26091ecccf18SFrançois Revol ASSERT(info.internal_id == flavorID); 26108b04ffc1Sbeveloper 26118b04ffc1Sbeveloper // load the BMediaAddOn object 261229bb91d6SAxel Dörfler BMediaAddOn* addon = gDormantNodeManager->GetAddOn(addonID); 261334c72144SAxel Dörfler if (addon == NULL) { 26145ac4fbd7Sbeveloper ERROR("BMediaRosterEx::InstantiateDormantNode: GetAddon failed\n"); 26158b04ffc1Sbeveloper return B_ERROR; 26168b04ffc1Sbeveloper } 26178b04ffc1Sbeveloper 261854187cc6Sbeveloper // Now we need to try to increment the use count of this addon flavor 261954187cc6Sbeveloper // in the server. This can fail if the total number instances of this 262054187cc6Sbeveloper // flavor is limited. 262134c72144SAxel Dörfler rv = IncrementAddonFlavorInstancesCount(addonID, flavorID); 262254187cc6Sbeveloper if (rv != B_OK) { 262334c72144SAxel Dörfler ERROR("BMediaRosterEx::InstantiateDormantNode error: can't create " 2624332cc6bcSAxel Dörfler "more nodes for addon-id %" B_PRId32 ", flavor-id %" B_PRId32 "\n", 2625332cc6bcSAxel Dörfler addonID, flavorID); 262654187cc6Sbeveloper // Put the addon back into the pool 262729bb91d6SAxel Dörfler gDormantNodeManager->PutAddOn(addonID); 262854187cc6Sbeveloper return B_ERROR; 262954187cc6Sbeveloper } 263054187cc6Sbeveloper 26318b04ffc1Sbeveloper BMessage config; 263234c72144SAxel Dörfler rv = LoadNodeConfiguration(addonID, flavorID, &config); 263354187cc6Sbeveloper if (rv != B_OK) { 263434c72144SAxel Dörfler ERROR("BMediaRosterEx::InstantiateDormantNode: couldn't load " 2635332cc6bcSAxel Dörfler "configuration for addon-id %" B_PRId32 ", flavor-id %" B_PRId32 2636332cc6bcSAxel Dörfler "\n", addonID, flavorID); 263754187cc6Sbeveloper // do not return, this is a minor problem, not a reason to fail 263854187cc6Sbeveloper } 26398b04ffc1Sbeveloper 264034c72144SAxel Dörfler status_t status = B_OK; 264134c72144SAxel Dörfler BMediaNode* node = addon->InstantiateNodeFor(&info, &config, &status); 264234c72144SAxel Dörfler if (node == NULL) { 264334c72144SAxel Dörfler ERROR("BMediaRosterEx::InstantiateDormantNode: InstantiateNodeFor " 264434c72144SAxel Dörfler "failed\n"); 26458b04ffc1Sbeveloper 264654187cc6Sbeveloper // Put the addon back into the pool 264729bb91d6SAxel Dörfler gDormantNodeManager->PutAddOn(addonID); 264834c72144SAxel Dörfler 264954187cc6Sbeveloper // We must decrement the use count of this addon flavor in the 265054187cc6Sbeveloper // server to compensate the increment done in the beginning. 265134c72144SAxel Dörfler rv = DecrementAddonFlavorInstancesCount(addonID, flavorID); 265254187cc6Sbeveloper if (rv != B_OK) { 265334c72144SAxel Dörfler ERROR("BMediaRosterEx::InstantiateDormantNode: DecrementAddon" 265434c72144SAxel Dörfler "FlavorInstancesCount failed\n"); 265516b7eea4Sbeveloper } 265634c72144SAxel Dörfler return status != B_OK ? status : B_ERROR; 265754187cc6Sbeveloper } 265854187cc6Sbeveloper 265934c72144SAxel Dörfler rv = RegisterNode(node, addonID, flavorID); 26608c6a6096Sbeveloper if (rv != B_OK) { 26615ac4fbd7Sbeveloper ERROR("BMediaRosterEx::InstantiateDormantNode: RegisterNode failed\n"); 26628c6a6096Sbeveloper delete node; 266354187cc6Sbeveloper // Put the addon back into the pool 266429bb91d6SAxel Dörfler gDormantNodeManager->PutAddOn(addonID); 266554187cc6Sbeveloper // We must decrement the use count of this addon flavor in the 266654187cc6Sbeveloper // server to compensate the increment done in the beginning. 266734c72144SAxel Dörfler rv = DecrementAddonFlavorInstancesCount(addonID, flavorID); 266854187cc6Sbeveloper if (rv != B_OK) { 266934c72144SAxel Dörfler ERROR("BMediaRosterEx::InstantiateDormantNode: DecrementAddon" 267034c72144SAxel Dörfler "FlavorInstancesCount failed\n"); 267154187cc6Sbeveloper } 26728c6a6096Sbeveloper return B_ERROR; 26738c6a6096Sbeveloper } 26748c6a6096Sbeveloper 267554187cc6Sbeveloper if (creator != -1) { 267634c72144SAxel Dörfler // send a message to the server to assign team "creator" as creator 267734c72144SAxel Dörfler // of node "node->ID()" 2678332cc6bcSAxel Dörfler printf("!!! BMediaRosterEx::InstantiateDormantNode assigning team %" 2679332cc6bcSAxel Dörfler B_PRId32 " as creator of node %" B_PRId32 "\n", creator, 2680332cc6bcSAxel Dörfler node->ID()); 268134c72144SAxel Dörfler 268254187cc6Sbeveloper rv = MediaRosterEx(this)->SetNodeCreator(node->ID(), creator); 268354187cc6Sbeveloper if (rv != B_OK) { 268434c72144SAxel Dörfler ERROR("BMediaRosterEx::InstantiateDormantNode failed to assign " 2685332cc6bcSAxel Dörfler "team %" B_PRId32 " as creator of node %" B_PRId32 "\n", 2686332cc6bcSAxel Dörfler creator, node->ID()); 268754187cc6Sbeveloper // do not return, this is a minor problem, not a reason to fail 268854187cc6Sbeveloper } 268954187cc6Sbeveloper } 269054187cc6Sbeveloper 269154187cc6Sbeveloper // RegisterNode() does remember the add-on id in the server 269254187cc6Sbeveloper // and UnregisterNode() will call DormantNodeManager::PutAddon() 269354187cc6Sbeveloper // when the node is unregistered. 26948c6a6096Sbeveloper 269534c72144SAxel Dörfler *_node = node->Node(); 2696cf4e2277Sbeveloper 2697332cc6bcSAxel Dörfler TRACE("BMediaRosterEx::InstantiateDormantNode: addon-id %" B_PRId32 2698332cc6bcSAxel Dörfler ", flavor_id %" B_PRId32 " instanciated as node %" B_PRId32 ", port %" 2699332cc6bcSAxel Dörfler B_PRId32 " in team %" B_PRId32 "\n", addonID, flavorID, _node->node, 2700332cc6bcSAxel Dörfler _node->port, BPrivate::current_team()); 2701cf4e2277Sbeveloper 270216b7eea4Sbeveloper return B_OK; 270316b7eea4Sbeveloper } 270452a38012Sejakowatz 270552a38012Sejakowatz 270652a38012Sejakowatz status_t 270734c72144SAxel Dörfler BMediaRoster::InstantiateDormantNode(const dormant_node_info& info, 270834c72144SAxel Dörfler media_node* _node, uint32 flags) 27098b04ffc1Sbeveloper { 27108b04ffc1Sbeveloper CALLED(); 271134c72144SAxel Dörfler if (_node == NULL) 27128b04ffc1Sbeveloper return B_BAD_VALUE; 271334c72144SAxel Dörfler if (info.addon <= B_OK) { 2714332cc6bcSAxel Dörfler ERROR("BMediaRoster::InstantiateDormantNode error: addon-id %" B_PRId32 271534c72144SAxel Dörfler " invalid.\n", info.addon); 27168b04ffc1Sbeveloper return B_BAD_VALUE; 27178b04ffc1Sbeveloper } 27188b04ffc1Sbeveloper 2719332cc6bcSAxel Dörfler printf("BMediaRoster::InstantiateDormantNode: addon-id %" B_PRId32 2720332cc6bcSAxel Dörfler ", flavor_id %" B_PRId32 ", flags 0x%" B_PRIx32 "\n", info.addon, 2721332cc6bcSAxel Dörfler info.flavor_id, flags); 27228b04ffc1Sbeveloper 27238b04ffc1Sbeveloper // Get flavor_info from the server 272434c72144SAxel Dörfler // TODO: this is a little overhead, as we get the full blown 272534c72144SAxel Dörfler // dormant_flavor_info, 272634c72144SAxel Dörfler // TODO: but only need the flags. 272734c72144SAxel Dörfler dormant_flavor_info flavorInfo; 27288b04ffc1Sbeveloper status_t rv; 272934c72144SAxel Dörfler rv = MediaRosterEx(this)->GetDormantFlavorInfo(info.addon, info.flavor_id, 273034c72144SAxel Dörfler &flavorInfo); 27318b04ffc1Sbeveloper if (rv != B_OK) { 273234c72144SAxel Dörfler ERROR("BMediaRoster::InstantiateDormantNode: failed to get " 2733332cc6bcSAxel Dörfler "dormant_flavor_info for addon-id %" B_PRId32 ", flavor-id %" 2734332cc6bcSAxel Dörfler B_PRId32 "\n", info.addon, info.flavor_id); 2735626824eaSbeveloper return B_NAME_NOT_FOUND; 27368b04ffc1Sbeveloper } 27378b04ffc1Sbeveloper 273834c72144SAxel Dörfler ASSERT(flavorInfo.internal_id == info.flavor_id); 27398b04ffc1Sbeveloper 27408b04ffc1Sbeveloper #if DEBUG 274134c72144SAxel Dörfler printf("BMediaRoster::InstantiateDormantNode: name \"%s\", info \"%s\", " 2742332cc6bcSAxel Dörfler "flavor_flags 0x%" B_PRIx32 ", internal_id %" B_PRId32 2743332cc6bcSAxel Dörfler ", possible_count %" B_PRId32 "\n", flavorInfo.name, flavorInfo.info, 2744332cc6bcSAxel Dörfler flavorInfo.flavor_flags, flavorInfo.internal_id, 2745332cc6bcSAxel Dörfler flavorInfo.possible_count); 274634c72144SAxel Dörfler 274734c72144SAxel Dörfler if ((flags & B_FLAVOR_IS_LOCAL) != 0) { 274834c72144SAxel Dörfler printf("BMediaRoster::InstantiateDormantNode: caller requested " 274934c72144SAxel Dörfler "B_FLAVOR_IS_LOCAL\n"); 275034c72144SAxel Dörfler } 275134c72144SAxel Dörfler if ((flags & B_FLAVOR_IS_GLOBAL) != 0) { 275234c72144SAxel Dörfler printf("BMediaRoster::InstantiateDormantNode: caller requested " 275334c72144SAxel Dörfler "B_FLAVOR_IS_GLOBAL\n"); 275434c72144SAxel Dörfler } 275534c72144SAxel Dörfler if ((flavorInfo.flavor_flags & B_FLAVOR_IS_LOCAL) != 0) { 275634c72144SAxel Dörfler printf("BMediaRoster::InstantiateDormantNode: node requires " 275734c72144SAxel Dörfler "B_FLAVOR_IS_LOCAL\n"); 275834c72144SAxel Dörfler } 275934c72144SAxel Dörfler if ((flavorInfo.flavor_flags & B_FLAVOR_IS_GLOBAL) != 0) { 276034c72144SAxel Dörfler printf("BMediaRoster::InstantiateDormantNode: node requires " 276134c72144SAxel Dörfler "B_FLAVOR_IS_GLOBAL\n"); 276234c72144SAxel Dörfler } 27638b04ffc1Sbeveloper #endif 27648b04ffc1Sbeveloper 27658b04ffc1Sbeveloper // Make sure that flags demanded by the dormant node and those requested 27668b04ffc1Sbeveloper // by the caller are not incompatible. 276734c72144SAxel Dörfler if ((flavorInfo.flavor_flags & B_FLAVOR_IS_GLOBAL) != 0 276834c72144SAxel Dörfler && (flags & B_FLAVOR_IS_LOCAL) != 0) { 276934c72144SAxel Dörfler ERROR("BMediaRoster::InstantiateDormantNode: requested " 277034c72144SAxel Dörfler "B_FLAVOR_IS_LOCAL, but dormant node has B_FLAVOR_IS_GLOBAL\n"); 2771626824eaSbeveloper return B_NAME_NOT_FOUND; 27728b04ffc1Sbeveloper } 277334c72144SAxel Dörfler if ((flavorInfo.flavor_flags & B_FLAVOR_IS_LOCAL) != 0 277434c72144SAxel Dörfler && (flags & B_FLAVOR_IS_GLOBAL) != 0) { 277534c72144SAxel Dörfler ERROR("BMediaRoster::InstantiateDormantNode: requested " 277634c72144SAxel Dörfler "B_FLAVOR_IS_GLOBAL, but dormant node has B_FLAVOR_IS_LOCAL\n"); 2777626824eaSbeveloper return B_NAME_NOT_FOUND; 27788b04ffc1Sbeveloper } 277954187cc6Sbeveloper 27808b04ffc1Sbeveloper // If either the node, or the caller requested to make the instance global 278134c72144SAxel Dörfler // we will do it by forwarding this request into the media_addon_server, 278234c72144SAxel Dörfler // which in turn will call BMediaRosterEx::InstantiateDormantNode to create 278334c72144SAxel Dörfler // the node there and make it globally available. 278434c72144SAxel Dörfler if ((flavorInfo.flavor_flags & B_FLAVOR_IS_GLOBAL) != 0 278534c72144SAxel Dörfler || (flags & B_FLAVOR_IS_GLOBAL) != 0) { 278634c72144SAxel Dörfler TRACE("BMediaRoster::InstantiateDormantNode: creating global object " 278734c72144SAxel Dörfler "in media_addon_server\n"); 2788cf4e2277Sbeveloper 27899c3b4706SAxel Dörfler add_on_server_instantiate_dormant_node_request request; 27909c3b4706SAxel Dörfler add_on_server_instantiate_dormant_node_reply reply; 27919c3b4706SAxel Dörfler request.add_on_id = info.addon; 27929dec2310SAxel Dörfler request.flavor_id = info.flavor_id; 27939dec2310SAxel Dörfler request.creator_team = BPrivate::current_team(); 279434c72144SAxel Dörfler // creator team is allowed to also release global nodes 27959c3b4706SAxel Dörfler rv = QueryAddOnServer(ADD_ON_SERVER_INSTANTIATE_DORMANT_NODE, &request, 279634c72144SAxel Dörfler sizeof(request), &reply, sizeof(reply)); 279734c72144SAxel Dörfler if (rv == B_OK) 279834c72144SAxel Dörfler *_node = reply.node; 27998b04ffc1Sbeveloper } else { 280054187cc6Sbeveloper // creator team = -1, as this is a local node 280134c72144SAxel Dörfler rv = MediaRosterEx(this)->InstantiateDormantNode(info.addon, 280234c72144SAxel Dörfler info.flavor_id, -1, _node); 28038b04ffc1Sbeveloper } 2804626824eaSbeveloper if (rv != B_OK) { 280534c72144SAxel Dörfler *_node = media_node::null; 2806626824eaSbeveloper return B_NAME_NOT_FOUND; 2807626824eaSbeveloper } 2808626824eaSbeveloper return B_OK; 28098b04ffc1Sbeveloper } 28108b04ffc1Sbeveloper 28118b04ffc1Sbeveloper 28128b04ffc1Sbeveloper status_t 281334c72144SAxel Dörfler BMediaRoster::InstantiateDormantNode(const dormant_node_info& info, 281434c72144SAxel Dörfler media_node* _node) 28158b04ffc1Sbeveloper { 281634c72144SAxel Dörfler return InstantiateDormantNode(info, _node, 0); 28178b04ffc1Sbeveloper } 28188b04ffc1Sbeveloper 28198b04ffc1Sbeveloper 28208b04ffc1Sbeveloper status_t 282152a38012Sejakowatz BMediaRoster::GetDormantNodeFor(const media_node& node, 282234c72144SAxel Dörfler dormant_node_info* _info) 282352a38012Sejakowatz { 282485dfab2bSbeveloper CALLED(); 282534c72144SAxel Dörfler if (_info == NULL) 282685dfab2bSbeveloper return B_BAD_VALUE; 282740f36b03Sbeveloper if (IS_INVALID_NODE(node)) 282885dfab2bSbeveloper return B_MEDIA_BAD_NODE; 282952a38012Sejakowatz 283085dfab2bSbeveloper server_get_dormant_node_for_request request; 283185dfab2bSbeveloper server_get_dormant_node_for_reply reply; 283285dfab2bSbeveloper status_t rv; 283385dfab2bSbeveloper 283485dfab2bSbeveloper request.node = node; 283585dfab2bSbeveloper 283634c72144SAxel Dörfler rv = QueryServer(SERVER_GET_DORMANT_NODE_FOR, &request, sizeof(request), 283734c72144SAxel Dörfler &reply, sizeof(reply)); 283885dfab2bSbeveloper if (rv != B_OK) 283985dfab2bSbeveloper return rv; 284085dfab2bSbeveloper 284134c72144SAxel Dörfler *_info = reply.node_info; 284285dfab2bSbeveloper return B_OK; 284352a38012Sejakowatz } 284452a38012Sejakowatz 284534c72144SAxel Dörfler 284652a38012Sejakowatz status_t 284734c72144SAxel Dörfler BMediaRosterEx::GetDormantFlavorInfo(media_addon_id addonID, int32 flavorID, 284834c72144SAxel Dörfler dormant_flavor_info* _flavor) 284952a38012Sejakowatz { 285052a38012Sejakowatz CALLED(); 285134c72144SAxel Dörfler if (_flavor == NULL) 28529bedd42cSbeveloper return B_BAD_VALUE; 285352a38012Sejakowatz 2854e4c87231SAxel Dörfler // TODO: better use an area here as well! 285552a38012Sejakowatz 2856e4c87231SAxel Dörfler server_get_dormant_flavor_info_reply* reply 2857e4c87231SAxel Dörfler = (server_get_dormant_flavor_info_reply*)malloc(16300); 285834c72144SAxel Dörfler if (reply == NULL) 285934c72144SAxel Dörfler return B_NO_MEMORY; 286052a38012Sejakowatz 2861e4c87231SAxel Dörfler server_get_dormant_flavor_info_request request; 2862e4c87231SAxel Dörfler request.add_on_id = addonID; 2863e4c87231SAxel Dörfler request.flavor_id = flavorID; 2864e4c87231SAxel Dörfler 2865e4c87231SAxel Dörfler status_t status = QueryServer(SERVER_GET_DORMANT_FLAVOR_INFO, &request, 2866e4c87231SAxel Dörfler sizeof(request), reply, 16300); 28679dec2310SAxel Dörfler if (status != B_OK) { 286852a38012Sejakowatz free(reply); 28699dec2310SAxel Dörfler return status; 287052a38012Sejakowatz } 287152a38012Sejakowatz 28729dec2310SAxel Dörfler if (reply->result == B_OK) { 28739dec2310SAxel Dörfler status = _flavor->Unflatten(reply->type, &reply->flattened_data, 28749dec2310SAxel Dörfler reply->flattened_size); 28759dec2310SAxel Dörfler } else 28769dec2310SAxel Dörfler status = reply->result; 287752a38012Sejakowatz 287852a38012Sejakowatz free(reply); 28799dec2310SAxel Dörfler return status; 288052a38012Sejakowatz } 288152a38012Sejakowatz 288234c72144SAxel Dörfler 28838b04ffc1Sbeveloper status_t 288434c72144SAxel Dörfler BMediaRoster::GetDormantFlavorInfoFor(const dormant_node_info& dormant, 288534c72144SAxel Dörfler dormant_flavor_info* _flavor) 28868b04ffc1Sbeveloper { 288734c72144SAxel Dörfler return MediaRosterEx(this)->GetDormantFlavorInfo(dormant.addon, 288834c72144SAxel Dörfler dormant.flavor_id, _flavor); 28898b04ffc1Sbeveloper } 289052a38012Sejakowatz 289134c72144SAxel Dörfler 289260f15390Sbeveloper // Reports in outLatency the maximum latency found downstream from 289360f15390Sbeveloper // the specified BBufferProducer, producer, given the current connections. 289452a38012Sejakowatz status_t 289534c72144SAxel Dörfler BMediaRoster::GetLatencyFor(const media_node& producer, bigtime_t* _latency) 289652a38012Sejakowatz { 289760f15390Sbeveloper CALLED(); 289834c72144SAxel Dörfler if (_latency == NULL) 289960f15390Sbeveloper return B_BAD_VALUE; 290034c72144SAxel Dörfler if (IS_INVALID_NODE(producer) 290134c72144SAxel Dörfler || (producer.kind & B_BUFFER_PRODUCER) == 0) 290260f15390Sbeveloper return B_MEDIA_BAD_NODE; 290360f15390Sbeveloper 290460f15390Sbeveloper producer_get_latency_request request; 290560f15390Sbeveloper producer_get_latency_reply reply; 290660f15390Sbeveloper status_t rv; 290760f15390Sbeveloper 290834c72144SAxel Dörfler rv = QueryPort(producer.port, PRODUCER_GET_LATENCY, &request, 290934c72144SAxel Dörfler sizeof(request), &reply, sizeof(reply)); 291060f15390Sbeveloper if (rv != B_OK) 291160f15390Sbeveloper return rv; 291260f15390Sbeveloper 291334c72144SAxel Dörfler *_latency = reply.latency; 291460f15390Sbeveloper 2915ab9afde3SMarcus Overhagen // printf("BMediaRoster::GetLatencyFor producer %ld has maximum latency %Ld\n", producer.node, *out_latency); 2916aac800c2Sbeveloper return B_OK; 291752a38012Sejakowatz } 291852a38012Sejakowatz 291952a38012Sejakowatz 292052a38012Sejakowatz status_t 292152a38012Sejakowatz BMediaRoster::GetInitialLatencyFor(const media_node& producer, 292234c72144SAxel Dörfler bigtime_t* _latency, uint32* _flags) 292352a38012Sejakowatz { 2924b65a0ac5SJérôme Duval CALLED(); 292534c72144SAxel Dörfler if (_latency == NULL) 2926b65a0ac5SJérôme Duval return B_BAD_VALUE; 292734c72144SAxel Dörfler if (IS_INVALID_NODE(producer) 292834c72144SAxel Dörfler || (producer.kind & B_BUFFER_PRODUCER) == 0) 2929b65a0ac5SJérôme Duval return B_MEDIA_BAD_NODE; 2930b65a0ac5SJérôme Duval 2931b65a0ac5SJérôme Duval producer_get_initial_latency_request request; 2932b65a0ac5SJérôme Duval producer_get_initial_latency_reply reply; 2933b65a0ac5SJérôme Duval status_t rv; 2934b65a0ac5SJérôme Duval 293534c72144SAxel Dörfler rv = QueryPort(producer.port, PRODUCER_GET_INITIAL_LATENCY, &request, 293634c72144SAxel Dörfler sizeof(request), &reply, sizeof(reply)); 2937b65a0ac5SJérôme Duval if (rv != B_OK) 2938b65a0ac5SJérôme Duval return rv; 2939b65a0ac5SJérôme Duval 294034c72144SAxel Dörfler *_latency = reply.initial_latency; 294134c72144SAxel Dörfler if (_flags != NULL) 294234c72144SAxel Dörfler *_flags = reply.flags; 2943b65a0ac5SJérôme Duval 2944332cc6bcSAxel Dörfler TRACE("BMediaRoster::GetInitialLatencyFor producer %" B_PRId32 " has " 2945332cc6bcSAxel Dörfler "maximum initial latency %" B_PRId64 "\n", producer.node, *_latency); 2946aac800c2Sbeveloper return B_OK; 294752a38012Sejakowatz } 294852a38012Sejakowatz 294952a38012Sejakowatz 295052a38012Sejakowatz status_t 295134c72144SAxel Dörfler BMediaRoster::GetStartLatencyFor(const media_node& timeSource, 295234c72144SAxel Dörfler bigtime_t* _latency) 295352a38012Sejakowatz { 2954fc8b28b6SJérôme Duval CALLED(); 295534c72144SAxel Dörfler if (_latency == NULL) 2956fc8b28b6SJérôme Duval return B_BAD_VALUE; 295734c72144SAxel Dörfler if (IS_INVALID_NODE(timeSource) 295834c72144SAxel Dörfler || (timeSource.kind & B_TIME_SOURCE) == 0) 2959fc8b28b6SJérôme Duval return B_MEDIA_BAD_NODE; 2960fc8b28b6SJérôme Duval 2961fc8b28b6SJérôme Duval timesource_get_start_latency_request request; 2962fc8b28b6SJérôme Duval timesource_get_start_latency_reply reply; 2963fc8b28b6SJérôme Duval status_t rv; 2964fc8b28b6SJérôme Duval 296534c72144SAxel Dörfler rv = QueryPort(timeSource.port, TIMESOURCE_GET_START_LATENCY, &request, 296634c72144SAxel Dörfler sizeof(request), &reply, sizeof(reply)); 2967fc8b28b6SJérôme Duval if (rv != B_OK) 2968fc8b28b6SJérôme Duval return rv; 2969fc8b28b6SJérôme Duval 297034c72144SAxel Dörfler *_latency = reply.start_latency; 2971fc8b28b6SJérôme Duval 2972332cc6bcSAxel Dörfler TRACE("BMediaRoster::GetStartLatencyFor timesource %" B_PRId32 " has " 2973332cc6bcSAxel Dörfler "maximum initial latency %" B_PRId64 "\n", timeSource.node, *_latency); 2974aac800c2Sbeveloper return B_OK; 297552a38012Sejakowatz } 297652a38012Sejakowatz 297752a38012Sejakowatz 297852a38012Sejakowatz status_t 297934c72144SAxel Dörfler BMediaRoster::GetFileFormatsFor(const media_node& fileInterface, 298034c72144SAxel Dörfler media_file_format* _formats, int32* _numFormats) 298152a38012Sejakowatz { 2982b6f0f884SDario Casalinuovo CALLED(); 2983b6f0f884SDario Casalinuovo 2984b6f0f884SDario Casalinuovo if (IS_INVALID_NODE(fileInterface) 2985b6f0f884SDario Casalinuovo || (fileInterface.kind & B_FILE_INTERFACE) == 0) 2986b6f0f884SDario Casalinuovo return B_MEDIA_BAD_NODE; 2987b6f0f884SDario Casalinuovo 2988b6f0f884SDario Casalinuovo if (_numFormats == NULL || *_numFormats < 1) 2989b6f0f884SDario Casalinuovo return B_BAD_VALUE; 2990b6f0f884SDario Casalinuovo 2991b6f0f884SDario Casalinuovo fileinterface_get_formats_request request; 2992b6f0f884SDario Casalinuovo fileinterface_get_formats_reply reply; 2993b6f0f884SDario Casalinuovo 2994b6f0f884SDario Casalinuovo media_file_format* formats; 2995b6f0f884SDario Casalinuovo size_t needSize = sizeof(media_file_format) * *_numFormats; 2996b6f0f884SDario Casalinuovo size_t size = (needSize + (B_PAGE_SIZE - 1)) & ~(B_PAGE_SIZE - 1); 2997b6f0f884SDario Casalinuovo 2998b6f0f884SDario Casalinuovo area_id area = create_area("formats area", (void**)&formats, 2999b6f0f884SDario Casalinuovo B_ANY_ADDRESS, size, B_NO_LOCK, 3000b6f0f884SDario Casalinuovo B_READ_AREA | B_WRITE_AREA); 3001b6f0f884SDario Casalinuovo 3002b6f0f884SDario Casalinuovo if (area < 0) 3003b6f0f884SDario Casalinuovo return B_NO_MEMORY; 3004b6f0f884SDario Casalinuovo 3005b6f0f884SDario Casalinuovo request.num_formats = *_numFormats; 3006b6f0f884SDario Casalinuovo request.data_area = area; 3007b6f0f884SDario Casalinuovo 3008b6f0f884SDario Casalinuovo status_t status = QueryPort(fileInterface.port, 3009b6f0f884SDario Casalinuovo FILEINTERFACE_GET_FORMATS, &request, 3010b6f0f884SDario Casalinuovo sizeof(request), &reply, sizeof(reply)); 3011b6f0f884SDario Casalinuovo 3012b6f0f884SDario Casalinuovo if (status == B_OK) { 3013b6f0f884SDario Casalinuovo memcpy(_formats, formats, sizeof(media_file_format)*reply.filled_slots); 3014b6f0f884SDario Casalinuovo *_numFormats = reply.filled_slots; 3015b6f0f884SDario Casalinuovo } 3016b6f0f884SDario Casalinuovo delete_area(area); 3017b6f0f884SDario Casalinuovo return status; 301852a38012Sejakowatz } 301952a38012Sejakowatz 302052a38012Sejakowatz 302152a38012Sejakowatz status_t 302234c72144SAxel Dörfler BMediaRoster::SetRefFor(const media_node& file_interface, const entry_ref& file, 302334c72144SAxel Dörfler bool createAndTruncate, bigtime_t* _length) 302452a38012Sejakowatz { 30256938364bSMaurice Kalinowski CALLED(); 30266938364bSMaurice Kalinowski 302742d17c1aSDario Casalinuovo if (IS_INVALID_NODE(file_interface) 302842d17c1aSDario Casalinuovo || (file_interface.kind & B_FILE_INTERFACE) == 0) 302942d17c1aSDario Casalinuovo return B_MEDIA_BAD_NODE; 303042d17c1aSDario Casalinuovo 30316938364bSMaurice Kalinowski fileinterface_set_ref_request request; 30326938364bSMaurice Kalinowski fileinterface_set_ref_reply reply; 30336938364bSMaurice Kalinowski status_t rv; 30346938364bSMaurice Kalinowski 30356938364bSMaurice Kalinowski request.device = file.device; 30366938364bSMaurice Kalinowski request.directory = file.directory; 30376938364bSMaurice Kalinowski strcpy(request.name, file.name); 303834c72144SAxel Dörfler request.create = createAndTruncate; 303934c72144SAxel Dörfler if (_length != NULL) 304034c72144SAxel Dörfler request.duration = *_length; 30416938364bSMaurice Kalinowski 304234c72144SAxel Dörfler rv = QueryPort(file_interface.port, FILEINTERFACE_SET_REF, &request, 304334c72144SAxel Dörfler sizeof(request), &reply, sizeof(reply)); 30446938364bSMaurice Kalinowski if (rv != B_OK) 30456938364bSMaurice Kalinowski return rv; 30466938364bSMaurice Kalinowski 304734c72144SAxel Dörfler if (!createAndTruncate && _length) 304834c72144SAxel Dörfler *_length = reply.duration; 30496938364bSMaurice Kalinowski 30506938364bSMaurice Kalinowski return B_OK; 305152a38012Sejakowatz } 305252a38012Sejakowatz 305352a38012Sejakowatz 305452a38012Sejakowatz status_t 305534c72144SAxel Dörfler BMediaRoster::GetRefFor(const media_node& node, entry_ref* _file, 305634c72144SAxel Dörfler BMimeType* mimeType) 305752a38012Sejakowatz { 30586938364bSMaurice Kalinowski CALLED(); 30596938364bSMaurice Kalinowski 306042d17c1aSDario Casalinuovo if (IS_INVALID_NODE(node) 306142d17c1aSDario Casalinuovo || (node.kind & B_FILE_INTERFACE) == 0) 306242d17c1aSDario Casalinuovo return B_MEDIA_BAD_NODE; 306342d17c1aSDario Casalinuovo 306434c72144SAxel Dörfler if (!_file) 30656938364bSMaurice Kalinowski return B_BAD_VALUE; 30666938364bSMaurice Kalinowski 30676938364bSMaurice Kalinowski fileinterface_get_ref_request request; 30686938364bSMaurice Kalinowski fileinterface_get_ref_reply reply; 30696938364bSMaurice Kalinowski status_t rv; 30706938364bSMaurice Kalinowski 307134c72144SAxel Dörfler rv = QueryPort(node.port, FILEINTERFACE_GET_REF, &request, sizeof(request), 307234c72144SAxel Dörfler &reply, sizeof(reply)); 30736938364bSMaurice Kalinowski if (rv != B_OK) 30746938364bSMaurice Kalinowski return rv; 30756938364bSMaurice Kalinowski 307634c72144SAxel Dörfler *_file = entry_ref(reply.device, reply.directory, reply.name); 30776938364bSMaurice Kalinowski 307834c72144SAxel Dörfler if (mimeType) 307934c72144SAxel Dörfler mimeType->SetTo(reply.mimetype); 30806938364bSMaurice Kalinowski 30816938364bSMaurice Kalinowski return B_OK; 308252a38012Sejakowatz } 308352a38012Sejakowatz 308452a38012Sejakowatz 308552a38012Sejakowatz status_t 308652a38012Sejakowatz BMediaRoster::SniffRefFor(const media_node& file_interface, 308734c72144SAxel Dörfler const entry_ref& file, BMimeType* mimeType, float* _capability) 308852a38012Sejakowatz { 30896938364bSMaurice Kalinowski CALLED(); 309042d17c1aSDario Casalinuovo 309142d17c1aSDario Casalinuovo if (IS_INVALID_NODE(file_interface) 309242d17c1aSDario Casalinuovo || (file_interface.kind & B_FILE_INTERFACE) == 0) 309342d17c1aSDario Casalinuovo return B_MEDIA_BAD_NODE; 309442d17c1aSDario Casalinuovo 309534c72144SAxel Dörfler if (mimeType == NULL || _capability == NULL) 30966938364bSMaurice Kalinowski return B_BAD_VALUE; 30976938364bSMaurice Kalinowski 30986938364bSMaurice Kalinowski fileinterface_sniff_ref_request request; 30996938364bSMaurice Kalinowski fileinterface_sniff_ref_reply reply; 31006938364bSMaurice Kalinowski status_t rv; 31016938364bSMaurice Kalinowski 31026938364bSMaurice Kalinowski request.device = file.device; 31036938364bSMaurice Kalinowski request.directory = file.directory; 31046938364bSMaurice Kalinowski strcpy(request.name, file.name); 31056938364bSMaurice Kalinowski 310634c72144SAxel Dörfler rv = QueryPort(file_interface.port, FILEINTERFACE_SNIFF_REF, &request, 310734c72144SAxel Dörfler sizeof(request), &reply, sizeof(reply)); 31086938364bSMaurice Kalinowski if (rv != B_OK) 31096938364bSMaurice Kalinowski return rv; 31106938364bSMaurice Kalinowski 311134c72144SAxel Dörfler mimeType->SetTo(reply.mimetype); 311234c72144SAxel Dörfler *_capability = reply.capability; 31136938364bSMaurice Kalinowski 31146938364bSMaurice Kalinowski return B_OK; 311552a38012Sejakowatz } 311652a38012Sejakowatz 311752a38012Sejakowatz 311834c72144SAxel Dörfler /*! This is the generic "here's a file, now can someone please play it" 311934c72144SAxel Dörfler interface. 312034c72144SAxel Dörfler */ 312152a38012Sejakowatz status_t 312234c72144SAxel Dörfler BMediaRoster::SniffRef(const entry_ref& file, uint64 requireNodeKinds, 312334c72144SAxel Dörfler dormant_node_info* _node, BMimeType* mimeType) 312452a38012Sejakowatz { 312505f452c3SDavid McPaul CALLED(); 312605f452c3SDavid McPaul 3127332cc6bcSAxel Dörfler TRACE("BMediaRoster::SniffRef looking for a node to handle %s: 0x%" B_PRIx64 3128332cc6bcSAxel Dörfler "\n", file.name, requireNodeKinds); 312905f452c3SDavid McPaul 313005f452c3SDavid McPaul if (_node == NULL) 313105f452c3SDavid McPaul return B_BAD_VALUE; 313205f452c3SDavid McPaul 313305f452c3SDavid McPaul BMimeType aMimeType; 313405f452c3SDavid McPaul 313505f452c3SDavid McPaul dormant_node_info nodes[30]; 313605f452c3SDavid McPaul int32 count = 30; 313705f452c3SDavid McPaul int32 highestCapability = -1; 313805f452c3SDavid McPaul float capability; 313905f452c3SDavid McPaul 314005f452c3SDavid McPaul media_node node; 314105f452c3SDavid McPaul 314205f452c3SDavid McPaul // Get all dormant nodes using GetDormantNodes 31436f7f87a2SDavid McPaul if (GetDormantNodes(nodes, &count, NULL, NULL, NULL, requireNodeKinds | B_FILE_INTERFACE, 0) == B_OK) { 314405f452c3SDavid McPaul // Call SniffRefFor on each node that matches requireNodeKinds 314505f452c3SDavid McPaul for (int32 i=0;i<count;i++) { 31466f7f87a2SDavid McPaul if (InstantiateDormantNode(nodes[i], &node) == B_OK) { 314705f452c3SDavid McPaul 31486f7f87a2SDavid McPaul if (SniffRefFor(node, file, &aMimeType, &capability) == B_OK) { 314905f452c3SDavid McPaul // find the first node that has 100% capability 315005f452c3SDavid McPaul TRACE("%s has a %f%% chance of playing file\n",nodes[i].name, capability * 100.0); 315105f452c3SDavid McPaul if (capability == 1.0) { 315205f452c3SDavid McPaul highestCapability = i; 315305f452c3SDavid McPaul break; 315405f452c3SDavid McPaul } 315505f452c3SDavid McPaul } 315605f452c3SDavid McPaul ReleaseNode(node); 315705f452c3SDavid McPaul } 315805f452c3SDavid McPaul } 315905f452c3SDavid McPaul 316005f452c3SDavid McPaul if (highestCapability != -1) { 316105f452c3SDavid McPaul *_node = nodes[highestCapability]; 316205f452c3SDavid McPaul 3163332cc6bcSAxel Dörfler TRACE("BMediaRoster::SniffRef: found a node %s addon-id %" B_PRId32 3164332cc6bcSAxel Dörfler ", flavor_id %" B_PRId32 "\n", 3165332cc6bcSAxel Dörfler nodes[highestCapability].name, nodes[highestCapability].addon, 3166332cc6bcSAxel Dörfler nodes[highestCapability].flavor_id); 316705f452c3SDavid McPaul 316805f452c3SDavid McPaul if (mimeType != NULL) { 316905f452c3SDavid McPaul //*mimeType = aMimeType; -- need a copy constructor 317005f452c3SDavid McPaul } 317105f452c3SDavid McPaul 317205f452c3SDavid McPaul return B_OK; 317305f452c3SDavid McPaul } 317405f452c3SDavid McPaul 317505f452c3SDavid McPaul } 317605f452c3SDavid McPaul 317752a38012Sejakowatz return B_ERROR; 317852a38012Sejakowatz } 317952a38012Sejakowatz 318052a38012Sejakowatz 318152a38012Sejakowatz status_t 318252a38012Sejakowatz BMediaRoster::GetDormantNodeForType(const BMimeType& type, 318334c72144SAxel Dörfler uint64 requireNodeKinds, dormant_node_info* _node) 318452a38012Sejakowatz { 318552a38012Sejakowatz UNIMPLEMENTED(); 318652a38012Sejakowatz return B_ERROR; 318752a38012Sejakowatz } 318852a38012Sejakowatz 318952a38012Sejakowatz 319052a38012Sejakowatz status_t 319134c72144SAxel Dörfler BMediaRoster::GetReadFileFormatsFor(const dormant_node_info& node, 319234c72144SAxel Dörfler media_file_format* _readFormats, int32 readCount, int32* _readCount) 319352a38012Sejakowatz { 319452a38012Sejakowatz UNIMPLEMENTED(); 319552a38012Sejakowatz return B_ERROR; 319652a38012Sejakowatz } 319752a38012Sejakowatz 319852a38012Sejakowatz 319952a38012Sejakowatz status_t 320034c72144SAxel Dörfler BMediaRoster::GetWriteFileFormatsFor(const dormant_node_info& node, 320134c72144SAxel Dörfler media_file_format* _write_formats, int32 writeCount, int32* _writeCount) 320252a38012Sejakowatz { 320352a38012Sejakowatz UNIMPLEMENTED(); 320452a38012Sejakowatz return B_ERROR; 320552a38012Sejakowatz } 320652a38012Sejakowatz 320752a38012Sejakowatz 320852a38012Sejakowatz status_t 320934c72144SAxel Dörfler BMediaRoster::GetFormatFor(const media_output& output, media_format* _format, 321052a38012Sejakowatz uint32 flags) 321152a38012Sejakowatz { 32129bedd42cSbeveloper CALLED(); 321334c72144SAxel Dörfler if (_format == NULL) 32149bedd42cSbeveloper return B_BAD_VALUE; 32159bedd42cSbeveloper if ((output.node.kind & B_BUFFER_PRODUCER) == 0) 32169bedd42cSbeveloper return B_MEDIA_BAD_NODE; 32179bedd42cSbeveloper if (IS_INVALID_SOURCE(output.source)) 32189bedd42cSbeveloper return B_MEDIA_BAD_SOURCE; 32199bedd42cSbeveloper 32209bedd42cSbeveloper producer_format_suggestion_requested_request request; 32219bedd42cSbeveloper producer_format_suggestion_requested_reply reply; 32229bedd42cSbeveloper status_t rv; 32239bedd42cSbeveloper 32249bedd42cSbeveloper request.type = B_MEDIA_UNKNOWN_TYPE; 322534c72144SAxel Dörfler request.quality = 0; // TODO: what should this be? 32269bedd42cSbeveloper 322734c72144SAxel Dörfler rv = QueryPort(output.source.port, PRODUCER_FORMAT_SUGGESTION_REQUESTED, 322834c72144SAxel Dörfler &request, sizeof(request), &reply, sizeof(reply)); 32299bedd42cSbeveloper if (rv != B_OK) 32309bedd42cSbeveloper return rv; 32319bedd42cSbeveloper 323234c72144SAxel Dörfler *_format = reply.format; 32339bedd42cSbeveloper return B_OK; 323452a38012Sejakowatz } 323552a38012Sejakowatz 323652a38012Sejakowatz 323752a38012Sejakowatz status_t 323834c72144SAxel Dörfler BMediaRoster::GetFormatFor(const media_input& input, media_format* _format, 323952a38012Sejakowatz uint32 flags) 324052a38012Sejakowatz { 32419bedd42cSbeveloper CALLED(); 324234c72144SAxel Dörfler if (_format == NULL) 32439bedd42cSbeveloper return B_BAD_VALUE; 32449bedd42cSbeveloper if ((input.node.kind & B_BUFFER_CONSUMER) == 0) 32459bedd42cSbeveloper return B_MEDIA_BAD_NODE; 32469bedd42cSbeveloper if (IS_INVALID_DESTINATION(input.destination)) 32479bedd42cSbeveloper return B_MEDIA_BAD_DESTINATION; 32489bedd42cSbeveloper 32499bedd42cSbeveloper consumer_accept_format_request request; 32509bedd42cSbeveloper consumer_accept_format_reply reply; 32519bedd42cSbeveloper status_t rv; 32529bedd42cSbeveloper 32539bedd42cSbeveloper request.dest = input.destination; 325412ed45b6SMurai Takashi request.format.Clear(); // wildcard 32559bedd42cSbeveloper 325634c72144SAxel Dörfler rv = QueryPort(input.destination.port, CONSUMER_ACCEPT_FORMAT, &request, 325734c72144SAxel Dörfler sizeof(request), &reply, sizeof(reply)); 32589bedd42cSbeveloper if (rv != B_OK) 32599bedd42cSbeveloper return rv; 32609bedd42cSbeveloper 326134c72144SAxel Dörfler *_format = reply.format; 32629bedd42cSbeveloper return B_OK; 326352a38012Sejakowatz } 326452a38012Sejakowatz 326552a38012Sejakowatz 326652a38012Sejakowatz status_t 326734c72144SAxel Dörfler BMediaRoster::GetFormatFor(const media_node& node, media_format* _format, 326852a38012Sejakowatz float quality) 326952a38012Sejakowatz { 327052a38012Sejakowatz UNIMPLEMENTED(); 327134c72144SAxel Dörfler if (_format == NULL) 32729bedd42cSbeveloper return B_BAD_VALUE; 32739bedd42cSbeveloper if (IS_INVALID_NODE(node)) 32749bedd42cSbeveloper return B_MEDIA_BAD_NODE; 32759bedd42cSbeveloper if ((node.kind & (B_BUFFER_CONSUMER | B_BUFFER_PRODUCER)) == 0) 32769bedd42cSbeveloper return B_MEDIA_BAD_NODE; 32779bedd42cSbeveloper 327852a38012Sejakowatz return B_ERROR; 327952a38012Sejakowatz } 328052a38012Sejakowatz 328152a38012Sejakowatz 328252a38012Sejakowatz ssize_t 328352a38012Sejakowatz BMediaRoster::GetNodeAttributesFor(const media_node& node, 328434c72144SAxel Dörfler media_node_attribute* _array, size_t maxCount) 328552a38012Sejakowatz { 3286c079d8d6SDario Casalinuovo CALLED(); 3287c079d8d6SDario Casalinuovo 3288c079d8d6SDario Casalinuovo if (IS_INVALID_NODE(node)) 3289c079d8d6SDario Casalinuovo return B_MEDIA_BAD_NODE; 3290c079d8d6SDario Casalinuovo 3291c079d8d6SDario Casalinuovo node_get_attributes_for_request request; 3292c079d8d6SDario Casalinuovo node_get_attributes_for_reply reply; 3293c079d8d6SDario Casalinuovo status_t status; 3294c079d8d6SDario Casalinuovo 3295c079d8d6SDario Casalinuovo media_node_attribute* addr = NULL; 3296c079d8d6SDario Casalinuovo size_t totalSize = maxCount*sizeof(media_node_attribute); 3297c079d8d6SDario Casalinuovo size_t size = (totalSize + (B_PAGE_SIZE - 1)) & ~(B_PAGE_SIZE - 1); 3298c079d8d6SDario Casalinuovo 3299c079d8d6SDario Casalinuovo area_id dataArea = create_area("attributes area", (void**)&addr, 3300c079d8d6SDario Casalinuovo B_ANY_ADDRESS, size, B_NO_LOCK, 3301c079d8d6SDario Casalinuovo B_READ_AREA | B_WRITE_AREA); 3302c079d8d6SDario Casalinuovo // No need to memset the padding 3303c079d8d6SDario Casalinuovo memset(addr, 0, totalSize); 3304c079d8d6SDario Casalinuovo 3305c079d8d6SDario Casalinuovo if (dataArea < 0) 3306c079d8d6SDario Casalinuovo return B_NO_MEMORY; 3307c079d8d6SDario Casalinuovo 3308c079d8d6SDario Casalinuovo request.count = maxCount; 3309c079d8d6SDario Casalinuovo request.area = dataArea; 3310c079d8d6SDario Casalinuovo 3311c079d8d6SDario Casalinuovo status = QueryPort(node.port, NODE_GET_ATTRIBUTES_FOR, &request, 3312c079d8d6SDario Casalinuovo sizeof(request), &reply, sizeof(reply)); 3313c079d8d6SDario Casalinuovo if (status != B_OK) 3314c079d8d6SDario Casalinuovo return status; 3315c079d8d6SDario Casalinuovo 3316c079d8d6SDario Casalinuovo memcpy(_array, addr, reply.filled_count 3317c079d8d6SDario Casalinuovo * sizeof(media_node_attribute)); 3318c079d8d6SDario Casalinuovo 3319c079d8d6SDario Casalinuovo delete_area(dataArea); 3320c079d8d6SDario Casalinuovo return reply.filled_count; 332152a38012Sejakowatz } 332252a38012Sejakowatz 332352a38012Sejakowatz 332452a38012Sejakowatz media_node_id 332534c72144SAxel Dörfler BMediaRoster::NodeIDFor(port_id port) 332652a38012Sejakowatz { 33279e9417d2Sbeveloper CALLED(); 33289e9417d2Sbeveloper 33299e9417d2Sbeveloper server_node_id_for_request request; 33309e9417d2Sbeveloper server_node_id_for_reply reply; 33319e9417d2Sbeveloper status_t rv; 33329e9417d2Sbeveloper 333334c72144SAxel Dörfler request.port = port; 33349e9417d2Sbeveloper 333534c72144SAxel Dörfler rv = QueryServer(SERVER_NODE_ID_FOR, &request, sizeof(request), &reply, 333634c72144SAxel Dörfler sizeof(reply)); 33379e9417d2Sbeveloper if (rv != B_OK) { 3338332cc6bcSAxel Dörfler ERROR("BMediaRoster::NodeIDFor: failed (error %#" B_PRIx32 ")\n", rv); 33399e9417d2Sbeveloper return -1; 33409e9417d2Sbeveloper } 33419e9417d2Sbeveloper 33429dec2310SAxel Dörfler return reply.node_id; 334352a38012Sejakowatz } 334452a38012Sejakowatz 334552a38012Sejakowatz 334652a38012Sejakowatz status_t 334734c72144SAxel Dörfler BMediaRoster::GetInstancesFor(media_addon_id addon, int32 flavor, 334834c72144SAxel Dörfler media_node_id* _id, int32* _count) 334952a38012Sejakowatz { 335085dfab2bSbeveloper CALLED(); 335134c72144SAxel Dörfler if (_id == NULL) 335285dfab2bSbeveloper return B_BAD_VALUE; 335334c72144SAxel Dörfler if (_count && *_count <= 0) 335485dfab2bSbeveloper return B_BAD_VALUE; 335585dfab2bSbeveloper 335685dfab2bSbeveloper server_get_instances_for_request request; 335785dfab2bSbeveloper server_get_instances_for_reply reply; 335885dfab2bSbeveloper status_t rv; 335985dfab2bSbeveloper 33609c3b4706SAxel Dörfler request.max_count = (_count ? *_count : 1); 33619c3b4706SAxel Dörfler request.add_on_id = addon; 33629c3b4706SAxel Dörfler request.flavor_id = flavor; 336385dfab2bSbeveloper 336434c72144SAxel Dörfler rv = QueryServer(SERVER_GET_INSTANCES_FOR, &request, sizeof(request), 336534c72144SAxel Dörfler &reply, sizeof(reply)); 336685dfab2bSbeveloper if (rv != B_OK) { 33675ac4fbd7Sbeveloper ERROR("BMediaRoster::GetLiveNodes failed\n"); 336885dfab2bSbeveloper return rv; 336952a38012Sejakowatz } 337052a38012Sejakowatz 337134c72144SAxel Dörfler if (_count) 337234c72144SAxel Dörfler *_count = reply.count; 337385dfab2bSbeveloper if (reply.count > 0) 337434c72144SAxel Dörfler memcpy(_id, reply.node_id, sizeof(media_node_id) * reply.count); 337585dfab2bSbeveloper 337685dfab2bSbeveloper return B_OK; 337785dfab2bSbeveloper } 337852a38012Sejakowatz 337952a38012Sejakowatz 338067483edaSDario Casalinuovo bool 338167483edaSDario Casalinuovo BMediaRoster::IsRunning() 338267483edaSDario Casalinuovo { 3383d009f286SDario Casalinuovo return be_roster->IsRunning(B_MEDIA_SERVER_SIGNATURE) 3384d009f286SDario Casalinuovo && be_roster->IsRunning(B_MEDIA_ADDON_SERVER_SIGNATURE); 338567483edaSDario Casalinuovo } 338667483edaSDario Casalinuovo 338767483edaSDario Casalinuovo 338852a38012Sejakowatz ssize_t 338934c72144SAxel Dörfler BMediaRoster::AudioBufferSizeFor(int32 channelCount, uint32 sampleFormat, 339034c72144SAxel Dörfler float frameRate, bus_type busKind) 339152a38012Sejakowatz { 339234c72144SAxel Dörfler bigtime_t bufferDuration; 339334c72144SAxel Dörfler ssize_t bufferSize; 3394df6c2e83Sbeveloper 33954c125ccaSPawel Dziepak if (busKind == B_ISA_BUS || busKind == B_PCMCIA_BUS) 339634c72144SAxel Dörfler bufferDuration = 25000; 33974c125ccaSPawel Dziepak else 33984c125ccaSPawel Dziepak bufferDuration = 10000; 3399df6c2e83Sbeveloper 340034c72144SAxel Dörfler bufferSize = (sampleFormat & 0xf) * channelCount 340134c72144SAxel Dörfler * (ssize_t)((frameRate * bufferDuration) / 1000000.0); 3402df6c2e83Sbeveloper 3403332cc6bcSAxel Dörfler printf("Suggested buffer duration %" B_PRId64 ", size %" B_PRIdSSIZE "\n", 3404332cc6bcSAxel Dörfler bufferDuration, bufferSize); 3405df6c2e83Sbeveloper 340634c72144SAxel Dörfler return bufferSize; 340752a38012Sejakowatz } 340852a38012Sejakowatz 340952a38012Sejakowatz 341034c72144SAxel Dörfler /*! Use MediaFlags to inquire about specific features of the Media Kit. 341134c72144SAxel Dörfler Returns < 0 for "not present", positive size for output data size. 341234c72144SAxel Dörfler 0 means that the capability is present, but no data about it. 341334c72144SAxel Dörfler */ 341452a38012Sejakowatz /*static*/ ssize_t 341534c72144SAxel Dörfler BMediaRoster::MediaFlags(media_flags cap, void* buffer, size_t maxSize) 341652a38012Sejakowatz { 341752a38012Sejakowatz UNIMPLEMENTED(); 341852a38012Sejakowatz return 0; 341952a38012Sejakowatz } 342052a38012Sejakowatz 342152a38012Sejakowatz 342234c72144SAxel Dörfler // #pragma mark - BLooper overrides 342334c72144SAxel Dörfler 342434c72144SAxel Dörfler 342534c72144SAxel Dörfler void 342652a38012Sejakowatz BMediaRoster::MessageReceived(BMessage* message) 342752a38012Sejakowatz { 3428cf4e2277Sbeveloper switch (message->what) { 342932afe10aSDario Casalinuovo case MEDIA_ROSTER_REQUEST_NOTIFICATIONS: 343032afe10aSDario Casalinuovo { 343132afe10aSDario Casalinuovo RosterNotification notification; 343232afe10aSDario Casalinuovo if (message->FindInt32(NOTIFICATION_PARAM_WHAT, ¬ification.what) 343332afe10aSDario Casalinuovo != B_OK) { 343432afe10aSDario Casalinuovo TRACE("BMediaRoster MEDIA_ROSTER_REQUEST_NOTIFICATIONS can't" 343532afe10aSDario Casalinuovo "find what parameter"); 343632afe10aSDario Casalinuovo return; 343732afe10aSDario Casalinuovo } 343832afe10aSDario Casalinuovo if (message->FindMessenger(NOTIFICATION_PARAM_MESSENGER, 343932afe10aSDario Casalinuovo ¬ification.messenger) != B_OK) { 344032afe10aSDario Casalinuovo TRACE("BMediaRoster MEDIA_ROSTER_REQUEST_NOTIFICATIONS can't" 344132afe10aSDario Casalinuovo "find messenger"); 344232afe10aSDario Casalinuovo return; 344332afe10aSDario Casalinuovo } 344432afe10aSDario Casalinuovo sNotificationList.Insert(notification); 344532afe10aSDario Casalinuovo return; 344632afe10aSDario Casalinuovo } 344732afe10aSDario Casalinuovo 344832afe10aSDario Casalinuovo case MEDIA_ROSTER_CANCEL_NOTIFICATIONS: 344932afe10aSDario Casalinuovo { 345032afe10aSDario Casalinuovo RosterNotification notification; 345132afe10aSDario Casalinuovo if (message->FindInt32(NOTIFICATION_PARAM_WHAT, ¬ification.what) 345232afe10aSDario Casalinuovo != B_OK) { 345332afe10aSDario Casalinuovo TRACE("BMediaRoster MEDIA_ROSTER_CANCEL_NOTIFICATIONS can't" 345432afe10aSDario Casalinuovo "find what parameter"); 345532afe10aSDario Casalinuovo return; 345632afe10aSDario Casalinuovo } 345732afe10aSDario Casalinuovo if (message->FindMessenger(NOTIFICATION_PARAM_MESSENGER, 345832afe10aSDario Casalinuovo ¬ification.messenger) != B_OK) { 345932afe10aSDario Casalinuovo TRACE("BMediaRoster MEDIA_ROSTER_CANCEL_NOTIFICATIONS can't" 346032afe10aSDario Casalinuovo "find messenger"); 346132afe10aSDario Casalinuovo return; 346232afe10aSDario Casalinuovo } 346332afe10aSDario Casalinuovo for (int32 i = 0; i < sNotificationList.CountItems(); i++) { 346432afe10aSDario Casalinuovo RosterNotification* current; 346532afe10aSDario Casalinuovo if (sNotificationList.Get(i, ¤t) != true) 346632afe10aSDario Casalinuovo return; 346732afe10aSDario Casalinuovo if (current->what == notification.what 346832afe10aSDario Casalinuovo && current->messenger == notification.messenger) { 346932afe10aSDario Casalinuovo sNotificationList.Remove(i); 347032afe10aSDario Casalinuovo return; 347132afe10aSDario Casalinuovo } 347232afe10aSDario Casalinuovo } 347332afe10aSDario Casalinuovo return; 347432afe10aSDario Casalinuovo } 347532afe10aSDario Casalinuovo 347632afe10aSDario Casalinuovo case B_SOME_APP_LAUNCHED: 347732afe10aSDario Casalinuovo { 347832afe10aSDario Casalinuovo BString mimeSig; 347932afe10aSDario Casalinuovo if (message->FindString("be:signature", &mimeSig) != B_OK) 348032afe10aSDario Casalinuovo return; 348132afe10aSDario Casalinuovo if (mimeSig != B_MEDIA_ADDON_SERVER_SIGNATURE 348232afe10aSDario Casalinuovo && mimeSig != B_MEDIA_SERVER_SIGNATURE) 348332afe10aSDario Casalinuovo return; 348432afe10aSDario Casalinuovo 348532afe10aSDario Casalinuovo TRACE("BMediaRoster::MessageReceived media services are going up."); 348632afe10aSDario Casalinuovo 348732afe10aSDario Casalinuovo if (BMediaRoster::IsRunning()) { 348811c7bd86SDario Casalinuovo // Wait for media services to wake up and restore our friendship 348932afe10aSDario Casalinuovo if (MediaRosterEx(this)->BuildConnections() != B_OK) { 349032afe10aSDario Casalinuovo TRACE("BMediaRoster::MessageReceived can't reconnect" 349132afe10aSDario Casalinuovo "to media_server."); 349232afe10aSDario Casalinuovo } 349332afe10aSDario Casalinuovo } 349432afe10aSDario Casalinuovo return; 349532afe10aSDario Casalinuovo } 349632afe10aSDario Casalinuovo 349732afe10aSDario Casalinuovo case B_SOME_APP_QUIT: 349832afe10aSDario Casalinuovo { 349932afe10aSDario Casalinuovo BString mimeSig; 350032afe10aSDario Casalinuovo if (message->FindString("be:signature", &mimeSig) != B_OK) 350132afe10aSDario Casalinuovo return; 350232afe10aSDario Casalinuovo if (mimeSig != B_MEDIA_ADDON_SERVER_SIGNATURE 350332afe10aSDario Casalinuovo && mimeSig != B_MEDIA_SERVER_SIGNATURE) 350432afe10aSDario Casalinuovo return; 350532afe10aSDario Casalinuovo 350632afe10aSDario Casalinuovo TRACE("BMediaRoster::MessageReceived media services are down."); 350732afe10aSDario Casalinuovo 350832afe10aSDario Casalinuovo // Send the notification to our subscribers 350932afe10aSDario Casalinuovo if (!BMediaRoster::IsRunning() && sServerIsUp == true) { 351032afe10aSDario Casalinuovo sServerIsUp = false; 351132afe10aSDario Casalinuovo for (int32 i = 0; i < sNotificationList.CountItems(); i++) { 351232afe10aSDario Casalinuovo RosterNotification* current; 351332afe10aSDario Casalinuovo if (sNotificationList.Get(i, ¤t) != true) 351432afe10aSDario Casalinuovo return; 351532afe10aSDario Casalinuovo if (current->what == B_MEDIA_SERVER_QUIT) { 351632afe10aSDario Casalinuovo if (current->messenger.SendMessage( 351732afe10aSDario Casalinuovo B_MEDIA_SERVER_QUIT) != B_OK) { 351832afe10aSDario Casalinuovo if(!current->messenger.IsValid()) 351932afe10aSDario Casalinuovo sNotificationList.Remove(i); 352032afe10aSDario Casalinuovo } 352132afe10aSDario Casalinuovo } 352232afe10aSDario Casalinuovo } 352332afe10aSDario Casalinuovo } 352432afe10aSDario Casalinuovo return; 352532afe10aSDario Casalinuovo } 352632afe10aSDario Casalinuovo 352711c7bd86SDario Casalinuovo case MEDIA_SERVER_ALIVE: 352811c7bd86SDario Casalinuovo { 352911c7bd86SDario Casalinuovo if (!BMediaRoster::IsRunning()) 353011c7bd86SDario Casalinuovo return; 353111c7bd86SDario Casalinuovo 353211c7bd86SDario Casalinuovo sServerIsUp = true; 353311c7bd86SDario Casalinuovo 353411c7bd86SDario Casalinuovo TRACE("BMediaRoster::MessageReceived media services are" 353511c7bd86SDario Casalinuovo " finally up."); 353611c7bd86SDario Casalinuovo 353776889670SDario Casalinuovo if (MediaRosterEx(this)->fLaunchNotification) { 353876889670SDario Casalinuovo progress_startup(100, NULL, NULL); 353976889670SDario Casalinuovo if (MediaRosterEx(this)->fAutoExit) 354076889670SDario Casalinuovo MediaRosterEx(this)->fLaunchNotification = false; 354176889670SDario Casalinuovo } 354276889670SDario Casalinuovo 354311c7bd86SDario Casalinuovo // Send the notification to our subscribers 354411c7bd86SDario Casalinuovo for (int32 i = 0; i < sNotificationList.CountItems(); i++) { 354511c7bd86SDario Casalinuovo RosterNotification* current; 354611c7bd86SDario Casalinuovo if (sNotificationList.Get(i, ¤t) != true) 354711c7bd86SDario Casalinuovo return; 354811c7bd86SDario Casalinuovo if (current->what == B_MEDIA_SERVER_STARTED) { 354911c7bd86SDario Casalinuovo if (current->messenger.SendMessage( 355011c7bd86SDario Casalinuovo B_MEDIA_SERVER_STARTED) != B_OK) { 355111c7bd86SDario Casalinuovo if(!current->messenger.IsValid()) 355211c7bd86SDario Casalinuovo sNotificationList.Remove(i); 355311c7bd86SDario Casalinuovo } 355411c7bd86SDario Casalinuovo } 355511c7bd86SDario Casalinuovo } 355676889670SDario Casalinuovo return; 355711c7bd86SDario Casalinuovo } 355811c7bd86SDario Casalinuovo 3559cf4e2277Sbeveloper case NODE_FINAL_RELEASE: 3560cf4e2277Sbeveloper { 35616423f87fSDario Casalinuovo // This function is called by a BMediaNode to delete 3562cf4e2277Sbeveloper // itself, as this needs to be done from another thread 3563cf4e2277Sbeveloper // context, it is done here. 3564cf4e2277Sbeveloper 35656423f87fSDario Casalinuovo BMediaNode* node = NULL; 35666423f87fSDario Casalinuovo status_t err = message->FindPointer("node", 35676423f87fSDario Casalinuovo reinterpret_cast<void **>(&node)); 35686423f87fSDario Casalinuovo if (err == B_OK && node != NULL) 35696423f87fSDario Casalinuovo node->Release(); 35706423f87fSDario Casalinuovo else { 35716423f87fSDario Casalinuovo TRACE("BMediaRoster::MessageReceived: CRITICAL! received" 35726423f87fSDario Casalinuovo "a release request but the node can't be found."); 35736423f87fSDario Casalinuovo } 3574cf4e2277Sbeveloper return; 3575cf4e2277Sbeveloper } 357648b2cb37SDario Casalinuovo 357748b2cb37SDario Casalinuovo default: 357848b2cb37SDario Casalinuovo BLooper::MessageReceived(message); 357948b2cb37SDario Casalinuovo break; 358048b2cb37SDario Casalinuovo } 358152a38012Sejakowatz } 358252a38012Sejakowatz 358334c72144SAxel Dörfler 358434c72144SAxel Dörfler bool 358552a38012Sejakowatz BMediaRoster::QuitRequested() 358652a38012Sejakowatz { 358732afe10aSDario Casalinuovo CALLED(); 358852a38012Sejakowatz return true; 358952a38012Sejakowatz } 359052a38012Sejakowatz 359134c72144SAxel Dörfler 359234c72144SAxel Dörfler BHandler* 359334c72144SAxel Dörfler BMediaRoster::ResolveSpecifier(BMessage* msg, int32 index, BMessage* specifier, 359434c72144SAxel Dörfler int32 form, const char* property) 359552a38012Sejakowatz { 3596286a3c91SJérôme Duval return BLooper::ResolveSpecifier(msg, index, specifier, form, property); 359752a38012Sejakowatz } 359852a38012Sejakowatz 359952a38012Sejakowatz 360034c72144SAxel Dörfler status_t 360152a38012Sejakowatz BMediaRoster::GetSupportedSuites(BMessage* data) 360252a38012Sejakowatz { 3603286a3c91SJérôme Duval return BLooper::GetSupportedSuites(data); 360452a38012Sejakowatz } 360552a38012Sejakowatz 360652a38012Sejakowatz 360752a38012Sejakowatz BMediaRoster::~BMediaRoster() 360852a38012Sejakowatz { 360952a38012Sejakowatz CALLED(); 36106396865dSbeveloper 36118b940bb4SStephan Aßmus // Unset the global instance pointer, the destructor is also called 36128b940bb4SStephan Aßmus // if a client app calls Lock(); and Quit(); directly. 36139def3bf7SStephan Aßmus sDefaultInstance = NULL; 361452a38012Sejakowatz } 361552a38012Sejakowatz 361634c72144SAxel Dörfler // #pragma mark - private BMediaRoster 361734c72144SAxel Dörfler 3618f0a1eb2dSAxel Dörfler // FBC reserved virtuals 361952a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_0(void*) { return B_ERROR; } 362052a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_1(void*) { return B_ERROR; } 362152a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_2(void*) { return B_ERROR; } 362252a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_3(void*) { return B_ERROR; } 362352a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_4(void*) { return B_ERROR; } 362452a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_5(void*) { return B_ERROR; } 362552a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_6(void*) { return B_ERROR; } 362652a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_7(void*) { return B_ERROR; } 362752a38012Sejakowatz 362852a38012Sejakowatz 362934c72144SAxel Dörfler BMediaRoster::BMediaRoster() 36302f9ed888SAxel Dörfler : 36312f9ed888SAxel Dörfler BLooper("_BMediaRoster_", B_URGENT_DISPLAY_PRIORITY, 363234c72144SAxel Dörfler B_LOOPER_PORT_DEFAULT_CAPACITY) 363352a38012Sejakowatz { 363452a38012Sejakowatz CALLED(); 36356396865dSbeveloper 36366396865dSbeveloper // start the looper 36376396865dSbeveloper Run(); 363852a38012Sejakowatz } 363952a38012Sejakowatz 36409def3bf7SStephan Aßmus // #pragma mark - static variables 364152a38012Sejakowatz 36429def3bf7SStephan Aßmus BMediaRoster* BMediaRoster::sDefaultInstance = NULL; 3643