summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/cli.c24
-rw-r--r--src/device.c71
-rw-r--r--src/device.h4
-rw-r--r--src/device_manager.c162
-rw-r--r--src/device_manager.h49
-rw-r--r--src/gui_app.c40
-rw-r--r--src/meson.build1
7 files changed, 232 insertions, 119 deletions
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 <glib.h>
#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: <nico at ni.fr.eu.org>
+ */
+#include "device_manager.h"
+#include "usb_source.h"
+
+#include <glib.h>
+
+#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: <nico at ni.fr.eu.org>
+ */
+#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: <nico at ni.fr.eu.org>
*/
#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',