From 1ff30dcecb7df24125bb53fbcf0129fe5f1803a0 Mon Sep 17 00:00:00 2001 From: Paul Davis Date: Tue, 30 Nov 2010 20:22:43 +0000 Subject: [PATCH] first basic pass at a single widget stereo panner git-svn-id: svn://localhost/ardour2/branches/3.0@8135 d708f5d6-7413-0410-9779-e7cbd77b26cf --- gtk2_ardour/ardour_ui.cc | 2 - gtk2_ardour/panner_ui.cc | 68 ++------------- gtk2_ardour/panner_ui.h | 7 +- gtk2_ardour/stereo_panner.cc | 162 +++++++++++++++++++++++++++++++++++ gtk2_ardour/stereo_panner.h | 54 ++++++++++++ gtk2_ardour/wscript | 1 + 6 files changed, 227 insertions(+), 67 deletions(-) create mode 100644 gtk2_ardour/stereo_panner.cc create mode 100644 gtk2_ardour/stereo_panner.h diff --git a/gtk2_ardour/ardour_ui.cc b/gtk2_ardour/ardour_ui.cc index ce27c6a3b8..e969f31cf1 100644 --- a/gtk2_ardour/ardour_ui.cc +++ b/gtk2_ardour/ardour_ui.cc @@ -288,9 +288,7 @@ ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[]) GainMeter::setup_slider_pix (); RouteTimeAxisView::setup_slider_pix (); SendProcessorEntry::setup_slider_pix (); - PannerUI::setup_slider_pix (); SessionEvent::create_per_thread_pool ("GUI", 512); - } catch (failed_constructor& err) { error << string_compose (_("could not initialize %1."), PROGRAM_NAME) << endmsg; diff --git a/gtk2_ardour/panner_ui.cc b/gtk2_ardour/panner_ui.cc index b038ac6f06..42d6684c94 100644 --- a/gtk2_ardour/panner_ui.cc +++ b/gtk2_ardour/panner_ui.cc @@ -31,6 +31,7 @@ #include "utils.h" #include "panner.h" #include "gui_thread.h" +#include "stereo_panner.h" #include "ardour/delivery.h" #include "ardour/session.h" @@ -46,7 +47,6 @@ using namespace Gtkmm2ext; using namespace Gtk; const int PannerUI::pan_bar_height = 20; -Glib::RefPtr PannerUI::_poswidth_slider; PannerUI::PannerUI (Session* s) : _current_nouts (-1) @@ -56,8 +56,6 @@ PannerUI::PannerUI (Session* s) , panning_viewport(hAdjustment, vAdjustment) , panning_up_arrow (Gtk::ARROW_UP, Gtk::SHADOW_OUT) , panning_down_arrow (Gtk::ARROW_DOWN, Gtk::SHADOW_OUT) - , _position_adjustment (0.5, 0.0, 1.0, 0.01, 0.1) - , _width_adjustment (0.0, -1.0, 1.0, 0.01, 0.1) , panning_link_button (_("link")) , pan_automation_style_button ("") , pan_automation_state_button ("") @@ -70,8 +68,7 @@ PannerUI::PannerUI (Session* s) pan_astate_menu = 0; pan_astyle_menu = 0; in_pan_update = false; - _position_fader = 0; - _width_fader = 0; + _stereo_panner = 0; _ignore_width_change = false; _ignore_position_change = false; @@ -309,8 +306,7 @@ PannerUI::~PannerUI () delete pan_menu; delete pan_astyle_menu; delete pan_astate_menu; - delete _position_fader; - delete _width_fader; + delete _stereo_panner; } @@ -488,33 +484,16 @@ PannerUI::setup_pan () if (npans == 2) { /* add position and width controls */ - if (_position_fader == 0) { - _position_fader = new BarController (_position_adjustment, _panner->direction_control()); - _position_fader->set_size_request (-1, pan_bar_height/2); - _position_fader->set_name ("PanSlider"); - _position_fader->set_style (BarController::Blob); - ARDOUR_UI::instance()->set_tip (_position_fader, _("Pan Position")); - _position_adjustment.signal_value_changed().connect (sigc::mem_fun (*this, &PannerUI::position_adjusted)); - _panner->direction_control()->Changed.connect (connections, invalidator (*this), boost::bind (&PannerUI::show_position, this), gui_context()); - show_position(); - - _width_fader = new BarController (_width_adjustment, _panner->width_control()); - _width_fader->set_size_request (-1, pan_bar_height/2); - _width_fader->set_name ("PanSlider"); - _width_fader->set_style (BarController::CenterOut); - ARDOUR_UI::instance()->set_tip (_width_fader, _("Stereo Image Width")); - _width_adjustment.signal_value_changed().connect (sigc::mem_fun (*this, &PannerUI::width_adjusted)); - _panner->width_control()->Changed.connect (connections, invalidator (*this), boost::bind (&PannerUI::show_width, this), gui_context()); - show_width(); - - poswidth_box.pack_start (*_position_fader, true, true); - poswidth_box.pack_start (*_width_fader, true, true); + if (_stereo_panner == 0) { + _stereo_panner = new StereoPanner (_panner->direction_control(), + _panner->width_control()); + poswidth_box.pack_start (*_stereo_panner, true, true); } pan_vbox.pack_start (poswidth_box, false, false); poswidth_box.show_all (); cerr << "Packed poswidth and mde it visible\n"; } else { - if (_position_fader) { + if (_stereo_panner) { pan_vbox.remove (poswidth_box); cerr << "Hid poswidth\n"; } @@ -974,53 +953,22 @@ PannerUI::bar_spinner_activate (bool a) _bar_spinner_active = a; } -void -PannerUI::setup_slider_pix () -{ - _poswidth_slider = ::get_icon ("fader_belt_h_thin"); - assert (_poswidth_slider); -} - void PannerUI::show_width () { - float const value = _panner->width_control()->get_value (); - - if (_width_adjustment.get_value() != value) { - _ignore_width_change = true; - _width_adjustment.set_value (value); - _ignore_width_change = false; - } } void PannerUI::width_adjusted () { - if (_ignore_width_change) { - return; - } - - _panner->width_control()->set_value (_width_adjustment.get_value()); } void PannerUI::show_position () { - float const value = _panner->direction_control()->get_value (); - - if (_position_adjustment.get_value() != value) { - _ignore_position_change = true; - _position_adjustment.set_value (value); - _ignore_position_change = false; - } } void PannerUI::position_adjusted () { - if (_ignore_position_change) { - return; - } - - _panner->direction_control()->set_value (_position_adjustment.get_value()); } diff --git a/gtk2_ardour/panner_ui.h b/gtk2_ardour/panner_ui.h index bf2d4bb0c4..ea54d82def 100644 --- a/gtk2_ardour/panner_ui.h +++ b/gtk2_ardour/panner_ui.h @@ -40,6 +40,7 @@ class Panner2d; class PannerBar; class Panner2dWindow; +class StereoPanner; namespace ARDOUR { class Session; @@ -112,11 +113,7 @@ class PannerUI : public Gtk::HBox, public ARDOUR::SessionHandlePtr Gtk::VBox poswidth_box; Width _width; - Gtk::Adjustment _position_adjustment; - Gtk::Adjustment _width_adjustment; - Gtkmm2ext::BarController* _position_fader; - Gtkmm2ext::BarController* _width_fader; - static Glib::RefPtr _poswidth_slider; + StereoPanner* _stereo_panner; bool _ignore_width_change; bool _ignore_position_change; void width_adjusted (); diff --git a/gtk2_ardour/stereo_panner.cc b/gtk2_ardour/stereo_panner.cc new file mode 100644 index 0000000000..9f3cad1290 --- /dev/null +++ b/gtk2_ardour/stereo_panner.cc @@ -0,0 +1,162 @@ +/* + Copyright (C) 2000-2007 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#include +#include +#include + +#include "pbd/controllable.h" + +#include "gtkmm2ext/gui_thread.h" + +#include "ardour/panner.h" +#include "stereo_panner.h" + +#include "i18n.h" + +using namespace std; +using namespace Gtk; + +StereoPanner::StereoPanner (boost::shared_ptr position, boost::shared_ptr width) + : position_control (position) + , width_control (width) + , dragging (false) + , dragging_position (false) + , drag_start_x (0) + , last_drag_x (0) +{ + set_size_request (-1, 15); + + position_control->Changed.connect (connections, invalidator(*this), boost::bind (&DrawingArea::queue_draw, this), gui_context()); + width_control->Changed.connect (connections, invalidator(*this), boost::bind (&DrawingArea::queue_draw, this), gui_context()); + + add_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK|Gdk::SCROLL_MASK|Gdk::POINTER_MOTION_MASK); +} + +StereoPanner::~StereoPanner () +{ +} + +bool +StereoPanner::on_expose_event (GdkEventExpose* ev) +{ + Glib::RefPtr win (get_window()); + Glib::RefPtr gc (get_style()->get_base_gc (get_state())); + + cairo_t* cr = gdk_cairo_create (win->gobj()); + + int x1, x2, y1, y2; + int h, w; + int width, height; + double pos = position_control->get_value (); /* 0..1 */ + double swidth = width_control->get_value (); /* -1..+1 */ + const int pos_box_size = 5; + + width = get_width(); + height = get_height (); + + /* compute where the central box is */ + + x1 = (int) floor (width * pos); + x1 -= pos_box_size/2; + + cairo_set_source_rgb (cr, 255, 0, 0); + cairo_rectangle (cr, x1, 4, pos_box_size, pos_box_size); + cairo_fill (cr); + + /* compute & draw the line through the box */ + + x2 = x1 - (int) floor ((fabs (swidth) * width)/2.0); // center, then back up half the swidth value + + cairo_set_source_rgb (cr, 0, 255, 0); + cairo_move_to (cr, x2, 4+(pos_box_size/2)); + cairo_line_to (cr, x2 + floor ((fabs (swidth * width))), 4+(pos_box_size/2)); + cairo_stroke (cr); + + cairo_destroy (cr); + return true; +} + +bool +StereoPanner::on_button_press_event (GdkEventButton* ev) +{ + drag_start_x = ev->x; + last_drag_x = ev->x; + + /* center 8 pixels are for position drag */ + + int w = get_width(); + + if ((ev->x >= (w/2)-4) && (ev->x <= (w/2)+4)) { + dragging_position = true; + } else { + dragging_position = false; + } + + dragging = true; + return true; +} + +bool +StereoPanner::on_button_release_event (GdkEventButton* ev) +{ + dragging = false; + dragging_position = false; + return true; +} + +bool +StereoPanner::on_motion_notify_event (GdkEventMotion* ev) +{ + if (!dragging) { + return false; + } + + int w = get_width(); + float delta = ((fabs) (ev->x - last_drag_x)) / (double) (w/2); + + if (!dragging_position) { + double wv = width_control->get_value(); + + if (((drag_start_x < w/2) && ev->x > last_drag_x) || // start left of center, move towards it + ((drag_start_x > w/2) && ev->x < last_drag_x)) { // start right of center, move towards it + wv = wv * (1.0 - delta); + } else { + /* moving out, so increase the width */ + wv = wv * (1.0 + delta); + } + + width_control->set_value (wv); + + } else { + + double pv = position_control->get_value(); // 0..1.0 ; 0 = left + + if (ev->x > last_drag_x) { // increasing + pv = pv * (1.0 + delta); + } else { + pv = pv * (1.0 - delta); + } + + position_control->set_value (pv); + } + + last_drag_x = ev->x; + return true; +} diff --git a/gtk2_ardour/stereo_panner.h b/gtk2_ardour/stereo_panner.h new file mode 100644 index 0000000000..f4652ca475 --- /dev/null +++ b/gtk2_ardour/stereo_panner.h @@ -0,0 +1,54 @@ +/* + Copyright (C) 2010 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#ifndef __gtk_ardour_stereo_panner_h__ +#define __gtk_ardour_stereo_panner_h__ + +#include "pbd/signals.h" + +#include +#include + +namespace PBD { + class Controllable; +} + +class StereoPanner : public Gtk::DrawingArea +{ + public: + StereoPanner (boost::shared_ptr pos, boost::shared_ptr width); + ~StereoPanner (); + + protected: + bool on_expose_event (GdkEventExpose*); + bool on_button_press_event (GdkEventButton*); + bool on_button_release_event (GdkEventButton*); + bool on_motion_notify_event (GdkEventMotion*); + + private: + boost::shared_ptr position_control; + boost::shared_ptr width_control; + PBD::ScopedConnectionList connections; + bool dragging; + bool dragging_position; + int drag_start_x; + int last_drag_x; +}; + +#endif /* __gtk_ardour_stereo_panner_h__ */ diff --git a/gtk2_ardour/wscript b/gtk2_ardour/wscript index d4ce3cc0a0..ac0ef483a7 100644 --- a/gtk2_ardour/wscript +++ b/gtk2_ardour/wscript @@ -202,6 +202,7 @@ gtk2_ardour_sources = [ 'startup.cc', 'step_editor.cc', 'step_entry.cc', + 'stereo_panner.cc', 'streamview.cc', 'strip_silence_dialog.cc', 'tape_region_view.cc', -- 2.30.2