xref: /haiku/src/kits/media/MediaRoster.cpp (revision 8496c38a3de20dae2d827969eb08d4b7f58a6fac)
1255a01c7Sbeveloper /*
2255a01c7Sbeveloper  * Copyright (c) 2002, 2003 Marcus Overhagen <Marcus@Overhagen.de>
3255a01c7Sbeveloper  *
4255a01c7Sbeveloper  * Permission is hereby granted, free of charge, to any person obtaining
5255a01c7Sbeveloper  * a copy of this software and associated documentation files or portions
6255a01c7Sbeveloper  * thereof (the "Software"), to deal in the Software without restriction,
7255a01c7Sbeveloper  * including without limitation the rights to use, copy, modify, merge,
8255a01c7Sbeveloper  * publish, distribute, sublicense, and/or sell copies of the Software,
9255a01c7Sbeveloper  * and to permit persons to whom the Software is furnished to do so, subject
10255a01c7Sbeveloper  * to the following conditions:
11255a01c7Sbeveloper  *
12255a01c7Sbeveloper  *  * Redistributions of source code must retain the above copyright notice,
13255a01c7Sbeveloper  *    this list of conditions and the following disclaimer.
14255a01c7Sbeveloper  *
15255a01c7Sbeveloper  *  * Redistributions in binary form must reproduce the above copyright notice
16255a01c7Sbeveloper  *    in the  binary, as well as this list of conditions and the following
17255a01c7Sbeveloper  *    disclaimer in the documentation and/or other materials provided with
18255a01c7Sbeveloper  *    the distribution.
19255a01c7Sbeveloper  *
20255a01c7Sbeveloper  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
21255a01c7Sbeveloper  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22255a01c7Sbeveloper  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
23255a01c7Sbeveloper  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24255a01c7Sbeveloper  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25255a01c7Sbeveloper  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
26255a01c7Sbeveloper  * THE SOFTWARE.
27255a01c7Sbeveloper  *
28255a01c7Sbeveloper  */
29255a01c7Sbeveloper 
30255a01c7Sbeveloper /* to comply with the license above, do not remove the following line */
31d91580cdSbeveloper char __dont_remove_copyright_from_binary[] = "Copyright (c) 2002, 2003 Marcus Overhagen <Marcus@Overhagen.de>";
32255a01c7Sbeveloper 
3352a38012Sejakowatz #include <MediaRoster.h>
3452a38012Sejakowatz #include <Locker.h>
3552a38012Sejakowatz #include <Message.h>
3652a38012Sejakowatz #include <Messenger.h>
3752a38012Sejakowatz #include <StopWatch.h>
3852a38012Sejakowatz #include <OS.h>
3952a38012Sejakowatz #include <String.h>
4052a38012Sejakowatz #include <TimeSource.h>
4160f15390Sbeveloper #include <ParameterWeb.h>
424d2d96e0Sbeveloper #include <BufferProducer.h>
434d2d96e0Sbeveloper #include <BufferConsumer.h>
4452a38012Sejakowatz #include "debug.h"
458b04ffc1Sbeveloper #include "MediaRosterEx.h"
4640f36b03Sbeveloper #include "MediaMisc.h"
4752a38012Sejakowatz #include "PortPool.h"
480a483e72SIngo Weinhold #include "ServerInterface.h"
49f4925104Sbeveloper #include "DataExchange.h"
5016b7eea4Sbeveloper #include "DormantNodeManager.h"
51f4925104Sbeveloper #include "Notifications.h"
52835140c8Sbeveloper #include "TimeSourceObjectManager.h"
5352a38012Sejakowatz 
54f4925104Sbeveloper namespace BPrivate { namespace media {
5552a38012Sejakowatz 
5652a38012Sejakowatz 	// the BMediaRoster destructor is private,
5752a38012Sejakowatz 	// but _DefaultDeleter is a friend class of
5852a38012Sejakowatz 	// the BMediaRoster an thus can delete it
598b04ffc1Sbeveloper 	class DefaultDeleter
6052a38012Sejakowatz 	{
6152a38012Sejakowatz 	public:
628b04ffc1Sbeveloper 		~DefaultDeleter()
636396865dSbeveloper 		{
646396865dSbeveloper 			if (BMediaRoster::_sDefault) {
656396865dSbeveloper 				BMediaRoster::_sDefault->Lock();
666396865dSbeveloper 				BMediaRoster::_sDefault->Quit();
676396865dSbeveloper 			}
686396865dSbeveloper 		}
698b04ffc1Sbeveloper 	};
7052a38012Sejakowatz 
718b04ffc1Sbeveloper } } // BPrivate::media
728b04ffc1Sbeveloper using namespace BPrivate::media;
7352a38012Sejakowatz 
748b04ffc1Sbeveloper // DefaultDeleter will delete the BMediaRoster object in it's destructor.
758b04ffc1Sbeveloper DefaultDeleter _deleter;
7652a38012Sejakowatz 
77dcfb6bfcSJérôme Duval BMediaRosterEx::BMediaRosterEx(status_t * out_error)
78dcfb6bfcSJérôme Duval 	: BMediaRoster()
79dcfb6bfcSJérôme Duval {
80dcfb6bfcSJérôme Duval 	status_t rv;
81dcfb6bfcSJérôme Duval 	// register this application with the media server
82dcfb6bfcSJérôme Duval 	server_register_app_request request;
83dcfb6bfcSJérôme Duval 	server_register_app_reply reply;
84dcfb6bfcSJérôme Duval 	request.team = team;
85dcfb6bfcSJérôme Duval 	request.messenger = BMessenger(NULL, this);
86dcfb6bfcSJérôme Duval 	rv = QueryServer(SERVER_REGISTER_APP, &request, sizeof(request), &reply, sizeof(reply));
87*8496c38aSbeveloper 	*out_error = (rv != B_OK) ? B_MEDIA_SYSTEM_FAILURE : B_OK;
88dcfb6bfcSJérôme Duval }
89dcfb6bfcSJérôme Duval 
903620737cSbeveloper status_t
9154187cc6Sbeveloper BMediaRosterEx::SaveNodeConfiguration(BMediaNode *node)
9254187cc6Sbeveloper {
9354187cc6Sbeveloper 	BMediaAddOn *addon;
9454187cc6Sbeveloper 	media_addon_id addonid;
9554187cc6Sbeveloper 	int32 flavorid;
9654187cc6Sbeveloper 	addon = node->AddOn(&flavorid);
9754187cc6Sbeveloper 	if (!addon) {
9860f15390Sbeveloper 		// XXX this check incorrectly triggers on BeOS R5 BT848 node
995ac4fbd7Sbeveloper 		ERROR("BMediaRosterEx::SaveNodeConfiguration node %ld not instantiated from BMediaAddOn!\n", node->ID());
10054187cc6Sbeveloper 		return B_ERROR;
10154187cc6Sbeveloper 	}
10254187cc6Sbeveloper 	addonid = addon->AddonID();
10354187cc6Sbeveloper 
10454187cc6Sbeveloper 	// XXX fix this
10554187cc6Sbeveloper 	printf("### BMediaRosterEx::SaveNodeConfiguration should save addon-id %ld, flavor-id %ld config NOW!\n", addonid, flavorid);
10654187cc6Sbeveloper 	return B_OK;
10754187cc6Sbeveloper }
10854187cc6Sbeveloper 
10954187cc6Sbeveloper status_t
11054187cc6Sbeveloper BMediaRosterEx::LoadNodeConfiguration(media_addon_id addonid, int32 flavorid, BMessage *out_msg)
11154187cc6Sbeveloper {
11254187cc6Sbeveloper 	// XXX fix this
11354187cc6Sbeveloper 	out_msg->MakeEmpty(); // to be fully R5 compliant
11454187cc6Sbeveloper 	printf("### BMediaRosterEx::LoadNodeConfiguration should load addon-id %ld, flavor-id %ld config NOW!\n", addonid, flavorid);
11554187cc6Sbeveloper 	return B_OK;
11654187cc6Sbeveloper }
11754187cc6Sbeveloper 
11854187cc6Sbeveloper status_t
11973794717Sbeveloper BMediaRosterEx::IncrementAddonFlavorInstancesCount(media_addon_id addonid, int32 flavorid)
12054187cc6Sbeveloper {
12173794717Sbeveloper 	server_change_addon_flavor_instances_count_request request;
12273794717Sbeveloper 	server_change_addon_flavor_instances_count_reply reply;
12373794717Sbeveloper 
12473794717Sbeveloper 	request.addonid = addonid;
12573794717Sbeveloper 	request.flavorid = flavorid;
12673794717Sbeveloper 	request.delta = 1;
12773794717Sbeveloper 	request.team = team;
12873794717Sbeveloper 	return QueryServer(SERVER_CHANGE_ADDON_FLAVOR_INSTANCES_COUNT, &request, sizeof(request), &reply, sizeof(reply));
12954187cc6Sbeveloper }
13054187cc6Sbeveloper 
13154187cc6Sbeveloper status_t
13273794717Sbeveloper BMediaRosterEx::DecrementAddonFlavorInstancesCount(media_addon_id addonid, int32 flavorid)
13354187cc6Sbeveloper {
13473794717Sbeveloper 	server_change_addon_flavor_instances_count_request request;
13573794717Sbeveloper 	server_change_addon_flavor_instances_count_reply reply;
13673794717Sbeveloper 
13773794717Sbeveloper 	request.addonid = addonid;
13873794717Sbeveloper 	request.flavorid = flavorid;
13973794717Sbeveloper 	request.delta = -1;
14073794717Sbeveloper 	request.team = team;
14173794717Sbeveloper 	return QueryServer(SERVER_CHANGE_ADDON_FLAVOR_INSTANCES_COUNT, &request, sizeof(request), &reply, sizeof(reply));
14254187cc6Sbeveloper }
14354187cc6Sbeveloper 
14454187cc6Sbeveloper status_t
14554187cc6Sbeveloper BMediaRosterEx::SetNodeCreator(media_node_id node, team_id creator)
14654187cc6Sbeveloper {
14754187cc6Sbeveloper 	server_set_node_creator_request request;
14854187cc6Sbeveloper 	server_set_node_creator_reply reply;
14954187cc6Sbeveloper 
15054187cc6Sbeveloper 	request.node = node;
15154187cc6Sbeveloper 	request.creator = creator;
15254187cc6Sbeveloper 	return QueryServer(SERVER_SET_NODE_CREATOR, &request, sizeof(request), &reply, sizeof(reply));
15354187cc6Sbeveloper }
15454187cc6Sbeveloper 
15554187cc6Sbeveloper status_t
1568b04ffc1Sbeveloper BMediaRosterEx::GetNode(node_type type, media_node * out_node, int32 * out_input_id, BString * out_input_name)
15752a38012Sejakowatz {
15852a38012Sejakowatz 	if (out_node == NULL)
15952a38012Sejakowatz 		return B_BAD_VALUE;
16052a38012Sejakowatz 
1618c6a6096Sbeveloper 	server_get_node_request request;
1628c6a6096Sbeveloper 	server_get_node_reply reply;
16352a38012Sejakowatz 	status_t rv;
16452a38012Sejakowatz 
1658c6a6096Sbeveloper 	request.type = type;
1669e9417d2Sbeveloper 	request.team = team;
1678c6a6096Sbeveloper 	rv = QueryServer(SERVER_GET_NODE, &request, sizeof(request), &reply, sizeof(reply));
1688c6a6096Sbeveloper 	if (rv != B_OK)
1698c6a6096Sbeveloper 		return rv;
17052a38012Sejakowatz 
17152a38012Sejakowatz 	*out_node = reply.node;
17252a38012Sejakowatz 	if (out_input_id)
17352a38012Sejakowatz 		*out_input_id = reply.input_id;
17452a38012Sejakowatz 	if (out_input_name)
17552a38012Sejakowatz 		*out_input_name = reply.input_name;
1768c6a6096Sbeveloper 	return rv;
17752a38012Sejakowatz }
17852a38012Sejakowatz 
1793620737cSbeveloper status_t
1808b04ffc1Sbeveloper BMediaRosterEx::SetNode(node_type type, const media_node *node, const dormant_node_info *info, const media_input *input)
18152a38012Sejakowatz {
1828c6a6096Sbeveloper 	server_set_node_request request;
1838c6a6096Sbeveloper 	server_set_node_reply reply;
18452a38012Sejakowatz 
1858c6a6096Sbeveloper 	request.type = type;
1868c6a6096Sbeveloper 	request.use_node = node ? true : false;
18752a38012Sejakowatz 	if (node)
1888c6a6096Sbeveloper 		request.node = *node;
1898c6a6096Sbeveloper 	request.use_dni = info ? true : false;
19052a38012Sejakowatz 	if (info)
1918c6a6096Sbeveloper 		request.dni = *info;
1928c6a6096Sbeveloper 	request.use_input = input ? true : false;
19352a38012Sejakowatz 	if (input)
1948c6a6096Sbeveloper 		request.input = *input;
19552a38012Sejakowatz 
1968c6a6096Sbeveloper 	return QueryServer(SERVER_SET_NODE, &request, sizeof(request), &reply, sizeof(reply));
19752a38012Sejakowatz }
19852a38012Sejakowatz 
1993620737cSbeveloper status_t
2008b04ffc1Sbeveloper BMediaRosterEx::GetAllOutputs(const media_node & node, List<media_output> *list)
2013620737cSbeveloper {
2023620737cSbeveloper 	int32 cookie;
2033620737cSbeveloper 	status_t rv;
2043620737cSbeveloper 	status_t result;
2053620737cSbeveloper 
2065ac4fbd7Sbeveloper 	PRINT(4, "BMediaRosterEx::GetAllOutputs() node %ld, port %ld\n", node.node, node.port);
2075ac4fbd7Sbeveloper 
2083620737cSbeveloper 	result = B_OK;
2093620737cSbeveloper 	cookie = 0;
21076669a29Sbeveloper 	list->MakeEmpty();
2113620737cSbeveloper 	for (;;) {
2123620737cSbeveloper 		producer_get_next_output_request request;
2133620737cSbeveloper 		producer_get_next_output_reply reply;
2143620737cSbeveloper 		request.cookie = cookie;
2150caff283Sbeveloper 		rv = QueryPort(node.port, PRODUCER_GET_NEXT_OUTPUT, &request, sizeof(request), &reply, sizeof(reply));
2163620737cSbeveloper 		if (rv != B_OK)
2173620737cSbeveloper 			break;
2183620737cSbeveloper 		cookie = reply.cookie;
21976669a29Sbeveloper 		if (!list->Insert(reply.output)) {
2205ac4fbd7Sbeveloper 			ERROR("GetAllOutputs: list->Insert failed\n");
2213620737cSbeveloper 			result = B_ERROR;
2223620737cSbeveloper 		}
2235ac4fbd7Sbeveloper 		#if DEBUG >= 3
2245ac4fbd7Sbeveloper 			PRINT(3," next cookie %ld, ", cookie);
2255ac4fbd7Sbeveloper 			PRINT_OUTPUT("output ", reply.output);
2265ac4fbd7Sbeveloper 		#endif
2273620737cSbeveloper 	}
2283620737cSbeveloper 
2293620737cSbeveloper 	producer_dispose_output_cookie_request request;
2303620737cSbeveloper 	producer_dispose_output_cookie_reply reply;
2310caff283Sbeveloper 	QueryPort(node.port, PRODUCER_DISPOSE_OUTPUT_COOKIE, &request, sizeof(request), &reply, sizeof(reply));
2323620737cSbeveloper 
2333620737cSbeveloper 	return result;
2343620737cSbeveloper }
2353620737cSbeveloper 
2363620737cSbeveloper status_t
2374d2d96e0Sbeveloper BMediaRosterEx::GetAllOutputs(BBufferProducer *node, List<media_output> *list)
2384d2d96e0Sbeveloper {
2394d2d96e0Sbeveloper 	int32 cookie;
2404d2d96e0Sbeveloper 	status_t result;
2414d2d96e0Sbeveloper 
2424d2d96e0Sbeveloper 	PRINT(4, "BMediaRosterEx::GetAllOutputs() (by pointer) node %ld, port %ld\n", node->ID(), node->ControlPort());
2434d2d96e0Sbeveloper 
2444d2d96e0Sbeveloper 	result = B_OK;
2454d2d96e0Sbeveloper 	cookie = 0;
2464d2d96e0Sbeveloper 	list->MakeEmpty();
2474d2d96e0Sbeveloper 	for (;;) {
2484d2d96e0Sbeveloper 		media_output output;
2494d2d96e0Sbeveloper 		if (B_OK != node->GetNextOutput(&cookie, &output))
2504d2d96e0Sbeveloper 			break;
2514d2d96e0Sbeveloper 		if (!list->Insert(output)) {
2524d2d96e0Sbeveloper 			ERROR("GetAllOutputs: list->Insert failed\n");
2534d2d96e0Sbeveloper 			result = B_ERROR;
2544d2d96e0Sbeveloper 		}
2554d2d96e0Sbeveloper 		#if DEBUG >= 3
2564d2d96e0Sbeveloper 			PRINT(3," next cookie %ld, ", cookie);
2574d2d96e0Sbeveloper 			PRINT_OUTPUT("output ", output);
2584d2d96e0Sbeveloper 		#endif
2594d2d96e0Sbeveloper 	}
2604d2d96e0Sbeveloper 	node->DisposeOutputCookie(cookie);
2614d2d96e0Sbeveloper 	return result;
2624d2d96e0Sbeveloper }
2634d2d96e0Sbeveloper 
2644d2d96e0Sbeveloper status_t
2658b04ffc1Sbeveloper BMediaRosterEx::GetAllInputs(const media_node & node, List<media_input> *list)
2663620737cSbeveloper {
2673620737cSbeveloper 	int32 cookie;
2683620737cSbeveloper 	status_t rv;
2693620737cSbeveloper 	status_t result;
2703620737cSbeveloper 
2715ac4fbd7Sbeveloper 	PRINT(4, "BMediaRosterEx::GetAllInputs() node %ld, port %ld\n", node.node, node.port);
2725ac4fbd7Sbeveloper 
2733620737cSbeveloper 	result = B_OK;
2743620737cSbeveloper 	cookie = 0;
27576669a29Sbeveloper 	list->MakeEmpty();
2763620737cSbeveloper 	for (;;) {
2773620737cSbeveloper 		consumer_get_next_input_request request;
2783620737cSbeveloper 		consumer_get_next_input_reply reply;
2793620737cSbeveloper 		request.cookie = cookie;
2800caff283Sbeveloper 		rv = QueryPort(node.port, CONSUMER_GET_NEXT_INPUT, &request, sizeof(request), &reply, sizeof(reply));
2813620737cSbeveloper 		if (rv != B_OK)
2823620737cSbeveloper 			break;
2833620737cSbeveloper 		cookie = reply.cookie;
28476669a29Sbeveloper 		if (!list->Insert(reply.input)) {
2855ac4fbd7Sbeveloper 			ERROR("GetAllInputs: list->Insert failed\n");
2863620737cSbeveloper 			result = B_ERROR;
2873620737cSbeveloper 		}
2885ac4fbd7Sbeveloper 		#if DEBUG >= 3
2895ac4fbd7Sbeveloper 			PRINT(3," next cookie %ld, ", cookie);
2905ac4fbd7Sbeveloper 			PRINT_OUTPUT("input ", reply.input);
2915ac4fbd7Sbeveloper 		#endif
2923620737cSbeveloper 	}
2933620737cSbeveloper 
2943620737cSbeveloper 	consumer_dispose_input_cookie_request request;
2953620737cSbeveloper 	consumer_dispose_input_cookie_reply reply;
2960caff283Sbeveloper 	QueryPort(node.port, CONSUMER_DISPOSE_INPUT_COOKIE, &request, sizeof(request), &reply, sizeof(reply));
2973620737cSbeveloper 
2983620737cSbeveloper 	return result;
2993620737cSbeveloper }
3003620737cSbeveloper 
3013620737cSbeveloper status_t
3024d2d96e0Sbeveloper BMediaRosterEx::GetAllInputs(BBufferConsumer *node, List<media_input> *list)
3034d2d96e0Sbeveloper {
3044d2d96e0Sbeveloper 	int32 cookie;
3054d2d96e0Sbeveloper 	status_t result;
3064d2d96e0Sbeveloper 
3074d2d96e0Sbeveloper 	PRINT(4, "BMediaRosterEx::GetAllInputs() (by pointer) node %ld, port %ld\n", node->ID(), node->ControlPort());
3084d2d96e0Sbeveloper 
3094d2d96e0Sbeveloper 	result = B_OK;
3104d2d96e0Sbeveloper 	cookie = 0;
3114d2d96e0Sbeveloper 	list->MakeEmpty();
3124d2d96e0Sbeveloper 	for (;;) {
3134d2d96e0Sbeveloper 		media_input input;
3144d2d96e0Sbeveloper 		if (B_OK != node->GetNextInput(&cookie, &input))
3154d2d96e0Sbeveloper 			break;
3164d2d96e0Sbeveloper 		if (!list->Insert(input)) {
3174d2d96e0Sbeveloper 			ERROR("GetAllInputs: list->Insert failed\n");
3184d2d96e0Sbeveloper 			result = B_ERROR;
3194d2d96e0Sbeveloper 		}
3204d2d96e0Sbeveloper 		#if DEBUG >= 3
3214d2d96e0Sbeveloper 			PRINT(3," next cookie %ld, ", cookie);
3224d2d96e0Sbeveloper 			PRINT_INPUT("input ", input);
3234d2d96e0Sbeveloper 		#endif
3244d2d96e0Sbeveloper 	}
3254d2d96e0Sbeveloper 	node->DisposeInputCookie(cookie);
3264d2d96e0Sbeveloper 	return result;
3274d2d96e0Sbeveloper }
3284d2d96e0Sbeveloper 
3294d2d96e0Sbeveloper status_t
3308b04ffc1Sbeveloper BMediaRosterEx::PublishOutputs(const media_node & node, List<media_output> *list)
3313620737cSbeveloper {
3323620737cSbeveloper 	server_publish_outputs_request request;
3333620737cSbeveloper 	server_publish_outputs_reply reply;
3343620737cSbeveloper 	media_output *output;
3353620737cSbeveloper 	media_output *outputs;
3363620737cSbeveloper 	int32 count;
337a7b41a96Sbeveloper 	status_t rv;
3383620737cSbeveloper 
33976669a29Sbeveloper 	count = list->CountItems();
3403620737cSbeveloper 	TRACE("PublishOutputs: publishing %ld\n", count);
3413620737cSbeveloper 
3423620737cSbeveloper 	request.node = node;
3433620737cSbeveloper 	request.count = count;
3443620737cSbeveloper 	if (count > MAX_OUTPUTS) {
3453620737cSbeveloper 		void *start_addr;
3463620737cSbeveloper 		size_t size;
34740f36b03Sbeveloper 		size = ROUND_UP_TO_PAGE(count * sizeof(media_output));
3483620737cSbeveloper 		request.area = create_area("publish outputs", &start_addr, B_ANY_ADDRESS, size, B_NO_LOCK, B_READ_AREA | B_WRITE_AREA);
3493620737cSbeveloper 		if (request.area < B_OK) {
3505ac4fbd7Sbeveloper 			ERROR("PublishOutputs: failed to create area, %#lx\n", request.area);
3513620737cSbeveloper 			return (status_t)request.area;
3523620737cSbeveloper 		}
3533620737cSbeveloper 		outputs = static_cast<media_output *>(start_addr);
3543620737cSbeveloper 	} else {
3553620737cSbeveloper 		request.area = -1;
3563620737cSbeveloper 		outputs = request.outputs;
3573620737cSbeveloper 	}
35876669a29Sbeveloper 	TRACE("PublishOutputs: area %ld\n", request.area);
3593620737cSbeveloper 
36076669a29Sbeveloper 	int i;
36176669a29Sbeveloper 	for (i = 0, list->Rewind(); list->GetNext(&output); i++) {
36276669a29Sbeveloper 		ASSERT(i < count);
3633620737cSbeveloper 		outputs[i] = *output;
3643620737cSbeveloper 	}
3653620737cSbeveloper 
366a7b41a96Sbeveloper 	rv = QueryServer(SERVER_PUBLISH_OUTPUTS, &request, sizeof(request), &reply, sizeof(reply));
367a7b41a96Sbeveloper 
368a7b41a96Sbeveloper 	if (request.area != -1)
369a7b41a96Sbeveloper 		delete_area(request.area);
370a7b41a96Sbeveloper 
371a7b41a96Sbeveloper 	return rv;
3723620737cSbeveloper }
3733620737cSbeveloper 
3743620737cSbeveloper status_t
3758b04ffc1Sbeveloper BMediaRosterEx::PublishInputs(const media_node & node, List<media_input> *list)
3763620737cSbeveloper {
3773620737cSbeveloper 	server_publish_inputs_request request;
3783620737cSbeveloper 	server_publish_inputs_reply reply;
3793620737cSbeveloper 	media_input *input;
3803620737cSbeveloper 	media_input *inputs;
3813620737cSbeveloper 	int32 count;
382a7b41a96Sbeveloper 	status_t rv;
3833620737cSbeveloper 
38476669a29Sbeveloper 	count = list->CountItems();
3853620737cSbeveloper 	TRACE("PublishInputs: publishing %ld\n", count);
3863620737cSbeveloper 
3873620737cSbeveloper 	request.node = node;
3883620737cSbeveloper 	request.count = count;
3893620737cSbeveloper 	if (count > MAX_INPUTS) {
3903620737cSbeveloper 		void *start_addr;
3913620737cSbeveloper 		size_t size;
39240f36b03Sbeveloper 		size = ROUND_UP_TO_PAGE(count * sizeof(media_input));
3933620737cSbeveloper 		request.area = create_area("publish inputs", &start_addr, B_ANY_ADDRESS, size, B_NO_LOCK, B_READ_AREA | B_WRITE_AREA);
3943620737cSbeveloper 		if (request.area < B_OK) {
3955ac4fbd7Sbeveloper 			ERROR("PublishInputs: failed to create area, %#lx\n", request.area);
3963620737cSbeveloper 			return (status_t)request.area;
3973620737cSbeveloper 		}
3983620737cSbeveloper 		inputs = static_cast<media_input *>(start_addr);
3993620737cSbeveloper 	} else {
4003620737cSbeveloper 		request.area = -1;
4013620737cSbeveloper 		inputs = request.inputs;
4023620737cSbeveloper 	}
40376669a29Sbeveloper 	TRACE("PublishInputs: area %ld\n", request.area);
4043620737cSbeveloper 
40576669a29Sbeveloper 	int i;
40676669a29Sbeveloper 	for (i = 0, list->Rewind(); list->GetNext(&input); i++) {
40776669a29Sbeveloper 		ASSERT(i < count);
4083620737cSbeveloper 		inputs[i] = *input;
4093620737cSbeveloper 	}
4103620737cSbeveloper 
411a7b41a96Sbeveloper 	rv = QueryServer(SERVER_PUBLISH_INPUTS, &request, sizeof(request), &reply, sizeof(reply));
412a7b41a96Sbeveloper 
413a7b41a96Sbeveloper 	if (request.area != -1)
414a7b41a96Sbeveloper 		delete_area(request.area);
415a7b41a96Sbeveloper 
416a7b41a96Sbeveloper 	return rv;
4173620737cSbeveloper }
4183620737cSbeveloper 
41952a38012Sejakowatz /*************************************************************
42052a38012Sejakowatz  * public BMediaRoster
42152a38012Sejakowatz  *************************************************************/
42252a38012Sejakowatz 
42352a38012Sejakowatz status_t
42452a38012Sejakowatz BMediaRoster::GetVideoInput(media_node * out_node)
42552a38012Sejakowatz {
42652a38012Sejakowatz 	CALLED();
4278b04ffc1Sbeveloper 	return MediaRosterEx(this)->GetNode(VIDEO_INPUT, out_node);
42852a38012Sejakowatz }
42952a38012Sejakowatz 
43052a38012Sejakowatz 
43152a38012Sejakowatz status_t
43252a38012Sejakowatz BMediaRoster::GetAudioInput(media_node * out_node)
43352a38012Sejakowatz {
43452a38012Sejakowatz 	CALLED();
4358b04ffc1Sbeveloper 	return MediaRosterEx(this)->GetNode(AUDIO_INPUT, out_node);
43652a38012Sejakowatz }
43752a38012Sejakowatz 
43852a38012Sejakowatz 
43952a38012Sejakowatz status_t
44052a38012Sejakowatz BMediaRoster::GetVideoOutput(media_node * out_node)
44152a38012Sejakowatz {
44252a38012Sejakowatz 	CALLED();
4438b04ffc1Sbeveloper 	return MediaRosterEx(this)->GetNode(VIDEO_OUTPUT, out_node);
44452a38012Sejakowatz }
44552a38012Sejakowatz 
44652a38012Sejakowatz 
44752a38012Sejakowatz status_t
44852a38012Sejakowatz BMediaRoster::GetAudioMixer(media_node * out_node)
44952a38012Sejakowatz {
45052a38012Sejakowatz 	CALLED();
4518b04ffc1Sbeveloper 	return MediaRosterEx(this)->GetNode(AUDIO_MIXER, out_node);
45252a38012Sejakowatz }
45352a38012Sejakowatz 
45452a38012Sejakowatz 
45552a38012Sejakowatz status_t
45652a38012Sejakowatz BMediaRoster::GetAudioOutput(media_node * out_node)
45752a38012Sejakowatz {
45852a38012Sejakowatz 	CALLED();
4598b04ffc1Sbeveloper 	return MediaRosterEx(this)->GetNode(AUDIO_OUTPUT, out_node);
46052a38012Sejakowatz }
46152a38012Sejakowatz 
46252a38012Sejakowatz 
46352a38012Sejakowatz status_t
46452a38012Sejakowatz BMediaRoster::GetAudioOutput(media_node * out_node,
46552a38012Sejakowatz 							 int32 * out_input_id,
46652a38012Sejakowatz 							 BString * out_input_name)
46752a38012Sejakowatz {
46852a38012Sejakowatz 	CALLED();
4698b04ffc1Sbeveloper 	return MediaRosterEx(this)->GetNode(AUDIO_OUTPUT_EX, out_node, out_input_id, out_input_name);
47052a38012Sejakowatz }
47152a38012Sejakowatz 
47252a38012Sejakowatz 
47352a38012Sejakowatz status_t
47452a38012Sejakowatz BMediaRoster::GetTimeSource(media_node * out_node)
47552a38012Sejakowatz {
47652a38012Sejakowatz 	CALLED();
47786bce45bSbeveloper 	status_t rv;
47886bce45bSbeveloper 
47986bce45bSbeveloper 	// XXX need to do this in a nicer way.
48086bce45bSbeveloper 
48186bce45bSbeveloper 	rv = MediaRosterEx(this)->GetNode(TIME_SOURCE, out_node);
48286bce45bSbeveloper 	if (rv != B_OK)
48386bce45bSbeveloper 		return rv;
48486bce45bSbeveloper 
48586bce45bSbeveloper 	// We don't do reference counting for timesources, that's why we
48686bce45bSbeveloper 	// release the node immediately.
48786bce45bSbeveloper 	ReleaseNode(*out_node);
48886bce45bSbeveloper 
48986bce45bSbeveloper 	// we need to remember to not use this node with server side reference counting
49086bce45bSbeveloper 	out_node->kind |= NODE_KIND_NO_REFCOUNTING;
49186bce45bSbeveloper 
49286bce45bSbeveloper 	return B_OK;
49352a38012Sejakowatz }
49452a38012Sejakowatz 
49552a38012Sejakowatz 
49652a38012Sejakowatz status_t
49752a38012Sejakowatz BMediaRoster::SetVideoInput(const media_node & producer)
49852a38012Sejakowatz {
49952a38012Sejakowatz 	CALLED();
5008b04ffc1Sbeveloper 	return MediaRosterEx(this)->SetNode(VIDEO_INPUT, &producer);
50152a38012Sejakowatz }
50252a38012Sejakowatz 
50352a38012Sejakowatz 
50452a38012Sejakowatz status_t
50552a38012Sejakowatz BMediaRoster::SetVideoInput(const dormant_node_info & producer)
50652a38012Sejakowatz {
50752a38012Sejakowatz 	CALLED();
5088b04ffc1Sbeveloper 	return MediaRosterEx(this)->SetNode(VIDEO_INPUT, NULL, &producer);
50952a38012Sejakowatz }
51052a38012Sejakowatz 
51152a38012Sejakowatz 
51252a38012Sejakowatz status_t
51352a38012Sejakowatz BMediaRoster::SetAudioInput(const media_node & producer)
51452a38012Sejakowatz {
51552a38012Sejakowatz 	CALLED();
5168b04ffc1Sbeveloper 	return MediaRosterEx(this)->SetNode(AUDIO_INPUT, &producer);
51752a38012Sejakowatz }
51852a38012Sejakowatz 
51952a38012Sejakowatz 
52052a38012Sejakowatz status_t
52152a38012Sejakowatz BMediaRoster::SetAudioInput(const dormant_node_info & producer)
52252a38012Sejakowatz {
52352a38012Sejakowatz 	CALLED();
5248b04ffc1Sbeveloper 	return MediaRosterEx(this)->SetNode(AUDIO_INPUT, NULL, &producer);
52552a38012Sejakowatz }
52652a38012Sejakowatz 
52752a38012Sejakowatz 
52852a38012Sejakowatz status_t
52952a38012Sejakowatz BMediaRoster::SetVideoOutput(const media_node & consumer)
53052a38012Sejakowatz {
53152a38012Sejakowatz 	CALLED();
5328b04ffc1Sbeveloper 	return MediaRosterEx(this)->SetNode(VIDEO_OUTPUT, &consumer);
53352a38012Sejakowatz }
53452a38012Sejakowatz 
53552a38012Sejakowatz 
53652a38012Sejakowatz status_t
53752a38012Sejakowatz BMediaRoster::SetVideoOutput(const dormant_node_info & consumer)
53852a38012Sejakowatz {
53952a38012Sejakowatz 	CALLED();
5408b04ffc1Sbeveloper 	return MediaRosterEx(this)->SetNode(VIDEO_OUTPUT, NULL, &consumer);
54152a38012Sejakowatz }
54252a38012Sejakowatz 
54352a38012Sejakowatz 
54452a38012Sejakowatz status_t
54552a38012Sejakowatz BMediaRoster::SetAudioOutput(const media_node & consumer)
54652a38012Sejakowatz {
54752a38012Sejakowatz 	CALLED();
5488b04ffc1Sbeveloper 	return MediaRosterEx(this)->SetNode(AUDIO_OUTPUT, &consumer);
54952a38012Sejakowatz }
55052a38012Sejakowatz 
55152a38012Sejakowatz 
55252a38012Sejakowatz status_t
55352a38012Sejakowatz BMediaRoster::SetAudioOutput(const media_input & input_to_output)
55452a38012Sejakowatz {
55552a38012Sejakowatz 	CALLED();
5568b04ffc1Sbeveloper 	return MediaRosterEx(this)->SetNode(AUDIO_OUTPUT, NULL, NULL, &input_to_output);
55752a38012Sejakowatz }
55852a38012Sejakowatz 
55952a38012Sejakowatz 
56052a38012Sejakowatz status_t
56152a38012Sejakowatz BMediaRoster::SetAudioOutput(const dormant_node_info & consumer)
56252a38012Sejakowatz {
56352a38012Sejakowatz 	CALLED();
5648b04ffc1Sbeveloper 	return MediaRosterEx(this)->SetNode(AUDIO_OUTPUT, NULL, &consumer);
56552a38012Sejakowatz }
56652a38012Sejakowatz 
56752a38012Sejakowatz 
56852a38012Sejakowatz status_t
56952a38012Sejakowatz BMediaRoster::GetNodeFor(media_node_id node,
57052a38012Sejakowatz 						 media_node * clone)
57152a38012Sejakowatz {
5729e9417d2Sbeveloper 	CALLED();
5739e9417d2Sbeveloper 	if (clone == NULL)
5749e9417d2Sbeveloper 		return B_BAD_VALUE;
5759e9417d2Sbeveloper 	if (node <= 0)
5769e9417d2Sbeveloper 		return B_MEDIA_BAD_NODE;
5779e9417d2Sbeveloper 
5789e9417d2Sbeveloper 	server_get_node_for_request request;
5799e9417d2Sbeveloper 	server_get_node_for_reply reply;
5809e9417d2Sbeveloper 	status_t rv;
5819e9417d2Sbeveloper 
5829e9417d2Sbeveloper 	request.nodeid = node;
5839e9417d2Sbeveloper 	request.team = team;
5849e9417d2Sbeveloper 
5859e9417d2Sbeveloper 	rv = QueryServer(SERVER_GET_NODE_FOR, &request, sizeof(request), &reply, sizeof(reply));
5869e9417d2Sbeveloper 	if (rv != B_OK)
5879e9417d2Sbeveloper 		return rv;
5889e9417d2Sbeveloper 
5899e9417d2Sbeveloper 	*clone = reply.clone;
5909e9417d2Sbeveloper 	return B_OK;
59152a38012Sejakowatz }
59252a38012Sejakowatz 
59352a38012Sejakowatz 
59452a38012Sejakowatz status_t
59552a38012Sejakowatz BMediaRoster::GetSystemTimeSource(media_node * clone)
59652a38012Sejakowatz {
59752a38012Sejakowatz 	CALLED();
59886bce45bSbeveloper 	status_t rv;
59986bce45bSbeveloper 
60086bce45bSbeveloper 	// XXX need to do this in a nicer way.
60186bce45bSbeveloper 
60286bce45bSbeveloper 	rv = MediaRosterEx(this)->GetNode(SYSTEM_TIME_SOURCE, clone);
60386bce45bSbeveloper 	if (rv != B_OK)
60486bce45bSbeveloper 		return rv;
60586bce45bSbeveloper 
60686bce45bSbeveloper 	// We don't do reference counting for timesources, that's why we
60786bce45bSbeveloper 	// release the node immediately.
60886bce45bSbeveloper 	ReleaseNode(*clone);
60986bce45bSbeveloper 
61086bce45bSbeveloper 	// we need to remember to not use this node with server side reference counting
61186bce45bSbeveloper 	clone->kind |= NODE_KIND_NO_REFCOUNTING;
61286bce45bSbeveloper 
61386bce45bSbeveloper 	return B_OK;
61452a38012Sejakowatz }
61552a38012Sejakowatz 
61652a38012Sejakowatz 
61752a38012Sejakowatz status_t
61852a38012Sejakowatz BMediaRoster::ReleaseNode(const media_node & node)
61952a38012Sejakowatz {
6209e9417d2Sbeveloper 	CALLED();
62140f36b03Sbeveloper 	if (IS_INVALID_NODE(node))
6229e9417d2Sbeveloper 		return B_MEDIA_BAD_NODE;
62352a38012Sejakowatz 
62486bce45bSbeveloper 	if (node.kind & NODE_KIND_NO_REFCOUNTING) {
62586bce45bSbeveloper 		printf("BMediaRoster::ReleaseNode, trying to release reference counting disabled timesource, node %ld, port %ld, team %ld\n", node.node, node.port, team);
62686bce45bSbeveloper 		return B_OK;
62786bce45bSbeveloper 	}
62886bce45bSbeveloper 
6299e9417d2Sbeveloper 	server_release_node_request request;
6309e9417d2Sbeveloper 	server_release_node_reply reply;
631cf4e2277Sbeveloper 	status_t rv;
6329e9417d2Sbeveloper 
6339e9417d2Sbeveloper 	request.node = node;
6349e9417d2Sbeveloper 	request.team = team;
6359e9417d2Sbeveloper 
63660f15390Sbeveloper 	TRACE("BMediaRoster::ReleaseNode, node %ld, port %ld, team %ld\n", node.node, node.port, team);
637cf4e2277Sbeveloper 
638cf4e2277Sbeveloper 	rv = QueryServer(SERVER_RELEASE_NODE, &request, sizeof(request), &reply, sizeof(reply));
639cf4e2277Sbeveloper 	if (rv != B_OK) {
6405ac4fbd7Sbeveloper 		ERROR("BMediaRoster::ReleaseNode FAILED, node %ld, port %ld, team %ld!\n", node.node, node.port, team);
641cf4e2277Sbeveloper 	}
642cf4e2277Sbeveloper 	return rv;
6439e9417d2Sbeveloper }
64452a38012Sejakowatz 
64552a38012Sejakowatz BTimeSource *
64652a38012Sejakowatz BMediaRoster::MakeTimeSourceFor(const media_node & for_node)
64752a38012Sejakowatz {
648f180ef79Sbeveloper 	// MakeTimeSourceFor() returns a BTimeSource object
649f180ef79Sbeveloper 	// corresponding to the specified node's time source.
650f180ef79Sbeveloper 
651835140c8Sbeveloper 	CALLED();
652f180ef79Sbeveloper 
65392e575c1Sbeveloper 	if (IS_SYSTEM_TIMESOURCE(for_node)) {
654f180ef79Sbeveloper 		// special handling for the system time source
655f180ef79Sbeveloper 		TRACE("BMediaRoster::MakeTimeSourceFor, asked for system time source\n");
656f180ef79Sbeveloper 		return MediaRosterEx(this)->MakeTimeSourceObject(NODE_SYSTEM_TIMESOURCE_ID);
657f180ef79Sbeveloper 	}
658f180ef79Sbeveloper 
6595917dd5bSbeveloper 	if (IS_INVALID_NODE(for_node)) {
6605ac4fbd7Sbeveloper 		ERROR("BMediaRoster::MakeTimeSourceFor: for_node invalid, node %ld, port %ld, kinds 0x%lx\n", for_node.node, for_node.port, for_node.kind);
6615917dd5bSbeveloper 		return NULL;
6620e21b167Sbeveloper 	}
6630e21b167Sbeveloper 
664f180ef79Sbeveloper 	TRACE("BMediaRoster::MakeTimeSourceFor: node %ld enter\n", for_node.node);
6655917dd5bSbeveloper 
6665917dd5bSbeveloper 	node_get_timesource_request request;
6675917dd5bSbeveloper 	node_get_timesource_reply reply;
6685917dd5bSbeveloper 	BTimeSource *source;
6695917dd5bSbeveloper 	status_t rv;
6705917dd5bSbeveloper 
67192e575c1Sbeveloper 	// ask the node to get it's current timesource id
6725917dd5bSbeveloper 	rv = QueryPort(for_node.port, NODE_GET_TIMESOURCE, &request, sizeof(request), &reply, sizeof(reply));
6735917dd5bSbeveloper 	if (rv != B_OK) {
6745ac4fbd7Sbeveloper 		ERROR("BMediaRoster::MakeTimeSourceFor: request failed\n");
6755917dd5bSbeveloper 		return NULL;
6765917dd5bSbeveloper 	}
6775917dd5bSbeveloper 
6785917dd5bSbeveloper 	source = MediaRosterEx(this)->MakeTimeSourceObject(reply.timesource_id);
6795917dd5bSbeveloper 
680f180ef79Sbeveloper 	TRACE("BMediaRoster::MakeTimeSourceFor: node %ld leave\n", for_node.node);
6815917dd5bSbeveloper 
6825917dd5bSbeveloper 	return source;
6835917dd5bSbeveloper }
6845917dd5bSbeveloper 
6855917dd5bSbeveloper BTimeSource *
6865917dd5bSbeveloper BMediaRosterEx::MakeTimeSourceObject(media_node_id timesource_id)
6875917dd5bSbeveloper {
6885917dd5bSbeveloper 	BTimeSource *source;
6895917dd5bSbeveloper 	media_node clone;
6905917dd5bSbeveloper 	status_t rv;
6915917dd5bSbeveloper 
6925917dd5bSbeveloper 	rv = GetNodeFor(timesource_id, &clone);
6935917dd5bSbeveloper 	if (rv != B_OK) {
6945ac4fbd7Sbeveloper 		ERROR("BMediaRosterEx::MakeTimeSourceObject: GetNodeFor failed\n");
6955917dd5bSbeveloper 		return NULL;
6965917dd5bSbeveloper 	}
6975917dd5bSbeveloper 
6985917dd5bSbeveloper 	source = _TimeSourceObjectManager->GetTimeSource(clone);
6995917dd5bSbeveloper 	if (source == NULL) {
7005ac4fbd7Sbeveloper 		ERROR("BMediaRosterEx::MakeTimeSourceObject: GetTimeSource failed\n");
7015917dd5bSbeveloper 		return NULL;
7025917dd5bSbeveloper 	}
7035917dd5bSbeveloper 
70492e575c1Sbeveloper 	// XXX release?
70592e575c1Sbeveloper 	ReleaseNode(clone);
706287f7492Sbeveloper 
707835140c8Sbeveloper 	return source;
70852a38012Sejakowatz }
70952a38012Sejakowatz 
71052a38012Sejakowatz 
71152a38012Sejakowatz status_t
71252a38012Sejakowatz BMediaRoster::Connect(const media_source & from,
71352a38012Sejakowatz 					  const media_destination & to,
71452a38012Sejakowatz 					  media_format * io_format,
71552a38012Sejakowatz 					  media_output * out_output,
71652a38012Sejakowatz 					  media_input * out_input)
71752a38012Sejakowatz {
718eae26d3dSbeveloper 	return BMediaRoster::Connect(from, to, io_format, out_output, out_input, 0);
719eae26d3dSbeveloper }
720eae26d3dSbeveloper 
721eae26d3dSbeveloper 
722eae26d3dSbeveloper status_t
723eae26d3dSbeveloper BMediaRoster::Connect(const media_source & from,
724eae26d3dSbeveloper 					  const media_destination & to,
725eae26d3dSbeveloper 					  media_format * io_format,
726eae26d3dSbeveloper 					  media_output * out_output,
727eae26d3dSbeveloper 					  media_input * out_input,
728eae26d3dSbeveloper 					  uint32 in_flags,
729eae26d3dSbeveloper 					  void * _reserved)
730eae26d3dSbeveloper {
73152a38012Sejakowatz 	CALLED();
73252a38012Sejakowatz 	if (io_format == NULL || out_output == NULL || out_input == NULL)
73352a38012Sejakowatz 		return B_BAD_VALUE;
73440f36b03Sbeveloper 	if (IS_INVALID_SOURCE(from)) {
7355ac4fbd7Sbeveloper 		ERROR("BMediaRoster::Connect: media_source invalid\n");
73652a38012Sejakowatz 		return B_MEDIA_BAD_SOURCE;
7379e9417d2Sbeveloper 	}
73840f36b03Sbeveloper 	if (IS_INVALID_DESTINATION(to)) {
7395ac4fbd7Sbeveloper 		ERROR("BMediaRoster::Connect: media_destination invalid\n");
74052a38012Sejakowatz 		return B_MEDIA_BAD_DESTINATION;
7419e9417d2Sbeveloper 	}
74252a38012Sejakowatz 
74352a38012Sejakowatz 	status_t rv;
7448c6a6096Sbeveloper 	producer_format_proposal_request request1;
7458c6a6096Sbeveloper 	producer_format_proposal_reply reply1;
74652a38012Sejakowatz 
74769983609Sbeveloper 	PRINT_FORMAT("BMediaRoster::Connect calling BBufferProducer::FormatProposal with format  ", *io_format);
74869983609Sbeveloper 
74952a38012Sejakowatz 	// BBufferProducer::FormatProposal
7508c6a6096Sbeveloper 	request1.output = from;
7518c6a6096Sbeveloper 	request1.format = *io_format;
7528c6a6096Sbeveloper 	rv = QueryPort(from.port, PRODUCER_FORMAT_PROPOSAL, &request1, sizeof(request1), &reply1, sizeof(reply1));
7538c6a6096Sbeveloper 	if (rv != B_OK) {
7545ac4fbd7Sbeveloper 		ERROR("BMediaRoster::Connect: aborted after BBufferProducer::FormatProposal, status = %#lx\n",rv);
75552a38012Sejakowatz 		return rv;
75652a38012Sejakowatz 	}
7578c6a6096Sbeveloper 	// reply1.format now contains the format proposed by the producer
7588c6a6096Sbeveloper 
7598c6a6096Sbeveloper 	consumer_accept_format_request request2;
7608c6a6096Sbeveloper 	consumer_accept_format_reply reply2;
7618c6a6096Sbeveloper 
76269983609Sbeveloper 	PRINT_FORMAT("BMediaRoster::Connect calling BBufferConsumer::AcceptFormat with format    ", reply1.format);
76369983609Sbeveloper 
7648c6a6096Sbeveloper 	// BBufferConsumer::AcceptFormat
7658c6a6096Sbeveloper 	request2.dest = to;
7668c6a6096Sbeveloper 	request2.format = reply1.format;
7678c6a6096Sbeveloper 	rv = QueryPort(to.port, CONSUMER_ACCEPT_FORMAT, &request2, sizeof(request2), &reply2, sizeof(reply2));
7688c6a6096Sbeveloper 	if (rv != B_OK) {
7695ac4fbd7Sbeveloper 		ERROR("BMediaRoster::Connect: aborted after BBufferConsumer::AcceptFormat, status = %#lx\n",rv);
7708c6a6096Sbeveloper 		return rv;
7718c6a6096Sbeveloper 	}
7728c6a6096Sbeveloper 	// reply2.format now contains the format accepted by the consumer
7738c6a6096Sbeveloper 
7748c6a6096Sbeveloper 	// BBufferProducer::PrepareToConnect
7758c6a6096Sbeveloper 	producer_prepare_to_connect_request request3;
7768c6a6096Sbeveloper 	producer_prepare_to_connect_reply reply3;
7778c6a6096Sbeveloper 
77869983609Sbeveloper 	PRINT_FORMAT("BMediaRoster::Connect calling BBufferProducer::PrepareToConnect with format", reply2.format);
77969983609Sbeveloper 
7808c6a6096Sbeveloper 	request3.source = from;
7818c6a6096Sbeveloper 	request3.destination = to;
7828c6a6096Sbeveloper 	request3.format = reply2.format;
7838c6a6096Sbeveloper 	strcpy(request3.name, "XXX some default name"); // XXX fix this
7848c6a6096Sbeveloper 	rv = QueryPort(from.port, PRODUCER_PREPARE_TO_CONNECT, &request3, sizeof(request3), &reply3, sizeof(reply3));
7858c6a6096Sbeveloper 	if (rv != B_OK) {
7865ac4fbd7Sbeveloper 		ERROR("BMediaRoster::Connect: aborted after BBufferProducer::PrepareToConnect, status = %#lx\n",rv);
7878c6a6096Sbeveloper 		return rv;
7888c6a6096Sbeveloper 	}
7898c6a6096Sbeveloper 	// reply3.format is still our pretty media format
7908c6a6096Sbeveloper 	// reply3.out_source the real source to be used for the connection
7918c6a6096Sbeveloper 	// reply3.name the name BBufferConsumer::Connected will see in the outInput->name argument
7928c6a6096Sbeveloper 
79369983609Sbeveloper 
79469983609Sbeveloper 	// find the output and input nodes
79569983609Sbeveloper 	// XXX isn't there a easier way?
79669983609Sbeveloper 	media_node sourcenode;
79769983609Sbeveloper 	media_node destnode;
79869983609Sbeveloper 	GetNodeFor(NodeIDFor(from.port), &sourcenode);
79969983609Sbeveloper 	GetNodeFor(NodeIDFor(to.port), &destnode);
80069983609Sbeveloper 	ReleaseNode(sourcenode);
80169983609Sbeveloper 	ReleaseNode(destnode);
80269983609Sbeveloper 
8038c6a6096Sbeveloper 	// BBufferConsumer::Connected
8048c6a6096Sbeveloper 	consumer_connected_request request4;
8058c6a6096Sbeveloper 	consumer_connected_reply reply4;
8068c6a6096Sbeveloper 	status_t con_status;
8078c6a6096Sbeveloper 
80869983609Sbeveloper 	PRINT_FORMAT("BMediaRoster::Connect calling BBufferConsumer::Connected with format       ", reply3.format);
80969983609Sbeveloper 
81069983609Sbeveloper 	request4.input.node = destnode;
81169983609Sbeveloper 	request4.input.source = reply3.out_source;
81269983609Sbeveloper 	request4.input.destination = to;
81369983609Sbeveloper 	request4.input.format = reply3.format;
81469983609Sbeveloper 	strcpy(request4.input.name, reply3.name);
81569983609Sbeveloper 
8168c6a6096Sbeveloper 	con_status = QueryPort(to.port, CONSUMER_CONNECTED, &request4, sizeof(request4), &reply4, sizeof(reply4));
8178c6a6096Sbeveloper 	if (con_status != B_OK) {
8185ac4fbd7Sbeveloper 		ERROR("BMediaRoster::Connect: aborting after BBufferConsumer::Connected, status = %#lx\n",con_status);
8198c6a6096Sbeveloper 		// we do NOT return here!
8208c6a6096Sbeveloper 	}
8218c6a6096Sbeveloper 	// con_status contains the status code to be supplied to BBufferProducer::Connect's status argument
8228c6a6096Sbeveloper 	// reply4.input contains the media_input that describes the connection from the consumer point of view
8238c6a6096Sbeveloper 
8248c6a6096Sbeveloper 	// BBufferProducer::Connect
8258c6a6096Sbeveloper 	producer_connect_request request5;
8268c6a6096Sbeveloper 	producer_connect_reply reply5;
8278c6a6096Sbeveloper 
82869983609Sbeveloper 	PRINT_FORMAT("BMediaRoster::Connect calling BBufferProducer::Connect with format         ", reply4.input.format);
82969983609Sbeveloper 
8308c6a6096Sbeveloper 	request5.error = con_status;
8318c6a6096Sbeveloper 	request5.source = reply3.out_source;
8328c6a6096Sbeveloper 	request5.destination = reply4.input.destination;
83369983609Sbeveloper 	request5.format = reply4.input.format;
8348c6a6096Sbeveloper 	strcpy(request5.name, reply4.input.name);
8350caff283Sbeveloper 	rv = QueryPort(reply4.input.source.port, PRODUCER_CONNECT, &request5, sizeof(request5), &reply5, sizeof(reply5));
8368c6a6096Sbeveloper 	if (con_status != B_OK) {
8375ac4fbd7Sbeveloper 		ERROR("BMediaRoster::Connect: aborted\n");
8388c6a6096Sbeveloper 		return con_status;
8398c6a6096Sbeveloper 	}
8408c6a6096Sbeveloper 	if (rv != B_OK) {
8415ac4fbd7Sbeveloper 		ERROR("BMediaRoster::Connect: aborted after BBufferProducer::Connect, status = %#lx\n",rv);
8428c6a6096Sbeveloper 		return rv;
8438c6a6096Sbeveloper 	}
8448c6a6096Sbeveloper 	// reply5.name contains the name assigned to the connection by the producer
8458c6a6096Sbeveloper 
8468c6a6096Sbeveloper 	// initilize connection info
84769983609Sbeveloper 	*io_format = reply4.input.format;
8488c6a6096Sbeveloper 	*out_input = reply4.input;
8498c6a6096Sbeveloper 	out_output->node = sourcenode;
8508c6a6096Sbeveloper 	out_output->source = reply4.input.source;
8518c6a6096Sbeveloper 	out_output->destination = reply4.input.destination;
8528c6a6096Sbeveloper 	out_output->format = reply4.input.format;
8538c6a6096Sbeveloper 	strcpy(out_output->name, reply5.name);
8548c6a6096Sbeveloper 
8558c6a6096Sbeveloper 	// the connection is now made
85669983609Sbeveloper 	printf("BMediaRoster::Connect connection established!\n");
85769983609Sbeveloper 	PRINT_FORMAT("   format", *io_format);
85869983609Sbeveloper 	PRINT_INPUT("   input", *out_input);
85969983609Sbeveloper 	PRINT_OUTPUT("   output", *out_output);
8608c6a6096Sbeveloper 
8618c6a6096Sbeveloper 	// XXX register connection with server
8629e9417d2Sbeveloper 	// XXX we should just send a notification, instead of republishing all endpoints
86376669a29Sbeveloper 	List<media_output> outlist;
86476669a29Sbeveloper 	List<media_input> inlist;
8658b04ffc1Sbeveloper 	if (B_OK == MediaRosterEx(this)->GetAllOutputs(out_output->node , &outlist))
8668b04ffc1Sbeveloper 		MediaRosterEx(this)->PublishOutputs(out_output->node , &outlist);
8678b04ffc1Sbeveloper 	if (B_OK == MediaRosterEx(this)->GetAllInputs(out_input->node , &inlist))
8688b04ffc1Sbeveloper 		MediaRosterEx(this)->PublishInputs(out_input->node, &inlist);
8698c6a6096Sbeveloper 
8708c6a6096Sbeveloper 
8718c6a6096Sbeveloper 	// XXX if (mute) BBufferProducer::EnableOutput(false)
8729e9417d2Sbeveloper 	if (in_flags & B_CONNECT_MUTED) {
8739e9417d2Sbeveloper 	}
8748c6a6096Sbeveloper 
8758c6a6096Sbeveloper 
8769e9417d2Sbeveloper 	// send a notification
8779e9417d2Sbeveloper 	BPrivate::media::notifications::ConnectionMade(*out_input, *out_output, *io_format);
8789e9417d2Sbeveloper 
8798c6a6096Sbeveloper 	return B_OK;
8808c6a6096Sbeveloper };
88152a38012Sejakowatz 
88252a38012Sejakowatz 
88352a38012Sejakowatz status_t
8849e9417d2Sbeveloper BMediaRoster::Disconnect(media_node_id source_nodeid,
88552a38012Sejakowatz 						 const media_source & source,
8869e9417d2Sbeveloper 						 media_node_id destination_nodeid,
88752a38012Sejakowatz 						 const media_destination & destination)
88852a38012Sejakowatz {
8899e9417d2Sbeveloper 	CALLED();
89040f36b03Sbeveloper 	if (IS_INVALID_NODEID(source_nodeid)) {
8915ac4fbd7Sbeveloper 		ERROR("BMediaRoster::Disconnect: source media_node_id invalid\n");
8929e9417d2Sbeveloper 		return B_MEDIA_BAD_SOURCE;
8939e9417d2Sbeveloper 	}
89440f36b03Sbeveloper 	if (IS_INVALID_NODEID(destination_nodeid)) {
8955ac4fbd7Sbeveloper 		ERROR("BMediaRoster::Disconnect: destination media_node_id invalid\n");
8969e9417d2Sbeveloper 		return B_MEDIA_BAD_DESTINATION;
8979e9417d2Sbeveloper 	}
89840f36b03Sbeveloper 	if (IS_INVALID_SOURCE(source)) {
8995ac4fbd7Sbeveloper 		ERROR("BMediaRoster::Disconnect: media_source invalid\n");
9009e9417d2Sbeveloper 		return B_MEDIA_BAD_SOURCE;
9019e9417d2Sbeveloper 	}
90240f36b03Sbeveloper 	if (IS_INVALID_DESTINATION(destination)) {
9035ac4fbd7Sbeveloper 		ERROR("BMediaRoster::Disconnect: media_destination invalid\n");
9049e9417d2Sbeveloper 		return B_MEDIA_BAD_DESTINATION;
9059e9417d2Sbeveloper 	}
9069e9417d2Sbeveloper 
9079e9417d2Sbeveloper 	producer_disconnect_request request2;
9089e9417d2Sbeveloper 	producer_disconnect_reply reply2;
9099e9417d2Sbeveloper 	consumer_disconnected_request request1;
9109e9417d2Sbeveloper 	consumer_disconnected_reply reply1;
9119e9417d2Sbeveloper 	status_t rv1, rv2;
9129e9417d2Sbeveloper 
9139e9417d2Sbeveloper 	// XXX we should ask the server if this connection really exists
9149e9417d2Sbeveloper 
9159e9417d2Sbeveloper 	request1.source = source;
9169e9417d2Sbeveloper 	request1.destination = destination;
9179e9417d2Sbeveloper 	request2.source = source;
9189e9417d2Sbeveloper 	request2.destination = destination;
9199e9417d2Sbeveloper 
9209e9417d2Sbeveloper 	rv1 = QueryPort(source.port, PRODUCER_DISCONNECT, &request1, sizeof(request1), &reply1, sizeof(reply1));
9219e9417d2Sbeveloper 	rv2 = QueryPort(destination.port, CONSUMER_DISCONNECTED, &request2, sizeof(request2), &reply2, sizeof(reply2));
9229e9417d2Sbeveloper 
9239e9417d2Sbeveloper 	// XXX unregister connection with server
9249e9417d2Sbeveloper 	// XXX we should just send a notification, instead of republishing all endpoints
92576669a29Sbeveloper 	List<media_output> outlist;
92676669a29Sbeveloper 	List<media_input> inlist;
9279e9417d2Sbeveloper 	media_node sourcenode;
9289e9417d2Sbeveloper 	media_node destnode;
9299e9417d2Sbeveloper 	if (B_OK == GetNodeFor(source_nodeid, &sourcenode)) {
9308b04ffc1Sbeveloper 		if (B_OK == MediaRosterEx(this)->GetAllOutputs(sourcenode , &outlist))
9318b04ffc1Sbeveloper 			MediaRosterEx(this)->PublishOutputs(sourcenode , &outlist);
9329e9417d2Sbeveloper 		ReleaseNode(sourcenode);
9334f09fa2fSbeveloper 	} else {
9345ac4fbd7Sbeveloper 		ERROR("BMediaRoster::Disconnect: source GetNodeFor failed\n");
9354f09fa2fSbeveloper 	}
9369e9417d2Sbeveloper 	if (B_OK == GetNodeFor(destination_nodeid, &destnode)) {
9378b04ffc1Sbeveloper 		if (B_OK == MediaRosterEx(this)->GetAllInputs(destnode , &inlist))
9388b04ffc1Sbeveloper 			MediaRosterEx(this)->PublishInputs(destnode, &inlist);
9399e9417d2Sbeveloper 		ReleaseNode(destnode);
9404f09fa2fSbeveloper 	} else {
9415ac4fbd7Sbeveloper 		ERROR("BMediaRoster::Disconnect: dest GetNodeFor failed\n");
9424f09fa2fSbeveloper 	}
9439e9417d2Sbeveloper 
9449e9417d2Sbeveloper 
9459e9417d2Sbeveloper 	// send a notification
9469e9417d2Sbeveloper 	BPrivate::media::notifications::ConnectionBroken(source, destination);
9479e9417d2Sbeveloper 
9489e9417d2Sbeveloper 	return (rv1 != B_OK || rv2 != B_OK) ? B_ERROR : B_OK;
94952a38012Sejakowatz }
95052a38012Sejakowatz 
95152a38012Sejakowatz 
95252a38012Sejakowatz status_t
95352a38012Sejakowatz BMediaRoster::StartNode(const media_node & node,
95452a38012Sejakowatz 						bigtime_t at_performance_time)
95552a38012Sejakowatz {
95652a38012Sejakowatz 	CALLED();
9579e9417d2Sbeveloper 	if (node.node <= 0)
95852a38012Sejakowatz 		return B_MEDIA_BAD_NODE;
95952a38012Sejakowatz 
96060f15390Sbeveloper 	TRACE("BMediaRoster::StartNode, node %ld, at perf %Ld\n", node.node, at_performance_time);
9610e21b167Sbeveloper 
9626396865dSbeveloper 	node_start_command command;
9636396865dSbeveloper 	command.performance_time = at_performance_time;
96452a38012Sejakowatz 
9656396865dSbeveloper 	return SendToPort(node.port, NODE_START, &command, sizeof(command));
96652a38012Sejakowatz }
96752a38012Sejakowatz 
96852a38012Sejakowatz 
96952a38012Sejakowatz status_t
97052a38012Sejakowatz BMediaRoster::StopNode(const media_node & node,
97152a38012Sejakowatz 					   bigtime_t at_performance_time,
97252a38012Sejakowatz 					   bool immediate)
97352a38012Sejakowatz {
97452a38012Sejakowatz 	CALLED();
97540f36b03Sbeveloper 	if (IS_INVALID_NODE(node))
97652a38012Sejakowatz 		return B_MEDIA_BAD_NODE;
97752a38012Sejakowatz 
97860f15390Sbeveloper 	TRACE("BMediaRoster::StopNode, node %ld, at perf %Ld %s\n", node.node, at_performance_time, immediate ? "NOW" : "");
9790e21b167Sbeveloper 
9806396865dSbeveloper 	node_stop_command command;
9816396865dSbeveloper 	command.performance_time = at_performance_time;
9826396865dSbeveloper 	command.immediate = immediate;
98352a38012Sejakowatz 
9846396865dSbeveloper 	return SendToPort(node.port, NODE_STOP, &command, sizeof(command));
98552a38012Sejakowatz }
98652a38012Sejakowatz 
98752a38012Sejakowatz 
98852a38012Sejakowatz status_t
98952a38012Sejakowatz BMediaRoster::SeekNode(const media_node & node,
99052a38012Sejakowatz 					   bigtime_t to_media_time,
99152a38012Sejakowatz 					   bigtime_t at_performance_time)
99252a38012Sejakowatz {
99352a38012Sejakowatz 	CALLED();
99440f36b03Sbeveloper 	if (IS_INVALID_NODE(node))
99552a38012Sejakowatz 		return B_MEDIA_BAD_NODE;
99652a38012Sejakowatz 
99760f15390Sbeveloper 	TRACE("BMediaRoster::SeekNode, node %ld, at perf %Ld, to perf %Ld\n", node.node, at_performance_time, to_media_time);
9980e21b167Sbeveloper 
9996396865dSbeveloper 	node_seek_command command;
10006396865dSbeveloper 	command.media_time = to_media_time;
10016396865dSbeveloper 	command.performance_time = at_performance_time;
100252a38012Sejakowatz 
10036396865dSbeveloper 	return SendToPort(node.port, NODE_SEEK, &command, sizeof(command));
100452a38012Sejakowatz }
100552a38012Sejakowatz 
100652a38012Sejakowatz 
100752a38012Sejakowatz status_t
100852a38012Sejakowatz BMediaRoster::StartTimeSource(const media_node & node,
100952a38012Sejakowatz 							  bigtime_t at_real_time)
101052a38012Sejakowatz {
101152a38012Sejakowatz 	CALLED();
101260f15390Sbeveloper 	if (IS_SYSTEM_TIMESOURCE(node)) {
101360f15390Sbeveloper 		// XXX debug this
10145ac4fbd7Sbeveloper 		//ERROR("BMediaRoster::StartTimeSource node %ld is system timesource\n", node.node);
101560f15390Sbeveloper 		return B_OK;
101660f15390Sbeveloper 	}
101792e575c1Sbeveloper //	if (IS_SHADOW_TIMESOURCE(node)) {
101892e575c1Sbeveloper //		// XXX debug this
101992e575c1Sbeveloper //		ERROR("BMediaRoster::StartTimeSource node %ld is shadow timesource\n", node.node);
102092e575c1Sbeveloper //		return B_OK;
102192e575c1Sbeveloper //	}
102240f36b03Sbeveloper 	if (IS_INVALID_NODE(node)) {
10235ac4fbd7Sbeveloper 		ERROR("BMediaRoster::StartTimeSource node %ld invalid\n", node.node);
102452a38012Sejakowatz 		return B_MEDIA_BAD_NODE;
10250e21b167Sbeveloper 	}
10260e21b167Sbeveloper 	if ((node.kind & B_TIME_SOURCE) == 0) {
10275ac4fbd7Sbeveloper 		ERROR("BMediaRoster::StartTimeSource node %ld is no timesource\n", node.node);
102852a38012Sejakowatz 		return B_MEDIA_BAD_NODE;
10290e21b167Sbeveloper 	}
10300e21b167Sbeveloper 
103160f15390Sbeveloper 	TRACE("BMediaRoster::StartTimeSource, node %ld, at real %Ld\n", node.node, at_real_time);
103252a38012Sejakowatz 
103352a38012Sejakowatz 	BTimeSource::time_source_op_info msg;
103452a38012Sejakowatz 	msg.op = BTimeSource::B_TIMESOURCE_START;
103552a38012Sejakowatz 	msg.real_time = at_real_time;
103652a38012Sejakowatz 
103752a38012Sejakowatz 	return write_port(node.port, TIMESOURCE_OP, &msg, sizeof(msg));
103852a38012Sejakowatz }
103952a38012Sejakowatz 
104052a38012Sejakowatz 
104152a38012Sejakowatz status_t
104252a38012Sejakowatz BMediaRoster::StopTimeSource(const media_node & node,
104352a38012Sejakowatz 							 bigtime_t at_real_time,
104452a38012Sejakowatz 							 bool immediate)
104552a38012Sejakowatz {
104652a38012Sejakowatz 	CALLED();
104760f15390Sbeveloper 	if (IS_SYSTEM_TIMESOURCE(node)) {
104860f15390Sbeveloper 		// XXX debug this
10495ac4fbd7Sbeveloper 		//ERROR("BMediaRoster::StopTimeSource node %ld is system timesource\n", node.node);
105060f15390Sbeveloper 		return B_OK;
105160f15390Sbeveloper 	}
105292e575c1Sbeveloper //	if (IS_SHADOW_TIMESOURCE(node)) {
105392e575c1Sbeveloper //		// XXX debug this
105492e575c1Sbeveloper //		ERROR("BMediaRoster::StopTimeSource node %ld is shadow timesource\n", node.node);
105592e575c1Sbeveloper //		return B_OK;
105692e575c1Sbeveloper //	}
105740f36b03Sbeveloper 	if (IS_INVALID_NODE(node)) {
10585ac4fbd7Sbeveloper 		ERROR("BMediaRoster::StopTimeSource node %ld invalid\n", node.node);
105952a38012Sejakowatz 		return B_MEDIA_BAD_NODE;
10600e21b167Sbeveloper 	}
10610e21b167Sbeveloper 	if ((node.kind & B_TIME_SOURCE) == 0) {
10625ac4fbd7Sbeveloper 		ERROR("BMediaRoster::StopTimeSource node %ld is no timesource\n", node.node);
106352a38012Sejakowatz 		return B_MEDIA_BAD_NODE;
10640e21b167Sbeveloper 	}
10650e21b167Sbeveloper 
106660f15390Sbeveloper 	TRACE("BMediaRoster::StopTimeSource, node %ld, at real %Ld %s\n", node.node, at_real_time, immediate ? "NOW" : "");
106752a38012Sejakowatz 
106852a38012Sejakowatz 	BTimeSource::time_source_op_info msg;
106952a38012Sejakowatz 	msg.op = immediate ? BTimeSource::B_TIMESOURCE_STOP_IMMEDIATELY : BTimeSource::B_TIMESOURCE_STOP;
107052a38012Sejakowatz 	msg.real_time = at_real_time;
107152a38012Sejakowatz 
107252a38012Sejakowatz 	return write_port(node.port, TIMESOURCE_OP, &msg, sizeof(msg));
107352a38012Sejakowatz }
107452a38012Sejakowatz 
107552a38012Sejakowatz 
107652a38012Sejakowatz status_t
107752a38012Sejakowatz BMediaRoster::SeekTimeSource(const media_node & node,
107852a38012Sejakowatz 							 bigtime_t to_performance_time,
107952a38012Sejakowatz 							 bigtime_t at_real_time)
108052a38012Sejakowatz {
108152a38012Sejakowatz 	CALLED();
108260f15390Sbeveloper 	if (IS_SYSTEM_TIMESOURCE(node)) {
108360f15390Sbeveloper 		// XXX debug this
10845ac4fbd7Sbeveloper 		// ERROR("BMediaRoster::SeekTimeSource node %ld is system timesource\n", node.node);
108560f15390Sbeveloper 		// you can't seek the system time source, but
108660f15390Sbeveloper 		// returning B_ERROR would break StampTV
108760f15390Sbeveloper 		return B_OK;
108860f15390Sbeveloper 	}
108992e575c1Sbeveloper //	if (IS_SHADOW_TIMESOURCE(node)) {
109092e575c1Sbeveloper //		// XXX debug this
109192e575c1Sbeveloper //		ERROR("BMediaRoster::SeekTimeSource node %ld is shadow timesource\n", node.node);
109292e575c1Sbeveloper //		return B_OK;
109392e575c1Sbeveloper //	}
109440f36b03Sbeveloper 	if (IS_INVALID_NODE(node)) {
10955ac4fbd7Sbeveloper 		ERROR("BMediaRoster::SeekTimeSource node %ld invalid\n", node.node);
109652a38012Sejakowatz 		return B_MEDIA_BAD_NODE;
10970e21b167Sbeveloper 	}
10980e21b167Sbeveloper 	if ((node.kind & B_TIME_SOURCE) == 0) {
10995ac4fbd7Sbeveloper 		ERROR("BMediaRoster::SeekTimeSource node %ld is no timesource\n", node.node);
110052a38012Sejakowatz 		return B_MEDIA_BAD_NODE;
11010e21b167Sbeveloper 	}
11020e21b167Sbeveloper 
110360f15390Sbeveloper 	TRACE("BMediaRoster::SeekTimeSource, node %ld, at real %Ld, to perf %Ld\n", node.node, at_real_time, to_performance_time);
110452a38012Sejakowatz 
110552a38012Sejakowatz 	BTimeSource::time_source_op_info msg;
110652a38012Sejakowatz 	msg.op = BTimeSource::B_TIMESOURCE_SEEK;
110752a38012Sejakowatz 	msg.real_time = at_real_time;
110852a38012Sejakowatz 	msg.performance_time = to_performance_time;
110952a38012Sejakowatz 
111052a38012Sejakowatz 	return write_port(node.port, TIMESOURCE_OP, &msg, sizeof(msg));
111152a38012Sejakowatz }
111252a38012Sejakowatz 
111352a38012Sejakowatz 
111452a38012Sejakowatz status_t
111552a38012Sejakowatz BMediaRoster::SyncToNode(const media_node & node,
111652a38012Sejakowatz 						 bigtime_t at_time,
111752a38012Sejakowatz 						 bigtime_t timeout)
111852a38012Sejakowatz {
111952a38012Sejakowatz 	UNIMPLEMENTED();
112060f15390Sbeveloper 	return B_OK;
112152a38012Sejakowatz }
112252a38012Sejakowatz 
112352a38012Sejakowatz 
112452a38012Sejakowatz status_t
112552a38012Sejakowatz BMediaRoster::SetRunModeNode(const media_node & node,
112652a38012Sejakowatz 							 BMediaNode::run_mode mode)
112752a38012Sejakowatz {
112852a38012Sejakowatz 	CALLED();
112940f36b03Sbeveloper 	if (IS_INVALID_NODE(node))
113052a38012Sejakowatz 		return B_MEDIA_BAD_NODE;
113152a38012Sejakowatz 
1132dfb2ad61Sbeveloper 	node_set_run_mode_command msg;
113352a38012Sejakowatz 	msg.mode = mode;
113452a38012Sejakowatz 
113552a38012Sejakowatz 	return write_port(node.port, NODE_SET_RUN_MODE, &msg, sizeof(msg));
113652a38012Sejakowatz }
113752a38012Sejakowatz 
113852a38012Sejakowatz 
113952a38012Sejakowatz status_t
114052a38012Sejakowatz BMediaRoster::PrerollNode(const media_node & node)
114152a38012Sejakowatz {
114252a38012Sejakowatz 	CALLED();
114340f36b03Sbeveloper 	if (IS_INVALID_NODE(node))
114452a38012Sejakowatz 		return B_MEDIA_BAD_NODE;
114552a38012Sejakowatz 
114652a38012Sejakowatz 	char dummy;
114752a38012Sejakowatz 	return write_port(node.port, NODE_PREROLL, &dummy, sizeof(dummy));
114852a38012Sejakowatz }
114952a38012Sejakowatz 
115052a38012Sejakowatz 
115152a38012Sejakowatz status_t
115252a38012Sejakowatz BMediaRoster::RollNode(const media_node & node,
115352a38012Sejakowatz 					   bigtime_t startPerformance,
115452a38012Sejakowatz 					   bigtime_t stopPerformance,
115552a38012Sejakowatz 					   bigtime_t atMediaTime)
115652a38012Sejakowatz {
115752a38012Sejakowatz 	UNIMPLEMENTED();
115852a38012Sejakowatz 	return B_ERROR;
115952a38012Sejakowatz }
116052a38012Sejakowatz 
116152a38012Sejakowatz 
116252a38012Sejakowatz status_t
116352a38012Sejakowatz BMediaRoster::SetProducerRunModeDelay(const media_node & node,
116452a38012Sejakowatz 									  bigtime_t delay,
116552a38012Sejakowatz 									  BMediaNode::run_mode mode)
116652a38012Sejakowatz {
116760f15390Sbeveloper 	CALLED();
116860f15390Sbeveloper 	if (IS_INVALID_NODE(node))
116960f15390Sbeveloper 		return B_MEDIA_BAD_NODE;
117060f15390Sbeveloper 	if ((node.kind & B_BUFFER_PRODUCER) == 0)
117160f15390Sbeveloper 		return B_MEDIA_BAD_NODE;
117260f15390Sbeveloper 
117360f15390Sbeveloper 	producer_set_run_mode_delay_command command;
117460f15390Sbeveloper 	command.mode = mode;
117560f15390Sbeveloper 	command.delay = delay;
117660f15390Sbeveloper 
117760f15390Sbeveloper 	return SendToPort(node.port, PRODUCER_SET_RUN_MODE_DELAY, &command, sizeof(command));
117852a38012Sejakowatz }
117952a38012Sejakowatz 
118052a38012Sejakowatz 
118152a38012Sejakowatz status_t
118252a38012Sejakowatz BMediaRoster::SetProducerRate(const media_node & producer,
118352a38012Sejakowatz 							  int32 numer,
118452a38012Sejakowatz 							  int32 denom)
118552a38012Sejakowatz {
118652a38012Sejakowatz 	CALLED();
118740f36b03Sbeveloper 	if (IS_INVALID_NODE(producer))
118852a38012Sejakowatz 		return B_MEDIA_BAD_NODE;
118952a38012Sejakowatz 	if ((producer.kind & B_BUFFER_PRODUCER) == 0)
119052a38012Sejakowatz 		return B_MEDIA_BAD_NODE;
119152a38012Sejakowatz 
1192dfb2ad61Sbeveloper 	producer_set_play_rate_request msg;
1193dfb2ad61Sbeveloper 	producer_set_play_rate_reply reply;
119452a38012Sejakowatz 	status_t rv;
119552a38012Sejakowatz 	int32 code;
119652a38012Sejakowatz 
119752a38012Sejakowatz 	msg.numer = numer;
119852a38012Sejakowatz 	msg.denom = denom;
119952a38012Sejakowatz 	msg.reply_port = _PortPool->GetPort();
120052a38012Sejakowatz 	rv = write_port(producer.node, PRODUCER_SET_PLAY_RATE, &msg, sizeof(msg));
120152a38012Sejakowatz 	if (rv != B_OK) {
120252a38012Sejakowatz 		_PortPool->PutPort(msg.reply_port);
120352a38012Sejakowatz 		return rv;
120452a38012Sejakowatz 	}
120552a38012Sejakowatz 	rv = read_port(msg.reply_port, &code, &reply, sizeof(reply));
120652a38012Sejakowatz 	_PortPool->PutPort(msg.reply_port);
120752a38012Sejakowatz 	return (rv < B_OK) ? rv : reply.result;
120852a38012Sejakowatz }
120952a38012Sejakowatz 
121052a38012Sejakowatz 
121152a38012Sejakowatz /* Nodes will have available inputs/outputs as long as they are capable */
121252a38012Sejakowatz /* of accepting more connections. The node may create an additional */
121352a38012Sejakowatz /* output or input as the currently available is taken into usage. */
121452a38012Sejakowatz status_t
121552a38012Sejakowatz BMediaRoster::GetLiveNodeInfo(const media_node & node,
121652a38012Sejakowatz 							  live_node_info * out_live_info)
121752a38012Sejakowatz {
12189e9417d2Sbeveloper 	CALLED();
12199e9417d2Sbeveloper 	if (out_live_info == NULL)
12209e9417d2Sbeveloper 		return B_BAD_VALUE;
122140f36b03Sbeveloper 	if (IS_INVALID_NODE(node))
12229e9417d2Sbeveloper 		return B_MEDIA_BAD_NODE;
12239e9417d2Sbeveloper 
12249e9417d2Sbeveloper 	server_get_live_node_info_request request;
12259e9417d2Sbeveloper 	server_get_live_node_info_reply reply;
12269e9417d2Sbeveloper 	status_t rv;
12279e9417d2Sbeveloper 
12289e9417d2Sbeveloper 	request.node = node;
12299e9417d2Sbeveloper 
12301299bfb2Sbeveloper 	rv = QueryServer(SERVER_GET_LIVE_NODE_INFO, &request, sizeof(request), &reply, sizeof(reply));
12319e9417d2Sbeveloper 	if (rv != B_OK)
12329e9417d2Sbeveloper 		return rv;
12339e9417d2Sbeveloper 
12349e9417d2Sbeveloper 	*out_live_info = reply.live_info;
12359e9417d2Sbeveloper 	return B_OK;
123652a38012Sejakowatz }
123752a38012Sejakowatz 
123852a38012Sejakowatz 
123952a38012Sejakowatz status_t
124052a38012Sejakowatz BMediaRoster::GetLiveNodes(live_node_info * out_live_nodes,
124152a38012Sejakowatz 						   int32 * io_total_count,
124252a38012Sejakowatz 						   const media_format * has_input,
124352a38012Sejakowatz 						   const media_format * has_output,
124452a38012Sejakowatz 						   const char * name,
124552a38012Sejakowatz 						   uint64 node_kinds)
124652a38012Sejakowatz {
12479e9417d2Sbeveloper 	CALLED();
12489e9417d2Sbeveloper 	if (out_live_nodes == NULL || io_total_count == NULL)
12499e9417d2Sbeveloper 		return B_BAD_VALUE;
12509e9417d2Sbeveloper 	if (*io_total_count <= 0)
12519e9417d2Sbeveloper 		return B_BAD_VALUE;
12529e9417d2Sbeveloper 
12539e9417d2Sbeveloper 	// XXX we also support the wildcard search as GetDormantNodes does. This needs to be documented
12549e9417d2Sbeveloper 
12559e9417d2Sbeveloper 	server_get_live_nodes_request request;
12569e9417d2Sbeveloper 	server_get_live_nodes_reply reply;
12579e9417d2Sbeveloper 	status_t rv;
12589e9417d2Sbeveloper 
12599e9417d2Sbeveloper 	request.maxcount = *io_total_count;
12609e9417d2Sbeveloper 	request.has_input = (bool) has_input;
12619e9417d2Sbeveloper 	if (has_input)
12629e9417d2Sbeveloper 		request.inputformat = *has_input; // XXX we should not make a flat copy of media_format
12639e9417d2Sbeveloper 	request.has_output = (bool) has_output;
12649e9417d2Sbeveloper 	if (has_output)
12659e9417d2Sbeveloper 		request.outputformat = *has_output; // XXX we should not make a flat copy of media_format
12669e9417d2Sbeveloper 	request.has_name = (bool) name;
12679e9417d2Sbeveloper 	if (name) {
12689e9417d2Sbeveloper 		int len = strlen(name);
12699e9417d2Sbeveloper 		len = min_c(len, (int)sizeof(request.name) - 1);
12709e9417d2Sbeveloper 		memcpy(request.name, name, len);
12719e9417d2Sbeveloper 		request.name[len] = 0;
12729e9417d2Sbeveloper 	}
12739e9417d2Sbeveloper 	request.require_kinds = node_kinds;
12749e9417d2Sbeveloper 
12759e9417d2Sbeveloper 	rv = QueryServer(SERVER_GET_LIVE_NODES, &request, sizeof(request), &reply, sizeof(reply));
12769e9417d2Sbeveloper 	if (rv != B_OK) {
12775ac4fbd7Sbeveloper 		ERROR("BMediaRoster::GetLiveNodes failed querying server\n");
12781299bfb2Sbeveloper 		*io_total_count = 0;
12799e9417d2Sbeveloper 		return rv;
12809e9417d2Sbeveloper 	}
12819e9417d2Sbeveloper 
12829e9417d2Sbeveloper 	if (reply.count > MAX_LIVE_INFO) {
12839e9417d2Sbeveloper 		live_node_info *live_info;
12849e9417d2Sbeveloper 		area_id clone;
12859e9417d2Sbeveloper 
12869e9417d2Sbeveloper 		clone = clone_area("live_node_info clone", reinterpret_cast<void **>(&live_info), B_ANY_ADDRESS, B_READ_AREA | B_WRITE_AREA, reply.area);
12879e9417d2Sbeveloper 		if (clone < B_OK) {
12885ac4fbd7Sbeveloper 			ERROR("BMediaRoster::GetLiveNodes failed to clone area, %#lx\n", clone);
12899e9417d2Sbeveloper 			delete_area(reply.area);
12901299bfb2Sbeveloper 			*io_total_count = 0;
129152a38012Sejakowatz 			return B_ERROR;
129252a38012Sejakowatz 		}
129352a38012Sejakowatz 
12949e9417d2Sbeveloper 		for (int32 i = 0; i < reply.count; i++) {
12959e9417d2Sbeveloper 			out_live_nodes[i] = live_info[i];
12969e9417d2Sbeveloper 		}
12979e9417d2Sbeveloper 
12989e9417d2Sbeveloper 		delete_area(clone);
12999e9417d2Sbeveloper 		delete_area(reply.area);
13009e9417d2Sbeveloper 	} else {
13019e9417d2Sbeveloper 		for (int32 i = 0; i < reply.count; i++) {
13029e9417d2Sbeveloper 			out_live_nodes[i] = reply.live_info[i];
13039e9417d2Sbeveloper 		}
13049e9417d2Sbeveloper 	}
13059e9417d2Sbeveloper 	*io_total_count = reply.count;
13069e9417d2Sbeveloper 
13079e9417d2Sbeveloper 	return B_OK;
13089e9417d2Sbeveloper }
13099e9417d2Sbeveloper 
131052a38012Sejakowatz 
131152a38012Sejakowatz status_t
131252a38012Sejakowatz BMediaRoster::GetFreeInputsFor(const media_node & node,
131352a38012Sejakowatz 							   media_input * out_free_inputs,
131452a38012Sejakowatz 							   int32 buf_num_inputs,
131552a38012Sejakowatz 							   int32 * out_total_count,
131652a38012Sejakowatz 							   media_type filter_type)
131752a38012Sejakowatz {
13183620737cSbeveloper 	CALLED();
13195ac4fbd7Sbeveloper 	if (IS_INVALID_NODE(node)) {
13205ac4fbd7Sbeveloper 		ERROR("BMediaRoster::GetFreeInputsFor: node %ld, port %ld invalid\n", node.node, node.port);
13213620737cSbeveloper 		return B_MEDIA_BAD_NODE;
13225ac4fbd7Sbeveloper 	}
13235ac4fbd7Sbeveloper 	if ((node.kind & B_BUFFER_CONSUMER) == 0) {
13245ac4fbd7Sbeveloper 		ERROR("BMediaRoster::GetFreeInputsFor: node %ld, port %ld is not a consumer\n", node.node, node.port);
13255ac4fbd7Sbeveloper 		return B_MEDIA_BAD_NODE;
13265ac4fbd7Sbeveloper 	}
13273620737cSbeveloper 	if (out_free_inputs == NULL || out_total_count == NULL)
13283620737cSbeveloper 		return B_BAD_VALUE;
13293620737cSbeveloper 
133076669a29Sbeveloper 	List<media_input> list;
13313620737cSbeveloper 	media_input *input;
13323620737cSbeveloper 	status_t rv;
13333620737cSbeveloper 
13341299bfb2Sbeveloper 	*out_total_count = 0;
13351299bfb2Sbeveloper 
13368b04ffc1Sbeveloper 	rv = MediaRosterEx(this)->GetAllInputs(node, &list);
13373620737cSbeveloper 	if (B_OK != rv)
13383620737cSbeveloper 		return rv;
13393620737cSbeveloper 
13405ac4fbd7Sbeveloper 	PRINT(4, "BMediaRoster::GetFreeInputsFor node %ld, max %ld, filter-type %ld\n", node.node, buf_num_inputs, filter_type);
13415ac4fbd7Sbeveloper 
134276669a29Sbeveloper 	int32 i;
1343b65a0ac5SJérôme Duval 	for (i = 0, list.Rewind(); list.GetNext(&input);) {
13443620737cSbeveloper 		if (filter_type != B_MEDIA_UNKNOWN_TYPE && filter_type != input->format.type)
13453620737cSbeveloper 			continue; // media_type used, but doesn't match
13463620737cSbeveloper 		if (input->source != media_source::null)
13473620737cSbeveloper 			continue; // consumer source already connected
13483620737cSbeveloper 		out_free_inputs[i] = *input;
13493620737cSbeveloper 		*out_total_count += 1;
13503620737cSbeveloper 		buf_num_inputs -= 1;
13515ac4fbd7Sbeveloper 		#if DEBUG >= 3
13525ac4fbd7Sbeveloper 			PRINT_OUTPUT("  input", out_free_inputs[i]);
13535ac4fbd7Sbeveloper 		#endif
13543620737cSbeveloper 		if (buf_num_inputs == 0)
13553620737cSbeveloper 			break;
1356b65a0ac5SJérôme Duval 		i++;
13573620737cSbeveloper 	}
13583620737cSbeveloper 
13598b04ffc1Sbeveloper 	MediaRosterEx(this)->PublishInputs(node, &list);
13603620737cSbeveloper 	return B_OK;
136152a38012Sejakowatz }
136252a38012Sejakowatz 
136352a38012Sejakowatz 
136452a38012Sejakowatz status_t
136552a38012Sejakowatz BMediaRoster::GetConnectedInputsFor(const media_node & node,
136652a38012Sejakowatz 									media_input * out_active_inputs,
136752a38012Sejakowatz 									int32 buf_num_inputs,
136852a38012Sejakowatz 									int32 * out_total_count)
136952a38012Sejakowatz {
13703620737cSbeveloper 	CALLED();
137140f36b03Sbeveloper 	if (IS_INVALID_NODE(node) || (node.kind & B_BUFFER_CONSUMER) == 0)
13723620737cSbeveloper 		return B_MEDIA_BAD_NODE;
13733620737cSbeveloper 	if (out_active_inputs == NULL || out_total_count == NULL)
13743620737cSbeveloper 		return B_BAD_VALUE;
13753620737cSbeveloper 
137676669a29Sbeveloper 	List<media_input> list;
13773620737cSbeveloper 	media_input *input;
13783620737cSbeveloper 	status_t rv;
13793620737cSbeveloper 
13801299bfb2Sbeveloper 	*out_total_count = 0;
13811299bfb2Sbeveloper 
13828b04ffc1Sbeveloper 	rv = MediaRosterEx(this)->GetAllInputs(node, &list);
13833620737cSbeveloper 	if (B_OK != rv)
13843620737cSbeveloper 		return rv;
13853620737cSbeveloper 
13865ac4fbd7Sbeveloper 	PRINT(4, "BMediaRoster::GetConnectedInputsFor node %ld, max %ld\n", node.node, buf_num_inputs);
13875ac4fbd7Sbeveloper 
138876669a29Sbeveloper 	int32 i;
1389b65a0ac5SJérôme Duval 	for (i = 0, list.Rewind(); list.GetNext(&input);) {
13903620737cSbeveloper 		if (input->source == media_source::null)
13913620737cSbeveloper 			continue; // consumer source not connected
13923620737cSbeveloper 		out_active_inputs[i] = *input;
13933620737cSbeveloper 		*out_total_count += 1;
13943620737cSbeveloper 		buf_num_inputs -= 1;
13955ac4fbd7Sbeveloper 		#if DEBUG >= 3
13965ac4fbd7Sbeveloper 			PRINT_OUTPUT("  input ", out_active_inputs[i]);
13975ac4fbd7Sbeveloper 		#endif
13983620737cSbeveloper 		if (buf_num_inputs == 0)
13993620737cSbeveloper 			break;
1400b65a0ac5SJérôme Duval 		i++;
14013620737cSbeveloper 	}
14023620737cSbeveloper 
14038b04ffc1Sbeveloper 	MediaRosterEx(this)->PublishInputs(node, &list);
14043620737cSbeveloper 	return B_OK;
140552a38012Sejakowatz }
140652a38012Sejakowatz 
140752a38012Sejakowatz 
140852a38012Sejakowatz status_t
140952a38012Sejakowatz BMediaRoster::GetAllInputsFor(const media_node & node,
141052a38012Sejakowatz 							  media_input * out_inputs,
141152a38012Sejakowatz 							  int32 buf_num_inputs,
141252a38012Sejakowatz 							  int32 * out_total_count)
141352a38012Sejakowatz {
141452a38012Sejakowatz 	CALLED();
141540f36b03Sbeveloper 	if (IS_INVALID_NODE(node) || (node.kind & B_BUFFER_CONSUMER) == 0)
141652a38012Sejakowatz 		return B_MEDIA_BAD_NODE;
141752a38012Sejakowatz 	if (out_inputs == NULL || out_total_count == NULL)
141852a38012Sejakowatz 		return B_BAD_VALUE;
141952a38012Sejakowatz 
142076669a29Sbeveloper 	List<media_input> list;
14213620737cSbeveloper 	media_input *input;
142252a38012Sejakowatz 	status_t rv;
142352a38012Sejakowatz 
14241299bfb2Sbeveloper 	*out_total_count = 0;
14251299bfb2Sbeveloper 
14268b04ffc1Sbeveloper 	rv = MediaRosterEx(this)->GetAllInputs(node, &list);
14273620737cSbeveloper 	if (B_OK != rv)
14283620737cSbeveloper 		return rv;
14293620737cSbeveloper 
14305ac4fbd7Sbeveloper 	PRINT(4, "BMediaRoster::GetAllInputsFor node %ld, max %ld\n", node.node, buf_num_inputs);
14315ac4fbd7Sbeveloper 
143276669a29Sbeveloper 	int32 i;
143376669a29Sbeveloper 	for (i = 0, list.Rewind(); list.GetNext(&input); i++) {
14343620737cSbeveloper 		out_inputs[i] = *input;
143552a38012Sejakowatz 		*out_total_count += 1;
14363620737cSbeveloper 		buf_num_inputs -= 1;
14375ac4fbd7Sbeveloper 		#if DEBUG >= 3
14385ac4fbd7Sbeveloper 			PRINT_OUTPUT("  input ", out_inputs[i]);
14395ac4fbd7Sbeveloper 		#endif
14403620737cSbeveloper 		if (buf_num_inputs == 0)
14413620737cSbeveloper 			break;
144252a38012Sejakowatz 	}
144352a38012Sejakowatz 
14448b04ffc1Sbeveloper 	MediaRosterEx(this)->PublishInputs(node, &list);
14453620737cSbeveloper 	return B_OK;
144652a38012Sejakowatz }
144752a38012Sejakowatz 
144852a38012Sejakowatz 
144952a38012Sejakowatz status_t
145052a38012Sejakowatz BMediaRoster::GetFreeOutputsFor(const media_node & node,
145152a38012Sejakowatz 								media_output * out_free_outputs,
145252a38012Sejakowatz 								int32 buf_num_outputs,
145352a38012Sejakowatz 								int32 * out_total_count,
145452a38012Sejakowatz 								media_type filter_type)
145552a38012Sejakowatz {
14563620737cSbeveloper 	CALLED();
145740f36b03Sbeveloper 	if (IS_INVALID_NODE(node) || (node.kind & B_BUFFER_PRODUCER) == 0)
14583620737cSbeveloper 		return B_MEDIA_BAD_NODE;
14593620737cSbeveloper 	if (out_free_outputs == NULL || out_total_count == NULL)
14603620737cSbeveloper 		return B_BAD_VALUE;
14613620737cSbeveloper 
146276669a29Sbeveloper 	List<media_output> list;
14633620737cSbeveloper 	media_output *output;
14643620737cSbeveloper 	status_t rv;
14653620737cSbeveloper 
14661299bfb2Sbeveloper 	*out_total_count = 0;
14671299bfb2Sbeveloper 
14688b04ffc1Sbeveloper 	rv = MediaRosterEx(this)->GetAllOutputs(node, &list);
14693620737cSbeveloper 	if (B_OK != rv)
14703620737cSbeveloper 		return rv;
14713620737cSbeveloper 
14725ac4fbd7Sbeveloper 	PRINT(4, "BMediaRoster::GetFreeOutputsFor node %ld, max %ld, filter-type %ld\n", node.node, buf_num_outputs, filter_type);
14735ac4fbd7Sbeveloper 
147476669a29Sbeveloper 	int32 i;
1475b65a0ac5SJérôme Duval 	for (i = 0, list.Rewind(); list.GetNext(&output);) {
14763620737cSbeveloper 		if (filter_type != B_MEDIA_UNKNOWN_TYPE && filter_type != output->format.type)
14773620737cSbeveloper 			continue; // media_type used, but doesn't match
14783620737cSbeveloper 		if (output->destination != media_destination::null)
14793620737cSbeveloper 			continue; // producer destination already connected
14803620737cSbeveloper 		out_free_outputs[i] = *output;
14813620737cSbeveloper 		*out_total_count += 1;
14823620737cSbeveloper 		buf_num_outputs -= 1;
14835ac4fbd7Sbeveloper 		#if DEBUG >= 3
14845ac4fbd7Sbeveloper 			PRINT_OUTPUT("  output ", out_free_outputs[i]);
14855ac4fbd7Sbeveloper 		#endif
14863620737cSbeveloper 		if (buf_num_outputs == 0)
14873620737cSbeveloper 			break;
1488b65a0ac5SJérôme Duval 		i++;
14893620737cSbeveloper 	}
14903620737cSbeveloper 
14918b04ffc1Sbeveloper 	MediaRosterEx(this)->PublishOutputs(node, &list);
14923620737cSbeveloper 	return B_OK;
149352a38012Sejakowatz }
149452a38012Sejakowatz 
149552a38012Sejakowatz 
149652a38012Sejakowatz status_t
149752a38012Sejakowatz BMediaRoster::GetConnectedOutputsFor(const media_node & node,
149852a38012Sejakowatz 									 media_output * out_active_outputs,
149952a38012Sejakowatz 									 int32 buf_num_outputs,
150052a38012Sejakowatz 									 int32 * out_total_count)
150152a38012Sejakowatz {
15023620737cSbeveloper 	CALLED();
150340f36b03Sbeveloper 	if (IS_INVALID_NODE(node) || (node.kind & B_BUFFER_PRODUCER) == 0)
15043620737cSbeveloper 		return B_MEDIA_BAD_NODE;
15053620737cSbeveloper 	if (out_active_outputs == NULL || out_total_count == NULL)
15063620737cSbeveloper 		return B_BAD_VALUE;
15073620737cSbeveloper 
150876669a29Sbeveloper 	List<media_output> list;
15093620737cSbeveloper 	media_output *output;
15103620737cSbeveloper 	status_t rv;
15113620737cSbeveloper 
15121299bfb2Sbeveloper 	*out_total_count = 0;
15131299bfb2Sbeveloper 
15148b04ffc1Sbeveloper 	rv = MediaRosterEx(this)->GetAllOutputs(node, &list);
15153620737cSbeveloper 	if (B_OK != rv)
15163620737cSbeveloper 		return rv;
15173620737cSbeveloper 
15185ac4fbd7Sbeveloper 	PRINT(4, "BMediaRoster::GetConnectedOutputsFor node %ld, max %ld\n", node.node, buf_num_outputs);
15195ac4fbd7Sbeveloper 
152076669a29Sbeveloper 	int32 i;
1521b65a0ac5SJérôme Duval 	for (i = 0, list.Rewind(); list.GetNext(&output);) {
15223620737cSbeveloper 		if (output->destination == media_destination::null)
15233620737cSbeveloper 			continue; // producer destination not connected
15243620737cSbeveloper 		out_active_outputs[i] = *output;
15253620737cSbeveloper 		*out_total_count += 1;
15263620737cSbeveloper 		buf_num_outputs -= 1;
15275ac4fbd7Sbeveloper 		#if DEBUG >= 3
15285ac4fbd7Sbeveloper 			PRINT_OUTPUT("  output ", out_active_outputs[i]);
15295ac4fbd7Sbeveloper 		#endif
15303620737cSbeveloper 		if (buf_num_outputs == 0)
15313620737cSbeveloper 			break;
1532b65a0ac5SJérôme Duval 		i++;
15333620737cSbeveloper 	}
15343620737cSbeveloper 
15358b04ffc1Sbeveloper 	MediaRosterEx(this)->PublishOutputs(node, &list);
15363620737cSbeveloper 	return B_OK;
153752a38012Sejakowatz }
153852a38012Sejakowatz 
153952a38012Sejakowatz 
154052a38012Sejakowatz status_t
154152a38012Sejakowatz BMediaRoster::GetAllOutputsFor(const media_node & node,
154252a38012Sejakowatz 							   media_output * out_outputs,
154352a38012Sejakowatz 							   int32 buf_num_outputs,
154452a38012Sejakowatz 							   int32 * out_total_count)
154552a38012Sejakowatz {
154652a38012Sejakowatz 	CALLED();
154740f36b03Sbeveloper 	if (IS_INVALID_NODE(node) || (node.kind & B_BUFFER_PRODUCER) == 0)
154852a38012Sejakowatz 		return B_MEDIA_BAD_NODE;
154952a38012Sejakowatz 	if (out_outputs == NULL || out_total_count == NULL)
155052a38012Sejakowatz 		return B_BAD_VALUE;
155152a38012Sejakowatz 
155276669a29Sbeveloper 	List<media_output> list;
15533620737cSbeveloper 	media_output *output;
155452a38012Sejakowatz 	status_t rv;
155552a38012Sejakowatz 
15561299bfb2Sbeveloper 	*out_total_count = 0;
15571299bfb2Sbeveloper 
15588b04ffc1Sbeveloper 	rv = MediaRosterEx(this)->GetAllOutputs(node, &list);
15593620737cSbeveloper 	if (B_OK != rv)
15603620737cSbeveloper 		return rv;
15613620737cSbeveloper 
15625ac4fbd7Sbeveloper 	PRINT(4, "BMediaRoster::GetAllOutputsFor node %ld, max %ld\n", node.node, buf_num_outputs);
15635ac4fbd7Sbeveloper 
156476669a29Sbeveloper 	int32 i;
156576669a29Sbeveloper 	for (i = 0, list.Rewind(); list.GetNext(&output); i++) {
15663620737cSbeveloper 		out_outputs[i] = *output;
156752a38012Sejakowatz 		*out_total_count += 1;
15683620737cSbeveloper 		buf_num_outputs -= 1;
15695ac4fbd7Sbeveloper 		#if DEBUG >= 3
15705ac4fbd7Sbeveloper 			PRINT_OUTPUT("  output ", out_outputs[i]);
15715ac4fbd7Sbeveloper 		#endif
15723620737cSbeveloper 		if (buf_num_outputs == 0)
15733620737cSbeveloper 			break;
157452a38012Sejakowatz 	}
157552a38012Sejakowatz 
15768b04ffc1Sbeveloper 	MediaRosterEx(this)->PublishOutputs(node, &list);
15773620737cSbeveloper 	return B_OK;
157852a38012Sejakowatz }
157952a38012Sejakowatz 
158052a38012Sejakowatz 
158152a38012Sejakowatz status_t
158252a38012Sejakowatz BMediaRoster::StartWatching(const BMessenger & where)
158352a38012Sejakowatz {
1584eae26d3dSbeveloper 	CALLED();
1585eae26d3dSbeveloper 	if (!where.IsValid()) {
15865ac4fbd7Sbeveloper 		ERROR("BMediaRoster::StartWatching: messenger invalid!\n");
1587eae26d3dSbeveloper 		return B_BAD_VALUE;
1588eae26d3dSbeveloper 	}
1589f4925104Sbeveloper 	return BPrivate::media::notifications::Register(where, media_node::null, B_MEDIA_WILDCARD);
159052a38012Sejakowatz }
159152a38012Sejakowatz 
159252a38012Sejakowatz 
159352a38012Sejakowatz status_t
159452a38012Sejakowatz BMediaRoster::StartWatching(const BMessenger & where,
159552a38012Sejakowatz 							int32 notificationType)
159652a38012Sejakowatz {
1597eae26d3dSbeveloper 	CALLED();
1598eae26d3dSbeveloper 	if (!where.IsValid()) {
15995ac4fbd7Sbeveloper 		ERROR("BMediaRoster::StartWatching: messenger invalid!\n");
1600eae26d3dSbeveloper 		return B_BAD_VALUE;
1601eae26d3dSbeveloper 	}
1602f4925104Sbeveloper 	if (false == BPrivate::media::notifications::IsValidNotificationRequest(false, notificationType)) {
16035ac4fbd7Sbeveloper 		ERROR("BMediaRoster::StartWatching: notificationType invalid!\n");
1604eae26d3dSbeveloper 		return B_BAD_VALUE;
1605eae26d3dSbeveloper 	}
1606f4925104Sbeveloper 	return BPrivate::media::notifications::Register(where, media_node::null, notificationType);
160752a38012Sejakowatz }
160852a38012Sejakowatz 
160952a38012Sejakowatz 
161052a38012Sejakowatz status_t
161152a38012Sejakowatz BMediaRoster::StartWatching(const BMessenger & where,
161252a38012Sejakowatz 							const media_node & node,
161352a38012Sejakowatz 							int32 notificationType)
161452a38012Sejakowatz {
1615eae26d3dSbeveloper 	CALLED();
1616eae26d3dSbeveloper 	if (!where.IsValid()) {
16175ac4fbd7Sbeveloper 		ERROR("BMediaRoster::StartWatching: messenger invalid!\n");
1618eae26d3dSbeveloper 		return B_BAD_VALUE;
1619eae26d3dSbeveloper 	}
162040f36b03Sbeveloper 	if (IS_INVALID_NODE(node)) {
16215ac4fbd7Sbeveloper 		ERROR("BMediaRoster::StartWatching: node invalid!\n");
1622eae26d3dSbeveloper 		return B_MEDIA_BAD_NODE;
1623eae26d3dSbeveloper 	}
1624f4925104Sbeveloper 	if (false == BPrivate::media::notifications::IsValidNotificationRequest(true, notificationType)) {
16255ac4fbd7Sbeveloper 		ERROR("BMediaRoster::StartWatching: notificationType invalid!\n");
1626eae26d3dSbeveloper 		return B_BAD_VALUE;
1627eae26d3dSbeveloper 	}
1628f4925104Sbeveloper 	return BPrivate::media::notifications::Register(where, node, notificationType);
162952a38012Sejakowatz }
163052a38012Sejakowatz 
163152a38012Sejakowatz 
163252a38012Sejakowatz status_t
163352a38012Sejakowatz BMediaRoster::StopWatching(const BMessenger & where)
163452a38012Sejakowatz {
1635eae26d3dSbeveloper 	CALLED();
1636eae26d3dSbeveloper 	// messenger may already be invalid, so we don't check this
1637f4925104Sbeveloper 	return BPrivate::media::notifications::Unregister(where, media_node::null, B_MEDIA_WILDCARD);
163852a38012Sejakowatz }
163952a38012Sejakowatz 
164052a38012Sejakowatz 
164152a38012Sejakowatz status_t
164252a38012Sejakowatz BMediaRoster::StopWatching(const BMessenger & where,
164352a38012Sejakowatz 						   int32 notificationType)
164452a38012Sejakowatz {
1645eae26d3dSbeveloper 	CALLED();
1646eae26d3dSbeveloper 	// messenger may already be invalid, so we don't check this
1647f4925104Sbeveloper 	if (false == BPrivate::media::notifications::IsValidNotificationRequest(false, notificationType)) {
16485ac4fbd7Sbeveloper 		ERROR("BMediaRoster::StopWatching: notificationType invalid!\n");
1649eae26d3dSbeveloper 		return B_BAD_VALUE;
1650eae26d3dSbeveloper 	}
1651f4925104Sbeveloper 	return BPrivate::media::notifications::Unregister(where, media_node::null, notificationType);
165252a38012Sejakowatz }
165352a38012Sejakowatz 
165452a38012Sejakowatz 
165552a38012Sejakowatz status_t
165652a38012Sejakowatz BMediaRoster::StopWatching(const BMessenger & where,
165752a38012Sejakowatz 						   const media_node & node,
165852a38012Sejakowatz 						   int32 notificationType)
165952a38012Sejakowatz {
1660eae26d3dSbeveloper 	CALLED();
1661eae26d3dSbeveloper 	// messenger may already be invalid, so we don't check this
166240f36b03Sbeveloper 	if (IS_INVALID_NODE(node)) {
16635ac4fbd7Sbeveloper 		ERROR("BMediaRoster::StopWatching: node invalid!\n");
1664eae26d3dSbeveloper 		return B_MEDIA_BAD_NODE;
1665eae26d3dSbeveloper 	}
1666f4925104Sbeveloper 	if (false == BPrivate::media::notifications::IsValidNotificationRequest(true, notificationType)) {
16675ac4fbd7Sbeveloper 		ERROR("BMediaRoster::StopWatching: notificationType invalid!\n");
1668eae26d3dSbeveloper 		return B_BAD_VALUE;
1669eae26d3dSbeveloper 	}
1670f4925104Sbeveloper 	return BPrivate::media::notifications::Unregister(where, node, notificationType);
167152a38012Sejakowatz }
167252a38012Sejakowatz 
167352a38012Sejakowatz 
167452a38012Sejakowatz status_t
167552a38012Sejakowatz BMediaRoster::RegisterNode(BMediaNode * node)
167652a38012Sejakowatz {
167754187cc6Sbeveloper 	CALLED();
167854187cc6Sbeveloper 	// addon-id = -1 (unused), addon-flavor-id = 0 (unused, too)
167954187cc6Sbeveloper 	return MediaRosterEx(this)->RegisterNode(node, -1, 0);
168054187cc6Sbeveloper }
168154187cc6Sbeveloper 
168254187cc6Sbeveloper 
168354187cc6Sbeveloper status_t
168454187cc6Sbeveloper BMediaRosterEx::RegisterNode(BMediaNode * node, media_addon_id addonid, int32 flavorid)
168554187cc6Sbeveloper {
168652a38012Sejakowatz 	CALLED();
168752a38012Sejakowatz 	if (node == NULL)
168852a38012Sejakowatz 		return B_BAD_VALUE;
168952a38012Sejakowatz 
169054187cc6Sbeveloper 	// some sanity check
169154187cc6Sbeveloper 	// I'm not sure if the media kit warrants to call BMediaNode::AddOn() here.
169254187cc6Sbeveloper 	// Perhaps we don't need it.
169354187cc6Sbeveloper 	{
16949e9417d2Sbeveloper 		BMediaAddOn *addon;
16959e9417d2Sbeveloper 		int32 addon_flavor_id;
16969e9417d2Sbeveloper 		media_addon_id addon_id;
16979e9417d2Sbeveloper 		addon_flavor_id = 0;
16989e9417d2Sbeveloper 		addon = node->AddOn(&addon_flavor_id);
16999e9417d2Sbeveloper 		addon_id = addon ? addon->AddonID() : -1;
170054187cc6Sbeveloper 		ASSERT(addonid == addon_id);
170154187cc6Sbeveloper 		ASSERT(flavorid == addon_flavor_id);
170254187cc6Sbeveloper 	}
170352a38012Sejakowatz 
170454187cc6Sbeveloper 	status_t rv;
17059e9417d2Sbeveloper 	server_register_node_request request;
17069e9417d2Sbeveloper 	server_register_node_reply reply;
17079e9417d2Sbeveloper 
170854187cc6Sbeveloper 	request.addon_id = addonid;
170954187cc6Sbeveloper 	request.addon_flavor_id = flavorid;
17109e9417d2Sbeveloper 	strcpy(request.name, node->Name());
17119e9417d2Sbeveloper 	request.kinds = node->Kinds();
17129e9417d2Sbeveloper 	request.port = node->ControlPort();
17139e9417d2Sbeveloper 	request.team = team;
17149e9417d2Sbeveloper 
17158b04ffc1Sbeveloper 	TRACE("BMediaRoster::RegisterNode: sending SERVER_REGISTER_NODE: port %ld, kinds 0x%Lx, team %ld, name '%s'\n", request.port, request.kinds, request.team, request.name);
17161299bfb2Sbeveloper 
17179e9417d2Sbeveloper 	rv = QueryServer(SERVER_REGISTER_NODE, &request, sizeof(request), &reply, sizeof(reply));
17189e9417d2Sbeveloper 	if (rv != B_OK) {
17195ac4fbd7Sbeveloper 		ERROR("BMediaRoster::RegisterNode: failed to register node %s (error %#lx)\n", node->Name(), rv);
17209e9417d2Sbeveloper 		return rv;
17219e9417d2Sbeveloper 	}
17229e9417d2Sbeveloper 
17234295907bSbeveloper 	TRACE("BMediaRoster::RegisterNode: QueryServer SERVER_REGISTER_NODE finished\n");
17244295907bSbeveloper 
17258b04ffc1Sbeveloper 	// we are a friend class of BMediaNode and initialize this member variable
17269e9417d2Sbeveloper 	node->fNodeID = reply.nodeid;
17279e9417d2Sbeveloper 	ASSERT(reply.nodeid == node->Node().node);
17289e9417d2Sbeveloper 	ASSERT(reply.nodeid == node->ID());
17299e9417d2Sbeveloper 
17309e9417d2Sbeveloper 	// call the callback
17319e9417d2Sbeveloper 	node->NodeRegistered();
17323620737cSbeveloper 
17334295907bSbeveloper 	TRACE("BMediaRoster::RegisterNode: NodeRegistered callback finished\n");
17344295907bSbeveloper 
17350e21b167Sbeveloper 	// if the BMediaNode also inherits from BTimeSource, we need to call BTimeSource::FinishCreate()
17360e21b167Sbeveloper 	if (node->Kinds() & B_TIME_SOURCE) {
17370e21b167Sbeveloper 		BTimeSource *ts;
17380e21b167Sbeveloper 		ts = dynamic_cast<BTimeSource *>(node);
17390e21b167Sbeveloper 		if (ts)
17400e21b167Sbeveloper 			ts->FinishCreate();
17410e21b167Sbeveloper 	}
17420e21b167Sbeveloper 
17434295907bSbeveloper 	TRACE("BMediaRoster::RegisterNode: publishing inputs/outputs\n");
17444295907bSbeveloper 
17453620737cSbeveloper 	// register existing inputs and outputs with the
17463620737cSbeveloper 	// media_server, this allows GetLiveNodes() to work
17473620737cSbeveloper 	// with created, but unconnected nodes.
17484d2d96e0Sbeveloper 	// The node control loop might not be running, or might deadlock
17494d2d96e0Sbeveloper 	// if we send a message and wait for a reply here.
17504d2d96e0Sbeveloper 	// We have a pointer to the node, and thus call the functions directly
17514295907bSbeveloper 
17523620737cSbeveloper 	if (node->Kinds() & B_BUFFER_PRODUCER) {
17534d2d96e0Sbeveloper 		BBufferProducer *bp;
17544d2d96e0Sbeveloper 		bp = dynamic_cast<BBufferProducer *>(node);
17554d2d96e0Sbeveloper 		if (bp) {
1756359ac306Sbeveloper 			List<media_output> list;
17574d2d96e0Sbeveloper 			if (B_OK == GetAllOutputs(bp, &list))
1758359ac306Sbeveloper 				PublishOutputs(node->Node(), &list);
175921871f38Sbeveloper 		}
17604d2d96e0Sbeveloper 	}
176121871f38Sbeveloper 	if (node->Kinds() & B_BUFFER_CONSUMER) {
17624d2d96e0Sbeveloper 		BBufferConsumer *bc;
17634d2d96e0Sbeveloper 		bc = dynamic_cast<BBufferConsumer *>(node);
17644d2d96e0Sbeveloper 		if (bc) {
1765359ac306Sbeveloper 			List<media_input> list;
17664d2d96e0Sbeveloper 			if (B_OK == GetAllInputs(bc, &list))
1767359ac306Sbeveloper 				PublishInputs(node->Node(), &list);
17683620737cSbeveloper 		}
17694d2d96e0Sbeveloper 	}
177021871f38Sbeveloper 
17714295907bSbeveloper 	TRACE("BMediaRoster::RegisterNode: sending NodesCreated\n");
17724295907bSbeveloper 
17731299bfb2Sbeveloper 	BPrivate::media::notifications::NodesCreated(&reply.nodeid, 1);
17744295907bSbeveloper 
17754295907bSbeveloper 	TRACE("BMediaRoster::RegisterNode: finished\n");
17764295907bSbeveloper 
1777570f7d04Sbeveloper /*
1778570f7d04Sbeveloper 	TRACE("BMediaRoster::RegisterNode: registered node name '%s', id %ld, addon %ld, flavor %ld\n", node->Name(), node->ID(), addon_id, addon_flavor_id);
1779570f7d04Sbeveloper 	TRACE("BMediaRoster::RegisterNode: node this               %p\n", node);
1780570f7d04Sbeveloper 	TRACE("BMediaRoster::RegisterNode: node fConsumerThis      %p\n", node->fConsumerThis);
1781570f7d04Sbeveloper 	TRACE("BMediaRoster::RegisterNode: node fProducerThis      %p\n", node->fProducerThis);
1782570f7d04Sbeveloper 	TRACE("BMediaRoster::RegisterNode: node fFileInterfaceThis %p\n", node->fFileInterfaceThis);
1783570f7d04Sbeveloper 	TRACE("BMediaRoster::RegisterNode: node fControllableThis  %p\n", node->fControllableThis);
1784570f7d04Sbeveloper 	TRACE("BMediaRoster::RegisterNode: node fTimeSourceThis    %p\n", node->fTimeSourceThis);
1785570f7d04Sbeveloper */
17869e9417d2Sbeveloper 	return B_OK;
178752a38012Sejakowatz }
178852a38012Sejakowatz 
178952a38012Sejakowatz 
179052a38012Sejakowatz status_t
179152a38012Sejakowatz BMediaRoster::UnregisterNode(BMediaNode * node)
179252a38012Sejakowatz {
17939e9417d2Sbeveloper 	CALLED();
17949e9417d2Sbeveloper 	if (node == NULL)
17959e9417d2Sbeveloper 		return B_BAD_VALUE;
17969e9417d2Sbeveloper 
179760f15390Sbeveloper 	TRACE("BMediaRoster::UnregisterNode %ld (%p)\n", node->ID(), node);
179860f15390Sbeveloper 
179986bce45bSbeveloper 	if (node->fKinds & NODE_KIND_NO_REFCOUNTING) {
180086bce45bSbeveloper 		printf("BMediaRoster::UnregisterNode, trying to unregister reference counting disabled timesource, node %ld, port %ld, team %ld\n", node->ID(), node->ControlPort(), team);
180186bce45bSbeveloper 		return B_OK;
180286bce45bSbeveloper 	}
18038b04ffc1Sbeveloper 	if (node->ID() == NODE_UNREGISTERED_ID) {
18045ac4fbd7Sbeveloper 		PRINT(1, "Warning: BMediaRoster::UnregisterNode: node id %ld, name '%s' already unregistered\n", node->ID(), node->Name());
18059e9417d2Sbeveloper 		return B_OK;
18069e9417d2Sbeveloper 	}
180754187cc6Sbeveloper 	if (node->fRefCount != 0) {
18085ac4fbd7Sbeveloper 		PRINT(1, "Warning: BMediaRoster::UnregisterNode: node id %ld, name '%s' has local reference count of %ld\n", node->ID(), node->Name(), node->fRefCount);
180954187cc6Sbeveloper 		// no return here, we continue and unregister!
181054187cc6Sbeveloper 	}
181154187cc6Sbeveloper 
181254187cc6Sbeveloper 	// Calling BMediaAddOn::GetConfigurationFor(BMediaNode *node, BMessage *config)
181354187cc6Sbeveloper 	// if this node was instanciated by an add-on needs to be done *somewhere*
181454187cc6Sbeveloper 	// We can't do it here because it is already to late (destructor of the node
181554187cc6Sbeveloper 	// might have been called).
18169e9417d2Sbeveloper 
18179e9417d2Sbeveloper 	server_unregister_node_request request;
18189e9417d2Sbeveloper 	server_unregister_node_reply reply;
18199e9417d2Sbeveloper 	status_t rv;
18209e9417d2Sbeveloper 
18219e9417d2Sbeveloper 	request.nodeid = node->ID();
18229e9417d2Sbeveloper 	request.team = team;
18239e9417d2Sbeveloper 
18241299bfb2Sbeveloper 	// send a notification
18251299bfb2Sbeveloper 	BPrivate::media::notifications::NodesDeleted(&request.nodeid, 1);
18261299bfb2Sbeveloper 
18279e9417d2Sbeveloper 	rv = QueryServer(SERVER_UNREGISTER_NODE, &request, sizeof(request), &reply, sizeof(reply));
18289e9417d2Sbeveloper 	if (rv != B_OK) {
18295ac4fbd7Sbeveloper 		ERROR("BMediaRoster::UnregisterNode: failed to unregister node id %ld, name '%s' (error %#lx)\n", node->ID(), node->Name(), rv);
18309e9417d2Sbeveloper 		return rv;
18319e9417d2Sbeveloper 	}
18329e9417d2Sbeveloper 
183354187cc6Sbeveloper 	if (reply.addonid != -1) {
183454187cc6Sbeveloper 		// Small problem here, we can't use DormantNodeManager::PutAddon(), as
183554187cc6Sbeveloper 		// UnregisterNode() is called by a dormant node itself (by the destructor).
183654187cc6Sbeveloper 		// The add-on that contains the node needs to remain in memory until the
183754187cc6Sbeveloper 		// destructor execution is finished.
183854187cc6Sbeveloper 		// DormantNodeManager::PutAddonDelayed() will delay unloading.
183954187cc6Sbeveloper 		_DormantNodeManager->PutAddonDelayed(reply.addonid);
1840cf4e2277Sbeveloper 
184173794717Sbeveloper 		rv = MediaRosterEx(this)->DecrementAddonFlavorInstancesCount(reply.addonid, reply.flavorid);
184254187cc6Sbeveloper 		if (rv != B_OK) {
18435ac4fbd7Sbeveloper 			ERROR("BMediaRoster::UnregisterNode: DecrementAddonFlavorInstancesCount failed\n");
184454187cc6Sbeveloper 			// this is really a problem, but we can't fail now
184554187cc6Sbeveloper 		}
18468b04ffc1Sbeveloper 	}
18479e9417d2Sbeveloper 
18481299bfb2Sbeveloper 	// we are a friend class of BMediaNode and invalidate this member variable
18498b04ffc1Sbeveloper 	node->fNodeID = NODE_UNREGISTERED_ID;
18509e9417d2Sbeveloper 
18519e9417d2Sbeveloper 	return B_OK;
185252a38012Sejakowatz }
185352a38012Sejakowatz 
185452a38012Sejakowatz 
185552a38012Sejakowatz //	thread safe for multiple calls to Roster()
185652a38012Sejakowatz /* static */ BMediaRoster *
185752a38012Sejakowatz BMediaRoster::Roster(status_t *out_error)
185852a38012Sejakowatz {
185952a38012Sejakowatz 	static BLocker locker("BMediaRoster::Roster locker");
186052a38012Sejakowatz 	locker.Lock();
1861*8496c38aSbeveloper 	if (out_error)
1862*8496c38aSbeveloper 		*out_error = B_OK;
186352a38012Sejakowatz 	if (_sDefault == NULL) {
1864*8496c38aSbeveloper 		status_t err;
1865dcfb6bfcSJérôme Duval 		_sDefault = new BMediaRosterEx(&err);
1866dcfb6bfcSJérôme Duval 		if (err != B_OK) {
1867dcfb6bfcSJérôme Duval 			if (_sDefault) {
1868dcfb6bfcSJérôme Duval 				_sDefault->Lock();
1869dcfb6bfcSJérôme Duval 				_sDefault->Quit();
1870dcfb6bfcSJérôme Duval 				_sDefault = NULL;
1871dcfb6bfcSJérôme Duval 			}
1872*8496c38aSbeveloper 			if (out_error)
1873*8496c38aSbeveloper 				*out_error = err;
1874*8496c38aSbeveloper 		}
187552a38012Sejakowatz 	}
187652a38012Sejakowatz 	locker.Unlock();
187752a38012Sejakowatz 	return _sDefault;
187852a38012Sejakowatz }
187952a38012Sejakowatz 
188052a38012Sejakowatz 
188152a38012Sejakowatz //	won't create it if there isn't one
188252a38012Sejakowatz //	not thread safe if you call Roster() at the same time
188352a38012Sejakowatz /* static */ BMediaRoster *
188452a38012Sejakowatz BMediaRoster::CurrentRoster()
188552a38012Sejakowatz {
188652a38012Sejakowatz 	return _sDefault;
188752a38012Sejakowatz }
188852a38012Sejakowatz 
188952a38012Sejakowatz 
189052a38012Sejakowatz status_t
189152a38012Sejakowatz BMediaRoster::SetTimeSourceFor(media_node_id node,
189252a38012Sejakowatz 							   media_node_id time_source)
189352a38012Sejakowatz {
1894aac800c2Sbeveloper 	CALLED();
189540f36b03Sbeveloper 	if (IS_INVALID_NODEID(node) || IS_INVALID_NODEID(time_source))
1896aac800c2Sbeveloper 		return B_BAD_VALUE;
1897aac800c2Sbeveloper 
1898aac800c2Sbeveloper 	media_node clone;
1899aac800c2Sbeveloper 	status_t rv, result;
1900aac800c2Sbeveloper 
19015917dd5bSbeveloper 	TRACE("BMediaRoster::SetTimeSourceFor: node %ld will be assigned time source %ld\n", node, time_source);
19025917dd5bSbeveloper 
19035917dd5bSbeveloper 	printf("BMediaRoster::SetTimeSourceFor: node %ld time source %ld enter\n", node, time_source);
19045917dd5bSbeveloper 
190586bce45bSbeveloper 	// we need to get a clone of the node to have a port id
1906aac800c2Sbeveloper 	rv = GetNodeFor(node, &clone);
1907aac800c2Sbeveloper 	if (rv != B_OK) {
19085ac4fbd7Sbeveloper 		ERROR("BMediaRoster::SetTimeSourceFor, GetNodeFor failed, node id %ld\n", node);
190952a38012Sejakowatz 		return B_ERROR;
191052a38012Sejakowatz 	}
191152a38012Sejakowatz 
191286bce45bSbeveloper 	// we just send the request to set time_source-id as timesource to the node,
191386bce45bSbeveloper 	// the NODE_SET_TIMESOURCE handler code will do the real assignment
1914aac800c2Sbeveloper 	result = B_OK;
1915aac800c2Sbeveloper 	node_set_timesource_command cmd;
1916aac800c2Sbeveloper 	cmd.timesource_id = time_source;
1917aac800c2Sbeveloper 	rv = SendToPort(clone.port, NODE_SET_TIMESOURCE, &cmd, sizeof(cmd));
1918aac800c2Sbeveloper 	if (rv != B_OK) {
19195ac4fbd7Sbeveloper 		ERROR("BMediaRoster::SetTimeSourceFor, sending NODE_SET_TIMESOURCE failed, node id %ld\n", node);
1920aac800c2Sbeveloper 		result = B_ERROR;
1921aac800c2Sbeveloper 	}
1922aac800c2Sbeveloper 
192360f15390Sbeveloper 	// we release the clone
1924aac800c2Sbeveloper 	rv = ReleaseNode(clone);
1925aac800c2Sbeveloper 	if (rv != B_OK) {
19265ac4fbd7Sbeveloper 		ERROR("BMediaRoster::SetTimeSourceFor, ReleaseNode failed, node id %ld\n", node);
1927aac800c2Sbeveloper 		result = B_ERROR;
1928aac800c2Sbeveloper 	}
1929aac800c2Sbeveloper 
19305917dd5bSbeveloper 	printf("BMediaRoster::SetTimeSourceFor: node %ld time source %ld leave\n", node, time_source);
19315917dd5bSbeveloper 
1932aac800c2Sbeveloper 	return result;
1933aac800c2Sbeveloper }
1934aac800c2Sbeveloper 
193552a38012Sejakowatz 
193652a38012Sejakowatz status_t
193752a38012Sejakowatz BMediaRoster::GetParameterWebFor(const media_node & node,
193852a38012Sejakowatz 								 BParameterWeb ** out_web)
193952a38012Sejakowatz {
194028ad138aSbeveloper 	CALLED();
194128ad138aSbeveloper 	if (out_web == NULL)
194228ad138aSbeveloper 		return B_BAD_VALUE;
194328ad138aSbeveloper 	if (IS_INVALID_NODE(node))
194428ad138aSbeveloper 		return B_MEDIA_BAD_NODE;
194528ad138aSbeveloper 	if ((node.kind & B_CONTROLLABLE) == 0)
194628ad138aSbeveloper 		return B_MEDIA_BAD_NODE;
194728ad138aSbeveloper 
194828ad138aSbeveloper 	controllable_get_parameter_web_request request;
194928ad138aSbeveloper 	controllable_get_parameter_web_reply reply;
195028ad138aSbeveloper 	int32 requestsize[] = {B_PAGE_SIZE, 4*B_PAGE_SIZE, 16*B_PAGE_SIZE, 64*B_PAGE_SIZE, 128*B_PAGE_SIZE, 256*B_PAGE_SIZE, 0};
195128ad138aSbeveloper 	int32 size;
195228ad138aSbeveloper 
195328ad138aSbeveloper 	// XXX it might be better to query the node for the (current) parameter size first
195428ad138aSbeveloper 	for (int i = 0; (size = requestsize[i]) != 0; i++) {
195528ad138aSbeveloper 		status_t rv;
195628ad138aSbeveloper 		area_id area;
195728ad138aSbeveloper 		void *data;
195828ad138aSbeveloper 		area = create_area("parameter web data", &data, B_ANY_ADDRESS, size, B_NO_LOCK, B_READ_AREA | B_WRITE_AREA);
195928ad138aSbeveloper 		if (area < B_OK) {
19605ac4fbd7Sbeveloper 			ERROR("BMediaRoster::GetParameterWebFor couldn't create area of size %ld\n", size);
196128ad138aSbeveloper 			return B_ERROR;
196228ad138aSbeveloper 		}
196328ad138aSbeveloper 		request.maxsize = size;
196428ad138aSbeveloper 		request.area = area;
196528ad138aSbeveloper 		rv = QueryPort(node.port, CONTROLLABLE_GET_PARAMETER_WEB, &request, sizeof(request), &reply, sizeof(reply));
196628ad138aSbeveloper 		if (rv != B_OK) {
19675ac4fbd7Sbeveloper 			ERROR("BMediaRoster::GetParameterWebFor CONTROLLABLE_GET_PARAMETER_WEB failed\n");
196828ad138aSbeveloper 			delete_area(area);
196928ad138aSbeveloper 			return B_ERROR;
197028ad138aSbeveloper 		}
197128ad138aSbeveloper 		if (reply.size == 0) {
197228ad138aSbeveloper 			// no parameter web available
197328ad138aSbeveloper 			// XXX should we return an error?
19745ac4fbd7Sbeveloper 			ERROR("BMediaRoster::GetParameterWebFor node %ld has no parameter web\n", node.node);
197528ad138aSbeveloper 			*out_web = new BParameterWeb();
197628ad138aSbeveloper 			delete_area(area);
197760f15390Sbeveloper 			return B_OK;
197852a38012Sejakowatz 		}
197928ad138aSbeveloper 		if (reply.size > 0) {
198028ad138aSbeveloper 			// we got a flattened parameter web!
198128ad138aSbeveloper 			*out_web = new BParameterWeb();
198228ad138aSbeveloper 
1983d91580cdSbeveloper 			printf("BMediaRoster::GetParameterWebFor Unflattening %ld bytes, 0x%08lx, 0x%08lx, 0x%08lx, 0x%08lx\n",
198428ad138aSbeveloper 				reply.size, ((uint32*)data)[0], ((uint32*)data)[1], ((uint32*)data)[2], ((uint32*)data)[3]);
198528ad138aSbeveloper 
198628ad138aSbeveloper 			rv = (*out_web)->Unflatten(reply.code, data, reply.size);
198728ad138aSbeveloper 			if (rv != B_OK) {
19885ac4fbd7Sbeveloper 				ERROR("BMediaRoster::GetParameterWebFor Unflatten failed, %s\n", strerror(rv));
198928ad138aSbeveloper 				delete_area(area);
199028ad138aSbeveloper 				delete *out_web;
199128ad138aSbeveloper 				return B_ERROR;
199228ad138aSbeveloper 			}
199328ad138aSbeveloper 			delete_area(area);
199428ad138aSbeveloper 			return B_OK;
199528ad138aSbeveloper 		}
199628ad138aSbeveloper 		delete_area(area);
199728ad138aSbeveloper 		ASSERT(reply.size == -1);
199828ad138aSbeveloper 		// parameter web data was too large
199928ad138aSbeveloper 		// loop and try a larger size
200028ad138aSbeveloper 	}
20015ac4fbd7Sbeveloper 	ERROR("BMediaRoster::GetParameterWebFor node %ld has no parameter web larger than %ld\n", node.node, size);
200228ad138aSbeveloper 	return B_ERROR;
200328ad138aSbeveloper }
200452a38012Sejakowatz 
200552a38012Sejakowatz 
200652a38012Sejakowatz status_t
200752a38012Sejakowatz BMediaRoster::StartControlPanel(const media_node & node,
200852a38012Sejakowatz 								BMessenger * out_messenger)
200952a38012Sejakowatz {
201052a38012Sejakowatz 	UNIMPLEMENTED();
201152a38012Sejakowatz 	return B_ERROR;
201252a38012Sejakowatz }
201352a38012Sejakowatz 
201452a38012Sejakowatz 
201552a38012Sejakowatz status_t
201652a38012Sejakowatz BMediaRoster::GetDormantNodes(dormant_node_info * out_info,
201752a38012Sejakowatz 							  int32 * io_count,
201852a38012Sejakowatz 							  const media_format * has_input /* = NULL */,
201952a38012Sejakowatz 							  const media_format * has_output /* = NULL */,
202052a38012Sejakowatz 							  const char * name /* = NULL */,
202152a38012Sejakowatz 							  uint64 require_kinds /* = NULL */,
202252a38012Sejakowatz 							  uint64 deny_kinds /* = NULL */)
202352a38012Sejakowatz {
202452a38012Sejakowatz 	CALLED();
202552a38012Sejakowatz 	if (out_info == NULL)
202652a38012Sejakowatz 		return B_BAD_VALUE;
202752a38012Sejakowatz 	if (io_count == NULL)
202852a38012Sejakowatz 		return B_BAD_VALUE;
202952a38012Sejakowatz 	if (*io_count <= 0)
203052a38012Sejakowatz 		return B_BAD_VALUE;
203152a38012Sejakowatz 
203252a38012Sejakowatz 	xfer_server_get_dormant_nodes msg;
203352a38012Sejakowatz 	port_id port;
203452a38012Sejakowatz 	status_t rv;
203552a38012Sejakowatz 
20364295907bSbeveloper 	port = find_port(MEDIA_SERVER_PORT_NAME);
203752a38012Sejakowatz 	if (port <= B_OK)
203852a38012Sejakowatz 		return B_ERROR;
203952a38012Sejakowatz 
204052a38012Sejakowatz 	msg.maxcount = *io_count;
204152a38012Sejakowatz 	msg.has_input = (bool) has_input;
204252a38012Sejakowatz 	if (has_input)
204352a38012Sejakowatz 		msg.inputformat = *has_input; // XXX we should not make a flat copy of media_format
204452a38012Sejakowatz 	msg.has_output = (bool) has_output;
204552a38012Sejakowatz 	if (has_output)
204652a38012Sejakowatz 		msg.outputformat = *has_output;; // XXX we should not make a flat copy of media_format
204752a38012Sejakowatz 	msg.has_name = (bool) name;
204852a38012Sejakowatz 	if (name) {
20499e9417d2Sbeveloper 		int len = strlen(name);
20509e9417d2Sbeveloper 		len = min_c(len, (int)sizeof(msg.name) - 1);
205152a38012Sejakowatz 		memcpy(msg.name, name, len);
205252a38012Sejakowatz 		msg.name[len] = 0;
205352a38012Sejakowatz 	}
205452a38012Sejakowatz 	msg.require_kinds = require_kinds;
205552a38012Sejakowatz 	msg.deny_kinds = deny_kinds;
205652a38012Sejakowatz 	msg.reply_port = _PortPool->GetPort();
205752a38012Sejakowatz 
205852a38012Sejakowatz 	rv = write_port(port, SERVER_GET_DORMANT_NODES, &msg, sizeof(msg));
205952a38012Sejakowatz 	if (rv != B_OK) {
206052a38012Sejakowatz 		_PortPool->PutPort(msg.reply_port);
206152a38012Sejakowatz 		return rv;
206252a38012Sejakowatz 	}
206352a38012Sejakowatz 
206452a38012Sejakowatz 	xfer_server_get_dormant_nodes_reply reply;
206552a38012Sejakowatz 	int32 code;
206652a38012Sejakowatz 
206752a38012Sejakowatz 	rv = read_port(msg.reply_port, &code, &reply, sizeof(reply));
206852a38012Sejakowatz 	if (rv < B_OK) {
206952a38012Sejakowatz 		_PortPool->PutPort(msg.reply_port);
207052a38012Sejakowatz 		return rv;
207152a38012Sejakowatz 	}
207252a38012Sejakowatz 
207352a38012Sejakowatz 	*io_count = reply.count;
207452a38012Sejakowatz 
207552a38012Sejakowatz 	if (*io_count > 0) {
207652a38012Sejakowatz 		rv = read_port(msg.reply_port, &code, out_info, *io_count * sizeof(dormant_node_info));
207752a38012Sejakowatz 		if (rv < B_OK)
207852a38012Sejakowatz 			reply.result = rv;
207952a38012Sejakowatz 	}
208052a38012Sejakowatz 	_PortPool->PutPort(msg.reply_port);
208152a38012Sejakowatz 
208252a38012Sejakowatz 	return reply.result;
208352a38012Sejakowatz }
208452a38012Sejakowatz 
20858b04ffc1Sbeveloper /* This function is used to do the real work of instantiating a dormant node. It is either
20868b04ffc1Sbeveloper  * called by the media_addon_server to instantiate a global node, or it gets called from
20878b04ffc1Sbeveloper  * BMediaRoster::InstantiateDormantNode() to create a local one.
20888b04ffc1Sbeveloper  *
20898b04ffc1Sbeveloper  * Checks concerning global/local are not done here.
20908b04ffc1Sbeveloper  */
209152a38012Sejakowatz status_t
209254187cc6Sbeveloper BMediaRosterEx::InstantiateDormantNode(media_addon_id addonid, int32 flavorid, team_id creator, media_node *out_node)
209352a38012Sejakowatz {
209454187cc6Sbeveloper 	// This function is always called from the correct context, if the node
209554187cc6Sbeveloper 	// is supposed to be global, it is called from the media_addon_server.
209654187cc6Sbeveloper 
209752a38012Sejakowatz 	// if B_FLAVOR_IS_GLOBAL, we need to use the BMediaAddOn object that
209852a38012Sejakowatz 	// resides in the media_addon_server
209952a38012Sejakowatz 
21008b04ffc1Sbeveloper 	// RegisterNode() must be called for nodes instantiated from add-ons,
21018b04ffc1Sbeveloper 	// since the media kit warrants that it's done automatically.
210252a38012Sejakowatz 
210354187cc6Sbeveloper 	// addonid		Indicates the ID number of the media add-on in which the node resides.
210454187cc6Sbeveloper 	// flavorid		Indicates the internal ID number that the add-on uses to identify the flavor,
210554187cc6Sbeveloper 	//				this is the number that was published by BMediaAddOn::GetFlavorAt() in the
21068b04ffc1Sbeveloper 	//				flavor_info::internal_id field.
210754187cc6Sbeveloper 	// creator		The creator team is -1 if nodes are created locally. If created globally,
210854187cc6Sbeveloper 	//				it will contain (while called in media_addon_server context) the team-id of
210954187cc6Sbeveloper 	// 				the team that requested the instantiation.
21108b04ffc1Sbeveloper 
211160f15390Sbeveloper 	TRACE("BMediaRosterEx::InstantiateDormantNode: addon-id %ld, flavor_id %ld\n", addonid, flavorid);
21128b04ffc1Sbeveloper 
21138b04ffc1Sbeveloper 	// Get flavor_info from the server
21148b04ffc1Sbeveloper 	dormant_flavor_info node_info;
21158c6a6096Sbeveloper 	status_t rv;
21168b04ffc1Sbeveloper 	rv = GetDormantFlavorInfo(addonid, flavorid, &node_info);
21178b04ffc1Sbeveloper 	if (rv != B_OK) {
21185ac4fbd7Sbeveloper 		ERROR("BMediaRosterEx::InstantiateDormantNode error: failed to get dormant_flavor_info for addon-id %ld, flavor-id %ld\n", addonid, flavorid);
211952a38012Sejakowatz 		return B_ERROR;
212052a38012Sejakowatz 	}
21218b04ffc1Sbeveloper 
2122908eaf85Sbeveloper 	//ASSERT(node_info.internal_id == flavorid);
2123908eaf85Sbeveloper 	if (node_info.internal_id != flavorid) {
21244d2d96e0Sbeveloper 		ERROR("############# BMediaRosterEx::InstantiateDormantNode failed: ID mismatch for addon-id %ld, flavor-id %ld, node_info.internal_id %ld, node_info.name %s\n", addonid, flavorid, node_info.internal_id, node_info.name);
2125908eaf85Sbeveloper 		return B_ERROR;
2126908eaf85Sbeveloper 	}
21278b04ffc1Sbeveloper 
21288b04ffc1Sbeveloper 	// load the BMediaAddOn object
21298b04ffc1Sbeveloper 	BMediaAddOn *addon;
21308b04ffc1Sbeveloper 	addon = _DormantNodeManager->GetAddon(addonid);
21318b04ffc1Sbeveloper 	if (!addon) {
21325ac4fbd7Sbeveloper 		ERROR("BMediaRosterEx::InstantiateDormantNode: GetAddon failed\n");
21338b04ffc1Sbeveloper 		return B_ERROR;
21348b04ffc1Sbeveloper 	}
21358b04ffc1Sbeveloper 
213654187cc6Sbeveloper 	// Now we need to try to increment the use count of this addon flavor
213754187cc6Sbeveloper 	// in the server. This can fail if the total number instances of this
213854187cc6Sbeveloper 	// flavor is limited.
213973794717Sbeveloper 	rv = IncrementAddonFlavorInstancesCount(addonid, flavorid);
214054187cc6Sbeveloper 	if (rv != B_OK) {
21415ac4fbd7Sbeveloper 		ERROR("BMediaRosterEx::InstantiateDormantNode error: can't create more nodes for addon-id %ld, flavor-id %ld\n", addonid, flavorid);
214254187cc6Sbeveloper 		// Put the addon back into the pool
214354187cc6Sbeveloper 		_DormantNodeManager->PutAddon(addonid);
214454187cc6Sbeveloper 		return B_ERROR;
214554187cc6Sbeveloper 	}
214654187cc6Sbeveloper 
21478b04ffc1Sbeveloper 	BMessage config;
214854187cc6Sbeveloper 	rv = LoadNodeConfiguration(addonid, flavorid, &config);
214954187cc6Sbeveloper 	if (rv != B_OK) {
21505ac4fbd7Sbeveloper 		ERROR("BMediaRosterEx::InstantiateDormantNode: couldn't load configuration for addon-id %ld, flavor-id %ld\n", addonid, flavorid);
215154187cc6Sbeveloper 		// do not return, this is a minor problem, not a reason to fail
215254187cc6Sbeveloper 	}
21538b04ffc1Sbeveloper 
21548b04ffc1Sbeveloper 	BMediaNode *node;
21558b04ffc1Sbeveloper 	status_t out_error;
21568b04ffc1Sbeveloper 
215754187cc6Sbeveloper 	out_error = B_OK;
21588b04ffc1Sbeveloper 	node = addon->InstantiateNodeFor(&node_info, &config, &out_error);
215916b7eea4Sbeveloper 	if (!node) {
21605ac4fbd7Sbeveloper 		ERROR("BMediaRosterEx::InstantiateDormantNode: InstantiateNodeFor failed\n");
216154187cc6Sbeveloper 		// Put the addon back into the pool
21628b04ffc1Sbeveloper 		_DormantNodeManager->PutAddon(addonid);
216354187cc6Sbeveloper 		// We must decrement the use count of this addon flavor in the
216454187cc6Sbeveloper 		// server to compensate the increment done in the beginning.
216573794717Sbeveloper 		rv = DecrementAddonFlavorInstancesCount(addonid, flavorid);
216654187cc6Sbeveloper 		if (rv != B_OK) {
21675ac4fbd7Sbeveloper 			ERROR("BMediaRosterEx::InstantiateDormantNode: DecrementAddonFlavorInstancesCount failed\n");
216816b7eea4Sbeveloper 		}
216954187cc6Sbeveloper 		return (out_error != B_OK) ? out_error : B_ERROR;
217054187cc6Sbeveloper 	}
217154187cc6Sbeveloper 
217254187cc6Sbeveloper 	rv = RegisterNode(node, addonid, flavorid);
21738c6a6096Sbeveloper 	if (rv != B_OK) {
21745ac4fbd7Sbeveloper 		ERROR("BMediaRosterEx::InstantiateDormantNode: RegisterNode failed\n");
21758c6a6096Sbeveloper 		delete node;
217654187cc6Sbeveloper 		// Put the addon back into the pool
21778b04ffc1Sbeveloper 		_DormantNodeManager->PutAddon(addonid);
217854187cc6Sbeveloper 		// We must decrement the use count of this addon flavor in the
217954187cc6Sbeveloper 		// server to compensate the increment done in the beginning.
218073794717Sbeveloper 		rv = DecrementAddonFlavorInstancesCount(addonid, flavorid);
218154187cc6Sbeveloper 		if (rv != B_OK) {
21825ac4fbd7Sbeveloper 			ERROR("BMediaRosterEx::InstantiateDormantNode: DecrementAddonFlavorInstancesCount failed\n");
218354187cc6Sbeveloper 		}
21848c6a6096Sbeveloper 		return B_ERROR;
21858c6a6096Sbeveloper 	}
21868c6a6096Sbeveloper 
218754187cc6Sbeveloper 	if (creator != -1) {
218854187cc6Sbeveloper 		// send a message to the server to assign team "creator" as creator of node "node->ID()"
218954187cc6Sbeveloper 		printf("!!! BMediaRosterEx::InstantiateDormantNode assigning team %ld as creator of node %ld\n", creator, node->ID());
219054187cc6Sbeveloper 		rv = MediaRosterEx(this)->SetNodeCreator(node->ID(), creator);
219154187cc6Sbeveloper 		if (rv != B_OK) {
21925ac4fbd7Sbeveloper 			ERROR("BMediaRosterEx::InstantiateDormantNode failed to assign team %ld as creator of node %ld\n", creator, node->ID());
219354187cc6Sbeveloper 			// do not return, this is a minor problem, not a reason to fail
219454187cc6Sbeveloper 		}
219554187cc6Sbeveloper 	}
219654187cc6Sbeveloper 
219754187cc6Sbeveloper 	// RegisterNode() does remember the add-on id in the server
219854187cc6Sbeveloper 	// and UnregisterNode() will call DormantNodeManager::PutAddon()
219954187cc6Sbeveloper 	// when the node is unregistered.
22008c6a6096Sbeveloper 
220116b7eea4Sbeveloper 	*out_node = node->Node();
2202cf4e2277Sbeveloper 
220360f15390Sbeveloper 	TRACE("BMediaRosterEx::InstantiateDormantNode: addon-id %ld, flavor_id %ld instanciated as node %ld, port %ld in team %ld\n", addonid, flavorid, out_node->node, out_node->port, team);
2204cf4e2277Sbeveloper 
220516b7eea4Sbeveloper 	return B_OK;
220616b7eea4Sbeveloper }
220752a38012Sejakowatz 
220852a38012Sejakowatz 
220952a38012Sejakowatz status_t
22108b04ffc1Sbeveloper BMediaRoster::InstantiateDormantNode(const dormant_node_info & in_info,
22118b04ffc1Sbeveloper 									 media_node * out_node,
22128b04ffc1Sbeveloper 									 uint32 flags /* currently 0 or B_FLAVOR_IS_GLOBAL or B_FLAVOR_IS_LOCAL */ )
22138b04ffc1Sbeveloper {
22148b04ffc1Sbeveloper 	CALLED();
22158b04ffc1Sbeveloper 	if (out_node == 0)
22168b04ffc1Sbeveloper 		return B_BAD_VALUE;
22178b04ffc1Sbeveloper 	if (in_info.addon <= 0) {
22185ac4fbd7Sbeveloper 		ERROR("BMediaRoster::InstantiateDormantNode error: addon-id %ld invalid.\n", in_info.addon);
22198b04ffc1Sbeveloper 		return B_BAD_VALUE;
22208b04ffc1Sbeveloper 	}
22218b04ffc1Sbeveloper 
2222d91580cdSbeveloper 	printf("BMediaRoster::InstantiateDormantNode: addon-id %ld, flavor_id %ld, flags 0x%lX\n", in_info.addon, in_info.flavor_id, flags);
22238b04ffc1Sbeveloper 
22248b04ffc1Sbeveloper 	// Get flavor_info from the server
22258b04ffc1Sbeveloper 	// XXX this is a little overhead, as we get the full blown dormant_flavor_info,
22268b04ffc1Sbeveloper 	// XXX but only need the flags.
22278b04ffc1Sbeveloper 	dormant_flavor_info node_info;
22288b04ffc1Sbeveloper 	status_t rv;
22298b04ffc1Sbeveloper 	rv = MediaRosterEx(this)->GetDormantFlavorInfo(in_info.addon, in_info.flavor_id, &node_info);
22308b04ffc1Sbeveloper 	if (rv != B_OK) {
22315ac4fbd7Sbeveloper 		ERROR("BMediaRoster::InstantiateDormantNode: failed to get dormant_flavor_info for addon-id %ld, flavor-id %ld\n", in_info.addon, in_info.flavor_id);
2232626824eaSbeveloper 		return B_NAME_NOT_FOUND;
22338b04ffc1Sbeveloper 	}
22348b04ffc1Sbeveloper 
22358b04ffc1Sbeveloper 	ASSERT(node_info.internal_id == in_info.flavor_id);
22368b04ffc1Sbeveloper 
2237d91580cdSbeveloper 	printf("BMediaRoster::InstantiateDormantNode: name \"%s\", info \"%s\", flavor_flags 0x%lX, internal_id %ld, possible_count %ld\n",
22388b04ffc1Sbeveloper 		node_info.name, node_info.info, node_info.flavor_flags, node_info.internal_id, node_info.possible_count);
22398b04ffc1Sbeveloper 
22408b04ffc1Sbeveloper 	#if DEBUG
22418b04ffc1Sbeveloper 		if (flags & B_FLAVOR_IS_LOCAL)
22428b04ffc1Sbeveloper 			printf("BMediaRoster::InstantiateDormantNode: caller requested B_FLAVOR_IS_LOCAL\n");
22438b04ffc1Sbeveloper 		if (flags & B_FLAVOR_IS_GLOBAL)
22448b04ffc1Sbeveloper 			printf("BMediaRoster::InstantiateDormantNode: caller requested B_FLAVOR_IS_GLOBAL\n");
22458b04ffc1Sbeveloper 		if (node_info.flavor_flags & B_FLAVOR_IS_LOCAL)
22468b04ffc1Sbeveloper 			printf("BMediaRoster::InstantiateDormantNode: node requires B_FLAVOR_IS_LOCAL\n");
22478b04ffc1Sbeveloper 		if (node_info.flavor_flags & B_FLAVOR_IS_GLOBAL)
22488b04ffc1Sbeveloper 			printf("BMediaRoster::InstantiateDormantNode: node requires B_FLAVOR_IS_GLOBAL\n");
22498b04ffc1Sbeveloper 	#endif
22508b04ffc1Sbeveloper 
22518b04ffc1Sbeveloper 	// Make sure that flags demanded by the dormant node and those requested
22528b04ffc1Sbeveloper 	// by the caller are not incompatible.
22538b04ffc1Sbeveloper 	if ((node_info.flavor_flags & B_FLAVOR_IS_GLOBAL) && (flags & B_FLAVOR_IS_LOCAL)) {
22545ac4fbd7Sbeveloper 		ERROR("BMediaRoster::InstantiateDormantNode: requested B_FLAVOR_IS_LOCAL, but dormant node has B_FLAVOR_IS_GLOBAL\n");
2255626824eaSbeveloper 		return B_NAME_NOT_FOUND;
22568b04ffc1Sbeveloper 	}
22578b04ffc1Sbeveloper 	if ((node_info.flavor_flags & B_FLAVOR_IS_LOCAL) && (flags & B_FLAVOR_IS_GLOBAL)) {
22585ac4fbd7Sbeveloper 		ERROR("BMediaRoster::InstantiateDormantNode: requested B_FLAVOR_IS_GLOBAL, but dormant node has B_FLAVOR_IS_LOCAL\n");
2259626824eaSbeveloper 		return B_NAME_NOT_FOUND;
22608b04ffc1Sbeveloper 	}
226154187cc6Sbeveloper 
22628b04ffc1Sbeveloper 	// If either the node, or the caller requested to make the instance global
22638b04ffc1Sbeveloper 	// we will do it by forwarding this request into the media_addon_server, which
22648b04ffc1Sbeveloper 	// in turn will call BMediaRosterEx::InstantiateDormantNode to create the node
22658b04ffc1Sbeveloper 	// there and make it globally available.
22668b04ffc1Sbeveloper 	if ((node_info.flavor_flags & B_FLAVOR_IS_GLOBAL) || (flags & B_FLAVOR_IS_GLOBAL)) {
22678b04ffc1Sbeveloper 
2268cf4e2277Sbeveloper 		printf("BMediaRoster::InstantiateDormantNode: creating global object in media_addon_server\n");
2269cf4e2277Sbeveloper 
22708b04ffc1Sbeveloper 		addonserver_instantiate_dormant_node_request request;
22718b04ffc1Sbeveloper 		addonserver_instantiate_dormant_node_reply reply;
22728b04ffc1Sbeveloper 		request.addonid = in_info.addon;
22738b04ffc1Sbeveloper 		request.flavorid = in_info.flavor_id;
227454187cc6Sbeveloper 		request.creator_team = team; // creator team is allowed to also release global nodes
22758b04ffc1Sbeveloper 		rv = QueryAddonServer(ADDONSERVER_INSTANTIATE_DORMANT_NODE, &request, sizeof(request), &reply, sizeof(reply));
22768b04ffc1Sbeveloper 		if (rv == B_OK) {
22778b04ffc1Sbeveloper 			*out_node = reply.node;
22788b04ffc1Sbeveloper 		}
22798b04ffc1Sbeveloper 
22808b04ffc1Sbeveloper 	} else {
22818b04ffc1Sbeveloper 
228254187cc6Sbeveloper 		// creator team = -1, as this is a local node
2283626824eaSbeveloper 		rv = MediaRosterEx(this)->InstantiateDormantNode(in_info.addon, in_info.flavor_id, -1, out_node);
2284626824eaSbeveloper 
22858b04ffc1Sbeveloper 	}
2286626824eaSbeveloper 	if (rv != B_OK) {
2287626824eaSbeveloper 		*out_node = media_node::null;
2288626824eaSbeveloper 		return B_NAME_NOT_FOUND;
2289626824eaSbeveloper 	}
2290626824eaSbeveloper 	return B_OK;
22918b04ffc1Sbeveloper }
22928b04ffc1Sbeveloper 
22938b04ffc1Sbeveloper 
22948b04ffc1Sbeveloper status_t
22958b04ffc1Sbeveloper BMediaRoster::InstantiateDormantNode(const dormant_node_info & in_info,
22968b04ffc1Sbeveloper 									 media_node * out_node)
22978b04ffc1Sbeveloper {
22988b04ffc1Sbeveloper 	return InstantiateDormantNode(in_info, out_node, 0);
22998b04ffc1Sbeveloper }
23008b04ffc1Sbeveloper 
23018b04ffc1Sbeveloper 
23028b04ffc1Sbeveloper status_t
230352a38012Sejakowatz BMediaRoster::GetDormantNodeFor(const media_node & node,
230452a38012Sejakowatz 								dormant_node_info * out_info)
230552a38012Sejakowatz {
230685dfab2bSbeveloper 	CALLED();
230785dfab2bSbeveloper 	if (out_info == NULL)
230885dfab2bSbeveloper 		return B_BAD_VALUE;
230940f36b03Sbeveloper 	if (IS_INVALID_NODE(node))
231085dfab2bSbeveloper 		return B_MEDIA_BAD_NODE;
231152a38012Sejakowatz 
231285dfab2bSbeveloper 	server_get_dormant_node_for_request request;
231385dfab2bSbeveloper 	server_get_dormant_node_for_reply reply;
231485dfab2bSbeveloper 	status_t rv;
231585dfab2bSbeveloper 
231685dfab2bSbeveloper 	request.node = node;
231785dfab2bSbeveloper 
23181299bfb2Sbeveloper 	rv = QueryServer(SERVER_GET_DORMANT_NODE_FOR, &request, sizeof(request), &reply, sizeof(reply));
231985dfab2bSbeveloper 	if (rv != B_OK)
232085dfab2bSbeveloper 		return rv;
232185dfab2bSbeveloper 
232285dfab2bSbeveloper 	*out_info = reply.node_info;
232385dfab2bSbeveloper 	return B_OK;
232452a38012Sejakowatz }
232552a38012Sejakowatz 
232652a38012Sejakowatz status_t
23278b04ffc1Sbeveloper BMediaRosterEx::GetDormantFlavorInfo(media_addon_id addonid,
23288b04ffc1Sbeveloper 									  int32 flavorid,
232952a38012Sejakowatz 									  dormant_flavor_info * out_flavor)
233052a38012Sejakowatz {
233152a38012Sejakowatz 	CALLED();
23329bedd42cSbeveloper 	if (out_flavor == NULL)
23339bedd42cSbeveloper 		return B_BAD_VALUE;
233452a38012Sejakowatz 
233552a38012Sejakowatz 	xfer_server_get_dormant_flavor_info msg;
233652a38012Sejakowatz 	xfer_server_get_dormant_flavor_info_reply *reply;
233752a38012Sejakowatz 	port_id port;
233852a38012Sejakowatz 	status_t rv;
233952a38012Sejakowatz 	int32 code;
234052a38012Sejakowatz 
23414295907bSbeveloper 	port = find_port(MEDIA_SERVER_PORT_NAME);
234252a38012Sejakowatz 	if (port <= B_OK)
234352a38012Sejakowatz 		return B_ERROR;
234452a38012Sejakowatz 
234552a38012Sejakowatz 	reply = (xfer_server_get_dormant_flavor_info_reply *) malloc(16000);
234652a38012Sejakowatz 	if (reply == 0)
234752a38012Sejakowatz 		return B_ERROR;
234852a38012Sejakowatz 
23498b04ffc1Sbeveloper 	msg.addon 		= addonid;
23508b04ffc1Sbeveloper 	msg.flavor_id 	= flavorid;
235152a38012Sejakowatz 	msg.reply_port 	= _PortPool->GetPort();
235252a38012Sejakowatz 	rv = write_port(port, SERVER_GET_DORMANT_FLAVOR_INFO, &msg, sizeof(msg));
235352a38012Sejakowatz 	if (rv != B_OK) {
235452a38012Sejakowatz 		free(reply);
235552a38012Sejakowatz 		_PortPool->PutPort(msg.reply_port);
235652a38012Sejakowatz 		return rv;
235752a38012Sejakowatz 	}
235852a38012Sejakowatz 	rv = read_port(msg.reply_port, &code, reply, 16000);
235952a38012Sejakowatz 	_PortPool->PutPort(msg.reply_port);
236052a38012Sejakowatz 
236152a38012Sejakowatz 	if (rv < B_OK) {
236252a38012Sejakowatz 		free(reply);
236352a38012Sejakowatz 		return rv;
236452a38012Sejakowatz 	}
236552a38012Sejakowatz 
236652a38012Sejakowatz 	if (reply->result == B_OK)
236752a38012Sejakowatz 		rv = out_flavor->Unflatten(reply->dfi_type, &reply->dfi, reply->dfi_size);
236852a38012Sejakowatz 	else
236952a38012Sejakowatz 		rv = reply->result;
237052a38012Sejakowatz 
237152a38012Sejakowatz 	free(reply);
237252a38012Sejakowatz 	return rv;
237352a38012Sejakowatz }
237452a38012Sejakowatz 
23758b04ffc1Sbeveloper status_t
23768b04ffc1Sbeveloper BMediaRoster::GetDormantFlavorInfoFor(const dormant_node_info & in_dormant,
23778b04ffc1Sbeveloper 									  dormant_flavor_info * out_flavor)
23788b04ffc1Sbeveloper {
23798b04ffc1Sbeveloper 	return MediaRosterEx(this)->GetDormantFlavorInfo(in_dormant.addon, in_dormant.flavor_id, out_flavor);
23808b04ffc1Sbeveloper }
238152a38012Sejakowatz 
238260f15390Sbeveloper // Reports in outLatency the maximum latency found downstream from
238360f15390Sbeveloper // the specified BBufferProducer, producer, given the current connections.
238452a38012Sejakowatz status_t
238552a38012Sejakowatz BMediaRoster::GetLatencyFor(const media_node & producer,
238652a38012Sejakowatz 							bigtime_t * out_latency)
238752a38012Sejakowatz {
238860f15390Sbeveloper 	CALLED();
238960f15390Sbeveloper 	if (out_latency == NULL)
239060f15390Sbeveloper 		return B_BAD_VALUE;
239160f15390Sbeveloper 	if (IS_INVALID_NODE(producer))
239260f15390Sbeveloper 		return B_MEDIA_BAD_NODE;
239360f15390Sbeveloper 	if ((producer.kind & B_BUFFER_PRODUCER) == 0)
239460f15390Sbeveloper 		return B_MEDIA_BAD_NODE;
239560f15390Sbeveloper 
239660f15390Sbeveloper 	producer_get_latency_request request;
239760f15390Sbeveloper 	producer_get_latency_reply reply;
239860f15390Sbeveloper 	status_t rv;
239960f15390Sbeveloper 
240060f15390Sbeveloper 	rv = QueryPort(producer.port, PRODUCER_GET_LATENCY, &request, sizeof(request), &reply, sizeof(reply));
240160f15390Sbeveloper 	if (rv != B_OK)
240260f15390Sbeveloper 		return rv;
240360f15390Sbeveloper 
240460f15390Sbeveloper 	*out_latency = reply.latency;
240560f15390Sbeveloper 
240660f15390Sbeveloper 	printf("BMediaRoster::GetLatencyFor producer %ld has maximum latency %Ld\n", producer.node, *out_latency);
2407aac800c2Sbeveloper 	return B_OK;
240852a38012Sejakowatz }
240952a38012Sejakowatz 
241052a38012Sejakowatz 
241152a38012Sejakowatz status_t
241252a38012Sejakowatz BMediaRoster::GetInitialLatencyFor(const media_node & producer,
241352a38012Sejakowatz 								   bigtime_t * out_latency,
2414aac800c2Sbeveloper 								   uint32 * out_flags /* = NULL */)
241552a38012Sejakowatz {
2416b65a0ac5SJérôme Duval 	CALLED();
2417b65a0ac5SJérôme Duval 	if (out_latency == NULL)
2418b65a0ac5SJérôme Duval 		return B_BAD_VALUE;
2419b65a0ac5SJérôme Duval 	if (IS_INVALID_NODE(producer))
2420b65a0ac5SJérôme Duval 		return B_MEDIA_BAD_NODE;
2421b65a0ac5SJérôme Duval 	if ((producer.kind & B_BUFFER_PRODUCER) == 0)
2422b65a0ac5SJérôme Duval 		return B_MEDIA_BAD_NODE;
2423b65a0ac5SJérôme Duval 
2424b65a0ac5SJérôme Duval 	producer_get_initial_latency_request request;
2425b65a0ac5SJérôme Duval 	producer_get_initial_latency_reply reply;
2426b65a0ac5SJérôme Duval 	status_t rv;
2427b65a0ac5SJérôme Duval 
2428b65a0ac5SJérôme Duval 	rv = QueryPort(producer.port, PRODUCER_GET_INITIAL_LATENCY, &request, sizeof(request), &reply, sizeof(reply));
2429b65a0ac5SJérôme Duval 	if (rv != B_OK)
2430b65a0ac5SJérôme Duval 		return rv;
2431b65a0ac5SJérôme Duval 
2432b65a0ac5SJérôme Duval 	*out_latency = reply.initial_latency;
2433aac800c2Sbeveloper 	if (out_flags)
2434b65a0ac5SJérôme Duval 		*out_flags = reply.flags;
2435b65a0ac5SJérôme Duval 
2436b65a0ac5SJérôme Duval 	printf("BMediaRoster::GetInitialLatencyFor producer %ld has maximum initial latency %Ld\n", producer.node, *out_latency);
2437aac800c2Sbeveloper 	return B_OK;
243852a38012Sejakowatz }
243952a38012Sejakowatz 
244052a38012Sejakowatz 
244152a38012Sejakowatz status_t
244252a38012Sejakowatz BMediaRoster::GetStartLatencyFor(const media_node & time_source,
244352a38012Sejakowatz 								 bigtime_t * out_latency)
244452a38012Sejakowatz {
2445fc8b28b6SJérôme Duval 	CALLED();
2446fc8b28b6SJérôme Duval 	if (out_latency == NULL)
2447fc8b28b6SJérôme Duval 		return B_BAD_VALUE;
2448fc8b28b6SJérôme Duval 	if (IS_INVALID_NODE(time_source))
2449fc8b28b6SJérôme Duval 		return B_MEDIA_BAD_NODE;
2450fc8b28b6SJérôme Duval 	if ((time_source.kind & B_TIME_SOURCE) == 0)
2451fc8b28b6SJérôme Duval 		return B_MEDIA_BAD_NODE;
2452fc8b28b6SJérôme Duval 
2453fc8b28b6SJérôme Duval 	timesource_get_start_latency_request request;
2454fc8b28b6SJérôme Duval 	timesource_get_start_latency_reply reply;
2455fc8b28b6SJérôme Duval 	status_t rv;
2456fc8b28b6SJérôme Duval 
2457fc8b28b6SJérôme Duval 	rv = QueryPort(time_source.port, TIMESOURCE_GET_START_LATENCY, &request, sizeof(request), &reply, sizeof(reply));
2458fc8b28b6SJérôme Duval 	if (rv != B_OK)
2459fc8b28b6SJérôme Duval 		return rv;
2460fc8b28b6SJérôme Duval 
2461fc8b28b6SJérôme Duval 	*out_latency = reply.start_latency;
2462fc8b28b6SJérôme Duval 
2463fc8b28b6SJérôme Duval 	printf("BMediaRoster::GetStartLatencyFor timesource %ld has maximum initial latency %Ld\n", time_source.node, *out_latency);
2464aac800c2Sbeveloper 	return B_OK;
246552a38012Sejakowatz }
246652a38012Sejakowatz 
246752a38012Sejakowatz 
246852a38012Sejakowatz status_t
246952a38012Sejakowatz BMediaRoster::GetFileFormatsFor(const media_node & file_interface,
247052a38012Sejakowatz 								media_file_format * out_formats,
247152a38012Sejakowatz 								int32 * io_num_infos)
247252a38012Sejakowatz {
247352a38012Sejakowatz 	UNIMPLEMENTED();
247452a38012Sejakowatz 	return B_ERROR;
247552a38012Sejakowatz }
247652a38012Sejakowatz 
247752a38012Sejakowatz 
247852a38012Sejakowatz status_t
247952a38012Sejakowatz BMediaRoster::SetRefFor(const media_node & file_interface,
248052a38012Sejakowatz 						const entry_ref & file,
248152a38012Sejakowatz 						bool create_and_truncate,
248252a38012Sejakowatz 						bigtime_t * out_length)	/* if create is false */
248352a38012Sejakowatz {
248452a38012Sejakowatz 	UNIMPLEMENTED();
248552a38012Sejakowatz 	return B_ERROR;
248652a38012Sejakowatz }
248752a38012Sejakowatz 
248852a38012Sejakowatz 
248952a38012Sejakowatz status_t
249052a38012Sejakowatz BMediaRoster::GetRefFor(const media_node & node,
249152a38012Sejakowatz 						entry_ref * out_file,
249252a38012Sejakowatz 						BMimeType * mime_type)
249352a38012Sejakowatz {
249452a38012Sejakowatz 	UNIMPLEMENTED();
249552a38012Sejakowatz 	return B_ERROR;
249652a38012Sejakowatz }
249752a38012Sejakowatz 
249852a38012Sejakowatz 
249952a38012Sejakowatz status_t
250052a38012Sejakowatz BMediaRoster::SniffRefFor(const media_node & file_interface,
250152a38012Sejakowatz 						  const entry_ref & file,
250252a38012Sejakowatz 						  BMimeType * mime_type,
250352a38012Sejakowatz 						  float * out_capability)
250452a38012Sejakowatz {
250552a38012Sejakowatz 	UNIMPLEMENTED();
250652a38012Sejakowatz 	return B_ERROR;
250752a38012Sejakowatz }
250852a38012Sejakowatz 
250952a38012Sejakowatz 
251052a38012Sejakowatz /* This is the generic "here's a file, now can someone please play it" interface */
251152a38012Sejakowatz status_t
251252a38012Sejakowatz BMediaRoster::SniffRef(const entry_ref & file,
251352a38012Sejakowatz 					   uint64 require_node_kinds,		/* if you need an EntityInterface or BufferConsumer or something */
251452a38012Sejakowatz 					   dormant_node_info * out_node,
251552a38012Sejakowatz 					   BMimeType * mime_type)
251652a38012Sejakowatz {
251752a38012Sejakowatz 	UNIMPLEMENTED();
251852a38012Sejakowatz 	return B_ERROR;
251952a38012Sejakowatz }
252052a38012Sejakowatz 
252152a38012Sejakowatz 
252252a38012Sejakowatz status_t
252352a38012Sejakowatz BMediaRoster::GetDormantNodeForType(const BMimeType & type,
252452a38012Sejakowatz 									uint64 require_node_kinds,
252552a38012Sejakowatz 									dormant_node_info * out_node)
252652a38012Sejakowatz {
252752a38012Sejakowatz 	UNIMPLEMENTED();
252852a38012Sejakowatz 	return B_ERROR;
252952a38012Sejakowatz }
253052a38012Sejakowatz 
253152a38012Sejakowatz 
253252a38012Sejakowatz status_t
253352a38012Sejakowatz BMediaRoster::GetReadFileFormatsFor(const dormant_node_info & in_node,
253452a38012Sejakowatz 									media_file_format * out_read_formats,
253552a38012Sejakowatz 									int32 in_read_count,
253652a38012Sejakowatz 									int32 * out_read_count)
253752a38012Sejakowatz {
253852a38012Sejakowatz 	UNIMPLEMENTED();
253952a38012Sejakowatz 	return B_ERROR;
254052a38012Sejakowatz }
254152a38012Sejakowatz 
254252a38012Sejakowatz 
254352a38012Sejakowatz status_t
254452a38012Sejakowatz BMediaRoster::GetWriteFileFormatsFor(const dormant_node_info & in_node,
254552a38012Sejakowatz 									 media_file_format * out_write_formats,
254652a38012Sejakowatz 									 int32 in_write_count,
254752a38012Sejakowatz 									 int32 * out_write_count)
254852a38012Sejakowatz {
254952a38012Sejakowatz 	UNIMPLEMENTED();
255052a38012Sejakowatz 	return B_ERROR;
255152a38012Sejakowatz }
255252a38012Sejakowatz 
255352a38012Sejakowatz 
255452a38012Sejakowatz status_t
255552a38012Sejakowatz BMediaRoster::GetFormatFor(const media_output & output,
255652a38012Sejakowatz 						   media_format * io_format,
255752a38012Sejakowatz 						   uint32 flags)
255852a38012Sejakowatz {
25599bedd42cSbeveloper 	CALLED();
25609bedd42cSbeveloper 	if (io_format == NULL)
25619bedd42cSbeveloper 		return B_BAD_VALUE;
25629bedd42cSbeveloper 	if ((output.node.kind & B_BUFFER_PRODUCER) == 0)
25639bedd42cSbeveloper 		return B_MEDIA_BAD_NODE;
25649bedd42cSbeveloper 	if (IS_INVALID_SOURCE(output.source))
25659bedd42cSbeveloper 		return B_MEDIA_BAD_SOURCE;
25669bedd42cSbeveloper 
25679bedd42cSbeveloper 	producer_format_suggestion_requested_request request;
25689bedd42cSbeveloper 	producer_format_suggestion_requested_reply reply;
25699bedd42cSbeveloper 	status_t rv;
25709bedd42cSbeveloper 
25719bedd42cSbeveloper 	request.type = B_MEDIA_UNKNOWN_TYPE;
25729bedd42cSbeveloper 	request.quality = 0; // XXX what should this be?
25739bedd42cSbeveloper 
25749bedd42cSbeveloper 	rv = QueryPort(output.source.port, PRODUCER_FORMAT_SUGGESTION_REQUESTED, &request, sizeof(request), &reply, sizeof(reply));
25759bedd42cSbeveloper 	if (rv != B_OK)
25769bedd42cSbeveloper 		return rv;
25779bedd42cSbeveloper 
25789bedd42cSbeveloper 	*io_format = reply.format;
25799bedd42cSbeveloper 	return B_OK;
258052a38012Sejakowatz }
258152a38012Sejakowatz 
258252a38012Sejakowatz 
258352a38012Sejakowatz status_t
258452a38012Sejakowatz BMediaRoster::GetFormatFor(const media_input & input,
258552a38012Sejakowatz 						   media_format * io_format,
258652a38012Sejakowatz 						   uint32 flags)
258752a38012Sejakowatz {
25889bedd42cSbeveloper 	CALLED();
25899bedd42cSbeveloper 	if (io_format == NULL)
25909bedd42cSbeveloper 		return B_BAD_VALUE;
25919bedd42cSbeveloper 	if ((input.node.kind & B_BUFFER_CONSUMER) == 0)
25929bedd42cSbeveloper 		return B_MEDIA_BAD_NODE;
25939bedd42cSbeveloper 	if (IS_INVALID_DESTINATION(input.destination))
25949bedd42cSbeveloper 		return B_MEDIA_BAD_DESTINATION;
25959bedd42cSbeveloper 
25969bedd42cSbeveloper 	consumer_accept_format_request request;
25979bedd42cSbeveloper 	consumer_accept_format_reply reply;
25989bedd42cSbeveloper 	status_t rv;
25999bedd42cSbeveloper 
26009bedd42cSbeveloper 	request.dest = input.destination;
26019bedd42cSbeveloper 	memset(&request.format, 0, sizeof(request.format)); // wildcard
26029bedd42cSbeveloper 
26039bedd42cSbeveloper 	rv = QueryPort(input.destination.port, CONSUMER_ACCEPT_FORMAT, &request, sizeof(request), &reply, sizeof(reply));
26049bedd42cSbeveloper 	if (rv != B_OK)
26059bedd42cSbeveloper 		return rv;
26069bedd42cSbeveloper 
26079bedd42cSbeveloper 	*io_format = reply.format;
26089bedd42cSbeveloper 	return B_OK;
260952a38012Sejakowatz }
261052a38012Sejakowatz 
261152a38012Sejakowatz 
261252a38012Sejakowatz status_t
261352a38012Sejakowatz BMediaRoster::GetFormatFor(const media_node & node,
261452a38012Sejakowatz 						   media_format * io_format,
261552a38012Sejakowatz 						   float quality)
261652a38012Sejakowatz {
261752a38012Sejakowatz 	UNIMPLEMENTED();
26189bedd42cSbeveloper 	if (io_format == NULL)
26199bedd42cSbeveloper 		return B_BAD_VALUE;
26209bedd42cSbeveloper 	if (IS_INVALID_NODE(node))
26219bedd42cSbeveloper 		return B_MEDIA_BAD_NODE;
26229bedd42cSbeveloper 	if ((node.kind & (B_BUFFER_CONSUMER | B_BUFFER_PRODUCER)) == 0)
26239bedd42cSbeveloper 		return B_MEDIA_BAD_NODE;
26249bedd42cSbeveloper 
26259bedd42cSbeveloper 
262652a38012Sejakowatz 	return B_ERROR;
262752a38012Sejakowatz }
262852a38012Sejakowatz 
262952a38012Sejakowatz 
263052a38012Sejakowatz ssize_t
263152a38012Sejakowatz BMediaRoster::GetNodeAttributesFor(const media_node & node,
263252a38012Sejakowatz 								   media_node_attribute * outArray,
263352a38012Sejakowatz 								   size_t inMaxCount)
263452a38012Sejakowatz {
263552a38012Sejakowatz 	UNIMPLEMENTED();
263652a38012Sejakowatz 	return B_ERROR;
263752a38012Sejakowatz }
263852a38012Sejakowatz 
263952a38012Sejakowatz 
264052a38012Sejakowatz media_node_id
264152a38012Sejakowatz BMediaRoster::NodeIDFor(port_id source_or_destination_port)
264252a38012Sejakowatz {
26439e9417d2Sbeveloper 	CALLED();
26449e9417d2Sbeveloper 
26459e9417d2Sbeveloper 	server_node_id_for_request request;
26469e9417d2Sbeveloper 	server_node_id_for_reply reply;
26479e9417d2Sbeveloper 	status_t rv;
26489e9417d2Sbeveloper 
26499e9417d2Sbeveloper 	request.port = source_or_destination_port;
26509e9417d2Sbeveloper 
26519e9417d2Sbeveloper 	rv = QueryServer(SERVER_NODE_ID_FOR, &request, sizeof(request), &reply, sizeof(reply));
26529e9417d2Sbeveloper 	if (rv != B_OK) {
26535ac4fbd7Sbeveloper 		ERROR("BMediaRoster::NodeIDFor: failed (error %#lx)\n", rv);
26549e9417d2Sbeveloper 		return -1;
26559e9417d2Sbeveloper 	}
26569e9417d2Sbeveloper 
26579e9417d2Sbeveloper 	return reply.nodeid;
265852a38012Sejakowatz }
265952a38012Sejakowatz 
266052a38012Sejakowatz 
266152a38012Sejakowatz status_t
266252a38012Sejakowatz BMediaRoster::GetInstancesFor(media_addon_id addon,
266352a38012Sejakowatz 							  int32 flavor,
266452a38012Sejakowatz 							  media_node_id * out_id,
266552a38012Sejakowatz 							  int32 * io_count)
266652a38012Sejakowatz {
266785dfab2bSbeveloper 	CALLED();
26688b9700adSJérôme Duval 	if (out_id == NULL)
266985dfab2bSbeveloper 		return B_BAD_VALUE;
26708b9700adSJérôme Duval 	if (io_count && *io_count <= 0)
267185dfab2bSbeveloper 		return B_BAD_VALUE;
267285dfab2bSbeveloper 
267385dfab2bSbeveloper 	server_get_instances_for_request request;
267485dfab2bSbeveloper 	server_get_instances_for_reply reply;
267585dfab2bSbeveloper 	status_t rv;
267685dfab2bSbeveloper 
26778b9700adSJérôme Duval 	request.maxcount = (io_count ? *io_count : 1);
267885dfab2bSbeveloper 	request.addon_id = addon;
267985dfab2bSbeveloper 	request.addon_flavor_id = flavor;
268085dfab2bSbeveloper 
268185dfab2bSbeveloper 	rv = QueryServer(SERVER_GET_INSTANCES_FOR, &request, sizeof(request), &reply, sizeof(reply));
268285dfab2bSbeveloper 	if (rv != B_OK) {
26835ac4fbd7Sbeveloper 		ERROR("BMediaRoster::GetLiveNodes failed\n");
268485dfab2bSbeveloper 		return rv;
268552a38012Sejakowatz 	}
268652a38012Sejakowatz 
26878b9700adSJérôme Duval 	if(io_count)
268885dfab2bSbeveloper 		*io_count = reply.count;
268985dfab2bSbeveloper 	if (reply.count > 0)
269085dfab2bSbeveloper 		memcpy(out_id, reply.node_id, sizeof(media_node_id) * reply.count);
269185dfab2bSbeveloper 
269285dfab2bSbeveloper 	return B_OK;
269385dfab2bSbeveloper }
269452a38012Sejakowatz 
269552a38012Sejakowatz 
269652a38012Sejakowatz status_t
269752a38012Sejakowatz BMediaRoster::SetRealtimeFlags(uint32 in_enabled)
269852a38012Sejakowatz {
269952a38012Sejakowatz 	UNIMPLEMENTED();
270052a38012Sejakowatz 	return B_ERROR;
270152a38012Sejakowatz }
270252a38012Sejakowatz 
270352a38012Sejakowatz 
270452a38012Sejakowatz status_t
270552a38012Sejakowatz BMediaRoster::GetRealtimeFlags(uint32 * out_enabled)
270652a38012Sejakowatz {
270752a38012Sejakowatz 	UNIMPLEMENTED();
270852a38012Sejakowatz 	return B_ERROR;
270952a38012Sejakowatz }
271052a38012Sejakowatz 
271152a38012Sejakowatz 
271252a38012Sejakowatz ssize_t
271352a38012Sejakowatz BMediaRoster::AudioBufferSizeFor(int32 channel_count,
271452a38012Sejakowatz 								 uint32 sample_format,
271552a38012Sejakowatz 								 float frame_rate,
271652a38012Sejakowatz 								 bus_type bus_kind)
271752a38012Sejakowatz {
2718df6c2e83Sbeveloper 	bigtime_t buffer_duration;
2719df6c2e83Sbeveloper 	ssize_t buffer_size;
2720df6c2e83Sbeveloper 
2721df6c2e83Sbeveloper 	system_info info;
2722df6c2e83Sbeveloper 	get_system_info(&info);
2723df6c2e83Sbeveloper 
2724df6c2e83Sbeveloper 	if (info.cpu_clock_speed > 2000000000)
2725df6c2e83Sbeveloper 		buffer_duration = 2500;
2726df6c2e83Sbeveloper 	else if (info.cpu_clock_speed > 1000000000)
2727df6c2e83Sbeveloper 		buffer_duration = 5000;
2728df6c2e83Sbeveloper 	else if (info.cpu_clock_speed > 600000000)
2729df6c2e83Sbeveloper 		buffer_duration = 10000;
2730df6c2e83Sbeveloper 	else if (info.cpu_clock_speed > 200000000)
2731df6c2e83Sbeveloper 		buffer_duration = 20000;
2732df6c2e83Sbeveloper 	else if (info.cpu_clock_speed > 100000000)
2733df6c2e83Sbeveloper 		buffer_duration = 30000;
2734df6c2e83Sbeveloper 	else
2735df6c2e83Sbeveloper 		buffer_duration = 50000;
2736df6c2e83Sbeveloper 
2737df6c2e83Sbeveloper 	if ((bus_kind == B_ISA_BUS || bus_kind == B_PCMCIA_BUS) && buffer_duration < 25000)
2738df6c2e83Sbeveloper 		buffer_duration = 25000;
2739df6c2e83Sbeveloper 
2740df6c2e83Sbeveloper 	buffer_size = (sample_format & 0xf) * channel_count * (ssize_t)((frame_rate * buffer_duration) / 1000000.0);
2741df6c2e83Sbeveloper 
2742df6c2e83Sbeveloper 	printf("Suggested buffer duration %Ld, size %ld\n", buffer_duration, buffer_size);
2743df6c2e83Sbeveloper 
2744df6c2e83Sbeveloper 	return buffer_size;
274552a38012Sejakowatz }
274652a38012Sejakowatz 
274752a38012Sejakowatz 
274852a38012Sejakowatz /* Use MediaFlags to inquire about specific features of the Media Kit. */
274952a38012Sejakowatz /* Returns < 0 for "not present", positive size for output data size. */
275052a38012Sejakowatz /* 0 means that the capability is present, but no data about it. */
275152a38012Sejakowatz /* static */ ssize_t
275252a38012Sejakowatz BMediaRoster::MediaFlags(media_flags cap,
275352a38012Sejakowatz 						 void * buf,
275452a38012Sejakowatz 						 size_t maxSize)
275552a38012Sejakowatz {
275652a38012Sejakowatz 	UNIMPLEMENTED();
275752a38012Sejakowatz 	return 0;
275852a38012Sejakowatz }
275952a38012Sejakowatz 
276052a38012Sejakowatz 
276152a38012Sejakowatz /* BLooper overrides */
276252a38012Sejakowatz /* virtual */ void
276352a38012Sejakowatz BMediaRoster::MessageReceived(BMessage * message)
276452a38012Sejakowatz {
2765cf4e2277Sbeveloper 	switch (message->what) {
2766cf4e2277Sbeveloper 		case 'PING':
2767cf4e2277Sbeveloper 		{
27686396865dSbeveloper 			// media_server plays ping-pong with the BMediaRosters
27696396865dSbeveloper 			// to detect dead teams. Normal communication uses ports.
27706396865dSbeveloper 			static BMessage pong('PONG');
27716396865dSbeveloper 			message->SendReply(&pong, static_cast<BHandler *>(NULL), 2000000);
27726396865dSbeveloper 			return;
27736396865dSbeveloper 		}
27746396865dSbeveloper 
2775cf4e2277Sbeveloper 		case NODE_FINAL_RELEASE:
2776cf4e2277Sbeveloper 		{
2777cf4e2277Sbeveloper 			// this function is called by a BMediaNode to delete
2778cf4e2277Sbeveloper 			// itself, as this needs to be done from another thread
2779cf4e2277Sbeveloper 			// context, it is done here.
2780cf4e2277Sbeveloper 			// XXX If a node is released using BMediaRoster::ReleaseNode()
2781cf4e2277Sbeveloper 			// XXX instead of using BMediaNode::Release() / BMediaNode::Acquire()
2782cf4e2277Sbeveloper 			// XXX fRefCount of the BMediaNode will not be correct.
2783cf4e2277Sbeveloper 
2784cf4e2277Sbeveloper 			BMediaNode *node;
2785cf4e2277Sbeveloper 			message->FindPointer("node", reinterpret_cast<void **>(&node));
2786cf4e2277Sbeveloper 
278754187cc6Sbeveloper 			TRACE("BMediaRoster::MessageReceived NODE_FINAL_RELEASE saving node %ld configuration\n", node->ID());
278854187cc6Sbeveloper 			MediaRosterEx(BMediaRoster::Roster())->SaveNodeConfiguration(node);
2789cf4e2277Sbeveloper 
279054187cc6Sbeveloper 			TRACE("BMediaRoster::MessageReceived NODE_FINAL_RELEASE releasing node %ld\n", node->ID());
2791cf4e2277Sbeveloper 			node->DeleteHook(node); // we don't call Release(), see above!
2792cf4e2277Sbeveloper 			return;
2793cf4e2277Sbeveloper 		}
2794cf4e2277Sbeveloper 	}
27956396865dSbeveloper 	printf("BMediaRoster::MessageReceived: unknown message!\n");
27966396865dSbeveloper 	message->PrintToStream();
279752a38012Sejakowatz }
279852a38012Sejakowatz 
279952a38012Sejakowatz /* virtual */ bool
280052a38012Sejakowatz BMediaRoster::QuitRequested()
280152a38012Sejakowatz {
280252a38012Sejakowatz 	UNIMPLEMENTED();
280352a38012Sejakowatz 	return true;
280452a38012Sejakowatz }
280552a38012Sejakowatz 
280652a38012Sejakowatz /* virtual */ BHandler *
280752a38012Sejakowatz BMediaRoster::ResolveSpecifier(BMessage *msg,
280852a38012Sejakowatz 				 int32 index,
280952a38012Sejakowatz 				 BMessage *specifier,
281052a38012Sejakowatz 				 int32 form,
281152a38012Sejakowatz 				 const char *property)
281252a38012Sejakowatz {
281352a38012Sejakowatz 	UNIMPLEMENTED();
281452a38012Sejakowatz 	return 0;
281552a38012Sejakowatz }
281652a38012Sejakowatz 
281752a38012Sejakowatz 
281852a38012Sejakowatz /* virtual */ status_t
281952a38012Sejakowatz BMediaRoster::GetSupportedSuites(BMessage *data)
282052a38012Sejakowatz {
282152a38012Sejakowatz 	UNIMPLEMENTED();
282252a38012Sejakowatz 	return B_ERROR;
282352a38012Sejakowatz }
282452a38012Sejakowatz 
282552a38012Sejakowatz 
282652a38012Sejakowatz BMediaRoster::~BMediaRoster()
282752a38012Sejakowatz {
282852a38012Sejakowatz 	CALLED();
28296396865dSbeveloper 
28306396865dSbeveloper 	// unregister this application with the media server
28316396865dSbeveloper 	server_unregister_app_request request;
28326396865dSbeveloper 	server_unregister_app_reply reply;
28336396865dSbeveloper 	request.team = team;
28346396865dSbeveloper 	QueryServer(SERVER_UNREGISTER_APP, &request, sizeof(request), &reply, sizeof(reply));
283552a38012Sejakowatz }
283652a38012Sejakowatz 
283752a38012Sejakowatz 
283852a38012Sejakowatz /*************************************************************
283952a38012Sejakowatz  * private BMediaRoster
284052a38012Sejakowatz  *************************************************************/
284152a38012Sejakowatz 
284252a38012Sejakowatz // deprecated call
284352a38012Sejakowatz status_t
284452a38012Sejakowatz BMediaRoster::SetOutputBuffersFor(const media_source & output,
284552a38012Sejakowatz 								  BBufferGroup * group,
284652a38012Sejakowatz 								  bool will_reclaim )
284752a38012Sejakowatz {
284852a38012Sejakowatz 	UNIMPLEMENTED();
28499e9417d2Sbeveloper 	debugger("BMediaRoster::SetOutputBuffersFor missing\n");
285052a38012Sejakowatz 	return B_ERROR;
285152a38012Sejakowatz }
285252a38012Sejakowatz 
285352a38012Sejakowatz 
285452a38012Sejakowatz /* FBC stuffing (Mmmh, Stuffing!) */
285552a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_0(void *) { return B_ERROR; }
285652a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_1(void *) { return B_ERROR; }
285752a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_2(void *) { return B_ERROR; }
285852a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_3(void *) { return B_ERROR; }
285952a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_4(void *) { return B_ERROR; }
286052a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_5(void *) { return B_ERROR; }
286152a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_6(void *) { return B_ERROR; }
286252a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_7(void *) { return B_ERROR; }
286352a38012Sejakowatz 
286452a38012Sejakowatz 
286552a38012Sejakowatz BMediaRoster::BMediaRoster() :
28666396865dSbeveloper 	BLooper("_BMediaRoster_", B_URGENT_DISPLAY_PRIORITY, B_LOOPER_PORT_DEFAULT_CAPACITY)
286752a38012Sejakowatz {
286852a38012Sejakowatz 	CALLED();
28696396865dSbeveloper 
28706396865dSbeveloper 	// start the looper
28716396865dSbeveloper 	Run();
287252a38012Sejakowatz }
287352a38012Sejakowatz 
28746396865dSbeveloper 
287552a38012Sejakowatz /* static */ status_t
287652a38012Sejakowatz BMediaRoster::ParseCommand(BMessage & reply)
287752a38012Sejakowatz {
287852a38012Sejakowatz 	UNIMPLEMENTED();
287952a38012Sejakowatz 	return B_ERROR;
288052a38012Sejakowatz }
288152a38012Sejakowatz 
288252a38012Sejakowatz 
288352a38012Sejakowatz status_t
288452a38012Sejakowatz BMediaRoster::GetDefaultInfo(media_node_id for_default,
288552a38012Sejakowatz 							 BMessage & out_config)
288652a38012Sejakowatz {
288752a38012Sejakowatz 	UNIMPLEMENTED();
288852a38012Sejakowatz 	return B_ERROR;
288952a38012Sejakowatz }
289052a38012Sejakowatz 
289152a38012Sejakowatz 
289252a38012Sejakowatz 
289352a38012Sejakowatz status_t
289452a38012Sejakowatz BMediaRoster::SetRunningDefault(media_node_id for_default,
289552a38012Sejakowatz 								const media_node & node)
289652a38012Sejakowatz {
289752a38012Sejakowatz 	UNIMPLEMENTED();
289852a38012Sejakowatz 	return B_ERROR;
289952a38012Sejakowatz }
290052a38012Sejakowatz 
290152a38012Sejakowatz 
290252a38012Sejakowatz /*************************************************************
290352a38012Sejakowatz  * static BMediaRoster variables
290452a38012Sejakowatz  *************************************************************/
290552a38012Sejakowatz 
290652a38012Sejakowatz bool BMediaRoster::_isMediaServer;
290752a38012Sejakowatz port_id BMediaRoster::_mReplyPort;
290852a38012Sejakowatz int32 BMediaRoster::_mReplyPortRes;
290952a38012Sejakowatz int32 BMediaRoster::_mReplyPortUnavailCount;
291052a38012Sejakowatz BMediaRoster * BMediaRoster::_sDefault = NULL;
291152a38012Sejakowatz 
2912