xref: /haiku/src/kits/media/MediaRoster.cpp (revision 425ac1b60a56f4df7a0e88bd784545c0ec4fa01f)
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, &notification.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 					&notification.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, &notification.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 					&notification.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, &current) != 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, &current) != 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, &current) != 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