From 861a5e2ce5c9df919b1f33e0241420cfa33f9023 Mon Sep 17 00:00:00 2001 From: itsmattkc Date: Wed, 30 Jan 2019 22:51:43 +1100 Subject: [PATCH] added audio device settings to preferences --- dialogs/newsequencedialog.cpp | 9 +--- dialogs/preferencesdialog.cpp | 77 +++++++++++++++++++++++++++++++++-- dialogs/preferencesdialog.h | 3 ++ io/config.cpp | 8 ++++ io/config.h | 2 + io/exportthread.cpp | 13 +++--- playback/audio.cpp | 59 +++++++++++++++++++++------ playback/audio.h | 3 ++ 8 files changed, 143 insertions(+), 31 deletions(-) diff --git a/dialogs/newsequencedialog.cpp b/dialogs/newsequencedialog.cpp index 9eaf35367..b80fde74f 100644 --- a/dialogs/newsequencedialog.cpp +++ b/dialogs/newsequencedialog.cpp @@ -8,6 +8,7 @@ #include "panels/timeline.h" #include "playback/playback.h" #include "project/media.h" +#include "playback/audio.h" #include #include @@ -232,13 +233,7 @@ void NewSequenceDialog::setup_ui() { audioLayout->addWidget(new QLabel(tr("Sample Rate: "), this), 0, 0, 1, 1); audio_frequency_combobox = new QComboBox(audioGroupBox); - audio_frequency_combobox->addItem("22050 Hz", 22050); - audio_frequency_combobox->addItem("24000 Hz", 24000); - audio_frequency_combobox->addItem("32000 Hz", 32000); - audio_frequency_combobox->addItem("44100 Hz", 44100); - audio_frequency_combobox->addItem("48000 Hz", 48000); - audio_frequency_combobox->addItem("88200 Hz", 88200); - audio_frequency_combobox->addItem("96000 Hz", 96000); + combobox_audio_sample_rates(audio_frequency_combobox); audio_frequency_combobox->setCurrentIndex(4); audioLayout->addWidget(audio_frequency_combobox, 0, 1, 1, 1); diff --git a/dialogs/preferencesdialog.cpp b/dialogs/preferencesdialog.cpp index 37b54958a..85150b666 100644 --- a/dialogs/preferencesdialog.cpp +++ b/dialogs/preferencesdialog.cpp @@ -1,6 +1,7 @@ #include "preferencesdialog.h" #include "io/config.h" +#include "playback/audio.h" #include "mainwindow.h" #include @@ -22,6 +23,7 @@ #include #include #include +#include #include "debug.h" @@ -133,6 +135,14 @@ void PreferencesDialog::save() { config.previous_queue_size = previous_queue_spinbox->value(); config.previous_queue_type = previous_queue_type->currentIndex(); + // audio preferences + bool reset_audio_required = (config.preferred_audio_output != audio_output_devices->currentData().toString() + || config.preferred_audio_input != audio_input_devices->currentData().toString()); + config.preferred_audio_output = audio_output_devices->currentData().toString(); + config.preferred_audio_input = audio_input_devices->currentData().toString(); + qDebug() << "selected audio input" << audio_input_devices->currentData().toString(); + config.audio_rate = audio_sample_rate->currentData().toInt(); + // the following settings may require a restart of Olive to take effect: bool needs_restart = false; @@ -152,6 +162,10 @@ void PreferencesDialog::save() { key_shortcut_fields.at(i)->set_action_shortcut(); } + if (reset_audio_required) { + init_audio(); + } + if (needs_restart) { QMessageBox::information(this, tr("Warning"), tr("Some changed settings will require restarting Olive to take effect")); } @@ -286,7 +300,7 @@ void PreferencesDialog::setup_ui() { QTabWidget* tabWidget = new QTabWidget(this); // General - QTabWidget* general_tab = new QTabWidget(this); + QWidget* general_tab = new QWidget(this); QGridLayout* general_layout = new QGridLayout(general_tab); // General -> Custom CSS @@ -382,6 +396,65 @@ void PreferencesDialog::setup_ui() { tabWidget->addTab(playback_tab, tr("Playback")); + // Audio + QWidget* audio_tab = new QWidget(this); + + QGridLayout* audio_tab_layout = new QGridLayout(audio_tab); + + audio_tab_layout->addWidget(new QLabel(tr("Output Device:")), 0, 0); + + audio_output_devices = new QComboBox(); + audio_output_devices->addItem(tr("Default"), ""); + + // list all available audio output devices + QList devs = QAudioDeviceInfo::availableDevices(QAudio::AudioOutput); + bool found_preferred_device = false; + for (int i=0;iaddItem(devs.at(i).deviceName(), devs.at(i).deviceName()); + if (!found_preferred_device + && devs.at(i).deviceName() == config.preferred_audio_output) { + audio_output_devices->setCurrentIndex(audio_output_devices->count()-1); + found_preferred_device = true; + } + } + + audio_tab_layout->addWidget(audio_output_devices, 0, 1); + + audio_tab_layout->addWidget(new QLabel(tr("Input Device:")), 1, 0); + + audio_input_devices = new QComboBox(); + audio_input_devices->addItem(tr("Default"), ""); + + // list all available audio input devices + devs = QAudioDeviceInfo::availableDevices(QAudio::AudioInput); + found_preferred_device = false; + for (int i=0;iaddItem(devs.at(i).deviceName(), devs.at(i).deviceName()); + if (!found_preferred_device + && devs.at(i).deviceName() == config.preferred_audio_input) { + audio_input_devices->setCurrentIndex(audio_input_devices->count()-1); + found_preferred_device = true; + } + } + + audio_tab_layout->addWidget(audio_input_devices, 1, 1); + + audio_tab_layout->addWidget(new QLabel(tr("Sample Rate:")), 2, 0); + + audio_sample_rate = new QComboBox(); + combobox_audio_sample_rates(audio_sample_rate); + for (int i=0;icount();i++) { + if (audio_sample_rate->itemData(i).toInt() == config.audio_rate) { + audio_sample_rate->setCurrentIndex(i); + break; + } + } + + audio_tab_layout->addWidget(audio_sample_rate, 2, 1); + + tabWidget->addTab(audio_tab, tr("Audio")); + + // Shortcuts QWidget* shortcut_tab = new QWidget(this); QVBoxLayout* shortcut_layout = new QVBoxLayout(shortcut_tab); @@ -432,6 +505,4 @@ void PreferencesDialog::setup_ui() { connect(buttonBox, SIGNAL(accepted()), this, SLOT(save())); connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject())); - - tabWidget->setCurrentIndex(2); } diff --git a/dialogs/preferencesdialog.h b/dialogs/preferencesdialog.h index 9e3ad21fc..2e8243fda 100644 --- a/dialogs/preferencesdialog.h +++ b/dialogs/preferencesdialog.h @@ -62,6 +62,9 @@ private: QComboBox* previous_queue_type; QSpinBox* effect_textbox_lines_field; QCheckBox* use_software_fallbacks_checkbox; + QComboBox* audio_output_devices; + QComboBox* audio_input_devices; + QComboBox* audio_sample_rate; QVector key_shortcut_actions; QVector key_shortcut_items; diff --git a/io/config.cpp b/io/config.cpp index 912fe86e9..2a3122557 100644 --- a/io/config.cpp +++ b/io/config.cpp @@ -173,6 +173,12 @@ void Config::load(QString path) { } else if (stream.name() == "CenterTimelineTimecodes") { stream.readNext(); center_timeline_timecodes = (stream.text() == "1"); + } else if (stream.name() == "PreferredAudioOutput") { + stream.readNext(); + preferred_audio_output = stream.text().toString(); + } else if (stream.name() == "PreferredAudioInput") { + stream.readNext(); + preferred_audio_input = stream.text().toString(); } } } @@ -235,6 +241,8 @@ void Config::save(QString path) { stream.writeTextElement("EffectTextboxLines", QString::number(effect_textbox_lines)); stream.writeTextElement("UseSoftwareFallback", QString::number(use_software_fallback)); stream.writeTextElement("CenterTimelineTimecodes", QString::number(center_timeline_timecodes)); + stream.writeTextElement("PreferredAudioOutput", preferred_audio_output); + stream.writeTextElement("PreferredAudioInput", preferred_audio_input); stream.writeEndElement(); // configuration stream.writeEndDocument(); // doc diff --git a/io/config.h b/io/config.h index 84bd848df..5e8c61f27 100644 --- a/io/config.h +++ b/io/config.h @@ -64,6 +64,8 @@ struct Config { int effect_textbox_lines; bool use_software_fallback; bool center_timeline_timecodes; + QString preferred_audio_output; + QString preferred_audio_input; void load(QString path); void save(QString path); diff --git a/io/exportthread.cpp b/io/exportthread.cpp index ad96a4a0b..79136b2f5 100644 --- a/io/exportthread.cpp +++ b/io/exportthread.cpp @@ -132,9 +132,6 @@ bool ExportThread::setupVideo() { break; } break; - case AV_CODEC_ID_GIF: - av_opt_set(vcodec_ctx->priv_data, "image", "1", AV_OPT_SEARCH_CHILDREN); - break; } AVDictionary* opts = nullptr; @@ -377,18 +374,20 @@ void ExportThread::run() { sws_frame->height = video_height; av_frame_get_buffer(sws_frame, 0); - // change pixel format + // convert pixel format to format expected by the encoder sws_scale(sws_ctx, video_frame->data, video_frame->linesize, 0, video_frame->height, sws_frame->data, sws_frame->linesize); sws_frame->pts = qRound(timecode_secs/av_q2d(video_stream->time_base)); - // send to encoder + // send converted frame to encoder if (!encode(fmt_ctx, vcodec_ctx, sws_frame, &video_pkt, video_stream, false)) continueEncode = false; av_frame_free(&sws_frame); } if (audio_enabled) { + // do we need to encode more audio samples? while (continueEncode && file_audio_samples <= (timecode_secs*audio_sampling_rate)) { + // copy samples from audio buffer to AVFrame int adjusted_read = audio_ibuffer_read%audio_ibuffer_size; int copylen = qMin(aframe_bytes, audio_ibuffer_size-adjusted_read); @@ -415,15 +414,13 @@ void ExportThread::run() { } } - // encoding stats + // generating encoding statistics (time it took to encode this frame/estimated remaining time) frame_time = (QDateTime::currentMSecsSinceEpoch()-start_time); total_time += frame_time; remaining_frames = (end_frame-sequence->playhead); avg_time = (total_time/frame_count); eta = (remaining_frames*avg_time); -// qInfo() << "Encoded frame" << sequence->playhead << "- took" << frame_time << "ms (avg:" << avg_time << "ms, remaining:" << remaining_frames << ", ETA:" << eta << ")"; - emit progress_changed(qRound((double(sequence->playhead-start_frame) / double(end_frame-start_frame)) * 100.0), eta); sequence->playhead++; frame_count++; diff --git a/playback/audio.cpp b/playback/audio.cpp index b5abc9faf..44402a6f6 100644 --- a/playback/audio.cpp +++ b/playback/audio.cpp @@ -17,6 +17,7 @@ #include #include #include +#include extern "C" { #include @@ -43,6 +44,35 @@ bool is_audio_device_set() { return audio_device_set; } +QAudioDeviceInfo get_audio_device(QAudio::Mode mode) { + QList devs = QAudioDeviceInfo::availableDevices(mode); + + // try to retrieve preferred device from config + QString preferred_device = (mode == QAudio::AudioOutput) ? config.preferred_audio_output : config.preferred_audio_input; + if (!preferred_device.isEmpty()) { + for (int i=0;i 0) { + return devs.at(0); + } + + // couldn't find any audio devices, return null device + return QAudioDeviceInfo(); +} + void init_audio() { stop_audio(); @@ -54,18 +84,9 @@ void init_audio() { audio_format.setByteOrder(QAudioFormat::LittleEndian); audio_format.setSampleType(QAudioFormat::SignedInt); - QAudioDeviceInfo info(QAudioDeviceInfo::defaultOutputDevice()); - QList devs = QAudioDeviceInfo::availableDevices(QAudio::AudioOutput); - qInfo() << "Found the following audio devices:"; - for (int i=0;i 0) { - qWarning() << "Default audio returned nullptr, attempting to use first device found..."; - info = devs.at(0); - } - qInfo() << "Using audio device" << info.deviceName(); + QAudioDeviceInfo info = get_audio_device(QAudio::AudioOutput); + // see if desired format can be used by the device, use nearest if not if (!info.isFormatSupported(audio_format)) { qWarning() << "Audio format is not supported by backend, using nearest"; audio_format = info.nearestFormat(audio_format); @@ -311,13 +332,15 @@ bool start_recording() { if (config.recording_mode != audio_format.channelCount()) { audio_format.setChannelCount(config.recording_mode); } - QAudioDeviceInfo info = QAudioDeviceInfo::defaultInputDevice(); + + QAudioDeviceInfo info = get_audio_device(QAudio::AudioInput); + if (!info.isFormatSupported(audio_format)) { qWarning() << "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 = new QAudioInput(info, audio_format); audio_input->start(&output_recording); recording = true; @@ -341,3 +364,13 @@ void stop_recording() { QString get_recorded_audio_filename() { return output_recording.fileName(); } + +void combobox_audio_sample_rates(QComboBox *combobox) { + combobox->addItem("22050 Hz", 22050); + combobox->addItem("24000 Hz", 24000); + combobox->addItem("32000 Hz", 32000); + combobox->addItem("44100 Hz", 44100); + combobox->addItem("48000 Hz", 48000); + combobox->addItem("88200 Hz", 88200); + combobox->addItem("96000 Hz", 96000); +} diff --git a/playback/audio.h b/playback/audio.h index 8ca487fa2..fdb7ee3eb 100644 --- a/playback/audio.h +++ b/playback/audio.h @@ -11,6 +11,7 @@ class QIODevice; class QAudioOutput; +class QComboBox; struct Sequence; @@ -59,4 +60,6 @@ bool start_recording(); void stop_recording(); QString get_recorded_audio_filename(); +void combobox_audio_sample_rates(QComboBox* combobox); + #endif // AUDIO_H