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