diff --git a/gtk2_ardour/mixer_strip.cc b/gtk2_ardour/mixer_strip.cc index dab658e06b..bafdce8b59 100644 --- a/gtk2_ardour/mixer_strip.cc +++ b/gtk2_ardour/mixer_strip.cc @@ -1730,7 +1730,7 @@ MixerStrip::show_send (boost::shared_ptr send) uint32_t const in = _current_delivery->pans_required(); uint32_t const out = _current_delivery->pan_outs(); - panner_ui().set_panner (_current_delivery->panner_shell(), _current_delivery->panner()); + panner_ui().set_panner (boost::shared_ptr(), _current_delivery->panner_shell(), _current_delivery->panner()); panner_ui().set_available_panners(PannerManager::instance().PannerManager::get_available_panners(in, out)); panner_ui().setup_pan (); panner_ui().show_all (); @@ -1756,7 +1756,7 @@ MixerStrip::revert_to_default_display () gain_meter().set_controls (_route, _route->shared_peak_meter(), _route->amp()); gain_meter().setup_meters (); - panner_ui().set_panner (_route->main_outs()->panner_shell(), _route->main_outs()->panner()); + panner_ui().set_panner (_route, _route->main_outs()->panner_shell(), _route->main_outs()->panner()); update_panner_choices(); panner_ui().setup_pan (); diff --git a/gtk2_ardour/mono_panner.cc b/gtk2_ardour/mono_panner.cc index f2a6b8b662..6500343395 100644 --- a/gtk2_ardour/mono_panner.cc +++ b/gtk2_ardour/mono_panner.cc @@ -38,6 +38,8 @@ #include "ardour/panner.h" #include "ardour/panner_shell.h" +#include "public_editor.h" +#include "selection.h" #include "ardour_ui.h" #include "global_signals.h" #include "mono_panner.h" @@ -53,6 +55,7 @@ using namespace Gtkmm2ext; using namespace ARDOUR_UI_UTILS; Gdk::Cursor* MonoPanner::__touch_cursor; +double MonoPanner::DEFAULT_VALUE = 0.5; MonoPanner::MonoPanner (boost::shared_ptr p) : PannerInterface (p->panner()) @@ -65,26 +68,22 @@ MonoPanner::MonoPanner (boost::shared_ptr p) , position_binder (position_control) , _dragging (false) { + init (); +} - if (_knob_image[0] == 0) { - for (size_t i=0; i < (sizeof(_knob_image)/sizeof(_knob_image[0])); i++) { - _knob_image[i] = load_pixbuf (_knob_image_files[i]); - } - } - - if (__touch_cursor == 0) { - __touch_cursor = new Gdk::Cursor (Gdk::Display::get_default(), - ::get_icon ("panner_touch_cursor"), - 12, - 12); - } - - position_control->Changed.connect (panvalue_connections, invalidator(*this), boost::bind (&MonoPanner::value_change, this), gui_context()); - - _panner_shell->Changed.connect (panshell_connections, invalidator (*this), boost::bind (&MonoPanner::bypass_handler, this), gui_context()); - _panner_shell->PannableChanged.connect (panshell_connections, invalidator (*this), boost::bind (&MonoPanner::pannable_handler, this), gui_context()); - - set_tooltip (); +MonoPanner::MonoPanner (boost::shared_ptr route, boost::shared_ptr p) +: PannerInterface (p->panner()) +, _route (route) +, _panner_shell (p) +, position_control (_panner->pannable()->pan_azimuth_control) +, drag_start_y (0) +, last_drag_y (0) +, accumulated_delta (0) +, detented (false) +, position_binder (position_control) +, _dragging (false) +{ + init (); } MonoPanner::~MonoPanner () @@ -92,6 +91,30 @@ MonoPanner::~MonoPanner () } +void +MonoPanner::init () +{ + if (_knob_image[0] == 0) { + for (size_t i=0; i < (sizeof(_knob_image)/sizeof(_knob_image[0])); i++) { + _knob_image[i] = load_pixbuf (_knob_image_files[i]); + } + } + + if (__touch_cursor == 0) { + __touch_cursor = new Gdk::Cursor (Gdk::Display::get_default(), + ::get_icon ("panner_touch_cursor"), + 12, + 12); + } + + position_control->Changed.connect (panvalue_connections, invalidator(*this), boost::bind (&MonoPanner::value_change, this), gui_context()); + + _panner_shell->Changed.connect (panshell_connections, invalidator (*this), boost::bind (&MonoPanner::bypass_handler, this), gui_context()); + _panner_shell->PannableChanged.connect (panshell_connections, invalidator (*this), boost::bind (&MonoPanner::pannable_handler, this), gui_context()); + + set_tooltip (); +} + void MonoPanner::set_tooltip () { @@ -174,7 +197,36 @@ MonoPanner::on_button_press_event (GdkEventButton* ev) if (ev->type == GDK_BUTTON_PRESS) { if (Keyboard::modifier_state_contains (ev->state, alt_modifier)) { - position_control->set_value (0.5); + + // reset panner to default value + if (_route && _route->main_outs()->panner() == _panner) { + + // determine if we deal with selection + PublicEditor& editor = ARDOUR_UI::instance()->the_editor(); + Selection& selection = editor.get_selection(); + TimeAxisView* tv = editor.get_route_view_by_route_id (_route->id() ); + + if (tv && selection.selected(tv) && selection.tracks.size() > 1 ) { + boost::shared_ptr routes = get_selected_routes (); + + ARDOUR::RouteList::const_iterator iter = routes->begin(); + for (; iter != routes->end(); ++iter) { + + boost::shared_ptr control; + control = (*iter)->panner()->pannable()->pan_azimuth_control; + control->set_value (DEFAULT_VALUE); + } + } else { + + boost::shared_ptr control; + control = _route->panner()->pannable()->pan_azimuth_control; + control->set_value (DEFAULT_VALUE); + } + + } else { + position_control->set_value (DEFAULT_VALUE); + } + _dragging = false; _tooltip.target_stop_drag (); } else { @@ -265,33 +317,111 @@ MonoPanner::on_motion_notify_event (GdkEventMotion* ev) int w = get_width(); double delta = (last_drag_y - ev->y) / (double) w; - /* create a detent close to the center */ - - if (!detented && ARDOUR::Panner::equivalent (position_control->get_value(), 0.5)) { - detented = true; - /* snap to center */ - position_control->set_value (0.5); - } - - if (detented) { - accumulated_delta += delta; - - /* have we pulled far enough to escape ? */ - - if (fabs (accumulated_delta) >= 0.025) { - position_control->set_value (position_control->get_value() + accumulated_delta); - detented = false; - accumulated_delta = false; - } - } else { - double pv = position_control->get_value(); // 0..1.0 ; 0 = left - position_control->set_value (pv + delta); - } + adjust_pan_value_by (delta); last_drag_y = ev->y; return true; } +boost::shared_ptr +MonoPanner::get_selected_routes () +{ + Selection& selection = ARDOUR_UI::instance()->the_editor().get_selection(); + + boost::shared_ptr routes (new ARDOUR::RouteList); + + TrackViewList track_list = selection.tracks; + TrackViewList::const_iterator iter = track_list.begin (); + for (; iter != track_list.end(); ++iter) { + RouteTimeAxisView* rtv = dynamic_cast(*iter); + + if (rtv) { + routes->push_back(rtv->route() ); + } + } + + return routes; + +} + +void +MonoPanner::adjust_pan_value_by (double delta) +{ + // first, calculate correct increment delta value + double update_by_delta = 0; + + /* create a detent close to the center */ + if (!detented && ARDOUR::Panner::equivalent (position_control->get_value(), DEFAULT_VALUE)) { + detented = true; + } + + if (detented) { + accumulated_delta += delta; + + /* have we pulled far enough to escape ? */ + + if (fabs (accumulated_delta) >= 0.025) { + update_by_delta = accumulated_delta; + detented = false; + accumulated_delta = 0; + } + } else { + update_by_delta = delta; + } + + // we've reached the bottom or the top, so don't move in this direction any more + double original_val = position_control->get_value(); + if ( (update_by_delta > 0 && original_val >= 1 ) || + (update_by_delta < 0 && original_val <= 0 ) ) { + return; + } + + // make sure that calculated delta won't exceed the value we need to reach the top + // or make us to go lower then the the bottom + double result_value = original_val + update_by_delta; + if (result_value < 0 ) { + update_by_delta = update_by_delta - result_value; + } else if (result_value > 1) { + update_by_delta = update_by_delta - (result_value - 1); + } + + // apply change to the associated route if we have it + if (_route && _route->main_outs()->panner() == _panner) { + + // determine if we deal with selection + PublicEditor& editor = ARDOUR_UI::instance()->the_editor(); + Selection& selection = editor.get_selection(); + TimeAxisView* tv = editor.get_route_view_by_route_id (_route->id() ); + + if (tv && selection.selected(tv) && selection.tracks.size() > 1 ) { + boost::shared_ptr routes = get_selected_routes (); + + // apply the change + ARDOUR::RouteList::const_iterator iter = routes->begin(); + for (; iter != routes->end(); ++iter) { + + boost::shared_ptr control; + control = (*iter)->panner()->pannable()->pan_azimuth_control; + + double pv = control->get_value(); // 0..1.0 ; 0 = left + control->set_value (pv + update_by_delta); + } + + } else { + + boost::shared_ptr control; + control = _route->panner()->pannable()->pan_azimuth_control; + + double pv = control->get_value(); // 0..1.0 ; 0 = left + control->set_value (pv + update_by_delta); + } + + } else { // apply change to the panner directly + double pv = position_control->get_value(); // 0..1.0 ; 0 = left + position_control->set_value (pv + update_by_delta); + } +} + bool MonoPanner::on_key_press_event (GdkEventKey* ev) { diff --git a/gtk2_ardour/mono_panner.h b/gtk2_ardour/mono_panner.h index afe9fe0a8c..c3ab7a214b 100644 --- a/gtk2_ardour/mono_panner.h +++ b/gtk2_ardour/mono_panner.h @@ -28,6 +28,8 @@ #include "panner_interface.h" +#include "ardour/route.h" + namespace ARDOUR { class PannerShell; } @@ -39,7 +41,12 @@ namespace PBD { class MonoPanner : public PannerInterface { public: + + static double DEFAULT_VALUE; + MonoPanner (boost::shared_ptr); + MonoPanner (boost::shared_ptr, boost::shared_ptr); + ~MonoPanner (); boost::shared_ptr get_controllable() const { return position_control; } @@ -54,9 +61,15 @@ class MonoPanner : public PannerInterface bool on_motion_notify_event (GdkEventMotion*); bool on_scroll_event (GdkEventScroll*); bool on_key_press_event (GdkEventKey*); + + void adjust_pan_value_by (double); private: + void init (); + boost::shared_ptr get_selected_routes (); + PannerEditor* editor (); + boost::shared_ptr _route; boost::shared_ptr _panner_shell; boost::shared_ptr position_control; diff --git a/gtk2_ardour/panner_ui.cc b/gtk2_ardour/panner_ui.cc index b1bd6873b0..35edca2a9c 100644 --- a/gtk2_ardour/panner_ui.cc +++ b/gtk2_ardour/panner_ui.cc @@ -90,7 +90,7 @@ PannerUI::PannerUI (Session* s) } void -PannerUI::set_panner (boost::shared_ptr ps, boost::shared_ptr p) +PannerUI::set_panner (boost::shared_ptr route, boost::shared_ptr ps, boost::shared_ptr p) { /* note that the panshell might not change here (i.e. ps == _panshell) */ @@ -115,6 +115,9 @@ PannerUI::set_panner (boost::shared_ptr ps, boost::shared_ptrpanner()); + set_panner (_route, _panshell, _panshell->panner()); setup_pan (); } @@ -275,8 +278,8 @@ PannerUI::setup_pan () boost::shared_ptr pannable = _panner->pannable(); boost::shared_ptr ac = pannable->pan_azimuth_control; - _mono_panner = new MonoPanner (_panshell); - + _mono_panner = new MonoPanner (_route, _panshell); + _mono_panner->StartGesture.connect (sigc::bind (sigc::mem_fun (*this, &PannerUI::start_touch), boost::weak_ptr (ac))); _mono_panner->StopGesture.connect (sigc::bind (sigc::mem_fun (*this, &PannerUI::stop_touch), diff --git a/gtk2_ardour/panner_ui.h b/gtk2_ardour/panner_ui.h index 8bf448c7ea..964ec518e0 100644 --- a/gtk2_ardour/panner_ui.h +++ b/gtk2_ardour/panner_ui.h @@ -64,7 +64,7 @@ class PannerUI : public Gtk::HBox, public ARDOUR::SessionHandlePtr PannerUI (ARDOUR::Session*); ~PannerUI (); - virtual void set_panner (boost::shared_ptr, boost::shared_ptr); + virtual void set_panner (boost::shared_ptr, boost::shared_ptr, boost::shared_ptr); void panshell_changed (); @@ -110,7 +110,8 @@ class PannerUI : public Gtk::HBox, public ARDOUR::SessionHandlePtr StereoPanner* _stereo_panner; MonoPanner* _mono_panner; - + boost::shared_ptr _route; + bool _ignore_width_change; bool _ignore_position_change; void width_adjusted (); diff --git a/gtk2_ardour/send_ui.cc b/gtk2_ardour/send_ui.cc index 64f628e8f1..063c7c2943 100644 --- a/gtk2_ardour/send_ui.cc +++ b/gtk2_ardour/send_ui.cc @@ -42,7 +42,7 @@ SendUI::SendUI (Gtk::Window* parent, boost::shared_ptr s, Session* session { assert (_send); - _panners.set_panner (s->panner_shell(), s->panner()); + _panners.set_panner (boost::shared_ptr(), s->panner_shell(), s->panner()); _gpm.set_controls (boost::shared_ptr(), s->meter(), s->amp()); _hbox.pack_start (_gpm, true, true); @@ -104,7 +104,7 @@ SendUI::outs_changed (IOChange change, void* /*ignored*/) uint32_t const in = _send->pans_required(); uint32_t const out = _send->pan_outs(); if (_panners._panner == 0) { - _panners.set_panner (_send->panner_shell(), _send->panner()); + _panners.set_panner (boost::shared_ptr(), _send->panner_shell(), _send->panner()); } _panners.set_available_panners(PannerManager::instance().PannerManager::get_available_panners(in, out)); _panners.setup_pan ();