From b4703718ece48fc5a6f01ae6873fae7d8ca0b710 Mon Sep 17 00:00:00 2001 From: Nicolas Schodet Date: Mon, 4 May 2020 22:32:40 +0200 Subject: Add device manager --- src/cli.c | 24 +++----- src/device.c | 71 ---------------------- src/device.h | 4 -- src/device_manager.c | 162 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/device_manager.h | 49 ++++++++++++++++ src/gui_app.c | 40 ++++--------- src/meson.build | 1 + 7 files changed, 232 insertions(+), 119 deletions(-) create mode 100644 src/device_manager.c create mode 100644 src/device_manager.h diff --git a/src/cli.c b/src/cli.c index a5c20c7..608aa58 100644 --- a/src/cli.c +++ b/src/cli.c @@ -23,12 +23,12 @@ #include #include "cli.h" -#include "device.h" +#include "device_manager.h" #include "utils.h" static bool -cli_read_images(libusb_context *usb, struct device *device, int count, - bool raw, const char *out, GError **error) +cli_read_images(struct device *device, int count, bool raw, const char *out, + GError **error) { g_return_val_if_fail(error == NULL || *error == NULL, false); if (!device_start(device, error)) @@ -43,10 +43,7 @@ cli_read_images(libusb_context *usb, struct device *device, int count, ret = false; } else if (!image) { /* No image yet, handle events. */ - int r = libusb_handle_events(usb); - if (r) - utils_fatal("unable to handle libusb events: %s", - libusb_strerror(r)); + g_main_context_iteration(NULL, TRUE); } else { /* Image received. */ if (!raw && image->format != IMAGE_FORMAT_XBGR32) { @@ -73,12 +70,9 @@ cli_read_images(libusb_context *usb, struct device *device, int count, int cli_run(struct options *options) { - libusb_context *usb; - int r = libusb_init(&usb); - if (r) - utils_fatal("unable to initialize libusb: %s", libusb_strerror(r)); + struct device_manager *device_manager = device_manager_new(NULL); GError *error = NULL; - struct device *device = device_open(usb, &error); + struct device *device = device_manager_open(device_manager, &error); if (!device) utils_fatal("unable to find device: %s", error->message); const struct device_info *info = device_get_info(device); @@ -98,11 +92,11 @@ cli_run(struct options *options) if (width == -1) utils_fatal("no matching resolution"); device_set_resolution(device, width, height, 0); - if (!cli_read_images(usb, device, options->count, options->raw, - options->out, &error)) + if (!cli_read_images(device, options->count, options->raw, options->out, + &error)) utils_fatal("unable to read images: %s", error->message); if (!device_close(device, &error)) utils_fatal("unable to close device: %s", error->message); - libusb_exit(usb); + device_manager_destroy(device_manager); return EXIT_SUCCESS; } diff --git a/src/device.c b/src/device.c index 6189de1..5d98b2a 100644 --- a/src/device.c +++ b/src/device.c @@ -22,83 +22,12 @@ */ #include "device.h" -#include "moticam.h" -#include "dummy.h" - -static const struct device_driver *drivers[] = { - &moticam_device_driver, - &dummy_device_driver, - NULL -}; - GQuark device_error_quark(void) { return g_quark_from_static_string("device-error-quark"); } -struct device * -device_open(libusb_context *usb, GError **error) -{ - g_return_val_if_fail(error == NULL || *error == NULL, NULL); - libusb_device **list; - libusb_device *found_usb_device = NULL; - char *found_device_name = NULL; - const struct device_driver *found_device_driver = NULL; - ssize_t cnt = libusb_get_device_list(usb, &list); - if (cnt < 0) { - g_set_error(error, DEVICE_ERROR, DEVICE_ERROR_LIST, - "can not list devices: %s", libusb_strerror(cnt)); - return NULL; - } - for (ssize_t i = 0; !found_usb_device && i < cnt; i++) { - libusb_device *usb_device = list[i]; - struct libusb_device_descriptor desc; - int r = libusb_get_device_descriptor(usb_device, &desc); - if (r) { - g_warning("can not get device descriptor: %s", - libusb_strerror(r)); - } else { - for (const struct device_driver **dd = drivers; - !found_usb_device && *dd; 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; - } - } - } - } - } - struct device *device = NULL; - if (found_usb_device) { - g_free(found_device_name); - device = found_device_driver->usb_open(usb, found_usb_device, error); - } else { - 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; -} - const struct device_info * device_get_info(struct device *device) { diff --git a/src/device.h b/src/device.h index 931df2d..904e21b 100644 --- a/src/device.h +++ b/src/device.h @@ -161,10 +161,6 @@ enum DeviceError { GQuark device_error_quark(void); -/* Find and open device. */ -struct device * -device_open(libusb_context *usb, GError **error); - /* Retrieve informations. */ const struct device_info * device_get_info(struct device *device); diff --git a/src/device_manager.c b/src/device_manager.c new file mode 100644 index 0000000..ee570d4 --- /dev/null +++ b/src/device_manager.c @@ -0,0 +1,162 @@ +/* Camicro - Microscope camera viewer. + * + * 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_manager.h" +#include "usb_source.h" + +#include + +#include "moticam.h" +#include "dummy.h" + +struct device_manager +{ + libusb_context *usb; + GSource *usb_source; + device_manager_callback_f callback; + void *user_data; +}; + +static const struct device_driver *drivers[] = { + &moticam_device_driver, + &dummy_device_driver, + NULL +}; + +static gboolean +device_manager_usb_source_cb(gpointer user_data) +{ + struct device_manager *dm = user_data; + struct timeval tv; + tv.tv_sec = 0; + tv.tv_usec = 0; + libusb_handle_events_timeout(dm->usb, &tv); + if (dm->callback) + dm->callback(dm->user_data); + return G_SOURCE_CONTINUE; +} + +struct device_manager * +device_manager_new(GMainContext *context) +{ + /* Create context. */ + struct device_manager *dm = g_new(struct device_manager, 1); + dm->usb = NULL; + dm->usb_source = NULL; + dm->callback = NULL; + dm->user_data = NULL; + /* Initialize USB. */ + int r = libusb_init(&dm->usb); + if (r) + g_error("unable to initialize libusb: %s", libusb_strerror(r)); + dm->usb_source = usb_source_new(dm->usb); + g_source_set_callback(dm->usb_source, device_manager_usb_source_cb, dm, + NULL); + g_source_attach(dm->usb_source, context); + /* Done. */ + return dm; +} + +void +device_manager_set_callback(struct device_manager *dm, + device_manager_callback_f callback, void *user_data) +{ + g_assert(dm); + dm->callback = callback; + dm->user_data = user_data; +} + +struct device * +device_manager_open(struct device_manager *dm, GError **error) +{ + g_assert(dm); + g_return_val_if_fail(error == NULL || *error == NULL, NULL); + libusb_device **list; + libusb_device *found_usb_device = NULL; + char *found_device_name = NULL; + const struct device_driver *found_device_driver = NULL; + ssize_t cnt = libusb_get_device_list(dm->usb, &list); + if (cnt < 0) { + g_set_error(error, DEVICE_ERROR, DEVICE_ERROR_LIST, + "can not list devices: %s", libusb_strerror(cnt)); + return NULL; + } + for (ssize_t i = 0; !found_usb_device && i < cnt; i++) { + libusb_device *usb_device = list[i]; + struct libusb_device_descriptor desc; + int r = libusb_get_device_descriptor(usb_device, &desc); + if (r) { + g_warning("can not get device descriptor: %s", + libusb_strerror(r)); + } else { + for (const struct device_driver **dd = drivers; + !found_usb_device && *dd; 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; + } + } + } + } + } + struct device *device = NULL; + if (found_usb_device) { + g_free(found_device_name); + device = found_device_driver->usb_open(dm->usb, found_usb_device, + error); + } else { + 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; +} + +void +device_manager_destroy(struct device_manager *dm) +{ + g_assert(dm); + /* Shutdown USB. */ + g_source_destroy(dm->usb_source); + g_source_unref(dm->usb_source); + libusb_exit(dm->usb); + /* Free context. */ + g_free(dm); +} diff --git a/src/device_manager.h b/src/device_manager.h new file mode 100644 index 0000000..1db5d81 --- /dev/null +++ b/src/device_manager.h @@ -0,0 +1,49 @@ +#ifndef device_manager_h +#define device_manager_h +/* Camicro - Microscope camera viewer. + * + * 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" + +struct device_manager; + +typedef void (*device_manager_callback_f) (void *user_data); + +/* Initialize a new device manager and attach it to the main context (or + * default main context if NULL). */ +struct device_manager * +device_manager_new(GMainContext *context); + +/* Set callback called on device readiness. */ +void +device_manager_set_callback(struct device_manager *dm, + device_manager_callback_f callback, void *user_data); + +/* Find and open device. */ +struct device * +device_manager_open(struct device_manager *dm, GError **error); + +/* Destroy a device manager, free all used resources. */ +void +device_manager_destroy(struct device_manager *dm); + +#endif /* device_manager_h */ diff --git a/src/gui_app.c b/src/gui_app.c index e7cc862..1a2f501 100644 --- a/src/gui_app.c +++ b/src/gui_app.c @@ -21,9 +21,9 @@ * Email: */ #include "gui_app.h" +#include "device_manager.h" #include "gui_app_window.h" #include "options.h" -#include "usb_source.h" #include "utils.h" struct _GuiApp { @@ -33,33 +33,23 @@ struct _GuiApp { typedef struct _GuiAppPrivate GuiAppPrivate; struct _GuiAppPrivate { - libusb_context *usb; - GSource *usb_source; + struct device_manager *device_manager; }; G_DEFINE_TYPE_WITH_PRIVATE(GuiApp, gui_app, GTK_TYPE_APPLICATION) -static gboolean -gui_app_usb_source_cb(gpointer user_data) +static void +gui_app_device_manager_cb(gpointer user_data) { GuiApp *app = user_data; - GuiAppPrivate *priv = gui_app_get_instance_private(app); - struct timeval tv; - tv.tv_sec = 0; - tv.tv_usec = 0; - int r = libusb_handle_events_timeout(priv->usb, &tv); - if (r) - g_error("unable to handle libusb events: %s", libusb_strerror(r)); g_signal_emit_by_name(app, "video-ready"); - return G_SOURCE_CONTINUE; } static void gui_app_init(GuiApp *app) { GuiAppPrivate *priv = gui_app_get_instance_private(app); - priv->usb = NULL; - priv->usb_source = NULL; + priv->device_manager = NULL; options_add(G_APPLICATION(app)); } @@ -68,13 +58,9 @@ gui_app_startup(GApplication *app) { G_APPLICATION_CLASS(gui_app_parent_class)->startup(app); GuiAppPrivate *priv = gui_app_get_instance_private(GUI_APP(app)); - int r = libusb_init(&priv->usb); - if (r) - g_error("unable to initialize libusb: %s", libusb_strerror(r)); - priv->usb_source = usb_source_new(priv->usb); - g_source_set_callback(priv->usb_source, gui_app_usb_source_cb, app, - NULL); - g_source_attach(priv->usb_source, NULL); + priv->device_manager = device_manager_new(NULL); + device_manager_set_callback(priv->device_manager, + gui_app_device_manager_cb, app); } static void @@ -82,7 +68,7 @@ gui_app_activate(GApplication *app) { GuiAppPrivate *priv = gui_app_get_instance_private(GUI_APP(app)); GError *error = NULL; - struct device *device = device_open(priv->usb, &error); + struct device *device = device_manager_open(priv->device_manager, &error); if (!device) { utils_dialog_error(NULL, "unable to find device: %s", error->message); g_error_free(error); @@ -98,12 +84,8 @@ static void gui_app_shutdown(GApplication *app) { GuiAppPrivate *priv = gui_app_get_instance_private(GUI_APP(app)); - if (priv->usb_source) { - g_source_destroy(priv->usb_source); - g_source_unref(priv->usb_source); - } - if (priv->usb) - libusb_exit(priv->usb); + if (priv->device_manager) + device_manager_destroy(priv->device_manager); G_APPLICATION_CLASS(gui_app_parent_class)->shutdown(app); } diff --git a/src/meson.build b/src/meson.build index 2d03302..b6cc5ea 100644 --- a/src/meson.build +++ b/src/meson.build @@ -1,6 +1,7 @@ sources = [ 'cli.c', 'device.c', + 'device_manager.c', 'dummy.c', 'gui_app.c', 'gui_app_window.c', -- cgit v1.2.3