diff options
-rw-r--r-- | .bzrignore | 1 | ||||
-rw-r--r-- | .gitignore | 16 | ||||
-rw-r--r-- | CMakeLists.txt | 12 | ||||
-rw-r--r-- | NEWS | 17 | ||||
-rw-r--r-- | docs/manual.md | 46 | ||||
-rw-r--r-- | docs/mock.html | 49 | ||||
-rw-r--r-- | docs/style.css | 7 | ||||
-rw-r--r-- | misc/README.rst | 29 | ||||
-rw-r--r-- | misc/opencv-2.2.0.patch | 374 | ||||
-rw-r--r-- | plugins/mock/uca-mock-camera.c | 93 | ||||
-rw-r--r-- | plugins/mock/uca-mock-camera.h | 2 | ||||
-rw-r--r-- | plugins/pco/uca-pco-camera.c | 314 | ||||
-rw-r--r-- | plugins/pco/uca-pco-camera.h | 4 | ||||
-rw-r--r-- | plugins/pf/uca-pf-camera.c | 178 | ||||
-rw-r--r-- | plugins/ufo/uca-ufo-camera.c | 323 | ||||
-rw-r--r-- | src/CMakeLists.txt | 5 | ||||
-rw-r--r-- | src/libuca.pc.in | 1 | ||||
-rw-r--r-- | src/scangobj.sh.in | 2 | ||||
-rw-r--r-- | src/uca-camera.c | 38 | ||||
-rw-r--r-- | src/uca-camera.h | 9 | ||||
-rw-r--r-- | src/uca-plugin-manager.c | 125 | ||||
-rw-r--r-- | src/uca-plugin-manager.h | 9 | ||||
-rw-r--r-- | src/uca.types.in | 3 | ||||
-rw-r--r-- | test/test-mock.c | 25 | ||||
-rw-r--r-- | tools/benchmark.c | 11 | ||||
-rw-r--r-- | tools/gen-doc.c | 83 | ||||
-rw-r--r-- | tools/grab-async.c | 2 | ||||
-rw-r--r-- | tools/grab.c | 4 | ||||
-rw-r--r-- | tools/gui/control.c | 30 | ||||
-rw-r--r-- | tools/perf-overhead.c | 2 |
30 files changed, 975 insertions, 839 deletions
diff --git a/.bzrignore b/.bzrignore deleted file mode 100644 index 6e92f57..0000000 --- a/.bzrignore +++ /dev/null @@ -1 +0,0 @@ -tags @@ -1,15 +1,17 @@ -CMakeFiles *~ *.cmake +*.orig +*.rpm +_CPack_Packages +build/ +CMakeFiles +install_manifest.txt +libuca.spec Makefile +src/config.h src/libuca.so* +tags test/ -libuca.spec -src/config.h -*.rpm -install_manifest.txt -_CPack_Packages -*.orig tools/benchmark tools/gen-doc tools/grab diff --git a/CMakeLists.txt b/CMakeLists.txt index 03abdad..39c421e 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 "1") -set(UCA_VERSION_PATCH "0") +set(UCA_VERSION_MINOR "2") +set(UCA_VERSION_PATCH "0dev") set(UCA_DESCRIPTION "Unified Camera Access") set(UCA_VERSION_STRING "${UCA_VERSION_MAJOR}.${UCA_VERSION_MINOR}.${UCA_VERSION_PATCH}") @@ -55,17 +55,21 @@ 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) +pkg_check_modules(GIO2 gio-2.0>=2.24 REQUIRED) include_directories( ${CMAKE_CURRENT_BINARY_DIR}/src ${CMAKE_CURRENT_SOURCE_DIR}/src ${GLIB2_INCLUDE_DIRS} - ${GOBJECT2_INCLUDE_DIRS}) + ${GOBJECT2_INCLUDE_DIRS} + ${GMODULE2_INCLUDE_DIRS} + ${GIO2_INCLUDE_DIRS}) set(UCA_DEPS ${GLIB2_LIBRARIES} ${GOBJECT2_LIBRARIES} - ${GMODULE2_LIBRARIES}) + ${GMODULE2_LIBRARIES} + ${GIO2_LIBRARIES}) add_subdirectory(src) add_subdirectory(plugins) @@ -1,3 +1,20 @@ +Changes in libuca 1.2 +===================== + +API break +--------- + +The interface of uca_camera_grab() has changed. The buffer must be provided as a +void pointer (or gpointer in GLib speak), _not_ the address of a void pointer. +Furthermore, uca_camera_grab() returns TRUE if grabbing an image was successful +and FALSE if not. + +The plugin manager does not call the plugins "constructor" function directly but +instantiates it via the GInitable initialization function. Therefore, all +plugins must implement initialization code in the objects init function and flag +errors in the init method from the GInitable interface. + + Changes in libuca 1.1 ===================== diff --git a/docs/manual.md b/docs/manual.md index 0dd9c66..85584df 100644 --- a/docs/manual.md +++ b/docs/manual.md @@ -185,22 +185,18 @@ To synchronously grab frames, first start the camera: g_assert_no_error (error); ~~~ -Now you have two options with regard to memory buffers. If you already have a -suitable sized buffer, just pass it to `uca_camera_grab`. Otherwise pass a -pointer pointing to `NULL` (this is different from a `NULL` pointer!). In this -case memory will be allocated for you: +Now, you have to allocate a suitably sized buffer and pass it to +`uca_camera_grab`. ~~~ {.c} - gpointer buffer_1 = NULL; /* A pointer pointing to NULL */ - gpointer buffer_2 = g_malloc0 (640 * 480 * 2); + gpointer buffer = g_malloc0 (640 * 480 * 2); - /* Memory will be allocated. Remember to free it! */ - uca_camera_grab (camera, &buffer_1, &error); - - /* Memory buffer will be used */ - uca_camera_grab (camera, &buffer_2, &error); + uca_camera_grab (camera, buffer, &error); ~~~ +You have to make sure that the buffer is large enough by querying the size of +the region of interest and the number of bits that are transferred. + ### Getting and setting camera parameters @@ -405,7 +401,7 @@ pm = Uca.PluginManager() print(pm.get_available_cameras()) # Load a camera -cam = pm.get_camera('pco') +cam = pm.get_camerav('pco', []) # You can read and write properties in two ways cam.set_properties(exposure_time=0.05) @@ -417,6 +413,32 @@ of the target language. For example with Python, the namespace prefix `uca_` becomes the module name `Uca` and dashes separating property names become underscores. +Integration with Numpy is relatively straightforward. The most important thing +is to get the data pointer from a Numpy array to pass it to `uca_camera_grab`: + +~~~ {.python} +import numpy as np + +def create_array_from(camera): + """Create a suitably sized Numpy array and return it together with the + arrays data pointer""" + bits = camera.props.sensor_bitdepth + dtype = np.uint16 if bits > 8 else np.uint8 + a = np.zeros((cam.props.roi_height, cam.props.roi_width), dtype=dtype) + return a, a.__array_interface__['data'][0] + +# Suppose 'camera' is a already available, you would get the camera data like +# this: +a, buf = create_array_from(camera) +camera.start_recording() +camera.grab(buf) + +# Now data is in 'a' and we can use Numpy functions on it +print(np.mean(a)) + +camera.stop_recording() +~~~ + # Integrating new cameras diff --git a/docs/mock.html b/docs/mock.html index 0d38fc8..a2db94d 100644 --- a/docs/mock.html +++ b/docs/mock.html @@ -1,70 +1,73 @@ -<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> +<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>Basic camera — properties</title></head><body><div id="header"><h1 class="title">Property documentation of Basic camera</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=#frames-per-second>"frames-per-second"</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=#recorded-frames>"recorded-frames"</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></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> +<p>Possible values: 1 ≤ <em>sensor-width</em> ≤ -1</p><p>Default value: 1</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> +<p>Possible values: 1 ≤ <em>sensor-height</em> ≤ -1</p><p>Default value: 1</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> +<p>Possible values: 1 ≤ <em>sensor-bitdepth</em> ≤ 32</p><p>Default value: 1</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> +<p>Possible values: 1 ≤ <em>sensor-horizontal-binning</em> ≤ -1</p><p>Default value: 1</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> +<p>Possible values: 1 ≤ <em>sensor-vertical-binning</em> ≤ -1</p><p>Default value: 1</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> +<p>Possible values: 0.0e+00 ≤ <em>sensor-max-frame-rate</em> ≤ 3.4e+38</p><p>Default value: 1.0e+00</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> +<p>Possible values: <table><tr><th>Enum name</th><th>Value</th><tr><td><code>UCA_CAMERA_TRIGGER_AUTO</code></td><td>0</td></tr><tr><td><code>UCA_CAMERA_TRIGGER_SOFTWARE</code></td><td>1</td></tr><tr><td><code>UCA_CAMERA_TRIGGER_EXTERNAL</code></td><td>2</td></tr></table></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> +<p>Possible values: 0.0e+00 ≤ <em>exposure-time</em> ≤ 1.8e+308</p><p>Default value: 1.0e+00</p></dd><dt id="frames-per-second"><a href="#toc">frames-per-second</a></dt> +<dd><pre><code class="prop-type">"frames-per-second" : gdouble : Read / Write</code></pre> +<p>Frames per second</p> +<p>Possible values: 0.0e+00 ≤ <em>frames-per-second</em> ≤ 1.8e+308</p><p>Default value: 1.0e+00</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> +<p>Possible values: 0 ≤ <em>roi-x0</em> ≤ -1</p><p>Default value: 0</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> +<p>Possible values: 0 ≤ <em>roi-y0</em> ≤ -1</p><p>Default value: 0</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> +<p>Possible values: 1 ≤ <em>roi-width</em> ≤ -1</p><p>Default value: 1</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> +<p>Possible values: 1 ≤ <em>roi-height</em> ≤ -1</p><p>Default value: 1</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> +<p>Possible values: 1 ≤ <em>roi-width-multiplier</em> ≤ -1</p><p>Default value: 1</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> +<p>Possible values: 1 ≤ <em>roi-height-multiplier</em> ≤ -1</p><p>Default value: 1</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> +<p>Default value: <code>TRUE</code></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> +<p>Default value: <code>FALSE</code></p></dd><dt id="recorded-frames"><a href="#toc">recorded-frames</a></dt> +<dd><pre><code class="prop-type">"recorded-frames" : guint : Read-only</code></pre> +<p>Number of frames recorded into internal camera memory</p> +<p>Possible values: 0 ≤ <em>recorded-frames</em> ≤ -1</p><p>Default value: 0</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> +<p>Default value: <code>FALSE</code></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> +<p>Default value: <code>FALSE</code></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> +<p>Default value: <code>FALSE</code></p></dd></dl></body></html> diff --git a/docs/style.css b/docs/style.css index beccf45..41651e1 100644 --- a/docs/style.css +++ b/docs/style.css @@ -140,8 +140,9 @@ ol ol { } table { - width: 100%; + margin-top: 1em; margin-bottom: 24px; + padding: 1em; } th { @@ -152,7 +153,9 @@ th { } td, th { - padding: 2px; + padding-right: 1em; + padding-top: 0.5em; + padding-bottom: 0.5em; } dl { diff --git a/misc/README.rst b/misc/README.rst deleted file mode 100644 index baf0f22..0000000 --- a/misc/README.rst +++ /dev/null @@ -1,29 +0,0 @@ -================================ -Patches for third party software -================================ - -OpenCV -====== - -OpenCV is a cross-platform, open source computer vision toolkit. We provide -patches that integrate libuca in OpenCV in order to use all UCA-supported -cameras within OpenCV like:: - - CvCapture *capture = cvCaptureFromCAM(CV_CAP_UCA); - cvNamedWindow("foo", CV_WINDOW_AUTOSIZE); - - IplImage *frame; - frame = cvQueryFrame(capture); - cvShowImage("foo", frame); - - cvDestroyWindow("foo"); - cvReleaseCapture(&capture); - -Patches -------- - -We only supply patches for stable releases of OpenCV. Apply them using - - ``patch -p0 < opencv-x.y.z.patch`` - -inside the top-level directory of the source directory of OpenCV x.y.z. diff --git a/misc/opencv-2.2.0.patch b/misc/opencv-2.2.0.patch deleted file mode 100644 index f7297e9..0000000 --- a/misc/opencv-2.2.0.patch +++ /dev/null @@ -1,374 +0,0 @@ -=== modified file 'CMakeLists.txt' ---- CMakeLists.txt 2011-03-24 16:43:57 +0000 -+++ CMakeLists.txt 2011-03-25 08:34:03 +0000 -@@ -289,6 +289,7 @@ - set(WITH_GSTREAMER ON CACHE BOOL "Include Gstreamer support")
- set(WITH_V4L ON CACHE BOOL "Include Video 4 Linux support")
- set(WITH_XINE OFF CACHE BOOL "Include Xine support (GPL)")
-+ set(WITH_UCA OFF CACHE BOOL "Include Unified Camera Access support")
- endif()
- set(WITH_PVAPI ON CACHE BOOL "Include Prosilica GigE support")
- set(WITH_1394 ON CACHE BOOL "Include IEEE1394 support")
-@@ -437,6 +438,13 @@ - set(HAVE_CAMV4L2 FALSE)
- endif()
-
-+ if(WITH_UCA)
-+ CHECK_MODULE(uca HAVE_UCA)
-+ CHECK_INCLUDE_FILE(uca.h HAVE_UCA)
-+ else()
-+ set(HAVE_UCA FALSE)
-+ endif()
-+
- if(NOT OPENCV_BUILD_3RDPARTY_LIBS)
- if(WITH_PNG)
- include(FindPNG)
-@@ -1367,6 +1375,7 @@ - message(STATUS " V4L/V4L2: ${HAVE_CAMV4L}/${HAVE_CAMV4L2}")
- endif()
- message(STATUS " Xine: ${HAVE_XINE}")
-+message(STATUS " Unified Camera Access: ${HAVE_UCA}")
- endif()
-
- if(APPLE)
- -=== modified file 'cvconfig.h.cmake' ---- cvconfig.h.cmake 2011-03-24 16:43:57 +0000 -+++ cvconfig.h.cmake 2011-03-25 10:41:09 +0000 -@@ -31,6 +31,9 @@ - /* IEEE1394 capturing support - libdc1394 v2.x */ - #cmakedefine HAVE_DC1394_2 - -+/* Unified Camera Access - libuca 0.4.0 */ -+#cmakedefine HAVE_UCA -+ - /* ffmpeg in Gentoo */ - #cmakedefine HAVE_GENTOO_FFMPEG - - -=== modified file 'modules/highgui/CMakeLists.txt' ---- modules/highgui/CMakeLists.txt 2011-03-24 16:43:57 +0000 -+++ modules/highgui/CMakeLists.txt 2011-03-25 09:33:17 +0000 -@@ -118,6 +118,10 @@ - set(highgui_srcs ${highgui_srcs} src/cap_dc1394.cpp) - endif() - -+ if(HAVE_UCA) -+ set(highgui_srcs ${highgui_srcs} src/cap_uca.cpp) -+ endif() -+ - if(HAVE_FFMPEG) - set(highgui_srcs ${highgui_srcs} src/cap_ffmpeg.cpp) - if(BZIP2_LIBRARIES) - -=== modified file 'modules/highgui/include/opencv2/highgui/highgui_c.h' ---- modules/highgui/include/opencv2/highgui/highgui_c.h 2011-03-24 16:43:57 +0000 -+++ modules/highgui/include/opencv2/highgui/highgui_c.h 2011-03-25 08:55:31 +0000 -@@ -288,7 +288,9 @@ - - CV_CAP_DSHOW =700, // DirectShow (via videoInput) - -- CV_CAP_PVAPI =800 // PvAPI, Prosilica GigE SDK -+ CV_CAP_PVAPI =800, // PvAPI, Prosilica GigE SDK -+ -+ CV_CAP_UCA =900 // Unified Camera Access for CameraLink and IPE camera - }; - - /* start capturing frames from camera: index = camera_index + domain_offset (CV_CAP_*) */ - -=== modified file 'modules/highgui/src/cap.cpp' ---- modules/highgui/src/cap.cpp 2011-03-24 16:43:57 +0000 -+++ modules/highgui/src/cap.cpp 2011-03-25 10:39:36 +0000 -@@ -123,6 +123,7 @@ - CV_CAP_MIL, - CV_CAP_QT, - CV_CAP_UNICAP, -+ CV_CAP_UCA, - -1 - }; - -@@ -142,7 +143,7 @@ - defined(HAVE_CAMV4L) || defined (HAVE_CAMV4L2) || defined(HAVE_GSTREAMER) || \ - defined(HAVE_DC1394_2) || defined(HAVE_DC1394) || defined(HAVE_CMU1394) || \ - defined(HAVE_GSTREAMER) || defined(HAVE_MIL) || defined(HAVE_QUICKTIME) || \ -- defined(HAVE_UNICAP) || defined(HAVE_PVAPI) -+ defined(HAVE_UNICAP) || defined(HAVE_PVAPI) || defined(HAVE_UCA) - // local variable to memorize the captured device - CvCapture *capture; - #endif -@@ -168,7 +169,7 @@ - case CV_CAP_VFW: - #ifdef HAVE_VFW - capture = cvCreateCameraCapture_VFW (index); -- if (capture) -+ if (capture) - return capture; - #endif - #if defined (HAVE_CAMV4L) || defined (HAVE_CAMV4L2) -@@ -241,6 +242,14 @@ - return capture; - break; - #endif -+ -+ #ifdef HAVE_UCA -+ case CV_CAP_UCA: -+ capture = cvCreateCameraCapture_UCA (index); -+ if (capture) -+ return capture; -+ break; -+ #endif - - } - } - -=== added file 'modules/highgui/src/cap_uca.cpp' ---- modules/highgui/src/cap_uca.cpp 1970-01-01 00:00:00 +0000 -+++ modules/highgui/src/cap_uca.cpp 2011-03-25 11:31:07 +0000 -@@ -0,0 +1,234 @@ -+/*M/////////////////////////////////////////////////////////////////////////////////////// -+// -+// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. -+// -+// By downloading, copying, installing or using the software you agree to this license. -+// If you do not agree to this license, do not download, install, -+// copy or use the software. -+// -+// -+// Intel License Agreement -+// For Open Source Computer Vision Library -+// -+// Copyright (C) 2008, Nils Hasler, all rights reserved. -+// Third party copyrights are property of their respective owners. -+// -+// Redistribution and use in source and binary forms, with or without modification, -+// are permitted provided that the following conditions are met: -+// -+// * Redistribution's of source code must retain the above copyright notice, -+// this list of conditions and the following disclaimer. -+// -+// * Redistribution's in binary form must reproduce the above copyright notice, -+// this list of conditions and the following disclaimer in the documentation -+// and/or other materials provided with the distribution. -+// -+// * The name of Intel Corporation may not be used to endorse or promote products -+// derived from this software without specific prior written permission. -+// -+// This software is provided by the copyright holders and contributors "as is" and -+// any express or implied warranties, including, but not limited to, the implied -+// warranties of merchantability and fitness for a particular purpose are disclaimed. -+// In no event shall the Intel Corporation or contributors be liable for any direct, -+// indirect, incidental, special, exemplary, or consequential damages -+// (including, but not limited to, procurement of substitute goods or services; -+// loss of use, data, or profits; or business interruption) however caused -+// and on any theory of liability, whether in contract, strict liability, -+// or tort (including negligence or otherwise) arising in any way out of -+// the use of this software, even if advised of the possibility of such damage. -+// -+//M*/ -+ -+// Author: Matthias Vogelgesang <matthias.vogelgesang@kit.edu> -+// -+// Karlsruhe Institute of Technology (KIT) -+// Institute for Data Processing and Electronics -+// -+ -+ -+#include "precomp.hpp" -+#include <unistd.h> -+#include <string.h> -+#include <uca/uca.h> -+#include <uca/uca-cam.h> -+ -+#ifdef NDEBUG -+#define CV_WARN(message) -+#else -+#define CV_WARN(message) fprintf(stderr, "warning: %s (%s:%d)\n", message, __FILE__, __LINE__) -+#endif -+ -+static bool is_initialized = false; -+ -+class CvCapture_UCA : public CvCapture -+{ -+ public: -+ CvCapture_UCA() { init(); } -+ virtual ~CvCapture_UCA() { close(); } -+ -+ virtual bool open(int); -+ virtual void close(); -+ -+ virtual double getProperty(int); -+ virtual bool setProperty(int, double); -+ virtual bool grabFrame(); -+ virtual IplImage* retrieveFrame(int); -+ -+ protected: -+ void init(); -+ char *buffer; -+ IplImage *frame; -+ -+ private: -+ struct uca *uca_handle; -+ struct uca_camera *device; -+ int width; -+ int height; -+ int bit_depth; // in terms of IplImage structure -+ int pixel_size; -+}; -+ -+void CvCapture_UCA::init() -+{ -+ buffer = NULL; -+ frame = NULL; -+ width = 0; -+ height = 0; -+ bit_depth = 0; -+ pixel_size = 0; -+} -+ -+bool CvCapture_UCA::grabFrame() -+{ -+ if (!buffer) -+ return false; -+ -+ device->grab(device, buffer, NULL); -+ return true; -+} -+ -+IplImage * CvCapture_UCA::retrieveFrame(int) -+{ -+ if (!frame) -+ frame = cvCreateImage(cvSize(width, height), bit_depth, 1); -+ -+ memcpy (frame->imageData, buffer, width*height*pixel_size); -+ return frame; -+} -+ -+bool CvCapture_UCA::open(int index) -+{ -+ //CV_FUNCNAME("cvCaptureFromCAM_UCA"); -+ -+ __BEGIN__; -+ -+ if (!is_initialized) { -+ is_initialized = true; -+ } -+ -+ uca_handle = uca_init(NULL); -+ if (uca_handle == NULL) -+ return false; -+ -+ device = uca_handle->cameras; -+ -+ device->get_property(device, UCA_PROP_WIDTH, &width, 0); -+ device->get_property(device, UCA_PROP_HEIGHT, &height, 0); -+ -+ int bits = 0; -+ device->get_property(device, UCA_PROP_BITDEPTH, &bits, 0); -+ bit_depth = (bits == 8) ? IPL_DEPTH_8U : IPL_DEPTH_16U; -+ -+ pixel_size = (bits == 8) ? 1 : 2; -+ buffer = new char[width*height*pixel_size]; -+ uca_cam_alloc(device, 10); -+ -+ device->start_recording(device); -+ -+ __END__; -+ return true; -+} -+ -+void CvCapture_UCA::close() -+{ -+ if (device) -+ device->stop_recording(device); -+ if (uca_handle); -+ uca_destroy(uca_handle); -+ delete[] buffer; -+} -+ -+double CvCapture_UCA::getProperty( int propId ) -+{ -+ switch(propId) { -+ case CV_CAP_PROP_POS_MSEC: -+ case CV_CAP_PROP_POS_FRAMES: -+ case CV_CAP_PROP_POS_AVI_RATIO: -+ break; -+ case CV_CAP_PROP_FRAME_WIDTH: -+ return (double) width; -+ case CV_CAP_PROP_FRAME_HEIGHT: -+ return (double) height; -+ case CV_CAP_PROP_FPS: -+ case CV_CAP_PROP_FOURCC: -+ break; -+ case CV_CAP_PROP_FRAME_COUNT: -+ return (double) device->current_frame; -+ case CV_CAP_PROP_FORMAT: -+ case CV_CAP_PROP_MODE: -+ case CV_CAP_PROP_BRIGHTNESS: -+ case CV_CAP_PROP_CONTRAST: -+ case CV_CAP_PROP_SATURATION: -+ case CV_CAP_PROP_HUE: -+ case CV_CAP_PROP_GAIN: -+ case CV_CAP_PROP_CONVERT_RGB: -+ break; -+ default: -+ CV_WARN("UCA: unhandled property"); -+ break; -+ } -+ return false; -+} -+ -+bool CvCapture_UCA::setProperty( int propId, double value ) -+{ -+ switch(propId) { -+ case CV_CAP_PROP_POS_MSEC: -+ break; -+ case CV_CAP_PROP_POS_FRAMES: -+ break; -+ case CV_CAP_PROP_POS_AVI_RATIO: -+ break; -+ case CV_CAP_PROP_FRAME_WIDTH: -+ break; -+ case CV_CAP_PROP_FRAME_HEIGHT: -+ break; -+ case CV_CAP_PROP_FPS: -+ break; -+ case CV_CAP_PROP_FOURCC: -+ case CV_CAP_PROP_FRAME_COUNT: -+ case CV_CAP_PROP_FORMAT: -+ case CV_CAP_PROP_MODE: -+ case CV_CAP_PROP_BRIGHTNESS: -+ case CV_CAP_PROP_CONTRAST: -+ case CV_CAP_PROP_SATURATION: -+ case CV_CAP_PROP_HUE: -+ case CV_CAP_PROP_GAIN: -+ case CV_CAP_PROP_CONVERT_RGB: -+ break; -+ default: -+ CV_WARN("UCA: unhandled property"); -+ } -+ return false; -+} -+ -+CvCapture *cvCreateCameraCapture_UCA(int index) -+{ -+ CvCapture_UCA* capture = new CvCapture_UCA; -+ -+ if (capture->open(index)) -+ return capture; -+ -+ delete capture; -+ return false; -+} - -=== modified file 'modules/highgui/src/precomp.hpp' ---- modules/highgui/src/precomp.hpp 2011-03-24 16:43:57 +0000 -+++ modules/highgui/src/precomp.hpp 2011-03-25 09:29:34 +0000 -@@ -113,6 +113,7 @@ - CvCapture * cvCreateCameraCapture_DC1394_2( int index ); - CvCapture* cvCreateCameraCapture_MIL( int index ); - CvCapture * cvCreateCameraCapture_CMU( int index ); -+CvCapture * cvCreateCameraCapture_UCA( int index ); - CV_IMPL CvCapture * cvCreateCameraCapture_TYZX( int index ); - CvCapture* cvCreateFileCapture_Win32( const char* filename ); - CvCapture* cvCreateCameraCapture_VFW( int index ); - diff --git a/plugins/mock/uca-mock-camera.c b/plugins/mock/uca-mock-camera.c index bf3124e..675d5ec 100644 --- a/plugins/mock/uca-mock-camera.c +++ b/plugins/mock/uca-mock-camera.c @@ -16,12 +16,17 @@ Franklin St, Fifth Floor, Boston, MA 02110, USA */ #include <gmodule.h> +#include <gio/gio.h> #include <string.h> #include "uca-mock-camera.h" #define UCA_MOCK_CAMERA_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), UCA_TYPE_MOCK_CAMERA, UcaMockCameraPrivate)) -G_DEFINE_TYPE(UcaMockCamera, uca_mock_camera, UCA_TYPE_CAMERA) +static void uca_mock_initable_iface_init (GInitableIface *iface); + +G_DEFINE_TYPE_WITH_CODE (UcaMockCamera, uca_mock_camera, UCA_TYPE_CAMERA, + G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, + uca_mock_initable_iface_init)) enum { PROP_FRAMERATE = N_BASE_PROPERTIES, @@ -38,6 +43,7 @@ static const gint mock_overrideables[] = { PROP_SENSOR_VERTICAL_BINNING, PROP_SENSOR_VERTICAL_BINNINGS, PROP_EXPOSURE_TIME, + PROP_TRIGGER_MODE, PROP_ROI_X, PROP_ROI_Y, PROP_ROI_WIDTH, @@ -53,6 +59,8 @@ static const gint mock_overrideables[] = { static GParamSpec *mock_properties[N_PROPERTIES] = { NULL, }; struct _UcaMockCameraPrivate { + UcaCameraTrigger trigger; + guint width; guint height; guint roi_x, roi_y, roi_width, roi_height; @@ -134,7 +142,8 @@ static const char g_digits[10][20] = { static const guint DIGIT_WIDTH = 4; static const guint DIGIT_HEIGHT = 5; -static void print_number(gchar *buffer, guint number, guint x, guint y, guint width) +static void +print_number(gchar *buffer, guint number, guint x, guint y, guint width) { for (int i = 0; i < DIGIT_WIDTH; i++) { for (int j = 0; j < DIGIT_HEIGHT; j++) { @@ -143,7 +152,8 @@ static void print_number(gchar *buffer, guint number, guint x, guint y, guint wi } } -static void print_current_frame(UcaMockCameraPrivate *priv, gchar *buffer) +static void +print_current_frame(UcaMockCameraPrivate *priv, gchar *buffer) { guint number = priv->current_frame; guint divisor = 10000000; @@ -157,7 +167,8 @@ static void print_current_frame(UcaMockCameraPrivate *priv, gchar *buffer) } } -static gpointer mock_grab_func(gpointer data) +static gpointer +mock_grab_func(gpointer data) { UcaMockCamera *mock_camera = UCA_MOCK_CAMERA(data); g_return_val_if_fail(UCA_IS_MOCK_CAMERA(mock_camera), NULL); @@ -174,7 +185,8 @@ static gpointer mock_grab_func(gpointer data) return NULL; } -static void uca_mock_camera_start_recording(UcaCamera *camera, GError **error) +static void +uca_mock_camera_start_recording(UcaCamera *camera, GError **error) { gboolean transfer_async = FALSE; UcaMockCameraPrivate *priv; @@ -204,7 +216,8 @@ static void uca_mock_camera_start_recording(UcaCamera *camera, GError **error) } } -static void uca_mock_camera_stop_recording(UcaCamera *camera, GError **error) +static void +uca_mock_camera_stop_recording(UcaCamera *camera, GError **error) { gboolean transfer_async = FALSE; UcaMockCameraPrivate *priv; @@ -224,22 +237,27 @@ static void uca_mock_camera_stop_recording(UcaCamera *camera, GError **error) } } -static void uca_mock_camera_grab(UcaCamera *camera, gpointer *data, GError **error) +static void +uca_mock_camera_trigger (UcaCamera *camera, GError **error) { - g_return_if_fail(UCA_IS_MOCK_CAMERA(camera)); - g_return_if_fail(data != NULL); +} - UcaMockCameraPrivate *priv = UCA_MOCK_CAMERA_GET_PRIVATE(camera); +static gboolean +uca_mock_camera_grab (UcaCamera *camera, gpointer data, GError **error) +{ + g_return_val_if_fail (UCA_IS_MOCK_CAMERA(camera), FALSE); - if (*data == NULL) - *data = g_malloc0(priv->width * priv->height); + UcaMockCameraPrivate *priv = UCA_MOCK_CAMERA_GET_PRIVATE (camera); - g_memmove(*data, priv->dummy_data, priv->width * priv->height); - print_current_frame(priv, *data); + g_memmove (data, priv->dummy_data, priv->roi_width * priv->roi_height); + print_current_frame (priv, data); priv->current_frame++; + + return TRUE; } -static void uca_mock_camera_set_property(GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) +static void +uca_mock_camera_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { g_return_if_fail(UCA_IS_MOCK_CAMERA(object)); UcaMockCameraPrivate *priv = UCA_MOCK_CAMERA_GET_PRIVATE(object); @@ -263,13 +281,17 @@ static void uca_mock_camera_set_property(GObject *object, guint property_id, con case PROP_ROI_HEIGHT: priv->roi_height = g_value_get_uint(value); break; + case PROP_TRIGGER_MODE: + priv->trigger = g_value_get_enum (value); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); return; } } -static void uca_mock_camera_get_property(GObject *object, guint property_id, GValue *value, GParamSpec *pspec) +static void +uca_mock_camera_get_property(GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { UcaMockCameraPrivate *priv = UCA_MOCK_CAMERA_GET_PRIVATE(object); @@ -331,13 +353,17 @@ static void uca_mock_camera_get_property(GObject *object, guint property_id, GVa case PROP_FRAMERATE: g_value_set_float(value, priv->frame_rate); break; + case PROP_TRIGGER_MODE: + g_value_set_enum (value, priv->trigger); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); break; } } -static void uca_mock_camera_finalize(GObject *object) +static void +uca_mock_camera_finalize(GObject *object) { UcaMockCameraPrivate *priv = UCA_MOCK_CAMERA_GET_PRIVATE(object); @@ -352,7 +378,23 @@ static void uca_mock_camera_finalize(GObject *object) G_OBJECT_CLASS(uca_mock_camera_parent_class)->finalize(object); } -static void uca_mock_camera_class_init(UcaMockCameraClass *klass) +static gboolean +ufo_mock_camera_initable_init (GInitable *initable, + GCancellable *cancellable, + GError **error) +{ + g_return_val_if_fail (UCA_IS_MOCK_CAMERA (initable), FALSE); + return TRUE; +} + +static void +uca_mock_initable_iface_init (GInitableIface *iface) +{ + iface->init = ufo_mock_camera_initable_init; +} + +static void +uca_mock_camera_class_init(UcaMockCameraClass *klass) { GObjectClass *gobject_class = G_OBJECT_CLASS(klass); gobject_class->set_property = uca_mock_camera_set_property; @@ -363,6 +405,7 @@ static void uca_mock_camera_class_init(UcaMockCameraClass *klass) camera_class->start_recording = uca_mock_camera_start_recording; camera_class->stop_recording = uca_mock_camera_stop_recording; camera_class->grab = uca_mock_camera_grab; + camera_class->trigger = uca_mock_camera_trigger; 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]]); @@ -380,13 +423,14 @@ static void uca_mock_camera_class_init(UcaMockCameraClass *klass) g_type_class_add_private(klass, sizeof(UcaMockCameraPrivate)); } -static void uca_mock_camera_init(UcaMockCamera *self) +static void +uca_mock_camera_init(UcaMockCamera *self) { self->priv = UCA_MOCK_CAMERA_GET_PRIVATE(self); self->priv->roi_x = 0; self->priv->roi_y = 0; - self->priv->width = self->priv->roi_width = 640; - self->priv->height = self->priv->roi_height = 480; + self->priv->width = self->priv->roi_width = 2016; + self->priv->height = self->priv->roi_height = 2016; self->priv->frame_rate = self->priv->max_frame_rate = 100000.0f; self->priv->grab_thread = NULL; self->priv->current_frame = 0; @@ -401,9 +445,8 @@ static void uca_mock_camera_init(UcaMockCamera *self) uca_camera_register_unit (UCA_CAMERA (self), "frame-rate", UCA_UNIT_COUNT); } -G_MODULE_EXPORT UcaCamera * -uca_camera_impl_new (GError **error) +G_MODULE_EXPORT GType +uca_camera_get_type (void) { - UcaCamera *camera = UCA_CAMERA (g_object_new (UCA_TYPE_MOCK_CAMERA, NULL)); - return camera; + return UCA_TYPE_MOCK_CAMERA; } diff --git a/plugins/mock/uca-mock-camera.h b/plugins/mock/uca-mock-camera.h index 9ee9190..bfbd166 100644 --- a/plugins/mock/uca-mock-camera.h +++ b/plugins/mock/uca-mock-camera.h @@ -58,8 +58,6 @@ struct _UcaMockCameraClass { UcaCameraClass parent; }; -GType uca_mock_camera_get_type(void); - G_END_DECLS #endif diff --git a/plugins/pco/uca-pco-camera.c b/plugins/pco/uca-pco-camera.c index bb7bd5a..4a0cce6 100644 --- a/plugins/pco/uca-pco-camera.c +++ b/plugins/pco/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 <gio/gio.h> #include <gmodule.h> #include <stdlib.h> #include <stdio.h> @@ -26,14 +27,13 @@ #include "uca-pco-camera.h" #include "uca-enums.h" -#define FG_TRY_PARAM(fg, camobj, param, val_addr, port) \ +#define FG_TRY_PARAM(fg, error, param, val_addr, port) \ { int r = Fg_setParameter(fg, param, val_addr, port); \ if (r != FG_OK) { \ - g_set_error(error, UCA_PCO_CAMERA_ERROR, \ + g_set_error (error, UCA_PCO_CAMERA_ERROR, \ UCA_PCO_CAMERA_ERROR_FG_GENERAL, \ "%s", Fg_getLastErrorDescription(fg)); \ - g_object_unref(camobj); \ - return NULL; \ + return FALSE; \ } } #define FG_SET_ERROR(err, fg, err_type) \ @@ -54,7 +54,11 @@ #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) +static void uca_pco_camera_initable_iface_init (GInitableIface *iface); + +G_DEFINE_TYPE_WITH_CODE (UcaPcoCamera, uca_pco_camera, UCA_TYPE_CAMERA, + G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, + uca_pco_camera_initable_iface_init)) #define TIMEBASE_INVALID 0xDEAD @@ -149,7 +153,7 @@ static GParamSpec *pco_properties[N_PROPERTIES] = { NULL, }; * This structure defines type-specific properties of PCO cameras. */ typedef struct { - int camera_type; + int type; const char *so_file; int cl_type; int cl_format; @@ -158,8 +162,9 @@ typedef struct { } pco_cl_map_entry; struct _UcaPcoCameraPrivate { + GError *construct_error; pco_handle pco; - pco_cl_map_entry *camera_description; + pco_cl_map_entry *description; Fg_Struct *fg; guint fg_port; @@ -193,7 +198,7 @@ struct _UcaPcoCameraPrivate { 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, "libDualAreaGray16.so", FG_CL_SINGLETAP_8_BIT, FG_GRAY16, 1279.0f, TRUE }, + { CAMERATYPE_PCO_DIMAX_STD, "libDualAreaGray16.so", FG_CL_SINGLETAP_16_BIT, FG_GRAY16, 1279.0f, TRUE }, { 0, NULL, 0, 0, 0.0f, FALSE } }; @@ -201,8 +206,8 @@ static pco_cl_map_entry *get_pco_cl_map_entry(int camera_type) { pco_cl_map_entry *entry = pco_cl_map; - while (entry->camera_type != 0) { - if (entry->camera_type == camera_type) + while (entry->type != 0) { + if (entry->type == camera_type) return entry; entry++; } @@ -249,7 +254,7 @@ fill_pixelrates(UcaPcoCameraPrivate *priv, guint32 rates[4], gint num_rates) { GValue val = {0}; g_value_init(&val, G_TYPE_UINT); - priv->pixelrates = g_value_array_new(num_rates); + priv->pixelrates = g_value_array_new (num_rates); for (gint i = 0; i < num_rates; i++) { g_value_set_uint(&val, (guint) rates[i]); @@ -330,7 +335,7 @@ get_suitable_timebase(gdouble time) static gdouble get_internal_delay (UcaPcoCamera *camera) { - if (camera->priv->camera_description->camera_type == CAMERATYPE_PCO_DIMAX_STD) { + if (camera->priv->description->type == CAMERATYPE_PCO_DIMAX_STD) { gdouble sensor_rate; g_object_get (camera, "sensor-pixelrate", &sensor_rate, NULL); @@ -350,7 +355,7 @@ fg_callback(frameindex_t frame, struct fg_apc_data *apc) UcaPcoCameraPrivate *priv = UCA_PCO_CAMERA_GET_PRIVATE(camera); gpointer data = Fg_getImagePtrEx(priv->fg, frame, priv->fg_port, priv->fg_mem); - if (priv->camera_description->camera_type != CAMERATYPE_PCO_EDGE) + if (priv->description->type != CAMERATYPE_PCO_EDGE) camera->grab_func(data, camera->user_data); else { pco_get_reorder_func(priv->pco)(priv->grab_buffer, data, priv->frame_width, priv->frame_height); @@ -392,7 +397,7 @@ check_pco_property_error (guint err, guint property_id) } static void -uca_pco_camera_start_recording(UcaCamera *camera, GError **error) +uca_pco_camera_start_recording (UcaCamera *camera, GError **error) { g_return_if_fail(UCA_IS_PCO_CAMERA(camera)); guint err = PCO_NOERROR; @@ -447,7 +452,7 @@ uca_pco_camera_start_recording(UcaCamera *camera, GError **error) /* g_warning("Cannot set binning\n"); */ if (priv->frame_width != priv->roi_width || priv->frame_height != priv->roi_height || priv->fg_mem == NULL) { - guint fg_width = priv->camera_description->camera_type == CAMERATYPE_PCO_EDGE ? 2 * priv->roi_width : priv->roi_width; + guint fg_width = priv->description->type == CAMERATYPE_PCO_EDGE ? 2 * priv->roi_width : priv->roi_width; priv->frame_width = priv->roi_width; priv->frame_height = priv->roi_height; @@ -474,8 +479,8 @@ uca_pco_camera_start_recording(UcaCamera *camera, GError **error) if (transfer_async) setup_fg_callback(camera); - if ((priv->camera_description->camera_type == CAMERATYPE_PCO_DIMAX_STD) || - (priv->camera_description->camera_type == CAMERATYPE_PCO4000)) + if ((priv->description->type == CAMERATYPE_PCO_DIMAX_STD) || + (priv->description->type == CAMERATYPE_PCO4000)) pco_clear_active_segment(priv->pco); priv->last_frame = 0; @@ -491,11 +496,10 @@ uca_pco_camera_start_recording(UcaCamera *camera, GError **error) } static void -uca_pco_camera_stop_recording(UcaCamera *camera, GError **error) +uca_pco_camera_stop_recording (UcaCamera *camera, GError **error) { g_return_if_fail(UCA_IS_PCO_CAMERA(camera)); UcaPcoCameraPrivate *priv = UCA_PCO_CAMERA_GET_PRIVATE(camera); - guint err = pco_stop_recording(priv->pco); HANDLE_PCO_ERROR(err); @@ -561,12 +565,12 @@ uca_pco_camera_trigger(UcaCamera *camera, GError **error) "Could not trigger frame acquisition"); } -static void -uca_pco_camera_grab(UcaCamera *camera, gpointer *data, GError **error) +static gboolean +uca_pco_camera_grab(UcaCamera *camera, gpointer data, GError **error) { - static const gint MAX_TIMEOUT = G_MAXINT; + static const gint MAX_TIMEOUT = 5; - g_return_if_fail(UCA_IS_PCO_CAMERA(camera)); + g_return_val_if_fail (UCA_IS_PCO_CAMERA(camera), FALSE); UcaPcoCameraPrivate *priv = UCA_PCO_CAMERA_GET_PRIVATE(camera); gboolean is_readout = FALSE; @@ -576,7 +580,7 @@ uca_pco_camera_grab(UcaCamera *camera, gpointer *data, GError **error) if (priv->current_image == priv->num_recorded_images) { g_set_error (error, UCA_CAMERA_ERROR, UCA_CAMERA_ERROR_END_OF_STREAM, "End of data stream"); - return; + return FALSE; } /* @@ -591,19 +595,20 @@ uca_pco_camera_grab(UcaCamera *camera, gpointer *data, GError **error) 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); + g_set_error (error, UCA_PCO_CAMERA_ERROR, + UCA_PCO_CAMERA_ERROR_FG_GENERAL, + "%s", Fg_getLastErrorDescription(priv->fg)); + return FALSE; } guint16 *frame = Fg_getImagePtrEx(priv->fg, priv->last_frame, priv->fg_port, priv->fg_mem); - if (*data == NULL) - *data = g_malloc0(priv->frame_width * priv->frame_height * priv->num_bytes); - - if (priv->camera_description->camera_type == CAMERATYPE_PCO_EDGE) - pco_get_reorder_func(priv->pco)((guint16 *) *data, frame, priv->frame_width, priv->frame_height); + if (priv->description->type == CAMERATYPE_PCO_EDGE) + pco_get_reorder_func(priv->pco)((guint16 *) data, frame, priv->frame_width, priv->frame_height); else - memcpy((gchar *) *data, (gchar *) frame, priv->frame_width * priv->frame_height * priv->num_bytes); + memcpy((gchar *) data, (gchar *) frame, priv->frame_width * priv->frame_height * priv->num_bytes); + + return TRUE; } static void @@ -915,7 +920,7 @@ uca_pco_camera_get_property(GObject *object, guint property_id, GValue *value, G break; case PROP_SENSOR_MAX_FRAME_RATE: - g_value_set_float(value, priv->camera_description->max_frame_rate); + g_value_set_float(value, priv->description->max_frame_rate); break; case PROP_SENSOR_BITDEPTH: @@ -1023,7 +1028,7 @@ uca_pco_camera_get_property(GObject *object, guint property_id, GValue *value, G break; case PROP_HAS_CAMRAM_RECORDING: - g_value_set_boolean(value, priv->camera_description->has_camram); + g_value_set_boolean(value, priv->description->has_camram); break; case PROP_RECORDED_FRAMES: @@ -1179,27 +1184,63 @@ uca_pco_camera_finalize(GObject *object) UcaPcoCameraPrivate *priv = UCA_PCO_CAMERA_GET_PRIVATE(object); if (priv->horizontal_binnings) - g_value_array_free(priv->horizontal_binnings); + g_value_array_free (priv->horizontal_binnings); if (priv->vertical_binnings) - g_value_array_free(priv->vertical_binnings); + g_value_array_free (priv->vertical_binnings); if (priv->pixelrates) - g_value_array_free(priv->pixelrates); + g_value_array_free (priv->pixelrates); if (priv->fg) { if (priv->fg_mem) Fg_FreeMemEx(priv->fg, priv->fg_mem); - Fg_FreeGrabber(priv->fg); + Fg_FreeGrabber (priv->fg); } if (priv->pco) - pco_destroy(priv->pco); + pco_destroy (priv->pco); + + g_free (priv->grab_buffer); + g_clear_error (&priv->construct_error); + + G_OBJECT_CLASS (uca_pco_camera_parent_class)->finalize (object); +} - g_free(priv->grab_buffer); +static gboolean +uca_pco_camera_initable_init (GInitable *initable, + GCancellable *cancellable, + GError **error) +{ + UcaPcoCamera *camera; + UcaPcoCameraPrivate *priv; + + g_return_val_if_fail (UCA_IS_PCO_CAMERA (initable), FALSE); + + if (cancellable != NULL) { + g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, + "Cancellable initialization not supported"); + return FALSE; + } + + camera = UCA_PCO_CAMERA (initable); + priv = camera->priv; + + if (priv->construct_error != NULL) { + if (error) + *error = g_error_copy (priv->construct_error); + + return FALSE; + } + + return TRUE; +} - G_OBJECT_CLASS(uca_pco_camera_parent_class)->finalize(object); +static void +uca_pco_camera_initable_iface_init (GInitableIface *iface) +{ + iface->init = uca_pco_camera_initable_init; } static void @@ -1387,62 +1428,43 @@ uca_pco_camera_class_init(UcaPcoCameraClass *klass) g_type_class_add_private(klass, sizeof(UcaPcoCameraPrivate)); } -static void -uca_pco_camera_init(UcaPcoCamera *self) +static gboolean +setup_pco_camera (UcaPcoCameraPrivate *priv) { - UcaCamera *camera; - - self->priv = UCA_PCO_CAMERA_GET_PRIVATE(self); - self->priv->fg = NULL; - self->priv->fg_mem = NULL; - self->priv->pco = NULL; - self->priv->horizontal_binnings = NULL; - self->priv->vertical_binnings = NULL; - self->priv->pixelrates = NULL; - self->priv->camera_description = NULL; - self->priv->last_frame = 0; - self->priv->grab_buffer = NULL; + pco_cl_map_entry *map_entry; + guint16 roi[4]; + guint16 camera_type; + guint16 camera_subtype; - self->priv->delay_timebase = TIMEBASE_INVALID; - self->priv->exposure_timebase = TIMEBASE_INVALID; + priv->pco = pco_init(); - camera = UCA_CAMERA (self); - uca_camera_register_unit (camera, "sensor-width-extended", UCA_UNIT_PIXEL); - uca_camera_register_unit (camera, "sensor-height-extended", UCA_UNIT_PIXEL); - uca_camera_register_unit (camera, "sensor-temperature", UCA_UNIT_DEGREE_CELSIUS); - uca_camera_register_unit (camera, "cooling-point", UCA_UNIT_DEGREE_CELSIUS); - uca_camera_register_unit (camera, "cooling-point-min", UCA_UNIT_DEGREE_CELSIUS); - uca_camera_register_unit (camera, "cooling-point-max", UCA_UNIT_DEGREE_CELSIUS); - uca_camera_register_unit (camera, "cooling-point-default", UCA_UNIT_DEGREE_CELSIUS); - uca_camera_register_unit (camera, "sensor-adcs", UCA_UNIT_COUNT); - uca_camera_register_unit (camera, "sensor-max-adcs", UCA_UNIT_COUNT); - uca_camera_register_unit (camera, "delay-time", UCA_UNIT_SECOND); -} + if (priv->pco == NULL) { + g_set_error (&priv->construct_error, + UCA_PCO_CAMERA_ERROR, UCA_PCO_CAMERA_ERROR_LIBPCO_INIT, + "Initializing libpco failed"); + return FALSE; + } -G_MODULE_EXPORT UcaCamera * -uca_camera_impl_new (GError **error) -{ - pco_handle pco = pco_init(); + pco_get_camera_type (priv->pco, &camera_type, &camera_subtype); + map_entry = get_pco_cl_map_entry (camera_type); - if (pco == NULL) { - g_set_error(error, UCA_PCO_CAMERA_ERROR, UCA_PCO_CAMERA_ERROR_LIBPCO_INIT, - "Initializing libpco failed"); - return NULL; + if (map_entry == NULL) { + g_set_error (&priv->construct_error, + UCA_PCO_CAMERA_ERROR, UCA_PCO_CAMERA_ERROR_UNSUPPORTED, + "Camera type is not supported"); + return FALSE; } - UcaPcoCamera *camera = g_object_new(UCA_TYPE_PCO_CAMERA, NULL); - UcaPcoCameraPrivate *priv = UCA_PCO_CAMERA_GET_PRIVATE(camera); - priv->pco = pco; + priv->description = map_entry; - pco_get_active_segment(priv->pco, &priv->active_segment); - 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); + pco_get_active_segment (priv->pco, &priv->active_segment); + 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 (priv->pco, STORAGE_MODE_RECORDER); + pco_set_auto_transfer (priv->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); + 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; @@ -1450,61 +1472,103 @@ uca_camera_impl_new (GError **error) priv->roi_height = roi[3] - roi[1] + 1; priv->num_recorded_images = 0; - guint16 camera_type, camera_subtype; - pco_get_camera_type(priv->pco, &camera_type, &camera_subtype); - pco_cl_map_entry *map_entry = get_pco_cl_map_entry(camera_type); - priv->camera_description = map_entry; + return TRUE; +} - 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; - } +static gboolean +setup_frame_grabber (UcaPcoCameraPrivate *priv) +{ + guint32 fg_width; + guint32 fg_height; + int val; priv->fg_port = PORT_A; - priv->fg = Fg_Init(map_entry->so_file, priv->fg_port); + priv->fg = Fg_Init (priv->description->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; + g_set_error (&priv->construct_error, UCA_PCO_CAMERA_ERROR, UCA_PCO_CAMERA_ERROR_FG_INIT, + "%s", Fg_getLastErrorDescription(priv->fg)); + return FALSE; } - 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, &priv->construct_error, FG_CAMERA_LINK_CAMTYP, &priv->description->cl_type, priv->fg_port); + FG_TRY_PARAM (priv->fg, &priv->construct_error, FG_FORMAT, &priv->description->cl_format, priv->fg_port); - 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); + fg_width = priv->description->type == CAMERATYPE_PCO_EDGE ? priv->width * 2 : priv->width; + FG_TRY_PARAM (priv->fg, &priv->construct_error, FG_WIDTH, &fg_width, priv->fg_port); - int val = FREE_RUN; - FG_TRY_PARAM(priv->fg, camera, FG_TRIGGERMODE, &val, priv->fg_port); + fg_height = priv->height; + FG_TRY_PARAM (priv->fg, &priv->construct_error, FG_HEIGHT, &fg_height, priv->fg_port); - fill_binnings(priv); + val = FREE_RUN; + FG_TRY_PARAM (priv->fg, &priv->construct_error, FG_TRIGGERMODE, &val, priv->fg_port); - /* - * 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); + return TRUE; +} + +static void +override_property_ranges (UcaPcoCamera *camera) +{ + UcaPcoCameraPrivate *priv; + GObjectClass *oclass; + + priv = UCA_PCO_CAMERA_GET_PRIVATE (camera); + oclass = G_OBJECT_CLASS (UCA_PCO_CAMERA_GET_CLASS (camera)); + property_override_default_guint_value (oclass, "roi-width", priv->width); + property_override_default_guint_value (oclass, "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]); + if (pco_get_available_pixelrates (priv->pco, rates, &num_rates) == PCO_NOERROR) { + fill_pixelrates (priv, rates, num_rates); + property_override_default_guint_value (oclass, "sensor-pixelrate", rates[0]); } override_temperature_range (priv); override_maximum_adcs (priv); +} + +static void +uca_pco_camera_init (UcaPcoCamera *self) +{ + UcaCamera *camera; + UcaPcoCameraPrivate *priv; + + self->priv = priv = UCA_PCO_CAMERA_GET_PRIVATE (self); - return UCA_CAMERA (camera); + priv->fg_mem = NULL; + priv->description = NULL; + priv->last_frame = 0; + priv->grab_buffer = NULL; + priv->construct_error = NULL; + priv->delay_timebase = TIMEBASE_INVALID; + priv->exposure_timebase = TIMEBASE_INVALID; + + if (!setup_pco_camera (priv)) + return; + + if (!setup_frame_grabber (priv)) + return; + + fill_binnings (priv); + override_property_ranges (self); + + camera = UCA_CAMERA (self); + uca_camera_register_unit (camera, "sensor-width-extended", UCA_UNIT_PIXEL); + uca_camera_register_unit (camera, "sensor-height-extended", UCA_UNIT_PIXEL); + uca_camera_register_unit (camera, "sensor-temperature", UCA_UNIT_DEGREE_CELSIUS); + uca_camera_register_unit (camera, "cooling-point", UCA_UNIT_DEGREE_CELSIUS); + uca_camera_register_unit (camera, "cooling-point-min", UCA_UNIT_DEGREE_CELSIUS); + uca_camera_register_unit (camera, "cooling-point-max", UCA_UNIT_DEGREE_CELSIUS); + uca_camera_register_unit (camera, "cooling-point-default", UCA_UNIT_DEGREE_CELSIUS); + uca_camera_register_unit (camera, "sensor-adcs", UCA_UNIT_COUNT); + uca_camera_register_unit (camera, "sensor-max-adcs", UCA_UNIT_COUNT); + uca_camera_register_unit (camera, "delay-time", UCA_UNIT_SECOND); +} + +G_MODULE_EXPORT GType +uca_camera_get_type (void) +{ + return UCA_TYPE_PCO_CAMERA; } diff --git a/plugins/pco/uca-pco-camera.h b/plugins/pco/uca-pco-camera.h index d134fb1..347c27c 100644 --- a/plugins/pco/uca-pco-camera.h +++ b/plugins/pco/uca-pco-camera.h @@ -57,8 +57,8 @@ typedef enum { typedef enum { UCA_PCO_CAMERA_TIMESTAMP_NONE, UCA_PCO_CAMERA_TIMESTAMP_BINARY, - UCA_PCO_CAMERA_TIMESTAMP_ASCII, - UCA_PCO_CAMERA_TIMESTAMP_BOTH + UCA_PCO_CAMERA_TIMESTAMP_BOTH, + UCA_PCO_CAMERA_TIMESTAMP_ASCII } UcaPcoCameraTimestamp; /** diff --git a/plugins/pf/uca-pf-camera.c b/plugins/pf/uca-pf-camera.c index 473ffd3..b7967be 100644 --- a/plugins/pf/uca-pf-camera.c +++ b/plugins/pf/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 <gio/gio.h> #include <gmodule.h> #include <stdlib.h> #include <stdio.h> @@ -32,7 +33,6 @@ g_set_error(error, UCA_PF_CAMERA_ERROR, \ UCA_PF_CAMERA_ERROR_FG_GENERAL, \ "%s", Fg_getLastErrorDescription(fg)); \ - g_object_unref(camobj); \ return NULL; \ } } @@ -46,7 +46,11 @@ #define UCA_PF_CAMERA_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), UCA_TYPE_PF_CAMERA, UcaPfCameraPrivate)) -G_DEFINE_TYPE(UcaPfCamera, uca_pf_camera, UCA_TYPE_CAMERA) +static void uca_pf_camera_initable_iface_init (GInitableIface *iface); + +G_DEFINE_TYPE_WITH_CODE (UcaPfCamera, uca_pf_camera, UCA_TYPE_CAMERA, + G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, + uca_pf_camera_initable_iface_init)) /** * UcaPfCameraError: @@ -91,6 +95,7 @@ enum { struct _UcaPfCameraPrivate { + GError *construct_error; guint roi_width; guint roi_height; guint last_frame; @@ -107,7 +112,8 @@ struct { UcaCamera *camera; } fg_apc_data; -static int me4_callback(frameindex_t frame, struct fg_apc_data *apc) +static int +me4_callback(frameindex_t frame, struct fg_apc_data *apc) { UcaCamera *camera = UCA_CAMERA(apc); UcaPfCameraPrivate *priv = UCA_PF_CAMERA_GET_PRIVATE(camera); @@ -115,7 +121,8 @@ static int me4_callback(frameindex_t frame, struct fg_apc_data *apc) return 0; } -static void uca_pf_camera_start_recording(UcaCamera *camera, GError **error) +static void +uca_pf_camera_start_recording(UcaCamera *camera, GError **error) { g_return_if_fail(UCA_IS_PF_CAMERA(camera)); UcaPfCameraPrivate *priv = UCA_PF_CAMERA_GET_PRIVATE(camera); @@ -155,7 +162,8 @@ static void uca_pf_camera_start_recording(UcaCamera *camera, GError **error) FG_SET_ERROR(err, priv->fg, UCA_PF_CAMERA_ERROR_FG_ACQUISITION); } -static void uca_pf_camera_stop_recording(UcaCamera *camera, GError **error) +static void +uca_pf_camera_stop_recording(UcaCamera *camera, GError **error) { g_return_if_fail(UCA_IS_PF_CAMERA(camera)); UcaPfCameraPrivate *priv = UCA_PF_CAMERA_GET_PRIVATE(camera); @@ -168,34 +176,39 @@ static void uca_pf_camera_stop_recording(UcaCamera *camera, GError **error) g_print(" Unable to unblock all\n"); } -static void uca_pf_camera_start_readout(UcaCamera *camera, GError **error) +static void +uca_pf_camera_start_readout(UcaCamera *camera, GError **error) { g_return_if_fail(UCA_IS_PF_CAMERA(camera)); g_set_error(error, UCA_CAMERA_ERROR, UCA_CAMERA_ERROR_NOT_IMPLEMENTED, "This photon focus camera does not support recording to internal memory"); } -static void uca_pf_camera_grab(UcaCamera *camera, gpointer *data, GError **error) +static gboolean +uca_pf_camera_grab(UcaCamera *camera, gpointer data, GError **error) { - g_return_if_fail(UCA_IS_PF_CAMERA(camera)); + g_return_val_if_fail (UCA_IS_PF_CAMERA (camera), FALSE); 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); + 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); + g_set_error (error, UCA_PF_CAMERA_ERROR, + UCA_PF_CAMERA_ERROR_FG_ACQUISITION, + "%s", Fg_getLastErrorDescription(priv->fg)); + return FALSE; } - guint16 *frame = Fg_getImagePtrEx(priv->fg, priv->last_frame, priv->fg_port, priv->fg_mem); - - if (*data == NULL) - *data = g_malloc0(priv->roi_width * priv->roi_height); + guint16 *frame = Fg_getImagePtrEx (priv->fg, priv->last_frame, + priv->fg_port, priv->fg_mem); - memcpy((gchar *) *data, (gchar *) frame, priv->roi_width * priv->roi_height); + memcpy((gchar *) data, (gchar *) frame, priv->roi_width * priv->roi_height); + return TRUE; } -static void uca_pf_camera_set_property(GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) +static void +uca_pf_camera_set_property(GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { switch (property_id) { default: @@ -204,7 +217,8 @@ 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) +static void +uca_pf_camera_get_property(GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { switch (property_id) { case PROP_SENSOR_WIDTH: @@ -263,7 +277,8 @@ static void uca_pf_camera_get_property(GObject *object, guint property_id, GValu } } -static void uca_pf_camera_finalize(GObject *object) +static void +uca_pf_camera_finalize(GObject *object) { UcaPfCameraPrivate *priv = UCA_PF_CAMERA_GET_PRIVATE(object); @@ -274,10 +289,54 @@ static void uca_pf_camera_finalize(GObject *object) Fg_FreeGrabber(priv->fg); } + g_clear_error (&priv->construct_error); + G_OBJECT_CLASS(uca_pf_camera_parent_class)->finalize(object); } -static void uca_pf_camera_class_init(UcaPfCameraClass *klass) +static gboolean +uca_pf_camera_initable_init (GInitable *initable, + GCancellable *cancellable, + GError **error) +{ + UcaPfCamera *camera; + UcaPfCameraPrivate *priv; + + g_return_val_if_fail (UCA_IS_PF_CAMERA (initable), FALSE); + + if (cancellable != NULL) { + g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, + "Cancellable initialization not supported"); + return FALSE; + } + + camera = UCA_PF_CAMERA (initable); + priv = camera->priv; + + if (priv->construct_error != NULL) { + if (error) + *error = g_error_copy (priv->construct_error); + + return FALSE; + } + + if (priv->fg == NULL) { + g_set_error (error, UCA_PF_CAMERA_ERROR, UCA_PF_CAMERA_ERROR_INIT, + "%s", Fg_getLastErrorDescription (NULL)); + return FALSE; + } + + return TRUE; +} + +static void +uca_pf_camera_initable_iface_init (GInitableIface *iface) +{ + iface->init = uca_pf_camera_initable_init; +} + +static void +uca_pf_camera_class_init(UcaPfCameraClass *klass) { GObjectClass *gobject_class = G_OBJECT_CLASS(klass); gobject_class->set_property = uca_pf_camera_set_property; @@ -296,57 +355,56 @@ static void uca_pf_camera_class_init(UcaPfCameraClass *klass) g_type_class_add_private(klass, sizeof(UcaPfCameraPrivate)); } -static void uca_pf_camera_init(UcaPfCamera *self) +static gboolean +try_fg_param (UcaPfCameraPrivate *priv, + int param, + const gpointer value) { - self->priv = UCA_PF_CAMERA_GET_PRIVATE(self); - self->priv->fg = NULL; - self->priv->fg_mem = NULL; - self->priv->last_frame = 0; + if (Fg_setParameter (priv->fg, param, value, priv->fg_port) != FG_OK) { + g_set_error (&priv->construct_error, UCA_PF_CAMERA_ERROR, + UCA_PF_CAMERA_ERROR_FG_GENERAL, + "%s", Fg_getLastErrorDescription (priv->fg)); + return FALSE; + } + + return TRUE; } -G_MODULE_EXPORT UcaCamera * -uca_camera_impl_new (GError **error) +static void +uca_pf_camera_init (UcaPfCamera *self) { + UcaPfCameraPrivate *priv; 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; - } - */ + static const int link_type = FG_CL_8BIT_FULL_8; + static const int format = FG_GRAY; - UcaPfCamera *camera = g_object_new(UCA_TYPE_PF_CAMERA, NULL); - UcaPfCameraPrivate *priv = UCA_PF_CAMERA_GET_PRIVATE(camera); + self->priv = priv = UCA_PF_CAMERA_GET_PRIVATE(self); + priv->construct_error = NULL; priv->fg_port = PORT_A; - priv->fg = Fg_Init(so_file, priv->fg_port); - - /* TODO: get this from the camera */ + priv->fg = Fg_Init (so_file, priv->fg_port); + priv->fg_mem = NULL; + priv->last_frame = 0; 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; - } + if (priv->fg != NULL) { + if (!try_fg_param (priv, FG_CAMERA_LINK_CAMTYP, (const gpointer) &link_type)) + return; - 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); + if (!try_fg_param (priv, FG_FORMAT, (const gpointer) &format)) + return; - return UCA_CAMERA (camera); + if (!try_fg_param (priv, FG_WIDTH, &priv->roi_width)) + return; + + if (!try_fg_param (priv, FG_HEIGHT, &priv->roi_height)) + return; + } +} + +G_MODULE_EXPORT GType +uca_camera_get_type (void) +{ + return UCA_TYPE_PF_CAMERA; } diff --git a/plugins/ufo/uca-ufo-camera.c b/plugins/ufo/uca-ufo-camera.c index c4e05b0..145c2ee 100644 --- a/plugins/ufo/uca-ufo-camera.c +++ b/plugins/ufo/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 <gio/gio.h> #include <gmodule.h> #include <stdlib.h> #include <stdio.h> @@ -33,9 +34,22 @@ return; \ } +#define PCILIB_SET_ERROR_RETURN_FALSE(err, err_type) \ + if (err != 0) { \ + g_set_error(error, UCA_UFO_CAMERA_ERROR, \ + err_type, \ + "%s:%i pcilib: %s (errcode = %d)", \ + __FILE__, __LINE__, strerror(err), err);\ + return FALSE; \ + } + #define UCA_UFO_CAMERA_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), UCA_TYPE_UFO_CAMERA, UcaUfoCameraPrivate)) -G_DEFINE_TYPE(UcaUfoCamera, uca_ufo_camera, UCA_TYPE_CAMERA) +static void uca_ufo_camera_initable_iface_init (GInitableIface *iface); + +G_DEFINE_TYPE_WITH_CODE (UcaUfoCamera, uca_ufo_camera, UCA_TYPE_CAMERA, + G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, + uca_ufo_camera_initable_iface_init)) static const guint SENSOR_WIDTH = 2048; static const guint SENSOR_HEIGHT = 1088; @@ -80,7 +94,6 @@ static gint base_overrideables[] = { PROP_ROI_HEIGHT_MULTIPLIER, PROP_HAS_STREAMING, PROP_HAS_CAMRAM_RECORDING, - PROP_TRIGGER_MODE, 0, }; @@ -92,9 +105,11 @@ typedef struct _RegisterInfo { static GParamSpec *ufo_properties[N_MAX_PROPERTIES] = { NULL, }; static guint N_PROPERTIES; -static GHashTable *ufo_property_table; /* maps from prop_id to RegisterInfo* */ struct _UcaUfoCameraPrivate { + GError *construct_error; + GHashTable *property_table; /* maps from prop_id to RegisterInfo* */ + GThread *async_thread; pcilib_t *handle; pcilib_timeout_t timeout; guint n_bits; @@ -102,7 +117,6 @@ struct _UcaUfoCameraPrivate { FPGA_48MHZ = 0, FPGA_40MHZ } frequency; - UcaCameraTrigger trigger; }; static void @@ -126,7 +140,8 @@ read_register_value (pcilib_t *handle, const gchar *name) return (guint) reg_value; } -static int event_callback(pcilib_event_id_t event_id, pcilib_event_info_t *info, void *user) +static int +event_callback(pcilib_event_id_t event_id, pcilib_event_info_t *info, void *user) { UcaCamera *camera = UCA_CAMERA(user); UcaUfoCameraPrivate *priv = UCA_UFO_CAMERA_GET_PRIVATE(camera); @@ -134,47 +149,32 @@ static int event_callback(pcilib_event_id_t event_id, pcilib_event_info_t *info, void *buffer = pcilib_get_data(priv->handle, event_id, PCILIB_EVENT_DATA, &error); - if (buffer == NULL) { - pcilib_trigger(priv->handle, PCILIB_EVENT0, 0, NULL); + if (buffer == NULL) return PCILIB_STREAMING_CONTINUE; - } - camera->grab_func(buffer, camera->user_data); - pcilib_return_data(priv->handle, event_id, PCILIB_EVENT_DATA, buffer); - pcilib_trigger(priv->handle, PCILIB_EVENT0, 0, NULL); + camera->grab_func (buffer, camera->user_data); + pcilib_return_data (priv->handle, event_id, PCILIB_EVENT_DATA, buffer); return PCILIB_STREAMING_CONTINUE; } -G_MODULE_EXPORT UcaCamera * -uca_camera_impl_new (GError **error) +static guint +update_properties (UcaUfoCameraPrivate *priv) { - pcilib_model_t model = PCILIB_MODEL_DETECT; - pcilib_model_description_t *model_description; - pcilib_t *handle = pcilib_open("/dev/fpga0", model); - guint prop = PROP_UFO_START; - guint adc_resolution; - - if (handle == NULL) { - g_set_error(error, UCA_UFO_CAMERA_ERROR, UCA_UFO_CAMERA_ERROR_INIT, - "Initializing pcilib failed"); - return NULL; - } + guint prop; + pcilib_model_description_t *description; - pcilib_set_error_handler(&error_handler, &error_handler); + prop = PROP_UFO_START; + description = pcilib_get_model_description (priv->handle); - /* Generate properties from model description */ - model_description = pcilib_get_model_description(handle); - ufo_property_table = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_free); - - for (guint i = 0; model_description->registers[i].name != NULL; i++) { + for (guint i = 0; description->registers[i].name != NULL; i++) { GParamFlags flags = 0; RegisterInfo *reg_info; gchar *prop_name; pcilib_register_description_t *reg; pcilib_register_value_t value; - reg = &model_description->registers[i]; + reg = &description->registers[i]; switch (reg->mode) { case PCILIB_REGISTER_R: @@ -190,12 +190,12 @@ uca_camera_impl_new (GError **error) break; } - pcilib_read_register (handle, NULL, reg->name, &value); + pcilib_read_register (priv->handle, NULL, reg->name, &value); reg_info = g_new0 (RegisterInfo, 1); reg_info->name = g_strdup (reg->name); reg_info->cached_value = (guint32) value; - g_hash_table_insert (ufo_property_table, GINT_TO_POINTER (prop), reg_info); + g_hash_table_insert (priv->property_table, GINT_TO_POINTER (prop), reg_info); prop_name = g_strdup_printf ("ufo-%s", reg->name); ufo_properties[prop++] = g_param_spec_uint ( @@ -205,13 +205,32 @@ uca_camera_impl_new (GError **error) g_free (prop_name); } - N_PROPERTIES = prop; + return prop; +} - UcaUfoCamera *camera = g_object_new(UCA_TYPE_UFO_CAMERA, NULL); - UcaUfoCameraPrivate *priv = UCA_UFO_CAMERA_GET_PRIVATE(camera); +static gboolean +setup_pcilib (UcaUfoCameraPrivate *priv) +{ + pcilib_model_t model; + guint adc_resolution; + + model = PCILIB_MODEL_DETECT; + priv->handle = pcilib_open("/dev/fpga0", model); - priv->frequency = read_register_value (handle, "bit_mode"); - adc_resolution = read_register_value (handle, "adc_resolution"); + if (priv->handle == NULL) { + g_set_error (&priv->construct_error, + UCA_UFO_CAMERA_ERROR, UCA_UFO_CAMERA_ERROR_INIT, + "Initializing pcilib failed"); + return FALSE; + } + + pcilib_set_error_handler (&error_handler, &error_handler); + + priv->property_table = g_hash_table_new_full (g_direct_hash, g_direct_equal, + NULL, g_free); + N_PROPERTIES = update_properties (priv); + priv->frequency = read_register_value (priv->handle, "bit_mode"); + adc_resolution = read_register_value (priv->handle, "adc_resolution"); switch (adc_resolution) { case 0: @@ -225,59 +244,115 @@ uca_camera_impl_new (GError **error) break; } - priv->handle = handle; + return TRUE; +} + +static void +set_control_bit (UcaUfoCameraPrivate *priv, guint bit, gboolean set) +{ + static const gchar *name = "control"; + pcilib_register_value_t flags; + pcilib_register_value_t mask; + + pcilib_read_register (priv->handle, NULL, name, &flags); + mask = 1 << bit; + + if (set) + flags |= mask; + else + flags = flags & ~mask; - return UCA_CAMERA (camera); + pcilib_write_register(priv->handle, NULL, name, flags); } -static void uca_ufo_camera_start_recording(UcaCamera *camera, GError **error) +static void +set_streaming (UcaUfoCameraPrivate *priv, gboolean enable) +{ + set_control_bit (priv, 11, enable); +} + +static gpointer +stream_async (UcaCamera *camera) { UcaUfoCameraPrivate *priv; + priv = UCA_UFO_CAMERA_GET_PRIVATE (camera); + pcilib_stream (priv->handle, &event_callback, camera); + + return NULL; +} + +static void +uca_ufo_camera_start_recording(UcaCamera *camera, GError **error) +{ + UcaUfoCameraPrivate *priv; + UcaCameraTrigger trigger; gdouble exposure_time; - int err; + gboolean transfer_async; + int err; g_return_if_fail(UCA_IS_UFO_CAMERA(camera)); priv = UCA_UFO_CAMERA_GET_PRIVATE(camera); + + g_object_get (G_OBJECT(camera), + "transfer-asynchronously", &transfer_async, + "exposure-time", &exposure_time, + "trigger-mode", &trigger, + NULL); + err = pcilib_start(priv->handle, PCILIB_EVENT_DATA, PCILIB_EVENT_FLAGS_DEFAULT); PCILIB_SET_ERROR(err, UCA_UFO_CAMERA_ERROR_START_RECORDING); - gboolean transfer_async = FALSE; - g_object_get(G_OBJECT(camera), - "transfer-asynchronously", &transfer_async, - "exposure-time", &exposure_time, - "trigger-mode", &priv->trigger, - NULL); + if (trigger == UCA_CAMERA_TRIGGER_AUTO) + set_streaming (priv, TRUE); priv->timeout = ((pcilib_timeout_t) (exposure_time * 1000 + 50.0) * 1000); - if (transfer_async) { - pcilib_trigger(priv->handle, PCILIB_EVENT0, 0, NULL); - pcilib_stream(priv->handle, &event_callback, camera); - } + if (transfer_async) + priv->async_thread = g_thread_create ((GThreadFunc) stream_async, camera, TRUE, error); } -static void uca_ufo_camera_stop_recording(UcaCamera *camera, GError **error) +static void +uca_ufo_camera_stop_recording(UcaCamera *camera, GError **error) { + UcaUfoCameraPrivate *priv; + UcaCameraTrigger trigger; g_return_if_fail(UCA_IS_UFO_CAMERA(camera)); - UcaUfoCameraPrivate *priv = UCA_UFO_CAMERA_GET_PRIVATE(camera); - int err = pcilib_stop(priv->handle, PCILIB_EVENT_FLAGS_DEFAULT); - PCILIB_SET_ERROR(err, UCA_UFO_CAMERA_ERROR_START_RECORDING); + + priv = UCA_UFO_CAMERA_GET_PRIVATE(camera); + + g_object_get (G_OBJECT (camera), "trigger-mode", &trigger, NULL); + + if (priv->async_thread) { + int err = pcilib_stop(priv->handle, PCILIB_EVENT_FLAG_STOP_ONLY); + PCILIB_SET_ERROR(err, UCA_UFO_CAMERA_ERROR_STOP_RECORDING); + g_thread_join(priv->async_thread); + priv->async_thread = NULL; + } + + int err = pcilib_stop (priv->handle, PCILIB_EVENT_FLAGS_DEFAULT); + PCILIB_SET_ERROR(err, UCA_UFO_CAMERA_ERROR_STOP_RECORDING); + + if (trigger == UCA_CAMERA_TRIGGER_AUTO) + set_streaming (priv, FALSE); } -static void uca_ufo_camera_start_readout(UcaCamera *camera, GError **error) +static void +uca_ufo_camera_start_readout(UcaCamera *camera, GError **error) { g_return_if_fail(UCA_IS_UFO_CAMERA(camera)); } -static void uca_ufo_camera_stop_readout(UcaCamera *camera, GError **error) +static void +uca_ufo_camera_stop_readout(UcaCamera *camera, GError **error) { g_return_if_fail(UCA_IS_UFO_CAMERA(camera)); } -static void uca_ufo_camera_grab(UcaCamera *camera, gpointer *data, GError **error) +static gboolean +uca_ufo_camera_grab(UcaCamera *camera, gpointer data, GError **error) { - g_return_if_fail(UCA_IS_UFO_CAMERA(camera)); + g_return_val_if_fail (UCA_IS_UFO_CAMERA(camera), FALSE); UcaUfoCameraPrivate *priv = UCA_UFO_CAMERA_GET_PRIVATE(camera); pcilib_event_id_t event_id; pcilib_event_info_t event_info; @@ -285,21 +360,13 @@ static void uca_ufo_camera_grab(UcaCamera *camera, gpointer *data, GError **erro const gsize size = SENSOR_WIDTH * SENSOR_HEIGHT * sizeof(guint16); - if (priv->trigger != UCA_CAMERA_TRIGGER_EXTERNAL) { - err = pcilib_trigger(priv->handle, PCILIB_EVENT0, 0, NULL); - PCILIB_SET_ERROR(err, UCA_UFO_CAMERA_ERROR_TRIGGER); - } - - err = pcilib_get_next_event(priv->handle, priv->timeout, &event_id, sizeof(pcilib_event_info_t), &event_info); - PCILIB_SET_ERROR(err, UCA_UFO_CAMERA_ERROR_NEXT_EVENT); - - if (*data == NULL) - *data = g_malloc0(SENSOR_WIDTH * SENSOR_HEIGHT * sizeof(guint16)); + err = pcilib_get_next_event (priv->handle, priv->timeout, &event_id, sizeof(pcilib_event_info_t), &event_info); + PCILIB_SET_ERROR_RETURN_FALSE (err, UCA_UFO_CAMERA_ERROR_NEXT_EVENT); - gpointer src = pcilib_get_data(priv->handle, event_id, PCILIB_EVENT_DATA, (size_t *) &err); + gpointer src = pcilib_get_data (priv->handle, event_id, PCILIB_EVENT_DATA, (size_t *) &err); if (src == NULL) - PCILIB_SET_ERROR(err, UCA_UFO_CAMERA_ERROR_NO_DATA); + PCILIB_SET_ERROR_RETURN_FALSE (err, UCA_UFO_CAMERA_ERROR_NO_DATA); /* * Apparently, we checked that err equals total size in previous version. @@ -309,15 +376,29 @@ static void uca_ufo_camera_grab(UcaCamera *camera, gpointer *data, GError **erro */ /* assert(err == size); */ - memcpy(*data, src, size); + memcpy (data, src, size); /* * Another problem here. What does this help us? At this point we have * already overwritten the original buffer but can only know here if the * data is corrupted. */ - err = pcilib_return_data(priv->handle, event_id, PCILIB_EVENT_DATA, data); - PCILIB_SET_ERROR(err, UCA_UFO_CAMERA_ERROR_MAYBE_CORRUPTED); + err = pcilib_return_data (priv->handle, event_id, PCILIB_EVENT_DATA, data); + PCILIB_SET_ERROR_RETURN_FALSE (err, UCA_UFO_CAMERA_ERROR_MAYBE_CORRUPTED); + + return TRUE; +} + +static void +uca_ufo_camera_trigger (UcaCamera *camera, GError **error) +{ + UcaUfoCameraPrivate *priv; + g_return_if_fail (UCA_IS_UFO_CAMERA(camera)); + + priv = UCA_UFO_CAMERA_GET_PRIVATE(camera); + + /* XXX: What is PCILIB_EVENT0? */ + pcilib_trigger (priv->handle, PCILIB_EVENT0, 0, NULL); } static void @@ -340,19 +421,18 @@ uca_ufo_camera_set_property(GObject *object, guint property_id, const GValue *va g_debug("ROI feature not implemented yet"); break; - case PROP_TRIGGER_MODE: - priv->trigger = g_value_get_enum (value); - break; - default: { - RegisterInfo *reg_info = g_hash_table_lookup (ufo_property_table, GINT_TO_POINTER (property_id)); + RegisterInfo *reg_info; + + reg_info = g_hash_table_lookup (priv->property_table, + GINT_TO_POINTER (property_id)); if (reg_info != NULL) { pcilib_register_value_t reg_value; reg_value = g_value_get_uint (value); - pcilib_write_register(priv->handle, NULL, reg_info->name, reg_value); + pcilib_write_register (priv->handle, NULL, reg_info->name, reg_value); pcilib_read_register (priv->handle, NULL, reg_info->name, ®_value); reg_info->cached_value = (guint) reg_value; } @@ -441,12 +521,9 @@ uca_ufo_camera_get_property(GObject *object, guint property_id, GValue *value, G case PROP_NAME: g_value_set_string(value, "Ufo Camera w/ CMOSIS CMV2000"); break; - case PROP_TRIGGER_MODE: - g_value_set_enum (value, priv->trigger); - break; default: { - RegisterInfo *reg_info = g_hash_table_lookup (ufo_property_table, GINT_TO_POINTER (property_id)); + RegisterInfo *reg_info = g_hash_table_lookup (priv->property_table, GINT_TO_POINTER (property_id)); if (reg_info != NULL) g_value_set_uint (value, reg_info->cached_value); @@ -457,14 +534,56 @@ uca_ufo_camera_get_property(GObject *object, guint property_id, GValue *value, G } } -static void uca_ufo_camera_finalize(GObject *object) +static void +uca_ufo_camera_finalize(GObject *object) { - UcaUfoCameraPrivate *priv = UCA_UFO_CAMERA_GET_PRIVATE(object); - pcilib_close(priv->handle); - G_OBJECT_CLASS(uca_ufo_camera_parent_class)->finalize(object); + UcaUfoCameraPrivate *priv; + + priv = UCA_UFO_CAMERA_GET_PRIVATE (object); + + pcilib_close (priv->handle); + g_clear_error (&priv->construct_error); + + G_OBJECT_CLASS (uca_ufo_camera_parent_class)->finalize (object); } -static void uca_ufo_camera_class_init(UcaUfoCameraClass *klass) +static gboolean +ufo_ufo_camera_initable_init (GInitable *initable, + GCancellable *cancellable, + GError **error) +{ + UcaUfoCamera *camera; + UcaUfoCameraPrivate *priv; + + g_return_val_if_fail (UCA_IS_UFO_CAMERA (initable), FALSE); + + if (cancellable != NULL) { + g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, + "Cancellable initialization not supported"); + return FALSE; + } + + camera = UCA_UFO_CAMERA (initable); + priv = camera->priv; + + if (priv->construct_error != NULL) { + if (error) + *error = g_error_copy (priv->construct_error); + + return FALSE; + } + + return TRUE; +} + +static void +uca_ufo_camera_initable_iface_init (GInitableIface *iface) +{ + iface->init = ufo_ufo_camera_initable_init; +} + +static void +uca_ufo_camera_class_init(UcaUfoCameraClass *klass) { GObjectClass *gobject_class = G_OBJECT_CLASS(klass); gobject_class->set_property = uca_ufo_camera_set_property; @@ -477,6 +596,7 @@ static void uca_ufo_camera_class_init(UcaUfoCameraClass *klass) camera_class->start_readout = uca_ufo_camera_start_readout; camera_class->stop_readout = uca_ufo_camera_stop_readout; camera_class->grab = uca_ufo_camera_grab; + camera_class->trigger = uca_ufo_camera_trigger; for (guint i = 0; base_overrideables[i] != 0; i++) g_object_class_override_property(gobject_class, base_overrideables[i], uca_camera_props[base_overrideables[i]]); @@ -505,7 +625,26 @@ static void uca_ufo_camera_class_init(UcaUfoCameraClass *klass) g_type_class_add_private(klass, sizeof(UcaUfoCameraPrivate)); } -static void uca_ufo_camera_init(UcaUfoCamera *self) +static void +uca_ufo_camera_init(UcaUfoCamera *self) +{ + UcaCamera *camera; + UcaUfoCameraPrivate *priv; + + self->priv = priv = UCA_UFO_CAMERA_GET_PRIVATE(self); + priv->construct_error = NULL; + priv->async_thread = NULL; + + if (!setup_pcilib (priv)) + return; + + camera = UCA_CAMERA (self); + uca_camera_register_unit (camera, "sensor-temperature", UCA_UNIT_DEGREE_CELSIUS); + uca_camera_register_unit (camera, "fpga-temperature", UCA_UNIT_DEGREE_CELSIUS); +} + +G_MODULE_EXPORT GType +uca_camera_get_type (void) { - self->priv = UCA_UFO_CAMERA_GET_PRIVATE(self); + return UCA_TYPE_UFO_CAMERA; } diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index fcacfa0..c3a037f 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -85,6 +85,9 @@ if (INTROSPECTION_SCANNER AND INTROSPECTION_COMPILER) list(APPEND _gir_input "${CMAKE_CURRENT_SOURCE_DIR}/${_src}") endforeach() + list(APPEND _gir_input "${CMAKE_CURRENT_BINARY_DIR}/uca-enums.h") + list(APPEND _gir_input "${CMAKE_CURRENT_BINARY_DIR}/uca-enums.c") + add_custom_command(OUTPUT ${GIR_XML} COMMAND ${INTROSPECTION_SCANNER} --namespace=Uca @@ -199,7 +202,7 @@ install(TARGETS uca COMPONENT libraries) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/libuca.pc - DESTINATION lib/pkgconfig + DESTINATION ${LIB_INSTALL_DIR}/pkgconfig COMPONENT libraries) install(FILES ${uca_HDRS} diff --git a/src/libuca.pc.in b/src/libuca.pc.in index 6401368..3ca4dbe 100644 --- a/src/libuca.pc.in +++ b/src/libuca.pc.in @@ -11,3 +11,4 @@ Description: @UCA_DESCRIPTION@ Version: @VERSION@ Libs: -L${libdir} -luca Cflags: -I${includedir_old} -I${includedir_new} +Requires: glib-2.0 gobject-2.0 diff --git a/src/scangobj.sh.in b/src/scangobj.sh.in index 65766b6..088d67e 100644 --- a/src/scangobj.sh.in +++ b/src/scangobj.sh.in @@ -1 +1 @@ -LD_LIBRARY_PATH=${CMAKE_CURRENT_BINARY_DIR}:/opt/pylon/lib64:/opt/pylon/genicam/bin/Linux64_x64 CC=gcc CFLAGS="${GTK_DOC_CFLAGS}" LDFLAGS="${GTK_DOC_LDFLAGS} -L${CMAKE_CURRENT_BINARY_DIR} -L${CMAKE_CURRENT_BINARY_DIR} -luca `pkg-config --libs gtk+-2.0`" gtkdoc-scangobj --module=uca +LD_LIBRARY_PATH=${CMAKE_CURRENT_BINARY_DIR}:/opt/pylon/lib64:/opt/pylon/genicam/bin/Linux64_x64 CC=gcc CFLAGS="${GTK_DOC_CFLAGS}" LDFLAGS="${GTK_DOC_LDFLAGS} -L${CMAKE_CURRENT_BINARY_DIR} -luca `pkg-config --libs gtk+-2.0`" gtkdoc-scangobj --module=uca diff --git a/src/uca-camera.c b/src/uca-camera.c index 8905a95..5073a57 100644 --- a/src/uca-camera.c +++ b/src/uca-camera.c @@ -116,6 +116,7 @@ struct _UcaCameraPrivate { gboolean is_recording; gboolean is_readout; gboolean transfer_async; + UcaCameraTrigger trigger; }; static void @@ -148,6 +149,10 @@ uca_camera_set_property (GObject *object, guint property_id, const GValue *value } break; + case PROP_TRIGGER_MODE: + priv->trigger = g_value_get_enum (value); + break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); } @@ -172,7 +177,7 @@ uca_camera_get_property(GObject *object, guint property_id, GValue *value, GPara break; case PROP_TRIGGER_MODE: - g_value_set_enum (value, UCA_CAMERA_TRIGGER_AUTO); + g_value_set_enum (value, priv->trigger); break; case PROP_FRAMES_PER_SECOND: @@ -403,6 +408,7 @@ uca_camera_init (UcaCamera *camera) camera->priv->is_recording = FALSE; camera->priv->is_readout = FALSE; camera->priv->transfer_async = FALSE; + camera->priv->trigger = UCA_CAMERA_TRIGGER_AUTO; uca_camera_set_property_unit (camera_properties[PROP_SENSOR_WIDTH], UCA_UNIT_PIXEL); uca_camera_set_property_unit (camera_properties[PROP_SENSOR_HEIGHT], UCA_UNIT_PIXEL); @@ -669,34 +675,31 @@ uca_camera_trigger (UcaCamera *camera, GError **error) /** * uca_camera_grab: * @camera: A #UcaCamera object - * @data: Pointer to pointer to the data. Must not be %NULL. + * @data: (type gulong): Pointer to suitably sized data buffer. Must not be + * %NULL. * @error: Location to store a #UcaCameraError error or %NULL * - * Grab a frame a single frame and store the result in @data. If the pointer - * pointing to the data is %NULL, memory will be allocated otherwise it will be - * used to store the frame. If memory is allocated by uca_camera_grab() it must - * be freed by the caller. + * Grab a frame a single frame and store the result in @data. * * You must have called uca_camera_start_recording() before, otherwise you will * get a #UCA_CAMERA_ERROR_NOT_RECORDING error. - * - * If *data is %NULL after returning from uca_camera_grab() and error is also - * %NULL, the data stream has ended. For example, with cameras that support - * in-camera memory, all frames have been transfered. */ -void -uca_camera_grab (UcaCamera *camera, gpointer *data, GError **error) +gboolean +uca_camera_grab (UcaCamera *camera, gpointer data, GError **error) { UcaCameraClass *klass; + gboolean result; + + /* FIXME: this prevents accessing two independent cameras simultanously. */ static GStaticMutex mutex = G_STATIC_MUTEX_INIT; - g_return_if_fail (UCA_IS_CAMERA(camera)); + g_return_val_if_fail (UCA_IS_CAMERA(camera), FALSE); klass = UCA_CAMERA_GET_CLASS (camera); - g_return_if_fail (klass != NULL); - g_return_if_fail (klass->grab != NULL); - g_return_if_fail (data != NULL); + g_return_val_if_fail (klass != NULL, FALSE); + g_return_val_if_fail (klass->grab != NULL, FALSE); + g_return_val_if_fail (data != NULL, FALSE); g_static_mutex_lock (&mutex); @@ -704,11 +707,12 @@ uca_camera_grab (UcaCamera *camera, gpointer *data, GError **error) g_set_error (error, UCA_CAMERA_ERROR, UCA_CAMERA_ERROR_NOT_RECORDING, "Camera is neither recording nor in readout mode"); else { g_static_mutex_lock (&access_lock); - (*klass->grab) (camera, data, error); + result = (*klass->grab) (camera, data, error); g_static_mutex_unlock (&access_lock); } g_static_mutex_unlock (&mutex); + return result; } /** diff --git a/src/uca-camera.h b/src/uca-camera.h index 87996c6..f6fdace 100644 --- a/src/uca-camera.h +++ b/src/uca-camera.h @@ -129,7 +129,7 @@ struct _UcaCameraClass { void (*start_readout) (UcaCamera *camera, GError **error); void (*stop_readout) (UcaCamera *camera, GError **error); void (*trigger) (UcaCamera *camera, GError **error); - void (*grab) (UcaCamera *camera, gpointer *data, GError **error); + gboolean (*grab) (UcaCamera *camera, gpointer data, GError **error); void (*recording_started) (UcaCamera *camera); void (*recording_stopped) (UcaCamera *camera); @@ -147,9 +147,10 @@ void uca_camera_stop_readout (UcaCamera *camera, GError **error); void uca_camera_trigger (UcaCamera *camera, GError **error); -void uca_camera_grab (UcaCamera *camera, - gpointer *data, - GError **error); +gboolean uca_camera_grab (UcaCamera *camera, + gpointer data, + GError **error) + __attribute__((nonnull (2))); void uca_camera_set_grab_func (UcaCamera *camera, UcaCameraGrabFunc func, gpointer user_data); diff --git a/src/uca-plugin-manager.c b/src/uca-plugin-manager.c index e99f478..5013981 100644 --- a/src/uca-plugin-manager.c +++ b/src/uca-plugin-manager.c @@ -32,6 +32,7 @@ * * @Since: 1.1 */ +#include <gio/gio.h> #include <gmodule.h> #include "uca-plugin-manager.h" @@ -45,7 +46,7 @@ struct _UcaPluginManagerPrivate { static const gchar *MODULE_PATTERN = "libuca([A-Za-z]+)"; -typedef UcaCamera * (*GetCameraFunc) (GError **error); +typedef GType (*GetTypeFunc) (void); /** * UcaPluginManagerError: @@ -208,39 +209,22 @@ find_camera_module_path (GList *search_paths, const gchar *name) return result; } -/** - * uca_plugin_manager_get_camera: - * @manager: A #UcaPluginManager - * @name: Name of the camera module, that maps to libuca<name>.so - * @error: Location for a #GError - * - * Create a new camera instance with camera @name. - * - * Returns: (transfer full): A new #UcaCamera object. - */ -UcaCamera * -uca_plugin_manager_get_camera (UcaPluginManager *manager, - const gchar *name, - GError **error) +static GType +get_camera_type (UcaPluginManagerPrivate *priv, + const gchar *name, + GError **error) { - UcaPluginManagerPrivate *priv; - UcaCamera *camera; GModule *module; - GetCameraFunc *func; gchar *module_path; - GError *tmp_error = NULL; + GetTypeFunc *func; + const gchar *symbol_name = "uca_camera_get_type"; - 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; + "Camera module `%s' not found", name); + return G_TYPE_NONE; } module = g_module_open (module_path, G_MODULE_BIND_LAZY); @@ -249,10 +233,10 @@ uca_plugin_manager_get_camera (UcaPluginManager *manager, 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; + return G_TYPE_NONE; } - func = g_malloc0 (sizeof (GetCameraFunc)); + func = g_malloc0 (sizeof (GetTypeFunc)); if (!g_module_symbol (module, symbol_name, (gpointer *) func)) { g_set_error (error, UCA_PLUGIN_MANAGER_ERROR, UCA_PLUGIN_MANAGER_ERROR_SYMBOL_NOT_FOUND, @@ -262,15 +246,90 @@ uca_plugin_manager_get_camera (UcaPluginManager *manager, if (!g_module_close (module)) g_warning ("%s", g_module_error ()); - return NULL; + return G_TYPE_NONE; } - camera = (*func) (&tmp_error); + return (*func) (); +} - if (tmp_error != NULL) { - g_propagate_error (error, tmp_error); +/** + * uca_plugin_manager_get_camerav: + * @manager: A #UcaPluginManager + * @name: Name of the camera module, that maps to libuca<name>.so + * @n_parameters: number of parameters in @parameters + * @parameters: (array length=n_parameters): the parameters to use to construct + * the camera + * @error: Location for a #GError or %NULL + * + * Create a new camera instance with camera @name. + * + * Returns: (transfer full): A new #UcaCamera object. + * @Since: 1.2 + */ +UcaCamera * +uca_plugin_manager_get_camerav (UcaPluginManager *manager, + const gchar *name, + guint n_parameters, + GParameter *parameters, + GError **error) +{ + UcaPluginManagerPrivate *priv; + UcaCamera *camera; + GType type; + + g_return_val_if_fail (UCA_IS_PLUGIN_MANAGER (manager) && (name != NULL), NULL); + + priv = manager->priv; + type = get_camera_type (priv, name, error); + + if (type == G_TYPE_NONE) return NULL; - } + + camera = (UcaCamera *) g_initable_newv (type, n_parameters, parameters, + NULL, error); + + return camera; +} + +/** + * uca_plugin_manager_get_camera: (skip) + * @manager: A #UcaPluginManager + * @name: Name of the camera module, that maps to libuca<name>.so + * @error: Location for a #GError + * @first_prop_name: (allow-none): name of the first property, or %NULL if no + * properties + * @...: value of the first property, followed by and other property value + * pairs, and ended by %NULL. + * + * Create a new camera instance with camera @name. + * + * Returns: (transfer full): A new #UcaCamera object. + * @Since: 1.2: Pass construction properties. + */ +UcaCamera * +uca_plugin_manager_get_camera (UcaPluginManager *manager, + const gchar *name, + GError **error, + const gchar *first_prop_name, + ...) +{ + UcaPluginManagerPrivate *priv; + UcaCamera *camera; + GType type; + va_list var_args; + + g_return_val_if_fail (UCA_IS_PLUGIN_MANAGER (manager) && (name != NULL), NULL); + + priv = manager->priv; + type = get_camera_type (priv, name, error); + + if (type == G_TYPE_NONE) + return NULL; + + va_start (var_args, first_prop_name); + camera = (UcaCamera *) g_initable_new (type, NULL, error, + first_prop_name, var_args); + va_end (var_args); return camera; } diff --git a/src/uca-plugin-manager.h b/src/uca-plugin-manager.h index 6c3ab4e..10fe9d1 100644 --- a/src/uca-plugin-manager.h +++ b/src/uca-plugin-manager.h @@ -55,9 +55,16 @@ void uca_plugin_manager_add_path (UcaPluginManager *manager const gchar *path); GList *uca_plugin_manager_get_available_cameras (UcaPluginManager *manager); -UcaCamera *uca_plugin_manager_get_camera (UcaPluginManager *manager, +UcaCamera *uca_plugin_manager_get_camerav (UcaPluginManager *manager, const gchar *name, + guint n_parameters, + GParameter *parameters, GError **error); +UcaCamera *uca_plugin_manager_get_camera (UcaPluginManager *manager, + const gchar *name, + GError **error, + const gchar *first_prop_name, + ...); GType uca_plugin_manager_get_type (void); G_END_DECLS diff --git a/src/uca.types.in b/src/uca.types.in index 7526948..76acc2b 100644 --- a/src/uca.types.in +++ b/src/uca.types.in @@ -1,2 +1,5 @@ uca_camera_get_type +uca_camera_error_get_type +uca_camera_trigger_get_type uca_plugin_manager_get_type +uca_unit_get_type diff --git a/test/test-mock.c b/test/test-mock.c index 85c1ba4..7876f5b 100644 --- a/test/test-mock.c +++ b/test/test-mock.c @@ -8,15 +8,31 @@ typedef struct { UcaCamera *camera; } Fixture; +static gchar * +build_mock_plugin_path (void) +{ + gchar *cwd; + gchar *plugin_path; + + cwd = g_get_current_dir (); + plugin_path = g_build_filename (cwd, "plugins", "mock", NULL); + g_free (cwd); + return plugin_path; +} + static void fixture_setup (Fixture *fixture, gconstpointer data) { + gchar *plugin_path; GError *error = NULL; - fixture->manager = uca_plugin_manager_new (); - uca_plugin_manager_add_path (fixture->manager, "./src"); + plugin_path = build_mock_plugin_path (); + g_setenv ("UCA_CAMERA_PATH", plugin_path, TRUE); + g_free (plugin_path); - fixture->camera = uca_plugin_manager_get_camera (fixture->manager, "mock", &error); + fixture->manager = uca_plugin_manager_new (); + fixture->camera = uca_plugin_manager_get_camera (fixture->manager, + "mock", &error, NULL); g_assert (error == NULL); g_assert (fixture->camera); } @@ -39,7 +55,8 @@ static void test_factory (Fixture *fixture, gconstpointer data) { GError *error = NULL; - UcaCamera *camera = uca_plugin_manager_get_camera (fixture->manager, "fox994m3a0yxmy", &error); + UcaCamera *camera = uca_plugin_manager_get_camera (fixture->manager, + "fox994m3a0yxmy", &error, NULL); g_assert_error (error, UCA_PLUGIN_MANAGER_ERROR, UCA_PLUGIN_MANAGER_ERROR_MODULE_NOT_FOUND); g_assert (camera == NULL); } diff --git a/tools/benchmark.c b/tools/benchmark.c index bff8b50..0939d78 100644 --- a/tools/benchmark.c +++ b/tools/benchmark.c @@ -100,7 +100,8 @@ grab_frames_sync (UcaCamera *camera, gpointer buffer, guint n_frames) uca_camera_start_recording (camera, &error); for (guint i = 0; i < n_frames; i++) { - uca_camera_grab(camera, &buffer, &error); + if (!uca_camera_grab (camera, buffer, &error)) + g_warning ("Data stream ended"); if (error != NULL) { g_warning ("Error grabbing frame %02i/%i: `%s'", i, n_frames, error->message); @@ -115,8 +116,12 @@ grab_frames_sync (UcaCamera *camera, gpointer buffer, guint n_frames) static void grab_callback (gpointer data, gpointer user_data) { + static GStaticMutex mutex = G_STATIC_MUTEX_INIT; guint *n_acquired_frames = user_data; + + g_static_mutex_lock (&mutex); *n_acquired_frames += 1; + g_static_mutex_unlock (&mutex); } static void @@ -136,7 +141,6 @@ grab_frames_async (UcaCamera *camera, gpointer buffer, guint n_frames) ; uca_camera_stop_recording (camera, &error); - } static void @@ -204,6 +208,7 @@ benchmark (UcaCamera *camera) g_print ("# Sensor size: %ix%i\n", sensor_width, sensor_height); g_print ("# ROI size: %ix%i\n", roi_width, roi_height); g_print ("# Exposure time: %fs\n", exposure); + g_print ("# Bits: %i\n", bits); /* Synchronous frame acquisition */ g_print ("# %-10s%-10s%-10s%-16s%-16s\n", "type", "n_frames", "n_runs", "frames/s", "MiB/s"); @@ -250,7 +255,7 @@ main (int argc, char *argv[]) g_log_set_handler (NULL, G_LOG_LEVEL_MASK, log_handler, log_channel); manager = uca_plugin_manager_new (); - camera = uca_plugin_manager_get_camera (manager, argv[1], &error); + camera = uca_plugin_manager_get_camera (manager, argv[1], &error, NULL); if (camera == NULL) { g_error ("Initialization: %s", error->message); diff --git a/tools/gen-doc.c b/tools/gen-doc.c index f555a5f..d27bdd8 100644 --- a/tools/gen-doc.c +++ b/tools/gen-doc.c @@ -67,9 +67,9 @@ 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]; + 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); } @@ -77,21 +77,90 @@ print_property_toc (GParamSpec **pspecs, guint n_props) } static void +print_value_info (GParamSpec *pspec) +{ + gchar *default_value = NULL; + GString *range = g_string_new(""); + +#define MAKE_RANGE(spec_type, fmt) \ + { \ + spec_type *spec = (spec_type *) pspec; \ + g_string_printf (range, \ + fmt" ≤ <em>%s</em> ≤ "fmt, \ + spec->minimum, \ + g_param_spec_get_name (pspec), \ + spec->maximum); \ + default_value = g_strdup_printf (fmt, spec->default_value); \ + } + + switch (pspec->value_type) { + case G_TYPE_BOOLEAN: + { + GParamSpecBoolean *spec = (GParamSpecBoolean *) pspec; + default_value = spec->default_value ? g_strdup ("<code>TRUE</code>") : g_strdup ("<code>FALSE</code>"); + } + break; + + case G_TYPE_UINT: + MAKE_RANGE (GParamSpecUInt, "%i"); + break; + + case G_TYPE_FLOAT: + MAKE_RANGE (GParamSpecFloat, "%.1e"); + break; + + case G_TYPE_DOUBLE: + MAKE_RANGE (GParamSpecDouble, "%.1e"); + break; + } + +#undef MAKE_RANGE + + if (g_type_is_a (pspec->value_type, G_TYPE_ENUM)) { + GParamSpecEnum *spec = (GParamSpecEnum *) pspec; + + if (spec->enum_class->n_values > 0) { + g_string_printf (range, "<table><tr><th>Enum name</th><th>Value</th>"); + + for (guint i = 0; i < spec->enum_class->n_values; i++) { + GEnumValue *v = &spec->enum_class->values[i]; + g_string_append_printf (range, + "<tr><td><code>%s</code></td><td>%i</td></tr>", + v->value_name, v->value); + } + + g_string_append_printf (range, "</table>"); + } + } + + if (range->len > 0) + g_print ("<p>Possible values: %s</p>", range->str); + + if (default_value != NULL) { + g_print ("<p>Default value: %s</p>", default_value); + g_free (default_value); + } + + g_string_free (range, TRUE); +} + +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]; + 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_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)); + print_value_info (pspec); g_print ("</dd>"); } @@ -104,7 +173,7 @@ 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); @@ -136,7 +205,7 @@ int main(int argc, char *argv[]) } else { name = argv[1]; - camera = uca_plugin_manager_get_camera (manager, name, &error); + camera = uca_plugin_manager_get_camera (manager, name, &error, NULL); } if (camera == NULL) { diff --git a/tools/grab-async.c b/tools/grab-async.c index 2c4bf04..00f2879 100644 --- a/tools/grab-async.c +++ b/tools/grab-async.c @@ -94,7 +94,7 @@ main(int argc, char *argv[]) } manager = uca_plugin_manager_new (); - camera = uca_plugin_manager_get_camera (manager, argv[1], &error); + camera = uca_plugin_manager_get_camera (manager, argv[1], &error, NULL); if (camera == NULL) { g_print("Error during initialization: %s\n", error->message); diff --git a/tools/grab.c b/tools/grab.c index 1518997..e8e91be 100644 --- a/tools/grab.c +++ b/tools/grab.c @@ -75,7 +75,7 @@ int main(int argc, char *argv[]) } manager = uca_plugin_manager_new (); - camera = uca_plugin_manager_get_camera (manager, argv[1], &error); + camera = uca_plugin_manager_get_camera (manager, argv[1], &error, NULL); if (camera == NULL) { g_print("Error during initialization: %s\n", error->message); @@ -127,7 +127,7 @@ int main(int argc, char *argv[]) while (counter < 5) { g_print(" grab frame ... "); g_timer_start(timer); - uca_camera_grab(camera, &buffer, &error); + uca_camera_grab(camera, buffer, &error); if (error != NULL) { g_print("\nError: %s\n", error->message); diff --git a/tools/gui/control.c b/tools/gui/control.c index f74e0f1..c177f07 100644 --- a/tools/gui/control.c +++ b/tools/gui/control.c @@ -135,6 +135,8 @@ update_pixbuf_dimensions (ThreadData *data) if (data->pixbuf != NULL) g_object_unref (data->pixbuf); + data->display_width = (gint) data->width * data->zoom_factor; + data->display_height = (gint) data->height * data->zoom_factor; data->pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8, data->display_width, data->display_height); data->pixels = gdk_pixbuf_get_pixels (data->pixbuf); gtk_image_set_from_pixbuf (GTK_IMAGE (data->image), data->pixbuf); @@ -159,7 +161,8 @@ preview_frames (void *args) gpointer buffer; buffer = ring_buffer_get_current_pointer (data->buffer); - uca_camera_grab (data->camera, &buffer, &error); + uca_camera_trigger (data->camera, &error); + uca_camera_grab (data->camera, buffer, &error); if (error == NULL) { convert_grayscale_to_rgb (data, buffer); @@ -189,7 +192,7 @@ record_frames (gpointer args) while (data->state == RECORDING) { buffer = ring_buffer_get_current_pointer (data->buffer); - uca_camera_grab (data->camera, &buffer, NULL); + uca_camera_grab (data->camera, buffer, NULL); if (error == NULL) { ring_buffer_proceed (data->buffer); @@ -343,7 +346,7 @@ download_frames (ThreadData *data) while (error == NULL) { buffer = ring_buffer_get_current_pointer (data->buffer); - uca_camera_grab (data->camera, &buffer, &error); + uca_camera_grab (data->camera, buffer, &error); ring_buffer_proceed (data->buffer); gdk_threads_enter (); gtk_adjustment_set_value (data->download_adjustment, current_frame++); @@ -415,13 +418,25 @@ on_zoom_changed (GtkComboBox *widget, ThreadData *data) gtk_combo_box_get_active_iter (widget, &iter); gtk_tree_model_get (model, &iter, FACTOR_COLUMN, &factor, -1); - data->display_width = (gint) data->width * factor; - data->display_height = (gint) data->height * factor; data->zoom_factor = factor; update_pixbuf_dimensions (data); } static void +on_roi_width_changed (GObject *object, GParamSpec *pspec, ThreadData *data) +{ + g_object_get (object, "roi-width", &data->width, NULL); + update_pixbuf_dimensions (data); +} + +static void +on_roi_height_changed (GObject *object, GParamSpec *pspec, ThreadData *data) +{ + g_object_get (object, "roi-height", &data->height, NULL); + update_pixbuf_dimensions (data); +} + +static void create_main_window (GtkBuilder *builder, const gchar* camera_name) { static ThreadData td; @@ -442,7 +457,7 @@ create_main_window (GtkBuilder *builder, const gchar* camera_name) guint width, height; GError *error = NULL; - camera = uca_plugin_manager_get_camera (plugin_manager, camera_name, &error); + camera = uca_plugin_manager_get_camera (plugin_manager, camera_name, &error, NULL); if ((camera == NULL) || (error != NULL)) { g_error ("%s\n", error->message); @@ -455,6 +470,9 @@ create_main_window (GtkBuilder *builder, const gchar* camera_name) "sensor-bitdepth", &bits_per_sample, NULL); + g_signal_connect (camera, "notify::roi-width", (GCallback) on_roi_width_changed, &td); + g_signal_connect (camera, "notify::roi-height", (GCallback) on_roi_height_changed, &td); + histogram_view = egg_histogram_view_new (); property_tree_view = egg_property_tree_view_new (G_OBJECT (camera)); property_window = GTK_CONTAINER (gtk_builder_get_object (builder, "property-window")); diff --git a/tools/perf-overhead.c b/tools/perf-overhead.c index 6735e6f..7661dbc 100644 --- a/tools/perf-overhead.c +++ b/tools/perf-overhead.c @@ -163,7 +163,7 @@ main (int argc, char *argv[]) } manager = uca_plugin_manager_new (); - camera = uca_plugin_manager_get_camera (manager, argv[1], &error); + camera = uca_plugin_manager_get_camera (manager, argv[1], &error, NULL); if (camera == NULL) { g_print ("Error during initialization: %s\n", error->message); |