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 {
LocalNodeBPrivate::media::LocalNode9367060664SDario Casalinuovo LocalNode(BMediaNode* local_node)
9467060664SDario Casalinuovo :
9567060664SDario Casalinuovo node(local_node) {}
9667060664SDario Casalinuovo
LocalNodeBPrivate::media::LocalNode9767060664SDario Casalinuovo LocalNode()
9867060664SDario Casalinuovo :
9967060664SDario Casalinuovo node(NULL) {}
10067060664SDario Casalinuovo
operator ==BPrivate::media::LocalNode10167060664SDario 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
118083314c2SAdrien Destugues // This class takes care of all static initialization and destruction of
119083314c2SAdrien Destugues // libmedia objects. It guarantees that things are created and destroyed in
120083314c2SAdrien Destugues // the correct order, as well as performing some "garbage collecting" by being
121083314c2SAdrien Destugues // destructed automatically on application exit.
1227d337b23SDario Casalinuovo class MediaRosterUndertaker {
1237d337b23SDario Casalinuovo public:
MediaRosterUndertaker()124083314c2SAdrien Destugues MediaRosterUndertaker()
125083314c2SAdrien Destugues {
126083314c2SAdrien Destugues gPortPool = new PortPool();
127083314c2SAdrien Destugues }
128083314c2SAdrien Destugues
~MediaRosterUndertaker()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
BMediaRosterEx(status_t * _error)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
Quit()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
BuildConnections()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
~BMediaRosterEx()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
RegisterLocalNode(BMediaNode * node)24467060664SDario Casalinuovo BMediaRosterEx::RegisterLocalNode(BMediaNode* node)
24567060664SDario Casalinuovo {
24667060664SDario Casalinuovo sRegisteredNodes.Insert(LocalNode(node));
24767060664SDario Casalinuovo }
24867060664SDario Casalinuovo
24967060664SDario Casalinuovo
25067060664SDario Casalinuovo void
UnregisterLocalNode(BMediaNode * node)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
EnableLaunchNotification(bool enable,bool autoExit)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
SaveNodeConfiguration(BMediaNode * node)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
LoadNodeConfiguration(media_addon_id addonID,int32 flavorID,BMessage * _msg)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
IncrementAddonFlavorInstancesCount(media_addon_id addonID,int32 flavorID)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
DecrementAddonFlavorInstancesCount(media_addon_id addonID,int32 flavorID)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
ReleaseNodeAll(const media_node & node)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
SetNodeCreator(media_node_id node,team_id creator)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
GetNode(node_type type,media_node * out_node,int32 * out_input_id,BString * out_input_name)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
SetNode(node_type type,const media_node * node,const dormant_node_info * info,const media_input * input)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
GetAllOutputs(const media_node & node,List<media_output> * list)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
GetAllOutputs(BBufferProducer * node,List<media_output> * list)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
GetAllInputs(const media_node & node,List<media_input> * list)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
GetAllInputs(BBufferConsumer * node,List<media_input> * list)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
PublishOutputs(const media_node & node,List<media_output> * list)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
PublishInputs(const media_node & node,List<media_input> * list)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*
MakeTimeSourceObject(media_node_id timeSourceID)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
GetVideoInput(media_node * _node)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
GetAudioInput(media_node * _node)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
GetVideoOutput(media_node * _node)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
GetAudioMixer(media_node * _node)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
GetAudioOutput(media_node * _node)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
GetAudioOutput(media_node * _node,int32 * _inputID,BString * _inputName)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
GetTimeSource(media_node * _node)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
SetVideoInput(const media_node & producer)79752a38012Sejakowatz BMediaRoster::SetVideoInput(const media_node& producer)
79852a38012Sejakowatz {
79952a38012Sejakowatz CALLED();
8008b04ffc1Sbeveloper return MediaRosterEx(this)->SetNode(VIDEO_INPUT, &producer);
80152a38012Sejakowatz }
80252a38012Sejakowatz
80352a38012Sejakowatz
80452a38012Sejakowatz status_t
SetVideoInput(const dormant_node_info & producer)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
SetAudioInput(const media_node & producer)81352a38012Sejakowatz BMediaRoster::SetAudioInput(const media_node& producer)
81452a38012Sejakowatz {
81552a38012Sejakowatz CALLED();
8168b04ffc1Sbeveloper return MediaRosterEx(this)->SetNode(AUDIO_INPUT, &producer);
81752a38012Sejakowatz }
81852a38012Sejakowatz
81952a38012Sejakowatz
82052a38012Sejakowatz status_t
SetAudioInput(const dormant_node_info & producer)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
SetVideoOutput(const media_node & consumer)82952a38012Sejakowatz BMediaRoster::SetVideoOutput(const media_node& consumer)
83052a38012Sejakowatz {
83152a38012Sejakowatz CALLED();
8328b04ffc1Sbeveloper return MediaRosterEx(this)->SetNode(VIDEO_OUTPUT, &consumer);
83352a38012Sejakowatz }
83452a38012Sejakowatz
83552a38012Sejakowatz
83652a38012Sejakowatz status_t
SetVideoOutput(const dormant_node_info & consumer)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
SetAudioOutput(const media_node & consumer)84552a38012Sejakowatz BMediaRoster::SetAudioOutput(const media_node& consumer)
84652a38012Sejakowatz {
84752a38012Sejakowatz CALLED();
8488b04ffc1Sbeveloper return MediaRosterEx(this)->SetNode(AUDIO_OUTPUT, &consumer);
84952a38012Sejakowatz }
85052a38012Sejakowatz
85152a38012Sejakowatz
85252a38012Sejakowatz status_t
SetAudioOutput(const media_input & input)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
SetAudioOutput(const dormant_node_info & consumer)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
GetNodeFor(media_node_id node,media_node * clone)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
GetSystemTimeSource(media_node * clone)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
ReleaseNode(const media_node & node)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*
MakeTimeSourceFor(const media_node & forNode)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
Connect(const media_source & from,const media_destination & to,media_format * _format,media_output * _output,media_input * _input)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
Connect(const media_source & from,const media_destination & to,media_format * io_format,media_output * out_output,media_input * out_input,uint32 in_flags,void * _reserved)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
Disconnect(media_node_id source_nodeid,const media_source & source,media_node_id destination_nodeid,const media_destination & destination)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
Disconnect(const media_output & output,const media_input & input)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
StartNode(const media_node & node,bigtime_t atPerformanceTime)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
StopNode(const media_node & node,bigtime_t atPerformanceTime,bool immediate)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
SeekNode(const media_node & node,bigtime_t toMediaTime,bigtime_t atPerformanceTime)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
StartTimeSource(const media_node & node,bigtime_t atRealTime)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
StopTimeSource(const media_node & node,bigtime_t atRealTime,bool immediate)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
SeekTimeSource(const media_node & node,bigtime_t toPerformanceTime,bigtime_t atRealTime)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
SyncToNode(const media_node & node,bigtime_t atTime,bigtime_t timeout)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
SetRunModeNode(const media_node & node,BMediaNode::run_mode mode)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
PrerollNode(const media_node & node)155852a38012Sejakowatz BMediaRoster::PrerollNode(const media_node& node)
155952a38012Sejakowatz {
156052a38012Sejakowatz CALLED();
156140f36b03Sbeveloper if (IS_INVALID_NODE(node))
156252a38012Sejakowatz return B_MEDIA_BAD_NODE;
156352a38012Sejakowatz
1564f7338bb6SAugustin Cavalier char dummy = 0;
156552a38012Sejakowatz return write_port(node.port, NODE_PREROLL, &dummy, sizeof(dummy));
156652a38012Sejakowatz }
156752a38012Sejakowatz
156852a38012Sejakowatz
156952a38012Sejakowatz status_t
RollNode(const media_node & node,bigtime_t startPerformance,bigtime_t stopPerformance,bigtime_t atMediaTime)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
SetProducerRunModeDelay(const media_node & node,bigtime_t delay,BMediaNode::run_mode mode)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
SetProducerRate(const media_node & producer,int32 numer,int32 denom)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
GetLiveNodeInfo(const media_node & node,live_node_info * out_live_info)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
GetLiveNodes(live_node_info * liveNodes,int32 * _totalCount,const media_format * hasInput,const media_format * hasOutput,const char * name,uint64 nodeKinds)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
GetFreeInputsFor(const media_node & node,media_input * out_free_inputs,int32 buf_num_inputs,int32 * out_total_count,media_type filter_type)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
GetConnectedInputsFor(const media_node & node,media_input * out_active_inputs,int32 buf_num_inputs,int32 * out_total_count)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
GetAllInputsFor(const media_node & node,media_input * out_inputs,int32 buf_num_inputs,int32 * out_total_count)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
GetFreeOutputsFor(const media_node & node,media_output * out_free_outputs,int32 buf_num_outputs,int32 * out_total_count,media_type filter_type)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
GetConnectedOutputsFor(const media_node & node,media_output * out_active_outputs,int32 buf_num_outputs,int32 * out_total_count)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
GetAllOutputsFor(const media_node & node,media_output * out_outputs,int32 buf_num_outputs,int32 * out_total_count)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
StartWatching(const BMessenger & where)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
StartWatching(const BMessenger & where,int32 notificationType)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
StartWatching(const BMessenger & where,const media_node & node,int32 notificationType)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
StopWatching(const BMessenger & where)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
StopWatching(const BMessenger & where,int32 notificationType)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
StopWatching(const BMessenger & where,const media_node & node,int32 notificationType)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
RegisterNode(BMediaNode * node)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
RegisterNode(BMediaNode * node,media_addon_id addOnID,int32 flavorID)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
UnregisterNode(BMediaNode * node)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) {
2250b073975eSJérôme Duval PRINT(1, "Warning: BMediaRoster::UnregisterNode: node id %" B_PRId32
2251b073975eSJérôme Duval ", name '%s' already unregistered\n", node->ID(), node->Name());
22529e9417d2Sbeveloper return B_OK;
22539e9417d2Sbeveloper }
225454187cc6Sbeveloper if (node->fRefCount != 0) {
2255b073975eSJérôme Duval PRINT(1, "Warning: BMediaRoster::UnregisterNode: node id %" B_PRId32
2256b073975eSJérôme Duval ", name '%s' has local reference count of %" B_PRId32 "\n",
2257b073975eSJérôme Duval node->ID(), node->Name(), 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*
Roster(status_t * out_error)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*
CurrentRoster()235152a38012Sejakowatz BMediaRoster::CurrentRoster()
235252a38012Sejakowatz {
23539def3bf7SStephan Aßmus return sDefaultInstance;
235452a38012Sejakowatz }
235552a38012Sejakowatz
235652a38012Sejakowatz
235752a38012Sejakowatz status_t
SetTimeSourceFor(media_node_id node,media_node_id time_source)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
GetParameterWebFor(const media_node & node,BParameterWeb ** _web)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
StartControlPanel(const media_node & node,BMessenger * _messenger)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
GetDormantNodes(dormant_node_info * _info,int32 * _count,const media_format * hasInput,const media_format * hasOutput,const char * name,uint64 requireKinds,uint64 denyKinds)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
InstantiateDormantNode(media_addon_id addonID,int32 flavorID,team_id creator,media_node * _node)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
InstantiateDormantNode(const dormant_node_info & info,media_node * _node,uint32 flags)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
InstantiateDormantNode(const dormant_node_info & info,media_node * _node)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
GetDormantNodeFor(const media_node & node,dormant_node_info * _info)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
GetDormantFlavorInfo(media_addon_id addonID,int32 flavorID,dormant_flavor_info * _flavor)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
GetDormantFlavorInfoFor(const dormant_node_info & dormant,dormant_flavor_info * _flavor)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
GetLatencyFor(const media_node & producer,bigtime_t * _latency)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
2915*425ac1b6SAlexander von Gluck IV // printf("BMediaRoster::GetLatencyFor producer %ld has maximum latency %lld\n", producer.node, *out_latency);
2916aac800c2Sbeveloper return B_OK;
291752a38012Sejakowatz }
291852a38012Sejakowatz
291952a38012Sejakowatz
292052a38012Sejakowatz status_t
GetInitialLatencyFor(const media_node & producer,bigtime_t * _latency,uint32 * _flags)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
GetStartLatencyFor(const media_node & timeSource,bigtime_t * _latency)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
GetFileFormatsFor(const media_node & fileInterface,media_file_format * _formats,int32 * _numFormats)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
SetRefFor(const media_node & file_interface,const entry_ref & file,bool createAndTruncate,bigtime_t * _length)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
GetRefFor(const media_node & node,entry_ref * _file,BMimeType * mimeType)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
SniffRefFor(const media_node & file_interface,const entry_ref & file,BMimeType * mimeType,float * _capability)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
SniffRef(const entry_ref & file,uint64 requireNodeKinds,dormant_node_info * _node,BMimeType * mimeType)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
GetDormantNodeForType(const BMimeType & type,uint64 requireNodeKinds,dormant_node_info * _node)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
GetReadFileFormatsFor(const dormant_node_info & node,media_file_format * _readFormats,int32 readCount,int32 * _readCount)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
GetWriteFileFormatsFor(const dormant_node_info & node,media_file_format * _write_formats,int32 writeCount,int32 * _writeCount)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
GetFormatFor(const media_output & output,media_format * _format,uint32 flags)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
GetFormatFor(const media_input & input,media_format * _format,uint32 flags)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
GetFormatFor(const media_node & node,media_format * _format,float quality)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
GetNodeAttributesFor(const media_node & node,media_node_attribute * _array,size_t maxCount)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
NodeIDFor(port_id port)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
GetInstancesFor(media_addon_id addon,int32 flavor,media_node_id * _id,int32 * _count)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
IsRunning()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
AudioBufferSizeFor(int32 channelCount,uint32 sampleFormat,float frameRate,bus_type busKind)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
MediaFlags(media_flags cap,void * buffer,size_t maxSize)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
MessageReceived(BMessage * message)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
QuitRequested()358552a38012Sejakowatz BMediaRoster::QuitRequested()
358652a38012Sejakowatz {
358732afe10aSDario Casalinuovo CALLED();
358852a38012Sejakowatz return true;
358952a38012Sejakowatz }
359052a38012Sejakowatz
359134c72144SAxel Dörfler
359234c72144SAxel Dörfler BHandler*
ResolveSpecifier(BMessage * msg,int32 index,BMessage * specifier,int32 form,const char * property)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
GetSupportedSuites(BMessage * data)360152a38012Sejakowatz BMediaRoster::GetSupportedSuites(BMessage* data)
360252a38012Sejakowatz {
3603286a3c91SJérôme Duval return BLooper::GetSupportedSuites(data);
360452a38012Sejakowatz }
360552a38012Sejakowatz
360652a38012Sejakowatz
~BMediaRoster()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
_Reserved_MediaRoster_0(void *)361952a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_0(void*) { return B_ERROR; }
_Reserved_MediaRoster_1(void *)362052a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_1(void*) { return B_ERROR; }
_Reserved_MediaRoster_2(void *)362152a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_2(void*) { return B_ERROR; }
_Reserved_MediaRoster_3(void *)362252a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_3(void*) { return B_ERROR; }
_Reserved_MediaRoster_4(void *)362352a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_4(void*) { return B_ERROR; }
_Reserved_MediaRoster_5(void *)362452a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_5(void*) { return B_ERROR; }
_Reserved_MediaRoster_6(void *)362552a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_6(void*) { return B_ERROR; }
_Reserved_MediaRoster_7(void *)362652a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_7(void*) { return B_ERROR; }
362752a38012Sejakowatz
362852a38012Sejakowatz
BMediaRoster()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