+ g_list_free(drives);
+#endif
+
+ return dvd_devices;
+}
+
+#if !defined(_WIN32)
+static LibHalContext *hal_ctx = NULL;
+#endif
+
+gboolean
+ghb_is_cd(GDrive *gd)
+{
+#if !defined(_WIN32)
+ gchar *device;
+ LibHalDrive *halDrive;
+ LibHalDriveType dtype;
+
+ if (hal_ctx == NULL)
+ return FALSE;
+
+ device = g_drive_get_identifier(gd, G_VOLUME_IDENTIFIER_KIND_UNIX_DEVICE);
+ if (device == NULL)
+ return FALSE;
+ halDrive = libhal_drive_from_device_file (hal_ctx, device);
+ g_free(device);
+ if (halDrive == NULL)
+ return FALSE;
+ dtype = libhal_drive_get_type(halDrive);
+ libhal_drive_free(halDrive);
+ return (dtype == LIBHAL_DRIVE_TYPE_CDROM);
+#else
+ return FALSE;
+#endif
+}
+
+#if defined(_WIN32)
+static void
+handle_media_change(const gchar *device, gboolean insert, signal_user_data_t *ud)
+{
+ guint dtype;
+ static gint ins_count = 0;
+ static gint rem_count = 0;
+
+ // The media change event in windows bounces around a bit
+ // so I debounce it here
+ // DVD insertion detected. Scan it.
+ dtype = GetDriveType(device);
+ if (dtype != DRIVE_CDROM)
+ return;
+ if (insert)
+ {
+ rem_count = 0;
+ ins_count++;
+ if (ins_count == 2)
+ {
+ g_thread_create((GThreadFunc)ghb_cache_volnames, ud, FALSE, NULL);
+ if (ghb_settings_get_boolean(ud->settings, "AutoScan") &&
+ ud->current_dvd_device != NULL &&
+ strcmp(device, ud->current_dvd_device) == 0)
+ {
+ show_scan_progress(ud);
+ update_source_label(ud, device, TRUE);
+ gint preview_count;
+ preview_count = ghb_settings_get_int(ud->settings, "preview_count");
+ ghb_settings_set_string(ud->settings, "scan_source", device);
+ start_scan(ud, device, 0, preview_count);
+ }
+ }
+ }
+ else
+ {
+ ins_count = 0;
+ rem_count++;
+ if (rem_count == 2)
+ {
+ g_thread_create((GThreadFunc)ghb_cache_volnames, ud, FALSE, NULL);
+ if (ud->current_dvd_device != NULL &&
+ strcmp(device, ud->current_dvd_device) == 0)
+ {
+ ghb_hb_cleanup(TRUE);
+ prune_logs(ud);
+ ghb_settings_set_string(ud->settings, "scan_source", "/dev/null");
+ start_scan(ud, "/dev/null", 0, 1);
+ }
+ }
+ }
+}
+
+static gchar
+FindDriveFromMask(ULONG unitmask)
+{
+ gchar cc;
+ for (cc = 0; cc < 26; cc++)
+ {
+ if (unitmask & 0x01)
+ return 'A' + cc;
+ unitmask >>= 1;
+ }
+ return 0;
+}
+
+void
+wm_drive_changed(MSG *msg, signal_user_data_t *ud)
+{
+ PDEV_BROADCAST_HDR bch = (PDEV_BROADCAST_HDR)msg->lParam;
+ gchar drive[4];
+
+ g_strlcpy(drive, "A:" G_DIR_SEPARATOR_S, 4);
+ switch (msg->wParam)
+ {
+ case DBT_DEVICEARRIVAL:
+ {
+ if (bch->dbch_devicetype == DBT_DEVTYP_VOLUME)
+ {
+ PDEV_BROADCAST_VOLUME bcv = (PDEV_BROADCAST_VOLUME)bch;
+
+ if (bcv->dbcv_flags & DBTF_MEDIA)
+ {
+ drive[0] = FindDriveFromMask(bcv->dbcv_unitmask);
+ handle_media_change(drive, TRUE, ud);
+ }
+ }
+ } break;
+
+ case DBT_DEVICEREMOVECOMPLETE:
+ {
+ if (bch->dbch_devicetype == DBT_DEVTYP_VOLUME)
+ {
+ PDEV_BROADCAST_VOLUME bcv = (PDEV_BROADCAST_VOLUME)bch;
+
+ if (bcv->dbcv_flags & DBTF_MEDIA)
+ {
+ drive[0] = FindDriveFromMask(bcv->dbcv_unitmask);
+ handle_media_change(drive, FALSE, ud);
+ }
+ }
+ } break;
+ default: ;
+ }
+}
+
+#else
+
+G_MODULE_EXPORT void
+drive_changed_cb(GVolumeMonitor *gvm, GDrive *gd, signal_user_data_t *ud)
+{
+ gchar *device;
+ gint state;
+
+ g_debug("drive_changed_cb()");
+ g_thread_create((GThreadFunc)ghb_cache_volnames, ud, FALSE, NULL);
+
+ state = ghb_get_scan_state();
+ device = g_drive_get_identifier(gd, G_VOLUME_IDENTIFIER_KIND_UNIX_DEVICE);
+ if (ud->current_dvd_device == NULL ||
+ strcmp(device, ud->current_dvd_device) != 0 ||
+ state != GHB_STATE_IDLE )
+ {
+ return;
+ }
+ if (g_drive_has_media(gd))
+ {
+ if (ghb_settings_get_boolean(ud->settings, "AutoScan"))
+ {
+ show_scan_progress(ud);
+ update_source_label(ud, device, TRUE);
+ gint preview_count;
+ preview_count = ghb_settings_get_int(ud->settings, "preview_count");
+ ghb_settings_set_string(ud->settings, "scan_source", device);
+ start_scan(ud, device, 0, preview_count);
+ }
+ }
+ else
+ {
+ ghb_hb_cleanup(TRUE);
+ prune_logs(ud);
+ ghb_settings_set_string(ud->settings, "scan_source", "/dev/null");
+ start_scan(ud, "/dev/null", 0, 1);
+ }
+}
+#endif
+
+#if !defined(_WIN32)
+static void
+dbus_init (void)
+{
+ dbus_g_thread_init();
+}
+
+#define GPM_DBUS_PM_SERVICE "org.freedesktop.PowerManagement"
+#define GPM_DBUS_PM_PATH "/org/freedesktop/PowerManagement"
+#define GPM_DBUS_PM_INTERFACE "org.freedesktop.PowerManagement"
+#define GPM_DBUS_INHIBIT_PATH "/org/freedesktop/PowerManagement/Inhibit"
+#define GPM_DBUS_INHIBIT_INTERFACE "org.freedesktop.PowerManagement.Inhibit"
+static gboolean gpm_inhibited = FALSE;
+static guint gpm_cookie = -1;
+#endif
+
+static gboolean
+ghb_can_suspend_gpm()
+{
+ gboolean can_suspend = FALSE;
+#if !defined(_WIN32)
+ DBusGConnection *conn;
+ DBusGProxy *proxy;
+ GError *error = NULL;
+ gboolean res;
+
+
+ g_debug("ghb_can_suspend_gpm()");
+ conn = dbus_g_bus_get(DBUS_BUS_SESSION, &error);
+ if (error != NULL)
+ {
+ g_warning("DBUS cannot connect: %s", error->message);
+ g_error_free(error);
+ return FALSE;
+ }
+ proxy = dbus_g_proxy_new_for_name(conn, GPM_DBUS_PM_SERVICE,
+ GPM_DBUS_PM_PATH, GPM_DBUS_PM_INTERFACE);
+ if (proxy == NULL)
+ {
+ g_warning("Could not get DBUS proxy: %s", GPM_DBUS_PM_SERVICE);
+ dbus_g_connection_unref(conn);
+ return FALSE;
+ }
+ res = dbus_g_proxy_call(proxy, "CanSuspend", &error,
+ G_TYPE_INVALID,
+ G_TYPE_BOOLEAN, &can_suspend,
+ G_TYPE_INVALID);
+ if (!res)
+ {
+ if (error != NULL)
+ {
+ g_warning("CanSuspend failed: %s", error->message);
+ g_error_free(error);
+ }
+ else
+ g_warning("CanSuspend failed");
+ // Try to shutdown anyway
+ can_suspend = TRUE;
+ }
+ g_object_unref(G_OBJECT(proxy));
+ dbus_g_connection_unref(conn);
+#endif
+ return can_suspend;
+}
+
+static void
+ghb_suspend_gpm()
+{
+#if !defined(_WIN32)
+ DBusGConnection *conn;
+ DBusGProxy *proxy;
+ GError *error = NULL;
+ gboolean res;
+
+
+ g_debug("ghb_suspend_gpm()");
+ conn = dbus_g_bus_get(DBUS_BUS_SESSION, &error);
+ if (error != NULL)
+ {
+ g_warning("DBUS cannot connect: %s", error->message);
+ g_error_free(error);
+ return;
+ }
+ proxy = dbus_g_proxy_new_for_name(conn, GPM_DBUS_PM_SERVICE,
+ GPM_DBUS_PM_PATH, GPM_DBUS_PM_INTERFACE);
+ if (proxy == NULL)
+ {
+ g_warning("Could not get DBUS proxy: %s", GPM_DBUS_PM_SERVICE);
+ dbus_g_connection_unref(conn);
+ return;
+ }
+ res = dbus_g_proxy_call(proxy, "Suspend", &error,
+ G_TYPE_INVALID,
+ G_TYPE_INVALID);
+ if (!res)
+ {
+ if (error != NULL)
+ {
+ g_warning("Suspend failed: %s", error->message);
+ g_error_free(error);
+ }
+ else
+ g_warning("Suspend failed");
+ }
+ g_object_unref(G_OBJECT(proxy));
+ dbus_g_connection_unref(conn);
+#endif
+}
+
+static gboolean
+ghb_can_shutdown_gpm()
+{
+ gboolean can_shutdown = FALSE;
+#if !defined(_WIN32)
+ DBusGConnection *conn;
+ DBusGProxy *proxy;
+ GError *error = NULL;
+ gboolean res;
+
+
+ g_debug("ghb_can_shutdown_gpm()");
+ conn = dbus_g_bus_get(DBUS_BUS_SESSION, &error);
+ if (error != NULL)
+ {
+ g_warning("DBUS cannot connect: %s", error->message);
+ g_error_free(error);
+ return FALSE;
+ }
+ proxy = dbus_g_proxy_new_for_name(conn, GPM_DBUS_PM_SERVICE,
+ GPM_DBUS_PM_PATH, GPM_DBUS_PM_INTERFACE);
+ if (proxy == NULL)
+ {
+ g_warning("Could not get DBUS proxy: %s", GPM_DBUS_PM_SERVICE);
+ dbus_g_connection_unref(conn);
+ return FALSE;
+ }
+ res = dbus_g_proxy_call(proxy, "CanShutdown", &error,
+ G_TYPE_INVALID,
+ G_TYPE_BOOLEAN, &can_shutdown,
+ G_TYPE_INVALID);
+ if (!res)
+ {
+ if (error != NULL)
+ {
+ g_warning("CanShutdown failed: %s", error->message);
+ g_error_free(error);
+ }
+ else
+ g_warning("CanShutdown failed");
+ // Try to shutdown anyway
+ can_shutdown = TRUE;
+ }
+ g_object_unref(G_OBJECT(proxy));
+ dbus_g_connection_unref(conn);
+#endif
+ return can_shutdown;
+}
+
+static void
+ghb_shutdown_gpm()
+{
+#if !defined(_WIN32)
+ DBusGConnection *conn;
+ DBusGProxy *proxy;
+ GError *error = NULL;
+ gboolean res;
+
+
+ g_debug("ghb_shutdown_gpm()");
+ conn = dbus_g_bus_get(DBUS_BUS_SESSION, &error);
+ if (error != NULL)
+ {
+ g_warning("DBUS cannot connect: %s", error->message);
+ g_error_free(error);
+ return;
+ }
+ proxy = dbus_g_proxy_new_for_name(conn, GPM_DBUS_PM_SERVICE,
+ GPM_DBUS_PM_PATH, GPM_DBUS_PM_INTERFACE);
+ if (proxy == NULL)
+ {
+ g_warning("Could not get DBUS proxy: %s", GPM_DBUS_PM_SERVICE);
+ dbus_g_connection_unref(conn);
+ return;
+ }
+ res = dbus_g_proxy_call(proxy, "Shutdown", &error,
+ G_TYPE_INVALID,
+ G_TYPE_INVALID);
+ if (!res)
+ {
+ if (error != NULL)
+ {
+ g_warning("Shutdown failed: %s", error->message);
+ g_error_free(error);
+ }
+ else
+ g_warning("Shutdown failed");
+ }
+ g_object_unref(G_OBJECT(proxy));
+ dbus_g_connection_unref(conn);
+#endif
+}
+
+void
+ghb_inhibit_gpm()
+{
+#if !defined(_WIN32)
+ DBusGConnection *conn;
+ DBusGProxy *proxy;
+ GError *error = NULL;
+ gboolean res;
+
+
+ if (gpm_inhibited)
+ {
+ // Already inhibited
+ return;
+ }
+ g_debug("ghb_inhibit_gpm()");
+ conn = dbus_g_bus_get(DBUS_BUS_SESSION, &error);
+ if (error != NULL)
+ {
+ g_warning("DBUS cannot connect: %s", error->message);
+ g_error_free(error);
+ return;
+ }
+ proxy = dbus_g_proxy_new_for_name(conn, GPM_DBUS_PM_SERVICE,
+ GPM_DBUS_INHIBIT_PATH, GPM_DBUS_INHIBIT_INTERFACE);
+ if (proxy == NULL)
+ {
+ g_warning("Could not get DBUS proxy: %s", GPM_DBUS_PM_SERVICE);
+ dbus_g_connection_unref(conn);
+ return;
+ }
+ res = dbus_g_proxy_call(proxy, "Inhibit", &error,
+ G_TYPE_STRING, "ghb",
+ G_TYPE_STRING, "Encoding",
+ G_TYPE_INVALID,
+ G_TYPE_UINT, &gpm_cookie,
+ G_TYPE_INVALID);
+ gpm_inhibited = TRUE;
+ if (!res)
+ {
+ if (error != NULL)
+ {
+ g_warning("Inhibit failed: %s", error->message);
+ g_error_free(error);
+ gpm_cookie = -1;
+ }
+ else
+ g_warning("Inhibit failed");
+ gpm_cookie = -1;
+ gpm_inhibited = FALSE;
+ }
+ g_object_unref(G_OBJECT(proxy));
+ dbus_g_connection_unref(conn);
+#endif
+}
+
+void
+ghb_uninhibit_gpm()
+{
+#if !defined(_WIN32)
+ DBusGConnection *conn;
+ DBusGProxy *proxy;
+ GError *error = NULL;
+ gboolean res;
+
+ g_debug("ghb_uninhibit_gpm() gpm_cookie %u", gpm_cookie);
+
+ if (!gpm_inhibited)
+ {
+ // Not inhibited
+ return;
+ }
+ conn = dbus_g_bus_get(DBUS_BUS_SESSION, &error);
+ if (error != NULL)
+ {
+ g_warning("DBUS cannot connect: %s", error->message);
+ g_error_free(error);
+ return;
+ }
+ proxy = dbus_g_proxy_new_for_name(conn, GPM_DBUS_PM_SERVICE,
+ GPM_DBUS_INHIBIT_PATH, GPM_DBUS_INHIBIT_INTERFACE);
+ if (proxy == NULL)
+ {
+ g_warning("Could not get DBUS proxy: %s", GPM_DBUS_PM_SERVICE);
+ dbus_g_connection_unref(conn);
+ return;
+ }
+ res = dbus_g_proxy_call(proxy, "UnInhibit", &error,
+ G_TYPE_UINT, gpm_cookie,
+ G_TYPE_INVALID,
+ G_TYPE_INVALID);
+ if (!res)
+ {
+ if (error != NULL)
+ {
+ g_warning("UnInhibit failed: %s", error->message);
+ g_error_free(error);
+ }
+ else
+ g_warning("UnInhibit failed");
+ }
+ gpm_inhibited = FALSE;
+ dbus_g_connection_unref(conn);
+ g_object_unref(G_OBJECT(proxy));