xref: /haiku/src/kits/media/MediaRoster.cpp (revision 28ad138ac925fbd55bbef5619d6802ddc0208c47)
152a38012Sejakowatz /***********************************************************************
252a38012Sejakowatz  * AUTHOR: Marcus Overhagen
352a38012Sejakowatz  *   FILE: MediaRoster.cpp
452a38012Sejakowatz  *  DESCR:
552a38012Sejakowatz  ***********************************************************************/
652a38012Sejakowatz #include <MediaRoster.h>
752a38012Sejakowatz #include <Locker.h>
852a38012Sejakowatz #include <Message.h>
952a38012Sejakowatz #include <Messenger.h>
1052a38012Sejakowatz #include <StopWatch.h>
1152a38012Sejakowatz #include <OS.h>
1252a38012Sejakowatz #include <String.h>
1352a38012Sejakowatz #include <TimeSource.h>
1460f15390Sbeveloper #include <ParameterWeb.h>
1552a38012Sejakowatz #include "debug.h"
168b04ffc1Sbeveloper #include "MediaRosterEx.h"
1740f36b03Sbeveloper #include "MediaMisc.h"
1852a38012Sejakowatz #include "PortPool.h"
190a483e72SIngo Weinhold #include "ServerInterface.h"
20f4925104Sbeveloper #include "DataExchange.h"
2116b7eea4Sbeveloper #include "DormantNodeManager.h"
22f4925104Sbeveloper #include "Notifications.h"
23835140c8Sbeveloper #include "TimeSourceObjectManager.h"
2452a38012Sejakowatz 
25f4925104Sbeveloper namespace BPrivate { namespace media {
2652a38012Sejakowatz 
2752a38012Sejakowatz 	// the BMediaRoster destructor is private,
2852a38012Sejakowatz 	// but _DefaultDeleter is a friend class of
2952a38012Sejakowatz 	// the BMediaRoster an thus can delete it
308b04ffc1Sbeveloper 	class DefaultDeleter
3152a38012Sejakowatz 	{
3252a38012Sejakowatz 	public:
338b04ffc1Sbeveloper 		~DefaultDeleter()
346396865dSbeveloper 		{
356396865dSbeveloper 			if (BMediaRoster::_sDefault) {
366396865dSbeveloper 				BMediaRoster::_sDefault->Lock();
376396865dSbeveloper 				BMediaRoster::_sDefault->Quit();
386396865dSbeveloper 			}
396396865dSbeveloper 		}
408b04ffc1Sbeveloper 	};
4152a38012Sejakowatz 
428b04ffc1Sbeveloper } } // BPrivate::media
438b04ffc1Sbeveloper using namespace BPrivate::media;
4452a38012Sejakowatz 
458b04ffc1Sbeveloper // DefaultDeleter will delete the BMediaRoster object in it's destructor.
468b04ffc1Sbeveloper DefaultDeleter _deleter;
4752a38012Sejakowatz 
483620737cSbeveloper status_t
4954187cc6Sbeveloper BMediaRosterEx::SaveNodeConfiguration(BMediaNode *node)
5054187cc6Sbeveloper {
5154187cc6Sbeveloper 	BMediaAddOn *addon;
5254187cc6Sbeveloper 	media_addon_id addonid;
5354187cc6Sbeveloper 	int32 flavorid;
5454187cc6Sbeveloper 	addon = node->AddOn(&flavorid);
5554187cc6Sbeveloper 	if (!addon) {
5660f15390Sbeveloper 		// XXX this check incorrectly triggers on BeOS R5 BT848 node
5760f15390Sbeveloper 		FATAL("BMediaRosterEx::SaveNodeConfiguration node %ld not instantiated from BMediaAddOn!\n", node->ID());
5854187cc6Sbeveloper 		return B_ERROR;
5954187cc6Sbeveloper 	}
6054187cc6Sbeveloper 	addonid = addon->AddonID();
6154187cc6Sbeveloper 
6254187cc6Sbeveloper 	// XXX fix this
6354187cc6Sbeveloper 	printf("### BMediaRosterEx::SaveNodeConfiguration should save addon-id %ld, flavor-id %ld config NOW!\n", addonid, flavorid);
6454187cc6Sbeveloper 	return B_OK;
6554187cc6Sbeveloper }
6654187cc6Sbeveloper 
6754187cc6Sbeveloper status_t
6854187cc6Sbeveloper BMediaRosterEx::LoadNodeConfiguration(media_addon_id addonid, int32 flavorid, BMessage *out_msg)
6954187cc6Sbeveloper {
7054187cc6Sbeveloper 	// XXX fix this
7154187cc6Sbeveloper 	out_msg->MakeEmpty(); // to be fully R5 compliant
7254187cc6Sbeveloper 	printf("### BMediaRosterEx::LoadNodeConfiguration should load addon-id %ld, flavor-id %ld config NOW!\n", addonid, flavorid);
7354187cc6Sbeveloper 	return B_OK;
7454187cc6Sbeveloper }
7554187cc6Sbeveloper 
7654187cc6Sbeveloper status_t
7773794717Sbeveloper BMediaRosterEx::IncrementAddonFlavorInstancesCount(media_addon_id addonid, int32 flavorid)
7854187cc6Sbeveloper {
7973794717Sbeveloper 	server_change_addon_flavor_instances_count_request request;
8073794717Sbeveloper 	server_change_addon_flavor_instances_count_reply reply;
8173794717Sbeveloper 
8273794717Sbeveloper 	request.addonid = addonid;
8373794717Sbeveloper 	request.flavorid = flavorid;
8473794717Sbeveloper 	request.delta = 1;
8573794717Sbeveloper 	request.team = team;
8673794717Sbeveloper 	return QueryServer(SERVER_CHANGE_ADDON_FLAVOR_INSTANCES_COUNT, &request, sizeof(request), &reply, sizeof(reply));
8754187cc6Sbeveloper }
8854187cc6Sbeveloper 
8954187cc6Sbeveloper status_t
9073794717Sbeveloper BMediaRosterEx::DecrementAddonFlavorInstancesCount(media_addon_id addonid, int32 flavorid)
9154187cc6Sbeveloper {
9273794717Sbeveloper 	server_change_addon_flavor_instances_count_request request;
9373794717Sbeveloper 	server_change_addon_flavor_instances_count_reply reply;
9473794717Sbeveloper 
9573794717Sbeveloper 	request.addonid = addonid;
9673794717Sbeveloper 	request.flavorid = flavorid;
9773794717Sbeveloper 	request.delta = -1;
9873794717Sbeveloper 	request.team = team;
9973794717Sbeveloper 	return QueryServer(SERVER_CHANGE_ADDON_FLAVOR_INSTANCES_COUNT, &request, sizeof(request), &reply, sizeof(reply));
10054187cc6Sbeveloper }
10154187cc6Sbeveloper 
10254187cc6Sbeveloper status_t
10354187cc6Sbeveloper BMediaRosterEx::SetNodeCreator(media_node_id node, team_id creator)
10454187cc6Sbeveloper {
10554187cc6Sbeveloper 	server_set_node_creator_request request;
10654187cc6Sbeveloper 	server_set_node_creator_reply reply;
10754187cc6Sbeveloper 
10854187cc6Sbeveloper 	request.node = node;
10954187cc6Sbeveloper 	request.creator = creator;
11054187cc6Sbeveloper 	return QueryServer(SERVER_SET_NODE_CREATOR, &request, sizeof(request), &reply, sizeof(reply));
11154187cc6Sbeveloper }
11254187cc6Sbeveloper 
11354187cc6Sbeveloper status_t
1148b04ffc1Sbeveloper BMediaRosterEx::GetNode(node_type type, media_node * out_node, int32 * out_input_id, BString * out_input_name)
11552a38012Sejakowatz {
11652a38012Sejakowatz 	if (out_node == NULL)
11752a38012Sejakowatz 		return B_BAD_VALUE;
11852a38012Sejakowatz 
1198c6a6096Sbeveloper 	server_get_node_request request;
1208c6a6096Sbeveloper 	server_get_node_reply reply;
12152a38012Sejakowatz 	status_t rv;
12252a38012Sejakowatz 
1238c6a6096Sbeveloper 	request.type = type;
1249e9417d2Sbeveloper 	request.team = team;
1258c6a6096Sbeveloper 	rv = QueryServer(SERVER_GET_NODE, &request, sizeof(request), &reply, sizeof(reply));
1268c6a6096Sbeveloper 	if (rv != B_OK)
1278c6a6096Sbeveloper 		return rv;
12852a38012Sejakowatz 
12952a38012Sejakowatz 	*out_node = reply.node;
13052a38012Sejakowatz 	if (out_input_id)
13152a38012Sejakowatz 		*out_input_id = reply.input_id;
13252a38012Sejakowatz 	if (out_input_name)
13352a38012Sejakowatz 		*out_input_name = reply.input_name;
1348c6a6096Sbeveloper 	return rv;
13552a38012Sejakowatz }
13652a38012Sejakowatz 
1373620737cSbeveloper status_t
1388b04ffc1Sbeveloper BMediaRosterEx::SetNode(node_type type, const media_node *node, const dormant_node_info *info, const media_input *input)
13952a38012Sejakowatz {
1408c6a6096Sbeveloper 	server_set_node_request request;
1418c6a6096Sbeveloper 	server_set_node_reply reply;
14252a38012Sejakowatz 
1438c6a6096Sbeveloper 	request.type = type;
1448c6a6096Sbeveloper 	request.use_node = node ? true : false;
14552a38012Sejakowatz 	if (node)
1468c6a6096Sbeveloper 		request.node = *node;
1478c6a6096Sbeveloper 	request.use_dni = info ? true : false;
14852a38012Sejakowatz 	if (info)
1498c6a6096Sbeveloper 		request.dni = *info;
1508c6a6096Sbeveloper 	request.use_input = input ? true : false;
15152a38012Sejakowatz 	if (input)
1528c6a6096Sbeveloper 		request.input = *input;
15352a38012Sejakowatz 
1548c6a6096Sbeveloper 	return QueryServer(SERVER_SET_NODE, &request, sizeof(request), &reply, sizeof(reply));
15552a38012Sejakowatz }
15652a38012Sejakowatz 
1573620737cSbeveloper status_t
1588b04ffc1Sbeveloper BMediaRosterEx::GetAllOutputs(const media_node & node, List<media_output> *list)
1593620737cSbeveloper {
1603620737cSbeveloper 	int32 cookie;
1613620737cSbeveloper 	status_t rv;
1623620737cSbeveloper 	status_t result;
1633620737cSbeveloper 
1643620737cSbeveloper 	result = B_OK;
1653620737cSbeveloper 	cookie = 0;
16676669a29Sbeveloper 	list->MakeEmpty();
1673620737cSbeveloper 	for (;;) {
1683620737cSbeveloper 		producer_get_next_output_request request;
1693620737cSbeveloper 		producer_get_next_output_reply reply;
1703620737cSbeveloper 		request.cookie = cookie;
1710caff283Sbeveloper 		rv = QueryPort(node.port, PRODUCER_GET_NEXT_OUTPUT, &request, sizeof(request), &reply, sizeof(reply));
1723620737cSbeveloper 		if (rv != B_OK)
1733620737cSbeveloper 			break;
1743620737cSbeveloper 		cookie = reply.cookie;
17576669a29Sbeveloper 		if (!list->Insert(reply.output)) {
17676669a29Sbeveloper 			FATAL("GetAllOutputs: list->Insert failed\n");
1773620737cSbeveloper 			result = B_ERROR;
1783620737cSbeveloper 		}
1793620737cSbeveloper 	}
1803620737cSbeveloper 
1813620737cSbeveloper 	producer_dispose_output_cookie_request request;
1823620737cSbeveloper 	producer_dispose_output_cookie_reply reply;
1830caff283Sbeveloper 	QueryPort(node.port, PRODUCER_DISPOSE_OUTPUT_COOKIE, &request, sizeof(request), &reply, sizeof(reply));
1843620737cSbeveloper 
1853620737cSbeveloper 	return result;
1863620737cSbeveloper }
1873620737cSbeveloper 
1883620737cSbeveloper status_t
1898b04ffc1Sbeveloper BMediaRosterEx::GetAllInputs(const media_node & node, List<media_input> *list)
1903620737cSbeveloper {
1913620737cSbeveloper 	int32 cookie;
1923620737cSbeveloper 	status_t rv;
1933620737cSbeveloper 	status_t result;
1943620737cSbeveloper 
1953620737cSbeveloper 	result = B_OK;
1963620737cSbeveloper 	cookie = 0;
19776669a29Sbeveloper 	list->MakeEmpty();
1983620737cSbeveloper 	for (;;) {
1993620737cSbeveloper 		consumer_get_next_input_request request;
2003620737cSbeveloper 		consumer_get_next_input_reply reply;
2013620737cSbeveloper 		request.cookie = cookie;
2020caff283Sbeveloper 		rv = QueryPort(node.port, CONSUMER_GET_NEXT_INPUT, &request, sizeof(request), &reply, sizeof(reply));
2033620737cSbeveloper 		if (rv != B_OK)
2043620737cSbeveloper 			break;
2053620737cSbeveloper 		cookie = reply.cookie;
20676669a29Sbeveloper 		if (!list->Insert(reply.input)) {
20776669a29Sbeveloper 			FATAL("GetAllInputs: list->Insert failed\n");
2083620737cSbeveloper 			result = B_ERROR;
2093620737cSbeveloper 		}
2103620737cSbeveloper 	}
2113620737cSbeveloper 
2123620737cSbeveloper 	consumer_dispose_input_cookie_request request;
2133620737cSbeveloper 	consumer_dispose_input_cookie_reply reply;
2140caff283Sbeveloper 	QueryPort(node.port, CONSUMER_DISPOSE_INPUT_COOKIE, &request, sizeof(request), &reply, sizeof(reply));
2153620737cSbeveloper 
2163620737cSbeveloper 	return result;
2173620737cSbeveloper }
2183620737cSbeveloper 
2193620737cSbeveloper status_t
2208b04ffc1Sbeveloper BMediaRosterEx::PublishOutputs(const media_node & node, List<media_output> *list)
2213620737cSbeveloper {
2223620737cSbeveloper 	server_publish_outputs_request request;
2233620737cSbeveloper 	server_publish_outputs_reply reply;
2243620737cSbeveloper 	media_output *output;
2253620737cSbeveloper 	media_output *outputs;
2263620737cSbeveloper 	int32 count;
227a7b41a96Sbeveloper 	status_t rv;
2283620737cSbeveloper 
22976669a29Sbeveloper 	count = list->CountItems();
2303620737cSbeveloper 	TRACE("PublishOutputs: publishing %ld\n", count);
2313620737cSbeveloper 
2323620737cSbeveloper 	request.node = node;
2333620737cSbeveloper 	request.count = count;
2343620737cSbeveloper 	if (count > MAX_OUTPUTS) {
2353620737cSbeveloper 		void *start_addr;
2363620737cSbeveloper 		size_t size;
23740f36b03Sbeveloper 		size = ROUND_UP_TO_PAGE(count * sizeof(media_output));
2383620737cSbeveloper 		request.area = create_area("publish outputs", &start_addr, B_ANY_ADDRESS, size, B_NO_LOCK, B_READ_AREA | B_WRITE_AREA);
2393620737cSbeveloper 		if (request.area < B_OK) {
240353b9f6bSbeveloper 			FATAL("PublishOutputs: failed to create area, %#lx\n", request.area);
2413620737cSbeveloper 			return (status_t)request.area;
2423620737cSbeveloper 		}
2433620737cSbeveloper 		outputs = static_cast<media_output *>(start_addr);
2443620737cSbeveloper 	} else {
2453620737cSbeveloper 		request.area = -1;
2463620737cSbeveloper 		outputs = request.outputs;
2473620737cSbeveloper 	}
24876669a29Sbeveloper 	TRACE("PublishOutputs: area %ld\n", request.area);
2493620737cSbeveloper 
25076669a29Sbeveloper 	int i;
25176669a29Sbeveloper 	for (i = 0, list->Rewind(); list->GetNext(&output); i++) {
25276669a29Sbeveloper 		ASSERT(i < count);
2533620737cSbeveloper 		outputs[i] = *output;
2543620737cSbeveloper 	}
2553620737cSbeveloper 
256a7b41a96Sbeveloper 	rv = QueryServer(SERVER_PUBLISH_OUTPUTS, &request, sizeof(request), &reply, sizeof(reply));
257a7b41a96Sbeveloper 
258a7b41a96Sbeveloper 	if (request.area != -1)
259a7b41a96Sbeveloper 		delete_area(request.area);
260a7b41a96Sbeveloper 
261a7b41a96Sbeveloper 	return rv;
2623620737cSbeveloper }
2633620737cSbeveloper 
2643620737cSbeveloper status_t
2658b04ffc1Sbeveloper BMediaRosterEx::PublishInputs(const media_node & node, List<media_input> *list)
2663620737cSbeveloper {
2673620737cSbeveloper 	server_publish_inputs_request request;
2683620737cSbeveloper 	server_publish_inputs_reply reply;
2693620737cSbeveloper 	media_input *input;
2703620737cSbeveloper 	media_input *inputs;
2713620737cSbeveloper 	int32 count;
272a7b41a96Sbeveloper 	status_t rv;
2733620737cSbeveloper 
27476669a29Sbeveloper 	count = list->CountItems();
2753620737cSbeveloper 	TRACE("PublishInputs: publishing %ld\n", count);
2763620737cSbeveloper 
2773620737cSbeveloper 	request.node = node;
2783620737cSbeveloper 	request.count = count;
2793620737cSbeveloper 	if (count > MAX_INPUTS) {
2803620737cSbeveloper 		void *start_addr;
2813620737cSbeveloper 		size_t size;
28240f36b03Sbeveloper 		size = ROUND_UP_TO_PAGE(count * sizeof(media_input));
2833620737cSbeveloper 		request.area = create_area("publish inputs", &start_addr, B_ANY_ADDRESS, size, B_NO_LOCK, B_READ_AREA | B_WRITE_AREA);
2843620737cSbeveloper 		if (request.area < B_OK) {
285353b9f6bSbeveloper 			FATAL("PublishInputs: failed to create area, %#lx\n", request.area);
2863620737cSbeveloper 			return (status_t)request.area;
2873620737cSbeveloper 		}
2883620737cSbeveloper 		inputs = static_cast<media_input *>(start_addr);
2893620737cSbeveloper 	} else {
2903620737cSbeveloper 		request.area = -1;
2913620737cSbeveloper 		inputs = request.inputs;
2923620737cSbeveloper 	}
29376669a29Sbeveloper 	TRACE("PublishInputs: area %ld\n", request.area);
2943620737cSbeveloper 
29576669a29Sbeveloper 	int i;
29676669a29Sbeveloper 	for (i = 0, list->Rewind(); list->GetNext(&input); i++) {
29776669a29Sbeveloper 		ASSERT(i < count);
2983620737cSbeveloper 		inputs[i] = *input;
2993620737cSbeveloper 	}
3003620737cSbeveloper 
301a7b41a96Sbeveloper 	rv = QueryServer(SERVER_PUBLISH_INPUTS, &request, sizeof(request), &reply, sizeof(reply));
302a7b41a96Sbeveloper 
303a7b41a96Sbeveloper 	if (request.area != -1)
304a7b41a96Sbeveloper 		delete_area(request.area);
305a7b41a96Sbeveloper 
306a7b41a96Sbeveloper 	return rv;
3073620737cSbeveloper }
3083620737cSbeveloper 
30952a38012Sejakowatz /*************************************************************
31052a38012Sejakowatz  * public BMediaRoster
31152a38012Sejakowatz  *************************************************************/
31252a38012Sejakowatz 
31352a38012Sejakowatz status_t
31452a38012Sejakowatz BMediaRoster::GetVideoInput(media_node * out_node)
31552a38012Sejakowatz {
31652a38012Sejakowatz 	CALLED();
3178b04ffc1Sbeveloper 	return MediaRosterEx(this)->GetNode(VIDEO_INPUT, out_node);
31852a38012Sejakowatz }
31952a38012Sejakowatz 
32052a38012Sejakowatz 
32152a38012Sejakowatz status_t
32252a38012Sejakowatz BMediaRoster::GetAudioInput(media_node * out_node)
32352a38012Sejakowatz {
32452a38012Sejakowatz 	CALLED();
3258b04ffc1Sbeveloper 	return MediaRosterEx(this)->GetNode(AUDIO_INPUT, out_node);
32652a38012Sejakowatz }
32752a38012Sejakowatz 
32852a38012Sejakowatz 
32952a38012Sejakowatz status_t
33052a38012Sejakowatz BMediaRoster::GetVideoOutput(media_node * out_node)
33152a38012Sejakowatz {
33252a38012Sejakowatz 	CALLED();
3338b04ffc1Sbeveloper 	return MediaRosterEx(this)->GetNode(VIDEO_OUTPUT, out_node);
33452a38012Sejakowatz }
33552a38012Sejakowatz 
33652a38012Sejakowatz 
33752a38012Sejakowatz status_t
33852a38012Sejakowatz BMediaRoster::GetAudioMixer(media_node * out_node)
33952a38012Sejakowatz {
34052a38012Sejakowatz 	CALLED();
3418b04ffc1Sbeveloper 	return MediaRosterEx(this)->GetNode(AUDIO_MIXER, out_node);
34252a38012Sejakowatz }
34352a38012Sejakowatz 
34452a38012Sejakowatz 
34552a38012Sejakowatz status_t
34652a38012Sejakowatz BMediaRoster::GetAudioOutput(media_node * out_node)
34752a38012Sejakowatz {
34852a38012Sejakowatz 	CALLED();
3498b04ffc1Sbeveloper 	return MediaRosterEx(this)->GetNode(AUDIO_OUTPUT, out_node);
35052a38012Sejakowatz }
35152a38012Sejakowatz 
35252a38012Sejakowatz 
35352a38012Sejakowatz status_t
35452a38012Sejakowatz BMediaRoster::GetAudioOutput(media_node * out_node,
35552a38012Sejakowatz 							 int32 * out_input_id,
35652a38012Sejakowatz 							 BString * out_input_name)
35752a38012Sejakowatz {
35852a38012Sejakowatz 	CALLED();
3598b04ffc1Sbeveloper 	return MediaRosterEx(this)->GetNode(AUDIO_OUTPUT_EX, out_node, out_input_id, out_input_name);
36052a38012Sejakowatz }
36152a38012Sejakowatz 
36252a38012Sejakowatz 
36352a38012Sejakowatz status_t
36452a38012Sejakowatz BMediaRoster::GetTimeSource(media_node * out_node)
36552a38012Sejakowatz {
36652a38012Sejakowatz 	CALLED();
36786bce45bSbeveloper 	status_t rv;
36886bce45bSbeveloper 
36986bce45bSbeveloper 	// XXX need to do this in a nicer way.
37086bce45bSbeveloper 
37186bce45bSbeveloper 	rv = MediaRosterEx(this)->GetNode(TIME_SOURCE, out_node);
37286bce45bSbeveloper 	if (rv != B_OK)
37386bce45bSbeveloper 		return rv;
37486bce45bSbeveloper 
37586bce45bSbeveloper 	// We don't do reference counting for timesources, that's why we
37686bce45bSbeveloper 	// release the node immediately.
37786bce45bSbeveloper 	ReleaseNode(*out_node);
37886bce45bSbeveloper 
37986bce45bSbeveloper 	// we need to remember to not use this node with server side reference counting
38086bce45bSbeveloper 	out_node->kind |= NODE_KIND_NO_REFCOUNTING;
38186bce45bSbeveloper 
38286bce45bSbeveloper 	return B_OK;
38352a38012Sejakowatz }
38452a38012Sejakowatz 
38552a38012Sejakowatz 
38652a38012Sejakowatz status_t
38752a38012Sejakowatz BMediaRoster::SetVideoInput(const media_node & producer)
38852a38012Sejakowatz {
38952a38012Sejakowatz 	CALLED();
3908b04ffc1Sbeveloper 	return MediaRosterEx(this)->SetNode(VIDEO_INPUT, &producer);
39152a38012Sejakowatz }
39252a38012Sejakowatz 
39352a38012Sejakowatz 
39452a38012Sejakowatz status_t
39552a38012Sejakowatz BMediaRoster::SetVideoInput(const dormant_node_info & producer)
39652a38012Sejakowatz {
39752a38012Sejakowatz 	CALLED();
3988b04ffc1Sbeveloper 	return MediaRosterEx(this)->SetNode(VIDEO_INPUT, NULL, &producer);
39952a38012Sejakowatz }
40052a38012Sejakowatz 
40152a38012Sejakowatz 
40252a38012Sejakowatz status_t
40352a38012Sejakowatz BMediaRoster::SetAudioInput(const media_node & producer)
40452a38012Sejakowatz {
40552a38012Sejakowatz 	CALLED();
4068b04ffc1Sbeveloper 	return MediaRosterEx(this)->SetNode(AUDIO_INPUT, &producer);
40752a38012Sejakowatz }
40852a38012Sejakowatz 
40952a38012Sejakowatz 
41052a38012Sejakowatz status_t
41152a38012Sejakowatz BMediaRoster::SetAudioInput(const dormant_node_info & producer)
41252a38012Sejakowatz {
41352a38012Sejakowatz 	CALLED();
4148b04ffc1Sbeveloper 	return MediaRosterEx(this)->SetNode(AUDIO_INPUT, NULL, &producer);
41552a38012Sejakowatz }
41652a38012Sejakowatz 
41752a38012Sejakowatz 
41852a38012Sejakowatz status_t
41952a38012Sejakowatz BMediaRoster::SetVideoOutput(const media_node & consumer)
42052a38012Sejakowatz {
42152a38012Sejakowatz 	CALLED();
4228b04ffc1Sbeveloper 	return MediaRosterEx(this)->SetNode(VIDEO_OUTPUT, &consumer);
42352a38012Sejakowatz }
42452a38012Sejakowatz 
42552a38012Sejakowatz 
42652a38012Sejakowatz status_t
42752a38012Sejakowatz BMediaRoster::SetVideoOutput(const dormant_node_info & consumer)
42852a38012Sejakowatz {
42952a38012Sejakowatz 	CALLED();
4308b04ffc1Sbeveloper 	return MediaRosterEx(this)->SetNode(VIDEO_OUTPUT, NULL, &consumer);
43152a38012Sejakowatz }
43252a38012Sejakowatz 
43352a38012Sejakowatz 
43452a38012Sejakowatz status_t
43552a38012Sejakowatz BMediaRoster::SetAudioOutput(const media_node & consumer)
43652a38012Sejakowatz {
43752a38012Sejakowatz 	CALLED();
4388b04ffc1Sbeveloper 	return MediaRosterEx(this)->SetNode(AUDIO_OUTPUT, &consumer);
43952a38012Sejakowatz }
44052a38012Sejakowatz 
44152a38012Sejakowatz 
44252a38012Sejakowatz status_t
44352a38012Sejakowatz BMediaRoster::SetAudioOutput(const media_input & input_to_output)
44452a38012Sejakowatz {
44552a38012Sejakowatz 	CALLED();
4468b04ffc1Sbeveloper 	return MediaRosterEx(this)->SetNode(AUDIO_OUTPUT, NULL, NULL, &input_to_output);
44752a38012Sejakowatz }
44852a38012Sejakowatz 
44952a38012Sejakowatz 
45052a38012Sejakowatz status_t
45152a38012Sejakowatz BMediaRoster::SetAudioOutput(const dormant_node_info & consumer)
45252a38012Sejakowatz {
45352a38012Sejakowatz 	CALLED();
4548b04ffc1Sbeveloper 	return MediaRosterEx(this)->SetNode(AUDIO_OUTPUT, NULL, &consumer);
45552a38012Sejakowatz }
45652a38012Sejakowatz 
45752a38012Sejakowatz 
45852a38012Sejakowatz status_t
45952a38012Sejakowatz BMediaRoster::GetNodeFor(media_node_id node,
46052a38012Sejakowatz 						 media_node * clone)
46152a38012Sejakowatz {
4629e9417d2Sbeveloper 	CALLED();
4639e9417d2Sbeveloper 	if (clone == NULL)
4649e9417d2Sbeveloper 		return B_BAD_VALUE;
4659e9417d2Sbeveloper 	if (node <= 0)
4669e9417d2Sbeveloper 		return B_MEDIA_BAD_NODE;
4679e9417d2Sbeveloper 
4689e9417d2Sbeveloper 	server_get_node_for_request request;
4699e9417d2Sbeveloper 	server_get_node_for_reply reply;
4709e9417d2Sbeveloper 	status_t rv;
4719e9417d2Sbeveloper 
4729e9417d2Sbeveloper 	request.nodeid = node;
4739e9417d2Sbeveloper 	request.team = team;
4749e9417d2Sbeveloper 
4759e9417d2Sbeveloper 	rv = QueryServer(SERVER_GET_NODE_FOR, &request, sizeof(request), &reply, sizeof(reply));
4769e9417d2Sbeveloper 	if (rv != B_OK)
4779e9417d2Sbeveloper 		return rv;
4789e9417d2Sbeveloper 
4799e9417d2Sbeveloper 	*clone = reply.clone;
4809e9417d2Sbeveloper 	return B_OK;
48152a38012Sejakowatz }
48252a38012Sejakowatz 
48352a38012Sejakowatz 
48452a38012Sejakowatz status_t
48552a38012Sejakowatz BMediaRoster::GetSystemTimeSource(media_node * clone)
48652a38012Sejakowatz {
48752a38012Sejakowatz 	CALLED();
48886bce45bSbeveloper 	status_t rv;
48986bce45bSbeveloper 
49086bce45bSbeveloper 	// XXX need to do this in a nicer way.
49186bce45bSbeveloper 
49286bce45bSbeveloper 	rv = MediaRosterEx(this)->GetNode(SYSTEM_TIME_SOURCE, clone);
49386bce45bSbeveloper 	if (rv != B_OK)
49486bce45bSbeveloper 		return rv;
49586bce45bSbeveloper 
49686bce45bSbeveloper 	// We don't do reference counting for timesources, that's why we
49786bce45bSbeveloper 	// release the node immediately.
49886bce45bSbeveloper 	ReleaseNode(*clone);
49986bce45bSbeveloper 
50086bce45bSbeveloper 	// we need to remember to not use this node with server side reference counting
50186bce45bSbeveloper 	clone->kind |= NODE_KIND_NO_REFCOUNTING;
50286bce45bSbeveloper 
50386bce45bSbeveloper 	return B_OK;
50452a38012Sejakowatz }
50552a38012Sejakowatz 
50652a38012Sejakowatz 
50752a38012Sejakowatz status_t
50852a38012Sejakowatz BMediaRoster::ReleaseNode(const media_node & node)
50952a38012Sejakowatz {
5109e9417d2Sbeveloper 	CALLED();
51140f36b03Sbeveloper 	if (IS_INVALID_NODE(node))
5129e9417d2Sbeveloper 		return B_MEDIA_BAD_NODE;
51352a38012Sejakowatz 
51486bce45bSbeveloper 	if (node.kind & NODE_KIND_NO_REFCOUNTING) {
51586bce45bSbeveloper 		printf("BMediaRoster::ReleaseNode, trying to release reference counting disabled timesource, node %ld, port %ld, team %ld\n", node.node, node.port, team);
51686bce45bSbeveloper 		return B_OK;
51786bce45bSbeveloper 	}
51886bce45bSbeveloper 
5199e9417d2Sbeveloper 	server_release_node_request request;
5209e9417d2Sbeveloper 	server_release_node_reply reply;
521cf4e2277Sbeveloper 	status_t rv;
5229e9417d2Sbeveloper 
5239e9417d2Sbeveloper 	request.node = node;
5249e9417d2Sbeveloper 	request.team = team;
5259e9417d2Sbeveloper 
52660f15390Sbeveloper 	TRACE("BMediaRoster::ReleaseNode, node %ld, port %ld, team %ld\n", node.node, node.port, team);
527cf4e2277Sbeveloper 
528cf4e2277Sbeveloper 	rv = QueryServer(SERVER_RELEASE_NODE, &request, sizeof(request), &reply, sizeof(reply));
529cf4e2277Sbeveloper 	if (rv != B_OK) {
530cf4e2277Sbeveloper 		FATAL("BMediaRoster::ReleaseNode FAILED, node %ld, port %ld, team %ld!\n", node.node, node.port, team);
531cf4e2277Sbeveloper 	}
532cf4e2277Sbeveloper 	return rv;
5339e9417d2Sbeveloper }
53452a38012Sejakowatz 
53552a38012Sejakowatz BTimeSource *
53652a38012Sejakowatz BMediaRoster::MakeTimeSourceFor(const media_node & for_node)
53752a38012Sejakowatz {
538835140c8Sbeveloper 	CALLED();
539287f7492Sbeveloper 
5400e21b167Sbeveloper 	BTimeSource *source;
541287f7492Sbeveloper 
54260f15390Sbeveloper 	TRACE("BMediaRoster::MakeTimeSourceFor enter, node %ld, port %ld, kind %#lx\n", for_node.node, for_node.port, for_node.kind);
543287f7492Sbeveloper 
5440e21b167Sbeveloper 	if (0 == (for_node.kind & B_TIME_SOURCE)) {
54560f15390Sbeveloper 		//FATAL("BMediaRoster::MakeTimeSourceFor, node %ld is not a timesource!\n", for_node.node);
5460e21b167Sbeveloper 		// XXX It appears that Cortex calls this function on every node, and expects
5470e21b167Sbeveloper 		// XXX to be returned a system time source if the for_node is not a timesource
5480e21b167Sbeveloper 		media_node clone;
5490e21b167Sbeveloper 		GetSystemTimeSource(&clone);
5500e21b167Sbeveloper 		source = _TimeSourceObjectManager->GetTimeSource(clone);
55186bce45bSbeveloper //		ReleaseNode(clone);
5520e21b167Sbeveloper 	} else {
5530e21b167Sbeveloper 		source = _TimeSourceObjectManager->GetTimeSource(for_node);
5540e21b167Sbeveloper 	}
5550e21b167Sbeveloper 
55660f15390Sbeveloper 	TRACE("BMediaRoster::MakeTimeSourceFor leave, node %ld, port %ld, kind %#lx\n", source->Node().node, source->Node().port, source->Node().kind);
557287f7492Sbeveloper 
558835140c8Sbeveloper 	return source;
55952a38012Sejakowatz }
56052a38012Sejakowatz 
56152a38012Sejakowatz 
56252a38012Sejakowatz status_t
56352a38012Sejakowatz BMediaRoster::Connect(const media_source & from,
56452a38012Sejakowatz 					  const media_destination & to,
56552a38012Sejakowatz 					  media_format * io_format,
56652a38012Sejakowatz 					  media_output * out_output,
56752a38012Sejakowatz 					  media_input * out_input)
56852a38012Sejakowatz {
569eae26d3dSbeveloper 	return BMediaRoster::Connect(from, to, io_format, out_output, out_input, 0);
570eae26d3dSbeveloper }
571eae26d3dSbeveloper 
572eae26d3dSbeveloper 
573eae26d3dSbeveloper status_t
574eae26d3dSbeveloper BMediaRoster::Connect(const media_source & from,
575eae26d3dSbeveloper 					  const media_destination & to,
576eae26d3dSbeveloper 					  media_format * io_format,
577eae26d3dSbeveloper 					  media_output * out_output,
578eae26d3dSbeveloper 					  media_input * out_input,
579eae26d3dSbeveloper 					  uint32 in_flags,
580eae26d3dSbeveloper 					  void * _reserved)
581eae26d3dSbeveloper {
58252a38012Sejakowatz 	CALLED();
58352a38012Sejakowatz 	if (io_format == NULL || out_output == NULL || out_input == NULL)
58452a38012Sejakowatz 		return B_BAD_VALUE;
58540f36b03Sbeveloper 	if (IS_INVALID_SOURCE(from)) {
586353b9f6bSbeveloper 		FATAL("BMediaRoster::Connect: media_source invalid\n");
58752a38012Sejakowatz 		return B_MEDIA_BAD_SOURCE;
5889e9417d2Sbeveloper 	}
58940f36b03Sbeveloper 	if (IS_INVALID_DESTINATION(to)) {
590353b9f6bSbeveloper 		FATAL("BMediaRoster::Connect: media_destination invalid\n");
59152a38012Sejakowatz 		return B_MEDIA_BAD_DESTINATION;
5929e9417d2Sbeveloper 	}
59352a38012Sejakowatz 
59452a38012Sejakowatz 	status_t rv;
5958c6a6096Sbeveloper 	producer_format_proposal_request request1;
5968c6a6096Sbeveloper 	producer_format_proposal_reply reply1;
59752a38012Sejakowatz 
59852a38012Sejakowatz 	// BBufferProducer::FormatProposal
5998c6a6096Sbeveloper 	request1.output = from;
6008c6a6096Sbeveloper 	request1.format = *io_format;
6018c6a6096Sbeveloper 	rv = QueryPort(from.port, PRODUCER_FORMAT_PROPOSAL, &request1, sizeof(request1), &reply1, sizeof(reply1));
6028c6a6096Sbeveloper 	if (rv != B_OK) {
603353b9f6bSbeveloper 		FATAL("BMediaRoster::Connect: aborted after BBufferProducer::FormatProposal, status = %#lx\n",rv);
60452a38012Sejakowatz 		return rv;
60552a38012Sejakowatz 	}
6068c6a6096Sbeveloper 	// reply1.format now contains the format proposed by the producer
6078c6a6096Sbeveloper 
6088c6a6096Sbeveloper 	consumer_accept_format_request request2;
6098c6a6096Sbeveloper 	consumer_accept_format_reply reply2;
6108c6a6096Sbeveloper 
6118c6a6096Sbeveloper 	// BBufferConsumer::AcceptFormat
6128c6a6096Sbeveloper 	request2.dest = to;
6138c6a6096Sbeveloper 	request2.format = reply1.format;
6148c6a6096Sbeveloper 	rv = QueryPort(to.port, CONSUMER_ACCEPT_FORMAT, &request2, sizeof(request2), &reply2, sizeof(reply2));
6158c6a6096Sbeveloper 	if (rv != B_OK) {
616353b9f6bSbeveloper 		FATAL("BMediaRoster::Connect: aborted after BBufferConsumer::AcceptFormat, status = %#lx\n",rv);
6178c6a6096Sbeveloper 		return rv;
6188c6a6096Sbeveloper 	}
6198c6a6096Sbeveloper 	// reply2.format now contains the format accepted by the consumer
6208c6a6096Sbeveloper 
6218c6a6096Sbeveloper 	// BBufferProducer::PrepareToConnect
6228c6a6096Sbeveloper 	producer_prepare_to_connect_request request3;
6238c6a6096Sbeveloper 	producer_prepare_to_connect_reply reply3;
6248c6a6096Sbeveloper 
6258c6a6096Sbeveloper 	request3.source = from;
6268c6a6096Sbeveloper 	request3.destination = to;
6278c6a6096Sbeveloper 	request3.format = reply2.format;
6288c6a6096Sbeveloper 	strcpy(request3.name, "XXX some default name"); // XXX fix this
6298c6a6096Sbeveloper 	rv = QueryPort(from.port, PRODUCER_PREPARE_TO_CONNECT, &request3, sizeof(request3), &reply3, sizeof(reply3));
6308c6a6096Sbeveloper 	if (rv != B_OK) {
631353b9f6bSbeveloper 		FATAL("BMediaRoster::Connect: aborted after BBufferProducer::PrepareToConnect, status = %#lx\n",rv);
6328c6a6096Sbeveloper 		return rv;
6338c6a6096Sbeveloper 	}
6348c6a6096Sbeveloper 	// reply3.format is still our pretty media format
6358c6a6096Sbeveloper 	// reply3.out_source the real source to be used for the connection
6368c6a6096Sbeveloper 	// reply3.name the name BBufferConsumer::Connected will see in the outInput->name argument
6378c6a6096Sbeveloper 
6388c6a6096Sbeveloper 	// BBufferConsumer::Connected
6398c6a6096Sbeveloper 	consumer_connected_request request4;
6408c6a6096Sbeveloper 	consumer_connected_reply reply4;
6418c6a6096Sbeveloper 	status_t con_status;
6428c6a6096Sbeveloper 
6438c6a6096Sbeveloper 	request4.producer = reply3.out_source;
6448c6a6096Sbeveloper 	request4.where = to;
6458c6a6096Sbeveloper 	request4.with_format = reply3.format;
6468c6a6096Sbeveloper 	con_status = QueryPort(to.port, CONSUMER_CONNECTED, &request4, sizeof(request4), &reply4, sizeof(reply4));
6478c6a6096Sbeveloper 	if (con_status != B_OK) {
648353b9f6bSbeveloper 		FATAL("BMediaRoster::Connect: aborting after BBufferConsumer::Connected, status = %#lx\n",con_status);
6498c6a6096Sbeveloper 		// we do NOT return here!
6508c6a6096Sbeveloper 	}
6518c6a6096Sbeveloper 	// con_status contains the status code to be supplied to BBufferProducer::Connect's status argument
6528c6a6096Sbeveloper 	// reply4.input contains the media_input that describes the connection from the consumer point of view
6538c6a6096Sbeveloper 
6548c6a6096Sbeveloper 	// BBufferProducer::Connect
6558c6a6096Sbeveloper 	producer_connect_request request5;
6568c6a6096Sbeveloper 	producer_connect_reply reply5;
6578c6a6096Sbeveloper 
6588c6a6096Sbeveloper 	request5.error = con_status;
6598c6a6096Sbeveloper 	request5.source = reply3.out_source;
6608c6a6096Sbeveloper 	request5.destination = reply4.input.destination;
6618c6a6096Sbeveloper 	request5.format = reply3.format; // XXX reply4.input.format ???
6628c6a6096Sbeveloper 	strcpy(request5.name, reply4.input.name);
6630caff283Sbeveloper 	rv = QueryPort(reply4.input.source.port, PRODUCER_CONNECT, &request5, sizeof(request5), &reply5, sizeof(reply5));
6648c6a6096Sbeveloper 	if (con_status != B_OK) {
665353b9f6bSbeveloper 		FATAL("BMediaRoster::Connect: aborted\n");
6668c6a6096Sbeveloper 		return con_status;
6678c6a6096Sbeveloper 	}
6688c6a6096Sbeveloper 	if (rv != B_OK) {
669353b9f6bSbeveloper 		FATAL("BMediaRoster::Connect: aborted after BBufferProducer::Connect, status = %#lx\n",rv);
6708c6a6096Sbeveloper 		return rv;
6718c6a6096Sbeveloper 	}
6728c6a6096Sbeveloper 	// reply5.name contains the name assigned to the connection by the producer
6738c6a6096Sbeveloper 
6748c6a6096Sbeveloper 	// find the output node
6758c6a6096Sbeveloper 	// XXX isn't there a easier way?
6768c6a6096Sbeveloper 	media_node sourcenode;
6778c6a6096Sbeveloper 	GetNodeFor(NodeIDFor(from.port), &sourcenode);
6788c6a6096Sbeveloper 	ReleaseNode(sourcenode);
6798c6a6096Sbeveloper 
6808c6a6096Sbeveloper 	// initilize connection info
6818c6a6096Sbeveloper 	*io_format = reply3.format;
6828c6a6096Sbeveloper 	*out_input = reply4.input;
6838c6a6096Sbeveloper 	out_output->node = sourcenode;
6848c6a6096Sbeveloper 	out_output->source = reply4.input.source;
6858c6a6096Sbeveloper 	out_output->destination = reply4.input.destination;
6868c6a6096Sbeveloper 	out_output->format = reply4.input.format;
6878c6a6096Sbeveloper 	strcpy(out_output->name, reply5.name);
6888c6a6096Sbeveloper 
6898c6a6096Sbeveloper 	// the connection is now made
6908c6a6096Sbeveloper 
6918c6a6096Sbeveloper 
6928c6a6096Sbeveloper 	// XXX register connection with server
6939e9417d2Sbeveloper 	// XXX we should just send a notification, instead of republishing all endpoints
69476669a29Sbeveloper 	List<media_output> outlist;
69576669a29Sbeveloper 	List<media_input> inlist;
6968b04ffc1Sbeveloper 	if (B_OK == MediaRosterEx(this)->GetAllOutputs(out_output->node , &outlist))
6978b04ffc1Sbeveloper 		MediaRosterEx(this)->PublishOutputs(out_output->node , &outlist);
6988b04ffc1Sbeveloper 	if (B_OK == MediaRosterEx(this)->GetAllInputs(out_input->node , &inlist))
6998b04ffc1Sbeveloper 		MediaRosterEx(this)->PublishInputs(out_input->node, &inlist);
7008c6a6096Sbeveloper 
7018c6a6096Sbeveloper 
7028c6a6096Sbeveloper 	// XXX if (mute) BBufferProducer::EnableOutput(false)
7039e9417d2Sbeveloper 	if (in_flags & B_CONNECT_MUTED) {
7049e9417d2Sbeveloper 	}
7058c6a6096Sbeveloper 
7068c6a6096Sbeveloper 
7079e9417d2Sbeveloper 	// send a notification
7089e9417d2Sbeveloper 	BPrivate::media::notifications::ConnectionMade(*out_input, *out_output, *io_format);
7099e9417d2Sbeveloper 
7108c6a6096Sbeveloper 	return B_OK;
7118c6a6096Sbeveloper };
71252a38012Sejakowatz 
71352a38012Sejakowatz 
71452a38012Sejakowatz status_t
7159e9417d2Sbeveloper BMediaRoster::Disconnect(media_node_id source_nodeid,
71652a38012Sejakowatz 						 const media_source & source,
7179e9417d2Sbeveloper 						 media_node_id destination_nodeid,
71852a38012Sejakowatz 						 const media_destination & destination)
71952a38012Sejakowatz {
7209e9417d2Sbeveloper 	CALLED();
72140f36b03Sbeveloper 	if (IS_INVALID_NODEID(source_nodeid)) {
722353b9f6bSbeveloper 		FATAL("BMediaRoster::Disconnect: source media_node_id invalid\n");
7239e9417d2Sbeveloper 		return B_MEDIA_BAD_SOURCE;
7249e9417d2Sbeveloper 	}
72540f36b03Sbeveloper 	if (IS_INVALID_NODEID(destination_nodeid)) {
72640f36b03Sbeveloper 		FATAL("BMediaRoster::Disconnect: destination media_node_id invalid\n");
7279e9417d2Sbeveloper 		return B_MEDIA_BAD_DESTINATION;
7289e9417d2Sbeveloper 	}
72940f36b03Sbeveloper 	if (IS_INVALID_SOURCE(source)) {
730353b9f6bSbeveloper 		FATAL("BMediaRoster::Disconnect: media_source invalid\n");
7319e9417d2Sbeveloper 		return B_MEDIA_BAD_SOURCE;
7329e9417d2Sbeveloper 	}
73340f36b03Sbeveloper 	if (IS_INVALID_DESTINATION(destination)) {
734353b9f6bSbeveloper 		FATAL("BMediaRoster::Disconnect: media_destination invalid\n");
7359e9417d2Sbeveloper 		return B_MEDIA_BAD_DESTINATION;
7369e9417d2Sbeveloper 	}
7379e9417d2Sbeveloper 
7389e9417d2Sbeveloper 	producer_disconnect_request request2;
7399e9417d2Sbeveloper 	producer_disconnect_reply reply2;
7409e9417d2Sbeveloper 	consumer_disconnected_request request1;
7419e9417d2Sbeveloper 	consumer_disconnected_reply reply1;
7429e9417d2Sbeveloper 	status_t rv1, rv2;
7439e9417d2Sbeveloper 
7449e9417d2Sbeveloper 	// XXX we should ask the server if this connection really exists
7459e9417d2Sbeveloper 
7469e9417d2Sbeveloper 	request1.source = source;
7479e9417d2Sbeveloper 	request1.destination = destination;
7489e9417d2Sbeveloper 	request2.source = source;
7499e9417d2Sbeveloper 	request2.destination = destination;
7509e9417d2Sbeveloper 
7519e9417d2Sbeveloper 	rv1 = QueryPort(source.port, PRODUCER_DISCONNECT, &request1, sizeof(request1), &reply1, sizeof(reply1));
7529e9417d2Sbeveloper 	rv2 = QueryPort(destination.port, CONSUMER_DISCONNECTED, &request2, sizeof(request2), &reply2, sizeof(reply2));
7539e9417d2Sbeveloper 
7549e9417d2Sbeveloper 	// XXX unregister connection with server
7559e9417d2Sbeveloper 	// XXX we should just send a notification, instead of republishing all endpoints
75676669a29Sbeveloper 	List<media_output> outlist;
75776669a29Sbeveloper 	List<media_input> inlist;
7589e9417d2Sbeveloper 	media_node sourcenode;
7599e9417d2Sbeveloper 	media_node destnode;
7609e9417d2Sbeveloper 	if (B_OK == GetNodeFor(source_nodeid, &sourcenode)) {
7618b04ffc1Sbeveloper 		if (B_OK == MediaRosterEx(this)->GetAllOutputs(sourcenode , &outlist))
7628b04ffc1Sbeveloper 			MediaRosterEx(this)->PublishOutputs(sourcenode , &outlist);
7639e9417d2Sbeveloper 		ReleaseNode(sourcenode);
764353b9f6bSbeveloper 	} else FATAL("BMediaRoster::Disconnect: source GetNodeFor failed\n");
7659e9417d2Sbeveloper 	if (B_OK == GetNodeFor(destination_nodeid, &destnode)) {
7668b04ffc1Sbeveloper 		if (B_OK == MediaRosterEx(this)->GetAllInputs(destnode , &inlist))
7678b04ffc1Sbeveloper 			MediaRosterEx(this)->PublishInputs(destnode, &inlist);
7689e9417d2Sbeveloper 		ReleaseNode(destnode);
769353b9f6bSbeveloper 	} else FATAL("BMediaRoster::Disconnect: dest GetNodeFor failed\n");
7709e9417d2Sbeveloper 
7719e9417d2Sbeveloper 
7729e9417d2Sbeveloper 	// send a notification
7739e9417d2Sbeveloper 	BPrivate::media::notifications::ConnectionBroken(source, destination);
7749e9417d2Sbeveloper 
7759e9417d2Sbeveloper 	return (rv1 != B_OK || rv2 != B_OK) ? B_ERROR : B_OK;
77652a38012Sejakowatz }
77752a38012Sejakowatz 
77852a38012Sejakowatz 
77952a38012Sejakowatz status_t
78052a38012Sejakowatz BMediaRoster::StartNode(const media_node & node,
78152a38012Sejakowatz 						bigtime_t at_performance_time)
78252a38012Sejakowatz {
78352a38012Sejakowatz 	CALLED();
7849e9417d2Sbeveloper 	if (node.node <= 0)
78552a38012Sejakowatz 		return B_MEDIA_BAD_NODE;
78652a38012Sejakowatz 
78760f15390Sbeveloper 	TRACE("BMediaRoster::StartNode, node %ld, at perf %Ld\n", node.node, at_performance_time);
7880e21b167Sbeveloper 
7896396865dSbeveloper 	node_start_command command;
7906396865dSbeveloper 	command.performance_time = at_performance_time;
79152a38012Sejakowatz 
7926396865dSbeveloper 	return SendToPort(node.port, NODE_START, &command, sizeof(command));
79352a38012Sejakowatz }
79452a38012Sejakowatz 
79552a38012Sejakowatz 
79652a38012Sejakowatz status_t
79752a38012Sejakowatz BMediaRoster::StopNode(const media_node & node,
79852a38012Sejakowatz 					   bigtime_t at_performance_time,
79952a38012Sejakowatz 					   bool immediate)
80052a38012Sejakowatz {
80152a38012Sejakowatz 	CALLED();
80240f36b03Sbeveloper 	if (IS_INVALID_NODE(node))
80352a38012Sejakowatz 		return B_MEDIA_BAD_NODE;
80452a38012Sejakowatz 
80560f15390Sbeveloper 	TRACE("BMediaRoster::StopNode, node %ld, at perf %Ld %s\n", node.node, at_performance_time, immediate ? "NOW" : "");
8060e21b167Sbeveloper 
8076396865dSbeveloper 	node_stop_command command;
8086396865dSbeveloper 	command.performance_time = at_performance_time;
8096396865dSbeveloper 	command.immediate = immediate;
81052a38012Sejakowatz 
8116396865dSbeveloper 	return SendToPort(node.port, NODE_STOP, &command, sizeof(command));
81252a38012Sejakowatz }
81352a38012Sejakowatz 
81452a38012Sejakowatz 
81552a38012Sejakowatz status_t
81652a38012Sejakowatz BMediaRoster::SeekNode(const media_node & node,
81752a38012Sejakowatz 					   bigtime_t to_media_time,
81852a38012Sejakowatz 					   bigtime_t at_performance_time)
81952a38012Sejakowatz {
82052a38012Sejakowatz 	CALLED();
82140f36b03Sbeveloper 	if (IS_INVALID_NODE(node))
82252a38012Sejakowatz 		return B_MEDIA_BAD_NODE;
82352a38012Sejakowatz 
82460f15390Sbeveloper 	TRACE("BMediaRoster::SeekNode, node %ld, at perf %Ld, to perf %Ld\n", node.node, at_performance_time, to_media_time);
8250e21b167Sbeveloper 
8266396865dSbeveloper 	node_seek_command command;
8276396865dSbeveloper 	command.media_time = to_media_time;
8286396865dSbeveloper 	command.performance_time = at_performance_time;
82952a38012Sejakowatz 
8306396865dSbeveloper 	return SendToPort(node.port, NODE_SEEK, &command, sizeof(command));
83152a38012Sejakowatz }
83252a38012Sejakowatz 
83352a38012Sejakowatz 
83452a38012Sejakowatz status_t
83552a38012Sejakowatz BMediaRoster::StartTimeSource(const media_node & node,
83652a38012Sejakowatz 							  bigtime_t at_real_time)
83752a38012Sejakowatz {
83852a38012Sejakowatz 	CALLED();
83960f15390Sbeveloper 	if (IS_SYSTEM_TIMESOURCE(node)) {
84060f15390Sbeveloper 		// XXX debug this
84160f15390Sbeveloper 		//FATAL("BMediaRoster::StartTimeSource node %ld is system timesource\n", node.node);
84260f15390Sbeveloper 		return B_OK;
84360f15390Sbeveloper 	}
84460f15390Sbeveloper 	if (IS_SHADOW_TIMESOURCE(node)) {
84560f15390Sbeveloper 		// XXX debug this
84660f15390Sbeveloper 		FATAL("BMediaRoster::StartTimeSource node %ld is shadow timesource\n", node.node);
84760f15390Sbeveloper 		return B_OK;
84860f15390Sbeveloper 	}
84940f36b03Sbeveloper 	if (IS_INVALID_NODE(node)) {
85060f15390Sbeveloper 		FATAL("BMediaRoster::StartTimeSource node %ld invalid\n", node.node);
85152a38012Sejakowatz 		return B_MEDIA_BAD_NODE;
8520e21b167Sbeveloper 	}
8530e21b167Sbeveloper 	if ((node.kind & B_TIME_SOURCE) == 0) {
85460f15390Sbeveloper 		FATAL("BMediaRoster::StartTimeSource node %ld is no timesource\n", node.node);
85552a38012Sejakowatz 		return B_MEDIA_BAD_NODE;
8560e21b167Sbeveloper 	}
8570e21b167Sbeveloper 
85860f15390Sbeveloper 	TRACE("BMediaRoster::StartTimeSource, node %ld, at real %Ld\n", node.node, at_real_time);
85952a38012Sejakowatz 
86052a38012Sejakowatz 	BTimeSource::time_source_op_info msg;
86152a38012Sejakowatz 	msg.op = BTimeSource::B_TIMESOURCE_START;
86252a38012Sejakowatz 	msg.real_time = at_real_time;
86352a38012Sejakowatz 
86452a38012Sejakowatz 	return write_port(node.port, TIMESOURCE_OP, &msg, sizeof(msg));
86552a38012Sejakowatz }
86652a38012Sejakowatz 
86752a38012Sejakowatz 
86852a38012Sejakowatz status_t
86952a38012Sejakowatz BMediaRoster::StopTimeSource(const media_node & node,
87052a38012Sejakowatz 							 bigtime_t at_real_time,
87152a38012Sejakowatz 							 bool immediate)
87252a38012Sejakowatz {
87352a38012Sejakowatz 	CALLED();
87460f15390Sbeveloper 	if (IS_SYSTEM_TIMESOURCE(node)) {
87560f15390Sbeveloper 		// XXX debug this
87660f15390Sbeveloper 		//FATAL("BMediaRoster::StopTimeSource node %ld is system timesource\n", node.node);
87760f15390Sbeveloper 		return B_OK;
87860f15390Sbeveloper 	}
87960f15390Sbeveloper 	if (IS_SHADOW_TIMESOURCE(node)) {
88060f15390Sbeveloper 		// XXX debug this
88160f15390Sbeveloper 		FATAL("BMediaRoster::StopTimeSource node %ld is shadow timesource\n", node.node);
88260f15390Sbeveloper 		return B_OK;
88360f15390Sbeveloper 	}
88440f36b03Sbeveloper 	if (IS_INVALID_NODE(node)) {
88560f15390Sbeveloper 		FATAL("BMediaRoster::StopTimeSource node %ld invalid\n", node.node);
88652a38012Sejakowatz 		return B_MEDIA_BAD_NODE;
8870e21b167Sbeveloper 	}
8880e21b167Sbeveloper 	if ((node.kind & B_TIME_SOURCE) == 0) {
88960f15390Sbeveloper 		FATAL("BMediaRoster::StopTimeSource node %ld is no timesource\n", node.node);
89052a38012Sejakowatz 		return B_MEDIA_BAD_NODE;
8910e21b167Sbeveloper 	}
8920e21b167Sbeveloper 
89360f15390Sbeveloper 	TRACE("BMediaRoster::StopTimeSource, node %ld, at real %Ld %s\n", node.node, at_real_time, immediate ? "NOW" : "");
89452a38012Sejakowatz 
89552a38012Sejakowatz 	BTimeSource::time_source_op_info msg;
89652a38012Sejakowatz 	msg.op = immediate ? BTimeSource::B_TIMESOURCE_STOP_IMMEDIATELY : BTimeSource::B_TIMESOURCE_STOP;
89752a38012Sejakowatz 	msg.real_time = at_real_time;
89852a38012Sejakowatz 
89952a38012Sejakowatz 	return write_port(node.port, TIMESOURCE_OP, &msg, sizeof(msg));
90052a38012Sejakowatz }
90152a38012Sejakowatz 
90252a38012Sejakowatz 
90352a38012Sejakowatz status_t
90452a38012Sejakowatz BMediaRoster::SeekTimeSource(const media_node & node,
90552a38012Sejakowatz 							 bigtime_t to_performance_time,
90652a38012Sejakowatz 							 bigtime_t at_real_time)
90752a38012Sejakowatz {
90852a38012Sejakowatz 	CALLED();
90960f15390Sbeveloper 	if (IS_SYSTEM_TIMESOURCE(node)) {
91060f15390Sbeveloper 		// XXX debug this
91160f15390Sbeveloper 		// FATAL("BMediaRoster::SeekTimeSource node %ld is system timesource\n", node.node);
91260f15390Sbeveloper 		// you can't seek the system time source, but
91360f15390Sbeveloper 		// returning B_ERROR would break StampTV
91460f15390Sbeveloper 		return B_OK;
91560f15390Sbeveloper 	}
91660f15390Sbeveloper 	if (IS_SHADOW_TIMESOURCE(node)) {
91760f15390Sbeveloper 		// XXX debug this
91860f15390Sbeveloper 		FATAL("BMediaRoster::SeekTimeSource node %ld is shadow timesource\n", node.node);
91960f15390Sbeveloper 		return B_OK;
92060f15390Sbeveloper 	}
92140f36b03Sbeveloper 	if (IS_INVALID_NODE(node)) {
92260f15390Sbeveloper 		FATAL("BMediaRoster::SeekTimeSource node %ld invalid\n", node.node);
92352a38012Sejakowatz 		return B_MEDIA_BAD_NODE;
9240e21b167Sbeveloper 	}
9250e21b167Sbeveloper 	if ((node.kind & B_TIME_SOURCE) == 0) {
92660f15390Sbeveloper 		FATAL("BMediaRoster::SeekTimeSource node %ld is no timesource\n", node.node);
92752a38012Sejakowatz 		return B_MEDIA_BAD_NODE;
9280e21b167Sbeveloper 	}
9290e21b167Sbeveloper 
93060f15390Sbeveloper 	TRACE("BMediaRoster::SeekTimeSource, node %ld, at real %Ld, to perf %Ld\n", node.node, at_real_time, to_performance_time);
93152a38012Sejakowatz 
93252a38012Sejakowatz 	BTimeSource::time_source_op_info msg;
93352a38012Sejakowatz 	msg.op = BTimeSource::B_TIMESOURCE_SEEK;
93452a38012Sejakowatz 	msg.real_time = at_real_time;
93552a38012Sejakowatz 	msg.performance_time = to_performance_time;
93652a38012Sejakowatz 
93752a38012Sejakowatz 	return write_port(node.port, TIMESOURCE_OP, &msg, sizeof(msg));
93852a38012Sejakowatz }
93952a38012Sejakowatz 
94052a38012Sejakowatz 
94152a38012Sejakowatz status_t
94252a38012Sejakowatz BMediaRoster::SyncToNode(const media_node & node,
94352a38012Sejakowatz 						 bigtime_t at_time,
94452a38012Sejakowatz 						 bigtime_t timeout)
94552a38012Sejakowatz {
94652a38012Sejakowatz 	UNIMPLEMENTED();
94760f15390Sbeveloper 	return B_OK;
94852a38012Sejakowatz }
94952a38012Sejakowatz 
95052a38012Sejakowatz 
95152a38012Sejakowatz status_t
95252a38012Sejakowatz BMediaRoster::SetRunModeNode(const media_node & node,
95352a38012Sejakowatz 							 BMediaNode::run_mode mode)
95452a38012Sejakowatz {
95552a38012Sejakowatz 	CALLED();
95640f36b03Sbeveloper 	if (IS_INVALID_NODE(node))
95752a38012Sejakowatz 		return B_MEDIA_BAD_NODE;
95852a38012Sejakowatz 
959dfb2ad61Sbeveloper 	node_set_run_mode_command msg;
96052a38012Sejakowatz 	msg.mode = mode;
96152a38012Sejakowatz 
96252a38012Sejakowatz 	return write_port(node.port, NODE_SET_RUN_MODE, &msg, sizeof(msg));
96352a38012Sejakowatz }
96452a38012Sejakowatz 
96552a38012Sejakowatz 
96652a38012Sejakowatz status_t
96752a38012Sejakowatz BMediaRoster::PrerollNode(const media_node & node)
96852a38012Sejakowatz {
96952a38012Sejakowatz 	CALLED();
97040f36b03Sbeveloper 	if (IS_INVALID_NODE(node))
97152a38012Sejakowatz 		return B_MEDIA_BAD_NODE;
97252a38012Sejakowatz 
97352a38012Sejakowatz 	char dummy;
97452a38012Sejakowatz 	return write_port(node.port, NODE_PREROLL, &dummy, sizeof(dummy));
97552a38012Sejakowatz }
97652a38012Sejakowatz 
97752a38012Sejakowatz 
97852a38012Sejakowatz status_t
97952a38012Sejakowatz BMediaRoster::RollNode(const media_node & node,
98052a38012Sejakowatz 					   bigtime_t startPerformance,
98152a38012Sejakowatz 					   bigtime_t stopPerformance,
98252a38012Sejakowatz 					   bigtime_t atMediaTime)
98352a38012Sejakowatz {
98452a38012Sejakowatz 	UNIMPLEMENTED();
98552a38012Sejakowatz 	return B_ERROR;
98652a38012Sejakowatz }
98752a38012Sejakowatz 
98852a38012Sejakowatz 
98952a38012Sejakowatz status_t
99052a38012Sejakowatz BMediaRoster::SetProducerRunModeDelay(const media_node & node,
99152a38012Sejakowatz 									  bigtime_t delay,
99252a38012Sejakowatz 									  BMediaNode::run_mode mode)
99352a38012Sejakowatz {
99460f15390Sbeveloper 	CALLED();
99560f15390Sbeveloper 	if (IS_INVALID_NODE(node))
99660f15390Sbeveloper 		return B_MEDIA_BAD_NODE;
99760f15390Sbeveloper 	if ((node.kind & B_BUFFER_PRODUCER) == 0)
99860f15390Sbeveloper 		return B_MEDIA_BAD_NODE;
99960f15390Sbeveloper 
100060f15390Sbeveloper 	producer_set_run_mode_delay_command command;
100160f15390Sbeveloper 	command.mode = mode;
100260f15390Sbeveloper 	command.delay = delay;
100360f15390Sbeveloper 
100460f15390Sbeveloper 	return SendToPort(node.port, PRODUCER_SET_RUN_MODE_DELAY, &command, sizeof(command));
100552a38012Sejakowatz }
100652a38012Sejakowatz 
100752a38012Sejakowatz 
100852a38012Sejakowatz status_t
100952a38012Sejakowatz BMediaRoster::SetProducerRate(const media_node & producer,
101052a38012Sejakowatz 							  int32 numer,
101152a38012Sejakowatz 							  int32 denom)
101252a38012Sejakowatz {
101352a38012Sejakowatz 	CALLED();
101440f36b03Sbeveloper 	if (IS_INVALID_NODE(producer))
101552a38012Sejakowatz 		return B_MEDIA_BAD_NODE;
101652a38012Sejakowatz 	if ((producer.kind & B_BUFFER_PRODUCER) == 0)
101752a38012Sejakowatz 		return B_MEDIA_BAD_NODE;
101852a38012Sejakowatz 
1019dfb2ad61Sbeveloper 	producer_set_play_rate_request msg;
1020dfb2ad61Sbeveloper 	producer_set_play_rate_reply reply;
102152a38012Sejakowatz 	status_t rv;
102252a38012Sejakowatz 	int32 code;
102352a38012Sejakowatz 
102452a38012Sejakowatz 	msg.numer = numer;
102552a38012Sejakowatz 	msg.denom = denom;
102652a38012Sejakowatz 	msg.reply_port = _PortPool->GetPort();
102752a38012Sejakowatz 	rv = write_port(producer.node, PRODUCER_SET_PLAY_RATE, &msg, sizeof(msg));
102852a38012Sejakowatz 	if (rv != B_OK) {
102952a38012Sejakowatz 		_PortPool->PutPort(msg.reply_port);
103052a38012Sejakowatz 		return rv;
103152a38012Sejakowatz 	}
103252a38012Sejakowatz 	rv = read_port(msg.reply_port, &code, &reply, sizeof(reply));
103352a38012Sejakowatz 	_PortPool->PutPort(msg.reply_port);
103452a38012Sejakowatz 	return (rv < B_OK) ? rv : reply.result;
103552a38012Sejakowatz }
103652a38012Sejakowatz 
103752a38012Sejakowatz 
103852a38012Sejakowatz /* Nodes will have available inputs/outputs as long as they are capable */
103952a38012Sejakowatz /* of accepting more connections. The node may create an additional */
104052a38012Sejakowatz /* output or input as the currently available is taken into usage. */
104152a38012Sejakowatz status_t
104252a38012Sejakowatz BMediaRoster::GetLiveNodeInfo(const media_node & node,
104352a38012Sejakowatz 							  live_node_info * out_live_info)
104452a38012Sejakowatz {
10459e9417d2Sbeveloper 	CALLED();
10469e9417d2Sbeveloper 	if (out_live_info == NULL)
10479e9417d2Sbeveloper 		return B_BAD_VALUE;
104840f36b03Sbeveloper 	if (IS_INVALID_NODE(node))
10499e9417d2Sbeveloper 		return B_MEDIA_BAD_NODE;
10509e9417d2Sbeveloper 
10519e9417d2Sbeveloper 	server_get_live_node_info_request request;
10529e9417d2Sbeveloper 	server_get_live_node_info_reply reply;
10539e9417d2Sbeveloper 	status_t rv;
10549e9417d2Sbeveloper 
10559e9417d2Sbeveloper 	request.node = node;
10569e9417d2Sbeveloper 
10571299bfb2Sbeveloper 	rv = QueryServer(SERVER_GET_LIVE_NODE_INFO, &request, sizeof(request), &reply, sizeof(reply));
10589e9417d2Sbeveloper 	if (rv != B_OK)
10599e9417d2Sbeveloper 		return rv;
10609e9417d2Sbeveloper 
10619e9417d2Sbeveloper 	*out_live_info = reply.live_info;
10629e9417d2Sbeveloper 	return B_OK;
106352a38012Sejakowatz }
106452a38012Sejakowatz 
106552a38012Sejakowatz 
106652a38012Sejakowatz status_t
106752a38012Sejakowatz BMediaRoster::GetLiveNodes(live_node_info * out_live_nodes,
106852a38012Sejakowatz 						   int32 * io_total_count,
106952a38012Sejakowatz 						   const media_format * has_input,
107052a38012Sejakowatz 						   const media_format * has_output,
107152a38012Sejakowatz 						   const char * name,
107252a38012Sejakowatz 						   uint64 node_kinds)
107352a38012Sejakowatz {
10749e9417d2Sbeveloper 	CALLED();
10759e9417d2Sbeveloper 	if (out_live_nodes == NULL || io_total_count == NULL)
10769e9417d2Sbeveloper 		return B_BAD_VALUE;
10779e9417d2Sbeveloper 	if (*io_total_count <= 0)
10789e9417d2Sbeveloper 		return B_BAD_VALUE;
10799e9417d2Sbeveloper 
10809e9417d2Sbeveloper 	// XXX we also support the wildcard search as GetDormantNodes does. This needs to be documented
10819e9417d2Sbeveloper 
10829e9417d2Sbeveloper 	server_get_live_nodes_request request;
10839e9417d2Sbeveloper 	server_get_live_nodes_reply reply;
10849e9417d2Sbeveloper 	status_t rv;
10859e9417d2Sbeveloper 
10869e9417d2Sbeveloper 	request.maxcount = *io_total_count;
10879e9417d2Sbeveloper 	request.has_input = (bool) has_input;
10889e9417d2Sbeveloper 	if (has_input)
10899e9417d2Sbeveloper 		request.inputformat = *has_input; // XXX we should not make a flat copy of media_format
10909e9417d2Sbeveloper 	request.has_output = (bool) has_output;
10919e9417d2Sbeveloper 	if (has_output)
10929e9417d2Sbeveloper 		request.outputformat = *has_output; // XXX we should not make a flat copy of media_format
10939e9417d2Sbeveloper 	request.has_name = (bool) name;
10949e9417d2Sbeveloper 	if (name) {
10959e9417d2Sbeveloper 		int len = strlen(name);
10969e9417d2Sbeveloper 		len = min_c(len, (int)sizeof(request.name) - 1);
10979e9417d2Sbeveloper 		memcpy(request.name, name, len);
10989e9417d2Sbeveloper 		request.name[len] = 0;
10999e9417d2Sbeveloper 	}
11009e9417d2Sbeveloper 	request.require_kinds = node_kinds;
11019e9417d2Sbeveloper 
11029e9417d2Sbeveloper 	rv = QueryServer(SERVER_GET_LIVE_NODES, &request, sizeof(request), &reply, sizeof(reply));
11039e9417d2Sbeveloper 	if (rv != B_OK) {
1104353b9f6bSbeveloper 		FATAL("BMediaRoster::GetLiveNodes failed\n");
11051299bfb2Sbeveloper 		*io_total_count = 0;
11069e9417d2Sbeveloper 		return rv;
11079e9417d2Sbeveloper 	}
11089e9417d2Sbeveloper 
11099e9417d2Sbeveloper 	if (reply.count > MAX_LIVE_INFO) {
11109e9417d2Sbeveloper 		live_node_info *live_info;
11119e9417d2Sbeveloper 		area_id clone;
11129e9417d2Sbeveloper 
11139e9417d2Sbeveloper 		clone = clone_area("live_node_info clone", reinterpret_cast<void **>(&live_info), B_ANY_ADDRESS, B_READ_AREA | B_WRITE_AREA, reply.area);
11149e9417d2Sbeveloper 		if (clone < B_OK) {
1115353b9f6bSbeveloper 			FATAL("BMediaRoster::GetLiveNodes failed to clone area, %#lx\n", clone);
11169e9417d2Sbeveloper 			delete_area(reply.area);
11171299bfb2Sbeveloper 			*io_total_count = 0;
111852a38012Sejakowatz 			return B_ERROR;
111952a38012Sejakowatz 		}
112052a38012Sejakowatz 
11219e9417d2Sbeveloper 		for (int32 i = 0; i < reply.count; i++) {
11229e9417d2Sbeveloper 			out_live_nodes[i] = live_info[i];
11239e9417d2Sbeveloper 		}
11249e9417d2Sbeveloper 
11259e9417d2Sbeveloper 		delete_area(clone);
11269e9417d2Sbeveloper 		delete_area(reply.area);
11279e9417d2Sbeveloper 	} else {
11289e9417d2Sbeveloper 		for (int32 i = 0; i < reply.count; i++) {
11299e9417d2Sbeveloper 			out_live_nodes[i] = reply.live_info[i];
11309e9417d2Sbeveloper 		}
11319e9417d2Sbeveloper 	}
11329e9417d2Sbeveloper 	*io_total_count = reply.count;
11339e9417d2Sbeveloper 
11349e9417d2Sbeveloper 	return B_OK;
11359e9417d2Sbeveloper }
11369e9417d2Sbeveloper 
113752a38012Sejakowatz 
113852a38012Sejakowatz status_t
113952a38012Sejakowatz BMediaRoster::GetFreeInputsFor(const media_node & node,
114052a38012Sejakowatz 							   media_input * out_free_inputs,
114152a38012Sejakowatz 							   int32 buf_num_inputs,
114252a38012Sejakowatz 							   int32 * out_total_count,
114352a38012Sejakowatz 							   media_type filter_type)
114452a38012Sejakowatz {
11453620737cSbeveloper 	CALLED();
114640f36b03Sbeveloper 	if (IS_INVALID_NODE(node) || (node.kind & B_BUFFER_CONSUMER) == 0)
11473620737cSbeveloper 		return B_MEDIA_BAD_NODE;
11483620737cSbeveloper 	if (out_free_inputs == NULL || out_total_count == NULL)
11493620737cSbeveloper 		return B_BAD_VALUE;
11503620737cSbeveloper 
115176669a29Sbeveloper 	List<media_input> list;
11523620737cSbeveloper 	media_input *input;
11533620737cSbeveloper 	status_t rv;
11543620737cSbeveloper 
11551299bfb2Sbeveloper 	*out_total_count = 0;
11561299bfb2Sbeveloper 
11578b04ffc1Sbeveloper 	rv = MediaRosterEx(this)->GetAllInputs(node, &list);
11583620737cSbeveloper 	if (B_OK != rv)
11593620737cSbeveloper 		return rv;
11603620737cSbeveloper 
116176669a29Sbeveloper 	int32 i;
116276669a29Sbeveloper 	for (i = 0, list.Rewind(); list.GetNext(&input); i++) {
11633620737cSbeveloper 		if (filter_type != B_MEDIA_UNKNOWN_TYPE && filter_type != input->format.type)
11643620737cSbeveloper 			continue; // media_type used, but doesn't match
11653620737cSbeveloper 		if (input->source != media_source::null)
11663620737cSbeveloper 			continue; // consumer source already connected
11673620737cSbeveloper 		out_free_inputs[i] = *input;
11683620737cSbeveloper 		*out_total_count += 1;
11693620737cSbeveloper 		buf_num_inputs -= 1;
11703620737cSbeveloper 		if (buf_num_inputs == 0)
11713620737cSbeveloper 			break;
11723620737cSbeveloper 	}
11733620737cSbeveloper 
11748b04ffc1Sbeveloper 	MediaRosterEx(this)->PublishInputs(node, &list);
11753620737cSbeveloper 	return B_OK;
117652a38012Sejakowatz }
117752a38012Sejakowatz 
117852a38012Sejakowatz 
117952a38012Sejakowatz status_t
118052a38012Sejakowatz BMediaRoster::GetConnectedInputsFor(const media_node & node,
118152a38012Sejakowatz 									media_input * out_active_inputs,
118252a38012Sejakowatz 									int32 buf_num_inputs,
118352a38012Sejakowatz 									int32 * out_total_count)
118452a38012Sejakowatz {
11853620737cSbeveloper 	CALLED();
118640f36b03Sbeveloper 	if (IS_INVALID_NODE(node) || (node.kind & B_BUFFER_CONSUMER) == 0)
11873620737cSbeveloper 		return B_MEDIA_BAD_NODE;
11883620737cSbeveloper 	if (out_active_inputs == NULL || out_total_count == NULL)
11893620737cSbeveloper 		return B_BAD_VALUE;
11903620737cSbeveloper 
119176669a29Sbeveloper 	List<media_input> list;
11923620737cSbeveloper 	media_input *input;
11933620737cSbeveloper 	status_t rv;
11943620737cSbeveloper 
11951299bfb2Sbeveloper 	*out_total_count = 0;
11961299bfb2Sbeveloper 
11978b04ffc1Sbeveloper 	rv = MediaRosterEx(this)->GetAllInputs(node, &list);
11983620737cSbeveloper 	if (B_OK != rv)
11993620737cSbeveloper 		return rv;
12003620737cSbeveloper 
120176669a29Sbeveloper 	int32 i;
120276669a29Sbeveloper 	for (i = 0, list.Rewind(); list.GetNext(&input); i++) {
12033620737cSbeveloper 		if (input->source == media_source::null)
12043620737cSbeveloper 			continue; // consumer source not connected
12053620737cSbeveloper 		out_active_inputs[i] = *input;
12063620737cSbeveloper 		*out_total_count += 1;
12073620737cSbeveloper 		buf_num_inputs -= 1;
12083620737cSbeveloper 		if (buf_num_inputs == 0)
12093620737cSbeveloper 			break;
12103620737cSbeveloper 	}
12113620737cSbeveloper 
12128b04ffc1Sbeveloper 	MediaRosterEx(this)->PublishInputs(node, &list);
12133620737cSbeveloper 	return B_OK;
121452a38012Sejakowatz }
121552a38012Sejakowatz 
121652a38012Sejakowatz 
121752a38012Sejakowatz status_t
121852a38012Sejakowatz BMediaRoster::GetAllInputsFor(const media_node & node,
121952a38012Sejakowatz 							  media_input * out_inputs,
122052a38012Sejakowatz 							  int32 buf_num_inputs,
122152a38012Sejakowatz 							  int32 * out_total_count)
122252a38012Sejakowatz {
122352a38012Sejakowatz 	CALLED();
122440f36b03Sbeveloper 	if (IS_INVALID_NODE(node) || (node.kind & B_BUFFER_CONSUMER) == 0)
122552a38012Sejakowatz 		return B_MEDIA_BAD_NODE;
122652a38012Sejakowatz 	if (out_inputs == NULL || out_total_count == NULL)
122752a38012Sejakowatz 		return B_BAD_VALUE;
122852a38012Sejakowatz 
122976669a29Sbeveloper 	List<media_input> list;
12303620737cSbeveloper 	media_input *input;
123152a38012Sejakowatz 	status_t rv;
123252a38012Sejakowatz 
12331299bfb2Sbeveloper 	*out_total_count = 0;
12341299bfb2Sbeveloper 
12358b04ffc1Sbeveloper 	rv = MediaRosterEx(this)->GetAllInputs(node, &list);
12363620737cSbeveloper 	if (B_OK != rv)
12373620737cSbeveloper 		return rv;
12383620737cSbeveloper 
123976669a29Sbeveloper 	int32 i;
124076669a29Sbeveloper 	for (i = 0, list.Rewind(); list.GetNext(&input); i++) {
12413620737cSbeveloper 		out_inputs[i] = *input;
124252a38012Sejakowatz 		*out_total_count += 1;
12433620737cSbeveloper 		buf_num_inputs -= 1;
12443620737cSbeveloper 		if (buf_num_inputs == 0)
12453620737cSbeveloper 			break;
124652a38012Sejakowatz 	}
124752a38012Sejakowatz 
12488b04ffc1Sbeveloper 	MediaRosterEx(this)->PublishInputs(node, &list);
12493620737cSbeveloper 	return B_OK;
125052a38012Sejakowatz }
125152a38012Sejakowatz 
125252a38012Sejakowatz 
125352a38012Sejakowatz status_t
125452a38012Sejakowatz BMediaRoster::GetFreeOutputsFor(const media_node & node,
125552a38012Sejakowatz 								media_output * out_free_outputs,
125652a38012Sejakowatz 								int32 buf_num_outputs,
125752a38012Sejakowatz 								int32 * out_total_count,
125852a38012Sejakowatz 								media_type filter_type)
125952a38012Sejakowatz {
12603620737cSbeveloper 	CALLED();
126140f36b03Sbeveloper 	if (IS_INVALID_NODE(node) || (node.kind & B_BUFFER_PRODUCER) == 0)
12623620737cSbeveloper 		return B_MEDIA_BAD_NODE;
12633620737cSbeveloper 	if (out_free_outputs == NULL || out_total_count == NULL)
12643620737cSbeveloper 		return B_BAD_VALUE;
12653620737cSbeveloper 
126676669a29Sbeveloper 	List<media_output> list;
12673620737cSbeveloper 	media_output *output;
12683620737cSbeveloper 	status_t rv;
12693620737cSbeveloper 
12701299bfb2Sbeveloper 	*out_total_count = 0;
12711299bfb2Sbeveloper 
12728b04ffc1Sbeveloper 	rv = MediaRosterEx(this)->GetAllOutputs(node, &list);
12733620737cSbeveloper 	if (B_OK != rv)
12743620737cSbeveloper 		return rv;
12753620737cSbeveloper 
127676669a29Sbeveloper 	int32 i;
127776669a29Sbeveloper 	for (i = 0, list.Rewind(); list.GetNext(&output); i++) {
12783620737cSbeveloper 		if (filter_type != B_MEDIA_UNKNOWN_TYPE && filter_type != output->format.type)
12793620737cSbeveloper 			continue; // media_type used, but doesn't match
12803620737cSbeveloper 		if (output->destination != media_destination::null)
12813620737cSbeveloper 			continue; // producer destination already connected
12823620737cSbeveloper 		out_free_outputs[i] = *output;
12833620737cSbeveloper 		*out_total_count += 1;
12843620737cSbeveloper 		buf_num_outputs -= 1;
12853620737cSbeveloper 		if (buf_num_outputs == 0)
12863620737cSbeveloper 			break;
12873620737cSbeveloper 	}
12883620737cSbeveloper 
12898b04ffc1Sbeveloper 	MediaRosterEx(this)->PublishOutputs(node, &list);
12903620737cSbeveloper 	return B_OK;
129152a38012Sejakowatz }
129252a38012Sejakowatz 
129352a38012Sejakowatz 
129452a38012Sejakowatz status_t
129552a38012Sejakowatz BMediaRoster::GetConnectedOutputsFor(const media_node & node,
129652a38012Sejakowatz 									 media_output * out_active_outputs,
129752a38012Sejakowatz 									 int32 buf_num_outputs,
129852a38012Sejakowatz 									 int32 * out_total_count)
129952a38012Sejakowatz {
13003620737cSbeveloper 	CALLED();
130140f36b03Sbeveloper 	if (IS_INVALID_NODE(node) || (node.kind & B_BUFFER_PRODUCER) == 0)
13023620737cSbeveloper 		return B_MEDIA_BAD_NODE;
13033620737cSbeveloper 	if (out_active_outputs == NULL || out_total_count == NULL)
13043620737cSbeveloper 		return B_BAD_VALUE;
13053620737cSbeveloper 
130676669a29Sbeveloper 	List<media_output> list;
13073620737cSbeveloper 	media_output *output;
13083620737cSbeveloper 	status_t rv;
13093620737cSbeveloper 
13101299bfb2Sbeveloper 	*out_total_count = 0;
13111299bfb2Sbeveloper 
13128b04ffc1Sbeveloper 	rv = MediaRosterEx(this)->GetAllOutputs(node, &list);
13133620737cSbeveloper 	if (B_OK != rv)
13143620737cSbeveloper 		return rv;
13153620737cSbeveloper 
131676669a29Sbeveloper 	int32 i;
131776669a29Sbeveloper 	for (i = 0, list.Rewind(); list.GetNext(&output); i++) {
13183620737cSbeveloper 		if (output->destination == media_destination::null)
13193620737cSbeveloper 			continue; // producer destination not connected
13203620737cSbeveloper 		out_active_outputs[i] = *output;
13213620737cSbeveloper 		*out_total_count += 1;
13223620737cSbeveloper 		buf_num_outputs -= 1;
13233620737cSbeveloper 		if (buf_num_outputs == 0)
13243620737cSbeveloper 			break;
13253620737cSbeveloper 	}
13263620737cSbeveloper 
13278b04ffc1Sbeveloper 	MediaRosterEx(this)->PublishOutputs(node, &list);
13283620737cSbeveloper 	return B_OK;
132952a38012Sejakowatz }
133052a38012Sejakowatz 
133152a38012Sejakowatz 
133252a38012Sejakowatz status_t
133352a38012Sejakowatz BMediaRoster::GetAllOutputsFor(const media_node & node,
133452a38012Sejakowatz 							   media_output * out_outputs,
133552a38012Sejakowatz 							   int32 buf_num_outputs,
133652a38012Sejakowatz 							   int32 * out_total_count)
133752a38012Sejakowatz {
133852a38012Sejakowatz 	CALLED();
133940f36b03Sbeveloper 	if (IS_INVALID_NODE(node) || (node.kind & B_BUFFER_PRODUCER) == 0)
134052a38012Sejakowatz 		return B_MEDIA_BAD_NODE;
134152a38012Sejakowatz 	if (out_outputs == NULL || out_total_count == NULL)
134252a38012Sejakowatz 		return B_BAD_VALUE;
134352a38012Sejakowatz 
134476669a29Sbeveloper 	List<media_output> list;
13453620737cSbeveloper 	media_output *output;
134652a38012Sejakowatz 	status_t rv;
134752a38012Sejakowatz 
13481299bfb2Sbeveloper 	*out_total_count = 0;
13491299bfb2Sbeveloper 
13508b04ffc1Sbeveloper 	rv = MediaRosterEx(this)->GetAllOutputs(node, &list);
13513620737cSbeveloper 	if (B_OK != rv)
13523620737cSbeveloper 		return rv;
13533620737cSbeveloper 
135476669a29Sbeveloper 	int32 i;
135576669a29Sbeveloper 	for (i = 0, list.Rewind(); list.GetNext(&output); i++) {
13563620737cSbeveloper 		out_outputs[i] = *output;
135752a38012Sejakowatz 		*out_total_count += 1;
13583620737cSbeveloper 		buf_num_outputs -= 1;
13593620737cSbeveloper 		if (buf_num_outputs == 0)
13603620737cSbeveloper 			break;
136152a38012Sejakowatz 	}
136252a38012Sejakowatz 
13638b04ffc1Sbeveloper 	MediaRosterEx(this)->PublishOutputs(node, &list);
13643620737cSbeveloper 	return B_OK;
136552a38012Sejakowatz }
136652a38012Sejakowatz 
136752a38012Sejakowatz 
136852a38012Sejakowatz status_t
136952a38012Sejakowatz BMediaRoster::StartWatching(const BMessenger & where)
137052a38012Sejakowatz {
1371eae26d3dSbeveloper 	CALLED();
1372eae26d3dSbeveloper 	if (!where.IsValid()) {
1373353b9f6bSbeveloper 		FATAL("BMediaRoster::StartWatching: messenger invalid!\n");
1374eae26d3dSbeveloper 		return B_BAD_VALUE;
1375eae26d3dSbeveloper 	}
1376f4925104Sbeveloper 	return BPrivate::media::notifications::Register(where, media_node::null, B_MEDIA_WILDCARD);
137752a38012Sejakowatz }
137852a38012Sejakowatz 
137952a38012Sejakowatz 
138052a38012Sejakowatz status_t
138152a38012Sejakowatz BMediaRoster::StartWatching(const BMessenger & where,
138252a38012Sejakowatz 							int32 notificationType)
138352a38012Sejakowatz {
1384eae26d3dSbeveloper 	CALLED();
1385eae26d3dSbeveloper 	if (!where.IsValid()) {
1386353b9f6bSbeveloper 		FATAL("BMediaRoster::StartWatching: messenger invalid!\n");
1387eae26d3dSbeveloper 		return B_BAD_VALUE;
1388eae26d3dSbeveloper 	}
1389f4925104Sbeveloper 	if (false == BPrivate::media::notifications::IsValidNotificationRequest(false, notificationType)) {
1390353b9f6bSbeveloper 		FATAL("BMediaRoster::StartWatching: notificationType invalid!\n");
1391eae26d3dSbeveloper 		return B_BAD_VALUE;
1392eae26d3dSbeveloper 	}
1393f4925104Sbeveloper 	return BPrivate::media::notifications::Register(where, media_node::null, notificationType);
139452a38012Sejakowatz }
139552a38012Sejakowatz 
139652a38012Sejakowatz 
139752a38012Sejakowatz status_t
139852a38012Sejakowatz BMediaRoster::StartWatching(const BMessenger & where,
139952a38012Sejakowatz 							const media_node & node,
140052a38012Sejakowatz 							int32 notificationType)
140152a38012Sejakowatz {
1402eae26d3dSbeveloper 	CALLED();
1403eae26d3dSbeveloper 	if (!where.IsValid()) {
1404353b9f6bSbeveloper 		FATAL("BMediaRoster::StartWatching: messenger invalid!\n");
1405eae26d3dSbeveloper 		return B_BAD_VALUE;
1406eae26d3dSbeveloper 	}
140740f36b03Sbeveloper 	if (IS_INVALID_NODE(node)) {
1408353b9f6bSbeveloper 		FATAL("BMediaRoster::StartWatching: node invalid!\n");
1409eae26d3dSbeveloper 		return B_MEDIA_BAD_NODE;
1410eae26d3dSbeveloper 	}
1411f4925104Sbeveloper 	if (false == BPrivate::media::notifications::IsValidNotificationRequest(true, notificationType)) {
1412353b9f6bSbeveloper 		FATAL("BMediaRoster::StartWatching: notificationType invalid!\n");
1413eae26d3dSbeveloper 		return B_BAD_VALUE;
1414eae26d3dSbeveloper 	}
1415f4925104Sbeveloper 	return BPrivate::media::notifications::Register(where, node, notificationType);
141652a38012Sejakowatz }
141752a38012Sejakowatz 
141852a38012Sejakowatz 
141952a38012Sejakowatz status_t
142052a38012Sejakowatz BMediaRoster::StopWatching(const BMessenger & where)
142152a38012Sejakowatz {
1422eae26d3dSbeveloper 	CALLED();
1423eae26d3dSbeveloper 	// messenger may already be invalid, so we don't check this
1424f4925104Sbeveloper 	return BPrivate::media::notifications::Unregister(where, media_node::null, B_MEDIA_WILDCARD);
142552a38012Sejakowatz }
142652a38012Sejakowatz 
142752a38012Sejakowatz 
142852a38012Sejakowatz status_t
142952a38012Sejakowatz BMediaRoster::StopWatching(const BMessenger & where,
143052a38012Sejakowatz 						   int32 notificationType)
143152a38012Sejakowatz {
1432eae26d3dSbeveloper 	CALLED();
1433eae26d3dSbeveloper 	// messenger may already be invalid, so we don't check this
1434f4925104Sbeveloper 	if (false == BPrivate::media::notifications::IsValidNotificationRequest(false, notificationType)) {
1435353b9f6bSbeveloper 		FATAL("BMediaRoster::StopWatching: notificationType invalid!\n");
1436eae26d3dSbeveloper 		return B_BAD_VALUE;
1437eae26d3dSbeveloper 	}
1438f4925104Sbeveloper 	return BPrivate::media::notifications::Unregister(where, media_node::null, notificationType);
143952a38012Sejakowatz }
144052a38012Sejakowatz 
144152a38012Sejakowatz 
144252a38012Sejakowatz status_t
144352a38012Sejakowatz BMediaRoster::StopWatching(const BMessenger & where,
144452a38012Sejakowatz 						   const media_node & node,
144552a38012Sejakowatz 						   int32 notificationType)
144652a38012Sejakowatz {
1447eae26d3dSbeveloper 	CALLED();
1448eae26d3dSbeveloper 	// messenger may already be invalid, so we don't check this
144940f36b03Sbeveloper 	if (IS_INVALID_NODE(node)) {
1450353b9f6bSbeveloper 		FATAL("BMediaRoster::StopWatching: node invalid!\n");
1451eae26d3dSbeveloper 		return B_MEDIA_BAD_NODE;
1452eae26d3dSbeveloper 	}
1453f4925104Sbeveloper 	if (false == BPrivate::media::notifications::IsValidNotificationRequest(true, notificationType)) {
1454353b9f6bSbeveloper 		FATAL("BMediaRoster::StopWatching: notificationType invalid!\n");
1455eae26d3dSbeveloper 		return B_BAD_VALUE;
1456eae26d3dSbeveloper 	}
1457f4925104Sbeveloper 	return BPrivate::media::notifications::Unregister(where, node, notificationType);
145852a38012Sejakowatz }
145952a38012Sejakowatz 
146052a38012Sejakowatz 
146152a38012Sejakowatz status_t
146252a38012Sejakowatz BMediaRoster::RegisterNode(BMediaNode * node)
146352a38012Sejakowatz {
146454187cc6Sbeveloper 	CALLED();
146554187cc6Sbeveloper 	// addon-id = -1 (unused), addon-flavor-id = 0 (unused, too)
146654187cc6Sbeveloper 	return MediaRosterEx(this)->RegisterNode(node, -1, 0);
146754187cc6Sbeveloper }
146854187cc6Sbeveloper 
146954187cc6Sbeveloper 
147054187cc6Sbeveloper status_t
147154187cc6Sbeveloper BMediaRosterEx::RegisterNode(BMediaNode * node, media_addon_id addonid, int32 flavorid)
147254187cc6Sbeveloper {
147352a38012Sejakowatz 	CALLED();
147452a38012Sejakowatz 	if (node == NULL)
147552a38012Sejakowatz 		return B_BAD_VALUE;
147652a38012Sejakowatz 
147754187cc6Sbeveloper 	// some sanity check
147854187cc6Sbeveloper 	// I'm not sure if the media kit warrants to call BMediaNode::AddOn() here.
147954187cc6Sbeveloper 	// Perhaps we don't need it.
148054187cc6Sbeveloper 	{
14819e9417d2Sbeveloper 		BMediaAddOn *addon;
14829e9417d2Sbeveloper 		int32 addon_flavor_id;
14839e9417d2Sbeveloper 		media_addon_id addon_id;
14849e9417d2Sbeveloper 		addon_flavor_id = 0;
14859e9417d2Sbeveloper 		addon = node->AddOn(&addon_flavor_id);
14869e9417d2Sbeveloper 		addon_id = addon ? addon->AddonID() : -1;
148754187cc6Sbeveloper 		ASSERT(addonid == addon_id);
148854187cc6Sbeveloper 		ASSERT(flavorid == addon_flavor_id);
148954187cc6Sbeveloper 	}
149052a38012Sejakowatz 
149154187cc6Sbeveloper 	status_t rv;
14929e9417d2Sbeveloper 	server_register_node_request request;
14939e9417d2Sbeveloper 	server_register_node_reply reply;
14949e9417d2Sbeveloper 
149554187cc6Sbeveloper 	request.addon_id = addonid;
149654187cc6Sbeveloper 	request.addon_flavor_id = flavorid;
14979e9417d2Sbeveloper 	strcpy(request.name, node->Name());
14989e9417d2Sbeveloper 	request.kinds = node->Kinds();
14999e9417d2Sbeveloper 	request.port = node->ControlPort();
15009e9417d2Sbeveloper 	request.team = team;
15019e9417d2Sbeveloper 
15028b04ffc1Sbeveloper 	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);
15031299bfb2Sbeveloper 
15049e9417d2Sbeveloper 	rv = QueryServer(SERVER_REGISTER_NODE, &request, sizeof(request), &reply, sizeof(reply));
15059e9417d2Sbeveloper 	if (rv != B_OK) {
1506353b9f6bSbeveloper 		FATAL("BMediaRoster::RegisterNode: failed to register node %s (error %#lx)\n", node->Name(), rv);
15079e9417d2Sbeveloper 		return rv;
15089e9417d2Sbeveloper 	}
15099e9417d2Sbeveloper 
15108b04ffc1Sbeveloper 	// we are a friend class of BMediaNode and initialize this member variable
15119e9417d2Sbeveloper 	node->fNodeID = reply.nodeid;
15129e9417d2Sbeveloper 	ASSERT(reply.nodeid == node->Node().node);
15139e9417d2Sbeveloper 	ASSERT(reply.nodeid == node->ID());
15149e9417d2Sbeveloper 
15159e9417d2Sbeveloper 	// call the callback
15169e9417d2Sbeveloper 	node->NodeRegistered();
15173620737cSbeveloper 
15180e21b167Sbeveloper 	// if the BMediaNode also inherits from BTimeSource, we need to call BTimeSource::FinishCreate()
15190e21b167Sbeveloper 	if (node->Kinds() & B_TIME_SOURCE) {
15200e21b167Sbeveloper 		BTimeSource *ts;
15210e21b167Sbeveloper 		ts = dynamic_cast<BTimeSource *>(node);
15220e21b167Sbeveloper 		if (ts)
15230e21b167Sbeveloper 			ts->FinishCreate();
15240e21b167Sbeveloper 	}
15250e21b167Sbeveloper 
1526570f7d04Sbeveloper /*
15273620737cSbeveloper 	// register existing inputs and outputs with the
15283620737cSbeveloper 	// media_server, this allows GetLiveNodes() to work
15293620737cSbeveloper 	// with created, but unconnected nodes.
15303620737cSbeveloper 	if (node->Kinds() & B_BUFFER_PRODUCER) {
15313620737cSbeveloper 		Stack<media_output> stack;
15323620737cSbeveloper 		if (B_OK == GetAllOutputs(node->Node(), &stack))
15333620737cSbeveloper 			PublishOutputs(node->Node(), &stack);
15343620737cSbeveloper 	} else if (node->Kinds() & B_BUFFER_CONSUMER) {
15353620737cSbeveloper 		Stack<media_input> stack;
15363620737cSbeveloper 		if (B_OK == GetAllInputs(node->Node(), &stack))
15373620737cSbeveloper 			PublishInputs(node->Node(), &stack);
15383620737cSbeveloper 	}
1539570f7d04Sbeveloper */
1540570f7d04Sbeveloper 
15411299bfb2Sbeveloper 	BPrivate::media::notifications::NodesCreated(&reply.nodeid, 1);
1542570f7d04Sbeveloper /*
1543570f7d04Sbeveloper 	TRACE("BMediaRoster::RegisterNode: registered node name '%s', id %ld, addon %ld, flavor %ld\n", node->Name(), node->ID(), addon_id, addon_flavor_id);
1544570f7d04Sbeveloper 	TRACE("BMediaRoster::RegisterNode: node this               %p\n", node);
1545570f7d04Sbeveloper 	TRACE("BMediaRoster::RegisterNode: node fConsumerThis      %p\n", node->fConsumerThis);
1546570f7d04Sbeveloper 	TRACE("BMediaRoster::RegisterNode: node fProducerThis      %p\n", node->fProducerThis);
1547570f7d04Sbeveloper 	TRACE("BMediaRoster::RegisterNode: node fFileInterfaceThis %p\n", node->fFileInterfaceThis);
1548570f7d04Sbeveloper 	TRACE("BMediaRoster::RegisterNode: node fControllableThis  %p\n", node->fControllableThis);
1549570f7d04Sbeveloper 	TRACE("BMediaRoster::RegisterNode: node fTimeSourceThis    %p\n", node->fTimeSourceThis);
1550570f7d04Sbeveloper */
15519e9417d2Sbeveloper 
15529e9417d2Sbeveloper 	return B_OK;
155352a38012Sejakowatz }
155452a38012Sejakowatz 
155552a38012Sejakowatz 
155652a38012Sejakowatz status_t
155752a38012Sejakowatz BMediaRoster::UnregisterNode(BMediaNode * node)
155852a38012Sejakowatz {
15599e9417d2Sbeveloper 	CALLED();
15609e9417d2Sbeveloper 	if (node == NULL)
15619e9417d2Sbeveloper 		return B_BAD_VALUE;
15629e9417d2Sbeveloper 
156360f15390Sbeveloper 	TRACE("BMediaRoster::UnregisterNode %ld (%p)\n", node->ID(), node);
156460f15390Sbeveloper 
156586bce45bSbeveloper 	if (node->fKinds & NODE_KIND_NO_REFCOUNTING) {
156686bce45bSbeveloper 		printf("BMediaRoster::UnregisterNode, trying to unregister reference counting disabled timesource, node %ld, port %ld, team %ld\n", node->ID(), node->ControlPort(), team);
156786bce45bSbeveloper 		return B_OK;
156886bce45bSbeveloper 	}
15698b04ffc1Sbeveloper 	if (node->ID() == NODE_UNREGISTERED_ID) {
15708b04ffc1Sbeveloper 		FATAL("BMediaRoster::UnregisterNode: Warning node id %ld, name '%s' already unregistered\n", node->ID(), node->Name());
15719e9417d2Sbeveloper 		return B_OK;
15729e9417d2Sbeveloper 	}
157354187cc6Sbeveloper 	if (node->fRefCount != 0) {
157454187cc6Sbeveloper 		FATAL("BMediaRoster::UnregisterNode: Warning node id %ld, name '%s' has local reference count of %ld\n", node->ID(), node->Name(), node->fRefCount);
157554187cc6Sbeveloper 		// no return here, we continue and unregister!
157654187cc6Sbeveloper 	}
157754187cc6Sbeveloper 
157854187cc6Sbeveloper 	// Calling BMediaAddOn::GetConfigurationFor(BMediaNode *node, BMessage *config)
157954187cc6Sbeveloper 	// if this node was instanciated by an add-on needs to be done *somewhere*
158054187cc6Sbeveloper 	// We can't do it here because it is already to late (destructor of the node
158154187cc6Sbeveloper 	// might have been called).
15829e9417d2Sbeveloper 
15839e9417d2Sbeveloper 	server_unregister_node_request request;
15849e9417d2Sbeveloper 	server_unregister_node_reply reply;
15859e9417d2Sbeveloper 	status_t rv;
15869e9417d2Sbeveloper 
15879e9417d2Sbeveloper 	request.nodeid = node->ID();
15889e9417d2Sbeveloper 	request.team = team;
15899e9417d2Sbeveloper 
15901299bfb2Sbeveloper 	// send a notification
15911299bfb2Sbeveloper 	BPrivate::media::notifications::NodesDeleted(&request.nodeid, 1);
15921299bfb2Sbeveloper 
15939e9417d2Sbeveloper 	rv = QueryServer(SERVER_UNREGISTER_NODE, &request, sizeof(request), &reply, sizeof(reply));
15949e9417d2Sbeveloper 	if (rv != B_OK) {
15958b04ffc1Sbeveloper 		FATAL("BMediaRoster::UnregisterNode: failed to unregister node id %ld, name '%s' (error %#lx)\n", node->ID(), node->Name(), rv);
15969e9417d2Sbeveloper 		return rv;
15979e9417d2Sbeveloper 	}
15989e9417d2Sbeveloper 
159954187cc6Sbeveloper 	if (reply.addonid != -1) {
160054187cc6Sbeveloper 		// Small problem here, we can't use DormantNodeManager::PutAddon(), as
160154187cc6Sbeveloper 		// UnregisterNode() is called by a dormant node itself (by the destructor).
160254187cc6Sbeveloper 		// The add-on that contains the node needs to remain in memory until the
160354187cc6Sbeveloper 		// destructor execution is finished.
160454187cc6Sbeveloper 		// DormantNodeManager::PutAddonDelayed() will delay unloading.
160554187cc6Sbeveloper 		_DormantNodeManager->PutAddonDelayed(reply.addonid);
1606cf4e2277Sbeveloper 
160773794717Sbeveloper 		rv = MediaRosterEx(this)->DecrementAddonFlavorInstancesCount(reply.addonid, reply.flavorid);
160854187cc6Sbeveloper 		if (rv != B_OK) {
160973794717Sbeveloper 			FATAL("BMediaRoster::UnregisterNode: DecrementAddonFlavorInstancesCount failed\n");
161054187cc6Sbeveloper 			// this is really a problem, but we can't fail now
161154187cc6Sbeveloper 		}
16128b04ffc1Sbeveloper 	}
16139e9417d2Sbeveloper 
16141299bfb2Sbeveloper 	// we are a friend class of BMediaNode and invalidate this member variable
16158b04ffc1Sbeveloper 	node->fNodeID = NODE_UNREGISTERED_ID;
16169e9417d2Sbeveloper 
16179e9417d2Sbeveloper 	return B_OK;
161852a38012Sejakowatz }
161952a38012Sejakowatz 
162052a38012Sejakowatz 
162152a38012Sejakowatz //	thread safe for multiple calls to Roster()
162252a38012Sejakowatz /* static */ BMediaRoster *
162352a38012Sejakowatz BMediaRoster::Roster(status_t* out_error)
162452a38012Sejakowatz {
162552a38012Sejakowatz 	static BLocker locker("BMediaRoster::Roster locker");
162652a38012Sejakowatz 	locker.Lock();
162752a38012Sejakowatz 	if (_sDefault == NULL) {
16288b04ffc1Sbeveloper 		_sDefault = new BMediaRosterEx();
162952a38012Sejakowatz 		if (out_error != NULL)
163052a38012Sejakowatz 			*out_error = B_OK;
163152a38012Sejakowatz 	} else {
163252a38012Sejakowatz 		if (out_error != NULL)
163352a38012Sejakowatz 			*out_error = B_OK;
163452a38012Sejakowatz 	}
163552a38012Sejakowatz 	locker.Unlock();
163652a38012Sejakowatz 	return _sDefault;
163752a38012Sejakowatz }
163852a38012Sejakowatz 
163952a38012Sejakowatz 
164052a38012Sejakowatz //	won't create it if there isn't one
164152a38012Sejakowatz //	not thread safe if you call Roster() at the same time
164252a38012Sejakowatz /* static */ BMediaRoster *
164352a38012Sejakowatz BMediaRoster::CurrentRoster()
164452a38012Sejakowatz {
164552a38012Sejakowatz 	return _sDefault;
164652a38012Sejakowatz }
164752a38012Sejakowatz 
164852a38012Sejakowatz 
164952a38012Sejakowatz status_t
165052a38012Sejakowatz BMediaRoster::SetTimeSourceFor(media_node_id node,
165152a38012Sejakowatz 							   media_node_id time_source)
165252a38012Sejakowatz {
1653aac800c2Sbeveloper 	CALLED();
165440f36b03Sbeveloper 	if (IS_INVALID_NODEID(node) || IS_INVALID_NODEID(time_source))
1655aac800c2Sbeveloper 		return B_BAD_VALUE;
1656aac800c2Sbeveloper 
1657aac800c2Sbeveloper 	media_node clone;
1658aac800c2Sbeveloper 	status_t rv, result;
1659aac800c2Sbeveloper 
166086bce45bSbeveloper 	// we need to get a clone of the node to have a port id
1661aac800c2Sbeveloper 	rv = GetNodeFor(node, &clone);
1662aac800c2Sbeveloper 	if (rv != B_OK) {
1663aac800c2Sbeveloper 		FATAL("BMediaRoster::SetTimeSourceFor, GetNodeFor failed, node id %ld\n", node);
166452a38012Sejakowatz 		return B_ERROR;
166552a38012Sejakowatz 	}
166652a38012Sejakowatz 
166760f15390Sbeveloper 	TRACE("BMediaRoster::SetTimeSourceFor: node %ld will be assigned time source %ld\n", node, time_source);
166886bce45bSbeveloper 
166986bce45bSbeveloper 	// we just send the request to set time_source-id as timesource to the node,
167086bce45bSbeveloper 	// the NODE_SET_TIMESOURCE handler code will do the real assignment
1671aac800c2Sbeveloper 	result = B_OK;
1672aac800c2Sbeveloper 	node_set_timesource_command cmd;
1673aac800c2Sbeveloper 	cmd.timesource_id = time_source;
1674aac800c2Sbeveloper 	rv = SendToPort(clone.port, NODE_SET_TIMESOURCE, &cmd, sizeof(cmd));
1675aac800c2Sbeveloper 	if (rv != B_OK) {
1676aac800c2Sbeveloper 		FATAL("BMediaRoster::SetTimeSourceFor, sending NODE_SET_TIMESOURCE failed, node id %ld\n", node);
1677aac800c2Sbeveloper 		result = B_ERROR;
1678aac800c2Sbeveloper 	}
1679aac800c2Sbeveloper 
168060f15390Sbeveloper 	// we release the clone
1681aac800c2Sbeveloper 	rv = ReleaseNode(clone);
1682aac800c2Sbeveloper 	if (rv != B_OK) {
1683aac800c2Sbeveloper 		FATAL("BMediaRoster::SetTimeSourceFor, ReleaseNode failed, node id %ld\n", node);
1684aac800c2Sbeveloper 		result = B_ERROR;
1685aac800c2Sbeveloper 	}
1686aac800c2Sbeveloper 
1687aac800c2Sbeveloper 	return result;
1688aac800c2Sbeveloper }
1689aac800c2Sbeveloper 
169052a38012Sejakowatz 
169152a38012Sejakowatz status_t
169252a38012Sejakowatz BMediaRoster::GetParameterWebFor(const media_node & node,
169352a38012Sejakowatz 								 BParameterWeb ** out_web)
169452a38012Sejakowatz {
1695*28ad138aSbeveloper 	CALLED();
1696*28ad138aSbeveloper 	if (out_web == NULL)
1697*28ad138aSbeveloper 		return B_BAD_VALUE;
1698*28ad138aSbeveloper 	if (IS_INVALID_NODE(node))
1699*28ad138aSbeveloper 		return B_MEDIA_BAD_NODE;
1700*28ad138aSbeveloper 	if ((node.kind & B_CONTROLLABLE) == 0)
1701*28ad138aSbeveloper 		return B_MEDIA_BAD_NODE;
1702*28ad138aSbeveloper 
1703*28ad138aSbeveloper 	controllable_get_parameter_web_request request;
1704*28ad138aSbeveloper 	controllable_get_parameter_web_reply reply;
1705*28ad138aSbeveloper 	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};
1706*28ad138aSbeveloper 	int32 size;
1707*28ad138aSbeveloper 
1708*28ad138aSbeveloper 	// XXX it might be better to query the node for the (current) parameter size first
1709*28ad138aSbeveloper 	for (int i = 0; (size = requestsize[i]) != 0; i++) {
1710*28ad138aSbeveloper 		status_t rv;
1711*28ad138aSbeveloper 		area_id area;
1712*28ad138aSbeveloper 		void *data;
1713*28ad138aSbeveloper 		area = create_area("parameter web data", &data, B_ANY_ADDRESS, size, B_NO_LOCK, B_READ_AREA | B_WRITE_AREA);
1714*28ad138aSbeveloper 		if (area < B_OK) {
1715*28ad138aSbeveloper 			FATAL("BMediaRoster::GetParameterWebFor couldn't create area of size %ld\n", size);
1716*28ad138aSbeveloper 			return B_ERROR;
1717*28ad138aSbeveloper 		}
1718*28ad138aSbeveloper 		request.maxsize = size;
1719*28ad138aSbeveloper 		request.area = area;
1720*28ad138aSbeveloper 		rv = QueryPort(node.port, CONTROLLABLE_GET_PARAMETER_WEB, &request, sizeof(request), &reply, sizeof(reply));
1721*28ad138aSbeveloper 		if (rv != B_OK) {
1722*28ad138aSbeveloper 			FATAL("BMediaRoster::GetParameterWebFor CONTROLLABLE_GET_PARAMETER_WEB failed\n");
1723*28ad138aSbeveloper 			delete_area(area);
1724*28ad138aSbeveloper 			return B_ERROR;
1725*28ad138aSbeveloper 		}
1726*28ad138aSbeveloper 		if (reply.size == 0) {
1727*28ad138aSbeveloper 			// no parameter web available
1728*28ad138aSbeveloper 			// XXX should we return an error?
1729*28ad138aSbeveloper 			FATAL("BMediaRoster::GetParameterWebFor node %ld has no parameter web\n", node.node);
1730*28ad138aSbeveloper 			*out_web = new BParameterWeb();
1731*28ad138aSbeveloper 			delete_area(area);
173260f15390Sbeveloper 			return B_OK;
173352a38012Sejakowatz 		}
1734*28ad138aSbeveloper 		if (reply.size > 0) {
1735*28ad138aSbeveloper 			// we got a flattened parameter web!
1736*28ad138aSbeveloper 			*out_web = new BParameterWeb();
1737*28ad138aSbeveloper 
1738*28ad138aSbeveloper 			printf("BMediaRoster::GetParameterWebFor Unflattening %ld bytes, 0x%08x, 0x%08x, 0x%08x, 0x%08x\n",
1739*28ad138aSbeveloper 				reply.size, ((uint32*)data)[0], ((uint32*)data)[1], ((uint32*)data)[2], ((uint32*)data)[3]);
1740*28ad138aSbeveloper 
1741*28ad138aSbeveloper 			rv = (*out_web)->Unflatten(reply.code, data, reply.size);
1742*28ad138aSbeveloper 			if (rv != B_OK) {
1743*28ad138aSbeveloper 				FATAL("BMediaRoster::GetParameterWebFor Unflatten failed, %s\n", strerror(rv));
1744*28ad138aSbeveloper 				delete_area(area);
1745*28ad138aSbeveloper 				delete *out_web;
1746*28ad138aSbeveloper 				return B_ERROR;
1747*28ad138aSbeveloper 			}
1748*28ad138aSbeveloper 			delete_area(area);
1749*28ad138aSbeveloper 			return B_OK;
1750*28ad138aSbeveloper 		}
1751*28ad138aSbeveloper 		delete_area(area);
1752*28ad138aSbeveloper 		ASSERT(reply.size == -1);
1753*28ad138aSbeveloper 		// parameter web data was too large
1754*28ad138aSbeveloper 		// loop and try a larger size
1755*28ad138aSbeveloper 	}
1756*28ad138aSbeveloper 	FATAL("BMediaRoster::GetParameterWebFor node %ld has no parameter web larger than %ld\n", node.node, size);
1757*28ad138aSbeveloper 	return B_ERROR;
1758*28ad138aSbeveloper }
175952a38012Sejakowatz 
176052a38012Sejakowatz 
176152a38012Sejakowatz status_t
176252a38012Sejakowatz BMediaRoster::StartControlPanel(const media_node & node,
176352a38012Sejakowatz 								BMessenger * out_messenger)
176452a38012Sejakowatz {
176552a38012Sejakowatz 	UNIMPLEMENTED();
176652a38012Sejakowatz 	return B_ERROR;
176752a38012Sejakowatz }
176852a38012Sejakowatz 
176952a38012Sejakowatz 
177052a38012Sejakowatz status_t
177152a38012Sejakowatz BMediaRoster::GetDormantNodes(dormant_node_info * out_info,
177252a38012Sejakowatz 							  int32 * io_count,
177352a38012Sejakowatz 							  const media_format * has_input /* = NULL */,
177452a38012Sejakowatz 							  const media_format * has_output /* = NULL */,
177552a38012Sejakowatz 							  const char * name /* = NULL */,
177652a38012Sejakowatz 							  uint64 require_kinds /* = NULL */,
177752a38012Sejakowatz 							  uint64 deny_kinds /* = NULL */)
177852a38012Sejakowatz {
177952a38012Sejakowatz 	CALLED();
178052a38012Sejakowatz 	if (out_info == NULL)
178152a38012Sejakowatz 		return B_BAD_VALUE;
178252a38012Sejakowatz 	if (io_count == NULL)
178352a38012Sejakowatz 		return B_BAD_VALUE;
178452a38012Sejakowatz 	if (*io_count <= 0)
178552a38012Sejakowatz 		return B_BAD_VALUE;
178652a38012Sejakowatz 
178752a38012Sejakowatz 	xfer_server_get_dormant_nodes msg;
178852a38012Sejakowatz 	port_id port;
178952a38012Sejakowatz 	status_t rv;
179052a38012Sejakowatz 
179152a38012Sejakowatz 	port = find_port("media_server port");
179252a38012Sejakowatz 	if (port <= B_OK)
179352a38012Sejakowatz 		return B_ERROR;
179452a38012Sejakowatz 
179552a38012Sejakowatz 	msg.maxcount = *io_count;
179652a38012Sejakowatz 	msg.has_input = (bool) has_input;
179752a38012Sejakowatz 	if (has_input)
179852a38012Sejakowatz 		msg.inputformat = *has_input; // XXX we should not make a flat copy of media_format
179952a38012Sejakowatz 	msg.has_output = (bool) has_output;
180052a38012Sejakowatz 	if (has_output)
180152a38012Sejakowatz 		msg.outputformat = *has_output;; // XXX we should not make a flat copy of media_format
180252a38012Sejakowatz 	msg.has_name = (bool) name;
180352a38012Sejakowatz 	if (name) {
18049e9417d2Sbeveloper 		int len = strlen(name);
18059e9417d2Sbeveloper 		len = min_c(len, (int)sizeof(msg.name) - 1);
180652a38012Sejakowatz 		memcpy(msg.name, name, len);
180752a38012Sejakowatz 		msg.name[len] = 0;
180852a38012Sejakowatz 	}
180952a38012Sejakowatz 	msg.require_kinds = require_kinds;
181052a38012Sejakowatz 	msg.deny_kinds = deny_kinds;
181152a38012Sejakowatz 	msg.reply_port = _PortPool->GetPort();
181252a38012Sejakowatz 
181352a38012Sejakowatz 	rv = write_port(port, SERVER_GET_DORMANT_NODES, &msg, sizeof(msg));
181452a38012Sejakowatz 	if (rv != B_OK) {
181552a38012Sejakowatz 		_PortPool->PutPort(msg.reply_port);
181652a38012Sejakowatz 		return rv;
181752a38012Sejakowatz 	}
181852a38012Sejakowatz 
181952a38012Sejakowatz 	xfer_server_get_dormant_nodes_reply reply;
182052a38012Sejakowatz 	int32 code;
182152a38012Sejakowatz 
182252a38012Sejakowatz 	rv = read_port(msg.reply_port, &code, &reply, sizeof(reply));
182352a38012Sejakowatz 	if (rv < B_OK) {
182452a38012Sejakowatz 		_PortPool->PutPort(msg.reply_port);
182552a38012Sejakowatz 		return rv;
182652a38012Sejakowatz 	}
182752a38012Sejakowatz 
182852a38012Sejakowatz 	*io_count = reply.count;
182952a38012Sejakowatz 
183052a38012Sejakowatz 	if (*io_count > 0) {
183152a38012Sejakowatz 		rv = read_port(msg.reply_port, &code, out_info, *io_count * sizeof(dormant_node_info));
183252a38012Sejakowatz 		if (rv < B_OK)
183352a38012Sejakowatz 			reply.result = rv;
183452a38012Sejakowatz 	}
183552a38012Sejakowatz 	_PortPool->PutPort(msg.reply_port);
183652a38012Sejakowatz 
183752a38012Sejakowatz 	return reply.result;
183852a38012Sejakowatz }
183952a38012Sejakowatz 
18408b04ffc1Sbeveloper /* This function is used to do the real work of instantiating a dormant node. It is either
18418b04ffc1Sbeveloper  * called by the media_addon_server to instantiate a global node, or it gets called from
18428b04ffc1Sbeveloper  * BMediaRoster::InstantiateDormantNode() to create a local one.
18438b04ffc1Sbeveloper  *
18448b04ffc1Sbeveloper  * Checks concerning global/local are not done here.
18458b04ffc1Sbeveloper  */
184652a38012Sejakowatz status_t
184754187cc6Sbeveloper BMediaRosterEx::InstantiateDormantNode(media_addon_id addonid, int32 flavorid, team_id creator, media_node *out_node)
184852a38012Sejakowatz {
184954187cc6Sbeveloper 	// This function is always called from the correct context, if the node
185054187cc6Sbeveloper 	// is supposed to be global, it is called from the media_addon_server.
185154187cc6Sbeveloper 
185252a38012Sejakowatz 	// if B_FLAVOR_IS_GLOBAL, we need to use the BMediaAddOn object that
185352a38012Sejakowatz 	// resides in the media_addon_server
185452a38012Sejakowatz 
18558b04ffc1Sbeveloper 	// RegisterNode() must be called for nodes instantiated from add-ons,
18568b04ffc1Sbeveloper 	// since the media kit warrants that it's done automatically.
185752a38012Sejakowatz 
185854187cc6Sbeveloper 	// addonid		Indicates the ID number of the media add-on in which the node resides.
185954187cc6Sbeveloper 	// flavorid		Indicates the internal ID number that the add-on uses to identify the flavor,
186054187cc6Sbeveloper 	//				this is the number that was published by BMediaAddOn::GetFlavorAt() in the
18618b04ffc1Sbeveloper 	//				flavor_info::internal_id field.
186254187cc6Sbeveloper 	// creator		The creator team is -1 if nodes are created locally. If created globally,
186354187cc6Sbeveloper 	//				it will contain (while called in media_addon_server context) the team-id of
186454187cc6Sbeveloper 	// 				the team that requested the instantiation.
18658b04ffc1Sbeveloper 
186660f15390Sbeveloper 	TRACE("BMediaRosterEx::InstantiateDormantNode: addon-id %ld, flavor_id %ld\n", addonid, flavorid);
18678b04ffc1Sbeveloper 
18688b04ffc1Sbeveloper 	// Get flavor_info from the server
18698b04ffc1Sbeveloper 	dormant_flavor_info node_info;
18708c6a6096Sbeveloper 	status_t rv;
18718b04ffc1Sbeveloper 	rv = GetDormantFlavorInfo(addonid, flavorid, &node_info);
18728b04ffc1Sbeveloper 	if (rv != B_OK) {
1873626824eaSbeveloper 		FATAL("BMediaRosterEx::InstantiateDormantNode error: failed to get dormant_flavor_info for addon-id %ld, flavor-id %ld\n", addonid, flavorid);
187452a38012Sejakowatz 		return B_ERROR;
187552a38012Sejakowatz 	}
18768b04ffc1Sbeveloper 
18778b04ffc1Sbeveloper 	ASSERT(node_info.internal_id == flavorid);
18788b04ffc1Sbeveloper 
18798b04ffc1Sbeveloper 	// load the BMediaAddOn object
18808b04ffc1Sbeveloper 	BMediaAddOn *addon;
18818b04ffc1Sbeveloper 	addon = _DormantNodeManager->GetAddon(addonid);
18828b04ffc1Sbeveloper 	if (!addon) {
18838b04ffc1Sbeveloper 		FATAL("BMediaRosterEx::InstantiateDormantNode: GetAddon failed\n");
18848b04ffc1Sbeveloper 		return B_ERROR;
18858b04ffc1Sbeveloper 	}
18868b04ffc1Sbeveloper 
188754187cc6Sbeveloper 	// Now we need to try to increment the use count of this addon flavor
188854187cc6Sbeveloper 	// in the server. This can fail if the total number instances of this
188954187cc6Sbeveloper 	// flavor is limited.
189073794717Sbeveloper 	rv = IncrementAddonFlavorInstancesCount(addonid, flavorid);
189154187cc6Sbeveloper 	if (rv != B_OK) {
1892626824eaSbeveloper 		FATAL("BMediaRosterEx::InstantiateDormantNode error: can't create more nodes for addon-id %ld, flavor-id %ld\n", addonid, flavorid);
189354187cc6Sbeveloper 		// Put the addon back into the pool
189454187cc6Sbeveloper 		_DormantNodeManager->PutAddon(addonid);
189554187cc6Sbeveloper 		return B_ERROR;
189654187cc6Sbeveloper 	}
189754187cc6Sbeveloper 
18988b04ffc1Sbeveloper 	BMessage config;
189954187cc6Sbeveloper 	rv = LoadNodeConfiguration(addonid, flavorid, &config);
190054187cc6Sbeveloper 	if (rv != B_OK) {
190154187cc6Sbeveloper 		FATAL("BMediaRosterEx::InstantiateDormantNode: couldn't load configuration for addon-id %ld, flavor-id %ld\n", addonid, flavorid);
190254187cc6Sbeveloper 		// do not return, this is a minor problem, not a reason to fail
190354187cc6Sbeveloper 	}
19048b04ffc1Sbeveloper 
19058b04ffc1Sbeveloper 	BMediaNode *node;
19068b04ffc1Sbeveloper 	status_t out_error;
19078b04ffc1Sbeveloper 
190854187cc6Sbeveloper 	out_error = B_OK;
19098b04ffc1Sbeveloper 	node = addon->InstantiateNodeFor(&node_info, &config, &out_error);
191016b7eea4Sbeveloper 	if (!node) {
19118b04ffc1Sbeveloper 		FATAL("BMediaRosterEx::InstantiateDormantNode: InstantiateNodeFor failed\n");
191254187cc6Sbeveloper 		// Put the addon back into the pool
19138b04ffc1Sbeveloper 		_DormantNodeManager->PutAddon(addonid);
191454187cc6Sbeveloper 		// We must decrement the use count of this addon flavor in the
191554187cc6Sbeveloper 		// server to compensate the increment done in the beginning.
191673794717Sbeveloper 		rv = DecrementAddonFlavorInstancesCount(addonid, flavorid);
191754187cc6Sbeveloper 		if (rv != B_OK) {
191873794717Sbeveloper 			FATAL("BMediaRosterEx::InstantiateDormantNode: DecrementAddonFlavorInstancesCount failed\n");
191916b7eea4Sbeveloper 		}
192054187cc6Sbeveloper 		return (out_error != B_OK) ? out_error : B_ERROR;
192154187cc6Sbeveloper 	}
192254187cc6Sbeveloper 
192354187cc6Sbeveloper 	rv = RegisterNode(node, addonid, flavorid);
19248c6a6096Sbeveloper 	if (rv != B_OK) {
19258b04ffc1Sbeveloper 		FATAL("BMediaRosterEx::InstantiateDormantNode: RegisterNode failed\n");
19268c6a6096Sbeveloper 		delete node;
192754187cc6Sbeveloper 		// Put the addon back into the pool
19288b04ffc1Sbeveloper 		_DormantNodeManager->PutAddon(addonid);
192954187cc6Sbeveloper 		// We must decrement the use count of this addon flavor in the
193054187cc6Sbeveloper 		// server to compensate the increment done in the beginning.
193173794717Sbeveloper 		rv = DecrementAddonFlavorInstancesCount(addonid, flavorid);
193254187cc6Sbeveloper 		if (rv != B_OK) {
193373794717Sbeveloper 			FATAL("BMediaRosterEx::InstantiateDormantNode: DecrementAddonFlavorInstancesCount failed\n");
193454187cc6Sbeveloper 		}
19358c6a6096Sbeveloper 		return B_ERROR;
19368c6a6096Sbeveloper 	}
19378c6a6096Sbeveloper 
193854187cc6Sbeveloper 	if (creator != -1) {
193954187cc6Sbeveloper 		// send a message to the server to assign team "creator" as creator of node "node->ID()"
194054187cc6Sbeveloper 		printf("!!! BMediaRosterEx::InstantiateDormantNode assigning team %ld as creator of node %ld\n", creator, node->ID());
194154187cc6Sbeveloper 		rv = MediaRosterEx(this)->SetNodeCreator(node->ID(), creator);
194254187cc6Sbeveloper 		if (rv != B_OK) {
194354187cc6Sbeveloper 			FATAL("BMediaRosterEx::InstantiateDormantNode failed to assign team %ld as creator of node %ld\n", creator, node->ID());
194454187cc6Sbeveloper 			// do not return, this is a minor problem, not a reason to fail
194554187cc6Sbeveloper 		}
194654187cc6Sbeveloper 	}
194754187cc6Sbeveloper 
194854187cc6Sbeveloper 	// RegisterNode() does remember the add-on id in the server
194954187cc6Sbeveloper 	// and UnregisterNode() will call DormantNodeManager::PutAddon()
195054187cc6Sbeveloper 	// when the node is unregistered.
19518c6a6096Sbeveloper 
195216b7eea4Sbeveloper 	*out_node = node->Node();
1953cf4e2277Sbeveloper 
195460f15390Sbeveloper 	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);
1955cf4e2277Sbeveloper 
195616b7eea4Sbeveloper 	return B_OK;
195716b7eea4Sbeveloper }
195852a38012Sejakowatz 
195952a38012Sejakowatz 
196052a38012Sejakowatz status_t
19618b04ffc1Sbeveloper BMediaRoster::InstantiateDormantNode(const dormant_node_info & in_info,
19628b04ffc1Sbeveloper 									 media_node * out_node,
19638b04ffc1Sbeveloper 									 uint32 flags /* currently 0 or B_FLAVOR_IS_GLOBAL or B_FLAVOR_IS_LOCAL */ )
19648b04ffc1Sbeveloper {
19658b04ffc1Sbeveloper 	CALLED();
19668b04ffc1Sbeveloper 	if (out_node == 0)
19678b04ffc1Sbeveloper 		return B_BAD_VALUE;
19688b04ffc1Sbeveloper 	if (in_info.addon <= 0) {
19698b04ffc1Sbeveloper 		FATAL("BMediaRoster::InstantiateDormantNode error: addon-id %ld invalid.\n", in_info.addon);
19708b04ffc1Sbeveloper 		return B_BAD_VALUE;
19718b04ffc1Sbeveloper 	}
19728b04ffc1Sbeveloper 
19738b04ffc1Sbeveloper 	printf("BMediaRoster::InstantiateDormantNode: addon-id %ld, flavor_id %ld, flags 0x%X\n", in_info.addon, in_info.flavor_id, flags);
19748b04ffc1Sbeveloper 
19758b04ffc1Sbeveloper 	// Get flavor_info from the server
19768b04ffc1Sbeveloper 	// XXX this is a little overhead, as we get the full blown dormant_flavor_info,
19778b04ffc1Sbeveloper 	// XXX but only need the flags.
19788b04ffc1Sbeveloper 	dormant_flavor_info node_info;
19798b04ffc1Sbeveloper 	status_t rv;
19808b04ffc1Sbeveloper 	rv = MediaRosterEx(this)->GetDormantFlavorInfo(in_info.addon, in_info.flavor_id, &node_info);
19818b04ffc1Sbeveloper 	if (rv != B_OK) {
1982626824eaSbeveloper 		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);
1983626824eaSbeveloper 		return B_NAME_NOT_FOUND;
19848b04ffc1Sbeveloper 	}
19858b04ffc1Sbeveloper 
19868b04ffc1Sbeveloper 	ASSERT(node_info.internal_id == in_info.flavor_id);
19878b04ffc1Sbeveloper 
19888b04ffc1Sbeveloper 	printf("BMediaRoster::InstantiateDormantNode: name \"%s\", info \"%s\", flavor_flags 0x%X, internal_id %ld, possible_count %ld\n",
19898b04ffc1Sbeveloper 		node_info.name, node_info.info, node_info.flavor_flags, node_info.internal_id, node_info.possible_count);
19908b04ffc1Sbeveloper 
19918b04ffc1Sbeveloper 	#if DEBUG
19928b04ffc1Sbeveloper 		if (flags & B_FLAVOR_IS_LOCAL)
19938b04ffc1Sbeveloper 			printf("BMediaRoster::InstantiateDormantNode: caller requested B_FLAVOR_IS_LOCAL\n");
19948b04ffc1Sbeveloper 		if (flags & B_FLAVOR_IS_GLOBAL)
19958b04ffc1Sbeveloper 			printf("BMediaRoster::InstantiateDormantNode: caller requested B_FLAVOR_IS_GLOBAL\n");
19968b04ffc1Sbeveloper 		if (node_info.flavor_flags & B_FLAVOR_IS_LOCAL)
19978b04ffc1Sbeveloper 			printf("BMediaRoster::InstantiateDormantNode: node requires B_FLAVOR_IS_LOCAL\n");
19988b04ffc1Sbeveloper 		if (node_info.flavor_flags & B_FLAVOR_IS_GLOBAL)
19998b04ffc1Sbeveloper 			printf("BMediaRoster::InstantiateDormantNode: node requires B_FLAVOR_IS_GLOBAL\n");
20008b04ffc1Sbeveloper 	#endif
20018b04ffc1Sbeveloper 
20028b04ffc1Sbeveloper 	// Make sure that flags demanded by the dormant node and those requested
20038b04ffc1Sbeveloper 	// by the caller are not incompatible.
20048b04ffc1Sbeveloper 	if ((node_info.flavor_flags & B_FLAVOR_IS_GLOBAL) && (flags & B_FLAVOR_IS_LOCAL)) {
20058b04ffc1Sbeveloper 		FATAL("BMediaRoster::InstantiateDormantNode Error: requested B_FLAVOR_IS_LOCAL, but dormant node has B_FLAVOR_IS_GLOBAL\n");
2006626824eaSbeveloper 		return B_NAME_NOT_FOUND;
20078b04ffc1Sbeveloper 	}
20088b04ffc1Sbeveloper 	if ((node_info.flavor_flags & B_FLAVOR_IS_LOCAL) && (flags & B_FLAVOR_IS_GLOBAL)) {
20098b04ffc1Sbeveloper 		FATAL("BMediaRoster::InstantiateDormantNode Error: requested B_FLAVOR_IS_GLOBAL, but dormant node has B_FLAVOR_IS_LOCAL\n");
2010626824eaSbeveloper 		return B_NAME_NOT_FOUND;
20118b04ffc1Sbeveloper 	}
201254187cc6Sbeveloper 
20138b04ffc1Sbeveloper 	// If either the node, or the caller requested to make the instance global
20148b04ffc1Sbeveloper 	// we will do it by forwarding this request into the media_addon_server, which
20158b04ffc1Sbeveloper 	// in turn will call BMediaRosterEx::InstantiateDormantNode to create the node
20168b04ffc1Sbeveloper 	// there and make it globally available.
20178b04ffc1Sbeveloper 	if ((node_info.flavor_flags & B_FLAVOR_IS_GLOBAL) || (flags & B_FLAVOR_IS_GLOBAL)) {
20188b04ffc1Sbeveloper 
2019cf4e2277Sbeveloper 		printf("BMediaRoster::InstantiateDormantNode: creating global object in media_addon_server\n");
2020cf4e2277Sbeveloper 
20218b04ffc1Sbeveloper 		addonserver_instantiate_dormant_node_request request;
20228b04ffc1Sbeveloper 		addonserver_instantiate_dormant_node_reply reply;
20238b04ffc1Sbeveloper 		request.addonid = in_info.addon;
20248b04ffc1Sbeveloper 		request.flavorid = in_info.flavor_id;
202554187cc6Sbeveloper 		request.creator_team = team; // creator team is allowed to also release global nodes
20268b04ffc1Sbeveloper 		rv = QueryAddonServer(ADDONSERVER_INSTANTIATE_DORMANT_NODE, &request, sizeof(request), &reply, sizeof(reply));
20278b04ffc1Sbeveloper 		if (rv == B_OK) {
20288b04ffc1Sbeveloper 			*out_node = reply.node;
20298b04ffc1Sbeveloper 		}
20308b04ffc1Sbeveloper 
20318b04ffc1Sbeveloper 	} else {
20328b04ffc1Sbeveloper 
203354187cc6Sbeveloper 		// creator team = -1, as this is a local node
2034626824eaSbeveloper 		rv = MediaRosterEx(this)->InstantiateDormantNode(in_info.addon, in_info.flavor_id, -1, out_node);
2035626824eaSbeveloper 
20368b04ffc1Sbeveloper 	}
2037626824eaSbeveloper 	if (rv != B_OK) {
2038626824eaSbeveloper 		*out_node = media_node::null;
2039626824eaSbeveloper 		return B_NAME_NOT_FOUND;
2040626824eaSbeveloper 	}
2041626824eaSbeveloper 	return B_OK;
20428b04ffc1Sbeveloper }
20438b04ffc1Sbeveloper 
20448b04ffc1Sbeveloper 
20458b04ffc1Sbeveloper status_t
20468b04ffc1Sbeveloper BMediaRoster::InstantiateDormantNode(const dormant_node_info & in_info,
20478b04ffc1Sbeveloper 									 media_node * out_node)
20488b04ffc1Sbeveloper {
20498b04ffc1Sbeveloper 	return InstantiateDormantNode(in_info, out_node, 0);
20508b04ffc1Sbeveloper }
20518b04ffc1Sbeveloper 
20528b04ffc1Sbeveloper 
20538b04ffc1Sbeveloper status_t
205452a38012Sejakowatz BMediaRoster::GetDormantNodeFor(const media_node & node,
205552a38012Sejakowatz 								dormant_node_info * out_info)
205652a38012Sejakowatz {
205785dfab2bSbeveloper 	CALLED();
205885dfab2bSbeveloper 	if (out_info == NULL)
205985dfab2bSbeveloper 		return B_BAD_VALUE;
206040f36b03Sbeveloper 	if (IS_INVALID_NODE(node))
206185dfab2bSbeveloper 		return B_MEDIA_BAD_NODE;
206252a38012Sejakowatz 
206385dfab2bSbeveloper 	server_get_dormant_node_for_request request;
206485dfab2bSbeveloper 	server_get_dormant_node_for_reply reply;
206585dfab2bSbeveloper 	status_t rv;
206685dfab2bSbeveloper 
206785dfab2bSbeveloper 	request.node = node;
206885dfab2bSbeveloper 
20691299bfb2Sbeveloper 	rv = QueryServer(SERVER_GET_DORMANT_NODE_FOR, &request, sizeof(request), &reply, sizeof(reply));
207085dfab2bSbeveloper 	if (rv != B_OK)
207185dfab2bSbeveloper 		return rv;
207285dfab2bSbeveloper 
207385dfab2bSbeveloper 	*out_info = reply.node_info;
207485dfab2bSbeveloper 	return B_OK;
207552a38012Sejakowatz }
207652a38012Sejakowatz 
207752a38012Sejakowatz status_t
20788b04ffc1Sbeveloper BMediaRosterEx::GetDormantFlavorInfo(media_addon_id addonid,
20798b04ffc1Sbeveloper 									  int32 flavorid,
208052a38012Sejakowatz 									  dormant_flavor_info * out_flavor)
208152a38012Sejakowatz {
208252a38012Sejakowatz 	CALLED();
208352a38012Sejakowatz 
208452a38012Sejakowatz 	xfer_server_get_dormant_flavor_info msg;
208552a38012Sejakowatz 	xfer_server_get_dormant_flavor_info_reply *reply;
208652a38012Sejakowatz 	port_id port;
208752a38012Sejakowatz 	status_t rv;
208852a38012Sejakowatz 	int32 code;
208952a38012Sejakowatz 
209052a38012Sejakowatz 	port = find_port("media_server port");
209152a38012Sejakowatz 	if (port <= B_OK)
209252a38012Sejakowatz 		return B_ERROR;
209352a38012Sejakowatz 
209452a38012Sejakowatz 	reply = (xfer_server_get_dormant_flavor_info_reply *) malloc(16000);
209552a38012Sejakowatz 	if (reply == 0)
209652a38012Sejakowatz 		return B_ERROR;
209752a38012Sejakowatz 
20988b04ffc1Sbeveloper 	msg.addon 		= addonid;
20998b04ffc1Sbeveloper 	msg.flavor_id 	= flavorid;
210052a38012Sejakowatz 	msg.reply_port 	= _PortPool->GetPort();
210152a38012Sejakowatz 	rv = write_port(port, SERVER_GET_DORMANT_FLAVOR_INFO, &msg, sizeof(msg));
210252a38012Sejakowatz 	if (rv != B_OK) {
210352a38012Sejakowatz 		free(reply);
210452a38012Sejakowatz 		_PortPool->PutPort(msg.reply_port);
210552a38012Sejakowatz 		return rv;
210652a38012Sejakowatz 	}
210752a38012Sejakowatz 	rv = read_port(msg.reply_port, &code, reply, 16000);
210852a38012Sejakowatz 	_PortPool->PutPort(msg.reply_port);
210952a38012Sejakowatz 
211052a38012Sejakowatz 	if (rv < B_OK) {
211152a38012Sejakowatz 		free(reply);
211252a38012Sejakowatz 		return rv;
211352a38012Sejakowatz 	}
211452a38012Sejakowatz 
211552a38012Sejakowatz 	if (reply->result == B_OK)
211652a38012Sejakowatz 		rv = out_flavor->Unflatten(reply->dfi_type, &reply->dfi, reply->dfi_size);
211752a38012Sejakowatz 	else
211852a38012Sejakowatz 		rv = reply->result;
211952a38012Sejakowatz 
212052a38012Sejakowatz 	free(reply);
212152a38012Sejakowatz 	return rv;
212252a38012Sejakowatz }
212352a38012Sejakowatz 
21248b04ffc1Sbeveloper status_t
21258b04ffc1Sbeveloper BMediaRoster::GetDormantFlavorInfoFor(const dormant_node_info & in_dormant,
21268b04ffc1Sbeveloper 									  dormant_flavor_info * out_flavor)
21278b04ffc1Sbeveloper {
21288b04ffc1Sbeveloper 	return MediaRosterEx(this)->GetDormantFlavorInfo(in_dormant.addon, in_dormant.flavor_id, out_flavor);
21298b04ffc1Sbeveloper }
213052a38012Sejakowatz 
213160f15390Sbeveloper // Reports in outLatency the maximum latency found downstream from
213260f15390Sbeveloper // the specified BBufferProducer, producer, given the current connections.
213352a38012Sejakowatz status_t
213452a38012Sejakowatz BMediaRoster::GetLatencyFor(const media_node & producer,
213552a38012Sejakowatz 							bigtime_t * out_latency)
213652a38012Sejakowatz {
213760f15390Sbeveloper 	CALLED();
213860f15390Sbeveloper 	if (out_latency == NULL)
213960f15390Sbeveloper 		return B_BAD_VALUE;
214060f15390Sbeveloper 	if (IS_INVALID_NODE(producer))
214160f15390Sbeveloper 		return B_MEDIA_BAD_NODE;
214260f15390Sbeveloper 	if ((producer.kind & B_BUFFER_PRODUCER) == 0)
214360f15390Sbeveloper 		return B_MEDIA_BAD_NODE;
214460f15390Sbeveloper 
214560f15390Sbeveloper 	producer_get_latency_request request;
214660f15390Sbeveloper 	producer_get_latency_reply reply;
214760f15390Sbeveloper 	status_t rv;
214860f15390Sbeveloper 
214960f15390Sbeveloper 	rv = QueryPort(producer.port, PRODUCER_GET_LATENCY, &request, sizeof(request), &reply, sizeof(reply));
215060f15390Sbeveloper 	if (rv != B_OK)
215160f15390Sbeveloper 		return rv;
215260f15390Sbeveloper 
215360f15390Sbeveloper 	*out_latency = reply.latency;
215460f15390Sbeveloper 
215560f15390Sbeveloper 	printf("BMediaRoster::GetLatencyFor producer %ld has maximum latency %Ld\n", producer.node, *out_latency);
2156aac800c2Sbeveloper 	return B_OK;
215752a38012Sejakowatz }
215852a38012Sejakowatz 
215952a38012Sejakowatz 
216052a38012Sejakowatz status_t
216152a38012Sejakowatz BMediaRoster::GetInitialLatencyFor(const media_node & producer,
216252a38012Sejakowatz 								   bigtime_t * out_latency,
2163aac800c2Sbeveloper 								   uint32 * out_flags /* = NULL */)
216452a38012Sejakowatz {
216552a38012Sejakowatz 	UNIMPLEMENTED();
216660f15390Sbeveloper 	*out_latency = 5000;
2167aac800c2Sbeveloper 	if (out_flags)
216852a38012Sejakowatz 		*out_flags = 0;
2169aac800c2Sbeveloper 	return B_OK;
217052a38012Sejakowatz }
217152a38012Sejakowatz 
217252a38012Sejakowatz 
217352a38012Sejakowatz status_t
217452a38012Sejakowatz BMediaRoster::GetStartLatencyFor(const media_node & time_source,
217552a38012Sejakowatz 								 bigtime_t * out_latency)
217652a38012Sejakowatz {
217752a38012Sejakowatz 	UNIMPLEMENTED();
2178aac800c2Sbeveloper 	*out_latency = 5000;
2179aac800c2Sbeveloper 	return B_OK;
218052a38012Sejakowatz }
218152a38012Sejakowatz 
218252a38012Sejakowatz 
218352a38012Sejakowatz status_t
218452a38012Sejakowatz BMediaRoster::GetFileFormatsFor(const media_node & file_interface,
218552a38012Sejakowatz 								media_file_format * out_formats,
218652a38012Sejakowatz 								int32 * io_num_infos)
218752a38012Sejakowatz {
218852a38012Sejakowatz 	UNIMPLEMENTED();
218952a38012Sejakowatz 	return B_ERROR;
219052a38012Sejakowatz }
219152a38012Sejakowatz 
219252a38012Sejakowatz 
219352a38012Sejakowatz status_t
219452a38012Sejakowatz BMediaRoster::SetRefFor(const media_node & file_interface,
219552a38012Sejakowatz 						const entry_ref & file,
219652a38012Sejakowatz 						bool create_and_truncate,
219752a38012Sejakowatz 						bigtime_t * out_length)	/* if create is false */
219852a38012Sejakowatz {
219952a38012Sejakowatz 	UNIMPLEMENTED();
220052a38012Sejakowatz 	return B_ERROR;
220152a38012Sejakowatz }
220252a38012Sejakowatz 
220352a38012Sejakowatz 
220452a38012Sejakowatz status_t
220552a38012Sejakowatz BMediaRoster::GetRefFor(const media_node & node,
220652a38012Sejakowatz 						entry_ref * out_file,
220752a38012Sejakowatz 						BMimeType * mime_type)
220852a38012Sejakowatz {
220952a38012Sejakowatz 	UNIMPLEMENTED();
221052a38012Sejakowatz 	return B_ERROR;
221152a38012Sejakowatz }
221252a38012Sejakowatz 
221352a38012Sejakowatz 
221452a38012Sejakowatz status_t
221552a38012Sejakowatz BMediaRoster::SniffRefFor(const media_node & file_interface,
221652a38012Sejakowatz 						  const entry_ref & file,
221752a38012Sejakowatz 						  BMimeType * mime_type,
221852a38012Sejakowatz 						  float * out_capability)
221952a38012Sejakowatz {
222052a38012Sejakowatz 	UNIMPLEMENTED();
222152a38012Sejakowatz 	return B_ERROR;
222252a38012Sejakowatz }
222352a38012Sejakowatz 
222452a38012Sejakowatz 
222552a38012Sejakowatz /* This is the generic "here's a file, now can someone please play it" interface */
222652a38012Sejakowatz status_t
222752a38012Sejakowatz BMediaRoster::SniffRef(const entry_ref & file,
222852a38012Sejakowatz 					   uint64 require_node_kinds,		/* if you need an EntityInterface or BufferConsumer or something */
222952a38012Sejakowatz 					   dormant_node_info * out_node,
223052a38012Sejakowatz 					   BMimeType * mime_type)
223152a38012Sejakowatz {
223252a38012Sejakowatz 	UNIMPLEMENTED();
223352a38012Sejakowatz 	return B_ERROR;
223452a38012Sejakowatz }
223552a38012Sejakowatz 
223652a38012Sejakowatz 
223752a38012Sejakowatz status_t
223852a38012Sejakowatz BMediaRoster::GetDormantNodeForType(const BMimeType & type,
223952a38012Sejakowatz 									uint64 require_node_kinds,
224052a38012Sejakowatz 									dormant_node_info * out_node)
224152a38012Sejakowatz {
224252a38012Sejakowatz 	UNIMPLEMENTED();
224352a38012Sejakowatz 	return B_ERROR;
224452a38012Sejakowatz }
224552a38012Sejakowatz 
224652a38012Sejakowatz 
224752a38012Sejakowatz status_t
224852a38012Sejakowatz BMediaRoster::GetReadFileFormatsFor(const dormant_node_info & in_node,
224952a38012Sejakowatz 									media_file_format * out_read_formats,
225052a38012Sejakowatz 									int32 in_read_count,
225152a38012Sejakowatz 									int32 * out_read_count)
225252a38012Sejakowatz {
225352a38012Sejakowatz 	UNIMPLEMENTED();
225452a38012Sejakowatz 	return B_ERROR;
225552a38012Sejakowatz }
225652a38012Sejakowatz 
225752a38012Sejakowatz 
225852a38012Sejakowatz status_t
225952a38012Sejakowatz BMediaRoster::GetWriteFileFormatsFor(const dormant_node_info & in_node,
226052a38012Sejakowatz 									 media_file_format * out_write_formats,
226152a38012Sejakowatz 									 int32 in_write_count,
226252a38012Sejakowatz 									 int32 * out_write_count)
226352a38012Sejakowatz {
226452a38012Sejakowatz 	UNIMPLEMENTED();
226552a38012Sejakowatz 	return B_ERROR;
226652a38012Sejakowatz }
226752a38012Sejakowatz 
226852a38012Sejakowatz 
226952a38012Sejakowatz status_t
227052a38012Sejakowatz BMediaRoster::GetFormatFor(const media_output & output,
227152a38012Sejakowatz 						   media_format * io_format,
227252a38012Sejakowatz 						   uint32 flags)
227352a38012Sejakowatz {
227452a38012Sejakowatz 	UNIMPLEMENTED();
227552a38012Sejakowatz 	return B_ERROR;
227652a38012Sejakowatz }
227752a38012Sejakowatz 
227852a38012Sejakowatz 
227952a38012Sejakowatz status_t
228052a38012Sejakowatz BMediaRoster::GetFormatFor(const media_input & input,
228152a38012Sejakowatz 						   media_format * io_format,
228252a38012Sejakowatz 						   uint32 flags)
228352a38012Sejakowatz {
228452a38012Sejakowatz 	UNIMPLEMENTED();
228552a38012Sejakowatz 	return B_ERROR;
228652a38012Sejakowatz }
228752a38012Sejakowatz 
228852a38012Sejakowatz 
228952a38012Sejakowatz status_t
229052a38012Sejakowatz BMediaRoster::GetFormatFor(const media_node & node,
229152a38012Sejakowatz 						   media_format * io_format,
229252a38012Sejakowatz 						   float quality)
229352a38012Sejakowatz {
229452a38012Sejakowatz 	UNIMPLEMENTED();
229552a38012Sejakowatz 	return B_ERROR;
229652a38012Sejakowatz }
229752a38012Sejakowatz 
229852a38012Sejakowatz 
229952a38012Sejakowatz ssize_t
230052a38012Sejakowatz BMediaRoster::GetNodeAttributesFor(const media_node & node,
230152a38012Sejakowatz 								   media_node_attribute * outArray,
230252a38012Sejakowatz 								   size_t inMaxCount)
230352a38012Sejakowatz {
230452a38012Sejakowatz 	UNIMPLEMENTED();
230552a38012Sejakowatz 	return B_ERROR;
230652a38012Sejakowatz }
230752a38012Sejakowatz 
230852a38012Sejakowatz 
230952a38012Sejakowatz media_node_id
231052a38012Sejakowatz BMediaRoster::NodeIDFor(port_id source_or_destination_port)
231152a38012Sejakowatz {
23129e9417d2Sbeveloper 	CALLED();
23139e9417d2Sbeveloper 
23149e9417d2Sbeveloper 	server_node_id_for_request request;
23159e9417d2Sbeveloper 	server_node_id_for_reply reply;
23169e9417d2Sbeveloper 	status_t rv;
23179e9417d2Sbeveloper 
23189e9417d2Sbeveloper 	request.port = source_or_destination_port;
23199e9417d2Sbeveloper 
23209e9417d2Sbeveloper 	rv = QueryServer(SERVER_NODE_ID_FOR, &request, sizeof(request), &reply, sizeof(reply));
23219e9417d2Sbeveloper 	if (rv != B_OK) {
2322353b9f6bSbeveloper 		FATAL("BMediaRoster::NodeIDFor: failed (error %#lx)\n", rv);
23239e9417d2Sbeveloper 		return -1;
23249e9417d2Sbeveloper 	}
23259e9417d2Sbeveloper 
23269e9417d2Sbeveloper 	return reply.nodeid;
232752a38012Sejakowatz }
232852a38012Sejakowatz 
232952a38012Sejakowatz 
233052a38012Sejakowatz status_t
233152a38012Sejakowatz BMediaRoster::GetInstancesFor(media_addon_id addon,
233252a38012Sejakowatz 							  int32 flavor,
233352a38012Sejakowatz 							  media_node_id * out_id,
233452a38012Sejakowatz 							  int32 * io_count)
233552a38012Sejakowatz {
233685dfab2bSbeveloper 	CALLED();
233785dfab2bSbeveloper 	if (out_id == NULL || io_count == NULL)
233885dfab2bSbeveloper 		return B_BAD_VALUE;
233985dfab2bSbeveloper 	if (*io_count <= 0)
234085dfab2bSbeveloper 		return B_BAD_VALUE;
234185dfab2bSbeveloper 
234285dfab2bSbeveloper 	server_get_instances_for_request request;
234385dfab2bSbeveloper 	server_get_instances_for_reply reply;
234485dfab2bSbeveloper 	status_t rv;
234585dfab2bSbeveloper 
234685dfab2bSbeveloper 	request.maxcount = *io_count;
234785dfab2bSbeveloper 	request.addon_id = addon;
234885dfab2bSbeveloper 	request.addon_flavor_id = flavor;
234985dfab2bSbeveloper 
235085dfab2bSbeveloper 	rv = QueryServer(SERVER_GET_INSTANCES_FOR, &request, sizeof(request), &reply, sizeof(reply));
235185dfab2bSbeveloper 	if (rv != B_OK) {
2352353b9f6bSbeveloper 		FATAL("BMediaRoster::GetLiveNodes failed\n");
235385dfab2bSbeveloper 		return rv;
235452a38012Sejakowatz 	}
235552a38012Sejakowatz 
235685dfab2bSbeveloper 	*io_count = reply.count;
235785dfab2bSbeveloper 	if (reply.count > 0)
235885dfab2bSbeveloper 		memcpy(out_id, reply.node_id, sizeof(media_node_id) * reply.count);
235985dfab2bSbeveloper 
236085dfab2bSbeveloper 	return B_OK;
236185dfab2bSbeveloper }
236252a38012Sejakowatz 
236352a38012Sejakowatz 
236452a38012Sejakowatz status_t
236552a38012Sejakowatz BMediaRoster::SetRealtimeFlags(uint32 in_enabled)
236652a38012Sejakowatz {
236752a38012Sejakowatz 	UNIMPLEMENTED();
236852a38012Sejakowatz 	return B_ERROR;
236952a38012Sejakowatz }
237052a38012Sejakowatz 
237152a38012Sejakowatz 
237252a38012Sejakowatz status_t
237352a38012Sejakowatz BMediaRoster::GetRealtimeFlags(uint32 * out_enabled)
237452a38012Sejakowatz {
237552a38012Sejakowatz 	UNIMPLEMENTED();
237652a38012Sejakowatz 	return B_ERROR;
237752a38012Sejakowatz }
237852a38012Sejakowatz 
237952a38012Sejakowatz 
238052a38012Sejakowatz ssize_t
238152a38012Sejakowatz BMediaRoster::AudioBufferSizeFor(int32 channel_count,
238252a38012Sejakowatz 								 uint32 sample_format,
238352a38012Sejakowatz 								 float frame_rate,
238452a38012Sejakowatz 								 bus_type bus_kind)
238552a38012Sejakowatz {
238652a38012Sejakowatz 	UNIMPLEMENTED();
238752a38012Sejakowatz 	return 4096;
238852a38012Sejakowatz }
238952a38012Sejakowatz 
239052a38012Sejakowatz 
239152a38012Sejakowatz /* Use MediaFlags to inquire about specific features of the Media Kit. */
239252a38012Sejakowatz /* Returns < 0 for "not present", positive size for output data size. */
239352a38012Sejakowatz /* 0 means that the capability is present, but no data about it. */
239452a38012Sejakowatz /* static */ ssize_t
239552a38012Sejakowatz BMediaRoster::MediaFlags(media_flags cap,
239652a38012Sejakowatz 						 void * buf,
239752a38012Sejakowatz 						 size_t maxSize)
239852a38012Sejakowatz {
239952a38012Sejakowatz 	UNIMPLEMENTED();
240052a38012Sejakowatz 	return 0;
240152a38012Sejakowatz }
240252a38012Sejakowatz 
240352a38012Sejakowatz 
240452a38012Sejakowatz /* BLooper overrides */
240552a38012Sejakowatz /* virtual */ void
240652a38012Sejakowatz BMediaRoster::MessageReceived(BMessage * message)
240752a38012Sejakowatz {
2408cf4e2277Sbeveloper 	switch (message->what) {
2409cf4e2277Sbeveloper 		case 'PING':
2410cf4e2277Sbeveloper 		{
24116396865dSbeveloper 			// media_server plays ping-pong with the BMediaRosters
24126396865dSbeveloper 			// to detect dead teams. Normal communication uses ports.
24136396865dSbeveloper 			static BMessage pong('PONG');
24146396865dSbeveloper 			message->SendReply(&pong, static_cast<BHandler *>(NULL), 2000000);
24156396865dSbeveloper 			return;
24166396865dSbeveloper 		}
24176396865dSbeveloper 
2418cf4e2277Sbeveloper 		case NODE_FINAL_RELEASE:
2419cf4e2277Sbeveloper 		{
2420cf4e2277Sbeveloper 			// this function is called by a BMediaNode to delete
2421cf4e2277Sbeveloper 			// itself, as this needs to be done from another thread
2422cf4e2277Sbeveloper 			// context, it is done here.
2423cf4e2277Sbeveloper 			// XXX If a node is released using BMediaRoster::ReleaseNode()
2424cf4e2277Sbeveloper 			// XXX instead of using BMediaNode::Release() / BMediaNode::Acquire()
2425cf4e2277Sbeveloper 			// XXX fRefCount of the BMediaNode will not be correct.
2426cf4e2277Sbeveloper 
2427cf4e2277Sbeveloper 			BMediaNode *node;
2428cf4e2277Sbeveloper 			message->FindPointer("node", reinterpret_cast<void **>(&node));
2429cf4e2277Sbeveloper 
243054187cc6Sbeveloper 			TRACE("BMediaRoster::MessageReceived NODE_FINAL_RELEASE saving node %ld configuration\n", node->ID());
243154187cc6Sbeveloper 			MediaRosterEx(BMediaRoster::Roster())->SaveNodeConfiguration(node);
2432cf4e2277Sbeveloper 
243354187cc6Sbeveloper 			TRACE("BMediaRoster::MessageReceived NODE_FINAL_RELEASE releasing node %ld\n", node->ID());
2434cf4e2277Sbeveloper 			node->DeleteHook(node); // we don't call Release(), see above!
2435cf4e2277Sbeveloper 			return;
2436cf4e2277Sbeveloper 		}
2437cf4e2277Sbeveloper 	}
24386396865dSbeveloper 	printf("BMediaRoster::MessageReceived: unknown message!\n");
24396396865dSbeveloper 	message->PrintToStream();
244052a38012Sejakowatz }
244152a38012Sejakowatz 
244252a38012Sejakowatz /* virtual */ bool
244352a38012Sejakowatz BMediaRoster::QuitRequested()
244452a38012Sejakowatz {
244552a38012Sejakowatz 	UNIMPLEMENTED();
244652a38012Sejakowatz 	return true;
244752a38012Sejakowatz }
244852a38012Sejakowatz 
244952a38012Sejakowatz /* virtual */ BHandler *
245052a38012Sejakowatz BMediaRoster::ResolveSpecifier(BMessage *msg,
245152a38012Sejakowatz 				 int32 index,
245252a38012Sejakowatz 				 BMessage *specifier,
245352a38012Sejakowatz 				 int32 form,
245452a38012Sejakowatz 				 const char *property)
245552a38012Sejakowatz {
245652a38012Sejakowatz 	UNIMPLEMENTED();
245752a38012Sejakowatz 	return 0;
245852a38012Sejakowatz }
245952a38012Sejakowatz 
246052a38012Sejakowatz 
246152a38012Sejakowatz /* virtual */ status_t
246252a38012Sejakowatz BMediaRoster::GetSupportedSuites(BMessage *data)
246352a38012Sejakowatz {
246452a38012Sejakowatz 	UNIMPLEMENTED();
246552a38012Sejakowatz 	return B_ERROR;
246652a38012Sejakowatz }
246752a38012Sejakowatz 
246852a38012Sejakowatz 
246952a38012Sejakowatz BMediaRoster::~BMediaRoster()
247052a38012Sejakowatz {
247152a38012Sejakowatz 	CALLED();
24726396865dSbeveloper 
24736396865dSbeveloper 	// unregister this application with the media server
24746396865dSbeveloper 	server_unregister_app_request request;
24756396865dSbeveloper 	server_unregister_app_reply reply;
24766396865dSbeveloper 	request.team = team;
24776396865dSbeveloper 	QueryServer(SERVER_UNREGISTER_APP, &request, sizeof(request), &reply, sizeof(reply));
247852a38012Sejakowatz }
247952a38012Sejakowatz 
248052a38012Sejakowatz 
248152a38012Sejakowatz /*************************************************************
248252a38012Sejakowatz  * private BMediaRoster
248352a38012Sejakowatz  *************************************************************/
248452a38012Sejakowatz 
248552a38012Sejakowatz // deprecated call
248652a38012Sejakowatz status_t
248752a38012Sejakowatz BMediaRoster::SetOutputBuffersFor(const media_source & output,
248852a38012Sejakowatz 								  BBufferGroup * group,
248952a38012Sejakowatz 								  bool will_reclaim )
249052a38012Sejakowatz {
249152a38012Sejakowatz 	UNIMPLEMENTED();
24929e9417d2Sbeveloper 	debugger("BMediaRoster::SetOutputBuffersFor missing\n");
249352a38012Sejakowatz 	return B_ERROR;
249452a38012Sejakowatz }
249552a38012Sejakowatz 
249652a38012Sejakowatz 
249752a38012Sejakowatz /* FBC stuffing (Mmmh, Stuffing!) */
249852a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_0(void *) { return B_ERROR; }
249952a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_1(void *) { return B_ERROR; }
250052a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_2(void *) { return B_ERROR; }
250152a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_3(void *) { return B_ERROR; }
250252a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_4(void *) { return B_ERROR; }
250352a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_5(void *) { return B_ERROR; }
250452a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_6(void *) { return B_ERROR; }
250552a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_7(void *) { return B_ERROR; }
250652a38012Sejakowatz 
250752a38012Sejakowatz 
250852a38012Sejakowatz BMediaRoster::BMediaRoster() :
25096396865dSbeveloper 	BLooper("_BMediaRoster_", B_URGENT_DISPLAY_PRIORITY, B_LOOPER_PORT_DEFAULT_CAPACITY)
251052a38012Sejakowatz {
251152a38012Sejakowatz 	CALLED();
25126396865dSbeveloper 
25136396865dSbeveloper 	// start the looper
25146396865dSbeveloper 	Run();
25156396865dSbeveloper 
25166396865dSbeveloper 	// register this application with the media server
25176396865dSbeveloper 	server_register_app_request request;
25186396865dSbeveloper 	server_register_app_reply reply;
25196396865dSbeveloper 	request.team = team;
25206396865dSbeveloper 	request.messenger = BMessenger(NULL, this);
25216396865dSbeveloper 	QueryServer(SERVER_REGISTER_APP, &request, sizeof(request), &reply, sizeof(reply));
252252a38012Sejakowatz }
252352a38012Sejakowatz 
25246396865dSbeveloper 
252552a38012Sejakowatz /* static */ status_t
252652a38012Sejakowatz BMediaRoster::ParseCommand(BMessage & reply)
252752a38012Sejakowatz {
252852a38012Sejakowatz 	UNIMPLEMENTED();
252952a38012Sejakowatz 	return B_ERROR;
253052a38012Sejakowatz }
253152a38012Sejakowatz 
253252a38012Sejakowatz 
253352a38012Sejakowatz status_t
253452a38012Sejakowatz BMediaRoster::GetDefaultInfo(media_node_id for_default,
253552a38012Sejakowatz 							 BMessage & out_config)
253652a38012Sejakowatz {
253752a38012Sejakowatz 	UNIMPLEMENTED();
253852a38012Sejakowatz 	return B_ERROR;
253952a38012Sejakowatz }
254052a38012Sejakowatz 
254152a38012Sejakowatz 
254252a38012Sejakowatz 
254352a38012Sejakowatz status_t
254452a38012Sejakowatz BMediaRoster::SetRunningDefault(media_node_id for_default,
254552a38012Sejakowatz 								const media_node & node)
254652a38012Sejakowatz {
254752a38012Sejakowatz 	UNIMPLEMENTED();
254852a38012Sejakowatz 	return B_ERROR;
254952a38012Sejakowatz }
255052a38012Sejakowatz 
255152a38012Sejakowatz 
255252a38012Sejakowatz /*************************************************************
255352a38012Sejakowatz  * static BMediaRoster variables
255452a38012Sejakowatz  *************************************************************/
255552a38012Sejakowatz 
255652a38012Sejakowatz bool BMediaRoster::_isMediaServer;
255752a38012Sejakowatz port_id BMediaRoster::_mReplyPort;
255852a38012Sejakowatz int32 BMediaRoster::_mReplyPortRes;
255952a38012Sejakowatz int32 BMediaRoster::_mReplyPortUnavailCount;
256052a38012Sejakowatz BMediaRoster * BMediaRoster::_sDefault = NULL;
256152a38012Sejakowatz 
2562