13
0

Provide dialogs to edit pan values numerically, at least for

mono and stereo panners.


git-svn-id: svn://localhost/ardour2/branches/3.0@12577 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
Carl Hetherington 2012-06-06 11:47:09 +00:00
parent 31f94b9b04
commit 46e448252f
20 changed files with 541 additions and 7 deletions

View File

@ -38,6 +38,7 @@
#include "ardour_ui.h"
#include "global_signals.h"
#include "mono_panner.h"
#include "mono_panner_editor.h"
#include "rgb_macros.h"
#include "utils.h"
@ -246,6 +247,10 @@ MonoPanner::on_expose_event (GdkEventExpose*)
bool
MonoPanner::on_button_press_event (GdkEventButton* ev)
{
if (PannerInterface::on_button_press_event (ev)) {
return true;
}
drag_start_x = ev->x;
last_drag_x = ev->x;
@ -304,6 +309,10 @@ MonoPanner::on_button_press_event (GdkEventButton* ev)
bool
MonoPanner::on_button_release_event (GdkEventButton* ev)
{
if (PannerInterface::on_button_release_event (ev)) {
return true;
}
if (ev->button != 1) {
return false;
}
@ -440,3 +449,8 @@ MonoPanner::color_handler ()
queue_draw ();
}
PannerEditor*
MonoPanner::editor ()
{
return new MonoPannerEditor (this);
}

View File

@ -52,6 +52,8 @@ class MonoPanner : public PannerInterface
bool on_key_press_event (GdkEventKey*);
private:
PannerEditor* editor ();
boost::shared_ptr<PBD::Controllable> position_control;
PBD::ScopedConnectionList connections;
int drag_start_x;

View File

@ -0,0 +1,119 @@
/*
Copyright (C) 2012 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 <gtkmm.h>
#include "gtkmm2ext/utils.h"
#include "gtkmm2ext/gtk_ui.h"
#include "gtkmm2ext/gui_thread.h"
#include "pbd/controllable.h"
#include "mono_panner_editor.h"
#include "mono_panner.h"
#include "i18n.h"
using namespace Gtk;
using namespace Gtkmm2ext;
MonoPannerEditor::MonoPannerEditor (MonoPanner* p)
: PannerEditor (_("Mono Panner"))
, _panner (p)
, _ignore_changes (false)
{
Table* t = manage (new Table (2, 3));
t->set_spacings (6);
int n = 0;
t->attach (*manage (left_aligned_label (_("Left"))), 0, 1, n, n + 1);
t->attach (_left, 1, 2, n, n + 1);
t->attach (*manage (left_aligned_label (_("%"))), 2, 3, n, n + 1);
++n;
t->attach (*manage (left_aligned_label (_("Right"))), 0, 1, n, n + 1);
t->attach (_right, 1, 2, n, n + 1);
t->attach (*manage (left_aligned_label (_("%"))), 2, 3, n, n + 1);
++n;
get_vbox()->pack_start (*manage (t));
get_vbox()->set_spacing (6);
_left.set_increments (1, 10);
_left.set_range (0, 100);
_right.set_increments (1, 10);
_right.set_range (0, 100);
_panner->get_controllable()->Changed.connect (_connections, invalidator (*this), boost::bind (&MonoPannerEditor::update_editor, this), gui_context ());
_panner->DropReferences.connect (_connections, invalidator (*this), boost::bind (&MonoPannerEditor::panner_going_away, this), gui_context ());
_left.signal_value_changed().connect (sigc::mem_fun (*this, &MonoPannerEditor::left_changed));
_right.signal_value_changed().connect (sigc::mem_fun (*this, &MonoPannerEditor::right_changed));
show_all ();
update_editor ();
}
void
MonoPannerEditor::panner_going_away ()
{
_panner = 0;
}
void
MonoPannerEditor::update_editor ()
{
if (!_panner) {
return;
}
float const v = _panner->get_controllable()->get_value();
_ignore_changes = true;
_left.set_value (100 * (1 - v));
_right.set_value (100 * v);
_ignore_changes = false;
}
void
MonoPannerEditor::left_changed ()
{
if (_ignore_changes || !_panner) {
return;
}
float const v = 1 - _left.get_value () / 100;
_ignore_changes = true;
_right.set_value (100 * v);
_panner->get_controllable()->set_value (v);
_ignore_changes = false;
}
void
MonoPannerEditor::right_changed ()
{
if (_ignore_changes || !_panner) {
return;
}
float const v = _right.get_value () / 100;
_ignore_changes = true;
_left.set_value (100 * (1 - v));
_panner->get_controllable()->set_value (v);
_ignore_changes = false;
}

View File

@ -0,0 +1,43 @@
/*
Copyright (C) 2012 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 <gtkmm.h>
#include "panner_editor.h"
class MonoPanner;
/** Editor dialog for the mono panner */
class MonoPannerEditor : public PannerEditor
{
public:
MonoPannerEditor (MonoPanner *);
private:
void panner_going_away ();
void update_editor ();
void left_changed ();
void right_changed ();
MonoPanner* _panner;
Gtk::SpinButton _left;
Gtk::SpinButton _right;
bool _ignore_changes;
PBD::ScopedConnectionList _connections;
};

View File

@ -0,0 +1,37 @@
/*
Copyright (C) 2012 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 "panner_editor.h"
#include "i18n.h"
using namespace std;
using namespace Gtk;
PannerEditor::PannerEditor (string t)
: ArdourDialog (t)
{
Button* b = add_button (_("Close"), RESPONSE_CANCEL);
b->signal_clicked().connect (sigc::mem_fun(*this, &PannerEditor::close_button_clicked));
}
void
PannerEditor::close_button_clicked ()
{
hide ();
}

View File

@ -0,0 +1,29 @@
/*
Copyright (C) 2012 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 "ardour_dialog.h"
class PannerEditor : public ArdourDialog
{
public:
PannerEditor (std::string);
private:
void close_button_clicked ();
};

View File

@ -20,6 +20,7 @@
#include <gtkmm.h>
#include "gtkmm2ext/keyboard.h"
#include "panner_interface.h"
#include "panner_editor.h"
#include "global_signals.h"
#include "i18n.h"
@ -34,6 +35,7 @@ PannerInterface::PannerInterface (boost::shared_ptr<Panner> p)
, _drag_data_window (0)
, _drag_data_label (0)
, _dragging (false)
, _editor (0)
{
set_flags (Gtk::CAN_FOCUS);
@ -48,6 +50,7 @@ PannerInterface::PannerInterface (boost::shared_ptr<Panner> p)
PannerInterface::~PannerInterface ()
{
delete _drag_data_window;
delete _editor;
}
void
@ -135,3 +138,32 @@ PannerInterface::value_change ()
queue_draw ();
}
bool
PannerInterface::on_button_press_event (GdkEventButton* ev)
{
if (Gtkmm2ext::Keyboard::is_edit_event (ev)) {
edit ();
return true;
}
return false;
}
bool
PannerInterface::on_button_release_event (GdkEventButton* ev)
{
if (Gtkmm2ext::Keyboard::is_edit_event (ev)) {
/* We edited on the press, so claim the release */
return true;
}
return false;
}
void
PannerInterface::edit ()
{
delete _editor;
_editor = editor ();
_editor->show ();
}

View File

@ -23,21 +23,30 @@
#include <boost/shared_ptr.hpp>
#include <gtkmm/drawingarea.h>
#include <gtkmm/label.h>
#include "pbd/destructible.h"
namespace ARDOUR {
class Panner;
}
class PannerEditor;
/** Parent class for some panner UI classes that contains some common code */
class PannerInterface : public Gtk::DrawingArea
class PannerInterface : public Gtk::DrawingArea, public PBD::Destructible
{
public:
PannerInterface (boost::shared_ptr<ARDOUR::Panner>);
virtual ~PannerInterface ();
boost::shared_ptr<ARDOUR::Panner> panner () {
return _panner;
}
void edit ();
protected:
virtual void set_drag_data () = 0;
void show_drag_data_window ();
void hide_drag_data_window ();
void value_change ();
@ -45,6 +54,8 @@ protected:
bool on_enter_notify_event (GdkEventCrossing *);
bool on_leave_notify_event (GdkEventCrossing *);
bool on_key_release_event (GdkEventKey *);
bool on_button_press_event (GdkEventButton*);
bool on_button_release_event (GdkEventButton*);
boost::shared_ptr<ARDOUR::Panner> _panner;
Gtk::Window* _drag_data_window;
@ -54,6 +65,9 @@ protected:
private:
bool drag_data_timeout ();
sigc::connection _drag_data_timeout;
virtual PannerEditor* editor () = 0;
PannerEditor* _editor;
};
#endif

View File

@ -37,7 +37,6 @@
#include "stereo_panner.h"
#include "mono_panner.h"
#include "i18n.h"
using namespace std;
@ -388,6 +387,7 @@ PannerUI::build_pan_menu ()
bypass_menu_item->signal_toggled().connect (sigc::mem_fun(*this, &PannerUI::pan_bypass_toggle));
items.push_back (MenuElem (_("Reset"), sigc::mem_fun (*this, &PannerUI::pan_reset)));
items.push_back (MenuElem (_("Edit..."), sigc::mem_fun (*this, &PannerUI::pan_edit)));
}
void
@ -398,6 +398,16 @@ PannerUI::pan_bypass_toggle ()
}
}
void
PannerUI::pan_edit ()
{
if (_mono_panner) {
_mono_panner->edit ();
} else if (_stereo_panner) {
_stereo_panner->edit ();
}
}
void
PannerUI::pan_reset ()
{

View File

@ -140,6 +140,7 @@ class PannerUI : public Gtk::HBox, public ARDOUR::SessionHandlePtr
void build_pan_menu ();
void pan_reset ();
void pan_bypass_toggle ();
void pan_edit ();
void pan_automation_state_changed();
void pan_automation_style_changed();

View File

@ -37,6 +37,7 @@
#include "ardour_ui.h"
#include "global_signals.h"
#include "stereo_panner.h"
#include "stereo_panner_editor.h"
#include "rgb_macros.h"
#include "utils.h"
@ -263,6 +264,10 @@ StereoPanner::on_expose_event (GdkEventExpose*)
bool
StereoPanner::on_button_press_event (GdkEventButton* ev)
{
if (PannerInterface::on_button_press_event (ev)) {
return true;
}
drag_start_x = ev->x;
last_drag_x = ev->x;
@ -398,6 +403,10 @@ StereoPanner::on_button_press_event (GdkEventButton* ev)
bool
StereoPanner::on_button_release_event (GdkEventButton* ev)
{
if (PannerInterface::on_button_release_event (ev)) {
return true;
}
if (ev->button != 1) {
return false;
}
@ -631,3 +640,9 @@ StereoPanner::color_handler ()
set_colors ();
queue_draw ();
}
PannerEditor*
StereoPanner::editor ()
{
return new StereoPannerEditor (this);
}

View File

@ -38,6 +38,9 @@ class StereoPanner : public PannerInterface
StereoPanner (boost::shared_ptr<ARDOUR::Panner>);
~StereoPanner ();
boost::shared_ptr<PBD::Controllable> get_position_controllable() const { return position_control; }
boost::shared_ptr<PBD::Controllable> get_width_controllable() const { return width_control; }
sigc::signal<void> StartPositionGesture;
sigc::signal<void> StopPositionGesture;
sigc::signal<void> StartWidthGesture;
@ -52,6 +55,8 @@ class StereoPanner : public PannerInterface
bool on_key_press_event (GdkEventKey*);
private:
PannerEditor* editor ();
boost::shared_ptr<PBD::Controllable> position_control;
boost::shared_ptr<PBD::Controllable> width_control;
PBD::ScopedConnectionList connections;

View File

@ -0,0 +1,138 @@
/*
Copyright (C) 2012 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 <gtkmm.h>
#include "gtkmm2ext/utils.h"
#include "gtkmm2ext/gtk_ui.h"
#include "gtkmm2ext/gui_thread.h"
#include "ardour/panner.h"
#include "pbd/controllable.h"
#include "stereo_panner_editor.h"
#include "stereo_panner.h"
#include "i18n.h"
using namespace std;
using namespace Gtk;
using namespace Gtkmm2ext;
StereoPannerEditor::StereoPannerEditor (StereoPanner* p)
: PannerEditor (_("Stereo Panner"))
, _panner (p)
, _ignore_changes (false)
{
Table* t = manage (new Table (2, 3));
t->set_spacings (6);
int n = 0;
t->attach (*manage (left_aligned_label (_("Position"))), 0, 1, n, n + 1);
t->attach (_position, 1, 2, n, n + 1);
t->attach (*manage (left_aligned_label (_("%"))), 2, 3, n, n + 1);
++n;
t->attach (*manage (left_aligned_label (_("Width"))), 0, 1, n, n + 1);
t->attach (_width, 1, 2, n, n + 1);
t->attach (*manage (left_aligned_label (_("%"))), 2, 3, n, n + 1);
++n;
get_vbox()->pack_start (*manage (t));
get_vbox()->set_spacing (6);
_position.set_increments (1, 10);
_width.set_increments (1, 10);
set_position_range ();
set_width_range ();
_panner->get_position_controllable()->Changed.connect (
_connections, invalidator (*this), boost::bind (&StereoPannerEditor::update_editor, this), gui_context ()
);
_panner->get_width_controllable()->Changed.connect (
_connections, invalidator (*this), boost::bind (&StereoPannerEditor::update_editor, this), gui_context ()
);
_panner->DropReferences.connect (_connections, invalidator (*this), boost::bind (&StereoPannerEditor::panner_going_away, this), gui_context ());
_position.signal_value_changed().connect (sigc::mem_fun (*this, &StereoPannerEditor::position_changed));
_width.signal_value_changed().connect (sigc::mem_fun (*this, &StereoPannerEditor::width_changed));
show_all ();
update_editor ();
}
void
StereoPannerEditor::panner_going_away ()
{
_panner = 0;
}
void
StereoPannerEditor::update_editor ()
{
if (!_panner) {
return;
}
_ignore_changes = true;
_position.set_value (100 * _panner->get_position_controllable()->get_value ());
_width.set_value (100 * _panner->get_width_controllable()->get_value ());
_ignore_changes = false;
}
void
StereoPannerEditor::position_changed ()
{
if (_ignore_changes || !_panner) {
return;
}
_ignore_changes = true;
double const v = _position.get_value() / 100;
_panner->get_position_controllable()->set_value (v);
set_width_range ();
_ignore_changes = false;
}
void
StereoPannerEditor::width_changed ()
{
if (_ignore_changes || !_panner) {
return;
}
_ignore_changes = true;
double const v = _width.get_value() / 100;
_panner->get_width_controllable()->set_value (v);
set_position_range ();
_ignore_changes = false;
}
void
StereoPannerEditor::set_position_range ()
{
pair<double, double> const pr = _panner->panner()->position_range ();
_position.set_range (pr.first * 100, pr.second * 100);
}
void
StereoPannerEditor::set_width_range ()
{
pair<double, double> const wr = _panner->panner()->width_range ();
_width.set_range (wr.first * 100, wr.second * 100);
}

View File

@ -0,0 +1,45 @@
/*
Copyright (C) 2012 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 <gtkmm.h>
#include "panner_editor.h"
class StereoPanner;
/** Editor dialog for the stereo panner */
class StereoPannerEditor : public PannerEditor
{
public:
StereoPannerEditor (StereoPanner *);
private:
void panner_going_away ();
void update_editor ();
void position_changed ();
void width_changed ();
void set_position_range ();
void set_width_range ();
StereoPanner* _panner;
Gtk::SpinButton _position;
Gtk::SpinButton _width;
bool _ignore_changes;
PBD::ScopedConnectionList _connections;
};

View File

@ -155,6 +155,7 @@ gtk2_ardour_sources = [
'mixer_ui.cc',
'monitor_section.cc',
'mono_panner.cc',
'mono_panner_editor.cc',
'mouse_cursors.cc',
'nag.cc',
'new_plugin_preset_dialog.cc',
@ -163,6 +164,7 @@ gtk2_ardour_sources = [
'option_editor.cc',
'opts.cc',
'panner2d.cc',
'panner_editor.cc',
'panner_interface.cc',
'panner_ui.cc',
'piano_roll_header.cc',
@ -215,6 +217,7 @@ gtk2_ardour_sources = [
'step_editor.cc',
'step_entry.cc',
'stereo_panner.cc',
'stereo_panner_editor.cc',
'streamview.cc',
'strip_silence_dialog.cc',
'tape_region_view.cc',

View File

@ -71,6 +71,10 @@ public:
virtual bool clamp_width (double&) { return true; }
virtual bool clamp_elevation (double&) { return true; }
virtual std::pair<double, double> position_range () const { return std::make_pair (-DBL_MAX, DBL_MAX); }
virtual std::pair<double, double> width_range () const { return std::make_pair (-DBL_MAX, DBL_MAX); }
virtual std::pair<double, double> elevation_range () const { return std::make_pair (-DBL_MAX, DBL_MAX); }
virtual void set_position (double) { }
virtual void set_width (double) { }
virtual void set_elevation (double) { }

View File

@ -121,6 +121,12 @@ Panner1in2out::clamp_position (double& p)
return true;
}
pair<double, double>
Panner1in2out::position_range () const
{
return make_pair (0, 1);
}
double
Panner1in2out::position () const
{

View File

@ -43,6 +43,7 @@ class Panner1in2out : public Panner
void set_position (double);
bool clamp_position (double&);
std::pair<double, double> position_range () const;
double position() const;

View File

@ -152,8 +152,8 @@ Panner2in2out::update ()
*/
float pos[2];
double width = _pannable->pan_width_control->get_value();
const double direction_as_lr_fract = _pannable->pan_azimuth_control->get_value();
double width = this->width ();
const double direction_as_lr_fract = position ();
if (width < 0.0) {
width = -width;
@ -189,17 +189,30 @@ Panner2in2out::update ()
bool
Panner2in2out::clamp_position (double& p)
{
double w = _pannable->pan_width_control->get_value();
double w = width ();
return clamp_stereo_pan (p, w);
}
bool
Panner2in2out::clamp_width (double& w)
{
double p = _pannable->pan_azimuth_control->get_value();
double p = position ();
return clamp_stereo_pan (p, w);
}
pair<double, double>
Panner2in2out::position_range () const
{
return make_pair (0.5 - (1 - width()) / 2, 0.5 + (1 - width()) / 2);
}
pair<double, double>
Panner2in2out::width_range () const
{
double const w = min (position(), (1 - position())) * 2;
return make_pair (-w, w);
}
bool
Panner2in2out::clamp_stereo_pan (double& direction_as_lr_fract, double& width)
{

View File

@ -49,6 +49,9 @@ class Panner2in2out : public Panner
bool clamp_position (double&);
bool clamp_width (double&);
std::pair<double, double> position_range () const;
std::pair<double, double> width_range () const;
void set_position (double);
void set_width (double);