diff options
31 files changed, 639 insertions, 223 deletions
diff --git a/gtk2_ardour/add_route_dialog.cc b/gtk2_ardour/add_route_dialog.cc index aa61cb2525..4a2c3d2a2a 100644 --- a/gtk2_ardour/add_route_dialog.cc +++ b/gtk2_ardour/add_route_dialog.cc @@ -159,11 +159,16 @@ AddRouteDialog::track () return track_button.get_active (); } -bool -AddRouteDialog::midi () +ARDOUR::DataType +AddRouteDialog::type () { + // FIXME: ew + const string str = channel_combo.get_active_text(); - return (str == _("MIDI")); + if (str == _("MIDI")) + return ARDOUR::DataType::MIDI; + else + return ARDOUR::DataType::AUDIO; } string diff --git a/gtk2_ardour/add_route_dialog.h b/gtk2_ardour/add_route_dialog.h index ae4679fd5d..d0c1ec661a 100644 --- a/gtk2_ardour/add_route_dialog.h +++ b/gtk2_ardour/add_route_dialog.h @@ -13,6 +13,7 @@ #include <gtkmm/comboboxtext.h> #include <ardour/types.h> +#include <ardour/data_type.h> class AddRouteDialog : public Gtk::Dialog { @@ -21,7 +22,7 @@ class AddRouteDialog : public Gtk::Dialog ~AddRouteDialog (); bool track (); - bool midi (); + ARDOUR::DataType type(); std::string name_template (); int channels (); int count (); diff --git a/gtk2_ardour/ardour_ui.cc b/gtk2_ardour/ardour_ui.cc index 203d64c3c3..337e10ea4b 100644 --- a/gtk2_ardour/ardour_ui.cc +++ b/gtk2_ardour/ardour_ui.cc @@ -1414,7 +1414,7 @@ ARDOUR_UI::name_io_setup (AudioEngine& engine, bool in) { if (in) { - if (io.n_inputs() == 0) { + if (io.n_inputs().get_total() == 0) { buf = _("none"); return; } @@ -1433,7 +1433,7 @@ ARDOUR_UI::name_io_setup (AudioEngine& engine, } else { - if (io.n_outputs() == 0) { + if (io.n_outputs().get_total() == 0) { buf = _("none"); return; } @@ -2103,7 +2103,7 @@ ARDOUR_UI::add_route () Session::AutoConnectOption oac = session->get_output_auto_connect(); if (oac & Session::AutoConnectMaster) { - output_chan = (session->master_out() ? session->master_out()->n_inputs() : input_chan); + output_chan = (session->master_out() ? session->master_out()->n_inputs().get(DataType::AUDIO) : input_chan); } else { output_chan = input_chan; } @@ -2111,10 +2111,15 @@ ARDOUR_UI::add_route () /* XXX do something with name template */ while (count) { - if (track && add_route_dialog->midi()) { - session_add_midi_track(); - } else if (add_route_dialog->midi()) { - session_add_midi_bus(); + if (add_route_dialog->type() == ARDOUR::DataType::MIDI) { + if (track) { + session_add_midi_track(); + } else { + MessageDialog msg (*editor, + _("Sorry, MIDI Busses are not supported at this time.")); + msg.run (); + //session_add_midi_bus(); + } } else if (track) { session_add_audio_track (input_chan, output_chan, add_route_dialog->mode()); } else { diff --git a/gtk2_ardour/audio_time_axis.cc b/gtk2_ardour/audio_time_axis.cc index 9ae94d1fe0..ffa95ae23d 100644 --- a/gtk2_ardour/audio_time_axis.cc +++ b/gtk2_ardour/audio_time_axis.cc @@ -406,7 +406,7 @@ AudioTimeAxisView::update_pans () /* we don't draw lines for "greater than stereo" panning. */ - if (_route->n_outputs() > 2) { + if (_route->n_outputs().get(DataType::AUDIO) > 2) { return; } diff --git a/gtk2_ardour/editor_audio_import.cc b/gtk2_ardour/editor_audio_import.cc index 7524f9605c..754706ad9f 100644 --- a/gtk2_ardour/editor_audio_import.cc +++ b/gtk2_ardour/editor_audio_import.cc @@ -293,7 +293,7 @@ Editor::embed_sndfile (Glib::ustring path, bool split, bool multiple_files, bool input_chan = finfo.channels; if (session->get_output_auto_connect() & Session::AutoConnectMaster) { - output_chan = (session->master_out() ? session->master_out()->n_inputs() : input_chan); + output_chan = (session->master_out() ? session->master_out()->n_inputs().get(DataType::AUDIO) : input_chan); } else { output_chan = input_chan; } diff --git a/gtk2_ardour/export_dialog.cc b/gtk2_ardour/export_dialog.cc index b5a4757090..bf7873914d 100644 --- a/gtk2_ardour/export_dialog.cc +++ b/gtk2_ardour/export_dialog.cc @@ -490,7 +490,7 @@ ExportDialog::set_state() } TreeModel::Children rows = master_selector.get_model()->children(); - for (uint32_t r = 0; r < session->master_out()->n_outputs(); ++r) { + for (uint32_t r = 0; r < session->master_out()->n_outputs().get(DataType::AUDIO); ++r) { if (nchns == 2) { if (r % 2) { rows[r][exp_cols.right] = true; @@ -1092,9 +1092,9 @@ ExportDialog::fill_lists () continue; } - for (uint32_t i=0; i < route->n_outputs(); ++i) { + for (uint32_t i=0; i < route->n_outputs().get(DataType::AUDIO); ++i) { string name; - if (route->n_outputs() == 1) { + if (route->n_outputs().get(DataType::AUDIO) == 1) { name = route->name(); } else { name = string_compose("%1: out-%2", route->name(), i+1); diff --git a/gtk2_ardour/gain_meter.cc b/gtk2_ardour/gain_meter.cc index 5fa8c462bc..ea7663da8a 100644 --- a/gtk2_ardour/gain_meter.cc +++ b/gtk2_ardour/gain_meter.cc @@ -141,13 +141,16 @@ GainMeter::GainMeter (boost::shared_ptr<IO> io, Session& s) gain_automation_state_button.set_size_request(15, 15); gain_automation_style_button.set_size_request(15, 15); + fader_vbox = manage (new Gtk::VBox()); fader_vbox->set_spacing (0); fader_vbox->pack_start (*gain_slider, false, false, 0); hbox.set_spacing (0); - hbox.pack_start (*fader_vbox, false, false, 2); + if (_io->default_type() == ARDOUR::DataType::AUDIO) + hbox.pack_start (*fader_vbox, false, false, 2); + set_width(Narrow); Route* r; @@ -382,7 +385,7 @@ GainMeter::hide_all_meters () void GainMeter::setup_meters () { - uint32_t nmeters = _io->n_outputs(); + uint32_t nmeters = _io->n_outputs().get(DataType::AUDIO); guint16 width; hide_all_meters (); @@ -394,16 +397,16 @@ GainMeter::setup_meters () switch (r->meter_point()) { case MeterPreFader: case MeterInput: - nmeters = r->n_inputs(); + nmeters = r->n_inputs().get(DataType::AUDIO); break; case MeterPostFader: - nmeters = r->n_outputs(); + nmeters = r->n_outputs().get(DataType::AUDIO); break; } } else { - nmeters = _io->n_outputs(); + nmeters = _io->n_outputs().get(DataType::AUDIO); } diff --git a/gtk2_ardour/io_selector.cc b/gtk2_ardour/io_selector.cc index f754435112..f9082c3ef0 100644 --- a/gtk2_ardour/io_selector.cc +++ b/gtk2_ardour/io_selector.cc @@ -183,15 +183,18 @@ IOSelector::IOSelector (Session& sess, boost::shared_ptr<IO> ior, bool input) port_button_box.pack_start (add_port_button, false, false); + // The IO selector only works for single typed IOs + const ARDOUR::DataType t = io->default_type(); + if (for_input) { - if (io->input_maximum() < 0 || io->input_maximum() > (int) io->n_inputs()) { + if (io->input_maximum().get(t) < 0 || io->input_maximum().get(t) > (size_t) io->n_inputs().get(t)) { add_port_button.set_sensitive (true); } else { add_port_button.set_sensitive (false); } } else { - if (io->output_maximum() < 0 || io->output_maximum() > (int) io->n_outputs()) { + if (io->output_maximum().get(t) < 0 || io->output_maximum().get(t) > (size_t) io->n_outputs().get(t)) { add_port_button.set_sensitive (true); } else { add_port_button.set_sensitive (false); @@ -202,14 +205,14 @@ IOSelector::IOSelector (Session& sess, boost::shared_ptr<IO> ior, bool input) port_button_box.pack_start (remove_port_button, false, false); if (for_input) { - if (io->input_minimum() < 0 || io->input_minimum() < (int) io->n_inputs()) { + if (io->input_minimum().get(t) < 0 || io->input_minimum().get(t) < (size_t) io->n_inputs().get(t)) { remove_port_button.set_sensitive (true); } else { remove_port_button.set_sensitive (false); } } else { - if (io->output_minimum() < 0 || io->output_minimum() < (int) io->n_outputs()) { + if (io->output_minimum().get(t) < 0 || io->output_minimum().get(t) < (size_t) io->n_outputs().get(t)) { remove_port_button.set_sensitive (true); } else { remove_port_button.set_sensitive (false); @@ -373,10 +376,13 @@ IOSelector::display_ports () Port *port; uint32_t limit; + // The IO selector only works for single typed IOs + const ARDOUR::DataType t = io->default_type(); + if (for_input) { - limit = io->n_inputs(); + limit = io->n_inputs().get(t); } else { - limit = io->n_outputs(); + limit = io->n_outputs().get(t); } for (slist<TreeView *>::iterator i = port_displays.begin(); i != port_displays.end(); ) { @@ -443,7 +449,7 @@ IOSelector::display_ports () if (for_input) { - if (io->input_maximum() == 1) { + if (io->input_maximum().get(io->default_type()) == 1) { selected_port = port; selected_port_tview = tview; } else { @@ -454,7 +460,7 @@ IOSelector::display_ports () } else { - if (io->output_maximum() == 1) { + if (io->output_maximum().get(t) == 1) { selected_port = port; selected_port_tview = tview; } else { @@ -545,6 +551,9 @@ IOSelector::add_port () { /* add a new port, then hide the button if we're up to the maximum allowed */ + // The IO selector only works for single typed IOs + const ARDOUR::DataType t = io->default_type(); + if (for_input) { try { @@ -556,11 +565,11 @@ IOSelector::add_port () msg.run (); } - if (io->input_maximum() >= 0 && io->input_maximum() <= (int) io->n_inputs()) { + if (io->input_maximum().get(t) >= 0 && io->input_maximum().get(t) <= (size_t) io->n_inputs().get(t)) { add_port_button.set_sensitive (false); } - if (io->input_minimum() < (int) io->n_inputs()) { + if (io->input_minimum().get(t) < (size_t) io->n_inputs().get(t)) { remove_port_button.set_sensitive (true); } @@ -575,7 +584,7 @@ IOSelector::add_port () msg.run (); } - if (io->output_maximum() >= 0 && io->output_maximum() <= (int) io->n_outputs()) { + if (io->output_maximum().get(t) >= 0 && io->output_maximum().get(t) <= (size_t) io->n_outputs().get(t)) { add_port_button.set_sensitive (false); } } @@ -586,17 +595,20 @@ IOSelector::remove_port () { uint32_t nports; + // The IO selector only works for single typed IOs + const ARDOUR::DataType t = io->default_type(); + // always remove last port if (for_input) { - if ((nports = io->n_inputs()) > 0) { + if ((nports = io->n_inputs().get(t)) > 0) { io->remove_input_port (io->input(nports-1), this); } - if (io->input_minimum() == (int) io->n_inputs()) { + if (io->input_minimum().get(t) == (size_t) io->n_inputs().get(t)) { remove_port_button.set_sensitive (false); } } else { - if ((nports = io->n_outputs()) > 0) { + if ((nports = io->n_outputs().get(t)) > 0) { io->remove_output_port (io->output(nports-1), this); } } @@ -749,11 +761,11 @@ IOSelector::redisplay () display_ports (); if (for_input) { - if (io->input_maximum() != 0) { + if (io->input_maximum().get(io->default_type()) != 0) { rescan (); } } else { - if (io->output_maximum() != 0) { + if (io->output_maximum().get(io->default_type()) != 0) { rescan(); } } diff --git a/gtk2_ardour/mixer_strip.cc b/gtk2_ardour/mixer_strip.cc index a866a9780a..14c5b920be 100644 --- a/gtk2_ardour/mixer_strip.cc +++ b/gtk2_ardour/mixer_strip.cc @@ -614,7 +614,7 @@ MixerStrip::add_connection_to_input_menu (ARDOUR::Connection* c) MenuList& citems = input_menu.items(); - if (c->nports() == _route->n_inputs()) { + if (c->nports() == _route->n_inputs().get_total()) { citems.push_back (CheckMenuElem (c->name(), bind (mem_fun(*this, &MixerStrip::connection_input_chosen), c))); @@ -637,7 +637,7 @@ MixerStrip::add_connection_to_output_menu (ARDOUR::Connection* c) return; } - if (c->nports() == _route->n_outputs()) { + if (c->nports() == _route->n_outputs().get_total()) { MenuList& citems = output_menu.items(); citems.push_back (CheckMenuElem (c->name(), bind (mem_fun(*this, &MixerStrip::connection_output_chosen), c))); @@ -1129,8 +1129,6 @@ MixerStrip::route_active_changed () { RouteUI::route_active_changed (); - // FIXME: MIDI/Audio bus distinction - if (is_midi_track()) { if (_route->active()) { set_name ("MidiTrackStripBase"); @@ -1139,7 +1137,6 @@ MixerStrip::route_active_changed () set_name ("MidiTrackStripBaseInactive"); gpm.set_meter_strip_name ("MidiTrackStripBaseInactive"); } - gpm.set_fader_name ("MidiTrackFader"); } else if (is_audio_track()) { if (_route->active()) { set_name ("AudioTrackStripBase"); diff --git a/gtk2_ardour/panner_ui.cc b/gtk2_ardour/panner_ui.cc index ccce2ec9f1..250f1e146e 100644 --- a/gtk2_ardour/panner_ui.cc +++ b/gtk2_ardour/panner_ui.cc @@ -276,7 +276,7 @@ PannerUI::update_pan_state () void PannerUI::setup_pan () { - uint32_t nouts = _io->n_outputs (); + uint32_t nouts = _io->n_outputs ().get(ARDOUR::DataType::AUDIO); if (nouts == 0 || nouts == 1) { @@ -375,7 +375,7 @@ PannerUI::setup_pan () } update_pan_sensitive (); - panner->reset (_io->n_inputs()); + panner->reset (_io->n_inputs().get(ARDOUR::DataType::AUDIO)); panner->set_size_request (w, 61); /* and finally, add it to the panner frame */ @@ -462,7 +462,7 @@ PannerUI::effective_pan_display () return; } - switch (_io->n_outputs()) { + switch (_io->n_outputs().get(ARDOUR::DataType::AUDIO)) { case 0: case 1: /* relax */ @@ -473,7 +473,7 @@ PannerUI::effective_pan_display () break; default: - //panner->move_puck (pan_value (v, right), 0.5); + //panner->move_puck (pan_value (v, right), 0.5); break; } } @@ -499,7 +499,7 @@ PannerUI::pan_changed (void *src) panning_link_button.set_sensitive (true); } - uint32_t nouts = _io->n_outputs(); + uint32_t nouts = _io->n_outputs().get(ARDOUR::DataType::AUDIO); switch (nouts) { case 0: @@ -556,7 +556,7 @@ PannerUI::pan_value_changed (uint32_t which) { ENSURE_GUI_THREAD (bind (mem_fun(*this, &PannerUI::pan_value_changed), which)); - if (_io->n_outputs() > 1 && which < _io->panner().size()) { + if (_io->n_outputs().get(ARDOUR::DataType::AUDIO) > 1 && which < _io->panner().size()) { float xpos; float val = pan_adjustments[which]->get_value (); @@ -626,7 +626,7 @@ PannerUI::update_pan_sensitive () { bool sensitive = !(_io->panner().automation_state() & Play); - switch (_io->n_outputs()) { + switch (_io->n_outputs().get(ARDOUR::DataType::AUDIO)) { case 0: case 1: break; diff --git a/gtk2_ardour/redirect_box.cc b/gtk2_ardour/redirect_box.cc index ddb9e85ca2..2c645d8ed1 100644 --- a/gtk2_ardour/redirect_box.cc +++ b/gtk2_ardour/redirect_box.cc @@ -417,8 +417,8 @@ RedirectBox::wierd_plugin_dialog (Plugin& p, uint32_t streams, boost::shared_ptr p.name(), p.get_info()->n_inputs, p.get_info()->n_outputs, - io->n_inputs(), - io->n_outputs(), + io->n_inputs().get_total(), + io->n_outputs().get_total(), streams)); } diff --git a/libs/ardour/SConscript b/libs/ardour/SConscript index 7230a0622b..5367c10a7c 100644 --- a/libs/ardour/SConscript +++ b/libs/ardour/SConscript @@ -27,6 +27,7 @@ ardour.Append(POTFILE = domain + '.pot') ardour.Append(CPPPATH = '#libs/surfaces/control_protocol') ardour_files=Split(""" +chan_count.cc diskstream.cc track.cc audio_diskstream.cc @@ -39,6 +40,7 @@ audio_port.cc midi_port.cc port_set.cc buffer.cc +buffer_set.cc audiofilesource.cc audiofilter.cc audioregion.cc diff --git a/libs/ardour/ardour/buffer_set.h b/libs/ardour/ardour/buffer_set.h new file mode 100644 index 0000000000..1799858794 --- /dev/null +++ b/libs/ardour/ardour/buffer_set.h @@ -0,0 +1,110 @@ +/* + Copyright (C) 2006 Paul Davis + + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the Free + Software Foundation; either version 2 of the License, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __ardour_buffer_set_h__ +#define __ardour_buffer_set_h__ + +#include <vector> +#include <ardour/buffer.h> +#include <ardour/chan_count.h> +#include <ardour/data_type.h> +#include <ardour/port_set.h> + +namespace ARDOUR { + + +/** A set of buffers of various types. + * + * These are mainly accessed from Session and passed around as scratch buffers + * (eg as parameters to run() methods) to do in-place signal processing. + * + * There are two types of counts associated with a BufferSet - available, + * and the 'use count'. Available is the actual number of allocated buffers + * (and so is the maximum acceptable value for the use counts). + * + * The use counts are how things determine the form of their input and inform + * others the form of their output (eg what they did to the BufferSet). + * Setting the use counts is realtime safe. + */ +class BufferSet +{ +public: + BufferSet(const PortSet& ports); + BufferSet(); + ~BufferSet(); + + void clear(); + + void ensure_buffers(const ChanCount& chan_count, size_t buffer_capacity); + void ensure_buffers(size_t num_buffers, DataType type, size_t buffer_capacity); + + // FIXME: add these + //const ChanCount& available() const { return _count; } + //ChanCount& available() { return _count; } + + const ChanCount& count() const { return _count; } + ChanCount& count() { return _count; } + + size_t available_buffers(DataType type) const; + size_t buffer_capacity(DataType type) const; + + Buffer& buffer(DataType type, size_t i) + { + assert(i <= _count.get(type)); + return *_buffers[type.to_index()][i]; + } + + AudioBuffer& audio_buffer(size_t i) + { + return (AudioBuffer&)buffer(DataType::AUDIO, i); + } + #if 0 + /** See PortInsert::run for an example of usage */ + class IndexSet { + public: + IndexSet() { reset(); } + + void reset() { _is[0] = 0; _is[1] = 0; } + + size_t index(DataType type) { return _is[type.to_index()]; } + void increment(DataType type) { _is[type.to_index()] += 1; } + + private: + int _is[2]; + }; + #endif + + const ChanCount& chan_count() const { return _count; } + +private: + typedef std::vector<Buffer*> BufferVec; + + /// Vector of vectors, indexed by DataType::to_index() + std::vector<BufferVec> _buffers; + + /// Use counts (there may be more actual buffers than this) + ChanCount _count; + + /// Whether we (don't) 'own' the contained buffers (are a mirror of a PortSet) + bool _is_mirror; +}; + + +} // namespace ARDOUR + +#endif // __ardour_buffer_set_h__ diff --git a/libs/ardour/ardour/chan_count.h b/libs/ardour/ardour/chan_count.h index 2ef49793d1..67ad5406e3 100644 --- a/libs/ardour/ardour/chan_count.h +++ b/libs/ardour/ardour/chan_count.h @@ -34,7 +34,7 @@ public: ChanCount(DataType type, size_t channels) { reset(); - set_count(type, channels); + set(type, channels); } void reset() @@ -44,10 +44,10 @@ public: } } - void set_count(DataType type, size_t count) { _counts[type.to_index()] = count; } - size_t get_count(DataType type) const { return _counts[type.to_index()]; } + void set(DataType type, size_t count) { _counts[type.to_index()] = count; } + size_t get(DataType type) const { return _counts[type.to_index()]; } - size_t get_total_count() const + size_t get_total() const { size_t ret = 0; for (size_t i=0; i < DataType::num_types; ++i) @@ -70,7 +70,51 @@ public: return ! (*this == other); } + bool operator<(const ChanCount& other) const + { + for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) { + if (_counts[(*t).to_index()] >= other._counts[(*t).to_index()]) { + return false; + } + } + return true; + } + + bool operator<=(const ChanCount& other) const + { + for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) { + if (_counts[(*t).to_index()] > other._counts[(*t).to_index()]) { + return false; + } + } + return true; + } + + bool operator>(const ChanCount& other) const + { + for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) { + if (_counts[(*t).to_index()] <= other._counts[(*t).to_index()]) { + return false; + } + } + return true; + } + + bool operator>=(const ChanCount& other) const + { + for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) { + if (_counts[(*t).to_index()] < other._counts[(*t).to_index()]) { + return false; + } + } + return true; + } + + static const ChanCount INFINITE; + static const ChanCount ZERO; + private: + size_t _counts[DataType::num_types]; }; diff --git a/libs/ardour/ardour/io.h b/libs/ardour/ardour/io.h index 818916f185..a4b50618bb 100644 --- a/libs/ardour/ardour/io.h +++ b/libs/ardour/ardour/io.h @@ -41,6 +41,7 @@ #include <ardour/types.h> #include <ardour/data_type.h> #include <ardour/port_set.h> +#include <ardour/chan_count.h> using std::string; using std::vector; @@ -72,14 +73,20 @@ class IO : public Stateful, public ARDOUR::StateManager int input_min = -1, int input_max = -1, int output_min = -1, int output_max = -1, DataType default_type = DataType::AUDIO); - + virtual ~IO(); - int input_minimum() const { return _input_minimum; } - int input_maximum() const { return _input_maximum; } - int output_minimum() const { return _output_minimum; } - int output_maximum() const { return _output_maximum; } + ChanCount input_minimum() const { return _input_minimum; } + ChanCount input_maximum() const { return _input_maximum; } + ChanCount output_minimum() const { return _output_minimum; } + ChanCount output_maximum() const { return _output_maximum; } + void set_input_minimum (ChanCount n); + void set_input_maximum (ChanCount n); + void set_output_minimum (ChanCount n); + void set_output_maximum (ChanCount n); + + // Do not write any new code using these void set_input_minimum (int n); void set_input_maximum (int n); void set_output_minimum (int n); @@ -162,8 +169,8 @@ class IO : public Stateful, public ARDOUR::StateManager MidiPort* midi_input(uint32_t n) const; MidiPort* midi_output(uint32_t n) const; - uint32_t n_inputs () const { return _inputs.num_ports(); } - uint32_t n_outputs () const { return _outputs.num_ports(); } + const ChanCount& n_inputs () const { return _inputs.chan_count(); } + const ChanCount& n_outputs () const { return _outputs.chan_count(); } sigc::signal<void,IOChange,void*> input_changed; sigc::signal<void,IOChange,void*> output_changed; @@ -193,7 +200,7 @@ class IO : public Stateful, public ARDOUR::StateManager static sigc::signal<int> PortsLegal; static sigc::signal<int> PannersLegal; static sigc::signal<int> ConnectingLegal; - static sigc::signal<void,uint32_t> MoreOutputs; + static sigc::signal<void,ChanCount> MoreOutputs; static sigc::signal<int> PortsCreated; PBD::Controllable& gain_control() { @@ -203,7 +210,8 @@ class IO : public Stateful, public ARDOUR::StateManager /* Peak metering */ float peak_input_power (uint32_t n) { - if (n < std::max (n_inputs(), n_outputs())) { + if (n < std::max (_inputs.chan_count().get(DataType::AUDIO), + _outputs.chan_count().get(DataType::AUDIO))) { return _visible_peak_power[n]; } else { return minus_infinity(); @@ -300,7 +308,8 @@ public: void reset_peak_meters(); void reset_panner (); - virtual uint32_t pans_required() const { return n_inputs(); } + virtual uint32_t pans_required() const + { return _inputs.chan_count().get(DataType::AUDIO); } static void apply_declick (vector<Sample*>&, uint32_t nbufs, jack_nframes_t nframes, gain_t initial, gain_t target, bool invert_polarity); @@ -363,10 +372,10 @@ public: sigc::connection port_legal_c; sigc::connection panner_legal_c; - int _input_minimum; - int _input_maximum; - int _output_minimum; - int _output_maximum; + ChanCount _input_minimum; + ChanCount _input_maximum; + ChanCount _output_minimum; + ChanCount _output_maximum; static int parse_io_string (const string&, vector<string>& chns); diff --git a/libs/ardour/ardour/port_set.h b/libs/ardour/ardour/port_set.h index f8975325a0..d38aab2c4b 100644 --- a/libs/ardour/ardour/port_set.h +++ b/libs/ardour/ardour/port_set.h @@ -60,7 +60,7 @@ public: const ChanCount& chan_count() const { return _chan_count; } - bool empty() const { return (_chan_count.get_total_count() == 0); } + bool empty() const { return (_chan_count.get_total() == 0); } // ITERATORS @@ -85,7 +85,7 @@ public: }; iterator begin() { return iterator(*this, 0); } - iterator end() { return iterator(*this, _chan_count.get_total_count()); } + iterator end() { return iterator(*this, _chan_count.get_total()); } class const_iterator { public: @@ -105,7 +105,7 @@ public: }; const_iterator begin() const { return const_iterator(*this, 0); } - const_iterator end() const { return const_iterator(*this, _chan_count.get_total_count()); } + const_iterator end() const { return const_iterator(*this, _chan_count.get_total()); } @@ -127,7 +127,7 @@ public: }; audio_iterator audio_begin() { return audio_iterator(*this, 0); } - audio_iterator audio_end() { return audio_iterator(*this, _chan_count.get_count(DataType::AUDIO)); } + audio_iterator audio_end() { return audio_iterator(*this, _chan_count.get(DataType::AUDIO)); } diff --git a/libs/ardour/ardour/redirect.h b/libs/ardour/ardour/redirect.h index 658cab5d3b..4e6ef5124c 100644 --- a/libs/ardour/ardour/redirect.h +++ b/libs/ardour/ardour/redirect.h @@ -70,10 +70,10 @@ class Redirect : public IO bool active () const { return _active; } void set_active (bool yn, void *src); - virtual uint32_t output_streams() const { return n_outputs(); } - virtual uint32_t input_streams () const { return n_inputs(); } - virtual uint32_t natural_output_streams() const { return n_outputs(); } - virtual uint32_t natural_input_streams () const { return n_inputs(); } + virtual uint32_t output_streams() const { return n_outputs().get(_default_type); } + virtual uint32_t input_streams () const { return n_inputs().get(_default_type); } + virtual uint32_t natural_output_streams() const { return n_outputs().get(_default_type); } + virtual uint32_t natural_input_streams () const { return n_inputs().get(_default_type); } uint32_t sort_key() const { return _sort_key; } void set_sort_key (uint32_t key); diff --git a/libs/ardour/ardour/session.h b/libs/ardour/ardour/session.h index 7331cbb5db..5cffe8a7c6 100644 --- a/libs/ardour/ardour/session.h +++ b/libs/ardour/ardour/session.h @@ -1091,7 +1091,7 @@ class Session : public sigc::trackable, public Stateful void update_latency_compensation_proxy (void* ignored); - void ensure_passthru_buffers (uint32_t howmany); + void ensure_passthru_buffers (ChanCount howmany); void process_scrub (jack_nframes_t); void process_without_events (jack_nframes_t); diff --git a/libs/ardour/audio_diskstream.cc b/libs/ardour/audio_diskstream.cc index 1b9d7d339d..04fb95ce62 100644 --- a/libs/ardour/audio_diskstream.cc +++ b/libs/ardour/audio_diskstream.cc @@ -212,21 +212,21 @@ AudioDiskstream::non_realtime_input_change () if (input_change_pending & ConfigurationChanged) { - if (_io->n_inputs() > _n_channels) { + if (_io->n_inputs().get(DataType::AUDIO) > _n_channels) { // we need to add new channel infos - int diff = _io->n_inputs() - channels.size(); + int diff = _io->n_inputs().get(DataType::AUDIO) - channels.size(); for (int i = 0; i < diff; ++i) { add_channel (); } - } else if (_io->n_inputs() < _n_channels) { + } else if (_io->n_inputs().get(DataType::AUDIO) < _n_channels) { // we need to get rid of channels - int diff = channels.size() - _io->n_inputs(); + int diff = channels.size() - _io->n_inputs().get(DataType::AUDIO); for (int i = 0; i < diff; ++i) { remove_channel (); @@ -264,7 +264,7 @@ AudioDiskstream::non_realtime_input_change () void AudioDiskstream::get_input_sources () { - uint32_t ni = _io->n_inputs(); + uint32_t ni = _io->n_inputs().get(DataType::AUDIO); for (uint32_t n = 0; n < ni; ++n) { diff --git a/libs/ardour/audio_track.cc b/libs/ardour/audio_track.cc index 409b0e560f..9be139ec72 100644 --- a/libs/ardour/audio_track.cc +++ b/libs/ardour/audio_track.cc @@ -417,7 +417,7 @@ int AudioTrack::no_roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nframes_t end_frame, jack_nframes_t offset, bool session_state_changing, bool can_record, bool rec_monitors_input) { - if (n_outputs() == 0) { + if (n_outputs().get_total() == 0) { return 0; } @@ -512,7 +512,7 @@ AudioTrack::roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nfram } } - if (n_outputs() == 0 && _redirects.empty()) { + if (n_outputs().get_total() == 0 && _redirects.empty()) { return 0; } @@ -609,7 +609,7 @@ int AudioTrack::silent_roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nframes_t end_frame, jack_nframes_t offset, bool can_record, bool rec_monitors_input) { - if (n_outputs() == 0 && _redirects.empty()) { + if (n_outputs().get_total() == 0 && _redirects.empty()) { return 0; } diff --git a/libs/ardour/auditioner.cc b/libs/ardour/auditioner.cc index e48f103b9f..db5296db3d 100644 --- a/libs/ardour/auditioner.cc +++ b/libs/ardour/auditioner.cc @@ -93,7 +93,7 @@ Auditioner::audition_current_playlist () /* force a panner reset now that we have all channels */ - _panner->reset (n_outputs(), _diskstream->n_channels()); + _panner->reset (n_outputs().get(DataType::AUDIO), _diskstream->n_channels()); g_atomic_int_set (&_active, 1); } @@ -126,7 +126,7 @@ Auditioner::audition_region (AudioRegion& region) /* force a panner reset now that we have all channels */ - _panner->reset (n_outputs(), _diskstream->n_channels()); + _panner->reset (n_outputs().get(DataType::AUDIO), _diskstream->n_channels()); length = the_region->length(); _diskstream->seek (0); diff --git a/libs/ardour/buffer_set.cc b/libs/ardour/buffer_set.cc new file mode 100644 index 0000000000..c479b6c405 --- /dev/null +++ b/libs/ardour/buffer_set.cc @@ -0,0 +1,141 @@ +/* + Copyright (C) 2006 Paul Davis + + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the Free + Software Foundation; either version 2 of the License, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include <algorithm> +#include <ardour/buffer_set.h> + +namespace ARDOUR { + + +/** Create a BufferSet to mirror a PortSet */ +BufferSet::BufferSet(const PortSet& ports) + : _count(ports.chan_count()) + , _is_mirror(true) +{ + for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) { + BufferVec v; + + for (size_t j=0; j < ports.num_ports(*t); ++j) { + v.push_back(&ports.nth_port_of_type(*t, j)->get_buffer()); + } + + _buffers.push_back(v); + } +} + +/** Create a new, empty BufferSet */ +BufferSet::BufferSet() + : _is_mirror(false) +{ + for (size_t i=0; i < DataType::num_types; ++i) + _buffers.push_back( BufferVec() ); + + _count.reset(); +} + + +BufferSet::~BufferSet() +{ + if (!_is_mirror) + clear(); +} + + +/** Destroy all contained buffers. + */ +void +BufferSet::clear() +{ + for (std::vector<BufferVec>::iterator i = _buffers.begin(); i != _buffers.end(); ++i) { + for (BufferVec::iterator j = (*i).begin(); j != (*i).end(); ++j) { + delete *j; + } + (*i).clear(); + } + _buffers.clear(); +} + + +void +BufferSet::ensure_buffers(const ChanCount& chan_count, size_t buffer_capacity) +{ + for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) { + ensure_buffers(chan_count.get(*t), *t, buffer_capacity); + } +} + + +/** Ensure that there are @a num_buffers buffers of type @a type available, + * each of size at least @a buffer_size + */ +void +BufferSet::ensure_buffers(size_t num_buffers, DataType type, size_t buffer_capacity) +{ + assert(type != DataType::NIL); + assert(type.to_index() < _buffers.size()); + + if (num_buffers == 0) + return; + + // The vector of buffers of the type we care about + BufferVec& bufs = _buffers[type.to_index()]; + + // If there's not enough or they're too small, just nuke the whole thing and + // rebuild it (so I'm lazy..) + if (bufs.size() < num_buffers + || (bufs.size() > 0 && bufs[0]->capacity() < buffer_capacity)) { + + // Nuke it + for (BufferVec::iterator i = bufs.begin(); i != bufs.end(); ++i) { + delete (*i); + } + bufs.clear(); + + // Rebuild it + for (size_t i=0; i < num_buffers; ++i) { + bufs.push_back(Buffer::create(type, buffer_capacity)); + } + } + + // Post-conditions + assert(bufs.size() >= num_buffers); + assert((bufs[0])->type() == type); + assert(bufs[0]->capacity() >= buffer_capacity); +} + +size_t +BufferSet::available_buffers(DataType type) const +{ + return _buffers[type.to_symbol()-1].size(); +} + + +/** Get the capacity (size) of the available buffers of the given type. + * + * All buffers of a certain type always have the same capacity. + */ +size_t +BufferSet::buffer_capacity(DataType type) const +{ + assert(available_buffers(type) > 0); + return _buffers[type.to_index()][0]->capacity(); +} + + +} // namespace ARDOUR + diff --git a/libs/ardour/chan_count.cc b/libs/ardour/chan_count.cc new file mode 100644 index 0000000000..269f985796 --- /dev/null +++ b/libs/ardour/chan_count.cc @@ -0,0 +1,48 @@ +/* + Copyright (C) 2006 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id: insert.cc 712 2006-07-28 01:08:57Z drobilla $ +*/ + +#define __STDC_LIMIT_MACROS 1 +#include <stdint.h> +#include <ardour/chan_count.h> + +namespace ARDOUR { + +// infinite/zero chan count stuff, for setting minimums and maximums, etc. +// FIXME: implement this in a less fugly way + +ChanCount +infinity_factory() +{ + ChanCount ret; + + for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) { + ret.set(*t, SIZE_MAX); + } + + return ret; +} + + +// Statics +const ChanCount ChanCount::INFINITE = infinity_factory(); +const ChanCount ChanCount::ZERO = ChanCount(); + + +} // namespace ARDOUR diff --git a/libs/ardour/insert.cc b/libs/ardour/insert.cc index 02d7bf0bb6..6bc22de3c1 100644 --- a/libs/ardour/insert.cc +++ b/libs/ardour/insert.cc @@ -85,7 +85,7 @@ PluginInsert::PluginInsert (Session& s, boost::shared_ptr<Plugin> plug, Placemen { Glib::Mutex::Lock em (_session.engine().process_lock()); - IO::MoreOutputs (output_streams ()); + IO::MoreOutputs (ChanCount(_default_type, output_streams())); } RedirectCreated (this); /* EMIT SIGNAL */ @@ -106,7 +106,7 @@ PluginInsert::PluginInsert (Session& s, const XMLNode& node) { Glib::Mutex::Lock em (_session.engine().process_lock()); - IO::MoreOutputs (output_streams()); + IO::MoreOutputs (ChanCount(_default_type, output_streams())); } } @@ -903,7 +903,7 @@ PortInsert::~PortInsert () void PortInsert::run (vector<Sample *>& bufs, uint32_t nbufs, jack_nframes_t nframes, jack_nframes_t offset) { - if (n_outputs() == 0) { + if (n_outputs().get(_default_type) == 0) { return; } @@ -999,7 +999,7 @@ PortInsert::latency() int32_t PortInsert::can_support_input_configuration (int32_t in) const { - if (input_maximum() == -1 && output_maximum() == -1) { + if (input_maximum() == ChanCount::INFINITE && output_maximum() == ChanCount::INFINITE) { /* not configured yet */ @@ -1011,7 +1011,7 @@ PortInsert::can_support_input_configuration (int32_t in) const many output ports it will have. */ - if (output_maximum() == in) { + if (output_maximum().get(_default_type) == static_cast<uint32_t>(in)) { return 1; } } @@ -1042,11 +1042,11 @@ PortInsert::configure_io (int32_t ignored_magic, int32_t in, int32_t out) set_input_minimum (out); if (in < 0) { - in = n_outputs (); + in = n_outputs ().get(_default_type); } if (out < 0) { - out = n_inputs (); + out = n_inputs ().get(_default_type); } return ensure_io (out, in, false, this); @@ -1056,17 +1056,17 @@ int32_t PortInsert::compute_output_streams (int32_t cnt) const { /* puzzling, eh? think about it ... */ - return n_inputs (); + return n_inputs ().get(_default_type); } uint32_t PortInsert::output_streams() const { - return n_inputs (); + return n_inputs ().get(_default_type); } uint32_t PortInsert::input_streams() const { - return n_outputs (); + return n_outputs ().get(_default_type); } diff --git a/libs/ardour/io.cc b/libs/ardour/io.cc index 9a41d74cee..80eeaa1f19 100644 --- a/libs/ardour/io.cc +++ b/libs/ardour/io.cc @@ -14,8 +14,6 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - - $Id$ */ #include <fstream> @@ -62,19 +60,19 @@ using namespace PBD; static float current_automation_version_number = 1.0; -jack_nframes_t IO::_automation_interval = 0; -const string IO::state_node_name = "IO"; -bool IO::connecting_legal = false; -bool IO::ports_legal = false; -bool IO::panners_legal = false; +jack_nframes_t IO::_automation_interval = 0; +const string IO::state_node_name = "IO"; +bool IO::connecting_legal = false; +bool IO::ports_legal = false; +bool IO::panners_legal = false; sigc::signal<void> IO::Meter; sigc::signal<int> IO::ConnectingLegal; sigc::signal<int> IO::PortsLegal; sigc::signal<int> IO::PannersLegal; -sigc::signal<void,uint32_t> IO::MoreOutputs; +sigc::signal<void,ChanCount> IO::MoreOutputs; sigc::signal<int> IO::PortsCreated; -Glib::StaticMutex IO::m_meter_signal_lock = GLIBMM_STATIC_MUTEX_INIT; +Glib::StaticMutex IO::m_meter_signal_lock = GLIBMM_STATIC_MUTEX_INIT; /* this is a default mapper of [0 .. 1.0] control values to a gain coefficient. others can be imagined. @@ -112,10 +110,10 @@ IO::IO (Session& s, string name, _default_type(default_type), _gain_control (*this), _gain_automation_curve (0.0, 2.0, 1.0), - _input_minimum (input_min), - _input_maximum (input_max), - _output_minimum (output_min), - _output_maximum (output_max) + _input_minimum (_default_type, input_min), + _input_maximum (_default_type, input_max), + _output_minimum (_default_type, output_min), + _output_maximum (_default_type, output_max) { _panner = new Panner (name, _session); _gain = 1.0; @@ -228,11 +226,11 @@ IO::pan_automated (vector<Sample*>& bufs, uint32_t nbufs, jack_nframes_t start, /* io_lock, not taken: function must be called from Session::process() calltree */ - if (n_outputs() == 0) { + if (n_outputs().get(DataType::AUDIO) == 0) { return; } - if (n_outputs() == 1) { + if (n_outputs().get(DataType::AUDIO) == 1) { dst = audio_output(0)->get_audio_buffer().data (nframes, offset); @@ -250,7 +248,7 @@ IO::pan_automated (vector<Sample*>& bufs, uint32_t nbufs, jack_nframes_t start, uint32_t o = 0; vector<Sample *>::iterator in; Panner::iterator pan; - Sample* obufs[n_outputs()]; + Sample* obufs[n_outputs().get(DataType::AUDIO)]; /* the terrible silence ... */ for (PortSet::audio_iterator out = _outputs.audio_begin(); out != _outputs.audio_end(); ++out, ++o) { @@ -273,7 +271,7 @@ IO::pan (vector<Sample*>& bufs, uint32_t nbufs, jack_nframes_t nframes, jack_nfr /* io_lock, not taken: function must be called from Session::process() calltree */ - if (n_outputs() == 0) { + if (n_outputs().get(DataType::AUDIO) == 0) { return; } @@ -286,7 +284,7 @@ IO::pan (vector<Sample*>& bufs, uint32_t nbufs, jack_nframes_t nframes, jack_nfr return; } - if (n_outputs() == 1) { + if (n_outputs().get(DataType::AUDIO) == 1) { dst = audio_output(0)->get_audio_buffer().data(nframes, offset); @@ -343,7 +341,7 @@ IO::pan (vector<Sample*>& bufs, uint32_t nbufs, jack_nframes_t nframes, jack_nfr uint32_t o = 0; vector<Sample *>::iterator in; Panner::iterator pan; - Sample* obufs[n_outputs()]; + Sample* obufs[n_outputs().get(DataType::AUDIO)]; /* the terrible silence ... */ @@ -376,7 +374,7 @@ IO::deliver_output (vector<Sample *>& bufs, uint32_t nbufs, jack_nframes_t nfram { /* io_lock, not taken: function must be called from Session::process() calltree */ - if (n_outputs() == 0) { + if (n_outputs().get(DataType::AUDIO) == 0) { return; } @@ -419,7 +417,7 @@ IO::deliver_output_no_pan (vector<Sample *>& bufs, uint32_t nbufs, jack_nframes_ { /* io_lock, not taken: function must be called from Session::process() calltree */ - if (n_outputs() == 0) { + if (n_outputs().get(DataType::AUDIO) == 0) { return; } @@ -520,7 +518,7 @@ IO::collect_input (vector<Sample *>& bufs, uint32_t nbufs, jack_nframes_t nframe have to do. Hack? Why yes .. we only need to read nframes-worth of - data, but the data we want is at `offset' within the + data, but the data we want is at 'offset' within the buffer. */ @@ -716,13 +714,13 @@ IO::set_input (Port* other_port, void* src) to the specified source. */ - if (_input_minimum > 1 || _input_minimum == 0) { + if (_input_minimum.get_total() > 1) { /* sorry, you can't do this */ return -1; } if (other_port == 0) { - if (_input_minimum < 0) { + if (_input_minimum == ChanCount::ZERO) { return ensure_inputs (0, false, true, src); } else { return -1; @@ -807,14 +805,14 @@ IO::add_output_port (string destination, void* src, DataType type) { Glib::Mutex::Lock lm (io_lock); - if (_output_maximum >= 0 && (int) n_outputs() == _output_maximum) { + if (n_outputs() >= _output_maximum) { return -1; } /* Create a new output port */ // FIXME: naming scheme for differently typed ports? - if (_output_maximum == 1) { + if (_output_maximum.get_total() == 1) { snprintf (name, sizeof (name), _("%s/out"), _name.c_str()); } else { snprintf (name, sizeof (name), _("%s/out %u"), _name.c_str(), find_output_port_hole()); @@ -920,14 +918,14 @@ IO::add_input_port (string source, void* src, DataType type) { Glib::Mutex::Lock lm (io_lock); - if (_input_maximum >= 0 && (int) n_inputs() == _input_maximum) { + if (n_inputs() >= _input_maximum) { return -1; } /* Create a new input port */ // FIXME: naming scheme for differently typed ports? - if (_input_maximum == 1) { + if (_input_maximum.get_total() == 1) { snprintf (name, sizeof (name), _("%s/in"), _name.c_str()); } else { snprintf (name, sizeof (name), _("%s/in %u"), _name.c_str(), find_input_port_hole()); @@ -1014,7 +1012,7 @@ IO::ensure_inputs_locked (uint32_t n, bool clear, void* src) /* remove unused ports */ - while (n_inputs() > n) { + while (n_inputs().get(_default_type) > n) { throw; // FIXME /* _session.engine().unregister_port (_inputs.back()); @@ -1026,13 +1024,13 @@ IO::ensure_inputs_locked (uint32_t n, bool clear, void* src) /* create any necessary new ports */ - while (n_inputs() < n) { + while (n_inputs().get(_default_type) < n) { char buf[64]; /* Create a new input port (of the default type) */ - if (_input_maximum == 1) { + if (_input_maximum.get_total() == 1) { snprintf (buf, sizeof (buf), _("%s/in"), _name.c_str()); } else { @@ -1084,15 +1082,11 @@ IO::ensure_io (uint32_t nin, uint32_t nout, bool clear, void* src) bool out_changed = false; bool need_pan_reset; - if (_input_maximum >= 0) { - nin = min (_input_maximum, (int) nin); - } + nin = min (_input_maximum.get(_default_type), static_cast<size_t>(nin)); - if (_output_maximum >= 0) { - nout = min (_output_maximum, (int) nout); - } + nout = min (_output_maximum.get(_default_type), static_cast<size_t>(nout)); - if (nin == n_inputs() && nout == n_outputs() && !clear) { + if (nin == n_inputs().get(_default_type) && nout == n_outputs().get(_default_type) && !clear) { return 0; } @@ -1102,7 +1096,7 @@ IO::ensure_io (uint32_t nin, uint32_t nout, bool clear, void* src) Port* port; - if (n_outputs() == nout) { + if (n_outputs().get(_default_type) == nout) { need_pan_reset = false; } else { need_pan_reset = true; @@ -1110,7 +1104,7 @@ IO::ensure_io (uint32_t nin, uint32_t nout, bool clear, void* src) /* remove unused ports */ - while (n_inputs() > nin) { + while (n_inputs().get(_default_type) > nin) { throw; // FIXME /* _session.engine().unregister_port (_inputs.back()); @@ -1119,7 +1113,7 @@ IO::ensure_io (uint32_t nin, uint32_t nout, bool clear, void* src) in_changed = true;*/ } - while (n_outputs() > nout) { + while (n_outputs().get(_default_type) > nout) { throw; // FIXME /* _session.engine().unregister_port (_outputs.back()); @@ -1130,13 +1124,13 @@ IO::ensure_io (uint32_t nin, uint32_t nout, bool clear, void* src) /* create any necessary new ports (of the default type) */ - while (n_inputs() < nin) { + while (n_inputs().get(_default_type) < nin) { char buf[64]; /* Create a new input port */ - if (_input_maximum == 1) { + if (_input_maximum.get_total() == 1) { snprintf (buf, sizeof (buf), _("%s/in"), _name.c_str()); } else { @@ -1163,13 +1157,13 @@ IO::ensure_io (uint32_t nin, uint32_t nout, bool clear, void* src) /* create any necessary new ports */ - while (n_outputs() < nout) { + while (n_outputs().get(_default_type) < nout) { char buf[64]; /* Create a new output port */ - if (_output_maximum == 1) { + if (_output_maximum.get_total() == 1) { snprintf (buf, sizeof (buf), _("%s/out"), _name.c_str()); } else { snprintf (buf, sizeof (buf), _("%s/out %u"), _name.c_str(), find_output_port_hole()); @@ -1235,14 +1229,12 @@ IO::ensure_inputs (uint32_t n, bool clear, bool lockit, void* src) { bool changed = false; - if (_input_maximum >= 0) { - n = min (_input_maximum, (int) n); - - if (n == n_inputs() && !clear) { - return 0; - } + n = min (_input_maximum.get(_default_type), static_cast<size_t>(n)); + + if (n == n_inputs().get(_default_type) && !clear) { + return 0; } - + if (lockit) { Glib::Mutex::Lock em (_session.engine().process_lock()); Glib::Mutex::Lock im (io_lock); @@ -1265,7 +1257,7 @@ IO::ensure_outputs_locked (uint32_t n, bool clear, void* src) bool changed = false; bool need_pan_reset; - if (n_outputs() == n) { + if (n_outputs().get(_default_type) == n) { need_pan_reset = false; } else { need_pan_reset = true; @@ -1273,7 +1265,7 @@ IO::ensure_outputs_locked (uint32_t n, bool clear, void* src) /* remove unused ports */ - while (n_outputs() > n) { + while (n_outputs().get(_default_type) > n) { throw; // FIXME /* _session.engine().unregister_port (_outputs.back()); @@ -1285,13 +1277,13 @@ IO::ensure_outputs_locked (uint32_t n, bool clear, void* src) /* create any necessary new ports */ - while (n_outputs() < n) { + while (n_outputs().get(_default_type) < n) { char buf[64]; /* Create a new output port */ - if (_output_maximum == 1) { + if (_output_maximum.get(_default_type) == 1) { snprintf (buf, sizeof (buf), _("%s/out"), _name.c_str()); } else { snprintf (buf, sizeof (buf), _("%s/out %u"), _name.c_str(), find_output_port_hole()); @@ -1333,9 +1325,9 @@ IO::ensure_outputs (uint32_t n, bool clear, bool lockit, void* src) { bool changed = false; - if (_output_maximum >= 0) { - n = min (_output_maximum, (int) n); - if (n == n_outputs() && !clear) { + if (_output_maximum < ChanCount::INFINITE) { + n = min (_output_maximum.get(_default_type), static_cast<size_t>(n)); + if (n == n_outputs().get(_default_type) && !clear) { return 0; } } @@ -1371,7 +1363,7 @@ IO::reset_panner () { if (panners_legal) { if (!no_panner_reset) { - _panner->reset (n_outputs(), pans_required()); + _panner->reset (n_outputs().get(_default_type), pans_required()); } } else { panner_legal_c.disconnect (); @@ -1382,7 +1374,7 @@ IO::reset_panner () int IO::panners_became_legal () { - _panner->reset (n_outputs(), pans_required()); + _panner->reset (n_outputs().get(_default_type), pans_required()); _panner->load (); // automation panner_legal_c.disconnect (); return 0; @@ -1506,11 +1498,12 @@ IO::state (bool full_state) snprintf (buf, sizeof(buf), "%2.12f", gain()); node->add_property ("gain", buf); - snprintf (buf, sizeof(buf)-1, "%d,%d,%d,%d", - _input_minimum, - _input_maximum, - _output_minimum, - _output_maximum); + const int in_min = (_input_minimum == ChanCount::ZERO) ? -1 : _input_minimum.get(_default_type); + const int in_max = (_input_maximum == ChanCount::INFINITE) ? -1 : _input_maximum.get(_default_type); + const int out_min = (_output_minimum == ChanCount::ZERO) ? -1 : _output_minimum.get(_default_type); + const int out_max = (_output_maximum == ChanCount::INFINITE) ? -1 : _output_maximum.get(_default_type); + + snprintf (buf, sizeof(buf)-1, "%d,%d,%d,%d", in_min, in_max, out_min, out_max); node->add_property ("iolimits", buf); @@ -1602,12 +1595,18 @@ IO::set_state (const XMLNode& node) _id = prop->value (); } + size_t in_min = -1; + size_t in_max = -1; + size_t out_min = -1; + size_t out_max = -1; + if ((prop = node.property ("iolimits")) != 0) { - sscanf (prop->value().c_str(), "%d,%d,%d,%d", - &_input_minimum, - &_input_maximum, - &_output_minimum, - &_output_maximum); + sscanf (prop->value().c_str(), "%zd,%zd,%zd,%zd", + &in_min, &in_max, &out_min, &out_max); + _input_minimum = ChanCount(_default_type, in_min); + _input_maximum = ChanCount(_default_type, in_max); + _output_minimum = ChanCount(_default_type, out_min); + _output_maximum = ChanCount(_default_type, out_max); } if ((prop = node.property ("gain")) != 0) { @@ -1972,24 +1971,60 @@ IO::set_name (string name, void* src) void IO::set_input_minimum (int n) { - _input_minimum = n; + if (n < 0) + _input_minimum = ChanCount::ZERO; + else + _input_minimum = ChanCount(_default_type, n); } void IO::set_input_maximum (int n) { - _input_maximum = n; + if (n < 0) + _input_maximum = ChanCount::INFINITE; + else + _input_maximum = ChanCount(_default_type, n); } void IO::set_output_minimum (int n) { - _output_minimum = n; + if (n < 0) + _output_minimum = ChanCount::ZERO; + else + _output_minimum = ChanCount(_default_type, n); } void IO::set_output_maximum (int n) { + if (n < 0) + _output_maximum = ChanCount::INFINITE; + else + _output_maximum = ChanCount(_default_type, n); +} + +void +IO::set_input_minimum (ChanCount n) +{ + _input_minimum = n; +} + +void +IO::set_input_maximum (ChanCount n) +{ + _input_maximum = n; +} + +void +IO::set_output_minimum (ChanCount n) +{ + _output_minimum = n; +} + +void +IO::set_output_maximum (ChanCount n) +{ _output_maximum = n; } @@ -2279,7 +2314,7 @@ IO::GainControllable::get_value (void) const void IO::reset_peak_meters () { - uint32_t limit = max (n_inputs(), n_outputs()); + uint32_t limit = max (n_inputs().get(DataType::AUDIO), n_outputs().get(DataType::AUDIO)); for (uint32_t i = 0; i < limit; ++i) { _peak_power[i] = 0; @@ -2289,7 +2324,7 @@ IO::reset_peak_meters () void IO::setup_peak_meters () { - uint32_t limit = max (n_inputs(), n_outputs()); + uint32_t limit = max (n_inputs().get(DataType::AUDIO), n_outputs().get(DataType::AUDIO)); while (_peak_power.size() < limit) { _peak_power.push_back (0); @@ -2336,7 +2371,7 @@ void IO::meter () { Glib::Mutex::Lock lm (io_lock); // READER: meter thread. - uint32_t limit = max (n_inputs(), n_outputs()); + uint32_t limit = max (n_inputs().get(DataType::AUDIO), n_outputs().get(DataType::AUDIO)); for (uint32_t n = 0; n < limit; ++n) { diff --git a/libs/ardour/midi_diskstream.cc b/libs/ardour/midi_diskstream.cc index 8722c65a5f..4d35e5f5fc 100644 --- a/libs/ardour/midi_diskstream.cc +++ b/libs/ardour/midi_diskstream.cc @@ -148,7 +148,7 @@ MidiDiskstream::non_realtime_input_change () if (input_change_pending & ConfigurationChanged) { - assert(_io->n_inputs() == _n_channels); + assert(_io->n_inputs().get(DataType::MIDI) == _n_channels); } get_input_sources (); diff --git a/libs/ardour/midi_track.cc b/libs/ardour/midi_track.cc index 93eba11a30..f27984bb49 100644 --- a/libs/ardour/midi_track.cc +++ b/libs/ardour/midi_track.cc @@ -403,7 +403,7 @@ int MidiTrack::no_roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nframes_t end_frame, jack_nframes_t offset, bool session_state_changing, bool can_record, bool rec_monitors_input) { - if (n_outputs() == 0) { + if (n_outputs().get(DataType::MIDI) == 0) { return 0; } @@ -490,7 +490,7 @@ int MidiTrack::silent_roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nframes_t end_frame, jack_nframes_t offset, bool can_record, bool rec_monitors_input) { - if (n_outputs() == 0 && _redirects.empty()) { + if (n_outputs().get(DataType::MIDI) == 0 && _redirects.empty()) { return 0; } diff --git a/libs/ardour/port_set.cc b/libs/ardour/port_set.cc index 22fb032c09..31f06cb139 100644 --- a/libs/ardour/port_set.cc +++ b/libs/ardour/port_set.cc @@ -42,9 +42,9 @@ PortSet::add_port(Port* port) v.push_back(port); sort(v.begin(), v.end(), sort_ports_by_name); - _chan_count.set_count(port->type(), _chan_count.get_count(port->type()) + 1); + _chan_count.set(port->type(), _chan_count.get(port->type()) + 1); - assert(_chan_count.get_count(port->type()) == _ports[port->type().to_index()].size()); + assert(_chan_count.get(port->type()) == _ports[port->type().to_index()].size()); } diff --git a/libs/ardour/route.cc b/libs/ardour/route.cc index be0ec61a8d..0e132f6412 100644 --- a/libs/ardour/route.cc +++ b/libs/ardour/route.cc @@ -587,7 +587,7 @@ Route::process_output_buffers (vector<Sample*>& bufs, uint32_t nbufs, solo_audible = dsg > 0; mute_audible = dmg > 0 || !_mute_affects_main_outs; - if (n_outputs() == 0) { + if (n_outputs().get(_default_type) == 0) { /* relax */ @@ -647,12 +647,12 @@ Route::process_output_buffers (vector<Sample*>& bufs, uint32_t nbufs, // cerr << "meter post" << endl; if ((_gain == 0 && !apply_gain_automation) || dmg == 0) { - uint32_t no = n_outputs(); + uint32_t no = n_outputs().get(DataType::AUDIO); for (n = 0; n < no; ++n) { _peak_power[n] = 0; } } else { - uint32_t no = n_outputs(); + uint32_t no = n_outputs().get(DataType::AUDIO); for (n = 0; n < no; ++n) { _peak_power[n] = Session::compute_peak (audio_output(n)->get_audio_buffer ().data(nframes, offset), nframes, _peak_power[n]); } @@ -663,7 +663,7 @@ Route::process_output_buffers (vector<Sample*>& bufs, uint32_t nbufs, uint32_t Route::n_process_buffers () { - return max (n_inputs(), redirect_max_outs); + return max (n_inputs().get(_default_type), static_cast<size_t>(redirect_max_outs)); } void @@ -801,7 +801,7 @@ Route::add_redirect (boost::shared_ptr<Redirect> redirect, void *src, uint32_t* */ - porti->ensure_io (n_outputs (), n_inputs(), false, this); + porti->ensure_io (n_outputs ().get(DataType::AUDIO), n_inputs().get(DataType::AUDIO), false, this); } // Ensure peak vector sizes before the plugin is activated @@ -1074,7 +1074,7 @@ Route::_reset_plugin_counts (uint32_t* err_streams) /* A: PreFader */ - if (check_some_plugin_counts (insert_map[PreFader], n_inputs (), err_streams)) { + if (check_some_plugin_counts (insert_map[PreFader], n_inputs ().get(_default_type), err_streams)) { return -1; } @@ -1084,7 +1084,7 @@ Route::_reset_plugin_counts (uint32_t* err_streams) InsertCount& ic (insert_map[PreFader].back()); initial_streams = ic.insert->compute_output_streams (ic.cnt); } else { - initial_streams = n_inputs (); + initial_streams = n_inputs ().get(_default_type); } /* B: PostFader */ @@ -1110,13 +1110,13 @@ Route::_reset_plugin_counts (uint32_t* err_streams) if ((s = boost::dynamic_pointer_cast<Send> (*r)) != 0) { if (r == _redirects.begin()) { - s->expect_inputs (n_inputs()); + s->expect_inputs (n_inputs().get(_default_type)); } else { s->expect_inputs ((*prev)->output_streams()); } } - redirect_max_outs = max ((*r)->output_streams (), redirect_max_outs); + redirect_max_outs = max ((*r)->output_streams(), redirect_max_outs); } /* we're done */ @@ -1761,7 +1761,7 @@ Route::set_control_outs (const vector<string>& ports) have outputs. we track the changes in ::output_change_handler(). */ - _control_outs->ensure_io (0, n_outputs(), true, this); + _control_outs->ensure_io (0, n_outputs().get(DataType::AUDIO), true, this); return 0; } @@ -1836,8 +1836,8 @@ Route::feeds (boost::shared_ptr<Route> other) uint32_t i, j; IO& self = *this; - uint32_t no = self.n_outputs(); - uint32_t ni = other->n_inputs (); + uint32_t no = self.n_outputs().get_total(); + uint32_t ni = other->n_inputs ().get_total(); for (i = 0; i < no; ++i) { for (j = 0; j < ni; ++j) { @@ -1851,7 +1851,7 @@ Route::feeds (boost::shared_ptr<Route> other) for (RedirectList::iterator r = _redirects.begin(); r != _redirects.end(); r++) { - no = (*r)->n_outputs(); + no = (*r)->n_outputs().get_total(); for (i = 0; i < no; ++i) { for (j = 0; j < ni; ++j) { @@ -1866,7 +1866,7 @@ Route::feeds (boost::shared_ptr<Route> other) if (_control_outs) { - no = _control_outs->n_outputs(); + no = _control_outs->n_outputs().get_total(); for (i = 0; i < no; ++i) { for (j = 0; j < ni; ++j) { @@ -1990,7 +1990,7 @@ Route::output_change_handler (IOChange change, void *ignored) { if (change & ConfigurationChanged) { if (_control_outs) { - _control_outs->ensure_io (0, n_outputs(), true, this); + _control_outs->ensure_io (0, n_outputs().get(DataType::AUDIO), true, this); } reset_plugin_counts (0); @@ -2000,18 +2000,18 @@ Route::output_change_handler (IOChange change, void *ignored) uint32_t Route::pans_required () const { - if (n_outputs() < 2) { + if (n_outputs().get(DataType::AUDIO) < 2) { return 0; } - return max (n_inputs (), redirect_max_outs); + return max (n_inputs ().get(DataType::AUDIO), static_cast<size_t>(redirect_max_outs)); } int Route::no_roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nframes_t end_frame, jack_nframes_t offset, bool session_state_changing, bool can_record, bool rec_monitors_input) { - if (n_outputs() == 0) { + if (n_outputs().get(_default_type) == 0) { return 0; } @@ -2022,7 +2022,7 @@ Route::no_roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nframes apply_gain_automation = false; - if (n_inputs()) { + if (n_inputs().get(_default_type)) { passthru (start_frame, end_frame, nframes, offset, 0, false); } else { silence (nframes, offset); @@ -2069,7 +2069,7 @@ Route::roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nframes_t } } - if ((n_outputs() == 0 && _redirects.empty()) || n_inputs() == 0 || !_active) { + if ((n_outputs().get_total() == 0 && _redirects.empty()) || n_inputs().get_total() == 0 || !_active) { silence (nframes, offset); return 0; } @@ -2126,7 +2126,7 @@ Route::has_external_redirects () const for (RedirectList::const_iterator i = _redirects.begin(); i != _redirects.end(); ++i) { if ((pi = boost::dynamic_pointer_cast<const PortInsert>(*i)) != 0) { - uint32_t no = pi->n_outputs(); + uint32_t no = pi->n_outputs().get(_default_type); for (uint32_t n = 0; n < no; ++n) { diff --git a/libs/ardour/send.cc b/libs/ardour/send.cc index fbbedf7953..691173c26f 100644 --- a/libs/ardour/send.cc +++ b/libs/ardour/send.cc @@ -123,7 +123,7 @@ Send::run (vector<Sample *>& bufs, uint32_t nbufs, jack_nframes_t nframes, jack_ if (_metering) { uint32_t n; - uint32_t no = n_outputs(); + uint32_t no = n_outputs().get(DataType::AUDIO); if (_gain == 0) { @@ -144,7 +144,7 @@ Send::run (vector<Sample *>& bufs, uint32_t nbufs, jack_nframes_t nframes, jack_ if (_metering) { uint32_t n; - uint32_t no = n_outputs(); + uint32_t no = n_outputs().get(DataType::AUDIO); for (n = 0; n < no; ++n) { _peak_power[n] = 0; diff --git a/libs/ardour/session.cc b/libs/ardour/session.cc index 6dd6216242..0e71b19316 100644 --- a/libs/ardour/session.cc +++ b/libs/ardour/session.cc @@ -719,7 +719,8 @@ Session::when_engine_running () _master_out->defer_pan_reset (); - while ((int) _master_out->n_inputs() < _master_out->input_maximum()) { + while (_master_out->n_inputs().get(DataType::AUDIO) + < _master_out->input_maximum().get(DataType::AUDIO)) { if (_master_out->add_input_port ("", this, DataType::AUDIO)) { error << _("cannot setup master inputs") << endmsg; @@ -727,7 +728,8 @@ Session::when_engine_running () } } n = 0; - while ((int) _master_out->n_outputs() < _master_out->output_maximum()) { + while (_master_out->n_outputs().get(DataType::AUDIO) + < _master_out->output_maximum().get(DataType::AUDIO)) { if (_master_out->add_output_port (_engine.get_nth_physical_output (DataType::AUDIO, n), this, DataType::AUDIO)) { error << _("cannot setup master outputs") << endmsg; @@ -742,7 +744,7 @@ Session::when_engine_running () Connection* c = new OutputConnection (_("Master Out"), true); - for (uint32_t n = 0; n < _master_out->n_inputs (); ++n) { + for (uint32_t n = 0; n < _master_out->n_inputs ().get_total(); ++n) { c->add_port (); c->add_connection ((int) n, _master_out->input(n)->name()); } @@ -810,7 +812,7 @@ Session::hookup_io () if (_control_out) { uint32_t n; - while ((int) _control_out->n_inputs() < _control_out->input_maximum()) { + while (_control_out->n_inputs().get(DataType::AUDIO) < _control_out->input_maximum().get(DataType::AUDIO)) { if (_control_out->add_input_port ("", this)) { error << _("cannot setup control inputs") << endmsg; @@ -818,7 +820,7 @@ Session::hookup_io () } } n = 0; - while ((int) _control_out->n_outputs() < _control_out->output_maximum()) { + while (_control_out->n_outputs().get(DataType::AUDIO) < _control_out->output_maximum().get(DataType::AUDIO)) { if (_control_out->add_output_port (_engine.get_nth_physical_output (DataType::AUDIO, n), this)) { error << _("cannot set up master outputs") << endmsg; @@ -1458,7 +1460,7 @@ Session::set_block_size (jack_nframes_t nframes) _passthru_buffers.clear (); _silent_buffers.clear (); - ensure_passthru_buffers (np); + ensure_passthru_buffers (ChanCount(DataType::AUDIO, np)); for (vector<Sample*>::iterator i = _send_buffers.begin(); i != _send_buffers.end(); ++i) { free(*i); @@ -1685,7 +1687,7 @@ Session::new_midi_track (TrackMode mode) if (dynamic_cast<MidiTrack*>((*i).get()) != 0) { if (!(*i)->hidden()) { n++; - channels_used += (*i)->n_inputs(); + channels_used += (*i)->n_inputs().get(DataType::MIDI); } } } @@ -1880,7 +1882,7 @@ Session::new_audio_track (int input_channels, int output_channels, TrackMode mod if (dynamic_cast<AudioTrack*>((*i).get()) != 0) { if (!(*i)->hidden()) { n++; - channels_used += (*i)->n_inputs(); + channels_used += (*i)->n_inputs().get(DataType::AUDIO); } } } @@ -1923,7 +1925,7 @@ Session::new_audio_track (int input_channels, int output_channels, TrackMode mod } if (nphysical_in) { - for (uint32_t x = 0; x < track->n_inputs() && x < nphysical_in; ++x) { + for (uint32_t x = 0; x < track->n_inputs().get(DataType::AUDIO) && x < nphysical_in; ++x) { port = ""; @@ -1937,7 +1939,7 @@ Session::new_audio_track (int input_channels, int output_channels, TrackMode mod } } - for (uint32_t x = 0; x < track->n_outputs(); ++x) { + for (uint32_t x = 0; x < track->n_outputs().get(DataType::AUDIO); ++x) { port = ""; @@ -1945,7 +1947,7 @@ Session::new_audio_track (int input_channels, int output_channels, TrackMode mod port = _engine.get_nth_physical_output (DataType::AUDIO, (channels_used+x)%nphysical_out); } else if (output_auto_connect & AutoConnectMaster) { if (_master_out) { - port = _master_out->input (x%_master_out->n_inputs())->name(); + port = _master_out->audio_input (x%_master_out->n_inputs().get(DataType::AUDIO))->name(); } } @@ -1956,10 +1958,10 @@ Session::new_audio_track (int input_channels, int output_channels, TrackMode mod if (_control_out) { vector<string> cports; - uint32_t ni = _control_out->n_inputs(); + uint32_t ni = _control_out->n_inputs().get(DataType::AUDIO); for (n = 0; n < ni; ++n) { - cports.push_back (_control_out->input(n)->name()); + cports.push_back (_control_out->audio_input(n)->name()); } track->set_control_outs (cports); @@ -2018,7 +2020,7 @@ Session::new_audio_route (int input_channels, int output_channels) << endmsg; } - for (uint32_t x = 0; x < bus->n_inputs(); ++x) { + for (uint32_t x = 0; x < bus->n_inputs().get(DataType::AUDIO); ++x) { port = ""; @@ -2031,7 +2033,7 @@ Session::new_audio_route (int input_channels, int output_channels) } } - for (uint32_t x = 0; x < bus->n_outputs(); ++x) { + for (uint32_t x = 0; x < bus->n_outputs().get(DataType::AUDIO); ++x) { port = ""; @@ -2039,7 +2041,7 @@ Session::new_audio_route (int input_channels, int output_channels) port = _engine.get_nth_physical_input (DataType::AUDIO, (n+x)%n_physical_outputs); } else if (output_auto_connect & AutoConnectMaster) { if (_master_out) { - port = _master_out->input (x%_master_out->n_inputs())->name(); + port = _master_out->audio_input (x%_master_out->n_inputs().get(DataType::AUDIO))->name(); } } @@ -2050,7 +2052,7 @@ Session::new_audio_route (int input_channels, int output_channels) if (_control_out) { vector<string> cports; - uint32_t ni = _control_out->n_inputs(); + uint32_t ni = _control_out->n_inputs().get(DataType::AUDIO); for (uint32_t n = 0; n < ni; ++n) { cports.push_back (_control_out->input(n)->name()); @@ -3656,9 +3658,11 @@ Session::tempo_map_changed (Change ignored) } void -Session::ensure_passthru_buffers (uint32_t howmany) +Session::ensure_passthru_buffers (ChanCount howmany) { - while (howmany > _passthru_buffers.size()) { + // FIXME: temporary hack + + while (howmany.get(DataType::AUDIO) > _passthru_buffers.size()) { Sample *p; #ifdef NO_POSIX_MEMALIGN p = (Sample *) malloc(current_block_size * sizeof(Sample)); @@ -3688,7 +3692,7 @@ Session::ensure_passthru_buffers (uint32_t howmany) _send_buffers.push_back (p); } - allocate_pan_automation_buffers (current_block_size, howmany, false); + allocate_pan_automation_buffers (current_block_size, howmany.get(DataType::AUDIO), false); } string |