merge with master

This commit is contained in:
Paul Davis 2014-01-15 14:29:32 -05:00
commit 9aacefc170
12 changed files with 251 additions and 61 deletions

View File

@ -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;
}
}
}

View File

@ -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 {

View File

@ -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
@ -1071,6 +1105,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)
{
@ -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;

View File

@ -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__ */

View File

@ -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;

View File

@ -397,8 +397,7 @@ Delivery::reset_panner ()
if (panners_legal) {
if (!_no_panner_reset) {
if (_panshell) {
assert (_role == Main || _role == Aux || _role == Send);
if (_panshell && _role != Insert) {
_panshell->configure_io (ChanCount (DataType::AUDIO, pans_required()), ChanCount (DataType::AUDIO, pan_outs()));
}
}
@ -412,8 +411,7 @@ Delivery::reset_panner ()
void
Delivery::panners_became_legal ()
{
if (_panshell) {
assert (_role == Main || _role == Aux || _role == Send);
if (_panshell && _role != Insert) {
_panshell->configure_io (ChanCount (DataType::AUDIO, pans_required()), ChanCount (DataType::AUDIO, pan_outs()));
}

View File

@ -149,7 +149,7 @@ Speakers::move_speaker (int id, const AngularVector& new_position)
void
Speakers::setup_default_speakers (uint32_t n)
{
double o = 90.0;
double o = 180.0;
/* default assignment of speaker position for n speakers */
@ -229,12 +229,12 @@ Speakers::setup_default_speakers (uint32_t n)
*/
if (n % 2) {
deg = 90.0 - degree_step;
deg = 360 + o + degree_step;
} else {
deg = 90.0;
deg = 360 + o;
}
for (i = 0; i < n; ++i, deg += degree_step) {
add_speaker (AngularVector (deg, 0.0));
for (i = 0; i < n; ++i, deg -= degree_step) {
add_speaker (AngularVector (fmod(deg, 360), 0.0));
}
}
}

View File

@ -528,23 +528,36 @@ VSTPlugin::connect_and_run (BufferSet& bufs,
{
Plugin::connect_and_run (bufs, in_map, out_map, nframes, offset);
// VC++ doesn't support this C99 extension. Use alloca instead of dynamic array (rather than std::vector which allocs on the heap)
ChanCount bufs_count;
bufs_count.set(DataType::AUDIO, 1);
bufs_count.set(DataType::MIDI, 1);
BufferSet& silent_bufs = _session.get_silent_buffers(bufs_count);
BufferSet& scratch_bufs = _session.get_scratch_buffers(bufs_count);
float** ins = (float**)alloca(_plugin->numInputs*sizeof(float*));
float** outs = (float**)alloca(_plugin->numInputs*sizeof(float*));
int32_t i;
const uint32_t nbufs = bufs.count().n_audio();
int in_index = 0;
uint32_t in_index = 0;
for (i = 0; i < (int32_t) _plugin->numInputs; ++i) {
ins[i] = bufs.get_audio(min((uint32_t) in_index, nbufs - 1)).data() + offset;
in_index++;
uint32_t index;
bool valid = false;
index = in_map.get(DataType::AUDIO, in_index++, &valid);
ins[i] = (valid)
? bufs.get_audio(index).data(offset)
: silent_bufs.get_audio(0).data(offset);
}
int out_index = 0;
uint32_t out_index = 0;
for (i = 0; i < (int32_t) _plugin->numOutputs; ++i) {
outs[i] = bufs.get_audio(min((uint32_t) out_index, nbufs - 1)).data() + offset;
out_index++;
uint32_t index;
bool valid = false;
index = out_map.get(DataType::AUDIO, out_index++, &valid);
outs[i] = (valid)
? bufs.get_audio(index).data(offset)
: scratch_bufs.get_audio(0).data(offset);
}
if (bufs.count().n_midi() > 0) {

View File

@ -385,7 +385,7 @@ Panner1in2out::value_as_string (boost::shared_ptr<AutomationControl> ac) const
(int) rint (100.0 * val));
default:
return _pannable->value_as_string (ac);
return _("unused");
}
}

View File

@ -78,7 +78,14 @@ Panner2in2out::Panner2in2out (boost::shared_ptr<Pannable> p)
if (!_pannable->has_state()) {
_pannable->pan_azimuth_control->set_value (0.5);
_pannable->pan_width_control->set_value (1.0);
}
}
double const w = width();
double const wrange = min (position(), (1 - position())) * 2;
if (fabs(w) > wrange) {
set_width(w > 0 ? wrange : -wrange);
}
update ();
@ -158,6 +165,11 @@ Panner2in2out::update ()
double width = this->width ();
const double direction_as_lr_fract = position ();
double const wrange = min (position(), (1 - position())) * 2;
if (fabs(width) > wrange) {
width = (width > 0 ? wrange : -wrange);
}
if (width < 0.0) {
width = -width;
pos[0] = direction_as_lr_fract + (width/2.0); // left signal lr_fract
@ -421,6 +433,8 @@ Panner2in2out::distribute_one_automated (AudioBuffer& srcbuf, BufferSet& obufs,
panR = position[n] + (width[n]/2.0f); // center - width/2
}
panR = max(0.f, min(1.f, panR));
const float panL = 1 - panR;
/* note that are overwriting buffers, but its OK
@ -522,7 +536,7 @@ Panner2in2out::value_as_string (boost::shared_ptr<AutomationControl> ac) const
return string_compose (_("Width: %1%%"), (int) floor (100.0 * val));
default:
return _pannable->value_as_string (ac);
return _("unused");
}
}

View File

@ -321,7 +321,7 @@ Pannerbalance::value_as_string (boost::shared_ptr<AutomationControl> ac) const
(int) rint (100.0 * val));
default:
return _pannable->value_as_string (ac);
return _("unused");
}
}

View File

@ -126,7 +126,7 @@ VBAPanner::update ()
if (_signals.size() > 1) {
double w = - (_pannable->pan_width_control->get_value());
double signal_direction = _pannable->pan_azimuth_control->get_value() - (w/2);
double signal_direction = 1.0 - (_pannable->pan_azimuth_control->get_value() + (w/2));
double grd_step_per_signal = w / (_signals.size() - 1);
for (vector<Signal*>::iterator s = _signals.begin(); s != _signals.end(); ++s) {
@ -141,7 +141,7 @@ VBAPanner::update ()
signal_direction += grd_step_per_signal;
}
} else if (_signals.size() == 1) {
double center = _pannable->pan_azimuth_control->get_value() * 360.0;
double center = (1.0 - _pannable->pan_azimuth_control->get_value()) * 360.0;
/* width has no role to play if there is only 1 signal: VBAP does not do "diffusion" of a single channel */
@ -425,7 +425,7 @@ VBAPanner::value_as_string (boost::shared_ptr<AutomationControl> ac) const
switch (ac->parameter().type()) {
case PanAzimuthAutomation: /* direction */
return string_compose (_("%1\u00B0"), int (rint (val * 360.0)));
return string_compose (_("%1\u00B0"), (int (rint (val * 360.0))+180)%360);
case PanWidthAutomation: /* diffusion */
return string_compose (_("%1%%"), (int) floor (100.0 * fabs(val)));
@ -434,7 +434,7 @@ VBAPanner::value_as_string (boost::shared_ptr<AutomationControl> ac) const
return string_compose (_("%1\u00B0"), (int) floor (90.0 * fabs(val)));
default:
return _pannable->value_as_string (ac);
return _("unused");
}
}
@ -479,11 +479,11 @@ VBAPanner::set_elevation (double e)
void
VBAPanner::reset ()
{
set_position (0);
set_position (.5);
if (_signals.size() > 1) {
set_width (1.0 - (1.0 / (double)_signals.size()));
} else {
set_width (0);
set_width (1.0);
}
set_elevation (0);