1 #include "mackie_jog_wheel.h"
3 #include "mackie_control_protocol.h"
4 #include "surface_port.h"
10 using namespace Mackie;
12 JogWheel::JogWheel( MackieControlProtocol & mcp )
14 , _transport_speed( 4.0 )
15 , _transport_direction( 0 )
16 , _shuttle_speed( 0.0 )
20 JogWheel::State JogWheel::jog_wheel_state() const
22 if ( !_jog_wheel_states.empty() )
23 return _jog_wheel_states.top();
28 void JogWheel::zoom_event( SurfacePort & port, Control & control, const ControlState & state )
32 void JogWheel::scrub_event( SurfacePort & port, Control & control, const ControlState & state )
36 void JogWheel::speed_event( SurfacePort & port, Control & control, const ControlState & state )
40 void JogWheel::scroll_event( SurfacePort & port, Control & control, const ControlState & state )
44 void JogWheel::jog_event( SurfacePort & port, Control & control, const ControlState & state )
46 // TODO use current snap-to setting?
47 switch ( jog_wheel_state() )
50 _mcp.ScrollTimeline( state.delta * state.sign );
55 // TODO implement something similar to ScrollTimeline which
56 // ends up in Editor::control_scroll for smoother zooming.
58 for ( unsigned int i = 0; i < state.ticks; ++i ) _mcp.ZoomIn();
60 for ( unsigned int i = 0; i < state.ticks; ++i ) _mcp.ZoomOut();
64 // locally, _transport_speed is an positive value
65 _transport_speed += _mcp.surface().scaled_delta( state, _mcp.get_session().transport_speed() );
67 // make sure no weirdness gets to the session
68 if ( _transport_speed < 0 || isnan( _transport_speed ) )
70 _transport_speed = 0.0;
73 // translate _transport_speed speed to a signed transport velocity
74 _mcp.get_session().request_transport_speed( transport_speed() * transport_direction() );
79 if ( state.delta != 0.0 )
81 add_scrub_interval( _scrub_timer.restart() );
82 // x clicks per second => speed == 1.0
83 float speed = _mcp.surface().scrub_scaling_factor() / average_scrub_interval() * state.ticks;
84 _mcp.get_session().request_transport_speed( speed * state.sign );
88 // we have a stop event
95 _shuttle_speed = _mcp.get_session().transport_speed();
96 _shuttle_speed += _mcp.surface().scaled_delta( state, _mcp.get_session().transport_speed() );
97 _mcp.get_session().request_transport_speed( _shuttle_speed );
101 cout << "JogWheel select not implemented" << endl;
106 void JogWheel::check_scrubbing()
108 // if the last elapsed is greater than the average + std deviation, then stop
109 if ( !_scrub_intervals.empty() && _scrub_timer.elapsed() > average_scrub_interval() + std_dev_scrub_interval() )
111 _mcp.get_session().request_transport_speed( 0.0 );
112 _scrub_intervals.clear();
116 void JogWheel::push( State state )
118 _jog_wheel_states.push( state );
123 if ( _jog_wheel_states.size() > 0 )
125 _jog_wheel_states.pop();
129 void JogWheel::zoom_state_toggle()
131 if ( jog_wheel_state() == zoom )
137 JogWheel::State JogWheel::scrub_state_cycle()
139 State top = jog_wheel_state();
142 // stop scrubbing and go to shuttle
145 _shuttle_speed = 0.0;
147 else if ( top == shuttle )
149 // default to scroll, or the last selected
158 return jog_wheel_state();
161 void JogWheel::add_scrub_interval( unsigned long elapsed )
163 if ( _scrub_intervals.size() > 5 )
165 _scrub_intervals.pop_front();
167 _scrub_intervals.push_back( elapsed );
170 float JogWheel::average_scrub_interval()
173 for ( std::deque<unsigned long>::iterator it = _scrub_intervals.begin(); it != _scrub_intervals.end(); ++it )
177 return sum / _scrub_intervals.size();
180 float JogWheel::std_dev_scrub_interval()
182 float average = average_scrub_interval();
184 // calculate standard deviation
186 for ( std::deque<unsigned long>::iterator it = _scrub_intervals.begin(); it != _scrub_intervals.end(); ++it )
188 sum += pow( *it - average, 2 );
190 return sqrt( sum / _scrub_intervals.size() -1 );