134c72144SAxel Dörfler/*
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
9255a01c7Sbeveloper/*
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ßmuschar __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>
64b84955d4SBarrett#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örflernamespace BPrivate {
78f0a1eb2dSAxel Dörflernamespace media {
7952a38012Sejakowatz
80f0a1eb2dSAxel Dörfler
8132afe10aSDario Casalinuovostruct RosterNotification {
8232afe10aSDario Casalinuovo	BMessenger	messenger;
8332afe10aSDario Casalinuovo	int32		what;
8432afe10aSDario Casalinuovo};
8532afe10aSDario Casalinuovo
8605962bb1SDario Casalinuovo
8776889670SDario Casalinuovostruct SyncedMessage {
8876889670SDario Casalinuovo	BMessage* message;
8976889670SDario Casalinuovo};
9076889670SDario Casalinuovo
9176889670SDario Casalinuovo
9267060664SDario Casalinuovostruct LocalNode {
9367060664SDario Casalinuovo				LocalNode(BMediaNode* local_node)
9467060664SDario Casalinuovo					:
9567060664SDario Casalinuovo					node(local_node) {}
9667060664SDario Casalinuovo
9767060664SDario Casalinuovo				LocalNode()
9867060664SDario Casalinuovo					:
9967060664SDario Casalinuovo					node(NULL) {}
10067060664SDario Casalinuovo
10167060664SDario Casalinuovo	bool 		operator==(const LocalNode& a)
10267060664SDario Casalinuovo				{
10367060664SDario Casalinuovo					if (a.node == this->node)
10467060664SDario Casalinuovo						return true;
10567060664SDario Casalinuovo					return false;
10667060664SDario Casalinuovo				}
10767060664SDario Casalinuovo
10867060664SDario Casalinuovo	BMediaNode* node;
10967060664SDario Casalinuovo};
11067060664SDario Casalinuovo
11167060664SDario Casalinuovo
11232afe10aSDario Casalinuovostatic bool sServerIsUp = false;
11332afe10aSDario Casalinuovostatic List<RosterNotification> sNotificationList;
114d15321ffSDario Casalinuovostatic BLocker sInitLocker("BMediaRoster::Roster locker");
11567060664SDario Casalinuovostatic 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 Casalinuovoclass MediaRosterUndertaker {
1237d337b23SDario Casalinuovopublic:
124083314c2SAdrien Destugues	MediaRosterUndertaker()
125083314c2SAdrien Destugues	{
126083314c2SAdrien Destugues		gPortPool = new PortPool();
127083314c2SAdrien Destugues	}
128083314c2SAdrien Destugues
1297d337b23SDario Casalinuovo	~MediaRosterUndertaker()
1307d337b23SDario Casalinuovo	{
1317d337b23SDario Casalinuovo		BAutolock _(sInitLocker);
132ad7255c8SDario Casalinuovo		if (BMediaRoster::CurrentRoster() != NULL) {
13305962bb1SDario Casalinuovo
13467060664SDario Casalinuovo			// Detect any forgotten node
13567060664SDario Casalinuovo			if (sRegisteredNodes.CountItems() > 0) {
13667060664SDario Casalinuovo				for (int32 i = 0; i < sRegisteredNodes.CountItems(); i++) {
13767060664SDario Casalinuovo					LocalNode* node = NULL;
13867060664SDario Casalinuovo					sRegisteredNodes.Get(i, &node);
13967060664SDario Casalinuovo					if (node != NULL) {
14067060664SDario Casalinuovo						ERROR("BMediaRoster: Node with ID %" B_PRId32
14167060664SDario Casalinuovo							" was not released correctly\n", node->node->ID());
14267060664SDario Casalinuovo					}
14367060664SDario Casalinuovo				}
14467060664SDario Casalinuovo			}
14567060664SDario Casalinuovo
14605962bb1SDario Casalinuovo			if (be_app != NULL)
14705962bb1SDario Casalinuovo				be_app->UnregisterLooper(BMediaRoster::CurrentRoster());
14805962bb1SDario Casalinuovo
149ad7255c8SDario Casalinuovo			status_t err = B_ERROR;
150ad7255c8SDario Casalinuovo			thread_id roster = BMediaRoster::CurrentRoster()->Thread();
151ad7255c8SDario Casalinuovo
152ad7255c8SDario Casalinuovo			BMediaRoster::CurrentRoster()->PostMessage(B_QUIT_REQUESTED);
153ad7255c8SDario Casalinuovo
154ad7255c8SDario Casalinuovo			wait_for_thread(roster, &err);
155ad7255c8SDario Casalinuovo			if (err != B_OK)
156ad7255c8SDario Casalinuovo				ERROR("BMediaRoster: wait_for_thread returned error");
157472d26a3SRyan Leavengood
158472d26a3SRyan Leavengood			// Only now delete the port pool
159472d26a3SRyan Leavengood			delete gPortPool;
1607d337b23SDario Casalinuovo		}
1617d337b23SDario Casalinuovo	}
1627d337b23SDario Casalinuovo};
1637d337b23SDario Casalinuovo
1647d337b23SDario Casalinuovo
1657d337b23SDario Casalinuovostatic MediaRosterUndertaker sMediaRosterUndertaker;
1667d337b23SDario Casalinuovo
1679dec2310SAxel Dörfler}	// namespace media
1689dec2310SAxel Dörfler}	// namespace BPrivate
16952a38012Sejakowatz
1708b04ffc1Sbeveloperusing namespace BPrivate::media;
17152a38012Sejakowatz
1729dec2310SAxel Dörfler
17334c72144SAxel DörflerBMediaRosterEx::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) {
188d009f286SDario Casalinuovo		*_error = B_ERROR;
189d009f286SDario Casalinuovo	}
19032afe10aSDario Casalinuovo	sServerIsUp = BMediaRoster::IsRunning();
19132afe10aSDario Casalinuovo}
19232afe10aSDario Casalinuovo
19332afe10aSDario Casalinuovo
1947d337b23SDario Casalinuovovoid
1957d337b23SDario CasalinuovoBMediaRosterEx::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 Casalinuovostatus_t
20832afe10aSDario CasalinuovoBMediaRosterEx::BuildConnections()
20932afe10aSDario Casalinuovo{
21032afe10aSDario Casalinuovo	InitServerDataExchange();
211dcfb6bfcSJérôme Duval	// register this application with the media server
212dcfb6bfcSJérôme Duval	server_register_app_request request;
213dcfb6bfcSJérôme Duval	server_register_app_reply reply;
2149dec2310SAxel Dörfler	request.team = BPrivate::current_team();
215dcfb6bfcSJérôme Duval	request.messenger = BMessenger(NULL, this);
2169dec2310SAxel Dörfler	status_t status = QueryServer(SERVER_REGISTER_APP, &request,
2179dec2310SAxel Dörfler		sizeof(request), &reply, sizeof(reply));
2189dec2310SAxel Dörfler	if (status != B_OK)
21932afe10aSDario Casalinuovo		return B_MEDIA_SYSTEM_FAILURE;
22032afe10aSDario Casalinuovo
22132afe10aSDario Casalinuovo	return B_OK;
222dcfb6bfcSJérôme Duval}
223dcfb6bfcSJérôme Duval
22434c72144SAxel Dörfler
225e57acc3aSDario CasalinuovoBMediaRosterEx::~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 Casalinuovovoid
24467060664SDario CasalinuovoBMediaRosterEx::RegisterLocalNode(BMediaNode* node)
24567060664SDario Casalinuovo{
24667060664SDario Casalinuovo	sRegisteredNodes.Insert(LocalNode(node));
24767060664SDario Casalinuovo}
24867060664SDario Casalinuovo
24967060664SDario Casalinuovo
25067060664SDario Casalinuovovoid
25167060664SDario CasalinuovoBMediaRosterEx::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 Casalinuovovoid
26076889670SDario CasalinuovoBMediaRosterEx::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
27054187cc6Sbeveloperstatus_t
27134c72144SAxel DörflerBMediaRosterEx::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();
28534c72144SAxel Dörfler
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
29454187cc6Sbeveloperstatus_t
2959dec2310SAxel DörflerBMediaRosterEx::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
30754187cc6Sbeveloperstatus_t
3089dec2310SAxel DörflerBMediaRosterEx::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;
31334c72144SAxel Dörfler
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
32354187cc6Sbeveloperstatus_t
3249dec2310SAxel DörflerBMediaRosterEx::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;
32934c72144SAxel Dörfler
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}
33734c72144SAxel Dörfler
33834c72144SAxel Dörfler
3396aee58a4SJérôme Duvalstatus_t
3406aee58a4SJérôme DuvalBMediaRosterEx::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 %"
365332cc6bcSAxel Dörfler			B_PRId32 ", team %" B_PRId32 "!\n", node.node, node.port,
366332cc6bcSAxel Dörfler			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) {
371c74afb57SJérôme Duval			ERROR("BMediaRoster::ReleaseNodeAll FAILED, node %" B_PRId32 ", port %"
372c74afb57SJérôme Duval				B_PRId32 ", team %" B_PRId32 "!\n", node.node, node.port,
373c74afb57SJérôme Duval				BPrivate::current_team());
374c74afb57SJérôme Duval		}
3756aee58a4SJérôme Duval	}
3766aee58a4SJérôme Duval	return rv;
3776aee58a4SJérôme Duval}
3786aee58a4SJérôme Duval
3796aee58a4SJérôme Duval
38054187cc6Sbeveloperstatus_t
38154187cc6SbeveloperBMediaRosterEx::SetNodeCreator(media_node_id node, team_id creator)
38254187cc6Sbeveloper{
38354187cc6Sbeveloper	server_set_node_creator_request request;
38454187cc6Sbeveloper	server_set_node_creator_reply reply;
38534c72144SAxel Dörfler
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
3933620737cSbeveloperstatus_t
39434c72144SAxel DörflerBMediaRosterEx::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)
40952a38012Sejakowatz		return rv;
4108c6a6096Sbeveloper
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
4203620737cSbeveloperstatus_t
42134c72144SAxel DörflerBMediaRosterEx::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;
42634c72144SAxel Dörfler
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;
43734c72144SAxel Dörfler
43834c72144SAxel Dörfler	return QueryServer(SERVER_SET_NODE, &request, sizeof(request), &reply,
43934c72144SAxel Dörfler		sizeof(reply));
44052a38012Sejakowatz}
44152a38012Sejakowatz
44234c72144SAxel Dörfler
4433620737cSbeveloperstatus_t
44434c72144SAxel DörflerBMediaRosterEx::GetAllOutputs(const media_node& node, List<media_output>* list)
4453620737cSbeveloper{
4463620737cSbeveloper	int32 cookie;
4473620737cSbeveloper	status_t rv;
4483620737cSbeveloper	status_t result;
44934c72144SAxel Dörfler
450332cc6bcSAxel Dörfler	PRINT(4, "BMediaRosterEx::GetAllOutputs() node %" B_PRId32 ", port %"
451332cc6bcSAxel Dörfler		B_PRId32 "\n", node.node, node.port);
45265b73ae4SMarcus Overhagen
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	}
45834c72144SAxel Dörfler
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));
48534c72144SAxel Dörfler
4863620737cSbeveloper	return result;
4873620737cSbeveloper}
4883620737cSbeveloper
48934c72144SAxel Dörfler
4904d2d96e0Sbeveloperstatus_t
49134c72144SAxel DörflerBMediaRosterEx::GetAllOutputs(BBufferProducer* node, List<media_output>* list)
4924d2d96e0Sbeveloper{
4934d2d96e0Sbeveloper	int32 cookie;
4944d2d96e0Sbeveloper	status_t result;
49534c72144SAxel Dörfler
496332cc6bcSAxel Dörfler	PRINT(4, "BMediaRosterEx::GetAllOutputs() (by pointer) node %" B_PRId32
497332cc6bcSAxel Dörfler		", port %" B_PRId32 "\n", node->ID(), node->ControlPort());
49834c72144SAxel Dörfler
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
5203620737cSbeveloperstatus_t
52134c72144SAxel DörflerBMediaRosterEx::GetAllInputs(const media_node& node, List<media_input>* list)
5223620737cSbeveloper{
5233620737cSbeveloper	int32 cookie;
5243620737cSbeveloper	status_t rv;
5253620737cSbeveloper	status_t result;
5265ac4fbd7Sbeveloper
527332cc6bcSAxel Dörfler	PRINT(4, "BMediaRosterEx::GetAllInputs() node %" B_PRId32 ", port %"
528332cc6bcSAxel Dörfler		B_PRId32 "\n", node.node, node.port);
52965b73ae4SMarcus Overhagen
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	}
53534c72144SAxel Dörfler
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));
56234c72144SAxel Dörfler
5633620737cSbeveloper	return result;
5643620737cSbeveloper}
5653620737cSbeveloper
56634c72144SAxel Dörfler
5674d2d96e0Sbeveloperstatus_t
56834c72144SAxel DörflerBMediaRosterEx::GetAllInputs(BBufferConsumer* node, List<media_input>* list)
5694d2d96e0Sbeveloper{
5704d2d96e0Sbeveloper	int32 cookie;
5714d2d96e0Sbeveloper	status_t result;
57234c72144SAxel Dörfler
573332cc6bcSAxel Dörfler	PRINT(4, "BMediaRosterEx::GetAllInputs() (by pointer) node %" B_PRId32
574332cc6bcSAxel Dörfler		", port %" B_PRId32 "\n", node->ID(), node->ControlPort());
57534c72144SAxel Dörfler
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
5973620737cSbeveloperstatus_t
59834c72144SAxel DörflerBMediaRosterEx::PublishOutputs(const media_node& node, List<media_output>* list)
5993620737cSbeveloper{
6003620737cSbeveloper	server_publish_outputs_request request;
6013620737cSbeveloper	server_publish_outputs_reply reply;
60234c72144SAxel Dörfler	media_output* output;
60334c72144SAxel Dörfler	media_output* outputs;
6043620737cSbeveloper	int32 count;
605a7b41a96Sbeveloper	status_t rv;
60634c72144SAxel Dörfler
60776669a29Sbeveloper	count = list->CountItems();
608332cc6bcSAxel Dörfler	TRACE("PublishOutputs: publishing %" B_PRId32 "\n", count);
60934c72144SAxel Dörfler
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);
63034c72144SAxel Dörfler
63176669a29Sbeveloper	int i;
63276669a29Sbeveloper	for (i = 0, list->Rewind(); list->GetNext(&output); i++) {
63376669a29Sbeveloper		ASSERT(i < count);
6343620737cSbeveloper		outputs[i] = *output;
6353620737cSbeveloper	}
63634c72144SAxel Dörfler
63734c72144SAxel Dörfler	rv = QueryServer(SERVER_PUBLISH_OUTPUTS, &request, sizeof(request),
63834c72144SAxel Dörfler		&reply, sizeof(reply));
63934c72144SAxel Dörfler
640a7b41a96Sbeveloper	if (request.area != -1)
641a7b41a96Sbeveloper		delete_area(request.area);
64234c72144SAxel Dörfler
643a7b41a96Sbeveloper	return rv;
644