xref: /haiku/src/kits/media/MediaRoster.cpp (revision 1ecccf181e7244f969dc99a33f84193af7d83a7f)
1255a01c7Sbeveloper /*
234c72144SAxel Dörfler  * Copyright 2008 Maurice Kalinowski, haiku@kaldience.com
334c72144SAxel Dörfler  * Copyright 2009, Axel Dörfler, axeld@pinc-software.de.
434c72144SAxel Dörfler  *
534c72144SAxel Dörfler  * All rights reserved. Distributed under the terms of the MIT License.
634c72144SAxel Dörfler  */
734c72144SAxel Dörfler 
834c72144SAxel 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 
9234c72144SAxel 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);
10134c72144SAxel Dörfler 	rv = QueryServer(SERVER_REGISTER_APP, &request, sizeof(request), &reply,
10234c72144SAxel Dörfler 		sizeof(reply));
103a7fb4c16SMaurice Kalinowski 	if (rv != B_OK)
10434c72144SAxel Dörfler 		*_error = B_MEDIA_SYSTEM_FAILURE;
105a7fb4c16SMaurice Kalinowski 	else
10634c72144SAxel Dörfler 		*_error = B_OK;
107dcfb6bfcSJérôme Duval }
108dcfb6bfcSJérôme Duval 
10934c72144SAxel 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.
12034c72144SAxel 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 
12734c72144SAxel 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 
13334c72144SAxel Dörfler 
13454187cc6Sbeveloper status_t
1358b940bb4SStephan Aßmus BMediaRosterEx::LoadNodeConfiguration(media_addon_id addonid, int32 flavorid,
1368b940bb4SStephan Aßmus 	BMessage *out_msg)
13754187cc6Sbeveloper {
13834c72144SAxel 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 
14534c72144SAxel Dörfler 
14654187cc6Sbeveloper status_t
14734c72144SAxel Dörfler BMediaRosterEx::IncrementAddonFlavorInstancesCount(media_addon_id addonid,
14834c72144SAxel 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;
15734c72144SAxel Dörfler 	return QueryServer(SERVER_CHANGE_ADDON_FLAVOR_INSTANCES_COUNT, &request,
15834c72144SAxel Dörfler 		sizeof(request), &reply, sizeof(reply));
15954187cc6Sbeveloper }
16054187cc6Sbeveloper 
16134c72144SAxel Dörfler 
16254187cc6Sbeveloper status_t
16334c72144SAxel Dörfler BMediaRosterEx::DecrementAddonFlavorInstancesCount(media_addon_id addonid,
16434c72144SAxel 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;
17334c72144SAxel Dörfler 	return QueryServer(SERVER_CHANGE_ADDON_FLAVOR_INSTANCES_COUNT, &request,
17434c72144SAxel Dörfler 		sizeof(request), &reply, sizeof(reply));
17554187cc6Sbeveloper }
17654187cc6Sbeveloper 
17734c72144SAxel 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;
18634c72144SAxel Dörfler 	return QueryServer(SERVER_SET_NODE_CREATOR, &request, sizeof(request),
18734c72144SAxel Dörfler 		&reply, sizeof(reply));
18854187cc6Sbeveloper }
18954187cc6Sbeveloper 
19034c72144SAxel Dörfler 
19154187cc6Sbeveloper status_t
19234c72144SAxel Dörfler BMediaRosterEx::GetNode(node_type type, media_node* out_node,
19334c72144SAxel 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;
20434c72144SAxel Dörfler 	rv = QueryServer(SERVER_GET_NODE, &request, sizeof(request), &reply,
20534c72144SAxel 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 
21734c72144SAxel Dörfler 
2183620737cSbeveloper status_t
21934c72144SAxel Dörfler BMediaRosterEx::SetNode(node_type type, const media_node* node,
22034c72144SAxel 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;
22634c72144SAxel Dörfler 	request.use_node = node != NULL;
22734c72144SAxel Dörfler 	if (node != NULL)
2288c6a6096Sbeveloper 		request.node = *node;
22934c72144SAxel Dörfler 	request.use_dni = info != NULL;
23034c72144SAxel Dörfler 	if (info != NULL)
2318c6a6096Sbeveloper 		request.dni = *info;
23234c72144SAxel Dörfler 	request.use_input = input != NULL;
23334c72144SAxel Dörfler 	if (input != NULL)
2348c6a6096Sbeveloper 		request.input = *input;
23552a38012Sejakowatz 
23634c72144SAxel Dörfler 	return QueryServer(SERVER_SET_NODE, &request, sizeof(request), &reply,
23734c72144SAxel Dörfler 		sizeof(reply));
23852a38012Sejakowatz }
23952a38012Sejakowatz 
24034c72144SAxel 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 
24834c72144SAxel Dörfler 	PRINT(4, "BMediaRosterEx::GetAllOutputs() node %ld, port %ld\n", node.node,
24934c72144SAxel Dörfler 		node.port);
2505ac4fbd7Sbeveloper 
25165b73ae4SMarcus Overhagen 	if (!(node.kind & B_BUFFER_PRODUCER)) {
25234c72144SAxel Dörfler 		ERROR("BMediaRosterEx::GetAllOutputs: node %ld is not a "
25334c72144SAxel 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;
26434c72144SAxel Dörfler 		rv = QueryPort(node.port, PRODUCER_GET_NEXT_OUTPUT, &request,
26534c72144SAxel 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;
28134c72144SAxel Dörfler 	QueryPort(node.port, PRODUCER_DISPOSE_OUTPUT_COOKIE, &request,
28234c72144SAxel Dörfler 		sizeof(request), &reply, sizeof(reply));
2833620737cSbeveloper 
2843620737cSbeveloper 	return result;
2853620737cSbeveloper }
2863620737cSbeveloper 
28734c72144SAxel 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 
31634c72144SAxel 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 
32434c72144SAxel Dörfler 	PRINT(4, "BMediaRosterEx::GetAllInputs() node %ld, port %ld\n", node.node,
32534c72144SAxel Dörfler 		node.port);
3265ac4fbd7Sbeveloper 
32765b73ae4SMarcus Overhagen 	if (!(node.kind & B_BUFFER_CONSUMER)) {
32834c72144SAxel Dörfler 		ERROR("BMediaRosterEx::GetAllInputs: node %ld is not a "
32934c72144SAxel 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;
34034c72144SAxel Dörfler 		rv = QueryPort(node.port, CONSUMER_GET_NEXT_INPUT, &request,
34134c72144SAxel 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;
35734c72144SAxel Dörfler 	QueryPort(node.port, CONSUMER_DISPOSE_INPUT_COOKIE, &request,
35834c72144SAxel Dörfler 		sizeof(request), &reply, sizeof(reply));
3593620737cSbeveloper 
3603620737cSbeveloper 	return result;
3613620737cSbeveloper }
3623620737cSbeveloper 
36334c72144SAxel 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 
39234c72144SAxel 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));
41234c72144SAxel Dörfler 		request.area = create_area("publish outputs", &start_addr,
41334c72144SAxel Dörfler 			B_ANY_ADDRESS, size, B_NO_LOCK, B_READ_AREA | B_WRITE_AREA);
4143620737cSbeveloper 		if (request.area < B_OK) {
41534c72144SAxel Dörfler 			ERROR("PublishOutputs: failed to create area, %#lx\n",
41634c72144SAxel 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 
43234c72144SAxel Dörfler 	rv = QueryServer(SERVER_PUBLISH_OUTPUTS, &request, sizeof(request),
43334c72144SAxel Dörfler 		&reply, sizeof(reply));
434a7b41a96Sbeveloper 
435a7b41a96Sbeveloper 	if (request.area != -1)
436a7b41a96Sbeveloper 		delete_area(request.area);
437a7b41a96Sbeveloper 
438a7b41a96Sbeveloper 	return rv;
4393620737cSbeveloper }
4403620737cSbeveloper 
44134c72144SAxel 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));
46134c72144SAxel Dörfler 		request.area = create_area("publish inputs", &start_addr,
46234c72144SAxel 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 
48034c72144SAxel Dörfler 	rv = QueryServer(SERVER_PUBLISH_INPUTS, &request, sizeof(request),
48134c72144SAxel Dörfler 		&reply, sizeof(reply));
482a7b41a96Sbeveloper 
483a7b41a96Sbeveloper 	if (request.area != -1)
484a7b41a96Sbeveloper 		delete_area(request.area);
485a7b41a96Sbeveloper 
486a7b41a96Sbeveloper 	return rv;
4873620737cSbeveloper }
4883620737cSbeveloper 
48934c72144SAxel Dörfler 
49034c72144SAxel Dörfler BTimeSource*
49134c72144SAxel Dörfler BMediaRosterEx::MakeTimeSourceObject(media_node_id timesourceID)
49234c72144SAxel Dörfler {
49334c72144SAxel Dörfler 	BTimeSource* source;
49434c72144SAxel Dörfler 	media_node clone;
49534c72144SAxel Dörfler 	status_t rv;
49634c72144SAxel Dörfler 
49734c72144SAxel Dörfler 	rv = GetNodeFor(timesourceID, &clone);
49834c72144SAxel Dörfler 	if (rv != B_OK) {
49934c72144SAxel Dörfler 		ERROR("BMediaRosterEx::MakeTimeSourceObject: GetNodeFor failed\n");
50034c72144SAxel Dörfler 		return NULL;
50134c72144SAxel Dörfler 	}
50234c72144SAxel Dörfler 
50334c72144SAxel Dörfler 	source = _TimeSourceObjectManager->GetTimeSource(clone);
50434c72144SAxel Dörfler 	if (source == NULL) {
50534c72144SAxel Dörfler 		ERROR("BMediaRosterEx::MakeTimeSourceObject: GetTimeSource failed\n");
50634c72144SAxel Dörfler 		return NULL;
50734c72144SAxel Dörfler 	}
50834c72144SAxel Dörfler 
50934c72144SAxel Dörfler 	// TODO: release?
51034c72144SAxel Dörfler 	ReleaseNode(clone);
51134c72144SAxel Dörfler 
51234c72144SAxel Dörfler 	return source;
51334c72144SAxel Dörfler }
51434c72144SAxel Dörfler 
51534c72144SAxel Dörfler 
51634c72144SAxel Dörfler //	#pragma mark - public BMediaRoster
51734c72144SAxel Dörfler 
51852a38012Sejakowatz 
51952a38012Sejakowatz status_t
52034c72144SAxel Dörfler BMediaRoster::GetVideoInput(media_node* _node)
52152a38012Sejakowatz {
52252a38012Sejakowatz 	CALLED();
52334c72144SAxel Dörfler 	return MediaRosterEx(this)->GetNode(VIDEO_INPUT, _node);
52452a38012Sejakowatz }
52552a38012Sejakowatz 
52652a38012Sejakowatz 
52752a38012Sejakowatz status_t
52834c72144SAxel Dörfler BMediaRoster::GetAudioInput(media_node* _node)
52952a38012Sejakowatz {
53052a38012Sejakowatz 	CALLED();
53134c72144SAxel Dörfler 	return MediaRosterEx(this)->GetNode(AUDIO_INPUT, _node);
53252a38012Sejakowatz }
53352a38012Sejakowatz 
53452a38012Sejakowatz 
53552a38012Sejakowatz status_t
53634c72144SAxel Dörfler BMediaRoster::GetVideoOutput(media_node* _node)
53752a38012Sejakowatz {
53852a38012Sejakowatz 	CALLED();
53934c72144SAxel Dörfler 	return MediaRosterEx(this)->GetNode(VIDEO_OUTPUT, _node);
54052a38012Sejakowatz }
54152a38012Sejakowatz 
54252a38012Sejakowatz 
54352a38012Sejakowatz status_t
54434c72144SAxel Dörfler BMediaRoster::GetAudioMixer(media_node* _node)
54552a38012Sejakowatz {
54652a38012Sejakowatz 	CALLED();
54734c72144SAxel Dörfler 	return MediaRosterEx(this)->GetNode(AUDIO_MIXER, _node);
54852a38012Sejakowatz }
54952a38012Sejakowatz 
55052a38012Sejakowatz 
55152a38012Sejakowatz status_t
55234c72144SAxel Dörfler BMediaRoster::GetAudioOutput(media_node* _node)
55352a38012Sejakowatz {
55452a38012Sejakowatz 	CALLED();
55534c72144SAxel Dörfler 	return MediaRosterEx(this)->GetNode(AUDIO_OUTPUT, _node);
55652a38012Sejakowatz }
55752a38012Sejakowatz 
55852a38012Sejakowatz 
55952a38012Sejakowatz status_t
56034c72144SAxel Dörfler BMediaRoster::GetAudioOutput(media_node* _node, int32* _inputID,
56134c72144SAxel Dörfler 	BString* _inputName)
56252a38012Sejakowatz {
56352a38012Sejakowatz 	CALLED();
56434c72144SAxel Dörfler 	return MediaRosterEx(this)->GetNode(AUDIO_OUTPUT_EX, _node, _inputID,
56534c72144SAxel Dörfler 		_inputName);
56652a38012Sejakowatz }
56752a38012Sejakowatz 
56852a38012Sejakowatz 
56952a38012Sejakowatz status_t
57034c72144SAxel Dörfler BMediaRoster::GetTimeSource(media_node* _node)
57152a38012Sejakowatz {
57252a38012Sejakowatz 	CALLED();
57386bce45bSbeveloper 	status_t rv;
57486bce45bSbeveloper 
57534c72144SAxel Dörfler 	// TODO: need to do this in a nicer way.
57686bce45bSbeveloper 
57734c72144SAxel 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.
58334c72144SAxel Dörfler 	ReleaseNode(*_node);
58486bce45bSbeveloper 
58586bce45bSbeveloper 	// we need to remember to not use this node with server side reference counting
58634c72144SAxel 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
64834c72144SAxel Dörfler BMediaRoster::SetAudioOutput(const media_input& input)
64952a38012Sejakowatz {
65052a38012Sejakowatz 	CALLED();
65134c72144SAxel 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
66434c72144SAxel 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 
67934c72144SAxel Dörfler 	rv = QueryServer(SERVER_GET_NODE_FOR, &request, sizeof(request), &reply,
68034c72144SAxel 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 
69534c72144SAxel 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 
70534c72144SAxel Dörfler 	// we need to remember to not use this node with server side reference
70634c72144SAxel 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) {
72134c72144SAxel Dörfler 		printf("BMediaRoster::ReleaseNode, trying to release reference "
72234c72144SAxel Dörfler 			"counting disabled timesource, node %ld, port %ld, team %ld\n",
72334c72144SAxel 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 
73434c72144SAxel Dörfler 	TRACE("BMediaRoster::ReleaseNode, node %ld, port %ld, team %ld\n",
73534c72144SAxel Dörfler 		node.node, node.port, team);
736cf4e2277Sbeveloper 
73734c72144SAxel Dörfler 	rv = QueryServer(SERVER_RELEASE_NODE, &request, sizeof(request), &reply,
73834c72144SAxel Dörfler 		sizeof(reply));
739cf4e2277Sbeveloper 	if (rv != B_OK) {
74034c72144SAxel Dörfler 		ERROR("BMediaRoster::ReleaseNode FAILED, node %ld, port %ld, team "
74134c72144SAxel Dörfler 			"%ld!\n", node.node, node.port, team);
742cf4e2277Sbeveloper 	}
743cf4e2277Sbeveloper 	return rv;
7449e9417d2Sbeveloper }
74552a38012Sejakowatz 
74634c72144SAxel Dörfler 
74752a38012Sejakowatz BTimeSource*
74834c72144SAxel 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 
75534c72144SAxel Dörfler 	if (IS_SYSTEM_TIMESOURCE(forNode)) {
756f180ef79Sbeveloper 		// special handling for the system time source
75734c72144SAxel Dörfler 		TRACE("BMediaRoster::MakeTimeSourceFor, asked for system time "
75834c72144SAxel Dörfler 			"source\n");
75934c72144SAxel Dörfler 		return MediaRosterEx(this)->MakeTimeSourceObject(
76034c72144SAxel Dörfler 			NODE_SYSTEM_TIMESOURCE_ID);
761f180ef79Sbeveloper 	}
762f180ef79Sbeveloper 
76334c72144SAxel Dörfler 	if (IS_INVALID_NODE(forNode)) {
76434c72144SAxel Dörfler 		ERROR("BMediaRoster::MakeTimeSourceFor: for_node invalid, node %ld, "
76534c72144SAxel Dörfler 			"port %ld, kinds 0x%lx\n", forNode.node, forNode.port,
76634c72144SAxel Dörfler 			forNode.kind);
7675917dd5bSbeveloper 		return NULL;
7680e21b167Sbeveloper 	}
7690e21b167Sbeveloper 
77034c72144SAxel 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
77834c72144SAxel Dörfler 	rv = QueryPort(forNode.port, NODE_GET_TIMESOURCE, &request,
77934c72144SAxel 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 
78734c72144SAxel Dörfler 	TRACE("BMediaRoster::MakeTimeSourceFor: node %ld leave\n", forNode.node);
788287f7492Sbeveloper 
789835140c8Sbeveloper 	return source;
79052a38012Sejakowatz }
79152a38012Sejakowatz 
79252a38012Sejakowatz 
79352a38012Sejakowatz status_t
79434c72144SAxel Dörfler BMediaRoster::Connect(const media_source& from, const media_destination& to,
79534c72144SAxel Dörfler 	media_format* _format, media_output* _output, media_input* _input)
79652a38012Sejakowatz {
79734c72144SAxel Dörfler 	return BMediaRoster::Connect(from, to, _format, _output, _input, 0);
798eae26d3dSbeveloper }
799eae26d3dSbeveloper 
800eae26d3dSbeveloper 
801eae26d3dSbeveloper status_t
80234c72144SAxel Dörfler BMediaRoster::Connect(const media_source& from, const media_destination& to,
80334c72144SAxel Dörfler 	media_format* io_format, media_output* out_output, media_input* out_input,
80434c72144SAxel 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
82134c72144SAxel 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) {
82634c72144SAxel Dörfler 		ERROR("BMediaRoster::Connect: Can't find source node for port %ld\n",
82734c72144SAxel 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) {
83334c72144SAxel Dörfler 		ERROR("BMediaRoster::Connect: Can't find destination node for port "
83434c72144SAxel 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)) {
84034c72144SAxel Dörfler 		ERROR("BMediaRoster::Connect: source node %ld is not a "
84134c72144SAxel 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)) {
84534c72144SAxel Dörfler 		ERROR("BMediaRoster::Connect: destination node %ld is not a "
84634c72144SAxel 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 
85334c72144SAxel Dörfler 	PRINT_FORMAT("BMediaRoster::Connect calling "
85434c72144SAxel Dörfler 		"BBufferProducer::FormatProposal with format  ", *io_format);
85569983609Sbeveloper 
85652a38012Sejakowatz 	// BBufferProducer::FormatProposal
8578c6a6096Sbeveloper 	request1.output = from;
8588c6a6096Sbeveloper 	request1.format = *io_format;
85934c72144SAxel Dörfler 	rv = QueryPort(from.port, PRODUCER_FORMAT_PROPOSAL, &request1,
86034c72144SAxel Dörfler 		sizeof(request1), &reply1, sizeof(reply1));
8618c6a6096Sbeveloper 	if (rv != B_OK) {
86234c72144SAxel Dörfler 		ERROR("BMediaRoster::Connect: aborted after "
86334c72144SAxel 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 
87134c72144SAxel Dörfler 	PRINT_FORMAT("BMediaRoster::Connect calling "
87234c72144SAxel Dörfler 		"BBufferConsumer::AcceptFormat with format    ", reply1.format);
87369983609Sbeveloper 
8748c6a6096Sbeveloper 	// BBufferConsumer::AcceptFormat
8758c6a6096Sbeveloper 	request2.dest = to;
8768c6a6096Sbeveloper 	request2.format = reply1.format;
87734c72144SAxel Dörfler 	rv = QueryPort(to.port, CONSUMER_ACCEPT_FORMAT, &request2,
87834c72144SAxel Dörfler 		sizeof(request2), &reply2, sizeof(reply2));
8798c6a6096Sbeveloper 	if (rv != B_OK) {
88034c72144SAxel Dörfler 		ERROR("BMediaRoster::Connect: aborted after "
88134c72144SAxel 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 
89034c72144SAxel Dörfler 	PRINT_FORMAT("BMediaRoster::Connect calling "
89134c72144SAxel Dörfler 		"BBufferProducer::PrepareToConnect with format", reply2.format);
89269983609Sbeveloper 
8938c6a6096Sbeveloper 	request3.source = from;
8948c6a6096Sbeveloper 	request3.destination = to;
8958c6a6096Sbeveloper 	request3.format = reply2.format;
89634c72144SAxel Dörfler 	strcpy(request3.name, "XXX some default name"); // TODO: fix this
89734c72144SAxel Dörfler 	rv = QueryPort(from.port, PRODUCER_PREPARE_TO_CONNECT, &request3,
89834c72144SAxel Dörfler 		sizeof(request3), &reply3, sizeof(reply3));
8998c6a6096Sbeveloper 	if (rv != B_OK) {
90034c72144SAxel Dörfler 		ERROR("BMediaRoster::Connect: aborted after "
90134c72144SAxel 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
90634c72144SAxel Dörfler 	// reply3.name the name BBufferConsumer::Connected will see in the
90734c72144SAxel 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 
91434c72144SAxel Dörfler 	PRINT_FORMAT("BMediaRoster::Connect calling BBufferConsumer::Connected() "
91534c72144SAxel 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 
92334c72144SAxel Dörfler 	con_status = QueryPort(to.port, CONSUMER_CONNECTED, &request4,
92434c72144SAxel Dörfler 		sizeof(request4), &reply4, sizeof(reply4));
9258c6a6096Sbeveloper 	if (con_status != B_OK) {
92634c72144SAxel Dörfler 		ERROR("BMediaRoster::Connect: aborting after "
92734c72144SAxel Dörfler 			"BBufferConsumer::Connected, status = %#lx\n",con_status);
9288c6a6096Sbeveloper 		// we do NOT return here!
9298c6a6096Sbeveloper 	}
93034c72144SAxel Dörfler 	// con_status contains the status code to be supplied to
93134c72144SAxel Dörfler 	// BBufferProducer::Connect's status argument
93234c72144SAxel Dörfler 	// reply4.input contains the media_input that describes the connection
93334c72144SAxel Dörfler 	// from the consumer point of view
9348c6a6096Sbeveloper 
9358c6a6096Sbeveloper 	// BBufferProducer::Connect
9368c6a6096Sbeveloper 	producer_connect_request request5;
9378c6a6096Sbeveloper 	producer_connect_reply reply5;
9388c6a6096Sbeveloper 
93934c72144SAxel Dörfler 	PRINT_FORMAT("BMediaRoster::Connect calling BBufferProducer::Connect with "
94034c72144SAxel 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);
94734c72144SAxel Dörfler 	rv = QueryPort(reply4.input.source.port, PRODUCER_CONNECT, &request5,
94834c72144SAxel 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) {
95434c72144SAxel Dörfler 		ERROR("BMediaRoster::Connect: aborted after BBufferProducer::Connect()"
95534c72144SAxel 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 
97534c72144SAxel Dörfler 	// TODO: register connection with server
97634c72144SAxel Dörfler 	// TODO: we should just send a notification, instead of republishing all
97734c72144SAxel Dörfler 	// endpoints
97876669a29Sbeveloper 	List<media_output> outlist;
97976669a29Sbeveloper 	List<media_input> inlist;
98034c72144SAxel Dörfler 	if (MediaRosterEx(this)->GetAllOutputs(out_output->node , &outlist) == B_OK)
9818b04ffc1Sbeveloper 		MediaRosterEx(this)->PublishOutputs(out_output->node , &outlist);
98234c72144SAxel Dörfler 	if (MediaRosterEx(this)->GetAllInputs(out_input->node , &inlist) == B_OK)
9838b04ffc1Sbeveloper 		MediaRosterEx(this)->PublishInputs(out_input->node, &inlist);
9848c6a6096Sbeveloper 
98534c72144SAxel Dörfler 	// TODO: if (mute) BBufferProducer::EnableOutput(false)
9869e9417d2Sbeveloper 	if (in_flags & B_CONNECT_MUTED) {
9879e9417d2Sbeveloper 	}
9888c6a6096Sbeveloper 
9899e9417d2Sbeveloper 	// send a notification
99034c72144SAxel Dörfler 	BPrivate::media::notifications::ConnectionMade(*out_input, *out_output,
99134c72144SAxel Dörfler 		*io_format);
9929e9417d2Sbeveloper 
9938c6a6096Sbeveloper 	return B_OK;
9948c6a6096Sbeveloper };
99552a38012Sejakowatz 
99652a38012Sejakowatz 
99752a38012Sejakowatz status_t
9989e9417d2Sbeveloper BMediaRoster::Disconnect(media_node_id source_nodeid,
99934c72144SAxel 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 
102634c72144SAxel 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 
103334c72144SAxel Dörfler 	rv1 = QueryPort(source.port, PRODUCER_DISCONNECT, &request1,
103434c72144SAxel Dörfler 		sizeof(request1), &reply1, sizeof(reply1));
103534c72144SAxel Dörfler 	rv2 = QueryPort(destination.port, CONSUMER_DISCONNECTED, &request2,
103634c72144SAxel Dörfler 		sizeof(request2), &reply2, sizeof(reply2));
10379e9417d2Sbeveloper 
103834c72144SAxel Dörfler 	// TODO: unregister connection with server
103934c72144SAxel Dörfler 	// TODO: we should just send a notification, instead of republishing all
104034c72144SAxel Dörfler 	// endpoints
104176669a29Sbeveloper 	List<media_output> outlist;
104276669a29Sbeveloper 	List<media_input> inlist;
10439e9417d2Sbeveloper 	media_node sourcenode;
10449e9417d2Sbeveloper 	media_node destnode;
104534c72144SAxel Dörfler 	if (GetNodeFor(source_nodeid, &sourcenode) == B_OK) {
104665b73ae4SMarcus Overhagen 		if (!(sourcenode.kind & B_BUFFER_PRODUCER)) {
104734c72144SAxel Dörfler 			ERROR("BMediaRoster::Disconnect: source_nodeid %ld is not a "
104834c72144SAxel Dörfler 				"B_BUFFER_PRODUCER\n", source_nodeid);
104965b73ae4SMarcus Overhagen 		}
105034c72144SAxel 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 	}
105634c72144SAxel Dörfler 	if (GetNodeFor(destination_nodeid, &destnode) == B_OK) {
105765b73ae4SMarcus Overhagen 		if (!(destnode.kind & B_BUFFER_CONSUMER)) {
105834c72144SAxel Dörfler 			ERROR("BMediaRoster::Disconnect: destination_nodeid %ld is not a "
105934c72144SAxel Dörfler 				"B_BUFFER_CONSUMER\n", destination_nodeid);
106065b73ae4SMarcus Overhagen 		}
106134c72144SAxel Dörfler 		if (MediaRosterEx(this)->GetAllInputs(destnode , &inlist) == B_OK)
10628b04ffc1Sbeveloper 			MediaRosterEx(this)->PublishInputs(destnode, &inlist);
10639e9417d2Sbeveloper 		ReleaseNode(destnode);
10644f09fa2fSbeveloper 	} else {
106534c72144SAxel Dörfler 		ERROR("BMediaRoster::Disconnect: GetNodeFor destination_nodeid %ld "
106634c72144SAxel Dörfler 			"failed\n", destination_nodeid);
10674f09fa2fSbeveloper 	}
10689e9417d2Sbeveloper 
10699e9417d2Sbeveloper 	// send a notification
10709e9417d2Sbeveloper 	BPrivate::media::notifications::ConnectionBroken(source, destination);
10719e9417d2Sbeveloper 
107234c72144SAxel Dörfler 	return rv1 != B_OK || rv2 != B_OK ? B_ERROR : B_OK;
107352a38012Sejakowatz }
107452a38012Sejakowatz 
107534c72144SAxel 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)) {
109034c72144SAxel Dörfler 		printf("BMediaRoster::Disconnect: output.node.kind 0x%lx is no "
109134c72144SAxel 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)) {
109534c72144SAxel Dörfler 		printf("BMediaRoster::Disconnect: input.node.kind 0x%lx is no "
109634c72144SAxel 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) {
110034c72144SAxel Dörfler 		printf("BMediaRoster::Disconnect: input.source.port %ld doesn't match "
110134c72144SAxel 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) {
110534c72144SAxel Dörfler 		printf("BMediaRoster::Disconnect: input.source.id %ld doesn't match "
110634c72144SAxel 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) {
111034c72144SAxel Dörfler 		printf("BMediaRoster::Disconnect: input.destination.port %ld doesn't "
111134c72144SAxel Dörfler 			"match output.destination.port %ld\n", input.destination.port,
111234c72144SAxel Dörfler 			output.destination.port);
111365b73ae4SMarcus Overhagen 		return B_MEDIA_BAD_DESTINATION;
111465b73ae4SMarcus Overhagen 	}
111565b73ae4SMarcus Overhagen 	if (input.destination.id != output.destination.id) {
111634c72144SAxel Dörfler 		printf("BMediaRoster::Disconnect: input.destination.id %ld doesn't "
111734c72144SAxel Dörfler 			"match output.destination.id %ld\n", input.destination.id,
111834c72144SAxel Dörfler 			output.destination.id);
111965b73ae4SMarcus Overhagen 		return B_MEDIA_BAD_DESTINATION;
112065b73ae4SMarcus Overhagen 	}
112134c72144SAxel Dörfler 
112234c72144SAxel Dörfler 	return Disconnect(output.node.node, output.source, input.node.node,
112334c72144SAxel Dörfler 		input.destination);
112465b73ae4SMarcus Overhagen }
112565b73ae4SMarcus Overhagen 
112652a38012Sejakowatz 
112752a38012Sejakowatz status_t
112834c72144SAxel 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 
113434c72144SAxel Dörfler 	TRACE("BMediaRoster::StartNode, node %ld, at perf %Ld\n", node.node,
113534c72144SAxel Dörfler 		atPerformanceTime);
11360e21b167Sbeveloper 
11376396865dSbeveloper 	node_start_command command;
113834c72144SAxel Dörfler 	command.performance_time = atPerformanceTime;
113952a38012Sejakowatz 
11406396865dSbeveloper 	return SendToPort(node.port, NODE_START, &command, sizeof(command));
114152a38012Sejakowatz }
114252a38012Sejakowatz 
114352a38012Sejakowatz 
114452a38012Sejakowatz status_t
114534c72144SAxel 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 
115234c72144SAxel Dörfler 	TRACE("BMediaRoster::StopNode, node %ld, at perf %Ld %s\n", node.node,
115334c72144SAxel Dörfler 		atPerformanceTime, immediate ? "NOW" : "");
11540e21b167Sbeveloper 
11556396865dSbeveloper 	node_stop_command command;
115634c72144SAxel 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
116434c72144SAxel Dörfler BMediaRoster::SeekNode(const media_node& node, bigtime_t toMediaTime,
116534c72144SAxel Dörfler 	bigtime_t atPerformanceTime)
116652a38012Sejakowatz {
116752a38012Sejakowatz 	CALLED();
116840f36b03Sbeveloper 	if (IS_INVALID_NODE(node))
116952a38012Sejakowatz 		return B_MEDIA_BAD_NODE;
117052a38012Sejakowatz 
117134c72144SAxel Dörfler 	TRACE("BMediaRoster::SeekNode, node %ld, at perf %Ld, to perf %Ld\n",
117234c72144SAxel Dörfler 		node.node, atPerformanceTime, toMediaTime);
11730e21b167Sbeveloper 
11746396865dSbeveloper 	node_seek_command command;
117534c72144SAxel Dörfler 	command.media_time = toMediaTime;
117634c72144SAxel Dörfler 	command.performance_time = atPerformanceTime;
117752a38012Sejakowatz 
11786396865dSbeveloper 	return SendToPort(node.port, NODE_SEEK, &command, sizeof(command));
117952a38012Sejakowatz }
118052a38012Sejakowatz 
118152a38012Sejakowatz 
118252a38012Sejakowatz status_t
118334c72144SAxel Dörfler BMediaRoster::StartTimeSource(const media_node& node, bigtime_t atRealTime)
118452a38012Sejakowatz {
118552a38012Sejakowatz 	CALLED();
118660f15390Sbeveloper 	if (IS_SYSTEM_TIMESOURCE(node)) {
118734c72144SAxel 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)) {
119234c72144SAxel 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) {
120134c72144SAxel Dörfler 		ERROR("BMediaRoster::StartTimeSource node %ld is no timesource\n",
120234c72144SAxel Dörfler 			node.node);
120352a38012Sejakowatz 		return B_MEDIA_BAD_NODE;
12040e21b167Sbeveloper 	}
12050e21b167Sbeveloper 
120634c72144SAxel Dörfler 	TRACE("BMediaRoster::StartTimeSource, node %ld, at real %Ld\n", node.node,
120734c72144SAxel Dörfler 		at_real_time);
120852a38012Sejakowatz 
120952a38012Sejakowatz 	BTimeSource::time_source_op_info msg;
121052a38012Sejakowatz 	msg.op = BTimeSource::B_TIMESOURCE_START;
121134c72144SAxel Dörfler 	msg.real_time = atRealTime;
121252a38012Sejakowatz 
121352a38012Sejakowatz 	return write_port(node.port, TIMESOURCE_OP, &msg, sizeof(msg));
121452a38012Sejakowatz }
121552a38012Sejakowatz 
121652a38012Sejakowatz 
121752a38012Sejakowatz status_t
121834c72144SAxel Dörfler BMediaRoster::StopTimeSource(const media_node& node, bigtime_t atRealTime,
121952a38012Sejakowatz 	bool immediate)
122052a38012Sejakowatz {
122152a38012Sejakowatz 	CALLED();
122260f15390Sbeveloper 	if (IS_SYSTEM_TIMESOURCE(node)) {
122334c72144SAxel 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)) {
122834c72144SAxel 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) {
123734c72144SAxel Dörfler 		ERROR("BMediaRoster::StopTimeSource node %ld is no timesource\n",
123834c72144SAxel Dörfler 			node.node);
123952a38012Sejakowatz 		return B_MEDIA_BAD_NODE;
12400e21b167Sbeveloper 	}
12410e21b167Sbeveloper 
124234c72144SAxel Dörfler 	TRACE("BMediaRoster::StopTimeSource, node %ld, at real %Ld %s\n",
124334c72144SAxel Dörfler 		node.node, atRealTime, immediate ? "NOW" : "");
124452a38012Sejakowatz 
124552a38012Sejakowatz 	BTimeSource::time_source_op_info msg;
124634c72144SAxel Dörfler 	msg.op = immediate ? BTimeSource::B_TIMESOURCE_STOP_IMMEDIATELY
124734c72144SAxel Dörfler 		: BTimeSource::B_TIMESOURCE_STOP;
124834c72144SAxel 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,
125634c72144SAxel Dörfler 	bigtime_t toPerformanceTime, bigtime_t atRealTime)
125752a38012Sejakowatz {
125852a38012Sejakowatz 	CALLED();
125960f15390Sbeveloper 	if (IS_SYSTEM_TIMESOURCE(node)) {
126034c72144SAxel 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)) {
126734c72144SAxel 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) {
127634c72144SAxel Dörfler 		ERROR("BMediaRoster::SeekTimeSource node %ld is no timesource\n",
127734c72144SAxel Dörfler 			node.node);
127852a38012Sejakowatz 		return B_MEDIA_BAD_NODE;
12790e21b167Sbeveloper 	}
12800e21b167Sbeveloper 
128134c72144SAxel Dörfler 	TRACE("BMediaRoster::SeekTimeSource, node %ld, at real %Ld, to perf %Ld\n",
128234c72144SAxel Dörfler 		node.node, atRealTime, toPerformanceTime);
128352a38012Sejakowatz 
128452a38012Sejakowatz 	BTimeSource::time_source_op_info msg;
128552a38012Sejakowatz 	msg.op = BTimeSource::B_TIMESOURCE_SEEK;
128634c72144SAxel Dörfler 	msg.real_time = atRealTime;
128734c72144SAxel Dörfler 	msg.performance_time = toPerformanceTime;
128852a38012Sejakowatz 
128952a38012Sejakowatz 	return write_port(node.port, TIMESOURCE_OP, &msg, sizeof(msg));
129052a38012Sejakowatz }
129152a38012Sejakowatz 
129252a38012Sejakowatz 
129352a38012Sejakowatz status_t
129434c72144SAxel 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
130334c72144SAxel 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
132934c72144SAxel Dörfler BMediaRoster::RollNode(const media_node& node, bigtime_t startPerformance,
133034c72144SAxel 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,
133934c72144SAxel Dörfler 	bigtime_t delay, BMediaNode::run_mode mode)
134052a38012Sejakowatz {
134134c72144SAxel Dörfler 	TRACE("BMediaRoster::SetProducerRunModeDelay, node %ld, delay %Ld, "
134234c72144SAxel 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 
135234c72144SAxel Dörfler 	return SendToPort(node.port, PRODUCER_SET_RUN_MODE_DELAY, &command,
135334c72144SAxel Dörfler 		sizeof(command));
135452a38012Sejakowatz }
135552a38012Sejakowatz 
135652a38012Sejakowatz 
135752a38012Sejakowatz status_t
135834c72144SAxel 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 
138634c72144SAxel Dörfler /*!	Nodes will have available inputs/outputs as long as they are capable
138734c72144SAxel Dörfler 	of accepting more connections. The node may create an additional
138834c72144SAxel Dörfler 	output or input as the currently available is taken into usage.
138934c72144SAxel 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 
140634c72144SAxel Dörfler 	rv = QueryServer(SERVER_GET_LIVE_NODE_INFO, &request, sizeof(request),
140734c72144SAxel 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
141734c72144SAxel Dörfler BMediaRoster::GetLiveNodes(live_node_info* _liveNodes, int32* _totalCount,
141834c72144SAxel Dörfler 	const media_format* hasInput, const media_format* hasOutput,
141934c72144SAxel Dörfler 	const char* name, uint64 nodeKinds)
142052a38012Sejakowatz {
14219e9417d2Sbeveloper 	CALLED();
142234c72144SAxel Dörfler 	if (_liveNodes == NULL || _totalCount == NULL || *_totalCount <= 0)
14239e9417d2Sbeveloper 		return B_BAD_VALUE;
14249e9417d2Sbeveloper 
142534c72144SAxel Dörfler 	// TODO: we also support the wildcard search as GetDormantNodes does.
142634c72144SAxel 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 
143234c72144SAxel Dörfler 	request.maxcount = *_totalCount;
143334c72144SAxel Dörfler 	request.has_input = hasInput != NULL;
143434c72144SAxel Dörfler 	if (hasInput != NULL) {
143534c72144SAxel Dörfler 		// TODO: we should not make a flat copy of media_format
143634c72144SAxel Dörfler 		request.inputformat = *hasInput;
143734c72144SAxel Dörfler 	}
143834c72144SAxel Dörfler 	request.has_output = hasOutput != NULL;
143934c72144SAxel Dörfler 	if (hasOutput != NULL) {
144034c72144SAxel Dörfler 		// TODO: we should not make a flat copy of media_format
144134c72144SAxel Dörfler 		request.outputformat = *hasOutput;
144234c72144SAxel Dörfler 	}
144334c72144SAxel Dörfler 	request.has_name = name != NULL;
144434c72144SAxel 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 	}
145034c72144SAxel Dörfler 	request.require_kinds = nodeKinds;
14519e9417d2Sbeveloper 
145234c72144SAxel Dörfler 	rv = QueryServer(SERVER_GET_LIVE_NODES, &request, sizeof(request),
145334c72144SAxel Dörfler 		&reply, sizeof(reply));
14549e9417d2Sbeveloper 	if (rv != B_OK) {
14555ac4fbd7Sbeveloper 		ERROR("BMediaRoster::GetLiveNodes failed querying server\n");
145634c72144SAxel Dörfler 		*_totalCount = 0;
14579e9417d2Sbeveloper 		return rv;
14589e9417d2Sbeveloper 	}
14599e9417d2Sbeveloper 
14609e9417d2Sbeveloper 	if (reply.count > MAX_LIVE_INFO) {
146134c72144SAxel Dörfler 		live_node_info* liveInfo;
14629e9417d2Sbeveloper 		area_id clone;
14639e9417d2Sbeveloper 
146434c72144SAxel Dörfler 		clone = clone_area("live_node_info clone",
146534c72144SAxel Dörfler 			reinterpret_cast<void **>(&liveInfo), B_ANY_ADDRESS,
146634c72144SAxel Dörfler 			B_READ_AREA | B_WRITE_AREA, reply.area);
14679e9417d2Sbeveloper 		if (clone < B_OK) {
146834c72144SAxel Dörfler 			ERROR("BMediaRoster::GetLiveNodes failed to clone area, %#lx\n",
146934c72144SAxel Dörfler 				clone);
14709e9417d2Sbeveloper 			delete_area(reply.area);
147134c72144SAxel Dörfler 			*_totalCount = 0;
147252a38012Sejakowatz 			return B_ERROR;
147352a38012Sejakowatz 		}
147452a38012Sejakowatz 
14759e9417d2Sbeveloper 		for (int32 i = 0; i < reply.count; i++) {
147634c72144SAxel 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++) {
148334c72144SAxel Dörfler 			_liveNodes[i] = reply.live_info[i];
14849e9417d2Sbeveloper 		}
14859e9417d2Sbeveloper 	}
148634c72144SAxel Dörfler 	*_totalCount = reply.count;
14879e9417d2Sbeveloper 
14889e9417d2Sbeveloper 	return B_OK;
14899e9417d2Sbeveloper }
14909e9417d2Sbeveloper 
149152a38012Sejakowatz 
149252a38012Sejakowatz status_t
149352a38012Sejakowatz BMediaRoster::GetFreeInputsFor(const media_node& node,
149434c72144SAxel Dörfler 	media_input * out_free_inputs, int32 buf_num_inputs,
149534c72144SAxel Dörfler 	int32 * out_total_count, media_type filter_type)
149652a38012Sejakowatz {
14973620737cSbeveloper 	CALLED();
14985ac4fbd7Sbeveloper 	if (IS_INVALID_NODE(node)) {
149934c72144SAxel Dörfler 		ERROR("BMediaRoster::GetFreeInputsFor: node %ld, port %ld invalid\n",
150034c72144SAxel Dörfler 			node.node, node.port);
15013620737cSbeveloper 		return B_MEDIA_BAD_NODE;
15025ac4fbd7Sbeveloper 	}
15035ac4fbd7Sbeveloper 	if ((node.kind & B_BUFFER_CONSUMER) == 0) {
150434c72144SAxel Dörfler 		ERROR("BMediaRoster::GetFreeInputsFor: node %ld, port %ld is not a "
150534c72144SAxel 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 
152134c72144SAxel Dörfler 	PRINT(4, "BMediaRoster::GetFreeInputsFor node %ld, max %ld, filter-type "
152234c72144SAxel 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);) {
152634c72144SAxel Dörfler 		if (filter_type != B_MEDIA_UNKNOWN_TYPE
152734c72144SAxel Dörfler 			&& filter_type != input->format.type) {
152834c72144SAxel Dörfler 			// media_type used, but doesn't match
152934c72144SAxel Dörfler 			continue;
153034c72144SAxel Dörfler 		}
153134c72144SAxel Dörfler 		if (input->source != media_source::null) {
153234c72144SAxel Dörfler 			// consumer source already connected
153334c72144SAxel Dörfler 			continue;
153434c72144SAxel Dörfler 		}
153534c72144SAxel 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,
155434c72144SAxel 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 
157334c72144SAxel Dörfler 	PRINT(4, "BMediaRoster::GetConnectedInputsFor node %ld, max %ld\n",
157434c72144SAxel 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
159734c72144SAxel Dörfler BMediaRoster::GetAllInputsFor(const media_node& node, media_input* out_inputs,
159834c72144SAxel 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 
161634c72144SAxel Dörfler 	PRINT(4, "BMediaRoster::GetAllInputsFor node %ld, max %ld\n", node.node,
161734c72144SAxel 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,
163834c72144SAxel Dörfler 	media_output* out_free_outputs, int32 buf_num_outputs,
163934c72144SAxel 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 
165734c72144SAxel Dörfler 	PRINT(4, "BMediaRoster::GetFreeOutputsFor node %ld, max %ld, filter-type "
165834c72144SAxel 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);) {
166234c72144SAxel Dörfler 		if (filter_type != B_MEDIA_UNKNOWN_TYPE
166334c72144SAxel Dörfler 			&& filter_type != output->format.type) {
166434c72144SAxel Dörfler 			// media_type used, but doesn't match
166534c72144SAxel Dörfler 			continue;
166634c72144SAxel Dörfler 		}
166734c72144SAxel Dörfler 		if (output->destination != media_destination::null) {
166834c72144SAxel Dörfler 			// producer destination already connected
166934c72144SAxel Dörfler 			continue;
167034c72144SAxel Dörfler 		}
167134c72144SAxel 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,
169034c72144SAxel 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 
170934c72144SAxel Dörfler 	PRINT(4, "BMediaRoster::GetConnectedOutputsFor node %ld, max %ld\n",
171034c72144SAxel Dörfler 		node.node, buf_num_outputs);
17115ac4fbd7Sbeveloper 
171276669a29Sbeveloper 	int32 i;
1713b65a0ac5SJérôme Duval 	for (i = 0, list.Rewind(); list.GetNext(&output);) {
171434c72144SAxel Dörfler 		if (output->destination == media_destination::null) {
171534c72144SAxel Dörfler 			// producer destination not connected
171634c72144SAxel Dörfler 			continue;
171734c72144SAxel 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,
173634c72144SAxel 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 
175434c72144SAxel Dörfler 	PRINT(4, "BMediaRoster::GetAllOutputsFor node %ld, max %ld\n", node.node,
175534c72144SAxel 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 	}
178234c72144SAxel Dörfler 	return BPrivate::media::notifications::Register(where, media_node::null,
178334c72144SAxel Dörfler 		B_MEDIA_WILDCARD);
178452a38012Sejakowatz }
178552a38012Sejakowatz 
178652a38012Sejakowatz 
178752a38012Sejakowatz status_t
178834c72144SAxel 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 	}
179534c72144SAxel Dörfler 	if (!BPrivate::media::notifications::IsValidNotificationRequest(false,
179634c72144SAxel Dörfler 			notificationType)) {
17975ac4fbd7Sbeveloper 		ERROR("BMediaRoster::StartWatching: notificationType invalid!\n");
1798eae26d3dSbeveloper 		return B_BAD_VALUE;
1799eae26d3dSbeveloper 	}
180034c72144SAxel Dörfler 	return BPrivate::media::notifications::Register(where, media_node::null,
180134c72144SAxel Dörfler 		notificationType);
180252a38012Sejakowatz }
180352a38012Sejakowatz 
180452a38012Sejakowatz 
180552a38012Sejakowatz status_t
180634c72144SAxel 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 	}
181834c72144SAxel Dörfler 	if (!BPrivate::media::notifications::IsValidNotificationRequest(true,
181934c72144SAxel Dörfler 			notificationType)) {
18205ac4fbd7Sbeveloper 		ERROR("BMediaRoster::StartWatching: notificationType invalid!\n");
1821eae26d3dSbeveloper 		return B_BAD_VALUE;
1822eae26d3dSbeveloper 	}
182334c72144SAxel Dörfler 	return BPrivate::media::notifications::Register(where, node,
182434c72144SAxel 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
183334c72144SAxel Dörfler 	return BPrivate::media::notifications::Unregister(where, media_node::null,
183434c72144SAxel Dörfler 		B_MEDIA_WILDCARD);
183552a38012Sejakowatz }
183652a38012Sejakowatz 
183752a38012Sejakowatz 
183852a38012Sejakowatz status_t
183934c72144SAxel Dörfler BMediaRoster::StopWatching(const BMessenger& where, int32 notificationType)
184052a38012Sejakowatz {
1841eae26d3dSbeveloper 	CALLED();
1842eae26d3dSbeveloper 	// messenger may already be invalid, so we don't check this
184334c72144SAxel Dörfler 	if (!BPrivate::media::notifications::IsValidNotificationRequest(false,
184434c72144SAxel Dörfler 			notificationType)) {
18455ac4fbd7Sbeveloper 		ERROR("BMediaRoster::StopWatching: notificationType invalid!\n");
1846eae26d3dSbeveloper 		return B_BAD_VALUE;
1847eae26d3dSbeveloper 	}
184834c72144SAxel Dörfler 	return BPrivate::media::notifications::Unregister(where, media_node::null,
184934c72144SAxel Dörfler 		notificationType);
185052a38012Sejakowatz }
185152a38012Sejakowatz 
185252a38012Sejakowatz 
185352a38012Sejakowatz status_t
185434c72144SAxel 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 	}
186334c72144SAxel Dörfler 	if (!BPrivate::media::notifications::IsValidNotificationRequest(true,
186434c72144SAxel Dörfler 			notificationType)) {
18655ac4fbd7Sbeveloper 		ERROR("BMediaRoster::StopWatching: notificationType invalid!\n");
1866eae26d3dSbeveloper 		return B_BAD_VALUE;
1867eae26d3dSbeveloper 	}
186834c72144SAxel Dörfler 	return BPrivate::media::notifications::Unregister(where, node,
186934c72144SAxel 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
188334c72144SAxel Dörfler BMediaRosterEx::RegisterNode(BMediaNode* node, media_addon_id addonid,
188434c72144SAxel 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 
191534c72144SAxel Dörfler 	TRACE("BMediaRoster::RegisterNode: sending SERVER_REGISTER_NODE: port "
191634c72144SAxel Dörfler 		"%ld, kinds 0x%Lx, team %ld, name '%s'\n", request.port, request.kinds,
191734c72144SAxel Dörfler 		request.team, request.name);
19181299bfb2Sbeveloper 
191934c72144SAxel Dörfler 	rv = QueryServer(SERVER_REGISTER_NODE, &request, sizeof(request), &reply,
192034c72144SAxel Dörfler 		sizeof(reply));
19219e9417d2Sbeveloper 	if (rv != B_OK) {
192234c72144SAxel Dörfler 		ERROR("BMediaRoster::RegisterNode: failed to register node %s (error "
192334c72144SAxel Dörfler 			"%#lx)\n", node->Name(), rv);
19249e9417d2Sbeveloper 		return rv;
19259e9417d2Sbeveloper 	}
19269e9417d2Sbeveloper 
192734c72144SAxel Dörfler 	TRACE("BMediaRoster::RegisterNode: QueryServer SERVER_REGISTER_NODE "
192834c72144SAxel 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 
194034c72144SAxel Dörfler 	// if the BMediaNode also inherits from BTimeSource, we need to call
194134c72144SAxel 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) {
200634c72144SAxel Dörfler 		TRACE("BMediaRoster::UnregisterNode, trying to unregister reference "
200734c72144SAxel Dörfler 			"counting disabled timesource, node %ld, port %ld, team %ld\n",
200834c72144SAxel Dörfler 			node->ID(), node->ControlPort(), team);
200986bce45bSbeveloper 		return B_OK;
201086bce45bSbeveloper 	}
20118b04ffc1Sbeveloper 	if (node->ID() == NODE_UNREGISTERED_ID) {
201234c72144SAxel Dörfler 		PRINT(1, "Warning: BMediaRoster::UnregisterNode: node id %ld, name "
201334c72144SAxel Dörfler 			"'%s' already unregistered\n", node->ID(), node->Name());
20149e9417d2Sbeveloper 		return B_OK;
20159e9417d2Sbeveloper 	}
201654187cc6Sbeveloper 	if (node->fRefCount != 0) {
201734c72144SAxel Dörfler 		PRINT(1, "Warning: BMediaRoster::UnregisterNode: node id %ld, name "
201834c72144SAxel Dörfler 			"'%s' has local reference count of %ld\n", node->ID(), node->Name(),
201934c72144SAxel Dörfler 			node->fRefCount);
202054187cc6Sbeveloper 		// no return here, we continue and unregister!
202154187cc6Sbeveloper 	}
202254187cc6Sbeveloper 
202334c72144SAxel Dörfler 	// Calling BMediaAddOn::GetConfigurationFor(BMediaNode *node,
202434c72144SAxel Dörfler 	// BMessage *config) if this node was instanciated by an add-on needs to
202534c72144SAxel 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 
203934c72144SAxel Dörfler 	rv = QueryServer(SERVER_UNREGISTER_NODE, &request, sizeof(request), &reply,
204034c72144SAxel Dörfler 		sizeof(reply));
20419e9417d2Sbeveloper 	if (rv != B_OK) {
204234c72144SAxel Dörfler 		ERROR("BMediaRoster::UnregisterNode: failed to unregister node id %ld, "
204334c72144SAxel 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
204934c72144SAxel Dörfler 		// UnregisterNode() is called by a dormant node itself (by the
205034c72144SAxel 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 
205634c72144SAxel Dörfler 		rv = MediaRosterEx(this)->DecrementAddonFlavorInstancesCount(
205734c72144SAxel Dörfler 			reply.addonid, reply.flavorid);
205854187cc6Sbeveloper 		if (rv != B_OK) {
205934c72144SAxel Dörfler 			ERROR("BMediaRoster::UnregisterNode: "
206034c72144SAxel 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 
207234c72144SAxel 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
210834c72144SAxel 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 
211734c72144SAxel Dörfler 	TRACE("BMediaRoster::SetTimeSourceFor: node %ld will be assigned time "
211834c72144SAxel Dörfler 		"source %ld\n", node, time_source);
211934c72144SAxel Dörfler 	TRACE("BMediaRoster::SetTimeSourceFor: node %ld time source %ld enter\n",
212034c72144SAxel 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) {
212534c72144SAxel Dörfler 		ERROR("BMediaRoster::SetTimeSourceFor, GetNodeFor failed, node id "
212634c72144SAxel 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) {
213734c72144SAxel Dörfler 		ERROR("BMediaRoster::SetTimeSourceFor, sending NODE_SET_TIMESOURCE "
213834c72144SAxel 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) {
214534c72144SAxel Dörfler 		ERROR("BMediaRoster::SetTimeSourceFor, ReleaseNode failed, node id "
214634c72144SAxel Dörfler 			"%ld\n", node);
2147aac800c2Sbeveloper 		result = B_ERROR;
2148aac800c2Sbeveloper 	}
2149aac800c2Sbeveloper 
215034c72144SAxel Dörfler 	TRACE("BMediaRoster::SetTimeSourceFor: node %ld time source %ld leave\n",
215134c72144SAxel Dörfler 		node, time_source);
21525917dd5bSbeveloper 
2153aac800c2Sbeveloper 	return result;
2154aac800c2Sbeveloper }
2155aac800c2Sbeveloper 
215652a38012Sejakowatz 
215752a38012Sejakowatz status_t
215834c72144SAxel Dörfler BMediaRoster::GetParameterWebFor(const media_node& node, BParameterWeb** _web)
215952a38012Sejakowatz {
216028ad138aSbeveloper 	CALLED();
216134c72144SAxel 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;
217034c72144SAxel Dörfler 	int32 requestsize[] = {B_PAGE_SIZE, 4 * B_PAGE_SIZE, 16 * B_PAGE_SIZE,
217134c72144SAxel Dörfler 		64 * B_PAGE_SIZE, 128 * B_PAGE_SIZE, 256 * B_PAGE_SIZE, 0};
217228ad138aSbeveloper 	int32 size;
217328ad138aSbeveloper 
217434c72144SAxel Dörfler 	// TODO: it might be better to query the node for the (current) parameter
217534c72144SAxel 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;
218034c72144SAxel Dörfler 		area = create_area("parameter web data", &data, B_ANY_ADDRESS, size,
218134c72144SAxel Dörfler 			B_NO_LOCK, B_READ_AREA | B_WRITE_AREA);
218228ad138aSbeveloper 		if (area < B_OK) {
218334c72144SAxel Dörfler 			ERROR("BMediaRoster::GetParameterWebFor couldn't create area of "
218434c72144SAxel Dörfler 				"size %ld\n", size);
218528ad138aSbeveloper 			return B_ERROR;
218628ad138aSbeveloper 		}
218734c72144SAxel Dörfler 		request.max_size = size;
218828ad138aSbeveloper 		request.area = area;
218934c72144SAxel Dörfler 		rv = QueryPort(node.port, CONTROLLABLE_GET_PARAMETER_WEB, &request,
219034c72144SAxel Dörfler 			sizeof(request), &reply, sizeof(reply));
219128ad138aSbeveloper 		if (rv != B_OK) {
219234c72144SAxel Dörfler 			ERROR("BMediaRoster::GetParameterWebFor "
219334c72144SAxel 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
219934c72144SAxel Dörfler 			// TODO: should we return an error?
220034c72144SAxel Dörfler 			ERROR("BMediaRoster::GetParameterWebFor node %ld has no parameter "
220134c72144SAxel Dörfler 				"web\n", node.node);
220234c72144SAxel Dörfler 			*_web = new (std::nothrow) BParameterWeb();
220328ad138aSbeveloper 			delete_area(area);
220434c72144SAxel Dörfler 			return *_web != NULL ? B_OK : B_NO_MEMORY;
220552a38012Sejakowatz 		}
220628ad138aSbeveloper 		if (reply.size > 0) {
220728ad138aSbeveloper 			// we got a flattened parameter web!
220834c72144SAxel Dörfler 			*_web = new (std::nothrow) BParameterWeb();
220934c72144SAxel Dörfler 			if (*_web == NULL)
2210a715f908SStephan Aßmus 				rv = B_NO_MEMORY;
2211a715f908SStephan Aßmus 			else {
221234c72144SAxel Dörfler 				printf("BMediaRoster::GetParameterWebFor Unflattening %ld "
221334c72144SAxel Dörfler 					"bytes, 0x%08lx, 0x%08lx, 0x%08lx, 0x%08lx\n",
221434c72144SAxel Dörfler 					reply.size, ((uint32*)data)[0], ((uint32*)data)[1],
221534c72144SAxel Dörfler 					((uint32*)data)[2], ((uint32*)data)[3]);
221628ad138aSbeveloper 
221734c72144SAxel Dörfler 				rv = (*_web)->Unflatten(reply.code, data, reply.size);
2218a715f908SStephan Aßmus 			}
221928ad138aSbeveloper 			if (rv != B_OK) {
222034c72144SAxel Dörfler 				ERROR("BMediaRoster::GetParameterWebFor Unflatten failed, "
222134c72144SAxel Dörfler 					"%s\n", strerror(rv));
222234c72144SAxel 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 	}
223234c72144SAxel Dörfler 	ERROR("BMediaRoster::GetParameterWebFor node %ld has no parameter web "
223334c72144SAxel Dörfler 		"larger than %ld\n", node.node, size);
223428ad138aSbeveloper 	return B_ERROR;
223528ad138aSbeveloper }
223652a38012Sejakowatz 
223752a38012Sejakowatz 
223852a38012Sejakowatz status_t
223934c72144SAxel 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;
224934c72144SAxel Dörfler 	rv = QueryPort(node.port, CONTROLLABLE_START_CONTROL_PANEL, &request,
225034c72144SAxel Dörfler 		sizeof(request), &reply, sizeof(reply));
2251999cd0acSMaurice Kalinowski 	if (rv != B_OK)
2252999cd0acSMaurice Kalinowski 		return rv;
2253999cd0acSMaurice Kalinowski 
225434c72144SAxel Dörfler 	if (reply.team != -1 && _messenger != NULL)
225534c72144SAxel Dörfler 		*_messenger = BMessenger(NULL, reply.team);
2256999cd0acSMaurice Kalinowski 
2257999cd0acSMaurice Kalinowski 	return B_OK;
225852a38012Sejakowatz }
225952a38012Sejakowatz 
226052a38012Sejakowatz 
226152a38012Sejakowatz status_t
226234c72144SAxel Dörfler BMediaRoster::GetDormantNodes(dormant_node_info* _info, int32* _count,
226334c72144SAxel Dörfler 	const media_format* hasInput, const media_format* hasOutput,
226434c72144SAxel Dörfler 	const char* name, uint64 requireKinds, uint64 denyKinds)
226552a38012Sejakowatz {
226652a38012Sejakowatz 	CALLED();
226734c72144SAxel 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 
227834c72144SAxel Dörfler 	msg.maxcount = *_count;
227934c72144SAxel Dörfler 	msg.has_input = hasInput != NULL;
228034c72144SAxel Dörfler 	if (hasInput != NULL) {
228134c72144SAxel Dörfler 		// TODO: we should not make a flat copy of media_format
228234c72144SAxel Dörfler 		msg.inputformat = *hasInput;
228334c72144SAxel Dörfler 	}
228434c72144SAxel Dörfler 	msg.has_output = hasOutput != NULL;
228534c72144SAxel Dörfler 	if (hasOutput != NULL) {
228634c72144SAxel Dörfler 		// TODO: we should not make a flat copy of media_format
228734c72144SAxel Dörfler 		msg.outputformat = *hasOutput;
228834c72144SAxel Dörfler 	}
228934c72144SAxel Dörfler 
229034c72144SAxel Dörfler 	msg.has_name = name != NULL;
229134c72144SAxel 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 	}
229734c72144SAxel Dörfler 	msg.require_kinds = requireKinds;
229834c72144SAxel 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 
231634c72144SAxel Dörfler 	*_count = reply.count;
231752a38012Sejakowatz 
231834c72144SAxel Dörfler 	if (*_count > 0) {
231934c72144SAxel Dörfler 		rv = read_port(msg.reply_port, &code, _info,
232034c72144SAxel 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 
232934c72144SAxel Dörfler /*!	This function is used to do the real work of instantiating a dormant node.
233034c72144SAxel Dörfler 	It is either called by the media_addon_server to instantiate a global node,
233134c72144SAxel Dörfler 	or it gets called from BMediaRoster::InstantiateDormantNode() to create a
233234c72144SAxel Dörfler 	local one.
233334c72144SAxel Dörfler 
233434c72144SAxel Dörfler 	Checks concerning global/local are not done here.
23358b04ffc1Sbeveloper */
233652a38012Sejakowatz status_t
233734c72144SAxel Dörfler BMediaRosterEx::InstantiateDormantNode(media_addon_id addonID, int32 flavorID,
233834c72144SAxel 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 
234934c72144SAxel Dörfler 	// addonID		Indicates the ID number of the media add-on in which the
235034c72144SAxel Dörfler 	//				node resides.
235134c72144SAxel Dörfler 	// flavorID		Indicates the internal ID number that the add-on uses to
235234c72144SAxel Dörfler 	//				identify the flavor, this is the number that was published
235334c72144SAxel Dörfler 	//				by BMediaAddOn::GetFlavorAt() in the
23548b04ffc1Sbeveloper 	//				flavor_info::internal_id field.
235534c72144SAxel Dörfler 	// creator		The creator team is -1 if nodes are created locally. If
235634c72144SAxel Dörfler 	//				created globally, it will contain (while called in
235734c72144SAxel Dörfler 	//				media_addon_server context) the team-id of the team that
235834c72144SAxel Dörfler 	//				requested the instantiation.
23598b04ffc1Sbeveloper 
236034c72144SAxel Dörfler 	TRACE("BMediaRosterEx::InstantiateDormantNode: addonID %ld, flavorID "
236134c72144SAxel Dörfler 		"%ld\n", addonID, flavorID);
23628b04ffc1Sbeveloper 
23638b04ffc1Sbeveloper 	// Get flavor_info from the server
236434c72144SAxel Dörfler 	dormant_flavor_info info;
23658c6a6096Sbeveloper 	status_t rv;
236634c72144SAxel Dörfler 	rv = GetDormantFlavorInfo(addonID, flavorID, &info);
23678b04ffc1Sbeveloper 	if (rv != B_OK) {
236834c72144SAxel Dörfler 		ERROR("BMediaRosterEx::InstantiateDormantNode error: failed to get "
236934c72144SAxel Dörfler 			"dormant_flavor_info for addon-id %ld, flavor-id %ld\n", addonID,
237034c72144SAxel Dörfler 			flavorID);
237152a38012Sejakowatz 		return B_ERROR;
237252a38012Sejakowatz 	}
23738b04ffc1Sbeveloper 
2374*1ecccf18SFrançois Revol 	ASSERT(info.internal_id == flavorID);
23758b04ffc1Sbeveloper 
23768b04ffc1Sbeveloper 	// load the BMediaAddOn object
23778b04ffc1Sbeveloper 	BMediaAddOn* addon;
237834c72144SAxel Dörfler 	addon = _DormantNodeManager->GetAddon(addonID);
237934c72144SAxel 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.
238734c72144SAxel Dörfler 	rv = IncrementAddonFlavorInstancesCount(addonID, flavorID);
238854187cc6Sbeveloper 	if (rv != B_OK) {
238934c72144SAxel Dörfler 		ERROR("BMediaRosterEx::InstantiateDormantNode error: can't create "
239034c72144SAxel Dörfler 			"more nodes for addon-id %ld, flavor-id %ld\n", addonID, flavorID);
239154187cc6Sbeveloper 		// Put the addon back into the pool
239234c72144SAxel Dörfler 		_DormantNodeManager->PutAddon(addonID);
239354187cc6Sbeveloper 		return B_ERROR;
239454187cc6Sbeveloper 	}
239554187cc6Sbeveloper 
23968b04ffc1Sbeveloper 	BMessage config;
239734c72144SAxel Dörfler 	rv = LoadNodeConfiguration(addonID, flavorID, &config);
239854187cc6Sbeveloper 	if (rv != B_OK) {
239934c72144SAxel Dörfler 		ERROR("BMediaRosterEx::InstantiateDormantNode: couldn't load "
240034c72144SAxel Dörfler 			"configuration for addon-id %ld, flavor-id %ld\n", addonID,
240134c72144SAxel Dörfler 			flavorID);
240254187cc6Sbeveloper 		// do not return, this is a minor problem, not a reason to fail
240354187cc6Sbeveloper 	}
24048b04ffc1Sbeveloper 
240534c72144SAxel Dörfler 	status_t status = B_OK;
240634c72144SAxel Dörfler 	BMediaNode* node = addon->InstantiateNodeFor(&info, &config, &status);
240734c72144SAxel Dörfler 	if (node == NULL) {
240834c72144SAxel Dörfler 		ERROR("BMediaRosterEx::InstantiateDormantNode: InstantiateNodeFor "
240934c72144SAxel Dörfler 			"failed\n");
24108b04ffc1Sbeveloper 
241154187cc6Sbeveloper 		// Put the addon back into the pool
241234c72144SAxel Dörfler 		_DormantNodeManager->PutAddon(addonID);
241334c72144SAxel 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.
241634c72144SAxel Dörfler 		rv = DecrementAddonFlavorInstancesCount(addonID, flavorID);
241754187cc6Sbeveloper 		if (rv != B_OK) {
241834c72144SAxel Dörfler 			ERROR("BMediaRosterEx::InstantiateDormantNode: DecrementAddon"
241934c72144SAxel Dörfler 				"FlavorInstancesCount failed\n");
242016b7eea4Sbeveloper 		}
242134c72144SAxel Dörfler 		return status != B_OK ? status : B_ERROR;
242254187cc6Sbeveloper 	}
242354187cc6Sbeveloper 
242434c72144SAxel 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
242934c72144SAxel 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.
243234c72144SAxel Dörfler 		rv = DecrementAddonFlavorInstancesCount(addonID, flavorID);
243354187cc6Sbeveloper 		if (rv != B_OK) {
243434c72144SAxel Dörfler 			ERROR("BMediaRosterEx::InstantiateDormantNode: DecrementAddon"
243534c72144SAxel Dörfler 				"FlavorInstancesCount failed\n");
243654187cc6Sbeveloper 		}
24378c6a6096Sbeveloper 		return B_ERROR;
24388c6a6096Sbeveloper 	}
24398c6a6096Sbeveloper 
244054187cc6Sbeveloper 	if (creator != -1) {
244134c72144SAxel Dörfler 		// send a message to the server to assign team "creator" as creator
244234c72144SAxel Dörfler 		// of node "node->ID()"
244334c72144SAxel Dörfler 		printf("!!! BMediaRosterEx::InstantiateDormantNode assigning team "
244434c72144SAxel Dörfler 			"%ld as creator of node %ld\n", creator, node->ID());
244534c72144SAxel Dörfler 
244654187cc6Sbeveloper 		rv = MediaRosterEx(this)->SetNodeCreator(node->ID(), creator);
244754187cc6Sbeveloper 		if (rv != B_OK) {
244834c72144SAxel Dörfler 			ERROR("BMediaRosterEx::InstantiateDormantNode failed to assign "
244934c72144SAxel 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 
245834c72144SAxel Dörfler 	*_node = node->Node();
2459cf4e2277Sbeveloper 
246034c72144SAxel Dörfler 	TRACE("BMediaRosterEx::InstantiateDormantNode: addon-id %ld, flavor_id "
246134c72144SAxel Dörfler 		"%ld instanciated as node %ld, port %ld in team %ld\n", addonID,
246234c72144SAxel Dörfler 		flavorID, _node->node, _node->port, team);
2463cf4e2277Sbeveloper 
246416b7eea4Sbeveloper 	return B_OK;
246516b7eea4Sbeveloper }
246652a38012Sejakowatz 
246752a38012Sejakowatz 
246852a38012Sejakowatz status_t
246934c72144SAxel Dörfler BMediaRoster::InstantiateDormantNode(const dormant_node_info& info,
247034c72144SAxel Dörfler 	media_node* _node, uint32 flags)
24718b04ffc1Sbeveloper {
24728b04ffc1Sbeveloper 	CALLED();
247334c72144SAxel Dörfler 	if (_node == NULL)
24748b04ffc1Sbeveloper 		return B_BAD_VALUE;
247534c72144SAxel Dörfler 	if (info.addon <= B_OK) {
247634c72144SAxel Dörfler 		ERROR("BMediaRoster::InstantiateDormantNode error: addon-id %ld "
247734c72144SAxel Dörfler 			"invalid.\n", info.addon);
24788b04ffc1Sbeveloper 		return B_BAD_VALUE;
24798b04ffc1Sbeveloper 	}
24808b04ffc1Sbeveloper 
248134c72144SAxel Dörfler 	printf("BMediaRoster::InstantiateDormantNode: addon-id %ld, flavor_id "
248234c72144SAxel Dörfler 		"%ld, flags 0x%lX\n", info.addon, info.flavor_id, flags);
24838b04ffc1Sbeveloper 
24848b04ffc1Sbeveloper 	// Get flavor_info from the server
248534c72144SAxel Dörfler 	// TODO: this is a little overhead, as we get the full blown
248634c72144SAxel Dörfler 	// dormant_flavor_info,
248734c72144SAxel Dörfler 	// TODO: but only need the flags.
248834c72144SAxel Dörfler 	dormant_flavor_info flavorInfo;
24898b04ffc1Sbeveloper 	status_t rv;
249034c72144SAxel Dörfler 	rv = MediaRosterEx(this)->GetDormantFlavorInfo(info.addon, info.flavor_id,
249134c72144SAxel Dörfler 		&flavorInfo);
24928b04ffc1Sbeveloper 	if (rv != B_OK) {
249334c72144SAxel Dörfler 		ERROR("BMediaRoster::InstantiateDormantNode: failed to get "
249434c72144SAxel Dörfler 			"dormant_flavor_info for addon-id %ld, flavor-id %ld\n",
249534c72144SAxel Dörfler 			info.addon, info.flavor_id);
2496626824eaSbeveloper 		return B_NAME_NOT_FOUND;
24978b04ffc1Sbeveloper 	}
24988b04ffc1Sbeveloper 
249934c72144SAxel Dörfler 	ASSERT(flavorInfo.internal_id == info.flavor_id);
25008b04ffc1Sbeveloper 
25018b04ffc1Sbeveloper #if DEBUG
250234c72144SAxel Dörfler 	printf("BMediaRoster::InstantiateDormantNode: name \"%s\", info \"%s\", "
250334c72144SAxel Dörfler 		"flavor_flags 0x%lX, internal_id %ld, possible_count %ld\n",
250434c72144SAxel Dörfler 		flavorInfo.name, flavorInfo.info, flavorInfo.flavor_flags,
250534c72144SAxel Dörfler 		flavorInfo.internal_id, flavorInfo.possible_count);
250634c72144SAxel Dörfler 
250734c72144SAxel Dörfler 	if ((flags & B_FLAVOR_IS_LOCAL) != 0) {
250834c72144SAxel Dörfler 		printf("BMediaRoster::InstantiateDormantNode: caller requested "
250934c72144SAxel Dörfler 			"B_FLAVOR_IS_LOCAL\n");
251034c72144SAxel Dörfler 	}
251134c72144SAxel Dörfler 	if ((flags & B_FLAVOR_IS_GLOBAL) != 0) {
251234c72144SAxel Dörfler 		printf("BMediaRoster::InstantiateDormantNode: caller requested "
251334c72144SAxel Dörfler 			"B_FLAVOR_IS_GLOBAL\n");
251434c72144SAxel Dörfler 	}
251534c72144SAxel Dörfler 	if ((flavorInfo.flavor_flags & B_FLAVOR_IS_LOCAL) != 0) {
251634c72144SAxel Dörfler 		printf("BMediaRoster::InstantiateDormantNode: node requires "
251734c72144SAxel Dörfler 			"B_FLAVOR_IS_LOCAL\n");
251834c72144SAxel Dörfler 	}
251934c72144SAxel Dörfler 	if ((flavorInfo.flavor_flags & B_FLAVOR_IS_GLOBAL) != 0) {
252034c72144SAxel Dörfler 		printf("BMediaRoster::InstantiateDormantNode: node requires "
252134c72144SAxel Dörfler 			"B_FLAVOR_IS_GLOBAL\n");
252234c72144SAxel 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.
252734c72144SAxel Dörfler 	if ((flavorInfo.flavor_flags & B_FLAVOR_IS_GLOBAL) != 0
252834c72144SAxel Dörfler 		&& (flags & B_FLAVOR_IS_LOCAL) != 0) {
252934c72144SAxel Dörfler 		ERROR("BMediaRoster::InstantiateDormantNode: requested "
253034c72144SAxel Dörfler 			"B_FLAVOR_IS_LOCAL, but dormant node has B_FLAVOR_IS_GLOBAL\n");
2531626824eaSbeveloper 		return B_NAME_NOT_FOUND;
25328b04ffc1Sbeveloper 	}
253334c72144SAxel Dörfler 	if ((flavorInfo.flavor_flags & B_FLAVOR_IS_LOCAL) != 0
253434c72144SAxel Dörfler 		&& (flags & B_FLAVOR_IS_GLOBAL) != 0) {
253534c72144SAxel Dörfler 		ERROR("BMediaRoster::InstantiateDormantNode: requested "
253634c72144SAxel 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
254134c72144SAxel Dörfler 	// we will do it by forwarding this request into the media_addon_server,
254234c72144SAxel Dörfler 	// which in turn will call BMediaRosterEx::InstantiateDormantNode to create
254334c72144SAxel Dörfler 	// the node there and make it globally available.
254434c72144SAxel Dörfler 	if ((flavorInfo.flavor_flags & B_FLAVOR_IS_GLOBAL) != 0
254534c72144SAxel Dörfler 		|| (flags & B_FLAVOR_IS_GLOBAL) != 0) {
254634c72144SAxel Dörfler 		TRACE("BMediaRoster::InstantiateDormantNode: creating global object "
254734c72144SAxel Dörfler 			"in media_addon_server\n");
2548cf4e2277Sbeveloper 
25498b04ffc1Sbeveloper 		addonserver_instantiate_dormant_node_request request;
25508b04ffc1Sbeveloper 		addonserver_instantiate_dormant_node_reply reply;
255134c72144SAxel Dörfler 		request.addonid = info.addon;
255234c72144SAxel Dörfler 		request.flavorid = info.flavor_id;
255334c72144SAxel Dörfler 		request.creator_team = team;
255434c72144SAxel Dörfler 			// creator team is allowed to also release global nodes
255534c72144SAxel Dörfler 		rv = QueryAddonServer(ADDONSERVER_INSTANTIATE_DORMANT_NODE, &request,
255634c72144SAxel Dörfler 			sizeof(request), &reply, sizeof(reply));
255734c72144SAxel Dörfler 		if (rv == B_OK)
255834c72144SAxel Dörfler 			*_node = reply.node;
25598b04ffc1Sbeveloper 	} else {
256054187cc6Sbeveloper 		// creator team = -1, as this is a local node
256134c72144SAxel Dörfler 		rv = MediaRosterEx(this)->InstantiateDormantNode(info.addon,
256234c72144SAxel Dörfler 			info.flavor_id, -1, _node);
25638b04ffc1Sbeveloper 	}
2564626824eaSbeveloper 	if (rv != B_OK) {
256534c72144SAxel Dörfler 		*_node = media_node::null;
2566626824eaSbeveloper 		return B_NAME_NOT_FOUND;
2567626824eaSbeveloper 	}
2568626824eaSbeveloper 	return B_OK;
25698b04ffc1Sbeveloper }
25708b04ffc1Sbeveloper 
25718b04ffc1Sbeveloper 
25728b04ffc1Sbeveloper status_t
257334c72144SAxel Dörfler BMediaRoster::InstantiateDormantNode(const dormant_node_info& info,
257434c72144SAxel Dörfler 	media_node* _node)
25758b04ffc1Sbeveloper {
257634c72144SAxel Dörfler 	return InstantiateDormantNode(info, _node, 0);
25778b04ffc1Sbeveloper }
25788b04ffc1Sbeveloper 
25798b04ffc1Sbeveloper 
25808b04ffc1Sbeveloper status_t
258152a38012Sejakowatz BMediaRoster::GetDormantNodeFor(const media_node& node,
258234c72144SAxel Dörfler 	dormant_node_info* _info)
258352a38012Sejakowatz {
258485dfab2bSbeveloper 	CALLED();
258534c72144SAxel 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 
259634c72144SAxel Dörfler 	rv = QueryServer(SERVER_GET_DORMANT_NODE_FOR, &request, sizeof(request),
259734c72144SAxel Dörfler 		&reply, sizeof(reply));
259885dfab2bSbeveloper 	if (rv != B_OK)
259985dfab2bSbeveloper 		return rv;
260085dfab2bSbeveloper 
260134c72144SAxel Dörfler 	*_info = reply.node_info;
260285dfab2bSbeveloper 	return B_OK;
260352a38012Sejakowatz }
260452a38012Sejakowatz 
260534c72144SAxel Dörfler 
260652a38012Sejakowatz status_t
260734c72144SAxel Dörfler BMediaRosterEx::GetDormantFlavorInfo(media_addon_id addonID, int32 flavorID,
260834c72144SAxel Dörfler 	dormant_flavor_info* _flavor)
260952a38012Sejakowatz {
261052a38012Sejakowatz 	CALLED();
261134c72144SAxel 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);
262134c72144SAxel Dörfler 	if (port < B_OK)
262252a38012Sejakowatz 		return B_ERROR;
262352a38012Sejakowatz 
262452a38012Sejakowatz 	reply = (xfer_server_get_dormant_flavor_info_reply*)malloc(16000);
262534c72144SAxel Dörfler 	if (reply == NULL)
262634c72144SAxel Dörfler 		return B_NO_MEMORY;
262752a38012Sejakowatz 
262834c72144SAxel Dörfler 	msg.addon = addonID;
262934c72144SAxel 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)
264634c72144SAxel 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 
265434c72144SAxel Dörfler 
26558b04ffc1Sbeveloper status_t
265634c72144SAxel Dörfler BMediaRoster::GetDormantFlavorInfoFor(const dormant_node_info& dormant,
265734c72144SAxel Dörfler 	dormant_flavor_info* _flavor)
26588b04ffc1Sbeveloper {
265934c72144SAxel Dörfler 	return MediaRosterEx(this)->GetDormantFlavorInfo(dormant.addon,
266034c72144SAxel Dörfler 		dormant.flavor_id, _flavor);
26618b04ffc1Sbeveloper }
266252a38012Sejakowatz 
266334c72144SAxel Dörfler 
266460f15390Sbeveloper // Reports in outLatency the maximum latency found downstream from
266560f15390Sbeveloper // the specified BBufferProducer, producer, given the current connections.
266652a38012Sejakowatz status_t
266734c72144SAxel Dörfler BMediaRoster::GetLatencyFor(const media_node& producer, bigtime_t* _latency)
266852a38012Sejakowatz {
266960f15390Sbeveloper 	CALLED();
267034c72144SAxel Dörfler 	if (_latency == NULL)
267160f15390Sbeveloper 		return B_BAD_VALUE;
267234c72144SAxel Dörfler 	if (IS_INVALID_NODE(producer)
267334c72144SAxel 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 
268034c72144SAxel Dörfler 	rv = QueryPort(producer.port, PRODUCER_GET_LATENCY, &request,
268134c72144SAxel Dörfler 		sizeof(request), &reply, sizeof(reply));
268260f15390Sbeveloper 	if (rv != B_OK)
268360f15390Sbeveloper 		return rv;
268460f15390Sbeveloper 
268534c72144SAxel 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,
269434c72144SAxel Dörfler 	bigtime_t* _latency, uint32* _flags)
269552a38012Sejakowatz {
2696b65a0ac5SJérôme Duval 	CALLED();
269734c72144SAxel Dörfler 	if (_latency == NULL)
2698b65a0ac5SJérôme Duval 		return B_BAD_VALUE;
269934c72144SAxel Dörfler 	if (IS_INVALID_NODE(producer)
270034c72144SAxel 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 
270734c72144SAxel Dörfler 	rv = QueryPort(producer.port, PRODUCER_GET_INITIAL_LATENCY, &request,
270834c72144SAxel 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 
271234c72144SAxel Dörfler 	*_latency = reply.initial_latency;
271334c72144SAxel Dörfler 	if (_flags != NULL)
271434c72144SAxel Dörfler 		*_flags = reply.flags;
2715b65a0ac5SJérôme Duval 
271634c72144SAxel Dörfler 	TRACE("BMediaRoster::GetInitialLatencyFor producer %ld has maximum "
271734c72144SAxel Dörfler 		"initial latency %Ld\n", producer.node, *_latency);
2718aac800c2Sbeveloper 	return B_OK;
271952a38012Sejakowatz }
272052a38012Sejakowatz 
272152a38012Sejakowatz 
272252a38012Sejakowatz status_t
272334c72144SAxel Dörfler BMediaRoster::GetStartLatencyFor(const media_node& timeSource,
272434c72144SAxel Dörfler 	bigtime_t* _latency)
272552a38012Sejakowatz {
2726fc8b28b6SJérôme Duval 	CALLED();
272734c72144SAxel Dörfler 	if (_latency == NULL)
2728fc8b28b6SJérôme Duval 		return B_BAD_VALUE;
272934c72144SAxel Dörfler 	if (IS_INVALID_NODE(timeSource)
273034c72144SAxel 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 
273734c72144SAxel Dörfler 	rv = QueryPort(timeSource.port, TIMESOURCE_GET_START_LATENCY, &request,
273834c72144SAxel 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 
274234c72144SAxel Dörfler 	*_latency = reply.start_latency;
2743fc8b28b6SJérôme Duval 
274434c72144SAxel Dörfler 	TRACE("BMediaRoster::GetStartLatencyFor timesource %ld has maximum "
274534c72144SAxel Dörfler 		"initial latency %Ld\n", timeSource.node, *_latency);
2746aac800c2Sbeveloper 	return B_OK;
274752a38012Sejakowatz }
274852a38012Sejakowatz 
274952a38012Sejakowatz 
275052a38012Sejakowatz status_t
275134c72144SAxel Dörfler BMediaRoster::GetFileFormatsFor(const media_node& fileInterface,
275234c72144SAxel Dörfler 	media_file_format* _formats, int32* _numFormats)
275352a38012Sejakowatz {
275452a38012Sejakowatz 	UNIMPLEMENTED();
275552a38012Sejakowatz 	return B_ERROR;
275652a38012Sejakowatz }
275752a38012Sejakowatz 
275852a38012Sejakowatz 
275952a38012Sejakowatz status_t
276034c72144SAxel Dörfler BMediaRoster::SetRefFor(const media_node& file_interface, const entry_ref& file,
276134c72144SAxel 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);
277234c72144SAxel Dörfler 	request.create = createAndTruncate;
277334c72144SAxel Dörfler 	if (_length != NULL)
277434c72144SAxel Dörfler 		request.duration = *_length;
27756938364bSMaurice Kalinowski 
277634c72144SAxel Dörfler 	rv = QueryPort(file_interface.port, FILEINTERFACE_SET_REF, &request,
277734c72144SAxel Dörfler 		sizeof(request), &reply, sizeof(reply));
27786938364bSMaurice Kalinowski 	if (rv != B_OK)
27796938364bSMaurice Kalinowski 		return rv;
27806938364bSMaurice Kalinowski 
278134c72144SAxel Dörfler 	if (!createAndTruncate && _length)
278234c72144SAxel Dörfler 		*_length = reply.duration;
27836938364bSMaurice Kalinowski 
27846938364bSMaurice Kalinowski 	return B_OK;
278552a38012Sejakowatz }
278652a38012Sejakowatz 
278752a38012Sejakowatz 
278852a38012Sejakowatz status_t
278934c72144SAxel Dörfler BMediaRoster::GetRefFor(const media_node& node, entry_ref* _file,
279034c72144SAxel Dörfler 	BMimeType* mimeType)
279152a38012Sejakowatz {
27926938364bSMaurice Kalinowski 	CALLED();
27936938364bSMaurice Kalinowski 
279434c72144SAxel 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 
280134c72144SAxel Dörfler 	rv = QueryPort(node.port, FILEINTERFACE_GET_REF, &request, sizeof(request),
280234c72144SAxel Dörfler 		&reply, sizeof(reply));
28036938364bSMaurice Kalinowski 	if (rv != B_OK)
28046938364bSMaurice Kalinowski 		return rv;
28056938364bSMaurice Kalinowski 
280634c72144SAxel Dörfler 	*_file = entry_ref(reply.device, reply.directory, reply.name);
28076938364bSMaurice Kalinowski 
280834c72144SAxel Dörfler 	if (mimeType)
280934c72144SAxel 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,
281734c72144SAxel Dörfler 	const entry_ref& file, BMimeType* mimeType, float* _capability)
281852a38012Sejakowatz {
28196938364bSMaurice Kalinowski 	CALLED();
282034c72144SAxel 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 
283134c72144SAxel Dörfler 	rv = QueryPort(file_interface.port, FILEINTERFACE_SNIFF_REF, &request,
283234c72144SAxel Dörfler 		sizeof(request), &reply, sizeof(reply));
28336938364bSMaurice Kalinowski 	if (rv != B_OK)
28346938364bSMaurice Kalinowski 		return rv;
28356938364bSMaurice Kalinowski 
283634c72144SAxel Dörfler 	mimeType->SetTo(reply.mimetype);
283734c72144SAxel Dörfler 	*_capability = reply.capability;
28386938364bSMaurice Kalinowski 
28396938364bSMaurice Kalinowski 	return B_OK;
284052a38012Sejakowatz }
284152a38012Sejakowatz 
284252a38012Sejakowatz 
284334c72144SAxel Dörfler /*!	This is the generic "here's a file, now can someone please play it"
284434c72144SAxel Dörfler 	interface.
284534c72144SAxel Dörfler */
284652a38012Sejakowatz status_t
284734c72144SAxel Dörfler BMediaRoster::SniffRef(const entry_ref& file, uint64 requireNodeKinds,
284834c72144SAxel 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,
285734c72144SAxel Dörfler 	uint64 requireNodeKinds, dormant_node_info* _node)
285852a38012Sejakowatz {
285952a38012Sejakowatz 	UNIMPLEMENTED();
286052a38012Sejakowatz 	return B_ERROR;
286152a38012Sejakowatz }
286252a38012Sejakowatz 
286352a38012Sejakowatz 
286452a38012Sejakowatz status_t
286534c72144SAxel Dörfler BMediaRoster::GetReadFileFormatsFor(const dormant_node_info& node,
286634c72144SAxel Dörfler 	media_file_format* _readFormats, int32 readCount, int32* _readCount)
286752a38012Sejakowatz {
286852a38012Sejakowatz 	UNIMPLEMENTED();
286952a38012Sejakowatz 	return B_ERROR;
287052a38012Sejakowatz }
287152a38012Sejakowatz 
287252a38012Sejakowatz 
287352a38012Sejakowatz status_t
287434c72144SAxel Dörfler BMediaRoster::GetWriteFileFormatsFor(const dormant_node_info& node,
287534c72144SAxel Dörfler 	media_file_format* _write_formats, int32 writeCount, int32* _writeCount)
287652a38012Sejakowatz {
287752a38012Sejakowatz 	UNIMPLEMENTED();
287852a38012Sejakowatz 	return B_ERROR;
287952a38012Sejakowatz }
288052a38012Sejakowatz 
288152a38012Sejakowatz 
288252a38012Sejakowatz status_t
288334c72144SAxel Dörfler BMediaRoster::GetFormatFor(const media_output& output, media_format* _format,
288452a38012Sejakowatz 	uint32 flags)
288552a38012Sejakowatz {
28869bedd42cSbeveloper 	CALLED();
288734c72144SAxel 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;
289934c72144SAxel Dörfler 	request.quality = 0; // TODO: what should this be?
29009bedd42cSbeveloper 
290134c72144SAxel Dörfler 	rv = QueryPort(output.source.port, PRODUCER_FORMAT_SUGGESTION_REQUESTED,
290234c72144SAxel Dörfler 		&request, sizeof(request), &reply, sizeof(reply));
29039bedd42cSbeveloper 	if (rv != B_OK)
29049bedd42cSbeveloper 		return rv;
29059bedd42cSbeveloper 
290634c72144SAxel Dörfler 	*_format = reply.format;
29079bedd42cSbeveloper 	return B_OK;
290852a38012Sejakowatz }
290952a38012Sejakowatz 
291052a38012Sejakowatz 
291152a38012Sejakowatz status_t
291234c72144SAxel Dörfler BMediaRoster::GetFormatFor(const media_input& input, media_format* _format,
291352a38012Sejakowatz 	uint32 flags)
291452a38012Sejakowatz {
29159bedd42cSbeveloper 	CALLED();
291634c72144SAxel 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 
293034c72144SAxel Dörfler 	rv = QueryPort(input.destination.port, CONSUMER_ACCEPT_FORMAT, &request,
293134c72144SAxel Dörfler 		sizeof(request), &reply, sizeof(reply));
29329bedd42cSbeveloper 	if (rv != B_OK)
29339bedd42cSbeveloper 		return rv;
29349bedd42cSbeveloper 
293534c72144SAxel Dörfler 	*_format = reply.format;
29369bedd42cSbeveloper 	return B_OK;
293752a38012Sejakowatz }
293852a38012Sejakowatz 
293952a38012Sejakowatz 
294052a38012Sejakowatz status_t
294134c72144SAxel Dörfler BMediaRoster::GetFormatFor(const media_node& node, media_format* _format,
294252a38012Sejakowatz 	float quality)
294352a38012Sejakowatz {
294452a38012Sejakowatz 	UNIMPLEMENTED();
294534c72144SAxel 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,
295834c72144SAxel Dörfler 	media_node_attribute* _array, size_t maxCount)
295952a38012Sejakowatz {
296052a38012Sejakowatz 	UNIMPLEMENTED();
296152a38012Sejakowatz 	return B_ERROR;
296252a38012Sejakowatz }
296352a38012Sejakowatz 
296452a38012Sejakowatz 
296552a38012Sejakowatz media_node_id
296634c72144SAxel 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 
297434c72144SAxel Dörfler 	request.port = port;
29759e9417d2Sbeveloper 
297634c72144SAxel Dörfler 	rv = QueryServer(SERVER_NODE_ID_FOR, &request, sizeof(request), &reply,
297734c72144SAxel 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
298834c72144SAxel Dörfler BMediaRoster::GetInstancesFor(media_addon_id addon, int32 flavor,
298934c72144SAxel Dörfler 	media_node_id* _id, int32* _count)
299052a38012Sejakowatz {
299185dfab2bSbeveloper 	CALLED();
299234c72144SAxel Dörfler 	if (_id == NULL)
299385dfab2bSbeveloper 		return B_BAD_VALUE;
299434c72144SAxel 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 
300134c72144SAxel Dörfler 	request.maxcount = (_count ? *_count : 1);
300285dfab2bSbeveloper 	request.addon_id = addon;
300385dfab2bSbeveloper 	request.addon_flavor_id = flavor;
300485dfab2bSbeveloper 
300534c72144SAxel Dörfler 	rv = QueryServer(SERVER_GET_INSTANCES_FOR, &request, sizeof(request),
300634c72144SAxel Dörfler 		&reply, sizeof(reply));
300785dfab2bSbeveloper 	if (rv != B_OK) {
30085ac4fbd7Sbeveloper 		ERROR("BMediaRoster::GetLiveNodes failed\n");
300985dfab2bSbeveloper 		return rv;
301052a38012Sejakowatz 	}
301152a38012Sejakowatz 
301234c72144SAxel Dörfler 	if (_count)
301334c72144SAxel Dörfler 		*_count = reply.count;
301485dfab2bSbeveloper 	if (reply.count > 0)
301534c72144SAxel Dörfler 		memcpy(_id, reply.node_id, sizeof(media_node_id) * reply.count);
301685dfab2bSbeveloper 
301785dfab2bSbeveloper 	return B_OK;
301885dfab2bSbeveloper }
301952a38012Sejakowatz 
302052a38012Sejakowatz 
302152a38012Sejakowatz status_t
302234c72144SAxel Dörfler BMediaRoster::SetRealtimeFlags(uint32 enabled)
302352a38012Sejakowatz {
302452a38012Sejakowatz 	UNIMPLEMENTED();
302552a38012Sejakowatz 	return B_ERROR;
302652a38012Sejakowatz }
302752a38012Sejakowatz 
302852a38012Sejakowatz 
302952a38012Sejakowatz status_t
303034c72144SAxel Dörfler BMediaRoster::GetRealtimeFlags(uint32* _enabled)
303152a38012Sejakowatz {
303252a38012Sejakowatz 	UNIMPLEMENTED();
303352a38012Sejakowatz 	return B_ERROR;
303452a38012Sejakowatz }
303552a38012Sejakowatz 
303652a38012Sejakowatz 
303752a38012Sejakowatz ssize_t
303834c72144SAxel Dörfler BMediaRoster::AudioBufferSizeFor(int32 channelCount, uint32 sampleFormat,
303934c72144SAxel Dörfler 	float frameRate, bus_type busKind)
304052a38012Sejakowatz {
304134c72144SAxel Dörfler 	bigtime_t bufferDuration;
304234c72144SAxel Dörfler 	ssize_t bufferSize;
3043df6c2e83Sbeveloper 
3044df6c2e83Sbeveloper 	system_info info;
3045df6c2e83Sbeveloper 	get_system_info(&info);
3046df6c2e83Sbeveloper 
304734c72144SAxel Dörfler 	if (info.cpu_clock_speed > 2000000000)	// 2 GHz
304834c72144SAxel Dörfler 		bufferDuration = 2500;
3049df6c2e83Sbeveloper 	else if (info.cpu_clock_speed > 1000000000)
305034c72144SAxel Dörfler 		bufferDuration = 5000;
3051df6c2e83Sbeveloper 	else if (info.cpu_clock_speed > 600000000)
305234c72144SAxel Dörfler 		bufferDuration = 10000;
3053df6c2e83Sbeveloper 	else if (info.cpu_clock_speed > 200000000)
305434c72144SAxel Dörfler 		bufferDuration = 20000;
3055df6c2e83Sbeveloper 	else if (info.cpu_clock_speed > 100000000)
305634c72144SAxel Dörfler 		bufferDuration = 30000;
3057df6c2e83Sbeveloper 	else
305834c72144SAxel Dörfler 		bufferDuration = 50000;
3059df6c2e83Sbeveloper 
306034c72144SAxel Dörfler 	if ((busKind == B_ISA_BUS || busKind == B_PCMCIA_BUS)
306134c72144SAxel Dörfler 		&& bufferDuration < 25000)
306234c72144SAxel Dörfler 		bufferDuration = 25000;
3063df6c2e83Sbeveloper 
306434c72144SAxel Dörfler 	bufferSize = (sampleFormat & 0xf) * channelCount
306534c72144SAxel Dörfler 		* (ssize_t)((frameRate * bufferDuration) / 1000000.0);
3066df6c2e83Sbeveloper 
306734c72144SAxel Dörfler 	printf("Suggested buffer duration %Ld, size %ld\n", bufferDuration,
306834c72144SAxel Dörfler 		bufferSize);
3069df6c2e83Sbeveloper 
307034c72144SAxel Dörfler 	return bufferSize;
307152a38012Sejakowatz }
307252a38012Sejakowatz 
307352a38012Sejakowatz 
307434c72144SAxel Dörfler /*!	Use MediaFlags to inquire about specific features of the Media Kit.
307534c72144SAxel Dörfler 	Returns < 0 for "not present", positive size for output data size.
307634c72144SAxel Dörfler 	0 means that the capability is present, but no data about it.
307734c72144SAxel Dörfler */
307852a38012Sejakowatz /*static*/ ssize_t
307934c72144SAxel Dörfler BMediaRoster::MediaFlags(media_flags cap, void* buffer, size_t maxSize)
308052a38012Sejakowatz {
308152a38012Sejakowatz 	UNIMPLEMENTED();
308252a38012Sejakowatz 	return 0;
308352a38012Sejakowatz }
308452a38012Sejakowatz 
308552a38012Sejakowatz 
308634c72144SAxel Dörfler //	#pragma mark - BLooper overrides
308734c72144SAxel Dörfler 
308834c72144SAxel Dörfler 
308934c72144SAxel 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.
310734c72144SAxel Dörfler 			// TODO: If a node is released using BMediaRoster::ReleaseNode()
310834c72144SAxel Dörfler 			// TODO: instead of using BMediaNode::Release() / BMediaNode::Acquire()
310934c72144SAxel 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 
312634c72144SAxel Dörfler 
312734c72144SAxel Dörfler bool
312852a38012Sejakowatz BMediaRoster::QuitRequested()
312952a38012Sejakowatz {
313052a38012Sejakowatz 	UNIMPLEMENTED();
313152a38012Sejakowatz 	return true;
313252a38012Sejakowatz }
313352a38012Sejakowatz 
313434c72144SAxel Dörfler 
313534c72144SAxel Dörfler BHandler*
313634c72144SAxel Dörfler BMediaRoster::ResolveSpecifier(BMessage* msg, int32 index, BMessage* specifier,
313734c72144SAxel Dörfler 	int32 form, const char* property)
313852a38012Sejakowatz {
3139286a3c91SJérôme Duval 	return BLooper::ResolveSpecifier(msg, index, specifier, form, property);
314052a38012Sejakowatz }
314152a38012Sejakowatz 
314252a38012Sejakowatz 
314334c72144SAxel 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;
315834c72144SAxel Dörfler 	QueryServer(SERVER_UNREGISTER_APP, &request, sizeof(request), &reply,
315934c72144SAxel 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 
316734c72144SAxel Dörfler //	#pragma mark - private BMediaRoster
316834c72144SAxel Dörfler 
316952a38012Sejakowatz 
317052a38012Sejakowatz // deprecated call
317152a38012Sejakowatz status_t
317252a38012Sejakowatz BMediaRoster::SetOutputBuffersFor(const media_source& output,
317334c72144SAxel Dörfler 	BBufferGroup* group, bool willReclaim)
317452a38012Sejakowatz {
317552a38012Sejakowatz 	UNIMPLEMENTED();
31769e9417d2Sbeveloper 	debugger("BMediaRoster::SetOutputBuffersFor missing\n");
317752a38012Sejakowatz 	return B_ERROR;
317852a38012Sejakowatz }
317952a38012Sejakowatz 
318052a38012Sejakowatz 
318134c72144SAxel 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 
319234c72144SAxel Dörfler BMediaRoster::BMediaRoster()
319334c72144SAxel Dörfler 	: BLooper("_BMediaRoster_", B_URGENT_DISPLAY_PRIORITY,
319434c72144SAxel 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
321334c72144SAxel Dörfler BMediaRoster::GetDefaultInfo(media_node_id forDefault, BMessage& config)
321452a38012Sejakowatz {
321552a38012Sejakowatz 	UNIMPLEMENTED();
321652a38012Sejakowatz 	return B_ERROR;
321752a38012Sejakowatz }
321852a38012Sejakowatz 
321952a38012Sejakowatz 
322052a38012Sejakowatz status_t
322134c72144SAxel 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