X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fardour%2Fsession.cc;h=14c5bde9969045bfbaa674b54eaa1b945d3b1a50;hb=337cee7a8344c76edc9068bf733ee8489b1c9bef;hp=c7e349d14e3dab69b0896504bef229f4512b2357;hpb=3c45ab08468e552b1c6f2b5bd6dff2b74204a0b9;p=ardour.git diff --git a/libs/ardour/session.cc b/libs/ardour/session.cc index c7e349d14e..14c5bde996 100644 --- a/libs/ardour/session.cc +++ b/libs/ardour/session.cc @@ -40,6 +40,7 @@ #include #include #include +#include #include #include @@ -66,6 +67,7 @@ #include #include #include +#include #ifdef HAVE_LIBLO #include @@ -96,8 +98,6 @@ sigc::signal Session::AskAboutPendingState; sigc::signal Session::SendFeedback; sigc::signal Session::SMPTEOffsetChanged; -sigc::signal Session::SMPTETypeChanged; -sigc::signal Session::PullupChanged; sigc::signal Session::StartTimeChanged; sigc::signal Session::EndTimeChanged; @@ -277,9 +277,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 (); + new_session = !g_file_test (_path.c_str(), GFileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR)); + if (new_session) { + if (create (new_session, mix_template, compute_initial_length())) { + cerr << "create failed\n"; + throw failed_constructor (); + } } if (second_stage_init (new_session)) { @@ -293,7 +296,7 @@ Session::Session (AudioEngine &eng, _state_of_the_state = StateOfTheState (_state_of_the_state & ~Dirty); - Config->ParameterChanged.connect (mem_fun (*this, &Session::handle_configuration_change)); + Config->ParameterChanged.connect (mem_fun (*this, &Session::config_changed)); if (was_dirty) { DirtyChanged (); /* EMIT SIGNAL */ @@ -309,7 +312,7 @@ Session::Session (AudioEngine &eng, uint32_t master_out_channels, uint32_t requested_physical_in, uint32_t requested_physical_out, - jack_nframes_t initial_length) + nframes_t initial_length) : _engine (eng), _mmc_port (default_mmc_port), @@ -326,13 +329,25 @@ Session::Session (AudioEngine &eng, cerr << "Loading session " << fullpath << " using snapshot " << snapshot_name << " (2)" << endl; - n_physical_outputs = max (requested_physical_out, _engine.n_physical_outputs()); - n_physical_inputs = max (requested_physical_in, _engine.n_physical_inputs()); + n_physical_outputs = _engine.n_physical_outputs(); + n_physical_inputs = _engine.n_physical_inputs(); + + if (n_physical_inputs) { + n_physical_inputs = max (requested_physical_in, n_physical_inputs); + } + + if (n_physical_outputs) { + n_physical_outputs = max (requested_physical_out, n_physical_outputs); + } first_stage_init (fullpath, snapshot_name); - - if (create (new_session, 0, initial_length)) { - throw failed_constructor (); + + new_session = !g_file_test (_path.c_str(), GFileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR)); + + if (new_session) { + if (create (new_session, 0, initial_length)) { + throw failed_constructor (); + } } if (control_out_channels) { @@ -354,8 +369,8 @@ Session::Session (AudioEngine &eng, output_ac = AutoConnectOption (output_ac & ~AutoConnectMaster); } - input_auto_connect = input_ac; - output_auto_connect = output_ac; + Config->set_input_auto_connect (input_ac); + Config->set_output_auto_connect (output_ac); if (second_stage_init (new_session)) { throw failed_constructor (); @@ -391,7 +406,7 @@ Session::~Session () /* clear history so that no references to objects are held any more */ - history.clear (); + _history.clear (); /* clear state tree so that no references to objects are held any more */ @@ -425,6 +440,10 @@ Session::~Session () } AudioDiskstream::free_working_buffers(); + + /* this should cause deletion of the auditioner */ + + // auditioner.reset (); #undef TRACK_DESTRUCTION #ifdef TRACK_DESTRUCTION @@ -458,8 +477,15 @@ Session::~Session () cerr << "delete audio regions\n"; #endif /* TRACK_DESTRUCTION */ - for (AudioRegionList::iterator i = audio_regions.begin(); i != audio_regions.end(); ++i) { + for (AudioRegionList::iterator i = audio_regions.begin(); i != audio_regions.end(); ) { + AudioRegionList::iterator tmp; + + tmp = i; + ++tmp; + i->second->drop_references (); + + i = tmp; } audio_regions.clear (); @@ -595,6 +621,8 @@ Session::when_engine_running () set_block_size (_engine.frames_per_cycle()); set_frame_rate (_engine.frame_rate()); + Config->map_parameters (mem_fun (*this, &Session::config_changed)); + /* every time we reconnect, recompute worst case output latencies */ _engine.Running.connect (mem_fun (*this, &Session::set_worst_io_latencies)); @@ -620,7 +648,7 @@ Session::when_engine_running () if (_click_io->set_state (*child->children().front()) == 0) { - _clicking = click_requested; + _clicking = Config->get_clicking (); } else { @@ -638,7 +666,7 @@ Session::when_engine_running () if (_click_io->add_output_port (first_physical_output, this)) { // relax, even though its an error } else { - _clicking = click_requested; + _clicking = Config->get_clicking (); } } } @@ -651,7 +679,7 @@ Session::when_engine_running () set_worst_io_latencies (); if (_clicking) { - ControlChanged (Clicking); /* EMIT SIGNAL */ + // XXX HOW TO ALERT UI TO THIS ? DO WE NEED TO? } if (auditioner == 0) { @@ -808,6 +836,11 @@ Session::when_engine_running () } } + + /* its safe to do this now */ + + restore_history (snap_name()); + _state_of_the_state = StateOfTheState (_state_of_the_state & ~(CannotSave|Dirty)); /* hook us up to the engine */ @@ -917,76 +950,12 @@ Session::record_enabling_legal () const // return false; // } - if (all_safe) { + if (Config->get_all_safe()) { return false; } return true; } -void -Session::set_auto_play (bool yn) -{ - if (auto_play != yn) { - auto_play = yn; - set_dirty (); - ControlChanged (AutoPlay); - } -} - -void -Session::set_auto_return (bool yn) -{ - if (auto_return != yn) { - auto_return = yn; - set_dirty (); - ControlChanged (AutoReturn); - } -} - -void -Session::set_crossfades_active (bool yn) -{ - if (crossfades_active != yn) { - crossfades_active = yn; - set_dirty (); - ControlChanged (CrossFadesActive); - } -} - -void -Session::set_do_not_record_plugins (bool yn) -{ - if (do_not_record_plugins != yn) { - do_not_record_plugins = yn; - set_dirty (); - ControlChanged (RecordingPlugins); - } -} - -void -Session::set_auto_input (bool yn) -{ - if (auto_input != yn) { - auto_input = yn; - - if (Config->get_use_hardware_monitoring() && transport_rolling()) { - /* auto-input only makes a difference if we're rolling */ - - boost::shared_ptr dsl = diskstreams.reader(); - - for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) { - if ((*i)->record_enabled ()) { - //cerr << "switching to input = " << !auto_input << __FILE__ << __LINE__ << endl << endl; - (*i)->monitor_input (!auto_input); - } - } - } - - set_dirty(); - ControlChanged (AutoInput); - } -} - void Session::reset_input_monitor_state () { @@ -997,7 +966,7 @@ Session::reset_input_monitor_state () for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) { if ((*i)->record_enabled ()) { //cerr << "switching to input = " << !auto_input << __FILE__ << __LINE__ << endl << endl; - (*i)->monitor_input (Config->get_use_hardware_monitoring() && !auto_input); + (*i)->monitor_input (Config->get_monitoring_model() == HardwareMonitoring && !Config->get_auto_input()); } } } else { @@ -1005,44 +974,19 @@ Session::reset_input_monitor_state () for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) { if ((*i)->record_enabled ()) { - //cerr << "switching to input = " << !auto_input << __FILE__ << __LINE__ << endl << endl; - (*i)->monitor_input (Config->get_use_hardware_monitoring()); + //cerr << "switching to input = " << !Config->get_auto_input() << __FILE__ << __LINE__ << endl << endl; + (*i)->monitor_input (Config->get_monitoring_model() == HardwareMonitoring); } } } } - -void -Session::set_input_auto_connect (bool yn) -{ - if (yn) { - input_auto_connect = AutoConnectOption (input_auto_connect|AutoConnectPhysical); - } else { - input_auto_connect = AutoConnectOption (input_auto_connect|~AutoConnectPhysical); - } - set_dirty (); -} - -bool -Session::get_input_auto_connect () const -{ - return (input_auto_connect & AutoConnectPhysical); -} - -void -Session::set_output_auto_connect (AutoConnectOption aco) -{ - output_auto_connect = aco; - set_dirty (); -} - void Session::auto_punch_start_changed (Location* location) { replace_event (Event::PunchIn, location->start()); - if (get_record_enabled() && get_punch_in()) { + if (get_record_enabled() && Config->get_punch_in()) { /* capture start has been changed, so save new pending state */ save_state ("", true); } @@ -1051,7 +995,7 @@ Session::auto_punch_start_changed (Location* location) void Session::auto_punch_end_changed (Location* location) { - jack_nframes_t when_to_stop = location->end(); + nframes_t when_to_stop = location->end(); // when_to_stop += _worst_output_latency + _worst_input_latency; replace_event (Event::PunchOut, when_to_stop); } @@ -1059,7 +1003,7 @@ Session::auto_punch_end_changed (Location* location) void Session::auto_punch_changed (Location* location) { - jack_nframes_t when_to_stop = location->end(); + nframes_t when_to_stop = location->end(); replace_event (Event::PunchIn, location->start()); //when_to_stop += _worst_output_latency + _worst_input_latency; @@ -1071,7 +1015,7 @@ Session::auto_loop_changed (Location* location) { replace_event (Event::AutoLoop, location->end(), location->start()); - if (transport_rolling() && get_auto_loop()) { + if (transport_rolling() && play_loop) { //if (_transport_frame < location->start() || _transport_frame > location->end()) { @@ -1082,7 +1026,7 @@ Session::auto_loop_changed (Location* location) request_locate (location->start(), true); } - else if (seamless_loop && !loop_changing) { + else if (Config->get_seamless_loop() && !loop_changing) { // schedule a locate-roll to refill the diskstreams at the // previous loop end @@ -1139,48 +1083,6 @@ Session::set_auto_punch_location (Location* location) auto_punch_location_changed (location); } -void -Session::set_punch_in (bool yn) -{ - if (punch_in == yn) { - return; - } - - Location* location; - - if ((location = _locations.auto_punch_location()) != 0) { - if ((punch_in = yn) == true) { - replace_event (Event::PunchIn, location->start()); - } else { - remove_event (location->start(), Event::PunchIn); - } - } - - set_dirty(); - ControlChanged (PunchIn); /* EMIT SIGNAL */ -} - -void -Session::set_punch_out (bool yn) -{ - if (punch_out == yn) { - return; - } - - Location* location; - - if ((location = _locations.auto_punch_location()) != 0) { - if ((punch_out = yn) == true) { - replace_event (Event::PunchOut, location->end()); - } else { - clear_events (Event::PunchOut); - } - } - - set_dirty(); - ControlChanged (PunchOut); /* EMIT SIGNAL */ -} - void Session::set_auto_loop_location (Location* location) { @@ -1274,7 +1176,7 @@ Session::enable_record () _last_record_location = _transport_frame; send_mmc_in_another_thread (MIDI::MachineControl::cmdRecordStrobe); - if (Config->get_use_hardware_monitoring() && auto_input) { + if (Config->get_monitoring_model() == HardwareMonitoring && Config->get_auto_input()) { boost::shared_ptr dsl = diskstreams.reader(); for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) { if ((*i)->record_enabled ()) { @@ -1304,7 +1206,7 @@ Session::disable_record (bool rt_context, bool force) send_mmc_in_another_thread (MIDI::MachineControl::cmdRecordExit); - if (Config->get_use_hardware_monitoring() && auto_input) { + if (Config->get_monitoring_model() == HardwareMonitoring && Config->get_auto_input()) { boost::shared_ptr dsl = diskstreams.reader(); for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) { @@ -1327,11 +1229,11 @@ Session::step_back_from_record () { g_atomic_int_set (&_record_status, Enabled); - if (Config->get_use_hardware_monitoring()) { + if (Config->get_monitoring_model() == HardwareMonitoring) { boost::shared_ptr dsl = diskstreams.reader(); for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) { - if (auto_input && (*i)->record_enabled ()) { + if (Config->get_auto_input() && (*i)->record_enabled ()) { //cerr << "switching from input" << __FILE__ << __LINE__ << endl << endl; (*i)->monitor_input (false); } @@ -1344,14 +1246,14 @@ Session::maybe_enable_record () { g_atomic_int_set (&_record_status, Enabled); - /* XXX this save should really happen in another thread. its needed so that - pending capture state can be recovered if we crash. + /* this function is currently called from somewhere other than an RT thread. + this save_state() call therefore doesn't impact anything. */ save_state ("", true); if (_transport_speed) { - if (!punch_in) { + if (!Config->get_punch_in()) { enable_record (); } } else { @@ -1362,12 +1264,12 @@ Session::maybe_enable_record () set_dirty(); } -jack_nframes_t +nframes_t Session::audible_frame () const { - jack_nframes_t ret; - jack_nframes_t offset; - jack_nframes_t tf; + nframes_t ret; + nframes_t offset; + nframes_t tf; /* the first of these two possible settings for "offset" mean that the audible frame is stationary until @@ -1421,9 +1323,9 @@ Session::audible_frame () const } void -Session::set_frame_rate (jack_nframes_t frames_per_second) +Session::set_frame_rate (nframes_t frames_per_second) { - /** \fn void Session::set_frame_size(jack_nframes_t) + /** \fn void Session::set_frame_size(nframes_t) the AudioEngine object that calls this guarantees that it will not be called while we are also in ::process(). Its fine to do things that block @@ -1437,7 +1339,7 @@ Session::set_frame_rate (jack_nframes_t frames_per_second) Route::set_automation_interval ((jack_nframes_t) ceil ((double) frames_per_second * 0.25)); // XXX we need some equivalent to this, somehow - // DestructiveFileSource::setup_standard_crossfades (frames_per_second); + // SndFileSource::setup_standard_crossfades (frames_per_second); set_dirty(); @@ -1445,7 +1347,7 @@ Session::set_frame_rate (jack_nframes_t frames_per_second) } void -Session::set_block_size (jack_nframes_t nframes) +Session::set_block_size (nframes_t nframes) { /* the AudioEngine guarantees that it will not be called while we are also in @@ -1513,7 +1415,7 @@ void Session::set_default_fade (float steepness, float fade_msecs) { #if 0 - jack_nframes_t fade_frames; + nframes_t fade_frames; /* Don't allow fade of less 1 frame */ @@ -1524,7 +1426,7 @@ Session::set_default_fade (float steepness, float fade_msecs) } else { - fade_frames = (jack_nframes_t) floor (fade_msecs * _current_frame_rate * 0.001); + fade_frames = (nframes_t) floor (fade_msecs * _current_frame_rate * 0.001); } @@ -1665,11 +1567,17 @@ Session::resort_routes_using (shared_ptr r) for (i = r->begin(); i != r->end(); ++i) { trace_terminal (*i, *i); - } - + } + RouteSorter cmp; r->sort (cmp); + /* don't leave dangling references to routes in Route::fed_by */ + + for (i = r->begin(); i != r->end(); ++i) { + (*i)->fed_by.clear (); + } + #if 0 cerr << "finished route resort\n"; @@ -1735,13 +1643,13 @@ Session::new_audio_track (int input_channels, int output_channels, TrackMode mod } while (track_id < (UINT_MAX-1)); - if (input_auto_connect & AutoConnectPhysical) { + if (Config->get_input_auto_connect() & AutoConnectPhysical) { nphysical_in = min (n_physical_inputs, (uint32_t) physinputs.size()); } else { nphysical_in = 0; } - if (output_auto_connect & AutoConnectPhysical) { + if (Config->get_output_auto_connect() & AutoConnectPhysical) { nphysical_out = min (n_physical_outputs, (uint32_t) physinputs.size()); } else { nphysical_out = 0; @@ -1761,7 +1669,7 @@ Session::new_audio_track (int input_channels, int output_channels, TrackMode mod port = ""; - if (input_auto_connect & AutoConnectPhysical) { + if (Config->get_input_auto_connect() & AutoConnectPhysical) { port = physinputs[(channels_used+x)%nphysical_in]; } @@ -1775,9 +1683,9 @@ Session::new_audio_track (int input_channels, int output_channels, TrackMode mod port = ""; - if (nphysical_out && (output_auto_connect & AutoConnectPhysical)) { + if (nphysical_out && (Config->get_output_auto_connect() & AutoConnectPhysical)) { port = physoutputs[(channels_used+x)%nphysical_out]; - } else if (output_auto_connect & AutoConnectMaster) { + } else if (Config->get_output_auto_connect() & AutoConnectMaster) { if (_master_out) { port = _master_out->input (x%_master_out->n_inputs())->name(); } @@ -1877,12 +1785,12 @@ Session::new_audio_route (int input_channels, int output_channels, uint32_t how_ << endmsg; } - for (uint32_t x = 0; x < bus->n_inputs(); ++x) { + for (uint32_t x = 0; n_physical_inputs && x < bus->n_inputs(); ++x) { port = ""; - - if (input_auto_connect & AutoConnectPhysical) { - port = physinputs[((n+x)%n_physical_inputs)]; + + if (Config->get_input_auto_connect() & AutoConnectPhysical) { + port = physinputs[((n+x)%n_physical_inputs)]; } if (port.length() && bus->connect_input (bus->input (x), port, this)) { @@ -1890,13 +1798,13 @@ Session::new_audio_route (int input_channels, int output_channels, uint32_t how_ } } - for (uint32_t x = 0; x < bus->n_outputs(); ++x) { + for (uint32_t x = 0; n_physical_outputs && x < bus->n_outputs(); ++x) { port = ""; - if (output_auto_connect & AutoConnectPhysical) { + if (Config->get_output_auto_connect() & AutoConnectPhysical) { port = physoutputs[((n+x)%n_physical_outputs)]; - } else if (output_auto_connect & AutoConnectMaster) { + } else if (Config->get_output_auto_connect() & AutoConnectMaster) { if (_master_out) { port = _master_out->input (x%_master_out->n_inputs())->name(); } @@ -1950,7 +1858,10 @@ Session::add_routes (RouteList& new_routes, bool save) } for (RouteList::iterator x = new_routes.begin(); x != new_routes.end(); ++x) { - (*x)->solo_changed.connect (sigc::bind (mem_fun (*this, &Session::route_solo_changed), (*x))); + + boost::weak_ptr wpr (*x); + + (*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)->redirects_changed.connect (mem_fun (*this, &Session::update_latency_compensation_proxy)); @@ -2000,19 +1911,20 @@ Session::remove_route (shared_ptr route) { RCUWriter writer (routes); shared_ptr rs = writer.get_copy (); - rs->remove (route); + rs->remove (route); + /* deleting the master out seems like a dumb idea, but its more of a UI policy issue than our concern. */ if (route == _master_out) { - _master_out = shared_ptr ((Route*) 0); + _master_out = shared_ptr (); } if (route == _control_out) { - _control_out = shared_ptr ((Route*) 0); + _control_out = shared_ptr (); /* cancel control outs for all routes */ @@ -2049,14 +1961,26 @@ Session::remove_route (shared_ptr route) update_latency_compensation (false, false); set_dirty(); + + // We need to disconnect the routes inputs and outputs + route->disconnect_inputs(NULL); + route->disconnect_outputs(NULL); - /* XXX should we disconnect from the Route's signals ? */ + /* get rid of it from the dead wood collection in the route list manager */ + + /* XXX i think this is unsafe as it currently stands, but i am not sure. (pd, october 2nd, 2006) */ - save_state (_current_snapshot_name); + routes.flush (); /* try to cause everyone to drop their references */ route->drop_references (); + + /* save the new state of the world */ + + if (save_state (_current_snapshot_name)) { + save_history (_current_snapshot_name); + } } void @@ -2066,7 +1990,7 @@ Session::route_mute_changed (void* src) } void -Session::route_solo_changed (void* src, shared_ptr route) +Session::route_solo_changed (void* src, boost::weak_ptr wpr) { if (solo_update_disabled) { // We know already @@ -2074,8 +1998,15 @@ Session::route_solo_changed (void* src, shared_ptr route) } bool is_track; - - is_track = (dynamic_cast(route.get()) != 0); + boost::shared_ptr route = wpr.lock (); + + if (!route) { + /* should not happen */ + error << string_compose (_("programming error: %1"), X_("invalid route weak ptr passed to route_solo_changed")) << endmsg; + return; + } + + is_track = (boost::dynamic_pointer_cast(route) != 0); shared_ptr r = routes.reader (); @@ -2111,7 +2042,7 @@ Session::route_solo_changed (void* src, shared_ptr route) then leave it as it is. */ - if (_solo_latched) { + if (Config->get_solo_latched()) { continue; } } @@ -2160,16 +2091,6 @@ Session::route_solo_changed (void* src, shared_ptr route) set_dirty(); } -void -Session::set_solo_latched (bool yn) -{ - if (yn != _solo_latched) { - _solo_latched = yn; - set_dirty (); - ControlChanged (SoloLatch); - } -} - void Session::update_route_solo_state () { @@ -2329,7 +2250,7 @@ Session::find_current_end () return; } - jack_nframes_t max = get_maximum_extent (); + nframes_t max = get_maximum_extent (); if (max > end_location->end()) { end_location->set_end (max); @@ -2338,11 +2259,11 @@ Session::find_current_end () } } -jack_nframes_t +nframes_t Session::get_maximum_extent () const { - jack_nframes_t max = 0; - jack_nframes_t me; + nframes_t max = 0; + nframes_t me; boost::shared_ptr dsl = diskstreams.reader(); @@ -2561,15 +2482,21 @@ Session::add_region (boost::shared_ptr region) set_dirty(); if (added) { - region->GoingAway.connect (sigc::bind (mem_fun (*this, &Session::remove_region), region)); - region->StateChanged.connect (sigc::bind (mem_fun (*this, &Session::region_changed), region)); + region->GoingAway.connect (sigc::bind (mem_fun (*this, &Session::remove_region), boost::weak_ptr(region))); + region->StateChanged.connect (sigc::bind (mem_fun (*this, &Session::region_changed), boost::weak_ptr(region))); AudioRegionAdded (ar); /* EMIT SIGNAL */ } } void -Session::region_changed (Change what_changed, boost::shared_ptr region) +Session::region_changed (Change what_changed, boost::weak_ptr weak_region) { + boost::shared_ptr region (weak_region.lock ()); + + if (!region) { + return; + } + if (what_changed & Region::HiddenChanged) { /* relay hidden changes */ RegionHiddenChange (region); @@ -2577,18 +2504,18 @@ Session::region_changed (Change what_changed, boost::shared_ptr region) } void -Session::region_renamed (boost::shared_ptr region) -{ - add_region (region); -} - -void -Session::remove_region (boost::shared_ptr region) +Session::remove_region (boost::weak_ptr weak_region) { AudioRegionList::iterator i; + boost::shared_ptr region (weak_region.lock ()); + + if (!region) { + return; + } + boost::shared_ptr ar; bool removed = false; - + { Glib::Mutex::Lock lm (region_lock); @@ -2614,12 +2541,12 @@ Session::remove_region (boost::shared_ptr region) set_dirty(); if (removed) { - AudioRegionRemoved(ar); /* EMIT SIGNAL */ + AudioRegionRemoved (ar); /* EMIT SIGNAL */ } } boost::shared_ptr -Session::find_whole_file_parent (boost::shared_ptr child) +Session::find_whole_file_parent (boost::shared_ptr child) { AudioRegionList::iterator i; boost::shared_ptr region; @@ -2637,7 +2564,7 @@ Session::find_whole_file_parent (boost::shared_ptr child) } } - return boost::shared_ptr ((AudioRegion*) 0); + return boost::shared_ptr (); } void @@ -2650,32 +2577,38 @@ Session::find_equivalent_playlist_regions (boost::shared_ptr region, vec int Session::destroy_region (boost::shared_ptr region) { - boost::shared_ptr aregion; - - if ((aregion = boost::dynamic_pointer_cast (region)) == 0) { - return 0; - } - - if (aregion->playlist()) { - aregion->playlist()->destroy_region (region); - } - vector > srcs; - - for (uint32_t n = 0; n < aregion->n_channels(); ++n) { - srcs.push_back (aregion->source (n)); + + { + boost::shared_ptr aregion; + + if ((aregion = boost::dynamic_pointer_cast (region)) == 0) { + return 0; + } + + if (aregion->playlist()) { + aregion->playlist()->destroy_region (region); + } + + for (uint32_t n = 0; n < aregion->n_channels(); ++n) { + srcs.push_back (aregion->source (n)); + } } + region->drop_references (); + for (vector >::iterator i = srcs.begin(); i != srcs.end(); ++i) { - - if ((*i).use_count() == 1) { - boost::shared_ptr afs = boost::dynamic_pointer_cast(*i); + if (!(*i)->used()) { + boost::shared_ptr afs = boost::dynamic_pointer_cast(*i); + if (afs) { (afs)->mark_for_remove (); } (*i)->drop_references (); + + cerr << "source was not used by any playlist\n"; } } @@ -2758,29 +2691,27 @@ Session::remove_source (boost::weak_ptr src) boost::shared_ptr source = src.lock(); if (!source) { - cerr << "removing a source DEAD\n"; - } else { - cerr << "removing a source " << source->name () << endl; + return; + } + + { + Glib::Mutex::Lock lm (audio_source_lock); - { - Glib::Mutex::Lock lm (audio_source_lock); - - if ((i = audio_sources.find (source->id())) != audio_sources.end()) { - audio_sources.erase (i); - } - } + if ((i = audio_sources.find (source->id())) != audio_sources.end()) { + audio_sources.erase (i); + } + } + + if (!_state_of_the_state & InCleanup) { - 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); - } + /* save state so we don't end up with a session file + referring to non-existent sources. + */ - SourceRemoved(source); /* EMIT SIGNAL */ + save_state (_current_snapshot_name); } + + SourceRemoved(source); /* EMIT SIGNAL */ } boost::shared_ptr @@ -2950,7 +2881,7 @@ Session::audio_path_from_name (string name, uint32_t nchan, uint32_t chan, bool spath = (*i).path; - spath += sound_dir_name; + spath += sound_dir (false); if (destructive) { if (nchan < 2) { @@ -2986,9 +2917,10 @@ Session::audio_path_from_name (string name, uint32_t nchan, uint32_t chan, bool } } - if (access (buf, F_OK) == 0) { + if (g_file_test (buf, G_FILE_TEST_EXISTS)) { existing++; - } + } + } if (existing == 0) { @@ -3068,6 +3000,20 @@ Session::add_playlist (Playlist* playlist) 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 (Playlist* pl, bool inuse) { @@ -3374,7 +3320,9 @@ Session::remove_redirect (Redirect* redirect) } else if ((plugin_insert = dynamic_cast (insert)) != 0) { _plugin_inserts.remove (plugin_insert); } else { - fatal << _("programming error: unknown type of Insert deleted!") << endmsg; + fatal << string_compose (_("programming error: %1"), + X_("unknown type of Insert deleted!")) + << endmsg; /*NOTREACHED*/ } } else if ((send = dynamic_cast (redirect)) != 0) { @@ -3387,16 +3335,35 @@ Session::remove_redirect (Redirect* redirect) set_dirty(); } -jack_nframes_t +nframes_t Session::available_capture_duration () { - const double scale = 4096.0 / sizeof (Sample); + float sample_bytes_on_disk; + + switch (Config->get_native_file_data_format()) { + case FormatFloat: + sample_bytes_on_disk = 4; + break; + + case FormatInt24: + sample_bytes_on_disk = 3; + break; + + default: + /* impossible, but keep some gcc versions happy */ + fatal << string_compose (_("programming error: %1"), + X_("illegal native file data format")) + << endmsg; + /*NOTREACHED*/ + } + + double scale = 4096.0 / sample_bytes_on_disk; if (_total_free_4k_blocks * scale > (double) max_frames) { return max_frames; } - return (jack_nframes_t) floor (_total_free_4k_blocks * scale); + return (nframes_t) floor (_total_free_4k_blocks * scale); } void @@ -3448,23 +3415,6 @@ Session::connection_by_name (string name) const return 0; } -void -Session::set_edit_mode (EditMode mode) -{ - _edit_mode = mode; - - { - Glib::Mutex::Lock lm (playlist_lock); - - for (PlaylistList::iterator i = playlists.begin(); i != playlists.end(); ++i) { - (*i)->set_edit_mode (mode); - } - } - - set_dirty (); - ControlChanged (EditingMode); /* EMIT SIGNAL */ -} - void Session::tempo_map_changed (Change ignored) { @@ -3511,9 +3461,15 @@ Session::ensure_passthru_buffers (uint32_t howmany) string Session::next_send_name () { - char buf[32]; - snprintf (buf, sizeof (buf), "send %" PRIu32, ++send_cnt); - return buf; + uint32_t cnt = 0; + + shared_ptr r = routes.reader (); + + for (RouteList::const_iterator i = r->begin(); i != r->end(); ++i) { + cnt += (*i)->count_sends (); + } + + return string_compose (_("send %1"), ++cnt); } string @@ -3612,17 +3568,7 @@ Session::n_playlists () const } void -Session::set_solo_model (SoloModel sm) -{ - if (sm != _solo_model) { - _solo_model = sm; - ControlChanged (SoloingModel); - set_dirty (); - } -} - -void -Session::allocate_pan_automation_buffers (jack_nframes_t nframes, uint32_t howmany, bool force) +Session::allocate_pan_automation_buffers (nframes_t nframes, uint32_t howmany, bool force) { if (!force && howmany <= _npan_buffers) { return; @@ -3667,7 +3613,7 @@ Session::freeze (InterThreadInfo& itt) } int -Session::write_one_audio_track (AudioTrack& track, jack_nframes_t start, jack_nframes_t len, +Session::write_one_audio_track (AudioTrack& track, nframes_t start, nframes_t len, bool overwrite, vector >& srcs, InterThreadInfo& itt) { int ret = -1; @@ -3677,13 +3623,13 @@ Session::write_one_audio_track (AudioTrack& track, jack_nframes_t start, jack_nf char buf[PATH_MAX+1]; string dir; uint32_t nchans; - jack_nframes_t position; - jack_nframes_t this_chunk; - jack_nframes_t to_do; + nframes_t position; + nframes_t this_chunk; + nframes_t to_do; vector buffers; // any bigger than this seems to cause stack overflows in called functions - const jack_nframes_t chunk_size = (128 * 1024)/4; + const nframes_t chunk_size = (128 * 1024)/4; g_atomic_int_set (&processing_prohibited, 1); @@ -3795,7 +3741,12 @@ Session::write_one_audio_track (AudioTrack& track, jack_nframes_t start, jack_nf afs->build_peaks (); } } - + + /* construct a region to represent the bounced material */ + + boost::shared_ptr aregion = RegionFactory::create (srcs, 0, srcs.front()->length(), + region_name_from_path (srcs.front()->name())); + ret = 0; } @@ -3863,43 +3814,14 @@ Session::nbusses () const } void -Session::set_layer_model (LayerModel lm) -{ - if (lm != layer_model) { - layer_model = lm; - set_dirty (); - ControlChanged (LayeringModel); - } -} - -void -Session::set_xfade_model (CrossfadeModel xm) -{ - if (xm != xfade_model) { - xfade_model = xm; - set_dirty (); - ControlChanged (CrossfadingModel); - } -} - -void -Session::handle_configuration_change (const char* parameter) +Session::add_automation_list(AutomationList *al) { - if (!strcmp (parameter, "use-video-sync")) { - if (_transport_speed == 0.0f) { - waiting_for_sync_offset = true; - } - } + automation_lists[al->id()] = al; } -void -Session::add_curve(Curve *curve) +nframes_t +Session::compute_initial_length () { - curves[curve->id()] = curve; + return _engine.frame_rate() * 60 * 5; } -void -Session::add_automation_list(AutomationList *al) -{ - automation_lists[al->id()] = al; -}