[Summary] Made panners to move relatively on selected tracks

[Reviewed by QA] Andriy Mishyn
This commit is contained in:
GZharun 2015-01-22 16:22:11 +02:00
parent 0334c46596
commit 416bfc5aab
6 changed files with 199 additions and 52 deletions

View file

@ -1730,7 +1730,7 @@ MixerStrip::show_send (boost::shared_ptr<Send> 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<Route>(), _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 ();

View file

@ -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<ARDOUR::PannerShell> p)
: PannerInterface (p->panner())
@ -65,26 +68,22 @@ MonoPanner::MonoPanner (boost::shared_ptr<ARDOUR::PannerShell> 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<ARDOUR::Route> route, boost::shared_ptr<ARDOUR::PannerShell> 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<ARDOUR::RouteList> routes = get_selected_routes ();
ARDOUR::RouteList::const_iterator iter = routes->begin();
for (; iter != routes->end(); ++iter) {
boost::shared_ptr<ARDOUR::AutomationControl> control;
control = (*iter)->panner()->pannable()->pan_azimuth_control;
control->set_value (DEFAULT_VALUE);
}
} else {
boost::shared_ptr<ARDOUR::AutomationControl> 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<ARDOUR::RouteList>
MonoPanner::get_selected_routes ()
{
Selection& selection = ARDOUR_UI::instance()->the_editor().get_selection();
boost::shared_ptr<ARDOUR::RouteList> 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<RouteTimeAxisView*>(*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<ARDOUR::RouteList> routes = get_selected_routes ();
// apply the change
ARDOUR::RouteList::const_iterator iter = routes->begin();
for (; iter != routes->end(); ++iter) {
boost::shared_ptr<ARDOUR::AutomationControl> 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<ARDOUR::AutomationControl> 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)
{

View file

@ -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<ARDOUR::PannerShell>);
MonoPanner (boost::shared_ptr<ARDOUR::Route>, boost::shared_ptr<ARDOUR::PannerShell>);
~MonoPanner ();
boost::shared_ptr<PBD::Controllable> 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<ARDOUR::RouteList> get_selected_routes ();
PannerEditor* editor ();
boost::shared_ptr<ARDOUR::Route> _route;
boost::shared_ptr<ARDOUR::PannerShell> _panner_shell;
boost::shared_ptr<PBD::Controllable> position_control;

View file

@ -90,7 +90,7 @@ PannerUI::PannerUI (Session* s)
}
void
PannerUI::set_panner (boost::shared_ptr<PannerShell> ps, boost::shared_ptr<Panner> p)
PannerUI::set_panner (boost::shared_ptr<ARDOUR::Route> route, boost::shared_ptr<PannerShell> ps, boost::shared_ptr<Panner> p)
{
/* note that the panshell might not change here (i.e. ps == _panshell)
*/
@ -115,6 +115,9 @@ PannerUI::set_panner (boost::shared_ptr<PannerShell> ps, boost::shared_ptr<Panne
delete _mono_panner;
_mono_panner = 0;
_route.reset();
_route = route;
if (!_panner) {
return;
}
@ -204,7 +207,7 @@ PannerUI::~PannerUI ()
void
PannerUI::panshell_changed ()
{
set_panner (_panshell, _panshell->panner());
set_panner (_route, _panshell, _panshell->panner());
setup_pan ();
}
@ -275,8 +278,8 @@ PannerUI::setup_pan ()
boost::shared_ptr<Pannable> pannable = _panner->pannable();
boost::shared_ptr<AutomationControl> 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<AutomationControl> (ac)));
_mono_panner->StopGesture.connect (sigc::bind (sigc::mem_fun (*this, &PannerUI::stop_touch),

View file

@ -64,7 +64,7 @@ class PannerUI : public Gtk::HBox, public ARDOUR::SessionHandlePtr
PannerUI (ARDOUR::Session*);
~PannerUI ();
virtual void set_panner (boost::shared_ptr<ARDOUR::PannerShell>, boost::shared_ptr<ARDOUR::Panner>);
virtual void set_panner (boost::shared_ptr<ARDOUR::Route>, boost::shared_ptr<ARDOUR::PannerShell>, boost::shared_ptr<ARDOUR::Panner>);
void panshell_changed ();
@ -110,7 +110,8 @@ class PannerUI : public Gtk::HBox, public ARDOUR::SessionHandlePtr
StereoPanner* _stereo_panner;
MonoPanner* _mono_panner;
boost::shared_ptr<ARDOUR::Route> _route;
bool _ignore_width_change;
bool _ignore_position_change;
void width_adjusted ();

View file

@ -42,7 +42,7 @@ SendUI::SendUI (Gtk::Window* parent, boost::shared_ptr<Send> s, Session* session
{
assert (_send);
_panners.set_panner (s->panner_shell(), s->panner());
_panners.set_panner (boost::shared_ptr<Route>(), s->panner_shell(), s->panner());
_gpm.set_controls (boost::shared_ptr<Route>(), 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<Route>(), _send->panner_shell(), _send->panner());
}
_panners.set_available_panners(PannerManager::instance().PannerManager::get_available_panners(in, out));
_panners.setup_pan ();