From 034204d3d8d1a32b1a20e50697c5f81db6fb20cf Mon Sep 17 00:00:00 2001 From: Matthias Vogelgesang Date: Fri, 31 Aug 2012 23:14:16 +0200 Subject: Initial plugin manager --- src/CMakeLists.txt | 12 ++- src/uca-camera.c | 199 ++++++++++++++++++------------------ src/uca-plugin-manager.c | 260 +++++++++++++++++++++++++++++++++++++++++++++++ src/uca-plugin-manager.h | 65 ++++++++++++ 4 files changed, 435 insertions(+), 101 deletions(-) create mode 100644 src/uca-plugin-manager.c create mode 100644 src/uca-plugin-manager.h (limited to 'src') diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 9508c5c..1b814aa 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -3,6 +3,7 @@ cmake_minimum_required(VERSION 2.8) # --- Set sources ------------------------------------------------------------- set(uca_SRCS uca-camera.c + uca-plugin-manager.c ) set(uca_HDRS @@ -10,6 +11,8 @@ set(uca_HDRS set(cameras) +set(LIB_INSTALL_DIR "lib${LIB_SUFFIX}") + # --- Find packages and libraries --------------------------------------------- set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake) @@ -107,9 +110,12 @@ if (PYLON_FOUND) endif() if (HAVE_MOCK_CAMERA) - list(APPEND uca_SRCS cameras/uca-mock-camera.c) - list(APPEND uca_HDRS cameras/uca-mock-camera.h) - list(APPEND cameras "Mock") + add_library(ucamock SHARED cameras/uca-mock-camera.c) + #list(APPEND uca_SRCS cameras/uca-mock-camera.c) + ##list(APPEND uca_HDRS cameras/uca-mock-camera.h) + #list(APPEND cameras "Mock") + install(TARGETS ucamock + LIBRARY DESTINATION ${LIB_INSTALL_DIR}/uca) endif() # --- Generate enum file diff --git a/src/uca-camera.c b/src/uca-camera.c index 78adae3..59ab5c7 100644 --- a/src/uca-camera.c +++ b/src/uca-camera.c @@ -20,25 +20,25 @@ #include "uca-camera.h" #include "uca-enums.h" -#ifdef HAVE_PCO_CL -#include "cameras/uca-pco-camera.h" -#endif +/* #ifdef HAVE_PCO_CL */ +/* #include "cameras/uca-pco-camera.h" */ +/* #endif */ -#ifdef HAVE_PYLON_CAMERA -#include "cameras/uca-pylon-camera.h" -#endif +/* #ifdef HAVE_PYLON_CAMERA */ +/* #include "cameras/uca-pylon-camera.h" */ +/* #endif */ -#ifdef HAVE_MOCK_CAMERA -#include "cameras/uca-mock-camera.h" -#endif +/* #ifdef HAVE_MOCK_CAMERA */ +/* #include "cameras/uca-mock-camera.h" */ +/* #endif */ -#ifdef HAVE_UFO_CAMERA -#include "cameras/uca-ufo-camera.h" -#endif +/* #ifdef HAVE_UFO_CAMERA */ +/* #include "cameras/uca-ufo-camera.h" */ +/* #endif */ -#ifdef HAVE_PHOTON_FOCUS -#include "cameras/uca-pf-camera.h" -#endif +/* #ifdef HAVE_PHOTON_FOCUS */ +/* #include "cameras/uca-pf-camera.h" */ +/* #endif */ #define UCA_CAMERA_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), UCA_TYPE_CAMERA, UcaCameraPrivate)) @@ -65,24 +65,24 @@ GQuark uca_camera_error_quark() return g_quark_from_static_string("uca-camera-error-quark"); } -static gchar *uca_camera_types[] = { -#ifdef HAVE_PCO_CL - "pco", -#endif -#ifdef HAVE_PYLON_CAMERA - "pylon", -#endif -#ifdef HAVE_MOCK_CAMERA - "mock", -#endif -#ifdef HAVE_UFO_CAMERA - "ufo", -#endif -#ifdef HAVE_PHOTON_FOCUS - "pf", -#endif - NULL -}; +/* static gchar *uca_camera_types[] = { */ +/* #ifdef HAVE_PCO_CL */ +/* "pco", */ +/* #endif */ +/* #ifdef HAVE_PYLON_CAMERA */ +/* "pylon", */ +/* #endif */ +/* #ifdef HAVE_MOCK_CAMERA */ +/* "mock", */ +/* #endif */ +/* #ifdef HAVE_UFO_CAMERA */ +/* "ufo", */ +/* #endif */ +/* #ifdef HAVE_PHOTON_FOCUS */ +/* "pf", */ +/* #endif */ +/* NULL */ +/* }; */ enum { LAST_SIGNAL @@ -126,7 +126,8 @@ struct _UcaCameraPrivate { gboolean transfer_async; }; -static void uca_camera_set_property(GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) +static void +uca_camera_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { UcaCameraPrivate *priv = UCA_CAMERA_GET_PRIVATE(object); @@ -145,7 +146,8 @@ static void uca_camera_set_property(GObject *object, guint property_id, const GV } } -static void uca_camera_get_property(GObject *object, guint property_id, GValue *value, GParamSpec *pspec) +static void +uca_camera_get_property(GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { UcaCameraPrivate *priv = UCA_CAMERA_GET_PRIVATE(object); @@ -167,7 +169,8 @@ static void uca_camera_get_property(GObject *object, guint property_id, GValue * } } -static void uca_camera_class_init(UcaCameraClass *klass) +static void +uca_camera_class_init(UcaCameraClass *klass) { GObjectClass *gobject_class = G_OBJECT_CLASS(klass); gobject_class->set_property = uca_camera_set_property; @@ -370,48 +373,48 @@ static void uca_camera_init(UcaCamera *camera) */ } -static UcaCamera *uca_camera_new_from_type(const gchar *type, GError **error) -{ -#ifdef HAVE_MOCK_CAMERA - if (!g_strcmp0(type, "mock")) - return UCA_CAMERA(uca_mock_camera_new(error)); -#endif - -#ifdef HAVE_PCO_CL - if (!g_strcmp0(type, "pco")) - return UCA_CAMERA(uca_pco_camera_new(error)); -#endif - -#ifdef HAVE_PYLON_CAMERA - if (!g_strcmp0(type, "pylon")) - return UCA_CAMERA(uca_pylon_camera_new(error)); -#endif - -#ifdef HAVE_UFO_CAMERA - if (!g_strcmp0(type, "ufo")) - return UCA_CAMERA(uca_ufo_camera_new(error)); -#endif - -#ifdef HAVE_PHOTON_FOCUS - if (!g_strcmp0(type, "pf")) - return UCA_CAMERA(uca_pf_camera_new(error)); -#endif - - return NULL; -} - -/** - * uca_camera_get_types: - * - * Enumerate all camera types that can be instantiated with uca_camera_new(). - * - * Returns: An array of strings with camera types. The list should be freed with - * g_strfreev(). - */ -gchar **uca_camera_get_types() -{ - return g_strdupv(uca_camera_types); -} +/* static UcaCamera *uca_camera_new_from_type(const gchar *type, GError **error) */ +/* { */ +/* #ifdef HAVE_MOCK_CAMERA */ +/* if (!g_strcmp0(type, "mock")) */ +/* return UCA_CAMERA(uca_mock_camera_new(error)); */ +/* #endif */ + +/* #ifdef HAVE_PCO_CL */ +/* if (!g_strcmp0(type, "pco")) */ +/* return UCA_CAMERA(uca_pco_camera_new(error)); */ +/* #endif */ + +/* #ifdef HAVE_PYLON_CAMERA */ +/* if (!g_strcmp0(type, "pylon")) */ +/* return UCA_CAMERA(uca_pylon_camera_new(error)); */ +/* #endif */ + +/* #ifdef HAVE_UFO_CAMERA */ +/* if (!g_strcmp0(type, "ufo")) */ +/* return UCA_CAMERA(uca_ufo_camera_new(error)); */ +/* #endif */ + +/* #ifdef HAVE_PHOTON_FOCUS */ +/* if (!g_strcmp0(type, "pf")) */ +/* return UCA_CAMERA(uca_pf_camera_new(error)); */ +/* #endif */ + +/* return NULL; */ +/* } */ + +/* /** */ +/* * uca_camera_get_types: */ +/* * */ +/* * Enumerate all camera types that can be instantiated with uca_camera_new(). */ +/* * */ +/* * Returns: An array of strings with camera types. The list should be freed with */ +/* * g_strfreev(). */ +/* *1/ */ +/* gchar **uca_camera_get_types() */ +/* { */ +/* return g_strdupv(uca_camera_types); */ +/* } */ /** * uca_camera_new: @@ -423,26 +426,26 @@ gchar **uca_camera_get_types() * * Returns: A new #UcaCamera of the correct type or %NULL if type was not found */ -UcaCamera *uca_camera_new(const gchar *type, GError **error) -{ - UcaCamera *camera = NULL; - GError *tmp_error = NULL; - - camera = uca_camera_new_from_type(type, &tmp_error); - - if (tmp_error != NULL) { - g_propagate_error(error, tmp_error); - return NULL; - } - - if ((tmp_error == NULL) && (camera == NULL)) { - g_set_error(error, UCA_CAMERA_ERROR, UCA_CAMERA_ERROR_NOT_FOUND, - "Camera type %s not found", type); - return NULL; - } - - return camera; -} +/* UcaCamera *uca_camera_new(const gchar *type, GError **error) */ +/* { */ +/* UcaCamera *camera = NULL; */ +/* GError *tmp_error = NULL; */ + +/* camera = uca_camera_new_from_type(type, &tmp_error); */ + +/* if (tmp_error != NULL) { */ +/* g_propagate_error(error, tmp_error); */ +/* return NULL; */ +/* } */ + +/* if ((tmp_error == NULL) && (camera == NULL)) { */ +/* g_set_error(error, UCA_CAMERA_ERROR, UCA_CAMERA_ERROR_NOT_FOUND, */ +/* "Camera type %s not found", type); */ +/* return NULL; */ +/* } */ + +/* return camera; */ +/* } */ /** * uca_camera_start_recording: diff --git a/src/uca-plugin-manager.c b/src/uca-plugin-manager.c new file mode 100644 index 0000000..7788678 --- /dev/null +++ b/src/uca-plugin-manager.c @@ -0,0 +1,260 @@ +/** + * SECTION:uca-plugin-manager + * @Short_description: Load an #UcaFilter from a shared object + * @Title: UcaPluginManager + * + * The plugin manager opens shared object modules searched for in locations + * specified with uca_plugin_manager_add_paths(). An #UcaFilter can be + * instantiated with uca_plugin_manager_get_filter() with a one-to-one mapping + * between filter name xyz and module name libfilterxyz.so. Any errors are + * reported as one of #UcaPluginManagerError codes. + */ +#include +#include "uca-plugin-manager.h" + +G_DEFINE_TYPE (UcaPluginManager, uca_plugin_manager, G_TYPE_OBJECT) + +#define UCA_PLUGIN_MANAGER_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), UCA_TYPE_PLUGIN_MANAGER, UcaPluginManagerPrivate)) + +struct _UcaPluginManagerPrivate { + GList *search_paths; +}; + +/** + * UcaPluginManagerError: + * @UCA_PLUGIN_MANAGER_ERROR_MODULE_NOT_FOUND: The module could not be found + * @UCA_PLUGIN_MANAGER_ERROR_MODULE_OPEN: Module could not be opened + * @UCA_PLUGIN_MANAGER_ERROR_SYMBOL_NOT_FOUND: Necessary entry symbol was not + * found + * + * Possible errors that uca_plugin_manager_get_filter() can return. + */ +GQuark +uca_plugin_manager_error_quark (void) +{ + return g_quark_from_static_string ("uca-plugin-manager-error-quark"); +} + +/** + * uca_plugin_manager_new: + * @config: (allow-none): A #UcaConfiguration object or %NULL. + * + * Create a plugin manager object to instantiate filter objects. When a config + * object is passed to the constructor, its search-path property is added to the + * internal search paths. + * + * Return value: A new plugin manager object. + */ +UcaPluginManager * +uca_plugin_manager_new () +{ + return UCA_PLUGIN_MANAGER (g_object_new (UCA_TYPE_PLUGIN_MANAGER, NULL)); +} + +void +uca_plugin_manager_add_path (UcaPluginManager *manager, + const gchar *path) +{ + g_return_if_fail (UCA_IS_PLUGIN_MANAGER (manager)); + + if (g_file_test (path, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR)) { + UcaPluginManagerPrivate *priv; + + priv = manager->priv; + priv->search_paths = g_list_append (priv->search_paths, + g_strdup (path)); + } +} + +static GList * +get_camera_names_from_directory (const gchar *path) +{ + static const gchar *pattern_string = "libuca([A-Za-z]+)"; + GRegex *pattern; + GDir *dir; + GList *result = NULL; + + pattern = g_regex_new (pattern_string, 0, 0, NULL); + dir = g_dir_open (path, 0, NULL); + + if (dir != NULL) { + GMatchInfo *match_info = NULL; + const gchar *name = g_dir_read_name (dir); + + while (name != NULL) { + g_regex_match (pattern, name, 0, &match_info); + + if (g_match_info_matches (match_info)) { + gchar *word = g_match_info_fetch (match_info, 1); + result = g_list_append (result, word); + } + + name = g_dir_read_name (dir); + } + } + + return result; +} + +GList * +uca_plugin_manager_get_available_cameras (UcaPluginManager *manager) +{ + UcaPluginManagerPrivate *priv; + GList *camera_names; + + g_return_val_if_fail (UCA_IS_PLUGIN_MANAGER (manager), NULL); + + priv = manager->priv; + + for (GList *it = g_list_first (priv->search_paths); it != NULL; it = g_list_next (it)) { + camera_names = g_list_concat (camera_names, + get_camera_names_from_directory ((const gchar*) it->data)); + } + + return camera_names; +} + +UcaCamera * +uca_plugin_manager_new_camera (UcaPluginManager *manager, + const gchar *name, + GError **error) +{ + return NULL; +} + +/** + * uca_plugin_manager_get_filter: + * @manager: A #UcaPluginManager + * @name: Name of the plugin. + * @error: return location for a GError or %NULL + * + * Load a #UcaFilter module and return an instance. The shared object name must + * be * constructed as "libfilter@name.so". + * + * Returns: (transfer none) (allow-none): #UcaFilter or %NULL if module cannot be found + * + * Since: 0.2, the error parameter is available + */ +/* UcaFilter * */ +/* uca_plugin_manager_get_filter (UcaPluginManager *manager, const gchar *name, GError **error) */ +/* { */ +/* g_return_val_if_fail (UCA_IS_PLUGIN_MANAGER (manager) && (name != NULL), NULL); */ +/* UcaPluginManagerPrivate *priv = UCA_PLUGIN_MANAGER_GET_PRIVATE (manager); */ +/* UcaFilter *filter; */ +/* GetFilterFunc *func = NULL; */ +/* GModule *module = NULL; */ +/* gchar *module_name = NULL; */ +/* const gchar *entry_symbol_name = "uca_filter_plugin_new"; */ + +/* func = g_hash_table_lookup (priv->filter_funcs, name); */ + +/* if (func == NULL) { */ +/* module_name = g_strdup_printf ("libucafilter%s.so", name); */ +/* gchar *path = plugin_manager_get_path (priv, module_name); */ + +/* if (path == NULL) { */ +/* g_set_error (error, UCA_PLUGIN_MANAGER_ERROR, UCA_PLUGIN_MANAGER_ERROR_MODULE_NOT_FOUND, */ +/* "Module %s not found", module_name); */ +/* goto handle_error; */ +/* } */ + +/* module = g_module_open (path, G_MODULE_BIND_LAZY); */ +/* g_free (path); */ + +/* if (!module) { */ +/* g_set_error (error, UCA_PLUGIN_MANAGER_ERROR, UCA_PLUGIN_MANAGER_ERROR_MODULE_OPEN, */ +/* "Module %s could not be opened: %s", module_name, g_module_error ()); */ +/* goto handle_error; */ +/* } */ + +/* func = g_malloc0 (sizeof (GetFilterFunc)); */ + +/* if (!g_module_symbol (module, entry_symbol_name, (gpointer *) func)) { */ +/* g_set_error (error, UCA_PLUGIN_MANAGER_ERROR, UCA_PLUGIN_MANAGER_ERROR_SYMBOL_NOT_FOUND, */ +/* "%s is not exported by module %s: %s", entry_symbol_name, module_name, g_module_error ()); */ +/* g_free (func); */ + +/* if (!g_module_close (module)) */ +/* g_warning ("%s", g_module_error ()); */ + +/* goto handle_error; */ +/* } */ + +/* priv->modules = g_slist_append (priv->modules, module); */ +/* g_hash_table_insert (priv->filter_funcs, g_strdup (name), func); */ +/* g_free (module_name); */ +/* } */ + +/* filter = (*func) (); */ +/* uca_filter_set_plugin_name (filter, name); */ +/* g_message ("UcaPluginManager: Created %s-%p", name, (gpointer) filter); */ + +/* return filter; */ + +/* handle_error: */ +/* g_free (module_name); */ +/* return NULL; */ +/* } */ + +static void +uca_plugin_manager_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) +{ + switch (property_id) { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +uca_plugin_manager_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) +{ + switch (property_id) { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +uca_plugin_manager_dispose (GObject *object) +{ + G_OBJECT_CLASS (uca_plugin_manager_parent_class)->dispose (object); +} + +static void +uca_plugin_manager_finalize (GObject *object) +{ + UcaPluginManagerPrivate *priv = UCA_PLUGIN_MANAGER_GET_PRIVATE (object); + + g_list_foreach (priv->search_paths, (GFunc) g_free, NULL); + g_list_free (priv->search_paths); + + G_OBJECT_CLASS (uca_plugin_manager_parent_class)->finalize (object); +} + +static void +uca_plugin_manager_class_init (UcaPluginManagerClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + gobject_class->get_property = uca_plugin_manager_get_property; + gobject_class->set_property = uca_plugin_manager_set_property; + gobject_class->dispose = uca_plugin_manager_dispose; + gobject_class->finalize = uca_plugin_manager_finalize; + + g_type_class_add_private (klass, sizeof (UcaPluginManagerPrivate)); +} + +static void +uca_plugin_manager_init (UcaPluginManager *manager) +{ + UcaPluginManagerPrivate *priv; + + manager->priv = priv = UCA_PLUGIN_MANAGER_GET_PRIVATE (manager); + priv->search_paths = NULL; + + uca_plugin_manager_add_path (manager, "/usr/lib/uca"); + uca_plugin_manager_add_path (manager, "/usr/lib64/uca"); + uca_plugin_manager_add_path (manager, "/usr/local/lib/uca"); + uca_plugin_manager_add_path (manager, "/usr/local/lib64/uca"); +} diff --git a/src/uca-plugin-manager.h b/src/uca-plugin-manager.h new file mode 100644 index 0000000..9291857 --- /dev/null +++ b/src/uca-plugin-manager.h @@ -0,0 +1,65 @@ +#ifndef __UCA_PLUGIN_MANAGER_H +#define __UCA_PLUGIN_MANAGER_H + +#include +#include "uca-camera.h" + +G_BEGIN_DECLS + +#define UCA_TYPE_PLUGIN_MANAGER (uca_plugin_manager_get_type()) +#define UCA_PLUGIN_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), UCA_TYPE_PLUGIN_MANAGER, UcaPluginManager)) +#define UCA_IS_PLUGIN_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), UCA_TYPE_PLUGIN_MANAGER)) +#define UCA_PLUGIN_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), UCA_TYPE_PLUGIN_MANAGER, UcaPluginManagerClass)) +#define UCA_IS_PLUGIN_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), UCA_TYPE_PLUGIN_MANAGER)) +#define UCA_PLUGIN_MANAGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), UCA_TYPE_PLUGIN_MANAGER, UcaPluginManagerClass)) + +#define UCA_PLUGIN_MANAGER_ERROR uca_plugin_manager_error_quark() +GQuark uca_plugin_manager_error_quark(void); + +typedef enum { + UCA_PLUGIN_MANAGER_ERROR_MODULE_NOT_FOUND, + UCA_PLUGIN_MANAGER_ERROR_MODULE_OPEN, + UCA_PLUGIN_MANAGER_ERROR_SYMBOL_NOT_FOUND +} UcaPluginManagerError; + +typedef struct _UcaPluginManager UcaPluginManager; +typedef struct _UcaPluginManagerClass UcaPluginManagerClass; +typedef struct _UcaPluginManagerPrivate UcaPluginManagerPrivate; + +/** + * UcaPluginManager: + * + * Creates #UcaFilter instances by loading corresponding shared objects. The + * contents of the #UcaPluginManager structure are private and should only be + * accessed via the provided API. + */ +struct _UcaPluginManager { + /*< private >*/ + GObject parent_instance; + + UcaPluginManagerPrivate *priv; +}; + +/** + * UcaPluginManagerClass: + * + * #UcaPluginManager class + */ +struct _UcaPluginManagerClass { + /*< private >*/ + GObjectClass parent_class; +}; + +UcaPluginManager *uca_plugin_manager_new (void); +void uca_plugin_manager_add_path (UcaPluginManager *manager, + const gchar *path); +GList *uca_plugin_manager_get_available_cameras + (UcaPluginManager *manager); +UcaCamera *uca_plugin_manager_new_camera (UcaPluginManager *manager, + const gchar *name, + GError **error); +GType uca_plugin_manager_get_type (void); + +G_END_DECLS + +#endif -- cgit v1.2.3 From af00a17308fd17ea454021649a36f2f397a6da2b Mon Sep 17 00:00:00 2001 From: Matthias Vogelgesang Date: Wed, 19 Sep 2012 15:59:57 +0200 Subject: Fix segfault --- src/uca-plugin-manager.c | 6 ++++-- test/benchmark.c | 4 +--- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/uca-plugin-manager.c b/src/uca-plugin-manager.c index 7788678..bb27215 100644 --- a/src/uca-plugin-manager.c +++ b/src/uca-plugin-manager.c @@ -86,7 +86,9 @@ get_camera_names_from_directory (const gchar *path) if (g_match_info_matches (match_info)) { gchar *word = g_match_info_fetch (match_info, 1); - result = g_list_append (result, word); + + if (word != NULL) + result = g_list_append (result, word); } name = g_dir_read_name (dir); @@ -100,7 +102,7 @@ GList * uca_plugin_manager_get_available_cameras (UcaPluginManager *manager) { UcaPluginManagerPrivate *priv; - GList *camera_names; + GList *camera_names = NULL; g_return_val_if_fail (UCA_IS_PLUGIN_MANAGER (manager), NULL); diff --git a/test/benchmark.c b/test/benchmark.c index 1604cdb..73b6805 100644 --- a/test/benchmark.c +++ b/test/benchmark.c @@ -38,16 +38,14 @@ sigint_handler(int signal) static void print_usage (void) { - /* gchar **types; */ GList *types; UcaPluginManager *manager; manager = uca_plugin_manager_new (); g_print ("Usage: benchmark ["); - /* types = uca_camera_get_types (); */ types = uca_plugin_manager_get_available_cameras (manager); - if (g_list_length (types) == 0) { + if (types == NULL) { g_print ("] -- no camera plugin found\n"); return; } -- cgit v1.2.3 From 90f0d4f6fa74111f38c9aedf31ecb740bc0ddf97 Mon Sep 17 00:00:00 2001 From: Matthias Vogelgesang Date: Wed, 19 Sep 2012 16:05:46 +0200 Subject: Add path from UCA_CAMERA_PATH environment variable --- src/uca-plugin-manager.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'src') diff --git a/src/uca-plugin-manager.c b/src/uca-plugin-manager.c index bb27215..61e43f8 100644 --- a/src/uca-plugin-manager.c +++ b/src/uca-plugin-manager.c @@ -8,6 +8,9 @@ * instantiated with uca_plugin_manager_get_filter() with a one-to-one mapping * between filter name xyz and module name libfilterxyz.so. Any errors are * reported as one of #UcaPluginManagerError codes. + * + * By default, any path listed in the %UCA_CAMERA_PATH environment variable is + * added to the search path. */ #include #include "uca-plugin-manager.h" @@ -251,10 +254,16 @@ static void uca_plugin_manager_init (UcaPluginManager *manager) { UcaPluginManagerPrivate *priv; + const gchar *uca_camera_path; manager->priv = priv = UCA_PLUGIN_MANAGER_GET_PRIVATE (manager); priv->search_paths = NULL; + uca_camera_path = g_getenv ("UCA_CAMERA_PATH"); + + if (uca_camera_path != NULL) + uca_plugin_manager_add_path (manager, uca_camera_path); + uca_plugin_manager_add_path (manager, "/usr/lib/uca"); uca_plugin_manager_add_path (manager, "/usr/lib64/uca"); uca_plugin_manager_add_path (manager, "/usr/local/lib/uca"); -- cgit v1.2.3 From 6dd3229337aa1920d266fbd2c4001fb7c65f5cf1 Mon Sep 17 00:00:00 2001 From: Matthias Vogelgesang Date: Wed, 19 Sep 2012 18:04:32 +0200 Subject: Make most cameras plugins --- src/CMakeLists.txt | 104 ++++++++------- src/cameras/uca-mock-camera.c | 30 ++--- src/cameras/uca-mock-camera.h | 2 - src/cameras/uca-pco-camera.c | 304 +++++++++++++++++++++--------------------- src/cameras/uca-pco-camera.h | 2 - src/cameras/uca-pf-camera.c | 102 +++++++------- src/cameras/uca-pf-camera.h | 2 - src/cameras/uca-ufo-camera.c | 6 +- src/cameras/uca-ufo-camera.h | 2 - src/uca-camera.c | 113 ---------------- src/uca-plugin-manager.c | 217 +++++++++++++++++------------- test/CMakeLists.txt | 4 +- test/benchmark.c | 9 +- test/grab.c | 40 +++--- 14 files changed, 435 insertions(+), 502 deletions(-) (limited to 'src') diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 1b814aa..42f9dd8 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -31,10 +31,25 @@ find_package(PkgConfig) find_program(GLIB2_MKENUMS glib-mkenums REQUIRED) pkg_check_modules(GLIB2 glib-2.0>=2.24 REQUIRED) pkg_check_modules(GOBJECT2 gobject-2.0>=2.24 REQUIRED) +pkg_check_modules(GMODULE2 gmodule-2.0>=2.24 REQUIRED) + +include_directories( + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/cameras + ${GLIB2_INCLUDE_DIRS} + ${GOBJECT2_INCLUDE_DIRS}) + +# --- Configure step +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config.h.in + ${CMAKE_CURRENT_BINARY_DIR}/config.h) set(uca_LIBS - ${GLIB2_LIBRARIES} - ${GOBJECT2_LIBRARIES}) + ${GLIB2_LIBRARIES} + ${GOBJECT2_LIBRARIES} + ${GMODULE2_LIBRARIES}) + +set(uca_enum_hdrs uca-camera.h) # --- Build options ----------------------------------------------------------- option(HAVE_MOCK_CAMERA "Camera: Dummy" ON) @@ -45,18 +60,20 @@ if (PF_FOUND) option(HAVE_PHOTON_FOCUS "Camera: Photon Focus MV2-D1280-640-CL-8" ON) if (HAVE_PHOTON_FOCUS AND CLSERME4_FOUND AND FGLIB5_FOUND) - list(APPEND uca_SRCS cameras/uca-pf-camera.c) - list(APPEND uca_HDRS cameras/uca-pf-camera.h) - list(APPEND cameras "Pf") - - set(uca_LIBS ${uca_LIBS} - ${CLSERME4_LIBRARY} - ${FGLIB5_LIBRARY} - ${PF_LIBRARIES}) + list(APPEND uca_enum_hdrs cameras/uca-pf-camera.h) - include_directories(${PF_INCLUDE_DIRS} + include_directories( + ${PF_INCLUDE_DIRS} ${CLSERME4_INCLUDE_DIR} ${FGLIB5_INCLUDE_DIR}) + + add_library(ucapf SHARED cameras/uca-pf-camera.c) + + target_link_libraries(ucapf + ${uca_LIBS} + ${CLSERME4_LIBRARY} + ${FGLIB5_LIBRARY} + ${PF_LIBRARIES}) endif() endif() @@ -64,19 +81,23 @@ if (PCO_FOUND AND CLSERME4_FOUND AND FGLIB5_FOUND) option(HAVE_PCO_CL "Camera: CameraLink-based pco" ON) if (HAVE_PCO_CL) - list(APPEND uca_SRCS cameras/uca-pco-camera.c) - list(APPEND uca_HDRS cameras/uca-pco-camera.h) - list(APPEND cameras "Pco") - - set(uca_LIBS ${uca_LIBS} - ${PCO_LIBRARIES} - ${CLSERME4_LIBRARY} - ${FGLIB5_LIBRARY}) + list(APPEND uca_enum_hdrs cameras/uca-pco-camera.h) include_directories( ${PCO_INCLUDE_DIRS} ${CLSERME4_INCLUDE_DIR} ${FGLIB5_INCLUDE_DIR}) + + add_library(ucapco SHARED cameras/uca-pco-camera.c) + + target_link_libraries(ucapco + ${uca_LIBS} + ${PCO_LIBRARIES} + ${CLSERME4_LIBRARY} + ${FGLIB5_LIBRARY}) + + install(TARGETS ucapco + LIBRARY DESTINATION ${LIB_INSTALL_DIR}/uca) endif() endif() @@ -84,13 +105,18 @@ if (IPE_FOUND) option(HAVE_UFO_CAMERA "Camera: Custom based on Xilinx FPGA" ON) if (HAVE_UFO_CAMERA) - list(APPEND uca_SRCS cameras/uca-ufo-camera.c) - list(APPEND uca_HDRS cameras/uca-ufo-camera.h) - list(APPEND cameras "Ufo") - - set(uca_LIBS ${uca_LIBS} ${IPE_LIBRARIES}) + list(APPEND uca_enum_hdrs cameras/uca-ufo-camera.h) include_directories(${IPE_INCLUDE_DIRS}) + + add_library(ucaufo SHARED cameras/uca-ufo-camera.c) + target_link_libraries(ucaufo + ${uca_LIBS} + ${IPE_LIBRARIES} + ) + + install(TARGETS ucaufo + LIBRARY DESTINATION ${LIB_INSTALL_DIR}/uca) endif() endif() @@ -111,9 +137,6 @@ endif() if (HAVE_MOCK_CAMERA) add_library(ucamock SHARED cameras/uca-mock-camera.c) - #list(APPEND uca_SRCS cameras/uca-mock-camera.c) - ##list(APPEND uca_HDRS cameras/uca-mock-camera.h) - #list(APPEND cameras "Mock") install(TARGETS ucamock LIBRARY DESTINATION ${LIB_INSTALL_DIR}/uca) endif() @@ -124,9 +147,9 @@ add_custom_command( COMMAND ${GLIB2_MKENUMS} ARGS --template uca-enums.h.template - ${uca_HDRS} > ${CMAKE_CURRENT_BINARY_DIR}/uca-enums.h + ${uca_enum_hdrs} > ${CMAKE_CURRENT_BINARY_DIR}/uca-enums.h WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} - DEPENDS ${uca_HDRS} + DEPENDS ${uca_enum_hdrs} ${CMAKE_CURRENT_SOURCE_DIR}/uca-enums.h.template) add_custom_command( @@ -134,29 +157,18 @@ add_custom_command( COMMAND ${GLIB2_MKENUMS} ARGS --template uca-enums.c.template - ${uca_HDRS} > ${CMAKE_CURRENT_BINARY_DIR}/uca-enums.c + ${uca_enum_hdrs} > ${CMAKE_CURRENT_BINARY_DIR}/uca-enums.c WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} - DEPENDS ${uca_HDRS} + DEPENDS ${uca_enum_hdrs} ${CMAKE_CURRENT_BINARY_DIR}/uca-enums.h ${CMAKE_CURRENT_SOURCE_DIR}/uca-enums.c.template ) -# --- Configure step -configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config.h.in - ${CMAKE_CURRENT_BINARY_DIR}/config.h) - -include_directories( - ${CMAKE_CURRENT_BINARY_DIR} - ${CMAKE_CURRENT_SOURCE_DIR} - ${CMAKE_CURRENT_SOURCE_DIR}/cameras - ${GLIB2_INCLUDE_DIRS} - ${GOBJECT2_INCLUDE_DIRS}) - # --- Build target ------------------------------------------------------------ add_definitions("-std=c99 -Wall") -add_library(uca SHARED - ${uca_SRCS} +add_library(uca SHARED + ${uca_SRCS} ${CMAKE_CURRENT_BINARY_DIR}/uca-enums.c) set_target_properties(uca PROPERTIES @@ -177,7 +189,7 @@ if(GTK_DOC_FOUND) set(docs_out "${docs_dir}/reference") file(MAKE_DIRECTORY ${docs_out}) - set(reference_files + set(reference_files "${docs_out}/index.html" "${docs_out}/api-index-full.html" "${docs_out}/ch01.html" @@ -261,7 +273,7 @@ set(LIB_INSTALL_DIR "lib${LIB_SUFFIX}") install(TARGETS uca LIBRARY DESTINATION ${LIB_INSTALL_DIR}) -install(FILES ${uca_HDRS} +install(FILES ${uca_HDRS} DESTINATION include/uca) # --- install pkg-config file diff --git a/src/cameras/uca-mock-camera.c b/src/cameras/uca-mock-camera.c index 59c5ae8..7cd4689 100644 --- a/src/cameras/uca-mock-camera.c +++ b/src/cameras/uca-mock-camera.c @@ -15,6 +15,7 @@ with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA */ +#include #include #include "uca-mock-camera.h" @@ -156,20 +157,6 @@ static void print_current_frame(UcaMockCameraPrivate *priv, gchar *buffer) } } -/** - * uca_mock_camera_new: - * @error: Location for error - * - * Create a new #UcaMockCamera object. - * - * Returns: A newly created #UcaMockCamera object - */ -UcaMockCamera *uca_mock_camera_new(GError **error) -{ - UcaMockCamera *camera = g_object_new(UCA_TYPE_MOCK_CAMERA, NULL); - return camera; -} - static gpointer mock_grab_func(gpointer data) { UcaMockCamera *mock_camera = UCA_MOCK_CAMERA(data); @@ -208,7 +195,7 @@ static void uca_mock_camera_start_recording(UcaCamera *camera, GError **error) if (transfer_async) { GError *tmp_error = NULL; priv->thread_running = TRUE; - priv->grab_thread = g_thread_create(mock_grab_func, camera, TRUE, &tmp_error); + priv->grab_thread = g_thread_create(mock_grab_func, camera, TRUE, &tmp_error); if (tmp_error != NULL) { priv->thread_running = FALSE; @@ -232,7 +219,7 @@ static void uca_mock_camera_stop_recording(UcaCamera *camera, GError **error) NULL); if (transfer_async) { - priv->thread_running = FALSE; + priv->thread_running = FALSE; g_thread_join(priv->grab_thread); } } @@ -358,7 +345,7 @@ static void uca_mock_camera_finalize(GObject *object) UcaMockCameraPrivate *priv = UCA_MOCK_CAMERA_GET_PRIVATE(object); if (priv->thread_running) { - priv->thread_running = FALSE; + priv->thread_running = FALSE; g_thread_join(priv->grab_thread); } @@ -383,7 +370,7 @@ static void uca_mock_camera_class_init(UcaMockCameraClass *klass) for (guint i = 0; mock_overrideables[i] != 0; i++) g_object_class_override_property(gobject_class, mock_overrideables[i], uca_camera_props[mock_overrideables[i]]); - mock_properties[PROP_FRAMERATE] = + mock_properties[PROP_FRAMERATE] = g_param_spec_float("frame-rate", "Frame rate", "Number of frames per second that are taken", @@ -413,3 +400,10 @@ static void uca_mock_camera_init(UcaMockCamera *self) g_value_set_uint(&val, 1); g_value_array_append(self->priv->binnings, &val); } + +G_MODULE_EXPORT UcaCamera * +uca_camera_impl_new (GError **error) +{ + UcaCamera *camera = UCA_CAMERA (g_object_new (UCA_TYPE_MOCK_CAMERA, NULL)); + return camera; +} diff --git a/src/cameras/uca-mock-camera.h b/src/cameras/uca-mock-camera.h index 92030f8..9ee9190 100644 --- a/src/cameras/uca-mock-camera.h +++ b/src/cameras/uca-mock-camera.h @@ -58,8 +58,6 @@ struct _UcaMockCameraClass { UcaCameraClass parent; }; -UcaMockCamera *uca_mock_camera_new(GError **error); - GType uca_mock_camera_get_type(void); G_END_DECLS diff --git a/src/cameras/uca-pco-camera.c b/src/cameras/uca-pco-camera.c index a56392f..8bf2936 100644 --- a/src/cameras/uca-pco-camera.c +++ b/src/cameras/uca-pco-camera.c @@ -15,6 +15,7 @@ with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA */ +#include #include #include #include @@ -50,7 +51,7 @@ "libpco error %x", err); \ return; \ } - + #define UCA_PCO_CAMERA_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), UCA_TYPE_PCO_CAMERA, UcaPcoCameraPrivate)) G_DEFINE_TYPE(UcaPcoCamera, uca_pco_camera, UCA_TYPE_CAMERA) @@ -186,7 +187,7 @@ struct _UcaPcoCameraPrivate { guint current_image; }; -static pco_cl_map_entry pco_cl_map[] = { +static pco_cl_map_entry pco_cl_map[] = { { CAMERATYPE_PCO_EDGE, "libFullAreaGray8.so", FG_CL_8BIT_FULL_10, FG_GRAY, 30.0f, FALSE }, { CAMERATYPE_PCO4000, "libDualAreaGray16.so", FG_CL_SINGLETAP_16_BIT, FG_GRAY16, 5.0f, TRUE }, { CAMERATYPE_PCO_DIMAX_STD, "libFullAreaGray16.so", FG_CL_SINGLETAP_8_BIT, FG_GRAY16, 1279.0f, TRUE }, @@ -200,7 +201,7 @@ static pco_cl_map_entry *get_pco_cl_map_entry(int camera_type) while (entry->camera_type != 0) { if (entry->camera_type == camera_type) return entry; - entry++; + entry++; } return NULL; @@ -212,8 +213,8 @@ static guint fill_binnings(UcaPcoCameraPrivate *priv) uint16_t *vertical = NULL; guint num_horizontal, num_vertical; - guint err = pco_get_possible_binnings(priv->pco, - &horizontal, &num_horizontal, + guint err = pco_get_possible_binnings(priv->pco, + &horizontal, &num_horizontal, &vertical, &num_vertical); GValue val = {0}; @@ -246,7 +247,7 @@ static void fill_pixelrates(UcaPcoCameraPrivate *priv, guint32 rates[4], gint nu priv->pixelrates = g_value_array_new(num_rates); for (gint i = 0; i < num_rates; i++) { - g_value_set_uint(&val, (guint) rates[i]); + g_value_set_uint(&val, (guint) rates[i]); g_value_array_append(priv->pixelrates, &val); } } @@ -315,93 +316,6 @@ static gdouble get_suitable_timebase(gdouble time) return TIMEBASE_INVALID; } -UcaPcoCamera *uca_pco_camera_new(GError **error) -{ - pco_handle pco = pco_init(); - - if (pco == NULL) { - g_set_error(error, UCA_PCO_CAMERA_ERROR, UCA_PCO_CAMERA_ERROR_LIBPCO_INIT, - "Initializing libpco failed"); - return NULL; - } - - UcaPcoCamera *camera = g_object_new(UCA_TYPE_PCO_CAMERA, NULL); - UcaPcoCameraPrivate *priv = UCA_PCO_CAMERA_GET_PRIVATE(camera); - priv->pco = pco; - - pco_get_resolution(priv->pco, &priv->width, &priv->height, &priv->width_ex, &priv->height_ex); - pco_get_binning(priv->pco, &priv->binning_h, &priv->binning_v); - pco_set_storage_mode(pco, STORAGE_MODE_RECORDER); - pco_set_auto_transfer(pco, 1); - - guint16 roi[4]; - pco_get_roi(priv->pco, roi); - pco_get_roi_steps(priv->pco, &priv->roi_horizontal_steps, &priv->roi_vertical_steps); - - priv->roi_x = roi[0] - 1; - priv->roi_y = roi[1] - 1; - priv->roi_width = roi[2] - roi[0] + 1; - priv->roi_height = roi[3] - roi[1] + 1; - - guint16 camera_type, camera_subtype; - pco_get_camera_type(priv->pco, &camera_type, &camera_subtype); - pco_cl_map_entry *map_entry = get_pco_cl_map_entry(camera_type); - priv->camera_description = map_entry; - - if (map_entry == NULL) { - g_set_error(error, UCA_PCO_CAMERA_ERROR, UCA_PCO_CAMERA_ERROR_UNSUPPORTED, - "Camera type is not supported"); - g_object_unref(camera); - return NULL; - } - - priv->fg_port = PORT_A; - priv->fg = Fg_Init(map_entry->so_file, priv->fg_port); - - if (priv->fg == NULL) { - g_set_error(error, UCA_PCO_CAMERA_ERROR, UCA_PCO_CAMERA_ERROR_FG_INIT, - "%s", Fg_getLastErrorDescription(priv->fg)); - g_object_unref(camera); - return NULL; - } - - const guint32 fg_height = priv->height; - const guint32 fg_width = camera_type == CAMERATYPE_PCO_EDGE ? priv->width * 2 : priv->width; - - FG_TRY_PARAM(priv->fg, camera, FG_CAMERA_LINK_CAMTYP, &map_entry->cl_type, priv->fg_port); - FG_TRY_PARAM(priv->fg, camera, FG_FORMAT, &map_entry->cl_format, priv->fg_port); - FG_TRY_PARAM(priv->fg, camera, FG_WIDTH, &fg_width, priv->fg_port); - FG_TRY_PARAM(priv->fg, camera, FG_HEIGHT, &fg_height, priv->fg_port); - - int val = FREE_RUN; - FG_TRY_PARAM(priv->fg, camera, FG_TRIGGERMODE, &val, priv->fg_port); - - fill_binnings(priv); - - /* - * Here we override property ranges because we didn't know them at property - * installation time. - */ - GObjectClass *camera_class = G_OBJECT_CLASS (UCA_CAMERA_GET_CLASS (camera)); - property_override_default_guint_value (camera_class, "roi-width", priv->width); - property_override_default_guint_value (camera_class, "roi-height", priv->height); - - guint32 rates[4] = {0}; - gint num_rates = 0; - - if (pco_get_available_pixelrates(priv->pco, rates, &num_rates) == PCO_NOERROR) { - GObjectClass *pco_camera_class = G_OBJECT_CLASS (UCA_PCO_CAMERA_GET_CLASS (camera)); - - fill_pixelrates(priv, rates, num_rates); - property_override_default_guint_value (pco_camera_class, "sensor-pixelrate", rates[0]); - } - - override_temperature_range (priv); - override_maximum_adcs (priv); - - return camera; -} - static int fg_callback(frameindex_t frame, struct fg_apc_data *apc) { UcaCamera *camera = UCA_CAMERA(apc); @@ -506,7 +420,7 @@ static void uca_pco_camera_start_recording(UcaCamera *camera, GError **error) Fg_FreeMemEx(priv->fg, priv->fg_mem); const guint num_buffers = 2; - priv->fg_mem = Fg_AllocMemEx(priv->fg, + priv->fg_mem = Fg_AllocMemEx(priv->fg, num_buffers * priv->frame_width * priv->frame_height * sizeof(uint16_t), num_buffers); if (priv->fg_mem == NULL) { @@ -557,9 +471,9 @@ static void uca_pco_camera_start_readout(UcaCamera *camera, GError **error) g_return_if_fail(UCA_IS_PCO_CAMERA(camera)); UcaPcoCameraPrivate *priv = UCA_PCO_CAMERA_GET_PRIVATE(camera); - /* + /* * TODO: Check if readout mode is possible. This is not the case for the - * edge. + * edge. */ guint err = pco_get_active_segment(priv->pco, &priv->active_segment); @@ -582,7 +496,7 @@ static void uca_pco_camera_trigger(UcaCamera *camera, GError **error) if (!success) g_set_error(error, UCA_PCO_CAMERA_ERROR, UCA_PCO_CAMERA_ERROR_LIBPCO_GENERAL, - "Could not trigger frame acquisition"); + "Could not trigger frame acquisition"); } static void uca_pco_camera_grab(UcaCamera *camera, gpointer *data, GError **error) @@ -611,7 +525,7 @@ static void uca_pco_camera_grab(UcaCamera *camera, gpointer *data, GError **erro pco_request_image(priv->pco); priv->last_frame = Fg_getLastPicNumberBlockingEx(priv->fg, priv->last_frame+1, priv->fg_port, MAX_TIMEOUT, priv->fg_mem); - + if (priv->last_frame <= 0) { guint err = FG_OK + 1; FG_SET_ERROR(err, priv->fg, UCA_PCO_CAMERA_ERROR_FG_GENERAL); @@ -620,7 +534,7 @@ static void uca_pco_camera_grab(UcaCamera *camera, gpointer *data, GError **erro guint16 *frame = Fg_getImagePtrEx(priv->fg, priv->last_frame, priv->fg_port, priv->fg_mem); if (*data == NULL) - *data = g_malloc0(priv->frame_width * priv->frame_height * priv->num_bytes); + *data = g_malloc0(priv->frame_width * priv->frame_height * priv->num_bytes); if (priv->camera_description->camera_type == CAMERATYPE_PCO_EDGE) pco_get_reorder_func(priv->pco)((guint16 *) *data, frame, priv->frame_width, priv->frame_height); @@ -635,7 +549,7 @@ static void uca_pco_camera_set_property(GObject *object, guint property_id, cons switch (property_id) { case PROP_SENSOR_EXTENDED: { - guint16 format = g_value_get_boolean (value) ? SENSORFORMAT_EXTENDED : SENSORFORMAT_STANDARD; + guint16 format = g_value_get_boolean (value) ? SENSORFORMAT_EXTENDED : SENSORFORMAT_STANDARD; pco_set_sensor_format(priv->pco, format); } break; @@ -651,7 +565,7 @@ static void uca_pco_camera_set_property(GObject *object, guint property_id, cons case PROP_ROI_WIDTH: { guint width = g_value_get_uint(value); - + if (width % priv->roi_horizontal_steps) g_warning("ROI width %i is not a multiple of %i", width, priv->roi_horizontal_steps); else @@ -662,7 +576,7 @@ static void uca_pco_camera_set_property(GObject *object, guint property_id, cons case PROP_ROI_HEIGHT: { guint height = g_value_get_uint(value); - + if (height % priv->roi_vertical_steps) g_warning("ROI height %i is not a multiple of %i", height, priv->roi_vertical_steps); else @@ -681,7 +595,7 @@ static void uca_pco_camera_set_property(GObject *object, guint property_id, cons case PROP_EXPOSURE_TIME: { const gdouble time = g_value_get_double(value); - + if (priv->exposure_timebase == TIMEBASE_INVALID) read_timebase(priv); @@ -692,7 +606,7 @@ static void uca_pco_camera_set_property(GObject *object, guint property_id, cons guint16 suitable_timebase = get_suitable_timebase(time); if (suitable_timebase == TIMEBASE_INVALID) { - g_warning("Cannot set such a small exposure time"); + g_warning("Cannot set such a small exposure time"); } else { if (suitable_timebase != priv->exposure_timebase) { @@ -712,7 +626,7 @@ static void uca_pco_camera_set_property(GObject *object, guint property_id, cons case PROP_DELAY_TIME: { const gdouble time = g_value_get_double(value); - + if (priv->delay_timebase == TIMEBASE_INVALID) read_timebase(priv); @@ -733,7 +647,7 @@ static void uca_pco_camera_set_property(GObject *object, guint property_id, cons g_warning("Cannot set zero delay time"); } else - g_warning("Cannot set such a small exposure time"); + g_warning("Cannot set such a small exposure time"); } else { if (suitable_timebase != priv->delay_timebase) { @@ -752,7 +666,7 @@ static void uca_pco_camera_set_property(GObject *object, guint property_id, cons case PROP_SENSOR_ADCS: { - const guint num_adcs = g_value_get_uint(value); + const guint num_adcs = g_value_get_uint(value); if (pco_set_adc_mode(priv->pco, num_adcs) != PCO_NOERROR) g_warning("Cannot set the number of ADCs per pixel\n"); } @@ -765,7 +679,7 @@ static void uca_pco_camera_set_property(GObject *object, guint property_id, cons for (guint i = 0; i < priv->pixelrates->n_values; i++) { if (g_value_get_uint(g_value_array_get_nth(priv->pixelrates, i)) == desired_pixel_rate) { - pixel_rate = desired_pixel_rate; + pixel_rate = desired_pixel_rate; break; } } @@ -792,7 +706,7 @@ static void uca_pco_camera_set_property(GObject *object, guint property_id, cons case PROP_COOLING_POINT: { - int16_t temperature = (int16_t) g_value_get_int(value); + int16_t temperature = (int16_t) g_value_get_int(value); pco_set_cooling_temperature(priv->pco, temperature); } break; @@ -856,11 +770,11 @@ static void uca_pco_camera_set_property(GObject *object, guint property_id, cons case PROP_TIMESTAMP_MODE: { guint16 modes[] = { - TIMESTAMP_MODE_OFF, /* 0 */ - TIMESTAMP_MODE_BINARY, /* 1 = 1 << 0 */ - TIMESTAMP_MODE_ASCII, /* 2 = 1 << 1 */ - TIMESTAMP_MODE_BINARYANDASCII, /* 3 = 1 << 0 | 1 << 1 */ - }; + TIMESTAMP_MODE_OFF, /* 0 */ + TIMESTAMP_MODE_BINARY, /* 1 = 1 << 0 */ + TIMESTAMP_MODE_ASCII, /* 2 = 1 << 1 */ + TIMESTAMP_MODE_BINARYANDASCII, /* 3 = 1 << 0 | 1 << 1 */ + }; pco_set_timestamp_mode(priv->pco, modes[g_value_get_flags(value)]); } break; @@ -878,25 +792,25 @@ static void uca_pco_camera_get_property(GObject *object, guint property_id, GVal switch (property_id) { case PROP_SENSOR_EXTENDED: { - guint16 format; + guint16 format; pco_get_sensor_format(priv->pco, &format); g_value_set_boolean(value, format == SENSORFORMAT_EXTENDED); } break; - case PROP_SENSOR_WIDTH: + case PROP_SENSOR_WIDTH: g_value_set_uint(value, priv->width); break; - case PROP_SENSOR_HEIGHT: + case PROP_SENSOR_HEIGHT: g_value_set_uint(value, priv->height); break; - case PROP_SENSOR_WIDTH_EXTENDED: + case PROP_SENSOR_WIDTH_EXTENDED: g_value_set_uint(value, priv->width_ex < priv->width ? priv->width : priv->width_ex); break; - case PROP_SENSOR_HEIGHT_EXTENDED: + case PROP_SENSOR_HEIGHT_EXTENDED: g_value_set_uint(value, priv->height_ex < priv->height ? priv->height : priv->height_ex); break; @@ -926,7 +840,7 @@ static void uca_pco_camera_get_property(GObject *object, guint property_id, GVal case PROP_SENSOR_TEMPERATURE: { - gint32 ccd, camera, power; + gint32 ccd, camera, power; pco_get_temperature(priv->pco, &ccd, &camera, &power); g_value_set_double(value, ccd / 10.0); } @@ -938,7 +852,7 @@ static void uca_pco_camera_get_property(GObject *object, guint property_id, GVal * Up to now, the ADC mode corresponds directly to the number of * ADCs in use. */ - pco_adc_mode mode; + pco_adc_mode mode; if (pco_get_adc_mode(priv->pco, &mode) != PCO_NOERROR) g_warning("Cannot read number of ADCs per pixel"); g_value_set_uint(value, mode); @@ -958,7 +872,7 @@ static void uca_pco_camera_get_property(GObject *object, guint property_id, GVal case PROP_SENSOR_PIXELRATE: { - guint32 pixelrate; + guint32 pixelrate; pco_get_pixelrate(priv->pco, &pixelrate); g_value_set_uint(value, pixelrate); } @@ -1048,7 +962,7 @@ static void uca_pco_camera_get_property(GObject *object, guint property_id, GVal case PROP_TRIGGER_MODE: { - guint16 mode; + guint16 mode; pco_get_trigger_mode(priv->pco, &mode); switch (mode) { @@ -1091,7 +1005,7 @@ static void uca_pco_camera_get_property(GObject *object, guint property_id, GVal g_value_set_uint(value, priv->roi_vertical_steps); break; - case PROP_NAME: + case PROP_NAME: { gchar *name = NULL; pco_get_name(priv->pco, &name); @@ -1102,7 +1016,7 @@ static void uca_pco_camera_get_property(GObject *object, guint property_id, GVal case PROP_COOLING_POINT: { - int16_t temperature; + int16_t temperature; if (pco_get_cooling_temperature(priv->pco, &temperature) != PCO_NOERROR) g_warning("Cannot read cooling temperature\n"); g_value_set_int(value, temperature); @@ -1140,7 +1054,7 @@ static void uca_pco_camera_get_property(GObject *object, guint property_id, GVal case PROP_TIMESTAMP_MODE: { - guint16 mode; + guint16 mode; pco_get_timestamp_mode(priv->pco, &mode); switch (mode) { @@ -1151,7 +1065,7 @@ static void uca_pco_camera_get_property(GObject *object, guint property_id, GVal g_value_set_flags(value, UCA_PCO_CAMERA_TIMESTAMP_BINARY); break; case TIMESTAMP_MODE_BINARYANDASCII: - g_value_set_flags(value, + g_value_set_flags(value, UCA_PCO_CAMERA_TIMESTAMP_BINARY | UCA_PCO_CAMERA_TIMESTAMP_ASCII); break; case TIMESTAMP_MODE_ASCII: @@ -1220,20 +1134,20 @@ static void uca_pco_camera_class_init(UcaPcoCameraClass *klass) * #UcaPcoCamera:sensor-height-extended to query the resolution of the * larger area. */ - pco_properties[PROP_SENSOR_EXTENDED] = + pco_properties[PROP_SENSOR_EXTENDED] = g_param_spec_boolean("sensor-extended", "Use extended sensor format", "Use extended sensor format", FALSE, G_PARAM_READWRITE); - pco_properties[PROP_SENSOR_WIDTH_EXTENDED] = + pco_properties[PROP_SENSOR_WIDTH_EXTENDED] = g_param_spec_uint("sensor-width-extended", "Width of extended sensor", "Width of the extended sensor in pixels", 1, G_MAXUINT, 1, G_PARAM_READABLE); - pco_properties[PROP_SENSOR_HEIGHT_EXTENDED] = + pco_properties[PROP_SENSOR_HEIGHT_EXTENDED] = g_param_spec_uint("sensor-height-extended", "Height of extended sensor", "Height of the extended sensor in pixels", @@ -1248,21 +1162,21 @@ static void uca_pco_camera_class_init(UcaPcoCameraClass *klass) * #UcaPcoCamera:sensor-pixelrates property. Any other value will be * rejected by the camera. */ - pco_properties[PROP_SENSOR_PIXELRATE] = + pco_properties[PROP_SENSOR_PIXELRATE] = g_param_spec_uint("sensor-pixelrate", "Pixel rate", "Pixel rate", 1, G_MAXUINT, 1, G_PARAM_READWRITE); - pco_properties[PROP_SENSOR_PIXELRATES] = + pco_properties[PROP_SENSOR_PIXELRATES] = g_param_spec_value_array("sensor-pixelrates", "Array of possible sensor pixel rates", "Array of possible sensor pixel rates", pco_properties[PROP_SENSOR_PIXELRATE], G_PARAM_READABLE); - pco_properties[PROP_NAME] = + pco_properties[PROP_NAME] = g_param_spec_string("name", "Name of the camera", "Name of the camera", @@ -1275,38 +1189,38 @@ static void uca_pco_camera_class_init(UcaPcoCameraClass *klass) -G_MAXDOUBLE, G_MAXDOUBLE, 0.0, G_PARAM_READABLE); - pco_properties[PROP_HAS_DOUBLE_IMAGE_MODE] = + pco_properties[PROP_HAS_DOUBLE_IMAGE_MODE] = g_param_spec_boolean("has-double-image-mode", "Is double image mode supported by this model", "Is double image mode supported by this model", FALSE, G_PARAM_READABLE); - pco_properties[PROP_DOUBLE_IMAGE_MODE] = + pco_properties[PROP_DOUBLE_IMAGE_MODE] = g_param_spec_boolean("double-image-mode", "Use double image mode", "Use double image mode", FALSE, G_PARAM_READWRITE); - pco_properties[PROP_OFFSET_MODE] = + pco_properties[PROP_OFFSET_MODE] = g_param_spec_boolean("offset-mode", "Use offset mode", "Use offset mode", FALSE, G_PARAM_READWRITE); - pco_properties[PROP_RECORD_MODE] = - g_param_spec_enum("record-mode", + pco_properties[PROP_RECORD_MODE] = + g_param_spec_enum("record-mode", "Record mode", "Record mode", UCA_TYPE_PCO_CAMERA_RECORD_MODE, UCA_PCO_CAMERA_RECORD_MODE_SEQUENCE, G_PARAM_READWRITE); - pco_properties[PROP_ACQUIRE_MODE] = - g_param_spec_enum("acquire-mode", + pco_properties[PROP_ACQUIRE_MODE] = + g_param_spec_enum("acquire-mode", "Acquire mode", "Acquire mode", UCA_TYPE_PCO_CAMERA_ACQUIRE_MODE, UCA_PCO_CAMERA_ACQUIRE_MODE_AUTO, G_PARAM_READWRITE); - + pco_properties[PROP_DELAY_TIME] = g_param_spec_double("delay-time", "Delay time", @@ -1314,7 +1228,7 @@ static void uca_pco_camera_class_init(UcaPcoCameraClass *klass) 0.0, G_MAXDOUBLE, 0.0, G_PARAM_READWRITE); - pco_properties[PROP_NOISE_FILTER] = + pco_properties[PROP_NOISE_FILTER] = g_param_spec_boolean("noise-filter", "Noise filter", "Noise filter", @@ -1327,42 +1241,42 @@ static void uca_pco_camera_class_init(UcaPcoCameraClass *klass) * the camera and just don't know the cooling range. We override these * values in #uca_pco_camera_new(). */ - pco_properties[PROP_COOLING_POINT] = + pco_properties[PROP_COOLING_POINT] = g_param_spec_int("cooling-point", "Cooling point of the camera", "Cooling point of the camera in degree celsius", 0, 10, 5, G_PARAM_READWRITE); - pco_properties[PROP_COOLING_POINT_MIN] = + pco_properties[PROP_COOLING_POINT_MIN] = g_param_spec_int("cooling-point-min", "Minimum cooling point", "Minimum cooling point in degree celsius", G_MININT, G_MAXINT, 0, G_PARAM_READABLE); - pco_properties[PROP_COOLING_POINT_MAX] = + pco_properties[PROP_COOLING_POINT_MAX] = g_param_spec_int("cooling-point-max", "Maximum cooling point", "Maximum cooling point in degree celsius", G_MININT, G_MAXINT, 0, G_PARAM_READABLE); - pco_properties[PROP_COOLING_POINT_DEFAULT] = + pco_properties[PROP_COOLING_POINT_DEFAULT] = g_param_spec_int("cooling-point-default", "Default cooling point", "Default cooling point in degree celsius", G_MININT, G_MAXINT, 0, G_PARAM_READABLE); - - pco_properties[PROP_SENSOR_ADCS] = + + pco_properties[PROP_SENSOR_ADCS] = g_param_spec_uint("sensor-adcs", "Number of ADCs to use", "Number of ADCs to use", - 1, 2, 1, + 1, 2, 1, G_PARAM_READWRITE); - pco_properties[PROP_SENSOR_MAX_ADCS] = + pco_properties[PROP_SENSOR_MAX_ADCS] = g_param_spec_uint("sensor-max-adcs", "Maximum number of ADCs", "Maximum number of ADCs that can be set with \"sensor-adcs\"", - 1, G_MAXUINT, 1, + 1, G_MAXUINT, 1, G_PARAM_READABLE); pco_properties[PROP_TIMESTAMP_MODE] = @@ -1394,3 +1308,91 @@ static void uca_pco_camera_init(UcaPcoCamera *self) self->priv->delay_timebase = TIMEBASE_INVALID; self->priv->exposure_timebase = TIMEBASE_INVALID; } + +G_MODULE_EXPORT UcaCamera * +uca_camera_impl_new (GError **error) +{ + pco_handle pco = pco_init(); + + if (pco == NULL) { + g_set_error(error, UCA_PCO_CAMERA_ERROR, UCA_PCO_CAMERA_ERROR_LIBPCO_INIT, + "Initializing libpco failed"); + return NULL; + } + + UcaPcoCamera *camera = g_object_new(UCA_TYPE_PCO_CAMERA, NULL); + UcaPcoCameraPrivate *priv = UCA_PCO_CAMERA_GET_PRIVATE(camera); + priv->pco = pco; + + pco_get_resolution(priv->pco, &priv->width, &priv->height, &priv->width_ex, &priv->height_ex); + pco_get_binning(priv->pco, &priv->binning_h, &priv->binning_v); + pco_set_storage_mode(pco, STORAGE_MODE_RECORDER); + pco_set_auto_transfer(pco, 1); + + guint16 roi[4]; + pco_get_roi(priv->pco, roi); + pco_get_roi_steps(priv->pco, &priv->roi_horizontal_steps, &priv->roi_vertical_steps); + + priv->roi_x = roi[0] - 1; + priv->roi_y = roi[1] - 1; + priv->roi_width = roi[2] - roi[0] + 1; + priv->roi_height = roi[3] - roi[1] + 1; + + guint16 camera_type, camera_subtype; + pco_get_camera_type(priv->pco, &camera_type, &camera_subtype); + pco_cl_map_entry *map_entry = get_pco_cl_map_entry(camera_type); + priv->camera_description = map_entry; + + if (map_entry == NULL) { + g_set_error(error, UCA_PCO_CAMERA_ERROR, UCA_PCO_CAMERA_ERROR_UNSUPPORTED, + "Camera type is not supported"); + g_object_unref(camera); + return NULL; + } + + priv->fg_port = PORT_A; + priv->fg = Fg_Init(map_entry->so_file, priv->fg_port); + + if (priv->fg == NULL) { + g_set_error(error, UCA_PCO_CAMERA_ERROR, UCA_PCO_CAMERA_ERROR_FG_INIT, + "%s", Fg_getLastErrorDescription(priv->fg)); + g_object_unref(camera); + return NULL; + } + + const guint32 fg_height = priv->height; + const guint32 fg_width = camera_type == CAMERATYPE_PCO_EDGE ? priv->width * 2 : priv->width; + + FG_TRY_PARAM(priv->fg, camera, FG_CAMERA_LINK_CAMTYP, &map_entry->cl_type, priv->fg_port); + FG_TRY_PARAM(priv->fg, camera, FG_FORMAT, &map_entry->cl_format, priv->fg_port); + FG_TRY_PARAM(priv->fg, camera, FG_WIDTH, &fg_width, priv->fg_port); + FG_TRY_PARAM(priv->fg, camera, FG_HEIGHT, &fg_height, priv->fg_port); + + int val = FREE_RUN; + FG_TRY_PARAM(priv->fg, camera, FG_TRIGGERMODE, &val, priv->fg_port); + + fill_binnings(priv); + + /* + * Here we override property ranges because we didn't know them at property + * installation time. + */ + GObjectClass *camera_class = G_OBJECT_CLASS (UCA_CAMERA_GET_CLASS (camera)); + property_override_default_guint_value (camera_class, "roi-width", priv->width); + property_override_default_guint_value (camera_class, "roi-height", priv->height); + + guint32 rates[4] = {0}; + gint num_rates = 0; + + if (pco_get_available_pixelrates(priv->pco, rates, &num_rates) == PCO_NOERROR) { + GObjectClass *pco_camera_class = G_OBJECT_CLASS (UCA_PCO_CAMERA_GET_CLASS (camera)); + + fill_pixelrates(priv, rates, num_rates); + property_override_default_guint_value (pco_camera_class, "sensor-pixelrate", rates[0]); + } + + override_temperature_range (priv); + override_maximum_adcs (priv); + + return UCA_CAMERA (camera); +} diff --git a/src/cameras/uca-pco-camera.h b/src/cameras/uca-pco-camera.h index fdb709a..73ae44e 100644 --- a/src/cameras/uca-pco-camera.h +++ b/src/cameras/uca-pco-camera.h @@ -84,8 +84,6 @@ struct _UcaPcoCameraClass { UcaCameraClass parent; }; -UcaPcoCamera *uca_pco_camera_new(GError **error); - GType uca_pco_camera_get_type(void); G_END_DECLS diff --git a/src/cameras/uca-pf-camera.c b/src/cameras/uca-pf-camera.c index 5bc8c6b..35b5edd 100644 --- a/src/cameras/uca-pf-camera.c +++ b/src/cameras/uca-pf-camera.c @@ -15,6 +15,7 @@ with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA */ +#include #include #include #include @@ -99,52 +100,6 @@ struct _UcaPfCameraPrivate { dma_mem *fg_mem; }; -UcaPfCamera *uca_pf_camera_new(GError **error) -{ - static const gchar *so_file = "libFullAreaGray8.so"; - static const int camera_link_type = FG_CL_8BIT_FULL_8; - static const int camera_format = FG_GRAY; - - /* - gint num_ports; - if (pfPortInit(&num_ports) < 0) { - g_set_error(error, UCA_PF_CAMERA_ERROR, UCA_PF_CAMERA_ERROR_INIT, - "Could not initialize ports"); - return NULL; - } - - if (pfDeviceOpen(0) < 0) { - g_set_error(error, UCA_PF_CAMERA_ERROR, UCA_PF_CAMERA_ERROR_INIT, - "Could not open device"); - return NULL; - } - */ - - UcaPfCamera *camera = g_object_new(UCA_TYPE_PF_CAMERA, NULL); - UcaPfCameraPrivate *priv = UCA_PF_CAMERA_GET_PRIVATE(camera); - - priv->fg_port = PORT_A; - priv->fg = Fg_Init(so_file, priv->fg_port); - - /* TODO: get this from the camera */ - priv->roi_width = 1280; - priv->roi_height = 1024; - - if (priv->fg == NULL) { - g_set_error(error, UCA_PF_CAMERA_ERROR, UCA_PF_CAMERA_ERROR_INIT, - "%s", Fg_getLastErrorDescription(priv->fg)); - g_object_unref(camera); - return NULL; - } - - FG_TRY_PARAM(priv->fg, camera, FG_CAMERA_LINK_CAMTYP, &camera_link_type, priv->fg_port); - FG_TRY_PARAM(priv->fg, camera, FG_FORMAT, &camera_format, priv->fg_port); - FG_TRY_PARAM(priv->fg, camera, FG_WIDTH, &priv->roi_width, priv->fg_port); - FG_TRY_PARAM(priv->fg, camera, FG_HEIGHT, &priv->roi_height, priv->fg_port); - - return camera; -} - /* * We just embed our private structure here. */ @@ -226,7 +181,7 @@ static void uca_pf_camera_grab(UcaCamera *camera, gpointer *data, GError **error UcaPfCameraPrivate *priv = UCA_PF_CAMERA_GET_PRIVATE(camera); priv->last_frame = Fg_getLastPicNumberBlockingEx(priv->fg, priv->last_frame+1, priv->fg_port, 5, priv->fg_mem); - + if (priv->last_frame <= 0) { guint err = FG_OK + 1; FG_SET_ERROR(err, priv->fg, UCA_PF_CAMERA_ERROR_FG_GENERAL); @@ -252,10 +207,10 @@ static void uca_pf_camera_set_property(GObject *object, guint property_id, const static void uca_pf_camera_get_property(GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { switch (property_id) { - case PROP_SENSOR_WIDTH: + case PROP_SENSOR_WIDTH: g_value_set_uint(value, 1280); break; - case PROP_SENSOR_HEIGHT: + case PROP_SENSOR_HEIGHT: g_value_set_uint(value, 1024); break; case PROP_SENSOR_BITDEPTH: @@ -298,7 +253,7 @@ static void uca_pf_camera_get_property(GObject *object, guint property_id, GValu case PROP_ROI_HEIGHT_MULTIPLIER: g_value_set_uint(value, 1); break; - case PROP_NAME: + case PROP_NAME: g_value_set_string(value, "Photon Focus MV2-D1280-640-CL"); break; default: @@ -347,3 +302,50 @@ static void uca_pf_camera_init(UcaPfCamera *self) self->priv->fg_mem = NULL; self->priv->last_frame = 0; } + +G_MODULE_EXPORT UcaCamera * +uca_camera_impl_new (GError **error) +{ + static const gchar *so_file = "libFullAreaGray8.so"; + static const int camera_link_type = FG_CL_8BIT_FULL_8; + static const int camera_format = FG_GRAY; + + /* + gint num_ports; + if (pfPortInit(&num_ports) < 0) { + g_set_error(error, UCA_PF_CAMERA_ERROR, UCA_PF_CAMERA_ERROR_INIT, + "Could not initialize ports"); + return NULL; + } + + if (pfDeviceOpen(0) < 0) { + g_set_error(error, UCA_PF_CAMERA_ERROR, UCA_PF_CAMERA_ERROR_INIT, + "Could not open device"); + return NULL; + } + */ + + UcaPfCamera *camera = g_object_new(UCA_TYPE_PF_CAMERA, NULL); + UcaPfCameraPrivate *priv = UCA_PF_CAMERA_GET_PRIVATE(camera); + + priv->fg_port = PORT_A; + priv->fg = Fg_Init(so_file, priv->fg_port); + + /* TODO: get this from the camera */ + priv->roi_width = 1280; + priv->roi_height = 1024; + + if (priv->fg == NULL) { + g_set_error(error, UCA_PF_CAMERA_ERROR, UCA_PF_CAMERA_ERROR_INIT, + "%s", Fg_getLastErrorDescription(priv->fg)); + g_object_unref(camera); + return NULL; + } + + FG_TRY_PARAM(priv->fg, camera, FG_CAMERA_LINK_CAMTYP, &camera_link_type, priv->fg_port); + FG_TRY_PARAM(priv->fg, camera, FG_FORMAT, &camera_format, priv->fg_port); + FG_TRY_PARAM(priv->fg, camera, FG_WIDTH, &priv->roi_width, priv->fg_port); + FG_TRY_PARAM(priv->fg, camera, FG_HEIGHT, &priv->roi_height, priv->fg_port); + + return UCA_CAMERA (camera); +} diff --git a/src/cameras/uca-pf-camera.h b/src/cameras/uca-pf-camera.h index 7e3fe2c..3a309aa 100644 --- a/src/cameras/uca-pf-camera.h +++ b/src/cameras/uca-pf-camera.h @@ -67,8 +67,6 @@ struct _UcaPfCameraClass { UcaCameraClass parent; }; -UcaPfCamera *uca_pf_camera_new(GError **error); - GType uca_pf_camera_get_type(void); G_END_DECLS diff --git a/src/cameras/uca-ufo-camera.c b/src/cameras/uca-ufo-camera.c index 5f59f4a..7542fdf 100644 --- a/src/cameras/uca-ufo-camera.c +++ b/src/cameras/uca-ufo-camera.c @@ -15,6 +15,7 @@ with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA */ +#include #include #include #include @@ -143,7 +144,8 @@ static int event_callback(pcilib_event_id_t event_id, pcilib_event_info_t *info, return PCILIB_STREAMING_CONTINUE; } -UcaUfoCamera *uca_ufo_camera_new(GError **error) +G_MODULE_EXPORT UcaCamera * +uca_camera_impl_new (GError **error) { pcilib_model_t model = PCILIB_MODEL_DETECT; pcilib_model_description_t *model_description; @@ -223,7 +225,7 @@ UcaUfoCamera *uca_ufo_camera_new(GError **error) priv->handle = handle; - return camera; + return UCA_CAMERA (camera); } static void uca_ufo_camera_start_recording(UcaCamera *camera, GError **error) diff --git a/src/cameras/uca-ufo-camera.h b/src/cameras/uca-ufo-camera.h index 0b52ffb..7030389 100644 --- a/src/cameras/uca-ufo-camera.h +++ b/src/cameras/uca-ufo-camera.h @@ -69,8 +69,6 @@ struct _UcaUfoCameraClass { UcaCameraClass parent; }; -UcaUfoCamera *uca_ufo_camera_new(GError **error); - GType uca_ufo_camera_get_type(void); G_END_DECLS diff --git a/src/uca-camera.c b/src/uca-camera.c index 59ab5c7..e34bf62 100644 --- a/src/uca-camera.c +++ b/src/uca-camera.c @@ -20,26 +20,6 @@ #include "uca-camera.h" #include "uca-enums.h" -/* #ifdef HAVE_PCO_CL */ -/* #include "cameras/uca-pco-camera.h" */ -/* #endif */ - -/* #ifdef HAVE_PYLON_CAMERA */ -/* #include "cameras/uca-pylon-camera.h" */ -/* #endif */ - -/* #ifdef HAVE_MOCK_CAMERA */ -/* #include "cameras/uca-mock-camera.h" */ -/* #endif */ - -/* #ifdef HAVE_UFO_CAMERA */ -/* #include "cameras/uca-ufo-camera.h" */ -/* #endif */ - -/* #ifdef HAVE_PHOTON_FOCUS */ -/* #include "cameras/uca-pf-camera.h" */ -/* #endif */ - #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) @@ -65,25 +45,6 @@ GQuark uca_camera_error_quark() return g_quark_from_static_string("uca-camera-error-quark"); } -/* static gchar *uca_camera_types[] = { */ -/* #ifdef HAVE_PCO_CL */ -/* "pco", */ -/* #endif */ -/* #ifdef HAVE_PYLON_CAMERA */ -/* "pylon", */ -/* #endif */ -/* #ifdef HAVE_MOCK_CAMERA */ -/* "mock", */ -/* #endif */ -/* #ifdef HAVE_UFO_CAMERA */ -/* "ufo", */ -/* #endif */ -/* #ifdef HAVE_PHOTON_FOCUS */ -/* "pf", */ -/* #endif */ -/* NULL */ -/* }; */ - enum { LAST_SIGNAL }; @@ -373,80 +334,6 @@ static void uca_camera_init(UcaCamera *camera) */ } -/* static UcaCamera *uca_camera_new_from_type(const gchar *type, GError **error) */ -/* { */ -/* #ifdef HAVE_MOCK_CAMERA */ -/* if (!g_strcmp0(type, "mock")) */ -/* return UCA_CAMERA(uca_mock_camera_new(error)); */ -/* #endif */ - -/* #ifdef HAVE_PCO_CL */ -/* if (!g_strcmp0(type, "pco")) */ -/* return UCA_CAMERA(uca_pco_camera_new(error)); */ -/* #endif */ - -/* #ifdef HAVE_PYLON_CAMERA */ -/* if (!g_strcmp0(type, "pylon")) */ -/* return UCA_CAMERA(uca_pylon_camera_new(error)); */ -/* #endif */ - -/* #ifdef HAVE_UFO_CAMERA */ -/* if (!g_strcmp0(type, "ufo")) */ -/* return UCA_CAMERA(uca_ufo_camera_new(error)); */ -/* #endif */ - -/* #ifdef HAVE_PHOTON_FOCUS */ -/* if (!g_strcmp0(type, "pf")) */ -/* return UCA_CAMERA(uca_pf_camera_new(error)); */ -/* #endif */ - -/* return NULL; */ -/* } */ - -/* /** */ -/* * uca_camera_get_types: */ -/* * */ -/* * Enumerate all camera types that can be instantiated with uca_camera_new(). */ -/* * */ -/* * Returns: An array of strings with camera types. The list should be freed with */ -/* * g_strfreev(). */ -/* *1/ */ -/* gchar **uca_camera_get_types() */ -/* { */ -/* return g_strdupv(uca_camera_types); */ -/* } */ - -/** - * uca_camera_new: - * @type: Type name of the camera - * @error: Location to store an error or %NULL - * - * Factory method for instantiating cameras by names listed in - * uca_camera_get_types(). - * - * Returns: A new #UcaCamera of the correct type or %NULL if type was not found - */ -/* UcaCamera *uca_camera_new(const gchar *type, GError **error) */ -/* { */ -/* UcaCamera *camera = NULL; */ -/* GError *tmp_error = NULL; */ - -/* camera = uca_camera_new_from_type(type, &tmp_error); */ - -/* if (tmp_error != NULL) { */ -/* g_propagate_error(error, tmp_error); */ -/* return NULL; */ -/* } */ - -/* if ((tmp_error == NULL) && (camera == NULL)) { */ -/* g_set_error(error, UCA_CAMERA_ERROR, UCA_CAMERA_ERROR_NOT_FOUND, */ -/* "Camera type %s not found", type); */ -/* return NULL; */ -/* } */ - -/* return camera; */ -/* } */ - /** * uca_camera_start_recording: * @camera: A #UcaCamera object diff --git a/src/uca-plugin-manager.c b/src/uca-plugin-manager.c index 61e43f8..c044a4a 100644 --- a/src/uca-plugin-manager.c +++ b/src/uca-plugin-manager.c @@ -23,6 +23,10 @@ struct _UcaPluginManagerPrivate { GList *search_paths; }; +static const gchar *MODULE_PATTERN = "libuca([A-Za-z]+)"; + +typedef UcaCamera * (*GetCameraFunc) (GError **error); + /** * UcaPluginManagerError: * @UCA_PLUGIN_MANAGER_ERROR_MODULE_NOT_FOUND: The module could not be found @@ -70,30 +74,24 @@ uca_plugin_manager_add_path (UcaPluginManager *manager, } static GList * -get_camera_names_from_directory (const gchar *path) +get_camera_module_paths (const gchar *path) { - static const gchar *pattern_string = "libuca([A-Za-z]+)"; - GRegex *pattern; + GRegex *pattern; GDir *dir; GList *result = NULL; - - pattern = g_regex_new (pattern_string, 0, 0, NULL); + + pattern = g_regex_new (MODULE_PATTERN, 0, 0, NULL); dir = g_dir_open (path, 0, NULL); if (dir != NULL) { GMatchInfo *match_info = NULL; - const gchar *name = g_dir_read_name (dir); + const gchar *name = g_dir_read_name (dir); while (name != NULL) { - g_regex_match (pattern, name, 0, &match_info); - - if (g_match_info_matches (match_info)) { - gchar *word = g_match_info_fetch (match_info, 1); - - if (word != NULL) - result = g_list_append (result, word); - } + if (g_regex_match (pattern, name, 0, &match_info)) + result = g_list_append (result, g_build_filename (path, name, NULL)); + g_match_info_free (match_info); name = g_dir_read_name (dir); } } @@ -101,105 +99,138 @@ get_camera_names_from_directory (const gchar *path) return result; } +static GList * +scan_search_paths (GList *search_paths) +{ + GList *camera_paths = NULL; + + for (GList *it = g_list_first (search_paths); it != NULL; it = g_list_next (it)) { + camera_paths = g_list_concat (camera_paths, + get_camera_module_paths ((const gchar*) it->data)); + } + + return camera_paths; +} + +static void +transform_camera_module_path_to_name (gchar *path, GList **result) +{ + GRegex *pattern; + GMatchInfo *match_info; + + pattern = g_regex_new (MODULE_PATTERN, 0, 0, NULL); + g_regex_match (pattern, path, 0, &match_info); + + *result = g_list_append (*result, g_match_info_fetch (match_info, 1)); + g_match_info_free (match_info); +} + +static void +g_list_free_full (GList *list) +{ + g_list_foreach (list, (GFunc) g_free, NULL); + g_list_free (list); +} + GList * uca_plugin_manager_get_available_cameras (UcaPluginManager *manager) { UcaPluginManagerPrivate *priv; + GList *camera_paths; GList *camera_names = NULL; g_return_val_if_fail (UCA_IS_PLUGIN_MANAGER (manager), NULL); priv = manager->priv; + camera_paths = scan_search_paths (priv->search_paths); - for (GList *it = g_list_first (priv->search_paths); it != NULL; it = g_list_next (it)) { - camera_names = g_list_concat (camera_names, - get_camera_names_from_directory ((const gchar*) it->data)); - } + g_list_foreach (camera_paths, (GFunc) transform_camera_module_path_to_name, &camera_names); + g_list_free_full (camera_paths); return camera_names; } +static gchar * +find_camera_module_path (GList *search_paths, const gchar *name) +{ + gchar *result = NULL; + GList *paths; + + paths = scan_search_paths (search_paths); + + for (GList *it = g_list_first (paths); it != NULL; it = g_list_next (it)) { + gchar *path = (gchar *) it->data; + gchar *basename = g_path_get_basename ((gchar *) path); + + if (g_strrstr (basename, name)) { + result = g_strdup (path); + g_free (basename); + break; + } + + g_free (basename); + } + + g_list_free_full (paths); + return result; +} + UcaCamera * uca_plugin_manager_new_camera (UcaPluginManager *manager, const gchar *name, GError **error) { - return NULL; -} + UcaPluginManagerPrivate *priv; + UcaCamera *camera; + GModule *module; + GetCameraFunc *func; + gchar *module_path; + GError *tmp_error = NULL; -/** - * uca_plugin_manager_get_filter: - * @manager: A #UcaPluginManager - * @name: Name of the plugin. - * @error: return location for a GError or %NULL - * - * Load a #UcaFilter module and return an instance. The shared object name must - * be * constructed as "libfilter@name.so". - * - * Returns: (transfer none) (allow-none): #UcaFilter or %NULL if module cannot be found - * - * Since: 0.2, the error parameter is available - */ -/* UcaFilter * */ -/* uca_plugin_manager_get_filter (UcaPluginManager *manager, const gchar *name, GError **error) */ -/* { */ -/* g_return_val_if_fail (UCA_IS_PLUGIN_MANAGER (manager) && (name != NULL), NULL); */ -/* UcaPluginManagerPrivate *priv = UCA_PLUGIN_MANAGER_GET_PRIVATE (manager); */ -/* UcaFilter *filter; */ -/* GetFilterFunc *func = NULL; */ -/* GModule *module = NULL; */ -/* gchar *module_name = NULL; */ -/* const gchar *entry_symbol_name = "uca_filter_plugin_new"; */ - -/* func = g_hash_table_lookup (priv->filter_funcs, name); */ - -/* if (func == NULL) { */ -/* module_name = g_strdup_printf ("libucafilter%s.so", name); */ -/* gchar *path = plugin_manager_get_path (priv, module_name); */ - -/* if (path == NULL) { */ -/* g_set_error (error, UCA_PLUGIN_MANAGER_ERROR, UCA_PLUGIN_MANAGER_ERROR_MODULE_NOT_FOUND, */ -/* "Module %s not found", module_name); */ -/* goto handle_error; */ -/* } */ - -/* module = g_module_open (path, G_MODULE_BIND_LAZY); */ -/* g_free (path); */ - -/* if (!module) { */ -/* g_set_error (error, UCA_PLUGIN_MANAGER_ERROR, UCA_PLUGIN_MANAGER_ERROR_MODULE_OPEN, */ -/* "Module %s could not be opened: %s", module_name, g_module_error ()); */ -/* goto handle_error; */ -/* } */ - -/* func = g_malloc0 (sizeof (GetFilterFunc)); */ - -/* if (!g_module_symbol (module, entry_symbol_name, (gpointer *) func)) { */ -/* g_set_error (error, UCA_PLUGIN_MANAGER_ERROR, UCA_PLUGIN_MANAGER_ERROR_SYMBOL_NOT_FOUND, */ -/* "%s is not exported by module %s: %s", entry_symbol_name, module_name, g_module_error ()); */ -/* g_free (func); */ - -/* if (!g_module_close (module)) */ -/* g_warning ("%s", g_module_error ()); */ - -/* goto handle_error; */ -/* } */ - -/* priv->modules = g_slist_append (priv->modules, module); */ -/* g_hash_table_insert (priv->filter_funcs, g_strdup (name), func); */ -/* g_free (module_name); */ -/* } */ - -/* filter = (*func) (); */ -/* uca_filter_set_plugin_name (filter, name); */ -/* g_message ("UcaPluginManager: Created %s-%p", name, (gpointer) filter); */ - -/* return filter; */ - -/* handle_error: */ -/* g_free (module_name); */ -/* return NULL; */ -/* } */ + const gchar *symbol_name = "uca_camera_impl_new"; + + g_return_val_if_fail (UCA_IS_PLUGIN_MANAGER (manager) && (name != NULL), NULL); + + priv = manager->priv; + module_path = find_camera_module_path (priv->search_paths, name); + + if (module_path == NULL) { + g_set_error (error, UCA_PLUGIN_MANAGER_ERROR, UCA_PLUGIN_MANAGER_ERROR_MODULE_NOT_FOUND, + "Camera module `%s' not found", name); + return NULL; + } + + module = g_module_open (module_path, G_MODULE_BIND_LAZY); + g_free (module_path); + + if (!module) { + g_set_error (error, UCA_PLUGIN_MANAGER_ERROR, UCA_PLUGIN_MANAGER_ERROR_MODULE_OPEN, + "Camera module `%s' could not be opened: %s", name, g_module_error ()); + return NULL; + } + + func = g_malloc0 (sizeof (GetCameraFunc)); + + if (!g_module_symbol (module, symbol_name, (gpointer *) func)) { + g_set_error (error, UCA_PLUGIN_MANAGER_ERROR, UCA_PLUGIN_MANAGER_ERROR_SYMBOL_NOT_FOUND, + "%s", g_module_error ()); + g_free (func); + + if (!g_module_close (module)) + g_warning ("%s", g_module_error ()); + + return NULL; + } + + camera = (*func) (&tmp_error); + + if (tmp_error != NULL) { + g_propagate_error (error, tmp_error); + return NULL; + } + + return camera; +} static void uca_plugin_manager_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 8fe702b..37ea6bf 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -36,12 +36,12 @@ if (HAVE_PYLON_CAMERA) link_directories(${PYLON_LIB_DIRS} ${LIBPYLONCAM_LIBDIR}) endif() -#add_executable(grab grab.c) +add_executable(grab grab.c) #add_executable(grab-async grab-async.c) add_executable(benchmark benchmark.c) target_link_libraries(benchmark uca ${GLIB2_LIBRARIES} ${GOBJECT2_LIBRARIES}) -#target_link_libraries(grab uca ${GLIB2_LIBRARIES} ${GOBJECT2_LIBRARIES}) +target_link_libraries(grab uca ${GLIB2_LIBRARIES} ${GOBJECT2_LIBRARIES}) #target_link_libraries(grab-async uca ${GLIB2_LIBRARIES} ${GOBJECT2_LIBRARIES}) #add_executable(grab_pylon grab_pylon.c) diff --git a/test/benchmark.c b/test/benchmark.c index 73b6805..ef99fd1 100644 --- a/test/benchmark.c +++ b/test/benchmark.c @@ -42,7 +42,7 @@ print_usage (void) UcaPluginManager *manager; manager = uca_plugin_manager_new (); - g_print ("Usage: benchmark ["); + g_print ("Usage: benchmark [ "); types = uca_plugin_manager_get_available_cameras (manager); if (types == NULL) { @@ -52,10 +52,11 @@ print_usage (void) for (GList *it = g_list_first (types); it != NULL; it = g_list_next (it)) { gchar *name = (gchar *) it->data; - g_print ("`%s' ", name); + if (g_list_next (it) == NULL) + g_print ("%s ]\n", name); + else + g_print ("%s, ", name); } - - g_print ("]\n"); } static void diff --git a/test/grab.c b/test/grab.c index 41e6d88..e507d69 100644 --- a/test/grab.c +++ b/test/grab.c @@ -19,6 +19,7 @@ #include #include #include +#include "uca-plugin-manager.h" #include "uca-camera.h" static UcaCamera *camera = NULL; @@ -31,26 +32,33 @@ static void sigint_handler(int signal) exit(signal); } -static void print_usage(void) +static void +print_usage (void) { - gchar **types; - - g_print("Usage: grab ("); - types = uca_camera_get_types(); - - for (guint i = 0; types[i] != NULL; i++) { - if (types[i+1] == NULL) - g_print("%s)", types[i]); - else - g_print("%s | ", types[i]); + GList *types; + UcaPluginManager *manager; + + manager = uca_plugin_manager_new (); + g_print ("Usage: benchmark [ "); + types = uca_plugin_manager_get_available_cameras (manager); + + if (types == NULL) { + g_print ("] -- no camera plugin found\n"); + return; } - g_print("\n"); - g_strfreev(types); + for (GList *it = g_list_first (types); it != NULL; it = g_list_next (it)) { + gchar *name = (gchar *) it->data; + if (g_list_next (it) == NULL) + g_print ("%s ]\n", name); + else + g_print ("%s, ", name); + } } int main(int argc, char *argv[]) { + UcaPluginManager *manager; GError *error = NULL; (void) signal(SIGINT, sigint_handler); @@ -59,13 +67,15 @@ int main(int argc, char *argv[]) guint bits; gchar *name; + g_type_init(); + if (argc < 2) { print_usage(); return 1; } - g_type_init(); - camera = uca_camera_new(argv[1], &error); + manager = uca_plugin_manager_new (); + camera = uca_plugin_manager_new_camera (manager, argv[1], &error); if (camera == NULL) { g_print("Error during initialization: %s\n", error->message); -- cgit v1.2.3 From 7b32cb1f541a4606bfed3cdfe470d69a9ccbde5a Mon Sep 17 00:00:00 2001 From: Matthias Vogelgesang Date: Wed, 19 Sep 2012 18:07:14 +0200 Subject: Install plugin manager header file --- src/CMakeLists.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 42f9dd8..e186975 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -7,7 +7,8 @@ set(uca_SRCS ) set(uca_HDRS - uca-camera.h) + uca-camera.h + uca-plugin-manager.h) set(cameras) -- cgit v1.2.3 From 94459e5838c8923a0820135c4915976958dde2ed Mon Sep 17 00:00:00 2001 From: Matthias Vogelgesang Date: Thu, 20 Sep 2012 18:32:08 +0200 Subject: Add docstrings --- src/uca-plugin-manager.c | 33 +++++++++++++++++++++++++++++---- 1 file changed, 29 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/uca-plugin-manager.c b/src/uca-plugin-manager.c index c044a4a..fdfb59f 100644 --- a/src/uca-plugin-manager.c +++ b/src/uca-plugin-manager.c @@ -4,13 +4,16 @@ * @Title: UcaPluginManager * * The plugin manager opens shared object modules searched for in locations - * specified with uca_plugin_manager_add_paths(). An #UcaFilter can be - * instantiated with uca_plugin_manager_get_filter() with a one-to-one mapping - * between filter name xyz and module name libfilterxyz.so. Any errors are - * reported as one of #UcaPluginManagerError codes. + * specified with uca_plugin_manager_add_path(). A #UcaCamera can be + * instantiated with uca_plugin_manager_new_camera() with a one-to-one mapping + * between filter name xyz and module name libucaxyz.so. Any errors are reported + * as one of #UcaPluginManagerError codes. To get a list of available camera + * names call uca_plugin_manager_get_available_cameras(). * * By default, any path listed in the %UCA_CAMERA_PATH environment variable is * added to the search path. + * + * @Since: 1.1 */ #include #include "uca-plugin-manager.h" @@ -58,6 +61,13 @@ uca_plugin_manager_new () return UCA_PLUGIN_MANAGER (g_object_new (UCA_TYPE_PLUGIN_MANAGER, NULL)); } +/** + * uca_plugin_manager_add_path: + * @manager: A #UcaPluginManager + * @path: Path to look for camera modules + * + * Add a search path to the plugin manager. + */ void uca_plugin_manager_add_path (UcaPluginManager *manager, const gchar *path) @@ -132,6 +142,15 @@ g_list_free_full (GList *list) g_list_free (list); } +/** + * uca_plugin_manager_get_available_cameras: + * + * @manager: A #UcaPluginManager + * + * Return: A list with strings of available camera names. You have to free the + * individual strings with g_list_foreach(list, (GFunc) g_free, NULL) and the + * list itself with g_list_free. + */ GList * uca_plugin_manager_get_available_cameras (UcaPluginManager *manager) { @@ -175,6 +194,12 @@ find_camera_module_path (GList *search_paths, const gchar *name) return result; } +/** + * uca_plugin_manager_new_camera: + * @manager: A #UcaPluginManager + * @name: Name of the camera module, that maps to libuca.so + * @error: Location for a #GError + */ UcaCamera * uca_plugin_manager_new_camera (UcaPluginManager *manager, const gchar *name, -- cgit v1.2.3 From 2c770ee3fe040186602aeadd62a5d256724e1105 Mon Sep 17 00:00:00 2001 From: Matthias Vogelgesang Date: Fri, 21 Sep 2012 11:46:46 +0200 Subject: Rename g_list_free_full to list_free_full This got really implemented with GLib 2.28, so the names clash. --- src/uca-plugin-manager.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/uca-plugin-manager.c b/src/uca-plugin-manager.c index fdfb59f..5678e83 100644 --- a/src/uca-plugin-manager.c +++ b/src/uca-plugin-manager.c @@ -136,7 +136,7 @@ transform_camera_module_path_to_name (gchar *path, GList **result) } static void -g_list_free_full (GList *list) +list_free_full (GList *list) { g_list_foreach (list, (GFunc) g_free, NULL); g_list_free (list); @@ -164,7 +164,7 @@ uca_plugin_manager_get_available_cameras (UcaPluginManager *manager) camera_paths = scan_search_paths (priv->search_paths); g_list_foreach (camera_paths, (GFunc) transform_camera_module_path_to_name, &camera_names); - g_list_free_full (camera_paths); + list_free_full (camera_paths); return camera_names; } @@ -190,7 +190,7 @@ find_camera_module_path (GList *search_paths, const gchar *name) g_free (basename); } - g_list_free_full (paths); + list_free_full (paths); return result; } -- cgit v1.2.3 From 468641280f9bd6771b5a565b526f40f7fb8e8fad Mon Sep 17 00:00:00 2001 From: Matthias Vogelgesang Date: Tue, 25 Sep 2012 10:58:43 +0200 Subject: Fix #139: Lock API functions --- src/uca-camera.c | 184 +++++++++++++++++++++++++++++++++---------------------- 1 file changed, 111 insertions(+), 73 deletions(-) (limited to 'src') diff --git a/src/uca-camera.c b/src/uca-camera.c index e34bf62..f973355 100644 --- a/src/uca-camera.c +++ b/src/uca-camera.c @@ -303,7 +303,8 @@ uca_camera_class_init(UcaCameraClass *klass) g_type_class_add_private(klass, sizeof(UcaCameraPrivate)); } -static void uca_camera_init(UcaCamera *camera) +static void +uca_camera_init(UcaCamera *camera) { camera->grab_func = NULL; @@ -343,38 +344,47 @@ static void uca_camera_init(UcaCamera *camera) * #UcaCameraGrabFunc callback is set, frames are automatically transfered to * the client program, otherwise you must use uca_camera_grab(). */ -void uca_camera_start_recording(UcaCamera *camera, GError **error) +void +uca_camera_start_recording (UcaCamera *camera, GError **error) { - g_return_if_fail(UCA_IS_CAMERA(camera)); + UcaCameraClass *klass; + GError *tmp_error = NULL; + static GStaticMutex mutex = G_STATIC_MUTEX_INIT; + + g_return_if_fail (UCA_IS_CAMERA (camera)); - UcaCameraClass *klass = UCA_CAMERA_GET_CLASS(camera); + klass = UCA_CAMERA_GET_CLASS (camera); - g_return_if_fail(klass != NULL); - g_return_if_fail(klass->start_recording != NULL); + g_return_if_fail (klass != NULL); + g_return_if_fail (klass->start_recording != NULL); + + g_static_mutex_lock (&mutex); if (camera->priv->is_recording) { - g_set_error(error, UCA_CAMERA_ERROR, UCA_CAMERA_ERROR_RECORDING, + g_set_error (error, UCA_CAMERA_ERROR, UCA_CAMERA_ERROR_RECORDING, "Camera is already recording"); - return; + goto start_recording_unlock; } if (camera->priv->transfer_async && (camera->grab_func == NULL)) { - g_set_error(error, UCA_CAMERA_ERROR, UCA_CAMERA_ERROR_NO_GRAB_FUNC, + g_set_error (error, UCA_CAMERA_ERROR, UCA_CAMERA_ERROR_NO_GRAB_FUNC, "No grab callback function set"); - return; + goto start_recording_unlock; } - GError *tmp_error = NULL; (*klass->start_recording)(camera, &tmp_error); if (tmp_error == NULL) { camera->priv->is_readout = FALSE; camera->priv->is_recording = TRUE; /* TODO: we should depend on GLib 2.26 and use g_object_notify_by_pspec */ - g_object_notify(G_OBJECT(camera), "is-recording"); + g_object_notify (G_OBJECT (camera), "is-recording"); } else - g_propagate_error(error, tmp_error); + g_propagate_error (error, tmp_error); + +start_recording_unlock: + g_static_mutex_unlock (&mutex); } /** @@ -384,32 +394,41 @@ void uca_camera_start_recording(UcaCamera *camera, GError **error) * * Stop recording. */ -void uca_camera_stop_recording(UcaCamera *camera, GError **error) +void +uca_camera_stop_recording (UcaCamera *camera, GError **error) { - g_return_if_fail(UCA_IS_CAMERA(camera)); + UcaCameraClass *klass; + static GStaticMutex mutex = G_STATIC_MUTEX_INIT; - UcaCameraClass *klass = UCA_CAMERA_GET_CLASS(camera); + g_return_if_fail (UCA_IS_CAMERA (camera)); - g_return_if_fail(klass != NULL); - g_return_if_fail(klass->stop_recording != NULL); + klass = UCA_CAMERA_GET_CLASS (camera); - if (!camera->priv->is_recording) { - g_set_error(error, UCA_CAMERA_ERROR, UCA_CAMERA_ERROR_NOT_RECORDING, - "Camera is not recording"); - return; - } + g_return_if_fail (klass != NULL); + g_return_if_fail (klass->stop_recording != NULL); - GError *tmp_error = NULL; - (*klass->stop_recording)(camera, &tmp_error); + g_static_mutex_lock (&mutex); - if (tmp_error == NULL) { - camera->priv->is_readout = FALSE; - camera->priv->is_recording = FALSE; - /* TODO: we should depend on GLib 2.26 and use g_object_notify_by_pspec */ - g_object_notify(G_OBJECT(camera), "is-recording"); + if (!camera->priv->is_recording) { + g_set_error (error, UCA_CAMERA_ERROR, UCA_CAMERA_ERROR_NOT_RECORDING, + "Camera is not recording"); } - else - g_propagate_error(error, tmp_error); + else { + GError *tmp_error = NULL; + + (*klass->stop_recording)(camera, &tmp_error); + + if (tmp_error == NULL) { + camera->priv->is_readout = FALSE; + camera->priv->is_recording = FALSE; + /* TODO: we should depend on GLib 2.26 and use g_object_notify_by_pspec */ + g_object_notify (G_OBJECT (camera), "is-recording"); + } + else + g_propagate_error (error, tmp_error); + } + + g_static_mutex_unlock (&mutex); } /** @@ -422,31 +441,40 @@ void uca_camera_stop_recording(UcaCamera *camera, GError **error) * uca_camera_stop_recording(). Frames have to be picked up with * ufo_camera_grab(). */ -void uca_camera_start_readout(UcaCamera *camera, GError **error) +void +uca_camera_start_readout (UcaCamera *camera, GError **error) { - g_return_if_fail(UCA_IS_CAMERA(camera)); + UcaCameraClass *klass; + static GStaticMutex mutex = G_STATIC_MUTEX_INIT; - UcaCameraClass *klass = UCA_CAMERA_GET_CLASS(camera); + g_return_if_fail (UCA_IS_CAMERA(camera)); - g_return_if_fail(klass != NULL); - g_return_if_fail(klass->start_readout != NULL); + klass = UCA_CAMERA_GET_CLASS(camera); - if (camera->priv->is_recording) { - g_set_error(error, UCA_CAMERA_ERROR, UCA_CAMERA_ERROR_RECORDING, - "Camera is still recording"); - return; - } + g_return_if_fail (klass != NULL); + g_return_if_fail (klass->start_readout != NULL); - GError *tmp_error = NULL; - (*klass->start_readout)(camera, &tmp_error); + g_static_mutex_lock (&mutex); - if (tmp_error == NULL) { - camera->priv->is_readout = TRUE; - /* TODO: we should depend on GLib 2.26 and use g_object_notify_by_pspec */ - g_object_notify(G_OBJECT(camera), "is-readout"); + if (camera->priv->is_recording) { + g_set_error (error, UCA_CAMERA_ERROR, UCA_CAMERA_ERROR_RECORDING, + "Camera is still recording"); } - else - g_propagate_error(error, tmp_error); + else { + GError *tmp_error = NULL; + + (*klass->start_readout) (camera, &tmp_error); + + if (tmp_error == NULL) { + camera->priv->is_readout = TRUE; + /* TODO: we should depend on GLib 2.26 and use g_object_notify_by_pspec */ + g_object_notify (G_OBJECT (camera), "is-readout"); + } + else + g_propagate_error (error, tmp_error); + } + + g_static_mutex_unlock (&mutex); } /** @@ -473,22 +501,27 @@ void uca_camera_set_grab_func(UcaCamera *camera, UcaCameraGrabFunc func, gpointe * You must have called uca_camera_start_recording() before, otherwise you will * get a #UCA_CAMERA_ERROR_NOT_RECORDING error. */ -void uca_camera_trigger(UcaCamera *camera, GError **error) +void +uca_camera_trigger (UcaCamera *camera, GError **error) { - g_return_if_fail(UCA_IS_CAMERA(camera)); + UcaCameraClass *klass; + static GStaticMutex mutex = G_STATIC_MUTEX_INIT; - UcaCameraClass *klass = UCA_CAMERA_GET_CLASS(camera); + g_return_if_fail (UCA_IS_CAMERA (camera)); - g_return_if_fail(klass != NULL); - g_return_if_fail(klass->trigger != NULL); + klass = UCA_CAMERA_GET_CLASS (camera); - if (!camera->priv->is_recording) { - g_set_error(error, UCA_CAMERA_ERROR, UCA_CAMERA_ERROR_NOT_RECORDING, - "Camera is not recording"); - return; - } + g_return_if_fail (klass != NULL); + g_return_if_fail (klass->trigger != NULL); + + g_static_mutex_lock (&mutex); + + if (!camera->priv->is_recording) + g_set_error (error, UCA_CAMERA_ERROR, UCA_CAMERA_ERROR_NOT_RECORDING, "Camera is not recording"); + else + (*klass->trigger) (camera, error); - (*klass->trigger)(camera, error); + g_static_mutex_unlock (&mutex); } /** @@ -505,22 +538,27 @@ void uca_camera_trigger(UcaCamera *camera, GError **error) * You must have called uca_camera_start_recording() before, otherwise you will * get a #UCA_CAMERA_ERROR_NOT_RECORDING error. */ -void uca_camera_grab(UcaCamera *camera, gpointer *data, GError **error) +void +uca_camera_grab (UcaCamera *camera, gpointer *data, GError **error) { - g_return_if_fail(UCA_IS_CAMERA(camera)); + UcaCameraClass *klass; + static GStaticMutex mutex = G_STATIC_MUTEX_INIT; - UcaCameraClass *klass = UCA_CAMERA_GET_CLASS(camera); + g_return_if_fail (UCA_IS_CAMERA(camera)); - g_return_if_fail(klass != NULL); - g_return_if_fail(klass->grab != NULL); - g_return_if_fail(data != NULL); + klass = UCA_CAMERA_GET_CLASS (camera); - if (!camera->priv->is_recording && !camera->priv->is_readout) { - g_set_error(error, UCA_CAMERA_ERROR, UCA_CAMERA_ERROR_NOT_RECORDING, - "Camera is neither recording nor in readout mode"); - return; - } + g_return_if_fail (klass != NULL); + g_return_if_fail (klass->grab != NULL); + g_return_if_fail (data != NULL); + + g_static_mutex_lock (&mutex); + + if (!camera->priv->is_recording && !camera->priv->is_readout) + g_set_error (error, UCA_CAMERA_ERROR, UCA_CAMERA_ERROR_NOT_RECORDING, "Camera is neither recording nor in readout mode"); + else + (*klass->grab) (camera, data, error); - (*klass->grab)(camera, data, error); + g_static_mutex_unlock (&mutex); } -- cgit v1.2.3 From 99b737ae9f3f1d35a4696594821fa3bc39e8aa87 Mon Sep 17 00:00:00 2001 From: Matthias Vogelgesang Date: Fri, 28 Sep 2012 18:16:56 +0200 Subject: Fix #146: Make a new top-level directory for cams ... and build a package for each camera. Moreover, for some reason we can live without the CMake generated spec file for RPM generation. AFAICS, the RPMs are prefixed correctly. --- CMakeLists.txt | 46 +- package.sh.in | 7 + plugins/CMakeLists.txt | 5 + plugins/mock/CMakeLists.txt | 18 + plugins/mock/uca-mock-camera.c | 409 +++++++++++ plugins/mock/uca-mock-camera.h | 65 ++ plugins/package-plugin.sh.in | 1 + plugins/pco/CMakeLists.txt | 30 + plugins/pco/uca-pco-camera.c | 1398 ++++++++++++++++++++++++++++++++++++++ plugins/pco/uca-pco-camera.h | 91 +++ plugins/pf/CMakeLists.txt | 30 + plugins/pf/uca-pf-camera.c | 351 ++++++++++ plugins/pf/uca-pf-camera.h | 74 ++ plugins/pylon/CMakeLists.txt | 24 + plugins/pylon/uca-pylon-camera.c | 391 +++++++++++ plugins/pylon/uca-pylon-camera.h | 74 ++ plugins/ufo/CMakeLists.txt | 24 + plugins/ufo/uca-ufo-camera.c | 497 ++++++++++++++ plugins/ufo/uca-ufo-camera.h | 76 +++ src/CMakeLists.txt | 202 ++---- src/cameras/uca-mock-camera.c | 409 ----------- src/cameras/uca-mock-camera.h | 65 -- src/cameras/uca-pco-camera.c | 1398 -------------------------------------- src/cameras/uca-pco-camera.h | 91 --- src/cameras/uca-pf-camera.c | 351 ---------- src/cameras/uca-pf-camera.h | 74 -- src/cameras/uca-pylon-camera.c | 391 ----------- src/cameras/uca-pylon-camera.h | 74 -- src/cameras/uca-ufo-camera.c | 497 -------------- src/cameras/uca-ufo-camera.h | 76 --- 30 files changed, 3646 insertions(+), 3593 deletions(-) create mode 100644 package.sh.in create mode 100644 plugins/CMakeLists.txt create mode 100644 plugins/mock/CMakeLists.txt create mode 100644 plugins/mock/uca-mock-camera.c create mode 100644 plugins/mock/uca-mock-camera.h create mode 100644 plugins/package-plugin.sh.in create mode 100644 plugins/pco/CMakeLists.txt create mode 100644 plugins/pco/uca-pco-camera.c create mode 100644 plugins/pco/uca-pco-camera.h create mode 100644 plugins/pf/CMakeLists.txt create mode 100644 plugins/pf/uca-pf-camera.c create mode 100644 plugins/pf/uca-pf-camera.h create mode 100644 plugins/pylon/CMakeLists.txt create mode 100644 plugins/pylon/uca-pylon-camera.c create mode 100644 plugins/pylon/uca-pylon-camera.h create mode 100644 plugins/ufo/CMakeLists.txt create mode 100644 plugins/ufo/uca-ufo-camera.c create mode 100644 plugins/ufo/uca-ufo-camera.h delete mode 100644 src/cameras/uca-mock-camera.c delete mode 100644 src/cameras/uca-mock-camera.h delete mode 100644 src/cameras/uca-pco-camera.c delete mode 100644 src/cameras/uca-pco-camera.h delete mode 100644 src/cameras/uca-pf-camera.c delete mode 100644 src/cameras/uca-pf-camera.h delete mode 100644 src/cameras/uca-pylon-camera.c delete mode 100644 src/cameras/uca-pylon-camera.h delete mode 100644 src/cameras/uca-ufo-camera.c delete mode 100644 src/cameras/uca-ufo-camera.h (limited to 'src') diff --git a/CMakeLists.txt b/CMakeLists.txt index bc65dc1..b6ac69f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,10 +1,9 @@ cmake_minimum_required(VERSION 2.8) -project(uca C) set(TARNAME "libuca") set(UCA_VERSION_MAJOR "1") set(UCA_VERSION_MINOR "1") -set(UCA_VERSION_PATCH "0-dev") +set(UCA_VERSION_PATCH "0dev") set(UCA_DESCRIPTION "Unified Camera Access") set(UCA_VERSION_STRING "${UCA_VERSION_MAJOR}.${UCA_VERSION_MINOR}.${UCA_VERSION_PATCH}") @@ -16,7 +15,7 @@ set(PACKAGE_TARNAME "${TARNAME}") set(PACKAGE_STRING "${PACKAGE_NAME} ${PACKAGE_VERSION}") set(PACKAGE_BUGREPORT "http://ufo.kit.edu/ufo/newticket") -set(CPACK_GENERATOR "DEB;RPM;") +set(CPACK_GENERATOR "RPM") set(CPACK_PACKAGE_RELEASE 3) set(CPACK_DEBIAN_PACKAGE_NAME "libuca") set(CPACK_DEBIAN_PACKAGE_MAINTAINER "Matthias Vogelgesang ") @@ -25,8 +24,47 @@ set(CPACK_DEBIAN_PACKAGE_DESCRIPTION_SUMMARY ${UCA_DESCRIPTION}) set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "amd64") -SET(UCA_BUILD_DIR ${CMAKE_CURRENT_BINARY_DIR}) +set(UCA_BUILD_DIR ${CMAKE_CURRENT_BINARY_DIR}) + +set(LIB_INSTALL_DIR "lib${LIB_SUFFIX}") + +set(UCA_ENUM_HDRS + ${CMAKE_CURRENT_SOURCE_DIR}/src/uca-camera.h + ${CMAKE_CURRENT_SOURCE_DIR}/plugins/pco/uca-pco-camera.h) + +# --- Common configuration --------------------------------------------------- + +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/package.sh.in + ${CMAKE_CURRENT_BINARY_DIR}/package.sh) + + +# --- Common flags ------------------------------------------------------------ + +add_definitions("-std=c99 -Wall") + + +# --- Common libraries -------------------------------------------------------- + +set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake) + +find_package(PkgConfig) +find_program(GLIB2_MKENUMS glib-mkenums REQUIRED) +pkg_check_modules(GLIB2 glib-2.0>=2.24 REQUIRED) +pkg_check_modules(GOBJECT2 gobject-2.0>=2.24 REQUIRED) +pkg_check_modules(GMODULE2 gmodule-2.0>=2.24 REQUIRED) + +include_directories( + ${CMAKE_CURRENT_BINARY_DIR}/src + ${CMAKE_CURRENT_SOURCE_DIR}/src + ${GLIB2_INCLUDE_DIRS} + ${GOBJECT2_INCLUDE_DIRS}) + +set(UCA_DEPS + ${GLIB2_LIBRARIES} + ${GOBJECT2_LIBRARIES} + ${GMODULE2_LIBRARIES}) add_subdirectory(src) +add_subdirectory(plugins) add_subdirectory(test) add_subdirectory(tools) diff --git a/package.sh.in b/package.sh.in new file mode 100644 index 0000000..7c15b78 --- /dev/null +++ b/package.sh.in @@ -0,0 +1,7 @@ +cpack -D CPACK_INSTALL_CMAKE_PROJECTS="${CMAKE_CURRENT_BINARY_DIR}/;Project;libraries;/" +cpack -D CPACK_INSTALL_CMAKE_PROJECTS="${CMAKE_CURRENT_BINARY_DIR}/;Project;headers;/" -D CPACK_PACKAGE_FILE_NAME="libuca-${UCA_VERSION_MAJOR}.${UCA_VERSION_MINOR}.${UCA_VERSION_PATCH}-devel" + +# Build packages for all available cameras +for shell_script in `find -name 'package-plugin-*.sh'`; do + sh $shell_script +done diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt new file mode 100644 index 0000000..5131280 --- /dev/null +++ b/plugins/CMakeLists.txt @@ -0,0 +1,5 @@ +add_subdirectory(mock) +add_subdirectory(pf) +add_subdirectory(pco) +add_subdirectory(pylon) +add_subdirectory(ufo) diff --git a/plugins/mock/CMakeLists.txt b/plugins/mock/CMakeLists.txt new file mode 100644 index 0000000..75d8635 --- /dev/null +++ b/plugins/mock/CMakeLists.txt @@ -0,0 +1,18 @@ +cmake_minimum_required(VERSION 2.8) +project(ucamock) + +set(UCA_CAMERA_NAME "mock") + +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/../package-plugin.sh.in + ${CMAKE_CURRENT_BINARY_DIR}/../../package-plugin-${UCA_CAMERA_NAME}.sh) + +add_library(ucamock SHARED + uca-mock-camera.c) + +target_link_libraries(ucamock + uca + ${UCA_DEPS}) + +install(TARGETS ucamock + LIBRARY DESTINATION ${LIB_INSTALL_DIR}/uca + COMPONENT ${UCA_CAMERA_NAME}) diff --git a/plugins/mock/uca-mock-camera.c b/plugins/mock/uca-mock-camera.c new file mode 100644 index 0000000..7cd4689 --- /dev/null +++ b/plugins/mock/uca-mock-camera.c @@ -0,0 +1,409 @@ +/* Copyright (C) 2011, 2012 Matthias Vogelgesang + (Karlsruhe Institute of Technology) + + This library is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by the + Free Software Foundation; either version 2.1 of the License, or (at your + option) any later version. + + This library is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + details. + + You should have received a copy of the GNU Lesser General Public License along + with this library; if not, write to the Free Software Foundation, Inc., 51 + Franklin St, Fifth Floor, Boston, MA 02110, USA */ + +#include +#include +#include "uca-mock-camera.h" + +#define UCA_MOCK_CAMERA_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), UCA_TYPE_MOCK_CAMERA, UcaMockCameraPrivate)) + +G_DEFINE_TYPE(UcaMockCamera, uca_mock_camera, UCA_TYPE_CAMERA) + +enum { + PROP_FRAMERATE = N_BASE_PROPERTIES, + N_PROPERTIES +}; + +static const gint mock_overrideables[] = { + PROP_NAME, + PROP_SENSOR_WIDTH, + PROP_SENSOR_HEIGHT, + PROP_SENSOR_BITDEPTH, + PROP_SENSOR_HORIZONTAL_BINNING, + PROP_SENSOR_HORIZONTAL_BINNINGS, + PROP_SENSOR_VERTICAL_BINNING, + PROP_SENSOR_VERTICAL_BINNINGS, + PROP_TRIGGER_MODE, + PROP_EXPOSURE_TIME, + PROP_ROI_X, + PROP_ROI_Y, + PROP_ROI_WIDTH, + PROP_ROI_HEIGHT, + PROP_ROI_HEIGHT_MULTIPLIER, + PROP_ROI_WIDTH_MULTIPLIER, + PROP_SENSOR_MAX_FRAME_RATE, + PROP_HAS_STREAMING, + PROP_HAS_CAMRAM_RECORDING, + 0, +}; + +static GParamSpec *mock_properties[N_PROPERTIES] = { NULL, }; + +struct _UcaMockCameraPrivate { + guint width; + guint height; + guint roi_x, roi_y, roi_width, roi_height; + gfloat frame_rate; + gfloat max_frame_rate; + gdouble exposure_time; + guint8 *dummy_data; + guint current_frame; + + gboolean thread_running; + + GThread *grab_thread; + GValueArray *binnings; +}; + +static const char g_digits[10][20] = { + /* 0 */ + { 0x00, 0xff, 0xff, 0x00, + 0xff, 0x00, 0x00, 0xff, + 0xff, 0x00, 0x00, 0xff, + 0xff, 0x00, 0x00, 0xff, + 0x00, 0xff, 0xff, 0x00 }, + /* 1 */ + { 0x00, 0x00, 0xff, 0x00, + 0x00, 0xff, 0xff, 0x00, + 0x00, 0x00, 0xff, 0x00, + 0x00, 0x00, 0xff, 0x00, + 0x00, 0x00, 0xff, 0x00 }, + /* 2 */ + { 0x00, 0xff, 0xff, 0x00, + 0xff, 0x00, 0x00, 0xff, + 0x00, 0x00, 0xff, 0x00, + 0x00, 0xff, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff }, + /* 3 */ + { 0x00, 0xff, 0xff, 0x00, + 0xff, 0x00, 0x00, 0xff, + 0x00, 0x00, 0xff, 0x00, + 0xff, 0x00, 0x00, 0xff, + 0x00, 0xff, 0xff, 0x00 }, + /* 4 */ + { 0xff, 0x00, 0x00, 0x00, + 0xff, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff }, + /* 5 */ + { 0xff, 0xff, 0xff, 0xff, + 0xff, 0x00, 0x00, 0x00, + 0x00, 0xff, 0xff, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0x00 }, + /* 6 */ + { 0x00, 0xff, 0xff, 0xff, + 0xff, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0x00, + 0xff, 0x00, 0x00, 0xff, + 0x00, 0xff, 0xff, 0x00 }, + /* 7 */ + { 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0xff, 0x00, + 0x00, 0xff, 0x00, 0x00, + 0xff, 0x00, 0x00, 0x00 }, + /* 8 */ + { 0x00, 0xff, 0xff, 0x00, + 0xff, 0x00, 0x00, 0xff, + 0x00, 0xff, 0xff, 0x00, + 0xff, 0x00, 0x00, 0xff, + 0x00, 0xff, 0xff, 0x00 }, + /* 9 */ + { 0x00, 0xff, 0xff, 0x00, + 0xff, 0x00, 0x00, 0xff, + 0x00, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0x00 } +}; + +static const guint DIGIT_WIDTH = 4; +static const guint DIGIT_HEIGHT = 5; + +static void print_number(gchar *buffer, guint number, guint x, guint y, guint width) +{ + for (int i = 0; i < DIGIT_WIDTH; i++) { + for (int j = 0; j < DIGIT_HEIGHT; j++) { + buffer[(y+j)*width + (x+i)] = g_digits[number][j*DIGIT_WIDTH+i]; + } + } +} + +static void print_current_frame(UcaMockCameraPrivate *priv, gchar *buffer) +{ + guint number = priv->current_frame; + guint divisor = 100000000; + int x = 10; + while (divisor > 1) { + print_number(buffer, number / divisor, x, 10, priv->width); + number = number % divisor; + divisor = divisor / 10; + x += DIGIT_WIDTH + 1; + } +} + +static gpointer mock_grab_func(gpointer data) +{ + UcaMockCamera *mock_camera = UCA_MOCK_CAMERA(data); + g_return_val_if_fail(UCA_IS_MOCK_CAMERA(mock_camera), NULL); + + UcaMockCameraPrivate *priv = UCA_MOCK_CAMERA_GET_PRIVATE(mock_camera); + UcaCamera *camera = UCA_CAMERA(mock_camera); + const gulong sleep_time = (gulong) G_USEC_PER_SEC / priv->frame_rate; + + while (priv->thread_running) { + camera->grab_func(priv->dummy_data, camera->user_data); + g_usleep(sleep_time); + } + + return NULL; +} + +static void uca_mock_camera_start_recording(UcaCamera *camera, GError **error) +{ + gboolean transfer_async = FALSE; + UcaMockCameraPrivate *priv; + g_return_if_fail(UCA_IS_MOCK_CAMERA(camera)); + + priv = UCA_MOCK_CAMERA_GET_PRIVATE(camera); + /* TODO: check that roi_x + roi_width < priv->width */ + priv->dummy_data = (guint8 *) g_malloc0(priv->roi_width * priv->roi_height); + + g_object_get(G_OBJECT(camera), + "transfer-asynchronously", &transfer_async, + NULL); + + /* + * In case asynchronous transfer is requested, we start a new thread that + * invokes the grab callback, otherwise nothing will be done here. + */ + if (transfer_async) { + GError *tmp_error = NULL; + priv->thread_running = TRUE; + priv->grab_thread = g_thread_create(mock_grab_func, camera, TRUE, &tmp_error); + + if (tmp_error != NULL) { + priv->thread_running = FALSE; + g_propagate_error(error, tmp_error); + } + } +} + +static void uca_mock_camera_stop_recording(UcaCamera *camera, GError **error) +{ + gboolean transfer_async = FALSE; + UcaMockCameraPrivate *priv; + g_return_if_fail(UCA_IS_MOCK_CAMERA(camera)); + + priv = UCA_MOCK_CAMERA_GET_PRIVATE(camera); + g_free(priv->dummy_data); + priv->dummy_data = NULL; + + g_object_get(G_OBJECT(camera), + "transfer-asynchronously", &transfer_async, + NULL); + + if (transfer_async) { + priv->thread_running = FALSE; + g_thread_join(priv->grab_thread); + } +} + +static void uca_mock_camera_grab(UcaCamera *camera, gpointer *data, GError **error) +{ + g_return_if_fail(UCA_IS_MOCK_CAMERA(camera)); + g_return_if_fail(data != NULL); + + UcaMockCameraPrivate *priv = UCA_MOCK_CAMERA_GET_PRIVATE(camera); + + if (*data == NULL) + *data = g_malloc0(priv->width * priv->height); + + g_memmove(*data, priv->dummy_data, priv->width * priv->height); + print_current_frame(priv, *data); + priv->current_frame++; +} + +static void uca_mock_camera_set_property(GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) +{ + g_return_if_fail(UCA_IS_MOCK_CAMERA(object)); + UcaMockCameraPrivate *priv = UCA_MOCK_CAMERA_GET_PRIVATE(object); + + switch (property_id) { + case PROP_EXPOSURE_TIME: + priv->exposure_time = g_value_get_double(value); + break; + case PROP_FRAMERATE: + priv->frame_rate = g_value_get_float(value); + break; + case PROP_ROI_X: + priv->roi_x = g_value_get_uint(value); + break; + case PROP_ROI_Y: + priv->roi_y = g_value_get_uint(value); + break; + case PROP_ROI_WIDTH: + priv->roi_width = g_value_get_uint(value); + break; + case PROP_ROI_HEIGHT: + priv->roi_height = g_value_get_uint(value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); + return; + } +} + +static void uca_mock_camera_get_property(GObject *object, guint property_id, GValue *value, GParamSpec *pspec) +{ + UcaMockCameraPrivate *priv = UCA_MOCK_CAMERA_GET_PRIVATE(object); + + switch (property_id) { + case PROP_NAME: + g_value_set_string(value, "mock camera"); + break; + case PROP_SENSOR_WIDTH: + 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; + case PROP_SENSOR_HORIZONTAL_BINNING: + g_value_set_uint(value, 1); + break; + case PROP_SENSOR_HORIZONTAL_BINNINGS: + g_value_set_boxed(value, priv->binnings); + break; + case PROP_SENSOR_VERTICAL_BINNING: + g_value_set_uint(value, 1); + break; + case PROP_SENSOR_VERTICAL_BINNINGS: + g_value_set_boxed(value, priv->binnings); + break; + case PROP_EXPOSURE_TIME: + g_value_set_double(value, priv->exposure_time); + break; + case PROP_TRIGGER_MODE: + g_value_set_enum(value, UCA_CAMERA_TRIGGER_AUTO); + break; + case PROP_ROI_X: + g_value_set_uint(value, priv->roi_x); + break; + case PROP_ROI_Y: + g_value_set_uint(value, priv->roi_y); + break; + case PROP_ROI_WIDTH: + g_value_set_uint(value, priv->roi_width); + break; + case PROP_ROI_HEIGHT: + g_value_set_uint(value, priv->roi_height); + break; + case PROP_ROI_WIDTH_MULTIPLIER: + g_value_set_uint(value, 1); + break; + case PROP_ROI_HEIGHT_MULTIPLIER: + g_value_set_uint(value, 1); + break; + case PROP_SENSOR_MAX_FRAME_RATE: + g_value_set_float(value, priv->max_frame_rate); + break; + case PROP_HAS_STREAMING: + g_value_set_boolean(value, TRUE); + break; + case PROP_HAS_CAMRAM_RECORDING: + g_value_set_boolean(value, FALSE); + break; + case PROP_FRAMERATE: + g_value_set_float(value, priv->frame_rate); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); + break; + } +} + +static void uca_mock_camera_finalize(GObject *object) +{ + UcaMockCameraPrivate *priv = UCA_MOCK_CAMERA_GET_PRIVATE(object); + + if (priv->thread_running) { + priv->thread_running = FALSE; + g_thread_join(priv->grab_thread); + } + + g_free(priv->dummy_data); + g_value_array_free(priv->binnings); + + G_OBJECT_CLASS(uca_mock_camera_parent_class)->finalize(object); +} + +static void uca_mock_camera_class_init(UcaMockCameraClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS(klass); + gobject_class->set_property = uca_mock_camera_set_property; + 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 i = 0; mock_overrideables[i] != 0; i++) + g_object_class_override_property(gobject_class, mock_overrideables[i], uca_camera_props[mock_overrideables[i]]); + + mock_properties[PROP_FRAMERATE] = + g_param_spec_float("frame-rate", + "Frame rate", + "Number of frames per second that are taken", + 1.0f, 100.0f, 100.0f, + G_PARAM_READWRITE); + + for (guint id = N_BASE_PROPERTIES; id < N_PROPERTIES; id++) + g_object_class_install_property(gobject_class, id, mock_properties[id]); + + g_type_class_add_private(klass, sizeof(UcaMockCameraPrivate)); +} + +static void uca_mock_camera_init(UcaMockCamera *self) +{ + self->priv = UCA_MOCK_CAMERA_GET_PRIVATE(self); + self->priv->roi_x = 0; + self->priv->roi_y = 0; + self->priv->width = self->priv->roi_width = 640; + self->priv->height = self->priv->roi_height = 480; + self->priv->frame_rate = self->priv->max_frame_rate = 100000.0f; + self->priv->grab_thread = NULL; + self->priv->current_frame = 0; + + self->priv->binnings = g_value_array_new(1); + GValue val = {0}; + g_value_init(&val, G_TYPE_UINT); + g_value_set_uint(&val, 1); + g_value_array_append(self->priv->binnings, &val); +} + +G_MODULE_EXPORT UcaCamera * +uca_camera_impl_new (GError **error) +{ + UcaCamera *camera = UCA_CAMERA (g_object_new (UCA_TYPE_MOCK_CAMERA, NULL)); + return camera; +} diff --git a/plugins/mock/uca-mock-camera.h b/plugins/mock/uca-mock-camera.h new file mode 100644 index 0000000..9ee9190 --- /dev/null +++ b/plugins/mock/uca-mock-camera.h @@ -0,0 +1,65 @@ +/* Copyright (C) 2011, 2012 Matthias Vogelgesang + (Karlsruhe Institute of Technology) + + This library is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by the + Free Software Foundation; either version 2.1 of the License, or (at your + option) any later version. + + This library is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + details. + + You should have received a copy of the GNU Lesser General Public License along + with this library; if not, write to the Free Software Foundation, Inc., 51 + Franklin St, Fifth Floor, Boston, MA 02110, USA */ + +#ifndef __UCA_MOCK_CAMERA_H +#define __UCA_MOCK_CAMERA_H + +#include +#include "uca-camera.h" + +G_BEGIN_DECLS + +#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)) +#define UCA_IS_MOCK_CAMERA(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), UCA_TYPE_MOCK_CAMERA)) +#define UCA_MOCK_CAMERA_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), UFO_TYPE_MOCK_CAMERA, UfoMockCameraClass)) +#define UCA_IS_MOCK_CAMERA_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), UCA_TYPE_MOCK_CAMERA)) +#define UCA_MOCK_CAMERA_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), UCA_TYPE_MOCK_CAMERA, UcaMockCameraClass)) + +typedef struct _UcaMockCamera UcaMockCamera; +typedef struct _UcaMockCameraClass UcaMockCameraClass; +typedef struct _UcaMockCameraPrivate UcaMockCameraPrivate; + +/** + * UcaMockCamera: + * + * Creates #UcaMockCamera instances by loading corresponding shared objects. The + * contents of the #UcaMockCamera structure are private and should only be + * accessed via the provided API. + */ +struct _UcaMockCamera { + /*< private >*/ + UcaCamera parent; + + UcaMockCameraPrivate *priv; +}; + +/** + * UcaMockCameraClass: + * + * #UcaMockCamera class + */ +struct _UcaMockCameraClass { + /*< private >*/ + UcaCameraClass parent; +}; + +GType uca_mock_camera_get_type(void); + +G_END_DECLS + +#endif diff --git a/plugins/package-plugin.sh.in b/plugins/package-plugin.sh.in new file mode 100644 index 0000000..c624d52 --- /dev/null +++ b/plugins/package-plugin.sh.in @@ -0,0 +1 @@ +cpack -D CPACK_INSTALL_CMAKE_PROJECTS="${CMAKE_CURRENT_BINARY_DIR}/;Project;${UCA_CAMERA_NAME};/" -D CPACK_PACKAGE_FILE_NAME="uca-plugin-${UCA_CAMERA_NAME}-${UCA_VERSION_MAJOR}.${UCA_VERSION_MINOR}.${UCA_VERSION_PATCH}" diff --git a/plugins/pco/CMakeLists.txt b/plugins/pco/CMakeLists.txt new file mode 100644 index 0000000..7c016b9 --- /dev/null +++ b/plugins/pco/CMakeLists.txt @@ -0,0 +1,30 @@ +cmake_minimum_required(VERSION 2.8) +project(ucapco) + +find_package(PCO) +find_package(FgLib5) +find_package(ClSerMe4) + +if (PCO_FOUND AND CLSERME4_FOUND AND FGLIB5_FOUND) + set(UCA_CAMERA_NAME "pco") + + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/../package-plugin.sh.in + ${CMAKE_CURRENT_BINARY_DIR}/../../package-plugin-${UCA_CAMERA_NAME}.sh) + + include_directories(${PCO_INCLUDE_DIRS} + ${CLSERME4_INCLUDE_DIR} + ${FGLIB5_INCLUDE_DIR}) + + add_library(ucapco SHARED + uca-pco-camera.c) + + target_link_libraries(ucapco + ${UCA_DEPS} + ${PCO_LIBRARIES} + ${CLSERME4_LIBRARY} + ${FGLIB5_LIBRARY}) + + install(TARGETS ucapco + LIBRARY DESTINATION ${LIB_INSTALL_DIR}/uca + COMPONENT ${UCA_CAMERA_NAME}) +endif() diff --git a/plugins/pco/uca-pco-camera.c b/plugins/pco/uca-pco-camera.c new file mode 100644 index 0000000..8bf2936 --- /dev/null +++ b/plugins/pco/uca-pco-camera.c @@ -0,0 +1,1398 @@ +/* Copyright (C) 2011, 2012 Matthias Vogelgesang + (Karlsruhe Institute of Technology) + + This library is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by the + Free Software Foundation; either version 2.1 of the License, or (at your + option) any later version. + + This library is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + details. + + You should have received a copy of the GNU Lesser General Public License along + with this library; if not, write to the Free Software Foundation, Inc., 51 + Franklin St, Fifth Floor, Boston, MA 02110, USA */ + +#include +#include +#include +#include +#include +#include +#include +#include "uca-camera.h" +#include "uca-pco-camera.h" +#include "uca-enums.h" + +#define FG_TRY_PARAM(fg, camobj, param, val_addr, port) \ + { int r = Fg_setParameter(fg, param, val_addr, port); \ + if (r != FG_OK) { \ + g_set_error(error, UCA_PCO_CAMERA_ERROR, \ + UCA_PCO_CAMERA_ERROR_FG_GENERAL, \ + "%s", Fg_getLastErrorDescription(fg)); \ + g_object_unref(camobj); \ + return NULL; \ + } } + +#define FG_SET_ERROR(err, fg, err_type) \ + if (err != FG_OK) { \ + g_set_error(error, UCA_PCO_CAMERA_ERROR, \ + err_type, \ + "%s", Fg_getLastErrorDescription(fg)); \ + return; \ + } + +#define HANDLE_PCO_ERROR(err) \ + if ((err) != PCO_NOERROR) { \ + g_set_error(error, UCA_PCO_CAMERA_ERROR, \ + UCA_PCO_CAMERA_ERROR_LIBPCO_GENERAL,\ + "libpco error %x", err); \ + return; \ + } + +#define UCA_PCO_CAMERA_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), UCA_TYPE_PCO_CAMERA, UcaPcoCameraPrivate)) + +G_DEFINE_TYPE(UcaPcoCamera, uca_pco_camera, UCA_TYPE_CAMERA) + +#define TIMEBASE_INVALID 0xDEAD + +/** + * UcaPcoCameraRecordMode: + * @UCA_PCO_CAMERA_RECORD_MODE_SEQUENCE: Store all frames and stop if necessary + * @UCA_PCO_CAMERA_RECORD_MODE_RING_BUFFER: Store frames in ring-buffer fashion + * and overwrite if necessary + */ + +/** + * UcaPcoCameraAcquireMode: + * @UCA_PCO_CAMERA_ACQUIRE_MODE_AUTO: Take all images + * @UCA_PCO_CAMERA_ACQUIRE_MODE_EXTERNAL: Use signal + */ + +/** + * UcaPcoCameraTimestamp: + * @UCA_PCO_CAMERA_TIMESTAMP_NONE: Don't embed any timestamp + * @UCA_PCO_CAMERA_TIMESTAMP_BINARY: Embed a BCD-coded timestamp in the first + * bytes + * @UCA_PCO_CAMERA_TIMESTAMP_ASCII: Embed a visible ASCII timestamp in the image + */ + +/** + * UcaPcoCameraError: + * @UCA_PCO_CAMERA_ERROR_LIBPCO_INIT: Initializing libpco failed + * @UCA_PCO_CAMERA_ERROR_LIBPCO_GENERAL: General libpco error + * @UCA_PCO_CAMERA_ERROR_UNSUPPORTED: Camera type is not supported + * @UCA_PCO_CAMERA_ERROR_FG_INIT: Framegrabber initialization failed + * @UCA_PCO_CAMERA_ERROR_FG_GENERAL: General framegrabber error + * @UCA_PCO_CAMERA_ERROR_FG_ACQUISITION: Framegrabber acquisition error + */ +GQuark uca_pco_camera_error_quark() +{ + return g_quark_from_static_string("uca-pco-camera-error-quark"); +} + +enum { + PROP_SENSOR_EXTENDED = N_BASE_PROPERTIES, + PROP_SENSOR_WIDTH_EXTENDED, + PROP_SENSOR_HEIGHT_EXTENDED, + PROP_SENSOR_TEMPERATURE, + PROP_SENSOR_PIXELRATES, + PROP_SENSOR_PIXELRATE, + PROP_SENSOR_ADCS, + PROP_SENSOR_MAX_ADCS, + PROP_DELAY_TIME, + PROP_HAS_DOUBLE_IMAGE_MODE, + PROP_DOUBLE_IMAGE_MODE, + PROP_OFFSET_MODE, + PROP_RECORD_MODE, + PROP_ACQUIRE_MODE, + PROP_COOLING_POINT, + PROP_COOLING_POINT_MIN, + PROP_COOLING_POINT_MAX, + PROP_COOLING_POINT_DEFAULT, + PROP_NOISE_FILTER, + PROP_TIMESTAMP_MODE, + N_PROPERTIES +}; + +static gint base_overrideables[] = { + PROP_NAME, + PROP_SENSOR_WIDTH, + PROP_SENSOR_HEIGHT, + PROP_SENSOR_BITDEPTH, + PROP_SENSOR_HORIZONTAL_BINNING, + PROP_SENSOR_HORIZONTAL_BINNINGS, + PROP_SENSOR_VERTICAL_BINNING, + PROP_SENSOR_VERTICAL_BINNINGS, + PROP_SENSOR_MAX_FRAME_RATE, + PROP_EXPOSURE_TIME, + PROP_TRIGGER_MODE, + PROP_ROI_X, + PROP_ROI_Y, + PROP_ROI_WIDTH, + PROP_ROI_HEIGHT, + PROP_ROI_WIDTH_MULTIPLIER, + PROP_ROI_HEIGHT_MULTIPLIER, + PROP_HAS_STREAMING, + PROP_HAS_CAMRAM_RECORDING, + 0 +}; + +static GParamSpec *pco_properties[N_PROPERTIES] = { NULL, }; + +/* + * This structure defines type-specific properties of PCO cameras. + */ +typedef struct { + int camera_type; + const char *so_file; + int cl_type; + int cl_format; + gfloat max_frame_rate; + gboolean has_camram; +} pco_cl_map_entry; + +struct _UcaPcoCameraPrivate { + pco_handle pco; + pco_cl_map_entry *camera_description; + + Fg_Struct *fg; + guint fg_port; + dma_mem *fg_mem; + + guint frame_width; + guint frame_height; + gsize num_bytes; + guint16 *grab_buffer; + + guint16 width, height; + guint16 width_ex, height_ex; + guint16 binning_h, binning_v; + guint16 roi_x, roi_y; + guint16 roi_width, roi_height; + guint16 roi_horizontal_steps, roi_vertical_steps; + GValueArray *horizontal_binnings; + GValueArray *vertical_binnings; + GValueArray *pixelrates; + + /* The time bases are given as pco time bases (TIMEBASE_NS and so on) */ + guint16 delay_timebase; + guint16 exposure_timebase; + + frameindex_t last_frame; + guint16 active_segment; + guint num_recorded_images; + guint current_image; +}; + +static pco_cl_map_entry pco_cl_map[] = { + { CAMERATYPE_PCO_EDGE, "libFullAreaGray8.so", FG_CL_8BIT_FULL_10, FG_GRAY, 30.0f, FALSE }, + { CAMERATYPE_PCO4000, "libDualAreaGray16.so", FG_CL_SINGLETAP_16_BIT, FG_GRAY16, 5.0f, TRUE }, + { CAMERATYPE_PCO_DIMAX_STD, "libFullAreaGray16.so", FG_CL_SINGLETAP_8_BIT, FG_GRAY16, 1279.0f, TRUE }, + { 0, NULL, 0, 0, 0.0f, FALSE } +}; + +static pco_cl_map_entry *get_pco_cl_map_entry(int camera_type) +{ + pco_cl_map_entry *entry = pco_cl_map; + + while (entry->camera_type != 0) { + if (entry->camera_type == camera_type) + return entry; + entry++; + } + + return NULL; +} + +static guint fill_binnings(UcaPcoCameraPrivate *priv) +{ + uint16_t *horizontal = NULL; + uint16_t *vertical = NULL; + guint num_horizontal, num_vertical; + + guint err = pco_get_possible_binnings(priv->pco, + &horizontal, &num_horizontal, + &vertical, &num_vertical); + + GValue val = {0}; + g_value_init(&val, G_TYPE_UINT); + + if (err == PCO_NOERROR) { + priv->horizontal_binnings = g_value_array_new(num_horizontal); + priv->vertical_binnings = g_value_array_new(num_vertical); + + for (guint i = 0; i < num_horizontal; i++) { + g_value_set_uint(&val, horizontal[i]); + g_value_array_append(priv->horizontal_binnings, &val); + } + + for (guint i = 0; i < num_vertical; i++) { + g_value_set_uint(&val, vertical[i]); + g_value_array_append(priv->vertical_binnings, &val); + } + } + + free(horizontal); + free(vertical); + return err; +} + +static void fill_pixelrates(UcaPcoCameraPrivate *priv, guint32 rates[4], gint num_rates) +{ + GValue val = {0}; + g_value_init(&val, G_TYPE_UINT); + priv->pixelrates = g_value_array_new(num_rates); + + for (gint i = 0; i < num_rates; i++) { + g_value_set_uint(&val, (guint) rates[i]); + g_value_array_append(priv->pixelrates, &val); + } +} + +static guint override_temperature_range(UcaPcoCameraPrivate *priv) +{ + int16_t default_temp, min_temp, max_temp; + guint err = pco_get_cooling_range(priv->pco, &default_temp, &min_temp, &max_temp); + + if (err == PCO_NOERROR) { + GParamSpecInt *spec = (GParamSpecInt *) pco_properties[PROP_COOLING_POINT]; + spec->minimum = min_temp; + spec->maximum = max_temp; + spec->default_value = default_temp; + } + else + g_warning("Unable to retrieve cooling range"); + + return err; +} + +static void property_override_default_guint_value (GObjectClass *oclass, const gchar *property_name, guint new_default) +{ + GParamSpecUInt *pspec = G_PARAM_SPEC_UINT (g_object_class_find_property (oclass, property_name)); + + if (pspec != NULL) + pspec->default_value = new_default; + else + g_warning ("pspec for %s not found\n", property_name); +} + +static void override_maximum_adcs(UcaPcoCameraPrivate *priv) +{ + GParamSpecInt *spec = (GParamSpecInt *) pco_properties[PROP_SENSOR_ADCS]; + spec->maximum = pco_get_maximum_number_of_adcs(priv->pco); +} + +static gdouble convert_timebase(guint16 timebase) +{ + switch (timebase) { + case TIMEBASE_NS: + return 1e-9; + case TIMEBASE_US: + return 1e-6; + case TIMEBASE_MS: + return 1e-3; + default: + g_warning("Unknown timebase"); + } + return 1e-3; +} + +static void read_timebase(UcaPcoCameraPrivate *priv) +{ + pco_get_timebase(priv->pco, &priv->delay_timebase, &priv->exposure_timebase); +} + +static gdouble get_suitable_timebase(gdouble time) +{ + if (time * 1e3 >= 1.0) + return TIMEBASE_MS; + if (time * 1e6 >= 1.0) + return TIMEBASE_US; + if (time * 1e9 >= 1.0) + return TIMEBASE_NS; + return TIMEBASE_INVALID; +} + +static int fg_callback(frameindex_t frame, struct fg_apc_data *apc) +{ + UcaCamera *camera = UCA_CAMERA(apc); + UcaPcoCameraPrivate *priv = UCA_PCO_CAMERA_GET_PRIVATE(camera); + gpointer data = Fg_getImagePtrEx(priv->fg, frame, priv->fg_port, priv->fg_mem); + + if (priv->camera_description->camera_type != CAMERATYPE_PCO_EDGE) + camera->grab_func(data, camera->user_data); + else { + pco_get_reorder_func(priv->pco)(priv->grab_buffer, data, priv->frame_width, priv->frame_height); + camera->grab_func(priv->grab_buffer, camera->user_data); + } + + return 0; +} + +static gboolean setup_fg_callback(UcaCamera *camera) +{ + UcaPcoCameraPrivate *priv = UCA_PCO_CAMERA_GET_PRIVATE(camera); + struct FgApcControl ctrl; + + /* Jeez, as if a NULL pointer would not be good enough. */ + ctrl.data = (struct fg_apc_data *) camera; + ctrl.version = 0; + ctrl.func = &fg_callback; + ctrl.flags = FG_APC_DEFAULTS; + ctrl.timeout = 1; + + if (priv->grab_buffer) + g_free(priv->grab_buffer); + + priv->grab_buffer = g_malloc0(priv->frame_width * priv->frame_height * sizeof(guint16)); + + return Fg_registerApcHandler(priv->fg, priv->fg_port, &ctrl, FG_APC_CONTROL_BASIC) == FG_OK; +} + +static void uca_pco_camera_start_recording(UcaCamera *camera, GError **error) +{ + g_return_if_fail(UCA_IS_PCO_CAMERA(camera)); + guint err = PCO_NOERROR; + + UcaPcoCameraPrivate *priv = UCA_PCO_CAMERA_GET_PRIVATE(camera); + guint16 binned_width, binned_height; + gboolean use_extended = FALSE; + gboolean transfer_async = FALSE; + + g_object_get (camera, "sensor-extended", &use_extended, NULL); + + if (use_extended) { + binned_width = priv->width_ex; + binned_height = priv->height_ex; + } + else { + binned_width = priv->width; + binned_height = priv->height; + } + + binned_width /= priv->binning_h; + binned_height /= priv->binning_v; + + if ((priv->roi_x + priv->roi_width > binned_width) || (priv->roi_y + priv->roi_height > binned_height)) { + g_set_error(error, UCA_PCO_CAMERA_ERROR, UCA_PCO_CAMERA_ERROR_UNSUPPORTED, + "ROI of size %ix%i @ (%i, %i) is outside of (binned) sensor size %ix%i\n", + priv->roi_width, priv->roi_height, priv->roi_x, priv->roi_y, binned_width, binned_height); + return; + } + + /* + * All parameters are valid. Now, set them on the camera. + */ + guint16 roi[4] = { priv->roi_x + 1, priv->roi_y + 1, priv->roi_x + priv->roi_width, priv->roi_y + priv->roi_height }; + + if (pco_set_roi(priv->pco, roi) != PCO_NOERROR) { + g_set_error(error, UCA_PCO_CAMERA_ERROR, UCA_PCO_CAMERA_ERROR_LIBPCO_GENERAL, + "Could not set ROI via pco_set_roi()"); + return; + } + + g_object_get(G_OBJECT(camera), "transfer-asynchronously", &transfer_async, NULL); + + /* + * FIXME: We cannot set the binning here as this breaks communication with + * the camera. Setting the binning works _before_ initializing the frame + * grabber though. However, it is rather inconvenient to initialize and + * de-initialize the frame grabber for each recording sequence. + */ + + /* if (pco_set_binning(priv->pco, priv->binning_h, priv->binning_v) != PCO_NOERROR) */ + /* g_warning("Cannot set binning\n"); */ + + if (priv->frame_width != priv->roi_width || priv->frame_height != priv->roi_height || priv->fg_mem == NULL) { + guint fg_width = priv->camera_description->camera_type == CAMERATYPE_PCO_EDGE ? 2 * priv->roi_width : priv->roi_width; + + priv->frame_width = priv->roi_width; + priv->frame_height = priv->roi_height; + priv->num_bytes = 2; + + Fg_setParameter(priv->fg, FG_WIDTH, &fg_width, priv->fg_port); + Fg_setParameter(priv->fg, FG_HEIGHT, &priv->frame_height, priv->fg_port); + + if (priv->fg_mem) + Fg_FreeMemEx(priv->fg, priv->fg_mem); + + const guint num_buffers = 2; + priv->fg_mem = Fg_AllocMemEx(priv->fg, + num_buffers * priv->frame_width * priv->frame_height * sizeof(uint16_t), num_buffers); + + if (priv->fg_mem == NULL) { + g_set_error(error, UCA_PCO_CAMERA_ERROR, UCA_PCO_CAMERA_ERROR_FG_INIT, + "%s", Fg_getLastErrorDescription(priv->fg)); + g_object_unref(camera); + return; + } + } + + if (transfer_async) + setup_fg_callback(camera); + + if ((priv->camera_description->camera_type == CAMERATYPE_PCO_DIMAX_STD) || + (priv->camera_description->camera_type == CAMERATYPE_PCO4000)) + pco_clear_active_segment(priv->pco); + + priv->last_frame = 0; + + err = pco_arm_camera(priv->pco); + HANDLE_PCO_ERROR(err); + + err = pco_start_recording(priv->pco); + HANDLE_PCO_ERROR(err); + + err = Fg_AcquireEx(priv->fg, priv->fg_port, GRAB_INFINITE, ACQ_STANDARD, priv->fg_mem); + FG_SET_ERROR(err, priv->fg, UCA_PCO_CAMERA_ERROR_FG_ACQUISITION); +} + +static void uca_pco_camera_stop_recording(UcaCamera *camera, GError **error) +{ + g_return_if_fail(UCA_IS_PCO_CAMERA(camera)); + UcaPcoCameraPrivate *priv = UCA_PCO_CAMERA_GET_PRIVATE(camera); + + guint err = pco_stop_recording(priv->pco); + HANDLE_PCO_ERROR(err); + + err = Fg_stopAcquireEx(priv->fg, priv->fg_port, priv->fg_mem, STOP_SYNC); + FG_SET_ERROR(err, priv->fg, UCA_PCO_CAMERA_ERROR_FG_ACQUISITION); + + err = Fg_setStatusEx(priv->fg, FG_UNBLOCK_ALL, 0, priv->fg_port, priv->fg_mem); + if (err == FG_INVALID_PARAMETER) + g_warning(" Unable to unblock all\n"); +} + +static void uca_pco_camera_start_readout(UcaCamera *camera, GError **error) +{ + g_return_if_fail(UCA_IS_PCO_CAMERA(camera)); + UcaPcoCameraPrivate *priv = UCA_PCO_CAMERA_GET_PRIVATE(camera); + + /* + * TODO: Check if readout mode is possible. This is not the case for the + * edge. + */ + + guint err = pco_get_active_segment(priv->pco, &priv->active_segment); + HANDLE_PCO_ERROR(err); + + err = pco_get_num_images(priv->pco, priv->active_segment, &priv->num_recorded_images); + HANDLE_PCO_ERROR(err); + + priv->current_image = 1; +} + +static void uca_pco_camera_trigger(UcaCamera *camera, GError **error) +{ + g_return_if_fail(UCA_IS_PCO_CAMERA(camera)); + UcaPcoCameraPrivate *priv = UCA_PCO_CAMERA_GET_PRIVATE(camera); + + /* TODO: Check if we can trigger */ + guint32 success = 0; + pco_force_trigger(priv->pco, &success); + + if (!success) + g_set_error(error, UCA_PCO_CAMERA_ERROR, UCA_PCO_CAMERA_ERROR_LIBPCO_GENERAL, + "Could not trigger frame acquisition"); +} + +static void uca_pco_camera_grab(UcaCamera *camera, gpointer *data, GError **error) +{ + static const gint MAX_TIMEOUT = G_MAXINT; + + g_return_if_fail(UCA_IS_PCO_CAMERA(camera)); + UcaPcoCameraPrivate *priv = UCA_PCO_CAMERA_GET_PRIVATE(camera); + + gboolean is_readout = FALSE; + g_object_get(G_OBJECT(camera), "is-readout", &is_readout, NULL); + + if (is_readout) { + if (priv->current_image == priv->num_recorded_images) { + *data = NULL; + return; + } + + /* + * No joke, the pco firmware allows to read a range of images but + * implements only reading single images ... + */ + pco_read_images(priv->pco, priv->active_segment, priv->current_image, priv->current_image); + priv->current_image++; + } + + pco_request_image(priv->pco); + priv->last_frame = Fg_getLastPicNumberBlockingEx(priv->fg, priv->last_frame+1, priv->fg_port, MAX_TIMEOUT, priv->fg_mem); + + if (priv->last_frame <= 0) { + guint err = FG_OK + 1; + FG_SET_ERROR(err, priv->fg, UCA_PCO_CAMERA_ERROR_FG_GENERAL); + } + + guint16 *frame = Fg_getImagePtrEx(priv->fg, priv->last_frame, priv->fg_port, priv->fg_mem); + + if (*data == NULL) + *data = g_malloc0(priv->frame_width * priv->frame_height * priv->num_bytes); + + if (priv->camera_description->camera_type == CAMERATYPE_PCO_EDGE) + pco_get_reorder_func(priv->pco)((guint16 *) *data, frame, priv->frame_width, priv->frame_height); + else + memcpy((gchar *) *data, (gchar *) frame, priv->frame_width * priv->frame_height * priv->num_bytes); +} + +static void uca_pco_camera_set_property(GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) +{ + UcaPcoCameraPrivate *priv = UCA_PCO_CAMERA_GET_PRIVATE(object); + + switch (property_id) { + case PROP_SENSOR_EXTENDED: + { + guint16 format = g_value_get_boolean (value) ? SENSORFORMAT_EXTENDED : SENSORFORMAT_STANDARD; + pco_set_sensor_format(priv->pco, format); + } + break; + + case PROP_ROI_X: + priv->roi_x = g_value_get_uint(value); + break; + + case PROP_ROI_Y: + priv->roi_y = g_value_get_uint(value); + break; + + case PROP_ROI_WIDTH: + { + guint width = g_value_get_uint(value); + + if (width % priv->roi_horizontal_steps) + g_warning("ROI width %i is not a multiple of %i", width, priv->roi_horizontal_steps); + else + priv->roi_width = width; + } + break; + + case PROP_ROI_HEIGHT: + { + guint height = g_value_get_uint(value); + + if (height % priv->roi_vertical_steps) + g_warning("ROI height %i is not a multiple of %i", height, priv->roi_vertical_steps); + else + priv->roi_height = height; + } + break; + + case PROP_SENSOR_HORIZONTAL_BINNING: + priv->binning_h = g_value_get_uint(value); + break; + + case PROP_SENSOR_VERTICAL_BINNING: + priv->binning_v = g_value_get_uint(value); + break; + + case PROP_EXPOSURE_TIME: + { + const gdouble time = g_value_get_double(value); + + if (priv->exposure_timebase == TIMEBASE_INVALID) + read_timebase(priv); + + /* + * Lets check if we can express the time in the current time + * base. If not, we need to adjust that. + */ + guint16 suitable_timebase = get_suitable_timebase(time); + + if (suitable_timebase == TIMEBASE_INVALID) { + g_warning("Cannot set such a small exposure time"); + } + else { + if (suitable_timebase != priv->exposure_timebase) { + priv->exposure_timebase = suitable_timebase; + if (pco_set_timebase(priv->pco, priv->delay_timebase, suitable_timebase) != PCO_NOERROR) + g_warning("Cannot set exposure time base"); + } + + gdouble timebase = convert_timebase(suitable_timebase); + guint32 timesteps = time / timebase; + if (pco_set_exposure_time(priv->pco, timesteps) != PCO_NOERROR) + g_warning("Cannot set exposure time"); + } + } + break; + + case PROP_DELAY_TIME: + { + const gdouble time = g_value_get_double(value); + + if (priv->delay_timebase == TIMEBASE_INVALID) + read_timebase(priv); + + /* + * Lets check if we can express the time in the current time + * base. If not, we need to adjust that. + */ + guint16 suitable_timebase = get_suitable_timebase(time); + + if (suitable_timebase == TIMEBASE_INVALID) { + if (time == 0.0) { + /* + * If we want to suppress any pre-exposure delays, we + * can set the 0 seconds in whatever time base that is + * currently active. + */ + if (pco_set_delay_time(priv->pco, 0) != PCO_NOERROR) + g_warning("Cannot set zero delay time"); + } + else + g_warning("Cannot set such a small exposure time"); + } + else { + if (suitable_timebase != priv->delay_timebase) { + priv->delay_timebase = suitable_timebase; + if (pco_set_timebase(priv->pco, suitable_timebase, priv->exposure_timebase) != PCO_NOERROR) + g_warning("Cannot set delay time base"); + } + + gdouble timebase = convert_timebase(suitable_timebase); + guint32 timesteps = time / timebase; + if (pco_set_delay_time(priv->pco, timesteps) != PCO_NOERROR) + g_warning("Cannot set delay time"); + } + } + break; + + case PROP_SENSOR_ADCS: + { + const guint num_adcs = g_value_get_uint(value); + if (pco_set_adc_mode(priv->pco, num_adcs) != PCO_NOERROR) + g_warning("Cannot set the number of ADCs per pixel\n"); + } + break; + + case PROP_SENSOR_PIXELRATE: + { + guint desired_pixel_rate = g_value_get_uint(value); + guint32 pixel_rate = 0; + + for (guint i = 0; i < priv->pixelrates->n_values; i++) { + if (g_value_get_uint(g_value_array_get_nth(priv->pixelrates, i)) == desired_pixel_rate) { + pixel_rate = desired_pixel_rate; + break; + } + } + + if (pixel_rate != 0) { + if (pco_set_pixelrate(priv->pco, pixel_rate) != PCO_NOERROR) + g_warning("Cannot set pixel rate"); + } + else + g_warning("%i Hz is not possible. Please check the \"sensor-pixelrates\" property", desired_pixel_rate); + } + break; + + case PROP_DOUBLE_IMAGE_MODE: + if (!pco_is_double_image_mode_available(priv->pco)) + g_warning("Double image mode is not available on this pco model"); + else + pco_set_double_image_mode(priv->pco, g_value_get_boolean(value)); + break; + + case PROP_OFFSET_MODE: + pco_set_offset_mode(priv->pco, g_value_get_boolean(value)); + break; + + case PROP_COOLING_POINT: + { + int16_t temperature = (int16_t) g_value_get_int(value); + pco_set_cooling_temperature(priv->pco, temperature); + } + break; + + case PROP_RECORD_MODE: + { + /* TODO: setting this is not possible for the edge */ + UcaPcoCameraRecordMode mode = (UcaPcoCameraRecordMode) g_value_get_enum(value); + + if (mode == UCA_PCO_CAMERA_RECORD_MODE_SEQUENCE) + pco_set_record_mode(priv->pco, RECORDER_SUBMODE_SEQUENCE); + else if (mode == UCA_PCO_CAMERA_RECORD_MODE_RING_BUFFER) + pco_set_record_mode(priv->pco, RECORDER_SUBMODE_RINGBUFFER); + else + g_warning("Unknown record mode"); + } + break; + + case PROP_ACQUIRE_MODE: + { + UcaPcoCameraAcquireMode mode = (UcaPcoCameraAcquireMode) g_value_get_enum(value); + unsigned int err = PCO_NOERROR; + + if (mode == UCA_PCO_CAMERA_ACQUIRE_MODE_AUTO) + err = pco_set_acquire_mode(priv->pco, ACQUIRE_MODE_AUTO); + else if (mode == UCA_PCO_CAMERA_ACQUIRE_MODE_EXTERNAL) + err = pco_set_acquire_mode(priv->pco, ACQUIRE_MODE_EXTERNAL); + else + g_warning("Unknown acquire mode"); + + if (err != PCO_NOERROR) + g_warning("Cannot set acquire mode"); + } + break; + + case PROP_TRIGGER_MODE: + { + UcaCameraTrigger trigger_mode = (UcaCameraTrigger) g_value_get_enum(value); + + switch (trigger_mode) { + case UCA_CAMERA_TRIGGER_AUTO: + pco_set_trigger_mode(priv->pco, TRIGGER_MODE_AUTOTRIGGER); + break; + case UCA_CAMERA_TRIGGER_INTERNAL: + pco_set_trigger_mode(priv->pco, TRIGGER_MODE_SOFTWARETRIGGER); + break; + case UCA_CAMERA_TRIGGER_EXTERNAL: + pco_set_trigger_mode(priv->pco, TRIGGER_MODE_EXTERNALTRIGGER); + break; + } + } + break; + + case PROP_NOISE_FILTER: + { + guint16 filter_mode = g_value_get_boolean(value) ? NOISE_FILTER_MODE_ON : NOISE_FILTER_MODE_OFF; + pco_set_noise_filter_mode(priv->pco, filter_mode); + } + break; + + case PROP_TIMESTAMP_MODE: + { + guint16 modes[] = { + TIMESTAMP_MODE_OFF, /* 0 */ + TIMESTAMP_MODE_BINARY, /* 1 = 1 << 0 */ + TIMESTAMP_MODE_ASCII, /* 2 = 1 << 1 */ + TIMESTAMP_MODE_BINARYANDASCII, /* 3 = 1 << 0 | 1 << 1 */ + }; + pco_set_timestamp_mode(priv->pco, modes[g_value_get_flags(value)]); + } + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); + return; + } +} + +static void uca_pco_camera_get_property(GObject *object, guint property_id, GValue *value, GParamSpec *pspec) +{ + UcaPcoCameraPrivate *priv = UCA_PCO_CAMERA_GET_PRIVATE(object); + + switch (property_id) { + case PROP_SENSOR_EXTENDED: + { + guint16 format; + pco_get_sensor_format(priv->pco, &format); + g_value_set_boolean(value, format == SENSORFORMAT_EXTENDED); + } + break; + + case PROP_SENSOR_WIDTH: + g_value_set_uint(value, priv->width); + break; + + case PROP_SENSOR_HEIGHT: + g_value_set_uint(value, priv->height); + break; + + case PROP_SENSOR_WIDTH_EXTENDED: + g_value_set_uint(value, priv->width_ex < priv->width ? priv->width : priv->width_ex); + break; + + case PROP_SENSOR_HEIGHT_EXTENDED: + g_value_set_uint(value, priv->height_ex < priv->height ? priv->height : priv->height_ex); + break; + + case PROP_SENSOR_HORIZONTAL_BINNING: + g_value_set_uint(value, priv->binning_h); + break; + + case PROP_SENSOR_HORIZONTAL_BINNINGS: + g_value_set_boxed(value, priv->horizontal_binnings); + break; + + case PROP_SENSOR_VERTICAL_BINNING: + g_value_set_uint(value, priv->binning_v); + break; + + case PROP_SENSOR_VERTICAL_BINNINGS: + g_value_set_boxed(value, priv->vertical_binnings); + break; + + case PROP_SENSOR_MAX_FRAME_RATE: + g_value_set_float(value, priv->camera_description->max_frame_rate); + break; + + case PROP_SENSOR_BITDEPTH: + g_value_set_uint(value, 16); + break; + + case PROP_SENSOR_TEMPERATURE: + { + gint32 ccd, camera, power; + pco_get_temperature(priv->pco, &ccd, &camera, &power); + g_value_set_double(value, ccd / 10.0); + } + break; + + case PROP_SENSOR_ADCS: + { + /* + * Up to now, the ADC mode corresponds directly to the number of + * ADCs in use. + */ + pco_adc_mode mode; + if (pco_get_adc_mode(priv->pco, &mode) != PCO_NOERROR) + g_warning("Cannot read number of ADCs per pixel"); + g_value_set_uint(value, mode); + } + break; + + case PROP_SENSOR_MAX_ADCS: + { + GParamSpecUInt *spec = (GParamSpecUInt *) pco_properties[PROP_SENSOR_ADCS]; + g_value_set_uint(value, spec->maximum); + } + break; + + case PROP_SENSOR_PIXELRATES: + g_value_set_boxed(value, priv->pixelrates); + break; + + case PROP_SENSOR_PIXELRATE: + { + guint32 pixelrate; + pco_get_pixelrate(priv->pco, &pixelrate); + g_value_set_uint(value, pixelrate); + } + break; + + case PROP_EXPOSURE_TIME: + { + uint32_t exposure_time; + pco_get_exposure_time(priv->pco, &exposure_time); + + if (priv->exposure_timebase == TIMEBASE_INVALID) + read_timebase(priv); + + g_value_set_double(value, convert_timebase(priv->exposure_timebase) * exposure_time); + } + break; + + case PROP_DELAY_TIME: + { + uint32_t delay_time; + pco_get_delay_time(priv->pco, &delay_time); + + if (priv->delay_timebase == TIMEBASE_INVALID) + read_timebase(priv); + + g_value_set_double(value, convert_timebase(priv->delay_timebase) * delay_time); + } + break; + + case PROP_HAS_DOUBLE_IMAGE_MODE: + g_value_set_boolean(value, pco_is_double_image_mode_available(priv->pco)); + break; + + case PROP_DOUBLE_IMAGE_MODE: + if (!pco_is_double_image_mode_available(priv->pco)) + g_warning("Double image mode is not available on this pco model"); + else { + bool on; + pco_get_double_image_mode(priv->pco, &on); + g_value_set_boolean(value, on); + } + break; + + case PROP_OFFSET_MODE: + { + bool on; + pco_get_offset_mode(priv->pco, &on); + g_value_set_boolean(value, on); + } + break; + + case PROP_HAS_STREAMING: + g_value_set_boolean(value, TRUE); + break; + + case PROP_HAS_CAMRAM_RECORDING: + g_value_set_boolean(value, priv->camera_description->has_camram); + break; + + case PROP_RECORD_MODE: + { + guint16 mode; + pco_get_record_mode(priv->pco, &mode); + + if (mode == RECORDER_SUBMODE_SEQUENCE) + g_value_set_enum(value, UCA_PCO_CAMERA_RECORD_MODE_SEQUENCE); + else if (mode == RECORDER_SUBMODE_RINGBUFFER) + g_value_set_enum(value, UCA_PCO_CAMERA_RECORD_MODE_RING_BUFFER); + else + g_warning("pco record mode not handled"); + } + break; + + case PROP_ACQUIRE_MODE: + { + guint16 mode; + pco_get_acquire_mode(priv->pco, &mode); + + if (mode == ACQUIRE_MODE_AUTO) + g_value_set_enum(value, UCA_PCO_CAMERA_ACQUIRE_MODE_AUTO); + else if (mode == ACQUIRE_MODE_EXTERNAL) + g_value_set_enum(value, UCA_PCO_CAMERA_ACQUIRE_MODE_EXTERNAL); + else + g_warning("pco acquire mode not handled"); + } + break; + + case PROP_TRIGGER_MODE: + { + guint16 mode; + pco_get_trigger_mode(priv->pco, &mode); + + switch (mode) { + case TRIGGER_MODE_AUTOTRIGGER: + g_value_set_enum(value, UCA_CAMERA_TRIGGER_AUTO); + break; + case TRIGGER_MODE_SOFTWARETRIGGER: + g_value_set_enum(value, UCA_CAMERA_TRIGGER_INTERNAL); + break; + case TRIGGER_MODE_EXTERNALTRIGGER: + g_value_set_enum(value, UCA_CAMERA_TRIGGER_EXTERNAL); + break; + default: + g_warning("pco trigger mode not handled"); + } + } + break; + + case PROP_ROI_X: + g_value_set_uint(value, priv->roi_x); + break; + + case PROP_ROI_Y: + g_value_set_uint(value, priv->roi_y); + break; + + case PROP_ROI_WIDTH: + g_value_set_uint(value, priv->roi_width); + break; + + case PROP_ROI_HEIGHT: + g_value_set_uint(value, priv->roi_height); + break; + + case PROP_ROI_WIDTH_MULTIPLIER: + g_value_set_uint(value, priv->roi_horizontal_steps); + break; + + case PROP_ROI_HEIGHT_MULTIPLIER: + g_value_set_uint(value, priv->roi_vertical_steps); + break; + + case PROP_NAME: + { + gchar *name = NULL; + pco_get_name(priv->pco, &name); + g_value_set_string(value, name); + g_free(name); + } + break; + + case PROP_COOLING_POINT: + { + int16_t temperature; + if (pco_get_cooling_temperature(priv->pco, &temperature) != PCO_NOERROR) + g_warning("Cannot read cooling temperature\n"); + g_value_set_int(value, temperature); + } + break; + + case PROP_COOLING_POINT_MIN: + { + GParamSpecInt *spec = (GParamSpecInt *) pco_properties[PROP_COOLING_POINT]; + g_value_set_int(value, spec->minimum); + } + break; + + case PROP_COOLING_POINT_MAX: + { + GParamSpecInt *spec = (GParamSpecInt *) pco_properties[PROP_COOLING_POINT]; + g_value_set_int(value, spec->maximum); + } + break; + + case PROP_COOLING_POINT_DEFAULT: + { + GParamSpecInt *spec = (GParamSpecInt *) pco_properties[PROP_COOLING_POINT]; + g_value_set_int(value, spec->default_value); + } + break; + + case PROP_NOISE_FILTER: + { + guint16 mode; + pco_get_noise_filter_mode(priv->pco, &mode); + g_value_set_boolean(value, mode != NOISE_FILTER_MODE_OFF); + } + break; + + case PROP_TIMESTAMP_MODE: + { + guint16 mode; + pco_get_timestamp_mode(priv->pco, &mode); + + switch (mode) { + case TIMESTAMP_MODE_OFF: + g_value_set_flags(value, UCA_PCO_CAMERA_TIMESTAMP_NONE); + break; + case TIMESTAMP_MODE_BINARY: + g_value_set_flags(value, UCA_PCO_CAMERA_TIMESTAMP_BINARY); + break; + case TIMESTAMP_MODE_BINARYANDASCII: + g_value_set_flags(value, + UCA_PCO_CAMERA_TIMESTAMP_BINARY | UCA_PCO_CAMERA_TIMESTAMP_ASCII); + break; + case TIMESTAMP_MODE_ASCII: + g_value_set_flags(value, UCA_PCO_CAMERA_TIMESTAMP_ASCII); + break; + } + } + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); + break; + } +} + +static void uca_pco_camera_finalize(GObject *object) +{ + UcaPcoCameraPrivate *priv = UCA_PCO_CAMERA_GET_PRIVATE(object); + + if (priv->horizontal_binnings) + g_value_array_free(priv->horizontal_binnings); + + if (priv->vertical_binnings) + g_value_array_free(priv->vertical_binnings); + + if (priv->pixelrates) + g_value_array_free(priv->pixelrates); + + if (priv->fg) { + if (priv->fg_mem) + Fg_FreeMemEx(priv->fg, priv->fg_mem); + + Fg_FreeGrabber(priv->fg); + } + + if (priv->pco) + pco_destroy(priv->pco); + + g_free(priv->grab_buffer); + + G_OBJECT_CLASS(uca_pco_camera_parent_class)->finalize(object); +} + +static void uca_pco_camera_class_init(UcaPcoCameraClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS(klass); + gobject_class->set_property = uca_pco_camera_set_property; + 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->start_readout = uca_pco_camera_start_readout; + camera_class->trigger = uca_pco_camera_trigger; + camera_class->grab = uca_pco_camera_grab; + + for (guint i = 0; base_overrideables[i] != 0; i++) + g_object_class_override_property(gobject_class, base_overrideables[i], uca_camera_props[base_overrideables[i]]); + + /** + * UcaPcoCamera:sensor-extended: + * + * Activate larger sensor area that contains surrounding pixels for dark + * references and dummies. Use #UcaPcoCamera:sensor-width-extended and + * #UcaPcoCamera:sensor-height-extended to query the resolution of the + * larger area. + */ + pco_properties[PROP_SENSOR_EXTENDED] = + g_param_spec_boolean("sensor-extended", + "Use extended sensor format", + "Use extended sensor format", + FALSE, G_PARAM_READWRITE); + + pco_properties[PROP_SENSOR_WIDTH_EXTENDED] = + g_param_spec_uint("sensor-width-extended", + "Width of extended sensor", + "Width of the extended sensor in pixels", + 1, G_MAXUINT, 1, + G_PARAM_READABLE); + + pco_properties[PROP_SENSOR_HEIGHT_EXTENDED] = + g_param_spec_uint("sensor-height-extended", + "Height of extended sensor", + "Height of the extended sensor in pixels", + 1, G_MAXUINT, 1, + G_PARAM_READABLE); + + /** + * UcaPcoCamera:sensor-pixelrate: + * + * Read and write the pixel rate or clock of the sensor in terms of Hertz. + * Make sure to query the possible pixel rates through the + * #UcaPcoCamera:sensor-pixelrates property. Any other value will be + * rejected by the camera. + */ + pco_properties[PROP_SENSOR_PIXELRATE] = + g_param_spec_uint("sensor-pixelrate", + "Pixel rate", + "Pixel rate", + 1, G_MAXUINT, 1, + G_PARAM_READWRITE); + + pco_properties[PROP_SENSOR_PIXELRATES] = + g_param_spec_value_array("sensor-pixelrates", + "Array of possible sensor pixel rates", + "Array of possible sensor pixel rates", + pco_properties[PROP_SENSOR_PIXELRATE], + G_PARAM_READABLE); + + pco_properties[PROP_NAME] = + g_param_spec_string("name", + "Name of the camera", + "Name of the camera", + "", G_PARAM_READABLE); + + pco_properties[PROP_SENSOR_TEMPERATURE] = + g_param_spec_double("sensor-temperature", + "Temperature of the sensor", + "Temperature of the sensor in degree Celsius", + -G_MAXDOUBLE, G_MAXDOUBLE, 0.0, + G_PARAM_READABLE); + + pco_properties[PROP_HAS_DOUBLE_IMAGE_MODE] = + g_param_spec_boolean("has-double-image-mode", + "Is double image mode supported by this model", + "Is double image mode supported by this model", + FALSE, G_PARAM_READABLE); + + pco_properties[PROP_DOUBLE_IMAGE_MODE] = + g_param_spec_boolean("double-image-mode", + "Use double image mode", + "Use double image mode", + FALSE, G_PARAM_READWRITE); + + pco_properties[PROP_OFFSET_MODE] = + g_param_spec_boolean("offset-mode", + "Use offset mode", + "Use offset mode", + FALSE, G_PARAM_READWRITE); + + pco_properties[PROP_RECORD_MODE] = + g_param_spec_enum("record-mode", + "Record mode", + "Record mode", + UCA_TYPE_PCO_CAMERA_RECORD_MODE, UCA_PCO_CAMERA_RECORD_MODE_SEQUENCE, + G_PARAM_READWRITE); + + pco_properties[PROP_ACQUIRE_MODE] = + g_param_spec_enum("acquire-mode", + "Acquire mode", + "Acquire mode", + UCA_TYPE_PCO_CAMERA_ACQUIRE_MODE, UCA_PCO_CAMERA_ACQUIRE_MODE_AUTO, + G_PARAM_READWRITE); + + pco_properties[PROP_DELAY_TIME] = + g_param_spec_double("delay-time", + "Delay time", + "Delay before starting actual exposure", + 0.0, G_MAXDOUBLE, 0.0, + G_PARAM_READWRITE); + + pco_properties[PROP_NOISE_FILTER] = + g_param_spec_boolean("noise-filter", + "Noise filter", + "Noise filter", + FALSE, G_PARAM_READWRITE); + + /** + * UcaPcoCamera:cooling-point: + * + * The value range is set arbitrarily, because we are not yet connected to + * the camera and just don't know the cooling range. We override these + * values in #uca_pco_camera_new(). + */ + pco_properties[PROP_COOLING_POINT] = + g_param_spec_int("cooling-point", + "Cooling point of the camera", + "Cooling point of the camera in degree celsius", + 0, 10, 5, G_PARAM_READWRITE); + + pco_properties[PROP_COOLING_POINT_MIN] = + g_param_spec_int("cooling-point-min", + "Minimum cooling point", + "Minimum cooling point in degree celsius", + G_MININT, G_MAXINT, 0, G_PARAM_READABLE); + + pco_properties[PROP_COOLING_POINT_MAX] = + g_param_spec_int("cooling-point-max", + "Maximum cooling point", + "Maximum cooling point in degree celsius", + G_MININT, G_MAXINT, 0, G_PARAM_READABLE); + + pco_properties[PROP_COOLING_POINT_DEFAULT] = + g_param_spec_int("cooling-point-default", + "Default cooling point", + "Default cooling point in degree celsius", + G_MININT, G_MAXINT, 0, G_PARAM_READABLE); + + pco_properties[PROP_SENSOR_ADCS] = + g_param_spec_uint("sensor-adcs", + "Number of ADCs to use", + "Number of ADCs to use", + 1, 2, 1, + G_PARAM_READWRITE); + + pco_properties[PROP_SENSOR_MAX_ADCS] = + g_param_spec_uint("sensor-max-adcs", + "Maximum number of ADCs", + "Maximum number of ADCs that can be set with \"sensor-adcs\"", + 1, G_MAXUINT, 1, + G_PARAM_READABLE); + + pco_properties[PROP_TIMESTAMP_MODE] = + g_param_spec_flags("timestamp-mode", + "Timestamp mode", + "Timestamp mode", + UCA_TYPE_PCO_CAMERA_TIMESTAMP, UCA_PCO_CAMERA_TIMESTAMP_NONE, + G_PARAM_READWRITE); + + for (guint id = N_BASE_PROPERTIES; id < N_PROPERTIES; id++) + g_object_class_install_property(gobject_class, id, pco_properties[id]); + + g_type_class_add_private(klass, sizeof(UcaPcoCameraPrivate)); +} + +static void uca_pco_camera_init(UcaPcoCamera *self) +{ + self->priv = UCA_PCO_CAMERA_GET_PRIVATE(self); + self->priv->fg = NULL; + self->priv->fg_mem = NULL; + self->priv->pco = NULL; + self->priv->horizontal_binnings = NULL; + self->priv->vertical_binnings = NULL; + self->priv->pixelrates = NULL; + self->priv->camera_description = NULL; + self->priv->last_frame = 0; + self->priv->grab_buffer = NULL; + + self->priv->delay_timebase = TIMEBASE_INVALID; + self->priv->exposure_timebase = TIMEBASE_INVALID; +} + +G_MODULE_EXPORT UcaCamera * +uca_camera_impl_new (GError **error) +{ + pco_handle pco = pco_init(); + + if (pco == NULL) { + g_set_error(error, UCA_PCO_CAMERA_ERROR, UCA_PCO_CAMERA_ERROR_LIBPCO_INIT, + "Initializing libpco failed"); + return NULL; + } + + UcaPcoCamera *camera = g_object_new(UCA_TYPE_PCO_CAMERA, NULL); + UcaPcoCameraPrivate *priv = UCA_PCO_CAMERA_GET_PRIVATE(camera); + priv->pco = pco; + + pco_get_resolution(priv->pco, &priv->width, &priv->height, &priv->width_ex, &priv->height_ex); + pco_get_binning(priv->pco, &priv->binning_h, &priv->binning_v); + pco_set_storage_mode(pco, STORAGE_MODE_RECORDER); + pco_set_auto_transfer(pco, 1); + + guint16 roi[4]; + pco_get_roi(priv->pco, roi); + pco_get_roi_steps(priv->pco, &priv->roi_horizontal_steps, &priv->roi_vertical_steps); + + priv->roi_x = roi[0] - 1; + priv->roi_y = roi[1] - 1; + priv->roi_width = roi[2] - roi[0] + 1; + priv->roi_height = roi[3] - roi[1] + 1; + + guint16 camera_type, camera_subtype; + pco_get_camera_type(priv->pco, &camera_type, &camera_subtype); + pco_cl_map_entry *map_entry = get_pco_cl_map_entry(camera_type); + priv->camera_description = map_entry; + + if (map_entry == NULL) { + g_set_error(error, UCA_PCO_CAMERA_ERROR, UCA_PCO_CAMERA_ERROR_UNSUPPORTED, + "Camera type is not supported"); + g_object_unref(camera); + return NULL; + } + + priv->fg_port = PORT_A; + priv->fg = Fg_Init(map_entry->so_file, priv->fg_port); + + if (priv->fg == NULL) { + g_set_error(error, UCA_PCO_CAMERA_ERROR, UCA_PCO_CAMERA_ERROR_FG_INIT, + "%s", Fg_getLastErrorDescription(priv->fg)); + g_object_unref(camera); + return NULL; + } + + const guint32 fg_height = priv->height; + const guint32 fg_width = camera_type == CAMERATYPE_PCO_EDGE ? priv->width * 2 : priv->width; + + FG_TRY_PARAM(priv->fg, camera, FG_CAMERA_LINK_CAMTYP, &map_entry->cl_type, priv->fg_port); + FG_TRY_PARAM(priv->fg, camera, FG_FORMAT, &map_entry->cl_format, priv->fg_port); + FG_TRY_PARAM(priv->fg, camera, FG_WIDTH, &fg_width, priv->fg_port); + FG_TRY_PARAM(priv->fg, camera, FG_HEIGHT, &fg_height, priv->fg_port); + + int val = FREE_RUN; + FG_TRY_PARAM(priv->fg, camera, FG_TRIGGERMODE, &val, priv->fg_port); + + fill_binnings(priv); + + /* + * Here we override property ranges because we didn't know them at property + * installation time. + */ + GObjectClass *camera_class = G_OBJECT_CLASS (UCA_CAMERA_GET_CLASS (camera)); + property_override_default_guint_value (camera_class, "roi-width", priv->width); + property_override_default_guint_value (camera_class, "roi-height", priv->height); + + guint32 rates[4] = {0}; + gint num_rates = 0; + + if (pco_get_available_pixelrates(priv->pco, rates, &num_rates) == PCO_NOERROR) { + GObjectClass *pco_camera_class = G_OBJECT_CLASS (UCA_PCO_CAMERA_GET_CLASS (camera)); + + fill_pixelrates(priv, rates, num_rates); + property_override_default_guint_value (pco_camera_class, "sensor-pixelrate", rates[0]); + } + + override_temperature_range (priv); + override_maximum_adcs (priv); + + return UCA_CAMERA (camera); +} diff --git a/plugins/pco/uca-pco-camera.h b/plugins/pco/uca-pco-camera.h new file mode 100644 index 0000000..73ae44e --- /dev/null +++ b/plugins/pco/uca-pco-camera.h @@ -0,0 +1,91 @@ +/* Copyright (C) 2011, 2012 Matthias Vogelgesang + (Karlsruhe Institute of Technology) + + This library is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by the + Free Software Foundation; either version 2.1 of the License, or (at your + option) any later version. + + This library is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + details. + + You should have received a copy of the GNU Lesser General Public License along + with this library; if not, write to the Free Software Foundation, Inc., 51 + Franklin St, Fifth Floor, Boston, MA 02110, USA */ + +#ifndef __UCA_PCO_CAMERA_H +#define __UCA_PCO_CAMERA_H + +#include +#include "uca-camera.h" + +G_BEGIN_DECLS + +#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)) +#define UCA_IS_PCO_CAMERA(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), UCA_TYPE_PCO_CAMERA)) +#define UCA_PCO_CAMERA_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), UCA_TYPE_PCO_CAMERA, UcaPcoCameraClass)) +#define UCA_IS_PCO_CAMERA_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), UCA_TYPE_PCO_CAMERA)) +#define UCA_PCO_CAMERA_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), UCA_TYPE_PCO_CAMERA, UcaPcoCameraClass)) + +#define UCA_PCO_CAMERA_ERROR uca_pco_camera_error_quark() +typedef enum { + UCA_PCO_CAMERA_ERROR_LIBPCO_INIT, + UCA_PCO_CAMERA_ERROR_LIBPCO_GENERAL, + UCA_PCO_CAMERA_ERROR_UNSUPPORTED, + UCA_PCO_CAMERA_ERROR_FG_INIT, + UCA_PCO_CAMERA_ERROR_FG_GENERAL, + UCA_PCO_CAMERA_ERROR_FG_ACQUISITION +} UcaPcoCameraError; + +typedef struct _UcaPcoCamera UcaPcoCamera; +typedef struct _UcaPcoCameraClass UcaPcoCameraClass; +typedef struct _UcaPcoCameraPrivate UcaPcoCameraPrivate; + +typedef enum { + UCA_PCO_CAMERA_RECORD_MODE_SEQUENCE, + UCA_PCO_CAMERA_RECORD_MODE_RING_BUFFER, +} UcaPcoCameraRecordMode; + +typedef enum { + UCA_PCO_CAMERA_ACQUIRE_MODE_AUTO, + UCA_PCO_CAMERA_ACQUIRE_MODE_EXTERNAL +} UcaPcoCameraAcquireMode; + +typedef enum { + UCA_PCO_CAMERA_TIMESTAMP_NONE = 0, + UCA_PCO_CAMERA_TIMESTAMP_BINARY = 1 << 0, + UCA_PCO_CAMERA_TIMESTAMP_ASCII = 1 << 1 +} UcaPcoCameraTimestamp; + +/** + * UcaPcoCamera: + * + * Creates #UcaPcoCamera instances by loading corresponding shared objects. The + * contents of the #UcaPcoCamera structure are private and should only be + * accessed via the provided API. + */ +struct _UcaPcoCamera { + /*< private >*/ + UcaCamera parent; + + UcaPcoCameraPrivate *priv; +}; + +/** + * UcaPcoCameraClass: + * + * #UcaPcoCamera class + */ +struct _UcaPcoCameraClass { + /*< private >*/ + UcaCameraClass parent; +}; + +GType uca_pco_camera_get_type(void); + +G_END_DECLS + +#endif diff --git a/plugins/pf/CMakeLists.txt b/plugins/pf/CMakeLists.txt new file mode 100644 index 0000000..f392603 --- /dev/null +++ b/plugins/pf/CMakeLists.txt @@ -0,0 +1,30 @@ +cmake_minimum_required(VERSION 2.8) +project(ucapf) + +find_package(PF) +find_package(FgLib5) +find_package(ClSerMe4) + +if (PF_FOUND AND CLSERME4_FOUND AND FGLIB5_FOUND) + set(UCA_CAMERA_NAME "pco") + + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/../package-plugin.sh.in + ${CMAKE_CURRENT_BINARY_DIR}/../../package-plugin-${UCA_CAMERA_NAME}.sh) + + include_directories(${PF_INCLUDE_DIRS} + ${CLSERME4_INCLUDE_DIR} + ${FGLIB5_INCLUDE_DIR}) + + add_library(ucapf SHARED + uca-pf-camera.c) + + target_link_libraries(ucapf + ${UCA_DEPS} + ${PF_LIBRARIES} + ${CLSERME4_LIBRARY} + ${FGLIB5_LIBRARY}) + + install(TARGETS ucapf + LIBRARY DESTINATION ${LIB_INSTALL_DIR}/uca + COMPONENT ${UCA_CAMERA_NAME}) +endif() diff --git a/plugins/pf/uca-pf-camera.c b/plugins/pf/uca-pf-camera.c new file mode 100644 index 0000000..35b5edd --- /dev/null +++ b/plugins/pf/uca-pf-camera.c @@ -0,0 +1,351 @@ +/* Copyright (C) 2011, 2012 Matthias Vogelgesang + (Karlsruhe Institute of Technology) + + This library is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by the + Free Software Foundation; either version 2.1 of the License, or (at your + option) any later version. + + This library is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + details. + + You should have received a copy of the GNU Lesser General Public License along + with this library; if not, write to the Free Software Foundation, Inc., 51 + Franklin St, Fifth Floor, Boston, MA 02110, USA */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "uca-camera.h" +#include "uca-pf-camera.h" + +#define FG_TRY_PARAM(fg, camobj, param, val_addr, port) \ + { int r = Fg_setParameter(fg, param, val_addr, port); \ + if (r != FG_OK) { \ + g_set_error(error, UCA_PF_CAMERA_ERROR, \ + UCA_PF_CAMERA_ERROR_FG_GENERAL, \ + "%s", Fg_getLastErrorDescription(fg)); \ + g_object_unref(camobj); \ + return NULL; \ + } } + +#define FG_SET_ERROR(err, fg, err_type) \ + if (err != FG_OK) { \ + g_set_error(error, UCA_PF_CAMERA_ERROR, \ + err_type, \ + "%s", Fg_getLastErrorDescription(fg)); \ + return; \ + } + +#define UCA_PF_CAMERA_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), UCA_TYPE_PF_CAMERA, UcaPfCameraPrivate)) + +G_DEFINE_TYPE(UcaPfCamera, uca_pf_camera, UCA_TYPE_CAMERA) + +/** + * UcaPfCameraError: + * @UCA_PF_CAMERA_ERROR_INIT: Initializing pcilib failed + * @UCA_PF_CAMERA_ERROR_FG_GENERAL: Frame grabber errors + * @UCA_PF_CAMERA_ERROR_FG_ACQUISITION: Acquisition errors related to the frame + * grabber + * @UCA_PF_CAMERA_ERROR_START_RECORDING: Starting failed + * @UCA_PF_CAMERA_ERROR_STOP_RECORDING: Stopping failed + */ +GQuark uca_pf_camera_error_quark() +{ + return g_quark_from_static_string("uca-pf-camera-error-quark"); +} + +static gint base_overrideables[] = { + PROP_NAME, + PROP_SENSOR_WIDTH, + PROP_SENSOR_HEIGHT, + PROP_SENSOR_BITDEPTH, + PROP_SENSOR_HORIZONTAL_BINNING, + PROP_SENSOR_HORIZONTAL_BINNINGS, + PROP_SENSOR_VERTICAL_BINNING, + PROP_SENSOR_VERTICAL_BINNINGS, + PROP_SENSOR_MAX_FRAME_RATE, + PROP_EXPOSURE_TIME, + PROP_ROI_X, + PROP_ROI_Y, + PROP_ROI_WIDTH, + PROP_ROI_HEIGHT, + PROP_ROI_WIDTH_MULTIPLIER, + PROP_ROI_HEIGHT_MULTIPLIER, + PROP_HAS_STREAMING, + PROP_HAS_CAMRAM_RECORDING, + 0 +}; + +enum { + PROP_FOO = N_BASE_PROPERTIES, + N_PROPERTIES +}; + + +struct _UcaPfCameraPrivate { + guint roi_width; + guint roi_height; + guint last_frame; + + Fg_Struct *fg; + guint fg_port; + dma_mem *fg_mem; +}; + +/* + * We just embed our private structure here. + */ +struct { + UcaCamera *camera; +} fg_apc_data; + +static int me4_callback(frameindex_t frame, struct fg_apc_data *apc) +{ + UcaCamera *camera = UCA_CAMERA(apc); + UcaPfCameraPrivate *priv = UCA_PF_CAMERA_GET_PRIVATE(camera); + camera->grab_func(Fg_getImagePtrEx(priv->fg, frame, priv->fg_port, priv->fg_mem), camera->user_data); + return 0; +} + +static void uca_pf_camera_start_recording(UcaCamera *camera, GError **error) +{ + g_return_if_fail(UCA_IS_PF_CAMERA(camera)); + UcaPfCameraPrivate *priv = UCA_PF_CAMERA_GET_PRIVATE(camera); + guint err = FG_OK; + + if (priv->fg_mem == NULL) { + const guint num_buffers = 2; + priv->fg_mem = Fg_AllocMemEx(priv->fg, num_buffers * priv->roi_width * priv->roi_height, num_buffers); + + if (priv->fg_mem == NULL) { + g_set_error(error, UCA_PF_CAMERA_ERROR, UCA_PF_CAMERA_ERROR_FG_ACQUISITION, + "%s", Fg_getLastErrorDescription(priv->fg)); + g_object_unref(camera); + return; + } + } + + gboolean transfer_async = FALSE; + g_object_get(G_OBJECT(camera), + "transfer-asynchronously", &transfer_async, + NULL); + + if (transfer_async) { + struct FgApcControl ctrl = { + .version = 0, + .data = (struct fg_apc_data *) camera, + .func = &me4_callback, + .flags = FG_APC_DEFAULTS, + .timeout = 1 + }; + + err = Fg_registerApcHandler(priv->fg, priv->fg_port, &ctrl, FG_APC_CONTROL_BASIC); + FG_SET_ERROR(err, priv->fg, UCA_PF_CAMERA_ERROR_FG_ACQUISITION); + } + + err = Fg_AcquireEx(priv->fg, priv->fg_port, GRAB_INFINITE, ACQ_STANDARD, priv->fg_mem); + FG_SET_ERROR(err, priv->fg, UCA_PF_CAMERA_ERROR_FG_ACQUISITION); +} + +static void uca_pf_camera_stop_recording(UcaCamera *camera, GError **error) +{ + g_return_if_fail(UCA_IS_PF_CAMERA(camera)); + UcaPfCameraPrivate *priv = UCA_PF_CAMERA_GET_PRIVATE(camera); + + guint err = Fg_stopAcquireEx(priv->fg, priv->fg_port, priv->fg_mem, STOP_SYNC); + FG_SET_ERROR(err, priv->fg, UCA_PF_CAMERA_ERROR_FG_ACQUISITION); + + err = Fg_setStatusEx(priv->fg, FG_UNBLOCK_ALL, 0, priv->fg_port, priv->fg_mem); + if (err == FG_INVALID_PARAMETER) + g_print(" Unable to unblock all\n"); +} + +static void uca_pf_camera_start_readout(UcaCamera *camera, GError **error) +{ + g_return_if_fail(UCA_IS_PF_CAMERA(camera)); + g_set_error(error, UCA_CAMERA_ERROR, UCA_CAMERA_ERROR_NOT_IMPLEMENTED, + "This photon focus camera does not support recording to internal memory"); +} + +static void uca_pf_camera_grab(UcaCamera *camera, gpointer *data, GError **error) +{ + g_return_if_fail(UCA_IS_PF_CAMERA(camera)); + UcaPfCameraPrivate *priv = UCA_PF_CAMERA_GET_PRIVATE(camera); + + priv->last_frame = Fg_getLastPicNumberBlockingEx(priv->fg, priv->last_frame+1, priv->fg_port, 5, priv->fg_mem); + + if (priv->last_frame <= 0) { + guint err = FG_OK + 1; + FG_SET_ERROR(err, priv->fg, UCA_PF_CAMERA_ERROR_FG_GENERAL); + } + + guint16 *frame = Fg_getImagePtrEx(priv->fg, priv->last_frame, priv->fg_port, priv->fg_mem); + + if (*data == NULL) + *data = g_malloc0(priv->roi_width * priv->roi_height); + + memcpy((gchar *) *data, (gchar *) frame, priv->roi_width * priv->roi_height); +} + +static void uca_pf_camera_set_property(GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) +{ + switch (property_id) { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); + return; + } +} + +static void uca_pf_camera_get_property(GObject *object, guint property_id, GValue *value, GParamSpec *pspec) +{ + switch (property_id) { + case PROP_SENSOR_WIDTH: + g_value_set_uint(value, 1280); + break; + case PROP_SENSOR_HEIGHT: + g_value_set_uint(value, 1024); + break; + case PROP_SENSOR_BITDEPTH: + g_value_set_uint(value, 8); + break; + case PROP_SENSOR_HORIZONTAL_BINNING: + break; + case PROP_SENSOR_HORIZONTAL_BINNINGS: + break; + case PROP_SENSOR_VERTICAL_BINNING: + break; + case PROP_SENSOR_VERTICAL_BINNINGS: + break; + case PROP_SENSOR_MAX_FRAME_RATE: + g_value_set_float(value, 488.0); + break; + case PROP_HAS_STREAMING: + g_value_set_boolean(value, TRUE); + break; + case PROP_HAS_CAMRAM_RECORDING: + g_value_set_boolean(value, FALSE); + break; + case PROP_EXPOSURE_TIME: + break; + case PROP_ROI_X: + g_value_set_uint(value, 0); + break; + case PROP_ROI_Y: + g_value_set_uint(value, 0); + break; + case PROP_ROI_WIDTH: + g_value_set_uint(value, 1280); + break; + case PROP_ROI_HEIGHT: + g_value_set_uint(value, 1024); + break; + case PROP_ROI_WIDTH_MULTIPLIER: + g_value_set_uint(value, 1); + break; + case PROP_ROI_HEIGHT_MULTIPLIER: + g_value_set_uint(value, 1); + break; + case PROP_NAME: + g_value_set_string(value, "Photon Focus MV2-D1280-640-CL"); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); + break; + } +} + +static void uca_pf_camera_finalize(GObject *object) +{ + UcaPfCameraPrivate *priv = UCA_PF_CAMERA_GET_PRIVATE(object); + + if (priv->fg) { + if (priv->fg_mem) + Fg_FreeMemEx(priv->fg, priv->fg_mem); + + Fg_FreeGrabber(priv->fg); + } + + G_OBJECT_CLASS(uca_pf_camera_parent_class)->finalize(object); +} + +static void uca_pf_camera_class_init(UcaPfCameraClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS(klass); + gobject_class->set_property = uca_pf_camera_set_property; + gobject_class->get_property = uca_pf_camera_get_property; + gobject_class->finalize = uca_pf_camera_finalize; + + UcaCameraClass *camera_class = UCA_CAMERA_CLASS(klass); + camera_class->start_recording = uca_pf_camera_start_recording; + camera_class->stop_recording = uca_pf_camera_stop_recording; + camera_class->start_readout = uca_pf_camera_start_readout; + camera_class->grab = uca_pf_camera_grab; + + for (guint i = 0; base_overrideables[i] != 0; i++) + g_object_class_override_property(gobject_class, base_overrideables[i], uca_camera_props[base_overrideables[i]]); + + g_type_class_add_private(klass, sizeof(UcaPfCameraPrivate)); +} + +static void uca_pf_camera_init(UcaPfCamera *self) +{ + self->priv = UCA_PF_CAMERA_GET_PRIVATE(self); + self->priv->fg = NULL; + self->priv->fg_mem = NULL; + self->priv->last_frame = 0; +} + +G_MODULE_EXPORT UcaCamera * +uca_camera_impl_new (GError **error) +{ + static const gchar *so_file = "libFullAreaGray8.so"; + static const int camera_link_type = FG_CL_8BIT_FULL_8; + static const int camera_format = FG_GRAY; + + /* + gint num_ports; + if (pfPortInit(&num_ports) < 0) { + g_set_error(error, UCA_PF_CAMERA_ERROR, UCA_PF_CAMERA_ERROR_INIT, + "Could not initialize ports"); + return NULL; + } + + if (pfDeviceOpen(0) < 0) { + g_set_error(error, UCA_PF_CAMERA_ERROR, UCA_PF_CAMERA_ERROR_INIT, + "Could not open device"); + return NULL; + } + */ + + UcaPfCamera *camera = g_object_new(UCA_TYPE_PF_CAMERA, NULL); + UcaPfCameraPrivate *priv = UCA_PF_CAMERA_GET_PRIVATE(camera); + + priv->fg_port = PORT_A; + priv->fg = Fg_Init(so_file, priv->fg_port); + + /* TODO: get this from the camera */ + priv->roi_width = 1280; + priv->roi_height = 1024; + + if (priv->fg == NULL) { + g_set_error(error, UCA_PF_CAMERA_ERROR, UCA_PF_CAMERA_ERROR_INIT, + "%s", Fg_getLastErrorDescription(priv->fg)); + g_object_unref(camera); + return NULL; + } + + FG_TRY_PARAM(priv->fg, camera, FG_CAMERA_LINK_CAMTYP, &camera_link_type, priv->fg_port); + FG_TRY_PARAM(priv->fg, camera, FG_FORMAT, &camera_format, priv->fg_port); + FG_TRY_PARAM(priv->fg, camera, FG_WIDTH, &priv->roi_width, priv->fg_port); + FG_TRY_PARAM(priv->fg, camera, FG_HEIGHT, &priv->roi_height, priv->fg_port); + + return UCA_CAMERA (camera); +} diff --git a/plugins/pf/uca-pf-camera.h b/plugins/pf/uca-pf-camera.h new file mode 100644 index 0000000..3a309aa --- /dev/null +++ b/plugins/pf/uca-pf-camera.h @@ -0,0 +1,74 @@ +/* Copyright (C) 2011, 2012 Matthias Vogelgesang + (Karlsruhe Institute of Technology) + + This library is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by the + Free Software Foundation; either version 2.1 of the License, or (at your + option) any later version. + + This library is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + details. + + You should have received a copy of the GNU Lesser General Public License along + with this library; if not, write to the Free Software Foundation, Inc., 51 + Franklin St, Fifth Floor, Boston, MA 02110, USA */ + +#ifndef __UCA_PF_CAMERA_H +#define __UCA_PF_CAMERA_H + +#include +#include "uca-camera.h" + +G_BEGIN_DECLS + +#define UCA_TYPE_PF_CAMERA (uca_pf_camera_get_type()) +#define UCA_PF_CAMERA(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), UCA_TYPE_PF_CAMERA, UcaPfCamera)) +#define UCA_IS_PF_CAMERA(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), UCA_TYPE_PF_CAMERA)) +#define UCA_PF_CAMERA_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), UCA_TYPE_PF_CAMERA, UcaPfCameraClass)) +#define UCA_IS_PF_CAMERA_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), UCA_TYPE_PF_CAMERA)) +#define UCA_PF_CAMERA_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), UCA_TYPE_PF_CAMERA, UcaPfCameraClass)) + +#define UCA_PF_CAMERA_ERROR uca_pf_camera_error_quark() +typedef enum { + UCA_PF_CAMERA_ERROR_INIT, + UCA_PF_CAMERA_ERROR_FG_GENERAL, + UCA_PF_CAMERA_ERROR_FG_ACQUISITION, + UCA_PF_CAMERA_ERROR_START_RECORDING, + UCA_PF_CAMERA_ERROR_STOP_RECORDING +} UcaPfCameraError; + +typedef struct _UcaPfCamera UcaPfCamera; +typedef struct _UcaPfCameraClass UcaPfCameraClass; +typedef struct _UcaPfCameraPrivate UcaPfCameraPrivate; + +/** + * UcaPfCamera: + * + * Creates #UcaPfCamera instances by loading corresponding shared objects. The + * contents of the #UcaPfCamera structure are private and should only be + * accessed via the provided API. + */ +struct _UcaPfCamera { + /*< private >*/ + UcaCamera parent; + + UcaPfCameraPrivate *priv; +}; + +/** + * UcaPfCameraClass: + * + * #UcaPfCamera class + */ +struct _UcaPfCameraClass { + /*< private >*/ + UcaCameraClass parent; +}; + +GType uca_pf_camera_get_type(void); + +G_END_DECLS + +#endif diff --git a/plugins/pylon/CMakeLists.txt b/plugins/pylon/CMakeLists.txt new file mode 100644 index 0000000..18823a4 --- /dev/null +++ b/plugins/pylon/CMakeLists.txt @@ -0,0 +1,24 @@ +cmake_minimum_required(VERSION 2.8) +project(ucapylon) + +find_package(Pylon) + +if (PYLON_FOUND) + set(UCA_CAMERA_NAME "pylon") + + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/../package-plugin.sh.in + ${CMAKE_CURRENT_BINARY_DIR}/../../package-plugin-${UCA_CAMERA_NAME}.sh) + + include_directories(${LIBPYLONCAM_INCLUDEDIR}) + + add_library(ucapylon SHARED + uca-pylon-camera.c) + + target_link_libraries(ucapylon + ${UCA_DEPS} + ${LIBPYLONCAM_LIBRARIES}) + + install(TARGETS ucapylon + LIBRARY DESTINATION ${LIB_INSTALL_DIR}/uca + COMPONENT ${UCA_CAMERA_NAME}) +endif() diff --git a/plugins/pylon/uca-pylon-camera.c b/plugins/pylon/uca-pylon-camera.c new file mode 100644 index 0000000..541b69b --- /dev/null +++ b/plugins/pylon/uca-pylon-camera.c @@ -0,0 +1,391 @@ +/* Copyright (C) 2012 Volker Kaiser + (Karlsruhe Institute of Technology) + + This library is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by the + Free Software Foundation; either version 2.1 of the License, or (at your + option) any later version. + + This library is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + details. + + You should have received a copy of the GNU Lesser General Public License along + with this library; if not, write to the Free Software Foundation, Inc., 51 + Franklin St, Fifth Floor, Boston, MA 02110, USA */ + +#include +#include +#include +#include +#include "uca-camera.h" +#include "uca-pylon-camera.h" + +#define UCA_PYLON_CAMERA_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), UCA_TYPE_PYLON_CAMERA, UcaPylonCameraPrivate)) + +G_DEFINE_TYPE(UcaPylonCamera, uca_pylon_camera, UCA_TYPE_CAMERA) + +/** + * UcapylonCameraError: + * @UCA_PYLON_CAMERA_ERROR_LIBPYLON_INIT: Initializing libpylon failed + * @UCA_PYLON_CAMERA_ERROR_LIBPYLON_GENERAL: General libpylon error + * @UCA_PYLON_CAMERA_ERROR_UNSUPPORTED: Camera type is not supported + * @UCA_PYLON_CAMERA_ERROR_FG_INIT: Framegrabber initialization failed + * @UCA_PYLON_CAMERA_ERROR_FG_GENERAL: General framegrabber error + * @UCA_PYLON_CAMERA_ERROR_FG_ACQUISITION: Framegrabber acquisition error + */ +GQuark uca_pylon_camera_error_quark() +{ + return g_quark_from_static_string("uca-pylon-camera-error-quark"); +} + +enum { + PROP_ROI_WIDTH_DEFAULT = N_BASE_PROPERTIES, + PROP_ROI_HEIGHT_DEFAULT, + PROP_GAIN, + N_PROPERTIES +}; + +static gint base_overrideables[] = { + PROP_NAME, + PROP_SENSOR_WIDTH, + PROP_SENSOR_HEIGHT, + PROP_SENSOR_BITDEPTH, + PROP_SENSOR_HORIZONTAL_BINNING, + PROP_SENSOR_HORIZONTAL_BINNINGS, + PROP_SENSOR_VERTICAL_BINNING, + PROP_SENSOR_VERTICAL_BINNINGS, + PROP_SENSOR_MAX_FRAME_RATE, + PROP_TRIGGER_MODE, + PROP_EXPOSURE_TIME, + PROP_ROI_X, + PROP_ROI_Y, + PROP_ROI_WIDTH, + PROP_ROI_HEIGHT, + PROP_ROI_WIDTH_MULTIPLIER, + PROP_ROI_HEIGHT_MULTIPLIER, + PROP_HAS_STREAMING, + PROP_HAS_CAMRAM_RECORDING, + 0 +}; + +static GParamSpec *pylon_properties[N_PROPERTIES] = { NULL, }; + + +struct _UcaPylonCameraPrivate { + guint bit_depth; + gsize num_bytes; + + guint width; + guint height; + guint16 roi_x, roi_y; + guint16 roi_width, roi_height; + GValueArray *binnings; +}; + + +static void pylon_get_roi(GObject *object, GError** error) +{ + UcaPylonCameraPrivate *priv = UCA_PYLON_CAMERA_GET_PRIVATE(object); + pylon_camera_get_roi(&priv->roi_x, &priv->roi_y, &priv->roi_width, &priv->roi_height, error); +} + +static void pylon_set_roi(GObject *object, GError** error) +{ + UcaPylonCameraPrivate *priv = UCA_PYLON_CAMERA_GET_PRIVATE(object); + pylon_camera_set_roi(priv->roi_x, priv->roi_y, priv->roi_width, priv->roi_height, error); +} + +UcaPylonCamera *uca_pylon_camera_new(GError **error) +{ + UcaPylonCamera *camera = g_object_new(UCA_TYPE_PYLON_CAMERA, NULL); + UcaPylonCameraPrivate *priv = UCA_PYLON_CAMERA_GET_PRIVATE(camera); + + pylon_camera_new("/usr/local/lib64", "141.52.111.110", error); + + if (*error != NULL) + return NULL; + + pylon_camera_get_sensor_size(&priv->width, &priv->height, error); + + if (*error != NULL) + return NULL; + + return camera; +} + +static void uca_pylon_camera_start_recording(UcaCamera *camera, GError **error) +{ + g_return_if_fail(UCA_IS_PYLON_CAMERA(camera)); + UcaPylonCameraPrivate *priv = UCA_PYLON_CAMERA_GET_PRIVATE(camera); + + priv->num_bytes = 2; + pylon_camera_start_acquision(error); + +} + +static void uca_pylon_camera_stop_recording(UcaCamera *camera, GError **error) +{ + g_return_if_fail(UCA_IS_PYLON_CAMERA(camera)); + pylon_camera_stop_acquision(error); +} + +static void uca_pylon_camera_grab(UcaCamera *camera, gpointer *data, GError **error) +{ + g_return_if_fail(UCA_IS_PYLON_CAMERA(camera)); + UcaPylonCameraPrivate *priv = UCA_PYLON_CAMERA_GET_PRIVATE(camera); + + if (*data == NULL) { + *data = g_malloc0(priv->width * priv->height * priv->num_bytes); + } + pylon_camera_grab(data, error); +} + +static void uca_pylon_camera_set_property(GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) +{ + UcaPylonCameraPrivate *priv = UCA_PYLON_CAMERA_GET_PRIVATE(object); + GError* error = NULL; + + switch (property_id) { + case PROP_SENSOR_HORIZONTAL_BINNING: + /* intentional fall-through*/ + case PROP_SENSOR_VERTICAL_BINNING: + /* intentional fall-through*/ + case PROP_TRIGGER_MODE: + break; + + case PROP_ROI_X: + { + priv->roi_x = g_value_get_uint(value); + pylon_set_roi(object, &error); + } + break; + + case PROP_ROI_Y: + { + priv->roi_y = g_value_get_uint(value); + pylon_set_roi(object, &error); + } + break; + + case PROP_ROI_WIDTH: + { + priv->roi_width = g_value_get_uint(value); + pylon_set_roi(object, &error); + } + break; + + case PROP_ROI_HEIGHT: + { + priv->roi_height = g_value_get_uint(value); + pylon_set_roi(object, &error); + } + break; + + case PROP_EXPOSURE_TIME: + pylon_camera_set_exposure_time(g_value_get_double(value), &error); + break; + + case PROP_GAIN: + pylon_camera_set_gain(g_value_get_int(value), &error); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); + return; + } +} + +static void uca_pylon_camera_get_property(GObject *object, guint property_id, GValue *value, GParamSpec *pspec) +{ + UcaPylonCameraPrivate *priv = UCA_PYLON_CAMERA_GET_PRIVATE(object); + GError* error = NULL; + + switch (property_id) { + case PROP_SENSOR_WIDTH: + pylon_camera_get_sensor_size(&priv->width, &priv->height, &error); + g_value_set_uint(value, priv->width); + break; + + case PROP_SENSOR_HEIGHT: + pylon_camera_get_sensor_size(&priv->width, &priv->height, &error); + g_value_set_uint(value, priv->height); + break; + + case PROP_SENSOR_BITDEPTH: + pylon_camera_get_bit_depth(&priv->bit_depth, &error); + g_value_set_uint(value, priv->bit_depth); + break; + + case PROP_SENSOR_HORIZONTAL_BINNING: + g_value_set_uint(value, 1); + break; + + case PROP_SENSOR_HORIZONTAL_BINNINGS: + g_value_set_boxed(value, priv->binnings); + break; + + case PROP_SENSOR_VERTICAL_BINNING: + g_value_set_uint(value, 1); + break; + + case PROP_SENSOR_VERTICAL_BINNINGS: + g_value_set_boxed(value, priv->binnings); + break; + + case PROP_SENSOR_MAX_FRAME_RATE: + g_value_set_float(value, 0.0); + break; + + case PROP_TRIGGER_MODE: + g_value_set_enum(value, UCA_CAMERA_TRIGGER_AUTO); + break; + + case PROP_HAS_STREAMING: + g_value_set_boolean(value, FALSE); + break; + + case PROP_HAS_CAMRAM_RECORDING: + g_value_set_boolean(value, FALSE); + break; + + case PROP_ROI_X: + { + pylon_get_roi(object, &error); + g_value_set_uint(value, priv->roi_x); + } + break; + + case PROP_ROI_Y: + { + pylon_get_roi(object, &error); + g_value_set_uint(value, priv->roi_y); + } + break; + + case PROP_ROI_WIDTH: + { + pylon_get_roi(object, &error); + g_value_set_uint(value, priv->roi_width); + } + break; + + case PROP_ROI_HEIGHT: + { + pylon_get_roi(object, &error); + g_value_set_uint(value, priv->roi_height); + } + break; + + case PROP_ROI_WIDTH_DEFAULT: + pylon_camera_get_sensor_size(&priv->width, &priv->height, &error); + g_value_set_uint(value, priv->width); + break; + + case PROP_ROI_HEIGHT_DEFAULT: + pylon_camera_get_sensor_size(&priv->width, &priv->height, &error); + g_value_set_uint(value, priv->height); + break; + + case PROP_GAIN: + { + gint gain=0; + pylon_camera_get_gain(&gain, &error); + g_value_set_int(value, gain); + } + break; + + case PROP_ROI_WIDTH_MULTIPLIER: + g_value_set_uint(value, 1); + break; + + case PROP_ROI_HEIGHT_MULTIPLIER: + g_value_set_uint(value, 1); + break; + + case PROP_EXPOSURE_TIME: + { + gdouble exp_time = 0.0; + pylon_camera_get_exposure_time(&exp_time, &error); + g_value_set_double(value, exp_time); + } + break; + + case PROP_NAME: + g_value_set_string(value, "Pylon Camera"); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); + break; + } +} + +static void uca_pylon_camera_finalize(GObject *object) +{ + UcaPylonCameraPrivate *priv = UCA_PYLON_CAMERA_GET_PRIVATE(object); + g_value_array_free(priv->binnings); + + G_OBJECT_CLASS(uca_pylon_camera_parent_class)->finalize(object); +} + +static void uca_pylon_camera_class_init(UcaPylonCameraClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS(klass); + gobject_class->set_property = uca_pylon_camera_set_property; + gobject_class->get_property = uca_pylon_camera_get_property; + gobject_class->finalize = uca_pylon_camera_finalize; + + UcaCameraClass *camera_class = UCA_CAMERA_CLASS(klass); + camera_class->start_recording = uca_pylon_camera_start_recording; + camera_class->stop_recording = uca_pylon_camera_stop_recording; + camera_class->grab = uca_pylon_camera_grab; + + for (guint i = 0; base_overrideables[i] != 0; i++) + g_object_class_override_property(gobject_class, base_overrideables[i], uca_camera_props[base_overrideables[i]]); + + pylon_properties[PROP_NAME] = + g_param_spec_string("name", + "Name of the camera", + "Name of the camera", + "", G_PARAM_READABLE); + + pylon_properties[PROP_ROI_WIDTH_DEFAULT] = + g_param_spec_uint("roi-width-default", + "ROI width default value", + "ROI width default value", + 0, G_MAXUINT, 0, + G_PARAM_READABLE); + + pylon_properties[PROP_ROI_HEIGHT_DEFAULT] = + g_param_spec_uint("roi-height-default", + "ROI height default value", + "ROI height default value", + 0, G_MAXUINT, 0, + G_PARAM_READABLE); + + pylon_properties[PROP_GAIN] = + g_param_spec_int("gain", + "gain", + "gain", + 0, G_MAXINT, 0, + G_PARAM_READWRITE); + + for (guint id = N_BASE_PROPERTIES; id < N_PROPERTIES; id++) + g_object_class_install_property(gobject_class, id, pylon_properties[id]); + + g_type_class_add_private(klass, sizeof(UcaPylonCameraPrivate)); +} + +static void uca_pylon_camera_init(UcaPylonCamera *self) +{ + self->priv = UCA_PYLON_CAMERA_GET_PRIVATE(self); + + /* binnings */ + GValue val = {0}; + g_value_init(&val, G_TYPE_UINT); + g_value_set_uint(&val, 1); + self->priv->binnings = g_value_array_new(1); + g_value_array_append(self->priv->binnings, &val); +} diff --git a/plugins/pylon/uca-pylon-camera.h b/plugins/pylon/uca-pylon-camera.h new file mode 100644 index 0000000..eebf63c --- /dev/null +++ b/plugins/pylon/uca-pylon-camera.h @@ -0,0 +1,74 @@ +/* Copyright (C) 2011, 2012 Matthias Vogelgesang + (Karlsruhe Institute of Technology) + + This library is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by the + Free Software Foundation; either version 2.1 of the License, or (at your + option) any later version. + + This library is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + details. + + You should have received a copy of the GNU Lesser General Public License along + with this library; if not, write to the Free Software Foundation, Inc., 51 + Franklin St, Fifth Floor, Boston, MA 02110, USA */ + +#ifndef __UCA_PYLON_CAMERA_H +#define __UCA_PYLON_CAMERA_H + +#include +#include "uca-camera.h" + +G_BEGIN_DECLS + +#define UCA_TYPE_PYLON_CAMERA (uca_pylon_camera_get_type()) +#define UCA_PYLON_CAMERA(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), UCA_TYPE_PYLON_CAMERA, UcaPylonCamera)) +#define UCA_IS_PYLON_CAMERA(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), UCA_TYPE_PYLON_CAMERA)) +#define UCA_PYLON_CAMERA_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), UFO_TYPE_PYLON_CAMERA, UfoPylonCameraClass)) +#define UCA_IS_PYLON_CAMERA_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), UCA_TYPE_PYLON_CAMERA)) +#define UCA_PYLON_CAMERA_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), UCA_TYPE_PYLON_CAMERA, UcaPylonCameraClass)) + +#define UCA_PYLON_CAMERA_ERROR uca_pylon_camera_error_quark() +typedef enum { + UCA_PYLON_CAMERA_ERROR_LIBPYLON_INIT, + UCA_PYLON_CAMERA_ERROR_LIBPYLON_GENERAL, + UCA_PYLON_CAMERA_ERROR_UNSUPPORTED, +} UcaPylonCameraError; + +typedef struct _UcaPylonCamera UcaPylonCamera; +typedef struct _UcaPylonCameraClass UcaPylonCameraClass; +typedef struct _UcaPylonCameraPrivate UcaPylonCameraPrivate; + +/** + * UcaPylonCamera: + * + * Creates #UcaPylonCamera instances by loading corresponding shared objects. The + * contents of the #UcaPylonCamera structure are private and should only be + * accessed via the provided API. + */ +struct _UcaPylonCamera { + /*< private >*/ + UcaCamera parent; + + UcaPylonCameraPrivate *priv; +}; + +/** + * UcaPylonCameraClass: + * + * #UcaPylonCamera class + */ +struct _UcaPylonCameraClass { + /*< private >*/ + UcaCameraClass parent; +}; + +UcaPylonCamera *uca_pylon_camera_new(GError **error); + +GType uca_pylon_camera_get_type(void); + +G_END_DECLS + +#endif diff --git a/plugins/ufo/CMakeLists.txt b/plugins/ufo/CMakeLists.txt new file mode 100644 index 0000000..fe89668 --- /dev/null +++ b/plugins/ufo/CMakeLists.txt @@ -0,0 +1,24 @@ +cmake_minimum_required(VERSION 2.8) +project(ucaufo) + +find_package(IPE) + +if (IPE_FOUND) + set(UCA_CAMERA_NAME "ufo") + + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/../package-plugin.sh.in + ${CMAKE_CURRENT_BINARY_DIR}/../../package-plugin-${UCA_CAMERA_NAME}.sh) + + include_directories(${IPE_INCLUDE_DIRS}) + + add_library(ucaufo SHARED + uca-ufo-camera.c) + + target_link_libraries(ucaufo + ${UCA_DEPS} + ${IPE_LIBRARIES}) + + install(TARGETS ucaufo + LIBRARY DESTINATION ${LIB_INSTALL_DIR}/uca + COMPONENT ${UCA_CAMERA_NAME}) +endif() diff --git a/plugins/ufo/uca-ufo-camera.c b/plugins/ufo/uca-ufo-camera.c new file mode 100644 index 0000000..7542fdf --- /dev/null +++ b/plugins/ufo/uca-ufo-camera.c @@ -0,0 +1,497 @@ +/* Copyright (C) 2011, 2012 Matthias Vogelgesang + (Karlsruhe Institute of Technology) + + This library is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by the + Free Software Foundation; either version 2.1 of the License, or (at your + option) any later version. + + This library is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + details. + + You should have received a copy of the GNU Lesser General Public License along + with this library; if not, write to the Free Software Foundation, Inc., 51 + Franklin St, Fifth Floor, Boston, MA 02110, USA */ + +#include +#include +#include +#include +#include +#include +#include "uca-camera.h" +#include "uca-ufo-camera.h" + +#define PCILIB_SET_ERROR(err, err_type) \ + if (err != 0) { \ + g_set_error(error, UCA_UFO_CAMERA_ERROR, \ + err_type, \ + "pcilib: %s", strerror(err)); \ + return; \ + } + +#define UCA_UFO_CAMERA_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), UCA_TYPE_UFO_CAMERA, UcaUfoCameraPrivate)) + +G_DEFINE_TYPE(UcaUfoCamera, uca_ufo_camera, UCA_TYPE_CAMERA) + +static const guint SENSOR_WIDTH = 2048; +static const guint SENSOR_HEIGHT = 1088; +static const gdouble EXPOSURE_TIME_SCALE = 2.69e6; + +/** + * UcaUfoCameraError: + * @UCA_UFO_CAMERA_ERROR_INIT: Initializing pcilib failed + * @UCA_UFO_CAMERA_ERROR_START_RECORDING: Starting failed + * @UCA_UFO_CAMERA_ERROR_STOP_RECORDING: Stopping failed + * @UCA_UFO_CAMERA_ERROR_TRIGGER: Triggering a frame failed + * @UCA_UFO_CAMERA_ERROR_NEXT_EVENT: No event happened + * @UCA_UFO_CAMERA_ERROR_NO_DATA: No data was transmitted + * @UCA_UFO_CAMERA_ERROR_MAYBE_CORRUPTED: Data is potentially corrupted + */ +GQuark uca_ufo_camera_error_quark() +{ + return g_quark_from_static_string("uca-ufo-camera-error-quark"); +} + +enum { + PROP_SENSOR_TEMPERATURE = N_BASE_PROPERTIES, + PROP_FPGA_TEMPERATURE, + PROP_UFO_START, + N_MAX_PROPERTIES = 512 +}; + +static gint base_overrideables[] = { + PROP_NAME, + PROP_SENSOR_WIDTH, + PROP_SENSOR_HEIGHT, + PROP_SENSOR_HORIZONTAL_BINNING, + PROP_SENSOR_VERTICAL_BINNING, + PROP_SENSOR_MAX_FRAME_RATE, + PROP_SENSOR_BITDEPTH, + PROP_EXPOSURE_TIME, + PROP_ROI_X, + PROP_ROI_Y, + PROP_ROI_WIDTH, + PROP_ROI_HEIGHT, + PROP_ROI_WIDTH_MULTIPLIER, + PROP_ROI_HEIGHT_MULTIPLIER, + PROP_HAS_STREAMING, + PROP_HAS_CAMRAM_RECORDING, + PROP_TRIGGER_MODE, + 0, +}; + +typedef struct _RegisterInfo { + gchar *name; + guint cached_value; +} RegisterInfo; + +static GParamSpec *ufo_properties[N_MAX_PROPERTIES] = { NULL, }; + +static guint N_PROPERTIES; +static GHashTable *ufo_property_table; /* maps from prop_id to RegisterInfo* */ + +struct _UcaUfoCameraPrivate { + pcilib_t *handle; + pcilib_timeout_t timeout; + guint n_bits; + enum { + FPGA_48MHZ = 0, + FPGA_40MHZ + } frequency; +}; + +static void +error_handler (const char *format, ...) +{ + va_list args; + gchar *message; + + va_start (args, format); + message = g_strdup_vprintf (format, args); + g_warning ("%s", message); + va_end (args); +} + +static guint +read_register_value (pcilib_t *handle, const gchar *name) +{ + pcilib_register_value_t reg_value; + + pcilib_read_register(handle, NULL, name, ®_value); + return (guint) reg_value; +} + +static int event_callback(pcilib_event_id_t event_id, pcilib_event_info_t *info, void *user) +{ + UcaCamera *camera = UCA_CAMERA(user); + UcaUfoCameraPrivate *priv = UCA_UFO_CAMERA_GET_PRIVATE(camera); + size_t error = 0; + + void *buffer = pcilib_get_data(priv->handle, event_id, PCILIB_EVENT_DATA, &error); + + if (buffer == NULL) { + pcilib_trigger(priv->handle, PCILIB_EVENT0, 0, NULL); + return PCILIB_STREAMING_CONTINUE; + } + + camera->grab_func(buffer, camera->user_data); + pcilib_return_data(priv->handle, event_id, PCILIB_EVENT_DATA, buffer); + pcilib_trigger(priv->handle, PCILIB_EVENT0, 0, NULL); + + return PCILIB_STREAMING_CONTINUE; +} + +G_MODULE_EXPORT UcaCamera * +uca_camera_impl_new (GError **error) +{ + pcilib_model_t model = PCILIB_MODEL_DETECT; + pcilib_model_description_t *model_description; + pcilib_t *handle = pcilib_open("/dev/fpga0", model); + guint prop = PROP_UFO_START; + guint adc_resolution; + + if (handle == NULL) { + g_set_error(error, UCA_UFO_CAMERA_ERROR, UCA_UFO_CAMERA_ERROR_INIT, + "Initializing pcilib failed"); + return NULL; + } + + pcilib_set_error_handler(&error_handler, &error_handler); + + /* Generate properties from model description */ + model_description = pcilib_get_model_description(handle); + ufo_property_table = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_free); + + for (guint i = 0; model_description->registers[i].name != NULL; i++) { + GParamFlags flags = 0; + RegisterInfo *reg_info; + gchar *prop_name; + pcilib_register_description_t *reg; + pcilib_register_value_t value; + + reg = &model_description->registers[i]; + + switch (reg->mode) { + case PCILIB_REGISTER_R: + flags = G_PARAM_READABLE; + break; + case PCILIB_REGISTER_W: + case PCILIB_REGISTER_W1C: + flags = G_PARAM_WRITABLE; + break; + case PCILIB_REGISTER_RW: + case PCILIB_REGISTER_RW1C: + flags = G_PARAM_READWRITE; + break; + } + + pcilib_read_register (handle, NULL, reg->name, &value); + reg_info = g_new0 (RegisterInfo, 1); + reg_info->name = g_strdup (reg->name); + reg_info->cached_value = (guint32) value; + + g_hash_table_insert (ufo_property_table, GINT_TO_POINTER (prop), reg_info); + prop_name = g_strdup_printf ("ufo-%s", reg->name); + + ufo_properties[prop++] = g_param_spec_uint ( + prop_name, reg->description, reg->description, + 0, G_MAXUINT, reg->defvalue, flags); + + g_free (prop_name); + } + + N_PROPERTIES = prop; + + UcaUfoCamera *camera = g_object_new(UCA_TYPE_UFO_CAMERA, NULL); + UcaUfoCameraPrivate *priv = UCA_UFO_CAMERA_GET_PRIVATE(camera); + + priv->frequency = read_register_value (handle, "bit_mode"); + adc_resolution = read_register_value (handle, "adc_resolution"); + + switch (adc_resolution) { + case 0: + priv->n_bits = 10; + break; + case 1: + priv->n_bits = 11; + break; + case 2: + priv->n_bits = 12; + break; + } + + priv->handle = handle; + + return UCA_CAMERA (camera); +} + +static void uca_ufo_camera_start_recording(UcaCamera *camera, GError **error) +{ + UcaUfoCameraPrivate *priv; + gdouble exposure_time; + int err; + + g_return_if_fail(UCA_IS_UFO_CAMERA(camera)); + + priv = UCA_UFO_CAMERA_GET_PRIVATE(camera); + err = pcilib_start(priv->handle, PCILIB_EVENT_DATA, PCILIB_EVENT_FLAGS_DEFAULT); + PCILIB_SET_ERROR(err, UCA_UFO_CAMERA_ERROR_START_RECORDING); + + gboolean transfer_async = FALSE; + g_object_get(G_OBJECT(camera), + "transfer-asynchronously", &transfer_async, + "exposure-time", &exposure_time, + NULL); + + priv->timeout = ((pcilib_timeout_t) (exposure_time * 1000 + 50.0) * 1000); + + if (transfer_async) { + pcilib_trigger(priv->handle, PCILIB_EVENT0, 0, NULL); + pcilib_stream(priv->handle, &event_callback, camera); + } +} + +static void uca_ufo_camera_stop_recording(UcaCamera *camera, GError **error) +{ + g_return_if_fail(UCA_IS_UFO_CAMERA(camera)); + UcaUfoCameraPrivate *priv = UCA_UFO_CAMERA_GET_PRIVATE(camera); + int err = pcilib_stop(priv->handle, PCILIB_EVENT_FLAGS_DEFAULT); + PCILIB_SET_ERROR(err, UCA_UFO_CAMERA_ERROR_START_RECORDING); +} + +static void uca_ufo_camera_start_readout(UcaCamera *camera, GError **error) +{ + g_return_if_fail(UCA_IS_UFO_CAMERA(camera)); + g_set_error(error, UCA_CAMERA_ERROR, UCA_CAMERA_ERROR_NOT_IMPLEMENTED, + "Ufo camera does not support recording to internal memory"); +} + +static void uca_ufo_camera_grab(UcaCamera *camera, gpointer *data, GError **error) +{ + g_return_if_fail(UCA_IS_UFO_CAMERA(camera)); + UcaUfoCameraPrivate *priv = UCA_UFO_CAMERA_GET_PRIVATE(camera); + pcilib_event_id_t event_id; + pcilib_event_info_t event_info; + size_t err; + + const gsize size = SENSOR_WIDTH * SENSOR_HEIGHT * sizeof(guint16); + + err = pcilib_trigger(priv->handle, PCILIB_EVENT0, 0, NULL); + PCILIB_SET_ERROR(err, UCA_UFO_CAMERA_ERROR_TRIGGER); + + err = pcilib_get_next_event(priv->handle, priv->timeout, &event_id, sizeof(pcilib_event_info_t), &event_info); + PCILIB_SET_ERROR(err, UCA_UFO_CAMERA_ERROR_NEXT_EVENT); + + if (*data == NULL) + *data = g_malloc0(SENSOR_WIDTH * SENSOR_HEIGHT * sizeof(guint16)); + + gpointer src = pcilib_get_data(priv->handle, event_id, PCILIB_EVENT_DATA, &err); + + if (src == NULL) + PCILIB_SET_ERROR(err, UCA_UFO_CAMERA_ERROR_NO_DATA); + + /* + * Apparently, we checked that err equals total size in previous version. + * This is problematic because errno is positive and size could be equal + * even when an error condition is met, e.g. with a very small ROI. However, + * we don't know if src will always be NULL when an error occured. + */ + /* assert(err == size); */ + + memcpy(*data, src, size); + + /* + * Another problem here. What does this help us? At this point we have + * already overwritten the original buffer but can only know here if the + * data is corrupted. + */ + err = pcilib_return_data(priv->handle, event_id, PCILIB_EVENT_DATA, data); + PCILIB_SET_ERROR(err, UCA_UFO_CAMERA_ERROR_MAYBE_CORRUPTED); +} + +static void +uca_ufo_camera_set_property(GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) +{ + UcaUfoCameraPrivate *priv = UCA_UFO_CAMERA_GET_PRIVATE(object); + + switch (property_id) { + case PROP_EXPOSURE_TIME: + { + const guint frequency = priv->frequency == FPGA_40MHZ ? 40 : 48; + pcilib_register_value_t reg_value = (pcilib_register_value_t) 129 / frequency * 1000 * 1000 * g_value_get_double(value); + pcilib_write_register(priv->handle, NULL, "cmosis_exp_time", reg_value); + } + break; + case PROP_ROI_X: + case PROP_ROI_Y: + case PROP_ROI_WIDTH: + case PROP_ROI_HEIGHT: + g_debug("ROI feature not implemented yet"); + break; + + default: + { + RegisterInfo *reg_info = g_hash_table_lookup (ufo_property_table, GINT_TO_POINTER (property_id)); + + if (reg_info != NULL) { + pcilib_register_value_t reg_value; + + reg_value = g_value_get_uint (value); + pcilib_write_register(priv->handle, NULL, reg_info->name, reg_value); + pcilib_read_register (priv->handle, NULL, reg_info->name, ®_value); + reg_info->cached_value = (guint) reg_value; + } + else + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); + } + return; + } +} + + +static void +uca_ufo_camera_get_property(GObject *object, guint property_id, GValue *value, GParamSpec *pspec) +{ + UcaUfoCameraPrivate *priv = UCA_UFO_CAMERA_GET_PRIVATE(object); + + switch (property_id) { + case PROP_SENSOR_WIDTH: + g_value_set_uint(value, SENSOR_WIDTH); + break; + case PROP_SENSOR_HEIGHT: + g_value_set_uint(value, SENSOR_HEIGHT); + break; + case PROP_SENSOR_BITDEPTH: + g_value_set_uint (value, priv->n_bits); + break; + case PROP_SENSOR_HORIZONTAL_BINNING: + g_value_set_uint(value, 1); + break; + case PROP_SENSOR_VERTICAL_BINNING: + g_value_set_uint(value, 1); + break; + case PROP_SENSOR_MAX_FRAME_RATE: + g_value_set_float(value, 340.0); + break; + case PROP_SENSOR_TEMPERATURE: + { + const double a = priv->frequency == FPGA_48MHZ ? 0.3 : 0.25; + const double b = priv->frequency == FPGA_48MHZ ? 1000 : 1200; + guint32 temperature; + + temperature = read_register_value (priv->handle, "sensor_temperature"); + g_value_set_double (value, a * (temperature - b)); + } + break; + case PROP_FPGA_TEMPERATURE: + { + const double a = 503.975 / 1024.0; + const double b = 273.15; + guint32 temperature; + + temperature = read_register_value (priv->handle, "fpga_temperature"); + g_value_set_double (value, a * temperature - b); + } + break; + case PROP_EXPOSURE_TIME: + { + const gdouble frequency = priv->frequency == FPGA_40MHZ ? 40.0 : 48.0; + g_value_set_double (value, read_register_value (priv->handle, "cmosis_exp_time") * 129 / frequency / 1000 / 1000 ); + } + break; + case PROP_HAS_STREAMING: + g_value_set_boolean(value, TRUE); + break; + case PROP_HAS_CAMRAM_RECORDING: + g_value_set_boolean(value, FALSE); + break; + case PROP_ROI_X: + g_value_set_uint(value, 0); + break; + case PROP_ROI_Y: + g_value_set_uint(value, 0); + break; + case PROP_ROI_WIDTH: + g_value_set_uint(value, SENSOR_WIDTH); + break; + case PROP_ROI_HEIGHT: + g_value_set_uint(value, SENSOR_HEIGHT); + break; + case PROP_ROI_WIDTH_MULTIPLIER: + g_value_set_uint(value, 1); + break; + case PROP_ROI_HEIGHT_MULTIPLIER: + g_value_set_uint(value, 1); + break; + case PROP_NAME: + g_value_set_string(value, "Ufo Camera w/ CMOSIS CMV2000"); + break; + case PROP_TRIGGER_MODE: + break; + default: + { + RegisterInfo *reg_info = g_hash_table_lookup (ufo_property_table, GINT_TO_POINTER (property_id)); + + if (reg_info != NULL) + g_value_set_uint (value, reg_info->cached_value); + else + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); + } + break; + } +} + +static void uca_ufo_camera_finalize(GObject *object) +{ + UcaUfoCameraPrivate *priv = UCA_UFO_CAMERA_GET_PRIVATE(object); + pcilib_close(priv->handle); + G_OBJECT_CLASS(uca_ufo_camera_parent_class)->finalize(object); +} + +static void uca_ufo_camera_class_init(UcaUfoCameraClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS(klass); + gobject_class->set_property = uca_ufo_camera_set_property; + gobject_class->get_property = uca_ufo_camera_get_property; + gobject_class->finalize = uca_ufo_camera_finalize; + + UcaCameraClass *camera_class = UCA_CAMERA_CLASS(klass); + camera_class->start_recording = uca_ufo_camera_start_recording; + camera_class->stop_recording = uca_ufo_camera_stop_recording; + camera_class->start_readout = uca_ufo_camera_start_readout; + camera_class->grab = uca_ufo_camera_grab; + + for (guint i = 0; base_overrideables[i] != 0; i++) + g_object_class_override_property(gobject_class, base_overrideables[i], uca_camera_props[base_overrideables[i]]); + + ufo_properties[PROP_SENSOR_TEMPERATURE] = + g_param_spec_double("sensor-temperature", + "Temperature of the sensor", + "Temperature of the sensor in degree Celsius", + -G_MAXDOUBLE, G_MAXDOUBLE, 0.0, + G_PARAM_READABLE); + + ufo_properties[PROP_FPGA_TEMPERATURE] = + g_param_spec_double("fpga-temperature", + "Temperature of the FPGA", + "Temperature of the FPGA in degree Celsius", + -G_MAXDOUBLE, G_MAXDOUBLE, 0.0, + G_PARAM_READABLE); + + /* + * This automatic property installation includes the properties created + * dynamically in uca_ufo_camera_new(). + */ + for (guint id = N_BASE_PROPERTIES; id < N_PROPERTIES; id++) + g_object_class_install_property(gobject_class, id, ufo_properties[id]); + + g_type_class_add_private(klass, sizeof(UcaUfoCameraPrivate)); +} + +static void uca_ufo_camera_init(UcaUfoCamera *self) +{ + self->priv = UCA_UFO_CAMERA_GET_PRIVATE(self); +} diff --git a/plugins/ufo/uca-ufo-camera.h b/plugins/ufo/uca-ufo-camera.h new file mode 100644 index 0000000..7030389 --- /dev/null +++ b/plugins/ufo/uca-ufo-camera.h @@ -0,0 +1,76 @@ +/* Copyright (C) 2011, 2012 Matthias Vogelgesang + (Karlsruhe Institute of Technology) + + This library is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by the + Free Software Foundation; either version 2.1 of the License, or (at your + option) any later version. + + This library is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + details. + + You should have received a copy of the GNU Lesser General Public License along + with this library; if not, write to the Free Software Foundation, Inc., 51 + Franklin St, Fifth Floor, Boston, MA 02110, USA */ + +#ifndef __UCA_UFO_CAMERA_H +#define __UCA_UFO_CAMERA_H + +#include +#include "uca-camera.h" + +G_BEGIN_DECLS + +#define UCA_TYPE_UFO_CAMERA (uca_ufo_camera_get_type()) +#define UCA_UFO_CAMERA(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), UCA_TYPE_UFO_CAMERA, UcaUfoCamera)) +#define UCA_IS_UFO_CAMERA(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), UCA_TYPE_UFO_CAMERA)) +#define UCA_UFO_CAMERA_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), UCA_TYPE_UFO_CAMERA, UcaUfoCameraClass)) +#define UCA_IS_UFO_CAMERA_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), UCA_TYPE_UFO_CAMERA)) +#define UCA_UFO_CAMERA_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), UCA_TYPE_UFO_CAMERA, UcaUfoCameraClass)) + +#define UCA_UFO_CAMERA_ERROR uca_ufo_camera_error_quark() +typedef enum { + UCA_UFO_CAMERA_ERROR_INIT, + UCA_UFO_CAMERA_ERROR_START_RECORDING, + UCA_UFO_CAMERA_ERROR_STOP_RECORDING, + UCA_UFO_CAMERA_ERROR_TRIGGER, + UCA_UFO_CAMERA_ERROR_NEXT_EVENT, + UCA_UFO_CAMERA_ERROR_NO_DATA, + UCA_UFO_CAMERA_ERROR_MAYBE_CORRUPTED +} UcaUfoCameraError; + +typedef struct _UcaUfoCamera UcaUfoCamera; +typedef struct _UcaUfoCameraClass UcaUfoCameraClass; +typedef struct _UcaUfoCameraPrivate UcaUfoCameraPrivate; + +/** + * UcaUfoCamera: + * + * Creates #UcaUfoCamera instances by loading corresponding shared objects. The + * contents of the #UcaUfoCamera structure are private and should only be + * accessed via the provided API. + */ +struct _UcaUfoCamera { + /*< private >*/ + UcaCamera parent; + + UcaUfoCameraPrivate *priv; +}; + +/** + * UcaUfoCameraClass: + * + * #UcaUfoCamera class + */ +struct _UcaUfoCameraClass { + /*< private >*/ + UcaCameraClass parent; +}; + +GType uca_ufo_camera_get_type(void); + +G_END_DECLS + +#endif diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index a681f67..4bf5820 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,4 +1,5 @@ cmake_minimum_required(VERSION 2.8) +project(uca C) # --- Set sources ------------------------------------------------------------- set(uca_SRCS @@ -10,147 +11,15 @@ set(uca_HDRS uca-camera.h uca-plugin-manager.h) -set(cameras) - -set(LIB_INSTALL_DIR "lib${LIB_SUFFIX}") - -# --- Find packages and libraries --------------------------------------------- -set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake) - -# --- Find camera interfaces -find_package(PCO) -find_package(PF) -find_package(IPE) -find_package(Pylon) - -# --- Find frame grabber interfaces -find_package(FgLib5) -find_package(ClSerMe4) - -# --- Miscellanous packages -find_package(PkgConfig) -find_program(GLIB2_MKENUMS glib-mkenums REQUIRED) -pkg_check_modules(GLIB2 glib-2.0>=2.24 REQUIRED) -pkg_check_modules(GOBJECT2 gobject-2.0>=2.24 REQUIRED) -pkg_check_modules(GMODULE2 gmodule-2.0>=2.24 REQUIRED) - -include_directories( - ${CMAKE_CURRENT_BINARY_DIR} - ${CMAKE_CURRENT_SOURCE_DIR} - ${CMAKE_CURRENT_SOURCE_DIR}/cameras - ${GLIB2_INCLUDE_DIRS} - ${GOBJECT2_INCLUDE_DIRS}) - -# --- Configure step -configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config.h.in - ${CMAKE_CURRENT_BINARY_DIR}/config.h) - -set(uca_LIBS - ${GLIB2_LIBRARIES} - ${GOBJECT2_LIBRARIES} - ${GMODULE2_LIBRARIES}) - -set(uca_enum_hdrs uca-camera.h) - -# --- Build options ----------------------------------------------------------- -option(HAVE_MOCK_CAMERA "Camera: Dummy" ON) - - -# --- Add sources if camera/framegrabber access sources are available --------- -if (PF_FOUND) - option(HAVE_PHOTON_FOCUS "Camera: Photon Focus MV2-D1280-640-CL-8" ON) - - if (HAVE_PHOTON_FOCUS AND CLSERME4_FOUND AND FGLIB5_FOUND) - list(APPEND uca_enum_hdrs cameras/uca-pf-camera.h) - - include_directories( - ${PF_INCLUDE_DIRS} - ${CLSERME4_INCLUDE_DIR} - ${FGLIB5_INCLUDE_DIR}) - - add_library(ucapf SHARED cameras/uca-pf-camera.c) - - target_link_libraries(ucapf - ${uca_LIBS} - ${CLSERME4_LIBRARY} - ${FGLIB5_LIBRARY} - ${PF_LIBRARIES}) - endif() -endif() - -if (PCO_FOUND AND CLSERME4_FOUND AND FGLIB5_FOUND) - option(HAVE_PCO_CL "Camera: CameraLink-based pco" ON) - - if (HAVE_PCO_CL) - list(APPEND uca_enum_hdrs cameras/uca-pco-camera.h) - - include_directories( - ${PCO_INCLUDE_DIRS} - ${CLSERME4_INCLUDE_DIR} - ${FGLIB5_INCLUDE_DIR}) - - add_library(ucapco SHARED cameras/uca-pco-camera.c) - - target_link_libraries(ucapco - ${uca_LIBS} - ${PCO_LIBRARIES} - ${CLSERME4_LIBRARY} - ${FGLIB5_LIBRARY}) - - install(TARGETS ucapco - LIBRARY DESTINATION ${LIB_INSTALL_DIR}/uca) - endif() -endif() - -if (IPE_FOUND) - option(HAVE_UFO_CAMERA "Camera: Custom based on Xilinx FPGA" ON) - - if (HAVE_UFO_CAMERA) - list(APPEND uca_enum_hdrs cameras/uca-ufo-camera.h) - - include_directories(${IPE_INCLUDE_DIRS}) - - add_library(ucaufo SHARED cameras/uca-ufo-camera.c) - target_link_libraries(ucaufo - ${uca_LIBS} - ${IPE_LIBRARIES} - ) - - install(TARGETS ucaufo - LIBRARY DESTINATION ${LIB_INSTALL_DIR}/uca) - endif() -endif() - -if (PYLON_FOUND) - option(HAVE_PYLON_CAMERA "Camera: Pylon based (Basler)" ON) - - if (HAVE_PYLON_CAMERA) - list(APPEND uca_SRCS cameras/uca-pylon-camera.c) - list(APPEND uca_HDRS cameras/uca-pylon-camera.h) - list(APPEND cameras "Pylon") - set(uca_LIBS ${uca_LIBS} ${LIBPYLONCAM_LIBRARIES}) - - include_directories(${LIBPYLONCAM_INCLUDEDIR}) - link_directories(${LIBPYLONCAM_LIBDIR}) - endif() - -endif() - -if (HAVE_MOCK_CAMERA) - add_library(ucamock SHARED cameras/uca-mock-camera.c) - install(TARGETS ucamock - LIBRARY DESTINATION ${LIB_INSTALL_DIR}/uca) -endif() - # --- Generate enum file add_custom_command( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/uca-enums.h COMMAND ${GLIB2_MKENUMS} ARGS --template uca-enums.h.template - ${uca_enum_hdrs} > ${CMAKE_CURRENT_BINARY_DIR}/uca-enums.h + ${UCA_ENUM_HDRS} > ${CMAKE_CURRENT_BINARY_DIR}/uca-enums.h WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} - DEPENDS ${uca_enum_hdrs} + DEPENDS ${UCA_ENUM_HDRS} ${CMAKE_CURRENT_SOURCE_DIR}/uca-enums.h.template) add_custom_command( @@ -158,15 +27,34 @@ add_custom_command( COMMAND ${GLIB2_MKENUMS} ARGS --template uca-enums.c.template - ${uca_enum_hdrs} > ${CMAKE_CURRENT_BINARY_DIR}/uca-enums.c + ${UCA_ENUM_HDRS} > ${CMAKE_CURRENT_BINARY_DIR}/uca-enums.c WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} - DEPENDS ${uca_enum_hdrs} + DEPENDS ${UCA_ENUM_HDRS} ${CMAKE_CURRENT_BINARY_DIR}/uca-enums.h ${CMAKE_CURRENT_SOURCE_DIR}/uca-enums.c.template ) + +# --- Configure --------------------------------------------------------------- + +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config.h.in + ${CMAKE_CURRENT_BINARY_DIR}/config.h) + +set(prefix ${CMAKE_INSTALL_PREFIX}) +if (CI_INSTALL_PREFIX) + set(prefix ${CI_INSTALL_PREFIX}) +endif() + +set(exec_prefix "\${prefix}") +set(libdir ${prefix}/${LIB_INSTALL_DIR}) +set(includedir "\${prefix}/include") +set(VERSION ${UCA_VERSION_STRING}) + +configure_file("${CMAKE_CURRENT_SOURCE_DIR}/uca.pc.in" + "${CMAKE_CURRENT_BINARY_DIR}/uca.pc" @ONLY IMMEDIATE) + + # --- Build target ------------------------------------------------------------ -add_definitions("-std=c99 -Wall") add_library(uca SHARED ${uca_SRCS} @@ -176,8 +64,8 @@ set_target_properties(uca PROPERTIES VERSION ${UCA_ABI_VERSION} SOVERSION ${UCA_VERSION_MAJOR}) -target_link_libraries(uca - ${uca_LIBS}) +target_link_libraries(uca ${UCA_DEPS}) + # --- Build documentation ----------------------------------------------------- pkg_check_modules(GTK_DOC gtk-doc) @@ -269,37 +157,26 @@ endif() # --- Install target ---------------------------------------------------------- -set(LIB_INSTALL_DIR "lib${LIB_SUFFIX}") install(TARGETS uca - LIBRARY DESTINATION ${LIB_INSTALL_DIR}) - -install(FILES ${uca_HDRS} - DESTINATION include/uca) - -# --- install pkg-config file -set(prefix ${CMAKE_INSTALL_PREFIX}) -if (CI_INSTALL_PREFIX) - set(prefix ${CI_INSTALL_PREFIX}) -endif() + LIBRARY DESTINATION ${LIB_INSTALL_DIR} + COMPONENT libraries) -set(exec_prefix "\${prefix}") -set(libdir ${prefix}/${LIB_INSTALL_DIR}) -set(includedir "\${prefix}/include") -set(VERSION ${UCA_VERSION_STRING}) +install(FILES ${CMAKE_CURRENT_BINARY_DIR}/uca.pc + DESTINATION lib/pkgconfig + COMPONENT libraries) -configure_file("${CMAKE_CURRENT_SOURCE_DIR}/uca.pc.in" "${CMAKE_CURRENT_BINARY_DIR}/uca.pc" @ONLY IMMEDIATE) +install(FILES ${uca_HDRS} + DESTINATION include/uca + COMPONENT headers) -install(FILES ${CMAKE_CURRENT_BINARY_DIR}/uca.pc DESTINATION lib/pkgconfig) +# --- Generate package description -------------------------------------------- set(CPACK_PACKAGE_DESCRIPTION "Unified Camera Access library") -set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Abstract interface for different camera classes and frame grabber devices") +set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "GObject-based library for accessing scientific cameras") set(CPACK_PACKAGE_NAME "libuca") -# --- Distro specific -set(CPACK_DEBIAN_PACKAGE_DEPENDS "libc6 (>= 2.3.6), libgcc1 (>= 1:4.1)") - # this doesn't work when building RPMs on Jenkins set(CPACK_SET_DESTDIR ON) @@ -310,13 +187,12 @@ set(CPACK_PACKAGE_VERSION_MINOR ${UCA_VERSION_MINOR}) set(CPACK_PACKAGE_VERSION_PATCH ${UCA_VERSION_PATCH}) set(VERSION ${UCA_VERSION_STRING}) -set(CPACK_GENERATOR "DEB;RPM;") +set(CPACK_GENERATOR "RPM;") + set(CPACK_SOURCE_GENERATOR "TGZ") set(CPACK_SOURCE_IGNORE_FILES ".git" "tags" ".bzr" ".swp") set(CPACK_SOURCE_PACKAGE_FILE_NAME "libuca-${UCA_VERSION_STRING}" CACHE INTERNAL "tarball basename") set(CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}-${UCA_VERSION_STRING}-${CMAKE_SYSTEM_PROCESSOR}") -configure_file("${CMAKE_CURRENT_SOURCE_DIR}/../libuca.spec.in" - "${CMAKE_CURRENT_BINARY_DIR}/../libuca.spec" @ONLY IMMEDIATE) include(CPack) diff --git a/src/cameras/uca-mock-camera.c b/src/cameras/uca-mock-camera.c deleted file mode 100644 index 7cd4689..0000000 --- a/src/cameras/uca-mock-camera.c +++ /dev/null @@ -1,409 +0,0 @@ -/* Copyright (C) 2011, 2012 Matthias Vogelgesang - (Karlsruhe Institute of Technology) - - This library is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by the - Free Software Foundation; either version 2.1 of the License, or (at your - option) any later version. - - This library is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more - details. - - You should have received a copy of the GNU Lesser General Public License along - with this library; if not, write to the Free Software Foundation, Inc., 51 - Franklin St, Fifth Floor, Boston, MA 02110, USA */ - -#include -#include -#include "uca-mock-camera.h" - -#define UCA_MOCK_CAMERA_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), UCA_TYPE_MOCK_CAMERA, UcaMockCameraPrivate)) - -G_DEFINE_TYPE(UcaMockCamera, uca_mock_camera, UCA_TYPE_CAMERA) - -enum { - PROP_FRAMERATE = N_BASE_PROPERTIES, - N_PROPERTIES -}; - -static const gint mock_overrideables[] = { - PROP_NAME, - PROP_SENSOR_WIDTH, - PROP_SENSOR_HEIGHT, - PROP_SENSOR_BITDEPTH, - PROP_SENSOR_HORIZONTAL_BINNING, - PROP_SENSOR_HORIZONTAL_BINNINGS, - PROP_SENSOR_VERTICAL_BINNING, - PROP_SENSOR_VERTICAL_BINNINGS, - PROP_TRIGGER_MODE, - PROP_EXPOSURE_TIME, - PROP_ROI_X, - PROP_ROI_Y, - PROP_ROI_WIDTH, - PROP_ROI_HEIGHT, - PROP_ROI_HEIGHT_MULTIPLIER, - PROP_ROI_WIDTH_MULTIPLIER, - PROP_SENSOR_MAX_FRAME_RATE, - PROP_HAS_STREAMING, - PROP_HAS_CAMRAM_RECORDING, - 0, -}; - -static GParamSpec *mock_properties[N_PROPERTIES] = { NULL, }; - -struct _UcaMockCameraPrivate { - guint width; - guint height; - guint roi_x, roi_y, roi_width, roi_height; - gfloat frame_rate; - gfloat max_frame_rate; - gdouble exposure_time; - guint8 *dummy_data; - guint current_frame; - - gboolean thread_running; - - GThread *grab_thread; - GValueArray *binnings; -}; - -static const char g_digits[10][20] = { - /* 0 */ - { 0x00, 0xff, 0xff, 0x00, - 0xff, 0x00, 0x00, 0xff, - 0xff, 0x00, 0x00, 0xff, - 0xff, 0x00, 0x00, 0xff, - 0x00, 0xff, 0xff, 0x00 }, - /* 1 */ - { 0x00, 0x00, 0xff, 0x00, - 0x00, 0xff, 0xff, 0x00, - 0x00, 0x00, 0xff, 0x00, - 0x00, 0x00, 0xff, 0x00, - 0x00, 0x00, 0xff, 0x00 }, - /* 2 */ - { 0x00, 0xff, 0xff, 0x00, - 0xff, 0x00, 0x00, 0xff, - 0x00, 0x00, 0xff, 0x00, - 0x00, 0xff, 0x00, 0x00, - 0xff, 0xff, 0xff, 0xff }, - /* 3 */ - { 0x00, 0xff, 0xff, 0x00, - 0xff, 0x00, 0x00, 0xff, - 0x00, 0x00, 0xff, 0x00, - 0xff, 0x00, 0x00, 0xff, - 0x00, 0xff, 0xff, 0x00 }, - /* 4 */ - { 0xff, 0x00, 0x00, 0x00, - 0xff, 0x00, 0x00, 0xff, - 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0x00, 0xff, - 0x00, 0x00, 0x00, 0xff }, - /* 5 */ - { 0xff, 0xff, 0xff, 0xff, - 0xff, 0x00, 0x00, 0x00, - 0x00, 0xff, 0xff, 0x00, - 0x00, 0x00, 0x00, 0xff, - 0xff, 0xff, 0xff, 0x00 }, - /* 6 */ - { 0x00, 0xff, 0xff, 0xff, - 0xff, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xff, 0x00, - 0xff, 0x00, 0x00, 0xff, - 0x00, 0xff, 0xff, 0x00 }, - /* 7 */ - { 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0x00, 0xff, - 0x00, 0x00, 0xff, 0x00, - 0x00, 0xff, 0x00, 0x00, - 0xff, 0x00, 0x00, 0x00 }, - /* 8 */ - { 0x00, 0xff, 0xff, 0x00, - 0xff, 0x00, 0x00, 0xff, - 0x00, 0xff, 0xff, 0x00, - 0xff, 0x00, 0x00, 0xff, - 0x00, 0xff, 0xff, 0x00 }, - /* 9 */ - { 0x00, 0xff, 0xff, 0x00, - 0xff, 0x00, 0x00, 0xff, - 0x00, 0xff, 0xff, 0xff, - 0x00, 0x00, 0x00, 0xff, - 0xff, 0xff, 0xff, 0x00 } -}; - -static const guint DIGIT_WIDTH = 4; -static const guint DIGIT_HEIGHT = 5; - -static void print_number(gchar *buffer, guint number, guint x, guint y, guint width) -{ - for (int i = 0; i < DIGIT_WIDTH; i++) { - for (int j = 0; j < DIGIT_HEIGHT; j++) { - buffer[(y+j)*width + (x+i)] = g_digits[number][j*DIGIT_WIDTH+i]; - } - } -} - -static void print_current_frame(UcaMockCameraPrivate *priv, gchar *buffer) -{ - guint number = priv->current_frame; - guint divisor = 100000000; - int x = 10; - while (divisor > 1) { - print_number(buffer, number / divisor, x, 10, priv->width); - number = number % divisor; - divisor = divisor / 10; - x += DIGIT_WIDTH + 1; - } -} - -static gpointer mock_grab_func(gpointer data) -{ - UcaMockCamera *mock_camera = UCA_MOCK_CAMERA(data); - g_return_val_if_fail(UCA_IS_MOCK_CAMERA(mock_camera), NULL); - - UcaMockCameraPrivate *priv = UCA_MOCK_CAMERA_GET_PRIVATE(mock_camera); - UcaCamera *camera = UCA_CAMERA(mock_camera); - const gulong sleep_time = (gulong) G_USEC_PER_SEC / priv->frame_rate; - - while (priv->thread_running) { - camera->grab_func(priv->dummy_data, camera->user_data); - g_usleep(sleep_time); - } - - return NULL; -} - -static void uca_mock_camera_start_recording(UcaCamera *camera, GError **error) -{ - gboolean transfer_async = FALSE; - UcaMockCameraPrivate *priv; - g_return_if_fail(UCA_IS_MOCK_CAMERA(camera)); - - priv = UCA_MOCK_CAMERA_GET_PRIVATE(camera); - /* TODO: check that roi_x + roi_width < priv->width */ - priv->dummy_data = (guint8 *) g_malloc0(priv->roi_width * priv->roi_height); - - g_object_get(G_OBJECT(camera), - "transfer-asynchronously", &transfer_async, - NULL); - - /* - * In case asynchronous transfer is requested, we start a new thread that - * invokes the grab callback, otherwise nothing will be done here. - */ - if (transfer_async) { - GError *tmp_error = NULL; - priv->thread_running = TRUE; - priv->grab_thread = g_thread_create(mock_grab_func, camera, TRUE, &tmp_error); - - if (tmp_error != NULL) { - priv->thread_running = FALSE; - g_propagate_error(error, tmp_error); - } - } -} - -static void uca_mock_camera_stop_recording(UcaCamera *camera, GError **error) -{ - gboolean transfer_async = FALSE; - UcaMockCameraPrivate *priv; - g_return_if_fail(UCA_IS_MOCK_CAMERA(camera)); - - priv = UCA_MOCK_CAMERA_GET_PRIVATE(camera); - g_free(priv->dummy_data); - priv->dummy_data = NULL; - - g_object_get(G_OBJECT(camera), - "transfer-asynchronously", &transfer_async, - NULL); - - if (transfer_async) { - priv->thread_running = FALSE; - g_thread_join(priv->grab_thread); - } -} - -static void uca_mock_camera_grab(UcaCamera *camera, gpointer *data, GError **error) -{ - g_return_if_fail(UCA_IS_MOCK_CAMERA(camera)); - g_return_if_fail(data != NULL); - - UcaMockCameraPrivate *priv = UCA_MOCK_CAMERA_GET_PRIVATE(camera); - - if (*data == NULL) - *data = g_malloc0(priv->width * priv->height); - - g_memmove(*data, priv->dummy_data, priv->width * priv->height); - print_current_frame(priv, *data); - priv->current_frame++; -} - -static void uca_mock_camera_set_property(GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) -{ - g_return_if_fail(UCA_IS_MOCK_CAMERA(object)); - UcaMockCameraPrivate *priv = UCA_MOCK_CAMERA_GET_PRIVATE(object); - - switch (property_id) { - case PROP_EXPOSURE_TIME: - priv->exposure_time = g_value_get_double(value); - break; - case PROP_FRAMERATE: - priv->frame_rate = g_value_get_float(value); - break; - case PROP_ROI_X: - priv->roi_x = g_value_get_uint(value); - break; - case PROP_ROI_Y: - priv->roi_y = g_value_get_uint(value); - break; - case PROP_ROI_WIDTH: - priv->roi_width = g_value_get_uint(value); - break; - case PROP_ROI_HEIGHT: - priv->roi_height = g_value_get_uint(value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); - return; - } -} - -static void uca_mock_camera_get_property(GObject *object, guint property_id, GValue *value, GParamSpec *pspec) -{ - UcaMockCameraPrivate *priv = UCA_MOCK_CAMERA_GET_PRIVATE(object); - - switch (property_id) { - case PROP_NAME: - g_value_set_string(value, "mock camera"); - break; - case PROP_SENSOR_WIDTH: - 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; - case PROP_SENSOR_HORIZONTAL_BINNING: - g_value_set_uint(value, 1); - break; - case PROP_SENSOR_HORIZONTAL_BINNINGS: - g_value_set_boxed(value, priv->binnings); - break; - case PROP_SENSOR_VERTICAL_BINNING: - g_value_set_uint(value, 1); - break; - case PROP_SENSOR_VERTICAL_BINNINGS: - g_value_set_boxed(value, priv->binnings); - break; - case PROP_EXPOSURE_TIME: - g_value_set_double(value, priv->exposure_time); - break; - case PROP_TRIGGER_MODE: - g_value_set_enum(value, UCA_CAMERA_TRIGGER_AUTO); - break; - case PROP_ROI_X: - g_value_set_uint(value, priv->roi_x); - break; - case PROP_ROI_Y: - g_value_set_uint(value, priv->roi_y); - break; - case PROP_ROI_WIDTH: - g_value_set_uint(value, priv->roi_width); - break; - case PROP_ROI_HEIGHT: - g_value_set_uint(value, priv->roi_height); - break; - case PROP_ROI_WIDTH_MULTIPLIER: - g_value_set_uint(value, 1); - break; - case PROP_ROI_HEIGHT_MULTIPLIER: - g_value_set_uint(value, 1); - break; - case PROP_SENSOR_MAX_FRAME_RATE: - g_value_set_float(value, priv->max_frame_rate); - break; - case PROP_HAS_STREAMING: - g_value_set_boolean(value, TRUE); - break; - case PROP_HAS_CAMRAM_RECORDING: - g_value_set_boolean(value, FALSE); - break; - case PROP_FRAMERATE: - g_value_set_float(value, priv->frame_rate); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); - break; - } -} - -static void uca_mock_camera_finalize(GObject *object) -{ - UcaMockCameraPrivate *priv = UCA_MOCK_CAMERA_GET_PRIVATE(object); - - if (priv->thread_running) { - priv->thread_running = FALSE; - g_thread_join(priv->grab_thread); - } - - g_free(priv->dummy_data); - g_value_array_free(priv->binnings); - - G_OBJECT_CLASS(uca_mock_camera_parent_class)->finalize(object); -} - -static void uca_mock_camera_class_init(UcaMockCameraClass *klass) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS(klass); - gobject_class->set_property = uca_mock_camera_set_property; - 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 i = 0; mock_overrideables[i] != 0; i++) - g_object_class_override_property(gobject_class, mock_overrideables[i], uca_camera_props[mock_overrideables[i]]); - - mock_properties[PROP_FRAMERATE] = - g_param_spec_float("frame-rate", - "Frame rate", - "Number of frames per second that are taken", - 1.0f, 100.0f, 100.0f, - G_PARAM_READWRITE); - - for (guint id = N_BASE_PROPERTIES; id < N_PROPERTIES; id++) - g_object_class_install_property(gobject_class, id, mock_properties[id]); - - g_type_class_add_private(klass, sizeof(UcaMockCameraPrivate)); -} - -static void uca_mock_camera_init(UcaMockCamera *self) -{ - self->priv = UCA_MOCK_CAMERA_GET_PRIVATE(self); - self->priv->roi_x = 0; - self->priv->roi_y = 0; - self->priv->width = self->priv->roi_width = 640; - self->priv->height = self->priv->roi_height = 480; - self->priv->frame_rate = self->priv->max_frame_rate = 100000.0f; - self->priv->grab_thread = NULL; - self->priv->current_frame = 0; - - self->priv->binnings = g_value_array_new(1); - GValue val = {0}; - g_value_init(&val, G_TYPE_UINT); - g_value_set_uint(&val, 1); - g_value_array_append(self->priv->binnings, &val); -} - -G_MODULE_EXPORT UcaCamera * -uca_camera_impl_new (GError **error) -{ - UcaCamera *camera = UCA_CAMERA (g_object_new (UCA_TYPE_MOCK_CAMERA, NULL)); - return camera; -} diff --git a/src/cameras/uca-mock-camera.h b/src/cameras/uca-mock-camera.h deleted file mode 100644 index 9ee9190..0000000 --- a/src/cameras/uca-mock-camera.h +++ /dev/null @@ -1,65 +0,0 @@ -/* Copyright (C) 2011, 2012 Matthias Vogelgesang - (Karlsruhe Institute of Technology) - - This library is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by the - Free Software Foundation; either version 2.1 of the License, or (at your - option) any later version. - - This library is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more - details. - - You should have received a copy of the GNU Lesser General Public License along - with this library; if not, write to the Free Software Foundation, Inc., 51 - Franklin St, Fifth Floor, Boston, MA 02110, USA */ - -#ifndef __UCA_MOCK_CAMERA_H -#define __UCA_MOCK_CAMERA_H - -#include -#include "uca-camera.h" - -G_BEGIN_DECLS - -#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)) -#define UCA_IS_MOCK_CAMERA(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), UCA_TYPE_MOCK_CAMERA)) -#define UCA_MOCK_CAMERA_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), UFO_TYPE_MOCK_CAMERA, UfoMockCameraClass)) -#define UCA_IS_MOCK_CAMERA_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), UCA_TYPE_MOCK_CAMERA)) -#define UCA_MOCK_CAMERA_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), UCA_TYPE_MOCK_CAMERA, UcaMockCameraClass)) - -typedef struct _UcaMockCamera UcaMockCamera; -typedef struct _UcaMockCameraClass UcaMockCameraClass; -typedef struct _UcaMockCameraPrivate UcaMockCameraPrivate; - -/** - * UcaMockCamera: - * - * Creates #UcaMockCamera instances by loading corresponding shared objects. The - * contents of the #UcaMockCamera structure are private and should only be - * accessed via the provided API. - */ -struct _UcaMockCamera { - /*< private >*/ - UcaCamera parent; - - UcaMockCameraPrivate *priv; -}; - -/** - * UcaMockCameraClass: - * - * #UcaMockCamera class - */ -struct _UcaMockCameraClass { - /*< private >*/ - UcaCameraClass parent; -}; - -GType uca_mock_camera_get_type(void); - -G_END_DECLS - -#endif diff --git a/src/cameras/uca-pco-camera.c b/src/cameras/uca-pco-camera.c deleted file mode 100644 index 8bf2936..0000000 --- a/src/cameras/uca-pco-camera.c +++ /dev/null @@ -1,1398 +0,0 @@ -/* Copyright (C) 2011, 2012 Matthias Vogelgesang - (Karlsruhe Institute of Technology) - - This library is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by the - Free Software Foundation; either version 2.1 of the License, or (at your - option) any later version. - - This library is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more - details. - - You should have received a copy of the GNU Lesser General Public License along - with this library; if not, write to the Free Software Foundation, Inc., 51 - Franklin St, Fifth Floor, Boston, MA 02110, USA */ - -#include -#include -#include -#include -#include -#include -#include -#include "uca-camera.h" -#include "uca-pco-camera.h" -#include "uca-enums.h" - -#define FG_TRY_PARAM(fg, camobj, param, val_addr, port) \ - { int r = Fg_setParameter(fg, param, val_addr, port); \ - if (r != FG_OK) { \ - g_set_error(error, UCA_PCO_CAMERA_ERROR, \ - UCA_PCO_CAMERA_ERROR_FG_GENERAL, \ - "%s", Fg_getLastErrorDescription(fg)); \ - g_object_unref(camobj); \ - return NULL; \ - } } - -#define FG_SET_ERROR(err, fg, err_type) \ - if (err != FG_OK) { \ - g_set_error(error, UCA_PCO_CAMERA_ERROR, \ - err_type, \ - "%s", Fg_getLastErrorDescription(fg)); \ - return; \ - } - -#define HANDLE_PCO_ERROR(err) \ - if ((err) != PCO_NOERROR) { \ - g_set_error(error, UCA_PCO_CAMERA_ERROR, \ - UCA_PCO_CAMERA_ERROR_LIBPCO_GENERAL,\ - "libpco error %x", err); \ - return; \ - } - -#define UCA_PCO_CAMERA_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), UCA_TYPE_PCO_CAMERA, UcaPcoCameraPrivate)) - -G_DEFINE_TYPE(UcaPcoCamera, uca_pco_camera, UCA_TYPE_CAMERA) - -#define TIMEBASE_INVALID 0xDEAD - -/** - * UcaPcoCameraRecordMode: - * @UCA_PCO_CAMERA_RECORD_MODE_SEQUENCE: Store all frames and stop if necessary - * @UCA_PCO_CAMERA_RECORD_MODE_RING_BUFFER: Store frames in ring-buffer fashion - * and overwrite if necessary - */ - -/** - * UcaPcoCameraAcquireMode: - * @UCA_PCO_CAMERA_ACQUIRE_MODE_AUTO: Take all images - * @UCA_PCO_CAMERA_ACQUIRE_MODE_EXTERNAL: Use signal - */ - -/** - * UcaPcoCameraTimestamp: - * @UCA_PCO_CAMERA_TIMESTAMP_NONE: Don't embed any timestamp - * @UCA_PCO_CAMERA_TIMESTAMP_BINARY: Embed a BCD-coded timestamp in the first - * bytes - * @UCA_PCO_CAMERA_TIMESTAMP_ASCII: Embed a visible ASCII timestamp in the image - */ - -/** - * UcaPcoCameraError: - * @UCA_PCO_CAMERA_ERROR_LIBPCO_INIT: Initializing libpco failed - * @UCA_PCO_CAMERA_ERROR_LIBPCO_GENERAL: General libpco error - * @UCA_PCO_CAMERA_ERROR_UNSUPPORTED: Camera type is not supported - * @UCA_PCO_CAMERA_ERROR_FG_INIT: Framegrabber initialization failed - * @UCA_PCO_CAMERA_ERROR_FG_GENERAL: General framegrabber error - * @UCA_PCO_CAMERA_ERROR_FG_ACQUISITION: Framegrabber acquisition error - */ -GQuark uca_pco_camera_error_quark() -{ - return g_quark_from_static_string("uca-pco-camera-error-quark"); -} - -enum { - PROP_SENSOR_EXTENDED = N_BASE_PROPERTIES, - PROP_SENSOR_WIDTH_EXTENDED, - PROP_SENSOR_HEIGHT_EXTENDED, - PROP_SENSOR_TEMPERATURE, - PROP_SENSOR_PIXELRATES, - PROP_SENSOR_PIXELRATE, - PROP_SENSOR_ADCS, - PROP_SENSOR_MAX_ADCS, - PROP_DELAY_TIME, - PROP_HAS_DOUBLE_IMAGE_MODE, - PROP_DOUBLE_IMAGE_MODE, - PROP_OFFSET_MODE, - PROP_RECORD_MODE, - PROP_ACQUIRE_MODE, - PROP_COOLING_POINT, - PROP_COOLING_POINT_MIN, - PROP_COOLING_POINT_MAX, - PROP_COOLING_POINT_DEFAULT, - PROP_NOISE_FILTER, - PROP_TIMESTAMP_MODE, - N_PROPERTIES -}; - -static gint base_overrideables[] = { - PROP_NAME, - PROP_SENSOR_WIDTH, - PROP_SENSOR_HEIGHT, - PROP_SENSOR_BITDEPTH, - PROP_SENSOR_HORIZONTAL_BINNING, - PROP_SENSOR_HORIZONTAL_BINNINGS, - PROP_SENSOR_VERTICAL_BINNING, - PROP_SENSOR_VERTICAL_BINNINGS, - PROP_SENSOR_MAX_FRAME_RATE, - PROP_EXPOSURE_TIME, - PROP_TRIGGER_MODE, - PROP_ROI_X, - PROP_ROI_Y, - PROP_ROI_WIDTH, - PROP_ROI_HEIGHT, - PROP_ROI_WIDTH_MULTIPLIER, - PROP_ROI_HEIGHT_MULTIPLIER, - PROP_HAS_STREAMING, - PROP_HAS_CAMRAM_RECORDING, - 0 -}; - -static GParamSpec *pco_properties[N_PROPERTIES] = { NULL, }; - -/* - * This structure defines type-specific properties of PCO cameras. - */ -typedef struct { - int camera_type; - const char *so_file; - int cl_type; - int cl_format; - gfloat max_frame_rate; - gboolean has_camram; -} pco_cl_map_entry; - -struct _UcaPcoCameraPrivate { - pco_handle pco; - pco_cl_map_entry *camera_description; - - Fg_Struct *fg; - guint fg_port; - dma_mem *fg_mem; - - guint frame_width; - guint frame_height; - gsize num_bytes; - guint16 *grab_buffer; - - guint16 width, height; - guint16 width_ex, height_ex; - guint16 binning_h, binning_v; - guint16 roi_x, roi_y; - guint16 roi_width, roi_height; - guint16 roi_horizontal_steps, roi_vertical_steps; - GValueArray *horizontal_binnings; - GValueArray *vertical_binnings; - GValueArray *pixelrates; - - /* The time bases are given as pco time bases (TIMEBASE_NS and so on) */ - guint16 delay_timebase; - guint16 exposure_timebase; - - frameindex_t last_frame; - guint16 active_segment; - guint num_recorded_images; - guint current_image; -}; - -static pco_cl_map_entry pco_cl_map[] = { - { CAMERATYPE_PCO_EDGE, "libFullAreaGray8.so", FG_CL_8BIT_FULL_10, FG_GRAY, 30.0f, FALSE }, - { CAMERATYPE_PCO4000, "libDualAreaGray16.so", FG_CL_SINGLETAP_16_BIT, FG_GRAY16, 5.0f, TRUE }, - { CAMERATYPE_PCO_DIMAX_STD, "libFullAreaGray16.so", FG_CL_SINGLETAP_8_BIT, FG_GRAY16, 1279.0f, TRUE }, - { 0, NULL, 0, 0, 0.0f, FALSE } -}; - -static pco_cl_map_entry *get_pco_cl_map_entry(int camera_type) -{ - pco_cl_map_entry *entry = pco_cl_map; - - while (entry->camera_type != 0) { - if (entry->camera_type == camera_type) - return entry; - entry++; - } - - return NULL; -} - -static guint fill_binnings(UcaPcoCameraPrivate *priv) -{ - uint16_t *horizontal = NULL; - uint16_t *vertical = NULL; - guint num_horizontal, num_vertical; - - guint err = pco_get_possible_binnings(priv->pco, - &horizontal, &num_horizontal, - &vertical, &num_vertical); - - GValue val = {0}; - g_value_init(&val, G_TYPE_UINT); - - if (err == PCO_NOERROR) { - priv->horizontal_binnings = g_value_array_new(num_horizontal); - priv->vertical_binnings = g_value_array_new(num_vertical); - - for (guint i = 0; i < num_horizontal; i++) { - g_value_set_uint(&val, horizontal[i]); - g_value_array_append(priv->horizontal_binnings, &val); - } - - for (guint i = 0; i < num_vertical; i++) { - g_value_set_uint(&val, vertical[i]); - g_value_array_append(priv->vertical_binnings, &val); - } - } - - free(horizontal); - free(vertical); - return err; -} - -static void fill_pixelrates(UcaPcoCameraPrivate *priv, guint32 rates[4], gint num_rates) -{ - GValue val = {0}; - g_value_init(&val, G_TYPE_UINT); - priv->pixelrates = g_value_array_new(num_rates); - - for (gint i = 0; i < num_rates; i++) { - g_value_set_uint(&val, (guint) rates[i]); - g_value_array_append(priv->pixelrates, &val); - } -} - -static guint override_temperature_range(UcaPcoCameraPrivate *priv) -{ - int16_t default_temp, min_temp, max_temp; - guint err = pco_get_cooling_range(priv->pco, &default_temp, &min_temp, &max_temp); - - if (err == PCO_NOERROR) { - GParamSpecInt *spec = (GParamSpecInt *) pco_properties[PROP_COOLING_POINT]; - spec->minimum = min_temp; - spec->maximum = max_temp; - spec->default_value = default_temp; - } - else - g_warning("Unable to retrieve cooling range"); - - return err; -} - -static void property_override_default_guint_value (GObjectClass *oclass, const gchar *property_name, guint new_default) -{ - GParamSpecUInt *pspec = G_PARAM_SPEC_UINT (g_object_class_find_property (oclass, property_name)); - - if (pspec != NULL) - pspec->default_value = new_default; - else - g_warning ("pspec for %s not found\n", property_name); -} - -static void override_maximum_adcs(UcaPcoCameraPrivate *priv) -{ - GParamSpecInt *spec = (GParamSpecInt *) pco_properties[PROP_SENSOR_ADCS]; - spec->maximum = pco_get_maximum_number_of_adcs(priv->pco); -} - -static gdouble convert_timebase(guint16 timebase) -{ - switch (timebase) { - case TIMEBASE_NS: - return 1e-9; - case TIMEBASE_US: - return 1e-6; - case TIMEBASE_MS: - return 1e-3; - default: - g_warning("Unknown timebase"); - } - return 1e-3; -} - -static void read_timebase(UcaPcoCameraPrivate *priv) -{ - pco_get_timebase(priv->pco, &priv->delay_timebase, &priv->exposure_timebase); -} - -static gdouble get_suitable_timebase(gdouble time) -{ - if (time * 1e3 >= 1.0) - return TIMEBASE_MS; - if (time * 1e6 >= 1.0) - return TIMEBASE_US; - if (time * 1e9 >= 1.0) - return TIMEBASE_NS; - return TIMEBASE_INVALID; -} - -static int fg_callback(frameindex_t frame, struct fg_apc_data *apc) -{ - UcaCamera *camera = UCA_CAMERA(apc); - UcaPcoCameraPrivate *priv = UCA_PCO_CAMERA_GET_PRIVATE(camera); - gpointer data = Fg_getImagePtrEx(priv->fg, frame, priv->fg_port, priv->fg_mem); - - if (priv->camera_description->camera_type != CAMERATYPE_PCO_EDGE) - camera->grab_func(data, camera->user_data); - else { - pco_get_reorder_func(priv->pco)(priv->grab_buffer, data, priv->frame_width, priv->frame_height); - camera->grab_func(priv->grab_buffer, camera->user_data); - } - - return 0; -} - -static gboolean setup_fg_callback(UcaCamera *camera) -{ - UcaPcoCameraPrivate *priv = UCA_PCO_CAMERA_GET_PRIVATE(camera); - struct FgApcControl ctrl; - - /* Jeez, as if a NULL pointer would not be good enough. */ - ctrl.data = (struct fg_apc_data *) camera; - ctrl.version = 0; - ctrl.func = &fg_callback; - ctrl.flags = FG_APC_DEFAULTS; - ctrl.timeout = 1; - - if (priv->grab_buffer) - g_free(priv->grab_buffer); - - priv->grab_buffer = g_malloc0(priv->frame_width * priv->frame_height * sizeof(guint16)); - - return Fg_registerApcHandler(priv->fg, priv->fg_port, &ctrl, FG_APC_CONTROL_BASIC) == FG_OK; -} - -static void uca_pco_camera_start_recording(UcaCamera *camera, GError **error) -{ - g_return_if_fail(UCA_IS_PCO_CAMERA(camera)); - guint err = PCO_NOERROR; - - UcaPcoCameraPrivate *priv = UCA_PCO_CAMERA_GET_PRIVATE(camera); - guint16 binned_width, binned_height; - gboolean use_extended = FALSE; - gboolean transfer_async = FALSE; - - g_object_get (camera, "sensor-extended", &use_extended, NULL); - - if (use_extended) { - binned_width = priv->width_ex; - binned_height = priv->height_ex; - } - else { - binned_width = priv->width; - binned_height = priv->height; - } - - binned_width /= priv->binning_h; - binned_height /= priv->binning_v; - - if ((priv->roi_x + priv->roi_width > binned_width) || (priv->roi_y + priv->roi_height > binned_height)) { - g_set_error(error, UCA_PCO_CAMERA_ERROR, UCA_PCO_CAMERA_ERROR_UNSUPPORTED, - "ROI of size %ix%i @ (%i, %i) is outside of (binned) sensor size %ix%i\n", - priv->roi_width, priv->roi_height, priv->roi_x, priv->roi_y, binned_width, binned_height); - return; - } - - /* - * All parameters are valid. Now, set them on the camera. - */ - guint16 roi[4] = { priv->roi_x + 1, priv->roi_y + 1, priv->roi_x + priv->roi_width, priv->roi_y + priv->roi_height }; - - if (pco_set_roi(priv->pco, roi) != PCO_NOERROR) { - g_set_error(error, UCA_PCO_CAMERA_ERROR, UCA_PCO_CAMERA_ERROR_LIBPCO_GENERAL, - "Could not set ROI via pco_set_roi()"); - return; - } - - g_object_get(G_OBJECT(camera), "transfer-asynchronously", &transfer_async, NULL); - - /* - * FIXME: We cannot set the binning here as this breaks communication with - * the camera. Setting the binning works _before_ initializing the frame - * grabber though. However, it is rather inconvenient to initialize and - * de-initialize the frame grabber for each recording sequence. - */ - - /* if (pco_set_binning(priv->pco, priv->binning_h, priv->binning_v) != PCO_NOERROR) */ - /* g_warning("Cannot set binning\n"); */ - - if (priv->frame_width != priv->roi_width || priv->frame_height != priv->roi_height || priv->fg_mem == NULL) { - guint fg_width = priv->camera_description->camera_type == CAMERATYPE_PCO_EDGE ? 2 * priv->roi_width : priv->roi_width; - - priv->frame_width = priv->roi_width; - priv->frame_height = priv->roi_height; - priv->num_bytes = 2; - - Fg_setParameter(priv->fg, FG_WIDTH, &fg_width, priv->fg_port); - Fg_setParameter(priv->fg, FG_HEIGHT, &priv->frame_height, priv->fg_port); - - if (priv->fg_mem) - Fg_FreeMemEx(priv->fg, priv->fg_mem); - - const guint num_buffers = 2; - priv->fg_mem = Fg_AllocMemEx(priv->fg, - num_buffers * priv->frame_width * priv->frame_height * sizeof(uint16_t), num_buffers); - - if (priv->fg_mem == NULL) { - g_set_error(error, UCA_PCO_CAMERA_ERROR, UCA_PCO_CAMERA_ERROR_FG_INIT, - "%s", Fg_getLastErrorDescription(priv->fg)); - g_object_unref(camera); - return; - } - } - - if (transfer_async) - setup_fg_callback(camera); - - if ((priv->camera_description->camera_type == CAMERATYPE_PCO_DIMAX_STD) || - (priv->camera_description->camera_type == CAMERATYPE_PCO4000)) - pco_clear_active_segment(priv->pco); - - priv->last_frame = 0; - - err = pco_arm_camera(priv->pco); - HANDLE_PCO_ERROR(err); - - err = pco_start_recording(priv->pco); - HANDLE_PCO_ERROR(err); - - err = Fg_AcquireEx(priv->fg, priv->fg_port, GRAB_INFINITE, ACQ_STANDARD, priv->fg_mem); - FG_SET_ERROR(err, priv->fg, UCA_PCO_CAMERA_ERROR_FG_ACQUISITION); -} - -static void uca_pco_camera_stop_recording(UcaCamera *camera, GError **error) -{ - g_return_if_fail(UCA_IS_PCO_CAMERA(camera)); - UcaPcoCameraPrivate *priv = UCA_PCO_CAMERA_GET_PRIVATE(camera); - - guint err = pco_stop_recording(priv->pco); - HANDLE_PCO_ERROR(err); - - err = Fg_stopAcquireEx(priv->fg, priv->fg_port, priv->fg_mem, STOP_SYNC); - FG_SET_ERROR(err, priv->fg, UCA_PCO_CAMERA_ERROR_FG_ACQUISITION); - - err = Fg_setStatusEx(priv->fg, FG_UNBLOCK_ALL, 0, priv->fg_port, priv->fg_mem); - if (err == FG_INVALID_PARAMETER) - g_warning(" Unable to unblock all\n"); -} - -static void uca_pco_camera_start_readout(UcaCamera *camera, GError **error) -{ - g_return_if_fail(UCA_IS_PCO_CAMERA(camera)); - UcaPcoCameraPrivate *priv = UCA_PCO_CAMERA_GET_PRIVATE(camera); - - /* - * TODO: Check if readout mode is possible. This is not the case for the - * edge. - */ - - guint err = pco_get_active_segment(priv->pco, &priv->active_segment); - HANDLE_PCO_ERROR(err); - - err = pco_get_num_images(priv->pco, priv->active_segment, &priv->num_recorded_images); - HANDLE_PCO_ERROR(err); - - priv->current_image = 1; -} - -static void uca_pco_camera_trigger(UcaCamera *camera, GError **error) -{ - g_return_if_fail(UCA_IS_PCO_CAMERA(camera)); - UcaPcoCameraPrivate *priv = UCA_PCO_CAMERA_GET_PRIVATE(camera); - - /* TODO: Check if we can trigger */ - guint32 success = 0; - pco_force_trigger(priv->pco, &success); - - if (!success) - g_set_error(error, UCA_PCO_CAMERA_ERROR, UCA_PCO_CAMERA_ERROR_LIBPCO_GENERAL, - "Could not trigger frame acquisition"); -} - -static void uca_pco_camera_grab(UcaCamera *camera, gpointer *data, GError **error) -{ - static const gint MAX_TIMEOUT = G_MAXINT; - - g_return_if_fail(UCA_IS_PCO_CAMERA(camera)); - UcaPcoCameraPrivate *priv = UCA_PCO_CAMERA_GET_PRIVATE(camera); - - gboolean is_readout = FALSE; - g_object_get(G_OBJECT(camera), "is-readout", &is_readout, NULL); - - if (is_readout) { - if (priv->current_image == priv->num_recorded_images) { - *data = NULL; - return; - } - - /* - * No joke, the pco firmware allows to read a range of images but - * implements only reading single images ... - */ - pco_read_images(priv->pco, priv->active_segment, priv->current_image, priv->current_image); - priv->current_image++; - } - - pco_request_image(priv->pco); - priv->last_frame = Fg_getLastPicNumberBlockingEx(priv->fg, priv->last_frame+1, priv->fg_port, MAX_TIMEOUT, priv->fg_mem); - - if (priv->last_frame <= 0) { - guint err = FG_OK + 1; - FG_SET_ERROR(err, priv->fg, UCA_PCO_CAMERA_ERROR_FG_GENERAL); - } - - guint16 *frame = Fg_getImagePtrEx(priv->fg, priv->last_frame, priv->fg_port, priv->fg_mem); - - if (*data == NULL) - *data = g_malloc0(priv->frame_width * priv->frame_height * priv->num_bytes); - - if (priv->camera_description->camera_type == CAMERATYPE_PCO_EDGE) - pco_get_reorder_func(priv->pco)((guint16 *) *data, frame, priv->frame_width, priv->frame_height); - else - memcpy((gchar *) *data, (gchar *) frame, priv->frame_width * priv->frame_height * priv->num_bytes); -} - -static void uca_pco_camera_set_property(GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) -{ - UcaPcoCameraPrivate *priv = UCA_PCO_CAMERA_GET_PRIVATE(object); - - switch (property_id) { - case PROP_SENSOR_EXTENDED: - { - guint16 format = g_value_get_boolean (value) ? SENSORFORMAT_EXTENDED : SENSORFORMAT_STANDARD; - pco_set_sensor_format(priv->pco, format); - } - break; - - case PROP_ROI_X: - priv->roi_x = g_value_get_uint(value); - break; - - case PROP_ROI_Y: - priv->roi_y = g_value_get_uint(value); - break; - - case PROP_ROI_WIDTH: - { - guint width = g_value_get_uint(value); - - if (width % priv->roi_horizontal_steps) - g_warning("ROI width %i is not a multiple of %i", width, priv->roi_horizontal_steps); - else - priv->roi_width = width; - } - break; - - case PROP_ROI_HEIGHT: - { - guint height = g_value_get_uint(value); - - if (height % priv->roi_vertical_steps) - g_warning("ROI height %i is not a multiple of %i", height, priv->roi_vertical_steps); - else - priv->roi_height = height; - } - break; - - case PROP_SENSOR_HORIZONTAL_BINNING: - priv->binning_h = g_value_get_uint(value); - break; - - case PROP_SENSOR_VERTICAL_BINNING: - priv->binning_v = g_value_get_uint(value); - break; - - case PROP_EXPOSURE_TIME: - { - const gdouble time = g_value_get_double(value); - - if (priv->exposure_timebase == TIMEBASE_INVALID) - read_timebase(priv); - - /* - * Lets check if we can express the time in the current time - * base. If not, we need to adjust that. - */ - guint16 suitable_timebase = get_suitable_timebase(time); - - if (suitable_timebase == TIMEBASE_INVALID) { - g_warning("Cannot set such a small exposure time"); - } - else { - if (suitable_timebase != priv->exposure_timebase) { - priv->exposure_timebase = suitable_timebase; - if (pco_set_timebase(priv->pco, priv->delay_timebase, suitable_timebase) != PCO_NOERROR) - g_warning("Cannot set exposure time base"); - } - - gdouble timebase = convert_timebase(suitable_timebase); - guint32 timesteps = time / timebase; - if (pco_set_exposure_time(priv->pco, timesteps) != PCO_NOERROR) - g_warning("Cannot set exposure time"); - } - } - break; - - case PROP_DELAY_TIME: - { - const gdouble time = g_value_get_double(value); - - if (priv->delay_timebase == TIMEBASE_INVALID) - read_timebase(priv); - - /* - * Lets check if we can express the time in the current time - * base. If not, we need to adjust that. - */ - guint16 suitable_timebase = get_suitable_timebase(time); - - if (suitable_timebase == TIMEBASE_INVALID) { - if (time == 0.0) { - /* - * If we want to suppress any pre-exposure delays, we - * can set the 0 seconds in whatever time base that is - * currently active. - */ - if (pco_set_delay_time(priv->pco, 0) != PCO_NOERROR) - g_warning("Cannot set zero delay time"); - } - else - g_warning("Cannot set such a small exposure time"); - } - else { - if (suitable_timebase != priv->delay_timebase) { - priv->delay_timebase = suitable_timebase; - if (pco_set_timebase(priv->pco, suitable_timebase, priv->exposure_timebase) != PCO_NOERROR) - g_warning("Cannot set delay time base"); - } - - gdouble timebase = convert_timebase(suitable_timebase); - guint32 timesteps = time / timebase; - if (pco_set_delay_time(priv->pco, timesteps) != PCO_NOERROR) - g_warning("Cannot set delay time"); - } - } - break; - - case PROP_SENSOR_ADCS: - { - const guint num_adcs = g_value_get_uint(value); - if (pco_set_adc_mode(priv->pco, num_adcs) != PCO_NOERROR) - g_warning("Cannot set the number of ADCs per pixel\n"); - } - break; - - case PROP_SENSOR_PIXELRATE: - { - guint desired_pixel_rate = g_value_get_uint(value); - guint32 pixel_rate = 0; - - for (guint i = 0; i < priv->pixelrates->n_values; i++) { - if (g_value_get_uint(g_value_array_get_nth(priv->pixelrates, i)) == desired_pixel_rate) { - pixel_rate = desired_pixel_rate; - break; - } - } - - if (pixel_rate != 0) { - if (pco_set_pixelrate(priv->pco, pixel_rate) != PCO_NOERROR) - g_warning("Cannot set pixel rate"); - } - else - g_warning("%i Hz is not possible. Please check the \"sensor-pixelrates\" property", desired_pixel_rate); - } - break; - - case PROP_DOUBLE_IMAGE_MODE: - if (!pco_is_double_image_mode_available(priv->pco)) - g_warning("Double image mode is not available on this pco model"); - else - pco_set_double_image_mode(priv->pco, g_value_get_boolean(value)); - break; - - case PROP_OFFSET_MODE: - pco_set_offset_mode(priv->pco, g_value_get_boolean(value)); - break; - - case PROP_COOLING_POINT: - { - int16_t temperature = (int16_t) g_value_get_int(value); - pco_set_cooling_temperature(priv->pco, temperature); - } - break; - - case PROP_RECORD_MODE: - { - /* TODO: setting this is not possible for the edge */ - UcaPcoCameraRecordMode mode = (UcaPcoCameraRecordMode) g_value_get_enum(value); - - if (mode == UCA_PCO_CAMERA_RECORD_MODE_SEQUENCE) - pco_set_record_mode(priv->pco, RECORDER_SUBMODE_SEQUENCE); - else if (mode == UCA_PCO_CAMERA_RECORD_MODE_RING_BUFFER) - pco_set_record_mode(priv->pco, RECORDER_SUBMODE_RINGBUFFER); - else - g_warning("Unknown record mode"); - } - break; - - case PROP_ACQUIRE_MODE: - { - UcaPcoCameraAcquireMode mode = (UcaPcoCameraAcquireMode) g_value_get_enum(value); - unsigned int err = PCO_NOERROR; - - if (mode == UCA_PCO_CAMERA_ACQUIRE_MODE_AUTO) - err = pco_set_acquire_mode(priv->pco, ACQUIRE_MODE_AUTO); - else if (mode == UCA_PCO_CAMERA_ACQUIRE_MODE_EXTERNAL) - err = pco_set_acquire_mode(priv->pco, ACQUIRE_MODE_EXTERNAL); - else - g_warning("Unknown acquire mode"); - - if (err != PCO_NOERROR) - g_warning("Cannot set acquire mode"); - } - break; - - case PROP_TRIGGER_MODE: - { - UcaCameraTrigger trigger_mode = (UcaCameraTrigger) g_value_get_enum(value); - - switch (trigger_mode) { - case UCA_CAMERA_TRIGGER_AUTO: - pco_set_trigger_mode(priv->pco, TRIGGER_MODE_AUTOTRIGGER); - break; - case UCA_CAMERA_TRIGGER_INTERNAL: - pco_set_trigger_mode(priv->pco, TRIGGER_MODE_SOFTWARETRIGGER); - break; - case UCA_CAMERA_TRIGGER_EXTERNAL: - pco_set_trigger_mode(priv->pco, TRIGGER_MODE_EXTERNALTRIGGER); - break; - } - } - break; - - case PROP_NOISE_FILTER: - { - guint16 filter_mode = g_value_get_boolean(value) ? NOISE_FILTER_MODE_ON : NOISE_FILTER_MODE_OFF; - pco_set_noise_filter_mode(priv->pco, filter_mode); - } - break; - - case PROP_TIMESTAMP_MODE: - { - guint16 modes[] = { - TIMESTAMP_MODE_OFF, /* 0 */ - TIMESTAMP_MODE_BINARY, /* 1 = 1 << 0 */ - TIMESTAMP_MODE_ASCII, /* 2 = 1 << 1 */ - TIMESTAMP_MODE_BINARYANDASCII, /* 3 = 1 << 0 | 1 << 1 */ - }; - pco_set_timestamp_mode(priv->pco, modes[g_value_get_flags(value)]); - } - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); - return; - } -} - -static void uca_pco_camera_get_property(GObject *object, guint property_id, GValue *value, GParamSpec *pspec) -{ - UcaPcoCameraPrivate *priv = UCA_PCO_CAMERA_GET_PRIVATE(object); - - switch (property_id) { - case PROP_SENSOR_EXTENDED: - { - guint16 format; - pco_get_sensor_format(priv->pco, &format); - g_value_set_boolean(value, format == SENSORFORMAT_EXTENDED); - } - break; - - case PROP_SENSOR_WIDTH: - g_value_set_uint(value, priv->width); - break; - - case PROP_SENSOR_HEIGHT: - g_value_set_uint(value, priv->height); - break; - - case PROP_SENSOR_WIDTH_EXTENDED: - g_value_set_uint(value, priv->width_ex < priv->width ? priv->width : priv->width_ex); - break; - - case PROP_SENSOR_HEIGHT_EXTENDED: - g_value_set_uint(value, priv->height_ex < priv->height ? priv->height : priv->height_ex); - break; - - case PROP_SENSOR_HORIZONTAL_BINNING: - g_value_set_uint(value, priv->binning_h); - break; - - case PROP_SENSOR_HORIZONTAL_BINNINGS: - g_value_set_boxed(value, priv->horizontal_binnings); - break; - - case PROP_SENSOR_VERTICAL_BINNING: - g_value_set_uint(value, priv->binning_v); - break; - - case PROP_SENSOR_VERTICAL_BINNINGS: - g_value_set_boxed(value, priv->vertical_binnings); - break; - - case PROP_SENSOR_MAX_FRAME_RATE: - g_value_set_float(value, priv->camera_description->max_frame_rate); - break; - - case PROP_SENSOR_BITDEPTH: - g_value_set_uint(value, 16); - break; - - case PROP_SENSOR_TEMPERATURE: - { - gint32 ccd, camera, power; - pco_get_temperature(priv->pco, &ccd, &camera, &power); - g_value_set_double(value, ccd / 10.0); - } - break; - - case PROP_SENSOR_ADCS: - { - /* - * Up to now, the ADC mode corresponds directly to the number of - * ADCs in use. - */ - pco_adc_mode mode; - if (pco_get_adc_mode(priv->pco, &mode) != PCO_NOERROR) - g_warning("Cannot read number of ADCs per pixel"); - g_value_set_uint(value, mode); - } - break; - - case PROP_SENSOR_MAX_ADCS: - { - GParamSpecUInt *spec = (GParamSpecUInt *) pco_properties[PROP_SENSOR_ADCS]; - g_value_set_uint(value, spec->maximum); - } - break; - - case PROP_SENSOR_PIXELRATES: - g_value_set_boxed(value, priv->pixelrates); - break; - - case PROP_SENSOR_PIXELRATE: - { - guint32 pixelrate; - pco_get_pixelrate(priv->pco, &pixelrate); - g_value_set_uint(value, pixelrate); - } - break; - - case PROP_EXPOSURE_TIME: - { - uint32_t exposure_time; - pco_get_exposure_time(priv->pco, &exposure_time); - - if (priv->exposure_timebase == TIMEBASE_INVALID) - read_timebase(priv); - - g_value_set_double(value, convert_timebase(priv->exposure_timebase) * exposure_time); - } - break; - - case PROP_DELAY_TIME: - { - uint32_t delay_time; - pco_get_delay_time(priv->pco, &delay_time); - - if (priv->delay_timebase == TIMEBASE_INVALID) - read_timebase(priv); - - g_value_set_double(value, convert_timebase(priv->delay_timebase) * delay_time); - } - break; - - case PROP_HAS_DOUBLE_IMAGE_MODE: - g_value_set_boolean(value, pco_is_double_image_mode_available(priv->pco)); - break; - - case PROP_DOUBLE_IMAGE_MODE: - if (!pco_is_double_image_mode_available(priv->pco)) - g_warning("Double image mode is not available on this pco model"); - else { - bool on; - pco_get_double_image_mode(priv->pco, &on); - g_value_set_boolean(value, on); - } - break; - - case PROP_OFFSET_MODE: - { - bool on; - pco_get_offset_mode(priv->pco, &on); - g_value_set_boolean(value, on); - } - break; - - case PROP_HAS_STREAMING: - g_value_set_boolean(value, TRUE); - break; - - case PROP_HAS_CAMRAM_RECORDING: - g_value_set_boolean(value, priv->camera_description->has_camram); - break; - - case PROP_RECORD_MODE: - { - guint16 mode; - pco_get_record_mode(priv->pco, &mode); - - if (mode == RECORDER_SUBMODE_SEQUENCE) - g_value_set_enum(value, UCA_PCO_CAMERA_RECORD_MODE_SEQUENCE); - else if (mode == RECORDER_SUBMODE_RINGBUFFER) - g_value_set_enum(value, UCA_PCO_CAMERA_RECORD_MODE_RING_BUFFER); - else - g_warning("pco record mode not handled"); - } - break; - - case PROP_ACQUIRE_MODE: - { - guint16 mode; - pco_get_acquire_mode(priv->pco, &mode); - - if (mode == ACQUIRE_MODE_AUTO) - g_value_set_enum(value, UCA_PCO_CAMERA_ACQUIRE_MODE_AUTO); - else if (mode == ACQUIRE_MODE_EXTERNAL) - g_value_set_enum(value, UCA_PCO_CAMERA_ACQUIRE_MODE_EXTERNAL); - else - g_warning("pco acquire mode not handled"); - } - break; - - case PROP_TRIGGER_MODE: - { - guint16 mode; - pco_get_trigger_mode(priv->pco, &mode); - - switch (mode) { - case TRIGGER_MODE_AUTOTRIGGER: - g_value_set_enum(value, UCA_CAMERA_TRIGGER_AUTO); - break; - case TRIGGER_MODE_SOFTWARETRIGGER: - g_value_set_enum(value, UCA_CAMERA_TRIGGER_INTERNAL); - break; - case TRIGGER_MODE_EXTERNALTRIGGER: - g_value_set_enum(value, UCA_CAMERA_TRIGGER_EXTERNAL); - break; - default: - g_warning("pco trigger mode not handled"); - } - } - break; - - case PROP_ROI_X: - g_value_set_uint(value, priv->roi_x); - break; - - case PROP_ROI_Y: - g_value_set_uint(value, priv->roi_y); - break; - - case PROP_ROI_WIDTH: - g_value_set_uint(value, priv->roi_width); - break; - - case PROP_ROI_HEIGHT: - g_value_set_uint(value, priv->roi_height); - break; - - case PROP_ROI_WIDTH_MULTIPLIER: - g_value_set_uint(value, priv->roi_horizontal_steps); - break; - - case PROP_ROI_HEIGHT_MULTIPLIER: - g_value_set_uint(value, priv->roi_vertical_steps); - break; - - case PROP_NAME: - { - gchar *name = NULL; - pco_get_name(priv->pco, &name); - g_value_set_string(value, name); - g_free(name); - } - break; - - case PROP_COOLING_POINT: - { - int16_t temperature; - if (pco_get_cooling_temperature(priv->pco, &temperature) != PCO_NOERROR) - g_warning("Cannot read cooling temperature\n"); - g_value_set_int(value, temperature); - } - break; - - case PROP_COOLING_POINT_MIN: - { - GParamSpecInt *spec = (GParamSpecInt *) pco_properties[PROP_COOLING_POINT]; - g_value_set_int(value, spec->minimum); - } - break; - - case PROP_COOLING_POINT_MAX: - { - GParamSpecInt *spec = (GParamSpecInt *) pco_properties[PROP_COOLING_POINT]; - g_value_set_int(value, spec->maximum); - } - break; - - case PROP_COOLING_POINT_DEFAULT: - { - GParamSpecInt *spec = (GParamSpecInt *) pco_properties[PROP_COOLING_POINT]; - g_value_set_int(value, spec->default_value); - } - break; - - case PROP_NOISE_FILTER: - { - guint16 mode; - pco_get_noise_filter_mode(priv->pco, &mode); - g_value_set_boolean(value, mode != NOISE_FILTER_MODE_OFF); - } - break; - - case PROP_TIMESTAMP_MODE: - { - guint16 mode; - pco_get_timestamp_mode(priv->pco, &mode); - - switch (mode) { - case TIMESTAMP_MODE_OFF: - g_value_set_flags(value, UCA_PCO_CAMERA_TIMESTAMP_NONE); - break; - case TIMESTAMP_MODE_BINARY: - g_value_set_flags(value, UCA_PCO_CAMERA_TIMESTAMP_BINARY); - break; - case TIMESTAMP_MODE_BINARYANDASCII: - g_value_set_flags(value, - UCA_PCO_CAMERA_TIMESTAMP_BINARY | UCA_PCO_CAMERA_TIMESTAMP_ASCII); - break; - case TIMESTAMP_MODE_ASCII: - g_value_set_flags(value, UCA_PCO_CAMERA_TIMESTAMP_ASCII); - break; - } - } - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); - break; - } -} - -static void uca_pco_camera_finalize(GObject *object) -{ - UcaPcoCameraPrivate *priv = UCA_PCO_CAMERA_GET_PRIVATE(object); - - if (priv->horizontal_binnings) - g_value_array_free(priv->horizontal_binnings); - - if (priv->vertical_binnings) - g_value_array_free(priv->vertical_binnings); - - if (priv->pixelrates) - g_value_array_free(priv->pixelrates); - - if (priv->fg) { - if (priv->fg_mem) - Fg_FreeMemEx(priv->fg, priv->fg_mem); - - Fg_FreeGrabber(priv->fg); - } - - if (priv->pco) - pco_destroy(priv->pco); - - g_free(priv->grab_buffer); - - G_OBJECT_CLASS(uca_pco_camera_parent_class)->finalize(object); -} - -static void uca_pco_camera_class_init(UcaPcoCameraClass *klass) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS(klass); - gobject_class->set_property = uca_pco_camera_set_property; - 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->start_readout = uca_pco_camera_start_readout; - camera_class->trigger = uca_pco_camera_trigger; - camera_class->grab = uca_pco_camera_grab; - - for (guint i = 0; base_overrideables[i] != 0; i++) - g_object_class_override_property(gobject_class, base_overrideables[i], uca_camera_props[base_overrideables[i]]); - - /** - * UcaPcoCamera:sensor-extended: - * - * Activate larger sensor area that contains surrounding pixels for dark - * references and dummies. Use #UcaPcoCamera:sensor-width-extended and - * #UcaPcoCamera:sensor-height-extended to query the resolution of the - * larger area. - */ - pco_properties[PROP_SENSOR_EXTENDED] = - g_param_spec_boolean("sensor-extended", - "Use extended sensor format", - "Use extended sensor format", - FALSE, G_PARAM_READWRITE); - - pco_properties[PROP_SENSOR_WIDTH_EXTENDED] = - g_param_spec_uint("sensor-width-extended", - "Width of extended sensor", - "Width of the extended sensor in pixels", - 1, G_MAXUINT, 1, - G_PARAM_READABLE); - - pco_properties[PROP_SENSOR_HEIGHT_EXTENDED] = - g_param_spec_uint("sensor-height-extended", - "Height of extended sensor", - "Height of the extended sensor in pixels", - 1, G_MAXUINT, 1, - G_PARAM_READABLE); - - /** - * UcaPcoCamera:sensor-pixelrate: - * - * Read and write the pixel rate or clock of the sensor in terms of Hertz. - * Make sure to query the possible pixel rates through the - * #UcaPcoCamera:sensor-pixelrates property. Any other value will be - * rejected by the camera. - */ - pco_properties[PROP_SENSOR_PIXELRATE] = - g_param_spec_uint("sensor-pixelrate", - "Pixel rate", - "Pixel rate", - 1, G_MAXUINT, 1, - G_PARAM_READWRITE); - - pco_properties[PROP_SENSOR_PIXELRATES] = - g_param_spec_value_array("sensor-pixelrates", - "Array of possible sensor pixel rates", - "Array of possible sensor pixel rates", - pco_properties[PROP_SENSOR_PIXELRATE], - G_PARAM_READABLE); - - pco_properties[PROP_NAME] = - g_param_spec_string("name", - "Name of the camera", - "Name of the camera", - "", G_PARAM_READABLE); - - pco_properties[PROP_SENSOR_TEMPERATURE] = - g_param_spec_double("sensor-temperature", - "Temperature of the sensor", - "Temperature of the sensor in degree Celsius", - -G_MAXDOUBLE, G_MAXDOUBLE, 0.0, - G_PARAM_READABLE); - - pco_properties[PROP_HAS_DOUBLE_IMAGE_MODE] = - g_param_spec_boolean("has-double-image-mode", - "Is double image mode supported by this model", - "Is double image mode supported by this model", - FALSE, G_PARAM_READABLE); - - pco_properties[PROP_DOUBLE_IMAGE_MODE] = - g_param_spec_boolean("double-image-mode", - "Use double image mode", - "Use double image mode", - FALSE, G_PARAM_READWRITE); - - pco_properties[PROP_OFFSET_MODE] = - g_param_spec_boolean("offset-mode", - "Use offset mode", - "Use offset mode", - FALSE, G_PARAM_READWRITE); - - pco_properties[PROP_RECORD_MODE] = - g_param_spec_enum("record-mode", - "Record mode", - "Record mode", - UCA_TYPE_PCO_CAMERA_RECORD_MODE, UCA_PCO_CAMERA_RECORD_MODE_SEQUENCE, - G_PARAM_READWRITE); - - pco_properties[PROP_ACQUIRE_MODE] = - g_param_spec_enum("acquire-mode", - "Acquire mode", - "Acquire mode", - UCA_TYPE_PCO_CAMERA_ACQUIRE_MODE, UCA_PCO_CAMERA_ACQUIRE_MODE_AUTO, - G_PARAM_READWRITE); - - pco_properties[PROP_DELAY_TIME] = - g_param_spec_double("delay-time", - "Delay time", - "Delay before starting actual exposure", - 0.0, G_MAXDOUBLE, 0.0, - G_PARAM_READWRITE); - - pco_properties[PROP_NOISE_FILTER] = - g_param_spec_boolean("noise-filter", - "Noise filter", - "Noise filter", - FALSE, G_PARAM_READWRITE); - - /** - * UcaPcoCamera:cooling-point: - * - * The value range is set arbitrarily, because we are not yet connected to - * the camera and just don't know the cooling range. We override these - * values in #uca_pco_camera_new(). - */ - pco_properties[PROP_COOLING_POINT] = - g_param_spec_int("cooling-point", - "Cooling point of the camera", - "Cooling point of the camera in degree celsius", - 0, 10, 5, G_PARAM_READWRITE); - - pco_properties[PROP_COOLING_POINT_MIN] = - g_param_spec_int("cooling-point-min", - "Minimum cooling point", - "Minimum cooling point in degree celsius", - G_MININT, G_MAXINT, 0, G_PARAM_READABLE); - - pco_properties[PROP_COOLING_POINT_MAX] = - g_param_spec_int("cooling-point-max", - "Maximum cooling point", - "Maximum cooling point in degree celsius", - G_MININT, G_MAXINT, 0, G_PARAM_READABLE); - - pco_properties[PROP_COOLING_POINT_DEFAULT] = - g_param_spec_int("cooling-point-default", - "Default cooling point", - "Default cooling point in degree celsius", - G_MININT, G_MAXINT, 0, G_PARAM_READABLE); - - pco_properties[PROP_SENSOR_ADCS] = - g_param_spec_uint("sensor-adcs", - "Number of ADCs to use", - "Number of ADCs to use", - 1, 2, 1, - G_PARAM_READWRITE); - - pco_properties[PROP_SENSOR_MAX_ADCS] = - g_param_spec_uint("sensor-max-adcs", - "Maximum number of ADCs", - "Maximum number of ADCs that can be set with \"sensor-adcs\"", - 1, G_MAXUINT, 1, - G_PARAM_READABLE); - - pco_properties[PROP_TIMESTAMP_MODE] = - g_param_spec_flags("timestamp-mode", - "Timestamp mode", - "Timestamp mode", - UCA_TYPE_PCO_CAMERA_TIMESTAMP, UCA_PCO_CAMERA_TIMESTAMP_NONE, - G_PARAM_READWRITE); - - for (guint id = N_BASE_PROPERTIES; id < N_PROPERTIES; id++) - g_object_class_install_property(gobject_class, id, pco_properties[id]); - - g_type_class_add_private(klass, sizeof(UcaPcoCameraPrivate)); -} - -static void uca_pco_camera_init(UcaPcoCamera *self) -{ - self->priv = UCA_PCO_CAMERA_GET_PRIVATE(self); - self->priv->fg = NULL; - self->priv->fg_mem = NULL; - self->priv->pco = NULL; - self->priv->horizontal_binnings = NULL; - self->priv->vertical_binnings = NULL; - self->priv->pixelrates = NULL; - self->priv->camera_description = NULL; - self->priv->last_frame = 0; - self->priv->grab_buffer = NULL; - - self->priv->delay_timebase = TIMEBASE_INVALID; - self->priv->exposure_timebase = TIMEBASE_INVALID; -} - -G_MODULE_EXPORT UcaCamera * -uca_camera_impl_new (GError **error) -{ - pco_handle pco = pco_init(); - - if (pco == NULL) { - g_set_error(error, UCA_PCO_CAMERA_ERROR, UCA_PCO_CAMERA_ERROR_LIBPCO_INIT, - "Initializing libpco failed"); - return NULL; - } - - UcaPcoCamera *camera = g_object_new(UCA_TYPE_PCO_CAMERA, NULL); - UcaPcoCameraPrivate *priv = UCA_PCO_CAMERA_GET_PRIVATE(camera); - priv->pco = pco; - - pco_get_resolution(priv->pco, &priv->width, &priv->height, &priv->width_ex, &priv->height_ex); - pco_get_binning(priv->pco, &priv->binning_h, &priv->binning_v); - pco_set_storage_mode(pco, STORAGE_MODE_RECORDER); - pco_set_auto_transfer(pco, 1); - - guint16 roi[4]; - pco_get_roi(priv->pco, roi); - pco_get_roi_steps(priv->pco, &priv->roi_horizontal_steps, &priv->roi_vertical_steps); - - priv->roi_x = roi[0] - 1; - priv->roi_y = roi[1] - 1; - priv->roi_width = roi[2] - roi[0] + 1; - priv->roi_height = roi[3] - roi[1] + 1; - - guint16 camera_type, camera_subtype; - pco_get_camera_type(priv->pco, &camera_type, &camera_subtype); - pco_cl_map_entry *map_entry = get_pco_cl_map_entry(camera_type); - priv->camera_description = map_entry; - - if (map_entry == NULL) { - g_set_error(error, UCA_PCO_CAMERA_ERROR, UCA_PCO_CAMERA_ERROR_UNSUPPORTED, - "Camera type is not supported"); - g_object_unref(camera); - return NULL; - } - - priv->fg_port = PORT_A; - priv->fg = Fg_Init(map_entry->so_file, priv->fg_port); - - if (priv->fg == NULL) { - g_set_error(error, UCA_PCO_CAMERA_ERROR, UCA_PCO_CAMERA_ERROR_FG_INIT, - "%s", Fg_getLastErrorDescription(priv->fg)); - g_object_unref(camera); - return NULL; - } - - const guint32 fg_height = priv->height; - const guint32 fg_width = camera_type == CAMERATYPE_PCO_EDGE ? priv->width * 2 : priv->width; - - FG_TRY_PARAM(priv->fg, camera, FG_CAMERA_LINK_CAMTYP, &map_entry->cl_type, priv->fg_port); - FG_TRY_PARAM(priv->fg, camera, FG_FORMAT, &map_entry->cl_format, priv->fg_port); - FG_TRY_PARAM(priv->fg, camera, FG_WIDTH, &fg_width, priv->fg_port); - FG_TRY_PARAM(priv->fg, camera, FG_HEIGHT, &fg_height, priv->fg_port); - - int val = FREE_RUN; - FG_TRY_PARAM(priv->fg, camera, FG_TRIGGERMODE, &val, priv->fg_port); - - fill_binnings(priv); - - /* - * Here we override property ranges because we didn't know them at property - * installation time. - */ - GObjectClass *camera_class = G_OBJECT_CLASS (UCA_CAMERA_GET_CLASS (camera)); - property_override_default_guint_value (camera_class, "roi-width", priv->width); - property_override_default_guint_value (camera_class, "roi-height", priv->height); - - guint32 rates[4] = {0}; - gint num_rates = 0; - - if (pco_get_available_pixelrates(priv->pco, rates, &num_rates) == PCO_NOERROR) { - GObjectClass *pco_camera_class = G_OBJECT_CLASS (UCA_PCO_CAMERA_GET_CLASS (camera)); - - fill_pixelrates(priv, rates, num_rates); - property_override_default_guint_value (pco_camera_class, "sensor-pixelrate", rates[0]); - } - - override_temperature_range (priv); - override_maximum_adcs (priv); - - return UCA_CAMERA (camera); -} diff --git a/src/cameras/uca-pco-camera.h b/src/cameras/uca-pco-camera.h deleted file mode 100644 index 73ae44e..0000000 --- a/src/cameras/uca-pco-camera.h +++ /dev/null @@ -1,91 +0,0 @@ -/* Copyright (C) 2011, 2012 Matthias Vogelgesang - (Karlsruhe Institute of Technology) - - This library is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by the - Free Software Foundation; either version 2.1 of the License, or (at your - option) any later version. - - This library is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more - details. - - You should have received a copy of the GNU Lesser General Public License along - with this library; if not, write to the Free Software Foundation, Inc., 51 - Franklin St, Fifth Floor, Boston, MA 02110, USA */ - -#ifndef __UCA_PCO_CAMERA_H -#define __UCA_PCO_CAMERA_H - -#include -#include "uca-camera.h" - -G_BEGIN_DECLS - -#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)) -#define UCA_IS_PCO_CAMERA(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), UCA_TYPE_PCO_CAMERA)) -#define UCA_PCO_CAMERA_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), UCA_TYPE_PCO_CAMERA, UcaPcoCameraClass)) -#define UCA_IS_PCO_CAMERA_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), UCA_TYPE_PCO_CAMERA)) -#define UCA_PCO_CAMERA_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), UCA_TYPE_PCO_CAMERA, UcaPcoCameraClass)) - -#define UCA_PCO_CAMERA_ERROR uca_pco_camera_error_quark() -typedef enum { - UCA_PCO_CAMERA_ERROR_LIBPCO_INIT, - UCA_PCO_CAMERA_ERROR_LIBPCO_GENERAL, - UCA_PCO_CAMERA_ERROR_UNSUPPORTED, - UCA_PCO_CAMERA_ERROR_FG_INIT, - UCA_PCO_CAMERA_ERROR_FG_GENERAL, - UCA_PCO_CAMERA_ERROR_FG_ACQUISITION -} UcaPcoCameraError; - -typedef struct _UcaPcoCamera UcaPcoCamera; -typedef struct _UcaPcoCameraClass UcaPcoCameraClass; -typedef struct _UcaPcoCameraPrivate UcaPcoCameraPrivate; - -typedef enum { - UCA_PCO_CAMERA_RECORD_MODE_SEQUENCE, - UCA_PCO_CAMERA_RECORD_MODE_RING_BUFFER, -} UcaPcoCameraRecordMode; - -typedef enum { - UCA_PCO_CAMERA_ACQUIRE_MODE_AUTO, - UCA_PCO_CAMERA_ACQUIRE_MODE_EXTERNAL -} UcaPcoCameraAcquireMode; - -typedef enum { - UCA_PCO_CAMERA_TIMESTAMP_NONE = 0, - UCA_PCO_CAMERA_TIMESTAMP_BINARY = 1 << 0, - UCA_PCO_CAMERA_TIMESTAMP_ASCII = 1 << 1 -} UcaPcoCameraTimestamp; - -/** - * UcaPcoCamera: - * - * Creates #UcaPcoCamera instances by loading corresponding shared objects. The - * contents of the #UcaPcoCamera structure are private and should only be - * accessed via the provided API. - */ -struct _UcaPcoCamera { - /*< private >*/ - UcaCamera parent; - - UcaPcoCameraPrivate *priv; -}; - -/** - * UcaPcoCameraClass: - * - * #UcaPcoCamera class - */ -struct _UcaPcoCameraClass { - /*< private >*/ - UcaCameraClass parent; -}; - -GType uca_pco_camera_get_type(void); - -G_END_DECLS - -#endif diff --git a/src/cameras/uca-pf-camera.c b/src/cameras/uca-pf-camera.c deleted file mode 100644 index 35b5edd..0000000 --- a/src/cameras/uca-pf-camera.c +++ /dev/null @@ -1,351 +0,0 @@ -/* Copyright (C) 2011, 2012 Matthias Vogelgesang - (Karlsruhe Institute of Technology) - - This library is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by the - Free Software Foundation; either version 2.1 of the License, or (at your - option) any later version. - - This library is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more - details. - - You should have received a copy of the GNU Lesser General Public License along - with this library; if not, write to the Free Software Foundation, Inc., 51 - Franklin St, Fifth Floor, Boston, MA 02110, USA */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include "uca-camera.h" -#include "uca-pf-camera.h" - -#define FG_TRY_PARAM(fg, camobj, param, val_addr, port) \ - { int r = Fg_setParameter(fg, param, val_addr, port); \ - if (r != FG_OK) { \ - g_set_error(error, UCA_PF_CAMERA_ERROR, \ - UCA_PF_CAMERA_ERROR_FG_GENERAL, \ - "%s", Fg_getLastErrorDescription(fg)); \ - g_object_unref(camobj); \ - return NULL; \ - } } - -#define FG_SET_ERROR(err, fg, err_type) \ - if (err != FG_OK) { \ - g_set_error(error, UCA_PF_CAMERA_ERROR, \ - err_type, \ - "%s", Fg_getLastErrorDescription(fg)); \ - return; \ - } - -#define UCA_PF_CAMERA_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), UCA_TYPE_PF_CAMERA, UcaPfCameraPrivate)) - -G_DEFINE_TYPE(UcaPfCamera, uca_pf_camera, UCA_TYPE_CAMERA) - -/** - * UcaPfCameraError: - * @UCA_PF_CAMERA_ERROR_INIT: Initializing pcilib failed - * @UCA_PF_CAMERA_ERROR_FG_GENERAL: Frame grabber errors - * @UCA_PF_CAMERA_ERROR_FG_ACQUISITION: Acquisition errors related to the frame - * grabber - * @UCA_PF_CAMERA_ERROR_START_RECORDING: Starting failed - * @UCA_PF_CAMERA_ERROR_STOP_RECORDING: Stopping failed - */ -GQuark uca_pf_camera_error_quark() -{ - return g_quark_from_static_string("uca-pf-camera-error-quark"); -} - -static gint base_overrideables[] = { - PROP_NAME, - PROP_SENSOR_WIDTH, - PROP_SENSOR_HEIGHT, - PROP_SENSOR_BITDEPTH, - PROP_SENSOR_HORIZONTAL_BINNING, - PROP_SENSOR_HORIZONTAL_BINNINGS, - PROP_SENSOR_VERTICAL_BINNING, - PROP_SENSOR_VERTICAL_BINNINGS, - PROP_SENSOR_MAX_FRAME_RATE, - PROP_EXPOSURE_TIME, - PROP_ROI_X, - PROP_ROI_Y, - PROP_ROI_WIDTH, - PROP_ROI_HEIGHT, - PROP_ROI_WIDTH_MULTIPLIER, - PROP_ROI_HEIGHT_MULTIPLIER, - PROP_HAS_STREAMING, - PROP_HAS_CAMRAM_RECORDING, - 0 -}; - -enum { - PROP_FOO = N_BASE_PROPERTIES, - N_PROPERTIES -}; - - -struct _UcaPfCameraPrivate { - guint roi_width; - guint roi_height; - guint last_frame; - - Fg_Struct *fg; - guint fg_port; - dma_mem *fg_mem; -}; - -/* - * We just embed our private structure here. - */ -struct { - UcaCamera *camera; -} fg_apc_data; - -static int me4_callback(frameindex_t frame, struct fg_apc_data *apc) -{ - UcaCamera *camera = UCA_CAMERA(apc); - UcaPfCameraPrivate *priv = UCA_PF_CAMERA_GET_PRIVATE(camera); - camera->grab_func(Fg_getImagePtrEx(priv->fg, frame, priv->fg_port, priv->fg_mem), camera->user_data); - return 0; -} - -static void uca_pf_camera_start_recording(UcaCamera *camera, GError **error) -{ - g_return_if_fail(UCA_IS_PF_CAMERA(camera)); - UcaPfCameraPrivate *priv = UCA_PF_CAMERA_GET_PRIVATE(camera); - guint err = FG_OK; - - if (priv->fg_mem == NULL) { - const guint num_buffers = 2; - priv->fg_mem = Fg_AllocMemEx(priv->fg, num_buffers * priv->roi_width * priv->roi_height, num_buffers); - - if (priv->fg_mem == NULL) { - g_set_error(error, UCA_PF_CAMERA_ERROR, UCA_PF_CAMERA_ERROR_FG_ACQUISITION, - "%s", Fg_getLastErrorDescription(priv->fg)); - g_object_unref(camera); - return; - } - } - - gboolean transfer_async = FALSE; - g_object_get(G_OBJECT(camera), - "transfer-asynchronously", &transfer_async, - NULL); - - if (transfer_async) { - struct FgApcControl ctrl = { - .version = 0, - .data = (struct fg_apc_data *) camera, - .func = &me4_callback, - .flags = FG_APC_DEFAULTS, - .timeout = 1 - }; - - err = Fg_registerApcHandler(priv->fg, priv->fg_port, &ctrl, FG_APC_CONTROL_BASIC); - FG_SET_ERROR(err, priv->fg, UCA_PF_CAMERA_ERROR_FG_ACQUISITION); - } - - err = Fg_AcquireEx(priv->fg, priv->fg_port, GRAB_INFINITE, ACQ_STANDARD, priv->fg_mem); - FG_SET_ERROR(err, priv->fg, UCA_PF_CAMERA_ERROR_FG_ACQUISITION); -} - -static void uca_pf_camera_stop_recording(UcaCamera *camera, GError **error) -{ - g_return_if_fail(UCA_IS_PF_CAMERA(camera)); - UcaPfCameraPrivate *priv = UCA_PF_CAMERA_GET_PRIVATE(camera); - - guint err = Fg_stopAcquireEx(priv->fg, priv->fg_port, priv->fg_mem, STOP_SYNC); - FG_SET_ERROR(err, priv->fg, UCA_PF_CAMERA_ERROR_FG_ACQUISITION); - - err = Fg_setStatusEx(priv->fg, FG_UNBLOCK_ALL, 0, priv->fg_port, priv->fg_mem); - if (err == FG_INVALID_PARAMETER) - g_print(" Unable to unblock all\n"); -} - -static void uca_pf_camera_start_readout(UcaCamera *camera, GError **error) -{ - g_return_if_fail(UCA_IS_PF_CAMERA(camera)); - g_set_error(error, UCA_CAMERA_ERROR, UCA_CAMERA_ERROR_NOT_IMPLEMENTED, - "This photon focus camera does not support recording to internal memory"); -} - -static void uca_pf_camera_grab(UcaCamera *camera, gpointer *data, GError **error) -{ - g_return_if_fail(UCA_IS_PF_CAMERA(camera)); - UcaPfCameraPrivate *priv = UCA_PF_CAMERA_GET_PRIVATE(camera); - - priv->last_frame = Fg_getLastPicNumberBlockingEx(priv->fg, priv->last_frame+1, priv->fg_port, 5, priv->fg_mem); - - if (priv->last_frame <= 0) { - guint err = FG_OK + 1; - FG_SET_ERROR(err, priv->fg, UCA_PF_CAMERA_ERROR_FG_GENERAL); - } - - guint16 *frame = Fg_getImagePtrEx(priv->fg, priv->last_frame, priv->fg_port, priv->fg_mem); - - if (*data == NULL) - *data = g_malloc0(priv->roi_width * priv->roi_height); - - memcpy((gchar *) *data, (gchar *) frame, priv->roi_width * priv->roi_height); -} - -static void uca_pf_camera_set_property(GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) -{ - switch (property_id) { - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); - return; - } -} - -static void uca_pf_camera_get_property(GObject *object, guint property_id, GValue *value, GParamSpec *pspec) -{ - switch (property_id) { - case PROP_SENSOR_WIDTH: - g_value_set_uint(value, 1280); - break; - case PROP_SENSOR_HEIGHT: - g_value_set_uint(value, 1024); - break; - case PROP_SENSOR_BITDEPTH: - g_value_set_uint(value, 8); - break; - case PROP_SENSOR_HORIZONTAL_BINNING: - break; - case PROP_SENSOR_HORIZONTAL_BINNINGS: - break; - case PROP_SENSOR_VERTICAL_BINNING: - break; - case PROP_SENSOR_VERTICAL_BINNINGS: - break; - case PROP_SENSOR_MAX_FRAME_RATE: - g_value_set_float(value, 488.0); - break; - case PROP_HAS_STREAMING: - g_value_set_boolean(value, TRUE); - break; - case PROP_HAS_CAMRAM_RECORDING: - g_value_set_boolean(value, FALSE); - break; - case PROP_EXPOSURE_TIME: - break; - case PROP_ROI_X: - g_value_set_uint(value, 0); - break; - case PROP_ROI_Y: - g_value_set_uint(value, 0); - break; - case PROP_ROI_WIDTH: - g_value_set_uint(value, 1280); - break; - case PROP_ROI_HEIGHT: - g_value_set_uint(value, 1024); - break; - case PROP_ROI_WIDTH_MULTIPLIER: - g_value_set_uint(value, 1); - break; - case PROP_ROI_HEIGHT_MULTIPLIER: - g_value_set_uint(value, 1); - break; - case PROP_NAME: - g_value_set_string(value, "Photon Focus MV2-D1280-640-CL"); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); - break; - } -} - -static void uca_pf_camera_finalize(GObject *object) -{ - UcaPfCameraPrivate *priv = UCA_PF_CAMERA_GET_PRIVATE(object); - - if (priv->fg) { - if (priv->fg_mem) - Fg_FreeMemEx(priv->fg, priv->fg_mem); - - Fg_FreeGrabber(priv->fg); - } - - G_OBJECT_CLASS(uca_pf_camera_parent_class)->finalize(object); -} - -static void uca_pf_camera_class_init(UcaPfCameraClass *klass) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS(klass); - gobject_class->set_property = uca_pf_camera_set_property; - gobject_class->get_property = uca_pf_camera_get_property; - gobject_class->finalize = uca_pf_camera_finalize; - - UcaCameraClass *camera_class = UCA_CAMERA_CLASS(klass); - camera_class->start_recording = uca_pf_camera_start_recording; - camera_class->stop_recording = uca_pf_camera_stop_recording; - camera_class->start_readout = uca_pf_camera_start_readout; - camera_class->grab = uca_pf_camera_grab; - - for (guint i = 0; base_overrideables[i] != 0; i++) - g_object_class_override_property(gobject_class, base_overrideables[i], uca_camera_props[base_overrideables[i]]); - - g_type_class_add_private(klass, sizeof(UcaPfCameraPrivate)); -} - -static void uca_pf_camera_init(UcaPfCamera *self) -{ - self->priv = UCA_PF_CAMERA_GET_PRIVATE(self); - self->priv->fg = NULL; - self->priv->fg_mem = NULL; - self->priv->last_frame = 0; -} - -G_MODULE_EXPORT UcaCamera * -uca_camera_impl_new (GError **error) -{ - static const gchar *so_file = "libFullAreaGray8.so"; - static const int camera_link_type = FG_CL_8BIT_FULL_8; - static const int camera_format = FG_GRAY; - - /* - gint num_ports; - if (pfPortInit(&num_ports) < 0) { - g_set_error(error, UCA_PF_CAMERA_ERROR, UCA_PF_CAMERA_ERROR_INIT, - "Could not initialize ports"); - return NULL; - } - - if (pfDeviceOpen(0) < 0) { - g_set_error(error, UCA_PF_CAMERA_ERROR, UCA_PF_CAMERA_ERROR_INIT, - "Could not open device"); - return NULL; - } - */ - - UcaPfCamera *camera = g_object_new(UCA_TYPE_PF_CAMERA, NULL); - UcaPfCameraPrivate *priv = UCA_PF_CAMERA_GET_PRIVATE(camera); - - priv->fg_port = PORT_A; - priv->fg = Fg_Init(so_file, priv->fg_port); - - /* TODO: get this from the camera */ - priv->roi_width = 1280; - priv->roi_height = 1024; - - if (priv->fg == NULL) { - g_set_error(error, UCA_PF_CAMERA_ERROR, UCA_PF_CAMERA_ERROR_INIT, - "%s", Fg_getLastErrorDescription(priv->fg)); - g_object_unref(camera); - return NULL; - } - - FG_TRY_PARAM(priv->fg, camera, FG_CAMERA_LINK_CAMTYP, &camera_link_type, priv->fg_port); - FG_TRY_PARAM(priv->fg, camera, FG_FORMAT, &camera_format, priv->fg_port); - FG_TRY_PARAM(priv->fg, camera, FG_WIDTH, &priv->roi_width, priv->fg_port); - FG_TRY_PARAM(priv->fg, camera, FG_HEIGHT, &priv->roi_height, priv->fg_port); - - return UCA_CAMERA (camera); -} diff --git a/src/cameras/uca-pf-camera.h b/src/cameras/uca-pf-camera.h deleted file mode 100644 index 3a309aa..0000000 --- a/src/cameras/uca-pf-camera.h +++ /dev/null @@ -1,74 +0,0 @@ -/* Copyright (C) 2011, 2012 Matthias Vogelgesang - (Karlsruhe Institute of Technology) - - This library is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by the - Free Software Foundation; either version 2.1 of the License, or (at your - option) any later version. - - This library is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more - details. - - You should have received a copy of the GNU Lesser General Public License along - with this library; if not, write to the Free Software Foundation, Inc., 51 - Franklin St, Fifth Floor, Boston, MA 02110, USA */ - -#ifndef __UCA_PF_CAMERA_H -#define __UCA_PF_CAMERA_H - -#include -#include "uca-camera.h" - -G_BEGIN_DECLS - -#define UCA_TYPE_PF_CAMERA (uca_pf_camera_get_type()) -#define UCA_PF_CAMERA(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), UCA_TYPE_PF_CAMERA, UcaPfCamera)) -#define UCA_IS_PF_CAMERA(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), UCA_TYPE_PF_CAMERA)) -#define UCA_PF_CAMERA_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), UCA_TYPE_PF_CAMERA, UcaPfCameraClass)) -#define UCA_IS_PF_CAMERA_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), UCA_TYPE_PF_CAMERA)) -#define UCA_PF_CAMERA_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), UCA_TYPE_PF_CAMERA, UcaPfCameraClass)) - -#define UCA_PF_CAMERA_ERROR uca_pf_camera_error_quark() -typedef enum { - UCA_PF_CAMERA_ERROR_INIT, - UCA_PF_CAMERA_ERROR_FG_GENERAL, - UCA_PF_CAMERA_ERROR_FG_ACQUISITION, - UCA_PF_CAMERA_ERROR_START_RECORDING, - UCA_PF_CAMERA_ERROR_STOP_RECORDING -} UcaPfCameraError; - -typedef struct _UcaPfCamera UcaPfCamera; -typedef struct _UcaPfCameraClass UcaPfCameraClass; -typedef struct _UcaPfCameraPrivate UcaPfCameraPrivate; - -/** - * UcaPfCamera: - * - * Creates #UcaPfCamera instances by loading corresponding shared objects. The - * contents of the #UcaPfCamera structure are private and should only be - * accessed via the provided API. - */ -struct _UcaPfCamera { - /*< private >*/ - UcaCamera parent; - - UcaPfCameraPrivate *priv; -}; - -/** - * UcaPfCameraClass: - * - * #UcaPfCamera class - */ -struct _UcaPfCameraClass { - /*< private >*/ - UcaCameraClass parent; -}; - -GType uca_pf_camera_get_type(void); - -G_END_DECLS - -#endif diff --git a/src/cameras/uca-pylon-camera.c b/src/cameras/uca-pylon-camera.c deleted file mode 100644 index 541b69b..0000000 --- a/src/cameras/uca-pylon-camera.c +++ /dev/null @@ -1,391 +0,0 @@ -/* Copyright (C) 2012 Volker Kaiser - (Karlsruhe Institute of Technology) - - This library is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by the - Free Software Foundation; either version 2.1 of the License, or (at your - option) any later version. - - This library is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more - details. - - You should have received a copy of the GNU Lesser General Public License along - with this library; if not, write to the Free Software Foundation, Inc., 51 - Franklin St, Fifth Floor, Boston, MA 02110, USA */ - -#include -#include -#include -#include -#include "uca-camera.h" -#include "uca-pylon-camera.h" - -#define UCA_PYLON_CAMERA_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), UCA_TYPE_PYLON_CAMERA, UcaPylonCameraPrivate)) - -G_DEFINE_TYPE(UcaPylonCamera, uca_pylon_camera, UCA_TYPE_CAMERA) - -/** - * UcapylonCameraError: - * @UCA_PYLON_CAMERA_ERROR_LIBPYLON_INIT: Initializing libpylon failed - * @UCA_PYLON_CAMERA_ERROR_LIBPYLON_GENERAL: General libpylon error - * @UCA_PYLON_CAMERA_ERROR_UNSUPPORTED: Camera type is not supported - * @UCA_PYLON_CAMERA_ERROR_FG_INIT: Framegrabber initialization failed - * @UCA_PYLON_CAMERA_ERROR_FG_GENERAL: General framegrabber error - * @UCA_PYLON_CAMERA_ERROR_FG_ACQUISITION: Framegrabber acquisition error - */ -GQuark uca_pylon_camera_error_quark() -{ - return g_quark_from_static_string("uca-pylon-camera-error-quark"); -} - -enum { - PROP_ROI_WIDTH_DEFAULT = N_BASE_PROPERTIES, - PROP_ROI_HEIGHT_DEFAULT, - PROP_GAIN, - N_PROPERTIES -}; - -static gint base_overrideables[] = { - PROP_NAME, - PROP_SENSOR_WIDTH, - PROP_SENSOR_HEIGHT, - PROP_SENSOR_BITDEPTH, - PROP_SENSOR_HORIZONTAL_BINNING, - PROP_SENSOR_HORIZONTAL_BINNINGS, - PROP_SENSOR_VERTICAL_BINNING, - PROP_SENSOR_VERTICAL_BINNINGS, - PROP_SENSOR_MAX_FRAME_RATE, - PROP_TRIGGER_MODE, - PROP_EXPOSURE_TIME, - PROP_ROI_X, - PROP_ROI_Y, - PROP_ROI_WIDTH, - PROP_ROI_HEIGHT, - PROP_ROI_WIDTH_MULTIPLIER, - PROP_ROI_HEIGHT_MULTIPLIER, - PROP_HAS_STREAMING, - PROP_HAS_CAMRAM_RECORDING, - 0 -}; - -static GParamSpec *pylon_properties[N_PROPERTIES] = { NULL, }; - - -struct _UcaPylonCameraPrivate { - guint bit_depth; - gsize num_bytes; - - guint width; - guint height; - guint16 roi_x, roi_y; - guint16 roi_width, roi_height; - GValueArray *binnings; -}; - - -static void pylon_get_roi(GObject *object, GError** error) -{ - UcaPylonCameraPrivate *priv = UCA_PYLON_CAMERA_GET_PRIVATE(object); - pylon_camera_get_roi(&priv->roi_x, &priv->roi_y, &priv->roi_width, &priv->roi_height, error); -} - -static void pylon_set_roi(GObject *object, GError** error) -{ - UcaPylonCameraPrivate *priv = UCA_PYLON_CAMERA_GET_PRIVATE(object); - pylon_camera_set_roi(priv->roi_x, priv->roi_y, priv->roi_width, priv->roi_height, error); -} - -UcaPylonCamera *uca_pylon_camera_new(GError **error) -{ - UcaPylonCamera *camera = g_object_new(UCA_TYPE_PYLON_CAMERA, NULL); - UcaPylonCameraPrivate *priv = UCA_PYLON_CAMERA_GET_PRIVATE(camera); - - pylon_camera_new("/usr/local/lib64", "141.52.111.110", error); - - if (*error != NULL) - return NULL; - - pylon_camera_get_sensor_size(&priv->width, &priv->height, error); - - if (*error != NULL) - return NULL; - - return camera; -} - -static void uca_pylon_camera_start_recording(UcaCamera *camera, GError **error) -{ - g_return_if_fail(UCA_IS_PYLON_CAMERA(camera)); - UcaPylonCameraPrivate *priv = UCA_PYLON_CAMERA_GET_PRIVATE(camera); - - priv->num_bytes = 2; - pylon_camera_start_acquision(error); - -} - -static void uca_pylon_camera_stop_recording(UcaCamera *camera, GError **error) -{ - g_return_if_fail(UCA_IS_PYLON_CAMERA(camera)); - pylon_camera_stop_acquision(error); -} - -static void uca_pylon_camera_grab(UcaCamera *camera, gpointer *data, GError **error) -{ - g_return_if_fail(UCA_IS_PYLON_CAMERA(camera)); - UcaPylonCameraPrivate *priv = UCA_PYLON_CAMERA_GET_PRIVATE(camera); - - if (*data == NULL) { - *data = g_malloc0(priv->width * priv->height * priv->num_bytes); - } - pylon_camera_grab(data, error); -} - -static void uca_pylon_camera_set_property(GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) -{ - UcaPylonCameraPrivate *priv = UCA_PYLON_CAMERA_GET_PRIVATE(object); - GError* error = NULL; - - switch (property_id) { - case PROP_SENSOR_HORIZONTAL_BINNING: - /* intentional fall-through*/ - case PROP_SENSOR_VERTICAL_BINNING: - /* intentional fall-through*/ - case PROP_TRIGGER_MODE: - break; - - case PROP_ROI_X: - { - priv->roi_x = g_value_get_uint(value); - pylon_set_roi(object, &error); - } - break; - - case PROP_ROI_Y: - { - priv->roi_y = g_value_get_uint(value); - pylon_set_roi(object, &error); - } - break; - - case PROP_ROI_WIDTH: - { - priv->roi_width = g_value_get_uint(value); - pylon_set_roi(object, &error); - } - break; - - case PROP_ROI_HEIGHT: - { - priv->roi_height = g_value_get_uint(value); - pylon_set_roi(object, &error); - } - break; - - case PROP_EXPOSURE_TIME: - pylon_camera_set_exposure_time(g_value_get_double(value), &error); - break; - - case PROP_GAIN: - pylon_camera_set_gain(g_value_get_int(value), &error); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); - return; - } -} - -static void uca_pylon_camera_get_property(GObject *object, guint property_id, GValue *value, GParamSpec *pspec) -{ - UcaPylonCameraPrivate *priv = UCA_PYLON_CAMERA_GET_PRIVATE(object); - GError* error = NULL; - - switch (property_id) { - case PROP_SENSOR_WIDTH: - pylon_camera_get_sensor_size(&priv->width, &priv->height, &error); - g_value_set_uint(value, priv->width); - break; - - case PROP_SENSOR_HEIGHT: - pylon_camera_get_sensor_size(&priv->width, &priv->height, &error); - g_value_set_uint(value, priv->height); - break; - - case PROP_SENSOR_BITDEPTH: - pylon_camera_get_bit_depth(&priv->bit_depth, &error); - g_value_set_uint(value, priv->bit_depth); - break; - - case PROP_SENSOR_HORIZONTAL_BINNING: - g_value_set_uint(value, 1); - break; - - case PROP_SENSOR_HORIZONTAL_BINNINGS: - g_value_set_boxed(value, priv->binnings); - break; - - case PROP_SENSOR_VERTICAL_BINNING: - g_value_set_uint(value, 1); - break; - - case PROP_SENSOR_VERTICAL_BINNINGS: - g_value_set_boxed(value, priv->binnings); - break; - - case PROP_SENSOR_MAX_FRAME_RATE: - g_value_set_float(value, 0.0); - break; - - case PROP_TRIGGER_MODE: - g_value_set_enum(value, UCA_CAMERA_TRIGGER_AUTO); - break; - - case PROP_HAS_STREAMING: - g_value_set_boolean(value, FALSE); - break; - - case PROP_HAS_CAMRAM_RECORDING: - g_value_set_boolean(value, FALSE); - break; - - case PROP_ROI_X: - { - pylon_get_roi(object, &error); - g_value_set_uint(value, priv->roi_x); - } - break; - - case PROP_ROI_Y: - { - pylon_get_roi(object, &error); - g_value_set_uint(value, priv->roi_y); - } - break; - - case PROP_ROI_WIDTH: - { - pylon_get_roi(object, &error); - g_value_set_uint(value, priv->roi_width); - } - break; - - case PROP_ROI_HEIGHT: - { - pylon_get_roi(object, &error); - g_value_set_uint(value, priv->roi_height); - } - break; - - case PROP_ROI_WIDTH_DEFAULT: - pylon_camera_get_sensor_size(&priv->width, &priv->height, &error); - g_value_set_uint(value, priv->width); - break; - - case PROP_ROI_HEIGHT_DEFAULT: - pylon_camera_get_sensor_size(&priv->width, &priv->height, &error); - g_value_set_uint(value, priv->height); - break; - - case PROP_GAIN: - { - gint gain=0; - pylon_camera_get_gain(&gain, &error); - g_value_set_int(value, gain); - } - break; - - case PROP_ROI_WIDTH_MULTIPLIER: - g_value_set_uint(value, 1); - break; - - case PROP_ROI_HEIGHT_MULTIPLIER: - g_value_set_uint(value, 1); - break; - - case PROP_EXPOSURE_TIME: - { - gdouble exp_time = 0.0; - pylon_camera_get_exposure_time(&exp_time, &error); - g_value_set_double(value, exp_time); - } - break; - - case PROP_NAME: - g_value_set_string(value, "Pylon Camera"); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); - break; - } -} - -static void uca_pylon_camera_finalize(GObject *object) -{ - UcaPylonCameraPrivate *priv = UCA_PYLON_CAMERA_GET_PRIVATE(object); - g_value_array_free(priv->binnings); - - G_OBJECT_CLASS(uca_pylon_camera_parent_class)->finalize(object); -} - -static void uca_pylon_camera_class_init(UcaPylonCameraClass *klass) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS(klass); - gobject_class->set_property = uca_pylon_camera_set_property; - gobject_class->get_property = uca_pylon_camera_get_property; - gobject_class->finalize = uca_pylon_camera_finalize; - - UcaCameraClass *camera_class = UCA_CAMERA_CLASS(klass); - camera_class->start_recording = uca_pylon_camera_start_recording; - camera_class->stop_recording = uca_pylon_camera_stop_recording; - camera_class->grab = uca_pylon_camera_grab; - - for (guint i = 0; base_overrideables[i] != 0; i++) - g_object_class_override_property(gobject_class, base_overrideables[i], uca_camera_props[base_overrideables[i]]); - - pylon_properties[PROP_NAME] = - g_param_spec_string("name", - "Name of the camera", - "Name of the camera", - "", G_PARAM_READABLE); - - pylon_properties[PROP_ROI_WIDTH_DEFAULT] = - g_param_spec_uint("roi-width-default", - "ROI width default value", - "ROI width default value", - 0, G_MAXUINT, 0, - G_PARAM_READABLE); - - pylon_properties[PROP_ROI_HEIGHT_DEFAULT] = - g_param_spec_uint("roi-height-default", - "ROI height default value", - "ROI height default value", - 0, G_MAXUINT, 0, - G_PARAM_READABLE); - - pylon_properties[PROP_GAIN] = - g_param_spec_int("gain", - "gain", - "gain", - 0, G_MAXINT, 0, - G_PARAM_READWRITE); - - for (guint id = N_BASE_PROPERTIES; id < N_PROPERTIES; id++) - g_object_class_install_property(gobject_class, id, pylon_properties[id]); - - g_type_class_add_private(klass, sizeof(UcaPylonCameraPrivate)); -} - -static void uca_pylon_camera_init(UcaPylonCamera *self) -{ - self->priv = UCA_PYLON_CAMERA_GET_PRIVATE(self); - - /* binnings */ - GValue val = {0}; - g_value_init(&val, G_TYPE_UINT); - g_value_set_uint(&val, 1); - self->priv->binnings = g_value_array_new(1); - g_value_array_append(self->priv->binnings, &val); -} diff --git a/src/cameras/uca-pylon-camera.h b/src/cameras/uca-pylon-camera.h deleted file mode 100644 index eebf63c..0000000 --- a/src/cameras/uca-pylon-camera.h +++ /dev/null @@ -1,74 +0,0 @@ -/* Copyright (C) 2011, 2012 Matthias Vogelgesang - (Karlsruhe Institute of Technology) - - This library is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by the - Free Software Foundation; either version 2.1 of the License, or (at your - option) any later version. - - This library is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more - details. - - You should have received a copy of the GNU Lesser General Public License along - with this library; if not, write to the Free Software Foundation, Inc., 51 - Franklin St, Fifth Floor, Boston, MA 02110, USA */ - -#ifndef __UCA_PYLON_CAMERA_H -#define __UCA_PYLON_CAMERA_H - -#include -#include "uca-camera.h" - -G_BEGIN_DECLS - -#define UCA_TYPE_PYLON_CAMERA (uca_pylon_camera_get_type()) -#define UCA_PYLON_CAMERA(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), UCA_TYPE_PYLON_CAMERA, UcaPylonCamera)) -#define UCA_IS_PYLON_CAMERA(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), UCA_TYPE_PYLON_CAMERA)) -#define UCA_PYLON_CAMERA_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), UFO_TYPE_PYLON_CAMERA, UfoPylonCameraClass)) -#define UCA_IS_PYLON_CAMERA_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), UCA_TYPE_PYLON_CAMERA)) -#define UCA_PYLON_CAMERA_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), UCA_TYPE_PYLON_CAMERA, UcaPylonCameraClass)) - -#define UCA_PYLON_CAMERA_ERROR uca_pylon_camera_error_quark() -typedef enum { - UCA_PYLON_CAMERA_ERROR_LIBPYLON_INIT, - UCA_PYLON_CAMERA_ERROR_LIBPYLON_GENERAL, - UCA_PYLON_CAMERA_ERROR_UNSUPPORTED, -} UcaPylonCameraError; - -typedef struct _UcaPylonCamera UcaPylonCamera; -typedef struct _UcaPylonCameraClass UcaPylonCameraClass; -typedef struct _UcaPylonCameraPrivate UcaPylonCameraPrivate; - -/** - * UcaPylonCamera: - * - * Creates #UcaPylonCamera instances by loading corresponding shared objects. The - * contents of the #UcaPylonCamera structure are private and should only be - * accessed via the provided API. - */ -struct _UcaPylonCamera { - /*< private >*/ - UcaCamera parent; - - UcaPylonCameraPrivate *priv; -}; - -/** - * UcaPylonCameraClass: - * - * #UcaPylonCamera class - */ -struct _UcaPylonCameraClass { - /*< private >*/ - UcaCameraClass parent; -}; - -UcaPylonCamera *uca_pylon_camera_new(GError **error); - -GType uca_pylon_camera_get_type(void); - -G_END_DECLS - -#endif diff --git a/src/cameras/uca-ufo-camera.c b/src/cameras/uca-ufo-camera.c deleted file mode 100644 index 7542fdf..0000000 --- a/src/cameras/uca-ufo-camera.c +++ /dev/null @@ -1,497 +0,0 @@ -/* Copyright (C) 2011, 2012 Matthias Vogelgesang - (Karlsruhe Institute of Technology) - - This library is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by the - Free Software Foundation; either version 2.1 of the License, or (at your - option) any later version. - - This library is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more - details. - - You should have received a copy of the GNU Lesser General Public License along - with this library; if not, write to the Free Software Foundation, Inc., 51 - Franklin St, Fifth Floor, Boston, MA 02110, USA */ - -#include -#include -#include -#include -#include -#include -#include "uca-camera.h" -#include "uca-ufo-camera.h" - -#define PCILIB_SET_ERROR(err, err_type) \ - if (err != 0) { \ - g_set_error(error, UCA_UFO_CAMERA_ERROR, \ - err_type, \ - "pcilib: %s", strerror(err)); \ - return; \ - } - -#define UCA_UFO_CAMERA_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), UCA_TYPE_UFO_CAMERA, UcaUfoCameraPrivate)) - -G_DEFINE_TYPE(UcaUfoCamera, uca_ufo_camera, UCA_TYPE_CAMERA) - -static const guint SENSOR_WIDTH = 2048; -static const guint SENSOR_HEIGHT = 1088; -static const gdouble EXPOSURE_TIME_SCALE = 2.69e6; - -/** - * UcaUfoCameraError: - * @UCA_UFO_CAMERA_ERROR_INIT: Initializing pcilib failed - * @UCA_UFO_CAMERA_ERROR_START_RECORDING: Starting failed - * @UCA_UFO_CAMERA_ERROR_STOP_RECORDING: Stopping failed - * @UCA_UFO_CAMERA_ERROR_TRIGGER: Triggering a frame failed - * @UCA_UFO_CAMERA_ERROR_NEXT_EVENT: No event happened - * @UCA_UFO_CAMERA_ERROR_NO_DATA: No data was transmitted - * @UCA_UFO_CAMERA_ERROR_MAYBE_CORRUPTED: Data is potentially corrupted - */ -GQuark uca_ufo_camera_error_quark() -{ - return g_quark_from_static_string("uca-ufo-camera-error-quark"); -} - -enum { - PROP_SENSOR_TEMPERATURE = N_BASE_PROPERTIES, - PROP_FPGA_TEMPERATURE, - PROP_UFO_START, - N_MAX_PROPERTIES = 512 -}; - -static gint base_overrideables[] = { - PROP_NAME, - PROP_SENSOR_WIDTH, - PROP_SENSOR_HEIGHT, - PROP_SENSOR_HORIZONTAL_BINNING, - PROP_SENSOR_VERTICAL_BINNING, - PROP_SENSOR_MAX_FRAME_RATE, - PROP_SENSOR_BITDEPTH, - PROP_EXPOSURE_TIME, - PROP_ROI_X, - PROP_ROI_Y, - PROP_ROI_WIDTH, - PROP_ROI_HEIGHT, - PROP_ROI_WIDTH_MULTIPLIER, - PROP_ROI_HEIGHT_MULTIPLIER, - PROP_HAS_STREAMING, - PROP_HAS_CAMRAM_RECORDING, - PROP_TRIGGER_MODE, - 0, -}; - -typedef struct _RegisterInfo { - gchar *name; - guint cached_value; -} RegisterInfo; - -static GParamSpec *ufo_properties[N_MAX_PROPERTIES] = { NULL, }; - -static guint N_PROPERTIES; -static GHashTable *ufo_property_table; /* maps from prop_id to RegisterInfo* */ - -struct _UcaUfoCameraPrivate { - pcilib_t *handle; - pcilib_timeout_t timeout; - guint n_bits; - enum { - FPGA_48MHZ = 0, - FPGA_40MHZ - } frequency; -}; - -static void -error_handler (const char *format, ...) -{ - va_list args; - gchar *message; - - va_start (args, format); - message = g_strdup_vprintf (format, args); - g_warning ("%s", message); - va_end (args); -} - -static guint -read_register_value (pcilib_t *handle, const gchar *name) -{ - pcilib_register_value_t reg_value; - - pcilib_read_register(handle, NULL, name, ®_value); - return (guint) reg_value; -} - -static int event_callback(pcilib_event_id_t event_id, pcilib_event_info_t *info, void *user) -{ - UcaCamera *camera = UCA_CAMERA(user); - UcaUfoCameraPrivate *priv = UCA_UFO_CAMERA_GET_PRIVATE(camera); - size_t error = 0; - - void *buffer = pcilib_get_data(priv->handle, event_id, PCILIB_EVENT_DATA, &error); - - if (buffer == NULL) { - pcilib_trigger(priv->handle, PCILIB_EVENT0, 0, NULL); - return PCILIB_STREAMING_CONTINUE; - } - - camera->grab_func(buffer, camera->user_data); - pcilib_return_data(priv->handle, event_id, PCILIB_EVENT_DATA, buffer); - pcilib_trigger(priv->handle, PCILIB_EVENT0, 0, NULL); - - return PCILIB_STREAMING_CONTINUE; -} - -G_MODULE_EXPORT UcaCamera * -uca_camera_impl_new (GError **error) -{ - pcilib_model_t model = PCILIB_MODEL_DETECT; - pcilib_model_description_t *model_description; - pcilib_t *handle = pcilib_open("/dev/fpga0", model); - guint prop = PROP_UFO_START; - guint adc_resolution; - - if (handle == NULL) { - g_set_error(error, UCA_UFO_CAMERA_ERROR, UCA_UFO_CAMERA_ERROR_INIT, - "Initializing pcilib failed"); - return NULL; - } - - pcilib_set_error_handler(&error_handler, &error_handler); - - /* Generate properties from model description */ - model_description = pcilib_get_model_description(handle); - ufo_property_table = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_free); - - for (guint i = 0; model_description->registers[i].name != NULL; i++) { - GParamFlags flags = 0; - RegisterInfo *reg_info; - gchar *prop_name; - pcilib_register_description_t *reg; - pcilib_register_value_t value; - - reg = &model_description->registers[i]; - - switch (reg->mode) { - case PCILIB_REGISTER_R: - flags = G_PARAM_READABLE; - break; - case PCILIB_REGISTER_W: - case PCILIB_REGISTER_W1C: - flags = G_PARAM_WRITABLE; - break; - case PCILIB_REGISTER_RW: - case PCILIB_REGISTER_RW1C: - flags = G_PARAM_READWRITE; - break; - } - - pcilib_read_register (handle, NULL, reg->name, &value); - reg_info = g_new0 (RegisterInfo, 1); - reg_info->name = g_strdup (reg->name); - reg_info->cached_value = (guint32) value; - - g_hash_table_insert (ufo_property_table, GINT_TO_POINTER (prop), reg_info); - prop_name = g_strdup_printf ("ufo-%s", reg->name); - - ufo_properties[prop++] = g_param_spec_uint ( - prop_name, reg->description, reg->description, - 0, G_MAXUINT, reg->defvalue, flags); - - g_free (prop_name); - } - - N_PROPERTIES = prop; - - UcaUfoCamera *camera = g_object_new(UCA_TYPE_UFO_CAMERA, NULL); - UcaUfoCameraPrivate *priv = UCA_UFO_CAMERA_GET_PRIVATE(camera); - - priv->frequency = read_register_value (handle, "bit_mode"); - adc_resolution = read_register_value (handle, "adc_resolution"); - - switch (adc_resolution) { - case 0: - priv->n_bits = 10; - break; - case 1: - priv->n_bits = 11; - break; - case 2: - priv->n_bits = 12; - break; - } - - priv->handle = handle; - - return UCA_CAMERA (camera); -} - -static void uca_ufo_camera_start_recording(UcaCamera *camera, GError **error) -{ - UcaUfoCameraPrivate *priv; - gdouble exposure_time; - int err; - - g_return_if_fail(UCA_IS_UFO_CAMERA(camera)); - - priv = UCA_UFO_CAMERA_GET_PRIVATE(camera); - err = pcilib_start(priv->handle, PCILIB_EVENT_DATA, PCILIB_EVENT_FLAGS_DEFAULT); - PCILIB_SET_ERROR(err, UCA_UFO_CAMERA_ERROR_START_RECORDING); - - gboolean transfer_async = FALSE; - g_object_get(G_OBJECT(camera), - "transfer-asynchronously", &transfer_async, - "exposure-time", &exposure_time, - NULL); - - priv->timeout = ((pcilib_timeout_t) (exposure_time * 1000 + 50.0) * 1000); - - if (transfer_async) { - pcilib_trigger(priv->handle, PCILIB_EVENT0, 0, NULL); - pcilib_stream(priv->handle, &event_callback, camera); - } -} - -static void uca_ufo_camera_stop_recording(UcaCamera *camera, GError **error) -{ - g_return_if_fail(UCA_IS_UFO_CAMERA(camera)); - UcaUfoCameraPrivate *priv = UCA_UFO_CAMERA_GET_PRIVATE(camera); - int err = pcilib_stop(priv->handle, PCILIB_EVENT_FLAGS_DEFAULT); - PCILIB_SET_ERROR(err, UCA_UFO_CAMERA_ERROR_START_RECORDING); -} - -static void uca_ufo_camera_start_readout(UcaCamera *camera, GError **error) -{ - g_return_if_fail(UCA_IS_UFO_CAMERA(camera)); - g_set_error(error, UCA_CAMERA_ERROR, UCA_CAMERA_ERROR_NOT_IMPLEMENTED, - "Ufo camera does not support recording to internal memory"); -} - -static void uca_ufo_camera_grab(UcaCamera *camera, gpointer *data, GError **error) -{ - g_return_if_fail(UCA_IS_UFO_CAMERA(camera)); - UcaUfoCameraPrivate *priv = UCA_UFO_CAMERA_GET_PRIVATE(camera); - pcilib_event_id_t event_id; - pcilib_event_info_t event_info; - size_t err; - - const gsize size = SENSOR_WIDTH * SENSOR_HEIGHT * sizeof(guint16); - - err = pcilib_trigger(priv->handle, PCILIB_EVENT0, 0, NULL); - PCILIB_SET_ERROR(err, UCA_UFO_CAMERA_ERROR_TRIGGER); - - err = pcilib_get_next_event(priv->handle, priv->timeout, &event_id, sizeof(pcilib_event_info_t), &event_info); - PCILIB_SET_ERROR(err, UCA_UFO_CAMERA_ERROR_NEXT_EVENT); - - if (*data == NULL) - *data = g_malloc0(SENSOR_WIDTH * SENSOR_HEIGHT * sizeof(guint16)); - - gpointer src = pcilib_get_data(priv->handle, event_id, PCILIB_EVENT_DATA, &err); - - if (src == NULL) - PCILIB_SET_ERROR(err, UCA_UFO_CAMERA_ERROR_NO_DATA); - - /* - * Apparently, we checked that err equals total size in previous version. - * This is problematic because errno is positive and size could be equal - * even when an error condition is met, e.g. with a very small ROI. However, - * we don't know if src will always be NULL when an error occured. - */ - /* assert(err == size); */ - - memcpy(*data, src, size); - - /* - * Another problem here. What does this help us? At this point we have - * already overwritten the original buffer but can only know here if the - * data is corrupted. - */ - err = pcilib_return_data(priv->handle, event_id, PCILIB_EVENT_DATA, data); - PCILIB_SET_ERROR(err, UCA_UFO_CAMERA_ERROR_MAYBE_CORRUPTED); -} - -static void -uca_ufo_camera_set_property(GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) -{ - UcaUfoCameraPrivate *priv = UCA_UFO_CAMERA_GET_PRIVATE(object); - - switch (property_id) { - case PROP_EXPOSURE_TIME: - { - const guint frequency = priv->frequency == FPGA_40MHZ ? 40 : 48; - pcilib_register_value_t reg_value = (pcilib_register_value_t) 129 / frequency * 1000 * 1000 * g_value_get_double(value); - pcilib_write_register(priv->handle, NULL, "cmosis_exp_time", reg_value); - } - break; - case PROP_ROI_X: - case PROP_ROI_Y: - case PROP_ROI_WIDTH: - case PROP_ROI_HEIGHT: - g_debug("ROI feature not implemented yet"); - break; - - default: - { - RegisterInfo *reg_info = g_hash_table_lookup (ufo_property_table, GINT_TO_POINTER (property_id)); - - if (reg_info != NULL) { - pcilib_register_value_t reg_value; - - reg_value = g_value_get_uint (value); - pcilib_write_register(priv->handle, NULL, reg_info->name, reg_value); - pcilib_read_register (priv->handle, NULL, reg_info->name, ®_value); - reg_info->cached_value = (guint) reg_value; - } - else - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); - } - return; - } -} - - -static void -uca_ufo_camera_get_property(GObject *object, guint property_id, GValue *value, GParamSpec *pspec) -{ - UcaUfoCameraPrivate *priv = UCA_UFO_CAMERA_GET_PRIVATE(object); - - switch (property_id) { - case PROP_SENSOR_WIDTH: - g_value_set_uint(value, SENSOR_WIDTH); - break; - case PROP_SENSOR_HEIGHT: - g_value_set_uint(value, SENSOR_HEIGHT); - break; - case PROP_SENSOR_BITDEPTH: - g_value_set_uint (value, priv->n_bits); - break; - case PROP_SENSOR_HORIZONTAL_BINNING: - g_value_set_uint(value, 1); - break; - case PROP_SENSOR_VERTICAL_BINNING: - g_value_set_uint(value, 1); - break; - case PROP_SENSOR_MAX_FRAME_RATE: - g_value_set_float(value, 340.0); - break; - case PROP_SENSOR_TEMPERATURE: - { - const double a = priv->frequency == FPGA_48MHZ ? 0.3 : 0.25; - const double b = priv->frequency == FPGA_48MHZ ? 1000 : 1200; - guint32 temperature; - - temperature = read_register_value (priv->handle, "sensor_temperature"); - g_value_set_double (value, a * (temperature - b)); - } - break; - case PROP_FPGA_TEMPERATURE: - { - const double a = 503.975 / 1024.0; - const double b = 273.15; - guint32 temperature; - - temperature = read_register_value (priv->handle, "fpga_temperature"); - g_value_set_double (value, a * temperature - b); - } - break; - case PROP_EXPOSURE_TIME: - { - const gdouble frequency = priv->frequency == FPGA_40MHZ ? 40.0 : 48.0; - g_value_set_double (value, read_register_value (priv->handle, "cmosis_exp_time") * 129 / frequency / 1000 / 1000 ); - } - break; - case PROP_HAS_STREAMING: - g_value_set_boolean(value, TRUE); - break; - case PROP_HAS_CAMRAM_RECORDING: - g_value_set_boolean(value, FALSE); - break; - case PROP_ROI_X: - g_value_set_uint(value, 0); - break; - case PROP_ROI_Y: - g_value_set_uint(value, 0); - break; - case PROP_ROI_WIDTH: - g_value_set_uint(value, SENSOR_WIDTH); - break; - case PROP_ROI_HEIGHT: - g_value_set_uint(value, SENSOR_HEIGHT); - break; - case PROP_ROI_WIDTH_MULTIPLIER: - g_value_set_uint(value, 1); - break; - case PROP_ROI_HEIGHT_MULTIPLIER: - g_value_set_uint(value, 1); - break; - case PROP_NAME: - g_value_set_string(value, "Ufo Camera w/ CMOSIS CMV2000"); - break; - case PROP_TRIGGER_MODE: - break; - default: - { - RegisterInfo *reg_info = g_hash_table_lookup (ufo_property_table, GINT_TO_POINTER (property_id)); - - if (reg_info != NULL) - g_value_set_uint (value, reg_info->cached_value); - else - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); - } - break; - } -} - -static void uca_ufo_camera_finalize(GObject *object) -{ - UcaUfoCameraPrivate *priv = UCA_UFO_CAMERA_GET_PRIVATE(object); - pcilib_close(priv->handle); - G_OBJECT_CLASS(uca_ufo_camera_parent_class)->finalize(object); -} - -static void uca_ufo_camera_class_init(UcaUfoCameraClass *klass) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS(klass); - gobject_class->set_property = uca_ufo_camera_set_property; - gobject_class->get_property = uca_ufo_camera_get_property; - gobject_class->finalize = uca_ufo_camera_finalize; - - UcaCameraClass *camera_class = UCA_CAMERA_CLASS(klass); - camera_class->start_recording = uca_ufo_camera_start_recording; - camera_class->stop_recording = uca_ufo_camera_stop_recording; - camera_class->start_readout = uca_ufo_camera_start_readout; - camera_class->grab = uca_ufo_camera_grab; - - for (guint i = 0; base_overrideables[i] != 0; i++) - g_object_class_override_property(gobject_class, base_overrideables[i], uca_camera_props[base_overrideables[i]]); - - ufo_properties[PROP_SENSOR_TEMPERATURE] = - g_param_spec_double("sensor-temperature", - "Temperature of the sensor", - "Temperature of the sensor in degree Celsius", - -G_MAXDOUBLE, G_MAXDOUBLE, 0.0, - G_PARAM_READABLE); - - ufo_properties[PROP_FPGA_TEMPERATURE] = - g_param_spec_double("fpga-temperature", - "Temperature of the FPGA", - "Temperature of the FPGA in degree Celsius", - -G_MAXDOUBLE, G_MAXDOUBLE, 0.0, - G_PARAM_READABLE); - - /* - * This automatic property installation includes the properties created - * dynamically in uca_ufo_camera_new(). - */ - for (guint id = N_BASE_PROPERTIES; id < N_PROPERTIES; id++) - g_object_class_install_property(gobject_class, id, ufo_properties[id]); - - g_type_class_add_private(klass, sizeof(UcaUfoCameraPrivate)); -} - -static void uca_ufo_camera_init(UcaUfoCamera *self) -{ - self->priv = UCA_UFO_CAMERA_GET_PRIVATE(self); -} diff --git a/src/cameras/uca-ufo-camera.h b/src/cameras/uca-ufo-camera.h deleted file mode 100644 index 7030389..0000000 --- a/src/cameras/uca-ufo-camera.h +++ /dev/null @@ -1,76 +0,0 @@ -/* Copyright (C) 2011, 2012 Matthias Vogelgesang - (Karlsruhe Institute of Technology) - - This library is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by the - Free Software Foundation; either version 2.1 of the License, or (at your - option) any later version. - - This library is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more - details. - - You should have received a copy of the GNU Lesser General Public License along - with this library; if not, write to the Free Software Foundation, Inc., 51 - Franklin St, Fifth Floor, Boston, MA 02110, USA */ - -#ifndef __UCA_UFO_CAMERA_H -#define __UCA_UFO_CAMERA_H - -#include -#include "uca-camera.h" - -G_BEGIN_DECLS - -#define UCA_TYPE_UFO_CAMERA (uca_ufo_camera_get_type()) -#define UCA_UFO_CAMERA(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), UCA_TYPE_UFO_CAMERA, UcaUfoCamera)) -#define UCA_IS_UFO_CAMERA(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), UCA_TYPE_UFO_CAMERA)) -#define UCA_UFO_CAMERA_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), UCA_TYPE_UFO_CAMERA, UcaUfoCameraClass)) -#define UCA_IS_UFO_CAMERA_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), UCA_TYPE_UFO_CAMERA)) -#define UCA_UFO_CAMERA_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), UCA_TYPE_UFO_CAMERA, UcaUfoCameraClass)) - -#define UCA_UFO_CAMERA_ERROR uca_ufo_camera_error_quark() -typedef enum { - UCA_UFO_CAMERA_ERROR_INIT, - UCA_UFO_CAMERA_ERROR_START_RECORDING, - UCA_UFO_CAMERA_ERROR_STOP_RECORDING, - UCA_UFO_CAMERA_ERROR_TRIGGER, - UCA_UFO_CAMERA_ERROR_NEXT_EVENT, - UCA_UFO_CAMERA_ERROR_NO_DATA, - UCA_UFO_CAMERA_ERROR_MAYBE_CORRUPTED -} UcaUfoCameraError; - -typedef struct _UcaUfoCamera UcaUfoCamera; -typedef struct _UcaUfoCameraClass UcaUfoCameraClass; -typedef struct _UcaUfoCameraPrivate UcaUfoCameraPrivate; - -/** - * UcaUfoCamera: - * - * Creates #UcaUfoCamera instances by loading corresponding shared objects. The - * contents of the #UcaUfoCamera structure are private and should only be - * accessed via the provided API. - */ -struct _UcaUfoCamera { - /*< private >*/ - UcaCamera parent; - - UcaUfoCameraPrivate *priv; -}; - -/** - * UcaUfoCameraClass: - * - * #UcaUfoCamera class - */ -struct _UcaUfoCameraClass { - /*< private >*/ - UcaCameraClass parent; -}; - -GType uca_ufo_camera_get_type(void); - -G_END_DECLS - -#endif -- cgit v1.2.3 From d58bbe683873d043f50c8261f4588d7941e9cb8c Mon Sep 17 00:00:00 2001 From: Matthias Vogelgesang Date: Mon, 8 Oct 2012 10:43:42 +0200 Subject: Remove uca_camera_get_types from public API This functionality was moved to the plugin manager and could not be used anyway. --- src/uca-camera.h | 33 ++++++++++++++++++++------------- 1 file changed, 20 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/uca-camera.h b/src/uca-camera.h index 8924fa8..bd89bc6 100644 --- a/src/uca-camera.h +++ b/src/uca-camera.h @@ -110,24 +110,31 @@ struct _UcaCameraClass { GObjectClass parent; void (*start_recording) (UcaCamera *camera, GError **error); - void (*stop_recording) (UcaCamera *camera, GError **error); - void (*start_readout) (UcaCamera *camera, GError **error); - void (*trigger) (UcaCamera *camera, GError **error); - void (*grab) (UcaCamera *camera, gpointer *data, GError **error); + void (*stop_recording) (UcaCamera *camera, GError **error); + void (*start_readout) (UcaCamera *camera, GError **error); + void (*trigger) (UcaCamera *camera, GError **error); + void (*grab) (UcaCamera *camera, gpointer *data, GError **error); void (*recording_started) (UcaCamera *camera); void (*recording_stopped) (UcaCamera *camera); }; -gchar **uca_camera_get_types(); -UcaCamera *uca_camera_new(const gchar *type, GError **error); - -void uca_camera_start_recording(UcaCamera *camera, GError **error); -void uca_camera_stop_recording(UcaCamera *camera, GError **error); -void uca_camera_start_readout(UcaCamera *camera, GError **error); -void uca_camera_trigger(UcaCamera *camera, GError **error); -void uca_camera_grab(UcaCamera *camera, gpointer *data, GError **error); -void uca_camera_set_grab_func(UcaCamera *camera, UcaCameraGrabFunc func, gpointer user_data); +UcaCamera * uca_camera_new (const gchar *type, + GError **error); +void uca_camera_start_recording (UcaCamera *camera, + GError **error); +void uca_camera_stop_recording (UcaCamera *camera, + GError **error); +void uca_camera_start_readout (UcaCamera *camera, + GError **error); +void uca_camera_trigger (UcaCamera *camera, + GError **error); +void uca_camera_grab (UcaCamera *camera, + gpointer *data, + GError **error); +void uca_camera_set_grab_func (UcaCamera *camera, + UcaCameraGrabFunc func, + gpointer user_data); GType uca_camera_get_type(void); -- cgit v1.2.3 From b3dbedeec78a55802565a3824ab52188e8b9bd4d Mon Sep 17 00:00:00 2001 From: Matthias Vogelgesang Date: Mon, 8 Oct 2012 14:38:16 +0200 Subject: Generate introspection files Unfortunately, the gir tools recognize anything with $PREFIX_new_$SUFFIX as some kind of constructor. This means that we have to rename uca_plugin_manager_new_camera() to uca_plugin_manager_get_camera(). --- CMakeLists.txt | 1 + NEWS | 2 +- src/CMakeLists.txt | 57 ++++++++++++++++++++++++++++++++++++++++++++++++ src/uca-plugin-manager.c | 13 +++++------ src/uca-plugin-manager.h | 2 +- test/test-mock.c | 4 ++-- tools/benchmark.c | 2 +- tools/gen-doc.c | 2 +- tools/grab-async.c | 2 +- tools/grab.c | 2 +- tools/gui/control.c | 2 +- tools/perf-overhead.c | 2 +- 12 files changed, 74 insertions(+), 17 deletions(-) (limited to 'src') diff --git a/CMakeLists.txt b/CMakeLists.txt index bb53b40..bef3712 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -33,6 +33,7 @@ set(UCA_ENUM_HDRS ${CMAKE_CURRENT_SOURCE_DIR}/src/uca-camera.h ${CMAKE_CURRENT_SOURCE_DIR}/plugins/pco/uca-pco-camera.h) + # --- Common configuration --------------------------------------------------- configure_file(${CMAKE_CURRENT_SOURCE_DIR}/package.sh.in diff --git a/NEWS b/NEWS index e7c7243..624242b 100644 --- a/NEWS +++ b/NEWS @@ -13,7 +13,7 @@ looks in pre- and user-defined directories for DSOs that match UcaCamera *camera; manager = uca_plugin_manager_new (); - camera = uca_plugin_manager_new_camera (manager, "foo", &error); + camera = uca_plugin_manager_get_camera (manager, "foo", &error); The plugin manager adds a dependency on GModule (pkg-config package `gmodule-2.0`) that is part of GLib. diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 4bf5820..dd2f464 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -37,6 +37,9 @@ add_custom_command( # --- Configure --------------------------------------------------------------- +find_program(INTROSPECTION_SCANNER "g-ir-scanner") +find_program(INTROSPECTION_COMPILER "g-ir-compiler") + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config.h.in ${CMAKE_CURRENT_BINARY_DIR}/config.h) @@ -67,7 +70,51 @@ set_target_properties(uca PROPERTIES target_link_libraries(uca ${UCA_DEPS}) +# --- Build introspection files ----------------------------------------------- + +if (INTROSPECTION_SCANNER AND INTROSPECTION_COMPILER) + option(WITH_GIR "Build introspection files" ON) + + if (WITH_GIR) + set(GIR_PREFIX "Uca-${UCA_ABI_VERSION}") + set(GIR_XML "${GIR_PREFIX}.gir") + set(GIR_TYPELIB "${GIR_PREFIX}.typelib") + set(_gir_input) + + foreach(_src ${uca_SRCS} ${uca_HDRS}) + list(APPEND _gir_input "${CMAKE_CURRENT_SOURCE_DIR}/${_src}") + endforeach() + + add_custom_command(OUTPUT ${GIR_XML} + COMMAND ${INTROSPECTION_SCANNER} + --namespace=Uca + --nsversion=${UCA_ABI_VERSION} + --library=uca + --no-libtool + --include=GObject-2.0 + --include=GModule-2.0 + --output ${GIR_XML} + --warn-all + ${_gir_input} + DEPENDS ${uca_SRCS} + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) + + add_custom_command(OUTPUT ${GIR_TYPELIB} + COMMAND ${INTROSPECTION_COMPILER} + -o ${GIR_TYPELIB} + ${GIR_XML} + DEPENDS ${GIR_XML} + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) + + add_custom_target(gir ALL DEPENDS ${GIR_XML} ${GIR_TYPELIB}) + add_dependencies(gir uca) + + endif() +endif() + + # --- Build documentation ----------------------------------------------------- + pkg_check_modules(GTK_DOC gtk-doc) if(GTK_DOC_FOUND) @@ -170,6 +217,16 @@ install(FILES ${uca_HDRS} DESTINATION include/uca COMPONENT headers) +if(WITH_GIR) + install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${GIR_XML} + DESTINATION share/gir-1.0 + COMPONENT libraries) + + install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${GIR_TYPELIB} + DESTINATION ${LIB_INSTALL_DIR}/girepository-1.0 + COMPONENT libraries) +endif() + # --- Generate package description -------------------------------------------- diff --git a/src/uca-plugin-manager.c b/src/uca-plugin-manager.c index 5678e83..cb7e518 100644 --- a/src/uca-plugin-manager.c +++ b/src/uca-plugin-manager.c @@ -49,9 +49,7 @@ uca_plugin_manager_error_quark (void) * uca_plugin_manager_new: * @config: (allow-none): A #UcaConfiguration object or %NULL. * - * Create a plugin manager object to instantiate filter objects. When a config - * object is passed to the constructor, its search-path property is added to the - * internal search paths. + * Create a plugin manager object to instantiate camera objects. * * Return value: A new plugin manager object. */ @@ -147,9 +145,10 @@ list_free_full (GList *list) * * @manager: A #UcaPluginManager * - * Return: A list with strings of available camera names. You have to free the - * individual strings with g_list_foreach(list, (GFunc) g_free, NULL) and the - * list itself with g_list_free. + * Returns: (element-type utf8) (transfer full): A list with strings of + * available camera names. You have to free the individual strings with + * g_list_foreach(list, (GFunc) g_free, NULL) and the list itself with + * g_list_free. */ GList * uca_plugin_manager_get_available_cameras (UcaPluginManager *manager) @@ -201,7 +200,7 @@ find_camera_module_path (GList *search_paths, const gchar *name) * @error: Location for a #GError */ UcaCamera * -uca_plugin_manager_new_camera (UcaPluginManager *manager, +uca_plugin_manager_get_camera (UcaPluginManager *manager, const gchar *name, GError **error) { diff --git a/src/uca-plugin-manager.h b/src/uca-plugin-manager.h index 9291857..6c3ab4e 100644 --- a/src/uca-plugin-manager.h +++ b/src/uca-plugin-manager.h @@ -55,7 +55,7 @@ void uca_plugin_manager_add_path (UcaPluginManager *manager const gchar *path); GList *uca_plugin_manager_get_available_cameras (UcaPluginManager *manager); -UcaCamera *uca_plugin_manager_new_camera (UcaPluginManager *manager, +UcaCamera *uca_plugin_manager_get_camera (UcaPluginManager *manager, const gchar *name, GError **error); GType uca_plugin_manager_get_type (void); diff --git a/test/test-mock.c b/test/test-mock.c index ca16c59..711364d 100644 --- a/test/test-mock.c +++ b/test/test-mock.c @@ -16,7 +16,7 @@ fixture_setup (Fixture *fixture, gconstpointer data) fixture->manager = uca_plugin_manager_new (); uca_plugin_manager_add_path (fixture->manager, "./src"); - fixture->camera = uca_plugin_manager_new_camera (fixture->manager, "mock", &error); + fixture->camera = uca_plugin_manager_get_camera (fixture->manager, "mock", &error); g_assert (error == NULL); g_assert (fixture->camera); } @@ -39,7 +39,7 @@ static void test_factory (Fixture *fixture, gconstpointer data) { GError *error = NULL; - UcaCamera *camera = uca_plugin_manager_new_camera (fixture->manager, "fox994m3a0yxmy", &error); + UcaCamera *camera = uca_plugin_manager_get_camera (fixture->manager, "fox994m3a0yxmy", &error); g_assert_error (error, UCA_PLUGIN_MANAGER_ERROR, UCA_PLUGIN_MANAGER_ERROR_MODULE_NOT_FOUND); g_assert (camera == NULL); } diff --git a/tools/benchmark.c b/tools/benchmark.c index ef99fd1..bff8b50 100644 --- a/tools/benchmark.c +++ b/tools/benchmark.c @@ -250,7 +250,7 @@ main (int argc, char *argv[]) g_log_set_handler (NULL, G_LOG_LEVEL_MASK, log_handler, log_channel); manager = uca_plugin_manager_new (); - camera = uca_plugin_manager_new_camera (manager, argv[1], &error); + camera = uca_plugin_manager_get_camera (manager, argv[1], &error); if (camera == NULL) { g_error ("Initialization: %s", error->message); diff --git a/tools/gen-doc.c b/tools/gen-doc.c index 86d6ff9..f555a5f 100644 --- a/tools/gen-doc.c +++ b/tools/gen-doc.c @@ -136,7 +136,7 @@ int main(int argc, char *argv[]) } else { name = argv[1]; - camera = uca_plugin_manager_new_camera (manager, name, &error); + camera = uca_plugin_manager_get_camera (manager, name, &error); } if (camera == NULL) { diff --git a/tools/grab-async.c b/tools/grab-async.c index 6132829..2c4bf04 100644 --- a/tools/grab-async.c +++ b/tools/grab-async.c @@ -94,7 +94,7 @@ main(int argc, char *argv[]) } manager = uca_plugin_manager_new (); - camera = uca_plugin_manager_new_camera (manager, argv[1], &error); + camera = uca_plugin_manager_get_camera (manager, argv[1], &error); if (camera == NULL) { g_print("Error during initialization: %s\n", error->message); diff --git a/tools/grab.c b/tools/grab.c index 1f5c917..1518997 100644 --- a/tools/grab.c +++ b/tools/grab.c @@ -75,7 +75,7 @@ int main(int argc, char *argv[]) } manager = uca_plugin_manager_new (); - camera = uca_plugin_manager_new_camera (manager, argv[1], &error); + camera = uca_plugin_manager_get_camera (manager, argv[1], &error); if (camera == NULL) { g_print("Error during initialization: %s\n", error->message); diff --git a/tools/gui/control.c b/tools/gui/control.c index 75b3cde..178c809 100644 --- a/tools/gui/control.c +++ b/tools/gui/control.c @@ -207,7 +207,7 @@ create_main_window (GtkBuilder *builder, const gchar* camera_name) static ThreadData td; GError *error = NULL; - UcaCamera *camera = uca_plugin_manager_new_camera (plugin_manager, camera_name, &error); + UcaCamera *camera = uca_plugin_manager_get_camera (plugin_manager, camera_name, &error); if ((camera == NULL) || (error != NULL)) { g_error ("%s\n", error->message); diff --git a/tools/perf-overhead.c b/tools/perf-overhead.c index f8bdcbd..6735e6f 100644 --- a/tools/perf-overhead.c +++ b/tools/perf-overhead.c @@ -163,7 +163,7 @@ main (int argc, char *argv[]) } manager = uca_plugin_manager_new (); - camera = uca_plugin_manager_new_camera (manager, argv[1], &error); + camera = uca_plugin_manager_get_camera (manager, argv[1], &error); if (camera == NULL) { g_print ("Error during initialization: %s\n", error->message); -- cgit v1.2.3 From 4a27a2e95aa1a2312ad17404d7ab236b2fa6f1b7 Mon Sep 17 00:00:00 2001 From: Matthias Vogelgesang Date: Tue, 9 Oct 2012 15:43:10 +0200 Subject: Fix #150: Add "frames-per-second" property Right now, there is only information for the DIMAX camera about the actual inherent system delay. For all other cameras fps = 1. / t_exp. --- plugins/pco/uca-pco-camera.c | 111 +++++++++++++++++++++++++++++++++++-------- src/uca-camera.c | 26 ++++++++++ src/uca-camera.h | 1 + test/test-mock.c | 21 ++++++++ 4 files changed, 139 insertions(+), 20 deletions(-) (limited to 'src') diff --git a/plugins/pco/uca-pco-camera.c b/plugins/pco/uca-pco-camera.c index ccccf82..893a480 100644 --- a/plugins/pco/uca-pco-camera.c +++ b/plugins/pco/uca-pco-camera.c @@ -129,6 +129,7 @@ static gint base_overrideables[] = { PROP_SENSOR_VERTICAL_BINNINGS, PROP_SENSOR_MAX_FRAME_RATE, PROP_EXPOSURE_TIME, + PROP_FRAMES_PER_SECOND, PROP_TRIGGER_MODE, PROP_ROI_X, PROP_ROI_Y, @@ -208,7 +209,8 @@ static pco_cl_map_entry *get_pco_cl_map_entry(int camera_type) return NULL; } -static guint fill_binnings(UcaPcoCameraPrivate *priv) +static guint +fill_binnings(UcaPcoCameraPrivate *priv) { uint16_t *horizontal = NULL; uint16_t *vertical = NULL; @@ -241,7 +243,8 @@ static guint fill_binnings(UcaPcoCameraPrivate *priv) return err; } -static void fill_pixelrates(UcaPcoCameraPrivate *priv, guint32 rates[4], gint num_rates) +static void +fill_pixelrates(UcaPcoCameraPrivate *priv, guint32 rates[4], gint num_rates) { GValue val = {0}; g_value_init(&val, G_TYPE_UINT); @@ -253,7 +256,8 @@ static void fill_pixelrates(UcaPcoCameraPrivate *priv, guint32 rates[4], gint nu } } -static guint override_temperature_range(UcaPcoCameraPrivate *priv) +static guint +override_temperature_range(UcaPcoCameraPrivate *priv) { int16_t default_temp, min_temp, max_temp; guint err = pco_get_cooling_range(priv->pco, &default_temp, &min_temp, &max_temp); @@ -270,7 +274,8 @@ static guint override_temperature_range(UcaPcoCameraPrivate *priv) return err; } -static void property_override_default_guint_value (GObjectClass *oclass, const gchar *property_name, guint new_default) +static void +property_override_default_guint_value (GObjectClass *oclass, const gchar *property_name, guint new_default) { GParamSpecUInt *pspec = G_PARAM_SPEC_UINT (g_object_class_find_property (oclass, property_name)); @@ -280,13 +285,15 @@ static void property_override_default_guint_value (GObjectClass *oclass, const g g_warning ("pspec for %s not found\n", property_name); } -static void override_maximum_adcs(UcaPcoCameraPrivate *priv) +static void +override_maximum_adcs(UcaPcoCameraPrivate *priv) { GParamSpecInt *spec = (GParamSpecInt *) pco_properties[PROP_SENSOR_ADCS]; spec->maximum = pco_get_maximum_number_of_adcs(priv->pco); } -static gdouble convert_timebase(guint16 timebase) +static gdouble +convert_timebase(guint16 timebase) { switch (timebase) { case TIMEBASE_NS: @@ -301,12 +308,14 @@ static gdouble convert_timebase(guint16 timebase) return 1e-3; } -static void read_timebase(UcaPcoCameraPrivate *priv) +static void +read_timebase(UcaPcoCameraPrivate *priv) { pco_get_timebase(priv->pco, &priv->delay_timebase, &priv->exposure_timebase); } -static gdouble get_suitable_timebase(gdouble time) +static gdouble +get_suitable_timebase(gdouble time) { if (time * 1e3 >= 1.0) return TIMEBASE_MS; @@ -317,7 +326,24 @@ static gdouble get_suitable_timebase(gdouble time) return TIMEBASE_INVALID; } -static int fg_callback(frameindex_t frame, struct fg_apc_data *apc) +static gdouble +get_internal_delay (UcaPcoCamera *camera) +{ + if (camera->priv->camera_description->camera_type == CAMERATYPE_PCO_DIMAX_STD) { + gdouble sensor_rate; + g_object_get (camera, "sensor-rate", &sensor_rate, NULL); + + if (sensor_rate == 55000000.0) + return 0.000079; + else if (sensor_rate == 62500000.0) + return 0.000069; + } + + return 0.0; +} + +static int +fg_callback(frameindex_t frame, struct fg_apc_data *apc) { UcaCamera *camera = UCA_CAMERA(apc); UcaPcoCameraPrivate *priv = UCA_PCO_CAMERA_GET_PRIVATE(camera); @@ -333,7 +359,8 @@ static int fg_callback(frameindex_t frame, struct fg_apc_data *apc) return 0; } -static gboolean setup_fg_callback(UcaCamera *camera) +static gboolean +setup_fg_callback(UcaCamera *camera) { UcaPcoCameraPrivate *priv = UCA_PCO_CAMERA_GET_PRIVATE(camera); struct FgApcControl ctrl; @@ -353,7 +380,8 @@ static gboolean setup_fg_callback(UcaCamera *camera) return Fg_registerApcHandler(priv->fg, priv->fg_port, &ctrl, FG_APC_CONTROL_BASIC) == FG_OK; } -static void uca_pco_camera_start_recording(UcaCamera *camera, GError **error) +static void +uca_pco_camera_start_recording(UcaCamera *camera, GError **error) { g_return_if_fail(UCA_IS_PCO_CAMERA(camera)); guint err = PCO_NOERROR; @@ -451,7 +479,8 @@ static void uca_pco_camera_start_recording(UcaCamera *camera, GError **error) FG_SET_ERROR(err, priv->fg, UCA_PCO_CAMERA_ERROR_FG_ACQUISITION); } -static void uca_pco_camera_stop_recording(UcaCamera *camera, GError **error) +static void +uca_pco_camera_stop_recording(UcaCamera *camera, GError **error) { g_return_if_fail(UCA_IS_PCO_CAMERA(camera)); UcaPcoCameraPrivate *priv = UCA_PCO_CAMERA_GET_PRIVATE(camera); @@ -467,7 +496,8 @@ static void uca_pco_camera_stop_recording(UcaCamera *camera, GError **error) g_warning(" Unable to unblock all\n"); } -static void uca_pco_camera_start_readout(UcaCamera *camera, GError **error) +static void +uca_pco_camera_start_readout(UcaCamera *camera, GError **error) { g_return_if_fail(UCA_IS_PCO_CAMERA(camera)); UcaPcoCameraPrivate *priv = UCA_PCO_CAMERA_GET_PRIVATE(camera); @@ -486,7 +516,8 @@ static void uca_pco_camera_start_readout(UcaCamera *camera, GError **error) priv->current_image = 1; } -static void uca_pco_camera_trigger(UcaCamera *camera, GError **error) +static void +uca_pco_camera_trigger(UcaCamera *camera, GError **error) { g_return_if_fail(UCA_IS_PCO_CAMERA(camera)); UcaPcoCameraPrivate *priv = UCA_PCO_CAMERA_GET_PRIVATE(camera); @@ -500,7 +531,8 @@ static void uca_pco_camera_trigger(UcaCamera *camera, GError **error) "Could not trigger frame acquisition"); } -static void uca_pco_camera_grab(UcaCamera *camera, gpointer *data, GError **error) +static void +uca_pco_camera_grab(UcaCamera *camera, gpointer *data, GError **error) { static const gint MAX_TIMEOUT = G_MAXINT; @@ -543,7 +575,8 @@ static void uca_pco_camera_grab(UcaCamera *camera, gpointer *data, GError **erro memcpy((gchar *) *data, (gchar *) frame, priv->frame_width * priv->frame_height * priv->num_bytes); } -static void uca_pco_camera_set_property(GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) +static void +uca_pco_camera_set_property(GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { UcaPcoCameraPrivate *priv = UCA_PCO_CAMERA_GET_PRIVATE(object); @@ -624,6 +657,29 @@ static void uca_pco_camera_set_property(GObject *object, guint property_id, cons } break; + case PROP_FRAMES_PER_SECOND: + { + gdouble n_frames_per_second; + gdouble exposure_time; + gdouble delay; + + /* + * We want to expose n frames in one second, each frame takes + * exposure time + delay time. Thus we have + * + * 1s = n * (t_exp + t_delay) <=> t_exp = 1s/n - t_delay. + */ + delay = get_internal_delay (UCA_PCO_CAMERA (object)); + n_frames_per_second = g_value_get_double (value); + exposure_time = 1.0 / n_frames_per_second - delay; + + if (exposure_time <= 0.0) + g_warning ("Too many frames per second requested."); + else + g_object_set (object, "exposure-time", exposure_time, NULL); + } + break; + case PROP_DELAY_TIME: { const gdouble time = g_value_get_double(value); @@ -787,7 +843,8 @@ static void uca_pco_camera_set_property(GObject *object, guint property_id, cons } } -static void uca_pco_camera_get_property(GObject *object, guint property_id, GValue *value, GParamSpec *pspec) +static void +uca_pco_camera_get_property(GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { UcaPcoCameraPrivate *priv = UCA_PCO_CAMERA_GET_PRIVATE(object); @@ -892,6 +949,17 @@ static void uca_pco_camera_get_property(GObject *object, guint property_id, GVal } break; + case PROP_FRAMES_PER_SECOND: + { + gdouble exposure_time; + gdouble delay; + + delay = get_internal_delay (UCA_PCO_CAMERA (object)); + g_object_get (object, "exposure-time", &exposure_time, NULL); + g_value_set_double (value, 1.0 / (exposure_time + delay)); + } + break; + case PROP_DELAY_TIME: { uint32_t delay_time; @@ -1075,7 +1143,8 @@ static void uca_pco_camera_get_property(GObject *object, guint property_id, GVal } } -static void uca_pco_camera_finalize(GObject *object) +static void +uca_pco_camera_finalize(GObject *object) { UcaPcoCameraPrivate *priv = UCA_PCO_CAMERA_GET_PRIVATE(object); @@ -1103,7 +1172,8 @@ static void uca_pco_camera_finalize(GObject *object) G_OBJECT_CLASS(uca_pco_camera_parent_class)->finalize(object); } -static void uca_pco_camera_class_init(UcaPcoCameraClass *klass) +static void +uca_pco_camera_class_init(UcaPcoCameraClass *klass) { GObjectClass *gobject_class = G_OBJECT_CLASS(klass); gobject_class->set_property = uca_pco_camera_set_property; @@ -1286,7 +1356,8 @@ static void uca_pco_camera_class_init(UcaPcoCameraClass *klass) g_type_class_add_private(klass, sizeof(UcaPcoCameraPrivate)); } -static void uca_pco_camera_init(UcaPcoCamera *self) +static void +uca_pco_camera_init(UcaPcoCamera *self) { self->priv = UCA_PCO_CAMERA_GET_PRIVATE(self); self->priv->fg = NULL; diff --git a/src/uca-camera.c b/src/uca-camera.c index f973355..14da820 100644 --- a/src/uca-camera.c +++ b/src/uca-camera.c @@ -66,6 +66,7 @@ const gchar *uca_camera_props[N_BASE_PROPERTIES] = { "sensor-max-frame-rate", "trigger-mode", "exposure-time", + "frames-per-second", "roi-x0", "roi-y0", "roi-width", @@ -102,6 +103,15 @@ uca_camera_set_property (GObject *object, guint property_id, const GValue *value priv->transfer_async = g_value_get_boolean(value); break; + case PROP_FRAMES_PER_SECOND: + { + gdouble frames_per_second; + + frames_per_second = g_value_get_double (value); + g_object_set (object, "exposure-time", 1. / frames_per_second, NULL); + } + break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); } @@ -125,6 +135,15 @@ uca_camera_get_property(GObject *object, guint property_id, GValue *value, GPara g_value_set_boolean(value, priv->transfer_async); break; + case PROP_FRAMES_PER_SECOND: + { + gdouble exposure_time; + + g_object_get (object, "exposure-time", &exposure_time, NULL); + g_value_set_double (value, 1. / exposure_time); + } + break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); } @@ -267,6 +286,13 @@ uca_camera_class_init(UcaCameraClass *klass) 0.0, G_MAXDOUBLE, 1.0, G_PARAM_READWRITE); + camera_properties[PROP_FRAMES_PER_SECOND] = + g_param_spec_double(uca_camera_props[PROP_FRAMES_PER_SECOND], + "Frames per second", + "Frames per second", + 0.0, G_MAXDOUBLE, 1.0, + G_PARAM_READWRITE); + camera_properties[PROP_HAS_STREAMING] = g_param_spec_boolean(uca_camera_props[PROP_HAS_STREAMING], "Streaming capability", diff --git a/src/uca-camera.h b/src/uca-camera.h index bd89bc6..7d81dac 100644 --- a/src/uca-camera.h +++ b/src/uca-camera.h @@ -63,6 +63,7 @@ enum { PROP_SENSOR_MAX_FRAME_RATE, PROP_TRIGGER_MODE, PROP_EXPOSURE_TIME, + PROP_FRAMES_PER_SECOND, PROP_ROI_X, PROP_ROI_Y, PROP_ROI_WIDTH, diff --git a/test/test-mock.c b/test/test-mock.c index 711364d..17af329 100644 --- a/test/test-mock.c +++ b/test/test-mock.c @@ -148,6 +148,26 @@ test_base_properties (Fixture *fixture, gconstpointer data) g_free (properties); } +static void +test_fps_property (Fixture *fixture, gconstpointer data) +{ + gdouble frames_per_second; + gdouble exposure_time = 0.5; + + g_object_set (G_OBJECT (fixture->camera), + "exposure-time", exposure_time, + NULL); + g_object_get (G_OBJECT (fixture->camera), + "frames-per-second", &frames_per_second, + NULL); + + /* + * The mock camera does not override the "frames-per-second" property, so we + * check the implementation from the base camera. + */ + g_assert_cmpfloat (frames_per_second, ==, 1.0 / exposure_time); +} + static void test_binnings_properties (Fixture *fixture, gconstpointer data) { @@ -189,6 +209,7 @@ int main (int argc, char *argv[]) g_test_add ("/properties/base", Fixture, NULL, fixture_setup, test_base_properties, fixture_teardown); g_test_add ("/properties/recording", Fixture, NULL, fixture_setup, test_recording_property, fixture_teardown); g_test_add ("/properties/binnings", Fixture, NULL, fixture_setup, test_binnings_properties, fixture_teardown); + g_test_add ("/properties/frames-per-second", Fixture, NULL, fixture_setup, test_fps_property, fixture_teardown); g_test_add ("/signal", Fixture, NULL, fixture_setup, test_signal, fixture_teardown); return g_test_run (); -- cgit v1.2.3 From b72daf9dbba95a208a4fb84e5b1c629d64a72c00 Mon Sep 17 00:00:00 2001 From: Matthias Vogelgesang Date: Tue, 9 Oct 2012 16:05:20 +0200 Subject: Fix #151: Rename trigger enum value --- plugins/pco/uca-pco-camera.c | 4 ++-- src/CMakeLists.txt | 13 +------------ src/uca-camera.c | 10 +++++++++- src/uca-camera.h | 2 +- src/uca-docs.xml.in | 4 ++-- src/uca-plugin-manager.c | 21 ++++++++++++++++++--- src/uca.types.in | 2 +- 7 files changed, 34 insertions(+), 22 deletions(-) (limited to 'src') diff --git a/plugins/pco/uca-pco-camera.c b/plugins/pco/uca-pco-camera.c index 893a480..5415867 100644 --- a/plugins/pco/uca-pco-camera.c +++ b/plugins/pco/uca-pco-camera.c @@ -807,7 +807,7 @@ uca_pco_camera_set_property(GObject *object, guint property_id, const GValue *va case UCA_CAMERA_TRIGGER_AUTO: pco_set_trigger_mode(priv->pco, TRIGGER_MODE_AUTOTRIGGER); break; - case UCA_CAMERA_TRIGGER_INTERNAL: + case UCA_CAMERA_TRIGGER_SOFTWARE: pco_set_trigger_mode(priv->pco, TRIGGER_MODE_SOFTWARETRIGGER); break; case UCA_CAMERA_TRIGGER_EXTERNAL: @@ -1040,7 +1040,7 @@ uca_pco_camera_get_property(GObject *object, guint property_id, GValue *value, G g_value_set_enum(value, UCA_CAMERA_TRIGGER_AUTO); break; case TRIGGER_MODE_SOFTWARETRIGGER: - g_value_set_enum(value, UCA_CAMERA_TRIGGER_INTERNAL); + g_value_set_enum(value, UCA_CAMERA_TRIGGER_SOFTWARE); break; case TRIGGER_MODE_EXTERNALTRIGGER: g_value_set_enum(value, UCA_CAMERA_TRIGGER_EXTERNAL); diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index dd2f464..160c52b 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -130,6 +130,7 @@ if(GTK_DOC_FOUND) "${docs_out}/api-index-full.html" "${docs_out}/ch01.html" "${docs_out}/UcaCamera.html" + "${docs_out}/UcaPluginManager.html" "${docs_out}/style.css" "${docs_out}/uca.devhelp2" "${docs_out}/home.png" @@ -137,18 +138,6 @@ if(GTK_DOC_FOUND) "${docs_out}/right.png" "${docs_out}/up.png") - # Put in uca-docs.xml and uca.types all cameras that are built - set(_xml_doc_input) - set(_types_input) - foreach (_cam ${cameras}) - # add camera to the installed documentation - list(APPEND reference_files "${docs_out}/Uca${_cam}Camera.html") - - string(TOLOWER ${_cam} _cam) - set(_xml_doc_input "${_xml_doc_input}\n") - set(_types_input "${_types_input}\nuca_${_cam}_camera_get_type") - endforeach() - configure_file(${CMAKE_CURRENT_SOURCE_DIR}/uca-docs.xml.in ${docs_out}/uca-docs.xml) diff --git a/src/uca-camera.c b/src/uca-camera.c index 14da820..6d92e6a 100644 --- a/src/uca-camera.c +++ b/src/uca-camera.c @@ -15,6 +15,14 @@ with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA */ +/** + * SECTION:uca-camera + * @Short_description: Base class representing a camera + * @Title: UcaCamera + * + * UcaCamera is the base camera from which a real hardware camera derives from. + */ + #include #include "config.h" #include "uca-camera.h" @@ -28,7 +36,7 @@ G_DEFINE_TYPE(UcaCamera, uca_camera, G_TYPE_OBJECT) * UcaCameraTrigger: * @UCA_CAMERA_TRIGGER_AUTO: Trigger automatically * @UCA_CAMERA_TRIGGER_EXTERNAL: Trigger from an external source - * @UCA_CAMERA_TRIGGER_INTERNAL: Trigger internally from software using + * @UCA_CAMERA_TRIGGER_SOFTWARE: Trigger from software using * #uca_camera_trigger */ diff --git a/src/uca-camera.h b/src/uca-camera.h index 7d81dac..8bc48bc 100644 --- a/src/uca-camera.h +++ b/src/uca-camera.h @@ -42,7 +42,7 @@ typedef enum { typedef enum { UCA_CAMERA_TRIGGER_AUTO, - UCA_CAMERA_TRIGGER_INTERNAL, + UCA_CAMERA_TRIGGER_SOFTWARE, UCA_CAMERA_TRIGGER_EXTERNAL } UcaCameraTrigger; diff --git a/src/uca-docs.xml.in b/src/uca-docs.xml.in index 43a830d..093fd36 100644 --- a/src/uca-docs.xml.in +++ b/src/uca-docs.xml.in @@ -16,8 +16,8 @@ Unified Camera Access - - ${_xml_doc_input} + + diff --git a/src/uca-plugin-manager.c b/src/uca-plugin-manager.c index cb7e518..373ccb2 100644 --- a/src/uca-plugin-manager.c +++ b/src/uca-plugin-manager.c @@ -1,3 +1,20 @@ +/* Copyright (C) 2012 Matthias Vogelgesang + (Karlsruhe Institute of Technology) + + This library is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by the + Free Software Foundation; either version 2.1 of the License, or (at your + option) any later version. + + This library is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + details. + + You should have received a copy of the GNU Lesser General Public License along + with this library; if not, write to the Free Software Foundation, Inc., 51 + Franklin St, Fifth Floor, Boston, MA 02110, USA */ + /** * SECTION:uca-plugin-manager * @Short_description: Load an #UcaFilter from a shared object @@ -47,7 +64,6 @@ uca_plugin_manager_error_quark (void) /** * uca_plugin_manager_new: - * @config: (allow-none): A #UcaConfiguration object or %NULL. * * Create a plugin manager object to instantiate camera objects. * @@ -142,10 +158,9 @@ list_free_full (GList *list) /** * uca_plugin_manager_get_available_cameras: - * * @manager: A #UcaPluginManager * - * Returns: (element-type utf8) (transfer full): A list with strings of + * Return value: (element-type utf8) (transfer full): A list with strings of * available camera names. You have to free the individual strings with * g_list_foreach(list, (GFunc) g_free, NULL) and the list itself with * g_list_free. diff --git a/src/uca.types.in b/src/uca.types.in index a9ce408..7526948 100644 --- a/src/uca.types.in +++ b/src/uca.types.in @@ -1,2 +1,2 @@ uca_camera_get_type -${_types_input} +uca_plugin_manager_get_type -- cgit v1.2.3 From 95a22bf2f02ad11c2602df5ac5ffd04fee93588c Mon Sep 17 00:00:00 2001 From: Matthias Vogelgesang Date: Wed, 10 Oct 2012 17:44:34 +0200 Subject: Implement experimental histogram view --- plugins/mock/uca-mock-camera.c | 4 - plugins/pf/uca-pf-camera.c | 1 + src/uca-camera.c | 10 +- tools/gui/control.c | 47 ++++--- tools/gui/control.glade | 75 ++++++++-- tools/gui/egg-histogram-view.c | 301 +++++++++++++++++++++++++++++++++++++++-- tools/gui/egg-histogram-view.h | 5 + 7 files changed, 400 insertions(+), 43 deletions(-) (limited to 'src') diff --git a/plugins/mock/uca-mock-camera.c b/plugins/mock/uca-mock-camera.c index 7ab1d4a..65c4240 100644 --- a/plugins/mock/uca-mock-camera.c +++ b/plugins/mock/uca-mock-camera.c @@ -37,7 +37,6 @@ static const gint mock_overrideables[] = { PROP_SENSOR_HORIZONTAL_BINNINGS, PROP_SENSOR_VERTICAL_BINNING, PROP_SENSOR_VERTICAL_BINNINGS, - PROP_TRIGGER_MODE, PROP_EXPOSURE_TIME, PROP_ROI_X, PROP_ROI_Y, @@ -301,9 +300,6 @@ static void uca_mock_camera_get_property(GObject *object, guint property_id, GVa case PROP_EXPOSURE_TIME: g_value_set_double(value, priv->exposure_time); break; - case PROP_TRIGGER_MODE: - g_value_set_enum(value, UCA_CAMERA_TRIGGER_AUTO); - break; case PROP_ROI_X: g_value_set_uint(value, priv->roi_x); break; diff --git a/plugins/pf/uca-pf-camera.c b/plugins/pf/uca-pf-camera.c index 35b5edd..473ffd3 100644 --- a/plugins/pf/uca-pf-camera.c +++ b/plugins/pf/uca-pf-camera.c @@ -234,6 +234,7 @@ static void uca_pf_camera_get_property(GObject *object, guint property_id, GValu g_value_set_boolean(value, FALSE); break; case PROP_EXPOSURE_TIME: + g_value_set_double(value, 1. / 488.0); break; case PROP_ROI_X: g_value_set_uint(value, 0); diff --git a/src/uca-camera.c b/src/uca-camera.c index 6d92e6a..5684888 100644 --- a/src/uca-camera.c +++ b/src/uca-camera.c @@ -132,15 +132,19 @@ uca_camera_get_property(GObject *object, guint property_id, GValue *value, GPara switch (property_id) { case PROP_IS_RECORDING: - g_value_set_boolean(value, priv->is_recording); + g_value_set_boolean (value, priv->is_recording); break; case PROP_IS_READOUT: - g_value_set_boolean(value, priv->is_readout); + g_value_set_boolean (value, priv->is_readout); break; case PROP_TRANSFER_ASYNCHRONOUSLY: - g_value_set_boolean(value, priv->transfer_async); + g_value_set_boolean (value, priv->transfer_async); + break; + + case PROP_TRIGGER_MODE: + g_value_set_enum (value, UCA_CAMERA_TRIGGER_AUTO); break; case PROP_FRAMES_PER_SECOND: diff --git a/tools/gui/control.c b/tools/gui/control.c index f7d3618..b36d188 100644 --- a/tools/gui/control.c +++ b/tools/gui/control.c @@ -28,6 +28,7 @@ #include "uca-camera.h" #include "uca-plugin-manager.h" #include "egg-property-tree-view.h" +#include "egg-histogram-view.h" typedef struct { @@ -37,6 +38,8 @@ typedef struct { GtkWidget *start_button; GtkWidget *stop_button; GtkWidget *record_button; + GtkWidget *histogram_view; + GtkToggleButton *histogram_button; guchar *buffer; guchar *pixels; @@ -49,15 +52,9 @@ typedef struct { int pixel_size; } ThreadData; -enum { - COLUMN_NAME = 0, - COLUMN_VALUE, - COLUMN_EDITABLE, - NUM_COLUMNS -}; - static UcaPluginManager *plugin_manager; + static void convert_8bit_to_rgb (guchar *output, guchar *input, int width, int height) { @@ -106,7 +103,7 @@ grab_thread (void *args) uca_camera_grab (data->camera, (gpointer) &data->buffer, NULL); if (data->store) { - snprintf (filename, FILENAME_MAX, "frame-%i-%08i.raw", data->timestamp, counter++); + snprintf (filename, FILENAME_MAX, "frame-%i-%08i.raw", data->timestamp, counter); FILE *fp = fopen (filename, "wb"); fwrite (data->buffer, data->width*data->height, data->pixel_size, fp); fclose (fp); @@ -121,11 +118,18 @@ grab_thread (void *args) } gdk_threads_enter (); + gdk_flush (); gtk_image_clear (GTK_IMAGE (data->image)); gtk_image_set_from_pixbuf (GTK_IMAGE (data->image), data->pixbuf); gtk_widget_queue_draw_area (data->image, 0, 0, data->width, data->height); + + if (gtk_toggle_button_get_active (data->histogram_button)) + gtk_widget_queue_draw (data->histogram_view); + gdk_threads_leave (); + + counter++; } return NULL; } @@ -211,6 +215,12 @@ on_record_button_clicked (GtkWidget *widget, gpointer args) static void create_main_window (GtkBuilder *builder, const gchar* camera_name) { + GtkWidget *window; + GtkWidget *image; + GtkWidget *property_tree_view; + GdkPixbuf *pixbuf; + GtkBox *histogram_box; + GtkContainer *scrolled_property_window; static ThreadData td; GError *error = NULL; @@ -228,15 +238,12 @@ create_main_window (GtkBuilder *builder, const gchar* camera_name) "sensor-bitdepth", &bits_per_sample, NULL); - GtkWidget *window = GTK_WIDGET (gtk_builder_get_object (builder, "window")); - GtkWidget *image = GTK_WIDGET (gtk_builder_get_object (builder, "image")); - GtkWidget *property_tree_view = egg_property_tree_view_new (G_OBJECT (camera)); - GtkContainer *scrolled_property_window = GTK_CONTAINER (gtk_builder_get_object (builder, "scrolledwindow2")); - + property_tree_view = egg_property_tree_view_new (G_OBJECT (camera)); + scrolled_property_window = GTK_CONTAINER (gtk_builder_get_object (builder, "scrolledwindow2")); gtk_container_add (scrolled_property_window, property_tree_view); - gtk_widget_show_all (GTK_WIDGET (scrolled_property_window)); - GdkPixbuf *pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8, td.width, td.height); + image = GTK_WIDGET (gtk_builder_get_object (builder, "image")); + pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8, td.width, td.height); gtk_image_set_from_pixbuf (GTK_IMAGE (image), pixbuf); td.pixel_size = bits_per_sample > 8 ? 2 : 1; @@ -247,7 +254,14 @@ create_main_window (GtkBuilder *builder, const gchar* camera_name) td.running = FALSE; td.store = FALSE; td.camera = camera; + td.histogram_view = egg_histogram_view_new (); + td.histogram_button = GTK_TOGGLE_BUTTON (gtk_builder_get_object (builder, "histogram-checkbutton")); + + histogram_box = GTK_BOX (gtk_builder_get_object (builder, "histogram-box")); + gtk_box_pack_start (histogram_box, td.histogram_view, TRUE, TRUE, 6); + egg_histogram_view_set_data (EGG_HISTOGRAM_VIEW (td.histogram_view), td.buffer, td.width * td.height, bits_per_sample, 256); + window = GTK_WIDGET (gtk_builder_get_object (builder, "window")); g_signal_connect (window, "destroy", G_CALLBACK (on_destroy), &td); td.start_button = GTK_WIDGET (gtk_builder_get_object (builder, "start-button")); @@ -259,8 +273,7 @@ create_main_window (GtkBuilder *builder, const gchar* camera_name) g_signal_connect (td.stop_button, "clicked", G_CALLBACK (on_stop_button_clicked), &td); g_signal_connect (td.record_button, "clicked", G_CALLBACK (on_record_button_clicked), &td); - gtk_widget_show (image); - gtk_widget_show (window); + gtk_widget_show_all (window); } static void diff --git a/tools/gui/control.glade b/tools/gui/control.glade index ee888e8..6d6d791 100644 --- a/tools/gui/control.glade +++ b/tools/gui/control.glade @@ -164,28 +164,83 @@ True 6 - - 300 + True True - automatic - automatic - + + 640 + 480 True - queue + True + automatic + automatic - + True - gtk-missing-image + queue + + + 640 + 480 + True + gtk-missing-image + + + + True + True + + + + + True + True + + + True + + + + + + Enable Live Update + True + True + False + 6 + True + True + + + end + 1 + + + + + + + True + Histogram + + + False + + + + + True + True + - True - False + False + True diff --git a/tools/gui/egg-histogram-view.c b/tools/gui/egg-histogram-view.c index 809a2d9..d3cb18b 100644 --- a/tools/gui/egg-histogram-view.c +++ b/tools/gui/egg-histogram-view.c @@ -15,17 +15,33 @@ with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA */ -#include +#include #include "egg-histogram-view.h" -G_DEFINE_TYPE (EggHistogramView, egg_histogram_view, GTK_TYPE_CELL_RENDERER) +G_DEFINE_TYPE (EggHistogramView, egg_histogram_view, GTK_TYPE_DRAWING_AREA) #define EGG_HISTOGRAM_VIEW_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), EGG_TYPE_HISTOGRAM_VIEW, EggHistogramViewPrivate)) +#define MIN_WIDTH 128 +#define MIN_HEIGHT 128 +#define BORDER 2 struct _EggHistogramViewPrivate { - guint foo; + GdkCursorType cursor_type; + gboolean grabbing; + + /* This could be moved into a real histogram class */ + guint n_bins; + gint *bins; + gint min_value; + gint max_value; + gint min_border; + gint max_border; + + gpointer data; + gint n_elements; + gint n_bits; }; enum @@ -46,9 +62,178 @@ egg_histogram_view_new (void) return GTK_WIDGET (view); } +void +egg_histogram_view_set_data (EggHistogramView *view, + gpointer data, + guint n_elements, + guint n_bits, + guint n_bins) +{ + EggHistogramViewPrivate *priv; + + priv = view->priv; + + if (priv->bins != NULL) + g_free (priv->bins); + + priv->data = data; + priv->bins = g_malloc0 (n_bins * sizeof (guint)); + priv->n_bins = n_bins; + priv->n_bits = n_bits; + priv->n_elements = n_elements; + + priv->min_value = 0; + priv->max_value = (gint) pow(2, n_bits) - 1; + + priv->min_border = 20; + priv->max_border = priv->max_value - 20; +} + +static void +compute_histogram (EggHistogramViewPrivate *priv) +{ + for (guint i = 0; i < priv->n_bins; i++) + priv->bins[i] = 0; + + if (priv->n_bits == 8) { + guint8 *data = (guint8 *) priv->data; + + for (guint i = 0; i < priv->n_elements; i++) { + guint8 v = data[i]; + guint index = (guint) round (((gdouble) v) / priv->max_value * (priv->n_bins - 1)); + priv->bins[index]++; + } + } + else if (priv->n_bits == 16) { + guint16 *data = (guint16 *) priv->data; + + for (guint i = 0; i < priv->n_elements; i++) { + guint16 v = data[i]; + guint index = (guint) floor (((gdouble ) v) / priv->max_value * (priv->n_bins - 1)); + priv->bins[index]++; + } + } + else + g_warning ("%i number of bits unsupported", priv->n_bits); +} + +static void +set_cursor_type (EggHistogramView *view, GdkCursorType cursor_type) +{ + if (cursor_type != view->priv->cursor_type) { + GdkCursor *cursor = gdk_cursor_new (cursor_type); + + gdk_window_set_cursor (gtk_widget_get_window (GTK_WIDGET(view)), cursor); + gdk_cursor_unref (cursor); + view->priv->cursor_type = cursor_type; + } +} + +static void +egg_histogram_view_size_request (GtkWidget *widget, + GtkRequisition *requisition) +{ + requisition->width = MIN_WIDTH; + requisition->height = MIN_HEIGHT; +} + +static gboolean +egg_histogram_view_expose (GtkWidget *widget, + GdkEventExpose *event) +{ + EggHistogramViewPrivate *priv; + GtkAllocation allocation; + GtkStyle *style; + cairo_t *cr; + gint width, height; + gint max_value = 0; + + priv = EGG_HISTOGRAM_VIEW_GET_PRIVATE (widget); + cr = gdk_cairo_create (gtk_widget_get_window (widget)); + + gdk_cairo_region (cr, event->region); + cairo_clip (cr); + + style = gtk_widget_get_style (widget); + gdk_cairo_set_source_color (cr, &style->base[GTK_STATE_NORMAL]); + cairo_paint (cr); + + /* Draw the background */ + gdk_cairo_set_source_color (cr, &style->base[GTK_STATE_NORMAL]); + cairo_paint (cr); + + gtk_widget_get_allocation (widget, &allocation); + width = allocation.width - 2 * BORDER; + height = allocation.height - 2 * BORDER; + + gdk_cairo_set_source_color (cr, &style->dark[GTK_STATE_NORMAL]); + cairo_set_line_width (cr, 1.0); + cairo_set_line_cap (cr, CAIRO_LINE_CAP_SQUARE); + cairo_translate (cr, 0.5, 0.5); + cairo_rectangle (cr, BORDER, BORDER, width - 1, height - 1); + cairo_stroke (cr); + + if (priv->bins == NULL) + goto cleanup; + + compute_histogram (priv); + + /* Draw border areas */ + gdk_cairo_set_source_color (cr, &style->dark[GTK_STATE_NORMAL]); + + if (priv->min_border > 0) { + cairo_rectangle (cr, BORDER, BORDER, priv->min_border + 0.5, height - 1); + cairo_fill (cr); + } + + /* Draw spikes */ + for (guint i = 0; i < priv->n_bins; i++) { + if (priv->bins[i] > max_value) + max_value = priv->bins[i]; + } + + if (max_value == 0) + goto cleanup; + + gdk_cairo_set_source_color (cr, &style->black); + + if (width > priv->n_bins) { + gdouble skip = ((gdouble) width) / priv->n_bins; + gdouble x = 1; + + for (guint i = 0; i < priv->n_bins; i++, x += skip) { + if (priv->bins[i] == 0) + continue; + + gint y = (gint) ((height - 2) * priv->bins[i]) / max_value; + cairo_move_to (cr, round (x + BORDER), height + BORDER - 1); + cairo_line_to (cr, round (x + BORDER), height + BORDER - 1 - y); + cairo_stroke (cr); + } + } + +cleanup: + cairo_destroy (cr); + return FALSE; +} + +static void +egg_histogram_view_finalize (GObject *object) +{ + EggHistogramViewPrivate *priv; + + priv = EGG_HISTOGRAM_VIEW_GET_PRIVATE (object); + + if (priv->bins) + g_free (priv->bins); + + G_OBJECT_CLASS (egg_histogram_view_parent_class)->finalize (object); +} + static void egg_histogram_view_dispose (GObject *object) { + G_OBJECT_CLASS (egg_histogram_view_parent_class)->dispose (object); } static void @@ -81,20 +266,118 @@ egg_histogram_view_get_property (GObject *object, } } +static gint +get_mouse_distance (EggHistogramViewPrivate *priv, + gint x) +{ + return (priv->min_border + BORDER) - x; +} + +static gboolean +egg_histogram_view_motion_notify (GtkWidget *widget, + GdkEventMotion *event) +{ + EggHistogramView *view; + EggHistogramViewPrivate *priv; + + view = EGG_HISTOGRAM_VIEW (widget); + priv = view->priv; + + if (priv->grabbing) { + priv->min_border = event->x + BORDER; + gtk_widget_queue_draw (widget); + } + else { + gint distance = get_mouse_distance (priv, event->x); + + if (ABS(distance) < 6) + set_cursor_type (view, GDK_FLEUR); + else + set_cursor_type (view, GDK_ARROW); + } + + return TRUE; +} + +static gboolean +egg_histogram_view_button_release (GtkWidget *widget, + GdkEventButton *event) +{ + EggHistogramView *view; + EggHistogramViewPrivate *priv; + GtkAllocation allocation; + gint width; + + gtk_widget_get_allocation (widget, &allocation); + width = allocation.width - 2 * BORDER; + + view = EGG_HISTOGRAM_VIEW (widget); + priv = view->priv; + + set_cursor_type (view, GDK_ARROW); + priv->grabbing = FALSE; + + return TRUE; +} + +static gboolean +egg_histogram_view_button_press (GtkWidget *widget, + GdkEventButton *event) +{ + EggHistogramView *view; + EggHistogramViewPrivate *priv; + gint distance; + + view = EGG_HISTOGRAM_VIEW (widget); + priv = view->priv; + distance = get_mouse_distance (priv, event->x); + + if (ABS (distance) < 6) { + priv->grabbing = TRUE; + set_cursor_type (view, GDK_FLEUR); + } + + return TRUE; +} + static void egg_histogram_view_class_init (EggHistogramViewClass *klass) { - GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); - gobject_class->set_property = egg_histogram_view_set_property; - gobject_class->get_property = egg_histogram_view_get_property; - gobject_class->dispose = egg_histogram_view_dispose; + object_class->set_property = egg_histogram_view_set_property; + object_class->get_property = egg_histogram_view_get_property; + object_class->dispose = egg_histogram_view_dispose; + object_class->finalize = egg_histogram_view_finalize; + + widget_class->size_request = egg_histogram_view_size_request; + widget_class->expose_event = egg_histogram_view_expose; + widget_class->button_press_event = egg_histogram_view_button_press; + widget_class->button_release_event = egg_histogram_view_button_release; + widget_class->motion_notify_event = egg_histogram_view_motion_notify; g_type_class_add_private (klass, sizeof (EggHistogramViewPrivate)); } static void -egg_histogram_view_init (EggHistogramView *renderer) +egg_histogram_view_init (EggHistogramView *view) { - renderer->priv = EGG_HISTOGRAM_VIEW_GET_PRIVATE (renderer); + EggHistogramViewPrivate *priv; + + view->priv = priv = EGG_HISTOGRAM_VIEW_GET_PRIVATE (view); + + priv->bins = NULL; + priv->data = NULL; + priv->n_bins = 0; + priv->n_elements = 0; + + priv->cursor_type = GDK_ARROW; + priv->grabbing = FALSE; + + gtk_widget_add_events (GTK_WIDGET (view), + GDK_BUTTON_PRESS_MASK | + GDK_BUTTON_RELEASE_MASK | + GDK_BUTTON1_MOTION_MASK | + GDK_POINTER_MOTION_MASK); } diff --git a/tools/gui/egg-histogram-view.h b/tools/gui/egg-histogram-view.h index 23581dc..a1df0ba 100644 --- a/tools/gui/egg-histogram-view.h +++ b/tools/gui/egg-histogram-view.h @@ -48,6 +48,11 @@ struct _EggHistogramViewClass GType egg_histogram_view_get_type (void); GtkWidget * egg_histogram_view_new (void); +void egg_histogram_view_set_data (EggHistogramView *view, + gpointer data, + guint n_elements, + guint n_bits, + guint n_bins); G_END_DECLS -- cgit v1.2.3 From 13b2833ea9c16750efb923a981ea04d37aaa6789 Mon Sep 17 00:00:00 2001 From: Matthias Vogelgesang Date: Thu, 11 Oct 2012 16:38:26 +0200 Subject: Implement adjustable histogram --- src/uca-camera.c | 2 +- tools/gui/control.c | 70 ++++++------ tools/gui/control.glade | 112 +++++++++++++++++--- tools/gui/egg-histogram-view.c | 234 +++++++++++++++++++++++++++++++---------- tools/gui/egg-histogram-view.h | 4 + 5 files changed, 316 insertions(+), 106 deletions(-) (limited to 'src') diff --git a/src/uca-camera.c b/src/uca-camera.c index 5684888..091ef54 100644 --- a/src/uca-camera.c +++ b/src/uca-camera.c @@ -128,7 +128,7 @@ uca_camera_set_property (GObject *object, guint property_id, const GValue *value static void uca_camera_get_property(GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { - UcaCameraPrivate *priv = UCA_CAMERA_GET_PRIVATE(object); + UcaCameraPrivate *priv = UCA_CAMERA_GET_PRIVATE (object); switch (property_id) { case PROP_IS_RECORDING: diff --git a/tools/gui/control.c b/tools/gui/control.c index b36d188..214e4da 100644 --- a/tools/gui/control.c +++ b/tools/gui/control.c @@ -19,10 +19,7 @@ #include #include #include -#include -#include -#include -#include +#include #include "config.h" #include "uca-camera.h" @@ -56,39 +53,28 @@ static UcaPluginManager *plugin_manager; static void -convert_8bit_to_rgb (guchar *output, guchar *input, int width, int height) +convert_8bit_to_rgb (guchar *output, guchar *input, gint width, gint height, gdouble min, gdouble max) { + gdouble factor = 255.0 / (max - min); + for (int i = 0, j = 0; i < width*height; i++) { - output[j++] = input[i]; - output[j++] = input[i]; - output[j++] = input[i]; + guchar val = (guchar) ((input[i] - min) * factor); + output[j++] = val; + output[j++] = val; + output[j++] = val; } } static void -convert_16bit_to_rgb (guchar *output, guchar *input, int width, int height) +convert_16bit_to_rgb (guchar *output, guchar *input, gint width, gint height, gdouble min, gdouble max) { - guint16 *in = (guint16 *) input; - guint16 min = G_MAXUINT16, max = 0; - gfloat spread = 0.0f; - - for (int i = 0; i < width * height; i++) { - guint16 v = in[i]; - if (v < min) - min = v; - if (v > max) - max = v; - } - - spread = (gfloat) max - min; + gdouble factor = 255.0 / (max - min); - if (spread > 0.0f) { - for (int i = 0, j = 0; i < width*height; i++) { - guchar val = (guint8) (((in[i] - min) / spread) * 255.0f); - output[j++] = val; - output[j++] = val; - output[j++] = val; - } + for (int i = 0, j = 0; i < width*height; i++) { + guchar val = (guint8) ((input[i] - min) * factor); + output[j++] = val; + output[j++] = val; + output[j++] = val; } } @@ -100,6 +86,9 @@ grab_thread (void *args) gint counter = 0; while (data->running) { + gdouble min_value; + gdouble max_value; + uca_camera_grab (data->camera, (gpointer) &data->buffer, NULL); if (data->store) { @@ -111,11 +100,12 @@ grab_thread (void *args) /* FIXME: We should actually check if this is really a new frame and * just do nothing if it is an already displayed one. */ + egg_histogram_get_visible_range (EGG_HISTOGRAM_VIEW (data->histogram_view), &min_value, &max_value); + if (data->pixel_size == 1) - convert_8bit_to_rgb (data->pixels, data->buffer, data->width, data->height); - else if (data->pixel_size == 2) { - convert_16bit_to_rgb (data->pixels, data->buffer, data->width, data->height); - } + convert_8bit_to_rgb (data->pixels, data->buffer, data->width, data->height, min_value, max_value); + else if (data->pixel_size == 2) + convert_16bit_to_rgb (data->pixels, data->buffer, data->width, data->height, min_value, max_value); gdk_threads_enter (); @@ -221,6 +211,7 @@ create_main_window (GtkBuilder *builder, const gchar* camera_name) GdkPixbuf *pixbuf; GtkBox *histogram_box; GtkContainer *scrolled_property_window; + GtkAdjustment *max_bin_adjustment; static ThreadData td; GError *error = NULL; @@ -259,7 +250,8 @@ create_main_window (GtkBuilder *builder, const gchar* camera_name) histogram_box = GTK_BOX (gtk_builder_get_object (builder, "histogram-box")); gtk_box_pack_start (histogram_box, td.histogram_view, TRUE, TRUE, 6); - egg_histogram_view_set_data (EGG_HISTOGRAM_VIEW (td.histogram_view), td.buffer, td.width * td.height, bits_per_sample, 256); + egg_histogram_view_set_data (EGG_HISTOGRAM_VIEW (td.histogram_view), + td.buffer, td.width * td.height, bits_per_sample, 256); window = GTK_WIDGET (gtk_builder_get_object (builder, "window")); g_signal_connect (window, "destroy", G_CALLBACK (on_destroy), &td); @@ -269,6 +261,16 @@ create_main_window (GtkBuilder *builder, const gchar* camera_name) td.record_button = GTK_WIDGET (gtk_builder_get_object (builder, "record-button")); set_tool_button_state (&td); + g_object_bind_property (gtk_builder_get_object (builder, "min_bin_value_adjustment"), "value", + td.histogram_view, "minimum-bin-value", + G_BINDING_DEFAULT); + + max_bin_adjustment = GTK_ADJUSTMENT (gtk_builder_get_object (builder, "max_bin_value_adjustment")); + gtk_adjustment_set_value (max_bin_adjustment, pow (2, bits_per_sample) - 1); + g_object_bind_property (max_bin_adjustment, "value", + td.histogram_view, "maximum-bin-value", + G_BINDING_DEFAULT); + g_signal_connect (td.start_button, "clicked", G_CALLBACK (on_start_button_clicked), &td); g_signal_connect (td.stop_button, "clicked", G_CALLBACK (on_stop_button_clicked), &td); g_signal_connect (td.record_button, "clicked", G_CALLBACK (on_record_button_clicked), &td); diff --git a/tools/gui/control.glade b/tools/gui/control.glade index 7ef712d..ebe2cc8 100644 --- a/tools/gui/control.glade +++ b/tools/gui/control.glade @@ -204,17 +204,97 @@ - - Enable Live Update + True - True - False 6 - True - True + 3 + 2 + 6 + 6 + + + True + 1 + Minimum Value: + + + GTK_FILL + + 6 + 6 + + + + + 100 + True + True + + min_bin_value_adjustment + + + 1 + 2 + GTK_EXPAND + + + + + + True + 1 + Maximum Value: + + + 1 + 2 + GTK_FILL + + 6 + 6 + + + + + 100 + True + True + + max_bin_value_adjustment + + + 1 + 2 + 1 + 2 + GTK_EXPAND + + + + + + Live Update + True + True + False + 6 + True + True + + + 2 + 3 + + + + + + + - end + False + False 1 @@ -264,13 +344,6 @@ - - 65535 - 1 - 65535 - 1 - 10 - 6 @@ -352,4 +425,15 @@ + + 65535 + 1 + 10 + + + 256 + 65535 + 1 + 10 + diff --git a/tools/gui/egg-histogram-view.c b/tools/gui/egg-histogram-view.c index 7abc2be..91e61e8 100644 --- a/tools/gui/egg-histogram-view.c +++ b/tools/gui/egg-histogram-view.c @@ -34,11 +34,14 @@ struct _EggHistogramViewPrivate /* This could be moved into a real histogram class */ guint n_bins; gint *bins; - gint min_value; - gint max_value; - gint min_border; + gint *grabbed; + gint min_border; /* threshold set in screen units */ gint max_border; + gdouble min_value; /* lowest value of the first bin */ + gdouble max_value; /* highest value of the last bin */ + gdouble range; + gpointer data; gint n_elements; gint n_bits; @@ -47,6 +50,8 @@ struct _EggHistogramViewPrivate enum { PROP_0, + PROP_MINIMUM_BIN_VALUE, + PROP_MAXIMUM_BIN_VALUE, N_PROPERTIES }; @@ -71,6 +76,7 @@ egg_histogram_view_set_data (EggHistogramView *view, { EggHistogramViewPrivate *priv; + g_return_if_fail (EGG_IS_HISTOGRAM_VIEW (view)); priv = view->priv; if (priv->bins != NULL) @@ -82,16 +88,46 @@ egg_histogram_view_set_data (EggHistogramView *view, priv->n_bits = n_bits; priv->n_elements = n_elements; - priv->min_value = 0; + priv->min_value = 0.0; priv->max_value = (gint) pow(2, n_bits) - 1; - priv->min_border = 20; - priv->max_border = priv->max_value - 20; + priv->min_border = 0; + priv->max_border = 256; + priv->range = priv->max_value - priv->min_value; +} + +void +egg_histogram_get_visible_range (EggHistogramView *view, gdouble *min, gdouble *max) +{ + EggHistogramViewPrivate *priv; + GtkAllocation allocation; + gdouble width; + + g_return_if_fail (EGG_IS_HISTOGRAM_VIEW (view)); + + gtk_widget_get_allocation (GTK_WIDGET (view), &allocation); + width = (gdouble) allocation.width - 2 * BORDER; + priv = view->priv; + + *min = (priv->min_border - 2) / width * priv->range; + *max = (priv->max_border - 2) / width * priv->range; +} + +static void +set_max_border (EggHistogramView *view) +{ + GtkAllocation allocation; + + g_return_if_fail (EGG_IS_HISTOGRAM_VIEW (view)); + gtk_widget_get_allocation (GTK_WIDGET (view), &allocation); + view->priv->max_border = allocation.width - 2 * BORDER; } static void compute_histogram (EggHistogramViewPrivate *priv) { + guint n_bins = priv->n_bins - 1; + for (guint i = 0; i < priv->n_bins; i++) priv->bins[i] = 0; @@ -100,8 +136,11 @@ compute_histogram (EggHistogramViewPrivate *priv) for (guint i = 0; i < priv->n_elements; i++) { guint8 v = data[i]; - guint index = (guint) round (((gdouble) v) / priv->max_value * (priv->n_bins - 1)); - priv->bins[index]++; + + if (v >= priv->min_value && v <= priv->max_value) { + guint index = (guint) round (((gdouble) v) / priv->max_value * n_bins); + priv->bins[index]++; + } } } else if (priv->n_bits == 16) { @@ -109,8 +148,11 @@ compute_histogram (EggHistogramViewPrivate *priv) for (guint i = 0; i < priv->n_elements; i++) { guint16 v = data[i]; - guint index = (guint) floor (((gdouble ) v) / priv->max_value * (priv->n_bins - 1)); - priv->bins[index]++; + + if (v >= priv->min_value && v <= priv->max_value) { + guint index = (guint) floor (((gdouble ) v) / priv->max_value * n_bins); + priv->bins[index]++; + } } } else @@ -137,6 +179,36 @@ egg_histogram_view_size_request (GtkWidget *widget, requisition->height = MIN_HEIGHT; } +static void +draw_bins (EggHistogramViewPrivate *priv, + cairo_t *cr, + gint width, + gint height) +{ + gdouble skip = ((gdouble) width) / priv->n_bins; + gdouble x = BORDER; + gdouble ys = height + BORDER - 1; + gint max_value = 0; + + for (guint i = 0; i < priv->n_bins; i++) { + if (priv->bins[i] > max_value) + max_value = priv->bins[i]; + } + + if (max_value == 0) + return; + + for (guint i = 0; i < priv->n_bins && x < (width - BORDER); i++, x += skip) { + if (priv->bins[i] == 0) + continue; + + gint y = (gint) ((height - 2) * priv->bins[i]) / max_value; + cairo_move_to (cr, round (x), ys); + cairo_line_to (cr, round (x), ys - y); + cairo_stroke (cr); + } +} + static gboolean egg_histogram_view_expose (GtkWidget *widget, GdkEventExpose *event) @@ -146,7 +218,6 @@ egg_histogram_view_expose (GtkWidget *widget, GtkStyle *style; cairo_t *cr; gint width, height; - gint max_value = 0; priv = EGG_HISTOGRAM_VIEW_GET_PRIVATE (widget); cr = gdk_cairo_create (gtk_widget_get_window (widget)); @@ -181,36 +252,15 @@ egg_histogram_view_expose (GtkWidget *widget, /* Draw border areas */ gdk_cairo_set_source_color (cr, &style->dark[GTK_STATE_NORMAL]); - if (priv->min_border > 0) { - cairo_rectangle (cr, BORDER, BORDER, priv->min_border + 0.5, height - 1); - cairo_fill (cr); - } - - /* Draw spikes */ - for (guint i = 0; i < priv->n_bins; i++) { - if (priv->bins[i] > max_value) - max_value = priv->bins[i]; - } + cairo_rectangle (cr, BORDER, BORDER, priv->min_border + 0.5, height - 1); + cairo_fill (cr); - if (max_value == 0) - goto cleanup; + cairo_rectangle (cr, priv->max_border + 0.5, BORDER, width - priv->min_border - 0.5, height - 1); + cairo_fill (cr); + /* Draw spikes */ gdk_cairo_set_source_color (cr, &style->black); - - if (width > priv->n_bins) { - gdouble skip = ((gdouble) width) / priv->n_bins; - gdouble x = 1; - - for (guint i = 0; i < priv->n_bins; i++, x += skip) { - if (priv->bins[i] == 0) - continue; - - gint y = (gint) ((height - 2) * priv->bins[i]) / max_value; - cairo_move_to (cr, round (x + BORDER), height + BORDER - 1); - cairo_line_to (cr, round (x + BORDER), height + BORDER - 1 - y); - cairo_stroke (cr); - } - } + draw_bins (priv, cr, width, height); cleanup: cairo_destroy (cr); @@ -242,9 +292,42 @@ egg_histogram_view_set_property (GObject *object, const GValue *value, GParamSpec *pspec) { + EggHistogramViewPrivate *priv; + g_return_if_fail (EGG_IS_HISTOGRAM_VIEW (object)); + priv = EGG_HISTOGRAM_VIEW_GET_PRIVATE (object); switch (property_id) { + case PROP_MINIMUM_BIN_VALUE: + { + gdouble v = g_value_get_double (value); + + if (v > priv->max_value) + g_warning ("Minimum value `%f' larger than maximum value `%f'", + v, priv->max_value); + else { + priv->min_value = v; + priv->range = priv->max_value - v; + priv->min_border = 0; + } + } + break; + + case PROP_MAXIMUM_BIN_VALUE: + { + gdouble v = g_value_get_double (value); + + if (v < priv->min_value) + g_warning ("Maximum value `%f' larger than minimum value `%f'", + v, priv->min_value); + else { + priv->max_value = v; + priv->range = v - priv->min_value; + set_max_border (EGG_HISTOGRAM_VIEW (object)); + } + } + break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); return; @@ -257,20 +340,48 @@ egg_histogram_view_get_property (GObject *object, GValue *value, GParamSpec *pspec) { + EggHistogramViewPrivate *priv; + g_return_if_fail (EGG_IS_HISTOGRAM_VIEW (object)); + priv = EGG_HISTOGRAM_VIEW_GET_PRIVATE (object); switch (property_id) { + case PROP_MINIMUM_BIN_VALUE: + g_value_set_double (value, priv->min_value); + break; + + case PROP_MAXIMUM_BIN_VALUE: + g_value_set_double (value, priv->max_value); + break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); return; } } -static gint -get_mouse_distance (EggHistogramViewPrivate *priv, +static gboolean +is_on_border (EggHistogramViewPrivate *priv, + gint x) +{ + gint d1 = (priv->min_border + BORDER) - x; + gint d2 = (priv->max_border + BORDER) - x; + return ABS (d1) < 6 || ABS (d2) < 6; +} + +static gint * +get_grabbed_border (EggHistogramViewPrivate *priv, gint x) { - return (priv->min_border + BORDER) - x; + gint d1 = (priv->min_border + BORDER) - x; + gint d2 = (priv->max_border + BORDER) - x; + + if (ABS (d1) < 6) + return &priv->min_border; + else if (ABS (d2) < 6) + return &priv->max_border; + + return NULL; } static gboolean @@ -284,13 +395,12 @@ egg_histogram_view_motion_notify (GtkWidget *widget, priv = view->priv; if (priv->grabbing) { - priv->min_border = event->x + BORDER; + *priv->grabbed = event->x; + gtk_widget_queue_draw (widget); } else { - gint distance = get_mouse_distance (priv, event->x); - - if (ABS(distance) < 6) + if (is_on_border (priv, event->x)) set_cursor_type (view, GDK_FLEUR); else set_cursor_type (view, GDK_ARROW); @@ -304,18 +414,10 @@ egg_histogram_view_button_release (GtkWidget *widget, GdkEventButton *event) { EggHistogramView *view; - EggHistogramViewPrivate *priv; - /* GtkAllocation allocation; */ - /* gint width; */ - - /* gtk_widget_get_allocation (widget, &allocation); */ - /* width = allocation.width - 2 * BORDER; */ view = EGG_HISTOGRAM_VIEW (widget); - priv = view->priv; - set_cursor_type (view, GDK_ARROW); - priv->grabbing = FALSE; + view->priv->grabbing = FALSE; return TRUE; } @@ -326,14 +428,13 @@ egg_histogram_view_button_press (GtkWidget *widget, { EggHistogramView *view; EggHistogramViewPrivate *priv; - gint distance; view = EGG_HISTOGRAM_VIEW (widget); priv = view->priv; - distance = get_mouse_distance (priv, event->x); - if (ABS (distance) < 6) { + if (is_on_border (priv, event->x)) { priv->grabbing = TRUE; + priv->grabbed = get_grabbed_border (priv, event->x); set_cursor_type (view, GDK_FLEUR); } @@ -357,6 +458,23 @@ egg_histogram_view_class_init (EggHistogramViewClass *klass) widget_class->button_release_event = egg_histogram_view_button_release; widget_class->motion_notify_event = egg_histogram_view_motion_notify; + egg_histogram_view_properties[PROP_MINIMUM_BIN_VALUE] = + g_param_spec_double ("minimum-bin-value", + "Smallest possible bin value", + "Smallest possible bin value, everything below is discarded.", + 0.0, G_MAXDOUBLE, 0.0, + G_PARAM_READWRITE); + + egg_histogram_view_properties[PROP_MAXIMUM_BIN_VALUE] = + g_param_spec_double ("maximum-bin-value", + "Largest possible bin value", + "Largest possible bin value, everything above is discarded.", + 0.0, G_MAXDOUBLE, 256.0, + G_PARAM_READWRITE); + + g_object_class_install_property (object_class, PROP_MINIMUM_BIN_VALUE, egg_histogram_view_properties[PROP_MINIMUM_BIN_VALUE]); + g_object_class_install_property (object_class, PROP_MAXIMUM_BIN_VALUE, egg_histogram_view_properties[PROP_MAXIMUM_BIN_VALUE]); + g_type_class_add_private (klass, sizeof (EggHistogramViewPrivate)); } @@ -371,6 +489,8 @@ egg_histogram_view_init (EggHistogramView *view) priv->data = NULL; priv->n_bins = 0; priv->n_elements = 0; + priv->min_value = priv->min_border = 0; + priv->max_value = priv->max_border = 256; priv->cursor_type = GDK_ARROW; priv->grabbing = FALSE; diff --git a/tools/gui/egg-histogram-view.h b/tools/gui/egg-histogram-view.h index a1df0ba..61a1c8c 100644 --- a/tools/gui/egg-histogram-view.h +++ b/tools/gui/egg-histogram-view.h @@ -53,6 +53,10 @@ void egg_histogram_view_set_data (EggHistogramView *view, guint n_elements, guint n_bits, guint n_bins); +void egg_histogram_get_visible_range + (EggHistogramView *view, + gdouble *min, + gdouble *max); G_END_DECLS -- cgit v1.2.3 From d8743d20b93d34497183d05ccb17519194ec5abb Mon Sep 17 00:00:00 2001 From: Matthias Vogelgesang Date: Tue, 16 Oct 2012 12:27:47 +0200 Subject: Integrate initial unit facility --- src/uca-camera.c | 140 +++++++++++++++++++++++++++++++++++++++++++++---------- src/uca-camera.h | 18 ++++++- test/test-mock.c | 8 ++++ 3 files changed, 140 insertions(+), 26 deletions(-) (limited to 'src') diff --git a/src/uca-camera.c b/src/uca-camera.c index 091ef54..2cf17ff 100644 --- a/src/uca-camera.c +++ b/src/uca-camera.c @@ -50,7 +50,25 @@ G_DEFINE_TYPE(UcaCamera, uca_camera, G_TYPE_OBJECT) */ GQuark uca_camera_error_quark() { - return g_quark_from_static_string("uca-camera-error-quark"); + return g_quark_from_static_string ("uca-camera-error-quark"); +} + +/** + * UcaUnit: + * @UCA_UNIT_NA: Not applicable + * @UCA_UNIT_METER: SI meter + * @UCA_UNIT_SECOND: SI second + * @UCA_UNIT_PIXEL: Number of pixels in one dimension + * @UCA_UNIT_COUNT: Number + * + * Units should be registered by camera implementations using + * uca_camera_register_unit() and can be queried by client programs with + * uca_camera_get_unit(). + */ + +GQuark uca_unit_quark () +{ + return g_quark_from_static_string ("uca-unit-quark"); } enum { @@ -96,6 +114,12 @@ struct _UcaCameraPrivate { gboolean transfer_async; }; +static void +uca_camera_set_property_unit (GParamSpec *pspec, UcaUnit unit) +{ + g_param_spec_set_qdata (pspec, UCA_UNIT_QUARK, GINT_TO_POINTER (unit)); +} + static void uca_camera_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { @@ -149,7 +173,7 @@ uca_camera_get_property(GObject *object, guint property_id, GValue *value, GPara case PROP_FRAMES_PER_SECOND: { - gdouble exposure_time; + gdouble exposure_time; g_object_get (object, "exposure-time", &exposure_time, NULL); g_value_set_double (value, 1. / exposure_time); @@ -162,11 +186,18 @@ uca_camera_get_property(GObject *object, guint property_id, GValue *value, GPara } static void -uca_camera_class_init(UcaCameraClass *klass) +uca_camera_finalize (GObject *object) +{ + G_OBJECT_CLASS (uca_camera_parent_class)->finalize (object); +} + +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; + gobject_class->finalize = uca_camera_finalize; klass->start_recording = NULL; klass->stop_recording = NULL; @@ -342,7 +373,7 @@ uca_camera_class_init(UcaCameraClass *klass) } static void -uca_camera_init(UcaCamera *camera) +uca_camera_init (UcaCamera *camera) { camera->grab_func = NULL; @@ -351,26 +382,20 @@ uca_camera_init(UcaCamera *camera) camera->priv->is_readout = FALSE; camera->priv->transfer_async = FALSE; - /* - * This here would be the best place to instantiate the tango server object, - * along these lines: - * - * // I'd prefer if you expose a single C method, so we don't have to - * // compile uca-camera.c with g++ - * tango_handle = tango_server_new(camera); - * - * void tango_server_new(UcaCamera *camera) - * { - * // Do whatever is necessary. In the end you will have some kind of - * // Tango object t which needs to somehow hook up to the properties. A - * // list of all available properties can be enumerated with - * // g_object_class_list_properties(G_OBJECT_CLASS(camera), - * // &n_properties); - * - * // For setting/getting properties, use g_object_get/set_property() or - * // g_object_get/set() whatever is more suitable. - * } - */ + uca_camera_set_property_unit (camera_properties[PROP_SENSOR_WIDTH], UCA_UNIT_PIXEL); + uca_camera_set_property_unit (camera_properties[PROP_SENSOR_HEIGHT], UCA_UNIT_PIXEL); + uca_camera_set_property_unit (camera_properties[PROP_SENSOR_BITDEPTH], UCA_UNIT_COUNT); + uca_camera_set_property_unit (camera_properties[PROP_SENSOR_HORIZONTAL_BINNING], UCA_UNIT_PIXEL); + uca_camera_set_property_unit (camera_properties[PROP_SENSOR_VERTICAL_BINNING], UCA_UNIT_PIXEL); + uca_camera_set_property_unit (camera_properties[PROP_SENSOR_MAX_FRAME_RATE], UCA_UNIT_COUNT); + uca_camera_set_property_unit (camera_properties[PROP_EXPOSURE_TIME], UCA_UNIT_SECOND); + uca_camera_set_property_unit (camera_properties[PROP_FRAMES_PER_SECOND], UCA_UNIT_COUNT); + uca_camera_set_property_unit (camera_properties[PROP_ROI_X], UCA_UNIT_PIXEL); + uca_camera_set_property_unit (camera_properties[PROP_ROI_Y], UCA_UNIT_PIXEL); + uca_camera_set_property_unit (camera_properties[PROP_ROI_WIDTH], UCA_UNIT_PIXEL); + uca_camera_set_property_unit (camera_properties[PROP_ROI_HEIGHT], UCA_UNIT_PIXEL); + uca_camera_set_property_unit (camera_properties[PROP_ROI_WIDTH_MULTIPLIER], UCA_UNIT_COUNT); + uca_camera_set_property_unit (camera_properties[PROP_ROI_HEIGHT_MULTIPLIER], UCA_UNIT_COUNT); } /** @@ -523,7 +548,8 @@ uca_camera_start_readout (UcaCamera *camera, GError **error) * * Set the grab function that is called whenever a frame is readily transfered. */ -void uca_camera_set_grab_func(UcaCamera *camera, UcaCameraGrabFunc func, gpointer user_data) +void +uca_camera_set_grab_func(UcaCamera *camera, UcaCameraGrabFunc func, gpointer user_data) { camera->grab_func = func; camera->user_data = user_data; @@ -600,3 +626,67 @@ uca_camera_grab (UcaCamera *camera, gpointer *data, GError **error) g_static_mutex_unlock (&mutex); } +/** + * uca_camera_register_unit: + * @camera: A #UcaCamera object + * @prop_name: Name of a property + * @unit: #UcaUnit + * + * Associates @prop_name of @camera with a specific @unit. + * + * Since: 1.1 + */ +void +uca_camera_register_unit (UcaCamera *camera, + const gchar *prop_name, + UcaUnit unit) +{ + UcaCameraClass *klass; + GObjectClass *oclass; + GParamSpec *pspec; + + klass = UCA_CAMERA_GET_CLASS (camera); + oclass = G_OBJECT_CLASS (klass); + pspec = g_object_class_find_property (oclass, prop_name); + + if (pspec == NULL) { + g_warning ("Camera does not have property `%s'", prop_name); + return; + } + + uca_camera_set_property_unit (pspec, unit); +} + +/** + * uca_camera_get_unit: + * @camera: A #UcaCamera object + * @prop_name: Name of a property + * + * Returns the unit associated with @prop_name of @camera. + * + * Returns: A #UcaUnit value associated with @prop_name. If there is none, the + * value will be #UCA_UNIT_NA. + * Since: 1.1 + */ +UcaUnit +uca_camera_get_unit (UcaCamera *camera, + const gchar *prop_name) +{ + UcaCameraClass *klass; + GObjectClass *oclass; + GParamSpec *pspec; + gpointer data; + + klass = UCA_CAMERA_GET_CLASS (camera); + oclass = G_OBJECT_CLASS (klass); + pspec = g_object_class_find_property (oclass, prop_name); + + if (pspec == NULL) { + g_warning ("Camera does not have property `%s'", prop_name); + return UCA_UNIT_NA; + } + + data = g_param_spec_get_qdata (pspec, UCA_UNIT_QUARK); + return data == NULL ? UCA_UNIT_NA : GPOINTER_TO_INT (data); +} + diff --git a/src/uca-camera.h b/src/uca-camera.h index 8bc48bc..4aad0b4 100644 --- a/src/uca-camera.h +++ b/src/uca-camera.h @@ -29,8 +29,11 @@ G_BEGIN_DECLS #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() +#define UCA_CAMERA_ERROR uca_camera_error_quark() +#define UCA_UNIT_QUARK uca_unit_quark() + GQuark uca_camera_error_quark(void); +GQuark uca_unit_quark(void); typedef enum { UCA_CAMERA_ERROR_NOT_FOUND, @@ -46,6 +49,14 @@ typedef enum { UCA_CAMERA_TRIGGER_EXTERNAL } UcaCameraTrigger; +typedef enum { + UCA_UNIT_NA, + UCA_UNIT_METER, + UCA_UNIT_SECOND, + UCA_UNIT_PIXEL, + UCA_UNIT_COUNT +} UcaUnit; + typedef struct _UcaCamera UcaCamera; typedef struct _UcaCameraClass UcaCameraClass; typedef struct _UcaCameraPrivate UcaCameraPrivate; @@ -136,6 +147,11 @@ void uca_camera_grab (UcaCamera *camera, void uca_camera_set_grab_func (UcaCamera *camera, UcaCameraGrabFunc func, gpointer user_data); +void uca_camera_register_unit (UcaCamera *camera, + const gchar *prop_name, + UcaUnit unit); +UcaUnit uca_camera_get_unit (UcaCamera *camera, + const gchar *prop_name); GType uca_camera_get_type(void); diff --git a/test/test-mock.c b/test/test-mock.c index 17af329..08f24b8 100644 --- a/test/test-mock.c +++ b/test/test-mock.c @@ -168,6 +168,13 @@ test_fps_property (Fixture *fixture, gconstpointer data) g_assert_cmpfloat (frames_per_second, ==, 1.0 / exposure_time); } +static void +test_property_units (Fixture *fixture, gconstpointer data) +{ + g_assert (uca_camera_get_unit (fixture->camera, "sensor-width") == UCA_UNIT_PIXEL); + g_assert (uca_camera_get_unit (fixture->camera, "name") == UCA_UNIT_NA); +} + static void test_binnings_properties (Fixture *fixture, gconstpointer data) { @@ -210,6 +217,7 @@ int main (int argc, char *argv[]) g_test_add ("/properties/recording", Fixture, NULL, fixture_setup, test_recording_property, fixture_teardown); g_test_add ("/properties/binnings", Fixture, NULL, fixture_setup, test_binnings_properties, fixture_teardown); g_test_add ("/properties/frames-per-second", Fixture, NULL, fixture_setup, test_fps_property, fixture_teardown); + g_test_add ("/properties/units", Fixture, NULL, fixture_setup, test_property_units, fixture_teardown); g_test_add ("/signal", Fixture, NULL, fixture_setup, test_signal, fixture_teardown); return g_test_run (); -- cgit v1.2.3 From de2e8e3191eae37b91f672a03e028a35c8863c9d Mon Sep 17 00:00:00 2001 From: Matthias Vogelgesang Date: Tue, 16 Oct 2012 12:40:18 +0200 Subject: Add temperature unit and descriptions for pco --- plugins/mock/uca-mock-camera.c | 2 ++ plugins/pco/uca-pco-camera.c | 14 ++++++++++++++ src/uca-camera.c | 7 ++++--- src/uca-camera.h | 1 + test/test-mock.c | 4 ++++ 5 files changed, 25 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/plugins/mock/uca-mock-camera.c b/plugins/mock/uca-mock-camera.c index 38caf0d..bf3124e 100644 --- a/plugins/mock/uca-mock-camera.c +++ b/plugins/mock/uca-mock-camera.c @@ -397,6 +397,8 @@ static void uca_mock_camera_init(UcaMockCamera *self) g_value_init(&val, G_TYPE_UINT); g_value_set_uint(&val, 1); g_value_array_append(self->priv->binnings, &val); + + uca_camera_register_unit (UCA_CAMERA (self), "frame-rate", UCA_UNIT_COUNT); } G_MODULE_EXPORT UcaCamera * diff --git a/plugins/pco/uca-pco-camera.c b/plugins/pco/uca-pco-camera.c index 725ffbf..92f814e 100644 --- a/plugins/pco/uca-pco-camera.c +++ b/plugins/pco/uca-pco-camera.c @@ -1363,6 +1363,8 @@ uca_pco_camera_class_init(UcaPcoCameraClass *klass) static void uca_pco_camera_init(UcaPcoCamera *self) { + UcaCamera *camera; + self->priv = UCA_PCO_CAMERA_GET_PRIVATE(self); self->priv->fg = NULL; self->priv->fg_mem = NULL; @@ -1376,6 +1378,18 @@ uca_pco_camera_init(UcaPcoCamera *self) self->priv->delay_timebase = TIMEBASE_INVALID; self->priv->exposure_timebase = TIMEBASE_INVALID; + + camera = UCA_CAMERA (self); + uca_camera_register_unit (camera, "sensor-width-extended", UCA_UNIT_PIXEL); + uca_camera_register_unit (camera, "sensor-height-extended", UCA_UNIT_PIXEL); + uca_camera_register_unit (camera, "temperature", UCA_UNIT_DEGREE_CELSIUS); + uca_camera_register_unit (camera, "cooling-point", UCA_UNIT_DEGREE_CELSIUS); + uca_camera_register_unit (camera, "cooling-point-min", UCA_UNIT_DEGREE_CELSIUS); + uca_camera_register_unit (camera, "cooling-point-max", UCA_UNIT_DEGREE_CELSIUS); + uca_camera_register_unit (camera, "cooling-point-default", UCA_UNIT_DEGREE_CELSIUS); + uca_camera_register_unit (camera, "sensor-adcs", UCA_UNIT_COUNT); + uca_camera_register_unit (camera, "sensor-max-adcs", UCA_UNIT_COUNT); + uca_camera_register_unit (camera, "delay-time", UCA_UNIT_SECOND); } G_MODULE_EXPORT UcaCamera * diff --git a/src/uca-camera.c b/src/uca-camera.c index 2cf17ff..8b08359 100644 --- a/src/uca-camera.c +++ b/src/uca-camera.c @@ -56,10 +56,11 @@ GQuark uca_camera_error_quark() /** * UcaUnit: * @UCA_UNIT_NA: Not applicable - * @UCA_UNIT_METER: SI meter - * @UCA_UNIT_SECOND: SI second + * @UCA_UNIT_METER: Length in SI meter + * @UCA_UNIT_SECOND: Time in SI second * @UCA_UNIT_PIXEL: Number of pixels in one dimension - * @UCA_UNIT_COUNT: Number + * @UCA_UNIT_DEGREE_CELSIUS: Temperature in degree Celsius + * @UCA_UNIT_COUNT: Generic number * * Units should be registered by camera implementations using * uca_camera_register_unit() and can be queried by client programs with diff --git a/src/uca-camera.h b/src/uca-camera.h index 4aad0b4..d84b5f2 100644 --- a/src/uca-camera.h +++ b/src/uca-camera.h @@ -54,6 +54,7 @@ typedef enum { UCA_UNIT_METER, UCA_UNIT_SECOND, UCA_UNIT_PIXEL, + UCA_UNIT_DEGREE_CELSIUS, UCA_UNIT_COUNT } UcaUnit; diff --git a/test/test-mock.c b/test/test-mock.c index 08f24b8..85c1ba4 100644 --- a/test/test-mock.c +++ b/test/test-mock.c @@ -171,8 +171,12 @@ test_fps_property (Fixture *fixture, gconstpointer data) static void test_property_units (Fixture *fixture, gconstpointer data) { + /* Default camera properties */ g_assert (uca_camera_get_unit (fixture->camera, "sensor-width") == UCA_UNIT_PIXEL); g_assert (uca_camera_get_unit (fixture->camera, "name") == UCA_UNIT_NA); + + /* Mock-specific properties */ + g_assert (uca_camera_get_unit (fixture->camera, "frame-rate") == UCA_UNIT_COUNT); } static void -- cgit v1.2.3 From a1ab005916ba3aa50923294c5be3da0ded16fbc0 Mon Sep 17 00:00:00 2001 From: Matthias Vogelgesang Date: Thu, 18 Oct 2012 10:56:30 +0200 Subject: Add download button and make dimax work --- plugins/pco/uca-pco-camera.c | 3 ++- src/uca-camera.c | 5 +++++ src/uca-camera.h | 3 ++- tools/gui/control.c | 48 ++++++++++++++++++++++++++++++++++++++++---- tools/gui/control.glade | 12 +++++++++++ 5 files changed, 65 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/plugins/pco/uca-pco-camera.c b/plugins/pco/uca-pco-camera.c index 92f814e..d5f5593 100644 --- a/plugins/pco/uca-pco-camera.c +++ b/plugins/pco/uca-pco-camera.c @@ -554,7 +554,8 @@ uca_pco_camera_grab(UcaCamera *camera, gpointer *data, GError **error) if (is_readout) { if (priv->current_image == priv->num_recorded_images) { - *data = NULL; + g_set_error (error, UCA_CAMERA_ERROR, UCA_CAMERA_ERROR_END_OF_STREAM, + "End of data stream"); return; } diff --git a/src/uca-camera.c b/src/uca-camera.c index 8b08359..9210a05 100644 --- a/src/uca-camera.c +++ b/src/uca-camera.c @@ -47,6 +47,7 @@ G_DEFINE_TYPE(UcaCamera, uca_camera, G_TYPE_OBJECT) * @UCA_CAMERA_ERROR_NOT_RECORDING: Camera is not recording * @UCA_CAMERA_ERROR_NO_GRAB_FUNC: No grab callback was set * @UCA_CAMERA_ERROR_NOT_IMPLEMENTED: Virtual function is not implemented + * @UCA_CAMERA_ERROR_END_OF_STREAM: Data stream has ended. */ GQuark uca_camera_error_quark() { @@ -602,6 +603,10 @@ uca_camera_trigger (UcaCamera *camera, GError **error) * * You must have called uca_camera_start_recording() before, otherwise you will * get a #UCA_CAMERA_ERROR_NOT_RECORDING error. + * + * If *data is %NULL after returning from uca_camera_grab() and error is also + * %NULL, the data stream has ended. For example, with cameras that support + * in-camera memory, all frames have been transfered. */ void uca_camera_grab (UcaCamera *camera, gpointer *data, GError **error) diff --git a/src/uca-camera.h b/src/uca-camera.h index d84b5f2..ef3bf14 100644 --- a/src/uca-camera.h +++ b/src/uca-camera.h @@ -40,7 +40,8 @@ typedef enum { UCA_CAMERA_ERROR_RECORDING, UCA_CAMERA_ERROR_NOT_RECORDING, UCA_CAMERA_ERROR_NO_GRAB_FUNC, - UCA_CAMERA_ERROR_NOT_IMPLEMENTED + UCA_CAMERA_ERROR_NOT_IMPLEMENTED, + UCA_CAMERA_ERROR_END_OF_STREAM } UcaCameraError; typedef enum { diff --git a/tools/gui/control.c b/tools/gui/control.c index c9fd2f6..930c4d0 100644 --- a/tools/gui/control.c +++ b/tools/gui/control.c @@ -41,6 +41,7 @@ typedef struct { GtkWidget *start_button; GtkWidget *stop_button; GtkWidget *record_button; + GtkWidget *download_button; GtkComboBox *zoom_box; GtkWidget *histogram_view; @@ -52,6 +53,7 @@ typedef struct { gint display_width, display_height; gdouble zoom_factor; State state; + gboolean data_in_camram; gint timestamp; gint width, height; @@ -88,7 +90,7 @@ convert_grayscale_to_rgb (ThreadData *data, gpointer buffer) output[i++] = val; output[i++] = val; output[i++] = val; - } + } } } else if (data->pixel_size == 2) { @@ -103,7 +105,7 @@ convert_grayscale_to_rgb (ThreadData *data, gpointer buffer) output[i++] = val; output[i++] = val; output[i++] = val; - } + } } } } @@ -204,6 +206,8 @@ set_tool_button_state (ThreadData *data) data->state == RUNNING || data->state == RECORDING); gtk_widget_set_sensitive (data->record_button, data->state == IDLE); + gtk_widget_set_sensitive (data->download_button, + data->data_in_camram); gtk_widget_set_sensitive (GTK_WIDGET (data->zoom_box), data->state == IDLE); } @@ -254,12 +258,14 @@ on_stop_button_clicked (GtkWidget *widget, ThreadData *data) { GError *error = NULL; + g_object_get (data->camera, "has-camram-recording", &data->data_in_camram, NULL); data->state = IDLE; set_tool_button_state (data); uca_camera_stop_recording (data->camera, &error); if (error != NULL) g_printerr ("Failed to stop: %s\n", error->message); + } static void @@ -284,6 +290,38 @@ on_record_button_clicked (GtkWidget *widget, ThreadData *data) } } +static void +on_download_button_clicked (GtkWidget *widget, ThreadData *data) +{ + gpointer buffer; + GError *error = NULL; + + uca_camera_start_readout (data->camera, &error); + + if (error != NULL) { + g_printerr ("Failed to start read out of camera memory: %s\n", error->message); + return; + } + + ring_buffer_reset (data->buffer); + + while (error == NULL) { + buffer = ring_buffer_get_current_pointer (data->buffer); + uca_camera_grab (data->camera, &buffer, &error); + ring_buffer_proceed (data->buffer); + } + + if (error->code != UCA_CAMERA_ERROR_END_OF_STREAM) { + guint n_frames = ring_buffer_get_num_blocks (data->buffer); + + gtk_adjustment_set_upper (data->frame_slider, n_frames - 1); + gtk_adjustment_set_value (data->frame_slider, n_frames - 1); + } + else { + g_printerr ("Error while reading out frames: %s\n", error->message); + } +} + static void on_histogram_changed (EggHistogramView *view, ThreadData *data) { @@ -359,6 +397,7 @@ create_main_window (GtkBuilder *builder, const gchar* camera_name) td.start_button = GTK_WIDGET (gtk_builder_get_object (builder, "start-button")); td.stop_button = GTK_WIDGET (gtk_builder_get_object (builder, "stop-button")); td.record_button = GTK_WIDGET (gtk_builder_get_object (builder, "record-button")); + td.download_button = GTK_WIDGET (gtk_builder_get_object (builder, "download-button")); td.histogram_button = GTK_TOGGLE_BUTTON (gtk_builder_get_object (builder, "histogram-checkbutton")); td.frame_slider = GTK_ADJUSTMENT (gtk_builder_get_object (builder, "frames-adjustment")); @@ -368,8 +407,6 @@ create_main_window (GtkBuilder *builder, const gchar* camera_name) n_frames = mem_size * 1024 * 1024 / image_size; ring_buffer = ring_buffer_new (image_size, n_frames); - set_tool_button_state (&td); - egg_histogram_view_set_data (EGG_HISTOGRAM_VIEW (histogram_view), ring_buffer_get_current_pointer (ring_buffer), width * height, bits_per_sample, 256); @@ -392,8 +429,10 @@ create_main_window (GtkBuilder *builder, const gchar* camera_name) td.height = td.display_height = height; td.zoom_factor = 1.0; td.histogram_view = histogram_view; + td.data_in_camram = FALSE; update_pixbuf_dimensions (&td); + set_tool_button_state (&td); /* Hook up signals */ g_object_bind_property (gtk_builder_get_object (builder, "min-bin-value-adjustment"), "value", @@ -408,6 +447,7 @@ create_main_window (GtkBuilder *builder, const gchar* camera_name) g_signal_connect (td.start_button, "clicked", G_CALLBACK (on_start_button_clicked), &td); g_signal_connect (td.stop_button, "clicked", G_CALLBACK (on_stop_button_clicked), &td); g_signal_connect (td.record_button, "clicked", G_CALLBACK (on_record_button_clicked), &td); + g_signal_connect (td.download_button, "clicked", G_CALLBACK (on_download_button_clicked), &td); g_signal_connect (td.zoom_box, "changed", G_CALLBACK (on_zoom_changed), &td); g_signal_connect (histogram_view, "changed", G_CALLBACK (on_histogram_changed), &td); g_signal_connect (window, "destroy", G_CALLBACK (on_destroy), &td); diff --git a/tools/gui/control.glade b/tools/gui/control.glade index 37f8150..2d2aaac 100644 --- a/tools/gui/control.glade +++ b/tools/gui/control.glade @@ -152,6 +152,18 @@ True + + + True + Download + True + network-receive + + + False + True + + False -- cgit v1.2.3 From 983005dfbc3b07093145c0b964063e334b928d48 Mon Sep 17 00:00:00 2001 From: Matthias Vogelgesang Date: Thu, 18 Oct 2012 12:44:40 +0200 Subject: Fix download of in-camera frames --- NEWS | 2 ++ plugins/pco/uca-pco-camera.c | 25 ++++++++++++++++++++++--- src/uca-camera.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ src/uca-camera.h | 3 +++ tools/gui/control.c | 10 +++++++--- 5 files changed, 78 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/NEWS b/NEWS index f0a4c30..7a91e80 100644 --- a/NEWS +++ b/NEWS @@ -23,6 +23,8 @@ Minor changes - It is now possible to generate GObject introspection meta data to bind libuca to all languages that support GObject introspection. +- Added uca_camera_stop_readout() to cleanup after using + uca_camera_start_readout(). Changes in libuca 1.0 aka 0.6 diff --git a/plugins/pco/uca-pco-camera.c b/plugins/pco/uca-pco-camera.c index d5f5593..03a1a17 100644 --- a/plugins/pco/uca-pco-camera.c +++ b/plugins/pco/uca-pco-camera.c @@ -385,7 +385,7 @@ check_pco_property_error (guint err, guint property_id) { if (err != PCO_NOERROR) { g_warning ("Call to libpco failed with error code %x for property `%s'", - err, + err, pco_properties[property_id]->name); } } @@ -523,9 +523,27 @@ uca_pco_camera_start_readout(UcaCamera *camera, GError **error) err = pco_get_num_images(priv->pco, priv->active_segment, &priv->num_recorded_images); HANDLE_PCO_ERROR(err); + err = Fg_AcquireEx(priv->fg, priv->fg_port, GRAB_INFINITE, ACQ_STANDARD, priv->fg_mem); + FG_SET_ERROR(err, priv->fg, UCA_PCO_CAMERA_ERROR_FG_ACQUISITION); + + priv->last_frame = 0; priv->current_image = 1; } +static void +uca_pco_camera_stop_readout(UcaCamera *camera, GError **error) +{ + g_return_if_fail(UCA_IS_PCO_CAMERA(camera)); + UcaPcoCameraPrivate *priv = UCA_PCO_CAMERA_GET_PRIVATE(camera); + + guint err = Fg_stopAcquireEx(priv->fg, priv->fg_port, priv->fg_mem, STOP_SYNC); + FG_SET_ERROR(err, priv->fg, UCA_PCO_CAMERA_ERROR_FG_ACQUISITION); + + err = Fg_setStatusEx(priv->fg, FG_UNBLOCK_ALL, 0, priv->fg_port, priv->fg_mem); + if (err == FG_INVALID_PARAMETER) + g_warning(" Unable to unblock all\n"); +} + static void uca_pco_camera_trigger(UcaCamera *camera, GError **error) { @@ -568,7 +586,7 @@ uca_pco_camera_grab(UcaCamera *camera, gpointer *data, GError **error) } pco_request_image(priv->pco); - priv->last_frame = Fg_getLastPicNumberBlockingEx(priv->fg, priv->last_frame+1, priv->fg_port, MAX_TIMEOUT, priv->fg_mem); + priv->last_frame = Fg_getLastPicNumberBlockingEx(priv->fg, priv->last_frame + 1, priv->fg_port, MAX_TIMEOUT, priv->fg_mem); if (priv->last_frame <= 0) { guint err = FG_OK + 1; @@ -1189,6 +1207,7 @@ uca_pco_camera_class_init(UcaPcoCameraClass *klass) camera_class->start_recording = uca_pco_camera_start_recording; camera_class->stop_recording = uca_pco_camera_stop_recording; camera_class->start_readout = uca_pco_camera_start_readout; + camera_class->stop_readout = uca_pco_camera_stop_readout; camera_class->trigger = uca_pco_camera_trigger; camera_class->grab = uca_pco_camera_grab; @@ -1383,7 +1402,7 @@ uca_pco_camera_init(UcaPcoCamera *self) camera = UCA_CAMERA (self); uca_camera_register_unit (camera, "sensor-width-extended", UCA_UNIT_PIXEL); uca_camera_register_unit (camera, "sensor-height-extended", UCA_UNIT_PIXEL); - uca_camera_register_unit (camera, "temperature", UCA_UNIT_DEGREE_CELSIUS); + uca_camera_register_unit (camera, "sensor-temperature", UCA_UNIT_DEGREE_CELSIUS); uca_camera_register_unit (camera, "cooling-point", UCA_UNIT_DEGREE_CELSIUS); uca_camera_register_unit (camera, "cooling-point-min", UCA_UNIT_DEGREE_CELSIUS); uca_camera_register_unit (camera, "cooling-point-max", UCA_UNIT_DEGREE_CELSIUS); diff --git a/src/uca-camera.c b/src/uca-camera.c index 9210a05..053dcca 100644 --- a/src/uca-camera.c +++ b/src/uca-camera.c @@ -542,6 +542,50 @@ uca_camera_start_readout (UcaCamera *camera, GError **error) g_static_mutex_unlock (&mutex); } +/** + * uca_camera_stop_readout: + * @camera: A #UcaCamera object + * @error: Location to store a #UcaCameraError error or %NULL + * + * Stop reading out frames. + * + * Since: 1.1 + */ +void +uca_camera_stop_readout (UcaCamera *camera, GError **error) +{ + UcaCameraClass *klass; + static GStaticMutex mutex = G_STATIC_MUTEX_INIT; + + g_return_if_fail (UCA_IS_CAMERA(camera)); + + klass = UCA_CAMERA_GET_CLASS(camera); + + g_return_if_fail (klass != NULL); + g_return_if_fail (klass->start_readout != NULL); + + g_static_mutex_lock (&mutex); + + if (camera->priv->is_recording) { + g_set_error (error, UCA_CAMERA_ERROR, UCA_CAMERA_ERROR_RECORDING, + "Camera is still recording"); + } + else { + GError *tmp_error = NULL; + + (*klass->stop_readout) (camera, &tmp_error); + + if (tmp_error == NULL) { + camera->priv->is_readout = FALSE; + g_object_notify (G_OBJECT (camera), "is-readout"); + } + else + g_propagate_error (error, tmp_error); + } + + g_static_mutex_unlock (&mutex); +} + /** * uca_camera_set_grab_func: * @camera: A #UcaCamera object diff --git a/src/uca-camera.h b/src/uca-camera.h index ef3bf14..78edd95 100644 --- a/src/uca-camera.h +++ b/src/uca-camera.h @@ -126,6 +126,7 @@ struct _UcaCameraClass { void (*start_recording) (UcaCamera *camera, GError **error); void (*stop_recording) (UcaCamera *camera, GError **error); void (*start_readout) (UcaCamera *camera, GError **error); + void (*stop_readout) (UcaCamera *camera, GError **error); void (*trigger) (UcaCamera *camera, GError **error); void (*grab) (UcaCamera *camera, gpointer *data, GError **error); @@ -141,6 +142,8 @@ void uca_camera_stop_recording (UcaCamera *camera, GError **error); void uca_camera_start_readout (UcaCamera *camera, GError **error); +void uca_camera_stop_readout (UcaCamera *camera, + GError **error); void uca_camera_trigger (UcaCamera *camera, GError **error); void uca_camera_grab (UcaCamera *camera, diff --git a/tools/gui/control.c b/tools/gui/control.c index 930c4d0..aaeeb75 100644 --- a/tools/gui/control.c +++ b/tools/gui/control.c @@ -311,15 +311,19 @@ on_download_button_clicked (GtkWidget *widget, ThreadData *data) ring_buffer_proceed (data->buffer); } - if (error->code != UCA_CAMERA_ERROR_END_OF_STREAM) { + if (error->code == UCA_CAMERA_ERROR_END_OF_STREAM) { guint n_frames = ring_buffer_get_num_blocks (data->buffer); gtk_adjustment_set_upper (data->frame_slider, n_frames - 1); gtk_adjustment_set_value (data->frame_slider, n_frames - 1); } - else { + else g_printerr ("Error while reading out frames: %s\n", error->message); - } + + uca_camera_stop_readout (data->camera, &error); + + if (error != NULL) + g_printerr ("Failed to stop reading out of camera memory: %s\n", error->message); } static void -- cgit v1.2.3 From 184fc22ce23f8ab7c8127b5ac0657fc20ddea924 Mon Sep 17 00:00:00 2001 From: Matthias Vogelgesang Date: Thu, 18 Oct 2012 16:07:00 +0200 Subject: Add "recorded-frames" property --- plugins/pco/uca-pco-camera.c | 9 +++++++++ src/uca-camera.c | 20 ++++++++++++++++++++ src/uca-camera.h | 1 + 3 files changed, 30 insertions(+) (limited to 'src') diff --git a/plugins/pco/uca-pco-camera.c b/plugins/pco/uca-pco-camera.c index 03a1a17..d34e0f4 100644 --- a/plugins/pco/uca-pco-camera.c +++ b/plugins/pco/uca-pco-camera.c @@ -139,6 +139,7 @@ static gint base_overrideables[] = { PROP_ROI_HEIGHT_MULTIPLIER, PROP_HAS_STREAMING, PROP_HAS_CAMRAM_RECORDING, + PROP_RECORDED_FRAMES, 0 }; @@ -504,6 +505,9 @@ uca_pco_camera_stop_recording(UcaCamera *camera, GError **error) err = Fg_setStatusEx(priv->fg, FG_UNBLOCK_ALL, 0, priv->fg_port, priv->fg_mem); if (err == FG_INVALID_PARAMETER) g_warning(" Unable to unblock all\n"); + + err = pco_get_num_images(priv->pco, priv->active_segment, &priv->num_recorded_images); + HANDLE_PCO_ERROR(err); } static void @@ -1024,6 +1028,10 @@ uca_pco_camera_get_property(GObject *object, guint property_id, GValue *value, G g_value_set_boolean(value, priv->camera_description->has_camram); break; + case PROP_RECORDED_FRAMES: + g_value_set_uint(value, priv->num_recorded_images); + break; + case PROP_RECORD_MODE: { guint16 mode; @@ -1440,6 +1448,7 @@ uca_camera_impl_new (GError **error) priv->roi_y = roi[1] - 1; priv->roi_width = roi[2] - roi[0] + 1; priv->roi_height = roi[3] - roi[1] + 1; + priv->num_recorded_images = 0; guint16 camera_type, camera_subtype; pco_get_camera_type(priv->pco, &camera_type, &camera_subtype); diff --git a/src/uca-camera.c b/src/uca-camera.c index 053dcca..53b2d7a 100644 --- a/src/uca-camera.c +++ b/src/uca-camera.c @@ -103,6 +103,7 @@ const gchar *uca_camera_props[N_BASE_PROPERTIES] = { "roi-height-multiplier", "has-streaming", "has-camram-recording", + "recorded-frames", "transfer-asynchronously", "is-recording", "is-readout" @@ -182,6 +183,10 @@ uca_camera_get_property(GObject *object, guint property_id, GValue *value, GPara } break; + case PROP_RECORDED_FRAMES: + g_value_set_uint (value, 0); + break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); } @@ -350,6 +355,20 @@ uca_camera_class_init (UcaCameraClass *klass) "Is the camera able to record the data in-camera", FALSE, G_PARAM_READABLE); + /** + * UcaCamera:recorded-frames + * + * Number of frames that are recorded into internal camera memory. + * + * Since: 1.1 + */ + camera_properties[PROP_RECORDED_FRAMES] = + g_param_spec_uint(uca_camera_props[PROP_RECORDED_FRAMES], + "Number of frames recorded into internal camera memory", + "Number of frames recorded into internal camera memory", + 0, G_MAXUINT, 0, + G_PARAM_READABLE); + camera_properties[PROP_TRANSFER_ASYNCHRONOUSLY] = g_param_spec_boolean(uca_camera_props[PROP_TRANSFER_ASYNCHRONOUSLY], "Specify whether data should be transfered asynchronously", @@ -398,6 +417,7 @@ uca_camera_init (UcaCamera *camera) uca_camera_set_property_unit (camera_properties[PROP_ROI_HEIGHT], UCA_UNIT_PIXEL); uca_camera_set_property_unit (camera_properties[PROP_ROI_WIDTH_MULTIPLIER], UCA_UNIT_COUNT); uca_camera_set_property_unit (camera_properties[PROP_ROI_HEIGHT_MULTIPLIER], UCA_UNIT_COUNT); + uca_camera_set_property_unit (camera_properties[PROP_RECORDED_FRAMES], UCA_UNIT_COUNT); } /** diff --git a/src/uca-camera.h b/src/uca-camera.h index 78edd95..87996c6 100644 --- a/src/uca-camera.h +++ b/src/uca-camera.h @@ -85,6 +85,7 @@ enum { PROP_ROI_HEIGHT_MULTIPLIER, PROP_HAS_STREAMING, PROP_HAS_CAMRAM_RECORDING, + PROP_RECORDED_FRAMES, /* These properties are handled internally */ PROP_TRANSFER_ASYNCHRONOUSLY, -- cgit v1.2.3 From 7fe0adeb842c3aa47b380a9290465b1250025878 Mon Sep 17 00:00:00 2001 From: Matthias Vogelgesang Date: Fri, 19 Oct 2012 10:39:40 +0200 Subject: Update uca_plugin_manager_get_camera annotation --- src/uca-plugin-manager.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/uca-plugin-manager.c b/src/uca-plugin-manager.c index 373ccb2..e99f478 100644 --- a/src/uca-plugin-manager.c +++ b/src/uca-plugin-manager.c @@ -209,10 +209,14 @@ find_camera_module_path (GList *search_paths, const gchar *name) } /** - * uca_plugin_manager_new_camera: + * uca_plugin_manager_get_camera: * @manager: A #UcaPluginManager * @name: Name of the camera module, that maps to libuca.so * @error: Location for a #GError + * + * Create a new camera instance with camera @name. + * + * Returns: (transfer full): A new #UcaCamera object. */ UcaCamera * uca_plugin_manager_get_camera (UcaPluginManager *manager, -- cgit v1.2.3