Mercurial > hg > svapp
changeset 714:fe268c16ae28
Make it possible to open an audio device for playback and upgrade it to I/O later on - avoiding the Mac microphone-permission dialog until we are actually wanting to record
author | Chris Cannam |
---|---|
date | Wed, 16 Oct 2019 15:26:59 +0100 |
parents | ce698f8d0831 |
children | ec8f21a20fa7 |
files | framework/MainWindowBase.cpp framework/MainWindowBase.h |
diffstat | 2 files changed, 72 insertions(+), 34 deletions(-) [+] |
line wrap: on
line diff
--- a/framework/MainWindowBase.cpp Fri Oct 11 13:40:54 2019 +0100 +++ b/framework/MainWindowBase.cpp Wed Oct 16 15:26:59 2019 +0100 @@ -137,13 +137,15 @@ #undef Window #endif -MainWindowBase::MainWindowBase(SoundOptions soundOptions, +MainWindowBase::MainWindowBase(AudioMode audioMode, + MIDIMode midiMode, PaneStack::Options paneStackOptions) : m_document(nullptr), m_paneStack(nullptr), m_viewManager(nullptr), m_timeRulerLayer(nullptr), - m_soundOptions(soundOptions), + m_audioMode(audioMode), + m_midiMode(midiMode), m_playSource(nullptr), m_recordTarget(nullptr), m_resamplerWrapper(nullptr), @@ -171,12 +173,6 @@ SVDEBUG << "MainWindowBase::MainWindowBase" << endl; - if (m_soundOptions & WithAudioInput) { - if (!(m_soundOptions & WithAudioOutput)) { - SVCERR << "WARNING: MainWindowBase: WithAudioInput requires WithAudioOutput -- recording will not work" << endl; - } - } - qRegisterMetaType<sv_frame_t>("sv_frame_t"); qRegisterMetaType<sv_samplerate_t>("sv_samplerate_t"); qRegisterMetaType<ModelId>("ModelId"); @@ -250,7 +246,8 @@ m_playSource = new AudioCallbackPlaySource (m_viewManager, QApplication::applicationName()); - if (m_soundOptions & WithAudioInput) { + if (m_audioMode == AUDIO_PLAYBACK_NOW_RECORD_LATER || + m_audioMode == AUDIO_PLAYBACK_AND_RECORD) { SVDEBUG << "MainWindowBase: Creating record target" << endl; m_recordTarget = new AudioCallbackRecordTarget (m_viewManager, QApplication::applicationName()); @@ -303,7 +300,7 @@ m_labeller = new Labeller(labellerType); m_labeller->setCounterCycleSize(cycle); - if (m_soundOptions & WithMIDIInput) { + if (m_midiMode == MIDI_LISTEN) { SVDEBUG << "MainWindowBase: Creating MIDI input" << endl; m_midiInput = new MIDIInput(QApplication::applicationName(), this); } @@ -739,12 +736,21 @@ // system play target or I/O exists, we can record even if no // record source (i.e. audioIO) exists because we can record into // an empty session before the audio device has been - // opened. However, if there is no record *target* then recording - // was actively disabled (flag not set in m_soundOptions). And if - // we have a play target instead of an audioIO, then we must have - // tried to open the device but failed to find any capture source. + // opened. + // + // However, if there is no record *target* then recording was + // actively disabled via the audio mode setting. + // + // If we have a play target instead of an audioIO, then if the + // audio mode is AUDIO_PLAYBACK_NOW_RECORD_LATER, we are still + // expecting to open the IO on demand, but if it is + // AUDIO_PLAYBACK_AND_RECORD then we must have tried to open the + // device and failed to find any capture source. + // bool recordDisabled = (m_recordTarget == nullptr); - bool recordDeviceFailed = (m_playTarget != nullptr && m_audioIO == nullptr); + bool recordDeviceFailed = + (m_audioMode == AUDIO_PLAYBACK_AND_RECORD && + (m_playTarget != nullptr && m_audioIO == nullptr)); emit canRecord(!recordDisabled && !recordDeviceFailed); } @@ -2503,8 +2509,8 @@ static AudioLogCallback audioLogCallback; breakfastquay::AudioFactory::setLogCallback(&audioLogCallback); - - if (!(m_soundOptions & WithAudioOutput)) return; + + if (m_audioMode == AUDIO_NONE) return; QSettings settings; settings.beginGroup("Preferences"); @@ -2541,7 +2547,7 @@ std::string errorString; - if (m_soundOptions & WithAudioInput) { + if (m_audioMode == AUDIO_PLAYBACK_AND_RECORD) { m_audioIO = breakfastquay::AudioFactory:: createCallbackIO(m_recordTarget, m_resamplerWrapper, preference, errorString); @@ -2579,7 +2585,8 @@ } else { firstBit = tr("<b>No audio available</b><p>Could not open audio device: %1</p>").arg(error); } - if (m_soundOptions & WithAudioInput) { + if (m_audioMode == AUDIO_PLAYBACK_NOW_RECORD_LATER || + m_audioMode == AUDIO_PLAYBACK_AND_RECORD) { secondBit = tr("<p>Automatic audio device detection failed. Audio playback and recording will not be available during this session.</p>"); } else { secondBit = tr("<p>Automatic audio device detection failed. Audio playback will not be available during this session.</p>"); @@ -2593,7 +2600,8 @@ } else { firstBit = tr("<b>No audio available</b><p>Failed to open your preferred audio driver (\"%1\"): %2.</p>").arg(driverName).arg(error); } - if (m_soundOptions & WithAudioInput) { + if (m_audioMode == AUDIO_PLAYBACK_NOW_RECORD_LATER || + m_audioMode == AUDIO_PLAYBACK_AND_RECORD) { secondBit = tr("<p>Audio playback and recording will not be available during this session.</p>"); } else { secondBit = tr("<p>Audio playback will not be available during this session.</p>"); @@ -3191,7 +3199,7 @@ { QAction *action = qobject_cast<QAction *>(sender()); - if (!(m_soundOptions & WithAudioInput)) { + if (m_audioMode == AUDIO_NONE || m_audioMode == AUDIO_PLAYBACK_ONLY) { if (action) action->setChecked(false); return; } @@ -3201,6 +3209,14 @@ return; } + if (m_audioMode == AUDIO_PLAYBACK_NOW_RECORD_LATER) { + SVDEBUG << "MainWindowBase::record: upgrading from " + << "AUDIO_PLAYBACK_NOW_RECORD_LATER to " + << "AUDIO_PLAYBACK_AND_RECORD" << endl; + m_audioMode = AUDIO_PLAYBACK_AND_RECORD; + deleteAudioIO(); + } + if (!m_audioIO) { SVDEBUG << "MainWindowBase::record: about to create audio IO" << endl; createAudioIO(); @@ -4090,8 +4106,7 @@ updateDescriptionLabel(); auto model = ModelById::getAs<WaveFileModel>(modelId); if (model) m_viewManager->setMainModelSampleRate(model->getSampleRate()); - if (model && !(m_playTarget || m_audioIO) && - (m_soundOptions & WithAudioOutput)) { + if (model && !(m_playTarget || m_audioIO) && (m_audioMode != AUDIO_NONE)) { createAudioIO(); } }
--- a/framework/MainWindowBase.h Fri Oct 11 13:40:54 2019 +0100 +++ b/framework/MainWindowBase.h Wed Oct 16 15:26:59 2019 +0100 @@ -93,17 +93,39 @@ Q_OBJECT public: - enum SoundOption { - WithAudioOutput = 0x01, - WithAudioInput = 0x02, - WithMIDIInput = 0x04, - WithEverything = 0xff, - WithNothing = 0x00 + /** + * Determine what kind of audio device to open when the first + * model is loaded or record() is called. + */ + enum AudioMode { + + /// Open no audio device, ever + AUDIO_NONE, + + /// Open for playback, never for recording + AUDIO_PLAYBACK_ONLY, + + /// Open for playback when model loaded, switch to I/O if record called + AUDIO_PLAYBACK_NOW_RECORD_LATER, + + /// Open for I/O as soon as model loaded or record called + AUDIO_PLAYBACK_AND_RECORD }; - typedef int SoundOptions; - - MainWindowBase(SoundOptions soundOptions = WithEverything, - PaneStack::Options paneStackOptions = 0x0); + + /** + * Determine whether to open a MIDI input device. + */ + enum MIDIMode { + + /// Open no MIDI device + MIDI_NONE, + + /// Open a MIDI device and listen for MIDI input + MIDI_LISTEN + }; + + MainWindowBase(AudioMode audioMode, MIDIMode midiMode, + PaneStack::Options paneStackOptions); virtual ~MainWindowBase(); enum AudioFileOpenMode { @@ -365,7 +387,8 @@ ViewManager *m_viewManager; Layer *m_timeRulerLayer; - SoundOptions m_soundOptions; + AudioMode m_audioMode; + MIDIMode m_midiMode; AudioCallbackPlaySource *m_playSource; AudioCallbackRecordTarget *m_recordTarget;