Source code upload
[framework/connectivity/libgphoto2.git] / libgphoto2 / gphoto2-camera.c
1 /** \file
2  *
3  * Implement Camera object representing a camera attached to the system.
4  *
5  * \author Copyright 2000 Scott Fritzinger
6  * \author Copyright 2001-2002 Lutz Müller <lutz@users.sf.net>
7  *
8  * \note
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 2 of the License, or (at your option) any later version.
13  *
14  * \note
15  * This library is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18  * Lesser General Public License for more details.
19  *
20  * \note
21  * You should have received a copy of the GNU Lesser General Public
22  * License along with this library; if not, write to the
23  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
24  * Boston, MA 02111-1307, USA.
25  */
26
27 #include "config.h"
28 #include <gphoto2/gphoto2-camera.h>
29
30 #include <stdlib.h>
31 #include <string.h>
32 #include <stdarg.h>
33 #include <stdio.h>
34
35 #include <gphoto2/gphoto2_slp_support.h>
36
37 #include <gphoto2/gphoto2-result.h>
38 #include <gphoto2/gphoto2-library.h>
39 #include <gphoto2/gphoto2-port-log.h>
40
41 #ifdef ENABLE_NLS
42 #  include <libintl.h>
43 #  undef _
44 #  define _(String) dgettext (GETTEXT_PACKAGE, String)
45 #  ifdef gettext_noop
46 #    define N_(String) gettext_noop (String)
47 #  else
48 #    define N_(String) (String)
49 #  endif
50 #else
51 #  define textdomain(String) (String)
52 #  define gettext(String) (String)
53 #  define dgettext(Domain,Message) (Message)
54 #  define dcgettext(Domain,Message,Type) (Message)
55 #  define bindtextdomain(Domain,Directory) (Domain)
56 #  define _(String) (String)
57 #  define N_(String) (String)
58 #endif
59
60 #define CHECK_NULL(r)              {if (!(r)) return (GP_ERROR_BAD_PARAMETERS);}
61
62 #define CAMERA_UNUSED(c,ctx)                                            \
63 {                                                                       \
64         (c)->pc->used--;                                                \
65         if (!(c)->pc->used) {                                           \
66                 if ((c)->pc->exit_requested)                            \
67                         gp_camera_exit ((c), (ctx));                    \
68                 if (!(c)->pc->ref_count)                                \
69                         gp_camera_free (c);                             \
70         }                                                               \
71 }
72
73 #define CR(c,result,ctx)                                                \
74 {                                                                       \
75         int r1 = (result);                                              \
76                                                                         \
77         if (r1 < 0) {                                                   \
78                                                                         \
79                 /* libgphoto2_port doesn't have a GPContext */          \
80                 if (r1 > -100)                                          \
81                         gp_context_error ((ctx), _("An error occurred " \
82                                 "in the io-library ('%s'): %s"),        \
83                                 gp_port_result_as_string (r1),          \
84                                 (c) ? gp_port_get_error ((c)->port) :   \
85                                       _("No additional information "    \
86                                       "available."));                   \
87                 if (c)                                                  \
88                         CAMERA_UNUSED((c),(ctx));                       \
89                 return (r1);                                            \
90         }                                                               \
91 }
92
93 /*
94  * HAVE_MULTI
95  * ----------
96  *
97  * The problem: Several different programs (gtkam, gphoto2, gimp) accessing
98  *              one camera.
99  * The solutions:
100  *  (1) gp_port_open before each operation, gp_port_close after. This has
101  *      shown to not work with some drivers (digita/dc240) for serial ports,
102  *      because the camera will notice that [1],
103  *      reset itself and will therefore need to be reinitialized. If you want
104  *      this behaviour, #define HAVE_MULTI.
105  *  (2) Leave it up to the frontend to release the camera by calling
106  *      gp_camera_exit after camera operations. This is what is implemented
107  *      right now. The drawback is that re-initialization takes more time than
108  *      just reopening the port. However, it works for all camera drivers.
109  *
110  * [1] Marr <marr@shianet.org> writes:
111  *
112  *     With the Digita-OS cameras at least, one of the RS-232 lines is tied
113  *     to a 'Reset' signal on the camera.  I quote from the Digita 'Host
114  *     Interface Specification' document:
115  *
116  *     "The Reset signal is a pulse on the Reset/Att line (which cooresponds
117  *     [sic] to pin 2 at the camera side) sent from the host computer to the
118  *     camera.  This pulse must be at least 50us."
119  */
120
121 #ifdef HAVE_MULTI
122 #define CHECK_OPEN(c,ctx)                                               \
123 {                                                                       \
124         int r2;                                                         \
125                                                                         \
126         if (strcmp ((c)->pc->a.model,"Directory Browse")) {             \
127                 r2 = gp_port_open ((c)->port);                          \
128                 if (r2 < 0) {                                           \
129                         CAMERA_UNUSED (c,ctx);                          \
130                         return (r2);                                    \
131                 }                                                       \
132         }                                                               \
133         if ((c)->functions->pre_func) {                                 \
134                 r2 = (c)->functions->pre_func (c,ctx);                  \
135                 if (r2 < 0) {                                           \
136                         CAMERA_UNUSED (c,ctx);                          \
137                         return (r2);                                    \
138                 }                                                       \
139         }                                                               \
140 }
141 #else
142 #define CHECK_OPEN(c,ctx)                                               \
143 {                                                                       \
144         if ((c)->functions->pre_func) {                                 \
145                 int r2 = (c)->functions->pre_func (c,ctx);              \
146                 if (r2 < 0) {                                           \
147                         CAMERA_UNUSED (c,ctx);                          \
148                         return (r2);                                    \
149                 }                                                       \
150         }                                                               \
151 }
152 #endif
153
154 #ifdef HAVE_MULTI
155 #define CHECK_CLOSE(c,ctx)                                      \
156 {                                                               \
157         if (strcmp ((c)->pc->a.model,"Directory Browse"))       \
158                 gp_port_close ((c)->port);                      \
159         if ((c)->functions->post_func) {                        \
160                 int r3 = (c)->functions->post_func (c,ctx);     \
161                 if (r3 < 0) {                                   \
162                         CAMERA_UNUSED (c,ctx);                  \
163                         return (r3);                            \
164                 }                                               \
165         }                                                       \
166 }
167 #else
168 #define CHECK_CLOSE(c,ctx)                                      \
169 {                                                               \
170         if ((c)->functions->post_func) {                        \
171                 int r3 = (c)->functions->post_func (c,ctx);     \
172                 if (r3 < 0) {                                   \
173                         CAMERA_UNUSED (c,ctx);                  \
174                         return (r3);                            \
175                 }                                               \
176         }                                                       \
177 }
178 #endif
179
180 #define CRS(c,res,ctx)                                                  \
181 {                                                                       \
182         int r4 = (res);                                                 \
183                                                                         \
184         if (r4 < 0) {                                                   \
185                 CAMERA_UNUSED (c,ctx);                                  \
186                 return (r4);                                            \
187         }                                                               \
188 }
189
190 #define CRSL(c,res,ctx,list)                                            \
191 {                                                                       \
192         int r5 = (res);                                                 \
193                                                                         \
194         if (r5 < 0) {                                                   \
195                 CAMERA_UNUSED (c,ctx);                                  \
196                 gp_list_free (list);                                    \
197                 return (r5);                                            \
198         }                                                               \
199 }
200
201 #define CHECK_RESULT_OPEN_CLOSE(c,result,ctx)                           \
202 {                                                                       \
203         int r6;                                                         \
204                                                                         \
205         CHECK_OPEN (c,ctx);                                             \
206         r6 = (result);                                                  \
207         if (r6 < 0) {                                                   \
208                 CHECK_CLOSE (c,ctx);                                    \
209                 gp_log (GP_LOG_DEBUG, "gphoto2-camera", "Operation failed!");\
210                 CAMERA_UNUSED (c,ctx);                                  \
211                 return (r6);                                            \
212         }                                                               \
213         CHECK_CLOSE (c,ctx);                                            \
214 }
215
216 #define CHECK_INIT(c,ctx)                                               \
217 {                                                                       \
218         if ((c)->pc->used)                                              \
219                 return (GP_ERROR_CAMERA_BUSY);                          \
220         (c)->pc->used++;                                                \
221         if (!(c)->pc->lh)                                               \
222                 CR((c), gp_camera_init (c, ctx), ctx);                  \
223 }
224
225 struct _CameraPrivateCore {
226
227         /* Some information about the port */
228         unsigned int speed;
229
230         /* The abilities of this camera */
231         CameraAbilities a;
232
233         /* Library handle */
234         lt_dlhandle lh;
235
236         char error[2048];
237
238         unsigned int ref_count;
239         unsigned char used;
240         unsigned char exit_requested;
241
242         int initialized;
243
244         /* Timeout functions */
245         CameraTimeoutStartFunc timeout_start_func;
246         CameraTimeoutStopFunc  timeout_stop_func;
247         void                  *timeout_data;
248         unsigned int          *timeout_ids;
249         unsigned int           timeout_ids_len;
250 };
251
252
253 /**
254  * Close connection to camera.
255  *
256  * @param camera a #Camera object
257  * @param context a #GPContext object
258  * @return a gphoto2 error code.
259  *
260  * Closes a connection to the camera and therefore gives other application
261  * the possibility to access the camera, too.
262  *
263  * It is recommended that you
264  * call this function when you currently don't need the camera. The camera
265  * will get reinitialized by gp_camera_init() automatically if you try to
266  * access the camera again.
267  *
268  */
269 int
270 gp_camera_exit (Camera *camera, GPContext *context)
271 {
272         CHECK_NULL (camera);
273
274         gp_log (GP_LOG_DEBUG, "gphoto2-camera", "Exiting camera ('%s')...",
275                 camera->pc->a.model);
276
277         /*
278          * We have to postpone this operation if the camera is currently
279          * in use. gp_camera_exit will be called again if the
280          * camera->pc->used will drop to zero.
281          */
282         if (camera->pc->used) {
283                 camera->pc->exit_requested = 1;
284                 return (GP_OK);
285         }
286
287         /* Remove every timeout that is still pending */
288         while (camera->pc->timeout_ids_len)
289                 gp_camera_stop_timeout (camera, camera->pc->timeout_ids[0]);
290         free (camera->pc->timeout_ids);
291         camera->pc->timeout_ids = NULL;
292
293         if (camera->functions->exit) {
294 #ifdef HAVE_MULTI
295                 gp_port_open (camera->port);
296 #endif
297                 camera->functions->exit (camera, context);
298         }
299         gp_port_close (camera->port);
300         memset (camera->functions, 0, sizeof (CameraFunctions));
301
302         if (camera->pc->lh) {
303                 lt_dlclose (camera->pc->lh);
304                 lt_dlexit ();
305                 camera->pc->lh = NULL;
306         }
307
308         gp_filesystem_reset (camera->fs);
309
310         return (GP_OK);
311 }
312
313
314 /**
315  * Allocates the memory for a #Camera.
316  *
317  * @param camera the #Camera object to initialize.
318  * @return a gphoto2 error code
319  *
320  */
321 int
322 gp_camera_new (Camera **camera)
323 {
324         int result;
325
326         CHECK_NULL (camera);
327
328         *camera = malloc (sizeof (Camera));
329         if (!*camera)
330                 return (GP_ERROR_NO_MEMORY);
331         memset (*camera, 0, sizeof (Camera));
332
333         (*camera)->functions = malloc(sizeof(CameraFunctions));
334         if (!(*camera)->functions) {
335                 gp_camera_free (*camera);
336                 return (GP_ERROR_NO_MEMORY);
337         }
338         memset ((*camera)->functions, 0, sizeof (CameraFunctions));
339
340         (*camera)->pc = malloc (sizeof (CameraPrivateCore));
341         if (!(*camera)->pc) {
342                 gp_camera_free (*camera);
343                 return (GP_ERROR_NO_MEMORY);
344         }
345         memset ((*camera)->pc, 0, sizeof (CameraPrivateCore));
346
347         (*camera)->pc->ref_count = 1;
348
349         /* Create the filesystem */
350         result = gp_filesystem_new (&(*camera)->fs);
351         if (result != GP_OK) {
352                 gp_camera_free (*camera);
353                 return (result);
354         }
355
356         /* Create the port */
357         result = gp_port_new (&(*camera)->port);
358         if (result < 0) {
359                 gp_camera_free (*camera);
360                 return (result);
361         }
362
363         return(GP_OK);
364 }
365
366
367 /**
368  * \brief Sets the camera abilities.
369  *
370  * @param camera a #Camera
371  * @param abilities the #CameraAbilities to be set
372  * @return a gphoto2 error code
373  *
374  * You need to call this function before calling #gp_camera_init the
375  * first time unless you want gphoto2 to autodetect cameras and choose
376  * the first detected one. By setting the \c abilities, you
377  * tell gphoto2 what model the \c camera is and what camera driver should
378  * be used for accessing the \c camera. You can get \c abilities by calling
379  * #gp_abilities_list_get_abilities.
380  *
381  */
382 int
383 gp_camera_set_abilities (Camera *camera, CameraAbilities abilities)
384 {
385         gp_log (GP_LOG_DEBUG, "gphoto2-camera", "Setting abilities ('%s')...",
386                 abilities.model);
387
388         CHECK_NULL (camera);
389
390         /*
391          * If the camera is currently initialized, terminate that connection.
392          * We don't care if we are successful or not.
393          */
394         if (camera->pc->lh)
395                 gp_camera_exit (camera, NULL);
396
397         memcpy (&camera->pc->a, &abilities, sizeof (CameraAbilities));
398
399         return (GP_OK);
400 }
401
402
403 /**
404  * Retrieve the \c abilities of the \c camera.
405  *
406  * @param camera a #Camera
407  * @param abilities
408  * @return a gphoto2 error code
409  *
410  */
411 int
412 gp_camera_get_abilities (Camera *camera, CameraAbilities *abilities)
413 {
414         CHECK_NULL (camera && abilities);
415
416         memcpy (abilities, &camera->pc->a, sizeof (CameraAbilities));
417
418         return (GP_OK);
419 }
420
421
422 int
423 gp_camera_get_port_info (Camera *camera, GPPortInfo *info)
424 {
425         CHECK_NULL (camera && info);
426
427         CR (camera, gp_port_get_info (camera->port, info), NULL);
428
429         return (GP_OK);
430 }
431
432
433 int
434 gp_camera_set_port_info (Camera *camera, GPPortInfo info)
435 {
436         CHECK_NULL (camera);
437
438         /*
439          * If the camera is currently initialized, terminate that connection.
440          * We don't care if we are successful or not.
441          */
442         if (camera->pc->lh)
443                 gp_camera_exit (camera, NULL);
444
445         gp_log (GP_LOG_DEBUG, "gphoto2-camera", "Setting port info for "
446                 "port '%s' at '%s'...", info.name, info.path);
447         CR (camera, gp_port_set_info (camera->port, info), NULL);
448
449         return (GP_OK);
450 }
451
452
453 /**
454  * Set the camera speed.
455  *
456  * @param camera a #Camera
457  * @param speed the speed
458  * @return a gphoto2 error code
459  *
460  * This function is typically used prior first initialization
461  * using #gp_camera_init for debugging purposes. Normally, a camera driver
462  * will try to figure out the current speed of the camera and set the speed
463  * to the optimal one automatically. Note that this function only works with
464  * serial ports. In other words, you have to set the camera's port to a
465  * serial one (using #gp_camera_set_port_path or #gp_camera_set_port_name)
466  * prior calling this function.
467  *
468  */
469 int
470 gp_camera_set_port_speed (Camera *camera, int speed)
471 {
472         GPPortSettings settings;
473
474         CHECK_NULL (camera);
475
476         if (!camera->port) {
477                 gp_log (GP_LOG_ERROR, "camera", "You need to set "
478                         "a port prior trying to set the speed");
479                 return (GP_ERROR_BAD_PARAMETERS);
480         }
481
482         if (camera->port->type != GP_PORT_SERIAL) {
483                 gp_log (GP_LOG_ERROR, "camera", "You can specify "
484                         "a speed only with serial ports");
485                 return (GP_ERROR_BAD_PARAMETERS);
486         }
487
488         /*
489          * If the camera is currently initialized, terminate that connection.
490          * We don't care if we are successful or not.
491          */
492         if (camera->pc->lh)
493                 gp_camera_exit (camera, NULL);
494
495         CR (camera, gp_port_get_settings (camera->port, &settings), NULL);
496         settings.serial.speed = speed;
497         CR (camera, gp_port_set_settings (camera->port, settings), NULL);
498         camera->pc->speed = speed;
499
500         return (GP_OK);
501 }
502
503
504 /**
505  * Retrieve the current speed.
506  *
507  * @param camera a #Camera
508  * @return The current speed or a gphoto2 error code
509  *
510  */
511 int
512 gp_camera_get_port_speed (Camera *camera)
513 {
514         CHECK_NULL (camera);
515
516         return (camera->pc->speed);
517 }
518
519
520 /**
521  * Increment the reference count of a \c camera.
522  *
523  * @param camera a #Camera
524  * @return a gphoto2 error code
525  *
526  */
527 int
528 gp_camera_ref (Camera *camera)
529 {
530         CHECK_NULL (camera);
531
532         camera->pc->ref_count += 1;
533
534         return (GP_OK);
535 }
536
537
538 /**
539  * Decrements the reference count of a #Camera.
540  *
541  * @param camera a #Camera
542  * @return a gphoto2 error code
543  *
544  * If the reference count reaches %0, the \c camera will be freed
545  * automatically.
546  *
547  */
548 int
549 gp_camera_unref (Camera *camera)
550 {
551         CHECK_NULL (camera);
552
553         if (!camera->pc->ref_count) {
554                 gp_log (GP_LOG_ERROR, "gphoto2-camera", "gp_camera_unref on "
555                         "a camera with ref_count == 0 should not happen "
556                         "at all");
557                 return (GP_ERROR);
558         }
559
560         camera->pc->ref_count -= 1;
561
562         if (!camera->pc->ref_count) {
563
564                 /* We cannot free a camera that is currently in use */
565                 if (!camera->pc->used)
566                         gp_camera_free (camera);
567         }
568
569         return (GP_OK);
570 }
571
572
573 /**
574  * Free the \c camera.
575  *
576  * @param camera a #Camera
577  * @return a gphoto2 error code
578  *
579  * \deprecated
580  * This function should never be used. Please use #gp_camera_unref instead.
581  *
582  */
583 int
584 gp_camera_free (Camera *camera)
585 {
586         CHECK_NULL (camera);
587
588         gp_log (GP_LOG_DEBUG, "gp-camera", "Freeing camera...");
589
590         /*
591          * If the camera is currently initialized, close the connection.
592          * We don't care if we are successful or not.
593          */
594         if (camera->port && camera->pc && camera->pc->lh)
595                 gp_camera_exit (camera, NULL);
596
597         /* We don't care if anything goes wrong */
598         if (camera->port) {
599                 gp_port_free (camera->port);
600                 camera->port = NULL;
601         }
602
603         if (camera->pc) {
604                 if (camera->pc->timeout_ids)
605                         free (camera->pc->timeout_ids);
606                 free (camera->pc);
607                 camera->pc = NULL;
608         }
609
610         if (camera->fs) {
611                 gp_filesystem_free (camera->fs);
612                 camera->fs = NULL;
613         }
614
615         if (camera->functions) {
616                 free (camera->functions);
617                 camera->functions = NULL;
618         }
619
620         free (camera);
621
622         return (GP_OK);
623 }
624
625
626 /**
627  * Initiate a connection to the \c camera.
628  *
629  * @param camera a #Camera
630  * @param context a #GPContext
631  * @return a gphoto2 error code
632  *
633  * Before calling this function, the
634  * \c camera should be set up using #gp_camera_set_port_path or
635  * #gp_camera_set_port_name and #gp_camera_set_abilities. If that has been
636  * omitted, gphoto2 tries to autodetect any cameras and chooses the first one
637  * if any cameras are found. It is generally a good idea to call
638  * #gp_camera_exit after transactions have been completed in order to give
639  * other applications the chance to access the camera, too.
640  *
641  */
642 int
643 gp_camera_init (Camera *camera, GPContext *context)
644 {
645         CameraAbilities a;
646         const char *model, *port;
647         CameraLibraryInitFunc init_func;
648         int result;
649
650         gp_log (GP_LOG_DEBUG, "gphoto2-camera", "Initializing camera...");
651
652         CHECK_NULL (camera);
653         /*
654          * Reset the exit_requested flag. If this flag is set,
655          * gp_camera_exit will be called as soon as the camera is no
656          * longer in use (used flag).
657          */
658         camera->pc->exit_requested = 0;
659
660         /*
661          * If the model hasn't been indicated, try to
662          * figure it out (USB only). Beware of "Directory Browse".
663          */
664         if (strcasecmp (camera->pc->a.model, "Directory Browse") &&
665             !strcmp ("", camera->pc->a.model)) {
666                 CameraAbilitiesList *al;
667                 GPPortInfo      pinfo;
668                 GPPortInfoList  *il;
669                 int             m, p;
670                 GPPortInfo      info;
671                 CameraList      *list;
672
673                 result = gp_list_new (&list);
674                 if (result < GP_OK)
675                         return result;
676
677                 result = gp_port_get_info (camera->port, &pinfo);
678                 if (result < GP_OK)
679                         return result;
680
681                 gp_log (GP_LOG_DEBUG, "gphoto2-camera", "pinfo.type %d", pinfo.type);
682                 gp_log (GP_LOG_DEBUG, "gphoto2-camera", "pinfo.path %s", pinfo.path);
683                 gp_log (GP_LOG_DEBUG, "gphoto2-camera", "pinfo.name %s", pinfo.name);
684                 gp_log (GP_LOG_DEBUG, "gphoto2-camera", "Neither "
685                         "port nor model set. Trying auto-detection...");
686
687                 /* Call auto-detect and choose the first camera */
688                 gp_abilities_list_new (&al);
689                 gp_abilities_list_load (al, context);
690                 gp_port_info_list_new (&il);
691                 gp_port_info_list_load (il);
692                 gp_abilities_list_detect (al, il, list, context);
693                 if (!gp_list_count (list)) {
694                         gp_abilities_list_free (al);
695                         gp_port_info_list_free (il);
696                         gp_context_error (context, _("Could not detect any camera"));
697                         gp_list_free (list);
698                         return (GP_ERROR_MODEL_NOT_FOUND);
699                 }
700                 p = 0;
701                 /* if the port was set before, then use that entry. but not if it is "usb:" */
702                 if (    (pinfo.type == GP_PORT_USB) &&
703                         strlen(pinfo.path) &&
704                         strcmp(pinfo.path,"usb:")
705                 ) {
706                         for (p = gp_list_count (list);p--;) {
707                                 const char *xp;
708
709                                 gp_list_get_value (list, p, &xp);
710                                 if (!strcmp (xp, pinfo.path))
711                                         break;
712                         }
713                         if (p<0) {
714                                 gp_context_error (context, _("Could not detect any camera at port %s"), pinfo.path);
715                                 return (GP_ERROR_FILE_NOT_FOUND);
716                         }
717                 }
718
719                 gp_list_get_name  (list, p, &model);
720                 m = gp_abilities_list_lookup_model (al, model);
721                 gp_abilities_list_get_abilities (al, m, &a);
722                 gp_abilities_list_free (al);
723                 CRSL (camera, gp_camera_set_abilities (camera, a), context, list);
724                 CRSL (camera, gp_list_get_value (list, p, &port), context, list);
725                 p = gp_port_info_list_lookup_path (il, port);
726                 gp_port_info_list_get_info (il, p, &info);
727                 gp_port_info_list_free (il);
728                 CRSL (camera, gp_camera_set_port_info (camera, info), context, list);
729                 gp_list_free (list);
730         }
731
732         if (strcasecmp (camera->pc->a.model, "Directory Browse")) {
733                 switch (camera->port->type) {
734                 case GP_PORT_NONE:
735                         gp_context_error (context, _("You have to set the "
736                                 "port prior to initialization of the camera."));
737                         return (GP_ERROR_UNKNOWN_PORT);
738                 case GP_PORT_USB:
739                         if (gp_port_usb_find_device (camera->port,
740                                         camera->pc->a.usb_vendor,
741                                         camera->pc->a.usb_product) != GP_OK) {
742                                 CRS (camera, gp_port_usb_find_device_by_class
743                                         (camera->port,
744                                         camera->pc->a.usb_class,
745                                         camera->pc->a.usb_subclass,
746                                         camera->pc->a.usb_protocol), context);
747                                         }
748                         break;
749                 default:
750                         break;
751                 }
752         }
753
754         /* Load the library. */
755         gp_log (GP_LOG_DEBUG, "gphoto2-camera", "Loading '%s'...",
756                 camera->pc->a.library);
757         lt_dlinit ();
758         camera->pc->lh = lt_dlopenext (camera->pc->a.library);
759         if (!camera->pc->lh) {
760                 gp_context_error (context, _("Could not load required "
761                         "camera driver '%s' (%s)."), camera->pc->a.library,
762                         lt_dlerror ());
763                 lt_dlexit ();
764                 return (GP_ERROR_LIBRARY);
765         }
766
767         /* Initialize the camera */
768         init_func = lt_dlsym (camera->pc->lh, "camera_init");
769         if (!init_func) {
770                 lt_dlclose (camera->pc->lh);
771                 lt_dlexit ();
772                 camera->pc->lh = NULL;
773                 gp_context_error (context, _("Camera driver '%s' is "
774                         "missing the 'camera_init' function."),
775                         camera->pc->a.library);
776                 return (GP_ERROR_LIBRARY);
777         }
778
779         if (strcasecmp (camera->pc->a.model, "Directory Browse")) {
780                 result = gp_port_open (camera->port);
781                 if (result < 0) {
782                         lt_dlclose (camera->pc->lh);
783                         lt_dlexit ();
784                         camera->pc->lh = NULL;
785                         return (result);
786                 }
787         }
788
789         result = init_func (camera, context);
790         if (result < 0) {
791                 gp_port_close (camera->port);
792                 lt_dlclose (camera->pc->lh);
793                 lt_dlexit ();
794                 camera->pc->lh = NULL;
795                 memset (camera->functions, 0, sizeof (CameraFunctions));
796                 return (result);
797         }
798
799         /* We don't care if that goes wrong */
800 #ifdef HAVE_MULTI
801         gp_port_close (camera->port);
802 #endif
803
804         return (GP_OK);
805 }
806
807
808 /**
809  * Retrieve a configuration \c window for the \c camera.
810  *
811  * @param camera a #Camera
812  * @param window a #CameraWidget
813  * @param context a #GPContext
814  * @return gphoto2 error code
815  *
816  * This \c window can be used for construction of a configuration dialog.
817  *
818  */
819 int
820 gp_camera_get_config (Camera *camera, CameraWidget **window, GPContext *context)
821 {
822         CHECK_NULL (camera);
823         CHECK_INIT (camera, context);
824
825         if (!camera->functions->get_config) {
826                 gp_context_error (context, _("This camera does "
827                         "not offer any configuration options."));
828                 CAMERA_UNUSED (camera, context);
829                 return (GP_ERROR_NOT_SUPPORTED);
830         }
831
832         CHECK_RESULT_OPEN_CLOSE (camera, camera->functions->get_config (
833                                         camera, window, context), context);
834
835         CAMERA_UNUSED (camera, context);
836         return (GP_OK);
837 }
838
839
840 /**
841  * Sets the configuration.
842  *
843  * @param camera a #Camera
844  * @param window a #CameraWidget
845  * @param context a #GPContext
846  * @return a gphoto2 error code
847  *
848  * Typically, a \c window is retrieved using #gp_camera_get_config and passed
849  * to this function in order to adjust the settings on the camera.
850  *
851  **/
852 int
853 gp_camera_set_config (Camera *camera, CameraWidget *window, GPContext *context)
854 {
855         CHECK_NULL (camera && window);
856         CHECK_INIT (camera, context);
857
858         if (!camera->functions->set_config) {
859                 gp_context_error (context, _("This camera does "
860                         "not support setting configuration options."));
861                 CAMERA_UNUSED (camera, context);
862                 return (GP_ERROR_NOT_SUPPORTED);
863         }
864
865         CHECK_RESULT_OPEN_CLOSE (camera, camera->functions->set_config (camera,
866                                                 window, context), context);
867
868         CAMERA_UNUSED (camera, context);
869         return (GP_OK);
870 }
871
872 /**
873  * Retrieves a camera summary.
874  *
875  * @param camera a #Camera
876  * @param summary a #CameraText
877  * @param context a #GPContext
878  * @return a gphoto2 error code
879  *
880  * This summary typically contains information like manufacturer, pictures
881  * taken, or generally information that is not configurable.
882  *
883  **/
884 int
885 gp_camera_get_summary (Camera *camera, CameraText *summary, GPContext *context)
886 {
887         CHECK_NULL (camera && summary);
888         CHECK_INIT (camera, context);
889
890         if (!camera->functions->summary) {
891                 gp_context_error (context, _("This camera does "
892                                   "not support summaries."));
893                 CAMERA_UNUSED (camera, context);
894                 return (GP_ERROR_NOT_SUPPORTED);
895         }
896
897         CHECK_RESULT_OPEN_CLOSE (camera, camera->functions->summary (camera,
898                                                 summary, context), context);
899
900         CAMERA_UNUSED (camera, context);
901         return (GP_OK);
902 }
903
904 /**
905  * Retrieves the \c manual for given \c camera.
906  *
907  * @param camera a #Camera
908  * @param manual a #CameraText
909  * @param context a #GPContext
910  * @return a gphoto2 error code
911  *
912  * This manual typically contains information about using the camera.
913  *
914  **/
915 int
916 gp_camera_get_manual (Camera *camera, CameraText *manual, GPContext *context)
917 {
918         CHECK_NULL (camera && manual);
919         CHECK_INIT (camera, context);
920
921         if (!camera->functions->manual) {
922                 gp_context_error (context, _("This camera "
923                         "does not offer a manual."));
924                 CAMERA_UNUSED (camera, context);
925                 return (GP_ERROR_NOT_SUPPORTED);
926         }
927
928         CHECK_RESULT_OPEN_CLOSE (camera, camera->functions->manual (camera,
929                                                 manual, context), context);
930
931         CAMERA_UNUSED (camera, context);
932         return (GP_OK);
933 }
934
935 /**
936  * Retrieves information about the camera driver.
937  *
938  * @param camera a #Camera
939  * @param about a #CameraText
940  * @param context a #GPContext
941  * @return a gphoto2 error code
942  *
943  * Typically, this information contains name and address of the author,
944  * acknowledgements, etc.
945  *
946  **/
947 int
948 gp_camera_get_about (Camera *camera, CameraText *about, GPContext *context)
949 {
950         CHECK_NULL (camera && about);
951         CHECK_INIT (camera, context);
952
953         if (!camera->functions->about) {
954                 gp_context_error (context, _("This camera does "
955                         "not provide information about the driver."));
956                 CAMERA_UNUSED (camera, context);
957                 return (GP_ERROR_NOT_SUPPORTED);
958         }
959
960         CHECK_RESULT_OPEN_CLOSE (camera, camera->functions->about (camera,
961                                                 about, context), context);
962
963         CAMERA_UNUSED (camera, context);
964         return (GP_OK);
965 }
966
967 /**
968  * Captures an image, movie, or sound clip depending on the given \c type.
969  *
970  * @param camera a #Camera
971  * @param type a #CameraCaptureType
972  * @param path a #CameraFilePath
973  * @param context a #GPContext
974  * @return a gphoto2 error code
975  *
976  * The resulting file will be stored on the camera. The location gets stored
977  * in \c path. The file can then be downloaded using #gp_camera_file_get.
978  *
979  **/
980 int
981 gp_camera_capture (Camera *camera, CameraCaptureType type,
982                    CameraFilePath *path, GPContext *context)
983 {
984         CHECK_NULL (camera);
985         CHECK_INIT (camera, context);
986
987         if (!camera->functions->capture) {
988                 gp_context_error (context, _("This camera can not capture."));
989                 CAMERA_UNUSED (camera, context);
990                 return (GP_ERROR_NOT_SUPPORTED);
991         }
992
993         CHECK_RESULT_OPEN_CLOSE (camera, camera->functions->capture (camera,
994                                                 type, path, context), context);
995
996         CAMERA_UNUSED (camera, context);
997         return (GP_OK);
998 }
999
1000 /**
1001  * Captures a preview that won't be stored on the camera but returned in
1002  * supplied file.
1003  *
1004  * @param camera a #Camera
1005  * @param file a #CameraFile
1006  * @param context a #GPContext
1007  * @return a gphoto2 error code
1008  *
1009  * For example, you could use #gp_capture_preview for taking some sample
1010  * pictures before calling #gp_capture.
1011  *
1012  **/
1013 int
1014 gp_camera_capture_preview (Camera *camera, CameraFile *file, GPContext *context)
1015 {
1016         CHECK_NULL (camera && file);
1017         CHECK_INIT (camera, context);
1018
1019         CR (camera, gp_file_clean (file), context);
1020
1021         if (!camera->functions->capture_preview) {
1022                 gp_context_error (context, _("This camera can "
1023                         "not capture previews."));
1024                 CAMERA_UNUSED (camera, context);
1025                 return (GP_ERROR_NOT_SUPPORTED);
1026         }
1027
1028         CHECK_RESULT_OPEN_CLOSE (camera, camera->functions->capture_preview (
1029                                         camera, file, context), context);
1030
1031         CAMERA_UNUSED (camera, context);
1032         return (GP_OK);
1033 }
1034
1035
1036 /**
1037  * Wait for an event from the camera.
1038  *
1039  * @param camera a Camera
1040  * @param timeout amount of time to wait in 1/1000 seconds
1041  * @param eventtype received CameraEventType [out]
1042  * @param eventdata received event specific data [out]
1043  * @param context a GPContext
1044  * @return gphoto2 error code
1045  *
1046  * This function blocks and waits for an event to come from the camera.  If
1047  * timeout occurs before an event is received then
1048  * *eventtype==GP_EVENT_TIMEOUT and eventdata is left unchanged.
1049  * If an event is received then eventtype is set to the type of event, and
1050  * eventdata is set to event specific data.  See the CameraEventType enum
1051  * to see which eventtype's match to which types of eventdata.
1052  *
1053  */
1054 int
1055 gp_camera_wait_for_event (Camera *camera, int timeout,
1056                           CameraEventType *eventtype, void **eventdata,
1057                           GPContext *context)
1058 {
1059         CHECK_NULL (camera);
1060         CHECK_INIT (camera, context);
1061
1062         if (!camera->functions->wait_for_event) {
1063                 CAMERA_UNUSED (camera, context);
1064                 return (GP_ERROR_NOT_SUPPORTED);
1065         }
1066         CHECK_RESULT_OPEN_CLOSE (camera, camera->functions->wait_for_event (
1067                                         camera, timeout, eventtype, eventdata,
1068                                         context), context);
1069         CAMERA_UNUSED (camera, context);
1070         return (GP_OK);
1071 }
1072
1073 /**
1074  * Lists the files in supplied \c folder.
1075  *
1076  * @param camera a #Camera
1077  * @param folder a folder
1078  * @param list a #CameraList
1079  * @param context a #GPContext
1080  * @return a gphoto2 error code
1081  *
1082  **/
1083 int
1084 gp_camera_folder_list_files (Camera *camera, const char *folder,
1085                              CameraList *list, GPContext *context)
1086 {
1087         gp_log (GP_LOG_DEBUG, "gphoto2-camera", "Listing files in '%s'...",
1088                 folder);
1089
1090         CHECK_NULL (camera && folder && list);
1091         CHECK_INIT (camera, context);
1092         CR (camera, gp_list_reset (list), context);
1093
1094         CHECK_RESULT_OPEN_CLOSE (camera, gp_filesystem_list_files (camera->fs,
1095                                         folder, list, context), context);
1096
1097         CR (camera, gp_list_sort (list), context);
1098         CAMERA_UNUSED (camera, context);
1099         return (GP_OK);
1100 }
1101
1102 /**
1103  * Lists the folders in supplied \c folder.
1104  *
1105  * @param camera a #Camera
1106  * @param folder a folder
1107  * @param list a #CameraList
1108  * @param context a #GPContext
1109  * @return a gphoto2 error code
1110  *
1111  **/
1112 int
1113 gp_camera_folder_list_folders (Camera *camera, const char* folder,
1114                                CameraList *list, GPContext *context)
1115 {
1116         gp_log (GP_LOG_DEBUG, "gphoto2-camera", "Listing folders in '%s'...",
1117                 folder);
1118
1119         CHECK_NULL (camera && folder && list);
1120         CHECK_INIT (camera, context);
1121         CR (camera, gp_list_reset (list), context);
1122
1123         CHECK_RESULT_OPEN_CLOSE (camera, gp_filesystem_list_folders (
1124                                 camera->fs, folder, list, context), context);
1125
1126         CR (camera, gp_list_sort (list), context);
1127         CAMERA_UNUSED (camera, context);
1128         return (GP_OK);
1129 }
1130
1131 /**
1132  * Deletes all files in a given \c folder.
1133  *
1134  * @param camera a #Camera
1135  * @param folder a folder
1136  * @param context a #GPContext
1137  * @return a gphoto2 error code
1138  *
1139  **/
1140 int
1141 gp_camera_folder_delete_all (Camera *camera, const char *folder,
1142                              GPContext *context)
1143 {
1144         gp_log (GP_LOG_DEBUG, "gphoto2-camera", "Deleting all files in "
1145                 "'%s'...", folder);
1146
1147         CHECK_NULL (camera && folder);
1148         CHECK_INIT (camera, context);
1149
1150         CHECK_RESULT_OPEN_CLOSE (camera, gp_filesystem_delete_all (camera->fs,
1151                                                 folder, context), context);
1152
1153         CAMERA_UNUSED (camera, context);
1154         return (GP_OK);
1155 }
1156
1157 /**
1158  * Uploads a file into given \c folder.
1159  *
1160  * @param camera a #Camera
1161  * @param folder a folder
1162  * @param file a #CameraFile
1163  * @param context a #GPContext
1164  * @return a gphoto2 error code
1165  *
1166  **/
1167 int
1168 gp_camera_folder_put_file (Camera *camera, const char *folder,
1169                            CameraFile *file, GPContext *context)
1170 {
1171         gp_log (GP_LOG_DEBUG, "gphoto2-camera", "Uploading file into '%s'...",
1172                 folder);
1173
1174         CHECK_NULL (camera && folder && file);
1175         CHECK_INIT (camera, context);
1176
1177         CHECK_RESULT_OPEN_CLOSE (camera, gp_filesystem_put_file (camera->fs,
1178                                         folder, file, context), context);
1179
1180         CAMERA_UNUSED (camera, context);
1181         return (GP_OK);
1182 }
1183
1184 /**
1185  * Retrieves information about a file.
1186  *
1187  * @param camera a #Camera
1188  * @param folder a folder
1189  * @param file the name of the file
1190  * @param info
1191  * @param context a #GPContext
1192  * @return a gphoto2 error code
1193  *
1194  **/
1195 int
1196 gp_camera_file_get_info (Camera *camera, const char *folder,
1197                          const char *file, CameraFileInfo *info,
1198                          GPContext *context)
1199 {
1200         int result = GP_OK;
1201         const char *mime_type;
1202         const char *data;
1203         /* long int size; */
1204         CameraFile *cfile;
1205
1206         gp_log (GP_LOG_DEBUG, "gphoto2-camera", "Getting file info for '%s' "
1207                 "in '%s'...", file, folder);
1208
1209         CHECK_NULL (camera && folder && file && info);
1210         CHECK_INIT (camera, context);
1211
1212         memset (info, 0, sizeof (CameraFileInfo));
1213
1214         /* Check first if the camera driver supports the filesystem */
1215         CHECK_OPEN (camera, context);
1216         result = gp_filesystem_get_info (camera->fs, folder, file, info,
1217                                          context);
1218         CHECK_CLOSE (camera, context);
1219         if (result != GP_ERROR_NOT_SUPPORTED) {
1220                 CAMERA_UNUSED (camera, context);
1221                 return (result);
1222         }
1223
1224         /*
1225          * The CameraFilesystem doesn't support file info. We simply get
1226          * the preview and the file and look for ourselves...
1227          */
1228
1229         /* It takes too long to get the file */
1230         info->file.fields = GP_FILE_INFO_NONE;
1231
1232         /* Get the preview */
1233         info->preview.fields = GP_FILE_INFO_NONE;
1234         CRS (camera, gp_file_new (&cfile), context);
1235         if (gp_camera_file_get (camera, folder, file, GP_FILE_TYPE_PREVIEW,
1236                                                 cfile, context) == GP_OK) {
1237                 unsigned long size;
1238                 info->preview.fields |= GP_FILE_INFO_SIZE | GP_FILE_INFO_TYPE;
1239                 gp_file_get_data_and_size (cfile, &data, &size);
1240                 info->preview.size = size;
1241                 gp_file_get_mime_type (cfile, &mime_type);
1242                 strncpy (info->preview.type, mime_type,
1243                          sizeof (info->preview.type));
1244         }
1245         gp_file_unref (cfile);
1246
1247         /* We don't trust the camera libraries */
1248         info->file.fields |= GP_FILE_INFO_NAME;
1249         strncpy (info->file.name, file, sizeof (info->file.name));
1250         info->preview.fields &= ~GP_FILE_INFO_NAME;
1251
1252         CAMERA_UNUSED (camera, context);
1253         return (GP_OK);
1254 }
1255
1256 /**
1257  * Sets some file properties like name or permissions.
1258  *
1259  * @param camera a #Camera
1260  * @param folder a folder
1261  * @param file the name of a file
1262  * @param info the #CameraFileInfo
1263  * @param context a #GPContext
1264  * @return a gphoto2 error code
1265  *
1266  **/
1267 int
1268 gp_camera_file_set_info (Camera *camera, const char *folder,
1269                          const char *file, CameraFileInfo info,
1270                          GPContext *context)
1271 {
1272         CHECK_NULL (camera && folder && file);
1273         CHECK_INIT (camera, context);
1274
1275         CHECK_RESULT_OPEN_CLOSE (camera, gp_filesystem_set_info (camera->fs,
1276                                         folder, file, info, context), context);
1277
1278         CAMERA_UNUSED (camera, context);
1279         return (GP_OK);
1280 }
1281
1282 /**
1283  * Retrieves a file from the #Camera.
1284  *
1285  * @param camera a #Camera
1286  * @param folder a folder
1287  * @param file the name of a file
1288  * @param type the #CameraFileType
1289  * @param camera_file a #CameraFile
1290  * @param context a #GPContext
1291  * @return a gphoto2 error code
1292  *
1293  **/
1294 int
1295 gp_camera_file_get (Camera *camera, const char *folder, const char *file,
1296                     CameraFileType type, CameraFile *camera_file,
1297                     GPContext *context)
1298 {
1299         gp_log (GP_LOG_DEBUG, "gphoto2-camera", "Getting file '%s' in "
1300                 "folder '%s'...", file, folder);
1301
1302         CHECK_NULL (camera && folder && file && camera_file);
1303         CHECK_INIT (camera, context);
1304
1305         CR (camera, gp_file_clean (camera_file), context);
1306
1307         /* Did we get reasonable foldername/filename? */
1308         if (strlen (folder) == 0) {
1309                 CAMERA_UNUSED (camera, context);
1310                 return (GP_ERROR_DIRECTORY_NOT_FOUND);
1311         }
1312         if (strlen (file) == 0) {
1313                 CAMERA_UNUSED (camera, context);
1314                 return (GP_ERROR_FILE_NOT_FOUND);
1315         }
1316
1317         CHECK_RESULT_OPEN_CLOSE (camera, gp_filesystem_get_file (camera->fs,
1318                         folder, file, type, camera_file, context), context);
1319
1320         CAMERA_UNUSED (camera, context);
1321         return (GP_OK);
1322 }
1323
1324 /**
1325  * Deletes the file from \c folder.
1326  *
1327  * \param camera a #Camera
1328  * \param folder a folder
1329  * \param file the name of a file
1330  * \param context a #GPContext
1331  * \return a gphoto2 error code
1332  *
1333  **/
1334 int
1335 gp_camera_file_delete (Camera *camera, const char *folder, const char *file,
1336                        GPContext *context)
1337 {
1338         gp_log (GP_LOG_DEBUG, "gphoto2-camera", "Deleting file '%s' in "
1339                 "folder '%s'...", file, folder);
1340
1341         CHECK_NULL (camera && folder && file);
1342         CHECK_INIT (camera, context);
1343
1344         CHECK_RESULT_OPEN_CLOSE (camera, gp_filesystem_delete_file (
1345                                 camera->fs, folder, file, context), context);
1346
1347         CAMERA_UNUSED (camera, context);
1348         return (GP_OK);
1349 }
1350
1351 /**
1352  * Creates a new directory called \c name in the given \c folder.
1353  *
1354  * @param camera a #Camera
1355  * @param folder the location where to create the new directory
1356  * @param name the name of the directory to be created
1357  * @param context a #GPContext
1358  * @return a gphoto2 error code
1359  *
1360  **/
1361 int
1362 gp_camera_folder_make_dir (Camera *camera, const char *folder,
1363                            const char *name, GPContext *context)
1364 {
1365         CHECK_NULL (camera && folder && name);
1366         CHECK_INIT (camera, context);
1367
1368         CHECK_RESULT_OPEN_CLOSE (camera, gp_filesystem_make_dir (camera->fs,
1369                                         folder, name, context), context);
1370
1371         CAMERA_UNUSED (camera, context);
1372         return (GP_OK);
1373 }
1374
1375 /**
1376  * Removes an (empty) directory called \c name from the given \c folder.
1377  *
1378  * @param camera a #Camera
1379  * @param folder the folder from which to remove the directory
1380  * @param name the name of the directory to be removed
1381  * @param context a #GPContext
1382  * @return a gphoto2 error code
1383  *
1384  */
1385 int
1386 gp_camera_folder_remove_dir (Camera *camera, const char *folder,
1387                              const char *name, GPContext *context)
1388 {
1389         CHECK_NULL (camera && folder && name);
1390         CHECK_INIT (camera, context);
1391
1392         CHECK_RESULT_OPEN_CLOSE (camera, gp_filesystem_remove_dir (camera->fs,
1393                                         folder, name, context), context);
1394
1395         CAMERA_UNUSED (camera, context);
1396         return (GP_OK);
1397 }
1398
1399 /**
1400  * \brief Gets information on the camera attached storage.
1401  *
1402  * \param camera a #Camera
1403  * \param sifs Pointer to receive a pointer to/array of storage info items
1404  * \param nrofsifs Pointer to receive number of array entries
1405  * \param context a #GPContext
1406  * \return a gphoto2 error code
1407  *
1408  * Retrieves the storage information, like maximum and free space, for
1409  * the specified filesystem, if supported by the device. The storage
1410  * information is returned in an newly allocated array of
1411  * #CameraStorageInformation objects, to which the pointer pointed to
1412  * by #sifs will be set.
1413  *
1414  * The variable pointed to by #nrofsifs will be set to the number of
1415  * elements in that array.
1416  *
1417  * It is the caller's responsibility to free the memory of the array.
1418  *
1419  **/
1420 int
1421 gp_camera_get_storageinfo (
1422         Camera *camera, CameraStorageInformation **sifs,
1423         int *nrofsifs, GPContext *context)
1424 {
1425         CHECK_NULL (camera && sifs && nrofsifs);
1426         CHECK_INIT (camera, context);
1427
1428         CHECK_RESULT_OPEN_CLOSE (camera,
1429                 gp_filesystem_get_storageinfo (
1430                         camera->fs, sifs, nrofsifs, context
1431                 ),
1432                 context
1433         );
1434         CAMERA_UNUSED (camera, context);
1435         return (GP_OK);
1436 }
1437
1438 /**
1439  * @param camera a Camera
1440  * @param start_func
1441  * @param stop_func
1442  * @param data
1443  * @return a gphoto2 error code
1444  *
1445  * If your frontend has something like idle loops, it is recommended you
1446  * use #gp_camera_set_timeout_funcs in order to give the camera driver the
1447  * possibility to keep up the connection to the camera.
1448  *
1449  */
1450 void
1451 gp_camera_set_timeout_funcs (Camera *camera, CameraTimeoutStartFunc start_func,
1452                              CameraTimeoutStopFunc stop_func,
1453                              void *data)
1454 {
1455         if (!camera || !camera->pc)
1456                 return;
1457
1458         camera->pc->timeout_start_func = start_func;
1459         camera->pc->timeout_stop_func = stop_func;
1460         camera->pc->timeout_data = data;
1461 }
1462
1463
1464 /**
1465  * @param camera a #Camera
1466  * @param timeout number of seconds that should pass between each call to
1467  *           \c func
1468  * @param func the function that should be called each \c timeout seconds
1469  * @return The id of the background process or a gphoto2 error code
1470  *
1471  * This function should be called by the camera driver during camera_init()
1472  * if the camera needs to be sent messages periodically in order to prevent
1473  * it from shutting down.
1474  *
1475  */
1476 int
1477 gp_camera_start_timeout (Camera *camera, unsigned int timeout,
1478                          CameraTimeoutFunc func)
1479 {
1480         int id;
1481         unsigned int *ids;
1482
1483         if (!camera || !camera->pc)
1484                 return (GP_ERROR_BAD_PARAMETERS);
1485
1486         if (!camera->pc->timeout_start_func)
1487                 return (GP_ERROR_NOT_SUPPORTED);
1488
1489         /*
1490          * We remember the id here in order to automatically remove
1491          * the timeout on gp_camera_exit.
1492          */
1493         ids = realloc (camera->pc->timeout_ids, sizeof (int) *
1494                                         (camera->pc->timeout_ids_len + 1));
1495         if (!ids)
1496                 return (GP_ERROR_NO_MEMORY);
1497         camera->pc->timeout_ids = ids;
1498
1499         id = camera->pc->timeout_start_func (camera, timeout, func,
1500                                              camera->pc->timeout_data);
1501         if (id < 0)
1502                 return (id);
1503         camera->pc->timeout_ids[camera->pc->timeout_ids_len] = id;
1504         camera->pc->timeout_ids_len++;
1505
1506         return (id);
1507 }
1508
1509
1510 /**
1511  * Stop periodic calls to keepalive function.
1512  *
1513  * @param camera a #Camera
1514  * @param id the id of the background process previously returned by
1515  *       #gp_camera_start_timeout
1516  *
1517  * Call this function in the camera driver if you want to stop a periodic
1518  * call to a function that has been started using #gp_camera_start_timeout.
1519  *
1520  */
1521 void
1522 gp_camera_stop_timeout (Camera *camera, unsigned int id)
1523 {
1524         unsigned int i;
1525
1526         if (!camera || !camera->pc)
1527                 return;
1528
1529         if (!camera->pc->timeout_stop_func)
1530                 return;
1531
1532         /* Check if we know this id. If yes, remove it. */
1533         for (i = 0; i < camera->pc->timeout_ids_len; i++)
1534                 if (camera->pc->timeout_ids[i] == id)
1535                         break;
1536         if (i == camera->pc->timeout_ids_len)
1537                 return;
1538         memmove (camera->pc->timeout_ids + i, camera->pc->timeout_ids + i + 1,
1539                  sizeof (int) * (camera->pc->timeout_ids_len - i - 1));
1540         camera->pc->timeout_ids_len--;
1541         camera->pc->timeout_ids = realloc (camera->pc->timeout_ids,
1542                                 sizeof (int) * camera->pc->timeout_ids_len);
1543
1544         camera->pc->timeout_stop_func (camera, id, camera->pc->timeout_data);
1545 }