/* 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" #include "device_manager.h" struct dummy_device { struct device device; struct device_manager *dm; int width; int height; int stride; double exposure_ms; double gain; bool ready; int n; struct image *image; GSource *source; }; static char * dummy_poll(void); static struct device * dummy_open(struct device_manager *dm, 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 gboolean dummy_source_cb(gpointer user_data) { struct dummy_device *mdev = user_data; mdev->ready = true; device_manager_driver_call_callback(mdev->dm); return G_SOURCE_CONTINUE; } 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); g_assert(!mdev->source); /* Add source. */ mdev->source = g_timeout_source_new(1000 / 10); g_source_set_callback(mdev->source, dummy_source_cb, mdev, NULL); device_manager_driver_source_attach(mdev->dm, mdev->source); /* Done. */ mdev->ready = true; 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; if (!mdev->ready) return NULL; mdev->ready = false; /* Prepare image. */ if (!mdev->image) mdev->image = image_new(mdev->width, mdev->height, mdev->stride, IMAGE_FORMAT_XBGR32); uint8_t *p = mdev->image->pixels; int mb = 0; int mg = 0; int mr = 0; int n = mdev->n % (3 * 255); if (n < 255) { mb = 255 - n; mg = n; } else if (n < 510) { n -= 255; mg = 255 - n; mr = n; } else { n -= 510; mr = 255 - n; mb = n; } mdev->n += 4; for (int y = 0; y < mdev->height; y++) { for (int x = 0; x < mdev->width; x++) { int g = (x ^ y) & 0xff; *p++ = g * mb / 255; *p++ = g * mg / 255; *p++ = g * mr / 255; *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; g_assert(mdev->source); g_source_destroy(mdev->source); g_source_unref(mdev->source); mdev->source = 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(struct device_manager *dm, 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->dm = dm; 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->ready = false; mdev->n = 0; mdev->image = NULL; mdev->source = NULL; /* Done. */ return &mdev->device; }