2 * Copyright (c) 1999-2000, Eric Moon.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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)
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
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
52 #include <MediaAddOn.h>
53 #include <MediaNode.h>
58 #include "ILockable.h"
59 #include "MultiInvoker.h"
60 #include "ObservableHandler.h"
63 #include "cortex_defs.h"
65 __BEGIN_CORTEX_NAMESPACE
73 public ObservableHandler
,
76 typedef ObservableHandler _inherited
;
78 friend class NodeManager
;
79 friend class NodeGroup
;
81 public: // *** messages
86 M_OBSERVER_ADDED
=NodeRef_message_base
,
100 M_INPUTS_CHANGED
, //nyi
101 M_OUTPUTS_CHANGED
, //nyi
104 // * only sent to position listeners
112 // delay: int64 (bigtime_t; applies only to B_RECORDING mode)
119 // "cycling"; bool (OR "be:value"; int32)
129 // node-level transport restrictions
130 NO_START_STOP
= 1<<1,
134 // [e.moon 28sep99] useful for misbehaved nodes
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
143 NO_ROSTER_WATCH
= 1<<5,
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
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
162 // call release() rather than deleting NodeRef objects
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
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;
191 uint32
flags() const;
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
);
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
214 const entry_ref
& file
,
215 bigtime_t
* outDuration
=0); //nyi
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
230 bigtime_t delay
=0LL);
231 uint32
runMode() const;
233 bigtime_t
recordingDelay() const;
235 // calculates the minimum amount of delay needed for
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(
295 status_t
removePositionObserver(
298 // Set how often position updates will be sent:
299 // Realistically, period should be > 10000 or so.
301 status_t
setPositionUpdatePeriod(
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.
323 const media_destination
& forDestination
,
324 media_input
* outInput
) const;
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
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
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
379 status_t
getFreeInputs(
380 media_input
* outInputs
,
383 media_type filterType
=B_MEDIA_UNKNOWN_TYPE
) const;
385 status_t
getConnectedInputs(
386 media_input
* outInputs
,
388 int32
* outNumInputs
) const;
390 status_t
getFreeOutputs(
391 media_output
* outOutputs
,
393 int32
* outNumOutputs
,
394 media_type filterType
=B_MEDIA_UNKNOWN_TYPE
) const;
396 status_t
getConnectedOutputs(
397 media_output
* outOutputs
,
399 int32
* outNumOutputs
) const;
401 public: // *** BHandler:
402 virtual void MessageReceived(
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!
421 bigtime_t timeout
=B_INFINITE_TIMEOUT
);
425 lock_t type
=WRITE
) const;
427 protected: // *** ctor (accessible to NodeManager)
428 // throws runtime_error
430 const media_node
& node
,
431 NodeManager
* manager
,
435 protected: // *** endpoint-fixing operations (no lock required)
437 // 'fix' (fill in node if needed) sets of inputs/outputs
442 std::vector
<media_input
>& inputs
) const;
445 media_output
* outputs
,
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
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
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
495 // seek the given node if possible
496 // (this may be called from the transport thread or from
497 // an API-implementation method.)
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(
510 // start the given node, if possible & necessary, at
512 // (this may be called from the transport thread or from
513 // an API-implementation method.)
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.)
525 // roll the given node, if possible.
526 // (this may be called from the transport thread or from
527 // an API-implementation method.)
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
545 // Pass the estimated amount of time needed to prepare the
546 // node for playback (ie. preroll & a little fudge factor) in
549 // (this may be called from the transport thread or from
550 // an API-implementation method.)
552 status_t
_calcStartTime(
553 bigtime_t startDelay
,
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(
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(
578 // callers: _handlePositionUpdate, _initPositionThread()
579 // Send a message to all position observers
580 status_t
_notifyPosition(
584 private: // *** members
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.
595 live_node_info m_info
;
597 // user-definable transport behavior
600 // private/implementation flags
603 // the node was created by NodeManager
605 // the node should NOT be released when this instance is destroyed
607 // notification of the node's instantiation has been received
609 _CREATE_NOTIFIED
= 1<<3
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.
620 // only valid if m_runMode is BMediaNode::B_RECORDING
621 bigtime_t m_recordingDelay
;
623 // Media Roster connection [e.moon 11oct99]
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.
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?
661 // has the media_node (NOT this object) been released?
664 // is this node supposed to loop?
667 // has the node been prepared to start?
670 // when was the node started?
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
686 __END_CORTEX_NAMESPACE
687 #endif /*__NodeRef_H__*/