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

mcallegari / qlcplus / 14445404527

14 Apr 2025 12:17PM UTC coverage: 31.854% (-0.05%) from 31.907%
14445404527

push

github

web-flow
Merge pull request #1714 from shaforostoff/webaccess_optimize_loadxml

engine: speedup loadXML methods by using QStringLiteral

1 of 1 new or added line in 1 file covered. (100.0%)

220 existing lines in 5 files now uncovered.

14674 of 46067 relevant lines covered (31.85%)

26455.49 hits per line

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

66.38
/engine/src/inputoutputmap.cpp
1
/*
2
  Q Light Controller Plus
3
  inputoutputmap.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
#if defined(WIN32) || defined(Q_OS_WIN)
21
#        include <Windows.h>
22
#else
23
#   include <unistd.h>
24
#endif
25

26
#include <QXmlStreamReader>
27
#include <QXmlStreamWriter>
28
#include <QElapsedTimer>
29
#include <QSettings>
30
#include <QDebug>
31
#include <qmath.h>
32

33
#include "inputoutputmap.h"
34
#include "qlcinputchannel.h"
35
#include "qlcinputsource.h"
36
#include "qlcioplugin.h"
37
#include "outputpatch.h"
38
#include "inputpatch.h"
39
#include "qlcconfig.h"
40
#include "universe.h"
41
#include "qlcfile.h"
42
#include "doc.h"
43

44
InputOutputMap::InputOutputMap(Doc *doc, quint32 universes)
200✔
45
  : QObject(doc)
46
  , m_blackout(false)
200✔
47
  , m_universeChanged(false)
200✔
48
  , m_currentBPM(0)
200✔
49
  , m_beatTime(new QElapsedTimer())
200✔
50
{
51
    m_grandMaster = new GrandMaster(this);
200✔
52
    for (quint32 i = 0; i < universes; i++)
1,000✔
53
        addUniverse();
800✔
54

55
    connect(doc->ioPluginCache(), SIGNAL(pluginConfigurationChanged(QLCIOPlugin*)),
200✔
56
            this, SLOT(slotPluginConfigurationChanged(QLCIOPlugin*)));
57
    connect(doc->masterTimer(), SIGNAL(beat()), this, SLOT(slotMasterTimerBeat()));
200✔
58
}
200✔
59

60
InputOutputMap::~InputOutputMap()
377✔
61
{
62
    removeAllUniverses();
200✔
63
    delete m_grandMaster;
200✔
64
    delete m_beatTime;
200✔
65
    qDeleteAll(m_profiles);
200✔
66
}
377✔
67

68
Doc* InputOutputMap::doc() const
867✔
69
{
70
    return qobject_cast<Doc*> (parent());
867✔
71
}
72

73
/*****************************************************************************
74
 * Blackout
75
 *****************************************************************************/
76

77
bool InputOutputMap::toggleBlackout()
4✔
78
{
79
    if (m_blackout == true)
4✔
80
        setBlackout(false);
2✔
81
    else
82
        setBlackout(true);
2✔
83

84
    return m_blackout;
4✔
85
}
86

87
bool InputOutputMap::setBlackout(bool blackout)
7✔
88
{
89
    /* Don't do blackout twice */
90
    if (m_blackout == blackout)
7✔
91
        return false;
92

93
    m_blackout = blackout;
5✔
94

95
    // blackout is an atomic setting, so it's safe to do it
96
    // without mutex locking
97
    foreach (Universe *universe, m_universeArray)
25✔
98
    {
99
        for (int i = 0; i < universe->outputPatchesCount(); i++)
32✔
100
        {
101
            OutputPatch *op = universe->outputPatch(i);
12✔
102
            if (op != NULL)
12✔
103
                op->setBlackout(blackout);
12✔
104
        }
105

106
        const QByteArray postGM = universe->postGMValues()->mid(0, universe->usedChannels());
20✔
107
        universe->dumpOutput(postGM, true);
20✔
108
    }
20✔
109

110
    emit blackoutChanged(m_blackout);
5✔
111

112
    return true;
5✔
113
}
114

UNCOV
115
void InputOutputMap::requestBlackout(BlackoutRequest blackout)
×
116
{
117
    if (blackout != BlackoutRequestNone)
×
118
        setBlackout(blackout == BlackoutRequestOn ? true : false);
×
UNCOV
119
}
×
120

121
bool InputOutputMap::blackout() const
9✔
122
{
123
    return m_blackout;
9✔
124
}
125

126
/*****************************************************************************
127
 * Universes
128
 *****************************************************************************/
129

130
quint32 InputOutputMap::invalidUniverse()
1,940✔
131
{
132
    return UINT_MAX;
1,940✔
133
}
134

135
bool InputOutputMap::addUniverse(quint32 id)
803✔
136
{
137
    {
138
        QMutexLocker locker(&m_universeMutex);
803✔
139
        Universe *uni = NULL;
803✔
140

141
        if (id == InputOutputMap::invalidUniverse())
803✔
142
        {
143
            id = universesCount();
801✔
144
        }
145
        else if (id < universesCount())
2✔
146
        {
147
            qWarning() << Q_FUNC_INFO
2✔
148
                << "Universe" << id << "is already present in the list."
1✔
149
                << "The universe list may be unsorted.";
1✔
150
            return false;
151
        }
152
        else if (id > universesCount())
1✔
153
        {
154
            qDebug() << Q_FUNC_INFO
155
                << "Gap between universe" << (universesCount() - 1)
156
                << "and universe" << id << ", filling the gap...";
157
            while (id > universesCount())
4✔
158
            {
159
                uni = new Universe(universesCount(), m_grandMaster);
3✔
160
                connect(doc()->masterTimer(), SIGNAL(tickReady()), uni, SLOT(tick()), Qt::QueuedConnection);
3✔
161
                connect(uni, SIGNAL(universeWritten(quint32,QByteArray)), this, SIGNAL(universeWritten(quint32,QByteArray)));
3✔
162
                m_universeArray.append(uni);
3✔
163
            }
164
        }
165

166
        uni = new Universe(id, m_grandMaster);
802✔
167
        connect(doc()->masterTimer(), SIGNAL(tickReady()), uni, SLOT(tick()), Qt::QueuedConnection);
802✔
168
        connect(uni, SIGNAL(universeWritten(quint32,QByteArray)), this, SIGNAL(universeWritten(quint32,QByteArray)));
802✔
169
        m_universeArray.append(uni);
802✔
170
    }
171

172
    emit universeAdded(id);
802✔
173
    return true;
802✔
174
}
175

176
bool InputOutputMap::removeUniverse(int index)
3✔
177
{
178
    {
179
        QMutexLocker locker(&m_universeMutex);
3✔
180

181
        if (index < 0 || index >= m_universeArray.count())
3✔
182
            return false;
183

184
        if (index != (m_universeArray.size() - 1))
2✔
185
        {
186
            qWarning() << Q_FUNC_INFO << "Removing universe" << index
2✔
187
                << "would create a gap in the universe list, cancelling";
1✔
188
            return false;
1✔
189
        }
190

191
        delete  m_universeArray.takeAt(index);
1✔
192
    }
193

194
    emit universeRemoved(index);
1✔
195
    return true;
1✔
196
}
197

198
bool InputOutputMap::removeAllUniverses()
201✔
199
{
200
    QMutexLocker locker(&m_universeMutex);
201✔
201
    qDeleteAll(m_universeArray);
201✔
202
    m_universeArray.clear();
201✔
203
    return true;
201✔
204
}
205

UNCOV
206
void InputOutputMap::startUniverses()
×
207
{
208
    foreach (Universe *uni, m_universeArray)
×
209
        uni->start();
×
UNCOV
210
}
×
211

212
quint32 InputOutputMap::getUniverseID(int index)
2✔
213
{
214
    if (index >= 0 && index < m_universeArray.count())
2✔
215
        return index;
1✔
216

217
    return invalidUniverse();
1✔
218
}
219

220
QString InputOutputMap::getUniverseNameByIndex(int index)
4✔
221
{
222
    if (index >= 0 && index < m_universeArray.count())
4✔
223
        return m_universeArray.at(index)->name();
3✔
224

225
    return QString();
226
}
227

228
QString InputOutputMap::getUniverseNameByID(quint32 id)
1✔
229
{
230
    return getUniverseNameByIndex(id);
1✔
231
}
232

233
void InputOutputMap::setUniverseName(int index, QString name)
2✔
234
{
235
    if (index < 0 || index >= m_universeArray.count())
2✔
236
        return;
237
    m_universeArray.at(index)->setName(name);
1✔
238
}
239

240
void InputOutputMap::setUniversePassthrough(int index, bool enable)
2✔
241
{
242
    if (index < 0 || index >= m_universeArray.count())
2✔
243
        return;
244
    m_universeArray.at(index)->setPassthrough(enable);
1✔
245
}
246

247
bool InputOutputMap::getUniversePassthrough(int index)
2✔
248
{
249
    if (index < 0 || index >= m_universeArray.count())
2✔
250
        return false;
251
    return m_universeArray.at(index)->passthrough();
1✔
252
}
253

254
void InputOutputMap::setUniverseMonitor(int index, bool enable)
2✔
255
{
256
    if (index < 0 || index >= m_universeArray.count())
2✔
257
        return;
258
    m_universeArray.at(index)->setMonitor(enable);
1✔
259
}
260

261
bool InputOutputMap::getUniverseMonitor(int index)
2✔
262
{
263
    if (index < 0 || index >= m_universeArray.count())
2✔
264
        return false;
265
    return m_universeArray.at(index)->monitor();
1✔
266
}
267

268
bool InputOutputMap::isUniversePatched(int index)
3✔
269
{
270
    if (index < 0 || index >= m_universeArray.count())
3✔
271
        return false;
272

273
    return m_universeArray.at(index)->isPatched();
2✔
274
}
275

276
quint32 InputOutputMap::universesCount() const
1,598✔
277
{
278
    return (quint32)m_universeArray.count();
1,598✔
279
}
280

281
QList<Universe *> InputOutputMap::universes() const
42✔
282
{
283
    return m_universeArray;
42✔
284
}
285

UNCOV
286
Universe *InputOutputMap::universe(quint32 id)
×
287
{
288
    for (int i = 0; i < m_universeArray.size(); i++)
×
289
        if (m_universeArray.at(i)->id() == id)
×
UNCOV
290
            return m_universeArray.at(i);
×
291

292
    return NULL;
293
}
294

295
QList<Universe*> InputOutputMap::claimUniverses()
1,045✔
296
{
297
    m_universeMutex.lock();
1,045✔
298
    return m_universeArray;
1,045✔
299
}
300

301
void InputOutputMap::releaseUniverses(bool changed)
1,045✔
302
{
303
    m_universeChanged = changed;
1,045✔
304
    m_universeMutex.unlock();
1,045✔
305
}
1,045✔
306

307
void InputOutputMap::resetUniverses()
1✔
308
{
309
    {
310
        QMutexLocker locker(&m_universeMutex);
1✔
311
        for (int i = 0; i < m_universeArray.size(); i++)
5✔
312
            m_universeArray.at(i)->reset();
4✔
313
    }
314

315
    /* Reset Grand Master parameters */
316
    setGrandMasterValue(255);
1✔
317
    setGrandMasterValueMode(GrandMaster::Reduce);
1✔
318
    setGrandMasterChannelMode(GrandMaster::Intensity);
1✔
319
}
1✔
320

321
/*********************************************************************
322
 * Grand Master
323
 *********************************************************************/
324

325
void InputOutputMap::setGrandMasterChannelMode(GrandMaster::ChannelMode mode)
2✔
326
{
327
    Q_ASSERT(m_grandMaster != NULL);
328

329
    if (m_grandMaster->channelMode() != mode)
2✔
330
    {
331
        m_grandMaster->setChannelMode(mode);
1✔
332
        m_universeChanged = true;
1✔
333
    }
334
}
2✔
335

336
GrandMaster::ChannelMode InputOutputMap::grandMasterChannelMode()
78✔
337
{
338
    Q_ASSERT(m_grandMaster != NULL);
339

340
    return m_grandMaster->channelMode();
78✔
341
}
342

343
void InputOutputMap::setGrandMasterValueMode(GrandMaster::ValueMode mode)
2✔
344
{
345
    Q_ASSERT(m_grandMaster != NULL);
346

347
    if (m_grandMaster->valueMode() != mode)
2✔
348
    {
349
        m_grandMaster->setValueMode(mode);
1✔
350
        m_universeChanged = true;
1✔
351
    }
352

353
    emit grandMasterValueModeChanged(mode);
2✔
354
}
2✔
355

356
GrandMaster::ValueMode InputOutputMap::grandMasterValueMode()
154✔
357
{
358
    Q_ASSERT(m_grandMaster != NULL);
359

360
    return m_grandMaster->valueMode();
154✔
361
}
362

363
void InputOutputMap::setGrandMasterValue(uchar value)
2✔
364
{
365
    Q_ASSERT(m_grandMaster != NULL);
366

367
    if (m_grandMaster->value() != value)
2✔
368
    {
369
        m_grandMaster->setValue(value);
1✔
370
        m_universeChanged = true;
1✔
371
    }
372

373
    if (m_universeChanged == true)
2✔
374
        emit grandMasterValueChanged(value);
2✔
375
}
2✔
376

377
uchar InputOutputMap::grandMasterValue()
2✔
378
{
379
    Q_ASSERT(m_grandMaster != NULL);
380

381
    return m_grandMaster->value();
2✔
382
}
383

384
/*********************************************************************
385
 * Patch
386
 *********************************************************************/
387

388
void InputOutputMap::flushInputs()
5✔
389
{
390
    QMutexLocker locker(&m_universeMutex);
5✔
391
    foreach (Universe *universe, m_universeArray)
30✔
392
        universe->flushInput();
20✔
393
}
5✔
394

395
bool InputOutputMap::setInputPatch(quint32 universe, const QString &pluginName,
7✔
396
                                   const QString &inputUID, quint32 input,
397
                                   const QString &profileName)
398
{
399
    /* Check that the universe that we're doing mapping for is valid */
400
    if (universe >= universesCount())
7✔
401
    {
402
        qWarning() << Q_FUNC_INFO << "Universe" << universe << "out of bounds.";
1✔
403
        return false;
1✔
404
    }
405

406
    QMutexLocker locker(&m_universeMutex);
6✔
407
    InputPatch *currInPatch = m_universeArray.at(universe)->inputPatch();
6✔
408
    QLCInputProfile *currProfile = NULL;
409
    if (currInPatch != NULL)
6✔
410
    {
411
        currProfile = currInPatch->profile();
1✔
412
        disconnect(currInPatch, SIGNAL(inputValueChanged(quint32,quint32,uchar,const QString&)),
1✔
413
                this, SIGNAL(inputValueChanged(quint32,quint32,uchar,const QString&)));
414
        if (currInPatch->plugin()->capabilities() & QLCIOPlugin::Beats)
1✔
415
        {
UNCOV
416
            disconnect(currInPatch, SIGNAL(inputValueChanged(quint32,quint32,uchar,const QString&)),
×
417
                       this, SLOT(slotPluginBeat(quint32,quint32,uchar,const QString&)));
418
        }
419
    }
420
    InputPatch *ip = NULL;
421
    QLCIOPlugin *plugin = doc()->ioPluginCache()->plugin(pluginName);
6✔
422

423
    if (!inputUID.isEmpty() && plugin != NULL)
6✔
424
    {
425
        QStringList inputs = plugin->inputs();
5✔
426
        int lIdx = inputs.indexOf(inputUID);
427
        if (lIdx != -1)
5✔
428
        {
429
            qDebug() << "[IOMAP] Found match on input by name on universe" << universe << "-" << input << "vs" << lIdx;
430
            input = lIdx;
5✔
431
        }
432
        else
433
        {
434
            qDebug() << "[IOMAP] !!No match found!! for input on universe" << universe << "-" << input << inputUID;
435
            qDebug() << plugin->inputs();
436
        }
437
    }
438

439
    if (m_universeArray.at(universe)->setInputPatch(
6✔
440
                plugin, input, profile(profileName)) == true)
441
    {
442
        ip = m_universeArray.at(universe)->inputPatch();
6✔
443
        if (ip != NULL)
6✔
444
        {
445
            connect(ip, SIGNAL(inputValueChanged(quint32,quint32,uchar,const QString&)),
5✔
446
                    this, SIGNAL(inputValueChanged(quint32,quint32,uchar,const QString&)));
447
            if (ip->plugin()->capabilities() & QLCIOPlugin::Beats)
5✔
448
            {
UNCOV
449
                connect(ip, SIGNAL(inputValueChanged(quint32,quint32,uchar,const QString&)),
×
450
                        this, SLOT(slotPluginBeat(quint32,quint32,uchar,const QString&)));
451
            }
452
        }
453
    }
454
    else
455
    {
456
        return false;
457
    }
458

459
    if (ip != NULL && currProfile != ip->profile())
6✔
460
        emit profileChanged(universe, ip->profileName());
3✔
461

462
    return true;
463
}
464

UNCOV
465
bool InputOutputMap::setInputProfile(quint32 universe, const QString &profileName)
×
466
{
467
    /* Check that the universe that we're doing mapping for is valid */
UNCOV
468
    if (universe >= universesCount())
×
469
    {
470
        qWarning() << Q_FUNC_INFO << "Universe" << universe << "out of bounds.";
×
UNCOV
471
        return false;
×
472
    }
473

474
    InputPatch *currInPatch = m_universeArray.at(universe)->inputPatch();
×
475
    if (currInPatch != NULL)
×
UNCOV
476
        currInPatch->set(profile(profileName));
×
477

478
    /* if no input patch is set, then setting a profile is useless,
479
       but there's no reason to cause an error here */
480
    return true;
481
}
482

483
bool InputOutputMap::setOutputPatch(quint32 universe, const QString &pluginName,
21✔
484
                                    const QString &outputUID, quint32 output,
485
                                    bool isFeedback, int index)
486
{
487
    /* Check that the universe that we're doing mapping for is valid */
488
    if (universe >= universesCount())
21✔
489
    {
490
        qWarning() << Q_FUNC_INFO << "Universe" << universe << "out of bounds.";
2✔
491
        return false;
2✔
492
    }
493

494
    QMutexLocker locker(&m_universeMutex);
19✔
495
    QLCIOPlugin *plugin = doc()->ioPluginCache()->plugin(pluginName);
19✔
496

497
    if (!outputUID.isEmpty() && plugin != NULL)
19✔
498
    {
499
        QStringList inputs = plugin->outputs();
12✔
500
        int lIdx = inputs.indexOf(outputUID);
501
        if (lIdx != -1)
12✔
502
        {
503
            qDebug() << "[IOMAP] Found match on output by name on universe" << universe << "-" << output << "vs" << lIdx;
504
            output = lIdx;
12✔
505
        }
506
        else
507
        {
508
            qDebug() << "[IOMAP] !!No match found!! for output on universe" << universe << "-" << output << outputUID;
509
            qDebug() << plugin->outputs();
510
        }
511
    }
512

513
    if (isFeedback == false)
19✔
514
        return m_universeArray.at(universe)->setOutputPatch(plugin, output, index);
19✔
515
    else
UNCOV
516
        return m_universeArray.at(universe)->setFeedbackPatch(plugin, output);
×
517

518
    return false;
519
}
520

521
int InputOutputMap::outputPatchesCount(quint32 universe) const
4✔
522
{
523
    if (universe >= universesCount())
4✔
524
    {
525
        qWarning() << Q_FUNC_INFO << "Universe" << universe << "out of bounds.";
×
UNCOV
526
        return 0;
×
527
    }
528

529
    return m_universeArray.at(universe)->outputPatchesCount();
4✔
530
}
531

532
InputPatch *InputOutputMap::inputPatch(quint32 universe) const
56✔
533
{
534
    if (universe >= universesCount())
56✔
535
    {
536
        qWarning() << Q_FUNC_INFO << "Universe" << universe << "out of bounds.";
7✔
537
        return NULL;
7✔
538
    }
539
    return m_universeArray.at(universe)->inputPatch();
49✔
540
}
541

542
OutputPatch *InputOutputMap::outputPatch(quint32 universe, int index) const
27✔
543
{
544
    if (universe >= universesCount())
27✔
545
    {
546
        qWarning() << Q_FUNC_INFO << "Universe" << universe << "out of bounds.";
×
UNCOV
547
        return NULL;
×
548
    }
549
    return m_universeArray.at(universe)->outputPatch(index);
27✔
550
}
551

552
OutputPatch *InputOutputMap::feedbackPatch(quint32 universe) const
2✔
553
{
554
    if (universe >= universesCount())
2✔
555
    {
556
        qWarning() << Q_FUNC_INFO << "Universe" << universe << "out of bounds.";
1✔
557
        return NULL;
1✔
558
    }
559
    return m_universeArray.at(universe)->feedbackPatch();
1✔
560
}
561

562
QStringList InputOutputMap::universeNames() const
23✔
563
{
564
    QStringList list;
565
    for (quint32 i = 0; i < universesCount(); i++)
115✔
566
        list << m_universeArray.at(i)->name();
184✔
567

568
    return list;
23✔
569
}
570

571
quint32 InputOutputMap::inputMapping(const QString &pluginName, quint32 input) const
16✔
572
{
573
    for (quint32 uni = 0; uni < universesCount(); uni++)
70✔
574
    {
575
        const InputPatch* p = m_universeArray.at(uni)->inputPatch();
57✔
576
        if (p != NULL && p->pluginName() == pluginName && p->input() == input)
57✔
577
            return uni;
3✔
578
    }
579

580
    return QLCIOPlugin::invalidLine();
581
}
582

583
quint32 InputOutputMap::outputMapping(const QString &pluginName, quint32 output) const
2✔
584
{
585
    for (quint32 uni = 0; uni < universesCount(); uni++)
9✔
586
    {
587
        Universe *universe = m_universeArray.at(uni);
8✔
588
        for (int i = 0; i < universe->outputPatchesCount(); i++)
15✔
589
        {
590
            const OutputPatch* p = universe->outputPatch(i);
8✔
591
            if (p != NULL && p->pluginName() == pluginName && p->output() == output)
8✔
592
                return uni;
1✔
593
        }
594
    }
595

596
    return QLCIOPlugin::invalidLine();
597
}
598

599
/*****************************************************************************
600
 * Plugins
601
 *****************************************************************************/
602

603
QString InputOutputMap::pluginDescription(const QString &pluginName)
2✔
604
{
605
    QLCIOPlugin* plugin = NULL;
606

607
    if (pluginName.isEmpty() == false)
2✔
608
        plugin = doc()->ioPluginCache()->plugin(pluginName);
2✔
609

610
    if (plugin != NULL)
2✔
611
    {
612
        return plugin->pluginInfo();
1✔
613
    }
614
    else
615
        return "";
1✔
616
}
617

618
void InputOutputMap::removeDuplicates(QStringList &list)
3✔
619
{
620
    if (list.count() == 1)
3✔
621
        return;
622

623
    int c = 2;
624

625
    for (int i = 1; i < list.count(); i++)
12✔
626
    {
627
        for (int j = 0; j < i; j++)
27✔
628
        {
629
            if (list.at(i) == list.at(j))
18✔
630
            {
631
                list.replace(i, QString("%1 %2").arg(list.at(j)).arg(c));
×
UNCOV
632
                c++;
×
633
            }
634
        }
635
    }
636
}
637

638
QStringList InputOutputMap::inputPluginNames()
2✔
639
{
640
    QStringList list;
641
    QListIterator <QLCIOPlugin*> it(doc()->ioPluginCache()->plugins());
2✔
642
    while (it.hasNext() == true)
6✔
643
    {
644
        QLCIOPlugin* plg(it.next());
2✔
645
        if (plg->capabilities() & QLCIOPlugin::Input)
2✔
646
            list << plg->name();
4✔
647
    }
648
    return list;
2✔
649
}
650

651
QStringList InputOutputMap::outputPluginNames()
2✔
652
{
653
    QStringList list;
654
    QListIterator <QLCIOPlugin*> it(doc()->ioPluginCache()->plugins());
2✔
655
    while (it.hasNext() == true)
6✔
656
    {
657
        QLCIOPlugin* plg(it.next());
2✔
658
        if (plg->capabilities() & QLCIOPlugin::Output)
2✔
659
            list << plg->name();
4✔
660
    }
661
    return list;
2✔
662
}
663

664
QStringList InputOutputMap::pluginInputs(const QString& pluginName)
3✔
665
{
666
    QLCIOPlugin* ip = doc()->ioPluginCache()->plugin(pluginName);
3✔
667
    if (ip == NULL)
3✔
668
        return QStringList();
669
    else
670
    {
671
        QStringList iList = ip->inputs();
2✔
672
        removeDuplicates(iList);
2✔
673
        return iList;
674
    }
675
}
676

677
QStringList InputOutputMap::pluginOutputs(const QString& pluginName)
2✔
678
{
679
    QLCIOPlugin* op = doc()->ioPluginCache()->plugin(pluginName);
2✔
680
    if (op == NULL)
2✔
681
        return QStringList();
682
    else
683
    {
684
        QStringList oList = op->outputs();
1✔
685
        removeDuplicates(oList);
1✔
686
        return oList;
687
    }
688
}
689

690
bool InputOutputMap::pluginSupportsFeedback(const QString& pluginName)
1✔
691
{
692
    QLCIOPlugin* outputPlugin = doc()->ioPluginCache()->plugin(pluginName);
1✔
693
    if (outputPlugin != NULL)
1✔
694
        return (outputPlugin->capabilities() & QLCIOPlugin::Feedback) > 0;
1✔
695
    else
696
        return false;
697
}
698

699
void InputOutputMap::configurePlugin(const QString& pluginName)
3✔
700
{
701
    QLCIOPlugin* outputPlugin = doc()->ioPluginCache()->plugin(pluginName);
3✔
702
    if (outputPlugin != NULL)
3✔
703
        outputPlugin->configure();
3✔
704
}
3✔
705

706
bool InputOutputMap::canConfigurePlugin(const QString& pluginName)
4✔
707
{
708
    QLCIOPlugin* outputPlugin = doc()->ioPluginCache()->plugin(pluginName);
4✔
709
    if (outputPlugin != NULL)
4✔
710
        return outputPlugin->canConfigure();
2✔
711
    else
712
        return false;
713
}
714

715
QString InputOutputMap::inputPluginStatus(const QString& pluginName, quint32 input)
9✔
716
{
717
    QLCIOPlugin* inputPlugin = NULL;
718
    QString info;
719

720
    if (pluginName.isEmpty() == false)
9✔
721
        inputPlugin = doc()->ioPluginCache()->plugin(pluginName);
9✔
722

723
    if (inputPlugin != NULL)
9✔
724
    {
725
        info = inputPlugin->inputInfo(input);
4✔
726
    }
727
    else
728
    {
729
        /* Nothing selected */
730
        info += QString("<HTML><HEAD></HEAD><BODY>");
10✔
731
        info += QString("<H3>%1</H3>").arg(tr("Nothing selected"));
15✔
732
        info += QString("</BODY></HTML>");
10✔
733
    }
734

735
    return info;
9✔
UNCOV
736
}
×
737

738
QString InputOutputMap::outputPluginStatus(const QString& pluginName, quint32 output)
9✔
739
{
740
    QLCIOPlugin* outputPlugin = doc()->ioPluginCache()->plugin(pluginName);
9✔
741
    if (outputPlugin != NULL)
9✔
742
    {
743
        return outputPlugin->outputInfo(output);
4✔
744
    }
745
    else
746
    {
747
        QString info;
748
        info += QString("<HTML><HEAD></HEAD><BODY>");
10✔
749
        info += QString("<H3>%1</H3>").arg(tr("Nothing selected"));
15✔
750
        info += QString("</BODY></HTML>");
10✔
751
        return info;
752
    }
5✔
753
}
754

755
bool InputOutputMap::sendFeedBack(quint32 universe, quint32 channel, uchar value, const QVariant &params)
12✔
756
{
757
    if (universe >= universesCount())
12✔
758
        return false;
759

760
    OutputPatch* patch = m_universeArray.at(universe)->feedbackPatch();
9✔
761

762
    if (patch != NULL && patch->isPatched())
9✔
763
    {
764
        patch->plugin()->sendFeedBack(universe, patch->output(), channel, value, params);
×
UNCOV
765
        return true;
×
766
    }
767
    else
768
    {
769
        return false;
9✔
770
    }
771
}
772

773
void InputOutputMap::slotPluginConfigurationChanged(QLCIOPlugin* plugin)
8✔
774
{
775
    QMutexLocker locker(&m_universeMutex);
8✔
776
    bool success = true;
777
    for (quint32 i = 0; i < universesCount(); i++)
40✔
778
    {
779
        Universe *universe = m_universeArray.at(i);
32✔
780
        for (int oi = 0; oi < universe->outputPatchesCount(); oi++)
32✔
781
        {
UNCOV
782
            OutputPatch* op = universe->outputPatch(oi);
×
783

UNCOV
784
            if (op != NULL && op->plugin() == plugin)
×
785
            {
UNCOV
786
                /*success = */ op->reconnect();
×
787
            }
788
        }
789

790
        InputPatch* ip = m_universeArray.at(i)->inputPatch();
32✔
791

792
        if (ip != NULL && ip->plugin() == plugin)
32✔
793
        {
UNCOV
794
            /*success = */ ip->reconnect();
×
795
        }
796

797
        OutputPatch* fp = m_universeArray.at(i)->feedbackPatch();
32✔
798
        if (fp != NULL && fp->plugin() == plugin)
32✔
799
        {
UNCOV
800
            /*success = */ fp->reconnect();
×
801
        }
802
    }
803
    locker.unlock();
8✔
804

805
    emit pluginConfigurationChanged(plugin->name(), success);
8✔
806
}
8✔
807

808
/*****************************************************************************
809
 * Profiles
810
 *****************************************************************************/
811

812
void InputOutputMap::loadProfiles(const QDir& dir)
5✔
813
{
814
    if (dir.exists() == false || dir.isReadable() == false)
5✔
815
        return;
1✔
816

817
    /* Go thru all found file entries and attempt to load an input
818
       profile from each of them. */
819
    QStringListIterator it(dir.entryList());
4✔
820
    while (it.hasNext() == true)
118✔
821
    {
822
        QLCInputProfile* prof;
823
        QString path;
824

825
        path = dir.absoluteFilePath(it.next());
114✔
826
        prof = QLCInputProfile::loader(path);
114✔
827
        if (prof != NULL)
114✔
828
        {
829
            /* Check for duplicates */
830
            if (profile(prof->name()) == NULL)
114✔
831
                addProfile(prof);
76✔
832
            else
833
                delete prof;
38✔
834
        }
835
        else
836
        {
UNCOV
837
            qWarning() << Q_FUNC_INFO << "Unable to find an input profile from" << path;
×
838
        }
839
    }
114✔
840
}
841

842
QStringList InputOutputMap::profileNames()
7✔
843
{
844
    QStringList list;
845
    QListIterator <QLCInputProfile*> it(m_profiles);
7✔
846
    while (it.hasNext() == true)
85✔
847
        list << it.next()->name();
156✔
848
    return list;
7✔
849
}
850

851
QLCInputProfile* InputOutputMap::profile(const QString& name)
122✔
852
{
853
    QListIterator <QLCInputProfile*> it(m_profiles);
122✔
854
    while (it.hasNext() == true)
2,285✔
855
    {
856
        QLCInputProfile* profile = it.next();
2,205✔
857
        if (profile->name() == name)
2,205✔
858
            return profile;
42✔
859
    }
860

861
    return NULL;
862
}
863

864
bool InputOutputMap::addProfile(QLCInputProfile* profile)
79✔
865
{
866
    Q_ASSERT(profile != NULL);
867

868
    /* Don't add the same profile twice */
869
    if (m_profiles.contains(profile) == false)
79✔
870
    {
871
        m_profiles.append(profile);
78✔
872
        return true;
78✔
873
    }
874
    else
875
    {
876
        return false;
877
    }
878
}
879

880
bool InputOutputMap::removeProfile(const QString& name)
2✔
881
{
882
    QMutableListIterator <QLCInputProfile*> it(m_profiles);
2✔
883
    while (it.hasNext() == true)
3✔
884
    {
885
        QLCInputProfile *profile = it.next();
2✔
886
        if (profile->name() == name)
2✔
887
        {
888
            it.remove();
1✔
889
            delete profile;
1✔
890
            return true;
1✔
891
        }
892
    }
893

894
    return false;
895
}
896

897
bool InputOutputMap::inputSourceNames(const QLCInputSource *src,
8✔
898
                                QString& uniName, QString& chName) const
899
{
900
    if (src == NULL || src->isValid() == false)
8✔
901
        return false;
3✔
902

903
    if (src->universe() >= universesCount())
5✔
904
        return false;
905

906
    InputPatch* pat = m_universeArray.at(src->universe())->inputPatch();
4✔
907
    if (pat == NULL)
4✔
908
    {
909
        /* There is no patch for the given universe */
910
        uniName = QString("%1 -UNPATCHED-").arg(src->universe() + 1);
1✔
911

912
        ushort page = src->page();
1✔
913
        ushort channel = (src->channel() & 0x0000FFFF) + 1;
1✔
914

915
        if (page != 0)
1✔
UNCOV
916
            chName = QString("%1: ? (Page %2)").arg(channel).arg(page + 1);
×
917
        else
918
            chName = QString("%1: ?").arg(channel);
2✔
919
        return true;
1✔
920
    }
921

922
    QLCInputProfile* profile = pat->profile();
3✔
923
    if (profile == NULL)
3✔
924
    {
925
        /* There is no profile. Display plugin name and channel number. */
926
        if (pat->plugin() != NULL)
1✔
927
            uniName = QString("%1: %2").arg(src->universe() + 1).arg(pat->plugin()->name());
1✔
928
        else
UNCOV
929
            uniName = QString("%1: ??").arg(src->universe() + 1);
×
930

931
        ushort page = src->page();
1✔
932
        ushort channel = (src->channel() & 0x0000FFFF) + 1;
1✔
933

934
        if (page != 0)
1✔
UNCOV
935
            chName = QString("%1: ? (Page %2)").arg(channel).arg(page + 1);
×
936
        else
937
            chName = QString("%1: ?").arg(channel);
2✔
938
    }
939
    else
940
    {
941
        QLCInputChannel* ich;
942
        QString name;
943

944
        /* Display profile name for universe */
945
        uniName = QString("%1: %2").arg(src->universe() + 1).arg(profile->name());
2✔
946

947
        /* User can input the channel number by hand, so put something
948
           rational to the channel name in those cases as well. */
949
        ushort page = src->page();
2✔
950
        ushort channel = (src->channel() & 0x0000FFFF);
2✔
951

952
        ich = profile->channel(channel);
2✔
953
        if (ich != NULL)
2✔
954
            name = ich->name();
1✔
955
        else
956
            name = QString("?");
1✔
957

958
        /* Display channel name */
959
        if (page != 0)
2✔
UNCOV
960
            chName = QString("%1: %2 (Page %3)").arg(channel + 1).arg(name).arg(page + 1);
×
961
        else
962
            chName = QString("%1: %2").arg(channel + 1).arg(name);
2✔
963
    }
2✔
964

965
    return true;
966
}
967

UNCOV
968
bool InputOutputMap::inputSourceNames(QSharedPointer<QLCInputSource> const& src,
×
969
                                QString& uniName, QString& chName) const
970
{
UNCOV
971
    return inputSourceNames(src.data(), uniName, chName);
×
972
}
973

974
QDir InputOutputMap::systemProfileDirectory()
1✔
975
{
976
    return QLCFile::systemDirectory(QString(INPUTPROFILEDIR), QString(KExtInputProfile));
1✔
977
}
978

979
QDir InputOutputMap::userProfileDirectory()
1✔
980
{
981
    return QLCFile::userDirectory(QString(USERINPUTPROFILEDIR), QString(INPUTPROFILEDIR),
2✔
982
                                  QStringList() << QString("*%1").arg(KExtInputProfile));
3✔
983
}
984

985
/*********************************************************************
986
 * Beats
987
 *********************************************************************/
988

UNCOV
989
void InputOutputMap::setBeatGeneratorType(InputOutputMap::BeatGeneratorType type)
×
990
{
UNCOV
991
    if (type == m_beatGeneratorType)
×
992
        return;
993

UNCOV
994
    m_beatGeneratorType = type;
×
995
    qDebug() << "[InputOutputMap] setting beat type:" << m_beatGeneratorType;
996

UNCOV
997
    switch (m_beatGeneratorType)
×
998
    {
999
        case Internal:
×
1000
            doc()->masterTimer()->setBeatSourceType(MasterTimer::Internal);
×
1001
            setBpmNumber(doc()->masterTimer()->bpmNumber());
×
1002
        break;
×
1003
        case Plugin:
×
UNCOV
1004
            doc()->masterTimer()->setBeatSourceType(MasterTimer::External);
×
1005
            // reset the current BPM number and detect it from the MIDI beats
1006
            setBpmNumber(0);
×
1007
            m_beatTime->restart();
×
1008
        break;
×
1009
        case Audio:
×
UNCOV
1010
            doc()->masterTimer()->setBeatSourceType(MasterTimer::External);
×
1011
            // reset the current BPM number and detect it from the audio input
1012
            setBpmNumber(0);
×
1013
            m_beatTime->restart();
×
1014
        break;
×
UNCOV
1015
        case Disabled:
×
1016
        default:
1017
            doc()->masterTimer()->setBeatSourceType(MasterTimer::None);
×
1018
            setBpmNumber(0);
×
UNCOV
1019
        break;
×
1020
    }
1021

UNCOV
1022
    emit beatGeneratorTypeChanged();
×
1023
}
1024

UNCOV
1025
InputOutputMap::BeatGeneratorType InputOutputMap::beatGeneratorType() const
×
1026
{
UNCOV
1027
    return m_beatGeneratorType;
×
1028
}
1029

1030
QString InputOutputMap::beatTypeToString(BeatGeneratorType type) const
1✔
1031
{
1032
    switch (type)
1✔
1033
    {
1034
        case Internal:  return "Internal";
×
1035
        case Plugin:    return "Plugin";
×
UNCOV
1036
        case Audio:     return "Audio";
×
1037
        default:        return "Disabled";
1✔
1038
    }
1039
}
1040

UNCOV
1041
InputOutputMap::BeatGeneratorType InputOutputMap::stringToBeatType(QString str)
×
1042
{
UNCOV
1043
    if (str == "Internal")
×
1044
        return Internal;
UNCOV
1045
    else if (str == "Plugin")
×
1046
        return Plugin;
1047
    else if (str == "Audio")
×
UNCOV
1048
        return Audio;
×
1049

1050
    return Disabled;
1051
}
1052

UNCOV
1053
void InputOutputMap::setBpmNumber(int bpm)
×
1054
{
UNCOV
1055
    if (m_beatGeneratorType == Disabled || bpm == m_currentBPM)
×
1056
        return;
1057

1058
    //qDebug() << "[InputOutputMap] set BPM to" << bpm;
UNCOV
1059
    m_currentBPM = bpm;
×
1060

1061
    if (bpm != 0)
×
UNCOV
1062
        doc()->masterTimer()->requestBpmNumber(bpm);
×
1063

UNCOV
1064
    emit bpmNumberChanged(m_currentBPM);
×
1065
}
1066

UNCOV
1067
int InputOutputMap::bpmNumber() const
×
1068
{
UNCOV
1069
    if (m_beatGeneratorType == Disabled)
×
1070
        return 0;
1071

UNCOV
1072
    return m_currentBPM;
×
1073
}
1074

UNCOV
1075
void InputOutputMap::slotMasterTimerBeat()
×
1076
{
UNCOV
1077
    if (m_beatGeneratorType != Internal)
×
1078
        return;
1079

UNCOV
1080
    emit beat();
×
1081
}
1082

UNCOV
1083
void InputOutputMap::slotPluginBeat(quint32 universe, quint32 channel, uchar value, const QString &key)
×
1084
{
1085
    Q_UNUSED(universe)
1086

1087
    // not interested in synthetic release or non-beat event
1088
    if (m_beatGeneratorType != Plugin || value == 0 || key != "beat")
×
UNCOV
1089
        return;
×
1090

1091
    qDebug() << "Plugin beat:" << channel << m_beatTime->elapsed();
1092

1093
    // process the timer as first thing, to avoid wasting time
1094
    // with the operations below
1095
    int elapsed = m_beatTime->elapsed();
×
UNCOV
1096
    m_beatTime->restart();
×
1097

1098
    int bpm = qRound(60000.0 / (float)elapsed);
×
UNCOV
1099
    float currBpmTime = 60000.0 / (float)m_currentBPM;
×
1100
    // here we check if the difference between the current BPM duration
1101
    // and the current time elapsed is within a range of +/-1ms.
1102
    // If it isn't, then the BPM number has really changed, otherwise
1103
    // it's just a tiny time drift
1104
    if (qAbs((float)elapsed - currBpmTime) > 1)
×
UNCOV
1105
        setBpmNumber(bpm);
×
1106

1107
    doc()->masterTimer()->requestBeat();
×
UNCOV
1108
    emit beat();
×
1109
}
1110

UNCOV
1111
void InputOutputMap::slotAudioSpectrum(double *spectrumBands, int size, double maxMagnitude, quint32 power)
×
1112
{
1113
    Q_UNUSED(spectrumBands)
1114
    Q_UNUSED(size)
1115
    Q_UNUSED(maxMagnitude)
1116
    Q_UNUSED(power)
UNCOV
1117
}
×
1118

1119
/*********************************************************************
1120
 * Defaults - !! FALLBACK !!
1121
 *********************************************************************/
1122

UNCOV
1123
void InputOutputMap::loadDefaults()
×
1124
{
1125
    /* ************************ INPUT *********************************** */
UNCOV
1126
    QSettings settings;
×
1127
    QString plugin;
1128
    QString input;
1129
    QString key;
1130

UNCOV
1131
    for (quint32 i = 0; i < universesCount(); i++)
×
1132
    {
1133
        QString profileName;
1134
        bool passthrough;
1135

1136
        /* Plugin name */
1137
        key = QString("/inputmap/universe%1/plugin/").arg(i);
×
UNCOV
1138
        plugin = settings.value(key).toString();
×
1139

1140
        /* Plugin input */
1141
        key = QString("/inputmap/universe%1/input/").arg(i);
×
UNCOV
1142
        input = settings.value(key).toString();
×
1143

1144
        /* Input profile */
1145
        key = QString("/inputmap/universe%1/profile/").arg(i);
×
UNCOV
1146
        profileName = settings.value(key).toString();
×
1147

1148
        key = QString("/inputmap/universe%1/passthrough/").arg(i);
×
1149
        passthrough = settings.value(key).toBool();
×
1150
        if (passthrough == true)
×
UNCOV
1151
            m_universeArray.at(i)->setPassthrough(passthrough);
×
1152

1153
        /* Do the mapping */
1154
        if (plugin != KInputNone && input != KInputNone)
×
1155
            setInputPatch(i, plugin, "", input.toUInt(), profileName);
×
UNCOV
1156
    }
×
1157

1158
    /* ************************ OUTPUT *********************************** */
1159
    QString output;
1160
    QString fb_plugin;
1161
    QString feedback;
1162

UNCOV
1163
    for (quint32 i = 0; i < universesCount(); i++)
×
1164
    {
1165
        /* Plugin name */
1166
        key = QString("/outputmap/universe%1/plugin/").arg(i);
×
UNCOV
1167
        plugin = settings.value(key).toString();
×
1168

1169
        /* Plugin output */
1170
        key = QString("/outputmap/universe%1/output/").arg(i);
×
UNCOV
1171
        output = settings.value(key).toString();
×
1172

1173
        /* Feedback plugin name */
1174
        key = QString("/outputmap/universe%1/feedbackplugin/").arg(i);
×
UNCOV
1175
        fb_plugin = settings.value(key).toString();
×
1176

1177
        /* Feedback line */
1178
        key = QString("/outputmap/universe%1/feedback/").arg(i);
×
UNCOV
1179
        feedback = settings.value(key).toString();
×
1180

1181
        if (plugin != KOutputNone && output != KOutputNone)
×
UNCOV
1182
            setOutputPatch(i, plugin, "", output.toUInt());
×
1183

1184
        if (fb_plugin != KOutputNone && feedback != KOutputNone)
×
UNCOV
1185
            setOutputPatch(i, fb_plugin, "", feedback.toUInt(), true);
×
1186
    }
UNCOV
1187
}
×
1188

UNCOV
1189
void InputOutputMap::saveDefaults()
×
1190
{
1191
    /* ************************ INPUT *********************************** */
UNCOV
1192
    QSettings settings;
×
1193
    QString key;
1194

UNCOV
1195
    for (quint32 i = 0; i < universesCount(); i++)
×
1196
    {
UNCOV
1197
        InputPatch* inPatch = inputPatch(i);
×
1198

1199
        /* Plugin name */
1200
        key = QString("/inputmap/universe%1/plugin/").arg(i);
×
1201
        if (inPatch != NULL)
×
UNCOV
1202
            settings.setValue(key, inPatch->pluginName());
×
1203
        else
UNCOV
1204
            settings.setValue(key, KInputNone);
×
1205

1206
        /* Plugin input */
1207
        key = QString("/inputmap/universe%1/input/").arg(i);
×
1208
        if (inPatch != NULL)
×
UNCOV
1209
            settings.setValue(key, QString::number(inPatch->input()));
×
1210
        else
UNCOV
1211
            settings.setValue(key, KInputNone);
×
1212

1213
        /* Input profile */
1214
        key = QString("/inputmap/universe%1/profile/").arg(i);
×
1215
        if (inPatch != NULL)
×
UNCOV
1216
            settings.setValue(key, inPatch->profileName());
×
1217
        else
UNCOV
1218
            settings.setValue(key, KInputNone);
×
1219

1220
        /* Passthrough */
1221
        key = QString("/inputmap/universe%1/passthrough/").arg(i);
×
1222
        bool passthrough = m_universeArray.at(i)->passthrough();
×
1223
        if (passthrough == true)
×
UNCOV
1224
            settings.setValue(key, passthrough);
×
1225
        else
UNCOV
1226
            settings.remove(key);
×
1227
    }
1228

1229
    /* ************************ OUTPUT *********************************** */
1230

UNCOV
1231
    for (quint32 i = 0; i < universesCount(); i++)
×
1232
    {
1233
        OutputPatch* outPatch = outputPatch(i);
×
UNCOV
1234
        OutputPatch* fbPatch = feedbackPatch(i);
×
1235

UNCOV
1236
        key = QString("/outputmap/universe%1/plugin/").arg(i);
×
1237

1238
        /* Plugin name */
1239
        if (outPatch != NULL)
×
UNCOV
1240
            settings.setValue(key, outPatch->pluginName());
×
1241
        else
UNCOV
1242
            settings.setValue(key, KOutputNone);
×
1243

1244
        /* Plugin output */
1245
        key = QString("/outputmap/universe%1/output/").arg(i);
×
1246
        if (outPatch != NULL)
×
UNCOV
1247
            settings.setValue(key, outPatch->output());
×
1248
        else
UNCOV
1249
            settings.setValue(key, KOutputNone);
×
1250

UNCOV
1251
        key = QString("/outputmap/universe%1/feedbackplugin/").arg(i);
×
1252

1253
        /* Feedback plugin name */
1254
        if (fbPatch != NULL)
×
UNCOV
1255
            settings.setValue(key, fbPatch->pluginName());
×
1256
        else
UNCOV
1257
            settings.setValue(key, KOutputNone);
×
1258

1259
        /* Feedback plugin output */
1260
        key = QString("/outputmap/universe%1/feedback/").arg(i);
×
1261
        if (fbPatch != NULL)
×
UNCOV
1262
            settings.setValue(key, QString::number(fbPatch->output()));
×
1263
        else
UNCOV
1264
            settings.setValue(key, KOutputNone);
×
1265
    }
UNCOV
1266
}
×
1267

1268
/*********************************************************************
1269
 * Load & Save
1270
 *********************************************************************/
1271

UNCOV
1272
bool InputOutputMap::loadXML(QXmlStreamReader &root)
×
1273
{
UNCOV
1274
    if (root.name() != KXMLIOMap)
×
1275
    {
1276
        qWarning() << Q_FUNC_INFO << "InputOutputMap node not found";
×
UNCOV
1277
        return false;
×
1278
    }
1279

1280
    /** Reset the current universe list and read the new one */
UNCOV
1281
    removeAllUniverses();
×
1282

UNCOV
1283
    while (root.readNextStartElement())
×
1284
    {
UNCOV
1285
        if (root.name() == KXMLQLCUniverse)
×
1286
        {
1287
            quint32 id = InputOutputMap::invalidUniverse();
×
1288
            if (root.attributes().hasAttribute(KXMLQLCUniverseID))
×
1289
                id = root.attributes().value(KXMLQLCUniverseID).toString().toUInt();
×
UNCOV
1290
            if (addUniverse(id))
×
1291
            {
1292
                Universe *uni = m_universeArray.last();
×
UNCOV
1293
                uni->loadXML(root, m_universeArray.count() - 1, this);
×
1294
            }
1295
        }
UNCOV
1296
        else if (root.name() == KXMLIOBeatGenerator)
×
1297
        {
UNCOV
1298
            QXmlStreamAttributes attrs = root.attributes();
×
1299

1300
            if (attrs.hasAttribute(KXMLIOBeatType))
×
UNCOV
1301
                setBeatGeneratorType(stringToBeatType(attrs.value(KXMLIOBeatType).toString()));
×
1302

1303
            if (attrs.hasAttribute(KXMLIOBeatsPerMinute))
×
UNCOV
1304
                setBpmNumber(attrs.value(KXMLIOBeatsPerMinute).toInt());
×
1305

UNCOV
1306
            root.skipCurrentElement();
×
1307
        }
1308
        else
1309
        {
1310
            qWarning() << Q_FUNC_INFO << "Unknown IO Map tag:" << root.name();
×
UNCOV
1311
            root.skipCurrentElement();
×
1312
        }
1313
    }
1314

1315
    return true;
1316
}
1317

1318
bool InputOutputMap::saveXML(QXmlStreamWriter *doc) const
1✔
1319
{
1320
    Q_ASSERT(doc != NULL);
1321

1322
    /* IO Map Instance entry */
1323
    doc->writeStartElement(KXMLIOMap);
1✔
1324

1325
    doc->writeStartElement(KXMLIOBeatGenerator);
1✔
1326
    doc->writeAttribute(KXMLIOBeatType, beatTypeToString(m_beatGeneratorType));
1✔
1327
    doc->writeAttribute(KXMLIOBeatsPerMinute, QString::number(m_currentBPM));
1✔
1328
    doc->writeEndElement();
1✔
1329

1330
    foreach (Universe *uni, m_universeArray)
5✔
1331
        uni->saveXML(doc);
4✔
1332

1333
    doc->writeEndElement();
1✔
1334

1335
    return true;
1✔
1336
}
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

© 2025 Coveralls, Inc