lots of fidgety work to get track renaming to work correctly now that we have to...
authorPaul Davis <paul@linuxaudiosystems.com>
Fri, 17 Mar 2006 17:39:21 +0000 (17:39 +0000)
committerPaul Davis <paul@linuxaudiosystems.com>
Fri, 17 Mar 2006 17:39:21 +0000 (17:39 +0000)
git-svn-id: svn://localhost/trunk/ardour2@404 d708f5d6-7413-0410-9779-e7cbd77b26cf

20 files changed:
gtk2_ardour/SConscript
gtk2_ardour/ardour.colors
gtk2_ardour/editor.cc
gtk2_ardour/editor.h
gtk2_ardour/editor_canvas.cc
gtk2_ardour/main.cc
libs/ardour/ardour/diskstream.h
libs/ardour/ardour/filesource.h
libs/ardour/ardour/session.h
libs/ardour/ardour/source.h
libs/ardour/audio_track.cc
libs/ardour/destructive_filesource.cc
libs/ardour/diskstream.cc
libs/ardour/externalsource.cc
libs/ardour/filesource.cc
libs/ardour/route.cc
libs/ardour/session.cc
libs/ardour/session_state.cc
libs/ardour/sndfilesource.cc
libs/ardour/source.cc

index 53576302cf62d2a677db2c92bc4cdd74e3b4d765..09e5b7f7eba20e2fae0cdf5826d275b7ba366e9f 100644 (file)
@@ -188,6 +188,7 @@ fft_result.cc
 """)
 
 glade_files=glob.glob('glade/*.glade')
+pixmap_files=glob.glob('pixmaps/*.xpm')
 
 intl_files = gtkardour_files + glade_files + glob.glob('*.h')
 
@@ -244,19 +245,20 @@ env.Alias('install', env.InstallAs(os.path.join(install_prefix, 'bin')+'/ardour'
 env.Alias('install', env.Install(os.path.join(config_prefix, 'ardour'), 'ardour2_ui.rc'))
 env.Alias('install', env.Install(os.path.join(config_prefix, 'ardour'), 'ardour.menus'))
 env.Alias('install', env.Install(os.path.join(config_prefix, 'ardour'), 'ardour.bindings'))
+env.Alias('install', env.Install(os.path.join(config_prefix, 'ardour'), 'ardour.colors'))
 env.Alias('install', env.Install(os.path.join(install_prefix, 'share/ardour'), 'splash.ppm'))
+env.Alias('install', env.Install(os.path.join(install_prefix, 'share/ardour/pixmaps'), pixmap_files))
 env.Alias('install', env.Install(os.path.join(install_prefix, 'share/ardour/glade'), glade_files))
 
 #dist
 env.Alias ('tarball', env.Distribute (env['DISTTREE'],
                                       [ 'SConscript',
                                         'i18n.h', 'gettext.h',
-                                        'editor_xpms', 'misc_xpms',
-                                        'crossfade_xpms.h', 'meter_xpms.h',
                                         'ardour2_ui.rc', 'splash.ppm',
-                                        'ardour.menus', 'ardour.bindings'
+                                        'ardour.menus', 'ardour.bindings', 'ardour.colors',
+                                       'editor_xpms'
                                         ] +
-                                      gtkardour_files + vst_files + glade_files +
+                                      gtkardour_files + vst_files + glade_files + pixmap_files +
                                       glob.glob('po/*.po') + glob.glob('*.h')))
 
 # generate a prototype full-featured ardour_ui.rc file
index db01ef384b565b2790295c638b1cf9af89e39f9a..cc514890fc582e51b90750bee3291d819d49fc45 100644 (file)
@@ -1,8 +1,8 @@
-cWaveForm 0.50 1.0 1.0 0.90
+cWaveForm 0.0 0.0 0.0 0.80
 cMutedWaveForm 0.35 0.35 0.35 1.0
-cSelectedFrameBase 0.63 0.13 0.94 0.2
-cFrameBase 0.0 0.0 0.0 0.25
-cAudioTrackBase 0.30 0.30 0.30 0.25
+cSelectedFrameBase 0.71 0.57 0.66 1.0
+cFrameBase 0.75 0.75 0.76 1.0
+cAudioTrackBase 0.79 0.80 0.85 0.41
 cAudioTrackOutline 0.00 0.00 0.00 1.00
 cAudioBusBase 0.90 0.82 0.90 0.41
 cTempoBar 0.64 0.64 0.66 1.0
index 88f1d05f3b9b2df076e7be9842cd9a8a5d2fa5dd..b68c1d3f6af3a4b02335de0d57ff6a08c7708070 100644 (file)
@@ -427,20 +427,18 @@ Editor::Editor (AudioEngine& eng)
        edit_packer.set_col_spacings (0);
        edit_packer.set_row_spacings (0);
        edit_packer.set_homogeneous (false);
+       edit_packer.set_border_width (0);
        edit_packer.set_name ("EditorWindow");
+       
+       edit_packer.attach (edit_vscrollbar,         0, 1, 1, 3,    FILL,        FILL|EXPAND, 0, 0);
 
-       edit_packer.attach (edit_hscrollbar,         1, 2, 0, 1,    FILL|EXPAND,  FILL, 0, 0);
-
-       edit_packer.attach (time_button_event_box,   0, 1, 1, 2,    FILL,        FILL, 0, 0);
-       edit_packer.attach (time_canvas_event_box,   1, 2, 1, 2,    FILL|EXPAND, FILL, 0, 0);
+       edit_packer.attach (time_button_event_box,   1, 2, 0, 1,    FILL,        FILL, 0, 0);
+       edit_packer.attach (time_canvas_event_box,   2, 3, 0, 1,    FILL|EXPAND, FILL, 0, 0);
 
-       edit_packer.attach (controls_layout,         0, 1, 2, 3,    FILL,        FILL|EXPAND, 0, 0);
-       edit_packer.attach (track_canvas_event_box,  1, 2, 2, 3,    FILL|EXPAND, FILL|EXPAND, 0, 0);
-       edit_packer.attach (edit_vscrollbar,         2, 3, 2, 3,    FILL,        FILL|EXPAND, 0, 0);
+       edit_packer.attach (controls_layout,         1, 2, 1, 2,    FILL,        FILL|EXPAND, 0, 0);
+       edit_packer.attach (track_canvas_event_box,  2, 3, 1, 2,    FILL|EXPAND, FILL|EXPAND, 0, 0);
 
-       edit_frame.set_name ("BaseFrame");
-       edit_frame.set_shadow_type (SHADOW_IN);
-       edit_frame.add (edit_packer);
+       edit_packer.attach (edit_hscrollbar,         2, 3, 2, 3,    FILL|EXPAND,  FILL, 0, 0);
 
        zoom_in_button.set_name ("EditorTimeButton");
        zoom_out_button.set_name ("EditorTimeButton");
@@ -637,20 +635,31 @@ Editor::Editor (AudioEngine& eng)
        snapshot_display.get_selection()->signal_changed().connect (mem_fun(*this, &Editor::snapshot_display_selection_changed));
        snapshot_display.signal_button_press_event().connect (mem_fun (*this, &Editor::snapshot_display_button_press), false);
 
-               the_notebook.append_page (region_list_scroller, _("Regions"));
-               the_notebook.append_page (route_list_scroller, _("Tracks/Busses"));
-       the_notebook.append_page (snapshot_display_scroller, _("Snapshots"));
-       the_notebook.append_page (*edit_group_display_packer, _("Edit Groups"));
-       the_notebook.append_page (named_selection_scroller, _("Chunks"));
+       Gtk::Label* nlabel;
+
+       nlabel = manage (new Label (_("Regions")));
+       nlabel->set_angle (-90);
+               the_notebook.append_page (region_list_scroller, *nlabel);
+       nlabel = manage (new Label (_("Tracks/Busses")));
+       nlabel->set_angle (-90);
+               the_notebook.append_page (route_list_scroller, *nlabel);
+       nlabel = manage (new Label (_("Snapshots")));
+       nlabel->set_angle (-90);
+       the_notebook.append_page (snapshot_display_scroller, *nlabel);
+       nlabel = manage (new Label (_("Edit Groups")));
+       nlabel->set_angle (-90);
+       the_notebook.append_page (*edit_group_display_packer, *nlabel);
+       nlabel = manage (new Label (_("Chunks")));
+       nlabel->set_angle (-90);
+       the_notebook.append_page (named_selection_scroller, *nlabel);
+
        the_notebook.set_show_tabs (true);
        the_notebook.set_scrollable (true);
        the_notebook.popup_enable ();
+       the_notebook.set_tab_pos (Gtk::POS_RIGHT);
 
-       TearOff *notebook_tearoff = manage (new TearOff (the_notebook, true));
-       notebook_tearoff->tearoff_window().set_size_request (200, 400);
-
-       edit_pane.pack1 (edit_frame, true, true);
-       edit_pane.pack2 (*notebook_tearoff, false, true);
+       edit_pane.pack1 (edit_packer, true, true);
+       edit_pane.pack2 (the_notebook, false, true);
        
        edit_pane.signal_size_allocate().connect_notify (bind (mem_fun(*this, &Editor::pane_allocation_handler), static_cast<Paned*> (&edit_pane)));
 
index ecf9da747d14fb4b64f53cc30d98c2ce24574f79..7312c5d596fc3b3a84cb381ef9d2fa80842fe255 100644 (file)
@@ -672,7 +672,6 @@ class Editor : public PublicEditor
        Gtk::HBox           bottom_hbox;
        
        Gtk::Table          edit_packer;
-       Gtk::Frame          edit_frame;
        Gtk::VScrollbar     edit_vscrollbar;
 
        Gtk::Adjustment     vertical_adjustment;
index 8db3ce7556eedc73e5f78f6fffa59cd8e4f81239..c18bf867cd88433824190f6fa09bcbc06aa3e1b2 100644 (file)
@@ -130,6 +130,7 @@ Editor::initialize_canvas ()
        time_canvas.set_name ("EditorTimeCanvas");
        time_canvas.add_events (Gdk::POINTER_MOTION_HINT_MASK);
        time_canvas.set_flags (CAN_FOCUS);
+       time_canvas.set_center_scroll_region (false);
        
        meter_group = new ArdourCanvas::Group (*time_canvas.root(), 0.0, 0.0);
        tempo_group = new ArdourCanvas::Group (*time_canvas.root(), 0.0, timebar_height);
index 14330e20092ae7440349f47032208418663466e7..028c38ac748760d61d9ae90d702166f206fa2b96 100644 (file)
@@ -239,11 +239,18 @@ string
 which_ui_rcfile ()
 {
        string rcfile;
+       char* env;
+
+       if ((env = getenv ("ARDOUR2_UI_RC")) != 0 && strlen (env)) {
+               rcfile = env;
+       } else {
+               rcfile = "ardour2_ui.rc";
+       }
+
+       rcfile = find_config_file (rcfile);
        
-       rcfile = find_config_file ("ardour2_ui.rc");
-       
-       if (rcfile.length() == 0) {
-               warning << _("Without a UI style file, ardour will look strange.\n Please set ARDOUR_UI_RC to point to a valid UI style file") << endmsg;
+       if (rcfile.empty()) {
+               warning << _("Without a UI style file, ardour will look strange.\n Please set ARDOUR2_UI_RC to point to a valid UI style file") << endmsg;
        }
 
        return rcfile;
index a163c125d739558f760389fe9a60fb5178ec9750..a0436696b0576f4103d4144de9f804dcab8e4029 100644 (file)
@@ -100,7 +100,7 @@ class DiskStream : public Stateful, public sigc::trackable
        jack_nframes_t roll_delay() const { return _roll_delay; }
        void set_roll_delay (jack_nframes_t);
 
-       void set_name (string str, void* src);
+       int set_name (string str, void* src);
 
        string input_source (uint32_t n=0) const {
                if (n < channels.size()) {
@@ -244,6 +244,7 @@ class DiskStream : public Stateful, public sigc::trackable
        void set_block_size (jack_nframes_t);
        int  internal_playback_seek (jack_nframes_t distance);
        int  can_internal_playback_seek (jack_nframes_t distance);
+       int  rename_write_sources ();
        void reset_write_sources (bool, bool force = false);
        void non_realtime_input_change ();
 
index af46596ec5fea7d866e295523929e1f69924278d..c7ae97c281e13e96e8384ac52934f85ae542007d 100644 (file)
@@ -54,12 +54,15 @@ class FileSource : public Source {
        FileSource (const XMLNode&, jack_nframes_t rate);
        ~FileSource ();
 
+       int set_name (std::string str, bool destructive);
+
+       void set_allow_remove_if_empty (bool yn);
+
        jack_nframes_t length() const { return _length; }
        jack_nframes_t read (Sample *dst, jack_nframes_t start, jack_nframes_t cnt, char * workbuf) const;
        jack_nframes_t write (Sample *src, jack_nframes_t cnt, char * workbuf);
        void           mark_for_remove();
        string         peak_path(string audio_path);
-       string         old_peak_path(string audio_path);
        string         path() const { return _path; }
 
        virtual int            seek (jack_nframes_t frame) {return 0; }
@@ -93,7 +96,8 @@ class FileSource : public Source {
        string        _take_id;
        SampleFormat  _sample_format;
        int           _sample_size;
-       
+       bool           allow_remove_if_empty;
+
        static char bwf_country_code[3];
        static char bwf_organization_code[4];
        static char bwf_serial_number[13];
index d0da2fef26861288adfdc4da4d393d03a59eacfa..24f15e97f53b9c01ff9be8e180004b58e00fcc1b 100644 (file)
@@ -253,8 +253,9 @@ class Session : public sigc::trackable, public Stateful
        static string template_dir ();
        static void get_template_list (list<string>&);
        
+       static string change_audio_path_by_name (string oldpath, string oldname, string newname, bool destructive);
        static string peak_path_from_audio_path (string);
-       static string old_peak_path_from_audio_path (string);
+       string audio_path_from_name (string, uint32_t nchans, uint32_t chan, bool destructive);
 
        void process (jack_nframes_t nframes);
 
@@ -1498,6 +1499,7 @@ class Session : public sigc::trackable, public Stateful
        RouteList       routes;
        mutable PBD::NonBlockingRWLock route_lock;
        void   add_route (Route*);
+       uint32_t destructive_index;
 
        int load_routes (const XMLNode&);
        Route* XMLRouteFactory (const XMLNode&);
index 7a5e2eb23ae27c6ed8cdb1baa12796e609ed221f..88a478a42027887a0393b6617987dbc482228db4 100644 (file)
@@ -56,6 +56,7 @@ class Source : public Stateful, public sigc::trackable
        virtual ~Source ();
 
        const string& name() const { return _name; }
+
        ARDOUR::id_t  id() const   { return _id; }
 
        /* returns the number of items in this `source' */
@@ -103,10 +104,11 @@ class Source : public Stateful, public sigc::trackable
        XMLNode& get_state ();
        int set_state (const XMLNode&);
 
-
        static int  start_peak_thread ();
        static void stop_peak_thread ();
 
+       int rename_peakfile (std::string newpath);
+
        static void set_build_missing_peakfiles (bool yn) {
                _build_missing_peakfiles = yn;
        }
@@ -125,7 +127,6 @@ class Source : public Stateful, public sigc::trackable
        jack_nframes_t    _length;
        bool               next_peak_clear_should_notify;
        string             peakpath;
-       int                peakfile; /* fd */
        time_t            _timestamp;
        string            _captured_for;
 
@@ -138,7 +139,6 @@ class Source : public Stateful, public sigc::trackable
        int  do_build_peak (jack_nframes_t, jack_nframes_t);
        virtual jack_nframes_t read_unlocked (Sample *dst, jack_nframes_t start, jack_nframes_t cnt, char * workbuf) const = 0;
        virtual string peak_path(string audio_path) = 0;
-       virtual string old_peak_path(string audio_path) = 0;
 
        static pthread_t peak_thread;
        static bool      have_peak_thread;
index 85cd86632c6340424741210244df5635a2bce5fd..ae3d1719c7b144d132b9de40da9030be993f6526 100644 (file)
@@ -755,13 +755,23 @@ AudioTrack::toggle_monitor_input ()
 int
 AudioTrack::set_name (string str, void *src)
 {
+       int ret;
+
        if (record_enabled() && _session.actively_recording()) {
                /* this messes things up if done while recording */
                return -1;
        }
 
-       diskstream->set_name (str, src);
-       return IO::set_name (str, src);
+       if (diskstream->set_name (str, src)) {
+               return -1;
+       }
+
+       /* save state so that the statefile fully reflects any filename changes */
+
+       if ((ret = IO::set_name (str, src)) == 0) {
+               _session.save_state ("");
+       }
+       return ret;
 }
 
 int
index 1ca6b5be5a8a764a7eedca660ec8832f99764b06..40138405b652edfdaa71032a2e431a445230d640 100644 (file)
@@ -69,7 +69,6 @@ jack_nframes_t DestructiveFileSource::xfade_frames = 64;
 DestructiveFileSource::DestructiveFileSource (string path, jack_nframes_t rate, bool repair_first, SampleFormat samp_format)
        : FileSource (path, rate, repair_first, samp_format)
 {
-       cerr << "DESTRUCTO DISK STREAM, " << _name << endl;
        if (out_coefficient == 0) {
                setup_standard_crossfades (rate);
        }
@@ -84,7 +83,6 @@ DestructiveFileSource::DestructiveFileSource (string path, jack_nframes_t rate,
 DestructiveFileSource::DestructiveFileSource (const XMLNode& node, jack_nframes_t rate)
        : FileSource (node, rate)
 {
-       cerr << "from XML, DESTRUCTO DISK STREAM, " << _name << endl;
        if (out_coefficient == 0) {
                setup_standard_crossfades (rate);
        }
index cd67659290501bee8778bd4113db10d5f5bf425a..28da6c9c31833a69dd0bad302ce55857d89eae55 100644 (file)
@@ -69,6 +69,9 @@ DiskStream::DiskStream (Session &sess, const string &name, Flag flag)
        /* prevent any write sources from being created */
 
        in_set_state = true;
+       
+       
+
        init (flag);
        use_new_playlist ();
        in_set_state = false;
@@ -472,13 +475,27 @@ void
 DiskStream::use_destructive_playlist ()
 {
        /* use the sources associated with the single full-extent region */
+       
+       Playlist::RegionList* rl = _playlist->regions_at (0);
+
+       if (rl->empty()) {
+               throw failed_constructor();
+       }
+
+       AudioRegion* region = dynamic_cast<AudioRegion*> (rl->front());
+
+       if (region == 0) {
+               throw failed_constructor();
+       }
+
+       delete rl;
 
-       AudioRegion* region = dynamic_cast<AudioRegion*> (_playlist->regions_at (0)->front());
        uint32_t n;
        ChannelList::iterator chan;
 
        for (n = 0, chan = channels.begin(); chan != channels.end(); ++chan, ++n) {
                (*chan).write_source = dynamic_cast<FileSource*>(&region->source (n));
+               (*chan).write_source->set_allow_remove_if_empty (false);
        }
 
        /* the source list will never be reset for a destructive track */
@@ -491,7 +508,7 @@ DiskStream::set_io (IO& io)
        set_align_style_from_io ();
 }
 
-void
+int
 DiskStream::set_name (string str, void *src)
 {
        if (str != _name) {
@@ -499,12 +516,14 @@ DiskStream::set_name (string str, void *src)
                _name = str;
                
                if (!in_set_state && recordable()) {
-
-                       /* open new capture files so that they have the correct name */
-
-                       reset_write_sources (false);
+                       /* rename existing capture files so that they have the correct name */
+                       return rename_write_sources ();
+               } else {
+                       return -1;
                }
        }
+
+       return 0;
 }
 
 void
@@ -2097,8 +2116,12 @@ DiskStream::set_state (const XMLNode& node)
                if (!had_playlist) {
                        _playlist->set_orig_diskstream_id (_id);
                }
-
-               if (capture_pending_node) {
+               
+               if (!destructive() && capture_pending_node) {
+                       /* destructive streams have one and only one source per channel,
+                          and so they never end up in pending capture in any useful
+                          sense.
+                       */
                        use_pending_capture_data (*capture_pending_node);
                }
 
@@ -2170,6 +2193,10 @@ DiskStream::use_new_write_source (uint32_t n)
 
        chan.write_source->use ();
 
+       /* do not remove destructive files even if they are empty */
+
+       chan.write_source->set_allow_remove_if_empty (!destructive());
+
        return 0;
 }
 
@@ -2213,6 +2240,22 @@ DiskStream::reset_write_sources (bool mark_write_complete, bool force)
        }
 }
 
+int
+DiskStream::rename_write_sources ()
+{
+       ChannelList::iterator chan;
+       uint32_t n;
+
+       for (chan = channels.begin(), n = 0; chan != channels.end(); ++chan, ++n) {
+               if ((*chan).write_source != 0) {
+                       (*chan).write_source->set_name (_name, destructive());
+                       /* XXX what to do if one of them fails ? */
+               }
+       }
+
+       return 0;
+}
+
 void
 DiskStream::set_block_size (jack_nframes_t nframes)
 {
index 568100ca4438cc7b0bc11122707cb5d00066a5be..4fb102a4a0159f4099ec9c4d4c77a0aa26cec8f1 100644 (file)
@@ -84,12 +84,6 @@ ExternalSource::peak_path (string audio_path)
        return res;
 }
 
-string
-ExternalSource::old_peak_path (string audio_path)
-{
-       return peak_path (audio_path);
-}
-
 #ifdef HAVE_COREAUDIO
 
 ExternalSource*
index b2fcc3d36d5af45d8f621db9cbf798d6bb6120bf..ad8979173e5895be9fe7e68ce5a0f5217bd9e9d8 100644 (file)
@@ -165,6 +165,7 @@ FileSource::init (string pathstr, bool must_exist, jack_nframes_t rate)
        fd = -1;
        remove_at_unref = false;
        next_peak_clear_should_notify = false;
+       allow_remove_if_empty = true;
 
        if (pathstr[0] != '/') {
 
@@ -300,7 +301,7 @@ FileSource::init (string pathstr, bool must_exist, jack_nframes_t rate)
        }
        
        if ((ret = initialize_peakfile (new_file, _path))) {
-               error << string_compose (_("FileSource: cannot initialize peakfile for %1"), _path) << endmsg;
+               error << string_compose (_("FileSource: cannot initialize peakfile for %1 as %2"), _path, peakpath) << endmsg;
        }
 
   out:
@@ -325,7 +326,7 @@ FileSource::~FileSource ()
        
        if (fd >= 0) {
 
-               if (remove_at_unref || is_empty (_path)) {
+               if (remove_at_unref || (is_empty (_path) && allow_remove_if_empty)) {
                        unlink (_path.c_str());
                        unlink (peakpath.c_str());
                }
@@ -334,6 +335,41 @@ FileSource::~FileSource ()
        } 
 }
 
+void
+FileSource::set_allow_remove_if_empty (bool yn)
+{
+       allow_remove_if_empty = yn;
+}
+
+int
+FileSource::set_name (string newname, bool destructive)
+{
+       LockMonitor lm (_lock, __LINE__, __FILE__);
+       string oldpath = _path;
+       string newpath = Session::change_audio_path_by_name (oldpath, _name, newname, destructive);
+
+       if (newpath.empty()) {
+               error << string_compose (_("programming error: %1"), "cannot generate a changed audio path") << endmsg;
+               return -1;
+       }
+
+       if (rename (oldpath.c_str(), newpath.c_str()) != 0) {
+               error << string_compose (_("cannot rename audio file for %1 to %2"), _name, newpath) << endmsg;
+               return -1;
+       }
+
+       _name = basename (newpath);
+       _path = newpath;
+
+       return rename_peakfile (peak_path (_path));
+}
+
+string
+FileSource::peak_path (string audio_path)
+{
+       return Session::peak_path_from_audio_path (audio_path);
+}
+
 int
 FileSource::discover_chunks (bool silent)
 {
@@ -1230,9 +1266,9 @@ FileSource::is_empty (string path)
           less than 1msec at typical sample rates.  
        */
 
-       /* NOTE: 700 bytes is the size of a BWF header structure *plus* our minimal coding history */
+       /* NOTE: 698 bytes is the size of a BWF header structure *plus* our minimal coding history */
 
-       return (statbuf.st_size == 0 || statbuf.st_size == wave_header_size || statbuf.st_size == 700);
+       return (statbuf.st_size == 0 || statbuf.st_size == wave_header_size || statbuf.st_size == 698);
 }
 
 void
@@ -1248,18 +1284,6 @@ FileSource::mark_streaming_write_completed ()
        }
 }
 
-string
-FileSource::peak_path(string audio_path)
-{
-       return Session::peak_path_from_audio_path (audio_path);
-}
-
-string
-FileSource::old_peak_path(string audio_path)
-{
-       return Session::old_peak_path_from_audio_path (audio_path);
-}
-
 void
 FileSource::mark_take (string id)
 {
@@ -1470,3 +1494,4 @@ FileSource::repair (string path, jack_nframes_t rate)
        fclose (in);
        return ret;
 }
+
index 18ce52dd437a673812ebd37fca012a82004d8fc7..84979fce6a63706b2f6e4ba4083bd411356dbf50 100644 (file)
@@ -622,6 +622,7 @@ Route::process_output_buffers (vector<Sample*>& bufs, uint32_t nbufs,
                        if (_session.transport_speed() > 1.5f || _session.transport_speed() < -1.5f) {
                                pan (bufs, nbufs, nframes, offset, speed_quietning); 
                        } else {
+                               // cerr << "panner state = " << _panner->automation_state() << endl;
                                if (!_panner->empty() &&
                                    (_panner->automation_state() & Play ||
                                     ((_panner->automation_state() & Touch) && !_panner->touching()))) {
index 9b61b5d816f726a5503a45a3234daa3670afd08e..fd54981908c459f969b7aaf4ca477c302e9ae6d8 100644 (file)
@@ -1881,6 +1881,11 @@ Session::add_route (Route* route)
                _control_out = route;
        }
 
+       AudioTrack* at = dynamic_cast<AudioTrack*>(route);
+       if (at && at->mode() == Destructive) {
+               destructive_index++;
+       }
+
        set_dirty();
        save_state (_current_snapshot_name);
 
@@ -2601,7 +2606,7 @@ void
 Session::add_source (Source* source)
 {
        pair<SourceList::key_type, SourceList::mapped_type> entry;
-       
+
        {
                LockMonitor lm (source_lock, __LINE__, __FILE__);
                entry.first = source->id();
@@ -2654,8 +2659,109 @@ Session::get_source (ARDOUR::id_t id)
        return source;
 }
 
-FileSource *
-Session::create_file_source (DiskStream& ds, int32_t chan, bool destructive)
+string
+Session::peak_path_from_audio_path (string audio_path)
+{
+       /* XXX hardly bombproof! fix me */
+
+       string res;
+
+       res = PBD::dirname (audio_path);
+       res = PBD::dirname (res);
+       res += '/';
+       res += peak_dir_name;
+       res += '/';
+       res += PBD::basename_nosuffix (audio_path);
+       res += ".peak";
+
+       return res;
+}
+
+string
+Session::change_audio_path_by_name (string path, string oldname, string newname, bool destructive)
+{
+       string look_for;
+       string old_basename = basename_nosuffix (oldname);
+       string new_legalized = legalize_for_path (newname);
+
+       /* note: we know (or assume) the old path is already valid */
+
+       if (destructive) {
+               
+               /* destructive file sources have a name of the form:
+
+                   /path/to/Tnnnn-NAME(%[LR])?.wav
+                 
+                   the task here is to replace NAME with the new name.
+               */
+               
+               /* find last slash */
+
+               string dir;
+               string prefix;
+               string::size_type slash;
+               string::size_type dash;
+
+               if ((slash = path.find_last_of ('/')) == string::npos) {
+                       return "";
+               }
+
+               dir = path.substr (0, slash+1);
+
+               /* '-' is not a legal character for the NAME part of the path */
+
+               if ((dash = path.find_last_of ('-')) == string::npos) {
+                       return "";
+               }
+
+               prefix = path.substr (slash+1, dash-(slash+1));
+
+               path = dir;
+               path += prefix;
+               path += '-';
+               path += new_legalized;
+               path += ".wav";  /* XXX gag me with a spoon */
+               
+       } else {
+               
+               /* non-destructive file sources have a name of the form:
+
+                   /path/to/NAME-nnnnn(%[LR])?.wav
+                 
+                   the task here is to replace NAME with the new name.
+               */
+               
+               /* find last slash */
+
+               string dir;
+               string suffix;
+               string::size_type slash;
+               string::size_type dash;
+
+               if ((slash = path.find_last_of ('/')) == string::npos) {
+                       return "";
+               }
+
+               dir = path.substr (0, slash+1);
+
+               /* '-' is not a legal character for the NAME part of the path */
+
+               if ((dash = path.find_last_of ('-')) == string::npos) {
+                       return "";
+               }
+
+               suffix = path.substr (dash);
+
+               path = dir;
+               path += new_legalized;
+               path += suffix;
+       }
+
+       return path;
+}
+
+string
+Session::audio_path_from_name (string name, uint32_t nchan, uint32_t chan, bool destructive)
 {
        string spath;
        uint32_t cnt;
@@ -2664,56 +2770,74 @@ Session::create_file_source (DiskStream& ds, int32_t chan, bool destructive)
        string legalized;
 
        buf[0] = '\0';
-       legalized = legalize_for_path (ds.name());
+       legalized = legalize_for_path (name);
 
        /* find a "version" of the file name that doesn't exist in
           any of the possible directories.
        */
        
-       for (cnt = 1; cnt <= limit; ++cnt) {
-
+       for (cnt = (destructive ? destructive_index + 1 : 1); cnt <= limit; ++cnt) {
+               
                vector<space_and_path>::iterator i;
                uint32_t existing = 0;
-
+               
                for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
-
+                       
                        spath = (*i).path;
-
+                       
                        if (destructive) {
                                spath += tape_dir_name;
                        } else {
                                spath += sound_dir_name;
                        }
-                       spath += '/';
-                       spath += legalized;
-
-                       if (ds.n_channels() < 2) {
-                               snprintf (buf, sizeof(buf), "%s-%u.wav", spath.c_str(), cnt);
-                       } else if (ds.n_channels() == 2) {
-                               if (chan == 0) {
-                                       snprintf (buf, sizeof(buf), "%s-%u%%L.wav", spath.c_str(), cnt);
+                       
+                       if (destructive) {
+                               if (nchan < 2) {
+                                       snprintf (buf, sizeof(buf), "%s/T%04d-%s.wav", spath.c_str(), cnt, legalized.c_str());
+                               } else if (nchan == 2) {
+                                       if (nchan == 0) {
+                                               snprintf (buf, sizeof(buf), "%s/T%04d-%s%%L.wav", spath.c_str(), cnt, legalized.c_str());
+                                       } else {
+                                               snprintf (buf, sizeof(buf), "%s/T%04d-%s%%R.wav", spath.c_str(), cnt, legalized.c_str());
+                                       }
+                               } else if (nchan < 26) {
+                                       snprintf (buf, sizeof(buf), "%s/T%04d-%s%%%c.wav", spath.c_str(), cnt, legalized.c_str(), 'a' + chan);
                                } else {
-                                       snprintf (buf, sizeof(buf), "%s-%u%%R.wav", spath.c_str(), cnt);
+                                       snprintf (buf, sizeof(buf), "%s/T%04d-%s.wav", spath.c_str(), cnt, legalized.c_str());
                                }
-                       } else if (ds.n_channels() < 26) {
-                               snprintf (buf, sizeof(buf), "%s-%u%%%c.wav", spath.c_str(), cnt, 'a' + chan);
                        } else {
-                               snprintf (buf, sizeof(buf), "%s-%u.wav", spath.c_str(), cnt);
+                               
+                               spath += '/';
+                               spath += legalized;
+                                       
+                               if (nchan < 2) {
+                                       snprintf (buf, sizeof(buf), "%s-%u.wav", spath.c_str(), cnt);
+                               } else if (nchan == 2) {
+                                       if (chan == 0) {
+                                               snprintf (buf, sizeof(buf), "%s-%u%%L.wav", spath.c_str(), cnt);
+                                       } else {
+                                               snprintf (buf, sizeof(buf), "%s-%u%%R.wav", spath.c_str(), cnt);
+                                       }
+                               } else if (nchan < 26) {
+                                       snprintf (buf, sizeof(buf), "%s-%u%%%c.wav", spath.c_str(), cnt, 'a' + chan);
+                               } else {
+                                       snprintf (buf, sizeof(buf), "%s-%u.wav", spath.c_str(), cnt);
+                               }
                        }
 
                        if (access (buf, F_OK) == 0) {
                                existing++;
                        }
                }
-
+                       
                if (existing == 0) {
                        break;
                }
-       }
 
-       if (cnt > limit) {
-               error << string_compose(_("There are already %1 recordings for %2, which I consider too many."), limit, ds.name()) << endmsg;
-               throw failed_constructor();
+               if (cnt > limit) {
+                       error << string_compose(_("There are already %1 recordings for %2, which I consider too many."), limit, name) << endmsg;
+                       throw failed_constructor();
+               }
        }
 
        /* we now have a unique name for the file, but figure out where to
@@ -2722,7 +2846,11 @@ Session::create_file_source (DiskStream& ds, int32_t chan, bool destructive)
 
        string foo = buf;
 
-       spath = discover_best_sound_dir ();
+       if (destructive) {
+               spath = tape_dir ();
+       } else {
+               spath = discover_best_sound_dir ();
+       }
 
        string::size_type pos = foo.find_last_of ('/');
        
@@ -2732,6 +2860,14 @@ Session::create_file_source (DiskStream& ds, int32_t chan, bool destructive)
                spath += foo.substr (pos + 1);
        }
 
+       return spath;
+}
+
+FileSource *
+Session::create_file_source (DiskStream& ds, int32_t chan, bool destructive)
+{
+       string spath = audio_path_from_name (ds.name(), ds.n_channels(), chan, destructive);
+
        /* this might throw failed_constructor(), which is OK */
 
        if (destructive) {
@@ -2944,40 +3080,6 @@ Session::is_auditioning () const
        }
 }
 
-
-string
-Session::peak_path_from_audio_path (string audio_path)
-{
-       /* XXX hardly bombproof! fix me */
-
-       string res;
-
-       res = PBD::dirname (audio_path);
-       res = PBD::dirname (res);
-       res += '/';
-       res += peak_dir_name;
-       res += '/';
-       res += PBD::basename_nosuffix (audio_path);
-       res += ".peak";
-
-       return res;
-}
-
-string
-Session::old_peak_path_from_audio_path (string audio_path)
-{
-       /* This is a hangover from when audio and peak files
-          lived in the same directory. We need it to to 
-          be able to open old sessions.
-       */
-
-       /* XXX hardly bombproof! fix me */
-
-       string res = audio_path.substr (0, audio_path.find_last_of ('.'));
-       res += ".peak";
-       return res;
-}
-
 void
 Session::set_all_solo (bool yn)
 {
index 5bb7ad01e4331a00da8498aaaf13c6e091fca055..3bfcb97c70d166d35cf8026fb71058557dcd6fdf 100644 (file)
@@ -192,6 +192,7 @@ Session::first_stage_init (string fullpath, string snapshot_name)
        pending_abort = false;
        layer_model = MoveAddHigher;
        xfade_model = ShortCrossfade;
+       destructive_index = 0;
 
        /* allocate conversion buffers */
        _conversion_buffers[ButlerContext] = new char[DiskStream::disk_io_frames() * 4];
@@ -401,13 +402,32 @@ Session::setup_raid_path (string path)
 
        if (colons == 0) {
 
-               /* no multiple search path, just one directory (common case) */
+               /* no multiple search path, just one location (common case) */
 
                sp.path = path;
                sp.blocks = 0;
                session_dirs.push_back (sp);
+
+               string fspath;
+
+               /* sounds dir */
+
+               fspath += sp.path;
+               if (fspath[fspath.length()-1] != '/') {
+                       fspath += '/';
+               }
+               fspath += sound_dir_name;
+               fspath += ':';
+
+               /* tape dir */
+
+               fspath += sp.path;
+               if (fspath[fspath.length()-1] != '/') {
+                       fspath += '/';
+               }
+               fspath += tape_dir_name;
                
-               FileSource::set_search_path (path + sound_dir_name);
+               FileSource::set_search_path (fspath);
 
                return;
        }
@@ -418,6 +438,9 @@ Session::setup_raid_path (string path)
                
                sp.blocks = 0;
                sp.path = remaining.substr (0, colon);
+               session_dirs.push_back (sp);
+
+               /* add sounds to file search path */
 
                fspath += sp.path;
                if (fspath[fspath.length()-1] != '/') {
@@ -426,7 +449,14 @@ Session::setup_raid_path (string path)
                fspath += sound_dir_name;
                fspath += ':';
 
-               session_dirs.push_back (sp);
+               /* add tape dir to file search path */
+
+               fspath += sp.path;
+               if (fspath[fspath.length()-1] != '/') {
+                       fspath += '/';
+               }
+               fspath += tape_dir_name;
+               fspath += ':';
 
                remaining = remaining.substr (colon+1);
        }
@@ -436,11 +466,19 @@ Session::setup_raid_path (string path)
                sp.blocks = 0;
                sp.path = remaining;
 
+               fspath += ':';
                fspath += sp.path;
                if (fspath[fspath.length()-1] != '/') {
                        fspath += '/';
                }
                fspath += sound_dir_name;
+               fspath += ':';
+
+               fspath += sp.path;
+               if (fspath[fspath.length()-1] != '/') {
+                       fspath += '/';
+               }
+               fspath += tape_dir_name;
 
                session_dirs.push_back (sp);
        }
@@ -681,7 +719,7 @@ Session::save_state (string snapshot_name, bool pending)
        if (!pending) {
 
                bool was_dirty = dirty();
-               
+
                _state_of_the_state = StateOfTheState (_state_of_the_state & ~Dirty);
                
                if (was_dirty) {
@@ -1298,10 +1336,18 @@ Session::state(bool full_state)
                        /* Don't save information about FileSources that are empty */
                        
                        FileSource* fs;
-                       
+
                        if ((fs = dynamic_cast<FileSource*> ((*siter).second)) != 0) {
-                               if (fs->length() == 0) {
-                                       continue;
+                               DestructiveFileSource* dfs = dynamic_cast<DestructiveFileSource*> (fs);
+
+                               /* destructive file sources are OK if they are empty, because
+                                  we will re-use them every time.
+                               */
+
+                               if (!dfs) {
+                                       if (fs->length() == 0) {
+                                               continue;
+                                       }
                                }
                        }
                        
index 5db5f95c35f07ebc0fa55c7b990df77b4575385b..522f94b5c2b20c3123d295fc7d7b8ab18c0f5965 100644 (file)
@@ -87,7 +87,7 @@ SndFileSource::init (const string& idstr, bool build_peak)
        _path = file;
 
        if (build_peak) {
-               if (initialize_peakfile (false, file)) {
+               if (initialize_peakfile (false, _path)) {
                        sf_close (sf);
                        sf = 0;
                        throw failed_constructor ();
index fb09293fd5bf138857fca5a6dc5d973823d425cd..ffb067733de6c2cb8fcf0fafd08b6fcf282ed21b 100644 (file)
@@ -59,7 +59,6 @@ Source::Source (bool announce)
        _use_cnt = 0;
        _peaks_built = false;
        next_peak_clear_should_notify = true;
-       peakfile = -1;
        _timestamp = 0;
        _read_data_count = 0;
        _write_data_count = 0;
@@ -70,7 +69,6 @@ Source::Source (const XMLNode& node)
        _use_cnt = 0;
        _peaks_built = false;
        next_peak_clear_should_notify = true;
-       peakfile = -1;
        _timestamp = 0;
        _read_data_count = 0;
        _write_data_count = 0;
@@ -82,9 +80,6 @@ Source::Source (const XMLNode& node)
 
 Source::~Source ()
 {
-       if (peakfile >= 0) {
-               close (peakfile);
-       }
 }
 
 XMLNode&
@@ -319,6 +314,25 @@ Source::peaks_ready (sigc::slot<void> the_slot, sigc::connection& conn) const
        return ret;
 }
 
+int
+Source::rename_peakfile (string newpath)
+{
+       /* caller must hold _lock */
+
+       string oldpath = peakpath;
+
+       if (access (oldpath.c_str(), F_OK) == 0) {
+               if (rename (oldpath.c_str(), newpath.c_str()) != 0) {
+                       error << string_compose (_("cannot rename peakfile for %1 from %2 to %3 (%4)"), _name, oldpath, newpath, strerror (errno)) << endmsg;
+                       return -1;
+               }
+       }
+
+       peakpath = newpath;
+
+       return 0;
+}
+
 int
 Source::initialize_peakfile (bool newfile, string audio_path)
 {
@@ -344,33 +358,6 @@ Source::initialize_peakfile (bool newfile, string audio_path)
                                return -1;
                        }
 
-                       /* older sessions stored peaks in the same directory
-                          as the audio. so check there as well.
-                       */
-                       
-                       string oldpeakpath = old_peak_path (audio_path);
-                       
-                       if (stat (oldpeakpath.c_str(), &statbuf)) {
-                               
-                               if (errno == ENOENT) {
-
-                                       statbuf.st_size = 0;
-
-                               } else {
-                                       
-                                       /* it exists in the audio dir , but there is some kind of error */
-                                       
-                                       error << string_compose(_("Source: cannot stat peakfile \"%1\" or \"%2\""), peakpath, oldpeakpath) << endmsg;
-                                       return -1;
-                               }
-                               
-                       } else {
-
-                               /* we found it in the sound dir, where they lived once upon a time, in a land ... etc. */
-
-                               peakpath = oldpeakpath;
-                       }
-
                } else {
                        
                        /* we found it in the peaks dir */
@@ -391,11 +378,6 @@ Source::initialize_peakfile (bool newfile, string audio_path)
                }
        }
 
-       if ((peakfile = ::open (peakpath.c_str(), O_RDWR|O_CREAT, 0664)) < 0) {
-               error << string_compose(_("Source: cannot open peakpath \"%1\" (%2)"), peakpath, strerror (errno)) << endmsg;
-               return -1;
-       }
-
        if (!newfile && !_peaks_built && _build_missing_peakfiles && _build_peakfiles) {
                build_peaks_from_scratch ();
        } 
@@ -418,7 +400,8 @@ Source::read_peaks (PeakData *peaks, jack_nframes_t npeaks, jack_nframes_t start
        PeakData* staging = 0;
        Sample* raw_staging = 0;
        char * workbuf = 0;
-       
+       int peakfile = -1;
+
        expected_peaks = (cnt / (double) frames_per_peak);
        scale = npeaks/expected_peaks;
 
@@ -474,11 +457,21 @@ Source::read_peaks (PeakData *peaks, jack_nframes_t npeaks, jack_nframes_t start
 
        if (scale == 1.0) {
 
+               off_t first_peak_byte = (start / frames_per_peak) * sizeof (PeakData);
+
+               /* open, read, close */
+
+               if ((peakfile = ::open (peakpath.c_str(), O_RDWR|O_CREAT, 0664)) < 0) {
+                       error << string_compose(_("Source: cannot open peakpath \"%1\" (%2)"), peakpath, strerror (errno)) << endmsg;
+                       return -1;
+               }
+
                // cerr << "DIRECT PEAKS\n";
                
-               off_t first_peak_byte = (start / frames_per_peak) * sizeof (PeakData);
+               nread = ::pread (peakfile, peaks, sizeof (PeakData)* npeaks, first_peak_byte);
+               close (peakfile);
 
-               if ((nread = ::pread (peakfile, peaks, sizeof (PeakData)* npeaks, first_peak_byte)) != sizeof (PeakData) * npeaks) {
+               if (nread != sizeof (PeakData) * npeaks) {
                        cerr << "Source["
                             << _name
                             << "]: cannot read peaks from peakfile! (read only " 
@@ -537,6 +530,13 @@ Source::read_peaks (PeakData *peaks, jack_nframes_t npeaks, jack_nframes_t start
 
                current_stored_peak = min (current_stored_peak, stored_peak_before_next_visual_peak);
 
+               /* open ... close during out: handling */
+
+               if ((peakfile = ::open (peakpath.c_str(), O_RDWR|O_CREAT, 0664)) < 0) {
+                       error << string_compose(_("Source: cannot open peakpath \"%1\" (%2)"), peakpath, strerror (errno)) << endmsg;
+                       return 0;
+               }
+
                while (nvisual_peaks < npeaks) {
 
                        if (i == stored_peaks_read) {
@@ -669,6 +669,10 @@ Source::read_peaks (PeakData *peaks, jack_nframes_t npeaks, jack_nframes_t start
        }
 
   out:
+       if (peakfile >= 0) {
+               close (peakfile);
+       }
+
        if (staging) {
                delete [] staging;
        } 
@@ -734,7 +738,6 @@ Source::build_peaks ()
                }
 
                if (pr_signal) {
-                       off_t fend = lseek (peakfile, 0, SEEK_END);
                        PeaksReady (); /* EMIT SIGNAL */
                }
        }
@@ -754,6 +757,7 @@ Source::do_build_peak (jack_nframes_t first_frame, jack_nframes_t cnt)
        jack_nframes_t frames_read;
        jack_nframes_t frames_to_read;
        off_t first_peak_byte;
+       int peakfile = -1;
        int ret = -1;
 
 #ifdef DEBUG_PEAK_BUILD
@@ -772,6 +776,11 @@ Source::do_build_peak (jack_nframes_t first_frame, jack_nframes_t cnt)
 
        workbuf = new char[max(frames_per_peak, cnt) * 4];
        
+       if ((peakfile = ::open (peakpath.c_str(), O_RDWR|O_CREAT, 0664)) < 0) {
+               error << string_compose(_("Source: cannot open peakpath \"%1\" (%2)"), peakpath, strerror (errno)) << endmsg;
+               return -1;
+       }
+       
        while (cnt) {
 
                frames_to_read = min (frames_per_peak, cnt);
@@ -810,6 +819,9 @@ Source::do_build_peak (jack_nframes_t first_frame, jack_nframes_t cnt)
 
   out:
        delete [] peakbuf;
+       if (peakfile >= 0) {
+               close (peakfile);
+       }
        if (workbuf)
                delete [] workbuf;
        return ret;
@@ -856,13 +868,27 @@ Source::release ()
 jack_nframes_t
 Source::available_peaks (double zoom_factor) const
 {
+       int peakfile;
+       off_t end;
+
        if (zoom_factor < frames_per_peak) {
                return length(); // peak data will come from the audio file
        } 
        
        /* peak data comes from peakfile */
 
-       LockMonitor lm (_lock, __LINE__, __FILE__);
-       off_t end = lseek (peakfile, 0, SEEK_END);
+       if ((peakfile = ::open (peakpath.c_str(), O_RDONLY)) < 0) {
+               error << string_compose(_("Source: cannot open peakpath \"%1\" (%2)"), peakpath, strerror (errno)) << endmsg;
+               return 0;
+       }
+
+       { 
+               LockMonitor lm (_lock, __LINE__, __FILE__);
+               end = lseek (peakfile, 0, SEEK_END);
+       }
+
+       close (peakfile);
+
        return (end/sizeof(PeakData)) * frames_per_peak;
 }
+