xref: /haiku/src/kits/media/MediaRoster.cpp (revision fc8b28b6e12d86de8fb9f07ac4fe9ed4ebe2698c)
1255a01c7Sbeveloper /*
2255a01c7Sbeveloper  * Copyright (c) 2002, 2003 Marcus Overhagen <Marcus@Overhagen.de>
3255a01c7Sbeveloper  *
4255a01c7Sbeveloper  * Permission is hereby granted, free of charge, to any person obtaining
5255a01c7Sbeveloper  * a copy of this software and associated documentation files or portions
6255a01c7Sbeveloper  * thereof (the "Software"), to deal in the Software without restriction,
7255a01c7Sbeveloper  * including without limitation the rights to use, copy, modify, merge,
8255a01c7Sbeveloper  * publish, distribute, sublicense, and/or sell copies of the Software,
9255a01c7Sbeveloper  * and to permit persons to whom the Software is furnished to do so, subject
10255a01c7Sbeveloper  * to the following conditions:
11255a01c7Sbeveloper  *
12255a01c7Sbeveloper  *  * Redistributions of source code must retain the above copyright notice,
13255a01c7Sbeveloper  *    this list of conditions and the following disclaimer.
14255a01c7Sbeveloper  *
15255a01c7Sbeveloper  *  * Redistributions in binary form must reproduce the above copyright notice
16255a01c7Sbeveloper  *    in the  binary, as well as this list of conditions and the following
17255a01c7Sbeveloper  *    disclaimer in the documentation and/or other materials provided with
18255a01c7Sbeveloper  *    the distribution.
19255a01c7Sbeveloper  *
20255a01c7Sbeveloper  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
21255a01c7Sbeveloper  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22255a01c7Sbeveloper  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
23255a01c7Sbeveloper  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24255a01c7Sbeveloper  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25255a01c7Sbeveloper  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
26255a01c7Sbeveloper  * THE SOFTWARE.
27255a01c7Sbeveloper  *
28255a01c7Sbeveloper  */
29255a01c7Sbeveloper 
30255a01c7Sbeveloper /* to comply with the license above, do not remove the following line */
31d91580cdSbeveloper char __dont_remove_copyright_from_binary[] = "Copyright (c) 2002, 2003 Marcus Overhagen <Marcus@Overhagen.de>";
32255a01c7Sbeveloper 
3352a38012Sejakowatz #include <MediaRoster.h>
3452a38012Sejakowatz #include <Locker.h>
3552a38012Sejakowatz #include <Message.h>
3652a38012Sejakowatz #include <Messenger.h>
3752a38012Sejakowatz #include <StopWatch.h>
3852a38012Sejakowatz #include <OS.h>
3952a38012Sejakowatz #include <String.h>
4052a38012Sejakowatz #include <TimeSource.h>
4160f15390Sbeveloper #include <ParameterWeb.h>
424d2d96e0Sbeveloper #include <BufferProducer.h>
434d2d96e0Sbeveloper #include <BufferConsumer.h>
4452a38012Sejakowatz #include "debug.h"
458b04ffc1Sbeveloper #include "MediaRosterEx.h"
4640f36b03Sbeveloper #include "MediaMisc.h"
4752a38012Sejakowatz #include "PortPool.h"
480a483e72SIngo Weinhold #include "ServerInterface.h"
49f4925104Sbeveloper #include "DataExchange.h"
5016b7eea4Sbeveloper #include "DormantNodeManager.h"
51f4925104Sbeveloper #include "Notifications.h"
52835140c8Sbeveloper #include "TimeSourceObjectManager.h"
5352a38012Sejakowatz 
54f4925104Sbeveloper namespace BPrivate { namespace media {
5552a38012Sejakowatz 
5652a38012Sejakowatz 	// the BMediaRoster destructor is private,
5752a38012Sejakowatz 	// but _DefaultDeleter is a friend class of
5852a38012Sejakowatz 	// the BMediaRoster an thus can delete it
598b04ffc1Sbeveloper 	class DefaultDeleter
6052a38012Sejakowatz 	{
6152a38012Sejakowatz 	public:
628b04ffc1Sbeveloper 		~DefaultDeleter()
636396865dSbeveloper 		{
646396865dSbeveloper 			if (BMediaRoster::_sDefault) {
656396865dSbeveloper 				BMediaRoster::_sDefault->Lock();
666396865dSbeveloper 				BMediaRoster::_sDefault->Quit();
676396865dSbeveloper 			}
686396865dSbeveloper 		}
698b04ffc1Sbeveloper 	};
7052a38012Sejakowatz 
718b04ffc1Sbeveloper } } // BPrivate::media
728b04ffc1Sbeveloper using namespace BPrivate::media;
7352a38012Sejakowatz 
748b04ffc1Sbeveloper // DefaultDeleter will delete the BMediaRoster object in it's destructor.
758b04ffc1Sbeveloper DefaultDeleter _deleter;
7652a38012Sejakowatz 
773620737cSbeveloper status_t
7854187cc6Sbeveloper BMediaRosterEx::SaveNodeConfiguration(BMediaNode *node)
7954187cc6Sbeveloper {
8054187cc6Sbeveloper 	BMediaAddOn *addon;
8154187cc6Sbeveloper 	media_addon_id addonid;
8254187cc6Sbeveloper 	int32 flavorid;
8354187cc6Sbeveloper 	addon = node->AddOn(&flavorid);
8454187cc6Sbeveloper 	if (!addon) {
8560f15390Sbeveloper 		// XXX this check incorrectly triggers on BeOS R5 BT848 node
865ac4fbd7Sbeveloper 		ERROR("BMediaRosterEx::SaveNodeConfiguration node %ld not instantiated from BMediaAddOn!\n", node->ID());
8754187cc6Sbeveloper 		return B_ERROR;
8854187cc6Sbeveloper 	}
8954187cc6Sbeveloper 	addonid = addon->AddonID();
9054187cc6Sbeveloper 
9154187cc6Sbeveloper 	// XXX fix this
9254187cc6Sbeveloper 	printf("### BMediaRosterEx::SaveNodeConfiguration should save addon-id %ld, flavor-id %ld config NOW!\n", addonid, flavorid);
9354187cc6Sbeveloper 	return B_OK;
9454187cc6Sbeveloper }
9554187cc6Sbeveloper 
9654187cc6Sbeveloper status_t
9754187cc6Sbeveloper BMediaRosterEx::LoadNodeConfiguration(media_addon_id addonid, int32 flavorid, BMessage *out_msg)
9854187cc6Sbeveloper {
9954187cc6Sbeveloper 	// XXX fix this
10054187cc6Sbeveloper 	out_msg->MakeEmpty(); // to be fully R5 compliant
10154187cc6Sbeveloper 	printf("### BMediaRosterEx::LoadNodeConfiguration should load addon-id %ld, flavor-id %ld config NOW!\n", addonid, flavorid);
10254187cc6Sbeveloper 	return B_OK;
10354187cc6Sbeveloper }
10454187cc6Sbeveloper 
10554187cc6Sbeveloper status_t
10673794717Sbeveloper BMediaRosterEx::IncrementAddonFlavorInstancesCount(media_addon_id addonid, int32 flavorid)
10754187cc6Sbeveloper {
10873794717Sbeveloper 	server_change_addon_flavor_instances_count_request request;
10973794717Sbeveloper 	server_change_addon_flavor_instances_count_reply reply;
11073794717Sbeveloper 
11173794717Sbeveloper 	request.addonid = addonid;
11273794717Sbeveloper 	request.flavorid = flavorid;
11373794717Sbeveloper 	request.delta = 1;
11473794717Sbeveloper 	request.team = team;
11573794717Sbeveloper 	return QueryServer(SERVER_CHANGE_ADDON_FLAVOR_INSTANCES_COUNT, &request, sizeof(request), &reply, sizeof(reply));
11654187cc6Sbeveloper }
11754187cc6Sbeveloper 
11854187cc6Sbeveloper status_t
11973794717Sbeveloper BMediaRosterEx::DecrementAddonFlavorInstancesCount(media_addon_id addonid, int32 flavorid)
12054187cc6Sbeveloper {
12173794717Sbeveloper 	server_change_addon_flavor_instances_count_request request;
12273794717Sbeveloper 	server_change_addon_flavor_instances_count_reply reply;
12373794717Sbeveloper 
12473794717Sbeveloper 	request.addonid = addonid;
12573794717Sbeveloper 	request.flavorid = flavorid;
12673794717Sbeveloper 	request.delta = -1;
12773794717Sbeveloper 	request.team = team;
12873794717Sbeveloper 	return QueryServer(SERVER_CHANGE_ADDON_FLAVOR_INSTANCES_COUNT, &request, sizeof(request), &reply, sizeof(reply));
12954187cc6Sbeveloper }
13054187cc6Sbeveloper 
13154187cc6Sbeveloper status_t
13254187cc6Sbeveloper BMediaRosterEx::SetNodeCreator(media_node_id node, team_id creator)
13354187cc6Sbeveloper {
13454187cc6Sbeveloper 	server_set_node_creator_request request;
13554187cc6Sbeveloper 	server_set_node_creator_reply reply;
13654187cc6Sbeveloper 
13754187cc6Sbeveloper 	request.node = node;
13854187cc6Sbeveloper 	request.creator = creator;
13954187cc6Sbeveloper 	return QueryServer(SERVER_SET_NODE_CREATOR, &request, sizeof(request), &reply, sizeof(reply));
14054187cc6Sbeveloper }
14154187cc6Sbeveloper 
14254187cc6Sbeveloper status_t
1438b04ffc1Sbeveloper BMediaRosterEx::GetNode(node_type type, media_node * out_node, int32 * out_input_id, BString * out_input_name)
14452a38012Sejakowatz {
14552a38012Sejakowatz 	if (out_node == NULL)
14652a38012Sejakowatz 		return B_BAD_VALUE;
14752a38012Sejakowatz 
1488c6a6096Sbeveloper 	server_get_node_request request;
1498c6a6096Sbeveloper 	server_get_node_reply reply;
15052a38012Sejakowatz 	status_t rv;
15152a38012Sejakowatz 
1528c6a6096Sbeveloper 	request.type = type;
1539e9417d2Sbeveloper 	request.team = team;
1548c6a6096Sbeveloper 	rv = QueryServer(SERVER_GET_NODE, &request, sizeof(request), &reply, sizeof(reply));
1558c6a6096Sbeveloper 	if (rv != B_OK)
1568c6a6096Sbeveloper 		return rv;
15752a38012Sejakowatz 
15852a38012Sejakowatz 	*out_node = reply.node;
15952a38012Sejakowatz 	if (out_input_id)
16052a38012Sejakowatz 		*out_input_id = reply.input_id;
16152a38012Sejakowatz 	if (out_input_name)
16252a38012Sejakowatz 		*out_input_name = reply.input_name;
1638c6a6096Sbeveloper 	return rv;
16452a38012Sejakowatz }
16552a38012Sejakowatz 
1663620737cSbeveloper status_t
1678b04ffc1Sbeveloper BMediaRosterEx::SetNode(node_type type, const media_node *node, const dormant_node_info *info, const media_input *input)
16852a38012Sejakowatz {
1698c6a6096Sbeveloper 	server_set_node_request request;
1708c6a6096Sbeveloper 	server_set_node_reply reply;
17152a38012Sejakowatz 
1728c6a6096Sbeveloper 	request.type = type;
1738c6a6096Sbeveloper 	request.use_node = node ? true : false;
17452a38012Sejakowatz 	if (node)
1758c6a6096Sbeveloper 		request.node = *node;
1768c6a6096Sbeveloper 	request.use_dni = info ? true : false;
17752a38012Sejakowatz 	if (info)
1788c6a6096Sbeveloper 		request.dni = *info;
1798c6a6096Sbeveloper 	request.use_input = input ? true : false;
18052a38012Sejakowatz 	if (input)
1818c6a6096Sbeveloper 		request.input = *input;
18252a38012Sejakowatz 
1838c6a6096Sbeveloper 	return QueryServer(SERVER_SET_NODE, &request, sizeof(request), &reply, sizeof(reply));
18452a38012Sejakowatz }
18552a38012Sejakowatz 
1863620737cSbeveloper status_t
1878b04ffc1Sbeveloper BMediaRosterEx::GetAllOutputs(const media_node & node, List<media_output> *list)
1883620737cSbeveloper {
1893620737cSbeveloper 	int32 cookie;
1903620737cSbeveloper 	status_t rv;
1913620737cSbeveloper 	status_t result;
1923620737cSbeveloper 
1935ac4fbd7Sbeveloper 	PRINT(4, "BMediaRosterEx::GetAllOutputs() node %ld, port %ld\n", node.node, node.port);
1945ac4fbd7Sbeveloper 
1953620737cSbeveloper 	result = B_OK;
1963620737cSbeveloper 	cookie = 0;
19776669a29Sbeveloper 	list->MakeEmpty();
1983620737cSbeveloper 	for (;;) {
1993620737cSbeveloper 		producer_get_next_output_request request;
2003620737cSbeveloper 		producer_get_next_output_reply reply;
2013620737cSbeveloper 		request.cookie = cookie;
2020caff283Sbeveloper 		rv = QueryPort(node.port, PRODUCER_GET_NEXT_OUTPUT, &request, sizeof(request), &reply, sizeof(reply));
2033620737cSbeveloper 		if (rv != B_OK)
2043620737cSbeveloper 			break;
2053620737cSbeveloper 		cookie = reply.cookie;
20676669a29Sbeveloper 		if (!list->Insert(reply.output)) {
2075ac4fbd7Sbeveloper 			ERROR("GetAllOutputs: list->Insert failed\n");
2083620737cSbeveloper 			result = B_ERROR;
2093620737cSbeveloper 		}
2105ac4fbd7Sbeveloper 		#if DEBUG >= 3
2115ac4fbd7Sbeveloper 			PRINT(3," next cookie %ld, ", cookie);
2125ac4fbd7Sbeveloper 			PRINT_OUTPUT("output ", reply.output);
2135ac4fbd7Sbeveloper 		#endif
2143620737cSbeveloper 	}
2153620737cSbeveloper 
2163620737cSbeveloper 	producer_dispose_output_cookie_request request;
2173620737cSbeveloper 	producer_dispose_output_cookie_reply reply;
2180caff283Sbeveloper 	QueryPort(node.port, PRODUCER_DISPOSE_OUTPUT_COOKIE, &request, sizeof(request), &reply, sizeof(reply));
2193620737cSbeveloper 
2203620737cSbeveloper 	return result;
2213620737cSbeveloper }
2223620737cSbeveloper 
2233620737cSbeveloper status_t
2244d2d96e0Sbeveloper BMediaRosterEx::GetAllOutputs(BBufferProducer *node, List<media_output> *list)
2254d2d96e0Sbeveloper {
2264d2d96e0Sbeveloper 	int32 cookie;
2274d2d96e0Sbeveloper 	status_t result;
2284d2d96e0Sbeveloper 
2294d2d96e0Sbeveloper 	PRINT(4, "BMediaRosterEx::GetAllOutputs() (by pointer) node %ld, port %ld\n", node->ID(), node->ControlPort());
2304d2d96e0Sbeveloper 
2314d2d96e0Sbeveloper 	result = B_OK;
2324d2d96e0Sbeveloper 	cookie = 0;
2334d2d96e0Sbeveloper 	list->MakeEmpty();
2344d2d96e0Sbeveloper 	for (;;) {
2354d2d96e0Sbeveloper 		media_output output;
2364d2d96e0Sbeveloper 		if (B_OK != node->GetNextOutput(&cookie, &output))
2374d2d96e0Sbeveloper 			break;
2384d2d96e0Sbeveloper 		if (!list->Insert(output)) {
2394d2d96e0Sbeveloper 			ERROR("GetAllOutputs: list->Insert failed\n");
2404d2d96e0Sbeveloper 			result = B_ERROR;
2414d2d96e0Sbeveloper 		}
2424d2d96e0Sbeveloper 		#if DEBUG >= 3
2434d2d96e0Sbeveloper 			PRINT(3," next cookie %ld, ", cookie);
2444d2d96e0Sbeveloper 			PRINT_OUTPUT("output ", output);
2454d2d96e0Sbeveloper 		#endif
2464d2d96e0Sbeveloper 	}
2474d2d96e0Sbeveloper 	node->DisposeOutputCookie(cookie);
2484d2d96e0Sbeveloper 	return result;
2494d2d96e0Sbeveloper }
2504d2d96e0Sbeveloper 
2514d2d96e0Sbeveloper status_t
2528b04ffc1Sbeveloper BMediaRosterEx::GetAllInputs(const media_node & node, List<media_input> *list)
2533620737cSbeveloper {
2543620737cSbeveloper 	int32 cookie;
2553620737cSbeveloper 	status_t rv;
2563620737cSbeveloper 	status_t result;
2573620737cSbeveloper 
2585ac4fbd7Sbeveloper 	PRINT(4, "BMediaRosterEx::GetAllInputs() node %ld, port %ld\n", node.node, node.port);
2595ac4fbd7Sbeveloper 
2603620737cSbeveloper 	result = B_OK;
2613620737cSbeveloper 	cookie = 0;
26276669a29Sbeveloper 	list->MakeEmpty();
2633620737cSbeveloper 	for (;;) {
2643620737cSbeveloper 		consumer_get_next_input_request request;
2653620737cSbeveloper 		consumer_get_next_input_reply reply;
2663620737cSbeveloper 		request.cookie = cookie;
2670caff283Sbeveloper 		rv = QueryPort(node.port, CONSUMER_GET_NEXT_INPUT, &request, sizeof(request), &reply, sizeof(reply));
2683620737cSbeveloper 		if (rv != B_OK)
2693620737cSbeveloper 			break;
2703620737cSbeveloper 		cookie = reply.cookie;
27176669a29Sbeveloper 		if (!list->Insert(reply.input)) {
2725ac4fbd7Sbeveloper 			ERROR("GetAllInputs: list->Insert failed\n");
2733620737cSbeveloper 			result = B_ERROR;
2743620737cSbeveloper 		}
2755ac4fbd7Sbeveloper 		#if DEBUG >= 3
2765ac4fbd7Sbeveloper 			PRINT(3," next cookie %ld, ", cookie);
2775ac4fbd7Sbeveloper 			PRINT_OUTPUT("input ", reply.input);
2785ac4fbd7Sbeveloper 		#endif
2793620737cSbeveloper 	}
2803620737cSbeveloper 
2813620737cSbeveloper 	consumer_dispose_input_cookie_request request;
2823620737cSbeveloper 	consumer_dispose_input_cookie_reply reply;
2830caff283Sbeveloper 	QueryPort(node.port, CONSUMER_DISPOSE_INPUT_COOKIE, &request, sizeof(request), &reply, sizeof(reply));
2843620737cSbeveloper 
2853620737cSbeveloper 	return result;
2863620737cSbeveloper }
2873620737cSbeveloper 
2883620737cSbeveloper status_t
2894d2d96e0Sbeveloper BMediaRosterEx::GetAllInputs(BBufferConsumer *node, List<media_input> *list)
2904d2d96e0Sbeveloper {
2914d2d96e0Sbeveloper 	int32 cookie;
2924d2d96e0Sbeveloper 	status_t result;
2934d2d96e0Sbeveloper 
2944d2d96e0Sbeveloper 	PRINT(4, "BMediaRosterEx::GetAllInputs() (by pointer) node %ld, port %ld\n", node->ID(), node->ControlPort());
2954d2d96e0Sbeveloper 
2964d2d96e0Sbeveloper 	result = B_OK;
2974d2d96e0Sbeveloper 	cookie = 0;
2984d2d96e0Sbeveloper 	list->MakeEmpty();
2994d2d96e0Sbeveloper 	for (;;) {
3004d2d96e0Sbeveloper 		media_input input;
3014d2d96e0Sbeveloper 		if (B_OK != node->GetNextInput(&cookie, &input))
3024d2d96e0Sbeveloper 			break;
3034d2d96e0Sbeveloper 		if (!list->Insert(input)) {
3044d2d96e0Sbeveloper 			ERROR("GetAllInputs: list->Insert failed\n");
3054d2d96e0Sbeveloper 			result = B_ERROR;
3064d2d96e0Sbeveloper 		}
3074d2d96e0Sbeveloper 		#if DEBUG >= 3
3084d2d96e0Sbeveloper 			PRINT(3," next cookie %ld, ", cookie);
3094d2d96e0Sbeveloper 			PRINT_INPUT("input ", input);
3104d2d96e0Sbeveloper 		#endif
3114d2d96e0Sbeveloper 	}
3124d2d96e0Sbeveloper 	node->DisposeInputCookie(cookie);
3134d2d96e0Sbeveloper 	return result;
3144d2d96e0Sbeveloper }
3154d2d96e0Sbeveloper 
3164d2d96e0Sbeveloper status_t
3178b04ffc1Sbeveloper BMediaRosterEx::PublishOutputs(const media_node & node, List<media_output> *list)
3183620737cSbeveloper {
3193620737cSbeveloper 	server_publish_outputs_request request;
3203620737cSbeveloper 	server_publish_outputs_reply reply;
3213620737cSbeveloper 	media_output *output;
3223620737cSbeveloper 	media_output *outputs;
3233620737cSbeveloper 	int32 count;
324a7b41a96Sbeveloper 	status_t rv;
3253620737cSbeveloper 
32676669a29Sbeveloper 	count = list->CountItems();
3273620737cSbeveloper 	TRACE("PublishOutputs: publishing %ld\n", count);
3283620737cSbeveloper 
3293620737cSbeveloper 	request.node = node;
3303620737cSbeveloper 	request.count = count;
3313620737cSbeveloper 	if (count > MAX_OUTPUTS) {
3323620737cSbeveloper 		void *start_addr;
3333620737cSbeveloper 		size_t size;
33440f36b03Sbeveloper 		size = ROUND_UP_TO_PAGE(count * sizeof(media_output));
3353620737cSbeveloper 		request.area = create_area("publish outputs", &start_addr, B_ANY_ADDRESS, size, B_NO_LOCK, B_READ_AREA | B_WRITE_AREA);
3363620737cSbeveloper 		if (request.area < B_OK) {
3375ac4fbd7Sbeveloper 			ERROR("PublishOutputs: failed to create area, %#lx\n", request.area);
3383620737cSbeveloper 			return (status_t)request.area;
3393620737cSbeveloper 		}
3403620737cSbeveloper 		outputs = static_cast<media_output *>(start_addr);
3413620737cSbeveloper 	} else {
3423620737cSbeveloper 		request.area = -1;
3433620737cSbeveloper 		outputs = request.outputs;
3443620737cSbeveloper 	}
34576669a29Sbeveloper 	TRACE("PublishOutputs: area %ld\n", request.area);
3463620737cSbeveloper 
34776669a29Sbeveloper 	int i;
34876669a29Sbeveloper 	for (i = 0, list->Rewind(); list->GetNext(&output); i++) {
34976669a29Sbeveloper 		ASSERT(i < count);
3503620737cSbeveloper 		outputs[i] = *output;
3513620737cSbeveloper 	}
3523620737cSbeveloper 
353a7b41a96Sbeveloper 	rv = QueryServer(SERVER_PUBLISH_OUTPUTS, &request, sizeof(request), &reply, sizeof(reply));
354a7b41a96Sbeveloper 
355a7b41a96Sbeveloper 	if (request.area != -1)
356a7b41a96Sbeveloper 		delete_area(request.area);
357a7b41a96Sbeveloper 
358a7b41a96Sbeveloper 	return rv;
3593620737cSbeveloper }
3603620737cSbeveloper 
3613620737cSbeveloper status_t
3628b04ffc1Sbeveloper BMediaRosterEx::PublishInputs(const media_node & node, List<media_input> *list)
3633620737cSbeveloper {
3643620737cSbeveloper 	server_publish_inputs_request request;
3653620737cSbeveloper 	server_publish_inputs_reply reply;
3663620737cSbeveloper 	media_input *input;
3673620737cSbeveloper 	media_input *inputs;
3683620737cSbeveloper 	int32 count;
369a7b41a96Sbeveloper 	status_t rv;
3703620737cSbeveloper 
37176669a29Sbeveloper 	count = list->CountItems();
3723620737cSbeveloper 	TRACE("PublishInputs: publishing %ld\n", count);
3733620737cSbeveloper 
3743620737cSbeveloper 	request.node = node;
3753620737cSbeveloper 	request.count = count;
3763620737cSbeveloper 	if (count > MAX_INPUTS) {
3773620737cSbeveloper 		void *start_addr;
3783620737cSbeveloper 		size_t size;
37940f36b03Sbeveloper 		size = ROUND_UP_TO_PAGE(count * sizeof(media_input));
3803620737cSbeveloper 		request.area = create_area("publish inputs", &start_addr, B_ANY_ADDRESS, size, B_NO_LOCK, B_READ_AREA | B_WRITE_AREA);
3813620737cSbeveloper 		if (request.area < B_OK) {
3825ac4fbd7Sbeveloper 			ERROR("PublishInputs: failed to create area, %#lx\n", request.area);
3833620737cSbeveloper 			return (status_t)request.area;
3843620737cSbeveloper 		}
3853620737cSbeveloper 		inputs = static_cast<media_input *>(start_addr);
3863620737cSbeveloper 	} else {
3873620737cSbeveloper 		request.area = -1;
3883620737cSbeveloper 		inputs = request.inputs;
3893620737cSbeveloper 	}
39076669a29Sbeveloper 	TRACE("PublishInputs: area %ld\n", request.area);
3913620737cSbeveloper 
39276669a29Sbeveloper 	int i;
39376669a29Sbeveloper 	for (i = 0, list->Rewind(); list->GetNext(&input); i++) {
39476669a29Sbeveloper 		ASSERT(i < count);
3953620737cSbeveloper 		inputs[i] = *input;
3963620737cSbeveloper 	}
3973620737cSbeveloper 
398a7b41a96Sbeveloper 	rv = QueryServer(SERVER_PUBLISH_INPUTS, &request, sizeof(request), &reply, sizeof(reply));
399a7b41a96Sbeveloper 
400a7b41a96Sbeveloper 	if (request.area != -1)
401a7b41a96Sbeveloper 		delete_area(request.area);
402a7b41a96Sbeveloper 
403a7b41a96Sbeveloper 	return rv;
4043620737cSbeveloper }
4053620737cSbeveloper 
40652a38012Sejakowatz /*************************************************************
40752a38012Sejakowatz  * public BMediaRoster
40852a38012Sejakowatz  *************************************************************/
40952a38012Sejakowatz 
41052a38012Sejakowatz status_t
41152a38012Sejakowatz BMediaRoster::GetVideoInput(media_node * out_node)
41252a38012Sejakowatz {
41352a38012Sejakowatz 	CALLED();
4148b04ffc1Sbeveloper 	return MediaRosterEx(this)->GetNode(VIDEO_INPUT, out_node);
41552a38012Sejakowatz }
41652a38012Sejakowatz 
41752a38012Sejakowatz 
41852a38012Sejakowatz status_t
41952a38012Sejakowatz BMediaRoster::GetAudioInput(media_node * out_node)
42052a38012Sejakowatz {
42152a38012Sejakowatz 	CALLED();
4228b04ffc1Sbeveloper 	return MediaRosterEx(this)->GetNode(AUDIO_INPUT, out_node);
42352a38012Sejakowatz }
42452a38012Sejakowatz 
42552a38012Sejakowatz 
42652a38012Sejakowatz status_t
42752a38012Sejakowatz BMediaRoster::GetVideoOutput(media_node * out_node)
42852a38012Sejakowatz {
42952a38012Sejakowatz 	CALLED();
4308b04ffc1Sbeveloper 	return MediaRosterEx(this)->GetNode(VIDEO_OUTPUT, out_node);
43152a38012Sejakowatz }
43252a38012Sejakowatz 
43352a38012Sejakowatz 
43452a38012Sejakowatz status_t
43552a38012Sejakowatz BMediaRoster::GetAudioMixer(media_node * out_node)
43652a38012Sejakowatz {
43752a38012Sejakowatz 	CALLED();
4388b04ffc1Sbeveloper 	return MediaRosterEx(this)->GetNode(AUDIO_MIXER, out_node);
43952a38012Sejakowatz }
44052a38012Sejakowatz 
44152a38012Sejakowatz 
44252a38012Sejakowatz status_t
44352a38012Sejakowatz BMediaRoster::GetAudioOutput(media_node * out_node)
44452a38012Sejakowatz {
44552a38012Sejakowatz 	CALLED();
4468b04ffc1Sbeveloper 	return MediaRosterEx(this)->GetNode(AUDIO_OUTPUT, out_node);
44752a38012Sejakowatz }
44852a38012Sejakowatz 
44952a38012Sejakowatz 
45052a38012Sejakowatz status_t
45152a38012Sejakowatz BMediaRoster::GetAudioOutput(media_node * out_node,
45252a38012Sejakowatz 							 int32 * out_input_id,
45352a38012Sejakowatz 							 BString * out_input_name)
45452a38012Sejakowatz {
45552a38012Sejakowatz 	CALLED();
4568b04ffc1Sbeveloper 	return MediaRosterEx(this)->GetNode(AUDIO_OUTPUT_EX, out_node, out_input_id, out_input_name);
45752a38012Sejakowatz }
45852a38012Sejakowatz 
45952a38012Sejakowatz 
46052a38012Sejakowatz status_t
46152a38012Sejakowatz BMediaRoster::GetTimeSource(media_node * out_node)
46252a38012Sejakowatz {
46352a38012Sejakowatz 	CALLED();
46486bce45bSbeveloper 	status_t rv;
46586bce45bSbeveloper 
46686bce45bSbeveloper 	// XXX need to do this in a nicer way.
46786bce45bSbeveloper 
46886bce45bSbeveloper 	rv = MediaRosterEx(this)->GetNode(TIME_SOURCE, out_node);
46986bce45bSbeveloper 	if (rv != B_OK)
47086bce45bSbeveloper 		return rv;
47186bce45bSbeveloper 
47286bce45bSbeveloper 	// We don't do reference counting for timesources, that's why we
47386bce45bSbeveloper 	// release the node immediately.
47486bce45bSbeveloper 	ReleaseNode(*out_node);
47586bce45bSbeveloper 
47686bce45bSbeveloper 	// we need to remember to not use this node with server side reference counting
47786bce45bSbeveloper 	out_node->kind |= NODE_KIND_NO_REFCOUNTING;
47886bce45bSbeveloper 
47986bce45bSbeveloper 	return B_OK;
48052a38012Sejakowatz }
48152a38012Sejakowatz 
48252a38012Sejakowatz 
48352a38012Sejakowatz status_t
48452a38012Sejakowatz BMediaRoster::SetVideoInput(const media_node & producer)
48552a38012Sejakowatz {
48652a38012Sejakowatz 	CALLED();
4878b04ffc1Sbeveloper 	return MediaRosterEx(this)->SetNode(VIDEO_INPUT, &producer);
48852a38012Sejakowatz }
48952a38012Sejakowatz 
49052a38012Sejakowatz 
49152a38012Sejakowatz status_t
49252a38012Sejakowatz BMediaRoster::SetVideoInput(const dormant_node_info & producer)
49352a38012Sejakowatz {
49452a38012Sejakowatz 	CALLED();
4958b04ffc1Sbeveloper 	return MediaRosterEx(this)->SetNode(VIDEO_INPUT, NULL, &producer);
49652a38012Sejakowatz }
49752a38012Sejakowatz 
49852a38012Sejakowatz 
49952a38012Sejakowatz status_t
50052a38012Sejakowatz BMediaRoster::SetAudioInput(const media_node & producer)
50152a38012Sejakowatz {
50252a38012Sejakowatz 	CALLED();
5038b04ffc1Sbeveloper 	return MediaRosterEx(this)->SetNode(AUDIO_INPUT, &producer);
50452a38012Sejakowatz }
50552a38012Sejakowatz 
50652a38012Sejakowatz 
50752a38012Sejakowatz status_t
50852a38012Sejakowatz BMediaRoster::SetAudioInput(const dormant_node_info & producer)
50952a38012Sejakowatz {
51052a38012Sejakowatz 	CALLED();
5118b04ffc1Sbeveloper 	return MediaRosterEx(this)->SetNode(AUDIO_INPUT, NULL, &producer);
51252a38012Sejakowatz }
51352a38012Sejakowatz 
51452a38012Sejakowatz 
51552a38012Sejakowatz status_t
51652a38012Sejakowatz BMediaRoster::SetVideoOutput(const media_node & consumer)
51752a38012Sejakowatz {
51852a38012Sejakowatz 	CALLED();
5198b04ffc1Sbeveloper 	return MediaRosterEx(this)->SetNode(VIDEO_OUTPUT, &consumer);
52052a38012Sejakowatz }
52152a38012Sejakowatz 
52252a38012Sejakowatz 
52352a38012Sejakowatz status_t
52452a38012Sejakowatz BMediaRoster::SetVideoOutput(const dormant_node_info & consumer)
52552a38012Sejakowatz {
52652a38012Sejakowatz 	CALLED();
5278b04ffc1Sbeveloper 	return MediaRosterEx(this)->SetNode(VIDEO_OUTPUT, NULL, &consumer);
52852a38012Sejakowatz }
52952a38012Sejakowatz 
53052a38012Sejakowatz 
53152a38012Sejakowatz status_t
53252a38012Sejakowatz BMediaRoster::SetAudioOutput(const media_node & consumer)
53352a38012Sejakowatz {
53452a38012Sejakowatz 	CALLED();
5358b04ffc1Sbeveloper 	return MediaRosterEx(this)->SetNode(AUDIO_OUTPUT, &consumer);
53652a38012Sejakowatz }
53752a38012Sejakowatz 
53852a38012Sejakowatz 
53952a38012Sejakowatz status_t
54052a38012Sejakowatz BMediaRoster::SetAudioOutput(const media_input & input_to_output)
54152a38012Sejakowatz {
54252a38012Sejakowatz 	CALLED();
5438b04ffc1Sbeveloper 	return MediaRosterEx(this)->SetNode(AUDIO_OUTPUT, NULL, NULL, &input_to_output);
54452a38012Sejakowatz }
54552a38012Sejakowatz 
54652a38012Sejakowatz 
54752a38012Sejakowatz status_t
54852a38012Sejakowatz BMediaRoster::SetAudioOutput(const dormant_node_info & consumer)
54952a38012Sejakowatz {
55052a38012Sejakowatz 	CALLED();
5518b04ffc1Sbeveloper 	return MediaRosterEx(this)->SetNode(AUDIO_OUTPUT, NULL, &consumer);
55252a38012Sejakowatz }
55352a38012Sejakowatz 
55452a38012Sejakowatz 
55552a38012Sejakowatz status_t
55652a38012Sejakowatz BMediaRoster::GetNodeFor(media_node_id node,
55752a38012Sejakowatz 						 media_node * clone)
55852a38012Sejakowatz {
5599e9417d2Sbeveloper 	CALLED();
5609e9417d2Sbeveloper 	if (clone == NULL)
5619e9417d2Sbeveloper 		return B_BAD_VALUE;
5629e9417d2Sbeveloper 	if (node <= 0)
5639e9417d2Sbeveloper 		return B_MEDIA_BAD_NODE;
5649e9417d2Sbeveloper 
5659e9417d2Sbeveloper 	server_get_node_for_request request;
5669e9417d2Sbeveloper 	server_get_node_for_reply reply;
5679e9417d2Sbeveloper 	status_t rv;
5689e9417d2Sbeveloper 
5699e9417d2Sbeveloper 	request.nodeid = node;
5709e9417d2Sbeveloper 	request.team = team;
5719e9417d2Sbeveloper 
5729e9417d2Sbeveloper 	rv = QueryServer(SERVER_GET_NODE_FOR, &request, sizeof(request), &reply, sizeof(reply));
5739e9417d2Sbeveloper 	if (rv != B_OK)
5749e9417d2Sbeveloper 		return rv;
5759e9417d2Sbeveloper 
5769e9417d2Sbeveloper 	*clone = reply.clone;
5779e9417d2Sbeveloper 	return B_OK;
57852a38012Sejakowatz }
57952a38012Sejakowatz 
58052a38012Sejakowatz 
58152a38012Sejakowatz status_t
58252a38012Sejakowatz BMediaRoster::GetSystemTimeSource(media_node * clone)
58352a38012Sejakowatz {
58452a38012Sejakowatz 	CALLED();
58586bce45bSbeveloper 	status_t rv;
58686bce45bSbeveloper 
58786bce45bSbeveloper 	// XXX need to do this in a nicer way.
58886bce45bSbeveloper 
58986bce45bSbeveloper 	rv = MediaRosterEx(this)->GetNode(SYSTEM_TIME_SOURCE, clone);
59086bce45bSbeveloper 	if (rv != B_OK)
59186bce45bSbeveloper 		return rv;
59286bce45bSbeveloper 
59386bce45bSbeveloper 	// We don't do reference counting for timesources, that's why we
59486bce45bSbeveloper 	// release the node immediately.
59586bce45bSbeveloper 	ReleaseNode(*clone);
59686bce45bSbeveloper 
59786bce45bSbeveloper 	// we need to remember to not use this node with server side reference counting
59886bce45bSbeveloper 	clone->kind |= NODE_KIND_NO_REFCOUNTING;
59986bce45bSbeveloper 
60086bce45bSbeveloper 	return B_OK;
60152a38012Sejakowatz }
60252a38012Sejakowatz 
60352a38012Sejakowatz 
60452a38012Sejakowatz status_t
60552a38012Sejakowatz BMediaRoster::ReleaseNode(const media_node & node)
60652a38012Sejakowatz {
6079e9417d2Sbeveloper 	CALLED();
60840f36b03Sbeveloper 	if (IS_INVALID_NODE(node))
6099e9417d2Sbeveloper 		return B_MEDIA_BAD_NODE;
61052a38012Sejakowatz 
61186bce45bSbeveloper 	if (node.kind & NODE_KIND_NO_REFCOUNTING) {
61286bce45bSbeveloper 		printf("BMediaRoster::ReleaseNode, trying to release reference counting disabled timesource, node %ld, port %ld, team %ld\n", node.node, node.port, team);
61386bce45bSbeveloper 		return B_OK;
61486bce45bSbeveloper 	}
61586bce45bSbeveloper 
6169e9417d2Sbeveloper 	server_release_node_request request;
6179e9417d2Sbeveloper 	server_release_node_reply reply;
618cf4e2277Sbeveloper 	status_t rv;
6199e9417d2Sbeveloper 
6209e9417d2Sbeveloper 	request.node = node;
6219e9417d2Sbeveloper 	request.team = team;
6229e9417d2Sbeveloper 
62360f15390Sbeveloper 	TRACE("BMediaRoster::ReleaseNode, node %ld, port %ld, team %ld\n", node.node, node.port, team);
624cf4e2277Sbeveloper 
625cf4e2277Sbeveloper 	rv = QueryServer(SERVER_RELEASE_NODE, &request, sizeof(request), &reply, sizeof(reply));
626cf4e2277Sbeveloper 	if (rv != B_OK) {
6275ac4fbd7Sbeveloper 		ERROR("BMediaRoster::ReleaseNode FAILED, node %ld, port %ld, team %ld!\n", node.node, node.port, team);
628cf4e2277Sbeveloper 	}
629cf4e2277Sbeveloper 	return rv;
6309e9417d2Sbeveloper }
63152a38012Sejakowatz 
63252a38012Sejakowatz BTimeSource *
63352a38012Sejakowatz BMediaRoster::MakeTimeSourceFor(const media_node & for_node)
63452a38012Sejakowatz {
635f180ef79Sbeveloper 	// MakeTimeSourceFor() returns a BTimeSource object
636f180ef79Sbeveloper 	// corresponding to the specified node's time source.
637f180ef79Sbeveloper 
638835140c8Sbeveloper 	CALLED();
639f180ef79Sbeveloper 
64092e575c1Sbeveloper 	if (IS_SYSTEM_TIMESOURCE(for_node)) {
641f180ef79Sbeveloper 		// special handling for the system time source
642f180ef79Sbeveloper 		TRACE("BMediaRoster::MakeTimeSourceFor, asked for system time source\n");
643f180ef79Sbeveloper 		return MediaRosterEx(this)->MakeTimeSourceObject(NODE_SYSTEM_TIMESOURCE_ID);
644f180ef79Sbeveloper 	}
645f180ef79Sbeveloper 
6465917dd5bSbeveloper 	if (IS_INVALID_NODE(for_node)) {
6475ac4fbd7Sbeveloper 		ERROR("BMediaRoster::MakeTimeSourceFor: for_node invalid, node %ld, port %ld, kinds 0x%lx\n", for_node.node, for_node.port, for_node.kind);
6485917dd5bSbeveloper 		return NULL;
6490e21b167Sbeveloper 	}
6500e21b167Sbeveloper 
651f180ef79Sbeveloper 	TRACE("BMediaRoster::MakeTimeSourceFor: node %ld enter\n", for_node.node);
6525917dd5bSbeveloper 
6535917dd5bSbeveloper 	node_get_timesource_request request;
6545917dd5bSbeveloper 	node_get_timesource_reply reply;
6555917dd5bSbeveloper 	BTimeSource *source;
6565917dd5bSbeveloper 	status_t rv;
6575917dd5bSbeveloper 
65892e575c1Sbeveloper 	// ask the node to get it's current timesource id
6595917dd5bSbeveloper 	rv = QueryPort(for_node.port, NODE_GET_TIMESOURCE, &request, sizeof(request), &reply, sizeof(reply));
6605917dd5bSbeveloper 	if (rv != B_OK) {
6615ac4fbd7Sbeveloper 		ERROR("BMediaRoster::MakeTimeSourceFor: request failed\n");
6625917dd5bSbeveloper 		return NULL;
6635917dd5bSbeveloper 	}
6645917dd5bSbeveloper 
6655917dd5bSbeveloper 	source = MediaRosterEx(this)->MakeTimeSourceObject(reply.timesource_id);
6665917dd5bSbeveloper 
667f180ef79Sbeveloper 	TRACE("BMediaRoster::MakeTimeSourceFor: node %ld leave\n", for_node.node);
6685917dd5bSbeveloper 
6695917dd5bSbeveloper 	return source;
6705917dd5bSbeveloper }
6715917dd5bSbeveloper 
6725917dd5bSbeveloper BTimeSource *
6735917dd5bSbeveloper BMediaRosterEx::MakeTimeSourceObject(media_node_id timesource_id)
6745917dd5bSbeveloper {
6755917dd5bSbeveloper 	BTimeSource *source;
6765917dd5bSbeveloper 	media_node clone;
6775917dd5bSbeveloper 	status_t rv;
6785917dd5bSbeveloper 
6795917dd5bSbeveloper 	rv = GetNodeFor(timesource_id, &clone);
6805917dd5bSbeveloper 	if (rv != B_OK) {
6815ac4fbd7Sbeveloper 		ERROR("BMediaRosterEx::MakeTimeSourceObject: GetNodeFor failed\n");
6825917dd5bSbeveloper 		return NULL;
6835917dd5bSbeveloper 	}
6845917dd5bSbeveloper 
6855917dd5bSbeveloper 	source = _TimeSourceObjectManager->GetTimeSource(clone);
6865917dd5bSbeveloper 	if (source == NULL) {
6875ac4fbd7Sbeveloper 		ERROR("BMediaRosterEx::MakeTimeSourceObject: GetTimeSource failed\n");
6885917dd5bSbeveloper 		return NULL;
6895917dd5bSbeveloper 	}
6905917dd5bSbeveloper 
69192e575c1Sbeveloper 	// XXX release?
69292e575c1Sbeveloper 	ReleaseNode(clone);
693287f7492Sbeveloper 
694835140c8Sbeveloper 	return source;
69552a38012Sejakowatz }
69652a38012Sejakowatz 
69752a38012Sejakowatz 
69852a38012Sejakowatz status_t
69952a38012Sejakowatz BMediaRoster::Connect(const media_source & from,
70052a38012Sejakowatz 					  const media_destination & to,
70152a38012Sejakowatz 					  media_format * io_format,
70252a38012Sejakowatz 					  media_output * out_output,
70352a38012Sejakowatz 					  media_input * out_input)
70452a38012Sejakowatz {
705eae26d3dSbeveloper 	return BMediaRoster::Connect(from, to, io_format, out_output, out_input, 0);
706eae26d3dSbeveloper }
707eae26d3dSbeveloper 
708eae26d3dSbeveloper 
709eae26d3dSbeveloper status_t
710eae26d3dSbeveloper BMediaRoster::Connect(const media_source & from,
711eae26d3dSbeveloper 					  const media_destination & to,
712eae26d3dSbeveloper 					  media_format * io_format,
713eae26d3dSbeveloper 					  media_output * out_output,
714eae26d3dSbeveloper 					  media_input * out_input,
715eae26d3dSbeveloper 					  uint32 in_flags,
716eae26d3dSbeveloper 					  void * _reserved)
717eae26d3dSbeveloper {
71852a38012Sejakowatz 	CALLED();
71952a38012Sejakowatz 	if (io_format == NULL || out_output == NULL || out_input == NULL)
72052a38012Sejakowatz 		return B_BAD_VALUE;
72140f36b03Sbeveloper 	if (IS_INVALID_SOURCE(from)) {
7225ac4fbd7Sbeveloper 		ERROR("BMediaRoster::Connect: media_source invalid\n");
72352a38012Sejakowatz 		return B_MEDIA_BAD_SOURCE;
7249e9417d2Sbeveloper 	}
72540f36b03Sbeveloper 	if (IS_INVALID_DESTINATION(to)) {
7265ac4fbd7Sbeveloper 		ERROR("BMediaRoster::Connect: media_destination invalid\n");
72752a38012Sejakowatz 		return B_MEDIA_BAD_DESTINATION;
7289e9417d2Sbeveloper 	}
72952a38012Sejakowatz 
73052a38012Sejakowatz 	status_t rv;
7318c6a6096Sbeveloper 	producer_format_proposal_request request1;
7328c6a6096Sbeveloper 	producer_format_proposal_reply reply1;
73352a38012Sejakowatz 
73469983609Sbeveloper 	PRINT_FORMAT("BMediaRoster::Connect calling BBufferProducer::FormatProposal with format  ", *io_format);
73569983609Sbeveloper 
73652a38012Sejakowatz 	// BBufferProducer::FormatProposal
7378c6a6096Sbeveloper 	request1.output = from;
7388c6a6096Sbeveloper 	request1.format = *io_format;
7398c6a6096Sbeveloper 	rv = QueryPort(from.port, PRODUCER_FORMAT_PROPOSAL, &request1, sizeof(request1), &reply1, sizeof(reply1));
7408c6a6096Sbeveloper 	if (rv != B_OK) {
7415ac4fbd7Sbeveloper 		ERROR("BMediaRoster::Connect: aborted after BBufferProducer::FormatProposal, status = %#lx\n",rv);
74252a38012Sejakowatz 		return rv;
74352a38012Sejakowatz 	}
7448c6a6096Sbeveloper 	// reply1.format now contains the format proposed by the producer
7458c6a6096Sbeveloper 
7468c6a6096Sbeveloper 	consumer_accept_format_request request2;
7478c6a6096Sbeveloper 	consumer_accept_format_reply reply2;
7488c6a6096Sbeveloper 
74969983609Sbeveloper 	PRINT_FORMAT("BMediaRoster::Connect calling BBufferConsumer::AcceptFormat with format    ", reply1.format);
75069983609Sbeveloper 
7518c6a6096Sbeveloper 	// BBufferConsumer::AcceptFormat
7528c6a6096Sbeveloper 	request2.dest = to;
7538c6a6096Sbeveloper 	request2.format = reply1.format;
7548c6a6096Sbeveloper 	rv = QueryPort(to.port, CONSUMER_ACCEPT_FORMAT, &request2, sizeof(request2), &reply2, sizeof(reply2));
7558c6a6096Sbeveloper 	if (rv != B_OK) {
7565ac4fbd7Sbeveloper 		ERROR("BMediaRoster::Connect: aborted after BBufferConsumer::AcceptFormat, status = %#lx\n",rv);
7578c6a6096Sbeveloper 		return rv;
7588c6a6096Sbeveloper 	}
7598c6a6096Sbeveloper 	// reply2.format now contains the format accepted by the consumer
7608c6a6096Sbeveloper 
7618c6a6096Sbeveloper 	// BBufferProducer::PrepareToConnect
7628c6a6096Sbeveloper 	producer_prepare_to_connect_request request3;
7638c6a6096Sbeveloper 	producer_prepare_to_connect_reply reply3;
7648c6a6096Sbeveloper 
76569983609Sbeveloper 	PRINT_FORMAT("BMediaRoster::Connect calling BBufferProducer::PrepareToConnect with format", reply2.format);
76669983609Sbeveloper 
7678c6a6096Sbeveloper 	request3.source = from;
7688c6a6096Sbeveloper 	request3.destination = to;
7698c6a6096Sbeveloper 	request3.format = reply2.format;
7708c6a6096Sbeveloper 	strcpy(request3.name, "XXX some default name"); // XXX fix this
7718c6a6096Sbeveloper 	rv = QueryPort(from.port, PRODUCER_PREPARE_TO_CONNECT, &request3, sizeof(request3), &reply3, sizeof(reply3));
7728c6a6096Sbeveloper 	if (rv != B_OK) {
7735ac4fbd7Sbeveloper 		ERROR("BMediaRoster::Connect: aborted after BBufferProducer::PrepareToConnect, status = %#lx\n",rv);
7748c6a6096Sbeveloper 		return rv;
7758c6a6096Sbeveloper 	}
7768c6a6096Sbeveloper 	// reply3.format is still our pretty media format
7778c6a6096Sbeveloper 	// reply3.out_source the real source to be used for the connection
7788c6a6096Sbeveloper 	// reply3.name the name BBufferConsumer::Connected will see in the outInput->name argument
7798c6a6096Sbeveloper 
78069983609Sbeveloper 
78169983609Sbeveloper 	// find the output and input nodes
78269983609Sbeveloper 	// XXX isn't there a easier way?
78369983609Sbeveloper 	media_node sourcenode;
78469983609Sbeveloper 	media_node destnode;
78569983609Sbeveloper 	GetNodeFor(NodeIDFor(from.port), &sourcenode);
78669983609Sbeveloper 	GetNodeFor(NodeIDFor(to.port), &destnode);
78769983609Sbeveloper 	ReleaseNode(sourcenode);
78869983609Sbeveloper 	ReleaseNode(destnode);
78969983609Sbeveloper 
7908c6a6096Sbeveloper 	// BBufferConsumer::Connected
7918c6a6096Sbeveloper 	consumer_connected_request request4;
7928c6a6096Sbeveloper 	consumer_connected_reply reply4;
7938c6a6096Sbeveloper 	status_t con_status;
7948c6a6096Sbeveloper 
79569983609Sbeveloper 	PRINT_FORMAT("BMediaRoster::Connect calling BBufferConsumer::Connected with format       ", reply3.format);
79669983609Sbeveloper 
79769983609Sbeveloper 	request4.input.node = destnode;
79869983609Sbeveloper 	request4.input.source = reply3.out_source;
79969983609Sbeveloper 	request4.input.destination = to;
80069983609Sbeveloper 	request4.input.format = reply3.format;
80169983609Sbeveloper 	strcpy(request4.input.name, reply3.name);
80269983609Sbeveloper 
8038c6a6096Sbeveloper 	con_status = QueryPort(to.port, CONSUMER_CONNECTED, &request4, sizeof(request4), &reply4, sizeof(reply4));
8048c6a6096Sbeveloper 	if (con_status != B_OK) {
8055ac4fbd7Sbeveloper 		ERROR("BMediaRoster::Connect: aborting after BBufferConsumer::Connected, status = %#lx\n",con_status);
8068c6a6096Sbeveloper 		// we do NOT return here!
8078c6a6096Sbeveloper 	}
8088c6a6096Sbeveloper 	// con_status contains the status code to be supplied to BBufferProducer::Connect's status argument
8098c6a6096Sbeveloper 	// reply4.input contains the media_input that describes the connection from the consumer point of view
8108c6a6096Sbeveloper 
8118c6a6096Sbeveloper 	// BBufferProducer::Connect
8128c6a6096Sbeveloper 	producer_connect_request request5;
8138c6a6096Sbeveloper 	producer_connect_reply reply5;
8148c6a6096Sbeveloper 
81569983609Sbeveloper 	PRINT_FORMAT("BMediaRoster::Connect calling BBufferProducer::Connect with format         ", reply4.input.format);
81669983609Sbeveloper 
8178c6a6096Sbeveloper 	request5.error = con_status;
8188c6a6096Sbeveloper 	request5.source = reply3.out_source;
8198c6a6096Sbeveloper 	request5.destination = reply4.input.destination;
82069983609Sbeveloper 	request5.format = reply4.input.format;
8218c6a6096Sbeveloper 	strcpy(request5.name, reply4.input.name);
8220caff283Sbeveloper 	rv = QueryPort(reply4.input.source.port, PRODUCER_CONNECT, &request5, sizeof(request5), &reply5, sizeof(reply5));
8238c6a6096Sbeveloper 	if (con_status != B_OK) {
8245ac4fbd7Sbeveloper 		ERROR("BMediaRoster::Connect: aborted\n");
8258c6a6096Sbeveloper 		return con_status;
8268c6a6096Sbeveloper 	}
8278c6a6096Sbeveloper 	if (rv != B_OK) {
8285ac4fbd7Sbeveloper 		ERROR("BMediaRoster::Connect: aborted after BBufferProducer::Connect, status = %#lx\n",rv);
8298c6a6096Sbeveloper 		return rv;
8308c6a6096Sbeveloper 	}
8318c6a6096Sbeveloper 	// reply5.name contains the name assigned to the connection by the producer
8328c6a6096Sbeveloper 
8338c6a6096Sbeveloper 	// initilize connection info
83469983609Sbeveloper 	*io_format = reply4.input.format;
8358c6a6096Sbeveloper 	*out_input = reply4.input;
8368c6a6096Sbeveloper 	out_output->node = sourcenode;
8378c6a6096Sbeveloper 	out_output->source = reply4.input.source;
8388c6a6096Sbeveloper 	out_output->destination = reply4.input.destination;
8398c6a6096Sbeveloper 	out_output->format = reply4.input.format;
8408c6a6096Sbeveloper 	strcpy(out_output->name, reply5.name);
8418c6a6096Sbeveloper 
8428c6a6096Sbeveloper 	// the connection is now made
84369983609Sbeveloper 	printf("BMediaRoster::Connect connection established!\n");
84469983609Sbeveloper 	PRINT_FORMAT("   format", *io_format);
84569983609Sbeveloper 	PRINT_INPUT("   input", *out_input);
84669983609Sbeveloper 	PRINT_OUTPUT("   output", *out_output);
8478c6a6096Sbeveloper 
8488c6a6096Sbeveloper 	// XXX register connection with server
8499e9417d2Sbeveloper 	// XXX we should just send a notification, instead of republishing all endpoints
85076669a29Sbeveloper 	List<media_output> outlist;
85176669a29Sbeveloper 	List<media_input> inlist;
8528b04ffc1Sbeveloper 	if (B_OK == MediaRosterEx(this)->GetAllOutputs(out_output->node , &outlist))
8538b04ffc1Sbeveloper 		MediaRosterEx(this)->PublishOutputs(out_output->node , &outlist);
8548b04ffc1Sbeveloper 	if (B_OK == MediaRosterEx(this)->GetAllInputs(out_input->node , &inlist))
8558b04ffc1Sbeveloper 		MediaRosterEx(this)->PublishInputs(out_input->node, &inlist);
8568c6a6096Sbeveloper 
8578c6a6096Sbeveloper 
8588c6a6096Sbeveloper 	// XXX if (mute) BBufferProducer::EnableOutput(false)
8599e9417d2Sbeveloper 	if (in_flags & B_CONNECT_MUTED) {
8609e9417d2Sbeveloper 	}
8618c6a6096Sbeveloper 
8628c6a6096Sbeveloper 
8639e9417d2Sbeveloper 	// send a notification
8649e9417d2Sbeveloper 	BPrivate::media::notifications::ConnectionMade(*out_input, *out_output, *io_format);
8659e9417d2Sbeveloper 
8668c6a6096Sbeveloper 	return B_OK;
8678c6a6096Sbeveloper };
86852a38012Sejakowatz 
86952a38012Sejakowatz 
87052a38012Sejakowatz status_t
8719e9417d2Sbeveloper BMediaRoster::Disconnect(media_node_id source_nodeid,
87252a38012Sejakowatz 						 const media_source & source,
8739e9417d2Sbeveloper 						 media_node_id destination_nodeid,
87452a38012Sejakowatz 						 const media_destination & destination)
87552a38012Sejakowatz {
8769e9417d2Sbeveloper 	CALLED();
87740f36b03Sbeveloper 	if (IS_INVALID_NODEID(source_nodeid)) {
8785ac4fbd7Sbeveloper 		ERROR("BMediaRoster::Disconnect: source media_node_id invalid\n");
8799e9417d2Sbeveloper 		return B_MEDIA_BAD_SOURCE;
8809e9417d2Sbeveloper 	}
88140f36b03Sbeveloper 	if (IS_INVALID_NODEID(destination_nodeid)) {
8825ac4fbd7Sbeveloper 		ERROR("BMediaRoster::Disconnect: destination media_node_id invalid\n");
8839e9417d2Sbeveloper 		return B_MEDIA_BAD_DESTINATION;
8849e9417d2Sbeveloper 	}
88540f36b03Sbeveloper 	if (IS_INVALID_SOURCE(source)) {
8865ac4fbd7Sbeveloper 		ERROR("BMediaRoster::Disconnect: media_source invalid\n");
8879e9417d2Sbeveloper 		return B_MEDIA_BAD_SOURCE;
8889e9417d2Sbeveloper 	}
88940f36b03Sbeveloper 	if (IS_INVALID_DESTINATION(destination)) {
8905ac4fbd7Sbeveloper 		ERROR("BMediaRoster::Disconnect: media_destination invalid\n");
8919e9417d2Sbeveloper 		return B_MEDIA_BAD_DESTINATION;
8929e9417d2Sbeveloper 	}
8939e9417d2Sbeveloper 
8949e9417d2Sbeveloper 	producer_disconnect_request request2;
8959e9417d2Sbeveloper 	producer_disconnect_reply reply2;
8969e9417d2Sbeveloper 	consumer_disconnected_request request1;
8979e9417d2Sbeveloper 	consumer_disconnected_reply reply1;
8989e9417d2Sbeveloper 	status_t rv1, rv2;
8999e9417d2Sbeveloper 
9009e9417d2Sbeveloper 	// XXX we should ask the server if this connection really exists
9019e9417d2Sbeveloper 
9029e9417d2Sbeveloper 	request1.source = source;
9039e9417d2Sbeveloper 	request1.destination = destination;
9049e9417d2Sbeveloper 	request2.source = source;
9059e9417d2Sbeveloper 	request2.destination = destination;
9069e9417d2Sbeveloper 
9079e9417d2Sbeveloper 	rv1 = QueryPort(source.port, PRODUCER_DISCONNECT, &request1, sizeof(request1), &reply1, sizeof(reply1));
9089e9417d2Sbeveloper 	rv2 = QueryPort(destination.port, CONSUMER_DISCONNECTED, &request2, sizeof(request2), &reply2, sizeof(reply2));
9099e9417d2Sbeveloper 
9109e9417d2Sbeveloper 	// XXX unregister connection with server
9119e9417d2Sbeveloper 	// XXX we should just send a notification, instead of republishing all endpoints
91276669a29Sbeveloper 	List<media_output> outlist;
91376669a29Sbeveloper 	List<media_input> inlist;
9149e9417d2Sbeveloper 	media_node sourcenode;
9159e9417d2Sbeveloper 	media_node destnode;
9169e9417d2Sbeveloper 	if (B_OK == GetNodeFor(source_nodeid, &sourcenode)) {
9178b04ffc1Sbeveloper 		if (B_OK == MediaRosterEx(this)->GetAllOutputs(sourcenode , &outlist))
9188b04ffc1Sbeveloper 			MediaRosterEx(this)->PublishOutputs(sourcenode , &outlist);
9199e9417d2Sbeveloper 		ReleaseNode(sourcenode);
9204f09fa2fSbeveloper 	} else {
9215ac4fbd7Sbeveloper 		ERROR("BMediaRoster::Disconnect: source GetNodeFor failed\n");
9224f09fa2fSbeveloper 	}
9239e9417d2Sbeveloper 	if (B_OK == GetNodeFor(destination_nodeid, &destnode)) {
9248b04ffc1Sbeveloper 		if (B_OK == MediaRosterEx(this)->GetAllInputs(destnode , &inlist))
9258b04ffc1Sbeveloper 			MediaRosterEx(this)->PublishInputs(destnode, &inlist);
9269e9417d2Sbeveloper 		ReleaseNode(destnode);
9274f09fa2fSbeveloper 	} else {
9285ac4fbd7Sbeveloper 		ERROR("BMediaRoster::Disconnect: dest GetNodeFor failed\n");
9294f09fa2fSbeveloper 	}
9309e9417d2Sbeveloper 
9319e9417d2Sbeveloper 
9329e9417d2Sbeveloper 	// send a notification
9339e9417d2Sbeveloper 	BPrivate::media::notifications::ConnectionBroken(source, destination);
9349e9417d2Sbeveloper 
9359e9417d2Sbeveloper 	return (rv1 != B_OK || rv2 != B_OK) ? B_ERROR : B_OK;
93652a38012Sejakowatz }
93752a38012Sejakowatz 
93852a38012Sejakowatz 
93952a38012Sejakowatz status_t
94052a38012Sejakowatz BMediaRoster::StartNode(const media_node & node,
94152a38012Sejakowatz 						bigtime_t at_performance_time)
94252a38012Sejakowatz {
94352a38012Sejakowatz 	CALLED();
9449e9417d2Sbeveloper 	if (node.node <= 0)
94552a38012Sejakowatz 		return B_MEDIA_BAD_NODE;
94652a38012Sejakowatz 
94760f15390Sbeveloper 	TRACE("BMediaRoster::StartNode, node %ld, at perf %Ld\n", node.node, at_performance_time);
9480e21b167Sbeveloper 
9496396865dSbeveloper 	node_start_command command;
9506396865dSbeveloper 	command.performance_time = at_performance_time;
95152a38012Sejakowatz 
9526396865dSbeveloper 	return SendToPort(node.port, NODE_START, &command, sizeof(command));
95352a38012Sejakowatz }
95452a38012Sejakowatz 
95552a38012Sejakowatz 
95652a38012Sejakowatz status_t
95752a38012Sejakowatz BMediaRoster::StopNode(const media_node & node,
95852a38012Sejakowatz 					   bigtime_t at_performance_time,
95952a38012Sejakowatz 					   bool immediate)
96052a38012Sejakowatz {
96152a38012Sejakowatz 	CALLED();
96240f36b03Sbeveloper 	if (IS_INVALID_NODE(node))
96352a38012Sejakowatz 		return B_MEDIA_BAD_NODE;
96452a38012Sejakowatz 
96560f15390Sbeveloper 	TRACE("BMediaRoster::StopNode, node %ld, at perf %Ld %s\n", node.node, at_performance_time, immediate ? "NOW" : "");
9660e21b167Sbeveloper 
9676396865dSbeveloper 	node_stop_command command;
9686396865dSbeveloper 	command.performance_time = at_performance_time;
9696396865dSbeveloper 	command.immediate = immediate;
97052a38012Sejakowatz 
9716396865dSbeveloper 	return SendToPort(node.port, NODE_STOP, &command, sizeof(command));
97252a38012Sejakowatz }
97352a38012Sejakowatz 
97452a38012Sejakowatz 
97552a38012Sejakowatz status_t
97652a38012Sejakowatz BMediaRoster::SeekNode(const media_node & node,
97752a38012Sejakowatz 					   bigtime_t to_media_time,
97852a38012Sejakowatz 					   bigtime_t at_performance_time)
97952a38012Sejakowatz {
98052a38012Sejakowatz 	CALLED();
98140f36b03Sbeveloper 	if (IS_INVALID_NODE(node))
98252a38012Sejakowatz 		return B_MEDIA_BAD_NODE;
98352a38012Sejakowatz 
98460f15390Sbeveloper 	TRACE("BMediaRoster::SeekNode, node %ld, at perf %Ld, to perf %Ld\n", node.node, at_performance_time, to_media_time);
9850e21b167Sbeveloper 
9866396865dSbeveloper 	node_seek_command command;
9876396865dSbeveloper 	command.media_time = to_media_time;
9886396865dSbeveloper 	command.performance_time = at_performance_time;
98952a38012Sejakowatz 
9906396865dSbeveloper 	return SendToPort(node.port, NODE_SEEK, &command, sizeof(command));
99152a38012Sejakowatz }
99252a38012Sejakowatz 
99352a38012Sejakowatz 
99452a38012Sejakowatz status_t
99552a38012Sejakowatz BMediaRoster::StartTimeSource(const media_node & node,
99652a38012Sejakowatz 							  bigtime_t at_real_time)
99752a38012Sejakowatz {
99852a38012Sejakowatz 	CALLED();
99960f15390Sbeveloper 	if (IS_SYSTEM_TIMESOURCE(node)) {
100060f15390Sbeveloper 		// XXX debug this
10015ac4fbd7Sbeveloper 		//ERROR("BMediaRoster::StartTimeSource node %ld is system timesource\n", node.node);
100260f15390Sbeveloper 		return B_OK;
100360f15390Sbeveloper 	}
100492e575c1Sbeveloper //	if (IS_SHADOW_TIMESOURCE(node)) {
100592e575c1Sbeveloper //		// XXX debug this
100692e575c1Sbeveloper //		ERROR("BMediaRoster::StartTimeSource node %ld is shadow timesource\n", node.node);
100792e575c1Sbeveloper //		return B_OK;
100892e575c1Sbeveloper //	}
100940f36b03Sbeveloper 	if (IS_INVALID_NODE(node)) {
10105ac4fbd7Sbeveloper 		ERROR("BMediaRoster::StartTimeSource node %ld invalid\n", node.node);
101152a38012Sejakowatz 		return B_MEDIA_BAD_NODE;
10120e21b167Sbeveloper 	}
10130e21b167Sbeveloper 	if ((node.kind & B_TIME_SOURCE) == 0) {
10145ac4fbd7Sbeveloper 		ERROR("BMediaRoster::StartTimeSource node %ld is no timesource\n", node.node);
101552a38012Sejakowatz 		return B_MEDIA_BAD_NODE;
10160e21b167Sbeveloper 	}
10170e21b167Sbeveloper 
101860f15390Sbeveloper 	TRACE("BMediaRoster::StartTimeSource, node %ld, at real %Ld\n", node.node, at_real_time);
101952a38012Sejakowatz 
102052a38012Sejakowatz 	BTimeSource::time_source_op_info msg;
102152a38012Sejakowatz 	msg.op = BTimeSource::B_TIMESOURCE_START;
102252a38012Sejakowatz 	msg.real_time = at_real_time;
102352a38012Sejakowatz 
102452a38012Sejakowatz 	return write_port(node.port, TIMESOURCE_OP, &msg, sizeof(msg));
102552a38012Sejakowatz }
102652a38012Sejakowatz 
102752a38012Sejakowatz 
102852a38012Sejakowatz status_t
102952a38012Sejakowatz BMediaRoster::StopTimeSource(const media_node & node,
103052a38012Sejakowatz 							 bigtime_t at_real_time,
103152a38012Sejakowatz 							 bool immediate)
103252a38012Sejakowatz {
103352a38012Sejakowatz 	CALLED();
103460f15390Sbeveloper 	if (IS_SYSTEM_TIMESOURCE(node)) {
103560f15390Sbeveloper 		// XXX debug this
10365ac4fbd7Sbeveloper 		//ERROR("BMediaRoster::StopTimeSource node %ld is system timesource\n", node.node);
103760f15390Sbeveloper 		return B_OK;
103860f15390Sbeveloper 	}
103992e575c1Sbeveloper //	if (IS_SHADOW_TIMESOURCE(node)) {
104092e575c1Sbeveloper //		// XXX debug this
104192e575c1Sbeveloper //		ERROR("BMediaRoster::StopTimeSource node %ld is shadow timesource\n", node.node);
104292e575c1Sbeveloper //		return B_OK;
104392e575c1Sbeveloper //	}
104440f36b03Sbeveloper 	if (IS_INVALID_NODE(node)) {
10455ac4fbd7Sbeveloper 		ERROR("BMediaRoster::StopTimeSource node %ld invalid\n", node.node);
104652a38012Sejakowatz 		return B_MEDIA_BAD_NODE;
10470e21b167Sbeveloper 	}
10480e21b167Sbeveloper 	if ((node.kind & B_TIME_SOURCE) == 0) {
10495ac4fbd7Sbeveloper 		ERROR("BMediaRoster::StopTimeSource node %ld is no timesource\n", node.node);
105052a38012Sejakowatz 		return B_MEDIA_BAD_NODE;
10510e21b167Sbeveloper 	}
10520e21b167Sbeveloper 
105360f15390Sbeveloper 	TRACE("BMediaRoster::StopTimeSource, node %ld, at real %Ld %s\n", node.node, at_real_time, immediate ? "NOW" : "");
105452a38012Sejakowatz 
105552a38012Sejakowatz 	BTimeSource::time_source_op_info msg;
105652a38012Sejakowatz 	msg.op = immediate ? BTimeSource::B_TIMESOURCE_STOP_IMMEDIATELY : BTimeSource::B_TIMESOURCE_STOP;
105752a38012Sejakowatz 	msg.real_time = at_real_time;
105852a38012Sejakowatz 
105952a38012Sejakowatz 	return write_port(node.port, TIMESOURCE_OP, &msg, sizeof(msg));
106052a38012Sejakowatz }
106152a38012Sejakowatz 
106252a38012Sejakowatz 
106352a38012Sejakowatz status_t
106452a38012Sejakowatz BMediaRoster::SeekTimeSource(const media_node & node,
106552a38012Sejakowatz 							 bigtime_t to_performance_time,
106652a38012Sejakowatz 							 bigtime_t at_real_time)
106752a38012Sejakowatz {
106852a38012Sejakowatz 	CALLED();
106960f15390Sbeveloper 	if (IS_SYSTEM_TIMESOURCE(node)) {
107060f15390Sbeveloper 		// XXX debug this
10715ac4fbd7Sbeveloper 		// ERROR("BMediaRoster::SeekTimeSource node %ld is system timesource\n", node.node);
107260f15390Sbeveloper 		// you can't seek the system time source, but
107360f15390Sbeveloper 		// returning B_ERROR would break StampTV
107460f15390Sbeveloper 		return B_OK;
107560f15390Sbeveloper 	}
107692e575c1Sbeveloper //	if (IS_SHADOW_TIMESOURCE(node)) {
107792e575c1Sbeveloper //		// XXX debug this
107892e575c1Sbeveloper //		ERROR("BMediaRoster::SeekTimeSource node %ld is shadow timesource\n", node.node);
107992e575c1Sbeveloper //		return B_OK;
108092e575c1Sbeveloper //	}
108140f36b03Sbeveloper 	if (IS_INVALID_NODE(node)) {
10825ac4fbd7Sbeveloper 		ERROR("BMediaRoster::SeekTimeSource node %ld invalid\n", node.node);
108352a38012Sejakowatz 		return B_MEDIA_BAD_NODE;
10840e21b167Sbeveloper 	}
10850e21b167Sbeveloper 	if ((node.kind & B_TIME_SOURCE) == 0) {
10865ac4fbd7Sbeveloper 		ERROR("BMediaRoster::SeekTimeSource node %ld is no timesource\n", node.node);
108752a38012Sejakowatz 		return B_MEDIA_BAD_NODE;
10880e21b167Sbeveloper 	}
10890e21b167Sbeveloper 
109060f15390Sbeveloper 	TRACE("BMediaRoster::SeekTimeSource, node %ld, at real %Ld, to perf %Ld\n", node.node, at_real_time, to_performance_time);
109152a38012Sejakowatz 
109252a38012Sejakowatz 	BTimeSource::time_source_op_info msg;
109352a38012Sejakowatz 	msg.op = BTimeSource::B_TIMESOURCE_SEEK;
109452a38012Sejakowatz 	msg.real_time = at_real_time;
109552a38012Sejakowatz 	msg.performance_time = to_performance_time;
109652a38012Sejakowatz 
109752a38012Sejakowatz 	return write_port(node.port, TIMESOURCE_OP, &msg, sizeof(msg));
109852a38012Sejakowatz }
109952a38012Sejakowatz 
110052a38012Sejakowatz 
110152a38012Sejakowatz status_t
110252a38012Sejakowatz BMediaRoster::SyncToNode(const media_node & node,
110352a38012Sejakowatz 						 bigtime_t at_time,
110452a38012Sejakowatz 						 bigtime_t timeout)
110552a38012Sejakowatz {
110652a38012Sejakowatz 	UNIMPLEMENTED();
110760f15390Sbeveloper 	return B_OK;
110852a38012Sejakowatz }
110952a38012Sejakowatz 
111052a38012Sejakowatz 
111152a38012Sejakowatz status_t
111252a38012Sejakowatz BMediaRoster::SetRunModeNode(const media_node & node,
111352a38012Sejakowatz 							 BMediaNode::run_mode mode)
111452a38012Sejakowatz {
111552a38012Sejakowatz 	CALLED();
111640f36b03Sbeveloper 	if (IS_INVALID_NODE(node))
111752a38012Sejakowatz 		return B_MEDIA_BAD_NODE;
111852a38012Sejakowatz 
1119dfb2ad61Sbeveloper 	node_set_run_mode_command msg;
112052a38012Sejakowatz 	msg.mode = mode;
112152a38012Sejakowatz 
112252a38012Sejakowatz 	return write_port(node.port, NODE_SET_RUN_MODE, &msg, sizeof(msg));
112352a38012Sejakowatz }
112452a38012Sejakowatz 
112552a38012Sejakowatz 
112652a38012Sejakowatz status_t
112752a38012Sejakowatz BMediaRoster::PrerollNode(const media_node & node)
112852a38012Sejakowatz {
112952a38012Sejakowatz 	CALLED();
113040f36b03Sbeveloper 	if (IS_INVALID_NODE(node))
113152a38012Sejakowatz 		return B_MEDIA_BAD_NODE;
113252a38012Sejakowatz 
113352a38012Sejakowatz 	char dummy;
113452a38012Sejakowatz 	return write_port(node.port, NODE_PREROLL, &dummy, sizeof(dummy));
113552a38012Sejakowatz }
113652a38012Sejakowatz 
113752a38012Sejakowatz 
113852a38012Sejakowatz status_t
113952a38012Sejakowatz BMediaRoster::RollNode(const media_node & node,
114052a38012Sejakowatz 					   bigtime_t startPerformance,
114152a38012Sejakowatz 					   bigtime_t stopPerformance,
114252a38012Sejakowatz 					   bigtime_t atMediaTime)
114352a38012Sejakowatz {
114452a38012Sejakowatz 	UNIMPLEMENTED();
114552a38012Sejakowatz 	return B_ERROR;
114652a38012Sejakowatz }
114752a38012Sejakowatz 
114852a38012Sejakowatz 
114952a38012Sejakowatz status_t
115052a38012Sejakowatz BMediaRoster::SetProducerRunModeDelay(const media_node & node,
115152a38012Sejakowatz 									  bigtime_t delay,
115252a38012Sejakowatz 									  BMediaNode::run_mode mode)
115352a38012Sejakowatz {
115460f15390Sbeveloper 	CALLED();
115560f15390Sbeveloper 	if (IS_INVALID_NODE(node))
115660f15390Sbeveloper 		return B_MEDIA_BAD_NODE;
115760f15390Sbeveloper 	if ((node.kind & B_BUFFER_PRODUCER) == 0)
115860f15390Sbeveloper 		return B_MEDIA_BAD_NODE;
115960f15390Sbeveloper 
116060f15390Sbeveloper 	producer_set_run_mode_delay_command command;
116160f15390Sbeveloper 	command.mode = mode;
116260f15390Sbeveloper 	command.delay = delay;
116360f15390Sbeveloper 
116460f15390Sbeveloper 	return SendToPort(node.port, PRODUCER_SET_RUN_MODE_DELAY, &command, sizeof(command));
116552a38012Sejakowatz }
116652a38012Sejakowatz 
116752a38012Sejakowatz 
116852a38012Sejakowatz status_t
116952a38012Sejakowatz BMediaRoster::SetProducerRate(const media_node & producer,
117052a38012Sejakowatz 							  int32 numer,
117152a38012Sejakowatz 							  int32 denom)
117252a38012Sejakowatz {
117352a38012Sejakowatz 	CALLED();
117440f36b03Sbeveloper 	if (IS_INVALID_NODE(producer))
117552a38012Sejakowatz 		return B_MEDIA_BAD_NODE;
117652a38012Sejakowatz 	if ((producer.kind & B_BUFFER_PRODUCER) == 0)
117752a38012Sejakowatz 		return B_MEDIA_BAD_NODE;
117852a38012Sejakowatz 
1179dfb2ad61Sbeveloper 	producer_set_play_rate_request msg;
1180dfb2ad61Sbeveloper 	producer_set_play_rate_reply reply;
118152a38012Sejakowatz 	status_t rv;
118252a38012Sejakowatz 	int32 code;
118352a38012Sejakowatz 
118452a38012Sejakowatz 	msg.numer = numer;
118552a38012Sejakowatz 	msg.denom = denom;
118652a38012Sejakowatz 	msg.reply_port = _PortPool->GetPort();
118752a38012Sejakowatz 	rv = write_port(producer.node, PRODUCER_SET_PLAY_RATE, &msg, sizeof(msg));
118852a38012Sejakowatz 	if (rv != B_OK) {
118952a38012Sejakowatz 		_PortPool->PutPort(msg.reply_port);
119052a38012Sejakowatz 		return rv;
119152a38012Sejakowatz 	}
119252a38012Sejakowatz 	rv = read_port(msg.reply_port, &code, &reply, sizeof(reply));
119352a38012Sejakowatz 	_PortPool->PutPort(msg.reply_port);
119452a38012Sejakowatz 	return (rv < B_OK) ? rv : reply.result;
119552a38012Sejakowatz }
119652a38012Sejakowatz 
119752a38012Sejakowatz 
119852a38012Sejakowatz /* Nodes will have available inputs/outputs as long as they are capable */
119952a38012Sejakowatz /* of accepting more connections. The node may create an additional */
120052a38012Sejakowatz /* output or input as the currently available is taken into usage. */
120152a38012Sejakowatz status_t
120252a38012Sejakowatz BMediaRoster::GetLiveNodeInfo(const media_node & node,
120352a38012Sejakowatz 							  live_node_info * out_live_info)
120452a38012Sejakowatz {
12059e9417d2Sbeveloper 	CALLED();
12069e9417d2Sbeveloper 	if (out_live_info == NULL)
12079e9417d2Sbeveloper 		return B_BAD_VALUE;
120840f36b03Sbeveloper 	if (IS_INVALID_NODE(node))
12099e9417d2Sbeveloper 		return B_MEDIA_BAD_NODE;
12109e9417d2Sbeveloper 
12119e9417d2Sbeveloper 	server_get_live_node_info_request request;
12129e9417d2Sbeveloper 	server_get_live_node_info_reply reply;
12139e9417d2Sbeveloper 	status_t rv;
12149e9417d2Sbeveloper 
12159e9417d2Sbeveloper 	request.node = node;
12169e9417d2Sbeveloper 
12171299bfb2Sbeveloper 	rv = QueryServer(SERVER_GET_LIVE_NODE_INFO, &request, sizeof(request), &reply, sizeof(reply));
12189e9417d2Sbeveloper 	if (rv != B_OK)
12199e9417d2Sbeveloper 		return rv;
12209e9417d2Sbeveloper 
12219e9417d2Sbeveloper 	*out_live_info = reply.live_info;
12229e9417d2Sbeveloper 	return B_OK;
122352a38012Sejakowatz }
122452a38012Sejakowatz 
122552a38012Sejakowatz 
122652a38012Sejakowatz status_t
122752a38012Sejakowatz BMediaRoster::GetLiveNodes(live_node_info * out_live_nodes,
122852a38012Sejakowatz 						   int32 * io_total_count,
122952a38012Sejakowatz 						   const media_format * has_input,
123052a38012Sejakowatz 						   const media_format * has_output,
123152a38012Sejakowatz 						   const char * name,
123252a38012Sejakowatz 						   uint64 node_kinds)
123352a38012Sejakowatz {
12349e9417d2Sbeveloper 	CALLED();
12359e9417d2Sbeveloper 	if (out_live_nodes == NULL || io_total_count == NULL)
12369e9417d2Sbeveloper 		return B_BAD_VALUE;
12379e9417d2Sbeveloper 	if (*io_total_count <= 0)
12389e9417d2Sbeveloper 		return B_BAD_VALUE;
12399e9417d2Sbeveloper 
12409e9417d2Sbeveloper 	// XXX we also support the wildcard search as GetDormantNodes does. This needs to be documented
12419e9417d2Sbeveloper 
12429e9417d2Sbeveloper 	server_get_live_nodes_request request;
12439e9417d2Sbeveloper 	server_get_live_nodes_reply reply;
12449e9417d2Sbeveloper 	status_t rv;
12459e9417d2Sbeveloper 
12469e9417d2Sbeveloper 	request.maxcount = *io_total_count;
12479e9417d2Sbeveloper 	request.has_input = (bool) has_input;
12489e9417d2Sbeveloper 	if (has_input)
12499e9417d2Sbeveloper 		request.inputformat = *has_input; // XXX we should not make a flat copy of media_format
12509e9417d2Sbeveloper 	request.has_output = (bool) has_output;
12519e9417d2Sbeveloper 	if (has_output)
12529e9417d2Sbeveloper 		request.outputformat = *has_output; // XXX we should not make a flat copy of media_format
12539e9417d2Sbeveloper 	request.has_name = (bool) name;
12549e9417d2Sbeveloper 	if (name) {
12559e9417d2Sbeveloper 		int len = strlen(name);
12569e9417d2Sbeveloper 		len = min_c(len, (int)sizeof(request.name) - 1);
12579e9417d2Sbeveloper 		memcpy(request.name, name, len);
12589e9417d2Sbeveloper 		request.name[len] = 0;
12599e9417d2Sbeveloper 	}
12609e9417d2Sbeveloper 	request.require_kinds = node_kinds;
12619e9417d2Sbeveloper 
12629e9417d2Sbeveloper 	rv = QueryServer(SERVER_GET_LIVE_NODES, &request, sizeof(request), &reply, sizeof(reply));
12639e9417d2Sbeveloper 	if (rv != B_OK) {
12645ac4fbd7Sbeveloper 		ERROR("BMediaRoster::GetLiveNodes failed querying server\n");
12651299bfb2Sbeveloper 		*io_total_count = 0;
12669e9417d2Sbeveloper 		return rv;
12679e9417d2Sbeveloper 	}
12689e9417d2Sbeveloper 
12699e9417d2Sbeveloper 	if (reply.count > MAX_LIVE_INFO) {
12709e9417d2Sbeveloper 		live_node_info *live_info;
12719e9417d2Sbeveloper 		area_id clone;
12729e9417d2Sbeveloper 
12739e9417d2Sbeveloper 		clone = clone_area("live_node_info clone", reinterpret_cast<void **>(&live_info), B_ANY_ADDRESS, B_READ_AREA | B_WRITE_AREA, reply.area);
12749e9417d2Sbeveloper 		if (clone < B_OK) {
12755ac4fbd7Sbeveloper 			ERROR("BMediaRoster::GetLiveNodes failed to clone area, %#lx\n", clone);
12769e9417d2Sbeveloper 			delete_area(reply.area);
12771299bfb2Sbeveloper 			*io_total_count = 0;
127852a38012Sejakowatz 			return B_ERROR;
127952a38012Sejakowatz 		}
128052a38012Sejakowatz 
12819e9417d2Sbeveloper 		for (int32 i = 0; i < reply.count; i++) {
12829e9417d2Sbeveloper 			out_live_nodes[i] = live_info[i];
12839e9417d2Sbeveloper 		}
12849e9417d2Sbeveloper 
12859e9417d2Sbeveloper 		delete_area(clone);
12869e9417d2Sbeveloper 		delete_area(reply.area);
12879e9417d2Sbeveloper 	} else {
12889e9417d2Sbeveloper 		for (int32 i = 0; i < reply.count; i++) {
12899e9417d2Sbeveloper 			out_live_nodes[i] = reply.live_info[i];
12909e9417d2Sbeveloper 		}
12919e9417d2Sbeveloper 	}
12929e9417d2Sbeveloper 	*io_total_count = reply.count;
12939e9417d2Sbeveloper 
12949e9417d2Sbeveloper 	return B_OK;
12959e9417d2Sbeveloper }
12969e9417d2Sbeveloper 
129752a38012Sejakowatz 
129852a38012Sejakowatz status_t
129952a38012Sejakowatz BMediaRoster::GetFreeInputsFor(const media_node & node,
130052a38012Sejakowatz 							   media_input * out_free_inputs,
130152a38012Sejakowatz 							   int32 buf_num_inputs,
130252a38012Sejakowatz 							   int32 * out_total_count,
130352a38012Sejakowatz 							   media_type filter_type)
130452a38012Sejakowatz {
13053620737cSbeveloper 	CALLED();
13065ac4fbd7Sbeveloper 	if (IS_INVALID_NODE(node)) {
13075ac4fbd7Sbeveloper 		ERROR("BMediaRoster::GetFreeInputsFor: node %ld, port %ld invalid\n", node.node, node.port);
13083620737cSbeveloper 		return B_MEDIA_BAD_NODE;
13095ac4fbd7Sbeveloper 	}
13105ac4fbd7Sbeveloper 	if ((node.kind & B_BUFFER_CONSUMER) == 0) {
13115ac4fbd7Sbeveloper 		ERROR("BMediaRoster::GetFreeInputsFor: node %ld, port %ld is not a consumer\n", node.node, node.port);
13125ac4fbd7Sbeveloper 		return B_MEDIA_BAD_NODE;
13135ac4fbd7Sbeveloper 	}
13143620737cSbeveloper 	if (out_free_inputs == NULL || out_total_count == NULL)
13153620737cSbeveloper 		return B_BAD_VALUE;
13163620737cSbeveloper 
131776669a29Sbeveloper 	List<media_input> list;
13183620737cSbeveloper 	media_input *input;
13193620737cSbeveloper 	status_t rv;
13203620737cSbeveloper 
13211299bfb2Sbeveloper 	*out_total_count = 0;
13221299bfb2Sbeveloper 
13238b04ffc1Sbeveloper 	rv = MediaRosterEx(this)->GetAllInputs(node, &list);
13243620737cSbeveloper 	if (B_OK != rv)
13253620737cSbeveloper 		return rv;
13263620737cSbeveloper 
13275ac4fbd7Sbeveloper 	PRINT(4, "BMediaRoster::GetFreeInputsFor node %ld, max %ld, filter-type %ld\n", node.node, buf_num_inputs, filter_type);
13285ac4fbd7Sbeveloper 
132976669a29Sbeveloper 	int32 i;
1330b65a0ac5SJérôme Duval 	for (i = 0, list.Rewind(); list.GetNext(&input);) {
13313620737cSbeveloper 		if (filter_type != B_MEDIA_UNKNOWN_TYPE && filter_type != input->format.type)
13323620737cSbeveloper 			continue; // media_type used, but doesn't match
13333620737cSbeveloper 		if (input->source != media_source::null)
13343620737cSbeveloper 			continue; // consumer source already connected
13353620737cSbeveloper 		out_free_inputs[i] = *input;
13363620737cSbeveloper 		*out_total_count += 1;
13373620737cSbeveloper 		buf_num_inputs -= 1;
13385ac4fbd7Sbeveloper 		#if DEBUG >= 3
13395ac4fbd7Sbeveloper 			PRINT_OUTPUT("  input", out_free_inputs[i]);
13405ac4fbd7Sbeveloper 		#endif
13413620737cSbeveloper 		if (buf_num_inputs == 0)
13423620737cSbeveloper 			break;
1343b65a0ac5SJérôme Duval 		i++;
13443620737cSbeveloper 	}
13453620737cSbeveloper 
13468b04ffc1Sbeveloper 	MediaRosterEx(this)->PublishInputs(node, &list);
13473620737cSbeveloper 	return B_OK;
134852a38012Sejakowatz }
134952a38012Sejakowatz 
135052a38012Sejakowatz 
135152a38012Sejakowatz status_t
135252a38012Sejakowatz BMediaRoster::GetConnectedInputsFor(const media_node & node,
135352a38012Sejakowatz 									media_input * out_active_inputs,
135452a38012Sejakowatz 									int32 buf_num_inputs,
135552a38012Sejakowatz 									int32 * out_total_count)
135652a38012Sejakowatz {
13573620737cSbeveloper 	CALLED();
135840f36b03Sbeveloper 	if (IS_INVALID_NODE(node) || (node.kind & B_BUFFER_CONSUMER) == 0)
13593620737cSbeveloper 		return B_MEDIA_BAD_NODE;
13603620737cSbeveloper 	if (out_active_inputs == NULL || out_total_count == NULL)
13613620737cSbeveloper 		return B_BAD_VALUE;
13623620737cSbeveloper 
136376669a29Sbeveloper 	List<media_input> list;
13643620737cSbeveloper 	media_input *input;
13653620737cSbeveloper 	status_t rv;
13663620737cSbeveloper 
13671299bfb2Sbeveloper 	*out_total_count = 0;
13681299bfb2Sbeveloper 
13698b04ffc1Sbeveloper 	rv = MediaRosterEx(this)->GetAllInputs(node, &list);
13703620737cSbeveloper 	if (B_OK != rv)
13713620737cSbeveloper 		return rv;
13723620737cSbeveloper 
13735ac4fbd7Sbeveloper 	PRINT(4, "BMediaRoster::GetConnectedInputsFor node %ld, max %ld\n", node.node, buf_num_inputs);
13745ac4fbd7Sbeveloper 
137576669a29Sbeveloper 	int32 i;
1376b65a0ac5SJérôme Duval 	for (i = 0, list.Rewind(); list.GetNext(&input);) {
13773620737cSbeveloper 		if (input->source == media_source::null)
13783620737cSbeveloper 			continue; // consumer source not connected
13793620737cSbeveloper 		out_active_inputs[i] = *input;
13803620737cSbeveloper 		*out_total_count += 1;
13813620737cSbeveloper 		buf_num_inputs -= 1;
13825ac4fbd7Sbeveloper 		#if DEBUG >= 3
13835ac4fbd7Sbeveloper 			PRINT_OUTPUT("  input ", out_active_inputs[i]);
13845ac4fbd7Sbeveloper 		#endif
13853620737cSbeveloper 		if (buf_num_inputs == 0)
13863620737cSbeveloper 			break;
1387b65a0ac5SJérôme Duval 		i++;
13883620737cSbeveloper 	}
13893620737cSbeveloper 
13908b04ffc1Sbeveloper 	MediaRosterEx(this)->PublishInputs(node, &list);
13913620737cSbeveloper 	return B_OK;
139252a38012Sejakowatz }
139352a38012Sejakowatz 
139452a38012Sejakowatz 
139552a38012Sejakowatz status_t
139652a38012Sejakowatz BMediaRoster::GetAllInputsFor(const media_node & node,
139752a38012Sejakowatz 							  media_input * out_inputs,
139852a38012Sejakowatz 							  int32 buf_num_inputs,
139952a38012Sejakowatz 							  int32 * out_total_count)
140052a38012Sejakowatz {
140152a38012Sejakowatz 	CALLED();
140240f36b03Sbeveloper 	if (IS_INVALID_NODE(node) || (node.kind & B_BUFFER_CONSUMER) == 0)
140352a38012Sejakowatz 		return B_MEDIA_BAD_NODE;
140452a38012Sejakowatz 	if (out_inputs == NULL || out_total_count == NULL)
140552a38012Sejakowatz 		return B_BAD_VALUE;
140652a38012Sejakowatz 
140776669a29Sbeveloper 	List<media_input> list;
14083620737cSbeveloper 	media_input *input;
140952a38012Sejakowatz 	status_t rv;
141052a38012Sejakowatz 
14111299bfb2Sbeveloper 	*out_total_count = 0;
14121299bfb2Sbeveloper 
14138b04ffc1Sbeveloper 	rv = MediaRosterEx(this)->GetAllInputs(node, &list);
14143620737cSbeveloper 	if (B_OK != rv)
14153620737cSbeveloper 		return rv;
14163620737cSbeveloper 
14175ac4fbd7Sbeveloper 	PRINT(4, "BMediaRoster::GetAllInputsFor node %ld, max %ld\n", node.node, buf_num_inputs);
14185ac4fbd7Sbeveloper 
141976669a29Sbeveloper 	int32 i;
142076669a29Sbeveloper 	for (i = 0, list.Rewind(); list.GetNext(&input); i++) {
14213620737cSbeveloper 		out_inputs[i] = *input;
142252a38012Sejakowatz 		*out_total_count += 1;
14233620737cSbeveloper 		buf_num_inputs -= 1;
14245ac4fbd7Sbeveloper 		#if DEBUG >= 3
14255ac4fbd7Sbeveloper 			PRINT_OUTPUT("  input ", out_inputs[i]);
14265ac4fbd7Sbeveloper 		#endif
14273620737cSbeveloper 		if (buf_num_inputs == 0)
14283620737cSbeveloper 			break;
142952a38012Sejakowatz 	}
143052a38012Sejakowatz 
14318b04ffc1Sbeveloper 	MediaRosterEx(this)->PublishInputs(node, &list);
14323620737cSbeveloper 	return B_OK;
143352a38012Sejakowatz }
143452a38012Sejakowatz 
143552a38012Sejakowatz 
143652a38012Sejakowatz status_t
143752a38012Sejakowatz BMediaRoster::GetFreeOutputsFor(const media_node & node,
143852a38012Sejakowatz 								media_output * out_free_outputs,
143952a38012Sejakowatz 								int32 buf_num_outputs,
144052a38012Sejakowatz 								int32 * out_total_count,
144152a38012Sejakowatz 								media_type filter_type)
144252a38012Sejakowatz {
14433620737cSbeveloper 	CALLED();
144440f36b03Sbeveloper 	if (IS_INVALID_NODE(node) || (node.kind & B_BUFFER_PRODUCER) == 0)
14453620737cSbeveloper 		return B_MEDIA_BAD_NODE;
14463620737cSbeveloper 	if (out_free_outputs == NULL || out_total_count == NULL)
14473620737cSbeveloper 		return B_BAD_VALUE;
14483620737cSbeveloper 
144976669a29Sbeveloper 	List<media_output> list;
14503620737cSbeveloper 	media_output *output;
14513620737cSbeveloper 	status_t rv;
14523620737cSbeveloper 
14531299bfb2Sbeveloper 	*out_total_count = 0;
14541299bfb2Sbeveloper 
14558b04ffc1Sbeveloper 	rv = MediaRosterEx(this)->GetAllOutputs(node, &list);
14563620737cSbeveloper 	if (B_OK != rv)
14573620737cSbeveloper 		return rv;
14583620737cSbeveloper 
14595ac4fbd7Sbeveloper 	PRINT(4, "BMediaRoster::GetFreeOutputsFor node %ld, max %ld, filter-type %ld\n", node.node, buf_num_outputs, filter_type);
14605ac4fbd7Sbeveloper 
146176669a29Sbeveloper 	int32 i;
1462b65a0ac5SJérôme Duval 	for (i = 0, list.Rewind(); list.GetNext(&output);) {
14633620737cSbeveloper 		if (filter_type != B_MEDIA_UNKNOWN_TYPE && filter_type != output->format.type)
14643620737cSbeveloper 			continue; // media_type used, but doesn't match
14653620737cSbeveloper 		if (output->destination != media_destination::null)
14663620737cSbeveloper 			continue; // producer destination already connected
14673620737cSbeveloper 		out_free_outputs[i] = *output;
14683620737cSbeveloper 		*out_total_count += 1;
14693620737cSbeveloper 		buf_num_outputs -= 1;
14705ac4fbd7Sbeveloper 		#if DEBUG >= 3
14715ac4fbd7Sbeveloper 			PRINT_OUTPUT("  output ", out_free_outputs[i]);
14725ac4fbd7Sbeveloper 		#endif
14733620737cSbeveloper 		if (buf_num_outputs == 0)
14743620737cSbeveloper 			break;
1475b65a0ac5SJérôme Duval 		i++;
14763620737cSbeveloper 	}
14773620737cSbeveloper 
14788b04ffc1Sbeveloper 	MediaRosterEx(this)->PublishOutputs(node, &list);
14793620737cSbeveloper 	return B_OK;
148052a38012Sejakowatz }
148152a38012Sejakowatz 
148252a38012Sejakowatz 
148352a38012Sejakowatz status_t
148452a38012Sejakowatz BMediaRoster::GetConnectedOutputsFor(const media_node & node,
148552a38012Sejakowatz 									 media_output * out_active_outputs,
148652a38012Sejakowatz 									 int32 buf_num_outputs,
148752a38012Sejakowatz 									 int32 * out_total_count)
148852a38012Sejakowatz {
14893620737cSbeveloper 	CALLED();
149040f36b03Sbeveloper 	if (IS_INVALID_NODE(node) || (node.kind & B_BUFFER_PRODUCER) == 0)
14913620737cSbeveloper 		return B_MEDIA_BAD_NODE;
14923620737cSbeveloper 	if (out_active_outputs == NULL || out_total_count == NULL)
14933620737cSbeveloper 		return B_BAD_VALUE;
14943620737cSbeveloper 
149576669a29Sbeveloper 	List<media_output> list;
14963620737cSbeveloper 	media_output *output;
14973620737cSbeveloper 	status_t rv;
14983620737cSbeveloper 
14991299bfb2Sbeveloper 	*out_total_count = 0;
15001299bfb2Sbeveloper 
15018b04ffc1Sbeveloper 	rv = MediaRosterEx(this)->GetAllOutputs(node, &list);
15023620737cSbeveloper 	if (B_OK != rv)
15033620737cSbeveloper 		return rv;
15043620737cSbeveloper 
15055ac4fbd7Sbeveloper 	PRINT(4, "BMediaRoster::GetConnectedOutputsFor node %ld, max %ld\n", node.node, buf_num_outputs);
15065ac4fbd7Sbeveloper 
150776669a29Sbeveloper 	int32 i;
1508b65a0ac5SJérôme Duval 	for (i = 0, list.Rewind(); list.GetNext(&output);) {
15093620737cSbeveloper 		if (output->destination == media_destination::null)
15103620737cSbeveloper 			continue; // producer destination not connected
15113620737cSbeveloper 		out_active_outputs[i] = *output;
15123620737cSbeveloper 		*out_total_count += 1;
15133620737cSbeveloper 		buf_num_outputs -= 1;
15145ac4fbd7Sbeveloper 		#if DEBUG >= 3
15155ac4fbd7Sbeveloper 			PRINT_OUTPUT("  output ", out_active_outputs[i]);
15165ac4fbd7Sbeveloper 		#endif
15173620737cSbeveloper 		if (buf_num_outputs == 0)
15183620737cSbeveloper 			break;
1519b65a0ac5SJérôme Duval 		i++;
15203620737cSbeveloper 	}
15213620737cSbeveloper 
15228b04ffc1Sbeveloper 	MediaRosterEx(this)->PublishOutputs(node, &list);
15233620737cSbeveloper 	return B_OK;
152452a38012Sejakowatz }
152552a38012Sejakowatz 
152652a38012Sejakowatz 
152752a38012Sejakowatz status_t
152852a38012Sejakowatz BMediaRoster::GetAllOutputsFor(const media_node & node,
152952a38012Sejakowatz 							   media_output * out_outputs,
153052a38012Sejakowatz 							   int32 buf_num_outputs,
153152a38012Sejakowatz 							   int32 * out_total_count)
153252a38012Sejakowatz {
153352a38012Sejakowatz 	CALLED();
153440f36b03Sbeveloper 	if (IS_INVALID_NODE(node) || (node.kind & B_BUFFER_PRODUCER) == 0)
153552a38012Sejakowatz 		return B_MEDIA_BAD_NODE;
153652a38012Sejakowatz 	if (out_outputs == NULL || out_total_count == NULL)
153752a38012Sejakowatz 		return B_BAD_VALUE;
153852a38012Sejakowatz 
153976669a29Sbeveloper 	List<media_output> list;
15403620737cSbeveloper 	media_output *output;
154152a38012Sejakowatz 	status_t rv;
154252a38012Sejakowatz 
15431299bfb2Sbeveloper 	*out_total_count = 0;
15441299bfb2Sbeveloper 
15458b04ffc1Sbeveloper 	rv = MediaRosterEx(this)->GetAllOutputs(node, &list);
15463620737cSbeveloper 	if (B_OK != rv)
15473620737cSbeveloper 		return rv;
15483620737cSbeveloper 
15495ac4fbd7Sbeveloper 	PRINT(4, "BMediaRoster::GetAllOutputsFor node %ld, max %ld\n", node.node, buf_num_outputs);
15505ac4fbd7Sbeveloper 
155176669a29Sbeveloper 	int32 i;
155276669a29Sbeveloper 	for (i = 0, list.Rewind(); list.GetNext(&output); i++) {
15533620737cSbeveloper 		out_outputs[i] = *output;
155452a38012Sejakowatz 		*out_total_count += 1;
15553620737cSbeveloper 		buf_num_outputs -= 1;
15565ac4fbd7Sbeveloper 		#if DEBUG >= 3
15575ac4fbd7Sbeveloper 			PRINT_OUTPUT("  output ", out_outputs[i]);
15585ac4fbd7Sbeveloper 		#endif
15593620737cSbeveloper 		if (buf_num_outputs == 0)
15603620737cSbeveloper 			break;
156152a38012Sejakowatz 	}
156252a38012Sejakowatz 
15638b04ffc1Sbeveloper 	MediaRosterEx(this)->PublishOutputs(node, &list);
15643620737cSbeveloper 	return B_OK;
156552a38012Sejakowatz }
156652a38012Sejakowatz 
156752a38012Sejakowatz 
156852a38012Sejakowatz status_t
156952a38012Sejakowatz BMediaRoster::StartWatching(const BMessenger & where)
157052a38012Sejakowatz {
1571eae26d3dSbeveloper 	CALLED();
1572eae26d3dSbeveloper 	if (!where.IsValid()) {
15735ac4fbd7Sbeveloper 		ERROR("BMediaRoster::StartWatching: messenger invalid!\n");
1574eae26d3dSbeveloper 		return B_BAD_VALUE;
1575eae26d3dSbeveloper 	}
1576f4925104Sbeveloper 	return BPrivate::media::notifications::Register(where, media_node::null, B_MEDIA_WILDCARD);
157752a38012Sejakowatz }
157852a38012Sejakowatz 
157952a38012Sejakowatz 
158052a38012Sejakowatz status_t
158152a38012Sejakowatz BMediaRoster::StartWatching(const BMessenger & where,
158252a38012Sejakowatz 							int32 notificationType)
158352a38012Sejakowatz {
1584eae26d3dSbeveloper 	CALLED();
1585eae26d3dSbeveloper 	if (!where.IsValid()) {
15865ac4fbd7Sbeveloper 		ERROR("BMediaRoster::StartWatching: messenger invalid!\n");
1587eae26d3dSbeveloper 		return B_BAD_VALUE;
1588eae26d3dSbeveloper 	}
1589f4925104Sbeveloper 	if (false == BPrivate::media::notifications::IsValidNotificationRequest(false, notificationType)) {
15905ac4fbd7Sbeveloper 		ERROR("BMediaRoster::StartWatching: notificationType invalid!\n");
1591eae26d3dSbeveloper 		return B_BAD_VALUE;
1592eae26d3dSbeveloper 	}
1593f4925104Sbeveloper 	return BPrivate::media::notifications::Register(where, media_node::null, notificationType);
159452a38012Sejakowatz }
159552a38012Sejakowatz 
159652a38012Sejakowatz 
159752a38012Sejakowatz status_t
159852a38012Sejakowatz BMediaRoster::StartWatching(const BMessenger & where,
159952a38012Sejakowatz 							const media_node & node,
160052a38012Sejakowatz 							int32 notificationType)
160152a38012Sejakowatz {
1602eae26d3dSbeveloper 	CALLED();
1603eae26d3dSbeveloper 	if (!where.IsValid()) {
16045ac4fbd7Sbeveloper 		ERROR("BMediaRoster::StartWatching: messenger invalid!\n");
1605eae26d3dSbeveloper 		return B_BAD_VALUE;
1606eae26d3dSbeveloper 	}
160740f36b03Sbeveloper 	if (IS_INVALID_NODE(node)) {
16085ac4fbd7Sbeveloper 		ERROR("BMediaRoster::StartWatching: node invalid!\n");
1609eae26d3dSbeveloper 		return B_MEDIA_BAD_NODE;
1610eae26d3dSbeveloper 	}
1611f4925104Sbeveloper 	if (false == BPrivate::media::notifications::IsValidNotificationRequest(true, notificationType)) {
16125ac4fbd7Sbeveloper 		ERROR("BMediaRoster::StartWatching: notificationType invalid!\n");
1613eae26d3dSbeveloper 		return B_BAD_VALUE;
1614eae26d3dSbeveloper 	}
1615f4925104Sbeveloper 	return BPrivate::media::notifications::Register(where, node, notificationType);
161652a38012Sejakowatz }
161752a38012Sejakowatz 
161852a38012Sejakowatz 
161952a38012Sejakowatz status_t
162052a38012Sejakowatz BMediaRoster::StopWatching(const BMessenger & where)
162152a38012Sejakowatz {
1622eae26d3dSbeveloper 	CALLED();
1623eae26d3dSbeveloper 	// messenger may already be invalid, so we don't check this
1624f4925104Sbeveloper 	return BPrivate::media::notifications::Unregister(where, media_node::null, B_MEDIA_WILDCARD);
162552a38012Sejakowatz }
162652a38012Sejakowatz 
162752a38012Sejakowatz 
162852a38012Sejakowatz status_t
162952a38012Sejakowatz BMediaRoster::StopWatching(const BMessenger & where,
163052a38012Sejakowatz 						   int32 notificationType)
163152a38012Sejakowatz {
1632eae26d3dSbeveloper 	CALLED();
1633eae26d3dSbeveloper 	// messenger may already be invalid, so we don't check this
1634f4925104Sbeveloper 	if (false == BPrivate::media::notifications::IsValidNotificationRequest(false, notificationType)) {
16355ac4fbd7Sbeveloper 		ERROR("BMediaRoster::StopWatching: notificationType invalid!\n");
1636eae26d3dSbeveloper 		return B_BAD_VALUE;
1637eae26d3dSbeveloper 	}
1638f4925104Sbeveloper 	return BPrivate::media::notifications::Unregister(where, media_node::null, notificationType);
163952a38012Sejakowatz }
164052a38012Sejakowatz 
164152a38012Sejakowatz 
164252a38012Sejakowatz status_t
164352a38012Sejakowatz BMediaRoster::StopWatching(const BMessenger & where,
164452a38012Sejakowatz 						   const media_node & node,
164552a38012Sejakowatz 						   int32 notificationType)
164652a38012Sejakowatz {
1647eae26d3dSbeveloper 	CALLED();
1648eae26d3dSbeveloper 	// messenger may already be invalid, so we don't check this
164940f36b03Sbeveloper 	if (IS_INVALID_NODE(node)) {
16505ac4fbd7Sbeveloper 		ERROR("BMediaRoster::StopWatching: node invalid!\n");
1651eae26d3dSbeveloper 		return B_MEDIA_BAD_NODE;
1652eae26d3dSbeveloper 	}
1653f4925104Sbeveloper 	if (false == BPrivate::media::notifications::IsValidNotificationRequest(true, notificationType)) {
16545ac4fbd7Sbeveloper 		ERROR("BMediaRoster::StopWatching: notificationType invalid!\n");
1655eae26d3dSbeveloper 		return B_BAD_VALUE;
1656eae26d3dSbeveloper 	}
1657f4925104Sbeveloper 	return BPrivate::media::notifications::Unregister(where, node, notificationType);
165852a38012Sejakowatz }
165952a38012Sejakowatz 
166052a38012Sejakowatz 
166152a38012Sejakowatz status_t
166252a38012Sejakowatz BMediaRoster::RegisterNode(BMediaNode * node)
166352a38012Sejakowatz {
166454187cc6Sbeveloper 	CALLED();
166554187cc6Sbeveloper 	// addon-id = -1 (unused), addon-flavor-id = 0 (unused, too)
166654187cc6Sbeveloper 	return MediaRosterEx(this)->RegisterNode(node, -1, 0);
166754187cc6Sbeveloper }
166854187cc6Sbeveloper 
166954187cc6Sbeveloper 
167054187cc6Sbeveloper status_t
167154187cc6Sbeveloper BMediaRosterEx::RegisterNode(BMediaNode * node, media_addon_id addonid, int32 flavorid)
167254187cc6Sbeveloper {
167352a38012Sejakowatz 	CALLED();
167452a38012Sejakowatz 	if (node == NULL)
167552a38012Sejakowatz 		return B_BAD_VALUE;
167652a38012Sejakowatz 
167754187cc6Sbeveloper 	// some sanity check
167854187cc6Sbeveloper 	// I'm not sure if the media kit warrants to call BMediaNode::AddOn() here.
167954187cc6Sbeveloper 	// Perhaps we don't need it.
168054187cc6Sbeveloper 	{
16819e9417d2Sbeveloper 		BMediaAddOn *addon;
16829e9417d2Sbeveloper 		int32 addon_flavor_id;
16839e9417d2Sbeveloper 		media_addon_id addon_id;
16849e9417d2Sbeveloper 		addon_flavor_id = 0;
16859e9417d2Sbeveloper 		addon = node->AddOn(&addon_flavor_id);
16869e9417d2Sbeveloper 		addon_id = addon ? addon->AddonID() : -1;
168754187cc6Sbeveloper 		ASSERT(addonid == addon_id);
168854187cc6Sbeveloper 		ASSERT(flavorid == addon_flavor_id);
168954187cc6Sbeveloper 	}
169052a38012Sejakowatz 
169154187cc6Sbeveloper 	status_t rv;
16929e9417d2Sbeveloper 	server_register_node_request request;
16939e9417d2Sbeveloper 	server_register_node_reply reply;
16949e9417d2Sbeveloper 
169554187cc6Sbeveloper 	request.addon_id = addonid;
169654187cc6Sbeveloper 	request.addon_flavor_id = flavorid;
16979e9417d2Sbeveloper 	strcpy(request.name, node->Name());
16989e9417d2Sbeveloper 	request.kinds = node->Kinds();
16999e9417d2Sbeveloper 	request.port = node->ControlPort();
17009e9417d2Sbeveloper 	request.team = team;
17019e9417d2Sbeveloper 
17028b04ffc1Sbeveloper 	TRACE("BMediaRoster::RegisterNode: sending SERVER_REGISTER_NODE: port %ld, kinds 0x%Lx, team %ld, name '%s'\n", request.port, request.kinds, request.team, request.name);
17031299bfb2Sbeveloper 
17049e9417d2Sbeveloper 	rv = QueryServer(SERVER_REGISTER_NODE, &request, sizeof(request), &reply, sizeof(reply));
17059e9417d2Sbeveloper 	if (rv != B_OK) {
17065ac4fbd7Sbeveloper 		ERROR("BMediaRoster::RegisterNode: failed to register node %s (error %#lx)\n", node->Name(), rv);
17079e9417d2Sbeveloper 		return rv;
17089e9417d2Sbeveloper 	}
17099e9417d2Sbeveloper 
17104295907bSbeveloper 	TRACE("BMediaRoster::RegisterNode: QueryServer SERVER_REGISTER_NODE finished\n");
17114295907bSbeveloper 
17128b04ffc1Sbeveloper 	// we are a friend class of BMediaNode and initialize this member variable
17139e9417d2Sbeveloper 	node->fNodeID = reply.nodeid;
17149e9417d2Sbeveloper 	ASSERT(reply.nodeid == node->Node().node);
17159e9417d2Sbeveloper 	ASSERT(reply.nodeid == node->ID());
17169e9417d2Sbeveloper 
17179e9417d2Sbeveloper 	// call the callback
17189e9417d2Sbeveloper 	node->NodeRegistered();
17193620737cSbeveloper 
17204295907bSbeveloper 	TRACE("BMediaRoster::RegisterNode: NodeRegistered callback finished\n");
17214295907bSbeveloper 
17220e21b167Sbeveloper 	// if the BMediaNode also inherits from BTimeSource, we need to call BTimeSource::FinishCreate()
17230e21b167Sbeveloper 	if (node->Kinds() & B_TIME_SOURCE) {
17240e21b167Sbeveloper 		BTimeSource *ts;
17250e21b167Sbeveloper 		ts = dynamic_cast<BTimeSource *>(node);
17260e21b167Sbeveloper 		if (ts)
17270e21b167Sbeveloper 			ts->FinishCreate();
17280e21b167Sbeveloper 	}
17290e21b167Sbeveloper 
17304295907bSbeveloper 	TRACE("BMediaRoster::RegisterNode: publishing inputs/outputs\n");
17314295907bSbeveloper 
17323620737cSbeveloper 	// register existing inputs and outputs with the
17333620737cSbeveloper 	// media_server, this allows GetLiveNodes() to work
17343620737cSbeveloper 	// with created, but unconnected nodes.
17354d2d96e0Sbeveloper 	// The node control loop might not be running, or might deadlock
17364d2d96e0Sbeveloper 	// if we send a message and wait for a reply here.
17374d2d96e0Sbeveloper 	// We have a pointer to the node, and thus call the functions directly
17384295907bSbeveloper 
17393620737cSbeveloper 	if (node->Kinds() & B_BUFFER_PRODUCER) {
17404d2d96e0Sbeveloper 		BBufferProducer *bp;
17414d2d96e0Sbeveloper 		bp = dynamic_cast<BBufferProducer *>(node);
17424d2d96e0Sbeveloper 		if (bp) {
1743359ac306Sbeveloper 			List<media_output> list;
17444d2d96e0Sbeveloper 			if (B_OK == GetAllOutputs(bp, &list))
1745359ac306Sbeveloper 				PublishOutputs(node->Node(), &list);
174621871f38Sbeveloper 		}
17474d2d96e0Sbeveloper 	}
174821871f38Sbeveloper 	if (node->Kinds() & B_BUFFER_CONSUMER) {
17494d2d96e0Sbeveloper 		BBufferConsumer *bc;
17504d2d96e0Sbeveloper 		bc = dynamic_cast<BBufferConsumer *>(node);
17514d2d96e0Sbeveloper 		if (bc) {
1752359ac306Sbeveloper 			List<media_input> list;
17534d2d96e0Sbeveloper 			if (B_OK == GetAllInputs(bc, &list))
1754359ac306Sbeveloper 				PublishInputs(node->Node(), &list);
17553620737cSbeveloper 		}
17564d2d96e0Sbeveloper 	}
175721871f38Sbeveloper 
17584295907bSbeveloper 	TRACE("BMediaRoster::RegisterNode: sending NodesCreated\n");
17594295907bSbeveloper 
17601299bfb2Sbeveloper 	BPrivate::media::notifications::NodesCreated(&reply.nodeid, 1);
17614295907bSbeveloper 
17624295907bSbeveloper 	TRACE("BMediaRoster::RegisterNode: finished\n");
17634295907bSbeveloper 
1764570f7d04Sbeveloper /*
1765570f7d04Sbeveloper 	TRACE("BMediaRoster::RegisterNode: registered node name '%s', id %ld, addon %ld, flavor %ld\n", node->Name(), node->ID(), addon_id, addon_flavor_id);
1766570f7d04Sbeveloper 	TRACE("BMediaRoster::RegisterNode: node this               %p\n", node);
1767570f7d04Sbeveloper 	TRACE("BMediaRoster::RegisterNode: node fConsumerThis      %p\n", node->fConsumerThis);
1768570f7d04Sbeveloper 	TRACE("BMediaRoster::RegisterNode: node fProducerThis      %p\n", node->fProducerThis);
1769570f7d04Sbeveloper 	TRACE("BMediaRoster::RegisterNode: node fFileInterfaceThis %p\n", node->fFileInterfaceThis);
1770570f7d04Sbeveloper 	TRACE("BMediaRoster::RegisterNode: node fControllableThis  %p\n", node->fControllableThis);
1771570f7d04Sbeveloper 	TRACE("BMediaRoster::RegisterNode: node fTimeSourceThis    %p\n", node->fTimeSourceThis);
1772570f7d04Sbeveloper */
17739e9417d2Sbeveloper 	return B_OK;
177452a38012Sejakowatz }
177552a38012Sejakowatz 
177652a38012Sejakowatz 
177752a38012Sejakowatz status_t
177852a38012Sejakowatz BMediaRoster::UnregisterNode(BMediaNode * node)
177952a38012Sejakowatz {
17809e9417d2Sbeveloper 	CALLED();
17819e9417d2Sbeveloper 	if (node == NULL)
17829e9417d2Sbeveloper 		return B_BAD_VALUE;
17839e9417d2Sbeveloper 
178460f15390Sbeveloper 	TRACE("BMediaRoster::UnregisterNode %ld (%p)\n", node->ID(), node);
178560f15390Sbeveloper 
178686bce45bSbeveloper 	if (node->fKinds & NODE_KIND_NO_REFCOUNTING) {
178786bce45bSbeveloper 		printf("BMediaRoster::UnregisterNode, trying to unregister reference counting disabled timesource, node %ld, port %ld, team %ld\n", node->ID(), node->ControlPort(), team);
178886bce45bSbeveloper 		return B_OK;
178986bce45bSbeveloper 	}
17908b04ffc1Sbeveloper 	if (node->ID() == NODE_UNREGISTERED_ID) {
17915ac4fbd7Sbeveloper 		PRINT(1, "Warning: BMediaRoster::UnregisterNode: node id %ld, name '%s' already unregistered\n", node->ID(), node->Name());
17929e9417d2Sbeveloper 		return B_OK;
17939e9417d2Sbeveloper 	}
179454187cc6Sbeveloper 	if (node->fRefCount != 0) {
17955ac4fbd7Sbeveloper 		PRINT(1, "Warning: BMediaRoster::UnregisterNode: node id %ld, name '%s' has local reference count of %ld\n", node->ID(), node->Name(), node->fRefCount);
179654187cc6Sbeveloper 		// no return here, we continue and unregister!
179754187cc6Sbeveloper 	}
179854187cc6Sbeveloper 
179954187cc6Sbeveloper 	// Calling BMediaAddOn::GetConfigurationFor(BMediaNode *node, BMessage *config)
180054187cc6Sbeveloper 	// if this node was instanciated by an add-on needs to be done *somewhere*
180154187cc6Sbeveloper 	// We can't do it here because it is already to late (destructor of the node
180254187cc6Sbeveloper 	// might have been called).
18039e9417d2Sbeveloper 
18049e9417d2Sbeveloper 	server_unregister_node_request request;
18059e9417d2Sbeveloper 	server_unregister_node_reply reply;
18069e9417d2Sbeveloper 	status_t rv;
18079e9417d2Sbeveloper 
18089e9417d2Sbeveloper 	request.nodeid = node->ID();
18099e9417d2Sbeveloper 	request.team = team;
18109e9417d2Sbeveloper 
18111299bfb2Sbeveloper 	// send a notification
18121299bfb2Sbeveloper 	BPrivate::media::notifications::NodesDeleted(&request.nodeid, 1);
18131299bfb2Sbeveloper 
18149e9417d2Sbeveloper 	rv = QueryServer(SERVER_UNREGISTER_NODE, &request, sizeof(request), &reply, sizeof(reply));
18159e9417d2Sbeveloper 	if (rv != B_OK) {
18165ac4fbd7Sbeveloper 		ERROR("BMediaRoster::UnregisterNode: failed to unregister node id %ld, name '%s' (error %#lx)\n", node->ID(), node->Name(), rv);
18179e9417d2Sbeveloper 		return rv;
18189e9417d2Sbeveloper 	}
18199e9417d2Sbeveloper 
182054187cc6Sbeveloper 	if (reply.addonid != -1) {
182154187cc6Sbeveloper 		// Small problem here, we can't use DormantNodeManager::PutAddon(), as
182254187cc6Sbeveloper 		// UnregisterNode() is called by a dormant node itself (by the destructor).
182354187cc6Sbeveloper 		// The add-on that contains the node needs to remain in memory until the
182454187cc6Sbeveloper 		// destructor execution is finished.
182554187cc6Sbeveloper 		// DormantNodeManager::PutAddonDelayed() will delay unloading.
182654187cc6Sbeveloper 		_DormantNodeManager->PutAddonDelayed(reply.addonid);
1827cf4e2277Sbeveloper 
182873794717Sbeveloper 		rv = MediaRosterEx(this)->DecrementAddonFlavorInstancesCount(reply.addonid, reply.flavorid);
182954187cc6Sbeveloper 		if (rv != B_OK) {
18305ac4fbd7Sbeveloper 			ERROR("BMediaRoster::UnregisterNode: DecrementAddonFlavorInstancesCount failed\n");
183154187cc6Sbeveloper 			// this is really a problem, but we can't fail now
183254187cc6Sbeveloper 		}
18338b04ffc1Sbeveloper 	}
18349e9417d2Sbeveloper 
18351299bfb2Sbeveloper 	// we are a friend class of BMediaNode and invalidate this member variable
18368b04ffc1Sbeveloper 	node->fNodeID = NODE_UNREGISTERED_ID;
18379e9417d2Sbeveloper 
18389e9417d2Sbeveloper 	return B_OK;
183952a38012Sejakowatz }
184052a38012Sejakowatz 
184152a38012Sejakowatz 
184252a38012Sejakowatz //	thread safe for multiple calls to Roster()
184352a38012Sejakowatz /* static */ BMediaRoster *
184452a38012Sejakowatz BMediaRoster::Roster(status_t* out_error)
184552a38012Sejakowatz {
184652a38012Sejakowatz 	static BLocker locker("BMediaRoster::Roster locker");
184752a38012Sejakowatz 	locker.Lock();
184852a38012Sejakowatz 	if (_sDefault == NULL) {
18498b04ffc1Sbeveloper 		_sDefault = new BMediaRosterEx();
185052a38012Sejakowatz 		if (out_error != NULL)
185152a38012Sejakowatz 			*out_error = B_OK;
185252a38012Sejakowatz 	} else {
185352a38012Sejakowatz 		if (out_error != NULL)
185452a38012Sejakowatz 			*out_error = B_OK;
185552a38012Sejakowatz 	}
185652a38012Sejakowatz 	locker.Unlock();
185752a38012Sejakowatz 	return _sDefault;
185852a38012Sejakowatz }
185952a38012Sejakowatz 
186052a38012Sejakowatz 
186152a38012Sejakowatz //	won't create it if there isn't one
186252a38012Sejakowatz //	not thread safe if you call Roster() at the same time
186352a38012Sejakowatz /* static */ BMediaRoster *
186452a38012Sejakowatz BMediaRoster::CurrentRoster()
186552a38012Sejakowatz {
186652a38012Sejakowatz 	return _sDefault;
186752a38012Sejakowatz }
186852a38012Sejakowatz 
186952a38012Sejakowatz 
187052a38012Sejakowatz status_t
187152a38012Sejakowatz BMediaRoster::SetTimeSourceFor(media_node_id node,
187252a38012Sejakowatz 							   media_node_id time_source)
187352a38012Sejakowatz {
1874aac800c2Sbeveloper 	CALLED();
187540f36b03Sbeveloper 	if (IS_INVALID_NODEID(node) || IS_INVALID_NODEID(time_source))
1876aac800c2Sbeveloper 		return B_BAD_VALUE;
1877aac800c2Sbeveloper 
1878aac800c2Sbeveloper 	media_node clone;
1879aac800c2Sbeveloper 	status_t rv, result;
1880aac800c2Sbeveloper 
18815917dd5bSbeveloper 	TRACE("BMediaRoster::SetTimeSourceFor: node %ld will be assigned time source %ld\n", node, time_source);
18825917dd5bSbeveloper 
18835917dd5bSbeveloper 	printf("BMediaRoster::SetTimeSourceFor: node %ld time source %ld enter\n", node, time_source);
18845917dd5bSbeveloper 
188586bce45bSbeveloper 	// we need to get a clone of the node to have a port id
1886aac800c2Sbeveloper 	rv = GetNodeFor(node, &clone);
1887aac800c2Sbeveloper 	if (rv != B_OK) {
18885ac4fbd7Sbeveloper 		ERROR("BMediaRoster::SetTimeSourceFor, GetNodeFor failed, node id %ld\n", node);
188952a38012Sejakowatz 		return B_ERROR;
189052a38012Sejakowatz 	}
189152a38012Sejakowatz 
189286bce45bSbeveloper 	// we just send the request to set time_source-id as timesource to the node,
189386bce45bSbeveloper 	// the NODE_SET_TIMESOURCE handler code will do the real assignment
1894aac800c2Sbeveloper 	result = B_OK;
1895aac800c2Sbeveloper 	node_set_timesource_command cmd;
1896aac800c2Sbeveloper 	cmd.timesource_id = time_source;
1897aac800c2Sbeveloper 	rv = SendToPort(clone.port, NODE_SET_TIMESOURCE, &cmd, sizeof(cmd));
1898aac800c2Sbeveloper 	if (rv != B_OK) {
18995ac4fbd7Sbeveloper 		ERROR("BMediaRoster::SetTimeSourceFor, sending NODE_SET_TIMESOURCE failed, node id %ld\n", node);
1900aac800c2Sbeveloper 		result = B_ERROR;
1901aac800c2Sbeveloper 	}
1902aac800c2Sbeveloper 
190360f15390Sbeveloper 	// we release the clone
1904aac800c2Sbeveloper 	rv = ReleaseNode(clone);
1905aac800c2Sbeveloper 	if (rv != B_OK) {
19065ac4fbd7Sbeveloper 		ERROR("BMediaRoster::SetTimeSourceFor, ReleaseNode failed, node id %ld\n", node);
1907aac800c2Sbeveloper 		result = B_ERROR;
1908aac800c2Sbeveloper 	}
1909aac800c2Sbeveloper 
19105917dd5bSbeveloper 	printf("BMediaRoster::SetTimeSourceFor: node %ld time source %ld leave\n", node, time_source);
19115917dd5bSbeveloper 
1912aac800c2Sbeveloper 	return result;
1913aac800c2Sbeveloper }
1914aac800c2Sbeveloper 
191552a38012Sejakowatz 
191652a38012Sejakowatz status_t
191752a38012Sejakowatz BMediaRoster::GetParameterWebFor(const media_node & node,
191852a38012Sejakowatz 								 BParameterWeb ** out_web)
191952a38012Sejakowatz {
192028ad138aSbeveloper 	CALLED();
192128ad138aSbeveloper 	if (out_web == NULL)
192228ad138aSbeveloper 		return B_BAD_VALUE;
192328ad138aSbeveloper 	if (IS_INVALID_NODE(node))
192428ad138aSbeveloper 		return B_MEDIA_BAD_NODE;
192528ad138aSbeveloper 	if ((node.kind & B_CONTROLLABLE) == 0)
192628ad138aSbeveloper 		return B_MEDIA_BAD_NODE;
192728ad138aSbeveloper 
192828ad138aSbeveloper 	controllable_get_parameter_web_request request;
192928ad138aSbeveloper 	controllable_get_parameter_web_reply reply;
193028ad138aSbeveloper 	int32 requestsize[] = {B_PAGE_SIZE, 4*B_PAGE_SIZE, 16*B_PAGE_SIZE, 64*B_PAGE_SIZE, 128*B_PAGE_SIZE, 256*B_PAGE_SIZE, 0};
193128ad138aSbeveloper 	int32 size;
193228ad138aSbeveloper 
193328ad138aSbeveloper 	// XXX it might be better to query the node for the (current) parameter size first
193428ad138aSbeveloper 	for (int i = 0; (size = requestsize[i]) != 0; i++) {
193528ad138aSbeveloper 		status_t rv;
193628ad138aSbeveloper 		area_id area;
193728ad138aSbeveloper 		void *data;
193828ad138aSbeveloper 		area = create_area("parameter web data", &data, B_ANY_ADDRESS, size, B_NO_LOCK, B_READ_AREA | B_WRITE_AREA);
193928ad138aSbeveloper 		if (area < B_OK) {
19405ac4fbd7Sbeveloper 			ERROR("BMediaRoster::GetParameterWebFor couldn't create area of size %ld\n", size);
194128ad138aSbeveloper 			return B_ERROR;
194228ad138aSbeveloper 		}
194328ad138aSbeveloper 		request.maxsize = size;
194428ad138aSbeveloper 		request.area = area;
194528ad138aSbeveloper 		rv = QueryPort(node.port, CONTROLLABLE_GET_PARAMETER_WEB, &request, sizeof(request), &reply, sizeof(reply));
194628ad138aSbeveloper 		if (rv != B_OK) {
19475ac4fbd7Sbeveloper 			ERROR("BMediaRoster::GetParameterWebFor CONTROLLABLE_GET_PARAMETER_WEB failed\n");
194828ad138aSbeveloper 			delete_area(area);
194928ad138aSbeveloper 			return B_ERROR;
195028ad138aSbeveloper 		}
195128ad138aSbeveloper 		if (reply.size == 0) {
195228ad138aSbeveloper 			// no parameter web available
195328ad138aSbeveloper 			// XXX should we return an error?
19545ac4fbd7Sbeveloper 			ERROR("BMediaRoster::GetParameterWebFor node %ld has no parameter web\n", node.node);
195528ad138aSbeveloper 			*out_web = new BParameterWeb();
195628ad138aSbeveloper 			delete_area(area);
195760f15390Sbeveloper 			return B_OK;
195852a38012Sejakowatz 		}
195928ad138aSbeveloper 		if (reply.size > 0) {
196028ad138aSbeveloper 			// we got a flattened parameter web!
196128ad138aSbeveloper 			*out_web = new BParameterWeb();
196228ad138aSbeveloper 
1963d91580cdSbeveloper 			printf("BMediaRoster::GetParameterWebFor Unflattening %ld bytes, 0x%08lx, 0x%08lx, 0x%08lx, 0x%08lx\n",
196428ad138aSbeveloper 				reply.size, ((uint32*)data)[0], ((uint32*)data)[1], ((uint32*)data)[2], ((uint32*)data)[3]);
196528ad138aSbeveloper 
196628ad138aSbeveloper 			rv = (*out_web)->Unflatten(reply.code, data, reply.size);
196728ad138aSbeveloper 			if (rv != B_OK) {
19685ac4fbd7Sbeveloper 				ERROR("BMediaRoster::GetParameterWebFor Unflatten failed, %s\n", strerror(rv));
196928ad138aSbeveloper 				delete_area(area);
197028ad138aSbeveloper 				delete *out_web;
197128ad138aSbeveloper 				return B_ERROR;
197228ad138aSbeveloper 			}
197328ad138aSbeveloper 			delete_area(area);
197428ad138aSbeveloper 			return B_OK;
197528ad138aSbeveloper 		}
197628ad138aSbeveloper 		delete_area(area);
197728ad138aSbeveloper 		ASSERT(reply.size == -1);
197828ad138aSbeveloper 		// parameter web data was too large
197928ad138aSbeveloper 		// loop and try a larger size
198028ad138aSbeveloper 	}
19815ac4fbd7Sbeveloper 	ERROR("BMediaRoster::GetParameterWebFor node %ld has no parameter web larger than %ld\n", node.node, size);
198228ad138aSbeveloper 	return B_ERROR;
198328ad138aSbeveloper }
198452a38012Sejakowatz 
198552a38012Sejakowatz 
198652a38012Sejakowatz status_t
198752a38012Sejakowatz BMediaRoster::StartControlPanel(const media_node & node,
198852a38012Sejakowatz 								BMessenger * out_messenger)
198952a38012Sejakowatz {
199052a38012Sejakowatz 	UNIMPLEMENTED();
199152a38012Sejakowatz 	return B_ERROR;
199252a38012Sejakowatz }
199352a38012Sejakowatz 
199452a38012Sejakowatz 
199552a38012Sejakowatz status_t
199652a38012Sejakowatz BMediaRoster::GetDormantNodes(dormant_node_info * out_info,
199752a38012Sejakowatz 							  int32 * io_count,
199852a38012Sejakowatz 							  const media_format * has_input /* = NULL */,
199952a38012Sejakowatz 							  const media_format * has_output /* = NULL */,
200052a38012Sejakowatz 							  const char * name /* = NULL */,
200152a38012Sejakowatz 							  uint64 require_kinds /* = NULL */,
200252a38012Sejakowatz 							  uint64 deny_kinds /* = NULL */)
200352a38012Sejakowatz {
200452a38012Sejakowatz 	CALLED();
200552a38012Sejakowatz 	if (out_info == NULL)
200652a38012Sejakowatz 		return B_BAD_VALUE;
200752a38012Sejakowatz 	if (io_count == NULL)
200852a38012Sejakowatz 		return B_BAD_VALUE;
200952a38012Sejakowatz 	if (*io_count <= 0)
201052a38012Sejakowatz 		return B_BAD_VALUE;
201152a38012Sejakowatz 
201252a38012Sejakowatz 	xfer_server_get_dormant_nodes msg;
201352a38012Sejakowatz 	port_id port;
201452a38012Sejakowatz 	status_t rv;
201552a38012Sejakowatz 
20164295907bSbeveloper 	port = find_port(MEDIA_SERVER_PORT_NAME);
201752a38012Sejakowatz 	if (port <= B_OK)
201852a38012Sejakowatz 		return B_ERROR;
201952a38012Sejakowatz 
202052a38012Sejakowatz 	msg.maxcount = *io_count;
202152a38012Sejakowatz 	msg.has_input = (bool) has_input;
202252a38012Sejakowatz 	if (has_input)
202352a38012Sejakowatz 		msg.inputformat = *has_input; // XXX we should not make a flat copy of media_format
202452a38012Sejakowatz 	msg.has_output = (bool) has_output;
202552a38012Sejakowatz 	if (has_output)
202652a38012Sejakowatz 		msg.outputformat = *has_output;; // XXX we should not make a flat copy of media_format
202752a38012Sejakowatz 	msg.has_name = (bool) name;
202852a38012Sejakowatz 	if (name) {
20299e9417d2Sbeveloper 		int len = strlen(name);
20309e9417d2Sbeveloper 		len = min_c(len, (int)sizeof(msg.name) - 1);
203152a38012Sejakowatz 		memcpy(msg.name, name, len);
203252a38012Sejakowatz 		msg.name[len] = 0;
203352a38012Sejakowatz 	}
203452a38012Sejakowatz 	msg.require_kinds = require_kinds;
203552a38012Sejakowatz 	msg.deny_kinds = deny_kinds;
203652a38012Sejakowatz 	msg.reply_port = _PortPool->GetPort();
203752a38012Sejakowatz 
203852a38012Sejakowatz 	rv = write_port(port, SERVER_GET_DORMANT_NODES, &msg, sizeof(msg));
203952a38012Sejakowatz 	if (rv != B_OK) {
204052a38012Sejakowatz 		_PortPool->PutPort(msg.reply_port);
204152a38012Sejakowatz 		return rv;
204252a38012Sejakowatz 	}
204352a38012Sejakowatz 
204452a38012Sejakowatz 	xfer_server_get_dormant_nodes_reply reply;
204552a38012Sejakowatz 	int32 code;
204652a38012Sejakowatz 
204752a38012Sejakowatz 	rv = read_port(msg.reply_port, &code, &reply, sizeof(reply));
204852a38012Sejakowatz 	if (rv < B_OK) {
204952a38012Sejakowatz 		_PortPool->PutPort(msg.reply_port);
205052a38012Sejakowatz 		return rv;
205152a38012Sejakowatz 	}
205252a38012Sejakowatz 
205352a38012Sejakowatz 	*io_count = reply.count;
205452a38012Sejakowatz 
205552a38012Sejakowatz 	if (*io_count > 0) {
205652a38012Sejakowatz 		rv = read_port(msg.reply_port, &code, out_info, *io_count * sizeof(dormant_node_info));
205752a38012Sejakowatz 		if (rv < B_OK)
205852a38012Sejakowatz 			reply.result = rv;
205952a38012Sejakowatz 	}
206052a38012Sejakowatz 	_PortPool->PutPort(msg.reply_port);
206152a38012Sejakowatz 
206252a38012Sejakowatz 	return reply.result;
206352a38012Sejakowatz }
206452a38012Sejakowatz 
20658b04ffc1Sbeveloper /* This function is used to do the real work of instantiating a dormant node. It is either
20668b04ffc1Sbeveloper  * called by the media_addon_server to instantiate a global node, or it gets called from
20678b04ffc1Sbeveloper  * BMediaRoster::InstantiateDormantNode() to create a local one.
20688b04ffc1Sbeveloper  *
20698b04ffc1Sbeveloper  * Checks concerning global/local are not done here.
20708b04ffc1Sbeveloper  */
207152a38012Sejakowatz status_t
207254187cc6Sbeveloper BMediaRosterEx::InstantiateDormantNode(media_addon_id addonid, int32 flavorid, team_id creator, media_node *out_node)
207352a38012Sejakowatz {
207454187cc6Sbeveloper 	// This function is always called from the correct context, if the node
207554187cc6Sbeveloper 	// is supposed to be global, it is called from the media_addon_server.
207654187cc6Sbeveloper 
207752a38012Sejakowatz 	// if B_FLAVOR_IS_GLOBAL, we need to use the BMediaAddOn object that
207852a38012Sejakowatz 	// resides in the media_addon_server
207952a38012Sejakowatz 
20808b04ffc1Sbeveloper 	// RegisterNode() must be called for nodes instantiated from add-ons,
20818b04ffc1Sbeveloper 	// since the media kit warrants that it's done automatically.
208252a38012Sejakowatz 
208354187cc6Sbeveloper 	// addonid		Indicates the ID number of the media add-on in which the node resides.
208454187cc6Sbeveloper 	// flavorid		Indicates the internal ID number that the add-on uses to identify the flavor,
208554187cc6Sbeveloper 	//				this is the number that was published by BMediaAddOn::GetFlavorAt() in the
20868b04ffc1Sbeveloper 	//				flavor_info::internal_id field.
208754187cc6Sbeveloper 	// creator		The creator team is -1 if nodes are created locally. If created globally,
208854187cc6Sbeveloper 	//				it will contain (while called in media_addon_server context) the team-id of
208954187cc6Sbeveloper 	// 				the team that requested the instantiation.
20908b04ffc1Sbeveloper 
209160f15390Sbeveloper 	TRACE("BMediaRosterEx::InstantiateDormantNode: addon-id %ld, flavor_id %ld\n", addonid, flavorid);
20928b04ffc1Sbeveloper 
20938b04ffc1Sbeveloper 	// Get flavor_info from the server
20948b04ffc1Sbeveloper 	dormant_flavor_info node_info;
20958c6a6096Sbeveloper 	status_t rv;
20968b04ffc1Sbeveloper 	rv = GetDormantFlavorInfo(addonid, flavorid, &node_info);
20978b04ffc1Sbeveloper 	if (rv != B_OK) {
20985ac4fbd7Sbeveloper 		ERROR("BMediaRosterEx::InstantiateDormantNode error: failed to get dormant_flavor_info for addon-id %ld, flavor-id %ld\n", addonid, flavorid);
209952a38012Sejakowatz 		return B_ERROR;
210052a38012Sejakowatz 	}
21018b04ffc1Sbeveloper 
2102908eaf85Sbeveloper 	//ASSERT(node_info.internal_id == flavorid);
2103908eaf85Sbeveloper 	if (node_info.internal_id != flavorid) {
21044d2d96e0Sbeveloper 		ERROR("############# BMediaRosterEx::InstantiateDormantNode failed: ID mismatch for addon-id %ld, flavor-id %ld, node_info.internal_id %ld, node_info.name %s\n", addonid, flavorid, node_info.internal_id, node_info.name);
2105908eaf85Sbeveloper 		return B_ERROR;
2106908eaf85Sbeveloper 	}
21078b04ffc1Sbeveloper 
21088b04ffc1Sbeveloper 	// load the BMediaAddOn object
21098b04ffc1Sbeveloper 	BMediaAddOn *addon;
21108b04ffc1Sbeveloper 	addon = _DormantNodeManager->GetAddon(addonid);
21118b04ffc1Sbeveloper 	if (!addon) {
21125ac4fbd7Sbeveloper 		ERROR("BMediaRosterEx::InstantiateDormantNode: GetAddon failed\n");
21138b04ffc1Sbeveloper 		return B_ERROR;
21148b04ffc1Sbeveloper 	}
21158b04ffc1Sbeveloper 
211654187cc6Sbeveloper 	// Now we need to try to increment the use count of this addon flavor
211754187cc6Sbeveloper 	// in the server. This can fail if the total number instances of this
211854187cc6Sbeveloper 	// flavor is limited.
211973794717Sbeveloper 	rv = IncrementAddonFlavorInstancesCount(addonid, flavorid);
212054187cc6Sbeveloper 	if (rv != B_OK) {
21215ac4fbd7Sbeveloper 		ERROR("BMediaRosterEx::InstantiateDormantNode error: can't create more nodes for addon-id %ld, flavor-id %ld\n", addonid, flavorid);
212254187cc6Sbeveloper 		// Put the addon back into the pool
212354187cc6Sbeveloper 		_DormantNodeManager->PutAddon(addonid);
212454187cc6Sbeveloper 		return B_ERROR;
212554187cc6Sbeveloper 	}
212654187cc6Sbeveloper 
21278b04ffc1Sbeveloper 	BMessage config;
212854187cc6Sbeveloper 	rv = LoadNodeConfiguration(addonid, flavorid, &config);
212954187cc6Sbeveloper 	if (rv != B_OK) {
21305ac4fbd7Sbeveloper 		ERROR("BMediaRosterEx::InstantiateDormantNode: couldn't load configuration for addon-id %ld, flavor-id %ld\n", addonid, flavorid);
213154187cc6Sbeveloper 		// do not return, this is a minor problem, not a reason to fail
213254187cc6Sbeveloper 	}
21338b04ffc1Sbeveloper 
21348b04ffc1Sbeveloper 	BMediaNode *node;
21358b04ffc1Sbeveloper 	status_t out_error;
21368b04ffc1Sbeveloper 
213754187cc6Sbeveloper 	out_error = B_OK;
21388b04ffc1Sbeveloper 	node = addon->InstantiateNodeFor(&node_info, &config, &out_error);
213916b7eea4Sbeveloper 	if (!node) {
21405ac4fbd7Sbeveloper 		ERROR("BMediaRosterEx::InstantiateDormantNode: InstantiateNodeFor failed\n");
214154187cc6Sbeveloper 		// Put the addon back into the pool
21428b04ffc1Sbeveloper 		_DormantNodeManager->PutAddon(addonid);
214354187cc6Sbeveloper 		// We must decrement the use count of this addon flavor in the
214454187cc6Sbeveloper 		// server to compensate the increment done in the beginning.
214573794717Sbeveloper 		rv = DecrementAddonFlavorInstancesCount(addonid, flavorid);
214654187cc6Sbeveloper 		if (rv != B_OK) {
21475ac4fbd7Sbeveloper 			ERROR("BMediaRosterEx::InstantiateDormantNode: DecrementAddonFlavorInstancesCount failed\n");
214816b7eea4Sbeveloper 		}
214954187cc6Sbeveloper 		return (out_error != B_OK) ? out_error : B_ERROR;
215054187cc6Sbeveloper 	}
215154187cc6Sbeveloper 
215254187cc6Sbeveloper 	rv = RegisterNode(node, addonid, flavorid);
21538c6a6096Sbeveloper 	if (rv != B_OK) {
21545ac4fbd7Sbeveloper 		ERROR("BMediaRosterEx::InstantiateDormantNode: RegisterNode failed\n");
21558c6a6096Sbeveloper 		delete node;
215654187cc6Sbeveloper 		// Put the addon back into the pool
21578b04ffc1Sbeveloper 		_DormantNodeManager->PutAddon(addonid);
215854187cc6Sbeveloper 		// We must decrement the use count of this addon flavor in the
215954187cc6Sbeveloper 		// server to compensate the increment done in the beginning.
216073794717Sbeveloper 		rv = DecrementAddonFlavorInstancesCount(addonid, flavorid);
216154187cc6Sbeveloper 		if (rv != B_OK) {
21625ac4fbd7Sbeveloper 			ERROR("BMediaRosterEx::InstantiateDormantNode: DecrementAddonFlavorInstancesCount failed\n");
216354187cc6Sbeveloper 		}
21648c6a6096Sbeveloper 		return B_ERROR;
21658c6a6096Sbeveloper 	}
21668c6a6096Sbeveloper 
216754187cc6Sbeveloper 	if (creator != -1) {
216854187cc6Sbeveloper 		// send a message to the server to assign team "creator" as creator of node "node->ID()"
216954187cc6Sbeveloper 		printf("!!! BMediaRosterEx::InstantiateDormantNode assigning team %ld as creator of node %ld\n", creator, node->ID());
217054187cc6Sbeveloper 		rv = MediaRosterEx(this)->SetNodeCreator(node->ID(), creator);
217154187cc6Sbeveloper 		if (rv != B_OK) {
21725ac4fbd7Sbeveloper 			ERROR("BMediaRosterEx::InstantiateDormantNode failed to assign team %ld as creator of node %ld\n", creator, node->ID());
217354187cc6Sbeveloper 			// do not return, this is a minor problem, not a reason to fail
217454187cc6Sbeveloper 		}
217554187cc6Sbeveloper 	}
217654187cc6Sbeveloper 
217754187cc6Sbeveloper 	// RegisterNode() does remember the add-on id in the server
217854187cc6Sbeveloper 	// and UnregisterNode() will call DormantNodeManager::PutAddon()
217954187cc6Sbeveloper 	// when the node is unregistered.
21808c6a6096Sbeveloper 
218116b7eea4Sbeveloper 	*out_node = node->Node();
2182cf4e2277Sbeveloper 
218360f15390Sbeveloper 	TRACE("BMediaRosterEx::InstantiateDormantNode: addon-id %ld, flavor_id %ld instanciated as node %ld, port %ld in team %ld\n", addonid, flavorid, out_node->node, out_node->port, team);
2184cf4e2277Sbeveloper 
218516b7eea4Sbeveloper 	return B_OK;
218616b7eea4Sbeveloper }
218752a38012Sejakowatz 
218852a38012Sejakowatz 
218952a38012Sejakowatz status_t
21908b04ffc1Sbeveloper BMediaRoster::InstantiateDormantNode(const dormant_node_info & in_info,
21918b04ffc1Sbeveloper 									 media_node * out_node,
21928b04ffc1Sbeveloper 									 uint32 flags /* currently 0 or B_FLAVOR_IS_GLOBAL or B_FLAVOR_IS_LOCAL */ )
21938b04ffc1Sbeveloper {
21948b04ffc1Sbeveloper 	CALLED();
21958b04ffc1Sbeveloper 	if (out_node == 0)
21968b04ffc1Sbeveloper 		return B_BAD_VALUE;
21978b04ffc1Sbeveloper 	if (in_info.addon <= 0) {
21985ac4fbd7Sbeveloper 		ERROR("BMediaRoster::InstantiateDormantNode error: addon-id %ld invalid.\n", in_info.addon);
21998b04ffc1Sbeveloper 		return B_BAD_VALUE;
22008b04ffc1Sbeveloper 	}
22018b04ffc1Sbeveloper 
2202d91580cdSbeveloper 	printf("BMediaRoster::InstantiateDormantNode: addon-id %ld, flavor_id %ld, flags 0x%lX\n", in_info.addon, in_info.flavor_id, flags);
22038b04ffc1Sbeveloper 
22048b04ffc1Sbeveloper 	// Get flavor_info from the server
22058b04ffc1Sbeveloper 	// XXX this is a little overhead, as we get the full blown dormant_flavor_info,
22068b04ffc1Sbeveloper 	// XXX but only need the flags.
22078b04ffc1Sbeveloper 	dormant_flavor_info node_info;
22088b04ffc1Sbeveloper 	status_t rv;
22098b04ffc1Sbeveloper 	rv = MediaRosterEx(this)->GetDormantFlavorInfo(in_info.addon, in_info.flavor_id, &node_info);
22108b04ffc1Sbeveloper 	if (rv != B_OK) {
22115ac4fbd7Sbeveloper 		ERROR("BMediaRoster::InstantiateDormantNode: failed to get dormant_flavor_info for addon-id %ld, flavor-id %ld\n", in_info.addon, in_info.flavor_id);
2212626824eaSbeveloper 		return B_NAME_NOT_FOUND;
22138b04ffc1Sbeveloper 	}
22148b04ffc1Sbeveloper 
22158b04ffc1Sbeveloper 	ASSERT(node_info.internal_id == in_info.flavor_id);
22168b04ffc1Sbeveloper 
2217d91580cdSbeveloper 	printf("BMediaRoster::InstantiateDormantNode: name \"%s\", info \"%s\", flavor_flags 0x%lX, internal_id %ld, possible_count %ld\n",
22188b04ffc1Sbeveloper 		node_info.name, node_info.info, node_info.flavor_flags, node_info.internal_id, node_info.possible_count);
22198b04ffc1Sbeveloper 
22208b04ffc1Sbeveloper 	#if DEBUG
22218b04ffc1Sbeveloper 		if (flags & B_FLAVOR_IS_LOCAL)
22228b04ffc1Sbeveloper 			printf("BMediaRoster::InstantiateDormantNode: caller requested B_FLAVOR_IS_LOCAL\n");
22238b04ffc1Sbeveloper 		if (flags & B_FLAVOR_IS_GLOBAL)
22248b04ffc1Sbeveloper 			printf("BMediaRoster::InstantiateDormantNode: caller requested B_FLAVOR_IS_GLOBAL\n");
22258b04ffc1Sbeveloper 		if (node_info.flavor_flags & B_FLAVOR_IS_LOCAL)
22268b04ffc1Sbeveloper 			printf("BMediaRoster::InstantiateDormantNode: node requires B_FLAVOR_IS_LOCAL\n");
22278b04ffc1Sbeveloper 		if (node_info.flavor_flags & B_FLAVOR_IS_GLOBAL)
22288b04ffc1Sbeveloper 			printf("BMediaRoster::InstantiateDormantNode: node requires B_FLAVOR_IS_GLOBAL\n");
22298b04ffc1Sbeveloper 	#endif
22308b04ffc1Sbeveloper 
22318b04ffc1Sbeveloper 	// Make sure that flags demanded by the dormant node and those requested
22328b04ffc1Sbeveloper 	// by the caller are not incompatible.
22338b04ffc1Sbeveloper 	if ((node_info.flavor_flags & B_FLAVOR_IS_GLOBAL) && (flags & B_FLAVOR_IS_LOCAL)) {
22345ac4fbd7Sbeveloper 		ERROR("BMediaRoster::InstantiateDormantNode: requested B_FLAVOR_IS_LOCAL, but dormant node has B_FLAVOR_IS_GLOBAL\n");
2235626824eaSbeveloper 		return B_NAME_NOT_FOUND;
22368b04ffc1Sbeveloper 	}
22378b04ffc1Sbeveloper 	if ((node_info.flavor_flags & B_FLAVOR_IS_LOCAL) && (flags & B_FLAVOR_IS_GLOBAL)) {
22385ac4fbd7Sbeveloper 		ERROR("BMediaRoster::InstantiateDormantNode: requested B_FLAVOR_IS_GLOBAL, but dormant node has B_FLAVOR_IS_LOCAL\n");
2239626824eaSbeveloper 		return B_NAME_NOT_FOUND;
22408b04ffc1Sbeveloper 	}
224154187cc6Sbeveloper 
22428b04ffc1Sbeveloper 	// If either the node, or the caller requested to make the instance global
22438b04ffc1Sbeveloper 	// we will do it by forwarding this request into the media_addon_server, which
22448b04ffc1Sbeveloper 	// in turn will call BMediaRosterEx::InstantiateDormantNode to create the node
22458b04ffc1Sbeveloper 	// there and make it globally available.
22468b04ffc1Sbeveloper 	if ((node_info.flavor_flags & B_FLAVOR_IS_GLOBAL) || (flags & B_FLAVOR_IS_GLOBAL)) {
22478b04ffc1Sbeveloper 
2248cf4e2277Sbeveloper 		printf("BMediaRoster::InstantiateDormantNode: creating global object in media_addon_server\n");
2249cf4e2277Sbeveloper 
22508b04ffc1Sbeveloper 		addonserver_instantiate_dormant_node_request request;
22518b04ffc1Sbeveloper 		addonserver_instantiate_dormant_node_reply reply;
22528b04ffc1Sbeveloper 		request.addonid = in_info.addon;
22538b04ffc1Sbeveloper 		request.flavorid = in_info.flavor_id;
225454187cc6Sbeveloper 		request.creator_team = team; // creator team is allowed to also release global nodes
22558b04ffc1Sbeveloper 		rv = QueryAddonServer(ADDONSERVER_INSTANTIATE_DORMANT_NODE, &request, sizeof(request), &reply, sizeof(reply));
22568b04ffc1Sbeveloper 		if (rv == B_OK) {
22578b04ffc1Sbeveloper 			*out_node = reply.node;
22588b04ffc1Sbeveloper 		}
22598b04ffc1Sbeveloper 
22608b04ffc1Sbeveloper 	} else {
22618b04ffc1Sbeveloper 
226254187cc6Sbeveloper 		// creator team = -1, as this is a local node
2263626824eaSbeveloper 		rv = MediaRosterEx(this)->InstantiateDormantNode(in_info.addon, in_info.flavor_id, -1, out_node);
2264626824eaSbeveloper 
22658b04ffc1Sbeveloper 	}
2266626824eaSbeveloper 	if (rv != B_OK) {
2267626824eaSbeveloper 		*out_node = media_node::null;
2268626824eaSbeveloper 		return B_NAME_NOT_FOUND;
2269626824eaSbeveloper 	}
2270626824eaSbeveloper 	return B_OK;
22718b04ffc1Sbeveloper }
22728b04ffc1Sbeveloper 
22738b04ffc1Sbeveloper 
22748b04ffc1Sbeveloper status_t
22758b04ffc1Sbeveloper BMediaRoster::InstantiateDormantNode(const dormant_node_info & in_info,
22768b04ffc1Sbeveloper 									 media_node * out_node)
22778b04ffc1Sbeveloper {
22788b04ffc1Sbeveloper 	return InstantiateDormantNode(in_info, out_node, 0);
22798b04ffc1Sbeveloper }
22808b04ffc1Sbeveloper 
22818b04ffc1Sbeveloper 
22828b04ffc1Sbeveloper status_t
228352a38012Sejakowatz BMediaRoster::GetDormantNodeFor(const media_node & node,
228452a38012Sejakowatz 								dormant_node_info * out_info)
228552a38012Sejakowatz {
228685dfab2bSbeveloper 	CALLED();
228785dfab2bSbeveloper 	if (out_info == NULL)
228885dfab2bSbeveloper 		return B_BAD_VALUE;
228940f36b03Sbeveloper 	if (IS_INVALID_NODE(node))
229085dfab2bSbeveloper 		return B_MEDIA_BAD_NODE;
229152a38012Sejakowatz 
229285dfab2bSbeveloper 	server_get_dormant_node_for_request request;
229385dfab2bSbeveloper 	server_get_dormant_node_for_reply reply;
229485dfab2bSbeveloper 	status_t rv;
229585dfab2bSbeveloper 
229685dfab2bSbeveloper 	request.node = node;
229785dfab2bSbeveloper 
22981299bfb2Sbeveloper 	rv = QueryServer(SERVER_GET_DORMANT_NODE_FOR, &request, sizeof(request), &reply, sizeof(reply));
229985dfab2bSbeveloper 	if (rv != B_OK)
230085dfab2bSbeveloper 		return rv;
230185dfab2bSbeveloper 
230285dfab2bSbeveloper 	*out_info = reply.node_info;
230385dfab2bSbeveloper 	return B_OK;
230452a38012Sejakowatz }
230552a38012Sejakowatz 
230652a38012Sejakowatz status_t
23078b04ffc1Sbeveloper BMediaRosterEx::GetDormantFlavorInfo(media_addon_id addonid,
23088b04ffc1Sbeveloper 									  int32 flavorid,
230952a38012Sejakowatz 									  dormant_flavor_info * out_flavor)
231052a38012Sejakowatz {
231152a38012Sejakowatz 	CALLED();
23129bedd42cSbeveloper 	if (out_flavor == NULL)
23139bedd42cSbeveloper 		return B_BAD_VALUE;
231452a38012Sejakowatz 
231552a38012Sejakowatz 	xfer_server_get_dormant_flavor_info msg;
231652a38012Sejakowatz 	xfer_server_get_dormant_flavor_info_reply *reply;
231752a38012Sejakowatz 	port_id port;
231852a38012Sejakowatz 	status_t rv;
231952a38012Sejakowatz 	int32 code;
232052a38012Sejakowatz 
23214295907bSbeveloper 	port = find_port(MEDIA_SERVER_PORT_NAME);
232252a38012Sejakowatz 	if (port <= B_OK)
232352a38012Sejakowatz 		return B_ERROR;
232452a38012Sejakowatz 
232552a38012Sejakowatz 	reply = (xfer_server_get_dormant_flavor_info_reply *) malloc(16000);
232652a38012Sejakowatz 	if (reply == 0)
232752a38012Sejakowatz 		return B_ERROR;
232852a38012Sejakowatz 
23298b04ffc1Sbeveloper 	msg.addon 		= addonid;
23308b04ffc1Sbeveloper 	msg.flavor_id 	= flavorid;
233152a38012Sejakowatz 	msg.reply_port 	= _PortPool->GetPort();
233252a38012Sejakowatz 	rv = write_port(port, SERVER_GET_DORMANT_FLAVOR_INFO, &msg, sizeof(msg));
233352a38012Sejakowatz 	if (rv != B_OK) {
233452a38012Sejakowatz 		free(reply);
233552a38012Sejakowatz 		_PortPool->PutPort(msg.reply_port);
233652a38012Sejakowatz 		return rv;
233752a38012Sejakowatz 	}
233852a38012Sejakowatz 	rv = read_port(msg.reply_port, &code, reply, 16000);
233952a38012Sejakowatz 	_PortPool->PutPort(msg.reply_port);
234052a38012Sejakowatz 
234152a38012Sejakowatz 	if (rv < B_OK) {
234252a38012Sejakowatz 		free(reply);
234352a38012Sejakowatz 		return rv;
234452a38012Sejakowatz 	}
234552a38012Sejakowatz 
234652a38012Sejakowatz 	if (reply->result == B_OK)
234752a38012Sejakowatz 		rv = out_flavor->Unflatten(reply->dfi_type, &reply->dfi, reply->dfi_size);
234852a38012Sejakowatz 	else
234952a38012Sejakowatz 		rv = reply->result;
235052a38012Sejakowatz 
235152a38012Sejakowatz 	free(reply);
235252a38012Sejakowatz 	return rv;
235352a38012Sejakowatz }
235452a38012Sejakowatz 
23558b04ffc1Sbeveloper status_t
23568b04ffc1Sbeveloper BMediaRoster::GetDormantFlavorInfoFor(const dormant_node_info & in_dormant,
23578b04ffc1Sbeveloper 									  dormant_flavor_info * out_flavor)
23588b04ffc1Sbeveloper {
23598b04ffc1Sbeveloper 	return MediaRosterEx(this)->GetDormantFlavorInfo(in_dormant.addon, in_dormant.flavor_id, out_flavor);
23608b04ffc1Sbeveloper }
236152a38012Sejakowatz 
236260f15390Sbeveloper // Reports in outLatency the maximum latency found downstream from
236360f15390Sbeveloper // the specified BBufferProducer, producer, given the current connections.
236452a38012Sejakowatz status_t
236552a38012Sejakowatz BMediaRoster::GetLatencyFor(const media_node & producer,
236652a38012Sejakowatz 							bigtime_t * out_latency)
236752a38012Sejakowatz {
236860f15390Sbeveloper 	CALLED();
236960f15390Sbeveloper 	if (out_latency == NULL)
237060f15390Sbeveloper 		return B_BAD_VALUE;
237160f15390Sbeveloper 	if (IS_INVALID_NODE(producer))
237260f15390Sbeveloper 		return B_MEDIA_BAD_NODE;
237360f15390Sbeveloper 	if ((producer.kind & B_BUFFER_PRODUCER) == 0)
237460f15390Sbeveloper 		return B_MEDIA_BAD_NODE;
237560f15390Sbeveloper 
237660f15390Sbeveloper 	producer_get_latency_request request;
237760f15390Sbeveloper 	producer_get_latency_reply reply;
237860f15390Sbeveloper 	status_t rv;
237960f15390Sbeveloper 
238060f15390Sbeveloper 	rv = QueryPort(producer.port, PRODUCER_GET_LATENCY, &request, sizeof(request), &reply, sizeof(reply));
238160f15390Sbeveloper 	if (rv != B_OK)
238260f15390Sbeveloper 		return rv;
238360f15390Sbeveloper 
238460f15390Sbeveloper 	*out_latency = reply.latency;
238560f15390Sbeveloper 
238660f15390Sbeveloper 	printf("BMediaRoster::GetLatencyFor producer %ld has maximum latency %Ld\n", producer.node, *out_latency);
2387aac800c2Sbeveloper 	return B_OK;
238852a38012Sejakowatz }
238952a38012Sejakowatz 
239052a38012Sejakowatz 
239152a38012Sejakowatz status_t
239252a38012Sejakowatz BMediaRoster::GetInitialLatencyFor(const media_node & producer,
239352a38012Sejakowatz 								   bigtime_t * out_latency,
2394aac800c2Sbeveloper 								   uint32 * out_flags /* = NULL */)
239552a38012Sejakowatz {
2396b65a0ac5SJérôme Duval 	CALLED();
2397b65a0ac5SJérôme Duval 	if (out_latency == NULL)
2398b65a0ac5SJérôme Duval 		return B_BAD_VALUE;
2399b65a0ac5SJérôme Duval 	if (IS_INVALID_NODE(producer))
2400b65a0ac5SJérôme Duval 		return B_MEDIA_BAD_NODE;
2401b65a0ac5SJérôme Duval 	if ((producer.kind & B_BUFFER_PRODUCER) == 0)
2402b65a0ac5SJérôme Duval 		return B_MEDIA_BAD_NODE;
2403b65a0ac5SJérôme Duval 
2404b65a0ac5SJérôme Duval 	producer_get_initial_latency_request request;
2405b65a0ac5SJérôme Duval 	producer_get_initial_latency_reply reply;
2406b65a0ac5SJérôme Duval 	status_t rv;
2407b65a0ac5SJérôme Duval 
2408b65a0ac5SJérôme Duval 	rv = QueryPort(producer.port, PRODUCER_GET_INITIAL_LATENCY, &request, sizeof(request), &reply, sizeof(reply));
2409b65a0ac5SJérôme Duval 	if (rv != B_OK)
2410b65a0ac5SJérôme Duval 		return rv;
2411b65a0ac5SJérôme Duval 
2412b65a0ac5SJérôme Duval 	*out_latency = reply.initial_latency;
2413aac800c2Sbeveloper 	if (out_flags)
2414b65a0ac5SJérôme Duval 		*out_flags = reply.flags;
2415b65a0ac5SJérôme Duval 
2416b65a0ac5SJérôme Duval 	printf("BMediaRoster::GetInitialLatencyFor producer %ld has maximum initial latency %Ld\n", producer.node, *out_latency);
2417aac800c2Sbeveloper 	return B_OK;
241852a38012Sejakowatz }
241952a38012Sejakowatz 
242052a38012Sejakowatz 
242152a38012Sejakowatz status_t
242252a38012Sejakowatz BMediaRoster::GetStartLatencyFor(const media_node & time_source,
242352a38012Sejakowatz 								 bigtime_t * out_latency)
242452a38012Sejakowatz {
2425*fc8b28b6SJérôme Duval 	CALLED();
2426*fc8b28b6SJérôme Duval 	if (out_latency == NULL)
2427*fc8b28b6SJérôme Duval 		return B_BAD_VALUE;
2428*fc8b28b6SJérôme Duval 	if (IS_INVALID_NODE(time_source))
2429*fc8b28b6SJérôme Duval 		return B_MEDIA_BAD_NODE;
2430*fc8b28b6SJérôme Duval 	if ((time_source.kind & B_TIME_SOURCE) == 0)
2431*fc8b28b6SJérôme Duval 		return B_MEDIA_BAD_NODE;
2432*fc8b28b6SJérôme Duval 
2433*fc8b28b6SJérôme Duval 	timesource_get_start_latency_request request;
2434*fc8b28b6SJérôme Duval 	timesource_get_start_latency_reply reply;
2435*fc8b28b6SJérôme Duval 	status_t rv;
2436*fc8b28b6SJérôme Duval 
2437*fc8b28b6SJérôme Duval 	rv = QueryPort(time_source.port, TIMESOURCE_GET_START_LATENCY, &request, sizeof(request), &reply, sizeof(reply));
2438*fc8b28b6SJérôme Duval 	if (rv != B_OK)
2439*fc8b28b6SJérôme Duval 		return rv;
2440*fc8b28b6SJérôme Duval 
2441*fc8b28b6SJérôme Duval 	*out_latency = reply.start_latency;
2442*fc8b28b6SJérôme Duval 
2443*fc8b28b6SJérôme Duval 	printf("BMediaRoster::GetStartLatencyFor timesource %ld has maximum initial latency %Ld\n", time_source.node, *out_latency);
2444aac800c2Sbeveloper 	return B_OK;
244552a38012Sejakowatz }
244652a38012Sejakowatz 
244752a38012Sejakowatz 
244852a38012Sejakowatz status_t
244952a38012Sejakowatz BMediaRoster::GetFileFormatsFor(const media_node & file_interface,
245052a38012Sejakowatz 								media_file_format * out_formats,
245152a38012Sejakowatz 								int32 * io_num_infos)
245252a38012Sejakowatz {
245352a38012Sejakowatz 	UNIMPLEMENTED();
245452a38012Sejakowatz 	return B_ERROR;
245552a38012Sejakowatz }
245652a38012Sejakowatz 
245752a38012Sejakowatz 
245852a38012Sejakowatz status_t
245952a38012Sejakowatz BMediaRoster::SetRefFor(const media_node & file_interface,
246052a38012Sejakowatz 						const entry_ref & file,
246152a38012Sejakowatz 						bool create_and_truncate,
246252a38012Sejakowatz 						bigtime_t * out_length)	/* if create is false */
246352a38012Sejakowatz {
246452a38012Sejakowatz 	UNIMPLEMENTED();
246552a38012Sejakowatz 	return B_ERROR;
246652a38012Sejakowatz }
246752a38012Sejakowatz 
246852a38012Sejakowatz 
246952a38012Sejakowatz status_t
247052a38012Sejakowatz BMediaRoster::GetRefFor(const media_node & node,
247152a38012Sejakowatz 						entry_ref * out_file,
247252a38012Sejakowatz 						BMimeType * mime_type)
247352a38012Sejakowatz {
247452a38012Sejakowatz 	UNIMPLEMENTED();
247552a38012Sejakowatz 	return B_ERROR;
247652a38012Sejakowatz }
247752a38012Sejakowatz 
247852a38012Sejakowatz 
247952a38012Sejakowatz status_t
248052a38012Sejakowatz BMediaRoster::SniffRefFor(const media_node & file_interface,
248152a38012Sejakowatz 						  const entry_ref & file,
248252a38012Sejakowatz 						  BMimeType * mime_type,
248352a38012Sejakowatz 						  float * out_capability)
248452a38012Sejakowatz {
248552a38012Sejakowatz 	UNIMPLEMENTED();
248652a38012Sejakowatz 	return B_ERROR;
248752a38012Sejakowatz }
248852a38012Sejakowatz 
248952a38012Sejakowatz 
249052a38012Sejakowatz /* This is the generic "here's a file, now can someone please play it" interface */
249152a38012Sejakowatz status_t
249252a38012Sejakowatz BMediaRoster::SniffRef(const entry_ref & file,
249352a38012Sejakowatz 					   uint64 require_node_kinds,		/* if you need an EntityInterface or BufferConsumer or something */
249452a38012Sejakowatz 					   dormant_node_info * out_node,
249552a38012Sejakowatz 					   BMimeType * mime_type)
249652a38012Sejakowatz {
249752a38012Sejakowatz 	UNIMPLEMENTED();
249852a38012Sejakowatz 	return B_ERROR;
249952a38012Sejakowatz }
250052a38012Sejakowatz 
250152a38012Sejakowatz 
250252a38012Sejakowatz status_t
250352a38012Sejakowatz BMediaRoster::GetDormantNodeForType(const BMimeType & type,
250452a38012Sejakowatz 									uint64 require_node_kinds,
250552a38012Sejakowatz 									dormant_node_info * out_node)
250652a38012Sejakowatz {
250752a38012Sejakowatz 	UNIMPLEMENTED();
250852a38012Sejakowatz 	return B_ERROR;
250952a38012Sejakowatz }
251052a38012Sejakowatz 
251152a38012Sejakowatz 
251252a38012Sejakowatz status_t
251352a38012Sejakowatz BMediaRoster::GetReadFileFormatsFor(const dormant_node_info & in_node,
251452a38012Sejakowatz 									media_file_format * out_read_formats,
251552a38012Sejakowatz 									int32 in_read_count,
251652a38012Sejakowatz 									int32 * out_read_count)
251752a38012Sejakowatz {
251852a38012Sejakowatz 	UNIMPLEMENTED();
251952a38012Sejakowatz 	return B_ERROR;
252052a38012Sejakowatz }
252152a38012Sejakowatz 
252252a38012Sejakowatz 
252352a38012Sejakowatz status_t
252452a38012Sejakowatz BMediaRoster::GetWriteFileFormatsFor(const dormant_node_info & in_node,
252552a38012Sejakowatz 									 media_file_format * out_write_formats,
252652a38012Sejakowatz 									 int32 in_write_count,
252752a38012Sejakowatz 									 int32 * out_write_count)
252852a38012Sejakowatz {
252952a38012Sejakowatz 	UNIMPLEMENTED();
253052a38012Sejakowatz 	return B_ERROR;
253152a38012Sejakowatz }
253252a38012Sejakowatz 
253352a38012Sejakowatz 
253452a38012Sejakowatz status_t
253552a38012Sejakowatz BMediaRoster::GetFormatFor(const media_output & output,
253652a38012Sejakowatz 						   media_format * io_format,
253752a38012Sejakowatz 						   uint32 flags)
253852a38012Sejakowatz {
25399bedd42cSbeveloper 	CALLED();
25409bedd42cSbeveloper 	if (io_format == NULL)
25419bedd42cSbeveloper 		return B_BAD_VALUE;
25429bedd42cSbeveloper 	if ((output.node.kind & B_BUFFER_PRODUCER) == 0)
25439bedd42cSbeveloper 		return B_MEDIA_BAD_NODE;
25449bedd42cSbeveloper 	if (IS_INVALID_SOURCE(output.source))
25459bedd42cSbeveloper 		return B_MEDIA_BAD_SOURCE;
25469bedd42cSbeveloper 
25479bedd42cSbeveloper 	producer_format_suggestion_requested_request request;
25489bedd42cSbeveloper 	producer_format_suggestion_requested_reply reply;
25499bedd42cSbeveloper 	status_t rv;
25509bedd42cSbeveloper 
25519bedd42cSbeveloper 	request.type = B_MEDIA_UNKNOWN_TYPE;
25529bedd42cSbeveloper 	request.quality = 0; // XXX what should this be?
25539bedd42cSbeveloper 
25549bedd42cSbeveloper 	rv = QueryPort(output.source.port, PRODUCER_FORMAT_SUGGESTION_REQUESTED, &request, sizeof(request), &reply, sizeof(reply));
25559bedd42cSbeveloper 	if (rv != B_OK)
25569bedd42cSbeveloper 		return rv;
25579bedd42cSbeveloper 
25589bedd42cSbeveloper 	*io_format = reply.format;
25599bedd42cSbeveloper 	return B_OK;
256052a38012Sejakowatz }
256152a38012Sejakowatz 
256252a38012Sejakowatz 
256352a38012Sejakowatz status_t
256452a38012Sejakowatz BMediaRoster::GetFormatFor(const media_input & input,
256552a38012Sejakowatz 						   media_format * io_format,
256652a38012Sejakowatz 						   uint32 flags)
256752a38012Sejakowatz {
25689bedd42cSbeveloper 	CALLED();
25699bedd42cSbeveloper 	if (io_format == NULL)
25709bedd42cSbeveloper 		return B_BAD_VALUE;
25719bedd42cSbeveloper 	if ((input.node.kind & B_BUFFER_CONSUMER) == 0)
25729bedd42cSbeveloper 		return B_MEDIA_BAD_NODE;
25739bedd42cSbeveloper 	if (IS_INVALID_DESTINATION(input.destination))
25749bedd42cSbeveloper 		return B_MEDIA_BAD_DESTINATION;
25759bedd42cSbeveloper 
25769bedd42cSbeveloper 	consumer_accept_format_request request;
25779bedd42cSbeveloper 	consumer_accept_format_reply reply;
25789bedd42cSbeveloper 	status_t rv;
25799bedd42cSbeveloper 
25809bedd42cSbeveloper 	request.dest = input.destination;
25819bedd42cSbeveloper 	memset(&request.format, 0, sizeof(request.format)); // wildcard
25829bedd42cSbeveloper 
25839bedd42cSbeveloper 	rv = QueryPort(input.destination.port, CONSUMER_ACCEPT_FORMAT, &request, sizeof(request), &reply, sizeof(reply));
25849bedd42cSbeveloper 	if (rv != B_OK)
25859bedd42cSbeveloper 		return rv;
25869bedd42cSbeveloper 
25879bedd42cSbeveloper 	*io_format = reply.format;
25889bedd42cSbeveloper 	return B_OK;
258952a38012Sejakowatz }
259052a38012Sejakowatz 
259152a38012Sejakowatz 
259252a38012Sejakowatz status_t
259352a38012Sejakowatz BMediaRoster::GetFormatFor(const media_node & node,
259452a38012Sejakowatz 						   media_format * io_format,
259552a38012Sejakowatz 						   float quality)
259652a38012Sejakowatz {
259752a38012Sejakowatz 	UNIMPLEMENTED();
25989bedd42cSbeveloper 	if (io_format == NULL)
25999bedd42cSbeveloper 		return B_BAD_VALUE;
26009bedd42cSbeveloper 	if (IS_INVALID_NODE(node))
26019bedd42cSbeveloper 		return B_MEDIA_BAD_NODE;
26029bedd42cSbeveloper 	if ((node.kind & (B_BUFFER_CONSUMER | B_BUFFER_PRODUCER)) == 0)
26039bedd42cSbeveloper 		return B_MEDIA_BAD_NODE;
26049bedd42cSbeveloper 
26059bedd42cSbeveloper 
260652a38012Sejakowatz 	return B_ERROR;
260752a38012Sejakowatz }
260852a38012Sejakowatz 
260952a38012Sejakowatz 
261052a38012Sejakowatz ssize_t
261152a38012Sejakowatz BMediaRoster::GetNodeAttributesFor(const media_node & node,
261252a38012Sejakowatz 								   media_node_attribute * outArray,
261352a38012Sejakowatz 								   size_t inMaxCount)
261452a38012Sejakowatz {
261552a38012Sejakowatz 	UNIMPLEMENTED();
261652a38012Sejakowatz 	return B_ERROR;
261752a38012Sejakowatz }
261852a38012Sejakowatz 
261952a38012Sejakowatz 
262052a38012Sejakowatz media_node_id
262152a38012Sejakowatz BMediaRoster::NodeIDFor(port_id source_or_destination_port)
262252a38012Sejakowatz {
26239e9417d2Sbeveloper 	CALLED();
26249e9417d2Sbeveloper 
26259e9417d2Sbeveloper 	server_node_id_for_request request;
26269e9417d2Sbeveloper 	server_node_id_for_reply reply;
26279e9417d2Sbeveloper 	status_t rv;
26289e9417d2Sbeveloper 
26299e9417d2Sbeveloper 	request.port = source_or_destination_port;
26309e9417d2Sbeveloper 
26319e9417d2Sbeveloper 	rv = QueryServer(SERVER_NODE_ID_FOR, &request, sizeof(request), &reply, sizeof(reply));
26329e9417d2Sbeveloper 	if (rv != B_OK) {
26335ac4fbd7Sbeveloper 		ERROR("BMediaRoster::NodeIDFor: failed (error %#lx)\n", rv);
26349e9417d2Sbeveloper 		return -1;
26359e9417d2Sbeveloper 	}
26369e9417d2Sbeveloper 
26379e9417d2Sbeveloper 	return reply.nodeid;
263852a38012Sejakowatz }
263952a38012Sejakowatz 
264052a38012Sejakowatz 
264152a38012Sejakowatz status_t
264252a38012Sejakowatz BMediaRoster::GetInstancesFor(media_addon_id addon,
264352a38012Sejakowatz 							  int32 flavor,
264452a38012Sejakowatz 							  media_node_id * out_id,
264552a38012Sejakowatz 							  int32 * io_count)
264652a38012Sejakowatz {
264785dfab2bSbeveloper 	CALLED();
26488b9700adSJérôme Duval 	if (out_id == NULL)
264985dfab2bSbeveloper 		return B_BAD_VALUE;
26508b9700adSJérôme Duval 	if (io_count && *io_count <= 0)
265185dfab2bSbeveloper 		return B_BAD_VALUE;
265285dfab2bSbeveloper 
265385dfab2bSbeveloper 	server_get_instances_for_request request;
265485dfab2bSbeveloper 	server_get_instances_for_reply reply;
265585dfab2bSbeveloper 	status_t rv;
265685dfab2bSbeveloper 
26578b9700adSJérôme Duval 	request.maxcount = (io_count ? *io_count : 1);
265885dfab2bSbeveloper 	request.addon_id = addon;
265985dfab2bSbeveloper 	request.addon_flavor_id = flavor;
266085dfab2bSbeveloper 
266185dfab2bSbeveloper 	rv = QueryServer(SERVER_GET_INSTANCES_FOR, &request, sizeof(request), &reply, sizeof(reply));
266285dfab2bSbeveloper 	if (rv != B_OK) {
26635ac4fbd7Sbeveloper 		ERROR("BMediaRoster::GetLiveNodes failed\n");
266485dfab2bSbeveloper 		return rv;
266552a38012Sejakowatz 	}
266652a38012Sejakowatz 
26678b9700adSJérôme Duval 	if(io_count)
266885dfab2bSbeveloper 		*io_count = reply.count;
266985dfab2bSbeveloper 	if (reply.count > 0)
267085dfab2bSbeveloper 		memcpy(out_id, reply.node_id, sizeof(media_node_id) * reply.count);
267185dfab2bSbeveloper 
267285dfab2bSbeveloper 	return B_OK;
267385dfab2bSbeveloper }
267452a38012Sejakowatz 
267552a38012Sejakowatz 
267652a38012Sejakowatz status_t
267752a38012Sejakowatz BMediaRoster::SetRealtimeFlags(uint32 in_enabled)
267852a38012Sejakowatz {
267952a38012Sejakowatz 	UNIMPLEMENTED();
268052a38012Sejakowatz 	return B_ERROR;
268152a38012Sejakowatz }
268252a38012Sejakowatz 
268352a38012Sejakowatz 
268452a38012Sejakowatz status_t
268552a38012Sejakowatz BMediaRoster::GetRealtimeFlags(uint32 * out_enabled)
268652a38012Sejakowatz {
268752a38012Sejakowatz 	UNIMPLEMENTED();
268852a38012Sejakowatz 	return B_ERROR;
268952a38012Sejakowatz }
269052a38012Sejakowatz 
269152a38012Sejakowatz 
269252a38012Sejakowatz ssize_t
269352a38012Sejakowatz BMediaRoster::AudioBufferSizeFor(int32 channel_count,
269452a38012Sejakowatz 								 uint32 sample_format,
269552a38012Sejakowatz 								 float frame_rate,
269652a38012Sejakowatz 								 bus_type bus_kind)
269752a38012Sejakowatz {
269852a38012Sejakowatz 	UNIMPLEMENTED();
269952a38012Sejakowatz 	return 4096;
270052a38012Sejakowatz }
270152a38012Sejakowatz 
270252a38012Sejakowatz 
270352a38012Sejakowatz /* Use MediaFlags to inquire about specific features of the Media Kit. */
270452a38012Sejakowatz /* Returns < 0 for "not present", positive size for output data size. */
270552a38012Sejakowatz /* 0 means that the capability is present, but no data about it. */
270652a38012Sejakowatz /* static */ ssize_t
270752a38012Sejakowatz BMediaRoster::MediaFlags(media_flags cap,
270852a38012Sejakowatz 						 void * buf,
270952a38012Sejakowatz 						 size_t maxSize)
271052a38012Sejakowatz {
271152a38012Sejakowatz 	UNIMPLEMENTED();
271252a38012Sejakowatz 	return 0;
271352a38012Sejakowatz }
271452a38012Sejakowatz 
271552a38012Sejakowatz 
271652a38012Sejakowatz /* BLooper overrides */
271752a38012Sejakowatz /* virtual */ void
271852a38012Sejakowatz BMediaRoster::MessageReceived(BMessage * message)
271952a38012Sejakowatz {
2720cf4e2277Sbeveloper 	switch (message->what) {
2721cf4e2277Sbeveloper 		case 'PING':
2722cf4e2277Sbeveloper 		{
27236396865dSbeveloper 			// media_server plays ping-pong with the BMediaRosters
27246396865dSbeveloper 			// to detect dead teams. Normal communication uses ports.
27256396865dSbeveloper 			static BMessage pong('PONG');
27266396865dSbeveloper 			message->SendReply(&pong, static_cast<BHandler *>(NULL), 2000000);
27276396865dSbeveloper 			return;
27286396865dSbeveloper 		}
27296396865dSbeveloper 
2730cf4e2277Sbeveloper 		case NODE_FINAL_RELEASE:
2731cf4e2277Sbeveloper 		{
2732cf4e2277Sbeveloper 			// this function is called by a BMediaNode to delete
2733cf4e2277Sbeveloper 			// itself, as this needs to be done from another thread
2734cf4e2277Sbeveloper 			// context, it is done here.
2735cf4e2277Sbeveloper 			// XXX If a node is released using BMediaRoster::ReleaseNode()
2736cf4e2277Sbeveloper 			// XXX instead of using BMediaNode::Release() / BMediaNode::Acquire()
2737cf4e2277Sbeveloper 			// XXX fRefCount of the BMediaNode will not be correct.
2738cf4e2277Sbeveloper 
2739cf4e2277Sbeveloper 			BMediaNode *node;
2740cf4e2277Sbeveloper 			message->FindPointer("node", reinterpret_cast<void **>(&node));
2741cf4e2277Sbeveloper 
274254187cc6Sbeveloper 			TRACE("BMediaRoster::MessageReceived NODE_FINAL_RELEASE saving node %ld configuration\n", node->ID());
274354187cc6Sbeveloper 			MediaRosterEx(BMediaRoster::Roster())->SaveNodeConfiguration(node);
2744cf4e2277Sbeveloper 
274554187cc6Sbeveloper 			TRACE("BMediaRoster::MessageReceived NODE_FINAL_RELEASE releasing node %ld\n", node->ID());
2746cf4e2277Sbeveloper 			node->DeleteHook(node); // we don't call Release(), see above!
2747cf4e2277Sbeveloper 			return;
2748cf4e2277Sbeveloper 		}
2749cf4e2277Sbeveloper 	}
27506396865dSbeveloper 	printf("BMediaRoster::MessageReceived: unknown message!\n");
27516396865dSbeveloper 	message->PrintToStream();
275252a38012Sejakowatz }
275352a38012Sejakowatz 
275452a38012Sejakowatz /* virtual */ bool
275552a38012Sejakowatz BMediaRoster::QuitRequested()
275652a38012Sejakowatz {
275752a38012Sejakowatz 	UNIMPLEMENTED();
275852a38012Sejakowatz 	return true;
275952a38012Sejakowatz }
276052a38012Sejakowatz 
276152a38012Sejakowatz /* virtual */ BHandler *
276252a38012Sejakowatz BMediaRoster::ResolveSpecifier(BMessage *msg,
276352a38012Sejakowatz 				 int32 index,
276452a38012Sejakowatz 				 BMessage *specifier,
276552a38012Sejakowatz 				 int32 form,
276652a38012Sejakowatz 				 const char *property)
276752a38012Sejakowatz {
276852a38012Sejakowatz 	UNIMPLEMENTED();
276952a38012Sejakowatz 	return 0;
277052a38012Sejakowatz }
277152a38012Sejakowatz 
277252a38012Sejakowatz 
277352a38012Sejakowatz /* virtual */ status_t
277452a38012Sejakowatz BMediaRoster::GetSupportedSuites(BMessage *data)
277552a38012Sejakowatz {
277652a38012Sejakowatz 	UNIMPLEMENTED();
277752a38012Sejakowatz 	return B_ERROR;
277852a38012Sejakowatz }
277952a38012Sejakowatz 
278052a38012Sejakowatz 
278152a38012Sejakowatz BMediaRoster::~BMediaRoster()
278252a38012Sejakowatz {
278352a38012Sejakowatz 	CALLED();
27846396865dSbeveloper 
27856396865dSbeveloper 	// unregister this application with the media server
27866396865dSbeveloper 	server_unregister_app_request request;
27876396865dSbeveloper 	server_unregister_app_reply reply;
27886396865dSbeveloper 	request.team = team;
27896396865dSbeveloper 	QueryServer(SERVER_UNREGISTER_APP, &request, sizeof(request), &reply, sizeof(reply));
279052a38012Sejakowatz }
279152a38012Sejakowatz 
279252a38012Sejakowatz 
279352a38012Sejakowatz /*************************************************************
279452a38012Sejakowatz  * private BMediaRoster
279552a38012Sejakowatz  *************************************************************/
279652a38012Sejakowatz 
279752a38012Sejakowatz // deprecated call
279852a38012Sejakowatz status_t
279952a38012Sejakowatz BMediaRoster::SetOutputBuffersFor(const media_source & output,
280052a38012Sejakowatz 								  BBufferGroup * group,
280152a38012Sejakowatz 								  bool will_reclaim )
280252a38012Sejakowatz {
280352a38012Sejakowatz 	UNIMPLEMENTED();
28049e9417d2Sbeveloper 	debugger("BMediaRoster::SetOutputBuffersFor missing\n");
280552a38012Sejakowatz 	return B_ERROR;
280652a38012Sejakowatz }
280752a38012Sejakowatz 
280852a38012Sejakowatz 
280952a38012Sejakowatz /* FBC stuffing (Mmmh, Stuffing!) */
281052a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_0(void *) { return B_ERROR; }
281152a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_1(void *) { return B_ERROR; }
281252a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_2(void *) { return B_ERROR; }
281352a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_3(void *) { return B_ERROR; }
281452a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_4(void *) { return B_ERROR; }
281552a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_5(void *) { return B_ERROR; }
281652a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_6(void *) { return B_ERROR; }
281752a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_7(void *) { return B_ERROR; }
281852a38012Sejakowatz 
281952a38012Sejakowatz 
282052a38012Sejakowatz BMediaRoster::BMediaRoster() :
28216396865dSbeveloper 	BLooper("_BMediaRoster_", B_URGENT_DISPLAY_PRIORITY, B_LOOPER_PORT_DEFAULT_CAPACITY)
282252a38012Sejakowatz {
282352a38012Sejakowatz 	CALLED();
28246396865dSbeveloper 
28256396865dSbeveloper 	// start the looper
28266396865dSbeveloper 	Run();
28276396865dSbeveloper 
28286396865dSbeveloper 	// register this application with the media server
28296396865dSbeveloper 	server_register_app_request request;
28306396865dSbeveloper 	server_register_app_reply reply;
28316396865dSbeveloper 	request.team = team;
28326396865dSbeveloper 	request.messenger = BMessenger(NULL, this);
28336396865dSbeveloper 	QueryServer(SERVER_REGISTER_APP, &request, sizeof(request), &reply, sizeof(reply));
283452a38012Sejakowatz }
283552a38012Sejakowatz 
28366396865dSbeveloper 
283752a38012Sejakowatz /* static */ status_t
283852a38012Sejakowatz BMediaRoster::ParseCommand(BMessage & reply)
283952a38012Sejakowatz {
284052a38012Sejakowatz 	UNIMPLEMENTED();
284152a38012Sejakowatz 	return B_ERROR;
284252a38012Sejakowatz }
284352a38012Sejakowatz 
284452a38012Sejakowatz 
284552a38012Sejakowatz status_t
284652a38012Sejakowatz BMediaRoster::GetDefaultInfo(media_node_id for_default,
284752a38012Sejakowatz 							 BMessage & out_config)
284852a38012Sejakowatz {
284952a38012Sejakowatz 	UNIMPLEMENTED();
285052a38012Sejakowatz 	return B_ERROR;
285152a38012Sejakowatz }
285252a38012Sejakowatz 
285352a38012Sejakowatz 
285452a38012Sejakowatz 
285552a38012Sejakowatz status_t
285652a38012Sejakowatz BMediaRoster::SetRunningDefault(media_node_id for_default,
285752a38012Sejakowatz 								const media_node & node)
285852a38012Sejakowatz {
285952a38012Sejakowatz 	UNIMPLEMENTED();
286052a38012Sejakowatz 	return B_ERROR;
286152a38012Sejakowatz }
286252a38012Sejakowatz 
286352a38012Sejakowatz 
286452a38012Sejakowatz /*************************************************************
286552a38012Sejakowatz  * static BMediaRoster variables
286652a38012Sejakowatz  *************************************************************/
286752a38012Sejakowatz 
286852a38012Sejakowatz bool BMediaRoster::_isMediaServer;
286952a38012Sejakowatz port_id BMediaRoster::_mReplyPort;
287052a38012Sejakowatz int32 BMediaRoster::_mReplyPortRes;
287152a38012Sejakowatz int32 BMediaRoster::_mReplyPortUnavailCount;
287252a38012Sejakowatz BMediaRoster * BMediaRoster::_sDefault = NULL;
287352a38012Sejakowatz 
2874