diff options
author | John Anderson <ardour@semiosix.com> | 2007-07-19 22:07:10 +0000 |
---|---|---|
committer | John Anderson <ardour@semiosix.com> | 2007-07-19 22:07:10 +0000 |
commit | 4c12c98e338dd88e7b05b7e47133f91c3e3bbc06 (patch) | |
tree | b4c58bcba79696bcaf453cff5441d6caff417f85 /libs/surfaces/mackie/mackie_jog_wheel.cc | |
parent | 47add43cd028855cda2292bef9dcde607f948490 (diff) |
Jog Wheel Fun:
- When ffwd/rew is pressed, wheel controls speed
- Zoom button allows jog wheel to zoom
- Scrub button cycles jog from scrub to shuttle to whatever it was before
git-svn-id: svn://localhost/ardour2/branches/2.0-ongoing@2155 d708f5d6-7413-0410-9779-e7cbd77b26cf
Diffstat (limited to 'libs/surfaces/mackie/mackie_jog_wheel.cc')
-rw-r--r-- | libs/surfaces/mackie/mackie_jog_wheel.cc | 218 |
1 files changed, 218 insertions, 0 deletions
diff --git a/libs/surfaces/mackie/mackie_jog_wheel.cc b/libs/surfaces/mackie/mackie_jog_wheel.cc new file mode 100644 index 0000000000..481c45bffc --- /dev/null +++ b/libs/surfaces/mackie/mackie_jog_wheel.cc @@ -0,0 +1,218 @@ +#include "mackie_jog_wheel.h" + +#include "mackie_control_protocol.h" +#include "surface_port.h" +#include "controls.h" + +#include <algorithm> + +using namespace Mackie; + +JogWheel::JogWheel( MackieControlProtocol & mcp ) +: _mcp( mcp ) +, _transport_speed( 4.0 ) +, _transport_direction( 0 ) +, _shuttle_speed( 0.0 ) +{ +} + +JogWheel::State JogWheel::jog_wheel_state() const +{ + if ( !_jog_wheel_states.empty() ) + return _jog_wheel_states.top(); + else + return scroll; +} + +void JogWheel::zoom_event( SurfacePort & port, Control & control, const ControlState & state ) +{ +} + +void JogWheel::scrub_event( SurfacePort & port, Control & control, const ControlState & state ) +{ +} + +void JogWheel::speed_event( SurfacePort & port, Control & control, const ControlState & state ) +{ +} + +void JogWheel::scroll_event( SurfacePort & port, Control & control, const ControlState & state ) +{ +} + +float scaled_delta( const ControlState & state, float current_speed ) +{ + return state.sign * ( pow( state.ticks + 1, 2 ) + current_speed ) / 100.0; +} + +void JogWheel::jog_event( SurfacePort & port, Control & control, const ControlState & state ) +{ +// TODO use current snap-to setting? +#if 0 + long delta = state.ticks * sign * 1000; + nframes_t next = session->transport_frame() + delta; + if ( delta < 0 && session->transport_frame() < (nframes_t) abs( delta ) ) + { + next = session->current_start_frame(); + } + else if ( next > session->current_end_frame() ) + { + next = session->current_end_frame(); + } + + // doesn't work very well + session->request_locate( next, session->transport_rolling() ); +#endif + + switch ( jog_wheel_state() ) + { + case scroll: + //ScrollTimeline causes crashes + if ( _mcp.mcu_port().emulation() == MackiePort::bcf2000 ) + _mcp.ScrollTimeline( state.ticks * state.sign / 100.0 ); + else + _mcp.ScrollTimeline( state.ticks * state.sign / 100.0 ); + break; + + case zoom: + // TODO do a for loop for each, to number of ticks + if ( state.sign > 0 ) + for ( unsigned int i = 0; i < state.ticks; ++i ) _mcp.ZoomIn(); + else + for ( unsigned int i = 0; i < state.ticks; ++i ) _mcp.ZoomOut(); + break; + + case speed: + { + // block because we initialize a variable + // locally, _transport_speed is an absolute value... + // fairly arbitrary scaling function + _transport_speed += scaled_delta( state, _mcp.get_session().transport_speed() ); + + // make sure not weirdness get so the session + if ( _transport_speed < 0 || isnan( _transport_speed ) ) + { + _transport_speed = 0.0; + } + + // translated current speed to a signed transport velocity + _mcp.get_session().request_transport_speed( transport_speed() * transport_direction() ); + break; + } + + case scrub: + { + add_scrub_interval( _scrub_timer.restart() ); + // copied from tranzport driver + float speed = 0.0; + + // This should really be part of the surface object + if ( _mcp.mcu_port().emulation() == MackiePort::bcf2000 ) + // 5 clicks per second => speed == 1.0 + speed = 50.0 / average_scrub_interval() * state.ticks; + else + // 10 clicks per second => speed == 1.0 + speed = 100.0 / average_scrub_interval() * state.ticks; + + _mcp.get_session().request_transport_speed( speed * state.sign ); + break; + } + + case shuttle: + _shuttle_speed = _mcp.get_session().transport_speed(); + _shuttle_speed += scaled_delta( state, _mcp.get_session().transport_speed() ); + _mcp.get_session().request_transport_speed( _shuttle_speed ); + break; + + case select: + cout << "JogWheel select not implemented" << endl; + break; + } +} + +void JogWheel::check_scrubbing() +{ + // if the last elapsed is greater than the average + std deviation, then stop + if ( !_scrub_intervals.empty() && _scrub_timer.elapsed() > average_scrub_interval() + std_dev_scrub_interval() ) + { + _mcp.get_session().request_transport_speed( 0.0 ); + _scrub_intervals.clear(); + } +} + +void JogWheel::push( State state ) +{ + _jog_wheel_states.push( state ); +} + +void JogWheel::pop() +{ + if ( _jog_wheel_states.size() > 0 ) + { + _jog_wheel_states.pop(); + } +} + +void JogWheel::zoom_state_toggle() +{ + if ( jog_wheel_state() == zoom ) + pop(); + else + push( zoom ); +} + +JogWheel::State JogWheel::scrub_state_cycle() +{ + State top = jog_wheel_state(); + if ( top == scrub ) + { + // stop scrubbing and go to shuttle + pop(); + push( shuttle ); + _shuttle_speed = 0.0; + } + else if ( top == shuttle ) + { + // default to scroll, or the last selected + pop(); + } + else + { + // start with scrub + push( scrub ); + } + + return jog_wheel_state(); +} + +void JogWheel::add_scrub_interval( unsigned long elapsed ) +{ + if ( _scrub_intervals.size() > 5 ) + { + _scrub_intervals.pop_front(); + } + _scrub_intervals.push_back( elapsed ); +} + +float JogWheel::average_scrub_interval() +{ + float sum = 0.0; + for ( std::deque<unsigned long>::iterator it = _scrub_intervals.begin(); it != _scrub_intervals.end(); ++it ) + { + sum += *it; + } + return sum / _scrub_intervals.size(); +} + +float JogWheel::std_dev_scrub_interval() +{ + float average = average_scrub_interval(); + + // calculate standard deviation + float sum = 0.0; + for ( std::deque<unsigned long>::iterator it = _scrub_intervals.begin(); it != _scrub_intervals.end(); ++it ) + { + sum += pow( *it - average, 2 ); + } + return sqrt( sum / _scrub_intervals.size() -1 ); +} |