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

mcallegari / qlcplus / 21722433216

05 Feb 2026 05:52PM UTC coverage: 34.078% (+0.08%) from 33.994%
21722433216

push

github

mcallegari
Enter 5.2.0 release

15811 of 46396 relevant lines covered (34.08%)

22805.58 hits per line

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

92.13
/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
QLCInputProfile* InputPatch::profile() const
12✔
181
{
182
    return m_profile;
12✔
183
}
184

185
QString InputPatch::profileName() const
9✔
186
{
187
    if (m_profile != NULL)
9✔
188
        return m_profile->name();
6✔
189
    else
190
        return KInputNone;
191
}
192

193
bool InputPatch::isPatched() const
3✔
194
{
195
    return input() != QLCIOPlugin::invalidLine();
3✔
196
}
197

198
void InputPatch::setPluginParameter(QString prop, QVariant value)
1✔
199
{
200
    qDebug() << "[InputPatch] caching parameter:" << prop << value;
1✔
201
    m_parametersCache[prop] = value;
1✔
202
    if (m_plugin != NULL)
1✔
203
        m_plugin->setParameter(m_universe, m_pluginLine, QLCIOPlugin::Input, prop, value);
3✔
204
}
1✔
205

206
QMap<QString, QVariant> InputPatch::getPluginParameters()
3✔
207
{
208
    if (m_plugin != NULL)
3✔
209
        return m_plugin->getParameters(m_universe, m_pluginLine, QLCIOPlugin::Input);
3✔
210

211
    return QMap<QString, QVariant>();
×
212
}
213

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

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

281
void InputPatch::flush(quint32 universe)
5✔
282
{
283
    if (universe == UINT_MAX || universe == m_universe)
5✔
284
    {
285
        QMutexLocker inputBufferLocker(&m_inputBufferMutex);
5✔
286
        for (QHash<quint32, InputValue>::const_iterator it = m_inputBuffer.begin(); it != m_inputBuffer.end(); ++it)
5✔
287
        {
288
            emit inputValueChanged(m_universe, it.key(), it.value().value, it.value().key);
3✔
289
        }
290
        m_inputBuffer.clear();
5✔
291
    }
292
}
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