From ca81401b14782b5d13905732778e6bf9b5f5f2ae Mon Sep 17 00:00:00 2001 From: Paul Davis Date: Wed, 3 Jan 2007 18:08:11 +0000 Subject: massive changes to clean up what happens during session destruction when an exception is thrown git-svn-id: svn://localhost/ardour2/trunk@1261 d708f5d6-7413-0410-9779-e7cbd77b26cf --- gtk2_ardour/ardour_ui.cc | 20 ++--- gtk2_ardour/ardour_ui.h | 2 +- gtk2_ardour/ardour_ui_ed.cc | 2 +- gtk2_ardour/main.cc | 11 +-- libs/ardour/ardour/audio_diskstream.h | 54 +++++++----- libs/ardour/ardour/audioengine.h | 3 +- libs/ardour/ardour/io.h | 4 +- libs/ardour/ardour/session.h | 1 + libs/ardour/audio_diskstream.cc | 162 ++++++++++++++++++++-------------- libs/ardour/audioengine.cc | 47 +++++++--- libs/ardour/io.cc | 41 +++++---- libs/ardour/session.cc | 12 ++- libs/ardour/session_state.cc | 12 ++- 13 files changed, 227 insertions(+), 144 deletions(-) diff --git a/gtk2_ardour/ardour_ui.cc b/gtk2_ardour/ardour_ui.cc index 4875b8db89..9692c89218 100644 --- a/gtk2_ardour/ardour_ui.cc +++ b/gtk2_ardour/ardour_ui.cc @@ -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 */ diff --git a/gtk2_ardour/ardour_ui.h b/gtk2_ardour/ardour_ui.h index fb8d87f05d..77418f9ab6 100644 --- a/gtk2_ardour/ardour_ui.h +++ b/gtk2_ardour/ardour_ui.h @@ -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(); diff --git a/gtk2_ardour/ardour_ui_ed.cc b/gtk2_ardour/ardour_ui_ed.cc index 47d035b54e..2ebcb765c3 100644 --- a/gtk2_ardour/ardour_ui_ed.cc +++ b/gtk2_ardour/ardour_ui_ed.cc @@ -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)); diff --git a/gtk2_ardour/main.cc b/gtk2_ardour/main.cc index 3e0d6d4e62..1004de19c2 100644 --- a/gtk2_ardour/main.cc +++ b/gtk2_ardour/main.cc @@ -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 (); } } diff --git a/libs/ardour/ardour/audio_diskstream.h b/libs/ardour/ardour/audio_diskstream.h index 7c00885228..1da8903a41 100644 --- a/libs/ardour/ardour/audio_diskstream.h +++ b/libs/ardour/ardour/audio_diskstream.h @@ -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 fades_source; - boost::shared_ptr write_source; - - Port *source; - Sample *current_capture_buffer; - Sample *current_playback_buffer; + ChannelInfo (); + ~ChannelInfo (); - RingBufferNPT *playback_buf; - RingBufferNPT *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::rw_vector playback_vector; - RingBufferNPT::rw_vector capture_vector; - - RingBufferNPT * 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 fades_source; + boost::shared_ptr write_source; + + Port *source; + Sample *current_capture_buffer; + Sample *current_playback_buffer; + + RingBufferNPT *playback_buf; + RingBufferNPT *capture_buf; + + Sample* scrub_buffer; + Sample* scrub_forward_buffer; + Sample* scrub_reverse_buffer; + + RingBufferNPT::rw_vector playback_vector; + RingBufferNPT::rw_vector capture_vector; + + RingBufferNPT * capture_transition_buf; + // the following are used in the butler thread only + nframes_t curr_capture_cnt; }; /* The two central butler operations */ diff --git a/libs/ardour/ardour/audioengine.h b/libs/ardour/ardour/audioengine.h index 7274f5646e..83d075a311 100644 --- a/libs/ardour/ardour/audioengine.h +++ b/libs/ardour/ardour/audioengine.h @@ -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; diff --git a/libs/ardour/ardour/io.h b/libs/ardour/ardour/io.h index eb332398da..7c198bb72a 100644 --- a/libs/ardour/ardour/io.h +++ b/libs/ardour/ardour/io.h @@ -199,13 +199,13 @@ class IO : public PBD::StatefulDestructible static void update_meters(); -private: + private: static sigc::signal Meter; static Glib::StaticMutex m_meter_signal_lock; sigc::connection m_meter_connection; -public: + public: /* automation */ diff --git a/libs/ardour/ardour/session.h b/libs/ardour/ardour/session.h index c71403e125..5aa53e274f 100644 --- a/libs/ardour/ardour/session.h +++ b/libs/ardour/ardour/session.h @@ -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 (); diff --git a/libs/ardour/audio_diskstream.cc b/libs/ardour/audio_diskstream.cc index 66b34956fe..ef3173e87b 100644 --- a/libs/ardour/audio_diskstream.cc +++ b/libs/ardour/audio_diskstream.cc @@ -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 (_session.diskstream_buffer_size()); - chan.capture_buf = new RingBufferNPT (_session.diskstream_buffer_size()); - chan.capture_transition_buf = new RingBufferNPT (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 (bufsize); + capture_buf = new RingBufferNPT (bufsize); + capture_transition_buf = new RingBufferNPT (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; + } +} diff --git a/libs/ardour/audioengine.cc b/libs/ardour/audioengine.cc index 39c5ddcdab..128fc37eb1 100644 --- a/libs/ardour/audioengine.cc +++ b/libs/ardour/audioengine.cc @@ -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; } diff --git a/libs/ardour/io.cc b/libs/ardour/io.cc index 77f3a33ff2..1c72697347 100644 --- a/libs/ardour/io.cc +++ b/libs/ardour/io.cc @@ -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(); diff --git a/libs/ardour/session.cc b/libs/ardour/session.cc index 45be26c598..c6cd6528d3 100644 --- a/libs/ardour/session.cc +++ b/libs/ardour/session.cc @@ -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(); } } diff --git a/libs/ardour/session_state.cc b/libs/ardour/session_state.cc index 0afa682d58..0c2961c82a 100644 --- a/libs/ardour/session_state.cc +++ b/libs/ardour/session_state.cc @@ -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); -- cgit v1.2.3