diff --git a/gtk2_ardour/io_selector.cc b/gtk2_ardour/io_selector.cc index e53bd2fb02..71e0a84bfd 100644 --- a/gtk2_ardour/io_selector.cc +++ b/gtk2_ardour/io_selector.cc @@ -526,7 +526,9 @@ IOSelector::port_selection_changed (GdkEventButton *ev, TreeView* treeview) if (for_input) { if ((status = io->connect_input (selected_port, other_port_name, this)) == 0) { Port *p = session.engine().get_port_by_name (other_port_name); - p->enable_metering(); + if (p) { + p->enable_metering(); + } } } else { status = io->connect_output (selected_port, other_port_name, this); @@ -664,7 +666,9 @@ IOSelector::connection_button_release (GdkEventButton *ev, TreeView *treeview) if (for_input) { Port *p = session.engine().get_port_by_name (connected_port_name); - p->disable_metering(); + if (p) { + p->disable_metering(); + } io->disconnect_input (port, connected_port_name, this); } else { io->disconnect_output (port, connected_port_name, this); diff --git a/libs/ardour/ardour/audio_track.h b/libs/ardour/ardour/audio_track.h index fe6c88cf7f..1277b598d4 100644 --- a/libs/ardour/ardour/audio_track.h +++ b/libs/ardour/ardour/audio_track.h @@ -64,8 +64,6 @@ class AudioTrack : public Track protected: XMLNode& state (bool full); - ChanCount n_process_buffers (); - private: int set_diskstream (boost::shared_ptr, void *); int deprecated_use_diskstream_connections (); diff --git a/libs/ardour/ardour/io.h b/libs/ardour/ardour/io.h index ec29c6f843..670718bb4e 100644 --- a/libs/ardour/ardour/io.h +++ b/libs/ardour/ardour/io.h @@ -76,7 +76,7 @@ class IO : public PBD::StatefulDestructible, public ARDOUR::StateManager int output_min = -1, int output_max = -1, DataType default_type = DataType::AUDIO); -virtual ~IO(); + virtual ~IO(); ChanCount input_minimum() const { return _input_minimum; } ChanCount input_maximum() const { return _input_maximum; } @@ -107,8 +107,6 @@ virtual ~IO(); void just_meter_input (jack_nframes_t start_frame, jack_nframes_t end_frame, jack_nframes_t nframes, jack_nframes_t offset); - virtual ChanCount n_process_buffers () { return ChanCount::ZERO; } - virtual void set_gain (gain_t g, void *src); void inc_gain (gain_t delta, void *src); gain_t gain () const { return _desired_gain; } @@ -120,8 +118,7 @@ virtual ~IO(); Panner& panner() { return *_panner; } PeakMeter& peak_meter() { return *_meter; } - int ensure_io (uint32_t, uint32_t, bool clear, void *src); - int ensure_io (const ChanCount& in, const ChanCount& out, bool clear, void *src); + int ensure_io (ChanCount in, ChanCount out, bool clear, void *src); int use_input_connection (Connection&, void *src); int use_output_connection (Connection&, void *src); @@ -379,8 +376,8 @@ public: int set_sources (vector&, void *src, bool add); int set_destinations (vector&, void *src, bool add); - int ensure_inputs (uint32_t, bool clear, bool lockit, void *src); - int ensure_outputs (uint32_t, bool clear, bool lockit, void *src); + int ensure_inputs (ChanCount, bool clear, bool lockit, void *src); + int ensure_outputs (ChanCount, bool clear, bool lockit, void *src); void drop_input_connection (); void drop_output_connection (); @@ -396,8 +393,8 @@ public: void setup_peak_meters (); void meter (); - bool ensure_inputs_locked (uint32_t, bool clear, void *src); - bool ensure_outputs_locked (uint32_t, bool clear, void *src); + bool ensure_inputs_locked (ChanCount, bool clear, void *src); + bool ensure_outputs_locked (ChanCount, bool clear, void *src); int32_t find_input_port_hole (); int32_t find_output_port_hole (); diff --git a/libs/ardour/ardour/midi_track.h b/libs/ardour/ardour/midi_track.h index 7c4befe116..6cffe01318 100644 --- a/libs/ardour/ardour/midi_track.h +++ b/libs/ardour/ardour/midi_track.h @@ -76,8 +76,6 @@ public: protected: XMLNode& state (bool full); - ChanCount n_process_buffers (); - private: int set_diskstream (boost::shared_ptr ds); diff --git a/libs/ardour/ardour/port_set.h b/libs/ardour/ardour/port_set.h index df6b20b37a..70edbf75fd 100644 --- a/libs/ardour/ardour/port_set.h +++ b/libs/ardour/ardour/port_set.h @@ -41,7 +41,8 @@ public: size_t num_ports() const; size_t num_ports(DataType type) const { return _ports[type.to_index()].size(); } - void add_port(Port* port); + void add(Port* port); + bool remove(Port* port); /** nth port */ Port* port(size_t index) const; diff --git a/libs/ardour/ardour/session.h b/libs/ardour/ardour/session.h index ee87848dcb..47b6c163ef 100644 --- a/libs/ardour/ardour/session.h +++ b/libs/ardour/ardour/session.h @@ -280,6 +280,7 @@ class Session : public sigc::trackable, public PBD::StatefulDestructible static void get_template_list (list&); static string change_audio_path_by_name (string oldpath, string oldname, string newname, bool destructive); + static string change_midi_path_by_name (string oldpath, string oldname, string newname, bool destructive); static string peak_path_from_audio_path (string); string audio_path_from_name (string, uint32_t nchans, uint32_t chan, bool destructive); string midi_path_from_name (string); diff --git a/libs/ardour/ardour/track.h b/libs/ardour/ardour/track.h index 2e628fa586..a49aa60d31 100644 --- a/libs/ardour/ardour/track.h +++ b/libs/ardour/ardour/track.h @@ -97,8 +97,6 @@ class Track : public Route virtual XMLNode& state (bool full) = 0; - virtual ChanCount n_process_buffers () = 0; - boost::shared_ptr _diskstream; MeterPoint _saved_meter_point; TrackMode _mode; diff --git a/libs/ardour/audio_track.cc b/libs/ardour/audio_track.cc index 2762418f19..4f7c45235d 100644 --- a/libs/ardour/audio_track.cc +++ b/libs/ardour/audio_track.cc @@ -398,12 +398,6 @@ AudioTrack::set_state_part_two () return; } -ChanCount -AudioTrack::n_process_buffers () -{ - return max (_diskstream->n_channels(), redirect_max_outs); -} - 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) diff --git a/libs/ardour/insert.cc b/libs/ardour/insert.cc index 2fe40424fd..55938ab240 100644 --- a/libs/ardour/insert.cc +++ b/libs/ardour/insert.cc @@ -923,24 +923,9 @@ PortInsert::run (BufferSet& bufs, jack_nframes_t start_frame, jack_nframes_t end return; } - //uint32_t n; - vector::iterator o; - vector::iterator i; + deliver_output(bufs, start_frame, end_frame, nframes, offset); -#if 0 - /* deliver output */ - - for (o = _outputs.begin(), n = 0; o != _outputs.end(); ++o, ++n) { - memcpy ((*o)->get_buffer (nframes) + offset, bufs[min(nbufs,n)], sizeof (Sample) * nframes); - (*o)->mark_silence (false); - } - - /* collect input */ - - for (i = _inputs.begin(), n = 0; i != _inputs.end(); ++i, ++n) { - memcpy (bufs[min(nbufs,n)], (*i)->get_buffer (nframes) + offset, sizeof (Sample) * nframes); - } -#endif + collect_input(bufs, nframes, offset); } XMLNode& @@ -1059,7 +1044,8 @@ PortInsert::configure_io (int32_t ignored_magic, int32_t in, int32_t out) out = n_inputs ().get(_default_type); } - return ensure_io (out, in, false, this); + // FIXME + return ensure_io (ChanCount(_default_type, out), ChanCount(_default_type, in), false, this); } int32_t diff --git a/libs/ardour/io.cc b/libs/ardour/io.cc index 0abc10648e..a555793d80 100644 --- a/libs/ardour/io.cc +++ b/libs/ardour/io.cc @@ -226,6 +226,8 @@ IO::deliver_output (BufferSet& bufs, jack_nframes_t start_frame, jack_nframes_t void IO::collect_input (BufferSet& outs, jack_nframes_t nframes, jack_nframes_t offset) { + assert(outs.available() >= n_inputs()); + outs.set_count(n_inputs()); if (outs.count() == ChanCount::ZERO) @@ -245,8 +247,7 @@ void IO::just_meter_input (jack_nframes_t start_frame, jack_nframes_t end_frame, jack_nframes_t nframes, jack_nframes_t offset) { - BufferSet& bufs = _session.get_scratch_buffers (); - ChanCount nbufs = n_process_buffers (); + BufferSet& bufs = _session.get_scratch_buffers (n_inputs()); collect_input (bufs, nframes, offset); @@ -424,13 +425,13 @@ IO::set_input (Port* other_port, void* src) if (other_port == 0) { if (_input_minimum == ChanCount::ZERO) { - return ensure_inputs (0, false, true, src); + return ensure_inputs (ChanCount::ZERO, false, true, src); } else { return -1; } } - if (ensure_inputs (1, true, true, src)) { + if (ensure_inputs (ChanCount(other_port->type(), 1), true, true, src)) { return -1; } @@ -440,8 +441,6 @@ IO::set_input (Port* other_port, void* src) int IO::remove_output_port (Port* port, void* src) { - throw; // FIXME -#if 0 IOChange change (NoChange); { @@ -449,41 +448,34 @@ IO::remove_output_port (Port* port, void* src) { Glib::Mutex::Lock lm (io_lock); - - if (_noutputs - 1 == (uint32_t) _output_minimum) { + + if (n_outputs() <= _output_minimum) { /* sorry, you can't do this */ return -1; } - - for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) { - if (*i == port) { - change = IOChange (change|ConfigurationChanged); - if (port->connected()) { - change = IOChange (change|ConnectionsChanged); - } - _session.engine().unregister_port (*i); - _outputs.erase (i); - _noutputs--; - drop_output_connection (); + if (_outputs.remove(port)) { + change = IOChange (change|ConfigurationChanged); - break; - } - } + if (port->connected()) { + change = IOChange (change|ConnectionsChanged); + } - if (change != NoChange) { + _session.engine().unregister_port (*port); + drop_output_connection (); + setup_peak_meters (); reset_panner (); } } } - + if (change != NoChange) { - output_changed (change, src); /* EMIT SIGNAL */ + output_changed (change, src); _session.set_dirty (); return 0; - } -#endif + } + return -1; } @@ -515,7 +507,7 @@ IO::add_output_port (string destination, void* src, DataType type) /* Create a new output port */ // FIXME: naming scheme for differently typed ports? - if (_output_maximum.get_total() == 1) { + if (_output_maximum.get(type) == 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()); @@ -526,7 +518,7 @@ IO::add_output_port (string destination, void* src, DataType type) return -1; } - _outputs.add_port (our_port); + _outputs.add (our_port); drop_output_connection (); setup_peak_meters (); reset_panner (); @@ -551,8 +543,6 @@ IO::add_output_port (string destination, void* src, DataType type) int IO::remove_input_port (Port* port, void* src) { - throw; // FIXME -#if 0 IOChange change (NoChange); { @@ -561,29 +551,21 @@ IO::remove_input_port (Port* port, void* src) { Glib::Mutex::Lock lm (io_lock); - if (((int)_ninputs - 1) < _input_minimum) { + if (n_inputs() <= _input_minimum) { /* sorry, you can't do this */ return -1; } - for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) { - if (*i == port) { - change = IOChange (change|ConfigurationChanged); + if (_inputs.remove(port)) { + change = IOChange (change|ConfigurationChanged); - if (port->connected()) { - change = IOChange (change|ConnectionsChanged); - } + if (port->connected()) { + change = IOChange (change|ConnectionsChanged); + } - _session.engine().unregister_port (*i); - _inputs.erase (i); - _ninputs--; - drop_input_connection (); - - break; - } - } - - if (change != NoChange) { + _session.engine().unregister_port (*port); + drop_input_connection (); + setup_peak_meters (); reset_panner (); } @@ -595,7 +577,7 @@ IO::remove_input_port (Port* port, void* src) _session.set_dirty (); return 0; } -#endif + return -1; } @@ -628,7 +610,7 @@ IO::add_input_port (string source, void* src, DataType type) /* Create a new input port */ // FIXME: naming scheme for differently typed ports? - if (_input_maximum.get_total() == 1) { + if (_input_maximum.get(type) == 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()); @@ -638,8 +620,8 @@ IO::add_input_port (string source, void* src, DataType type) error << string_compose(_("IO: cannot register input port %1"), name) << endmsg; return -1; } - - _inputs.add_port(our_port); + + _inputs.add (our_port); drop_input_connection (); setup_peak_meters (); reset_panner (); @@ -708,55 +690,56 @@ IO::disconnect_outputs (void* src) } bool -IO::ensure_inputs_locked (uint32_t n, bool clear, void* src) +IO::ensure_inputs_locked (ChanCount count, bool clear, void* src) { - Port* input_port; - bool changed = false; + Port* input_port = 0; + bool changed = false; + + + for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) { + + const size_t n = count.get(*t); - /* remove unused ports */ + /* remove unused ports */ + for (size_t i = n_inputs().get(*t); i > n; --i) { + input_port = _inputs.port(*t, i-1); - while (n_inputs().get(_default_type) > n) { - throw; // FIXME - /* - _session.engine().unregister_port (_inputs.back()); - _inputs.pop_back(); - _ninputs--; - changed = true; - */ - } - - /* create any necessary new ports */ - - while (n_inputs().get(_default_type) < n) { - - char buf[64]; - - /* Create a new input port (of the default type) */ - - if (_input_maximum.get_total() == 1) { - snprintf (buf, sizeof (buf), _("%s/in"), _name.c_str()); + assert(input_port); + _inputs.remove(input_port); + _session.engine().unregister_port (*input_port); + + changed = true; } - else { - snprintf (buf, sizeof (buf), _("%s/in %u"), _name.c_str(), find_input_port_hole()); - } - - try { - - if ((input_port = _session.engine().register_input_port (_default_type, buf)) == 0) { - error << string_compose(_("IO: cannot register input port %1"), buf) << endmsg; - return -1; + + /* create any necessary new ports */ + while (n_inputs().get(*t) < n) { + + char buf[64]; + + if (_input_maximum.get(*t) == 1) { + snprintf (buf, sizeof (buf), _("%s/in"), _name.c_str()); + } else { + snprintf (buf, sizeof (buf), _("%s/in %u"), _name.c_str(), find_input_port_hole()); } - } - catch (AudioEngine::PortRegistrationFailure& err) { - setup_peak_meters (); - reset_panner (); - /* pass it on */ - throw err; + try { + + if ((input_port = _session.engine().register_input_port (*t, buf)) == 0) { + error << string_compose(_("IO: cannot register input port %1"), buf) << endmsg; + return -1; + } + } + + catch (AudioEngine::PortRegistrationFailure& err) { + setup_peak_meters (); + reset_panner (); + /* pass it on */ + throw err; + } + + _inputs.add (input_port); + changed = true; } - - _inputs.add_port (input_port); - changed = true; } if (changed) { @@ -769,7 +752,6 @@ IO::ensure_inputs_locked (uint32_t n, bool clear, void* src) if (clear) { /* disconnect all existing ports so that we get a fresh start */ - for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) { _session.engine().disconnect (*i); } @@ -780,7 +762,7 @@ IO::ensure_inputs_locked (uint32_t n, bool clear, void* src) /** Attach output_buffers to port buffers. * - * Connected to IOs own MoreChannels signal. + * Connected to IO's own MoreChannels signal. */ void IO::attach_buffers(ChanCount ignored) @@ -789,31 +771,17 @@ IO::attach_buffers(ChanCount ignored) } int -IO::ensure_io (const ChanCount& in, const ChanCount& out, bool clear, void* src) +IO::ensure_io (ChanCount in, ChanCount out, bool clear, void* src) { - // FIXME: TYPE - uint32_t nin = in.get(_default_type); - uint32_t nout = out.get(_default_type); + bool in_changed = false; + bool out_changed = false; + bool need_pan_reset = false; - // We only deal with one type still. Sorry about your luck. - assert(nin == in.get_total()); - assert(nout == out.get_total()); + in = min (_input_maximum, in); - return ensure_io(nin, nout, clear, src); -} + out = min (_output_maximum, out); -int -IO::ensure_io (uint32_t nin, uint32_t nout, bool clear, void* src) -{ - bool in_changed = false; - bool out_changed = false; - bool need_pan_reset; - - nin = min (_input_maximum.get(_default_type), static_cast(nin)); - - nout = min (_output_maximum.get(_default_type), static_cast(nout)); - - if (nin == n_inputs().get(_default_type) && nout == n_outputs().get(_default_type) && !clear) { + if (in == n_inputs() && out == n_outputs() && !clear) { return 0; } @@ -823,95 +791,103 @@ IO::ensure_io (uint32_t nin, uint32_t nout, bool clear, void* src) Port* port; - if (n_outputs().get(_default_type) == nout) { - need_pan_reset = false; - } else { + if (n_outputs() != out) { need_pan_reset = true; } - /* remove unused ports */ - - while (n_inputs().get(_default_type) > nin) { - throw; // FIXME - /* - _session.engine().unregister_port (_inputs.back()); - _inputs.pop_back(); - _ninputs--; - in_changed = true;*/ - } - - while (n_outputs().get(_default_type) > nout) { - throw; // FIXME - /* - _session.engine().unregister_port (_outputs.back()); - _outputs.pop_back(); - _noutputs--; - out_changed = true;*/ - } - - /* create any necessary new ports (of the default type) */ - - while (n_inputs().get(_default_type) < nin) { - - char buf[64]; + for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) { - /* Create a new input port */ - - if (_input_maximum.get_total() == 1) { - snprintf (buf, sizeof (buf), _("%s/in"), _name.c_str()); + const size_t nin = in.get(*t); + const size_t nout = out.get(*t); + + Port* output_port = 0; + Port* input_port = 0; + + /* remove unused output ports */ + for (size_t i = n_outputs().get(*t); i > nout; --i) { + output_port = _outputs.port(*t, i-1); + + assert(output_port); + _outputs.remove(output_port); + _session.engine().unregister_port (*output_port); + + out_changed = true; } - else { - snprintf (buf, sizeof (buf), _("%s/in %u"), _name.c_str(), find_input_port_hole()); + + /* remove unused input ports */ + for (size_t i = n_inputs().get(*t); i > nin; --i) { + input_port = _inputs.port(*t, i-1); + + assert(input_port); + _inputs.remove(input_port); + _session.engine().unregister_port (*input_port); + + in_changed = true; } - - try { - if ((port = _session.engine().register_input_port (_default_type, buf)) == 0) { - error << string_compose(_("IO: cannot register input port %1"), buf) << endmsg; - return -1; + + /* create any necessary new input ports */ + + while (n_inputs().get(*t) < nin) { + + char buf[64]; + + /* Create a new input port */ + + if (_input_maximum.get(*t) == 1) { + snprintf (buf, sizeof (buf), _("%s/in"), _name.c_str()); + } else { + snprintf (buf, sizeof (buf), _("%s/in %u"), _name.c_str(), find_input_port_hole()); } - } - catch (AudioEngine::PortRegistrationFailure& err) { - setup_peak_meters (); - reset_panner (); - /* pass it on */ - throw err; - } - - _inputs.add_port (port); - in_changed = true; - } - - /* create any necessary new ports */ - - while (n_outputs().get(_default_type) < nout) { - - char buf[64]; - - /* Create a new output port */ - - 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()); - } - - try { - if ((port = _session.engine().register_output_port (_default_type, buf)) == 0) { - error << string_compose(_("IO: cannot register output port %1"), buf) << endmsg; - return -1; + try { + if ((port = _session.engine().register_input_port (*t, buf)) == 0) { + error << string_compose(_("IO: cannot register input port %1"), buf) << endmsg; + return -1; + } } + + catch (AudioEngine::PortRegistrationFailure& err) { + setup_peak_meters (); + reset_panner (); + /* pass it on */ + throw err; + } + + _inputs.add (port); + in_changed = true; } - - catch (AudioEngine::PortRegistrationFailure& err) { - setup_peak_meters (); - reset_panner (); - /* pass it on */ - throw err; + + /* create any necessary new output ports */ + + while (n_outputs().get(*t) < nout) { + + char buf[64]; + + /* Create a new output port */ + + if (_output_maximum.get(*t) == 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()); + } + + try { + if ((port = _session.engine().register_output_port (*t, buf)) == 0) { + error << string_compose(_("IO: cannot register output port %1"), buf) << endmsg; + return -1; + } + } + + catch (AudioEngine::PortRegistrationFailure& err) { + setup_peak_meters (); + reset_panner (); + /* pass it on */ + throw err; + } + + _outputs.add (port); + out_changed = true; } - - _outputs.add_port (port); - out_changed = true; } if (clear) { @@ -952,22 +928,22 @@ IO::ensure_io (uint32_t nin, uint32_t nout, bool clear, void* src) } int -IO::ensure_inputs (uint32_t n, bool clear, bool lockit, void* src) +IO::ensure_inputs (ChanCount count, bool clear, bool lockit, void* src) { bool changed = false; - n = min (_input_maximum.get(_default_type), static_cast(n)); + count = min (_input_maximum, count); - if (n == n_inputs().get(_default_type) && !clear) { + if (count == n_inputs() && !clear) { return 0; } if (lockit) { Glib::Mutex::Lock em (_session.engine().process_lock()); Glib::Mutex::Lock im (io_lock); - changed = ensure_inputs_locked (n, clear, src); + changed = ensure_inputs_locked (count, clear, src); } else { - changed = ensure_inputs_locked (n, clear, src); + changed = ensure_inputs_locked (count, clear, src); } if (changed) { @@ -978,55 +954,54 @@ IO::ensure_inputs (uint32_t n, bool clear, bool lockit, void* src) } bool -IO::ensure_outputs_locked (uint32_t n, bool clear, void* src) +IO::ensure_outputs_locked (ChanCount count, bool clear, void* src) { - Port* output_port; - bool changed = false; - bool need_pan_reset; + Port* output_port = 0; + bool changed = false; + bool need_pan_reset = false; - if (n_outputs().get(_default_type) == n) { - need_pan_reset = false; - } else { + if (n_outputs() != count) { need_pan_reset = true; } - /* remove unused ports */ - - while (n_outputs().get(_default_type) > n) { - throw; // FIXME - /* - _session.engine().unregister_port (_outputs.back()); - _outputs.pop_back(); - _noutputs--; - changed = true; - */ - } - - /* create any necessary new ports */ - - while (n_outputs().get(_default_type) < n) { - - char buf[64]; - - /* Create a new output port */ - - 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()); - } - - if ((output_port = _session.engine().register_output_port (_default_type, buf)) == 0) { - error << string_compose(_("IO: cannot register output port %1"), buf) << endmsg; - return -1; - } - - _outputs.add_port (output_port); - changed = true; - setup_peak_meters (); + for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) { - if (need_pan_reset) { - reset_panner (); + const size_t n = count.get(*t); + + /* remove unused ports */ + for (size_t i = n_outputs().get(*t); i > n; --i) { + output_port = _outputs.port(*t, i-1); + + assert(output_port); + _outputs.remove(output_port); + _session.engine().unregister_port (*output_port); + + changed = true; + } + + /* create any necessary new ports */ + while (n_outputs().get(*t) < n) { + + char buf[64]; + + if (_output_maximum.get(*t) == 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()); + } + + if ((output_port = _session.engine().register_output_port (*t, buf)) == 0) { + error << string_compose(_("IO: cannot register output port %1"), buf) << endmsg; + return -1; + } + + _outputs.add (output_port); + changed = true; + setup_peak_meters (); + + if (need_pan_reset) { + reset_panner (); + } } } @@ -1038,7 +1013,6 @@ IO::ensure_outputs_locked (uint32_t n, bool clear, void* src) if (clear) { /* disconnect all existing ports so that we get a fresh start */ - for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) { _session.engine().disconnect (*i); } @@ -1048,13 +1022,13 @@ IO::ensure_outputs_locked (uint32_t n, bool clear, void* src) } int -IO::ensure_outputs (uint32_t n, bool clear, bool lockit, void* src) +IO::ensure_outputs (ChanCount count, bool clear, bool lockit, void* src) { bool changed = false; if (_output_maximum < ChanCount::INFINITE) { - n = min (_output_maximum.get(_default_type), static_cast(n)); - if (n == n_outputs().get(_default_type) && !clear) { + count = min (_output_maximum, count); + if (count == n_outputs() && !clear) { return 0; } } @@ -1064,14 +1038,15 @@ IO::ensure_outputs (uint32_t n, bool clear, bool lockit, void* src) if (lockit) { Glib::Mutex::Lock em (_session.engine().process_lock()); Glib::Mutex::Lock im (io_lock); - changed = ensure_outputs_locked (n, clear, src); + changed = ensure_outputs_locked (count, clear, src); } else { - changed = ensure_outputs_locked (n, clear, src); + changed = ensure_outputs_locked (count, clear, src); } if (changed) { output_changed (ConfigurationChanged, src); /* EMIT SIGNAL */ } + return 0; } @@ -1090,7 +1065,7 @@ IO::reset_panner () { if (panners_legal) { if (!no_panner_reset) { - _panner->reset (n_outputs().get(_default_type), pans_required()); + _panner->reset (n_outputs().get(DataType::AUDIO), pans_required()); } } else { panner_legal_c.disconnect (); @@ -1101,7 +1076,7 @@ IO::reset_panner () int IO::panners_became_legal () { - _panner->reset (n_outputs().get(_default_type), pans_required()); + _panner->reset (n_outputs().get(DataType::AUDIO), pans_required()); _panner->load (); // automation panner_legal_c.disconnect (); return 0; @@ -1225,6 +1200,7 @@ IO::state (bool full_state) snprintf (buf, sizeof(buf), "%2.12f", gain()); node->add_property ("gain", buf); + // FIXME: this is NOT sufficient! 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); @@ -1451,7 +1427,8 @@ IO::create_ports (const XMLNode& node) no_panner_reset = true; - if (ensure_io (num_inputs, num_outputs, true, this)) { + // FIXME: audio-only + if (ensure_io (ChanCount(DataType::AUDIO, num_inputs), ChanCount(DataType::AUDIO, num_outputs), true, this)) { error << string_compose(_("%1: cannot create I/O ports"), _name) << endmsg; return -1; } @@ -1535,7 +1512,8 @@ IO::set_inputs (const string& str) return 0; } - if (ensure_inputs (nports, true, true, this)) { + // FIXME: audio-only + if (ensure_inputs (ChanCount(DataType::AUDIO, nports), true, true, this)) { return -1; } @@ -1585,7 +1563,8 @@ IO::set_outputs (const string& str) return 0; } - if (ensure_outputs (nports, true, true, this)) { + // FIXME: audio-only + if (ensure_outputs (ChanCount(DataType::AUDIO, nports), true, true, this)) { return -1; } @@ -1816,7 +1795,8 @@ IO::use_input_connection (Connection& c, void* src) drop_input_connection (); - if (ensure_inputs (limit, false, false, src)) { + // FIXME connections only work for audio-only + if (ensure_inputs (ChanCount(DataType::AUDIO, limit), false, false, src)) { return -1; } @@ -1894,7 +1874,8 @@ IO::use_output_connection (Connection& c, void* src) drop_output_connection (); - if (ensure_outputs (limit, false, false, src)) { + // FIXME: audio-only + if (ensure_outputs (ChanCount(DataType::AUDIO, limit), false, false, src)) { return -1; } diff --git a/libs/ardour/midi_region.cc b/libs/ardour/midi_region.cc index c4816d8121..4e39436ae3 100644 --- a/libs/ardour/midi_region.cc +++ b/libs/ardour/midi_region.cc @@ -334,6 +334,9 @@ MidiRegion::recompute_at_start () int MidiRegion::separate_by_channel (Session& session, vector& v) const { + // Separate by MIDI channel? bit different from audio since this is separating based + // on the actual contained data and destructively modifies and creates new sources.. + #if 0 SourceList srcs; string new_name; diff --git a/libs/ardour/midi_track.cc b/libs/ardour/midi_track.cc index aeff92bed3..2336baac75 100644 --- a/libs/ardour/midi_track.cc +++ b/libs/ardour/midi_track.cc @@ -62,6 +62,11 @@ MidiTrack::MidiTrack (Session& sess, string name, Route::Flag flag, TrackMode mo _freeze_record.state = NoFreeze; _saved_meter_point = _meter_point; _mode = mode; + + set_input_minimum(ChanCount(DataType::MIDI, 1)); + set_input_maximum(ChanCount(DataType::MIDI, 1)); + set_output_minimum(ChanCount(DataType::MIDI, 1)); + set_output_maximum(ChanCount(DataType::MIDI, 1)); } MidiTrack::MidiTrack (Session& sess, const XMLNode& node) @@ -71,6 +76,11 @@ MidiTrack::MidiTrack (Session& sess, const XMLNode& node) set_state (node); _declickable = true; _saved_meter_point = _meter_point; + + set_input_minimum(ChanCount(DataType::MIDI, 1)); + set_input_maximum(ChanCount(DataType::MIDI, 1)); + set_output_minimum(ChanCount(DataType::MIDI, 1)); + set_output_maximum(ChanCount(DataType::MIDI, 1)); } MidiTrack::~MidiTrack () @@ -341,12 +351,6 @@ MidiTrack::set_state_part_two () return; } -ChanCount -MidiTrack::n_process_buffers () -{ - return max (_diskstream->n_channels(), redirect_max_outs); -} - 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) diff --git a/libs/ardour/port_set.cc b/libs/ardour/port_set.cc index 3d6ab8c537..388162359b 100644 --- a/libs/ardour/port_set.cc +++ b/libs/ardour/port_set.cc @@ -32,7 +32,7 @@ static bool sort_ports_by_name (Port* a, Port* b) } void -PortSet::add_port(Port* port) +PortSet::add(Port* port) { const size_t list_index = port->type().to_index(); assert(list_index < _ports.size()); @@ -47,6 +47,20 @@ PortSet::add_port(Port* port) assert(_count.get(port->type()) == _ports[port->type().to_index()].size()); } +bool +PortSet::remove(Port* port) +{ + for (std::vector::iterator l = _ports.begin(); l != _ports.end(); ++l) { + PortVec::iterator i = find(l->begin(), l->end(), port); + if (i != l->end()) { + l->erase(i); + _count.set(port->type(), _count.get(port->type()) - 1); + return true; + } + } + + return false; +} /** Get the total number of ports (of all types) in the PortSet */ @@ -74,7 +88,7 @@ PortSet::contains(const Port* port) const Port* PortSet::port(size_t n) const { - // This is awesome + // This is awesome. Awesomely slow. size_t size_so_far = 0; diff --git a/libs/ardour/route.cc b/libs/ardour/route.cc index 039f88e2ea..4aedf24b55 100644 --- a/libs/ardour/route.cc +++ b/libs/ardour/route.cc @@ -652,7 +652,8 @@ Route::process_output_buffers (BufferSet& bufs, ChanCount Route::n_process_buffers () { - return max (n_inputs(), redirect_max_outs); + //return max (n_inputs(), redirect_max_outs); + return n_inputs(); // FIXME? } void @@ -784,7 +785,7 @@ Route::add_redirect (boost::shared_ptr redirect, void *src, uint32_t* */ - porti->ensure_io (n_outputs ().get(DataType::AUDIO), n_inputs().get(DataType::AUDIO), false, this); + porti->ensure_io (n_outputs (), n_inputs(), false, this); } // Ensure peak vector sizes before the plugin is activated @@ -1729,10 +1730,10 @@ Route::set_control_outs (const vector& ports) _control_outs = new IO (_session, coutname); /* our control outs need as many outputs as we - have outputs. we track the changes in ::output_change_handler(). + have audio outputs. we track the changes in ::output_change_handler(). */ - _control_outs->ensure_io (0, n_outputs().get(DataType::AUDIO), true, this); + _control_outs->ensure_io (ChanCount::ZERO, ChanCount(DataType::AUDIO, n_outputs().get(DataType::AUDIO)), true, this); return 0; } @@ -1961,7 +1962,7 @@ Route::output_change_handler (IOChange change, void *ignored) { if (change & ConfigurationChanged) { if (_control_outs) { - _control_outs->ensure_io (0, n_outputs().get(DataType::AUDIO), true, this); + _control_outs->ensure_io (ChanCount::ZERO, ChanCount(DataType::AUDIO, n_outputs().get(DataType::AUDIO)), true, this); } reset_plugin_counts (0); diff --git a/libs/ardour/session.cc b/libs/ardour/session.cc index 0a85c47cb9..3c325ee538 100644 --- a/libs/ardour/session.cc +++ b/libs/ardour/session.cc @@ -1668,7 +1668,7 @@ Session::new_midi_track (TrackMode mode, uint32_t how_many) RouteList new_routes; list > ret; - /* count existing audio tracks */ + /* count existing midi tracks */ { shared_ptr r = routes.reader (); @@ -1737,156 +1737,6 @@ Session::new_midi_track (TrackMode mode, uint32_t how_many) return ret; } -#if 0 -std::list > -Session::new_midi_track (TrackMode mode) -{ - char track_name[32]; - uint32_t n = 0; - uint32_t channels_used = 0; - string port; - - /* count existing midi tracks */ - - { - shared_ptr r = routes.reader (); - - for (RouteList::iterator i = r->begin(); i != r->end(); ++i) { - if (dynamic_cast((*i).get()) != 0) { - if (!(*i)->hidden()) { - n++; - channels_used += (*i)->n_inputs().get(DataType::MIDI); - } - } - } - } - - /* check for duplicate route names, since we might have pre-existing - routes with this name (e.g. create Midi1, Midi2, delete Midi1, - save, close,restart,add new route - first named route is now - Midi2) - */ - - do { - snprintf (track_name, sizeof(track_name), "Midi %" PRIu32, n+1); - if (route_by_name (track_name) == 0) { - break; - } - n++; - - } while (n < (UINT_MAX-1)); - - try { - shared_ptr track (new MidiTrack (*this, track_name, Route::Flag (0), mode)); - - if (track->ensure_io (1, 1, false, this)) { - error << string_compose (_("cannot configure %1 in/%2 out configuration for new midi track"), track_name) - << endmsg; - } - - track->DiskstreamChanged.connect (mem_fun (this, &Session::resort_routes)); - - add_route (track); - - track->set_remote_control_id (ntracks()); - return track; - } - - catch (failed_constructor &err) { - error << _("Session: could not create new midi track.") << endmsg; - return shared_ptr ((MidiTrack*) 0); - } -} - -boost::shared_ptr -Session::new_midi_route () -{ - char bus_name[32]; - uint32_t n = 0; - string port; - - /* count existing midi busses */ - { - shared_ptr r = routes.reader (); - - for (RouteList::iterator i = r->begin(); i != r->end(); ++i) { - if (dynamic_cast((*i).get()) == 0) { - if (!(*i)->hidden()) { - n++; - } - } - } - } - - do { - snprintf (bus_name, sizeof(bus_name), "Bus %" PRIu32, n+1); - if (route_by_name (bus_name) == 0) { - break; - } - n++; - - } while (n < (UINT_MAX-1)); - - try { - shared_ptr bus (new Route (*this, bus_name, -1, -1, -1, -1, Route::Flag(0), DataType::MIDI)); - - if (bus->ensure_io (1, 1, false, this)) { - error << (_("cannot configure 1 in/1 out configuration for new midi track")) - << endmsg; - } -#if 0 - for (uint32_t x = 0; x < bus->n_inputs(); ++x) { - - port = ""; - - if (input_auto_connect & AutoConnectPhysical) { - port = _engine.get_nth_physical_input ((n+x)%n_physical_inputs); - } - - if (port.length() && bus->connect_input (bus->input (x), port, this)) { - break; - } - } - - for (uint32_t x = 0; x < bus->n_outputs(); ++x) { - - port = ""; - - if (output_auto_connect & AutoConnectPhysical) { - port = _engine.get_nth_physical_input ((n+x)%n_physical_outputs); - } else if (output_auto_connect & AutoConnectMaster) { - if (_master_out) { - port = _master_out->input (x%_master_out->n_inputs())->name(); - } - } - - if (port.length() && bus->connect_output (bus->output (x), port, this)) { - break; - } - } -#endif -/* - if (_control_out) { - vector cports; - uint32_t ni = _control_out->n_inputs(); - - for (uint32_t n = 0; n < ni; ++n) { - cports.push_back (_control_out->input(n)->name()); - } - bus->set_control_outs (cports); - } -*/ - add_route (bus); - return bus; - } - - catch (failed_constructor &err) { - error << _("Session: could not create new MIDI route.") << endmsg; - return shared_ptr ((Route*) 0); - } -} -#endif - list > Session::new_audio_track (int input_channels, int output_channels, TrackMode mode, uint32_t how_many) { @@ -1956,7 +1806,7 @@ Session::new_audio_track (int input_channels, int output_channels, TrackMode mod try { shared_ptr track (new AudioTrack (*this, track_name, Route::Flag (0), mode)); - if (track->ensure_io (input_channels, output_channels, false, this)) { + if (track->ensure_io (ChanCount(DataType::AUDIO, input_channels), ChanCount(DataType::AUDIO, output_channels), false, this)) { error << string_compose (_("cannot configure %1 in/%2 out configuration for new audio track"), input_channels, output_channels) << endmsg; @@ -2077,7 +1927,7 @@ Session::new_audio_route (int input_channels, int output_channels, uint32_t how_ try { shared_ptr bus (new Route (*this, bus_name, -1, -1, -1, -1, Route::Flag(0), DataType::AUDIO)); - if (bus->ensure_io (input_channels, output_channels, false, this)) { + if (bus->ensure_io (ChanCount(DataType::AUDIO, input_channels), ChanCount(DataType::AUDIO, output_channels), false, this)) { error << string_compose (_("cannot configure %1 in/%2 out configuration for new audio track"), input_channels, output_channels) << endmsg; @@ -3222,6 +3072,121 @@ Session::create_audio_source_for_session (AudioDiskstream& ds, uint32_t chan, bo return boost::dynamic_pointer_cast (SourceFactory::createWritable (DataType::AUDIO, spath, destructive, frame_rate())); } +// FIXME: _terrible_ code duplication +string +Session::change_midi_path_by_name (string path, string oldname, string newname, bool destructive) +{ + string look_for; + string old_basename = PBD::basename_nosuffix (oldname); + string new_legalized = legalize_for_path (newname); + + /* note: we know (or assume) the old path is already valid */ + + if (destructive) { + + /* destructive file sources have a name of the form: + + /path/to/Tnnnn-NAME(%[LR])?.wav + + the task here is to replace NAME with the new name. + */ + + /* find last slash */ + + string dir; + string prefix; + string::size_type slash; + string::size_type dash; + + if ((slash = path.find_last_of ('/')) == string::npos) { + return ""; + } + + dir = path.substr (0, slash+1); + + /* '-' is not a legal character for the NAME part of the path */ + + if ((dash = path.find_last_of ('-')) == string::npos) { + return ""; + } + + prefix = path.substr (slash+1, dash-(slash+1)); + + path = dir; + path += prefix; + path += '-'; + path += new_legalized; + path += ".mid"; /* XXX gag me with a spoon */ + + } else { + + /* non-destructive file sources have a name of the form: + + /path/to/NAME-nnnnn(%[LR])?.wav + + the task here is to replace NAME with the new name. + */ + + string dir; + string suffix; + string::size_type slash; + string::size_type dash; + string::size_type postfix; + + /* find last slash */ + + if ((slash = path.find_last_of ('/')) == string::npos) { + return ""; + } + + dir = path.substr (0, slash+1); + + /* '-' is not a legal character for the NAME part of the path */ + + if ((dash = path.find_last_of ('-')) == string::npos) { + return ""; + } + + suffix = path.substr (dash+1); + + // Suffix is now everything after the dash. Now we need to eliminate + // the nnnnn part, which is done by either finding a '%' or a '.' + + postfix = suffix.find_last_of ("%"); + if (postfix == string::npos) { + postfix = suffix.find_last_of ('.'); + } + + if (postfix != string::npos) { + suffix = suffix.substr (postfix); + } else { + error << "Logic error in Session::change_midi_path_by_name(), please report to the developers" << endl; + return ""; + } + + const uint32_t limit = 10000; + char buf[PATH_MAX+1]; + + for (uint32_t cnt = 1; cnt <= limit; ++cnt) { + + snprintf (buf, sizeof(buf), "%s%s-%u%s", dir.c_str(), newname.c_str(), cnt, suffix.c_str()); + + if (access (buf, F_OK) != 0) { + path = buf; + break; + } + path = ""; + } + + if (path == "") { + error << "FATAL ERROR! Could not find a " << endl; + } + + } + + return path; +} + string Session::midi_path_from_name (string name) { diff --git a/libs/ardour/smf_source.cc b/libs/ardour/smf_source.cc index 44186ef86f..d73bb8351f 100644 --- a/libs/ardour/smf_source.cc +++ b/libs/ardour/smf_source.cc @@ -330,36 +330,7 @@ SMFSource::read_unlocked (MidiRingBuffer& dst, jack_nframes_t start, jack_nframe } } } -#if 0 - cerr << "SMF pretending to read" << endl; - - MidiEvent ev; - RawMidi data[4]; - - const char note = rand()%30 + 30; - ev.buffer = data; - ev.time = start+1; // FIXME: bug at 0? - ev.size = 3; - - data[0] = 0x90; - data[1] = note; - data[2] = 120; - - dst.write(ev); - - ev.buffer = data; - ev.time = start + (jack_nframes_t)(cnt * 8.0/10.0); - ev.size = 3; - - data[0] = 0x80; - data[1] = note; - data[2] = 64; - - dst.write(ev); - - //dst.clear(); -#endif return cnt; } @@ -488,7 +459,7 @@ SMFSource::move_to_trash (const string trash_dir_name) } /* don't move the file across filesystems, just - stick it in the `trash_dir_name' directory + stick it in the 'trash_dir_name' directory on whichever filesystem it was already on. */ @@ -531,7 +502,7 @@ SMFSource::move_to_trash (const string trash_dir_name) } if (::rename (_path.c_str(), newpath.c_str()) != 0) { - PBD::error << string_compose (_("cannot rename audio file source from %1 to %2 (%3)"), + PBD::error << string_compose (_("cannot rename midi file source from %1 to %2 (%3)"), _path, newpath, strerror (errno)) << endmsg; return -1; @@ -682,15 +653,15 @@ SMFSource::set_name (string newname, bool destructive) { //Glib::Mutex::Lock lm (_lock); FIXME string oldpath = _path; - string newpath = Session::change_audio_path_by_name (oldpath, _name, newname, destructive); + string newpath = Session::change_midi_path_by_name (oldpath, _name, newname, destructive); if (newpath.empty()) { - PBD::error << string_compose (_("programming error: %1"), "cannot generate a changed audio path") << endmsg; + PBD::error << string_compose (_("programming error: %1"), "cannot generate a changed midi path") << endmsg; return -1; } if (rename (oldpath.c_str(), newpath.c_str()) != 0) { - PBD::error << string_compose (_("cannot rename audio file for %1 to %2"), _name, newpath) << endmsg; + PBD::error << string_compose (_("cannot rename midi file for %1 to %2"), _name, newpath) << endmsg; return -1; }