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 if ((in_info.flavor_flags & B_FLAVOR_IS_GLOBAL) == 0 && (flags & B_FLAVOR_IS_LOCAL)) { 1049 return InstantiateDormantNode(in_info,out_node); 1050 } 1051 1052 if ((in_info.flavor_flags & B_FLAVOR_IS_GLOBAL) || (flags & B_FLAVOR_IS_GLOBAL)) { 1053 // forward this request into the media_addon_server, 1054 // which in turn will call InstantiateDormantNode() 1055 // to create it there localy 1056 xfer_addonserver_instantiate_dormant_node msg; 1057 xfer_addonserver_instantiate_dormant_node_reply reply; 1058 port_id port; 1059 status_t rv; 1060 int32 code; 1061 port = find_port("media_addon_server port"); 1062 if (port <= B_OK) 1063 return B_ERROR; 1064 msg.info = in_info; 1065 msg.reply_port = _PortPool->GetPort(); 1066 rv = write_port(port, ADDONSERVER_INSTANTIATE_DORMANT_NODE, &msg, sizeof(msg)); 1067 if (rv != B_OK) { 1068 _PortPool->PutPort(msg.reply_port); 1069 return rv; 1070 } 1071 rv = read_port(msg.reply_port, &code, &reply, sizeof(reply)); 1072 _PortPool->PutPort(msg.reply_port); 1073 if (rv < B_OK) 1074 return rv; 1075 *out_node = reply.node; 1076 return reply.result; 1077 } 1078 1079 printf("Error: BMediaRoster::InstantiateDormantNode in_info.flavor_flags = %#08lx, flags = %#08lx\n", in_info.flavor_flags, flags); 1080 1081 return B_ERROR; 1082 } 1083 1084 1085 status_t 1086 BMediaRoster::InstantiateDormantNode(const dormant_node_info & in_info, 1087 media_node * out_node) 1088 { 1089 UNIMPLEMENTED(); 1090 in_info 1091 1092 // to instantiate a dormant node in the current address space, we need to 1093 // either load the add-on from file and create a new BMediaAddOn class, or 1094 // reuse the cached BMediaAddOn from a previous call 1095 // call BMediaAddOn::InstantiateNodeFor() 1096 // and cache the BMediaAddOn after that for later reuse. 1097 // BeOS R5 does not seem to delete it when the application quits 1098 // if B_FLAVOR_IS_GLOBAL, we need to use the BMediaAddOn object that 1099 // resides in the media_addon_server 1100 1101 // RegisterNode() is called automatically for nodes instantiated from add-ons 1102 1103 return B_ERROR; 1104 } 1105 1106 1107 status_t 1108 BMediaRoster::GetDormantNodeFor(const media_node & node, 1109 dormant_node_info * out_info) 1110 { 1111 UNIMPLEMENTED(); 1112 1113 return B_ERROR; 1114 } 1115 1116 1117 status_t 1118 BMediaRoster::GetDormantFlavorInfoFor(const dormant_node_info & in_dormant, 1119 dormant_flavor_info * out_flavor) 1120 { 1121 CALLED(); 1122 1123 xfer_server_get_dormant_flavor_info msg; 1124 xfer_server_get_dormant_flavor_info_reply *reply; 1125 port_id port; 1126 status_t rv; 1127 int32 code; 1128 1129 port = find_port("media_server port"); 1130 if (port <= B_OK) 1131 return B_ERROR; 1132 1133 reply = (xfer_server_get_dormant_flavor_info_reply *) malloc(16000); 1134 if (reply == 0) 1135 return B_ERROR; 1136 1137 msg.addon = in_dormant.addon; 1138 msg.flavor_id = in_dormant.flavor_id; 1139 msg.reply_port = _PortPool->GetPort(); 1140 rv = write_port(port, SERVER_GET_DORMANT_FLAVOR_INFO, &msg, sizeof(msg)); 1141 if (rv != B_OK) { 1142 free(reply); 1143 _PortPool->PutPort(msg.reply_port); 1144 return rv; 1145 } 1146 rv = read_port(msg.reply_port, &code, reply, 16000); 1147 _PortPool->PutPort(msg.reply_port); 1148 1149 if (rv < B_OK) { 1150 free(reply); 1151 return rv; 1152 } 1153 1154 if (reply->result == B_OK) 1155 rv = out_flavor->Unflatten(reply->dfi_type, &reply->dfi, reply->dfi_size); 1156 else 1157 rv = reply->result; 1158 1159 free(reply); 1160 return rv; 1161 } 1162 1163 1164 status_t 1165 BMediaRoster::GetLatencyFor(const media_node & producer, 1166 bigtime_t * out_latency) 1167 { 1168 UNIMPLEMENTED(); 1169 *out_latency = 0; 1170 return B_ERROR; 1171 } 1172 1173 1174 status_t 1175 BMediaRoster::GetInitialLatencyFor(const media_node & producer, 1176 bigtime_t * out_latency, 1177 uint32 * out_flags) 1178 { 1179 UNIMPLEMENTED(); 1180 *out_latency = 0; 1181 *out_flags = 0; 1182 return B_ERROR; 1183 } 1184 1185 1186 status_t 1187 BMediaRoster::GetStartLatencyFor(const media_node & time_source, 1188 bigtime_t * out_latency) 1189 { 1190 UNIMPLEMENTED(); 1191 *out_latency = 0; 1192 return B_ERROR; 1193 } 1194 1195 1196 status_t 1197 BMediaRoster::GetFileFormatsFor(const media_node & file_interface, 1198 media_file_format * out_formats, 1199 int32 * io_num_infos) 1200 { 1201 UNIMPLEMENTED(); 1202 return B_ERROR; 1203 } 1204 1205 1206 status_t 1207 BMediaRoster::SetRefFor(const media_node & file_interface, 1208 const entry_ref & file, 1209 bool create_and_truncate, 1210 bigtime_t * out_length) /* if create is false */ 1211 { 1212 UNIMPLEMENTED(); 1213 return B_ERROR; 1214 } 1215 1216 1217 status_t 1218 BMediaRoster::GetRefFor(const media_node & node, 1219 entry_ref * out_file, 1220 BMimeType * mime_type) 1221 { 1222 UNIMPLEMENTED(); 1223 return B_ERROR; 1224 } 1225 1226 1227 status_t 1228 BMediaRoster::SniffRefFor(const media_node & file_interface, 1229 const entry_ref & file, 1230 BMimeType * mime_type, 1231 float * out_capability) 1232 { 1233 UNIMPLEMENTED(); 1234 return B_ERROR; 1235 } 1236 1237 1238 /* This is the generic "here's a file, now can someone please play it" interface */ 1239 status_t 1240 BMediaRoster::SniffRef(const entry_ref & file, 1241 uint64 require_node_kinds, /* if you need an EntityInterface or BufferConsumer or something */ 1242 dormant_node_info * out_node, 1243 BMimeType * mime_type) 1244 { 1245 UNIMPLEMENTED(); 1246 return B_ERROR; 1247 } 1248 1249 1250 status_t 1251 BMediaRoster::GetDormantNodeForType(const BMimeType & type, 1252 uint64 require_node_kinds, 1253 dormant_node_info * out_node) 1254 { 1255 UNIMPLEMENTED(); 1256 return B_ERROR; 1257 } 1258 1259 1260 status_t 1261 BMediaRoster::GetReadFileFormatsFor(const dormant_node_info & in_node, 1262 media_file_format * out_read_formats, 1263 int32 in_read_count, 1264 int32 * out_read_count) 1265 { 1266 UNIMPLEMENTED(); 1267 return B_ERROR; 1268 } 1269 1270 1271 status_t 1272 BMediaRoster::GetWriteFileFormatsFor(const dormant_node_info & in_node, 1273 media_file_format * out_write_formats, 1274 int32 in_write_count, 1275 int32 * out_write_count) 1276 { 1277 UNIMPLEMENTED(); 1278 return B_ERROR; 1279 } 1280 1281 1282 status_t 1283 BMediaRoster::GetFormatFor(const media_output & output, 1284 media_format * io_format, 1285 uint32 flags) 1286 { 1287 UNIMPLEMENTED(); 1288 return B_ERROR; 1289 } 1290 1291 1292 status_t 1293 BMediaRoster::GetFormatFor(const media_input & input, 1294 media_format * io_format, 1295 uint32 flags) 1296 { 1297 UNIMPLEMENTED(); 1298 return B_ERROR; 1299 } 1300 1301 1302 status_t 1303 BMediaRoster::GetFormatFor(const media_node & node, 1304 media_format * io_format, 1305 float quality) 1306 { 1307 UNIMPLEMENTED(); 1308 return B_ERROR; 1309 } 1310 1311 1312 ssize_t 1313 BMediaRoster::GetNodeAttributesFor(const media_node & node, 1314 media_node_attribute * outArray, 1315 size_t inMaxCount) 1316 { 1317 UNIMPLEMENTED(); 1318 return B_ERROR; 1319 } 1320 1321 1322 media_node_id 1323 BMediaRoster::NodeIDFor(port_id source_or_destination_port) 1324 { 1325 UNIMPLEMENTED(); 1326 return B_ERROR; 1327 } 1328 1329 1330 status_t 1331 BMediaRoster::GetInstancesFor(media_addon_id addon, 1332 int32 flavor, 1333 media_node_id * out_id, 1334 int32 * io_count) 1335 { 1336 UNIMPLEMENTED(); 1337 return B_ERROR; 1338 } 1339 1340 1341 1342 status_t 1343 BMediaRoster::SetRealtimeFlags(uint32 in_enabled) 1344 { 1345 UNIMPLEMENTED(); 1346 return B_ERROR; 1347 } 1348 1349 1350 status_t 1351 BMediaRoster::GetRealtimeFlags(uint32 * out_enabled) 1352 { 1353 UNIMPLEMENTED(); 1354 return B_ERROR; 1355 } 1356 1357 1358 ssize_t 1359 BMediaRoster::AudioBufferSizeFor(int32 channel_count, 1360 uint32 sample_format, 1361 float frame_rate, 1362 bus_type bus_kind) 1363 { 1364 UNIMPLEMENTED(); 1365 return 4096; 1366 } 1367 1368 1369 /* Use MediaFlags to inquire about specific features of the Media Kit. */ 1370 /* Returns < 0 for "not present", positive size for output data size. */ 1371 /* 0 means that the capability is present, but no data about it. */ 1372 /* static */ ssize_t 1373 BMediaRoster::MediaFlags(media_flags cap, 1374 void * buf, 1375 size_t maxSize) 1376 { 1377 UNIMPLEMENTED(); 1378 return 0; 1379 } 1380 1381 1382 1383 /* BLooper overrides */ 1384 /* virtual */ void 1385 BMediaRoster::MessageReceived(BMessage * message) 1386 { 1387 UNIMPLEMENTED(); 1388 } 1389 1390 /* virtual */ bool 1391 BMediaRoster::QuitRequested() 1392 { 1393 UNIMPLEMENTED(); 1394 return true; 1395 } 1396 1397 /* virtual */ BHandler * 1398 BMediaRoster::ResolveSpecifier(BMessage *msg, 1399 int32 index, 1400 BMessage *specifier, 1401 int32 form, 1402 const char *property) 1403 { 1404 UNIMPLEMENTED(); 1405 return 0; 1406 } 1407 1408 1409 /* virtual */ status_t 1410 BMediaRoster::GetSupportedSuites(BMessage *data) 1411 { 1412 UNIMPLEMENTED(); 1413 return B_ERROR; 1414 } 1415 1416 1417 BMediaRoster::~BMediaRoster() 1418 { 1419 CALLED(); 1420 BMessage msg(MEDIA_SERVER_UNREGISTER_APP); 1421 BMessage reply; 1422 msg.AddInt32("team",team); 1423 ServerMessenger->SendMessage(&msg,&reply); 1424 } 1425 1426 1427 /************************************************************* 1428 * private BMediaRoster 1429 *************************************************************/ 1430 1431 // deprecated call 1432 status_t 1433 BMediaRoster::SetOutputBuffersFor(const media_source & output, 1434 BBufferGroup * group, 1435 bool will_reclaim ) 1436 { 1437 UNIMPLEMENTED(); 1438 return B_ERROR; 1439 } 1440 1441 1442 /* FBC stuffing (Mmmh, Stuffing!) */ 1443 status_t BMediaRoster::_Reserved_MediaRoster_0(void *) { return B_ERROR; } 1444 status_t BMediaRoster::_Reserved_MediaRoster_1(void *) { return B_ERROR; } 1445 status_t BMediaRoster::_Reserved_MediaRoster_2(void *) { return B_ERROR; } 1446 status_t BMediaRoster::_Reserved_MediaRoster_3(void *) { return B_ERROR; } 1447 status_t BMediaRoster::_Reserved_MediaRoster_4(void *) { return B_ERROR; } 1448 status_t BMediaRoster::_Reserved_MediaRoster_5(void *) { return B_ERROR; } 1449 status_t BMediaRoster::_Reserved_MediaRoster_6(void *) { return B_ERROR; } 1450 status_t BMediaRoster::_Reserved_MediaRoster_7(void *) { return B_ERROR; } 1451 1452 1453 BMediaRoster::BMediaRoster() : 1454 BLooper("BMediaRoster looper",B_NORMAL_PRIORITY,B_LOOPER_PORT_DEFAULT_CAPACITY) 1455 { 1456 CALLED(); 1457 BMessage msg(MEDIA_SERVER_REGISTER_APP); 1458 BMessage reply; 1459 msg.AddInt32("team",team); 1460 ServerMessenger->SendMessage(&msg,&reply); 1461 } 1462 1463 /* static */ status_t 1464 BMediaRoster::ParseCommand(BMessage & reply) 1465 { 1466 UNIMPLEMENTED(); 1467 return B_ERROR; 1468 } 1469 1470 1471 1472 status_t 1473 BMediaRoster::GetDefaultInfo(media_node_id for_default, 1474 BMessage & out_config) 1475 { 1476 UNIMPLEMENTED(); 1477 return B_ERROR; 1478 } 1479 1480 1481 1482 status_t 1483 BMediaRoster::SetRunningDefault(media_node_id for_default, 1484 const media_node & node) 1485 { 1486 UNIMPLEMENTED(); 1487 return B_ERROR; 1488 } 1489 1490 1491 /************************************************************* 1492 * static BMediaRoster variables 1493 *************************************************************/ 1494 1495 bool BMediaRoster::_isMediaServer; 1496 port_id BMediaRoster::_mReplyPort; 1497 int32 BMediaRoster::_mReplyPortRes; 1498 int32 BMediaRoster::_mReplyPortUnavailCount; 1499 BMediaRoster * BMediaRoster::_sDefault = NULL; 1500 1501