Skip to content

Commit 1095e47

Browse files
committed
add keepalive timer in order to keep camera from switching into standby
1 parent 8deaaf4 commit 1095e47

2 files changed

Lines changed: 243 additions & 21 deletions

File tree

src/gphotocamera.cpp

Lines changed: 235 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -83,9 +83,8 @@ GPhotoCameraWorker::GPhotoCameraWorker()
8383
gp_abilities_list_new(&caList);
8484
mAbilitiesList.reset(caList);
8585

86-
mCaptureTimer.setInterval(1000 * 60); // Check every minute
87-
connect(&mCaptureTimer, &QTimer::timeout, this,
88-
&GPhotoCameraWorker::checkCaptureParameter);
86+
mKeepAliveTimer.setInterval(1000 * 60); // Check every minute
87+
mKeepAliveTimer.setSingleShot(true);
8988
}
9089
GPhotoCameraWorker::~GPhotoCameraWorker() {}
9190

@@ -147,8 +146,8 @@ void GPhotoCameraWorker::startCamera(const QString &cameraName) {
147146

148147
mCameraStarted = true;
149148

150-
if (!mCaptureTimer.isActive()) {
151-
mCaptureTimer.start();
149+
if (!mKeepAliveTimer.isActive()) {
150+
QMetaObject::invokeMethod(&mKeepAliveTimer, "start", Qt::QueuedConnection);
152151
}
153152

154153
getPreviewFrame();
@@ -159,10 +158,6 @@ void GPhotoCameraWorker::stopCamera() {
159158
return;
160159
}
161160

162-
if (mCaptureTimer.isActive()) {
163-
mCaptureTimer.stop();
164-
}
165-
166161
// Reset capturing fail counter
167162
mCapturingFailCount = 0;
168163

@@ -258,6 +253,11 @@ void GPhotoCameraWorker::getPreviewFrame() {
258253
return;
259254
} else {
260255

256+
if(!mKeepAliveTimer.isActive()) {
257+
checkCaptureParameter();
258+
QMetaObject::invokeMethod(&mKeepAliveTimer, "start", Qt::QueuedConnection);
259+
}
260+
261261
gp_file_clean(mPreviewFile.get());
262262

263263
auto ret = gp_camera_capture_preview(mCamera.get(), mPreviewFile.get(),
@@ -295,17 +295,233 @@ void GPhotoCameraWorker::checkCaptureParameter() {
295295
return;
296296
}
297297

298-
CameraWidget *widget = nullptr;
299-
int ret = gp_camera_get_config(mCamera.get(), &widget, mContext.get());
300-
if (ret >= GP_OK) {
301-
CameraWidget *child = nullptr;
302-
ret = gp_widget_get_child_by_name(widget, "capture", &child);
303-
if (ret >= GP_OK) {
304-
ret = gp_widget_set_value(child, 1); // Set capture to true
305-
if (ret >= GP_OK) {
306-
gp_camera_set_config(mCamera.get(), widget, mContext.get());
298+
QVariant captureParameter = parameter("capture");
299+
300+
if (captureParameter.isValid())
301+
{
302+
if (captureParameter.toBool() == false)
303+
{
304+
setParameter("capture", true);
305+
qWarning() << "Set parameter 'capture' to 'true'";
306+
}
307+
}
308+
}
309+
310+
void GPhotoCameraWorker::waitForOperationCompleted() {
311+
CameraEventType type;
312+
void *data;
313+
int ret;
314+
315+
do {
316+
ret = gp_camera_wait_for_event(mCamera.get(), 10, &type, &data, mContext.get());
317+
} while ((ret == GP_OK) && (type != GP_EVENT_TIMEOUT));
318+
}
319+
320+
QVariant GPhotoCameraWorker::parameter(const QString &name) {
321+
CameraWidget *root;
322+
int ret = gp_camera_get_config(mCamera.get(), &root, mContext.get());
323+
if (ret < GP_OK) {
324+
qWarning() << "Unable to get root option from gphoto";
325+
return QVariant();
326+
}
327+
328+
CameraWidget *option;
329+
ret = gp_widget_get_child_by_name(root, qPrintable(name), &option);
330+
if (ret < GP_OK) {
331+
qWarning() << "Unable to get config widget from gphoto";
332+
return QVariant();
333+
}
334+
335+
CameraWidgetType type;
336+
ret = gp_widget_get_type(option, &type);
337+
if (ret < GP_OK) {
338+
qWarning() << "Unable to get config widget type from gphoto";
339+
return QVariant();
340+
}
341+
342+
if (type == GP_WIDGET_RADIO) {
343+
char *value;
344+
ret = gp_widget_get_value(option, &value);
345+
if (ret < GP_OK) {
346+
qWarning() << "Unable to get value for option" << qPrintable(name)
347+
<< "from gphoto";
348+
return QVariant();
349+
} else {
350+
return QString::fromLocal8Bit(value);
351+
}
352+
} else if (type == GP_WIDGET_TOGGLE) {
353+
int value;
354+
ret = gp_widget_get_value(option, &value);
355+
if (ret < GP_OK) {
356+
qWarning() << "Unable to get value for option" << qPrintable(name)
357+
<< "from gphoto";
358+
return QVariant();
359+
} else {
360+
return value == 0 ? false : true;
361+
}
362+
} else {
363+
qWarning() << "Options of type" << type << "are currently not supported";
364+
}
365+
366+
return QVariant();
367+
}
368+
369+
bool GPhotoCameraWorker::setParameter(const QString &name,
370+
const QVariant &value) {
371+
CameraWidget *root;
372+
int ret = gp_camera_get_config(mCamera.get(), &root, mContext.get());
373+
if (ret < GP_OK) {
374+
qWarning() << "Unable to get root option from gphoto";
375+
return false;
376+
}
377+
378+
// Get widget pointer
379+
CameraWidget *option;
380+
ret = gp_widget_get_child_by_name(root, qPrintable(name), &option);
381+
if (ret < GP_OK) {
382+
qWarning() << "Unable to get option" << qPrintable(name) << "from gphoto";
383+
return false;
384+
}
385+
386+
// Get option type
387+
CameraWidgetType type;
388+
ret = gp_widget_get_type(option, &type);
389+
if (ret < GP_OK) {
390+
qWarning() << "Unable to get option type from gphoto";
391+
gp_widget_free(option);
392+
return false;
393+
}
394+
395+
if (type == GP_WIDGET_RADIO) {
396+
if (value.type() == QVariant::String) {
397+
// String, need no conversion
398+
ret = gp_widget_set_value(option, qPrintable(value.toString()));
399+
400+
if (ret < GP_OK) {
401+
qWarning() << "Failed to set value" << value << "to" << name
402+
<< "option:" << ret;
403+
return false;
404+
}
405+
406+
ret = gp_camera_set_config(mCamera.get(), root, mContext.get());
407+
408+
if (ret < GP_OK) {
409+
qWarning() << "Failed to set config to camera";
410+
return false;
307411
}
412+
413+
waitForOperationCompleted();
414+
return true;
415+
} else if (value.type() == QVariant::Double) {
416+
// Trying to find nearest possible value (with the distance of 0.1) and
417+
// set it to property
418+
double v = value.toDouble();
419+
420+
int count = gp_widget_count_choices(option);
421+
for (int i = 0; i < count; ++i) {
422+
const char *choice;
423+
gp_widget_get_choice(option, i, &choice);
424+
425+
// We use a workaround for flawed russian i18n of gphoto2 strings
426+
bool ok;
427+
double choiceValue =
428+
QString::fromLocal8Bit(choice).replace(',', '.').toDouble(&ok);
429+
if (!ok) {
430+
qDebug() << "Failed to convert value" << choice << "to double";
431+
continue;
432+
}
433+
434+
if (qAbs(choiceValue - v) < 0.1) {
435+
ret = gp_widget_set_value(option, choice);
436+
if (ret < GP_OK) {
437+
qWarning() << "Failed to set value" << choice << "to" << name
438+
<< "option:" << ret;
439+
return false;
440+
}
441+
442+
ret = gp_camera_set_config(mCamera.get(), root, mContext.get());
443+
if (ret < GP_OK) {
444+
qWarning() << "Failed to set config to camera";
445+
return false;
446+
}
447+
448+
waitForOperationCompleted();
449+
return true;
450+
}
451+
}
452+
453+
qWarning() << "Can't find value matching to" << v << "for option" << name;
454+
return false;
455+
} else if (value.type() == QVariant::Int) {
456+
// Little hacks for 'ISO' option: if the value is -1, we pick the first
457+
// non-integer value we found and set it as a parameter
458+
int v = value.toInt();
459+
460+
int count = gp_widget_count_choices(option);
461+
for (int i = 0; i < count; ++i) {
462+
const char *choice;
463+
gp_widget_get_choice(option, i, &choice);
464+
465+
bool ok;
466+
int choiceValue = QString::fromLocal8Bit(choice).toInt(&ok);
467+
468+
if ((ok && choiceValue == v) || (!ok && v == -1)) {
469+
ret = gp_widget_set_value(option, choice);
470+
if (ret < GP_OK) {
471+
qWarning() << "Failed to set value" << choice << "to" << name
472+
<< "option:" << ret;
473+
return false;
474+
}
475+
476+
ret = gp_camera_set_config(mCamera.get(), root, mContext.get());
477+
if (ret < GP_OK) {
478+
qWarning() << "Failed to set config to camera";
479+
return false;
480+
}
481+
482+
waitForOperationCompleted();
483+
return true;
484+
}
485+
}
486+
487+
qWarning() << "Can't find value matching to" << v << "for option" << name;
488+
return false;
489+
} else {
490+
qWarning() << "Failed to set value" << value << "to" << name
491+
<< "option. Type" << value.type() << "is not supported";
492+
gp_widget_free(option);
493+
return false;
494+
}
495+
} else if (type == GP_WIDGET_TOGGLE) {
496+
int v = 0;
497+
if (value.canConvert<int>()) {
498+
v = value.toInt();
499+
} else {
500+
qWarning() << "Failed to set value" << value << "to" << name
501+
<< "option. Type" << value.type() << "is not supported";
502+
gp_widget_free(option);
503+
return false;
308504
}
309-
gp_widget_free(widget);
505+
506+
ret = gp_widget_set_value(option, &v);
507+
if (ret < GP_OK) {
508+
qWarning() << "Failed to set value" << v << "to" << name
509+
<< "option:" << ret;
510+
return false;
511+
}
512+
513+
ret = gp_camera_set_config(mCamera.get(), root, mContext.get());
514+
if (ret < GP_OK) {
515+
qWarning() << "Failed to set config to camera";
516+
return false;
517+
}
518+
519+
waitForOperationCompleted();
520+
return true;
521+
} else {
522+
qWarning() << "Options of type" << type << "are currently not supported";
310523
}
524+
525+
gp_widget_free(option);
526+
return false;
311527
}

src/gphotocamera.h

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33
#include <QThread>
44
#include <QStringList>
55
#include <QImage>
6+
#include <QTimer>
7+
#include <QVariant>
8+
#include <memory>
69

710
#include <cstdint>
811
#include <gphoto2/gphoto2-abilities-list.h>
@@ -73,15 +76,18 @@ public slots:
7376
void imageCaptured(const QImage &image);
7477
void captureError(const QString &error);
7578
protected:
76-
QTimer mCaptureTimer;
79+
QTimer mKeepAliveTimer;
7780
GPContextPtr mContext;
7881
GPPortInfoListPtr mPortInfoList;
7982
CameraAbilitiesListPtr mAbilitiesList;
8083
CameraPtr mCamera;
8184
CameraFilePtr mPreviewFile;
8285
bool mCameraStarted = false;
8386
uint32_t mCapturingFailCount = 0;
84-
// Add private members for camera handling
87+
88+
void waitForOperationCompleted();
89+
QVariant parameter(const QString &name);
90+
bool setParameter(const QString &name, const QVariant &value);
8591
protected slots:
8692
// check and set capture parameters to keep camera alive
8793
void checkCaptureParameter();

0 commit comments

Comments
 (0)