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