Gtkmm2ext::container_clear (basic_vbox);
Gtkmm2ext::container_clear (basic_packer);
+ if (control_app_button.get_parent()) {
+ control_app_button.get_parent()->remove (control_app_button);
+ }
+
label = manage (left_aligned_label (_("Audio System:")));
basic_packer.attach (*label, 0, 1, 0, 1, xopt, (AttachOptions) 0);
basic_packer.attach (backend_combo, 1, 2, 0, 1, xopt, (AttachOptions) 0);
: ProcessorEntry (b, p, w)
, _plugin_insert (p)
{
- p->SplittingChanged.connect (
+ p->PluginIoReConfigure.connect (
_splitting_connection, invalidator (*this), boost::bind (&PluginInsertProcessorEntry::plugin_insert_splitting_changed, this), gui_context()
);
void
PluginInsertProcessorEntry::plugin_insert_splitting_changed ()
{
- if (_plugin_insert->splitting ()) {
+ _splitting_icon.set_inputs(_plugin_insert->input_streams());
+ _splitting_icon.set_outputs(_plugin_insert->output_streams());
+
+ if (_plugin_insert->splitting () || (
+ _plugin_insert->input_streams().n_midi() == 0
+ && _plugin_insert->input_streams().n_audio() < _plugin_insert->output_streams().n_audio()
+ )
+ )
+ {
_splitting_icon.show ();
+ _splitting_icon.queue_draw();
} else {
_splitting_icon.hide ();
}
Gdk::Color const fg = get_style()->get_fg (STATE_NORMAL);
cairo_set_source_rgb (cr, fg.get_red_p (), fg.get_green_p (), fg.get_blue_p ());
- const float si_l = rint(width * 0.3) + .5;
- const float si_c = rint(width * 0.5) + .5;
- const float si_r = rint(width * 0.7) + .5;
- const float si_m = rint(height * 0.5) + .5;
+ const uint32_t inputs = _inputs.n_audio();
+ const uint32_t outputs = _outputs.n_audio();
+
+ const float si_m = rintf(height * 0.5) + .5f;
+
+ if (inputs == 1) {
+ const float si_l = rintf(width * 0.2) + .5f;
+ const float si_c = rintf(width * 0.5) + .5f;
+ const float si_r = rintf(width * 0.8) + .5f;
- cairo_move_to (cr, si_l, height);
- cairo_line_to (cr, si_l, si_m);
- cairo_line_to (cr, si_r, si_m);
- cairo_line_to (cr, si_r, height);
+ cairo_move_to (cr, si_l, height);
+ cairo_line_to (cr, si_l, si_m);
+ cairo_line_to (cr, si_r, si_m);
+ cairo_line_to (cr, si_r, height);
+ cairo_stroke (cr);
+
+ cairo_set_line_cap (cr, CAIRO_LINE_CAP_BUTT);
+
+ const uint32_t outputs = _outputs.n_audio();
+ for (uint32_t i = 2; i < outputs; ++i) {
+ const float si_b = rintf(width * (.2f + .6f * (i - 1.f) / (outputs - 1.f))) + .5f;
+ cairo_move_to (cr, si_b, height);
+ cairo_line_to (cr, si_b, si_m);
+ cairo_stroke (cr);
+ }
- cairo_set_line_cap (cr, CAIRO_LINE_CAP_BUTT);
- cairo_move_to (cr, si_c, si_m);
- cairo_line_to (cr, si_c, 0);
- cairo_stroke (cr);
+ cairo_move_to (cr, si_c, si_m);
+ cairo_line_to (cr, si_c, 0);
+ cairo_stroke (cr);
+ } else {
+ cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND);
+ for (uint32_t i = 0 ; i < outputs; ++i) {
+ const float si_x = rintf(width * (.2f + .6f * i / (outputs - 1.f))) + .5f;
+ if (i < inputs) {
+ cairo_move_to (cr, si_x, height);
+ cairo_line_to (cr, si_x, 0);
+ cairo_stroke (cr);
+ } else {
+ cairo_move_to (cr, si_x, si_m);
+ cairo_line_to (cr, si_x, height);
+ cairo_stroke (cr);
+ cairo_move_to (cr, si_x+4, si_m);
+ cairo_line_to (cr, si_x-4, si_m);
+ cairo_stroke (cr);
+ }
+ }
+ }
return true;
}
void setup_visuals ();
void plugin_insert_splitting_changed ();
- /* XXX: this seems a little ridiculous just for a simple scaleable icon */
class SplittingIcon : public Gtk::DrawingArea {
+ public:
+ SplittingIcon() {
+ _inputs = ARDOUR::ChanCount(ARDOUR::DataType::AUDIO, 1);
+ _outputs = ARDOUR::ChanCount(ARDOUR::DataType::AUDIO, 2);
+ }
+ void set_inputs(ARDOUR::ChanCount const inputs) { _inputs = inputs; }
+ void set_outputs(ARDOUR::ChanCount const outputs) { _outputs = outputs; }
private:
bool on_expose_event (GdkEventExpose *);
+ ARDOUR::ChanCount _inputs;
+ ARDOUR::ChanCount _outputs;
};
boost::shared_ptr<ARDOUR::PluginInsert> _plugin_insert;
Iec1ppmdsp (void);
~Iec1ppmdsp (void);
- void process (float *p, int n);
+ void process (float const *p, int n);
float read (void);
void reset ();
- static void init (float fsamp);
+ static void init (float fsamp);
private:
Iec2ppmdsp (void);
~Iec2ppmdsp (void);
- void process (float *p, int n);
+ void process (float const *p, int n);
float read (void);
void reset ();
- static void init (float fsamp);
+ static void init (float fsamp);
private:
Kmeterdsp (void);
~Kmeterdsp (void);
- void process (float *p, int n);
+ void process (float const *p, int n);
float read ();
void reset ();
}
PBD::Signal2<void,BufferSet*, BufferSet*> AnalysisDataGathered;
- /** Emitted when the return value of splitting () has changed */
- PBD::Signal0<void> SplittingChanged;
+ PBD::Signal0<void> PluginIoReConfigure;
/** Enumeration of the ways in which we can match our insert's
* IO to that of the plugin(s).
Vumeterdsp (void);
~Vumeterdsp (void);
- void process (float *p, int n);
+ void process (float const *p, int n);
float read (void);
void reset ();
- static void init (float fsamp);
+ static void init (float fsamp);
private:
/* copy an existing channel's data in for this non-existant one */
- uint32_t channel = n_channels() % chan_n;
+ uint32_t channel = chan_n % n_channels();
boost::shared_ptr<AudioSource> src = boost::dynamic_pointer_cast<AudioSource> (srcs[channel]);
if (src->read (buf, _start + internal_offset, to_read) != to_read) {
}
-void Iec1ppmdsp::process (float *p, int n)
+void Iec1ppmdsp::process (float const *p, int n)
{
float z1, z2, m, t;
}
-void Iec2ppmdsp::process (float *p, int n)
+void Iec2ppmdsp::process (float const *p, int n)
{
float z1, z2, m, t;
_omega = 9.72f / fsamp; // ballistic filter coefficient
}
-void Kmeterdsp::process (float *p, int n)
+void Kmeterdsp::process (float const *p, int n)
{
// Called by JACK's process callback.
//
// Meter audio in to the rest of the peaks
for (uint32_t i = 0; i < n_audio; ++i, ++n) {
- _peak_signal[n] = compute_peak (bufs.get_audio(i).data(), nframes, _peak_signal[n]);
+ if (bufs.get_audio(i).silent()) {
+ _peak_signal[n] = .0f;
+ } else {
+ _peak_signal[n] = compute_peak (bufs.get_audio(i).data(), nframes, _peak_signal[n]);
+ }
if (_meter_type & (MeterKrms | MeterK20 | MeterK14 | MeterK12)) {
_kmeter[i]->process(bufs.get_audio(i).data(), nframes);
}
*/
if (port_engine.midi_event_put (port_buffer, when, ev, 3) != 0) {
- cerr << "failed to deliver sustain-zero on channel " << channel << " on port " << name() << endl;
+ cerr << "failed to deliver sustain-zero on channel " << (int)channel << " on port " << name() << endl;
}
ev[1] = MIDI_CTL_ALL_NOTES_OFF;
if (port_engine.midi_event_put (port_buffer, 0, ev, 3) != 0) {
- cerr << "failed to deliver ALL NOTES OFF on channel " << channel << " on port " << name() << endl;
+ cerr << "failed to deliver ALL NOTES OFF on channel " << (int)channel << " on port " << name() << endl;
}
}
}
<< ev.time() << " > " << _global_port_buffer_offset + _port_buffer_offset << endl;
}
} else {
- cerr << "drop flushed event on the floor, time " << ev
+ cerr << "drop flushed event on the floor, time " << ev.time()
<< " to early for " << _global_port_buffer_offset
<< " + " << _port_buffer_offset << endl;
}
/* XXX: audio only */
uint32_t first_idx = in_map.get (DataType::AUDIO, 0, &valid);
if (valid) {
- Sample const * mono = bufs.get_audio (first_idx).data (offset);
for (uint32_t i = in_streams.n_audio(); i < natural_input_streams().n_audio(); ++i) {
- memcpy (bufs.get_audio (in_map.get (DataType::AUDIO, i, &valid)).data (offset), mono, sizeof (Sample) * nframes);
+ bufs.get_audio(in_map.get (DataType::AUDIO, i, &valid)).read_from(bufs.get_audio(first_idx), nframes, offset, offset);
}
}
}
/* not active, but something has make up for any channel count increase */
- for (uint32_t n = out - in; n < out; ++n) {
- memcpy (bufs.get_audio (n).data(), bufs.get_audio(in - 1).data(), sizeof (Sample) * nframes);
+ // TODO: option round-robin (n % in) or silence additional buffers ??
+ for (uint32_t n = in; n < out; ++n) {
+ bufs.get_audio(n).read_from(bufs.get_audio(in - 1), nframes);
}
}
PluginInsert::configure_io (ChanCount in, ChanCount out)
{
Match old_match = _match;
+ ChanCount old_in = input_streams ();
+ ChanCount old_out = output_streams ();
/* set the matching method and number of plugins that we will use to meet this configuration */
_match = private_can_support_io_configuration (in, out);
return false;
}
- /* a signal needs emitting if we start or stop splitting */
- if (old_match.method != _match.method && (old_match.method == Split || _match.method == Split)) {
- SplittingChanged (); /* EMIT SIGNAL */
+ if ( (old_match.method != _match.method && (old_match.method == Split || _match.method == Split))
+ || old_in != in
+ || old_out != out
+ )
+ {
+ PluginIoReConfigure (); /* EMIT SIGNAL */
}
/* configure plugins */
ControlProtocolManager& m = ControlProtocolManager::instance ();
for (list<ControlProtocolInfo*>::iterator i = m.control_protocol_info.begin(); i != m.control_protocol_info.end(); ++i) {
- m.instantiate (**i);
- m.teardown (**i);
+ m.activate (**i);
+ m.deactivate (**i);
}
}
}
-void Vumeterdsp::process (float *p, int n)
+void Vumeterdsp::process (float const *p, int n)
{
float z1, z2, m, t1, t2;
void Vumeterdsp::init (float fsamp)
{
- _w = 11.1f / fsamp;
+ _w = 11.1f / fsamp;
_g = 1.5f * 1.571f;
}
boost::shared_ptr<Patch>
MasterDeviceNames::find_patch(const std::string& mode, uint8_t channel, const PatchPrimaryKey& key)
{
- return channel_name_set_by_device_mode_and_channel(mode, channel)->find_patch(key);
+ boost::shared_ptr<ChannelNameSet> cns = channel_name_set_by_device_mode_and_channel(mode, channel);
+ if (!cns) return boost::shared_ptr<Patch>();
+ return cns->find_patch(key);
}
boost::shared_ptr<ChannelNameSet>