xref: /haiku/src/kits/media/MediaRoster.cpp (revision 34c721444214fe3e783ecc57b3eb4627b1a18b77)
1255a01c7Sbeveloper /*
2*34c72144SAxel Dörfler  * Copyright 2008 Maurice Kalinowski, haiku@kaldience.com
3*34c72144SAxel Dörfler  * Copyright 2009, Axel Dörfler, axeld@pinc-software.de.
4*34c72144SAxel Dörfler  *
5*34c72144SAxel Dörfler  * All rights reserved. Distributed under the terms of the MIT License.
6*34c72144SAxel Dörfler  */
7*34c72144SAxel Dörfler 
8*34c72144SAxel Dörfler /*
965b73ae4SMarcus Overhagen  * Copyright (c) 2002-2006 Marcus Overhagen <Marcus@Overhagen.de>
10255a01c7Sbeveloper  *
11255a01c7Sbeveloper  * Permission is hereby granted, free of charge, to any person obtaining
12255a01c7Sbeveloper  * a copy of this software and associated documentation files or portions
13255a01c7Sbeveloper  * thereof (the "Software"), to deal in the Software without restriction,
14255a01c7Sbeveloper  * including without limitation the rights to use, copy, modify, merge,
15255a01c7Sbeveloper  * publish, distribute, sublicense, and/or sell copies of the Software,
16255a01c7Sbeveloper  * and to permit persons to whom the Software is furnished to do so, subject
17255a01c7Sbeveloper  * to the following conditions:
18255a01c7Sbeveloper  *
19255a01c7Sbeveloper  *  * Redistributions of source code must retain the above copyright notice,
20255a01c7Sbeveloper  *    this list of conditions and the following disclaimer.
21255a01c7Sbeveloper  *
22255a01c7Sbeveloper  *  * Redistributions in binary form must reproduce the above copyright notice
23255a01c7Sbeveloper  *    in the  binary, as well as this list of conditions and the following
24255a01c7Sbeveloper  *    disclaimer in the documentation and/or other materials provided with
25255a01c7Sbeveloper  *    the distribution.
26255a01c7Sbeveloper  *
27255a01c7Sbeveloper  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
28255a01c7Sbeveloper  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
29255a01c7Sbeveloper  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
30255a01c7Sbeveloper  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
31255a01c7Sbeveloper  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
32255a01c7Sbeveloper  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
33255a01c7Sbeveloper  * THE SOFTWARE.
34255a01c7Sbeveloper  *
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 
4231cf24c1SMarcus Overhagen //#define DEBUG 7
4352a38012Sejakowatz #include <MediaRoster.h>
448b940bb4SStephan Aßmus 
45a715f908SStephan Aßmus #include <new>
46a715f908SStephan Aßmus 
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>
556938364bSMaurice Kalinowski #include <StopWatch.h>
5652a38012Sejakowatz #include <String.h>
5752a38012Sejakowatz #include <TimeSource.h>
588b940bb4SStephan Aßmus 
5952a38012Sejakowatz #include "debug.h"
608b04ffc1Sbeveloper #include "MediaRosterEx.h"
6140f36b03Sbeveloper #include "MediaMisc.h"
6252a38012Sejakowatz #include "PortPool.h"
630a483e72SIngo Weinhold #include "ServerInterface.h"
64f4925104Sbeveloper #include "DataExchange.h"
6516b7eea4Sbeveloper #include "DormantNodeManager.h"
66f4925104Sbeveloper #include "Notifications.h"
67835140c8Sbeveloper #include "TimeSourceObjectManager.h"
6852a38012Sejakowatz 
69f4925104Sbeveloper namespace BPrivate { namespace media {
7052a38012Sejakowatz 
7152a38012Sejakowatz 	// the BMediaRoster destructor is private,
7252a38012Sejakowatz 	// but _DefaultDeleter is a friend class of
7352a38012Sejakowatz 	// the BMediaRoster an thus can delete it
748b04ffc1Sbeveloper 	class DefaultDeleter
7552a38012Sejakowatz 	{
7652a38012Sejakowatz 	public:
778b04ffc1Sbeveloper 		~DefaultDeleter()
786396865dSbeveloper 		{
799def3bf7SStephan Aßmus 			if (BMediaRoster::sDefaultInstance) {
809def3bf7SStephan Aßmus 				BMediaRoster::sDefaultInstance->Lock();
819def3bf7SStephan Aßmus 				BMediaRoster::sDefaultInstance->Quit();
826396865dSbeveloper 			}
836396865dSbeveloper 		}
848b04ffc1Sbeveloper 	};
8552a38012Sejakowatz 
868b04ffc1Sbeveloper } } // BPrivate::media
878b04ffc1Sbeveloper using namespace BPrivate::media;
8852a38012Sejakowatz 
898b04ffc1Sbeveloper // DefaultDeleter will delete the BMediaRoster object in it's destructor.
908b04ffc1Sbeveloper DefaultDeleter _deleter;
9152a38012Sejakowatz 
92*34c72144SAxel Dörfler BMediaRosterEx::BMediaRosterEx(status_t* _error)
93dcfb6bfcSJérôme Duval 	: BMediaRoster()
94dcfb6bfcSJérôme Duval {
95dcfb6bfcSJérôme Duval 	status_t rv;
96dcfb6bfcSJérôme Duval 	// register this application with the media server
97dcfb6bfcSJérôme Duval 	server_register_app_request request;
98dcfb6bfcSJérôme Duval 	server_register_app_reply reply;
99dcfb6bfcSJérôme Duval 	request.team = team;
100dcfb6bfcSJérôme Duval 	request.messenger = BMessenger(NULL, this);
101*34c72144SAxel Dörfler 	rv = QueryServer(SERVER_REGISTER_APP, &request, sizeof(request), &reply,
102*34c72144SAxel Dörfler 		sizeof(reply));
103a7fb4c16SMaurice Kalinowski 	if (rv != B_OK)
104*34c72144SAxel Dörfler 		*_error = B_MEDIA_SYSTEM_FAILURE;
105a7fb4c16SMaurice Kalinowski 	else
106*34c72144SAxel Dörfler 		*_error = B_OK;
107dcfb6bfcSJérôme Duval }
108dcfb6bfcSJérôme Duval 
109*34c72144SAxel Dörfler 
1103620737cSbeveloper status_t
11154187cc6Sbeveloper BMediaRosterEx::SaveNodeConfiguration(BMediaNode* node)
11254187cc6Sbeveloper {
11354187cc6Sbeveloper 	BMediaAddOn *addon;
11454187cc6Sbeveloper 	media_addon_id addonid;
11554187cc6Sbeveloper 	int32 flavorid;
11654187cc6Sbeveloper 	addon = node->AddOn(&flavorid);
11754187cc6Sbeveloper 	if (!addon) {
1188056f0dbSStephan Aßmus 		// NOTE: This node could have been created by an application,
1198056f0dbSStephan Aßmus 		// it does not mean there is an error.
120*34c72144SAxel Dörfler 		// TODO: this check incorrectly triggers on BeOS R5 BT848 node
1218056f0dbSStephan Aßmus 		TRACE("BMediaRosterEx::SaveNodeConfiguration node %ld not instantiated "
1228056f0dbSStephan Aßmus 			"from BMediaAddOn!\n", node->ID());
12354187cc6Sbeveloper 		return B_ERROR;
12454187cc6Sbeveloper 	}
12554187cc6Sbeveloper 	addonid = addon->AddonID();
12654187cc6Sbeveloper 
127*34c72144SAxel Dörfler 	// TODO: fix this
1288056f0dbSStephan Aßmus 	printf("### BMediaRosterEx::SaveNodeConfiguration should save addon-id "
1298056f0dbSStephan Aßmus 		"%ld, flavor-id %ld config NOW!\n", addonid, flavorid);
13054187cc6Sbeveloper 	return B_OK;
13154187cc6Sbeveloper }
13254187cc6Sbeveloper 
133*34c72144SAxel Dörfler 
13454187cc6Sbeveloper status_t
1358b940bb4SStephan Aßmus BMediaRosterEx::LoadNodeConfiguration(media_addon_id addonid, int32 flavorid,
1368b940bb4SStephan Aßmus 	BMessage *out_msg)
13754187cc6Sbeveloper {
138*34c72144SAxel Dörfler 	// TODO: fix this
13954187cc6Sbeveloper 	out_msg->MakeEmpty(); // to be fully R5 compliant
1408b940bb4SStephan Aßmus 	printf("### BMediaRosterEx::LoadNodeConfiguration should load addon-id "
1418b940bb4SStephan Aßmus 		"%ld, flavor-id %ld config NOW!\n", addonid, flavorid);
14254187cc6Sbeveloper 	return B_OK;
14354187cc6Sbeveloper }
14454187cc6Sbeveloper 
145*34c72144SAxel Dörfler 
14654187cc6Sbeveloper status_t
147*34c72144SAxel Dörfler BMediaRosterEx::IncrementAddonFlavorInstancesCount(media_addon_id addonid,
148*34c72144SAxel Dörfler 	int32 flavorid)
14954187cc6Sbeveloper {
15073794717Sbeveloper 	server_change_addon_flavor_instances_count_request request;
15173794717Sbeveloper 	server_change_addon_flavor_instances_count_reply reply;
15273794717Sbeveloper 
15373794717Sbeveloper 	request.addonid = addonid;
15473794717Sbeveloper 	request.flavorid = flavorid;
15573794717Sbeveloper 	request.delta = 1;
15673794717Sbeveloper 	request.team = team;
157*34c72144SAxel Dörfler 	return QueryServer(SERVER_CHANGE_ADDON_FLAVOR_INSTANCES_COUNT, &request,
158*34c72144SAxel Dörfler 		sizeof(request), &reply, sizeof(reply));
15954187cc6Sbeveloper }
16054187cc6Sbeveloper 
161*34c72144SAxel Dörfler 
16254187cc6Sbeveloper status_t
163*34c72144SAxel Dörfler BMediaRosterEx::DecrementAddonFlavorInstancesCount(media_addon_id addonid,
164*34c72144SAxel Dörfler 	int32 flavorid)
16554187cc6Sbeveloper {
16673794717Sbeveloper 	server_change_addon_flavor_instances_count_request request;
16773794717Sbeveloper 	server_change_addon_flavor_instances_count_reply reply;
16873794717Sbeveloper 
16973794717Sbeveloper 	request.addonid = addonid;
17073794717Sbeveloper 	request.flavorid = flavorid;
17173794717Sbeveloper 	request.delta = -1;
17273794717Sbeveloper 	request.team = team;
173*34c72144SAxel Dörfler 	return QueryServer(SERVER_CHANGE_ADDON_FLAVOR_INSTANCES_COUNT, &request,
174*34c72144SAxel Dörfler 		sizeof(request), &reply, sizeof(reply));
17554187cc6Sbeveloper }
17654187cc6Sbeveloper 
177*34c72144SAxel Dörfler 
17854187cc6Sbeveloper status_t
17954187cc6Sbeveloper BMediaRosterEx::SetNodeCreator(media_node_id node, team_id creator)
18054187cc6Sbeveloper {
18154187cc6Sbeveloper 	server_set_node_creator_request request;
18254187cc6Sbeveloper 	server_set_node_creator_reply reply;
18354187cc6Sbeveloper 
18454187cc6Sbeveloper 	request.node = node;
18554187cc6Sbeveloper 	request.creator = creator;
186*34c72144SAxel Dörfler 	return QueryServer(SERVER_SET_NODE_CREATOR, &request, sizeof(request),
187*34c72144SAxel Dörfler 		&reply, sizeof(reply));
18854187cc6Sbeveloper }
18954187cc6Sbeveloper 
190*34c72144SAxel Dörfler 
19154187cc6Sbeveloper status_t
192*34c72144SAxel Dörfler BMediaRosterEx::GetNode(node_type type, media_node* out_node,
193*34c72144SAxel Dörfler 	int32* out_input_id, BString* out_input_name)
19452a38012Sejakowatz {
19552a38012Sejakowatz 	if (out_node == NULL)
19652a38012Sejakowatz 		return B_BAD_VALUE;
19752a38012Sejakowatz 
1988c6a6096Sbeveloper 	server_get_node_request request;
1998c6a6096Sbeveloper 	server_get_node_reply reply;
20052a38012Sejakowatz 	status_t rv;
20152a38012Sejakowatz 
2028c6a6096Sbeveloper 	request.type = type;
2039e9417d2Sbeveloper 	request.team = team;
204*34c72144SAxel Dörfler 	rv = QueryServer(SERVER_GET_NODE, &request, sizeof(request), &reply,
205*34c72144SAxel Dörfler 		sizeof(reply));
2068c6a6096Sbeveloper 	if (rv != B_OK)
2078c6a6096Sbeveloper 		return rv;
20852a38012Sejakowatz 
20952a38012Sejakowatz 	*out_node = reply.node;
21052a38012Sejakowatz 	if (out_input_id)
21152a38012Sejakowatz 		*out_input_id = reply.input_id;
21252a38012Sejakowatz 	if (out_input_name)
21352a38012Sejakowatz 		*out_input_name = reply.input_name;
2148c6a6096Sbeveloper 	return rv;
21552a38012Sejakowatz }
21652a38012Sejakowatz 
217*34c72144SAxel Dörfler 
2183620737cSbeveloper status_t
219*34c72144SAxel Dörfler BMediaRosterEx::SetNode(node_type type, const media_node* node,
220*34c72144SAxel Dörfler 	const dormant_node_info* info, const media_input* input)
22152a38012Sejakowatz {
2228c6a6096Sbeveloper 	server_set_node_request request;
2238c6a6096Sbeveloper 	server_set_node_reply reply;
22452a38012Sejakowatz 
2258c6a6096Sbeveloper 	request.type = type;
226*34c72144SAxel Dörfler 	request.use_node = node != NULL;
227*34c72144SAxel Dörfler 	if (node != NULL)
2288c6a6096Sbeveloper 		request.node = *node;
229*34c72144SAxel Dörfler 	request.use_dni = info != NULL;
230*34c72144SAxel Dörfler 	if (info != NULL)
2318c6a6096Sbeveloper 		request.dni = *info;
232*34c72144SAxel Dörfler 	request.use_input = input != NULL;
233*34c72144SAxel Dörfler 	if (input != NULL)
2348c6a6096Sbeveloper 		request.input = *input;
23552a38012Sejakowatz 
236*34c72144SAxel Dörfler 	return QueryServer(SERVER_SET_NODE, &request, sizeof(request), &reply,
237*34c72144SAxel Dörfler 		sizeof(reply));
23852a38012Sejakowatz }
23952a38012Sejakowatz 
240*34c72144SAxel Dörfler 
2413620737cSbeveloper status_t
2428b04ffc1Sbeveloper BMediaRosterEx::GetAllOutputs(const media_node& node, List<media_output>* list)
2433620737cSbeveloper {
2443620737cSbeveloper 	int32 cookie;
2453620737cSbeveloper 	status_t rv;
2463620737cSbeveloper 	status_t result;
2473620737cSbeveloper 
248*34c72144SAxel Dörfler 	PRINT(4, "BMediaRosterEx::GetAllOutputs() node %ld, port %ld\n", node.node,
249*34c72144SAxel Dörfler 		node.port);
2505ac4fbd7Sbeveloper 
25165b73ae4SMarcus Overhagen 	if (!(node.kind & B_BUFFER_PRODUCER)) {
252*34c72144SAxel Dörfler 		ERROR("BMediaRosterEx::GetAllOutputs: node %ld is not a "
253*34c72144SAxel Dörfler 			"B_BUFFER_PRODUCER\n", node.node);
25465b73ae4SMarcus Overhagen 		return B_MEDIA_BAD_NODE;
25565b73ae4SMarcus Overhagen 	}
25665b73ae4SMarcus Overhagen 
2573620737cSbeveloper 	result = B_OK;
2583620737cSbeveloper 	cookie = 0;
25976669a29Sbeveloper 	list->MakeEmpty();
2603620737cSbeveloper 	for (;;) {
2613620737cSbeveloper 		producer_get_next_output_request request;
2623620737cSbeveloper 		producer_get_next_output_reply reply;
2633620737cSbeveloper 		request.cookie = cookie;
264*34c72144SAxel Dörfler 		rv = QueryPort(node.port, PRODUCER_GET_NEXT_OUTPUT, &request,
265*34c72144SAxel Dörfler 			sizeof(request), &reply, sizeof(reply));
2663620737cSbeveloper 		if (rv != B_OK)
2673620737cSbeveloper 			break;
2683620737cSbeveloper 		cookie = reply.cookie;
26976669a29Sbeveloper 		if (!list->Insert(reply.output)) {
2705ac4fbd7Sbeveloper 			ERROR("GetAllOutputs: list->Insert failed\n");
2713620737cSbeveloper 			result = B_ERROR;
2723620737cSbeveloper 		}
2735ac4fbd7Sbeveloper 		#if DEBUG >= 3
2745ac4fbd7Sbeveloper 			PRINT(3," next cookie %ld, ", cookie);
2755ac4fbd7Sbeveloper 			PRINT_OUTPUT("output ", reply.output);
2765ac4fbd7Sbeveloper 		#endif
2773620737cSbeveloper 	}
2783620737cSbeveloper 
2793620737cSbeveloper 	producer_dispose_output_cookie_request request;
2803620737cSbeveloper 	producer_dispose_output_cookie_reply reply;
281*34c72144SAxel Dörfler 	QueryPort(node.port, PRODUCER_DISPOSE_OUTPUT_COOKIE, &request,
282*34c72144SAxel Dörfler 		sizeof(request), &reply, sizeof(reply));
2833620737cSbeveloper 
2843620737cSbeveloper 	return result;
2853620737cSbeveloper }
2863620737cSbeveloper 
287*34c72144SAxel Dörfler 
2883620737cSbeveloper status_t
2894d2d96e0Sbeveloper BMediaRosterEx::GetAllOutputs(BBufferProducer* node, List<media_output>* list)
2904d2d96e0Sbeveloper {
2914d2d96e0Sbeveloper 	int32 cookie;
2924d2d96e0Sbeveloper 	status_t result;
2934d2d96e0Sbeveloper 
2944d2d96e0Sbeveloper 	PRINT(4, "BMediaRosterEx::GetAllOutputs() (by pointer) node %ld, port %ld\n", node->ID(), node->ControlPort());
2954d2d96e0Sbeveloper 
2964d2d96e0Sbeveloper 	result = B_OK;
2974d2d96e0Sbeveloper 	cookie = 0;
2984d2d96e0Sbeveloper 	list->MakeEmpty();
2994d2d96e0Sbeveloper 	for (;;) {
3004d2d96e0Sbeveloper 		media_output output;
3014d2d96e0Sbeveloper 		if (B_OK != node->GetNextOutput(&cookie, &output))
3024d2d96e0Sbeveloper 			break;
3034d2d96e0Sbeveloper 		if (!list->Insert(output)) {
3044d2d96e0Sbeveloper 			ERROR("GetAllOutputs: list->Insert failed\n");
3054d2d96e0Sbeveloper 			result = B_ERROR;
3064d2d96e0Sbeveloper 		}
3074d2d96e0Sbeveloper 		#if DEBUG >= 3
3084d2d96e0Sbeveloper 			PRINT(3," next cookie %ld, ", cookie);
3094d2d96e0Sbeveloper 			PRINT_OUTPUT("output ", output);
3104d2d96e0Sbeveloper 		#endif
3114d2d96e0Sbeveloper 	}
3124d2d96e0Sbeveloper 	node->DisposeOutputCookie(cookie);
3134d2d96e0Sbeveloper 	return result;
3144d2d96e0Sbeveloper }
3154d2d96e0Sbeveloper 
316*34c72144SAxel Dörfler 
3174d2d96e0Sbeveloper status_t
3188b04ffc1Sbeveloper BMediaRosterEx::GetAllInputs(const media_node& node, List<media_input>* list)
3193620737cSbeveloper {
3203620737cSbeveloper 	int32 cookie;
3213620737cSbeveloper 	status_t rv;
3223620737cSbeveloper 	status_t result;
3233620737cSbeveloper 
324*34c72144SAxel Dörfler 	PRINT(4, "BMediaRosterEx::GetAllInputs() node %ld, port %ld\n", node.node,
325*34c72144SAxel Dörfler 		node.port);
3265ac4fbd7Sbeveloper 
32765b73ae4SMarcus Overhagen 	if (!(node.kind & B_BUFFER_CONSUMER)) {
328*34c72144SAxel Dörfler 		ERROR("BMediaRosterEx::GetAllInputs: node %ld is not a "
329*34c72144SAxel Dörfler 			"B_BUFFER_CONSUMER\n", node.node);
33065b73ae4SMarcus Overhagen 		return B_MEDIA_BAD_NODE;
33165b73ae4SMarcus Overhagen 	}
33265b73ae4SMarcus Overhagen 
3333620737cSbeveloper 	result = B_OK;
3343620737cSbeveloper 	cookie = 0;
33576669a29Sbeveloper 	list->MakeEmpty();
3363620737cSbeveloper 	for (;;) {
3373620737cSbeveloper 		consumer_get_next_input_request request;
3383620737cSbeveloper 		consumer_get_next_input_reply reply;
3393620737cSbeveloper 		request.cookie = cookie;
340*34c72144SAxel Dörfler 		rv = QueryPort(node.port, CONSUMER_GET_NEXT_INPUT, &request,
341*34c72144SAxel Dörfler 			sizeof(request), &reply, sizeof(reply));
3423620737cSbeveloper 		if (rv != B_OK)
3433620737cSbeveloper 			break;
3443620737cSbeveloper 		cookie = reply.cookie;
34576669a29Sbeveloper 		if (!list->Insert(reply.input)) {
3465ac4fbd7Sbeveloper 			ERROR("GetAllInputs: list->Insert failed\n");
3473620737cSbeveloper 			result = B_ERROR;
3483620737cSbeveloper 		}
3495ac4fbd7Sbeveloper 		#if DEBUG >= 3
3505ac4fbd7Sbeveloper 			PRINT(3," next cookie %ld, ", cookie);
3515ac4fbd7Sbeveloper 			PRINT_OUTPUT("input ", reply.input);
3525ac4fbd7Sbeveloper 		#endif
3533620737cSbeveloper 	}
3543620737cSbeveloper 
3553620737cSbeveloper 	consumer_dispose_input_cookie_request request;
3563620737cSbeveloper 	consumer_dispose_input_cookie_reply reply;
357*34c72144SAxel Dörfler 	QueryPort(node.port, CONSUMER_DISPOSE_INPUT_COOKIE, &request,
358*34c72144SAxel Dörfler 		sizeof(request), &reply, sizeof(reply));
3593620737cSbeveloper 
3603620737cSbeveloper 	return result;
3613620737cSbeveloper }
3623620737cSbeveloper 
363*34c72144SAxel Dörfler 
3643620737cSbeveloper status_t
3654d2d96e0Sbeveloper BMediaRosterEx::GetAllInputs(BBufferConsumer* node, List<media_input>* list)
3664d2d96e0Sbeveloper {
3674d2d96e0Sbeveloper 	int32 cookie;
3684d2d96e0Sbeveloper 	status_t result;
3694d2d96e0Sbeveloper 
3704d2d96e0Sbeveloper 	PRINT(4, "BMediaRosterEx::GetAllInputs() (by pointer) node %ld, port %ld\n", node->ID(), node->ControlPort());
3714d2d96e0Sbeveloper 
3724d2d96e0Sbeveloper 	result = B_OK;
3734d2d96e0Sbeveloper 	cookie = 0;
3744d2d96e0Sbeveloper 	list->MakeEmpty();
3754d2d96e0Sbeveloper 	for (;;) {
3764d2d96e0Sbeveloper 		media_input input;
3774d2d96e0Sbeveloper 		if (B_OK != node->GetNextInput(&cookie, &input))
3784d2d96e0Sbeveloper 			break;
3794d2d96e0Sbeveloper 		if (!list->Insert(input)) {
3804d2d96e0Sbeveloper 			ERROR("GetAllInputs: list->Insert failed\n");
3814d2d96e0Sbeveloper 			result = B_ERROR;
3824d2d96e0Sbeveloper 		}
3834d2d96e0Sbeveloper 		#if DEBUG >= 3
3844d2d96e0Sbeveloper 			PRINT(3," next cookie %ld, ", cookie);
3854d2d96e0Sbeveloper 			PRINT_INPUT("input ", input);
3864d2d96e0Sbeveloper 		#endif
3874d2d96e0Sbeveloper 	}
3884d2d96e0Sbeveloper 	node->DisposeInputCookie(cookie);
3894d2d96e0Sbeveloper 	return result;
3904d2d96e0Sbeveloper }
3914d2d96e0Sbeveloper 
392*34c72144SAxel Dörfler 
3934d2d96e0Sbeveloper status_t
3948b04ffc1Sbeveloper BMediaRosterEx::PublishOutputs(const media_node& node, List<media_output>* list)
3953620737cSbeveloper {
3963620737cSbeveloper 	server_publish_outputs_request request;
3973620737cSbeveloper 	server_publish_outputs_reply reply;
3983620737cSbeveloper 	media_output* output;
3993620737cSbeveloper 	media_output* outputs;
4003620737cSbeveloper 	int32 count;
401a7b41a96Sbeveloper 	status_t rv;
4023620737cSbeveloper 
40376669a29Sbeveloper 	count = list->CountItems();
4043620737cSbeveloper 	TRACE("PublishOutputs: publishing %ld\n", count);
4053620737cSbeveloper 
4063620737cSbeveloper 	request.node = node;
4073620737cSbeveloper 	request.count = count;
4083620737cSbeveloper 	if (count > MAX_OUTPUTS) {
4093620737cSbeveloper 		void *start_addr;
4103620737cSbeveloper 		size_t size;
41140f36b03Sbeveloper 		size = ROUND_UP_TO_PAGE(count * sizeof(media_output));
412*34c72144SAxel Dörfler 		request.area = create_area("publish outputs", &start_addr,
413*34c72144SAxel Dörfler 			B_ANY_ADDRESS, size, B_NO_LOCK, B_READ_AREA | B_WRITE_AREA);
4143620737cSbeveloper 		if (request.area < B_OK) {
415*34c72144SAxel Dörfler 			ERROR("PublishOutputs: failed to create area, %#lx\n",
416*34c72144SAxel Dörfler 				request.area);
4173620737cSbeveloper 			return (status_t)request.area;
4183620737cSbeveloper 		}
4193620737cSbeveloper 		outputs = static_cast<media_output *>(start_addr);
4203620737cSbeveloper 	} else {
4213620737cSbeveloper 		request.area = -1;
4223620737cSbeveloper 		outputs = request.outputs;
4233620737cSbeveloper 	}
42476669a29Sbeveloper 	TRACE("PublishOutputs: area %ld\n", request.area);
4253620737cSbeveloper 
42676669a29Sbeveloper 	int i;
42776669a29Sbeveloper 	for (i = 0, list->Rewind(); list->GetNext(&output); i++) {
42876669a29Sbeveloper 		ASSERT(i < count);
4293620737cSbeveloper 		outputs[i] = *output;
4303620737cSbeveloper 	}
4313620737cSbeveloper 
432*34c72144SAxel Dörfler 	rv = QueryServer(SERVER_PUBLISH_OUTPUTS, &request, sizeof(request),
433*34c72144SAxel Dörfler 		&reply, sizeof(reply));
434a7b41a96Sbeveloper 
435a7b41a96Sbeveloper 	if (request.area != -1)
436a7b41a96Sbeveloper 		delete_area(request.area);
437a7b41a96Sbeveloper 
438a7b41a96Sbeveloper 	return rv;
4393620737cSbeveloper }
4403620737cSbeveloper 
441*34c72144SAxel Dörfler 
4423620737cSbeveloper status_t
4438b04ffc1Sbeveloper BMediaRosterEx::PublishInputs(const media_node& node, List<media_input>* list)
4443620737cSbeveloper {
4453620737cSbeveloper 	server_publish_inputs_request request;
4463620737cSbeveloper 	server_publish_inputs_reply reply;
4473620737cSbeveloper 	media_input* input;
4483620737cSbeveloper 	media_input* inputs;
4493620737cSbeveloper 	int32 count;
450a7b41a96Sbeveloper 	status_t rv;
4513620737cSbeveloper 
45276669a29Sbeveloper 	count = list->CountItems();
4533620737cSbeveloper 	TRACE("PublishInputs: publishing %ld\n", count);
4543620737cSbeveloper 
4553620737cSbeveloper 	request.node = node;
4563620737cSbeveloper 	request.count = count;
4573620737cSbeveloper 	if (count > MAX_INPUTS) {
4583620737cSbeveloper 		void* start_addr;
4593620737cSbeveloper 		size_t size;
46040f36b03Sbeveloper 		size = ROUND_UP_TO_PAGE(count * sizeof(media_input));
461*34c72144SAxel Dörfler 		request.area = create_area("publish inputs", &start_addr,
462*34c72144SAxel Dörfler 			B_ANY_ADDRESS, size, B_NO_LOCK, B_READ_AREA | B_WRITE_AREA);
4633620737cSbeveloper 		if (request.area < B_OK) {
4645ac4fbd7Sbeveloper 			ERROR("PublishInputs: failed to create area, %#lx\n", request.area);
4653620737cSbeveloper 			return (status_t)request.area;
4663620737cSbeveloper 		}
4673620737cSbeveloper 		inputs = static_cast<media_input *>(start_addr);
4683620737cSbeveloper 	} else {
4693620737cSbeveloper 		request.area = -1;
4703620737cSbeveloper 		inputs = request.inputs;
4713620737cSbeveloper 	}
47276669a29Sbeveloper 	TRACE("PublishInputs: area %ld\n", request.area);
4733620737cSbeveloper 
47476669a29Sbeveloper 	int i;
47576669a29Sbeveloper 	for (i = 0, list->Rewind(); list->GetNext(&input); i++) {
47676669a29Sbeveloper 		ASSERT(i < count);
4773620737cSbeveloper 		inputs[i] = *input;
4783620737cSbeveloper 	}
4793620737cSbeveloper 
480*34c72144SAxel Dörfler 	rv = QueryServer(SERVER_PUBLISH_INPUTS, &request, sizeof(request),
481*34c72144SAxel Dörfler 		&reply, sizeof(reply));
482a7b41a96Sbeveloper 
483a7b41a96Sbeveloper 	if (request.area != -1)
484a7b41a96Sbeveloper 		delete_area(request.area);
485a7b41a96Sbeveloper 
486a7b41a96Sbeveloper 	return rv;
4873620737cSbeveloper }
4883620737cSbeveloper 
489*34c72144SAxel Dörfler 
490*34c72144SAxel Dörfler BTimeSource*
491*34c72144SAxel Dörfler BMediaRosterEx::MakeTimeSourceObject(media_node_id timesourceID)
492*34c72144SAxel Dörfler {
493*34c72144SAxel Dörfler 	BTimeSource* source;
494*34c72144SAxel Dörfler 	media_node clone;
495*34c72144SAxel Dörfler 	status_t rv;
496*34c72144SAxel Dörfler 
497*34c72144SAxel Dörfler 	rv = GetNodeFor(timesourceID, &clone);
498*34c72144SAxel Dörfler 	if (rv != B_OK) {
499*34c72144SAxel Dörfler 		ERROR("BMediaRosterEx::MakeTimeSourceObject: GetNodeFor failed\n");
500*34c72144SAxel Dörfler 		return NULL;
501*34c72144SAxel Dörfler 	}
502*34c72144SAxel Dörfler 
503*34c72144SAxel Dörfler 	source = _TimeSourceObjectManager->GetTimeSource(clone);
504*34c72144SAxel Dörfler 	if (source == NULL) {
505*34c72144SAxel Dörfler 		ERROR("BMediaRosterEx::MakeTimeSourceObject: GetTimeSource failed\n");
506*34c72144SAxel Dörfler 		return NULL;
507*34c72144SAxel Dörfler 	}
508*34c72144SAxel Dörfler 
509*34c72144SAxel Dörfler 	// TODO: release?
510*34c72144SAxel Dörfler 	ReleaseNode(clone);
511*34c72144SAxel Dörfler 
512*34c72144SAxel Dörfler 	return source;
513*34c72144SAxel Dörfler }
514*34c72144SAxel Dörfler 
515*34c72144SAxel Dörfler 
516*34c72144SAxel Dörfler //	#pragma mark - public BMediaRoster
517*34c72144SAxel Dörfler 
51852a38012Sejakowatz 
51952a38012Sejakowatz status_t
520*34c72144SAxel Dörfler BMediaRoster::GetVideoInput(media_node* _node)
52152a38012Sejakowatz {
52252a38012Sejakowatz 	CALLED();
523*34c72144SAxel Dörfler 	return MediaRosterEx(this)->GetNode(VIDEO_INPUT, _node);
52452a38012Sejakowatz }
52552a38012Sejakowatz 
52652a38012Sejakowatz 
52752a38012Sejakowatz status_t
528*34c72144SAxel Dörfler BMediaRoster::GetAudioInput(media_node* _node)
52952a38012Sejakowatz {
53052a38012Sejakowatz 	CALLED();
531*34c72144SAxel Dörfler 	return MediaRosterEx(this)->GetNode(AUDIO_INPUT, _node);
53252a38012Sejakowatz }
53352a38012Sejakowatz 
53452a38012Sejakowatz 
53552a38012Sejakowatz status_t
536*34c72144SAxel Dörfler BMediaRoster::GetVideoOutput(media_node* _node)
53752a38012Sejakowatz {
53852a38012Sejakowatz 	CALLED();
539*34c72144SAxel Dörfler 	return MediaRosterEx(this)->GetNode(VIDEO_OUTPUT, _node);
54052a38012Sejakowatz }
54152a38012Sejakowatz 
54252a38012Sejakowatz 
54352a38012Sejakowatz status_t
544*34c72144SAxel Dörfler BMediaRoster::GetAudioMixer(media_node* _node)
54552a38012Sejakowatz {
54652a38012Sejakowatz 	CALLED();
547*34c72144SAxel Dörfler 	return MediaRosterEx(this)->GetNode(AUDIO_MIXER, _node);
54852a38012Sejakowatz }
54952a38012Sejakowatz 
55052a38012Sejakowatz 
55152a38012Sejakowatz status_t
552*34c72144SAxel Dörfler BMediaRoster::GetAudioOutput(media_node* _node)
55352a38012Sejakowatz {
55452a38012Sejakowatz 	CALLED();
555*34c72144SAxel Dörfler 	return MediaRosterEx(this)->GetNode(AUDIO_OUTPUT, _node);
55652a38012Sejakowatz }
55752a38012Sejakowatz 
55852a38012Sejakowatz 
55952a38012Sejakowatz status_t
560*34c72144SAxel Dörfler BMediaRoster::GetAudioOutput(media_node* _node, int32* _inputID,
561*34c72144SAxel Dörfler 	BString* _inputName)
56252a38012Sejakowatz {
56352a38012Sejakowatz 	CALLED();
564*34c72144SAxel Dörfler 	return MediaRosterEx(this)->GetNode(AUDIO_OUTPUT_EX, _node, _inputID,
565*34c72144SAxel Dörfler 		_inputName);
56652a38012Sejakowatz }
56752a38012Sejakowatz 
56852a38012Sejakowatz 
56952a38012Sejakowatz status_t
570*34c72144SAxel Dörfler BMediaRoster::GetTimeSource(media_node* _node)
57152a38012Sejakowatz {
57252a38012Sejakowatz 	CALLED();
57386bce45bSbeveloper 	status_t rv;
57486bce45bSbeveloper 
575*34c72144SAxel Dörfler 	// TODO: need to do this in a nicer way.
57686bce45bSbeveloper 
577*34c72144SAxel Dörfler 	rv = MediaRosterEx(this)->GetNode(TIME_SOURCE, _node);
57886bce45bSbeveloper 	if (rv != B_OK)
57986bce45bSbeveloper 		return rv;
58086bce45bSbeveloper 
58186bce45bSbeveloper 	// We don't do reference counting for timesources, that's why we
58286bce45bSbeveloper 	// release the node immediately.
583*34c72144SAxel Dörfler 	ReleaseNode(*_node);
58486bce45bSbeveloper 
58586bce45bSbeveloper 	// we need to remember to not use this node with server side reference counting
586*34c72144SAxel Dörfler 	_node->kind |= NODE_KIND_NO_REFCOUNTING;
58786bce45bSbeveloper 	return B_OK;
58852a38012Sejakowatz }
58952a38012Sejakowatz 
59052a38012Sejakowatz 
59152a38012Sejakowatz status_t
59252a38012Sejakowatz BMediaRoster::SetVideoInput(const media_node& producer)
59352a38012Sejakowatz {
59452a38012Sejakowatz 	CALLED();
5958b04ffc1Sbeveloper 	return MediaRosterEx(this)->SetNode(VIDEO_INPUT, &producer);
59652a38012Sejakowatz }
59752a38012Sejakowatz 
59852a38012Sejakowatz 
59952a38012Sejakowatz status_t
60052a38012Sejakowatz BMediaRoster::SetVideoInput(const dormant_node_info& producer)
60152a38012Sejakowatz {
60252a38012Sejakowatz 	CALLED();
6038b04ffc1Sbeveloper 	return MediaRosterEx(this)->SetNode(VIDEO_INPUT, NULL, &producer);
60452a38012Sejakowatz }
60552a38012Sejakowatz 
60652a38012Sejakowatz 
60752a38012Sejakowatz status_t
60852a38012Sejakowatz BMediaRoster::SetAudioInput(const media_node& producer)
60952a38012Sejakowatz {
61052a38012Sejakowatz 	CALLED();
6118b04ffc1Sbeveloper 	return MediaRosterEx(this)->SetNode(AUDIO_INPUT, &producer);
61252a38012Sejakowatz }
61352a38012Sejakowatz 
61452a38012Sejakowatz 
61552a38012Sejakowatz status_t
61652a38012Sejakowatz BMediaRoster::SetAudioInput(const dormant_node_info& producer)
61752a38012Sejakowatz {
61852a38012Sejakowatz 	CALLED();
6198b04ffc1Sbeveloper 	return MediaRosterEx(this)->SetNode(AUDIO_INPUT, NULL, &producer);
62052a38012Sejakowatz }
62152a38012Sejakowatz 
62252a38012Sejakowatz 
62352a38012Sejakowatz status_t
62452a38012Sejakowatz BMediaRoster::SetVideoOutput(const media_node& consumer)
62552a38012Sejakowatz {
62652a38012Sejakowatz 	CALLED();
6278b04ffc1Sbeveloper 	return MediaRosterEx(this)->SetNode(VIDEO_OUTPUT, &consumer);
62852a38012Sejakowatz }
62952a38012Sejakowatz 
63052a38012Sejakowatz 
63152a38012Sejakowatz status_t
63252a38012Sejakowatz BMediaRoster::SetVideoOutput(const dormant_node_info& consumer)
63352a38012Sejakowatz {
63452a38012Sejakowatz 	CALLED();
6358b04ffc1Sbeveloper 	return MediaRosterEx(this)->SetNode(VIDEO_OUTPUT, NULL, &consumer);
63652a38012Sejakowatz }
63752a38012Sejakowatz 
63852a38012Sejakowatz 
63952a38012Sejakowatz status_t
64052a38012Sejakowatz BMediaRoster::SetAudioOutput(const media_node& consumer)
64152a38012Sejakowatz {
64252a38012Sejakowatz 	CALLED();
6438b04ffc1Sbeveloper 	return MediaRosterEx(this)->SetNode(AUDIO_OUTPUT, &consumer);
64452a38012Sejakowatz }
64552a38012Sejakowatz 
64652a38012Sejakowatz 
64752a38012Sejakowatz status_t
648*34c72144SAxel Dörfler BMediaRoster::SetAudioOutput(const media_input& input)
64952a38012Sejakowatz {
65052a38012Sejakowatz 	CALLED();
651*34c72144SAxel Dörfler 	return MediaRosterEx(this)->SetNode(AUDIO_OUTPUT, NULL, NULL, &input);
65252a38012Sejakowatz }
65352a38012Sejakowatz 
65452a38012Sejakowatz 
65552a38012Sejakowatz status_t
65652a38012Sejakowatz BMediaRoster::SetAudioOutput(const dormant_node_info& consumer)
65752a38012Sejakowatz {
65852a38012Sejakowatz 	CALLED();
6598b04ffc1Sbeveloper 	return MediaRosterEx(this)->SetNode(AUDIO_OUTPUT, NULL, &consumer);
66052a38012Sejakowatz }
66152a38012Sejakowatz 
66252a38012Sejakowatz 
66352a38012Sejakowatz status_t
664*34c72144SAxel Dörfler BMediaRoster::GetNodeFor(media_node_id node, media_node* clone)
66552a38012Sejakowatz {
6669e9417d2Sbeveloper 	CALLED();
6679e9417d2Sbeveloper 	if (clone == NULL)
6689e9417d2Sbeveloper 		return B_BAD_VALUE;
66965b73ae4SMarcus Overhagen 	if (IS_INVALID_NODEID(node))
6709e9417d2Sbeveloper 		return B_MEDIA_BAD_NODE;
6719e9417d2Sbeveloper 
6729e9417d2Sbeveloper 	server_get_node_for_request request;
6739e9417d2Sbeveloper 	server_get_node_for_reply reply;
6749e9417d2Sbeveloper 	status_t rv;
6759e9417d2Sbeveloper 
6769e9417d2Sbeveloper 	request.nodeid = node;
6779e9417d2Sbeveloper 	request.team = team;
6789e9417d2Sbeveloper 
679*34c72144SAxel Dörfler 	rv = QueryServer(SERVER_GET_NODE_FOR, &request, sizeof(request), &reply,
680*34c72144SAxel Dörfler 		sizeof(reply));
6819e9417d2Sbeveloper 	if (rv != B_OK)
6829e9417d2Sbeveloper 		return rv;
6839e9417d2Sbeveloper 
6849e9417d2Sbeveloper 	*clone = reply.clone;
6859e9417d2Sbeveloper 	return B_OK;
68652a38012Sejakowatz }
68752a38012Sejakowatz 
68852a38012Sejakowatz 
68952a38012Sejakowatz status_t
69052a38012Sejakowatz BMediaRoster::GetSystemTimeSource(media_node* clone)
69152a38012Sejakowatz {
69252a38012Sejakowatz 	CALLED();
69386bce45bSbeveloper 	status_t rv;
69486bce45bSbeveloper 
695*34c72144SAxel Dörfler 	// TODO: need to do this in a nicer way.
69686bce45bSbeveloper 
69786bce45bSbeveloper 	rv = MediaRosterEx(this)->GetNode(SYSTEM_TIME_SOURCE, clone);
69886bce45bSbeveloper 	if (rv != B_OK)
69986bce45bSbeveloper 		return rv;
70086bce45bSbeveloper 
70186bce45bSbeveloper 	// We don't do reference counting for timesources, that's why we
70286bce45bSbeveloper 	// release the node immediately.
70386bce45bSbeveloper 	ReleaseNode(*clone);
70486bce45bSbeveloper 
705*34c72144SAxel Dörfler 	// we need to remember to not use this node with server side reference
706*34c72144SAxel Dörfler 	// counting
70786bce45bSbeveloper 	clone->kind |= NODE_KIND_NO_REFCOUNTING;
70886bce45bSbeveloper 
70986bce45bSbeveloper 	return B_OK;
71052a38012Sejakowatz }
71152a38012Sejakowatz 
71252a38012Sejakowatz 
71352a38012Sejakowatz status_t
71452a38012Sejakowatz BMediaRoster::ReleaseNode(const media_node& node)
71552a38012Sejakowatz {
7169e9417d2Sbeveloper 	CALLED();
71740f36b03Sbeveloper 	if (IS_INVALID_NODE(node))
7189e9417d2Sbeveloper 		return B_MEDIA_BAD_NODE;
71952a38012Sejakowatz 
72086bce45bSbeveloper 	if (node.kind & NODE_KIND_NO_REFCOUNTING) {
721*34c72144SAxel Dörfler 		printf("BMediaRoster::ReleaseNode, trying to release reference "
722*34c72144SAxel Dörfler 			"counting disabled timesource, node %ld, port %ld, team %ld\n",
723*34c72144SAxel Dörfler 			node.node, node.port, team);
72486bce45bSbeveloper 		return B_OK;
72586bce45bSbeveloper 	}
72686bce45bSbeveloper 
7279e9417d2Sbeveloper 	server_release_node_request request;
7289e9417d2Sbeveloper 	server_release_node_reply reply;
729cf4e2277Sbeveloper 	status_t rv;
7309e9417d2Sbeveloper 
7319e9417d2Sbeveloper 	request.node = node;
7329e9417d2Sbeveloper 	request.team = team;
7339e9417d2Sbeveloper 
734*34c72144SAxel Dörfler 	TRACE("BMediaRoster::ReleaseNode, node %ld, port %ld, team %ld\n",
735*34c72144SAxel Dörfler 		node.node, node.port, team);
736cf4e2277Sbeveloper 
737*34c72144SAxel Dörfler 	rv = QueryServer(SERVER_RELEASE_NODE, &request, sizeof(request), &reply,
738*34c72144SAxel Dörfler 		sizeof(reply));
739cf4e2277Sbeveloper 	if (rv != B_OK) {
740*34c72144SAxel Dörfler 		ERROR("BMediaRoster::ReleaseNode FAILED, node %ld, port %ld, team "
741*34c72144SAxel Dörfler 			"%ld!\n", node.node, node.port, team);
742cf4e2277Sbeveloper 	}
743cf4e2277Sbeveloper 	return rv;
7449e9417d2Sbeveloper }
74552a38012Sejakowatz 
746*34c72144SAxel Dörfler 
74752a38012Sejakowatz BTimeSource*
748*34c72144SAxel Dörfler BMediaRoster::MakeTimeSourceFor(const media_node& forNode)
74952a38012Sejakowatz {
750f180ef79Sbeveloper 	// MakeTimeSourceFor() returns a BTimeSource object
751f180ef79Sbeveloper 	// corresponding to the specified node's time source.
752f180ef79Sbeveloper 
753835140c8Sbeveloper 	CALLED();
754f180ef79Sbeveloper 
755*34c72144SAxel Dörfler 	if (IS_SYSTEM_TIMESOURCE(forNode)) {
756f180ef79Sbeveloper 		// special handling for the system time source
757*34c72144SAxel Dörfler 		TRACE("BMediaRoster::MakeTimeSourceFor, asked for system time "
758*34c72144SAxel Dörfler 			"source\n");
759*34c72144SAxel Dörfler 		return MediaRosterEx(this)->MakeTimeSourceObject(
760*34c72144SAxel Dörfler 			NODE_SYSTEM_TIMESOURCE_ID);
761f180ef79Sbeveloper 	}
762f180ef79Sbeveloper 
763*34c72144SAxel Dörfler 	if (IS_INVALID_NODE(forNode)) {
764*34c72144SAxel Dörfler 		ERROR("BMediaRoster::MakeTimeSourceFor: for_node invalid, node %ld, "
765*34c72144SAxel Dörfler 			"port %ld, kinds 0x%lx\n", forNode.node, forNode.port,
766*34c72144SAxel Dörfler 			forNode.kind);
7675917dd5bSbeveloper 		return NULL;
7680e21b167Sbeveloper 	}
7690e21b167Sbeveloper 
770*34c72144SAxel Dörfler 	TRACE("BMediaRoster::MakeTimeSourceFor: node %ld enter\n", forNode.node);
7715917dd5bSbeveloper 
7725917dd5bSbeveloper 	node_get_timesource_request request;
7735917dd5bSbeveloper 	node_get_timesource_reply reply;
7745917dd5bSbeveloper 	BTimeSource *source;
7755917dd5bSbeveloper 	status_t rv;
7765917dd5bSbeveloper 
77792e575c1Sbeveloper 	// ask the node to get it's current timesource id
778*34c72144SAxel Dörfler 	rv = QueryPort(forNode.port, NODE_GET_TIMESOURCE, &request,
779*34c72144SAxel Dörfler 		sizeof(request), &reply, sizeof(reply));
7805917dd5bSbeveloper 	if (rv != B_OK) {
7815ac4fbd7Sbeveloper 		ERROR("BMediaRoster::MakeTimeSourceFor: request failed\n");
7825917dd5bSbeveloper 		return NULL;
7835917dd5bSbeveloper 	}
7845917dd5bSbeveloper 
7855917dd5bSbeveloper 	source = MediaRosterEx(this)->MakeTimeSourceObject(reply.timesource_id);
7865917dd5bSbeveloper 
787*34c72144SAxel Dörfler 	TRACE("BMediaRoster::MakeTimeSourceFor: node %ld leave\n", forNode.node);
788287f7492Sbeveloper 
789835140c8Sbeveloper 	return source;
79052a38012Sejakowatz }
79152a38012Sejakowatz 
79252a38012Sejakowatz 
79352a38012Sejakowatz status_t
794*34c72144SAxel Dörfler BMediaRoster::Connect(const media_source& from, const media_destination& to,
795*34c72144SAxel Dörfler 	media_format* _format, media_output* _output, media_input* _input)
79652a38012Sejakowatz {
797*34c72144SAxel Dörfler 	return BMediaRoster::Connect(from, to, _format, _output, _input, 0);
798eae26d3dSbeveloper }
799eae26d3dSbeveloper 
800eae26d3dSbeveloper 
801eae26d3dSbeveloper status_t
802*34c72144SAxel Dörfler BMediaRoster::Connect(const media_source& from, const media_destination& to,
803*34c72144SAxel Dörfler 	media_format* io_format, media_output* out_output, media_input* out_input,
804*34c72144SAxel Dörfler 	uint32 in_flags, void* _reserved)
805eae26d3dSbeveloper {
80652a38012Sejakowatz 	CALLED();
80752a38012Sejakowatz 	if (io_format == NULL || out_output == NULL || out_input == NULL)
80852a38012Sejakowatz 		return B_BAD_VALUE;
80940f36b03Sbeveloper 	if (IS_INVALID_SOURCE(from)) {
8105ac4fbd7Sbeveloper 		ERROR("BMediaRoster::Connect: media_source invalid\n");
81152a38012Sejakowatz 		return B_MEDIA_BAD_SOURCE;
8129e9417d2Sbeveloper 	}
81340f36b03Sbeveloper 	if (IS_INVALID_DESTINATION(to)) {
8145ac4fbd7Sbeveloper 		ERROR("BMediaRoster::Connect: media_destination invalid\n");
81552a38012Sejakowatz 		return B_MEDIA_BAD_DESTINATION;
8169e9417d2Sbeveloper 	}
81752a38012Sejakowatz 
81852a38012Sejakowatz 	status_t rv;
81965b73ae4SMarcus Overhagen 
82065b73ae4SMarcus Overhagen 	// find the output and input nodes
821*34c72144SAxel Dörfler 	// TODO: isn't there a easier way?
82265b73ae4SMarcus Overhagen 	media_node sourcenode;
82365b73ae4SMarcus Overhagen 	media_node destnode;
82465b73ae4SMarcus Overhagen 	rv = GetNodeFor(NodeIDFor(from.port), &sourcenode);
82565b73ae4SMarcus Overhagen 	if (rv != B_OK) {
826*34c72144SAxel Dörfler 		ERROR("BMediaRoster::Connect: Can't find source node for port %ld\n",
827*34c72144SAxel Dörfler 			from.port);
82865b73ae4SMarcus Overhagen 		return B_MEDIA_BAD_SOURCE;
82965b73ae4SMarcus Overhagen 	}
83065b73ae4SMarcus Overhagen 	ReleaseNode(sourcenode);
83165b73ae4SMarcus Overhagen 	rv = GetNodeFor(NodeIDFor(to.port), &destnode);
83265b73ae4SMarcus Overhagen 	if (rv != B_OK) {
833*34c72144SAxel Dörfler 		ERROR("BMediaRoster::Connect: Can't find destination node for port "
834*34c72144SAxel Dörfler 			"%ld\n", to.port);
83565b73ae4SMarcus Overhagen 		return B_MEDIA_BAD_DESTINATION;
83665b73ae4SMarcus Overhagen 	}
83765b73ae4SMarcus Overhagen 	ReleaseNode(destnode);
83865b73ae4SMarcus Overhagen 
83965b73ae4SMarcus Overhagen 	if (!(sourcenode.kind & B_BUFFER_PRODUCER)) {
840*34c72144SAxel Dörfler 		ERROR("BMediaRoster::Connect: source node %ld is not a "
841*34c72144SAxel Dörfler 			"B_BUFFER_PRODUCER\n", sourcenode.node);
84265b73ae4SMarcus Overhagen 		return B_MEDIA_BAD_SOURCE;
84365b73ae4SMarcus Overhagen 	}
84465b73ae4SMarcus Overhagen 	if (!(destnode.kind & B_BUFFER_CONSUMER)) {
845*34c72144SAxel Dörfler 		ERROR("BMediaRoster::Connect: destination node %ld is not a "
846*34c72144SAxel Dörfler 			"B_BUFFER_CONSUMER\n", destnode.node);
84765b73ae4SMarcus Overhagen 		return B_MEDIA_BAD_DESTINATION;
84865b73ae4SMarcus Overhagen 	}
84965b73ae4SMarcus Overhagen 
8508c6a6096Sbeveloper 	producer_format_proposal_request request1;
8518c6a6096Sbeveloper 	producer_format_proposal_reply reply1;
85252a38012Sejakowatz 
853*34c72144SAxel Dörfler 	PRINT_FORMAT("BMediaRoster::Connect calling "
854*34c72144SAxel Dörfler 		"BBufferProducer::FormatProposal with format  ", *io_format);
85569983609Sbeveloper 
85652a38012Sejakowatz 	// BBufferProducer::FormatProposal
8578c6a6096Sbeveloper 	request1.output = from;
8588c6a6096Sbeveloper 	request1.format = *io_format;
859*34c72144SAxel Dörfler 	rv = QueryPort(from.port, PRODUCER_FORMAT_PROPOSAL, &request1,
860*34c72144SAxel Dörfler 		sizeof(request1), &reply1, sizeof(reply1));
8618c6a6096Sbeveloper 	if (rv != B_OK) {
862*34c72144SAxel Dörfler 		ERROR("BMediaRoster::Connect: aborted after "
863*34c72144SAxel Dörfler 			"BBufferProducer::FormatProposal, status = %#lx\n",rv);
86452a38012Sejakowatz 		return rv;
86552a38012Sejakowatz 	}
8668c6a6096Sbeveloper 	// reply1.format now contains the format proposed by the producer
8678c6a6096Sbeveloper 
8688c6a6096Sbeveloper 	consumer_accept_format_request request2;
8698c6a6096Sbeveloper 	consumer_accept_format_reply reply2;
8708c6a6096Sbeveloper 
871*34c72144SAxel Dörfler 	PRINT_FORMAT("BMediaRoster::Connect calling "
872*34c72144SAxel Dörfler 		"BBufferConsumer::AcceptFormat with format    ", reply1.format);
87369983609Sbeveloper 
8748c6a6096Sbeveloper 	// BBufferConsumer::AcceptFormat
8758c6a6096Sbeveloper 	request2.dest = to;
8768c6a6096Sbeveloper 	request2.format = reply1.format;
877*34c72144SAxel Dörfler 	rv = QueryPort(to.port, CONSUMER_ACCEPT_FORMAT, &request2,
878*34c72144SAxel Dörfler 		sizeof(request2), &reply2, sizeof(reply2));
8798c6a6096Sbeveloper 	if (rv != B_OK) {
880*34c72144SAxel Dörfler 		ERROR("BMediaRoster::Connect: aborted after "
881*34c72144SAxel Dörfler 			"BBufferConsumer::AcceptFormat, status = %#lx\n",rv);
8828c6a6096Sbeveloper 		return rv;
8838c6a6096Sbeveloper 	}
8848c6a6096Sbeveloper 	// reply2.format now contains the format accepted by the consumer
8858c6a6096Sbeveloper 
8868c6a6096Sbeveloper 	// BBufferProducer::PrepareToConnect
8878c6a6096Sbeveloper 	producer_prepare_to_connect_request request3;
8888c6a6096Sbeveloper 	producer_prepare_to_connect_reply reply3;
8898c6a6096Sbeveloper 
890*34c72144SAxel Dörfler 	PRINT_FORMAT("BMediaRoster::Connect calling "
891*34c72144SAxel Dörfler 		"BBufferProducer::PrepareToConnect with format", reply2.format);
89269983609Sbeveloper 
8938c6a6096Sbeveloper 	request3.source = from;
8948c6a6096Sbeveloper 	request3.destination = to;
8958c6a6096Sbeveloper 	request3.format = reply2.format;
896*34c72144SAxel Dörfler 	strcpy(request3.name, "XXX some default name"); // TODO: fix this
897*34c72144SAxel Dörfler 	rv = QueryPort(from.port, PRODUCER_PREPARE_TO_CONNECT, &request3,
898*34c72144SAxel Dörfler 		sizeof(request3), &reply3, sizeof(reply3));
8998c6a6096Sbeveloper 	if (rv != B_OK) {
900*34c72144SAxel Dörfler 		ERROR("BMediaRoster::Connect: aborted after "
901*34c72144SAxel Dörfler 			"BBufferProducer::PrepareToConnect, status = %#lx\n",rv);
9028c6a6096Sbeveloper 		return rv;
9038c6a6096Sbeveloper 	}
9048c6a6096Sbeveloper 	// reply3.format is still our pretty media format
9058c6a6096Sbeveloper 	// reply3.out_source the real source to be used for the connection
906*34c72144SAxel Dörfler 	// reply3.name the name BBufferConsumer::Connected will see in the
907*34c72144SAxel Dörfler 	// outInput->name argument
9088c6a6096Sbeveloper 
9098c6a6096Sbeveloper 	// BBufferConsumer::Connected
9108c6a6096Sbeveloper 	consumer_connected_request request4;
9118c6a6096Sbeveloper 	consumer_connected_reply reply4;
9128c6a6096Sbeveloper 	status_t con_status;
9138c6a6096Sbeveloper 
914*34c72144SAxel Dörfler 	PRINT_FORMAT("BMediaRoster::Connect calling BBufferConsumer::Connected() "
915*34c72144SAxel Dörfler 		"with format       ", reply3.format);
91669983609Sbeveloper 
91769983609Sbeveloper 	request4.input.node = destnode;
91869983609Sbeveloper 	request4.input.source = reply3.out_source;
91969983609Sbeveloper 	request4.input.destination = to;
92069983609Sbeveloper 	request4.input.format = reply3.format;
92169983609Sbeveloper 	strcpy(request4.input.name, reply3.name);
92269983609Sbeveloper 
923*34c72144SAxel Dörfler 	con_status = QueryPort(to.port, CONSUMER_CONNECTED, &request4,
924*34c72144SAxel Dörfler 		sizeof(request4), &reply4, sizeof(reply4));
9258c6a6096Sbeveloper 	if (con_status != B_OK) {
926*34c72144SAxel Dörfler 		ERROR("BMediaRoster::Connect: aborting after "
927*34c72144SAxel Dörfler 			"BBufferConsumer::Connected, status = %#lx\n",con_status);
9288c6a6096Sbeveloper 		// we do NOT return here!
9298c6a6096Sbeveloper 	}
930*34c72144SAxel Dörfler 	// con_status contains the status code to be supplied to
931*34c72144SAxel Dörfler 	// BBufferProducer::Connect's status argument
932*34c72144SAxel Dörfler 	// reply4.input contains the media_input that describes the connection
933*34c72144SAxel Dörfler 	// from the consumer point of view
9348c6a6096Sbeveloper 
9358c6a6096Sbeveloper 	// BBufferProducer::Connect
9368c6a6096Sbeveloper 	producer_connect_request request5;
9378c6a6096Sbeveloper 	producer_connect_reply reply5;
9388c6a6096Sbeveloper 
939*34c72144SAxel Dörfler 	PRINT_FORMAT("BMediaRoster::Connect calling BBufferProducer::Connect with "
940*34c72144SAxel Dörfler 		"format         ", reply4.input.format);
94169983609Sbeveloper 
9428c6a6096Sbeveloper 	request5.error = con_status;
9438c6a6096Sbeveloper 	request5.source = reply3.out_source;
9448c6a6096Sbeveloper 	request5.destination = reply4.input.destination;
94569983609Sbeveloper 	request5.format = reply4.input.format;
9468c6a6096Sbeveloper 	strcpy(request5.name, reply4.input.name);
947*34c72144SAxel Dörfler 	rv = QueryPort(reply4.input.source.port, PRODUCER_CONNECT, &request5,
948*34c72144SAxel Dörfler 		sizeof(request5), &reply5, sizeof(reply5));
9498c6a6096Sbeveloper 	if (con_status != B_OK) {
9505ac4fbd7Sbeveloper 		ERROR("BMediaRoster::Connect: aborted\n");
9518c6a6096Sbeveloper 		return con_status;
9528c6a6096Sbeveloper 	}
9538c6a6096Sbeveloper 	if (rv != B_OK) {
954*34c72144SAxel Dörfler 		ERROR("BMediaRoster::Connect: aborted after BBufferProducer::Connect()"
955*34c72144SAxel Dörfler 			", status = %#lx\n",rv);
9568c6a6096Sbeveloper 		return rv;
9578c6a6096Sbeveloper 	}
9588c6a6096Sbeveloper 	// reply5.name contains the name assigned to the connection by the producer
9598c6a6096Sbeveloper 
9608c6a6096Sbeveloper 	// initilize connection info
96169983609Sbeveloper 	*io_format = reply4.input.format;
9628c6a6096Sbeveloper 	*out_input = reply4.input;
9638c6a6096Sbeveloper 	out_output->node = sourcenode;
9648c6a6096Sbeveloper 	out_output->source = reply4.input.source;
9658c6a6096Sbeveloper 	out_output->destination = reply4.input.destination;
9668c6a6096Sbeveloper 	out_output->format = reply4.input.format;
9678c6a6096Sbeveloper 	strcpy(out_output->name, reply5.name);
9688c6a6096Sbeveloper 
9698c6a6096Sbeveloper 	// the connection is now made
97069983609Sbeveloper 	printf("BMediaRoster::Connect connection established!\n");
97169983609Sbeveloper 	PRINT_FORMAT("   format", *io_format);
97269983609Sbeveloper 	PRINT_INPUT("   input", *out_input);
97369983609Sbeveloper 	PRINT_OUTPUT("   output", *out_output);
9748c6a6096Sbeveloper 
975*34c72144SAxel Dörfler 	// TODO: register connection with server
976*34c72144SAxel Dörfler 	// TODO: we should just send a notification, instead of republishing all
977*34c72144SAxel Dörfler 	// endpoints
97876669a29Sbeveloper 	List<media_output> outlist;
97976669a29Sbeveloper 	List<media_input> inlist;
980*34c72144SAxel Dörfler 	if (MediaRosterEx(this)->GetAllOutputs(out_output->node , &outlist) == B_OK)
9818b04ffc1Sbeveloper 		MediaRosterEx(this)->PublishOutputs(out_output->node , &outlist);
982*34c72144SAxel Dörfler 	if (MediaRosterEx(this)->GetAllInputs(out_input->node , &inlist) == B_OK)
9838b04ffc1Sbeveloper 		MediaRosterEx(this)->PublishInputs(out_input->node, &inlist);
9848c6a6096Sbeveloper 
985*34c72144SAxel Dörfler 	// TODO: if (mute) BBufferProducer::EnableOutput(false)
9869e9417d2Sbeveloper 	if (in_flags & B_CONNECT_MUTED) {
9879e9417d2Sbeveloper 	}
9888c6a6096Sbeveloper 
9899e9417d2Sbeveloper 	// send a notification
990*34c72144SAxel Dörfler 	BPrivate::media::notifications::ConnectionMade(*out_input, *out_output,
991*34c72144SAxel Dörfler 		*io_format);
9929e9417d2Sbeveloper 
9938c6a6096Sbeveloper 	return B_OK;
9948c6a6096Sbeveloper };
99552a38012Sejakowatz 
99652a38012Sejakowatz 
99752a38012Sejakowatz status_t
9989e9417d2Sbeveloper BMediaRoster::Disconnect(media_node_id source_nodeid,
999*34c72144SAxel Dörfler 	const media_source& source, media_node_id destination_nodeid,
100052a38012Sejakowatz 	const media_destination& destination)
100152a38012Sejakowatz {
10029e9417d2Sbeveloper 	CALLED();
100340f36b03Sbeveloper 	if (IS_INVALID_NODEID(source_nodeid)) {
10045ac4fbd7Sbeveloper 		ERROR("BMediaRoster::Disconnect: source media_node_id invalid\n");
10059e9417d2Sbeveloper 		return B_MEDIA_BAD_SOURCE;
10069e9417d2Sbeveloper 	}
100740f36b03Sbeveloper 	if (IS_INVALID_NODEID(destination_nodeid)) {
10085ac4fbd7Sbeveloper 		ERROR("BMediaRoster::Disconnect: destination media_node_id invalid\n");
10099e9417d2Sbeveloper 		return B_MEDIA_BAD_DESTINATION;
10109e9417d2Sbeveloper 	}
101140f36b03Sbeveloper 	if (IS_INVALID_SOURCE(source)) {
10125ac4fbd7Sbeveloper 		ERROR("BMediaRoster::Disconnect: media_source invalid\n");
10139e9417d2Sbeveloper 		return B_MEDIA_BAD_SOURCE;
10149e9417d2Sbeveloper 	}
101540f36b03Sbeveloper 	if (IS_INVALID_DESTINATION(destination)) {
10165ac4fbd7Sbeveloper 		ERROR("BMediaRoster::Disconnect: media_destination invalid\n");
10179e9417d2Sbeveloper 		return B_MEDIA_BAD_DESTINATION;
10189e9417d2Sbeveloper 	}
10199e9417d2Sbeveloper 
10209e9417d2Sbeveloper 	producer_disconnect_request request2;
10219e9417d2Sbeveloper 	producer_disconnect_reply reply2;
10229e9417d2Sbeveloper 	consumer_disconnected_request request1;
10239e9417d2Sbeveloper 	consumer_disconnected_reply reply1;
10249e9417d2Sbeveloper 	status_t rv1, rv2;
10259e9417d2Sbeveloper 
1026*34c72144SAxel Dörfler 	// TODO: we should ask the server if this connection really exists
10279e9417d2Sbeveloper 
10289e9417d2Sbeveloper 	request1.source = source;
10299e9417d2Sbeveloper 	request1.destination = destination;
10309e9417d2Sbeveloper 	request2.source = source;
10319e9417d2Sbeveloper 	request2.destination = destination;
10329e9417d2Sbeveloper 
1033*34c72144SAxel Dörfler 	rv1 = QueryPort(source.port, PRODUCER_DISCONNECT, &request1,
1034*34c72144SAxel Dörfler 		sizeof(request1), &reply1, sizeof(reply1));
1035*34c72144SAxel Dörfler 	rv2 = QueryPort(destination.port, CONSUMER_DISCONNECTED, &request2,
1036*34c72144SAxel Dörfler 		sizeof(request2), &reply2, sizeof(reply2));
10379e9417d2Sbeveloper 
1038*34c72144SAxel Dörfler 	// TODO: unregister connection with server
1039*34c72144SAxel Dörfler 	// TODO: we should just send a notification, instead of republishing all
1040*34c72144SAxel Dörfler 	// endpoints
104176669a29Sbeveloper 	List<media_output> outlist;
104276669a29Sbeveloper 	List<media_input> inlist;
10439e9417d2Sbeveloper 	media_node sourcenode;
10449e9417d2Sbeveloper 	media_node destnode;
1045*34c72144SAxel Dörfler 	if (GetNodeFor(source_nodeid, &sourcenode) == B_OK) {
104665b73ae4SMarcus Overhagen 		if (!(sourcenode.kind & B_BUFFER_PRODUCER)) {
1047*34c72144SAxel Dörfler 			ERROR("BMediaRoster::Disconnect: source_nodeid %ld is not a "
1048*34c72144SAxel Dörfler 				"B_BUFFER_PRODUCER\n", source_nodeid);
104965b73ae4SMarcus Overhagen 		}
1050*34c72144SAxel Dörfler 		if (MediaRosterEx(this)->GetAllOutputs(sourcenode , &outlist) == B_OK)
10518b04ffc1Sbeveloper 			MediaRosterEx(this)->PublishOutputs(sourcenode , &outlist);
10529e9417d2Sbeveloper 		ReleaseNode(sourcenode);
10534f09fa2fSbeveloper 	} else {
105465b73ae4SMarcus Overhagen 		ERROR("BMediaRoster::Disconnect: GetNodeFor source_nodeid %ld failed\n", source_nodeid);
10554f09fa2fSbeveloper 	}
1056*34c72144SAxel Dörfler 	if (GetNodeFor(destination_nodeid, &destnode) == B_OK) {
105765b73ae4SMarcus Overhagen 		if (!(destnode.kind & B_BUFFER_CONSUMER)) {
1058*34c72144SAxel Dörfler 			ERROR("BMediaRoster::Disconnect: destination_nodeid %ld is not a "
1059*34c72144SAxel Dörfler 				"B_BUFFER_CONSUMER\n", destination_nodeid);
106065b73ae4SMarcus Overhagen 		}
1061*34c72144SAxel Dörfler 		if (MediaRosterEx(this)->GetAllInputs(destnode , &inlist) == B_OK)
10628b04ffc1Sbeveloper 			MediaRosterEx(this)->PublishInputs(destnode, &inlist);
10639e9417d2Sbeveloper 		ReleaseNode(destnode);
10644f09fa2fSbeveloper 	} else {
1065*34c72144SAxel Dörfler 		ERROR("BMediaRoster::Disconnect: GetNodeFor destination_nodeid %ld "
1066*34c72144SAxel Dörfler 			"failed\n", destination_nodeid);
10674f09fa2fSbeveloper 	}
10689e9417d2Sbeveloper 
10699e9417d2Sbeveloper 	// send a notification
10709e9417d2Sbeveloper 	BPrivate::media::notifications::ConnectionBroken(source, destination);
10719e9417d2Sbeveloper 
1072*34c72144SAxel Dörfler 	return rv1 != B_OK || rv2 != B_OK ? B_ERROR : B_OK;
107352a38012Sejakowatz }
107452a38012Sejakowatz 
1075*34c72144SAxel Dörfler 
107665b73ae4SMarcus Overhagen status_t
107765b73ae4SMarcus Overhagen BMediaRoster::Disconnect(const media_output& output, const media_input& input)
107865b73ae4SMarcus Overhagen {
107965b73ae4SMarcus Overhagen 	if (IS_INVALID_NODEID(output.node.node)) {
108065b73ae4SMarcus Overhagen 		printf("BMediaRoster::Disconnect: output.node.node %ld invalid\n",
108165b73ae4SMarcus Overhagen 			output.node.node);
108265b73ae4SMarcus Overhagen 		return B_MEDIA_BAD_SOURCE;
108365b73ae4SMarcus Overhagen 	}
108465b73ae4SMarcus Overhagen 	if (IS_INVALID_NODEID(input.node.node)) {
108565b73ae4SMarcus Overhagen 		printf("BMediaRoster::Disconnect: input.node.node %ld invalid\n",
108665b73ae4SMarcus Overhagen 			input.node.node);
108765b73ae4SMarcus Overhagen 		return B_MEDIA_BAD_DESTINATION;
108865b73ae4SMarcus Overhagen 	}
108965b73ae4SMarcus Overhagen 	if (!(output.node.kind & B_BUFFER_PRODUCER)) {
1090*34c72144SAxel Dörfler 		printf("BMediaRoster::Disconnect: output.node.kind 0x%lx is no "
1091*34c72144SAxel Dörfler 			"B_BUFFER_PRODUCER\n", output.node.kind);
109265b73ae4SMarcus Overhagen 		return B_MEDIA_BAD_SOURCE;
109365b73ae4SMarcus Overhagen 	}
109465b73ae4SMarcus Overhagen 	if (!(input.node.kind & B_BUFFER_CONSUMER)) {
1095*34c72144SAxel Dörfler 		printf("BMediaRoster::Disconnect: input.node.kind 0x%lx is no "
1096*34c72144SAxel Dörfler 			"B_BUFFER_PRODUCER\n", input.node.kind);
109765b73ae4SMarcus Overhagen 		return B_MEDIA_BAD_DESTINATION;
109865b73ae4SMarcus Overhagen 	}
109965b73ae4SMarcus Overhagen 	if (input.source.port != output.source.port) {
1100*34c72144SAxel Dörfler 		printf("BMediaRoster::Disconnect: input.source.port %ld doesn't match "
1101*34c72144SAxel Dörfler 			"output.source.port %ld\n", input.source.port, output.source.port);
110265b73ae4SMarcus Overhagen 		return B_MEDIA_BAD_SOURCE;
110365b73ae4SMarcus Overhagen 	}
110465b73ae4SMarcus Overhagen 	if (input.source.id != output.source.id) {
1105*34c72144SAxel Dörfler 		printf("BMediaRoster::Disconnect: input.source.id %ld doesn't match "
1106*34c72144SAxel Dörfler 			"output.source.id %ld\n", input.source.id, output.source.id);
110765b73ae4SMarcus Overhagen 		return B_MEDIA_BAD_SOURCE;
110865b73ae4SMarcus Overhagen 	}
110965b73ae4SMarcus Overhagen 	if (input.destination.port != output.destination.port) {
1110*34c72144SAxel Dörfler 		printf("BMediaRoster::Disconnect: input.destination.port %ld doesn't "
1111*34c72144SAxel Dörfler 			"match output.destination.port %ld\n", input.destination.port,
1112*34c72144SAxel Dörfler 			output.destination.port);
111365b73ae4SMarcus Overhagen 		return B_MEDIA_BAD_DESTINATION;
111465b73ae4SMarcus Overhagen 	}
111565b73ae4SMarcus Overhagen 	if (input.destination.id != output.destination.id) {
1116*34c72144SAxel Dörfler 		printf("BMediaRoster::Disconnect: input.destination.id %ld doesn't "
1117*34c72144SAxel Dörfler 			"match output.destination.id %ld\n", input.destination.id,
1118*34c72144SAxel Dörfler 			output.destination.id);
111965b73ae4SMarcus Overhagen 		return B_MEDIA_BAD_DESTINATION;
112065b73ae4SMarcus Overhagen 	}
1121*34c72144SAxel Dörfler 
1122*34c72144SAxel Dörfler 	return Disconnect(output.node.node, output.source, input.node.node,
1123*34c72144SAxel Dörfler 		input.destination);
112465b73ae4SMarcus Overhagen }
112565b73ae4SMarcus Overhagen 
112652a38012Sejakowatz 
112752a38012Sejakowatz status_t
1128*34c72144SAxel Dörfler BMediaRoster::StartNode(const media_node& node, bigtime_t atPerformanceTime)
112952a38012Sejakowatz {
113052a38012Sejakowatz 	CALLED();
11319e9417d2Sbeveloper 	if (node.node <= 0)
113252a38012Sejakowatz 		return B_MEDIA_BAD_NODE;
113352a38012Sejakowatz 
1134*34c72144SAxel Dörfler 	TRACE("BMediaRoster::StartNode, node %ld, at perf %Ld\n", node.node,
1135*34c72144SAxel Dörfler 		atPerformanceTime);
11360e21b167Sbeveloper 
11376396865dSbeveloper 	node_start_command command;
1138*34c72144SAxel Dörfler 	command.performance_time = atPerformanceTime;
113952a38012Sejakowatz 
11406396865dSbeveloper 	return SendToPort(node.port, NODE_START, &command, sizeof(command));
114152a38012Sejakowatz }
114252a38012Sejakowatz 
114352a38012Sejakowatz 
114452a38012Sejakowatz status_t
1145*34c72144SAxel Dörfler BMediaRoster::StopNode(const media_node& node, bigtime_t atPerformanceTime,
114652a38012Sejakowatz 	bool immediate)
114752a38012Sejakowatz {
114852a38012Sejakowatz 	CALLED();
114940f36b03Sbeveloper 	if (IS_INVALID_NODE(node))
115052a38012Sejakowatz 		return B_MEDIA_BAD_NODE;
115152a38012Sejakowatz 
1152*34c72144SAxel Dörfler 	TRACE("BMediaRoster::StopNode, node %ld, at perf %Ld %s\n", node.node,
1153*34c72144SAxel Dörfler 		atPerformanceTime, immediate ? "NOW" : "");
11540e21b167Sbeveloper 
11556396865dSbeveloper 	node_stop_command command;
1156*34c72144SAxel Dörfler 	command.performance_time = atPerformanceTime;
11576396865dSbeveloper 	command.immediate = immediate;
115852a38012Sejakowatz 
11596396865dSbeveloper 	return SendToPort(node.port, NODE_STOP, &command, sizeof(command));
116052a38012Sejakowatz }
116152a38012Sejakowatz 
116252a38012Sejakowatz 
116352a38012Sejakowatz status_t
1164*34c72144SAxel Dörfler BMediaRoster::SeekNode(const media_node& node, bigtime_t toMediaTime,
1165*34c72144SAxel Dörfler 	bigtime_t atPerformanceTime)
116652a38012Sejakowatz {
116752a38012Sejakowatz 	CALLED();
116840f36b03Sbeveloper 	if (IS_INVALID_NODE(node))
116952a38012Sejakowatz 		return B_MEDIA_BAD_NODE;
117052a38012Sejakowatz 
1171*34c72144SAxel Dörfler 	TRACE("BMediaRoster::SeekNode, node %ld, at perf %Ld, to perf %Ld\n",
1172*34c72144SAxel Dörfler 		node.node, atPerformanceTime, toMediaTime);
11730e21b167Sbeveloper 
11746396865dSbeveloper 	node_seek_command command;
1175*34c72144SAxel Dörfler 	command.media_time = toMediaTime;
1176*34c72144SAxel Dörfler 	command.performance_time = atPerformanceTime;
117752a38012Sejakowatz 
11786396865dSbeveloper 	return SendToPort(node.port, NODE_SEEK, &command, sizeof(command));
117952a38012Sejakowatz }
118052a38012Sejakowatz 
118152a38012Sejakowatz 
118252a38012Sejakowatz status_t
1183*34c72144SAxel Dörfler BMediaRoster::StartTimeSource(const media_node& node, bigtime_t atRealTime)
118452a38012Sejakowatz {
118552a38012Sejakowatz 	CALLED();
118660f15390Sbeveloper 	if (IS_SYSTEM_TIMESOURCE(node)) {
1187*34c72144SAxel Dörfler 		// TODO: debug this
11885ac4fbd7Sbeveloper 		//ERROR("BMediaRoster::StartTimeSource node %ld is system timesource\n", node.node);
118960f15390Sbeveloper 		return B_OK;
119060f15390Sbeveloper 	}
119192e575c1Sbeveloper //	if (IS_SHADOW_TIMESOURCE(node)) {
1192*34c72144SAxel Dörfler //		// TODO: debug this
119392e575c1Sbeveloper //		ERROR("BMediaRoster::StartTimeSource node %ld is shadow timesource\n", node.node);
119492e575c1Sbeveloper //		return B_OK;
119592e575c1Sbeveloper //	}
119640f36b03Sbeveloper 	if (IS_INVALID_NODE(node)) {
11975ac4fbd7Sbeveloper 		ERROR("BMediaRoster::StartTimeSource node %ld invalid\n", node.node);
119852a38012Sejakowatz 		return B_MEDIA_BAD_NODE;
11990e21b167Sbeveloper 	}
12000e21b167Sbeveloper 	if ((node.kind & B_TIME_SOURCE) == 0) {
1201*34c72144SAxel Dörfler 		ERROR("BMediaRoster::StartTimeSource node %ld is no timesource\n",
1202*34c72144SAxel Dörfler 			node.node);
120352a38012Sejakowatz 		return B_MEDIA_BAD_NODE;
12040e21b167Sbeveloper 	}
12050e21b167Sbeveloper 
1206*34c72144SAxel Dörfler 	TRACE("BMediaRoster::StartTimeSource, node %ld, at real %Ld\n", node.node,
1207*34c72144SAxel Dörfler 		at_real_time);
120852a38012Sejakowatz 
120952a38012Sejakowatz 	BTimeSource::time_source_op_info msg;
121052a38012Sejakowatz 	msg.op = BTimeSource::B_TIMESOURCE_START;
1211*34c72144SAxel Dörfler 	msg.real_time = atRealTime;
121252a38012Sejakowatz 
121352a38012Sejakowatz 	return write_port(node.port, TIMESOURCE_OP, &msg, sizeof(msg));
121452a38012Sejakowatz }
121552a38012Sejakowatz 
121652a38012Sejakowatz 
121752a38012Sejakowatz status_t
1218*34c72144SAxel Dörfler BMediaRoster::StopTimeSource(const media_node& node, bigtime_t atRealTime,
121952a38012Sejakowatz 	bool immediate)
122052a38012Sejakowatz {
122152a38012Sejakowatz 	CALLED();
122260f15390Sbeveloper 	if (IS_SYSTEM_TIMESOURCE(node)) {
1223*34c72144SAxel Dörfler 		// TODO: debug this
12245ac4fbd7Sbeveloper 		//ERROR("BMediaRoster::StopTimeSource node %ld is system timesource\n", node.node);
122560f15390Sbeveloper 		return B_OK;
122660f15390Sbeveloper 	}
122792e575c1Sbeveloper //	if (IS_SHADOW_TIMESOURCE(node)) {
1228*34c72144SAxel Dörfler //		// TODO: debug this
122992e575c1Sbeveloper //		ERROR("BMediaRoster::StopTimeSource node %ld is shadow timesource\n", node.node);
123092e575c1Sbeveloper //		return B_OK;
123192e575c1Sbeveloper //	}
123240f36b03Sbeveloper 	if (IS_INVALID_NODE(node)) {
12335ac4fbd7Sbeveloper 		ERROR("BMediaRoster::StopTimeSource node %ld invalid\n", node.node);
123452a38012Sejakowatz 		return B_MEDIA_BAD_NODE;
12350e21b167Sbeveloper 	}
12360e21b167Sbeveloper 	if ((node.kind & B_TIME_SOURCE) == 0) {
1237*34c72144SAxel Dörfler 		ERROR("BMediaRoster::StopTimeSource node %ld is no timesource\n",
1238*34c72144SAxel Dörfler 			node.node);
123952a38012Sejakowatz 		return B_MEDIA_BAD_NODE;
12400e21b167Sbeveloper 	}
12410e21b167Sbeveloper 
1242*34c72144SAxel Dörfler 	TRACE("BMediaRoster::StopTimeSource, node %ld, at real %Ld %s\n",
1243*34c72144SAxel Dörfler 		node.node, atRealTime, immediate ? "NOW" : "");
124452a38012Sejakowatz 
124552a38012Sejakowatz 	BTimeSource::time_source_op_info msg;
1246*34c72144SAxel Dörfler 	msg.op = immediate ? BTimeSource::B_TIMESOURCE_STOP_IMMEDIATELY
1247*34c72144SAxel Dörfler 		: BTimeSource::B_TIMESOURCE_STOP;
1248*34c72144SAxel Dörfler 	msg.real_time = atRealTime;
124952a38012Sejakowatz 
125052a38012Sejakowatz 	return write_port(node.port, TIMESOURCE_OP, &msg, sizeof(msg));
125152a38012Sejakowatz }
125252a38012Sejakowatz 
125352a38012Sejakowatz 
125452a38012Sejakowatz status_t
125552a38012Sejakowatz BMediaRoster::SeekTimeSource(const media_node& node,
1256*34c72144SAxel Dörfler 	bigtime_t toPerformanceTime, bigtime_t atRealTime)
125752a38012Sejakowatz {
125852a38012Sejakowatz 	CALLED();
125960f15390Sbeveloper 	if (IS_SYSTEM_TIMESOURCE(node)) {
1260*34c72144SAxel Dörfler 		// TODO: debug this
12615ac4fbd7Sbeveloper 		// ERROR("BMediaRoster::SeekTimeSource node %ld is system timesource\n", node.node);
126260f15390Sbeveloper 		// you can't seek the system time source, but
126360f15390Sbeveloper 		// returning B_ERROR would break StampTV
126460f15390Sbeveloper 		return B_OK;
126560f15390Sbeveloper 	}
126692e575c1Sbeveloper //	if (IS_SHADOW_TIMESOURCE(node)) {
1267*34c72144SAxel Dörfler //		// TODO: debug this
126892e575c1Sbeveloper //		ERROR("BMediaRoster::SeekTimeSource node %ld is shadow timesource\n", node.node);
126992e575c1Sbeveloper //		return B_OK;
127092e575c1Sbeveloper //	}
127140f36b03Sbeveloper 	if (IS_INVALID_NODE(node)) {
12725ac4fbd7Sbeveloper 		ERROR("BMediaRoster::SeekTimeSource node %ld invalid\n", node.node);
127352a38012Sejakowatz 		return B_MEDIA_BAD_NODE;
12740e21b167Sbeveloper 	}
12750e21b167Sbeveloper 	if ((node.kind & B_TIME_SOURCE) == 0) {
1276*34c72144SAxel Dörfler 		ERROR("BMediaRoster::SeekTimeSource node %ld is no timesource\n",
1277*34c72144SAxel Dörfler 			node.node);
127852a38012Sejakowatz 		return B_MEDIA_BAD_NODE;
12790e21b167Sbeveloper 	}
12800e21b167Sbeveloper 
1281*34c72144SAxel Dörfler 	TRACE("BMediaRoster::SeekTimeSource, node %ld, at real %Ld, to perf %Ld\n",
1282*34c72144SAxel Dörfler 		node.node, atRealTime, toPerformanceTime);
128352a38012Sejakowatz 
128452a38012Sejakowatz 	BTimeSource::time_source_op_info msg;
128552a38012Sejakowatz 	msg.op = BTimeSource::B_TIMESOURCE_SEEK;
1286*34c72144SAxel Dörfler 	msg.real_time = atRealTime;
1287*34c72144SAxel Dörfler 	msg.performance_time = toPerformanceTime;
128852a38012Sejakowatz 
128952a38012Sejakowatz 	return write_port(node.port, TIMESOURCE_OP, &msg, sizeof(msg));
129052a38012Sejakowatz }
129152a38012Sejakowatz 
129252a38012Sejakowatz 
129352a38012Sejakowatz status_t
1294*34c72144SAxel Dörfler BMediaRoster::SyncToNode(const media_node& node, bigtime_t atTime,
129552a38012Sejakowatz 	bigtime_t timeout)
129652a38012Sejakowatz {
129752a38012Sejakowatz 	UNIMPLEMENTED();
129860f15390Sbeveloper 	return B_OK;
129952a38012Sejakowatz }
130052a38012Sejakowatz 
130152a38012Sejakowatz 
130252a38012Sejakowatz status_t
1303*34c72144SAxel Dörfler BMediaRoster::SetRunModeNode(const media_node& node, BMediaNode::run_mode mode)
130452a38012Sejakowatz {
130531cf24c1SMarcus Overhagen 	TRACE("BMediaRoster::SetRunModeNode, node %ld, mode %d\n", node.node, mode);
130640f36b03Sbeveloper 	if (IS_INVALID_NODE(node))
130752a38012Sejakowatz 		return B_MEDIA_BAD_NODE;
130852a38012Sejakowatz 
1309dfb2ad61Sbeveloper 	node_set_run_mode_command msg;
131052a38012Sejakowatz 	msg.mode = mode;
131152a38012Sejakowatz 
131252a38012Sejakowatz 	return write_port(node.port, NODE_SET_RUN_MODE, &msg, sizeof(msg));
131352a38012Sejakowatz }
131452a38012Sejakowatz 
131552a38012Sejakowatz 
131652a38012Sejakowatz status_t
131752a38012Sejakowatz BMediaRoster::PrerollNode(const media_node& node)
131852a38012Sejakowatz {
131952a38012Sejakowatz 	CALLED();
132040f36b03Sbeveloper 	if (IS_INVALID_NODE(node))
132152a38012Sejakowatz 		return B_MEDIA_BAD_NODE;
132252a38012Sejakowatz 
132352a38012Sejakowatz 	char dummy;
132452a38012Sejakowatz 	return write_port(node.port, NODE_PREROLL, &dummy, sizeof(dummy));
132552a38012Sejakowatz }
132652a38012Sejakowatz 
132752a38012Sejakowatz 
132852a38012Sejakowatz status_t
1329*34c72144SAxel Dörfler BMediaRoster::RollNode(const media_node& node, bigtime_t startPerformance,
1330*34c72144SAxel Dörfler 	bigtime_t stopPerformance, bigtime_t atMediaTime)
133152a38012Sejakowatz {
133252a38012Sejakowatz 	UNIMPLEMENTED();
133352a38012Sejakowatz 	return B_ERROR;
133452a38012Sejakowatz }
133552a38012Sejakowatz 
133652a38012Sejakowatz 
133752a38012Sejakowatz status_t
133852a38012Sejakowatz BMediaRoster::SetProducerRunModeDelay(const media_node& node,
1339*34c72144SAxel Dörfler 	bigtime_t delay, BMediaNode::run_mode mode)
134052a38012Sejakowatz {
1341*34c72144SAxel Dörfler 	TRACE("BMediaRoster::SetProducerRunModeDelay, node %ld, delay %Ld, "
1342*34c72144SAxel Dörfler 		"mode %d\n", node.node, delay, mode);
134360f15390Sbeveloper 	if (IS_INVALID_NODE(node))
134460f15390Sbeveloper 		return B_MEDIA_BAD_NODE;
134560f15390Sbeveloper 	if ((node.kind & B_BUFFER_PRODUCER) == 0)
134660f15390Sbeveloper 		return B_MEDIA_BAD_NODE;
134760f15390Sbeveloper 
134860f15390Sbeveloper 	producer_set_run_mode_delay_command command;
134960f15390Sbeveloper 	command.mode = mode;
135060f15390Sbeveloper 	command.delay = delay;
135160f15390Sbeveloper 
1352*34c72144SAxel Dörfler 	return SendToPort(node.port, PRODUCER_SET_RUN_MODE_DELAY, &command,
1353*34c72144SAxel Dörfler 		sizeof(command));
135452a38012Sejakowatz }
135552a38012Sejakowatz 
135652a38012Sejakowatz 
135752a38012Sejakowatz status_t
1358*34c72144SAxel Dörfler BMediaRoster::SetProducerRate(const media_node& producer, int32 numer,
135952a38012Sejakowatz 	int32 denom)
136052a38012Sejakowatz {
136152a38012Sejakowatz 	CALLED();
136240f36b03Sbeveloper 	if (IS_INVALID_NODE(producer))
136352a38012Sejakowatz 		return B_MEDIA_BAD_NODE;
136452a38012Sejakowatz 	if ((producer.kind & B_BUFFER_PRODUCER) == 0)
136552a38012Sejakowatz 		return B_MEDIA_BAD_NODE;
136652a38012Sejakowatz 
1367dfb2ad61Sbeveloper 	producer_set_play_rate_request msg;
1368dfb2ad61Sbeveloper 	producer_set_play_rate_reply reply;
136952a38012Sejakowatz 	status_t rv;
137052a38012Sejakowatz 	int32 code;
137152a38012Sejakowatz 
137252a38012Sejakowatz 	msg.numer = numer;
137352a38012Sejakowatz 	msg.denom = denom;
137452a38012Sejakowatz 	msg.reply_port = _PortPool->GetPort();
137552a38012Sejakowatz 	rv = write_port(producer.node, PRODUCER_SET_PLAY_RATE, &msg, sizeof(msg));
137652a38012Sejakowatz 	if (rv != B_OK) {
137752a38012Sejakowatz 		_PortPool->PutPort(msg.reply_port);
137852a38012Sejakowatz 		return rv;
137952a38012Sejakowatz 	}
138052a38012Sejakowatz 	rv = read_port(msg.reply_port, &code, &reply, sizeof(reply));
138152a38012Sejakowatz 	_PortPool->PutPort(msg.reply_port);
138252a38012Sejakowatz 	return (rv < B_OK) ? rv : reply.result;
138352a38012Sejakowatz }
138452a38012Sejakowatz 
138552a38012Sejakowatz 
1386*34c72144SAxel Dörfler /*!	Nodes will have available inputs/outputs as long as they are capable
1387*34c72144SAxel Dörfler 	of accepting more connections. The node may create an additional
1388*34c72144SAxel Dörfler 	output or input as the currently available is taken into usage.
1389*34c72144SAxel Dörfler */
139052a38012Sejakowatz status_t
139152a38012Sejakowatz BMediaRoster::GetLiveNodeInfo(const media_node& node,
139252a38012Sejakowatz 	live_node_info* out_live_info)
139352a38012Sejakowatz {
13949e9417d2Sbeveloper 	CALLED();
13959e9417d2Sbeveloper 	if (out_live_info == NULL)
13969e9417d2Sbeveloper 		return B_BAD_VALUE;
139740f36b03Sbeveloper 	if (IS_INVALID_NODE(node))
13989e9417d2Sbeveloper 		return B_MEDIA_BAD_NODE;
13999e9417d2Sbeveloper 
14009e9417d2Sbeveloper 	server_get_live_node_info_request request;
14019e9417d2Sbeveloper 	server_get_live_node_info_reply reply;
14029e9417d2Sbeveloper 	status_t rv;
14039e9417d2Sbeveloper 
14049e9417d2Sbeveloper 	request.node = node;
14059e9417d2Sbeveloper 
1406*34c72144SAxel Dörfler 	rv = QueryServer(SERVER_GET_LIVE_NODE_INFO, &request, sizeof(request),
1407*34c72144SAxel Dörfler 		&reply, sizeof(reply));
14089e9417d2Sbeveloper 	if (rv != B_OK)
14099e9417d2Sbeveloper 		return rv;
14109e9417d2Sbeveloper 
14119e9417d2Sbeveloper 	*out_live_info = reply.live_info;
14129e9417d2Sbeveloper 	return B_OK;
141352a38012Sejakowatz }
141452a38012Sejakowatz 
141552a38012Sejakowatz 
141652a38012Sejakowatz status_t
1417*34c72144SAxel Dörfler BMediaRoster::GetLiveNodes(live_node_info* _liveNodes, int32* _totalCount,
1418*34c72144SAxel Dörfler 	const media_format* hasInput, const media_format* hasOutput,
1419*34c72144SAxel Dörfler 	const char* name, uint64 nodeKinds)
142052a38012Sejakowatz {
14219e9417d2Sbeveloper 	CALLED();
1422*34c72144SAxel Dörfler 	if (_liveNodes == NULL || _totalCount == NULL || *_totalCount <= 0)
14239e9417d2Sbeveloper 		return B_BAD_VALUE;
14249e9417d2Sbeveloper 
1425*34c72144SAxel Dörfler 	// TODO: we also support the wildcard search as GetDormantNodes does.
1426*34c72144SAxel Dörfler 	// This needs to be documented
14279e9417d2Sbeveloper 
14289e9417d2Sbeveloper 	server_get_live_nodes_request request;
14299e9417d2Sbeveloper 	server_get_live_nodes_reply reply;
14309e9417d2Sbeveloper 	status_t rv;
14319e9417d2Sbeveloper 
1432*34c72144SAxel Dörfler 	request.maxcount = *_totalCount;
1433*34c72144SAxel Dörfler 	request.has_input = hasInput != NULL;
1434*34c72144SAxel Dörfler 	if (hasInput != NULL) {
1435*34c72144SAxel Dörfler 		// TODO: we should not make a flat copy of media_format
1436*34c72144SAxel Dörfler 		request.inputformat = *hasInput;
1437*34c72144SAxel Dörfler 	}
1438*34c72144SAxel Dörfler 	request.has_output = hasOutput != NULL;
1439*34c72144SAxel Dörfler 	if (hasOutput != NULL) {
1440*34c72144SAxel Dörfler 		// TODO: we should not make a flat copy of media_format
1441*34c72144SAxel Dörfler 		request.outputformat = *hasOutput;
1442*34c72144SAxel Dörfler 	}
1443*34c72144SAxel Dörfler 	request.has_name = name != NULL;
1444*34c72144SAxel Dörfler 	if (name != NULL) {
14459e9417d2Sbeveloper 		int len = strlen(name);
14469e9417d2Sbeveloper 		len = min_c(len, (int)sizeof(request.name) - 1);
14479e9417d2Sbeveloper 		memcpy(request.name, name, len);
14489e9417d2Sbeveloper 		request.name[len] = 0;
14499e9417d2Sbeveloper 	}
1450*34c72144SAxel Dörfler 	request.require_kinds = nodeKinds;
14519e9417d2Sbeveloper 
1452*34c72144SAxel Dörfler 	rv = QueryServer(SERVER_GET_LIVE_NODES, &request, sizeof(request),
1453*34c72144SAxel Dörfler 		&reply, sizeof(reply));
14549e9417d2Sbeveloper 	if (rv != B_OK) {
14555ac4fbd7Sbeveloper 		ERROR("BMediaRoster::GetLiveNodes failed querying server\n");
1456*34c72144SAxel Dörfler 		*_totalCount = 0;
14579e9417d2Sbeveloper 		return rv;
14589e9417d2Sbeveloper 	}
14599e9417d2Sbeveloper 
14609e9417d2Sbeveloper 	if (reply.count > MAX_LIVE_INFO) {
1461*34c72144SAxel Dörfler 		live_node_info* liveInfo;
14629e9417d2Sbeveloper 		area_id clone;
14639e9417d2Sbeveloper 
1464*34c72144SAxel Dörfler 		clone = clone_area("live_node_info clone",
1465*34c72144SAxel Dörfler 			reinterpret_cast<void **>(&liveInfo), B_ANY_ADDRESS,
1466*34c72144SAxel Dörfler 			B_READ_AREA | B_WRITE_AREA, reply.area);
14679e9417d2Sbeveloper 		if (clone < B_OK) {
1468*34c72144SAxel Dörfler 			ERROR("BMediaRoster::GetLiveNodes failed to clone area, %#lx\n",
1469*34c72144SAxel Dörfler 				clone);
14709e9417d2Sbeveloper 			delete_area(reply.area);
1471*34c72144SAxel Dörfler 			*_totalCount = 0;
147252a38012Sejakowatz 			return B_ERROR;
147352a38012Sejakowatz 		}
147452a38012Sejakowatz 
14759e9417d2Sbeveloper 		for (int32 i = 0; i < reply.count; i++) {
1476*34c72144SAxel Dörfler 			_liveNodes[i] = liveInfo[i];
14779e9417d2Sbeveloper 		}
14789e9417d2Sbeveloper 
14799e9417d2Sbeveloper 		delete_area(clone);
14809e9417d2Sbeveloper 		delete_area(reply.area);
14819e9417d2Sbeveloper 	} else {
14829e9417d2Sbeveloper 		for (int32 i = 0; i < reply.count; i++) {
1483*34c72144SAxel Dörfler 			_liveNodes[i] = reply.live_info[i];
14849e9417d2Sbeveloper 		}
14859e9417d2Sbeveloper 	}
1486*34c72144SAxel Dörfler 	*_totalCount = reply.count;
14879e9417d2Sbeveloper 
14889e9417d2Sbeveloper 	return B_OK;
14899e9417d2Sbeveloper }
14909e9417d2Sbeveloper 
149152a38012Sejakowatz 
149252a38012Sejakowatz status_t
149352a38012Sejakowatz BMediaRoster::GetFreeInputsFor(const media_node& node,
1494*34c72144SAxel Dörfler 	media_input * out_free_inputs, int32 buf_num_inputs,
1495*34c72144SAxel Dörfler 	int32 * out_total_count, media_type filter_type)
149652a38012Sejakowatz {
14973620737cSbeveloper 	CALLED();
14985ac4fbd7Sbeveloper 	if (IS_INVALID_NODE(node)) {
1499*34c72144SAxel Dörfler 		ERROR("BMediaRoster::GetFreeInputsFor: node %ld, port %ld invalid\n",
1500*34c72144SAxel Dörfler 			node.node, node.port);
15013620737cSbeveloper 		return B_MEDIA_BAD_NODE;
15025ac4fbd7Sbeveloper 	}
15035ac4fbd7Sbeveloper 	if ((node.kind & B_BUFFER_CONSUMER) == 0) {
1504*34c72144SAxel Dörfler 		ERROR("BMediaRoster::GetFreeInputsFor: node %ld, port %ld is not a "
1505*34c72144SAxel Dörfler 			"consumer\n", node.node, node.port);
15065ac4fbd7Sbeveloper 		return B_MEDIA_BAD_NODE;
15075ac4fbd7Sbeveloper 	}
15083620737cSbeveloper 	if (out_free_inputs == NULL || out_total_count == NULL)
15093620737cSbeveloper 		return B_BAD_VALUE;
15103620737cSbeveloper 
151176669a29Sbeveloper 	List<media_input> list;
15123620737cSbeveloper 	media_input *input;
15133620737cSbeveloper 	status_t rv;
15143620737cSbeveloper 
15151299bfb2Sbeveloper 	*out_total_count = 0;
15161299bfb2Sbeveloper 
15178b04ffc1Sbeveloper 	rv = MediaRosterEx(this)->GetAllInputs(node, &list);
15183620737cSbeveloper 	if (B_OK != rv)
15193620737cSbeveloper 		return rv;
15203620737cSbeveloper 
1521*34c72144SAxel Dörfler 	PRINT(4, "BMediaRoster::GetFreeInputsFor node %ld, max %ld, filter-type "
1522*34c72144SAxel Dörfler 		"%ld\n", node.node, buf_num_inputs, filter_type);
15235ac4fbd7Sbeveloper 
152476669a29Sbeveloper 	int32 i;
1525b65a0ac5SJérôme Duval 	for (i = 0, list.Rewind(); list.GetNext(&input);) {
1526*34c72144SAxel Dörfler 		if (filter_type != B_MEDIA_UNKNOWN_TYPE
1527*34c72144SAxel Dörfler 			&& filter_type != input->format.type) {
1528*34c72144SAxel Dörfler 			// media_type used, but doesn't match
1529*34c72144SAxel Dörfler 			continue;
1530*34c72144SAxel Dörfler 		}
1531*34c72144SAxel Dörfler 		if (input->source != media_source::null) {
1532*34c72144SAxel Dörfler 			// consumer source already connected
1533*34c72144SAxel Dörfler 			continue;
1534*34c72144SAxel Dörfler 		}
1535*34c72144SAxel Dörfler 
15363620737cSbeveloper 		out_free_inputs[i] = *input;
15373620737cSbeveloper 		*out_total_count += 1;
15383620737cSbeveloper 		buf_num_inputs -= 1;
15395ac4fbd7Sbeveloper 		#if DEBUG >= 3
15405ac4fbd7Sbeveloper 			PRINT_OUTPUT("  input", out_free_inputs[i]);
15415ac4fbd7Sbeveloper 		#endif
15423620737cSbeveloper 		if (buf_num_inputs == 0)
15433620737cSbeveloper 			break;
1544b65a0ac5SJérôme Duval 		i++;
15453620737cSbeveloper 	}
15463620737cSbeveloper 
15478b04ffc1Sbeveloper 	MediaRosterEx(this)->PublishInputs(node, &list);
15483620737cSbeveloper 	return B_OK;
154952a38012Sejakowatz }
155052a38012Sejakowatz 
155152a38012Sejakowatz 
155252a38012Sejakowatz status_t
155352a38012Sejakowatz BMediaRoster::GetConnectedInputsFor(const media_node& node,
1554*34c72144SAxel Dörfler 	media_input* out_active_inputs, int32 buf_num_inputs,
155552a38012Sejakowatz 	int32* out_total_count)
155652a38012Sejakowatz {
15573620737cSbeveloper 	CALLED();
155840f36b03Sbeveloper 	if (IS_INVALID_NODE(node) || (node.kind & B_BUFFER_CONSUMER) == 0)
15593620737cSbeveloper 		return B_MEDIA_BAD_NODE;
15603620737cSbeveloper 	if (out_active_inputs == NULL || out_total_count == NULL)
15613620737cSbeveloper 		return B_BAD_VALUE;
15623620737cSbeveloper 
156376669a29Sbeveloper 	List<media_input> list;
15643620737cSbeveloper 	media_input *input;
15653620737cSbeveloper 	status_t rv;
15663620737cSbeveloper 
15671299bfb2Sbeveloper 	*out_total_count = 0;
15681299bfb2Sbeveloper 
15698b04ffc1Sbeveloper 	rv = MediaRosterEx(this)->GetAllInputs(node, &list);
15703620737cSbeveloper 	if (B_OK != rv)
15713620737cSbeveloper 		return rv;
15723620737cSbeveloper 
1573*34c72144SAxel Dörfler 	PRINT(4, "BMediaRoster::GetConnectedInputsFor node %ld, max %ld\n",
1574*34c72144SAxel Dörfler 		node.node, buf_num_inputs);
15755ac4fbd7Sbeveloper 
157676669a29Sbeveloper 	int32 i;
1577b65a0ac5SJérôme Duval 	for (i = 0, list.Rewind(); list.GetNext(&input);) {
15783620737cSbeveloper 		if (input->source == media_source::null)
15793620737cSbeveloper 			continue; // consumer source not connected
15803620737cSbeveloper 		out_active_inputs[i] = *input;
15813620737cSbeveloper 		*out_total_count += 1;
15823620737cSbeveloper 		buf_num_inputs -= 1;
15835ac4fbd7Sbeveloper 		#if DEBUG >= 3
15845ac4fbd7Sbeveloper 			PRINT_OUTPUT("  input ", out_active_inputs[i]);
15855ac4fbd7Sbeveloper 		#endif
15863620737cSbeveloper 		if (buf_num_inputs == 0)
15873620737cSbeveloper 			break;
1588b65a0ac5SJérôme Duval 		i++;
15893620737cSbeveloper 	}
15903620737cSbeveloper 
15918b04ffc1Sbeveloper 	MediaRosterEx(this)->PublishInputs(node, &list);
15923620737cSbeveloper 	return B_OK;
159352a38012Sejakowatz }
159452a38012Sejakowatz 
159552a38012Sejakowatz 
159652a38012Sejakowatz status_t
1597*34c72144SAxel Dörfler BMediaRoster::GetAllInputsFor(const media_node& node, media_input* out_inputs,
1598*34c72144SAxel Dörfler 	int32 buf_num_inputs, int32* out_total_count)
159952a38012Sejakowatz {
160052a38012Sejakowatz 	CALLED();
160140f36b03Sbeveloper 	if (IS_INVALID_NODE(node) || (node.kind & B_BUFFER_CONSUMER) == 0)
160252a38012Sejakowatz 		return B_MEDIA_BAD_NODE;
160352a38012Sejakowatz 	if (out_inputs == NULL || out_total_count == NULL)
160452a38012Sejakowatz 		return B_BAD_VALUE;
160552a38012Sejakowatz 
160676669a29Sbeveloper 	List<media_input> list;
16073620737cSbeveloper 	media_input *input;
160852a38012Sejakowatz 	status_t rv;
160952a38012Sejakowatz 
16101299bfb2Sbeveloper 	*out_total_count = 0;
16111299bfb2Sbeveloper 
16128b04ffc1Sbeveloper 	rv = MediaRosterEx(this)->GetAllInputs(node, &list);
16133620737cSbeveloper 	if (B_OK != rv)
16143620737cSbeveloper 		return rv;
16153620737cSbeveloper 
1616*34c72144SAxel Dörfler 	PRINT(4, "BMediaRoster::GetAllInputsFor node %ld, max %ld\n", node.node,
1617*34c72144SAxel Dörfler 		buf_num_inputs);
16185ac4fbd7Sbeveloper 
161976669a29Sbeveloper 	int32 i;
162076669a29Sbeveloper 	for (i = 0, list.Rewind(); list.GetNext(&input); i++) {
16213620737cSbeveloper 		out_inputs[i] = *input;
162252a38012Sejakowatz 		*out_total_count += 1;
16233620737cSbeveloper 		buf_num_inputs -= 1;
16245ac4fbd7Sbeveloper 		#if DEBUG >= 3
16255ac4fbd7Sbeveloper 			PRINT_OUTPUT("  input ", out_inputs[i]);
16265ac4fbd7Sbeveloper 		#endif
16273620737cSbeveloper 		if (buf_num_inputs == 0)
16283620737cSbeveloper 			break;
162952a38012Sejakowatz 	}
163052a38012Sejakowatz 
16318b04ffc1Sbeveloper 	MediaRosterEx(this)->PublishInputs(node, &list);
16323620737cSbeveloper 	return B_OK;
163352a38012Sejakowatz }
163452a38012Sejakowatz 
163552a38012Sejakowatz 
163652a38012Sejakowatz status_t
163752a38012Sejakowatz BMediaRoster::GetFreeOutputsFor(const media_node& node,
1638*34c72144SAxel Dörfler 	media_output* out_free_outputs, int32 buf_num_outputs,
1639*34c72144SAxel Dörfler 	int32* out_total_count, media_type filter_type)
164052a38012Sejakowatz {
16413620737cSbeveloper 	CALLED();
164240f36b03Sbeveloper 	if (IS_INVALID_NODE(node) || (node.kind & B_BUFFER_PRODUCER) == 0)
16433620737cSbeveloper 		return B_MEDIA_BAD_NODE;
16443620737cSbeveloper 	if (out_free_outputs == NULL || out_total_count == NULL)
16453620737cSbeveloper 		return B_BAD_VALUE;
16463620737cSbeveloper 
164776669a29Sbeveloper 	List<media_output> list;
16483620737cSbeveloper 	media_output *output;
16493620737cSbeveloper 	status_t rv;
16503620737cSbeveloper 
16511299bfb2Sbeveloper 	*out_total_count = 0;
16521299bfb2Sbeveloper 
16538b04ffc1Sbeveloper 	rv = MediaRosterEx(this)->GetAllOutputs(node, &list);
16543620737cSbeveloper 	if (B_OK != rv)
16553620737cSbeveloper 		return rv;
16563620737cSbeveloper 
1657*34c72144SAxel Dörfler 	PRINT(4, "BMediaRoster::GetFreeOutputsFor node %ld, max %ld, filter-type "
1658*34c72144SAxel Dörfler 		"%ld\n", node.node, buf_num_outputs, filter_type);
16595ac4fbd7Sbeveloper 
166076669a29Sbeveloper 	int32 i;
1661b65a0ac5SJérôme Duval 	for (i = 0, list.Rewind(); list.GetNext(&output);) {
1662*34c72144SAxel Dörfler 		if (filter_type != B_MEDIA_UNKNOWN_TYPE
1663*34c72144SAxel Dörfler 			&& filter_type != output->format.type) {
1664*34c72144SAxel Dörfler 			// media_type used, but doesn't match
1665*34c72144SAxel Dörfler 			continue;
1666*34c72144SAxel Dörfler 		}
1667*34c72144SAxel Dörfler 		if (output->destination != media_destination::null) {
1668*34c72144SAxel Dörfler 			// producer destination already connected
1669*34c72144SAxel Dörfler 			continue;
1670*34c72144SAxel Dörfler 		}
1671*34c72144SAxel Dörfler 
16723620737cSbeveloper 		out_free_outputs[i] = *output;
16733620737cSbeveloper 		*out_total_count += 1;
16743620737cSbeveloper 		buf_num_outputs -= 1;
16755ac4fbd7Sbeveloper 		#if DEBUG >= 3
16765ac4fbd7Sbeveloper 			PRINT_OUTPUT("  output ", out_free_outputs[i]);
16775ac4fbd7Sbeveloper 		#endif
16783620737cSbeveloper 		if (buf_num_outputs == 0)
16793620737cSbeveloper 			break;
1680b65a0ac5SJérôme Duval 		i++;
16813620737cSbeveloper 	}
16823620737cSbeveloper 
16838b04ffc1Sbeveloper 	MediaRosterEx(this)->PublishOutputs(node, &list);
16843620737cSbeveloper 	return B_OK;
168552a38012Sejakowatz }
168652a38012Sejakowatz 
168752a38012Sejakowatz 
168852a38012Sejakowatz status_t
168952a38012Sejakowatz BMediaRoster::GetConnectedOutputsFor(const media_node& node,
1690*34c72144SAxel Dörfler 	media_output* out_active_outputs, int32 buf_num_outputs,
169152a38012Sejakowatz 	int32* out_total_count)
169252a38012Sejakowatz {
16933620737cSbeveloper 	CALLED();
169440f36b03Sbeveloper 	if (IS_INVALID_NODE(node) || (node.kind & B_BUFFER_PRODUCER) == 0)
16953620737cSbeveloper 		return B_MEDIA_BAD_NODE;
16963620737cSbeveloper 	if (out_active_outputs == NULL || out_total_count == NULL)
16973620737cSbeveloper 		return B_BAD_VALUE;
16983620737cSbeveloper 
169976669a29Sbeveloper 	List<media_output> list;
17003620737cSbeveloper 	media_output *output;
17013620737cSbeveloper 	status_t rv;
17023620737cSbeveloper 
17031299bfb2Sbeveloper 	*out_total_count = 0;
17041299bfb2Sbeveloper 
17058b04ffc1Sbeveloper 	rv = MediaRosterEx(this)->GetAllOutputs(node, &list);
17063620737cSbeveloper 	if (B_OK != rv)
17073620737cSbeveloper 		return rv;
17083620737cSbeveloper 
1709*34c72144SAxel Dörfler 	PRINT(4, "BMediaRoster::GetConnectedOutputsFor node %ld, max %ld\n",
1710*34c72144SAxel Dörfler 		node.node, buf_num_outputs);
17115ac4fbd7Sbeveloper 
171276669a29Sbeveloper 	int32 i;
1713b65a0ac5SJérôme Duval 	for (i = 0, list.Rewind(); list.GetNext(&output);) {
1714*34c72144SAxel Dörfler 		if (output->destination == media_destination::null) {
1715*34c72144SAxel Dörfler 			// producer destination not connected
1716*34c72144SAxel Dörfler 			continue;
1717*34c72144SAxel Dörfler 		}
17183620737cSbeveloper 		out_active_outputs[i] = *output;
17193620737cSbeveloper 		*out_total_count += 1;
17203620737cSbeveloper 		buf_num_outputs -= 1;
17215ac4fbd7Sbeveloper 		#if DEBUG >= 3
17225ac4fbd7Sbeveloper 			PRINT_OUTPUT("  output ", out_active_outputs[i]);
17235ac4fbd7Sbeveloper 		#endif
17243620737cSbeveloper 		if (buf_num_outputs == 0)
17253620737cSbeveloper 			break;
1726b65a0ac5SJérôme Duval 		i++;
17273620737cSbeveloper 	}
17283620737cSbeveloper 
17298b04ffc1Sbeveloper 	MediaRosterEx(this)->PublishOutputs(node, &list);
17303620737cSbeveloper 	return B_OK;
173152a38012Sejakowatz }
173252a38012Sejakowatz 
173352a38012Sejakowatz 
173452a38012Sejakowatz status_t
173552a38012Sejakowatz BMediaRoster::GetAllOutputsFor(const media_node& node,
1736*34c72144SAxel Dörfler 	media_output* out_outputs, int32 buf_num_outputs, int32* out_total_count)
173752a38012Sejakowatz {
173852a38012Sejakowatz 	CALLED();
173940f36b03Sbeveloper 	if (IS_INVALID_NODE(node) || (node.kind & B_BUFFER_PRODUCER) == 0)
174052a38012Sejakowatz 		return B_MEDIA_BAD_NODE;
174152a38012Sejakowatz 	if (out_outputs == NULL || out_total_count == NULL)
174252a38012Sejakowatz 		return B_BAD_VALUE;
174352a38012Sejakowatz 
174476669a29Sbeveloper 	List<media_output> list;
17453620737cSbeveloper 	media_output *output;
174652a38012Sejakowatz 	status_t rv;
174752a38012Sejakowatz 
17481299bfb2Sbeveloper 	*out_total_count = 0;
17491299bfb2Sbeveloper 
17508b04ffc1Sbeveloper 	rv = MediaRosterEx(this)->GetAllOutputs(node, &list);
17513620737cSbeveloper 	if (B_OK != rv)
17523620737cSbeveloper 		return rv;
17533620737cSbeveloper 
1754*34c72144SAxel Dörfler 	PRINT(4, "BMediaRoster::GetAllOutputsFor node %ld, max %ld\n", node.node,
1755*34c72144SAxel Dörfler 		buf_num_outputs);
17565ac4fbd7Sbeveloper 
175776669a29Sbeveloper 	int32 i;
175876669a29Sbeveloper 	for (i = 0, list.Rewind(); list.GetNext(&output); i++) {
17593620737cSbeveloper 		out_outputs[i] = *output;
176052a38012Sejakowatz 		*out_total_count += 1;
17613620737cSbeveloper 		buf_num_outputs -= 1;
17625ac4fbd7Sbeveloper 		#if DEBUG >= 3
17635ac4fbd7Sbeveloper 			PRINT_OUTPUT("  output ", out_outputs[i]);
17645ac4fbd7Sbeveloper 		#endif
17653620737cSbeveloper 		if (buf_num_outputs == 0)
17663620737cSbeveloper 			break;
176752a38012Sejakowatz 	}
176852a38012Sejakowatz 
17698b04ffc1Sbeveloper 	MediaRosterEx(this)->PublishOutputs(node, &list);
17703620737cSbeveloper 	return B_OK;
177152a38012Sejakowatz }
177252a38012Sejakowatz 
177352a38012Sejakowatz 
177452a38012Sejakowatz status_t
177552a38012Sejakowatz BMediaRoster::StartWatching(const BMessenger& where)
177652a38012Sejakowatz {
1777eae26d3dSbeveloper 	CALLED();
1778eae26d3dSbeveloper 	if (!where.IsValid()) {
17795ac4fbd7Sbeveloper 		ERROR("BMediaRoster::StartWatching: messenger invalid!\n");
1780eae26d3dSbeveloper 		return B_BAD_VALUE;
1781eae26d3dSbeveloper 	}
1782*34c72144SAxel Dörfler 	return BPrivate::media::notifications::Register(where, media_node::null,
1783*34c72144SAxel Dörfler 		B_MEDIA_WILDCARD);
178452a38012Sejakowatz }
178552a38012Sejakowatz 
178652a38012Sejakowatz 
178752a38012Sejakowatz status_t
1788*34c72144SAxel Dörfler BMediaRoster::StartWatching(const BMessenger & where, int32 notificationType)
178952a38012Sejakowatz {
1790eae26d3dSbeveloper 	CALLED();
1791eae26d3dSbeveloper 	if (!where.IsValid()) {
17925ac4fbd7Sbeveloper 		ERROR("BMediaRoster::StartWatching: messenger invalid!\n");
1793eae26d3dSbeveloper 		return B_BAD_VALUE;
1794eae26d3dSbeveloper 	}
1795*34c72144SAxel Dörfler 	if (!BPrivate::media::notifications::IsValidNotificationRequest(false,
1796*34c72144SAxel Dörfler 			notificationType)) {
17975ac4fbd7Sbeveloper 		ERROR("BMediaRoster::StartWatching: notificationType invalid!\n");
1798eae26d3dSbeveloper 		return B_BAD_VALUE;
1799eae26d3dSbeveloper 	}
1800*34c72144SAxel Dörfler 	return BPrivate::media::notifications::Register(where, media_node::null,
1801*34c72144SAxel Dörfler 		notificationType);
180252a38012Sejakowatz }
180352a38012Sejakowatz 
180452a38012Sejakowatz 
180552a38012Sejakowatz status_t
1806*34c72144SAxel Dörfler BMediaRoster::StartWatching(const BMessenger& where, const media_node& node,
180752a38012Sejakowatz 	int32 notificationType)
180852a38012Sejakowatz {
1809eae26d3dSbeveloper 	CALLED();
1810eae26d3dSbeveloper 	if (!where.IsValid()) {
18115ac4fbd7Sbeveloper 		ERROR("BMediaRoster::StartWatching: messenger invalid!\n");
1812eae26d3dSbeveloper 		return B_BAD_VALUE;
1813eae26d3dSbeveloper 	}
181440f36b03Sbeveloper 	if (IS_INVALID_NODE(node)) {
18155ac4fbd7Sbeveloper 		ERROR("BMediaRoster::StartWatching: node invalid!\n");
1816eae26d3dSbeveloper 		return B_MEDIA_BAD_NODE;
1817eae26d3dSbeveloper 	}
1818*34c72144SAxel Dörfler 	if (!BPrivate::media::notifications::IsValidNotificationRequest(true,
1819*34c72144SAxel Dörfler 			notificationType)) {
18205ac4fbd7Sbeveloper 		ERROR("BMediaRoster::StartWatching: notificationType invalid!\n");
1821eae26d3dSbeveloper 		return B_BAD_VALUE;
1822eae26d3dSbeveloper 	}
1823*34c72144SAxel Dörfler 	return BPrivate::media::notifications::Register(where, node,
1824*34c72144SAxel Dörfler 		notificationType);
182552a38012Sejakowatz }
182652a38012Sejakowatz 
182752a38012Sejakowatz 
182852a38012Sejakowatz status_t
182952a38012Sejakowatz BMediaRoster::StopWatching(const BMessenger& where)
183052a38012Sejakowatz {
1831eae26d3dSbeveloper 	CALLED();
1832eae26d3dSbeveloper 	// messenger may already be invalid, so we don't check this
1833*34c72144SAxel Dörfler 	return BPrivate::media::notifications::Unregister(where, media_node::null,
1834*34c72144SAxel Dörfler 		B_MEDIA_WILDCARD);
183552a38012Sejakowatz }
183652a38012Sejakowatz 
183752a38012Sejakowatz 
183852a38012Sejakowatz status_t
1839*34c72144SAxel Dörfler BMediaRoster::StopWatching(const BMessenger& where, int32 notificationType)
184052a38012Sejakowatz {
1841eae26d3dSbeveloper 	CALLED();
1842eae26d3dSbeveloper 	// messenger may already be invalid, so we don't check this
1843*34c72144SAxel Dörfler 	if (!BPrivate::media::notifications::IsValidNotificationRequest(false,
1844*34c72144SAxel Dörfler 			notificationType)) {
18455ac4fbd7Sbeveloper 		ERROR("BMediaRoster::StopWatching: notificationType invalid!\n");
1846eae26d3dSbeveloper 		return B_BAD_VALUE;
1847eae26d3dSbeveloper 	}
1848*34c72144SAxel Dörfler 	return BPrivate::media::notifications::Unregister(where, media_node::null,
1849*34c72144SAxel Dörfler 		notificationType);
185052a38012Sejakowatz }
185152a38012Sejakowatz 
185252a38012Sejakowatz 
185352a38012Sejakowatz status_t
1854*34c72144SAxel Dörfler BMediaRoster::StopWatching(const BMessenger& where, const media_node& node,
185552a38012Sejakowatz 	int32 notificationType)
185652a38012Sejakowatz {
1857eae26d3dSbeveloper 	CALLED();
1858eae26d3dSbeveloper 	// messenger may already be invalid, so we don't check this
185940f36b03Sbeveloper 	if (IS_INVALID_NODE(node)) {
18605ac4fbd7Sbeveloper 		ERROR("BMediaRoster::StopWatching: node invalid!\n");
1861eae26d3dSbeveloper 		return B_MEDIA_BAD_NODE;
1862eae26d3dSbeveloper 	}
1863*34c72144SAxel Dörfler 	if (!BPrivate::media::notifications::IsValidNotificationRequest(true,
1864*34c72144SAxel Dörfler 			notificationType)) {
18655ac4fbd7Sbeveloper 		ERROR("BMediaRoster::StopWatching: notificationType invalid!\n");
1866eae26d3dSbeveloper 		return B_BAD_VALUE;
1867eae26d3dSbeveloper 	}
1868*34c72144SAxel Dörfler 	return BPrivate::media::notifications::Unregister(where, node,
1869*34c72144SAxel Dörfler 		notificationType);
187052a38012Sejakowatz }
187152a38012Sejakowatz 
187252a38012Sejakowatz 
187352a38012Sejakowatz status_t
187452a38012Sejakowatz BMediaRoster::RegisterNode(BMediaNode* node)
187552a38012Sejakowatz {
187654187cc6Sbeveloper 	CALLED();
187754187cc6Sbeveloper 	// addon-id = -1 (unused), addon-flavor-id = 0 (unused, too)
187854187cc6Sbeveloper 	return MediaRosterEx(this)->RegisterNode(node, -1, 0);
187954187cc6Sbeveloper }
188054187cc6Sbeveloper 
188154187cc6Sbeveloper 
188254187cc6Sbeveloper status_t
1883*34c72144SAxel Dörfler BMediaRosterEx::RegisterNode(BMediaNode* node, media_addon_id addonid,
1884*34c72144SAxel Dörfler 	int32 flavorid)
188554187cc6Sbeveloper {
188652a38012Sejakowatz 	CALLED();
188752a38012Sejakowatz 	if (node == NULL)
188852a38012Sejakowatz 		return B_BAD_VALUE;
188952a38012Sejakowatz 
189054187cc6Sbeveloper 	// some sanity check
189154187cc6Sbeveloper 	// I'm not sure if the media kit warrants to call BMediaNode::AddOn() here.
189254187cc6Sbeveloper 	// Perhaps we don't need it.
189354187cc6Sbeveloper 	{
18949e9417d2Sbeveloper 		BMediaAddOn *addon;
18959e9417d2Sbeveloper 		int32 addon_flavor_id;
18969e9417d2Sbeveloper 		media_addon_id addon_id;
18979e9417d2Sbeveloper 		addon_flavor_id = 0;
18989e9417d2Sbeveloper 		addon = node->AddOn(&addon_flavor_id);
18999e9417d2Sbeveloper 		addon_id = addon ? addon->AddonID() : -1;
190054187cc6Sbeveloper 		ASSERT(addonid == addon_id);
190154187cc6Sbeveloper 		ASSERT(flavorid == addon_flavor_id);
190254187cc6Sbeveloper 	}
190352a38012Sejakowatz 
190454187cc6Sbeveloper 	status_t rv;
19059e9417d2Sbeveloper 	server_register_node_request request;
19069e9417d2Sbeveloper 	server_register_node_reply reply;
19079e9417d2Sbeveloper 
190854187cc6Sbeveloper 	request.addon_id = addonid;
190954187cc6Sbeveloper 	request.addon_flavor_id = flavorid;
19109e9417d2Sbeveloper 	strcpy(request.name, node->Name());
19119e9417d2Sbeveloper 	request.kinds = node->Kinds();
19129e9417d2Sbeveloper 	request.port = node->ControlPort();
19139e9417d2Sbeveloper 	request.team = team;
19149e9417d2Sbeveloper 
1915*34c72144SAxel Dörfler 	TRACE("BMediaRoster::RegisterNode: sending SERVER_REGISTER_NODE: port "
1916*34c72144SAxel Dörfler 		"%ld, kinds 0x%Lx, team %ld, name '%s'\n", request.port, request.kinds,
1917*34c72144SAxel Dörfler 		request.team, request.name);
19181299bfb2Sbeveloper 
1919*34c72144SAxel Dörfler 	rv = QueryServer(SERVER_REGISTER_NODE, &request, sizeof(request), &reply,
1920*34c72144SAxel Dörfler 		sizeof(reply));
19219e9417d2Sbeveloper 	if (rv != B_OK) {
1922*34c72144SAxel Dörfler 		ERROR("BMediaRoster::RegisterNode: failed to register node %s (error "
1923*34c72144SAxel Dörfler 			"%#lx)\n", node->Name(), rv);
19249e9417d2Sbeveloper 		return rv;
19259e9417d2Sbeveloper 	}
19269e9417d2Sbeveloper 
1927*34c72144SAxel Dörfler 	TRACE("BMediaRoster::RegisterNode: QueryServer SERVER_REGISTER_NODE "
1928*34c72144SAxel Dörfler 		"finished\n");
19294295907bSbeveloper 
19308b04ffc1Sbeveloper 	// we are a friend class of BMediaNode and initialize this member variable
19319e9417d2Sbeveloper 	node->fNodeID = reply.nodeid;
19329e9417d2Sbeveloper 	ASSERT(reply.nodeid == node->Node().node);
19339e9417d2Sbeveloper 	ASSERT(reply.nodeid == node->ID());
19349e9417d2Sbeveloper 
19359e9417d2Sbeveloper 	// call the callback
19369e9417d2Sbeveloper 	node->NodeRegistered();
19373620737cSbeveloper 
19384295907bSbeveloper 	TRACE("BMediaRoster::RegisterNode: NodeRegistered callback finished\n");
19394295907bSbeveloper 
1940*34c72144SAxel Dörfler 	// if the BMediaNode also inherits from BTimeSource, we need to call
1941*34c72144SAxel Dörfler 	// BTimeSource::FinishCreate()
19420e21b167Sbeveloper 	if (node->Kinds() & B_TIME_SOURCE) {
19430e21b167Sbeveloper 		BTimeSource *ts;
19440e21b167Sbeveloper 		ts = dynamic_cast<BTimeSource *>(node);
19450e21b167Sbeveloper 		if (ts)
19460e21b167Sbeveloper 			ts->FinishCreate();
19470e21b167Sbeveloper 	}
19480e21b167Sbeveloper 
19494295907bSbeveloper 	TRACE("BMediaRoster::RegisterNode: publishing inputs/outputs\n");
19504295907bSbeveloper 
19513620737cSbeveloper 	// register existing inputs and outputs with the
19523620737cSbeveloper 	// media_server, this allows GetLiveNodes() to work
19533620737cSbeveloper 	// with created, but unconnected nodes.
19544d2d96e0Sbeveloper 	// The node control loop might not be running, or might deadlock
19554d2d96e0Sbeveloper 	// if we send a message and wait for a reply here.
19564d2d96e0Sbeveloper 	// We have a pointer to the node, and thus call the functions directly
19574295907bSbeveloper 
19583620737cSbeveloper 	if (node->Kinds() & B_BUFFER_PRODUCER) {
19594d2d96e0Sbeveloper 		BBufferProducer *bp;
19604d2d96e0Sbeveloper 		bp = dynamic_cast<BBufferProducer *>(node);
19614d2d96e0Sbeveloper 		if (bp) {
1962359ac306Sbeveloper 			List<media_output> list;
19634d2d96e0Sbeveloper 			if (B_OK == GetAllOutputs(bp, &list))
1964359ac306Sbeveloper 				PublishOutputs(node->Node(), &list);
196521871f38Sbeveloper 		}
19664d2d96e0Sbeveloper 	}
196721871f38Sbeveloper 	if (node->Kinds() & B_BUFFER_CONSUMER) {
19684d2d96e0Sbeveloper 		BBufferConsumer *bc;
19694d2d96e0Sbeveloper 		bc = dynamic_cast<BBufferConsumer *>(node);
19704d2d96e0Sbeveloper 		if (bc) {
1971359ac306Sbeveloper 			List<media_input> list;
19724d2d96e0Sbeveloper 			if (B_OK == GetAllInputs(bc, &list))
1973359ac306Sbeveloper 				PublishInputs(node->Node(), &list);
19743620737cSbeveloper 		}
19754d2d96e0Sbeveloper 	}
197621871f38Sbeveloper 
19774295907bSbeveloper 	TRACE("BMediaRoster::RegisterNode: sending NodesCreated\n");
19784295907bSbeveloper 
19791299bfb2Sbeveloper 	BPrivate::media::notifications::NodesCreated(&reply.nodeid, 1);
19804295907bSbeveloper 
19814295907bSbeveloper 	TRACE("BMediaRoster::RegisterNode: finished\n");
19824295907bSbeveloper 
1983570f7d04Sbeveloper /*
1984570f7d04Sbeveloper 	TRACE("BMediaRoster::RegisterNode: registered node name '%s', id %ld, addon %ld, flavor %ld\n", node->Name(), node->ID(), addon_id, addon_flavor_id);
1985570f7d04Sbeveloper 	TRACE("BMediaRoster::RegisterNode: node this               %p\n", node);
1986570f7d04Sbeveloper 	TRACE("BMediaRoster::RegisterNode: node fConsumerThis      %p\n", node->fConsumerThis);
1987570f7d04Sbeveloper 	TRACE("BMediaRoster::RegisterNode: node fProducerThis      %p\n", node->fProducerThis);
1988570f7d04Sbeveloper 	TRACE("BMediaRoster::RegisterNode: node fFileInterfaceThis %p\n", node->fFileInterfaceThis);
1989570f7d04Sbeveloper 	TRACE("BMediaRoster::RegisterNode: node fControllableThis  %p\n", node->fControllableThis);
1990570f7d04Sbeveloper 	TRACE("BMediaRoster::RegisterNode: node fTimeSourceThis    %p\n", node->fTimeSourceThis);
1991570f7d04Sbeveloper */
19929e9417d2Sbeveloper 	return B_OK;
199352a38012Sejakowatz }
199452a38012Sejakowatz 
199552a38012Sejakowatz 
199652a38012Sejakowatz status_t
199752a38012Sejakowatz BMediaRoster::UnregisterNode(BMediaNode* node)
199852a38012Sejakowatz {
19999e9417d2Sbeveloper 	CALLED();
20009e9417d2Sbeveloper 	if (node == NULL)
20019e9417d2Sbeveloper 		return B_BAD_VALUE;
20029e9417d2Sbeveloper 
200360f15390Sbeveloper 	TRACE("BMediaRoster::UnregisterNode %ld (%p)\n", node->ID(), node);
200460f15390Sbeveloper 
200586bce45bSbeveloper 	if (node->fKinds & NODE_KIND_NO_REFCOUNTING) {
2006*34c72144SAxel Dörfler 		TRACE("BMediaRoster::UnregisterNode, trying to unregister reference "
2007*34c72144SAxel Dörfler 			"counting disabled timesource, node %ld, port %ld, team %ld\n",
2008*34c72144SAxel Dörfler 			node->ID(), node->ControlPort(), team);
200986bce45bSbeveloper 		return B_OK;
201086bce45bSbeveloper 	}
20118b04ffc1Sbeveloper 	if (node->ID() == NODE_UNREGISTERED_ID) {
2012*34c72144SAxel Dörfler 		PRINT(1, "Warning: BMediaRoster::UnregisterNode: node id %ld, name "
2013*34c72144SAxel Dörfler 			"'%s' already unregistered\n", node->ID(), node->Name());
20149e9417d2Sbeveloper 		return B_OK;
20159e9417d2Sbeveloper 	}
201654187cc6Sbeveloper 	if (node->fRefCount != 0) {
2017*34c72144SAxel Dörfler 		PRINT(1, "Warning: BMediaRoster::UnregisterNode: node id %ld, name "
2018*34c72144SAxel Dörfler 			"'%s' has local reference count of %ld\n", node->ID(), node->Name(),
2019*34c72144SAxel Dörfler 			node->fRefCount);
202054187cc6Sbeveloper 		// no return here, we continue and unregister!
202154187cc6Sbeveloper 	}
202254187cc6Sbeveloper 
2023*34c72144SAxel Dörfler 	// Calling BMediaAddOn::GetConfigurationFor(BMediaNode *node,
2024*34c72144SAxel Dörfler 	// BMessage *config) if this node was instanciated by an add-on needs to
2025*34c72144SAxel Dörfler 	// be done *somewhere*
202654187cc6Sbeveloper 	// We can't do it here because it is already to late (destructor of the node
202754187cc6Sbeveloper 	// might have been called).
20289e9417d2Sbeveloper 
20299e9417d2Sbeveloper 	server_unregister_node_request request;
20309e9417d2Sbeveloper 	server_unregister_node_reply reply;
20319e9417d2Sbeveloper 	status_t rv;
20329e9417d2Sbeveloper 
20339e9417d2Sbeveloper 	request.nodeid = node->ID();
20349e9417d2Sbeveloper 	request.team = team;
20359e9417d2Sbeveloper 
20361299bfb2Sbeveloper 	// send a notification
20371299bfb2Sbeveloper 	BPrivate::media::notifications::NodesDeleted(&request.nodeid, 1);
20381299bfb2Sbeveloper 
2039*34c72144SAxel Dörfler 	rv = QueryServer(SERVER_UNREGISTER_NODE, &request, sizeof(request), &reply,
2040*34c72144SAxel Dörfler 		sizeof(reply));
20419e9417d2Sbeveloper 	if (rv != B_OK) {
2042*34c72144SAxel Dörfler 		ERROR("BMediaRoster::UnregisterNode: failed to unregister node id %ld, "
2043*34c72144SAxel Dörfler 			"name '%s' (error %#lx)\n", node->ID(), node->Name(), rv);
20449e9417d2Sbeveloper 		return rv;
20459e9417d2Sbeveloper 	}
20469e9417d2Sbeveloper 
204754187cc6Sbeveloper 	if (reply.addonid != -1) {
204854187cc6Sbeveloper 		// Small problem here, we can't use DormantNodeManager::PutAddon(), as
2049*34c72144SAxel Dörfler 		// UnregisterNode() is called by a dormant node itself (by the
2050*34c72144SAxel Dörfler 		// destructor).
205154187cc6Sbeveloper 		// The add-on that contains the node needs to remain in memory until the
205254187cc6Sbeveloper 		// destructor execution is finished.
205354187cc6Sbeveloper 		// DormantNodeManager::PutAddonDelayed() will delay unloading.
205454187cc6Sbeveloper 		_DormantNodeManager->PutAddonDelayed(reply.addonid);
2055cf4e2277Sbeveloper 
2056*34c72144SAxel Dörfler 		rv = MediaRosterEx(this)->DecrementAddonFlavorInstancesCount(
2057*34c72144SAxel Dörfler 			reply.addonid, reply.flavorid);
205854187cc6Sbeveloper 		if (rv != B_OK) {
2059*34c72144SAxel Dörfler 			ERROR("BMediaRoster::UnregisterNode: "
2060*34c72144SAxel Dörfler 				"DecrementAddonFlavorInstancesCount() failed\n");
206154187cc6Sbeveloper 			// this is really a problem, but we can't fail now
206254187cc6Sbeveloper 		}
20638b04ffc1Sbeveloper 	}
20649e9417d2Sbeveloper 
20651299bfb2Sbeveloper 	// we are a friend class of BMediaNode and invalidate this member variable
20668b04ffc1Sbeveloper 	node->fNodeID = NODE_UNREGISTERED_ID;
20679e9417d2Sbeveloper 
20689e9417d2Sbeveloper 	return B_OK;
206952a38012Sejakowatz }
207052a38012Sejakowatz 
207152a38012Sejakowatz 
2072*34c72144SAxel Dörfler //!	Thread safe for multiple calls to Roster()
207352a38012Sejakowatz /*static*/ BMediaRoster*
207452a38012Sejakowatz BMediaRoster::Roster(status_t* out_error)
207552a38012Sejakowatz {
207652a38012Sejakowatz 	static BLocker locker("BMediaRoster::Roster locker");
207752a38012Sejakowatz 	locker.Lock();
20788496c38aSbeveloper 	if (out_error)
20798496c38aSbeveloper 		*out_error = B_OK;
20809def3bf7SStephan Aßmus 	if (sDefaultInstance == NULL) {
20818496c38aSbeveloper 		status_t err;
20829def3bf7SStephan Aßmus 		sDefaultInstance = new (std::nothrow) BMediaRosterEx(&err);
20839def3bf7SStephan Aßmus 		if (sDefaultInstance == NULL)
2084a715f908SStephan Aßmus 			err = B_NO_MEMORY;
2085a715f908SStephan Aßmus 		else if (err != B_OK) {
20869def3bf7SStephan Aßmus 			if (sDefaultInstance) {
20879def3bf7SStephan Aßmus 				sDefaultInstance->Lock();
20889def3bf7SStephan Aßmus 				sDefaultInstance->Quit();
20899def3bf7SStephan Aßmus 				sDefaultInstance = NULL;
2090dcfb6bfcSJérôme Duval 			}
20918496c38aSbeveloper 			if (out_error)
20928496c38aSbeveloper 				*out_error = err;
20938496c38aSbeveloper 		}
209452a38012Sejakowatz 	}
209552a38012Sejakowatz 	locker.Unlock();
20969def3bf7SStephan Aßmus 	return sDefaultInstance;
209752a38012Sejakowatz }
209852a38012Sejakowatz 
209952a38012Sejakowatz 
210052a38012Sejakowatz /*static*/ BMediaRoster*
210152a38012Sejakowatz BMediaRoster::CurrentRoster()
210252a38012Sejakowatz {
21039def3bf7SStephan Aßmus 	return sDefaultInstance;
210452a38012Sejakowatz }
210552a38012Sejakowatz 
210652a38012Sejakowatz 
210752a38012Sejakowatz status_t
2108*34c72144SAxel Dörfler BMediaRoster::SetTimeSourceFor(media_node_id node, media_node_id time_source)
210952a38012Sejakowatz {
2110aac800c2Sbeveloper 	CALLED();
211140f36b03Sbeveloper 	if (IS_INVALID_NODEID(node) || IS_INVALID_NODEID(time_source))
2112aac800c2Sbeveloper 		return B_BAD_VALUE;
2113aac800c2Sbeveloper 
2114aac800c2Sbeveloper 	media_node clone;
2115aac800c2Sbeveloper 	status_t rv, result;
2116aac800c2Sbeveloper 
2117*34c72144SAxel Dörfler 	TRACE("BMediaRoster::SetTimeSourceFor: node %ld will be assigned time "
2118*34c72144SAxel Dörfler 		"source %ld\n", node, time_source);
2119*34c72144SAxel Dörfler 	TRACE("BMediaRoster::SetTimeSourceFor: node %ld time source %ld enter\n",
2120*34c72144SAxel Dörfler 		node, time_source);
21215917dd5bSbeveloper 
212286bce45bSbeveloper 	// we need to get a clone of the node to have a port id
2123aac800c2Sbeveloper 	rv = GetNodeFor(node, &clone);
2124aac800c2Sbeveloper 	if (rv != B_OK) {
2125*34c72144SAxel Dörfler 		ERROR("BMediaRoster::SetTimeSourceFor, GetNodeFor failed, node id "
2126*34c72144SAxel Dörfler 			"%ld\n", node);
212752a38012Sejakowatz 		return B_ERROR;
212852a38012Sejakowatz 	}
212952a38012Sejakowatz 
213086bce45bSbeveloper 	// we just send the request to set time_source-id as timesource to the node,
213186bce45bSbeveloper 	// the NODE_SET_TIMESOURCE handler code will do the real assignment
2132aac800c2Sbeveloper 	result = B_OK;
2133aac800c2Sbeveloper 	node_set_timesource_command cmd;
2134aac800c2Sbeveloper 	cmd.timesource_id = time_source;
2135aac800c2Sbeveloper 	rv = SendToPort(clone.port, NODE_SET_TIMESOURCE, &cmd, sizeof(cmd));
2136aac800c2Sbeveloper 	if (rv != B_OK) {
2137*34c72144SAxel Dörfler 		ERROR("BMediaRoster::SetTimeSourceFor, sending NODE_SET_TIMESOURCE "
2138*34c72144SAxel Dörfler 			"failed, node id %ld\n", node);
2139aac800c2Sbeveloper 		result = B_ERROR;
2140aac800c2Sbeveloper 	}
2141aac800c2Sbeveloper 
214260f15390Sbeveloper 	// we release the clone
2143aac800c2Sbeveloper 	rv = ReleaseNode(clone);
2144aac800c2Sbeveloper 	if (rv != B_OK) {
2145*34c72144SAxel Dörfler 		ERROR("BMediaRoster::SetTimeSourceFor, ReleaseNode failed, node id "
2146*34c72144SAxel Dörfler 			"%ld\n", node);
2147aac800c2Sbeveloper 		result = B_ERROR;
2148aac800c2Sbeveloper 	}
2149aac800c2Sbeveloper 
2150*34c72144SAxel Dörfler 	TRACE("BMediaRoster::SetTimeSourceFor: node %ld time source %ld leave\n",
2151*34c72144SAxel Dörfler 		node, time_source);
21525917dd5bSbeveloper 
2153aac800c2Sbeveloper 	return result;
2154aac800c2Sbeveloper }
2155aac800c2Sbeveloper 
215652a38012Sejakowatz 
215752a38012Sejakowatz status_t
2158*34c72144SAxel Dörfler BMediaRoster::GetParameterWebFor(const media_node& node, BParameterWeb** _web)
215952a38012Sejakowatz {
216028ad138aSbeveloper 	CALLED();
2161*34c72144SAxel Dörfler 	if (_web == NULL)
216228ad138aSbeveloper 		return B_BAD_VALUE;
216328ad138aSbeveloper 	if (IS_INVALID_NODE(node))
216428ad138aSbeveloper 		return B_MEDIA_BAD_NODE;
216528ad138aSbeveloper 	if ((node.kind & B_CONTROLLABLE) == 0)
216628ad138aSbeveloper 		return B_MEDIA_BAD_NODE;
216728ad138aSbeveloper 
216828ad138aSbeveloper 	controllable_get_parameter_web_request request;
216928ad138aSbeveloper 	controllable_get_parameter_web_reply reply;
2170*34c72144SAxel Dörfler 	int32 requestsize[] = {B_PAGE_SIZE, 4 * B_PAGE_SIZE, 16 * B_PAGE_SIZE,
2171*34c72144SAxel Dörfler 		64 * B_PAGE_SIZE, 128 * B_PAGE_SIZE, 256 * B_PAGE_SIZE, 0};
217228ad138aSbeveloper 	int32 size;
217328ad138aSbeveloper 
2174*34c72144SAxel Dörfler 	// TODO: it might be better to query the node for the (current) parameter
2175*34c72144SAxel Dörfler 	// size first
217628ad138aSbeveloper 	for (int i = 0; (size = requestsize[i]) != 0; i++) {
217728ad138aSbeveloper 		status_t rv;
217828ad138aSbeveloper 		area_id area;
217928ad138aSbeveloper 		void *data;
2180*34c72144SAxel Dörfler 		area = create_area("parameter web data", &data, B_ANY_ADDRESS, size,
2181*34c72144SAxel Dörfler 			B_NO_LOCK, B_READ_AREA | B_WRITE_AREA);
218228ad138aSbeveloper 		if (area < B_OK) {
2183*34c72144SAxel Dörfler 			ERROR("BMediaRoster::GetParameterWebFor couldn't create area of "
2184*34c72144SAxel Dörfler 				"size %ld\n", size);
218528ad138aSbeveloper 			return B_ERROR;
218628ad138aSbeveloper 		}
2187*34c72144SAxel Dörfler 		request.max_size = size;
218828ad138aSbeveloper 		request.area = area;
2189*34c72144SAxel Dörfler 		rv = QueryPort(node.port, CONTROLLABLE_GET_PARAMETER_WEB, &request,
2190*34c72144SAxel Dörfler 			sizeof(request), &reply, sizeof(reply));
219128ad138aSbeveloper 		if (rv != B_OK) {
2192*34c72144SAxel Dörfler 			ERROR("BMediaRoster::GetParameterWebFor "
2193*34c72144SAxel Dörfler 				"CONTROLLABLE_GET_PARAMETER_WEB failed\n");
219428ad138aSbeveloper 			delete_area(area);
219528ad138aSbeveloper 			return B_ERROR;
219628ad138aSbeveloper 		}
219728ad138aSbeveloper 		if (reply.size == 0) {
219828ad138aSbeveloper 			// no parameter web available
2199*34c72144SAxel Dörfler 			// TODO: should we return an error?
2200*34c72144SAxel Dörfler 			ERROR("BMediaRoster::GetParameterWebFor node %ld has no parameter "
2201*34c72144SAxel Dörfler 				"web\n", node.node);
2202*34c72144SAxel Dörfler 			*_web = new (std::nothrow) BParameterWeb();
220328ad138aSbeveloper 			delete_area(area);
2204*34c72144SAxel Dörfler 			return *_web != NULL ? B_OK : B_NO_MEMORY;
220552a38012Sejakowatz 		}
220628ad138aSbeveloper 		if (reply.size > 0) {
220728ad138aSbeveloper 			// we got a flattened parameter web!
2208*34c72144SAxel Dörfler 			*_web = new (std::nothrow) BParameterWeb();
2209*34c72144SAxel Dörfler 			if (*_web == NULL)
2210a715f908SStephan Aßmus 				rv = B_NO_MEMORY;
2211a715f908SStephan Aßmus 			else {
2212*34c72144SAxel Dörfler 				printf("BMediaRoster::GetParameterWebFor Unflattening %ld "
2213*34c72144SAxel Dörfler 					"bytes, 0x%08lx, 0x%08lx, 0x%08lx, 0x%08lx\n",
2214*34c72144SAxel Dörfler 					reply.size, ((uint32*)data)[0], ((uint32*)data)[1],
2215*34c72144SAxel Dörfler 					((uint32*)data)[2], ((uint32*)data)[3]);
221628ad138aSbeveloper 
2217*34c72144SAxel Dörfler 				rv = (*_web)->Unflatten(reply.code, data, reply.size);
2218a715f908SStephan Aßmus 			}
221928ad138aSbeveloper 			if (rv != B_OK) {
2220*34c72144SAxel Dörfler 				ERROR("BMediaRoster::GetParameterWebFor Unflatten failed, "
2221*34c72144SAxel Dörfler 					"%s\n", strerror(rv));
2222*34c72144SAxel Dörfler 				delete *_web;
222328ad138aSbeveloper 			}
222428ad138aSbeveloper 			delete_area(area);
2225a715f908SStephan Aßmus 			return rv;
222628ad138aSbeveloper 		}
222728ad138aSbeveloper 		delete_area(area);
222828ad138aSbeveloper 		ASSERT(reply.size == -1);
222928ad138aSbeveloper 		// parameter web data was too large
223028ad138aSbeveloper 		// loop and try a larger size
223128ad138aSbeveloper 	}
2232*34c72144SAxel Dörfler 	ERROR("BMediaRoster::GetParameterWebFor node %ld has no parameter web "
2233*34c72144SAxel Dörfler 		"larger than %ld\n", node.node, size);
223428ad138aSbeveloper 	return B_ERROR;
223528ad138aSbeveloper }
223652a38012Sejakowatz 
223752a38012Sejakowatz 
223852a38012Sejakowatz status_t
2239*34c72144SAxel Dörfler BMediaRoster::StartControlPanel(const media_node& node, BMessenger* _messenger)
224052a38012Sejakowatz {
2241999cd0acSMaurice Kalinowski 	CALLED();
2242999cd0acSMaurice Kalinowski 
2243999cd0acSMaurice Kalinowski 	controllable_start_control_panel_request request;
2244999cd0acSMaurice Kalinowski 	controllable_start_control_panel_reply reply;
2245999cd0acSMaurice Kalinowski 
2246999cd0acSMaurice Kalinowski 	request.node = node;
2247999cd0acSMaurice Kalinowski 
2248999cd0acSMaurice Kalinowski 	status_t rv;
2249*34c72144SAxel Dörfler 	rv = QueryPort(node.port, CONTROLLABLE_START_CONTROL_PANEL, &request,
2250*34c72144SAxel Dörfler 		sizeof(request), &reply, sizeof(reply));
2251999cd0acSMaurice Kalinowski 	if (rv != B_OK)
2252999cd0acSMaurice Kalinowski 		return rv;
2253999cd0acSMaurice Kalinowski 
2254*34c72144SAxel Dörfler 	if (reply.team != -1 && _messenger != NULL)
2255*34c72144SAxel Dörfler 		*_messenger = BMessenger(NULL, reply.team);
2256999cd0acSMaurice Kalinowski 
2257999cd0acSMaurice Kalinowski 	return B_OK;
225852a38012Sejakowatz }
225952a38012Sejakowatz 
226052a38012Sejakowatz 
226152a38012Sejakowatz status_t
2262*34c72144SAxel Dörfler BMediaRoster::GetDormantNodes(dormant_node_info* _info, int32* _count,
2263*34c72144SAxel Dörfler 	const media_format* hasInput, const media_format* hasOutput,
2264*34c72144SAxel Dörfler 	const char* name, uint64 requireKinds, uint64 denyKinds)
226552a38012Sejakowatz {
226652a38012Sejakowatz 	CALLED();
2267*34c72144SAxel Dörfler 	if (_info == NULL || _count == NULL || *_count <= 0)
226852a38012Sejakowatz 		return B_BAD_VALUE;
226952a38012Sejakowatz 
227052a38012Sejakowatz 	xfer_server_get_dormant_nodes msg;
227152a38012Sejakowatz 	port_id port;
227252a38012Sejakowatz 	status_t rv;
227352a38012Sejakowatz 
22744295907bSbeveloper 	port = find_port(MEDIA_SERVER_PORT_NAME);
227552a38012Sejakowatz 	if (port <= B_OK)
227652a38012Sejakowatz 		return B_ERROR;
227752a38012Sejakowatz 
2278*34c72144SAxel Dörfler 	msg.maxcount = *_count;
2279*34c72144SAxel Dörfler 	msg.has_input = hasInput != NULL;
2280*34c72144SAxel Dörfler 	if (hasInput != NULL) {
2281*34c72144SAxel Dörfler 		// TODO: we should not make a flat copy of media_format
2282*34c72144SAxel Dörfler 		msg.inputformat = *hasInput;
2283*34c72144SAxel Dörfler 	}
2284*34c72144SAxel Dörfler 	msg.has_output = hasOutput != NULL;
2285*34c72144SAxel Dörfler 	if (hasOutput != NULL) {
2286*34c72144SAxel Dörfler 		// TODO: we should not make a flat copy of media_format
2287*34c72144SAxel Dörfler 		msg.outputformat = *hasOutput;
2288*34c72144SAxel Dörfler 	}
2289*34c72144SAxel Dörfler 
2290*34c72144SAxel Dörfler 	msg.has_name = name != NULL;
2291*34c72144SAxel Dörfler 	if (name != NULL) {
22929e9417d2Sbeveloper 		int len = strlen(name);
22939e9417d2Sbeveloper 		len = min_c(len, (int)sizeof(msg.name) - 1);
229452a38012Sejakowatz 		memcpy(msg.name, name, len);
229552a38012Sejakowatz 		msg.name[len] = 0;
229652a38012Sejakowatz 	}
2297*34c72144SAxel Dörfler 	msg.require_kinds = requireKinds;
2298*34c72144SAxel Dörfler 	msg.deny_kinds = denyKinds;
229952a38012Sejakowatz 	msg.reply_port = _PortPool->GetPort();
230052a38012Sejakowatz 
230152a38012Sejakowatz 	rv = write_port(port, SERVER_GET_DORMANT_NODES, &msg, sizeof(msg));
230252a38012Sejakowatz 	if (rv != B_OK) {
230352a38012Sejakowatz 		_PortPool->PutPort(msg.reply_port);
230452a38012Sejakowatz 		return rv;
230552a38012Sejakowatz 	}
230652a38012Sejakowatz 
230752a38012Sejakowatz 	xfer_server_get_dormant_nodes_reply reply;
230852a38012Sejakowatz 	int32 code;
230952a38012Sejakowatz 
231052a38012Sejakowatz 	rv = read_port(msg.reply_port, &code, &reply, sizeof(reply));
231152a38012Sejakowatz 	if (rv < B_OK) {
231252a38012Sejakowatz 		_PortPool->PutPort(msg.reply_port);
231352a38012Sejakowatz 		return rv;
231452a38012Sejakowatz 	}
231552a38012Sejakowatz 
2316*34c72144SAxel Dörfler 	*_count = reply.count;
231752a38012Sejakowatz 
2318*34c72144SAxel Dörfler 	if (*_count > 0) {
2319*34c72144SAxel Dörfler 		rv = read_port(msg.reply_port, &code, _info,
2320*34c72144SAxel Dörfler 			*_count * sizeof(dormant_node_info));
232152a38012Sejakowatz 		if (rv < B_OK)
232252a38012Sejakowatz 			reply.result = rv;
232352a38012Sejakowatz 	}
232452a38012Sejakowatz 	_PortPool->PutPort(msg.reply_port);
232552a38012Sejakowatz 
232652a38012Sejakowatz 	return reply.result;
232752a38012Sejakowatz }
232852a38012Sejakowatz 
2329*34c72144SAxel Dörfler /*!	This function is used to do the real work of instantiating a dormant node.
2330*34c72144SAxel Dörfler 	It is either called by the media_addon_server to instantiate a global node,
2331*34c72144SAxel Dörfler 	or it gets called from BMediaRoster::InstantiateDormantNode() to create a
2332*34c72144SAxel Dörfler 	local one.
2333*34c72144SAxel Dörfler 
2334*34c72144SAxel Dörfler 	Checks concerning global/local are not done here.
23358b04ffc1Sbeveloper */
233652a38012Sejakowatz status_t
2337*34c72144SAxel Dörfler BMediaRosterEx::InstantiateDormantNode(media_addon_id addonID, int32 flavorID,
2338*34c72144SAxel Dörfler 	team_id creator, media_node *_node)
233952a38012Sejakowatz {
234054187cc6Sbeveloper 	// This function is always called from the correct context, if the node
234154187cc6Sbeveloper 	// is supposed to be global, it is called from the media_addon_server.
234254187cc6Sbeveloper 
234352a38012Sejakowatz 	// if B_FLAVOR_IS_GLOBAL, we need to use the BMediaAddOn object that
234452a38012Sejakowatz 	// resides in the media_addon_server
234552a38012Sejakowatz 
23468b04ffc1Sbeveloper 	// RegisterNode() must be called for nodes instantiated from add-ons,
23478b04ffc1Sbeveloper 	// since the media kit warrants that it's done automatically.
234852a38012Sejakowatz 
2349*34c72144SAxel Dörfler 	// addonID		Indicates the ID number of the media add-on in which the
2350*34c72144SAxel Dörfler 	//				node resides.
2351*34c72144SAxel Dörfler 	// flavorID		Indicates the internal ID number that the add-on uses to
2352*34c72144SAxel Dörfler 	//				identify the flavor, this is the number that was published
2353*34c72144SAxel Dörfler 	//				by BMediaAddOn::GetFlavorAt() in the
23548b04ffc1Sbeveloper 	//				flavor_info::internal_id field.
2355*34c72144SAxel Dörfler 	// creator		The creator team is -1 if nodes are created locally. If
2356*34c72144SAxel Dörfler 	//				created globally, it will contain (while called in
2357*34c72144SAxel Dörfler 	//				media_addon_server context) the team-id of the team that
2358*34c72144SAxel Dörfler 	//				requested the instantiation.
23598b04ffc1Sbeveloper 
2360*34c72144SAxel Dörfler 	TRACE("BMediaRosterEx::InstantiateDormantNode: addonID %ld, flavorID "
2361*34c72144SAxel Dörfler 		"%ld\n", addonID, flavorID);
23628b04ffc1Sbeveloper 
23638b04ffc1Sbeveloper 	// Get flavor_info from the server
2364*34c72144SAxel Dörfler 	dormant_flavor_info info;
23658c6a6096Sbeveloper 	status_t rv;
2366*34c72144SAxel Dörfler 	rv = GetDormantFlavorInfo(addonID, flavorID, &info);
23678b04ffc1Sbeveloper 	if (rv != B_OK) {
2368*34c72144SAxel Dörfler 		ERROR("BMediaRosterEx::InstantiateDormantNode error: failed to get "
2369*34c72144SAxel Dörfler 			"dormant_flavor_info for addon-id %ld, flavor-id %ld\n", addonID,
2370*34c72144SAxel Dörfler 			flavorID);
237152a38012Sejakowatz 		return B_ERROR;
237252a38012Sejakowatz 	}
23738b04ffc1Sbeveloper 
2374*34c72144SAxel Dörfler 	ASSERT(node_info.internal_id == flavorID);
23758b04ffc1Sbeveloper 
23768b04ffc1Sbeveloper 	// load the BMediaAddOn object
23778b04ffc1Sbeveloper 	BMediaAddOn* addon;
2378*34c72144SAxel Dörfler 	addon = _DormantNodeManager->GetAddon(addonID);
2379*34c72144SAxel Dörfler 	if (addon == NULL) {
23805ac4fbd7Sbeveloper 		ERROR("BMediaRosterEx::InstantiateDormantNode: GetAddon failed\n");
23818b04ffc1Sbeveloper 		return B_ERROR;
23828b04ffc1Sbeveloper 	}
23838b04ffc1Sbeveloper 
238454187cc6Sbeveloper 	// Now we need to try to increment the use count of this addon flavor
238554187cc6Sbeveloper 	// in the server. This can fail if the total number instances of this
238654187cc6Sbeveloper 	// flavor is limited.
2387*34c72144SAxel Dörfler 	rv = IncrementAddonFlavorInstancesCount(addonID, flavorID);
238854187cc6Sbeveloper 	if (rv != B_OK) {
2389*34c72144SAxel Dörfler 		ERROR("BMediaRosterEx::InstantiateDormantNode error: can't create "
2390*34c72144SAxel Dörfler 			"more nodes for addon-id %ld, flavor-id %ld\n", addonID, flavorID);
239154187cc6Sbeveloper 		// Put the addon back into the pool
2392*34c72144SAxel Dörfler 		_DormantNodeManager->PutAddon(addonID);
239354187cc6Sbeveloper 		return B_ERROR;
239454187cc6Sbeveloper 	}
239554187cc6Sbeveloper 
23968b04ffc1Sbeveloper 	BMessage config;
2397*34c72144SAxel Dörfler 	rv = LoadNodeConfiguration(addonID, flavorID, &config);
239854187cc6Sbeveloper 	if (rv != B_OK) {
2399*34c72144SAxel Dörfler 		ERROR("BMediaRosterEx::InstantiateDormantNode: couldn't load "
2400*34c72144SAxel Dörfler 			"configuration for addon-id %ld, flavor-id %ld\n", addonID,
2401*34c72144SAxel Dörfler 			flavorID);
240254187cc6Sbeveloper 		// do not return, this is a minor problem, not a reason to fail
240354187cc6Sbeveloper 	}
24048b04ffc1Sbeveloper 
2405*34c72144SAxel Dörfler 	status_t status = B_OK;
2406*34c72144SAxel Dörfler 	BMediaNode* node = addon->InstantiateNodeFor(&info, &config, &status);
2407*34c72144SAxel Dörfler 	if (node == NULL) {
2408*34c72144SAxel Dörfler 		ERROR("BMediaRosterEx::InstantiateDormantNode: InstantiateNodeFor "
2409*34c72144SAxel Dörfler 			"failed\n");
24108b04ffc1Sbeveloper 
241154187cc6Sbeveloper 		// Put the addon back into the pool
2412*34c72144SAxel Dörfler 		_DormantNodeManager->PutAddon(addonID);
2413*34c72144SAxel Dörfler 
241454187cc6Sbeveloper 		// We must decrement the use count of this addon flavor in the
241554187cc6Sbeveloper 		// server to compensate the increment done in the beginning.
2416*34c72144SAxel Dörfler 		rv = DecrementAddonFlavorInstancesCount(addonID, flavorID);
241754187cc6Sbeveloper 		if (rv != B_OK) {
2418*34c72144SAxel Dörfler 			ERROR("BMediaRosterEx::InstantiateDormantNode: DecrementAddon"
2419*34c72144SAxel Dörfler 				"FlavorInstancesCount failed\n");
242016b7eea4Sbeveloper 		}
2421*34c72144SAxel Dörfler 		return status != B_OK ? status : B_ERROR;
242254187cc6Sbeveloper 	}
242354187cc6Sbeveloper 
2424*34c72144SAxel Dörfler 	rv = RegisterNode(node, addonID, flavorID);
24258c6a6096Sbeveloper 	if (rv != B_OK) {
24265ac4fbd7Sbeveloper 		ERROR("BMediaRosterEx::InstantiateDormantNode: RegisterNode failed\n");
24278c6a6096Sbeveloper 		delete node;
242854187cc6Sbeveloper 		// Put the addon back into the pool
2429*34c72144SAxel Dörfler 		_DormantNodeManager->PutAddon(addonID);
243054187cc6Sbeveloper 		// We must decrement the use count of this addon flavor in the
243154187cc6Sbeveloper 		// server to compensate the increment done in the beginning.
2432*34c72144SAxel Dörfler 		rv = DecrementAddonFlavorInstancesCount(addonID, flavorID);
243354187cc6Sbeveloper 		if (rv != B_OK) {
2434*34c72144SAxel Dörfler 			ERROR("BMediaRosterEx::InstantiateDormantNode: DecrementAddon"
2435*34c72144SAxel Dörfler 				"FlavorInstancesCount failed\n");
243654187cc6Sbeveloper 		}
24378c6a6096Sbeveloper 		return B_ERROR;
24388c6a6096Sbeveloper 	}
24398c6a6096Sbeveloper 
244054187cc6Sbeveloper 	if (creator != -1) {
2441*34c72144SAxel Dörfler 		// send a message to the server to assign team "creator" as creator
2442*34c72144SAxel Dörfler 		// of node "node->ID()"
2443*34c72144SAxel Dörfler 		printf("!!! BMediaRosterEx::InstantiateDormantNode assigning team "
2444*34c72144SAxel Dörfler 			"%ld as creator of node %ld\n", creator, node->ID());
2445*34c72144SAxel Dörfler 
244654187cc6Sbeveloper 		rv = MediaRosterEx(this)->SetNodeCreator(node->ID(), creator);
244754187cc6Sbeveloper 		if (rv != B_OK) {
2448*34c72144SAxel Dörfler 			ERROR("BMediaRosterEx::InstantiateDormantNode failed to assign "
2449*34c72144SAxel Dörfler 				"team %ld as creator of node %ld\n", creator, node->ID());
245054187cc6Sbeveloper 			// do not return, this is a minor problem, not a reason to fail
245154187cc6Sbeveloper 		}
245254187cc6Sbeveloper 	}
245354187cc6Sbeveloper 
245454187cc6Sbeveloper 	// RegisterNode() does remember the add-on id in the server
245554187cc6Sbeveloper 	// and UnregisterNode() will call DormantNodeManager::PutAddon()
245654187cc6Sbeveloper 	// when the node is unregistered.
24578c6a6096Sbeveloper 
2458*34c72144SAxel Dörfler 	*_node = node->Node();
2459cf4e2277Sbeveloper 
2460*34c72144SAxel Dörfler 	TRACE("BMediaRosterEx::InstantiateDormantNode: addon-id %ld, flavor_id "
2461*34c72144SAxel Dörfler 		"%ld instanciated as node %ld, port %ld in team %ld\n", addonID,
2462*34c72144SAxel Dörfler 		flavorID, _node->node, _node->port, team);
2463cf4e2277Sbeveloper 
246416b7eea4Sbeveloper 	return B_OK;
246516b7eea4Sbeveloper }
246652a38012Sejakowatz 
246752a38012Sejakowatz 
246852a38012Sejakowatz status_t
2469*34c72144SAxel Dörfler BMediaRoster::InstantiateDormantNode(const dormant_node_info& info,
2470*34c72144SAxel Dörfler 	media_node* _node, uint32 flags)
24718b04ffc1Sbeveloper {
24728b04ffc1Sbeveloper 	CALLED();
2473*34c72144SAxel Dörfler 	if (_node == NULL)
24748b04ffc1Sbeveloper 		return B_BAD_VALUE;
2475*34c72144SAxel Dörfler 	if (info.addon <= B_OK) {
2476*34c72144SAxel Dörfler 		ERROR("BMediaRoster::InstantiateDormantNode error: addon-id %ld "
2477*34c72144SAxel Dörfler 			"invalid.\n", info.addon);
24788b04ffc1Sbeveloper 		return B_BAD_VALUE;
24798b04ffc1Sbeveloper 	}
24808b04ffc1Sbeveloper 
2481*34c72144SAxel Dörfler 	printf("BMediaRoster::InstantiateDormantNode: addon-id %ld, flavor_id "
2482*34c72144SAxel Dörfler 		"%ld, flags 0x%lX\n", info.addon, info.flavor_id, flags);
24838b04ffc1Sbeveloper 
24848b04ffc1Sbeveloper 	// Get flavor_info from the server
2485*34c72144SAxel Dörfler 	// TODO: this is a little overhead, as we get the full blown
2486*34c72144SAxel Dörfler 	// dormant_flavor_info,
2487*34c72144SAxel Dörfler 	// TODO: but only need the flags.
2488*34c72144SAxel Dörfler 	dormant_flavor_info flavorInfo;
24898b04ffc1Sbeveloper 	status_t rv;
2490*34c72144SAxel Dörfler 	rv = MediaRosterEx(this)->GetDormantFlavorInfo(info.addon, info.flavor_id,
2491*34c72144SAxel Dörfler 		&flavorInfo);
24928b04ffc1Sbeveloper 	if (rv != B_OK) {
2493*34c72144SAxel Dörfler 		ERROR("BMediaRoster::InstantiateDormantNode: failed to get "
2494*34c72144SAxel Dörfler 			"dormant_flavor_info for addon-id %ld, flavor-id %ld\n",
2495*34c72144SAxel Dörfler 			info.addon, info.flavor_id);
2496626824eaSbeveloper 		return B_NAME_NOT_FOUND;
24978b04ffc1Sbeveloper 	}
24988b04ffc1Sbeveloper 
2499*34c72144SAxel Dörfler 	ASSERT(flavorInfo.internal_id == info.flavor_id);
25008b04ffc1Sbeveloper 
25018b04ffc1Sbeveloper #if DEBUG
2502*34c72144SAxel Dörfler 	printf("BMediaRoster::InstantiateDormantNode: name \"%s\", info \"%s\", "
2503*34c72144SAxel Dörfler 		"flavor_flags 0x%lX, internal_id %ld, possible_count %ld\n",
2504*34c72144SAxel Dörfler 		flavorInfo.name, flavorInfo.info, flavorInfo.flavor_flags,
2505*34c72144SAxel Dörfler 		flavorInfo.internal_id, flavorInfo.possible_count);
2506*34c72144SAxel Dörfler 
2507*34c72144SAxel Dörfler 	if ((flags & B_FLAVOR_IS_LOCAL) != 0) {
2508*34c72144SAxel Dörfler 		printf("BMediaRoster::InstantiateDormantNode: caller requested "
2509*34c72144SAxel Dörfler 			"B_FLAVOR_IS_LOCAL\n");
2510*34c72144SAxel Dörfler 	}
2511*34c72144SAxel Dörfler 	if ((flags & B_FLAVOR_IS_GLOBAL) != 0) {
2512*34c72144SAxel Dörfler 		printf("BMediaRoster::InstantiateDormantNode: caller requested "
2513*34c72144SAxel Dörfler 			"B_FLAVOR_IS_GLOBAL\n");
2514*34c72144SAxel Dörfler 	}
2515*34c72144SAxel Dörfler 	if ((flavorInfo.flavor_flags & B_FLAVOR_IS_LOCAL) != 0) {
2516*34c72144SAxel Dörfler 		printf("BMediaRoster::InstantiateDormantNode: node requires "
2517*34c72144SAxel Dörfler 			"B_FLAVOR_IS_LOCAL\n");
2518*34c72144SAxel Dörfler 	}
2519*34c72144SAxel Dörfler 	if ((flavorInfo.flavor_flags & B_FLAVOR_IS_GLOBAL) != 0) {
2520*34c72144SAxel Dörfler 		printf("BMediaRoster::InstantiateDormantNode: node requires "
2521*34c72144SAxel Dörfler 			"B_FLAVOR_IS_GLOBAL\n");
2522*34c72144SAxel Dörfler 	}
25238b04ffc1Sbeveloper #endif
25248b04ffc1Sbeveloper 
25258b04ffc1Sbeveloper 	// Make sure that flags demanded by the dormant node and those requested
25268b04ffc1Sbeveloper 	// by the caller are not incompatible.
2527*34c72144SAxel Dörfler 	if ((flavorInfo.flavor_flags & B_FLAVOR_IS_GLOBAL) != 0
2528*34c72144SAxel Dörfler 		&& (flags & B_FLAVOR_IS_LOCAL) != 0) {
2529*34c72144SAxel Dörfler 		ERROR("BMediaRoster::InstantiateDormantNode: requested "
2530*34c72144SAxel Dörfler 			"B_FLAVOR_IS_LOCAL, but dormant node has B_FLAVOR_IS_GLOBAL\n");
2531626824eaSbeveloper 		return B_NAME_NOT_FOUND;
25328b04ffc1Sbeveloper 	}
2533*34c72144SAxel Dörfler 	if ((flavorInfo.flavor_flags & B_FLAVOR_IS_LOCAL) != 0
2534*34c72144SAxel Dörfler 		&& (flags & B_FLAVOR_IS_GLOBAL) != 0) {
2535*34c72144SAxel Dörfler 		ERROR("BMediaRoster::InstantiateDormantNode: requested "
2536*34c72144SAxel Dörfler 			"B_FLAVOR_IS_GLOBAL, but dormant node has B_FLAVOR_IS_LOCAL\n");
2537626824eaSbeveloper 		return B_NAME_NOT_FOUND;
25388b04ffc1Sbeveloper 	}
253954187cc6Sbeveloper 
25408b04ffc1Sbeveloper 	// If either the node, or the caller requested to make the instance global
2541*34c72144SAxel Dörfler 	// we will do it by forwarding this request into the media_addon_server,
2542*34c72144SAxel Dörfler 	// which in turn will call BMediaRosterEx::InstantiateDormantNode to create
2543*34c72144SAxel Dörfler 	// the node there and make it globally available.
2544*34c72144SAxel Dörfler 	if ((flavorInfo.flavor_flags & B_FLAVOR_IS_GLOBAL) != 0
2545*34c72144SAxel Dörfler 		|| (flags & B_FLAVOR_IS_GLOBAL) != 0) {
2546*34c72144SAxel Dörfler 		TRACE("BMediaRoster::InstantiateDormantNode: creating global object "
2547*34c72144SAxel Dörfler 			"in media_addon_server\n");
2548cf4e2277Sbeveloper 
25498b04ffc1Sbeveloper 		addonserver_instantiate_dormant_node_request request;
25508b04ffc1Sbeveloper 		addonserver_instantiate_dormant_node_reply reply;
2551*34c72144SAxel Dörfler 		request.addonid = info.addon;
2552*34c72144SAxel Dörfler 		request.flavorid = info.flavor_id;
2553*34c72144SAxel Dörfler 		request.creator_team = team;
2554*34c72144SAxel Dörfler 			// creator team is allowed to also release global nodes
2555*34c72144SAxel Dörfler 		rv = QueryAddonServer(ADDONSERVER_INSTANTIATE_DORMANT_NODE, &request,
2556*34c72144SAxel Dörfler 			sizeof(request), &reply, sizeof(reply));
2557*34c72144SAxel Dörfler 		if (rv == B_OK)
2558*34c72144SAxel Dörfler 			*_node = reply.node;
25598b04ffc1Sbeveloper 	} else {
256054187cc6Sbeveloper 		// creator team = -1, as this is a local node
2561*34c72144SAxel Dörfler 		rv = MediaRosterEx(this)->InstantiateDormantNode(info.addon,
2562*34c72144SAxel Dörfler 			info.flavor_id, -1, _node);
25638b04ffc1Sbeveloper 	}
2564626824eaSbeveloper 	if (rv != B_OK) {
2565*34c72144SAxel Dörfler 		*_node = media_node::null;
2566626824eaSbeveloper 		return B_NAME_NOT_FOUND;
2567626824eaSbeveloper 	}
2568626824eaSbeveloper 	return B_OK;
25698b04ffc1Sbeveloper }
25708b04ffc1Sbeveloper 
25718b04ffc1Sbeveloper 
25728b04ffc1Sbeveloper status_t
2573*34c72144SAxel Dörfler BMediaRoster::InstantiateDormantNode(const dormant_node_info& info,
2574*34c72144SAxel Dörfler 	media_node* _node)
25758b04ffc1Sbeveloper {
2576*34c72144SAxel Dörfler 	return InstantiateDormantNode(info, _node, 0);
25778b04ffc1Sbeveloper }
25788b04ffc1Sbeveloper 
25798b04ffc1Sbeveloper 
25808b04ffc1Sbeveloper status_t
258152a38012Sejakowatz BMediaRoster::GetDormantNodeFor(const media_node& node,
2582*34c72144SAxel Dörfler 	dormant_node_info* _info)
258352a38012Sejakowatz {
258485dfab2bSbeveloper 	CALLED();
2585*34c72144SAxel Dörfler 	if (_info == NULL)
258685dfab2bSbeveloper 		return B_BAD_VALUE;
258740f36b03Sbeveloper 	if (IS_INVALID_NODE(node))
258885dfab2bSbeveloper 		return B_MEDIA_BAD_NODE;
258952a38012Sejakowatz 
259085dfab2bSbeveloper 	server_get_dormant_node_for_request request;
259185dfab2bSbeveloper 	server_get_dormant_node_for_reply reply;
259285dfab2bSbeveloper 	status_t rv;
259385dfab2bSbeveloper 
259485dfab2bSbeveloper 	request.node = node;
259585dfab2bSbeveloper 
2596*34c72144SAxel Dörfler 	rv = QueryServer(SERVER_GET_DORMANT_NODE_FOR, &request, sizeof(request),
2597*34c72144SAxel Dörfler 		&reply, sizeof(reply));
259885dfab2bSbeveloper 	if (rv != B_OK)
259985dfab2bSbeveloper 		return rv;
260085dfab2bSbeveloper 
2601*34c72144SAxel Dörfler 	*_info = reply.node_info;
260285dfab2bSbeveloper 	return B_OK;
260352a38012Sejakowatz }
260452a38012Sejakowatz 
2605*34c72144SAxel Dörfler 
260652a38012Sejakowatz status_t
2607*34c72144SAxel Dörfler BMediaRosterEx::GetDormantFlavorInfo(media_addon_id addonID, int32 flavorID,
2608*34c72144SAxel Dörfler 	dormant_flavor_info* _flavor)
260952a38012Sejakowatz {
261052a38012Sejakowatz 	CALLED();
2611*34c72144SAxel Dörfler 	if (_flavor == NULL)
26129bedd42cSbeveloper 		return B_BAD_VALUE;
261352a38012Sejakowatz 
261452a38012Sejakowatz 	xfer_server_get_dormant_flavor_info msg;
261552a38012Sejakowatz 	xfer_server_get_dormant_flavor_info_reply *reply;
261652a38012Sejakowatz 	port_id port;
261752a38012Sejakowatz 	status_t rv;
261852a38012Sejakowatz 	int32 code;
261952a38012Sejakowatz 
26204295907bSbeveloper 	port = find_port(MEDIA_SERVER_PORT_NAME);
2621*34c72144SAxel Dörfler 	if (port < B_OK)
262252a38012Sejakowatz 		return B_ERROR;
262352a38012Sejakowatz 
262452a38012Sejakowatz 	reply = (xfer_server_get_dormant_flavor_info_reply*)malloc(16000);
2625*34c72144SAxel Dörfler 	if (reply == NULL)
2626*34c72144SAxel Dörfler 		return B_NO_MEMORY;
262752a38012Sejakowatz 
2628*34c72144SAxel Dörfler 	msg.addon = addonID;
2629*34c72144SAxel Dörfler 	msg.flavor_id = flavorID;
263052a38012Sejakowatz 	msg.reply_port = _PortPool->GetPort();
263152a38012Sejakowatz 	rv = write_port(port, SERVER_GET_DORMANT_FLAVOR_INFO, &msg, sizeof(msg));
263252a38012Sejakowatz 	if (rv != B_OK) {
263352a38012Sejakowatz 		free(reply);
263452a38012Sejakowatz 		_PortPool->PutPort(msg.reply_port);
263552a38012Sejakowatz 		return rv;
263652a38012Sejakowatz 	}
263752a38012Sejakowatz 	rv = read_port(msg.reply_port, &code, reply, 16000);
263852a38012Sejakowatz 	_PortPool->PutPort(msg.reply_port);
263952a38012Sejakowatz 
264052a38012Sejakowatz 	if (rv < B_OK) {
264152a38012Sejakowatz 		free(reply);
264252a38012Sejakowatz 		return rv;
264352a38012Sejakowatz 	}
264452a38012Sejakowatz 
264552a38012Sejakowatz 	if (reply->result == B_OK)
2646*34c72144SAxel Dörfler 		rv = _flavor->Unflatten(reply->dfi_type, &reply->dfi, reply->dfi_size);
264752a38012Sejakowatz 	else
264852a38012Sejakowatz 		rv = reply->result;
264952a38012Sejakowatz 
265052a38012Sejakowatz 	free(reply);
265152a38012Sejakowatz 	return rv;
265252a38012Sejakowatz }
265352a38012Sejakowatz 
2654*34c72144SAxel Dörfler 
26558b04ffc1Sbeveloper status_t
2656*34c72144SAxel Dörfler BMediaRoster::GetDormantFlavorInfoFor(const dormant_node_info& dormant,
2657*34c72144SAxel Dörfler 	dormant_flavor_info* _flavor)
26588b04ffc1Sbeveloper {
2659*34c72144SAxel Dörfler 	return MediaRosterEx(this)->GetDormantFlavorInfo(dormant.addon,
2660*34c72144SAxel Dörfler 		dormant.flavor_id, _flavor);
26618b04ffc1Sbeveloper }
266252a38012Sejakowatz 
2663*34c72144SAxel Dörfler 
266460f15390Sbeveloper // Reports in outLatency the maximum latency found downstream from
266560f15390Sbeveloper // the specified BBufferProducer, producer, given the current connections.
266652a38012Sejakowatz status_t
2667*34c72144SAxel Dörfler BMediaRoster::GetLatencyFor(const media_node& producer, bigtime_t* _latency)
266852a38012Sejakowatz {
266960f15390Sbeveloper 	CALLED();
2670*34c72144SAxel Dörfler 	if (_latency == NULL)
267160f15390Sbeveloper 		return B_BAD_VALUE;
2672*34c72144SAxel Dörfler 	if (IS_INVALID_NODE(producer)
2673*34c72144SAxel Dörfler 		|| (producer.kind & B_BUFFER_PRODUCER) == 0)
267460f15390Sbeveloper 		return B_MEDIA_BAD_NODE;
267560f15390Sbeveloper 
267660f15390Sbeveloper 	producer_get_latency_request request;
267760f15390Sbeveloper 	producer_get_latency_reply reply;
267860f15390Sbeveloper 	status_t rv;
267960f15390Sbeveloper 
2680*34c72144SAxel Dörfler 	rv = QueryPort(producer.port, PRODUCER_GET_LATENCY, &request,
2681*34c72144SAxel Dörfler 		sizeof(request), &reply, sizeof(reply));
268260f15390Sbeveloper 	if (rv != B_OK)
268360f15390Sbeveloper 		return rv;
268460f15390Sbeveloper 
2685*34c72144SAxel Dörfler 	*_latency = reply.latency;
268660f15390Sbeveloper 
2687ab9afde3SMarcus Overhagen //	printf("BMediaRoster::GetLatencyFor producer %ld has maximum latency %Ld\n", producer.node, *out_latency);
2688aac800c2Sbeveloper 	return B_OK;
268952a38012Sejakowatz }
269052a38012Sejakowatz 
269152a38012Sejakowatz 
269252a38012Sejakowatz status_t
269352a38012Sejakowatz BMediaRoster::GetInitialLatencyFor(const media_node& producer,
2694*34c72144SAxel Dörfler 	bigtime_t* _latency, uint32* _flags)
269552a38012Sejakowatz {
2696b65a0ac5SJérôme Duval 	CALLED();
2697*34c72144SAxel Dörfler 	if (_latency == NULL)
2698b65a0ac5SJérôme Duval 		return B_BAD_VALUE;
2699*34c72144SAxel Dörfler 	if (IS_INVALID_NODE(producer)
2700*34c72144SAxel Dörfler 		|| (producer.kind & B_BUFFER_PRODUCER) == 0)
2701b65a0ac5SJérôme Duval 		return B_MEDIA_BAD_NODE;
2702b65a0ac5SJérôme Duval 
2703b65a0ac5SJérôme Duval 	producer_get_initial_latency_request request;
2704b65a0ac5SJérôme Duval 	producer_get_initial_latency_reply reply;
2705b65a0ac5SJérôme Duval 	status_t rv;
2706b65a0ac5SJérôme Duval 
2707*34c72144SAxel Dörfler 	rv = QueryPort(producer.port, PRODUCER_GET_INITIAL_LATENCY, &request,
2708*34c72144SAxel Dörfler 		sizeof(request), &reply, sizeof(reply));
2709b65a0ac5SJérôme Duval 	if (rv != B_OK)
2710b65a0ac5SJérôme Duval 		return rv;
2711b65a0ac5SJérôme Duval 
2712*34c72144SAxel Dörfler 	*_latency = reply.initial_latency;
2713*34c72144SAxel Dörfler 	if (_flags != NULL)
2714*34c72144SAxel Dörfler 		*_flags = reply.flags;
2715b65a0ac5SJérôme Duval 
2716*34c72144SAxel Dörfler 	TRACE("BMediaRoster::GetInitialLatencyFor producer %ld has maximum "
2717*34c72144SAxel Dörfler 		"initial latency %Ld\n", producer.node, *_latency);
2718aac800c2Sbeveloper 	return B_OK;
271952a38012Sejakowatz }
272052a38012Sejakowatz 
272152a38012Sejakowatz 
272252a38012Sejakowatz status_t
2723*34c72144SAxel Dörfler BMediaRoster::GetStartLatencyFor(const media_node& timeSource,
2724*34c72144SAxel Dörfler 	bigtime_t* _latency)
272552a38012Sejakowatz {
2726fc8b28b6SJérôme Duval 	CALLED();
2727*34c72144SAxel Dörfler 	if (_latency == NULL)
2728fc8b28b6SJérôme Duval 		return B_BAD_VALUE;
2729*34c72144SAxel Dörfler 	if (IS_INVALID_NODE(timeSource)
2730*34c72144SAxel Dörfler 		|| (timeSource.kind & B_TIME_SOURCE) == 0)
2731fc8b28b6SJérôme Duval 		return B_MEDIA_BAD_NODE;
2732fc8b28b6SJérôme Duval 
2733fc8b28b6SJérôme Duval 	timesource_get_start_latency_request request;
2734fc8b28b6SJérôme Duval 	timesource_get_start_latency_reply reply;
2735fc8b28b6SJérôme Duval 	status_t rv;
2736fc8b28b6SJérôme Duval 
2737*34c72144SAxel Dörfler 	rv = QueryPort(timeSource.port, TIMESOURCE_GET_START_LATENCY, &request,
2738*34c72144SAxel Dörfler 		sizeof(request), &reply, sizeof(reply));
2739fc8b28b6SJérôme Duval 	if (rv != B_OK)
2740fc8b28b6SJérôme Duval 		return rv;
2741fc8b28b6SJérôme Duval 
2742*34c72144SAxel Dörfler 	*_latency = reply.start_latency;
2743fc8b28b6SJérôme Duval 
2744*34c72144SAxel Dörfler 	TRACE("BMediaRoster::GetStartLatencyFor timesource %ld has maximum "
2745*34c72144SAxel Dörfler 		"initial latency %Ld\n", timeSource.node, *_latency);
2746aac800c2Sbeveloper 	return B_OK;
274752a38012Sejakowatz }
274852a38012Sejakowatz 
274952a38012Sejakowatz 
275052a38012Sejakowatz status_t
2751*34c72144SAxel Dörfler BMediaRoster::GetFileFormatsFor(const media_node& fileInterface,
2752*34c72144SAxel Dörfler 	media_file_format* _formats, int32* _numFormats)
275352a38012Sejakowatz {
275452a38012Sejakowatz 	UNIMPLEMENTED();
275552a38012Sejakowatz 	return B_ERROR;
275652a38012Sejakowatz }
275752a38012Sejakowatz 
275852a38012Sejakowatz 
275952a38012Sejakowatz status_t
2760*34c72144SAxel Dörfler BMediaRoster::SetRefFor(const media_node& file_interface, const entry_ref& file,
2761*34c72144SAxel Dörfler 	bool createAndTruncate, bigtime_t* _length)
276252a38012Sejakowatz {
27636938364bSMaurice Kalinowski 	CALLED();
27646938364bSMaurice Kalinowski 
27656938364bSMaurice Kalinowski 	fileinterface_set_ref_request request;
27666938364bSMaurice Kalinowski 	fileinterface_set_ref_reply reply;
27676938364bSMaurice Kalinowski 	status_t rv;
27686938364bSMaurice Kalinowski 
27696938364bSMaurice Kalinowski 	request.device = file.device;
27706938364bSMaurice Kalinowski 	request.directory = file.directory;
27716938364bSMaurice Kalinowski 	strcpy(request.name, file.name);
2772*34c72144SAxel Dörfler 	request.create = createAndTruncate;
2773*34c72144SAxel Dörfler 	if (_length != NULL)
2774*34c72144SAxel Dörfler 		request.duration = *_length;
27756938364bSMaurice Kalinowski 
2776*34c72144SAxel Dörfler 	rv = QueryPort(file_interface.port, FILEINTERFACE_SET_REF, &request,
2777*34c72144SAxel Dörfler 		sizeof(request), &reply, sizeof(reply));
27786938364bSMaurice Kalinowski 	if (rv != B_OK)
27796938364bSMaurice Kalinowski 		return rv;
27806938364bSMaurice Kalinowski 
2781*34c72144SAxel Dörfler 	if (!createAndTruncate && _length)
2782*34c72144SAxel Dörfler 		*_length = reply.duration;
27836938364bSMaurice Kalinowski 
27846938364bSMaurice Kalinowski 	return B_OK;
278552a38012Sejakowatz }
278652a38012Sejakowatz 
278752a38012Sejakowatz 
278852a38012Sejakowatz status_t
2789*34c72144SAxel Dörfler BMediaRoster::GetRefFor(const media_node& node, entry_ref* _file,
2790*34c72144SAxel Dörfler 	BMimeType* mimeType)
279152a38012Sejakowatz {
27926938364bSMaurice Kalinowski 	CALLED();
27936938364bSMaurice Kalinowski 
2794*34c72144SAxel Dörfler 	if (!_file)
27956938364bSMaurice Kalinowski 		return B_BAD_VALUE;
27966938364bSMaurice Kalinowski 
27976938364bSMaurice Kalinowski 	fileinterface_get_ref_request request;
27986938364bSMaurice Kalinowski 	fileinterface_get_ref_reply reply;
27996938364bSMaurice Kalinowski 	status_t rv;
28006938364bSMaurice Kalinowski 
2801*34c72144SAxel Dörfler 	rv = QueryPort(node.port, FILEINTERFACE_GET_REF, &request, sizeof(request),
2802*34c72144SAxel Dörfler 		&reply, sizeof(reply));
28036938364bSMaurice Kalinowski 	if (rv != B_OK)
28046938364bSMaurice Kalinowski 		return rv;
28056938364bSMaurice Kalinowski 
2806*34c72144SAxel Dörfler 	*_file = entry_ref(reply.device, reply.directory, reply.name);
28076938364bSMaurice Kalinowski 
2808*34c72144SAxel Dörfler 	if (mimeType)
2809*34c72144SAxel Dörfler 		mimeType->SetTo(reply.mimetype);
28106938364bSMaurice Kalinowski 
28116938364bSMaurice Kalinowski 	return B_OK;
281252a38012Sejakowatz }
281352a38012Sejakowatz 
281452a38012Sejakowatz 
281552a38012Sejakowatz status_t
281652a38012Sejakowatz BMediaRoster::SniffRefFor(const media_node& file_interface,
2817*34c72144SAxel Dörfler 	const entry_ref& file, BMimeType* mimeType, float* _capability)
281852a38012Sejakowatz {
28196938364bSMaurice Kalinowski 	CALLED();
2820*34c72144SAxel Dörfler 	if (mimeType == NULL || _capability == NULL)
28216938364bSMaurice Kalinowski 		return B_BAD_VALUE;
28226938364bSMaurice Kalinowski 
28236938364bSMaurice Kalinowski 	fileinterface_sniff_ref_request request;
28246938364bSMaurice Kalinowski 	fileinterface_sniff_ref_reply reply;
28256938364bSMaurice Kalinowski 	status_t rv;
28266938364bSMaurice Kalinowski 
28276938364bSMaurice Kalinowski 	request.device = file.device;
28286938364bSMaurice Kalinowski 	request.directory = file.directory;
28296938364bSMaurice Kalinowski 	strcpy(request.name, file.name);
28306938364bSMaurice Kalinowski 
2831*34c72144SAxel Dörfler 	rv = QueryPort(file_interface.port, FILEINTERFACE_SNIFF_REF, &request,
2832*34c72144SAxel Dörfler 		sizeof(request), &reply, sizeof(reply));
28336938364bSMaurice Kalinowski 	if (rv != B_OK)
28346938364bSMaurice Kalinowski 		return rv;
28356938364bSMaurice Kalinowski 
2836*34c72144SAxel Dörfler 	mimeType->SetTo(reply.mimetype);
2837*34c72144SAxel Dörfler 	*_capability = reply.capability;
28386938364bSMaurice Kalinowski 
28396938364bSMaurice Kalinowski 	return B_OK;
284052a38012Sejakowatz }
284152a38012Sejakowatz 
284252a38012Sejakowatz 
2843*34c72144SAxel Dörfler /*!	This is the generic "here's a file, now can someone please play it"
2844*34c72144SAxel Dörfler 	interface.
2845*34c72144SAxel Dörfler */
284652a38012Sejakowatz status_t
2847*34c72144SAxel Dörfler BMediaRoster::SniffRef(const entry_ref& file, uint64 requireNodeKinds,
2848*34c72144SAxel Dörfler 	dormant_node_info* _node, BMimeType* mimeType)
284952a38012Sejakowatz {
285052a38012Sejakowatz 	UNIMPLEMENTED();
285152a38012Sejakowatz 	return B_ERROR;
285252a38012Sejakowatz }
285352a38012Sejakowatz 
285452a38012Sejakowatz 
285552a38012Sejakowatz status_t
285652a38012Sejakowatz BMediaRoster::GetDormantNodeForType(const BMimeType& type,
2857*34c72144SAxel Dörfler 	uint64 requireNodeKinds, dormant_node_info* _node)
285852a38012Sejakowatz {
285952a38012Sejakowatz 	UNIMPLEMENTED();
286052a38012Sejakowatz 	return B_ERROR;
286152a38012Sejakowatz }
286252a38012Sejakowatz 
286352a38012Sejakowatz 
286452a38012Sejakowatz status_t
2865*34c72144SAxel Dörfler BMediaRoster::GetReadFileFormatsFor(const dormant_node_info& node,
2866*34c72144SAxel Dörfler 	media_file_format* _readFormats, int32 readCount, int32* _readCount)
286752a38012Sejakowatz {
286852a38012Sejakowatz 	UNIMPLEMENTED();
286952a38012Sejakowatz 	return B_ERROR;
287052a38012Sejakowatz }
287152a38012Sejakowatz 
287252a38012Sejakowatz 
287352a38012Sejakowatz status_t
2874*34c72144SAxel Dörfler BMediaRoster::GetWriteFileFormatsFor(const dormant_node_info& node,
2875*34c72144SAxel Dörfler 	media_file_format* _write_formats, int32 writeCount, int32* _writeCount)
287652a38012Sejakowatz {
287752a38012Sejakowatz 	UNIMPLEMENTED();
287852a38012Sejakowatz 	return B_ERROR;
287952a38012Sejakowatz }
288052a38012Sejakowatz 
288152a38012Sejakowatz 
288252a38012Sejakowatz status_t
2883*34c72144SAxel Dörfler BMediaRoster::GetFormatFor(const media_output& output, media_format* _format,
288452a38012Sejakowatz 	uint32 flags)
288552a38012Sejakowatz {
28869bedd42cSbeveloper 	CALLED();
2887*34c72144SAxel Dörfler 	if (_format == NULL)
28889bedd42cSbeveloper 		return B_BAD_VALUE;
28899bedd42cSbeveloper 	if ((output.node.kind & B_BUFFER_PRODUCER) == 0)
28909bedd42cSbeveloper 		return B_MEDIA_BAD_NODE;
28919bedd42cSbeveloper 	if (IS_INVALID_SOURCE(output.source))
28929bedd42cSbeveloper 		return B_MEDIA_BAD_SOURCE;
28939bedd42cSbeveloper 
28949bedd42cSbeveloper 	producer_format_suggestion_requested_request request;
28959bedd42cSbeveloper 	producer_format_suggestion_requested_reply reply;
28969bedd42cSbeveloper 	status_t rv;
28979bedd42cSbeveloper 
28989bedd42cSbeveloper 	request.type = B_MEDIA_UNKNOWN_TYPE;
2899*34c72144SAxel Dörfler 	request.quality = 0; // TODO: what should this be?
29009bedd42cSbeveloper 
2901*34c72144SAxel Dörfler 	rv = QueryPort(output.source.port, PRODUCER_FORMAT_SUGGESTION_REQUESTED,
2902*34c72144SAxel Dörfler 		&request, sizeof(request), &reply, sizeof(reply));
29039bedd42cSbeveloper 	if (rv != B_OK)
29049bedd42cSbeveloper 		return rv;
29059bedd42cSbeveloper 
2906*34c72144SAxel Dörfler 	*_format = reply.format;
29079bedd42cSbeveloper 	return B_OK;
290852a38012Sejakowatz }
290952a38012Sejakowatz 
291052a38012Sejakowatz 
291152a38012Sejakowatz status_t
2912*34c72144SAxel Dörfler BMediaRoster::GetFormatFor(const media_input& input, media_format* _format,
291352a38012Sejakowatz 	uint32 flags)
291452a38012Sejakowatz {
29159bedd42cSbeveloper 	CALLED();
2916*34c72144SAxel Dörfler 	if (_format == NULL)
29179bedd42cSbeveloper 		return B_BAD_VALUE;
29189bedd42cSbeveloper 	if ((input.node.kind & B_BUFFER_CONSUMER) == 0)
29199bedd42cSbeveloper 		return B_MEDIA_BAD_NODE;
29209bedd42cSbeveloper 	if (IS_INVALID_DESTINATION(input.destination))
29219bedd42cSbeveloper 		return B_MEDIA_BAD_DESTINATION;
29229bedd42cSbeveloper 
29239bedd42cSbeveloper 	consumer_accept_format_request request;
29249bedd42cSbeveloper 	consumer_accept_format_reply reply;
29259bedd42cSbeveloper 	status_t rv;
29269bedd42cSbeveloper 
29279bedd42cSbeveloper 	request.dest = input.destination;
29289bedd42cSbeveloper 	memset(&request.format, 0, sizeof(request.format)); // wildcard
29299bedd42cSbeveloper 
2930*34c72144SAxel Dörfler 	rv = QueryPort(input.destination.port, CONSUMER_ACCEPT_FORMAT, &request,
2931*34c72144SAxel Dörfler 		sizeof(request), &reply, sizeof(reply));
29329bedd42cSbeveloper 	if (rv != B_OK)
29339bedd42cSbeveloper 		return rv;
29349bedd42cSbeveloper 
2935*34c72144SAxel Dörfler 	*_format = reply.format;
29369bedd42cSbeveloper 	return B_OK;
293752a38012Sejakowatz }
293852a38012Sejakowatz 
293952a38012Sejakowatz 
294052a38012Sejakowatz status_t
2941*34c72144SAxel Dörfler BMediaRoster::GetFormatFor(const media_node& node, media_format* _format,
294252a38012Sejakowatz 	float quality)
294352a38012Sejakowatz {
294452a38012Sejakowatz 	UNIMPLEMENTED();
2945*34c72144SAxel Dörfler 	if (_format == NULL)
29469bedd42cSbeveloper 		return B_BAD_VALUE;
29479bedd42cSbeveloper 	if (IS_INVALID_NODE(node))
29489bedd42cSbeveloper 		return B_MEDIA_BAD_NODE;
29499bedd42cSbeveloper 	if ((node.kind & (B_BUFFER_CONSUMER | B_BUFFER_PRODUCER)) == 0)
29509bedd42cSbeveloper 		return B_MEDIA_BAD_NODE;
29519bedd42cSbeveloper 
295252a38012Sejakowatz 	return B_ERROR;
295352a38012Sejakowatz }
295452a38012Sejakowatz 
295552a38012Sejakowatz 
295652a38012Sejakowatz ssize_t
295752a38012Sejakowatz BMediaRoster::GetNodeAttributesFor(const media_node& node,
2958*34c72144SAxel Dörfler 	media_node_attribute* _array, size_t maxCount)
295952a38012Sejakowatz {
296052a38012Sejakowatz 	UNIMPLEMENTED();
296152a38012Sejakowatz 	return B_ERROR;
296252a38012Sejakowatz }
296352a38012Sejakowatz 
296452a38012Sejakowatz 
296552a38012Sejakowatz media_node_id
2966*34c72144SAxel Dörfler BMediaRoster::NodeIDFor(port_id port)
296752a38012Sejakowatz {
29689e9417d2Sbeveloper 	CALLED();
29699e9417d2Sbeveloper 
29709e9417d2Sbeveloper 	server_node_id_for_request request;
29719e9417d2Sbeveloper 	server_node_id_for_reply reply;
29729e9417d2Sbeveloper 	status_t rv;
29739e9417d2Sbeveloper 
2974*34c72144SAxel Dörfler 	request.port = port;
29759e9417d2Sbeveloper 
2976*34c72144SAxel Dörfler 	rv = QueryServer(SERVER_NODE_ID_FOR, &request, sizeof(request), &reply,
2977*34c72144SAxel Dörfler 		sizeof(reply));
29789e9417d2Sbeveloper 	if (rv != B_OK) {
29795ac4fbd7Sbeveloper 		ERROR("BMediaRoster::NodeIDFor: failed (error %#lx)\n", rv);
29809e9417d2Sbeveloper 		return -1;
29819e9417d2Sbeveloper 	}
29829e9417d2Sbeveloper 
29839e9417d2Sbeveloper 	return reply.nodeid;
298452a38012Sejakowatz }
298552a38012Sejakowatz 
298652a38012Sejakowatz 
298752a38012Sejakowatz status_t
2988*34c72144SAxel Dörfler BMediaRoster::GetInstancesFor(media_addon_id addon, int32 flavor,
2989*34c72144SAxel Dörfler 	media_node_id* _id, int32* _count)
299052a38012Sejakowatz {
299185dfab2bSbeveloper 	CALLED();
2992*34c72144SAxel Dörfler 	if (_id == NULL)
299385dfab2bSbeveloper 		return B_BAD_VALUE;
2994*34c72144SAxel Dörfler 	if (_count && *_count <= 0)
299585dfab2bSbeveloper 		return B_BAD_VALUE;
299685dfab2bSbeveloper 
299785dfab2bSbeveloper 	server_get_instances_for_request request;
299885dfab2bSbeveloper 	server_get_instances_for_reply reply;
299985dfab2bSbeveloper 	status_t rv;
300085dfab2bSbeveloper 
3001*34c72144SAxel Dörfler 	request.maxcount = (_count ? *_count : 1);
300285dfab2bSbeveloper 	request.addon_id = addon;
300385dfab2bSbeveloper 	request.addon_flavor_id = flavor;
300485dfab2bSbeveloper 
3005*34c72144SAxel Dörfler 	rv = QueryServer(SERVER_GET_INSTANCES_FOR, &request, sizeof(request),
3006*34c72144SAxel Dörfler 		&reply, sizeof(reply));
300785dfab2bSbeveloper 	if (rv != B_OK) {
30085ac4fbd7Sbeveloper 		ERROR("BMediaRoster::GetLiveNodes failed\n");
300985dfab2bSbeveloper 		return rv;
301052a38012Sejakowatz 	}
301152a38012Sejakowatz 
3012*34c72144SAxel Dörfler 	if (_count)
3013*34c72144SAxel Dörfler 		*_count = reply.count;
301485dfab2bSbeveloper 	if (reply.count > 0)
3015*34c72144SAxel Dörfler 		memcpy(_id, reply.node_id, sizeof(media_node_id) * reply.count);
301685dfab2bSbeveloper 
301785dfab2bSbeveloper 	return B_OK;
301885dfab2bSbeveloper }
301952a38012Sejakowatz 
302052a38012Sejakowatz 
302152a38012Sejakowatz status_t
3022*34c72144SAxel Dörfler BMediaRoster::SetRealtimeFlags(uint32 enabled)
302352a38012Sejakowatz {
302452a38012Sejakowatz 	UNIMPLEMENTED();
302552a38012Sejakowatz 	return B_ERROR;
302652a38012Sejakowatz }
302752a38012Sejakowatz 
302852a38012Sejakowatz 
302952a38012Sejakowatz status_t
3030*34c72144SAxel Dörfler BMediaRoster::GetRealtimeFlags(uint32* _enabled)
303152a38012Sejakowatz {
303252a38012Sejakowatz 	UNIMPLEMENTED();
303352a38012Sejakowatz 	return B_ERROR;
303452a38012Sejakowatz }
303552a38012Sejakowatz 
303652a38012Sejakowatz 
303752a38012Sejakowatz ssize_t
3038*34c72144SAxel Dörfler BMediaRoster::AudioBufferSizeFor(int32 channelCount, uint32 sampleFormat,
3039*34c72144SAxel Dörfler 	float frameRate, bus_type busKind)
304052a38012Sejakowatz {
3041*34c72144SAxel Dörfler 	bigtime_t bufferDuration;
3042*34c72144SAxel Dörfler 	ssize_t bufferSize;
3043df6c2e83Sbeveloper 
3044df6c2e83Sbeveloper 	system_info info;
3045df6c2e83Sbeveloper 	get_system_info(&info);
3046df6c2e83Sbeveloper 
3047*34c72144SAxel Dörfler 	if (info.cpu_clock_speed > 2000000000)	// 2 GHz
3048*34c72144SAxel Dörfler 		bufferDuration = 2500;
3049df6c2e83Sbeveloper 	else if (info.cpu_clock_speed > 1000000000)
3050*34c72144SAxel Dörfler 		bufferDuration = 5000;
3051df6c2e83Sbeveloper 	else if (info.cpu_clock_speed > 600000000)
3052*34c72144SAxel Dörfler 		bufferDuration = 10000;
3053df6c2e83Sbeveloper 	else if (info.cpu_clock_speed > 200000000)
3054*34c72144SAxel Dörfler 		bufferDuration = 20000;
3055df6c2e83Sbeveloper 	else if (info.cpu_clock_speed > 100000000)
3056*34c72144SAxel Dörfler 		bufferDuration = 30000;
3057df6c2e83Sbeveloper 	else
3058*34c72144SAxel Dörfler 		bufferDuration = 50000;
3059df6c2e83Sbeveloper 
3060*34c72144SAxel Dörfler 	if ((busKind == B_ISA_BUS || busKind == B_PCMCIA_BUS)
3061*34c72144SAxel Dörfler 		&& bufferDuration < 25000)
3062*34c72144SAxel Dörfler 		bufferDuration = 25000;
3063df6c2e83Sbeveloper 
3064*34c72144SAxel Dörfler 	bufferSize = (sampleFormat & 0xf) * channelCount
3065*34c72144SAxel Dörfler 		* (ssize_t)((frameRate * bufferDuration) / 1000000.0);
3066df6c2e83Sbeveloper 
3067*34c72144SAxel Dörfler 	printf("Suggested buffer duration %Ld, size %ld\n", bufferDuration,
3068*34c72144SAxel Dörfler 		bufferSize);
3069df6c2e83Sbeveloper 
3070*34c72144SAxel Dörfler 	return bufferSize;
307152a38012Sejakowatz }
307252a38012Sejakowatz 
307352a38012Sejakowatz 
3074*34c72144SAxel Dörfler /*!	Use MediaFlags to inquire about specific features of the Media Kit.
3075*34c72144SAxel Dörfler 	Returns < 0 for "not present", positive size for output data size.
3076*34c72144SAxel Dörfler 	0 means that the capability is present, but no data about it.
3077*34c72144SAxel Dörfler */
307852a38012Sejakowatz /*static*/ ssize_t
3079*34c72144SAxel Dörfler BMediaRoster::MediaFlags(media_flags cap, void* buffer, size_t maxSize)
308052a38012Sejakowatz {
308152a38012Sejakowatz 	UNIMPLEMENTED();
308252a38012Sejakowatz 	return 0;
308352a38012Sejakowatz }
308452a38012Sejakowatz 
308552a38012Sejakowatz 
3086*34c72144SAxel Dörfler //	#pragma mark - BLooper overrides
3087*34c72144SAxel Dörfler 
3088*34c72144SAxel Dörfler 
3089*34c72144SAxel Dörfler void
309052a38012Sejakowatz BMediaRoster::MessageReceived(BMessage* message)
309152a38012Sejakowatz {
3092cf4e2277Sbeveloper 	switch (message->what) {
3093cf4e2277Sbeveloper 		case 'PING':
3094cf4e2277Sbeveloper 		{
30956396865dSbeveloper 			// media_server plays ping-pong with the BMediaRosters
30966396865dSbeveloper 			// to detect dead teams. Normal communication uses ports.
30976396865dSbeveloper 			static BMessage pong('PONG');
30986396865dSbeveloper 			message->SendReply(&pong, static_cast<BHandler *>(NULL), 2000000);
30996396865dSbeveloper 			return;
31006396865dSbeveloper 		}
31016396865dSbeveloper 
3102cf4e2277Sbeveloper 		case NODE_FINAL_RELEASE:
3103cf4e2277Sbeveloper 		{
3104cf4e2277Sbeveloper 			// this function is called by a BMediaNode to delete
3105cf4e2277Sbeveloper 			// itself, as this needs to be done from another thread
3106cf4e2277Sbeveloper 			// context, it is done here.
3107*34c72144SAxel Dörfler 			// TODO: If a node is released using BMediaRoster::ReleaseNode()
3108*34c72144SAxel Dörfler 			// TODO: instead of using BMediaNode::Release() / BMediaNode::Acquire()
3109*34c72144SAxel Dörfler 			// TODO: fRefCount of the BMediaNode will not be correct.
3110cf4e2277Sbeveloper 
3111cf4e2277Sbeveloper 			BMediaNode *node;
3112cf4e2277Sbeveloper 			message->FindPointer("node", reinterpret_cast<void **>(&node));
3113cf4e2277Sbeveloper 
311454187cc6Sbeveloper 			TRACE("BMediaRoster::MessageReceived NODE_FINAL_RELEASE saving node %ld configuration\n", node->ID());
311554187cc6Sbeveloper 			MediaRosterEx(BMediaRoster::Roster())->SaveNodeConfiguration(node);
3116cf4e2277Sbeveloper 
311754187cc6Sbeveloper 			TRACE("BMediaRoster::MessageReceived NODE_FINAL_RELEASE releasing node %ld\n", node->ID());
3118cf4e2277Sbeveloper 			node->DeleteHook(node); // we don't call Release(), see above!
3119cf4e2277Sbeveloper 			return;
3120cf4e2277Sbeveloper 		}
3121cf4e2277Sbeveloper 	}
31226396865dSbeveloper 	printf("BMediaRoster::MessageReceived: unknown message!\n");
31236396865dSbeveloper 	message->PrintToStream();
312452a38012Sejakowatz }
312552a38012Sejakowatz 
3126*34c72144SAxel Dörfler 
3127*34c72144SAxel Dörfler bool
312852a38012Sejakowatz BMediaRoster::QuitRequested()
312952a38012Sejakowatz {
313052a38012Sejakowatz 	UNIMPLEMENTED();
313152a38012Sejakowatz 	return true;
313252a38012Sejakowatz }
313352a38012Sejakowatz 
3134*34c72144SAxel Dörfler 
3135*34c72144SAxel Dörfler BHandler*
3136*34c72144SAxel Dörfler BMediaRoster::ResolveSpecifier(BMessage* msg, int32 index, BMessage* specifier,
3137*34c72144SAxel Dörfler 	int32 form, const char* property)
313852a38012Sejakowatz {
3139286a3c91SJérôme Duval 	return BLooper::ResolveSpecifier(msg, index, specifier, form, property);
314052a38012Sejakowatz }
314152a38012Sejakowatz 
314252a38012Sejakowatz 
3143*34c72144SAxel Dörfler status_t
314452a38012Sejakowatz BMediaRoster::GetSupportedSuites(BMessage* data)
314552a38012Sejakowatz {
3146286a3c91SJérôme Duval 	return BLooper::GetSupportedSuites(data);
314752a38012Sejakowatz }
314852a38012Sejakowatz 
314952a38012Sejakowatz 
315052a38012Sejakowatz BMediaRoster::~BMediaRoster()
315152a38012Sejakowatz {
315252a38012Sejakowatz 	CALLED();
31536396865dSbeveloper 
31546396865dSbeveloper 	// unregister this application with the media server
31556396865dSbeveloper 	server_unregister_app_request request;
31566396865dSbeveloper 	server_unregister_app_reply reply;
31576396865dSbeveloper 	request.team = team;
3158*34c72144SAxel Dörfler 	QueryServer(SERVER_UNREGISTER_APP, &request, sizeof(request), &reply,
3159*34c72144SAxel Dörfler 		sizeof(reply));
31608b940bb4SStephan Aßmus 
31618b940bb4SStephan Aßmus 	// Unset the global instance pointer, the destructor is also called
31628b940bb4SStephan Aßmus 	// if a client app calls Lock(); and Quit(); directly.
31639def3bf7SStephan Aßmus 	sDefaultInstance = NULL;
316452a38012Sejakowatz }
316552a38012Sejakowatz 
316652a38012Sejakowatz 
3167*34c72144SAxel Dörfler //	#pragma mark - private BMediaRoster
3168*34c72144SAxel Dörfler 
316952a38012Sejakowatz 
317052a38012Sejakowatz // deprecated call
317152a38012Sejakowatz status_t
317252a38012Sejakowatz BMediaRoster::SetOutputBuffersFor(const media_source& output,
3173*34c72144SAxel Dörfler 	BBufferGroup* group, bool willReclaim)
317452a38012Sejakowatz {
317552a38012Sejakowatz 	UNIMPLEMENTED();
31769e9417d2Sbeveloper 	debugger("BMediaRoster::SetOutputBuffersFor missing\n");
317752a38012Sejakowatz 	return B_ERROR;
317852a38012Sejakowatz }
317952a38012Sejakowatz 
318052a38012Sejakowatz 
3181*34c72144SAxel Dörfler /* FBC reserved virtuals */
318252a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_0(void *) { return B_ERROR; }
318352a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_1(void *) { return B_ERROR; }
318452a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_2(void *) { return B_ERROR; }
318552a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_3(void *) { return B_ERROR; }
318652a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_4(void *) { return B_ERROR; }
318752a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_5(void *) { return B_ERROR; }
318852a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_6(void *) { return B_ERROR; }
318952a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_7(void *) { return B_ERROR; }
319052a38012Sejakowatz 
319152a38012Sejakowatz 
3192*34c72144SAxel Dörfler BMediaRoster::BMediaRoster()
3193*34c72144SAxel Dörfler 	: BLooper("_BMediaRoster_", B_URGENT_DISPLAY_PRIORITY,
3194*34c72144SAxel Dörfler 		B_LOOPER_PORT_DEFAULT_CAPACITY)
319552a38012Sejakowatz {
319652a38012Sejakowatz 	CALLED();
31976396865dSbeveloper 
31986396865dSbeveloper 	// start the looper
31996396865dSbeveloper 	Run();
320052a38012Sejakowatz }
320152a38012Sejakowatz 
32026396865dSbeveloper 
32039def3bf7SStephan Aßmus // TODO: Looks like these can be safely removed:
320452a38012Sejakowatz /*static*/ status_t
320552a38012Sejakowatz BMediaRoster::ParseCommand(BMessage& reply)
320652a38012Sejakowatz {
320752a38012Sejakowatz 	UNIMPLEMENTED();
320852a38012Sejakowatz 	return B_ERROR;
320952a38012Sejakowatz }
321052a38012Sejakowatz 
321152a38012Sejakowatz 
321252a38012Sejakowatz status_t
3213*34c72144SAxel Dörfler BMediaRoster::GetDefaultInfo(media_node_id forDefault, BMessage& config)
321452a38012Sejakowatz {
321552a38012Sejakowatz 	UNIMPLEMENTED();
321652a38012Sejakowatz 	return B_ERROR;
321752a38012Sejakowatz }
321852a38012Sejakowatz 
321952a38012Sejakowatz 
322052a38012Sejakowatz status_t
3221*34c72144SAxel Dörfler BMediaRoster::SetRunningDefault(media_node_id forDefault,
322252a38012Sejakowatz 	const media_node& node)
322352a38012Sejakowatz {
322452a38012Sejakowatz 	UNIMPLEMENTED();
322552a38012Sejakowatz 	return B_ERROR;
322652a38012Sejakowatz }
322752a38012Sejakowatz 
322852a38012Sejakowatz 
32299def3bf7SStephan Aßmus // #pragma mark - static variables
323052a38012Sejakowatz 
32319def3bf7SStephan Aßmus 
32329def3bf7SStephan Aßmus BMediaRoster* BMediaRoster::sDefaultInstance = NULL;
323352a38012Sejakowatz 
3234