• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

mcallegari / qlcplus / 26643984380

29 May 2026 02:45PM UTC coverage: 34.968% (-0.07%) from 35.037%
26643984380

Pull #2036

github

web-flow
Merge dd2197bec into f9fbc19ef
Pull Request #2036: engine/audio: configurable spectrum grid for Audio Triggers

17 of 188 new or added lines in 5 files covered. (9.04%)

13 existing lines in 4 files now uncovered.

18309 of 52359 relevant lines covered (34.97%)

41042.29 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/ui/src/virtualconsole/vcaudiotriggers.cpp
1
/*
2
  Q Light Controller Plus
3
  vcaudiotriggers.cpp
4

5
  Copyright (c) Massimo Callegari
6

7
  Licensed under the Apache License, Version 2.0 (the "License");
8
  you may not use this file except in compliance with the License.
9
  You may obtain a copy of the License at
10

11
      http://www.apache.org/licenses/LICENSE-2.0.txt
12

13
  Unless required by applicable law or agreed to in writing, software
14
  distributed under the License is distributed on an "AS IS" BASIS,
15
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
  See the License for the specific language governing permissions and
17
  limitations under the License.
18
*/
19

20
#include <QXmlStreamReader>
21
#include <QXmlStreamWriter>
22
#include <QMessageBox>
23
#include <QSettings>
24
#include <QDebug>
25

26
#include "vcaudiotriggersproperties.h"
27
#include "vcpropertieseditor.h"
28
#include "vcaudiotriggers.h"
29
#include "audiocapture.h"
30
#include "spectrumgrid.h"
31
#include "genericfader.h"
32
#include "fadechannel.h"
33
#include "universe.h"
34
#include "audiobar.h"
35
#include "apputil.h"
36
#include "doc.h"
37

38
#define KXMLQLCVCATKey          QStringLiteral("Key")
39
#define KXMLQLCVCATBarsNumber   QStringLiteral("BarsNumber")
40

41
#define KXMLQLCVolumeBar    QStringLiteral("VolumeBar")
42
#define KXMLQLCSpectrumBar  QStringLiteral("SpectrumBar")
43

44
const QSize VCAudioTriggers::defaultSize(QSize(300, 200));
45

46
VCAudioTriggers::VCAudioTriggers(QWidget* parent, Doc* doc)
×
47
    : VCWidget(parent, doc)
48
    , m_hbox(NULL)
×
49
    , m_button(NULL)
×
50
    , m_label(NULL)
×
51
    , m_spectrum(NULL)
×
52
    , m_volumeSlider(NULL)
×
53
    , m_inputCapture(NULL)
×
NEW
54
    , m_spectrumGridMode(SpectrumGridMode::LogUniform)
×
NEW
55
    , m_spectrumLowBandGamma(1.0)
×
56
{
57
    /* Set the class name "VCAudioTriggers" as the object name as well */
58
    setObjectName(VCAudioTriggers::staticMetaObject.className());
×
59

60
    setType(VCWidget::AudioTriggersWidget);
×
61
    setFrameStyle(KVCFrameStyleSunken);
×
62

63
    new QVBoxLayout(this);
×
64

65
    /* Main HBox */
66
    m_hbox = new QHBoxLayout();
×
67
    m_hbox->setGeometry(QRect(0, 0, 300, 40));
×
68

69
    layout()->setSpacing(2);
×
70
    layout()->setContentsMargins(4, 4, 4, 4);
×
71
    layout()->addItem(m_hbox);
×
72

73
    m_button = new QToolButton(this);
×
74
    m_button->setStyle(AppUtil::saneStyle());
×
75
    m_button->setIconSize(QSize(32, 32));
×
76
    m_button->setMinimumSize(QSize(32, 32));
×
77
    m_button->setMaximumSize(QSize(32, 32));
×
78
    m_button->setIcon(QIcon(":/check.png"));
×
79
    m_button->setCheckable(true);
×
80
    QString btnSS = "QToolButton { background-color: #E0DFDF; border: 1px solid gray; border-radius: 3px; padding: 3px; } ";
×
81
    btnSS += "QToolButton:checked { background-color: #D7DE75; border: 1px solid gray; border-radius: 3px; padding: 3px; } ";
×
82
    m_button->setStyleSheet(btnSS);
×
83
    m_button->setEnabled(false);
×
84

85
    m_hbox->addWidget(m_button);
×
86
    connect(m_button, SIGNAL(toggled(bool)), this, SLOT(slotEnableButtonToggled(bool)));
×
87

88
    m_label = new QLabel(this);
×
89
    m_label->setText(this->caption());
×
90
    QString txtColor = "white";
×
91
    if (m_hasCustomForegroundColor)
×
92
        txtColor = this->foregroundColor().name();
×
93
    m_label->setStyleSheet("QLabel { background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #345D27, stop: 1 #0E1A0A); "
×
94
                           "color: " + txtColor + "; border-radius: 3px; padding: 3px; margin-left: 2px; }");
×
95

96
    if (m_hasCustomFont)
×
97
        m_label->setFont(font());
×
98
    else
99
    {
100
        QFont m_font = QApplication::font();
×
101
        m_font.setBold(true);
×
102
        m_font.setPixelSize(12);
×
103
        m_label->setFont(m_font);
×
104
    }
×
105
    m_hbox->addWidget(m_label);
×
106

107
    QSharedPointer<AudioCapture> capture(m_doc->audioInputCapture());
×
108
    m_inputCapture = capture.data();
×
109

110
    // create the  AudioBar items to hold the spectrum data.
111
    // To be loaded from the project
112
    m_volumeBar = new AudioBar(AudioBar::BarType::None, 0, id());
×
113
    m_spectrumBars.reserve(m_inputCapture->defaultBarsNumber());
×
114
    for (int i = 0; i < m_inputCapture->defaultBarsNumber(); i++)
×
115
    {
116
        AudioBar *asb = new AudioBar(AudioBar::BarType::None, 0, id());
×
117
        m_spectrumBars.append(asb);
×
118
    }
119

120
    QHBoxLayout *hbox2 = new QHBoxLayout();
×
121
    m_volumeSlider = new ClickAndGoSlider(this);
×
122
    m_volumeSlider->setOrientation(Qt::Vertical);
×
123
    m_volumeSlider->setRange(0, 100);
×
124
    m_volumeSlider->setSliderStyleSheet(CNG_DEFAULT_STYLE);
×
125
    m_volumeSlider->setValue(100);
×
126
    m_volumeSlider->setFixedWidth(32);
×
127
    m_volumeSlider->setEnabled(false);
×
128

129
    connect(m_volumeSlider, SIGNAL(valueChanged(int)),
×
130
            this, SLOT(slotVolumeChanged(int)));
131

132
    m_spectrum = new AudioTriggerWidget(this);
×
133
    m_spectrum->setBarsNumber(m_inputCapture->defaultBarsNumber());
×
134
    m_spectrum->setMaxFrequency(AudioCapture::maxFrequency());
×
135
    m_spectrum->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
×
NEW
136
    updateSpectrumBandLayout();
×
137

138
    layout()->addItem(hbox2);
×
139
    hbox2->addWidget(m_spectrum);
×
140
    hbox2->addWidget(m_volumeSlider);
×
141

142
    /* Initial size */
143
    QSettings settings;
×
144
    QVariant var = settings.value(SETTINGS_AUDIOTRIGGERS_SIZE);
×
145
    if (var.isValid() == true)
×
146
        resize(var.toSize());
×
147
    else
148
        resize(defaultSize);
×
149

150
    slotModeChanged(m_doc->mode());
×
151
}
×
152

153
VCAudioTriggers::~VCAudioTriggers()
×
154
{
155
    QSharedPointer<AudioCapture> capture(m_doc->audioInputCapture());
×
156

157
    if (m_inputCapture == capture.data())
×
NEW
158
        m_inputCapture->unregisterBands(m_spectrum->barsNumber(), m_spectrumGridMode, m_spectrumLowBandGamma);
×
159

160
    qDeleteAll(m_spectrumBars);
×
161
    delete m_volumeBar;
×
162
}
×
163

164
void VCAudioTriggers::enableWidgetUI(bool enable)
×
165
{
166
    if (m_button)
×
167
        m_button->setEnabled(enable);
×
168

169
    m_volumeSlider->setEnabled(enable);
×
170
}
×
171

172
void VCAudioTriggers::notifyFunctionStarting(quint32 fid, qreal intensity, bool excludeMonitored)
×
173
{
174
    // Stop on any other function started
175
    Q_UNUSED(fid)
176
    Q_UNUSED(intensity)
177
    Q_UNUSED(excludeMonitored)
178

179
    if (m_button->isChecked() == true)
×
180
        enableCapture(false);
×
181
}
×
182

183
void VCAudioTriggers::enableCapture(bool enable)
×
184
{
185
    // in case the audio input device has been changed in the meantime...
186
    QSharedPointer<AudioCapture> capture(m_doc->audioInputCapture());
×
187
    bool captureIsNew = m_inputCapture != capture.data();
×
188
    m_inputCapture = capture.data();
×
189

190
    if (enable == true)
×
191
    {
NEW
192
        connect(m_inputCapture, SIGNAL(dataProcessed(double*,int,double,quint32,int,double)),
×
193
                this, SLOT(slotDisplaySpectrum(double*,int,double,quint32,int,double)));
UNCOV
194
        connect(m_inputCapture, SIGNAL(volumeChanged(int)),
×
195
                this, SLOT(slotUpdateVolumeSlider(int)));
NEW
196
        m_inputCapture->registerBands(m_spectrum->barsNumber(), m_spectrumGridMode, m_spectrumLowBandGamma);
×
197

198
        m_button->blockSignals(true);
×
199
        m_button->setChecked(true);
×
200
        m_button->blockSignals(false);
×
201

202
        emit captureEnabled(true);
×
203

204
        // Invalid ID: Stop every other widget
205
        emit functionStarting(Function::invalidId());
×
206
    }
207
    else
208
    {
209
        if (!captureIsNew)
×
210
        {
NEW
211
            m_inputCapture->unregisterBands(m_spectrum->barsNumber(), m_spectrumGridMode, m_spectrumLowBandGamma);
×
NEW
212
            disconnect(m_inputCapture, SIGNAL(dataProcessed(double*,int,double,quint32,int,double)),
×
213
                       this, SLOT(slotDisplaySpectrum(double*,int,double,quint32,int,double)));
UNCOV
214
            disconnect(m_inputCapture, SIGNAL(volumeChanged(int)),
×
215
                       this, SLOT(slotUpdateVolumeSlider(int)));
216
        }
217

218
        m_button->blockSignals(true);
×
219
        m_button->setChecked(false);
×
220
        m_button->blockSignals(false);
×
221

222
        emit captureEnabled(false);
×
223
    }
224
}
×
225

226
void VCAudioTriggers::toggleEnableButton(bool toggle)
×
227
{
228
    if (mode() == Doc::Design)
×
229
        return;
×
230

231
    if (m_button)
×
232
        m_button->setChecked(toggle);
×
233
}
234

235
void VCAudioTriggers::slotEnableButtonToggled(bool toggle)
×
236
{
237
    if (mode() == Doc::Design)
×
238
        return;
×
239

240
    enableCapture(toggle);
×
241
    updateFeedback();
×
242
}
243

244
void VCAudioTriggers::slotDisplaySpectrum(double *spectrumBands, int size,
×
245
                                          double maxMagnitude, quint32 power,
246
                                          int spectrumGridMode, double spectrumLowBandGamma)
247
{
NEW
248
    if (spectrumGridMode != int(m_spectrumGridMode))
×
NEW
249
        return;
×
NEW
250
    if (qAbs(spectrumLowBandGamma - m_spectrumLowBandGamma) > 0.05)
×
NEW
251
        return;
×
252

253
    if (size != m_spectrum->barsNumber())
×
254
        return;
×
255

256
    m_spectrum->displaySpectrum(spectrumBands, maxMagnitude, power);
×
257
    m_volumeBar->m_value = m_spectrum->getUcharVolume();
×
258

259
    if (mode() == Doc::Design)
×
260
        return;
×
261

262
    if (m_volumeBar->m_type == AudioBar::BarType::FunctionBar)
×
263
        m_volumeBar->checkFunctionThresholds(m_doc);
×
264
    else if (m_volumeBar->m_type == AudioBar::BarType::VCWidgetBar)
×
265
        m_volumeBar->checkWidgetFunctionality();
×
266

267
    for (int i = 0; i < m_spectrumBars.count(); i++)
×
268
    {
269
        m_spectrumBars[i]->m_value = m_spectrum->getUcharBand(i);
×
270
        if (m_spectrumBars[i]->m_type == AudioBar::BarType::FunctionBar)
×
271
            m_spectrumBars[i]->checkFunctionThresholds(m_doc);
×
272
        else if (m_spectrumBars[i]->m_type == AudioBar::BarType::VCWidgetBar)
×
273
            m_spectrumBars[i]->checkWidgetFunctionality();
×
274
    }
275
}
276

277
void VCAudioTriggers::slotVolumeChanged(int volume)
×
278
{
279
    m_doc->audioInputCapture()->setVolume(intensity() * qreal(volume) / 100.0);
×
280
}
×
281

282
void VCAudioTriggers::slotUpdateVolumeSlider(int volume)
×
283
{
284
    m_volumeSlider->setValue(volume);
×
285
}
×
286

287
/*********************************************************************
288
 * DMXSource
289
 *********************************************************************/
290

291
void VCAudioTriggers::writeDMX(MasterTimer *timer, QList<Universe *> universes)
×
292
{
293
    Q_UNUSED(timer);
294

295
    if (mode() == Doc::Design)
×
296
        return;
×
297

298
    quint32 lastUniverse = Universe::invalid();
×
299
    QSharedPointer<GenericFader> fader;
×
300

301
    if (m_volumeBar->m_type == AudioBar::BarType::DMXBar)
×
302
    {
303
        for (int i = 0; i < m_volumeBar->m_absDmxChannels.count(); i++)
×
304
        {
305
            int absAddress = m_volumeBar->m_absDmxChannels.at(i);
×
306
            //quint32 address = absAddress & 0x01FF;
307
            quint32 universe = absAddress >> 9;
×
308
            if (universe != lastUniverse)
×
309
            {
310
                fader = m_fadersMap.value(universe, QSharedPointer<GenericFader>());
×
311
                if (fader.isNull())
×
312
                {
313
                    fader = universes[universe]->requestFader();
×
314
                    fader->adjustIntensity(intensity());
×
315
                    m_fadersMap[universe] = fader;
×
316
                }
317
                lastUniverse = universe;
×
318
                fader->setEnabled(m_button->isChecked() ? true : false);
×
319
            }
320

321
            FadeChannel *fc = fader->getChannelFader(m_doc, universes[universe], Fixture::invalidId(), absAddress);           
×
322
            fc->setStart(fc->current());
×
323
            fc->setTarget(m_volumeBar->m_value);
×
324
            fc->setReady(false);
×
325
            fc->setElapsed(0);
×
326
        }
327
    }
328
    foreach (AudioBar *sb, m_spectrumBars)
×
329
    {
330
        if (sb->m_type == AudioBar::BarType::DMXBar)
×
331
        {
332
            for (int i = 0; i < sb->m_absDmxChannels.count(); i++)
×
333
            {
334
                int absAddress = sb->m_absDmxChannels.at(i);
×
335
                //quint32 address = absAddress & 0x01FF;
336
                quint32 universe = absAddress >> 9;
×
337
                if (universe != lastUniverse)
×
338
                {
339
                    fader = m_fadersMap.value(universe, QSharedPointer<GenericFader>());
×
340
                    if (fader == NULL)
×
341
                    {
342
                        fader = universes[universe]->requestFader();
×
343
                        fader->adjustIntensity(intensity());
×
344
                        m_fadersMap[universe] = fader;
×
345
                    }
346
                    fader->setEnabled(m_button->isChecked() ? true : false);
×
347
                    lastUniverse = universe;
×
348
                }
349

350
                FadeChannel *fc = fader->getChannelFader(m_doc, universes[universe], Fixture::invalidId(), absAddress);
×
351
                fc->setStart(fc->current());
×
352
                fc->setTarget(sb->m_value);
×
353
                fc->setReady(false);
×
354
                fc->setElapsed(0);
×
355
            }
356
        }
357
    }
×
358
}
×
359

360
/*********************************************************************
361
 * Key sequence handler
362
 *********************************************************************/
363

364
void VCAudioTriggers::setKeySequence(const QKeySequence& keySequence)
×
365
{
366
    m_keySequence = QKeySequence(keySequence);
×
367
}
×
368

369
QKeySequence VCAudioTriggers::keySequence() const
×
370
{
371
    return m_keySequence;
×
372
}
373

374
void VCAudioTriggers::slotKeyPressed(const QKeySequence& keySequence)
×
375
{
376
    if (acceptsInput() == false)
×
377
        return;
×
378

379
    if (m_keySequence == keySequence)
×
380
    {
381
        if (m_button->isChecked())
×
382
            slotEnableButtonToggled(false);
×
383
        else
384
            slotEnableButtonToggled(true);
×
385
    }
386
}
387

388
void VCAudioTriggers::updateFeedback()
×
389
{
390
    QSharedPointer<QLCInputSource> src = inputSource();
×
391
    if (!src.isNull() && src->isValid() == true)
×
392
    {
393
        if (m_button->isChecked())
×
394
            sendFeedback(src->feedbackValue(QLCInputFeedback::UpperValue));
×
395
        else
396
            sendFeedback(src->feedbackValue(QLCInputFeedback::LowerValue));
×
397
    }
398
}
×
399

400
void VCAudioTriggers::slotInputValueChanged(quint32 universe, quint32 channel, uchar value)
×
401
{
402
    /* Don't let input data through in design mode or if disabled */
403
    if (acceptsInput() == false)
×
404
        return;
×
405

406
    if (checkInputSource(universe, (page() << 16) | channel, value, sender()) && value > 0)
×
407
    {
408
        if (m_button->isChecked())
×
409
            slotEnableButtonToggled(false);
×
410
        else
411
            slotEnableButtonToggled(true);
×
412
    }
413
}
414

415
/*********************************************************************
416
 * Clipboard
417
 *********************************************************************/
418

419
VCWidget *VCAudioTriggers::createCopy(VCWidget *parent) const
×
420
{
421
    Q_ASSERT(parent != NULL);
×
422

423
    VCAudioTriggers* triggers = new VCAudioTriggers(parent, m_doc);
×
424
    if (triggers->copyFrom(this) == false)
×
425
    {
426
        delete triggers;
×
427
        triggers = NULL;
×
428
    }
429

430
    return triggers;
×
431
}
432

433
bool VCAudioTriggers::copyFrom(const VCWidget *widget)
×
434
{
435
    const VCAudioTriggers* triggers = qobject_cast <const VCAudioTriggers*> (widget);
×
436
    if (triggers == NULL)
×
437
        return false;
×
438

NEW
439
    m_spectrumGridMode = triggers->m_spectrumGridMode;
×
NEW
440
    m_spectrumLowBandGamma = triggers->m_spectrumLowBandGamma;
×
NEW
441
    updateSpectrumBandLayout();
×
442

UNCOV
443
    return VCWidget::copyFrom(widget);
×
444
}
445

NEW
446
SpectrumGridMode VCAudioTriggers::spectrumGridMode() const
×
447
{
NEW
448
    return m_spectrumGridMode;
×
449
}
450

NEW
451
void VCAudioTriggers::setSpectrumGridMode(SpectrumGridMode mode)
×
452
{
NEW
453
    if (m_spectrumGridMode == mode)
×
NEW
454
        return;
×
455

NEW
456
    const int bars = m_spectrum->barsNumber();
×
NEW
457
    const bool capturing = (m_button && m_button->isChecked());
×
458

NEW
459
    if (capturing && m_inputCapture)
×
460
    {
NEW
461
        m_inputCapture->unregisterBands(bars, m_spectrumGridMode, m_spectrumLowBandGamma);
×
NEW
462
        m_spectrumGridMode = mode;
×
NEW
463
        m_inputCapture->registerBands(bars, m_spectrumGridMode, m_spectrumLowBandGamma);
×
464
    }
465
    else
466
    {
NEW
467
        m_spectrumGridMode = mode;
×
468
    }
469

NEW
470
    updateSpectrumBandLayout();
×
471
}
472

NEW
473
double VCAudioTriggers::spectrumLowBandGamma() const
×
474
{
NEW
475
    return m_spectrumLowBandGamma;
×
476
}
477

NEW
478
void VCAudioTriggers::setSpectrumLowBandGamma(double gamma)
×
479
{
NEW
480
    gamma = qBound(1.0, gamma, 4.0);
×
NEW
481
    if (qAbs(m_spectrumLowBandGamma - gamma) < 0.05)
×
NEW
482
        return;
×
483

NEW
484
    const int bars = m_spectrum->barsNumber();
×
NEW
485
    const bool capturing = (m_button && m_button->isChecked());
×
486

NEW
487
    if (capturing && m_inputCapture)
×
488
    {
NEW
489
        m_inputCapture->unregisterBands(bars, m_spectrumGridMode, m_spectrumLowBandGamma);
×
NEW
490
        m_spectrumLowBandGamma = gamma;
×
NEW
491
        m_inputCapture->registerBands(bars, m_spectrumGridMode, m_spectrumLowBandGamma);
×
492
    }
493
    else
494
    {
NEW
495
        m_spectrumLowBandGamma = gamma;
×
496
    }
497

NEW
498
    updateSpectrumBandLayout();
×
499
}
500

NEW
501
void VCAudioTriggers::updateSpectrumBandLayout()
×
502
{
NEW
503
    if (m_spectrum == NULL)
×
NEW
504
        return;
×
505

NEW
506
    const double minFreq = qMax(1.0, double(AudioCapture::minFrequency()));
×
NEW
507
    const double maxFreq = double(AudioCapture::maxFrequency());
×
NEW
508
    const QVector<double> edges = computeSpectrumBandEdges(m_spectrum->barsNumber(),
×
509
                                                           minFreq, maxFreq, m_spectrumGridMode,
NEW
510
                                                           m_spectrumLowBandGamma);
×
NEW
511
    m_spectrum->setBandFrequencyEdges(edges);
×
NEW
512
}
×
513

514
/*************************************************************************
515
 * VCWidget-inherited
516
 *************************************************************************/
517

518
void VCAudioTriggers::setCaption(const QString &text)
×
519
{
520
    if (m_label != NULL)
×
521
        m_label->setText(text);
×
522

523
    VCWidget::setCaption(text);
×
524
}
×
525

526
void VCAudioTriggers::setForegroundColor(const QColor &color)
×
527
{
528
    if (m_label != NULL)
×
529
    {
530
        m_label->setStyleSheet("QLabel { background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #345D27, stop: 1 #0E1A0A); "
×
531
                               "color: " + color.name() + "; border-radius: 3px; padding: 3px; margin-left: 2px; }");
×
532
        m_hasCustomForegroundColor = true;
×
533
        m_doc->setModified();
×
534
    }
535
}
×
536

537
QColor VCAudioTriggers::foregroundColor() const
×
538
{
539
    if (m_label != NULL)
×
540
        return m_label->palette().color(m_label->foregroundRole());
×
541
    else
542
        return VCWidget::foregroundColor();
×
543
}
544

545
void VCAudioTriggers::slotModeChanged(Doc::Mode mode)
×
546
{
547
    if (mode == Doc::Operate)
×
548
    {
549
        enableWidgetUI(true);
×
550

551
        foreach (AudioBar *bar, getAudioBars())
×
552
        {
553
            if (bar->m_type == AudioBar::BarType::DMXBar)
×
554
            {
555
                m_doc->masterTimer()->registerDMXSource(this);
×
556
                break;
×
557
            }
558
        }
×
559
    }
560
    else
561
    {
562
        enableWidgetUI(false);
×
563
        enableCapture(false);
×
564
        m_doc->masterTimer()->unregisterDMXSource(this);
×
565

566
        // request to delete all the active faders
567
        foreach (QSharedPointer<GenericFader> fader, m_fadersMap)
×
568
        {
569
            if (!fader.isNull())
×
570
                fader->requestDelete();
×
571
        }
×
572
        m_fadersMap.clear();
×
573
    }
574
    VCWidget::slotModeChanged(mode);
×
575
}
×
576

577
/*************************************************************************
578
 * Configuration
579
 *************************************************************************/
580

581
AudioBar *VCAudioTriggers::getSpectrumBar(int index)
×
582
{
583
    if (index == volumeBarIndex())
×
584
        return m_volumeBar;
×
585
    if (index >= 0 && index < m_spectrumBars.size())
×
586
        return m_spectrumBars.at(index);
×
587

588
    return NULL;
×
589
}
590

591
QList<AudioBar *> VCAudioTriggers::getAudioBars()
×
592
{
593
    QList <AudioBar *> list;
×
594
    list.reserve(1 + m_spectrumBars.size());
×
595
    list.append(m_volumeBar);
×
596
    list.append(m_spectrumBars);
×
597

598
    return list;
×
599
}
×
600

601
void VCAudioTriggers::setSpectrumBarsNumber(int num)
×
602
{
603
    if (num > m_spectrumBars.count())
×
604
    {
605
        int barsToAdd = num - m_spectrumBars.count();
×
606
        for (int i = 0 ; i < barsToAdd; i++)
×
607
        {
608
            AudioBar *asb = new AudioBar(AudioBar::BarType::None, 0, id());
×
609
            m_spectrumBars.append(asb);
×
610
        }
611
    }
612
    else if (num < m_spectrumBars.count())
×
613
    {
614
        int barsToRemove = m_spectrumBars.count() - num;
×
615
        for (int i = 0 ; i < barsToRemove; i++)
×
616
            delete m_spectrumBars.takeLast();
×
617
    }
618

619
    if (m_spectrum != NULL)
×
620
        m_spectrum->setBarsNumber(num);
×
621

NEW
622
    updateSpectrumBandLayout();
×
UNCOV
623
}
×
624

625
void VCAudioTriggers::setSpectrumBarType(int index, int type)
×
626
{
627
    if (index == volumeBarIndex())
×
628
    {
629
        m_volumeBar->setType(type);
×
630
        return;
×
631
    }
632
    if (index >= 0 && index < m_spectrumBars.size())
×
633
    {
634
        m_spectrumBars[index]->setType(type);
×
635
    }
636
}
637

638
void VCAudioTriggers::editProperties()
×
639
{
640
    // make a backup copy of the current bars
641
    AudioBar *tmpVolume = m_volumeBar->createCopy();
×
642
    QList <AudioBar *> tmpSpectrumBars;
×
643
    foreach (AudioBar *bar, m_spectrumBars)
×
644
        tmpSpectrumBars.append(bar->createCopy());
×
645
    int barsNumber = m_spectrumBars.count();
×
646

647
    AudioTriggersConfiguration atc(this, m_doc, barsNumber, AudioCapture::maxFrequency());
×
648

649
    if (atc.exec() == QDialog::Rejected)
×
650
    {
651
        // restore the previous bars backup
652
        delete m_volumeBar;
×
653
        m_volumeBar = tmpVolume;
×
654
        qDeleteAll(m_spectrumBars);
×
655
        m_spectrumBars.clear();
×
656
        foreach (AudioBar *bar, tmpSpectrumBars)
×
657
            m_spectrumBars.append(bar);
×
658
    }
659

660
    m_spectrum->setBarsNumber(m_spectrumBars.count());
×
NEW
661
    updateSpectrumBandLayout();
×
662

663
    if (barsNumber != m_spectrumBars.count())
×
664
    {
665
        QSharedPointer<AudioCapture> capture(m_doc->audioInputCapture());
×
666
        bool captureIsNew = m_inputCapture != capture.data();
×
667
        m_inputCapture = capture.data();
×
668

669
        if (m_button->isChecked())
×
670
        {
671
            if (!captureIsNew)
×
NEW
672
                m_inputCapture->unregisterBands(barsNumber, m_spectrumGridMode, m_spectrumLowBandGamma);
×
673

NEW
674
            m_inputCapture->registerBands(m_spectrumBars.count(), m_spectrumGridMode, m_spectrumLowBandGamma);
×
675

676
            if (captureIsNew)
×
677
            {
NEW
678
                connect(m_inputCapture, SIGNAL(dataProcessed(double*,int,double,quint32,int,double)),
×
679
                        this, SLOT(slotDisplaySpectrum(double*,int,double,quint32,int,double)));
UNCOV
680
                connect(m_inputCapture, SIGNAL(volumeChanged(qreal)),
×
681
                        this, SLOT(slotUpdateVolumeSlider(int)));
682
            }
683
        }
684
    }
×
685
}
×
686

687
void VCAudioTriggers::adjustIntensity(qreal val)
×
688
{
689
    VCWidget::adjustIntensity(val);
×
690
    slotVolumeChanged(m_volumeSlider->value());
×
691
}
×
692

693
/*********************************************************************
694
 * Load & Save
695
 *********************************************************************/
696

697
bool VCAudioTriggers::loadXML(QXmlStreamReader &root)
×
698
{
699
    if (root.name() != KXMLQLCVCAudioTriggers)
×
700
    {
701
        qWarning() << Q_FUNC_INFO << "Audio Triggers node not found";
×
702
        return false;
×
703
    }
704
    if (root.attributes().hasAttribute(KXMLQLCVCATBarsNumber))
×
705
    {
706
        int barsNum = root.attributes().value(KXMLQLCVCATBarsNumber).toString().toInt();
×
707
        setSpectrumBarsNumber(barsNum);
×
708
    }
NEW
709
    if (root.attributes().hasAttribute(KXMLQLCVCATSpectrumGrid))
×
710
    {
NEW
711
        m_spectrumGridMode = spectrumGridModeFromString(
×
NEW
712
            root.attributes().value(KXMLQLCVCATSpectrumGrid).toString());
×
713
    }
NEW
714
    if (root.attributes().hasAttribute(KXMLQLCVCATSpectrumLowBandGamma))
×
715
    {
NEW
716
        m_spectrumLowBandGamma = qBound(1.0,
×
NEW
717
            root.attributes().value(KXMLQLCVCATSpectrumLowBandGamma).toString().toDouble(), 4.0);
×
718
    }
NEW
719
    updateSpectrumBandLayout();
×
720

721
    /* Widget commons */
722
    loadXMLCommon(root);
×
723

724
    /* Children */
725
    while (root.readNextStartElement())
×
726
    {
727
        //qDebug() << "VC Audio triggers tag:" << root.name();
728
        QXmlStreamAttributes attrs = root.attributes();
×
729

730
        if (root.name() == KXMLQLCWindowState)
×
731
        {
732
            int x = 0, y = 0, w = 0, h = 0;
×
733
            bool visible = false;
×
734
            loadXMLWindowState(root, &x, &y, &w, &h, &visible);
×
735
            setGeometry(x, y, w, h);
×
736
        }
737
        else if (root.name() == KXMLQLCVCWidgetAppearance)
×
738
        {
739
            loadXMLAppearance(root);
×
740
        }
741
        else if (root.name() == KXMLQLCVCWidgetInput)
×
742
        {
743
            loadXMLInput(root);
×
744
        }
745
        else if (root.name() == KXMLQLCVCATKey)
×
746
        {
747
            setKeySequence(stripKeySequence(QKeySequence(root.readElementText())));
×
748
        }
749
        else if (root.name() == KXMLQLCVolumeBar)
×
750
        {
751
            m_volumeBar->loadXML(root, m_doc);
×
752
        }
753
        else if (root.name() == KXMLQLCSpectrumBar)
×
754
        {
755
            if (attrs.hasAttribute(KXMLQLCAudioBarIndex))
×
756
            {
757
                int idx = attrs.value(KXMLQLCAudioBarIndex).toString().toInt();
×
758
                if (idx >= 0 && idx < m_spectrumBars.count())
×
759
                    m_spectrumBars[idx]->loadXML(root, m_doc);
×
760
            }
761
        }
762
        else
763
        {
764
            qWarning() << Q_FUNC_INFO << "Unknown audio triggers tag:" << root.name().toString();
×
765
            root.skipCurrentElement();
×
766
        }
767
    }
×
768

769
    return true;
×
770
}
771

772
bool VCAudioTriggers::saveXML(QXmlStreamWriter *doc)
×
773
{
774
    Q_ASSERT(doc != NULL);
×
775

776
    /* VC button entry */
777
    doc->writeStartElement(KXMLQLCVCAudioTriggers);
×
778
    doc->writeAttribute(KXMLQLCVCATBarsNumber, QString::number(m_spectrumBars.count()));
×
NEW
779
    doc->writeAttribute(KXMLQLCVCATSpectrumGrid, spectrumGridModeToString(m_spectrumGridMode));
×
NEW
780
    if (qAbs(m_spectrumLowBandGamma - 1.0) > 0.05)
×
NEW
781
        doc->writeAttribute(KXMLQLCVCATSpectrumLowBandGamma, QString::number(m_spectrumLowBandGamma, 'f', 1));
×
782

783
    saveXMLCommon(doc);
×
784

785
    /* Window state */
786
    saveXMLWindowState(doc);
×
787

788
    /* Appearance */
789
    saveXMLAppearance(doc);
×
790

791
    /* Key sequence */
792
    if (m_keySequence.isEmpty() == false)
×
793
        doc->writeTextElement(KXMLQLCVCATKey, m_keySequence.toString());
×
794

795
    /* External input */
796
    saveXMLInput(doc);
×
797

798
    /* Lookup for any assigned bar */
799
    bool hasAssignment = false;
×
800
    if (m_volumeBar->m_type != AudioBar::BarType::None)
×
801
        hasAssignment = true;
×
802
    else
803
    {
804
        foreach (AudioBar *bar, m_spectrumBars)
×
805
        {
806
            if (bar->m_type != AudioBar::BarType::None)
×
807
            {
808
                hasAssignment = true;
×
809
                break;
×
810
            }
811
        }
×
812
    }
813

814
    if (hasAssignment == false)
×
815
    {
816
        /* End the <AudioTriggers> tag */
817
        doc->writeEndElement();
×
818
        return false;
×
819
    }
820

821
    if (m_volumeBar->m_type != AudioBar::BarType::None)
×
822
    {
823
        m_volumeBar->saveXML(doc, KXMLQLCVolumeBar, volumeBarIndex());
×
824
    }
825
    int idx = 0;
×
826
    foreach (AudioBar *bar, m_spectrumBars)
×
827
    {
828
        if (bar->m_type != AudioBar::BarType::None)
×
829
            bar->saveXML(doc, KXMLQLCSpectrumBar, idx);
×
830
        idx++;
×
831
    }
×
832

833
    /* End the <AudioTriggers> tag */
834
    doc->writeEndElement();
×
835

836
    return true;
×
837
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc