View Issue Details

IDProjectCategoryView StatusLast Update
0002675ardourbugspublic2010-04-24 10:33
Reporteroofus Assigned Tocth103  
PrioritynormalSeveritytweakReproducibilityalways
Status closedResolutionfixed 
PlatformDell D830 core2duo T9300 2.5GHzOSMandrivaOS Version2009.0
Product VersionSVN/2.0-ongoing 
Summary0002675: Pan readouts should be in percentage left or right.
DescriptionPan readouts should be in percentage. Either 50|50 when in the center and then 100|0 for full left and 0|100 for full right. Or, C when centred and then a single percentage to indicate the amount left or right. ie 37% L or 59% R. with 100% indicating full left or right. This could be shown in a tool tip when panning. double clicking and entering a value is of little use I think.

The current 0.xxx readout is meaningless and unreadable.
TagsNo tags attached.

Activities

thorgal

2009-05-18 13:00

reporter   ~0006012

I believe I mentioned a similar thing about a year ago (?) Can not find it again.
You want something like the hdspmixer shows for the HDSP card channels. I fully agree :)

2009-05-19 23:25

 

panner-percentage.patch (5,863 bytes)   
diff --git a/gtk2_ardour/panner.cc b/gtk2_ardour/panner.cc
index 975f1e6..e1ce802 100644
--- a/gtk2_ardour/panner.cc
+++ b/gtk2_ardour/panner.cc
@@ -19,9 +19,12 @@
 
 #include <iostream>
 
+#include "ardour/panner.h"
 #include "panner.h"
+#include "i18n.h"
 
 using namespace std;
+using namespace Gtk;
 
 static const int triangle_size = 5;
 
@@ -34,7 +37,7 @@ null_label_callback (char* buf, unsigned int bufsize)
 }
 
 
-PannerBar::PannerBar (Gtk::Adjustment& adj, boost::shared_ptr<PBD::Controllable> c)
+PannerBar::PannerBar (Adjustment& adj, boost::shared_ptr<PBD::Controllable> c)
 	: BarController (adj, c, sigc::ptr_fun (null_label_callback))
 {
 	set_style (BarController::Line);
@@ -121,3 +124,66 @@ PannerBar::button_release (GdkEventButton* ev)
 	return BarController::button_release (ev);
 }
 
+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);
+	double const v = spinner.get_adjustment()->get_value();
+	if (ARDOUR::Panner::equivalent (v, 0.5)) {
+		e->set_text (_("C"));
+	} else if (ARDOUR::Panner::equivalent (v, 0)) {
+		e->set_text (_("L"));
+	} else if (ARDOUR::Panner::equivalent (v, 1)) {
+		e->set_text (_("R"));
+	} else if (v < 0.5) {
+		std::stringstream s;
+		s << _("L") << ((0.5 - v) * 200) << "%";
+		e->set_text (s.str ());
+	} else if (v > 0.5) {
+		std::stringstream s;
+		s << _("R") << ((v -0.5) * 200) << "%";
+		e->set_text (s.str ());
+	}
+
+	return true;
+}
diff --git a/gtk2_ardour/panner.h b/gtk2_ardour/panner.h
index 21f984a..2103966 100644
--- a/gtk2_ardour/panner.h
+++ b/gtk2_ardour/panner.h
@@ -33,6 +33,8 @@ class PannerBar : public Gtkmm2ext::BarController
 	bool expose (GdkEventExpose*);
 	bool button_press (GdkEventButton*);
 	bool button_release (GdkEventButton*);
+	bool entry_input (double *);
+	bool entry_output ();
 };
 
 #endif /* __gtk_ardour_panner_h__ */
diff --git a/gtk2_ardour/panner_ui.cc b/gtk2_ardour/panner_ui.cc
index 3ffec0a..208ff6e 100644
--- a/gtk2_ardour/panner_ui.cc
+++ b/gtk2_ardour/panner_ui.cc
@@ -697,23 +697,6 @@ PannerUI::update_pan_bars (bool only_if_aplay)
 }
 
 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 () 
 {
 	bool sensitive = !(_io->panner()->automation_state() & Play);
diff --git a/gtk2_ardour/panner_ui.h b/gtk2_ardour/panner_ui.h
index fa0b7ce..602164d 100644
--- a/gtk2_ardour/panner_ui.h
+++ b/gtk2_ardour/panner_ui.h
@@ -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 ();
diff --git a/libs/gtkmm2ext/barcontroller.cc b/libs/gtkmm2ext/barcontroller.cc
index 90954e5..53414d8 100644
--- a/libs/gtkmm2ext/barcontroller.cc
+++ b/libs/gtkmm2ext/barcontroller.cc
@@ -76,6 +76,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);
@@ -467,3 +469,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;
+}
+
+	
diff --git a/libs/gtkmm2ext/gtkmm2ext/barcontroller.h b/libs/gtkmm2ext/gtkmm2ext/barcontroller.h
index 2c0ca94..a01007f 100644
--- a/libs/gtkmm2ext/gtkmm2ext/barcontroller.h
+++ b/libs/gtkmm2ext/gtkmm2ext/barcontroller.h
@@ -55,8 +55,6 @@ class BarController : public Gtk::Frame
 
 	void set_sensitive (bool yn);
 
-	Gtk::SpinButton& get_spin_button() { return spinner; }
-
 	sigc::signal<void> StartGesture;
 	sigc::signal<void> StopGesture;
 
@@ -90,6 +88,8 @@ class BarController : public Gtk::Frame
 	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);
 
panner-percentage.patch (5,863 bytes)   

cth103

2009-05-19 23:28

administrator   ~0006015

The attached patch implements percentages in the double-click entry. Any thoughts? I suppose you could put the percentage figure actually within the pan control... hmm...

2009-05-20 00:16

 

panner-percentage.2.patch (6,801 bytes)   
diff --git a/gtk2_ardour/panner.cc b/gtk2_ardour/panner.cc
index 975f1e6..022c78e 100644
--- a/gtk2_ardour/panner.cc
+++ b/gtk2_ardour/panner.cc
@@ -18,10 +18,14 @@
 */
 
 #include <iostream>
+#include <iomanip>
 
+#include "ardour/panner.h"
 #include "panner.h"
+#include "i18n.h"
 
 using namespace std;
+using namespace Gtk;
 
 static const int triangle_size = 5;
 
@@ -34,7 +38,7 @@ null_label_callback (char* buf, unsigned int bufsize)
 }
 
 
-PannerBar::PannerBar (Gtk::Adjustment& adj, boost::shared_ptr<PBD::Controllable> c)
+PannerBar::PannerBar (Adjustment& adj, boost::shared_ptr<PBD::Controllable> c)
 	: BarController (adj, c, sigc::ptr_fun (null_label_callback))
 {
 	set_style (BarController::Line);
@@ -95,6 +99,27 @@ PannerBar::expose (GdkEventExpose* ev)
 
 	gdk_draw_polygon (win->gobj(), gc->gobj(), true, points, 3);
 
+	double const value = spinner.get_adjustment()->get_value ();
+	if (!ARDOUR::Panner::equivalent (value, 0.5)) {
+		
+		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 ();
+		
+		int x = 0;
+		if (value < 0.5) {
+			x = (darea.get_width() - 4 - ext.get_width() / Pango::SCALE);
+		} else {
+			x = 4;
+		}
+		
+		int const y = (darea.get_height() - ext.get_height() / Pango::SCALE) / 2;
+
+		win->draw_layout (gc, x, y, l);
+	}
+
 	return true;
 }
 
@@ -121,3 +146,72 @@ PannerBar::button_release (GdkEventButton* ev)
 	return BarController::button_release (ev);
 }
 
+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 "";
+}
diff --git a/gtk2_ardour/panner.h b/gtk2_ardour/panner.h
index 21f984a..2d1d351 100644
--- a/gtk2_ardour/panner.h
+++ b/gtk2_ardour/panner.h
@@ -33,6 +33,11 @@ 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 value_as_string (double v) const;
 };
 
 #endif /* __gtk_ardour_panner_h__ */
diff --git a/gtk2_ardour/panner_ui.cc b/gtk2_ardour/panner_ui.cc
index 3ffec0a..208ff6e 100644
--- a/gtk2_ardour/panner_ui.cc
+++ b/gtk2_ardour/panner_ui.cc
@@ -697,23 +697,6 @@ PannerUI::update_pan_bars (bool only_if_aplay)
 }
 
 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 () 
 {
 	bool sensitive = !(_io->panner()->automation_state() & Play);
diff --git a/gtk2_ardour/panner_ui.h b/gtk2_ardour/panner_ui.h
index fa0b7ce..602164d 100644
--- a/gtk2_ardour/panner_ui.h
+++ b/gtk2_ardour/panner_ui.h
@@ -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 ();
diff --git a/libs/gtkmm2ext/barcontroller.cc b/libs/gtkmm2ext/barcontroller.cc
index 90954e5..53414d8 100644
--- a/libs/gtkmm2ext/barcontroller.cc
+++ b/libs/gtkmm2ext/barcontroller.cc
@@ -76,6 +76,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);
@@ -467,3 +469,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;
+}
+
+	
diff --git a/libs/gtkmm2ext/gtkmm2ext/barcontroller.h b/libs/gtkmm2ext/gtkmm2ext/barcontroller.h
index 2c0ca94..a01007f 100644
--- a/libs/gtkmm2ext/gtkmm2ext/barcontroller.h
+++ b/libs/gtkmm2ext/gtkmm2ext/barcontroller.h
@@ -55,8 +55,6 @@ class BarController : public Gtk::Frame
 
 	void set_sensitive (bool yn);
 
-	Gtk::SpinButton& get_spin_button() { return spinner; }
-
 	sigc::signal<void> StartGesture;
 	sigc::signal<void> StopGesture;
 
@@ -90,6 +88,8 @@ class BarController : public Gtk::Frame
 	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);
 
panner-percentage.2.patch (6,801 bytes)   

cth103

2009-05-20 00:18

administrator   ~0006016

The second patch (to be applied instead of the first patch) fixes some problems with precision and writes the pan string into the pan control itself (except when the panner is at centre). Any thoughts welcome!

oofus

2009-05-20 11:53

developer   ~0006017

Tested the second patch and I think that it's really good. I like the use of the space, in as much as you write the percentage on the opposite side to the pan direction. Subtle, but great.

The only comment I might have is that the sensitivity is to low, I only seem to be able to drag the pan in 3% (and sometimes 6%) steps. This could of course be down to my mouse settings, but it would be nice if I could drag in single percent increments, especially as I don't seem to be able to accurately drag back to the centre, it keeps skipping over it. Also, maybe, whilst dragging show 'C' as you pass through the centre, but then cancel it when dragging stops. A 'C' under the panner permanently wouldn't look right.

thorgal

2009-05-20 12:01

reporter   ~0006018

I have not tried the patch yet but I feel a 1% increment as you drag is a good thing too. Now, would that be too much to add a "pan-dead-center-from-wherever-the-panner-is-located" mouse action, e.g. a single click with the middle button (or scroll-wheel button) ?

agorka

2009-05-20 14:41

reporter   ~0006019

Usually short-cut for 'reset to default position' is ctrl-click, hope to have it in Ardour also both for panners and faders. But for stereo panners it would be dead-left and dead-right. Were you talking about mono tracks?

oofus

2009-05-20 17:23

developer   ~0006020

You can set the panner to be full left, full right or centre by clicking the white triangles. I think this is quicker than a key combination. Also there is a right click menu option to reset.

cth103

2009-05-20 17:59

administrator   ~0006021

Shift click appears to reset panners at present. You can change the drag sensitivity by holding down Shift, Ctrl or both while dragging. Other changes have been committed to SVN.

oofus

2009-10-29 23:45

developer   ~0006977

implemented

Issue History

Date Modified Username Field Change
2009-05-15 16:33 oofus New Issue
2009-05-18 13:00 thorgal Note Added: 0006012
2009-05-19 23:25 cth103 File Added: panner-percentage.patch
2009-05-19 23:28 cth103 Note Added: 0006015
2009-05-19 23:28 cth103 Status new => feedback
2009-05-20 00:16 cth103 File Added: panner-percentage.2.patch
2009-05-20 00:18 cth103 Note Added: 0006016
2009-05-20 11:53 oofus Note Added: 0006017
2009-05-20 12:01 thorgal Note Added: 0006018
2009-05-20 14:41 agorka Note Added: 0006019
2009-05-20 17:23 oofus Note Added: 0006020
2009-05-20 17:59 cth103 cost => 0.00
2009-05-20 17:59 cth103 Note Added: 0006021
2009-05-20 17:59 cth103 Status feedback => resolved
2009-05-20 17:59 cth103 Fixed in Version => SVN 3.0
2009-05-20 17:59 cth103 Resolution open => fixed
2009-05-20 17:59 cth103 Assigned To => cth103
2009-10-29 23:45 oofus Status resolved => feedback
2009-10-29 23:45 oofus Resolution fixed => reopened
2009-10-29 23:45 oofus Note Added: 0006977
2009-10-29 23:45 oofus Status feedback => closed
2009-10-29 23:45 oofus Resolution reopened => fixed
2010-04-24 10:28 cth103 Category bugs => bugs2
2010-04-24 10:33 cth103 Category bugs2 => bugs