mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-17 12:16:30 +01:00
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:
parent
dbe20bd3a9
commit
64524c0ba4
10 changed files with 191 additions and 96 deletions
|
|
@ -18,6 +18,7 @@
|
|||
|
||||
*/
|
||||
|
||||
#include <iomanip>
|
||||
#include "pbd/error.h"
|
||||
#include "ardour/automation_list.h"
|
||||
#include "ardour/automation_control.h"
|
||||
|
|
@ -35,7 +36,7 @@ using namespace Gtk;
|
|||
|
||||
|
||||
AutomationController::AutomationController(boost::shared_ptr<AutomationControl> ac, Adjustment* adj)
|
||||
: BarController(*adj, ac)
|
||||
: BarController (*adj, ac)
|
||||
, _ignore_change(false)
|
||||
, _controllable(ac)
|
||||
, _adjustment(adj)
|
||||
|
|
@ -44,8 +45,6 @@ AutomationController::AutomationController(boost::shared_ptr<AutomationControl>
|
|||
set_style (BarController::LeftToRight);
|
||||
set_use_parent (true);
|
||||
|
||||
label_callback = sigc::mem_fun(this, &AutomationController::update_label);
|
||||
|
||||
StartGesture.connect (mem_fun(*this, &AutomationController::start_touch));
|
||||
StopGesture.connect (mem_fun(*this, &AutomationController::end_touch));
|
||||
|
||||
|
|
@ -78,16 +77,19 @@ AutomationController::create(
|
|||
return boost::shared_ptr<AutomationController>(new AutomationController(ac, adjustment));
|
||||
}
|
||||
|
||||
void
|
||||
AutomationController::update_label(char* label, int label_len)
|
||||
std::string
|
||||
AutomationController::get_label (int&)
|
||||
{
|
||||
if (label && label_len) {
|
||||
// Hack to display CC rounded to int
|
||||
if (_controllable->parameter().type() == MidiCCAutomation)
|
||||
snprintf(label, label_len, "%d", (int)_controllable->get_value());
|
||||
else
|
||||
snprintf(label, label_len, "%.3f", _controllable->get_value());
|
||||
std::stringstream s;
|
||||
|
||||
// Hack to display CC rounded to int
|
||||
if (_controllable->parameter().type() == MidiCCAutomation) {
|
||||
s << (int)_controllable->get_value();
|
||||
} else {
|
||||
s << std::fixed << std::setprecision(3) << _controllable->get_value();
|
||||
}
|
||||
|
||||
return s.str ();
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -46,12 +46,13 @@ public:
|
|||
|
||||
Gtk::Adjustment* adjustment() { return _adjustment; }
|
||||
|
||||
void update_label(char* label, int label_len);
|
||||
void display_effective_value();
|
||||
void value_adjusted();
|
||||
|
||||
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 end_touch();
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
#define __STDC_FORMAT_MACROS 1
|
||||
#include <inttypes.h>
|
||||
|
||||
#include <iomanip>
|
||||
#include "ardour/latent.h"
|
||||
#include <gtkmm2ext/utils.h>
|
||||
|
||||
|
|
@ -24,16 +25,19 @@ static const gchar *_unit_strings[] = {
|
|||
|
||||
std::vector<std::string> LatencyGUI::unit_strings;
|
||||
|
||||
void
|
||||
LatencyGUI::latency_printer (char *buf, unsigned int bufsize)
|
||||
std::string
|
||||
LatencyGUI::get_label (int&)
|
||||
{
|
||||
double nframes = adjustment.get_value();
|
||||
double const nframes = adjustment.get_value();
|
||||
std::stringstream s;
|
||||
|
||||
if (nframes < (sample_rate / 1000.0)) {
|
||||
snprintf (buf, bufsize, "%" PRId64 " samples", (nframes64_t) rint (nframes));
|
||||
s << ((nframes64_t) rint (nframes)) << " samples";
|
||||
} 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)
|
||||
|
|
@ -44,7 +48,7 @@ LatencyGUI::LatencyGUI (Latent& l, nframes64_t sr, nframes64_t psz)
|
|||
ignored (new PBD::IgnorableControllable()),
|
||||
/* max 1 second, step by frames, page by msecs */
|
||||
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"))
|
||||
{
|
||||
Widget* w;
|
||||
|
|
|
|||
|
|
@ -31,6 +31,8 @@ class LatencyGUI : public Gtk::VBox
|
|||
void refresh ();
|
||||
|
||||
private:
|
||||
std::string get_label (int&);
|
||||
|
||||
ARDOUR::Latent& _latent;
|
||||
nframes64_t initial_value;
|
||||
nframes64_t sample_rate;
|
||||
|
|
@ -48,7 +50,6 @@ class LatencyGUI : public Gtk::VBox
|
|||
Gtk::ComboBoxText units_combo;
|
||||
|
||||
void change_latency_from_button (int dir);
|
||||
void latency_printer (char* buf, unsigned int bufsize);
|
||||
|
||||
static std::vector<std::string> unit_strings;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -18,24 +18,19 @@
|
|||
*/
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include <iomanip>
|
||||
#include <cstring>
|
||||
#include "ardour/panner.h"
|
||||
#include "panner.h"
|
||||
#include "i18n.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace Gtk;
|
||||
|
||||
static const int triangle_size = 5;
|
||||
|
||||
static void
|
||||
null_label_callback (char* buf, unsigned int bufsize)
|
||||
{
|
||||
/* 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))
|
||||
PannerBar::PannerBar (Adjustment& adj, boost::shared_ptr<PBD::Controllable> c)
|
||||
: BarController (adj, c)
|
||||
{
|
||||
set_style (BarController::Line);
|
||||
}
|
||||
|
|
@ -118,6 +113,112 @@ PannerBar::button_press (GdkEventButton* ev)
|
|||
bool
|
||||
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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,6 +33,12 @@ class PannerBar : public Gtkmm2ext::BarController
|
|||
bool expose (GdkEventExpose*);
|
||||
bool button_press (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__ */
|
||||
|
|
|
|||
|
|
@ -393,7 +393,7 @@ PannerUI::setup_pan ()
|
|||
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],
|
||||
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;
|
||||
}
|
||||
|
||||
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
|
||||
PannerUI::update_pan_sensitive ()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -119,7 +119,6 @@ class PannerUI : public Gtk::HBox
|
|||
|
||||
void pan_adjustment_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_linkage ();
|
||||
void update_pan_state ();
|
||||
|
|
|
|||
|
|
@ -36,12 +36,10 @@ using namespace Gtk;
|
|||
using namespace Gtkmm2ext;
|
||||
|
||||
BarController::BarController (Gtk::Adjustment& adj,
|
||||
boost::shared_ptr<PBD::Controllable> mc,
|
||||
sigc::slot<void,char*,unsigned int> lc)
|
||||
boost::shared_ptr<PBD::Controllable> mc)
|
||||
|
||||
: adjustment (adj),
|
||||
binding_proxy (mc),
|
||||
label_callback (lc),
|
||||
spinner (adjustment)
|
||||
|
||||
{
|
||||
|
|
@ -49,7 +47,6 @@ BarController::BarController (Gtk::Adjustment& adj,
|
|||
grabbed = false;
|
||||
switching = false;
|
||||
switch_on_release = false;
|
||||
with_text = true;
|
||||
use_parent = false;
|
||||
|
||||
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_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);
|
||||
|
||||
add (darea);
|
||||
|
|
@ -343,46 +342,32 @@ BarController::expose (GdkEventExpose* event)
|
|||
break;
|
||||
}
|
||||
|
||||
if (with_text) {
|
||||
/* draw label */
|
||||
/* draw label */
|
||||
|
||||
char buf[64];
|
||||
buf[0] = '\0';
|
||||
int xpos = -1;
|
||||
std::string const label = get_label (xpos);
|
||||
|
||||
if (label_callback)
|
||||
label_callback (buf, 64);
|
||||
if (!label.empty()) {
|
||||
|
||||
if (buf[0] != '\0') {
|
||||
layout->set_text (label);
|
||||
|
||||
layout->set_text (buf);
|
||||
|
||||
int width, height;
|
||||
layout->get_pixel_size (width, height);
|
||||
|
||||
int xpos;
|
||||
int width, height;
|
||||
layout->get_pixel_size (width, height);
|
||||
|
||||
if (xpos == -1) {
|
||||
xpos = max (3, 1 + (x2 - (width/2)));
|
||||
xpos = min (darea.get_width() - width - 3, xpos);
|
||||
|
||||
win->draw_layout (get_style()->get_text_gc (get_state()),
|
||||
xpos,
|
||||
(darea.get_height()/2) - (height/2),
|
||||
layout);
|
||||
}
|
||||
|
||||
win->draw_layout (get_style()->get_text_gc (get_state()),
|
||||
xpos,
|
||||
(darea.get_height()/2) - (height/2),
|
||||
layout);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
BarController::set_with_text (bool yn)
|
||||
{
|
||||
if (with_text != yn) {
|
||||
with_text = yn;
|
||||
queue_draw ();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
BarController::set_style (Style s)
|
||||
{
|
||||
|
|
@ -467,3 +452,17 @@ BarController::set_sensitive (bool yn)
|
|||
Frame::set_sensitive (yn);
|
||||
darea.set_sensitive (yn);
|
||||
}
|
||||
|
||||
bool
|
||||
BarController::entry_input (double* v)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
BarController::entry_output ()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -32,9 +32,7 @@ namespace Gtkmm2ext {
|
|||
class BarController : public Gtk::Frame
|
||||
{
|
||||
public:
|
||||
typedef sigc::slot<void,char*,unsigned int> LabelCallback;
|
||||
|
||||
BarController (Gtk::Adjustment& adj, boost::shared_ptr<PBD::Controllable>, LabelCallback lc = LabelCallback());
|
||||
BarController (Gtk::Adjustment& adj, boost::shared_ptr<PBD::Controllable>);
|
||||
|
||||
virtual ~BarController () {}
|
||||
|
||||
|
|
@ -50,13 +48,10 @@ class BarController : public Gtk::Frame
|
|||
|
||||
Style style() const { return _style; }
|
||||
void set_style (Style);
|
||||
void set_with_text (bool yn);
|
||||
void set_use_parent (bool yn);
|
||||
|
||||
void set_sensitive (bool yn);
|
||||
|
||||
Gtk::SpinButton& get_spin_button() { return spinner; }
|
||||
|
||||
sigc::signal<void> StartGesture;
|
||||
sigc::signal<void> StopGesture;
|
||||
|
||||
|
|
@ -71,25 +66,29 @@ class BarController : public Gtk::Frame
|
|||
Gtk::Adjustment& adjustment;
|
||||
BindingProxy binding_proxy;
|
||||
Gtk::DrawingArea darea;
|
||||
LabelCallback label_callback;
|
||||
Glib::RefPtr<Pango::Layout> layout;
|
||||
Style _style;
|
||||
bool grabbed;
|
||||
bool switching;
|
||||
bool switch_on_release;
|
||||
bool with_text;
|
||||
double initial_value;
|
||||
double grab_x;
|
||||
GdkWindow* grab_window;
|
||||
Gtk::SpinButton spinner;
|
||||
bool use_parent;
|
||||
|
||||
virtual std::string get_label (int& x) {
|
||||
return "";
|
||||
}
|
||||
|
||||
virtual bool button_press (GdkEventButton *);
|
||||
virtual bool button_release (GdkEventButton *);
|
||||
virtual bool motion (GdkEventMotion *);
|
||||
virtual bool expose (GdkEventExpose *);
|
||||
virtual bool scroll (GdkEventScroll *);
|
||||
virtual bool entry_focus_out (GdkEventFocus*);
|
||||
virtual bool entry_input (double *);
|
||||
virtual bool entry_output ();
|
||||
|
||||
gint mouse_control (double x, GdkWindow* w, double scaling);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue