@@ -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}
9089GPhotoCameraWorker::~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}
0 commit comments