summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Davis <paul@linuxaudiosystems.com>2012-06-21 20:31:14 +0000
committerPaul Davis <paul@linuxaudiosystems.com>2012-06-21 20:31:14 +0000
commit39becbeb70aa4ab82b963669d87995a32141981c (patch)
tree4124b69dbc082561e601377fb41109ee96216735
parent33d17f176b20e2ebc96e7bb05af5ff3984e71f1d (diff)
smooth 0.5 second fade out during quit, plus MIDI panic to turn everything off (someone will want an opton for that, no doubt)
git-svn-id: svn://localhost/ardour2/branches/3.0@12814 d708f5d6-7413-0410-9779-e7cbd77b26cf
-rw-r--r--gtk2_ardour/ardour_ui.cc5
-rw-r--r--libs/ardour/ardour/audio_port.h3
-rw-r--r--libs/ardour/ardour/audioengine.h8
-rw-r--r--libs/ardour/audio_port.cc12
-rw-r--r--libs/ardour/audioengine.cc107
-rw-r--r--libs/ardour/session_process.cc2
6 files changed, 93 insertions, 44 deletions
diff --git a/gtk2_ardour/ardour_ui.cc b/gtk2_ardour/ardour_ui.cc
index 0a4a4782d2..e41f712351 100644
--- a/gtk2_ardour/ardour_ui.cc
+++ b/gtk2_ardour/ardour_ui.cc
@@ -755,11 +755,6 @@ ARDOUR_UI::finish()
if (_session) {
int tries = 0;
- if (_session->transport_rolling() && (++tries < 8)) {
- _session->request_stop (false, true);
- usleep (10000);
- }
-
if (_session->dirty()) {
vector<string> actions;
actions.push_back (_("Don't quit"));
diff --git a/libs/ardour/ardour/audio_port.h b/libs/ardour/ardour/audio_port.h
index 6b534afe62..7f084a5c85 100644
--- a/libs/ardour/ardour/audio_port.h
+++ b/libs/ardour/ardour/audio_port.h
@@ -49,9 +49,12 @@ class AudioPort : public Port
friend class AudioEngine;
AudioPort (std::string const &, Flags);
+ /* special access for engine only */
+ Sample* engine_get_whole_audio_buffer ();
private:
AudioBuffer* _buffer;
+ bool _buf_valid;
};
} // namespace ARDOUR
diff --git a/libs/ardour/ardour/audioengine.h b/libs/ardour/ardour/audioengine.h
index fdaf864a0d..73e40e8ab4 100644
--- a/libs/ardour/ardour/audioengine.h
+++ b/libs/ardour/ardour/audioengine.h
@@ -268,6 +268,9 @@ private:
Glib::Mutex _process_lock;
Glib::Cond session_removed;
bool session_remove_pending;
+ frameoffset_t session_removal_countdown;
+ gain_t session_removal_gain;
+ gain_t session_removal_gain_step;
bool _running;
bool _has_run;
mutable framecnt_t _buffer_size;
@@ -283,6 +286,8 @@ private:
bool _pre_freewheel_mmc_enabled;
int _usecs_per_cycle;
bool port_remove_in_progress;
+ Glib::Thread* m_meter_thread;
+ ProcessThread* _main_thread;
SerializedRCUManager<Ports> ports;
@@ -331,11 +336,8 @@ private:
void start_metering_thread ();
void stop_metering_thread ();
- Glib::Thread* m_meter_thread;
static gint m_meter_exit;
- ProcessThread* _main_thread;
-
struct ThreadData {
AudioEngine* engine;
boost::function<void()> f;
diff --git a/libs/ardour/audio_port.cc b/libs/ardour/audio_port.cc
index 48a757fb42..240224ea5e 100644
--- a/libs/ardour/audio_port.cc
+++ b/libs/ardour/audio_port.cc
@@ -73,10 +73,18 @@ AudioBuffer&
AudioPort::get_audio_buffer (pframes_t nframes)
{
/* caller must hold process lock */
- _buffer->set_data ((Sample *) jack_port_get_buffer (_jack_port, _cycle_nframes) +
- _global_port_buffer_offset + _port_buffer_offset, nframes);
+ _buffer->set_data ((Sample *) jack_port_get_buffer (_jack_port, _cycle_nframes) +
+ _global_port_buffer_offset + _port_buffer_offset, nframes);
return *_buffer;
}
+Sample*
+AudioPort::engine_get_whole_audio_buffer ()
+{
+ /* caller must hold process lock */
+ return (Sample *) jack_port_get_buffer (_jack_port, _cycle_nframes);
+}
+
+
diff --git a/libs/ardour/audioengine.cc b/libs/ardour/audioengine.cc
index 5642db8932..004ba33a6e 100644
--- a/libs/ardour/audioengine.cc
+++ b/libs/ardour/audioengine.cc
@@ -62,26 +62,26 @@ AudioEngine* AudioEngine::_instance = 0;
#define GET_PRIVATE_JACK_POINTER_RET(j,r) jack_client_t* _priv_jack = (jack_client_t*) (j); if (!_priv_jack) { return r; }
AudioEngine::AudioEngine (string client_name, string session_uuid)
- : ports (new Ports)
+ : _jack (0)
+ , session_remove_pending (false)
+ , session_removal_countdown (-1)
+ , _running (false)
+ , _has_run (false)
+ , _buffer_size (0)
+ , _frame_rate (0)
+ , monitor_check_interval (INT32_MAX)
+ , last_monitor_check (0)
+ , _processed_frames (0)
+ , _freewheeling (false)
+ , _pre_freewheel_mmc_enabled (false)
+ , _usecs_per_cycle (0)
+ , port_remove_in_progress (false)
+ , m_meter_thread (0)
+ , _main_thread (0)
+ , ports (new Ports)
{
_instance = this; /* singleton */
- session_remove_pending = false;
- _running = false;
- _has_run = false;
- last_monitor_check = 0;
- monitor_check_interval = INT32_MAX;
- _processed_frames = 0;
- _usecs_per_cycle = 0;
- _jack = 0;
- _frame_rate = 0;
- _buffer_size = 0;
- _freewheeling = false;
- _pre_freewheel_mmc_enabled = false;
- _main_thread = 0;
- port_remove_in_progress = false;
-
- m_meter_thread = 0;
g_atomic_int_set (&m_meter_exit, 0);
if (connect_to_jack (client_name, session_uuid)) {
@@ -476,28 +476,43 @@ AudioEngine::process_callback (pframes_t nframes)
}
if (session_remove_pending) {
+
/* perform the actual session removal */
- _session = 0;
- session_remove_pending = false;
- /* pump one cycle of silence into the ports
- before the session tears them all down
- (asynchronously).
- */
+ if (session_removal_countdown < 0) {
- boost::shared_ptr<Ports> p = ports.reader();
-
- for (Ports::iterator i = p->begin(); i != p->end(); ++i) {
-
- if (i->second->sends_output()) {
- i->second->get_buffer (nframes).silence (nframes);
+ /* fade out over 1 second */
+ session_removal_countdown = _frame_rate/2;
+ session_removal_gain = 1.0;
+ session_removal_gain_step = 1.0/session_removal_countdown;
+
+ } else if (session_removal_countdown > 0) {
+
+ /* we'll be fading audio out.
+
+ if this is the last time we do this as part
+ of session removal, do a MIDI panic now
+ to get MIDI stopped. This relies on the fact
+ that "immediate data" (aka "out of band data") from
+ MIDI tracks is *appended* after any other data,
+ so that it emerges after any outbound note ons, etc.
+ */
+
+ if (session_removal_countdown <= nframes) {
+ _session->midi_panic ();
}
- }
- session_removed.signal();
+ } else {
+ /* fade out done */
+ _session = 0;
+ session_removal_countdown = -1; // reset to "not in progress"
+ session_remove_pending = false;
+ session_removed.signal(); // wakes up thread that initiated session removal
+ }
}
if (_session == 0) {
+
if (!_freewheeling) {
MIDI::Manager::instance()->cycle_start(nframes);
MIDI::Manager::instance()->cycle_end();
@@ -574,8 +589,6 @@ AudioEngine::process_callback (pframes_t nframes)
if (_session->silent()) {
- boost::shared_ptr<Ports> p = ports.reader();
-
for (Ports::iterator i = p->begin(); i != p->end(); ++i) {
if (i->second->sends_output()) {
@@ -584,6 +597,34 @@ AudioEngine::process_callback (pframes_t nframes)
}
}
+ if (session_remove_pending && session_removal_countdown) {
+
+ for (Ports::iterator i = p->begin(); i != p->end(); ++i) {
+
+ if (i->second->sends_output()) {
+
+ boost::shared_ptr<AudioPort> ap = boost::dynamic_pointer_cast<AudioPort> (i->second);
+ if (ap) {
+ Sample* s = ap->engine_get_whole_audio_buffer ();
+ gain_t g = session_removal_gain;
+
+ for (pframes_t n = 0; n < nframes; ++n) {
+ *s++ *= g;
+ g -= session_removal_gain_step;
+ }
+ }
+ }
+ }
+
+ if (session_removal_countdown > nframes) {
+ session_removal_countdown -= nframes;
+ } else {
+ session_removal_countdown = 0;
+ }
+
+ session_removal_gain -= (nframes * session_removal_gain_step);
+ }
+
// Finalize ports
for (Ports::iterator i = p->begin(); i != p->end(); ++i) {
diff --git a/libs/ardour/session_process.cc b/libs/ardour/session_process.cc
index 3936423b14..585d0927f2 100644
--- a/libs/ardour/session_process.cc
+++ b/libs/ardour/session_process.cc
@@ -158,7 +158,7 @@ Session::process_routes (pframes_t nframes, bool& need_butler)
const framepos_t start_frame = _transport_frame;
const framepos_t end_frame = _transport_frame + floor (nframes * _transport_speed);
-
+
if (_process_graph) {
DEBUG_TRACE(DEBUG::ProcessThreads,"calling graph/process-routes\n");
_process_graph->process_routes (nframes, start_frame, end_frame, declick, need_butler);