X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fardour%2Fsession.cc;h=31693daff39d715ae5384e123f1d7cfcf7f6b3ce;hb=9e0d03020ff47773f7d1c0414de1c74e6c9e0dac;hp=8d707545fe71d8efa63e47b160496dc723da489b;hpb=738387f9a417537e768d56d3fc4afcb9dc82d66b;p=ardour.git diff --git a/libs/ardour/session.cc b/libs/ardour/session.cc index 8d707545fe..31693daff3 100644 --- a/libs/ardour/session.cc +++ b/libs/ardour/session.cc @@ -32,9 +32,9 @@ #include #include #include +#include #include "pbd/error.h" -#include #include "pbd/boost_debug.h" #include "pbd/pathscanner.h" #include "pbd/stl_delete.h" @@ -93,6 +93,8 @@ #include "ardour/tempo.h" #include "ardour/utils.h" +#include "midi++/jack.h" + #include "i18n.h" using namespace std; @@ -190,8 +192,8 @@ Session::Session (AudioEngine &eng, _state_of_the_state = StateOfTheState (_state_of_the_state & ~Dirty); - Config->ParameterChanged.connect (*this, boost::bind (&Session::config_changed, this, _1, false)); - config.ParameterChanged.connect (*this, boost::bind (&Session::config_changed, this, _1, true)); + Config->ParameterChanged.connect_same_thread (*this, boost::bind (&Session::config_changed, this, _1, false)); + config.ParameterChanged.connect_same_thread (*this, boost::bind (&Session::config_changed, this, _1, true)); if (was_dirty) { DirtyChanged (); /* EMIT SIGNAL */ @@ -280,8 +282,8 @@ Session::Session (AudioEngine &eng, if (master_out_channels) { ChanCount count(DataType::AUDIO, master_out_channels); Route* rt = new Route (*this, _("master"), Route::MasterOut, DataType::AUDIO); - boost_debug_shared_ptr_mark_interesting (rt, typeid (rt).name()); - shared_ptr r (rt); + boost_debug_shared_ptr_mark_interesting (rt, "Route"); + boost::shared_ptr r (rt); r->input()->ensure_io (count, false, this); r->output()->ensure_io (count, false, this); r->set_remote_control_id (control_id); @@ -295,7 +297,7 @@ Session::Session (AudioEngine &eng, if (control_out_channels) { ChanCount count(DataType::AUDIO, control_out_channels); Route* rt = new Route (*this, _("monitor"), Route::ControlOut, DataType::AUDIO); - boost_debug_shared_ptr_mark_interesting (rt, typeid (rt).name()); + boost_debug_shared_ptr_mark_interesting (rt, "Route"); shared_ptr r (rt); r->input()->ensure_io (count, false, this); r->output()->ensure_io (count, false, this); @@ -327,7 +329,7 @@ Session::Session (AudioEngine &eng, _state_of_the_state = StateOfTheState (_state_of_the_state & ~Dirty); - Config->ParameterChanged.connect (*this, boost::bind (&Session::config_changed, this, _1, false)); + Config->ParameterChanged.connect_same_thread (*this, boost::bind (&Session::config_changed, this, _1, false)); } Session::~Session () @@ -362,8 +364,7 @@ Session::destroy () Stateful::loading_state_version = 0; - _butler->terminate_thread (); - + delete _butler; delete midi_control_ui; if (click_data != default_click) { @@ -388,32 +389,19 @@ Session::destroy () AudioDiskstream::free_working_buffers(); - DEBUG_TRACE (DEBUG::Destruction, "delete named selections\n"); - for (NamedSelectionList::iterator i = named_selections.begin(); i != named_selections.end(); ) { - NamedSelectionList::iterator tmp; + /* tell everyone who is still standing that we're about to die */ + drop_references (); - tmp = i; - ++tmp; + /* tell everyone to drop references and delete objects as we go */ - delete *i; - i = tmp; - } + DEBUG_TRACE (DEBUG::Destruction, "delete named selections\n"); + named_selections.clear (); DEBUG_TRACE (DEBUG::Destruction, "delete regions\n"); - for (RegionList::iterator i = regions.begin(); i != regions.end(); ) { - RegionList::iterator tmp; - - tmp = i; - ++tmp; - - boost::shared_ptr keep (i->second); - - DEBUG_TRACE(DEBUG::Destruction, string_compose ("Dropping for region %1 (%2); pre-ref = %3\n", i->second->name(), i->second.get(), i->second.use_count())); + for (RegionList::iterator i = regions.begin(); i != regions.end(); ++i) { + DEBUG_TRACE(DEBUG::Destruction, string_compose ("Dropping for region %1 ; pre-ref = %2\n", i->second->name(), i->second.use_count())); i->second->drop_references (); - DEBUG_TRACE(DEBUG::Destruction, string_compose ("region post ref = %1\n", i->second.use_count())); - i = tmp; } - regions.clear (); DEBUG_TRACE (DEBUG::Destruction, "delete routes\n"); @@ -427,15 +415,19 @@ Session::destroy () { RCUWriter writer (routes); boost::shared_ptr r = writer.get_copy (); + for (RouteList::iterator i = r->begin(); i != r->end(); ++i) { DEBUG_TRACE(DEBUG::Destruction, string_compose ("Dropping for route %1 ; pre-ref = %2\n", (*i)->name(), (*i).use_count())); (*i)->drop_references (); } + r->clear (); /* writer goes out of scope and updates master */ } routes.flush (); + boost::shared_ptr r = routes.reader (); + DEBUG_TRACE (DEBUG::Destruction, "delete diskstreams\n"); { RCUWriter dwriter (diskstreams); @@ -444,28 +436,22 @@ Session::destroy () DEBUG_TRACE(DEBUG::Destruction, string_compose ("Dropping for diskstream %1 ; pre-ref = %2\n", (*i)->name(), (*i).use_count())); (*i)->drop_references (); } + dsl->clear (); } diskstreams.flush (); DEBUG_TRACE (DEBUG::Destruction, "delete sources\n"); - for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) { - SourceMap::iterator tmp; - - tmp = i; - ++tmp; - + for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) { DEBUG_TRACE(DEBUG::Destruction, string_compose ("Dropping for source %1 ; pre-ref = %2\n", i->second->path(), i->second.use_count())); i->second->drop_references (); - - i = tmp; } sources.clear (); - DEBUG_TRACE (DEBUG::Destruction, "delete route groups\n"); for (list::iterator i = _route_groups.begin(); i != _route_groups.end(); ++i) { + delete *i; } @@ -476,10 +462,6 @@ Session::destroy () /* not strictly necessary, but doing it here allows the shared_ptr debugging to work */ playlists.reset (); - /* tell everyone who is still standing that we're about to die */ - - drop_references (); - boost_debug_list_ptrs (); DEBUG_TRACE (DEBUG::Destruction, "Session::destroy() done\n"); @@ -523,7 +505,7 @@ Session::when_engine_running () /* every time we reconnect, recompute worst case output latencies */ - _engine.Running.connect (*this, boost::bind (&Session::set_worst_io_latencies, this)); + _engine.Running.connect_same_thread (*this, boost::bind (&Session::set_worst_io_latencies, this)); if (synced_to_jack()) { _engine.transport_stop (); @@ -810,6 +792,7 @@ Session::hookup_io () /* Tell all IO objects to connect themselves together */ IO::enable_connecting (); + MIDI::JACK_MidiPort::MakeConnections (); /* Now reset all panners */ @@ -877,7 +860,7 @@ Session::diskstream_playlist_changed (boost::weak_ptr wp) boost::shared_ptr playlist; if ((playlist = dstream->playlist()) != 0) { - playlist->LengthChanged.connect (*this, boost::bind (&Session::playlist_length_changed, this)); + playlist->LengthChanged.connect_same_thread (*this, boost::bind (&Session::playlist_length_changed, this)); } /* see comment in playlist_length_changed () */ @@ -1013,9 +996,9 @@ Session::set_auto_punch_location (Location* location) punch_connections.drop_connections (); - location->start_changed.connect (punch_connections, boost::bind (&Session::auto_punch_start_changed, this, _1)); - location->end_changed.connect (punch_connections, boost::bind (&Session::auto_punch_end_changed, this, _1)); - location->changed.connect (punch_connections, boost::bind (&Session::auto_punch_changed, this, _1)); + location->start_changed.connect_same_thread (punch_connections, boost::bind (&Session::auto_punch_start_changed, this, _1)); + location->end_changed.connect_same_thread (punch_connections, boost::bind (&Session::auto_punch_end_changed, this, _1)); + location->changed.connect_same_thread (punch_connections, boost::bind (&Session::auto_punch_changed, this, _1)); location->set_auto_punch (true, this); @@ -1051,9 +1034,9 @@ Session::set_auto_loop_location (Location* location) loop_connections.drop_connections (); - location->start_changed.connect (loop_connections, boost::bind (&Session::auto_loop_changed, this, _1)); - location->end_changed.connect (loop_connections, boost::bind (&Session::auto_loop_changed, this, _1)); - location->changed.connect (loop_connections, boost::bind (&Session::auto_loop_changed, this, _1)); + location->start_changed.connect_same_thread (loop_connections, boost::bind (&Session::auto_loop_changed, this, _1)); + location->end_changed.connect_same_thread (loop_connections, boost::bind (&Session::auto_loop_changed, this, _1)); + location->changed.connect_same_thread (loop_connections, boost::bind (&Session::auto_loop_changed, this, _1)); location->set_auto_loop (true, this); @@ -1647,7 +1630,7 @@ Session::new_midi_track (TrackMode mode, RouteGroup* route_group, uint32_t how_m route_group->add (track); } - track->DiskstreamChanged.connect (*this, boost::bind (&Session::resort_routes, this)); + track->DiskstreamChanged.connect_same_thread (*this, boost::bind (&Session::resort_routes, this)); //track->set_remote_control_id (control_id); new_routes.push_back (track); @@ -1760,7 +1743,7 @@ Session::new_audio_track (int input_channels, int output_channels, TrackMode mod try { AudioTrack* at = new AudioTrack (*this, track_name, Route::Flag (0), mode); - boost_debug_shared_ptr_mark_interesting (at, typeid (at).name()); + boost_debug_shared_ptr_mark_interesting (at, "Track"); track = boost::shared_ptr(at); if (track->input()->ensure_io (ChanCount(DataType::AUDIO, input_channels), false, this)) { @@ -1822,7 +1805,7 @@ Session::new_audio_track (int input_channels, int output_channels, TrackMode mod track->audio_diskstream()->non_realtime_input_change(); - track->DiskstreamChanged.connect (*this, boost::bind (&Session::resort_routes, this)); + track->DiskstreamChanged.connect_same_thread (*this, boost::bind (&Session::resort_routes, this)); track->set_remote_control_id (control_id); ++control_id; @@ -1880,20 +1863,27 @@ void Session::set_remote_control_ids () { RemoteModel m = Config->get_remote_model(); + bool emit_signal = false; shared_ptr r = routes.reader (); for (RouteList::iterator i = r->begin(); i != r->end(); ++i) { - if ( MixerOrdered == m) { + if (MixerOrdered == m) { long order = (*i)->order_key(N_("signal")); - (*i)->set_remote_control_id( order+1 ); - } else if ( EditorOrdered == m) { + (*i)->set_remote_control_id (order+1, false); + emit_signal = true; + } else if (EditorOrdered == m) { long order = (*i)->order_key(N_("editor")); - (*i)->set_remote_control_id( order+1 ); - } else if ( UserOrdered == m) { + (*i)->set_remote_control_id (order+1, false); + emit_signal = true; + } else if (UserOrdered == m) { //do nothing ... only changes to remote id's are initiated by user } } + + if (emit_signal) { + Route::RemoteControlIDChange(); + } } @@ -1951,7 +1941,7 @@ Session::new_audio_route (bool aux, int input_channels, int output_channels, Rou try { Route* rt = new Route (*this, bus_name, Route::Flag(0), DataType::AUDIO); - boost_debug_shared_ptr_mark_interesting (rt, typeid (rt).name()); + boost_debug_shared_ptr_mark_interesting (rt, "Route"); shared_ptr bus (rt); if (bus->input()->ensure_io (ChanCount(DataType::AUDIO, input_channels), false, this)) { @@ -2148,20 +2138,21 @@ Session::add_routes (RouteList& new_routes, bool save) for (RouteList::iterator x = new_routes.begin(); x != new_routes.end(); ++x) { boost::weak_ptr wpr (*x); + boost::shared_ptr r (*x); - (*x)->listen_changed.connect (*this, boost::bind (&Session::route_listen_changed, this, _1, wpr)); - (*x)->solo_changed.connect (*this, boost::bind (&Session::route_solo_changed, this, _1, wpr)); - (*x)->mute_changed.connect (*this, boost::bind (&Session::route_mute_changed, this, _1)); - (*x)->output()->changed.connect (*this, boost::bind (&Session::set_worst_io_latencies_x, this, _1, _2)); - (*x)->processors_changed.connect (*this, boost::bind (&Session::route_processors_changed, this, _1)); - (*x)->route_group_changed.connect (*this, boost::bind (&Session::route_group_changed, this)); + r->listen_changed.connect_same_thread (*this, boost::bind (&Session::route_listen_changed, this, _1, wpr)); + r->solo_changed.connect_same_thread (*this, boost::bind (&Session::route_solo_changed, this, _1, wpr)); + r->mute_changed.connect_same_thread (*this, boost::bind (&Session::route_mute_changed, this, _1)); + r->output()->changed.connect_same_thread (*this, boost::bind (&Session::set_worst_io_latencies_x, this, _1, _2)); + r->processors_changed.connect_same_thread (*this, boost::bind (&Session::route_processors_changed, this, _1)); + r->route_group_changed.connect_same_thread (*this, boost::bind (&Session::route_group_changed, this)); - if ((*x)->is_master()) { - _master_out = (*x); + if (r->is_master()) { + _master_out = r; } - if ((*x)->is_control()) { - _control_out = (*x); + if (r->is_control()) { + _control_out = r; } } @@ -2186,6 +2177,7 @@ Session::add_routes (RouteList& new_routes, bool save) } RouteAdded (new_routes); /* EMIT SIGNAL */ + Route::RemoteControlIDChange (); /* EMIT SIGNAL */ } void @@ -2294,11 +2286,11 @@ Session::add_diskstream (boost::shared_ptr dstream) /* writer goes out of scope, copies ds back to main */ } - dstream->PlaylistChanged.connect (*this, boost::bind (&Session::diskstream_playlist_changed, this, boost::weak_ptr (dstream))); + dstream->PlaylistChanged.connect_same_thread (*this, boost::bind (&Session::diskstream_playlist_changed, this, boost::weak_ptr (dstream))); /* this will connect to future changes, and check the current length */ diskstream_playlist_changed (boost::weak_ptr (dstream)); - dstream->RecordEnableChanged.connect (*this, boost::bind (&Session::update_have_rec_enabled_diskstream, this)); + dstream->RecordEnableChanged.connect_same_thread (*this, boost::bind (&Session::update_have_rec_enabled_diskstream, this)); dstream->prepare (); @@ -2388,6 +2380,8 @@ Session::remove_route (shared_ptr route) sync_order_keys (N_("session")); + Route::RemoteControlIDChange(); /* EMIT SIGNAL */ + /* save the new state of the world */ if (save_state (_current_snapshot_name)) { @@ -2812,9 +2806,7 @@ Session::add_regions (vector >& new_regions) } } - region->StateChanged.connect (*this, boost::bind (&Session::region_changed, this, _1, boost::weak_ptr(region))); - region->GoingAway.connect (*this, boost::bind (&Session::remove_region, this, boost::weak_ptr(region))); - + region->StateChanged.connect_same_thread (*this, boost::bind (&Session::region_changed, this, _1, boost::weak_ptr(region))); update_region_name_map (region); } @@ -2970,6 +2962,10 @@ Session::remove_last_capture () } } + for (list >::iterator i = r.begin(); i != r.end(); ++i) { + remove_region (*i); + } + destroy_regions (r); save_state (_current_snapshot_name); @@ -3001,7 +2997,6 @@ Session::add_source (boost::shared_ptr source) } if (result.second) { - source->GoingAway.connect (*this, boost::bind (&Session::remove_source, this, boost::weak_ptr (source))); set_dirty(); } @@ -3390,10 +3385,7 @@ Session::add_playlist (boost::shared_ptr playlist, bool unused) return; } - bool existing = playlists->add (playlist); - if (!existing) { - playlist->GoingAway.connect (*this, boost::bind (&Session::remove_playlist, this, boost::weak_ptr(playlist))); - } + playlists->add (playlist); if (unused) { playlist->release(); @@ -3566,7 +3558,11 @@ Session::graph_reordered () void Session::add_processor (Processor* processor) { - processor->GoingAway.connect (*this, boost::bind (&Session::remove_processor, this, processor)); + /* Session does not own Processors (they belong to a Route) but we do want to track + the arrival and departure of port inserts, sends and returns for naming + purposes. + */ + processor->DropReferences.connect_same_thread (*this, boost::bind (&Session::remove_processor, this, processor)); set_dirty(); } @@ -3810,37 +3806,33 @@ Session::mark_insert_id (uint32_t id) /* Named Selection management */ -NamedSelection * +boost::shared_ptr Session::named_selection_by_name (string name) { Glib::Mutex::Lock lm (named_selection_lock); for (NamedSelectionList::iterator i = named_selections.begin(); i != named_selections.end(); ++i) { if ((*i)->name == name) { - return* i; + return *i; } } - return 0; + return boost::shared_ptr(); } void -Session::add_named_selection (NamedSelection* named_selection) +Session::add_named_selection (boost::shared_ptr named_selection) { { Glib::Mutex::Lock lm (named_selection_lock); named_selections.insert (named_selections.begin(), named_selection); } - for (list >::iterator i = named_selection->playlists.begin(); i != named_selection->playlists.end(); ++i) { - add_playlist (*i); - } - set_dirty(); NamedSelectionAdded (); /* EMIT SIGNAL */ } void -Session::remove_named_selection (NamedSelection* named_selection) +Session::remove_named_selection (boost::shared_ptr named_selection) { bool removed = false; @@ -3850,7 +3842,6 @@ Session::remove_named_selection (NamedSelection* named_selection) NamedSelectionList::iterator i = find (named_selections.begin(), named_selections.end(), named_selection); if (i != named_selections.end()) { - delete (*i); named_selections.erase (i); set_dirty(); removed = true; @@ -4186,6 +4177,10 @@ Session::compute_initial_length () void Session::sync_order_keys (std::string const & base) { + if (deletion_in_progress()) { + return; + } + if (!Config->get_sync_all_route_ordering()) { /* leave order keys as they are */ return; @@ -4198,8 +4193,11 @@ Session::sync_order_keys (std::string const & base) } Route::SyncOrderKeys (base); // EMIT SIGNAL -} + /* this might not do anything */ + + set_remote_control_ids (); +} /** @return true if there is at least one record-enabled diskstream, otherwise false */ bool