1135446Strhodes/* 2193149Sdougb * Copyright (c) 2002, 2003 Marcus Overhagen <Marcus@Overhagen.de> 3135446Strhodes * 4135446Strhodes * Permission is hereby granted, free of charge, to any person obtaining 5193149Sdougb * a copy of this software and associated documentation files or portions 6135446Strhodes * thereof (the "Software"), to deal in the Software without restriction, 7135446Strhodes * including without limitation the rights to use, copy, modify, merge, 8135446Strhodes * publish, distribute, sublicense, and/or sell copies of the Software, 9135446Strhodes * and to permit persons to whom the Software is furnished to do so, subject 10135446Strhodes * to the following conditions: 11135446Strhodes * 12135446Strhodes * * Redistributions of source code must retain the above copyright notice, 13135446Strhodes * this list of conditions and the following disclaimer. 14135446Strhodes * 15135446Strhodes * * Redistributions in binary form must reproduce the above copyright notice 16135446Strhodes * in the binary, as well as this list of conditions and the following 17135446Strhodes * disclaimer in the documentation and/or other materials provided with 18234010Sdougb * the distribution. 19135446Strhodes * 20135446Strhodes * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 21135446Strhodes * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22135446Strhodes * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 23170222Sdougb * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24170222Sdougb * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25135446Strhodes * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 26135446Strhodes * THE SOFTWARE. 27135446Strhodes * 28135446Strhodes */ 29170222Sdougb//#define DEBUG 7 30135446Strhodes#include <MediaRoster.h> 31135446Strhodes#include <MediaNode.h> 32135446Strhodes#include <TimeSource.h> 33165071Sdougb#include <BufferConsumer.h> 34135446Strhodes#include <BufferProducer.h> 35170222Sdougb#include <Controllable.h> 36135446Strhodes#include <FileInterface.h> 37135446Strhodes#include <string.h> 38135446Strhodes#include "debug.h" 39135446Strhodes#include "MediaMisc.h" 40135446Strhodes#include "MediaRosterEx.h" 41135446Strhodes#include "DataExchange.h" 42135446Strhodes#include "ServerInterface.h" 43135446Strhodes#include "Notifications.h" 44135446Strhodes#include "TimeSourceObject.h" 45165071Sdougb#include "TimeSourceObjectManager.h" 46165071Sdougb 47170222Sdougbusing std::nothrow; 48135446Strhodesusing std::nothrow_t; 49135446Strhodes 50135446Strhodes#undef TRACE 51135446Strhodes//#define TRACE_MEDIA_NODE 52135446Strhodes#ifdef TRACE_MEDIA_NODE 53135446Strhodes #define TRACE printf 54135446Strhodes#else 55135446Strhodes #define TRACE(x...) 56135446Strhodes#endif 57135446Strhodes 58135446Strhodes 59135446Strhodes// don't rename this one, it's used and exported for binary compatibility 60135446Strhodesint32 BMediaNode::_m_changeTag = 0; 61165071Sdougb 62170222Sdougb/************************************************************* 63135446Strhodes * media_node 64135446Strhodes *************************************************************/ 65135446Strhodes 66135446Strhodes// final & verified 67135446Strhodesmedia_node::media_node() 68165071Sdougb : node(-1), 69170222Sdougb port(-1), 70135446Strhodes kind(0) 71135446Strhodes{ 72135446Strhodes} 73135446Strhodes 74135446Strhodes// final & verified 75135446Strhodesmedia_node::~media_node() 76135446Strhodes{ 77135446Strhodes} 78165071Sdougb 79170222Sdougb/************************************************************* 80135446Strhodes * static media_node variables 81135446Strhodes *************************************************************/ 82135446Strhodes 83135446Strhodes// final & verified 84135446Strhodesmedia_node media_node::null; 85135446Strhodes 86135446Strhodes/************************************************************* 87135446Strhodes * media_input 88 *************************************************************/ 89 90// final 91media_input::media_input() 92{ 93 name[0] = '\0'; 94} 95 96// final 97media_input::~media_input() 98{ 99} 100 101/************************************************************* 102 * media_output 103 *************************************************************/ 104 105// final 106media_output::media_output() 107{ 108 name[0] = '\0'; 109} 110 111// final 112media_output::~media_output() 113{ 114} 115 116/************************************************************* 117 * live_node_info 118 *************************************************************/ 119 120// final & verified 121live_node_info::live_node_info() 122 : hint_point(0.0f, 0.0f) 123{ 124 name[0] = '\0'; 125} 126 127// final & verified 128live_node_info::~live_node_info() 129{ 130} 131 132/************************************************************* 133 * protected BMediaNode 134 *************************************************************/ 135 136/* virtual */ 137BMediaNode::~BMediaNode() 138{ 139 CALLED(); 140 // BeBook: UnregisterNode() unregisters a node from the Media Server. It's called automatically 141 // BeBook: by the BMediaNode destructor, but it might be convenient to call it sometime before 142 // BeBook: you delete your node instance, depending on your implementation and circumstances. 143 144 // first we remove the time source 145 if (fTimeSource) { 146 fTimeSource->RemoveMe(this); 147 fTimeSource->Release(); 148 fTimeSource = NULL; 149 } 150 151 // Attention! We do not unregister TimeSourceObject nodes, 152 // or delete their control ports, since they are only a 153 // shadow object, and the real one still exists 154 if (0 == (fKinds & NODE_KIND_SHADOW_TIMESOURCE)) { 155 BMediaRoster::Roster()->UnregisterNode(this); 156 157 if (fControlPort > 0) 158 delete_port(fControlPort); 159 } else { 160 TRACE("BMediaNode::~BMediaNode: shadow timesource, not unregistering\n"); 161 } 162} 163 164/************************************************************* 165 * public BMediaNode 166 *************************************************************/ 167 168BMediaNode * 169BMediaNode::Acquire() 170{ 171 CALLED(); 172 atomic_add(&fRefCount,1); 173 return this; 174} 175 176 177BMediaNode * 178BMediaNode::Release() 179{ 180 CALLED(); 181 if (atomic_add(&fRefCount, -1) == 1) { 182 TRACE("BMediaNode::Release() saving node %ld configuration\n", fNodeID); 183 MediaRosterEx(BMediaRoster::Roster())->SaveNodeConfiguration(this); 184 if (DeleteHook(this) != B_OK) { 185 ERROR("BMediaNode::Release(): DeleteHook failed\n"); 186 return Acquire(); 187 } 188 return NULL; 189 } 190 return this; 191} 192 193 194const char * 195BMediaNode::Name() const 196{ 197 CALLED(); 198 return fName; 199} 200 201 202media_node_id 203BMediaNode::ID() const 204{ 205 CALLED(); 206 return fNodeID; 207} 208 209 210uint64 211BMediaNode::Kinds() const 212{ 213 CALLED(); 214 return fKinds & NODE_KIND_USER_MASK; 215} 216 217 218media_node 219BMediaNode::Node() const 220{ 221 CALLED(); 222 media_node temp; 223 temp.node = ID(); 224 temp.port = ControlPort(); // we *must* call ControlPort(), some derived nodes use it to start the port read thread! 225 temp.kind = Kinds(); 226 return temp; 227} 228 229 230BMediaNode::run_mode 231BMediaNode::RunMode() const 232{ 233 CALLED(); 234 return fRunMode; 235} 236 237 238BTimeSource * 239BMediaNode::TimeSource() const 240{ 241 PRINT(7, "CALLED BMediaNode::TimeSource()\n"); 242 243 // return the currently assigned time source 244 if (fTimeSource != 0) 245 return fTimeSource; 246 247 TRACE("BMediaNode::TimeSource node %ld enter\n", ID()); 248 249 // If the node doesn't have a time source object, we need to create one. 250 // If the node is still unregistered, we can't call MakeTimeSourceFor(), 251 // but since the node does still have the default system time source, we 252 // can use GetSystemTimeSource 253 254 BMediaNode *self = const_cast<BMediaNode *>(this); 255// if (fTimeSourceID == NODE_SYSTEM_TIMESOURCE_ID) { 256// self->fTimeSource = _TimeSourceObjectManager->GetSystemTimeSource(); 257// } else { 258 self->fTimeSource = MediaRosterEx(BMediaRoster::Roster())->MakeTimeSourceObject(fTimeSourceID); 259// } 260 ASSERT(fTimeSource == self->fTimeSource); 261 262 if (fTimeSource == 0) { 263 ERROR("BMediaNode::TimeSource: MakeTimeSourceFor failed\n"); 264 } else { 265 ASSERT(fTimeSourceID == fTimeSource->ID()); 266 fTimeSource->AddMe(self); 267 } 268 269 TRACE("BMediaNode::TimeSource node %ld leave\n", ID()); 270 271 return fTimeSource; 272} 273 274 275/* virtual */ port_id 276BMediaNode::ControlPort() const 277{ 278 PRINT(7, "CALLED BMediaNode::ControlPort()\n"); 279 return fControlPort; 280} 281 282 283/************************************************************* 284 * protected BMediaNode 285 *************************************************************/ 286 287status_t 288BMediaNode::ReportError(node_error what, 289 const BMessage *info) 290{ 291 CALLED(); 292 293 // sanity check the what value 294 switch (what) { 295 case BMediaNode::B_NODE_FAILED_START: 296 case BMediaNode::B_NODE_FAILED_STOP: 297 case BMediaNode::B_NODE_FAILED_SEEK: 298 case BMediaNode::B_NODE_FAILED_SET_RUN_MODE: 299 case BMediaNode::B_NODE_FAILED_TIME_WARP: 300 case BMediaNode::B_NODE_FAILED_PREROLL: 301 case BMediaNode::B_NODE_FAILED_SET_TIME_SOURCE_FOR: 302 case BMediaNode::B_NODE_IN_DISTRESS: 303 break; 304 default: 305 ERROR("BMediaNode::ReportError: invalid what!\n"); 306 return B_BAD_VALUE; 307 } 308 309 // Transmits the error code specified by what to anyone 310 // that's receiving notifications from this node 311 return BPrivate::media::notifications::ReportError(Node(), what, info); 312} 313 314 315status_t 316BMediaNode::NodeStopped(bigtime_t whenPerformance) 317{ 318 UNIMPLEMENTED(); 319 // called by derived classes when they have 320 // finished handling a stop request. 321 322 // notify anyone who is listening for stop notifications! 323 BPrivate::media::notifications::NodeStopped(Node(), whenPerformance); 324 325 // XXX If your node is a BBufferProducer, downstream consumers 326 // XXX will be notified that your node stopped (automatically, no less) 327 // XXX through the BBufferConsumer::ProducerDataStatus(B_PRODUCER_STOPPED) call. 328 329 return B_OK; 330} 331 332 333void 334BMediaNode::TimerExpired(bigtime_t notifyPoint, 335 int32 cookie, 336 status_t error) 337{ 338 UNIMPLEMENTED(); 339 // Used with AddTimer 340 // This will, in turn, cause the BMediaRoster::SyncToNode() call 341 // that instigated the timer to return to the caller. 342 // Probably only important to classes derived from BTimeSource. 343} 344 345 346/* explicit */ 347BMediaNode::BMediaNode(const char *name) 348{ 349 TRACE("BMediaNode::BMediaNode: name '%s'\n", name); 350 _InitObject(name, NODE_JUST_CREATED_ID, 0); 351} 352 353 354status_t 355BMediaNode::WaitForMessage(bigtime_t waitUntil, 356 uint32 flags, 357 void *_reserved_) 358{ 359 TRACE("entering: BMediaNode::WaitForMessage()\n"); 360 361 // This function waits until either real time specified by 362 // waitUntil or a message is received on the control port. 363 // The flags are currently unused and should be 0. 364 365 char data[B_MEDIA_MESSAGE_SIZE]; // about 16 KByte stack used 366 int32 message; 367 ssize_t size = read_port_etc(ControlPort(), &message, data, sizeof(data), 368 B_ABSOLUTE_TIMEOUT, waitUntil); 369 if (size < 0) { 370 status_t error = (status_t)size; 371 if (error != B_TIMED_OUT && error != B_BAD_PORT_ID) 372 ERROR("BMediaNode::WaitForMessage: read_port_etc error: %s\n", 373 strerror(error)); 374 return error; 375 } 376 377 TRACE("BMediaNode::WaitForMessage request is: %#lx, node %ld, this %p\n", 378 message, fNodeID, this); 379 380 if (message == GENERAL_PURPOSE_WAKEUP) return B_OK; // no action needed 381 382 if (message > NODE_MESSAGE_START && message < NODE_MESSAGE_END) { 383 TRACE("BMediaNode::WaitForMessage calling BMediaNode\n"); 384 if (B_OK == BMediaNode::HandleMessage(message, data, size)) 385 return B_OK; 386 } 387 388 if (message > PRODUCER_MESSAGE_START && message < PRODUCER_MESSAGE_END) { 389 if (!fProducerThis) 390 fProducerThis = dynamic_cast<BBufferProducer *>(this); 391 TRACE("BMediaNode::WaitForMessage calling BBufferProducer %p\n", 392 fProducerThis); 393 if (fProducerThis && fProducerThis->BBufferProducer::HandleMessage( 394 message, data, size) == B_OK) { 395 return B_OK; 396 } 397 } 398 399 if (message > CONSUMER_MESSAGE_START && message < CONSUMER_MESSAGE_END) { 400 if (!fConsumerThis) 401 fConsumerThis = dynamic_cast<BBufferConsumer *>(this); 402 TRACE("BMediaNode::WaitForMessage calling BBufferConsumer %p\n", 403 fConsumerThis); 404 if (fConsumerThis && fConsumerThis->BBufferConsumer::HandleMessage( 405 message, data, size) == B_OK) { 406 return B_OK; 407 } 408 } 409 410 if (message > FILEINTERFACE_MESSAGE_START 411 && message < FILEINTERFACE_MESSAGE_END) { 412 if (!fFileInterfaceThis) 413 fFileInterfaceThis = dynamic_cast<BFileInterface *>(this); 414 TRACE("BMediaNode::WaitForMessage calling BFileInterface %p\n", 415 fFileInterfaceThis); 416 if (fFileInterfaceThis 417 && fFileInterfaceThis->BFileInterface::HandleMessage( 418 message, data, size) == B_OK) { 419 return B_OK; 420 } 421 } 422 423 if (message > CONTROLLABLE_MESSAGE_START 424 && message < CONTROLLABLE_MESSAGE_END) { 425 if (!fControllableThis) 426 fControllableThis = dynamic_cast<BControllable *>(this); 427 TRACE("BMediaNode::WaitForMessage calling BControllable %p\n", 428 fControllableThis); 429 if (fControllableThis 430 && fControllableThis->BControllable::HandleMessage( 431 message, data, size) == B_OK) { 432 return B_OK; 433 } 434 } 435 436 if (message > TIMESOURCE_MESSAGE_START 437 && message < TIMESOURCE_MESSAGE_END) { 438 if (!fTimeSourceThis) 439 fTimeSourceThis = dynamic_cast<BTimeSource *>(this); 440 TRACE("BMediaNode::WaitForMessage calling BTimeSource %p\n", 441 fTimeSourceThis); 442 if (fTimeSourceThis && fTimeSourceThis->BTimeSource::HandleMessage( 443 message, data, size) == B_OK) { 444 return B_OK; 445 } 446 } 447 448 TRACE("BMediaNode::WaitForMessage calling default HandleMessage\n"); 449 if (B_OK == HandleMessage(message, data, size)) 450 return B_OK; 451 452 HandleBadMessage(message, data, size); 453 454 return B_ERROR; 455} 456 457 458/* virtual */ void 459BMediaNode::Start(bigtime_t performance_time) 460{ 461 CALLED(); 462 // This hook function is called when a node is started 463 // by a call to the BMediaRoster. The specified 464 // performanceTime, the time at which the node 465 // should start running, may be in the future. 466 // It may be overriden by derived classes. 467 // The BMediaEventLooper class handles this event! 468 // The BMediaNode class does nothing here. 469} 470 471 472/* virtual */ void 473BMediaNode::Stop(bigtime_t performance_time, 474 bool immediate) 475{ 476 CALLED(); 477 // This hook function is called when a node is stopped 478 // by a call to the BMediaRoster. The specified 479 // performanceTime, the time at which the node 480 // should stop running, may be in the future. 481 // It may be overriden by derived classes. 482 // The BMediaEventLooper class handles this event! 483 // The BMediaNode class does nothing here. 484} 485 486 487/* virtual */ void 488BMediaNode::Seek(bigtime_t media_time, 489 bigtime_t performance_time) 490{ 491 CALLED(); 492 // This hook function is called when a node is asked 493 // to seek to the specified mediaTime by a call to 494 // the BMediaRoster. The specified performanceTime, 495 // the time at which the node should begin the seek 496 // operation, may be in the future. 497 // It may be overriden by derived classes. 498 // The BMediaEventLooper class handles this event! 499 // The BMediaNode class does nothing here. 500} 501 502 503/* virtual */ void 504BMediaNode::SetRunMode(run_mode mode) 505{ 506 CALLED(); 507 508 // this is a hook function, and 509 // may be overriden by derived classes. 510 511 // the functionality here is only to 512 // support those people that don't 513 // use the roster to set the run mode 514 fRunMode = mode; 515} 516 517 518/* virtual */ void 519BMediaNode::TimeWarp(bigtime_t at_real_time, 520 bigtime_t to_performance_time) 521{ 522 CALLED(); 523 // May be overriden by derived classes. 524} 525 526 527/* virtual */ void 528BMediaNode::Preroll() 529{ 530 CALLED(); 531 // May be overriden by derived classes. 532} 533 534 535/* virtual */ void 536BMediaNode::SetTimeSource(BTimeSource *time_source) 537{ 538 CALLED(); 539 // this is a hook function, and 540 // may be overriden by derived classes. 541 542 if (time_source == NULL || time_source == fTimeSource) 543 return; 544 545 // we just trip into debugger, code that tries to do this is broken. 546 debugger("BMediaNode::SetTimeSource() can't be used to set a timesource, use BMediaRoster::SetTimeSourceFor()!\n"); 547} 548 549/************************************************************* 550 * public BMediaNode 551 *************************************************************/ 552 553/* virtual */ status_t 554BMediaNode::HandleMessage(int32 message, 555 const void *data, 556 size_t size) 557{ 558 TRACE("BMediaNode::HandleMessage %#lx, node %ld\n", message, fNodeID); 559 switch (message) { 560 case NODE_FINAL_RELEASE: 561 { 562 // const node_final_release_command *command = static_cast<const node_final_release_command *>(data); 563 // This is called by the media server to delete the object 564 // after is has been released by all nodes that are using it. 565 // We forward the function to the BMediaRoster, since the 566 // deletion must be done from a different thread, or the 567 // outermost destructor that will exit the thread that is 568 // reading messages from the port (this thread contex) will 569 // quit, and ~BMediaNode destructor won't be called ever. 570 571 TRACE("BMediaNode::HandleMessage NODE_FINAL_RELEASE, this %p\n", this); 572 BMessage msg(NODE_FINAL_RELEASE); 573 msg.AddPointer("node", this); 574 BMediaRoster::Roster()->PostMessage(&msg); 575 576 return B_OK; 577 } 578 579 case NODE_START: 580 { 581 const node_start_command *command = static_cast<const node_start_command *>(data); 582 TRACE("BMediaNode::HandleMessage NODE_START, node %ld\n", fNodeID); 583 Start(command->performance_time); 584 return B_OK; 585 } 586 587 case NODE_STOP: 588 { 589 const node_stop_command *command = static_cast<const node_stop_command *>(data); 590 TRACE("BMediaNode::HandleMessage NODE_STOP, node %ld\n", fNodeID); 591 Stop(command->performance_time, command->immediate); 592 return B_OK; 593 } 594 595 case NODE_SEEK: 596 { 597 const node_seek_command *command = static_cast<const node_seek_command *>(data); 598 TRACE("BMediaNode::HandleMessage NODE_SEEK, node %ld\n", fNodeID); 599 Seek(command->media_time, command->performance_time); 600 return B_OK; 601 } 602 603 case NODE_SET_RUN_MODE: 604 { 605 const node_set_run_mode_command *command = static_cast<const node_set_run_mode_command *>(data); 606 TRACE("BMediaNode::HandleMessage NODE_SET_RUN_MODE, node %ld\n", fNodeID); 607 // when changing this, also change PRODUCER_SET_RUN_MODE_DELAY 608 fRunMode = command->mode; 609 SetRunMode(fRunMode); 610 return B_OK; 611 } 612 613 case NODE_TIME_WARP: 614 { 615 const node_time_warp_command *command = static_cast<const node_time_warp_command *>(data); 616 TRACE("BMediaNode::HandleMessage NODE_TIME_WARP, node %ld\n", fNodeID); 617 TimeWarp(command->at_real_time, command->to_performance_time); 618 return B_OK; 619 } 620 621 case NODE_PREROLL: 622 { 623 TRACE("BMediaNode::HandleMessage NODE_PREROLL, node %ld\n", fNodeID); 624 Preroll(); 625 return B_OK; 626 } 627 628 case NODE_SET_TIMESOURCE: 629 { 630 const node_set_timesource_command *command = static_cast<const node_set_timesource_command *>(data); 631 632 TRACE("BMediaNode::HandleMessage NODE_SET_TIMESOURCE, node %ld, timesource %ld enter\n", fNodeID, command->timesource_id); 633 634 fTimeSourceID = command->timesource_id; 635 636 if (fTimeSource) { 637 // as this node already had a timesource, we need 638 // we need to remove this node from time source control 639 fTimeSource->RemoveMe(this); 640 // Then release the time source 641 fTimeSource->Release(); 642 // force next call to TimeSource() to create a new object 643 fTimeSource = 0; 644 } 645 646 // create new time source object 647 fTimeSource = TimeSource(); 648 // and call the SetTimeSource hook function to notify 649 // any derived class 650 SetTimeSource(fTimeSource); 651 652 TRACE("BMediaNode::HandleMessage NODE_SET_TIMESOURCE, node %ld, timesource %ld leave\n", fNodeID, command->timesource_id); 653 654 return B_OK; 655 } 656 657 case NODE_GET_TIMESOURCE: 658 { 659 const node_get_timesource_request *request = static_cast<const node_get_timesource_request *>(data); 660 TRACE("BMediaNode::HandleMessage NODE_GET_TIMESOURCE, node %ld\n", fNodeID); 661 node_get_timesource_reply reply; 662 reply.timesource_id = fTimeSourceID; 663 request->SendReply(B_OK, &reply, sizeof(reply)); 664 return B_OK; 665 } 666 667 case NODE_REQUEST_COMPLETED: 668 { 669 const node_request_completed_command *command = static_cast<const node_request_completed_command *>(data); 670 TRACE("BMediaNode::HandleMessage NODE_REQUEST_COMPLETED, node %ld\n", fNodeID); 671 RequestCompleted(command->info); 672 return B_OK; 673 } 674 675 }; 676 return B_ERROR; 677} 678 679 680void 681BMediaNode::HandleBadMessage(int32 code, 682 const void *buffer, 683 size_t size) 684{ 685 CALLED(); 686 687 TRACE("BMediaNode::HandleBadMessage: code %#08lx, buffer %p, size %ld\n", code, buffer, size); 688 if (code < NODE_MESSAGE_START || code > TIMESOURCE_MESSAGE_END) { 689 ERROR("BMediaNode::HandleBadMessage: unknown code!\n"); 690 } else { 691 /* All messages targeted to nodes should be handled here, 692 * messages targetted to the wrong node should be handled 693 * by returning an error, not by stalling the sender. 694 */ 695 const request_data *request = static_cast<const request_data *>(buffer); 696 reply_data reply; 697 request->SendReply(B_ERROR, &reply, sizeof(reply)); 698 } 699} 700 701 702void 703BMediaNode::AddNodeKind(uint64 kind) 704{ 705 TRACE("BMediaNode::AddNodeKind: node %ld, this %p\n", fNodeID, this); 706 707 fKinds |= kind; 708} 709 710 711void * 712BMediaNode::operator new(size_t size) 713{ 714 CALLED(); 715 return ::operator new(size); 716} 717 718void * 719BMediaNode::operator new(size_t size, 720 const nothrow_t &) throw() 721{ 722 CALLED(); 723 return ::operator new(size, nothrow); 724} 725 726void 727BMediaNode::operator delete(void *ptr) 728{ 729 CALLED(); 730 ::operator delete(ptr); 731} 732 733void 734BMediaNode::operator delete(void * ptr, 735 const nothrow_t &) throw() 736{ 737 CALLED(); 738 ::operator delete(ptr, nothrow); 739} 740 741/************************************************************* 742 * protected BMediaNode 743 *************************************************************/ 744 745/* virtual */ status_t 746BMediaNode::RequestCompleted(const media_request_info &info) 747{ 748 CALLED(); 749 // This function is called whenever a request issued by the node is completed. 750 // May be overriden by derived classes. 751 // info.change_tag can be used to match up requests against 752 // the accompaning calles from 753 // BBufferConsumer::RequestFormatChange() 754 // BBufferConsumer::SetOutputBuffersFor() 755 // BBufferConsumer::SetOutputEnabled() 756 // BBufferConsumer::SetVideoClippingFor() 757 return B_OK; 758} 759 760/************************************************************* 761 * private BMediaNode 762 *************************************************************/ 763 764int32 765BMediaNode::IncrementChangeTag() 766{ 767 CALLED(); 768 // Only present in BeOS R4 769 // Obsoleted in BeOS R4.5 and later 770 // "updates the change tag, so that downstream consumers know that the node is in a new state." 771 // not supported, only for binary compatibility 772 return 0; 773} 774 775 776int32 777BMediaNode::ChangeTag() 778{ 779 UNIMPLEMENTED(); 780 // Only present in BeOS R4 781 // Obsoleted in BeOS R4.5 and later 782 // "returns the node's current change tag value." 783 // not supported, only for binary compatibility 784 return 0; 785} 786 787 788int32 789BMediaNode::MintChangeTag() 790{ 791 UNIMPLEMENTED(); 792 // Only present in BeOS R4 793 // Obsoleted in BeOS R4.5 and later 794 // "mints a new, reserved, change tag." 795 // "Call ApplyChangeTag() to apply it to the node" 796 // not supported, only for binary compatibility 797 return 0; 798} 799 800 801status_t 802BMediaNode::ApplyChangeTag(int32 previously_reserved) 803{ 804 UNIMPLEMENTED(); 805 // Only present in BeOS R4 806 // Obsoleted in BeOS R4.5 and later 807 // "this returns B_OK if the new change tag is" 808 // "successfully applied, or B_MEDIA_STALE_CHANGE_TAG if the new change" 809 // "count you tried to apply is already obsolete." 810 // not supported, only for binary compatibility 811 return B_OK; 812} 813 814/************************************************************* 815 * protected BMediaNode 816 *************************************************************/ 817 818/* virtual */ status_t 819BMediaNode::DeleteHook(BMediaNode *node) 820{ 821 CALLED(); 822 delete this; // delete "this" or "node", both are the same 823 return B_OK; 824} 825 826 827/* virtual */ void 828BMediaNode::NodeRegistered() 829{ 830 CALLED(); 831 // The Media Server calls this hook function after the node has been registered. 832 // May be overriden by derived classes. 833} 834 835/************************************************************* 836 * public BMediaNode 837 *************************************************************/ 838 839/* virtual */ status_t 840BMediaNode::GetNodeAttributes(media_node_attribute *outAttributes, 841 size_t inMaxCount) 842{ 843 UNIMPLEMENTED(); 844 845 return B_ERROR; 846} 847 848 849/* virtual */ status_t 850BMediaNode::AddTimer(bigtime_t at_performance_time, 851 int32 cookie) 852{ 853 UNIMPLEMENTED(); 854 855 return B_ERROR; 856} 857 858 859status_t BMediaNode::_Reserved_MediaNode_0(void *) { return B_ERROR; } 860status_t BMediaNode::_Reserved_MediaNode_1(void *) { return B_ERROR; } 861status_t BMediaNode::_Reserved_MediaNode_2(void *) { return B_ERROR; } 862status_t BMediaNode::_Reserved_MediaNode_3(void *) { return B_ERROR; } 863status_t BMediaNode::_Reserved_MediaNode_4(void *) { return B_ERROR; } 864status_t BMediaNode::_Reserved_MediaNode_5(void *) { return B_ERROR; } 865status_t BMediaNode::_Reserved_MediaNode_6(void *) { return B_ERROR; } 866status_t BMediaNode::_Reserved_MediaNode_7(void *) { return B_ERROR; } 867status_t BMediaNode::_Reserved_MediaNode_8(void *) { return B_ERROR; } 868status_t BMediaNode::_Reserved_MediaNode_9(void *) { return B_ERROR; } 869status_t BMediaNode::_Reserved_MediaNode_10(void *) { return B_ERROR; } 870status_t BMediaNode::_Reserved_MediaNode_11(void *) { return B_ERROR; } 871status_t BMediaNode::_Reserved_MediaNode_12(void *) { return B_ERROR; } 872status_t BMediaNode::_Reserved_MediaNode_13(void *) { return B_ERROR; } 873status_t BMediaNode::_Reserved_MediaNode_14(void *) { return B_ERROR; } 874status_t BMediaNode::_Reserved_MediaNode_15(void *) { return B_ERROR; } 875 876/* 877private unimplemented 878BMediaNode::BMediaNode() 879BMediaNode::BMediaNode(const BMediaNode &clone) 880BMediaNode &BMediaNode::operator=(const BMediaNode &clone) 881*/ 882 883void 884BMediaNode::_InitObject(const char *name, media_node_id id, uint64 kinds) 885{ 886 TRACE("BMediaNode::_InitObject: nodeid %ld, this %p\n", id, this); 887 888 fNodeID = id; 889 fRefCount = 1; 890 fName[0] = 0; 891 if (name) 892 strlcpy(fName, name, B_MEDIA_NAME_LENGTH); 893 fRunMode = B_INCREASE_LATENCY; 894 fKinds = kinds; 895 fProducerThis = 0; 896 fConsumerThis = 0; 897 fFileInterfaceThis = 0; 898 fControllableThis = 0; 899 fTimeSourceThis = 0; 900 901 // create control port 902 fControlPort = create_port(64, fName); 903 904 // nodes are assigned the system time source by default 905 fTimeSourceID = NODE_SYSTEM_TIMESOURCE_ID; 906 907 // We can't create the timesource object here, because 908 // every timesource is a BMediaNode, which would result 909 // in infinite recursions 910 fTimeSource = NULL; 911} 912 913 914BMediaNode::BMediaNode(const char *name, 915 media_node_id id, 916 uint32 kinds) 917{ 918 TRACE("BMediaNode::BMediaNode: name '%s', nodeid %ld, kinds %#lx\n", name, id, kinds); 919 _InitObject(name, id, kinds); 920} 921 922 923/************************************************************* 924 * protected BMediaNode 925 *************************************************************/ 926 927/* static */ int32 928BMediaNode::NewChangeTag() 929{ 930 CALLED(); 931 // change tags have been used in BeOS R4 to match up 932 // format change requests between producer and consumer, 933 // This has changed starting with R4.5 934 // now "change tags" are used with 935 // BMediaNode::RequestCompleted() 936 // and 937 // BBufferConsumer::RequestFormatChange() 938 // BBufferConsumer::SetOutputBuffersFor() 939 // BBufferConsumer::SetOutputEnabled() 940 // BBufferConsumer::SetVideoClippingFor() 941 return atomic_add(&BMediaNode::_m_changeTag,1); 942} 943