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 | |
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
-rw-r--r-- | gtk2_ardour/editor_actions.cc | 2 | ||||
-rw-r--r-- | gtk2_ardour/editor_audio_import.cc | 4 | ||||
-rw-r--r-- | gtk2_ardour/midi_time_axis.cc | 24 | ||||
-rw-r--r-- | gtk2_ardour/midi_time_axis.h | 1 | ||||
-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 |
12 files changed, 92 insertions, 53 deletions
diff --git a/gtk2_ardour/editor_actions.cc b/gtk2_ardour/editor_actions.cc index 14439f54a6..4d4ab99046 100644 --- a/gtk2_ardour/editor_actions.cc +++ b/gtk2_ardour/editor_actions.cc @@ -529,7 +529,7 @@ Editor::register_actions () /* the next two are duplicate items with different names for use in two different contexts */ - ActionManager::register_action (editor_actions, X_("addExistingAudioFiles"), _("Add Existing Media"), mem_fun (*this, &Editor::external_audio_dialog)); + ActionManager::register_action (editor_actions, X_("addExistingAudioFiles"), _("Import Existing Media"), mem_fun (*this, &Editor::external_audio_dialog)); act = ActionManager::register_action (editor_actions, X_("addExternalAudioToRegionList"), _("Add External Media"), bind (mem_fun(*this, &Editor::add_external_audio_action), ImportAsRegion)); ActionManager::session_sensitive_actions.push_back (act); diff --git a/gtk2_ardour/editor_audio_import.cc b/gtk2_ardour/editor_audio_import.cc index 3e1cf4f648..e13eb81181 100644 --- a/gtk2_ardour/editor_audio_import.cc +++ b/gtk2_ardour/editor_audio_import.cc @@ -734,7 +734,9 @@ Editor::add_sources (vector<Glib::ustring> paths, SourceList& sources, nframes64 } } - cout << "TARGET REGIONS: " << target_regions << endl; + // kludge (for MIDI we're abusing "channel" for "track" here) + if (paths.front().rfind(".mid") != Glib::ustring::npos) + target_regions = -1; if (target_regions == 1) { diff --git a/gtk2_ardour/midi_time_axis.cc b/gtk2_ardour/midi_time_axis.cc index cb72363f88..2c7429c85a 100644 --- a/gtk2_ardour/midi_time_axis.cc +++ b/gtk2_ardour/midi_time_axis.cc @@ -262,7 +262,8 @@ MidiTimeAxisView::set_note_range(MidiStreamView::VisibleNoteRange range) void -MidiTimeAxisView::update_range() { +MidiTimeAxisView::update_range() +{ MidiGhostRegion* mgr; for(list<GhostRegion*>::iterator i = ghosts.begin(); i != ghosts.end(); ++i) { @@ -272,6 +273,20 @@ MidiTimeAxisView::update_range() { } } +void +MidiTimeAxisView::show_existing_automation () +{ + if (midi_track()) { + const set<Parameter> params = midi_track()->midi_diskstream()-> + midi_playlist()->contained_automation(); + + for (set<Parameter>::const_iterator i = params.begin(); i != params.end(); ++i) + create_automation_child(*i, true); + } + + RouteTimeAxisView::show_existing_automation (); +} + /** Prompt for a controller with a dialog and add an automation track for it */ void @@ -298,7 +313,8 @@ MidiTimeAxisView::create_automation_child (Parameter param, bool show) { if (param.type() == MidiCCAutomation) { - /* FIXME: don't create AutomationList for track itself */ + /* FIXME: don't create AutomationList for track itself + * (not actually needed or used, since the automation is region-ey) */ boost::shared_ptr<AutomationControl> c = _route->control(param); @@ -308,6 +324,10 @@ MidiTimeAxisView::create_automation_child (Parameter param, bool show) _route->add_control(c); } + AutomationTracks::iterator existing = _automation_tracks.find(param); + if (existing != _automation_tracks.end()) + return; + boost::shared_ptr<AutomationTimeAxisView> track(new AutomationTimeAxisView (_session, _route, _route, c, editor, diff --git a/gtk2_ardour/midi_time_axis.h b/gtk2_ardour/midi_time_axis.h index efc987760b..a91bd01d21 100644 --- a/gtk2_ardour/midi_time_axis.h +++ b/gtk2_ardour/midi_time_axis.h @@ -65,6 +65,7 @@ class MidiTimeAxisView : public RouteTimeAxisView guint32 show_at (double y, int& nth, Gtk::VBox *parent); void hide (); + void show_existing_automation (); void add_controller_track (); void create_automation_child (ARDOUR::Parameter param, bool show); 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) { |