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

mcallegari / qlcplus / 27464675422

13 Jun 2026 10:51AM UTC coverage: 35.377% (+0.1%) from 35.268%
27464675422

push

github

mcallegari
Enter 5.2.2 release

16530 of 46725 relevant lines covered (35.38%)

45646.51 hits per line

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

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

26
#include <QDebug>
27

28
#include "qlcinputchannel.h"
29
#include "qlcioplugin.h"
30
#include "inputpatch.h"
31

32
#define GRACE_MS 1
33

34
/*****************************************************************************
35
 * Initialization
36
 *****************************************************************************/
37

38
InputPatch::InputPatch(QObject *parent)
1✔
39
    : QObject(parent)
40
    , m_universe(UINT_MAX)
1✔
41
    , m_plugin(NULL)
1✔
42
    , m_pluginLine(QLCIOPlugin::invalidLine())
1✔
43
    , m_profile(NULL)
1✔
44
    , m_nextPageCh(USHRT_MAX)
1✔
45
    , m_prevPageCh(USHRT_MAX)
1✔
46
    , m_pageSetCh(USHRT_MAX)
1✔
47
{
48
}
1✔
49

50
InputPatch::InputPatch(quint32 inputUniverse, QObject* parent)
8✔
51
    : QObject(parent)
52
    , m_universe(inputUniverse)
8✔
53
    , m_plugin(NULL)
8✔
54
    , m_pluginLine(QLCIOPlugin::invalidLine())
8✔
55
    , m_profile(NULL)
8✔
56
    , m_nextPageCh(USHRT_MAX)
8✔
57
    , m_prevPageCh(USHRT_MAX)
8✔
58
    , m_pageSetCh(USHRT_MAX)
8✔
59
{
60
}
8✔
61

62
InputPatch::~InputPatch()
16✔
63
{
64
    if (m_plugin != NULL)
9✔
65
        m_plugin->closeInput(m_pluginLine, m_universe);
6✔
66
}
25✔
67

68
/*****************************************************************************
69
 * Properties
70
 *****************************************************************************/
71

72
bool InputPatch::set(QLCIOPlugin* plugin, quint32 input, QLCInputProfile* profile)
8✔
73
{
74
    bool result = false;
75

76
    qDebug() << "InputPatch::set - plugin:" << ((plugin == NULL)?"None":plugin->name())
16✔
77
             << ", line:" << input
8✔
78
             << ", profile:" << ((profile == NULL)?"None":profile->name());
16✔
79

80
    if (m_plugin != NULL && m_pluginLine != QLCIOPlugin::invalidLine())
8✔
81
    {
82
        disconnect(m_plugin, SIGNAL(valueChanged(quint32,quint32,quint32,uchar,QString)),
2✔
83
                   this, SLOT(slotValueChanged(quint32,quint32,quint32,uchar,QString)));
84
        m_plugin->closeInput(m_pluginLine, m_universe);
2✔
85
    }
86

87
    m_plugin = plugin;
8✔
88
    m_pluginLine = input;
8✔
89
    m_profile = profile;
8✔
90

91
    if (m_plugin != NULL)
8✔
92
    {
93
        emit pluginNameChanged();
8✔
94
        if (m_pluginLine != QLCIOPlugin::invalidLine())
8✔
95
            emit inputNameChanged();
8✔
96
        if (m_profile != NULL)
8✔
97
            emit profileNameChanged();
4✔
98
    }
99

100
    /* Open the assigned plugin input */
101
    if (m_plugin != NULL && m_pluginLine != QLCIOPlugin::invalidLine())
8✔
102
    {
103
        connect(m_plugin, SIGNAL(valueChanged(quint32,quint32,quint32,uchar,QString)),
8✔
104
                this, SLOT(slotValueChanged(quint32,quint32,quint32,uchar,QString)));
105
        result = m_plugin->openInput(m_pluginLine, m_universe);
8✔
106

107
        if (m_profile != NULL)
8✔
108
            setProfilePageControls();
4✔
109
    }
110
    return result;
8✔
111
}
112

113
bool InputPatch::set(QLCInputProfile *profile)
2✔
114
{
115
    if (m_plugin == NULL || m_pluginLine == QLCIOPlugin::invalidLine())
2✔
116
        return false;
117

118
    m_profile = profile;
1✔
119

120
    if (m_profile != NULL)
1✔
121
        setProfilePageControls();
1✔
122

123
    emit profileNameChanged();
1✔
124

125
    return true;
1✔
126
}
127

128
bool InputPatch::reconnect()
1✔
129
{
130
    if (m_plugin != NULL && m_pluginLine != QLCIOPlugin::invalidLine())
1✔
131
    {
132
        m_plugin->closeInput(m_pluginLine, m_universe);
1✔
133
#if defined(WIN32) || defined(Q_OS_WIN)
134
        Sleep(GRACE_MS);
135
#else
136
        usleep(GRACE_MS * 1000);
1✔
137
#endif
138
        bool ret = m_plugin->openInput(m_pluginLine, m_universe);
1✔
139
        if (ret == true)
1✔
140
        {
141
            QMap<QString, QVariant>::iterator it = m_parametersCache.begin();
1✔
142
            for (; it != m_parametersCache.end(); it++)
1✔
143
            {
144
                qDebug() << "[InputPatch] restoring parameter:" << it.key() << it.value();
×
145
                m_plugin->setParameter(m_universe, m_pluginLine, QLCIOPlugin::Input, it.key(), it.value());
×
146
            }
147
        }
148
        return ret;
1✔
149
    }
150
    return false;
151
}
152

153
QLCIOPlugin* InputPatch::plugin() const
12✔
154
{
155
    return m_plugin;
12✔
156
}
157

158
QString InputPatch::pluginName() const
17✔
159
{
160
    if (m_plugin != NULL)
17✔
161
        return m_plugin->name();
15✔
162
    else
163
        return KInputNone;
164
}
165

166
quint32 InputPatch::input() const
20✔
167
{
168
    return m_pluginLine;
20✔
169
}
170

171
QString InputPatch::inputName() const
6✔
172
{
173
    if (m_plugin != NULL && m_pluginLine != QLCIOPlugin::invalidLine() &&
6✔
174
            m_pluginLine < quint32(m_plugin->inputs().count()))
10✔
175
        return m_plugin->inputs()[m_pluginLine];
8✔
176
    else
177
        return KInputNone;
178
}
179

180
QString InputPatch::inputUID() const
×
181
{
182
    if (m_plugin != NULL && m_pluginLine != QLCIOPlugin::invalidLine() &&
×
183
            m_pluginLine < quint32(m_plugin->inputs().count()))
×
184
        return m_plugin->inputsUID()[m_pluginLine];
×
185
    else
186
        return KInputNone;
187
}
188

189
QLCInputProfile* InputPatch::profile() const
12✔
190
{
191
    return m_profile;
12✔
192
}
193

194
QString InputPatch::profileName() const
9✔
195
{
196
    if (m_profile != NULL)
9✔
197
        return m_profile->name();
6✔
198
    else
199
        return KInputNone;
200
}
201

202
bool InputPatch::isPatched() const
3✔
203
{
204
    return input() != QLCIOPlugin::invalidLine();
3✔
205
}
206

207
void InputPatch::setPluginParameter(QString prop, QVariant value)
1✔
208
{
209
    qDebug() << "[InputPatch] caching parameter:" << prop << value;
1✔
210
    m_parametersCache[prop] = value;
1✔
211
    if (m_plugin != NULL)
1✔
212
        m_plugin->setParameter(m_universe, m_pluginLine, QLCIOPlugin::Input, prop, value);
3✔
213
}
1✔
214

215
QMap<QString, QVariant> InputPatch::getPluginParameters()
3✔
216
{
217
    if (m_plugin != NULL)
3✔
218
        return m_plugin->getParameters(m_universe, m_pluginLine, QLCIOPlugin::Input);
3✔
219

220
    return QMap<QString, QVariant>();
×
221
}
222

223
void InputPatch::slotValueChanged(quint32 universe, quint32 input, quint32 channel,
6✔
224
                                  uchar value, const QString& key)
225
{
226
    // In case we have several lines connected to the same plugin, emit only
227
    // such values that belong to this particular patch.
228
    if (input == m_pluginLine)
6✔
229
    {
230
        if (universe == UINT_MAX || universe == m_universe)
4✔
231
        {
232
            QMutexLocker inputBufferLocker(&m_inputBufferMutex);
4✔
233
            InputValue val(value, key);
234
            if (m_inputBuffer.contains(channel))
1✔
235
            {
236
                InputValue const& curVal = m_inputBuffer.value(channel);
1✔
237
                if (curVal.value != val.value)
1✔
238
                {
239
                    // Every ON/OFF changes must pass through
240
                    if (curVal.value == 0 || val.value == 0)
1✔
241
                    {
242
                        emit inputValueChanged(m_universe, channel, curVal.value, curVal.key);
1✔
243
                    }
244
                    m_inputBuffer.insert(channel, val);
245
                }
246
            }
247
            else
248
            {
249
                m_inputBuffer.insert(channel, val);
3✔
250
            }
251
        }
252
    }
253
}
6✔
254

255
void InputPatch::setProfilePageControls()
5✔
256
{
257
    if (m_profile != NULL)
5✔
258
    {
259
        if (m_plugin != NULL)
5✔
260
        {
261
            QMap<QString, QVariant> settings = m_profile->globalSettings();
5✔
262
            if (settings.isEmpty() == false)
×
263
            {
264
                QMapIterator <QString,QVariant> it(settings);
×
265
                while (it.hasNext() == true)
×
266
                {
267
                    it.next();
268
                    m_plugin->setParameter(m_universe, m_pluginLine, QLCIOPlugin::Input, it.key(), it.value());
×
269
                }
270
            }
271
        }
272
        QMapIterator <quint32,QLCInputChannel*> it(m_profile->channels());
5✔
273
        while (it.hasNext() == true)
266✔
274
        {
275
            it.next();
276
            QLCInputChannel *ch = it.value();
256✔
277
            if (ch != NULL)
256✔
278
            {
279
                if (m_nextPageCh == USHRT_MAX && ch->type() == QLCInputChannel::NextPage)
256✔
280
                    m_nextPageCh = m_profile->channelNumber(ch);
×
281
                else if (m_prevPageCh == USHRT_MAX && ch->type() == QLCInputChannel::PrevPage)
256✔
282
                    m_prevPageCh = m_profile->channelNumber(ch);
×
283
                else if (m_pageSetCh == USHRT_MAX && ch->type() == QLCInputChannel::PageSet)
256✔
284
                    m_pageSetCh = m_profile->channelNumber(ch);
×
285
            }
286
        }
287
    }
288
}
5✔
289

290
void InputPatch::flush(quint32 universe)
5✔
291
{
292
    if (universe == UINT_MAX || universe == m_universe)
5✔
293
    {
294
        QMutexLocker inputBufferLocker(&m_inputBufferMutex);
5✔
295
        for (QHash<quint32, InputValue>::const_iterator it = m_inputBuffer.begin(); it != m_inputBuffer.end(); ++it)
5✔
296
        {
297
            emit inputValueChanged(m_universe, it.key(), it.value().value, it.value().key);
3✔
298
        }
299
        m_inputBuffer.clear();
5✔
300
    }
301
}
5✔
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