- Fixed port adding/removing/connecting and related bugs with route signal path

- Minor MIDI bug fixes/cleanups


git-svn-id: svn://localhost/ardour2/branches/midi@874 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
David Robillard 2006-08-31 01:06:37 +00:00
parent 82232f06ba
commit 5a40162026
16 changed files with 414 additions and 498 deletions

View File

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

View File

@ -64,8 +64,6 @@ class AudioTrack : public Track
protected:
XMLNode& state (bool full);
ChanCount n_process_buffers ();
private:
int set_diskstream (boost::shared_ptr<AudioDiskstream>, void *);
int deprecated_use_diskstream_connections ();

View File

@ -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<string>&, void *src, bool add);
int set_destinations (vector<string>&, 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 ();

View File

@ -76,8 +76,6 @@ public:
protected:
XMLNode& state (bool full);
ChanCount n_process_buffers ();
private:
int set_diskstream (boost::shared_ptr<MidiDiskstream> ds);

View File

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

View File

@ -280,6 +280,7 @@ class Session : public sigc::trackable, public PBD::StatefulDestructible
static void get_template_list (list<string>&);
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);

View File

@ -97,8 +97,6 @@ class Track : public Route
virtual XMLNode& state (bool full) = 0;
virtual ChanCount n_process_buffers () = 0;
boost::shared_ptr<Diskstream> _diskstream;
MeterPoint _saved_meter_point;
TrackMode _mode;

View File

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

View File

@ -923,24 +923,9 @@ PortInsert::run (BufferSet& bufs, jack_nframes_t start_frame, jack_nframes_t end
return;
}
//uint32_t n;
vector<Port*>::iterator o;
vector<Port*>::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

View File

@ -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<size_t>(nin));
nout = min (_output_maximum.get(_default_type), static_cast<size_t>(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<size_t>(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<size_t>(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;
}

View File

@ -334,6 +334,9 @@ MidiRegion::recompute_at_start ()
int
MidiRegion::separate_by_channel (Session& session, vector<MidiRegion*>& 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;

View File

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

View File

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

View File

@ -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> 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<string>& 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);

View File

@ -1668,7 +1668,7 @@ Session::new_midi_track (TrackMode mode, uint32_t how_many)
RouteList new_routes;
list<boost::shared_ptr<MidiTrack> > ret;
/* count existing audio tracks */
/* count existing midi tracks */
{
shared_ptr<RouteList> r = routes.reader ();
@ -1737,156 +1737,6 @@ Session::new_midi_track (TrackMode mode, uint32_t how_many)
return ret;
}
#if 0
std::list<boost::shared_ptr<MidiTrack> >
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<RouteList> r = routes.reader ();
for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
if (dynamic_cast<MidiTrack*>((*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<MidiTrack> 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> ((MidiTrack*) 0);
}
}
boost::shared_ptr<Route>
Session::new_midi_route ()
{
char bus_name[32];
uint32_t n = 0;
string port;
/* count existing midi busses */
{
shared_ptr<RouteList> r = routes.reader ();
for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
if (dynamic_cast<MidiTrack*>((*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<Route> 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<string> 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> ((Route*) 0);
}
}
#endif
list<boost::shared_ptr<AudioTrack> >
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<AudioTrack> 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<Route> 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<AudioFileSource> (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)
{

View File

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