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