xref: /haiku/src/kits/media/MediaRoster.cpp (revision e4c87231a37d9ec8cb923c61af6995b0622218dc)
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  */
356938364bSMaurice Kalinowski 
36255a01c7Sbeveloper 
37255a01c7Sbeveloper /* to comply with the license above, do not remove the following line */
388b940bb4SStephan Aßmus char __dont_remove_copyright_from_binary[] = "Copyright (c) 2002-2006 Marcus "
398b940bb4SStephan Aßmus 	"Overhagen <Marcus@Overhagen.de>";
40255a01c7Sbeveloper 
419dec2310SAxel Dörfler 
4252a38012Sejakowatz #include <MediaRoster.h>
438b940bb4SStephan Aßmus 
44a715f908SStephan Aßmus #include <new>
45a715f908SStephan Aßmus 
466938364bSMaurice Kalinowski #include <BufferConsumer.h>
476938364bSMaurice Kalinowski #include <BufferProducer.h>
4852a38012Sejakowatz #include <Locker.h>
4952a38012Sejakowatz #include <Message.h>
5052a38012Sejakowatz #include <Messenger.h>
516938364bSMaurice Kalinowski #include <MimeType.h>
5252a38012Sejakowatz #include <OS.h>
536938364bSMaurice Kalinowski #include <ParameterWeb.h>
546938364bSMaurice Kalinowski #include <StopWatch.h>
5552a38012Sejakowatz #include <String.h>
5652a38012Sejakowatz #include <TimeSource.h>
578b940bb4SStephan Aßmus 
589dec2310SAxel Dörfler #include <AppMisc.h>
599dec2310SAxel Dörfler 
602f9ed888SAxel Dörfler #include <debug.h>
612f9ed888SAxel Dörfler #include <DataExchange.h>
622f9ed888SAxel Dörfler #include <DormantNodeManager.h>
632f9ed888SAxel Dörfler #include <MediaRosterEx.h>
642f9ed888SAxel Dörfler #include <MediaMisc.h>
652f9ed888SAxel Dörfler #include <Notifications.h>
662f9ed888SAxel Dörfler #include <PortPool.h>
672f9ed888SAxel Dörfler #include <ServerInterface.h>
682f9ed888SAxel Dörfler #include <SharedBufferList.h>
692f9ed888SAxel Dörfler 
70835140c8Sbeveloper #include "TimeSourceObjectManager.h"
7152a38012Sejakowatz 
722f9ed888SAxel Dörfler 
73f4925104Sbeveloper namespace BPrivate { namespace media {
7452a38012Sejakowatz 
7552a38012Sejakowatz // the BMediaRoster destructor is private,
7652a38012Sejakowatz // but _DefaultDeleter is a friend class of
7752a38012Sejakowatz // the BMediaRoster an thus can delete it
789dec2310SAxel Dörfler class DefaultDeleter {
7952a38012Sejakowatz public:
808b04ffc1Sbeveloper 	~DefaultDeleter()
816396865dSbeveloper 	{
829dec2310SAxel Dörfler 		if (BMediaRoster::sDefaultInstance != NULL) {
839def3bf7SStephan Aßmus 			BMediaRoster::sDefaultInstance->Lock();
849def3bf7SStephan Aßmus 			BMediaRoster::sDefaultInstance->Quit();
856396865dSbeveloper 		}
866396865dSbeveloper 	}
878b04ffc1Sbeveloper };
8852a38012Sejakowatz 
899dec2310SAxel Dörfler }	// namespace media
909dec2310SAxel Dörfler }	// namespace BPrivate
919dec2310SAxel Dörfler 
928b04ffc1Sbeveloper using namespace BPrivate::media;
9352a38012Sejakowatz 
949dec2310SAxel Dörfler 
958b04ffc1Sbeveloper // DefaultDeleter will delete the BMediaRoster object in it's destructor.
968b04ffc1Sbeveloper DefaultDeleter _deleter;
9752a38012Sejakowatz 
989dec2310SAxel Dörfler 
9934c72144SAxel Dörfler BMediaRosterEx::BMediaRosterEx(status_t* _error)
1009dec2310SAxel Dörfler 	:
1019dec2310SAxel Dörfler 	BMediaRoster()
102dcfb6bfcSJérôme Duval {
103dcfb6bfcSJérôme Duval 	// register this application with the media server
104dcfb6bfcSJérôme Duval 	server_register_app_request request;
105dcfb6bfcSJérôme Duval 	server_register_app_reply reply;
1069dec2310SAxel Dörfler 	request.team = BPrivate::current_team();
107dcfb6bfcSJérôme Duval 	request.messenger = BMessenger(NULL, this);
1089dec2310SAxel Dörfler 
1099dec2310SAxel Dörfler 	status_t status = QueryServer(SERVER_REGISTER_APP, &request,
1109dec2310SAxel Dörfler 		sizeof(request), &reply, sizeof(reply));
1119dec2310SAxel Dörfler 	if (status != B_OK)
11234c72144SAxel Dörfler 		*_error = B_MEDIA_SYSTEM_FAILURE;
113a7fb4c16SMaurice Kalinowski 	else
11434c72144SAxel Dörfler 		*_error = B_OK;
115dcfb6bfcSJérôme Duval }
116dcfb6bfcSJérôme Duval 
11734c72144SAxel Dörfler 
1183620737cSbeveloper status_t
11954187cc6Sbeveloper BMediaRosterEx::SaveNodeConfiguration(BMediaNode* node)
12054187cc6Sbeveloper {
1219dec2310SAxel Dörfler 	int32 flavorID;
1229dec2310SAxel Dörfler 	BMediaAddOn* addon = node->AddOn(&flavorID);
1239dec2310SAxel Dörfler 	if (addon == NULL) {
1248056f0dbSStephan Aßmus 		// NOTE: This node could have been created by an application,
1258056f0dbSStephan Aßmus 		// it does not mean there is an error.
12634c72144SAxel Dörfler 		// TODO: this check incorrectly triggers on BeOS R5 BT848 node
1278056f0dbSStephan Aßmus 		TRACE("BMediaRosterEx::SaveNodeConfiguration node %ld not instantiated "
1288056f0dbSStephan Aßmus 			"from BMediaAddOn!\n", node->ID());
12954187cc6Sbeveloper 		return B_ERROR;
13054187cc6Sbeveloper 	}
1319dec2310SAxel Dörfler 
1329dec2310SAxel Dörfler 	media_addon_id addonID = addon->AddonID();
13354187cc6Sbeveloper 
13434c72144SAxel Dörfler 	// TODO: fix this
1358056f0dbSStephan Aßmus 	printf("### BMediaRosterEx::SaveNodeConfiguration should save addon-id "
1369dec2310SAxel Dörfler 		"%ld, flavor-id %ld config NOW!\n", addonID, flavorID);
13754187cc6Sbeveloper 	return B_OK;
13854187cc6Sbeveloper }
13954187cc6Sbeveloper 
14034c72144SAxel Dörfler 
14154187cc6Sbeveloper status_t
1429dec2310SAxel Dörfler BMediaRosterEx::LoadNodeConfiguration(media_addon_id addonID, int32 flavorID,
1439dec2310SAxel Dörfler 	BMessage *_msg)
14454187cc6Sbeveloper {
14534c72144SAxel Dörfler 	// TODO: fix this
1469dec2310SAxel Dörfler 	_msg->MakeEmpty(); // to be fully R5 compliant
1478b940bb4SStephan Aßmus 	printf("### BMediaRosterEx::LoadNodeConfiguration should load addon-id "
1489dec2310SAxel Dörfler 		"%ld, flavor-id %ld config NOW!\n", addonID, flavorID);
14954187cc6Sbeveloper 	return B_OK;
15054187cc6Sbeveloper }
15154187cc6Sbeveloper 
15234c72144SAxel Dörfler 
15354187cc6Sbeveloper status_t
1549dec2310SAxel Dörfler BMediaRosterEx::IncrementAddonFlavorInstancesCount(media_addon_id addonID,
1559dec2310SAxel Dörfler 	int32 flavorID)
15654187cc6Sbeveloper {
1579c3b4706SAxel Dörfler 	server_change_flavor_instances_count_request request;
1589c3b4706SAxel Dörfler 	server_change_flavor_instances_count_reply reply;
15973794717Sbeveloper 
1609c3b4706SAxel Dörfler 	request.add_on_id = addonID;
1619dec2310SAxel Dörfler 	request.flavor_id = flavorID;
16273794717Sbeveloper 	request.delta = 1;
1639dec2310SAxel Dörfler 	request.team = BPrivate::current_team();
1649c3b4706SAxel Dörfler 	return QueryServer(SERVER_CHANGE_FLAVOR_INSTANCES_COUNT, &request,
16534c72144SAxel Dörfler 		sizeof(request), &reply, sizeof(reply));
16654187cc6Sbeveloper }
16754187cc6Sbeveloper 
16834c72144SAxel Dörfler 
16954187cc6Sbeveloper status_t
1709dec2310SAxel Dörfler BMediaRosterEx::DecrementAddonFlavorInstancesCount(media_addon_id addonID,
1719dec2310SAxel Dörfler 	int32 flavorID)
17254187cc6Sbeveloper {
1739c3b4706SAxel Dörfler 	server_change_flavor_instances_count_request request;
1749c3b4706SAxel Dörfler 	server_change_flavor_instances_count_reply reply;
17573794717Sbeveloper 
1769c3b4706SAxel Dörfler 	request.add_on_id = addonID;
1779dec2310SAxel Dörfler 	request.flavor_id = flavorID;
17873794717Sbeveloper 	request.delta = -1;
1799dec2310SAxel Dörfler 	request.team = BPrivate::current_team();
1809c3b4706SAxel Dörfler 	return QueryServer(SERVER_CHANGE_FLAVOR_INSTANCES_COUNT, &request,
18134c72144SAxel Dörfler 		sizeof(request), &reply, sizeof(reply));
18254187cc6Sbeveloper }
18354187cc6Sbeveloper 
18434c72144SAxel Dörfler 
18554187cc6Sbeveloper status_t
18654187cc6Sbeveloper BMediaRosterEx::SetNodeCreator(media_node_id node, team_id creator)
18754187cc6Sbeveloper {
18854187cc6Sbeveloper 	server_set_node_creator_request request;
18954187cc6Sbeveloper 	server_set_node_creator_reply reply;
19054187cc6Sbeveloper 
19154187cc6Sbeveloper 	request.node = node;
19254187cc6Sbeveloper 	request.creator = creator;
19334c72144SAxel Dörfler 	return QueryServer(SERVER_SET_NODE_CREATOR, &request, sizeof(request),
19434c72144SAxel Dörfler 		&reply, sizeof(reply));
19554187cc6Sbeveloper }
19654187cc6Sbeveloper 
19734c72144SAxel Dörfler 
19854187cc6Sbeveloper status_t
19934c72144SAxel Dörfler BMediaRosterEx::GetNode(node_type type, media_node* out_node,
20034c72144SAxel Dörfler 	int32* out_input_id, BString* out_input_name)
20152a38012Sejakowatz {
20252a38012Sejakowatz 	if (out_node == NULL)
20352a38012Sejakowatz 		return B_BAD_VALUE;
20452a38012Sejakowatz 
2058c6a6096Sbeveloper 	server_get_node_request request;
2068c6a6096Sbeveloper 	server_get_node_reply reply;
20752a38012Sejakowatz 	status_t rv;
20852a38012Sejakowatz 
2098c6a6096Sbeveloper 	request.type = type;
2109dec2310SAxel Dörfler 	request.team = BPrivate::current_team();
21134c72144SAxel Dörfler 	rv = QueryServer(SERVER_GET_NODE, &request, sizeof(request), &reply,
21234c72144SAxel Dörfler 		sizeof(reply));
2138c6a6096Sbeveloper 	if (rv != B_OK)
2148c6a6096Sbeveloper 		return rv;
21552a38012Sejakowatz 
21652a38012Sejakowatz 	*out_node = reply.node;
21752a38012Sejakowatz 	if (out_input_id)
21852a38012Sejakowatz 		*out_input_id = reply.input_id;
21952a38012Sejakowatz 	if (out_input_name)
22052a38012Sejakowatz 		*out_input_name = reply.input_name;
2218c6a6096Sbeveloper 	return rv;
22252a38012Sejakowatz }
22352a38012Sejakowatz 
22434c72144SAxel Dörfler 
2253620737cSbeveloper status_t
22634c72144SAxel Dörfler BMediaRosterEx::SetNode(node_type type, const media_node* node,
22734c72144SAxel Dörfler 	const dormant_node_info* info, const media_input* input)
22852a38012Sejakowatz {
2298c6a6096Sbeveloper 	server_set_node_request request;
2308c6a6096Sbeveloper 	server_set_node_reply reply;
23152a38012Sejakowatz 
2328c6a6096Sbeveloper 	request.type = type;
23334c72144SAxel Dörfler 	request.use_node = node != NULL;
23434c72144SAxel Dörfler 	if (node != NULL)
2358c6a6096Sbeveloper 		request.node = *node;
23634c72144SAxel Dörfler 	request.use_dni = info != NULL;
23734c72144SAxel Dörfler 	if (info != NULL)
2388c6a6096Sbeveloper 		request.dni = *info;
23934c72144SAxel Dörfler 	request.use_input = input != NULL;
24034c72144SAxel Dörfler 	if (input != NULL)
2418c6a6096Sbeveloper 		request.input = *input;
24252a38012Sejakowatz 
24334c72144SAxel Dörfler 	return QueryServer(SERVER_SET_NODE, &request, sizeof(request), &reply,
24434c72144SAxel Dörfler 		sizeof(reply));
24552a38012Sejakowatz }
24652a38012Sejakowatz 
24734c72144SAxel Dörfler 
2483620737cSbeveloper status_t
2498b04ffc1Sbeveloper BMediaRosterEx::GetAllOutputs(const media_node& node, List<media_output>* list)
2503620737cSbeveloper {
2513620737cSbeveloper 	int32 cookie;
2523620737cSbeveloper 	status_t rv;
2533620737cSbeveloper 	status_t result;
2543620737cSbeveloper 
25534c72144SAxel Dörfler 	PRINT(4, "BMediaRosterEx::GetAllOutputs() node %ld, port %ld\n", node.node,
25634c72144SAxel Dörfler 		node.port);
2575ac4fbd7Sbeveloper 
25865b73ae4SMarcus Overhagen 	if (!(node.kind & B_BUFFER_PRODUCER)) {
25934c72144SAxel Dörfler 		ERROR("BMediaRosterEx::GetAllOutputs: node %ld is not a "
26034c72144SAxel Dörfler 			"B_BUFFER_PRODUCER\n", node.node);
26165b73ae4SMarcus Overhagen 		return B_MEDIA_BAD_NODE;
26265b73ae4SMarcus Overhagen 	}
26365b73ae4SMarcus Overhagen 
2643620737cSbeveloper 	result = B_OK;
2653620737cSbeveloper 	cookie = 0;
26676669a29Sbeveloper 	list->MakeEmpty();
2673620737cSbeveloper 	for (;;) {
2683620737cSbeveloper 		producer_get_next_output_request request;
2693620737cSbeveloper 		producer_get_next_output_reply reply;
2703620737cSbeveloper 		request.cookie = cookie;
27134c72144SAxel Dörfler 		rv = QueryPort(node.port, PRODUCER_GET_NEXT_OUTPUT, &request,
27234c72144SAxel Dörfler 			sizeof(request), &reply, sizeof(reply));
2733620737cSbeveloper 		if (rv != B_OK)
2743620737cSbeveloper 			break;
2753620737cSbeveloper 		cookie = reply.cookie;
27676669a29Sbeveloper 		if (!list->Insert(reply.output)) {
2775ac4fbd7Sbeveloper 			ERROR("GetAllOutputs: list->Insert failed\n");
2783620737cSbeveloper 			result = B_ERROR;
2793620737cSbeveloper 		}
2805ac4fbd7Sbeveloper 		#if DEBUG >= 3
2815ac4fbd7Sbeveloper 			PRINT(3," next cookie %ld, ", cookie);
2825ac4fbd7Sbeveloper 			PRINT_OUTPUT("output ", reply.output);
2835ac4fbd7Sbeveloper 		#endif
2843620737cSbeveloper 	}
2853620737cSbeveloper 
2863620737cSbeveloper 	producer_dispose_output_cookie_request request;
2873620737cSbeveloper 	producer_dispose_output_cookie_reply reply;
28834c72144SAxel Dörfler 	QueryPort(node.port, PRODUCER_DISPOSE_OUTPUT_COOKIE, &request,
28934c72144SAxel Dörfler 		sizeof(request), &reply, sizeof(reply));
2903620737cSbeveloper 
2913620737cSbeveloper 	return result;
2923620737cSbeveloper }
2933620737cSbeveloper 
29434c72144SAxel Dörfler 
2953620737cSbeveloper status_t
2964d2d96e0Sbeveloper BMediaRosterEx::GetAllOutputs(BBufferProducer* node, List<media_output>* list)
2974d2d96e0Sbeveloper {
2984d2d96e0Sbeveloper 	int32 cookie;
2994d2d96e0Sbeveloper 	status_t result;
3004d2d96e0Sbeveloper 
3014d2d96e0Sbeveloper 	PRINT(4, "BMediaRosterEx::GetAllOutputs() (by pointer) node %ld, port %ld\n", node->ID(), node->ControlPort());
3024d2d96e0Sbeveloper 
3034d2d96e0Sbeveloper 	result = B_OK;
3044d2d96e0Sbeveloper 	cookie = 0;
3054d2d96e0Sbeveloper 	list->MakeEmpty();
3064d2d96e0Sbeveloper 	for (;;) {
3074d2d96e0Sbeveloper 		media_output output;
3084d2d96e0Sbeveloper 		if (B_OK != node->GetNextOutput(&cookie, &output))
3094d2d96e0Sbeveloper 			break;
3104d2d96e0Sbeveloper 		if (!list->Insert(output)) {
3114d2d96e0Sbeveloper 			ERROR("GetAllOutputs: list->Insert failed\n");
3124d2d96e0Sbeveloper 			result = B_ERROR;
3134d2d96e0Sbeveloper 		}
3144d2d96e0Sbeveloper 		#if DEBUG >= 3
3154d2d96e0Sbeveloper 			PRINT(3," next cookie %ld, ", cookie);
3164d2d96e0Sbeveloper 			PRINT_OUTPUT("output ", output);
3174d2d96e0Sbeveloper 		#endif
3184d2d96e0Sbeveloper 	}
3194d2d96e0Sbeveloper 	node->DisposeOutputCookie(cookie);
3204d2d96e0Sbeveloper 	return result;
3214d2d96e0Sbeveloper }
3224d2d96e0Sbeveloper 
32334c72144SAxel Dörfler 
3244d2d96e0Sbeveloper status_t
3258b04ffc1Sbeveloper BMediaRosterEx::GetAllInputs(const media_node& node, List<media_input>* list)
3263620737cSbeveloper {
3273620737cSbeveloper 	int32 cookie;
3283620737cSbeveloper 	status_t rv;
3293620737cSbeveloper 	status_t result;
3303620737cSbeveloper 
33134c72144SAxel Dörfler 	PRINT(4, "BMediaRosterEx::GetAllInputs() node %ld, port %ld\n", node.node,
33234c72144SAxel Dörfler 		node.port);
3335ac4fbd7Sbeveloper 
33465b73ae4SMarcus Overhagen 	if (!(node.kind & B_BUFFER_CONSUMER)) {
33534c72144SAxel Dörfler 		ERROR("BMediaRosterEx::GetAllInputs: node %ld is not a "
33634c72144SAxel Dörfler 			"B_BUFFER_CONSUMER\n", node.node);
33765b73ae4SMarcus Overhagen 		return B_MEDIA_BAD_NODE;
33865b73ae4SMarcus Overhagen 	}
33965b73ae4SMarcus Overhagen 
3403620737cSbeveloper 	result = B_OK;
3413620737cSbeveloper 	cookie = 0;
34276669a29Sbeveloper 	list->MakeEmpty();
3433620737cSbeveloper 	for (;;) {
3443620737cSbeveloper 		consumer_get_next_input_request request;
3453620737cSbeveloper 		consumer_get_next_input_reply reply;
3463620737cSbeveloper 		request.cookie = cookie;
34734c72144SAxel Dörfler 		rv = QueryPort(node.port, CONSUMER_GET_NEXT_INPUT, &request,
34834c72144SAxel Dörfler 			sizeof(request), &reply, sizeof(reply));
3493620737cSbeveloper 		if (rv != B_OK)
3503620737cSbeveloper 			break;
3513620737cSbeveloper 		cookie = reply.cookie;
35276669a29Sbeveloper 		if (!list->Insert(reply.input)) {
3535ac4fbd7Sbeveloper 			ERROR("GetAllInputs: list->Insert failed\n");
3543620737cSbeveloper 			result = B_ERROR;
3553620737cSbeveloper 		}
3565ac4fbd7Sbeveloper 		#if DEBUG >= 3
3575ac4fbd7Sbeveloper 			PRINT(3," next cookie %ld, ", cookie);
3585ac4fbd7Sbeveloper 			PRINT_OUTPUT("input ", reply.input);
3595ac4fbd7Sbeveloper 		#endif
3603620737cSbeveloper 	}
3613620737cSbeveloper 
3623620737cSbeveloper 	consumer_dispose_input_cookie_request request;
3633620737cSbeveloper 	consumer_dispose_input_cookie_reply reply;
36434c72144SAxel Dörfler 	QueryPort(node.port, CONSUMER_DISPOSE_INPUT_COOKIE, &request,
36534c72144SAxel Dörfler 		sizeof(request), &reply, sizeof(reply));
3663620737cSbeveloper 
3673620737cSbeveloper 	return result;
3683620737cSbeveloper }
3693620737cSbeveloper 
37034c72144SAxel Dörfler 
3713620737cSbeveloper status_t
3724d2d96e0Sbeveloper BMediaRosterEx::GetAllInputs(BBufferConsumer* node, List<media_input>* list)
3734d2d96e0Sbeveloper {
3744d2d96e0Sbeveloper 	int32 cookie;
3754d2d96e0Sbeveloper 	status_t result;
3764d2d96e0Sbeveloper 
3774d2d96e0Sbeveloper 	PRINT(4, "BMediaRosterEx::GetAllInputs() (by pointer) node %ld, port %ld\n", node->ID(), node->ControlPort());
3784d2d96e0Sbeveloper 
3794d2d96e0Sbeveloper 	result = B_OK;
3804d2d96e0Sbeveloper 	cookie = 0;
3814d2d96e0Sbeveloper 	list->MakeEmpty();
3824d2d96e0Sbeveloper 	for (;;) {
3834d2d96e0Sbeveloper 		media_input input;
3844d2d96e0Sbeveloper 		if (B_OK != node->GetNextInput(&cookie, &input))
3854d2d96e0Sbeveloper 			break;
3864d2d96e0Sbeveloper 		if (!list->Insert(input)) {
3874d2d96e0Sbeveloper 			ERROR("GetAllInputs: list->Insert failed\n");
3884d2d96e0Sbeveloper 			result = B_ERROR;
3894d2d96e0Sbeveloper 		}
3904d2d96e0Sbeveloper 		#if DEBUG >= 3
3914d2d96e0Sbeveloper 			PRINT(3," next cookie %ld, ", cookie);
3924d2d96e0Sbeveloper 			PRINT_INPUT("input ", input);
3934d2d96e0Sbeveloper 		#endif
3944d2d96e0Sbeveloper 	}
3954d2d96e0Sbeveloper 	node->DisposeInputCookie(cookie);
3964d2d96e0Sbeveloper 	return result;
3974d2d96e0Sbeveloper }
3984d2d96e0Sbeveloper 
39934c72144SAxel Dörfler 
4004d2d96e0Sbeveloper status_t
4018b04ffc1Sbeveloper BMediaRosterEx::PublishOutputs(const media_node& node, List<media_output>* list)
4023620737cSbeveloper {
4033620737cSbeveloper 	server_publish_outputs_request request;
4043620737cSbeveloper 	server_publish_outputs_reply reply;
4053620737cSbeveloper 	media_output* output;
4063620737cSbeveloper 	media_output* outputs;
4073620737cSbeveloper 	int32 count;
408a7b41a96Sbeveloper 	status_t rv;
4093620737cSbeveloper 
41076669a29Sbeveloper 	count = list->CountItems();
4113620737cSbeveloper 	TRACE("PublishOutputs: publishing %ld\n", count);
4123620737cSbeveloper 
4133620737cSbeveloper 	request.node = node;
4143620737cSbeveloper 	request.count = count;
4153620737cSbeveloper 	if (count > MAX_OUTPUTS) {
4163620737cSbeveloper 		void *start_addr;
4173620737cSbeveloper 		size_t size;
41840f36b03Sbeveloper 		size = ROUND_UP_TO_PAGE(count * sizeof(media_output));
41934c72144SAxel Dörfler 		request.area = create_area("publish outputs", &start_addr,
42034c72144SAxel Dörfler 			B_ANY_ADDRESS, size, B_NO_LOCK, B_READ_AREA | B_WRITE_AREA);
4213620737cSbeveloper 		if (request.area < B_OK) {
42234c72144SAxel Dörfler 			ERROR("PublishOutputs: failed to create area, %#lx\n",
42334c72144SAxel Dörfler 				request.area);
4243620737cSbeveloper 			return (status_t)request.area;
4253620737cSbeveloper 		}
4263620737cSbeveloper 		outputs = static_cast<media_output *>(start_addr);
4273620737cSbeveloper 	} else {
4283620737cSbeveloper 		request.area = -1;
4293620737cSbeveloper 		outputs = request.outputs;
4303620737cSbeveloper 	}
43176669a29Sbeveloper 	TRACE("PublishOutputs: area %ld\n", request.area);
4323620737cSbeveloper 
43376669a29Sbeveloper 	int i;
43476669a29Sbeveloper 	for (i = 0, list->Rewind(); list->GetNext(&output); i++) {
43576669a29Sbeveloper 		ASSERT(i < count);
4363620737cSbeveloper 		outputs[i] = *output;
4373620737cSbeveloper 	}
4383620737cSbeveloper 
43934c72144SAxel Dörfler 	rv = QueryServer(SERVER_PUBLISH_OUTPUTS, &request, sizeof(request),
44034c72144SAxel Dörfler 		&reply, sizeof(reply));
441a7b41a96Sbeveloper 
442a7b41a96Sbeveloper 	if (request.area != -1)
443a7b41a96Sbeveloper 		delete_area(request.area);
444a7b41a96Sbeveloper 
445a7b41a96Sbeveloper 	return rv;
4463620737cSbeveloper }
4473620737cSbeveloper 
44834c72144SAxel Dörfler 
4493620737cSbeveloper status_t
4508b04ffc1Sbeveloper BMediaRosterEx::PublishInputs(const media_node& node, List<media_input>* list)
4513620737cSbeveloper {
4523620737cSbeveloper 	server_publish_inputs_request request;
4533620737cSbeveloper 	server_publish_inputs_reply reply;
4543620737cSbeveloper 	media_input* input;
4553620737cSbeveloper 	media_input* inputs;
4563620737cSbeveloper 	int32 count;
457a7b41a96Sbeveloper 	status_t rv;
4583620737cSbeveloper 
45976669a29Sbeveloper 	count = list->CountItems();
4603620737cSbeveloper 	TRACE("PublishInputs: publishing %ld\n", count);
4613620737cSbeveloper 
4623620737cSbeveloper 	request.node = node;
4633620737cSbeveloper 	request.count = count;
4643620737cSbeveloper 	if (count > MAX_INPUTS) {
4653620737cSbeveloper 		void* start_addr;
4663620737cSbeveloper 		size_t size;
46740f36b03Sbeveloper 		size = ROUND_UP_TO_PAGE(count * sizeof(media_input));
46834c72144SAxel Dörfler 		request.area = create_area("publish inputs", &start_addr,
46934c72144SAxel Dörfler 			B_ANY_ADDRESS, size, B_NO_LOCK, B_READ_AREA | B_WRITE_AREA);
4703620737cSbeveloper 		if (request.area < B_OK) {
4715ac4fbd7Sbeveloper 			ERROR("PublishInputs: failed to create area, %#lx\n", request.area);
4723620737cSbeveloper 			return (status_t)request.area;
4733620737cSbeveloper 		}
4743620737cSbeveloper 		inputs = static_cast<media_input *>(start_addr);
4753620737cSbeveloper 	} else {
4763620737cSbeveloper 		request.area = -1;
4773620737cSbeveloper 		inputs = request.inputs;
4783620737cSbeveloper 	}
47976669a29Sbeveloper 	TRACE("PublishInputs: area %ld\n", request.area);
4803620737cSbeveloper 
48176669a29Sbeveloper 	int i;
48276669a29Sbeveloper 	for (i = 0, list->Rewind(); list->GetNext(&input); i++) {
48376669a29Sbeveloper 		ASSERT(i < count);
4843620737cSbeveloper 		inputs[i] = *input;
4853620737cSbeveloper 	}
4863620737cSbeveloper 
48734c72144SAxel Dörfler 	rv = QueryServer(SERVER_PUBLISH_INPUTS, &request, sizeof(request),
48834c72144SAxel Dörfler 		&reply, sizeof(reply));
489a7b41a96Sbeveloper 
490a7b41a96Sbeveloper 	if (request.area != -1)
491a7b41a96Sbeveloper 		delete_area(request.area);
492a7b41a96Sbeveloper 
493a7b41a96Sbeveloper 	return rv;
4943620737cSbeveloper }
4953620737cSbeveloper 
49634c72144SAxel Dörfler 
49734c72144SAxel Dörfler BTimeSource*
498f4ec236cSAxel Dörfler BMediaRosterEx::MakeTimeSourceObject(media_node_id timeSourceID)
49934c72144SAxel Dörfler {
50034c72144SAxel Dörfler 	media_node clone;
501f4ec236cSAxel Dörfler 	status_t status = GetNodeFor(timeSourceID, &clone);
502f4ec236cSAxel Dörfler 	if (status != B_OK) {
503f4ec236cSAxel Dörfler 		ERROR("BMediaRosterEx::MakeTimeSourceObject: GetNodeFor failed: %s\n",
504f4ec236cSAxel Dörfler 			strerror(status));
50534c72144SAxel Dörfler 		return NULL;
50634c72144SAxel Dörfler 	}
50734c72144SAxel Dörfler 
508f4ec236cSAxel Dörfler 	BTimeSource* source = gTimeSourceObjectManager->GetTimeSource(clone);
50934c72144SAxel Dörfler 	if (source == NULL) {
51034c72144SAxel Dörfler 		ERROR("BMediaRosterEx::MakeTimeSourceObject: GetTimeSource failed\n");
51134c72144SAxel Dörfler 		return NULL;
51234c72144SAxel Dörfler 	}
51334c72144SAxel Dörfler 
51434c72144SAxel Dörfler 	// TODO: release?
51534c72144SAxel Dörfler 	ReleaseNode(clone);
51634c72144SAxel Dörfler 
51734c72144SAxel Dörfler 	return source;
51834c72144SAxel Dörfler }
51934c72144SAxel Dörfler 
52034c72144SAxel Dörfler 
52134c72144SAxel Dörfler //	#pragma mark - public BMediaRoster
52234c72144SAxel Dörfler 
52352a38012Sejakowatz 
52452a38012Sejakowatz status_t
52534c72144SAxel Dörfler BMediaRoster::GetVideoInput(media_node* _node)
52652a38012Sejakowatz {
52752a38012Sejakowatz 	CALLED();
52834c72144SAxel Dörfler 	return MediaRosterEx(this)->GetNode(VIDEO_INPUT, _node);
52952a38012Sejakowatz }
53052a38012Sejakowatz 
53152a38012Sejakowatz 
53252a38012Sejakowatz status_t
53334c72144SAxel Dörfler BMediaRoster::GetAudioInput(media_node* _node)
53452a38012Sejakowatz {
53552a38012Sejakowatz 	CALLED();
53634c72144SAxel Dörfler 	return MediaRosterEx(this)->GetNode(AUDIO_INPUT, _node);
53752a38012Sejakowatz }
53852a38012Sejakowatz 
53952a38012Sejakowatz 
54052a38012Sejakowatz status_t
54134c72144SAxel Dörfler BMediaRoster::GetVideoOutput(media_node* _node)
54252a38012Sejakowatz {
54352a38012Sejakowatz 	CALLED();
54434c72144SAxel Dörfler 	return MediaRosterEx(this)->GetNode(VIDEO_OUTPUT, _node);
54552a38012Sejakowatz }
54652a38012Sejakowatz 
54752a38012Sejakowatz 
54852a38012Sejakowatz status_t
54934c72144SAxel Dörfler BMediaRoster::GetAudioMixer(media_node* _node)
55052a38012Sejakowatz {
55152a38012Sejakowatz 	CALLED();
55234c72144SAxel Dörfler 	return MediaRosterEx(this)->GetNode(AUDIO_MIXER, _node);
55352a38012Sejakowatz }
55452a38012Sejakowatz 
55552a38012Sejakowatz 
55652a38012Sejakowatz status_t
55734c72144SAxel Dörfler BMediaRoster::GetAudioOutput(media_node* _node)
55852a38012Sejakowatz {
55952a38012Sejakowatz 	CALLED();
56034c72144SAxel Dörfler 	return MediaRosterEx(this)->GetNode(AUDIO_OUTPUT, _node);
56152a38012Sejakowatz }
56252a38012Sejakowatz 
56352a38012Sejakowatz 
56452a38012Sejakowatz status_t
56534c72144SAxel Dörfler BMediaRoster::GetAudioOutput(media_node* _node, int32* _inputID,
56634c72144SAxel Dörfler 	BString* _inputName)
56752a38012Sejakowatz {
56852a38012Sejakowatz 	CALLED();
56934c72144SAxel Dörfler 	return MediaRosterEx(this)->GetNode(AUDIO_OUTPUT_EX, _node, _inputID,
57034c72144SAxel Dörfler 		_inputName);
57152a38012Sejakowatz }
57252a38012Sejakowatz 
57352a38012Sejakowatz 
57452a38012Sejakowatz status_t
57534c72144SAxel Dörfler BMediaRoster::GetTimeSource(media_node* _node)
57652a38012Sejakowatz {
57752a38012Sejakowatz 	CALLED();
57886bce45bSbeveloper 	status_t rv;
57986bce45bSbeveloper 
58034c72144SAxel Dörfler 	// TODO: need to do this in a nicer way.
58186bce45bSbeveloper 
58234c72144SAxel Dörfler 	rv = MediaRosterEx(this)->GetNode(TIME_SOURCE, _node);
58386bce45bSbeveloper 	if (rv != B_OK)
58486bce45bSbeveloper 		return rv;
58586bce45bSbeveloper 
58686bce45bSbeveloper 	// We don't do reference counting for timesources, that's why we
58786bce45bSbeveloper 	// release the node immediately.
58834c72144SAxel Dörfler 	ReleaseNode(*_node);
58986bce45bSbeveloper 
59086bce45bSbeveloper 	// we need to remember to not use this node with server side reference counting
59134c72144SAxel Dörfler 	_node->kind |= NODE_KIND_NO_REFCOUNTING;
59286bce45bSbeveloper 	return B_OK;
59352a38012Sejakowatz }
59452a38012Sejakowatz 
59552a38012Sejakowatz 
59652a38012Sejakowatz status_t
59752a38012Sejakowatz BMediaRoster::SetVideoInput(const media_node& producer)
59852a38012Sejakowatz {
59952a38012Sejakowatz 	CALLED();
6008b04ffc1Sbeveloper 	return MediaRosterEx(this)->SetNode(VIDEO_INPUT, &producer);
60152a38012Sejakowatz }
60252a38012Sejakowatz 
60352a38012Sejakowatz 
60452a38012Sejakowatz status_t
60552a38012Sejakowatz BMediaRoster::SetVideoInput(const dormant_node_info& producer)
60652a38012Sejakowatz {
60752a38012Sejakowatz 	CALLED();
6088b04ffc1Sbeveloper 	return MediaRosterEx(this)->SetNode(VIDEO_INPUT, NULL, &producer);
60952a38012Sejakowatz }
61052a38012Sejakowatz 
61152a38012Sejakowatz 
61252a38012Sejakowatz status_t
61352a38012Sejakowatz BMediaRoster::SetAudioInput(const media_node& producer)
61452a38012Sejakowatz {
61552a38012Sejakowatz 	CALLED();
6168b04ffc1Sbeveloper 	return MediaRosterEx(this)->SetNode(AUDIO_INPUT, &producer);
61752a38012Sejakowatz }
61852a38012Sejakowatz 
61952a38012Sejakowatz 
62052a38012Sejakowatz status_t
62152a38012Sejakowatz BMediaRoster::SetAudioInput(const dormant_node_info& producer)
62252a38012Sejakowatz {
62352a38012Sejakowatz 	CALLED();
6248b04ffc1Sbeveloper 	return MediaRosterEx(this)->SetNode(AUDIO_INPUT, NULL, &producer);
62552a38012Sejakowatz }
62652a38012Sejakowatz 
62752a38012Sejakowatz 
62852a38012Sejakowatz status_t
62952a38012Sejakowatz BMediaRoster::SetVideoOutput(const media_node& consumer)
63052a38012Sejakowatz {
63152a38012Sejakowatz 	CALLED();
6328b04ffc1Sbeveloper 	return MediaRosterEx(this)->SetNode(VIDEO_OUTPUT, &consumer);
63352a38012Sejakowatz }
63452a38012Sejakowatz 
63552a38012Sejakowatz 
63652a38012Sejakowatz status_t
63752a38012Sejakowatz BMediaRoster::SetVideoOutput(const dormant_node_info& consumer)
63852a38012Sejakowatz {
63952a38012Sejakowatz 	CALLED();
6408b04ffc1Sbeveloper 	return MediaRosterEx(this)->SetNode(VIDEO_OUTPUT, NULL, &consumer);
64152a38012Sejakowatz }
64252a38012Sejakowatz 
64352a38012Sejakowatz 
64452a38012Sejakowatz status_t
64552a38012Sejakowatz BMediaRoster::SetAudioOutput(const media_node& consumer)
64652a38012Sejakowatz {
64752a38012Sejakowatz 	CALLED();
6488b04ffc1Sbeveloper 	return MediaRosterEx(this)->SetNode(AUDIO_OUTPUT, &consumer);
64952a38012Sejakowatz }
65052a38012Sejakowatz 
65152a38012Sejakowatz 
65252a38012Sejakowatz status_t
65334c72144SAxel Dörfler BMediaRoster::SetAudioOutput(const media_input& input)
65452a38012Sejakowatz {
65552a38012Sejakowatz 	CALLED();
65634c72144SAxel Dörfler 	return MediaRosterEx(this)->SetNode(AUDIO_OUTPUT, NULL, NULL, &input);
65752a38012Sejakowatz }
65852a38012Sejakowatz 
65952a38012Sejakowatz 
66052a38012Sejakowatz status_t
66152a38012Sejakowatz BMediaRoster::SetAudioOutput(const dormant_node_info& consumer)
66252a38012Sejakowatz {
66352a38012Sejakowatz 	CALLED();
6648b04ffc1Sbeveloper 	return MediaRosterEx(this)->SetNode(AUDIO_OUTPUT, NULL, &consumer);
66552a38012Sejakowatz }
66652a38012Sejakowatz 
66752a38012Sejakowatz 
66852a38012Sejakowatz status_t
66934c72144SAxel Dörfler BMediaRoster::GetNodeFor(media_node_id node, media_node* clone)
67052a38012Sejakowatz {
6719e9417d2Sbeveloper 	CALLED();
6729e9417d2Sbeveloper 	if (clone == NULL)
6739e9417d2Sbeveloper 		return B_BAD_VALUE;
67465b73ae4SMarcus Overhagen 	if (IS_INVALID_NODEID(node))
6759e9417d2Sbeveloper 		return B_MEDIA_BAD_NODE;
6769e9417d2Sbeveloper 
6779e9417d2Sbeveloper 	server_get_node_for_request request;
6789e9417d2Sbeveloper 	server_get_node_for_reply reply;
6799e9417d2Sbeveloper 	status_t rv;
6809e9417d2Sbeveloper 
6819dec2310SAxel Dörfler 	request.node_id = node;
6829dec2310SAxel Dörfler 	request.team = BPrivate::current_team();
6839e9417d2Sbeveloper 
68434c72144SAxel Dörfler 	rv = QueryServer(SERVER_GET_NODE_FOR, &request, sizeof(request), &reply,
68534c72144SAxel Dörfler 		sizeof(reply));
6869e9417d2Sbeveloper 	if (rv != B_OK)
6879e9417d2Sbeveloper 		return rv;
6889e9417d2Sbeveloper 
6899e9417d2Sbeveloper 	*clone = reply.clone;
6909e9417d2Sbeveloper 	return B_OK;
69152a38012Sejakowatz }
69252a38012Sejakowatz 
69352a38012Sejakowatz 
69452a38012Sejakowatz status_t
69552a38012Sejakowatz BMediaRoster::GetSystemTimeSource(media_node* clone)
69652a38012Sejakowatz {
69752a38012Sejakowatz 	CALLED();
69886bce45bSbeveloper 	status_t rv;
69986bce45bSbeveloper 
70034c72144SAxel Dörfler 	// TODO: need to do this in a nicer way.
70186bce45bSbeveloper 
70286bce45bSbeveloper 	rv = MediaRosterEx(this)->GetNode(SYSTEM_TIME_SOURCE, clone);
70386bce45bSbeveloper 	if (rv != B_OK)
70486bce45bSbeveloper 		return rv;
70586bce45bSbeveloper 
70686bce45bSbeveloper 	// We don't do reference counting for timesources, that's why we
70786bce45bSbeveloper 	// release the node immediately.
70886bce45bSbeveloper 	ReleaseNode(*clone);
70986bce45bSbeveloper 
71034c72144SAxel Dörfler 	// we need to remember to not use this node with server side reference
71134c72144SAxel Dörfler 	// counting
71286bce45bSbeveloper 	clone->kind |= NODE_KIND_NO_REFCOUNTING;
71386bce45bSbeveloper 
71486bce45bSbeveloper 	return B_OK;
71552a38012Sejakowatz }
71652a38012Sejakowatz 
71752a38012Sejakowatz 
71852a38012Sejakowatz status_t
71952a38012Sejakowatz BMediaRoster::ReleaseNode(const media_node& node)
72052a38012Sejakowatz {
7219e9417d2Sbeveloper 	CALLED();
72240f36b03Sbeveloper 	if (IS_INVALID_NODE(node))
7239e9417d2Sbeveloper 		return B_MEDIA_BAD_NODE;
72452a38012Sejakowatz 
72586bce45bSbeveloper 	if (node.kind & NODE_KIND_NO_REFCOUNTING) {
72634c72144SAxel Dörfler 		printf("BMediaRoster::ReleaseNode, trying to release reference "
72734c72144SAxel Dörfler 			"counting disabled timesource, node %ld, port %ld, team %ld\n",
7289dec2310SAxel Dörfler 			node.node, node.port, BPrivate::current_team());
72986bce45bSbeveloper 		return B_OK;
73086bce45bSbeveloper 	}
73186bce45bSbeveloper 
7329e9417d2Sbeveloper 	server_release_node_request request;
7339e9417d2Sbeveloper 	server_release_node_reply reply;
734cf4e2277Sbeveloper 	status_t rv;
7359e9417d2Sbeveloper 
7369e9417d2Sbeveloper 	request.node = node;
7379dec2310SAxel Dörfler 	request.team = BPrivate::current_team();
7389e9417d2Sbeveloper 
73934c72144SAxel Dörfler 	TRACE("BMediaRoster::ReleaseNode, node %ld, port %ld, team %ld\n",
7409dec2310SAxel Dörfler 		node.node, node.port, BPrivate::current_team());
741cf4e2277Sbeveloper 
74234c72144SAxel Dörfler 	rv = QueryServer(SERVER_RELEASE_NODE, &request, sizeof(request), &reply,
74334c72144SAxel Dörfler 		sizeof(reply));
744cf4e2277Sbeveloper 	if (rv != B_OK) {
74534c72144SAxel Dörfler 		ERROR("BMediaRoster::ReleaseNode FAILED, node %ld, port %ld, team "
7469dec2310SAxel Dörfler 			"%ld!\n", node.node, node.port, BPrivate::current_team());
747cf4e2277Sbeveloper 	}
748cf4e2277Sbeveloper 	return rv;
7499e9417d2Sbeveloper }
75052a38012Sejakowatz 
75134c72144SAxel Dörfler 
75252a38012Sejakowatz BTimeSource*
75334c72144SAxel Dörfler BMediaRoster::MakeTimeSourceFor(const media_node& forNode)
75452a38012Sejakowatz {
755f180ef79Sbeveloper 	// MakeTimeSourceFor() returns a BTimeSource object
756f180ef79Sbeveloper 	// corresponding to the specified node's time source.
757f180ef79Sbeveloper 
758835140c8Sbeveloper 	CALLED();
759f180ef79Sbeveloper 
76034c72144SAxel Dörfler 	if (IS_SYSTEM_TIMESOURCE(forNode)) {
761f180ef79Sbeveloper 		// special handling for the system time source
76234c72144SAxel Dörfler 		TRACE("BMediaRoster::MakeTimeSourceFor, asked for system time "
76334c72144SAxel Dörfler 			"source\n");
76434c72144SAxel Dörfler 		return MediaRosterEx(this)->MakeTimeSourceObject(
76534c72144SAxel Dörfler 			NODE_SYSTEM_TIMESOURCE_ID);
766f180ef79Sbeveloper 	}
767f180ef79Sbeveloper 
76834c72144SAxel Dörfler 	if (IS_INVALID_NODE(forNode)) {
76934c72144SAxel Dörfler 		ERROR("BMediaRoster::MakeTimeSourceFor: for_node invalid, node %ld, "
77034c72144SAxel Dörfler 			"port %ld, kinds 0x%lx\n", forNode.node, forNode.port,
77134c72144SAxel Dörfler 			forNode.kind);
7725917dd5bSbeveloper 		return NULL;
7730e21b167Sbeveloper 	}
7740e21b167Sbeveloper 
77534c72144SAxel Dörfler 	TRACE("BMediaRoster::MakeTimeSourceFor: node %ld enter\n", forNode.node);
7765917dd5bSbeveloper 
7775917dd5bSbeveloper 	node_get_timesource_request request;
7785917dd5bSbeveloper 	node_get_timesource_reply reply;
7795917dd5bSbeveloper 	BTimeSource *source;
7805917dd5bSbeveloper 	status_t rv;
7815917dd5bSbeveloper 
78292e575c1Sbeveloper 	// ask the node to get it's current timesource id
78334c72144SAxel Dörfler 	rv = QueryPort(forNode.port, NODE_GET_TIMESOURCE, &request,
78434c72144SAxel Dörfler 		sizeof(request), &reply, sizeof(reply));
7855917dd5bSbeveloper 	if (rv != B_OK) {
7865ac4fbd7Sbeveloper 		ERROR("BMediaRoster::MakeTimeSourceFor: request failed\n");
7875917dd5bSbeveloper 		return NULL;
7885917dd5bSbeveloper 	}
7895917dd5bSbeveloper 
7905917dd5bSbeveloper 	source = MediaRosterEx(this)->MakeTimeSourceObject(reply.timesource_id);
7915917dd5bSbeveloper 
79234c72144SAxel Dörfler 	TRACE("BMediaRoster::MakeTimeSourceFor: node %ld leave\n", forNode.node);
793287f7492Sbeveloper 
794835140c8Sbeveloper 	return source;
79552a38012Sejakowatz }
79652a38012Sejakowatz 
79752a38012Sejakowatz 
79852a38012Sejakowatz status_t
79934c72144SAxel Dörfler BMediaRoster::Connect(const media_source& from, const media_destination& to,
80034c72144SAxel Dörfler 	media_format* _format, media_output* _output, media_input* _input)
80152a38012Sejakowatz {
80234c72144SAxel Dörfler 	return BMediaRoster::Connect(from, to, _format, _output, _input, 0);
803eae26d3dSbeveloper }
804eae26d3dSbeveloper 
805eae26d3dSbeveloper 
806eae26d3dSbeveloper status_t
80734c72144SAxel Dörfler BMediaRoster::Connect(const media_source& from, const media_destination& to,
80834c72144SAxel Dörfler 	media_format* io_format, media_output* out_output, media_input* out_input,
80934c72144SAxel Dörfler 	uint32 in_flags, void* _reserved)
810eae26d3dSbeveloper {
81152a38012Sejakowatz 	CALLED();
81252a38012Sejakowatz 	if (io_format == NULL || out_output == NULL || out_input == NULL)
81352a38012Sejakowatz 		return B_BAD_VALUE;
81440f36b03Sbeveloper 	if (IS_INVALID_SOURCE(from)) {
8155ac4fbd7Sbeveloper 		ERROR("BMediaRoster::Connect: media_source invalid\n");
81652a38012Sejakowatz 		return B_MEDIA_BAD_SOURCE;
8179e9417d2Sbeveloper 	}
81840f36b03Sbeveloper 	if (IS_INVALID_DESTINATION(to)) {
8195ac4fbd7Sbeveloper 		ERROR("BMediaRoster::Connect: media_destination invalid\n");
82052a38012Sejakowatz 		return B_MEDIA_BAD_DESTINATION;
8219e9417d2Sbeveloper 	}
82252a38012Sejakowatz 
82352a38012Sejakowatz 	status_t rv;
82465b73ae4SMarcus Overhagen 
82565b73ae4SMarcus Overhagen 	// find the output and input nodes
82634c72144SAxel Dörfler 	// TODO: isn't there a easier way?
82765b73ae4SMarcus Overhagen 	media_node sourcenode;
82865b73ae4SMarcus Overhagen 	media_node destnode;
82965b73ae4SMarcus Overhagen 	rv = GetNodeFor(NodeIDFor(from.port), &sourcenode);
83065b73ae4SMarcus Overhagen 	if (rv != B_OK) {
83134c72144SAxel Dörfler 		ERROR("BMediaRoster::Connect: Can't find source node for port %ld\n",
83234c72144SAxel Dörfler 			from.port);
83365b73ae4SMarcus Overhagen 		return B_MEDIA_BAD_SOURCE;
83465b73ae4SMarcus Overhagen 	}
83565b73ae4SMarcus Overhagen 	ReleaseNode(sourcenode);
83665b73ae4SMarcus Overhagen 	rv = GetNodeFor(NodeIDFor(to.port), &destnode);
83765b73ae4SMarcus Overhagen 	if (rv != B_OK) {
83834c72144SAxel Dörfler 		ERROR("BMediaRoster::Connect: Can't find destination node for port "
83934c72144SAxel Dörfler 			"%ld\n", to.port);
84065b73ae4SMarcus Overhagen 		return B_MEDIA_BAD_DESTINATION;
84165b73ae4SMarcus Overhagen 	}
84265b73ae4SMarcus Overhagen 	ReleaseNode(destnode);
84365b73ae4SMarcus Overhagen 
84465b73ae4SMarcus Overhagen 	if (!(sourcenode.kind & B_BUFFER_PRODUCER)) {
84534c72144SAxel Dörfler 		ERROR("BMediaRoster::Connect: source node %ld is not a "
84634c72144SAxel Dörfler 			"B_BUFFER_PRODUCER\n", sourcenode.node);
84765b73ae4SMarcus Overhagen 		return B_MEDIA_BAD_SOURCE;
84865b73ae4SMarcus Overhagen 	}
84965b73ae4SMarcus Overhagen 	if (!(destnode.kind & B_BUFFER_CONSUMER)) {
85034c72144SAxel Dörfler 		ERROR("BMediaRoster::Connect: destination node %ld is not a "
85134c72144SAxel Dörfler 			"B_BUFFER_CONSUMER\n", destnode.node);
85265b73ae4SMarcus Overhagen 		return B_MEDIA_BAD_DESTINATION;
85365b73ae4SMarcus Overhagen 	}
85465b73ae4SMarcus Overhagen 
8558c6a6096Sbeveloper 	producer_format_proposal_request request1;
8568c6a6096Sbeveloper 	producer_format_proposal_reply reply1;
85752a38012Sejakowatz 
85834c72144SAxel Dörfler 	PRINT_FORMAT("BMediaRoster::Connect calling "
85934c72144SAxel Dörfler 		"BBufferProducer::FormatProposal with format  ", *io_format);
86069983609Sbeveloper 
86152a38012Sejakowatz 	// BBufferProducer::FormatProposal
8628c6a6096Sbeveloper 	request1.output = from;
8638c6a6096Sbeveloper 	request1.format = *io_format;
86434c72144SAxel Dörfler 	rv = QueryPort(from.port, PRODUCER_FORMAT_PROPOSAL, &request1,
86534c72144SAxel Dörfler 		sizeof(request1), &reply1, sizeof(reply1));
8668c6a6096Sbeveloper 	if (rv != B_OK) {
86734c72144SAxel Dörfler 		ERROR("BMediaRoster::Connect: aborted after "
86834c72144SAxel Dörfler 			"BBufferProducer::FormatProposal, status = %#lx\n",rv);
86952a38012Sejakowatz 		return rv;
87052a38012Sejakowatz 	}
8718c6a6096Sbeveloper 	// reply1.format now contains the format proposed by the producer
8728c6a6096Sbeveloper 
8738c6a6096Sbeveloper 	consumer_accept_format_request request2;
8748c6a6096Sbeveloper 	consumer_accept_format_reply reply2;
8758c6a6096Sbeveloper 
87634c72144SAxel Dörfler 	PRINT_FORMAT("BMediaRoster::Connect calling "
87734c72144SAxel Dörfler 		"BBufferConsumer::AcceptFormat with format    ", reply1.format);
87869983609Sbeveloper 
8798c6a6096Sbeveloper 	// BBufferConsumer::AcceptFormat
8808c6a6096Sbeveloper 	request2.dest = to;
8818c6a6096Sbeveloper 	request2.format = reply1.format;
88234c72144SAxel Dörfler 	rv = QueryPort(to.port, CONSUMER_ACCEPT_FORMAT, &request2,
88334c72144SAxel Dörfler 		sizeof(request2), &reply2, sizeof(reply2));
8848c6a6096Sbeveloper 	if (rv != B_OK) {
88534c72144SAxel Dörfler 		ERROR("BMediaRoster::Connect: aborted after "
88634c72144SAxel Dörfler 			"BBufferConsumer::AcceptFormat, status = %#lx\n",rv);
8878c6a6096Sbeveloper 		return rv;
8888c6a6096Sbeveloper 	}
8898c6a6096Sbeveloper 	// reply2.format now contains the format accepted by the consumer
8908c6a6096Sbeveloper 
8918c6a6096Sbeveloper 	// BBufferProducer::PrepareToConnect
8928c6a6096Sbeveloper 	producer_prepare_to_connect_request request3;
8938c6a6096Sbeveloper 	producer_prepare_to_connect_reply reply3;
8948c6a6096Sbeveloper 
89534c72144SAxel Dörfler 	PRINT_FORMAT("BMediaRoster::Connect calling "
89634c72144SAxel Dörfler 		"BBufferProducer::PrepareToConnect with format", reply2.format);
89769983609Sbeveloper 
8988c6a6096Sbeveloper 	request3.source = from;
8998c6a6096Sbeveloper 	request3.destination = to;
9008c6a6096Sbeveloper 	request3.format = reply2.format;
90134c72144SAxel Dörfler 	strcpy(request3.name, "XXX some default name"); // TODO: fix this
90234c72144SAxel Dörfler 	rv = QueryPort(from.port, PRODUCER_PREPARE_TO_CONNECT, &request3,
90334c72144SAxel Dörfler 		sizeof(request3), &reply3, sizeof(reply3));
9048c6a6096Sbeveloper 	if (rv != B_OK) {
90534c72144SAxel Dörfler 		ERROR("BMediaRoster::Connect: aborted after "
90634c72144SAxel Dörfler 			"BBufferProducer::PrepareToConnect, status = %#lx\n",rv);
9078c6a6096Sbeveloper 		return rv;
9088c6a6096Sbeveloper 	}
9098c6a6096Sbeveloper 	// reply3.format is still our pretty media format
9108c6a6096Sbeveloper 	// reply3.out_source the real source to be used for the connection
91134c72144SAxel Dörfler 	// reply3.name the name BBufferConsumer::Connected will see in the
91234c72144SAxel Dörfler 	// outInput->name argument
9138c6a6096Sbeveloper 
9148c6a6096Sbeveloper 	// BBufferConsumer::Connected
9158c6a6096Sbeveloper 	consumer_connected_request request4;
9168c6a6096Sbeveloper 	consumer_connected_reply reply4;
9178c6a6096Sbeveloper 	status_t con_status;
9188c6a6096Sbeveloper 
91934c72144SAxel Dörfler 	PRINT_FORMAT("BMediaRoster::Connect calling BBufferConsumer::Connected() "
92034c72144SAxel Dörfler 		"with format       ", reply3.format);
92169983609Sbeveloper 
92269983609Sbeveloper 	request4.input.node = destnode;
92369983609Sbeveloper 	request4.input.source = reply3.out_source;
92469983609Sbeveloper 	request4.input.destination = to;
92569983609Sbeveloper 	request4.input.format = reply3.format;
92669983609Sbeveloper 	strcpy(request4.input.name, reply3.name);
92769983609Sbeveloper 
92834c72144SAxel Dörfler 	con_status = QueryPort(to.port, CONSUMER_CONNECTED, &request4,
92934c72144SAxel Dörfler 		sizeof(request4), &reply4, sizeof(reply4));
9308c6a6096Sbeveloper 	if (con_status != B_OK) {
93134c72144SAxel Dörfler 		ERROR("BMediaRoster::Connect: aborting after "
93234c72144SAxel Dörfler 			"BBufferConsumer::Connected, status = %#lx\n",con_status);
9338c6a6096Sbeveloper 		// we do NOT return here!
9348c6a6096Sbeveloper 	}
93534c72144SAxel Dörfler 	// con_status contains the status code to be supplied to
93634c72144SAxel Dörfler 	// BBufferProducer::Connect's status argument
93734c72144SAxel Dörfler 	// reply4.input contains the media_input that describes the connection
93834c72144SAxel Dörfler 	// from the consumer point of view
9398c6a6096Sbeveloper 
9408c6a6096Sbeveloper 	// BBufferProducer::Connect
9418c6a6096Sbeveloper 	producer_connect_request request5;
9428c6a6096Sbeveloper 	producer_connect_reply reply5;
9438c6a6096Sbeveloper 
94434c72144SAxel Dörfler 	PRINT_FORMAT("BMediaRoster::Connect calling BBufferProducer::Connect with "
94534c72144SAxel Dörfler 		"format         ", reply4.input.format);
94669983609Sbeveloper 
9478c6a6096Sbeveloper 	request5.error = con_status;
9488c6a6096Sbeveloper 	request5.source = reply3.out_source;
9498c6a6096Sbeveloper 	request5.destination = reply4.input.destination;
95069983609Sbeveloper 	request5.format = reply4.input.format;
9518c6a6096Sbeveloper 	strcpy(request5.name, reply4.input.name);
95234c72144SAxel Dörfler 	rv = QueryPort(reply4.input.source.port, PRODUCER_CONNECT, &request5,
95334c72144SAxel Dörfler 		sizeof(request5), &reply5, sizeof(reply5));
9548c6a6096Sbeveloper 	if (con_status != B_OK) {
9555ac4fbd7Sbeveloper 		ERROR("BMediaRoster::Connect: aborted\n");
9568c6a6096Sbeveloper 		return con_status;
9578c6a6096Sbeveloper 	}
9588c6a6096Sbeveloper 	if (rv != B_OK) {
95934c72144SAxel Dörfler 		ERROR("BMediaRoster::Connect: aborted after BBufferProducer::Connect()"
96034c72144SAxel Dörfler 			", status = %#lx\n",rv);
9618c6a6096Sbeveloper 		return rv;
9628c6a6096Sbeveloper 	}
9638c6a6096Sbeveloper 	// reply5.name contains the name assigned to the connection by the producer
9648c6a6096Sbeveloper 
9658c6a6096Sbeveloper 	// initilize connection info
96669983609Sbeveloper 	*io_format = reply4.input.format;
9678c6a6096Sbeveloper 	*out_input = reply4.input;
9688c6a6096Sbeveloper 	out_output->node = sourcenode;
9698c6a6096Sbeveloper 	out_output->source = reply4.input.source;
9708c6a6096Sbeveloper 	out_output->destination = reply4.input.destination;
9718c6a6096Sbeveloper 	out_output->format = reply4.input.format;
9728c6a6096Sbeveloper 	strcpy(out_output->name, reply5.name);
9738c6a6096Sbeveloper 
9748c6a6096Sbeveloper 	// the connection is now made
97569983609Sbeveloper 	printf("BMediaRoster::Connect connection established!\n");
97669983609Sbeveloper 	PRINT_FORMAT("   format", *io_format);
97769983609Sbeveloper 	PRINT_INPUT("   input", *out_input);
97869983609Sbeveloper 	PRINT_OUTPUT("   output", *out_output);
9798c6a6096Sbeveloper 
98034c72144SAxel Dörfler 	// TODO: register connection with server
98134c72144SAxel Dörfler 	// TODO: we should just send a notification, instead of republishing all
98234c72144SAxel Dörfler 	// endpoints
98376669a29Sbeveloper 	List<media_output> outlist;
98476669a29Sbeveloper 	List<media_input> inlist;
98534c72144SAxel Dörfler 	if (MediaRosterEx(this)->GetAllOutputs(out_output->node , &outlist) == B_OK)
9868b04ffc1Sbeveloper 		MediaRosterEx(this)->PublishOutputs(out_output->node , &outlist);
98734c72144SAxel Dörfler 	if (MediaRosterEx(this)->GetAllInputs(out_input->node , &inlist) == B_OK)
9888b04ffc1Sbeveloper 		MediaRosterEx(this)->PublishInputs(out_input->node, &inlist);
9898c6a6096Sbeveloper 
99034c72144SAxel Dörfler 	// TODO: if (mute) BBufferProducer::EnableOutput(false)
9919e9417d2Sbeveloper 	if (in_flags & B_CONNECT_MUTED) {
9929e9417d2Sbeveloper 	}
9938c6a6096Sbeveloper 
9949e9417d2Sbeveloper 	// send a notification
99534c72144SAxel Dörfler 	BPrivate::media::notifications::ConnectionMade(*out_input, *out_output,
99634c72144SAxel Dörfler 		*io_format);
9979e9417d2Sbeveloper 
9988c6a6096Sbeveloper 	return B_OK;
9998c6a6096Sbeveloper };
100052a38012Sejakowatz 
100152a38012Sejakowatz 
100252a38012Sejakowatz status_t
10039e9417d2Sbeveloper BMediaRoster::Disconnect(media_node_id source_nodeid,
100434c72144SAxel Dörfler 	const media_source& source, media_node_id destination_nodeid,
100552a38012Sejakowatz 	const media_destination& destination)
100652a38012Sejakowatz {
10079e9417d2Sbeveloper 	CALLED();
100840f36b03Sbeveloper 	if (IS_INVALID_NODEID(source_nodeid)) {
10095ac4fbd7Sbeveloper 		ERROR("BMediaRoster::Disconnect: source media_node_id invalid\n");
10109e9417d2Sbeveloper 		return B_MEDIA_BAD_SOURCE;
10119e9417d2Sbeveloper 	}
101240f36b03Sbeveloper 	if (IS_INVALID_NODEID(destination_nodeid)) {
10135ac4fbd7Sbeveloper 		ERROR("BMediaRoster::Disconnect: destination media_node_id invalid\n");
10149e9417d2Sbeveloper 		return B_MEDIA_BAD_DESTINATION;
10159e9417d2Sbeveloper 	}
101640f36b03Sbeveloper 	if (IS_INVALID_SOURCE(source)) {
10175ac4fbd7Sbeveloper 		ERROR("BMediaRoster::Disconnect: media_source invalid\n");
10189e9417d2Sbeveloper 		return B_MEDIA_BAD_SOURCE;
10199e9417d2Sbeveloper 	}
102040f36b03Sbeveloper 	if (IS_INVALID_DESTINATION(destination)) {
10215ac4fbd7Sbeveloper 		ERROR("BMediaRoster::Disconnect: media_destination invalid\n");
10229e9417d2Sbeveloper 		return B_MEDIA_BAD_DESTINATION;
10239e9417d2Sbeveloper 	}
10249e9417d2Sbeveloper 
10259e9417d2Sbeveloper 	producer_disconnect_request request2;
10269e9417d2Sbeveloper 	producer_disconnect_reply reply2;
10279e9417d2Sbeveloper 	consumer_disconnected_request request1;
10289e9417d2Sbeveloper 	consumer_disconnected_reply reply1;
10299e9417d2Sbeveloper 	status_t rv1, rv2;
10309e9417d2Sbeveloper 
103134c72144SAxel Dörfler 	// TODO: we should ask the server if this connection really exists
10329e9417d2Sbeveloper 
10339e9417d2Sbeveloper 	request1.source = source;
10349e9417d2Sbeveloper 	request1.destination = destination;
10359e9417d2Sbeveloper 	request2.source = source;
10369e9417d2Sbeveloper 	request2.destination = destination;
10379e9417d2Sbeveloper 
103834c72144SAxel Dörfler 	rv1 = QueryPort(source.port, PRODUCER_DISCONNECT, &request1,
103934c72144SAxel Dörfler 		sizeof(request1), &reply1, sizeof(reply1));
104034c72144SAxel Dörfler 	rv2 = QueryPort(destination.port, CONSUMER_DISCONNECTED, &request2,
104134c72144SAxel Dörfler 		sizeof(request2), &reply2, sizeof(reply2));
10429e9417d2Sbeveloper 
104334c72144SAxel Dörfler 	// TODO: unregister connection with server
104434c72144SAxel Dörfler 	// TODO: we should just send a notification, instead of republishing all
104534c72144SAxel Dörfler 	// endpoints
104676669a29Sbeveloper 	List<media_output> outlist;
104776669a29Sbeveloper 	List<media_input> inlist;
10489e9417d2Sbeveloper 	media_node sourcenode;
10499e9417d2Sbeveloper 	media_node destnode;
105034c72144SAxel Dörfler 	if (GetNodeFor(source_nodeid, &sourcenode) == B_OK) {
105165b73ae4SMarcus Overhagen 		if (!(sourcenode.kind & B_BUFFER_PRODUCER)) {
105234c72144SAxel Dörfler 			ERROR("BMediaRoster::Disconnect: source_nodeid %ld is not a "
105334c72144SAxel Dörfler 				"B_BUFFER_PRODUCER\n", source_nodeid);
105465b73ae4SMarcus Overhagen 		}
105534c72144SAxel Dörfler 		if (MediaRosterEx(this)->GetAllOutputs(sourcenode , &outlist) == B_OK)
10568b04ffc1Sbeveloper 			MediaRosterEx(this)->PublishOutputs(sourcenode , &outlist);
10579e9417d2Sbeveloper 		ReleaseNode(sourcenode);
10584f09fa2fSbeveloper 	} else {
105965b73ae4SMarcus Overhagen 		ERROR("BMediaRoster::Disconnect: GetNodeFor source_nodeid %ld failed\n", source_nodeid);
10604f09fa2fSbeveloper 	}
106134c72144SAxel Dörfler 	if (GetNodeFor(destination_nodeid, &destnode) == B_OK) {
106265b73ae4SMarcus Overhagen 		if (!(destnode.kind & B_BUFFER_CONSUMER)) {
106334c72144SAxel Dörfler 			ERROR("BMediaRoster::Disconnect: destination_nodeid %ld is not a "
106434c72144SAxel Dörfler 				"B_BUFFER_CONSUMER\n", destination_nodeid);
106565b73ae4SMarcus Overhagen 		}
106634c72144SAxel Dörfler 		if (MediaRosterEx(this)->GetAllInputs(destnode , &inlist) == B_OK)
10678b04ffc1Sbeveloper 			MediaRosterEx(this)->PublishInputs(destnode, &inlist);
10689e9417d2Sbeveloper 		ReleaseNode(destnode);
10694f09fa2fSbeveloper 	} else {
107034c72144SAxel Dörfler 		ERROR("BMediaRoster::Disconnect: GetNodeFor destination_nodeid %ld "
107134c72144SAxel Dörfler 			"failed\n", destination_nodeid);
10724f09fa2fSbeveloper 	}
10739e9417d2Sbeveloper 
10749e9417d2Sbeveloper 	// send a notification
10759e9417d2Sbeveloper 	BPrivate::media::notifications::ConnectionBroken(source, destination);
10769e9417d2Sbeveloper 
107734c72144SAxel Dörfler 	return rv1 != B_OK || rv2 != B_OK ? B_ERROR : B_OK;
107852a38012Sejakowatz }
107952a38012Sejakowatz 
108034c72144SAxel Dörfler 
108165b73ae4SMarcus Overhagen status_t
108265b73ae4SMarcus Overhagen BMediaRoster::Disconnect(const media_output& output, const media_input& input)
108365b73ae4SMarcus Overhagen {
108465b73ae4SMarcus Overhagen 	if (IS_INVALID_NODEID(output.node.node)) {
108565b73ae4SMarcus Overhagen 		printf("BMediaRoster::Disconnect: output.node.node %ld invalid\n",
108665b73ae4SMarcus Overhagen 			output.node.node);
108765b73ae4SMarcus Overhagen 		return B_MEDIA_BAD_SOURCE;
108865b73ae4SMarcus Overhagen 	}
108965b73ae4SMarcus Overhagen 	if (IS_INVALID_NODEID(input.node.node)) {
109065b73ae4SMarcus Overhagen 		printf("BMediaRoster::Disconnect: input.node.node %ld invalid\n",
109165b73ae4SMarcus Overhagen 			input.node.node);
109265b73ae4SMarcus Overhagen 		return B_MEDIA_BAD_DESTINATION;
109365b73ae4SMarcus Overhagen 	}
109465b73ae4SMarcus Overhagen 	if (!(output.node.kind & B_BUFFER_PRODUCER)) {
109534c72144SAxel Dörfler 		printf("BMediaRoster::Disconnect: output.node.kind 0x%lx is no "
109634c72144SAxel Dörfler 			"B_BUFFER_PRODUCER\n", output.node.kind);
109765b73ae4SMarcus Overhagen 		return B_MEDIA_BAD_SOURCE;
109865b73ae4SMarcus Overhagen 	}
109965b73ae4SMarcus Overhagen 	if (!(input.node.kind & B_BUFFER_CONSUMER)) {
110034c72144SAxel Dörfler 		printf("BMediaRoster::Disconnect: input.node.kind 0x%lx is no "
110134c72144SAxel Dörfler 			"B_BUFFER_PRODUCER\n", input.node.kind);
110265b73ae4SMarcus Overhagen 		return B_MEDIA_BAD_DESTINATION;
110365b73ae4SMarcus Overhagen 	}
110465b73ae4SMarcus Overhagen 	if (input.source.port != output.source.port) {
110534c72144SAxel Dörfler 		printf("BMediaRoster::Disconnect: input.source.port %ld doesn't match "
110634c72144SAxel Dörfler 			"output.source.port %ld\n", input.source.port, output.source.port);
110765b73ae4SMarcus Overhagen 		return B_MEDIA_BAD_SOURCE;
110865b73ae4SMarcus Overhagen 	}
110965b73ae4SMarcus Overhagen 	if (input.source.id != output.source.id) {
111034c72144SAxel Dörfler 		printf("BMediaRoster::Disconnect: input.source.id %ld doesn't match "
111134c72144SAxel Dörfler 			"output.source.id %ld\n", input.source.id, output.source.id);
111265b73ae4SMarcus Overhagen 		return B_MEDIA_BAD_SOURCE;
111365b73ae4SMarcus Overhagen 	}
111465b73ae4SMarcus Overhagen 	if (input.destination.port != output.destination.port) {
111534c72144SAxel Dörfler 		printf("BMediaRoster::Disconnect: input.destination.port %ld doesn't "
111634c72144SAxel Dörfler 			"match output.destination.port %ld\n", input.destination.port,
111734c72144SAxel Dörfler 			output.destination.port);
111865b73ae4SMarcus Overhagen 		return B_MEDIA_BAD_DESTINATION;
111965b73ae4SMarcus Overhagen 	}
112065b73ae4SMarcus Overhagen 	if (input.destination.id != output.destination.id) {
112134c72144SAxel Dörfler 		printf("BMediaRoster::Disconnect: input.destination.id %ld doesn't "
112234c72144SAxel Dörfler 			"match output.destination.id %ld\n", input.destination.id,
112334c72144SAxel Dörfler 			output.destination.id);
112465b73ae4SMarcus Overhagen 		return B_MEDIA_BAD_DESTINATION;
112565b73ae4SMarcus Overhagen 	}
112634c72144SAxel Dörfler 
112734c72144SAxel Dörfler 	return Disconnect(output.node.node, output.source, input.node.node,
112834c72144SAxel Dörfler 		input.destination);
112965b73ae4SMarcus Overhagen }
113065b73ae4SMarcus Overhagen 
113152a38012Sejakowatz 
113252a38012Sejakowatz status_t
113334c72144SAxel Dörfler BMediaRoster::StartNode(const media_node& node, bigtime_t atPerformanceTime)
113452a38012Sejakowatz {
113552a38012Sejakowatz 	CALLED();
11369e9417d2Sbeveloper 	if (node.node <= 0)
113752a38012Sejakowatz 		return B_MEDIA_BAD_NODE;
113852a38012Sejakowatz 
113934c72144SAxel Dörfler 	TRACE("BMediaRoster::StartNode, node %ld, at perf %Ld\n", node.node,
114034c72144SAxel Dörfler 		atPerformanceTime);
11410e21b167Sbeveloper 
11426396865dSbeveloper 	node_start_command command;
114334c72144SAxel Dörfler 	command.performance_time = atPerformanceTime;
114452a38012Sejakowatz 
11456396865dSbeveloper 	return SendToPort(node.port, NODE_START, &command, sizeof(command));
114652a38012Sejakowatz }
114752a38012Sejakowatz 
114852a38012Sejakowatz 
114952a38012Sejakowatz status_t
115034c72144SAxel Dörfler BMediaRoster::StopNode(const media_node& node, bigtime_t atPerformanceTime,
115152a38012Sejakowatz 	bool immediate)
115252a38012Sejakowatz {
115352a38012Sejakowatz 	CALLED();
115440f36b03Sbeveloper 	if (IS_INVALID_NODE(node))
115552a38012Sejakowatz 		return B_MEDIA_BAD_NODE;
115652a38012Sejakowatz 
115734c72144SAxel Dörfler 	TRACE("BMediaRoster::StopNode, node %ld, at perf %Ld %s\n", node.node,
115834c72144SAxel Dörfler 		atPerformanceTime, immediate ? "NOW" : "");
11590e21b167Sbeveloper 
11606396865dSbeveloper 	node_stop_command command;
116134c72144SAxel Dörfler 	command.performance_time = atPerformanceTime;
11626396865dSbeveloper 	command.immediate = immediate;
116352a38012Sejakowatz 
11646396865dSbeveloper 	return SendToPort(node.port, NODE_STOP, &command, sizeof(command));
116552a38012Sejakowatz }
116652a38012Sejakowatz 
116752a38012Sejakowatz 
116852a38012Sejakowatz status_t
116934c72144SAxel Dörfler BMediaRoster::SeekNode(const media_node& node, bigtime_t toMediaTime,
117034c72144SAxel Dörfler 	bigtime_t atPerformanceTime)
117152a38012Sejakowatz {
117252a38012Sejakowatz 	CALLED();
117340f36b03Sbeveloper 	if (IS_INVALID_NODE(node))
117452a38012Sejakowatz 		return B_MEDIA_BAD_NODE;
117552a38012Sejakowatz 
117634c72144SAxel Dörfler 	TRACE("BMediaRoster::SeekNode, node %ld, at perf %Ld, to perf %Ld\n",
117734c72144SAxel Dörfler 		node.node, atPerformanceTime, toMediaTime);
11780e21b167Sbeveloper 
11796396865dSbeveloper 	node_seek_command command;
118034c72144SAxel Dörfler 	command.media_time = toMediaTime;
118134c72144SAxel Dörfler 	command.performance_time = atPerformanceTime;
118252a38012Sejakowatz 
11836396865dSbeveloper 	return SendToPort(node.port, NODE_SEEK, &command, sizeof(command));
118452a38012Sejakowatz }
118552a38012Sejakowatz 
118652a38012Sejakowatz 
118752a38012Sejakowatz status_t
118834c72144SAxel Dörfler BMediaRoster::StartTimeSource(const media_node& node, bigtime_t atRealTime)
118952a38012Sejakowatz {
119052a38012Sejakowatz 	CALLED();
119160f15390Sbeveloper 	if (IS_SYSTEM_TIMESOURCE(node)) {
119234c72144SAxel Dörfler 		// TODO: debug this
11935ac4fbd7Sbeveloper 		//ERROR("BMediaRoster::StartTimeSource node %ld is system timesource\n", node.node);
119460f15390Sbeveloper 		return B_OK;
119560f15390Sbeveloper 	}
119692e575c1Sbeveloper //	if (IS_SHADOW_TIMESOURCE(node)) {
119734c72144SAxel Dörfler //		// TODO: debug this
119892e575c1Sbeveloper //		ERROR("BMediaRoster::StartTimeSource node %ld is shadow timesource\n", node.node);
119992e575c1Sbeveloper //		return B_OK;
120092e575c1Sbeveloper //	}
120140f36b03Sbeveloper 	if (IS_INVALID_NODE(node)) {
12025ac4fbd7Sbeveloper 		ERROR("BMediaRoster::StartTimeSource node %ld invalid\n", node.node);
120352a38012Sejakowatz 		return B_MEDIA_BAD_NODE;
12040e21b167Sbeveloper 	}
12050e21b167Sbeveloper 	if ((node.kind & B_TIME_SOURCE) == 0) {
120634c72144SAxel Dörfler 		ERROR("BMediaRoster::StartTimeSource node %ld is no timesource\n",
120734c72144SAxel Dörfler 			node.node);
120852a38012Sejakowatz 		return B_MEDIA_BAD_NODE;
12090e21b167Sbeveloper 	}
12100e21b167Sbeveloper 
121134c72144SAxel Dörfler 	TRACE("BMediaRoster::StartTimeSource, node %ld, at real %Ld\n", node.node,
1212791a4a77SStephan Aßmus 		atRealTime);
121352a38012Sejakowatz 
121452a38012Sejakowatz 	BTimeSource::time_source_op_info msg;
121552a38012Sejakowatz 	msg.op = BTimeSource::B_TIMESOURCE_START;
121634c72144SAxel Dörfler 	msg.real_time = atRealTime;
121752a38012Sejakowatz 
121852a38012Sejakowatz 	return write_port(node.port, TIMESOURCE_OP, &msg, sizeof(msg));
121952a38012Sejakowatz }
122052a38012Sejakowatz 
122152a38012Sejakowatz 
122252a38012Sejakowatz status_t
122334c72144SAxel Dörfler BMediaRoster::StopTimeSource(const media_node& node, bigtime_t atRealTime,
122452a38012Sejakowatz 	bool immediate)
122552a38012Sejakowatz {
122652a38012Sejakowatz 	CALLED();
122760f15390Sbeveloper 	if (IS_SYSTEM_TIMESOURCE(node)) {
122834c72144SAxel Dörfler 		// TODO: debug this
12295ac4fbd7Sbeveloper 		//ERROR("BMediaRoster::StopTimeSource node %ld is system timesource\n", node.node);
123060f15390Sbeveloper 		return B_OK;
123160f15390Sbeveloper 	}
123292e575c1Sbeveloper //	if (IS_SHADOW_TIMESOURCE(node)) {
123334c72144SAxel Dörfler //		// TODO: debug this
123492e575c1Sbeveloper //		ERROR("BMediaRoster::StopTimeSource node %ld is shadow timesource\n", node.node);
123592e575c1Sbeveloper //		return B_OK;
123692e575c1Sbeveloper //	}
123740f36b03Sbeveloper 	if (IS_INVALID_NODE(node)) {
12385ac4fbd7Sbeveloper 		ERROR("BMediaRoster::StopTimeSource node %ld invalid\n", node.node);
123952a38012Sejakowatz 		return B_MEDIA_BAD_NODE;
12400e21b167Sbeveloper 	}
12410e21b167Sbeveloper 	if ((node.kind & B_TIME_SOURCE) == 0) {
124234c72144SAxel Dörfler 		ERROR("BMediaRoster::StopTimeSource node %ld is no timesource\n",
124334c72144SAxel Dörfler 			node.node);
124452a38012Sejakowatz 		return B_MEDIA_BAD_NODE;
12450e21b167Sbeveloper 	}
12460e21b167Sbeveloper 
124734c72144SAxel Dörfler 	TRACE("BMediaRoster::StopTimeSource, node %ld, at real %Ld %s\n",
124834c72144SAxel Dörfler 		node.node, atRealTime, immediate ? "NOW" : "");
124952a38012Sejakowatz 
125052a38012Sejakowatz 	BTimeSource::time_source_op_info msg;
125134c72144SAxel Dörfler 	msg.op = immediate ? BTimeSource::B_TIMESOURCE_STOP_IMMEDIATELY
125234c72144SAxel Dörfler 		: BTimeSource::B_TIMESOURCE_STOP;
125334c72144SAxel Dörfler 	msg.real_time = atRealTime;
125452a38012Sejakowatz 
125552a38012Sejakowatz 	return write_port(node.port, TIMESOURCE_OP, &msg, sizeof(msg));
125652a38012Sejakowatz }
125752a38012Sejakowatz 
125852a38012Sejakowatz 
125952a38012Sejakowatz status_t
126052a38012Sejakowatz BMediaRoster::SeekTimeSource(const media_node& node,
126134c72144SAxel Dörfler 	bigtime_t toPerformanceTime, bigtime_t atRealTime)
126252a38012Sejakowatz {
126352a38012Sejakowatz 	CALLED();
126460f15390Sbeveloper 	if (IS_SYSTEM_TIMESOURCE(node)) {
126534c72144SAxel Dörfler 		// TODO: debug this
12665ac4fbd7Sbeveloper 		// ERROR("BMediaRoster::SeekTimeSource node %ld is system timesource\n", node.node);
126760f15390Sbeveloper 		// you can't seek the system time source, but
126860f15390Sbeveloper 		// returning B_ERROR would break StampTV
126960f15390Sbeveloper 		return B_OK;
127060f15390Sbeveloper 	}
127192e575c1Sbeveloper //	if (IS_SHADOW_TIMESOURCE(node)) {
127234c72144SAxel Dörfler //		// TODO: debug this
127392e575c1Sbeveloper //		ERROR("BMediaRoster::SeekTimeSource node %ld is shadow timesource\n", node.node);
127492e575c1Sbeveloper //		return B_OK;
127592e575c1Sbeveloper //	}
127640f36b03Sbeveloper 	if (IS_INVALID_NODE(node)) {
12775ac4fbd7Sbeveloper 		ERROR("BMediaRoster::SeekTimeSource node %ld invalid\n", node.node);
127852a38012Sejakowatz 		return B_MEDIA_BAD_NODE;
12790e21b167Sbeveloper 	}
12800e21b167Sbeveloper 	if ((node.kind & B_TIME_SOURCE) == 0) {
128134c72144SAxel Dörfler 		ERROR("BMediaRoster::SeekTimeSource node %ld is no timesource\n",
128234c72144SAxel Dörfler 			node.node);
128352a38012Sejakowatz 		return B_MEDIA_BAD_NODE;
12840e21b167Sbeveloper 	}
12850e21b167Sbeveloper 
128634c72144SAxel Dörfler 	TRACE("BMediaRoster::SeekTimeSource, node %ld, at real %Ld, to perf %Ld\n",
128734c72144SAxel Dörfler 		node.node, atRealTime, toPerformanceTime);
128852a38012Sejakowatz 
128952a38012Sejakowatz 	BTimeSource::time_source_op_info msg;
129052a38012Sejakowatz 	msg.op = BTimeSource::B_TIMESOURCE_SEEK;
129134c72144SAxel Dörfler 	msg.real_time = atRealTime;
129234c72144SAxel Dörfler 	msg.performance_time = toPerformanceTime;
129352a38012Sejakowatz 
129452a38012Sejakowatz 	return write_port(node.port, TIMESOURCE_OP, &msg, sizeof(msg));
129552a38012Sejakowatz }
129652a38012Sejakowatz 
129752a38012Sejakowatz 
129852a38012Sejakowatz status_t
129934c72144SAxel Dörfler BMediaRoster::SyncToNode(const media_node& node, bigtime_t atTime,
130052a38012Sejakowatz 	bigtime_t timeout)
130152a38012Sejakowatz {
130252a38012Sejakowatz 	UNIMPLEMENTED();
130360f15390Sbeveloper 	return B_OK;
130452a38012Sejakowatz }
130552a38012Sejakowatz 
130652a38012Sejakowatz 
130752a38012Sejakowatz status_t
130834c72144SAxel Dörfler BMediaRoster::SetRunModeNode(const media_node& node, BMediaNode::run_mode mode)
130952a38012Sejakowatz {
131031cf24c1SMarcus Overhagen 	TRACE("BMediaRoster::SetRunModeNode, node %ld, mode %d\n", node.node, mode);
131140f36b03Sbeveloper 	if (IS_INVALID_NODE(node))
131252a38012Sejakowatz 		return B_MEDIA_BAD_NODE;
131352a38012Sejakowatz 
1314dfb2ad61Sbeveloper 	node_set_run_mode_command msg;
131552a38012Sejakowatz 	msg.mode = mode;
131652a38012Sejakowatz 
131752a38012Sejakowatz 	return write_port(node.port, NODE_SET_RUN_MODE, &msg, sizeof(msg));
131852a38012Sejakowatz }
131952a38012Sejakowatz 
132052a38012Sejakowatz 
132152a38012Sejakowatz status_t
132252a38012Sejakowatz BMediaRoster::PrerollNode(const media_node& node)
132352a38012Sejakowatz {
132452a38012Sejakowatz 	CALLED();
132540f36b03Sbeveloper 	if (IS_INVALID_NODE(node))
132652a38012Sejakowatz 		return B_MEDIA_BAD_NODE;
132752a38012Sejakowatz 
132852a38012Sejakowatz 	char dummy;
132952a38012Sejakowatz 	return write_port(node.port, NODE_PREROLL, &dummy, sizeof(dummy));
133052a38012Sejakowatz }
133152a38012Sejakowatz 
133252a38012Sejakowatz 
133352a38012Sejakowatz status_t
133434c72144SAxel Dörfler BMediaRoster::RollNode(const media_node& node, bigtime_t startPerformance,
133534c72144SAxel Dörfler 	bigtime_t stopPerformance, bigtime_t atMediaTime)
133652a38012Sejakowatz {
133752a38012Sejakowatz 	UNIMPLEMENTED();
133852a38012Sejakowatz 	return B_ERROR;
133952a38012Sejakowatz }
134052a38012Sejakowatz 
134152a38012Sejakowatz 
134252a38012Sejakowatz status_t
134352a38012Sejakowatz BMediaRoster::SetProducerRunModeDelay(const media_node& node,
134434c72144SAxel Dörfler 	bigtime_t delay, BMediaNode::run_mode mode)
134552a38012Sejakowatz {
134634c72144SAxel Dörfler 	TRACE("BMediaRoster::SetProducerRunModeDelay, node %ld, delay %Ld, "
134734c72144SAxel Dörfler 		"mode %d\n", node.node, delay, mode);
134860f15390Sbeveloper 	if (IS_INVALID_NODE(node))
134960f15390Sbeveloper 		return B_MEDIA_BAD_NODE;
135060f15390Sbeveloper 	if ((node.kind & B_BUFFER_PRODUCER) == 0)
135160f15390Sbeveloper 		return B_MEDIA_BAD_NODE;
135260f15390Sbeveloper 
135360f15390Sbeveloper 	producer_set_run_mode_delay_command command;
135460f15390Sbeveloper 	command.mode = mode;
135560f15390Sbeveloper 	command.delay = delay;
135660f15390Sbeveloper 
135734c72144SAxel Dörfler 	return SendToPort(node.port, PRODUCER_SET_RUN_MODE_DELAY, &command,
135834c72144SAxel Dörfler 		sizeof(command));
135952a38012Sejakowatz }
136052a38012Sejakowatz 
136152a38012Sejakowatz 
136252a38012Sejakowatz status_t
136334c72144SAxel Dörfler BMediaRoster::SetProducerRate(const media_node& producer, int32 numer,
136452a38012Sejakowatz 	int32 denom)
136552a38012Sejakowatz {
136652a38012Sejakowatz 	CALLED();
136740f36b03Sbeveloper 	if (IS_INVALID_NODE(producer))
136852a38012Sejakowatz 		return B_MEDIA_BAD_NODE;
136952a38012Sejakowatz 	if ((producer.kind & B_BUFFER_PRODUCER) == 0)
137052a38012Sejakowatz 		return B_MEDIA_BAD_NODE;
137152a38012Sejakowatz 
1372dfb2ad61Sbeveloper 	producer_set_play_rate_request msg;
1373dfb2ad61Sbeveloper 	producer_set_play_rate_reply reply;
137452a38012Sejakowatz 	status_t rv;
137552a38012Sejakowatz 	int32 code;
137652a38012Sejakowatz 
137752a38012Sejakowatz 	msg.numer = numer;
137852a38012Sejakowatz 	msg.denom = denom;
13799834d875SAxel Dörfler 	msg.reply_port = gPortPool->GetPort();
138052a38012Sejakowatz 	rv = write_port(producer.node, PRODUCER_SET_PLAY_RATE, &msg, sizeof(msg));
138152a38012Sejakowatz 	if (rv != B_OK) {
13829834d875SAxel Dörfler 		gPortPool->PutPort(msg.reply_port);
138352a38012Sejakowatz 		return rv;
138452a38012Sejakowatz 	}
138552a38012Sejakowatz 	rv = read_port(msg.reply_port, &code, &reply, sizeof(reply));
13869834d875SAxel Dörfler 	gPortPool->PutPort(msg.reply_port);
138752a38012Sejakowatz 	return (rv < B_OK) ? rv : reply.result;
138852a38012Sejakowatz }
138952a38012Sejakowatz 
139052a38012Sejakowatz 
139134c72144SAxel Dörfler /*!	Nodes will have available inputs/outputs as long as they are capable
139234c72144SAxel Dörfler 	of accepting more connections. The node may create an additional
139334c72144SAxel Dörfler 	output or input as the currently available is taken into usage.
139434c72144SAxel Dörfler */
139552a38012Sejakowatz status_t
139652a38012Sejakowatz BMediaRoster::GetLiveNodeInfo(const media_node& node,
139752a38012Sejakowatz 	live_node_info* out_live_info)
139852a38012Sejakowatz {
13999e9417d2Sbeveloper 	CALLED();
14009e9417d2Sbeveloper 	if (out_live_info == NULL)
14019e9417d2Sbeveloper 		return B_BAD_VALUE;
140240f36b03Sbeveloper 	if (IS_INVALID_NODE(node))
14039e9417d2Sbeveloper 		return B_MEDIA_BAD_NODE;
14049e9417d2Sbeveloper 
14059e9417d2Sbeveloper 	server_get_live_node_info_request request;
14069e9417d2Sbeveloper 	server_get_live_node_info_reply reply;
14079e9417d2Sbeveloper 	status_t rv;
14089e9417d2Sbeveloper 
14099e9417d2Sbeveloper 	request.node = node;
14109e9417d2Sbeveloper 
141134c72144SAxel Dörfler 	rv = QueryServer(SERVER_GET_LIVE_NODE_INFO, &request, sizeof(request),
141234c72144SAxel Dörfler 		&reply, sizeof(reply));
14139e9417d2Sbeveloper 	if (rv != B_OK)
14149e9417d2Sbeveloper 		return rv;
14159e9417d2Sbeveloper 
14169e9417d2Sbeveloper 	*out_live_info = reply.live_info;
14179e9417d2Sbeveloper 	return B_OK;
141852a38012Sejakowatz }
141952a38012Sejakowatz 
142052a38012Sejakowatz 
142152a38012Sejakowatz status_t
14229c3b4706SAxel Dörfler BMediaRoster::GetLiveNodes(live_node_info* liveNodes, int32* _totalCount,
142334c72144SAxel Dörfler 	const media_format* hasInput, const media_format* hasOutput,
142434c72144SAxel Dörfler 	const char* name, uint64 nodeKinds)
142552a38012Sejakowatz {
14269e9417d2Sbeveloper 	CALLED();
14279c3b4706SAxel Dörfler 	if (liveNodes == NULL || _totalCount == NULL || *_totalCount <= 0)
14289e9417d2Sbeveloper 		return B_BAD_VALUE;
14299e9417d2Sbeveloper 
143034c72144SAxel Dörfler 	// TODO: we also support the wildcard search as GetDormantNodes does.
143134c72144SAxel Dörfler 	// This needs to be documented
14329e9417d2Sbeveloper 
14339e9417d2Sbeveloper 	server_get_live_nodes_request request;
14349c3b4706SAxel Dörfler 	request.team = BPrivate::current_team();
14359e9417d2Sbeveloper 
14369c3b4706SAxel Dörfler 	request.max_count = *_totalCount;
143734c72144SAxel Dörfler 	request.has_input = hasInput != NULL;
143834c72144SAxel Dörfler 	if (hasInput != NULL) {
143934c72144SAxel Dörfler 		// TODO: we should not make a flat copy of media_format
14409c3b4706SAxel Dörfler 		request.input_format = *hasInput;
144134c72144SAxel Dörfler 	}
144234c72144SAxel Dörfler 	request.has_output = hasOutput != NULL;
144334c72144SAxel Dörfler 	if (hasOutput != NULL) {
144434c72144SAxel Dörfler 		// TODO: we should not make a flat copy of media_format
14459c3b4706SAxel Dörfler 		request.output_format = *hasOutput;
144634c72144SAxel Dörfler 	}
144734c72144SAxel Dörfler 	request.has_name = name != NULL;
14489c3b4706SAxel Dörfler 	if (name != NULL)
14499c3b4706SAxel Dörfler 		strlcpy(request.name, name, sizeof(request.name));
145034c72144SAxel Dörfler 	request.require_kinds = nodeKinds;
14519e9417d2Sbeveloper 
14529c3b4706SAxel Dörfler 	server_get_live_nodes_reply reply;
14539c3b4706SAxel Dörfler 	status_t status = QueryServer(SERVER_GET_LIVE_NODES, &request,
14549c3b4706SAxel Dörfler 		sizeof(request), &reply, sizeof(reply));
14559c3b4706SAxel Dörfler 	if (status != B_OK) {
14569c3b4706SAxel Dörfler 		ERROR("BMediaRoster::GetLiveNodes failed querying server: %s\n",
14579c3b4706SAxel Dörfler 			strerror(status));
145834c72144SAxel Dörfler 		*_totalCount = 0;
14599c3b4706SAxel Dörfler 		return status;
14609e9417d2Sbeveloper 	}
14619e9417d2Sbeveloper 
14629c3b4706SAxel Dörfler 	const live_node_info* info;
14639c3b4706SAxel Dörfler 	if (reply.area >= 0)
14649c3b4706SAxel Dörfler 		info = (live_node_info*)reply.address;
14659c3b4706SAxel Dörfler 	else
14669c3b4706SAxel Dörfler 		info = reply.live_info;
14679e9417d2Sbeveloper 
14689c3b4706SAxel Dörfler 	for (int32 i = 0; i < reply.count; i++)
14699c3b4706SAxel Dörfler 		liveNodes[i] = info[i];
14709c3b4706SAxel Dörfler 
14719c3b4706SAxel Dörfler 	if (reply.area >= 0)
14729e9417d2Sbeveloper 		delete_area(reply.area);
147352a38012Sejakowatz 
147434c72144SAxel Dörfler 	*_totalCount = reply.count;
14759e9417d2Sbeveloper 	return B_OK;
14769e9417d2Sbeveloper }
14779e9417d2Sbeveloper 
147852a38012Sejakowatz 
147952a38012Sejakowatz status_t
148052a38012Sejakowatz BMediaRoster::GetFreeInputsFor(const media_node& node,
148134c72144SAxel Dörfler 	media_input * out_free_inputs, int32 buf_num_inputs,
148234c72144SAxel Dörfler 	int32 * out_total_count, media_type filter_type)
148352a38012Sejakowatz {
14843620737cSbeveloper 	CALLED();
14855ac4fbd7Sbeveloper 	if (IS_INVALID_NODE(node)) {
148634c72144SAxel Dörfler 		ERROR("BMediaRoster::GetFreeInputsFor: node %ld, port %ld invalid\n",
148734c72144SAxel Dörfler 			node.node, node.port);
14883620737cSbeveloper 		return B_MEDIA_BAD_NODE;
14895ac4fbd7Sbeveloper 	}
14905ac4fbd7Sbeveloper 	if ((node.kind & B_BUFFER_CONSUMER) == 0) {
149134c72144SAxel Dörfler 		ERROR("BMediaRoster::GetFreeInputsFor: node %ld, port %ld is not a "
149234c72144SAxel Dörfler 			"consumer\n", node.node, node.port);
14935ac4fbd7Sbeveloper 		return B_MEDIA_BAD_NODE;
14945ac4fbd7Sbeveloper 	}
14953620737cSbeveloper 	if (out_free_inputs == NULL || out_total_count == NULL)
14963620737cSbeveloper 		return B_BAD_VALUE;
14973620737cSbeveloper 
149876669a29Sbeveloper 	List<media_input> list;
14993620737cSbeveloper 	media_input *input;
15003620737cSbeveloper 	status_t rv;
15013620737cSbeveloper 
15021299bfb2Sbeveloper 	*out_total_count = 0;
15031299bfb2Sbeveloper 
15048b04ffc1Sbeveloper 	rv = MediaRosterEx(this)->GetAllInputs(node, &list);
15053620737cSbeveloper 	if (B_OK != rv)
15063620737cSbeveloper 		return rv;
15073620737cSbeveloper 
150834c72144SAxel Dörfler 	PRINT(4, "BMediaRoster::GetFreeInputsFor node %ld, max %ld, filter-type "
150934c72144SAxel Dörfler 		"%ld\n", node.node, buf_num_inputs, filter_type);
15105ac4fbd7Sbeveloper 
151176669a29Sbeveloper 	int32 i;
1512b65a0ac5SJérôme Duval 	for (i = 0, list.Rewind(); list.GetNext(&input);) {
151334c72144SAxel Dörfler 		if (filter_type != B_MEDIA_UNKNOWN_TYPE
151434c72144SAxel Dörfler 			&& filter_type != input->format.type) {
151534c72144SAxel Dörfler 			// media_type used, but doesn't match
151634c72144SAxel Dörfler 			continue;
151734c72144SAxel Dörfler 		}
151834c72144SAxel Dörfler 		if (input->source != media_source::null) {
151934c72144SAxel Dörfler 			// consumer source already connected
152034c72144SAxel Dörfler 			continue;
152134c72144SAxel Dörfler 		}
152234c72144SAxel Dörfler 
15233620737cSbeveloper 		out_free_inputs[i] = *input;
15243620737cSbeveloper 		*out_total_count += 1;
15253620737cSbeveloper 		buf_num_inputs -= 1;
15265ac4fbd7Sbeveloper 		#if DEBUG >= 3
15275ac4fbd7Sbeveloper 			PRINT_OUTPUT("  input", out_free_inputs[i]);
15285ac4fbd7Sbeveloper 		#endif
15293620737cSbeveloper 		if (buf_num_inputs == 0)
15303620737cSbeveloper 			break;
1531b65a0ac5SJérôme Duval 		i++;
15323620737cSbeveloper 	}
15333620737cSbeveloper 
15348b04ffc1Sbeveloper 	MediaRosterEx(this)->PublishInputs(node, &list);
15353620737cSbeveloper 	return B_OK;
153652a38012Sejakowatz }
153752a38012Sejakowatz 
153852a38012Sejakowatz 
153952a38012Sejakowatz status_t
154052a38012Sejakowatz BMediaRoster::GetConnectedInputsFor(const media_node& node,
154134c72144SAxel Dörfler 	media_input* out_active_inputs, int32 buf_num_inputs,
154252a38012Sejakowatz 	int32* out_total_count)
154352a38012Sejakowatz {
15443620737cSbeveloper 	CALLED();
154540f36b03Sbeveloper 	if (IS_INVALID_NODE(node) || (node.kind & B_BUFFER_CONSUMER) == 0)
15463620737cSbeveloper 		return B_MEDIA_BAD_NODE;
15473620737cSbeveloper 	if (out_active_inputs == NULL || out_total_count == NULL)
15483620737cSbeveloper 		return B_BAD_VALUE;
15493620737cSbeveloper 
155076669a29Sbeveloper 	List<media_input> list;
15513620737cSbeveloper 	media_input *input;
15523620737cSbeveloper 	status_t rv;
15533620737cSbeveloper 
15541299bfb2Sbeveloper 	*out_total_count = 0;
15551299bfb2Sbeveloper 
15568b04ffc1Sbeveloper 	rv = MediaRosterEx(this)->GetAllInputs(node, &list);
15573620737cSbeveloper 	if (B_OK != rv)
15583620737cSbeveloper 		return rv;
15593620737cSbeveloper 
156034c72144SAxel Dörfler 	PRINT(4, "BMediaRoster::GetConnectedInputsFor node %ld, max %ld\n",
156134c72144SAxel Dörfler 		node.node, buf_num_inputs);
15625ac4fbd7Sbeveloper 
156376669a29Sbeveloper 	int32 i;
1564b65a0ac5SJérôme Duval 	for (i = 0, list.Rewind(); list.GetNext(&input);) {
15653620737cSbeveloper 		if (input->source == media_source::null)
15663620737cSbeveloper 			continue; // consumer source not connected
15673620737cSbeveloper 		out_active_inputs[i] = *input;
15683620737cSbeveloper 		*out_total_count += 1;
15693620737cSbeveloper 		buf_num_inputs -= 1;
15705ac4fbd7Sbeveloper 		#if DEBUG >= 3
15715ac4fbd7Sbeveloper 			PRINT_OUTPUT("  input ", out_active_inputs[i]);
15725ac4fbd7Sbeveloper 		#endif
15733620737cSbeveloper 		if (buf_num_inputs == 0)
15743620737cSbeveloper 			break;
1575b65a0ac5SJérôme Duval 		i++;
15763620737cSbeveloper 	}
15773620737cSbeveloper 
15788b04ffc1Sbeveloper 	MediaRosterEx(this)->PublishInputs(node, &list);
15793620737cSbeveloper 	return B_OK;
158052a38012Sejakowatz }
158152a38012Sejakowatz 
158252a38012Sejakowatz 
158352a38012Sejakowatz status_t
158434c72144SAxel Dörfler BMediaRoster::GetAllInputsFor(const media_node& node, media_input* out_inputs,
158534c72144SAxel Dörfler 	int32 buf_num_inputs, int32* out_total_count)
158652a38012Sejakowatz {
158752a38012Sejakowatz 	CALLED();
158840f36b03Sbeveloper 	if (IS_INVALID_NODE(node) || (node.kind & B_BUFFER_CONSUMER) == 0)
158952a38012Sejakowatz 		return B_MEDIA_BAD_NODE;
159052a38012Sejakowatz 	if (out_inputs == NULL || out_total_count == NULL)
159152a38012Sejakowatz 		return B_BAD_VALUE;
159252a38012Sejakowatz 
159376669a29Sbeveloper 	List<media_input> list;
15943620737cSbeveloper 	media_input *input;
159552a38012Sejakowatz 	status_t rv;
159652a38012Sejakowatz 
15971299bfb2Sbeveloper 	*out_total_count = 0;
15981299bfb2Sbeveloper 
15998b04ffc1Sbeveloper 	rv = MediaRosterEx(this)->GetAllInputs(node, &list);
16003620737cSbeveloper 	if (B_OK != rv)
16013620737cSbeveloper 		return rv;
16023620737cSbeveloper 
160334c72144SAxel Dörfler 	PRINT(4, "BMediaRoster::GetAllInputsFor node %ld, max %ld\n", node.node,
160434c72144SAxel Dörfler 		buf_num_inputs);
16055ac4fbd7Sbeveloper 
160676669a29Sbeveloper 	int32 i;
160776669a29Sbeveloper 	for (i = 0, list.Rewind(); list.GetNext(&input); i++) {
16083620737cSbeveloper 		out_inputs[i] = *input;
160952a38012Sejakowatz 		*out_total_count += 1;
16103620737cSbeveloper 		buf_num_inputs -= 1;
16115ac4fbd7Sbeveloper 		#if DEBUG >= 3
16125ac4fbd7Sbeveloper 			PRINT_OUTPUT("  input ", out_inputs[i]);
16135ac4fbd7Sbeveloper 		#endif
16143620737cSbeveloper 		if (buf_num_inputs == 0)
16153620737cSbeveloper 			break;
161652a38012Sejakowatz 	}
161752a38012Sejakowatz 
16188b04ffc1Sbeveloper 	MediaRosterEx(this)->PublishInputs(node, &list);
16193620737cSbeveloper 	return B_OK;
162052a38012Sejakowatz }
162152a38012Sejakowatz 
162252a38012Sejakowatz 
162352a38012Sejakowatz status_t
162452a38012Sejakowatz BMediaRoster::GetFreeOutputsFor(const media_node& node,
162534c72144SAxel Dörfler 	media_output* out_free_outputs, int32 buf_num_outputs,
162634c72144SAxel Dörfler 	int32* out_total_count, media_type filter_type)
162752a38012Sejakowatz {
16283620737cSbeveloper 	CALLED();
162940f36b03Sbeveloper 	if (IS_INVALID_NODE(node) || (node.kind & B_BUFFER_PRODUCER) == 0)
16303620737cSbeveloper 		return B_MEDIA_BAD_NODE;
16313620737cSbeveloper 	if (out_free_outputs == NULL || out_total_count == NULL)
16323620737cSbeveloper 		return B_BAD_VALUE;
16333620737cSbeveloper 
163476669a29Sbeveloper 	List<media_output> list;
16353620737cSbeveloper 	media_output *output;
16363620737cSbeveloper 	status_t rv;
16373620737cSbeveloper 
16381299bfb2Sbeveloper 	*out_total_count = 0;
16391299bfb2Sbeveloper 
16408b04ffc1Sbeveloper 	rv = MediaRosterEx(this)->GetAllOutputs(node, &list);
16413620737cSbeveloper 	if (B_OK != rv)
16423620737cSbeveloper 		return rv;
16433620737cSbeveloper 
164434c72144SAxel Dörfler 	PRINT(4, "BMediaRoster::GetFreeOutputsFor node %ld, max %ld, filter-type "
164534c72144SAxel Dörfler 		"%ld\n", node.node, buf_num_outputs, filter_type);
16465ac4fbd7Sbeveloper 
164776669a29Sbeveloper 	int32 i;
1648b65a0ac5SJérôme Duval 	for (i = 0, list.Rewind(); list.GetNext(&output);) {
164934c72144SAxel Dörfler 		if (filter_type != B_MEDIA_UNKNOWN_TYPE
165034c72144SAxel Dörfler 			&& filter_type != output->format.type) {
165134c72144SAxel Dörfler 			// media_type used, but doesn't match
165234c72144SAxel Dörfler 			continue;
165334c72144SAxel Dörfler 		}
165434c72144SAxel Dörfler 		if (output->destination != media_destination::null) {
165534c72144SAxel Dörfler 			// producer destination already connected
165634c72144SAxel Dörfler 			continue;
165734c72144SAxel Dörfler 		}
165834c72144SAxel Dörfler 
16593620737cSbeveloper 		out_free_outputs[i] = *output;
16603620737cSbeveloper 		*out_total_count += 1;
16613620737cSbeveloper 		buf_num_outputs -= 1;
16625ac4fbd7Sbeveloper 		#if DEBUG >= 3
16635ac4fbd7Sbeveloper 			PRINT_OUTPUT("  output ", out_free_outputs[i]);
16645ac4fbd7Sbeveloper 		#endif
16653620737cSbeveloper 		if (buf_num_outputs == 0)
16663620737cSbeveloper 			break;
1667b65a0ac5SJérôme Duval 		i++;
16683620737cSbeveloper 	}
16693620737cSbeveloper 
16708b04ffc1Sbeveloper 	MediaRosterEx(this)->PublishOutputs(node, &list);
16713620737cSbeveloper 	return B_OK;
167252a38012Sejakowatz }
167352a38012Sejakowatz 
167452a38012Sejakowatz 
167552a38012Sejakowatz status_t
167652a38012Sejakowatz BMediaRoster::GetConnectedOutputsFor(const media_node& node,
167734c72144SAxel Dörfler 	media_output* out_active_outputs, int32 buf_num_outputs,
167852a38012Sejakowatz 	int32* out_total_count)
167952a38012Sejakowatz {
16803620737cSbeveloper 	CALLED();
168140f36b03Sbeveloper 	if (IS_INVALID_NODE(node) || (node.kind & B_BUFFER_PRODUCER) == 0)
16823620737cSbeveloper 		return B_MEDIA_BAD_NODE;
16833620737cSbeveloper 	if (out_active_outputs == NULL || out_total_count == NULL)
16843620737cSbeveloper 		return B_BAD_VALUE;
16853620737cSbeveloper 
168676669a29Sbeveloper 	List<media_output> list;
16873620737cSbeveloper 	media_output *output;
16883620737cSbeveloper 	status_t rv;
16893620737cSbeveloper 
16901299bfb2Sbeveloper 	*out_total_count = 0;
16911299bfb2Sbeveloper 
16928b04ffc1Sbeveloper 	rv = MediaRosterEx(this)->GetAllOutputs(node, &list);
16933620737cSbeveloper 	if (B_OK != rv)
16943620737cSbeveloper 		return rv;
16953620737cSbeveloper 
169634c72144SAxel Dörfler 	PRINT(4, "BMediaRoster::GetConnectedOutputsFor node %ld, max %ld\n",
169734c72144SAxel Dörfler 		node.node, buf_num_outputs);
16985ac4fbd7Sbeveloper 
169976669a29Sbeveloper 	int32 i;
1700b65a0ac5SJérôme Duval 	for (i = 0, list.Rewind(); list.GetNext(&output);) {
170134c72144SAxel Dörfler 		if (output->destination == media_destination::null) {
170234c72144SAxel Dörfler 			// producer destination not connected
170334c72144SAxel Dörfler 			continue;
170434c72144SAxel Dörfler 		}
17053620737cSbeveloper 		out_active_outputs[i] = *output;
17063620737cSbeveloper 		*out_total_count += 1;
17073620737cSbeveloper 		buf_num_outputs -= 1;
17085ac4fbd7Sbeveloper 		#if DEBUG >= 3
17095ac4fbd7Sbeveloper 			PRINT_OUTPUT("  output ", out_active_outputs[i]);
17105ac4fbd7Sbeveloper 		#endif
17113620737cSbeveloper 		if (buf_num_outputs == 0)
17123620737cSbeveloper 			break;
1713b65a0ac5SJérôme Duval 		i++;
17143620737cSbeveloper 	}
17153620737cSbeveloper 
17168b04ffc1Sbeveloper 	MediaRosterEx(this)->PublishOutputs(node, &list);
17173620737cSbeveloper 	return B_OK;
171852a38012Sejakowatz }
171952a38012Sejakowatz 
172052a38012Sejakowatz 
172152a38012Sejakowatz status_t
172252a38012Sejakowatz BMediaRoster::GetAllOutputsFor(const media_node& node,
172334c72144SAxel Dörfler 	media_output* out_outputs, int32 buf_num_outputs, int32* out_total_count)
172452a38012Sejakowatz {
172552a38012Sejakowatz 	CALLED();
172640f36b03Sbeveloper 	if (IS_INVALID_NODE(node) || (node.kind & B_BUFFER_PRODUCER) == 0)
172752a38012Sejakowatz 		return B_MEDIA_BAD_NODE;
172852a38012Sejakowatz 	if (out_outputs == NULL || out_total_count == NULL)
172952a38012Sejakowatz 		return B_BAD_VALUE;
173052a38012Sejakowatz 
173176669a29Sbeveloper 	List<media_output> list;
17323620737cSbeveloper 	media_output *output;
173352a38012Sejakowatz 	status_t rv;
173452a38012Sejakowatz 
17351299bfb2Sbeveloper 	*out_total_count = 0;
17361299bfb2Sbeveloper 
17378b04ffc1Sbeveloper 	rv = MediaRosterEx(this)->GetAllOutputs(node, &list);
17383620737cSbeveloper 	if (B_OK != rv)
17393620737cSbeveloper 		return rv;
17403620737cSbeveloper 
174134c72144SAxel Dörfler 	PRINT(4, "BMediaRoster::GetAllOutputsFor node %ld, max %ld\n", node.node,
174234c72144SAxel Dörfler 		buf_num_outputs);
17435ac4fbd7Sbeveloper 
174476669a29Sbeveloper 	int32 i;
174576669a29Sbeveloper 	for (i = 0, list.Rewind(); list.GetNext(&output); i++) {
17463620737cSbeveloper 		out_outputs[i] = *output;
174752a38012Sejakowatz 		*out_total_count += 1;
17483620737cSbeveloper 		buf_num_outputs -= 1;
17495ac4fbd7Sbeveloper 		#if DEBUG >= 3
17505ac4fbd7Sbeveloper 			PRINT_OUTPUT("  output ", out_outputs[i]);
17515ac4fbd7Sbeveloper 		#endif
17523620737cSbeveloper 		if (buf_num_outputs == 0)
17533620737cSbeveloper 			break;
175452a38012Sejakowatz 	}
175552a38012Sejakowatz 
17568b04ffc1Sbeveloper 	MediaRosterEx(this)->PublishOutputs(node, &list);
17573620737cSbeveloper 	return B_OK;
175852a38012Sejakowatz }
175952a38012Sejakowatz 
176052a38012Sejakowatz 
176152a38012Sejakowatz status_t
176252a38012Sejakowatz BMediaRoster::StartWatching(const BMessenger& where)
176352a38012Sejakowatz {
1764eae26d3dSbeveloper 	CALLED();
1765eae26d3dSbeveloper 	if (!where.IsValid()) {
17665ac4fbd7Sbeveloper 		ERROR("BMediaRoster::StartWatching: messenger invalid!\n");
1767eae26d3dSbeveloper 		return B_BAD_VALUE;
1768eae26d3dSbeveloper 	}
176934c72144SAxel Dörfler 	return BPrivate::media::notifications::Register(where, media_node::null,
177034c72144SAxel Dörfler 		B_MEDIA_WILDCARD);
177152a38012Sejakowatz }
177252a38012Sejakowatz 
177352a38012Sejakowatz 
177452a38012Sejakowatz status_t
177534c72144SAxel Dörfler BMediaRoster::StartWatching(const BMessenger & where, int32 notificationType)
177652a38012Sejakowatz {
1777eae26d3dSbeveloper 	CALLED();
1778eae26d3dSbeveloper 	if (!where.IsValid()) {
17795ac4fbd7Sbeveloper 		ERROR("BMediaRoster::StartWatching: messenger invalid!\n");
1780eae26d3dSbeveloper 		return B_BAD_VALUE;
1781eae26d3dSbeveloper 	}
178234c72144SAxel Dörfler 	if (!BPrivate::media::notifications::IsValidNotificationRequest(false,
178334c72144SAxel Dörfler 			notificationType)) {
17845ac4fbd7Sbeveloper 		ERROR("BMediaRoster::StartWatching: notificationType invalid!\n");
1785eae26d3dSbeveloper 		return B_BAD_VALUE;
1786eae26d3dSbeveloper 	}
178734c72144SAxel Dörfler 	return BPrivate::media::notifications::Register(where, media_node::null,
178834c72144SAxel Dörfler 		notificationType);
178952a38012Sejakowatz }
179052a38012Sejakowatz 
179152a38012Sejakowatz 
179252a38012Sejakowatz status_t
179334c72144SAxel Dörfler BMediaRoster::StartWatching(const BMessenger& where, const media_node& node,
179452a38012Sejakowatz 	int32 notificationType)
179552a38012Sejakowatz {
1796eae26d3dSbeveloper 	CALLED();
1797eae26d3dSbeveloper 	if (!where.IsValid()) {
17985ac4fbd7Sbeveloper 		ERROR("BMediaRoster::StartWatching: messenger invalid!\n");
1799eae26d3dSbeveloper 		return B_BAD_VALUE;
1800eae26d3dSbeveloper 	}
180140f36b03Sbeveloper 	if (IS_INVALID_NODE(node)) {
18025ac4fbd7Sbeveloper 		ERROR("BMediaRoster::StartWatching: node invalid!\n");
1803eae26d3dSbeveloper 		return B_MEDIA_BAD_NODE;
1804eae26d3dSbeveloper 	}
180534c72144SAxel Dörfler 	if (!BPrivate::media::notifications::IsValidNotificationRequest(true,
180634c72144SAxel Dörfler 			notificationType)) {
18075ac4fbd7Sbeveloper 		ERROR("BMediaRoster::StartWatching: notificationType invalid!\n");
1808eae26d3dSbeveloper 		return B_BAD_VALUE;
1809eae26d3dSbeveloper 	}
181034c72144SAxel Dörfler 	return BPrivate::media::notifications::Register(where, node,
181134c72144SAxel Dörfler 		notificationType);
181252a38012Sejakowatz }
181352a38012Sejakowatz 
181452a38012Sejakowatz 
181552a38012Sejakowatz status_t
181652a38012Sejakowatz BMediaRoster::StopWatching(const BMessenger& where)
181752a38012Sejakowatz {
1818eae26d3dSbeveloper 	CALLED();
1819eae26d3dSbeveloper 	// messenger may already be invalid, so we don't check this
182034c72144SAxel Dörfler 	return BPrivate::media::notifications::Unregister(where, media_node::null,
182134c72144SAxel Dörfler 		B_MEDIA_WILDCARD);
182252a38012Sejakowatz }
182352a38012Sejakowatz 
182452a38012Sejakowatz 
182552a38012Sejakowatz status_t
182634c72144SAxel Dörfler BMediaRoster::StopWatching(const BMessenger& where, int32 notificationType)
182752a38012Sejakowatz {
1828eae26d3dSbeveloper 	CALLED();
1829eae26d3dSbeveloper 	// messenger may already be invalid, so we don't check this
183034c72144SAxel Dörfler 	if (!BPrivate::media::notifications::IsValidNotificationRequest(false,
183134c72144SAxel Dörfler 			notificationType)) {
18325ac4fbd7Sbeveloper 		ERROR("BMediaRoster::StopWatching: notificationType invalid!\n");
1833eae26d3dSbeveloper 		return B_BAD_VALUE;
1834eae26d3dSbeveloper 	}
183534c72144SAxel Dörfler 	return BPrivate::media::notifications::Unregister(where, media_node::null,
183634c72144SAxel Dörfler 		notificationType);
183752a38012Sejakowatz }
183852a38012Sejakowatz 
183952a38012Sejakowatz 
184052a38012Sejakowatz status_t
184134c72144SAxel Dörfler BMediaRoster::StopWatching(const BMessenger& where, const media_node& node,
184252a38012Sejakowatz 	int32 notificationType)
184352a38012Sejakowatz {
1844eae26d3dSbeveloper 	CALLED();
1845eae26d3dSbeveloper 	// messenger may already be invalid, so we don't check this
184640f36b03Sbeveloper 	if (IS_INVALID_NODE(node)) {
18475ac4fbd7Sbeveloper 		ERROR("BMediaRoster::StopWatching: node invalid!\n");
1848eae26d3dSbeveloper 		return B_MEDIA_BAD_NODE;
1849eae26d3dSbeveloper 	}
185034c72144SAxel Dörfler 	if (!BPrivate::media::notifications::IsValidNotificationRequest(true,
185134c72144SAxel Dörfler 			notificationType)) {
18525ac4fbd7Sbeveloper 		ERROR("BMediaRoster::StopWatching: notificationType invalid!\n");
1853eae26d3dSbeveloper 		return B_BAD_VALUE;
1854eae26d3dSbeveloper 	}
185534c72144SAxel Dörfler 	return BPrivate::media::notifications::Unregister(where, node,
185634c72144SAxel Dörfler 		notificationType);
185752a38012Sejakowatz }
185852a38012Sejakowatz 
185952a38012Sejakowatz 
186052a38012Sejakowatz status_t
186152a38012Sejakowatz BMediaRoster::RegisterNode(BMediaNode* node)
186252a38012Sejakowatz {
186354187cc6Sbeveloper 	CALLED();
186454187cc6Sbeveloper 	// addon-id = -1 (unused), addon-flavor-id = 0 (unused, too)
186554187cc6Sbeveloper 	return MediaRosterEx(this)->RegisterNode(node, -1, 0);
186654187cc6Sbeveloper }
186754187cc6Sbeveloper 
186854187cc6Sbeveloper 
186954187cc6Sbeveloper status_t
18709c3b4706SAxel Dörfler BMediaRosterEx::RegisterNode(BMediaNode* node, media_addon_id addOnID,
18719dec2310SAxel Dörfler 	int32 flavorID)
187254187cc6Sbeveloper {
187352a38012Sejakowatz 	CALLED();
187452a38012Sejakowatz 	if (node == NULL)
187552a38012Sejakowatz 		return B_BAD_VALUE;
187652a38012Sejakowatz 
187754187cc6Sbeveloper 	// some sanity check
187854187cc6Sbeveloper 	// I'm not sure if the media kit warrants to call BMediaNode::AddOn() here.
187954187cc6Sbeveloper 	// Perhaps we don't need it.
18809dec2310SAxel Dörfler 	DEBUG_ONLY(
18819dec2310SAxel Dörfler 		int32 testFlavorID;
18829dec2310SAxel Dörfler 		BMediaAddOn* addon = node->AddOn(&testFlavorID);
18839dec2310SAxel Dörfler 
18849c3b4706SAxel Dörfler 		ASSERT(addOnID == addon != NULL ? addon->AddonID() : -1);
18859dec2310SAxel Dörfler 		ASSERT(flavorID == testFlavorID);
18869dec2310SAxel Dörfler 	);
188752a38012Sejakowatz 
18889e9417d2Sbeveloper 	server_register_node_request request;
18899e9417d2Sbeveloper 	server_register_node_reply reply;
18909e9417d2Sbeveloper 
18919c3b4706SAxel Dörfler 	request.add_on_id = addOnID;
18929c3b4706SAxel Dörfler 	request.flavor_id = flavorID;
18939e9417d2Sbeveloper 	strcpy(request.name, node->Name());
18949e9417d2Sbeveloper 	request.kinds = node->Kinds();
18959e9417d2Sbeveloper 	request.port = node->ControlPort();
18969dec2310SAxel Dörfler 	request.team = BPrivate::current_team();
18979e9417d2Sbeveloper 
189834c72144SAxel Dörfler 	TRACE("BMediaRoster::RegisterNode: sending SERVER_REGISTER_NODE: port "
189934c72144SAxel Dörfler 		"%ld, kinds 0x%Lx, team %ld, name '%s'\n", request.port, request.kinds,
190034c72144SAxel Dörfler 		request.team, request.name);
19011299bfb2Sbeveloper 
19029c3b4706SAxel Dörfler 	status_t status = QueryServer(SERVER_REGISTER_NODE, &request,
19039c3b4706SAxel Dörfler 		sizeof(request), &reply, sizeof(reply));
19049c3b4706SAxel Dörfler 	if (status != B_OK) {
19059c3b4706SAxel Dörfler 		ERROR("BMediaRoster::RegisterNode: failed to register node %s: %s\n",
19069c3b4706SAxel Dörfler 			node->Name(), strerror(status));
19079c3b4706SAxel Dörfler 		return status;
19089e9417d2Sbeveloper 	}
19099e9417d2Sbeveloper 
191034c72144SAxel Dörfler 	TRACE("BMediaRoster::RegisterNode: QueryServer SERVER_REGISTER_NODE "
191134c72144SAxel Dörfler 		"finished\n");
19124295907bSbeveloper 
19138b04ffc1Sbeveloper 	// we are a friend class of BMediaNode and initialize this member variable
19149dec2310SAxel Dörfler 	node->fNodeID = reply.node_id;
19159dec2310SAxel Dörfler 	ASSERT(reply.node_id == node->Node().node);
19169dec2310SAxel Dörfler 	ASSERT(reply.node_id == node->ID());
19179e9417d2Sbeveloper 
19189e9417d2Sbeveloper 	// call the callback
19199e9417d2Sbeveloper 	node->NodeRegistered();
19203620737cSbeveloper 
19214295907bSbeveloper 	TRACE("BMediaRoster::RegisterNode: NodeRegistered callback finished\n");
19224295907bSbeveloper 
192334c72144SAxel Dörfler 	// if the BMediaNode also inherits from BTimeSource, we need to call
192434c72144SAxel Dörfler 	// BTimeSource::FinishCreate()
19259c3b4706SAxel Dörfler 	if ((node->Kinds() & B_TIME_SOURCE) != 0) {
19269c3b4706SAxel Dörfler 		if (BTimeSource* timeSource = dynamic_cast<BTimeSource*>(node))
19279c3b4706SAxel Dörfler 			timeSource->FinishCreate();
19280e21b167Sbeveloper 	}
19290e21b167Sbeveloper 
19304295907bSbeveloper 	TRACE("BMediaRoster::RegisterNode: publishing inputs/outputs\n");
19314295907bSbeveloper 
19323620737cSbeveloper 	// register existing inputs and outputs with the
19333620737cSbeveloper 	// media_server, this allows GetLiveNodes() to work
19343620737cSbeveloper 	// with created, but unconnected nodes.
19354d2d96e0Sbeveloper 	// The node control loop might not be running, or might deadlock
19364d2d96e0Sbeveloper 	// if we send a message and wait for a reply here.
19374d2d96e0Sbeveloper 	// We have a pointer to the node, and thus call the functions directly
19384295907bSbeveloper 
19399c3b4706SAxel Dörfler 	if ((node->Kinds() & B_BUFFER_PRODUCER) != 0) {
19409c3b4706SAxel Dörfler 		if (BBufferProducer* producer = dynamic_cast<BBufferProducer*>(node)) {
1941359ac306Sbeveloper 			List<media_output> list;
19429c3b4706SAxel Dörfler 			if (GetAllOutputs(producer, &list) == B_OK)
1943359ac306Sbeveloper 				PublishOutputs(node->Node(), &list);
194421871f38Sbeveloper 		}
19454d2d96e0Sbeveloper 	}
19469dec2310SAxel Dörfler 	if ((node->Kinds() & B_BUFFER_CONSUMER) != 0) {
19479c3b4706SAxel Dörfler 		if (BBufferConsumer* consumer = dynamic_cast<BBufferConsumer*>(node)) {
1948359ac306Sbeveloper 			List<media_input> list;
19499dec2310SAxel Dörfler 			if (GetAllInputs(consumer, &list) == B_OK)
1950359ac306Sbeveloper 				PublishInputs(node->Node(), &list);
19513620737cSbeveloper 		}
19524d2d96e0Sbeveloper 	}
195321871f38Sbeveloper 
19544295907bSbeveloper 	TRACE("BMediaRoster::RegisterNode: sending NodesCreated\n");
19554295907bSbeveloper 
19569dec2310SAxel Dörfler 	BPrivate::media::notifications::NodesCreated(&reply.node_id, 1);
19574295907bSbeveloper 
19584295907bSbeveloper 	TRACE("BMediaRoster::RegisterNode: finished\n");
19594295907bSbeveloper 
1960570f7d04Sbeveloper /*
19619c3b4706SAxel Dörfler 	TRACE("BMediaRoster::RegisterNode: registered node name '%s', id %ld,
19629c3b4706SAxel Dörfler 		addon %ld, flavor %ld\n", node->Name(), node->ID(), addOnID, flavorID);
1963570f7d04Sbeveloper 	TRACE("BMediaRoster::RegisterNode: node this               %p\n", node);
19649c3b4706SAxel Dörfler 	TRACE("BMediaRoster::RegisterNode: node fConsumerThis      %p\n",
19659c3b4706SAxel Dörfler 		node->fConsumerThis);
19669c3b4706SAxel Dörfler 	TRACE("BMediaRoster::RegisterNode: node fProducerThis      %p\n",
19679c3b4706SAxel Dörfler 		node->fProducerThis);
19689c3b4706SAxel Dörfler 	TRACE("BMediaRoster::RegisterNode: node fFileInterfaceThis %p\n",
19699c3b4706SAxel Dörfler 		node->fFileInterfaceThis);
19709c3b4706SAxel Dörfler 	TRACE("BMediaRoster::RegisterNode: node fControllableThis  %p\n",
19719c3b4706SAxel Dörfler 		node->fControllableThis);
19729c3b4706SAxel Dörfler 	TRACE("BMediaRoster::RegisterNode: node fTimeSourceThis    %p\n",
19739c3b4706SAxel Dörfler 		node->fTimeSourceThis);
1974570f7d04Sbeveloper */
19759e9417d2Sbeveloper 	return B_OK;
197652a38012Sejakowatz }
197752a38012Sejakowatz 
197852a38012Sejakowatz 
197952a38012Sejakowatz status_t
198052a38012Sejakowatz BMediaRoster::UnregisterNode(BMediaNode* node)
198152a38012Sejakowatz {
19829e9417d2Sbeveloper 	CALLED();
19839e9417d2Sbeveloper 	if (node == NULL)
19849e9417d2Sbeveloper 		return B_BAD_VALUE;
19859e9417d2Sbeveloper 
198660f15390Sbeveloper 	TRACE("BMediaRoster::UnregisterNode %ld (%p)\n", node->ID(), node);
198760f15390Sbeveloper 
198829bb91d6SAxel Dörfler 	if ((node->fKinds & NODE_KIND_NO_REFCOUNTING) !=0) {
198934c72144SAxel Dörfler 		TRACE("BMediaRoster::UnregisterNode, trying to unregister reference "
199034c72144SAxel Dörfler 			"counting disabled timesource, node %ld, port %ld, team %ld\n",
19919dec2310SAxel Dörfler 			node->ID(), node->ControlPort(), BPrivate::current_team());
199286bce45bSbeveloper 		return B_OK;
199386bce45bSbeveloper 	}
19948b04ffc1Sbeveloper 	if (node->ID() == NODE_UNREGISTERED_ID) {
199534c72144SAxel Dörfler 		PRINT(1, "Warning: BMediaRoster::UnregisterNode: node id %ld, name "
199634c72144SAxel Dörfler 			"'%s' already unregistered\n", node->ID(), node->Name());
19979e9417d2Sbeveloper 		return B_OK;
19989e9417d2Sbeveloper 	}
199954187cc6Sbeveloper 	if (node->fRefCount != 0) {
200034c72144SAxel Dörfler 		PRINT(1, "Warning: BMediaRoster::UnregisterNode: node id %ld, name "
200134c72144SAxel Dörfler 			"'%s' has local reference count of %ld\n", node->ID(), node->Name(),
200234c72144SAxel Dörfler 			node->fRefCount);
200354187cc6Sbeveloper 		// no return here, we continue and unregister!
200454187cc6Sbeveloper 	}
200554187cc6Sbeveloper 
200634c72144SAxel Dörfler 	// Calling BMediaAddOn::GetConfigurationFor(BMediaNode *node,
200734c72144SAxel Dörfler 	// BMessage *config) if this node was instanciated by an add-on needs to
200834c72144SAxel Dörfler 	// be done *somewhere*
200954187cc6Sbeveloper 	// We can't do it here because it is already to late (destructor of the node
201054187cc6Sbeveloper 	// might have been called).
20119e9417d2Sbeveloper 
20129e9417d2Sbeveloper 	server_unregister_node_request request;
20139dec2310SAxel Dörfler 	request.node_id = node->ID();
20149dec2310SAxel Dörfler 	request.team = BPrivate::current_team();
20159e9417d2Sbeveloper 
20161299bfb2Sbeveloper 	// send a notification
20179dec2310SAxel Dörfler 	BPrivate::media::notifications::NodesDeleted(&request.node_id, 1);
20181299bfb2Sbeveloper 
201929bb91d6SAxel Dörfler 	server_unregister_node_reply reply;
202029bb91d6SAxel Dörfler 	status_t status = QueryServer(SERVER_UNREGISTER_NODE, &request,
202129bb91d6SAxel Dörfler 		sizeof(request), &reply, sizeof(reply));
202229bb91d6SAxel Dörfler 	if (status != B_OK) {
202334c72144SAxel Dörfler 		ERROR("BMediaRoster::UnregisterNode: failed to unregister node id %ld, "
202429bb91d6SAxel Dörfler 			"name '%s': %s\n", node->ID(), node->Name(), strerror(status));
202529bb91d6SAxel Dörfler 		return status;
20269e9417d2Sbeveloper 	}
20279e9417d2Sbeveloper 
20289c3b4706SAxel Dörfler 	if (reply.add_on_id != -1) {
202929bb91d6SAxel Dörfler 		// TODO: this doesn't look right
203029bb91d6SAxel Dörfler 		// Small problem here, we can't use DormantNodeManager::PutAddOn(), as
203134c72144SAxel Dörfler 		// UnregisterNode() is called by a dormant node itself (by the
203234c72144SAxel Dörfler 		// destructor).
203354187cc6Sbeveloper 		// The add-on that contains the node needs to remain in memory until the
203454187cc6Sbeveloper 		// destructor execution is finished.
203529bb91d6SAxel Dörfler 		// DormantNodeManager::PutAddOnDelayed() will delay unloading.
20369c3b4706SAxel Dörfler 		gDormantNodeManager->PutAddOnDelayed(reply.add_on_id);
2037cf4e2277Sbeveloper 
203829bb91d6SAxel Dörfler 		status = MediaRosterEx(this)->DecrementAddonFlavorInstancesCount(
20399c3b4706SAxel Dörfler 			reply.add_on_id, reply.flavor_id);
204029bb91d6SAxel Dörfler 		if (status != B_OK) {
204134c72144SAxel Dörfler 			ERROR("BMediaRoster::UnregisterNode: "
204234c72144SAxel Dörfler 				"DecrementAddonFlavorInstancesCount() failed\n");
204354187cc6Sbeveloper 			// this is really a problem, but we can't fail now
204454187cc6Sbeveloper 		}
20458b04ffc1Sbeveloper 	}
20469e9417d2Sbeveloper 
20471299bfb2Sbeveloper 	// we are a friend class of BMediaNode and invalidate this member variable
20488b04ffc1Sbeveloper 	node->fNodeID = NODE_UNREGISTERED_ID;
20499e9417d2Sbeveloper 
20509e9417d2Sbeveloper 	return B_OK;
205152a38012Sejakowatz }
205252a38012Sejakowatz 
205352a38012Sejakowatz 
205434c72144SAxel Dörfler //!	Thread safe for multiple calls to Roster()
205552a38012Sejakowatz /*static*/ BMediaRoster*
205652a38012Sejakowatz BMediaRoster::Roster(status_t* out_error)
205752a38012Sejakowatz {
205852a38012Sejakowatz 	static BLocker locker("BMediaRoster::Roster locker");
205952a38012Sejakowatz 	locker.Lock();
20608496c38aSbeveloper 	if (out_error)
20618496c38aSbeveloper 		*out_error = B_OK;
20629def3bf7SStephan Aßmus 	if (sDefaultInstance == NULL) {
20638496c38aSbeveloper 		status_t err;
20649def3bf7SStephan Aßmus 		sDefaultInstance = new (std::nothrow) BMediaRosterEx(&err);
20659def3bf7SStephan Aßmus 		if (sDefaultInstance == NULL)
2066a715f908SStephan Aßmus 			err = B_NO_MEMORY;
2067a715f908SStephan Aßmus 		else if (err != B_OK) {
20689def3bf7SStephan Aßmus 			if (sDefaultInstance) {
20699def3bf7SStephan Aßmus 				sDefaultInstance->Lock();
20709def3bf7SStephan Aßmus 				sDefaultInstance->Quit();
20719def3bf7SStephan Aßmus 				sDefaultInstance = NULL;
2072dcfb6bfcSJérôme Duval 			}
20738496c38aSbeveloper 			if (out_error)
20748496c38aSbeveloper 				*out_error = err;
20758496c38aSbeveloper 		}
207652a38012Sejakowatz 	}
207752a38012Sejakowatz 	locker.Unlock();
20789def3bf7SStephan Aßmus 	return sDefaultInstance;
207952a38012Sejakowatz }
208052a38012Sejakowatz 
208152a38012Sejakowatz 
208252a38012Sejakowatz /*static*/ BMediaRoster*
208352a38012Sejakowatz BMediaRoster::CurrentRoster()
208452a38012Sejakowatz {
20859def3bf7SStephan Aßmus 	return sDefaultInstance;
208652a38012Sejakowatz }
208752a38012Sejakowatz 
208852a38012Sejakowatz 
208952a38012Sejakowatz status_t
209034c72144SAxel Dörfler BMediaRoster::SetTimeSourceFor(media_node_id node, media_node_id time_source)
209152a38012Sejakowatz {
2092aac800c2Sbeveloper 	CALLED();
209340f36b03Sbeveloper 	if (IS_INVALID_NODEID(node) || IS_INVALID_NODEID(time_source))
2094aac800c2Sbeveloper 		return B_BAD_VALUE;
2095aac800c2Sbeveloper 
2096aac800c2Sbeveloper 	media_node clone;
2097aac800c2Sbeveloper 	status_t rv, result;
2098aac800c2Sbeveloper 
209934c72144SAxel Dörfler 	TRACE("BMediaRoster::SetTimeSourceFor: node %ld will be assigned time "
210034c72144SAxel Dörfler 		"source %ld\n", node, time_source);
210134c72144SAxel Dörfler 	TRACE("BMediaRoster::SetTimeSourceFor: node %ld time source %ld enter\n",
210234c72144SAxel Dörfler 		node, time_source);
21035917dd5bSbeveloper 
210486bce45bSbeveloper 	// we need to get a clone of the node to have a port id
2105aac800c2Sbeveloper 	rv = GetNodeFor(node, &clone);
2106aac800c2Sbeveloper 	if (rv != B_OK) {
210734c72144SAxel Dörfler 		ERROR("BMediaRoster::SetTimeSourceFor, GetNodeFor failed, node id "
210834c72144SAxel Dörfler 			"%ld\n", node);
210952a38012Sejakowatz 		return B_ERROR;
211052a38012Sejakowatz 	}
211152a38012Sejakowatz 
211286bce45bSbeveloper 	// we just send the request to set time_source-id as timesource to the node,
211386bce45bSbeveloper 	// the NODE_SET_TIMESOURCE handler code will do the real assignment
2114aac800c2Sbeveloper 	result = B_OK;
2115aac800c2Sbeveloper 	node_set_timesource_command cmd;
2116aac800c2Sbeveloper 	cmd.timesource_id = time_source;
2117aac800c2Sbeveloper 	rv = SendToPort(clone.port, NODE_SET_TIMESOURCE, &cmd, sizeof(cmd));
2118aac800c2Sbeveloper 	if (rv != B_OK) {
211934c72144SAxel Dörfler 		ERROR("BMediaRoster::SetTimeSourceFor, sending NODE_SET_TIMESOURCE "
212034c72144SAxel Dörfler 			"failed, node id %ld\n", node);
2121aac800c2Sbeveloper 		result = B_ERROR;
2122aac800c2Sbeveloper 	}
2123aac800c2Sbeveloper 
212460f15390Sbeveloper 	// we release the clone
2125aac800c2Sbeveloper 	rv = ReleaseNode(clone);
2126aac800c2Sbeveloper 	if (rv != B_OK) {
212734c72144SAxel Dörfler 		ERROR("BMediaRoster::SetTimeSourceFor, ReleaseNode failed, node id "
212834c72144SAxel Dörfler 			"%ld\n", node);
2129aac800c2Sbeveloper 		result = B_ERROR;
2130aac800c2Sbeveloper 	}
2131aac800c2Sbeveloper 
213234c72144SAxel Dörfler 	TRACE("BMediaRoster::SetTimeSourceFor: node %ld time source %ld leave\n",
213334c72144SAxel Dörfler 		node, time_source);
21345917dd5bSbeveloper 
2135aac800c2Sbeveloper 	return result;
2136aac800c2Sbeveloper }
2137aac800c2Sbeveloper 
213852a38012Sejakowatz 
213952a38012Sejakowatz status_t
214034c72144SAxel Dörfler BMediaRoster::GetParameterWebFor(const media_node& node, BParameterWeb** _web)
214152a38012Sejakowatz {
214228ad138aSbeveloper 	CALLED();
214334c72144SAxel Dörfler 	if (_web == NULL)
214428ad138aSbeveloper 		return B_BAD_VALUE;
214528ad138aSbeveloper 	if (IS_INVALID_NODE(node))
214628ad138aSbeveloper 		return B_MEDIA_BAD_NODE;
214728ad138aSbeveloper 	if ((node.kind & B_CONTROLLABLE) == 0)
214828ad138aSbeveloper 		return B_MEDIA_BAD_NODE;
214928ad138aSbeveloper 
215028ad138aSbeveloper 	controllable_get_parameter_web_request request;
215128ad138aSbeveloper 	controllable_get_parameter_web_reply reply;
215234c72144SAxel Dörfler 	int32 requestsize[] = {B_PAGE_SIZE, 4 * B_PAGE_SIZE, 16 * B_PAGE_SIZE,
215334c72144SAxel Dörfler 		64 * B_PAGE_SIZE, 128 * B_PAGE_SIZE, 256 * B_PAGE_SIZE, 0};
215428ad138aSbeveloper 	int32 size;
215528ad138aSbeveloper 
215634c72144SAxel Dörfler 	// TODO: it might be better to query the node for the (current) parameter
215734c72144SAxel Dörfler 	// size first
215828ad138aSbeveloper 	for (int i = 0; (size = requestsize[i]) != 0; i++) {
215928ad138aSbeveloper 		status_t rv;
216028ad138aSbeveloper 		area_id area;
216128ad138aSbeveloper 		void *data;
216234c72144SAxel Dörfler 		area = create_area("parameter web data", &data, B_ANY_ADDRESS, size,
216334c72144SAxel Dörfler 			B_NO_LOCK, B_READ_AREA | B_WRITE_AREA);
216428ad138aSbeveloper 		if (area < B_OK) {
216534c72144SAxel Dörfler 			ERROR("BMediaRoster::GetParameterWebFor couldn't create area of "
216634c72144SAxel Dörfler 				"size %ld\n", size);
216728ad138aSbeveloper 			return B_ERROR;
216828ad138aSbeveloper 		}
216934c72144SAxel Dörfler 		request.max_size = size;
217028ad138aSbeveloper 		request.area = area;
217134c72144SAxel Dörfler 		rv = QueryPort(node.port, CONTROLLABLE_GET_PARAMETER_WEB, &request,
217234c72144SAxel Dörfler 			sizeof(request), &reply, sizeof(reply));
217328ad138aSbeveloper 		if (rv != B_OK) {
217434c72144SAxel Dörfler 			ERROR("BMediaRoster::GetParameterWebFor "
217534c72144SAxel Dörfler 				"CONTROLLABLE_GET_PARAMETER_WEB failed\n");
217628ad138aSbeveloper 			delete_area(area);
217728ad138aSbeveloper 			return B_ERROR;
217828ad138aSbeveloper 		}
217928ad138aSbeveloper 		if (reply.size == 0) {
218028ad138aSbeveloper 			// no parameter web available
218134c72144SAxel Dörfler 			// TODO: should we return an error?
218234c72144SAxel Dörfler 			ERROR("BMediaRoster::GetParameterWebFor node %ld has no parameter "
218334c72144SAxel Dörfler 				"web\n", node.node);
218434c72144SAxel Dörfler 			*_web = new (std::nothrow) BParameterWeb();
218528ad138aSbeveloper 			delete_area(area);
218634c72144SAxel Dörfler 			return *_web != NULL ? B_OK : B_NO_MEMORY;
218752a38012Sejakowatz 		}
218828ad138aSbeveloper 		if (reply.size > 0) {
218928ad138aSbeveloper 			// we got a flattened parameter web!
219034c72144SAxel Dörfler 			*_web = new (std::nothrow) BParameterWeb();
219134c72144SAxel Dörfler 			if (*_web == NULL)
2192a715f908SStephan Aßmus 				rv = B_NO_MEMORY;
2193a715f908SStephan Aßmus 			else {
219434c72144SAxel Dörfler 				printf("BMediaRoster::GetParameterWebFor Unflattening %ld "
219534c72144SAxel Dörfler 					"bytes, 0x%08lx, 0x%08lx, 0x%08lx, 0x%08lx\n",
219634c72144SAxel Dörfler 					reply.size, ((uint32*)data)[0], ((uint32*)data)[1],
219734c72144SAxel Dörfler 					((uint32*)data)[2], ((uint32*)data)[3]);
219828ad138aSbeveloper 
219934c72144SAxel Dörfler 				rv = (*_web)->Unflatten(reply.code, data, reply.size);
2200a715f908SStephan Aßmus 			}
220128ad138aSbeveloper 			if (rv != B_OK) {
220234c72144SAxel Dörfler 				ERROR("BMediaRoster::GetParameterWebFor Unflatten failed, "
220334c72144SAxel Dörfler 					"%s\n", strerror(rv));
220434c72144SAxel Dörfler 				delete *_web;
220528ad138aSbeveloper 			}
220628ad138aSbeveloper 			delete_area(area);
2207a715f908SStephan Aßmus 			return rv;
220828ad138aSbeveloper 		}
220928ad138aSbeveloper 		delete_area(area);
221028ad138aSbeveloper 		ASSERT(reply.size == -1);
221128ad138aSbeveloper 		// parameter web data was too large
221228ad138aSbeveloper 		// loop and try a larger size
221328ad138aSbeveloper 	}
221434c72144SAxel Dörfler 	ERROR("BMediaRoster::GetParameterWebFor node %ld has no parameter web "
221534c72144SAxel Dörfler 		"larger than %ld\n", node.node, size);
221628ad138aSbeveloper 	return B_ERROR;
221728ad138aSbeveloper }
221852a38012Sejakowatz 
221952a38012Sejakowatz 
222052a38012Sejakowatz status_t
222134c72144SAxel Dörfler BMediaRoster::StartControlPanel(const media_node& node, BMessenger* _messenger)
222252a38012Sejakowatz {
2223999cd0acSMaurice Kalinowski 	CALLED();
2224999cd0acSMaurice Kalinowski 
2225999cd0acSMaurice Kalinowski 	controllable_start_control_panel_request request;
2226999cd0acSMaurice Kalinowski 	controllable_start_control_panel_reply reply;
2227999cd0acSMaurice Kalinowski 
2228999cd0acSMaurice Kalinowski 	request.node = node;
2229999cd0acSMaurice Kalinowski 
2230999cd0acSMaurice Kalinowski 	status_t rv;
223134c72144SAxel Dörfler 	rv = QueryPort(node.port, CONTROLLABLE_START_CONTROL_PANEL, &request,
223234c72144SAxel Dörfler 		sizeof(request), &reply, sizeof(reply));
2233999cd0acSMaurice Kalinowski 	if (rv != B_OK)
2234999cd0acSMaurice Kalinowski 		return rv;
2235999cd0acSMaurice Kalinowski 
223634c72144SAxel Dörfler 	if (reply.team != -1 && _messenger != NULL)
223734c72144SAxel Dörfler 		*_messenger = BMessenger(NULL, reply.team);
2238999cd0acSMaurice Kalinowski 
2239999cd0acSMaurice Kalinowski 	return B_OK;
224052a38012Sejakowatz }
224152a38012Sejakowatz 
224252a38012Sejakowatz 
224352a38012Sejakowatz status_t
224434c72144SAxel Dörfler BMediaRoster::GetDormantNodes(dormant_node_info* _info, int32* _count,
224534c72144SAxel Dörfler 	const media_format* hasInput, const media_format* hasOutput,
224634c72144SAxel Dörfler 	const char* name, uint64 requireKinds, uint64 denyKinds)
224752a38012Sejakowatz {
224852a38012Sejakowatz 	CALLED();
224934c72144SAxel Dörfler 	if (_info == NULL || _count == NULL || *_count <= 0)
225052a38012Sejakowatz 		return B_BAD_VALUE;
225152a38012Sejakowatz 
2252*e4c87231SAxel Dörfler 	server_get_dormant_nodes_request request;
2253*e4c87231SAxel Dörfler 	request.max_count = *_count;
2254*e4c87231SAxel Dörfler 	request.has_input = hasInput != NULL;
225534c72144SAxel Dörfler 	if (hasInput != NULL) {
225634c72144SAxel Dörfler 		// TODO: we should not make a flat copy of media_format
2257*e4c87231SAxel Dörfler 		request.input_format = *hasInput;
225834c72144SAxel Dörfler 	}
2259*e4c87231SAxel Dörfler 	request.has_output = hasOutput != NULL;
226034c72144SAxel Dörfler 	if (hasOutput != NULL) {
226134c72144SAxel Dörfler 		// TODO: we should not make a flat copy of media_format
2262*e4c87231SAxel Dörfler 		request.output_format = *hasOutput;
226334c72144SAxel Dörfler 	}
226434c72144SAxel Dörfler 
2265*e4c87231SAxel Dörfler 	request.has_name = name != NULL;
2266*e4c87231SAxel Dörfler 	if (name != NULL)
2267*e4c87231SAxel Dörfler 		strlcpy(request.name, name, sizeof(request.name));
226852a38012Sejakowatz 
2269*e4c87231SAxel Dörfler 	request.require_kinds = requireKinds;
2270*e4c87231SAxel Dörfler 	request.deny_kinds = denyKinds;
2271*e4c87231SAxel Dörfler 	request.reply_port = gPortPool->GetPort();
227252a38012Sejakowatz 
2273*e4c87231SAxel Dörfler 	server_get_dormant_nodes_reply reply;
2274*e4c87231SAxel Dörfler 	status_t status = QueryServer(SERVER_GET_DORMANT_NODES, &request,
2275*e4c87231SAxel Dörfler 		sizeof(request), &reply, sizeof(reply));
2276*e4c87231SAxel Dörfler 	if (status != B_OK) {
2277*e4c87231SAxel Dörfler 		gPortPool->PutPort(request.reply_port);
2278*e4c87231SAxel Dörfler 		return status;
227952a38012Sejakowatz 	}
228052a38012Sejakowatz 
228134c72144SAxel Dörfler 	*_count = reply.count;
228252a38012Sejakowatz 
2283*e4c87231SAxel Dörfler 	if (reply.count > 0) {
2284*e4c87231SAxel Dörfler 		int32 code;
2285*e4c87231SAxel Dörfler 		status = read_port(request.reply_port, &code, _info,
2286*e4c87231SAxel Dörfler 			reply.count * sizeof(dormant_node_info));
2287*e4c87231SAxel Dörfler 		if (status < B_OK)
2288*e4c87231SAxel Dörfler 			reply.result = status;
228952a38012Sejakowatz 	}
2290*e4c87231SAxel Dörfler 	gPortPool->PutPort(request.reply_port);
229152a38012Sejakowatz 
229252a38012Sejakowatz 	return reply.result;
229352a38012Sejakowatz }
229452a38012Sejakowatz 
2295*e4c87231SAxel Dörfler 
229634c72144SAxel Dörfler /*!	This function is used to do the real work of instantiating a dormant node.
229734c72144SAxel Dörfler 	It is either called by the media_addon_server to instantiate a global node,
229834c72144SAxel Dörfler 	or it gets called from BMediaRoster::InstantiateDormantNode() to create a
229934c72144SAxel Dörfler 	local one.
230034c72144SAxel Dörfler 
230134c72144SAxel Dörfler 	Checks concerning global/local are not done here.
23028b04ffc1Sbeveloper */
230352a38012Sejakowatz status_t
230434c72144SAxel Dörfler BMediaRosterEx::InstantiateDormantNode(media_addon_id addonID, int32 flavorID,
230534c72144SAxel Dörfler 	team_id creator, media_node *_node)
230652a38012Sejakowatz {
230754187cc6Sbeveloper 	// This function is always called from the correct context, if the node
230854187cc6Sbeveloper 	// is supposed to be global, it is called from the media_addon_server.
230954187cc6Sbeveloper 
231052a38012Sejakowatz 	// if B_FLAVOR_IS_GLOBAL, we need to use the BMediaAddOn object that
231152a38012Sejakowatz 	// resides in the media_addon_server
231252a38012Sejakowatz 
23138b04ffc1Sbeveloper 	// RegisterNode() must be called for nodes instantiated from add-ons,
23148b04ffc1Sbeveloper 	// since the media kit warrants that it's done automatically.
231552a38012Sejakowatz 
231634c72144SAxel Dörfler 	// addonID		Indicates the ID number of the media add-on in which the
231734c72144SAxel Dörfler 	//				node resides.
231834c72144SAxel Dörfler 	// flavorID		Indicates the internal ID number that the add-on uses to
231934c72144SAxel Dörfler 	//				identify the flavor, this is the number that was published
232034c72144SAxel Dörfler 	//				by BMediaAddOn::GetFlavorAt() in the
23218b04ffc1Sbeveloper 	//				flavor_info::internal_id field.
232234c72144SAxel Dörfler 	// creator		The creator team is -1 if nodes are created locally. If
232334c72144SAxel Dörfler 	//				created globally, it will contain (while called in
232434c72144SAxel Dörfler 	//				media_addon_server context) the team-id of the team that
232534c72144SAxel Dörfler 	//				requested the instantiation.
23268b04ffc1Sbeveloper 
232734c72144SAxel Dörfler 	TRACE("BMediaRosterEx::InstantiateDormantNode: addonID %ld, flavorID "
232834c72144SAxel Dörfler 		"%ld\n", addonID, flavorID);
23298b04ffc1Sbeveloper 
23308b04ffc1Sbeveloper 	// Get flavor_info from the server
233134c72144SAxel Dörfler 	dormant_flavor_info info;
23328c6a6096Sbeveloper 	status_t rv;
233334c72144SAxel Dörfler 	rv = GetDormantFlavorInfo(addonID, flavorID, &info);
23348b04ffc1Sbeveloper 	if (rv != B_OK) {
233534c72144SAxel Dörfler 		ERROR("BMediaRosterEx::InstantiateDormantNode error: failed to get "
233634c72144SAxel Dörfler 			"dormant_flavor_info for addon-id %ld, flavor-id %ld\n", addonID,
233734c72144SAxel Dörfler 			flavorID);
233852a38012Sejakowatz 		return B_ERROR;
233952a38012Sejakowatz 	}
23408b04ffc1Sbeveloper 
23411ecccf18SFrançois Revol 	ASSERT(info.internal_id == flavorID);
23428b04ffc1Sbeveloper 
23438b04ffc1Sbeveloper 	// load the BMediaAddOn object
234429bb91d6SAxel Dörfler 	BMediaAddOn* addon = gDormantNodeManager->GetAddOn(addonID);
234534c72144SAxel Dörfler 	if (addon == NULL) {
23465ac4fbd7Sbeveloper 		ERROR("BMediaRosterEx::InstantiateDormantNode: GetAddon failed\n");
23478b04ffc1Sbeveloper 		return B_ERROR;
23488b04ffc1Sbeveloper 	}
23498b04ffc1Sbeveloper 
235054187cc6Sbeveloper 	// Now we need to try to increment the use count of this addon flavor
235154187cc6Sbeveloper 	// in the server. This can fail if the total number instances of this
235254187cc6Sbeveloper 	// flavor is limited.
235334c72144SAxel Dörfler 	rv = IncrementAddonFlavorInstancesCount(addonID, flavorID);
235454187cc6Sbeveloper 	if (rv != B_OK) {
235534c72144SAxel Dörfler 		ERROR("BMediaRosterEx::InstantiateDormantNode error: can't create "
235634c72144SAxel Dörfler 			"more nodes for addon-id %ld, flavor-id %ld\n", addonID, flavorID);
235754187cc6Sbeveloper 		// Put the addon back into the pool
235829bb91d6SAxel Dörfler 		gDormantNodeManager->PutAddOn(addonID);
235954187cc6Sbeveloper 		return B_ERROR;
236054187cc6Sbeveloper 	}
236154187cc6Sbeveloper 
23628b04ffc1Sbeveloper 	BMessage config;
236334c72144SAxel Dörfler 	rv = LoadNodeConfiguration(addonID, flavorID, &config);
236454187cc6Sbeveloper 	if (rv != B_OK) {
236534c72144SAxel Dörfler 		ERROR("BMediaRosterEx::InstantiateDormantNode: couldn't load "
236634c72144SAxel Dörfler 			"configuration for addon-id %ld, flavor-id %ld\n", addonID,
236734c72144SAxel Dörfler 			flavorID);
236854187cc6Sbeveloper 		// do not return, this is a minor problem, not a reason to fail
236954187cc6Sbeveloper 	}
23708b04ffc1Sbeveloper 
237134c72144SAxel Dörfler 	status_t status = B_OK;
237234c72144SAxel Dörfler 	BMediaNode* node = addon->InstantiateNodeFor(&info, &config, &status);
237334c72144SAxel Dörfler 	if (node == NULL) {
237434c72144SAxel Dörfler 		ERROR("BMediaRosterEx::InstantiateDormantNode: InstantiateNodeFor "
237534c72144SAxel Dörfler 			"failed\n");
23768b04ffc1Sbeveloper 
237754187cc6Sbeveloper 		// Put the addon back into the pool
237829bb91d6SAxel Dörfler 		gDormantNodeManager->PutAddOn(addonID);
237934c72144SAxel Dörfler 
238054187cc6Sbeveloper 		// We must decrement the use count of this addon flavor in the
238154187cc6Sbeveloper 		// server to compensate the increment done in the beginning.
238234c72144SAxel Dörfler 		rv = DecrementAddonFlavorInstancesCount(addonID, flavorID);
238354187cc6Sbeveloper 		if (rv != B_OK) {
238434c72144SAxel Dörfler 			ERROR("BMediaRosterEx::InstantiateDormantNode: DecrementAddon"
238534c72144SAxel Dörfler 				"FlavorInstancesCount failed\n");
238616b7eea4Sbeveloper 		}
238734c72144SAxel Dörfler 		return status != B_OK ? status : B_ERROR;
238854187cc6Sbeveloper 	}
238954187cc6Sbeveloper 
239034c72144SAxel Dörfler 	rv = RegisterNode(node, addonID, flavorID);
23918c6a6096Sbeveloper 	if (rv != B_OK) {
23925ac4fbd7Sbeveloper 		ERROR("BMediaRosterEx::InstantiateDormantNode: RegisterNode failed\n");
23938c6a6096Sbeveloper 		delete node;
239454187cc6Sbeveloper 		// Put the addon back into the pool
239529bb91d6SAxel Dörfler 		gDormantNodeManager->PutAddOn(addonID);
239654187cc6Sbeveloper 		// We must decrement the use count of this addon flavor in the
239754187cc6Sbeveloper 		// server to compensate the increment done in the beginning.
239834c72144SAxel Dörfler 		rv = DecrementAddonFlavorInstancesCount(addonID, flavorID);
239954187cc6Sbeveloper 		if (rv != B_OK) {
240034c72144SAxel Dörfler 			ERROR("BMediaRosterEx::InstantiateDormantNode: DecrementAddon"
240134c72144SAxel Dörfler 				"FlavorInstancesCount failed\n");
240254187cc6Sbeveloper 		}
24038c6a6096Sbeveloper 		return B_ERROR;
24048c6a6096Sbeveloper 	}
24058c6a6096Sbeveloper 
240654187cc6Sbeveloper 	if (creator != -1) {
240734c72144SAxel Dörfler 		// send a message to the server to assign team "creator" as creator
240834c72144SAxel Dörfler 		// of node "node->ID()"
240934c72144SAxel Dörfler 		printf("!!! BMediaRosterEx::InstantiateDormantNode assigning team "
241034c72144SAxel Dörfler 			"%ld as creator of node %ld\n", creator, node->ID());
241134c72144SAxel Dörfler 
241254187cc6Sbeveloper 		rv = MediaRosterEx(this)->SetNodeCreator(node->ID(), creator);
241354187cc6Sbeveloper 		if (rv != B_OK) {
241434c72144SAxel Dörfler 			ERROR("BMediaRosterEx::InstantiateDormantNode failed to assign "
241534c72144SAxel Dörfler 				"team %ld as creator of node %ld\n", creator, node->ID());
241654187cc6Sbeveloper 			// do not return, this is a minor problem, not a reason to fail
241754187cc6Sbeveloper 		}
241854187cc6Sbeveloper 	}
241954187cc6Sbeveloper 
242054187cc6Sbeveloper 	// RegisterNode() does remember the add-on id in the server
242154187cc6Sbeveloper 	// and UnregisterNode() will call DormantNodeManager::PutAddon()
242254187cc6Sbeveloper 	// when the node is unregistered.
24238c6a6096Sbeveloper 
242434c72144SAxel Dörfler 	*_node = node->Node();
2425cf4e2277Sbeveloper 
242634c72144SAxel Dörfler 	TRACE("BMediaRosterEx::InstantiateDormantNode: addon-id %ld, flavor_id "
242734c72144SAxel Dörfler 		"%ld instanciated as node %ld, port %ld in team %ld\n", addonID,
24289dec2310SAxel Dörfler 		flavorID, _node->node, _node->port, BPrivate::current_team());
2429cf4e2277Sbeveloper 
243016b7eea4Sbeveloper 	return B_OK;
243116b7eea4Sbeveloper }
243252a38012Sejakowatz 
243352a38012Sejakowatz 
243452a38012Sejakowatz status_t
243534c72144SAxel Dörfler BMediaRoster::InstantiateDormantNode(const dormant_node_info& info,
243634c72144SAxel Dörfler 	media_node* _node, uint32 flags)
24378b04ffc1Sbeveloper {
24388b04ffc1Sbeveloper 	CALLED();
243934c72144SAxel Dörfler 	if (_node == NULL)
24408b04ffc1Sbeveloper 		return B_BAD_VALUE;
244134c72144SAxel Dörfler 	if (info.addon <= B_OK) {
244234c72144SAxel Dörfler 		ERROR("BMediaRoster::InstantiateDormantNode error: addon-id %ld "
244334c72144SAxel Dörfler 			"invalid.\n", info.addon);
24448b04ffc1Sbeveloper 		return B_BAD_VALUE;
24458b04ffc1Sbeveloper 	}
24468b04ffc1Sbeveloper 
244734c72144SAxel Dörfler 	printf("BMediaRoster::InstantiateDormantNode: addon-id %ld, flavor_id "
244834c72144SAxel Dörfler 		"%ld, flags 0x%lX\n", info.addon, info.flavor_id, flags);
24498b04ffc1Sbeveloper 
24508b04ffc1Sbeveloper 	// Get flavor_info from the server
245134c72144SAxel Dörfler 	// TODO: this is a little overhead, as we get the full blown
245234c72144SAxel Dörfler 	// dormant_flavor_info,
245334c72144SAxel Dörfler 	// TODO: but only need the flags.
245434c72144SAxel Dörfler 	dormant_flavor_info flavorInfo;
24558b04ffc1Sbeveloper 	status_t rv;
245634c72144SAxel Dörfler 	rv = MediaRosterEx(this)->GetDormantFlavorInfo(info.addon, info.flavor_id,
245734c72144SAxel Dörfler 		&flavorInfo);
24588b04ffc1Sbeveloper 	if (rv != B_OK) {
245934c72144SAxel Dörfler 		ERROR("BMediaRoster::InstantiateDormantNode: failed to get "
246034c72144SAxel Dörfler 			"dormant_flavor_info for addon-id %ld, flavor-id %ld\n",
246134c72144SAxel Dörfler 			info.addon, info.flavor_id);
2462626824eaSbeveloper 		return B_NAME_NOT_FOUND;
24638b04ffc1Sbeveloper 	}
24648b04ffc1Sbeveloper 
246534c72144SAxel Dörfler 	ASSERT(flavorInfo.internal_id == info.flavor_id);
24668b04ffc1Sbeveloper 
24678b04ffc1Sbeveloper #if DEBUG
246834c72144SAxel Dörfler 	printf("BMediaRoster::InstantiateDormantNode: name \"%s\", info \"%s\", "
246934c72144SAxel Dörfler 		"flavor_flags 0x%lX, internal_id %ld, possible_count %ld\n",
247034c72144SAxel Dörfler 		flavorInfo.name, flavorInfo.info, flavorInfo.flavor_flags,
247134c72144SAxel Dörfler 		flavorInfo.internal_id, flavorInfo.possible_count);
247234c72144SAxel Dörfler 
247334c72144SAxel Dörfler 	if ((flags & B_FLAVOR_IS_LOCAL) != 0) {
247434c72144SAxel Dörfler 		printf("BMediaRoster::InstantiateDormantNode: caller requested "
247534c72144SAxel Dörfler 			"B_FLAVOR_IS_LOCAL\n");
247634c72144SAxel Dörfler 	}
247734c72144SAxel Dörfler 	if ((flags & B_FLAVOR_IS_GLOBAL) != 0) {
247834c72144SAxel Dörfler 		printf("BMediaRoster::InstantiateDormantNode: caller requested "
247934c72144SAxel Dörfler 			"B_FLAVOR_IS_GLOBAL\n");
248034c72144SAxel Dörfler 	}
248134c72144SAxel Dörfler 	if ((flavorInfo.flavor_flags & B_FLAVOR_IS_LOCAL) != 0) {
248234c72144SAxel Dörfler 		printf("BMediaRoster::InstantiateDormantNode: node requires "
248334c72144SAxel Dörfler 			"B_FLAVOR_IS_LOCAL\n");
248434c72144SAxel Dörfler 	}
248534c72144SAxel Dörfler 	if ((flavorInfo.flavor_flags & B_FLAVOR_IS_GLOBAL) != 0) {
248634c72144SAxel Dörfler 		printf("BMediaRoster::InstantiateDormantNode: node requires "
248734c72144SAxel Dörfler 			"B_FLAVOR_IS_GLOBAL\n");
248834c72144SAxel Dörfler 	}
24898b04ffc1Sbeveloper #endif
24908b04ffc1Sbeveloper 
24918b04ffc1Sbeveloper 	// Make sure that flags demanded by the dormant node and those requested
24928b04ffc1Sbeveloper 	// by the caller are not incompatible.
249334c72144SAxel Dörfler 	if ((flavorInfo.flavor_flags & B_FLAVOR_IS_GLOBAL) != 0
249434c72144SAxel Dörfler 		&& (flags & B_FLAVOR_IS_LOCAL) != 0) {
249534c72144SAxel Dörfler 		ERROR("BMediaRoster::InstantiateDormantNode: requested "
249634c72144SAxel Dörfler 			"B_FLAVOR_IS_LOCAL, but dormant node has B_FLAVOR_IS_GLOBAL\n");
2497626824eaSbeveloper 		return B_NAME_NOT_FOUND;
24988b04ffc1Sbeveloper 	}
249934c72144SAxel Dörfler 	if ((flavorInfo.flavor_flags & B_FLAVOR_IS_LOCAL) != 0
250034c72144SAxel Dörfler 		&& (flags & B_FLAVOR_IS_GLOBAL) != 0) {
250134c72144SAxel Dörfler 		ERROR("BMediaRoster::InstantiateDormantNode: requested "
250234c72144SAxel Dörfler 			"B_FLAVOR_IS_GLOBAL, but dormant node has B_FLAVOR_IS_LOCAL\n");
2503626824eaSbeveloper 		return B_NAME_NOT_FOUND;
25048b04ffc1Sbeveloper 	}
250554187cc6Sbeveloper 
25068b04ffc1Sbeveloper 	// If either the node, or the caller requested to make the instance global
250734c72144SAxel Dörfler 	// we will do it by forwarding this request into the media_addon_server,
250834c72144SAxel Dörfler 	// which in turn will call BMediaRosterEx::InstantiateDormantNode to create
250934c72144SAxel Dörfler 	// the node there and make it globally available.
251034c72144SAxel Dörfler 	if ((flavorInfo.flavor_flags & B_FLAVOR_IS_GLOBAL) != 0
251134c72144SAxel Dörfler 		|| (flags & B_FLAVOR_IS_GLOBAL) != 0) {
251234c72144SAxel Dörfler 		TRACE("BMediaRoster::InstantiateDormantNode: creating global object "
251334c72144SAxel Dörfler 			"in media_addon_server\n");
2514cf4e2277Sbeveloper 
25159c3b4706SAxel Dörfler 		add_on_server_instantiate_dormant_node_request request;
25169c3b4706SAxel Dörfler 		add_on_server_instantiate_dormant_node_reply reply;
25179c3b4706SAxel Dörfler 		request.add_on_id = info.addon;
25189dec2310SAxel Dörfler 		request.flavor_id = info.flavor_id;
25199dec2310SAxel Dörfler 		request.creator_team = BPrivate::current_team();
252034c72144SAxel Dörfler 			// creator team is allowed to also release global nodes
25219c3b4706SAxel Dörfler 		rv = QueryAddOnServer(ADD_ON_SERVER_INSTANTIATE_DORMANT_NODE, &request,
252234c72144SAxel Dörfler 			sizeof(request), &reply, sizeof(reply));
252334c72144SAxel Dörfler 		if (rv == B_OK)
252434c72144SAxel Dörfler 			*_node = reply.node;
25258b04ffc1Sbeveloper 	} else {
252654187cc6Sbeveloper 		// creator team = -1, as this is a local node
252734c72144SAxel Dörfler 		rv = MediaRosterEx(this)->InstantiateDormantNode(info.addon,
252834c72144SAxel Dörfler 			info.flavor_id, -1, _node);
25298b04ffc1Sbeveloper 	}
2530626824eaSbeveloper 	if (rv != B_OK) {
253134c72144SAxel Dörfler 		*_node = media_node::null;
2532626824eaSbeveloper 		return B_NAME_NOT_FOUND;
2533626824eaSbeveloper 	}
2534626824eaSbeveloper 	return B_OK;
25358b04ffc1Sbeveloper }
25368b04ffc1Sbeveloper 
25378b04ffc1Sbeveloper 
25388b04ffc1Sbeveloper status_t
253934c72144SAxel Dörfler BMediaRoster::InstantiateDormantNode(const dormant_node_info& info,
254034c72144SAxel Dörfler 	media_node* _node)
25418b04ffc1Sbeveloper {
254234c72144SAxel Dörfler 	return InstantiateDormantNode(info, _node, 0);
25438b04ffc1Sbeveloper }
25448b04ffc1Sbeveloper 
25458b04ffc1Sbeveloper 
25468b04ffc1Sbeveloper status_t
254752a38012Sejakowatz BMediaRoster::GetDormantNodeFor(const media_node& node,
254834c72144SAxel Dörfler 	dormant_node_info* _info)
254952a38012Sejakowatz {
255085dfab2bSbeveloper 	CALLED();
255134c72144SAxel Dörfler 	if (_info == NULL)
255285dfab2bSbeveloper 		return B_BAD_VALUE;
255340f36b03Sbeveloper 	if (IS_INVALID_NODE(node))
255485dfab2bSbeveloper 		return B_MEDIA_BAD_NODE;
255552a38012Sejakowatz 
255685dfab2bSbeveloper 	server_get_dormant_node_for_request request;
255785dfab2bSbeveloper 	server_get_dormant_node_for_reply reply;
255885dfab2bSbeveloper 	status_t rv;
255985dfab2bSbeveloper 
256085dfab2bSbeveloper 	request.node = node;
256185dfab2bSbeveloper 
256234c72144SAxel Dörfler 	rv = QueryServer(SERVER_GET_DORMANT_NODE_FOR, &request, sizeof(request),
256334c72144SAxel Dörfler 		&reply, sizeof(reply));
256485dfab2bSbeveloper 	if (rv != B_OK)
256585dfab2bSbeveloper 		return rv;
256685dfab2bSbeveloper 
256734c72144SAxel Dörfler 	*_info = reply.node_info;
256885dfab2bSbeveloper 	return B_OK;
256952a38012Sejakowatz }
257052a38012Sejakowatz 
257134c72144SAxel Dörfler 
257252a38012Sejakowatz status_t
257334c72144SAxel Dörfler BMediaRosterEx::GetDormantFlavorInfo(media_addon_id addonID, int32 flavorID,
257434c72144SAxel Dörfler 	dormant_flavor_info* _flavor)
257552a38012Sejakowatz {
257652a38012Sejakowatz 	CALLED();
257734c72144SAxel Dörfler 	if (_flavor == NULL)
25789bedd42cSbeveloper 		return B_BAD_VALUE;
257952a38012Sejakowatz 
2580*e4c87231SAxel Dörfler 	// TODO: better use an area here as well!
258152a38012Sejakowatz 
2582*e4c87231SAxel Dörfler 	server_get_dormant_flavor_info_reply* reply
2583*e4c87231SAxel Dörfler 		= (server_get_dormant_flavor_info_reply*)malloc(16300);
258434c72144SAxel Dörfler 	if (reply == NULL)
258534c72144SAxel Dörfler 		return B_NO_MEMORY;
258652a38012Sejakowatz 
2587*e4c87231SAxel Dörfler 	server_get_dormant_flavor_info_request request;
2588*e4c87231SAxel Dörfler 	request.add_on_id = addonID;
2589*e4c87231SAxel Dörfler 	request.flavor_id = flavorID;
2590*e4c87231SAxel Dörfler 	request.reply_port = gPortPool->GetPort();
2591*e4c87231SAxel Dörfler 
2592*e4c87231SAxel Dörfler 	status_t status = QueryServer(SERVER_GET_DORMANT_FLAVOR_INFO, &request,
2593*e4c87231SAxel Dörfler 		sizeof(request), reply, 16300);
2594*e4c87231SAxel Dörfler 
2595*e4c87231SAxel Dörfler 	gPortPool->PutPort(request.reply_port);
2596*e4c87231SAxel Dörfler 
25979dec2310SAxel Dörfler 	if (status != B_OK) {
259852a38012Sejakowatz 		free(reply);
25999dec2310SAxel Dörfler 		return status;
260052a38012Sejakowatz 	}
260152a38012Sejakowatz 
26029dec2310SAxel Dörfler 	if (reply->result == B_OK) {
26039dec2310SAxel Dörfler 		status = _flavor->Unflatten(reply->type, &reply->flattened_data,
26049dec2310SAxel Dörfler 			reply->flattened_size);
26059dec2310SAxel Dörfler 	} else
26069dec2310SAxel Dörfler 		status = reply->result;
260752a38012Sejakowatz 
260852a38012Sejakowatz 	free(reply);
26099dec2310SAxel Dörfler 	return status;
261052a38012Sejakowatz }
261152a38012Sejakowatz 
261234c72144SAxel Dörfler 
26138b04ffc1Sbeveloper status_t
261434c72144SAxel Dörfler BMediaRoster::GetDormantFlavorInfoFor(const dormant_node_info& dormant,
261534c72144SAxel Dörfler 	dormant_flavor_info* _flavor)
26168b04ffc1Sbeveloper {
261734c72144SAxel Dörfler 	return MediaRosterEx(this)->GetDormantFlavorInfo(dormant.addon,
261834c72144SAxel Dörfler 		dormant.flavor_id, _flavor);
26198b04ffc1Sbeveloper }
262052a38012Sejakowatz 
262134c72144SAxel Dörfler 
262260f15390Sbeveloper // Reports in outLatency the maximum latency found downstream from
262360f15390Sbeveloper // the specified BBufferProducer, producer, given the current connections.
262452a38012Sejakowatz status_t
262534c72144SAxel Dörfler BMediaRoster::GetLatencyFor(const media_node& producer, bigtime_t* _latency)
262652a38012Sejakowatz {
262760f15390Sbeveloper 	CALLED();
262834c72144SAxel Dörfler 	if (_latency == NULL)
262960f15390Sbeveloper 		return B_BAD_VALUE;
263034c72144SAxel Dörfler 	if (IS_INVALID_NODE(producer)
263134c72144SAxel Dörfler 		|| (producer.kind & B_BUFFER_PRODUCER) == 0)
263260f15390Sbeveloper 		return B_MEDIA_BAD_NODE;
263360f15390Sbeveloper 
263460f15390Sbeveloper 	producer_get_latency_request request;
263560f15390Sbeveloper 	producer_get_latency_reply reply;
263660f15390Sbeveloper 	status_t rv;
263760f15390Sbeveloper 
263834c72144SAxel Dörfler 	rv = QueryPort(producer.port, PRODUCER_GET_LATENCY, &request,
263934c72144SAxel Dörfler 		sizeof(request), &reply, sizeof(reply));
264060f15390Sbeveloper 	if (rv != B_OK)
264160f15390Sbeveloper 		return rv;
264260f15390Sbeveloper 
264334c72144SAxel Dörfler 	*_latency = reply.latency;
264460f15390Sbeveloper 
2645ab9afde3SMarcus Overhagen //	printf("BMediaRoster::GetLatencyFor producer %ld has maximum latency %Ld\n", producer.node, *out_latency);
2646aac800c2Sbeveloper 	return B_OK;
264752a38012Sejakowatz }
264852a38012Sejakowatz 
264952a38012Sejakowatz 
265052a38012Sejakowatz status_t
265152a38012Sejakowatz BMediaRoster::GetInitialLatencyFor(const media_node& producer,
265234c72144SAxel Dörfler 	bigtime_t* _latency, uint32* _flags)
265352a38012Sejakowatz {
2654b65a0ac5SJérôme Duval 	CALLED();
265534c72144SAxel Dörfler 	if (_latency == NULL)
2656b65a0ac5SJérôme Duval 		return B_BAD_VALUE;
265734c72144SAxel Dörfler 	if (IS_INVALID_NODE(producer)
265834c72144SAxel Dörfler 		|| (producer.kind & B_BUFFER_PRODUCER) == 0)
2659b65a0ac5SJérôme Duval 		return B_MEDIA_BAD_NODE;
2660b65a0ac5SJérôme Duval 
2661b65a0ac5SJérôme Duval 	producer_get_initial_latency_request request;
2662b65a0ac5SJérôme Duval 	producer_get_initial_latency_reply reply;
2663b65a0ac5SJérôme Duval 	status_t rv;
2664b65a0ac5SJérôme Duval 
266534c72144SAxel Dörfler 	rv = QueryPort(producer.port, PRODUCER_GET_INITIAL_LATENCY, &request,
266634c72144SAxel Dörfler 		sizeof(request), &reply, sizeof(reply));
2667b65a0ac5SJérôme Duval 	if (rv != B_OK)
2668b65a0ac5SJérôme Duval 		return rv;
2669b65a0ac5SJérôme Duval 
267034c72144SAxel Dörfler 	*_latency = reply.initial_latency;
267134c72144SAxel Dörfler 	if (_flags != NULL)
267234c72144SAxel Dörfler 		*_flags = reply.flags;
2673b65a0ac5SJérôme Duval 
267434c72144SAxel Dörfler 	TRACE("BMediaRoster::GetInitialLatencyFor producer %ld has maximum "
267534c72144SAxel Dörfler 		"initial latency %Ld\n", producer.node, *_latency);
2676aac800c2Sbeveloper 	return B_OK;
267752a38012Sejakowatz }
267852a38012Sejakowatz 
267952a38012Sejakowatz 
268052a38012Sejakowatz status_t
268134c72144SAxel Dörfler BMediaRoster::GetStartLatencyFor(const media_node& timeSource,
268234c72144SAxel Dörfler 	bigtime_t* _latency)
268352a38012Sejakowatz {
2684fc8b28b6SJérôme Duval 	CALLED();
268534c72144SAxel Dörfler 	if (_latency == NULL)
2686fc8b28b6SJérôme Duval 		return B_BAD_VALUE;
268734c72144SAxel Dörfler 	if (IS_INVALID_NODE(timeSource)
268834c72144SAxel Dörfler 		|| (timeSource.kind & B_TIME_SOURCE) == 0)
2689fc8b28b6SJérôme Duval 		return B_MEDIA_BAD_NODE;
2690fc8b28b6SJérôme Duval 
2691fc8b28b6SJérôme Duval 	timesource_get_start_latency_request request;
2692fc8b28b6SJérôme Duval 	timesource_get_start_latency_reply reply;
2693fc8b28b6SJérôme Duval 	status_t rv;
2694fc8b28b6SJérôme Duval 
269534c72144SAxel Dörfler 	rv = QueryPort(timeSource.port, TIMESOURCE_GET_START_LATENCY, &request,
269634c72144SAxel Dörfler 		sizeof(request), &reply, sizeof(reply));
2697fc8b28b6SJérôme Duval 	if (rv != B_OK)
2698fc8b28b6SJérôme Duval 		return rv;
2699fc8b28b6SJérôme Duval 
270034c72144SAxel Dörfler 	*_latency = reply.start_latency;
2701fc8b28b6SJérôme Duval 
270234c72144SAxel Dörfler 	TRACE("BMediaRoster::GetStartLatencyFor timesource %ld has maximum "
270334c72144SAxel Dörfler 		"initial latency %Ld\n", timeSource.node, *_latency);
2704aac800c2Sbeveloper 	return B_OK;
270552a38012Sejakowatz }
270652a38012Sejakowatz 
270752a38012Sejakowatz 
270852a38012Sejakowatz status_t
270934c72144SAxel Dörfler BMediaRoster::GetFileFormatsFor(const media_node& fileInterface,
271034c72144SAxel Dörfler 	media_file_format* _formats, int32* _numFormats)
271152a38012Sejakowatz {
271252a38012Sejakowatz 	UNIMPLEMENTED();
271352a38012Sejakowatz 	return B_ERROR;
271452a38012Sejakowatz }
271552a38012Sejakowatz 
271652a38012Sejakowatz 
271752a38012Sejakowatz status_t
271834c72144SAxel Dörfler BMediaRoster::SetRefFor(const media_node& file_interface, const entry_ref& file,
271934c72144SAxel Dörfler 	bool createAndTruncate, bigtime_t* _length)
272052a38012Sejakowatz {
27216938364bSMaurice Kalinowski 	CALLED();
27226938364bSMaurice Kalinowski 
27236938364bSMaurice Kalinowski 	fileinterface_set_ref_request request;
27246938364bSMaurice Kalinowski 	fileinterface_set_ref_reply reply;
27256938364bSMaurice Kalinowski 	status_t rv;
27266938364bSMaurice Kalinowski 
27276938364bSMaurice Kalinowski 	request.device = file.device;
27286938364bSMaurice Kalinowski 	request.directory = file.directory;
27296938364bSMaurice Kalinowski 	strcpy(request.name, file.name);
273034c72144SAxel Dörfler 	request.create = createAndTruncate;
273134c72144SAxel Dörfler 	if (_length != NULL)
273234c72144SAxel Dörfler 		request.duration = *_length;
27336938364bSMaurice Kalinowski 
273434c72144SAxel Dörfler 	rv = QueryPort(file_interface.port, FILEINTERFACE_SET_REF, &request,
273534c72144SAxel Dörfler 		sizeof(request), &reply, sizeof(reply));
27366938364bSMaurice Kalinowski 	if (rv != B_OK)
27376938364bSMaurice Kalinowski 		return rv;
27386938364bSMaurice Kalinowski 
273934c72144SAxel Dörfler 	if (!createAndTruncate && _length)
274034c72144SAxel Dörfler 		*_length = reply.duration;
27416938364bSMaurice Kalinowski 
27426938364bSMaurice Kalinowski 	return B_OK;
274352a38012Sejakowatz }
274452a38012Sejakowatz 
274552a38012Sejakowatz 
274652a38012Sejakowatz status_t
274734c72144SAxel Dörfler BMediaRoster::GetRefFor(const media_node& node, entry_ref* _file,
274834c72144SAxel Dörfler 	BMimeType* mimeType)
274952a38012Sejakowatz {
27506938364bSMaurice Kalinowski 	CALLED();
27516938364bSMaurice Kalinowski 
275234c72144SAxel Dörfler 	if (!_file)
27536938364bSMaurice Kalinowski 		return B_BAD_VALUE;
27546938364bSMaurice Kalinowski 
27556938364bSMaurice Kalinowski 	fileinterface_get_ref_request request;
27566938364bSMaurice Kalinowski 	fileinterface_get_ref_reply reply;
27576938364bSMaurice Kalinowski 	status_t rv;
27586938364bSMaurice Kalinowski 
275934c72144SAxel Dörfler 	rv = QueryPort(node.port, FILEINTERFACE_GET_REF, &request, sizeof(request),
276034c72144SAxel Dörfler 		&reply, sizeof(reply));
27616938364bSMaurice Kalinowski 	if (rv != B_OK)
27626938364bSMaurice Kalinowski 		return rv;
27636938364bSMaurice Kalinowski 
276434c72144SAxel Dörfler 	*_file = entry_ref(reply.device, reply.directory, reply.name);
27656938364bSMaurice Kalinowski 
276634c72144SAxel Dörfler 	if (mimeType)
276734c72144SAxel Dörfler 		mimeType->SetTo(reply.mimetype);
27686938364bSMaurice Kalinowski 
27696938364bSMaurice Kalinowski 	return B_OK;
277052a38012Sejakowatz }
277152a38012Sejakowatz 
277252a38012Sejakowatz 
277352a38012Sejakowatz status_t
277452a38012Sejakowatz BMediaRoster::SniffRefFor(const media_node& file_interface,
277534c72144SAxel Dörfler 	const entry_ref& file, BMimeType* mimeType, float* _capability)
277652a38012Sejakowatz {
27776938364bSMaurice Kalinowski 	CALLED();
277834c72144SAxel Dörfler 	if (mimeType == NULL || _capability == NULL)
27796938364bSMaurice Kalinowski 		return B_BAD_VALUE;
27806938364bSMaurice Kalinowski 
27816938364bSMaurice Kalinowski 	fileinterface_sniff_ref_request request;
27826938364bSMaurice Kalinowski 	fileinterface_sniff_ref_reply reply;
27836938364bSMaurice Kalinowski 	status_t rv;
27846938364bSMaurice Kalinowski 
27856938364bSMaurice Kalinowski 	request.device = file.device;
27866938364bSMaurice Kalinowski 	request.directory = file.directory;
27876938364bSMaurice Kalinowski 	strcpy(request.name, file.name);
27886938364bSMaurice Kalinowski 
278934c72144SAxel Dörfler 	rv = QueryPort(file_interface.port, FILEINTERFACE_SNIFF_REF, &request,
279034c72144SAxel Dörfler 		sizeof(request), &reply, sizeof(reply));
27916938364bSMaurice Kalinowski 	if (rv != B_OK)
27926938364bSMaurice Kalinowski 		return rv;
27936938364bSMaurice Kalinowski 
279434c72144SAxel Dörfler 	mimeType->SetTo(reply.mimetype);
279534c72144SAxel Dörfler 	*_capability = reply.capability;
27966938364bSMaurice Kalinowski 
27976938364bSMaurice Kalinowski 	return B_OK;
279852a38012Sejakowatz }
279952a38012Sejakowatz 
280052a38012Sejakowatz 
280134c72144SAxel Dörfler /*!	This is the generic "here's a file, now can someone please play it"
280234c72144SAxel Dörfler 	interface.
280334c72144SAxel Dörfler */
280452a38012Sejakowatz status_t
280534c72144SAxel Dörfler BMediaRoster::SniffRef(const entry_ref& file, uint64 requireNodeKinds,
280634c72144SAxel Dörfler 	dormant_node_info* _node, BMimeType* mimeType)
280752a38012Sejakowatz {
280805f452c3SDavid McPaul 	CALLED();
280905f452c3SDavid McPaul 
281005f452c3SDavid McPaul 	TRACE("BMediaRoster::SniffRef looking for a node to handle %s : %Ld\n",file.name, requireNodeKinds);
281105f452c3SDavid McPaul 
281205f452c3SDavid McPaul 	if (_node == NULL)
281305f452c3SDavid McPaul 		return B_BAD_VALUE;
281405f452c3SDavid McPaul 
281505f452c3SDavid McPaul 	BMimeType aMimeType;
281605f452c3SDavid McPaul 
281705f452c3SDavid McPaul 	dormant_node_info nodes[30];
281805f452c3SDavid McPaul 	int32 count = 30;
281905f452c3SDavid McPaul 	int32 highestCapability = -1;
282005f452c3SDavid McPaul 	float capability;
282105f452c3SDavid McPaul 
282205f452c3SDavid McPaul 	media_node node;
282305f452c3SDavid McPaul 
282405f452c3SDavid McPaul 	// Get all dormant nodes using GetDormantNodes
28256f7f87a2SDavid McPaul 	if (GetDormantNodes(nodes, &count, NULL, NULL, NULL, requireNodeKinds | B_FILE_INTERFACE, 0) == B_OK) {
282605f452c3SDavid McPaul 		// Call SniffRefFor on each node that matches requireNodeKinds
282705f452c3SDavid McPaul 		for (int32 i=0;i<count;i++) {
28286f7f87a2SDavid McPaul 			if (InstantiateDormantNode(nodes[i], &node) == B_OK) {
282905f452c3SDavid McPaul 
28306f7f87a2SDavid McPaul 				if (SniffRefFor(node, file, &aMimeType, &capability) == B_OK) {
283105f452c3SDavid McPaul 					// find the first node that has 100% capability
283205f452c3SDavid McPaul 					TRACE("%s has a %f%% chance of playing file\n",nodes[i].name, capability * 100.0);
283305f452c3SDavid McPaul 					if (capability == 1.0) {
283405f452c3SDavid McPaul 						highestCapability = i;
283505f452c3SDavid McPaul 						break;
283605f452c3SDavid McPaul 					}
283705f452c3SDavid McPaul 				}
283805f452c3SDavid McPaul 				ReleaseNode(node);
283905f452c3SDavid McPaul 			}
284005f452c3SDavid McPaul 		}
284105f452c3SDavid McPaul 
284205f452c3SDavid McPaul 		if (highestCapability != -1) {
284305f452c3SDavid McPaul 			*_node = nodes[highestCapability];
284405f452c3SDavid McPaul 
284505f452c3SDavid McPaul 			TRACE("BMediaRoster::SniffRef: found a node %s addon-id %ld, flavor_id %ld\n",
284605f452c3SDavid McPaul 			nodes[highestCapability].name, nodes[highestCapability].addon, nodes[highestCapability].flavor_id);
284705f452c3SDavid McPaul 
284805f452c3SDavid McPaul 			if (mimeType != NULL) {
284905f452c3SDavid McPaul 				//*mimeType = aMimeType; -- need a copy constructor
285005f452c3SDavid McPaul 			}
285105f452c3SDavid McPaul 
285205f452c3SDavid McPaul 			return B_OK;
285305f452c3SDavid McPaul 		}
285405f452c3SDavid McPaul 
285505f452c3SDavid McPaul 	}
285605f452c3SDavid McPaul 
285752a38012Sejakowatz 	return B_ERROR;
285852a38012Sejakowatz }
285952a38012Sejakowatz 
286052a38012Sejakowatz 
286152a38012Sejakowatz status_t
286252a38012Sejakowatz BMediaRoster::GetDormantNodeForType(const BMimeType& type,
286334c72144SAxel Dörfler 	uint64 requireNodeKinds, dormant_node_info* _node)
286452a38012Sejakowatz {
286552a38012Sejakowatz 	UNIMPLEMENTED();
286652a38012Sejakowatz 	return B_ERROR;
286752a38012Sejakowatz }
286852a38012Sejakowatz 
286952a38012Sejakowatz 
287052a38012Sejakowatz status_t
287134c72144SAxel Dörfler BMediaRoster::GetReadFileFormatsFor(const dormant_node_info& node,
287234c72144SAxel Dörfler 	media_file_format* _readFormats, int32 readCount, int32* _readCount)
287352a38012Sejakowatz {
287452a38012Sejakowatz 	UNIMPLEMENTED();
287552a38012Sejakowatz 	return B_ERROR;
287652a38012Sejakowatz }
287752a38012Sejakowatz 
287852a38012Sejakowatz 
287952a38012Sejakowatz status_t
288034c72144SAxel Dörfler BMediaRoster::GetWriteFileFormatsFor(const dormant_node_info& node,
288134c72144SAxel Dörfler 	media_file_format* _write_formats, int32 writeCount, int32* _writeCount)
288252a38012Sejakowatz {
288352a38012Sejakowatz 	UNIMPLEMENTED();
288452a38012Sejakowatz 	return B_ERROR;
288552a38012Sejakowatz }
288652a38012Sejakowatz 
288752a38012Sejakowatz 
288852a38012Sejakowatz status_t
288934c72144SAxel Dörfler BMediaRoster::GetFormatFor(const media_output& output, media_format* _format,
289052a38012Sejakowatz 	uint32 flags)
289152a38012Sejakowatz {
28929bedd42cSbeveloper 	CALLED();
289334c72144SAxel Dörfler 	if (_format == NULL)
28949bedd42cSbeveloper 		return B_BAD_VALUE;
28959bedd42cSbeveloper 	if ((output.node.kind & B_BUFFER_PRODUCER) == 0)
28969bedd42cSbeveloper 		return B_MEDIA_BAD_NODE;
28979bedd42cSbeveloper 	if (IS_INVALID_SOURCE(output.source))
28989bedd42cSbeveloper 		return B_MEDIA_BAD_SOURCE;
28999bedd42cSbeveloper 
29009bedd42cSbeveloper 	producer_format_suggestion_requested_request request;
29019bedd42cSbeveloper 	producer_format_suggestion_requested_reply reply;
29029bedd42cSbeveloper 	status_t rv;
29039bedd42cSbeveloper 
29049bedd42cSbeveloper 	request.type = B_MEDIA_UNKNOWN_TYPE;
290534c72144SAxel Dörfler 	request.quality = 0; // TODO: what should this be?
29069bedd42cSbeveloper 
290734c72144SAxel Dörfler 	rv = QueryPort(output.source.port, PRODUCER_FORMAT_SUGGESTION_REQUESTED,
290834c72144SAxel Dörfler 		&request, sizeof(request), &reply, sizeof(reply));
29099bedd42cSbeveloper 	if (rv != B_OK)
29109bedd42cSbeveloper 		return rv;
29119bedd42cSbeveloper 
291234c72144SAxel Dörfler 	*_format = reply.format;
29139bedd42cSbeveloper 	return B_OK;
291452a38012Sejakowatz }
291552a38012Sejakowatz 
291652a38012Sejakowatz 
291752a38012Sejakowatz status_t
291834c72144SAxel Dörfler BMediaRoster::GetFormatFor(const media_input& input, media_format* _format,
291952a38012Sejakowatz 	uint32 flags)
292052a38012Sejakowatz {
29219bedd42cSbeveloper 	CALLED();
292234c72144SAxel Dörfler 	if (_format == NULL)
29239bedd42cSbeveloper 		return B_BAD_VALUE;
29249bedd42cSbeveloper 	if ((input.node.kind & B_BUFFER_CONSUMER) == 0)
29259bedd42cSbeveloper 		return B_MEDIA_BAD_NODE;
29269bedd42cSbeveloper 	if (IS_INVALID_DESTINATION(input.destination))
29279bedd42cSbeveloper 		return B_MEDIA_BAD_DESTINATION;
29289bedd42cSbeveloper 
29299bedd42cSbeveloper 	consumer_accept_format_request request;
29309bedd42cSbeveloper 	consumer_accept_format_reply reply;
29319bedd42cSbeveloper 	status_t rv;
29329bedd42cSbeveloper 
29339bedd42cSbeveloper 	request.dest = input.destination;
29349bedd42cSbeveloper 	memset(&request.format, 0, sizeof(request.format)); // wildcard
29359bedd42cSbeveloper 
293634c72144SAxel Dörfler 	rv = QueryPort(input.destination.port, CONSUMER_ACCEPT_FORMAT, &request,
293734c72144SAxel Dörfler 		sizeof(request), &reply, sizeof(reply));
29389bedd42cSbeveloper 	if (rv != B_OK)
29399bedd42cSbeveloper 		return rv;
29409bedd42cSbeveloper 
294134c72144SAxel Dörfler 	*_format = reply.format;
29429bedd42cSbeveloper 	return B_OK;
294352a38012Sejakowatz }
294452a38012Sejakowatz 
294552a38012Sejakowatz 
294652a38012Sejakowatz status_t
294734c72144SAxel Dörfler BMediaRoster::GetFormatFor(const media_node& node, media_format* _format,
294852a38012Sejakowatz 	float quality)
294952a38012Sejakowatz {
295052a38012Sejakowatz 	UNIMPLEMENTED();
295134c72144SAxel Dörfler 	if (_format == NULL)
29529bedd42cSbeveloper 		return B_BAD_VALUE;
29539bedd42cSbeveloper 	if (IS_INVALID_NODE(node))
29549bedd42cSbeveloper 		return B_MEDIA_BAD_NODE;
29559bedd42cSbeveloper 	if ((node.kind & (B_BUFFER_CONSUMER | B_BUFFER_PRODUCER)) == 0)
29569bedd42cSbeveloper 		return B_MEDIA_BAD_NODE;
29579bedd42cSbeveloper 
295852a38012Sejakowatz 	return B_ERROR;
295952a38012Sejakowatz }
296052a38012Sejakowatz 
296152a38012Sejakowatz 
296252a38012Sejakowatz ssize_t
296352a38012Sejakowatz BMediaRoster::GetNodeAttributesFor(const media_node& node,
296434c72144SAxel Dörfler 	media_node_attribute* _array, size_t maxCount)
296552a38012Sejakowatz {
296652a38012Sejakowatz 	UNIMPLEMENTED();
296752a38012Sejakowatz 	return B_ERROR;
296852a38012Sejakowatz }
296952a38012Sejakowatz 
297052a38012Sejakowatz 
297152a38012Sejakowatz media_node_id
297234c72144SAxel Dörfler BMediaRoster::NodeIDFor(port_id port)
297352a38012Sejakowatz {
29749e9417d2Sbeveloper 	CALLED();
29759e9417d2Sbeveloper 
29769e9417d2Sbeveloper 	server_node_id_for_request request;
29779e9417d2Sbeveloper 	server_node_id_for_reply reply;
29789e9417d2Sbeveloper 	status_t rv;
29799e9417d2Sbeveloper 
298034c72144SAxel Dörfler 	request.port = port;
29819e9417d2Sbeveloper 
298234c72144SAxel Dörfler 	rv = QueryServer(SERVER_NODE_ID_FOR, &request, sizeof(request), &reply,
298334c72144SAxel Dörfler 		sizeof(reply));
29849e9417d2Sbeveloper 	if (rv != B_OK) {
29855ac4fbd7Sbeveloper 		ERROR("BMediaRoster::NodeIDFor: failed (error %#lx)\n", rv);
29869e9417d2Sbeveloper 		return -1;
29879e9417d2Sbeveloper 	}
29889e9417d2Sbeveloper 
29899dec2310SAxel Dörfler 	return reply.node_id;
299052a38012Sejakowatz }
299152a38012Sejakowatz 
299252a38012Sejakowatz 
299352a38012Sejakowatz status_t
299434c72144SAxel Dörfler BMediaRoster::GetInstancesFor(media_addon_id addon, int32 flavor,
299534c72144SAxel Dörfler 	media_node_id* _id, int32* _count)
299652a38012Sejakowatz {
299785dfab2bSbeveloper 	CALLED();
299834c72144SAxel Dörfler 	if (_id == NULL)
299985dfab2bSbeveloper 		return B_BAD_VALUE;
300034c72144SAxel Dörfler 	if (_count && *_count <= 0)
300185dfab2bSbeveloper 		return B_BAD_VALUE;
300285dfab2bSbeveloper 
300385dfab2bSbeveloper 	server_get_instances_for_request request;
300485dfab2bSbeveloper 	server_get_instances_for_reply reply;
300585dfab2bSbeveloper 	status_t rv;
300685dfab2bSbeveloper 
30079c3b4706SAxel Dörfler 	request.max_count = (_count ? *_count : 1);
30089c3b4706SAxel Dörfler 	request.add_on_id = addon;
30099c3b4706SAxel Dörfler 	request.flavor_id = flavor;
301085dfab2bSbeveloper 
301134c72144SAxel Dörfler 	rv = QueryServer(SERVER_GET_INSTANCES_FOR, &request, sizeof(request),
301234c72144SAxel Dörfler 		&reply, sizeof(reply));
301385dfab2bSbeveloper 	if (rv != B_OK) {
30145ac4fbd7Sbeveloper 		ERROR("BMediaRoster::GetLiveNodes failed\n");
301585dfab2bSbeveloper 		return rv;
301652a38012Sejakowatz 	}
301752a38012Sejakowatz 
301834c72144SAxel Dörfler 	if (_count)
301934c72144SAxel Dörfler 		*_count = reply.count;
302085dfab2bSbeveloper 	if (reply.count > 0)
302134c72144SAxel Dörfler 		memcpy(_id, reply.node_id, sizeof(media_node_id) * reply.count);
302285dfab2bSbeveloper 
302385dfab2bSbeveloper 	return B_OK;
302485dfab2bSbeveloper }
302552a38012Sejakowatz 
302652a38012Sejakowatz 
302752a38012Sejakowatz status_t
302834c72144SAxel Dörfler BMediaRoster::SetRealtimeFlags(uint32 enabled)
302952a38012Sejakowatz {
303052a38012Sejakowatz 	UNIMPLEMENTED();
303152a38012Sejakowatz 	return B_ERROR;
303252a38012Sejakowatz }
303352a38012Sejakowatz 
303452a38012Sejakowatz 
303552a38012Sejakowatz status_t
303634c72144SAxel Dörfler BMediaRoster::GetRealtimeFlags(uint32* _enabled)
303752a38012Sejakowatz {
303852a38012Sejakowatz 	UNIMPLEMENTED();
303952a38012Sejakowatz 	return B_ERROR;
304052a38012Sejakowatz }
304152a38012Sejakowatz 
304252a38012Sejakowatz 
304352a38012Sejakowatz ssize_t
304434c72144SAxel Dörfler BMediaRoster::AudioBufferSizeFor(int32 channelCount, uint32 sampleFormat,
304534c72144SAxel Dörfler 	float frameRate, bus_type busKind)
304652a38012Sejakowatz {
304734c72144SAxel Dörfler 	bigtime_t bufferDuration;
304834c72144SAxel Dörfler 	ssize_t bufferSize;
3049df6c2e83Sbeveloper 
3050df6c2e83Sbeveloper 	system_info info;
3051df6c2e83Sbeveloper 	get_system_info(&info);
3052df6c2e83Sbeveloper 
305334c72144SAxel Dörfler 	if (info.cpu_clock_speed > 2000000000)	// 2 GHz
305434c72144SAxel Dörfler 		bufferDuration = 2500;
3055df6c2e83Sbeveloper 	else if (info.cpu_clock_speed > 1000000000)
305634c72144SAxel Dörfler 		bufferDuration = 5000;
3057df6c2e83Sbeveloper 	else if (info.cpu_clock_speed > 600000000)
305834c72144SAxel Dörfler 		bufferDuration = 10000;
3059df6c2e83Sbeveloper 	else if (info.cpu_clock_speed > 200000000)
306034c72144SAxel Dörfler 		bufferDuration = 20000;
3061df6c2e83Sbeveloper 	else if (info.cpu_clock_speed > 100000000)
306234c72144SAxel Dörfler 		bufferDuration = 30000;
3063df6c2e83Sbeveloper 	else
306434c72144SAxel Dörfler 		bufferDuration = 50000;
3065df6c2e83Sbeveloper 
306634c72144SAxel Dörfler 	if ((busKind == B_ISA_BUS || busKind == B_PCMCIA_BUS)
306734c72144SAxel Dörfler 		&& bufferDuration < 25000)
306834c72144SAxel Dörfler 		bufferDuration = 25000;
3069df6c2e83Sbeveloper 
307034c72144SAxel Dörfler 	bufferSize = (sampleFormat & 0xf) * channelCount
307134c72144SAxel Dörfler 		* (ssize_t)((frameRate * bufferDuration) / 1000000.0);
3072df6c2e83Sbeveloper 
307334c72144SAxel Dörfler 	printf("Suggested buffer duration %Ld, size %ld\n", bufferDuration,
307434c72144SAxel Dörfler 		bufferSize);
3075df6c2e83Sbeveloper 
307634c72144SAxel Dörfler 	return bufferSize;
307752a38012Sejakowatz }
307852a38012Sejakowatz 
307952a38012Sejakowatz 
308034c72144SAxel Dörfler /*!	Use MediaFlags to inquire about specific features of the Media Kit.
308134c72144SAxel Dörfler 	Returns < 0 for "not present", positive size for output data size.
308234c72144SAxel Dörfler 	0 means that the capability is present, but no data about it.
308334c72144SAxel Dörfler */
308452a38012Sejakowatz /*static*/ ssize_t
308534c72144SAxel Dörfler BMediaRoster::MediaFlags(media_flags cap, void* buffer, size_t maxSize)
308652a38012Sejakowatz {
308752a38012Sejakowatz 	UNIMPLEMENTED();
308852a38012Sejakowatz 	return 0;
308952a38012Sejakowatz }
309052a38012Sejakowatz 
309152a38012Sejakowatz 
309234c72144SAxel Dörfler //	#pragma mark - BLooper overrides
309334c72144SAxel Dörfler 
309434c72144SAxel Dörfler 
309534c72144SAxel Dörfler void
309652a38012Sejakowatz BMediaRoster::MessageReceived(BMessage* message)
309752a38012Sejakowatz {
3098cf4e2277Sbeveloper 	switch (message->what) {
3099cf4e2277Sbeveloper 		case 'PING':
3100cf4e2277Sbeveloper 		{
31016396865dSbeveloper 			// media_server plays ping-pong with the BMediaRosters
31026396865dSbeveloper 			// to detect dead teams. Normal communication uses ports.
31036396865dSbeveloper 			static BMessage pong('PONG');
31046396865dSbeveloper 			message->SendReply(&pong, static_cast<BHandler *>(NULL), 2000000);
31056396865dSbeveloper 			return;
31066396865dSbeveloper 		}
31076396865dSbeveloper 
3108cf4e2277Sbeveloper 		case NODE_FINAL_RELEASE:
3109cf4e2277Sbeveloper 		{
3110cf4e2277Sbeveloper 			// this function is called by a BMediaNode to delete
3111cf4e2277Sbeveloper 			// itself, as this needs to be done from another thread
3112cf4e2277Sbeveloper 			// context, it is done here.
311334c72144SAxel Dörfler 			// TODO: If a node is released using BMediaRoster::ReleaseNode()
311434c72144SAxel Dörfler 			// TODO: instead of using BMediaNode::Release() / BMediaNode::Acquire()
311534c72144SAxel Dörfler 			// TODO: fRefCount of the BMediaNode will not be correct.
3116cf4e2277Sbeveloper 
3117cf4e2277Sbeveloper 			BMediaNode *node;
3118cf4e2277Sbeveloper 			message->FindPointer("node", reinterpret_cast<void **>(&node));
3119cf4e2277Sbeveloper 
312054187cc6Sbeveloper 			TRACE("BMediaRoster::MessageReceived NODE_FINAL_RELEASE saving node %ld configuration\n", node->ID());
312154187cc6Sbeveloper 			MediaRosterEx(BMediaRoster::Roster())->SaveNodeConfiguration(node);
3122cf4e2277Sbeveloper 
312354187cc6Sbeveloper 			TRACE("BMediaRoster::MessageReceived NODE_FINAL_RELEASE releasing node %ld\n", node->ID());
3124cf4e2277Sbeveloper 			node->DeleteHook(node); // we don't call Release(), see above!
3125cf4e2277Sbeveloper 			return;
3126cf4e2277Sbeveloper 		}
3127cf4e2277Sbeveloper 	}
31286396865dSbeveloper 	printf("BMediaRoster::MessageReceived: unknown message!\n");
31296396865dSbeveloper 	message->PrintToStream();
313052a38012Sejakowatz }
313152a38012Sejakowatz 
313234c72144SAxel Dörfler 
313334c72144SAxel Dörfler bool
313452a38012Sejakowatz BMediaRoster::QuitRequested()
313552a38012Sejakowatz {
313652a38012Sejakowatz 	UNIMPLEMENTED();
313752a38012Sejakowatz 	return true;
313852a38012Sejakowatz }
313952a38012Sejakowatz 
314034c72144SAxel Dörfler 
314134c72144SAxel Dörfler BHandler*
314234c72144SAxel Dörfler BMediaRoster::ResolveSpecifier(BMessage* msg, int32 index, BMessage* specifier,
314334c72144SAxel Dörfler 	int32 form, const char* property)
314452a38012Sejakowatz {
3145286a3c91SJérôme Duval 	return BLooper::ResolveSpecifier(msg, index, specifier, form, property);
314652a38012Sejakowatz }
314752a38012Sejakowatz 
314852a38012Sejakowatz 
314934c72144SAxel Dörfler status_t
315052a38012Sejakowatz BMediaRoster::GetSupportedSuites(BMessage* data)
315152a38012Sejakowatz {
3152286a3c91SJérôme Duval 	return BLooper::GetSupportedSuites(data);
315352a38012Sejakowatz }
315452a38012Sejakowatz 
315552a38012Sejakowatz 
315652a38012Sejakowatz BMediaRoster::~BMediaRoster()
315752a38012Sejakowatz {
315852a38012Sejakowatz 	CALLED();
31596396865dSbeveloper 
31606396865dSbeveloper 	// unregister this application with the media server
31616396865dSbeveloper 	server_unregister_app_request request;
31626396865dSbeveloper 	server_unregister_app_reply reply;
31639dec2310SAxel Dörfler 	request.team = BPrivate::current_team();
316434c72144SAxel Dörfler 	QueryServer(SERVER_UNREGISTER_APP, &request, sizeof(request), &reply,
316534c72144SAxel Dörfler 		sizeof(reply));
31668b940bb4SStephan Aßmus 
31672f9ed888SAxel Dörfler 	BPrivate::SharedBufferList::Invalidate();
31682f9ed888SAxel Dörfler 
31698b940bb4SStephan Aßmus 	// Unset the global instance pointer, the destructor is also called
31708b940bb4SStephan Aßmus 	// if a client app calls Lock(); and Quit(); directly.
31719def3bf7SStephan Aßmus 	sDefaultInstance = NULL;
317252a38012Sejakowatz }
317352a38012Sejakowatz 
317452a38012Sejakowatz 
317534c72144SAxel Dörfler //	#pragma mark - private BMediaRoster
317634c72144SAxel Dörfler 
317752a38012Sejakowatz 
317852a38012Sejakowatz // deprecated call
317952a38012Sejakowatz status_t
318052a38012Sejakowatz BMediaRoster::SetOutputBuffersFor(const media_source& output,
318134c72144SAxel Dörfler 	BBufferGroup* group, bool willReclaim)
318252a38012Sejakowatz {
318352a38012Sejakowatz 	UNIMPLEMENTED();
31849e9417d2Sbeveloper 	debugger("BMediaRoster::SetOutputBuffersFor missing\n");
318552a38012Sejakowatz 	return B_ERROR;
318652a38012Sejakowatz }
318752a38012Sejakowatz 
318852a38012Sejakowatz 
318934c72144SAxel Dörfler /* FBC reserved virtuals */
319052a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_0(void *) { return B_ERROR; }
319152a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_1(void *) { return B_ERROR; }
319252a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_2(void *) { return B_ERROR; }
319352a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_3(void *) { return B_ERROR; }
319452a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_4(void *) { return B_ERROR; }
319552a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_5(void *) { return B_ERROR; }
319652a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_6(void *) { return B_ERROR; }
319752a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_7(void *) { return B_ERROR; }
319852a38012Sejakowatz 
319952a38012Sejakowatz 
320034c72144SAxel Dörfler BMediaRoster::BMediaRoster()
32012f9ed888SAxel Dörfler 	:
32022f9ed888SAxel Dörfler 	BLooper("_BMediaRoster_", B_URGENT_DISPLAY_PRIORITY,
320334c72144SAxel Dörfler 		B_LOOPER_PORT_DEFAULT_CAPACITY)
320452a38012Sejakowatz {
320552a38012Sejakowatz 	CALLED();
32066396865dSbeveloper 
32076396865dSbeveloper 	// start the looper
32086396865dSbeveloper 	Run();
320952a38012Sejakowatz }
321052a38012Sejakowatz 
32116396865dSbeveloper 
32129def3bf7SStephan Aßmus // TODO: Looks like these can be safely removed:
321352a38012Sejakowatz /*static*/ status_t
321452a38012Sejakowatz BMediaRoster::ParseCommand(BMessage& reply)
321552a38012Sejakowatz {
321652a38012Sejakowatz 	UNIMPLEMENTED();
321752a38012Sejakowatz 	return B_ERROR;
321852a38012Sejakowatz }
321952a38012Sejakowatz 
322052a38012Sejakowatz 
322152a38012Sejakowatz status_t
322234c72144SAxel Dörfler BMediaRoster::GetDefaultInfo(media_node_id forDefault, BMessage& config)
322352a38012Sejakowatz {
322452a38012Sejakowatz 	UNIMPLEMENTED();
322552a38012Sejakowatz 	return B_ERROR;
322652a38012Sejakowatz }
322752a38012Sejakowatz 
322852a38012Sejakowatz 
322952a38012Sejakowatz status_t
323034c72144SAxel Dörfler BMediaRoster::SetRunningDefault(media_node_id forDefault,
323152a38012Sejakowatz 	const media_node& node)
323252a38012Sejakowatz {
323352a38012Sejakowatz 	UNIMPLEMENTED();
323452a38012Sejakowatz 	return B_ERROR;
323552a38012Sejakowatz }
323652a38012Sejakowatz 
323752a38012Sejakowatz 
32389def3bf7SStephan Aßmus // #pragma mark - static variables
323952a38012Sejakowatz 
32409def3bf7SStephan Aßmus 
32419def3bf7SStephan Aßmus BMediaRoster* BMediaRoster::sDefaultInstance = NULL;
324252a38012Sejakowatz 
3243