Skip to content

Commit 5516761

Browse files
committed
Fix PTZ action commands getting ignored
Switching to the prochandler API broke the action source because the proc handler lambdas were ignoring all calls from threads other than the GUI thread. This was done because the calldata structure usually lives on the callers stack, and if a call was queued on the correct thread, e.g. by calling QMetaObject::invokeMethod(), then the calldata would be gone by the time the method ran. However, the action source triggers don't come from the UI thread. To fix this, rework the proc handlers to extract the calldata arguments in the callers thread, and then use invokeMethod() to call the device method, using the default Qt::AutoConnection mode so that calls from the GUI thread are direct, but calls from other threads get queued. For most methods this works fine because the calls are commands to the device. The one exception is the ::get() method which needs to return data to the caller. This is the one proc handler method that still needs to be called by the GUI thread, and it gets ignored if it is not. This perhaps could be fixed by using a BlockingQueued connection, but it is unclear if it is needed and that change can be done in another patch. Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
1 parent 29c80a6 commit 5516761

2 files changed

Lines changed: 20 additions & 21 deletions

File tree

src/ptz-device.cpp

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,6 @@
3535
blog(LOG_ERROR, "PTZ proc_handler called without PTZDevice pointer"); \
3636
return; \
3737
} \
38-
if (QThread::currentThread() != ptz->thread()) { \
39-
blog(LOG_WARNING, "PTZDevice proc_handler '%s'->%s() call from non-GUI thread; ignored", QT_TO_UTF8(ptz->objectName()), #_method); \
40-
return; \
41-
} \
4238
ptz->_method(cd); \
4339
}
4440

@@ -172,39 +168,43 @@ void PTZDevice::move(calldata_t *cd)
172168
double p = 0, t = 0, z = 0, f = 0;
173169

174170
if (calldata_get_float(cd, "pan", &p) + calldata_get_float(cd, "tilt", &t))
175-
pantilt(p, t);
171+
QMetaObject::invokeMethod(this, &PTZDevice::pantilt, p, t);
176172

177173
if (calldata_get_float(cd, "zoom", &z))
178-
zoom(z);
174+
QMetaObject::invokeMethod(this, &PTZDevice::zoom, z);
179175

180176
if (calldata_get_float(cd, "focus", &f))
181-
focus(f);
177+
QMetaObject::invokeMethod(this, &PTZDevice::focus, f);
182178
}
183179

184180
void PTZDevice::move_abs(calldata_t *cd)
185181
{
186182
double p = 0, t = 0, z = 0, f = 0;
187183

188184
if (calldata_get_float(cd, "pan", &p) + calldata_get_float(cd, "tilt", &t))
189-
pantilt_abs(p, t);
185+
QMetaObject::invokeMethod(this, &PTZDevice::pantilt_abs, p, t);
190186

191187
if (calldata_get_float(cd, "zoom", &z))
192-
zoom_abs(z);
188+
QMetaObject::invokeMethod(this, &PTZDevice::zoom_abs, z);
193189

194190
if (calldata_get_float(cd, "focus", &f))
195-
focus_abs(f);
191+
QMetaObject::invokeMethod(this, &PTZDevice::focus_abs, f);
196192
}
197193

198194
void PTZDevice::move_rel(calldata_t *cd)
199195
{
200196
double p = 0, t = 0;
201197

202198
if (calldata_get_float(cd, "pan", &p) + calldata_get_float(cd, "tilt", &t))
203-
pantilt_rel(p, t);
199+
QMetaObject::invokeMethod(this, &PTZDevice::pantilt_rel, p, t);
204200
}
205201

206202
void PTZDevice::get(calldata_t *cd) const
207203
{
204+
if (QThread::currentThread() != thread()) {
205+
ptz_log(LOG_ERROR, "get(calldata) called from non-GUI thread; ignored");
206+
return;
207+
}
208208
QString arg = calldata_string(cd, "property");
209209
if (arg == "power_on")
210210
calldata_set_bool(cd, "power_on", obs_data_get_bool(settings, "power_on"));
@@ -217,31 +217,31 @@ void PTZDevice::set(calldata_t *cd)
217217
{
218218
bool enable;
219219
if (calldata_get_bool(cd, "focus_af_enabled", &enable))
220-
set_autofocus(enable);
220+
QMetaObject::invokeMethod(this, &PTZDevice::set_autofocus, enable);
221221
bool trigger;
222222
if (calldata_get_bool(cd, "focus_onetouch_trigger", &trigger) && trigger)
223-
focus_onetouch();
223+
QMetaObject::invokeMethod(this, &PTZDevice::focus_onetouch);
224224
}
225225

226226
void PTZDevice::preset_save(calldata_t *cd)
227227
{
228228
long long id;
229229
if (calldata_get_int(cd, "preset_id", &id))
230-
memory_set(id);
230+
QMetaObject::invokeMethod(this, &PTZDevice::memory_set, (int)id);
231231
}
232232

233233
void PTZDevice::preset_recall(calldata_t *cd)
234234
{
235235
long long id;
236236
if (calldata_get_int(cd, "preset_id", &id))
237-
memory_recall(id);
237+
QMetaObject::invokeMethod(this, "memory_recall", (int)id);
238238
}
239239

240240
void PTZDevice::preset_clear(calldata_t *cd)
241241
{
242242
long long id;
243243
if (calldata_get_int(cd, "preset_id", &id))
244-
memory_reset(id);
244+
QMetaObject::invokeMethod(this, &PTZDevice::memory_reset, (int)id);
245245
}
246246

247247
void PTZDevice::getDefaults(OBSData config) const

src/ptz-device.hpp

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ class PTZDevice : public QObject {
109109
* zoom: range[0.0, 1.0], 0.0 == wide angle, 1.0 == telephoto
110110
* focus: range[0.0, 1.0], 0.0 == far focus, 1.0 == near focus
111111
*/
112-
protected:
112+
protected slots:
113113
void stop();
114114
void pantilt(double pan, double tilt);
115115
virtual void pantilt_rel(double pan, double tilt)
@@ -142,10 +142,9 @@ class PTZDevice : public QObject {
142142
virtual void memory_recall(int i) { Q_UNUSED(i); }
143143
virtual void memory_reset(int i) { Q_UNUSED(i); }
144144

145-
protected slots:
146-
void stop(calldata_t *) { stop(); }
147-
void pantilt_home(calldata_t *) { pantilt_home(); }
148-
void pantilt_set_home(calldata_t *) { pantilt_set_home(); };
145+
void stop(calldata_t *) { QMetaObject::invokeMethod(this, "stop"); }
146+
void pantilt_home(calldata_t *) { QMetaObject::invokeMethod(this, "pantilt_home"); }
147+
void pantilt_set_home(calldata_t *) { QMetaObject::invokeMethod(this, "pantilt_set_home"); }
149148
void move(calldata_t *cd);
150149
void move_abs(calldata_t *cd);
151150
void move_rel(calldata_t *cd);

0 commit comments

Comments
 (0)