From a8436e9b42a1b5a2b30b13a13496539fc23f480e Mon Sep 17 00:00:00 2001
From: Matthias Vogelgesang <matthias.vogelgesang@kit.edu>
Date: Fri, 2 Mar 2012 10:31:40 +0100
Subject: Make UcaCamera a base class not an interface

---
 src/cameras/uca-mock-camera.c | 50 +++++++++++++-----------
 src/cameras/uca-mock-camera.h |  7 +++-
 src/cameras/uca-pco-camera.c  | 20 ++++------
 src/cameras/uca-pco-camera.h  |  5 ++-
 src/uca-camera.c              | 88 +++++++++++++++++++++++++++++++++++--------
 src/uca-camera.h              | 24 ++++++++++--
 test/CMakeLists.txt           |  7 ++++
 test/test-gobject.c           |  4 +-
 8 files changed, 146 insertions(+), 59 deletions(-)

diff --git a/src/cameras/uca-mock-camera.c b/src/cameras/uca-mock-camera.c
index ba92a67..12ba070 100644
--- a/src/cameras/uca-mock-camera.c
+++ b/src/cameras/uca-mock-camera.c
@@ -15,21 +15,18 @@
    with this library; if not, write to the Free Software Foundation, Inc., 51
    Franklin St, Fifth Floor, Boston, MA 02110, USA */
 
-#include "uca-camera.h"
+#include <string.h>
 #include "uca-mock-camera.h"
 
 #define UCA_MOCK_CAMERA_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), UCA_TYPE_MOCK_CAMERA, UcaMockCameraPrivate))
 
-static void uca_mock_camera_interface_init(UcaCameraInterface *iface);
-
-G_DEFINE_TYPE_WITH_CODE(UcaMockCamera, uca_mock_camera, G_TYPE_OBJECT,
-                        G_IMPLEMENT_INTERFACE(UCA_TYPE_CAMERA,
-                                              uca_mock_camera_interface_init));
+G_DEFINE_TYPE(UcaMockCamera, uca_mock_camera, UCA_TYPE_CAMERA)
 
 enum {
     PROP_0,
     PROP_SENSOR_WIDTH,
     PROP_SENSOR_HEIGHT,
+    PROP_SENSOR_BITDEPTH,
     N_INTERFACE_PROPERTIES,
 
     N_PROPERTIES
@@ -37,7 +34,8 @@ enum {
 
 static const gchar *mock_overrideables[N_PROPERTIES] = {
     "sensor-width",
-    "sensor-height"
+    "sensor-height",
+    "sensor-bitdepth"
 };
 
 struct _UcaMockCameraPrivate {
@@ -46,22 +44,28 @@ struct _UcaMockCameraPrivate {
     guint16 *dummy_data;
 };
 
+UcaMockCamera *uca_mock_camera_new(GError **error)
+{
+    UcaMockCamera *camera = g_object_new(UCA_TYPE_MOCK_CAMERA, NULL);
+    return camera;
+}
+
 static void uca_mock_camera_start_recording(UcaCamera *camera, GError **error)
 {
     g_return_if_fail(UCA_IS_MOCK_CAMERA(camera));
-    g_print("start recording\n");
 }
 
 static void uca_mock_camera_stop_recording(UcaCamera *camera, GError **error)
 {
     g_return_if_fail(UCA_IS_MOCK_CAMERA(camera));
-    g_print("stop recording\n");
+    UcaMockCameraPrivate *priv = UCA_MOCK_CAMERA_GET_PRIVATE(camera);
 }
 
 static void uca_mock_camera_grab(UcaCamera *camera, gchar *data, GError **error)
 {
     g_return_if_fail(UCA_IS_MOCK_CAMERA(camera));
-    /* g_memmove(data, camera->priv->dummy_data, camera->priv->width * camera->priv->height * 2); */
+    UcaMockCameraPrivate *priv = UCA_MOCK_CAMERA_GET_PRIVATE(camera);
+    g_memmove(data, priv->dummy_data, priv->width * priv->height);
 }
 
 static void uca_mock_camera_set_property(GObject *object, guint property_id, const GValue *value, GParamSpec *pspec)
@@ -81,7 +85,13 @@ static void uca_mock_camera_get_property(GObject *object, guint property_id, GVa
 
     switch (property_id) {
         case PROP_SENSOR_WIDTH:
-            g_value_set_uint(value, 1024);
+            g_value_set_uint(value, priv->width);
+            break;
+        case PROP_SENSOR_HEIGHT:
+            g_value_set_uint(value, priv->height);
+            break;
+        case PROP_SENSOR_BITDEPTH:
+            g_value_set_uint(value, 8);
             break;
         default:
             G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
@@ -98,13 +108,6 @@ static void uca_mock_camera_finalize(GObject *object)
     G_OBJECT_CLASS(uca_mock_camera_parent_class)->finalize(object);
 }
 
-static void uca_mock_camera_interface_init(UcaCameraInterface *iface)
-{
-    iface->start_recording = uca_mock_camera_start_recording;
-    iface->stop_recording = uca_mock_camera_stop_recording;
-    iface->grab = uca_mock_camera_grab;
-}
-
 static void uca_mock_camera_class_init(UcaMockCameraClass *klass)
 {
     GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
@@ -112,6 +115,11 @@ static void uca_mock_camera_class_init(UcaMockCameraClass *klass)
     gobject_class->get_property = uca_mock_camera_get_property;
     gobject_class->finalize = uca_mock_camera_finalize;
 
+    UcaCameraClass *camera_class = UCA_CAMERA_CLASS(klass);
+    camera_class->start_recording = uca_mock_camera_start_recording;
+    camera_class->stop_recording = uca_mock_camera_stop_recording;
+    camera_class->grab = uca_mock_camera_grab;
+
     for (guint id = PROP_0 + 1; id < N_INTERFACE_PROPERTIES; id++)
         g_object_class_override_property(gobject_class, id, mock_overrideables[id-1]);
 
@@ -121,7 +129,7 @@ static void uca_mock_camera_class_init(UcaMockCameraClass *klass)
 static void uca_mock_camera_init(UcaMockCamera *self)
 {
     self->priv = UCA_MOCK_CAMERA_GET_PRIVATE(self);
-    self->priv->width = 1024;
-    self->priv->height = 768;
-    self->priv->dummy_data = (guint16 *) g_malloc0(self->priv->width * self->priv->height * 2);
+    self->priv->width = 640;
+    self->priv->height = 480;
+    self->priv->dummy_data = (guint16 *) g_malloc0(self->priv->width * self->priv->height);
 }
diff --git a/src/cameras/uca-mock-camera.h b/src/cameras/uca-mock-camera.h
index 708542a..aa196db 100644
--- a/src/cameras/uca-mock-camera.h
+++ b/src/cameras/uca-mock-camera.h
@@ -19,6 +19,7 @@
 #define __UCA_MOCK_CAMERA_H
 
 #include <glib-object.h>
+#include "uca-camera.h"
 
 #define UCA_TYPE_MOCK_CAMERA             (uca_mock_camera_get_type())
 #define UCA_MOCK_CAMERA(obj)             (G_TYPE_CHECK_INSTANCE_CAST((obj), UCA_TYPE_MOCK_CAMERA, UcaMockCamera))
@@ -40,7 +41,7 @@ typedef struct _UcaMockCameraPrivate    UcaMockCameraPrivate;
  */
 struct _UcaMockCamera {
     /*< private >*/
-    GObject parent;
+    UcaCamera parent;
 
     UcaMockCameraPrivate *priv;
 };
@@ -52,9 +53,11 @@ struct _UcaMockCamera {
  */
 struct _UcaMockCameraClass {
     /*< private >*/
-    GObjectClass parent;
+    UcaCameraClass parent;
 };
 
+UcaMockCamera *uca_mock_camera_new(GError **error);
+
 GType uca_mock_camera_get_type(void);
 
 #endif
diff --git a/src/cameras/uca-pco-camera.c b/src/cameras/uca-pco-camera.c
index 332d3ea..0e1267c 100644
--- a/src/cameras/uca-pco-camera.c
+++ b/src/cameras/uca-pco-camera.c
@@ -27,9 +27,7 @@
 
 static void uca_pco_camera_interface_init(UcaCameraInterface *iface);
 
-G_DEFINE_TYPE_WITH_CODE(UcaPcoCamera, uca_pco_camera, G_TYPE_OBJECT,
-                        G_IMPLEMENT_INTERFACE(UCA_TYPE_CAMERA,
-                                              uca_pco_camera_interface_init));
+G_DEFINE_TYPE(UcaPcoCamera, uca_pco_camera, UCA_TYPE_CAMERA)
 
 /**
  * UcaPcoCameraError:
@@ -54,7 +52,7 @@ enum {
     N_PROPERTIES
 };
 
-static const gchar *pco_overrideables[N_PROPERTIES] = {
+static const gchar *base_overrideables[N_PROPERTIES] = {
     "sensor-width",
     "sensor-height",
     "sensor-bitdepth"
@@ -229,13 +227,6 @@ static void uca_pco_camera_finalize(GObject *object)
     G_OBJECT_CLASS(uca_pco_camera_parent_class)->finalize(object);
 }
 
-static void uca_pco_camera_interface_init(UcaCameraInterface *iface)
-{
-    iface->start_recording = uca_pco_camera_start_recording;
-    iface->stop_recording = uca_pco_camera_stop_recording;
-    iface->grab = uca_pco_camera_grab;
-}
-
 static void uca_pco_camera_class_init(UcaPcoCameraClass *klass)
 {
     GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
@@ -243,8 +234,13 @@ static void uca_pco_camera_class_init(UcaPcoCameraClass *klass)
     gobject_class->get_property = uca_pco_camera_get_property;
     gobject_class->finalize = uca_pco_camera_finalize;
 
+    UcaCameraClass *camera_class = UCA_CAMERA_CLASS(klass);
+    camera_class->start_recording = uca_pco_camera_start_recording;
+    camera_class->stop_recording = uca_pco_camera_stop_recording;
+    camera_class->grab = uca_pco_camera_grab;
+
     for (guint id = PROP_0 + 1; id < N_INTERFACE_PROPERTIES; id++)
-        g_object_class_override_property(gobject_class, id, pco_overrideables[id-1]);
+        g_object_class_override_property(gobject_class, id, base_overrideables[id-1]);
 
     pco_properties[PROP_NAME] = 
         g_param_spec_string("name",
diff --git a/src/cameras/uca-pco-camera.h b/src/cameras/uca-pco-camera.h
index 68e92fa..ba6a105 100644
--- a/src/cameras/uca-pco-camera.h
+++ b/src/cameras/uca-pco-camera.h
@@ -19,6 +19,7 @@
 #define __UCA_PCO_CAMERA_H
 
 #include <glib-object.h>
+#include "uca-camera.h"
 
 #define UCA_TYPE_PCO_CAMERA             (uca_pco_camera_get_type())
 #define UCA_PCO_CAMERA(obj)             (G_TYPE_CHECK_INSTANCE_CAST((obj), UCA_TYPE_PCO_CAMERA, UcaPcoCamera))
@@ -48,7 +49,7 @@ typedef struct _UcaPcoCameraPrivate    UcaPcoCameraPrivate;
  */
 struct _UcaPcoCamera {
     /*< private >*/
-    GObject parent;
+    UcaCamera parent;
 
     UcaPcoCameraPrivate *priv;
 };
@@ -60,7 +61,7 @@ struct _UcaPcoCamera {
  */
 struct _UcaPcoCameraClass {
     /*< private >*/
-    GObjectClass parent;
+    UcaCameraClass parent;
 };
 
 UcaPcoCamera *uca_pco_camera_new(GError **error);
diff --git a/src/uca-camera.c b/src/uca-camera.c
index cb7890b..d8c1a25 100644
--- a/src/uca-camera.c
+++ b/src/uca-camera.c
@@ -18,7 +18,19 @@
 #include <glib.h>
 #include "uca-camera.h"
 
-G_DEFINE_INTERFACE(UcaCamera, uca_camera, G_TYPE_OBJECT)
+#define UCA_CAMERA_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), UCA_TYPE_CAMERA, UcaCameraPrivate))
+
+G_DEFINE_TYPE(UcaCamera, uca_camera, G_TYPE_OBJECT)
+
+/**
+ * UcaCameraError:
+ * @UCA_CAMERA_ERROR_RECORDING: Camera is already recording
+ * @UCA_CAMERA_ERROR_NOT_RECORDING: Camera is not recording
+ */
+GQuark uca_camera_error_quark()
+{
+    return g_quark_from_static_string("uca-camera-error-quark");
+}
 
 enum {
     PROP_0 = 0,
@@ -30,10 +42,26 @@ enum {
     N_PROPERTIES
 };
 
+struct _UcaCameraPrivate {
+    gboolean recording;
+};
+
 static GParamSpec *uca_camera_properties[N_PROPERTIES] = { NULL, };
 
-static void uca_camera_default_init(UcaCameraInterface *klass)
+static void uca_camera_set_property(GObject *object, guint property_id, const GValue *value, GParamSpec *pspec)
+{
+}
+
+static void uca_camera_get_property(GObject *object, guint property_id, GValue *value, GParamSpec *pspec)
+{
+}
+
+static void uca_camera_class_init(UcaCameraClass *klass)
 {
+    GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
+    gobject_class->set_property = uca_camera_set_property;
+    gobject_class->get_property = uca_camera_get_property;
+
     klass->start_recording = NULL;
     klass->stop_recording = NULL;
     klass->grab = NULL;
@@ -73,43 +101,71 @@ static void uca_camera_default_init(UcaCameraInterface *klass)
             1, G_MAXUINT, 1,
             G_PARAM_READWRITE);
 
-    for (int i = PROP_0 + 1; i < N_PROPERTIES; i++)
-        g_object_interface_install_property(klass, uca_camera_properties[i]);
+    for (guint id = PROP_0 + 1; id < N_PROPERTIES; id++)
+        g_object_class_install_property(gobject_class, id, uca_camera_properties[id]);
+
+    g_type_class_add_private(klass, sizeof(UcaCameraPrivate));
+}
+
+static void uca_camera_init(UcaCamera *camera)
+{
+    camera->priv = UCA_CAMERA_GET_PRIVATE(camera);
+    camera->priv->recording = FALSE;
 }
 
 void uca_camera_start_recording(UcaCamera *camera, GError **error)
 {
     g_return_if_fail(UCA_IS_CAMERA(camera));
 
-    UcaCameraInterface *iface = UCA_CAMERA_GET_INTERFACE(camera);
+    UcaCameraClass *klass = UCA_CAMERA_GET_CLASS(camera);
+
+    g_return_if_fail(klass != NULL);
+    g_return_if_fail(klass->start_recording != NULL);
 
-    g_return_if_fail(iface != NULL);
-    g_return_if_fail(iface->start_recording != NULL);
+    if (camera->priv->recording) {
+        g_set_error(error, UCA_CAMERA_ERROR, UCA_CAMERA_ERROR_RECORDING,
+                "Camera is already recording");
+        return;
+    }
 
-    (*iface->start_recording)(camera, error);
+    camera->priv->recording = TRUE;
+    (*klass->start_recording)(camera, error);
 }
 
 void uca_camera_stop_recording(UcaCamera *camera, GError **error)
 {
     g_return_if_fail(UCA_IS_CAMERA(camera));
 
-    UcaCameraInterface *iface = UCA_CAMERA_GET_INTERFACE(camera);
+    UcaCameraClass *klass = UCA_CAMERA_GET_CLASS(camera);
 
-    g_return_if_fail(iface != NULL);
-    g_return_if_fail(iface->start_recording != NULL);
+    g_return_if_fail(klass != NULL);
+    g_return_if_fail(klass->stop_recording != NULL);
 
-    (*iface->stop_recording)(camera, error);
+    if (!camera->priv->recording) {
+        g_set_error(error, UCA_CAMERA_ERROR, UCA_CAMERA_ERROR_NOT_RECORDING,
+                "Camera is not recording");
+        return;
+    }
+
+    camera->priv->recording = FALSE;
+    (*klass->stop_recording)(camera, error);
 }
 
 void uca_camera_grab(UcaCamera *camera, gchar *data, GError **error)
 {
     g_return_if_fail(UCA_IS_CAMERA(camera));
 
-    UcaCameraInterface *iface = UCA_CAMERA_GET_INTERFACE(camera);
+    UcaCameraClass *klass = UCA_CAMERA_GET_CLASS(camera);
+
+    g_return_if_fail(klass != NULL);
+    g_return_if_fail(klass->grab != NULL);
 
-    g_return_if_fail(iface != NULL);
-    g_return_if_fail(iface->start_recording != NULL);
+    if (!camera->priv->recording) {
+        g_set_error(error, UCA_CAMERA_ERROR, UCA_CAMERA_ERROR_NOT_RECORDING,
+                "Camera is not recording");
+        return;
+    }
 
-    (*iface->grab)(camera, data, error);
+    (*klass->grab)(camera, data, error);
 }
 
diff --git a/src/uca-camera.h b/src/uca-camera.h
index 1d66d8f..4e30c0a 100644
--- a/src/uca-camera.h
+++ b/src/uca-camera.h
@@ -23,19 +23,35 @@
 #define UCA_TYPE_CAMERA             (uca_camera_get_type())
 #define UCA_CAMERA(obj)             (G_TYPE_CHECK_INSTANCE_CAST((obj), UCA_TYPE_CAMERA, UcaCamera))
 #define UCA_IS_CAMERA(obj)          (G_TYPE_CHECK_INSTANCE_TYPE((obj), UCA_TYPE_CAMERA))
-#define UCA_CAMERA_GET_INTERFACE(obj)   (G_TYPE_INSTANCE_GET_INTERFACE((obj), UCA_TYPE_CAMERA, UcaCameraInterface))
+#define UCA_CAMERA_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST((klass), UCA_TYPE_CAMERA, UcaCameraClass))
+#define UCA_IS_CAMERA_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE((klass), UCA_TYPE_CAMERA))
+#define UCA_CAMERA_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS((obj), UCA_TYPE_CAMERA, UcaCameraClass))
+
+#define UCA_CAMERA_ERROR uca_camera_error_quark()
+typedef enum {
+    UCA_CAMERA_ERROR_RECORDING,
+    UCA_CAMERA_ERROR_NOT_RECORDING
+} UcaCameraError;
 
 typedef struct _UcaCamera           UcaCamera;
-typedef struct _UcaCameraInterface  UcaCameraInterface;
+typedef struct _UcaCameraClass      UcaCameraClass;
+typedef struct _UcaCameraPrivate    UcaCameraPrivate;
+
+struct _UcaCamera {
+    /*< private >*/
+    GObject parent;
+
+    UcaCameraPrivate *priv;
+};
 
 /**
  * UcaCameraInterface:
  *
  * Base interface for cameras.
  */
-struct _UcaCameraInterface {
+struct _UcaCameraClass {
     /*< private >*/
-    GTypeInterface parent;
+    GObjectClass parent;
 
     void (*start_recording) (UcaCamera *camera, GError **error);
     void (*stop_recording) (UcaCamera *camera, GError **error);
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 63c46d7..4ee097b 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -50,3 +50,10 @@ target_link_libraries(test-gobject
     ${GLIB2_LIBRARIES}
     ${GOBJECT2_LIBRARIES}
     )
+
+add_executable(test-mock test-mock.c)
+target_link_libraries(test-mock
+    uca-gobject 
+    ${GLIB2_LIBRARIES}
+    ${GOBJECT2_LIBRARIES}
+    )
diff --git a/test/test-gobject.c b/test/test-gobject.c
index 44a13cb..3ff77bf 100644
--- a/test/test-gobject.c
+++ b/test/test-gobject.c
@@ -1,13 +1,13 @@
 #include <glib-object.h>
 #include "uca-camera.h"
-#include "uca-pco-camera.h"
+#include "uca-mock-camera.h"
 
 int main(int argc, char **argv)
 {
     g_type_init();
 
     GError *error = NULL;
-    UcaPcoCamera *cam = uca_pco_camera_new(&error);
+    UcaMockCamera *cam = uca_mock_camera_new(&error);
 
     if (cam == NULL) {
         g_error("Camera could not be initialized\n");
-- 
cgit v1.2.3