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 if (atomic_add(&fRefCount
,1) == 0) {
155 status_t status
= B_ERROR
;
156 BMediaRoster
* roster
= BMediaRoster::Roster(&status
);
157 if (roster
!= NULL
&& status
== B_OK
)
158 MediaRosterEx(roster
)->RegisterLocalNode(this);
165 BMediaNode::Release()
168 if (atomic_add(&fRefCount
, -1) == 1) {
169 status_t status
= B_ERROR
;
170 BMediaRoster
* roster
= BMediaRoster::Roster(&status
);
171 if (roster
!= NULL
&& status
== B_OK
) {
172 MediaRosterEx(roster
)->UnregisterLocalNode(this);
174 // Only addons needs the configuration to be saved.
176 if (AddOn(&id
) != NULL
) {
177 TRACE("BMediaNode::Release() saving node %ld"
178 " configuration\n", fNodeID
);
179 MediaRosterEx(roster
)->SaveNodeConfiguration(this);
182 if (DeleteHook(this) != B_OK
) {
183 ERROR("BMediaNode::Release(): DeleteHook failed\n");
188 TRACE("BMediaRoster::Release() the media roster is NULL!");
195 BMediaNode::Name() const
203 BMediaNode::ID() const
211 BMediaNode::Kinds() const
214 return fKinds
& NODE_KIND_USER_MASK
;
219 BMediaNode::Node() const
224 // We *must* call ControlPort(), some derived nodes
225 // use it to start the port read thread!
226 temp
.port
= ControlPort();
233 BMediaNode::RunMode() const
241 BMediaNode::TimeSource() const
243 PRINT(7, "CALLED BMediaNode::TimeSource()\n");
245 // Return the currently assigned time source
246 if (fTimeSource
!= 0)
249 TRACE("BMediaNode::TimeSource node %ld enter\n", ID());
251 // If the node doesn't have a time source object, we need to create one.
252 // If the node is still unregistered, we can't call MakeTimeSourceFor(),
253 // but since the node does still have the default system time source, we
254 // can use GetSystemTimeSource
256 BMediaNode
* self
= const_cast<BMediaNode
*>(this);
257 self
->fTimeSource
= MediaRosterEx(
258 BMediaRoster::Roster())->MakeTimeSourceObject(fTimeSourceID
);
260 ASSERT(fTimeSource
== self
->fTimeSource
);
262 if (fTimeSource
== 0) {
263 ERROR("BMediaNode::TimeSource: MakeTimeSourceFor failed\n");
265 ASSERT(fTimeSourceID
== fTimeSource
->ID());
266 fTimeSource
->AddMe(self
);
269 TRACE("BMediaNode::TimeSource node %ld leave\n", ID());
276 BMediaNode::ControlPort() const
278 PRINT(7, "CALLED BMediaNode::ControlPort()\n");
284 BMediaNode::ReportError(node_error what
, const BMessage
* info
)
288 // Sanity check the what value
290 case BMediaNode::B_NODE_FAILED_START
:
291 case BMediaNode::B_NODE_FAILED_STOP
:
292 case BMediaNode::B_NODE_FAILED_SEEK
:
293 case BMediaNode::B_NODE_FAILED_SET_RUN_MODE
:
294 case BMediaNode::B_NODE_FAILED_TIME_WARP
:
295 case BMediaNode::B_NODE_FAILED_PREROLL
:
296 case BMediaNode::B_NODE_FAILED_SET_TIME_SOURCE_FOR
:
297 case BMediaNode::B_NODE_IN_DISTRESS
:
300 ERROR("BMediaNode::ReportError: invalid what!\n");
304 // Transmits the error code specified by what to anyone
305 // that's receiving notifications from this node
306 return BPrivate::media::notifications::ReportError(Node(), what
, info
);
311 BMediaNode::NodeStopped(bigtime_t whenPerformance
)
314 // Called by derived classes when they have
315 // finished handling a stop request.
317 // Notify anyone who is listening for stop notifications!
318 BPrivate::media::notifications::NodeStopped(Node(), whenPerformance
);
320 // NOTE: If your node is a BBufferProducer, downstream consumers
321 // will be notified that your node stopped (automatically, no less) through
322 // the BBufferConsumer::ProducerDataStatus(B_PRODUCER_STOPPED) call.
329 * Used in couple with AddTimer, this will cause the BMediaRoster::SyncToNode()
330 * call that requested the timer to return to the caller with an appropriate
334 BMediaNode::TimerExpired(bigtime_t notifyPoint
, int32 cookie
, status_t error
)
337 if (write_port((port_id
)cookie
, 0, &error
, sizeof(error
)) < 0) {
338 TRACE("BMediaNode::TimerExpired: error writing port" B_PRId32
339 ", at notifyPoint" B_PRId64
"\n", cookie
, notifyPoint
);
344 BMediaNode::BMediaNode(const char* name
)
346 TRACE("BMediaNode::BMediaNode: name '%s'\n", name
);
347 _InitObject(name
, NODE_JUST_CREATED_ID
, 0);
352 BMediaNode::WaitForMessage(bigtime_t waitUntil
, uint32 flags
,
355 TRACE("entering: BMediaNode::WaitForMessage()\n");
357 // This function waits until either real time specified by
358 // waitUntil or a message is received on the control port.
359 // The flags are currently unused and should be 0.
360 // Note: about 16 KByte stack used
361 char data
[B_MEDIA_MESSAGE_SIZE
];
366 size
= read_port_etc(ControlPort(), &message
, data
,
367 sizeof(data
), B_ABSOLUTE_TIMEOUT
, waitUntil
);
372 status_t error
= (status_t
)size
;
373 if (error
== B_INTERRUPTED
)
376 if (error
!= B_TIMED_OUT
&& error
!= B_BAD_PORT_ID
) {
377 ERROR("BMediaNode::WaitForMessage: read_port_etc error: %s\n",
384 TRACE("BMediaNode::WaitForMessage request is: %#lx, node %ld, this %p\n",
385 message
, fNodeID
, this);
387 if (message
== GENERAL_PURPOSE_WAKEUP
)
390 if (message
> NODE_MESSAGE_START
&& message
< NODE_MESSAGE_END
) {
391 TRACE("BMediaNode::WaitForMessage calling BMediaNode\n");
393 if (B_OK
== BMediaNode::HandleMessage(message
, data
, size
))
397 if (message
> PRODUCER_MESSAGE_START
&& message
< PRODUCER_MESSAGE_END
) {
399 fProducerThis
= dynamic_cast<BBufferProducer
*>(this);
401 TRACE("BMediaNode::WaitForMessage calling BBufferProducer %p\n",
404 if (fProducerThis
&& fProducerThis
->BBufferProducer::HandleMessage(
405 message
, data
, size
) == B_OK
) {
410 if (message
> CONSUMER_MESSAGE_START
&& message
< CONSUMER_MESSAGE_END
) {
412 fConsumerThis
= dynamic_cast<BBufferConsumer
*>(this);
414 TRACE("BMediaNode::WaitForMessage calling BBufferConsumer %p\n",
417 if (fConsumerThis
&& fConsumerThis
->BBufferConsumer::HandleMessage(
418 message
, data
, size
) == B_OK
) {
423 if (message
> FILEINTERFACE_MESSAGE_START
424 && message
< FILEINTERFACE_MESSAGE_END
) {
425 if (!fFileInterfaceThis
)
426 fFileInterfaceThis
= dynamic_cast<BFileInterface
*>(this);
428 TRACE("BMediaNode::WaitForMessage calling BFileInterface %p\n",
431 if (fFileInterfaceThis
432 && fFileInterfaceThis
->BFileInterface::HandleMessage(
433 message
, data
, size
) == B_OK
) {
438 if (message
> CONTROLLABLE_MESSAGE_START
439 && message
< CONTROLLABLE_MESSAGE_END
) {
440 if (!fControllableThis
)
441 fControllableThis
= dynamic_cast<BControllable
*>(this);
443 TRACE("BMediaNode::WaitForMessage calling BControllable %p\n",
446 if (fControllableThis
447 && fControllableThis
->BControllable::HandleMessage(
448 message
, data
, size
) == B_OK
) {
453 if (message
> TIMESOURCE_MESSAGE_START
454 && message
< TIMESOURCE_MESSAGE_END
) {
455 if (!fTimeSourceThis
)
456 fTimeSourceThis
= dynamic_cast<BTimeSource
*>(this);
458 TRACE("BMediaNode::WaitForMessage calling BTimeSource %p\n",
461 if (fTimeSourceThis
&& fTimeSourceThis
->BTimeSource::HandleMessage(
462 message
, data
, size
) == B_OK
) {
467 TRACE("BMediaNode::WaitForMessage calling default HandleMessage\n");
468 if (HandleMessage(message
, data
, size
) == B_OK
)
471 HandleBadMessage(message
, data
, size
);
478 BMediaNode::Start(bigtime_t performance_time
)
481 // This hook function is called when a node is started
482 // by a call to the BMediaRoster. The specified
483 // performanceTime, the time at which the node
484 // should start running, may be in the future.
485 // It may be overriden by derived classes.
486 // The BMediaEventLooper class handles this event!
487 // The BMediaNode class does nothing here.
492 BMediaNode::Stop(bigtime_t performance_time
, bool immediate
)
495 // This hook function is called when a node is stopped
496 // by a call to the BMediaRoster. The specified
497 // performanceTime, the time at which the node
498 // should stop running, may be in the future.
499 // It may be overriden by derived classes.
500 // The BMediaEventLooper class handles this event!
501 // The BMediaNode class does nothing here.
506 BMediaNode::Seek(bigtime_t media_time
, bigtime_t performance_time
)
509 // This hook function is called when a node is asked
510 // to seek to the specified mediaTime by a call to
511 // the BMediaRoster. The specified performanceTime,
512 // the time at which the node should begin the seek
513 // operation, may be in the future.
514 // It may be overriden by derived classes.
515 // The BMediaEventLooper class handles this event!
516 // The BMediaNode class does nothing here.
521 BMediaNode::SetRunMode(run_mode mode
)
525 // This is a hook function, and
526 // may be overriden by derived classes.
528 // The functionality here is only to
529 // support those people that don't
530 // use the roster to set the run mode
536 BMediaNode::TimeWarp(bigtime_t at_real_time
, bigtime_t to_performance_time
)
539 // May be overriden by derived classes.
544 BMediaNode::Preroll()
547 // May be overriden by derived classes.
552 BMediaNode::SetTimeSource(BTimeSource
* time_source
)
555 // This is a hook function, and
556 // may be overriden by derived classes.
558 if (time_source
== NULL
|| time_source
== fTimeSource
)
561 // We just trip into debugger, code that tries to do this is broken.
562 debugger("BMediaNode::SetTimeSource() can't be used to set a timesource, "
563 "use BMediaRoster::SetTimeSourceFor()!\n");
568 BMediaNode::HandleMessage(int32 message
, const void* data
, size_t size
)
570 TRACE("BMediaNode::HandleMessage %#lx, node %ld\n", message
, fNodeID
);
572 case NODE_FINAL_RELEASE
:
574 TRACE("BMediaNode::HandleMessage NODE_FINAL_RELEASE, this %p\n",
577 // This is called by the media server to delete the object
578 // after is has been released by all nodes that are using it.
579 // We forward the function to the BMediaRoster, since the
580 // deletion must be done from a different thread, or the
581 // outermost destructor that will exit the thread that is
582 // reading messages from the port (this thread contex) will
583 // quit, and ~BMediaNode destructor won't be called ever.
584 BMessage
msg(NODE_FINAL_RELEASE
);
585 msg
.AddPointer("node", this);
586 BMediaRoster::Roster()->PostMessage(&msg
);
592 const node_start_command
* command
593 = static_cast<const node_start_command
*>(data
);
594 TRACE("BMediaNode::HandleMessage NODE_START, node %ld\n", fNodeID
);
595 Start(command
->performance_time
);
601 const node_stop_command
* command
602 = static_cast<const node_stop_command
*>(data
);
603 TRACE("BMediaNode::HandleMessage NODE_STOP, node %ld\n", fNodeID
);
604 Stop(command
->performance_time
, command
->immediate
);
610 const node_seek_command
* command
611 = static_cast<const node_seek_command
*>(data
);
612 TRACE("BMediaNode::HandleMessage NODE_SEEK, node %ld\n", fNodeID
);
613 Seek(command
->media_time
, command
->performance_time
);
617 case NODE_SET_RUN_MODE
:
619 const node_set_run_mode_command
* command
620 = static_cast<const node_set_run_mode_command
*>(data
);
621 TRACE("BMediaNode::HandleMessage NODE_SET_RUN_MODE,"
622 " node %ld\n", fNodeID
);
623 // Need to change PRODUCER_SET_RUN_MODE_DELAY
624 fRunMode
= command
->mode
;
625 SetRunMode(fRunMode
);
631 const node_time_warp_command
* command
632 = static_cast<const node_time_warp_command
*>(data
);
633 TRACE("BMediaNode::HandleMessage NODE_TIME_WARP,"
634 " node %ld\n", fNodeID
);
635 TimeWarp(command
->at_real_time
, command
->to_performance_time
);
641 TRACE("BMediaNode::HandleMessage NODE_PREROLL, "
642 " node %ld\n", fNodeID
);
649 const node_roll_command
* command
650 = static_cast<const node_roll_command
*>(data
);
652 TRACE("BMediaNode::HandleMessage NODE_ROLL, node %ld\n",
655 if (command
->seek_media_time
!= B_INFINITE_TIMEOUT
)
656 Seek(command
->seek_media_time
,
657 command
->start_performance_time
);
659 Start(command
->start_performance_time
);
660 Stop(command
->stop_performance_time
, false);
666 const node_sync_to_request
* request
667 = static_cast<const node_sync_to_request
*>(data
);
668 node_sync_to_reply reply
;
670 TRACE("BMediaNode::HandleMessage NODE_SYNC_TO, node %ld\n",
673 // If AddTimer return an error the caller will know that the node
674 // doesn't support this feature or there was a problem when adding
675 // it, this will result in SyncToNode returning immediately
676 // to the caller with an error.
677 status_t status
= AddTimer(request
->performance_time
,
680 request
->SendReply(status
, &reply
, sizeof(reply
));
684 case NODE_SET_TIMESOURCE
:
686 const node_set_timesource_command
* command
687 = static_cast<const node_set_timesource_command
*>(data
);
689 TRACE("BMediaNode::HandleMessage NODE_SET_TIMESOURCE,"
690 " node %ld, timesource %ld enter\n",
691 fNodeID
, command
->timesource_id
);
693 fTimeSourceID
= command
->timesource_id
;
696 // As this node already had a timesource, to remove this node
697 // from time source control
698 fTimeSource
->RemoveMe(this);
699 // Release the time source
700 fTimeSource
->Release();
701 // Force next call to TimeSource() to create a new object
705 // Create new time source object and call the SetTimeSource
706 // hook function to notify any derived class
707 fTimeSource
= TimeSource();
708 SetTimeSource(fTimeSource
);
710 TRACE("BMediaNode::HandleMessage NODE_SET_TIMESOURCE, node %ld,"
711 "timesource %ld leave\n", fNodeID
, command
->timesource_id
);
716 case NODE_GET_TIMESOURCE
:
718 const node_get_timesource_request
* request
719 = static_cast<const node_get_timesource_request
*>(data
);
721 TRACE("BMediaNode::HandleMessage NODE_GET_TIMESOURCE,"
722 " node %ld\n", fNodeID
);
724 node_get_timesource_reply reply
;
725 reply
.timesource_id
= fTimeSourceID
;
726 request
->SendReply(B_OK
, &reply
, sizeof(reply
));
730 case NODE_GET_ATTRIBUTES_FOR
:
732 const node_get_attributes_for_request
*request
=
733 (const node_get_attributes_for_request
*) data
;
735 TRACE("BMediaNode::HandleMessage NODE_GET_ATTRIBUTES_FOR,"
736 "node %ld\n", fNodeID
);
738 node_get_attributes_for_reply reply
;
740 media_node_attribute
* addr
;
741 area_id dataArea
= clone_area("client attributes area",
742 (void**)&addr
, B_ANY_ADDRESS
, B_WRITE_AREA
,
746 ERROR("NODE_GET_ATTRIBUTES_FOR can't clone area\n");
750 status_t status
= GetNodeAttributes(addr
, request
->count
);
751 if (status
== B_OK
) {
752 // NOTE: we do it because there's not an easy way
753 // to guess the number of attributes filled.
755 for (i
= 0; i
< request
->count
; i
++) {
756 if (addr
[i
].what
<= 0)
759 reply
.filled_count
= i
;
761 request
->SendReply(status
, &reply
, sizeof(reply
));
762 delete_area(dataArea
);
766 case NODE_REQUEST_COMPLETED
:
768 const node_request_completed_command
* command
769 = static_cast<const node_request_completed_command
*>(data
);
770 TRACE("BMediaNode::HandleMessage NODE_REQUEST_COMPLETED,"
771 " node %ld\n", fNodeID
);
772 RequestCompleted(command
->info
);
785 BMediaNode::HandleBadMessage(int32 code
, const void* buffer
, size_t size
)
789 TRACE("BMediaNode::HandleBadMessage: code %#08lx, buffer %p, size %ld\n",
791 if (code
< NODE_MESSAGE_START
|| code
> TIMESOURCE_MESSAGE_END
) {
792 ERROR("BMediaNode::HandleBadMessage: unknown code!\n");
794 // All messages targeted to nodes should be handled here,
795 // messages targetted to the wrong node should be handled
796 // by returning an error, not by stalling the sender.
797 const request_data
* request
= static_cast<const request_data
* >(buffer
);
799 request
->SendReply(B_ERROR
, &reply
, sizeof(reply
));
805 BMediaNode::AddNodeKind(uint64 kind
)
807 TRACE("BMediaNode::AddNodeKind: node %ld, this %p\n", fNodeID
, this);
813 BMediaNode::operator new(size_t size
)
816 return ::operator new(size
);
821 BMediaNode::operator new(size_t size
, const nothrow_t
&) throw()
824 return ::operator new(size
, nothrow
);
829 BMediaNode::operator delete(void* ptr
)
832 ::operator delete(ptr
);
837 BMediaNode::operator delete(void* ptr
, const nothrow_t
&) throw()
840 ::operator delete(ptr
, nothrow
);
845 BMediaNode::RequestCompleted(const media_request_info
& info
)
848 // This function is called whenever
849 // a request issued by the node is completed.
850 // May be overriden by derived classes.
851 // info.change_tag can be used to match up requests against
852 // the accompaning calles from
853 // BBufferConsumer::RequestFormatChange()
854 // BBufferConsumer::SetOutputBuffersFor()
855 // BBufferConsumer::SetOutputEnabled()
856 // BBufferConsumer::SetVideoClippingFor()
862 BMediaNode::DeleteHook(BMediaNode
* node
)
865 // Attention! We do not unregister TimeSourceObject nodes,
866 // since they are only a shadow object, and the real one still exists
867 if ((fKinds
& NODE_KIND_SHADOW_TIMESOURCE
) == 0)
868 BMediaRoster::Roster()->UnregisterNode(this);
869 delete this; // delete "this" or "node", both are the same
875 BMediaNode::NodeRegistered()
878 // The Media Server calls this hook function
879 // after the node has been registered.
880 // May be overriden by derived classes.
885 BMediaNode::GetNodeAttributes(media_node_attribute
* outAttributes
,
889 // This is implemented by derived classes that fills
890 // it's own attributes to a max of inMaxCount elements.
896 BMediaNode::AddTimer(bigtime_t at_performance_time
, int32 cookie
)
903 status_t
BMediaNode::_Reserved_MediaNode_0(void*) { return B_ERROR
; }
904 status_t
BMediaNode::_Reserved_MediaNode_1(void*) { return B_ERROR
; }
905 status_t
BMediaNode::_Reserved_MediaNode_2(void*) { return B_ERROR
; }
906 status_t
BMediaNode::_Reserved_MediaNode_3(void*) { return B_ERROR
; }
907 status_t
BMediaNode::_Reserved_MediaNode_4(void*) { return B_ERROR
; }
908 status_t
BMediaNode::_Reserved_MediaNode_5(void*) { return B_ERROR
; }
909 status_t
BMediaNode::_Reserved_MediaNode_6(void*) { return B_ERROR
; }
910 status_t
BMediaNode::_Reserved_MediaNode_7(void*) { return B_ERROR
; }
911 status_t
BMediaNode::_Reserved_MediaNode_8(void*) { return B_ERROR
; }
912 status_t
BMediaNode::_Reserved_MediaNode_9(void*) { return B_ERROR
; }
913 status_t
BMediaNode::_Reserved_MediaNode_10(void*) { return B_ERROR
; }
914 status_t
BMediaNode::_Reserved_MediaNode_11(void*) { return B_ERROR
; }
915 status_t
BMediaNode::_Reserved_MediaNode_12(void*) { return B_ERROR
; }
916 status_t
BMediaNode::_Reserved_MediaNode_13(void*) { return B_ERROR
; }
917 status_t
BMediaNode::_Reserved_MediaNode_14(void*) { return B_ERROR
; }
918 status_t
BMediaNode::_Reserved_MediaNode_15(void*) { return B_ERROR
; }
921 private unimplemented
922 BMediaNode::BMediaNode()
923 BMediaNode::BMediaNode(const BMediaNode &clone)
924 BMediaNode &BMediaNode::operator=(const BMediaNode &clone)
928 BMediaNode::_InitObject(const char* name
, media_node_id id
, uint64 kinds
)
930 TRACE("BMediaNode::_InitObject: nodeid %ld, this %p\n", id
, this);
936 strlcpy(fName
, name
, B_MEDIA_NAME_LENGTH
);
937 fRunMode
= B_INCREASE_LATENCY
;
941 fFileInterfaceThis
= 0;
942 fControllableThis
= 0;
945 // Create control port
946 fControlPort
= create_port(64, fName
);
948 // Nodes are assigned the system time source by default
949 fTimeSourceID
= NODE_SYSTEM_TIMESOURCE_ID
;
951 // We can't create the timesource object here, because
952 // every timesource is a BMediaNode, which would result
953 // in infinite recursions
958 BMediaNode::BMediaNode(const char* name
, media_node_id id
, uint32 kinds
)
960 TRACE("BMediaNode::BMediaNode: name '%s', nodeid %ld, kinds %#lx\n",
962 _InitObject(name
, id
, kinds
);
967 BMediaNode::NewChangeTag()
970 // Change tags have been used in BeOS R4 to match up
971 // format change requests between producer and consumer,
972 // This has changed starting with R4.5
973 // now "change tags" are used with the following functions:
974 // BMediaNode::RequestCompleted()
975 // BBufferConsumer::RequestFormatChange()
976 // BBufferConsumer::SetOutputBuffersFor()
977 // BBufferConsumer::SetOutputEnabled()
978 // BBufferConsumer::SetVideoClippingFor()
979 return atomic_add(&BMediaNode::_m_changeTag
,1);
982 // BeOS R4 deprecated API
985 BMediaNode::IncrementChangeTag()
988 // Only present in BeOS R4
989 // Obsoleted in BeOS R4.5 and later
990 // "updates the change tag, so that downstream consumers
991 // know that the node is in a new state."
992 // not supported, only for binary compatibility
998 BMediaNode::ChangeTag()
1001 // Only present in BeOS R4
1002 // Obsoleted in BeOS R4.5 and later
1003 // "returns the node's current change tag value."
1004 // not supported, only for binary compatibility
1010 BMediaNode::MintChangeTag()
1013 // Only present in BeOS R4
1014 // Obsoleted in BeOS R4.5 and later
1015 // "mints a new, reserved, change tag."
1016 // "Call ApplyChangeTag() to apply it to the node"
1017 // not supported, only for binary compatibility
1023 BMediaNode::ApplyChangeTag(int32 previously_reserved
)
1026 // Only present in BeOS R4
1027 // Obsoleted in BeOS R4.5 and later
1028 // "this returns B_OK if the new change tag is"
1029 // "successfully applied, or B_MEDIA_STALE_CHANGE_TAG if the new change"
1030 // "count you tried to apply is already obsolete."
1031 // not supported, only for binary compatibility