diff options
author | David Robillard <d@drobilla.net> | 2008-02-19 03:24:44 +0000 |
---|---|---|
committer | David Robillard <d@drobilla.net> | 2008-02-19 03:24:44 +0000 |
commit | 012292b4bdf5bf843232243852b39e8892b837de (patch) | |
tree | cddefe42aab1301df0677d652d37ba757894d97b /libs/ardour | |
parent | b79d5bfad3473f54ab24c0b7852fc4bfc9d9ebb0 (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.h | 3 | ||||
-rw-r--r-- | libs/ardour/ardour/smf_reader.h | 4 | ||||
-rw-r--r-- | libs/ardour/automation_event.cc | 8 | ||||
-rw-r--r-- | libs/ardour/import.cc | 8 | ||||
-rw-r--r-- | libs/ardour/midi_model.cc | 6 | ||||
-rw-r--r-- | libs/ardour/midi_playlist.cc | 24 | ||||
-rw-r--r-- | libs/ardour/smf_reader.cc | 14 | ||||
-rw-r--r-- | libs/ardour/smf_source.cc | 47 |
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) { |