#pragma once #include "filewatcher.hh" #include "utilities.hh" #include // Duration and current playing time struct T_SyncTime { float uDuration = 1.f / 60.f; // Duration - unit size uint32_t iDuration = 3600; // Duration - total units float time = 0; void setDuration( const float uDuration , const uint32_t iDuration ); float duration( ) const noexcept { return uDuration * iDuration; } void setTime( const float t ) noexcept { time = std::max( 0.f , std::min( t , duration( ) ) ); } }; /*============================================================================*/ // Segment of an input's curve struct T_SyncSegment { enum E_SegmentType { LINEAR , RAMP , SMOOTH , //HERMITE }; E_SegmentType type; T_Array< float > values; T_Array< uint32_t > durations; // n(values) - 1 items }; // An input curve struct T_SyncCurve { T_String name; T_Array< T_SyncSegment > segments; T_SyncCurve( ) noexcept { } T_SyncCurve( T_String const& name ) noexcept : name( name ) { } T_SyncCurve( char const* name ) noexcept : name( T_String( name ).usePool( ) ) { } }; // All configured curves. Some may not actually correspond to an input and may // have been defined for inputs that have been removed temporarily (e.g. // because some include was commented out), in which case we don't want to // waste them. struct T_SyncCurves { T_ObjectTable< T_String , T_SyncCurve > curves; T_SyncCurves( ) : curves( []( T_SyncCurve const& c ) -> T_String { return c.name; } ) { } void clear( ); void setCurve( T_SyncCurve curve ); // Returns -1 on lookup failure int32_t indexOf( T_String const& name ) noexcept; int32_t indexOf( char const* name ) noexcept { return indexOf( T_String( name ) ); } }; /*----------------------------------------------------------------------------*/ // Pre-computed data for a curve struct T_SyncCurveCache { using T_SegRef = std::pair< uint32_t , uint32_t >; uint32_t curve; T_Array< T_SegRef > segRefs; T_Array< float > segStarts; T_Array< float > segEnds; uint32_t curPos; T_SyncCurveCache( T_SyncTime const& time , T_SyncCurves const& curves , const uint32_t curve ) noexcept; // Find the index of the segment for the specified time uint32_t findSegment( const float time ) const noexcept; // Compute the value of the curve at the specified location, ignoring // curPos. float valueAt( T_SyncTime const& time , T_SyncCurves const& curves , const float position ) const noexcept; // Compute the value of the curve at the current time, using and // updating curPos as necessary. float value( T_SyncTime const& time , T_SyncCurves const& curves ) noexcept; float segmentValue( float time , uint32_t segIndex , T_Array< T_SyncSegment > const& segments ) const noexcept; }; using P_SyncCurveCache = T_OwnPtr< T_SyncCurveCache >; /*============================================================================*/ // Synchronization values. The values vector always contains an extra entry // used for missing inputs. struct T_SyncValues { T_HashIndex index; T_Array< T_String > identifiers; T_Array< float > values; T_Array< bool > overriden; T_SyncValues( ); void clear( ); // Returns true on success, false on duplicate bool addValue( T_String const& name , const float initial = 0.f ) noexcept; bool addValue( char const* name , const float initial = 0.f ) noexcept { return addValue( T_String( name ) , initial ); } // If the name isn't found, the last entry of values[] is returned uint32_t indexOf( T_String const& name ) const noexcept; }; /*============================================================================*/ // Synchronisation manager; handles all the synchronization data and makes it // work together. struct T_SyncManager { T_SyncManager( ); // --------------------------------------------------------------------- // Duration & time controls void setDuration( const float uDuration , const uint32_t iDuration ); float duration( ) const noexcept { return time_.duration( ); } void setTime( const float time ); void timeDelta( const float delta ) { setTime( time_.time + delta ); } float time( ) const noexcept { return time_.time; } bool finished( ) const noexcept { return time_.time >= time_.duration( ); } // --------------------------------------------------------------------- // Value access void clearInputs( ) { values_.clear( ); } bool addInput( T_String const& name , const float initial = 0.f ) noexcept { return values_.addValue( name , initial ); } uint32_t inputPos( T_String const& name ) const noexcept { return values_.indexOf( name ); } T_Array< float > const& inputs( ) const noexcept { return values_.values; } // --------------------------------------------------------------------- // Curves void checkCurveFile( ); void clearCurves( ); void setCurve( T_SyncCurve curve ); private: void curvesChanged_( ); bool loadCurves_( bool& missing ); // --------------------------------------------------------------------- // Update public: void updateCurveCaches( ); void updateValues( ); private: ebcl::T_SRDParserConfig pConfig_; P_WatchedFiles watcher_; T_SyncTime time_; T_SyncValues values_; T_SyncCurves curves_; T_Array< P_SyncCurveCache > curveCaches_; };