X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fardour%2Fsession.cc;h=31693daff39d715ae5384e123f1d7cfcf7f6b3ce;hb=7d96960b162d25da87c388a3083775e8770bba56;hp=598d9b01b5058ff7b8613ff95282ccb6e5df233c;hpb=515d19c74519599c53d6fc85c1af2647f390d95f;p=ardour.git diff --git a/libs/ardour/session.cc b/libs/ardour/session.cc index 598d9b01b5..31693daff3 100644 --- a/libs/ardour/session.cc +++ b/libs/ardour/session.cc @@ -28,15 +28,13 @@ #include #include -#include -#include #include #include #include +#include #include "pbd/error.h" -#include #include "pbd/boost_debug.h" #include "pbd/pathscanner.h" #include "pbd/stl_delete.h" @@ -71,6 +69,7 @@ #include "ardour/midi_playlist.h" #include "ardour/midi_region.h" #include "ardour/midi_track.h" +#include "ardour/midi_ui.h" #include "ardour/named_selection.h" #include "ardour/playlist.h" #include "ardour/plugin_insert.h" @@ -86,6 +85,7 @@ #include "ardour/session_directory.h" #include "ardour/session_directory.h" #include "ardour/session_metadata.h" +#include "ardour/session_playlists.h" #include "ardour/slave.h" #include "ardour/smf_source.h" #include "ardour/source_factory.h" @@ -93,6 +93,8 @@ #include "ardour/tempo.h" #include "ardour/utils.h" +#include "midi++/jack.h" + #include "i18n.h" using namespace std; @@ -103,17 +105,21 @@ using boost::weak_ptr; bool Session::_disable_all_loaded_plugins = false; -sigc::signal Session::Dialog; -sigc::signal Session::AskAboutPendingState; -sigc::signal Session::AskAboutSampleRateMismatch; -sigc::signal Session::SendFeedback; +PBD::Signal1 Session::Dialog; +PBD::Signal0 Session::AskAboutPendingState; +PBD::Signal2 Session::AskAboutSampleRateMismatch; +PBD::Signal0 Session::SendFeedback; + +PBD::Signal0 Session::TimecodeOffsetChanged; +PBD::Signal0 Session::StartTimeChanged; +PBD::Signal0 Session::EndTimeChanged; +PBD::Signal0 Session::AutoBindingOn; +PBD::Signal0 Session::AutoBindingOff; +PBD::Signal2 Session::Exported; +PBD::Signal1 > Session::AskAboutPlaylistDeletion; -sigc::signal Session::TimecodeOffsetChanged; -sigc::signal Session::StartTimeChanged; -sigc::signal Session::EndTimeChanged; -sigc::signal Session::AutoBindingOn; -sigc::signal Session::AutoBindingOff; -sigc::signal Session::Exported; +static void clean_up_session_event (SessionEvent* ev) { delete ev; } +const SessionEvent::RTeventCallback Session::rt_cleanup (clean_up_session_event); Session::Session (AudioEngine &eng, const string& fullpath, @@ -132,13 +138,10 @@ Session::Session (AudioEngine &eng, _midi_port (default_midi_port), _midi_clock_port (default_midi_clock_port), _session_dir (new SessionDirectory(fullpath)), - pending_events (2048), state_tree (0), - _butler (new Butler (this)), + _butler (new Butler (*this)), _post_transport_work (0), _send_timecode_update (false), - midi_thread (pthread_t (0)), - midi_requests (128), // the size of this should match the midi request pool size diskstreams (new DiskstreamList), routes (new RouteList), _total_free_4k_blocks (0), @@ -152,6 +155,8 @@ Session::Session (AudioEngine &eng, _have_rec_enabled_diskstream (false) { + playlists.reset (new SessionPlaylists); + bool new_session; interpolation.add_channel_to (0, 0); @@ -187,8 +192,8 @@ Session::Session (AudioEngine &eng, _state_of_the_state = StateOfTheState (_state_of_the_state & ~Dirty); - Config->ParameterChanged.connect (bind (mem_fun (*this, &Session::config_changed), false)); - config.ParameterChanged.connect (bind (mem_fun (*this, &Session::config_changed), 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 */ @@ -218,13 +223,10 @@ Session::Session (AudioEngine &eng, _midi_port (default_midi_port), _midi_clock_port (default_midi_clock_port), _session_dir ( new SessionDirectory(fullpath)), - pending_events (2048), state_tree (0), - _butler (new Butler (this)), + _butler (new Butler (*this)), _post_transport_work (0), _send_timecode_update (false), - midi_thread (pthread_t (0)), - midi_requests (16), diskstreams (new DiskstreamList), routes (new RouteList), _total_free_4k_blocks (0), @@ -237,6 +239,8 @@ Session::Session (AudioEngine &eng, _metadata (new SessionMetadata()), _have_rec_enabled_diskstream (false) { + playlists.reset (new SessionPlaylists); + bool new_session; interpolation.add_channel_to (0, 0); @@ -277,7 +281,9 @@ Session::Session (AudioEngine &eng, if (master_out_channels) { ChanCount count(DataType::AUDIO, master_out_channels); - shared_ptr r (new Route (*this, _("master"), Route::MasterOut, DataType::AUDIO)); + Route* rt = new Route (*this, _("master"), Route::MasterOut, DataType::AUDIO); + 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); @@ -290,7 +296,9 @@ Session::Session (AudioEngine &eng, if (control_out_channels) { ChanCount count(DataType::AUDIO, control_out_channels); - shared_ptr r (new Route (*this, _("monitor"), Route::ControlOut, DataType::AUDIO)); + Route* rt = new Route (*this, _("monitor"), Route::ControlOut, DataType::AUDIO); + 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); r->set_remote_control_id (control_id++); @@ -321,7 +329,7 @@ Session::Session (AudioEngine &eng, _state_of_the_state = StateOfTheState (_state_of_the_state & ~Dirty); - Config->ParameterChanged.connect (bind (mem_fun (*this, &Session::config_changed), false)); + Config->ParameterChanged.connect_same_thread (*this, boost::bind (&Session::config_changed, this, _1, false)); } Session::~Session () @@ -344,12 +352,6 @@ Session::destroy () _engine.remove_session (); - GoingAway (); /* EMIT SIGNAL */ - - /* do this */ - - notify_callbacks (); - /* clear history so that no references to objects are held any more */ _history.clear (); @@ -362,8 +364,8 @@ Session::destroy () Stateful::loading_state_version = 0; - _butler->terminate_thread (); - //terminate_midi_thread (); + delete _butler; + delete midi_control_ui; if (click_data != default_click) { delete [] click_data; @@ -387,62 +389,19 @@ Session::destroy () AudioDiskstream::free_working_buffers(); - Route::SyncOrderKeys.clear(); - - 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; - - delete *i; - i = tmp; - } + /* tell everyone to drop references and delete objects as we go */ - DEBUG_TRACE (DEBUG::Destruction, "delete used playlists\n"); - for (PlaylistList::iterator i = playlists.begin(); i != playlists.end(); ) { - PlaylistList::iterator tmp; - - tmp = i; - ++tmp; - - DEBUG_TRACE(DEBUG::Destruction, string_compose ("Dropping for used playlist %1 ; pre-ref = %2\n", (*i)->name(), (*i).use_count())); - (*i)->drop_references (); - - - i = tmp; - } - - DEBUG_TRACE (DEBUG::Destruction, "delete unused playlists\n"); - for (PlaylistList::iterator i = unused_playlists.begin(); i != unused_playlists.end(); ) { - PlaylistList::iterator tmp; - - tmp = i; - ++tmp; - - DEBUG_TRACE(DEBUG::Destruction, string_compose ("Dropping for unused playlist %1 ; pre-ref = %2\n", (*i)->name(), (*i).use_count())); - (*i)->drop_references (); - - i = tmp; - } - - playlists.clear (); - unused_playlists.clear (); + 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; - - DEBUG_TRACE(DEBUG::Destruction, string_compose ("Dropping for region %1 (%2); pre-ref = %2\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"); @@ -456,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); @@ -473,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; } @@ -502,6 +459,9 @@ Session::destroy () delete mmc; + /* not strictly necessary, but doing it here allows the shared_ptr debugging to work */ + playlists.reset (); + boost_debug_list_ptrs (); DEBUG_TRACE (DEBUG::Destruction, "Session::destroy() done\n"); @@ -537,11 +497,15 @@ Session::when_engine_running () BootMessage (_("Using configuration")); - Config->map_parameters (bind (mem_fun (*this, &Session::config_changed), false)); + boost::function ff (boost::bind (&Session::config_changed, this, _1, false)); + boost::function ft (boost::bind (&Session::config_changed, this, _1, true)); + + Config->map_parameters (ff); + config.map_parameters (ft); /* every time we reconnect, recompute worst case output latencies */ - _engine.Running.connect (mem_fun (*this, &Session::set_worst_io_latencies)); + _engine.Running.connect_same_thread (*this, boost::bind (&Session::set_worst_io_latencies, this)); if (synced_to_jack()) { _engine.transport_stop (); @@ -828,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 */ @@ -895,7 +860,7 @@ Session::diskstream_playlist_changed (boost::weak_ptr wp) boost::shared_ptr playlist; if ((playlist = dstream->playlist()) != 0) { - playlist->LengthChanged.connect (mem_fun (this, &Session::playlist_length_changed)); + playlist->LengthChanged.connect_same_thread (*this, boost::bind (&Session::playlist_length_changed, this)); } /* see comment in playlist_length_changed () */ @@ -944,7 +909,7 @@ Session::reset_input_monitor_state () void Session::auto_punch_start_changed (Location* location) { - replace_event (Event::PunchIn, location->start()); + replace_event (SessionEvent::PunchIn, location->start()); if (get_record_enabled() && config.get_punch_in()) { /* capture start has been changed, so save new pending state */ @@ -957,7 +922,7 @@ Session::auto_punch_end_changed (Location* location) { nframes_t when_to_stop = location->end(); // when_to_stop += _worst_output_latency + _worst_input_latency; - replace_event (Event::PunchOut, when_to_stop); + replace_event (SessionEvent::PunchOut, when_to_stop); } void @@ -965,15 +930,15 @@ Session::auto_punch_changed (Location* location) { nframes_t when_to_stop = location->end(); - replace_event (Event::PunchIn, location->start()); + replace_event (SessionEvent::PunchIn, location->start()); //when_to_stop += _worst_output_latency + _worst_input_latency; - replace_event (Event::PunchOut, when_to_stop); + replace_event (SessionEvent::PunchOut, when_to_stop); } void Session::auto_loop_changed (Location* location) { - replace_event (Event::AutoLoop, location->end(), location->start()); + replace_event (SessionEvent::AutoLoop, location->end(), location->start()); if (transport_rolling() && play_loop) { @@ -982,7 +947,7 @@ Session::auto_loop_changed (Location* location) if (_transport_frame < location->start() || _transport_frame > location->end()) { // relocate to beginning of loop - clear_events (Event::LocateRoll); + clear_events (SessionEvent::LocateRoll); request_locate (location->start(), true); @@ -994,8 +959,8 @@ Session::auto_loop_changed (Location* location) loop_changing = true; if (location->end() > last_loopend) { - clear_events (Event::LocateRoll); - Event *ev = new Event (Event::LocateRoll, Event::Add, last_loopend, last_loopend, 0, true); + clear_events (SessionEvent::LocateRoll); + SessionEvent *ev = new SessionEvent (SessionEvent::LocateRoll, SessionEvent::Add, last_loopend, last_loopend, 0, true); queue_event (ev); } @@ -1011,12 +976,10 @@ Session::set_auto_punch_location (Location* location) Location* existing; if ((existing = _locations.auto_punch_location()) != 0 && existing != location) { - auto_punch_start_changed_connection.disconnect(); - auto_punch_end_changed_connection.disconnect(); - auto_punch_changed_connection.disconnect(); + punch_connections.drop_connections(); existing->set_auto_punch (false, this); - remove_event (existing->start(), Event::PunchIn); - clear_events (Event::PunchOut); + remove_event (existing->start(), SessionEvent::PunchIn); + clear_events (SessionEvent::PunchOut); auto_punch_location_changed (0); } @@ -1031,17 +994,14 @@ Session::set_auto_punch_location (Location* location) return; } - auto_punch_start_changed_connection.disconnect(); - auto_punch_end_changed_connection.disconnect(); - auto_punch_changed_connection.disconnect(); + punch_connections.drop_connections (); - auto_punch_start_changed_connection = location->start_changed.connect (mem_fun (this, &Session::auto_punch_start_changed)); - auto_punch_end_changed_connection = location->end_changed.connect (mem_fun (this, &Session::auto_punch_end_changed)); - auto_punch_changed_connection = location->changed.connect (mem_fun (this, &Session::auto_punch_changed)); + 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); - auto_punch_changed (location); auto_punch_location_changed (location); @@ -1053,11 +1013,9 @@ Session::set_auto_loop_location (Location* location) Location* existing; if ((existing = _locations.auto_loop_location()) != 0 && existing != location) { - auto_loop_start_changed_connection.disconnect(); - auto_loop_end_changed_connection.disconnect(); - auto_loop_changed_connection.disconnect(); + loop_connections.drop_connections (); existing->set_auto_loop (false, this); - remove_event (existing->end(), Event::AutoLoop); + remove_event (existing->end(), SessionEvent::AutoLoop); auto_loop_location_changed (0); } @@ -1074,16 +1032,11 @@ Session::set_auto_loop_location (Location* location) last_loopend = location->end(); - auto_loop_start_changed_connection.disconnect(); - auto_loop_end_changed_connection.disconnect(); - auto_loop_changed_connection.disconnect(); + loop_connections.drop_connections (); - auto_loop_start_changed_connection = location->start_changed.connect ( - mem_fun (this, &Session::auto_loop_changed)); - auto_loop_end_changed_connection = location->end_changed.connect ( - mem_fun (this, &Session::auto_loop_changed)); - auto_loop_changed_connection = location->changed.connect ( - mem_fun (this, &Session::auto_loop_changed)); + 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); @@ -1187,8 +1140,9 @@ Session::disable_record (bool rt_context, bool force) // FIXME: timestamp correct? [DR] // FIXME FIXME FIXME: rt_context? this must be called in the process thread. // does this /need/ to be sent in all cases? - if (rt_context) + if (rt_context) { deliver_mmc (MIDI::MachineControl::cmdRecordExit, _transport_frame); + } if (Config->get_monitoring_model() == HardwareMonitoring && config.get_auto_input()) { boost::shared_ptr dsl = diskstreams.reader(); @@ -1672,9 +1626,11 @@ Session::new_midi_track (TrackMode mode, RouteGroup* route_group, uint32_t how_m */ track->midi_diskstream()->non_realtime_input_change(); - track->set_route_group (route_group, 0); + if (route_group) { + route_group->add (track); + } - track->DiskstreamChanged.connect (mem_fun (this, &Session::resort_routes)); + track->DiskstreamChanged.connect_same_thread (*this, boost::bind (&Session::resort_routes, this)); //track->set_remote_control_id (control_id); new_routes.push_back (track); @@ -1787,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)) { @@ -1843,11 +1799,13 @@ Session::new_audio_track (int input_channels, int output_channels, TrackMode mod channels_used += track->n_inputs ().n_audio(); - track->set_route_group (route_group, 0); + if (route_group) { + route_group->add (track); + } track->audio_diskstream()->non_realtime_input_change(); - track->DiskstreamChanged.connect (mem_fun (this, &Session::resort_routes)); + track->DiskstreamChanged.connect_same_thread (*this, boost::bind (&Session::resort_routes, this)); track->set_remote_control_id (control_id); ++control_id; @@ -1905,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(); + } } @@ -1975,7 +1940,9 @@ Session::new_audio_route (bool aux, int input_channels, int output_channels, Rou } while (bus_id < (UINT_MAX-1)); try { - shared_ptr bus (new Route (*this, bus_name, Route::Flag(0), DataType::AUDIO)); + Route* rt = new Route (*this, bus_name, Route::Flag(0), DataType::AUDIO); + boost_debug_shared_ptr_mark_interesting (rt, "Route"); + shared_ptr bus (rt); if (bus->input()->ensure_io (ChanCount(DataType::AUDIO, input_channels), false, this)) { error << string_compose (_("cannot configure %1 in/%2 out configuration for new audio track"), @@ -2022,7 +1989,9 @@ Session::new_audio_route (bool aux, int input_channels, int output_channels, Rou channels_used += bus->n_inputs ().n_audio(); - bus->set_route_group (route_group, 0); + if (route_group) { + route_group->add (bus); + } bus->set_remote_control_id (control_id); ++control_id; @@ -2169,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 (sigc::bind (mem_fun (*this, &Session::route_listen_changed), wpr)); - (*x)->solo_changed.connect (sigc::bind (mem_fun (*this, &Session::route_solo_changed), wpr)); - (*x)->mute_changed.connect (mem_fun (*this, &Session::route_mute_changed)); - (*x)->output()->changed.connect (mem_fun (*this, &Session::set_worst_io_latencies_x)); - (*x)->processors_changed.connect (bind (mem_fun (*this, &Session::update_latency_compensation), false, false)); - (*x)->route_group_changed.connect (hide (mem_fun (*this, &Session::route_group_changed))); + 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; } } @@ -2207,6 +2177,7 @@ Session::add_routes (RouteList& new_routes, bool save) } RouteAdded (new_routes); /* EMIT SIGNAL */ + Route::RemoteControlIDChange (); /* EMIT SIGNAL */ } void @@ -2315,11 +2286,11 @@ Session::add_diskstream (boost::shared_ptr dstream) /* writer goes out of scope, copies ds back to main */ } - dstream->PlaylistChanged.connect (sigc::bind (mem_fun (*this, &Session::diskstream_playlist_changed), 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 (mem_fun (*this, &Session::update_have_rec_enabled_diskstream)); + dstream->RecordEnableChanged.connect_same_thread (*this, boost::bind (&Session::update_have_rec_enabled_diskstream, this)); dstream->prepare (); @@ -2382,6 +2353,18 @@ Session::remove_route (shared_ptr route) route->input()->disconnect (0); route->output()->disconnect (0); + /* if the route had internal sends sending to it, remove them */ + if (route->internal_return()) { + + boost::shared_ptr r = routes.reader (); + for (RouteList::iterator i = r->begin(); i != r->end(); ++i) { + boost::shared_ptr s = (*i)->internal_send_for (route); + if (s) { + (*i)->remove_processor (s); + } + } + } + update_latency_compensation (false, false); set_dirty(); @@ -2397,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)) { @@ -2821,9 +2806,7 @@ Session::add_regions (vector >& new_regions) } } - region->StateChanged.connect (sigc::bind (mem_fun (*this, &Session::region_changed), boost::weak_ptr(region))); - region->GoingAway.connect (sigc::bind (mem_fun (*this, &Session::remove_region), 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); } @@ -2926,13 +2909,6 @@ Session::find_whole_file_parent (boost::shared_ptr child) return boost::shared_ptr (); } -void -Session::find_equivalent_playlist_regions (boost::shared_ptr region, vector >& result) -{ - for (PlaylistList::iterator i = playlists.begin(); i != playlists.end(); ++i) - (*i)->get_region_list_equivalent_regions (region, result); -} - int Session::destroy_region (boost::shared_ptr region) { @@ -2986,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); @@ -3017,7 +2997,6 @@ Session::add_source (boost::shared_ptr source) } if (result.second) { - source->GoingAway.connect (sigc::bind (mem_fun (this, &Session::remove_source), boost::weak_ptr (source))); set_dirty(); } @@ -3058,23 +3037,6 @@ Session::remove_source (boost::weak_ptr src) } } -/** Return the number of playlists (not regions) that contain @a src */ -uint32_t -Session::source_use_count (boost::shared_ptr src) const -{ - uint32_t count = 0; - for (PlaylistList::const_iterator p = playlists.begin(); p != playlists.end(); ++p) { - for (Playlist::RegionList::const_iterator r = (*p)->region_list().begin(); - r != (*p)->region_list().end(); ++r) { - if ((*r)->uses_source(src)) { - ++count; - break; - } - } - } - return count; -} - boost::shared_ptr Session::source_by_id (const PBD::ID& id) { @@ -3221,7 +3183,7 @@ Session::change_source_path_by_name (string path, string oldname, string newname return path; } -/** Return the full path (in some session directory) for a new embedded source. +/** Return the full path (in some session directory) for a new within-session source. * \a name must be a session-unique name that does not contain slashes * (e.g. as returned by new_*_source_name) */ @@ -3342,7 +3304,7 @@ Session::new_audio_source_name (const string& base, uint32_t nchan, uint32_t cha return Glib::path_get_basename(buf); } -/** Create a new embedded audio source */ +/** Create a new within-session audio source */ boost::shared_ptr Session::create_audio_source_for_session (AudioDiskstream& ds, uint32_t chan, bool destructive) { @@ -3351,7 +3313,7 @@ Session::create_audio_source_for_session (AudioDiskstream& ds, uint32_t chan, bo const string path = new_source_path_from_name(DataType::AUDIO, name); return boost::dynamic_pointer_cast ( - SourceFactory::createWritable (DataType::AUDIO, *this, path, true, destructive, frame_rate())); + SourceFactory::createWritable (DataType::AUDIO, *this, path, destructive, frame_rate())); } /** Return a unique name based on \a base for a new internal MIDI source */ @@ -3403,7 +3365,7 @@ Session::new_midi_source_name (const string& base) } -/** Create a new embedded MIDI source */ +/** Create a new within-session MIDI source */ boost::shared_ptr Session::create_midi_source_for_session (MidiDiskstream& ds) { @@ -3412,46 +3374,10 @@ Session::create_midi_source_for_session (MidiDiskstream& ds) return boost::dynamic_pointer_cast ( SourceFactory::createWritable ( - DataType::MIDI, *this, path, true, false, frame_rate())); + DataType::MIDI, *this, path, false, frame_rate())); } -/* Playlist management */ - -boost::shared_ptr -Session::playlist_by_name (string name) -{ - Glib::Mutex::Lock lm (playlist_lock); - for (PlaylistList::iterator i = playlists.begin(); i != playlists.end(); ++i) { - if ((*i)->name() == name) { - return* i; - } - } - for (PlaylistList::iterator i = unused_playlists.begin(); i != unused_playlists.end(); ++i) { - if ((*i)->name() == name) { - return* i; - } - } - - return boost::shared_ptr(); -} - -void -Session::unassigned_playlists (std::list > & list) -{ - Glib::Mutex::Lock lm (playlist_lock); - for (PlaylistList::iterator i = playlists.begin(); i != playlists.end(); ++i) { - if (!(*i)->get_orig_diskstream_id().to_s().compare ("0")) { - list.push_back (*i); - } - } - for (PlaylistList::iterator i = unused_playlists.begin(); i != unused_playlists.end(); ++i) { - if (!(*i)->get_orig_diskstream_id().to_s().compare ("0")) { - list.push_back (*i); - } - } -} - void Session::add_playlist (boost::shared_ptr playlist, bool unused) { @@ -3459,75 +3385,13 @@ Session::add_playlist (boost::shared_ptr playlist, bool unused) return; } - { - Glib::Mutex::Lock lm (playlist_lock); - if (find (playlists.begin(), playlists.end(), playlist) == playlists.end()) { - playlists.insert (playlists.begin(), playlist); - playlist->InUse.connect (sigc::bind (mem_fun (*this, &Session::track_playlist), boost::weak_ptr(playlist))); - playlist->GoingAway.connect (sigc::bind (mem_fun (*this, &Session::remove_playlist), boost::weak_ptr(playlist))); - } - } + playlists->add (playlist); if (unused) { playlist->release(); } set_dirty(); - - PlaylistAdded (playlist); /* EMIT SIGNAL */ -} - -void -Session::get_playlists (vector >& s) -{ - { - Glib::Mutex::Lock lm (playlist_lock); - for (PlaylistList::iterator i = playlists.begin(); i != playlists.end(); ++i) { - s.push_back (*i); - } - for (PlaylistList::iterator i = unused_playlists.begin(); i != unused_playlists.end(); ++i) { - s.push_back (*i); - } - } -} - -void -Session::track_playlist (bool inuse, boost::weak_ptr wpl) -{ - boost::shared_ptr pl(wpl.lock()); - - if (!pl) { - return; - } - - PlaylistList::iterator x; - - if (pl->hidden()) { - /* its not supposed to be visible */ - return; - } - - { - Glib::Mutex::Lock lm (playlist_lock); - - if (!inuse) { - - unused_playlists.insert (pl); - - if ((x = playlists.find (pl)) != playlists.end()) { - playlists.erase (x); - } - - - } else { - - playlists.insert (pl); - - if ((x = unused_playlists.find (pl)) != unused_playlists.end()) { - unused_playlists.erase (x); - } - } - } } void @@ -3543,26 +3407,9 @@ Session::remove_playlist (boost::weak_ptr weak_playlist) return; } - { - Glib::Mutex::Lock lm (playlist_lock); - - PlaylistList::iterator i; - - i = find (playlists.begin(), playlists.end(), playlist); - if (i != playlists.end()) { - playlists.erase (i); - } - - i = find (unused_playlists.begin(), unused_playlists.end(), playlist); - if (i != unused_playlists.end()) { - unused_playlists.erase (i); - } - - } + playlists->remove (playlist); set_dirty(); - - PlaylistRemoved (playlist); /* EMIT SIGNAL */ } void @@ -3576,7 +3423,7 @@ Session::set_audition (boost::shared_ptr r) void Session::audition_playlist () { - Event* ev = new Event (Event::Audition, Event::Add, Event::Immediate, 0, 0.0); + SessionEvent* ev = new SessionEvent (SessionEvent::Audition, SessionEvent::Add, SessionEvent::Immediate, 0, 0.0); ev->region.reset (); queue_event (ev); } @@ -3596,7 +3443,7 @@ Session::non_realtime_set_audition () void Session::audition_region (boost::shared_ptr r) { - Event* ev = new Event (Event::Audition, Event::Add, Event::Immediate, 0, 0.0); + SessionEvent* ev = new SessionEvent (SessionEvent::Audition, SessionEvent::Add, SessionEvent::Immediate, 0, 0.0); ev->region = r; queue_event (ev); } @@ -3628,8 +3475,8 @@ Session::remove_empty_sounds () TapeFileMatcher tape_file_matcher; remove_if (audio_filenames.begin(), audio_filenames.end(), - sigc::mem_fun (tape_file_matcher, &TapeFileMatcher::matches)); - + boost::bind (&TapeFileMatcher::matches, &tape_file_matcher, _1)); + for (vector::iterator i = audio_filenames.begin(); i != audio_filenames.end(); ++i) { sys::path audio_file_path (_session_dir->sound_path()); @@ -3663,48 +3510,6 @@ Session::is_auditioning () const } } -void -Session::set_all_solo (bool yn) -{ - shared_ptr r = routes.reader (); - - for (RouteList::iterator i = r->begin(); i != r->end(); ++i) { - if (!(*i)->is_hidden()) { - (*i)->set_solo (yn, this); - } - } - - set_dirty(); -} - -void -Session::set_all_listen (bool yn) -{ - shared_ptr r = routes.reader (); - - for (RouteList::iterator i = r->begin(); i != r->end(); ++i) { - if (!(*i)->is_hidden()) { - (*i)->set_listen (yn, this); - } - } - - set_dirty(); -} - -void -Session::set_all_mute (bool yn) -{ - shared_ptr r = routes.reader (); - - for (RouteList::iterator i = r->begin(); i != r->end(); ++i) { - if (!(*i)->is_hidden()) { - (*i)->set_mute (yn, this); - } - } - - set_dirty(); -} - uint32_t Session::n_diskstreams () const { @@ -3750,38 +3555,14 @@ Session::graph_reordered () } } -void -Session::record_disenable_all () -{ - record_enable_change_all (false); -} - -void -Session::record_enable_all () -{ - record_enable_change_all (true); -} - -void -Session::record_enable_change_all (bool yn) -{ - shared_ptr r = routes.reader (); - - for (RouteList::iterator i = r->begin(); i != r->end(); ++i) { - boost::shared_ptr t; - - if ((t = boost::dynamic_pointer_cast(*i)) != 0) { - t->set_record_enable (yn, this); - } - } - - /* since we don't keep rec-enable state, don't mark session dirty */ -} - void Session::add_processor (Processor* processor) { - processor->GoingAway.connect (sigc::bind (mem_fun (*this, &Session::remove_processor), 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(); } @@ -3894,13 +3675,7 @@ Session::tempo_map_changed (Change) { clear_clicks (); - for (PlaylistList::iterator i = playlists.begin(); i != playlists.end(); ++i) { - (*i)->update_after_tempo_map_change (); - } - - for (PlaylistList::iterator i = unused_playlists.begin(); i != unused_playlists.end(); ++i) { - (*i)->update_after_tempo_map_change (); - } + playlists->update_after_tempo_map_change (); set_dirty (); } @@ -4031,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; @@ -4071,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; @@ -4121,13 +3891,6 @@ Session::route_name_internal (string n) const return false; } -uint32_t -Session::n_playlists () const -{ - Glib::Mutex::Lock lm (playlist_lock); - return playlists.size(); -} - void Session::allocate_pan_automation_buffers (nframes_t nframes, uint32_t howmany, bool force) { @@ -4198,8 +3961,7 @@ Session::write_one_track (AudioTrack& track, nframes_t start, nframes_t end, return result; } - // any bigger than this seems to cause stack overflows in called functions - const nframes_t chunk_size = (128 * 1024)/4; + const nframes_t chunk_size = (256 * 1024)/4; // block all process callback handling @@ -4233,7 +3995,7 @@ Session::write_one_track (AudioTrack& track, nframes_t start, nframes_t end, try { fsource = boost::dynamic_pointer_cast ( - SourceFactory::createWritable (DataType::AUDIO, *this, buf, true, false, frame_rate())); + SourceFactory::createWritable (DataType::AUDIO, *this, buf, false, frame_rate())); } catch (failed_constructor& err) { @@ -4415,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; @@ -4427,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 @@ -4484,9 +4253,9 @@ Session::solo_control_mode_changed () /* cancel all solo or all listen when solo control mode changes */ if (Config->get_solo_control_is_listen_control()) { - set_all_solo (false); + set_solo (routes.reader(), false); } else { - set_all_listen (false); + set_listen (routes.reader(), false); } } @@ -4543,5 +4312,3 @@ Session::get_routes_with_regions_at (nframes64_t const p) const return rl; } - -