vfs: check userland buffers before reading them.
[haiku.git] / src / apps / cortex / NodeManager / NodeRef.h
blob8a167f6b9bb8a5a1ea53cf6a1f318a33e980d369
1 /*
2 * Copyright (c) 1999-2000, Eric Moon.
3 * All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions, and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions, and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * 3. The name of the author may not be used to endorse or promote products
17 * derived from this software without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR
20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21 * OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
23 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
26 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
27 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 // NodeRef.h (Cortex/NodeManager)
34 // * PURPOSE
35 // Represents a NodeManager reference to a live Media Kit Node.
37 // * FEATURES UNDER CONSIDERATION +++++
38 // - lazy referencing: m_released becomes m_referenced; only reference
39 // externally created nodes once they've been grouped or connected.
40 // +++++ or disconnected? keep a'thinkin...
41 // - expose dormant_node_info
43 // * HISTORY
44 // e.moon 11aug99 Added kind().
45 // e.moon 9aug99 Moved position & cycle threads into NodeRef;
46 // no more 'group transport thread'.
47 // e.moon 25jun99 Begun
49 #ifndef __NodeRef_H__
50 #define __NodeRef_H__
52 #include <MediaAddOn.h>
53 #include <MediaNode.h>
54 #include <String.h>
56 #include <vector>
58 #include "ILockable.h"
59 #include "MultiInvoker.h"
60 #include "ObservableHandler.h"
61 #include "observe.h"
63 #include "cortex_defs.h"
65 __BEGIN_CORTEX_NAMESPACE
67 class Connection;
68 class NodeManager;
69 class NodeGroup;
70 class NodeSyncThread;
72 class NodeRef :
73 public ObservableHandler,
74 protected ILockable {
76 typedef ObservableHandler _inherited;
78 friend class NodeManager;
79 friend class NodeGroup;
81 public: // *** messages
82 enum message_t {
83 // OUTBOUND
84 // nodeID: int32
85 // target: BMessenger
86 M_OBSERVER_ADDED =NodeRef_message_base,
87 M_OBSERVER_REMOVED,
88 M_RELEASED,
90 // OUTBOUND
91 // nodeID: int32
92 // groupID: int32
93 M_GROUP_CHANGED,
95 // nodeID: int32
96 // runMode: int32
97 M_RUN_MODE_CHANGED,
99 // +++++
100 M_INPUTS_CHANGED, //nyi
101 M_OUTPUTS_CHANGED, //nyi
103 // OUTBOUND
104 // * only sent to position listeners
105 // nodeID: int32
106 // when: int64
107 // position: int64
108 M_POSITION,
110 // INBOUND
111 // runMode: int32
112 // delay: int64 (bigtime_t; applies only to B_RECORDING mode)
113 M_SET_RUN_MODE,
115 // INBOUND
116 M_PREROLL,
118 // INBOUND
119 // "cycling"; bool (OR "be:value"; int32)
120 M_SET_CYCLING,
122 // OUTBOUND
123 // "cycling"; bool
124 M_CYCLING_CHANGED
127 public: // *** flags
128 enum flag_t {
129 // node-level transport restrictions
130 NO_START_STOP = 1<<1,
131 NO_SEEK = 1<<2,
132 NO_PREROLL = 1<<3,
134 // [e.moon 28sep99] useful for misbehaved nodes
135 NO_STOP = 1<<4,
137 // [e.moon 11oct99]
138 // Disables media-roster connection (which currently
139 // only makes use of B_MEDIA_NODE_STOPPED.)
140 // This flag may become deprecated as the Media Kit
141 // evolves (ie. more node-level notifications come
142 // along.)
143 NO_ROSTER_WATCH = 1<<5,
145 // [e.moon 14oct99]
146 // Disables position reporting (via BMediaRoster::SyncToNode().)
147 // Some system-provided nodes tend to explode when SyncToNode() is
148 // called on them (like the video-file player in BeOS R4.5.2).
149 NO_POSITION_REPORTING = 1<<6
152 public: // *** dtor
154 // free the node (this call will result in the eventual
155 // deletion of the object.)
156 // returns B_OK on success; B_NOT_ALLOWED if release() has
157 // already been called; other error codes if the Media Roster
158 // call fails.
160 status_t release();
162 // call release() rather than deleting NodeRef objects
163 virtual ~NodeRef();
165 public: // *** const accessors
166 // [e.moon 13oct99] moved method definitions here to keep inline
167 // in the face of a balky PPC compiler
168 inline const media_node& node() const { return m_info.node; }
169 inline uint32 kind() const { return m_info.node.kind; }
170 inline const live_node_info& nodeInfo() const { return m_info; }
171 inline const char* name() const { return m_info.name; }
172 inline media_node_id id() const { return m_info.node.node; }
174 public: // *** member access
176 // turn cycle mode (looping) on or off
177 void setCycling(
178 bool cycle);
179 bool isCycling() const;
181 // is the node running?
182 bool isRunning() const;
184 // was the node created via NodeManager::instantiate()?
185 bool isInternal() const;
187 // fetch the group, or 0 if the node is ungrouped.
188 NodeGroup* group() const;
190 // flag access
191 uint32 flags() const;
192 void setFlags(
193 uint32 flags);
195 // [e.moon 29sep99]
196 // access addon-hint info
197 // - returns B_BAD_VALUE if not an add-on node created by this NodeManager
199 status_t getDormantNodeInfo(
200 dormant_node_info* outInfo);
202 // [e.moon 29sep99]
203 // access file being played
204 // - returns B_BAD_VALUE if not an add-on node created by this NodeManager,
205 // or if the node has no associated file
207 status_t getFile(
208 entry_ref* outFile);
210 // [e.moon 8dec99]
211 // set file to play
213 status_t setFile(
214 const entry_ref& file,
215 bigtime_t* outDuration=0); //nyi
217 // [e.moon 23oct99]
218 // returns true if the media_node has been released (call releaseNode() to
219 // make this happen.)
221 bool isNodeReleased() const;
223 // now implemented by ObservableHandler [20aug99]
224 // // has this reference been released?
225 // bool isReleased() const;
227 public: // *** run-mode operations
228 void setRunMode(
229 uint32 runMode,
230 bigtime_t delay=0LL);
231 uint32 runMode() const;
233 bigtime_t recordingDelay() const;
235 // calculates the minimum amount of delay needed for
236 // B_RECORDING mode
237 // +++++ 15sep99: returns biggest_output_buffer_duration * 2
238 // +++++ 28sep99: adds downstream latency
239 bigtime_t calculateRecordingModeDelay(); //nyi
241 public: // *** connection access
243 // connection access: vector versions
245 status_t getInputConnections(
246 std::vector<Connection>& ioConnections,
247 media_type filterType=B_MEDIA_UNKNOWN_TYPE) const;
249 status_t getOutputConnections(
250 std::vector<Connection>& ioConnections,
251 media_type filterType=B_MEDIA_UNKNOWN_TYPE) const;
253 // connection access: flat array versions
255 status_t getInputConnections(
256 Connection* outConnections,
257 int32 maxConnections,
258 int32* outNumConnections,
259 media_type filterType=B_MEDIA_UNKNOWN_TYPE) const;
261 status_t getOutputConnections(
262 Connection* outConnections,
263 int32 maxConnections,
264 int32* outNumConnections,
265 media_type filterType=B_MEDIA_UNKNOWN_TYPE) const;
267 // +++++ connection matching by source/destination +++++
269 public: // *** position reporting/listening
271 bool positionReportsEnabled() const;
273 void enablePositionReports();
274 void disablePositionReports();
276 // Fetch the approximate current position:
277 // Returns the last reported position, and the
278 // performance time at which that position was reached. If the
279 // transport has never been started, the start position and
280 // a performance time of 0 will be returned. If position updating
281 // isn't currently enabled, returns B_NOT_ALLOWED.
283 status_t getLastPosition(
284 bigtime_t* outPosition,
285 bigtime_t* outPerfTime) const;
287 // Subscribe to regular position reports:
288 // Position reporting isn't rolled into the regular observer
289 // interface because a large number of messages are generated
290 // (the frequency can be changed; see below.)
292 status_t addPositionObserver(
293 BHandler* handler);
295 status_t removePositionObserver(
296 BHandler* handler);
298 // Set how often position updates will be sent:
299 // Realistically, period should be > 10000 or so.
301 status_t setPositionUpdatePeriod(
302 bigtime_t period);
304 bigtime_t positionUpdatePeriod() const;
306 public: // *** BMediaRoster wrappers & convenience methods
308 // release the media node
309 // (if allowed, will trigger the release/deletion of this object)
310 status_t releaseNode();
312 // calculate total (internal + downstream) latency for this node
314 status_t totalLatency(
315 bigtime_t* outLatency) const;
318 // retrieve input/output matching the given destination/source.
319 // returns B_MEDIA_BAD_[SOURCE | DESTINATION] if the destination
320 // or source don't correspond to this node.
322 status_t findInput(
323 const media_destination& forDestination,
324 media_input* outInput) const;
326 status_t findOutput(
327 const media_source& forSource,
328 media_output* outOutput) const;
331 // endpoint matching (given name and/or format as 'hints').
332 // If no hints are given, returns the first free endpoint, if
333 // any exist.
334 // returns B_ERROR if no matching endpoint is found.
336 status_t findFreeInput(
337 media_input* outInput,
338 media_type type=B_MEDIA_UNKNOWN_TYPE,
339 const char* name=0) const;
341 status_t findFreeInput(
342 media_input* outInput,
343 const media_format* format,
344 const char* name=0) const;
346 status_t findFreeOutput(
347 media_output* outOutput,
348 media_type type=B_MEDIA_UNKNOWN_TYPE,
349 const char* name=0) const;
351 status_t findFreeOutput(
352 media_output* outOutput,
353 const media_format* format,
354 const char* name=0) const;
356 // node endpoint access: vector versions (wrappers for BMediaRoster
357 // calls.)
359 status_t getFreeInputs(
360 std::vector<media_input>& ioInputs,
361 media_type filterType=B_MEDIA_UNKNOWN_TYPE) const;
363 status_t getConnectedInputs(
364 std::vector<media_input>& ioInputs,
365 media_type filterType=B_MEDIA_UNKNOWN_TYPE) const;
367 status_t getFreeOutputs(
368 std::vector<media_output>& ioOutputs,
369 media_type filterType=B_MEDIA_UNKNOWN_TYPE) const;
371 status_t getConnectedOutputs(
372 std::vector<media_output>& ioOutputs,
373 media_type filterType=B_MEDIA_UNKNOWN_TYPE) const;
376 // node endpoint access: array versions (wrappers for BMediaRoster
377 // calls.)
379 status_t getFreeInputs(
380 media_input* outInputs,
381 int32 maxInputs,
382 int32* outNumInputs,
383 media_type filterType=B_MEDIA_UNKNOWN_TYPE) const;
385 status_t getConnectedInputs(
386 media_input* outInputs,
387 int32 maxInputs,
388 int32* outNumInputs) const;
390 status_t getFreeOutputs(
391 media_output* outOutputs,
392 int32 maxOutputs,
393 int32* outNumOutputs,
394 media_type filterType=B_MEDIA_UNKNOWN_TYPE) const;
396 status_t getConnectedOutputs(
397 media_output* outOutputs,
398 int32 maxOutputs,
399 int32* outNumOutputs) const;
401 public: // *** BHandler:
402 virtual void MessageReceived(
403 BMessage* message);
405 public: // *** IObservable: [20aug99]
406 virtual void observerAdded(
407 const BMessenger& observer);
409 virtual void observerRemoved(
410 const BMessenger& observer);
412 virtual void notifyRelease();
414 virtual void releaseComplete();
416 protected: // *** ILockable
417 // Only WRITE locking is allowed!
419 bool lock(
420 lock_t type=WRITE,
421 bigtime_t timeout=B_INFINITE_TIMEOUT);
422 bool unlock(
423 lock_t type=WRITE);
424 bool isLocked(
425 lock_t type=WRITE) const;
427 protected: // *** ctor (accessible to NodeManager)
428 // throws runtime_error
429 NodeRef(
430 const media_node& node,
431 NodeManager* manager,
432 uint32 userFlags,
433 uint32 implFlags);
435 protected: // *** endpoint-fixing operations (no lock required)
437 // 'fix' (fill in node if needed) sets of inputs/outputs
438 void _fixInputs(
439 media_input* inputs,
440 int32 count) const;
441 void _fixInputs(
442 std::vector<media_input>& inputs) const;
444 void _fixOutputs(
445 media_output* outputs,
446 int32 count) const;
447 void _fixOutputs(
448 std::vector<media_output>& outputs) const;
450 protected: // *** internal/NodeManager operations (LOCK REQUIRED)
452 // call after instantiation to register info used to select and
453 // create this add-on node
455 void _setAddonHint(
456 const dormant_node_info* info,
457 const entry_ref* file=0);
459 // call to set a new group; if 0, the node must have no
460 // connections
461 void _setGroup(
462 NodeGroup* group);
464 // *** NodeGroup API ***
465 // 9aug99: moved from NodeGroup
466 // [e.moon 13oct99] removed inlines for the sake of PPC sanity
468 // initialize the given node's transport-state members
469 // (this may be called from the transport thread or from
470 // an API-implementation method.)
472 status_t _initTransportState();
474 status_t _setTimeSource(
475 media_node_id timeSourceID);
477 status_t _setRunMode(
478 const uint32 runMode,
479 bigtime_t delay=0LL);
481 status_t _setRunModeAuto(
482 const uint32 runMode);
484 // seek and preroll the given node.
485 // *** this method should not be called from the transport thread
486 // (since preroll operations can block for a relatively long time.)
488 // returns B_NOT_ALLOWED if the node is running, or if its NO_PREROLL
489 // flag is set; otherwise, returns B_OK on success or a Media Roster
490 // error.
492 status_t _preroll(
493 bigtime_t position);
495 // seek the given node if possible
496 // (this may be called from the transport thread or from
497 // an API-implementation method.)
499 status_t _seek(
500 bigtime_t position,
501 bigtime_t when);
503 // seek the given (stopped) node
504 // (this may be called from the transport thread or from
505 // an API-implementation method.)
507 status_t _seekStopped(
508 bigtime_t position);
510 // start the given node, if possible & necessary, at
511 // the given time
512 // (this may be called from the transport thread or from
513 // an API-implementation method.)
515 status_t _start(
516 bigtime_t when);
518 // stop the given node (which may or may not still be
519 // a member of this group.)
520 // (this may be called from the transport thread or from
521 // an API-implementation method.)
523 status_t _stop();
525 // roll the given node, if possible.
526 // (this may be called from the transport thread or from
527 // an API-implementation method.)
529 status_t _roll(
530 bigtime_t start,
531 bigtime_t stop,
532 bigtime_t position);
534 // refresh the node's current latency; if I reference
535 // a B_RECORDING node, update its 'producer delay'.
537 status_t _updateLatency();
539 // +++++ this method may not be needed 10aug99 +++++
540 // Figure the earliest time at which the given node can be started.
541 // Also calculates the position at which it should start from to
542 // play in sync with other nodes in the group, if the transport is
543 // running; if stopped, *outPosition will be set to the current
544 // start position.
545 // Pass the estimated amount of time needed to prepare the
546 // node for playback (ie. preroll & a little fudge factor) in
547 // startDelay.
549 // (this may be called from the transport thread or from
550 // an API-implementation method.)
552 status_t _calcStartTime(
553 bigtime_t startDelay,
554 bigtime_t* outTime,
555 bigtime_t* outPosition); //nyi
557 // *** Position reporting ***
559 // callers: _start(), _roll(), enablePositionReports()
560 status_t _startPositionThread();
562 // callers: _stop(), disablePositionReports(), dtor
563 status_t _stopPositionThread();
565 // [e.moon 14oct99] handle a report
566 status_t _handlePositionUpdate(
567 bigtime_t perfTime,
568 bigtime_t position);
570 // callers: _handlePositionUpdate
571 // (schedules a position update for the given time and position;
572 // if the position overlaps a cycle, adjusts time & position
573 // so that the notification is sent at the cycle point.)
574 status_t _schedulePositionUpdate(
575 bigtime_t when,
576 bigtime_t position);
578 // callers: _handlePositionUpdate, _initPositionThread()
579 // Send a message to all position observers
580 status_t _notifyPosition(
581 bigtime_t when,
582 bigtime_t position);
584 private: // *** members
586 // the node manager
587 NodeManager* m_manager;
589 // owning (parent) group; may be 0 if node is not connected.
590 // A connected node always has a group, since groups allow transport
591 // operations. New groups are created as necessary.
592 NodeGroup* m_group;
594 // the node's state
595 live_node_info m_info;
597 // user-definable transport behavior
598 uint32 m_flags;
600 // private/implementation flags
602 enum impl_flag_t {
603 // the node was created by NodeManager
604 _INTERNAL = 1<<1,
605 // the node should NOT be released when this instance is destroyed
606 _NO_RELEASE = 1<<2,
607 // notification of the node's instantiation has been received
608 // [e.moon 11oct99]
609 _CREATE_NOTIFIED = 1<<3
612 uint32 m_implFlags;
614 // takes BMediaNode::run_mode values or 0 (wildcard:
615 // group run mode used instead)
616 // May not be B_OFFLINE; that must be specified at the group level.
618 uint32 m_runMode;
620 // only valid if m_runMode is BMediaNode::B_RECORDING
621 bigtime_t m_recordingDelay;
623 // Media Roster connection [e.moon 11oct99]
624 bool m_watching;
626 // hint information: this info is serialized with the object
627 // to provide 'hints' towards properly finding the same add-on
628 // node later on. If no hint is provided, the node is assumed
629 // to be external to (not created by) the NodeManager.
631 struct addon_hint;
632 addon_hint* m_addonHint;
634 // * position listening:
635 // - moved from NodeGroup 9aug99
637 bool m_positionReportsEnabled;
638 bool m_positionReportsStarted;
639 bigtime_t m_positionUpdatePeriod;
640 static const bigtime_t s_defaultPositionUpdatePeriod = 50000LL;
642 ::MultiInvoker m_positionInvoker;
644 bigtime_t m_tpLastPositionUpdate;
645 bigtime_t m_lastPosition;
647 // * synchronization threads
649 // only active if position listening has been enabled
650 NodeSyncThread* m_positionThread;
652 // // only active if this node is cycling (looping)
653 // CycleSyncThread* m_cycleSyncThread;
654 // +++++ 10aug99: moved back to NodeGroup
656 private: // *** transport state members
658 // is this node running?
659 bool m_running;
661 // has the media_node (NOT this object) been released?
662 bool m_nodeReleased;
664 // is this node supposed to loop?
665 bool m_cycle;
667 // has the node been prepared to start?
668 bool m_prerolled;
670 // when was the node started?
671 bigtime_t m_tpStart;
673 // if the node has been prerolled, m_tpLastSeek will be 0 but
674 // m_lastSeekPos will reflect the node's prerolled position
676 bigtime_t m_tpLastSeek;
677 bigtime_t m_lastSeekPos;
679 // has a stop event been queued? [e.moon 11oct99]
680 bigtime_t m_stopQueued;
682 // last known latency for this node
683 bigtime_t m_latency;
686 __END_CORTEX_NAMESPACE
687 #endif /*__NodeRef_H__*/