xref: /haiku/src/kits/media/MediaRoster.cpp (revision 359ac30644ff37232316ad7c0a187c2454e64770)
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 */
31255a01c7Sbeveloper static char __copyright[] = "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>
4252a38012Sejakowatz #include "debug.h"
438b04ffc1Sbeveloper #include "MediaRosterEx.h"
4440f36b03Sbeveloper #include "MediaMisc.h"
4552a38012Sejakowatz #include "PortPool.h"
460a483e72SIngo Weinhold #include "ServerInterface.h"
47f4925104Sbeveloper #include "DataExchange.h"
4816b7eea4Sbeveloper #include "DormantNodeManager.h"
49f4925104Sbeveloper #include "Notifications.h"
50835140c8Sbeveloper #include "TimeSourceObjectManager.h"
5152a38012Sejakowatz 
52f4925104Sbeveloper namespace BPrivate { namespace media {
5352a38012Sejakowatz 
5452a38012Sejakowatz 	// the BMediaRoster destructor is private,
5552a38012Sejakowatz 	// but _DefaultDeleter is a friend class of
5652a38012Sejakowatz 	// the BMediaRoster an thus can delete it
578b04ffc1Sbeveloper 	class DefaultDeleter
5852a38012Sejakowatz 	{
5952a38012Sejakowatz 	public:
608b04ffc1Sbeveloper 		~DefaultDeleter()
616396865dSbeveloper 		{
626396865dSbeveloper 			if (BMediaRoster::_sDefault) {
636396865dSbeveloper 				BMediaRoster::_sDefault->Lock();
646396865dSbeveloper 				BMediaRoster::_sDefault->Quit();
656396865dSbeveloper 			}
666396865dSbeveloper 		}
678b04ffc1Sbeveloper 	};
6852a38012Sejakowatz 
698b04ffc1Sbeveloper } } // BPrivate::media
708b04ffc1Sbeveloper using namespace BPrivate::media;
7152a38012Sejakowatz 
728b04ffc1Sbeveloper // DefaultDeleter will delete the BMediaRoster object in it's destructor.
738b04ffc1Sbeveloper DefaultDeleter _deleter;
7452a38012Sejakowatz 
753620737cSbeveloper status_t
7654187cc6Sbeveloper BMediaRosterEx::SaveNodeConfiguration(BMediaNode *node)
7754187cc6Sbeveloper {
7854187cc6Sbeveloper 	BMediaAddOn *addon;
7954187cc6Sbeveloper 	media_addon_id addonid;
8054187cc6Sbeveloper 	int32 flavorid;
8154187cc6Sbeveloper 	addon = node->AddOn(&flavorid);
8254187cc6Sbeveloper 	if (!addon) {
8360f15390Sbeveloper 		// XXX this check incorrectly triggers on BeOS R5 BT848 node
8460f15390Sbeveloper 		FATAL("BMediaRosterEx::SaveNodeConfiguration node %ld not instantiated from BMediaAddOn!\n", node->ID());
8554187cc6Sbeveloper 		return B_ERROR;
8654187cc6Sbeveloper 	}
8754187cc6Sbeveloper 	addonid = addon->AddonID();
8854187cc6Sbeveloper 
8954187cc6Sbeveloper 	// XXX fix this
9054187cc6Sbeveloper 	printf("### BMediaRosterEx::SaveNodeConfiguration should save addon-id %ld, flavor-id %ld config NOW!\n", addonid, flavorid);
9154187cc6Sbeveloper 	return B_OK;
9254187cc6Sbeveloper }
9354187cc6Sbeveloper 
9454187cc6Sbeveloper status_t
9554187cc6Sbeveloper BMediaRosterEx::LoadNodeConfiguration(media_addon_id addonid, int32 flavorid, BMessage *out_msg)
9654187cc6Sbeveloper {
9754187cc6Sbeveloper 	// XXX fix this
9854187cc6Sbeveloper 	out_msg->MakeEmpty(); // to be fully R5 compliant
9954187cc6Sbeveloper 	printf("### BMediaRosterEx::LoadNodeConfiguration should load addon-id %ld, flavor-id %ld config NOW!\n", addonid, flavorid);
10054187cc6Sbeveloper 	return B_OK;
10154187cc6Sbeveloper }
10254187cc6Sbeveloper 
10354187cc6Sbeveloper status_t
10473794717Sbeveloper BMediaRosterEx::IncrementAddonFlavorInstancesCount(media_addon_id addonid, int32 flavorid)
10554187cc6Sbeveloper {
10673794717Sbeveloper 	server_change_addon_flavor_instances_count_request request;
10773794717Sbeveloper 	server_change_addon_flavor_instances_count_reply reply;
10873794717Sbeveloper 
10973794717Sbeveloper 	request.addonid = addonid;
11073794717Sbeveloper 	request.flavorid = flavorid;
11173794717Sbeveloper 	request.delta = 1;
11273794717Sbeveloper 	request.team = team;
11373794717Sbeveloper 	return QueryServer(SERVER_CHANGE_ADDON_FLAVOR_INSTANCES_COUNT, &request, sizeof(request), &reply, sizeof(reply));
11454187cc6Sbeveloper }
11554187cc6Sbeveloper 
11654187cc6Sbeveloper status_t
11773794717Sbeveloper BMediaRosterEx::DecrementAddonFlavorInstancesCount(media_addon_id addonid, int32 flavorid)
11854187cc6Sbeveloper {
11973794717Sbeveloper 	server_change_addon_flavor_instances_count_request request;
12073794717Sbeveloper 	server_change_addon_flavor_instances_count_reply reply;
12173794717Sbeveloper 
12273794717Sbeveloper 	request.addonid = addonid;
12373794717Sbeveloper 	request.flavorid = flavorid;
12473794717Sbeveloper 	request.delta = -1;
12573794717Sbeveloper 	request.team = team;
12673794717Sbeveloper 	return QueryServer(SERVER_CHANGE_ADDON_FLAVOR_INSTANCES_COUNT, &request, sizeof(request), &reply, sizeof(reply));
12754187cc6Sbeveloper }
12854187cc6Sbeveloper 
12954187cc6Sbeveloper status_t
13054187cc6Sbeveloper BMediaRosterEx::SetNodeCreator(media_node_id node, team_id creator)
13154187cc6Sbeveloper {
13254187cc6Sbeveloper 	server_set_node_creator_request request;
13354187cc6Sbeveloper 	server_set_node_creator_reply reply;
13454187cc6Sbeveloper 
13554187cc6Sbeveloper 	request.node = node;
13654187cc6Sbeveloper 	request.creator = creator;
13754187cc6Sbeveloper 	return QueryServer(SERVER_SET_NODE_CREATOR, &request, sizeof(request), &reply, sizeof(reply));
13854187cc6Sbeveloper }
13954187cc6Sbeveloper 
14054187cc6Sbeveloper status_t
1418b04ffc1Sbeveloper BMediaRosterEx::GetNode(node_type type, media_node * out_node, int32 * out_input_id, BString * out_input_name)
14252a38012Sejakowatz {
14352a38012Sejakowatz 	if (out_node == NULL)
14452a38012Sejakowatz 		return B_BAD_VALUE;
14552a38012Sejakowatz 
1468c6a6096Sbeveloper 	server_get_node_request request;
1478c6a6096Sbeveloper 	server_get_node_reply reply;
14852a38012Sejakowatz 	status_t rv;
14952a38012Sejakowatz 
1508c6a6096Sbeveloper 	request.type = type;
1519e9417d2Sbeveloper 	request.team = team;
1528c6a6096Sbeveloper 	rv = QueryServer(SERVER_GET_NODE, &request, sizeof(request), &reply, sizeof(reply));
1538c6a6096Sbeveloper 	if (rv != B_OK)
1548c6a6096Sbeveloper 		return rv;
15552a38012Sejakowatz 
15652a38012Sejakowatz 	*out_node = reply.node;
15752a38012Sejakowatz 	if (out_input_id)
15852a38012Sejakowatz 		*out_input_id = reply.input_id;
15952a38012Sejakowatz 	if (out_input_name)
16052a38012Sejakowatz 		*out_input_name = reply.input_name;
1618c6a6096Sbeveloper 	return rv;
16252a38012Sejakowatz }
16352a38012Sejakowatz 
1643620737cSbeveloper status_t
1658b04ffc1Sbeveloper BMediaRosterEx::SetNode(node_type type, const media_node *node, const dormant_node_info *info, const media_input *input)
16652a38012Sejakowatz {
1678c6a6096Sbeveloper 	server_set_node_request request;
1688c6a6096Sbeveloper 	server_set_node_reply reply;
16952a38012Sejakowatz 
1708c6a6096Sbeveloper 	request.type = type;
1718c6a6096Sbeveloper 	request.use_node = node ? true : false;
17252a38012Sejakowatz 	if (node)
1738c6a6096Sbeveloper 		request.node = *node;
1748c6a6096Sbeveloper 	request.use_dni = info ? true : false;
17552a38012Sejakowatz 	if (info)
1768c6a6096Sbeveloper 		request.dni = *info;
1778c6a6096Sbeveloper 	request.use_input = input ? true : false;
17852a38012Sejakowatz 	if (input)
1798c6a6096Sbeveloper 		request.input = *input;
18052a38012Sejakowatz 
1818c6a6096Sbeveloper 	return QueryServer(SERVER_SET_NODE, &request, sizeof(request), &reply, sizeof(reply));
18252a38012Sejakowatz }
18352a38012Sejakowatz 
1843620737cSbeveloper status_t
1858b04ffc1Sbeveloper BMediaRosterEx::GetAllOutputs(const media_node & node, List<media_output> *list)
1863620737cSbeveloper {
1873620737cSbeveloper 	int32 cookie;
1883620737cSbeveloper 	status_t rv;
1893620737cSbeveloper 	status_t result;
1903620737cSbeveloper 
1913620737cSbeveloper 	result = B_OK;
1923620737cSbeveloper 	cookie = 0;
19376669a29Sbeveloper 	list->MakeEmpty();
1943620737cSbeveloper 	for (;;) {
1953620737cSbeveloper 		producer_get_next_output_request request;
1963620737cSbeveloper 		producer_get_next_output_reply reply;
1973620737cSbeveloper 		request.cookie = cookie;
1980caff283Sbeveloper 		rv = QueryPort(node.port, PRODUCER_GET_NEXT_OUTPUT, &request, sizeof(request), &reply, sizeof(reply));
1993620737cSbeveloper 		if (rv != B_OK)
2003620737cSbeveloper 			break;
2013620737cSbeveloper 		cookie = reply.cookie;
20276669a29Sbeveloper 		if (!list->Insert(reply.output)) {
20376669a29Sbeveloper 			FATAL("GetAllOutputs: list->Insert failed\n");
2043620737cSbeveloper 			result = B_ERROR;
2053620737cSbeveloper 		}
2063620737cSbeveloper 	}
2073620737cSbeveloper 
2083620737cSbeveloper 	producer_dispose_output_cookie_request request;
2093620737cSbeveloper 	producer_dispose_output_cookie_reply reply;
2100caff283Sbeveloper 	QueryPort(node.port, PRODUCER_DISPOSE_OUTPUT_COOKIE, &request, sizeof(request), &reply, sizeof(reply));
2113620737cSbeveloper 
2123620737cSbeveloper 	return result;
2133620737cSbeveloper }
2143620737cSbeveloper 
2153620737cSbeveloper status_t
2168b04ffc1Sbeveloper BMediaRosterEx::GetAllInputs(const media_node & node, List<media_input> *list)
2173620737cSbeveloper {
2183620737cSbeveloper 	int32 cookie;
2193620737cSbeveloper 	status_t rv;
2203620737cSbeveloper 	status_t result;
2213620737cSbeveloper 
2223620737cSbeveloper 	result = B_OK;
2233620737cSbeveloper 	cookie = 0;
22476669a29Sbeveloper 	list->MakeEmpty();
2253620737cSbeveloper 	for (;;) {
2263620737cSbeveloper 		consumer_get_next_input_request request;
2273620737cSbeveloper 		consumer_get_next_input_reply reply;
2283620737cSbeveloper 		request.cookie = cookie;
2290caff283Sbeveloper 		rv = QueryPort(node.port, CONSUMER_GET_NEXT_INPUT, &request, sizeof(request), &reply, sizeof(reply));
2303620737cSbeveloper 		if (rv != B_OK)
2313620737cSbeveloper 			break;
2323620737cSbeveloper 		cookie = reply.cookie;
23376669a29Sbeveloper 		if (!list->Insert(reply.input)) {
23476669a29Sbeveloper 			FATAL("GetAllInputs: list->Insert failed\n");
2353620737cSbeveloper 			result = B_ERROR;
2363620737cSbeveloper 		}
2373620737cSbeveloper 	}
2383620737cSbeveloper 
2393620737cSbeveloper 	consumer_dispose_input_cookie_request request;
2403620737cSbeveloper 	consumer_dispose_input_cookie_reply reply;
2410caff283Sbeveloper 	QueryPort(node.port, CONSUMER_DISPOSE_INPUT_COOKIE, &request, sizeof(request), &reply, sizeof(reply));
2423620737cSbeveloper 
2433620737cSbeveloper 	return result;
2443620737cSbeveloper }
2453620737cSbeveloper 
2463620737cSbeveloper status_t
2478b04ffc1Sbeveloper BMediaRosterEx::PublishOutputs(const media_node & node, List<media_output> *list)
2483620737cSbeveloper {
2493620737cSbeveloper 	server_publish_outputs_request request;
2503620737cSbeveloper 	server_publish_outputs_reply reply;
2513620737cSbeveloper 	media_output *output;
2523620737cSbeveloper 	media_output *outputs;
2533620737cSbeveloper 	int32 count;
254a7b41a96Sbeveloper 	status_t rv;
2553620737cSbeveloper 
25676669a29Sbeveloper 	count = list->CountItems();
2573620737cSbeveloper 	TRACE("PublishOutputs: publishing %ld\n", count);
2583620737cSbeveloper 
2593620737cSbeveloper 	request.node = node;
2603620737cSbeveloper 	request.count = count;
2613620737cSbeveloper 	if (count > MAX_OUTPUTS) {
2623620737cSbeveloper 		void *start_addr;
2633620737cSbeveloper 		size_t size;
26440f36b03Sbeveloper 		size = ROUND_UP_TO_PAGE(count * sizeof(media_output));
2653620737cSbeveloper 		request.area = create_area("publish outputs", &start_addr, B_ANY_ADDRESS, size, B_NO_LOCK, B_READ_AREA | B_WRITE_AREA);
2663620737cSbeveloper 		if (request.area < B_OK) {
267353b9f6bSbeveloper 			FATAL("PublishOutputs: failed to create area, %#lx\n", request.area);
2683620737cSbeveloper 			return (status_t)request.area;
2693620737cSbeveloper 		}
2703620737cSbeveloper 		outputs = static_cast<media_output *>(start_addr);
2713620737cSbeveloper 	} else {
2723620737cSbeveloper 		request.area = -1;
2733620737cSbeveloper 		outputs = request.outputs;
2743620737cSbeveloper 	}
27576669a29Sbeveloper 	TRACE("PublishOutputs: area %ld\n", request.area);
2763620737cSbeveloper 
27776669a29Sbeveloper 	int i;
27876669a29Sbeveloper 	for (i = 0, list->Rewind(); list->GetNext(&output); i++) {
27976669a29Sbeveloper 		ASSERT(i < count);
2803620737cSbeveloper 		outputs[i] = *output;
2813620737cSbeveloper 	}
2823620737cSbeveloper 
283a7b41a96Sbeveloper 	rv = QueryServer(SERVER_PUBLISH_OUTPUTS, &request, sizeof(request), &reply, sizeof(reply));
284a7b41a96Sbeveloper 
285a7b41a96Sbeveloper 	if (request.area != -1)
286a7b41a96Sbeveloper 		delete_area(request.area);
287a7b41a96Sbeveloper 
288a7b41a96Sbeveloper 	return rv;
2893620737cSbeveloper }
2903620737cSbeveloper 
2913620737cSbeveloper status_t
2928b04ffc1Sbeveloper BMediaRosterEx::PublishInputs(const media_node & node, List<media_input> *list)
2933620737cSbeveloper {
2943620737cSbeveloper 	server_publish_inputs_request request;
2953620737cSbeveloper 	server_publish_inputs_reply reply;
2963620737cSbeveloper 	media_input *input;
2973620737cSbeveloper 	media_input *inputs;
2983620737cSbeveloper 	int32 count;
299a7b41a96Sbeveloper 	status_t rv;
3003620737cSbeveloper 
30176669a29Sbeveloper 	count = list->CountItems();
3023620737cSbeveloper 	TRACE("PublishInputs: publishing %ld\n", count);
3033620737cSbeveloper 
3043620737cSbeveloper 	request.node = node;
3053620737cSbeveloper 	request.count = count;
3063620737cSbeveloper 	if (count > MAX_INPUTS) {
3073620737cSbeveloper 		void *start_addr;
3083620737cSbeveloper 		size_t size;
30940f36b03Sbeveloper 		size = ROUND_UP_TO_PAGE(count * sizeof(media_input));
3103620737cSbeveloper 		request.area = create_area("publish inputs", &start_addr, B_ANY_ADDRESS, size, B_NO_LOCK, B_READ_AREA | B_WRITE_AREA);
3113620737cSbeveloper 		if (request.area < B_OK) {
312353b9f6bSbeveloper 			FATAL("PublishInputs: failed to create area, %#lx\n", request.area);
3133620737cSbeveloper 			return (status_t)request.area;
3143620737cSbeveloper 		}
3153620737cSbeveloper 		inputs = static_cast<media_input *>(start_addr);
3163620737cSbeveloper 	} else {
3173620737cSbeveloper 		request.area = -1;
3183620737cSbeveloper 		inputs = request.inputs;
3193620737cSbeveloper 	}
32076669a29Sbeveloper 	TRACE("PublishInputs: area %ld\n", request.area);
3213620737cSbeveloper 
32276669a29Sbeveloper 	int i;
32376669a29Sbeveloper 	for (i = 0, list->Rewind(); list->GetNext(&input); i++) {
32476669a29Sbeveloper 		ASSERT(i < count);
3253620737cSbeveloper 		inputs[i] = *input;
3263620737cSbeveloper 	}
3273620737cSbeveloper 
328a7b41a96Sbeveloper 	rv = QueryServer(SERVER_PUBLISH_INPUTS, &request, sizeof(request), &reply, sizeof(reply));
329a7b41a96Sbeveloper 
330a7b41a96Sbeveloper 	if (request.area != -1)
331a7b41a96Sbeveloper 		delete_area(request.area);
332a7b41a96Sbeveloper 
333a7b41a96Sbeveloper 	return rv;
3343620737cSbeveloper }
3353620737cSbeveloper 
33652a38012Sejakowatz /*************************************************************
33752a38012Sejakowatz  * public BMediaRoster
33852a38012Sejakowatz  *************************************************************/
33952a38012Sejakowatz 
34052a38012Sejakowatz status_t
34152a38012Sejakowatz BMediaRoster::GetVideoInput(media_node * out_node)
34252a38012Sejakowatz {
34352a38012Sejakowatz 	CALLED();
3448b04ffc1Sbeveloper 	return MediaRosterEx(this)->GetNode(VIDEO_INPUT, out_node);
34552a38012Sejakowatz }
34652a38012Sejakowatz 
34752a38012Sejakowatz 
34852a38012Sejakowatz status_t
34952a38012Sejakowatz BMediaRoster::GetAudioInput(media_node * out_node)
35052a38012Sejakowatz {
35152a38012Sejakowatz 	CALLED();
3528b04ffc1Sbeveloper 	return MediaRosterEx(this)->GetNode(AUDIO_INPUT, out_node);
35352a38012Sejakowatz }
35452a38012Sejakowatz 
35552a38012Sejakowatz 
35652a38012Sejakowatz status_t
35752a38012Sejakowatz BMediaRoster::GetVideoOutput(media_node * out_node)
35852a38012Sejakowatz {
35952a38012Sejakowatz 	CALLED();
3608b04ffc1Sbeveloper 	return MediaRosterEx(this)->GetNode(VIDEO_OUTPUT, out_node);
36152a38012Sejakowatz }
36252a38012Sejakowatz 
36352a38012Sejakowatz 
36452a38012Sejakowatz status_t
36552a38012Sejakowatz BMediaRoster::GetAudioMixer(media_node * out_node)
36652a38012Sejakowatz {
36752a38012Sejakowatz 	CALLED();
3688b04ffc1Sbeveloper 	return MediaRosterEx(this)->GetNode(AUDIO_MIXER, out_node);
36952a38012Sejakowatz }
37052a38012Sejakowatz 
37152a38012Sejakowatz 
37252a38012Sejakowatz status_t
37352a38012Sejakowatz BMediaRoster::GetAudioOutput(media_node * out_node)
37452a38012Sejakowatz {
37552a38012Sejakowatz 	CALLED();
3768b04ffc1Sbeveloper 	return MediaRosterEx(this)->GetNode(AUDIO_OUTPUT, out_node);
37752a38012Sejakowatz }
37852a38012Sejakowatz 
37952a38012Sejakowatz 
38052a38012Sejakowatz status_t
38152a38012Sejakowatz BMediaRoster::GetAudioOutput(media_node * out_node,
38252a38012Sejakowatz 							 int32 * out_input_id,
38352a38012Sejakowatz 							 BString * out_input_name)
38452a38012Sejakowatz {
38552a38012Sejakowatz 	CALLED();
3868b04ffc1Sbeveloper 	return MediaRosterEx(this)->GetNode(AUDIO_OUTPUT_EX, out_node, out_input_id, out_input_name);
38752a38012Sejakowatz }
38852a38012Sejakowatz 
38952a38012Sejakowatz 
39052a38012Sejakowatz status_t
39152a38012Sejakowatz BMediaRoster::GetTimeSource(media_node * out_node)
39252a38012Sejakowatz {
39352a38012Sejakowatz 	CALLED();
39486bce45bSbeveloper 	status_t rv;
39586bce45bSbeveloper 
39686bce45bSbeveloper 	// XXX need to do this in a nicer way.
39786bce45bSbeveloper 
39886bce45bSbeveloper 	rv = MediaRosterEx(this)->GetNode(TIME_SOURCE, out_node);
39986bce45bSbeveloper 	if (rv != B_OK)
40086bce45bSbeveloper 		return rv;
40186bce45bSbeveloper 
40286bce45bSbeveloper 	// We don't do reference counting for timesources, that's why we
40386bce45bSbeveloper 	// release the node immediately.
40486bce45bSbeveloper 	ReleaseNode(*out_node);
40586bce45bSbeveloper 
40686bce45bSbeveloper 	// we need to remember to not use this node with server side reference counting
40786bce45bSbeveloper 	out_node->kind |= NODE_KIND_NO_REFCOUNTING;
40886bce45bSbeveloper 
40986bce45bSbeveloper 	return B_OK;
41052a38012Sejakowatz }
41152a38012Sejakowatz 
41252a38012Sejakowatz 
41352a38012Sejakowatz status_t
41452a38012Sejakowatz BMediaRoster::SetVideoInput(const media_node & producer)
41552a38012Sejakowatz {
41652a38012Sejakowatz 	CALLED();
4178b04ffc1Sbeveloper 	return MediaRosterEx(this)->SetNode(VIDEO_INPUT, &producer);
41852a38012Sejakowatz }
41952a38012Sejakowatz 
42052a38012Sejakowatz 
42152a38012Sejakowatz status_t
42252a38012Sejakowatz BMediaRoster::SetVideoInput(const dormant_node_info & producer)
42352a38012Sejakowatz {
42452a38012Sejakowatz 	CALLED();
4258b04ffc1Sbeveloper 	return MediaRosterEx(this)->SetNode(VIDEO_INPUT, NULL, &producer);
42652a38012Sejakowatz }
42752a38012Sejakowatz 
42852a38012Sejakowatz 
42952a38012Sejakowatz status_t
43052a38012Sejakowatz BMediaRoster::SetAudioInput(const media_node & producer)
43152a38012Sejakowatz {
43252a38012Sejakowatz 	CALLED();
4338b04ffc1Sbeveloper 	return MediaRosterEx(this)->SetNode(AUDIO_INPUT, &producer);
43452a38012Sejakowatz }
43552a38012Sejakowatz 
43652a38012Sejakowatz 
43752a38012Sejakowatz status_t
43852a38012Sejakowatz BMediaRoster::SetAudioInput(const dormant_node_info & producer)
43952a38012Sejakowatz {
44052a38012Sejakowatz 	CALLED();
4418b04ffc1Sbeveloper 	return MediaRosterEx(this)->SetNode(AUDIO_INPUT, NULL, &producer);
44252a38012Sejakowatz }
44352a38012Sejakowatz 
44452a38012Sejakowatz 
44552a38012Sejakowatz status_t
44652a38012Sejakowatz BMediaRoster::SetVideoOutput(const media_node & consumer)
44752a38012Sejakowatz {
44852a38012Sejakowatz 	CALLED();
4498b04ffc1Sbeveloper 	return MediaRosterEx(this)->SetNode(VIDEO_OUTPUT, &consumer);
45052a38012Sejakowatz }
45152a38012Sejakowatz 
45252a38012Sejakowatz 
45352a38012Sejakowatz status_t
45452a38012Sejakowatz BMediaRoster::SetVideoOutput(const dormant_node_info & consumer)
45552a38012Sejakowatz {
45652a38012Sejakowatz 	CALLED();
4578b04ffc1Sbeveloper 	return MediaRosterEx(this)->SetNode(VIDEO_OUTPUT, NULL, &consumer);
45852a38012Sejakowatz }
45952a38012Sejakowatz 
46052a38012Sejakowatz 
46152a38012Sejakowatz status_t
46252a38012Sejakowatz BMediaRoster::SetAudioOutput(const media_node & consumer)
46352a38012Sejakowatz {
46452a38012Sejakowatz 	CALLED();
4658b04ffc1Sbeveloper 	return MediaRosterEx(this)->SetNode(AUDIO_OUTPUT, &consumer);
46652a38012Sejakowatz }
46752a38012Sejakowatz 
46852a38012Sejakowatz 
46952a38012Sejakowatz status_t
47052a38012Sejakowatz BMediaRoster::SetAudioOutput(const media_input & input_to_output)
47152a38012Sejakowatz {
47252a38012Sejakowatz 	CALLED();
4738b04ffc1Sbeveloper 	return MediaRosterEx(this)->SetNode(AUDIO_OUTPUT, NULL, NULL, &input_to_output);
47452a38012Sejakowatz }
47552a38012Sejakowatz 
47652a38012Sejakowatz 
47752a38012Sejakowatz status_t
47852a38012Sejakowatz BMediaRoster::SetAudioOutput(const dormant_node_info & consumer)
47952a38012Sejakowatz {
48052a38012Sejakowatz 	CALLED();
4818b04ffc1Sbeveloper 	return MediaRosterEx(this)->SetNode(AUDIO_OUTPUT, NULL, &consumer);
48252a38012Sejakowatz }
48352a38012Sejakowatz 
48452a38012Sejakowatz 
48552a38012Sejakowatz status_t
48652a38012Sejakowatz BMediaRoster::GetNodeFor(media_node_id node,
48752a38012Sejakowatz 						 media_node * clone)
48852a38012Sejakowatz {
4899e9417d2Sbeveloper 	CALLED();
4909e9417d2Sbeveloper 	if (clone == NULL)
4919e9417d2Sbeveloper 		return B_BAD_VALUE;
4929e9417d2Sbeveloper 	if (node <= 0)
4939e9417d2Sbeveloper 		return B_MEDIA_BAD_NODE;
4949e9417d2Sbeveloper 
4959e9417d2Sbeveloper 	server_get_node_for_request request;
4969e9417d2Sbeveloper 	server_get_node_for_reply reply;
4979e9417d2Sbeveloper 	status_t rv;
4989e9417d2Sbeveloper 
4999e9417d2Sbeveloper 	request.nodeid = node;
5009e9417d2Sbeveloper 	request.team = team;
5019e9417d2Sbeveloper 
5029e9417d2Sbeveloper 	rv = QueryServer(SERVER_GET_NODE_FOR, &request, sizeof(request), &reply, sizeof(reply));
5039e9417d2Sbeveloper 	if (rv != B_OK)
5049e9417d2Sbeveloper 		return rv;
5059e9417d2Sbeveloper 
5069e9417d2Sbeveloper 	*clone = reply.clone;
5079e9417d2Sbeveloper 	return B_OK;
50852a38012Sejakowatz }
50952a38012Sejakowatz 
51052a38012Sejakowatz 
51152a38012Sejakowatz status_t
51252a38012Sejakowatz BMediaRoster::GetSystemTimeSource(media_node * clone)
51352a38012Sejakowatz {
51452a38012Sejakowatz 	CALLED();
51586bce45bSbeveloper 	status_t rv;
51686bce45bSbeveloper 
51786bce45bSbeveloper 	// XXX need to do this in a nicer way.
51886bce45bSbeveloper 
51986bce45bSbeveloper 	rv = MediaRosterEx(this)->GetNode(SYSTEM_TIME_SOURCE, clone);
52086bce45bSbeveloper 	if (rv != B_OK)
52186bce45bSbeveloper 		return rv;
52286bce45bSbeveloper 
52386bce45bSbeveloper 	// We don't do reference counting for timesources, that's why we
52486bce45bSbeveloper 	// release the node immediately.
52586bce45bSbeveloper 	ReleaseNode(*clone);
52686bce45bSbeveloper 
52786bce45bSbeveloper 	// we need to remember to not use this node with server side reference counting
52886bce45bSbeveloper 	clone->kind |= NODE_KIND_NO_REFCOUNTING;
52986bce45bSbeveloper 
53086bce45bSbeveloper 	return B_OK;
53152a38012Sejakowatz }
53252a38012Sejakowatz 
53352a38012Sejakowatz 
53452a38012Sejakowatz status_t
53552a38012Sejakowatz BMediaRoster::ReleaseNode(const media_node & node)
53652a38012Sejakowatz {
5379e9417d2Sbeveloper 	CALLED();
53840f36b03Sbeveloper 	if (IS_INVALID_NODE(node))
5399e9417d2Sbeveloper 		return B_MEDIA_BAD_NODE;
54052a38012Sejakowatz 
54186bce45bSbeveloper 	if (node.kind & NODE_KIND_NO_REFCOUNTING) {
54286bce45bSbeveloper 		printf("BMediaRoster::ReleaseNode, trying to release reference counting disabled timesource, node %ld, port %ld, team %ld\n", node.node, node.port, team);
54386bce45bSbeveloper 		return B_OK;
54486bce45bSbeveloper 	}
54586bce45bSbeveloper 
5469e9417d2Sbeveloper 	server_release_node_request request;
5479e9417d2Sbeveloper 	server_release_node_reply reply;
548cf4e2277Sbeveloper 	status_t rv;
5499e9417d2Sbeveloper 
5509e9417d2Sbeveloper 	request.node = node;
5519e9417d2Sbeveloper 	request.team = team;
5529e9417d2Sbeveloper 
55360f15390Sbeveloper 	TRACE("BMediaRoster::ReleaseNode, node %ld, port %ld, team %ld\n", node.node, node.port, team);
554cf4e2277Sbeveloper 
555cf4e2277Sbeveloper 	rv = QueryServer(SERVER_RELEASE_NODE, &request, sizeof(request), &reply, sizeof(reply));
556cf4e2277Sbeveloper 	if (rv != B_OK) {
557cf4e2277Sbeveloper 		FATAL("BMediaRoster::ReleaseNode FAILED, node %ld, port %ld, team %ld!\n", node.node, node.port, team);
558cf4e2277Sbeveloper 	}
559cf4e2277Sbeveloper 	return rv;
5609e9417d2Sbeveloper }
56152a38012Sejakowatz 
56252a38012Sejakowatz BTimeSource *
56352a38012Sejakowatz BMediaRoster::MakeTimeSourceFor(const media_node & for_node)
56452a38012Sejakowatz {
565835140c8Sbeveloper 	CALLED();
566287f7492Sbeveloper 
5670e21b167Sbeveloper 	BTimeSource *source;
568287f7492Sbeveloper 
56960f15390Sbeveloper 	TRACE("BMediaRoster::MakeTimeSourceFor enter, node %ld, port %ld, kind %#lx\n", for_node.node, for_node.port, for_node.kind);
570287f7492Sbeveloper 
5710e21b167Sbeveloper 	if (0 == (for_node.kind & B_TIME_SOURCE)) {
57260f15390Sbeveloper 		//FATAL("BMediaRoster::MakeTimeSourceFor, node %ld is not a timesource!\n", for_node.node);
5730e21b167Sbeveloper 		// XXX It appears that Cortex calls this function on every node, and expects
5740e21b167Sbeveloper 		// XXX to be returned a system time source if the for_node is not a timesource
5750e21b167Sbeveloper 		media_node clone;
5760e21b167Sbeveloper 		GetSystemTimeSource(&clone);
5770e21b167Sbeveloper 		source = _TimeSourceObjectManager->GetTimeSource(clone);
57886bce45bSbeveloper //		ReleaseNode(clone);
5790e21b167Sbeveloper 	} else {
5800e21b167Sbeveloper 		source = _TimeSourceObjectManager->GetTimeSource(for_node);
5810e21b167Sbeveloper 	}
5820e21b167Sbeveloper 
58360f15390Sbeveloper 	TRACE("BMediaRoster::MakeTimeSourceFor leave, node %ld, port %ld, kind %#lx\n", source->Node().node, source->Node().port, source->Node().kind);
584287f7492Sbeveloper 
585835140c8Sbeveloper 	return source;
58652a38012Sejakowatz }
58752a38012Sejakowatz 
58852a38012Sejakowatz 
58952a38012Sejakowatz status_t
59052a38012Sejakowatz BMediaRoster::Connect(const media_source & from,
59152a38012Sejakowatz 					  const media_destination & to,
59252a38012Sejakowatz 					  media_format * io_format,
59352a38012Sejakowatz 					  media_output * out_output,
59452a38012Sejakowatz 					  media_input * out_input)
59552a38012Sejakowatz {
596eae26d3dSbeveloper 	return BMediaRoster::Connect(from, to, io_format, out_output, out_input, 0);
597eae26d3dSbeveloper }
598eae26d3dSbeveloper 
599eae26d3dSbeveloper 
600eae26d3dSbeveloper status_t
601eae26d3dSbeveloper BMediaRoster::Connect(const media_source & from,
602eae26d3dSbeveloper 					  const media_destination & to,
603eae26d3dSbeveloper 					  media_format * io_format,
604eae26d3dSbeveloper 					  media_output * out_output,
605eae26d3dSbeveloper 					  media_input * out_input,
606eae26d3dSbeveloper 					  uint32 in_flags,
607eae26d3dSbeveloper 					  void * _reserved)
608eae26d3dSbeveloper {
60952a38012Sejakowatz 	CALLED();
61052a38012Sejakowatz 	if (io_format == NULL || out_output == NULL || out_input == NULL)
61152a38012Sejakowatz 		return B_BAD_VALUE;
61240f36b03Sbeveloper 	if (IS_INVALID_SOURCE(from)) {
613353b9f6bSbeveloper 		FATAL("BMediaRoster::Connect: media_source invalid\n");
61452a38012Sejakowatz 		return B_MEDIA_BAD_SOURCE;
6159e9417d2Sbeveloper 	}
61640f36b03Sbeveloper 	if (IS_INVALID_DESTINATION(to)) {
617353b9f6bSbeveloper 		FATAL("BMediaRoster::Connect: media_destination invalid\n");
61852a38012Sejakowatz 		return B_MEDIA_BAD_DESTINATION;
6199e9417d2Sbeveloper 	}
62052a38012Sejakowatz 
62152a38012Sejakowatz 	status_t rv;
6228c6a6096Sbeveloper 	producer_format_proposal_request request1;
6238c6a6096Sbeveloper 	producer_format_proposal_reply reply1;
62452a38012Sejakowatz 
62552a38012Sejakowatz 	// BBufferProducer::FormatProposal
6268c6a6096Sbeveloper 	request1.output = from;
6278c6a6096Sbeveloper 	request1.format = *io_format;
6288c6a6096Sbeveloper 	rv = QueryPort(from.port, PRODUCER_FORMAT_PROPOSAL, &request1, sizeof(request1), &reply1, sizeof(reply1));
6298c6a6096Sbeveloper 	if (rv != B_OK) {
630353b9f6bSbeveloper 		FATAL("BMediaRoster::Connect: aborted after BBufferProducer::FormatProposal, status = %#lx\n",rv);
63152a38012Sejakowatz 		return rv;
63252a38012Sejakowatz 	}
6338c6a6096Sbeveloper 	// reply1.format now contains the format proposed by the producer
6348c6a6096Sbeveloper 
6358c6a6096Sbeveloper 	consumer_accept_format_request request2;
6368c6a6096Sbeveloper 	consumer_accept_format_reply reply2;
6378c6a6096Sbeveloper 
6388c6a6096Sbeveloper 	// BBufferConsumer::AcceptFormat
6398c6a6096Sbeveloper 	request2.dest = to;
6408c6a6096Sbeveloper 	request2.format = reply1.format;
6418c6a6096Sbeveloper 	rv = QueryPort(to.port, CONSUMER_ACCEPT_FORMAT, &request2, sizeof(request2), &reply2, sizeof(reply2));
6428c6a6096Sbeveloper 	if (rv != B_OK) {
643353b9f6bSbeveloper 		FATAL("BMediaRoster::Connect: aborted after BBufferConsumer::AcceptFormat, status = %#lx\n",rv);
6448c6a6096Sbeveloper 		return rv;
6458c6a6096Sbeveloper 	}
6468c6a6096Sbeveloper 	// reply2.format now contains the format accepted by the consumer
6478c6a6096Sbeveloper 
6488c6a6096Sbeveloper 	// BBufferProducer::PrepareToConnect
6498c6a6096Sbeveloper 	producer_prepare_to_connect_request request3;
6508c6a6096Sbeveloper 	producer_prepare_to_connect_reply reply3;
6518c6a6096Sbeveloper 
6528c6a6096Sbeveloper 	request3.source = from;
6538c6a6096Sbeveloper 	request3.destination = to;
6548c6a6096Sbeveloper 	request3.format = reply2.format;
6558c6a6096Sbeveloper 	strcpy(request3.name, "XXX some default name"); // XXX fix this
6568c6a6096Sbeveloper 	rv = QueryPort(from.port, PRODUCER_PREPARE_TO_CONNECT, &request3, sizeof(request3), &reply3, sizeof(reply3));
6578c6a6096Sbeveloper 	if (rv != B_OK) {
658353b9f6bSbeveloper 		FATAL("BMediaRoster::Connect: aborted after BBufferProducer::PrepareToConnect, status = %#lx\n",rv);
6598c6a6096Sbeveloper 		return rv;
6608c6a6096Sbeveloper 	}
6618c6a6096Sbeveloper 	// reply3.format is still our pretty media format
6628c6a6096Sbeveloper 	// reply3.out_source the real source to be used for the connection
6638c6a6096Sbeveloper 	// reply3.name the name BBufferConsumer::Connected will see in the outInput->name argument
6648c6a6096Sbeveloper 
6658c6a6096Sbeveloper 	// BBufferConsumer::Connected
6668c6a6096Sbeveloper 	consumer_connected_request request4;
6678c6a6096Sbeveloper 	consumer_connected_reply reply4;
6688c6a6096Sbeveloper 	status_t con_status;
6698c6a6096Sbeveloper 
6708c6a6096Sbeveloper 	request4.producer = reply3.out_source;
6718c6a6096Sbeveloper 	request4.where = to;
6728c6a6096Sbeveloper 	request4.with_format = reply3.format;
6738c6a6096Sbeveloper 	con_status = QueryPort(to.port, CONSUMER_CONNECTED, &request4, sizeof(request4), &reply4, sizeof(reply4));
6748c6a6096Sbeveloper 	if (con_status != B_OK) {
675353b9f6bSbeveloper 		FATAL("BMediaRoster::Connect: aborting after BBufferConsumer::Connected, status = %#lx\n",con_status);
6768c6a6096Sbeveloper 		// we do NOT return here!
6778c6a6096Sbeveloper 	}
6788c6a6096Sbeveloper 	// con_status contains the status code to be supplied to BBufferProducer::Connect's status argument
6798c6a6096Sbeveloper 	// reply4.input contains the media_input that describes the connection from the consumer point of view
6808c6a6096Sbeveloper 
6818c6a6096Sbeveloper 	// BBufferProducer::Connect
6828c6a6096Sbeveloper 	producer_connect_request request5;
6838c6a6096Sbeveloper 	producer_connect_reply reply5;
6848c6a6096Sbeveloper 
6858c6a6096Sbeveloper 	request5.error = con_status;
6868c6a6096Sbeveloper 	request5.source = reply3.out_source;
6878c6a6096Sbeveloper 	request5.destination = reply4.input.destination;
6888c6a6096Sbeveloper 	request5.format = reply3.format; // XXX reply4.input.format ???
6898c6a6096Sbeveloper 	strcpy(request5.name, reply4.input.name);
6900caff283Sbeveloper 	rv = QueryPort(reply4.input.source.port, PRODUCER_CONNECT, &request5, sizeof(request5), &reply5, sizeof(reply5));
6918c6a6096Sbeveloper 	if (con_status != B_OK) {
692353b9f6bSbeveloper 		FATAL("BMediaRoster::Connect: aborted\n");
6938c6a6096Sbeveloper 		return con_status;
6948c6a6096Sbeveloper 	}
6958c6a6096Sbeveloper 	if (rv != B_OK) {
696353b9f6bSbeveloper 		FATAL("BMediaRoster::Connect: aborted after BBufferProducer::Connect, status = %#lx\n",rv);
6978c6a6096Sbeveloper 		return rv;
6988c6a6096Sbeveloper 	}
6998c6a6096Sbeveloper 	// reply5.name contains the name assigned to the connection by the producer
7008c6a6096Sbeveloper 
7018c6a6096Sbeveloper 	// find the output node
7028c6a6096Sbeveloper 	// XXX isn't there a easier way?
7038c6a6096Sbeveloper 	media_node sourcenode;
7048c6a6096Sbeveloper 	GetNodeFor(NodeIDFor(from.port), &sourcenode);
7058c6a6096Sbeveloper 	ReleaseNode(sourcenode);
7068c6a6096Sbeveloper 
7078c6a6096Sbeveloper 	// initilize connection info
7088c6a6096Sbeveloper 	*io_format = reply3.format;
7098c6a6096Sbeveloper 	*out_input = reply4.input;
7108c6a6096Sbeveloper 	out_output->node = sourcenode;
7118c6a6096Sbeveloper 	out_output->source = reply4.input.source;
7128c6a6096Sbeveloper 	out_output->destination = reply4.input.destination;
7138c6a6096Sbeveloper 	out_output->format = reply4.input.format;
7148c6a6096Sbeveloper 	strcpy(out_output->name, reply5.name);
7158c6a6096Sbeveloper 
7168c6a6096Sbeveloper 	// the connection is now made
7178c6a6096Sbeveloper 
7188c6a6096Sbeveloper 
7198c6a6096Sbeveloper 	// XXX register connection with server
7209e9417d2Sbeveloper 	// XXX we should just send a notification, instead of republishing all endpoints
72176669a29Sbeveloper 	List<media_output> outlist;
72276669a29Sbeveloper 	List<media_input> inlist;
7238b04ffc1Sbeveloper 	if (B_OK == MediaRosterEx(this)->GetAllOutputs(out_output->node , &outlist))
7248b04ffc1Sbeveloper 		MediaRosterEx(this)->PublishOutputs(out_output->node , &outlist);
7258b04ffc1Sbeveloper 	if (B_OK == MediaRosterEx(this)->GetAllInputs(out_input->node , &inlist))
7268b04ffc1Sbeveloper 		MediaRosterEx(this)->PublishInputs(out_input->node, &inlist);
7278c6a6096Sbeveloper 
7288c6a6096Sbeveloper 
7298c6a6096Sbeveloper 	// XXX if (mute) BBufferProducer::EnableOutput(false)
7309e9417d2Sbeveloper 	if (in_flags & B_CONNECT_MUTED) {
7319e9417d2Sbeveloper 	}
7328c6a6096Sbeveloper 
7338c6a6096Sbeveloper 
7349e9417d2Sbeveloper 	// send a notification
7359e9417d2Sbeveloper 	BPrivate::media::notifications::ConnectionMade(*out_input, *out_output, *io_format);
7369e9417d2Sbeveloper 
7378c6a6096Sbeveloper 	return B_OK;
7388c6a6096Sbeveloper };
73952a38012Sejakowatz 
74052a38012Sejakowatz 
74152a38012Sejakowatz status_t
7429e9417d2Sbeveloper BMediaRoster::Disconnect(media_node_id source_nodeid,
74352a38012Sejakowatz 						 const media_source & source,
7449e9417d2Sbeveloper 						 media_node_id destination_nodeid,
74552a38012Sejakowatz 						 const media_destination & destination)
74652a38012Sejakowatz {
7479e9417d2Sbeveloper 	CALLED();
74840f36b03Sbeveloper 	if (IS_INVALID_NODEID(source_nodeid)) {
749353b9f6bSbeveloper 		FATAL("BMediaRoster::Disconnect: source media_node_id invalid\n");
7509e9417d2Sbeveloper 		return B_MEDIA_BAD_SOURCE;
7519e9417d2Sbeveloper 	}
75240f36b03Sbeveloper 	if (IS_INVALID_NODEID(destination_nodeid)) {
75340f36b03Sbeveloper 		FATAL("BMediaRoster::Disconnect: destination media_node_id invalid\n");
7549e9417d2Sbeveloper 		return B_MEDIA_BAD_DESTINATION;
7559e9417d2Sbeveloper 	}
75640f36b03Sbeveloper 	if (IS_INVALID_SOURCE(source)) {
757353b9f6bSbeveloper 		FATAL("BMediaRoster::Disconnect: media_source invalid\n");
7589e9417d2Sbeveloper 		return B_MEDIA_BAD_SOURCE;
7599e9417d2Sbeveloper 	}
76040f36b03Sbeveloper 	if (IS_INVALID_DESTINATION(destination)) {
761353b9f6bSbeveloper 		FATAL("BMediaRoster::Disconnect: media_destination invalid\n");
7629e9417d2Sbeveloper 		return B_MEDIA_BAD_DESTINATION;
7639e9417d2Sbeveloper 	}
7649e9417d2Sbeveloper 
7659e9417d2Sbeveloper 	producer_disconnect_request request2;
7669e9417d2Sbeveloper 	producer_disconnect_reply reply2;
7679e9417d2Sbeveloper 	consumer_disconnected_request request1;
7689e9417d2Sbeveloper 	consumer_disconnected_reply reply1;
7699e9417d2Sbeveloper 	status_t rv1, rv2;
7709e9417d2Sbeveloper 
7719e9417d2Sbeveloper 	// XXX we should ask the server if this connection really exists
7729e9417d2Sbeveloper 
7739e9417d2Sbeveloper 	request1.source = source;
7749e9417d2Sbeveloper 	request1.destination = destination;
7759e9417d2Sbeveloper 	request2.source = source;
7769e9417d2Sbeveloper 	request2.destination = destination;
7779e9417d2Sbeveloper 
7789e9417d2Sbeveloper 	rv1 = QueryPort(source.port, PRODUCER_DISCONNECT, &request1, sizeof(request1), &reply1, sizeof(reply1));
7799e9417d2Sbeveloper 	rv2 = QueryPort(destination.port, CONSUMER_DISCONNECTED, &request2, sizeof(request2), &reply2, sizeof(reply2));
7809e9417d2Sbeveloper 
7819e9417d2Sbeveloper 	// XXX unregister connection with server
7829e9417d2Sbeveloper 	// XXX we should just send a notification, instead of republishing all endpoints
78376669a29Sbeveloper 	List<media_output> outlist;
78476669a29Sbeveloper 	List<media_input> inlist;
7859e9417d2Sbeveloper 	media_node sourcenode;
7869e9417d2Sbeveloper 	media_node destnode;
7879e9417d2Sbeveloper 	if (B_OK == GetNodeFor(source_nodeid, &sourcenode)) {
7888b04ffc1Sbeveloper 		if (B_OK == MediaRosterEx(this)->GetAllOutputs(sourcenode , &outlist))
7898b04ffc1Sbeveloper 			MediaRosterEx(this)->PublishOutputs(sourcenode , &outlist);
7909e9417d2Sbeveloper 		ReleaseNode(sourcenode);
791353b9f6bSbeveloper 	} else FATAL("BMediaRoster::Disconnect: source GetNodeFor failed\n");
7929e9417d2Sbeveloper 	if (B_OK == GetNodeFor(destination_nodeid, &destnode)) {
7938b04ffc1Sbeveloper 		if (B_OK == MediaRosterEx(this)->GetAllInputs(destnode , &inlist))
7948b04ffc1Sbeveloper 			MediaRosterEx(this)->PublishInputs(destnode, &inlist);
7959e9417d2Sbeveloper 		ReleaseNode(destnode);
796353b9f6bSbeveloper 	} else FATAL("BMediaRoster::Disconnect: dest GetNodeFor failed\n");
7979e9417d2Sbeveloper 
7989e9417d2Sbeveloper 
7999e9417d2Sbeveloper 	// send a notification
8009e9417d2Sbeveloper 	BPrivate::media::notifications::ConnectionBroken(source, destination);
8019e9417d2Sbeveloper 
8029e9417d2Sbeveloper 	return (rv1 != B_OK || rv2 != B_OK) ? B_ERROR : B_OK;
80352a38012Sejakowatz }
80452a38012Sejakowatz 
80552a38012Sejakowatz 
80652a38012Sejakowatz status_t
80752a38012Sejakowatz BMediaRoster::StartNode(const media_node & node,
80852a38012Sejakowatz 						bigtime_t at_performance_time)
80952a38012Sejakowatz {
81052a38012Sejakowatz 	CALLED();
8119e9417d2Sbeveloper 	if (node.node <= 0)
81252a38012Sejakowatz 		return B_MEDIA_BAD_NODE;
81352a38012Sejakowatz 
81460f15390Sbeveloper 	TRACE("BMediaRoster::StartNode, node %ld, at perf %Ld\n", node.node, at_performance_time);
8150e21b167Sbeveloper 
8166396865dSbeveloper 	node_start_command command;
8176396865dSbeveloper 	command.performance_time = at_performance_time;
81852a38012Sejakowatz 
8196396865dSbeveloper 	return SendToPort(node.port, NODE_START, &command, sizeof(command));
82052a38012Sejakowatz }
82152a38012Sejakowatz 
82252a38012Sejakowatz 
82352a38012Sejakowatz status_t
82452a38012Sejakowatz BMediaRoster::StopNode(const media_node & node,
82552a38012Sejakowatz 					   bigtime_t at_performance_time,
82652a38012Sejakowatz 					   bool immediate)
82752a38012Sejakowatz {
82852a38012Sejakowatz 	CALLED();
82940f36b03Sbeveloper 	if (IS_INVALID_NODE(node))
83052a38012Sejakowatz 		return B_MEDIA_BAD_NODE;
83152a38012Sejakowatz 
83260f15390Sbeveloper 	TRACE("BMediaRoster::StopNode, node %ld, at perf %Ld %s\n", node.node, at_performance_time, immediate ? "NOW" : "");
8330e21b167Sbeveloper 
8346396865dSbeveloper 	node_stop_command command;
8356396865dSbeveloper 	command.performance_time = at_performance_time;
8366396865dSbeveloper 	command.immediate = immediate;
83752a38012Sejakowatz 
8386396865dSbeveloper 	return SendToPort(node.port, NODE_STOP, &command, sizeof(command));
83952a38012Sejakowatz }
84052a38012Sejakowatz 
84152a38012Sejakowatz 
84252a38012Sejakowatz status_t
84352a38012Sejakowatz BMediaRoster::SeekNode(const media_node & node,
84452a38012Sejakowatz 					   bigtime_t to_media_time,
84552a38012Sejakowatz 					   bigtime_t at_performance_time)
84652a38012Sejakowatz {
84752a38012Sejakowatz 	CALLED();
84840f36b03Sbeveloper 	if (IS_INVALID_NODE(node))
84952a38012Sejakowatz 		return B_MEDIA_BAD_NODE;
85052a38012Sejakowatz 
85160f15390Sbeveloper 	TRACE("BMediaRoster::SeekNode, node %ld, at perf %Ld, to perf %Ld\n", node.node, at_performance_time, to_media_time);
8520e21b167Sbeveloper 
8536396865dSbeveloper 	node_seek_command command;
8546396865dSbeveloper 	command.media_time = to_media_time;
8556396865dSbeveloper 	command.performance_time = at_performance_time;
85652a38012Sejakowatz 
8576396865dSbeveloper 	return SendToPort(node.port, NODE_SEEK, &command, sizeof(command));
85852a38012Sejakowatz }
85952a38012Sejakowatz 
86052a38012Sejakowatz 
86152a38012Sejakowatz status_t
86252a38012Sejakowatz BMediaRoster::StartTimeSource(const media_node & node,
86352a38012Sejakowatz 							  bigtime_t at_real_time)
86452a38012Sejakowatz {
86552a38012Sejakowatz 	CALLED();
86660f15390Sbeveloper 	if (IS_SYSTEM_TIMESOURCE(node)) {
86760f15390Sbeveloper 		// XXX debug this
86860f15390Sbeveloper 		//FATAL("BMediaRoster::StartTimeSource node %ld is system timesource\n", node.node);
86960f15390Sbeveloper 		return B_OK;
87060f15390Sbeveloper 	}
87160f15390Sbeveloper 	if (IS_SHADOW_TIMESOURCE(node)) {
87260f15390Sbeveloper 		// XXX debug this
87360f15390Sbeveloper 		FATAL("BMediaRoster::StartTimeSource node %ld is shadow timesource\n", node.node);
87460f15390Sbeveloper 		return B_OK;
87560f15390Sbeveloper 	}
87640f36b03Sbeveloper 	if (IS_INVALID_NODE(node)) {
87760f15390Sbeveloper 		FATAL("BMediaRoster::StartTimeSource node %ld invalid\n", node.node);
87852a38012Sejakowatz 		return B_MEDIA_BAD_NODE;
8790e21b167Sbeveloper 	}
8800e21b167Sbeveloper 	if ((node.kind & B_TIME_SOURCE) == 0) {
88160f15390Sbeveloper 		FATAL("BMediaRoster::StartTimeSource node %ld is no timesource\n", node.node);
88252a38012Sejakowatz 		return B_MEDIA_BAD_NODE;
8830e21b167Sbeveloper 	}
8840e21b167Sbeveloper 
88560f15390Sbeveloper 	TRACE("BMediaRoster::StartTimeSource, node %ld, at real %Ld\n", node.node, at_real_time);
88652a38012Sejakowatz 
88752a38012Sejakowatz 	BTimeSource::time_source_op_info msg;
88852a38012Sejakowatz 	msg.op = BTimeSource::B_TIMESOURCE_START;
88952a38012Sejakowatz 	msg.real_time = at_real_time;
89052a38012Sejakowatz 
89152a38012Sejakowatz 	return write_port(node.port, TIMESOURCE_OP, &msg, sizeof(msg));
89252a38012Sejakowatz }
89352a38012Sejakowatz 
89452a38012Sejakowatz 
89552a38012Sejakowatz status_t
89652a38012Sejakowatz BMediaRoster::StopTimeSource(const media_node & node,
89752a38012Sejakowatz 							 bigtime_t at_real_time,
89852a38012Sejakowatz 							 bool immediate)
89952a38012Sejakowatz {
90052a38012Sejakowatz 	CALLED();
90160f15390Sbeveloper 	if (IS_SYSTEM_TIMESOURCE(node)) {
90260f15390Sbeveloper 		// XXX debug this
90360f15390Sbeveloper 		//FATAL("BMediaRoster::StopTimeSource node %ld is system timesource\n", node.node);
90460f15390Sbeveloper 		return B_OK;
90560f15390Sbeveloper 	}
90660f15390Sbeveloper 	if (IS_SHADOW_TIMESOURCE(node)) {
90760f15390Sbeveloper 		// XXX debug this
90860f15390Sbeveloper 		FATAL("BMediaRoster::StopTimeSource node %ld is shadow timesource\n", node.node);
90960f15390Sbeveloper 		return B_OK;
91060f15390Sbeveloper 	}
91140f36b03Sbeveloper 	if (IS_INVALID_NODE(node)) {
91260f15390Sbeveloper 		FATAL("BMediaRoster::StopTimeSource node %ld invalid\n", node.node);
91352a38012Sejakowatz 		return B_MEDIA_BAD_NODE;
9140e21b167Sbeveloper 	}
9150e21b167Sbeveloper 	if ((node.kind & B_TIME_SOURCE) == 0) {
91660f15390Sbeveloper 		FATAL("BMediaRoster::StopTimeSource node %ld is no timesource\n", node.node);
91752a38012Sejakowatz 		return B_MEDIA_BAD_NODE;
9180e21b167Sbeveloper 	}
9190e21b167Sbeveloper 
92060f15390Sbeveloper 	TRACE("BMediaRoster::StopTimeSource, node %ld, at real %Ld %s\n", node.node, at_real_time, immediate ? "NOW" : "");
92152a38012Sejakowatz 
92252a38012Sejakowatz 	BTimeSource::time_source_op_info msg;
92352a38012Sejakowatz 	msg.op = immediate ? BTimeSource::B_TIMESOURCE_STOP_IMMEDIATELY : BTimeSource::B_TIMESOURCE_STOP;
92452a38012Sejakowatz 	msg.real_time = at_real_time;
92552a38012Sejakowatz 
92652a38012Sejakowatz 	return write_port(node.port, TIMESOURCE_OP, &msg, sizeof(msg));
92752a38012Sejakowatz }
92852a38012Sejakowatz 
92952a38012Sejakowatz 
93052a38012Sejakowatz status_t
93152a38012Sejakowatz BMediaRoster::SeekTimeSource(const media_node & node,
93252a38012Sejakowatz 							 bigtime_t to_performance_time,
93352a38012Sejakowatz 							 bigtime_t at_real_time)
93452a38012Sejakowatz {
93552a38012Sejakowatz 	CALLED();
93660f15390Sbeveloper 	if (IS_SYSTEM_TIMESOURCE(node)) {
93760f15390Sbeveloper 		// XXX debug this
93860f15390Sbeveloper 		// FATAL("BMediaRoster::SeekTimeSource node %ld is system timesource\n", node.node);
93960f15390Sbeveloper 		// you can't seek the system time source, but
94060f15390Sbeveloper 		// returning B_ERROR would break StampTV
94160f15390Sbeveloper 		return B_OK;
94260f15390Sbeveloper 	}
94360f15390Sbeveloper 	if (IS_SHADOW_TIMESOURCE(node)) {
94460f15390Sbeveloper 		// XXX debug this
94560f15390Sbeveloper 		FATAL("BMediaRoster::SeekTimeSource node %ld is shadow timesource\n", node.node);
94660f15390Sbeveloper 		return B_OK;
94760f15390Sbeveloper 	}
94840f36b03Sbeveloper 	if (IS_INVALID_NODE(node)) {
94960f15390Sbeveloper 		FATAL("BMediaRoster::SeekTimeSource node %ld invalid\n", node.node);
95052a38012Sejakowatz 		return B_MEDIA_BAD_NODE;
9510e21b167Sbeveloper 	}
9520e21b167Sbeveloper 	if ((node.kind & B_TIME_SOURCE) == 0) {
95360f15390Sbeveloper 		FATAL("BMediaRoster::SeekTimeSource node %ld is no timesource\n", node.node);
95452a38012Sejakowatz 		return B_MEDIA_BAD_NODE;
9550e21b167Sbeveloper 	}
9560e21b167Sbeveloper 
95760f15390Sbeveloper 	TRACE("BMediaRoster::SeekTimeSource, node %ld, at real %Ld, to perf %Ld\n", node.node, at_real_time, to_performance_time);
95852a38012Sejakowatz 
95952a38012Sejakowatz 	BTimeSource::time_source_op_info msg;
96052a38012Sejakowatz 	msg.op = BTimeSource::B_TIMESOURCE_SEEK;
96152a38012Sejakowatz 	msg.real_time = at_real_time;
96252a38012Sejakowatz 	msg.performance_time = to_performance_time;
96352a38012Sejakowatz 
96452a38012Sejakowatz 	return write_port(node.port, TIMESOURCE_OP, &msg, sizeof(msg));
96552a38012Sejakowatz }
96652a38012Sejakowatz 
96752a38012Sejakowatz 
96852a38012Sejakowatz status_t
96952a38012Sejakowatz BMediaRoster::SyncToNode(const media_node & node,
97052a38012Sejakowatz 						 bigtime_t at_time,
97152a38012Sejakowatz 						 bigtime_t timeout)
97252a38012Sejakowatz {
97352a38012Sejakowatz 	UNIMPLEMENTED();
97460f15390Sbeveloper 	return B_OK;
97552a38012Sejakowatz }
97652a38012Sejakowatz 
97752a38012Sejakowatz 
97852a38012Sejakowatz status_t
97952a38012Sejakowatz BMediaRoster::SetRunModeNode(const media_node & node,
98052a38012Sejakowatz 							 BMediaNode::run_mode mode)
98152a38012Sejakowatz {
98252a38012Sejakowatz 	CALLED();
98340f36b03Sbeveloper 	if (IS_INVALID_NODE(node))
98452a38012Sejakowatz 		return B_MEDIA_BAD_NODE;
98552a38012Sejakowatz 
986dfb2ad61Sbeveloper 	node_set_run_mode_command msg;
98752a38012Sejakowatz 	msg.mode = mode;
98852a38012Sejakowatz 
98952a38012Sejakowatz 	return write_port(node.port, NODE_SET_RUN_MODE, &msg, sizeof(msg));
99052a38012Sejakowatz }
99152a38012Sejakowatz 
99252a38012Sejakowatz 
99352a38012Sejakowatz status_t
99452a38012Sejakowatz BMediaRoster::PrerollNode(const media_node & node)
99552a38012Sejakowatz {
99652a38012Sejakowatz 	CALLED();
99740f36b03Sbeveloper 	if (IS_INVALID_NODE(node))
99852a38012Sejakowatz 		return B_MEDIA_BAD_NODE;
99952a38012Sejakowatz 
100052a38012Sejakowatz 	char dummy;
100152a38012Sejakowatz 	return write_port(node.port, NODE_PREROLL, &dummy, sizeof(dummy));
100252a38012Sejakowatz }
100352a38012Sejakowatz 
100452a38012Sejakowatz 
100552a38012Sejakowatz status_t
100652a38012Sejakowatz BMediaRoster::RollNode(const media_node & node,
100752a38012Sejakowatz 					   bigtime_t startPerformance,
100852a38012Sejakowatz 					   bigtime_t stopPerformance,
100952a38012Sejakowatz 					   bigtime_t atMediaTime)
101052a38012Sejakowatz {
101152a38012Sejakowatz 	UNIMPLEMENTED();
101252a38012Sejakowatz 	return B_ERROR;
101352a38012Sejakowatz }
101452a38012Sejakowatz 
101552a38012Sejakowatz 
101652a38012Sejakowatz status_t
101752a38012Sejakowatz BMediaRoster::SetProducerRunModeDelay(const media_node & node,
101852a38012Sejakowatz 									  bigtime_t delay,
101952a38012Sejakowatz 									  BMediaNode::run_mode mode)
102052a38012Sejakowatz {
102160f15390Sbeveloper 	CALLED();
102260f15390Sbeveloper 	if (IS_INVALID_NODE(node))
102360f15390Sbeveloper 		return B_MEDIA_BAD_NODE;
102460f15390Sbeveloper 	if ((node.kind & B_BUFFER_PRODUCER) == 0)
102560f15390Sbeveloper 		return B_MEDIA_BAD_NODE;
102660f15390Sbeveloper 
102760f15390Sbeveloper 	producer_set_run_mode_delay_command command;
102860f15390Sbeveloper 	command.mode = mode;
102960f15390Sbeveloper 	command.delay = delay;
103060f15390Sbeveloper 
103160f15390Sbeveloper 	return SendToPort(node.port, PRODUCER_SET_RUN_MODE_DELAY, &command, sizeof(command));
103252a38012Sejakowatz }
103352a38012Sejakowatz 
103452a38012Sejakowatz 
103552a38012Sejakowatz status_t
103652a38012Sejakowatz BMediaRoster::SetProducerRate(const media_node & producer,
103752a38012Sejakowatz 							  int32 numer,
103852a38012Sejakowatz 							  int32 denom)
103952a38012Sejakowatz {
104052a38012Sejakowatz 	CALLED();
104140f36b03Sbeveloper 	if (IS_INVALID_NODE(producer))
104252a38012Sejakowatz 		return B_MEDIA_BAD_NODE;
104352a38012Sejakowatz 	if ((producer.kind & B_BUFFER_PRODUCER) == 0)
104452a38012Sejakowatz 		return B_MEDIA_BAD_NODE;
104552a38012Sejakowatz 
1046dfb2ad61Sbeveloper 	producer_set_play_rate_request msg;
1047dfb2ad61Sbeveloper 	producer_set_play_rate_reply reply;
104852a38012Sejakowatz 	status_t rv;
104952a38012Sejakowatz 	int32 code;
105052a38012Sejakowatz 
105152a38012Sejakowatz 	msg.numer = numer;
105252a38012Sejakowatz 	msg.denom = denom;
105352a38012Sejakowatz 	msg.reply_port = _PortPool->GetPort();
105452a38012Sejakowatz 	rv = write_port(producer.node, PRODUCER_SET_PLAY_RATE, &msg, sizeof(msg));
105552a38012Sejakowatz 	if (rv != B_OK) {
105652a38012Sejakowatz 		_PortPool->PutPort(msg.reply_port);
105752a38012Sejakowatz 		return rv;
105852a38012Sejakowatz 	}
105952a38012Sejakowatz 	rv = read_port(msg.reply_port, &code, &reply, sizeof(reply));
106052a38012Sejakowatz 	_PortPool->PutPort(msg.reply_port);
106152a38012Sejakowatz 	return (rv < B_OK) ? rv : reply.result;
106252a38012Sejakowatz }
106352a38012Sejakowatz 
106452a38012Sejakowatz 
106552a38012Sejakowatz /* Nodes will have available inputs/outputs as long as they are capable */
106652a38012Sejakowatz /* of accepting more connections. The node may create an additional */
106752a38012Sejakowatz /* output or input as the currently available is taken into usage. */
106852a38012Sejakowatz status_t
106952a38012Sejakowatz BMediaRoster::GetLiveNodeInfo(const media_node & node,
107052a38012Sejakowatz 							  live_node_info * out_live_info)
107152a38012Sejakowatz {
10729e9417d2Sbeveloper 	CALLED();
10739e9417d2Sbeveloper 	if (out_live_info == NULL)
10749e9417d2Sbeveloper 		return B_BAD_VALUE;
107540f36b03Sbeveloper 	if (IS_INVALID_NODE(node))
10769e9417d2Sbeveloper 		return B_MEDIA_BAD_NODE;
10779e9417d2Sbeveloper 
10789e9417d2Sbeveloper 	server_get_live_node_info_request request;
10799e9417d2Sbeveloper 	server_get_live_node_info_reply reply;
10809e9417d2Sbeveloper 	status_t rv;
10819e9417d2Sbeveloper 
10829e9417d2Sbeveloper 	request.node = node;
10839e9417d2Sbeveloper 
10841299bfb2Sbeveloper 	rv = QueryServer(SERVER_GET_LIVE_NODE_INFO, &request, sizeof(request), &reply, sizeof(reply));
10859e9417d2Sbeveloper 	if (rv != B_OK)
10869e9417d2Sbeveloper 		return rv;
10879e9417d2Sbeveloper 
10889e9417d2Sbeveloper 	*out_live_info = reply.live_info;
10899e9417d2Sbeveloper 	return B_OK;
109052a38012Sejakowatz }
109152a38012Sejakowatz 
109252a38012Sejakowatz 
109352a38012Sejakowatz status_t
109452a38012Sejakowatz BMediaRoster::GetLiveNodes(live_node_info * out_live_nodes,
109552a38012Sejakowatz 						   int32 * io_total_count,
109652a38012Sejakowatz 						   const media_format * has_input,
109752a38012Sejakowatz 						   const media_format * has_output,
109852a38012Sejakowatz 						   const char * name,
109952a38012Sejakowatz 						   uint64 node_kinds)
110052a38012Sejakowatz {
11019e9417d2Sbeveloper 	CALLED();
11029e9417d2Sbeveloper 	if (out_live_nodes == NULL || io_total_count == NULL)
11039e9417d2Sbeveloper 		return B_BAD_VALUE;
11049e9417d2Sbeveloper 	if (*io_total_count <= 0)
11059e9417d2Sbeveloper 		return B_BAD_VALUE;
11069e9417d2Sbeveloper 
11079e9417d2Sbeveloper 	// XXX we also support the wildcard search as GetDormantNodes does. This needs to be documented
11089e9417d2Sbeveloper 
11099e9417d2Sbeveloper 	server_get_live_nodes_request request;
11109e9417d2Sbeveloper 	server_get_live_nodes_reply reply;
11119e9417d2Sbeveloper 	status_t rv;
11129e9417d2Sbeveloper 
11139e9417d2Sbeveloper 	request.maxcount = *io_total_count;
11149e9417d2Sbeveloper 	request.has_input = (bool) has_input;
11159e9417d2Sbeveloper 	if (has_input)
11169e9417d2Sbeveloper 		request.inputformat = *has_input; // XXX we should not make a flat copy of media_format
11179e9417d2Sbeveloper 	request.has_output = (bool) has_output;
11189e9417d2Sbeveloper 	if (has_output)
11199e9417d2Sbeveloper 		request.outputformat = *has_output; // XXX we should not make a flat copy of media_format
11209e9417d2Sbeveloper 	request.has_name = (bool) name;
11219e9417d2Sbeveloper 	if (name) {
11229e9417d2Sbeveloper 		int len = strlen(name);
11239e9417d2Sbeveloper 		len = min_c(len, (int)sizeof(request.name) - 1);
11249e9417d2Sbeveloper 		memcpy(request.name, name, len);
11259e9417d2Sbeveloper 		request.name[len] = 0;
11269e9417d2Sbeveloper 	}
11279e9417d2Sbeveloper 	request.require_kinds = node_kinds;
11289e9417d2Sbeveloper 
11299e9417d2Sbeveloper 	rv = QueryServer(SERVER_GET_LIVE_NODES, &request, sizeof(request), &reply, sizeof(reply));
11309e9417d2Sbeveloper 	if (rv != B_OK) {
1131353b9f6bSbeveloper 		FATAL("BMediaRoster::GetLiveNodes failed\n");
11321299bfb2Sbeveloper 		*io_total_count = 0;
11339e9417d2Sbeveloper 		return rv;
11349e9417d2Sbeveloper 	}
11359e9417d2Sbeveloper 
11369e9417d2Sbeveloper 	if (reply.count > MAX_LIVE_INFO) {
11379e9417d2Sbeveloper 		live_node_info *live_info;
11389e9417d2Sbeveloper 		area_id clone;
11399e9417d2Sbeveloper 
11409e9417d2Sbeveloper 		clone = clone_area("live_node_info clone", reinterpret_cast<void **>(&live_info), B_ANY_ADDRESS, B_READ_AREA | B_WRITE_AREA, reply.area);
11419e9417d2Sbeveloper 		if (clone < B_OK) {
1142353b9f6bSbeveloper 			FATAL("BMediaRoster::GetLiveNodes failed to clone area, %#lx\n", clone);
11439e9417d2Sbeveloper 			delete_area(reply.area);
11441299bfb2Sbeveloper 			*io_total_count = 0;
114552a38012Sejakowatz 			return B_ERROR;
114652a38012Sejakowatz 		}
114752a38012Sejakowatz 
11489e9417d2Sbeveloper 		for (int32 i = 0; i < reply.count; i++) {
11499e9417d2Sbeveloper 			out_live_nodes[i] = live_info[i];
11509e9417d2Sbeveloper 		}
11519e9417d2Sbeveloper 
11529e9417d2Sbeveloper 		delete_area(clone);
11539e9417d2Sbeveloper 		delete_area(reply.area);
11549e9417d2Sbeveloper 	} else {
11559e9417d2Sbeveloper 		for (int32 i = 0; i < reply.count; i++) {
11569e9417d2Sbeveloper 			out_live_nodes[i] = reply.live_info[i];
11579e9417d2Sbeveloper 		}
11589e9417d2Sbeveloper 	}
11599e9417d2Sbeveloper 	*io_total_count = reply.count;
11609e9417d2Sbeveloper 
11619e9417d2Sbeveloper 	return B_OK;
11629e9417d2Sbeveloper }
11639e9417d2Sbeveloper 
116452a38012Sejakowatz 
116552a38012Sejakowatz status_t
116652a38012Sejakowatz BMediaRoster::GetFreeInputsFor(const media_node & node,
116752a38012Sejakowatz 							   media_input * out_free_inputs,
116852a38012Sejakowatz 							   int32 buf_num_inputs,
116952a38012Sejakowatz 							   int32 * out_total_count,
117052a38012Sejakowatz 							   media_type filter_type)
117152a38012Sejakowatz {
11723620737cSbeveloper 	CALLED();
117340f36b03Sbeveloper 	if (IS_INVALID_NODE(node) || (node.kind & B_BUFFER_CONSUMER) == 0)
11743620737cSbeveloper 		return B_MEDIA_BAD_NODE;
11753620737cSbeveloper 	if (out_free_inputs == NULL || out_total_count == NULL)
11763620737cSbeveloper 		return B_BAD_VALUE;
11773620737cSbeveloper 
117876669a29Sbeveloper 	List<media_input> list;
11793620737cSbeveloper 	media_input *input;
11803620737cSbeveloper 	status_t rv;
11813620737cSbeveloper 
11821299bfb2Sbeveloper 	*out_total_count = 0;
11831299bfb2Sbeveloper 
11848b04ffc1Sbeveloper 	rv = MediaRosterEx(this)->GetAllInputs(node, &list);
11853620737cSbeveloper 	if (B_OK != rv)
11863620737cSbeveloper 		return rv;
11873620737cSbeveloper 
118876669a29Sbeveloper 	int32 i;
118976669a29Sbeveloper 	for (i = 0, list.Rewind(); list.GetNext(&input); i++) {
11903620737cSbeveloper 		if (filter_type != B_MEDIA_UNKNOWN_TYPE && filter_type != input->format.type)
11913620737cSbeveloper 			continue; // media_type used, but doesn't match
11923620737cSbeveloper 		if (input->source != media_source::null)
11933620737cSbeveloper 			continue; // consumer source already connected
11943620737cSbeveloper 		out_free_inputs[i] = *input;
11953620737cSbeveloper 		*out_total_count += 1;
11963620737cSbeveloper 		buf_num_inputs -= 1;
11973620737cSbeveloper 		if (buf_num_inputs == 0)
11983620737cSbeveloper 			break;
11993620737cSbeveloper 	}
12003620737cSbeveloper 
12018b04ffc1Sbeveloper 	MediaRosterEx(this)->PublishInputs(node, &list);
12023620737cSbeveloper 	return B_OK;
120352a38012Sejakowatz }
120452a38012Sejakowatz 
120552a38012Sejakowatz 
120652a38012Sejakowatz status_t
120752a38012Sejakowatz BMediaRoster::GetConnectedInputsFor(const media_node & node,
120852a38012Sejakowatz 									media_input * out_active_inputs,
120952a38012Sejakowatz 									int32 buf_num_inputs,
121052a38012Sejakowatz 									int32 * out_total_count)
121152a38012Sejakowatz {
12123620737cSbeveloper 	CALLED();
121340f36b03Sbeveloper 	if (IS_INVALID_NODE(node) || (node.kind & B_BUFFER_CONSUMER) == 0)
12143620737cSbeveloper 		return B_MEDIA_BAD_NODE;
12153620737cSbeveloper 	if (out_active_inputs == NULL || out_total_count == NULL)
12163620737cSbeveloper 		return B_BAD_VALUE;
12173620737cSbeveloper 
121876669a29Sbeveloper 	List<media_input> list;
12193620737cSbeveloper 	media_input *input;
12203620737cSbeveloper 	status_t rv;
12213620737cSbeveloper 
12221299bfb2Sbeveloper 	*out_total_count = 0;
12231299bfb2Sbeveloper 
12248b04ffc1Sbeveloper 	rv = MediaRosterEx(this)->GetAllInputs(node, &list);
12253620737cSbeveloper 	if (B_OK != rv)
12263620737cSbeveloper 		return rv;
12273620737cSbeveloper 
122876669a29Sbeveloper 	int32 i;
122976669a29Sbeveloper 	for (i = 0, list.Rewind(); list.GetNext(&input); i++) {
12303620737cSbeveloper 		if (input->source == media_source::null)
12313620737cSbeveloper 			continue; // consumer source not connected
12323620737cSbeveloper 		out_active_inputs[i] = *input;
12333620737cSbeveloper 		*out_total_count += 1;
12343620737cSbeveloper 		buf_num_inputs -= 1;
12353620737cSbeveloper 		if (buf_num_inputs == 0)
12363620737cSbeveloper 			break;
12373620737cSbeveloper 	}
12383620737cSbeveloper 
12398b04ffc1Sbeveloper 	MediaRosterEx(this)->PublishInputs(node, &list);
12403620737cSbeveloper 	return B_OK;
124152a38012Sejakowatz }
124252a38012Sejakowatz 
124352a38012Sejakowatz 
124452a38012Sejakowatz status_t
124552a38012Sejakowatz BMediaRoster::GetAllInputsFor(const media_node & node,
124652a38012Sejakowatz 							  media_input * out_inputs,
124752a38012Sejakowatz 							  int32 buf_num_inputs,
124852a38012Sejakowatz 							  int32 * out_total_count)
124952a38012Sejakowatz {
125052a38012Sejakowatz 	CALLED();
125140f36b03Sbeveloper 	if (IS_INVALID_NODE(node) || (node.kind & B_BUFFER_CONSUMER) == 0)
125252a38012Sejakowatz 		return B_MEDIA_BAD_NODE;
125352a38012Sejakowatz 	if (out_inputs == NULL || out_total_count == NULL)
125452a38012Sejakowatz 		return B_BAD_VALUE;
125552a38012Sejakowatz 
125676669a29Sbeveloper 	List<media_input> list;
12573620737cSbeveloper 	media_input *input;
125852a38012Sejakowatz 	status_t rv;
125952a38012Sejakowatz 
12601299bfb2Sbeveloper 	*out_total_count = 0;
12611299bfb2Sbeveloper 
12628b04ffc1Sbeveloper 	rv = MediaRosterEx(this)->GetAllInputs(node, &list);
12633620737cSbeveloper 	if (B_OK != rv)
12643620737cSbeveloper 		return rv;
12653620737cSbeveloper 
126676669a29Sbeveloper 	int32 i;
126776669a29Sbeveloper 	for (i = 0, list.Rewind(); list.GetNext(&input); i++) {
12683620737cSbeveloper 		out_inputs[i] = *input;
126952a38012Sejakowatz 		*out_total_count += 1;
12703620737cSbeveloper 		buf_num_inputs -= 1;
12713620737cSbeveloper 		if (buf_num_inputs == 0)
12723620737cSbeveloper 			break;
127352a38012Sejakowatz 	}
127452a38012Sejakowatz 
12758b04ffc1Sbeveloper 	MediaRosterEx(this)->PublishInputs(node, &list);
12763620737cSbeveloper 	return B_OK;
127752a38012Sejakowatz }
127852a38012Sejakowatz 
127952a38012Sejakowatz 
128052a38012Sejakowatz status_t
128152a38012Sejakowatz BMediaRoster::GetFreeOutputsFor(const media_node & node,
128252a38012Sejakowatz 								media_output * out_free_outputs,
128352a38012Sejakowatz 								int32 buf_num_outputs,
128452a38012Sejakowatz 								int32 * out_total_count,
128552a38012Sejakowatz 								media_type filter_type)
128652a38012Sejakowatz {
12873620737cSbeveloper 	CALLED();
128840f36b03Sbeveloper 	if (IS_INVALID_NODE(node) || (node.kind & B_BUFFER_PRODUCER) == 0)
12893620737cSbeveloper 		return B_MEDIA_BAD_NODE;
12903620737cSbeveloper 	if (out_free_outputs == NULL || out_total_count == NULL)
12913620737cSbeveloper 		return B_BAD_VALUE;
12923620737cSbeveloper 
129376669a29Sbeveloper 	List<media_output> list;
12943620737cSbeveloper 	media_output *output;
12953620737cSbeveloper 	status_t rv;
12963620737cSbeveloper 
12971299bfb2Sbeveloper 	*out_total_count = 0;
12981299bfb2Sbeveloper 
12998b04ffc1Sbeveloper 	rv = MediaRosterEx(this)->GetAllOutputs(node, &list);
13003620737cSbeveloper 	if (B_OK != rv)
13013620737cSbeveloper 		return rv;
13023620737cSbeveloper 
130376669a29Sbeveloper 	int32 i;
130476669a29Sbeveloper 	for (i = 0, list.Rewind(); list.GetNext(&output); i++) {
13053620737cSbeveloper 		if (filter_type != B_MEDIA_UNKNOWN_TYPE && filter_type != output->format.type)
13063620737cSbeveloper 			continue; // media_type used, but doesn't match
13073620737cSbeveloper 		if (output->destination != media_destination::null)
13083620737cSbeveloper 			continue; // producer destination already connected
13093620737cSbeveloper 		out_free_outputs[i] = *output;
13103620737cSbeveloper 		*out_total_count += 1;
13113620737cSbeveloper 		buf_num_outputs -= 1;
13123620737cSbeveloper 		if (buf_num_outputs == 0)
13133620737cSbeveloper 			break;
13143620737cSbeveloper 	}
13153620737cSbeveloper 
13168b04ffc1Sbeveloper 	MediaRosterEx(this)->PublishOutputs(node, &list);
13173620737cSbeveloper 	return B_OK;
131852a38012Sejakowatz }
131952a38012Sejakowatz 
132052a38012Sejakowatz 
132152a38012Sejakowatz status_t
132252a38012Sejakowatz BMediaRoster::GetConnectedOutputsFor(const media_node & node,
132352a38012Sejakowatz 									 media_output * out_active_outputs,
132452a38012Sejakowatz 									 int32 buf_num_outputs,
132552a38012Sejakowatz 									 int32 * out_total_count)
132652a38012Sejakowatz {
13273620737cSbeveloper 	CALLED();
132840f36b03Sbeveloper 	if (IS_INVALID_NODE(node) || (node.kind & B_BUFFER_PRODUCER) == 0)
13293620737cSbeveloper 		return B_MEDIA_BAD_NODE;
13303620737cSbeveloper 	if (out_active_outputs == NULL || out_total_count == NULL)
13313620737cSbeveloper 		return B_BAD_VALUE;
13323620737cSbeveloper 
133376669a29Sbeveloper 	List<media_output> list;
13343620737cSbeveloper 	media_output *output;
13353620737cSbeveloper 	status_t rv;
13363620737cSbeveloper 
13371299bfb2Sbeveloper 	*out_total_count = 0;
13381299bfb2Sbeveloper 
13398b04ffc1Sbeveloper 	rv = MediaRosterEx(this)->GetAllOutputs(node, &list);
13403620737cSbeveloper 	if (B_OK != rv)
13413620737cSbeveloper 		return rv;
13423620737cSbeveloper 
134376669a29Sbeveloper 	int32 i;
134476669a29Sbeveloper 	for (i = 0, list.Rewind(); list.GetNext(&output); i++) {
13453620737cSbeveloper 		if (output->destination == media_destination::null)
13463620737cSbeveloper 			continue; // producer destination not connected
13473620737cSbeveloper 		out_active_outputs[i] = *output;
13483620737cSbeveloper 		*out_total_count += 1;
13493620737cSbeveloper 		buf_num_outputs -= 1;
13503620737cSbeveloper 		if (buf_num_outputs == 0)
13513620737cSbeveloper 			break;
13523620737cSbeveloper 	}
13533620737cSbeveloper 
13548b04ffc1Sbeveloper 	MediaRosterEx(this)->PublishOutputs(node, &list);
13553620737cSbeveloper 	return B_OK;
135652a38012Sejakowatz }
135752a38012Sejakowatz 
135852a38012Sejakowatz 
135952a38012Sejakowatz status_t
136052a38012Sejakowatz BMediaRoster::GetAllOutputsFor(const media_node & node,
136152a38012Sejakowatz 							   media_output * out_outputs,
136252a38012Sejakowatz 							   int32 buf_num_outputs,
136352a38012Sejakowatz 							   int32 * out_total_count)
136452a38012Sejakowatz {
136552a38012Sejakowatz 	CALLED();
136640f36b03Sbeveloper 	if (IS_INVALID_NODE(node) || (node.kind & B_BUFFER_PRODUCER) == 0)
136752a38012Sejakowatz 		return B_MEDIA_BAD_NODE;
136852a38012Sejakowatz 	if (out_outputs == NULL || out_total_count == NULL)
136952a38012Sejakowatz 		return B_BAD_VALUE;
137052a38012Sejakowatz 
137176669a29Sbeveloper 	List<media_output> list;
13723620737cSbeveloper 	media_output *output;
137352a38012Sejakowatz 	status_t rv;
137452a38012Sejakowatz 
13751299bfb2Sbeveloper 	*out_total_count = 0;
13761299bfb2Sbeveloper 
13778b04ffc1Sbeveloper 	rv = MediaRosterEx(this)->GetAllOutputs(node, &list);
13783620737cSbeveloper 	if (B_OK != rv)
13793620737cSbeveloper 		return rv;
13803620737cSbeveloper 
138176669a29Sbeveloper 	int32 i;
138276669a29Sbeveloper 	for (i = 0, list.Rewind(); list.GetNext(&output); i++) {
13833620737cSbeveloper 		out_outputs[i] = *output;
138452a38012Sejakowatz 		*out_total_count += 1;
13853620737cSbeveloper 		buf_num_outputs -= 1;
13863620737cSbeveloper 		if (buf_num_outputs == 0)
13873620737cSbeveloper 			break;
138852a38012Sejakowatz 	}
138952a38012Sejakowatz 
13908b04ffc1Sbeveloper 	MediaRosterEx(this)->PublishOutputs(node, &list);
13913620737cSbeveloper 	return B_OK;
139252a38012Sejakowatz }
139352a38012Sejakowatz 
139452a38012Sejakowatz 
139552a38012Sejakowatz status_t
139652a38012Sejakowatz BMediaRoster::StartWatching(const BMessenger & where)
139752a38012Sejakowatz {
1398eae26d3dSbeveloper 	CALLED();
1399eae26d3dSbeveloper 	if (!where.IsValid()) {
1400353b9f6bSbeveloper 		FATAL("BMediaRoster::StartWatching: messenger invalid!\n");
1401eae26d3dSbeveloper 		return B_BAD_VALUE;
1402eae26d3dSbeveloper 	}
1403f4925104Sbeveloper 	return BPrivate::media::notifications::Register(where, media_node::null, B_MEDIA_WILDCARD);
140452a38012Sejakowatz }
140552a38012Sejakowatz 
140652a38012Sejakowatz 
140752a38012Sejakowatz status_t
140852a38012Sejakowatz BMediaRoster::StartWatching(const BMessenger & where,
140952a38012Sejakowatz 							int32 notificationType)
141052a38012Sejakowatz {
1411eae26d3dSbeveloper 	CALLED();
1412eae26d3dSbeveloper 	if (!where.IsValid()) {
1413353b9f6bSbeveloper 		FATAL("BMediaRoster::StartWatching: messenger invalid!\n");
1414eae26d3dSbeveloper 		return B_BAD_VALUE;
1415eae26d3dSbeveloper 	}
1416f4925104Sbeveloper 	if (false == BPrivate::media::notifications::IsValidNotificationRequest(false, notificationType)) {
1417353b9f6bSbeveloper 		FATAL("BMediaRoster::StartWatching: notificationType invalid!\n");
1418eae26d3dSbeveloper 		return B_BAD_VALUE;
1419eae26d3dSbeveloper 	}
1420f4925104Sbeveloper 	return BPrivate::media::notifications::Register(where, media_node::null, notificationType);
142152a38012Sejakowatz }
142252a38012Sejakowatz 
142352a38012Sejakowatz 
142452a38012Sejakowatz status_t
142552a38012Sejakowatz BMediaRoster::StartWatching(const BMessenger & where,
142652a38012Sejakowatz 							const media_node & node,
142752a38012Sejakowatz 							int32 notificationType)
142852a38012Sejakowatz {
1429eae26d3dSbeveloper 	CALLED();
1430eae26d3dSbeveloper 	if (!where.IsValid()) {
1431353b9f6bSbeveloper 		FATAL("BMediaRoster::StartWatching: messenger invalid!\n");
1432eae26d3dSbeveloper 		return B_BAD_VALUE;
1433eae26d3dSbeveloper 	}
143440f36b03Sbeveloper 	if (IS_INVALID_NODE(node)) {
1435353b9f6bSbeveloper 		FATAL("BMediaRoster::StartWatching: node invalid!\n");
1436eae26d3dSbeveloper 		return B_MEDIA_BAD_NODE;
1437eae26d3dSbeveloper 	}
1438f4925104Sbeveloper 	if (false == BPrivate::media::notifications::IsValidNotificationRequest(true, notificationType)) {
1439353b9f6bSbeveloper 		FATAL("BMediaRoster::StartWatching: notificationType invalid!\n");
1440eae26d3dSbeveloper 		return B_BAD_VALUE;
1441eae26d3dSbeveloper 	}
1442f4925104Sbeveloper 	return BPrivate::media::notifications::Register(where, node, notificationType);
144352a38012Sejakowatz }
144452a38012Sejakowatz 
144552a38012Sejakowatz 
144652a38012Sejakowatz status_t
144752a38012Sejakowatz BMediaRoster::StopWatching(const BMessenger & where)
144852a38012Sejakowatz {
1449eae26d3dSbeveloper 	CALLED();
1450eae26d3dSbeveloper 	// messenger may already be invalid, so we don't check this
1451f4925104Sbeveloper 	return BPrivate::media::notifications::Unregister(where, media_node::null, B_MEDIA_WILDCARD);
145252a38012Sejakowatz }
145352a38012Sejakowatz 
145452a38012Sejakowatz 
145552a38012Sejakowatz status_t
145652a38012Sejakowatz BMediaRoster::StopWatching(const BMessenger & where,
145752a38012Sejakowatz 						   int32 notificationType)
145852a38012Sejakowatz {
1459eae26d3dSbeveloper 	CALLED();
1460eae26d3dSbeveloper 	// messenger may already be invalid, so we don't check this
1461f4925104Sbeveloper 	if (false == BPrivate::media::notifications::IsValidNotificationRequest(false, notificationType)) {
1462353b9f6bSbeveloper 		FATAL("BMediaRoster::StopWatching: notificationType invalid!\n");
1463eae26d3dSbeveloper 		return B_BAD_VALUE;
1464eae26d3dSbeveloper 	}
1465f4925104Sbeveloper 	return BPrivate::media::notifications::Unregister(where, media_node::null, notificationType);
146652a38012Sejakowatz }
146752a38012Sejakowatz 
146852a38012Sejakowatz 
146952a38012Sejakowatz status_t
147052a38012Sejakowatz BMediaRoster::StopWatching(const BMessenger & where,
147152a38012Sejakowatz 						   const media_node & node,
147252a38012Sejakowatz 						   int32 notificationType)
147352a38012Sejakowatz {
1474eae26d3dSbeveloper 	CALLED();
1475eae26d3dSbeveloper 	// messenger may already be invalid, so we don't check this
147640f36b03Sbeveloper 	if (IS_INVALID_NODE(node)) {
1477353b9f6bSbeveloper 		FATAL("BMediaRoster::StopWatching: node invalid!\n");
1478eae26d3dSbeveloper 		return B_MEDIA_BAD_NODE;
1479eae26d3dSbeveloper 	}
1480f4925104Sbeveloper 	if (false == BPrivate::media::notifications::IsValidNotificationRequest(true, notificationType)) {
1481353b9f6bSbeveloper 		FATAL("BMediaRoster::StopWatching: notificationType invalid!\n");
1482eae26d3dSbeveloper 		return B_BAD_VALUE;
1483eae26d3dSbeveloper 	}
1484f4925104Sbeveloper 	return BPrivate::media::notifications::Unregister(where, node, notificationType);
148552a38012Sejakowatz }
148652a38012Sejakowatz 
148752a38012Sejakowatz 
148852a38012Sejakowatz status_t
148952a38012Sejakowatz BMediaRoster::RegisterNode(BMediaNode * node)
149052a38012Sejakowatz {
149154187cc6Sbeveloper 	CALLED();
149254187cc6Sbeveloper 	// addon-id = -1 (unused), addon-flavor-id = 0 (unused, too)
149354187cc6Sbeveloper 	return MediaRosterEx(this)->RegisterNode(node, -1, 0);
149454187cc6Sbeveloper }
149554187cc6Sbeveloper 
149654187cc6Sbeveloper 
149754187cc6Sbeveloper status_t
149854187cc6Sbeveloper BMediaRosterEx::RegisterNode(BMediaNode * node, media_addon_id addonid, int32 flavorid)
149954187cc6Sbeveloper {
150052a38012Sejakowatz 	CALLED();
150152a38012Sejakowatz 	if (node == NULL)
150252a38012Sejakowatz 		return B_BAD_VALUE;
150352a38012Sejakowatz 
150454187cc6Sbeveloper 	// some sanity check
150554187cc6Sbeveloper 	// I'm not sure if the media kit warrants to call BMediaNode::AddOn() here.
150654187cc6Sbeveloper 	// Perhaps we don't need it.
150754187cc6Sbeveloper 	{
15089e9417d2Sbeveloper 		BMediaAddOn *addon;
15099e9417d2Sbeveloper 		int32 addon_flavor_id;
15109e9417d2Sbeveloper 		media_addon_id addon_id;
15119e9417d2Sbeveloper 		addon_flavor_id = 0;
15129e9417d2Sbeveloper 		addon = node->AddOn(&addon_flavor_id);
15139e9417d2Sbeveloper 		addon_id = addon ? addon->AddonID() : -1;
151454187cc6Sbeveloper 		ASSERT(addonid == addon_id);
151554187cc6Sbeveloper 		ASSERT(flavorid == addon_flavor_id);
151654187cc6Sbeveloper 	}
151752a38012Sejakowatz 
151854187cc6Sbeveloper 	status_t rv;
15199e9417d2Sbeveloper 	server_register_node_request request;
15209e9417d2Sbeveloper 	server_register_node_reply reply;
15219e9417d2Sbeveloper 
152254187cc6Sbeveloper 	request.addon_id = addonid;
152354187cc6Sbeveloper 	request.addon_flavor_id = flavorid;
15249e9417d2Sbeveloper 	strcpy(request.name, node->Name());
15259e9417d2Sbeveloper 	request.kinds = node->Kinds();
15269e9417d2Sbeveloper 	request.port = node->ControlPort();
15279e9417d2Sbeveloper 	request.team = team;
15289e9417d2Sbeveloper 
15298b04ffc1Sbeveloper 	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);
15301299bfb2Sbeveloper 
15319e9417d2Sbeveloper 	rv = QueryServer(SERVER_REGISTER_NODE, &request, sizeof(request), &reply, sizeof(reply));
15329e9417d2Sbeveloper 	if (rv != B_OK) {
1533353b9f6bSbeveloper 		FATAL("BMediaRoster::RegisterNode: failed to register node %s (error %#lx)\n", node->Name(), rv);
15349e9417d2Sbeveloper 		return rv;
15359e9417d2Sbeveloper 	}
15369e9417d2Sbeveloper 
15378b04ffc1Sbeveloper 	// we are a friend class of BMediaNode and initialize this member variable
15389e9417d2Sbeveloper 	node->fNodeID = reply.nodeid;
15399e9417d2Sbeveloper 	ASSERT(reply.nodeid == node->Node().node);
15409e9417d2Sbeveloper 	ASSERT(reply.nodeid == node->ID());
15419e9417d2Sbeveloper 
15429e9417d2Sbeveloper 	// call the callback
15439e9417d2Sbeveloper 	node->NodeRegistered();
15443620737cSbeveloper 
15450e21b167Sbeveloper 	// if the BMediaNode also inherits from BTimeSource, we need to call BTimeSource::FinishCreate()
15460e21b167Sbeveloper 	if (node->Kinds() & B_TIME_SOURCE) {
15470e21b167Sbeveloper 		BTimeSource *ts;
15480e21b167Sbeveloper 		ts = dynamic_cast<BTimeSource *>(node);
15490e21b167Sbeveloper 		if (ts)
15500e21b167Sbeveloper 			ts->FinishCreate();
15510e21b167Sbeveloper 	}
15520e21b167Sbeveloper 
1553*359ac306Sbeveloper 	// XXX XXX XXX
1554*359ac306Sbeveloper 	// Calling GetAllOutputs and GetAllInputs here,
1555*359ac306Sbeveloper 	// followed by PublishOutputs and PublishInputs,
1556*359ac306Sbeveloper 	// does not work, it is too early, and in some
1557*359ac306Sbeveloper 	// cases it will deadlock the node control thread.
1558*359ac306Sbeveloper 
1559*359ac306Sbeveloper 	// Posting a message to the roster thread here
1560*359ac306Sbeveloper 	// is also to early, the multi_audio add-on will
1561*359ac306Sbeveloper 	// no list any inputs
1562*359ac306Sbeveloper 	// XXX XXX XXX
1563*359ac306Sbeveloper 
1564*359ac306Sbeveloper /*
1565*359ac306Sbeveloper 	BMessage msg(NODE_PUBLISH_CONNECTIONS);
1566*359ac306Sbeveloper 	media_node tempnode;
1567*359ac306Sbeveloper 	tempnode = node->Node();
1568*359ac306Sbeveloper 	msg.AddData("node", B_RAW_TYPE, &tempnode, sizeof(tempnode));
1569*359ac306Sbeveloper 	PostMessage(&msg);
1570*359ac306Sbeveloper */
1571570f7d04Sbeveloper /*
15723620737cSbeveloper 	// register existing inputs and outputs with the
15733620737cSbeveloper 	// media_server, this allows GetLiveNodes() to work
15743620737cSbeveloper 	// with created, but unconnected nodes.
15753620737cSbeveloper 	if (node->Kinds() & B_BUFFER_PRODUCER) {
1576*359ac306Sbeveloper 		List<media_output> list;
1577*359ac306Sbeveloper 		if (B_OK == GetAllOutputs(node->Node(), &list))
1578*359ac306Sbeveloper 			PublishOutputs(node->Node(), &list);
15793620737cSbeveloper 	} else if (node->Kinds() & B_BUFFER_CONSUMER) {
1580*359ac306Sbeveloper 		List<media_input> list;
1581*359ac306Sbeveloper 		if (B_OK == GetAllInputs(node->Node(), &list))
1582*359ac306Sbeveloper 			PublishInputs(node->Node(), &list);
15833620737cSbeveloper 	}
1584570f7d04Sbeveloper */
15851299bfb2Sbeveloper 	BPrivate::media::notifications::NodesCreated(&reply.nodeid, 1);
1586570f7d04Sbeveloper /*
1587570f7d04Sbeveloper 	TRACE("BMediaRoster::RegisterNode: registered node name '%s', id %ld, addon %ld, flavor %ld\n", node->Name(), node->ID(), addon_id, addon_flavor_id);
1588570f7d04Sbeveloper 	TRACE("BMediaRoster::RegisterNode: node this               %p\n", node);
1589570f7d04Sbeveloper 	TRACE("BMediaRoster::RegisterNode: node fConsumerThis      %p\n", node->fConsumerThis);
1590570f7d04Sbeveloper 	TRACE("BMediaRoster::RegisterNode: node fProducerThis      %p\n", node->fProducerThis);
1591570f7d04Sbeveloper 	TRACE("BMediaRoster::RegisterNode: node fFileInterfaceThis %p\n", node->fFileInterfaceThis);
1592570f7d04Sbeveloper 	TRACE("BMediaRoster::RegisterNode: node fControllableThis  %p\n", node->fControllableThis);
1593570f7d04Sbeveloper 	TRACE("BMediaRoster::RegisterNode: node fTimeSourceThis    %p\n", node->fTimeSourceThis);
1594570f7d04Sbeveloper */
15959e9417d2Sbeveloper 
15969e9417d2Sbeveloper 	return B_OK;
159752a38012Sejakowatz }
159852a38012Sejakowatz 
159952a38012Sejakowatz 
160052a38012Sejakowatz status_t
160152a38012Sejakowatz BMediaRoster::UnregisterNode(BMediaNode * node)
160252a38012Sejakowatz {
16039e9417d2Sbeveloper 	CALLED();
16049e9417d2Sbeveloper 	if (node == NULL)
16059e9417d2Sbeveloper 		return B_BAD_VALUE;
16069e9417d2Sbeveloper 
160760f15390Sbeveloper 	TRACE("BMediaRoster::UnregisterNode %ld (%p)\n", node->ID(), node);
160860f15390Sbeveloper 
160986bce45bSbeveloper 	if (node->fKinds & NODE_KIND_NO_REFCOUNTING) {
161086bce45bSbeveloper 		printf("BMediaRoster::UnregisterNode, trying to unregister reference counting disabled timesource, node %ld, port %ld, team %ld\n", node->ID(), node->ControlPort(), team);
161186bce45bSbeveloper 		return B_OK;
161286bce45bSbeveloper 	}
16138b04ffc1Sbeveloper 	if (node->ID() == NODE_UNREGISTERED_ID) {
16148b04ffc1Sbeveloper 		FATAL("BMediaRoster::UnregisterNode: Warning node id %ld, name '%s' already unregistered\n", node->ID(), node->Name());
16159e9417d2Sbeveloper 		return B_OK;
16169e9417d2Sbeveloper 	}
161754187cc6Sbeveloper 	if (node->fRefCount != 0) {
161854187cc6Sbeveloper 		FATAL("BMediaRoster::UnregisterNode: Warning node id %ld, name '%s' has local reference count of %ld\n", node->ID(), node->Name(), node->fRefCount);
161954187cc6Sbeveloper 		// no return here, we continue and unregister!
162054187cc6Sbeveloper 	}
162154187cc6Sbeveloper 
162254187cc6Sbeveloper 	// Calling BMediaAddOn::GetConfigurationFor(BMediaNode *node, BMessage *config)
162354187cc6Sbeveloper 	// if this node was instanciated by an add-on needs to be done *somewhere*
162454187cc6Sbeveloper 	// We can't do it here because it is already to late (destructor of the node
162554187cc6Sbeveloper 	// might have been called).
16269e9417d2Sbeveloper 
16279e9417d2Sbeveloper 	server_unregister_node_request request;
16289e9417d2Sbeveloper 	server_unregister_node_reply reply;
16299e9417d2Sbeveloper 	status_t rv;
16309e9417d2Sbeveloper 
16319e9417d2Sbeveloper 	request.nodeid = node->ID();
16329e9417d2Sbeveloper 	request.team = team;
16339e9417d2Sbeveloper 
16341299bfb2Sbeveloper 	// send a notification
16351299bfb2Sbeveloper 	BPrivate::media::notifications::NodesDeleted(&request.nodeid, 1);
16361299bfb2Sbeveloper 
16379e9417d2Sbeveloper 	rv = QueryServer(SERVER_UNREGISTER_NODE, &request, sizeof(request), &reply, sizeof(reply));
16389e9417d2Sbeveloper 	if (rv != B_OK) {
16398b04ffc1Sbeveloper 		FATAL("BMediaRoster::UnregisterNode: failed to unregister node id %ld, name '%s' (error %#lx)\n", node->ID(), node->Name(), rv);
16409e9417d2Sbeveloper 		return rv;
16419e9417d2Sbeveloper 	}
16429e9417d2Sbeveloper 
164354187cc6Sbeveloper 	if (reply.addonid != -1) {
164454187cc6Sbeveloper 		// Small problem here, we can't use DormantNodeManager::PutAddon(), as
164554187cc6Sbeveloper 		// UnregisterNode() is called by a dormant node itself (by the destructor).
164654187cc6Sbeveloper 		// The add-on that contains the node needs to remain in memory until the
164754187cc6Sbeveloper 		// destructor execution is finished.
164854187cc6Sbeveloper 		// DormantNodeManager::PutAddonDelayed() will delay unloading.
164954187cc6Sbeveloper 		_DormantNodeManager->PutAddonDelayed(reply.addonid);
1650cf4e2277Sbeveloper 
165173794717Sbeveloper 		rv = MediaRosterEx(this)->DecrementAddonFlavorInstancesCount(reply.addonid, reply.flavorid);
165254187cc6Sbeveloper 		if (rv != B_OK) {
165373794717Sbeveloper 			FATAL("BMediaRoster::UnregisterNode: DecrementAddonFlavorInstancesCount failed\n");
165454187cc6Sbeveloper 			// this is really a problem, but we can't fail now
165554187cc6Sbeveloper 		}
16568b04ffc1Sbeveloper 	}
16579e9417d2Sbeveloper 
16581299bfb2Sbeveloper 	// we are a friend class of BMediaNode and invalidate this member variable
16598b04ffc1Sbeveloper 	node->fNodeID = NODE_UNREGISTERED_ID;
16609e9417d2Sbeveloper 
16619e9417d2Sbeveloper 	return B_OK;
166252a38012Sejakowatz }
166352a38012Sejakowatz 
166452a38012Sejakowatz 
166552a38012Sejakowatz //	thread safe for multiple calls to Roster()
166652a38012Sejakowatz /* static */ BMediaRoster *
166752a38012Sejakowatz BMediaRoster::Roster(status_t* out_error)
166852a38012Sejakowatz {
166952a38012Sejakowatz 	static BLocker locker("BMediaRoster::Roster locker");
167052a38012Sejakowatz 	locker.Lock();
167152a38012Sejakowatz 	if (_sDefault == NULL) {
16728b04ffc1Sbeveloper 		_sDefault = new BMediaRosterEx();
167352a38012Sejakowatz 		if (out_error != NULL)
167452a38012Sejakowatz 			*out_error = B_OK;
167552a38012Sejakowatz 	} else {
167652a38012Sejakowatz 		if (out_error != NULL)
167752a38012Sejakowatz 			*out_error = B_OK;
167852a38012Sejakowatz 	}
167952a38012Sejakowatz 	locker.Unlock();
168052a38012Sejakowatz 	return _sDefault;
168152a38012Sejakowatz }
168252a38012Sejakowatz 
168352a38012Sejakowatz 
168452a38012Sejakowatz //	won't create it if there isn't one
168552a38012Sejakowatz //	not thread safe if you call Roster() at the same time
168652a38012Sejakowatz /* static */ BMediaRoster *
168752a38012Sejakowatz BMediaRoster::CurrentRoster()
168852a38012Sejakowatz {
168952a38012Sejakowatz 	return _sDefault;
169052a38012Sejakowatz }
169152a38012Sejakowatz 
169252a38012Sejakowatz 
169352a38012Sejakowatz status_t
169452a38012Sejakowatz BMediaRoster::SetTimeSourceFor(media_node_id node,
169552a38012Sejakowatz 							   media_node_id time_source)
169652a38012Sejakowatz {
1697aac800c2Sbeveloper 	CALLED();
169840f36b03Sbeveloper 	if (IS_INVALID_NODEID(node) || IS_INVALID_NODEID(time_source))
1699aac800c2Sbeveloper 		return B_BAD_VALUE;
1700aac800c2Sbeveloper 
1701aac800c2Sbeveloper 	media_node clone;
1702aac800c2Sbeveloper 	status_t rv, result;
1703aac800c2Sbeveloper 
170486bce45bSbeveloper 	// we need to get a clone of the node to have a port id
1705aac800c2Sbeveloper 	rv = GetNodeFor(node, &clone);
1706aac800c2Sbeveloper 	if (rv != B_OK) {
1707aac800c2Sbeveloper 		FATAL("BMediaRoster::SetTimeSourceFor, GetNodeFor failed, node id %ld\n", node);
170852a38012Sejakowatz 		return B_ERROR;
170952a38012Sejakowatz 	}
171052a38012Sejakowatz 
171160f15390Sbeveloper 	TRACE("BMediaRoster::SetTimeSourceFor: node %ld will be assigned time source %ld\n", node, time_source);
171286bce45bSbeveloper 
171386bce45bSbeveloper 	// we just send the request to set time_source-id as timesource to the node,
171486bce45bSbeveloper 	// the NODE_SET_TIMESOURCE handler code will do the real assignment
1715aac800c2Sbeveloper 	result = B_OK;
1716aac800c2Sbeveloper 	node_set_timesource_command cmd;
1717aac800c2Sbeveloper 	cmd.timesource_id = time_source;
1718aac800c2Sbeveloper 	rv = SendToPort(clone.port, NODE_SET_TIMESOURCE, &cmd, sizeof(cmd));
1719aac800c2Sbeveloper 	if (rv != B_OK) {
1720aac800c2Sbeveloper 		FATAL("BMediaRoster::SetTimeSourceFor, sending NODE_SET_TIMESOURCE failed, node id %ld\n", node);
1721aac800c2Sbeveloper 		result = B_ERROR;
1722aac800c2Sbeveloper 	}
1723aac800c2Sbeveloper 
172460f15390Sbeveloper 	// we release the clone
1725aac800c2Sbeveloper 	rv = ReleaseNode(clone);
1726aac800c2Sbeveloper 	if (rv != B_OK) {
1727aac800c2Sbeveloper 		FATAL("BMediaRoster::SetTimeSourceFor, ReleaseNode failed, node id %ld\n", node);
1728aac800c2Sbeveloper 		result = B_ERROR;
1729aac800c2Sbeveloper 	}
1730aac800c2Sbeveloper 
1731aac800c2Sbeveloper 	return result;
1732aac800c2Sbeveloper }
1733aac800c2Sbeveloper 
173452a38012Sejakowatz 
173552a38012Sejakowatz status_t
173652a38012Sejakowatz BMediaRoster::GetParameterWebFor(const media_node & node,
173752a38012Sejakowatz 								 BParameterWeb ** out_web)
173852a38012Sejakowatz {
173928ad138aSbeveloper 	CALLED();
174028ad138aSbeveloper 	if (out_web == NULL)
174128ad138aSbeveloper 		return B_BAD_VALUE;
174228ad138aSbeveloper 	if (IS_INVALID_NODE(node))
174328ad138aSbeveloper 		return B_MEDIA_BAD_NODE;
174428ad138aSbeveloper 	if ((node.kind & B_CONTROLLABLE) == 0)
174528ad138aSbeveloper 		return B_MEDIA_BAD_NODE;
174628ad138aSbeveloper 
174728ad138aSbeveloper 	controllable_get_parameter_web_request request;
174828ad138aSbeveloper 	controllable_get_parameter_web_reply reply;
174928ad138aSbeveloper 	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};
175028ad138aSbeveloper 	int32 size;
175128ad138aSbeveloper 
175228ad138aSbeveloper 	// XXX it might be better to query the node for the (current) parameter size first
175328ad138aSbeveloper 	for (int i = 0; (size = requestsize[i]) != 0; i++) {
175428ad138aSbeveloper 		status_t rv;
175528ad138aSbeveloper 		area_id area;
175628ad138aSbeveloper 		void *data;
175728ad138aSbeveloper 		area = create_area("parameter web data", &data, B_ANY_ADDRESS, size, B_NO_LOCK, B_READ_AREA | B_WRITE_AREA);
175828ad138aSbeveloper 		if (area < B_OK) {
175928ad138aSbeveloper 			FATAL("BMediaRoster::GetParameterWebFor couldn't create area of size %ld\n", size);
176028ad138aSbeveloper 			return B_ERROR;
176128ad138aSbeveloper 		}
176228ad138aSbeveloper 		request.maxsize = size;
176328ad138aSbeveloper 		request.area = area;
176428ad138aSbeveloper 		rv = QueryPort(node.port, CONTROLLABLE_GET_PARAMETER_WEB, &request, sizeof(request), &reply, sizeof(reply));
176528ad138aSbeveloper 		if (rv != B_OK) {
176628ad138aSbeveloper 			FATAL("BMediaRoster::GetParameterWebFor CONTROLLABLE_GET_PARAMETER_WEB failed\n");
176728ad138aSbeveloper 			delete_area(area);
176828ad138aSbeveloper 			return B_ERROR;
176928ad138aSbeveloper 		}
177028ad138aSbeveloper 		if (reply.size == 0) {
177128ad138aSbeveloper 			// no parameter web available
177228ad138aSbeveloper 			// XXX should we return an error?
177328ad138aSbeveloper 			FATAL("BMediaRoster::GetParameterWebFor node %ld has no parameter web\n", node.node);
177428ad138aSbeveloper 			*out_web = new BParameterWeb();
177528ad138aSbeveloper 			delete_area(area);
177660f15390Sbeveloper 			return B_OK;
177752a38012Sejakowatz 		}
177828ad138aSbeveloper 		if (reply.size > 0) {
177928ad138aSbeveloper 			// we got a flattened parameter web!
178028ad138aSbeveloper 			*out_web = new BParameterWeb();
178128ad138aSbeveloper 
178228ad138aSbeveloper 			printf("BMediaRoster::GetParameterWebFor Unflattening %ld bytes, 0x%08x, 0x%08x, 0x%08x, 0x%08x\n",
178328ad138aSbeveloper 				reply.size, ((uint32*)data)[0], ((uint32*)data)[1], ((uint32*)data)[2], ((uint32*)data)[3]);
178428ad138aSbeveloper 
178528ad138aSbeveloper 			rv = (*out_web)->Unflatten(reply.code, data, reply.size);
178628ad138aSbeveloper 			if (rv != B_OK) {
178728ad138aSbeveloper 				FATAL("BMediaRoster::GetParameterWebFor Unflatten failed, %s\n", strerror(rv));
178828ad138aSbeveloper 				delete_area(area);
178928ad138aSbeveloper 				delete *out_web;
179028ad138aSbeveloper 				return B_ERROR;
179128ad138aSbeveloper 			}
179228ad138aSbeveloper 			delete_area(area);
179328ad138aSbeveloper 			return B_OK;
179428ad138aSbeveloper 		}
179528ad138aSbeveloper 		delete_area(area);
179628ad138aSbeveloper 		ASSERT(reply.size == -1);
179728ad138aSbeveloper 		// parameter web data was too large
179828ad138aSbeveloper 		// loop and try a larger size
179928ad138aSbeveloper 	}
180028ad138aSbeveloper 	FATAL("BMediaRoster::GetParameterWebFor node %ld has no parameter web larger than %ld\n", node.node, size);
180128ad138aSbeveloper 	return B_ERROR;
180228ad138aSbeveloper }
180352a38012Sejakowatz 
180452a38012Sejakowatz 
180552a38012Sejakowatz status_t
180652a38012Sejakowatz BMediaRoster::StartControlPanel(const media_node & node,
180752a38012Sejakowatz 								BMessenger * out_messenger)
180852a38012Sejakowatz {
180952a38012Sejakowatz 	UNIMPLEMENTED();
181052a38012Sejakowatz 	return B_ERROR;
181152a38012Sejakowatz }
181252a38012Sejakowatz 
181352a38012Sejakowatz 
181452a38012Sejakowatz status_t
181552a38012Sejakowatz BMediaRoster::GetDormantNodes(dormant_node_info * out_info,
181652a38012Sejakowatz 							  int32 * io_count,
181752a38012Sejakowatz 							  const media_format * has_input /* = NULL */,
181852a38012Sejakowatz 							  const media_format * has_output /* = NULL */,
181952a38012Sejakowatz 							  const char * name /* = NULL */,
182052a38012Sejakowatz 							  uint64 require_kinds /* = NULL */,
182152a38012Sejakowatz 							  uint64 deny_kinds /* = NULL */)
182252a38012Sejakowatz {
182352a38012Sejakowatz 	CALLED();
182452a38012Sejakowatz 	if (out_info == NULL)
182552a38012Sejakowatz 		return B_BAD_VALUE;
182652a38012Sejakowatz 	if (io_count == NULL)
182752a38012Sejakowatz 		return B_BAD_VALUE;
182852a38012Sejakowatz 	if (*io_count <= 0)
182952a38012Sejakowatz 		return B_BAD_VALUE;
183052a38012Sejakowatz 
183152a38012Sejakowatz 	xfer_server_get_dormant_nodes msg;
183252a38012Sejakowatz 	port_id port;
183352a38012Sejakowatz 	status_t rv;
183452a38012Sejakowatz 
183552a38012Sejakowatz 	port = find_port("media_server port");
183652a38012Sejakowatz 	if (port <= B_OK)
183752a38012Sejakowatz 		return B_ERROR;
183852a38012Sejakowatz 
183952a38012Sejakowatz 	msg.maxcount = *io_count;
184052a38012Sejakowatz 	msg.has_input = (bool) has_input;
184152a38012Sejakowatz 	if (has_input)
184252a38012Sejakowatz 		msg.inputformat = *has_input; // XXX we should not make a flat copy of media_format
184352a38012Sejakowatz 	msg.has_output = (bool) has_output;
184452a38012Sejakowatz 	if (has_output)
184552a38012Sejakowatz 		msg.outputformat = *has_output;; // XXX we should not make a flat copy of media_format
184652a38012Sejakowatz 	msg.has_name = (bool) name;
184752a38012Sejakowatz 	if (name) {
18489e9417d2Sbeveloper 		int len = strlen(name);
18499e9417d2Sbeveloper 		len = min_c(len, (int)sizeof(msg.name) - 1);
185052a38012Sejakowatz 		memcpy(msg.name, name, len);
185152a38012Sejakowatz 		msg.name[len] = 0;
185252a38012Sejakowatz 	}
185352a38012Sejakowatz 	msg.require_kinds = require_kinds;
185452a38012Sejakowatz 	msg.deny_kinds = deny_kinds;
185552a38012Sejakowatz 	msg.reply_port = _PortPool->GetPort();
185652a38012Sejakowatz 
185752a38012Sejakowatz 	rv = write_port(port, SERVER_GET_DORMANT_NODES, &msg, sizeof(msg));
185852a38012Sejakowatz 	if (rv != B_OK) {
185952a38012Sejakowatz 		_PortPool->PutPort(msg.reply_port);
186052a38012Sejakowatz 		return rv;
186152a38012Sejakowatz 	}
186252a38012Sejakowatz 
186352a38012Sejakowatz 	xfer_server_get_dormant_nodes_reply reply;
186452a38012Sejakowatz 	int32 code;
186552a38012Sejakowatz 
186652a38012Sejakowatz 	rv = read_port(msg.reply_port, &code, &reply, sizeof(reply));
186752a38012Sejakowatz 	if (rv < B_OK) {
186852a38012Sejakowatz 		_PortPool->PutPort(msg.reply_port);
186952a38012Sejakowatz 		return rv;
187052a38012Sejakowatz 	}
187152a38012Sejakowatz 
187252a38012Sejakowatz 	*io_count = reply.count;
187352a38012Sejakowatz 
187452a38012Sejakowatz 	if (*io_count > 0) {
187552a38012Sejakowatz 		rv = read_port(msg.reply_port, &code, out_info, *io_count * sizeof(dormant_node_info));
187652a38012Sejakowatz 		if (rv < B_OK)
187752a38012Sejakowatz 			reply.result = rv;
187852a38012Sejakowatz 	}
187952a38012Sejakowatz 	_PortPool->PutPort(msg.reply_port);
188052a38012Sejakowatz 
188152a38012Sejakowatz 	return reply.result;
188252a38012Sejakowatz }
188352a38012Sejakowatz 
18848b04ffc1Sbeveloper /* This function is used to do the real work of instantiating a dormant node. It is either
18858b04ffc1Sbeveloper  * called by the media_addon_server to instantiate a global node, or it gets called from
18868b04ffc1Sbeveloper  * BMediaRoster::InstantiateDormantNode() to create a local one.
18878b04ffc1Sbeveloper  *
18888b04ffc1Sbeveloper  * Checks concerning global/local are not done here.
18898b04ffc1Sbeveloper  */
189052a38012Sejakowatz status_t
189154187cc6Sbeveloper BMediaRosterEx::InstantiateDormantNode(media_addon_id addonid, int32 flavorid, team_id creator, media_node *out_node)
189252a38012Sejakowatz {
189354187cc6Sbeveloper 	// This function is always called from the correct context, if the node
189454187cc6Sbeveloper 	// is supposed to be global, it is called from the media_addon_server.
189554187cc6Sbeveloper 
189652a38012Sejakowatz 	// if B_FLAVOR_IS_GLOBAL, we need to use the BMediaAddOn object that
189752a38012Sejakowatz 	// resides in the media_addon_server
189852a38012Sejakowatz 
18998b04ffc1Sbeveloper 	// RegisterNode() must be called for nodes instantiated from add-ons,
19008b04ffc1Sbeveloper 	// since the media kit warrants that it's done automatically.
190152a38012Sejakowatz 
190254187cc6Sbeveloper 	// addonid		Indicates the ID number of the media add-on in which the node resides.
190354187cc6Sbeveloper 	// flavorid		Indicates the internal ID number that the add-on uses to identify the flavor,
190454187cc6Sbeveloper 	//				this is the number that was published by BMediaAddOn::GetFlavorAt() in the
19058b04ffc1Sbeveloper 	//				flavor_info::internal_id field.
190654187cc6Sbeveloper 	// creator		The creator team is -1 if nodes are created locally. If created globally,
190754187cc6Sbeveloper 	//				it will contain (while called in media_addon_server context) the team-id of
190854187cc6Sbeveloper 	// 				the team that requested the instantiation.
19098b04ffc1Sbeveloper 
191060f15390Sbeveloper 	TRACE("BMediaRosterEx::InstantiateDormantNode: addon-id %ld, flavor_id %ld\n", addonid, flavorid);
19118b04ffc1Sbeveloper 
19128b04ffc1Sbeveloper 	// Get flavor_info from the server
19138b04ffc1Sbeveloper 	dormant_flavor_info node_info;
19148c6a6096Sbeveloper 	status_t rv;
19158b04ffc1Sbeveloper 	rv = GetDormantFlavorInfo(addonid, flavorid, &node_info);
19168b04ffc1Sbeveloper 	if (rv != B_OK) {
1917626824eaSbeveloper 		FATAL("BMediaRosterEx::InstantiateDormantNode error: failed to get dormant_flavor_info for addon-id %ld, flavor-id %ld\n", addonid, flavorid);
191852a38012Sejakowatz 		return B_ERROR;
191952a38012Sejakowatz 	}
19208b04ffc1Sbeveloper 
19218b04ffc1Sbeveloper 	ASSERT(node_info.internal_id == flavorid);
19228b04ffc1Sbeveloper 
19238b04ffc1Sbeveloper 	// load the BMediaAddOn object
19248b04ffc1Sbeveloper 	BMediaAddOn *addon;
19258b04ffc1Sbeveloper 	addon = _DormantNodeManager->GetAddon(addonid);
19268b04ffc1Sbeveloper 	if (!addon) {
19278b04ffc1Sbeveloper 		FATAL("BMediaRosterEx::InstantiateDormantNode: GetAddon failed\n");
19288b04ffc1Sbeveloper 		return B_ERROR;
19298b04ffc1Sbeveloper 	}
19308b04ffc1Sbeveloper 
193154187cc6Sbeveloper 	// Now we need to try to increment the use count of this addon flavor
193254187cc6Sbeveloper 	// in the server. This can fail if the total number instances of this
193354187cc6Sbeveloper 	// flavor is limited.
193473794717Sbeveloper 	rv = IncrementAddonFlavorInstancesCount(addonid, flavorid);
193554187cc6Sbeveloper 	if (rv != B_OK) {
1936626824eaSbeveloper 		FATAL("BMediaRosterEx::InstantiateDormantNode error: can't create more nodes for addon-id %ld, flavor-id %ld\n", addonid, flavorid);
193754187cc6Sbeveloper 		// Put the addon back into the pool
193854187cc6Sbeveloper 		_DormantNodeManager->PutAddon(addonid);
193954187cc6Sbeveloper 		return B_ERROR;
194054187cc6Sbeveloper 	}
194154187cc6Sbeveloper 
19428b04ffc1Sbeveloper 	BMessage config;
194354187cc6Sbeveloper 	rv = LoadNodeConfiguration(addonid, flavorid, &config);
194454187cc6Sbeveloper 	if (rv != B_OK) {
194554187cc6Sbeveloper 		FATAL("BMediaRosterEx::InstantiateDormantNode: couldn't load configuration for addon-id %ld, flavor-id %ld\n", addonid, flavorid);
194654187cc6Sbeveloper 		// do not return, this is a minor problem, not a reason to fail
194754187cc6Sbeveloper 	}
19488b04ffc1Sbeveloper 
19498b04ffc1Sbeveloper 	BMediaNode *node;
19508b04ffc1Sbeveloper 	status_t out_error;
19518b04ffc1Sbeveloper 
195254187cc6Sbeveloper 	out_error = B_OK;
19538b04ffc1Sbeveloper 	node = addon->InstantiateNodeFor(&node_info, &config, &out_error);
195416b7eea4Sbeveloper 	if (!node) {
19558b04ffc1Sbeveloper 		FATAL("BMediaRosterEx::InstantiateDormantNode: InstantiateNodeFor failed\n");
195654187cc6Sbeveloper 		// Put the addon back into the pool
19578b04ffc1Sbeveloper 		_DormantNodeManager->PutAddon(addonid);
195854187cc6Sbeveloper 		// We must decrement the use count of this addon flavor in the
195954187cc6Sbeveloper 		// server to compensate the increment done in the beginning.
196073794717Sbeveloper 		rv = DecrementAddonFlavorInstancesCount(addonid, flavorid);
196154187cc6Sbeveloper 		if (rv != B_OK) {
196273794717Sbeveloper 			FATAL("BMediaRosterEx::InstantiateDormantNode: DecrementAddonFlavorInstancesCount failed\n");
196316b7eea4Sbeveloper 		}
196454187cc6Sbeveloper 		return (out_error != B_OK) ? out_error : B_ERROR;
196554187cc6Sbeveloper 	}
196654187cc6Sbeveloper 
196754187cc6Sbeveloper 	rv = RegisterNode(node, addonid, flavorid);
19688c6a6096Sbeveloper 	if (rv != B_OK) {
19698b04ffc1Sbeveloper 		FATAL("BMediaRosterEx::InstantiateDormantNode: RegisterNode failed\n");
19708c6a6096Sbeveloper 		delete node;
197154187cc6Sbeveloper 		// Put the addon back into the pool
19728b04ffc1Sbeveloper 		_DormantNodeManager->PutAddon(addonid);
197354187cc6Sbeveloper 		// We must decrement the use count of this addon flavor in the
197454187cc6Sbeveloper 		// server to compensate the increment done in the beginning.
197573794717Sbeveloper 		rv = DecrementAddonFlavorInstancesCount(addonid, flavorid);
197654187cc6Sbeveloper 		if (rv != B_OK) {
197773794717Sbeveloper 			FATAL("BMediaRosterEx::InstantiateDormantNode: DecrementAddonFlavorInstancesCount failed\n");
197854187cc6Sbeveloper 		}
19798c6a6096Sbeveloper 		return B_ERROR;
19808c6a6096Sbeveloper 	}
19818c6a6096Sbeveloper 
198254187cc6Sbeveloper 	if (creator != -1) {
198354187cc6Sbeveloper 		// send a message to the server to assign team "creator" as creator of node "node->ID()"
198454187cc6Sbeveloper 		printf("!!! BMediaRosterEx::InstantiateDormantNode assigning team %ld as creator of node %ld\n", creator, node->ID());
198554187cc6Sbeveloper 		rv = MediaRosterEx(this)->SetNodeCreator(node->ID(), creator);
198654187cc6Sbeveloper 		if (rv != B_OK) {
198754187cc6Sbeveloper 			FATAL("BMediaRosterEx::InstantiateDormantNode failed to assign team %ld as creator of node %ld\n", creator, node->ID());
198854187cc6Sbeveloper 			// do not return, this is a minor problem, not a reason to fail
198954187cc6Sbeveloper 		}
199054187cc6Sbeveloper 	}
199154187cc6Sbeveloper 
199254187cc6Sbeveloper 	// RegisterNode() does remember the add-on id in the server
199354187cc6Sbeveloper 	// and UnregisterNode() will call DormantNodeManager::PutAddon()
199454187cc6Sbeveloper 	// when the node is unregistered.
19958c6a6096Sbeveloper 
199616b7eea4Sbeveloper 	*out_node = node->Node();
1997cf4e2277Sbeveloper 
199860f15390Sbeveloper 	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);
1999cf4e2277Sbeveloper 
200016b7eea4Sbeveloper 	return B_OK;
200116b7eea4Sbeveloper }
200252a38012Sejakowatz 
200352a38012Sejakowatz 
200452a38012Sejakowatz status_t
20058b04ffc1Sbeveloper BMediaRoster::InstantiateDormantNode(const dormant_node_info & in_info,
20068b04ffc1Sbeveloper 									 media_node * out_node,
20078b04ffc1Sbeveloper 									 uint32 flags /* currently 0 or B_FLAVOR_IS_GLOBAL or B_FLAVOR_IS_LOCAL */ )
20088b04ffc1Sbeveloper {
20098b04ffc1Sbeveloper 	CALLED();
20108b04ffc1Sbeveloper 	if (out_node == 0)
20118b04ffc1Sbeveloper 		return B_BAD_VALUE;
20128b04ffc1Sbeveloper 	if (in_info.addon <= 0) {
20138b04ffc1Sbeveloper 		FATAL("BMediaRoster::InstantiateDormantNode error: addon-id %ld invalid.\n", in_info.addon);
20148b04ffc1Sbeveloper 		return B_BAD_VALUE;
20158b04ffc1Sbeveloper 	}
20168b04ffc1Sbeveloper 
20178b04ffc1Sbeveloper 	printf("BMediaRoster::InstantiateDormantNode: addon-id %ld, flavor_id %ld, flags 0x%X\n", in_info.addon, in_info.flavor_id, flags);
20188b04ffc1Sbeveloper 
20198b04ffc1Sbeveloper 	// Get flavor_info from the server
20208b04ffc1Sbeveloper 	// XXX this is a little overhead, as we get the full blown dormant_flavor_info,
20218b04ffc1Sbeveloper 	// XXX but only need the flags.
20228b04ffc1Sbeveloper 	dormant_flavor_info node_info;
20238b04ffc1Sbeveloper 	status_t rv;
20248b04ffc1Sbeveloper 	rv = MediaRosterEx(this)->GetDormantFlavorInfo(in_info.addon, in_info.flavor_id, &node_info);
20258b04ffc1Sbeveloper 	if (rv != B_OK) {
2026626824eaSbeveloper 		FATAL("BMediaRoster::InstantiateDormantNode error: failed to get dormant_flavor_info for addon-id %ld, flavor-id %ld\n", in_info.addon, in_info.flavor_id);
2027626824eaSbeveloper 		return B_NAME_NOT_FOUND;
20288b04ffc1Sbeveloper 	}
20298b04ffc1Sbeveloper 
20308b04ffc1Sbeveloper 	ASSERT(node_info.internal_id == in_info.flavor_id);
20318b04ffc1Sbeveloper 
20328b04ffc1Sbeveloper 	printf("BMediaRoster::InstantiateDormantNode: name \"%s\", info \"%s\", flavor_flags 0x%X, internal_id %ld, possible_count %ld\n",
20338b04ffc1Sbeveloper 		node_info.name, node_info.info, node_info.flavor_flags, node_info.internal_id, node_info.possible_count);
20348b04ffc1Sbeveloper 
20358b04ffc1Sbeveloper 	#if DEBUG
20368b04ffc1Sbeveloper 		if (flags & B_FLAVOR_IS_LOCAL)
20378b04ffc1Sbeveloper 			printf("BMediaRoster::InstantiateDormantNode: caller requested B_FLAVOR_IS_LOCAL\n");
20388b04ffc1Sbeveloper 		if (flags & B_FLAVOR_IS_GLOBAL)
20398b04ffc1Sbeveloper 			printf("BMediaRoster::InstantiateDormantNode: caller requested B_FLAVOR_IS_GLOBAL\n");
20408b04ffc1Sbeveloper 		if (node_info.flavor_flags & B_FLAVOR_IS_LOCAL)
20418b04ffc1Sbeveloper 			printf("BMediaRoster::InstantiateDormantNode: node requires B_FLAVOR_IS_LOCAL\n");
20428b04ffc1Sbeveloper 		if (node_info.flavor_flags & B_FLAVOR_IS_GLOBAL)
20438b04ffc1Sbeveloper 			printf("BMediaRoster::InstantiateDormantNode: node requires B_FLAVOR_IS_GLOBAL\n");
20448b04ffc1Sbeveloper 	#endif
20458b04ffc1Sbeveloper 
20468b04ffc1Sbeveloper 	// Make sure that flags demanded by the dormant node and those requested
20478b04ffc1Sbeveloper 	// by the caller are not incompatible.
20488b04ffc1Sbeveloper 	if ((node_info.flavor_flags & B_FLAVOR_IS_GLOBAL) && (flags & B_FLAVOR_IS_LOCAL)) {
20498b04ffc1Sbeveloper 		FATAL("BMediaRoster::InstantiateDormantNode Error: requested B_FLAVOR_IS_LOCAL, but dormant node has B_FLAVOR_IS_GLOBAL\n");
2050626824eaSbeveloper 		return B_NAME_NOT_FOUND;
20518b04ffc1Sbeveloper 	}
20528b04ffc1Sbeveloper 	if ((node_info.flavor_flags & B_FLAVOR_IS_LOCAL) && (flags & B_FLAVOR_IS_GLOBAL)) {
20538b04ffc1Sbeveloper 		FATAL("BMediaRoster::InstantiateDormantNode Error: requested B_FLAVOR_IS_GLOBAL, but dormant node has B_FLAVOR_IS_LOCAL\n");
2054626824eaSbeveloper 		return B_NAME_NOT_FOUND;
20558b04ffc1Sbeveloper 	}
205654187cc6Sbeveloper 
20578b04ffc1Sbeveloper 	// If either the node, or the caller requested to make the instance global
20588b04ffc1Sbeveloper 	// we will do it by forwarding this request into the media_addon_server, which
20598b04ffc1Sbeveloper 	// in turn will call BMediaRosterEx::InstantiateDormantNode to create the node
20608b04ffc1Sbeveloper 	// there and make it globally available.
20618b04ffc1Sbeveloper 	if ((node_info.flavor_flags & B_FLAVOR_IS_GLOBAL) || (flags & B_FLAVOR_IS_GLOBAL)) {
20628b04ffc1Sbeveloper 
2063cf4e2277Sbeveloper 		printf("BMediaRoster::InstantiateDormantNode: creating global object in media_addon_server\n");
2064cf4e2277Sbeveloper 
20658b04ffc1Sbeveloper 		addonserver_instantiate_dormant_node_request request;
20668b04ffc1Sbeveloper 		addonserver_instantiate_dormant_node_reply reply;
20678b04ffc1Sbeveloper 		request.addonid = in_info.addon;
20688b04ffc1Sbeveloper 		request.flavorid = in_info.flavor_id;
206954187cc6Sbeveloper 		request.creator_team = team; // creator team is allowed to also release global nodes
20708b04ffc1Sbeveloper 		rv = QueryAddonServer(ADDONSERVER_INSTANTIATE_DORMANT_NODE, &request, sizeof(request), &reply, sizeof(reply));
20718b04ffc1Sbeveloper 		if (rv == B_OK) {
20728b04ffc1Sbeveloper 			*out_node = reply.node;
20738b04ffc1Sbeveloper 		}
20748b04ffc1Sbeveloper 
20758b04ffc1Sbeveloper 	} else {
20768b04ffc1Sbeveloper 
207754187cc6Sbeveloper 		// creator team = -1, as this is a local node
2078626824eaSbeveloper 		rv = MediaRosterEx(this)->InstantiateDormantNode(in_info.addon, in_info.flavor_id, -1, out_node);
2079626824eaSbeveloper 
20808b04ffc1Sbeveloper 	}
2081626824eaSbeveloper 	if (rv != B_OK) {
2082626824eaSbeveloper 		*out_node = media_node::null;
2083626824eaSbeveloper 		return B_NAME_NOT_FOUND;
2084626824eaSbeveloper 	}
2085626824eaSbeveloper 	return B_OK;
20868b04ffc1Sbeveloper }
20878b04ffc1Sbeveloper 
20888b04ffc1Sbeveloper 
20898b04ffc1Sbeveloper status_t
20908b04ffc1Sbeveloper BMediaRoster::InstantiateDormantNode(const dormant_node_info & in_info,
20918b04ffc1Sbeveloper 									 media_node * out_node)
20928b04ffc1Sbeveloper {
20938b04ffc1Sbeveloper 	return InstantiateDormantNode(in_info, out_node, 0);
20948b04ffc1Sbeveloper }
20958b04ffc1Sbeveloper 
20968b04ffc1Sbeveloper 
20978b04ffc1Sbeveloper status_t
209852a38012Sejakowatz BMediaRoster::GetDormantNodeFor(const media_node & node,
209952a38012Sejakowatz 								dormant_node_info * out_info)
210052a38012Sejakowatz {
210185dfab2bSbeveloper 	CALLED();
210285dfab2bSbeveloper 	if (out_info == NULL)
210385dfab2bSbeveloper 		return B_BAD_VALUE;
210440f36b03Sbeveloper 	if (IS_INVALID_NODE(node))
210585dfab2bSbeveloper 		return B_MEDIA_BAD_NODE;
210652a38012Sejakowatz 
210785dfab2bSbeveloper 	server_get_dormant_node_for_request request;
210885dfab2bSbeveloper 	server_get_dormant_node_for_reply reply;
210985dfab2bSbeveloper 	status_t rv;
211085dfab2bSbeveloper 
211185dfab2bSbeveloper 	request.node = node;
211285dfab2bSbeveloper 
21131299bfb2Sbeveloper 	rv = QueryServer(SERVER_GET_DORMANT_NODE_FOR, &request, sizeof(request), &reply, sizeof(reply));
211485dfab2bSbeveloper 	if (rv != B_OK)
211585dfab2bSbeveloper 		return rv;
211685dfab2bSbeveloper 
211785dfab2bSbeveloper 	*out_info = reply.node_info;
211885dfab2bSbeveloper 	return B_OK;
211952a38012Sejakowatz }
212052a38012Sejakowatz 
212152a38012Sejakowatz status_t
21228b04ffc1Sbeveloper BMediaRosterEx::GetDormantFlavorInfo(media_addon_id addonid,
21238b04ffc1Sbeveloper 									  int32 flavorid,
212452a38012Sejakowatz 									  dormant_flavor_info * out_flavor)
212552a38012Sejakowatz {
212652a38012Sejakowatz 	CALLED();
212752a38012Sejakowatz 
212852a38012Sejakowatz 	xfer_server_get_dormant_flavor_info msg;
212952a38012Sejakowatz 	xfer_server_get_dormant_flavor_info_reply *reply;
213052a38012Sejakowatz 	port_id port;
213152a38012Sejakowatz 	status_t rv;
213252a38012Sejakowatz 	int32 code;
213352a38012Sejakowatz 
213452a38012Sejakowatz 	port = find_port("media_server port");
213552a38012Sejakowatz 	if (port <= B_OK)
213652a38012Sejakowatz 		return B_ERROR;
213752a38012Sejakowatz 
213852a38012Sejakowatz 	reply = (xfer_server_get_dormant_flavor_info_reply *) malloc(16000);
213952a38012Sejakowatz 	if (reply == 0)
214052a38012Sejakowatz 		return B_ERROR;
214152a38012Sejakowatz 
21428b04ffc1Sbeveloper 	msg.addon 		= addonid;
21438b04ffc1Sbeveloper 	msg.flavor_id 	= flavorid;
214452a38012Sejakowatz 	msg.reply_port 	= _PortPool->GetPort();
214552a38012Sejakowatz 	rv = write_port(port, SERVER_GET_DORMANT_FLAVOR_INFO, &msg, sizeof(msg));
214652a38012Sejakowatz 	if (rv != B_OK) {
214752a38012Sejakowatz 		free(reply);
214852a38012Sejakowatz 		_PortPool->PutPort(msg.reply_port);
214952a38012Sejakowatz 		return rv;
215052a38012Sejakowatz 	}
215152a38012Sejakowatz 	rv = read_port(msg.reply_port, &code, reply, 16000);
215252a38012Sejakowatz 	_PortPool->PutPort(msg.reply_port);
215352a38012Sejakowatz 
215452a38012Sejakowatz 	if (rv < B_OK) {
215552a38012Sejakowatz 		free(reply);
215652a38012Sejakowatz 		return rv;
215752a38012Sejakowatz 	}
215852a38012Sejakowatz 
215952a38012Sejakowatz 	if (reply->result == B_OK)
216052a38012Sejakowatz 		rv = out_flavor->Unflatten(reply->dfi_type, &reply->dfi, reply->dfi_size);
216152a38012Sejakowatz 	else
216252a38012Sejakowatz 		rv = reply->result;
216352a38012Sejakowatz 
216452a38012Sejakowatz 	free(reply);
216552a38012Sejakowatz 	return rv;
216652a38012Sejakowatz }
216752a38012Sejakowatz 
21688b04ffc1Sbeveloper status_t
21698b04ffc1Sbeveloper BMediaRoster::GetDormantFlavorInfoFor(const dormant_node_info & in_dormant,
21708b04ffc1Sbeveloper 									  dormant_flavor_info * out_flavor)
21718b04ffc1Sbeveloper {
21728b04ffc1Sbeveloper 	return MediaRosterEx(this)->GetDormantFlavorInfo(in_dormant.addon, in_dormant.flavor_id, out_flavor);
21738b04ffc1Sbeveloper }
217452a38012Sejakowatz 
217560f15390Sbeveloper // Reports in outLatency the maximum latency found downstream from
217660f15390Sbeveloper // the specified BBufferProducer, producer, given the current connections.
217752a38012Sejakowatz status_t
217852a38012Sejakowatz BMediaRoster::GetLatencyFor(const media_node & producer,
217952a38012Sejakowatz 							bigtime_t * out_latency)
218052a38012Sejakowatz {
218160f15390Sbeveloper 	CALLED();
218260f15390Sbeveloper 	if (out_latency == NULL)
218360f15390Sbeveloper 		return B_BAD_VALUE;
218460f15390Sbeveloper 	if (IS_INVALID_NODE(producer))
218560f15390Sbeveloper 		return B_MEDIA_BAD_NODE;
218660f15390Sbeveloper 	if ((producer.kind & B_BUFFER_PRODUCER) == 0)
218760f15390Sbeveloper 		return B_MEDIA_BAD_NODE;
218860f15390Sbeveloper 
218960f15390Sbeveloper 	producer_get_latency_request request;
219060f15390Sbeveloper 	producer_get_latency_reply reply;
219160f15390Sbeveloper 	status_t rv;
219260f15390Sbeveloper 
219360f15390Sbeveloper 	rv = QueryPort(producer.port, PRODUCER_GET_LATENCY, &request, sizeof(request), &reply, sizeof(reply));
219460f15390Sbeveloper 	if (rv != B_OK)
219560f15390Sbeveloper 		return rv;
219660f15390Sbeveloper 
219760f15390Sbeveloper 	*out_latency = reply.latency;
219860f15390Sbeveloper 
219960f15390Sbeveloper 	printf("BMediaRoster::GetLatencyFor producer %ld has maximum latency %Ld\n", producer.node, *out_latency);
2200aac800c2Sbeveloper 	return B_OK;
220152a38012Sejakowatz }
220252a38012Sejakowatz 
220352a38012Sejakowatz 
220452a38012Sejakowatz status_t
220552a38012Sejakowatz BMediaRoster::GetInitialLatencyFor(const media_node & producer,
220652a38012Sejakowatz 								   bigtime_t * out_latency,
2207aac800c2Sbeveloper 								   uint32 * out_flags /* = NULL */)
220852a38012Sejakowatz {
220952a38012Sejakowatz 	UNIMPLEMENTED();
221060f15390Sbeveloper 	*out_latency = 5000;
2211aac800c2Sbeveloper 	if (out_flags)
221252a38012Sejakowatz 		*out_flags = 0;
2213aac800c2Sbeveloper 	return B_OK;
221452a38012Sejakowatz }
221552a38012Sejakowatz 
221652a38012Sejakowatz 
221752a38012Sejakowatz status_t
221852a38012Sejakowatz BMediaRoster::GetStartLatencyFor(const media_node & time_source,
221952a38012Sejakowatz 								 bigtime_t * out_latency)
222052a38012Sejakowatz {
222152a38012Sejakowatz 	UNIMPLEMENTED();
2222aac800c2Sbeveloper 	*out_latency = 5000;
2223aac800c2Sbeveloper 	return B_OK;
222452a38012Sejakowatz }
222552a38012Sejakowatz 
222652a38012Sejakowatz 
222752a38012Sejakowatz status_t
222852a38012Sejakowatz BMediaRoster::GetFileFormatsFor(const media_node & file_interface,
222952a38012Sejakowatz 								media_file_format * out_formats,
223052a38012Sejakowatz 								int32 * io_num_infos)
223152a38012Sejakowatz {
223252a38012Sejakowatz 	UNIMPLEMENTED();
223352a38012Sejakowatz 	return B_ERROR;
223452a38012Sejakowatz }
223552a38012Sejakowatz 
223652a38012Sejakowatz 
223752a38012Sejakowatz status_t
223852a38012Sejakowatz BMediaRoster::SetRefFor(const media_node & file_interface,
223952a38012Sejakowatz 						const entry_ref & file,
224052a38012Sejakowatz 						bool create_and_truncate,
224152a38012Sejakowatz 						bigtime_t * out_length)	/* if create is false */
224252a38012Sejakowatz {
224352a38012Sejakowatz 	UNIMPLEMENTED();
224452a38012Sejakowatz 	return B_ERROR;
224552a38012Sejakowatz }
224652a38012Sejakowatz 
224752a38012Sejakowatz 
224852a38012Sejakowatz status_t
224952a38012Sejakowatz BMediaRoster::GetRefFor(const media_node & node,
225052a38012Sejakowatz 						entry_ref * out_file,
225152a38012Sejakowatz 						BMimeType * mime_type)
225252a38012Sejakowatz {
225352a38012Sejakowatz 	UNIMPLEMENTED();
225452a38012Sejakowatz 	return B_ERROR;
225552a38012Sejakowatz }
225652a38012Sejakowatz 
225752a38012Sejakowatz 
225852a38012Sejakowatz status_t
225952a38012Sejakowatz BMediaRoster::SniffRefFor(const media_node & file_interface,
226052a38012Sejakowatz 						  const entry_ref & file,
226152a38012Sejakowatz 						  BMimeType * mime_type,
226252a38012Sejakowatz 						  float * out_capability)
226352a38012Sejakowatz {
226452a38012Sejakowatz 	UNIMPLEMENTED();
226552a38012Sejakowatz 	return B_ERROR;
226652a38012Sejakowatz }
226752a38012Sejakowatz 
226852a38012Sejakowatz 
226952a38012Sejakowatz /* This is the generic "here's a file, now can someone please play it" interface */
227052a38012Sejakowatz status_t
227152a38012Sejakowatz BMediaRoster::SniffRef(const entry_ref & file,
227252a38012Sejakowatz 					   uint64 require_node_kinds,		/* if you need an EntityInterface or BufferConsumer or something */
227352a38012Sejakowatz 					   dormant_node_info * out_node,
227452a38012Sejakowatz 					   BMimeType * mime_type)
227552a38012Sejakowatz {
227652a38012Sejakowatz 	UNIMPLEMENTED();
227752a38012Sejakowatz 	return B_ERROR;
227852a38012Sejakowatz }
227952a38012Sejakowatz 
228052a38012Sejakowatz 
228152a38012Sejakowatz status_t
228252a38012Sejakowatz BMediaRoster::GetDormantNodeForType(const BMimeType & type,
228352a38012Sejakowatz 									uint64 require_node_kinds,
228452a38012Sejakowatz 									dormant_node_info * out_node)
228552a38012Sejakowatz {
228652a38012Sejakowatz 	UNIMPLEMENTED();
228752a38012Sejakowatz 	return B_ERROR;
228852a38012Sejakowatz }
228952a38012Sejakowatz 
229052a38012Sejakowatz 
229152a38012Sejakowatz status_t
229252a38012Sejakowatz BMediaRoster::GetReadFileFormatsFor(const dormant_node_info & in_node,
229352a38012Sejakowatz 									media_file_format * out_read_formats,
229452a38012Sejakowatz 									int32 in_read_count,
229552a38012Sejakowatz 									int32 * out_read_count)
229652a38012Sejakowatz {
229752a38012Sejakowatz 	UNIMPLEMENTED();
229852a38012Sejakowatz 	return B_ERROR;
229952a38012Sejakowatz }
230052a38012Sejakowatz 
230152a38012Sejakowatz 
230252a38012Sejakowatz status_t
230352a38012Sejakowatz BMediaRoster::GetWriteFileFormatsFor(const dormant_node_info & in_node,
230452a38012Sejakowatz 									 media_file_format * out_write_formats,
230552a38012Sejakowatz 									 int32 in_write_count,
230652a38012Sejakowatz 									 int32 * out_write_count)
230752a38012Sejakowatz {
230852a38012Sejakowatz 	UNIMPLEMENTED();
230952a38012Sejakowatz 	return B_ERROR;
231052a38012Sejakowatz }
231152a38012Sejakowatz 
231252a38012Sejakowatz 
231352a38012Sejakowatz status_t
231452a38012Sejakowatz BMediaRoster::GetFormatFor(const media_output & output,
231552a38012Sejakowatz 						   media_format * io_format,
231652a38012Sejakowatz 						   uint32 flags)
231752a38012Sejakowatz {
231852a38012Sejakowatz 	UNIMPLEMENTED();
231952a38012Sejakowatz 	return B_ERROR;
232052a38012Sejakowatz }
232152a38012Sejakowatz 
232252a38012Sejakowatz 
232352a38012Sejakowatz status_t
232452a38012Sejakowatz BMediaRoster::GetFormatFor(const media_input & input,
232552a38012Sejakowatz 						   media_format * io_format,
232652a38012Sejakowatz 						   uint32 flags)
232752a38012Sejakowatz {
232852a38012Sejakowatz 	UNIMPLEMENTED();
232952a38012Sejakowatz 	return B_ERROR;
233052a38012Sejakowatz }
233152a38012Sejakowatz 
233252a38012Sejakowatz 
233352a38012Sejakowatz status_t
233452a38012Sejakowatz BMediaRoster::GetFormatFor(const media_node & node,
233552a38012Sejakowatz 						   media_format * io_format,
233652a38012Sejakowatz 						   float quality)
233752a38012Sejakowatz {
233852a38012Sejakowatz 	UNIMPLEMENTED();
233952a38012Sejakowatz 	return B_ERROR;
234052a38012Sejakowatz }
234152a38012Sejakowatz 
234252a38012Sejakowatz 
234352a38012Sejakowatz ssize_t
234452a38012Sejakowatz BMediaRoster::GetNodeAttributesFor(const media_node & node,
234552a38012Sejakowatz 								   media_node_attribute * outArray,
234652a38012Sejakowatz 								   size_t inMaxCount)
234752a38012Sejakowatz {
234852a38012Sejakowatz 	UNIMPLEMENTED();
234952a38012Sejakowatz 	return B_ERROR;
235052a38012Sejakowatz }
235152a38012Sejakowatz 
235252a38012Sejakowatz 
235352a38012Sejakowatz media_node_id
235452a38012Sejakowatz BMediaRoster::NodeIDFor(port_id source_or_destination_port)
235552a38012Sejakowatz {
23569e9417d2Sbeveloper 	CALLED();
23579e9417d2Sbeveloper 
23589e9417d2Sbeveloper 	server_node_id_for_request request;
23599e9417d2Sbeveloper 	server_node_id_for_reply reply;
23609e9417d2Sbeveloper 	status_t rv;
23619e9417d2Sbeveloper 
23629e9417d2Sbeveloper 	request.port = source_or_destination_port;
23639e9417d2Sbeveloper 
23649e9417d2Sbeveloper 	rv = QueryServer(SERVER_NODE_ID_FOR, &request, sizeof(request), &reply, sizeof(reply));
23659e9417d2Sbeveloper 	if (rv != B_OK) {
2366353b9f6bSbeveloper 		FATAL("BMediaRoster::NodeIDFor: failed (error %#lx)\n", rv);
23679e9417d2Sbeveloper 		return -1;
23689e9417d2Sbeveloper 	}
23699e9417d2Sbeveloper 
23709e9417d2Sbeveloper 	return reply.nodeid;
237152a38012Sejakowatz }
237252a38012Sejakowatz 
237352a38012Sejakowatz 
237452a38012Sejakowatz status_t
237552a38012Sejakowatz BMediaRoster::GetInstancesFor(media_addon_id addon,
237652a38012Sejakowatz 							  int32 flavor,
237752a38012Sejakowatz 							  media_node_id * out_id,
237852a38012Sejakowatz 							  int32 * io_count)
237952a38012Sejakowatz {
238085dfab2bSbeveloper 	CALLED();
238185dfab2bSbeveloper 	if (out_id == NULL || io_count == NULL)
238285dfab2bSbeveloper 		return B_BAD_VALUE;
238385dfab2bSbeveloper 	if (*io_count <= 0)
238485dfab2bSbeveloper 		return B_BAD_VALUE;
238585dfab2bSbeveloper 
238685dfab2bSbeveloper 	server_get_instances_for_request request;
238785dfab2bSbeveloper 	server_get_instances_for_reply reply;
238885dfab2bSbeveloper 	status_t rv;
238985dfab2bSbeveloper 
239085dfab2bSbeveloper 	request.maxcount = *io_count;
239185dfab2bSbeveloper 	request.addon_id = addon;
239285dfab2bSbeveloper 	request.addon_flavor_id = flavor;
239385dfab2bSbeveloper 
239485dfab2bSbeveloper 	rv = QueryServer(SERVER_GET_INSTANCES_FOR, &request, sizeof(request), &reply, sizeof(reply));
239585dfab2bSbeveloper 	if (rv != B_OK) {
2396353b9f6bSbeveloper 		FATAL("BMediaRoster::GetLiveNodes failed\n");
239785dfab2bSbeveloper 		return rv;
239852a38012Sejakowatz 	}
239952a38012Sejakowatz 
240085dfab2bSbeveloper 	*io_count = reply.count;
240185dfab2bSbeveloper 	if (reply.count > 0)
240285dfab2bSbeveloper 		memcpy(out_id, reply.node_id, sizeof(media_node_id) * reply.count);
240385dfab2bSbeveloper 
240485dfab2bSbeveloper 	return B_OK;
240585dfab2bSbeveloper }
240652a38012Sejakowatz 
240752a38012Sejakowatz 
240852a38012Sejakowatz status_t
240952a38012Sejakowatz BMediaRoster::SetRealtimeFlags(uint32 in_enabled)
241052a38012Sejakowatz {
241152a38012Sejakowatz 	UNIMPLEMENTED();
241252a38012Sejakowatz 	return B_ERROR;
241352a38012Sejakowatz }
241452a38012Sejakowatz 
241552a38012Sejakowatz 
241652a38012Sejakowatz status_t
241752a38012Sejakowatz BMediaRoster::GetRealtimeFlags(uint32 * out_enabled)
241852a38012Sejakowatz {
241952a38012Sejakowatz 	UNIMPLEMENTED();
242052a38012Sejakowatz 	return B_ERROR;
242152a38012Sejakowatz }
242252a38012Sejakowatz 
242352a38012Sejakowatz 
242452a38012Sejakowatz ssize_t
242552a38012Sejakowatz BMediaRoster::AudioBufferSizeFor(int32 channel_count,
242652a38012Sejakowatz 								 uint32 sample_format,
242752a38012Sejakowatz 								 float frame_rate,
242852a38012Sejakowatz 								 bus_type bus_kind)
242952a38012Sejakowatz {
243052a38012Sejakowatz 	UNIMPLEMENTED();
243152a38012Sejakowatz 	return 4096;
243252a38012Sejakowatz }
243352a38012Sejakowatz 
243452a38012Sejakowatz 
243552a38012Sejakowatz /* Use MediaFlags to inquire about specific features of the Media Kit. */
243652a38012Sejakowatz /* Returns < 0 for "not present", positive size for output data size. */
243752a38012Sejakowatz /* 0 means that the capability is present, but no data about it. */
243852a38012Sejakowatz /* static */ ssize_t
243952a38012Sejakowatz BMediaRoster::MediaFlags(media_flags cap,
244052a38012Sejakowatz 						 void * buf,
244152a38012Sejakowatz 						 size_t maxSize)
244252a38012Sejakowatz {
244352a38012Sejakowatz 	UNIMPLEMENTED();
244452a38012Sejakowatz 	return 0;
244552a38012Sejakowatz }
244652a38012Sejakowatz 
244752a38012Sejakowatz 
244852a38012Sejakowatz /* BLooper overrides */
244952a38012Sejakowatz /* virtual */ void
245052a38012Sejakowatz BMediaRoster::MessageReceived(BMessage * message)
245152a38012Sejakowatz {
2452cf4e2277Sbeveloper 	switch (message->what) {
2453cf4e2277Sbeveloper 		case 'PING':
2454cf4e2277Sbeveloper 		{
24556396865dSbeveloper 			// media_server plays ping-pong with the BMediaRosters
24566396865dSbeveloper 			// to detect dead teams. Normal communication uses ports.
24576396865dSbeveloper 			static BMessage pong('PONG');
24586396865dSbeveloper 			message->SendReply(&pong, static_cast<BHandler *>(NULL), 2000000);
24596396865dSbeveloper 			return;
24606396865dSbeveloper 		}
24616396865dSbeveloper 
2462*359ac306Sbeveloper 		case NODE_PUBLISH_CONNECTIONS:
2463*359ac306Sbeveloper 		{
2464*359ac306Sbeveloper 			const void *data;
2465*359ac306Sbeveloper 			ssize_t numBytes;
2466*359ac306Sbeveloper 			media_node node;
2467*359ac306Sbeveloper 
2468*359ac306Sbeveloper 			printf("NODE_PUBLISH_CONNECTIONS enter\n");
2469*359ac306Sbeveloper 
2470*359ac306Sbeveloper 			message->FindData("node", B_RAW_TYPE, &data, &numBytes);
2471*359ac306Sbeveloper 			node = *(const media_node *)data;
2472*359ac306Sbeveloper 
2473*359ac306Sbeveloper 			// register existing inputs and outputs with the
2474*359ac306Sbeveloper 			// media_server, this allows GetLiveNodes() to work
2475*359ac306Sbeveloper 			// with created, but unconnected nodes.
2476*359ac306Sbeveloper 			if (node.kind & B_BUFFER_PRODUCER) {
2477*359ac306Sbeveloper 				List<media_output> outputlist;
2478*359ac306Sbeveloper 				if (B_OK == MediaRosterEx(this)->GetAllOutputs(node, &outputlist))
2479*359ac306Sbeveloper 					MediaRosterEx(this)->PublishOutputs(node, &outputlist);
2480*359ac306Sbeveloper 			} else if (node.kind & B_BUFFER_CONSUMER) {
2481*359ac306Sbeveloper 				List<media_input> inputlist;
2482*359ac306Sbeveloper 				if (B_OK == MediaRosterEx(this)->GetAllInputs(node, &inputlist))
2483*359ac306Sbeveloper 					MediaRosterEx(this)->PublishInputs(node, &inputlist);
2484*359ac306Sbeveloper 			}
2485*359ac306Sbeveloper 			printf("NODE_PUBLISH_CONNECTIONS leave\n");
2486*359ac306Sbeveloper 			return;
2487*359ac306Sbeveloper 		}
2488*359ac306Sbeveloper 
2489cf4e2277Sbeveloper 		case NODE_FINAL_RELEASE:
2490cf4e2277Sbeveloper 		{
2491cf4e2277Sbeveloper 			// this function is called by a BMediaNode to delete
2492cf4e2277Sbeveloper 			// itself, as this needs to be done from another thread
2493cf4e2277Sbeveloper 			// context, it is done here.
2494cf4e2277Sbeveloper 			// XXX If a node is released using BMediaRoster::ReleaseNode()
2495cf4e2277Sbeveloper 			// XXX instead of using BMediaNode::Release() / BMediaNode::Acquire()
2496cf4e2277Sbeveloper 			// XXX fRefCount of the BMediaNode will not be correct.
2497cf4e2277Sbeveloper 
2498cf4e2277Sbeveloper 			BMediaNode *node;
2499cf4e2277Sbeveloper 			message->FindPointer("node", reinterpret_cast<void **>(&node));
2500cf4e2277Sbeveloper 
250154187cc6Sbeveloper 			TRACE("BMediaRoster::MessageReceived NODE_FINAL_RELEASE saving node %ld configuration\n", node->ID());
250254187cc6Sbeveloper 			MediaRosterEx(BMediaRoster::Roster())->SaveNodeConfiguration(node);
2503cf4e2277Sbeveloper 
250454187cc6Sbeveloper 			TRACE("BMediaRoster::MessageReceived NODE_FINAL_RELEASE releasing node %ld\n", node->ID());
2505cf4e2277Sbeveloper 			node->DeleteHook(node); // we don't call Release(), see above!
2506cf4e2277Sbeveloper 			return;
2507cf4e2277Sbeveloper 		}
2508cf4e2277Sbeveloper 	}
25096396865dSbeveloper 	printf("BMediaRoster::MessageReceived: unknown message!\n");
25106396865dSbeveloper 	message->PrintToStream();
251152a38012Sejakowatz }
251252a38012Sejakowatz 
251352a38012Sejakowatz /* virtual */ bool
251452a38012Sejakowatz BMediaRoster::QuitRequested()
251552a38012Sejakowatz {
251652a38012Sejakowatz 	UNIMPLEMENTED();
251752a38012Sejakowatz 	return true;
251852a38012Sejakowatz }
251952a38012Sejakowatz 
252052a38012Sejakowatz /* virtual */ BHandler *
252152a38012Sejakowatz BMediaRoster::ResolveSpecifier(BMessage *msg,
252252a38012Sejakowatz 				 int32 index,
252352a38012Sejakowatz 				 BMessage *specifier,
252452a38012Sejakowatz 				 int32 form,
252552a38012Sejakowatz 				 const char *property)
252652a38012Sejakowatz {
252752a38012Sejakowatz 	UNIMPLEMENTED();
252852a38012Sejakowatz 	return 0;
252952a38012Sejakowatz }
253052a38012Sejakowatz 
253152a38012Sejakowatz 
253252a38012Sejakowatz /* virtual */ status_t
253352a38012Sejakowatz BMediaRoster::GetSupportedSuites(BMessage *data)
253452a38012Sejakowatz {
253552a38012Sejakowatz 	UNIMPLEMENTED();
253652a38012Sejakowatz 	return B_ERROR;
253752a38012Sejakowatz }
253852a38012Sejakowatz 
253952a38012Sejakowatz 
254052a38012Sejakowatz BMediaRoster::~BMediaRoster()
254152a38012Sejakowatz {
254252a38012Sejakowatz 	CALLED();
25436396865dSbeveloper 
25446396865dSbeveloper 	// unregister this application with the media server
25456396865dSbeveloper 	server_unregister_app_request request;
25466396865dSbeveloper 	server_unregister_app_reply reply;
25476396865dSbeveloper 	request.team = team;
25486396865dSbeveloper 	QueryServer(SERVER_UNREGISTER_APP, &request, sizeof(request), &reply, sizeof(reply));
254952a38012Sejakowatz }
255052a38012Sejakowatz 
255152a38012Sejakowatz 
255252a38012Sejakowatz /*************************************************************
255352a38012Sejakowatz  * private BMediaRoster
255452a38012Sejakowatz  *************************************************************/
255552a38012Sejakowatz 
255652a38012Sejakowatz // deprecated call
255752a38012Sejakowatz status_t
255852a38012Sejakowatz BMediaRoster::SetOutputBuffersFor(const media_source & output,
255952a38012Sejakowatz 								  BBufferGroup * group,
256052a38012Sejakowatz 								  bool will_reclaim )
256152a38012Sejakowatz {
256252a38012Sejakowatz 	UNIMPLEMENTED();
25639e9417d2Sbeveloper 	debugger("BMediaRoster::SetOutputBuffersFor missing\n");
256452a38012Sejakowatz 	return B_ERROR;
256552a38012Sejakowatz }
256652a38012Sejakowatz 
256752a38012Sejakowatz 
256852a38012Sejakowatz /* FBC stuffing (Mmmh, Stuffing!) */
256952a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_0(void *) { return B_ERROR; }
257052a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_1(void *) { return B_ERROR; }
257152a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_2(void *) { return B_ERROR; }
257252a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_3(void *) { return B_ERROR; }
257352a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_4(void *) { return B_ERROR; }
257452a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_5(void *) { return B_ERROR; }
257552a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_6(void *) { return B_ERROR; }
257652a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_7(void *) { return B_ERROR; }
257752a38012Sejakowatz 
257852a38012Sejakowatz 
257952a38012Sejakowatz BMediaRoster::BMediaRoster() :
25806396865dSbeveloper 	BLooper("_BMediaRoster_", B_URGENT_DISPLAY_PRIORITY, B_LOOPER_PORT_DEFAULT_CAPACITY)
258152a38012Sejakowatz {
258252a38012Sejakowatz 	CALLED();
25836396865dSbeveloper 
25846396865dSbeveloper 	// start the looper
25856396865dSbeveloper 	Run();
25866396865dSbeveloper 
25876396865dSbeveloper 	// register this application with the media server
25886396865dSbeveloper 	server_register_app_request request;
25896396865dSbeveloper 	server_register_app_reply reply;
25906396865dSbeveloper 	request.team = team;
25916396865dSbeveloper 	request.messenger = BMessenger(NULL, this);
25926396865dSbeveloper 	QueryServer(SERVER_REGISTER_APP, &request, sizeof(request), &reply, sizeof(reply));
259352a38012Sejakowatz }
259452a38012Sejakowatz 
25956396865dSbeveloper 
259652a38012Sejakowatz /* static */ status_t
259752a38012Sejakowatz BMediaRoster::ParseCommand(BMessage & reply)
259852a38012Sejakowatz {
259952a38012Sejakowatz 	UNIMPLEMENTED();
260052a38012Sejakowatz 	return B_ERROR;
260152a38012Sejakowatz }
260252a38012Sejakowatz 
260352a38012Sejakowatz 
260452a38012Sejakowatz status_t
260552a38012Sejakowatz BMediaRoster::GetDefaultInfo(media_node_id for_default,
260652a38012Sejakowatz 							 BMessage & out_config)
260752a38012Sejakowatz {
260852a38012Sejakowatz 	UNIMPLEMENTED();
260952a38012Sejakowatz 	return B_ERROR;
261052a38012Sejakowatz }
261152a38012Sejakowatz 
261252a38012Sejakowatz 
261352a38012Sejakowatz 
261452a38012Sejakowatz status_t
261552a38012Sejakowatz BMediaRoster::SetRunningDefault(media_node_id for_default,
261652a38012Sejakowatz 								const media_node & node)
261752a38012Sejakowatz {
261852a38012Sejakowatz 	UNIMPLEMENTED();
261952a38012Sejakowatz 	return B_ERROR;
262052a38012Sejakowatz }
262152a38012Sejakowatz 
262252a38012Sejakowatz 
262352a38012Sejakowatz /*************************************************************
262452a38012Sejakowatz  * static BMediaRoster variables
262552a38012Sejakowatz  *************************************************************/
262652a38012Sejakowatz 
262752a38012Sejakowatz bool BMediaRoster::_isMediaServer;
262852a38012Sejakowatz port_id BMediaRoster::_mReplyPort;
262952a38012Sejakowatz int32 BMediaRoster::_mReplyPortRes;
263052a38012Sejakowatz int32 BMediaRoster::_mReplyPortUnavailCount;
263152a38012Sejakowatz BMediaRoster * BMediaRoster::_sDefault = NULL;
263252a38012Sejakowatz 
2633