summaryrefslogtreecommitdiff
path: root/libs/ardour
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2008-02-19 03:24:44 +0000
committerDavid Robillard <d@drobilla.net>2008-02-19 03:24:44 +0000
commit012292b4bdf5bf843232243852b39e8892b837de (patch)
treecddefe42aab1301df0677d652d37ba757894d97b /libs/ardour
parentb79d5bfad3473f54ab24c0b7852fc4bfc9d9ebb0 (diff)
Less crash-happy MIDI reading on weird MIDI files.
Make "show existing automation" create/show automation tracks for all contained CC in MIDI tracks. Fix staggered time when importing multi-track MIDI files. git-svn-id: svn://localhost/ardour2/branches/3.0@3086 d708f5d6-7413-0410-9779-e7cbd77b26cf
Diffstat (limited to 'libs/ardour')
-rw-r--r--libs/ardour/ardour/midi_playlist.h3
-rw-r--r--libs/ardour/ardour/smf_reader.h4
-rw-r--r--libs/ardour/automation_event.cc8
-rw-r--r--libs/ardour/import.cc8
-rw-r--r--libs/ardour/midi_model.cc6
-rw-r--r--libs/ardour/midi_playlist.cc24
-rw-r--r--libs/ardour/smf_reader.cc14
-rw-r--r--libs/ardour/smf_source.cc47
8 files changed, 65 insertions, 49 deletions
diff --git a/libs/ardour/ardour/midi_playlist.h b/libs/ardour/ardour/midi_playlist.h
index 5838f5addd..dcc202bbf4 100644
--- a/libs/ardour/ardour/midi_playlist.h
+++ b/libs/ardour/ardour/midi_playlist.h
@@ -25,6 +25,7 @@
#include <ardour/ardour.h>
#include <ardour/playlist.h>
+#include <ardour/parameter.h>
namespace ARDOUR
{
@@ -56,6 +57,8 @@ public:
void set_note_mode (NoteMode m) { _note_mode = m; }
+ std::set<Parameter> contained_automation();
+
protected:
/* playlist "callbacks" */
diff --git a/libs/ardour/ardour/smf_reader.h b/libs/ardour/ardour/smf_reader.h
index 806844004e..a96ef6bf7f 100644
--- a/libs/ardour/ardour/smf_reader.h
+++ b/libs/ardour/ardour/smf_reader.h
@@ -65,13 +65,13 @@ public:
throw (std::logic_error, PrematureEOF, CorruptFile);
void close();
+
+ static uint32_t read_var_len(FILE* fd) throw (PrematureEOF);
protected:
/** size of SMF header, including MTrk chunk header */
static const uint32_t HEADER_SIZE = 22;
- uint32_t read_var_len() const throw(PrematureEOF);
-
std::string _filename;
FILE* _fd;
//TimeUnit _unit;
diff --git a/libs/ardour/automation_event.cc b/libs/ardour/automation_event.cc
index 3a80dddc76..ccf3c35104 100644
--- a/libs/ardour/automation_event.cc
+++ b/libs/ardour/automation_event.cc
@@ -1029,9 +1029,9 @@ AutomationList::build_search_cache_if_necessary(double start, double end) const
{
/* Only do the range lookup if x is in a different range than last time
* this was called (or if the search cache has been marked "dirty" (left<0) */
- if ((_search_cache.left < 0) ||
+ if (!_events.empty() && ((_search_cache.left < 0) ||
((_search_cache.left > start) ||
- (_search_cache.right < end))) {
+ (_search_cache.right < end)))) {
const ControlEvent start_point (start, 0);
const ControlEvent end_point (end, 0);
@@ -1140,7 +1140,9 @@ AutomationList::rt_safe_earliest_event_linear_unlocked (double start, double end
{
//cerr << "earliest_event(" << start << ", " << end << ", " << x << ", " << y << ", " << inclusive << endl;
- if (_events.size() < 2)
+ if (_events.size() == 0)
+ return false;
+ else if (_events.size() == 1)
return rt_safe_earliest_event_discrete_unlocked(start, end, x, y, inclusive);
// Hack to avoid infinitely repeating the same event
diff --git a/libs/ardour/import.cc b/libs/ardour/import.cc
index b028e1c1a7..60fb5eddb8 100644
--- a/libs/ardour/import.cc
+++ b/libs/ardour/import.cc
@@ -270,10 +270,6 @@ write_midi_data_to_new_files (SMFReader* source, Session::import_status& status,
{
MidiEvent ev(0.0, 4, NULL, true);
- uint64_t t = 0;
- uint32_t delta_t = 0;
- uint32_t size = 0;
-
status.progress = 0.0f;
try {
@@ -283,6 +279,10 @@ write_midi_data_to_new_files (SMFReader* source, Session::import_status& status,
boost::shared_ptr<SMFSource> smfs = boost::dynamic_pointer_cast<SMFSource>(newfiles[i-1]);
source->seek_to_track(i);
+
+ uint64_t t = 0;
+ uint32_t delta_t = 0;
+ uint32_t size = 0;
while (!status.cancel) {
diff --git a/libs/ardour/midi_model.cc b/libs/ardour/midi_model.cc
index 00fcd44021..44416713f8 100644
--- a/libs/ardour/midi_model.cc
+++ b/libs/ardour/midi_model.cc
@@ -276,12 +276,6 @@ MidiModel::read(MidiRingBuffer& dst, nframes_t start, nframes_t nframes, nframes
//cerr << "Using cached iterator at " << _next_read << endl;
}
- if (_read_iter == end()) {
- //cerr << this << " MM::read: at end @ " << _read_iter->time() << endl;
- } else {
- //cerr << this << " MM::read: at " << _read_iter->time() << endl;
- }
-
_next_read = start + nframes;
while (_read_iter != end() && _read_iter->time() < start + nframes) {
diff --git a/libs/ardour/midi_playlist.cc b/libs/ardour/midi_playlist.cc
index d8e59efd4a..d258d49524 100644
--- a/libs/ardour/midi_playlist.cc
+++ b/libs/ardour/midi_playlist.cc
@@ -265,6 +265,30 @@ MidiPlaylist::destroy_region (boost::shared_ptr<Region> region)
return changed;
}
+set<Parameter>
+MidiPlaylist::contained_automation()
+{
+ /* this function is never called from a realtime thread, so
+ its OK to block (for short intervals).
+ */
+
+ Glib::Mutex::Lock rm (region_lock);
+
+ set<Parameter> ret;
+
+ for (RegionList::const_iterator r = regions.begin(); r != regions.end(); ++r) {
+ boost::shared_ptr<MidiRegion> mr = boost::dynamic_pointer_cast<MidiRegion>(*r);
+
+ for (Automatable::Controls::iterator c = mr->controls().begin();
+ c != mr->controls().end(); ++c) {
+ ret.insert(c->first);
+ }
+ }
+
+ return ret;
+}
+
+
bool
MidiPlaylist::region_changed (Change what_changed, boost::shared_ptr<Region> region)
{
diff --git a/libs/ardour/smf_reader.cc b/libs/ardour/smf_reader.cc
index 21ca370e6c..20204f1d32 100644
--- a/libs/ardour/smf_reader.cc
+++ b/libs/ardour/smf_reader.cc
@@ -194,7 +194,7 @@ SMFReader::read_event(size_t buf_len,
static uint8_t last_status = 0;
static uint32_t last_size = 0;
- *delta_time = read_var_len();
+ *delta_time = read_var_len(_fd);
int status = fgetc(_fd);
if (status == EOF)
throw PrematureEOF();
@@ -222,7 +222,7 @@ SMFReader::read_event(size_t buf_len,
if (feof(_fd))
throw PrematureEOF();
uint8_t type = fgetc(_fd);
- const uint32_t size = read_var_len();
+ const uint32_t size = read_var_len(_fd);
/*cerr.flags(ios::hex);
cerr << "SMF - meta 0x" << (int)type << ", size = ";
cerr.flags(ios::dec);
@@ -269,20 +269,20 @@ SMFReader::close()
uint32_t
-SMFReader::read_var_len() const throw(PrematureEOF)
+SMFReader::read_var_len(FILE* fd) throw (PrematureEOF)
{
- if (feof(_fd))
+ if (feof(fd))
throw PrematureEOF();
uint32_t value;
uint8_t c;
- if ( (value = getc(_fd)) & 0x80 ) {
+ if ( (value = getc(fd)) & 0x80 ) {
value &= 0x7F;
do {
- if (feof(_fd))
+ if (feof(fd))
throw PrematureEOF();
- value = (value << 7) + ((c = getc(_fd)) & 0x7F);
+ value = (value << 7) + ((c = getc(fd)) & 0x7F);
} while (c & 0x80);
}
diff --git a/libs/ardour/smf_source.cc b/libs/ardour/smf_source.cc
index 4903cf384f..85cebf2b09 100644
--- a/libs/ardour/smf_source.cc
+++ b/libs/ardour/smf_source.cc
@@ -38,6 +38,7 @@
#include <ardour/midi_util.h>
#include <ardour/tempo.h>
#include <ardour/audioengine.h>
+#include <ardour/smf_reader.h>
#include "i18n.h"
@@ -272,20 +273,31 @@ SMFSource::read_event(uint32_t* delta_t, uint32_t* size, Byte** buf) const
assert(size);
assert(buf);
- *delta_t = read_var_len();
- assert(!feof(_fd));
+ try {
+ *delta_t = SMFReader::read_var_len(_fd);
+ } catch (...) {
+ return -1; // Premature EOF
+ }
+
+ if (feof(_fd)) {
+ return -1; // Premature EOF
+ }
const int status = fgetc(_fd);
- assert(status != EOF); // FIXME die gracefully
+
+ if (status == EOF) {
+ return -1; // Premature EOF
+ }
//printf("Status @ %X = %X\n", (unsigned)ftell(_fd) - 1, status);
if (status == 0xFF) {
- assert(!feof(_fd));
+ if (feof(_fd)) {
+ return -1; // Premature EOF
+ }
const int type = fgetc(_fd);
if ((unsigned char)type == 0x2F) {
- //cerr << _name << " hit EOT" << endl;
- return -1;
+ return -1; // hit end of track
} else {
*size = 0;
return 0;
@@ -444,12 +456,12 @@ SMFSource::write_unlocked (MidiRingBuffer& src, nframes_t cnt)
void
SMFSource::append_event_unlocked(const MidiEvent& ev)
{
- printf("%s - append chan = %u, time = %lf, size = %u, data = ", _path.c_str(),
+ /*printf("%s - append chan = %u, time = %lf, size = %u, data = ", _path.c_str(),
(unsigned)ev.channel(), ev.time(), ev.size());
for (size_t i=0; i < ev.size(); ++i) {
printf("%X ", ev.buffer()[i]);
}
- printf("\n");
+ printf("\n");*/
assert(ev.time() >= 0);
assert(ev.time() >= _last_ev_time);
@@ -838,25 +850,6 @@ SMFSource::write_var_len(uint32_t value)
return ret;
}
-uint32_t
-SMFSource::read_var_len() const
-{
- assert(!feof(_fd));
-
- uint32_t value;
- unsigned char c;
-
- if ( (value = getc(_fd)) & 0x80 ) {
- value &= 0x7F;
- do {
- assert(!feof(_fd));
- value = (value << 7) + ((c = getc(_fd)) & 0x7F);
- } while (c & 0x80);
- }
-
- return value;
-}
-
void
SMFSource::load_model(bool lock, bool force_reload)
{