X-Git-Url: https://git.carlh.net/gitweb/?a=blobdiff_plain;f=gtk2_ardour%2Fshuttle_control.cc;h=1d150f73d67511ff8a60ab838e0820a3376e601c;hb=e1b0f1bd0b03c071d2b5987e4ab75ef059e32111;hp=c941336de51d6829886637450fbc4a1d2e7fab88;hpb=35a966c824a862deec9691f6b3ea665f0f8a1dd6;p=ardour.git diff --git a/gtk2_ardour/shuttle_control.cc b/gtk2_ardour/shuttle_control.cc index c941336de5..1d150f73d6 100644 --- a/gtk2_ardour/shuttle_control.cc +++ b/gtk2_ardour/shuttle_control.cc @@ -18,7 +18,7 @@ #include -#include +#include #include "ardour/ardour.h" #include "ardour/audioengine.h" @@ -27,10 +27,17 @@ #include "gtkmm2ext/keyboard.h" #include "gtkmm2ext/gui_thread.h" +#include "gtkmm2ext/cairocell.h" +#include "gtkmm2ext/utils.h" +#include "gtkmm2ext/rgb_macros.h" +#include "actions.h" #include "ardour_ui.h" +#include "rgb_macros.h" #include "shuttle_control.h" +#include "i18n.h" + using namespace Gtk; using namespace Gtkmm2ext; using namespace ARDOUR; @@ -39,72 +46,85 @@ using std::max; gboolean qt (gboolean, gint, gint, gboolean, Gtk::Tooltip*, gpointer) { - return FALSE; + return FALSE; } ShuttleControl::ShuttleControl () - : _controllable (new ShuttleControllable (*this)) - , binding_proxy (_controllable) + : _controllable (new ShuttleControllable (*this)) + , binding_proxy (_controllable) { - ARDOUR_UI::instance()->set_tip (*this, _("Shuttle speed control (Context-click for options)")); + ARDOUR_UI::instance()->set_tip (*this, _("Shuttle speed control (Context-click for options)")); - pattern = 0; + pattern = 0; + shine_pattern = 0; last_shuttle_request = 0; last_speed_displayed = -99999999; shuttle_grabbed = false; + shuttle_speed_on_grab = 0; shuttle_fract = 0.0; shuttle_max_speed = 8.0f; shuttle_style_menu = 0; shuttle_unit_menu = 0; - shuttle_context_menu = 0; + shuttle_context_menu = 0; + _hovering = false; - set_flags (CAN_FOCUS); - add_events (Gdk::ENTER_NOTIFY_MASK|Gdk::LEAVE_NOTIFY_MASK|Gdk::BUTTON_RELEASE_MASK|Gdk::BUTTON_PRESS_MASK|Gdk::POINTER_MOTION_MASK|Gdk::SCROLL_MASK); - set_size_request (100, 15); + set_flags (CAN_FOCUS); + add_events (Gdk::ENTER_NOTIFY_MASK|Gdk::LEAVE_NOTIFY_MASK|Gdk::BUTTON_RELEASE_MASK|Gdk::BUTTON_PRESS_MASK|Gdk::POINTER_MOTION_MASK|Gdk::SCROLL_MASK); + set_size_request (85, 20); set_name (X_("ShuttleControl")); - Config->ParameterChanged.connect (parameter_connection, MISSING_INVALIDATOR, ui_bind (&ShuttleControl::parameter_changed, this, _1), gui_context()); + Config->ParameterChanged.connect (parameter_connection, MISSING_INVALIDATOR, boost::bind (&ShuttleControl::parameter_changed, this, _1), gui_context()); - /* gtkmm 2.4: the C++ wrapper doesn't work */ - g_signal_connect ((GObject*) gobj(), "query-tooltip", G_CALLBACK (qt), NULL); - // signal_query_tooltip().connect (sigc::mem_fun (*this, &ShuttleControl::on_query_tooltip)); + /* gtkmm 2.4: the C++ wrapper doesn't work */ + g_signal_connect ((GObject*) gobj(), "query-tooltip", G_CALLBACK (qt), NULL); + // signal_query_tooltip().connect (sigc::mem_fun (*this, &ShuttleControl::on_query_tooltip)); } ShuttleControl::~ShuttleControl () { cairo_pattern_destroy (pattern); + cairo_pattern_destroy (shine_pattern); } void ShuttleControl::set_session (Session *s) { - SessionHandlePtr::set_session (s); + SessionHandlePtr::set_session (s); - if (_session) { - set_sensitive (true); - _session->add_controllable (_controllable); - } else { - set_sensitive (false); - } + if (_session) { + set_sensitive (true); + _session->add_controllable (_controllable); + } else { + set_sensitive (false); + } } void ShuttleControl::on_size_allocate (Gtk::Allocation& alloc) { - if (pattern) { - cairo_pattern_destroy (pattern); - pattern = 0; - } - - pattern = cairo_pattern_create_linear (0, 0, alloc.get_width(), alloc.get_height()); - - /* add 3 color stops */ - - cairo_pattern_add_color_stop_rgb (pattern, 0.0, 0, 0, 0); - cairo_pattern_add_color_stop_rgb (pattern, 0.5, 0.0, 0.0, 1.0); - cairo_pattern_add_color_stop_rgb (pattern, 1.0, 0, 0, 0); + if (pattern) { + cairo_pattern_destroy (pattern); + pattern = 0; + cairo_pattern_destroy (shine_pattern); + shine_pattern = 0; + } - DrawingArea::on_size_allocate (alloc); + CairoWidget::on_size_allocate ( alloc); + + //background + pattern = cairo_pattern_create_linear (0, 0, 0, alloc.get_height()); + uint32_t col = ARDOUR_UI::config()->get_canvasvar_Shuttle(); + int r,b,g,a; + UINT_TO_RGBA(col, &r, &g, &b, &a); + cairo_pattern_add_color_stop_rgb (pattern, 0.0, r/400.0, g/400.0, b/400.0); + cairo_pattern_add_color_stop_rgb (pattern, 0.4, r/255.0, g/255.0, b/255.0); + cairo_pattern_add_color_stop_rgb (pattern, 1.0, r/512.0, g/512.0, b/512.0); + + //reflection + shine_pattern = cairo_pattern_create_linear (0.0, 0.0, 0.0, 10); + cairo_pattern_add_color_stop_rgba (shine_pattern, 0, 1,1,1,0.0); + cairo_pattern_add_color_stop_rgba (shine_pattern, 0.2, 1,1,1,0.4); + cairo_pattern_add_color_stop_rgba (shine_pattern, 1, 1,1,1,0.1); } void @@ -114,14 +134,14 @@ ShuttleControl::map_transport_state () if (fabs(speed) <= (2*DBL_EPSILON)) { shuttle_fract = 0; - } else { - if (Config->get_shuttle_units() == Semitones) { - bool reverse; - int semi = speed_as_semitones (speed, reverse); - shuttle_fract = semitones_as_fract (semi, reverse); - } else { - shuttle_fract = speed/shuttle_max_speed; - } + } else { + if (Config->get_shuttle_units() == Semitones) { + bool reverse; + int semi = speed_as_semitones (speed, reverse); + shuttle_fract = semitones_as_fract (semi, reverse); + } else { + shuttle_fract = speed/shuttle_max_speed; + } } queue_draw (); @@ -138,34 +158,34 @@ ShuttleControl::build_shuttle_context_menu () Menu* speed_menu = manage (new Menu()); MenuList& speed_items = speed_menu->items(); - Menu* units_menu = manage (new Menu); - MenuList& units_items = units_menu->items(); + Menu* units_menu = manage (new Menu); + MenuList& units_items = units_menu->items(); RadioMenuItem::Group units_group; - + units_items.push_back (RadioMenuElem (units_group, _("Percent"), sigc::bind (sigc::mem_fun (*this, &ShuttleControl::set_shuttle_units), Percentage))); - if (Config->get_shuttle_units() == Percentage) { - static_cast(&units_items.back())->set_active(); - } + if (Config->get_shuttle_units() == Percentage) { + static_cast(&units_items.back())->set_active(); + } units_items.push_back (RadioMenuElem (units_group, _("Semitones"), sigc::bind (sigc::mem_fun (*this, &ShuttleControl::set_shuttle_units), Semitones))); - if (Config->get_shuttle_units() == Semitones) { - static_cast(&units_items.back())->set_active(); - } - items.push_back (MenuElem (_("Units"), *units_menu)); - - Menu* style_menu = manage (new Menu); - MenuList& style_items = style_menu->items(); + if (Config->get_shuttle_units() == Semitones) { + static_cast(&units_items.back())->set_active(); + } + items.push_back (MenuElem (_("Units"), *units_menu)); + + Menu* style_menu = manage (new Menu); + MenuList& style_items = style_menu->items(); RadioMenuItem::Group style_group; style_items.push_back (RadioMenuElem (style_group, _("Sprung"), sigc::bind (sigc::mem_fun (*this, &ShuttleControl::set_shuttle_style), Sprung))); - if (Config->get_shuttle_behaviour() == Sprung) { - static_cast(&style_items.back())->set_active(); - } + if (Config->get_shuttle_behaviour() == Sprung) { + static_cast(&style_items.back())->set_active(); + } style_items.push_back (RadioMenuElem (style_group, _("Wheel"), sigc::bind (sigc::mem_fun (*this, &ShuttleControl::set_shuttle_style), Wheel))); - if (Config->get_shuttle_behaviour() == Wheel) { - static_cast(&style_items.back())->set_active(); - } - - items.push_back (MenuElem (_("Mode"), *style_menu)); + if (Config->get_shuttle_behaviour() == Wheel) { + static_cast(&style_items.back())->set_active(); + } + + items.push_back (MenuElem (_("Mode"), *style_menu)); RadioMenuItem::Group speed_group; @@ -195,7 +215,7 @@ ShuttleControl::build_shuttle_context_menu () } items.push_back (MenuElem (_("Maximum speed"), *speed_menu)); - + } void @@ -232,9 +252,19 @@ ShuttleControl::on_button_press_event (GdkEventButton* ev) switch (ev->button) { case 1: - add_modal_grab (); - shuttle_grabbed = true; - mouse_shuttle (ev->x, true); + if (Keyboard::modifier_state_equals (ev->state, Keyboard::TertiaryModifier)) { + if (_session->transport_rolling()) { + _session->request_transport_speed (1.0); + } + } else { + add_modal_grab (); + shuttle_grabbed = true; + shuttle_speed_on_grab = _session->transport_speed (); + mouse_shuttle (ev->x, true); + gdk_pointer_grab(ev->window,false, + GdkEventMask( Gdk::POINTER_MOTION_MASK | Gdk::BUTTON_PRESS_MASK |Gdk::BUTTON_RELEASE_MASK), + NULL,NULL,ev->time); + } break; case 2: @@ -255,25 +285,26 @@ ShuttleControl::on_button_release_event (GdkEventButton* ev) switch (ev->button) { case 1: - shuttle_grabbed = false; - remove_modal_grab (); - - if (Config->get_shuttle_behaviour() == Sprung) { - if (_session->config.get_auto_play()) { - _session->request_transport_speed (1.0); + if (shuttle_grabbed) { + shuttle_grabbed = false; + remove_modal_grab (); + gdk_pointer_ungrab (GDK_CURRENT_TIME); + + if (Config->get_shuttle_behaviour() == Sprung) { + if (shuttle_speed_on_grab == 0 ) { + _session->request_transport_speed (1.0); + } + _session->request_transport_speed (shuttle_speed_on_grab); } else { - _session->request_transport_speed (0.0); + mouse_shuttle (ev->x, true); } - } else { - mouse_shuttle (ev->x, true); - } - + } return true; case 2: if (_session->transport_rolling()) { - _session->request_transport_speed (1.0); - } + _session->request_transport_speed (1.0, Config->get_shuttle_behaviour() == Wheel); + } return true; case 3: @@ -288,7 +319,7 @@ ShuttleControl::on_button_release_event (GdkEventButton* ev) bool ShuttleControl::on_query_tooltip (int, int, bool, const Glib::RefPtr&) { - return false; + return false; } bool @@ -298,46 +329,68 @@ ShuttleControl::on_scroll_event (GdkEventScroll* ev) return true; } - switch (ev->direction) { - case GDK_SCROLL_UP: - case GDK_SCROLL_RIGHT: - shuttle_fract += 0.005; - break; - case GDK_SCROLL_DOWN: - case GDK_SCROLL_LEFT: - shuttle_fract -= 0.005; - break; - default: - return false; - } - - if (Config->get_shuttle_units() == Semitones) { - - float lower_side_of_dead_zone = semitones_as_fract (-24, true); - float upper_side_of_dead_zone = semitones_as_fract (-24, false); - - /* if we entered the "dead zone" (-24 semitones in forward or reverse), jump - to the far side of it. - */ - - if (shuttle_fract > lower_side_of_dead_zone && shuttle_fract < upper_side_of_dead_zone) { - switch (ev->direction) { - case GDK_SCROLL_UP: - case GDK_SCROLL_RIGHT: - shuttle_fract = upper_side_of_dead_zone; - break; - case GDK_SCROLL_DOWN: - case GDK_SCROLL_LEFT: - shuttle_fract = lower_side_of_dead_zone; - break; - default: - /* impossible, checked above */ - return false; - } - } - } - - use_shuttle_fract (true); + bool semis = (Config->get_shuttle_units() == Semitones); + + switch (ev->direction) { + case GDK_SCROLL_UP: + case GDK_SCROLL_RIGHT: + if (semis) { + if (shuttle_fract == 0) { + shuttle_fract = semitones_as_fract (1, false); + } else { + bool rev; + int st = fract_as_semitones (shuttle_fract, rev); + shuttle_fract = semitones_as_fract (st + 1, rev); + } + } else { + shuttle_fract += 0.00125; + } + break; + case GDK_SCROLL_DOWN: + case GDK_SCROLL_LEFT: + if (semis) { + if (shuttle_fract == 0) { + shuttle_fract = semitones_as_fract (1, true); + } else { + bool rev; + int st = fract_as_semitones (shuttle_fract, rev); + shuttle_fract = semitones_as_fract (st - 1, rev); + } + } else { + shuttle_fract -= 0.00125; + } + break; + default: + return false; + } + + if (semis) { + + float lower_side_of_dead_zone = semitones_as_fract (-24, true); + float upper_side_of_dead_zone = semitones_as_fract (-24, false); + + /* if we entered the "dead zone" (-24 semitones in forward or reverse), jump + to the far side of it. + */ + + if (shuttle_fract > lower_side_of_dead_zone && shuttle_fract < upper_side_of_dead_zone) { + switch (ev->direction) { + case GDK_SCROLL_UP: + case GDK_SCROLL_RIGHT: + shuttle_fract = upper_side_of_dead_zone; + break; + case GDK_SCROLL_DOWN: + case GDK_SCROLL_LEFT: + shuttle_fract = lower_side_of_dead_zone; + break; + default: + /* impossible, checked above */ + return false; + } + } + } + + use_shuttle_fract (true); return true; } @@ -364,10 +417,10 @@ ShuttleControl::mouse_shuttle (double x, bool force) distance_from_center = max (distance_from_center, -center); } - /* compute shuttle fract as expressing how far between the center - and the edge we are. positive values indicate we are right of - center, negative values indicate left of center - */ + /* compute shuttle fract as expressing how far between the center + and the edge we are. positive values indicate we are right of + center, negative values indicate left of center + */ shuttle_fract = distance_from_center / center; // center == half the width use_shuttle_fract (force); @@ -375,61 +428,61 @@ ShuttleControl::mouse_shuttle (double x, bool force) } void -ShuttleControl::set_shuttle_fract (double f) +ShuttleControl::set_shuttle_fract (double f, bool zero_ok) { shuttle_fract = f; - use_shuttle_fract (false); + use_shuttle_fract (false, zero_ok); } int ShuttleControl::speed_as_semitones (float speed, bool& reverse) { - assert (speed != 0.0); + assert (speed != 0.0); - if (speed < 0.0) { - reverse = true; - return (int) round (12.0 * fast_log2 (-speed)); - } else { - reverse = false; - return (int) round (12.0 * fast_log2 (speed)); - } -} + if (speed < 0.0) { + reverse = true; + return (int) round (12.0 * fast_log2 (-speed)); + } else { + reverse = false; + return (int) round (12.0 * fast_log2 (speed)); + } +} float ShuttleControl::semitones_as_speed (int semi, bool reverse) { - if (reverse) { - return -pow (2.0, (semi / 12.0)); - } else { - return pow (2.0, (semi / 12.0)); - } + if (reverse) { + return -pow (2.0, (semi / 12.0)); + } else { + return pow (2.0, (semi / 12.0)); + } } float ShuttleControl::semitones_as_fract (int semi, bool reverse) { - float speed = semitones_as_speed (semi, reverse); - return speed/4.0; /* 4.0 is the maximum speed for a 24 semitone shift */ + float speed = semitones_as_speed (semi, reverse); + return speed/4.0; /* 4.0 is the maximum speed for a 24 semitone shift */ } int ShuttleControl::fract_as_semitones (float fract, bool& reverse) { - assert (fract != 0.0); - return speed_as_semitones (fract * 4.0, reverse); + assert (fract != 0.0); + return speed_as_semitones (fract * 4.0, reverse); } void -ShuttleControl::use_shuttle_fract (bool force) +ShuttleControl::use_shuttle_fract (bool force, bool zero_ok) { microseconds_t now = get_microseconds(); - shuttle_fract = max (-1.0f, shuttle_fract); - shuttle_fract = min (1.0f, shuttle_fract); + shuttle_fract = max (-1.0f, shuttle_fract); + shuttle_fract = min (1.0f, shuttle_fract); /* do not attempt to submit a motion-driven transport speed request more than once per process cycle. - */ + */ if (!force && (last_shuttle_request - now) < (microseconds_t) AudioEngine::instance()->usecs_per_cycle()) { return; @@ -439,50 +492,61 @@ ShuttleControl::use_shuttle_fract (bool force) double speed = 0; - if (Config->get_shuttle_units() == Semitones) { - if (shuttle_fract != 0.0) { - bool reverse; - int semi = fract_as_semitones (shuttle_fract, reverse); - speed = semitones_as_speed (semi, reverse); - } else { - speed = 0.0; - } - } else { - speed = shuttle_max_speed * shuttle_fract; - } + if (Config->get_shuttle_units() == Semitones) { + if (shuttle_fract != 0.0) { + bool reverse; + int semi = fract_as_semitones (shuttle_fract, reverse); + speed = semitones_as_speed (semi, reverse); + } else { + speed = 0.0; + } + } else { + speed = shuttle_max_speed * shuttle_fract; + } - _session->request_transport_speed_nonzero (speed); + if (zero_ok) { + _session->request_transport_speed (speed, Config->get_shuttle_behaviour() == Wheel); + } else { + _session->request_transport_speed_nonzero (speed, Config->get_shuttle_behaviour() == Wheel); + } } -bool -ShuttleControl::on_expose_event (GdkEventExpose* event) +void +ShuttleControl::render (cairo_t* cr) { - cairo_text_extents_t extents; - Glib::RefPtr win (get_window()); - Glib::RefPtr style (get_style()); - - cairo_t* cr = gdk_cairo_create (win->gobj()); - - cairo_set_source (cr, pattern); - cairo_rectangle (cr, 0.0, 0.0, get_width(), get_height()); - cairo_fill_preserve (cr); + cairo_text_extents_t extents; - cairo_set_source_rgb (cr, 0, 0, 0.0); - cairo_stroke (cr); + //black border + cairo_set_source_rgb (cr, 0, 0.0, 0.0); + rounded_rectangle (cr, 0, 0, get_width(), get_height(), 4); +// cairo_fill_preserve (cr); +// cairo_stroke (cr); + cairo_fill (cr); float speed = 0.0; - if (_session) { - speed = _session->transport_speed (); - } + if (_session) { + speed = _session->transport_speed (); + } /* Marker */ - - double visual_fraction = std::min (1.0f, speed/shuttle_max_speed); - double x = (get_width() / 2.0) + (0.5 * (get_width() * visual_fraction)); - cairo_move_to (cr, x, 1); - cairo_set_source_rgb (cr, 1.0, 1.0, 1.0); - cairo_line_to (cr, x, get_height()-1); + float visual_fraction = std::min (1.0f, speed/shuttle_max_speed); + float marker_size = get_height()-4; + float avail_width = get_width() - marker_size; + float x = get_width()*0.5 + visual_fraction * avail_width*0.5; + float offset = x - marker_size*0.5; +// cairo_set_source_rgb (cr, 0, 1, 0.0); + cairo_set_source (cr, pattern); + if (speed == 1.0) { + cairo_move_to( cr, offset-4, 2); + cairo_line_to( cr, offset+4, 2+marker_size*0.5); + cairo_line_to( cr, offset-4, 2+marker_size); + cairo_line_to( cr, offset-4, 2); + } else if ( speed ==0.0 ) + rounded_rectangle (cr, offset, 4, marker_size-2, marker_size-2, 1); + else + cairo_arc (cr, offset + marker_size*0.5, 2 + marker_size*0.5, marker_size*0.5, 0, 360); + cairo_set_line_width (cr, 2); cairo_stroke (cr); /* speed text */ @@ -493,37 +557,38 @@ ShuttleControl::on_expose_event (GdkEventExpose* event) if (Config->get_shuttle_units() == Percentage) { - if (speed == 1.0) { - snprintf (buf, sizeof (buf), _("Playing")); - } else { - if (speed < 0.0) { - snprintf (buf, sizeof (buf), "<<< %d%%", (int) round (-speed * 100)); - } else { - snprintf (buf, sizeof (buf), ">>> %d%%", (int) round (speed * 100)); - } - } + if (speed == 1.0) { + snprintf (buf, sizeof (buf), "%s", _("Playing")); + } else { + if (speed < 0.0) { + snprintf (buf, sizeof (buf), "<<< %d%%", (int) round (-speed * 100)); + } else { + snprintf (buf, sizeof (buf), ">>> %d%%", (int) round (speed * 100)); + } + } } else { - bool reversed; - int semi = speed_as_semitones (speed, reversed); + bool reversed; + int semi = speed_as_semitones (speed, reversed); - if (reversed) { - snprintf (buf, sizeof (buf), _("<<< %+d semitones"), semi); - } else { - snprintf (buf, sizeof (buf), _(">>> %+d semitones"), semi); - } + if (reversed) { + snprintf (buf, sizeof (buf), _("<<< %+d semitones"), semi); + } else { + snprintf (buf, sizeof (buf), _(">>> %+d semitones"), semi); + } } } else { - snprintf (buf, sizeof (buf), _("Stopped")); + snprintf (buf, sizeof (buf), "%s", _("Stopped")); } last_speed_displayed = speed; - cairo_set_source_rgb (cr, 1.0, 1.0, 1.0); - cairo_text_extents (cr, buf, &extents); - cairo_move_to (cr, 10, extents.height + 2); + cairo_set_source_rgb (cr, 0.6, 0.6, 0.6); + cairo_text_extents (cr, buf, &extents); + cairo_move_to (cr, 10, extents.height + 4); + cairo_set_font_size (cr, 13.0); cairo_show_text (cr, buf); /* style text */ @@ -531,21 +596,32 @@ ShuttleControl::on_expose_event (GdkEventExpose* event) switch (Config->get_shuttle_behaviour()) { case Sprung: - snprintf (buf, sizeof (buf), _("Sprung")); + snprintf (buf, sizeof (buf), "%s", _("Sprung")); break; case Wheel: - snprintf (buf, sizeof (buf), _("Wheel")); + snprintf (buf, sizeof (buf), "%s", _("Wheel")); break; } - cairo_text_extents (cr, buf, &extents); - - cairo_move_to (cr, get_width() - (fabs(extents.x_advance) + 5), extents.height + 2); + cairo_text_extents (cr, buf, &extents); + cairo_move_to (cr, get_width() - (fabs(extents.x_advance) + 5), extents.height + 4); cairo_show_text (cr, buf); - cairo_destroy (cr); + float _corner_radius = 4.0; - return true; +/* //reflection + float rheight = 10.0; + Gtkmm2ext::rounded_rectangle (cr, 2, 1, get_width()-4, rheight, _corner_radius); + cairo_set_source (cr, shine_pattern); + cairo_fill (cr); +*/ + if (ARDOUR::Config->get_widget_prelight()) { + if (_hovering) { + rounded_rectangle (cr, 1, 1, get_width()-2, get_height()-2, _corner_radius); + cairo_set_source_rgba (cr, 1, 1, 1, 0.2); + cairo_fill (cr); + } + } } void @@ -560,13 +636,13 @@ ShuttleControl::shuttle_unit_clicked () void ShuttleControl::set_shuttle_style (ShuttleBehaviour s) { - Config->set_shuttle_behaviour (s); + Config->set_shuttle_behaviour (s); } void ShuttleControl::set_shuttle_units (ShuttleUnits s) { - Config->set_shuttle_units (s); + Config->set_shuttle_units (s); } void @@ -576,71 +652,81 @@ ShuttleControl::update_speed_display () queue_draw (); } } - -ShuttleControl::ShuttleControllable::ShuttleControllable (ShuttleControl& s) - : PBD::Controllable (X_("Shuttle")) - , sc (s) -{ -} -void -ShuttleControl::ShuttleControllable::set_id (const std::string& str) +ShuttleControl::ShuttleControllable::ShuttleControllable (ShuttleControl& s) + : PBD::Controllable (X_("Shuttle")) + , sc (s) { - _id = str; } void ShuttleControl::ShuttleControllable::set_value (double val) { - double fract; - - if (val == 0.5) { - fract = 0.0; - } else { - if (val < 0.5) { - fract = -((0.5 - val)/0.5); - } else { - fract = ((val - 0.5)/0.5); - } - } - - sc.set_shuttle_fract (fract); + sc.set_shuttle_fract ((val - lower()) / (upper() - lower()), true); } -double +double ShuttleControl::ShuttleControllable::get_value () const { - return sc.get_shuttle_fract (); + return lower() + (sc.get_shuttle_fract () * (upper() - lower())); } void ShuttleControl::parameter_changed (std::string p) { - if (p == "shuttle-behaviour") { + if (p == "shuttle-behaviour") { switch (Config->get_shuttle_behaviour ()) { case Sprung: - /* back to Sprung - reset to speed = 1.0 if playing - */ + /* back to Sprung - reset to speed = 1.0 if playing + */ if (_session) { if (_session->transport_rolling()) { - if (_session->transport_speed() == 1.0) { - queue_draw (); - } else { - _session->request_transport_speed (1.0); - /* redraw when speed changes */ - } + if (_session->transport_speed() == 1.0) { + queue_draw (); + } else { + /* reset current speed and + revert to 1.0 as the default + */ + _session->request_transport_speed (1.0); + /* redraw when speed changes */ + } } else { - queue_draw (); - } + queue_draw (); + } } break; case Wheel: - queue_draw (); + queue_draw (); break; } - + } else if (p == "shuttle-units") { - queue_draw (); - } + queue_draw (); + } +} + + +bool +ShuttleControl::on_enter_notify_event (GdkEventCrossing* ev) +{ + _hovering = true; + + if (ARDOUR::Config->get_widget_prelight()) { + queue_draw (); + } + + return CairoWidget::on_enter_notify_event (ev); +} + +bool +ShuttleControl::on_leave_notify_event (GdkEventCrossing* ev) +{ + _hovering = false; + + if (ARDOUR::Config->get_widget_prelight()) { + queue_draw (); + } + + return CairoWidget::on_leave_notify_event (ev); }