3 #include <ardour/session.h>
5 #include "mackie_jog_wheel.h"
7 #include "mackie_control_protocol.h"
8 #include "surface_port.h"
14 using namespace Mackie;
17 JogWheel::JogWheel( MackieControlProtocol & mcp )
19 , _transport_speed( 4.0 )
20 , _transport_direction( 0 )
21 , _shuttle_speed( 0.0 )
25 JogWheel::State JogWheel::jog_wheel_state() const
27 if ( !_jog_wheel_states.empty() )
28 return _jog_wheel_states.top();
33 void JogWheel::zoom_event (SurfacePort &, Control &, const ControlState &)
37 void JogWheel::scrub_event (SurfacePort &, Control &, const ControlState &)
41 void JogWheel::speed_event (SurfacePort &, Control &, const ControlState &)
45 void JogWheel::scroll_event (SurfacePort &, Control &, const ControlState &)
49 void JogWheel::jog_event (SurfacePort &, Control &, const ControlState & state)
51 // TODO use current snap-to setting?
52 switch ( jog_wheel_state() )
55 _mcp.ScrollTimeline( state.delta * state.sign );
60 // TODO implement something similar to ScrollTimeline which
61 // ends up in Editor::control_scroll for smoother zooming.
63 for ( unsigned int i = 0; i < state.ticks; ++i ) _mcp.ZoomIn();
65 for ( unsigned int i = 0; i < state.ticks; ++i ) _mcp.ZoomOut();
69 // locally, _transport_speed is an positive value
70 _transport_speed += _mcp.surface().scaled_delta( state, _mcp.get_session().transport_speed() );
72 // make sure no weirdness gets to the session
73 if ( _transport_speed < 0 || isnan( _transport_speed ) )
75 _transport_speed = 0.0;
78 // translate _transport_speed speed to a signed transport velocity
79 _mcp.get_session().request_transport_speed( transport_speed() * transport_direction() );
84 if ( state.sign != 0 )
86 add_scrub_interval( _scrub_timer.restart() );
87 // x clicks per second => speed == 1.0
88 float speed = _mcp.surface().scrub_scaling_factor() / average_scrub_interval() * state.ticks;
89 _mcp.get_session().request_transport_speed( speed * state.sign );
93 // we have a stop event
100 _shuttle_speed = _mcp.get_session().transport_speed();
101 _shuttle_speed += _mcp.surface().scaled_delta( state, _mcp.get_session().transport_speed() );
102 _mcp.get_session().request_transport_speed( _shuttle_speed );
106 std::cout << "JogWheel select not implemented" << std::endl;
111 void JogWheel::check_scrubbing()
113 // if the last elapsed is greater than the average + std deviation, then stop
114 if ( !_scrub_intervals.empty() && _scrub_timer.elapsed() > average_scrub_interval() + std_dev_scrub_interval() )
116 _mcp.get_session().request_transport_speed( 0.0 );
117 _scrub_intervals.clear();
121 void JogWheel::push( State state )
123 _jog_wheel_states.push( state );
128 if ( _jog_wheel_states.size() > 0 )
130 _jog_wheel_states.pop();
134 void JogWheel::zoom_state_toggle()
136 if ( jog_wheel_state() == zoom )
142 JogWheel::State JogWheel::scrub_state_cycle()
144 State top = jog_wheel_state();
147 // stop scrubbing and go to shuttle
150 _shuttle_speed = 0.0;
152 else if ( top == shuttle )
154 // default to scroll, or the last selected
163 return jog_wheel_state();
166 void JogWheel::add_scrub_interval( unsigned long elapsed )
168 if ( _scrub_intervals.size() > 5 )
170 _scrub_intervals.pop_front();
172 _scrub_intervals.push_back( elapsed );
175 float JogWheel::average_scrub_interval()
178 for ( std::deque<unsigned long>::iterator it = _scrub_intervals.begin(); it != _scrub_intervals.end(); ++it )
182 return sum / _scrub_intervals.size();
185 float JogWheel::std_dev_scrub_interval()
187 float average = average_scrub_interval();
189 // calculate standard deviation
191 for ( std::deque<unsigned long>::iterator it = _scrub_intervals.begin(); it != _scrub_intervals.end(); ++it )
193 sum += pow( *it - average, 2 );
195 return sqrt( sum / _scrub_intervals.size() -1 );