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