From 12d62cd16eee280e0b23a0c943bc07a573a9f80c Mon Sep 17 00:00:00 2001 From: Damien Zammit Date: Wed, 6 Jan 2021 17:06:54 +1100 Subject: [PATCH] pt import: Fix race condition/threading, don't call new_audio_track() in bg thread --- gtk2_ardour/editor_pt_import.cc | 12 +++-- libs/ardour/ardour/session.h | 15 +++++- libs/ardour/import_pt.cc | 91 ++++++++++++++++----------------- 3 files changed, 66 insertions(+), 52 deletions(-) diff --git a/gtk2_ardour/editor_pt_import.cc b/gtk2_ardour/editor_pt_import.cc index 8c9ac6c82f..f5e73db4d5 100644 --- a/gtk2_ardour/editor_pt_import.cc +++ b/gtk2_ardour/editor_pt_import.cc @@ -97,19 +97,21 @@ Editor::external_pt_dialog () ipw.show(); - while (!import_pt_status.all_done) { + while (!import_pt_status.all_done && !import_pt_status.cancel) { gtk_main_iteration (); } // wait for thread to terminate - while (!import_pt_status.done) { + while (!import_pt_status.done && !import_pt_status.cancel) { gtk_main_iteration (); } if (import_pt_status.cancel) { - MessageDialog msg (_("PT import may have missing files, check session log for details")); + MessageDialog msg (_("PT import cancelled")); msg.run (); } else { + _session->import_pt_rest (import_ptf); + import_pt_status.progress = 1.0; MessageDialog msg (_("PT import complete!")); msg.run (); } @@ -118,7 +120,7 @@ Editor::external_pt_dialog () void * Editor::_import_pt_thread (void *arg) { - SessionEvent::create_per_thread_pool ("import pt events", 2048); + SessionEvent::create_per_thread_pool ("import pt events", 64); Editor *ed = (Editor *) arg; return ed->import_pt_thread (); @@ -127,6 +129,6 @@ Editor::_import_pt_thread (void *arg) void * Editor::import_pt_thread () { - _session->import_pt (import_ptf, import_pt_status); + _session->import_pt_sources (import_ptf, import_pt_status); return 0; } diff --git a/libs/ardour/ardour/session.h b/libs/ardour/ardour/session.h index 701c5860af..9676889846 100644 --- a/libs/ardour/ardour/session.h +++ b/libs/ardour/ardour/session.h @@ -1276,9 +1276,22 @@ public: bool transport_master_no_external_or_using_engine() const; boost::shared_ptr transport_master() const; - void import_pt (PTFFormat& ptf, ImportStatus& status); + void import_pt_sources (PTFFormat& ptf, ImportStatus& status); + void import_pt_rest (PTFFormat& ptf); bool import_sndfile_as_region (std::string path, SrcQuality quality, samplepos_t& pos, SourceList& sources, ImportStatus& status); + struct ptflookup { + uint16_t index1; + uint16_t index2; + PBD::ID id; + + bool operator ==(const struct ptflookup& other) { + return (this->index1 == other.index1); + } + }; + std::vector ptfwavpair; + SourceList pt_imported_sources; + protected: friend class AudioEngine; void set_block_size (pframes_t nframes); diff --git a/libs/ardour/import_pt.cc b/libs/ardour/import_pt.cc index aa5da5a1ad..050368e310 100644 --- a/libs/ardour/import_pt.cc +++ b/libs/ardour/import_pt.cc @@ -67,17 +67,6 @@ struct midipair { string trname; }; -typedef struct ptflookup { - uint16_t index1; - uint16_t index2; - PBD::ID id; - - bool operator ==(const struct ptflookup& other) { - return (this->index1 == other.index1); - } -} ptflookup_t; - - bool Session::import_sndfile_as_region (string path, SrcQuality quality, samplepos_t& pos, SourceList& sources, ImportStatus& status) { @@ -185,7 +174,7 @@ Session::import_sndfile_as_region (string path, SrcQuality quality, samplepos_t& void -Session::import_pt (PTFFormat& ptf, ImportStatus& status) +Session::import_pt_sources (PTFFormat& ptf, ImportStatus& status) { vector > regions; boost::shared_ptr track; @@ -195,22 +184,21 @@ Session::import_pt (PTFFormat& ptf, ImportStatus& status) bool ok = false; bool onefailed = false; samplepos_t pos = -1; - uint32_t srate = sample_rate (); - vector ptfwavpair; - vector ptfregpair; + vector ptfregpair; vector::const_iterator w; SourceList just_one_src; - SourceList imported; boost::shared_ptr existing_track; - uint16_t nth = 0; - vector usedtracks; - ptflookup_t utr; + vector usedtracks; + struct ptflookup utr; + + ptfwavpair.clear(); + pt_imported_sources.clear(); for (w = ptf.audiofiles ().begin (); w != ptf.audiofiles ().end () && !status.cancel; ++w) { - ptflookup_t p; + struct ptflookup p; ok = false; /* Try audio file */ fullpath = Glib::build_filename (Glib::path_get_dirname (ptf.path ()), "Audio Files"); @@ -244,7 +232,7 @@ Session::import_pt (PTFFormat& ptf, ImportStatus& status) p.index1 = w->index; p.id = source->id (); ptfwavpair.push_back (p); - imported.push_back (source); + pt_imported_sources.push_back (source); warning << string_compose (_("PT Import : MISSING `%1`, inserting ref to missing source"), fullpath) << endmsg; } else { warning << string_compose (_("PT Import : MISSING `%1`, please check Audio Files"), fullpath) << endmsg; @@ -256,28 +244,54 @@ Session::import_pt (PTFFormat& ptf, ImportStatus& status) p.id = just_one_src.back ()->id (); ptfwavpair.push_back (p); - imported.push_back (just_one_src.back ()); + pt_imported_sources.push_back (just_one_src.back ()); } } - if (imported.empty ()) { + if (pt_imported_sources.empty ()) { error << _("Failed to find any audio for PT import") << endmsg; - goto trymidi; } else if (onefailed) { warning << _("Failed to load one or more of the audio files for PT import, see above list") << endmsg; } else { info << _("All audio files found for PT import!") << endmsg; } + status.progress = 1.0; + status.sources.clear (); + status.done = true; + status.all_done = true; +} + + +void +Session::import_pt_rest (PTFFormat& ptf) +{ + vector > regions; + boost::shared_ptr track; + ARDOUR::PluginInfoPtr instrument; + vector to_import; + string fullpath; + uint32_t srate = sample_rate (); + + vector ptfregpair; + vector::const_iterator w; + + SourceList just_one_src; + + boost::shared_ptr existing_track; + uint16_t nth = 0; + vector usedtracks; + struct ptflookup utr; + for (vector::const_iterator a = ptf.regions ().begin (); a != ptf.regions ().end (); ++a) { - for (vector::iterator p = ptfwavpair.begin (); + for (vector::iterator p = ptfwavpair.begin (); p != ptfwavpair.end (); ++p) { if ((p->index1 == a->wave.index) && (strcmp (a->wave.filename.c_str (), "") != 0)) { - for (SourceList::iterator x = imported.begin (); x != imported.end (); ++x) { + for (SourceList::iterator x = pt_imported_sources.begin (); x != pt_imported_sources.end (); ++x) { if ((*x)->id () == p->id) { /* Matched an uncreated ptf region to ardour region */ - ptflookup_t rp; + struct ptflookup rp; PropertyList plist; plist.add (ARDOUR::Properties::start, a->sampleoffset); @@ -304,7 +318,7 @@ Session::import_pt (PTFFormat& ptf, ImportStatus& status) } for (vector::const_iterator a = ptf.tracks ().begin (); a != ptf.tracks ().end (); ++a) { - for (vector::iterator p = ptfregpair.begin (); + for (vector::iterator p = ptfregpair.begin (); p != ptfregpair.end (); ++p) { if (p->index1 == a->reg.index) { @@ -314,8 +328,8 @@ Session::import_pt (PTFFormat& ptf, ImportStatus& status) utr.index2 = nth; utr.id = p->id; boost::shared_ptr r = RegionFactory::region_by_id (p->id); - vector::iterator lookuptr = usedtracks.begin (); - vector::iterator found; + vector::iterator lookuptr = usedtracks.begin (); + vector::iterator found; if ((found = std::find (lookuptr, usedtracks.end (), utr)) != usedtracks.end ()) { DEBUG_TRACE (DEBUG::FileUtils, string_compose ("\twav(%1) reg(%2) ptf_tr(%3) ard_tr(%4)\n", a->reg.wave.filename.c_str (), a->reg.index, found->index1, found->index2)); @@ -367,16 +381,6 @@ Session::import_pt (PTFFormat& ptf, ImportStatus& status) } } -trymidi: - status.paths.clear(); - status.paths.push_back(ptf.path ()); - status.current = 1; - status.total = 1; - status.freeze = false; - status.done = false; - status.cancel = false; - status.progress = 0; - /* MIDI - Find list of unique midi tracks first */ vector uniquetr; @@ -398,7 +402,7 @@ trymidi: std::map > midi_tracks; /* MIDI - Create unique midi tracks and a lookup table for used tracks */ for (vector::iterator a = uniquetr.begin (); a != uniquetr.end (); ++a) { - ptflookup_t miditr; + struct ptflookup miditr; list > mt (new_midi_track ( ChanCount (DataType::MIDI, 1), ChanCount (DataType::MIDI, 1), @@ -450,9 +454,4 @@ trymidi: playlist->clear_changes (); playlist->add_region (copy, f); } - - status.progress = 1.0; - status.done = true; - status.sources.clear (); - status.all_done = true; }