diff --git a/data/rc/rosegardenmainwindow.rc b/data/rc/rosegardenmainwindow.rc
index d83c82932..39cc1e315 100644
--- a/data/rc/rosegardenmainwindow.rc
+++ b/data/rc/rosegardenmainwindow.rc
@@ -38,6 +38,8 @@
+
+
@@ -535,6 +537,7 @@
+
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index dc44f789f..d548e7ae4 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -579,6 +579,7 @@ set(rg_CPPS
sound/Resampler.cpp
sound/ExternalController.cpp
sound/KorgNanoKontrol2.cpp
+ sound/WAVExporter.cpp
commands/notation/ResetDisplacementsCommand.cpp
commands/notation/RemoveNotationQuantizeCommand.cpp
commands/notation/AddMarkCommand.cpp
diff --git a/src/gui/application/RosegardenMainWindow.cpp b/src/gui/application/RosegardenMainWindow.cpp
index 847d871b8..20eab7953 100644
--- a/src/gui/application/RosegardenMainWindow.cpp
+++ b/src/gui/application/RosegardenMainWindow.cpp
@@ -271,9 +271,6 @@ RosegardenMainWindow::RosegardenMainWindow(bool enableSound,
m_recentFiles(),
m_sequencerThread(nullptr),
m_sequencerCheckedIn(false),
-#ifdef HAVE_LIBJACK
- m_jackProcess(nullptr),
-#endif
m_cpuBar(nullptr),
m_zoomSlider(nullptr),
m_zoomLabel(nullptr),
@@ -747,6 +744,7 @@ RosegardenMainWindow::setupActions()
createAction("file_export_midi", SLOT(slotExportMIDI()));
createAction("file_export_lilypond", SLOT(slotExportLilyPond()));
createAction("file_export_musicxml", SLOT(slotExportMusicXml()));
+ createAction("file_export_wav", SLOT(slotExportWAV()));
createAction("file_export_csound", SLOT(slotExportCsound()));
createAction("file_export_mup", SLOT(slotExportMup()));
createAction("file_print_lilypond", SLOT(slotPrintLilyPond()));
@@ -5080,70 +5078,6 @@ RosegardenMainWindow::slotTestStartupTester()
return ;
}
-/* QStringList missingFeatures;
- QStringList allMissing;
-
- QStringList missing;
-
-#ifdef HAVE_LIBJACK
- if (m_seqManager && (m_seqManager->getSoundDriverStatus() & AUDIO_OK)) {
-
- m_haveAudioImporter = m_startupTester->haveAudioFileImporter(&missing);
-
- if (!m_haveAudioImporter) {
- missingFeatures.push_back(tr("General audio file import and conversion"));
- if (missing.count() == 0) {
- allMissing.push_back(tr("The Rosegarden Audio File Importer helper script"));
- } else {
- for (int i = 0; i < missing.count(); ++i) {
- if (missingFeatures.count() > 1) {
- allMissing.push_back(tr("%1 - for audio file import").arg(missing[i]));
- } else {
- allMissing.push_back(missing[i]);
- }
- }
- }
- }
- }
-#endif
-
- if (missingFeatures.count() > 0) {
- QString message = tr("Helper programs not found
Rosegarden could not find one or more helper programs which it needs to provide some features. The following features will not be available:
");
- message += tr("");
- for (int i = 0; i < missingFeatures.count(); ++i) {
- message += tr("- %1
").arg(missingFeatures[i]);
- }
- message += tr("
");
- message += tr("To fix this, you should install the following additional programs:
");
- message += tr("");
- for (int i = 0; i < allMissing.count(); ++i) {
- message += tr("- %1
").arg(allMissing[i]);
- }
- message += tr("
");
-
- awaitDialogClearance();
-
- QString shortMessage = tr("Helper programs not found");
-
-// QMessageBox info(m_view);
-// info.setText(shortMessage);
-// info.setInformativeText(message);
-// info.setStandardButtons(QMessageBox::Ok);
-// info.setDefaultButton(QMessageBox::Ok);
-// info.setIcon(QMessageBox::Warning);
-//
-// if (!DialogSuppressor::shouldSuppress
-// (&info, "startuphelpersmissing")) {
-// info.exec();
-// }
-
- // Looks like Thorn will have to keep the startup test for
- // audiofile-importer around indefinitely, and so we need to move that
- // irritating @#@^@#^ dialog into the warning widget, and get it out of
- // my face before I punch it right in the nose.
- m_warningWidget->queueMessage(shortMessage, message);
- }*/
-
m_startupTester->wait();
delete m_startupTester;
m_startupTester = nullptr;
@@ -5535,6 +5469,49 @@ RosegardenMainWindow::slotExportMusicXml()
exportMusicXmlFile(fileName);
}
+void
+RosegardenMainWindow::slotExportWAV()
+{
+ RG_DEBUG << "slotExportWAV()";
+
+ if (!m_seqManager)
+ return;
+
+ if (!(m_seqManager->getSoundDriverStatus() & AUDIO_OK)) {
+ QMessageBox::information(
+ this, // parent
+ tr("Rosegarden"), // title
+ tr("Unable to export WAV without JACK running.")); // text
+ return;
+ }
+
+ QString fileName = FileDialog::getSaveFileName(
+ this, // parent
+ tr("Rosegarden"), // caption
+ "", // dir
+ "", // defaultName
+ tr("WAV files") + " (*.wav)"); // filter
+
+ if (fileName.isEmpty())
+ return;
+
+ if (fileName.right(4).toLower() != ".wav")
+ fileName += ".wav";
+
+ QString msg = tr(
+ "Press play to start exporting to\n"
+ "%1\n"
+ "Press stop to stop export.\n"
+ "Only audio and synth plugin tracks will be exported").arg(fileName);
+
+ QMessageBox::information(
+ this, // parent
+ tr("Rosegarden"), // title
+ msg); // text
+
+ m_seqManager->setExportWavFile(fileName);
+}
+
void
RosegardenMainWindow::exportMusicXmlFile(QString file)
{
diff --git a/src/gui/application/RosegardenMainWindow.h b/src/gui/application/RosegardenMainWindow.h
index b6c872170..99a78f964 100644
--- a/src/gui/application/RosegardenMainWindow.h
+++ b/src/gui/application/RosegardenMainWindow.h
@@ -657,6 +657,11 @@ public slots:
*/
void slotExportMusicXml();
+ /**
+ * Export (render) file to audio (only audio and synth plugins)
+ */
+ void slotExportWAV();
+
/**
* closes all open windows by calling close() on each memberList
* item until the list is empty, then quits the application. If
@@ -1567,10 +1572,6 @@ protected slots:
SequencerThread *m_sequencerThread;
bool m_sequencerCheckedIn;
-#ifdef HAVE_LIBJACK
- QProcess *m_jackProcess;
-#endif // HAVE_LIBJACK
-
/// CPU meter in the main window status bar.
/**
* This is NOT a general-purpose progress indicator. You want to use
diff --git a/src/gui/dialogs/SelectBankDialog.cpp b/src/gui/dialogs/SelectBankDialog.cpp
index ebebfcc82..555be3dee 100644
--- a/src/gui/dialogs/SelectBankDialog.cpp
+++ b/src/gui/dialogs/SelectBankDialog.cpp
@@ -16,7 +16,7 @@
*/
#define RG_MODULE_STRING "[SelectBankDialog]"
-//#define RG_NO_DEBUG_PRINT
+#define RG_NO_DEBUG_PRINT
#include "SelectBankDialog.h"
diff --git a/src/gui/seqmanager/SequenceManager.cpp b/src/gui/seqmanager/SequenceManager.cpp
index 3fae5ad93..7bf9134d7 100644
--- a/src/gui/seqmanager/SequenceManager.cpp
+++ b/src/gui/seqmanager/SequenceManager.cpp
@@ -55,6 +55,7 @@
#include "sound/MappedEventList.h"
#include "sound/MappedEvent.h"
#include "sound/MappedInstrument.h"
+#include "sound/WAVExporter.h"
#include "misc/Preferences.h"
#include "rosegarden-version.h" // for VERSION
@@ -95,8 +96,13 @@ SequenceManager::SequenceManager() :
m_recordTime(new QElapsedTimer()),
m_lastTransportStartPosition(0),
m_sampleRate(0),
- m_tempo(0)
+ m_tempo(0),
+ m_wavExporter(nullptr),
+ m_exportTimer(new QTimer(this))
{
+ // The timer is started when required
+ connect(m_exportTimer, &QTimer::timeout,
+ this, &SequenceManager::slotExportUpdate);
}
SequenceManager::~SequenceManager()
@@ -105,6 +111,10 @@ SequenceManager::~SequenceManager()
if (m_doc)
m_doc->getComposition().removeObserver(this);
+
+ if (m_wavExporter) {
+ delete m_wavExporter;
+ }
}
void
@@ -1080,6 +1090,19 @@ void SequenceManager::slotLoopChanged()
}
}
+void SequenceManager::slotExportUpdate()
+{
+ // The timer is only run when the m_compositionExportManager is set
+ m_wavExporter->update();
+ if (m_wavExporter->isComplete()) {
+ RG_DEBUG << "deleting completed export manager";
+ delete m_wavExporter;
+ m_wavExporter = nullptr;
+ // timer no longer needed
+ m_exportTimer->stop();
+ }
+}
+
bool SequenceManager::inCountIn(const RealTime &time) const
{
if (m_transportStatus == RECORDING ||
@@ -1866,6 +1889,25 @@ SequenceManager::getSampleRate() const
return m_sampleRate;
}
+void
+SequenceManager::setExportWavFile(const QString& fileName)
+{
+ RG_DEBUG << "setExportWavFile" << fileName;
+ if (m_wavExporter) {
+ RG_DEBUG << "replacing previous export manager";
+ delete m_wavExporter;
+ }
+ m_wavExporter = new WAVExporter(fileName);
+ // If creation of the WAVExporter has failed, bail.
+ if (!m_wavExporter->isOK())
+ return;
+
+ // and install in the driver
+ RosegardenSequencer::getInstance()->installExporter(m_wavExporter);
+ // and start the timer
+ m_exportTimer->start(50);
+}
+
bool
SequenceManager::shouldWarnForImpreciseTimer()
{
diff --git a/src/gui/seqmanager/SequenceManager.h b/src/gui/seqmanager/SequenceManager.h
index 4180dfa77..4773db35d 100644
--- a/src/gui/seqmanager/SequenceManager.h
+++ b/src/gui/seqmanager/SequenceManager.h
@@ -51,6 +51,7 @@ class CountdownDialog;
class CompositionMapper;
class AudioManagerDialog;
class MappedBufMetaIterator;
+class WAVExporter;
/**
@@ -261,6 +262,9 @@ class ROSEGARDENPRIVATE_EXPORT SequenceManager :
/// Get sample rate from RosegardenSequencer.
int getSampleRate() const;
+ /// set file for export of composition at next play
+ void setExportWavFile(const QString& fileName);
+
public slots:
/**
@@ -281,6 +285,8 @@ public slots:
void slotLoopChanged();
+ void slotExportUpdate();
+
signals:
/// A program change was received.
/**
@@ -482,6 +488,8 @@ private slots:
/// Used by setTempo() to detect tempo changes.
tempoT m_tempo;
+ WAVExporter* m_wavExporter;
+ QTimer *m_exportTimer;
};
diff --git a/src/sequencer/RosegardenSequencer.cpp b/src/sequencer/RosegardenSequencer.cpp
index 5aa900099..450c55234 100644
--- a/src/sequencer/RosegardenSequencer.cpp
+++ b/src/sequencer/RosegardenSequencer.cpp
@@ -1523,6 +1523,12 @@ RosegardenSequencer::initialiseStudio()
m_studio->clear();
}
+void
+RosegardenSequencer::installExporter(WAVExporter* wavExporter)
+{
+ m_driver->installExporter(wavExporter);
+}
+
void
RosegardenSequencer::checkForNewClients()
{
diff --git a/src/sequencer/RosegardenSequencer.h b/src/sequencer/RosegardenSequencer.h
index 1e7e2daa3..37b5432a7 100644
--- a/src/sequencer/RosegardenSequencer.h
+++ b/src/sequencer/RosegardenSequencer.h
@@ -38,6 +38,7 @@ namespace Rosegarden {
class MappedInstrument;
class SoundDriver;
+class WAVExporter;
/// MIDI and Audio recording and playback
@@ -435,6 +436,8 @@ class RosegardenSequencer : public QObject
/// Initialise the virtual studio at this end of the link.
void initialiseStudio();
+ void installExporter(WAVExporter* wavExporter);
+
// --------- Transport Interface --------
//
diff --git a/src/sound/AlsaDriver.cpp b/src/sound/AlsaDriver.cpp
index 71834d515..7e0ee6e82 100644
--- a/src/sound/AlsaDriver.cpp
+++ b/src/sound/AlsaDriver.cpp
@@ -5489,6 +5489,16 @@ AlsaDriver::scavengePlugins()
m_pluginScavenger.scavenge();
}
+void
+AlsaDriver::installExporter(WAVExporter* wavExporter)
+{
+#ifdef HAVE_LIBJACK
+ if (m_jackDriver) {
+ m_jackDriver->installExporter(wavExporter);
+ }
+#endif
+}
+
QString
AlsaDriver::getStatusLog()
{
diff --git a/src/sound/AlsaDriver.h b/src/sound/AlsaDriver.h
index 82e6527af..237ab82b2 100644
--- a/src/sound/AlsaDriver.h
+++ b/src/sound/AlsaDriver.h
@@ -350,6 +350,8 @@ class AlsaDriver : public SoundDriver
void claimUnwantedPlugin(void *plugin) override;
void scavengePlugins() override;
+ void installExporter(WAVExporter* WAVExporter) override;
+
/// Update Ports and Connections
/**
* Updates m_alsaPorts and m_devicePortMap to match the ports and
diff --git a/src/sound/JackDriver.cpp b/src/sound/JackDriver.cpp
index 5164b3130..3cebfd2e4 100644
--- a/src/sound/JackDriver.cpp
+++ b/src/sound/JackDriver.cpp
@@ -26,6 +26,7 @@
#include "Audit.h"
#include "PluginFactory.h"
#include "SequencerDataBlock.h"
+#include "sound/WAVExporter.h"
#include "misc/ConfigGroups.h"
#include "misc/Debug.h"
@@ -73,7 +74,9 @@ JackDriver::JackDriver(AlsaDriver *alsaDriver) :
m_haveAsyncAudioEvent(false),
m_kickedOutAt(0),
m_framesProcessed(0),
- m_ok(false)
+ m_ok(false),
+ m_playing(false),
+ m_exportManager(nullptr)
{
initialise();
}
@@ -854,6 +857,22 @@ JackDriver::jackProcess(jack_nframes_t nframes)
// receiving midi input so always process async audio
bool asyncAudio = m_haveAsyncAudioEvent || (synthCount > 0);
+ if (m_exportManager) {
+ // Transitioning to play.
+ if (playing && !m_playing) {
+ RG_DEBUG << "export start playing";
+ m_exportManager->start();
+ }
+ // Transitioning to stop.
+ if (!playing && m_playing) {
+ RG_DEBUG << "export stop playing";
+ m_exportManager->stop();
+ // finished with the exportManager - it is deleted elsewhere
+ m_exportManager = nullptr;
+ }
+ m_playing = playing;
+ }
+
#ifdef DEBUG_JACK_PROCESS
Profiler profiler("jackProcess", true);
#else
@@ -1289,6 +1308,11 @@ JackDriver::jackProcess(jack_nframes_t nframes)
}
}
+
+ if (m_exportManager && playing) {
+ m_exportManager->addSamples(master[0], master[1], m_bufferSize);
+ }
+
if (playing) {
if (!lowLatencyMode) {
if (m_bussMixer->getBussCount() == 0) {
@@ -2536,6 +2560,12 @@ JackDriver::reportFailure(MappedEvent::FailureCode code)
m_alsaDriver->reportFailure(code);
}
+void
+JackDriver::installExporter(WAVExporter* wavExporter)
+{
+ m_exportManager = wavExporter;
+}
+
}
diff --git a/src/sound/JackDriver.h b/src/sound/JackDriver.h
index fea6591eb..fd633028f 100644
--- a/src/sound/JackDriver.h
+++ b/src/sound/JackDriver.h
@@ -36,6 +36,7 @@ class AudioBussMixer;
class AudioInstrumentMixer;
class AudioFileReader;
class AudioFileWriter;
+class WAVExporter;
class JackDriver
{
@@ -195,6 +196,8 @@ class JackDriver
//
void reportFailure(MappedEvent::FailureCode code);
+ void installExporter(WAVExporter* wavExporter);
+
protected:
// static methods for JACK process thread:
@@ -290,8 +293,12 @@ class JackDriver
bool m_ok;
bool m_checkLoad;
-};
+ private:
+ /// Previous play state for detecting state transition for export.
+ bool m_playing;
+ WAVExporter* m_exportManager;
+};
}
diff --git a/src/sound/SoundDriver.h b/src/sound/SoundDriver.h
index db6f6747c..c5b494901 100644
--- a/src/sound/SoundDriver.h
+++ b/src/sound/SoundDriver.h
@@ -39,6 +39,7 @@ namespace Rosegarden
{
class PlayableData;
+class WAVExporter;
// Current recording status - whether we're monitoring anything
// or recording.
@@ -327,6 +328,9 @@ class SoundDriver
unsigned int getDevices();
*/
+ // install the manager for rendering the composition to an audio file
+ virtual void installExporter(WAVExporter*) { }
+
protected:
// *** General ***
diff --git a/src/sound/WAVExporter.cpp b/src/sound/WAVExporter.cpp
new file mode 100644
index 000000000..c0206e9f8
--- /dev/null
+++ b/src/sound/WAVExporter.cpp
@@ -0,0 +1,172 @@
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
+
+/*
+ Rosegarden
+ A MIDI and audio sequencer and musical notation editor.
+ Copyright 2000-2024 the Rosegarden development team.
+
+ Other copyrights also apply to some parts of this work. Please
+ see the AUTHORS file and individual file headers for details.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version. See the file
+ COPYING included with this distribution for more information.
+*/
+
+#define RG_MODULE_STRING "[WAVExporter]"
+#define RG_NO_DEBUG_PRINT 1
+
+#include "WAVExporter.h"
+
+#include "misc/Debug.h"
+#include "sound/audiostream/AudioWriteStream.h"
+#include "sound/audiostream/AudioWriteStreamFactory.h"
+#include "gui/application/RosegardenMainWindow.h"
+#include "sequencer/RosegardenSequencer.h"
+
+#include
+
+
+namespace Rosegarden
+{
+
+
+WAVExporter::WAVExporter(const QString& fileName)
+{
+ RG_DEBUG << "ctor" << fileName;
+
+ const unsigned sampleRate =
+ RosegardenSequencer::getInstance()->getSampleRate();
+
+ // Create the output file.
+ m_audioWriteStream.reset(AudioWriteStreamFactory::createWriteStream(
+ fileName,
+ 2, // channelCount
+ sampleRate));
+ if (!m_audioWriteStream) {
+ QMessageBox::information(
+ RosegardenMainWindow::self(), // parent
+ QObject::tr("Rosegarden"), // title
+ QObject::tr(
+ "WAV Export
"
+ "Unable to create WAV file.
")); // text
+
+ return;
+ }
+
+ // create the ring buffers
+ m_leftChannelBuffer.reset(new RingBuffer(sampleRate/2));
+ m_rightChannelBuffer.reset(new RingBuffer(sampleRate/2));
+}
+
+void WAVExporter::start()
+{
+ if (!m_audioWriteStream)
+ return;
+
+ RG_DEBUG << "start";
+
+ m_running = true;
+}
+
+void WAVExporter::stop()
+{
+ RG_DEBUG << "stop";
+ m_stopRequested = true;
+}
+
+void WAVExporter::addSamples(sample_t *left,
+ sample_t *right,
+ size_t numSamples)
+{
+ if (!m_audioWriteStream)
+ return;
+ if (!m_leftChannelBuffer)
+ return;
+ if (!m_rightChannelBuffer)
+ return;
+
+ RG_DEBUG << "addSamples" << left << right << numSamples;
+ if (! m_running) {
+ RG_DEBUG << "addSamples not running";
+ return;
+ }
+ size_t spacel = m_leftChannelBuffer->getWriteSpace();
+ size_t spacer = m_rightChannelBuffer->getWriteSpace();
+ if (spacel < numSamples || spacer < numSamples) {
+ RG_WARNING << "export to audio buffer overflow";
+ return;
+ }
+ m_leftChannelBuffer->write(left, numSamples);
+ m_rightChannelBuffer->write(right, numSamples);
+}
+
+void WAVExporter::update()
+{
+ if (!m_audioWriteStream)
+ return;
+ if (!m_leftChannelBuffer)
+ return;
+ if (!m_rightChannelBuffer)
+ return;
+
+ if (m_running) {
+ size_t spacel = m_leftChannelBuffer->getReadSpace();
+ size_t spacer = m_rightChannelBuffer->getReadSpace();
+ size_t toRead = spacel;
+ if (spacer < spacel) toRead = spacer;
+ if (toRead > 0) {
+ sample_t lbuf[toRead];
+ sample_t rbuf[toRead];
+ sample_t ileaveBuf[2 * toRead];
+ RG_DEBUG << "update read" << toRead;
+ m_leftChannelBuffer->read(lbuf, toRead);
+ m_rightChannelBuffer->read(rbuf, toRead);
+#ifndef NDEBUG
+ // Gather samples squared for debugging.
+ double ssq = 0.0;
+#endif
+ // For each interleaved sample...
+ for (size_t is=0; isputInterleavedFrames(toRead, ileaveBuf);
+ }
+ if (m_stopRequested) {
+ RG_DEBUG << "stop requested - deleting write stream";
+
+ m_running = false;
+
+ // Free all the memory since we are done.
+ m_audioWriteStream = nullptr;
+ m_leftChannelBuffer = nullptr;
+ m_rightChannelBuffer = nullptr;
+ }
+ }
+}
+
+bool WAVExporter::isComplete() const
+{
+ // File creation failed? We're done.
+ if (!m_audioWriteStream)
+ return true;
+
+ return (m_stopRequested && ! m_running);
+}
+
+
+}
diff --git a/src/sound/WAVExporter.h b/src/sound/WAVExporter.h
new file mode 100644
index 000000000..85802cdf1
--- /dev/null
+++ b/src/sound/WAVExporter.h
@@ -0,0 +1,83 @@
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
+
+/*
+ Rosegarden
+ A MIDI and audio sequencer and musical notation editor.
+ Copyright 2000-2024 the Rosegarden development team.
+
+ Other copyrights also apply to some parts of this work. Please
+ see the AUTHORS file and individual file headers for details.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version. See the file
+ COPYING included with this distribution for more information.
+*/
+
+#ifndef RG_WAVEXPORTER_H
+#define RG_WAVEXPORTER_H
+
+typedef float sample_t;
+#include "RingBuffer.h"
+
+#include
+
+class QString;
+
+
+namespace Rosegarden
+{
+
+
+class AudioWriteStream;
+
+
+/// Export playback to wav file
+class WAVExporter
+{
+public:
+ explicit WAVExporter(const QString& fileName);
+ /*
+ * Call this after the ctor to determine whether the file was
+ * successfully created.
+ */
+ bool isOK() const { return static_cast(m_audioWriteStream); }
+
+ /// called by the audio thread on start playback
+ void start();
+
+ /// called by the audio thread on stop playback
+ void stop();
+
+ /// called by the audio thread to provide channel data
+ void addSamples(sample_t *left, sample_t *right, size_t numSamples);
+
+ /// called by the gui thread to update the file data
+ void update();
+
+ /// Export is complete, or this object is not OK.
+ /**
+ * Called by the gui thread to request completion status.
+ */
+ bool isComplete() const;
+
+private:
+
+ // Output File
+ std::shared_ptr m_audioWriteStream;
+
+ // Processing state.
+ bool m_running{false};
+ bool m_stopRequested{false};
+
+ // Lock-free buffers written by the audio thread and read by the GUI thread.
+ std::unique_ptr> m_leftChannelBuffer;
+ std::unique_ptr> m_rightChannelBuffer;
+
+};
+
+
+}
+
+#endif /* ifndef RG_WAVEXPORTER_H */
diff --git a/src/sound/audiostream/AudioWriteStreamFactory.cpp b/src/sound/audiostream/AudioWriteStreamFactory.cpp
index dd9a5ef47..2f0b0b8b2 100644
--- a/src/sound/audiostream/AudioWriteStreamFactory.cpp
+++ b/src/sound/audiostream/AudioWriteStreamFactory.cpp
@@ -14,11 +14,14 @@
COPYING included with this distribution for more information.
*/
+#define RG_MODULE_STRING "[AudioWriteStreamFactory]"
+#define RG_NO_DEBUG_PRINT 1
#include "AudioWriteStreamFactory.h"
#include "AudioWriteStream.h"
#include "base/ThingFactory.h"
+#include "misc/Debug.h"
#include
@@ -49,7 +52,19 @@ AudioWriteStreamFactory::createWriteStream(QString audioFileName,
} catch (...) {
}
- if (s && s->isOK() && s->getError() == "") {
+ if (!s) {
+ RG_WARNING << "createWriteStream(): createFor() returned nullptr";
+ return nullptr;
+ }
+
+ if (!s->isOK()) {
+ RG_WARNING << "createWriteStream(): AudioWriteStream is not OK";
+ }
+ if (s->getError() != "") {
+ RG_WARNING << "createWriteStream(): AudioWriteStream error: " << s->getError();
+ }
+
+ if (s->isOK() && s->getError() == "") {
return s;
}