diff --git a/icons/icons.qrc b/icons/icons.qrc
index a65c87c34..07232d1b6 100644
--- a/icons/icons.qrc
+++ b/icons/icons.qrc
@@ -43,5 +43,7 @@
clock.png
sequence.png
folder.png
+ record.png
+ record-disabled.png
diff --git a/icons/record-disabled.png b/icons/record-disabled.png
new file mode 100644
index 000000000..9510d9c8c
Binary files /dev/null and b/icons/record-disabled.png differ
diff --git a/icons/record.png b/icons/record.png
new file mode 100644
index 000000000..87e09bfd8
Binary files /dev/null and b/icons/record.png differ
diff --git a/panels/timeline.cpp b/panels/timeline.cpp
index 8448528b2..b2ef9e3e1 100644
--- a/panels/timeline.cpp
+++ b/panels/timeline.cpp
@@ -193,6 +193,7 @@ void Timeline::update_sequence() {
ui->snappingButton->setEnabled(!null_sequence);
ui->pushButton_4->setEnabled(!null_sequence);
ui->pushButton_5->setEnabled(!null_sequence);
+ ui->recordButton->setEnabled(!null_sequence);
ui->addButton->setEnabled(!null_sequence);
ui->headers->setEnabled(!null_sequence);
@@ -1152,3 +1153,7 @@ void Timeline::setScroll(int s) {
ui->headers->set_scroll(s);
repaint_timeline();
}
+
+void Timeline::on_recordButton_clicked() {
+ qDebug() << "recording is a" << start_recording();
+}
diff --git a/panels/timeline.h b/panels/timeline.h
index c92db4b62..cad39b7af 100644
--- a/panels/timeline.h
+++ b/panels/timeline.h
@@ -194,6 +194,8 @@ private slots:
void setScroll(int);
+ void on_recordButton_clicked();
+
private:
QVector tool_buttons;
void decheck_tool_buttons(QObject* sender);
diff --git a/panels/timeline.ui b/panels/timeline.ui
index af2bf631e..985a2eea3 100644
--- a/panels/timeline.ui
+++ b/panels/timeline.ui
@@ -245,6 +245,19 @@
+ -
+
+
+ Record audio
+
+
+
+ :/icons/record.png
+ :/icons/record-disabled.png
+
+
+
+
-
diff --git a/panels/viewer.cpp b/panels/viewer.cpp
index c5e5ca61a..95d76dc1f 100644
--- a/panels/viewer.cpp
+++ b/panels/viewer.cpp
@@ -263,6 +263,7 @@ void Viewer::pause() {
playing = false;
set_playpause_icon(true);
playback_updater.stop();
+ stop_recording();
}
void Viewer::update_playhead_timecode(long p) {
diff --git a/playback/audio.cpp b/playback/audio.cpp
index d9be1fbde..d5666074b 100644
--- a/playback/audio.cpp
+++ b/playback/audio.cpp
@@ -8,7 +8,9 @@
#include "ui_timeline.h"
#include
+#include
#include
+#include
#include
extern "C" {
@@ -19,6 +21,9 @@ QAudioOutput* audio_output;
QIODevice* audio_io_device;
bool audio_device_set = false;
QMutex audio_write_lock;
+QAudioInput* audio_input = NULL;
+QFile output_recording;
+bool recording = false;
qint8 audio_ibuffer[audio_ibuffer_size];
int audio_ibuffer_read = 0;
@@ -177,3 +182,121 @@ int AudioSenderThread::send_audio_to_output(int offset, int max) {
return actual_write;
}
+
+void int32_to_char_array(qint32 i, char* array) {
+ memcpy(array, &i, 4);
+}
+
+void write_wave_header(QFile& f, const QAudioFormat& format) {
+ qint32 int32bit;
+ char arr[4];
+
+ // 4 byte riff header
+ f.write("RIFF");
+
+ // 4 byte file size, filled in later
+ for (int i=0;i<4;i++) f.putChar(0);
+
+ // 4 byte file type header + 4 byte format chunk marker
+ f.write("WAVEfmt");
+ f.putChar(0x20);
+
+ // 4 byte length of the above format data (always 16 bytes)
+ f.putChar(16);
+ for (int i=0;i<3;i++) f.putChar(0);
+
+ // 2 byte type format (1 is PCM)
+ f.putChar(1);
+ f.putChar(0);
+
+ // 2 byte channel count (2 for stereo)
+ f.putChar(2);
+ f.putChar(0);
+
+ // 4 byte integer for sample rate
+ int32bit = format.sampleRate();
+ int32_to_char_array(int32bit, arr);
+ f.write(arr, 4);
+
+ // 4 byte integer for bytes per second
+ int32bit = (format.sampleRate() * format.sampleSize() * format.channelCount()) / 8;
+ int32_to_char_array(int32bit, arr);
+ f.write(arr, 4);
+
+ // 2 byte integer for bytes per sample per channel
+ int32bit = (format.sampleSize() * format.channelCount()) / 8;
+ int32_to_char_array(int32bit, arr);
+ f.write(arr, 2);
+
+ // 2 byte integer for bits per sample (16)
+ int32bit = format.sampleSize();
+ int32_to_char_array(int32bit, arr);
+ f.write(arr, 2);
+
+ // data chunk header
+ f.write("data");
+
+ // 4 byte integer for data chunk size (filled in later)?
+ for (int i=0;i<4;i++) f.putChar(0);
+}
+
+void write_wave_trailer(QFile& f) {
+ char arr[4];
+
+ f.seek(4);
+
+ // 4 bytes for total file size - 8 bytes
+ qint32 file_size = f.size() - 8;
+ int32_to_char_array(file_size, arr);
+ f.write(arr, 4);
+
+ f.seek(40);
+
+ // 4 bytes for data chunk size (file size - header)
+ file_size = f.size() - 44;
+ int32_to_char_array(file_size, arr);
+ f.write(arr, 4);
+}
+
+bool start_recording() {
+ if (sequence == NULL) {
+ qDebug() << "[ERROR] No active sequence to record into";
+ return false;
+ }
+ output_recording.setFileName("C:/Users/Matt/output.wav");
+ if (!output_recording.open(QFile::WriteOnly)) {
+ qDebug() << "[ERROR] Failed to open output file. Does Olive have permission to write to this directory?";
+ return false;
+ }
+
+ QAudioFormat audio_format = audio_output->format();
+ QAudioDeviceInfo info = QAudioDeviceInfo::defaultInputDevice();
+ if (!info.isFormatSupported(audio_format)) {
+ qDebug() << "[WARNING] Default format not supported, using nearest";
+ audio_format = info.nearestFormat(audio_format);
+ }
+ write_wave_header(output_recording, audio_format);
+ audio_input = new QAudioInput(audio_format);
+ audio_input->start(&output_recording);
+ recording = true;
+
+ return true;
+}
+
+void stop_recording() {
+ if (recording) {
+ audio_input->stop();
+
+ /*if (audio_input->state() == QAudio::ActiveState) {
+
+ }*/
+
+ write_wave_trailer(output_recording);
+
+ output_recording.close();
+
+ delete audio_input;
+ audio_input = NULL;
+ }
+ recording = false;
+}
diff --git a/playback/audio.h b/playback/audio.h
index 60d75f77e..913ed0ac9 100644
--- a/playback/audio.h
+++ b/playback/audio.h
@@ -46,4 +46,8 @@ void init_audio(Sequence *s);
void stop_audio();
int get_buffer_offset_from_frame(Sequence *s, long frame);
+bool start_recording();
+void stop_recording();
+extern bool recording;
+
#endif // AUDIO_H
diff --git a/ui/viewerwidget.cpp b/ui/viewerwidget.cpp
index bbbf95d5b..dd5b74089 100644
--- a/ui/viewerwidget.cpp
+++ b/ui/viewerwidget.cpp
@@ -529,7 +529,8 @@ void ViewerWidget::paintGL() {
glDisable(GL_TEXTURE_2D);
} while (loop);
- if (viewer->playing
+ if (!recording
+ && viewer->playing
&& (viewer->seq->playhead == viewer->seq->getEndFrame() || (viewer->seq->using_workarea && viewer->seq->playhead >= viewer->seq->workarea_out))) {
viewer->pause();
}