2 * Copyright (c) 2015, Dario Casalinuovo
3 * Copyright (c) 2002, 2003 Marcus Overhagen <Marcus@Overhagen.de>
5 * Permission is hereby granted, free of charge, to any person obtaining
6 * a copy of this software and associated documentation files or portions
7 * thereof (the "Software"), to deal in the Software without restriction,
8 * including without limitation the rights to use, copy, modify, merge,
9 * publish, distribute, sublicense, and/or sell copies of the Software,
10 * and to permit persons to whom the Software is furnished to do so, subject
11 * to the following conditions:
13 * * Redistributions of source code must retain the above copyright notice,
14 * this list of conditions and the following disclaimer.
16 * * Redistributions in binary form must reproduce the above copyright notice
17 * in the binary, as well as this list of conditions and the following
18 * disclaimer in the documentation and/or other materials provided with
21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
24 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
32 #include <BufferConsumer.h>
33 #include <BufferProducer.h>
34 #include <Controllable.h>
35 #include <FileInterface.h>
36 #include <MediaRoster.h>
37 #include <MediaNode.h>
38 #include <SupportDefs.h>
39 #include <TimeSource.h>
43 #include "DataExchange.h"
45 #include "MediaMisc.h"
46 #include "MediaRosterEx.h"
47 #include "Notifications.h"
48 #include "ServerInterface.h"
49 #include "TimeSourceObject.h"
50 #include "TimeSourceObjectManager.h"
56 //#define TRACE_MEDIA_NODE
57 #ifdef TRACE_MEDIA_NODE
63 // Don't rename this one, it's used and exported for binary compatibility
64 int32
BMediaNode::_m_changeTag
= 0;
68 media_node
media_node::null
;
70 media_node::media_node()
79 media_node::~media_node()
85 media_input::media_input()
91 media_input::~media_input()
97 media_output::media_output()
103 media_output::~media_output()
109 live_node_info::live_node_info()
111 hint_point(0.0f
, 0.0f
)
117 live_node_info::~live_node_info()
123 BMediaNode::~BMediaNode()
126 // BeBook: UnregisterNode() unregisters a node from the Media Server.
127 // It's called automatically by the BMediaNode destructor, but it might
128 // be convenient to call it sometime before you delete your node instance,
129 // depending on your implementation and circumstances.
131 // First we remove the time source
133 fTimeSource
->RemoveMe(this);
134 fTimeSource
->Release();
138 // Attention! We do not delete their control ports, since they are only a
139 // shadow object, and the real one still exists
140 if ((fKinds
& NODE_KIND_SHADOW_TIMESOURCE
) == 0) {
141 if (fControlPort
> 0)
142 delete_port(fControlPort
);
144 TRACE("BMediaNode::~BMediaNode: shadow timesource,"
145 " not unregistering\n");
151 BMediaNode::Acquire()
154 atomic_add(&fRefCount
,1);
160 BMediaNode::Release()
163 if (atomic_add(&fRefCount
, -1) == 1) {
164 TRACE("BMediaNode::Release() saving node %ld configuration\n", fNodeID
);
165 MediaRosterEx(BMediaRoster::Roster())->SaveNodeConfiguration(this);
166 if (DeleteHook(this) != B_OK
) {
167 ERROR("BMediaNode::Release(): DeleteHook failed\n");
177 BMediaNode::Name() const
185 BMediaNode::ID() const
193 BMediaNode::Kinds() const
196 return fKinds
& NODE_KIND_USER_MASK
;
201 BMediaNode::Node() const
206 // We *must* call ControlPort(), some derived nodes
207 // use it to start the port read thread!
208 temp
.port
= ControlPort();
215 BMediaNode::RunMode() const
223 BMediaNode::TimeSource() const
225 PRINT(7, "CALLED BMediaNode::TimeSource()\n");
227 // Return the currently assigned time source
228 if (fTimeSource
!= 0)
231 TRACE("BMediaNode::TimeSource node %ld enter\n", ID());
233 // If the node doesn't have a time source object, we need to create one.
234 // If the node is still unregistered, we can't call MakeTimeSourceFor(),
235 // but since the node does still have the default system time source, we
236 // can use GetSystemTimeSource
238 BMediaNode
* self
= const_cast<BMediaNode
*>(this);
239 self
->fTimeSource
= MediaRosterEx(
240 BMediaRoster::Roster())->MakeTimeSourceObject(fTimeSourceID
);
242 ASSERT(fTimeSource
== self
->fTimeSource
);
244 if (fTimeSource
== 0) {
245 ERROR("BMediaNode::TimeSource: MakeTimeSourceFor failed\n");
247 ASSERT(fTimeSourceID
== fTimeSource
->ID());
248 fTimeSource
->AddMe(self
);
251 TRACE("BMediaNode::TimeSource node %ld leave\n", ID());
258 BMediaNode::ControlPort() const
260 PRINT(7, "CALLED BMediaNode::ControlPort()\n");
266 BMediaNode::ReportError(node_error what
, const BMessage
* info
)
270 // Sanity check the what value
272 case BMediaNode::B_NODE_FAILED_START
:
273 case BMediaNode::B_NODE_FAILED_STOP
:
274 case BMediaNode::B_NODE_FAILED_SEEK
:
275 case BMediaNode::B_NODE_FAILED_SET_RUN_MODE
:
276 case BMediaNode::B_NODE_FAILED_TIME_WARP
:
277 case BMediaNode::B_NODE_FAILED_PREROLL
:
278 case BMediaNode::B_NODE_FAILED_SET_TIME_SOURCE_FOR
:
279 case BMediaNode::B_NODE_IN_DISTRESS
:
282 ERROR("BMediaNode::ReportError: invalid what!\n");
286 // Transmits the error code specified by what to anyone
287 // that's receiving notifications from this node
288 return BPrivate::media::notifications::ReportError(Node(), what
, info
);
293 BMediaNode::NodeStopped(bigtime_t whenPerformance
)
296 // Called by derived classes when they have
297 // finished handling a stop request.
299 // Notify anyone who is listening for stop notifications!
300 BPrivate::media::notifications::NodeStopped(Node(), whenPerformance
);
302 // NOTE: If your node is a BBufferProducer, downstream consumers
303 // will be notified that your node stopped (automatically, no less) through
304 // the BBufferConsumer::ProducerDataStatus(B_PRODUCER_STOPPED) call.
311 * Used in couple with AddTimer, this will cause the BMediaRoster::SyncToNode()
312 * call that requested the timer to return to the caller with an appropriate
316 BMediaNode::TimerExpired(bigtime_t notifyPoint
, int32 cookie
, status_t error
)
319 if (write_port((port_id
)cookie
, 0, &error
, sizeof(error
)) < 0) {
320 TRACE("BMediaNode::TimerExpired: error writing port" B_PRId32
321 ", at notifyPoint" B_PRId64
"\n", cookie
, notifyPoint
);
326 BMediaNode::BMediaNode(const char* name
)
328 TRACE("BMediaNode::BMediaNode: name '%s'\n", name
);
329 _InitObject(name
, NODE_JUST_CREATED_ID
, 0);
334 BMediaNode::WaitForMessage(bigtime_t waitUntil
, uint32 flags
,
337 TRACE("entering: BMediaNode::WaitForMessage()\n");
339 // This function waits until either real time specified by
340 // waitUntil or a message is received on the control port.
341 // The flags are currently unused and should be 0.
342 // Note: about 16 KByte stack used
343 char data
[B_MEDIA_MESSAGE_SIZE
];
347 size
= read_port_etc(ControlPort(), &message
, data
,
348 sizeof(data
), B_ABSOLUTE_TIMEOUT
, waitUntil
);
353 status_t error
= (status_t
)size
;
354 if (error
== B_INTERRUPTED
)
357 if (error
!= B_TIMED_OUT
&& error
!= B_BAD_PORT_ID
) {
358 ERROR("BMediaNode::WaitForMessage: read_port_etc error: %s\n",
365 TRACE("BMediaNode::WaitForMessage request is: %#lx, node %ld, this %p\n",
366 message
, fNodeID
, this);
368 if (message
== GENERAL_PURPOSE_WAKEUP
)
371 if (message
> NODE_MESSAGE_START
&& message
< NODE_MESSAGE_END
) {
372 TRACE("BMediaNode::WaitForMessage calling BMediaNode\n");
374 if (B_OK
== BMediaNode::HandleMessage(message
, data
, size
))
378 if (message
> PRODUCER_MESSAGE_START
&& message
< PRODUCER_MESSAGE_END
) {
380 fProducerThis
= dynamic_cast<BBufferProducer
*>(this);
382 TRACE("BMediaNode::WaitForMessage calling BBufferProducer %p\n",
385 if (fProducerThis
&& fProducerThis
->BBufferProducer::HandleMessage(
386 message
, data
, size
) == B_OK
) {
391 if (message
> CONSUMER_MESSAGE_START
&& message
< CONSUMER_MESSAGE_END
) {
393 fConsumerThis
= dynamic_cast<BBufferConsumer
*>(this);
395 TRACE("BMediaNode::WaitForMessage calling BBufferConsumer %p\n",
398 if (fConsumerThis
&& fConsumerThis
->BBufferConsumer::HandleMessage(
399 message
, data
, size
) == B_OK
) {
404 if (message
> FILEINTERFACE_MESSAGE_START
405 && message
< FILEINTERFACE_MESSAGE_END
) {
406 if (!fFileInterfaceThis
)
407 fFileInterfaceThis
= dynamic_cast<BFileInterface
*>(this);
409 TRACE("BMediaNode::WaitForMessage calling BFileInterface %p\n",
412 if (fFileInterfaceThis
413 && fFileInterfaceThis
->BFileInterface::HandleMessage(
414 message
, data
, size
) == B_OK
) {
419 if (message
> CONTROLLABLE_MESSAGE_START
420 && message
< CONTROLLABLE_MESSAGE_END
) {
421 if (!fControllableThis
)
422 fControllableThis
= dynamic_cast<BControllable
*>(this);
424 TRACE("BMediaNode::WaitForMessage calling BControllable %p\n",
427 if (fControllableThis
428 && fControllableThis
->BControllable::HandleMessage(
429 message
, data
, size
) == B_OK
) {
434 if (message
> TIMESOURCE_MESSAGE_START
435 && message
< TIMESOURCE_MESSAGE_END
) {
436 if (!fTimeSourceThis
)
437 fTimeSourceThis
= dynamic_cast<BTimeSource
*>(this);
439 TRACE("BMediaNode::WaitForMessage calling BTimeSource %p\n",
442 if (fTimeSourceThis
&& fTimeSourceThis
->BTimeSource::HandleMessage(
443 message
, data
, size
) == B_OK
) {
448 TRACE("BMediaNode::WaitForMessage calling default HandleMessage\n");
449 if (HandleMessage(message
, data
, size
) == B_OK
)
452 HandleBadMessage(message
, data
, size
);
459 BMediaNode::Start(bigtime_t performance_time
)
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.
473 BMediaNode::Stop(bigtime_t performance_time
, bool immediate
)
476 // This hook function is called when a node is stopped
477 // by a call to the BMediaRoster. The specified
478 // performanceTime, the time at which the node
479 // should stop running, may be in the future.
480 // It may be overriden by derived classes.
481 // The BMediaEventLooper class handles this event!
482 // The BMediaNode class does nothing here.
487 BMediaNode::Seek(bigtime_t media_time
, bigtime_t performance_time
)
490 // This hook function is called when a node is asked
491 // to seek to the specified mediaTime by a call to
492 // the BMediaRoster. The specified performanceTime,
493 // the time at which the node should begin the seek
494 // operation, may be in the future.
495 // It may be overriden by derived classes.
496 // The BMediaEventLooper class handles this event!
497 // The BMediaNode class does nothing here.
502 BMediaNode::SetRunMode(run_mode mode
)
506 // This is a hook function, and
507 // may be overriden by derived classes.
509 // The functionality here is only to
510 // support those people that don't
511 // use the roster to set the run mode
517 BMediaNode::TimeWarp(bigtime_t at_real_time
, bigtime_t to_performance_time
)
520 // May be overriden by derived classes.
525 BMediaNode::Preroll()
528 // May be overriden by derived classes.
533 BMediaNode::SetTimeSource(BTimeSource
* time_source
)
536 // This is a hook function, and
537 // may be overriden by derived classes.
539 if (time_source
== NULL
|| time_source
== fTimeSource
)
542 // We just trip into debugger, code that tries to do this is broken.
543 debugger("BMediaNode::SetTimeSource() can't be used to set a timesource, "
544 "use BMediaRoster::SetTimeSourceFor()!\n");
549 BMediaNode::HandleMessage(int32 message
, const void* data
, size_t size
)
551 TRACE("BMediaNode::HandleMessage %#lx, node %ld\n", message
, fNodeID
);
553 case NODE_FINAL_RELEASE
:
555 TRACE("BMediaNode::HandleMessage NODE_FINAL_RELEASE, this %p\n",
558 // This is called by the media server to delete the object
559 // after is has been released by all nodes that are using it.
560 // We forward the function to the BMediaRoster, since the
561 // deletion must be done from a different thread, or the
562 // outermost destructor that will exit the thread that is
563 // reading messages from the port (this thread contex) will
564 // quit, and ~BMediaNode destructor won't be called ever.
565 BMessage
msg(NODE_FINAL_RELEASE
);
566 msg
.AddPointer("node", this);
567 BMediaRoster::Roster()->PostMessage(&msg
);
573 const node_start_command
* command
574 = static_cast<const node_start_command
*>(data
);
575 TRACE("BMediaNode::HandleMessage NODE_START, node %ld\n", fNodeID
);
576 Start(command
->performance_time
);
582 const node_stop_command
* command
583 = static_cast<const node_stop_command
*>(data
);
584 TRACE("BMediaNode::HandleMessage NODE_STOP, node %ld\n", fNodeID
);
585 Stop(command
->performance_time
, command
->immediate
);
591 const node_seek_command
* command
592 = static_cast<const node_seek_command
*>(data
);
593 TRACE("BMediaNode::HandleMessage NODE_SEEK, node %ld\n", fNodeID
);
594 Seek(command
->media_time
, command
->performance_time
);
598 case NODE_SET_RUN_MODE
:
600 const node_set_run_mode_command
* command
601 = static_cast<const node_set_run_mode_command
*>(data
);
602 TRACE("BMediaNode::HandleMessage NODE_SET_RUN_MODE,"
603 " node %ld\n", fNodeID
);
604 // Need to change PRODUCER_SET_RUN_MODE_DELAY
605 fRunMode
= command
->mode
;
606 SetRunMode(fRunMode
);
612 const node_time_warp_command
* command
613 = static_cast<const node_time_warp_command
*>(data
);
614 TRACE("BMediaNode::HandleMessage NODE_TIME_WARP,"
615 " node %ld\n", fNodeID
);
616 TimeWarp(command
->at_real_time
, command
->to_performance_time
);
622 TRACE("BMediaNode::HandleMessage NODE_PREROLL, "
623 " node %ld\n", fNodeID
);
630 const node_roll_command
* command
631 = static_cast<const node_roll_command
*>(data
);
633 TRACE("BMediaNode::HandleMessage NODE_ROLL, node %ld\n",
636 if (command
->seek_media_time
!= B_INFINITE_TIMEOUT
)
637 Seek(command
->seek_media_time
,
638 command
->start_performance_time
);
640 Start(command
->start_performance_time
);
641 Stop(command
->stop_performance_time
, false);
647 const node_sync_to_request
* request
648 = static_cast<const node_sync_to_request
*>(data
);
649 node_sync_to_reply reply
;
651 TRACE("BMediaNode::HandleMessage NODE_SYNC_TO, node %ld\n",
654 // If AddTimer return an error the caller will know that the node
655 // doesn't support this feature or there was a problem when adding
656 // it, this will result in SyncToNode returning immediately
657 // to the caller with an error.
658 status_t status
= AddTimer(request
->performance_time
,
661 request
->SendReply(status
, &reply
, sizeof(reply
));
665 case NODE_SET_TIMESOURCE
:
667 const node_set_timesource_command
* command
668 = static_cast<const node_set_timesource_command
*>(data
);
670 TRACE("BMediaNode::HandleMessage NODE_SET_TIMESOURCE,"
671 " node %ld, timesource %ld enter\n",
672 fNodeID
, command
->timesource_id
);
674 fTimeSourceID
= command
->timesource_id
;
677 // As this node already had a timesource, to remove this node
678 // from time source control
679 fTimeSource
->RemoveMe(this);
680 // Release the time source
681 fTimeSource
->Release();
682 // Force next call to TimeSource() to create a new object
686 // Create new time source object and call the SetTimeSource
687 // hook function to notify any derived class
688 fTimeSource
= TimeSource();
689 SetTimeSource(fTimeSource
);
691 TRACE("BMediaNode::HandleMessage NODE_SET_TIMESOURCE, node %ld,"
692 "timesource %ld leave\n", fNodeID
, command
->timesource_id
);
697 case NODE_GET_TIMESOURCE
:
699 const node_get_timesource_request
* request
700 = static_cast<const node_get_timesource_request
*>(data
);
702 TRACE("BMediaNode::HandleMessage NODE_GET_TIMESOURCE,"
703 " node %ld\n", fNodeID
);
705 node_get_timesource_reply reply
;
706 reply
.timesource_id
= fTimeSourceID
;
707 request
->SendReply(B_OK
, &reply
, sizeof(reply
));
711 case NODE_GET_ATTRIBUTES_FOR
:
713 const node_get_attributes_for_request
*request
=
714 (const node_get_attributes_for_request
*) data
;
716 TRACE("BMediaNode::HandleMessage NODE_GET_ATTRIBUTES_FOR,"
717 "node %ld\n", fNodeID
);
719 node_get_attributes_for_reply reply
;
721 media_node_attribute
* addr
;
722 area_id dataArea
= clone_area("client attributes area",
723 (void**)&addr
, B_ANY_ADDRESS
, B_WRITE_AREA
,
727 ERROR("NODE_GET_ATTRIBUTES_FOR can't clone area\n");
731 status_t status
= GetNodeAttributes(addr
, request
->count
);
732 if (status
== B_OK
) {
733 // NOTE: we do it because there's not an easy way
734 // to guess the number of attributes filled.
736 for (i
= 0; i
< request
->count
; i
++) {
737 if (addr
[i
].what
<= 0)
740 reply
.filled_count
= i
;
742 request
->SendReply(status
, &reply
, sizeof(reply
));
743 delete_area(dataArea
);
747 case NODE_REQUEST_COMPLETED
:
749 const node_request_completed_command
* command
750 = static_cast<const node_request_completed_command
*>(data
);
751 TRACE("BMediaNode::HandleMessage NODE_REQUEST_COMPLETED,"
752 " node %ld\n", fNodeID
);
753 RequestCompleted(command
->info
);
766 BMediaNode::HandleBadMessage(int32 code
, const void* buffer
, size_t size
)
770 TRACE("BMediaNode::HandleBadMessage: code %#08lx, buffer %p, size %ld\n",
772 if (code
< NODE_MESSAGE_START
|| code
> TIMESOURCE_MESSAGE_END
) {
773 ERROR("BMediaNode::HandleBadMessage: unknown code!\n");
775 // All messages targeted to nodes should be handled here,
776 // messages targetted to the wrong node should be handled
777 // by returning an error, not by stalling the sender.
778 const request_data
* request
= static_cast<const request_data
* >(buffer
);
780 request
->SendReply(B_ERROR
, &reply
, sizeof(reply
));
786 BMediaNode::AddNodeKind(uint64 kind
)
788 TRACE("BMediaNode::AddNodeKind: node %ld, this %p\n", fNodeID
, this);
794 BMediaNode::operator new(size_t size
)
797 return ::operator new(size
);
802 BMediaNode::operator new(size_t size
, const nothrow_t
&) throw()
805 return ::operator new(size
, nothrow
);
810 BMediaNode::operator delete(void* ptr
)
813 ::operator delete(ptr
);
818 BMediaNode::operator delete(void* ptr
, const nothrow_t
&) throw()
821 ::operator delete(ptr
, nothrow
);
826 BMediaNode::RequestCompleted(const media_request_info
& info
)
829 // This function is called whenever
830 // a request issued by the node is completed.
831 // May be overriden by derived classes.
832 // info.change_tag can be used to match up requests against
833 // the accompaning calles from
834 // BBufferConsumer::RequestFormatChange()
835 // BBufferConsumer::SetOutputBuffersFor()
836 // BBufferConsumer::SetOutputEnabled()
837 // BBufferConsumer::SetVideoClippingFor()
843 BMediaNode::DeleteHook(BMediaNode
* node
)
846 // Attention! We do not unregister TimeSourceObject nodes,
847 // since they are only a shadow object, and the real one still exists
848 if ((fKinds
& NODE_KIND_SHADOW_TIMESOURCE
) == 0)
849 BMediaRoster::Roster()->UnregisterNode(this);
850 delete this; // delete "this" or "node", both are the same
856 BMediaNode::NodeRegistered()
859 // The Media Server calls this hook function
860 // after the node has been registered.
861 // May be overriden by derived classes.
866 BMediaNode::GetNodeAttributes(media_node_attribute
* outAttributes
,
870 // This is implemented by derived classes that fills
871 // it's own attributes to a max of inMaxCount elements.
877 BMediaNode::AddTimer(bigtime_t at_performance_time
, int32 cookie
)
884 status_t
BMediaNode::_Reserved_MediaNode_0(void*) { return B_ERROR
; }
885 status_t
BMediaNode::_Reserved_MediaNode_1(void*) { return B_ERROR
; }
886 status_t
BMediaNode::_Reserved_MediaNode_2(void*) { return B_ERROR
; }
887 status_t
BMediaNode::_Reserved_MediaNode_3(void*) { return B_ERROR
; }
888 status_t
BMediaNode::_Reserved_MediaNode_4(void*) { return B_ERROR
; }
889 status_t
BMediaNode::_Reserved_MediaNode_5(void*) { return B_ERROR
; }
890 status_t
BMediaNode::_Reserved_MediaNode_6(void*) { return B_ERROR
; }
891 status_t
BMediaNode::_Reserved_MediaNode_7(void*) { return B_ERROR
; }
892 status_t
BMediaNode::_Reserved_MediaNode_8(void*) { return B_ERROR
; }
893 status_t
BMediaNode::_Reserved_MediaNode_9(void*) { return B_ERROR
; }
894 status_t
BMediaNode::_Reserved_MediaNode_10(void*) { return B_ERROR
; }
895 status_t
BMediaNode::_Reserved_MediaNode_11(void*) { return B_ERROR
; }
896 status_t
BMediaNode::_Reserved_MediaNode_12(void*) { return B_ERROR
; }
897 status_t
BMediaNode::_Reserved_MediaNode_13(void*) { return B_ERROR
; }
898 status_t
BMediaNode::_Reserved_MediaNode_14(void*) { return B_ERROR
; }
899 status_t
BMediaNode::_Reserved_MediaNode_15(void*) { return B_ERROR
; }
902 private unimplemented
903 BMediaNode::BMediaNode()
904 BMediaNode::BMediaNode(const BMediaNode &clone)
905 BMediaNode &BMediaNode::operator=(const BMediaNode &clone)
909 BMediaNode::_InitObject(const char* name
, media_node_id id
, uint64 kinds
)
911 TRACE("BMediaNode::_InitObject: nodeid %ld, this %p\n", id
, this);
917 strlcpy(fName
, name
, B_MEDIA_NAME_LENGTH
);
918 fRunMode
= B_INCREASE_LATENCY
;
922 fFileInterfaceThis
= 0;
923 fControllableThis
= 0;
926 // Create control port
927 fControlPort
= create_port(64, fName
);
929 // Nodes are assigned the system time source by default
930 fTimeSourceID
= NODE_SYSTEM_TIMESOURCE_ID
;
932 // We can't create the timesource object here, because
933 // every timesource is a BMediaNode, which would result
934 // in infinite recursions
939 BMediaNode::BMediaNode(const char* name
, media_node_id id
, uint32 kinds
)
941 TRACE("BMediaNode::BMediaNode: name '%s', nodeid %ld, kinds %#lx\n",
943 _InitObject(name
, id
, kinds
);
948 BMediaNode::NewChangeTag()
951 // Change tags have been used in BeOS R4 to match up
952 // format change requests between producer and consumer,
953 // This has changed starting with R4.5
954 // now "change tags" are used with the following functions:
955 // BMediaNode::RequestCompleted()
956 // BBufferConsumer::RequestFormatChange()
957 // BBufferConsumer::SetOutputBuffersFor()
958 // BBufferConsumer::SetOutputEnabled()
959 // BBufferConsumer::SetVideoClippingFor()
960 return atomic_add(&BMediaNode::_m_changeTag
,1);
963 // BeOS R4 deprecated API
966 BMediaNode::IncrementChangeTag()
969 // Only present in BeOS R4
970 // Obsoleted in BeOS R4.5 and later
971 // "updates the change tag, so that downstream consumers
972 // know that the node is in a new state."
973 // not supported, only for binary compatibility
979 BMediaNode::ChangeTag()
982 // Only present in BeOS R4
983 // Obsoleted in BeOS R4.5 and later
984 // "returns the node's current change tag value."
985 // not supported, only for binary compatibility
991 BMediaNode::MintChangeTag()
994 // Only present in BeOS R4
995 // Obsoleted in BeOS R4.5 and later
996 // "mints a new, reserved, change tag."
997 // "Call ApplyChangeTag() to apply it to the node"
998 // not supported, only for binary compatibility
1004 BMediaNode::ApplyChangeTag(int32 previously_reserved
)
1007 // Only present in BeOS R4
1008 // Obsoleted in BeOS R4.5 and later
1009 // "this returns B_OK if the new change tag is"
1010 // "successfully applied, or B_MEDIA_STALE_CHANGE_TAG if the new change"
1011 // "count you tried to apply is already obsolete."
1012 // not supported, only for binary compatibility