From 4fd2aab9b24b988d06b4f186dbdf8265e829c9ff Mon Sep 17 00:00:00 2001 From: Nicolas Schodet Date: Fri, 1 May 2020 12:22:02 +0200 Subject: Add dummy camera --- src/device.c | 33 +++++++--- src/device.h | 13 ++++ src/dummy.c | 184 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/dummy.h | 31 ++++++++++ src/meson.build | 11 ++-- src/moticam.c | 4 +- 6 files changed, 262 insertions(+), 14 deletions(-) create mode 100644 src/dummy.c create mode 100644 src/dummy.h diff --git a/src/device.c b/src/device.c index 09a94e3..6189de1 100644 --- a/src/device.c +++ b/src/device.c @@ -23,9 +23,11 @@ #include "device.h" #include "moticam.h" +#include "dummy.h" static const struct device_driver *drivers[] = { &moticam_device_driver, + &dummy_device_driver, NULL }; @@ -59,11 +61,13 @@ device_open(libusb_context *usb, GError **error) } else { for (const struct device_driver **dd = drivers; !found_usb_device && *dd; dd++) { - char *device_name = (*dd)->usb_poll(&desc); - if (device_name) { - found_usb_device = usb_device; - found_device_name = device_name; - found_device_driver = *dd; + if ((*dd)->usb_poll) { + char *device_name = (*dd)->usb_poll(&desc); + if (device_name) { + found_usb_device = usb_device; + found_device_name = device_name; + found_device_driver = *dd; + } } } } @@ -73,8 +77,23 @@ device_open(libusb_context *usb, GError **error) g_free(found_device_name); device = found_device_driver->usb_open(usb, found_usb_device, error); } else { - g_set_error(error, DEVICE_ERROR, DEVICE_ERROR_LIST, - "no device found"); + for (const struct device_driver **dd = drivers; + !found_device_name && *dd; dd++) { + if ((*dd)->poll) { + char *device_name = (*dd)->poll(); + if (device_name) { + found_device_name = device_name; + found_device_driver = *dd; + } + } + } + if (found_device_name) { + g_free(found_device_name); + device = found_device_driver->open(error); + } else { + g_set_error(error, DEVICE_ERROR, DEVICE_ERROR_LIST, + "no device found"); + } } libusb_free_device_list(list, 1); return device; diff --git a/src/device.h b/src/device.h index 7028ebb..931df2d 100644 --- a/src/device.h +++ b/src/device.h @@ -45,6 +45,15 @@ typedef char *(*device_driver_usb_poll_f)( typedef struct device *(*device_driver_usb_open_f)( libusb_context *usb, libusb_device *usb_device, GError **error); +/* Poll function. If a device is handled by this driver, it should return a + * dynamically allocated string naming this device. */ +typedef char *(*device_driver_poll_f)(void); + +/* Open function. The device driver previously declared that it handles a + * device. */ +typedef struct device *(*device_driver_open_f)( + GError **error); + /* Information on a device driver. */ struct device_driver { /* Driver name. */ @@ -53,6 +62,10 @@ struct device_driver { device_driver_usb_poll_f usb_poll; /* Open an USB device. */ device_driver_usb_open_f usb_open; + /* Poll this driver for support without USB. */ + device_driver_poll_f poll; + /* Open a device without USB. */ + device_driver_open_f open; }; /* Information on a supported resolution. */ diff --git a/src/dummy.c b/src/dummy.c new file mode 100644 index 0000000..834f212 --- /dev/null +++ b/src/dummy.c @@ -0,0 +1,184 @@ +/* Camicro - Microscope camera viewer. + * + * This is a dummy camera for testing. + * + * Copyright (C) 2020 Nicolas Schodet + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Contact : + * Web: http://ni.fr.eu.org/ + * Email: + */ +#include "dummy.h" + +struct dummy_device { + struct device device; + int width; + int height; + int stride; + double exposure_ms; + double gain; + struct image *image; +}; + +static char * +dummy_poll(void); + +static struct device * +dummy_open(GError **error); + +const struct device_driver dummy_device_driver = { + "Dummy camera", + .poll = &dummy_poll, + .open = &dummy_open, +}; + +static const struct device_info_resolution dummy_device_info_resolution[] = { + { 1024, 768 }, +}; + +static const struct device_info dummy_device_info = { + .exposure_min_ms = 1, + .exposure_max_ms = 5000, + .exposure_default_ms = 100, + .exposure_step_ms = 1, + .gain_min = 0.5, + .gain_max = 5.0, + .gain_default = 1, + .gain_step = 0.5, + .resolutions = 1, + .resolution = dummy_device_info_resolution, +}; + +static const struct device_info * +dummy_get_info(struct device *device) +{ + return &dummy_device_info; +} + +static void +dummy_set_exposure(struct device *device, double exposure_ms) +{ + struct dummy_device *mdev = (struct dummy_device *) device; + mdev->exposure_ms = exposure_ms; +} + +static void +dummy_set_gain(struct device *device, double gain) +{ + struct dummy_device *mdev = (struct dummy_device *) device; + mdev->gain = gain; +} + +static void +dummy_set_resolution(struct device *device, int width, int height, + int stride) +{ + struct dummy_device *mdev = (struct dummy_device *) device; + g_assert(!mdev->image); + g_assert(stride == 0 || stride >= width * 4); + /* Store parameters. */ + mdev->width = width; + mdev->height = height; + mdev->stride = stride ? stride : width * 4; +} + +static bool +dummy_start(struct device *device, GError **error) +{ + g_return_val_if_fail(error == NULL || *error == NULL, false); + struct dummy_device *mdev = (struct dummy_device *) device; + g_assert(!mdev->image); + /* Nothing to do. */ + return true; +} + +static struct image * +dummy_read(struct device *device, GError **error) +{ + g_return_val_if_fail(error == NULL || *error == NULL, NULL); + struct dummy_device *mdev = (struct dummy_device *) device; + /* Prepare image. */ + if (!mdev->image) { + mdev->image = image_new(mdev->width, mdev->height, mdev->stride, + IMAGE_FORMAT_XBGR32); + uint8_t *p = mdev->image->pixels; + for (int y = 0; y < mdev->height; y++) { + for (int x = 0; x < mdev->width; x++) { + *p++ = (x ^ y) & 0xffffff; + *p++ = 0; + *p++ = 0; + *p++ = 0xff; + } + } + } + image_ref(mdev->image); + return mdev->image; +} + +static bool +dummy_stop(struct device *device, GError **error) +{ + g_return_val_if_fail(error == NULL || *error == NULL, false); + struct dummy_device *mdev = (struct dummy_device *) device; + if (mdev->image) { + image_unref(mdev->image); + mdev->image = NULL; + } + return true; +} + +static bool +dummy_close(struct device *device, GError **error) +{ + g_return_val_if_fail(error == NULL || *error == NULL, false); + struct dummy_device *mdev = (struct dummy_device *) device; + bool ret = true; + if (mdev->image) + ret = dummy_stop(device, error); + free(device); + return ret; +} + +static char * +dummy_poll(void) +{ + return g_strdup("Dummy"); +} + +static struct device * +dummy_open(GError **error) +{ + g_return_val_if_fail(error == NULL || *error == NULL, NULL); + /* Create context. */ + struct dummy_device *mdev = g_new(struct dummy_device, 1); + mdev->device.get_info = &dummy_get_info; + mdev->device.set_exposure = &dummy_set_exposure; + mdev->device.set_gain = &dummy_set_gain; + mdev->device.set_resolution = &dummy_set_resolution; + mdev->device.start = &dummy_start; + mdev->device.read = &dummy_read; + mdev->device.stop = &dummy_stop; + mdev->device.close = &dummy_close; + mdev->width = 0; + mdev->height = 0; + mdev->stride = 0; + mdev->exposure_ms = dummy_device_info.exposure_default_ms; + mdev->gain = dummy_device_info.gain_default; + mdev->image = NULL; + /* Done. */ + return &mdev->device; +} diff --git a/src/dummy.h b/src/dummy.h new file mode 100644 index 0000000..481bd90 --- /dev/null +++ b/src/dummy.h @@ -0,0 +1,31 @@ +#ifndef dummy_h +#define dummy_h +/* Camicro - Microscope camera viewer. + * + * This is a dummy camera for testing. + * + * Copyright (C) 2020 Nicolas Schodet + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Contact : + * Web: http://ni.fr.eu.org/ + * Email: + */ +#include "device.h" + +extern const struct device_driver dummy_device_driver; + +#endif /* dummy_h */ diff --git a/src/meson.build b/src/meson.build index cf832e1..2d03302 100644 --- a/src/meson.build +++ b/src/meson.build @@ -1,13 +1,14 @@ sources = [ - 'device.c', 'cli.c', + 'device.c', + 'dummy.c', + 'gui_app.c', + 'gui_app_window.c', 'image.c', + 'main.c', + 'moticam.c', 'options.c', - 'gui_app_window.c', 'usb_source.c', - 'moticam.c', - 'main.c', - 'gui_app.c', 'utils.c', ] diff --git a/src/moticam.c b/src/moticam.c index 232fb77..c628c6f 100644 --- a/src/moticam.c +++ b/src/moticam.c @@ -60,8 +60,8 @@ moticam_stop(struct device *device, GError **error); const struct device_driver moticam_device_driver = { "Moticam USB cameras", - &moticam_usb_poll, - &moticam_usb_open, + .usb_poll = &moticam_usb_poll, + .usb_open = &moticam_usb_open, }; static const struct device_info_resolution moticam_device_info_resolution[] = { -- cgit v1.2.3