changeset 477:411e019474e5 recording

OK, we can record -- sort of
author Chris Cannam
date Tue, 18 Aug 2015 16:47:54 +0100
parents f4d1fa41b94b
children 1f86bf6644b8
files audio/AudioRecordTarget.cpp audio/AudioRecordTarget.h framework/MainWindowBase.cpp framework/MainWindowBase.h
diffstat 4 files changed, 104 insertions(+), 25 deletions(-) [+]
line wrap: on
line diff
--- a/audio/AudioRecordTarget.cpp	Tue Aug 18 15:00:34 2015 +0100
+++ b/audio/AudioRecordTarget.cpp	Tue Aug 18 16:47:54 2015 +0100
@@ -17,7 +17,7 @@
 #include "base/ViewManagerBase.h"
 #include "base/TempDirectory.h"
 
-#include "data/fileio/WavFileWriter.h"
+#include "data/model/WritableWaveFileModel.h"
 
 #include <QDir>
 
@@ -27,14 +27,13 @@
     m_clientName(clientName.toUtf8().data()),
     m_recording(false),
     m_recordSampleRate(44100),
-    m_writer(0)
+    m_model(0)
 {
 }
 
 AudioRecordTarget::~AudioRecordTarget()
 {
     QMutexLocker locker(&m_mutex);
-    delete m_writer;
 }
 
 void
@@ -58,7 +57,7 @@
 {
     QMutexLocker locker(&m_mutex); //!!! bad here
     if (!m_recording) return;
-    m_writer->writeSamples(samples, nframes);
+    m_model->addSamples(samples, nframes);
 }
 
 void
@@ -66,21 +65,34 @@
 {
 }
 
-QString
+void
+AudioRecordTarget::modelAboutToBeDeleted()
+{
+    QMutexLocker locker(&m_mutex);
+    if (sender() == m_model) {
+        m_model = 0;
+        m_recording = false;
+    }
+}
+
+WritableWaveFileModel *
 AudioRecordTarget::startRecording()
 {
+    {
     QMutexLocker locker(&m_mutex);
     if (m_recording) {
         cerr << "WARNING: AudioRecordTarget::startRecording: We are already recording" << endl;
-        return "";
+        return 0;
     }
 
+    m_model = 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 "";
+        return 0;
     } else {
         recordedDir = parent.filePath(subdirname);
     }
@@ -90,37 +102,41 @@
     QString filename = "recorded.wav"; //!!!
 
     m_audioFileName = recordedDir.filePath(filename);
-        
-    m_writer = new WavFileWriter(m_audioFileName,
-                                 m_recordSampleRate,
-                                 2,
-                                 WavFileWriter::WriteToTarget);
 
-    if (!m_writer->isOK()) {
-        cerr << "ERROR: AudioRecordTarget::startRecording: Recording failed: "
-             << m_writer->getError() << endl;
+    m_model = new WritableWaveFileModel(m_recordSampleRate, 2, m_audioFileName);
+
+    if (!m_model->isOK()) {
+        cerr << "ERROR: AudioRecordTarget::startRecording: Recording failed"
+             << endl;
         //!!! and throw?
-        delete m_writer;
-        return "";
+        delete m_model;
+        m_model = 0;
+        return 0;
     }
 
     m_recording = true;
-    
-    return m_audioFileName;
+    }
+
+    emit recordStatusChanged(true);
+    return m_model;
 }
 
 void
 AudioRecordTarget::stopRecording()
 {
+    {
     QMutexLocker locker(&m_mutex);
     if (!m_recording) {
         cerr << "WARNING: AudioRecordTarget::startRecording: Not recording" << endl;
         return;
     }
 
-    m_writer->close();
-    delete m_writer;
+    m_model->setCompletion(100);
+    m_model = 0;
     m_recording = false;
+    }
+
+    emit recordStatusChanged(false);
 }
 
 
--- a/audio/AudioRecordTarget.h	Tue Aug 18 15:00:34 2015 +0100
+++ b/audio/AudioRecordTarget.h	Tue Aug 18 16:47:54 2015 +0100
@@ -25,7 +25,7 @@
 #include "base/BaseTypes.h"
 
 class ViewManagerBase;
-class WavFileWriter;
+class WritableWaveFileModel;
 
 class AudioRecordTarget : public QObject,
 			  public breakfastquay::ApplicationRecordTarget
@@ -51,8 +51,15 @@
 
     virtual void audioProcessingOverload() { }
 
-    QString startRecording(); // and return the audio filename
+    bool isRecording() const { return m_recording; }
+    WritableWaveFileModel *startRecording(); // caller takes ownership
     void stopRecording();
+
+signals:
+    void recordStatusChanged(bool recording);
+
+protected slots:
+    void modelAboutToBeDeleted();
     
 private:
     ViewManagerBase *m_viewManager;
@@ -60,7 +67,7 @@
     bool m_recording;
     sv_samplerate_t m_recordSampleRate;
     QString m_audioFileName;
-    WavFileWriter *m_writer;
+    WritableWaveFileModel *m_model;
     QMutex m_mutex;
 };
 
--- a/framework/MainWindowBase.cpp	Tue Aug 18 15:00:34 2015 +0100
+++ b/framework/MainWindowBase.cpp	Tue Aug 18 16:47:54 2015 +0100
@@ -19,6 +19,7 @@
 #include "view/Pane.h"
 #include "view/PaneStack.h"
 #include "data/model/WaveFileModel.h"
+#include "data/model/WritableWaveFileModel.h"
 #include "data/model/SparseOneDimensionalModel.h"
 #include "data/model/NoteModel.h"
 #include "data/model/FlexiNoteModel.h"
@@ -2654,7 +2655,7 @@
 void
 MainWindowBase::play()
 {
-    if (m_playSource->isPlaying()) {
+    if (m_recordTarget->isRecording() || m_playSource->isPlaying()) {
         stop();
     } else {
         playbackFrameChanged(m_viewManager->getPlaybackFrame());
@@ -2663,6 +2664,56 @@
 }
 
 void
+MainWindowBase::record()
+{
+    if (!m_recordTarget) {
+        //!!! report
+        return;
+    }
+
+    if (m_recordTarget->isRecording()) {
+        m_recordTarget->stopRecording();
+        return;
+    }
+
+    WritableWaveFileModel *model = m_recordTarget->startRecording();
+    if (!model) {
+        cerr << "ERROR: MainWindowBase::record: Recording failed" << endl;
+        //!!! report
+        return;
+    }
+
+    if (!model->isOK()) {
+        m_recordTarget->stopRecording();
+        delete model;
+        //!!! ???
+        return;
+    }
+
+    CommandHistory::getInstance()->startCompoundOperation
+        (tr("Import Recorded Audio"), true);
+
+    m_document->addImportedModel(model);
+
+    AddPaneCommand *command = new AddPaneCommand(this);
+    CommandHistory::getInstance()->addCommand(command);
+
+    Pane *pane = command->getPane();
+
+    if (m_timeRulerLayer) {
+        m_document->addLayerToView(pane, m_timeRulerLayer);
+    }
+
+    Layer *newLayer = m_document->createImportedLayer(model);
+
+    if (newLayer) {
+        m_document->addLayerToView(pane, newLayer);
+    }
+	
+    CommandHistory::getInstance()->endCompoundOperation();
+}
+
+void
 MainWindowBase::ffwd()
 {
     if (!getMainModel()) return;
@@ -2890,6 +2941,10 @@
 void
 MainWindowBase::stop()
 {
+    if (m_recordTarget->isRecording()) {
+        m_recordTarget->stopRecording();
+    }
+        
     m_playSource->stop();
 
     if (m_paneStack && m_paneStack->getCurrentPane()) {
--- a/framework/MainWindowBase.h	Tue Aug 18 15:00:34 2015 +0100
+++ b/framework/MainWindowBase.h	Tue Aug 18 16:47:54 2015 +0100
@@ -210,6 +210,7 @@
     virtual void ffwdEnd();
     virtual void rewind();
     virtual void rewindStart();
+    virtual void record();
     virtual void stop();
 
     virtual void ffwdSimilar();