summaryrefslogtreecommitdiff
path: root/libs
diff options
context:
space:
mode:
authorPaul Davis <paul@linuxaudiosystems.com>2010-06-26 13:45:59 +0000
committerPaul Davis <paul@linuxaudiosystems.com>2010-06-26 13:45:59 +0000
commit37978aa21437b9bb308efeb9828fbe4a06077cee (patch)
treef7b3b681e0e42c233ded6715ea824114d9e5c3ec /libs
parentecb0cd5d119d28092a8f48e4521ac5eba197bb54 (diff)
lots of details relating to MIDI file management; try to ignore ALSA sequencer MIDI ports named "Midi-Through"
git-svn-id: svn://localhost/ardour2/branches/3.0@7305 d708f5d6-7413-0410-9779-e7cbd77b26cf
Diffstat (limited to 'libs')
-rw-r--r--libs/ardour/ardour/file_source.h1
-rw-r--r--libs/ardour/ardour/region.h2
-rw-r--r--libs/ardour/ardour/source.h10
-rw-r--r--libs/ardour/audio_diskstream.cc2
-rw-r--r--libs/ardour/audioengine.cc41
-rw-r--r--libs/ardour/file_source.cc6
-rw-r--r--libs/ardour/midi_diskstream.cc69
-rw-r--r--libs/ardour/midi_model.cc2
-rw-r--r--libs/ardour/midi_region.cc13
-rw-r--r--libs/ardour/midi_source.cc11
-rw-r--r--libs/ardour/region.cc3
-rw-r--r--libs/ardour/region_factory.cc9
-rw-r--r--libs/ardour/smf_source.cc7
-rw-r--r--libs/ardour/source.cc14
-rw-r--r--libs/ardour/source_factory.cc4
-rw-r--r--libs/evoral/src/SMF.cpp4
16 files changed, 116 insertions, 82 deletions
diff --git a/libs/ardour/ardour/file_source.h b/libs/ardour/ardour/file_source.h
index 76c3c57e36..38449def26 100644
--- a/libs/ardour/ardour/file_source.h
+++ b/libs/ardour/ardour/file_source.h
@@ -41,6 +41,7 @@ public:
int move_to_trash (const Glib::ustring& trash_dir_name);
void mark_take (const Glib::ustring& id);
void mark_immutable ();
+ void mark_nonremovable ();
const Glib::ustring& take_id () const { return _take_id; }
bool within_session () const { return _within_session; }
diff --git a/libs/ardour/ardour/region.h b/libs/ardour/ardour/region.h
index a30bb8660c..9d85c5b43d 100644
--- a/libs/ardour/ardour/region.h
+++ b/libs/ardour/ardour/region.h
@@ -353,7 +353,7 @@ class Region
void register_properties ();
-private:
+protected:
void use_sources (SourceList const &);
};
diff --git a/libs/ardour/ardour/source.h b/libs/ardour/ardour/source.h
index 9abf7ff8f0..6f750e6fd0 100644
--- a/libs/ardour/ardour/source.h
+++ b/libs/ardour/ardour/source.h
@@ -106,15 +106,7 @@ class Source : public SessionObject
Flag flags() const { return _flags; }
void inc_use_count () { g_atomic_int_inc (&_use_count); }
- void dec_use_count () {
-#ifndef NDEBUG
- gint oldval = g_atomic_int_exchange_and_add (&_use_count, -1);
- assert (oldval > 0);
-#else
- g_atomic_int_exchange_and_add (&_use_count, -1);
-#endif
- }
-
+ void dec_use_count ();
int use_count() const { return g_atomic_int_get (&_use_count); }
bool used() const { return use_count() > 0; }
diff --git a/libs/ardour/audio_diskstream.cc b/libs/ardour/audio_diskstream.cc
index d3e19dac91..6dc29a510b 100644
--- a/libs/ardour/audio_diskstream.cc
+++ b/libs/ardour/audio_diskstream.cc
@@ -1917,8 +1917,6 @@ AudioDiskstream::reset_write_sources (bool mark_write_complete, bool /*force*/)
boost::shared_ptr<ChannelList> c = channels.reader();
uint32_t n;
- cerr << name() << " resetting write sources, recrodable " << recordable() << " chans = " << c->size() << endl;
-
if (!_session.writable() || !recordable()) {
return;
}
diff --git a/libs/ardour/audioengine.cc b/libs/ardour/audioengine.cc
index 2282a20809..79aa5d9ff8 100644
--- a/libs/ardour/audioengine.cc
+++ b/libs/ardour/audioengine.cc
@@ -1109,16 +1109,21 @@ AudioEngine::n_physical_outputs (DataType type) const
{
GET_PRIVATE_JACK_POINTER_RET (_jack,0);
const char ** ports;
- uint32_t i = 0;
+ uint32_t cnt = 0;
if ((ports = jack_get_ports (_priv_jack, NULL, type.to_jack_type(), JackPortIsPhysical|JackPortIsInput)) == 0) {
return 0;
}
- for (i = 0; ports[i]; ++i) {}
+ for (uint32_t i = 0; ports[i]; ++i) {
+ if (!strstr (ports[i], "Midi-Through")) {
+ cnt++;
+ }
+ }
+
free (ports);
- return i;
+ return cnt;
}
uint32_t
@@ -1126,16 +1131,21 @@ AudioEngine::n_physical_inputs (DataType type) const
{
GET_PRIVATE_JACK_POINTER_RET (_jack,0);
const char ** ports;
- uint32_t i = 0;
-
+ uint32_t cnt = 0;
+
if ((ports = jack_get_ports (_priv_jack, NULL, type.to_jack_type(), JackPortIsPhysical|JackPortIsOutput)) == 0) {
return 0;
}
- for (i = 0; ports[i]; ++i) {}
+ for (uint32_t i = 0; ports[i]; ++i) {
+ if (!strstr (ports[i], "Midi-Through")) {
+ cnt++;
+ }
+ }
+
free (ports);
- return i;
+ return cnt;
}
void
@@ -1150,6 +1160,9 @@ AudioEngine::get_physical_inputs (DataType type, vector<string>& ins)
if (ports) {
for (uint32_t i = 0; ports[i]; ++i) {
+ if (strstr (ports[i], "Midi-Through")) {
+ continue;
+ }
ins.push_back (ports[i]);
}
free (ports);
@@ -1168,6 +1181,9 @@ AudioEngine::get_physical_outputs (DataType type, vector<string>& outs)
}
for (i = 0; ports[i]; ++i) {
+ if (strstr (ports[i], "Midi-Through")) {
+ continue;
+ }
outs.push_back (ports[i]);
}
free (ports);
@@ -1179,6 +1195,7 @@ AudioEngine::get_nth_physical (DataType type, uint32_t n, int flag)
GET_PRIVATE_JACK_POINTER_RET (_jack,"");
const char ** ports;
uint32_t i;
+ uint32_t idx;
string ret;
assert(type != DataType::NIL);
@@ -1187,10 +1204,14 @@ AudioEngine::get_nth_physical (DataType type, uint32_t n, int flag)
return ret;
}
- for (i = 0; i < n && ports[i]; ++i) {}
+ for (i = 0, idx = 0; idx < n && ports[i]; ++i) {
+ if (!strstr (ports[i], "Midi-Through")) {
+ ++idx;
+ }
+ }
- if (ports[i]) {
- ret = ports[i];
+ if (ports[idx]) {
+ ret = ports[idx];
}
free ((const char **) ports);
diff --git a/libs/ardour/file_source.cc b/libs/ardour/file_source.cc
index fd66a7a167..be68c0c405 100644
--- a/libs/ardour/file_source.cc
+++ b/libs/ardour/file_source.cc
@@ -418,6 +418,12 @@ FileSource::mark_immutable ()
}
void
+FileSource::mark_nonremovable ()
+{
+ _flags = Flag (_flags & ~(Removable|RemovableIfEmpty|RemoveAtDestroy));
+}
+
+void
FileSource::set_within_session_from_path (const std::string& path)
{
_within_session = _session.path_is_within_session (path);
diff --git a/libs/ardour/midi_diskstream.cc b/libs/ardour/midi_diskstream.cc
index f9ece16aec..95e242e671 100644
--- a/libs/ardour/midi_diskstream.cc
+++ b/libs/ardour/midi_diskstream.cc
@@ -36,6 +36,7 @@
#include "pbd/memento_command.h"
#include "pbd/enumwriter.h"
#include "pbd/stateful_diff_command.h"
+#include "pbd/stacktrace.h"
#include "ardour/ardour.h"
#include "ardour/audioengine.h"
@@ -84,6 +85,7 @@ MidiDiskstream::MidiDiskstream (Session &sess, const string &name, Diskstream::F
init ();
use_new_playlist ();
+ use_new_write_source (0);
in_set_state = false;
@@ -101,6 +103,7 @@ MidiDiskstream::MidiDiskstream (Session& sess, const XMLNode& node)
, _frames_read_from_ringbuffer(0)
{
in_set_state = true;
+
init ();
if (set_state (node, Stateful::loading_state_version)) {
@@ -108,11 +111,9 @@ MidiDiskstream::MidiDiskstream (Session& sess, const XMLNode& node)
throw failed_constructor();
}
- in_set_state = false;
+ use_new_write_source (0);
- if (destructive()) {
- use_destructive_playlist ();
- }
+ in_set_state = false;
}
void
@@ -183,9 +184,10 @@ MidiDiskstream::non_realtime_input_change ()
/* implicit unlock */
}
- /* reset capture files */
-
- reset_write_sources (false);
+ /* unlike with audio, there is never any need to reset write sources
+ based on input configuration changes because ... a MIDI track
+ has just 1 MIDI port as input, always.
+ */
/* now refill channel buffers */
@@ -945,8 +947,23 @@ MidiDiskstream::transport_stopped_wallclock (struct tm& /*when*/, time_t /*twhen
/* figure out the name for this take */
srcs.push_back (_write_source);
+
_write_source->set_timeline_position (capture_info.front()->start);
_write_source->set_captured_for (_name);
+
+ /* flush to disk: this step differs from the audio path,
+ where all the data is already on disk.
+ */
+
+ _write_source->mark_streaming_write_completed ();
+
+ /* we will want to be able to keep (over)writing the source
+ but we don't want it to be removable. this also differs
+ from the audio situation, where the source at this point
+ must be considered immutable
+ */
+
+ _write_source->mark_nonremovable ();
string whole_file_region_name;
whole_file_region_name = region_name_from_path (_write_source->name(), true);
@@ -1021,11 +1038,11 @@ MidiDiskstream::transport_stopped_wallclock (struct tm& /*when*/, time_t /*twhen
_playlist->thaw ();
_session.add_command (new StatefulDiffCommand(_playlist));
}
- }
- mark_write_completed = true;
+ mark_write_completed = true;
+ }
- reset_write_sources (mark_write_completed);
+ use_new_write_source (0);
for (ci = capture_info.begin(); ci != capture_info.end(); ++ci) {
delete *ci;
@@ -1133,10 +1150,6 @@ MidiDiskstream::engage_record_enable ()
_source_port->request_monitor_input (!(_session.config.get_auto_input() && rolling));
}
- // FIXME: Why is this necessary? Isn't needed for AudioDiskstream...
- if (!_write_source)
- use_new_write_source();
-
_write_source->mark_streaming_midi_write_started (_note_mode, _session.transport_frame());
RecordEnableChanged (); /* EMIT SIGNAL */
@@ -1293,45 +1306,19 @@ MidiDiskstream::set_state (const XMLNode& node, int /*version*/)
in_set_state = false;
- /* make sure this is clear before we do anything else */
-
- // FIXME?
- //_capturing_source = 0;
-
- /* write sources are handled when we handle the input set
- up of the IO that owns this DS (::non_realtime_input_change())
- */
-
- in_set_state = false;
-
return 0;
}
int
MidiDiskstream::use_new_write_source (uint32_t n)
{
- cerr << name() << " use new write source for n = " << n << " recordable ? " << recordable() << endl;
-
if (!recordable()) {
return 1;
}
assert(n == 0);
- if (_write_source) {
-
- if (_write_source->is_empty ()) {
- /* remove any region that is using this empty source; they can result when MIDI recordings
- are made, but no MIDI data is received.
- */
- _playlist->remove_region_by_source (_write_source);
- _write_source->mark_for_remove ();
- _write_source->drop_references ();
- _write_source.reset();
- } else {
- _write_source.reset();
- }
- }
+ _write_source.reset();
try {
_write_source = boost::dynamic_pointer_cast<SMFSource>(_session.create_midi_source_for_session (0, name ()));
diff --git a/libs/ardour/midi_model.cc b/libs/ardour/midi_model.cc
index 57cbb70cfd..5926d403c3 100644
--- a/libs/ardour/midi_model.cc
+++ b/libs/ardour/midi_model.cc
@@ -780,7 +780,7 @@ MidiModel::DiffCommand::side_effect_remove(const NotePtr note)
source->mark_streaming_write_completed();
set_edited(false);
-
+
return true;
}
diff --git a/libs/ardour/midi_region.cc b/libs/ardour/midi_region.cc
index fe49547bf3..aad4bdfc67 100644
--- a/libs/ardour/midi_region.cc
+++ b/libs/ardour/midi_region.cc
@@ -51,7 +51,7 @@ using namespace PBD;
MidiRegion::MidiRegion (const SourceList& srcs)
: Region (srcs)
{
- midi_source(0)->Switched.connect_same_thread (*this, boost::bind (&MidiRegion::switch_source, this, _1));
+ // midi_source(0)->Switched.connect_same_thread (*this, boost::bind (&MidiRegion::switch_source, this, _1));
midi_source(0)->ModelChanged.connect_same_thread (_source_connection, boost::bind (&MidiRegion::model_changed, this));
model_changed ();
assert(_name.val().find("/") == string::npos);
@@ -63,7 +63,7 @@ MidiRegion::MidiRegion (boost::shared_ptr<const MidiRegion> other, frameoffset_t
: Region (other, offset, offset_relative)
{
assert(_name.val().find("/") == string::npos);
- midi_source(0)->Switched.connect_same_thread (*this, boost::bind (&MidiRegion::switch_source, this, _1));
+ // midi_source(0)->Switched.connect_same_thread (*this, boost::bind (&MidiRegion::switch_source, this, _1));
midi_source(0)->ModelChanged.connect_same_thread (_source_connection, boost::bind (&MidiRegion::model_changed, this));
model_changed ();
}
@@ -258,10 +258,13 @@ MidiRegion::switch_source(boost::shared_ptr<Source> src)
}
// MIDI regions have only one source
- _sources.clear();
- _sources.push_back(msrc);
+ SourceList srcs;
+ srcs.push_back (msrc);
- set_name(msrc->name());
+ drop_sources ();
+ use_sources (srcs);
+
+ set_name (msrc->name());
msrc->ModelChanged.connect_same_thread (_source_connection, boost::bind (&MidiRegion::model_changed, this));
}
diff --git a/libs/ardour/midi_source.cc b/libs/ardour/midi_source.cc
index 2e549b6fc6..36cd36795a 100644
--- a/libs/ardour/midi_source.cc
+++ b/libs/ardour/midi_source.cc
@@ -288,9 +288,19 @@ MidiSource::clone (Evoral::MusicalTime begin, Evoral::MusicalTime end)
void
MidiSource::session_saved()
{
+ /* this writes a copy of the data to disk.
+ XXX do we need to do this every time?
+ */
+
flush_midi();
+ cerr << name() << " @ " << this << " length at save = " << _length_beats << endl;
+
+#if 0 // old style: clone the source if necessary on every session save
+ // and switch to the new source
if (_model && _model->edited()) {
+ cerr << "Model exists and is edited\n";
+
boost::shared_ptr<MidiSource> newsrc = clone ();
if (newsrc) {
@@ -298,6 +308,7 @@ MidiSource::session_saved()
Switched (newsrc); /* EMIT SIGNAL */
}
}
+#endif
}
void
diff --git a/libs/ardour/region.cc b/libs/ardour/region.cc
index e620319633..0ae947063f 100644
--- a/libs/ardour/region.cc
+++ b/libs/ardour/region.cc
@@ -1381,6 +1381,7 @@ void
Region::set_master_sources (const SourceList& srcs)
{
for (SourceList::const_iterator i = _master_sources.begin (); i != _master_sources.end(); ++i) {
+ cerr << name() << " " << id() << " DEC M SMS\n";
(*i)->dec_use_count ();
}
@@ -1535,12 +1536,14 @@ void
Region::drop_sources ()
{
for (SourceList::const_iterator i = _sources.begin (); i != _sources.end(); ++i) {
+ cerr << name() << " " << id() << " DEC DS\n";
(*i)->dec_use_count ();
}
_sources.clear ();
for (SourceList::const_iterator i = _master_sources.begin (); i != _master_sources.end(); ++i) {
+ cerr << name() << " " << id() << " DEC MDS \n";
(*i)->dec_use_count ();
}
diff --git a/libs/ardour/region_factory.cc b/libs/ardour/region_factory.cc
index 65649ad8f7..b4beddfb64 100644
--- a/libs/ardour/region_factory.cc
+++ b/libs/ardour/region_factory.cc
@@ -73,7 +73,6 @@ RegionFactory::create (boost::shared_ptr<const Region> region)
}
if (ret) {
- cerr << "Pure copy constructor region " << ret << " named " << ret->name() << endl;
map_add (ret);
/* pure copy constructor - no property list */
@@ -125,7 +124,6 @@ RegionFactory::create (boost::shared_ptr<Region> region, frameoffset_t offset, b
if (ret) {
ret->set_properties (plist);
- cerr << "Partial copy constructor region\n";
map_add (ret);
if (announce) {
@@ -165,7 +163,6 @@ RegionFactory::create (boost::shared_ptr<Region> region, const SourceList& srcs,
if (ret) {
ret->set_properties (plist);
- cerr << "New sources copy constructor region\n";
map_add (ret);
if (announce) {
@@ -211,7 +208,6 @@ RegionFactory::create (const SourceList& srcs, const PropertyList& plist, bool a
if (ret) {
ret->set_properties (plist);
- cerr << "de-novo constructor region " << ret << " named " << ret->name() << endl;
map_add (ret);
if (announce) {
@@ -285,8 +281,6 @@ RegionFactory::map_add (boost::shared_ptr<Region> r)
boost::bind (&RegionFactory::region_changed, _1, boost::weak_ptr<Region> (r))
);
- cerr << "Added region with ID = " << r->id() << " named " << r->name() << endl;
-
update_region_name_map (r);
}
@@ -298,7 +292,6 @@ RegionFactory::map_remove (boost::shared_ptr<Region> r)
if (i != region_map.end()) {
region_map.erase (i);
- cerr << "Removed region with ID = " << r->id() << " named " << r->name() << endl;;
}
}
@@ -313,10 +306,8 @@ RegionFactory::map_remove_with_equivalents (boost::shared_ptr<Region> r)
++tmp;
if (r->region_list_equivalent (i->second)) {
- cerr << "Removed equivalent region " << i->second->name() << '/' << i->first << endl;
region_map.erase (i);
} else if (r == i->second) {
- cerr << "Removed actual region " << i->second->name() << '/' << i->first << endl;
region_map.erase (i);
}
diff --git a/libs/ardour/smf_source.cc b/libs/ardour/smf_source.cc
index 99d0e8c5e6..bf038326d5 100644
--- a/libs/ardour/smf_source.cc
+++ b/libs/ardour/smf_source.cc
@@ -99,6 +99,7 @@ SMFSource::SMFSource (Session& s, const XMLNode& node, bool must_exist)
SMFSource::~SMFSource ()
{
if (removable()) {
+ cerr << name() << " is removable, empty ? " << empty() << " UC " << use_count() << endl;
unlink (_path.c_str());
}
}
@@ -383,6 +384,7 @@ SMFSource::mark_streaming_write_completed ()
MidiSource::mark_streaming_write_completed();
if (!writable()) {
+ cerr << "\n\n\n[[[[[[[[[ This SMFS is not writable! ]]]]]]]]]]]\n\n\n";
return;
}
@@ -495,6 +497,11 @@ SMFSource::destroy_model ()
void
SMFSource::flush_midi ()
{
+ if (!writable()) {
+ cerr << "\n\n\n\n " << name() << " CANNOT FLUSH - not writable\n\n\n\n";
+ return;
+ }
+
Evoral::SMF::end_write();
}
diff --git a/libs/ardour/source.cc b/libs/ardour/source.cc
index 55ce9f8bef..894233f436 100644
--- a/libs/ardour/source.cc
+++ b/libs/ardour/source.cc
@@ -272,3 +272,17 @@ Source::set_allow_remove_if_empty (bool yn)
}
}
+void
+Source::dec_use_count ()
+{
+#ifndef NDEBUG
+ gint oldval = g_atomic_int_exchange_and_add (&_use_count, -1);
+ cerr << "Bad use dec for " << name() << endl;
+ if (oldval <= 0) {
+ abort ();
+ }
+ assert (oldval > 0);
+#else
+ g_atomic_int_exchange_and_add (&_use_count, -1);
+#endif
+}
diff --git a/libs/ardour/source_factory.cc b/libs/ardour/source_factory.cc
index 05e7513da9..357dbbadf8 100644
--- a/libs/ardour/source_factory.cc
+++ b/libs/ardour/source_factory.cc
@@ -285,8 +285,8 @@ SourceFactory::createWritable (DataType type, Session& s, const std::string& pat
return ret;
} else if (type == DataType::MIDI) {
-
- Source* src = new SMFSource (s, path, Source::Flag(0));
+ // XXX writable flags should belong to MidiSource too
+ Source* src = new SMFSource (s, path, SndFileSource::default_writable_flags);
// boost_debug_shared_ptr_mark_interesting (src, "Source");
boost::shared_ptr<Source> ret (src);
diff --git a/libs/evoral/src/SMF.cpp b/libs/evoral/src/SMF.cpp
index cf838455ce..5768b1cae3 100644
--- a/libs/evoral/src/SMF.cpp
+++ b/libs/evoral/src/SMF.cpp
@@ -275,7 +275,6 @@ SMF::begin_write()
void
SMF::end_write() THROW_FILE_ERROR
{
-#if 0
/* don't create empty MIDI files
*/
@@ -283,13 +282,14 @@ SMF::end_write() THROW_FILE_ERROR
if (smf_peek_next_event (_smf) == 0) {
return;
}
-#endif
PBD::StdioFileDescriptor d (_file_path, "w+");
FILE* f = d.allocate ();
if (f == 0) {
throw FileError ();
}
+
+ cerr << "\n\n\nSAVE SMF to " << _file_path << "\n\n";
if (smf_save(_smf, f) != 0) {
throw FileError();