Mercurial > hg > svapp
changeset 489:111e976f9ed4 3.0-integration
Merge from branch "recording"
author | Chris Cannam |
---|---|
date | Thu, 17 Sep 2015 13:46:07 +0100 |
parents | 52c0aff69478 (current diff) 66b92c188cbd (diff) |
children | b3568eca53ba a4d90cf2bb79 |
files | framework/MainWindowBase.cpp |
diffstat | 4 files changed, 114 insertions(+), 17 deletions(-) [+] |
line wrap: on
line diff
--- a/audio/AudioRecordTarget.cpp Thu Aug 20 13:15:19 2015 +0100 +++ b/audio/AudioRecordTarget.cpp Thu Sep 17 13:46:07 2015 +0100 @@ -27,6 +27,7 @@ m_clientName(clientName.toUtf8().data()), m_recording(false), m_recordSampleRate(44100), + m_frameCount(0), m_model(0) { } @@ -55,9 +56,30 @@ void AudioRecordTarget::putSamples(int nframes, float **samples) { - QMutexLocker locker(&m_mutex); //!!! bad here - if (!m_recording) return; - m_model->addSamples(samples, nframes); + bool secChanged = false; + sv_frame_t frameToEmit = 0; + + { + QMutexLocker locker(&m_mutex); //!!! bad here + if (!m_recording) return; + + m_model->addSamples(samples, nframes); + + sv_frame_t priorFrameCount = m_frameCount; + m_frameCount += nframes; + + RealTime priorRT = RealTime::frame2RealTime + (priorFrameCount, m_recordSampleRate); + RealTime postRT = RealTime::frame2RealTime + (m_frameCount, m_recordSampleRate); + + secChanged = (postRT.sec > priorRT.sec); + if (secChanged) frameToEmit = m_frameCount; + } + + if (secChanged) { + emit recordDurationChanged(frameToEmit, m_recordSampleRate); + } } void @@ -75,6 +97,19 @@ } } +QString +AudioRecordTarget::getRecordFolder() +{ + QDir parent(TempDirectory::getInstance()->getContainingPath()); + QString subdirname = "recorded"; //!!! tr? + if (!parent.mkpath(subdirname)) { + cerr << "ERROR: AudioRecordTarget::getRecordFolder: Failed to create recorded dir in \"" << parent.canonicalPath() << "\"" << endl; + return ""; + } else { + return parent.filePath(subdirname); + } +} + WritableWaveFileModel * AudioRecordTarget::startRecording() { @@ -86,16 +121,11 @@ } m_model = 0; + m_frameCount = 0; - QDir parent(TempDirectory::getInstance()->getContainingPath()); - QDir recordedDir; - QString subdirname = "recorded"; //!!! tr? - if (!parent.mkpath(subdirname)) { - cerr << "ERROR: AudioRecordTarget::startRecording: Failed to create recorded dir in \"" << parent.canonicalPath() << "\"" << endl; - return 0; - } else { - recordedDir = parent.filePath(subdirname); - } + QString folder = getRecordFolder(); + if (folder == "") return 0; + QDir recordedDir(folder); QDateTime now = QDateTime::currentDateTime();
--- a/audio/AudioRecordTarget.h Thu Aug 20 13:15:19 2015 +0100 +++ b/audio/AudioRecordTarget.h Thu Sep 17 13:46:07 2015 +0100 @@ -51,12 +51,15 @@ virtual void audioProcessingOverload() { } + QString getRecordFolder(); + bool isRecording() const { return m_recording; } WritableWaveFileModel *startRecording(); // caller takes ownership void stopRecording(); signals: void recordStatusChanged(bool recording); + void recordDurationChanged(sv_frame_t, sv_samplerate_t); // emitted occasionally protected slots: void modelAboutToBeDeleted(); @@ -66,6 +69,7 @@ std::string m_clientName; bool m_recording; sv_samplerate_t m_recordSampleRate; + sv_frame_t m_frameCount; QString m_audioFileName; WritableWaveFileModel *m_model; QMutex m_mutex;
--- a/framework/MainWindowBase.cpp Thu Aug 20 13:15:19 2015 +0100 +++ b/framework/MainWindowBase.cpp Thu Sep 17 13:46:07 2015 +0100 @@ -155,6 +155,7 @@ m_lastPlayStatusSec(0), m_initialDarkBackground(false), m_defaultFfwdRwdStep(2, 0), + m_audioRecordMode(RecordCreateAdditionalModel), m_statusLabel(0), m_menuShortcutMapper(0) { @@ -230,6 +231,8 @@ if (m_soundOptions & WithAudioInput) { m_recordTarget = new AudioRecordTarget(m_viewManager, QApplication::applicationName()); + connect(m_recordTarget, SIGNAL(recordDurationChanged(sv_frame_t, sv_samplerate_t)), + this, SLOT(recordDurationChanged(sv_frame_t, sv_samplerate_t))); } connect(m_playSource, SIGNAL(sampleRateMismatch(sv_samplerate_t, sv_samplerate_t, bool)), @@ -611,7 +614,7 @@ emit canMeasureLayer(haveCurrentLayer); emit canSelect(haveMainModel && haveCurrentPane); emit canPlay(haveMainModel && havePlayTarget); - emit canRecord(m_soundOptions & WithAudioInput); // always possible then + emit canRecord(m_recordTarget != 0); emit canFfwd(haveMainModel); emit canRewind(haveMainModel); emit canPaste(haveClipboardContents); @@ -2195,6 +2198,7 @@ if (m_soundOptions & WithAudioInput) { m_audioIO = breakfastquay::AudioFactory:: createCallbackIO(m_recordTarget, m_playSource); + m_audioIO->suspend(); // start in suspended state m_playSource->setSystemPlaybackTarget(m_audioIO); } else { m_playTarget = breakfastquay::AudioFactory:: @@ -2656,6 +2660,7 @@ QAction *action = qobject_cast<QAction *>(sender()); if (action) action->setChecked(false); } else { + if (m_audioIO) m_audioIO->resume(); playbackFrameChanged(m_viewManager->getPlaybackFrame()); m_playSource->play(m_viewManager->getPlaybackFrame()); } @@ -2683,6 +2688,12 @@ return; } + if (m_audioRecordMode == RecordReplaceSession) { + if (!checkSaveModified()) return; + } + + if (m_audioIO) m_audioIO->resume(); + WritableWaveFileModel *model = m_recordTarget->startRecording(); if (!model) { cerr << "ERROR: MainWindowBase::record: Recording failed" << endl; @@ -2696,10 +2707,10 @@ //!!! ??? return; } - + PlayParameterRepository::getInstance()->addPlayable(model); - - if (!getMainModel()) { + + if (m_audioRecordMode == RecordReplaceSession || !getMainModel()) { //!!! duplication with openAudio here @@ -3014,6 +3025,8 @@ m_playSource->stop(); + if (m_audioIO) m_audioIO->suspend(); + if (m_paneStack && m_paneStack->getCurrentPane()) { updateVisibleRangeDisplay(m_paneStack->getCurrentPane()); } else { @@ -3352,6 +3365,17 @@ } void +MainWindowBase::recordDurationChanged(sv_frame_t frame, sv_samplerate_t rate) +{ + RealTime duration = RealTime::frame2RealTime(frame, rate); + QString durStr = duration.toSecText().c_str(); + + m_myStatusMessage = tr("Recording: %1").arg(durStr); + + getStatusLabel()->setText(m_myStatusMessage); +} + +void MainWindowBase::globalCentreFrameChanged(sv_frame_t ) { if ((m_playSource && m_playSource->isPlaying()) || !getMainModel()) return; @@ -3613,4 +3637,30 @@ #endif } - +void +MainWindowBase::openLocalFolder(QString path) +{ + QDir d(path); + if (d.exists()) { + QStringList args; + QString path = d.canonicalPath(); +#if defined Q_OS_WIN32 + // Although the Win32 API is quite happy to have + // forward slashes as directory separators, Windows + // Explorer is not + path = path.replace('/', '\\'); + args << path; + QProcess::execute("c:/windows/explorer.exe", args); +#else + args << path; + QProcess::execute( +#if defined Q_OS_MAC + "/usr/bin/open", +#else + "/usr/bin/xdg-open", +#endif + args); +#endif + } +} +
--- a/framework/MainWindowBase.h Thu Aug 20 13:15:19 2015 +0100 +++ b/framework/MainWindowBase.h Thu Sep 17 13:46:07 2015 +0100 @@ -108,6 +108,11 @@ FileOpenWrongMode // attempted to open layer when no main model present }; + enum AudioRecordMode { + RecordReplaceSession, + RecordCreateAdditionalModel + }; + virtual FileOpenStatus open(FileSource source, AudioFileOpenMode = AskUser); virtual FileOpenStatus openPath(QString fileOrUrl, AudioFileOpenMode = AskUser); virtual FileOpenStatus openAudio(FileSource source, AudioFileOpenMode = AskUser, QString templateName = ""); @@ -130,6 +135,10 @@ m_defaultFfwdRwdStep = step; } + void setAudioRecordMode(AudioRecordMode mode) { + m_audioRecordMode = mode; + } + signals: // Used to toggle the availability of menu actions void canAddPane(bool); @@ -238,6 +247,7 @@ virtual void viewCentreFrameChanged(View *, sv_frame_t); virtual void viewZoomLevelChanged(View *, int, bool); virtual void outputLevelsChanged(float, float) = 0; + virtual void recordDurationChanged(sv_frame_t, sv_samplerate_t); virtual void currentPaneChanged(Pane *); virtual void currentLayerChanged(Pane *, Layer *); @@ -360,6 +370,8 @@ RealTime m_defaultFfwdRwdStep; + AudioRecordMode m_audioRecordMode; + mutable QLabel *m_statusLabel; QLabel *getStatusLabel() const; @@ -441,6 +453,7 @@ virtual void createAudioIO(); virtual void openHelpUrl(QString url); + virtual void openLocalFolder(QString path); virtual void setupMenus() = 0; virtual void updateVisibleRangeDisplay(Pane *p) const = 0;