Move Diskstream ownership to Track, so that Session no longer holds lists of Diskstre...
[ardour.git] / gtk2_ardour / editor_audio_import.cc
index fb3828ab5375fc9985c8a1a013bb3c6dbc40ed19..119ea3bc5127f337887da759a03aa0646b8c1c15 100644 (file)
@@ -29,6 +29,7 @@
 #include "pbd/pthread_utils.h"
 #include "pbd/basename.h"
 #include "pbd/shortpath.h"
+#include "pbd/stateful_diff_command.h"
 
 #include <gtkmm2ext/choice.h>
 
 #include "session_import_dialog.h"
 #include "utils.h"
 #include "gui_thread.h"
+#include "interthread_progress_window.h"
 
 #include "i18n.h"
 
 using namespace std;
 using namespace ARDOUR;
 using namespace PBD;
-using namespace sigc;
 using namespace Gtk;
 using namespace Gtkmm2ext;
 using namespace Editing;
@@ -74,14 +75,14 @@ using Glib::ustring;
 void
 Editor::add_external_audio_action (ImportMode mode_hint)
 {
-       if (session == 0) {
+       if (_session == 0) {
                MessageDialog msg (_("You can't import or embed an audiofile until you have a session loaded."));
                msg.run ();
                return;
        }
-
+       
        if (sfbrowser == 0) {
-               sfbrowser = new SoundFileOmega (*this, _("Add Existing Media"), session, 0, true, mode_hint);
+               sfbrowser = new SoundFileOmega (*this, _("Add Existing Media"), _session, 0, true, mode_hint);
        } else {
                sfbrowser->set_mode (mode_hint);
        }
@@ -95,7 +96,7 @@ Editor::external_audio_dialog ()
        vector<Glib::ustring> paths;
        uint32_t track_cnt;
 
-       if (session == 0) {
+       if (_session == 0) {
                MessageDialog msg (_("You can't import or embed an audiofile until you have a session loaded."));
                msg.run ();
                return;
@@ -114,7 +115,7 @@ Editor::external_audio_dialog ()
        }
 
        if (sfbrowser == 0) {
-               sfbrowser = new SoundFileOmega (*this, _("Add Existing Media"), session, track_cnt, true);
+               sfbrowser = new SoundFileOmega (*this, _("Add Existing Media"), _session, track_cnt, true);
        } else {
                sfbrowser->reset (track_cnt);
        }
@@ -164,7 +165,7 @@ Editor::external_audio_dialog ()
                                where = playhead_cursor->current_frame;
                                break;
                        case ImportAtStart:
-                               where = session->current_start_frame();
+                               where = _session->current_start_frame();
                                break;
                }
 
@@ -188,7 +189,7 @@ Editor::external_audio_dialog ()
 void
 Editor::session_import_dialog ()
 {
-       SessionImportDialog dialog (*session);
+       SessionImportDialog dialog (_session);
        ensure_float (dialog);
        dialog.run ();
 }
@@ -212,7 +213,7 @@ Editor::check_whether_and_how_to_import(string path, bool all_or_nothing)
 {
        string wave_name (Glib::path_get_basename(path));
 
-       SourceMap all_sources = session->get_sources();
+       SourceMap all_sources = _session->get_sources();
        bool wave_name_exists = false;
 
        for (SourceMap::iterator i = all_sources.begin(); i != all_sources.end(); ++i) {
@@ -326,9 +327,11 @@ Editor::do_import (vector<ustring> paths, ImportDisposition chns, ImportMode mod
        vector<ustring> to_import;
        int nth = 0;
 
-       if (interthread_progress_window == 0) {
-               build_interthread_progress_window ();
-       }
+       current_interthread_info = &import_status;
+       import_status.current = 1;
+       import_status.total = paths.size ();
+
+       ImportProgressWindow ipw (&import_status, _("Import"), _("Cancel Import"));
 
        if (chns == Editing::ImportMergeFiles) {
 
@@ -346,47 +349,69 @@ Editor::do_import (vector<ustring> paths, ImportDisposition chns, ImportMode mod
                }
 
                if (!cancel) {
-                       import_sndfiles (paths, mode, quality, pos, 1, 1, track, false, paths.size());
+                       import_sndfiles (paths, mode, quality, pos, 1, 1, track, false);
                }
 
        } else {
 
-               for (vector<ustring>::iterator a = paths.begin(); a != paths.end(); ++a) {
-
-                       int const check = check_whether_and_how_to_import (*a, true);
-
-                       if (check != 2) {
-                               to_import.push_back (*a);
-                       }
-               }
-
+                bool replace = false;
                bool ok = true;
 
-               switch (chns) {
-               case Editing::ImportDistinctFiles:
+               for (vector<ustring>::iterator a = paths.begin(); a != paths.end(); ++a) {
 
-                       if (mode == Editing::ImportToTrack) {
-                               track = get_nth_selected_audio_track (nth++);
+                        const int check = check_whether_and_how_to_import (*a, true);
+                        
+                       switch (check) {
+                       case 2:
+                               // user said skip
+                               continue;
+                       case 0:
+                               fatal << "Updating existing sources should be disabled!" << endmsg;
+                               /* NOTREACHED*/
+                               break;
+                       case 1:
+                               replace = false;
+                               break;
+                       default:
+                               fatal << "Illegal return " << check <<  " from check_whether_and_how_to_import()!" << endmsg;
+                               /* NOTREACHED*/
                        }
 
-                       ok = (import_sndfiles (to_import, mode, quality, pos, 1, -1, track, false, to_import.size()) == 0);
-                       break;
-
-               case Editing::ImportDistinctChannels:
-                       ok = (import_sndfiles (to_import, mode, quality, pos, -1, -1, track, false, to_import.size()) == 0);
-                       break;
+                        switch (chns) {
+                        case Editing::ImportDistinctFiles:
+                                
+                                to_import.clear ();
+                                to_import.push_back (*a);
+                                
+                                if (mode == Editing::ImportToTrack) {
+                                        track = get_nth_selected_audio_track (nth++);
+                                }
+                       
+                                ok = (import_sndfiles (to_import, mode, quality, pos, 1, -1, track, replace) == 0);
+                                break;
+                               
+                        case Editing::ImportDistinctChannels:
+                               
+                                to_import.clear ();
+                                to_import.push_back (*a);
+                               
+                                ok = (import_sndfiles (to_import, mode, quality, pos, -1, -1, track, replace) == 0);
+                                break;
+                               
+                        case Editing::ImportSerializeFiles:
+                               
+                                to_import.clear ();
+                                to_import.push_back (*a);
 
-               case Editing::ImportSerializeFiles:
-                       ok = (import_sndfiles (to_import, mode, quality, pos, 1, 1, track, false, to_import.size()) == 0);
-                       break;
+                                ok = (import_sndfiles (to_import, mode, quality, pos, 1, 1, track, replace) == 0);
+                                break;
 
-               case Editing::ImportMergeFiles:
-                       // Not entered, handled in earlier if() branch
-                       break;
-               }
+                        case Editing::ImportMergeFiles:
+                                // Not entered, handled in earlier if() branch
+                                break;
+                        }
+                }
        }
-
-       interthread_progress_window->hide_all ();
 }
 
 void
@@ -432,7 +457,7 @@ Editor::do_embed (vector<ustring> paths, ImportDisposition chns, ImportMode mode
                if (embed_sndfiles (paths, multi, check_sample_rate, mode, pos, 1, 1, track) < -1) {
                        goto out;
                }
-       break;
+                break;
 
        case Editing::ImportSerializeFiles:
                for (vector<ustring>::iterator a = paths.begin(); a != paths.end(); ++a) {
@@ -451,20 +476,14 @@ Editor::do_embed (vector<ustring> paths, ImportDisposition chns, ImportMode mode
 
   out:
        if (ok) {
-               session->save_state ("");
+               _session->save_state ("");
        }
 }
 
 int
 Editor::import_sndfiles (vector<ustring> paths, ImportMode mode, SrcQuality quality, nframes64_t& pos,
-                        int target_regions, int target_tracks, boost::shared_ptr<Track> track, bool replace, uint32_t total)
+                        int target_regions, int target_tracks, boost::shared_ptr<Track>& track, bool replace)
 {
-       interthread_progress_window->set_title (string_compose (_("Importing %1"), paths.front()));
-       interthread_progress_window->set_position (Gtk::WIN_POS_MOUSE);
-       interthread_progress_bar.set_fraction (0.0f);
-       interthread_cancel_label.set_text (_("Cancel Import"));
-       current_interthread_info = &import_status;
-
        import_status.paths = paths;
        import_status.done = false;
        import_status.cancel = false;
@@ -472,7 +491,6 @@ Editor::import_sndfiles (vector<ustring> paths, ImportMode mode, SrcQuality qual
        import_status.done = 0.0;
        import_status.quality = quality;
        import_status.replace_existing_source = replace;
-       import_status.total = total;
 
        import_status.mode = mode;
        import_status.pos = pos;
@@ -480,8 +498,6 @@ Editor::import_sndfiles (vector<ustring> paths, ImportMode mode, SrcQuality qual
        import_status.target_regions = target_regions;
        import_status.track = track;
        import_status.replace = replace;
-       interthread_progress_connection = Glib::signal_timeout().connect
-               (bind (mem_fun(*this, &Editor::import_progress_timeout), (gpointer) 0), 500);
 
        track_canvas->get_window()->set_cursor (Gdk::Cursor (Gdk::WATCH));
        gdk_flush ();
@@ -498,9 +514,7 @@ Editor::import_sndfiles (vector<ustring> paths, ImportMode mode, SrcQuality qual
                gtk_main_iteration ();
        }
 
-       interthread_progress_window->hide ();
        import_status.done = true;
-       interthread_progress_connection.disconnect ();
 
        if (!import_status.cancel && !import_status.sources.empty()) {
                if (add_sources (import_status.paths,
@@ -509,8 +523,8 @@ Editor::import_sndfiles (vector<ustring> paths, ImportMode mode, SrcQuality qual
                                 import_status.mode,
                                 import_status.target_regions,
                                 import_status.target_tracks,
-                                import_status.track, false) == 0) {
-                       session->save_state ("");
+                                track, false) == 0) {
+                       _session->save_state ("");
                }
 
                /* update position from results */
@@ -546,7 +560,7 @@ Editor::embed_sndfiles (vector<Glib::ustring> paths, bool multifile,
 
                        /* lets see if we can link it into the session */
                        
-                       sys::path tmp = session->session_directory().sound_path() / Glib::path_get_basename(path);
+                       sys::path tmp = _session->session_directory().sound_path() / Glib::path_get_basename(path);
                        linked_path = tmp.to_string();
                        
                        path_to_use = linked_path;
@@ -588,7 +602,7 @@ Editor::embed_sndfiles (vector<Glib::ustring> paths, bool multifile,
                        goto out;
                }
 
-               if (check_sample_rate  && (finfo.samplerate != (int) session->frame_rate())) {
+               if (check_sample_rate  && (finfo.samplerate != (int) _session->frame_rate())) {
                        vector<string> choices;
 
                        if (multifile) {
@@ -597,9 +611,11 @@ Editor::embed_sndfiles (vector<Glib::ustring> paths, bool multifile,
                                choices.push_back (_("Embed all without questions"));
 
                                Gtkmm2ext::Choice rate_choice (
+                                       _("Sample rate"),
                                        string_compose (_("%1\nThis audiofile's sample rate doesn't match the session sample rate!"),
                                                        short_path (path, 40)),
-                                       choices, false);
+                                       choices, false
+                                       );
 
                                int resx = rate_choice.run ();
 
@@ -624,8 +640,10 @@ Editor::embed_sndfiles (vector<Glib::ustring> paths, bool multifile,
                                choices.push_back (_("Embed it anyway"));
 
                                Gtkmm2ext::Choice rate_choice (
+                                       _("Sample rate"),
                                        string_compose (_("%1\nThis audiofile's sample rate doesn't match the session sample rate!"), path),
-                                       choices, false);
+                                       choices, false
+                                       );
 
                                int resx = rate_choice.run ();
 
@@ -651,10 +669,10 @@ Editor::embed_sndfiles (vector<Glib::ustring> paths, bool multifile,
 
                                boost::shared_ptr<Source> s;
 
-                               if ((s = session->source_by_path_and_channel (path, n)) == 0) {
+                               if ((s = _session->source_by_path_and_channel (path, n)) == 0) {
 
                                        source = boost::dynamic_pointer_cast<AudioFileSource> (
-                                               SourceFactory::createReadable (DataType::AUDIO, *session,
+                                               SourceFactory::createReadable (DataType::AUDIO, *_session,
                                                                               path_to_use, n,
                                                                               (mode == ImportAsTapeTrack
                                                                                ? Source::Destructive
@@ -703,7 +721,7 @@ Editor::add_sources (vector<Glib::ustring> paths, SourceList& sources, nframes64
                if (sources[0]->natural_position() != 0) {
                        pos = sources[0]->natural_position();
                } else {
-                       pos = get_preferred_edit_position ();
+                       pos = _session->current_start_frame();
                }
        }
 
@@ -717,8 +735,16 @@ Editor::add_sources (vector<Glib::ustring> paths, SourceList& sources, nframes64
 
                region_name = region_name_from_path (paths.front(), (sources.size() > 1), false);
 
-               boost::shared_ptr<Region> r = RegionFactory::create (sources, 0, sources[0]->length(pos), region_name, 0,
-                                                                    Region::Flag (Region::DefaultFlags|Region::WholeFile|Region::External));
+               PropertyList plist; 
+               
+               plist.add (ARDOUR::Properties::start, 0);
+               plist.add (ARDOUR::Properties::length, sources[0]->length (pos));
+               plist.add (ARDOUR::Properties::name, region_name);
+               plist.add (ARDOUR::Properties::layer, 0);
+               plist.add (ARDOUR::Properties::whole_file, true);
+               plist.add (ARDOUR::Properties::external, true);
+
+               boost::shared_ptr<Region> r = RegionFactory::create (sources, plist);
 
                if (use_timestamp && boost::dynamic_pointer_cast<AudioRegion>(r)) {
                        boost::dynamic_pointer_cast<AudioRegion>(r)->special_set_position(sources[0]->natural_position());
@@ -742,8 +768,16 @@ Editor::add_sources (vector<Glib::ustring> paths, SourceList& sources, nframes64
 
                        region_name = region_name_from_path ((*x)->path(), false, false, sources.size(), n);
 
-                       boost::shared_ptr<Region> r = RegionFactory::create (just_one, 0, (*x)->length(pos), region_name, 0,
-                                                                            Region::Flag (Region::DefaultFlags|Region::WholeFile|Region::External));
+                       PropertyList plist; 
+                       
+                       plist.add (ARDOUR::Properties::start, 0);
+                       plist.add (ARDOUR::Properties::length, (*x)->length (pos));
+                       plist.add (ARDOUR::Properties::name, region_name);
+                       plist.add (ARDOUR::Properties::layer, 0);
+                       plist.add (ARDOUR::Properties::whole_file, true);
+                       plist.add (ARDOUR::Properties::external, true);
+
+                       boost::shared_ptr<Region> r = RegionFactory::create (just_one, plist);
 
                        if (use_timestamp && boost::dynamic_pointer_cast<AudioRegion>(r)) {
                                boost::dynamic_pointer_cast<AudioRegion>(r)->special_set_position((*x)->natural_position());
@@ -764,7 +798,7 @@ Editor::add_sources (vector<Glib::ustring> paths, SourceList& sources, nframes64
        }
 
        if (Config->get_output_auto_connect() & AutoConnectMaster) {
-               output_chan = (session->master_out() ? session->master_out()->n_inputs().n_audio() : input_chan);
+               output_chan = (_session->master_out() ? _session->master_out()->n_inputs().n_audio() : input_chan);
        } else {
                output_chan = input_chan;
        }
@@ -818,12 +852,12 @@ Editor::finish_bringing_in_material (boost::shared_ptr<Region> region, uint32_t
                        }
                }
 
-               boost::shared_ptr<Playlist> playlist = existing_track->diskstream()->playlist();
-               boost::shared_ptr<Region> copy (RegionFactory::create (region));
+               boost::shared_ptr<Playlist> playlist = existing_track->playlist();
+               boost::shared_ptr<Region> copy (RegionFactory::create (region, region->properties()));
                begin_reversible_command (_("insert file"));
-               XMLNode &before = playlist->get_state();
+                playlist->clear_history ();
                playlist->add_region (copy, pos);
-               session->add_command (new MementoCommand<Playlist>(*playlist, &before, &playlist->get_state()));
+               _session->add_command (new StatefulDiffCommand (playlist));
                commit_reversible_command ();
                break;
        }
@@ -832,7 +866,7 @@ Editor::finish_bringing_in_material (boost::shared_ptr<Region> region, uint32_t
        {
                if (!existing_track) {
                        if (ar) {
-                               list<boost::shared_ptr<AudioTrack> > at (session->new_audio_track (in_chans, out_chans, Normal, 0, 1));
+                               list<boost::shared_ptr<AudioTrack> > at (_session->new_audio_track (in_chans, out_chans, Normal, 0, 1));
 
                                if (at.empty()) {
                                        return -1;
@@ -840,7 +874,7 @@ Editor::finish_bringing_in_material (boost::shared_ptr<Region> region, uint32_t
 
                                existing_track = at.front();
                        } else if (mr) {
-                               list<boost::shared_ptr<MidiTrack> > mt (session->new_midi_track (Normal, 0, 1));
+                               list<boost::shared_ptr<MidiTrack> > mt (_session->new_midi_track (Normal, 0, 1));
 
                                if (mt.empty()) {
                                        return -1;
@@ -853,7 +887,7 @@ Editor::finish_bringing_in_material (boost::shared_ptr<Region> region, uint32_t
                }
 
                boost::shared_ptr<Region> copy (RegionFactory::create (region));
-               existing_track->diskstream()->playlist()->add_region (copy, pos);
+               existing_track->playlist()->add_region (copy, pos);
                break;
        }
 
@@ -863,11 +897,11 @@ Editor::finish_bringing_in_material (boost::shared_ptr<Region> region, uint32_t
                if (!ar)
                        return -1;
 
-               list<boost::shared_ptr<AudioTrack> > at (session->new_audio_track (in_chans, out_chans, Destructive));
+               list<boost::shared_ptr<AudioTrack> > at (_session->new_audio_track (in_chans, out_chans, Destructive));
                if (!at.empty()) {
                        boost::shared_ptr<Region> copy (RegionFactory::create (region));
                        at.front()->set_name (basename_nosuffix (copy->name()));
-                       at.front()->diskstream()->playlist()->add_region (copy, pos);
+                       at.front()->playlist()->add_region (copy, pos);
                }
                break;
        }
@@ -888,48 +922,8 @@ Editor::_import_thread (void *arg)
 void *
 Editor::import_thread ()
 {
-       session->import_audiofiles (import_status);
+       _session->import_audiofiles (import_status);
        pthread_exit_pbd (0);
        /*NOTREACHED*/
        return 0;
 }
-
-gint
-Editor::import_progress_timeout (void */*arg*/)
-{
-       bool reset = false;
-
-       if (!interthread_progress_window->is_visible()) {
-               interthread_progress_window->show_all ();
-               reset = true;
-       }
-
-       interthread_progress_label.set_text (import_status.doing_what);
-
-       if (import_status.freeze) {
-               interthread_cancel_button.set_sensitive(false);
-       } else {
-               interthread_cancel_button.set_sensitive(true);
-       }
-
-       if (import_status.doing_what == "building peak files") {
-               interthread_progress_bar.pulse ();
-               return FALSE;
-       } else {
-               float val = import_status.progress;
-               interthread_progress_bar.set_fraction (min (max (0.0f, val), 1.0f));
-       }
-
-       if (reset) {
-
-               /* the window is now visible, speed up the updates */
-
-               interthread_progress_connection.disconnect ();
-               interthread_progress_connection = Glib::signal_timeout().connect
-                       (bind (mem_fun(*this, &Editor::import_progress_timeout), (gpointer) 0), 100);
-               return false;
-       } else {
-               return !(import_status.done || import_status.cancel);
-       }
-}
-