massive changes to clean up what happens during session destruction when an exception...
authorPaul Davis <paul@linuxaudiosystems.com>
Wed, 3 Jan 2007 18:08:11 +0000 (18:08 +0000)
committerPaul Davis <paul@linuxaudiosystems.com>
Wed, 3 Jan 2007 18:08:11 +0000 (18:08 +0000)
git-svn-id: svn://localhost/ardour2/trunk@1261 d708f5d6-7413-0410-9779-e7cbd77b26cf

13 files changed:
gtk2_ardour/ardour_ui.cc
gtk2_ardour/ardour_ui.h
gtk2_ardour/ardour_ui_ed.cc
gtk2_ardour/main.cc
libs/ardour/ardour/audio_diskstream.h
libs/ardour/ardour/audioengine.h
libs/ardour/ardour/io.h
libs/ardour/ardour/session.h
libs/ardour/audio_diskstream.cc
libs/ardour/audioengine.cc
libs/ardour/io.cc
libs/ardour/session.cc
libs/ardour/session_state.cc

index 4875b8db89a53bf6e825fd20969c6c266f2c3cf6..9692c89218a17a5d4d9d4050adaee4e90d2fbf99 100644 (file)
@@ -1262,14 +1262,6 @@ ARDOUR_UI::do_engine_start ()
                engine->start();
        }
 
-       catch (AudioEngine::PortRegistrationFailure& err) {
-               engine->stop ();
-               error << _("Unable to create all required ports")
-                     << endmsg;
-               unload_session ();
-               return -1;
-       }
-
        catch (...) {
                engine->stop ();
                error << _("Unable to start the session running")
@@ -1588,7 +1580,7 @@ ARDOUR_UI::save_template ()
 }
 
 void
-ARDOUR_UI::new_session (bool startup, std::string predetermined_path)
+ARDOUR_UI::new_session (std::string predetermined_path)
 {
        string session_name;
        string session_path;
@@ -1818,6 +1810,14 @@ This prevents the session from being loaded."));
                new_session = new Session (*engine, path, snap_name, mix_template);
        }
 
+       /* handle this one in a different way than all others, so that its clear what happened */
+       
+       catch (AudioEngine::PortRegistrationFailure& err) {
+               error << _("Unable to create all required ports")
+                     << endmsg;
+               return -1;
+       }
+
        catch (...) {
 
                error << string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name) << endmsg;
@@ -2330,7 +2330,7 @@ ARDOUR_UI::cmdline_new_session (string path)
                path = str;
        }
 
-       new_session (false, path);
+       new_session (path);
 
        _will_create_new_session_automatically = false; /* done it */
        return FALSE; /* don't call it again */
index fb8d87f05daeb15ca2e70dba84abaec49ef28756..77418f9ab68d9facd2c1830a788994b06906be57 100644 (file)
@@ -128,7 +128,7 @@ class ARDOUR_UI : public Gtkmm2ext::UI
                _will_create_new_session_automatically = yn;
        }
 
-        void new_session(bool startup = false, std::string path = string());
+        void new_session(std::string path = string());
        gint cmdline_new_session (string path);
        int  unload_session ();
        void close_session(); 
index 47d035b54e22c2018f75fc1dc99873b47bebc327..2ebcb765c33e69c7413af24be44ebbe8c58f4c78 100644 (file)
@@ -92,7 +92,7 @@ ARDOUR_UI::install_actions ()
 
        /* the real actions */
 
-       act = ActionManager::register_action (main_actions, X_("New"), _("New"),  bind (mem_fun(*this, &ARDOUR_UI::new_session), false, string ()));
+       act = ActionManager::register_action (main_actions, X_("New"), _("New"),  bind (mem_fun(*this, &ARDOUR_UI::new_session), string ()));
 
        ActionManager::register_action (main_actions, X_("Open"), _("Open"),  mem_fun(*this, &ARDOUR_UI::open_session));
        ActionManager::register_action (main_actions, X_("Recent"), _("Recent"),  mem_fun(*this, &ARDOUR_UI::open_recent_session));
index 3e0d6d4e6292c175748e6bb3b8d713e666843e1e..1004de19c2a94df362e2cce80b8b483d4dab1670 100644 (file)
@@ -79,8 +79,6 @@ shutdown (int status)
        } else {
 
                if (ui) {
-                       msg = _("stopping user interface\n");
-                       write (1, msg, strlen (msg));
                        ui->kill();
                }
                
@@ -301,7 +299,7 @@ maybe_load_session ()
        if (!session_name.length()) {
                ui->hide_splash ();
                if (!Config->get_no_new_session_dialog()) {
-                      ui->new_session (true);
+                      ui->new_session ();
                }
 
                return true;
@@ -326,7 +324,10 @@ To create it from the command line, start ardour as \"ardour --new %1"), path) <
                        return false;
                }
 
-               ui->load_session (path, name);
+               if (ui->load_session (path, name)) {
+                       /* it failed */
+                       return false;
+               }
 
        } else {
 
@@ -338,7 +339,7 @@ To create it from the command line, start ardour as \"ardour --new %1"), path) <
                /* Show the NSD */
                ui->hide_splash ();
                if (!Config->get_no_new_session_dialog()) {
-                      ui->new_session (true);
+                      ui->new_session ();
                }
        }
 
index 7c00885228b67bf9686e1c1e4a7da075f16b836a..1da8903a41b1c61d62b86db8fcf91932a80bfba6 100644 (file)
@@ -173,33 +173,39 @@ class AudioDiskstream : public Diskstream
   private:
 
        struct ChannelInfo {
-
-               Sample     *playback_wrap_buffer;
-               Sample     *capture_wrap_buffer;
-               Sample     *speed_buffer;
-
-               float       peak_power;
            
-               boost::shared_ptr<AudioFileSource> fades_source;
-               boost::shared_ptr<AudioFileSource> write_source;
-
-               Port         *source;
-               Sample       *current_capture_buffer;
-               Sample       *current_playback_buffer;
+           ChannelInfo ();
+           ~ChannelInfo ();
 
-               RingBufferNPT<Sample> *playback_buf;
-               RingBufferNPT<Sample> *capture_buf;
+           void init (nframes_t buffer_size, nframes_t speed_buffer_size, nframes_t wrap_buffer_size);
+           void release ();
 
-               Sample* scrub_buffer;
-               Sample* scrub_forward_buffer;
-               Sample* scrub_reverse_buffer;
-
-               RingBufferNPT<Sample>::rw_vector playback_vector;
-               RingBufferNPT<Sample>::rw_vector capture_vector;
-
-               RingBufferNPT<CaptureTransition> * capture_transition_buf;
-               // the following are used in the butler thread only
-               nframes_t                     curr_capture_cnt;
+           Sample     *playback_wrap_buffer;
+           Sample     *capture_wrap_buffer;
+           Sample     *speed_buffer;
+           
+           float       peak_power;
+           
+           boost::shared_ptr<AudioFileSource> fades_source;
+           boost::shared_ptr<AudioFileSource> write_source;
+           
+           Port         *source;
+           Sample       *current_capture_buffer;
+           Sample       *current_playback_buffer;
+           
+           RingBufferNPT<Sample> *playback_buf;
+           RingBufferNPT<Sample> *capture_buf;
+           
+           Sample* scrub_buffer;
+           Sample* scrub_forward_buffer;
+           Sample* scrub_reverse_buffer;
+           
+           RingBufferNPT<Sample>::rw_vector playback_vector;
+           RingBufferNPT<Sample>::rw_vector capture_vector;
+           
+           RingBufferNPT<CaptureTransition> * capture_transition_buf;
+           // the following are used in the butler thread only
+           nframes_t                     curr_capture_cnt;
        };
 
        /* The two central butler operations */
index 7274f5646e451e4153222bf89ca1504d328f0a76..83d075a311c4468fef03f0db50ba4de7b09b8ea2 100644 (file)
@@ -197,8 +197,7 @@ class AudioEngine : public sigc::trackable
        jack_client_t       *_jack;
        std::string           jack_client_name;
        Glib::Mutex           _process_lock;
-       Glib::Mutex           session_remove_lock;
-    Glib::Cond            session_removed;
+       Glib::Cond            session_removed;
        bool                  session_remove_pending;
        bool                 _running;
        bool                 _has_run;
index eb332398da5e41d1ebe68cf2429c3d39e1fa920b..7c198bb72ab696dc669a1758db2f0ccde8414346 100644 (file)
@@ -199,13 +199,13 @@ class IO : public PBD::StatefulDestructible
 
     static void update_meters();
 
-private: 
+  private: 
 
     static sigc::signal<void>   Meter;
     static Glib::StaticMutex    m_meter_signal_lock;
     sigc::connection            m_meter_connection;
 
-public:
+  public:
 
        /* automation */
 
index c71403e125d592f68aa8ffd6005ee7fc10cd69ad..5aa53e274f88fc4dcf5ad0308283191ed6c56f14 100644 (file)
@@ -933,6 +933,7 @@ class Session : public PBD::StatefulDestructible
        
   private:
        int  create (bool& new_session, string* mix_template, nframes_t initial_length);
+       void destroy ();
 
        nframes_t compute_initial_length ();
 
index 66b34956fe6ce5f7a74b46eef16784bfcd54801e..ef3173e87b4624a5766e2b2cd77081ffc9e4208f 100644 (file)
@@ -96,34 +96,6 @@ AudioDiskstream::AudioDiskstream (Session& sess, const XMLNode& node)
        }
 }
 
-void
-AudioDiskstream::init_channel (ChannelInfo &chan)
-{
-       chan.playback_wrap_buffer = 0;
-       chan.capture_wrap_buffer = 0;
-       chan.speed_buffer = 0;
-       chan.peak_power = 0.0f;
-       chan.source = 0;
-       chan.current_capture_buffer = 0;
-       chan.current_playback_buffer = 0;
-       chan.curr_capture_cnt = 0;
-       
-       chan.playback_buf = new RingBufferNPT<Sample> (_session.diskstream_buffer_size());
-       chan.capture_buf = new RingBufferNPT<Sample> (_session.diskstream_buffer_size());
-       chan.capture_transition_buf = new RingBufferNPT<CaptureTransition> (128);
-       
-       
-       /* touch the ringbuffer buffers, which will cause
-          them to be mapped into locked physical RAM if
-          we're running with mlockall(). this doesn't do
-          much if we're not.  
-       */
-       memset (chan.playback_buf->buffer(), 0, sizeof (Sample) * chan.playback_buf->bufsize());
-       memset (chan.capture_buf->buffer(), 0, sizeof (Sample) * chan.capture_buf->bufsize());
-       memset (chan.capture_transition_buf->buffer(), 0, sizeof (CaptureTransition) * chan.capture_transition_buf->bufsize());
-}
-
-
 void
 AudioDiskstream::init (Diskstream::Flag f)
 {
@@ -141,44 +113,19 @@ AudioDiskstream::init (Diskstream::Flag f)
        assert(_n_channels == 1);
 }
 
-void
-AudioDiskstream::destroy_channel (ChannelInfo &chan)
-{
-       if (chan.write_source) {
-               chan.write_source.reset ();
-       }
-               
-       if (chan.speed_buffer) {
-               delete [] chan.speed_buffer;
-       }
-
-       if (chan.playback_wrap_buffer) {
-               delete [] chan.playback_wrap_buffer;
-       }
-       if (chan.capture_wrap_buffer) {
-               delete [] chan.capture_wrap_buffer;
-       }
-       
-       delete chan.playback_buf;
-       delete chan.capture_buf;
-       delete chan.capture_transition_buf;
-       
-       chan.playback_buf = 0;
-       chan.capture_buf = 0;
-}
-
 AudioDiskstream::~AudioDiskstream ()
 {
+       notify_callbacks ();
+
        {
                /* don't be holding this lock as we exit the destructor, glib will wince
                   visibly since the mutex gets destroyed before we release it.
                */
 
                Glib::Mutex::Lock lm (state_lock);
-               
-               for (ChannelList::iterator chan = channels.begin(); chan != channels.end(); ++chan)
-                       destroy_channel((*chan));
-               
+               for (ChannelList::iterator chan = channels.begin(); chan != channels.end(); ++chan) {
+                       (*chan).release ();
+               }
                channels.clear();
        }
 }
@@ -2107,15 +2054,19 @@ AudioDiskstream::add_channel ()
 {
        /* XXX need to take lock??? */
 
-       ChannelInfo chan;
+       /* this copies the ChannelInfo, which currently has no buffers. kind
+          of pointless really, but we want the channels list to contain
+          actual objects, not pointers to objects. mostly for convenience,
+          which isn't much in evidence.
+       */
 
-       init_channel (chan);
+       channels.push_back (ChannelInfo());
 
-       chan.speed_buffer = new Sample[speed_buffer_size];
-       chan.playback_wrap_buffer = new Sample[wrap_buffer_size];
-       chan.capture_wrap_buffer = new Sample[wrap_buffer_size];
+       /* now allocate the buffers */
 
-       channels.push_back (chan);
+       channels.back().init (_session.diskstream_buffer_size(), 
+                             speed_buffer_size,
+                             wrap_buffer_size);
 
        _n_channels = channels.size();
 
@@ -2127,10 +2078,8 @@ AudioDiskstream::remove_channel ()
 {
        if (channels.size() > 1) {
                /* XXX need to take lock??? */
-               ChannelInfo & chan = channels.back();
-               destroy_channel (chan);
+               channels.back().release ();
                channels.pop_back();
-
                _n_channels = channels.size();
                return 0;
        }
@@ -2310,3 +2259,82 @@ AudioDiskstream::can_become_destructive (bool& requires_bounce) const
        requires_bounce = false;
        return true;
 }
+
+AudioDiskstream::ChannelInfo::ChannelInfo ()
+{
+       playback_wrap_buffer = 0;
+       capture_wrap_buffer = 0;
+       speed_buffer = 0;
+       peak_power = 0.0f;
+       source = 0;
+       current_capture_buffer = 0;
+       current_playback_buffer = 0;
+       curr_capture_cnt = 0;
+       playback_buf = 0;
+       capture_buf = 0;
+       capture_transition_buf = 0;
+}
+
+void
+AudioDiskstream::ChannelInfo::init (nframes_t bufsize, nframes_t speed_size, nframes_t wrap_size)
+{
+       speed_buffer = new Sample[speed_size];
+       playback_wrap_buffer = new Sample[wrap_size];
+       capture_wrap_buffer = new Sample[wrap_size];
+
+       playback_buf = new RingBufferNPT<Sample> (bufsize);
+       capture_buf = new RingBufferNPT<Sample> (bufsize);
+       capture_transition_buf = new RingBufferNPT<CaptureTransition> (128);
+       
+       /* touch the ringbuffer buffers, which will cause
+          them to be mapped into locked physical RAM if
+          we're running with mlockall(). this doesn't do
+          much if we're not.  
+       */
+
+       memset (playback_buf->buffer(), 0, sizeof (Sample) * playback_buf->bufsize());
+       memset (capture_buf->buffer(), 0, sizeof (Sample) * capture_buf->bufsize());
+       memset (capture_transition_buf->buffer(), 0, sizeof (CaptureTransition) * capture_transition_buf->bufsize());
+}
+
+AudioDiskstream::ChannelInfo::~ChannelInfo ()
+{
+}
+
+void
+AudioDiskstream::ChannelInfo::release ()
+{
+       if (write_source) {
+               write_source.reset ();
+       }
+               
+       if (speed_buffer) {
+               delete [] speed_buffer;
+               speed_buffer = 0;
+       }
+
+       if (playback_wrap_buffer) {
+               delete [] playback_wrap_buffer;
+               playback_wrap_buffer = 0;
+       }
+
+       if (capture_wrap_buffer) {
+               delete [] capture_wrap_buffer;
+               capture_wrap_buffer = 0;
+       }
+       
+       if (playback_buf) {
+               delete playback_buf;
+               playback_buf = 0;
+       }
+
+       if (capture_buf) {
+               delete capture_buf;
+               capture_buf = 0;
+       }
+
+       if (capture_transition_buf) {
+               delete capture_transition_buf;
+               capture_transition_buf = 0;
+       }
+}
index 39c5ddcdabc3c24687d11bcbfe68928b30b6cb0f..128fc37eb167a0f27520bf2ede5d21681b20719f 100644 (file)
@@ -45,6 +45,12 @@ using namespace PBD;
 
 gint AudioEngine::m_meter_exit;
 
+static void 
+ardour_jack_error (const char* msg) 
+{
+       error << "JACK: " << msg << endmsg;
+}
+
 AudioEngine::AudioEngine (string client_name) 
        : ports (new Ports)
 {
@@ -76,11 +82,16 @@ AudioEngine::AudioEngine (string client_name)
 
 AudioEngine::~AudioEngine ()
 {
-       if (_running) {
-               jack_client_close (_jack);
+       {
+               Glib::Mutex::Lock tm (_process_lock);
+               session_removed.signal ();
+               
+               if (_running) {
+                       jack_client_close (_jack);
+               }
+               
+               stop_metering_thread ();
        }
-
-       stop_metering_thread ();
 }
 
 void
@@ -407,8 +418,26 @@ AudioEngine::meter_thread ()
 void 
 AudioEngine::set_session (Session *s)
 {
+       Glib::Mutex::Lock pl (_process_lock);
+
        if (!session) {
+
                session = s;
+
+               nframes_t blocksize = jack_get_buffer_size (_jack);
+               
+               /* page in as much of the session process code as we
+                  can before we really start running.
+               */
+               
+               session->process (blocksize);
+               session->process (blocksize);
+               session->process (blocksize);
+               session->process (blocksize);
+               session->process (blocksize);
+               session->process (blocksize);
+               session->process (blocksize);
+               session->process (blocksize);
        }
 }
 
@@ -422,12 +451,10 @@ AudioEngine::remove_session ()
                if (session) {
                        session_remove_pending = true;
                        session_removed.wait(_process_lock);
-               } 
+               }
 
        } else {
-
                session = 0;
-
        }
        
        remove_all_ports ();
@@ -461,8 +488,6 @@ AudioEngine::register_input_port (DataType type, const string& portname)
                return newport;
 
        } else {
-
-               _process_lock.unlock();
                throw PortRegistrationFailure();
        }
 
@@ -501,8 +526,6 @@ AudioEngine::register_output_port (DataType type, const string& portname)
                return newport;
 
        } else {
-
-               _process_lock.unlock();
                throw PortRegistrationFailure ();
        }
 
@@ -1015,6 +1038,8 @@ AudioEngine::connect_to_jack (string client_name)
        if (status & JackNameNotUnique) {
                jack_client_name = jack_get_client_name (_jack);
        }
+
+       jack_set_error_function (ardour_jack_error);
        
        return 0;
 }
index 77f3a33ff2cc74e9ba16368f2e5cec6dd62f702b..1c72697347faf18e6d2f8b3db2ab0fd4d58f2b3e 100644 (file)
@@ -53,6 +53,7 @@ extern "C" int isnan (double);
 extern "C" int isinf (double);
 #endif
 
+#define BLOCK_PROCESS_CALLBACK() Glib::Mutex::Lock em (_session.engine().process_lock())
 
 using namespace std;
 using namespace ARDOUR;
@@ -624,7 +625,7 @@ IO::disconnect_input (Port* our_port, string other_port, void* src)
        }
 
        { 
-               Glib::Mutex::Lock em (_session.engine().process_lock());
+               BLOCK_PROCESS_CALLBACK ();
                
                {
                        Glib::Mutex::Lock lm (io_lock);
@@ -660,7 +661,7 @@ IO::connect_input (Port* our_port, string other_port, void* src)
        }
 
        {
-               Glib::Mutex::Lock em(_session.engine().process_lock());
+               BLOCK_PROCESS_CALLBACK ();
                
                {
                        Glib::Mutex::Lock lm (io_lock);
@@ -694,7 +695,7 @@ IO::disconnect_output (Port* our_port, string other_port, void* src)
        }
 
        {
-               Glib::Mutex::Lock em(_session.engine().process_lock());
+               BLOCK_PROCESS_CALLBACK ();
                
                {
                        Glib::Mutex::Lock lm (io_lock);
@@ -727,7 +728,8 @@ IO::connect_output (Port* our_port, string other_port, void* src)
        }
 
        {
-               Glib::Mutex::Lock em(_session.engine().process_lock());
+               BLOCK_PROCESS_CALLBACK ();
+
                
                {
                        Glib::Mutex::Lock lm (io_lock);
@@ -786,7 +788,8 @@ IO::remove_output_port (Port* port, void* src)
        IOChange change (NoChange);
 
        {
-               Glib::Mutex::Lock em(_session.engine().process_lock());
+               BLOCK_PROCESS_CALLBACK ();
+
                
                {
                        Glib::Mutex::Lock lm (io_lock);
@@ -844,7 +847,8 @@ IO::add_output_port (string destination, void* src, DataType type)
                type = _default_type;
 
        {
-               Glib::Mutex::Lock em(_session.engine().process_lock());
+               BLOCK_PROCESS_CALLBACK ();
+
                
                { 
                        Glib::Mutex::Lock lm (io_lock);
@@ -896,7 +900,8 @@ IO::remove_input_port (Port* port, void* src)
        IOChange change (NoChange);
 
        {
-               Glib::Mutex::Lock em(_session.engine().process_lock());
+               BLOCK_PROCESS_CALLBACK ();
+
                
                {
                        Glib::Mutex::Lock lm (io_lock);
@@ -956,7 +961,7 @@ IO::add_input_port (string source, void* src, DataType type)
                type = _default_type;
 
        {
-               Glib::Mutex::Lock em (_session.engine().process_lock());
+               BLOCK_PROCESS_CALLBACK ();
                
                { 
                        Glib::Mutex::Lock lm (io_lock);
@@ -1008,7 +1013,7 @@ int
 IO::disconnect_inputs (void* src)
 {
        { 
-               Glib::Mutex::Lock em (_session.engine().process_lock());
+               BLOCK_PROCESS_CALLBACK ();
                
                {
                        Glib::Mutex::Lock lm (io_lock);
@@ -1028,7 +1033,7 @@ int
 IO::disconnect_outputs (void* src)
 {
        {
-               Glib::Mutex::Lock em (_session.engine().process_lock());
+               BLOCK_PROCESS_CALLBACK ();
                
                {
                        Glib::Mutex::Lock lm (io_lock);
@@ -1090,7 +1095,7 @@ IO::ensure_inputs_locked (uint32_t n, bool clear, void* src)
                        setup_peak_meters ();
                        reset_panner ();
                        /* pass it on */
-                       throw err;
+                       throw AudioEngine::PortRegistrationFailure();
                }
                
                _inputs.push_back (input_port);
@@ -1140,7 +1145,7 @@ IO::ensure_io (uint32_t nin, uint32_t nout, bool clear, void* src)
        }
 
        {
-               Glib::Mutex::Lock em (_session.engine().process_lock());
+               BLOCK_PROCESS_CALLBACK ();
                Glib::Mutex::Lock lm (io_lock);
 
                Port* port;
@@ -1195,7 +1200,7 @@ IO::ensure_io (uint32_t nin, uint32_t nout, bool clear, void* src)
                                setup_peak_meters ();
                                reset_panner ();
                                /* pass it on */
-                               throw err;
+                               throw AudioEngine::PortRegistrationFailure();
                        }
                
                        _inputs.push_back (port);
@@ -1228,7 +1233,7 @@ IO::ensure_io (uint32_t nin, uint32_t nout, bool clear, void* src)
                                setup_peak_meters ();
                                reset_panner ();
                                /* pass it on */
-                               throw err;
+                               throw AudioEngine::PortRegistrationFailure ();
                        }
                
                        _outputs.push_back (port);
@@ -1289,7 +1294,7 @@ IO::ensure_inputs (uint32_t n, bool clear, bool lockit, void* src)
        }
        
        if (lockit) {
-               Glib::Mutex::Lock em (_session.engine().process_lock());
+               BLOCK_PROCESS_CALLBACK ();
                Glib::Mutex::Lock im (io_lock);
                changed = ensure_inputs_locked (n, clear, src);
        } else {
@@ -1391,7 +1396,7 @@ IO::ensure_outputs (uint32_t n, bool clear, bool lockit, void* src)
        /* XXX caller should hold io_lock, but generally doesn't */
 
        if (lockit) {
-               Glib::Mutex::Lock em (_session.engine().process_lock());
+               BLOCK_PROCESS_CALLBACK ();
                Glib::Mutex::Lock im (io_lock);
                changed = ensure_outputs_locked (n, clear, src);
        } else {
@@ -2191,7 +2196,7 @@ IO::use_input_connection (Connection& c, void* src)
        uint32_t limit;
 
        {
-               Glib::Mutex::Lock lm (_session.engine().process_lock());
+               BLOCK_PROCESS_CALLBACK ();
                Glib::Mutex::Lock lm2 (io_lock);
                
                limit = c.nports();
@@ -2269,7 +2274,7 @@ IO::use_output_connection (Connection& c, void* src)
        uint32_t limit; 
 
        {
-               Glib::Mutex::Lock lm (_session.engine().process_lock());
+               BLOCK_PROCESS_CALLBACK ();
                Glib::Mutex::Lock lm2 (io_lock);
 
                limit = c.nports();
index 45be26c598fa34f2f282170c14ee7a8b2b589738..c6cd6528d35802e294cfd0c2413b17898b1aeb0f 100644 (file)
@@ -281,12 +281,13 @@ Session::Session (AudioEngine &eng,
        if (new_session) {
                if (create (new_session, mix_template, compute_initial_length())) {
                        cerr << "create failed\n";
+                       destroy ();
                        throw failed_constructor ();
                }
        }
        
        if (second_stage_init (new_session)) {
-               cerr << "2nd state failed\n";
+               destroy ();
                throw failed_constructor ();
        }
        
@@ -346,6 +347,7 @@ Session::Session (AudioEngine &eng,
 
        if (new_session) {
                if (create (new_session, 0, initial_length)) {
+                       destroy ();
                        throw failed_constructor ();
                }
        }
@@ -373,6 +375,7 @@ Session::Session (AudioEngine &eng,
        Config->set_output_auto_connect (output_ac);
 
        if (second_stage_init (new_session)) {
+               destroy ();
                throw failed_constructor ();
        }
        
@@ -388,6 +391,12 @@ Session::Session (AudioEngine &eng,
 }
 
 Session::~Session ()
+{
+       destroy ();
+}
+
+void
+Session::destroy ()
 {
        /* if we got to here, leaving pending capture state around
           is a mistake.
@@ -2930,6 +2939,7 @@ Session::audio_path_from_name (string name, uint32_t nchan, uint32_t chan, bool
 
                if (cnt > limit) {
                        error << string_compose(_("There are already %1 recordings for %2, which I consider too many."), limit, name) << endmsg;
+                       destroy ();
                        throw failed_constructor();
                }
        }
index 0afa682d58cce73c00b9e0231779db1f66ac9900..0c2961c82a200d29b3b3f1a6f218fcd2127cc3b9 100644 (file)
@@ -99,12 +99,14 @@ void
 Session::first_stage_init (string fullpath, string snapshot_name)
 {
        if (fullpath.length() == 0) {
+               destroy ();
                throw failed_constructor();
        }
 
        char buf[PATH_MAX+1];
        if (!realpath (fullpath.c_str(), buf) && (errno != ENOENT)) {
                error << string_compose(_("Could not use path %1 (%s)"), buf, strerror(errno)) << endmsg;
+               destroy ();
                throw failed_constructor();
        }
 
@@ -155,7 +157,7 @@ Session::first_stage_init (string fullpath, string snapshot_name)
        _worst_output_latency = 0;
        _worst_input_latency = 0;
        _worst_track_latency = 0;
-       _state_of_the_state = StateOfTheState(CannotSave|InitialConnecting|Loading);
+       _state_of_the_state = StateOfTheState(CannotSave|InitialConnecting|Loading|Deletion);
        _slave = 0;
        butler_mixdown_buffer = 0;
        butler_gain_buffer = 0;
@@ -307,7 +309,13 @@ Session::second_stage_init (bool new_session)
        _engine.Halted.connect (mem_fun (*this, &Session::engine_halted));
        _engine.Xrun.connect (mem_fun (*this, &Session::xrun_recovery));
 
-       when_engine_running();
+       try {
+               when_engine_running();
+       }
+
+       catch (...) {
+               return -1;
+       }
 
        send_full_time_code ();
        _engine.transport_locate (0);