xref: /haiku/src/kits/media/MediaRoster.cpp (revision 0e21b167c923fa9d57cd68e29886d8431d4ba918)
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>
1452a38012Sejakowatz #include "debug.h"
1576669a29Sbeveloper #include "TList.h"
1652a38012Sejakowatz #include "PortPool.h"
170a483e72SIngo Weinhold #include "ServerInterface.h"
18f4925104Sbeveloper #include "DataExchange.h"
1916b7eea4Sbeveloper #include "DormantNodeManager.h"
20f4925104Sbeveloper #include "Notifications.h"
21835140c8Sbeveloper #include "TimeSourceObjectManager.h"
2252a38012Sejakowatz 
23f4925104Sbeveloper namespace BPrivate { namespace media {
24f4925104Sbeveloper 	extern team_id team;
253620737cSbeveloper } } // BPrivate::media
263620737cSbeveloper 
273620737cSbeveloper using namespace BPrivate::media;
2852a38012Sejakowatz 
2952a38012Sejakowatz // the BMediaRoster destructor is private,
3052a38012Sejakowatz // but _DefaultDeleter is a friend class of
3152a38012Sejakowatz // the BMediaRoster an thus can delete it
3252a38012Sejakowatz class _DefaultDeleter
3352a38012Sejakowatz {
3452a38012Sejakowatz public:
356396865dSbeveloper 	~_DefaultDeleter()
366396865dSbeveloper 	{
376396865dSbeveloper 		if (BMediaRoster::_sDefault) {
386396865dSbeveloper 			BMediaRoster::_sDefault->Lock();
396396865dSbeveloper 			BMediaRoster::_sDefault->Quit();
406396865dSbeveloper 		}
416396865dSbeveloper 	}
426396865dSbeveloper } _deleter;
4352a38012Sejakowatz 
443620737cSbeveloper namespace BPrivate { namespace media { namespace mediaroster {
4552a38012Sejakowatz 
4652a38012Sejakowatz status_t GetNode(node_type type, media_node * out_node, int32 * out_input_id = NULL, BString * out_input_name = NULL);
4752a38012Sejakowatz status_t SetNode(node_type type, const media_node *node, const dormant_node_info *info = NULL, const media_input *input = NULL);
4876669a29Sbeveloper status_t GetAllOutputs(const media_node & node, List<media_output> *list);
4976669a29Sbeveloper status_t GetAllInputs(const media_node & node, List<media_input> *list);
5076669a29Sbeveloper status_t PublishOutputs(const media_node & node, List<media_output> *list);
5176669a29Sbeveloper status_t PublishInputs(const media_node & node, List<media_input> *list);
5252a38012Sejakowatz 
533620737cSbeveloper status_t
543620737cSbeveloper GetNode(node_type type, media_node * out_node, int32 * out_input_id, BString * out_input_name)
5552a38012Sejakowatz {
5652a38012Sejakowatz 	if (out_node == NULL)
5752a38012Sejakowatz 		return B_BAD_VALUE;
5852a38012Sejakowatz 
598c6a6096Sbeveloper 	server_get_node_request request;
608c6a6096Sbeveloper 	server_get_node_reply reply;
6152a38012Sejakowatz 	status_t rv;
6252a38012Sejakowatz 
638c6a6096Sbeveloper 	request.type = type;
649e9417d2Sbeveloper 	request.team = team;
658c6a6096Sbeveloper 	rv = QueryServer(SERVER_GET_NODE, &request, sizeof(request), &reply, sizeof(reply));
668c6a6096Sbeveloper 	if (rv != B_OK)
678c6a6096Sbeveloper 		return rv;
6852a38012Sejakowatz 
6952a38012Sejakowatz 	*out_node = reply.node;
7052a38012Sejakowatz 	if (out_input_id)
7152a38012Sejakowatz 		*out_input_id = reply.input_id;
7252a38012Sejakowatz 	if (out_input_name)
7352a38012Sejakowatz 		*out_input_name = reply.input_name;
748c6a6096Sbeveloper 	return rv;
7552a38012Sejakowatz }
7652a38012Sejakowatz 
773620737cSbeveloper status_t
783620737cSbeveloper SetNode(node_type type, const media_node *node, const dormant_node_info *info, const media_input *input)
7952a38012Sejakowatz {
808c6a6096Sbeveloper 	server_set_node_request request;
818c6a6096Sbeveloper 	server_set_node_reply reply;
8252a38012Sejakowatz 
838c6a6096Sbeveloper 	request.type = type;
848c6a6096Sbeveloper 	request.use_node = node ? true : false;
8552a38012Sejakowatz 	if (node)
868c6a6096Sbeveloper 		request.node = *node;
878c6a6096Sbeveloper 	request.use_dni = info ? true : false;
8852a38012Sejakowatz 	if (info)
898c6a6096Sbeveloper 		request.dni = *info;
908c6a6096Sbeveloper 	request.use_input = input ? true : false;
9152a38012Sejakowatz 	if (input)
928c6a6096Sbeveloper 		request.input = *input;
9352a38012Sejakowatz 
948c6a6096Sbeveloper 	return QueryServer(SERVER_SET_NODE, &request, sizeof(request), &reply, sizeof(reply));
9552a38012Sejakowatz }
9652a38012Sejakowatz 
973620737cSbeveloper status_t
9876669a29Sbeveloper GetAllOutputs(const media_node & node, List<media_output> *list)
993620737cSbeveloper {
1003620737cSbeveloper 	int32 cookie;
1013620737cSbeveloper 	status_t rv;
1023620737cSbeveloper 	status_t result;
1033620737cSbeveloper 
1043620737cSbeveloper 	result = B_OK;
1053620737cSbeveloper 	cookie = 0;
10676669a29Sbeveloper 	list->MakeEmpty();
1073620737cSbeveloper 	for (;;) {
1083620737cSbeveloper 		producer_get_next_output_request request;
1093620737cSbeveloper 		producer_get_next_output_reply reply;
1103620737cSbeveloper 		request.cookie = cookie;
1110caff283Sbeveloper 		rv = QueryPort(node.port, PRODUCER_GET_NEXT_OUTPUT, &request, sizeof(request), &reply, sizeof(reply));
1123620737cSbeveloper 		if (rv != B_OK)
1133620737cSbeveloper 			break;
1143620737cSbeveloper 		cookie = reply.cookie;
11576669a29Sbeveloper 		if (!list->Insert(reply.output)) {
11676669a29Sbeveloper 			FATAL("GetAllOutputs: list->Insert failed\n");
1173620737cSbeveloper 			result = B_ERROR;
1183620737cSbeveloper 		}
1193620737cSbeveloper 	}
1203620737cSbeveloper 
1213620737cSbeveloper 	producer_dispose_output_cookie_request request;
1223620737cSbeveloper 	producer_dispose_output_cookie_reply reply;
1230caff283Sbeveloper 	QueryPort(node.port, PRODUCER_DISPOSE_OUTPUT_COOKIE, &request, sizeof(request), &reply, sizeof(reply));
1243620737cSbeveloper 
1253620737cSbeveloper 	return result;
1263620737cSbeveloper }
1273620737cSbeveloper 
1283620737cSbeveloper status_t
12976669a29Sbeveloper GetAllInputs(const media_node & node, List<media_input> *list)
1303620737cSbeveloper {
1313620737cSbeveloper 	int32 cookie;
1323620737cSbeveloper 	status_t rv;
1333620737cSbeveloper 	status_t result;
1343620737cSbeveloper 
1353620737cSbeveloper 	result = B_OK;
1363620737cSbeveloper 	cookie = 0;
13776669a29Sbeveloper 	list->MakeEmpty();
1383620737cSbeveloper 	for (;;) {
1393620737cSbeveloper 		consumer_get_next_input_request request;
1403620737cSbeveloper 		consumer_get_next_input_reply reply;
1413620737cSbeveloper 		request.cookie = cookie;
1420caff283Sbeveloper 		rv = QueryPort(node.port, CONSUMER_GET_NEXT_INPUT, &request, sizeof(request), &reply, sizeof(reply));
1433620737cSbeveloper 		if (rv != B_OK)
1443620737cSbeveloper 			break;
1453620737cSbeveloper 		cookie = reply.cookie;
14676669a29Sbeveloper 		if (!list->Insert(reply.input)) {
14776669a29Sbeveloper 			FATAL("GetAllInputs: list->Insert failed\n");
1483620737cSbeveloper 			result = B_ERROR;
1493620737cSbeveloper 		}
1503620737cSbeveloper 	}
1513620737cSbeveloper 
1523620737cSbeveloper 	consumer_dispose_input_cookie_request request;
1533620737cSbeveloper 	consumer_dispose_input_cookie_reply reply;
1540caff283Sbeveloper 	QueryPort(node.port, CONSUMER_DISPOSE_INPUT_COOKIE, &request, sizeof(request), &reply, sizeof(reply));
1553620737cSbeveloper 
1563620737cSbeveloper 	return result;
1573620737cSbeveloper }
1583620737cSbeveloper 
1593620737cSbeveloper status_t
16076669a29Sbeveloper PublishOutputs(const media_node & node, List<media_output> *list)
1613620737cSbeveloper {
1623620737cSbeveloper 	server_publish_outputs_request request;
1633620737cSbeveloper 	server_publish_outputs_reply reply;
1643620737cSbeveloper 	media_output *output;
1653620737cSbeveloper 	media_output *outputs;
1663620737cSbeveloper 	int32 count;
167a7b41a96Sbeveloper 	status_t rv;
1683620737cSbeveloper 
16976669a29Sbeveloper 	count = list->CountItems();
1703620737cSbeveloper 	TRACE("PublishOutputs: publishing %ld\n", count);
1713620737cSbeveloper 
1723620737cSbeveloper 	request.node = node;
1733620737cSbeveloper 	request.count = count;
1743620737cSbeveloper 	if (count > MAX_OUTPUTS) {
1753620737cSbeveloper 		void *start_addr;
1763620737cSbeveloper 		size_t size;
1773620737cSbeveloper 		size = ((count * sizeof(media_output)) + B_PAGE_SIZE - 1) & ~(B_PAGE_SIZE - 1);
1783620737cSbeveloper 		request.area = create_area("publish outputs", &start_addr, B_ANY_ADDRESS, size, B_NO_LOCK, B_READ_AREA | B_WRITE_AREA);
1793620737cSbeveloper 		if (request.area < B_OK) {
180353b9f6bSbeveloper 			FATAL("PublishOutputs: failed to create area, %#lx\n", request.area);
1813620737cSbeveloper 			return (status_t)request.area;
1823620737cSbeveloper 		}
1833620737cSbeveloper 		outputs = static_cast<media_output *>(start_addr);
1843620737cSbeveloper 	} else {
1853620737cSbeveloper 		request.area = -1;
1863620737cSbeveloper 		outputs = request.outputs;
1873620737cSbeveloper 	}
18876669a29Sbeveloper 	TRACE("PublishOutputs: area %ld\n", request.area);
1893620737cSbeveloper 
19076669a29Sbeveloper 	int i;
19176669a29Sbeveloper 	for (i = 0, list->Rewind(); list->GetNext(&output); i++) {
19276669a29Sbeveloper 		ASSERT(i < count);
1933620737cSbeveloper 		outputs[i] = *output;
1943620737cSbeveloper 	}
1953620737cSbeveloper 
196a7b41a96Sbeveloper 	rv = QueryServer(SERVER_PUBLISH_OUTPUTS, &request, sizeof(request), &reply, sizeof(reply));
197a7b41a96Sbeveloper 
198a7b41a96Sbeveloper 	if (request.area != -1)
199a7b41a96Sbeveloper 		delete_area(request.area);
200a7b41a96Sbeveloper 
201a7b41a96Sbeveloper 	return rv;
2023620737cSbeveloper }
2033620737cSbeveloper 
2043620737cSbeveloper status_t
20576669a29Sbeveloper PublishInputs(const media_node & node, List<media_input> *list)
2063620737cSbeveloper {
2073620737cSbeveloper 	server_publish_inputs_request request;
2083620737cSbeveloper 	server_publish_inputs_reply reply;
2093620737cSbeveloper 	media_input *input;
2103620737cSbeveloper 	media_input *inputs;
2113620737cSbeveloper 	int32 count;
212a7b41a96Sbeveloper 	status_t rv;
2133620737cSbeveloper 
21476669a29Sbeveloper 	count = list->CountItems();
2153620737cSbeveloper 	TRACE("PublishInputs: publishing %ld\n", count);
2163620737cSbeveloper 
2173620737cSbeveloper 	request.node = node;
2183620737cSbeveloper 	request.count = count;
2193620737cSbeveloper 	if (count > MAX_INPUTS) {
2203620737cSbeveloper 		void *start_addr;
2213620737cSbeveloper 		size_t size;
2223620737cSbeveloper 		size = ((count * sizeof(media_input)) + B_PAGE_SIZE - 1) & ~(B_PAGE_SIZE - 1);
2233620737cSbeveloper 		request.area = create_area("publish inputs", &start_addr, B_ANY_ADDRESS, size, B_NO_LOCK, B_READ_AREA | B_WRITE_AREA);
2243620737cSbeveloper 		if (request.area < B_OK) {
225353b9f6bSbeveloper 			FATAL("PublishInputs: failed to create area, %#lx\n", request.area);
2263620737cSbeveloper 			return (status_t)request.area;
2273620737cSbeveloper 		}
2283620737cSbeveloper 		inputs = static_cast<media_input *>(start_addr);
2293620737cSbeveloper 	} else {
2303620737cSbeveloper 		request.area = -1;
2313620737cSbeveloper 		inputs = request.inputs;
2323620737cSbeveloper 	}
23376669a29Sbeveloper 	TRACE("PublishInputs: area %ld\n", request.area);
2343620737cSbeveloper 
23576669a29Sbeveloper 	int i;
23676669a29Sbeveloper 	for (i = 0, list->Rewind(); list->GetNext(&input); i++) {
23776669a29Sbeveloper 		ASSERT(i < count);
2383620737cSbeveloper 		inputs[i] = *input;
2393620737cSbeveloper 	}
2403620737cSbeveloper 
241a7b41a96Sbeveloper 	rv = QueryServer(SERVER_PUBLISH_INPUTS, &request, sizeof(request), &reply, sizeof(reply));
242a7b41a96Sbeveloper 
243a7b41a96Sbeveloper 	if (request.area != -1)
244a7b41a96Sbeveloper 		delete_area(request.area);
245a7b41a96Sbeveloper 
246a7b41a96Sbeveloper 	return rv;
2473620737cSbeveloper }
2483620737cSbeveloper 
2493620737cSbeveloper } } } // namespace BPrivate::media::mediaroster
2503620737cSbeveloper 
2513620737cSbeveloper using namespace BPrivate::media::mediaroster;
25252a38012Sejakowatz 
25352a38012Sejakowatz /*************************************************************
25452a38012Sejakowatz  * public BMediaRoster
25552a38012Sejakowatz  *************************************************************/
25652a38012Sejakowatz 
25752a38012Sejakowatz status_t
25852a38012Sejakowatz BMediaRoster::GetVideoInput(media_node * out_node)
25952a38012Sejakowatz {
26052a38012Sejakowatz 	CALLED();
2613620737cSbeveloper 	return GetNode(VIDEO_INPUT, out_node);
26252a38012Sejakowatz }
26352a38012Sejakowatz 
26452a38012Sejakowatz 
26552a38012Sejakowatz status_t
26652a38012Sejakowatz BMediaRoster::GetAudioInput(media_node * out_node)
26752a38012Sejakowatz {
26852a38012Sejakowatz 	CALLED();
2693620737cSbeveloper 	return GetNode(AUDIO_INPUT, out_node);
27052a38012Sejakowatz }
27152a38012Sejakowatz 
27252a38012Sejakowatz 
27352a38012Sejakowatz status_t
27452a38012Sejakowatz BMediaRoster::GetVideoOutput(media_node * out_node)
27552a38012Sejakowatz {
27652a38012Sejakowatz 	CALLED();
2773620737cSbeveloper 	return GetNode(VIDEO_OUTPUT, out_node);
27852a38012Sejakowatz }
27952a38012Sejakowatz 
28052a38012Sejakowatz 
28152a38012Sejakowatz status_t
28252a38012Sejakowatz BMediaRoster::GetAudioMixer(media_node * out_node)
28352a38012Sejakowatz {
28452a38012Sejakowatz 	CALLED();
2853620737cSbeveloper 	return GetNode(AUDIO_MIXER, out_node);
28652a38012Sejakowatz }
28752a38012Sejakowatz 
28852a38012Sejakowatz 
28952a38012Sejakowatz status_t
29052a38012Sejakowatz BMediaRoster::GetAudioOutput(media_node * out_node)
29152a38012Sejakowatz {
29252a38012Sejakowatz 	CALLED();
2933620737cSbeveloper 	return GetNode(AUDIO_OUTPUT, out_node);
29452a38012Sejakowatz }
29552a38012Sejakowatz 
29652a38012Sejakowatz 
29752a38012Sejakowatz status_t
29852a38012Sejakowatz BMediaRoster::GetAudioOutput(media_node * out_node,
29952a38012Sejakowatz 							 int32 * out_input_id,
30052a38012Sejakowatz 							 BString * out_input_name)
30152a38012Sejakowatz {
30252a38012Sejakowatz 	CALLED();
3033620737cSbeveloper 	return GetNode(AUDIO_OUTPUT_EX, out_node, out_input_id, out_input_name);
30452a38012Sejakowatz }
30552a38012Sejakowatz 
30652a38012Sejakowatz 
30752a38012Sejakowatz status_t
30852a38012Sejakowatz BMediaRoster::GetTimeSource(media_node * out_node)
30952a38012Sejakowatz {
31052a38012Sejakowatz 	CALLED();
3113620737cSbeveloper 	return GetNode(TIME_SOURCE, out_node);
31252a38012Sejakowatz }
31352a38012Sejakowatz 
31452a38012Sejakowatz 
31552a38012Sejakowatz status_t
31652a38012Sejakowatz BMediaRoster::SetVideoInput(const media_node & producer)
31752a38012Sejakowatz {
31852a38012Sejakowatz 	CALLED();
3193620737cSbeveloper 	return SetNode(VIDEO_INPUT, &producer);
32052a38012Sejakowatz }
32152a38012Sejakowatz 
32252a38012Sejakowatz 
32352a38012Sejakowatz status_t
32452a38012Sejakowatz BMediaRoster::SetVideoInput(const dormant_node_info & producer)
32552a38012Sejakowatz {
32652a38012Sejakowatz 	CALLED();
3273620737cSbeveloper 	return SetNode(VIDEO_INPUT, NULL, &producer);
32852a38012Sejakowatz }
32952a38012Sejakowatz 
33052a38012Sejakowatz 
33152a38012Sejakowatz status_t
33252a38012Sejakowatz BMediaRoster::SetAudioInput(const media_node & producer)
33352a38012Sejakowatz {
33452a38012Sejakowatz 	CALLED();
3353620737cSbeveloper 	return SetNode(AUDIO_INPUT, &producer);
33652a38012Sejakowatz }
33752a38012Sejakowatz 
33852a38012Sejakowatz 
33952a38012Sejakowatz status_t
34052a38012Sejakowatz BMediaRoster::SetAudioInput(const dormant_node_info & producer)
34152a38012Sejakowatz {
34252a38012Sejakowatz 	CALLED();
3433620737cSbeveloper 	return SetNode(AUDIO_INPUT, NULL, &producer);
34452a38012Sejakowatz }
34552a38012Sejakowatz 
34652a38012Sejakowatz 
34752a38012Sejakowatz status_t
34852a38012Sejakowatz BMediaRoster::SetVideoOutput(const media_node & consumer)
34952a38012Sejakowatz {
35052a38012Sejakowatz 	CALLED();
3513620737cSbeveloper 	return SetNode(VIDEO_OUTPUT, &consumer);
35252a38012Sejakowatz }
35352a38012Sejakowatz 
35452a38012Sejakowatz 
35552a38012Sejakowatz status_t
35652a38012Sejakowatz BMediaRoster::SetVideoOutput(const dormant_node_info & consumer)
35752a38012Sejakowatz {
35852a38012Sejakowatz 	CALLED();
3593620737cSbeveloper 	return SetNode(VIDEO_OUTPUT, NULL, &consumer);
36052a38012Sejakowatz }
36152a38012Sejakowatz 
36252a38012Sejakowatz 
36352a38012Sejakowatz status_t
36452a38012Sejakowatz BMediaRoster::SetAudioOutput(const media_node & consumer)
36552a38012Sejakowatz {
36652a38012Sejakowatz 	CALLED();
3673620737cSbeveloper 	return SetNode(AUDIO_OUTPUT, &consumer);
36852a38012Sejakowatz }
36952a38012Sejakowatz 
37052a38012Sejakowatz 
37152a38012Sejakowatz status_t
37252a38012Sejakowatz BMediaRoster::SetAudioOutput(const media_input & input_to_output)
37352a38012Sejakowatz {
37452a38012Sejakowatz 	CALLED();
3753620737cSbeveloper 	return SetNode(AUDIO_OUTPUT, NULL, NULL, &input_to_output);
37652a38012Sejakowatz }
37752a38012Sejakowatz 
37852a38012Sejakowatz 
37952a38012Sejakowatz status_t
38052a38012Sejakowatz BMediaRoster::SetAudioOutput(const dormant_node_info & consumer)
38152a38012Sejakowatz {
38252a38012Sejakowatz 	CALLED();
3833620737cSbeveloper 	return SetNode(AUDIO_OUTPUT, NULL, &consumer);
38452a38012Sejakowatz }
38552a38012Sejakowatz 
38652a38012Sejakowatz 
38752a38012Sejakowatz status_t
38852a38012Sejakowatz BMediaRoster::GetNodeFor(media_node_id node,
38952a38012Sejakowatz 						 media_node * clone)
39052a38012Sejakowatz {
3919e9417d2Sbeveloper 	CALLED();
3929e9417d2Sbeveloper 	if (clone == NULL)
3939e9417d2Sbeveloper 		return B_BAD_VALUE;
3949e9417d2Sbeveloper 	if (node <= 0)
3959e9417d2Sbeveloper 		return B_MEDIA_BAD_NODE;
3969e9417d2Sbeveloper 
3979e9417d2Sbeveloper 	server_get_node_for_request request;
3989e9417d2Sbeveloper 	server_get_node_for_reply reply;
3999e9417d2Sbeveloper 	status_t rv;
4009e9417d2Sbeveloper 
4019e9417d2Sbeveloper 	request.nodeid = node;
4029e9417d2Sbeveloper 	request.team = team;
4039e9417d2Sbeveloper 
4049e9417d2Sbeveloper 	rv = QueryServer(SERVER_GET_NODE_FOR, &request, sizeof(request), &reply, sizeof(reply));
4059e9417d2Sbeveloper 	if (rv != B_OK)
4069e9417d2Sbeveloper 		return rv;
4079e9417d2Sbeveloper 
4089e9417d2Sbeveloper 	*clone = reply.clone;
4099e9417d2Sbeveloper 	return B_OK;
41052a38012Sejakowatz }
41152a38012Sejakowatz 
41252a38012Sejakowatz 
41352a38012Sejakowatz status_t
41452a38012Sejakowatz BMediaRoster::GetSystemTimeSource(media_node * clone)
41552a38012Sejakowatz {
41652a38012Sejakowatz 	CALLED();
4173620737cSbeveloper 	return GetNode(SYSTEM_TIME_SOURCE, clone);
41852a38012Sejakowatz }
41952a38012Sejakowatz 
42052a38012Sejakowatz 
42152a38012Sejakowatz status_t
42252a38012Sejakowatz BMediaRoster::ReleaseNode(const media_node & node)
42352a38012Sejakowatz {
4249e9417d2Sbeveloper 	CALLED();
4259e9417d2Sbeveloper 	if (node.node <= 0)
4269e9417d2Sbeveloper 		return B_MEDIA_BAD_NODE;
42752a38012Sejakowatz 
4289e9417d2Sbeveloper 	server_release_node_request request;
4299e9417d2Sbeveloper 	server_release_node_reply reply;
4309e9417d2Sbeveloper 
4319e9417d2Sbeveloper 	request.node = node;
4329e9417d2Sbeveloper 	request.team = team;
4339e9417d2Sbeveloper 
4349e9417d2Sbeveloper 	return QueryServer(SERVER_RELEASE_NODE, &request, sizeof(request), &reply, sizeof(reply));
4359e9417d2Sbeveloper }
43652a38012Sejakowatz 
43752a38012Sejakowatz BTimeSource *
43852a38012Sejakowatz BMediaRoster::MakeTimeSourceFor(const media_node & for_node)
43952a38012Sejakowatz {
440835140c8Sbeveloper 	CALLED();
441287f7492Sbeveloper 
442*0e21b167Sbeveloper 	BTimeSource *source;
443287f7492Sbeveloper 
444*0e21b167Sbeveloper //	printf("BMediaRoster::MakeTimeSourceFor enter, node %ld, port %ld, kind %#lx\n", for_node.node, for_node.port, for_node.kind);
445287f7492Sbeveloper 
446*0e21b167Sbeveloper 	if (0 == (for_node.kind & B_TIME_SOURCE)) {
447*0e21b167Sbeveloper 		FATAL("BMediaRoster::MakeTimeSourceFor, node %ld is not a timesource!\n", for_node.node);
448*0e21b167Sbeveloper 		// XXX It appears that Cortex calls this function on every node, and expects
449*0e21b167Sbeveloper 		// XXX to be returned a system time source if the for_node is not a timesource
450*0e21b167Sbeveloper 		media_node clone;
451*0e21b167Sbeveloper 		GetSystemTimeSource(&clone);
452*0e21b167Sbeveloper 		source = _TimeSourceObjectManager->GetTimeSource(clone);
453*0e21b167Sbeveloper 		ReleaseNode(clone);
454*0e21b167Sbeveloper 	} else {
455*0e21b167Sbeveloper 		source = _TimeSourceObjectManager->GetTimeSource(for_node);
456*0e21b167Sbeveloper 	}
457*0e21b167Sbeveloper 
458*0e21b167Sbeveloper //	printf("BMediaRoster::MakeTimeSourceFor leave, node %ld, port %ld, kind %#lx\n", source->Node().node, source->Node().port, source->Node().kind);
459287f7492Sbeveloper 
460835140c8Sbeveloper 	return source;
46152a38012Sejakowatz }
46252a38012Sejakowatz 
46352a38012Sejakowatz 
46452a38012Sejakowatz status_t
46552a38012Sejakowatz BMediaRoster::Connect(const media_source & from,
46652a38012Sejakowatz 					  const media_destination & to,
46752a38012Sejakowatz 					  media_format * io_format,
46852a38012Sejakowatz 					  media_output * out_output,
46952a38012Sejakowatz 					  media_input * out_input)
47052a38012Sejakowatz {
471eae26d3dSbeveloper 	return BMediaRoster::Connect(from, to, io_format, out_output, out_input, 0);
472eae26d3dSbeveloper }
473eae26d3dSbeveloper 
474eae26d3dSbeveloper 
475eae26d3dSbeveloper status_t
476eae26d3dSbeveloper BMediaRoster::Connect(const media_source & from,
477eae26d3dSbeveloper 					  const media_destination & to,
478eae26d3dSbeveloper 					  media_format * io_format,
479eae26d3dSbeveloper 					  media_output * out_output,
480eae26d3dSbeveloper 					  media_input * out_input,
481eae26d3dSbeveloper 					  uint32 in_flags,
482eae26d3dSbeveloper 					  void * _reserved)
483eae26d3dSbeveloper {
48452a38012Sejakowatz 	CALLED();
48552a38012Sejakowatz 	if (io_format == NULL || out_output == NULL || out_input == NULL)
48652a38012Sejakowatz 		return B_BAD_VALUE;
4879e9417d2Sbeveloper 	if (from == media_source::null) {
488353b9f6bSbeveloper 		FATAL("BMediaRoster::Connect: media_source invalid\n");
48952a38012Sejakowatz 		return B_MEDIA_BAD_SOURCE;
4909e9417d2Sbeveloper 	}
4919e9417d2Sbeveloper 	if (to == media_destination::null) {
492353b9f6bSbeveloper 		FATAL("BMediaRoster::Connect: media_destination invalid\n");
49352a38012Sejakowatz 		return B_MEDIA_BAD_DESTINATION;
4949e9417d2Sbeveloper 	}
49552a38012Sejakowatz 
49652a38012Sejakowatz 	status_t rv;
4978c6a6096Sbeveloper 	producer_format_proposal_request request1;
4988c6a6096Sbeveloper 	producer_format_proposal_reply reply1;
49952a38012Sejakowatz 
50052a38012Sejakowatz 	// BBufferProducer::FormatProposal
5018c6a6096Sbeveloper 	request1.output = from;
5028c6a6096Sbeveloper 	request1.format = *io_format;
5038c6a6096Sbeveloper 	rv = QueryPort(from.port, PRODUCER_FORMAT_PROPOSAL, &request1, sizeof(request1), &reply1, sizeof(reply1));
5048c6a6096Sbeveloper 	if (rv != B_OK) {
505353b9f6bSbeveloper 		FATAL("BMediaRoster::Connect: aborted after BBufferProducer::FormatProposal, status = %#lx\n",rv);
50652a38012Sejakowatz 		return rv;
50752a38012Sejakowatz 	}
5088c6a6096Sbeveloper 	// reply1.format now contains the format proposed by the producer
5098c6a6096Sbeveloper 
5108c6a6096Sbeveloper 	consumer_accept_format_request request2;
5118c6a6096Sbeveloper 	consumer_accept_format_reply reply2;
5128c6a6096Sbeveloper 
5138c6a6096Sbeveloper 	// BBufferConsumer::AcceptFormat
5148c6a6096Sbeveloper 	request2.dest = to;
5158c6a6096Sbeveloper 	request2.format = reply1.format;
5168c6a6096Sbeveloper 	rv = QueryPort(to.port, CONSUMER_ACCEPT_FORMAT, &request2, sizeof(request2), &reply2, sizeof(reply2));
5178c6a6096Sbeveloper 	if (rv != B_OK) {
518353b9f6bSbeveloper 		FATAL("BMediaRoster::Connect: aborted after BBufferConsumer::AcceptFormat, status = %#lx\n",rv);
5198c6a6096Sbeveloper 		return rv;
5208c6a6096Sbeveloper 	}
5218c6a6096Sbeveloper 	// reply2.format now contains the format accepted by the consumer
5228c6a6096Sbeveloper 
5238c6a6096Sbeveloper 	// BBufferProducer::PrepareToConnect
5248c6a6096Sbeveloper 	producer_prepare_to_connect_request request3;
5258c6a6096Sbeveloper 	producer_prepare_to_connect_reply reply3;
5268c6a6096Sbeveloper 
5278c6a6096Sbeveloper 	request3.source = from;
5288c6a6096Sbeveloper 	request3.destination = to;
5298c6a6096Sbeveloper 	request3.format = reply2.format;
5308c6a6096Sbeveloper 	strcpy(request3.name, "XXX some default name"); // XXX fix this
5318c6a6096Sbeveloper 	rv = QueryPort(from.port, PRODUCER_PREPARE_TO_CONNECT, &request3, sizeof(request3), &reply3, sizeof(reply3));
5328c6a6096Sbeveloper 	if (rv != B_OK) {
533353b9f6bSbeveloper 		FATAL("BMediaRoster::Connect: aborted after BBufferProducer::PrepareToConnect, status = %#lx\n",rv);
5348c6a6096Sbeveloper 		return rv;
5358c6a6096Sbeveloper 	}
5368c6a6096Sbeveloper 	// reply3.format is still our pretty media format
5378c6a6096Sbeveloper 	// reply3.out_source the real source to be used for the connection
5388c6a6096Sbeveloper 	// reply3.name the name BBufferConsumer::Connected will see in the outInput->name argument
5398c6a6096Sbeveloper 
5408c6a6096Sbeveloper 	// BBufferConsumer::Connected
5418c6a6096Sbeveloper 	consumer_connected_request request4;
5428c6a6096Sbeveloper 	consumer_connected_reply reply4;
5438c6a6096Sbeveloper 	status_t con_status;
5448c6a6096Sbeveloper 
5458c6a6096Sbeveloper 	request4.producer = reply3.out_source;
5468c6a6096Sbeveloper 	request4.where = to;
5478c6a6096Sbeveloper 	request4.with_format = reply3.format;
5488c6a6096Sbeveloper 	con_status = QueryPort(to.port, CONSUMER_CONNECTED, &request4, sizeof(request4), &reply4, sizeof(reply4));
5498c6a6096Sbeveloper 	if (con_status != B_OK) {
550353b9f6bSbeveloper 		FATAL("BMediaRoster::Connect: aborting after BBufferConsumer::Connected, status = %#lx\n",con_status);
5518c6a6096Sbeveloper 		// we do NOT return here!
5528c6a6096Sbeveloper 	}
5538c6a6096Sbeveloper 	// con_status contains the status code to be supplied to BBufferProducer::Connect's status argument
5548c6a6096Sbeveloper 	// reply4.input contains the media_input that describes the connection from the consumer point of view
5558c6a6096Sbeveloper 
5568c6a6096Sbeveloper 	// BBufferProducer::Connect
5578c6a6096Sbeveloper 	producer_connect_request request5;
5588c6a6096Sbeveloper 	producer_connect_reply reply5;
5598c6a6096Sbeveloper 
5608c6a6096Sbeveloper 	request5.error = con_status;
5618c6a6096Sbeveloper 	request5.source = reply3.out_source;
5628c6a6096Sbeveloper 	request5.destination = reply4.input.destination;
5638c6a6096Sbeveloper 	request5.format = reply3.format; // XXX reply4.input.format ???
5648c6a6096Sbeveloper 	strcpy(request5.name, reply4.input.name);
5650caff283Sbeveloper 	rv = QueryPort(reply4.input.source.port, PRODUCER_CONNECT, &request5, sizeof(request5), &reply5, sizeof(reply5));
5668c6a6096Sbeveloper 	if (con_status != B_OK) {
567353b9f6bSbeveloper 		FATAL("BMediaRoster::Connect: aborted\n");
5688c6a6096Sbeveloper 		return con_status;
5698c6a6096Sbeveloper 	}
5708c6a6096Sbeveloper 	if (rv != B_OK) {
571353b9f6bSbeveloper 		FATAL("BMediaRoster::Connect: aborted after BBufferProducer::Connect, status = %#lx\n",rv);
5728c6a6096Sbeveloper 		return rv;
5738c6a6096Sbeveloper 	}
5748c6a6096Sbeveloper 	// reply5.name contains the name assigned to the connection by the producer
5758c6a6096Sbeveloper 
5768c6a6096Sbeveloper 	// find the output node
5778c6a6096Sbeveloper 	// XXX isn't there a easier way?
5788c6a6096Sbeveloper 	media_node sourcenode;
5798c6a6096Sbeveloper 	GetNodeFor(NodeIDFor(from.port), &sourcenode);
5808c6a6096Sbeveloper 	ReleaseNode(sourcenode);
5818c6a6096Sbeveloper 
5828c6a6096Sbeveloper 	// initilize connection info
5838c6a6096Sbeveloper 	*io_format = reply3.format;
5848c6a6096Sbeveloper 	*out_input = reply4.input;
5858c6a6096Sbeveloper 	out_output->node = sourcenode;
5868c6a6096Sbeveloper 	out_output->source = reply4.input.source;
5878c6a6096Sbeveloper 	out_output->destination = reply4.input.destination;
5888c6a6096Sbeveloper 	out_output->format = reply4.input.format;
5898c6a6096Sbeveloper 	strcpy(out_output->name, reply5.name);
5908c6a6096Sbeveloper 
5918c6a6096Sbeveloper 	// the connection is now made
5928c6a6096Sbeveloper 
5938c6a6096Sbeveloper 
5948c6a6096Sbeveloper 	// XXX register connection with server
5959e9417d2Sbeveloper 	// XXX we should just send a notification, instead of republishing all endpoints
59676669a29Sbeveloper 	List<media_output> outlist;
59776669a29Sbeveloper 	List<media_input> inlist;
59876669a29Sbeveloper 	if (B_OK == GetAllOutputs(out_output->node , &outlist))
59976669a29Sbeveloper 		PublishOutputs(out_output->node , &outlist);
60076669a29Sbeveloper 	if (B_OK == GetAllInputs(out_input->node , &inlist))
60176669a29Sbeveloper 		PublishInputs(out_input->node, &inlist);
6028c6a6096Sbeveloper 
6038c6a6096Sbeveloper 
6048c6a6096Sbeveloper 	// XXX if (mute) BBufferProducer::EnableOutput(false)
6059e9417d2Sbeveloper 	if (in_flags & B_CONNECT_MUTED) {
6069e9417d2Sbeveloper 	}
6078c6a6096Sbeveloper 
6088c6a6096Sbeveloper 
6099e9417d2Sbeveloper 	// send a notification
6109e9417d2Sbeveloper 	BPrivate::media::notifications::ConnectionMade(*out_input, *out_output, *io_format);
6119e9417d2Sbeveloper 
6128c6a6096Sbeveloper 	return B_OK;
6138c6a6096Sbeveloper };
61452a38012Sejakowatz 
61552a38012Sejakowatz 
61652a38012Sejakowatz status_t
6179e9417d2Sbeveloper BMediaRoster::Disconnect(media_node_id source_nodeid,
61852a38012Sejakowatz 						 const media_source & source,
6199e9417d2Sbeveloper 						 media_node_id destination_nodeid,
62052a38012Sejakowatz 						 const media_destination & destination)
62152a38012Sejakowatz {
6229e9417d2Sbeveloper 	CALLED();
6239e9417d2Sbeveloper 	if (source_nodeid <= 0) {
624353b9f6bSbeveloper 		FATAL("BMediaRoster::Disconnect: source media_node_id invalid\n");
6259e9417d2Sbeveloper 		return B_MEDIA_BAD_SOURCE;
6269e9417d2Sbeveloper 	}
6279e9417d2Sbeveloper 	if (destination_nodeid <= 0) {
628353b9f6bSbeveloper 		FATAL("BMediaRoster::Disconnect: source media_node_id invalid\n");
6299e9417d2Sbeveloper 		return B_MEDIA_BAD_DESTINATION;
6309e9417d2Sbeveloper 	}
6319e9417d2Sbeveloper 	if (source == media_source::null) {
632353b9f6bSbeveloper 		FATAL("BMediaRoster::Disconnect: media_source invalid\n");
6339e9417d2Sbeveloper 		return B_MEDIA_BAD_SOURCE;
6349e9417d2Sbeveloper 	}
6359e9417d2Sbeveloper 	if (destination == media_destination::null) {
636353b9f6bSbeveloper 		FATAL("BMediaRoster::Disconnect: media_destination invalid\n");
6379e9417d2Sbeveloper 		return B_MEDIA_BAD_DESTINATION;
6389e9417d2Sbeveloper 	}
6399e9417d2Sbeveloper 
6409e9417d2Sbeveloper 	producer_disconnect_request request2;
6419e9417d2Sbeveloper 	producer_disconnect_reply reply2;
6429e9417d2Sbeveloper 	consumer_disconnected_request request1;
6439e9417d2Sbeveloper 	consumer_disconnected_reply reply1;
6449e9417d2Sbeveloper 	status_t rv1, rv2;
6459e9417d2Sbeveloper 
6469e9417d2Sbeveloper 	// XXX we should ask the server if this connection really exists
6479e9417d2Sbeveloper 
6489e9417d2Sbeveloper 	request1.source = source;
6499e9417d2Sbeveloper 	request1.destination = destination;
6509e9417d2Sbeveloper 	request2.source = source;
6519e9417d2Sbeveloper 	request2.destination = destination;
6529e9417d2Sbeveloper 
6539e9417d2Sbeveloper 	rv1 = QueryPort(source.port, PRODUCER_DISCONNECT, &request1, sizeof(request1), &reply1, sizeof(reply1));
6549e9417d2Sbeveloper 	rv2 = QueryPort(destination.port, CONSUMER_DISCONNECTED, &request2, sizeof(request2), &reply2, sizeof(reply2));
6559e9417d2Sbeveloper 
6569e9417d2Sbeveloper 	// XXX unregister connection with server
6579e9417d2Sbeveloper 	// XXX we should just send a notification, instead of republishing all endpoints
65876669a29Sbeveloper 	List<media_output> outlist;
65976669a29Sbeveloper 	List<media_input> inlist;
6609e9417d2Sbeveloper 	media_node sourcenode;
6619e9417d2Sbeveloper 	media_node destnode;
6629e9417d2Sbeveloper 	if (B_OK == GetNodeFor(source_nodeid, &sourcenode)) {
66376669a29Sbeveloper 		if (B_OK == GetAllOutputs(sourcenode , &outlist))
66476669a29Sbeveloper 			PublishOutputs(sourcenode , &outlist);
6659e9417d2Sbeveloper 		ReleaseNode(sourcenode);
666353b9f6bSbeveloper 	} else FATAL("BMediaRoster::Disconnect: source GetNodeFor failed\n");
6679e9417d2Sbeveloper 	if (B_OK == GetNodeFor(destination_nodeid, &destnode)) {
66876669a29Sbeveloper 		if (B_OK == GetAllInputs(destnode , &inlist))
66976669a29Sbeveloper 			PublishInputs(destnode, &inlist);
6709e9417d2Sbeveloper 		ReleaseNode(destnode);
671353b9f6bSbeveloper 	} else FATAL("BMediaRoster::Disconnect: dest GetNodeFor failed\n");
6729e9417d2Sbeveloper 
6739e9417d2Sbeveloper 
6749e9417d2Sbeveloper 	// send a notification
6759e9417d2Sbeveloper 	BPrivate::media::notifications::ConnectionBroken(source, destination);
6769e9417d2Sbeveloper 
6779e9417d2Sbeveloper 	return (rv1 != B_OK || rv2 != B_OK) ? B_ERROR : B_OK;
67852a38012Sejakowatz }
67952a38012Sejakowatz 
68052a38012Sejakowatz 
68152a38012Sejakowatz status_t
68252a38012Sejakowatz BMediaRoster::StartNode(const media_node & node,
68352a38012Sejakowatz 						bigtime_t at_performance_time)
68452a38012Sejakowatz {
68552a38012Sejakowatz 	CALLED();
6869e9417d2Sbeveloper 	if (node.node <= 0)
68752a38012Sejakowatz 		return B_MEDIA_BAD_NODE;
68852a38012Sejakowatz 
689*0e21b167Sbeveloper 	printf("BMediaRoster::StartNode, node %ld, at perf %Ld\n", node.node, at_performance_time);
690*0e21b167Sbeveloper 
6916396865dSbeveloper 	node_start_command command;
6926396865dSbeveloper 	command.performance_time = at_performance_time;
69352a38012Sejakowatz 
6946396865dSbeveloper 	return SendToPort(node.port, NODE_START, &command, sizeof(command));
69552a38012Sejakowatz }
69652a38012Sejakowatz 
69752a38012Sejakowatz 
69852a38012Sejakowatz status_t
69952a38012Sejakowatz BMediaRoster::StopNode(const media_node & node,
70052a38012Sejakowatz 					   bigtime_t at_performance_time,
70152a38012Sejakowatz 					   bool immediate)
70252a38012Sejakowatz {
70352a38012Sejakowatz 	CALLED();
7049e9417d2Sbeveloper 	if (node.node <= 0)
70552a38012Sejakowatz 		return B_MEDIA_BAD_NODE;
70652a38012Sejakowatz 
707*0e21b167Sbeveloper 	printf("BMediaRoster::StopNode, node %ld, at perf %Ld %s\n", node.node, at_performance_time, immediate ? "NOW" : "");
708*0e21b167Sbeveloper 
7096396865dSbeveloper 	node_stop_command command;
7106396865dSbeveloper 	command.performance_time = at_performance_time;
7116396865dSbeveloper 	command.immediate = immediate;
71252a38012Sejakowatz 
7136396865dSbeveloper 	return SendToPort(node.port, NODE_STOP, &command, sizeof(command));
71452a38012Sejakowatz }
71552a38012Sejakowatz 
71652a38012Sejakowatz 
71752a38012Sejakowatz status_t
71852a38012Sejakowatz BMediaRoster::SeekNode(const media_node & node,
71952a38012Sejakowatz 					   bigtime_t to_media_time,
72052a38012Sejakowatz 					   bigtime_t at_performance_time)
72152a38012Sejakowatz {
72252a38012Sejakowatz 	CALLED();
7239e9417d2Sbeveloper 	if (node.node <= 0)
72452a38012Sejakowatz 		return B_MEDIA_BAD_NODE;
72552a38012Sejakowatz 
726*0e21b167Sbeveloper 	printf("BMediaRoster::SeekNode, node %ld, at perf %Ld, to perf %Ld\n", node.node, at_performance_time, to_media_time);
727*0e21b167Sbeveloper 
7286396865dSbeveloper 	node_seek_command command;
7296396865dSbeveloper 	command.media_time = to_media_time;
7306396865dSbeveloper 	command.performance_time = at_performance_time;
73152a38012Sejakowatz 
7326396865dSbeveloper 	return SendToPort(node.port, NODE_SEEK, &command, sizeof(command));
73352a38012Sejakowatz }
73452a38012Sejakowatz 
73552a38012Sejakowatz 
73652a38012Sejakowatz status_t
73752a38012Sejakowatz BMediaRoster::StartTimeSource(const media_node & node,
73852a38012Sejakowatz 							  bigtime_t at_real_time)
73952a38012Sejakowatz {
74052a38012Sejakowatz 	CALLED();
741*0e21b167Sbeveloper 	if (node.node <= 0) {
742*0e21b167Sbeveloper 		FATAL("BMediaRoster::StartTimeSource node invalid\n");
74352a38012Sejakowatz 		return B_MEDIA_BAD_NODE;
744*0e21b167Sbeveloper 	}
745*0e21b167Sbeveloper 	if ((node.kind & B_TIME_SOURCE) == 0) {
746*0e21b167Sbeveloper 		FATAL("BMediaRoster::StartTimeSource node is no timesource invalid\n");
74752a38012Sejakowatz 		return B_MEDIA_BAD_NODE;
748*0e21b167Sbeveloper 	}
749*0e21b167Sbeveloper 
750*0e21b167Sbeveloper 	printf("BMediaRoster::StartTimeSource, node %ld, at real %Ld\n", node.node, at_real_time);
75152a38012Sejakowatz 
75252a38012Sejakowatz 	BTimeSource::time_source_op_info msg;
75352a38012Sejakowatz 	msg.op = BTimeSource::B_TIMESOURCE_START;
75452a38012Sejakowatz 	msg.real_time = at_real_time;
75552a38012Sejakowatz 
75652a38012Sejakowatz 	return write_port(node.port, TIMESOURCE_OP, &msg, sizeof(msg));
75752a38012Sejakowatz }
75852a38012Sejakowatz 
75952a38012Sejakowatz 
76052a38012Sejakowatz status_t
76152a38012Sejakowatz BMediaRoster::StopTimeSource(const media_node & node,
76252a38012Sejakowatz 							 bigtime_t at_real_time,
76352a38012Sejakowatz 							 bool immediate)
76452a38012Sejakowatz {
76552a38012Sejakowatz 	CALLED();
766*0e21b167Sbeveloper 	if (node.node <= 0) {
767*0e21b167Sbeveloper 		FATAL("BMediaRoster::StartTimeSource node invalid\n");
76852a38012Sejakowatz 		return B_MEDIA_BAD_NODE;
769*0e21b167Sbeveloper 	}
770*0e21b167Sbeveloper 	if ((node.kind & B_TIME_SOURCE) == 0) {
771*0e21b167Sbeveloper 		FATAL("BMediaRoster::StartTimeSource node is no timesource invalid\n");
77252a38012Sejakowatz 		return B_MEDIA_BAD_NODE;
773*0e21b167Sbeveloper 	}
774*0e21b167Sbeveloper 
775*0e21b167Sbeveloper 	printf("BMediaRoster::StopTimeSource, node %ld, at real %Ld %s\n", node.node, at_real_time, immediate ? "NOW" : "");
77652a38012Sejakowatz 
77752a38012Sejakowatz 	BTimeSource::time_source_op_info msg;
77852a38012Sejakowatz 	msg.op = immediate ? BTimeSource::B_TIMESOURCE_STOP_IMMEDIATELY : BTimeSource::B_TIMESOURCE_STOP;
77952a38012Sejakowatz 	msg.real_time = at_real_time;
78052a38012Sejakowatz 
78152a38012Sejakowatz 	return write_port(node.port, TIMESOURCE_OP, &msg, sizeof(msg));
78252a38012Sejakowatz }
78352a38012Sejakowatz 
78452a38012Sejakowatz 
78552a38012Sejakowatz status_t
78652a38012Sejakowatz BMediaRoster::SeekTimeSource(const media_node & node,
78752a38012Sejakowatz 							 bigtime_t to_performance_time,
78852a38012Sejakowatz 							 bigtime_t at_real_time)
78952a38012Sejakowatz {
79052a38012Sejakowatz 	CALLED();
791*0e21b167Sbeveloper 	if (node.node <= 0) {
792*0e21b167Sbeveloper 		FATAL("BMediaRoster::StartTimeSource node invalid\n");
79352a38012Sejakowatz 		return B_MEDIA_BAD_NODE;
794*0e21b167Sbeveloper 	}
795*0e21b167Sbeveloper 	if ((node.kind & B_TIME_SOURCE) == 0) {
796*0e21b167Sbeveloper 		FATAL("BMediaRoster::StartTimeSource node is no timesource invalid\n");
79752a38012Sejakowatz 		return B_MEDIA_BAD_NODE;
798*0e21b167Sbeveloper 	}
799*0e21b167Sbeveloper 
800*0e21b167Sbeveloper 	printf("BMediaRoster::SeekTimeSource, node %ld, at real %Ld, to perf %Ld\n", node.node, at_real_time, to_performance_time);
80152a38012Sejakowatz 
80252a38012Sejakowatz 	BTimeSource::time_source_op_info msg;
80352a38012Sejakowatz 	msg.op = BTimeSource::B_TIMESOURCE_SEEK;
80452a38012Sejakowatz 	msg.real_time = at_real_time;
80552a38012Sejakowatz 	msg.performance_time = to_performance_time;
80652a38012Sejakowatz 
80752a38012Sejakowatz 	return write_port(node.port, TIMESOURCE_OP, &msg, sizeof(msg));
80852a38012Sejakowatz }
80952a38012Sejakowatz 
81052a38012Sejakowatz 
81152a38012Sejakowatz status_t
81252a38012Sejakowatz BMediaRoster::SyncToNode(const media_node & node,
81352a38012Sejakowatz 						 bigtime_t at_time,
81452a38012Sejakowatz 						 bigtime_t timeout)
81552a38012Sejakowatz {
81652a38012Sejakowatz 	UNIMPLEMENTED();
81752a38012Sejakowatz 	return B_ERROR;
81852a38012Sejakowatz }
81952a38012Sejakowatz 
82052a38012Sejakowatz 
82152a38012Sejakowatz status_t
82252a38012Sejakowatz BMediaRoster::SetRunModeNode(const media_node & node,
82352a38012Sejakowatz 							 BMediaNode::run_mode mode)
82452a38012Sejakowatz {
82552a38012Sejakowatz 	CALLED();
8269e9417d2Sbeveloper 	if (node.node <= 0)
82752a38012Sejakowatz 		return B_MEDIA_BAD_NODE;
82852a38012Sejakowatz 
829dfb2ad61Sbeveloper 	node_set_run_mode_command msg;
83052a38012Sejakowatz 	msg.mode = mode;
83152a38012Sejakowatz 
83252a38012Sejakowatz 	return write_port(node.port, NODE_SET_RUN_MODE, &msg, sizeof(msg));
83352a38012Sejakowatz }
83452a38012Sejakowatz 
83552a38012Sejakowatz 
83652a38012Sejakowatz status_t
83752a38012Sejakowatz BMediaRoster::PrerollNode(const media_node & node)
83852a38012Sejakowatz {
83952a38012Sejakowatz 	CALLED();
8409e9417d2Sbeveloper 	if (node.node <= 0)
84152a38012Sejakowatz 		return B_MEDIA_BAD_NODE;
84252a38012Sejakowatz 
84352a38012Sejakowatz 	char dummy;
84452a38012Sejakowatz 	return write_port(node.port, NODE_PREROLL, &dummy, sizeof(dummy));
84552a38012Sejakowatz }
84652a38012Sejakowatz 
84752a38012Sejakowatz 
84852a38012Sejakowatz status_t
84952a38012Sejakowatz BMediaRoster::RollNode(const media_node & node,
85052a38012Sejakowatz 					   bigtime_t startPerformance,
85152a38012Sejakowatz 					   bigtime_t stopPerformance,
85252a38012Sejakowatz 					   bigtime_t atMediaTime)
85352a38012Sejakowatz {
85452a38012Sejakowatz 	UNIMPLEMENTED();
85552a38012Sejakowatz 	return B_ERROR;
85652a38012Sejakowatz }
85752a38012Sejakowatz 
85852a38012Sejakowatz 
85952a38012Sejakowatz status_t
86052a38012Sejakowatz BMediaRoster::SetProducerRunModeDelay(const media_node & node,
86152a38012Sejakowatz 									  bigtime_t delay,
86252a38012Sejakowatz 									  BMediaNode::run_mode mode)
86352a38012Sejakowatz {
86452a38012Sejakowatz 	UNIMPLEMENTED();
86552a38012Sejakowatz 	return B_ERROR;
86652a38012Sejakowatz }
86752a38012Sejakowatz 
86852a38012Sejakowatz 
86952a38012Sejakowatz status_t
87052a38012Sejakowatz BMediaRoster::SetProducerRate(const media_node & producer,
87152a38012Sejakowatz 							  int32 numer,
87252a38012Sejakowatz 							  int32 denom)
87352a38012Sejakowatz {
87452a38012Sejakowatz 	CALLED();
87552a38012Sejakowatz 	if (producer.node == 0)
87652a38012Sejakowatz 		return B_MEDIA_BAD_NODE;
87752a38012Sejakowatz 	if ((producer.kind & B_BUFFER_PRODUCER) == 0)
87852a38012Sejakowatz 		return B_MEDIA_BAD_NODE;
87952a38012Sejakowatz 
880dfb2ad61Sbeveloper 	producer_set_play_rate_request msg;
881dfb2ad61Sbeveloper 	producer_set_play_rate_reply reply;
88252a38012Sejakowatz 	status_t rv;
88352a38012Sejakowatz 	int32 code;
88452a38012Sejakowatz 
88552a38012Sejakowatz 	msg.numer = numer;
88652a38012Sejakowatz 	msg.denom = denom;
88752a38012Sejakowatz 	msg.reply_port = _PortPool->GetPort();
88852a38012Sejakowatz 	rv = write_port(producer.node, PRODUCER_SET_PLAY_RATE, &msg, sizeof(msg));
88952a38012Sejakowatz 	if (rv != B_OK) {
89052a38012Sejakowatz 		_PortPool->PutPort(msg.reply_port);
89152a38012Sejakowatz 		return rv;
89252a38012Sejakowatz 	}
89352a38012Sejakowatz 	rv = read_port(msg.reply_port, &code, &reply, sizeof(reply));
89452a38012Sejakowatz 	_PortPool->PutPort(msg.reply_port);
89552a38012Sejakowatz 	return (rv < B_OK) ? rv : reply.result;
89652a38012Sejakowatz }
89752a38012Sejakowatz 
89852a38012Sejakowatz 
89952a38012Sejakowatz /* Nodes will have available inputs/outputs as long as they are capable */
90052a38012Sejakowatz /* of accepting more connections. The node may create an additional */
90152a38012Sejakowatz /* output or input as the currently available is taken into usage. */
90252a38012Sejakowatz status_t
90352a38012Sejakowatz BMediaRoster::GetLiveNodeInfo(const media_node & node,
90452a38012Sejakowatz 							  live_node_info * out_live_info)
90552a38012Sejakowatz {
9069e9417d2Sbeveloper 	CALLED();
9079e9417d2Sbeveloper 	if (out_live_info == NULL)
9089e9417d2Sbeveloper 		return B_BAD_VALUE;
9099e9417d2Sbeveloper 	if (node.node <= 0)
9109e9417d2Sbeveloper 		return B_MEDIA_BAD_NODE;
9119e9417d2Sbeveloper 
9129e9417d2Sbeveloper 	server_get_live_node_info_request request;
9139e9417d2Sbeveloper 	server_get_live_node_info_reply reply;
9149e9417d2Sbeveloper 	status_t rv;
9159e9417d2Sbeveloper 
9169e9417d2Sbeveloper 	request.node = node;
9179e9417d2Sbeveloper 
9181299bfb2Sbeveloper 	rv = QueryServer(SERVER_GET_LIVE_NODE_INFO, &request, sizeof(request), &reply, sizeof(reply));
9199e9417d2Sbeveloper 	if (rv != B_OK)
9209e9417d2Sbeveloper 		return rv;
9219e9417d2Sbeveloper 
9229e9417d2Sbeveloper 	*out_live_info = reply.live_info;
9239e9417d2Sbeveloper 	return B_OK;
92452a38012Sejakowatz }
92552a38012Sejakowatz 
92652a38012Sejakowatz 
92752a38012Sejakowatz status_t
92852a38012Sejakowatz BMediaRoster::GetLiveNodes(live_node_info * out_live_nodes,
92952a38012Sejakowatz 						   int32 * io_total_count,
93052a38012Sejakowatz 						   const media_format * has_input,
93152a38012Sejakowatz 						   const media_format * has_output,
93252a38012Sejakowatz 						   const char * name,
93352a38012Sejakowatz 						   uint64 node_kinds)
93452a38012Sejakowatz {
9359e9417d2Sbeveloper 	CALLED();
9369e9417d2Sbeveloper 	if (out_live_nodes == NULL || io_total_count == NULL)
9379e9417d2Sbeveloper 		return B_BAD_VALUE;
9389e9417d2Sbeveloper 	if (*io_total_count <= 0)
9399e9417d2Sbeveloper 		return B_BAD_VALUE;
9409e9417d2Sbeveloper 
9419e9417d2Sbeveloper 	// XXX we also support the wildcard search as GetDormantNodes does. This needs to be documented
9429e9417d2Sbeveloper 
9439e9417d2Sbeveloper 	server_get_live_nodes_request request;
9449e9417d2Sbeveloper 	server_get_live_nodes_reply reply;
9459e9417d2Sbeveloper 	status_t rv;
9469e9417d2Sbeveloper 
9479e9417d2Sbeveloper 	request.maxcount = *io_total_count;
9489e9417d2Sbeveloper 	request.has_input = (bool) has_input;
9499e9417d2Sbeveloper 	if (has_input)
9509e9417d2Sbeveloper 		request.inputformat = *has_input; // XXX we should not make a flat copy of media_format
9519e9417d2Sbeveloper 	request.has_output = (bool) has_output;
9529e9417d2Sbeveloper 	if (has_output)
9539e9417d2Sbeveloper 		request.outputformat = *has_output; // XXX we should not make a flat copy of media_format
9549e9417d2Sbeveloper 	request.has_name = (bool) name;
9559e9417d2Sbeveloper 	if (name) {
9569e9417d2Sbeveloper 		int len = strlen(name);
9579e9417d2Sbeveloper 		len = min_c(len, (int)sizeof(request.name) - 1);
9589e9417d2Sbeveloper 		memcpy(request.name, name, len);
9599e9417d2Sbeveloper 		request.name[len] = 0;
9609e9417d2Sbeveloper 	}
9619e9417d2Sbeveloper 	request.require_kinds = node_kinds;
9629e9417d2Sbeveloper 
9639e9417d2Sbeveloper 	rv = QueryServer(SERVER_GET_LIVE_NODES, &request, sizeof(request), &reply, sizeof(reply));
9649e9417d2Sbeveloper 	if (rv != B_OK) {
965353b9f6bSbeveloper 		FATAL("BMediaRoster::GetLiveNodes failed\n");
9661299bfb2Sbeveloper 		*io_total_count = 0;
9679e9417d2Sbeveloper 		return rv;
9689e9417d2Sbeveloper 	}
9699e9417d2Sbeveloper 
9709e9417d2Sbeveloper 	if (reply.count > MAX_LIVE_INFO) {
9719e9417d2Sbeveloper 		live_node_info *live_info;
9729e9417d2Sbeveloper 		area_id clone;
9739e9417d2Sbeveloper 
9749e9417d2Sbeveloper 		clone = clone_area("live_node_info clone", reinterpret_cast<void **>(&live_info), B_ANY_ADDRESS, B_READ_AREA | B_WRITE_AREA, reply.area);
9759e9417d2Sbeveloper 		if (clone < B_OK) {
976353b9f6bSbeveloper 			FATAL("BMediaRoster::GetLiveNodes failed to clone area, %#lx\n", clone);
9779e9417d2Sbeveloper 			delete_area(reply.area);
9781299bfb2Sbeveloper 			*io_total_count = 0;
97952a38012Sejakowatz 			return B_ERROR;
98052a38012Sejakowatz 		}
98152a38012Sejakowatz 
9829e9417d2Sbeveloper 		for (int32 i = 0; i < reply.count; i++) {
9839e9417d2Sbeveloper 			out_live_nodes[i] = live_info[i];
9849e9417d2Sbeveloper 		}
9859e9417d2Sbeveloper 
9869e9417d2Sbeveloper 		delete_area(clone);
9879e9417d2Sbeveloper 		delete_area(reply.area);
9889e9417d2Sbeveloper 	} else {
9899e9417d2Sbeveloper 		for (int32 i = 0; i < reply.count; i++) {
9909e9417d2Sbeveloper 			out_live_nodes[i] = reply.live_info[i];
9919e9417d2Sbeveloper 		}
9929e9417d2Sbeveloper 	}
9939e9417d2Sbeveloper 	*io_total_count = reply.count;
9949e9417d2Sbeveloper 
9959e9417d2Sbeveloper 	return B_OK;
9969e9417d2Sbeveloper }
9979e9417d2Sbeveloper 
99852a38012Sejakowatz 
99952a38012Sejakowatz status_t
100052a38012Sejakowatz BMediaRoster::GetFreeInputsFor(const media_node & node,
100152a38012Sejakowatz 							   media_input * out_free_inputs,
100252a38012Sejakowatz 							   int32 buf_num_inputs,
100352a38012Sejakowatz 							   int32 * out_total_count,
100452a38012Sejakowatz 							   media_type filter_type)
100552a38012Sejakowatz {
10063620737cSbeveloper 	CALLED();
10079e9417d2Sbeveloper 	if (node.node <= 0 || (node.kind & B_BUFFER_CONSUMER) == 0)
10083620737cSbeveloper 		return B_MEDIA_BAD_NODE;
10093620737cSbeveloper 	if (out_free_inputs == NULL || out_total_count == NULL)
10103620737cSbeveloper 		return B_BAD_VALUE;
10113620737cSbeveloper 
101276669a29Sbeveloper 	List<media_input> list;
10133620737cSbeveloper 	media_input *input;
10143620737cSbeveloper 	status_t rv;
10153620737cSbeveloper 
10161299bfb2Sbeveloper 	*out_total_count = 0;
10171299bfb2Sbeveloper 
101876669a29Sbeveloper 	rv = GetAllInputs(node, &list);
10193620737cSbeveloper 	if (B_OK != rv)
10203620737cSbeveloper 		return rv;
10213620737cSbeveloper 
102276669a29Sbeveloper 	int32 i;
102376669a29Sbeveloper 	for (i = 0, list.Rewind(); list.GetNext(&input); i++) {
10243620737cSbeveloper 		if (filter_type != B_MEDIA_UNKNOWN_TYPE && filter_type != input->format.type)
10253620737cSbeveloper 			continue; // media_type used, but doesn't match
10263620737cSbeveloper 		if (input->source != media_source::null)
10273620737cSbeveloper 			continue; // consumer source already connected
10283620737cSbeveloper 		out_free_inputs[i] = *input;
10293620737cSbeveloper 		*out_total_count += 1;
10303620737cSbeveloper 		buf_num_inputs -= 1;
10313620737cSbeveloper 		if (buf_num_inputs == 0)
10323620737cSbeveloper 			break;
10333620737cSbeveloper 	}
10343620737cSbeveloper 
103576669a29Sbeveloper 	PublishInputs(node, &list);
10363620737cSbeveloper 	return B_OK;
103752a38012Sejakowatz }
103852a38012Sejakowatz 
103952a38012Sejakowatz 
104052a38012Sejakowatz status_t
104152a38012Sejakowatz BMediaRoster::GetConnectedInputsFor(const media_node & node,
104252a38012Sejakowatz 									media_input * out_active_inputs,
104352a38012Sejakowatz 									int32 buf_num_inputs,
104452a38012Sejakowatz 									int32 * out_total_count)
104552a38012Sejakowatz {
10463620737cSbeveloper 	CALLED();
10479e9417d2Sbeveloper 	if (node.node <= 0 || (node.kind & B_BUFFER_CONSUMER) == 0)
10483620737cSbeveloper 		return B_MEDIA_BAD_NODE;
10493620737cSbeveloper 	if (out_active_inputs == NULL || out_total_count == NULL)
10503620737cSbeveloper 		return B_BAD_VALUE;
10513620737cSbeveloper 
105276669a29Sbeveloper 	List<media_input> list;
10533620737cSbeveloper 	media_input *input;
10543620737cSbeveloper 	status_t rv;
10553620737cSbeveloper 
10561299bfb2Sbeveloper 	*out_total_count = 0;
10571299bfb2Sbeveloper 
105876669a29Sbeveloper 	rv = GetAllInputs(node, &list);
10593620737cSbeveloper 	if (B_OK != rv)
10603620737cSbeveloper 		return rv;
10613620737cSbeveloper 
106276669a29Sbeveloper 	int32 i;
106376669a29Sbeveloper 	for (i = 0, list.Rewind(); list.GetNext(&input); i++) {
10643620737cSbeveloper 		if (input->source == media_source::null)
10653620737cSbeveloper 			continue; // consumer source not connected
10663620737cSbeveloper 		out_active_inputs[i] = *input;
10673620737cSbeveloper 		*out_total_count += 1;
10683620737cSbeveloper 		buf_num_inputs -= 1;
10693620737cSbeveloper 		if (buf_num_inputs == 0)
10703620737cSbeveloper 			break;
10713620737cSbeveloper 	}
10723620737cSbeveloper 
107376669a29Sbeveloper 	PublishInputs(node, &list);
10743620737cSbeveloper 	return B_OK;
107552a38012Sejakowatz }
107652a38012Sejakowatz 
107752a38012Sejakowatz 
107852a38012Sejakowatz status_t
107952a38012Sejakowatz BMediaRoster::GetAllInputsFor(const media_node & node,
108052a38012Sejakowatz 							  media_input * out_inputs,
108152a38012Sejakowatz 							  int32 buf_num_inputs,
108252a38012Sejakowatz 							  int32 * out_total_count)
108352a38012Sejakowatz {
108452a38012Sejakowatz 	CALLED();
10859e9417d2Sbeveloper 	if (node.node <= 0 || (node.kind & B_BUFFER_CONSUMER) == 0)
108652a38012Sejakowatz 		return B_MEDIA_BAD_NODE;
108752a38012Sejakowatz 	if (out_inputs == NULL || out_total_count == NULL)
108852a38012Sejakowatz 		return B_BAD_VALUE;
108952a38012Sejakowatz 
109076669a29Sbeveloper 	List<media_input> list;
10913620737cSbeveloper 	media_input *input;
109252a38012Sejakowatz 	status_t rv;
109352a38012Sejakowatz 
10941299bfb2Sbeveloper 	*out_total_count = 0;
10951299bfb2Sbeveloper 
109676669a29Sbeveloper 	rv = GetAllInputs(node, &list);
10973620737cSbeveloper 	if (B_OK != rv)
10983620737cSbeveloper 		return rv;
10993620737cSbeveloper 
110076669a29Sbeveloper 	int32 i;
110176669a29Sbeveloper 	for (i = 0, list.Rewind(); list.GetNext(&input); i++) {
11023620737cSbeveloper 		out_inputs[i] = *input;
110352a38012Sejakowatz 		*out_total_count += 1;
11043620737cSbeveloper 		buf_num_inputs -= 1;
11053620737cSbeveloper 		if (buf_num_inputs == 0)
11063620737cSbeveloper 			break;
110752a38012Sejakowatz 	}
110852a38012Sejakowatz 
110976669a29Sbeveloper 	PublishInputs(node, &list);
11103620737cSbeveloper 	return B_OK;
111152a38012Sejakowatz }
111252a38012Sejakowatz 
111352a38012Sejakowatz 
111452a38012Sejakowatz status_t
111552a38012Sejakowatz BMediaRoster::GetFreeOutputsFor(const media_node & node,
111652a38012Sejakowatz 								media_output * out_free_outputs,
111752a38012Sejakowatz 								int32 buf_num_outputs,
111852a38012Sejakowatz 								int32 * out_total_count,
111952a38012Sejakowatz 								media_type filter_type)
112052a38012Sejakowatz {
11213620737cSbeveloper 	CALLED();
11229e9417d2Sbeveloper 	if (node.node <= 0 || (node.kind & B_BUFFER_PRODUCER) == 0)
11233620737cSbeveloper 		return B_MEDIA_BAD_NODE;
11243620737cSbeveloper 	if (out_free_outputs == NULL || out_total_count == NULL)
11253620737cSbeveloper 		return B_BAD_VALUE;
11263620737cSbeveloper 
112776669a29Sbeveloper 	List<media_output> list;
11283620737cSbeveloper 	media_output *output;
11293620737cSbeveloper 	status_t rv;
11303620737cSbeveloper 
11311299bfb2Sbeveloper 	*out_total_count = 0;
11321299bfb2Sbeveloper 
113376669a29Sbeveloper 	rv = GetAllOutputs(node, &list);
11343620737cSbeveloper 	if (B_OK != rv)
11353620737cSbeveloper 		return rv;
11363620737cSbeveloper 
113776669a29Sbeveloper 	int32 i;
113876669a29Sbeveloper 	for (i = 0, list.Rewind(); list.GetNext(&output); i++) {
11393620737cSbeveloper 		if (filter_type != B_MEDIA_UNKNOWN_TYPE && filter_type != output->format.type)
11403620737cSbeveloper 			continue; // media_type used, but doesn't match
11413620737cSbeveloper 		if (output->destination != media_destination::null)
11423620737cSbeveloper 			continue; // producer destination already connected
11433620737cSbeveloper 		out_free_outputs[i] = *output;
11443620737cSbeveloper 		*out_total_count += 1;
11453620737cSbeveloper 		buf_num_outputs -= 1;
11463620737cSbeveloper 		if (buf_num_outputs == 0)
11473620737cSbeveloper 			break;
11483620737cSbeveloper 	}
11493620737cSbeveloper 
115076669a29Sbeveloper 	PublishOutputs(node, &list);
11513620737cSbeveloper 	return B_OK;
115252a38012Sejakowatz }
115352a38012Sejakowatz 
115452a38012Sejakowatz 
115552a38012Sejakowatz status_t
115652a38012Sejakowatz BMediaRoster::GetConnectedOutputsFor(const media_node & node,
115752a38012Sejakowatz 									 media_output * out_active_outputs,
115852a38012Sejakowatz 									 int32 buf_num_outputs,
115952a38012Sejakowatz 									 int32 * out_total_count)
116052a38012Sejakowatz {
11613620737cSbeveloper 	CALLED();
11629e9417d2Sbeveloper 	if (node.node <= 0 || (node.kind & B_BUFFER_PRODUCER) == 0)
11633620737cSbeveloper 		return B_MEDIA_BAD_NODE;
11643620737cSbeveloper 	if (out_active_outputs == NULL || out_total_count == NULL)
11653620737cSbeveloper 		return B_BAD_VALUE;
11663620737cSbeveloper 
116776669a29Sbeveloper 	List<media_output> list;
11683620737cSbeveloper 	media_output *output;
11693620737cSbeveloper 	status_t rv;
11703620737cSbeveloper 
11711299bfb2Sbeveloper 	*out_total_count = 0;
11721299bfb2Sbeveloper 
117376669a29Sbeveloper 	rv = GetAllOutputs(node, &list);
11743620737cSbeveloper 	if (B_OK != rv)
11753620737cSbeveloper 		return rv;
11763620737cSbeveloper 
117776669a29Sbeveloper 	int32 i;
117876669a29Sbeveloper 	for (i = 0, list.Rewind(); list.GetNext(&output); i++) {
11793620737cSbeveloper 		if (output->destination == media_destination::null)
11803620737cSbeveloper 			continue; // producer destination not connected
11813620737cSbeveloper 		out_active_outputs[i] = *output;
11823620737cSbeveloper 		*out_total_count += 1;
11833620737cSbeveloper 		buf_num_outputs -= 1;
11843620737cSbeveloper 		if (buf_num_outputs == 0)
11853620737cSbeveloper 			break;
11863620737cSbeveloper 	}
11873620737cSbeveloper 
118876669a29Sbeveloper 	PublishOutputs(node, &list);
11893620737cSbeveloper 	return B_OK;
119052a38012Sejakowatz }
119152a38012Sejakowatz 
119252a38012Sejakowatz 
119352a38012Sejakowatz status_t
119452a38012Sejakowatz BMediaRoster::GetAllOutputsFor(const media_node & node,
119552a38012Sejakowatz 							   media_output * out_outputs,
119652a38012Sejakowatz 							   int32 buf_num_outputs,
119752a38012Sejakowatz 							   int32 * out_total_count)
119852a38012Sejakowatz {
119952a38012Sejakowatz 	CALLED();
12009e9417d2Sbeveloper 	if (node.node <= 0 || (node.kind & B_BUFFER_PRODUCER) == 0)
120152a38012Sejakowatz 		return B_MEDIA_BAD_NODE;
120252a38012Sejakowatz 	if (out_outputs == NULL || out_total_count == NULL)
120352a38012Sejakowatz 		return B_BAD_VALUE;
120452a38012Sejakowatz 
120576669a29Sbeveloper 	List<media_output> list;
12063620737cSbeveloper 	media_output *output;
120752a38012Sejakowatz 	status_t rv;
120852a38012Sejakowatz 
12091299bfb2Sbeveloper 	*out_total_count = 0;
12101299bfb2Sbeveloper 
121176669a29Sbeveloper 	rv = GetAllOutputs(node, &list);
12123620737cSbeveloper 	if (B_OK != rv)
12133620737cSbeveloper 		return rv;
12143620737cSbeveloper 
121576669a29Sbeveloper 	int32 i;
121676669a29Sbeveloper 	for (i = 0, list.Rewind(); list.GetNext(&output); i++) {
12173620737cSbeveloper 		out_outputs[i] = *output;
121852a38012Sejakowatz 		*out_total_count += 1;
12193620737cSbeveloper 		buf_num_outputs -= 1;
12203620737cSbeveloper 		if (buf_num_outputs == 0)
12213620737cSbeveloper 			break;
122252a38012Sejakowatz 	}
122352a38012Sejakowatz 
122476669a29Sbeveloper 	PublishOutputs(node, &list);
12253620737cSbeveloper 	return B_OK;
122652a38012Sejakowatz }
122752a38012Sejakowatz 
122852a38012Sejakowatz 
122952a38012Sejakowatz status_t
123052a38012Sejakowatz BMediaRoster::StartWatching(const BMessenger & where)
123152a38012Sejakowatz {
1232eae26d3dSbeveloper 	CALLED();
1233eae26d3dSbeveloper 	if (!where.IsValid()) {
1234353b9f6bSbeveloper 		FATAL("BMediaRoster::StartWatching: messenger invalid!\n");
1235eae26d3dSbeveloper 		return B_BAD_VALUE;
1236eae26d3dSbeveloper 	}
1237f4925104Sbeveloper 	return BPrivate::media::notifications::Register(where, media_node::null, B_MEDIA_WILDCARD);
123852a38012Sejakowatz }
123952a38012Sejakowatz 
124052a38012Sejakowatz 
124152a38012Sejakowatz status_t
124252a38012Sejakowatz BMediaRoster::StartWatching(const BMessenger & where,
124352a38012Sejakowatz 							int32 notificationType)
124452a38012Sejakowatz {
1245eae26d3dSbeveloper 	CALLED();
1246eae26d3dSbeveloper 	if (!where.IsValid()) {
1247353b9f6bSbeveloper 		FATAL("BMediaRoster::StartWatching: messenger invalid!\n");
1248eae26d3dSbeveloper 		return B_BAD_VALUE;
1249eae26d3dSbeveloper 	}
1250f4925104Sbeveloper 	if (false == BPrivate::media::notifications::IsValidNotificationRequest(false, notificationType)) {
1251353b9f6bSbeveloper 		FATAL("BMediaRoster::StartWatching: notificationType invalid!\n");
1252eae26d3dSbeveloper 		return B_BAD_VALUE;
1253eae26d3dSbeveloper 	}
1254f4925104Sbeveloper 	return BPrivate::media::notifications::Register(where, media_node::null, notificationType);
125552a38012Sejakowatz }
125652a38012Sejakowatz 
125752a38012Sejakowatz 
125852a38012Sejakowatz status_t
125952a38012Sejakowatz BMediaRoster::StartWatching(const BMessenger & where,
126052a38012Sejakowatz 							const media_node & node,
126152a38012Sejakowatz 							int32 notificationType)
126252a38012Sejakowatz {
1263eae26d3dSbeveloper 	CALLED();
1264eae26d3dSbeveloper 	if (!where.IsValid()) {
1265353b9f6bSbeveloper 		FATAL("BMediaRoster::StartWatching: messenger invalid!\n");
1266eae26d3dSbeveloper 		return B_BAD_VALUE;
1267eae26d3dSbeveloper 	}
12689e9417d2Sbeveloper 	if (node.node <= 0) {
1269353b9f6bSbeveloper 		FATAL("BMediaRoster::StartWatching: node invalid!\n");
1270eae26d3dSbeveloper 		return B_MEDIA_BAD_NODE;
1271eae26d3dSbeveloper 	}
1272f4925104Sbeveloper 	if (false == BPrivate::media::notifications::IsValidNotificationRequest(true, notificationType)) {
1273353b9f6bSbeveloper 		FATAL("BMediaRoster::StartWatching: notificationType invalid!\n");
1274eae26d3dSbeveloper 		return B_BAD_VALUE;
1275eae26d3dSbeveloper 	}
1276f4925104Sbeveloper 	return BPrivate::media::notifications::Register(where, node, notificationType);
127752a38012Sejakowatz }
127852a38012Sejakowatz 
127952a38012Sejakowatz 
128052a38012Sejakowatz status_t
128152a38012Sejakowatz BMediaRoster::StopWatching(const BMessenger & where)
128252a38012Sejakowatz {
1283eae26d3dSbeveloper 	CALLED();
1284eae26d3dSbeveloper 	// messenger may already be invalid, so we don't check this
1285f4925104Sbeveloper 	return BPrivate::media::notifications::Unregister(where, media_node::null, B_MEDIA_WILDCARD);
128652a38012Sejakowatz }
128752a38012Sejakowatz 
128852a38012Sejakowatz 
128952a38012Sejakowatz status_t
129052a38012Sejakowatz BMediaRoster::StopWatching(const BMessenger & where,
129152a38012Sejakowatz 						   int32 notificationType)
129252a38012Sejakowatz {
1293eae26d3dSbeveloper 	CALLED();
1294eae26d3dSbeveloper 	// messenger may already be invalid, so we don't check this
1295f4925104Sbeveloper 	if (false == BPrivate::media::notifications::IsValidNotificationRequest(false, notificationType)) {
1296353b9f6bSbeveloper 		FATAL("BMediaRoster::StopWatching: notificationType invalid!\n");
1297eae26d3dSbeveloper 		return B_BAD_VALUE;
1298eae26d3dSbeveloper 	}
1299f4925104Sbeveloper 	return BPrivate::media::notifications::Unregister(where, media_node::null, notificationType);
130052a38012Sejakowatz }
130152a38012Sejakowatz 
130252a38012Sejakowatz 
130352a38012Sejakowatz status_t
130452a38012Sejakowatz BMediaRoster::StopWatching(const BMessenger & where,
130552a38012Sejakowatz 						   const media_node & node,
130652a38012Sejakowatz 						   int32 notificationType)
130752a38012Sejakowatz {
1308eae26d3dSbeveloper 	CALLED();
1309eae26d3dSbeveloper 	// messenger may already be invalid, so we don't check this
13109e9417d2Sbeveloper 	if (node.node <= 0) {
1311353b9f6bSbeveloper 		FATAL("BMediaRoster::StopWatching: node invalid!\n");
1312eae26d3dSbeveloper 		return B_MEDIA_BAD_NODE;
1313eae26d3dSbeveloper 	}
1314f4925104Sbeveloper 	if (false == BPrivate::media::notifications::IsValidNotificationRequest(true, notificationType)) {
1315353b9f6bSbeveloper 		FATAL("BMediaRoster::StopWatching: notificationType invalid!\n");
1316eae26d3dSbeveloper 		return B_BAD_VALUE;
1317eae26d3dSbeveloper 	}
1318f4925104Sbeveloper 	return BPrivate::media::notifications::Unregister(where, node, notificationType);
131952a38012Sejakowatz }
132052a38012Sejakowatz 
132152a38012Sejakowatz 
132252a38012Sejakowatz status_t
132352a38012Sejakowatz BMediaRoster::RegisterNode(BMediaNode * node)
132452a38012Sejakowatz {
132552a38012Sejakowatz 	CALLED();
132652a38012Sejakowatz 	if (node == NULL)
132752a38012Sejakowatz 		return B_BAD_VALUE;
132852a38012Sejakowatz 
13293620737cSbeveloper 	status_t rv;
13309e9417d2Sbeveloper 	BMediaAddOn *addon;
13319e9417d2Sbeveloper 	int32 addon_flavor_id;
13329e9417d2Sbeveloper 	media_addon_id addon_id;
13333620737cSbeveloper 
13349e9417d2Sbeveloper 	addon_flavor_id = 0;
13359e9417d2Sbeveloper 	addon = node->AddOn(&addon_flavor_id);
13369e9417d2Sbeveloper 	addon_id = addon ? addon->AddonID() : -1;
133752a38012Sejakowatz 
13389e9417d2Sbeveloper 	server_register_node_request request;
13399e9417d2Sbeveloper 	server_register_node_reply reply;
13409e9417d2Sbeveloper 
13419e9417d2Sbeveloper 	request.addon_id = addon_id;
13429e9417d2Sbeveloper 	request.addon_flavor_id = addon_flavor_id;
13439e9417d2Sbeveloper 	strcpy(request.name, node->Name());
13449e9417d2Sbeveloper 	request.kinds = node->Kinds();
13459e9417d2Sbeveloper 	request.port = node->ControlPort();
13469e9417d2Sbeveloper 	request.team = team;
13479e9417d2Sbeveloper 
13481299bfb2Sbeveloper 	TRACE("BMediaRoster::RegisterNode: sending SERVER_REGISTER_NODE: port %ld, kinds %#Lx, team %ld, name '%s'\n", request.port, request.kinds, request.team, request.name);
13491299bfb2Sbeveloper 
13509e9417d2Sbeveloper 	rv = QueryServer(SERVER_REGISTER_NODE, &request, sizeof(request), &reply, sizeof(reply));
13519e9417d2Sbeveloper 	if (rv != B_OK) {
1352353b9f6bSbeveloper 		FATAL("BMediaRoster::RegisterNode: failed to register node %s (error %#lx)\n", node->Name(), rv);
13539e9417d2Sbeveloper 		return rv;
13549e9417d2Sbeveloper 	}
13559e9417d2Sbeveloper 
13569e9417d2Sbeveloper 	// we are a friend class of BMediaNode and initilize this member variable
13579e9417d2Sbeveloper 	node->fNodeID = reply.nodeid;
13589e9417d2Sbeveloper 	ASSERT(reply.nodeid == node->Node().node);
13599e9417d2Sbeveloper 	ASSERT(reply.nodeid == node->ID());
13609e9417d2Sbeveloper 
13619e9417d2Sbeveloper 	// call the callback
13629e9417d2Sbeveloper 	node->NodeRegistered();
13633620737cSbeveloper 
1364*0e21b167Sbeveloper 	// if the BMediaNode also inherits from BTimeSource, we need to call BTimeSource::FinishCreate()
1365*0e21b167Sbeveloper 	if (node->Kinds() & B_TIME_SOURCE) {
1366*0e21b167Sbeveloper 		BTimeSource *ts;
1367*0e21b167Sbeveloper 		ts = dynamic_cast<BTimeSource *>(node);
1368*0e21b167Sbeveloper 		if (ts)
1369*0e21b167Sbeveloper 			ts->FinishCreate();
1370*0e21b167Sbeveloper 	}
1371*0e21b167Sbeveloper 
1372570f7d04Sbeveloper /*
13733620737cSbeveloper 	// register existing inputs and outputs with the
13743620737cSbeveloper 	// media_server, this allows GetLiveNodes() to work
13753620737cSbeveloper 	// with created, but unconnected nodes.
13763620737cSbeveloper 	if (node->Kinds() & B_BUFFER_PRODUCER) {
13773620737cSbeveloper 		Stack<media_output> stack;
13783620737cSbeveloper 		if (B_OK == GetAllOutputs(node->Node(), &stack))
13793620737cSbeveloper 			PublishOutputs(node->Node(), &stack);
13803620737cSbeveloper 	} else if (node->Kinds() & B_BUFFER_CONSUMER) {
13813620737cSbeveloper 		Stack<media_input> stack;
13823620737cSbeveloper 		if (B_OK == GetAllInputs(node->Node(), &stack))
13833620737cSbeveloper 			PublishInputs(node->Node(), &stack);
13843620737cSbeveloper 	}
1385570f7d04Sbeveloper */
1386570f7d04Sbeveloper 
13871299bfb2Sbeveloper 	BPrivate::media::notifications::NodesCreated(&reply.nodeid, 1);
1388570f7d04Sbeveloper /*
1389570f7d04Sbeveloper 	TRACE("BMediaRoster::RegisterNode: registered node name '%s', id %ld, addon %ld, flavor %ld\n", node->Name(), node->ID(), addon_id, addon_flavor_id);
1390570f7d04Sbeveloper 	TRACE("BMediaRoster::RegisterNode: node this               %p\n", node);
1391570f7d04Sbeveloper 	TRACE("BMediaRoster::RegisterNode: node fConsumerThis      %p\n", node->fConsumerThis);
1392570f7d04Sbeveloper 	TRACE("BMediaRoster::RegisterNode: node fProducerThis      %p\n", node->fProducerThis);
1393570f7d04Sbeveloper 	TRACE("BMediaRoster::RegisterNode: node fFileInterfaceThis %p\n", node->fFileInterfaceThis);
1394570f7d04Sbeveloper 	TRACE("BMediaRoster::RegisterNode: node fControllableThis  %p\n", node->fControllableThis);
1395570f7d04Sbeveloper 	TRACE("BMediaRoster::RegisterNode: node fTimeSourceThis    %p\n", node->fTimeSourceThis);
1396570f7d04Sbeveloper */
13979e9417d2Sbeveloper 
13989e9417d2Sbeveloper 	return B_OK;
139952a38012Sejakowatz }
140052a38012Sejakowatz 
140152a38012Sejakowatz 
140252a38012Sejakowatz status_t
140352a38012Sejakowatz BMediaRoster::UnregisterNode(BMediaNode * node)
140452a38012Sejakowatz {
14059e9417d2Sbeveloper 	CALLED();
14069e9417d2Sbeveloper 	if (node == NULL)
14079e9417d2Sbeveloper 		return B_BAD_VALUE;
14089e9417d2Sbeveloper 
14099e9417d2Sbeveloper 	if (node->fRefCount != 0) {
1410353b9f6bSbeveloper 		FATAL("BMediaRoster::UnregisterNode: Warning node name '%s' has local reference count of %ld\n", node->Name(), node->fRefCount);
14119e9417d2Sbeveloper 		// no return here, we continue and unregister!
14129e9417d2Sbeveloper 	}
14139e9417d2Sbeveloper 	if (node->ID() == -2) {
1414353b9f6bSbeveloper 		FATAL("BMediaRoster::UnregisterNode: Warning node name '%s' already unregistered\n", node->Name());
14159e9417d2Sbeveloper 		return B_OK;
14169e9417d2Sbeveloper 	}
14179e9417d2Sbeveloper 
14189e9417d2Sbeveloper 	server_unregister_node_request request;
14199e9417d2Sbeveloper 	server_unregister_node_reply reply;
14209e9417d2Sbeveloper 	status_t rv;
14219e9417d2Sbeveloper 
14229e9417d2Sbeveloper 	request.nodeid = node->ID();
14239e9417d2Sbeveloper 	request.team = team;
14249e9417d2Sbeveloper 
14251299bfb2Sbeveloper 	// send a notification
14261299bfb2Sbeveloper 	BPrivate::media::notifications::NodesDeleted(&request.nodeid, 1);
14271299bfb2Sbeveloper 
14289e9417d2Sbeveloper 	rv = QueryServer(SERVER_UNREGISTER_NODE, &request, sizeof(request), &reply, sizeof(reply));
14299e9417d2Sbeveloper 	if (rv != B_OK) {
1430353b9f6bSbeveloper 		FATAL("BMediaRoster::UnregisterNode: failed to unregister node name '%s' (error %#lx)\n", node->Name(), rv);
14319e9417d2Sbeveloper 		return rv;
14329e9417d2Sbeveloper 	}
14339e9417d2Sbeveloper 
14349e9417d2Sbeveloper 	if (reply.addon_id != -1)
14359e9417d2Sbeveloper 		_DormantNodeManager->PutAddon(reply.addon_id);
14369e9417d2Sbeveloper 
14371299bfb2Sbeveloper 	// we are a friend class of BMediaNode and invalidate this member variable
14389e9417d2Sbeveloper 	node->fNodeID = -2;
14399e9417d2Sbeveloper 
14409e9417d2Sbeveloper 	return B_OK;
144152a38012Sejakowatz }
144252a38012Sejakowatz 
144352a38012Sejakowatz 
144452a38012Sejakowatz //	thread safe for multiple calls to Roster()
144552a38012Sejakowatz /* static */ BMediaRoster *
144652a38012Sejakowatz BMediaRoster::Roster(status_t* out_error)
144752a38012Sejakowatz {
144852a38012Sejakowatz 	static BLocker locker("BMediaRoster::Roster locker");
144952a38012Sejakowatz 	locker.Lock();
145052a38012Sejakowatz 	if (_sDefault == NULL) {
145152a38012Sejakowatz 		_sDefault = new BMediaRoster();
145252a38012Sejakowatz 		if (out_error != NULL)
145352a38012Sejakowatz 			*out_error = B_OK;
145452a38012Sejakowatz 	} else {
145552a38012Sejakowatz 		if (out_error != NULL)
145652a38012Sejakowatz 			*out_error = B_OK;
145752a38012Sejakowatz 	}
145852a38012Sejakowatz 	locker.Unlock();
145952a38012Sejakowatz 	return _sDefault;
146052a38012Sejakowatz }
146152a38012Sejakowatz 
146252a38012Sejakowatz 
146352a38012Sejakowatz //	won't create it if there isn't one
146452a38012Sejakowatz //	not thread safe if you call Roster() at the same time
146552a38012Sejakowatz /* static */ BMediaRoster *
146652a38012Sejakowatz BMediaRoster::CurrentRoster()
146752a38012Sejakowatz {
146852a38012Sejakowatz 	return _sDefault;
146952a38012Sejakowatz }
147052a38012Sejakowatz 
147152a38012Sejakowatz 
147252a38012Sejakowatz status_t
147352a38012Sejakowatz BMediaRoster::SetTimeSourceFor(media_node_id node,
147452a38012Sejakowatz 							   media_node_id time_source)
147552a38012Sejakowatz {
1476aac800c2Sbeveloper 	CALLED();
1477aac800c2Sbeveloper 	if (node <= 0 || time_source <= 0)
1478aac800c2Sbeveloper 		return B_BAD_VALUE;
1479aac800c2Sbeveloper 
1480aac800c2Sbeveloper 	media_node clone;
1481aac800c2Sbeveloper 	status_t rv, result;
1482aac800c2Sbeveloper 
1483aac800c2Sbeveloper 	rv = GetNodeFor(node, &clone);
1484aac800c2Sbeveloper 	if (rv != B_OK) {
1485aac800c2Sbeveloper 		FATAL("BMediaRoster::SetTimeSourceFor, GetNodeFor failed, node id %ld\n", node);
148652a38012Sejakowatz 		return B_ERROR;
148752a38012Sejakowatz 	}
148852a38012Sejakowatz 
1489aac800c2Sbeveloper 	result = B_OK;
1490aac800c2Sbeveloper 	node_set_timesource_command cmd;
1491aac800c2Sbeveloper 	cmd.timesource_id = time_source;
1492aac800c2Sbeveloper 	rv = SendToPort(clone.port, NODE_SET_TIMESOURCE, &cmd, sizeof(cmd));
1493aac800c2Sbeveloper 	if (rv != B_OK) {
1494aac800c2Sbeveloper 		FATAL("BMediaRoster::SetTimeSourceFor, sending NODE_SET_TIMESOURCE failed, node id %ld\n", node);
1495aac800c2Sbeveloper 		result = B_ERROR;
1496aac800c2Sbeveloper 	}
1497aac800c2Sbeveloper 
1498aac800c2Sbeveloper 	rv = ReleaseNode(clone);
1499aac800c2Sbeveloper 	if (rv != B_OK) {
1500aac800c2Sbeveloper 		FATAL("BMediaRoster::SetTimeSourceFor, ReleaseNode failed, node id %ld\n", node);
1501aac800c2Sbeveloper 		result = B_ERROR;
1502aac800c2Sbeveloper 	}
1503aac800c2Sbeveloper 
1504aac800c2Sbeveloper 	return result;
1505aac800c2Sbeveloper }
1506aac800c2Sbeveloper 
150752a38012Sejakowatz 
150852a38012Sejakowatz status_t
150952a38012Sejakowatz BMediaRoster::GetParameterWebFor(const media_node & node,
151052a38012Sejakowatz 								 BParameterWeb ** out_web)
151152a38012Sejakowatz {
151252a38012Sejakowatz 	UNIMPLEMENTED();
151352a38012Sejakowatz 	return B_ERROR;
151452a38012Sejakowatz }
151552a38012Sejakowatz 
151652a38012Sejakowatz 
151752a38012Sejakowatz status_t
151852a38012Sejakowatz BMediaRoster::StartControlPanel(const media_node & node,
151952a38012Sejakowatz 								BMessenger * out_messenger)
152052a38012Sejakowatz {
152152a38012Sejakowatz 	UNIMPLEMENTED();
152252a38012Sejakowatz 	return B_ERROR;
152352a38012Sejakowatz }
152452a38012Sejakowatz 
152552a38012Sejakowatz 
152652a38012Sejakowatz status_t
152752a38012Sejakowatz BMediaRoster::GetDormantNodes(dormant_node_info * out_info,
152852a38012Sejakowatz 							  int32 * io_count,
152952a38012Sejakowatz 							  const media_format * has_input /* = NULL */,
153052a38012Sejakowatz 							  const media_format * has_output /* = NULL */,
153152a38012Sejakowatz 							  const char * name /* = NULL */,
153252a38012Sejakowatz 							  uint64 require_kinds /* = NULL */,
153352a38012Sejakowatz 							  uint64 deny_kinds /* = NULL */)
153452a38012Sejakowatz {
153552a38012Sejakowatz 	CALLED();
153652a38012Sejakowatz 	if (out_info == NULL)
153752a38012Sejakowatz 		return B_BAD_VALUE;
153852a38012Sejakowatz 	if (io_count == NULL)
153952a38012Sejakowatz 		return B_BAD_VALUE;
154052a38012Sejakowatz 	if (*io_count <= 0)
154152a38012Sejakowatz 		return B_BAD_VALUE;
154252a38012Sejakowatz 
154352a38012Sejakowatz 	xfer_server_get_dormant_nodes msg;
154452a38012Sejakowatz 	port_id port;
154552a38012Sejakowatz 	status_t rv;
154652a38012Sejakowatz 
154752a38012Sejakowatz 	port = find_port("media_server port");
154852a38012Sejakowatz 	if (port <= B_OK)
154952a38012Sejakowatz 		return B_ERROR;
155052a38012Sejakowatz 
155152a38012Sejakowatz 	msg.maxcount = *io_count;
155252a38012Sejakowatz 	msg.has_input = (bool) has_input;
155352a38012Sejakowatz 	if (has_input)
155452a38012Sejakowatz 		msg.inputformat = *has_input; // XXX we should not make a flat copy of media_format
155552a38012Sejakowatz 	msg.has_output = (bool) has_output;
155652a38012Sejakowatz 	if (has_output)
155752a38012Sejakowatz 		msg.outputformat = *has_output;; // XXX we should not make a flat copy of media_format
155852a38012Sejakowatz 	msg.has_name = (bool) name;
155952a38012Sejakowatz 	if (name) {
15609e9417d2Sbeveloper 		int len = strlen(name);
15619e9417d2Sbeveloper 		len = min_c(len, (int)sizeof(msg.name) - 1);
156252a38012Sejakowatz 		memcpy(msg.name, name, len);
156352a38012Sejakowatz 		msg.name[len] = 0;
156452a38012Sejakowatz 	}
156552a38012Sejakowatz 	msg.require_kinds = require_kinds;
156652a38012Sejakowatz 	msg.deny_kinds = deny_kinds;
156752a38012Sejakowatz 	msg.reply_port = _PortPool->GetPort();
156852a38012Sejakowatz 
156952a38012Sejakowatz 	rv = write_port(port, SERVER_GET_DORMANT_NODES, &msg, sizeof(msg));
157052a38012Sejakowatz 	if (rv != B_OK) {
157152a38012Sejakowatz 		_PortPool->PutPort(msg.reply_port);
157252a38012Sejakowatz 		return rv;
157352a38012Sejakowatz 	}
157452a38012Sejakowatz 
157552a38012Sejakowatz 	xfer_server_get_dormant_nodes_reply reply;
157652a38012Sejakowatz 	int32 code;
157752a38012Sejakowatz 
157852a38012Sejakowatz 	rv = read_port(msg.reply_port, &code, &reply, sizeof(reply));
157952a38012Sejakowatz 	if (rv < B_OK) {
158052a38012Sejakowatz 		_PortPool->PutPort(msg.reply_port);
158152a38012Sejakowatz 		return rv;
158252a38012Sejakowatz 	}
158352a38012Sejakowatz 
158452a38012Sejakowatz 	*io_count = reply.count;
158552a38012Sejakowatz 
158652a38012Sejakowatz 	if (*io_count > 0) {
158752a38012Sejakowatz 		rv = read_port(msg.reply_port, &code, out_info, *io_count * sizeof(dormant_node_info));
158852a38012Sejakowatz 		if (rv < B_OK)
158952a38012Sejakowatz 			reply.result = rv;
159052a38012Sejakowatz 	}
159152a38012Sejakowatz 	_PortPool->PutPort(msg.reply_port);
159252a38012Sejakowatz 
159352a38012Sejakowatz 	return reply.result;
159452a38012Sejakowatz }
159552a38012Sejakowatz 
159652a38012Sejakowatz 
159752a38012Sejakowatz status_t
159852a38012Sejakowatz BMediaRoster::InstantiateDormantNode(const dormant_node_info & in_info,
159952a38012Sejakowatz 									 media_node * out_node,
160052a38012Sejakowatz 									 uint32 flags /* currently B_FLAVOR_IS_GLOBAL or B_FLAVOR_IS_LOCAL */ )
160152a38012Sejakowatz {
160252a38012Sejakowatz 	CALLED();
160352a38012Sejakowatz 	if ((flags & (B_FLAVOR_IS_GLOBAL | B_FLAVOR_IS_LOCAL)) == 0) {
1604618b1338Sbeveloper 		FATAL("Error: BMediaRoster::InstantiateDormantNode called without valid flags\n");
160552a38012Sejakowatz 		return B_BAD_VALUE;
160652a38012Sejakowatz 	}
160752a38012Sejakowatz 	if (out_node == 0)
160852a38012Sejakowatz 		return B_BAD_VALUE;
160952a38012Sejakowatz 
161052a38012Sejakowatz 	// XXX we should not trust the values passed in by the user,
161152a38012Sejakowatz 	// XXX and ask the server to determine where to insta
161252a38012Sejakowatz 
1613e0207628Sbeveloper 
1614e0207628Sbeveloper // XXX SOMETHING IS VERY WRONG HERE
1615e0207628Sbeveloper //	if ((in_info.flavor_flags & B_FLAVOR_IS_GLOBAL) == 0 && (flags & B_FLAVOR_IS_LOCAL)) {
1616e0207628Sbeveloper 	if (flags & B_FLAVOR_IS_LOCAL) {
161752a38012Sejakowatz 		return InstantiateDormantNode(in_info,out_node);
161852a38012Sejakowatz 	}
161952a38012Sejakowatz 
1620e0207628Sbeveloper // XXX SOMETHING IS VERY WRONG HERE
1621e0207628Sbeveloper //	if ((in_info.flavor_flags & B_FLAVOR_IS_GLOBAL) || (flags & B_FLAVOR_IS_GLOBAL)) {
1622e0207628Sbeveloper 	if (flags & B_FLAVOR_IS_GLOBAL) {
162352a38012Sejakowatz 		// forward this request into the media_addon_server,
162452a38012Sejakowatz 		// which in turn will call InstantiateDormantNode()
162552a38012Sejakowatz 		// to create it there localy
16268c6a6096Sbeveloper 		addonserver_instantiate_dormant_node_request request;
16278c6a6096Sbeveloper 		addonserver_instantiate_dormant_node_reply reply;
162852a38012Sejakowatz 		status_t rv;
1629f4925104Sbeveloper 
1630f4925104Sbeveloper 		request.info = in_info;
1631f4925104Sbeveloper 		rv = QueryAddonServer(ADDONSERVER_INSTANTIATE_DORMANT_NODE, &request, sizeof(request), &reply, sizeof(reply));
1632f4925104Sbeveloper 		if (rv == B_OK) {
163352a38012Sejakowatz 			*out_node = reply.node;
1634f4925104Sbeveloper 		}
1635f4925104Sbeveloper 		return rv;
163652a38012Sejakowatz 	}
163752a38012Sejakowatz 
1638e0207628Sbeveloper // XXX SOMETHING IS VERY WRONG HERE
1639618b1338Sbeveloper 	FATAL("Error: BMediaRoster::InstantiateDormantNode addon_id %d, flavor_id %d, flags %#08lx\n", (int)in_info.addon, (int)in_info.flavor_id, flags);
164052a38012Sejakowatz 
164152a38012Sejakowatz 	return B_ERROR;
164252a38012Sejakowatz }
164352a38012Sejakowatz 
164452a38012Sejakowatz 
164552a38012Sejakowatz status_t
164652a38012Sejakowatz BMediaRoster::InstantiateDormantNode(const dormant_node_info & in_info,
164752a38012Sejakowatz 									 media_node * out_node)
164852a38012Sejakowatz {
164916b7eea4Sbeveloper 	CALLED();
165052a38012Sejakowatz 
165152a38012Sejakowatz 	// to instantiate a dormant node in the current address space, we need to
165252a38012Sejakowatz 	// either load the add-on from file and create a new BMediaAddOn class, or
165352a38012Sejakowatz 	// reuse the cached BMediaAddOn from a previous call
165452a38012Sejakowatz 	// call BMediaAddOn::InstantiateNodeFor()
165552a38012Sejakowatz 	// and cache the BMediaAddOn after that for later reuse.
165652a38012Sejakowatz 	// BeOS R5 does not seem to delete it when the application quits
165752a38012Sejakowatz 	// if B_FLAVOR_IS_GLOBAL, we need to use the BMediaAddOn object that
165852a38012Sejakowatz 	// resides in the media_addon_server
165952a38012Sejakowatz 
166052a38012Sejakowatz 	// RegisterNode() is called automatically for nodes instantiated from add-ons
166152a38012Sejakowatz 
166216b7eea4Sbeveloper 	//XXX TEST!
166316b7eea4Sbeveloper 	BMediaAddOn *addon;
166416b7eea4Sbeveloper 	BMediaNode *node;
166516b7eea4Sbeveloper 	BMessage config;
166616b7eea4Sbeveloper 	status_t out_error;
16678c6a6096Sbeveloper 	status_t rv;
166816b7eea4Sbeveloper 	addon = _DormantNodeManager->GetAddon(in_info.addon);
166916b7eea4Sbeveloper 	if (!addon) {
1670618b1338Sbeveloper 		FATAL("BMediaRoster::InstantiateDormantNode: GetAddon failed\n");
167152a38012Sejakowatz 		return B_ERROR;
167252a38012Sejakowatz 	}
16731299bfb2Sbeveloper 	flavor_info temp; // XXX fix this!
16741299bfb2Sbeveloper 	temp.name = "XXX flavor_info name";
16751299bfb2Sbeveloper 	temp.info = "XXX flavor_info info";
167616b7eea4Sbeveloper 	temp.internal_id = in_info.flavor_id;
167716b7eea4Sbeveloper 	node = addon->InstantiateNodeFor(&temp, &config, &out_error);
167816b7eea4Sbeveloper 	if (!node) {
1679618b1338Sbeveloper 		FATAL("BMediaRoster::InstantiateDormantNode: InstantiateNodeFor failed\n");
168016b7eea4Sbeveloper 		_DormantNodeManager->PutAddon(in_info.addon);
168116b7eea4Sbeveloper 		return B_ERROR;
168216b7eea4Sbeveloper 	}
16838c6a6096Sbeveloper 	rv = RegisterNode(node);
16848c6a6096Sbeveloper 	if (rv != B_OK) {
1685618b1338Sbeveloper 		FATAL("BMediaRoster::InstantiateDormantNode: RegisterNode failed\n");
16868c6a6096Sbeveloper 		delete node;
16878c6a6096Sbeveloper 		_DormantNodeManager->PutAddon(in_info.addon);
16888c6a6096Sbeveloper 		return B_ERROR;
16898c6a6096Sbeveloper 	}
16908c6a6096Sbeveloper 
16918c6a6096Sbeveloper 	// XXX we must remember in_info.addon and call
16928c6a6096Sbeveloper 	// XXX _DormantNodeManager->PutAddon when the
16938c6a6096Sbeveloper 	// XXX node is unregistered
16949e9417d2Sbeveloper 	// should be handled by RegisterNode() and UnegisterNode() now
16958c6a6096Sbeveloper 
169616b7eea4Sbeveloper 	*out_node = node->Node();
169716b7eea4Sbeveloper 	return B_OK;
169816b7eea4Sbeveloper }
169952a38012Sejakowatz 
170052a38012Sejakowatz 
170152a38012Sejakowatz status_t
170252a38012Sejakowatz BMediaRoster::GetDormantNodeFor(const media_node & node,
170352a38012Sejakowatz 								dormant_node_info * out_info)
170452a38012Sejakowatz {
170585dfab2bSbeveloper 	CALLED();
170685dfab2bSbeveloper 	if (out_info == NULL)
170785dfab2bSbeveloper 		return B_BAD_VALUE;
170885dfab2bSbeveloper 	if (node.node <= 0)
170985dfab2bSbeveloper 		return B_MEDIA_BAD_NODE;
171052a38012Sejakowatz 
171185dfab2bSbeveloper 	server_get_dormant_node_for_request request;
171285dfab2bSbeveloper 	server_get_dormant_node_for_reply reply;
171385dfab2bSbeveloper 	status_t rv;
171485dfab2bSbeveloper 
171585dfab2bSbeveloper 	request.node = node;
171685dfab2bSbeveloper 
17171299bfb2Sbeveloper 	rv = QueryServer(SERVER_GET_DORMANT_NODE_FOR, &request, sizeof(request), &reply, sizeof(reply));
171885dfab2bSbeveloper 	if (rv != B_OK)
171985dfab2bSbeveloper 		return rv;
172085dfab2bSbeveloper 
172185dfab2bSbeveloper 	*out_info = reply.node_info;
172285dfab2bSbeveloper 	return B_OK;
172352a38012Sejakowatz }
172452a38012Sejakowatz 
172552a38012Sejakowatz 
172652a38012Sejakowatz status_t
172752a38012Sejakowatz BMediaRoster::GetDormantFlavorInfoFor(const dormant_node_info & in_dormant,
172852a38012Sejakowatz 									  dormant_flavor_info * out_flavor)
172952a38012Sejakowatz {
173052a38012Sejakowatz 	CALLED();
173152a38012Sejakowatz 
173252a38012Sejakowatz 	xfer_server_get_dormant_flavor_info msg;
173352a38012Sejakowatz 	xfer_server_get_dormant_flavor_info_reply *reply;
173452a38012Sejakowatz 	port_id port;
173552a38012Sejakowatz 	status_t rv;
173652a38012Sejakowatz 	int32 code;
173752a38012Sejakowatz 
173852a38012Sejakowatz 	port = find_port("media_server port");
173952a38012Sejakowatz 	if (port <= B_OK)
174052a38012Sejakowatz 		return B_ERROR;
174152a38012Sejakowatz 
174252a38012Sejakowatz 	reply = (xfer_server_get_dormant_flavor_info_reply *) malloc(16000);
174352a38012Sejakowatz 	if (reply == 0)
174452a38012Sejakowatz 		return B_ERROR;
174552a38012Sejakowatz 
174652a38012Sejakowatz 	msg.addon 		= in_dormant.addon;
174752a38012Sejakowatz 	msg.flavor_id 	= in_dormant.flavor_id;
174852a38012Sejakowatz 	msg.reply_port 	= _PortPool->GetPort();
174952a38012Sejakowatz 	rv = write_port(port, SERVER_GET_DORMANT_FLAVOR_INFO, &msg, sizeof(msg));
175052a38012Sejakowatz 	if (rv != B_OK) {
175152a38012Sejakowatz 		free(reply);
175252a38012Sejakowatz 		_PortPool->PutPort(msg.reply_port);
175352a38012Sejakowatz 		return rv;
175452a38012Sejakowatz 	}
175552a38012Sejakowatz 	rv = read_port(msg.reply_port, &code, reply, 16000);
175652a38012Sejakowatz 	_PortPool->PutPort(msg.reply_port);
175752a38012Sejakowatz 
175852a38012Sejakowatz 	if (rv < B_OK) {
175952a38012Sejakowatz 		free(reply);
176052a38012Sejakowatz 		return rv;
176152a38012Sejakowatz 	}
176252a38012Sejakowatz 
176352a38012Sejakowatz 	if (reply->result == B_OK)
176452a38012Sejakowatz 		rv = out_flavor->Unflatten(reply->dfi_type, &reply->dfi, reply->dfi_size);
176552a38012Sejakowatz 	else
176652a38012Sejakowatz 		rv = reply->result;
176752a38012Sejakowatz 
176852a38012Sejakowatz 	free(reply);
176952a38012Sejakowatz 	return rv;
177052a38012Sejakowatz }
177152a38012Sejakowatz 
177252a38012Sejakowatz 
177352a38012Sejakowatz status_t
177452a38012Sejakowatz BMediaRoster::GetLatencyFor(const media_node & producer,
177552a38012Sejakowatz 							bigtime_t * out_latency)
177652a38012Sejakowatz {
177752a38012Sejakowatz 	UNIMPLEMENTED();
1778*0e21b167Sbeveloper 	*out_latency = 2000;
1779aac800c2Sbeveloper 	return B_OK;
178052a38012Sejakowatz }
178152a38012Sejakowatz 
178252a38012Sejakowatz 
178352a38012Sejakowatz status_t
178452a38012Sejakowatz BMediaRoster::GetInitialLatencyFor(const media_node & producer,
178552a38012Sejakowatz 								   bigtime_t * out_latency,
1786aac800c2Sbeveloper 								   uint32 * out_flags /* = NULL */)
178752a38012Sejakowatz {
178852a38012Sejakowatz 	UNIMPLEMENTED();
1789*0e21b167Sbeveloper 	*out_latency = 1000;
1790aac800c2Sbeveloper 	if (out_flags)
179152a38012Sejakowatz 		*out_flags = 0;
1792aac800c2Sbeveloper 	return B_OK;
179352a38012Sejakowatz }
179452a38012Sejakowatz 
179552a38012Sejakowatz 
179652a38012Sejakowatz status_t
179752a38012Sejakowatz BMediaRoster::GetStartLatencyFor(const media_node & time_source,
179852a38012Sejakowatz 								 bigtime_t * out_latency)
179952a38012Sejakowatz {
180052a38012Sejakowatz 	UNIMPLEMENTED();
1801aac800c2Sbeveloper 	*out_latency = 5000;
1802aac800c2Sbeveloper 	return B_OK;
180352a38012Sejakowatz }
180452a38012Sejakowatz 
180552a38012Sejakowatz 
180652a38012Sejakowatz status_t
180752a38012Sejakowatz BMediaRoster::GetFileFormatsFor(const media_node & file_interface,
180852a38012Sejakowatz 								media_file_format * out_formats,
180952a38012Sejakowatz 								int32 * io_num_infos)
181052a38012Sejakowatz {
181152a38012Sejakowatz 	UNIMPLEMENTED();
181252a38012Sejakowatz 	return B_ERROR;
181352a38012Sejakowatz }
181452a38012Sejakowatz 
181552a38012Sejakowatz 
181652a38012Sejakowatz status_t
181752a38012Sejakowatz BMediaRoster::SetRefFor(const media_node & file_interface,
181852a38012Sejakowatz 						const entry_ref & file,
181952a38012Sejakowatz 						bool create_and_truncate,
182052a38012Sejakowatz 						bigtime_t * out_length)	/* if create is false */
182152a38012Sejakowatz {
182252a38012Sejakowatz 	UNIMPLEMENTED();
182352a38012Sejakowatz 	return B_ERROR;
182452a38012Sejakowatz }
182552a38012Sejakowatz 
182652a38012Sejakowatz 
182752a38012Sejakowatz status_t
182852a38012Sejakowatz BMediaRoster::GetRefFor(const media_node & node,
182952a38012Sejakowatz 						entry_ref * out_file,
183052a38012Sejakowatz 						BMimeType * mime_type)
183152a38012Sejakowatz {
183252a38012Sejakowatz 	UNIMPLEMENTED();
183352a38012Sejakowatz 	return B_ERROR;
183452a38012Sejakowatz }
183552a38012Sejakowatz 
183652a38012Sejakowatz 
183752a38012Sejakowatz status_t
183852a38012Sejakowatz BMediaRoster::SniffRefFor(const media_node & file_interface,
183952a38012Sejakowatz 						  const entry_ref & file,
184052a38012Sejakowatz 						  BMimeType * mime_type,
184152a38012Sejakowatz 						  float * out_capability)
184252a38012Sejakowatz {
184352a38012Sejakowatz 	UNIMPLEMENTED();
184452a38012Sejakowatz 	return B_ERROR;
184552a38012Sejakowatz }
184652a38012Sejakowatz 
184752a38012Sejakowatz 
184852a38012Sejakowatz /* This is the generic "here's a file, now can someone please play it" interface */
184952a38012Sejakowatz status_t
185052a38012Sejakowatz BMediaRoster::SniffRef(const entry_ref & file,
185152a38012Sejakowatz 					   uint64 require_node_kinds,		/* if you need an EntityInterface or BufferConsumer or something */
185252a38012Sejakowatz 					   dormant_node_info * out_node,
185352a38012Sejakowatz 					   BMimeType * mime_type)
185452a38012Sejakowatz {
185552a38012Sejakowatz 	UNIMPLEMENTED();
185652a38012Sejakowatz 	return B_ERROR;
185752a38012Sejakowatz }
185852a38012Sejakowatz 
185952a38012Sejakowatz 
186052a38012Sejakowatz status_t
186152a38012Sejakowatz BMediaRoster::GetDormantNodeForType(const BMimeType & type,
186252a38012Sejakowatz 									uint64 require_node_kinds,
186352a38012Sejakowatz 									dormant_node_info * out_node)
186452a38012Sejakowatz {
186552a38012Sejakowatz 	UNIMPLEMENTED();
186652a38012Sejakowatz 	return B_ERROR;
186752a38012Sejakowatz }
186852a38012Sejakowatz 
186952a38012Sejakowatz 
187052a38012Sejakowatz status_t
187152a38012Sejakowatz BMediaRoster::GetReadFileFormatsFor(const dormant_node_info & in_node,
187252a38012Sejakowatz 									media_file_format * out_read_formats,
187352a38012Sejakowatz 									int32 in_read_count,
187452a38012Sejakowatz 									int32 * out_read_count)
187552a38012Sejakowatz {
187652a38012Sejakowatz 	UNIMPLEMENTED();
187752a38012Sejakowatz 	return B_ERROR;
187852a38012Sejakowatz }
187952a38012Sejakowatz 
188052a38012Sejakowatz 
188152a38012Sejakowatz status_t
188252a38012Sejakowatz BMediaRoster::GetWriteFileFormatsFor(const dormant_node_info & in_node,
188352a38012Sejakowatz 									 media_file_format * out_write_formats,
188452a38012Sejakowatz 									 int32 in_write_count,
188552a38012Sejakowatz 									 int32 * out_write_count)
188652a38012Sejakowatz {
188752a38012Sejakowatz 	UNIMPLEMENTED();
188852a38012Sejakowatz 	return B_ERROR;
188952a38012Sejakowatz }
189052a38012Sejakowatz 
189152a38012Sejakowatz 
189252a38012Sejakowatz status_t
189352a38012Sejakowatz BMediaRoster::GetFormatFor(const media_output & output,
189452a38012Sejakowatz 						   media_format * io_format,
189552a38012Sejakowatz 						   uint32 flags)
189652a38012Sejakowatz {
189752a38012Sejakowatz 	UNIMPLEMENTED();
189852a38012Sejakowatz 	return B_ERROR;
189952a38012Sejakowatz }
190052a38012Sejakowatz 
190152a38012Sejakowatz 
190252a38012Sejakowatz status_t
190352a38012Sejakowatz BMediaRoster::GetFormatFor(const media_input & input,
190452a38012Sejakowatz 						   media_format * io_format,
190552a38012Sejakowatz 						   uint32 flags)
190652a38012Sejakowatz {
190752a38012Sejakowatz 	UNIMPLEMENTED();
190852a38012Sejakowatz 	return B_ERROR;
190952a38012Sejakowatz }
191052a38012Sejakowatz 
191152a38012Sejakowatz 
191252a38012Sejakowatz status_t
191352a38012Sejakowatz BMediaRoster::GetFormatFor(const media_node & node,
191452a38012Sejakowatz 						   media_format * io_format,
191552a38012Sejakowatz 						   float quality)
191652a38012Sejakowatz {
191752a38012Sejakowatz 	UNIMPLEMENTED();
191852a38012Sejakowatz 	return B_ERROR;
191952a38012Sejakowatz }
192052a38012Sejakowatz 
192152a38012Sejakowatz 
192252a38012Sejakowatz ssize_t
192352a38012Sejakowatz BMediaRoster::GetNodeAttributesFor(const media_node & node,
192452a38012Sejakowatz 								   media_node_attribute * outArray,
192552a38012Sejakowatz 								   size_t inMaxCount)
192652a38012Sejakowatz {
192752a38012Sejakowatz 	UNIMPLEMENTED();
192852a38012Sejakowatz 	return B_ERROR;
192952a38012Sejakowatz }
193052a38012Sejakowatz 
193152a38012Sejakowatz 
193252a38012Sejakowatz media_node_id
193352a38012Sejakowatz BMediaRoster::NodeIDFor(port_id source_or_destination_port)
193452a38012Sejakowatz {
19359e9417d2Sbeveloper 	CALLED();
19369e9417d2Sbeveloper 
19379e9417d2Sbeveloper 	server_node_id_for_request request;
19389e9417d2Sbeveloper 	server_node_id_for_reply reply;
19399e9417d2Sbeveloper 	status_t rv;
19409e9417d2Sbeveloper 
19419e9417d2Sbeveloper 	request.port = source_or_destination_port;
19429e9417d2Sbeveloper 
19439e9417d2Sbeveloper 	rv = QueryServer(SERVER_NODE_ID_FOR, &request, sizeof(request), &reply, sizeof(reply));
19449e9417d2Sbeveloper 	if (rv != B_OK) {
1945353b9f6bSbeveloper 		FATAL("BMediaRoster::NodeIDFor: failed (error %#lx)\n", rv);
19469e9417d2Sbeveloper 		return -1;
19479e9417d2Sbeveloper 	}
19489e9417d2Sbeveloper 
19499e9417d2Sbeveloper 	return reply.nodeid;
195052a38012Sejakowatz }
195152a38012Sejakowatz 
195252a38012Sejakowatz 
195352a38012Sejakowatz status_t
195452a38012Sejakowatz BMediaRoster::GetInstancesFor(media_addon_id addon,
195552a38012Sejakowatz 							  int32 flavor,
195652a38012Sejakowatz 							  media_node_id * out_id,
195752a38012Sejakowatz 							  int32 * io_count)
195852a38012Sejakowatz {
195985dfab2bSbeveloper 	CALLED();
196085dfab2bSbeveloper 	if (out_id == NULL || io_count == NULL)
196185dfab2bSbeveloper 		return B_BAD_VALUE;
196285dfab2bSbeveloper 	if (*io_count <= 0)
196385dfab2bSbeveloper 		return B_BAD_VALUE;
196485dfab2bSbeveloper 
196585dfab2bSbeveloper 	server_get_instances_for_request request;
196685dfab2bSbeveloper 	server_get_instances_for_reply reply;
196785dfab2bSbeveloper 	status_t rv;
196885dfab2bSbeveloper 
196985dfab2bSbeveloper 	request.maxcount = *io_count;
197085dfab2bSbeveloper 	request.addon_id = addon;
197185dfab2bSbeveloper 	request.addon_flavor_id = flavor;
197285dfab2bSbeveloper 
197385dfab2bSbeveloper 	rv = QueryServer(SERVER_GET_INSTANCES_FOR, &request, sizeof(request), &reply, sizeof(reply));
197485dfab2bSbeveloper 	if (rv != B_OK) {
1975353b9f6bSbeveloper 		FATAL("BMediaRoster::GetLiveNodes failed\n");
197685dfab2bSbeveloper 		return rv;
197752a38012Sejakowatz 	}
197852a38012Sejakowatz 
197985dfab2bSbeveloper 	*io_count = reply.count;
198085dfab2bSbeveloper 	if (reply.count > 0)
198185dfab2bSbeveloper 		memcpy(out_id, reply.node_id, sizeof(media_node_id) * reply.count);
198285dfab2bSbeveloper 
198385dfab2bSbeveloper 	return B_OK;
198485dfab2bSbeveloper }
198552a38012Sejakowatz 
198652a38012Sejakowatz 
198752a38012Sejakowatz status_t
198852a38012Sejakowatz BMediaRoster::SetRealtimeFlags(uint32 in_enabled)
198952a38012Sejakowatz {
199052a38012Sejakowatz 	UNIMPLEMENTED();
199152a38012Sejakowatz 	return B_ERROR;
199252a38012Sejakowatz }
199352a38012Sejakowatz 
199452a38012Sejakowatz 
199552a38012Sejakowatz status_t
199652a38012Sejakowatz BMediaRoster::GetRealtimeFlags(uint32 * out_enabled)
199752a38012Sejakowatz {
199852a38012Sejakowatz 	UNIMPLEMENTED();
199952a38012Sejakowatz 	return B_ERROR;
200052a38012Sejakowatz }
200152a38012Sejakowatz 
200252a38012Sejakowatz 
200352a38012Sejakowatz ssize_t
200452a38012Sejakowatz BMediaRoster::AudioBufferSizeFor(int32 channel_count,
200552a38012Sejakowatz 								 uint32 sample_format,
200652a38012Sejakowatz 								 float frame_rate,
200752a38012Sejakowatz 								 bus_type bus_kind)
200852a38012Sejakowatz {
200952a38012Sejakowatz 	UNIMPLEMENTED();
201052a38012Sejakowatz 	return 4096;
201152a38012Sejakowatz }
201252a38012Sejakowatz 
201352a38012Sejakowatz 
201452a38012Sejakowatz /* Use MediaFlags to inquire about specific features of the Media Kit. */
201552a38012Sejakowatz /* Returns < 0 for "not present", positive size for output data size. */
201652a38012Sejakowatz /* 0 means that the capability is present, but no data about it. */
201752a38012Sejakowatz /* static */ ssize_t
201852a38012Sejakowatz BMediaRoster::MediaFlags(media_flags cap,
201952a38012Sejakowatz 						 void * buf,
202052a38012Sejakowatz 						 size_t maxSize)
202152a38012Sejakowatz {
202252a38012Sejakowatz 	UNIMPLEMENTED();
202352a38012Sejakowatz 	return 0;
202452a38012Sejakowatz }
202552a38012Sejakowatz 
202652a38012Sejakowatz 
202752a38012Sejakowatz /* BLooper overrides */
202852a38012Sejakowatz /* virtual */ void
202952a38012Sejakowatz BMediaRoster::MessageReceived(BMessage * message)
203052a38012Sejakowatz {
20316396865dSbeveloper 	// media_server plays ping-pong with the BMediaRosters
20326396865dSbeveloper 	// to detect dead teams. Normal communication uses ports.
20336396865dSbeveloper 	static BMessage pong('PONG');
20346396865dSbeveloper 	if (message->what == 'PING') {
20356396865dSbeveloper 		message->SendReply(&pong, static_cast<BHandler *>(NULL), 2000000);
20366396865dSbeveloper 		return;
20376396865dSbeveloper 	}
20386396865dSbeveloper 
20396396865dSbeveloper 	printf("BMediaRoster::MessageReceived: unknown message!\n");
20406396865dSbeveloper 	message->PrintToStream();
204152a38012Sejakowatz }
204252a38012Sejakowatz 
204352a38012Sejakowatz /* virtual */ bool
204452a38012Sejakowatz BMediaRoster::QuitRequested()
204552a38012Sejakowatz {
204652a38012Sejakowatz 	UNIMPLEMENTED();
204752a38012Sejakowatz 	return true;
204852a38012Sejakowatz }
204952a38012Sejakowatz 
205052a38012Sejakowatz /* virtual */ BHandler *
205152a38012Sejakowatz BMediaRoster::ResolveSpecifier(BMessage *msg,
205252a38012Sejakowatz 				 int32 index,
205352a38012Sejakowatz 				 BMessage *specifier,
205452a38012Sejakowatz 				 int32 form,
205552a38012Sejakowatz 				 const char *property)
205652a38012Sejakowatz {
205752a38012Sejakowatz 	UNIMPLEMENTED();
205852a38012Sejakowatz 	return 0;
205952a38012Sejakowatz }
206052a38012Sejakowatz 
206152a38012Sejakowatz 
206252a38012Sejakowatz /* virtual */ status_t
206352a38012Sejakowatz BMediaRoster::GetSupportedSuites(BMessage *data)
206452a38012Sejakowatz {
206552a38012Sejakowatz 	UNIMPLEMENTED();
206652a38012Sejakowatz 	return B_ERROR;
206752a38012Sejakowatz }
206852a38012Sejakowatz 
206952a38012Sejakowatz 
207052a38012Sejakowatz BMediaRoster::~BMediaRoster()
207152a38012Sejakowatz {
207252a38012Sejakowatz 	CALLED();
20736396865dSbeveloper 
20746396865dSbeveloper 	// unregister this application with the media server
20756396865dSbeveloper 	server_unregister_app_request request;
20766396865dSbeveloper 	server_unregister_app_reply reply;
20776396865dSbeveloper 	request.team = team;
20786396865dSbeveloper 	QueryServer(SERVER_UNREGISTER_APP, &request, sizeof(request), &reply, sizeof(reply));
207952a38012Sejakowatz }
208052a38012Sejakowatz 
208152a38012Sejakowatz 
208252a38012Sejakowatz /*************************************************************
208352a38012Sejakowatz  * private BMediaRoster
208452a38012Sejakowatz  *************************************************************/
208552a38012Sejakowatz 
208652a38012Sejakowatz // deprecated call
208752a38012Sejakowatz status_t
208852a38012Sejakowatz BMediaRoster::SetOutputBuffersFor(const media_source & output,
208952a38012Sejakowatz 								  BBufferGroup * group,
209052a38012Sejakowatz 								  bool will_reclaim )
209152a38012Sejakowatz {
209252a38012Sejakowatz 	UNIMPLEMENTED();
20939e9417d2Sbeveloper 	debugger("BMediaRoster::SetOutputBuffersFor missing\n");
209452a38012Sejakowatz 	return B_ERROR;
209552a38012Sejakowatz }
209652a38012Sejakowatz 
209752a38012Sejakowatz 
209852a38012Sejakowatz /* FBC stuffing (Mmmh, Stuffing!) */
209952a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_0(void *) { return B_ERROR; }
210052a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_1(void *) { return B_ERROR; }
210152a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_2(void *) { return B_ERROR; }
210252a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_3(void *) { return B_ERROR; }
210352a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_4(void *) { return B_ERROR; }
210452a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_5(void *) { return B_ERROR; }
210552a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_6(void *) { return B_ERROR; }
210652a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_7(void *) { return B_ERROR; }
210752a38012Sejakowatz 
210852a38012Sejakowatz 
210952a38012Sejakowatz BMediaRoster::BMediaRoster() :
21106396865dSbeveloper 	BLooper("_BMediaRoster_", B_URGENT_DISPLAY_PRIORITY, B_LOOPER_PORT_DEFAULT_CAPACITY)
211152a38012Sejakowatz {
211252a38012Sejakowatz 	CALLED();
21136396865dSbeveloper 
21146396865dSbeveloper 	// start the looper
21156396865dSbeveloper 	Run();
21166396865dSbeveloper 
21176396865dSbeveloper 	// register this application with the media server
21186396865dSbeveloper 	server_register_app_request request;
21196396865dSbeveloper 	server_register_app_reply reply;
21206396865dSbeveloper 	request.team = team;
21216396865dSbeveloper 	request.messenger = BMessenger(NULL, this);
21226396865dSbeveloper 	QueryServer(SERVER_REGISTER_APP, &request, sizeof(request), &reply, sizeof(reply));
212352a38012Sejakowatz }
212452a38012Sejakowatz 
21256396865dSbeveloper 
212652a38012Sejakowatz /* static */ status_t
212752a38012Sejakowatz BMediaRoster::ParseCommand(BMessage & reply)
212852a38012Sejakowatz {
212952a38012Sejakowatz 	UNIMPLEMENTED();
213052a38012Sejakowatz 	return B_ERROR;
213152a38012Sejakowatz }
213252a38012Sejakowatz 
213352a38012Sejakowatz 
213452a38012Sejakowatz status_t
213552a38012Sejakowatz BMediaRoster::GetDefaultInfo(media_node_id for_default,
213652a38012Sejakowatz 							 BMessage & out_config)
213752a38012Sejakowatz {
213852a38012Sejakowatz 	UNIMPLEMENTED();
213952a38012Sejakowatz 	return B_ERROR;
214052a38012Sejakowatz }
214152a38012Sejakowatz 
214252a38012Sejakowatz 
214352a38012Sejakowatz 
214452a38012Sejakowatz status_t
214552a38012Sejakowatz BMediaRoster::SetRunningDefault(media_node_id for_default,
214652a38012Sejakowatz 								const media_node & node)
214752a38012Sejakowatz {
214852a38012Sejakowatz 	UNIMPLEMENTED();
214952a38012Sejakowatz 	return B_ERROR;
215052a38012Sejakowatz }
215152a38012Sejakowatz 
215252a38012Sejakowatz 
215352a38012Sejakowatz /*************************************************************
215452a38012Sejakowatz  * static BMediaRoster variables
215552a38012Sejakowatz  *************************************************************/
215652a38012Sejakowatz 
215752a38012Sejakowatz bool BMediaRoster::_isMediaServer;
215852a38012Sejakowatz port_id BMediaRoster::_mReplyPort;
215952a38012Sejakowatz int32 BMediaRoster::_mReplyPortRes;
216052a38012Sejakowatz int32 BMediaRoster::_mReplyPortUnavailCount;
216152a38012Sejakowatz BMediaRoster * BMediaRoster::_sDefault = NULL;
216252a38012Sejakowatz 
2163