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

mcallegari / qlcplus / 8121957695

02 Mar 2024 09:50AM UTC coverage: 32.097% (+0.06%) from 32.036%
8121957695

push

github

web-flow
Merge pull request #1522 from mcallegari/16bitfade

16bit fade rework

145 of 178 new or added lines in 7 files covered. (81.46%)

1 existing line in 1 file now uncovered.

15387 of 47939 relevant lines covered (32.1%)

24361.41 hits per line

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

82.66
/engine/src/genericfader.cpp
1
/*
2
  Q Light Controller
3
  genericfader.cpp
4

5
  Copyright (c) Heikki Junnila
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 <QDebug>
21

22
#include "genericfader.h"
23
#include "fadechannel.h"
24
#include "doc.h"
25

26
GenericFader::GenericFader(QObject *parent)
148✔
27
    : QObject(parent)
28
    , m_fid(Function::invalidId())
148✔
29
    , m_priority(Universe::Auto)
30
    , m_handleSecondary(false)
31
    , m_intensity(1.0)
32
    , m_parentIntensity(1.0)
33
    , m_paused(false)
34
    , m_enabled(true)
35
    , m_fadeOut(false)
36
    , m_deleteRequest(false)
37
    , m_blendMode(Universe::NormalBlend)
38
    , m_monitoring(false)
296✔
39
{
40
}
148✔
41

42
GenericFader::~GenericFader()
294✔
43
{
44
}
294✔
45

46
QString GenericFader::name() const
×
47
{
48
    return m_name;
×
49
}
50

51
void GenericFader::setName(QString name)
120✔
52
{
53
    m_name = name;
120✔
54
}
120✔
55

56
quint32 GenericFader::parentFunctionID() const
9✔
57
{
58
    return m_fid;
9✔
59
}
60

61
void GenericFader::setParentFunctionID(quint32 fid)
120✔
62
{
63
    m_fid = fid;
120✔
64
}
120✔
65

66
int GenericFader::priority() const
401✔
67
{
68
    return m_priority;
401✔
69
}
70

71
void GenericFader::setPriority(int priority)
147✔
72
{
73
    m_priority = priority;
147✔
74
}
147✔
75

76
bool GenericFader::handleSecondary()
1,589,830✔
77
{
78
    return m_handleSecondary;
1,589,830✔
79
}
80

81
void GenericFader::setHandleSecondary(bool enable)
119✔
82
{
83
    m_handleSecondary = enable;
119✔
84
}
119✔
85

86
quint32 GenericFader::channelHash(quint32 fixtureID, quint32 channel)
795,252✔
87
{
88
    return ((fixtureID & 0x0000FFFF) << 16) | (channel & 0x0000FFFF);
795,252✔
89
}
90

91
void GenericFader::add(const FadeChannel& ch)
17✔
92
{
93
    quint32 hash = channelHash(ch.fixture(), ch.channel());
17✔
94

95
    QHash<quint32,FadeChannel>::iterator channelIterator = m_channels.find(hash);
17✔
96
    if (channelIterator != m_channels.end())
17✔
97
    {
98
        // perform a HTP check
99
        if (channelIterator.value().current() <= ch.current())
3✔
100
            channelIterator.value() = ch;
3✔
101
    }
102
    else
103
    {
104
        m_channels.insert(hash, ch);
14✔
105
        qDebug() << "Added new fader with hash" << hash;
14✔
106
    }
107
}
17✔
108

109
void GenericFader::replace(const FadeChannel &ch)
1✔
110
{
111
    quint32 hash = channelHash(ch.fixture(), ch.channel());
1✔
112
    m_channels.insert(hash, ch);
1✔
113
}
1✔
114

115
void GenericFader::remove(FadeChannel *ch)
2✔
116
{
117
    if (ch == NULL)
2✔
118
        return;
×
119

120
    quint32 hash = channelHash(ch->fixture(), ch->channel());
2✔
121
    if (m_channels.remove(hash) == 0)
2✔
122
        qDebug() << "No FadeChannel found with hash" << hash;
1✔
123
}
124

125
void GenericFader::removeAll()
3✔
126
{
127
    m_channels.clear();
3✔
128
}
3✔
129

130
bool GenericFader::deleteRequested()
927,070✔
131
{
132
    return m_deleteRequest;
927,070✔
133
}
134

135
void GenericFader::requestDelete()
101✔
136
{
137
    m_deleteRequest = true;
101✔
138
}
101✔
139

140
FadeChannel *GenericFader::getChannelFader(const Doc *doc, Universe *universe, quint32 fixtureID, quint32 channel)
795,207✔
141
{
142
    FadeChannel fc(doc, fixtureID, channel);
1,590,410✔
143
    quint32 primary = fc.primaryChannel();
795,207✔
144
    quint32 hash;
145

146
    // calculate hash depending on primary channel presence
147
    if (handleSecondary() && primary != QLCChannel::invalid())
795,207✔
NEW
148
        hash = channelHash(fc.fixture(), primary);
×
149
    else
150
        hash = channelHash(fc.fixture(), fc.channel());
795,207✔
151

152
    // search for existing FadeChannel
153
    QHash<quint32,FadeChannel>::iterator channelIterator = m_channels.find(hash);
795,207✔
154
    if (channelIterator != m_channels.end())
795,207✔
155
    {
156
        FadeChannel *fcFound = &channelIterator.value();
794,625✔
157

158
        if (handleSecondary() &&
794,625✔
159
            fcFound->channelCount() == 1 &&
794,625✔
NEW
160
            primary != QLCChannel::invalid())
×
161
        {
NEW
162
            qDebug() << "Adding channel to primary" << channel;
×
NEW
163
            fcFound->addChannel(channel);
×
NEW
164
            if (universe)
×
NEW
165
                fcFound->setCurrent(universe->preGMValue(fcFound->address() + 1), 1);
×
166
        }
167
        return fcFound;
794,625✔
168
    }
169

170
    // set current universe value
171
    if (universe)
582✔
172
        fc.setCurrent(universe->preGMValue(fc.address()));
582✔
173

174
    // new channel. Add to GenericFader
175
    m_channels[hash] = fc;
582✔
176
    //qDebug() << "Added new fader with hash" << hash;
177

178
    return &m_channels[hash];
582✔
179
}
180

181
const QHash<quint32, FadeChannel> &GenericFader::channels() const
74✔
182
{
183
    return m_channels;
74✔
184
}
185

186
int GenericFader::channelsCount() const
4✔
187
{
188
    return m_channels.count();
4✔
189
}
190

191
void GenericFader::write(Universe *universe)
927,169✔
192
{
193
    if (m_monitoring)
927,169✔
194
        emit preWriteData(universe->id(), universe->preGMValues());
×
195

196
    qreal compIntensity = intensity() * parentIntensity();
927,169✔
197

198
    //qDebug() << "[GenericFader] writing channels: " << this << m_channels.count();
199

200
    QMutableHashIterator <quint32,FadeChannel> it(m_channels);
927,169✔
201
    while (it.hasNext() == true)
2,649,540✔
202
    {
203
        FadeChannel& fc(it.next().value());
1,722,370✔
204
        int flags = fc.flags();
1,722,370✔
205
        int address = int(fc.addressInUniverse());
1,722,370✔
206
        int channelCount = fc.channelCount();
1,722,370✔
207

208
        // iterate through all the channels handled by this fader
209

210
        if (flags & FadeChannel::SetTarget)
1,722,370✔
211
        {
212
            fc.removeFlag(FadeChannel::SetTarget);
2✔
213
            fc.addFlag(FadeChannel::AutoRemove);
2✔
214
            for (int i = 0; i < channelCount; i++)
4✔
215
                fc.setTarget(universe->preGMValue(address + i), i);
2✔
216
        }
217

218
        // Calculate the next step
219
        if (m_paused == false)
1,722,370✔
220
            fc.nextStep(MasterTimer::tick());
1,722,370✔
221

222
        quint32 value = fc.current();
1,722,370✔
223

224
        // Apply intensity to channels that can fade
225
        if (fc.canFade())
1,722,370✔
226
        {
227
            if ((flags & FadeChannel::CrossFade) && fc.fadeTime() == 0)
1,722,370✔
228
            {
229
                // morph start <-> target depending on intensities
NEW
230
                value = quint32(((qreal(fc.target() - fc.start()) * intensity()) + fc.start()) * parentIntensity());
×
231
            }
232
            else if (flags & FadeChannel::Intensity)
1,722,370✔
233
            {
234
                value = fc.current(compIntensity);
126✔
235
            }
236
        }
237

238
        //qDebug() << "[GenericFader] >>> uni:" << universe->id() << ", address:" << (address + i) << ", value:" << value << "int:" << compIntensity;
239
        if (flags & FadeChannel::Override)
1,722,370✔
240
        {
241
            universe->write(address, value, true);
×
242
            continue;
8✔
243
        }
244
        else if (flags & FadeChannel::Relative)
1,722,370✔
245
        {
NEW
246
            for (int i = 0; i < channelCount; i++)
×
NEW
247
                universe->writeRelative(address + i, ((uchar *)&value)[channelCount - 1 - i]);
×
248
        }
249
        else if (flags & FadeChannel::Flashing)
1,722,370✔
250
        {
251
            universe->write(address, value, flags & FadeChannel::ForceLTP);
8✔
252
            continue;
8✔
253
        }
254
        else
255
        {
256
            // treat value as a whole, so do this just once per FadeChannel
257
            universe->writeBlended(address, value, channelCount, m_blendMode);
1,722,360✔
258
        }
259

260
        if (((flags & FadeChannel::Intensity) &&
1,722,360✔
261
            (flags & FadeChannel::HTP) &&
118✔
262
            m_blendMode == Universe::NormalBlend) || m_fadeOut)
1,722,360✔
263
        {
264
            // Remove all channels that reach their target _zero_ value.
265
            // They have no effect either way so removing them saves a bit of CPU.
266
            if (fc.current() == 0 && fc.target() == 0 && fc.isReady())
122✔
267
                it.remove();
3✔
268
        }
269

270
        if (flags & FadeChannel::AutoRemove && value == fc.target())
1,722,360✔
271
            it.remove();
2✔
272
    }
273

274
    // self-request deletion when fadeout is complete
275
    if (m_fadeOut && channelsCount() == 0)
927,169✔
276
    {
277
        m_fadeOut = false;
2✔
278
        requestDelete();
2✔
279
    }
280
}
927,169✔
281

282
qreal GenericFader::intensity() const
927,170✔
283
{
284
    return m_intensity;
927,170✔
285
}
286

287
void GenericFader::adjustIntensity(qreal fraction)
127✔
288
{
289
    //qDebug() << name() << "I FADER intensity" << fraction << ", PARENT:" << m_parentIntensity;
290
    m_intensity = fraction;
127✔
291
}
127✔
292

293
qreal GenericFader::parentIntensity() const
927,169✔
294
{
295
    return m_parentIntensity;
927,169✔
296
}
297

298
void GenericFader::setParentIntensity(qreal fraction)
122✔
299
{
300
    //qDebug() << name() << "P FADER intensity" << m_intensity << ", PARENT:" << fraction;
301
    m_parentIntensity = fraction;
122✔
302
}
122✔
303

304
bool GenericFader::isPaused() const
×
305
{
306
    return m_paused;
×
307
}
308

309
void GenericFader::setPaused(bool paused)
5✔
310
{
311
    m_paused = paused;
5✔
312
}
5✔
313

314
bool GenericFader::isEnabled() const
927,068✔
315
{
316
    return m_enabled;
927,068✔
317
}
318

319
void GenericFader::setEnabled(bool enable)
×
320
{
321
    m_enabled = enable;
×
322
}
×
323

324
bool GenericFader::isFadingOut() const
2✔
325
{
326
    return m_fadeOut;
2✔
327
}
328

329
void GenericFader::setFadeOut(bool enable, uint fadeTime)
6✔
330
{
331
    m_fadeOut = enable;
6✔
332

333
    if (fadeTime == 0)
6✔
NEW
334
        return;
×
335

336
    QMutableHashIterator <quint32,FadeChannel> it(m_channels);
6✔
337
    while (it.hasNext() == true)
24✔
338
    {
339
        FadeChannel& fc(it.next().value());
18✔
340

341
        // non-intensity channels (eg LTP) should fade
342
        // to the current universe value
343
        if ((fc.flags() & FadeChannel::Intensity) == 0)
18✔
344
            fc.addFlag(FadeChannel::SetTarget);
6✔
345

346
        fc.setStart(fc.current());
18✔
347
        fc.setTarget(0);
18✔
348
        fc.setElapsed(0);
18✔
349
        fc.setReady(false);
18✔
350
        fc.setFadeTime(fc.canFade() ? fadeTime : 0);
18✔
351
    }
352
}
353

354
void GenericFader::setBlendMode(Universe::BlendMode mode)
120✔
355
{
356
    m_blendMode = mode;
120✔
357
}
120✔
358

359
void GenericFader::setMonitoring(bool enable)
×
360
{
361
    m_monitoring = enable;
×
362
}
×
363

364
void GenericFader::resetCrossfade()
×
365
{
366
    qDebug() << name() << "resetting crossfade channels";
×
367
    QMutableHashIterator <quint32,FadeChannel> it(m_channels);
×
368
    while (it.hasNext() == true)
×
369
    {
370
        FadeChannel& fc(it.next().value());
×
371
        fc.removeFlag(FadeChannel::CrossFade);
×
372
    }
373
}
×
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