diff options
-rw-r--r-- | CMakeLists.txt | 5 | ||||
-rw-r--r-- | NEWS | 20 | ||||
-rw-r--r-- | docs/manual.md | 74 | ||||
-rw-r--r-- | docs/mock.html | 70 | ||||
-rw-r--r-- | docs/style.css | 99 | ||||
-rw-r--r-- | src/CMakeLists.txt | 113 | ||||
-rw-r--r-- | src/cameras/uca-mock-camera.c | 30 | ||||
-rw-r--r-- | src/cameras/uca-mock-camera.h | 2 | ||||
-rw-r--r-- | src/cameras/uca-pco-camera.c | 304 | ||||
-rw-r--r-- | src/cameras/uca-pco-camera.h | 2 | ||||
-rw-r--r-- | src/cameras/uca-pf-camera.c | 102 | ||||
-rw-r--r-- | src/cameras/uca-pf-camera.h | 2 | ||||
-rw-r--r-- | src/cameras/uca-ufo-camera.c | 6 | ||||
-rw-r--r-- | src/cameras/uca-ufo-camera.h | 2 | ||||
-rw-r--r-- | src/uca-camera.c | 306 | ||||
-rw-r--r-- | src/uca-plugin-manager.c | 327 | ||||
-rw-r--r-- | src/uca-plugin-manager.h | 65 | ||||
-rw-r--r-- | test/CMakeLists.txt | 65 | ||||
-rw-r--r-- | test/control.c | 336 | ||||
-rw-r--r-- | test/enum.c | 88 | ||||
-rw-r--r-- | test/grab_pylon.c | 96 | ||||
-rw-r--r-- | test/perf-overhead.c | 143 | ||||
-rwxr-xr-x | test/run.py | 31 | ||||
-rw-r--r-- | test/test-all.c | 214 | ||||
-rw-r--r-- | test/test-mock.c | 181 | ||||
-rw-r--r-- | tools/CMakeLists.txt | 36 | ||||
-rw-r--r-- | tools/benchmark.c (renamed from test/benchmark.c) | 32 | ||||
-rw-r--r-- | tools/gen-doc.c | 151 | ||||
-rw-r--r-- | tools/grab-async.c (renamed from test/grab-async.c) | 44 | ||||
-rw-r--r-- | tools/grab.c (renamed from test/grab.c) | 42 | ||||
-rw-r--r-- | tools/gui/CMakeLists.txt | 39 | ||||
-rw-r--r-- | tools/gui/control.c | 350 | ||||
-rw-r--r-- | tools/gui/control.glade (renamed from test/control.glade) | 0 | ||||
-rw-r--r-- | tools/gui/egg-property-cell-renderer.c (renamed from test/egg-property-cell-renderer.c) | 0 | ||||
-rw-r--r-- | tools/gui/egg-property-cell-renderer.h (renamed from test/egg-property-cell-renderer.h) | 0 | ||||
-rw-r--r-- | tools/gui/egg-property-tree-view.c (renamed from test/egg-property-tree-view.c) | 1 | ||||
-rw-r--r-- | tools/gui/egg-property-tree-view.h (renamed from test/egg-property-tree-view.h) | 0 | ||||
-rw-r--r-- | tools/perf-overhead.c | 181 |
38 files changed, 1959 insertions, 1600 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 48592fd..bc65dc1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,8 +3,8 @@ project(uca C) set(TARNAME "libuca") set(UCA_VERSION_MAJOR "1") -set(UCA_VERSION_MINOR "0") -set(UCA_VERSION_PATCH "0") +set(UCA_VERSION_MINOR "1") +set(UCA_VERSION_PATCH "0-dev") set(UCA_DESCRIPTION "Unified Camera Access") set(UCA_VERSION_STRING "${UCA_VERSION_MAJOR}.${UCA_VERSION_MINOR}.${UCA_VERSION_PATCH}") @@ -29,3 +29,4 @@ SET(UCA_BUILD_DIR ${CMAKE_CURRENT_BINARY_DIR}) add_subdirectory(src) add_subdirectory(test) +add_subdirectory(tools) @@ -1,3 +1,23 @@ +Changes in libuca 1.1 +===================== + +Plugin System +------------- + +A new plugin manager is used to instantiate camera objects from a shared +library. Instead of calling `uca_camera_new`, a plugin manager is created that +looks in pre- and user-defined directories for DSOs that match +`libuca[A-Za-z].so` and used to instantiate: + + UcaPluginManager *manager; + UcaCamera *camera; + + manager = uca_plugin_manager_new (); + camera = uca_plugin_manager_new_camera (manager, "foo", &error); + +The plugin manager adds a dependency on GModule (pkg-config package +`gmodule-2.0`) that is part of GLib. + Changes in libuca 1.0 aka 0.6 ============================= diff --git a/docs/manual.md b/docs/manual.md index 69abae8..cff6f18 100644 --- a/docs/manual.md +++ b/docs/manual.md @@ -107,6 +107,7 @@ necessary header files: ~~~ {.c} #include <glib-object.h> +#include <uca-plugin-manager.h> #include <uca-camera.h> ~~~ @@ -116,6 +117,7 @@ Then you need to setup the type system: int main (int argc, char *argv[]) { + UcaPluginManager *manager; UcaCamera *camera; GError *error = NULL; /* this _must_ be set to NULL */ @@ -124,10 +126,12 @@ main (int argc, char *argv[]) Now you can instantiate new camera _objects_. Each camera is identified by a human-readable string, in this case we want to access any pco camera that is -supported by [libpco][]: +supported by [libpco][]. To instantiate a camera we have to create a plugin +manager first: ~~~ {.c} - camera = uca_camera_new ("pco", &error); + manager = uca_plugin_manager_new (); + camera = uca_plugin_manager_new_camera (manager, "pco", &error); ~~~ Errors are indicated with a returned value `NULL` and `error` set to a value @@ -241,6 +245,12 @@ The following cameras are supported: * Pylon * UFO Camera developed at KIT/IPE. +## Property documentation + +* [mock][mock-doc] + +[mock-doc]: mock.html + # More API @@ -252,38 +262,19 @@ communicate with the camera. Now we will go into more detail. We have already seen how to instantiate a camera object from a name. If you have more than one camera connected to a machine, you will most likely want the user decide which to use. To do so, you can enumerate all camera strings with -`uca_camera_get_types`: +`uca_plugin_manager_get_available_cameras`: ~~~ {.c} - gchar **types; + GList *types; - types = uca_camera_get_types (); + types = uca_camera_get_available_cameras (manager); - for (guint i = 0; types[i] != NULL; i++) - g_print ("%s\n", types[i]); + for (GList *it = g_list_first; it != NULL; it = g_list_next (it)) + g_print ("%s\n", (gchar *) it->data); - /* free the string array */ - g_strfreev (types); -~~~ - -If you _know_ which camera you want to use you can instantiate the sub-classed -camera object directly. In this case we create a pco-based camera: - -~~~ {.c} -#include <glib-object.h> -#include <uca/uca-camera-pco.h> - -int -main (int argc, char *argv[]) -{ - UcaPcoCamera *camera; - GError *error = NULL; - - g_type_init (); - camera = uca_pco_camera_new (&error); - g_object_unref (camera); - return 0; -} + /* free the strings and the list */ + g_list_foreach (types, (GFunc) g_free, NULL); + g_list_free (types); ~~~ [last section]: #first-look-at-the-api @@ -381,6 +372,31 @@ virtual methods. The simplest way is to take the `mock` camera and rename all occurences. Note, that if you class is going to be called `FooBar`, the upper case variant is `FOO_BAR` and the lower case variant is `foo_bar`. +In order to fully implement a camera, you need to override at least the +following virtual methods: + +* `start_recording`: Take suitable actions so that a subsequent call to + `grab` delivers an image or blocks until one is exposed. +* `stop_recording`: Stop recording so that subsequent calls to `grab` + fail. +* `grab`: Return an image from the camera or block until one is ready. + +## Asynchronous operation + +When the camera supports asynchronous acquisition and announces it with a true +boolean value for `"transfer-asynchronously"`, a mechanism must be setup up +during `start_recording` so that for each new frame the grab func callback is +called. + +## Cameras with internal memory + +Cameras such as the pco.dimax record into their own on-board memory rather than +streaming directly to the host PC. In this case, both `start_recording` and +`stop_recording` initiate and end acquisition to the on-board memory. To +initiate a data transfer, the host calls `start_readout` which must be suitably +implemented. The actual data transfer happens either with `grab` or +asynchronously. + [sub-classing]: http://developer.gnome.org/gobject/stable/howto-gobject.html diff --git a/docs/mock.html b/docs/mock.html new file mode 100644 index 0000000..0d38fc8 --- /dev/null +++ b/docs/mock.html @@ -0,0 +1,70 @@ +<html><head><link rel="stylesheet" href="style.css" type="text/css" /><link href='http://fonts.googleapis.com/css?family=Droid+Sans:400,700|Droid+Serif:400,400italic|Inconsolata' rel='stylesheet' type='text/css'><title>mock — properties</title></head><body><div id="header"><h1 class="title">Property documentation of mock</h1><h2>Properties</h2><ul id="toc"><li><code><a href=#name>"name"</a></code></li><li><code><a href=#sensor-width>"sensor-width"</a></code></li><li><code><a href=#sensor-height>"sensor-height"</a></code></li><li><code><a href=#sensor-bitdepth>"sensor-bitdepth"</a></code></li><li><code><a href=#sensor-horizontal-binning>"sensor-horizontal-binning"</a></code></li><li><code><a href=#sensor-horizontal-binnings>"sensor-horizontal-binnings"</a></code></li><li><code><a href=#sensor-vertical-binning>"sensor-vertical-binning"</a></code></li><li><code><a href=#sensor-vertical-binnings>"sensor-vertical-binnings"</a></code></li><li><code><a href=#sensor-max-frame-rate>"sensor-max-frame-rate"</a></code></li><li><code><a href=#trigger-mode>"trigger-mode"</a></code></li><li><code><a href=#exposure-time>"exposure-time"</a></code></li><li><code><a href=#roi-x0>"roi-x0"</a></code></li><li><code><a href=#roi-y0>"roi-y0"</a></code></li><li><code><a href=#roi-width>"roi-width"</a></code></li><li><code><a href=#roi-height>"roi-height"</a></code></li><li><code><a href=#roi-width-multiplier>"roi-width-multiplier"</a></code></li><li><code><a href=#roi-height-multiplier>"roi-height-multiplier"</a></code></li><li><code><a href=#has-streaming>"has-streaming"</a></code></li><li><code><a href=#has-camram-recording>"has-camram-recording"</a></code></li><li><code><a href=#transfer-asynchronously>"transfer-asynchronously"</a></code></li><li><code><a href=#is-recording>"is-recording"</a></code></li><li><code><a href=#is-readout>"is-readout"</a></code></li><li><code><a href=#frame-rate>"frame-rate"</a></code></li></ul><h2>Details</h2><dl><dt id="name"><a href="#toc">name</a></dt> +<dd><pre><code class="prop-type">"name" : gchararray : Read-only</code></pre> +<p>Name of the camera</p> +</dd><dt id="sensor-width"><a href="#toc">sensor-width</a></dt> +<dd><pre><code class="prop-type">"sensor-width" : guint : Read-only</code></pre> +<p>Width of the sensor in pixels</p> +</dd><dt id="sensor-height"><a href="#toc">sensor-height</a></dt> +<dd><pre><code class="prop-type">"sensor-height" : guint : Read-only</code></pre> +<p>Height of the sensor in pixels</p> +</dd><dt id="sensor-bitdepth"><a href="#toc">sensor-bitdepth</a></dt> +<dd><pre><code class="prop-type">"sensor-bitdepth" : guint : Read-only</code></pre> +<p>Number of bits per pixel</p> +</dd><dt id="sensor-horizontal-binning"><a href="#toc">sensor-horizontal-binning</a></dt> +<dd><pre><code class="prop-type">"sensor-horizontal-binning" : guint : Read / Write</code></pre> +<p>Number of sensor ADCs that are combined to one pixel in horizontal direction</p> +</dd><dt id="sensor-horizontal-binnings"><a href="#toc">sensor-horizontal-binnings</a></dt> +<dd><pre><code class="prop-type">"sensor-horizontal-binnings" : GValueArray : Read-only</code></pre> +<p>Array of possible binnings in horizontal direction</p> +</dd><dt id="sensor-vertical-binning"><a href="#toc">sensor-vertical-binning</a></dt> +<dd><pre><code class="prop-type">"sensor-vertical-binning" : guint : Read / Write</code></pre> +<p>Number of sensor ADCs that are combined to one pixel in vertical direction</p> +</dd><dt id="sensor-vertical-binnings"><a href="#toc">sensor-vertical-binnings</a></dt> +<dd><pre><code class="prop-type">"sensor-vertical-binnings" : GValueArray : Read-only</code></pre> +<p>Array of possible binnings in vertical direction</p> +</dd><dt id="sensor-max-frame-rate"><a href="#toc">sensor-max-frame-rate</a></dt> +<dd><pre><code class="prop-type">"sensor-max-frame-rate" : gfloat : Read-only</code></pre> +<p>Maximum frame rate at full frame resolution</p> +</dd><dt id="trigger-mode"><a href="#toc">trigger-mode</a></dt> +<dd><pre><code class="prop-type">"trigger-mode" : UcaCameraTrigger : Read / Write</code></pre> +<p>Trigger mode</p> +</dd><dt id="exposure-time"><a href="#toc">exposure-time</a></dt> +<dd><pre><code class="prop-type">"exposure-time" : gdouble : Read / Write</code></pre> +<p>Exposure time in seconds</p> +</dd><dt id="roi-x0"><a href="#toc">roi-x0</a></dt> +<dd><pre><code class="prop-type">"roi-x0" : guint : Read / Write</code></pre> +<p>Horizontal coordinate</p> +</dd><dt id="roi-y0"><a href="#toc">roi-y0</a></dt> +<dd><pre><code class="prop-type">"roi-y0" : guint : Read / Write</code></pre> +<p>Vertical coordinate</p> +</dd><dt id="roi-width"><a href="#toc">roi-width</a></dt> +<dd><pre><code class="prop-type">"roi-width" : guint : Read / Write</code></pre> +<p>Width of the region of interest</p> +</dd><dt id="roi-height"><a href="#toc">roi-height</a></dt> +<dd><pre><code class="prop-type">"roi-height" : guint : Read / Write</code></pre> +<p>Height of the region of interest</p> +</dd><dt id="roi-width-multiplier"><a href="#toc">roi-width-multiplier</a></dt> +<dd><pre><code class="prop-type">"roi-width-multiplier" : guint : Read-only</code></pre> +<p>Minimum possible step size of horizontal ROI</p> +</dd><dt id="roi-height-multiplier"><a href="#toc">roi-height-multiplier</a></dt> +<dd><pre><code class="prop-type">"roi-height-multiplier" : guint : Read-only</code></pre> +<p>Minimum possible step size of vertical ROI</p> +</dd><dt id="has-streaming"><a href="#toc">has-streaming</a></dt> +<dd><pre><code class="prop-type">"has-streaming" : gboolean : Read-only</code></pre> +<p>Is the camera able to stream the data</p> +</dd><dt id="has-camram-recording"><a href="#toc">has-camram-recording</a></dt> +<dd><pre><code class="prop-type">"has-camram-recording" : gboolean : Read-only</code></pre> +<p>Is the camera able to record the data in-camera</p> +</dd><dt id="transfer-asynchronously"><a href="#toc">transfer-asynchronously</a></dt> +<dd><pre><code class="prop-type">"transfer-asynchronously" : gboolean : Read / Write</code></pre> +<p>Specify whether data should be transfered asynchronously using a specified callback</p> +</dd><dt id="is-recording"><a href="#toc">is-recording</a></dt> +<dd><pre><code class="prop-type">"is-recording" : gboolean : Read-only</code></pre> +<p>Is the camera currently recording</p> +</dd><dt id="is-readout"><a href="#toc">is-readout</a></dt> +<dd><pre><code class="prop-type">"is-readout" : gboolean : Read-only</code></pre> +<p>Is camera in readout mode</p> +</dd><dt id="frame-rate"><a href="#toc">frame-rate</a></dt> +<dd><pre><code class="prop-type">"frame-rate" : gfloat : Read / Write</code></pre> +<p>Number of frames per second that are taken</p> +</dd></dl></body></html> diff --git a/docs/style.css b/docs/style.css index a9fc9ca..beccf45 100644 --- a/docs/style.css +++ b/docs/style.css @@ -1,35 +1,34 @@ - /* --- Reset ------------------------------------------------------ */ body, div, dl, dt, dd, ul, ol, li, h1, h2, h3, h4, h5, h6, pre, form, fieldset, input, textarea, -p, blockquote, th, td { - margin: 0; +p, blockquote, th, td { + margin: 0; padding: 0; } table { - border-collapse: collapse; + border-collapse: collapse; border-spacing: 0; } fieldset, img { - border: 0; - } - address, caption, cite, dfn, th, var { + border: 0; +} +address, caption, cite, dfn, th, var { font-style: normal; - font-weight: normal; - } - caption, th { + font-weight: normal; +} +caption, th { text-align: left; } h1, h2, h3, h4, h5, h6 { - font-size: 100%; + font-size: 100%; font-weight: normal; } q:before, q:after { - content: ''; - } - abbr, acronym { + content: ''; +} +abbr, acronym { border: 0; } @@ -52,10 +51,6 @@ p { margin-bottom: 24px; } -/* p > code { */ -/* font-size: 0.8em; */ -/* } */ - h1, h2, h3, h4, h5, h6 { margin-bottom: 24px; font-family: "Droid Sans", sans-serif; @@ -65,6 +60,9 @@ h1, h2, h3, h4, h5, h6 { h1 { font-size: 1.5em; line-height: 1em; + margin-top: 2em; + padding-bottom: 0.5em; + border-bottom: 2px dotted #bbb; } h2 { @@ -87,11 +85,29 @@ h5, h6 { line-height: 1.5em; } -h1 > a, h2 > a, h3 > a, h4 > a, h5 > a, h6 > a { - color: black; +h1 > a { + color: #555; text-decoration: none; } +a { + color: #8e3557; + text-decoration: none; +} + +a:hover { + color: #88a33e; +} + +h1:hover :after, +h2:hover :after, +h3:hover :after, +h4:hover :after, +h5:hover :after, +h6:hover :after { + content: " \2191"; +} + pre { margin-bottom: 24px; line-height: 1.2em; @@ -103,19 +119,62 @@ code { } ul, ol { + list-style-position: inside; + padding-left: 1em; + text-indent: -1em; + margin-left: 0; margin-bottom: 24px; } +ul#toc { + list-style-type: none; +} + +li + li { + margin-top: 0.1em; +} + ul ul, ol ol { margin: 0 0 0 24px; } +table { + width: 100%; + margin-bottom: 24px; +} + +th { + color: #555; + font-family: 'Droid Sans', sans-serif; + font-weight: bold; + border-bottom: 1px dotted #bbb; +} + +td, th { + padding: 2px; +} + +dl { + margin-bottom: 24px; +} + +dt { + font-style: italic; +} + +dd { + margin-top: 12px; + padding-left: 1em; +} + .title { font-size: xx-large; + color: #555; } .author { font-size: 1.25em; font-weight: normal; + color: #555; } diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 05fd37f..a681f67 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -3,13 +3,17 @@ cmake_minimum_required(VERSION 2.8) # --- Set sources ------------------------------------------------------------- set(uca_SRCS uca-camera.c + uca-plugin-manager.c ) set(uca_HDRS - uca-camera.h) + 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) @@ -28,10 +32,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) @@ -42,18 +61,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() @@ -61,19 +82,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() @@ -81,13 +106,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() @@ -107,9 +137,9 @@ 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) + install(TARGETS ucamock + LIBRARY DESTINATION ${LIB_INSTALL_DIR}/uca) endif() # --- Generate enum file @@ -118,9 +148,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( @@ -128,29 +158,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 @@ -171,7 +190,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" @@ -255,7 +274,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 <gmodule.h> #include <string.h> #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 <gmodule.h> #include <stdlib.h> #include <stdio.h> #include <string.h> @@ -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 <gmodule.h> #include <stdlib.h> #include <stdio.h> #include <string.h> @@ -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 <gmodule.h> #include <stdlib.h> #include <stdio.h> #include <string.h> @@ -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 78adae3..f973355 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 }; @@ -126,7 +87,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 +107,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 +130,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; @@ -339,7 +303,8 @@ static void 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; @@ -370,80 +335,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(). - */ -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 @@ -453,38 +344,47 @@ UcaCamera *uca_camera_new(const gchar *type, GError **error) * #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); } /** @@ -494,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); } /** @@ -532,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); } /** @@ -583,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); - (*klass->trigger)(camera, error); + 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); + + g_static_mutex_unlock (&mutex); } /** @@ -615,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); } diff --git a/src/uca-plugin-manager.c b/src/uca-plugin-manager.c new file mode 100644 index 0000000..5678e83 --- /dev/null +++ b/src/uca-plugin-manager.c @@ -0,0 +1,327 @@ +/** + * 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_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 <gmodule.h> +#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; +}; + +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 + * @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)); +} + +/** + * 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) +{ + 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_module_paths (const gchar *path) +{ + GRegex *pattern; + GDir *dir; + GList *result = 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); + + while (name != NULL) { + 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); + } + } + + 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 +list_free_full (GList *list) +{ + g_list_foreach (list, (GFunc) g_free, NULL); + 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) +{ + 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); + + g_list_foreach (camera_paths, (GFunc) transform_camera_module_path_to_name, &camera_names); + 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); + } + + list_free_full (paths); + return result; +} + +/** + * uca_plugin_manager_new_camera: + * @manager: A #UcaPluginManager + * @name: Name of the camera module, that maps to libuca<name>.so + * @error: Location for a #GError + */ +UcaCamera * +uca_plugin_manager_new_camera (UcaPluginManager *manager, + const gchar *name, + GError **error) +{ + UcaPluginManagerPrivate *priv; + UcaCamera *camera; + GModule *module; + GetCameraFunc *func; + gchar *module_path; + GError *tmp_error = 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) +{ + 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; + 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"); + 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 <glib-object.h> +#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 diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index ce45d71..b579d1b 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -5,15 +5,10 @@ add_definitions("--std=c99 -Wall") # --- Find packages and libraries --------------------------------------------- find_package(PkgConfig) -pkg_check_modules(GTK2 gtk+-2.0>=2.22) -pkg_check_modules(GTHREAD2 gthread-2.0) pkg_check_modules(GLIB2 glib-2.0>=2.24 REQUIRED) pkg_check_modules(GOBJECT2 gobject-2.0>=2.24 REQUIRED) -#include_directories(${CMAKE_SOURCE_DIR}/src) - -configure_file(${CMAKE_CURRENT_SOURCE_DIR}/control.glade ${CMAKE_CURRENT_BINARY_DIR}) -configure_file(${CMAKE_CURRENT_SOURCE_DIR}/run.py ${CMAKE_CURRENT_BINARY_DIR}) +set(libs uca ${GLIB2_LIBRARIES} ${GOBJECT2_LIBRARIES}) # --- Build targets ----------------------------------------------------------- include_directories( @@ -23,64 +18,10 @@ include_directories( ${CMAKE_CURRENT_SOURCE_DIR}/../src ) -if (HAVE_PYLON_CAMERA) - set(GENICAM_ROOT $ENV{PYLON_ROOT}/genicam) - # check for 32/64 bit - if (CMAKE_SIZEOF_VOID_P EQUAL 8) - set(PYLON_LIB_DIRS $ENV{PYLON_ROOT}/lib64 $ENV{PYLON_ROOT}/bin ${GENICAM_ROOT}/bin/Linux64_x64 - ${GENICAM_ROOT}/bin/Linux64_x64/GenApi/Generic) - else() - set(PYLON_LIB_DIRS $ENV{PYLON_ROOT}/lib64 $ENV{PYLON_ROOT}/bin ${GENICAM_ROOT}/bin/Linux32_i86 - ${GENICAM_ROOT}/bin/Linux32_i86/GenApi/Generic) - endif() - link_directories(${PYLON_LIB_DIRS} ${LIBPYLONCAM_LIBDIR}) -endif() - -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-async uca ${GLIB2_LIBRARIES} ${GOBJECT2_LIBRARIES}) - -add_executable(grab_pylon grab_pylon.c) -target_link_libraries(grab_pylon uca ${GLIB2_LIBRARIES} ${GOBJECT2_LIBRARIES}) - -if (NOT DEFINED WITH_CONTROL_GUI) - set(WITH_CONTROL_GUI TRUE) -endif() - -if (GTK2_FOUND AND WITH_CONTROL_GUI) - include_directories(${GTK2_INCLUDE_DIRS}) - - add_executable(control - control.c - egg-property-cell-renderer.c - egg-property-tree-view.c) - - target_link_libraries(control uca - ${GTK2_LIBRARIES} ${GTHREAD2_LIBRARIES}) - - install(TARGETS control - RUNTIME DESTINATION bin) - - install(FILES control.glade - DESTINATION share/libuca) -endif() - if (HAVE_MOCK_CAMERA) add_executable(test-mock test-mock.c) - - target_link_libraries(test-mock - uca - ${GLIB2_LIBRARIES} - ${GOBJECT2_LIBRARIES}) + target_link_libraries(test-mock ${libs}) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/gtester.xsl - ${CMAKE_CURRENT_BINARY_DIR}/gtester.xsl) + ${CMAKE_CURRENT_BINARY_DIR}/gtester.xsl) endif() - -add_executable(test-all test-all.c) -target_link_libraries(test-all uca - ${GLIB2_LIBRARIES} ${GOBJECT2_LIBRARIES}) diff --git a/test/control.c b/test/control.c deleted file mode 100644 index eaa88e3..0000000 --- a/test/control.c +++ /dev/null @@ -1,336 +0,0 @@ -/* Copyright (C) 2011, 2012 Matthias Vogelgesang <matthias.vogelgesang@kit.edu> - (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 <glib/gprintf.h> -#include <gtk/gtk.h> -#include <gdk/gdk.h> -#include <gdk/gdkkeysyms.h> -#include <string.h> -#include <time.h> -#include <unistd.h> -#include <errno.h> - -#include "config.h" -#include "uca-camera.h" -#include "egg-property-tree-view.h" - - -typedef struct { - gboolean running; - gboolean store; - - guchar *buffer, *pixels; - GdkPixbuf *pixbuf; - GtkWidget *image; - GtkTreeModel *property_model; - UcaCamera *camera; - - GtkStatusbar *statusbar; - guint statusbar_context_id; - - int timestamp; - int width; - int height; - int pixel_size; -} ThreadData; - -typedef struct { - ThreadData *thread_data; - GtkTreeStore *tree_store; -} ValueCellData; - -enum { - COLUMN_NAME = 0, - COLUMN_VALUE, - COLUMN_EDITABLE, - NUM_COLUMNS -}; - - -static void convert_8bit_to_rgb(guchar *output, guchar *input, int width, int height) -{ - for (int i = 0, j = 0; i < width*height; i++) { - output[j++] = input[i]; - output[j++] = input[i]; - output[j++] = input[i]; - } -} - -static void convert_16bit_to_rgb(guchar *output, guchar *input, int width, int height) -{ - 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; - - 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; - } - } -} - -static void *grab_thread(void *args) -{ - ThreadData *data = (ThreadData *) args; - gchar filename[FILENAME_MAX] = {0,}; - gint counter = 0; - - while (data->running) { - uca_camera_grab(data->camera, (gpointer) &data->buffer, NULL); - - if (data->store) { - 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); - } - - /* FIXME: We should actually check if this is really a new frame and - * just do nothing if it is an already displayed one. */ - 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); - } - - 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); - gdk_threads_leave(); - } - return NULL; -} - -gboolean on_delete_event(GtkWidget *widget, GdkEvent *event, gpointer data) -{ - return FALSE; -} - -void on_destroy(GtkWidget *widget, gpointer data) -{ - ThreadData *td = (ThreadData *) data; - td->running = FALSE; - g_object_unref(td->camera); - gtk_main_quit(); -} - -static void on_toolbutton_run_clicked(GtkWidget *widget, gpointer args) -{ - ThreadData *data = (ThreadData *) args; - - if (data->running) - return; - - GError *error = NULL; - data->running = TRUE; - - uca_camera_start_recording(data->camera, &error); - - if (error != NULL) { - g_printerr("Failed to start recording: %s\n", error->message); - return; - } - - if (!g_thread_create(grab_thread, data, FALSE, &error)) { - g_printerr("Failed to create thread: %s\n", error->message); - return; - } -} - -static void on_toolbutton_stop_clicked(GtkWidget *widget, gpointer args) -{ - ThreadData *data = (ThreadData *) args; - data->running = FALSE; - data->store = FALSE; - GError *error = NULL; - uca_camera_stop_recording(data->camera, &error); - - if (error != NULL) - g_printerr("Failed to stop: %s\n", error->message); -} - -static void on_toolbutton_record_clicked(GtkWidget *widget, gpointer args) -{ - ThreadData *data = (ThreadData *) args; - data->timestamp = (int) time(0); - data->store = TRUE; - GError *error = NULL; - - gtk_statusbar_push(data->statusbar, data->statusbar_context_id, "Recording..."); - - if (data->running != TRUE) { - data->running = TRUE; - uca_camera_start_recording(data->camera, &error); - - if (!g_thread_create(grab_thread, data, FALSE, &error)) - g_printerr("Failed to create thread: %s\n", error->message); - } -} - -static void create_main_window(GtkBuilder *builder, const gchar* camera_name) -{ - static ThreadData td; - - GError *error = NULL; - UcaCamera *camera = uca_camera_new(camera_name, &error); - - if ((camera == NULL) || (error != NULL)) { - g_error("%s\n", error->message); - gtk_main_quit(); - } - - guint bits_per_sample; - g_object_get(camera, - "roi-width", &td.width, - "roi-height", &td.height, - "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")); - - 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); - gtk_image_set_from_pixbuf(GTK_IMAGE(image), pixbuf); - - td.pixel_size = bits_per_sample > 8 ? 2 : 1; - td.image = image; - td.pixbuf = pixbuf; - td.buffer = (guchar *) g_malloc(td.pixel_size * td.width * td.height); - td.pixels = gdk_pixbuf_get_pixels(pixbuf); - td.running = FALSE; - td.statusbar = GTK_STATUSBAR(gtk_builder_get_object(builder, "statusbar")); - td.statusbar_context_id = gtk_statusbar_get_context_id(td.statusbar, "Recording Information"); - td.store = FALSE; - td.camera = camera; - td.property_model = GTK_TREE_MODEL(gtk_builder_get_object(builder, "camera-properties")); - - g_signal_connect(window, "destroy", G_CALLBACK(on_destroy), &td); - g_signal_connect(gtk_builder_get_object(builder, "toolbutton_run"), - "clicked", G_CALLBACK(on_toolbutton_run_clicked), &td); - g_signal_connect(gtk_builder_get_object(builder, "toolbutton_stop"), - "clicked", G_CALLBACK(on_toolbutton_stop_clicked), &td); - g_signal_connect(gtk_builder_get_object(builder, "toolbutton_record"), - "clicked", G_CALLBACK(on_toolbutton_record_clicked), &td); - - gtk_widget_show(image); - gtk_widget_show(window); -} - -static void on_button_proceed_clicked(GtkWidget *widget, gpointer data) -{ - GtkBuilder *builder = GTK_BUILDER(data); - GtkWidget *choice_window = GTK_WIDGET(gtk_builder_get_object(builder, "choice-window")); - GtkTreeView *treeview = GTK_TREE_VIEW(gtk_builder_get_object(builder, "treeview-cameras")); - GtkListStore *list_store = GTK_LIST_STORE(gtk_builder_get_object(builder, "camera-types")); - - GtkTreeSelection *selection = gtk_tree_view_get_selection(treeview); - GList *selected_rows = gtk_tree_selection_get_selected_rows(selection, NULL); - GtkTreeIter iter; - - gtk_widget_destroy(choice_window); - gboolean valid = gtk_tree_model_get_iter(GTK_TREE_MODEL(list_store), &iter, selected_rows->data); - - if (valid) { - gchar *data; - gtk_tree_model_get(GTK_TREE_MODEL(list_store), &iter, 0, &data, -1); - create_main_window(builder, data); - g_free(data); - } - - g_list_foreach(selected_rows, (GFunc) gtk_tree_path_free, NULL); - g_list_free(selected_rows); -} - -static void on_treeview_keypress(GtkWidget *widget, GdkEventKey *event, gpointer data) -{ - if (event->keyval == GDK_KEY_Return) - gtk_widget_grab_focus(GTK_WIDGET(data)); -} - -static void create_choice_window(GtkBuilder *builder) -{ - gchar **camera_types = uca_camera_get_types(); - - GtkWidget *choice_window = GTK_WIDGET(gtk_builder_get_object(builder, "choice-window")); - GtkTreeView *treeview = GTK_TREE_VIEW(gtk_builder_get_object(builder, "treeview-cameras")); - GtkListStore *list_store = GTK_LIST_STORE(gtk_builder_get_object(builder, "camera-types")); - GtkButton *proceed_button = GTK_BUTTON(gtk_builder_get_object(builder, "button-proceed")); - GtkTreeIter iter; - - for (guint i = 0; camera_types[i] != NULL; i++) { - gtk_list_store_append(list_store, &iter); - gtk_list_store_set(list_store, &iter, 0, camera_types[i], -1); - } - - gboolean valid = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(list_store), &iter); - - if (valid) { - GtkTreeSelection *selection = gtk_tree_view_get_selection(treeview); - gtk_tree_selection_unselect_all(selection); - gtk_tree_selection_select_path(selection, gtk_tree_model_get_path(GTK_TREE_MODEL(list_store), &iter)); - } - - g_strfreev(camera_types); - g_signal_connect(proceed_button, "clicked", G_CALLBACK(on_button_proceed_clicked), builder); - g_signal_connect(treeview, "key-press-event", G_CALLBACK(on_treeview_keypress), proceed_button); - gtk_widget_show_all(GTK_WIDGET(choice_window)); -} - -int main(int argc, char *argv[]) -{ - GError *error = NULL; - - g_thread_init(NULL); - gdk_threads_init(); - gtk_init(&argc, &argv); - - GtkBuilder *builder = gtk_builder_new(); - - if (!gtk_builder_add_from_file(builder, CONTROL_GLADE_PATH, &error)) { - g_print("Error: %s\n", error->message); - return 1; - } - - create_choice_window(builder); - gtk_builder_connect_signals(builder, NULL); - - gdk_threads_enter(); - gtk_main(); - gdk_threads_leave(); - - return 0; -} diff --git a/test/enum.c b/test/enum.c deleted file mode 100644 index 75ca596..0000000 --- a/test/enum.c +++ /dev/null @@ -1,88 +0,0 @@ -/* Copyright (C) 2011, 2012 Matthias Vogelgesang <matthias.vogelgesang@kit.edu> - (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 <stdio.h> -#include "uca.h" - -int count_dots(const char *s) -{ - int res = 0; - while (*(s++) != '\0') - if (*s == '.') - res++; - return res; -} - -void print_level(int depth) -{ - for (int i = 0; i < depth; i++) - printf("| "); - printf("|-- "); -} - -int main(int argc, char *argv[]) -{ - uca *u = uca_init(NULL); - if (u == NULL) { - printf("Couldn't find a camera\n"); - return 1; - } - - /* take first camera */ - uca_camera *cam = u->cameras; - - const size_t num_bytes = 256; - char string_value[num_bytes]; - uint32_t uint32_value; - uint8_t uint8_value; - - while (cam != NULL) { - for (int i = 0; i < UCA_PROP_LAST; i++) { - uca_property *prop = uca_get_full_property(i); - print_level(count_dots(prop->name)); - printf("%s = ", prop->name); - switch (prop->type) { - case uca_string: - if (uca_cam_get_property(cam, i, string_value, num_bytes) == UCA_NO_ERROR) { - printf("%s ", string_value); - } - else - printf("n/a"); - break; - case uca_uint32t: - if (uca_cam_get_property(cam, i, &uint32_value, 0) == UCA_NO_ERROR) { - printf("%u %s", uint32_value, uca_unit_map[prop->unit]); - } - else - printf("n/a"); - break; - case uca_uint8t: - if (uca_cam_get_property(cam, i, &uint8_value, 0) == UCA_NO_ERROR) { - printf("%u %s", uint8_value, uca_unit_map[prop->unit]); - } - else - printf("n/a"); - break; - } - printf("\n"); - } - cam = cam->next; - } - - uca_destroy(u); - return 0; -} diff --git a/test/grab_pylon.c b/test/grab_pylon.c deleted file mode 100644 index 2f9b5a0..0000000 --- a/test/grab_pylon.c +++ /dev/null @@ -1,96 +0,0 @@ -/* Copyright (C) 2011, 2012 Matthias Vogelgesang <matthias.vogelgesang@kit.edu> - (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 <glib-object.h> -#include <signal.h> -#include <stdio.h> -#include <stdlib.h> -#include "uca-camera.h" - -#define handle_error(errno) {if ((errno) != UCA_NO_ERROR) printf("error at <%s:%i>\n", \ - __FILE__, __LINE__);} - -static UcaCamera *camera = NULL; - -void sigint_handler(int signal) -{ - printf("Closing down libuca\n"); - uca_camera_stop_recording(camera, NULL); - g_object_unref(camera); - exit(signal); -} - -int main(int argc, char *argv[]) -{ - GError *error = NULL; - (void) signal(SIGINT, sigint_handler); - - g_type_init(); - camera = uca_camera_new("pylon", &error); - - if (camera == NULL) { - g_print("Couldn't initialize camera\n"); - return 1; - } - - guint width, height, bits; - g_object_get(G_OBJECT(camera), - "sensor-width", &width, - "sensor-height", &height, - "sensor-bitdepth", &bits, - NULL); - - const int pixel_size = bits == 8 ? 1 : 2; - g_print("allocate buffer %u, %u, %d\n", width, height, pixel_size); - gpointer buffer = g_malloc0(width * height * pixel_size); - - gchar filename[FILENAME_MAX]; - - for (int i = 0; i < 2; i++) { - gint counter = 0; - g_print("Start recording\n"); - uca_camera_start_recording(camera, &error); - g_assert_no_error(error); - - while (counter < 10) { - g_print(" grab frame ... "); - uca_camera_grab(camera, &buffer, &error); - if (error != NULL) { - g_print("\nError: %s\n", error->message); - goto cleanup; - } - g_print("done\n"); - - snprintf(filename, FILENAME_MAX, "frame-%08i.raw", counter++); - FILE *fp = fopen(filename, "wb"); - fwrite(buffer, width*height, pixel_size, fp); - fclose(fp); - //g_usleep(2 * G_USEC_PER_SEC); - } - - g_print("Stop recording\n"); - uca_camera_stop_recording(camera, &error); - g_assert_no_error(error); - } - -cleanup: - uca_camera_stop_recording(camera, NULL); - g_object_unref(camera); - g_free(buffer); - - return error != NULL ? 1 : 0; -} diff --git a/test/perf-overhead.c b/test/perf-overhead.c deleted file mode 100644 index 20ca6c3..0000000 --- a/test/perf-overhead.c +++ /dev/null @@ -1,143 +0,0 @@ -/* Copyright (C) 2011, 2012 Matthias Vogelgesang <matthias.vogelgesang@kit.edu> - (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 <glib-object.h> -#include <signal.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include "uca-camera.h" - -#define handle_error(errno) {if ((errno) != UCA_NO_ERROR) printf("error at <%s:%i>\n", \ - __FILE__, __LINE__);} - -typedef struct { - guint counter; - gsize size; - gpointer destination; -} thread_data; - -static UcaCamera *camera = NULL; - -static void sigint_handler(int signal) -{ - printf("Closing down libuca\n"); - uca_camera_stop_recording(camera, NULL); - g_object_unref(camera); - exit(signal); -} - -static void test_synchronous_operation(UcaCamera *camera) -{ - GError *error = NULL; - guint width, height, bits; - g_object_get(G_OBJECT(camera), - "sensor-width", &width, - "sensor-height", &height, - "sensor-bitdepth", &bits, - NULL); - - const int pixel_size = bits == 8 ? 1 : 2; - const gsize size = width * height * pixel_size; - const guint n_trials = 10000; - gpointer buffer = g_malloc0(size); - - uca_camera_start_recording(camera, &error); - GTimer *timer = g_timer_new(); - - for (guint n = 0; n < n_trials; n++) - uca_camera_grab(camera, &buffer, &error); - - gdouble total_time = g_timer_elapsed(timer, NULL); - g_timer_stop(timer); - - g_print("Synchronous data transfer\n"); - g_print(" Bandwidth: %3.2f MB/s\n", size * n_trials / 1024. / 1024. / total_time); - g_print(" Throughput: %3.2f frames/s\n", n_trials / total_time); - - uca_camera_stop_recording(camera, &error); - g_free(buffer); - g_timer_destroy(timer); -} - -static void grab_func(gpointer data, gpointer user_data) -{ - static GStaticMutex mutex = G_STATIC_MUTEX_INIT; - - thread_data *d = (thread_data *) user_data; - g_memmove(d->destination, data, d->size); - g_static_mutex_lock(&mutex); - d->counter++; - g_static_mutex_unlock(&mutex); -} - -static void test_asynchronous_operation(UcaCamera *camera) -{ - GError *error = NULL; - guint width, height, bits; - - g_object_get(G_OBJECT(camera), - "sensor-width", &width, - "sensor-height", &height, - "sensor-bitdepth", &bits, - NULL); - - const guint pixel_size = bits == 8 ? 1 : 2; - - thread_data d = { - .counter = 0, - .size = width * height * pixel_size, - .destination = g_malloc0(width * height * pixel_size) - }; - - g_object_set(G_OBJECT(camera), - "transfer-asynchronously", TRUE, - NULL); - - uca_camera_set_grab_func(camera, &grab_func, &d); - uca_camera_start_recording(camera, &error); - g_usleep(G_USEC_PER_SEC); - uca_camera_stop_recording(camera, &error); - - g_print("Asynchronous data transfer\n"); - g_print(" Bandwidth: %3.2f MB/s\n", d.size * d.counter / 1024. / 1024.); - g_print(" Throughput: %i frames/s\n", d.counter); - - g_free(d.destination); -} - -int main(int argc, char *argv[]) -{ - GError *error = NULL; - (void) signal(SIGINT, sigint_handler); - - g_type_init(); - camera = uca_camera_new("mock", &error); - - if (camera == NULL) { - g_print("Couldn't initialize camera\n"); - return 1; - } - - test_synchronous_operation(camera); - g_print("\n"); - test_asynchronous_operation(camera); - - g_object_unref(camera); - - return error != NULL ? 1 : 0; -} diff --git a/test/run.py b/test/run.py deleted file mode 100755 index 7982617..0000000 --- a/test/run.py +++ /dev/null @@ -1,31 +0,0 @@ -#!/usr/bin/env python - -import Tkinter -import threading -import subprocess - -class App(object): - def __init__(self, parent): - self.parent = parent - self.canvas = Tkinter.Canvas(root, width=300, height=300) - self.canvas.pack() - self.rect = self.canvas.create_rectangle(0, 0, 300, 300, fill='yellow') - self.run_button = Tkinter.Button(parent, text='Start grabbing', command=self.run_click) - self.run_button.pack() - - def run_grab(self): - proc = subprocess.Popen(['./grab']) - proc.wait() - self.canvas.itemconfig(self.rect, fill='red') - self.run_button.config(state=Tkinter.NORMAL, text='Close', command=self.parent.destroy) - - def run_click(self): - self.canvas.itemconfig(self.rect, fill='green') - self.run_button.config(state=Tkinter.DISABLED) - thread = threading.Thread(None, self.run_grab) - thread.start() - -if __name__ == '__main__': - root = Tkinter.Tk() - app = App(root) - root.mainloop() diff --git a/test/test-all.c b/test/test-all.c deleted file mode 100644 index 9526d4f..0000000 --- a/test/test-all.c +++ /dev/null @@ -1,214 +0,0 @@ - -#include <glib.h> -#include "uca-camera.h" -#include "cameras/uca-mock-camera.h" - -typedef struct { - UcaCamera *camera; -} Fixture; - -typedef void (*UcaFixtureFunc) (Fixture *fixture, gconstpointer data); - -static void fixture_setup(Fixture *fixture, gconstpointer data) -{ - const gchar *type = (gchar *) data; - GError *error = NULL; - fixture->camera = uca_camera_new(type, &error); - g_assert_no_error(error); - g_assert(fixture->camera); -} - -static void fixture_teardown(Fixture *fixture, gconstpointer data) -{ - g_object_unref(fixture->camera); -} - -static void on_property_change(gpointer instance, GParamSpec *pspec, gpointer user_data) -{ - gboolean *success = (gboolean *) user_data; - *success = TRUE; -} - -static void test_factory() -{ - GError *error = NULL; - UcaCamera *camera = uca_camera_new("fox994m3a0yxmy", &error); - g_assert_error(error, UCA_CAMERA_ERROR, UCA_CAMERA_ERROR_NOT_FOUND); - g_assert(camera == NULL); -} - -static void test_recording(Fixture *fixture, gconstpointer data) -{ - GError *error = NULL; - UcaCamera *camera = UCA_CAMERA(fixture->camera); - - uca_camera_stop_recording(camera, &error); - g_assert_error(error, UCA_CAMERA_ERROR, UCA_CAMERA_ERROR_NOT_RECORDING); - g_error_free(error); - - error = NULL; - gboolean success = FALSE; - g_signal_connect(G_OBJECT(camera), "notify::is-recording", - (GCallback) on_property_change, &success); - uca_camera_start_recording(camera, &error); - g_assert_no_error(error); - g_assert(success == TRUE); - - success = FALSE; - uca_camera_stop_recording(camera, &error); - g_assert_no_error(error); - g_assert(success == TRUE); -} - -static void grab_func(gpointer data, gpointer user_data) -{ - gboolean *success = (gboolean *) user_data; - *success = TRUE; -} - -static void test_recording_async(Fixture *fixture, gconstpointer data) -{ - UcaCamera *camera = UCA_CAMERA(fixture->camera); - - gboolean success = FALSE; - uca_camera_set_grab_func(camera, grab_func, &success); - - gfloat max_frame_rate = 1.0f; - g_object_get(G_OBJECT(camera), - "sensor-max-frame-rate", &max_frame_rate, - NULL); - g_assert(max_frame_rate != 0.0f); - - g_object_set(G_OBJECT(camera), - "transfer-asynchronously", TRUE, - NULL); - - GError *error = NULL; - uca_camera_start_recording(camera, &error); - g_assert_no_error(error); - - const gulong sleep_time = G_USEC_PER_SEC / ((gulong) (max_frame_rate / 2.0f)); - g_usleep(sleep_time); - - uca_camera_stop_recording(camera, &error); - g_assert_no_error(error); - g_assert(success == TRUE); -} - -static void test_recording_grab(Fixture *fixture, gconstpointer data) -{ - UcaCamera *camera = UCA_CAMERA(fixture->camera); - GError *error = NULL; - gpointer frame = NULL; - - uca_camera_start_recording(camera, &error); - g_assert_no_error(error); - - uca_camera_grab(camera, &frame, &error); - g_assert_no_error(error); - g_assert(frame != NULL); - - uca_camera_stop_recording(camera, &error); - g_assert_no_error(error); -} - -static void test_recording_property(Fixture *fixture, gconstpointer data) -{ - UcaCamera *camera = UCA_CAMERA(fixture->camera); - - gboolean is_recording = FALSE; - uca_camera_start_recording(camera, NULL); - g_object_get(G_OBJECT(camera), - "is-recording", &is_recording, - NULL); - g_assert(is_recording == TRUE); - - uca_camera_stop_recording(camera, NULL); - g_object_get(G_OBJECT(camera), - "is-recording", &is_recording, - NULL); - g_assert(is_recording == FALSE); -} - -static void test_base_properties(Fixture *fixture, gconstpointer data) -{ - UcaCamera *camera = UCA_CAMERA(fixture->camera); - guint n_properties = 0; - GParamSpec **properties = g_object_class_list_properties(G_OBJECT_GET_CLASS(camera), &n_properties); - GValue val = {0}; - - for (guint i = 0; i < n_properties; i++) { - g_value_init(&val, properties[i]->value_type); - g_object_get_property(G_OBJECT(camera), properties[i]->name, &val); - g_value_unset(&val); - } - - g_free(properties); -} - -static void test_binnings_properties(Fixture *fixture, gconstpointer data) -{ - UcaCamera *camera = UCA_CAMERA(fixture->camera); - - GValueArray *array = NULL; - g_object_get(G_OBJECT(camera), - "sensor-horizontal-binnings", &array, - NULL); - - GValue *value = g_value_array_get_nth(array, 0); - g_assert(value != NULL); - g_assert(g_value_get_uint(value) == 1); -} - - -int main(int argc, char *argv[]) -{ - g_type_init(); - g_test_init(&argc, &argv, NULL); - g_test_bug_base("http://ufo.kit.edu/ufo/ticket"); - - g_test_add_func("/factory", test_factory); - - gchar **types = NULL; - types = argc > 1 ? argv + 1 : uca_camera_get_types(); - - /* - * paths and test_funcs MUST correspond! - */ - static const gchar *paths[] = { - "/recording", - "/recording/grab", - "/recording/asynchronous", - "/properties/base", - "/properties/recording", - "/properties/binnings", - NULL - }; - - static UcaFixtureFunc test_funcs[] = { - test_recording, - test_recording_grab, - test_recording_async, - test_base_properties, - test_recording_property, - test_binnings_properties, - }; - - for (guint i = 0; i < g_strv_length(types); i++) { - guint j = 0; - - while (paths[j] != NULL) { - gchar *new_path = g_strdup_printf("/%s%s", types[i], paths[j]); - g_test_add(new_path, Fixture, types[i], fixture_setup, test_funcs[j], fixture_teardown); - g_free(new_path); - j++; - } - } - - gint result = g_test_run(); - - if (argc == 1) - g_strfreev(types); - - return result; -} diff --git a/test/test-mock.c b/test/test-mock.c index 7594a3a..ca16c59 100644 --- a/test/test-mock.c +++ b/test/test-mock.c @@ -1,176 +1,195 @@ #include <glib.h> #include "uca-camera.h" -#include "cameras/uca-mock-camera.h" +#include "uca-plugin-manager.h" typedef struct { - UcaMockCamera *camera; + UcaPluginManager *manager; + UcaCamera *camera; } Fixture; -static void fixture_setup(Fixture *fixture, gconstpointer data) +static void +fixture_setup (Fixture *fixture, gconstpointer data) { GError *error = NULL; - fixture->camera = uca_mock_camera_new(&error); - g_assert(error == NULL); - g_assert(fixture->camera); + + 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); + g_assert (error == NULL); + g_assert (fixture->camera); } -static void fixture_teardown(Fixture *fixture, gconstpointer data) +static void +fixture_teardown (Fixture *fixture, gconstpointer data) { - g_object_unref(fixture->camera); + g_object_unref (fixture->camera); + g_object_unref (fixture->manager); } -static void on_property_change(gpointer instance, GParamSpec *pspec, gpointer user_data) +static void +on_property_change (gpointer instance, GParamSpec *pspec, gpointer user_data) { gboolean *success = (gboolean *) user_data; *success = TRUE; } -static void test_factory() +static void +test_factory (Fixture *fixture, gconstpointer data) { GError *error = NULL; - UcaCamera *camera = uca_camera_new("fox994m3a0yxmy", &error); - g_assert_error(error, UCA_CAMERA_ERROR, UCA_CAMERA_ERROR_NOT_FOUND); - g_assert(camera == NULL); + UcaCamera *camera = uca_plugin_manager_new_camera (fixture->manager, "fox994m3a0yxmy", &error); + g_assert_error (error, UCA_PLUGIN_MANAGER_ERROR, UCA_PLUGIN_MANAGER_ERROR_MODULE_NOT_FOUND); + g_assert (camera == NULL); } -static void test_recording(Fixture *fixture, gconstpointer data) +static void +test_recording (Fixture *fixture, gconstpointer data) { GError *error = NULL; - UcaCamera *camera = UCA_CAMERA(fixture->camera); + UcaCamera *camera = UCA_CAMERA (fixture->camera); - uca_camera_stop_recording(camera, &error); - g_assert_error(error, UCA_CAMERA_ERROR, UCA_CAMERA_ERROR_NOT_RECORDING); - g_error_free(error); + uca_camera_stop_recording (camera, &error); + g_assert_error (error, UCA_CAMERA_ERROR, UCA_CAMERA_ERROR_NOT_RECORDING); + g_error_free (error); error = NULL; - uca_camera_start_recording(camera, &error); - g_assert_no_error(error); - uca_camera_stop_recording(camera, &error); - g_assert_no_error(error); + uca_camera_start_recording (camera, &error); + g_assert_no_error (error); + uca_camera_stop_recording (camera, &error); + g_assert_no_error (error); } -static void test_recording_signal(Fixture *fixture, gconstpointer data) +static void +test_recording_signal (Fixture *fixture, gconstpointer data) { - UcaCamera *camera = UCA_CAMERA(fixture->camera); + UcaCamera *camera = UCA_CAMERA (fixture->camera); gboolean success = FALSE; - g_signal_connect(G_OBJECT(camera), "notify::is-recording", + g_signal_connect (G_OBJECT (camera), "notify::is-recording", (GCallback) on_property_change, &success); - uca_camera_start_recording(camera, NULL); - g_assert(success == TRUE); + uca_camera_start_recording (camera, NULL); + g_assert (success == TRUE); success = FALSE; - uca_camera_stop_recording(camera, NULL); - g_assert(success == TRUE); + uca_camera_stop_recording (camera, NULL); + g_assert (success == TRUE); } -static void grab_func(gpointer data, gpointer user_data) +static void +grab_func (gpointer data, gpointer user_data) { guint *count = (guint *) user_data; *count += 1; } -static void test_recording_async(Fixture *fixture, gconstpointer data) +static void +test_recording_async (Fixture *fixture, gconstpointer data) { - UcaCamera *camera = UCA_CAMERA(fixture->camera); + UcaCamera *camera = UCA_CAMERA (fixture->camera); guint count = 0; - uca_camera_set_grab_func(camera, grab_func, &count); + uca_camera_set_grab_func (camera, grab_func, &count); - g_object_set(G_OBJECT(camera), + g_object_set (G_OBJECT (camera), "frame-rate", 10.0, "transfer-asynchronously", TRUE, NULL); GError *error = NULL; - uca_camera_start_recording(camera, &error); - g_assert_no_error(error); + uca_camera_start_recording (camera, &error); + g_assert_no_error (error); /* * We sleep for an 1/8 of a second at 10 frames per second, thus we should * record 2 frames. */ - g_usleep(G_USEC_PER_SEC / 8); + g_usleep (G_USEC_PER_SEC / 8); - uca_camera_stop_recording(camera, &error); - g_assert_no_error(error); - g_assert_cmpint(count, ==, 2); + uca_camera_stop_recording (camera, &error); + g_assert_no_error (error); + g_assert_cmpint (count, ==, 2); } -static void test_recording_property(Fixture *fixture, gconstpointer data) +static void +test_recording_property (Fixture *fixture, gconstpointer data) { - UcaCamera *camera = UCA_CAMERA(fixture->camera); + UcaCamera *camera = UCA_CAMERA (fixture->camera); gboolean is_recording = FALSE; - uca_camera_start_recording(camera, NULL); - g_object_get(G_OBJECT(camera), + uca_camera_start_recording (camera, NULL); + g_object_get (G_OBJECT (camera), "is-recording", &is_recording, NULL); - g_assert(is_recording == TRUE); + g_assert (is_recording == TRUE); - uca_camera_stop_recording(camera, NULL); - g_object_get(G_OBJECT(camera), + uca_camera_stop_recording (camera, NULL); + g_object_get (G_OBJECT (camera), "is-recording", &is_recording, NULL); - g_assert(is_recording == FALSE); + g_assert (is_recording == FALSE); } -static void test_base_properties(Fixture *fixture, gconstpointer data) +static void +test_base_properties (Fixture *fixture, gconstpointer data) { - UcaCamera *camera = UCA_CAMERA(fixture->camera); + UcaCamera *camera = UCA_CAMERA (fixture->camera); guint n_properties = 0; - GParamSpec **properties = g_object_class_list_properties(G_OBJECT_GET_CLASS(camera), &n_properties); + GParamSpec **properties = g_object_class_list_properties (G_OBJECT_GET_CLASS (camera), &n_properties); GValue val = {0}; for (guint i = 0; i < n_properties; i++) { - g_value_init(&val, properties[i]->value_type); - g_object_get_property(G_OBJECT(camera), properties[i]->name, &val); - g_value_unset(&val); + g_value_init (&val, properties[i]->value_type); + g_object_get_property (G_OBJECT (camera), properties[i]->name, &val); + g_value_unset (&val); } - g_free(properties); + g_free (properties); } -static void test_binnings_properties(Fixture *fixture, gconstpointer data) +static void +test_binnings_properties (Fixture *fixture, gconstpointer data) { - UcaCamera *camera = UCA_CAMERA(fixture->camera); + UcaCamera *camera = UCA_CAMERA (fixture->camera); GValueArray *array = NULL; - g_object_get(G_OBJECT(camera), + g_object_get (G_OBJECT (camera), "sensor-horizontal-binnings", &array, NULL); - GValue *value = g_value_array_get_nth(array, 0); - g_assert(value != NULL); - g_assert(g_value_get_uint(value) == 1); + GValue *value = g_value_array_get_nth (array, 0); + g_assert (value != NULL); + g_assert (g_value_get_uint (value) == 1); } -static void test_signal(Fixture *fixture, gconstpointer data) +static void +test_signal (Fixture *fixture, gconstpointer data) { - UcaCamera *camera = UCA_CAMERA(fixture->camera); + UcaCamera *camera = UCA_CAMERA (fixture->camera); gboolean success = FALSE; - g_signal_connect(camera, "notify::frame-rate", (GCallback) on_property_change, &success); - g_object_set(G_OBJECT(camera), + g_signal_connect (camera, "notify::frame-rate", (GCallback) on_property_change, &success); + g_object_set (G_OBJECT (camera), "frame-rate", 30.0, NULL); - g_assert(success == TRUE); + g_assert (success == TRUE); } -int main(int argc, char *argv[]) +int main (int argc, char *argv[]) { - g_type_init(); - g_test_init(&argc, &argv, NULL); - g_test_bug_base("http://ufo.kit.edu/ufo/ticket"); - - g_test_add_func("/factory", test_factory); - g_test_add("/recording", Fixture, NULL, fixture_setup, test_recording, fixture_teardown); - g_test_add("/recording/signal", Fixture, NULL, fixture_setup, test_recording_signal, fixture_teardown); - g_test_add("/recording/asynchronous", Fixture, NULL, fixture_setup, test_recording_async, fixture_teardown); - 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("/signal", Fixture, NULL, fixture_setup, test_signal, fixture_teardown); - - return g_test_run(); + g_type_init (); + + g_test_init (&argc, &argv, NULL); + g_test_bug_base ("http://ufo.kit.edu/ufo/ticket"); + + g_test_add ("/factory", Fixture, NULL, fixture_setup, test_factory, fixture_teardown); + g_test_add ("/recording", Fixture, NULL, fixture_setup, test_recording, fixture_teardown); + g_test_add ("/recording/signal", Fixture, NULL, fixture_setup, test_recording_signal, fixture_teardown); + g_test_add ("/recording/asynchronous", Fixture, NULL, fixture_setup, test_recording_async, fixture_teardown); + 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 ("/signal", Fixture, NULL, fixture_setup, test_signal, fixture_teardown); + + return g_test_run (); } diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt new file mode 100644 index 0000000..0e4d28e --- /dev/null +++ b/tools/CMakeLists.txt @@ -0,0 +1,36 @@ +cmake_minimum_required(VERSION 2.8) + +add_definitions("--std=c99 -Wall") + +# --- Find packages and libraries --------------------------------------------- +find_package(PkgConfig) + +pkg_check_modules(GLIB2 glib-2.0>=2.24 REQUIRED) +pkg_check_modules(GOBJECT2 gobject-2.0>=2.24 REQUIRED) + +# --- Build targets ----------------------------------------------------------- +include_directories( + ${GLIB2_INCLUDE_DIRS} + ${GOBJECT2_INCLUDE_DIRS} + ${CMAKE_CURRENT_BINARY_DIR}/../src/ + ${CMAKE_CURRENT_SOURCE_DIR}/../src + ) + +set(libs uca ${GLIB2_LIBRARIES} ${GOBJECT2_LIBRARIES}) + +add_executable(gen-doc gen-doc.c) +target_link_libraries(gen-doc ${libs}) + +add_executable(grab grab.c) +target_link_libraries(grab ${libs}) + +add_executable(grab-async grab-async.c) +target_link_libraries(grab-async ${libs}) + +add_executable(benchmark benchmark.c) +target_link_libraries(benchmark ${libs}) + +add_executable(perf perf-overhead.c) +target_link_libraries(perf ${libs}) + +add_subdirectory(gui) diff --git a/test/benchmark.c b/tools/benchmark.c index 0b4f6f8..ef99fd1 100644 --- a/test/benchmark.c +++ b/tools/benchmark.c @@ -20,6 +20,7 @@ #include <string.h> #include <stdlib.h> #include "uca-camera.h" +#include "uca-plugin-manager.h" typedef void (*GrabFrameFunc) (UcaCamera *camera, gpointer buffer, guint n_frames); @@ -37,20 +38,25 @@ sigint_handler(int signal) static void print_usage (void) { - gchar **types; + GList *types; + UcaPluginManager *manager; - g_print ("Usage: benchmark ("); - types = uca_camera_get_types (); + manager = uca_plugin_manager_new (); + g_print ("Usage: benchmark [ "); + types = uca_plugin_manager_get_available_cameras (manager); - for (guint i = 0; types[i] != NULL; i++) { - if (types[i+1] == NULL) - g_print ("%s)", types[i]); - else - g_print ("%s | ", types[i]); + 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); + } } static void @@ -227,10 +233,12 @@ benchmark (UcaCamera *camera) int main (int argc, char *argv[]) { + UcaPluginManager *manager; GIOChannel *log_channel; GError *error = NULL; (void) signal (SIGINT, sigint_handler); + g_type_init(); if (argc < 2) { print_usage(); @@ -241,8 +249,8 @@ main (int argc, char *argv[]) g_assert_no_error (error); g_log_set_handler (NULL, G_LOG_LEVEL_MASK, log_handler, log_channel); - 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_error ("Initialization: %s", error->message); diff --git a/tools/gen-doc.c b/tools/gen-doc.c new file mode 100644 index 0000000..d9b6b41 --- /dev/null +++ b/tools/gen-doc.c @@ -0,0 +1,151 @@ +/* Copyright (C) 2012 Matthias Vogelgesang <matthias.vogelgesang@kit.edu> + (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 <glib-object.h> +#include "uca-plugin-manager.h" +#include "uca-camera.h" + + +static void +print_usage (void) +{ + GList *types; + UcaPluginManager *manager; + + manager = uca_plugin_manager_new (); + g_print ("Usage: gen-doc [ "); + types = uca_plugin_manager_get_available_cameras (manager); + + if (types == NULL) { + g_print ("] -- no camera plugin found\n"); + return; + } + + 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); + } +} + +static const gchar * +get_flags_description (GParamSpec *pspec) +{ + static const gchar *descriptions[] = { + "", + "Read-only", + "Write-only", + "Read / Write", + "" + }; + + if (pspec->flags >= 3) + return descriptions[3]; + + return descriptions[pspec->flags]; +} + +static void +print_property_toc (GParamSpec **pspecs, guint n_props) +{ + g_print ("<h2>Properties</h2><ul id=\"toc\">"); + + for (guint i = 0; i < n_props; i++) { + GParamSpec *pspec = pspecs[i]; + const gchar *name = g_param_spec_get_name (pspec); + + g_print ("<li><code><a href=#%s>\"%s\"</a></code></li>", name, name); + } + + g_print ("</ul>"); +} + +static void +print_property_descriptions (GParamSpec **pspecs, guint n_props) +{ + g_print ("<h2>Details</h2><dl>"); + + for (guint i = 0; i < n_props; i++) { + GParamSpec *pspec = pspecs[i]; + const gchar *name = g_param_spec_get_name (pspec); + + g_print ("<dt id=\"%s\"><a href=\"#toc\">%s</a></dt>\n", name, name); + g_print ("<dd>"); + g_print ("<pre><code class=\"prop-type\">\"%s\" : %s : %s</code></pre>\n", + name, + g_type_name (pspec->value_type), + get_flags_description (pspec)); + g_print ("<p>%s</p>\n", g_param_spec_get_blurb (pspec)); + g_print ("</dd>"); + } + + g_print ("</dl>"); +} + +static void +print_properties (UcaCamera *camera) +{ + GObjectClass *oclass; + GParamSpec **pspecs; + guint n_props; + + oclass = G_OBJECT_GET_CLASS (camera); + pspecs = g_object_class_list_properties (oclass, &n_props); + + print_property_toc (pspecs, n_props); + print_property_descriptions (pspecs, n_props); + + g_free (pspecs); +} + +static const gchar *html_header = "<html><head>\ +<link rel=\"stylesheet\" href=\"style.css\" type=\"text/css\" />\ +<link href='http://fonts.googleapis.com/css?family=Droid+Sans:400,700|Droid+Serif:400,400italic|Inconsolata' rel='stylesheet' type='text/css'>\ +<title>%s — properties</title></head><body>"; +static const gchar *html_footer = "</body></html>"; + +int main(int argc, char *argv[]) +{ + UcaPluginManager *manager; + UcaCamera *camera; + GError *error = NULL; + + g_type_init(); + + if (argc < 2) { + print_usage(); + return 1; + } + + 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); + return 1; + } + + g_print (html_header, argv[1]); + g_print ("<div id=\"header\"><h1 class=\"title\">Property documentation of %s</h1>", argv[1]); + print_properties (camera); + g_print ("%s\n", html_footer); + + g_object_unref (camera); + g_object_unref (manager); +} diff --git a/test/grab-async.c b/tools/grab-async.c index e1ec114..6132829 100644 --- a/test/grab-async.c +++ b/tools/grab-async.c @@ -19,6 +19,7 @@ #include <signal.h> #include <stdio.h> #include <stdlib.h> +#include "uca-plugin-manager.h" #include "uca-camera.h" static UcaCamera *camera = NULL; @@ -29,7 +30,8 @@ typedef struct { guint counter; } CallbackData; -static void sigint_handler(int signal) +static void +sigint_handler(int signal) { printf("Closing down libuca\n"); uca_camera_stop_recording(camera, NULL); @@ -37,7 +39,8 @@ static void sigint_handler(int signal) exit(signal); } -static void grab_callback(gpointer data, gpointer user_data) +static void +grab_callback(gpointer data, gpointer user_data) { CallbackData *cbd = (CallbackData *) user_data; gchar *filename = g_strdup_printf("frame-%04i.raw", cbd->counter++); @@ -49,16 +52,49 @@ static void grab_callback(gpointer data, gpointer user_data) g_free(filename); } -int main(int argc, char *argv[]) +static void +print_usage (void) +{ + 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; + } + + 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[]) { CallbackData cbd; guint sensor_width, sensor_height; gchar *name; + UcaPluginManager *manager; GError *error = NULL; (void) signal(SIGINT, sigint_handler); g_type_init(); - camera = uca_camera_new("pco", &error); + + if (argc < 2) { + print_usage(); + return 1; + } + + 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); diff --git a/test/grab.c b/tools/grab.c index 41e6d88..1f5c917 100644 --- a/test/grab.c +++ b/tools/grab.c @@ -19,6 +19,7 @@ #include <signal.h> #include <stdio.h> #include <stdlib.h> +#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); @@ -100,7 +110,7 @@ int main(int argc, char *argv[]) g_free(name); g_print("Sensor: %ix%i px\n", sensor_width, sensor_height); - g_print("ROI: %ix%i @ (%i, %i), steps: %i, %i\n", + g_print("ROI: %ix%i @ (%i, %i), steps: %i, %i\n", roi_width, roi_height, roi_x, roi_y, roi_width_multiplier, roi_height_multiplier); const int pixel_size = bits == 8 ? 1 : 2; diff --git a/tools/gui/CMakeLists.txt b/tools/gui/CMakeLists.txt new file mode 100644 index 0000000..39afe98 --- /dev/null +++ b/tools/gui/CMakeLists.txt @@ -0,0 +1,39 @@ +cmake_minimum_required(VERSION 2.8) + +add_definitions("--std=c99 -Wall") + +# --- Find packages and libraries --------------------------------------------- +find_package(PkgConfig) + +pkg_check_modules(GTK2 gtk+-2.0>=2.22) +pkg_check_modules(GTHREAD2 gthread-2.0) +pkg_check_modules(GLIB2 glib-2.0>=2.24 REQUIRED) +pkg_check_modules(GOBJECT2 gobject-2.0>=2.24 REQUIRED) + +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/control.glade ${CMAKE_CURRENT_BINARY_DIR}) + +# --- Build targets ----------------------------------------------------------- +include_directories( + ${GLIB2_INCLUDE_DIRS} + ${GOBJECT2_INCLUDE_DIRS} + ${CMAKE_CURRENT_BINARY_DIR}/../../src/ + ${CMAKE_CURRENT_SOURCE_DIR}/../../src + ) + +if (GTK2_FOUND) + include_directories(${GTK2_INCLUDE_DIRS}) + + add_executable(control + control.c + egg-property-cell-renderer.c + egg-property-tree-view.c) + + target_link_libraries(control uca + ${GTK2_LIBRARIES} ${GTHREAD2_LIBRARIES}) + + install(TARGETS control + RUNTIME DESTINATION bin) + + install(FILES control.glade + DESTINATION share/libuca) +endif() diff --git a/tools/gui/control.c b/tools/gui/control.c new file mode 100644 index 0000000..75b3cde --- /dev/null +++ b/tools/gui/control.c @@ -0,0 +1,350 @@ +/* Copyright (C) 2011, 2012 Matthias Vogelgesang <matthias.vogelgesang@kit.edu> + (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 <glib/gprintf.h> +#include <gtk/gtk.h> +#include <gdk/gdk.h> +#include <gdk/gdkkeysyms.h> +#include <string.h> +#include <time.h> +#include <unistd.h> +#include <errno.h> + +#include "config.h" +#include "uca-camera.h" +#include "uca-plugin-manager.h" +#include "egg-property-tree-view.h" + + +typedef struct { + gboolean running; + gboolean store; + + guchar *buffer, *pixels; + GdkPixbuf *pixbuf; + GtkWidget *image; + GtkTreeModel *property_model; + UcaCamera *camera; + + GtkStatusbar *statusbar; + guint statusbar_context_id; + + int timestamp; + int width; + int height; + 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) +{ + for (int i = 0, j = 0; i < width*height; i++) { + output[j++] = input[i]; + output[j++] = input[i]; + output[j++] = input[i]; + } +} + +static void +convert_16bit_to_rgb (guchar *output, guchar *input, int width, int height) +{ + 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; + + 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; + } + } +} + +static void * +grab_thread (void *args) +{ + ThreadData *data = (ThreadData *) args; + gchar filename[FILENAME_MAX] = {0,}; + gint counter = 0; + + while (data->running) { + uca_camera_grab (data->camera, (gpointer) &data->buffer, NULL); + + if (data->store) { + 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); + } + + /* FIXME: We should actually check if this is really a new frame and + * just do nothing if it is an already displayed one. */ + 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); + } + + 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); + gdk_threads_leave (); + } + return NULL; +} + +gboolean +on_delete_event (GtkWidget *widget, GdkEvent *event, gpointer data) +{ + return FALSE; +} + +void +on_destroy (GtkWidget *widget, gpointer data) +{ + ThreadData *td = (ThreadData *) data; + td->running = FALSE; + g_object_unref (td->camera); + gtk_main_quit (); +} + +static void +on_toolbutton_run_clicked (GtkWidget *widget, gpointer args) +{ + ThreadData *data = (ThreadData *) args; + + if (data->running) + return; + + GError *error = NULL; + data->running = TRUE; + + uca_camera_start_recording (data->camera, &error); + + if (error != NULL) { + g_printerr ("Failed to start recording: %s\n", error->message); + return; + } + + if (!g_thread_create (grab_thread, data, FALSE, &error)) { + g_printerr ("Failed to create thread: %s\n", error->message); + return; + } +} + +static void +on_toolbutton_stop_clicked (GtkWidget *widget, gpointer args) +{ + ThreadData *data = (ThreadData *) args; + data->running = FALSE; + data->store = FALSE; + GError *error = NULL; + uca_camera_stop_recording (data->camera, &error); + + if (error != NULL) + g_printerr ("Failed to stop: %s\n", error->message); +} + +static void +on_toolbutton_record_clicked (GtkWidget *widget, gpointer args) +{ + ThreadData *data = (ThreadData *) args; + data->timestamp = (int) time (0); + data->store = TRUE; + GError *error = NULL; + + gtk_statusbar_push (data->statusbar, data->statusbar_context_id, "Recording..."); + + if (data->running != TRUE) { + data->running = TRUE; + uca_camera_start_recording (data->camera, &error); + + if (!g_thread_create (grab_thread, data, FALSE, &error)) + g_printerr ("Failed to create thread: %s\n", error->message); + } +} + +static void +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); + + if ((camera == NULL) || (error != NULL)) { + g_error ("%s\n", error->message); + gtk_main_quit (); + } + + guint bits_per_sample; + g_object_get (camera, + "roi-width", &td.width, + "roi-height", &td.height, + "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")); + + 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); + gtk_image_set_from_pixbuf (GTK_IMAGE (image), pixbuf); + + td.pixel_size = bits_per_sample > 8 ? 2 : 1; + td.image = image; + td.pixbuf = pixbuf; + td.buffer = (guchar *) g_malloc (td.pixel_size * td.width * td.height); + td.pixels = gdk_pixbuf_get_pixels (pixbuf); + td.running = FALSE; + td.statusbar = GTK_STATUSBAR (gtk_builder_get_object (builder, "statusbar")); + td.statusbar_context_id = gtk_statusbar_get_context_id (td.statusbar, "Recording Information"); + td.store = FALSE; + td.camera = camera; + td.property_model = GTK_TREE_MODEL (gtk_builder_get_object (builder, "camera-properties")); + + g_signal_connect (window, "destroy", G_CALLBACK (on_destroy), &td); + g_signal_connect (gtk_builder_get_object (builder, "toolbutton_run"), + "clicked", G_CALLBACK (on_toolbutton_run_clicked), &td); + g_signal_connect (gtk_builder_get_object (builder, "toolbutton_stop"), + "clicked", G_CALLBACK (on_toolbutton_stop_clicked), &td); + g_signal_connect (gtk_builder_get_object (builder, "toolbutton_record"), + "clicked", G_CALLBACK (on_toolbutton_record_clicked), &td); + + gtk_widget_show (image); + gtk_widget_show (window); +} + +static void +on_button_proceed_clicked (GtkWidget *widget, gpointer data) +{ + GtkBuilder *builder = GTK_BUILDER (data); + GtkWidget *choice_window = GTK_WIDGET (gtk_builder_get_object (builder, "choice-window")); + GtkTreeView *treeview = GTK_TREE_VIEW (gtk_builder_get_object (builder, "treeview-cameras")); + GtkListStore *list_store = GTK_LIST_STORE (gtk_builder_get_object (builder, "camera-types")); + + GtkTreeSelection *selection = gtk_tree_view_get_selection (treeview); + GList *selected_rows = gtk_tree_selection_get_selected_rows (selection, NULL); + GtkTreeIter iter; + + gtk_widget_destroy (choice_window); + gboolean valid = gtk_tree_model_get_iter (GTK_TREE_MODEL (list_store), &iter, selected_rows->data); + + if (valid) { + gchar *data; + gtk_tree_model_get (GTK_TREE_MODEL (list_store), &iter, 0, &data, -1); + create_main_window (builder, data); + g_free (data); + } + + g_list_foreach (selected_rows, (GFunc) gtk_tree_path_free, NULL); + g_list_free (selected_rows); +} + +static void +on_treeview_keypress (GtkWidget *widget, GdkEventKey *event, gpointer data) +{ + if (event->keyval == GDK_KEY_Return) + gtk_widget_grab_focus (GTK_WIDGET (data)); +} + +static void +create_choice_window (GtkBuilder *builder) +{ + GList *camera_types = uca_plugin_manager_get_available_cameras (plugin_manager); + + GtkWidget *choice_window = GTK_WIDGET (gtk_builder_get_object (builder, "choice-window")); + GtkTreeView *treeview = GTK_TREE_VIEW (gtk_builder_get_object (builder, "treeview-cameras")); + GtkListStore *list_store = GTK_LIST_STORE (gtk_builder_get_object (builder, "camera-types")); + GtkButton *proceed_button = GTK_BUTTON (gtk_builder_get_object (builder, "button-proceed")); + GtkTreeIter iter; + + for (GList *it = g_list_first (camera_types); it != NULL; it = g_list_next (it)) { + gtk_list_store_append (list_store, &iter); + gtk_list_store_set (list_store, &iter, 0, g_strdup ((gchar *) it->data), -1); + } + + gboolean valid = gtk_tree_model_get_iter_first (GTK_TREE_MODEL (list_store), &iter); + + if (valid) { + GtkTreeSelection *selection = gtk_tree_view_get_selection (treeview); + gtk_tree_selection_unselect_all (selection); + gtk_tree_selection_select_path (selection, gtk_tree_model_get_path (GTK_TREE_MODEL (list_store), &iter)); + } + + g_signal_connect (proceed_button, "clicked", G_CALLBACK (on_button_proceed_clicked), builder); + g_signal_connect (treeview, "key-press-event", G_CALLBACK (on_treeview_keypress), proceed_button); + gtk_widget_show_all (GTK_WIDGET (choice_window)); + + g_list_foreach (camera_types, (GFunc) g_free, NULL); + g_list_free (camera_types); +} + +int +main (int argc, char *argv[]) +{ + GError *error = NULL; + + g_thread_init (NULL); + gdk_threads_init (); + gtk_init (&argc, &argv); + + GtkBuilder *builder = gtk_builder_new (); + + if (!gtk_builder_add_from_file (builder, CONTROL_GLADE_PATH, &error)) { + g_print ("Error: %s\n", error->message); + return 1; + } + + plugin_manager = uca_plugin_manager_new (); + create_choice_window (builder); + gtk_builder_connect_signals (builder, NULL); + + gdk_threads_enter (); + gtk_main (); + gdk_threads_leave (); + + g_object_unref (plugin_manager); + return 0; +} diff --git a/test/control.glade b/tools/gui/control.glade index d7ba2fc..d7ba2fc 100644 --- a/test/control.glade +++ b/tools/gui/control.glade diff --git a/test/egg-property-cell-renderer.c b/tools/gui/egg-property-cell-renderer.c index 9df5cc3..9df5cc3 100644 --- a/test/egg-property-cell-renderer.c +++ b/tools/gui/egg-property-cell-renderer.c diff --git a/test/egg-property-cell-renderer.h b/tools/gui/egg-property-cell-renderer.h index d4dbe02..d4dbe02 100644 --- a/test/egg-property-cell-renderer.h +++ b/tools/gui/egg-property-cell-renderer.h diff --git a/test/egg-property-tree-view.c b/tools/gui/egg-property-tree-view.c index f4ed2fb..52d1e10 100644 --- a/test/egg-property-tree-view.c +++ b/tools/gui/egg-property-tree-view.c @@ -111,4 +111,3 @@ egg_property_tree_view_init (EggPropertyTreeView *tree_view) tree_view->priv = priv = EGG_PROPERTY_TREE_VIEW_GET_PRIVATE (tree_view); priv->list_store = gtk_list_store_new (N_COLUMNS, G_TYPE_STRING, G_TYPE_BOOLEAN, GTK_TYPE_ADJUSTMENT); } - diff --git a/test/egg-property-tree-view.h b/tools/gui/egg-property-tree-view.h index e8fd0fe..e8fd0fe 100644 --- a/test/egg-property-tree-view.h +++ b/tools/gui/egg-property-tree-view.h diff --git a/tools/perf-overhead.c b/tools/perf-overhead.c new file mode 100644 index 0000000..f8bdcbd --- /dev/null +++ b/tools/perf-overhead.c @@ -0,0 +1,181 @@ +/* Copyright (C) 2011, 2012 Matthias Vogelgesang <matthias.vogelgesang@kit.edu> + (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 <glib-object.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "uca-plugin-manager.h" +#include "uca-camera.h" + +#define handle_error(errno) {if ((errno) != UCA_NO_ERROR) printf("error at <%s:%i>\n", \ + __FILE__, __LINE__);} + +typedef struct { + guint counter; + gsize size; + gpointer destination; +} thread_data; + +static UcaCamera *camera = NULL; + +static void +sigint_handler (int signal) +{ + printf ("Closing down libuca\n"); + uca_camera_stop_recording (camera, NULL); + g_object_unref (camera); + exit (signal); +} + +static void +print_usage (void) +{ + 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; + } + + 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); + } +} + +static void +test_synchronous_operation (UcaCamera *camera) +{ + GError *error = NULL; + guint width, height, bits; + g_object_get (G_OBJECT (camera), + "sensor-width", &width, + "sensor-height", &height, + "sensor-bitdepth", &bits, + NULL); + + const int pixel_size = bits == 8 ? 1 : 2; + const gsize size = width * height * pixel_size; + const guint n_trials = 10000; + gpointer buffer = g_malloc0(size); + + uca_camera_start_recording (camera, &error); + GTimer *timer = g_timer_new (); + + for (guint n = 0; n < n_trials; n++) + uca_camera_grab (camera, &buffer, &error); + + gdouble total_time = g_timer_elapsed (timer, NULL); + g_timer_stop (timer); + + g_print ("Synchronous data transfer\n"); + g_print (" Bandwidth: %3.2f MB/s\n", size * n_trials / 1024. / 1024. / total_time); + g_print (" Throughput: %3.2f frames/s\n", n_trials / total_time); + + uca_camera_stop_recording (camera, &error); + g_free (buffer); + g_timer_destroy (timer); +} + +static void +grab_func (gpointer data, gpointer user_data) +{ + static GStaticMutex mutex = G_STATIC_MUTEX_INIT; + + thread_data *d = (thread_data *) user_data; + g_memmove (d->destination, data, d->size); + g_static_mutex_lock (&mutex); + d->counter++; + g_static_mutex_unlock (&mutex); +} + +static void +test_asynchronous_operation (UcaCamera *camera) +{ + GError *error = NULL; + guint width, height, bits; + + g_object_get (G_OBJECT (camera), + "sensor-width", &width, + "sensor-height", &height, + "sensor-bitdepth", &bits, + NULL); + + const guint pixel_size = bits == 8 ? 1 : 2; + + thread_data d = { + .counter = 0, + .size = width * height * pixel_size, + .destination = g_malloc0(width * height * pixel_size) + }; + + g_object_set (G_OBJECT (camera), + "transfer-asynchronously", TRUE, + NULL); + + uca_camera_set_grab_func (camera, &grab_func, &d); + uca_camera_start_recording (camera, &error); + g_usleep (G_USEC_PER_SEC); + uca_camera_stop_recording (camera, &error); + + g_print ("Asynchronous data transfer\n"); + g_print (" Bandwidth: %3.2f MB/s\n", d.size * d.counter / 1024. / 1024.); + g_print (" Throughput: %i frames/s\n", d.counter); + + g_free (d.destination); +} + +int +main (int argc, char *argv[]) +{ + UcaPluginManager *manager; + GError *error = NULL; + (void) signal (SIGINT, sigint_handler); + + g_type_init (); + if (argc < 2) { + print_usage (); + return 1; + } + + 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); + return 1; + } + + test_synchronous_operation (camera); + g_print ("\n"); + test_asynchronous_operation (camera); + + g_object_unref (camera); + g_object_unref (manager); + + return error != NULL ? 1 : 0; +} |