vfs: check userland buffers before reading them.
[haiku.git] / src / kits / media / MediaNode.cpp
blob362c3f39193b11b2bfc28807701341a5292c0de6
1 /*
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
19 * the distribution.
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
27 * THE SOFTWARE.
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>
41 #include <string.h>
43 #include "DataExchange.h"
44 #include "debug.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"
52 using std::nothrow;
53 using std::nothrow_t;
55 #undef TRACE
56 //#define TRACE_MEDIA_NODE
57 #ifdef TRACE_MEDIA_NODE
58 #define TRACE printf
59 #else
60 #define TRACE(x...)
61 #endif
63 // Don't rename this one, it's used and exported for binary compatibility
64 int32 BMediaNode::_m_changeTag = 0;
66 // media_node
68 media_node media_node::null;
70 media_node::media_node()
72 node(-1),
73 port(-1),
74 kind(0)
79 media_node::~media_node()
83 // media_input
85 media_input::media_input()
87 name[0] = '\0';
91 media_input::~media_input()
95 // media_output
97 media_output::media_output()
99 name[0] = '\0';
103 media_output::~media_output()
107 // live_node_info
109 live_node_info::live_node_info()
111 hint_point(0.0f, 0.0f)
113 name[0] = '\0';
117 live_node_info::~live_node_info()
121 // BMediaNode
123 BMediaNode::~BMediaNode()
125 CALLED();
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
132 if (fTimeSource) {
133 fTimeSource->RemoveMe(this);
134 fTimeSource->Release();
135 fTimeSource = NULL;
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);
143 } else {
144 TRACE("BMediaNode::~BMediaNode: shadow timesource,"
145 " not unregistering\n");
150 BMediaNode*
151 BMediaNode::Acquire()
153 CALLED();
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);
160 return this;
164 BMediaNode*
165 BMediaNode::Release()
167 CALLED();
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.
175 int32 id;
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");
184 return Acquire();
186 return NULL;
188 TRACE("BMediaRoster::Release() the media roster is NULL!");
190 return this;
194 const char*
195 BMediaNode::Name() const
197 CALLED();
198 return fName;
202 media_node_id
203 BMediaNode::ID() const
205 CALLED();
206 return fNodeID;
210 uint64
211 BMediaNode::Kinds() const
213 CALLED();
214 return fKinds & NODE_KIND_USER_MASK;
218 media_node
219 BMediaNode::Node() const
221 CALLED();
222 media_node temp;
223 temp.node = ID();
224 // We *must* call ControlPort(), some derived nodes
225 // use it to start the port read thread!
226 temp.port = ControlPort();
227 temp.kind = Kinds();
228 return temp;
232 BMediaNode::run_mode
233 BMediaNode::RunMode() const
235 CALLED();
236 return fRunMode;
240 BTimeSource*
241 BMediaNode::TimeSource() const
243 PRINT(7, "CALLED BMediaNode::TimeSource()\n");
245 // Return the currently assigned time source
246 if (fTimeSource != 0)
247 return fTimeSource;
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");
264 } else {
265 ASSERT(fTimeSourceID == fTimeSource->ID());
266 fTimeSource->AddMe(self);
269 TRACE("BMediaNode::TimeSource node %ld leave\n", ID());
271 return fTimeSource;
275 port_id
276 BMediaNode::ControlPort() const
278 PRINT(7, "CALLED BMediaNode::ControlPort()\n");
279 return fControlPort;
283 status_t
284 BMediaNode::ReportError(node_error what, const BMessage* info)
286 CALLED();
288 // Sanity check the what value
289 switch (what) {
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:
298 break;
299 default:
300 ERROR("BMediaNode::ReportError: invalid what!\n");
301 return B_BAD_VALUE;
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);
310 status_t
311 BMediaNode::NodeStopped(bigtime_t whenPerformance)
313 UNIMPLEMENTED();
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.
324 return B_OK;
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
331 * value.
333 void
334 BMediaNode::TimerExpired(bigtime_t notifyPoint, int32 cookie, status_t error)
336 CALLED();
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);
351 status_t
352 BMediaNode::WaitForMessage(bigtime_t waitUntil, uint32 flags,
353 void* _reserved_)
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];
362 int32 message;
363 ssize_t size;
365 while (true) {
366 size = read_port_etc(ControlPort(), &message, data,
367 sizeof(data), B_ABSOLUTE_TIMEOUT, waitUntil);
369 if (size >= 0)
370 break;
372 status_t error = (status_t)size;
373 if (error == B_INTERRUPTED)
374 continue;
376 if (error != B_TIMED_OUT && error != B_BAD_PORT_ID) {
377 ERROR("BMediaNode::WaitForMessage: read_port_etc error: %s\n",
378 strerror(error));
381 return error;
384 TRACE("BMediaNode::WaitForMessage request is: %#lx, node %ld, this %p\n",
385 message, fNodeID, this);
387 if (message == GENERAL_PURPOSE_WAKEUP)
388 return B_OK;
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))
394 return B_OK;
397 if (message > PRODUCER_MESSAGE_START && message < PRODUCER_MESSAGE_END) {
398 if (!fProducerThis)
399 fProducerThis = dynamic_cast<BBufferProducer*>(this);
401 TRACE("BMediaNode::WaitForMessage calling BBufferProducer %p\n",
402 fProducerThis);
404 if (fProducerThis && fProducerThis->BBufferProducer::HandleMessage(
405 message, data, size) == B_OK) {
406 return B_OK;
410 if (message > CONSUMER_MESSAGE_START && message < CONSUMER_MESSAGE_END) {
411 if (!fConsumerThis)
412 fConsumerThis = dynamic_cast<BBufferConsumer*>(this);
414 TRACE("BMediaNode::WaitForMessage calling BBufferConsumer %p\n",
415 fConsumerThis);
417 if (fConsumerThis && fConsumerThis->BBufferConsumer::HandleMessage(
418 message, data, size) == B_OK) {
419 return 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",
429 fFileInterfaceThis);
431 if (fFileInterfaceThis
432 && fFileInterfaceThis->BFileInterface::HandleMessage(
433 message, data, size) == B_OK) {
434 return 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",
444 fControllableThis);
446 if (fControllableThis
447 && fControllableThis->BControllable::HandleMessage(
448 message, data, size) == B_OK) {
449 return 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",
459 fTimeSourceThis);
461 if (fTimeSourceThis && fTimeSourceThis->BTimeSource::HandleMessage(
462 message, data, size) == B_OK) {
463 return B_OK;
467 TRACE("BMediaNode::WaitForMessage calling default HandleMessage\n");
468 if (HandleMessage(message, data, size) == B_OK)
469 return B_OK;
471 HandleBadMessage(message, data, size);
473 return B_ERROR;
477 void
478 BMediaNode::Start(bigtime_t performance_time)
480 CALLED();
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.
491 void
492 BMediaNode::Stop(bigtime_t performance_time, bool immediate)
494 CALLED();
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.
505 void
506 BMediaNode::Seek(bigtime_t media_time, bigtime_t performance_time)
508 CALLED();
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.
520 void
521 BMediaNode::SetRunMode(run_mode mode)
523 CALLED();
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
531 fRunMode = mode;
535 void
536 BMediaNode::TimeWarp(bigtime_t at_real_time, bigtime_t to_performance_time)
538 CALLED();
539 // May be overriden by derived classes.
543 void
544 BMediaNode::Preroll()
546 CALLED();
547 // May be overriden by derived classes.
551 void
552 BMediaNode::SetTimeSource(BTimeSource* time_source)
554 CALLED();
555 // This is a hook function, and
556 // may be overriden by derived classes.
558 if (time_source == NULL || time_source == fTimeSource)
559 return;
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");
567 status_t
568 BMediaNode::HandleMessage(int32 message, const void* data, size_t size)
570 TRACE("BMediaNode::HandleMessage %#lx, node %ld\n", message, fNodeID);
571 switch (message) {
572 case NODE_FINAL_RELEASE:
574 TRACE("BMediaNode::HandleMessage NODE_FINAL_RELEASE, this %p\n",
575 this);
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);
587 return B_OK;
590 case NODE_START:
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);
596 return B_OK;
599 case NODE_STOP:
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);
605 return B_OK;
608 case NODE_SEEK:
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);
614 return B_OK;
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);
626 return B_OK;
629 case NODE_TIME_WARP:
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);
636 return B_OK;
639 case NODE_PREROLL:
641 TRACE("BMediaNode::HandleMessage NODE_PREROLL, "
642 " node %ld\n", fNodeID);
643 Preroll();
644 return B_OK;
647 case NODE_ROLL:
649 const node_roll_command* command
650 = static_cast<const node_roll_command*>(data);
652 TRACE("BMediaNode::HandleMessage NODE_ROLL, node %ld\n",
653 fNodeID);
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);
661 return B_OK;
664 case NODE_SYNC_TO:
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",
671 fNodeID);
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,
678 request->port);
680 request->SendReply(status, &reply, sizeof(reply));
681 return B_OK;
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;
695 if (fTimeSource) {
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
702 fTimeSource = 0;
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);
713 return B_OK;
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));
727 return B_OK;
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,
743 request->area);
745 if (dataArea < 0) {
746 ERROR("NODE_GET_ATTRIBUTES_FOR can't clone area\n");
747 return B_NO_MEMORY;
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.
754 size_t i;
755 for (i = 0; i < request->count; i++) {
756 if (addr[i].what <= 0)
757 break;
759 reply.filled_count = i;
761 request->SendReply(status, &reply, sizeof(reply));
762 delete_area(dataArea);
763 return B_OK;
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);
773 return B_OK;
776 default:
777 return B_ERROR;
780 return B_ERROR;
784 void
785 BMediaNode::HandleBadMessage(int32 code, const void* buffer, size_t size)
787 CALLED();
789 TRACE("BMediaNode::HandleBadMessage: code %#08lx, buffer %p, size %ld\n",
790 code, buffer, size);
791 if (code < NODE_MESSAGE_START || code > TIMESOURCE_MESSAGE_END) {
792 ERROR("BMediaNode::HandleBadMessage: unknown code!\n");
793 } else {
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);
798 reply_data reply;
799 request->SendReply(B_ERROR, &reply, sizeof(reply));
804 void
805 BMediaNode::AddNodeKind(uint64 kind)
807 TRACE("BMediaNode::AddNodeKind: node %ld, this %p\n", fNodeID, this);
808 fKinds |= kind;
812 void*
813 BMediaNode::operator new(size_t size)
815 CALLED();
816 return ::operator new(size);
820 void*
821 BMediaNode::operator new(size_t size, const nothrow_t&) throw()
823 CALLED();
824 return ::operator new(size, nothrow);
828 void
829 BMediaNode::operator delete(void* ptr)
831 CALLED();
832 ::operator delete(ptr);
836 void
837 BMediaNode::operator delete(void* ptr, const nothrow_t&) throw()
839 CALLED();
840 ::operator delete(ptr, nothrow);
844 status_t
845 BMediaNode::RequestCompleted(const media_request_info& info)
847 CALLED();
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()
857 return B_OK;
861 status_t
862 BMediaNode::DeleteHook(BMediaNode* node)
864 CALLED();
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
870 return B_OK;
874 void
875 BMediaNode::NodeRegistered()
877 CALLED();
878 // The Media Server calls this hook function
879 // after the node has been registered.
880 // May be overriden by derived classes.
884 status_t
885 BMediaNode::GetNodeAttributes(media_node_attribute* outAttributes,
886 size_t inMaxCount)
888 CALLED();
889 // This is implemented by derived classes that fills
890 // it's own attributes to a max of inMaxCount elements.
891 return B_ERROR;
895 status_t
896 BMediaNode::AddTimer(bigtime_t at_performance_time, int32 cookie)
898 CALLED();
899 return B_ERROR;
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)
927 void
928 BMediaNode::_InitObject(const char* name, media_node_id id, uint64 kinds)
930 TRACE("BMediaNode::_InitObject: nodeid %ld, this %p\n", id, this);
932 fNodeID = id;
933 fRefCount = 1;
934 fName[0] = 0;
935 if (name)
936 strlcpy(fName, name, B_MEDIA_NAME_LENGTH);
937 fRunMode = B_INCREASE_LATENCY;
938 fKinds = kinds;
939 fProducerThis = 0;
940 fConsumerThis = 0;
941 fFileInterfaceThis = 0;
942 fControllableThis = 0;
943 fTimeSourceThis = 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
954 fTimeSource = NULL;
958 BMediaNode::BMediaNode(const char* name, media_node_id id, uint32 kinds)
960 TRACE("BMediaNode::BMediaNode: name '%s', nodeid %ld, kinds %#lx\n",
961 name, id, kinds);
962 _InitObject(name, id, kinds);
966 int32
967 BMediaNode::NewChangeTag()
969 CALLED();
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
984 int32
985 BMediaNode::IncrementChangeTag()
987 CALLED();
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
993 return 0;
997 int32
998 BMediaNode::ChangeTag()
1000 UNIMPLEMENTED();
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
1005 return 0;
1009 int32
1010 BMediaNode::MintChangeTag()
1012 UNIMPLEMENTED();
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
1018 return 0;
1022 status_t
1023 BMediaNode::ApplyChangeTag(int32 previously_reserved)
1025 UNIMPLEMENTED();
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
1032 return B_OK;