Members of the KDE Community are recommended to subscribe to the kde-community mailing list at https://mail.kde.org/mailman/listinfo/kde-community to allow them to participate in important discussions and receive other important announcements

Mixer: add record buttons (volume doesn't yet adjust mic level)

parent df21bcce
Pipeline #8998 passed with stage
in 17 minutes and 12 seconds
......@@ -128,7 +128,7 @@ void MixerManager::setModel(std::shared_ptr<TimelineItemModel> model)
{
// Insert master mixer
m_model = model;
connect(m_model.get(), &TimelineItemModel::dataChanged, [&](const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector<int> &roles) {
connect(m_model.get(), &TimelineItemModel::dataChanged, [&](const QModelIndex &topLeft, const QModelIndex &, const QVector<int> &roles) {
if (roles.contains(TimelineModel::IsDisabledRole)) {
int id = (int) topLeft.internalId();
if (m_mixers.count(id) > 0) {
......@@ -153,3 +153,9 @@ void MixerManager::setModel(std::shared_ptr<TimelineItemModel> model)
m_masterBox->addWidget(m_masterMixer.get());
}
void MixerManager::recordStateChanged(int tid, bool recording)
{
if (m_mixers.count(tid) > 0) {
m_mixers[tid]->setRecordState(recording);
}
}
......@@ -50,11 +50,13 @@ public:
public slots:
void resetAudioValues();
void recordStateChanged(int tid, bool recording);
signals:
void updateLevels(int);
void connectMixerRenderer(bool);
void triggerUpdate();
void recordAudio(int tid);
public:
int renderPosition;
......
......@@ -25,9 +25,12 @@
#include "mlt++/MltTractor.h"
#include "mlt++/MltEvent.h"
#include "mlt++/MltProfile.h"
#include "core.h"
#include "kdenlivesettings.h"
#include "mixerwidget.hpp"
#include "mixermanager.hpp"
#include "audiolevelwidget.hpp"
#include "capture/mediacapture.h"
#include <klocalizedstring.h>
#include <KDualAction>
......@@ -73,8 +76,10 @@ MixerWidget::MixerWidget(int tid, std::shared_ptr<Mlt::Tractor> service, const Q
, m_monitorFilter(nullptr)
, m_balanceFilter(nullptr)
, m_solo(nullptr)
, m_record(nullptr)
, m_lastVolume(0)
, m_listener(nullptr)
, m_recording(false)
{
buildUI(service.get(), trackTag);
}
......@@ -87,8 +92,10 @@ MixerWidget::MixerWidget(int tid, Mlt::Tractor *service, const QString &trackTag
, m_monitorFilter(nullptr)
, m_balanceFilter(nullptr)
, m_solo(nullptr)
, m_record(nullptr)
, m_lastVolume(0)
, m_listener(nullptr)
, m_recording(false)
{
buildUI(service, trackTag);
}
......@@ -209,7 +216,7 @@ void MixerWidget::buildUI(Mlt::Tractor *service, const QString &trackTag)
mute->setAutoRaise(true);
if (m_tid > -1) {
// No solo button on master
// No solo / rec button on master
m_solo = new QToolButton(this);
m_solo->setCheckable(true);
m_solo->setIcon(QIcon::fromTheme("headphones"));
......@@ -217,12 +224,22 @@ void MixerWidget::buildUI(Mlt::Tractor *service, const QString &trackTag)
connect(m_solo, &QToolButton::toggled, [&](bool toggled) {
emit toggleSolo(m_tid, toggled);
});
m_record = new QToolButton(this);
m_record->setCheckable(true);
m_record->setIcon(QIcon::fromTheme("media-record"));
m_record->setAutoRaise(true);
connect(m_record, &QToolButton::toggled, [&](bool toggled) {
m_manager->recordAudio(m_tid);
});
}
connect(m_volumeSlider, &QSlider::valueChanged, [&](int value) {
QSignalBlocker bk(m_volumeSpin);
m_volumeSpin->setValue(value);
if (m_levelFilter != nullptr) {
if (m_recording) {
KdenliveSettings::setAudiocapturevolume(value);
//TODO update capture volume
} else if (m_levelFilter != nullptr) {
m_levelFilter->set("level", value);
}
});
......@@ -243,6 +260,9 @@ void MixerWidget::buildUI(Mlt::Tractor *service, const QString &trackTag)
if (m_solo) {
buttonslay->addWidget(m_solo);
}
if (m_record) {
buttonslay->addWidget(m_record);
}
lay->addLayout(buttonslay);
lay->addWidget(m_balanceDial);
lay->addWidget(m_balanceSpin);
......@@ -305,3 +325,42 @@ void MixerWidget::unSolo()
}
}
void MixerWidget::gotRecLevels(QVector<qreal>levels)
{
switch (levels.size()) {
case 0:
m_audioMeterWidget->setAudioValues({-100, -100});
break;
case 1:
m_audioMeterWidget->setAudioValues({levelToDB(levels[0]), -100});
break;
default:
m_audioMeterWidget->setAudioValues({levelToDB(levels[0]), levelToDB(levels[1])});
break;
}
}
void MixerWidget::setRecordState(bool recording)
{
m_recording = recording;
QSignalBlocker bk(m_volumeSpin);
QSignalBlocker bk2(m_volumeSlider);
if (m_recording) {
connect(pCore->getAudioDevice(), &MediaCapture::audioLevels, this, &MixerWidget::gotRecLevels);
m_volumeSlider->setRange(0, 100);
m_volumeSpin->setRange(0, 100);
m_volumeSpin->setSuffix(QStringLiteral("%"));
m_volumeSpin->setValue(KdenliveSettings::audiocapturevolume());
m_volumeSlider->setValue(KdenliveSettings::audiocapturevolume());
} else {
int level = m_levelFilter->get_int("level");
disconnect(pCore->getAudioDevice(), &MediaCapture::audioLevels, this, &MixerWidget::gotRecLevels);
m_volumeSlider->setRange(-100, 60);
m_volumeSpin->setRange(-100, 60);
m_volumeSpin->setSuffix(i18n("dB"));
m_volumeSpin->setValue(level);
m_volumeSlider->setValue(level);
}
QSignalBlocker bk3(m_record);
m_record->setChecked(recording);
}
......@@ -66,6 +66,10 @@ public:
public slots:
void updateAudioLevel(int pos);
void setAudioLevel(const QVector<int> vol);
void setRecordState(bool recording);
private slots:
void gotRecLevels(QVector<qreal>levels);
protected:
MixerManager *m_manager;
......@@ -83,14 +87,16 @@ private:
std::shared_ptr<AudioLevelWidget> m_audioMeterWidget;
QSlider *m_volumeSlider;
QToolButton *m_solo;
QToolButton *m_record;
QMutex m_storeMutex;
int m_lastVolume;
Mlt::Event *m_listener;
bool m_recording;
signals:
void gotLevels(QPair <double, double>);
void muteTrack(int tid, bool mute);
void toggleSolo(int m_tid, bool toggled);
void toggleSolo(int tid, bool toggled);
};
#endif
......
......@@ -59,21 +59,22 @@ void MediaCapture::resetIfUnused()
}
}
void MediaCapture::recordAudio(bool record)
void MediaCapture::recordAudio(int tid, bool record)
{
QMutexLocker lk(&m_recMutex);
if (!m_audioRecorder) {
m_audioRecorder = std::make_unique<QAudioRecorder>(this);
m_probe->setSource(m_audioRecorder.get());
connect(m_audioRecorder.get(), &QAudioRecorder::stateChanged, [&] (QMediaRecorder::State state) {
connect(m_audioRecorder.get(), &QAudioRecorder::stateChanged, [&, tid] (QMediaRecorder::State state) {
m_recordState = state;
if (m_recordState == QMediaRecorder::StoppedState) {
m_resetTimer.start();
m_levels.clear();
emit audioLevels(m_levels);
emit levelsChanged();
pCore->finalizeRecording(getCaptureOutputLocation().toLocalFile());
}
emit recordStateChanged();
emit recordStateChanged(tid, m_recordState == QMediaRecorder::RecordingState);
});
}
......@@ -101,7 +102,7 @@ void MediaCapture::recordAudio(bool record)
}
}
void MediaCapture::recordVideo(bool record)
void MediaCapture::recordVideo(int tid, bool record)
{
// TO DO - fix video capture
if (!m_videoRecorder) {
......@@ -317,13 +318,13 @@ QVector<qreal> getBufferLevels(const QAudioBuffer &buffer)
}
break;
}
return values;
}
void MediaCapture::processBuffer(const QAudioBuffer &buffer)
{
m_levels = getBufferLevels(buffer);
emit audioLevels(m_levels);
emit levelsChanged();
}
......
......@@ -44,8 +44,8 @@ class MediaCapture : public QObject
public:
MediaCapture(QObject *parent);
~MediaCapture() override;
void recordAudio(bool /*record*/);
void recordVideo(bool /*record*/);
void recordAudio(int tid, bool /*record*/);
void recordVideo(int tid, bool /*record*/);
/** @brief Returns true if a recording is in progress **/
bool isRecording() const;
/** @brief Sets m_path to selected output location **/
......@@ -86,8 +86,9 @@ private slots:
signals:
void levelsChanged();
void recordStateChanged();
void recordStateChanged(int tid, bool recording);
void recordDone();
void audioLevels(QVector<qreal> levels);
};
#endif
......@@ -175,6 +175,7 @@ void Core::initGUI(const QUrl &Url)
m_mixerWidget = new MixerManager(m_mainWindow);
connect(m_library, SIGNAL(addProjectClips(QList<QUrl>)), m_binWidget, SLOT(droppedUrls(QList<QUrl>)));
connect(this, &Core::updateLibraryPath, m_library, &LibraryWidget::slotUpdateLibraryPath);
connect(m_capture.get(), &MediaCapture::recordStateChanged, m_mixerWidget, &MixerManager::recordStateChanged);
m_monitorManager = new MonitorManager(this);
connect(m_monitorManager, &MonitorManager::pauseTriggered, m_mixerWidget, &MixerManager::resetAudioValues);
// Producer queue, creating MLT::Producers on request
......@@ -711,22 +712,22 @@ void Core::clean()
m_self.reset();
}
void Core::startMediaCapture(bool checkAudio, bool checkVideo)
void Core::startMediaCapture(int tid, bool checkAudio, bool checkVideo)
{
if (checkAudio && checkVideo) {
m_capture->recordVideo(true);
m_capture->recordVideo(tid, true);
} else if (checkAudio) {
m_capture->recordAudio(true);
m_capture->recordAudio(tid, true);
}
m_mediaCaptureFile = m_capture->getCaptureOutputLocation();
}
void Core::stopMediaCapture(bool checkAudio, bool checkVideo)
void Core::stopMediaCapture(int tid, bool checkAudio, bool checkVideo)
{
if (checkAudio && checkVideo) {
m_capture->recordVideo(false);
m_capture->recordVideo(tid, false);
} else if (checkAudio) {
m_capture->recordAudio(false);
m_capture->recordAudio(tid, false);
}
}
......
......@@ -187,8 +187,8 @@ public:
/** @brief Returns current timeline cursor position */
int getTimelinePosition() const;
/** @brief Handles audio and video capture **/
void startMediaCapture(bool, bool);
void stopMediaCapture(bool, bool);
void startMediaCapture(int tid, bool, bool);
void stopMediaCapture(int tid, bool, bool);
QStringList getAudioCaptureDevices();
int getMediaCaptureState();
bool isMediaCapturing();
......
......@@ -151,7 +151,7 @@ void RecManager::stopCapture()
slotRecord(false);
} else if (pCore->getMediaCaptureState() == 1 && (m_checkAudio || m_checkVideo)) {
// QMediaRecorder::RecordingState value is 1
pCore->stopMediaCapture(m_checkAudio, m_checkVideo);
pCore->stopMediaCapture(-1, m_checkAudio, m_checkVideo);
m_monitor->slotOpenClip(nullptr);
}
}
......@@ -242,7 +242,7 @@ void RecManager::slotRecord(bool record)
params.replace(QLatin1String("alsa"), QStringLiteral("dshow"));
// Remove vorbis codec
params.replace(QLatin1String("-acodec libvorbis"), QString());
// Find first audio device
QProcess tst;
tst.setProcessChannelMode(QProcess::MergedChannels);
......
......@@ -48,6 +48,7 @@
#include "timeline2/view/dialogs/clipdurationdialog.h"
#include "timeline2/view/dialogs/trackdialog.h"
#include "transitions/transitionsrepository.hpp"
#include "audiomixer/mixermanager.hpp"
#include <KColorScheme>
#include <QApplication>
......@@ -78,6 +79,7 @@ TimelineController::TimelineController(QObject *parent)
m_disablePreview->setEnabled(false);
connect(pCore.get(), &Core::finalizeRecording, this, &TimelineController::finishRecording);
connect(pCore.get(), &Core::autoScrollChanged, this, &TimelineController::autoScrollChanged);
connect(pCore->mixer(), &MixerManager::recordAudio, this, &TimelineController::switchRecording);
}
TimelineController::~TimelineController()
......@@ -2556,10 +2558,10 @@ void TimelineController::switchRecording(int trackId)
}
}
pCore->monitorManager()->slotSwitchMonitors(false);
pCore->startMediaCapture(true, false);
pCore->startMediaCapture(trackId, true, false);
pCore->monitorManager()->slotPlay();
} else {
pCore->stopMediaCapture(true, false);
pCore->stopMediaCapture(trackId, true, false);
pCore->monitorManager()->slotPause();
}
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment