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