File indexing completed on 2024-04-21 04:51:04
0001 /* 0002 SPDX-FileCopyrightText: 2019 Jean-Baptiste Mardelle 0003 SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL 0004 */ 0005 0006 #include "mixerwidget.hpp" 0007 0008 #include "audiolevelwidget.hpp" 0009 #include "capture/mediacapture.h" 0010 #include "core.h" 0011 #include "iecscale.h" 0012 #include "kdenlivesettings.h" 0013 #include "mixermanager.hpp" 0014 #include "mlt++/MltEvent.h" 0015 #include "mlt++/MltFilter.h" 0016 #include "mlt++/MltProfile.h" 0017 #include "mlt++/MltTractor.h" 0018 0019 #include <KDualAction> 0020 #include <KLocalizedString> 0021 #include <KSqueezedTextLabel> 0022 #include <QCheckBox> 0023 #include <QDial> 0024 #include <QDoubleSpinBox> 0025 #include <QFontDatabase> 0026 #include <QGridLayout> 0027 #include <QLabel> 0028 #include <QMouseEvent> 0029 #include <QSlider> 0030 #include <QSpinBox> 0031 #include <QStyle> 0032 #include <QToolButton> 0033 0034 void MixerWidget::property_changed(mlt_service, MixerWidget *widget, mlt_event_data data) 0035 { 0036 if (widget && !strcmp(Mlt::EventData(data).to_string(), "_position")) { 0037 mlt_properties filter_props = MLT_FILTER_PROPERTIES(widget->m_monitorFilter->get_filter()); 0038 int pos = mlt_properties_get_int(filter_props, "_position"); 0039 if (!widget->m_levels.contains(pos)) { 0040 QVector<double> levels; 0041 for (int i = 0; i < widget->m_channels; i++) { 0042 // NOTE: this is an approximation. To get the real peak level, we need version 2 of audiolevel MLT filter, see property_changedV2 0043 levels << log10(mlt_properties_get_double(filter_props, QString("_audio_level.%1").arg(i).toUtf8().constData()) / 1.18) * 20; 0044 } 0045 widget->m_levels[pos] = std::move(levels); 0046 if (widget->m_levels.size() > widget->m_maxLevels) { 0047 widget->m_levels.erase(widget->m_levels.begin()); 0048 } 0049 } 0050 } 0051 } 0052 0053 void MixerWidget::property_changedV2(mlt_service, MixerWidget *widget, mlt_event_data data) 0054 { 0055 if (widget && !strcmp(Mlt::EventData(data).to_string(), "_position")) { 0056 mlt_properties filter_props = MLT_FILTER_PROPERTIES(widget->m_monitorFilter->get_filter()); 0057 int pos = mlt_properties_get_int(filter_props, "_position"); 0058 if (!widget->m_levels.contains(pos)) { 0059 QVector<double> levels; 0060 for (int i = 0; i < widget->m_channels; i++) { 0061 levels << mlt_properties_get_double(filter_props, QString("_audio_level.%1").arg(i).toUtf8().constData()); 0062 } 0063 widget->m_levels[pos] = std::move(levels); 0064 if (widget->m_levels.size() > widget->m_maxLevels) { 0065 widget->m_levels.erase(widget->m_levels.begin()); 0066 } 0067 } 0068 } 0069 } 0070 0071 MixerWidget::MixerWidget(int tid, Mlt::Tractor *service, QString trackTag, const QString &trackName, int sliderHandle, MixerManager *parent) 0072 : QWidget(parent) 0073 , m_manager(parent) 0074 , m_tid(tid) 0075 , m_levelFilter(nullptr) 0076 , m_monitorFilter(nullptr) 0077 , m_balanceFilter(nullptr) 0078 , m_channels(pCore->audioChannels()) 0079 , m_balanceSpin(nullptr) 0080 , m_balanceSlider(nullptr) 0081 , m_maxLevels(qMax(30, int(service->get_fps() * 1.5))) 0082 , m_solo(nullptr) 0083 , m_collapse(nullptr) 0084 , m_monitor(nullptr) 0085 , m_lastVolume(0) 0086 , m_listener(nullptr) 0087 , m_recording(false) 0088 , m_trackTag(std::move(trackTag)) 0089 , m_sliderHandleSize(sliderHandle) 0090 { 0091 buildUI(service, trackName); 0092 } 0093 0094 MixerWidget::~MixerWidget() 0095 { 0096 if (m_listener) { 0097 delete m_listener; 0098 } 0099 } 0100 0101 void MixerWidget::buildUI(Mlt::Tractor *service, const QString &trackName) 0102 { 0103 setFont(QFontDatabase::systemFont(QFontDatabase::SmallestReadableFont)); 0104 // Build audio meter widget 0105 m_audioMeterWidget.reset(new AudioLevelWidget(width(), m_sliderHandleSize, this)); 0106 // initialize for stereo display 0107 for (int i = 0; i < m_channels; i++) { 0108 m_audioData << -100; 0109 } 0110 m_audioMeterWidget->setAudioValues(m_audioData); 0111 0112 // Build volume widget 0113 m_volumeSlider = new QSlider(Qt::Vertical, this); 0114 m_volumeSlider->setRange(0, 10000); 0115 m_volumeSlider->setValue(6000); 0116 m_volumeSlider->setSingleStep(50); 0117 m_volumeSlider->setToolTip(i18n("Volume")); 0118 m_volumeSlider->setWhatsThis(xi18nc("@info:whatsthis", "Adjusts the output volume of the audio track (affects all audio clips equally).")); 0119 m_volumeSpin = new QDoubleSpinBox(this); 0120 m_volumeSpin->setRange(-50, 24); 0121 m_volumeSpin->setSuffix(i18n("dB")); 0122 m_volumeSpin->setFrame(false); 0123 0124 connect(m_volumeSpin, &QDoubleSpinBox::editingFinished, this, [&]() { 0125 double val = m_volumeSpin->value(); 0126 if (m_monitor && m_monitor->isChecked()) { 0127 m_volumeSlider->setValue(val * 100.); 0128 } else { 0129 m_volumeSlider->setValue(fromDB(val) * 100.); 0130 } 0131 }); 0132 0133 QLabel *labelLeft = nullptr; 0134 QLabel *labelRight = nullptr; 0135 if (m_channels == 2) { 0136 m_balanceSlider = new QSlider(Qt::Horizontal, this); 0137 m_balanceSlider->setRange(-50, 50); 0138 m_balanceSlider->setValue(0); 0139 m_balanceSlider->setTickPosition(QSlider::TicksBelow); 0140 m_balanceSlider->setTickInterval(50); 0141 m_balanceSlider->setToolTip(i18n("Balance")); 0142 m_balanceSlider->setWhatsThis(xi18nc("@info:whatsthis", "Adjusts the output balance of the track. Negative values move the output towards the left, " 0143 "positive values to the right. Affects all audio clips equally.")); 0144 0145 labelLeft = new QLabel(i18nc("Left", "L"), this); 0146 labelLeft->setAlignment(Qt::AlignHCenter); 0147 labelRight = new QLabel(i18nc("Right", "R"), this); 0148 labelRight->setAlignment(Qt::AlignHCenter); 0149 0150 m_balanceSpin = new QSpinBox(this); 0151 m_balanceSpin->setRange(-50, 50); 0152 m_balanceSpin->setValue(0); 0153 m_balanceSpin->setFrame(false); 0154 m_balanceSpin->setToolTip(i18n("Balance")); 0155 m_balanceSpin->setWhatsThis(xi18nc("@info:whatsthis", "Adjusts the output balance of the track. Negative values move the output towards the left, " 0156 "positive values to the right. Affects all audio clips equally.")); 0157 } 0158 0159 // Check if we already have built-in filters for this tractor 0160 int max = service->filter_count(); 0161 for (int i = 0; i < max; i++) { 0162 std::shared_ptr<Mlt::Filter> fl(service->filter(i)); 0163 if (!fl->is_valid()) { 0164 continue; 0165 } 0166 const QString filterService = fl->get("mlt_service"); 0167 if (filterService == QLatin1String("audiolevel")) { 0168 m_monitorFilter = fl; 0169 m_monitorFilter->set("disable", 0); 0170 } else if (filterService == QLatin1String("volume")) { 0171 m_levelFilter = fl; 0172 double volume = m_levelFilter->get_double("level"); 0173 m_volumeSpin->setValue(volume); 0174 m_volumeSlider->setValue(fromDB(volume) * 100.); 0175 } else if (m_channels == 2 && filterService == QLatin1String("panner")) { 0176 m_balanceFilter = fl; 0177 int val = int(m_balanceFilter->get_double("start") * 100) - 50; 0178 m_balanceSpin->setValue(val); 0179 m_balanceSlider->setValue(val); 0180 } 0181 } 0182 // Build default filters if not found 0183 if (m_levelFilter == nullptr) { 0184 m_levelFilter.reset(new Mlt::Filter(service->get_profile(), "volume")); 0185 if (m_levelFilter->is_valid()) { 0186 m_levelFilter->set("internal_added", 237); 0187 m_levelFilter->set("disable", 1); 0188 service->attach(*m_levelFilter.get()); 0189 } 0190 } 0191 if (m_balanceFilter == nullptr && m_channels == 2) { 0192 m_balanceFilter.reset(new Mlt::Filter(service->get_profile(), "panner")); 0193 if (m_balanceFilter->is_valid()) { 0194 m_balanceFilter->set("internal_added", 237); 0195 m_balanceFilter->set("start", 0.5); 0196 m_balanceFilter->set("disable", 1); 0197 service->attach(*m_balanceFilter.get()); 0198 } 0199 } 0200 // Monitoring should be appended last so that other effects are reflected in audio monitor 0201 if (m_monitorFilter == nullptr && m_tid != -1) { 0202 m_monitorFilter.reset(new Mlt::Filter(service->get_profile(), "audiolevel")); 0203 if (m_monitorFilter->is_valid()) { 0204 m_monitorFilter->set("iec_scale", 0); 0205 if (m_manager->audioLevelV2()) { 0206 m_monitorFilter->set("dbpeak", 1); 0207 } 0208 service->attach(*m_monitorFilter.get()); 0209 } 0210 } 0211 0212 m_trackLabel = new KSqueezedTextLabel(this); 0213 m_trackLabel->setAutoFillBackground(true); 0214 m_trackLabel->setAlignment(Qt::AlignHCenter); 0215 m_trackLabel->setFrameStyle(QFrame::Panel | QFrame::Sunken); 0216 m_trackLabel->setTextElideMode(Qt::ElideRight); 0217 setTrackName(trackName); 0218 m_muteAction = new KDualAction(i18n("Mute track"), i18n("Unmute track"), this); 0219 m_muteAction->setWhatsThis(xi18nc("@info:whatsthis", "Mutes/un-mutes the audio track.")); 0220 m_muteAction->setActiveIcon(QIcon::fromTheme(QStringLiteral("kdenlive-hide-audio"))); 0221 m_muteAction->setInactiveIcon(QIcon::fromTheme(QStringLiteral("kdenlive-show-audio"))); 0222 0223 if (m_balanceSlider) { 0224 connect(m_balanceSlider, &QSlider::valueChanged, m_balanceSpin, &QSpinBox::setValue); 0225 } 0226 0227 connect(m_muteAction, &KDualAction::activeChangedByUser, this, [&](bool active) { 0228 if (m_tid == -1) { 0229 // Muting master, special case 0230 if (m_levelFilter) { 0231 if (active) { 0232 m_lastVolume = m_levelFilter->get_double("level"); 0233 m_levelFilter->set("level", -1000); 0234 m_levelFilter->set("disable", 0); 0235 } else { 0236 m_levelFilter->set("level", m_lastVolume); 0237 m_levelFilter->set("disable", qFuzzyIsNull(m_lastVolume) ? 1 : 0); 0238 } 0239 } 0240 } else { 0241 Q_EMIT muteTrack(m_tid, !active); 0242 reset(); 0243 } 0244 pCore->setDocumentModified(); 0245 updateLabel(); 0246 }); 0247 0248 auto *mute = new QToolButton(this); 0249 mute->setDefaultAction(m_muteAction); 0250 mute->setAutoRaise(true); 0251 0252 QToolButton *showEffects = nullptr; 0253 0254 // Setup default width 0255 setFixedWidth(3 * mute->sizeHint().width()); 0256 0257 if (m_tid > -1) { 0258 // Solo / rec button only on tracks (not on master) 0259 m_solo = new QToolButton(this); 0260 m_solo->setCheckable(true); 0261 m_solo->setIcon(QIcon::fromTheme("headphones")); 0262 m_solo->setToolTip(i18n("Solo mode")); 0263 m_solo->setWhatsThis(xi18nc("@info:whatsthis", "When selected mutes all other audio tracks.")); 0264 m_solo->setAutoRaise(true); 0265 connect(m_solo, &QToolButton::toggled, this, [&](bool toggled) { 0266 Q_EMIT toggleSolo(m_tid, toggled); 0267 updateLabel(); 0268 }); 0269 0270 m_monitor = new QToolButton(this); 0271 m_monitor->setIcon(QIcon::fromTheme("audio-input-microphone")); 0272 m_monitor->setToolTip(i18n("Record audio")); 0273 m_monitor->setWhatsThis(xi18nc("@info:whatsthis", "Puts the audio track into recording mode.")); 0274 m_monitor->setCheckable(true); 0275 m_monitor->setAutoRaise(true); 0276 connect(m_monitor, &QToolButton::toggled, this, [&](bool toggled) { 0277 if (!toggled && (m_recording || pCore->isMediaCapturing())) { 0278 // Abort recording if in progress 0279 Q_EMIT pCore->recordAudio(m_tid, false); 0280 } 0281 m_manager->monitorAudio(m_tid, toggled); 0282 }); 0283 } else { 0284 m_collapse = new QToolButton(this); 0285 m_collapse->setIcon(KdenliveSettings::mixerCollapse() ? QIcon::fromTheme("arrow-left") : QIcon::fromTheme("arrow-right")); 0286 m_collapse->setToolTip(i18n("Show channels")); 0287 m_collapse->setWhatsThis(xi18nc("@info:whatsthis", "Toggles the display of the audio track controls in the audio mixer view.")); 0288 m_collapse->setCheckable(true); 0289 m_collapse->setAutoRaise(true); 0290 m_collapse->setChecked(KdenliveSettings::mixerCollapse()); 0291 connect(m_collapse, &QToolButton::clicked, this, [&]() { 0292 KdenliveSettings::setMixerCollapse(m_collapse->isChecked()); 0293 m_collapse->setIcon(m_collapse->isChecked() ? QIcon::fromTheme("arrow-left") : QIcon::fromTheme("arrow-right")); 0294 m_manager->collapseMixers(); 0295 }); 0296 } 0297 showEffects = new QToolButton(this); 0298 showEffects->setIcon(QIcon::fromTheme("autocorrection")); 0299 showEffects->setToolTip(i18n("Open Effect Stack")); 0300 if (m_tid > -1) { 0301 showEffects->setWhatsThis(xi18nc("@info:whatsthis", "Opens the effect stack for the audio track.")); 0302 } else { 0303 showEffects->setWhatsThis(xi18nc("@info:whatsthis", "Opens the effect stack for the audio master.")); 0304 } 0305 showEffects->setAutoRaise(true); 0306 connect(showEffects, &QToolButton::clicked, this, [&]() { Q_EMIT m_manager->showEffectStack(m_tid); }); 0307 0308 connect(m_volumeSlider, &QSlider::valueChanged, this, [&](int value) { 0309 QSignalBlocker bk(m_volumeSpin); 0310 if (m_recording || (m_monitor && m_monitor->isChecked())) { 0311 m_volumeSpin->setValue(value / 100); 0312 KdenliveSettings::setAudiocapturevolume(value / 100); 0313 Q_EMIT m_manager->updateRecVolume(); 0314 // TODO update capture volume 0315 } else if (m_levelFilter != nullptr) { 0316 double dbValue = 0; 0317 if (value > 6000) { 0318 // increase volume 0319 dbValue = 24 * (1 - log10((100 - value / 100.) * 0.225 + 1)); 0320 } else if (value < 6000) { 0321 dbValue = -50 * (1 - log10(10 - (value / 100. - 59) * (-0.11395))); 0322 } 0323 m_volumeSpin->setValue(dbValue); 0324 m_levelFilter->set("level", dbValue); 0325 m_levelFilter->set("disable", value == 60 ? 1 : 0); 0326 m_levels.clear(); 0327 Q_EMIT m_manager->purgeCache(); 0328 pCore->setDocumentModified(); 0329 } 0330 }); 0331 if (m_balanceSlider) { 0332 connect(m_balanceSpin, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), this, [&](int value) { 0333 QSignalBlocker bk(m_balanceSlider); 0334 m_balanceSlider->setValue(value); 0335 if (m_balanceFilter != nullptr) { 0336 m_balanceFilter->set("start", (value + 50) / 100.); 0337 m_balanceFilter->set("disable", value == 0 ? 1 : 0); 0338 m_levels.clear(); 0339 Q_EMIT m_manager->purgeCache(); 0340 pCore->setDocumentModified(); 0341 } 0342 }); 0343 } 0344 auto *lay = new QVBoxLayout; 0345 setContentsMargins(0, 0, 0, 0); 0346 lay->setContentsMargins(0, 0, 0, 0); 0347 lay->addWidget(m_trackLabel); 0348 auto *buttonslay = new QHBoxLayout; 0349 buttonslay->setSpacing(0); 0350 buttonslay->setContentsMargins(0, 0, 0, 0); 0351 if (m_collapse) { 0352 buttonslay->addWidget(m_collapse); 0353 } 0354 buttonslay->addWidget(mute); 0355 if (m_solo) { 0356 buttonslay->addWidget(m_solo); 0357 } 0358 if (m_monitor) { 0359 buttonslay->addWidget(m_monitor); 0360 } 0361 if (showEffects) { 0362 buttonslay->addWidget(showEffects); 0363 } 0364 lay->addLayout(buttonslay); 0365 if (m_balanceSlider) { 0366 auto *balancelay = new QGridLayout; 0367 balancelay->addWidget(m_balanceSlider, 0, 0, 1, 3); 0368 balancelay->addWidget(labelLeft, 1, 0, 1, 1); 0369 balancelay->addWidget(m_balanceSpin, 1, 1, 1, 1); 0370 balancelay->addWidget(labelRight, 1, 2, 1, 1); 0371 lay->addLayout(balancelay); 0372 } 0373 auto *hlay = new QHBoxLayout; 0374 hlay->setSpacing(0); 0375 hlay->setContentsMargins(0, 0, 0, 0); 0376 hlay->addWidget(m_audioMeterWidget.get()); 0377 hlay->addWidget(m_volumeSlider); 0378 lay->addLayout(hlay); 0379 lay->addWidget(m_volumeSpin); 0380 lay->setStretch(4, 10); 0381 setLayout(lay); 0382 if (service->get_int("hide") > 1) { 0383 setMute(true); 0384 } 0385 } 0386 0387 void MixerWidget::mousePressEvent(QMouseEvent *event) 0388 { 0389 if (event->button() == Qt::RightButton) { 0390 QWidget *child = childAt(event->pos()); 0391 if (child == m_balanceSlider) { 0392 m_balanceSpin->setValue(0); 0393 } else if (child == m_volumeSlider) { 0394 m_volumeSlider->setValue(6000); 0395 } 0396 } else { 0397 QWidget::mousePressEvent(event); 0398 } 0399 } 0400 0401 void MixerWidget::setTrackName(const QString &name) 0402 { 0403 // Show only tag on master or if name is empty 0404 if (name.isEmpty() || m_tid == -1) { 0405 m_trackLabel->setText(m_trackTag); 0406 } else { 0407 m_trackLabel->setText(QString("%1 - %2").arg(m_trackTag, name)); 0408 } 0409 } 0410 0411 void MixerWidget::setMute(bool mute) 0412 { 0413 m_muteAction->setActive(mute); 0414 m_volumeSlider->setEnabled(!mute); 0415 m_volumeSpin->setEnabled(!mute); 0416 m_audioMeterWidget->setEnabled(!mute); 0417 if (m_balanceSlider) { 0418 m_balanceSpin->setEnabled(!mute); 0419 m_balanceSlider->setEnabled(!mute); 0420 } 0421 updateLabel(); 0422 } 0423 0424 void MixerWidget::updateLabel() 0425 { 0426 if (m_recording) { 0427 QPalette pal = m_trackLabel->palette(); 0428 pal.setColor(QPalette::Window, Qt::red); 0429 m_trackLabel->setPalette(pal); 0430 } else if (m_monitor && m_monitor->isChecked()) { 0431 QPalette pal = m_trackLabel->palette(); 0432 pal.setColor(QPalette::Window, Qt::darkBlue); 0433 m_trackLabel->setPalette(pal); 0434 } else if (m_muteAction->isActive()) { 0435 QPalette pal = m_trackLabel->palette(); 0436 pal.setColor(QPalette::Window, QColor(0xff8c00)); 0437 m_trackLabel->setPalette(pal); 0438 } else if (m_solo && m_solo->isChecked()) { 0439 QPalette pal = m_trackLabel->palette(); 0440 pal.setColor(QPalette::Window, Qt::darkGreen); 0441 m_trackLabel->setPalette(pal); 0442 } else { 0443 QPalette pal = palette(); 0444 m_trackLabel->setPalette(pal); 0445 } 0446 } 0447 0448 void MixerWidget::updateAudioLevel(int pos) 0449 { 0450 QMutexLocker lk(&m_storeMutex); 0451 if (m_levels.contains(pos)) { 0452 m_audioMeterWidget->setAudioValues(m_levels.value(pos)); 0453 // m_levels.remove(pos); 0454 } else { 0455 m_audioMeterWidget->setAudioValues(m_audioData); 0456 } 0457 } 0458 0459 void MixerWidget::reset() 0460 { 0461 QMutexLocker lk(&m_storeMutex); 0462 m_levels.clear(); 0463 m_audioMeterWidget->setAudioValues(m_audioData); 0464 } 0465 0466 void MixerWidget::clear() 0467 { 0468 QMutexLocker lk(&m_storeMutex); 0469 m_levels.clear(); 0470 } 0471 0472 bool MixerWidget::isMute() const 0473 { 0474 return m_muteAction->isActive(); 0475 } 0476 0477 void MixerWidget::unSolo() 0478 { 0479 if (m_solo) { 0480 QSignalBlocker bl(m_solo); 0481 m_solo->setChecked(false); 0482 } 0483 } 0484 0485 void MixerWidget::gotRecLevels(QVector<qreal> levels) 0486 { 0487 switch (levels.size()) { 0488 case 0: 0489 m_audioMeterWidget->setAudioValues({-100, -100}); 0490 break; 0491 case 1: 0492 m_audioMeterWidget->setAudioValues({levels[0]}); 0493 break; 0494 default: 0495 m_audioMeterWidget->setAudioValues({levels[0], levels[1]}); 0496 break; 0497 } 0498 } 0499 0500 void MixerWidget::updateMonitorState() 0501 { 0502 QSignalBlocker bk(m_volumeSpin); 0503 QSignalBlocker bk2(m_volumeSlider); 0504 if (m_monitor && m_monitor->isChecked()) { 0505 connect(pCore->getAudioDevice(), &MediaCapture::audioLevels, this, &MixerWidget::gotRecLevels); 0506 if (m_balanceSlider) { 0507 m_balanceSlider->setEnabled(false); 0508 m_balanceSpin->setEnabled(false); 0509 } 0510 m_volumeSpin->setRange(0, 100); 0511 m_volumeSpin->setSuffix(QStringLiteral("%")); 0512 m_volumeSpin->setValue(KdenliveSettings::audiocapturevolume()); 0513 m_volumeSlider->setValue(KdenliveSettings::audiocapturevolume() * 100); 0514 } else { 0515 disconnect(pCore->getAudioDevice(), &MediaCapture::audioLevels, this, &MixerWidget::gotRecLevels); 0516 if (m_balanceSlider) { 0517 m_balanceSlider->setEnabled(true); 0518 m_balanceSpin->setEnabled(true); 0519 } 0520 int level = m_levelFilter->get_int("level"); 0521 m_volumeSpin->setRange(-100, 60); 0522 m_volumeSpin->setSuffix(i18n("dB")); 0523 m_volumeSpin->setValue(level); 0524 m_volumeSlider->setValue(fromDB(level) * 100.); 0525 } 0526 updateLabel(); 0527 } 0528 0529 void MixerWidget::monitorAudio(bool monitor) 0530 { 0531 QSignalBlocker bk(m_monitor); 0532 qDebug() << ":::: MONIOTORING AUDIO: " << monitor; 0533 if (monitor) { 0534 m_monitor->setChecked(true); 0535 updateMonitorState(); 0536 } else { 0537 m_monitor->setChecked(false); 0538 updateMonitorState(); 0539 reset(); 0540 } 0541 } 0542 0543 void MixerWidget::setRecordState(bool recording) 0544 { 0545 m_recording = recording; 0546 updateMonitorState(); 0547 } 0548 0549 void MixerWidget::connectMixer(bool doConnect) 0550 { 0551 if (doConnect) { 0552 if (m_tid == -1) { 0553 // Master level 0554 connect(pCore.get(), &Core::audioLevelsAvailable, m_audioMeterWidget.get(), &AudioLevelWidget::setAudioValues); 0555 } else if (m_listener == nullptr) { 0556 m_listener = m_monitorFilter->listen("property-changed", this, 0557 m_manager->audioLevelV2() ? reinterpret_cast<mlt_listener>(property_changedV2) 0558 : reinterpret_cast<mlt_listener>(property_changed)); 0559 } 0560 } else { 0561 if (m_tid == -1) { 0562 disconnect(pCore.get(), &Core::audioLevelsAvailable, m_audioMeterWidget.get(), &AudioLevelWidget::setAudioValues); 0563 } else { 0564 delete m_listener; 0565 m_listener = nullptr; 0566 } 0567 } 0568 pauseMonitoring(!doConnect); 0569 } 0570 0571 void MixerWidget::pauseMonitoring(bool pause) 0572 { 0573 if (m_monitorFilter) { 0574 m_monitorFilter->set("disable", pause ? 1 : 0); 0575 } 0576 }