remove all duplicated _id members from children of PBD::Stateful.
authorPaul Davis <paul@linuxaudiosystems.com>
Thu, 7 Sep 2006 15:07:14 +0000 (15:07 +0000)
committerPaul Davis <paul@linuxaudiosystems.com>
Thu, 7 Sep 2006 15:07:14 +0000 (15:07 +0000)
Sources now know about Session.
rearrange session directory heirarchy. remove tape_dir stuff.
NSD allows absolute/relative paths to be typed straight into the text entry.
Session history reloaded after all 3rd party registrations done.
Editor restores its ID; other objects still need this.
use g_mkdir_with_parents() instead of mkdir()
one example of using g_file_test() instead of access.

git-svn-id: svn://localhost/ardour2/trunk@908 d708f5d6-7413-0410-9779-e7cbd77b26cf

50 files changed:
gtk2_ardour/ardev
gtk2_ardour/ardour_ui.cc
gtk2_ardour/ardour_ui_dependents.cc
gtk2_ardour/audio_streamview.cc
gtk2_ardour/automation_line.h
gtk2_ardour/editor.cc
gtk2_ardour/editor.h
gtk2_ardour/editor_audio_import.cc
gtk2_ardour/editor_export_audio.cc
gtk2_ardour/region_gain_line.h
gtk2_ardour/sfdb_ui.cc
libs/ardour/ardour/audio_diskstream.h
libs/ardour/ardour/audiofilesource.h
libs/ardour/ardour/audioplaylist.h
libs/ardour/ardour/audioregion.h
libs/ardour/ardour/audiosource.h
libs/ardour/ardour/automation_event.h
libs/ardour/ardour/destructive_filesource.h
libs/ardour/ardour/diskstream.h
libs/ardour/ardour/io.h
libs/ardour/ardour/location.h
libs/ardour/ardour/playlist.h
libs/ardour/ardour/region.h
libs/ardour/ardour/session.h
libs/ardour/ardour/sndfilesource.h
libs/ardour/ardour/source.h
libs/ardour/ardour/source_factory.h
libs/ardour/ardour/tempo.h
libs/ardour/audio_diskstream.cc
libs/ardour/audio_playlist.cc
libs/ardour/audiofilesource.cc
libs/ardour/audiofilter.cc
libs/ardour/audioregion.cc
libs/ardour/audiosource.cc
libs/ardour/destructive_filesource.cc
libs/ardour/globals.cc
libs/ardour/import.cc
libs/ardour/io.cc
libs/ardour/location.cc
libs/ardour/panner.cc
libs/ardour/plugin.cc
libs/ardour/session.cc
libs/ardour/session_state.cc
libs/ardour/session_time.cc
libs/ardour/session_timefx.cc
libs/ardour/sndfilesource.cc
libs/ardour/source.cc
libs/ardour/source_factory.cc
libs/ardour/vst_plugin.cc
libs/pbd/pbd/stateful.h

index 751557d634fbec98440b914b5951e1098a945f01..d3d44e55fe0d1c62ba50505699e7729295964035 100755 (executable)
@@ -1,3 +1,3 @@
 #!/bin/sh
 source `dirname "$0"`/ardev_common.sh
-exec gtk2_ardour/ardour.bin --novst "$*"
+exec gtk2_ardour/ardour.bin --novst $*
index c65346881a9711ab31159abc9912b46872506de9..0c8c26fdf090846412005d6b8bece6290305b5a7 100644 (file)
@@ -1616,6 +1616,9 @@ ARDOUR_UI::save_template ()
 void
 ARDOUR_UI::new_session (bool startup, std::string predetermined_path)
 {
+       string session_name;
+       string session_path;
+
        int response = Gtk::RESPONSE_NONE;
 
        new_session_dialog->set_modal(true);
@@ -1637,14 +1640,28 @@ ARDOUR_UI::new_session (bool startup, std::string predetermined_path)
                        new_session_dialog->reset();
 
                } else if (response == Gtk::RESPONSE_YES) {
-                       /* YES  == OPEN, but there's no enum for that */
 
-                       std::string session_name = new_session_dialog->session_name();
-                       std::string session_path = new_session_dialog->session_folder();
-                       load_session (session_path, session_name);
+                       /* YES  == OPEN, but there's no enum for that */
 
+                       session_name = new_session_dialog->session_name();
+                       
+                       if (session_name.empty()) {
+                               response = Gtk::RESPONSE_NONE;
+                               cerr << "session name is empty\n";
+                               continue;
+                       } 
+
+                       if (session_name[0] == '/' || 
+                           (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
+                           (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
+                               load_session (Glib::path_get_dirname (session_name), session_name);
+                       } else {
+                               session_path = new_session_dialog->session_folder();
+                               load_session (session_path, session_name);
+                       }
                        
                } else if (response == Gtk::RESPONSE_OK) {
+
                        if (new_session_dialog->get_current_page() == 1) {
                  
                                /* XXX this is a bit of a hack.. 
@@ -1652,93 +1669,121 @@ ARDOUR_UI::new_session (bool startup, std::string predetermined_path)
                                   if we're on page 1 (the load page)
                                   Unfortunately i can't see how atm.. 
                                */
-                        
-                               std::string session_name = new_session_dialog->session_name();
-                               std::string session_path = new_session_dialog->session_folder();
-                               load_session (session_path, session_name);
-                              
+                               
+                               if (session_name.empty()) {
+                                       response = Gtk::RESPONSE_NONE;
+                                       cerr << "session name is empty 2\n";
+                                       continue;
+                               } 
+                               
+                               if (session_name[0] == '/' || 
+                                   (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
+                                   (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
+                                       load_session (Glib::path_get_dirname (session_name), session_name);
+                               } else {
+                                       session_path = new_session_dialog->session_folder();
+                                       load_session (session_path, session_name);
+                               }
+                       
                        } else {
 
                                _session_is_new = true;
                              
-                               std::string session_name = new_session_dialog->session_name();
-                               std::string session_path = new_session_dialog->session_folder();
+                               session_name = new_session_dialog->session_name();
                        
+                               if (session_name.empty()) {
+                                       response = Gtk::RESPONSE_NONE;
+                                       cerr << "session name is empty 3\n";
+                                       continue;
+                               } 
+
+                               if (session_name[0] == '/' || 
+                                   (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
+                                   (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
+
+                                       session_path = Glib::path_get_dirname (session_name);
+                                       session_name = Glib::path_get_basename (session_name);
+
+                               } else {
+
+                                       std::string session_path = new_session_dialog->session_folder();
+                                       
+                               }
                        
                                //XXX This is needed because session constructor wants a 
                                //non-existant path. hopefully this will be fixed at some point.
-                       
-                               session_path = Glib::build_filename(session_path, session_name);
-                       
+                               
+                               session_path = Glib::build_filename (session_path, session_name);
+                                               
                                std::string template_name = new_session_dialog->session_template_name();
-                       
+                                               
                                if (new_session_dialog->use_session_template()) {
-                         
-                                       load_session (session_path, session_name, &template_name);
+                                                       
+                                       load_session (session_path, session_name, &template_name);
                          
                                } else {
-                               
-                                       uint32_t cchns;
+                                                       
+                                       uint32_t cchns;
                                        uint32_t mchns;
                                        Session::AutoConnectOption iconnect;
                                        Session::AutoConnectOption oconnect;
-                               
+                                                       
                                        if (new_session_dialog->create_control_bus()) {
-                                               cchns = (uint32_t) new_session_dialog->control_channel_count();
+                                               cchns = (uint32_t) new_session_dialog->control_channel_count();
                                        } else {
-                                               cchns = 0;
+                                               cchns = 0;
                                        }
-                               
+                                                       
                                        if (new_session_dialog->create_master_bus()) {
-                                               mchns = (uint32_t) new_session_dialog->master_channel_count();
+                                               mchns = (uint32_t) new_session_dialog->master_channel_count();
                                        } else {
-                                               mchns = 0;
+                                               mchns = 0;
                                        }
-                                     
+                                                       
                                        if (new_session_dialog->connect_inputs()) {
-                                               iconnect = Session::AutoConnectPhysical;
+                                               iconnect = Session::AutoConnectPhysical;
                                        } else {
-                                               iconnect = Session::AutoConnectOption (0);
+                                               iconnect = Session::AutoConnectOption (0);
                                        }
-                                     
+                                                       
                                        /// @todo some minor tweaks.
-                               
+                                                       
                                        if (new_session_dialog->connect_outs_to_master()) {
-                                               oconnect = Session::AutoConnectMaster;
+                                               oconnect = Session::AutoConnectMaster;
                                        } else if (new_session_dialog->connect_outs_to_physical()) {
-                                               oconnect = Session::AutoConnectPhysical;
+                                               oconnect = Session::AutoConnectPhysical;
                                        } else {
-                                               oconnect = Session::AutoConnectOption (0);
+                                               oconnect = Session::AutoConnectOption (0);
                                        } 
-                               
+                                                       
                                        uint32_t nphysin = (uint32_t) new_session_dialog->input_limit_count();
                                        uint32_t nphysout = (uint32_t) new_session_dialog->output_limit_count();
-                               
+                                                       
                                        build_session (session_path,
-                                              session_name,
-                                              cchns,
-                                              mchns,
-                                              iconnect,
-                                              oconnect,
-                                              nphysin,
-                                              nphysout, 
-                                              engine->frame_rate() * 60 * 5);
+                                                      session_name,
+                                                      cchns,
+                                                      mchns,
+                                                      iconnect,
+                                                      oconnect,
+                                                      nphysin,
+                                                      nphysout, 
+                                                      engine->frame_rate() * 60 * 5);
                                }
-                       }       
+                       }
                }
                
        } while (response == Gtk::RESPONSE_NONE);
+
        show();
        new_session_dialog->get_window()->set_cursor();
-       
        new_session_dialog->hide();
 }
 
 void
 ARDOUR_UI::close_session()
 {
-  unload_session();
-  new_session ();
+       unload_session();
+       new_session ();
 }
 
 int
index 0603fc6baa5acb95ee365736ac18eb2be21734c1..bf096f86c1a729728c1dd4eeb0f66e6c2fb63e76 100644 (file)
@@ -79,6 +79,10 @@ ARDOUR_UI::connect_dependents_to_session (ARDOUR::Session *s)
 {
        editor->connect_to_session (s);
        mixer->connect_to_session (s);
+
+       /* its safe to do this now */
+
+       s->restore_history (s->snap_name());
 }
 
 void
index beb8cb8d2ec8dbdc653484949fdab53cb47a08de..fcf2289570d9c9e0fc78b7a7555c31b80a4fd654 100644 (file)
@@ -69,6 +69,7 @@ AudioStreamView::AudioStreamView (AudioTimeAxisView& tv)
 
        use_rec_regions = tv.editor.show_waveforms_recording ();
        last_rec_peak_frame = 0;
+
 }
 
 AudioStreamView::~AudioStreamView ()
index f8262d2a2d55ba03cc795c4f2b20e4305fc95ad3..8311025b029c594bc3d59eed1e2f56c6b501ba7c 100644 (file)
@@ -163,9 +163,8 @@ class AutomationLine : public sigc::trackable, public PBD::StatefulDestructible
        XMLNode& get_state (void);
        int set_state (const XMLNode&);
 
-        PBD::ID id() { return _id; }
   protected:
-        PBD::ID _id;
+
        string _name;
        guint32 _height;
        uint32_t _line_color;
index 1b2d61a136420a9905b4aaa4f3e797fe6bd9c438..b9d14d44751beeb78610b30ece7434efd5111188 100644 (file)
@@ -1327,6 +1327,7 @@ Editor::connect_to_session (Session *t)
        }
 
         /* register for undo history */
+
         session->register_with_memento_command_factory(_id, this);
 }
 
@@ -2109,6 +2110,9 @@ Editor::set_state (const XMLNode& node)
        int x, y, xoff, yoff;
        Gdk::Geometry g;
 
+       if ((prop = node.property ("id")) != 0) {
+               _id = prop->value ();
+       }
 
        if ((geometry = find_named_node (node, "geometry")) == 0) {
 
@@ -2240,6 +2244,9 @@ Editor::get_state ()
        XMLNode* node = new XMLNode ("Editor");
        char buf[32];
 
+       _id.print (buf);
+       node->add_property ("id", buf);
+       
        if (is_realized()) {
                Glib::RefPtr<Gdk::Window> win = get_window();
                
@@ -2249,7 +2256,7 @@ Editor::get_state ()
                win->get_size(width, height);
                
                XMLNode* geometry = new XMLNode ("geometry");
-               char buf[32];
+
                snprintf(buf, sizeof(buf), "%d", width);
                geometry->add_property("x_size", string(buf));
                snprintf(buf, sizeof(buf), "%d", height);
index 49a5a7b94febe10261bd3ab707e7bf918e504d91..81bbbdaaab2b7c0ddd5162a42cc0f5d25a3d11b1 100644 (file)
@@ -143,8 +143,6 @@ class Editor : public PublicEditor
        XMLNode& get_state ();
        int set_state (const XMLNode& );
 
-        PBD::ID id() { return _id; }
-
        void set_mouse_mode (Editing::MouseMode, bool force=true);
        void step_mouse_mode (bool next);
        Editing::MouseMode current_mouse_mode () { return mouse_mode; }
@@ -349,8 +347,6 @@ class Editor : public PublicEditor
        ARDOUR::AudioEngine& engine;
        bool                 constructed;
 
-        PBD::ID _id;
-
        PlaylistSelector* _playlist_selector;
 
        void          set_frames_per_unit (double);
index 75517ec18d5baa14ba761f5436993f615f8823d5..2b3d983ab412c0ecd0e6ce6a806d514c4168d46b 100644 (file)
@@ -270,7 +270,7 @@ Editor::embed_sndfile (Glib::ustring path, bool split, bool multiple_files, bool
                idspec += string_compose(":%1", n);
                
                try {
-                       source = boost::dynamic_pointer_cast<AudioFileSource> (SourceFactory::createReadable (idspec, (mode == ImportAsTrack ? AudioFileSource::Destructive : AudioFileSource::Flag (0))));
+                       source = boost::dynamic_pointer_cast<AudioFileSource> (SourceFactory::createReadable (*session, idspec, (mode == ImportAsTrack ? AudioFileSource::Destructive : AudioFileSource::Flag (0))));
                        sources.push_back(source);
                } 
                
index dc7fadb4702a4b572d267e0d2aa0d71ad271516a..2a62f7a7512674ccf68d3b9f52cbfe71034895a4 100644 (file)
@@ -208,7 +208,7 @@ Editor::write_region (string path, boost::shared_ptr<AudioRegion> region)
                
                        
                        try {
-                               fs = boost::dynamic_pointer_cast<AudioFileSource> (SourceFactory::createReadable (path, AudioFileSource::Flag (0)));
+                               fs = boost::dynamic_pointer_cast<AudioFileSource> (SourceFactory::createReadable (*session, path, AudioFileSource::Flag (0)));
                        }
                        
                        catch (failed_constructor& err) {
@@ -339,7 +339,7 @@ Editor::write_audio_range (AudioPlaylist& playlist, uint32_t channels, list<Audi
                path = s;
                
                try {
-                       fs = boost::dynamic_pointer_cast<AudioFileSource> (SourceFactory::createReadable (path, AudioFileSource::Flag (0)));
+                       fs = boost::dynamic_pointer_cast<AudioFileSource> (SourceFactory::createReadable (*session, path, AudioFileSource::Flag (0)));
                }
                
                catch (failed_constructor& err) {
index 02340c8bae29e49feae6b77dccf36b1a140b8a4c..3781fe60bb2ee0abbcaac9b185c8d582e69f06b5 100644 (file)
@@ -26,16 +26,12 @@ class AudioRegionGainLine : public AutomationLine
 
        void remove_point (ControlPoint&);
 
-        PBD::ID id() { return _id; }
-
 
   private:
        ARDOUR::Session& session;
        AudioRegionView& rv;
 
        UndoAction get_memento();
-
-        PBD::ID _id;
 };
 
 
index 5cfcf56337c85ce69ceb209faa3150372a9a9dd6..124b33a9f1cfaebe84ed11d0840777260827c6cc 100644 (file)
@@ -198,7 +198,7 @@ SoundFileBox::play_btn_clicked ()
                
                for (int n = 0; n < sf_info.channels; ++n) {
                        try {
-                               afs = boost::dynamic_pointer_cast<AudioFileSource> (SourceFactory::createReadable (path+":"+string_compose("%1", n), AudioFileSource::Flag (0)));
+                               afs = boost::dynamic_pointer_cast<AudioFileSource> (SourceFactory::createReadable (*_session, path+":"+string_compose("%1", n), AudioFileSource::Flag (0)));
                                srclist.push_back(afs);
 
                        } catch (failed_constructor& err) {
index 44fb6e59a4dc2716e57ee1f0f4635bd57909304a..a43c198ff2944512432f483165267e10a6a0bcd0 100644 (file)
@@ -61,8 +61,6 @@ class AudioDiskstream : public Diskstream
        AudioDiskstream (Session &, const XMLNode&);
        ~AudioDiskstream();
 
-       const PBD::ID& id() const { return _id; }
-
        float playback_buffer_load() const;
        float capture_buffer_load() const;
 
index b0aa9bac588ac5817ebe53aa10e1708885209d0b..a18f055fd384a074134892cafd04528c1fbeb76c 100644 (file)
@@ -75,7 +75,7 @@ class AudioFileSource : public AudioSource {
 
        int move_to_trash (const string trash_dir_name);
 
-       static bool is_empty (string path);
+       static bool is_empty (Session&, string path);
        void mark_streaming_write_completed ();
 
        void   mark_take (string);
@@ -104,16 +104,16 @@ class AudioFileSource : public AudioSource {
        
        /* constructor to be called for existing external-to-session files */
 
-       AudioFileSource (std::string path, Flag flags);
+       AudioFileSource (Session&, std::string path, Flag flags);
 
        /* constructor to be called for new in-session files */
 
-       AudioFileSource (std::string path, Flag flags,
+       AudioFileSource (Session&, std::string path, Flag flags,
                         SampleFormat samp_format, HeaderFormat hdr_format);
 
        /* constructor to be called for existing in-session files */
 
-       AudioFileSource (const XMLNode&);
+       AudioFileSource (Session&, const XMLNode&);
 
        int init (string idstr, bool must_exist);
 
index 0426208ba1c7300e6cb5f21a141ca8652d3e642d..6a52f1c16fa5be5046523cf650a221f049751c17 100644 (file)
@@ -111,6 +111,8 @@ class AudioPlaylist : public ARDOUR::Playlist
        bool region_changed (Change, boost::shared_ptr<Region>);
        void crossfade_changed (Change);
        void add_crossfade (Crossfade&);
+
+       void source_offset_changed (boost::shared_ptr<AudioRegion> region);
 };
 
 } /* namespace ARDOUR */
index 36c6256d50bd5c3296f2ca65c3446f0a5b220733..06115aa8b092180f9d4c3c157b190c763e00561d 100644 (file)
@@ -187,6 +187,7 @@ class AudioRegion : public Region
        void recompute_at_end ();
 
        void envelope_changed (Change);
+       void source_offset_changed ();
 
        void source_deleted (boost::shared_ptr<Source>);
        
index 45fe8e5c9f04e32add6d6a03abb57327719f6051..d598e424ac462beba97dd43eee3f42237d013d43 100644 (file)
@@ -47,8 +47,8 @@ const jack_nframes_t frames_per_peak = 256;
 class AudioSource : public Source
 {
   public:
-       AudioSource (string name);
-       AudioSource (const XMLNode&);
+       AudioSource (Session&, string name);
+       AudioSource (Session&, const XMLNode&);
        virtual ~AudioSource ();
 
        /* one could argue that this should belong to Source, but other data types
index a3b84289c1ceb6262a7c35052dd462bb33b1bc3c..22ab706f82bed73e946ac2532a2f0b6d57827b9f 100644 (file)
@@ -159,8 +159,6 @@ struct ControlEvent {
        XMLNode &get_state(void); 
        int set_state (const XMLNode &s);
 
-        PBD::ID id() { return _id; }
-
        void set_max_xval (double);
        double get_max_xval() const { return max_xval; }
 
@@ -189,7 +187,7 @@ struct ControlEvent {
         static sigc::signal<void, AutomationList*> AutomationListCreated;
 
   protected:
-        PBD::ID _id;
+
        struct State : public ARDOUR::StateManager::State {
            AutomationEventList events;
 
index fb2a3be47b79e639471691d26774405571e01ed1..fed84217e797801353c7ef0571e588c105b80fb7 100644 (file)
@@ -31,12 +31,12 @@ namespace ARDOUR {
 
 class DestructiveFileSource : public SndFileSource {
   public:
-       DestructiveFileSource (std::string path, SampleFormat samp_format, HeaderFormat hdr_format, jack_nframes_t rate,
+       DestructiveFileSource (Session&, std::string path, SampleFormat samp_format, HeaderFormat hdr_format, jack_nframes_t rate,
                               Flag flags = AudioFileSource::Flag (AudioFileSource::Writable));
 
-       DestructiveFileSource (std::string path, Flag flags);
+       DestructiveFileSource (Session&, std::string path, Flag flags);
 
-       DestructiveFileSource (const XMLNode&);
+       DestructiveFileSource (Session&, const XMLNode&);
        ~DestructiveFileSource ();
 
        jack_nframes_t last_capture_start_frame() const;
index 3c2154896cebbd717d460cea9c3279b647472e2a..08041d949f6543cf5a3ef0ef70aad287d09ea9b0 100644 (file)
@@ -92,7 +92,6 @@ class IO;
        bool destructive() const { return _flags & Destructive; }
        virtual void set_destructive (bool yn);
 
-       const PBD::ID& id()          const { return _id; }
        bool           hidden()      const { return _flags & Hidden; }
        bool           recordable()  const { return _flags & Recordable; }
        bool           reversed()    const { return _actual_speed < 0.0f; }
@@ -244,7 +243,6 @@ class IO;
        ARDOUR::Session&  _session;
        ARDOUR::IO*       _io;
        uint32_t          _n_channels;
-       PBD::ID           _id;
        Playlist*         _playlist;
 
        mutable gint             _record_enabled;
index 1248f60e0fed0760dd608c10281a269ed69a13b6..77f72f82d72cbbeb0f98a9b48e93c29340a30296 100644 (file)
@@ -253,8 +253,6 @@ public:
        void start_pan_touch (uint32_t which);
        void end_pan_touch (uint32_t which);
 
-       const PBD::ID& id() const { return _id; }
-
        void defer_pan_reset ();
        void allow_pan_reset ();
 
@@ -282,7 +280,6 @@ public:
        string              _name;
        Connection*         _input_connection;
        Connection*         _output_connection;
-       PBD::ID             _id;
        bool                 no_panner_reset;
        XMLNode*             deferred_state;
        DataType        _default_type;
index 1052b74bd41072d4bc6d525fcbc79413e3ab870e..96fb1b1bcfee319fa0f2c074947944a4740cfd84 100644 (file)
@@ -121,10 +121,7 @@ class Location : public sigc::trackable, public PBD::StatefulDestructible
        XMLNode& get_state (void);
        int set_state (const XMLNode&);
 
-        PBD::ID id() { return _id; }
-
   private:
-        PBD::ID _id;
        string        _name;
        jack_nframes_t     _start;
        jack_nframes_t     _end;
@@ -150,7 +147,6 @@ class Locations : public StateManager, public PBD::StatefulDestructible
 
        XMLNode& get_state (void);
        int set_state (const XMLNode&);
-        PBD::ID id() { return _id; }
         Location *get_location_by_id(PBD::ID);
 
        Location* auto_loop_location () const;
@@ -204,8 +200,6 @@ class Locations : public StateManager, public PBD::StatefulDestructible
 
        Change   restore_state (StateManager::State&);
        StateManager::State* state_factory (std::string why) const;
-
-        PBD::ID _id;
 };
 
 } // namespace ARDOUR
index 36c3ae34926391f7ddcce52c9599873d7fe415df..e3911dac0be66cc14f2c0fcb62a1d52bcd25632a 100644 (file)
@@ -78,7 +78,6 @@ class Playlist : public StateManager, public PBD::StatefulDestructible {
        EditMode get_edit_mode() const { return _edit_mode; }
        void set_edit_mode (EditMode);
 
-        PBD::ID id() { return _id; }
        /* Editing operations */
 
        void add_region (boost::shared_ptr<Region>, jack_nframes_t position, float times = 1, bool with_save = true);
@@ -275,8 +274,6 @@ class Playlist : public StateManager, public PBD::StatefulDestructible {
        void unset_freeze_child (Playlist*);
 
        void timestamp_layer_op (boost::shared_ptr<Region>);
-
-        PBD::ID _id;
 };
 
 } /* namespace ARDOUR */
index 9bdf3357cf2650a077dc6d02b0fb531a59772203..2ff7d0bdb2b1a243aeab0cb33a637e88708b12e8 100644 (file)
@@ -35,7 +35,6 @@ class XMLNode;
 namespace ARDOUR {
 
 class Playlist;
-class Source;
 
 enum RegionEditState {
        EditChangesNothing = 0,
@@ -95,8 +94,6 @@ class Region : public PBD::StatefulDestructible, public StateManager, public boo
 
        virtual ~Region();
 
-       const PBD::ID& id() const { return _id; }
-
        /* Note: changing the name of a Region does not constitute an edit */
 
        string name() const { return _name; }
@@ -243,7 +240,6 @@ class Region : public PBD::StatefulDestructible, public StateManager, public boo
        mutable RegionEditState _first_edit;
        int                     _frozen;
        Glib::Mutex             lock;
-       PBD::ID                 _id;
        ARDOUR::Playlist*       _playlist;
        mutable uint32_t        _read_data_count; // modified in read()
        Change                   pending_changed;
index 25f06c03b4daceb5207fd260fa3acd4a9782e08c..8b4123d4f0edd1e0698f283d5ee9d5caf8defa8a 100644 (file)
@@ -255,12 +255,13 @@ class Session : public sigc::trackable, public PBD::StatefulDestructible
        bool dirty() const { return _state_of_the_state & Dirty; }
        sigc::signal<void> DirtyChanged;
 
-       std::string sound_dir () const;
-       std::string tape_dir () const;
+       std::string sound_dir (bool with_path = true) const;
        std::string peak_dir () const;
        std::string dead_sound_dir () const;
        std::string automation_dir () const;
 
+       string peak_path_from_audio_path (string) const;
+
        static string suffixed_search_path (std::string suffix, bool data);
        static string control_protocol_path ();
        static string template_path ();
@@ -268,7 +269,6 @@ class Session : public sigc::trackable, public PBD::StatefulDestructible
        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);
        string audio_path_from_name (string, uint32_t nchans, uint32_t chan, bool destructive);
 
        void process (jack_nframes_t nframes);
@@ -1696,9 +1696,10 @@ class Session : public sigc::trackable, public PBD::StatefulDestructible
        uint32_t _total_free_4k_blocks;
        Glib::Mutex space_lock;
 
+       static const char* old_sound_dir_name;
        static const char* sound_dir_name;
-       static const char* tape_dir_name;
        static const char* dead_sound_dir_name;
+       static const char* interchange_dir_name;
        static const char* peak_dir_name;
 
        string discover_best_sound_dir (bool destructive = false);
index ab3e61eb2963f470d072f3cce83101d2b7fd7326..cb6bd2e92004dcbffd3d99b4928b92a4044958e6 100644 (file)
@@ -31,11 +31,11 @@ class SndFileSource : public AudioFileSource {
   public:
        /* constructor to be called for existing external-to-session files */
 
-       SndFileSource (std::string path, Flag flags);
+       SndFileSource (Session&, std::string path, Flag flags);
 
        /* constructor to be called for new in-session files */
 
-       SndFileSource (std::string path, SampleFormat samp_format, HeaderFormat hdr_format, jack_nframes_t rate, 
+       SndFileSource (Session&, std::string path, SampleFormat samp_format, HeaderFormat hdr_format, jack_nframes_t rate, 
                       Flag flags = AudioFileSource::Flag (AudioFileSource::Writable|
                                                           AudioFileSource::Removable|
                                                           AudioFileSource::RemovableIfEmpty|
@@ -43,7 +43,7 @@ class SndFileSource : public AudioFileSource {
                       
        /* constructor to be called for existing in-session files */
        
-       SndFileSource (const XMLNode&);
+       SndFileSource (Session&, const XMLNode&);
 
        ~SndFileSource ();
 
index 28ccd682724727375f3825522df74fe7c6a4975a..40594f744b22f9435333101cb6048fd8141541c9 100644 (file)
 
 namespace ARDOUR {
 
+class Session;
+
 class Source : public PBD::StatefulDestructible, public sigc::trackable
 {
   public:
-       Source (std::string name);
-       Source (const XMLNode&);
+       Source (Session&, std::string name);
+       Source (Session&, const XMLNode&);
        virtual ~Source ();
 
        std::string name() const { return _name; }
        int set_name (std::string str, bool destructive);
 
-       const PBD::ID&  id() const   { return _id; }
-
        time_t timestamp() const { return _timestamp; }
        void stamp (time_t when) { _timestamp = when; }
 
@@ -51,11 +51,11 @@ class Source : public PBD::StatefulDestructible, public sigc::trackable
 
 
   protected:
+       Session&          _session;
        string            _name;
        time_t            _timestamp;
 
   private:
-       PBD::ID _id;
 };
 
 }
index 92ed0415c8ca2bed392970759441d30bc322e85b..9b2a7d98f059421b630f867f386140cfbbed5158 100644 (file)
@@ -13,15 +13,17 @@ class XMLNode;
 
 namespace ARDOUR {
 
+class Session;
+
 class SourceFactory {
   public:
        static sigc::signal<void,boost::shared_ptr<Source> > SourceCreated;
 
-       static boost::shared_ptr<Source> create (const XMLNode& node);
+       static boost::shared_ptr<Source> create (Session&, const XMLNode& node);
 
        // MIDI sources will have to be hacked in here somehow
-       static boost::shared_ptr<Source> createReadable (std::string idstr, AudioFileSource::Flag flags, bool announce = true);
-       static boost::shared_ptr<Source> createWritable (std::string name, bool destructive, jack_nframes_t rate, bool announce = true);
+       static boost::shared_ptr<Source> createReadable (Session&, std::string idstr, AudioFileSource::Flag flags, bool announce = true);
+       static boost::shared_ptr<Source> createWritable (Session&, std::string name, bool destructive, jack_nframes_t rate, bool announce = true);
 };
 
 }
index 9111aeba681428d88477deac06ef6fa85f6d57a8..0b37579ecb1e0d45e7bbc4b7a8d4ce6fed19ad57 100644 (file)
@@ -242,7 +242,6 @@ class TempoMap : public StateManager, public PBD::StatefulDestructible
 
        XMLNode& get_state (void);
        int set_state (const XMLNode&);
-        PBD::ID id() { return _id; }
 
        void dump (std::ostream&) const;
        void clear ();
@@ -320,8 +319,6 @@ class TempoMap : public StateManager, public PBD::StatefulDestructible
 
        void save_state (std::string why);
 
-        PBD::ID _id;
-
 };
 
 }; /* namespace ARDOUR */
index 56f051890a3cf2ea83f726d9eec1597a1af05e72..037ffdb30a6e5c910181df559f66f892aa2d1678 100644 (file)
@@ -1939,7 +1939,7 @@ AudioDiskstream::use_new_write_source (uint32_t n)
        
        if (chan.write_source) {
 
-               if (AudioFileSource::is_empty (chan.write_source->path())) {
+               if (AudioFileSource::is_empty (_session, chan.write_source->path())) {
                        chan.write_source->mark_for_remove ();
                        chan.write_source.reset ();
                } else {
@@ -2176,7 +2176,7 @@ AudioDiskstream::use_pending_capture_data (XMLNode& node)
                        }
 
                        try {
-                               fs = boost::dynamic_pointer_cast<AudioFileSource> (SourceFactory::createWritable (prop->value(), false, _session.frame_rate()));
+                               fs = boost::dynamic_pointer_cast<AudioFileSource> (SourceFactory::createWritable (_session, prop->value(), false, _session.frame_rate()));
                        }
 
                        catch (failed_constructor& err) {
index d9902c8b599e8fe034c964d962eb74c74595d886..66db77336d4e3986e287d6d611fdc1f8e04f62ff 100644 (file)
@@ -897,3 +897,4 @@ AudioPlaylist::crossfades_at (jack_nframes_t frame, Crossfades& clist)
                } 
        }
 }
+
index 66bf3ed561e4cc5fb410db94964bb55de991302a..ad473e9d640ba17e52c68d4cd7d8be406ae9d814 100644 (file)
@@ -63,8 +63,8 @@ char   AudioFileSource::bwf_country_code[3] = "US";
 char   AudioFileSource::bwf_organization_code[4] = "LAS";
 char   AudioFileSource::bwf_serial_number[13] = "000000000000";
 
-AudioFileSource::AudioFileSource (string idstr, Flag flags)
-       : AudioSource (idstr), _flags (flags)
+AudioFileSource::AudioFileSource (Session& s, string idstr, Flag flags)
+       : AudioSource (s, idstr), _flags (flags)
 {
        /* constructor used for existing external to session files. file must exist already */
 
@@ -74,8 +74,8 @@ AudioFileSource::AudioFileSource (string idstr, Flag flags)
 
 }
 
-AudioFileSource::AudioFileSource (std::string path, Flag flags, SampleFormat samp_format, HeaderFormat hdr_format)
-       : AudioSource (path), _flags (flags)
+AudioFileSource::AudioFileSource (Session& s, std::string path, Flag flags, SampleFormat samp_format, HeaderFormat hdr_format)
+       : AudioSource (s, path), _flags (flags)
 {
        /* constructor used for new internal-to-session files. file cannot exist */
 
@@ -84,8 +84,8 @@ AudioFileSource::AudioFileSource (std::string path, Flag flags, SampleFormat sam
        }
 }
 
-AudioFileSource::AudioFileSource (const XMLNode& node)
-       : AudioSource (node), _flags (Flag (Writable|CanRename))
+AudioFileSource::AudioFileSource (Session& s, const XMLNode& node)
+       : AudioSource (s, node), _flags (Flag (Writable|CanRename))
 {
        /* constructor used for existing internal-to-session files. file must exist */
 
@@ -109,7 +109,7 @@ AudioFileSource::~AudioFileSource ()
 bool
 AudioFileSource::removable () const
 {
-       return (_flags & Removable) && ((_flags & RemoveAtDestroy) || ((_flags & RemovableIfEmpty) && is_empty (_path)));
+       return (_flags & Removable) && ((_flags & RemoveAtDestroy) || ((_flags & RemovableIfEmpty) && is_empty (_session, _path)));
 }
 
 int
@@ -135,7 +135,7 @@ AudioFileSource::init (string pathstr, bool must_exist)
 string
 AudioFileSource::peak_path (string audio_path)
 {
-       return Session::peak_path_from_audio_path (audio_path);
+       return _session.peak_path_from_audio_path (audio_path);
 }
 
 string
@@ -552,10 +552,10 @@ AudioFileSource::set_name (string newname, bool destructive)
 }
 
 bool
-AudioFileSource::is_empty (string path)
+AudioFileSource::is_empty (Session& s, string path)
 {
        bool ret = false;
-       boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource> (SourceFactory::createReadable (path, NoPeakFile, false));
+       boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource> (SourceFactory::createReadable (s, path, NoPeakFile, false));
 
        if (afs) {
                ret = (afs->length() == 0);
index dab32cc3303c716314e75964c950f32b8f0d1785..a7117cf9dc1646ad87f61408dc3f2a35f8d8d7b1 100644 (file)
@@ -50,7 +50,7 @@ AudioFilter::make_new_sources (boost::shared_ptr<AudioRegion> region, SourceList
                }
 
                try {
-                       nsrcs.push_back (boost::dynamic_pointer_cast<AudioSource> (SourceFactory::createWritable (path, false, session.frame_rate())));
+                       nsrcs.push_back (boost::dynamic_pointer_cast<AudioSource> (SourceFactory::createWritable (session, path, false, session.frame_rate())));
                } 
 
                catch (failed_constructor& err) {
index 4cd45c5d99619684b5f268ebef0dbbfa86258710..f5272821d10dac2a33b58cb82a9512b00d653bd0 100644 (file)
@@ -38,7 +38,7 @@
 #include <ardour/dB.h>
 #include <ardour/playlist.h>
 #include <ardour/audiofilter.h>
-#include <ardour/audiosource.h>
+#include <ardour/audiofilesource.h>
 
 #include "i18n.h"
 #include <locale.h>
@@ -76,6 +76,11 @@ AudioRegion::AudioRegion (boost::shared_ptr<AudioSource> src, jack_nframes_t sta
        master_sources.push_back (src);
        src->GoingAway.connect (bind (mem_fun (*this, &AudioRegion::source_deleted), src));
 
+       boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource> (src);
+       if (afs) {
+               afs->HeaderPositionOffsetChanged.connect (mem_fun (*this, &AudioRegion::source_offset_changed));
+       }
+
        _scale_amplitude = 1.0;
 
        set_default_fades ();
@@ -98,6 +103,11 @@ AudioRegion::AudioRegion (boost::shared_ptr<AudioSource> src, jack_nframes_t sta
        master_sources.push_back (src);
        src->GoingAway.connect (bind (mem_fun (*this, &AudioRegion::source_deleted), src));
 
+       boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource> (src);
+       if (afs) {
+               afs->HeaderPositionOffsetChanged.connect (mem_fun (*this, &AudioRegion::source_offset_changed));
+       }
+
        _scale_amplitude = 1.0;
 
        set_default_fades ();
@@ -119,6 +129,11 @@ AudioRegion::AudioRegion (SourceList& srcs, jack_nframes_t start, jack_nframes_t
                sources.push_back (*i);
                master_sources.push_back (*i);
                (*i)->GoingAway.connect (bind (mem_fun (*this, &AudioRegion::source_deleted), (*i)));
+               
+               boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource> ((*i));
+               if (afs) {
+                       afs->HeaderPositionOffsetChanged.connect (mem_fun (*this, &AudioRegion::source_offset_changed));
+               }
        }
 
        _scale_amplitude = 1.0;
@@ -144,7 +159,17 @@ AudioRegion::AudioRegion (boost::shared_ptr<const AudioRegion> other, jack_nfram
        for (SourceList::const_iterator i= other->sources.begin(); i != other->sources.end(); ++i) {
                sources.push_back (*i);
                (*i)->GoingAway.connect (bind (mem_fun (*this, &AudioRegion::source_deleted), *i));
-               unique_srcs.insert (*i);
+
+               pair<set<boost::shared_ptr<AudioSource> >::iterator,bool> result;
+
+               result = unique_srcs.insert (*i);
+
+               if (result.second) {
+                       boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource> (*i);
+                       if (afs) {
+                               afs->HeaderPositionOffsetChanged.connect (mem_fun (*this, &AudioRegion::source_offset_changed));
+                       }
+               }
        }
 
        for (SourceList::const_iterator i = other->master_sources.begin(); i != other->master_sources.end(); ++i) {
@@ -199,7 +224,16 @@ AudioRegion::AudioRegion (boost::shared_ptr<const AudioRegion> other)
        for (SourceList::const_iterator i = other->sources.begin(); i != other->sources.end(); ++i) {
                sources.push_back (*i);
                (*i)->GoingAway.connect (bind (mem_fun (*this, &AudioRegion::source_deleted), *i));
-               unique_srcs.insert (*i);
+               pair<set<boost::shared_ptr<AudioSource> >::iterator,bool> result;
+
+               result = unique_srcs.insert (*i);
+
+               if (result.second) {
+                       boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource> (*i);
+                       if (afs) {
+                               afs->HeaderPositionOffsetChanged.connect (mem_fun (*this, &AudioRegion::source_offset_changed));
+                       }
+               }
        }
 
        for (SourceList::const_iterator i = other->master_sources.begin(); i != other->master_sources.end(); ++i) {
@@ -230,6 +264,11 @@ AudioRegion::AudioRegion (boost::shared_ptr<AudioSource> src, const XMLNode& nod
        master_sources.push_back (src);
        src->GoingAway.connect (bind (mem_fun (*this, &AudioRegion::source_deleted), src));
 
+       boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource> (src);
+       if (afs) {
+               afs->HeaderPositionOffsetChanged.connect (mem_fun (*this, &AudioRegion::source_offset_changed));
+       }
+
        set_default_fades ();
 
        if (set_state (node)) {
@@ -252,7 +291,16 @@ AudioRegion::AudioRegion (SourceList& srcs, const XMLNode& node)
        for (SourceList::iterator i=srcs.begin(); i != srcs.end(); ++i) {
                sources.push_back (*i);
                (*i)->GoingAway.connect (bind (mem_fun (*this, &AudioRegion::source_deleted), *i));
-               unique_srcs.insert (*i);
+               pair<set<boost::shared_ptr<AudioSource> >::iterator,bool> result;
+
+               result = unique_srcs.insert (*i);
+
+               if (result.second) {
+                       boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource> (*i);
+                       if (afs) {
+                               afs->HeaderPositionOffsetChanged.connect (mem_fun (*this, &AudioRegion::source_offset_changed));
+                       }
+               }
        }
 
        for (SourceList::iterator i = srcs.begin(); i != srcs.end(); ++i) {
@@ -1324,6 +1372,12 @@ AudioRegion::speed_mismatch (float sr) const
        return fsr != sr;
 }
 
+void
+AudioRegion::source_offset_changed ()
+{
+       set_position (source()->natural_position() + start(), this);
+}
+
 extern "C" {
 
        int region_read_peaks_from_c (void *arg, uint32_t npeaks, uint32_t start, uint32_t cnt, intptr_t data, uint32_t n_chan, double samples_per_unit) 
index e3a064bb093da3a924b8a9223d142e0f0443d662..a8a7af6f9cc8a25e96637c21084d8ab5528c858d 100644 (file)
@@ -50,8 +50,8 @@ int                          AudioSource::peak_request_pipe[2];
 bool AudioSource::_build_missing_peakfiles = false;
 bool AudioSource::_build_peakfiles = false;
 
-AudioSource::AudioSource (string name)
-       : Source (name)
+AudioSource::AudioSource (Session& s, string name)
+       : Source (s, name)
 {
        if (pending_peak_sources_lock == 0) {
                pending_peak_sources_lock = new Glib::Mutex;
@@ -63,8 +63,8 @@ AudioSource::AudioSource (string name)
        _write_data_count = 0;
 }
 
-AudioSource::AudioSource (const XMLNode& node) 
-       : Source (node)
+AudioSource::AudioSource (Session& s, const XMLNode& node) 
+       : Source (s, node)
 {
        if (pending_peak_sources_lock == 0) {
                pending_peak_sources_lock = new Glib::Mutex;
index bf16b40005c7e7247f15d3ca1e3a0a42791ee893..1e57d88d709dd4cdcc57ea08ad85a33aab693ea8 100644 (file)
@@ -68,21 +68,21 @@ gain_t* DestructiveFileSource::out_coefficient = 0;
 gain_t* DestructiveFileSource::in_coefficient = 0;
 jack_nframes_t DestructiveFileSource::xfade_frames = 64;
 
-DestructiveFileSource::DestructiveFileSource (string path, SampleFormat samp_format, HeaderFormat hdr_format, jack_nframes_t rate, Flag flags)
-       : SndFileSource (path, samp_format, hdr_format, rate, flags)
+DestructiveFileSource::DestructiveFileSource (Session& s, string path, SampleFormat samp_format, HeaderFormat hdr_format, jack_nframes_t rate, Flag flags)
+       : SndFileSource (s, path, samp_format, hdr_format, rate, flags)
 {
        init ();
 }
 
 
-DestructiveFileSource::DestructiveFileSource (string path, Flag flags)
-       : SndFileSource (path, flags)
+DestructiveFileSource::DestructiveFileSource (Session& s, string path, Flag flags)
+       : SndFileSource (s, path, flags)
 {
        init ();
 }
 
-DestructiveFileSource::DestructiveFileSource (const XMLNode& node)
-       : SndFileSource (node)
+DestructiveFileSource::DestructiveFileSource (Session& s, const XMLNode& node)
+       : SndFileSource (s, node)
 {
        init ();
 }
index 1342c0147baecacaa37add2550da15dc13150839..59a12a29170e76c5dba2aa0a3666e4f52a046bd6 100644 (file)
@@ -372,7 +372,9 @@ ARDOUR::get_user_ardour_path ()
 
        /* create it if necessary */
 
-       mkdir (path.c_str (), 0755);
+       if (g_mkdir_with_parents (path.c_str (), 0755)) {
+               throw exception ();
+       }
 
        return path;
 }
index 2fd38bf0a6d335afd27314a2c0cc45f5ec13498c..5b9740720745705646cc7aaad28b6d5e2996e1c2 100644 (file)
@@ -138,7 +138,7 @@ Session::import_audiofile (import_status& status)
                } while ( !goodfile);
 
                try { 
-                       newfiles[n] = boost::dynamic_pointer_cast<AudioFileSource> (SourceFactory::createWritable (buf, false, frame_rate()));
+                       newfiles[n] = boost::dynamic_pointer_cast<AudioFileSource> (SourceFactory::createWritable (*this, buf, false, frame_rate()));
                }
 
                catch (failed_constructor& err) {
index 242d94c2d77f91a456b3082b4a7efe7fb088aa9c..a6a976705c4408a5645401367ffe69440d980d09 100644 (file)
@@ -22,6 +22,7 @@
 #include <algorithm>
 #include <unistd.h>
 #include <locale.h>
+#include <errno.h>
 
 #include <sigc++/bind.h>
 
@@ -2426,8 +2427,8 @@ IO::load_automation (const string& path)
                fullpath += path;
                in.open (fullpath.c_str());
                if (!in) {
-                               error << string_compose(_("%1: cannot open automation event file \"%2\""), _name, fullpath) << endmsg;
-                               return -1;
+                       error << string_compose(_("%1: cannot open automation event file \"%2\" (%2)"), _name, fullpath, strerror (errno)) << endmsg;
+                       return -1;
                }
        }
 
index 30b28c6abee73a937e76d9eec31988ab66f3d5c9..6b3ea6f2200ddc6c6bae7275089aa595b4080c8b 100644 (file)
@@ -81,13 +81,18 @@ Location::set_start (jack_nframes_t s)
 {
        if (is_mark()) {
                if (_start != s) {
+
                        _start = s;
                        _end = s;
+
                        start_changed(this); /* EMIT SIGNAL */
+
                        if ( is_start() ) {
+
                                Session::StartTimeChanged (); /* EMIT SIGNAL */
                                AudioFileSource::set_header_position_offset ( s );
                        }
+
                        if ( is_end() ) {
                                Session::EndTimeChanged (); /* EMIT SIGNAL */
                        }
index f866b5ae1098c863176687cf20c2b1391fc0347f..c93deb8df948ae57c3a03de42f05f06196897978 100644 (file)
@@ -1080,7 +1080,7 @@ Panner::save () const
        ofstream out (automation_path.c_str());
        
        if (!out) {
-               error << string_compose (_("cannot open pan automation file \"%1\" for saving (%s)"), automation_path, strerror (errno))
+               error << string_compose (_("cannot open pan automation file \"%1\" for saving (%2)"), automation_path, strerror (errno))
                      << endmsg;
                return -1;
        }
index 8d200b0ee413b30a273de56d59d90e81335bd72e..9a82c3bbabef3e22ca07fc4edb545a7c22a14ebf 100644 (file)
@@ -224,13 +224,13 @@ Plugin::save_preset (string name, string domain)
        free(lrdf_add_preset(source.c_str(), name.c_str(), unique_id(), &defaults));
 
        string path = string_compose("%1/.%2", envvar, domain);
-       if (mkdir(path.c_str(), 0775) && errno != EEXIST) {
+       if (g_mkdir_with_parents (path.c_str(), 0775)) {
                warning << string_compose(_("Could not create %1.  Preset not saved. (%2)"), path, strerror(errno)) << endmsg;
                return false;
        }
        
        path += "/rdf";
-       if (mkdir(path.c_str(), 0775) && errno != EEXIST) {
+       if (g_mkdir_with_parents (path.c_str(), 0775)) {
                warning << string_compose(_("Could not create %1.  Preset not saved. (%2)"), path, strerror(errno)) << endmsg;
                return false;
        }
index b9888dfd3058d0d10b96ff6c02b78253f01ba035..bafb43a57c8740d38521e93555c991a2a6303f49 100644 (file)
@@ -81,10 +81,11 @@ using boost::shared_ptr;
 const char* Session::_template_suffix = X_(".template");
 const char* Session::_statefile_suffix = X_(".ardour");
 const char* Session::_pending_suffix = X_(".pending");
-const char* Session::sound_dir_name = X_("sounds");
-const char* Session::tape_dir_name = X_("tapes");
+const char* Session::old_sound_dir_name = X_("sounds");
+const char* Session::sound_dir_name = X_("audiofiles");
 const char* Session::peak_dir_name = X_("peaks");
 const char* Session::dead_sound_dir_name = X_("dead_sounds");
+const char* Session::interchange_dir_name = X_("interchange");
 
 Session::compute_peak_t                                Session::compute_peak                   = 0;
 Session::apply_gain_to_buffer_t                Session::apply_gain_to_buffer   = 0;
@@ -2799,17 +2800,11 @@ Session::source_by_id (const PBD::ID& id)
 }
 
 string
-Session::peak_path_from_audio_path (string audio_path)
+Session::peak_path_from_audio_path (string audio_path) const
 {
-       /* XXX hardly bombproof! fix me */
-
        string res;
 
-       res = Glib::path_get_dirname (audio_path);
-       res = Glib::path_get_dirname (res);
-       res += '/';
-       res += peak_dir_name;
-       res += '/';
+       res = peak_dir ();
        res += PBD::basename_nosuffix (audio_path);
        res += ".peak";
 
@@ -2955,11 +2950,7 @@ Session::audio_path_from_name (string name, uint32_t nchan, uint32_t chan, bool
 
                        spath = (*i).path;
 
-                       if (destructive) {
-                               spath += tape_dir_name;
-                       } else {
-                               spath += sound_dir_name;
-                       }
+                       spath += sound_dir_name;
 
                        if (destructive) {
                                if (nchan < 2) {
@@ -3016,11 +3007,7 @@ Session::audio_path_from_name (string name, uint32_t nchan, uint32_t chan, bool
 
        string foo = buf;
 
-       if (destructive) {
-               spath = tape_dir ();
-       } else {
-               spath = discover_best_sound_dir ();
-       }
+       spath = discover_best_sound_dir ();
 
        string::size_type pos = foo.find_last_of ('/');
        
@@ -3037,7 +3024,7 @@ boost::shared_ptr<AudioFileSource>
 Session::create_audio_source_for_session (AudioDiskstream& ds, uint32_t chan, bool destructive)
 {
        string spath = audio_path_from_name (ds.name(), ds.n_channels(), chan, destructive);
-       return boost::dynamic_pointer_cast<AudioFileSource> (SourceFactory::createWritable (spath, destructive, frame_rate()));
+       return boost::dynamic_pointer_cast<AudioFileSource> (SourceFactory::createWritable (*this, spath, destructive, frame_rate()));
 }
 
 /* Playlist management */
@@ -3206,7 +3193,7 @@ Session::remove_empty_sounds ()
        
        for (vector<string *>::iterator i = possible_audiofiles->begin(); i != possible_audiofiles->end(); ++i) {
 
-               if (AudioFileSource::is_empty (*(*i))) {
+               if (AudioFileSource::is_empty (*this, *(*i))) {
 
                        unlink ((*i)->c_str());
                        
@@ -3386,7 +3373,7 @@ jack_nframes_t
 Session::available_capture_duration ()
 {
        const double scale = 4096.0 / sizeof (Sample);
-       
+
        if (_total_free_4k_blocks * scale > (double) max_frames) {
                return max_frames;
        }
@@ -3713,7 +3700,7 @@ Session::write_one_audio_track (AudioTrack& track, jack_nframes_t start, jack_nf
                }
                
                try {
-                       fsource = boost::dynamic_pointer_cast<AudioFileSource> (SourceFactory::createWritable (buf, false, frame_rate()));
+                       fsource = boost::dynamic_pointer_cast<AudioFileSource> (SourceFactory::createWritable (*this, buf, false, frame_rate()));
                }
                
                catch (failed_constructor& err) {
index 9f1c6baf4ad0e941ddd61ce1c12aaf09ddcdac23..18c5721f7ab54c5bb61283e18d956efdc3874409 100644 (file)
@@ -364,7 +364,6 @@ Session::second_stage_init (bool new_session)
                _end_location_is_free = false;
        }
        
-        restore_history(_current_snapshot_name);
        return 0;
 }
 
@@ -429,16 +428,7 @@ Session::setup_raid_path (string 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;
+               fspath += sound_dir (false);
                
                AudioFileSource::set_search_path (fspath);
 
@@ -459,16 +449,7 @@ Session::setup_raid_path (string path)
                if (fspath[fspath.length()-1] != '/') {
                        fspath += '/';
                }
-               fspath += sound_dir_name;
-               fspath += ':';
-
-               /* add tape dir to file search path */
-
-               fspath += sp.path;
-               if (fspath[fspath.length()-1] != '/') {
-                       fspath += '/';
-               }
-               fspath += tape_dir_name;
+               fspath += sound_dir (false);
                fspath += ':';
 
                remaining = remaining.substr (colon+1);
@@ -484,15 +465,9 @@ Session::setup_raid_path (string path)
                if (fspath[fspath.length()-1] != '/') {
                        fspath += '/';
                }
-               fspath += sound_dir_name;
+               fspath += sound_dir (false);
                fspath += ':';
 
-               fspath += sp.path;
-               if (fspath[fspath.length()-1] != '/') {
-                       fspath += '/';
-               }
-               fspath += tape_dir_name;
-
                session_dirs.push_back (sp);
        }
 
@@ -509,61 +484,40 @@ int
 Session::create (bool& new_session, string* mix_template, jack_nframes_t initial_length)
 {
        string dir;
+
+       new_session = !g_file_test (_path.c_str(), GFileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR));
        
-       if (mkdir (_path.c_str(), 0755) < 0) {
-               if (errno == EEXIST) {
-                       new_session = false;
-               } else {
-                       error << string_compose(_("Session: cannot create session dir \"%1\" (%2)"), _path, strerror (errno)) << endmsg;
-                       return -1;
-               }
-       } else {
-               new_session = true;
+       if (g_mkdir_with_parents (_path.c_str(), 0755) < 0) {
+               error << string_compose(_("Session: cannot create session dir \"%1\" (%2)"), _path, strerror (errno)) << endmsg;
+               return -1;
        }
 
        dir = peak_dir ();
 
-       if (mkdir (dir.c_str(), 0755) < 0) {
-               if (errno != EEXIST) {
-                       error << string_compose(_("Session: cannot create session peakfile dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
-                       return -1;
-               }
+       if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
+               error << string_compose(_("Session: cannot create session peakfile dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
+               return -1;
        }
 
        dir = sound_dir ();
 
-       if (mkdir (dir.c_str(), 0755) < 0) {
-               if (errno != EEXIST) {
-                       error << string_compose(_("Session: cannot create session sounds dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
-                       return -1;
-               }
-       }
-
-       dir = tape_dir ();
-
-       if (mkdir (dir.c_str(), 0755) < 0) {
-               if (errno != EEXIST) {
-                       error << string_compose(_("Session: cannot create session tape dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
-                       return -1;
-               }
+       if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
+               error << string_compose(_("Session: cannot create session sounds dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
+               return -1;
        }
 
        dir = dead_sound_dir ();
 
-       if (mkdir (dir.c_str(), 0755) < 0) {
-               if (errno != EEXIST) {
-                       error << string_compose(_("Session: cannot create session dead sounds dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
-                       return -1;
-               }
+       if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
+               error << string_compose(_("Session: cannot create session dead sounds dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
+               return -1;
        }
 
        dir = automation_dir ();
 
-       if (mkdir (dir.c_str(), 0755) < 0) {
-               if (errno != EEXIST) {
-                       error << string_compose(_("Session: cannot create session automation dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
-                       return -1;
-               }
+       if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
+               error << string_compose(_("Session: cannot create session automation dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
+               return -1;
        }
 
        
@@ -709,6 +663,8 @@ Session::save_state (string snapshot_name, bool pending)
 
        }
 
+       cerr << "actually writing state\n";
+
        if (!tree.write (xml_path)) {
                error << string_compose (_("state could not be saved to %1"), xml_path) << endmsg;
 
@@ -1934,7 +1890,7 @@ Session::XMLSourceFactory (const XMLNode& node)
        }
 
        try {
-               return SourceFactory::create (node);
+               return SourceFactory::create (*this, node);
        }
        
        catch (failed_constructor& err) {
@@ -1959,7 +1915,7 @@ Session::save_template (string template_name)
        if ((dp = opendir (dir.c_str()))) {
                closedir (dp);
        } else {
-               if (mkdir (dir.c_str(), S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)<0) {
+               if (g_mkdir_with_parents (dir.c_str(), S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)) {
                        error << string_compose(_("Could not create mix templates directory \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
                        return -1;
                }
@@ -2039,11 +1995,9 @@ Session::ensure_sound_dir (string path, string& result)
 
        /* Ensure that the parent directory exists */
        
-       if (mkdir (path.c_str(), 0775)) {
-               if (errno != EEXIST) {
-                       error << string_compose(_("cannot create session directory \"%1\"; ignored"), path) << endmsg;
-                       return -1;
-               }
+       if (g_mkdir_with_parents (path.c_str(), 0775)) {
+               error << string_compose(_("cannot create session directory \"%1\"; ignored"), path) << endmsg;
+               return -1;
        }
        
        /* Ensure that the sounds directory exists */
@@ -2052,33 +2006,27 @@ Session::ensure_sound_dir (string path, string& result)
        result += '/';
        result += sound_dir_name;
        
-       if (mkdir (result.c_str(), 0775)) {
-               if (errno != EEXIST) {
-                       error << string_compose(_("cannot create sounds directory \"%1\"; ignored"), result) << endmsg;
-                       return -1;
-               }
+       if (g_mkdir_with_parents (result.c_str(), 0775)) {
+               error << string_compose(_("cannot create sounds directory \"%1\"; ignored"), result) << endmsg;
+               return -1;
        }
 
        dead = path;
        dead += '/';
        dead += dead_sound_dir_name;
        
-       if (mkdir (dead.c_str(), 0775)) {
-               if (errno != EEXIST) {
-                       error << string_compose(_("cannot create dead sounds directory \"%1\"; ignored"), dead) << endmsg;
-                       return -1;
-               }
+       if (g_mkdir_with_parents (dead.c_str(), 0775)) {
+               error << string_compose(_("cannot create dead sounds directory \"%1\"; ignored"), dead) << endmsg;
+               return -1;
        }
 
        peak = path;
        peak += '/';
        peak += peak_dir_name;
        
-       if (mkdir (peak.c_str(), 0775)) {
-               if (errno != EEXIST) {
-                       error << string_compose(_("cannot create peak file directory \"%1\"; ignored"), peak) << endmsg;
-                       return -1;
-               }
+       if (g_mkdir_with_parents (peak.c_str(), 0775)) {
+               error << string_compose(_("cannot create peak file directory \"%1\"; ignored"), peak) << endmsg;
+               return -1;
        }
        
        /* callers expect this to be terminated ... */
@@ -2093,12 +2041,6 @@ Session::discover_best_sound_dir (bool destructive)
        vector<space_and_path>::iterator i;
        string result;
 
-       /* destructive files all go into the same place */
-
-       if (destructive) {
-               return tape_dir();
-       }
-
        /* handle common case without system calls */
 
        if (session_dirs.size() == 1) {
@@ -2304,20 +2246,37 @@ Session::dead_sound_dir () const
 }
 
 string
-Session::sound_dir () const
+Session::sound_dir (bool with_path) const
 {
-       string res = _path;
+       /* support old session structure */
+
+       struct stat statbuf;
+       string old;
+
+       if (with_path) {
+               old = _path;
+       }
+
+       old += sound_dir_name;
+       old += '/';
+
+       if (stat (old.c_str(), &statbuf) == 0) {
+               return old;
+       }
+
+       string res;
+
+       if (with_path) {
+               res = _path;
+       }
+
+       res += interchange_dir_name;
+       res += '/';
+       res += legalize_for_path (_name);
+       res += '/';
        res += sound_dir_name;
        res += '/';
-       return res;
-}
 
-string
-Session::tape_dir () const
-{
-       string res = _path;
-       res += tape_dir_name;
-       res += '/';
        return res;
 }
 
@@ -3314,8 +3273,7 @@ Session::save_history (string snapshot_name)
     XMLTree tree;
     string xml_path;
     string bak_path;
-
-
+    
     tree.set_root (&history.get_state());
 
     if (snapshot_name.empty()) {
@@ -3323,7 +3281,6 @@ Session::save_history (string snapshot_name)
     }
 
     xml_path = _path + snapshot_name + ".history"; 
-    cerr << "Saving history to " << xml_path << endmsg;
 
     bak_path = xml_path + ".bak";
 
@@ -3334,6 +3291,8 @@ Session::save_history (string snapshot_name)
         return -1;
     }
 
+    cerr << "actually writing history\n";
+
     if (!tree.write (xml_path))
     {
         error << string_compose (_("history could not be saved to %1"), xml_path) << endmsg;
index 0f783ab9435bc7314a8861b33042b0d2edfa5b20..69138f1c8bb81c677eb403c12f6171315a956fad 100644 (file)
@@ -51,7 +51,7 @@ Session::bbt_time (jack_nframes_t when, BBT_Time& bbt)
 void
 Session::sync_time_vars ()
 {
-       _current_frame_rate = _base_frame_rate * (1.0 + (video_pullup/100.0) );
+       _current_frame_rate = (jack_nframes_t) round (_base_frame_rate * (1.0 + (video_pullup/100.0)));
        _frames_per_hour = _current_frame_rate * 3600;
        _frames_per_smpte_frame = (double) _current_frame_rate / (double) smpte_frames_per_second;
        _smpte_frames_per_hour = (unsigned long) (smpte_frames_per_second * 3600.0);
index dc00cf499c48b2e75c0e7274b540abc032b7dc52..337a0c885c17bcbfe387f80675cd008897ea21eb 100644 (file)
@@ -82,7 +82,7 @@ Session::tempoize_region (TimeStretchRequest& tsr)
                }
 
                try {
-                       sources.push_back (boost::dynamic_pointer_cast<AudioFileSource> (SourceFactory::createWritable (path, false, frame_rate())));
+                       sources.push_back (boost::dynamic_pointer_cast<AudioFileSource> (SourceFactory::createWritable (*this, path, false, frame_rate())));
 
                } catch (failed_constructor& err) {
                        error << string_compose (_("tempoize: error creating new audio file %1 (%2)"), path, strerror (errno)) << endmsg;
index faed2409e54c744eb6860e8ab9d85b5c8168cfeb..61ebb153f7e67defea12365de2b9433d8470fbde 100644 (file)
@@ -34,8 +34,8 @@ using namespace std;
 using namespace ARDOUR;
 using namespace PBD;
 
-SndFileSource::SndFileSource (const XMLNode& node)
-       : AudioFileSource (node)
+SndFileSource::SndFileSource (Session& s, const XMLNode& node)
+       : AudioFileSource (s, node)
 {
        init (_name);
 
@@ -52,9 +52,9 @@ SndFileSource::SndFileSource (const XMLNode& node)
        }
 }
 
-SndFileSource::SndFileSource (string idstr, Flag flags)
+SndFileSource::SndFileSource (Session& s, string idstr, Flag flags)
                                        /* files created this way are never writable or removable */
-       : AudioFileSource (idstr, Flag (flags & ~(Writable|Removable|RemovableIfEmpty|RemoveAtDestroy)))
+       : AudioFileSource (s, idstr, Flag (flags & ~(Writable|Removable|RemovableIfEmpty|RemoveAtDestroy)))
 {
        init (idstr);
 
@@ -71,8 +71,8 @@ SndFileSource::SndFileSource (string idstr, Flag flags)
        }
 }
 
-SndFileSource::SndFileSource (string idstr, SampleFormat sfmt, HeaderFormat hf, jack_nframes_t rate, Flag flags)
-       : AudioFileSource(idstr, flags, sfmt, hf)
+SndFileSource::SndFileSource (Session& s, string idstr, SampleFormat sfmt, HeaderFormat hf, jack_nframes_t rate, Flag flags)
+       : AudioFileSource (s, idstr, flags, sfmt, hf)
 {
        int fmt = 0;
 
@@ -507,6 +507,9 @@ SndFileSource::set_header_timeline_position ()
                delete _broadcast_info;
                _broadcast_info = 0;
        }
+
+       
+
 }
 
 jack_nframes_t
index ad0d0f8a133a957d67d1c8e6ad20ea3bc9ca5b8e..e4e036584c508441ce906c04bac82b53cd7282f4 100644 (file)
@@ -42,13 +42,15 @@ using std::max;
 
 using namespace ARDOUR;
 
-Source::Source (string name)
+Source::Source (Session& s, string name)
+       : _session (s)
 {
        _name = name;
        _timestamp = 0;
 }
 
-Source::Source (const XMLNode& node) 
+Source::Source (Session& s, const XMLNode& node) 
+       : _session (s)
 {
        _timestamp = 0;
 
index e5bbe96d5ee04840d22b5e310fe26f37cff4d2d1..c7539a1370f416a285f0363d472ca396b5b5798c 100644 (file)
@@ -36,25 +36,25 @@ sigc::signal<void,boost::shared_ptr<Source> > SourceFactory::SourceCreated;
 
 #ifdef HAVE_COREAUDIO
 boost::shared_ptr<Source>
-SourceFactory::create (const XMLNode& node)
+SourceFactory::create (Session& s, const XMLNode& node)
 {
        if (node.property (X_("destructive")) != 0) {
                
-               boost::shared_ptr<Source> ret (new DestructiveFileSource (node));
+               boost::shared_ptr<Source> ret (new DestructiveFileSource (s, node));
                SourceCreated (ret);
                return ret;
                
        } else {
                
                try {
-                       boost::shared_ptr<Source> ret (new CoreAudioSource (node));
+                       boost::shared_ptr<Source> ret (new CoreAudioSource (s, node));
                        SourceCreated (ret);
                        return ret;
                } 
                
                
                catch (failed_constructor& err) {
-                       boost::shared_ptr<Source> ret (new SndFileSource (node));
+                       boost::shared_ptr<Source> ret (new SndFileSource (s, node));
                        SourceCreated (ret);
                        return ret;
                }
@@ -66,17 +66,17 @@ SourceFactory::create (const XMLNode& node)
 #else
 
 boost::shared_ptr<Source>
-SourceFactory::create (const XMLNode& node)
+SourceFactory::create (Session& s, const XMLNode& node)
 {
        if (node.property (X_("destructive")) != 0) {
                
-               boost::shared_ptr<Source> ret (new DestructiveFileSource (node));
+               boost::shared_ptr<Source> ret (new DestructiveFileSource (s, node));
                SourceCreated (ret);
                return ret;
                
        } else {
                
-               boost::shared_ptr<Source> ret (new SndFileSource (node));
+               boost::shared_ptr<Source> ret (new SndFileSource (s, node));
                SourceCreated (ret);
                return ret;
        }
@@ -86,10 +86,10 @@ SourceFactory::create (const XMLNode& node)
 
 #ifdef HAVE_COREAUDIO
 boost::shared_ptr<Source>
-SourceFactory::createReadable (string idstr, AudioFileSource::Flag flags, bool announce)
+SourceFactory::createReadable (Session& s, string idstr, AudioFileSource::Flag flags, bool announce)
 {
        if (flags & Destructive) {
-               boost::shared_ptr<Source> ret (new DestructiveFileSource (idstr, flags));
+               boost::shared_ptr<Source> ret (new DestructiveFileSource (s, idstr, flags));
                if (announce) {
                        SourceCreated (ret);
                }
@@ -97,7 +97,7 @@ SourceFactory::createReadable (string idstr, AudioFileSource::Flag flags, bool a
        }
 
        try {
-               boost::shared_ptr<Source> ret (new CoreAudioSource (idstr, flags));
+               boost::shared_ptr<Source> ret (new CoreAudioSource (s, idstr, flags));
                if (announce) {
                        SourceCreated (ret);
                }
@@ -105,7 +105,7 @@ SourceFactory::createReadable (string idstr, AudioFileSource::Flag flags, bool a
        }
 
        catch (failed_constructor& err) {
-               boost::shared_ptr<Source> ret (new SndFileSource (idstr, flags));
+               boost::shared_ptr<Source> ret (new SndFileSource (s, idstr, flags));
                if (announce) {
                        SourceCreated (ret);
                }
@@ -118,9 +118,9 @@ SourceFactory::createReadable (string idstr, AudioFileSource::Flag flags, bool a
 #else
 
 boost::shared_ptr<Source>
-SourceFactory::createReadable (string idstr, AudioFileSource::Flag flags, bool announce)
+SourceFactory::createReadable (Session& s, string idstr, AudioFileSource::Flag flags, bool announce)
 {
-       boost::shared_ptr<Source> ret (new SndFileSource (idstr, flags));
+       boost::shared_ptr<Source> ret (new SndFileSource (s, idstr, flags));
        if (announce) {
                SourceCreated (ret);
        }
@@ -130,12 +130,12 @@ SourceFactory::createReadable (string idstr, AudioFileSource::Flag flags, bool a
 #endif // HAVE_COREAUDIO
 
 boost::shared_ptr<Source>
-SourceFactory::createWritable (std::string path, bool destructive, jack_nframes_t rate, bool announce)
+SourceFactory::createWritable (Session& s, std::string path, bool destructive, jack_nframes_t rate, bool announce)
 {
        /* this might throw failed_constructor(), which is OK */
        
        if (destructive) {
-               boost::shared_ptr<Source> ret (new DestructiveFileSource (path,
+               boost::shared_ptr<Source> ret (new DestructiveFileSource (s, path,
                                                                          Config->get_native_file_data_format(),
                                                                          Config->get_native_file_header_format(),
                                                                          rate));
@@ -145,7 +145,7 @@ SourceFactory::createWritable (std::string path, bool destructive, jack_nframes_
                return ret;
                
        } else {
-               boost::shared_ptr<Source> ret (new SndFileSource (path, 
+               boost::shared_ptr<Source> ret (new SndFileSource (s, path, 
                                                                  Config->get_native_file_data_format(),
                                                                  Config->get_native_file_header_format(),
                                                                  rate));
index dbb75470525c6cbe29b447498fe840237d74553b..5dd32f2d512f32cfc9a2b3068c7985b931cc1739 100644 (file)
@@ -174,9 +174,9 @@ VSTPlugin::get_state()
 
                if (stat (path.c_str(), &sbuf)) {
                        if (errno == ENOENT) {
-                               if (mkdir (path.c_str(), 0600)) {
+                               if (g_mkdir_with_parents (path.c_str(), 0600)) {
                                        error << string_compose (_("cannot create VST chunk directory: %1"),
-                                                         strerror (errno))
+                                                                strerror (errno))
                                              << endmsg;
                                        return *root;
                                }
index 5adddfc1c06e8b10e19414cc8f7a2fa7bc5e26ed..5fbac11e5c7abcda4ec8ebfa9a721ae0cb68c7fa 100644 (file)
@@ -42,7 +42,7 @@ class Stateful {
 
        virtual void add_instant_xml (XMLNode&, const std::string& dir);
        XMLNode *instant_xml (const std::string& str, const std::string& dir);
-        PBD::ID id() { return _id; }
+        const PBD::ID& id() const { return _id; }
 
   protected:
        XMLNode *_extra_xml;