From 037e989c3e618bef8120ba2df3a22abc57f9eaf8 Mon Sep 17 00:00:00 2001 From: Javier Date: Sat, 10 Mar 2018 17:44:47 +0100 Subject: drop udisks dependency (instead use gio volume monitor) --- monitor.c | 212 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 212 insertions(+) create mode 100644 monitor.c (limited to 'monitor.c') diff --git a/monitor.c b/monitor.c new file mode 100644 index 0000000..13214bf --- /dev/null +++ b/monitor.c @@ -0,0 +1,212 @@ +#include "rodisc.h" + +#include + +static GVolumeMonitor *monitor; + +static bool guess_volume_type(GVolume *volume, const char **type) +{ + GIcon *icon = g_volume_get_icon(volume); + g_return_val_if_fail(G_IS_THEMED_ICON(icon), false); + GThemedIcon *ticon = G_THEMED_ICON(icon); + + const gchar * const * names = g_themed_icon_get_names(ticon); + for (const gchar * const * name = names; *name; ++name) { + if (g_str_has_prefix(*name, "media-optical")) { + if (g_str_has_prefix(*name, "media-optical-dvd")) { + *type = RODISC_TYPE_DVD; + } else if (g_str_has_prefix(*name, "media-optical-cd")) { + *type = RODISC_TYPE_CD; + } else { + *type = RODISC_TYPE_GENERIC; + } + return true; + } + } + + return false; +} + +static bool set_disc_attrs(RODisc *disc, GVolume *volume) +{ + g_free(disc->label); + + disc->label = g_volume_get_identifier(volume, G_VOLUME_IDENTIFIER_KIND_LABEL); + if (!disc->label || disc->label[0] == '\0') { + g_free(disc->label); + disc->label = g_volume_get_name(volume); + } + if (!disc->label || disc->label[0] == '\0') { + g_free(disc->label); + disc->label = g_strdup("Disc"); + } + + // Open file and seek to end to verify read permission and file size + + GError *error = NULL; + GFileInputStream * stream = g_file_read(disc->file, NULL, &error); + + if (!stream) { + g_warning("Could not open file '%s' for reading: %s", + disc->file_path, error->message); + g_error_free(error); + return false; + } + + if (!g_seekable_seek(G_SEEKABLE(stream), 0, G_SEEK_END, NULL, &error)) { + g_warning("Could not seek in file '%s' for obtaining file size: %s", + disc->file_path, error->message); + g_error_free(error); + return false; + } + + disc->size = g_seekable_tell(G_SEEKABLE(stream)); + + g_input_stream_close(G_INPUT_STREAM(stream), NULL, NULL); + g_object_unref(stream); + + return true; +} + +static void try_add_volume(GVolume *volume) +{ + const char * type; + if (!guess_volume_type(volume, &type)) { + // Ignore non-optical device + return; + } + + char *device_file_path = g_volume_get_identifier(volume, G_VOLUME_IDENTIFIER_KIND_UNIX_DEVICE); + if (!device_file_path) { + return; + } + + RODisc *disc = rodisc_new(); + + char *basename = g_path_get_basename(device_file_path); + + disc->id = device_file_path; + disc->uri = g_strconcat("/", basename, NULL); + disc->file = g_file_new_for_path(device_file_path); + disc->file_path = g_file_get_path(disc->file); + disc->type = type; + + g_free(basename); + + if (set_disc_attrs(disc, volume)) { + rodisc_export(disc); + } else { + rodisc_destroy(disc); + } +} + +static void try_update_volume(GVolume *volume, RODisc *disc) +{ + const char * type; + if (!guess_volume_type(volume, &type)) { + g_debug("no longer a optical media"); + rodisc_remove(disc); + return; + } + + disc->type = type; + + if (set_disc_attrs(disc, volume)) { + rodisc_refresh(disc); + } else { + rodisc_remove(disc); + } +} + +static void monitor_volume_added_cb(GVolumeMonitor *volume_monitor, GVolume *volume, + gpointer user_data) +{ + char *device_file_path = g_volume_get_identifier(volume, G_VOLUME_IDENTIFIER_KIND_UNIX_DEVICE); + if (!device_file_path) { + return; + } + + g_debug("Volume added: %s", device_file_path); + + RODisc *disc = rodisc_lookup(device_file_path); + if (disc) { + g_warning("Device already added: %s", device_file_path); + } else { + try_add_volume(volume); + } + + g_free(device_file_path); +} + +static void monitor_volume_changed_cb(GVolumeMonitor *volume_monitor, GVolume *volume, + gpointer user_data) +{ + char *device_file_path = g_volume_get_identifier(volume, G_VOLUME_IDENTIFIER_KIND_UNIX_DEVICE); + if (!device_file_path) { + return; + } + + g_debug("Volume changed: %s", device_file_path); + + RODisc *disc = rodisc_lookup(device_file_path); + if (disc) { + try_update_volume(volume, disc); + } else { + try_add_volume(volume); + } + + g_free(device_file_path); +} + +static void monitor_volume_removed_cb(GVolumeMonitor *volume_monitor, GVolume *volume, + gpointer user_data) +{ + char *device_file_path = g_volume_get_identifier(volume, G_VOLUME_IDENTIFIER_KIND_UNIX_DEVICE); + if (!device_file_path) { + return; + } + + g_debug("Volume removed: %s", device_file_path); + + RODisc *disc = rodisc_lookup(device_file_path); + if (disc) { + rodisc_remove(disc); + } + + g_free(device_file_path); +} + +static void enumerate_volumes() +{ + GList *volumes = g_volume_monitor_get_volumes(monitor); + for (GList *l = volumes; l != NULL; l = l->next) { + GVolume *volume = G_VOLUME(l->data); + try_add_volume(volume); + } + g_list_free_full(volumes, g_object_unref); +} + +bool monitor_start() +{ + monitor = g_volume_monitor_get(); + if (!monitor) { + g_warning("Could not get volume monitor"); + return false; + } + + g_signal_connect(monitor, "volume-added", + G_CALLBACK(monitor_volume_added_cb), NULL); + g_signal_connect(monitor, "volume-changed", + G_CALLBACK(monitor_volume_changed_cb), NULL); + g_signal_connect(monitor, "volume-removed", + G_CALLBACK(monitor_volume_removed_cb), NULL); + + enumerate_volumes(); + + return true; +} + +void monitor_stop() +{ + g_object_unref(monitor); +} -- cgit v1.2.3