summaryrefslogtreecommitdiff
path: root/gtk2_ardour
diff options
context:
space:
mode:
authorPaul Davis <paul@linuxaudiosystems.com>2014-01-15 14:29:32 -0500
committerPaul Davis <paul@linuxaudiosystems.com>2014-01-15 14:29:32 -0500
commit9aacefc17010a889222425f97b99050171165038 (patch)
treea1a80ed3557caa2b223274fd33f54df35252ee5f /gtk2_ardour
parent96586e81f40e883a7807c88eaa7df73b60140352 (diff)
parent79b56b1d3319d03d14b2d3e2f8d6cd7b3e797deb (diff)
merge with master
Diffstat (limited to 'gtk2_ardour')
-rw-r--r--gtk2_ardour/audio_time_axis.cc28
-rw-r--r--gtk2_ardour/automation_line.cc11
-rw-r--r--gtk2_ardour/midi_time_axis.cc128
-rw-r--r--gtk2_ardour/midi_time_axis.h9
-rw-r--r--gtk2_ardour/panner2d.cc55
5 files changed, 198 insertions, 33 deletions
diff --git a/gtk2_ardour/audio_time_axis.cc b/gtk2_ardour/audio_time_axis.cc
index 8ca04c7bdb..1381271390 100644
--- a/gtk2_ardour/audio_time_axis.cc
+++ b/gtk2_ardour/audio_time_axis.cc
@@ -214,6 +214,16 @@ AudioTimeAxisView::create_automation_child (const Evoral::Parameter& param, bool
void
AudioTimeAxisView::ensure_pan_views (bool show)
{
+ bool changed = false;
+ for (list<boost::shared_ptr<AutomationTimeAxisView> >::iterator i = pan_tracks.begin(); i != pan_tracks.end(); ++i) {
+ changed = true;
+ (*i)->set_marked_for_display (false);
+ }
+ if (changed) {
+ _route->gui_changed (X_("visible_tracks"), (void *) 0); /* EMIT_SIGNAL */
+ }
+ pan_tracks.clear();
+
if (!_route->panner()) {
return;
}
@@ -250,6 +260,8 @@ AudioTimeAxisView::ensure_pan_views (bool show)
pan_tracks.push_back (t);
add_automation_child (*p, t, show);
+ } else {
+ pan_tracks.push_back (automation_child (pan_control->parameter ()));
}
}
}
@@ -391,14 +403,16 @@ AudioTimeAxisView::build_automation_action_menu (bool for_selection)
_main_automation_menu_map[Evoral::Parameter(GainAutomation)] = gain_automation_item;
- automation_items.push_back (CheckMenuElem (_("Pan"), sigc::mem_fun (*this, &AudioTimeAxisView::update_pan_track_visibility)));
- pan_automation_item = dynamic_cast<Gtk::CheckMenuItem*> (&automation_items.back ());
- pan_automation_item->set_active ((!for_selection || _editor.get_selection().tracks.size() == 1) &&
- (!pan_tracks.empty() && string_is_affirmative (pan_tracks.front()->gui_property ("visible"))));
+ if (!pan_tracks.empty()) {
+ automation_items.push_back (CheckMenuElem (_("Pan"), sigc::mem_fun (*this, &AudioTimeAxisView::update_pan_track_visibility)));
+ pan_automation_item = dynamic_cast<CheckMenuItem*> (&automation_items.back ());
+ pan_automation_item->set_active ((!for_selection || _editor.get_selection().tracks.size() == 1) &&
+ (!pan_tracks.empty() && string_is_affirmative (pan_tracks.front()->gui_property ("visible"))));
- set<Evoral::Parameter> const & params = _route->pannable()->what_can_be_automated ();
- for (set<Evoral::Parameter>::const_iterator p = params.begin(); p != params.end(); ++p) {
- _main_automation_menu_map[*p] = pan_automation_item;
+ set<Evoral::Parameter> const & params = _route->pannable()->what_can_be_automated ();
+ for (set<Evoral::Parameter>::iterator p = params.begin(); p != params.end(); ++p) {
+ _main_automation_menu_map[*p] = pan_automation_item;
+ }
}
}
diff --git a/gtk2_ardour/automation_line.cc b/gtk2_ardour/automation_line.cc
index a4d58cb531..8a11f199af 100644
--- a/gtk2_ardour/automation_line.cc
+++ b/gtk2_ardour/automation_line.cc
@@ -1153,9 +1153,10 @@ AutomationLine::view_to_model_coord_y (double& y) const
y = max (0.0, y);
y = min (2.0, y);
} else if (alist->parameter().type() == PanAzimuthAutomation ||
- alist->parameter().type() == PanElevationAutomation ||
- alist->parameter().type() == PanWidthAutomation) {
+ alist->parameter().type() == PanElevationAutomation) {
y = 1.0 - y;
+ } else if (alist->parameter().type() == PanWidthAutomation) {
+ y = 2.0 * y - 1.0;
} else if (alist->parameter().type() == PluginAutomation) {
y = y * (double)(alist->get_max_y()- alist->get_min_y()) + alist->get_min_y();
} else {
@@ -1171,10 +1172,10 @@ AutomationLine::model_to_view_coord (double& x, double& y) const
alist->parameter().type() == EnvelopeAutomation) {
y = gain_to_slider_position_with_max (y, Config->get_max_gain());
} else if (alist->parameter().type() == PanAzimuthAutomation ||
- alist->parameter().type() == PanElevationAutomation ||
- alist->parameter().type() == PanWidthAutomation) {
- // vertical coordinate axis reversal
+ alist->parameter().type() == PanElevationAutomation) {
y = 1.0 - y;
+ } else if (alist->parameter().type() == PanWidthAutomation) {
+ y = .5 + y * .5;
} else if (alist->parameter().type() == PluginAutomation) {
y = (y - alist->get_min_y()) / (double)(alist->get_max_y()- alist->get_min_y());
} else {
diff --git a/gtk2_ardour/midi_time_axis.cc b/gtk2_ardour/midi_time_axis.cc
index 4884dc34f3..e04f86aa95 100644
--- a/gtk2_ardour/midi_time_axis.cc
+++ b/gtk2_ardour/midi_time_axis.cc
@@ -46,6 +46,9 @@
#include "ardour/midi_source.h"
#include "ardour/midi_track.h"
#include "ardour/operations.h"
+#include "ardour/pannable.h"
+#include "ardour/panner.h"
+#include "ardour/panner_shell.h"
#include "ardour/playlist.h"
#include "ardour/region.h"
#include "ardour/region_factory.h"
@@ -162,7 +165,17 @@ MidiTimeAxisView::set_route (boost::shared_ptr<Route> rt)
controls_ebox.set_name ("MidiBusControlsBaseUnselected");
}
+ /* if set_state above didn't create a gain automation child, we need to make one */
+ if (automation_child (GainAutomation) == 0) {
+ create_automation_child (GainAutomation, false);
+ }
+
+ if (_route->panner_shell()) {
+ _route->panner_shell()->Changed.connect (*this, invalidator (*this), boost::bind (&MidiTimeAxisView::ensure_pan_views, this, false), gui_context());
+ }
+
/* map current state of the route */
+ ensure_pan_views (false);
processors_changed (RouteProcessorChange ());
@@ -580,6 +593,27 @@ MidiTimeAxisView::build_automation_action_menu (bool for_selection)
MenuElem (string_compose ("<i>%1</i>", _("No MIDI Channels selected"))));
dynamic_cast<Label*> (automation_items.back().get_child())->set_use_markup (true);
}
+
+ automation_items.push_back (SeparatorElem());
+ automation_items.push_back (CheckMenuElem (_("Fader"), sigc::mem_fun (*this, &MidiTimeAxisView::update_gain_track_visibility)));
+ gain_automation_item = dynamic_cast<CheckMenuItem*> (&automation_items.back ());
+ gain_automation_item->set_active ((!for_selection || _editor.get_selection().tracks.size() == 1) &&
+ (gain_track && string_is_affirmative (gain_track->gui_property ("visible"))));
+
+ _main_automation_menu_map[Evoral::Parameter(GainAutomation)] = gain_automation_item;
+
+ if (!pan_tracks.empty()) {
+ automation_items.push_back (CheckMenuElem (_("Pan"), sigc::mem_fun (*this, &MidiTimeAxisView::update_pan_track_visibility)));
+ pan_automation_item = dynamic_cast<CheckMenuItem*> (&automation_items.back ());
+ pan_automation_item->set_active ((!for_selection || _editor.get_selection().tracks.size() == 1) &&
+ (!pan_tracks.empty() && string_is_affirmative (pan_tracks.front()->gui_property ("visible"))));
+
+ set<Evoral::Parameter> const & params = _route->pannable()->what_can_be_automated ();
+ for (set<Evoral::Parameter>::iterator p = params.begin(); p != params.end(); ++p) {
+ _main_automation_menu_map[*p] = pan_automation_item;
+ }
+ }
+
}
void
@@ -1072,6 +1106,94 @@ MidiTimeAxisView::update_range()
}
void
+MidiTimeAxisView::ensure_pan_views (bool show)
+{
+ bool changed = false;
+ for (list<boost::shared_ptr<AutomationTimeAxisView> >::iterator i = pan_tracks.begin(); i != pan_tracks.end(); ++i) {
+ changed = true;
+ (*i)->set_marked_for_display (false);
+ }
+ if (changed) {
+ _route->gui_changed (X_("visible_tracks"), (void *) 0); /* EMIT_SIGNAL */
+ }
+ pan_tracks.clear();
+
+ if (!_route->panner()) {
+ return;
+ }
+
+ set<Evoral::Parameter> params = _route->panner()->what_can_be_automated();
+ set<Evoral::Parameter>::iterator p;
+
+ for (p = params.begin(); p != params.end(); ++p) {
+ boost::shared_ptr<ARDOUR::AutomationControl> pan_control = _route->pannable()->automation_control(*p);
+
+ if (pan_control->parameter().type() == NullAutomation) {
+ error << "Pan control has NULL automation type!" << endmsg;
+ continue;
+ }
+
+ if (automation_child (pan_control->parameter ()).get () == 0) {
+
+ /* we don't already have an AutomationTimeAxisView for this parameter */
+
+ std::string const name = _route->panner()->describe_parameter (pan_control->parameter ());
+
+ boost::shared_ptr<AutomationTimeAxisView> t (
+ new AutomationTimeAxisView (_session,
+ _route,
+ _route->pannable(),
+ pan_control,
+ pan_control->parameter (),
+ _editor,
+ *this,
+ false,
+ parent_canvas,
+ name)
+ );
+
+ pan_tracks.push_back (t);
+ add_automation_child (*p, t, show);
+ } else {
+ pan_tracks.push_back (automation_child (pan_control->parameter ()));
+ }
+ }
+}
+
+void
+MidiTimeAxisView::update_gain_track_visibility ()
+{
+ bool const showit = gain_automation_item->get_active();
+
+ if (showit != string_is_affirmative (gain_track->gui_property ("visible"))) {
+ gain_track->set_marked_for_display (showit);
+
+ /* now trigger a redisplay */
+
+ if (!no_redraw) {
+ _route->gui_changed (X_("visible_tracks"), (void *) 0); /* EMIT_SIGNAL */
+ }
+ }
+}
+
+void
+MidiTimeAxisView::update_pan_track_visibility ()
+{
+ bool const showit = pan_automation_item->get_active();
+ bool changed = false;
+
+ for (list<boost::shared_ptr<AutomationTimeAxisView> >::iterator i = pan_tracks.begin(); i != pan_tracks.end(); ++i) {
+ if ((*i)->set_marked_for_display (showit)) {
+ changed = true;
+ }
+ }
+
+ if (changed) {
+ _route->gui_changed (X_("visible_tracks"), (void *) 0); /* EMIT_SIGNAL */
+ }
+}
+
+void
MidiTimeAxisView::show_all_automation (bool apply_to_selection)
{
if (apply_to_selection) {
@@ -1177,6 +1299,12 @@ MidiTimeAxisView::create_automation_child (const Evoral::Parameter& param, bool
add_automation_child (param, track, show);
break;
+ case PanWidthAutomation:
+ case PanElevationAutomation:
+ case PanAzimuthAutomation:
+ ensure_pan_views (show);
+ break;
+
default:
error << "MidiTimeAxisView: unknown automation child "
<< EventTypeMap::instance().to_symbol(param) << endmsg;
diff --git a/gtk2_ardour/midi_time_axis.h b/gtk2_ardour/midi_time_axis.h
index e021e38769..fa22b431a0 100644
--- a/gtk2_ardour/midi_time_axis.h
+++ b/gtk2_ardour/midi_time_axis.h
@@ -178,6 +178,15 @@ class MidiTimeAxisView : public RouteTimeAxisView
void capture_channel_mode_changed();
void playback_channel_mode_changed();
+
+ void ensure_pan_views (bool show = true);
+
+ void update_gain_track_visibility ();
+ void update_pan_track_visibility ();
+
+ Gtk::CheckMenuItem* gain_automation_item;
+ std::list<boost::shared_ptr<AutomationTimeAxisView> > pan_tracks;
+ Gtk::CheckMenuItem* pan_automation_item;
};
#endif /* __ardour_midi_time_axis_h__ */
diff --git a/gtk2_ardour/panner2d.cc b/gtk2_ardour/panner2d.cc
index 0f8b46aa56..a3befff5cf 100644
--- a/gtk2_ardour/panner2d.cc
+++ b/gtk2_ardour/panner2d.cc
@@ -166,6 +166,7 @@ Panner2d::on_size_allocate (Gtk::Allocation& alloc)
radius = min (width, height);
radius -= border;
radius /= 2;
+ radius = rint(radius) + .5;
hoffset = max ((double) (width - height), border);
voffset = max ((double) (height - width), border);
@@ -251,12 +252,8 @@ Panner2d::handle_position_change ()
uint32_t n;
double w = panner_shell->pannable()->pan_width_control->get_value();
- if (have_elevation) {
- position.position = AngularVector (panner_shell->pannable()->pan_azimuth_control->get_value() * 360.0,
- panner_shell->pannable()->pan_elevation_control->get_value() * 90.0);
- } else {
- position.position = AngularVector (panner_shell->pannable()->pan_azimuth_control->get_value() * 360.0, 0);
- }
+ position.position = AngularVector (panner_shell->pannable()->pan_azimuth_control->get_value() * 360.0,
+ panner_shell->pannable()->pan_elevation_control->get_value() * 90.0);
for (uint32_t i = 0; i < signals.size(); ++i) {
signals[i]->position = panner_shell->panner()->signal_position (i);
@@ -300,7 +297,11 @@ Panner2d::find_closest_object (gdouble x, gdouble y, bool& is_signal)
/* start with the position itself */
- position.position.cartesian (c);
+ PBD::AngularVector dp = position.position;
+ if (!have_elevation) dp.ele = 0;
+ dp.azi = 270 - dp.azi;
+ dp.cartesian (c);
+
cart_to_gtk (c);
best_distance = sqrt ((c.x - x) * (c.x - x) +
(c.y - y) * (c.y - y));
@@ -342,9 +343,11 @@ Panner2d::find_closest_object (gdouble x, gdouble y, bool& is_signal)
if (!closest) {
for (Targets::const_iterator i = speakers.begin(); i != speakers.end(); ++i) {
candidate = *i;
-
- candidate->position.cartesian (c);
- cart_to_gtk (c);
+ PBD::AngularVector sp = candidate->position;
+ sp.azi = 270 -sp.azi;
+ CartesianVector c;
+ sp.cartesian (c);
+ cart_to_gtk (c);
distance = sqrt ((c.x - x) * (c.x - x) +
(c.y - y) * (c.y - y));
@@ -426,14 +429,14 @@ Panner2d::on_expose_event (GdkEventExpose *event)
/* horizontal line of "crosshairs" */
cairo_set_source_rgba (cr, 0.282, 0.517, 0.662, 1.0);
- cairo_move_to (cr, 0.0, rint(radius) + .5);
- cairo_line_to (cr, diameter, rint(radius) + .5);
+ cairo_move_to (cr, 0.0, radius);
+ cairo_line_to (cr, diameter, radius);
cairo_stroke (cr);
/* vertical line of "crosshairs" */
- cairo_move_to (cr, rint(radius) + .5, 0);
- cairo_line_to (cr, rint(radius) + .5, diameter);
+ cairo_move_to (cr, radius, 0);
+ cairo_line_to (cr, radius, diameter);
cairo_stroke (cr);
/* the circle on which signals live */
@@ -456,15 +459,17 @@ Panner2d::on_expose_event (GdkEventExpose *event)
}
if (!panner_shell->bypassed()) {
+ /* convention top == front ^= azimuth == .5 (same as stereo/mono panners) */
if (signals.size() > 1) {
/* arc to show "diffusion" */
double width_angle = fabs (panner_shell->pannable()->pan_width_control->get_value()) * 2 * M_PI;
- double position_angle = (2 * M_PI) - panner_shell->pannable()->pan_azimuth_control->get_value() * 2 * M_PI;
+ double position_angle = panner_shell->pannable()->pan_azimuth_control->get_value() * 2 * M_PI;
cairo_save (cr);
cairo_translate (cr, radius, radius);
+ cairo_rotate (cr, M_PI / 2.0);
cairo_rotate (cr, position_angle - (width_angle/2.0));
cairo_move_to (cr, 0, 0);
cairo_arc_negative (cr, 0, 0, radius, width_angle, 0.0);
@@ -493,7 +498,10 @@ Panner2d::on_expose_event (GdkEventExpose *event)
/* draw position */
- position.position.cartesian (c);
+ PBD::AngularVector dp = position.position;
+ if (!have_elevation) dp.ele = 0;
+ dp.azi = 270 - dp.azi;
+ dp.cartesian (c);
cart_to_gtk (c);
cairo_new_path (cr);
@@ -505,7 +513,7 @@ Panner2d::on_expose_event (GdkEventExpose *event)
/* signals */
- if (signals.size() > 1) {
+ if (signals.size() > 0) {
for (Targets::iterator i = signals.begin(); i != signals.end(); ++i) {
Target* signal = *i;
@@ -516,6 +524,7 @@ Panner2d::on_expose_event (GdkEventExpose *event)
*/
PBD::AngularVector sp = signal->position;
if (!have_elevation) sp.ele = 0;
+ sp.azi += 270.0;
sp.cartesian (c);
cart_to_gtk (c);
@@ -553,9 +562,10 @@ Panner2d::on_expose_event (GdkEventExpose *event)
if (speaker->visible) {
+ PBD::AngularVector sp = speaker->position;
+ sp.azi += 270.0;
CartesianVector c;
-
- speaker->position.cartesian (c);
+ sp.cartesian (c);
cart_to_gtk (c);
snprintf (buf, sizeof (buf), "%d", n);
@@ -564,7 +574,7 @@ Panner2d::on_expose_event (GdkEventExpose *event)
cairo_move_to (cr, c.x, c.y);
cairo_save (cr);
- cairo_rotate (cr, -(speaker->position.azi/360.0) * (2.0 * M_PI));
+ cairo_rotate (cr, -(sp.azi/360.0) * (2.0 * M_PI));
if (small) {
cairo_scale (cr, 0.8, 0.8);
} else {
@@ -588,7 +598,8 @@ Panner2d::on_expose_event (GdkEventExpose *event)
/* move the text in just a bit */
- AngularVector textpos (speaker->position.azi, speaker->position.ele, 0.85);
+ AngularVector textpos (speaker->position.azi + 270.0, speaker->position.ele, 0.85);
+
textpos.cartesian (c);
cart_to_gtk (c);
cairo_move_to (cr, c.x, c.y);
@@ -716,6 +727,7 @@ Panner2d::handle_motion (gint evx, gint evy, GdkModifierType state)
if (!have_elevation) {
clamp_to_circle (cp.x, cp.y);
cp.angular (av);
+ av.azi = fmod(270 - av.azi, 360);
if (drag_target == &position) {
double degree_fract = av.azi / 360.0;
panner_shell->panner()->set_position (degree_fract);
@@ -727,6 +739,7 @@ Panner2d::handle_motion (gint evx, gint evy, GdkModifierType state)
double r2d = 180.0 / M_PI;
av.azi = r2d * atan2(cp.y, cp.x);
av.ele = r2d * asin(cp.z);
+ av.azi = fmod(270 - av.azi, 360);
if (drag_target == &position) {
double azi_fract = av.azi / 360.0;