Make pan double-click entry work in percentage left or right. Write pan position to the panner as text (except when centered). Use a virtual function rather than a signal for BarController labels.

git-svn-id: svn://localhost/ardour2/branches/3.0@5104 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
Carl Hetherington 2009-05-20 13:28:30 +00:00
parent dbe20bd3a9
commit 64524c0ba4
10 changed files with 191 additions and 96 deletions

View file

@ -18,6 +18,7 @@
*/ */
#include <iomanip>
#include "pbd/error.h" #include "pbd/error.h"
#include "ardour/automation_list.h" #include "ardour/automation_list.h"
#include "ardour/automation_control.h" #include "ardour/automation_control.h"
@ -44,8 +45,6 @@ AutomationController::AutomationController(boost::shared_ptr<AutomationControl>
set_style (BarController::LeftToRight); set_style (BarController::LeftToRight);
set_use_parent (true); set_use_parent (true);
label_callback = sigc::mem_fun(this, &AutomationController::update_label);
StartGesture.connect (mem_fun(*this, &AutomationController::start_touch)); StartGesture.connect (mem_fun(*this, &AutomationController::start_touch));
StopGesture.connect (mem_fun(*this, &AutomationController::end_touch)); StopGesture.connect (mem_fun(*this, &AutomationController::end_touch));
@ -78,16 +77,19 @@ AutomationController::create(
return boost::shared_ptr<AutomationController>(new AutomationController(ac, adjustment)); return boost::shared_ptr<AutomationController>(new AutomationController(ac, adjustment));
} }
void std::string
AutomationController::update_label(char* label, int label_len) AutomationController::get_label (int&)
{ {
if (label && label_len) { std::stringstream s;
// Hack to display CC rounded to int // Hack to display CC rounded to int
if (_controllable->parameter().type() == MidiCCAutomation) if (_controllable->parameter().type() == MidiCCAutomation) {
snprintf(label, label_len, "%d", (int)_controllable->get_value()); s << (int)_controllable->get_value();
else } else {
snprintf(label, label_len, "%.3f", _controllable->get_value()); s << std::fixed << std::setprecision(3) << _controllable->get_value();
} }
return s.str ();
} }
void void

View file

@ -46,12 +46,13 @@ public:
Gtk::Adjustment* adjustment() { return _adjustment; } Gtk::Adjustment* adjustment() { return _adjustment; }
void update_label(char* label, int label_len);
void display_effective_value(); void display_effective_value();
void value_adjusted(); void value_adjusted();
private: private:
AutomationController (boost::shared_ptr<ARDOUR::AutomationControl> ac, Gtk::Adjustment* adj); AutomationController (boost::shared_ptr<ARDOUR::AutomationControl> ac, Gtk::Adjustment* adj);
std::string get_label (int&);
void start_touch(); void start_touch();
void end_touch(); void end_touch();

View file

@ -1,6 +1,7 @@
#define __STDC_FORMAT_MACROS 1 #define __STDC_FORMAT_MACROS 1
#include <inttypes.h> #include <inttypes.h>
#include <iomanip>
#include "ardour/latent.h" #include "ardour/latent.h"
#include <gtkmm2ext/utils.h> #include <gtkmm2ext/utils.h>
@ -24,16 +25,19 @@ static const gchar *_unit_strings[] = {
std::vector<std::string> LatencyGUI::unit_strings; std::vector<std::string> LatencyGUI::unit_strings;
void std::string
LatencyGUI::latency_printer (char *buf, unsigned int bufsize) LatencyGUI::get_label (int&)
{ {
double nframes = adjustment.get_value(); double const nframes = adjustment.get_value();
std::stringstream s;
if (nframes < (sample_rate / 1000.0)) { if (nframes < (sample_rate / 1000.0)) {
snprintf (buf, bufsize, "%" PRId64 " samples", (nframes64_t) rint (nframes)); s << ((nframes64_t) rint (nframes)) << " samples";
} else { } else {
snprintf (buf, bufsize, "%.2g msecs" , nframes / (sample_rate / 1000.0)); s << std::fixed << std::setprecision (2) << (nframes / (sample_rate / 1000.0)) << " msecs";
} }
return s.str ();
} }
LatencyGUI::LatencyGUI (Latent& l, nframes64_t sr, nframes64_t psz) LatencyGUI::LatencyGUI (Latent& l, nframes64_t sr, nframes64_t psz)
@ -44,7 +48,7 @@ LatencyGUI::LatencyGUI (Latent& l, nframes64_t sr, nframes64_t psz)
ignored (new PBD::IgnorableControllable()), ignored (new PBD::IgnorableControllable()),
/* max 1 second, step by frames, page by msecs */ /* max 1 second, step by frames, page by msecs */
adjustment (initial_value, 0.0, sample_rate, 1.0, sample_rate / 1000.0f), adjustment (initial_value, 0.0, sample_rate, 1.0, sample_rate / 1000.0f),
bc (adjustment, ignored, sigc::mem_fun (*this, &LatencyGUI::latency_printer)), bc (adjustment, ignored),
reset_button (_("Reset")) reset_button (_("Reset"))
{ {
Widget* w; Widget* w;

View file

@ -31,6 +31,8 @@ class LatencyGUI : public Gtk::VBox
void refresh (); void refresh ();
private: private:
std::string get_label (int&);
ARDOUR::Latent& _latent; ARDOUR::Latent& _latent;
nframes64_t initial_value; nframes64_t initial_value;
nframes64_t sample_rate; nframes64_t sample_rate;
@ -48,7 +50,6 @@ class LatencyGUI : public Gtk::VBox
Gtk::ComboBoxText units_combo; Gtk::ComboBoxText units_combo;
void change_latency_from_button (int dir); void change_latency_from_button (int dir);
void latency_printer (char* buf, unsigned int bufsize);
static std::vector<std::string> unit_strings; static std::vector<std::string> unit_strings;
}; };

View file

@ -18,24 +18,19 @@
*/ */
#include <iostream> #include <iostream>
#include <iomanip>
#include <cstring>
#include "ardour/panner.h"
#include "panner.h" #include "panner.h"
#include "i18n.h"
using namespace std; using namespace std;
using namespace Gtk;
static const int triangle_size = 5; static const int triangle_size = 5;
static void PannerBar::PannerBar (Adjustment& adj, boost::shared_ptr<PBD::Controllable> c)
null_label_callback (char* buf, unsigned int bufsize) : BarController (adj, c)
{
/* no label */
buf[0] = '\0';
}
PannerBar::PannerBar (Gtk::Adjustment& adj, boost::shared_ptr<PBD::Controllable> c)
: BarController (adj, c, sigc::ptr_fun (null_label_callback))
{ {
set_style (BarController::Line); set_style (BarController::Line);
} }
@ -118,6 +113,112 @@ PannerBar::button_press (GdkEventButton* ev)
bool bool
PannerBar::button_release (GdkEventButton* ev) PannerBar::button_release (GdkEventButton* ev)
{ {
return BarController::button_release (ev); bool const r = BarController::button_release (ev);
/* get rid of any `C' labels that may exist */
queue_draw ();
return r;
} }
bool
PannerBar::entry_input (double *new_value)
{
Entry* e = dynamic_cast<Entry*> (&spinner);
string const text = e->get_text ();
string digits;
string letters;
string const L = _("L");
string const C = _("C");
string const R = _("R");
for (string::size_type i = 0; i < text.length(); ++i) {
if (isdigit (text[i])) {
digits += text[i];
} else if (text[i] != '%') {
letters += text[i];
}
}
if (letters.empty()) {
/* no letter specified, so take any number as a percentage where
* 0 is left and 100 right */
*new_value = digits.empty() ? 0.5 : (atoi (digits.c_str()) / 100.0);
} else {
/* letter given, so value is a percentage to the extreme
* (e.g. 100L is full left, 1L is slightly left */
if (letters[0] == L[0] || letters[0] == tolower (L[0])) {
*new_value = digits.empty() ? 0 : (0.5 - atoi (digits.c_str()) / 200.0);
} else if (letters[0] == R[0] || letters[0] == tolower (R[0])) {
*new_value = digits.empty() ? 1 : 0.5 + atoi (digits.c_str()) / 200.0;
} else if (letters[0] == C[0] || letters[0] == tolower (C[0])) {
*new_value = 0.5;
}
}
return true;
}
bool
PannerBar::entry_output ()
{
Entry* e = dynamic_cast<Entry*> (&spinner);
e->set_text (value_as_string (spinner.get_adjustment()->get_value()));
return true;
}
string
PannerBar::value_as_string (double v) const
{
if (ARDOUR::Panner::equivalent (v, 0.5)) {
return _("C");
} else if (ARDOUR::Panner::equivalent (v, 0)) {
return _("L");
} else if (ARDOUR::Panner::equivalent (v, 1)) {
return _("R");
} else if (v < 0.5) {
std::stringstream s;
s << fixed << setprecision (0) << _("L") << ((0.5 - v) * 200) << "%";
return s.str();
} else if (v > 0.5) {
std::stringstream s;
s << fixed << setprecision (0) << _("R") << ((v -0.5) * 200) << "%";
return s.str ();
}
return "";
}
std::string
PannerBar::get_label (int& x)
{
double const value = spinner.get_adjustment()->get_value ();
if (ARDOUR::Panner::equivalent (value, 0.5)) {
/* centre: only display text during a drag */
if (!grabbed) {
return "";
}
} else {
/* non-centre: display text on the side of the panner which has more space */
Glib::RefPtr<Pango::Context> p = get_pango_context ();
Glib::RefPtr<Pango::Layout> l = Pango::Layout::create (p);
l->set_text (value_as_string (value));
Pango::Rectangle const ext = l->get_ink_extents ();
if (value < 0.5) {
x = (darea.get_width() - 4 - ext.get_width() / Pango::SCALE);
} else {
x = 4;
}
}
return value_as_string (value);
}

View file

@ -33,6 +33,12 @@ class PannerBar : public Gtkmm2ext::BarController
bool expose (GdkEventExpose*); bool expose (GdkEventExpose*);
bool button_press (GdkEventButton*); bool button_press (GdkEventButton*);
bool button_release (GdkEventButton*); bool button_release (GdkEventButton*);
bool entry_input (double *);
bool entry_output ();
private:
std::string get_label (int&);
std::string value_as_string (double v) const;
}; };
#endif /* __gtk_ardour_panner_h__ */ #endif /* __gtk_ardour_panner_h__ */

View file

@ -393,7 +393,7 @@ PannerUI::setup_pan ()
x = rx; x = rx;
} }
pan_adjustments.push_back (new Adjustment (x, 0, 1.0, 0.05, 0.1)); pan_adjustments.push_back (new Adjustment (x, 0, 1.0, 0.005, 0.05));
bc = new PannerBar (*pan_adjustments[asz], bc = new PannerBar (*pan_adjustments[asz],
boost::static_pointer_cast<PBD::Controllable>( _io->panner()->pan_control( asz )) ); boost::static_pointer_cast<PBD::Controllable>( _io->panner()->pan_control( asz )) );
@ -696,23 +696,6 @@ PannerUI::update_pan_bars (bool only_if_aplay)
in_pan_update = false; in_pan_update = false;
} }
void
PannerUI::pan_printer (char *buf, uint32_t len, Adjustment* adj)
{
float val = adj->get_value();
if (val == 0.0f) {
snprintf (buf, len, X_("L"));
} else if (val == 1.0f) {
snprintf (buf, len, X_("R"));
} else if (Panner::equivalent (val, 0.5f)) {
snprintf (buf, len, X_("C"));
} else {
/* don't print anything */
buf[0] = '\0';
}
}
void void
PannerUI::update_pan_sensitive () PannerUI::update_pan_sensitive ()
{ {

View file

@ -119,7 +119,6 @@ class PannerUI : public Gtk::HBox
void pan_adjustment_changed (uint32_t which); void pan_adjustment_changed (uint32_t which);
void pan_value_changed (uint32_t which); void pan_value_changed (uint32_t which);
void pan_printer (char* buf, uint32_t, Gtk::Adjustment*);
void update_pan_bars (bool only_if_aplay); void update_pan_bars (bool only_if_aplay);
void update_pan_linkage (); void update_pan_linkage ();
void update_pan_state (); void update_pan_state ();

View file

@ -36,12 +36,10 @@ using namespace Gtk;
using namespace Gtkmm2ext; using namespace Gtkmm2ext;
BarController::BarController (Gtk::Adjustment& adj, BarController::BarController (Gtk::Adjustment& adj,
boost::shared_ptr<PBD::Controllable> mc, boost::shared_ptr<PBD::Controllable> mc)
sigc::slot<void,char*,unsigned int> lc)
: adjustment (adj), : adjustment (adj),
binding_proxy (mc), binding_proxy (mc),
label_callback (lc),
spinner (adjustment) spinner (adjustment)
{ {
@ -49,7 +47,6 @@ BarController::BarController (Gtk::Adjustment& adj,
grabbed = false; grabbed = false;
switching = false; switching = false;
switch_on_release = false; switch_on_release = false;
with_text = true;
use_parent = false; use_parent = false;
layout = darea.create_pango_layout(""); layout = darea.create_pango_layout("");
@ -76,6 +73,8 @@ BarController::BarController (Gtk::Adjustment& adj,
spinner.signal_activate().connect (mem_fun (*this, &BarController::entry_activated)); spinner.signal_activate().connect (mem_fun (*this, &BarController::entry_activated));
spinner.signal_focus_out_event().connect (mem_fun (*this, &BarController::entry_focus_out)); spinner.signal_focus_out_event().connect (mem_fun (*this, &BarController::entry_focus_out));
spinner.signal_input().connect (mem_fun (*this, &BarController::entry_input));
spinner.signal_output().connect (mem_fun (*this, &BarController::entry_output));
spinner.set_digits (3); spinner.set_digits (3);
add (darea); add (darea);
@ -343,46 +342,32 @@ BarController::expose (GdkEventExpose* event)
break; break;
} }
if (with_text) {
/* draw label */ /* draw label */
char buf[64]; int xpos = -1;
buf[0] = '\0'; std::string const label = get_label (xpos);
if (label_callback) if (!label.empty()) {
label_callback (buf, 64);
if (buf[0] != '\0') { layout->set_text (label);
layout->set_text (buf);
int width, height; int width, height;
layout->get_pixel_size (width, height); layout->get_pixel_size (width, height);
int xpos; if (xpos == -1) {
xpos = max (3, 1 + (x2 - (width/2))); xpos = max (3, 1 + (x2 - (width/2)));
xpos = min (darea.get_width() - width - 3, xpos); xpos = min (darea.get_width() - width - 3, xpos);
}
win->draw_layout (get_style()->get_text_gc (get_state()), win->draw_layout (get_style()->get_text_gc (get_state()),
xpos, xpos,
(darea.get_height()/2) - (height/2), (darea.get_height()/2) - (height/2),
layout); layout);
} }
}
return true; return true;
} }
void
BarController::set_with_text (bool yn)
{
if (with_text != yn) {
with_text = yn;
queue_draw ();
}
}
void void
BarController::set_style (Style s) BarController::set_style (Style s)
{ {
@ -467,3 +452,17 @@ BarController::set_sensitive (bool yn)
Frame::set_sensitive (yn); Frame::set_sensitive (yn);
darea.set_sensitive (yn); darea.set_sensitive (yn);
} }
bool
BarController::entry_input (double* v)
{
return false;
}
bool
BarController::entry_output ()
{
return false;
}

View file

@ -32,9 +32,7 @@ namespace Gtkmm2ext {
class BarController : public Gtk::Frame class BarController : public Gtk::Frame
{ {
public: public:
typedef sigc::slot<void,char*,unsigned int> LabelCallback; BarController (Gtk::Adjustment& adj, boost::shared_ptr<PBD::Controllable>);
BarController (Gtk::Adjustment& adj, boost::shared_ptr<PBD::Controllable>, LabelCallback lc = LabelCallback());
virtual ~BarController () {} virtual ~BarController () {}
@ -50,13 +48,10 @@ class BarController : public Gtk::Frame
Style style() const { return _style; } Style style() const { return _style; }
void set_style (Style); void set_style (Style);
void set_with_text (bool yn);
void set_use_parent (bool yn); void set_use_parent (bool yn);
void set_sensitive (bool yn); void set_sensitive (bool yn);
Gtk::SpinButton& get_spin_button() { return spinner; }
sigc::signal<void> StartGesture; sigc::signal<void> StartGesture;
sigc::signal<void> StopGesture; sigc::signal<void> StopGesture;
@ -71,25 +66,29 @@ class BarController : public Gtk::Frame
Gtk::Adjustment& adjustment; Gtk::Adjustment& adjustment;
BindingProxy binding_proxy; BindingProxy binding_proxy;
Gtk::DrawingArea darea; Gtk::DrawingArea darea;
LabelCallback label_callback;
Glib::RefPtr<Pango::Layout> layout; Glib::RefPtr<Pango::Layout> layout;
Style _style; Style _style;
bool grabbed; bool grabbed;
bool switching; bool switching;
bool switch_on_release; bool switch_on_release;
bool with_text;
double initial_value; double initial_value;
double grab_x; double grab_x;
GdkWindow* grab_window; GdkWindow* grab_window;
Gtk::SpinButton spinner; Gtk::SpinButton spinner;
bool use_parent; bool use_parent;
virtual std::string get_label (int& x) {
return "";
}
virtual bool button_press (GdkEventButton *); virtual bool button_press (GdkEventButton *);
virtual bool button_release (GdkEventButton *); virtual bool button_release (GdkEventButton *);
virtual bool motion (GdkEventMotion *); virtual bool motion (GdkEventMotion *);
virtual bool expose (GdkEventExpose *); virtual bool expose (GdkEventExpose *);
virtual bool scroll (GdkEventScroll *); virtual bool scroll (GdkEventScroll *);
virtual bool entry_focus_out (GdkEventFocus*); virtual bool entry_focus_out (GdkEventFocus*);
virtual bool entry_input (double *);
virtual bool entry_output ();
gint mouse_control (double x, GdkWindow* w, double scaling); gint mouse_control (double x, GdkWindow* w, double scaling);