allow to load/save default session-properties
[ardour.git] / libs / ardour / session.cc
index 04c86dc979e896316135fe9cd703acece4b2b989..121df3130cb60f2cf08755d6318ad28e9013b61e 100644 (file)
@@ -38,7 +38,6 @@
 
 #include "pbd/error.h"
 #include "pbd/boost_debug.h"
-#include "pbd/pathscanner.h"
 #include "pbd/stl_delete.h"
 #include "pbd/basename.h"
 #include "pbd/stacktrace.h"
@@ -82,6 +81,7 @@
 #include "ardour/region_factory.h"
 #include "ardour/route_graph.h"
 #include "ardour/route_group.h"
+#include "ardour/route_sorters.h"
 #include "ardour/send.h"
 #include "ardour/session.h"
 #include "ardour/session_directory.h"
@@ -194,6 +194,8 @@ Session::Session (AudioEngine &eng,
        , state_tree (0)
        , state_was_pending (false)
        , _state_of_the_state (StateOfTheState(CannotSave|InitialConnecting|Loading))
+       , _suspend_save (0)
+       , _save_queued (false)
        , _last_roll_location (0)
        , _last_roll_or_reversal_location (0)
        , _last_record_location (0)
@@ -235,6 +237,7 @@ Session::Session (AudioEngine &eng,
        , routes (new RouteList)
        , _adding_routes_in_progress (false)
        , destructive_index (0)
+       , _track_number_decimals(1)
        , solo_update_disabled (false)
        , default_fade_steepness (0)
        , default_fade_msecs (0)
@@ -297,6 +300,9 @@ Session::Session (AudioEngine &eng,
                        throw failed_constructor ();
                }
 
+               /* load default session properties - if any */
+               config.load_state();
+
        } else {
 
                if (load_state (_current_snapshot_name)) {
@@ -1879,6 +1885,7 @@ Session::new_midi_track (const ChanCount& input, const ChanCount& output, boost:
 
   failed:
        if (!new_routes.empty()) {
+               StateProtector sp (this);
                add_routes (new_routes, true, true, true);
 
                if (instrument) {
@@ -2120,6 +2127,7 @@ Session::new_audio_track (int input_channels, int output_channels, TrackMode mod
 
   failed:
        if (!new_routes.empty()) {
+               StateProtector sp (this);
                add_routes (new_routes, true, true, true);
        }
 
@@ -2205,6 +2213,7 @@ Session::new_audio_route (int input_channels, int output_channels, RouteGroup* r
 
   failure:
        if (!ret.empty()) {
+               StateProtector sp (this);
                add_routes (ret, false, true, true); // autoconnect outputs only
        }
 
@@ -2321,6 +2330,7 @@ Session::new_route_from_template (uint32_t how_many, const std::string& template
 
   out:
        if (!ret.empty()) {
+               StateProtector sp (this);
                add_routes (ret, true, true, true);
                IO::enable_connecting ();
        }
@@ -2350,6 +2360,8 @@ Session::add_routes (RouteList& new_routes, bool input_auto_connect, bool output
                save_state (_current_snapshot_name);
        }
        
+       reassign_track_numbers();
+
        RouteAdded (new_routes); /* EMIT SIGNAL */
 }
 
@@ -2627,6 +2639,7 @@ Session::remove_route (boost::shared_ptr<Route> route)
        if (save_state (_current_snapshot_name)) {
                save_history (_current_snapshot_name);
        }
+       reassign_track_numbers();
 }
 
 void
@@ -3043,6 +3056,42 @@ Session::route_by_remote_id (uint32_t id)
        return boost::shared_ptr<Route> ((Route*) 0);
 }
 
+
+void
+Session::reassign_track_numbers ()
+{
+       int64_t tn = 0;
+       int64_t bn = 0;
+       RouteList r (*(routes.reader ()));
+       SignalOrderRouteSorter sorter;
+       r.sort (sorter);
+
+       StateProtector sp (this);
+
+       for (RouteList::iterator i = r.begin(); i != r.end(); ++i) {
+               if (boost::dynamic_pointer_cast<Track> (*i)) {
+                       (*i)->set_track_number(++tn);
+               }
+               else if (!(*i)->is_master() && !(*i)->is_monitor() && !(*i)->is_auditioner()) {
+                       (*i)->set_track_number(--bn);
+               }
+       }
+       const uint32_t decimals = ceilf (log10f (tn + 1));
+       const bool decimals_changed = _track_number_decimals != decimals;
+       _track_number_decimals = decimals;
+
+       if (decimals_changed && config.get_track_name_number ()) {
+               for (RouteList::iterator i = r.begin(); i != r.end(); ++i) {
+                       boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track> (*i);
+                       if (t) {
+                               t->resync_track_name();
+                       }
+               }
+               // trigger GUI re-layout
+               config.ParameterChanged("track-name-number");
+       }
+}
+
 void
 Session::playlist_region_added (boost::weak_ptr<Region> w)
 {
@@ -3311,7 +3360,7 @@ Session::source_by_id (const PBD::ID& id)
 }
 
 boost::shared_ptr<AudioFileSource>
-Session::source_by_path_and_channel (const string& path, uint16_t chn) const
+Session::audio_source_by_path_and_channel (const string& path, uint16_t chn) const
 {
        /* Restricted to audio files because only audio sources have channel
           as a property.
@@ -3332,7 +3381,7 @@ Session::source_by_path_and_channel (const string& path, uint16_t chn) const
 }
 
 boost::shared_ptr<MidiSource>
-Session::source_by_path (const std::string& path) const
+Session::midi_source_by_path (const std::string& path) const
 {
        /* Restricted to MIDI files because audio sources require a channel
           for unique identification, in addition to a path.
@@ -3487,7 +3536,7 @@ Session::new_audio_source_name (const string& base, uint32_t nchan, uint32_t cha
 
                        string possible_path = Glib::build_filename (spath, buf);
 
-                       if (source_by_path (possible_path)) {
+                       if (audio_source_by_path_and_channel (possible_path, chan)) {
                                existing++;
                                break;
                        }
@@ -3553,7 +3602,7 @@ Session::new_midi_source_name (const string& owner_name)
                                existing++;
                        }
 
-                       if (source_by_path (possible_path)) {
+                       if (midi_source_by_path (possible_path)) {
                                existing++;
                        }
                }
@@ -4124,13 +4173,12 @@ Session::write_one_track (AudioTrack& track, framepos_t start, framepos_t end,
                          bool /*overwrite*/, vector<boost::shared_ptr<Source> >& srcs,
                          InterThreadInfo& itt, 
                          boost::shared_ptr<Processor> endpoint, bool include_endpoint,
-                         bool for_export)
+                         bool for_export, bool for_freeze)
 {
        boost::shared_ptr<Region> result;
        boost::shared_ptr<Playlist> playlist;
        boost::shared_ptr<AudioFileSource> fsource;
        uint32_t x;
-       char buf[PATH_MAX+1];
        ChanCount diskstream_channels (track.n_channels());
        framepos_t position;
        framecnt_t this_chunk;
@@ -4143,6 +4191,8 @@ Session::write_one_track (AudioTrack& track, framepos_t start, framepos_t end,
        bool need_block_size_reset = false;
        string ext;
        ChanCount const max_proc = track.max_processor_streams ();
+       string legal_playlist_name;
+       string possible_path;
 
        if (end <= start) {
                error << string_compose (_("Cannot write a range where end <= start (e.g. %1 <= %2)"),
@@ -4150,7 +4200,8 @@ Session::write_one_track (AudioTrack& track, framepos_t start, framepos_t end,
                return result;
        }
 
-       diskstream_channels = track.bounce_get_output_streams (diskstream_channels, endpoint, include_endpoint, for_export);
+       diskstream_channels = track.bounce_get_output_streams (diskstream_channels, endpoint,
+                       include_endpoint, for_export, for_freeze);
 
        if (diskstream_channels.n_audio() < 1) {
                error << _("Cannot write a range with no audio.") << endmsg;
@@ -4177,13 +4228,15 @@ Session::write_one_track (AudioTrack& track, framepos_t start, framepos_t end,
                goto out;
        }
 
+       legal_playlist_name = legalize_for_path (playlist->name());
+
        ext = native_header_format_extension (config.get_native_file_header_format(), DataType::AUDIO);
 
        for (uint32_t chan_n = 0; chan_n < diskstream_channels.n_audio(); ++chan_n) {
 
                for (x = 0; x < 99999; ++x) {
-                       snprintf (buf, sizeof(buf), "%s/%s-%d-bounce-%" PRIu32 "%s", sound_dir.c_str(), playlist->name().c_str(), chan_n, x+1, ext.c_str());
-                       if (!Glib::file_test (buf, Glib::FILE_TEST_EXISTS)) {
+                       possible_path = Glib::build_filename (sound_dir, string_compose ("%1-%2-bounce-%3%4", legal_playlist_name.c_str(), chan_n, x+1, ext.c_str()));
+                       if (!Glib::file_test (possible_path, Glib::FILE_TEST_EXISTS)) {
                                break;
                        }
                }
@@ -4195,11 +4248,11 @@ Session::write_one_track (AudioTrack& track, framepos_t start, framepos_t end,
 
                try {
                        fsource = boost::dynamic_pointer_cast<AudioFileSource> (
-                               SourceFactory::createWritable (DataType::AUDIO, *this, buf, false, frame_rate()));
+                               SourceFactory::createWritable (DataType::AUDIO, *this, possible_path, false, frame_rate()));
                }
 
                catch (failed_constructor& err) {
-                       error << string_compose (_("cannot create new audio file \"%1\" for %2"), buf, track.name()) << endmsg;
+                       error << string_compose (_("cannot create new audio file \"%1\" for %2"), possible_path, track.name()) << endmsg;
                        goto out;
                }
 
@@ -4217,7 +4270,7 @@ Session::write_one_track (AudioTrack& track, framepos_t start, framepos_t end,
 
        position = start;
        to_do = len;
-       latency_skip = track.bounce_get_latency (endpoint, include_endpoint, for_export);
+       latency_skip = track.bounce_get_latency (endpoint, include_endpoint, for_export, for_freeze);
 
        /* create a set of reasonably-sized buffers */
        for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
@@ -4235,7 +4288,7 @@ Session::write_one_track (AudioTrack& track, framepos_t start, framepos_t end,
 
                this_chunk = min (to_do, bounce_chunk_size);
 
-               if (track.export_stuff (buffers, start, this_chunk, endpoint, include_endpoint, for_export)) {
+               if (track.export_stuff (buffers, start, this_chunk, endpoint, include_endpoint, for_export, for_freeze)) {
                        goto out;
                }
 
@@ -4264,14 +4317,14 @@ Session::write_one_track (AudioTrack& track, framepos_t start, framepos_t end,
        }
 
        /* post-roll, pick up delayed processor output */
-       latency_skip = track.bounce_get_latency (endpoint, include_endpoint, for_export);
+       latency_skip = track.bounce_get_latency (endpoint, include_endpoint, for_export, for_freeze);
 
        while (latency_skip && !itt.cancel) {
                this_chunk = min (latency_skip, bounce_chunk_size);
                latency_skip -= this_chunk;
 
                buffers.silence (this_chunk, 0);
-               track.bounce_process (buffers, start, this_chunk, endpoint, include_endpoint, for_export);
+               track.bounce_process (buffers, start, this_chunk, endpoint, include_endpoint, for_export, for_freeze);
 
                uint32_t n = 0;
                for (vector<boost::shared_ptr<Source> >::iterator src=srcs.begin(); src != srcs.end(); ++src, ++n) {
@@ -5001,6 +5054,8 @@ Session::sync_order_keys ()
 
        DEBUG_TRACE (DEBUG::OrderKeys, "Sync Order Keys.\n");
 
+       reassign_track_numbers();
+
        Route::SyncOrderKeys (); /* EMIT SIGNAL */
 
        DEBUG_TRACE (DEBUG::OrderKeys, "\tsync done\n");