+ action = GHB_ACTION (ud->builder, "hbfd");
+ gtk_action_set_visible(action, hbfd);
+}
+
+gboolean
+ghb_file_menu_add_dvd(signal_user_data_t *ud)
+{
+ GList *link, *drives;
+ static GtkActionGroup *agroup = NULL;
+ static gint merge_id;
+
+ g_debug("ghb_file_menu_add_dvd()");
+ link = drives = dvd_device_list();
+ if (drives != NULL)
+ {
+ GtkUIManager *ui = GTK_UI_MANAGER(
+ gtk_builder_get_object(ud->builder, "uimanager1"));
+
+ if (agroup == NULL)
+ {
+ agroup = gtk_action_group_new("dvdgroup");
+ gtk_ui_manager_insert_action_group(ui, agroup, 0);
+ }
+ else
+ gtk_ui_manager_remove_ui(ui, merge_id);
+
+ merge_id = gtk_ui_manager_new_merge_id(ui);
+ // Add separator
+ gtk_ui_manager_add_ui(ui, merge_id,
+ "ui/menubar1/menuitem1/quit1", "dvdsep", NULL,
+ GTK_UI_MANAGER_SEPARATOR, TRUE);
+
+ while (link != NULL)
+ {
+ GtkAction *action;
+ gchar *drive = get_dvd_device_name(link->data);
+ gchar *name = get_dvd_volume_name(link->data);
+
+ action = gtk_action_group_get_action(agroup, drive);
+ if (action != NULL)
+ {
+ gtk_action_group_remove_action(agroup, action);
+ g_object_unref(G_OBJECT(action));
+ }
+ // Create action for this drive
+ action = gtk_action_new(drive, name,
+ "Scan this DVD source", "gtk-cdrom");
+ // Add action to action group
+ gtk_action_group_add_action_with_accel(agroup, action, NULL);
+ // Add to ui manager
+ gtk_ui_manager_add_ui(ui, merge_id,
+ "ui/menubar1/menuitem1/dvdsep", drive, drive,
+ GTK_UI_MANAGER_AUTO, TRUE);
+ // Connect signal to action (menu item)
+ g_signal_connect(action, "activate",
+ (GCallback)dvd_source_activate_cb, ud);
+ g_free(name);
+ g_free(drive);
+ free_drive(link->data);
+ link = link->next;
+ }
+ g_list_free(drives);
+ }
+ return FALSE;
+}
+
+gboolean ghb_is_cd(GDrive *gd);
+
+static GList*
+dvd_device_list()
+{
+ GList *dvd_devices = NULL;
+
+#if defined(_WIN32)
+ gint ii, drives;
+ gchar drive[5];
+
+ strcpy(drive, "A:" G_DIR_SEPARATOR_S);
+ drives = GetLogicalDrives();
+ for (ii = 0; ii < 26; ii++)
+ {
+ if (drives & 0x01)
+ {
+ guint dtype;
+
+ drive[0] = 'A' + ii;
+ dtype = GetDriveType(drive);
+ if (dtype == DRIVE_CDROM)
+ {
+ dvd_devices = g_list_append(dvd_devices,
+ (gpointer)g_strdup(drive));
+ }
+ }
+ drives >>= 1;
+ }
+#else
+ GVolumeMonitor *gvm;
+ GList *drives, *link;
+
+ gvm = g_volume_monitor_get ();
+ drives = g_volume_monitor_get_connected_drives (gvm);
+ link = drives;
+ while (link != NULL)
+ {
+ GDrive *gd;
+
+ gd = (GDrive*)link->data;
+ if (ghb_is_cd(gd))
+ {
+ dvd_devices = g_list_append(dvd_devices, gd);
+ }
+ else
+ g_object_unref (gd);
+ link = link->next;
+ }
+ 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