xref: /haiku/src/kits/media/MediaRoster.cpp (revision 3620737cb79cb28d11eba8a7396a4d0f00fc512d)
1 /***********************************************************************
2  * AUTHOR: Marcus Overhagen
3  *   FILE: MediaRoster.cpp
4  *  DESCR:
5  ***********************************************************************/
6 #include <MediaRoster.h>
7 #include <Locker.h>
8 #include <Message.h>
9 #include <Messenger.h>
10 #include <StopWatch.h>
11 #include <OS.h>
12 #include <String.h>
13 #include <TimeSource.h>
14 #undef 	DEBUG
15 #define	DEBUG 3
16 #include "debug.h"
17 #include "TStack.h"
18 #include "PortPool.h"
19 #include "ServerInterface.h"
20 #include "DataExchange.h"
21 #include "DormantNodeManager.h"
22 #include "Notifications.h"
23 
24 namespace BPrivate { namespace media {
25 	extern team_id team;
26 } } // BPrivate::media
27 
28 using namespace BPrivate::media;
29 
30 // the BMediaRoster destructor is private,
31 // but _DefaultDeleter is a friend class of
32 // the BMediaRoster an thus can delete it
33 class _DefaultDeleter
34 {
35 public:
36 	~_DefaultDeleter() { delete BMediaRoster::_sDefault; }
37 };
38 
39 _DefaultDeleter _deleter;
40 
41 namespace BPrivate { namespace media { namespace mediaroster {
42 
43 status_t GetNode(node_type type, media_node * out_node, int32 * out_input_id = NULL, BString * out_input_name = NULL);
44 status_t SetNode(node_type type, const media_node *node, const dormant_node_info *info = NULL, const media_input *input = NULL);
45 status_t GetAllOutputs(const media_node & node, Stack<media_output> *stack);
46 status_t GetAllInputs(const media_node & node, Stack<media_input> *stack);
47 status_t PublishOutputs(const media_node & node, Stack<media_output> *stack);
48 status_t PublishInputs(const media_node & node, Stack<media_input> *stack);
49 
50 status_t
51 GetNode(node_type type, media_node * out_node, int32 * out_input_id, BString * out_input_name)
52 {
53 	if (out_node == NULL)
54 		return B_BAD_VALUE;
55 
56 	server_get_node_request request;
57 	server_get_node_reply reply;
58 	status_t rv;
59 
60 	request.type = type;
61 	rv = QueryServer(SERVER_GET_NODE, &request, sizeof(request), &reply, sizeof(reply));
62 	if (rv != B_OK)
63 		return rv;
64 
65 	*out_node = reply.node;
66 	if (out_input_id)
67 		*out_input_id = reply.input_id;
68 	if (out_input_name)
69 		*out_input_name = reply.input_name;
70 	return rv;
71 }
72 
73 status_t
74 SetNode(node_type type, const media_node *node, const dormant_node_info *info, const media_input *input)
75 {
76 	server_set_node_request request;
77 	server_set_node_reply reply;
78 
79 	request.type = type;
80 	request.use_node = node ? true : false;
81 	if (node)
82 		request.node = *node;
83 	request.use_dni = info ? true : false;
84 	if (info)
85 		request.dni = *info;
86 	request.use_input = input ? true : false;
87 	if (input)
88 		request.input = *input;
89 
90 	return QueryServer(SERVER_SET_NODE, &request, sizeof(request), &reply, sizeof(reply));
91 }
92 
93 status_t
94 GetAllOutputs(const media_node & node, Stack<media_output> *stack)
95 {
96 	int32 cookie;
97 	status_t rv;
98 	status_t result;
99 
100 	result = B_OK;
101 	cookie = 0;
102 	for (;;) {
103 		producer_get_next_output_request request;
104 		producer_get_next_output_reply reply;
105 		request.cookie = cookie;
106 		rv = QueryServer(PRODUCER_GET_NEXT_OUTPUT, &request, sizeof(request), &reply, sizeof(reply));
107 		if (rv != B_OK)
108 			break;
109 		cookie = reply.cookie;
110 		if (!stack->Push(reply.output)) {
111 			TRACE("GetAllOutputs: stack->Push failed\n");
112 			result = B_ERROR;
113 		}
114 	}
115 
116 	producer_dispose_output_cookie_request request;
117 	producer_dispose_output_cookie_reply reply;
118 	QueryServer(PRODUCER_DISPOSE_OUTPUT_COOKIE, &request, sizeof(request), &reply, sizeof(reply));
119 
120 	return result;
121 }
122 
123 status_t
124 GetAllInputs(const media_node & node, Stack<media_input> *stack)
125 {
126 	int32 cookie;
127 	status_t rv;
128 	status_t result;
129 
130 	result = B_OK;
131 	cookie = 0;
132 	for (;;) {
133 		consumer_get_next_input_request request;
134 		consumer_get_next_input_reply reply;
135 		request.cookie = cookie;
136 		rv = QueryServer(CONSUMER_GET_NEXT_INPUT, &request, sizeof(request), &reply, sizeof(reply));
137 		if (rv != B_OK)
138 			break;
139 		cookie = reply.cookie;
140 		if (!stack->Push(reply.input)) {
141 			TRACE("GetAllInputs: stack->Push failed\n");
142 			result = B_ERROR;
143 		}
144 	}
145 
146 	consumer_dispose_input_cookie_request request;
147 	consumer_dispose_input_cookie_reply reply;
148 	QueryServer(CONSUMER_DISPOSE_INPUT_COOKIE, &request, sizeof(request), &reply, sizeof(reply));
149 
150 	return result;
151 }
152 
153 status_t
154 PublishOutputs(const media_node & node, Stack<media_output> *stack)
155 {
156 	server_publish_outputs_request request;
157 	server_publish_outputs_reply reply;
158 	media_output *output;
159 	media_output *outputs;
160 	int32 count;
161 
162 	count = stack->CountItems();
163 	TRACE("PublishOutputs: publishing %ld\n", count);
164 
165 	request.node = node;
166 	request.count = count;
167 	if (count > MAX_OUTPUTS) {
168 		void *start_addr;
169 		size_t size;
170 		size = ((count * sizeof(media_output)) + B_PAGE_SIZE - 1) & ~(B_PAGE_SIZE - 1);
171 		request.area = create_area("publish outputs", &start_addr, B_ANY_ADDRESS, size, B_NO_LOCK, B_READ_AREA | B_WRITE_AREA);
172 		if (request.area < B_OK) {
173 			TRACE("PublishOutputs: failed to create area, %#lx\n", request.area);
174 			return (status_t)request.area;
175 		}
176 		outputs = static_cast<media_output *>(start_addr);
177 	} else {
178 		request.area = -1;
179 		outputs = request.outputs;
180 	}
181 	TRACE("PublishOutputs: area %#lx\n", request.area);
182 
183 	for (int32 i = 0; i != count; i++) {
184 		stack->GetPointerAt(i, &output);
185 		outputs[i] = *output;
186 	}
187 
188 	return QueryServer(SERVER_PUBLISH_OUTPUTS, &request, sizeof(request), &reply, sizeof(reply));
189 }
190 
191 status_t
192 PublishInputs(const media_node & node, Stack<media_input> *stack)
193 {
194 	server_publish_inputs_request request;
195 	server_publish_inputs_reply reply;
196 	media_input *input;
197 	media_input *inputs;
198 	int32 count;
199 
200 	count = stack->CountItems();
201 	TRACE("PublishInputs: publishing %ld\n", count);
202 
203 	request.node = node;
204 	request.count = count;
205 	if (count > MAX_INPUTS) {
206 		void *start_addr;
207 		size_t size;
208 		size = ((count * sizeof(media_input)) + B_PAGE_SIZE - 1) & ~(B_PAGE_SIZE - 1);
209 		request.area = create_area("publish inputs", &start_addr, B_ANY_ADDRESS, size, B_NO_LOCK, B_READ_AREA | B_WRITE_AREA);
210 		if (request.area < B_OK) {
211 			TRACE("PublishInputs: failed to create area, %#lx\n", request.area);
212 			return (status_t)request.area;
213 		}
214 		inputs = static_cast<media_input *>(start_addr);
215 	} else {
216 		request.area = -1;
217 		inputs = request.inputs;
218 	}
219 	TRACE("PublishInputs: area %#lx\n", request.area);
220 
221 	for (int32 i = 0; i != count; i++) {
222 		stack->GetPointerAt(i, &input);
223 		inputs[i] = *input;
224 	}
225 
226 	return QueryServer(SERVER_PUBLISH_INPUTS, &request, sizeof(request), &reply, sizeof(reply));
227 }
228 
229 } } } // namespace BPrivate::media::mediaroster
230 
231 using namespace BPrivate::media::mediaroster;
232 
233 /*************************************************************
234  * public BMediaRoster
235  *************************************************************/
236 
237 status_t
238 BMediaRoster::GetVideoInput(media_node * out_node)
239 {
240 	CALLED();
241 	return GetNode(VIDEO_INPUT, out_node);
242 }
243 
244 
245 status_t
246 BMediaRoster::GetAudioInput(media_node * out_node)
247 {
248 	CALLED();
249 	return GetNode(AUDIO_INPUT, out_node);
250 }
251 
252 
253 status_t
254 BMediaRoster::GetVideoOutput(media_node * out_node)
255 {
256 	CALLED();
257 	return GetNode(VIDEO_OUTPUT, out_node);
258 }
259 
260 
261 status_t
262 BMediaRoster::GetAudioMixer(media_node * out_node)
263 {
264 	CALLED();
265 	return GetNode(AUDIO_MIXER, out_node);
266 }
267 
268 
269 status_t
270 BMediaRoster::GetAudioOutput(media_node * out_node)
271 {
272 	CALLED();
273 	return GetNode(AUDIO_OUTPUT, out_node);
274 }
275 
276 
277 status_t
278 BMediaRoster::GetAudioOutput(media_node * out_node,
279 							 int32 * out_input_id,
280 							 BString * out_input_name)
281 {
282 	CALLED();
283 	return GetNode(AUDIO_OUTPUT_EX, out_node, out_input_id, out_input_name);
284 }
285 
286 
287 status_t
288 BMediaRoster::GetTimeSource(media_node * out_node)
289 {
290 	CALLED();
291 	return GetNode(TIME_SOURCE, out_node);
292 }
293 
294 
295 status_t
296 BMediaRoster::SetVideoInput(const media_node & producer)
297 {
298 	CALLED();
299 	return SetNode(VIDEO_INPUT, &producer);
300 }
301 
302 
303 status_t
304 BMediaRoster::SetVideoInput(const dormant_node_info & producer)
305 {
306 	CALLED();
307 	return SetNode(VIDEO_INPUT, NULL, &producer);
308 }
309 
310 
311 status_t
312 BMediaRoster::SetAudioInput(const media_node & producer)
313 {
314 	CALLED();
315 	return SetNode(AUDIO_INPUT, &producer);
316 }
317 
318 
319 status_t
320 BMediaRoster::SetAudioInput(const dormant_node_info & producer)
321 {
322 	CALLED();
323 	return SetNode(AUDIO_INPUT, NULL, &producer);
324 }
325 
326 
327 status_t
328 BMediaRoster::SetVideoOutput(const media_node & consumer)
329 {
330 	CALLED();
331 	return SetNode(VIDEO_OUTPUT, &consumer);
332 }
333 
334 
335 status_t
336 BMediaRoster::SetVideoOutput(const dormant_node_info & consumer)
337 {
338 	CALLED();
339 	return SetNode(VIDEO_OUTPUT, NULL, &consumer);
340 }
341 
342 
343 status_t
344 BMediaRoster::SetAudioOutput(const media_node & consumer)
345 {
346 	CALLED();
347 	return SetNode(AUDIO_OUTPUT, &consumer);
348 }
349 
350 
351 status_t
352 BMediaRoster::SetAudioOutput(const media_input & input_to_output)
353 {
354 	CALLED();
355 	return SetNode(AUDIO_OUTPUT, NULL, NULL, &input_to_output);
356 }
357 
358 
359 status_t
360 BMediaRoster::SetAudioOutput(const dormant_node_info & consumer)
361 {
362 	CALLED();
363 	return SetNode(AUDIO_OUTPUT, NULL, &consumer);
364 }
365 
366 
367 status_t
368 BMediaRoster::GetNodeFor(media_node_id node,
369 						 media_node * clone)
370 {
371 	UNIMPLEMENTED();
372 	return B_ERROR;
373 }
374 
375 
376 status_t
377 BMediaRoster::GetSystemTimeSource(media_node * clone)
378 {
379 	CALLED();
380 	return GetNode(SYSTEM_TIME_SOURCE, clone);
381 }
382 
383 
384 status_t
385 BMediaRoster::ReleaseNode(const media_node & node)
386 {
387 	UNIMPLEMENTED();
388 	return B_ERROR;
389 }
390 
391 
392 
393 BTimeSource *
394 BMediaRoster::MakeTimeSourceFor(const media_node & for_node)
395 {
396 	UNIMPLEMENTED();
397 	return 0;
398 }
399 
400 
401 status_t
402 BMediaRoster::Connect(const media_source & from,
403 					  const media_destination & to,
404 					  media_format * io_format,
405 					  media_output * out_output,
406 					  media_input * out_input)
407 {
408 	return BMediaRoster::Connect(from, to, io_format, out_output, out_input, 0);
409 }
410 
411 
412 status_t
413 BMediaRoster::Connect(const media_source & from,
414 					  const media_destination & to,
415 					  media_format * io_format,
416 					  media_output * out_output,
417 					  media_input * out_input,
418 					  uint32 in_flags,
419 					  void * _reserved)
420 {
421 	CALLED();
422 	if (io_format == NULL || out_output == NULL || out_input == NULL)
423 		return B_BAD_VALUE;
424 	if (from == media_source::null)
425 		return B_MEDIA_BAD_SOURCE;
426 	if (to == media_destination::null)
427 		return B_MEDIA_BAD_DESTINATION;
428 
429 	status_t rv;
430 	producer_format_proposal_request request1;
431 	producer_format_proposal_reply reply1;
432 
433 	// BBufferProducer::FormatProposal
434 	request1.output = from;
435 	request1.format = *io_format;
436 	rv = QueryPort(from.port, PRODUCER_FORMAT_PROPOSAL, &request1, sizeof(request1), &reply1, sizeof(reply1));
437 	if (rv != B_OK) {
438 		TRACE("BMediaRoster::Connect: aborted after BBufferProducer::FormatProposal, status = %#lx\n",rv);
439 		return rv;
440 	}
441 	// reply1.format now contains the format proposed by the producer
442 
443 	consumer_accept_format_request request2;
444 	consumer_accept_format_reply reply2;
445 
446 	// BBufferConsumer::AcceptFormat
447 	request2.dest = to;
448 	request2.format = reply1.format;
449 	rv = QueryPort(to.port, CONSUMER_ACCEPT_FORMAT, &request2, sizeof(request2), &reply2, sizeof(reply2));
450 	if (rv != B_OK) {
451 		TRACE("BMediaRoster::Connect: aborted after BBufferConsumer::AcceptFormat, status = %#lx\n",rv);
452 		return rv;
453 	}
454 	// reply2.format now contains the format accepted by the consumer
455 
456 	// BBufferProducer::PrepareToConnect
457 	producer_prepare_to_connect_request request3;
458 	producer_prepare_to_connect_reply reply3;
459 
460 	request3.source = from;
461 	request3.destination = to;
462 	request3.format = reply2.format;
463 	strcpy(request3.name, "XXX some default name"); // XXX fix this
464 	rv = QueryPort(from.port, PRODUCER_PREPARE_TO_CONNECT, &request3, sizeof(request3), &reply3, sizeof(reply3));
465 	if (rv != B_OK) {
466 		TRACE("BMediaRoster::Connect: aborted after BBufferProducer::PrepareToConnect, status = %#lx\n",rv);
467 		return rv;
468 	}
469 	// reply3.format is still our pretty media format
470 	// reply3.out_source the real source to be used for the connection
471 	// reply3.name the name BBufferConsumer::Connected will see in the outInput->name argument
472 
473 	// BBufferConsumer::Connected
474 	consumer_connected_request request4;
475 	consumer_connected_reply reply4;
476 	status_t con_status;
477 
478 	request4.producer = reply3.out_source;
479 	request4.where = to;
480 	request4.with_format = reply3.format;
481 	con_status = QueryPort(to.port, CONSUMER_CONNECTED, &request4, sizeof(request4), &reply4, sizeof(reply4));
482 	if (con_status != B_OK) {
483 		TRACE("BMediaRoster::Connect: aborting after BBufferConsumer::Connected, status = %#lx\n",con_status);
484 		// we do NOT return here!
485 	}
486 	// con_status contains the status code to be supplied to BBufferProducer::Connect's status argument
487 	// reply4.input contains the media_input that describes the connection from the consumer point of view
488 
489 	// BBufferProducer::Connect
490 	producer_connect_request request5;
491 	producer_connect_reply reply5;
492 
493 	request5.error = con_status;
494 	request5.source = reply3.out_source;
495 	request5.destination = reply4.input.destination;
496 	request5.format = reply3.format; // XXX reply4.input.format ???
497 	strcpy(request5.name, reply4.input.name);
498 	rv = QueryPort(reply4.input.node.port, PRODUCER_CONNECT, &request5, sizeof(request5), &reply5, sizeof(reply5));
499 	if (con_status != B_OK) {
500 		TRACE("BMediaRoster::Connect: aborted\n");
501 		return con_status;
502 	}
503 	if (rv != B_OK) {
504 		TRACE("BMediaRoster::Connect: aborted after BBufferProducer::Connect, status = %#lx\n",rv);
505 		return rv;
506 	}
507 	// reply5.name contains the name assigned to the connection by the producer
508 
509 	// find the output node
510 	// XXX isn't there a easier way?
511 	media_node sourcenode;
512 	GetNodeFor(NodeIDFor(from.port), &sourcenode);
513 	ReleaseNode(sourcenode);
514 
515 	// initilize connection info
516 	*io_format = reply3.format;
517 	*out_input = reply4.input;
518 	out_output->node = sourcenode;
519 	out_output->source = reply4.input.source;
520 	out_output->destination = reply4.input.destination;
521 	out_output->format = reply4.input.format;
522 	strcpy(out_output->name, reply5.name);
523 
524 	// the connection is now made
525 
526 
527 	// XXX register connection with server
528 
529 
530 	// XXX if (mute) BBufferProducer::EnableOutput(false)
531 
532 
533 	return B_OK;
534 };
535 
536 
537 status_t
538 BMediaRoster::Disconnect(media_node_id source_node,
539 						 const media_source & source,
540 						 media_node_id destination_node,
541 						 const media_destination & destination)
542 {
543 	UNIMPLEMENTED();
544 	return B_ERROR;
545 }
546 
547 
548 status_t
549 BMediaRoster::StartNode(const media_node & node,
550 						bigtime_t at_performance_time)
551 {
552 	CALLED();
553 	if (node.node == 0)
554 		return B_MEDIA_BAD_NODE;
555 
556 	xfer_node_start msg;
557 	msg.performance_time = at_performance_time;
558 
559 	return write_port(node.port, NODE_START, &msg, sizeof(msg));
560 }
561 
562 
563 status_t
564 BMediaRoster::StopNode(const media_node & node,
565 					   bigtime_t at_performance_time,
566 					   bool immediate)
567 {
568 	CALLED();
569 	if (node.node == 0)
570 		return B_MEDIA_BAD_NODE;
571 
572 	xfer_node_stop msg;
573 	msg.performance_time = at_performance_time;
574 	msg.immediate = immediate;
575 
576 	return write_port(node.port, NODE_STOP, &msg, sizeof(msg));
577 }
578 
579 
580 status_t
581 BMediaRoster::SeekNode(const media_node & node,
582 					   bigtime_t to_media_time,
583 					   bigtime_t at_performance_time)
584 {
585 	CALLED();
586 	if (node.node == 0)
587 		return B_MEDIA_BAD_NODE;
588 
589 	xfer_node_seek msg;
590 	msg.media_time = to_media_time;
591 	msg.performance_time = at_performance_time;
592 
593 	return write_port(node.port, NODE_SEEK, &msg, sizeof(msg));
594 }
595 
596 
597 status_t
598 BMediaRoster::StartTimeSource(const media_node & node,
599 							  bigtime_t at_real_time)
600 {
601 	CALLED();
602 	if (node.node == 0)
603 		return B_MEDIA_BAD_NODE;
604 	if ((node.kind & B_TIME_SOURCE) == 0)
605 		return B_MEDIA_BAD_NODE;
606 
607 	BTimeSource::time_source_op_info msg;
608 	msg.op = BTimeSource::B_TIMESOURCE_START;
609 	msg.real_time = at_real_time;
610 
611 	return write_port(node.port, TIMESOURCE_OP, &msg, sizeof(msg));
612 }
613 
614 
615 status_t
616 BMediaRoster::StopTimeSource(const media_node & node,
617 							 bigtime_t at_real_time,
618 							 bool immediate)
619 {
620 	CALLED();
621 	if (node.node == 0)
622 		return B_MEDIA_BAD_NODE;
623 	if ((node.kind & B_TIME_SOURCE) == 0)
624 		return B_MEDIA_BAD_NODE;
625 
626 	BTimeSource::time_source_op_info msg;
627 	msg.op = immediate ? BTimeSource::B_TIMESOURCE_STOP_IMMEDIATELY : BTimeSource::B_TIMESOURCE_STOP;
628 	msg.real_time = at_real_time;
629 
630 	return write_port(node.port, TIMESOURCE_OP, &msg, sizeof(msg));
631 }
632 
633 
634 status_t
635 BMediaRoster::SeekTimeSource(const media_node & node,
636 							 bigtime_t to_performance_time,
637 							 bigtime_t at_real_time)
638 {
639 	CALLED();
640 	if (node.node == 0)
641 		return B_MEDIA_BAD_NODE;
642 	if ((node.kind & B_TIME_SOURCE) == 0)
643 		return B_MEDIA_BAD_NODE;
644 
645 	BTimeSource::time_source_op_info msg;
646 	msg.op = BTimeSource::B_TIMESOURCE_SEEK;
647 	msg.real_time = at_real_time;
648 	msg.performance_time = to_performance_time;
649 
650 	return write_port(node.port, TIMESOURCE_OP, &msg, sizeof(msg));
651 }
652 
653 
654 status_t
655 BMediaRoster::SyncToNode(const media_node & node,
656 						 bigtime_t at_time,
657 						 bigtime_t timeout)
658 {
659 	UNIMPLEMENTED();
660 	return B_ERROR;
661 }
662 
663 
664 status_t
665 BMediaRoster::SetRunModeNode(const media_node & node,
666 							 BMediaNode::run_mode mode)
667 {
668 	CALLED();
669 	if (node.node == 0)
670 		return B_MEDIA_BAD_NODE;
671 
672 	xfer_node_set_run_mode msg;
673 	msg.mode = mode;
674 
675 	return write_port(node.port, NODE_SET_RUN_MODE, &msg, sizeof(msg));
676 }
677 
678 
679 status_t
680 BMediaRoster::PrerollNode(const media_node & node)
681 {
682 	CALLED();
683 	if (node.node == 0)
684 		return B_MEDIA_BAD_NODE;
685 
686 	char dummy;
687 	return write_port(node.port, NODE_PREROLL, &dummy, sizeof(dummy));
688 }
689 
690 
691 status_t
692 BMediaRoster::RollNode(const media_node & node,
693 					   bigtime_t startPerformance,
694 					   bigtime_t stopPerformance,
695 					   bigtime_t atMediaTime)
696 {
697 	UNIMPLEMENTED();
698 	return B_ERROR;
699 }
700 
701 
702 status_t
703 BMediaRoster::SetProducerRunModeDelay(const media_node & node,
704 									  bigtime_t delay,
705 									  BMediaNode::run_mode mode)
706 {
707 	UNIMPLEMENTED();
708 	return B_ERROR;
709 }
710 
711 
712 status_t
713 BMediaRoster::SetProducerRate(const media_node & producer,
714 							  int32 numer,
715 							  int32 denom)
716 {
717 	CALLED();
718 	if (producer.node == 0)
719 		return B_MEDIA_BAD_NODE;
720 	if ((producer.kind & B_BUFFER_PRODUCER) == 0)
721 		return B_MEDIA_BAD_NODE;
722 
723 	xfer_producer_set_play_rate msg;
724 	xfer_producer_set_play_rate_reply reply;
725 	status_t rv;
726 	int32 code;
727 
728 	msg.numer = numer;
729 	msg.denom = denom;
730 	msg.reply_port = _PortPool->GetPort();
731 	rv = write_port(producer.node, PRODUCER_SET_PLAY_RATE, &msg, sizeof(msg));
732 	if (rv != B_OK) {
733 		_PortPool->PutPort(msg.reply_port);
734 		return rv;
735 	}
736 	rv = read_port(msg.reply_port, &code, &reply, sizeof(reply));
737 	_PortPool->PutPort(msg.reply_port);
738 	return (rv < B_OK) ? rv : reply.result;
739 }
740 
741 
742 
743 /* Nodes will have available inputs/outputs as long as they are capable */
744 /* of accepting more connections. The node may create an additional */
745 /* output or input as the currently available is taken into usage. */
746 status_t
747 BMediaRoster::GetLiveNodeInfo(const media_node & node,
748 							  live_node_info * out_live_info)
749 {
750 	UNIMPLEMENTED();
751 	return B_ERROR;
752 }
753 
754 
755 status_t
756 BMediaRoster::GetLiveNodes(live_node_info * out_live_nodes,
757 						   int32 * io_total_count,
758 						   const media_format * has_input,
759 						   const media_format * has_output,
760 						   const char * name,
761 						   uint64 node_kinds)
762 {
763 	UNIMPLEMENTED();
764 	return B_ERROR;
765 }
766 
767 
768 status_t
769 BMediaRoster::GetFreeInputsFor(const media_node & node,
770 							   media_input * out_free_inputs,
771 							   int32 buf_num_inputs,
772 							   int32 * out_total_count,
773 							   media_type filter_type)
774 {
775 	CALLED();
776 	if (node.node == 0 || (node.kind & B_BUFFER_PRODUCER) == 0)
777 		return B_MEDIA_BAD_NODE;
778 	if (out_free_inputs == NULL || out_total_count == NULL)
779 		return B_BAD_VALUE;
780 
781 	Stack<media_input> stack;
782 	media_input *input;
783 	status_t rv;
784 
785 	rv = GetAllInputs(node, &stack);
786 	if (B_OK != rv)
787 		return rv;
788 
789 	*out_total_count = 0;
790 	for (int32 i = 0; stack.GetPointerAt(i, &input); i++) {
791 		if (filter_type != B_MEDIA_UNKNOWN_TYPE && filter_type != input->format.type)
792 			continue; // media_type used, but doesn't match
793 		if (input->source != media_source::null)
794 			continue; // consumer source already connected
795 		out_free_inputs[i] = *input;
796 		*out_total_count += 1;
797 		buf_num_inputs -= 1;
798 		if (buf_num_inputs == 0)
799 			break;
800 	}
801 
802 	PublishInputs(node, &stack);
803 	return B_OK;
804 }
805 
806 
807 status_t
808 BMediaRoster::GetConnectedInputsFor(const media_node & node,
809 									media_input * out_active_inputs,
810 									int32 buf_num_inputs,
811 									int32 * out_total_count)
812 {
813 	CALLED();
814 	if (node.node == 0 || (node.kind & B_BUFFER_PRODUCER) == 0)
815 		return B_MEDIA_BAD_NODE;
816 	if (out_active_inputs == NULL || out_total_count == NULL)
817 		return B_BAD_VALUE;
818 
819 	Stack<media_input> stack;
820 	media_input *input;
821 	status_t rv;
822 
823 	rv = GetAllInputs(node, &stack);
824 	if (B_OK != rv)
825 		return rv;
826 
827 	*out_total_count = 0;
828 	for (int32 i = 0; stack.GetPointerAt(i, &input); i++) {
829 		if (input->source == media_source::null)
830 			continue; // consumer source not connected
831 		out_active_inputs[i] = *input;
832 		*out_total_count += 1;
833 		buf_num_inputs -= 1;
834 		if (buf_num_inputs == 0)
835 			break;
836 	}
837 
838 	PublishInputs(node, &stack);
839 	return B_OK;
840 }
841 
842 
843 status_t
844 BMediaRoster::GetAllInputsFor(const media_node & node,
845 							  media_input * out_inputs,
846 							  int32 buf_num_inputs,
847 							  int32 * out_total_count)
848 {
849 	CALLED();
850 	if (node.node == 0 || (node.kind & B_BUFFER_CONSUMER) == 0)
851 		return B_MEDIA_BAD_NODE;
852 	if (out_inputs == NULL || out_total_count == NULL)
853 		return B_BAD_VALUE;
854 
855 	Stack<media_input> stack;
856 	media_input *input;
857 	status_t rv;
858 
859 	rv = GetAllInputs(node, &stack);
860 	if (B_OK != rv)
861 		return rv;
862 
863 	*out_total_count = 0;
864 	for (int32 i = 0; stack.GetPointerAt(i, &input); i++) {
865 		out_inputs[i] = *input;
866 		*out_total_count += 1;
867 		buf_num_inputs -= 1;
868 		if (buf_num_inputs == 0)
869 			break;
870 	}
871 
872 	PublishInputs(node, &stack);
873 	return B_OK;
874 }
875 
876 
877 status_t
878 BMediaRoster::GetFreeOutputsFor(const media_node & node,
879 								media_output * out_free_outputs,
880 								int32 buf_num_outputs,
881 								int32 * out_total_count,
882 								media_type filter_type)
883 {
884 	CALLED();
885 	if (node.node == 0 || (node.kind & B_BUFFER_PRODUCER) == 0)
886 		return B_MEDIA_BAD_NODE;
887 	if (out_free_outputs == NULL || out_total_count == NULL)
888 		return B_BAD_VALUE;
889 
890 	Stack<media_output> stack;
891 	media_output *output;
892 	status_t rv;
893 
894 	rv = GetAllOutputs(node, &stack);
895 	if (B_OK != rv)
896 		return rv;
897 
898 	*out_total_count = 0;
899 	for (int32 i = 0; stack.GetPointerAt(i, &output); i++) {
900 		if (filter_type != B_MEDIA_UNKNOWN_TYPE && filter_type != output->format.type)
901 			continue; // media_type used, but doesn't match
902 		if (output->destination != media_destination::null)
903 			continue; // producer destination already connected
904 		out_free_outputs[i] = *output;
905 		*out_total_count += 1;
906 		buf_num_outputs -= 1;
907 		if (buf_num_outputs == 0)
908 			break;
909 	}
910 
911 	PublishOutputs(node, &stack);
912 	return B_OK;
913 }
914 
915 
916 status_t
917 BMediaRoster::GetConnectedOutputsFor(const media_node & node,
918 									 media_output * out_active_outputs,
919 									 int32 buf_num_outputs,
920 									 int32 * out_total_count)
921 {
922 	CALLED();
923 	if (node.node == 0 || (node.kind & B_BUFFER_PRODUCER) == 0)
924 		return B_MEDIA_BAD_NODE;
925 	if (out_active_outputs == NULL || out_total_count == NULL)
926 		return B_BAD_VALUE;
927 
928 	Stack<media_output> stack;
929 	media_output *output;
930 	status_t rv;
931 
932 	rv = GetAllOutputs(node, &stack);
933 	if (B_OK != rv)
934 		return rv;
935 
936 	*out_total_count = 0;
937 	for (int32 i = 0; stack.GetPointerAt(i, &output); i++) {
938 		if (output->destination == media_destination::null)
939 			continue; // producer destination not connected
940 		out_active_outputs[i] = *output;
941 		*out_total_count += 1;
942 		buf_num_outputs -= 1;
943 		if (buf_num_outputs == 0)
944 			break;
945 	}
946 
947 	PublishOutputs(node, &stack);
948 	return B_OK;
949 }
950 
951 
952 status_t
953 BMediaRoster::GetAllOutputsFor(const media_node & node,
954 							   media_output * out_outputs,
955 							   int32 buf_num_outputs,
956 							   int32 * out_total_count)
957 {
958 	CALLED();
959 	if (node.node == 0 || (node.kind & B_BUFFER_PRODUCER) == 0)
960 		return B_MEDIA_BAD_NODE;
961 	if (out_outputs == NULL || out_total_count == NULL)
962 		return B_BAD_VALUE;
963 
964 	Stack<media_output> stack;
965 	media_output *output;
966 	status_t rv;
967 
968 	rv = GetAllOutputs(node, &stack);
969 	if (B_OK != rv)
970 		return rv;
971 
972 	*out_total_count = 0;
973 	for (int32 i = 0; stack.GetPointerAt(i, &output); i++) {
974 		out_outputs[i] = *output;
975 		*out_total_count += 1;
976 		buf_num_outputs -= 1;
977 		if (buf_num_outputs == 0)
978 			break;
979 	}
980 
981 	PublishOutputs(node, &stack);
982 	return B_OK;
983 }
984 
985 
986 status_t
987 BMediaRoster::StartWatching(const BMessenger & where)
988 {
989 	CALLED();
990 	if (!where.IsValid()) {
991 		TRACE("BMediaRoster::StartWatching: messenger invalid!\n");
992 		return B_BAD_VALUE;
993 	}
994 	return BPrivate::media::notifications::Register(where, media_node::null, B_MEDIA_WILDCARD);
995 }
996 
997 
998 status_t
999 BMediaRoster::StartWatching(const BMessenger & where,
1000 							int32 notificationType)
1001 {
1002 	CALLED();
1003 	if (!where.IsValid()) {
1004 		TRACE("BMediaRoster::StartWatching: messenger invalid!\n");
1005 		return B_BAD_VALUE;
1006 	}
1007 	if (false == BPrivate::media::notifications::IsValidNotificationRequest(false, notificationType)) {
1008 		TRACE("BMediaRoster::StartWatching: notificationType invalid!\n");
1009 		return B_BAD_VALUE;
1010 	}
1011 	return BPrivate::media::notifications::Register(where, media_node::null, notificationType);
1012 }
1013 
1014 
1015 status_t
1016 BMediaRoster::StartWatching(const BMessenger & where,
1017 							const media_node & node,
1018 							int32 notificationType)
1019 {
1020 	CALLED();
1021 	if (!where.IsValid()) {
1022 		TRACE("BMediaRoster::StartWatching: messenger invalid!\n");
1023 		return B_BAD_VALUE;
1024 	}
1025 	if (node.node == 0) {
1026 		TRACE("BMediaRoster::StartWatching: node invalid!\n");
1027 		return B_MEDIA_BAD_NODE;
1028 	}
1029 	if (false == BPrivate::media::notifications::IsValidNotificationRequest(true, notificationType)) {
1030 		TRACE("BMediaRoster::StartWatching: notificationType invalid!\n");
1031 		return B_BAD_VALUE;
1032 	}
1033 	return BPrivate::media::notifications::Register(where, node, notificationType);
1034 }
1035 
1036 
1037 status_t
1038 BMediaRoster::StopWatching(const BMessenger & where)
1039 {
1040 	CALLED();
1041 	// messenger may already be invalid, so we don't check this
1042 	return BPrivate::media::notifications::Unregister(where, media_node::null, B_MEDIA_WILDCARD);
1043 }
1044 
1045 
1046 status_t
1047 BMediaRoster::StopWatching(const BMessenger & where,
1048 						   int32 notificationType)
1049 {
1050 	CALLED();
1051 	// messenger may already be invalid, so we don't check this
1052 	if (false == BPrivate::media::notifications::IsValidNotificationRequest(false, notificationType)) {
1053 		TRACE("BMediaRoster::StopWatching: notificationType invalid!\n");
1054 		return B_BAD_VALUE;
1055 	}
1056 	return BPrivate::media::notifications::Unregister(where, media_node::null, notificationType);
1057 }
1058 
1059 
1060 status_t
1061 BMediaRoster::StopWatching(const BMessenger & where,
1062 						   const media_node & node,
1063 						   int32 notificationType)
1064 {
1065 	CALLED();
1066 	// messenger may already be invalid, so we don't check this
1067 	if (node.node == 0) {
1068 		TRACE("BMediaRoster::StopWatching: node invalid!\n");
1069 		return B_MEDIA_BAD_NODE;
1070 	}
1071 	if (false == BPrivate::media::notifications::IsValidNotificationRequest(true, notificationType)) {
1072 		TRACE("BMediaRoster::StopWatching: notificationType invalid!\n");
1073 		return B_BAD_VALUE;
1074 	}
1075 	return BPrivate::media::notifications::Unregister(where, node, notificationType);
1076 }
1077 
1078 
1079 status_t
1080 BMediaRoster::RegisterNode(BMediaNode * node)
1081 {
1082 	CALLED();
1083 	if (node == NULL)
1084 		return B_BAD_VALUE;
1085 
1086 	status_t rv;
1087 
1088 	// XXX fix node registration
1089 	xfer_node_registered msg;
1090 	msg.node_id = 1;
1091 
1092 	rv = node->HandleMessage(NODE_REGISTERED,&msg,sizeof(msg));
1093 
1094 	// register existing inputs and outputs with the
1095 	// media_server, this allows GetLiveNodes() to work
1096 	// with created, but unconnected nodes.
1097 	if (node->Kinds() & B_BUFFER_PRODUCER) {
1098 		Stack<media_output> stack;
1099 		if (B_OK == GetAllOutputs(node->Node(), &stack))
1100 			PublishOutputs(node->Node(), &stack);
1101 	} else if (node->Kinds() & B_BUFFER_CONSUMER) {
1102 		Stack<media_input> stack;
1103 		if (B_OK == GetAllInputs(node->Node(), &stack))
1104 			PublishInputs(node->Node(), &stack);
1105 	}
1106 
1107 	return rv;
1108 }
1109 
1110 
1111 status_t
1112 BMediaRoster::UnregisterNode(BMediaNode * node)
1113 {
1114 	UNIMPLEMENTED();
1115 	return B_ERROR;
1116 }
1117 
1118 
1119 //	thread safe for multiple calls to Roster()
1120 /* static */ BMediaRoster *
1121 BMediaRoster::Roster(status_t* out_error)
1122 {
1123 	CALLED();
1124 	static BLocker locker("BMediaRoster::Roster locker");
1125 	locker.Lock();
1126 	if (_sDefault == NULL) {
1127 		_sDefault = new BMediaRoster();
1128 		if (out_error != NULL)
1129 			*out_error = B_OK;
1130 	} else {
1131 		if (out_error != NULL)
1132 			*out_error = B_OK;
1133 	}
1134 	locker.Unlock();
1135 	return _sDefault;
1136 }
1137 
1138 
1139 //	won't create it if there isn't one
1140 //	not thread safe if you call Roster() at the same time
1141 /* static */ BMediaRoster *
1142 BMediaRoster::CurrentRoster()
1143 {
1144 	CALLED();
1145 	return _sDefault;
1146 }
1147 
1148 
1149 status_t
1150 BMediaRoster::SetTimeSourceFor(media_node_id node,
1151 							   media_node_id time_source)
1152 {
1153 	UNIMPLEMENTED();
1154 	return B_ERROR;
1155 }
1156 
1157 
1158 status_t
1159 BMediaRoster::GetParameterWebFor(const media_node & node,
1160 								 BParameterWeb ** out_web)
1161 {
1162 	UNIMPLEMENTED();
1163 	return B_ERROR;
1164 }
1165 
1166 
1167 status_t
1168 BMediaRoster::StartControlPanel(const media_node & node,
1169 								BMessenger * out_messenger)
1170 {
1171 	UNIMPLEMENTED();
1172 	return B_ERROR;
1173 }
1174 
1175 
1176 status_t
1177 BMediaRoster::GetDormantNodes(dormant_node_info * out_info,
1178 							  int32 * io_count,
1179 							  const media_format * has_input /* = NULL */,
1180 							  const media_format * has_output /* = NULL */,
1181 							  const char * name /* = NULL */,
1182 							  uint64 require_kinds /* = NULL */,
1183 							  uint64 deny_kinds /* = NULL */)
1184 {
1185 	CALLED();
1186 	if (out_info == NULL)
1187 		return B_BAD_VALUE;
1188 	if (io_count == NULL)
1189 		return B_BAD_VALUE;
1190 	if (*io_count <= 0)
1191 		return B_BAD_VALUE;
1192 
1193 	xfer_server_get_dormant_nodes msg;
1194 	port_id port;
1195 	status_t rv;
1196 
1197 	port = find_port("media_server port");
1198 	if (port <= B_OK)
1199 		return B_ERROR;
1200 
1201 	msg.maxcount = *io_count;
1202 	msg.has_input = (bool) has_input;
1203 	if (has_input)
1204 		msg.inputformat = *has_input; // XXX we should not make a flat copy of media_format
1205 	msg.has_output = (bool) has_output;
1206 	if (has_output)
1207 		msg.outputformat = *has_output;; // XXX we should not make a flat copy of media_format
1208 	msg.has_name = (bool) name;
1209 	if (name) {
1210 		int len = min_c(strlen(name),sizeof(msg.name) - 1);
1211 		memcpy(msg.name,name,len);
1212 		msg.name[len] = 0;
1213 	}
1214 	msg.require_kinds = require_kinds;
1215 	msg.deny_kinds = deny_kinds;
1216 	msg.reply_port = _PortPool->GetPort();
1217 
1218 	rv = write_port(port, SERVER_GET_DORMANT_NODES, &msg, sizeof(msg));
1219 	if (rv != B_OK) {
1220 		_PortPool->PutPort(msg.reply_port);
1221 		return rv;
1222 	}
1223 
1224 	xfer_server_get_dormant_nodes_reply reply;
1225 	int32 code;
1226 
1227 	rv = read_port(msg.reply_port, &code, &reply, sizeof(reply));
1228 	if (rv < B_OK) {
1229 		_PortPool->PutPort(msg.reply_port);
1230 		return rv;
1231 	}
1232 
1233 	*io_count = reply.count;
1234 
1235 	if (*io_count > 0) {
1236 		rv = read_port(msg.reply_port, &code, out_info, *io_count * sizeof(dormant_node_info));
1237 		if (rv < B_OK)
1238 			reply.result = rv;
1239 	}
1240 	_PortPool->PutPort(msg.reply_port);
1241 
1242 	return reply.result;
1243 }
1244 
1245 
1246 status_t
1247 BMediaRoster::InstantiateDormantNode(const dormant_node_info & in_info,
1248 									 media_node * out_node,
1249 									 uint32 flags /* currently B_FLAVOR_IS_GLOBAL or B_FLAVOR_IS_LOCAL */ )
1250 {
1251 	CALLED();
1252 	if ((flags & (B_FLAVOR_IS_GLOBAL | B_FLAVOR_IS_LOCAL)) == 0) {
1253 		printf("Error: BMediaRoster::InstantiateDormantNode called without flags\n");
1254 		return B_BAD_VALUE;
1255 	}
1256 	if (out_node == 0)
1257 		return B_BAD_VALUE;
1258 
1259 	// XXX we should not trust the values passed in by the user,
1260 	// XXX and ask the server to determine where to insta
1261 
1262 
1263 // XXX SOMETHING IS VERY WRONG HERE
1264 //	if ((in_info.flavor_flags & B_FLAVOR_IS_GLOBAL) == 0 && (flags & B_FLAVOR_IS_LOCAL)) {
1265 	if (flags & B_FLAVOR_IS_LOCAL) {
1266 		return InstantiateDormantNode(in_info,out_node);
1267 	}
1268 
1269 // XXX SOMETHING IS VERY WRONG HERE
1270 //	if ((in_info.flavor_flags & B_FLAVOR_IS_GLOBAL) || (flags & B_FLAVOR_IS_GLOBAL)) {
1271 	if (flags & B_FLAVOR_IS_GLOBAL) {
1272 		// forward this request into the media_addon_server,
1273 		// which in turn will call InstantiateDormantNode()
1274 		// to create it there localy
1275 		addonserver_instantiate_dormant_node_request request;
1276 		addonserver_instantiate_dormant_node_reply reply;
1277 		status_t rv;
1278 
1279 		request.info = in_info;
1280 		rv = QueryAddonServer(ADDONSERVER_INSTANTIATE_DORMANT_NODE, &request, sizeof(request), &reply, sizeof(reply));
1281 		if (rv == B_OK) {
1282 			*out_node = reply.node;
1283 		}
1284 		return rv;
1285 	}
1286 
1287 // XXX SOMETHING IS VERY WRONG HERE
1288 	printf("Error: BMediaRoster::InstantiateDormantNode addon_id %d, flavor_id %d, flags %#08lx\n", (int)in_info.addon, (int)in_info.flavor_id, flags);
1289 
1290 	return B_ERROR;
1291 }
1292 
1293 
1294 status_t
1295 BMediaRoster::InstantiateDormantNode(const dormant_node_info & in_info,
1296 									 media_node * out_node)
1297 {
1298 	CALLED();
1299 
1300 	// to instantiate a dormant node in the current address space, we need to
1301 	// either load the add-on from file and create a new BMediaAddOn class, or
1302 	// reuse the cached BMediaAddOn from a previous call
1303 	// call BMediaAddOn::InstantiateNodeFor()
1304 	// and cache the BMediaAddOn after that for later reuse.
1305 	// BeOS R5 does not seem to delete it when the application quits
1306 	// if B_FLAVOR_IS_GLOBAL, we need to use the BMediaAddOn object that
1307 	// resides in the media_addon_server
1308 
1309 	// RegisterNode() is called automatically for nodes instantiated from add-ons
1310 
1311 	//XXX TEST!
1312 	BMediaAddOn *addon;
1313 	BMediaNode *node;
1314 	BMessage config;
1315 	status_t out_error;
1316 	status_t rv;
1317 	addon = _DormantNodeManager->GetAddon(in_info.addon);
1318 	if (!addon) {
1319 		printf("BMediaRoster::InstantiateDormantNode: GetAddon failed\n");
1320 		return B_ERROR;
1321 	}
1322 	flavor_info temp;
1323 	temp.internal_id = in_info.flavor_id;
1324 	node = addon->InstantiateNodeFor(&temp, &config, &out_error);
1325 	if (!node) {
1326 		printf("BMediaRoster::InstantiateDormantNode: InstantiateNodeFor failed\n");
1327 		_DormantNodeManager->PutAddon(in_info.addon);
1328 		return B_ERROR;
1329 	}
1330 	rv = RegisterNode(node);
1331 	if (rv != B_OK) {
1332 		printf("BMediaRoster::InstantiateDormantNode: RegisterNode failed\n");
1333 		delete node;
1334 		_DormantNodeManager->PutAddon(in_info.addon);
1335 		return B_ERROR;
1336 	}
1337 
1338 	// XXX we must remember in_info.addon and call
1339 	// XXX _DormantNodeManager->PutAddon when the
1340 	// XXX node is unregistered
1341 
1342 	*out_node = node->Node();
1343 	return B_OK;
1344 }
1345 
1346 
1347 status_t
1348 BMediaRoster::GetDormantNodeFor(const media_node & node,
1349 								dormant_node_info * out_info)
1350 {
1351 	UNIMPLEMENTED();
1352 
1353 	return B_ERROR;
1354 }
1355 
1356 
1357 status_t
1358 BMediaRoster::GetDormantFlavorInfoFor(const dormant_node_info & in_dormant,
1359 									  dormant_flavor_info * out_flavor)
1360 {
1361 	CALLED();
1362 
1363 	xfer_server_get_dormant_flavor_info msg;
1364 	xfer_server_get_dormant_flavor_info_reply *reply;
1365 	port_id port;
1366 	status_t rv;
1367 	int32 code;
1368 
1369 	port = find_port("media_server port");
1370 	if (port <= B_OK)
1371 		return B_ERROR;
1372 
1373 	reply = (xfer_server_get_dormant_flavor_info_reply *) malloc(16000);
1374 	if (reply == 0)
1375 		return B_ERROR;
1376 
1377 	msg.addon 		= in_dormant.addon;
1378 	msg.flavor_id 	= in_dormant.flavor_id;
1379 	msg.reply_port 	= _PortPool->GetPort();
1380 	rv = write_port(port, SERVER_GET_DORMANT_FLAVOR_INFO, &msg, sizeof(msg));
1381 	if (rv != B_OK) {
1382 		free(reply);
1383 		_PortPool->PutPort(msg.reply_port);
1384 		return rv;
1385 	}
1386 	rv = read_port(msg.reply_port, &code, reply, 16000);
1387 	_PortPool->PutPort(msg.reply_port);
1388 
1389 	if (rv < B_OK) {
1390 		free(reply);
1391 		return rv;
1392 	}
1393 
1394 	if (reply->result == B_OK)
1395 		rv = out_flavor->Unflatten(reply->dfi_type, &reply->dfi, reply->dfi_size);
1396 	else
1397 		rv = reply->result;
1398 
1399 	free(reply);
1400 	return rv;
1401 }
1402 
1403 
1404 status_t
1405 BMediaRoster::GetLatencyFor(const media_node & producer,
1406 							bigtime_t * out_latency)
1407 {
1408 	UNIMPLEMENTED();
1409 	*out_latency = 0;
1410 	return B_ERROR;
1411 }
1412 
1413 
1414 status_t
1415 BMediaRoster::GetInitialLatencyFor(const media_node & producer,
1416 								   bigtime_t * out_latency,
1417 								   uint32 * out_flags)
1418 {
1419 	UNIMPLEMENTED();
1420 	*out_latency = 0;
1421 	*out_flags = 0;
1422 	return B_ERROR;
1423 }
1424 
1425 
1426 status_t
1427 BMediaRoster::GetStartLatencyFor(const media_node & time_source,
1428 								 bigtime_t * out_latency)
1429 {
1430 	UNIMPLEMENTED();
1431 	*out_latency = 0;
1432 	return B_ERROR;
1433 }
1434 
1435 
1436 status_t
1437 BMediaRoster::GetFileFormatsFor(const media_node & file_interface,
1438 								media_file_format * out_formats,
1439 								int32 * io_num_infos)
1440 {
1441 	UNIMPLEMENTED();
1442 	return B_ERROR;
1443 }
1444 
1445 
1446 status_t
1447 BMediaRoster::SetRefFor(const media_node & file_interface,
1448 						const entry_ref & file,
1449 						bool create_and_truncate,
1450 						bigtime_t * out_length)	/* if create is false */
1451 {
1452 	UNIMPLEMENTED();
1453 	return B_ERROR;
1454 }
1455 
1456 
1457 status_t
1458 BMediaRoster::GetRefFor(const media_node & node,
1459 						entry_ref * out_file,
1460 						BMimeType * mime_type)
1461 {
1462 	UNIMPLEMENTED();
1463 	return B_ERROR;
1464 }
1465 
1466 
1467 status_t
1468 BMediaRoster::SniffRefFor(const media_node & file_interface,
1469 						  const entry_ref & file,
1470 						  BMimeType * mime_type,
1471 						  float * out_capability)
1472 {
1473 	UNIMPLEMENTED();
1474 	return B_ERROR;
1475 }
1476 
1477 
1478 /* This is the generic "here's a file, now can someone please play it" interface */
1479 status_t
1480 BMediaRoster::SniffRef(const entry_ref & file,
1481 					   uint64 require_node_kinds,		/* if you need an EntityInterface or BufferConsumer or something */
1482 					   dormant_node_info * out_node,
1483 					   BMimeType * mime_type)
1484 {
1485 	UNIMPLEMENTED();
1486 	return B_ERROR;
1487 }
1488 
1489 
1490 status_t
1491 BMediaRoster::GetDormantNodeForType(const BMimeType & type,
1492 									uint64 require_node_kinds,
1493 									dormant_node_info * out_node)
1494 {
1495 	UNIMPLEMENTED();
1496 	return B_ERROR;
1497 }
1498 
1499 
1500 status_t
1501 BMediaRoster::GetReadFileFormatsFor(const dormant_node_info & in_node,
1502 									media_file_format * out_read_formats,
1503 									int32 in_read_count,
1504 									int32 * out_read_count)
1505 {
1506 	UNIMPLEMENTED();
1507 	return B_ERROR;
1508 }
1509 
1510 
1511 status_t
1512 BMediaRoster::GetWriteFileFormatsFor(const dormant_node_info & in_node,
1513 									 media_file_format * out_write_formats,
1514 									 int32 in_write_count,
1515 									 int32 * out_write_count)
1516 {
1517 	UNIMPLEMENTED();
1518 	return B_ERROR;
1519 }
1520 
1521 
1522 status_t
1523 BMediaRoster::GetFormatFor(const media_output & output,
1524 						   media_format * io_format,
1525 						   uint32 flags)
1526 {
1527 	UNIMPLEMENTED();
1528 	return B_ERROR;
1529 }
1530 
1531 
1532 status_t
1533 BMediaRoster::GetFormatFor(const media_input & input,
1534 						   media_format * io_format,
1535 						   uint32 flags)
1536 {
1537 	UNIMPLEMENTED();
1538 	return B_ERROR;
1539 }
1540 
1541 
1542 status_t
1543 BMediaRoster::GetFormatFor(const media_node & node,
1544 						   media_format * io_format,
1545 						   float quality)
1546 {
1547 	UNIMPLEMENTED();
1548 	return B_ERROR;
1549 }
1550 
1551 
1552 ssize_t
1553 BMediaRoster::GetNodeAttributesFor(const media_node & node,
1554 								   media_node_attribute * outArray,
1555 								   size_t inMaxCount)
1556 {
1557 	UNIMPLEMENTED();
1558 	return B_ERROR;
1559 }
1560 
1561 
1562 media_node_id
1563 BMediaRoster::NodeIDFor(port_id source_or_destination_port)
1564 {
1565 	UNIMPLEMENTED();
1566 	return B_ERROR;
1567 }
1568 
1569 
1570 status_t
1571 BMediaRoster::GetInstancesFor(media_addon_id addon,
1572 							  int32 flavor,
1573 							  media_node_id * out_id,
1574 							  int32 * io_count)
1575 {
1576 	UNIMPLEMENTED();
1577 	return B_ERROR;
1578 }
1579 
1580 
1581 
1582 status_t
1583 BMediaRoster::SetRealtimeFlags(uint32 in_enabled)
1584 {
1585 	UNIMPLEMENTED();
1586 	return B_ERROR;
1587 }
1588 
1589 
1590 status_t
1591 BMediaRoster::GetRealtimeFlags(uint32 * out_enabled)
1592 {
1593 	UNIMPLEMENTED();
1594 	return B_ERROR;
1595 }
1596 
1597 
1598 ssize_t
1599 BMediaRoster::AudioBufferSizeFor(int32 channel_count,
1600 								 uint32 sample_format,
1601 								 float frame_rate,
1602 								 bus_type bus_kind)
1603 {
1604 	UNIMPLEMENTED();
1605 	return 4096;
1606 }
1607 
1608 
1609 /* Use MediaFlags to inquire about specific features of the Media Kit. */
1610 /* Returns < 0 for "not present", positive size for output data size. */
1611 /* 0 means that the capability is present, but no data about it. */
1612 /* static */ ssize_t
1613 BMediaRoster::MediaFlags(media_flags cap,
1614 						 void * buf,
1615 						 size_t maxSize)
1616 {
1617 	UNIMPLEMENTED();
1618 	return 0;
1619 }
1620 
1621 
1622 
1623 /* BLooper overrides */
1624 /* virtual */ void
1625 BMediaRoster::MessageReceived(BMessage * message)
1626 {
1627 	UNIMPLEMENTED();
1628 }
1629 
1630 /* virtual */ bool
1631 BMediaRoster::QuitRequested()
1632 {
1633 	UNIMPLEMENTED();
1634 	return true;
1635 }
1636 
1637 /* virtual */ BHandler *
1638 BMediaRoster::ResolveSpecifier(BMessage *msg,
1639 				 int32 index,
1640 				 BMessage *specifier,
1641 				 int32 form,
1642 				 const char *property)
1643 {
1644 	UNIMPLEMENTED();
1645 	return 0;
1646 }
1647 
1648 
1649 /* virtual */ status_t
1650 BMediaRoster::GetSupportedSuites(BMessage *data)
1651 {
1652 	UNIMPLEMENTED();
1653 	return B_ERROR;
1654 }
1655 
1656 
1657 BMediaRoster::~BMediaRoster()
1658 {
1659 	CALLED();
1660 	BMessage msg(MEDIA_SERVER_UNREGISTER_APP);
1661 	BMessage reply;
1662 	msg.AddInt32("team",team);
1663 	QueryServer(&msg, &reply);
1664 }
1665 
1666 
1667 /*************************************************************
1668  * private BMediaRoster
1669  *************************************************************/
1670 
1671 // deprecated call
1672 status_t
1673 BMediaRoster::SetOutputBuffersFor(const media_source & output,
1674 								  BBufferGroup * group,
1675 								  bool will_reclaim )
1676 {
1677 	UNIMPLEMENTED();
1678 	return B_ERROR;
1679 }
1680 
1681 
1682 /* FBC stuffing (Mmmh, Stuffing!) */
1683 status_t BMediaRoster::_Reserved_MediaRoster_0(void *) { return B_ERROR; }
1684 status_t BMediaRoster::_Reserved_MediaRoster_1(void *) { return B_ERROR; }
1685 status_t BMediaRoster::_Reserved_MediaRoster_2(void *) { return B_ERROR; }
1686 status_t BMediaRoster::_Reserved_MediaRoster_3(void *) { return B_ERROR; }
1687 status_t BMediaRoster::_Reserved_MediaRoster_4(void *) { return B_ERROR; }
1688 status_t BMediaRoster::_Reserved_MediaRoster_5(void *) { return B_ERROR; }
1689 status_t BMediaRoster::_Reserved_MediaRoster_6(void *) { return B_ERROR; }
1690 status_t BMediaRoster::_Reserved_MediaRoster_7(void *) { return B_ERROR; }
1691 
1692 
1693 BMediaRoster::BMediaRoster() :
1694 	BLooper("BMediaRoster looper",B_NORMAL_PRIORITY,B_LOOPER_PORT_DEFAULT_CAPACITY)
1695 {
1696 	CALLED();
1697 	BMessage msg(MEDIA_SERVER_REGISTER_APP);
1698 	BMessage reply;
1699 	msg.AddInt32("team",team);
1700 	QueryServer(&msg,&reply);
1701 }
1702 
1703 /* static */ status_t
1704 BMediaRoster::ParseCommand(BMessage & reply)
1705 {
1706 	UNIMPLEMENTED();
1707 	return B_ERROR;
1708 }
1709 
1710 
1711 
1712 status_t
1713 BMediaRoster::GetDefaultInfo(media_node_id for_default,
1714 							 BMessage & out_config)
1715 {
1716 	UNIMPLEMENTED();
1717 	return B_ERROR;
1718 }
1719 
1720 
1721 
1722 status_t
1723 BMediaRoster::SetRunningDefault(media_node_id for_default,
1724 								const media_node & node)
1725 {
1726 	UNIMPLEMENTED();
1727 	return B_ERROR;
1728 }
1729 
1730 
1731 /*************************************************************
1732  * static BMediaRoster variables
1733  *************************************************************/
1734 
1735 bool BMediaRoster::_isMediaServer;
1736 port_id BMediaRoster::_mReplyPort;
1737 int32 BMediaRoster::_mReplyPortRes;
1738 int32 BMediaRoster::_mReplyPortUnavailCount;
1739 BMediaRoster * BMediaRoster::_sDefault = NULL;
1740 
1741