From f200da9c7915521f77c6c23e825181da73db474d Mon Sep 17 00:00:00 2001
From: Matthias Vogelgesang <matthias.vogelgesang@ipe.fzk.de>
Date: Mon, 28 Feb 2011 11:09:43 +0100
Subject: Add support for multiple cameras

---
 src/cameras/uca_pco.c | 72 +++++++++++++++++++++--------------------
 src/cameras/uca_pco.h |  4 +--
 src/uca.c             | 89 +++++++++++++++++++++++++++++----------------------
 src/uca.h             | 68 +++++++++++++++++++++------------------
 4 files changed, 126 insertions(+), 107 deletions(-)

(limited to 'src')

diff --git a/src/cameras/uca_pco.c b/src/cameras/uca_pco.c
index 33b09d6..8a89fa0 100644
--- a/src/cameras/uca_pco.c
+++ b/src/cameras/uca_pco.c
@@ -19,73 +19,73 @@ struct pco_cam_t {
 #define set_void(p, type, value) { *((type *) p) = value; }
 
 
-static uint32_t uca_pco_set_bitdepth(struct uca_t *uca, uint8_t *bitdepth)
+static uint32_t uca_pco_set_bitdepth(struct uca_camera_t *cam, uint8_t *bitdepth)
 {
     /* TODO: it's not possible via CameraLink so do it via frame grabber */
     return 0;
 }
 
-static uint32_t uca_pco_set_exposure(struct uca_t *uca, uint32_t *exposure)
+static uint32_t uca_pco_set_exposure(struct uca_camera_t *cam, uint32_t *exposure)
 {
     uint32_t e, d;
-    if (pco_get_delay_exposure(GET_PCO(uca), &d, &e) != PCO_NOERROR)
+    if (pco_get_delay_exposure(GET_PCO(cam), &d, &e) != PCO_NOERROR)
         return UCA_ERR_PROP_GENERAL;
-    if (pco_set_delay_exposure(GET_PCO(uca), d, *exposure) != PCO_NOERROR)
+    if (pco_set_delay_exposure(GET_PCO(cam), d, *exposure) != PCO_NOERROR)
         return UCA_ERR_PROP_GENERAL;
     return UCA_NO_ERROR;
 }
 
-static uint32_t uca_pco_set_delay(struct uca_t *uca, uint32_t *delay)
+static uint32_t uca_pco_set_delay(struct uca_camera_t *cam, uint32_t *delay)
 {
     uint32_t e, d;
-    if (pco_get_delay_exposure(GET_PCO(uca), &d, &e) != PCO_NOERROR)
+    if (pco_get_delay_exposure(GET_PCO(cam), &d, &e) != PCO_NOERROR)
         return UCA_ERR_PROP_GENERAL;
-    if (pco_set_delay_exposure(GET_PCO(uca), *delay, e) != PCO_NOERROR)
+    if (pco_set_delay_exposure(GET_PCO(cam), *delay, e) != PCO_NOERROR)
         return UCA_ERR_PROP_GENERAL;
     return UCA_NO_ERROR;
 }
 
-static uint32_t uca_pco_acquire_image(struct uca_t *uca, void *buffer)
+static uint32_t uca_pco_acquire_image(struct uca_camera_t *cam, void *buffer)
 {
     return UCA_NO_ERROR;
 }
 
-static uint32_t uca_pco_destroy(struct uca_t *uca)
+static uint32_t uca_pco_destroy(struct uca_camera_t *cam)
 {
-    Fg_FreeGrabber(GET_FG(uca));
-    pco_destroy(GET_PCO(uca));
-    free(uca->user);
+    Fg_FreeGrabber(GET_FG(cam));
+    pco_destroy(GET_PCO(cam));
+    free(cam->user);
     return UCA_NO_ERROR;
 }
 
-static uint32_t uca_pco_set_property(struct uca_t *uca, int32_t property, void *data)
+static uint32_t uca_pco_set_property(struct uca_camera_t *cam, int32_t property, void *data)
 {
     switch (property) {
         case UCA_PROP_WIDTH:
-            if (Fg_setParameter(GET_FG(uca), FG_WIDTH, (uint32_t *) data, PORT_A) != FG_OK)
+            if (Fg_setParameter(GET_FG(cam), FG_WIDTH, (uint32_t *) data, PORT_A) != FG_OK)
                 return UCA_ERR_PROP_VALUE_OUT_OF_RANGE;
             break;
 
         case UCA_PROP_HEIGHT:
-            if (Fg_setParameter(GET_FG(uca), FG_HEIGHT, (uint32_t *) data, PORT_A) != FG_OK)
+            if (Fg_setParameter(GET_FG(cam), FG_HEIGHT, (uint32_t *) data, PORT_A) != FG_OK)
                 return UCA_ERR_PROP_VALUE_OUT_OF_RANGE;
             break;
 
         case UCA_PROP_X_OFFSET:
-            if (Fg_setParameter(GET_FG(uca), FG_XOFFSET, (uint32_t *) data, PORT_A) != FG_OK)
+            if (Fg_setParameter(GET_FG(cam), FG_XOFFSET, (uint32_t *) data, PORT_A) != FG_OK)
                 return UCA_ERR_PROP_VALUE_OUT_OF_RANGE;
             break;
 
         case UCA_PROP_Y_OFFSET:
-            if (Fg_setParameter(GET_FG(uca), FG_YOFFSET, (uint32_t *) data, PORT_A) != FG_OK)
+            if (Fg_setParameter(GET_FG(cam), FG_YOFFSET, (uint32_t *) data, PORT_A) != FG_OK)
                 return UCA_ERR_PROP_VALUE_OUT_OF_RANGE;
             break;
 
         case UCA_PROP_EXPOSURE:
-            return uca_pco_set_exposure(uca, (uint32_t *) data);
+            return uca_pco_set_exposure(cam, (uint32_t *) data);
 
         case UCA_PROP_DELAY:
-            return uca_pco_set_delay(uca, (uint32_t *) data);
+            return uca_pco_set_delay(cam, (uint32_t *) data);
 
         default:
             return UCA_ERR_PROP_INVALID;
@@ -94,9 +94,9 @@ static uint32_t uca_pco_set_property(struct uca_t *uca, int32_t property, void *
 }
 
 
-static uint32_t uca_pco_get_property(struct uca_t *uca, int32_t property, void *data)
+static uint32_t uca_pco_get_property(struct uca_camera_t *cam, int32_t property, void *data)
 {
-    struct pco_edge_t *pco = GET_PCO(uca);
+    struct pco_edge_t *pco = GET_PCO(cam);
 
     switch (property) {
         case UCA_PROP_NAME: 
@@ -141,12 +141,12 @@ static uint32_t uca_pco_get_property(struct uca_t *uca, int32_t property, void *
             break;
 
         case UCA_PROP_X_OFFSET:
-            if (Fg_getParameter(GET_FG(uca), FG_XOFFSET, (uint32_t *) data, PORT_A) != FG_OK)
+            if (Fg_getParameter(GET_FG(cam), FG_XOFFSET, (uint32_t *) data, PORT_A) != FG_OK)
                 return UCA_ERR_PROP_GENERAL;
             break;
 
         case UCA_PROP_Y_OFFSET:
-            if (Fg_getParameter(GET_FG(uca), FG_YOFFSET, (uint32_t *) data, PORT_A) != FG_OK)
+            if (Fg_getParameter(GET_FG(cam), FG_YOFFSET, (uint32_t *) data, PORT_A) != FG_OK)
                 return UCA_ERR_PROP_GENERAL;
             break;
 
@@ -176,37 +176,39 @@ static uint32_t uca_pco_get_property(struct uca_t *uca, int32_t property, void *
     return UCA_NO_ERROR;
 }
 
-uint32_t uca_pco_alloc(struct uca_t *uca, uint32_t n_buffers)
+uint32_t uca_pco_alloc(struct uca_camera_t *cam, uint32_t n_buffers)
 {
 
 }
 
-uint32_t uca_pco_init(struct uca_t *uca)
+uint32_t uca_pco_init(struct uca_camera_t **cam)
 {
-    uca->user = (struct pco_cam_t *) malloc(sizeof(struct pco_cam_t));
-
-    struct pco_cam_t *pco_cam = uca->user;
+    struct pco_cam_t *pco_cam = (struct pco_cam_t *) malloc(sizeof(struct pco_cam_t));
     struct pco_edge_t *pco = pco_cam->pco = pco_init();
 
     if (pco == NULL) {
-        free(uca->user);
+        free(pco_cam);
         return UCA_ERR_INIT_NOT_FOUND;
     }
 
     if ((pco->serial_ref == NULL) || !pco_active(pco)) {
-        free(uca->user);
+        free(pco_cam);
         pco_destroy(pco);
         return UCA_ERR_INIT_NOT_FOUND;
     }
 
     Fg_Struct *fg = pco_cam->fg = Fg_Init("libFullAreaGray8.so", 0);
 
+    struct uca_camera_t *uca = (struct uca_camera_t *) malloc(sizeof(struct uca_camera_t));
+    uca->user = pco_cam;
+    *cam = uca;
+
     /* Camera found, set function pointers... */
-    uca->cam_destroy = &uca_pco_destroy;
-    uca->cam_set_property = &uca_pco_set_property;
-    uca->cam_get_property = &uca_pco_get_property;
-    uca->cam_alloc = &uca_pco_alloc;
-    uca->cam_acquire_image = &uca_pco_acquire_image;
+    uca->destroy = &uca_pco_destroy;
+    uca->set_property = &uca_pco_set_property;
+    uca->get_property = &uca_pco_get_property;
+    uca->alloc = &uca_pco_alloc;
+    uca->acquire_image = &uca_pco_acquire_image;
 
     /* Prepare camera for recording */
     pco_set_rec_state(pco, 0);
diff --git a/src/cameras/uca_pco.h b/src/cameras/uca_pco.h
index 07c3ef2..240e675 100644
--- a/src/cameras/uca_pco.h
+++ b/src/cameras/uca_pco.h
@@ -1,8 +1,8 @@
 #ifndef __UNIFIED_CAMERA_ACCESS_PCO_H
 #define __UNIFIED_CAMERA_ACCESS_PCO_H
 
-struct uca_t;
+struct uca_camera_t;
 
-uint32_t uca_pco_init(struct uca_t *uca);
+uint32_t uca_pco_init(struct uca_camera_t **uca);
 
 #endif
diff --git a/src/uca.c b/src/uca.c
index 73dd79e..0e9e184 100644
--- a/src/uca.c
+++ b/src/uca.c
@@ -19,6 +19,7 @@
 struct uca_t *uca_init()
 {
     struct uca_t *uca = (struct uca_t *) malloc(sizeof(struct uca_t));
+    uca->cameras = NULL;
 
     uca_cam_init inits[] = {
 #ifdef HAVE_PCO_EDGE
@@ -32,58 +33,70 @@ struct uca_t *uca_init()
 #endif
     NULL };
 
-    /* Set all function pointers to NULL and thus make the class abstract */
-    uca->cam_set_property = NULL;
-    uca->cam_get_property = NULL;
-    uca->cam_alloc = NULL;
-    uca->cam_acquire_image = NULL;
-
     int i = 0;
+    struct uca_camera_t* current = NULL;
+
     while (inits[i] != NULL) {
+        struct uca_camera_t *cam = NULL;
         uca_cam_init init = inits[i];
-        if (init(uca) != UCA_ERR_INIT_NOT_FOUND)
-            return uca;
+        if (init(&cam) != UCA_ERR_INIT_NOT_FOUND) {
+            if (current == NULL) 
+                uca->cameras = current = cam;
+            else {
+                current->next = cam;
+                current = cam;
+            }
+            current->next = NULL;
+        }
         i++;
     }
 
-    /* No camera found then indicate error */
-    free(uca);
-    return NULL;
+    if (uca->cameras == NULL) {
+        free(uca);
+        return NULL;
+    }
+    return uca;
 }
 
 void uca_destroy(struct uca_t *uca)
 {
     if (uca != NULL) {
-        uca->cam_destroy(uca);
+        struct uca_camera_t *current = uca->cameras, *tmp;
+        while (current != NULL) {
+            tmp = current;
+            current->destroy(current);
+            current = current->next;
+            free(tmp);
+        }
         free(uca);
     }
 }
 
-static struct uca_property_t property_map[UCA_PROP_LAST] = {
-    { "name",       uca_na,    uca_string }, 
-    { "width",      uca_pixel, uca_uint32t }, 
-    { "width.min",  uca_pixel, uca_uint32t }, 
-    { "width.max",  uca_pixel, uca_uint32t }, 
-    { "height",     uca_pixel, uca_uint32t }, 
-    { "height.min", uca_pixel, uca_uint32t }, 
-    { "height.max", uca_pixel, uca_uint32t }, 
-    { "offset.x",   uca_pixel, uca_uint32t }, 
-    { "offset.y",   uca_pixel, uca_uint32t }, 
-    { "bit-depth",  uca_pixel, uca_uint8t }, 
-    { "exposure",   uca_us,    uca_uint32t }, 
-    { "exposure.min", uca_ns, uca_uint32t }, 
-    { "exposure.max", uca_ms, uca_uint32t }, 
-    { "delay",      uca_us, uca_uint32t }, 
-    { "delay.min",  uca_ns, uca_uint32t }, 
-    { "delay.max",  uca_ms, uca_uint32t }, 
-    { "frame-rate", uca_na, uca_uint32t }, 
-    { "trigger-mode", uca_na, uca_uint32t }, 
-    { "timestamp-mode", uca_na, uca_uint32t }, 
-    { "scan-mode",  uca_na, uca_uint32t }, 
-    { "interlace.sample-rate", uca_na, uca_uint32t }, 
+static struct uca_property_t property_map[UCA_PROP_LAST+1] = {
+    { "name",           uca_na,     uca_string }, 
+    { "width",          uca_pixel,  uca_uint32t }, 
+    { "width.min",      uca_pixel,  uca_uint32t }, 
+    { "width.max",      uca_pixel,  uca_uint32t }, 
+    { "height",         uca_pixel,  uca_uint32t }, 
+    { "height.min",     uca_pixel,  uca_uint32t }, 
+    { "height.max",     uca_pixel,  uca_uint32t }, 
+    { "offset.x",       uca_pixel,  uca_uint32t }, 
+    { "offset.y",       uca_pixel,  uca_uint32t }, 
+    { "bitdepth",       uca_bits,   uca_uint8t }, 
+    { "exposure",       uca_us,     uca_uint32t }, 
+    { "exposure.min",   uca_ns,     uca_uint32t }, 
+    { "exposure.max",   uca_ms,     uca_uint32t }, 
+    { "delay",          uca_us,     uca_uint32t }, 
+    { "delay.min",      uca_ns,     uca_uint32t }, 
+    { "delay.max",      uca_ms,     uca_uint32t }, 
+    { "framerate",      uca_na,     uca_uint32t }, 
+    { "triggermode",    uca_na,     uca_uint32t }, 
+    { "timestampmode",  uca_na,     uca_uint32t }, 
+    { "scan-mode",      uca_na,     uca_uint32t }, 
+    { "interlace.samplerate", uca_na, uca_uint32t }, 
     { "interlace.threshold.pixel", uca_na, uca_uint32t }, 
     { "interlace.threshold.row", uca_na, uca_uint32t }, 
-    { "correction-mode", uca_na, uca_uint32t }, 
+    { "correctionmode", uca_na, uca_uint32t }, 
     { NULL, 0, 0 }
 };
 
@@ -96,7 +109,7 @@ int32_t uca_get_property_id(const char *property_name)
             return i;
         i++;
     }
-    return UCA_PROP_INVALID;
+    return UCA_ERR_PROP_INVALID;
 }
 
 struct uca_property_t *uca_get_full_property(int32_t property_id)
@@ -108,6 +121,6 @@ struct uca_property_t *uca_get_full_property(int32_t property_id)
 
 const char* uca_get_property_name(int32_t property_id)
 {
-    /* TODO: guard that thing */
-    return property_map[property_id].name;
+    if ((property_id >= 0) && (property_id < UCA_PROP_LAST))
+        return property_map[property_id].name;
 }
diff --git a/src/uca.h b/src/uca.h
index bf0cc21..c067d9f 100644
--- a/src/uca.h
+++ b/src/uca.h
@@ -14,18 +14,19 @@
 #include <stdint.h>
 
 struct uca_t;
+struct uca_camera_t;
 struct uca_property_t;
 
 /**
  * \brief Camera probing and initialization
  * \return UCA_ERR_INIT_NOT_FOUND if camera is not found or could not be initialized
  */
-typedef uint32_t (*uca_cam_init) (struct uca_t *uca);
+typedef uint32_t (*uca_cam_init) (struct uca_camera_t **cam);
 
 /**
  * \brief Free camera resouces
  */
-typedef uint32_t (*uca_cam_destroy) (struct uca_t *uca);
+typedef uint32_t (*uca_cam_destroy) (struct uca_camera_t *cam);
 
 /**
  * \brief Set a property
@@ -33,31 +34,31 @@ typedef uint32_t (*uca_cam_destroy) (struct uca_t *uca);
  * \return UCA_ERR_PROP_INVALID if property is not supported on the camera or
  * UCA_ERR_PROP_VALUE_OUT_OF_RANGE if value cannot be set.
  */
-typedef uint32_t (*uca_cam_set_property) (struct uca_t *uca, int32_t property, void *data);
+typedef uint32_t (*uca_cam_set_property) (struct uca_camera_t *cam, int32_t property, void *data);
 
 /**
  * \brief Set a property
  * \param[in] property_name Name of the property as defined in XXX
  * \return UCA_ERR_PROP_INVALID if property is not supported on the camera
  */
-typedef uint32_t (*uca_cam_get_property) (struct uca_t *uca, int32_t property, void *data);
+typedef uint32_t (*uca_cam_get_property) (struct uca_camera_t *cam, int32_t property, void *data);
 
 /** \brief Allocate number of buffers
  *
  * The size of each buffer is width x height x bits
  */
-typedef uint32_t (*uca_cam_alloc) (struct uca_t *uca, uint32_t n_buffers);
+typedef uint32_t (*uca_cam_alloc) (struct uca_camera_t *cam, uint32_t n_buffers);
 
 /**
  * \brief Acquire one frame
  */
-typedef uint32_t (*uca_cam_acquire_image) (struct uca_t *uca, void *buffer);
+typedef uint32_t (*uca_cam_acquire_image) (struct uca_camera_t *cam, void *buffer);
 
 /**
  * \brief Initialize the unified camera access interface
  * \return Pointer to a uca_t structure
  */
-struct uca_t *uca_init();
+struct uca_t *uca_init(void);
 
 /**
  * \brief Free resources of the unified camera access interface
@@ -85,7 +86,6 @@ struct uca_property_t *uca_get_full_property(int32_t property_id);
 
 /* The property IDs must start with 0 and must be continuous. Whenever this
  * library is released, the IDs must not change to guarantee binary compatibility! */
-#define UCA_PROP_INVALID        -1
 #define UCA_PROP_NAME           0
 #define UCA_PROP_WIDTH          1
 #define UCA_PROP_WIDTH_MIN      2
@@ -95,31 +95,29 @@ struct uca_property_t *uca_get_full_property(int32_t property_id);
 #define UCA_PROP_HEIGHT_MAX     6
 #define UCA_PROP_X_OFFSET       7
 #define UCA_PROP_Y_OFFSET       8
-#define UCA_PROP_MAX_WIDTH      9
-#define UCA_PROP_MAX_HEIGHT     10
-#define UCA_PROP_BITDEPTH       11
-#define UCA_PROP_EXPOSURE       12
-#define UCA_PROP_EXPOSURE_MIN   13
-#define UCA_PROP_EXPOSURE_MAX   14
-#define UCA_PROP_DELAY          15
-#define UCA_PROP_DELAY_MIN      16
-#define UCA_PROP_DELAY_MAX      17
-#define UCA_PROP_FRAMERATE      18 
-#define UCA_PROP_TRIGGER_MODE   19
+#define UCA_PROP_BITDEPTH       9
+#define UCA_PROP_EXPOSURE       10
+#define UCA_PROP_EXPOSURE_MIN   11
+#define UCA_PROP_EXPOSURE_MAX   12
+#define UCA_PROP_DELAY          13
+#define UCA_PROP_DELAY_MIN      14
+#define UCA_PROP_DELAY_MAX      15
+#define UCA_PROP_FRAMERATE      16 
+#define UCA_PROP_TRIGGER_MODE   17
 
 /* pco.edge specific */
-#define UCA_PROP_TIMESTAMP_MODE 20
-#define UCA_PROP_SCAN_MODE      21
+#define UCA_PROP_TIMESTAMP_MODE 18
+#define UCA_PROP_SCAN_MODE      19
 
 /* IPE camera specific */
-#define UCA_PROP_INTERLACE_SAMPLE_RATE  22
-#define UCA_PROP_INTERLACE_PIXEL_THRESH 23
-#define UCA_PROP_INTERLACE_ROW_THRESH   24
+#define UCA_PROP_INTERLACE_SAMPLE_RATE  20
+#define UCA_PROP_INTERLACE_PIXEL_THRESH 21
+#define UCA_PROP_INTERLACE_ROW_THRESH   22
 
 /* Photon Focus specific */
-#define UCA_PROP_CORRECTION_MODE        25
+#define UCA_PROP_CORRECTION_MODE        23
 
-#define UCA_PROP_LAST                   26
+#define UCA_PROP_LAST                   24
 
 /* Possible timestamp modes for UCA_PROP_TIMESTAMP_MODE */
 #define UCA_TIMESTAMP_ASCII     0x01
@@ -156,18 +154,24 @@ struct uca_property_t {
     } type;
 };
 
-struct uca_t {
+struct uca_camera_t {
+    struct uca_camera_t     *next;
+
     /* Function pointers to camera-specific methods */
-    uca_cam_set_property    cam_set_property;
-    uca_cam_get_property    cam_get_property;
-    uca_cam_acquire_image   cam_acquire_image;
-    uca_cam_alloc           cam_alloc;
+    uca_cam_set_property    set_property;
+    uca_cam_get_property    get_property;
+    uca_cam_acquire_image   acquire_image;
+    uca_cam_alloc           alloc;
 
     /* Private */
-    uca_cam_destroy         cam_destroy;
+    uca_cam_destroy         destroy;
 
     void *user; /**< private user data to be used by the camera driver */
 };
 
+struct uca_t {
+    struct uca_camera_t *cameras;
+};
+
 
 #endif
-- 
cgit v1.2.3