diff options
Diffstat (limited to 'libs/ardour/session.cc')
-rw-r--r-- | libs/ardour/session.cc | 312 |
1 files changed, 158 insertions, 154 deletions
diff --git a/libs/ardour/session.cc b/libs/ardour/session.cc index 7d5f838499..0a85c47cb9 100644 --- a/libs/ardour/session.cc +++ b/libs/ardour/session.cc @@ -71,6 +71,7 @@ #include <ardour/click.h> #include <ardour/data_type.h> #include <ardour/buffer_set.h> +#include <ardour/source_factory.h> #ifdef HAVE_LIBLO #include <ardour/osc.h> @@ -282,10 +283,12 @@ Session::Session (AudioEngine &eng, first_stage_init (fullpath, snapshot_name); if (create (new_session, mix_template, _engine.frame_rate() * 60 * 5)) { + cerr << "create failed\n"; throw failed_constructor (); } if (second_stage_init (new_session)) { + cerr << "2nd state failed\n"; throw failed_constructor (); } @@ -386,9 +389,23 @@ Session::~Session () _state_of_the_state = StateOfTheState (CannotSave|Deletion); _engine.remove_session (); + + GoingAway (); /* EMIT SIGNAL */ - going_away (); /* EMIT SIGNAL */ + /* do this */ + + notify_callbacks (); + + /* clear history so that no references to objects are held any more */ + + history.clear (); + + /* clear state tree so that no references to objects are held any more */ + if (state_tree) { + delete state_tree; + } + terminate_butler_thread (); //terminate_midi_thread (); @@ -439,16 +456,12 @@ Session::~Session () #ifdef TRACK_DESTRUCTION cerr << "delete regions\n"; #endif /* TRACK_DESTRUCTION */ - for (RegionList::iterator i = regions.begin(); i != regions.end(); ) { - RegionList::iterator tmp; - - tmp =i; - ++tmp; - - delete i->second; - - i = tmp; + + for (RegionList::iterator i = regions.begin(); i != regions.end(); ++i) { + i->second->drop_references (); } + + regions.clear (); #ifdef TRACK_DESTRUCTION cerr << "delete routes\n"; @@ -456,12 +469,8 @@ Session::~Session () { RCUWriter<RouteList> writer (routes); boost::shared_ptr<RouteList> r = writer.get_copy (); - for (RouteList::iterator i = r->begin(); i != r->end(); ) { - RouteList::iterator tmp; - tmp = i; - ++tmp; + for (RouteList::iterator i = r->begin(); i != r->end(); ++i) { (*i)->drop_references (); - i = tmp; } r->clear (); /* writer goes out of scope and updates master */ @@ -475,15 +484,8 @@ Session::~Session () { RCUWriter<DiskstreamList> dwriter (diskstreams); boost::shared_ptr<DiskstreamList> dsl = dwriter.get_copy(); - for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ) { - DiskstreamList::iterator tmp; - - tmp = i; - ++tmp; - + for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) { (*i)->drop_references (); - - i = tmp; } dsl->clear (); } @@ -492,17 +494,19 @@ Session::~Session () #ifdef TRACK_DESTRUCTION cerr << "delete audio sources\n"; #endif /* TRACK_DESTRUCTION */ - for (SourceList::iterator i = sources.begin(); i != sources.end(); ) { - SourceList::iterator tmp; + for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) { + SourceMap::iterator tmp; tmp = i; ++tmp; - delete i->second; + i->second->drop_references (); i = tmp; } + sources.clear (); + #ifdef TRACK_DESTRUCTION cerr << "delete mix groups\n"; #endif /* TRACK_DESTRUCTION */ @@ -558,10 +562,6 @@ Session::~Session () if (mmc) { delete mmc; } - - if (state_tree) { - delete state_tree; - } } void @@ -2712,8 +2712,9 @@ Session::region_name (string& result, string base, bool newlevel) const } void -Session::add_region (Region* region) +Session::add_region (boost::shared_ptr<Region> region) { + boost::shared_ptr<Region> other; bool added = false; { @@ -2723,7 +2724,9 @@ Session::add_region (Region* region) for (x = regions.begin(); x != regions.end(); ++x) { - if (region->region_list_equivalent (*x->second)) { + other = x->second; + + if (region->region_list_equivalent (other)) { break; } } @@ -2737,6 +2740,7 @@ Session::add_region (Region* region) pair<RegionList::iterator,bool> x = regions.insert (entry); + if (!x.second) { return; } @@ -2748,19 +2752,19 @@ Session::add_region (Region* region) /* mark dirty because something has changed even if we didn't add the region to the region list. - */ - + */ + set_dirty(); - + if (added) { - region->GoingAway.connect (mem_fun (*this, &Session::remove_region)); + region->GoingAway.connect (sigc::bind (mem_fun (*this, &Session::remove_region), region)); region->StateChanged.connect (sigc::bind (mem_fun (*this, &Session::region_changed), region)); RegionAdded (region); /* EMIT SIGNAL */ } } void -Session::region_changed (Change what_changed, Region* region) +Session::region_changed (Change what_changed, boost::shared_ptr<Region> region) { if (what_changed & Region::HiddenChanged) { /* relay hidden changes */ @@ -2769,17 +2773,17 @@ Session::region_changed (Change what_changed, Region* region) } void -Session::region_renamed (Region* region) +Session::region_renamed (boost::shared_ptr<Region> region) { add_region (region); } void -Session::remove_region (Region* region) +Session::remove_region (boost::shared_ptr<Region> region) { RegionList::iterator i; bool removed = false; - + { Glib::Mutex::Lock lm (region_lock); @@ -2787,25 +2791,25 @@ Session::remove_region (Region* region) regions.erase (i); removed = true; } - } /* mark dirty because something has changed even if we didn't remove the region from the region list. - */ + */ set_dirty(); if (removed) { - RegionRemoved(region); /* EMIT SIGNAL */ + RegionRemoved(region); /* EMIT SIGNAL */ } } -Region* +boost::shared_ptr<Region> Session::find_whole_file_parent (Region& child) { RegionList::iterator i; - Region* region; + boost::shared_ptr<Region> region; + Glib::Mutex::Lock lm (region_lock); for (i = regions.begin(); i != regions.end(); ++i) { @@ -2814,49 +2818,51 @@ Session::find_whole_file_parent (Region& child) if (region->whole_file()) { - if (child.source_equivalent (*region)) { + if (child.source_equivalent (region)) { return region; } } } - return 0; + return boost::shared_ptr<AudioRegion> ((AudioRegion*) 0); } void -Session::find_equivalent_playlist_regions (Region& region, vector<Region*>& result) +Session::find_equivalent_playlist_regions (boost::shared_ptr<Region> region, vector<boost::shared_ptr<Region> >& result) { for (PlaylistList::iterator i = playlists.begin(); i != playlists.end(); ++i) (*i)->get_region_list_equivalent_regions (region, result); } int -Session::destroy_region (Region* region) +Session::destroy_region (boost::shared_ptr<Region> region) { - AudioRegion* aregion; + boost::shared_ptr<AudioRegion> aregion; - if ((aregion = dynamic_cast<AudioRegion*> (region)) == 0) { + if ((aregion = boost::dynamic_pointer_cast<AudioRegion> (region)) == 0) { return 0; } - + if (aregion->playlist()) { aregion->playlist()->destroy_region (region); } - vector<Source*> srcs; + vector<boost::shared_ptr<Source> > srcs; for (uint32_t n = 0; n < aregion->n_channels(); ++n) { - srcs.push_back (&aregion->source (n)); + srcs.push_back (aregion->source (n)); } - for (vector<Source*>::iterator i = srcs.begin(); i != srcs.end(); ++i) { + for (vector<boost::shared_ptr<Source> >::iterator i = srcs.begin(); i != srcs.end(); ++i) { - if ((*i)->use_cnt() == 0) { - AudioFileSource* afs = dynamic_cast<AudioFileSource*>(*i); + if ((*i).use_count() == 1) { + boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource>(*i); + if (afs) { (afs)->mark_for_remove (); } - delete *i; + + (*i)->drop_references (); } } @@ -2864,9 +2870,9 @@ Session::destroy_region (Region* region) } int -Session::destroy_regions (list<Region*> regions) +Session::destroy_regions (list<boost::shared_ptr<Region> > regions) { - for (list<Region*>::iterator i = regions.begin(); i != regions.end(); ++i) { + for (list<boost::shared_ptr<Region> >::iterator i = regions.begin(); i != regions.end(); ++i) { destroy_region (*i); } return 0; @@ -2875,12 +2881,12 @@ Session::destroy_regions (list<Region*> regions) int Session::remove_last_capture () { - list<Region*> r; + list<boost::shared_ptr<Region> > r; boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader(); for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) { - list<Region*>& l = (*i)->last_capture_regions(); + list<boost::shared_ptr<Region> >& l = (*i)->last_capture_regions(); if (!l.empty()) { r.insert (r.end(), l.begin(), l.end()); @@ -2893,62 +2899,77 @@ Session::remove_last_capture () } int -Session::remove_region_from_region_list (Region& r) +Session::remove_region_from_region_list (boost::shared_ptr<Region> r) { - remove_region (&r); + remove_region (r); return 0; } /* Source Management */ void -Session::add_source (Source* source) +Session::add_source (boost::shared_ptr<Source> source) { - pair<SourceList::key_type, SourceList::mapped_type> entry; + cerr << "add new source " << source->name() << endl; + + pair<SourceMap::key_type, SourceMap::mapped_type> entry; + pair<SourceMap::iterator,bool> result; - { - Glib::Mutex::Lock lm (source_lock); - entry.first = source->id(); - entry.second = source; - sources.insert (entry); - } + entry.first = source->id(); + entry.second = source; - source->GoingAway.connect (mem_fun (this, &Session::remove_source)); + { + Glib::Mutex::Lock lm (source_lock); + result = sources.insert (entry); + } + + if (!result.second) { + cerr << "\tNOT inserted ? " << result.second << endl; + } + + source->GoingAway.connect (sigc::bind (mem_fun (this, &Session::remove_source), boost::weak_ptr<Source> (source))); set_dirty(); SourceAdded (source); /* EMIT SIGNAL */ } void -Session::remove_source (Source* source) +Session::remove_source (boost::weak_ptr<Source> src) { - SourceList::iterator i; + SourceMap::iterator i; + boost::shared_ptr<Source> source = src.lock(); - { - Glib::Mutex::Lock lm (source_lock); - - if ((i = sources.find (source->id())) != sources.end()) { - sources.erase (i); - } - } - - if (!_state_of_the_state & InCleanup) { - - /* save state so we don't end up with a session file - referring to non-existent sources. - */ + if (!source) { + cerr << "removing a source DEAD\n"; + } else { + cerr << "removing a source " << source->name () << endl; - save_state (_current_snapshot_name); + { + Glib::Mutex::Lock lm (source_lock); + + if ((i = sources.find (source->id())) != sources.end()) { + sources.erase (i); + } + } + + if (!_state_of_the_state & InCleanup) { + + /* save state so we don't end up with a session file + referring to non-existent sources. + */ + + save_state (_current_snapshot_name); + } + + SourceRemoved(source); /* EMIT SIGNAL */ } - - SourceRemoved(source); /* EMIT SIGNAL */ } -Source * +boost::shared_ptr<Source> Session::source_by_id (const PBD::ID& id) { Glib::Mutex::Lock lm (source_lock); - SourceList::iterator i; - Source* source = 0; + SourceMap::iterator i; + boost::shared_ptr<Source> source; if ((i = sources.find (id)) != sources.end()) { source = i->second; @@ -3194,24 +3215,11 @@ Session::audio_path_from_name (string name, uint32_t nchan, uint32_t chan, bool return spath; } -AudioFileSource * +boost::shared_ptr<AudioFileSource> Session::create_audio_source_for_session (AudioDiskstream& ds, uint32_t chan, bool destructive) { string spath = audio_path_from_name (ds.name(), ds.n_channels().get(DataType::AUDIO), chan, destructive); - - /* this might throw failed_constructor(), which is OK */ - - if (destructive) { - return new DestructiveFileSource (spath, - Config->get_native_file_data_format(), - Config->get_native_file_header_format(), - frame_rate()); - } else { - return new SndFileSource (spath, - Config->get_native_file_data_format(), - Config->get_native_file_header_format(), - frame_rate()); - } + return boost::dynamic_pointer_cast<AudioFileSource> (SourceFactory::createWritable (DataType::AUDIO, spath, destructive, frame_rate())); } string @@ -3277,13 +3285,12 @@ Session::midi_path_from_name (string name) return spath; } -MidiSource * +boost::shared_ptr<MidiSource> Session::create_midi_source_for_session (MidiDiskstream& ds) { string spath = midi_path_from_name (ds.name()); - - /* this might throw failed_constructor(), which is OK */ - return new SMFSource (spath); + + return boost::dynamic_pointer_cast<SMFSource> (SourceFactory::createWritable (DataType::MIDI, spath, false, frame_rate())); } @@ -3319,7 +3326,7 @@ Session::add_playlist (Playlist* playlist) playlists.insert (playlists.begin(), playlist); // playlist->ref(); playlist->InUse.connect (mem_fun (*this, &Session::track_playlist)); - playlist->GoingAway.connect (mem_fun (*this, &Session::remove_playlist)); + playlist->GoingAway.connect (sigc::bind (mem_fun (*this, &Session::remove_playlist), playlist)); } } @@ -3390,7 +3397,7 @@ Session::remove_playlist (Playlist* playlist) } void -Session::set_audition (AudioRegion* r) +Session::set_audition (boost::shared_ptr<Region> r) { pending_audition_region = r; post_transport_work = PostTransportWork (post_transport_work | PostTransportAudition); @@ -3398,42 +3405,39 @@ Session::set_audition (AudioRegion* r) } void +Session::audition_playlist () +{ + Event* ev = new Event (Event::Audition, Event::Add, Event::Immediate, 0, 0.0); + ev->region.reset (); + queue_event (ev); +} + +void Session::non_realtime_set_audition () { - if (pending_audition_region == (AudioRegion*) 0xfeedface) { + if (!pending_audition_region) { auditioner->audition_current_playlist (); - } else if (pending_audition_region) { - auditioner->audition_region (*pending_audition_region); + } else { + auditioner->audition_region (pending_audition_region); + pending_audition_region.reset (); } - pending_audition_region = 0; AuditionActive (true); /* EMIT SIGNAL */ } void -Session::audition_playlist () +Session::audition_region (boost::shared_ptr<Region> r) { Event* ev = new Event (Event::Audition, Event::Add, Event::Immediate, 0, 0.0); - ev->set_ptr ((void*) 0xfeedface); + ev->region = r; queue_event (ev); } void -Session::audition_region (Region& r) -{ - AudioRegion* ar = dynamic_cast<AudioRegion*>(&r); - if (ar) { - Event* ev = new Event (Event::Audition, Event::Add, Event::Immediate, 0, 0.0); - ev->set_ptr (ar); - queue_event (ev); - } -} - -void Session::cancel_audition () { if (auditioner->active()) { auditioner->cancel_audition (); - AuditionActive (false); /* EMIT SIGNAL */ + AuditionActive (false); /* EMIT SIGNAL */ } } @@ -3600,7 +3604,7 @@ Session::add_redirect (Redirect* redirect) /*NOTREACHED*/ } - redirect->GoingAway.connect (mem_fun (*this, &Session::remove_redirect)); + redirect->GoingAway.connect (sigc::bind (mem_fun (*this, &Session::remove_redirect), redirect)); set_dirty(); } @@ -3822,9 +3826,9 @@ Session::route_name_unique (string n) const } int -Session::cleanup_audio_file_source (AudioFileSource& fs) +Session::cleanup_audio_file_source (boost::shared_ptr<AudioFileSource> fs) { - return fs.move_to_trash (dead_sound_dir_name); + return fs->move_to_trash (dead_sound_dir_name); } uint32_t @@ -3891,11 +3895,12 @@ Session::freeze (InterThreadInfo& itt) int Session::write_one_audio_track (AudioTrack& track, jack_nframes_t start, jack_nframes_t len, - bool overwrite, vector<Source*>& srcs, InterThreadInfo& itt) + bool overwrite, vector<boost::shared_ptr<Source> >& srcs, InterThreadInfo& itt) { + boost::shared_ptr<AudioFileSource> fsource; + int ret = -1; Playlist* playlist = 0; - AudioFileSource* fsource = 0; uint32_t x; char buf[PATH_MAX+1]; string dir; @@ -3939,11 +3944,7 @@ Session::write_one_audio_track (AudioTrack& track, jack_nframes_t start, jack_nf } try { - fsource = new SndFileSource (buf, - Config->get_native_file_data_format(), - Config->get_native_file_header_format(), - frame_rate()); - + fsource = boost::dynamic_pointer_cast<AudioFileSource> (SourceFactory::createWritable (DataType::AUDIO, buf, false, frame_rate())); } catch (failed_constructor& err) { @@ -3951,7 +3952,7 @@ Session::write_one_audio_track (AudioTrack& track, jack_nframes_t start, jack_nf goto out; } - srcs.push_back(fsource); + srcs.push_back (fsource); } /* XXX need to flush all redirects */ @@ -3972,9 +3973,9 @@ Session::write_one_audio_track (AudioTrack& track, jack_nframes_t start, jack_nf } uint32_t n = 0; - for (vector<Source*>::iterator src=srcs.begin(); src != srcs.end(); ++src, ++n) { - AudioFileSource* afs = dynamic_cast<AudioFileSource*>(*src); - + for (vector<boost::shared_ptr<Source> >::iterator src=srcs.begin(); src != srcs.end(); ++src, ++n) { + boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource>(*src); + if (afs) { if (afs->write (buffers.get_audio(n).data(this_chunk), this_chunk) != this_chunk) { goto out; @@ -3996,8 +3997,9 @@ Session::write_one_audio_track (AudioTrack& track, jack_nframes_t start, jack_nf time (&now); xnow = localtime (&now); - for (vector<Source*>::iterator src=srcs.begin(); src != srcs.end(); ++src) { - AudioFileSource* afs = dynamic_cast<AudioFileSource*>(*src); + for (vector<boost::shared_ptr<Source> >::iterator src=srcs.begin(); src != srcs.end(); ++src) { + boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource>(*src); + if (afs) { afs->update_header (position, *xnow, now); } @@ -4005,8 +4007,8 @@ Session::write_one_audio_track (AudioTrack& track, jack_nframes_t start, jack_nf /* build peakfile for new source */ - for (vector<Source*>::iterator src=srcs.begin(); src != srcs.end(); ++src) { - AudioFileSource* afs = dynamic_cast<AudioFileSource*>(*src); + for (vector<boost::shared_ptr<Source> >::iterator src=srcs.begin(); src != srcs.end(); ++src) { + boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource>(*src); if (afs) { afs->build_peaks (); } @@ -4017,12 +4019,14 @@ Session::write_one_audio_track (AudioTrack& track, jack_nframes_t start, jack_nf out: if (ret) { - for (vector<Source*>::iterator src=srcs.begin(); src != srcs.end(); ++src) { - AudioFileSource* afs = dynamic_cast<AudioFileSource*>(*src); + for (vector<boost::shared_ptr<Source> >::iterator src = srcs.begin(); src != srcs.end(); ++src) { + boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource>(*src); + if (afs) { afs->mark_for_remove (); } - delete *src; + + (*src)->drop_references (); } } |