static void ghb_suspend_gpm();
static gboolean appcast_busy = FALSE;
-// This is a dependency map used for greying widgets
-// that are dependent on the state of another widget.
-// The enable_value comes from the values that are
-// obtained from ghb_widget_value(). For combo boxes
-// you will have to look further to combo box options
-// maps in hb-backend.c
-
-GhbValue *dep_map;
-GhbValue *rev_map;
-
-void
-ghb_init_dep_map()
-{
- dep_map = ghb_resource_get("widget-deps");
- rev_map = ghb_resource_get("widget-reverse-deps");
-}
+#if !defined(_WIN32)
+#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"
+#endif
static gboolean
-dep_check(signal_user_data_t *ud, const gchar *name, gboolean *out_hide)
+ghb_can_suspend_gpm()
{
- GtkWidget *widget;
- GObject *dep_object;
- gint ii;
- gint count;
- gboolean result = TRUE;
- GhbValue *array, *data;
- const gchar *widget_name;
+ gboolean can_suspend = FALSE;
+#if !defined(_WIN32)
+ DBusGConnection *conn;
+ DBusGProxy *proxy;
+ GError *error = NULL;
+ gboolean res;
- g_debug("dep_check () %s", name);
- if (rev_map == NULL) return TRUE;
- array = ghb_dict_get(rev_map, name);
- count = ghb_array_len(array);
- *out_hide = FALSE;
- for (ii = 0; ii < count; ii++)
+ g_debug("ghb_can_suspend_gpm()");
+ conn = dbus_g_bus_get(DBUS_BUS_SESSION, &error);
+ if (error != NULL)
{
- data = ghb_array_get(array, ii);
- widget_name = ghb_value_get_string(ghb_array_get(data, 0));
- widget = GHB_WIDGET(ud->builder, widget_name);
- dep_object = gtk_builder_get_object(ud->builder, name);
- if (widget != NULL && !gtk_widget_is_sensitive(widget))
- {
- continue;
- }
- if (dep_object == 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_message("Failed to find widget");
+ g_warning("CanSuspend failed: %s", error->message);
+ g_error_free(error);
}
else
- {
- gchar *value;
- gint jj = 0;
- gchar **values;
- gboolean sensitive = FALSE;
- gboolean die, hide;
-
- die = ghb_value_get_bool(ghb_array_get(data, 2));
- hide = ghb_value_get_bool(ghb_array_get(data, 3));
- const char *tmp = ghb_value_get_string(ghb_array_get(data, 1));
- values = g_strsplit(tmp, "|", 10);
-
- if (widget)
- value = ghb_widget_string(widget);
- else
- value = ghb_dict_get_string_xform(ud->settings, widget_name);
- while (values && values[jj])
- {
- if (values[jj][0] == '>')
- {
- gdouble dbl = g_strtod (&values[jj][1], NULL);
- gdouble dvalue = ghb_widget_double(widget);
- if (dvalue > dbl)
- {
- sensitive = TRUE;
- break;
- }
- }
- else if (values[jj][0] == '<')
- {
- gdouble dbl = g_strtod (&values[jj][1], NULL);
- gdouble dvalue = ghb_widget_double(widget);
- if (dvalue < dbl)
- {
- sensitive = TRUE;
- break;
- }
- }
- if (strcmp(values[jj], value) == 0)
- {
- sensitive = TRUE;
- break;
- }
- jj++;
- }
- sensitive = die ^ sensitive;
- if (!sensitive)
- {
- result = FALSE;
- *out_hide |= hide;
- }
- g_strfreev (values);
- g_free(value);
- }
+ g_warning("CanSuspend failed");
+ // Try to shutdown anyway
+ can_suspend = TRUE;
}
- return result;
+ g_object_unref(G_OBJECT(proxy));
+ dbus_g_connection_unref(conn);
+#endif
+ return can_suspend;
}
-void
-ghb_check_dependency(
- signal_user_data_t *ud,
- GtkWidget *widget,
- const char *alt_name)
+static void
+ghb_suspend_gpm()
{
- GObject *dep_object;
- const gchar *name;
- GhbValue *array, *data;
- gint count, ii;
- const gchar *dep_name;
- GType type;
+#if !defined(_WIN32)
+ DBusGConnection *conn;
+ DBusGProxy *proxy;
+ GError *error = NULL;
+ gboolean res;
- if (widget != NULL)
+
+ g_debug("ghb_suspend_gpm()");
+ conn = dbus_g_bus_get(DBUS_BUS_SESSION, &error);
+ if (error != NULL)
{
- type = G_OBJECT_TYPE(widget);
- if (type == GTK_TYPE_COMBO_BOX)
- if (gtk_combo_box_get_active(GTK_COMBO_BOX(widget)) < 0) return;
- name = ghb_get_setting_key(widget);
+ g_warning("DBUS cannot connect: %s", error->message);
+ g_error_free(error);
+ return;
}
- else
- name = alt_name;
-
- g_debug("ghb_check_dependency() %s", name);
-
- if (dep_map == NULL) return;
- array = ghb_dict_get(dep_map, name);
- count = ghb_array_len(array);
- for (ii = 0; ii < count; ii++)
+ proxy = dbus_g_proxy_new_for_name(conn, GPM_DBUS_PM_SERVICE,
+ GPM_DBUS_PM_PATH, GPM_DBUS_PM_INTERFACE);
+ if (proxy == NULL)
{
- gboolean sensitive;
- gboolean hide;
-
- data = ghb_array_get(array, ii);
- dep_name = ghb_value_get_string(data);
- dep_object = gtk_builder_get_object(ud->builder, dep_name);
- if (dep_object == NULL)
- {
- g_message("Failed to find dependent widget %s", dep_name);
- continue;
- }
- sensitive = dep_check(ud, dep_name, &hide);
- gtk_widget_set_sensitive(GTK_WIDGET(dep_object), sensitive);
- gtk_widget_set_can_focus(GTK_WIDGET(dep_object), sensitive);
- if (!sensitive && hide)
+ 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)
{
- if (gtk_widget_get_visible(GTK_WIDGET(dep_object)))
- {
- gtk_widget_hide(GTK_WIDGET(dep_object));
- }
+ g_warning("Suspend failed: %s", error->message);
+ g_error_free(error);
}
else
- {
- if (!gtk_widget_get_visible(GTK_WIDGET(dep_object)))
- {
- gtk_widget_show_now(GTK_WIDGET(dep_object));
- }
- }
+ g_warning("Suspend failed");
}
+ g_object_unref(G_OBJECT(proxy));
+ dbus_g_connection_unref(conn);
+#endif
}
-void
-ghb_check_all_depencencies(signal_user_data_t *ud)
+#if !defined(_WIN32)
+static gboolean
+ghb_can_shutdown_gpm()
{
- GhbDictIter iter;
- const gchar *dep_name;
- GhbValue *value;
- GObject *dep_object;
+ gboolean can_shutdown = FALSE;
+ DBusGConnection *conn;
+ DBusGProxy *proxy;
+ GError *error = NULL;
+ gboolean res;
- g_debug("ghb_check_all_depencencies ()");
- if (rev_map == NULL) return;
- iter = ghb_dict_iter_init(rev_map);
- while (ghb_dict_iter_next(rev_map, &iter, &dep_name, &value))
- {
- gboolean sensitive;
- gboolean hide;
- dep_object = gtk_builder_get_object (ud->builder, dep_name);
- if (dep_object == NULL)
- {
- g_message("Failed to find dependent widget %s", dep_name);
- continue;
- }
- sensitive = dep_check(ud, dep_name, &hide);
- gtk_widget_set_sensitive(GTK_WIDGET(dep_object), sensitive);
- gtk_widget_set_can_focus(GTK_WIDGET(dep_object), sensitive);
- if (!sensitive && hide)
- {
- gtk_widget_hide(GTK_WIDGET(dep_object));
- }
- else
+ 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)
{
- gtk_widget_show_now(GTK_WIDGET(dep_object));
+ 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);
+ return can_shutdown;
}
+#endif
-G_MODULE_EXPORT void
-quit_action_cb(GSimpleAction *action, GVariant *param, signal_user_data_t *ud)
+#if !defined(_WIN32)
+static void
+ghb_shutdown_gpm()
{
- gint state = ghb_get_queue_state();
- if (state & (GHB_STATE_WORKING|GHB_STATE_SEARCHING))
+ 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)
{
- if (ghb_cancel_encode2(ud, _("Closing HandBrake will terminate encoding.\n")))
- {
- ghb_hb_cleanup(FALSE);
- prune_logs(ud);
- g_application_quit(G_APPLICATION(ud->app));
- return;
- }
+ g_warning("DBUS cannot connect: %s", error->message);
+ g_error_free(error);
return;
}
- ghb_hb_cleanup(FALSE);
- prune_logs(ud);
- g_application_quit(G_APPLICATION(ud->app));
-}
-
-gboolean
-uppers_and_unders(gchar *str)
-{
- if (str == NULL) return FALSE;
- str = g_strchomp(g_strchug(str));
- while (*str)
+ proxy = dbus_g_proxy_new_for_name(conn, GPM_DBUS_PM_SERVICE,
+ GPM_DBUS_PM_PATH, GPM_DBUS_PM_INTERFACE);
+ if (proxy == NULL)
{
- if (*str == ' ')
- {
- return FALSE;
- }
- if (*str >= 'a' && *str <= 'z')
+ 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)
{
- return FALSE;
+ g_warning("Shutdown failed: %s", error->message);
+ g_error_free(error);
}
- str++;
+ else
+ g_warning("Shutdown failed");
}
- return TRUE;
+ g_object_unref(G_OBJECT(proxy));
+ dbus_g_connection_unref(conn);
}
+#endif
-enum
+guint
+ghb_inhibit_gpm()
{
- CAMEL_FIRST_UPPER,
- CAMEL_OTHER
-};
+ guint cookie = -1;
-void
-camel_convert(gchar *str)
-{
- gint state = CAMEL_OTHER;
+#if !defined(_WIN32)
+ DBusGConnection *conn;
+ DBusGProxy *proxy;
+ GError *error = NULL;
+ gboolean res;
- if (str == NULL) return;
- while (*str)
+ g_debug("ghb_inhibit_gpm()");
+ conn = dbus_g_bus_get(DBUS_BUS_SESSION, &error);
+ if (error != NULL)
{
- if (*str == '_') *str = ' ';
- switch (state)
+ g_warning("DBUS cannot connect: %s", error->message);
+ g_error_free(error);
+ return 0;
+ }
+ 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 0;
+ }
+ res = dbus_g_proxy_call(proxy, "Inhibit", &error,
+ G_TYPE_STRING, "ghb",
+ G_TYPE_STRING, "Encoding",
+ G_TYPE_INVALID,
+ G_TYPE_UINT, &cookie,
+ G_TYPE_INVALID);
+ if (!res)
+ {
+ if (error != NULL)
{
- case CAMEL_OTHER:
- {
- if (*str >= 'A' && *str <= 'Z')
- state = CAMEL_FIRST_UPPER;
- else
- state = CAMEL_OTHER;
-
- } break;
- case CAMEL_FIRST_UPPER:
- {
- if (*str >= 'A' && *str <= 'Z')
- *str = *str - 'A' + 'a';
- else
- state = CAMEL_OTHER;
- } break;
+ g_error_free(error);
}
- str++;
+ cookie = -1;
}
-}
-
-#if defined(_WIN32)
-static gchar*
-get_dvd_device_name(gchar *device)
-{
- return g_strdup(device);
-}
-#else
-static gchar*
-get_dvd_device_name(GDrive *gd)
-{
- return g_drive_get_identifier(gd, G_VOLUME_IDENTIFIER_KIND_UNIX_DEVICE);
-}
-#endif
-
-static GHashTable *volname_hash = NULL;
-#if GLIB_CHECK_VERSION(2, 32, 0)
-static GMutex volname_mutex_static;
+ g_object_unref(G_OBJECT(proxy));
+ dbus_g_connection_unref(conn);
#endif
-static GMutex *volname_mutex;
-static void
-free_volname_key(gpointer data)
-{
- if (data != NULL)
- g_free(data);
+ return cookie;
}
-static void
-free_volname_value(gpointer data)
+void
+ghb_uninhibit_gpm(guint cookie)
{
- if (data != NULL)
- g_free(data);
-}
+#if !defined(_WIN32)
+ DBusGConnection *conn;
+ DBusGProxy *proxy;
+ GError *error = NULL;
+ gboolean res;
-#if defined(_WIN32)
-static gchar*
-get_direct_dvd_volume_name(const gchar *drive)
-{
- gchar *result = NULL;
- gchar vname[51], fsname[51];
+ g_debug("ghb_uninhibit_gpm() cookie %u", cookie);
- if (GetVolumeInformation(drive, vname, 50, NULL, NULL, NULL, fsname, 50))
+ conn = dbus_g_bus_get(DBUS_BUS_SESSION, &error);
+ if (error != NULL)
{
- result = g_strdup_printf("%s", vname);
+ g_warning("DBUS cannot connect: %s", error->message);
+ g_error_free(error);
+ return;
}
- return result;
+ 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, cookie,
+ G_TYPE_INVALID,
+ G_TYPE_INVALID);
+ if (!res)
+ {
+ if (error != NULL)
+ {
+ g_error_free(error);
+ }
+ }
+ dbus_g_connection_unref(conn);
+ g_object_unref(G_OBJECT(proxy));
+#endif
}
-#else
-static gchar*
-get_direct_dvd_volume_name(const gchar *drive)
-{
- gchar *result;
- result = ghb_dvd_volname (drive);
- return result;
-}
+#if !defined(_WIN32)
+// For inhibit and shutdown
+#define GPM_DBUS_SM_SERVICE "org.gnome.SessionManager"
+#define GPM_DBUS_SM_PATH "/org/gnome/SessionManager"
+#define GPM_DBUS_SM_INTERFACE "org.gnome.SessionManager"
#endif
-static gchar*
-get_dvd_volume_name(gpointer gd)
+static gboolean
+ghb_can_shutdown_gsm()
{
- gchar *label = NULL;
- gchar *result;
- gchar *drive;
+ gboolean can_shutdown = FALSE;
+#if !defined(_WIN32)
+ DBusGConnection *conn;
+ DBusGProxy *proxy;
+ GError *error = NULL;
+ gboolean res;
- drive = get_dvd_device_name(gd);
- g_mutex_lock(volname_mutex);
- label = g_strdup(g_hash_table_lookup(volname_hash, drive));
- g_mutex_unlock(volname_mutex);
- if (label != NULL)
+ conn = dbus_g_bus_get(DBUS_BUS_SESSION, &error);
+ if (error != NULL)
{
- if (uppers_and_unders(label))
- {
- camel_convert(label);
- }
-#if defined(_WIN32)
- result = g_strdup_printf("%s (%s)", label, drive);
-#else
- result = g_strdup_printf("%s - %s", drive, label);
-#endif
- g_free(label);
+ g_warning("DBUS cannot connect: %s", error->message);
+ g_error_free(error);
+ return FALSE;
}
- else
+ proxy = dbus_g_proxy_new_for_name(conn, GPM_DBUS_SM_SERVICE,
+ GPM_DBUS_SM_PATH, GPM_DBUS_SM_INTERFACE);
+ if (proxy == NULL)
{
- result = g_strdup_printf("%s", drive);
+ g_warning("Could not get DBUS proxy: %s", GPM_DBUS_SM_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);
+ g_object_unref(G_OBJECT(proxy));
+ dbus_g_connection_unref(conn);
+ if (!res)
+ {
+ if (error != NULL)
+ {
+ g_error_free(error);
+ }
+ // Try to shutdown anyway
+ can_shutdown = TRUE;
+ // Try the gpm version
+ return ghb_can_shutdown_gpm();
}
- g_free(drive);
- return result;
-}
-
-void
-ghb_volname_cache_init(void)
-{
-#if GLIB_CHECK_VERSION(2, 32, 0)
- g_mutex_init(&volname_mutex_static);
- volname_mutex = &volname_mutex_static;
-#else
- volname_mutex = g_mutex_new();
#endif
- volname_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
- free_volname_key, free_volname_value);
+ return can_shutdown;
}
static void
-free_drive(gpointer drive)
-{
-#if defined(_WIN32)
- g_free(drive);
-#else
- g_object_unref(drive);
-#endif
-}
-
-gpointer
-ghb_cache_volnames(signal_user_data_t *ud)
+ghb_shutdown_gsm()
{
- GList *link, *drives;
+#if !defined(_WIN32)
+ DBusGConnection *conn;
+ DBusGProxy *proxy;
+ GError *error = NULL;
+ gboolean res;
- g_debug("ghb_cache_volnames()");
- link = drives = dvd_device_list();
- if (drives == NULL)
- return NULL;
- g_mutex_lock(volname_mutex);
- g_hash_table_remove_all(volname_hash);
- while (link != NULL)
+ g_debug("ghb_shutdown_gpm()");
+ conn = dbus_g_bus_get(DBUS_BUS_SESSION, &error);
+ if (error != NULL)
{
- gchar *name, *drive;
-
-#if !defined(_WIN32)
- if (!g_drive_has_media (link->data))
+ g_warning("DBUS cannot connect: %s", error->message);
+ g_error_free(error);
+ return;
+ }
+ proxy = dbus_g_proxy_new_for_name(conn, GPM_DBUS_SM_SERVICE,
+ GPM_DBUS_SM_PATH, GPM_DBUS_SM_INTERFACE);
+ if (proxy == NULL)
+ {
+ g_warning("Could not get DBUS proxy: %s", GPM_DBUS_SM_SERVICE);
+ dbus_g_connection_unref(conn);
+ return;
+ }
+ res = dbus_g_proxy_call(proxy, "Shutdown", &error,
+ G_TYPE_INVALID,
+ G_TYPE_INVALID);
+ g_object_unref(G_OBJECT(proxy));
+ dbus_g_connection_unref(conn);
+ if (!res)
+ {
+ if (error != NULL)
{
- g_object_unref(link->data);
- link = link->next;
- continue;
+ g_error_free(error);
}
+ // Try the gpm version
+ ghb_shutdown_gpm();
+ }
#endif
- drive = get_dvd_device_name(link->data);
- name = get_direct_dvd_volume_name(drive);
+}
- if (drive != NULL && name != NULL)
- {
- g_hash_table_insert(volname_hash, drive, name);
- }
- else
+guint
+ghb_inhibit_gsm(signal_user_data_t *ud)
+{
+ guint cookie = -1;
+
+#if !defined(_WIN32)
+ DBusGConnection *conn;
+ DBusGProxy *proxy;
+ GError *error = NULL;
+ gboolean res;
+ guint xid;
+ GtkWidget *widget;
+
+ g_debug("ghb_inhibit_gsm()");
+ 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 -1;
+ }
+ proxy = dbus_g_proxy_new_for_name(conn, GPM_DBUS_SM_SERVICE,
+ GPM_DBUS_SM_PATH, GPM_DBUS_SM_INTERFACE);
+ if (proxy == NULL)
+ {
+ g_warning("Could not get DBUS proxy: %s", GPM_DBUS_SM_SERVICE);
+ dbus_g_connection_unref(conn);
+ return -1;
+ }
+ widget = GHB_WIDGET(ud->builder, "hb_window");
+ xid = GDK_WINDOW_XID(gtk_widget_get_window(widget));
+ res = dbus_g_proxy_call(proxy, "Inhibit", &error,
+ G_TYPE_STRING, "ghb",
+ G_TYPE_UINT, xid,
+ G_TYPE_STRING, "Encoding",
+ G_TYPE_UINT, 1 | 4,
+ G_TYPE_INVALID,
+ G_TYPE_UINT, &cookie,
+ G_TYPE_INVALID);
+ g_object_unref(G_OBJECT(proxy));
+ dbus_g_connection_unref(conn);
+ if (!res)
+ {
+ if (error != NULL)
{
- if (drive != NULL)
- g_free(drive);
- if (name != NULL)
- g_free(name);
+ g_error_free(error);
}
-
- free_drive(link->data);
- link = link->next;
+ cookie = -1;
}
- g_mutex_unlock(volname_mutex);
-
- g_list_free(drives);
-
- g_idle_add((GSourceFunc)ghb_file_menu_add_dvd, ud);
+#endif
- return NULL;
+ return cookie;
}
-static const gchar*
-get_extension(signal_user_data_t *ud, GhbValue *settings)
+void
+ghb_uninhibit_gsm(guint cookie)
{
- const char *mux_id;
- const hb_container_t *mux;
+#if !defined(_WIN32)
+ DBusGConnection *conn;
+ DBusGProxy *proxy;
+ GError *error = NULL;
+ gboolean res;
- mux_id = ghb_dict_get_string(settings, "FileFormat");
- mux = ghb_lookup_container_by_name(mux_id);
+ g_debug("ghb_uninhibit_gsm() cookie %u", cookie);
- if ((mux->format & HB_MUX_MASK_MP4) &&
- ghb_dict_get_bool(ud->prefs, "UseM4v"))
+ conn = dbus_g_bus_get(DBUS_BUS_SESSION, &error);
+ if (error != NULL)
{
- return "m4v";
+ g_warning("DBUS cannot connect: %s", error->message);
+ g_error_free(error);
+ return;
}
- return mux->default_extension;
+ proxy = dbus_g_proxy_new_for_name(conn, GPM_DBUS_SM_SERVICE,
+ GPM_DBUS_SM_PATH, GPM_DBUS_SM_INTERFACE);
+ if (proxy == NULL)
+ {
+ g_warning("Could not get DBUS proxy: %s", GPM_DBUS_SM_SERVICE);
+ dbus_g_connection_unref(conn);
+ return;
+ }
+ res = dbus_g_proxy_call(proxy, "Uninhibit", &error,
+ G_TYPE_UINT, cookie,
+ G_TYPE_INVALID,
+ G_TYPE_INVALID);
+ if (!res)
+ {
+ if (error != NULL)
+ {
+ g_error_free(error);
+ }
+ }
+ dbus_g_connection_unref(conn);
+ g_object_unref(G_OBJECT(proxy));
+#endif
}
-static gboolean
-check_name_template(signal_user_data_t *ud, const char *str)
+enum {
+ GHB_SUSPEND_UNINHIBITED = 0,
+ GHB_SUSPEND_INHIBITED_GPM,
+ GHB_SUSPEND_INHIBITED_GSM,
+ GHB_SUSPEND_INHIBITED_GTK
+};
+static int suspend_inhibited = GHB_SUSPEND_UNINHIBITED;
+static guint suspend_cookie;
+
+void
+ghb_inhibit_suspend(signal_user_data_t *ud)
{
- if (ghb_dict_get_bool(ud->prefs, "auto_name"))
+ if (suspend_inhibited != GHB_SUSPEND_UNINHIBITED)
{
- const gchar *template;
-
- template = ghb_dict_get_string(ud->prefs, "auto_name_template");
- if (strstr(template, str) != NULL)
- return TRUE;
+ // Already inhibited
+ return;
}
- return FALSE;
+#if GTK_CHECK_VERSION(3, 4, 0)
+ suspend_cookie = gtk_application_inhibit(ud->app, NULL,
+ GTK_APPLICATION_INHIBIT_SUSPEND, "Encoding");
+ if (suspend_cookie != 0)
+ {
+ suspend_inhibited = GHB_SUSPEND_INHIBITED_GTK;
+ return;
+ }
+#else
+ suspend_cookie = ghb_inhibit_gsm(ud);
+ if (suspend_cookie != -1)
+ {
+ suspend_inhibited = GHB_SUSPEND_INHIBITED_GSM;
+ return;
+ }
+ suspend_cookie = ghb_inhibit_gpm(ud);
+ if (suspend_cookie != -1)
+ {
+ suspend_inhibited = GHB_SUSPEND_INHIBITED_GPM;
+ return;
+ }
+#endif
}
-static void
-set_destination_settings(signal_user_data_t *ud, GhbValue *settings)
+void
+ghb_uninhibit_suspend(signal_user_data_t *ud)
{
- const gchar *extension, *dest_file;
- gchar *filename;
+ switch (suspend_inhibited)
+ {
+#if GTK_CHECK_VERSION(3, 4, 0)
+ case GHB_SUSPEND_INHIBITED_GTK:
+ gtk_application_uninhibit(ud->app, suspend_cookie);
+ break;
+#endif
- extension = get_extension(ud, settings);
+ case GHB_SUSPEND_INHIBITED_GPM:
+ ghb_uninhibit_gpm(suspend_cookie);
+ break;
- g_debug("set_destination_settings");
- dest_file = ghb_dict_get_string(ud->settings, "dest_file");
- if (dest_file == NULL)
- {
- // Initialize destination filename if it has no value yet.
- // If auto-naming is disabled, this will be the default filename.
- GString *str = g_string_new("");
- const gchar *vol_name;
- vol_name = ghb_dict_get_string(settings, "volume");
- g_string_append_printf(str, "%s", vol_name);
- g_string_append_printf(str, ".%s", extension);
- filename = g_string_free(str, FALSE);
- ghb_dict_set_string(settings, "dest_file", filename);
- g_free(filename);
+ case GHB_SUSPEND_INHIBITED_GSM:
+ ghb_uninhibit_gsm(suspend_cookie);
+ break;
+
+ default:
+ break;
}
- if (ghb_dict_get_bool(ud->prefs, "auto_name"))
- {
- GString *str = g_string_new("");
- const gchar *p;
+ suspend_inhibited = GHB_SUSPEND_UNINHIBITED;
+}
- p = ghb_dict_get_string(ud->prefs, "auto_name_template");
- while (*p)
+// This is a dependency map used for greying widgets
+// that are dependent on the state of another widget.
+// The enable_value comes from the values that are
+// obtained from ghb_widget_value(). For combo boxes
+// you will have to look further to combo box options
+// maps in hb-backend.c
+
+GhbValue *dep_map;
+GhbValue *rev_map;
+
+void
+ghb_init_dep_map()
+{
+ dep_map = ghb_resource_get("widget-deps");
+ rev_map = ghb_resource_get("widget-reverse-deps");
+}
+
+static gboolean
+dep_check(signal_user_data_t *ud, const gchar *name, gboolean *out_hide)
+{
+ GtkWidget *widget;
+ GObject *dep_object;
+ gint ii;
+ gint count;
+ gboolean result = TRUE;
+ GhbValue *array, *data;
+ const gchar *widget_name;
+
+ g_debug("dep_check () %s", name);
+
+ if (rev_map == NULL) return TRUE;
+ array = ghb_dict_get(rev_map, name);
+ count = ghb_array_len(array);
+ *out_hide = FALSE;
+ for (ii = 0; ii < count; ii++)
+ {
+ data = ghb_array_get(array, ii);
+ widget_name = ghb_value_get_string(ghb_array_get(data, 0));
+ widget = GHB_WIDGET(ud->builder, widget_name);
+ dep_object = gtk_builder_get_object(ud->builder, name);
+ if (widget != NULL && !gtk_widget_is_sensitive(widget))
{
- if (!strncmp(p, "{source}", strlen("{source}")))
- {
- const gchar *vol_name;
- vol_name = ghb_dict_get_string(settings, "volume");
- g_string_append_printf(str, "%s", vol_name);
- p += strlen("{source}");
- }
- else if (!strncmp(p, "{title}", strlen("{title}")))
- {
- gint title = ghb_dict_get_int(settings, "title");
- if (title >= 0)
- g_string_append_printf(str, "%d", title);
- p += strlen("{title}");
- }
- else if (!strncmp(p, "{preset}", strlen("{preset}")))
- {
- const gchar *preset_name;
- preset_name = ghb_dict_get_string(settings, "PresetName");
- g_string_append_printf(str, "%s", preset_name);
- p += strlen("{preset}");
- }
- else if (!strncmp(p, "{chapters}", strlen("{chapters}")))
+ continue;
+ }
+ if (dep_object == NULL)
+ {
+ g_message("Failed to find widget");
+ }
+ else
+ {
+ gchar *value;
+ gint jj = 0;
+ gchar **values;
+ gboolean sensitive = FALSE;
+ gboolean die, hide;
+
+ die = ghb_value_get_bool(ghb_array_get(data, 2));
+ hide = ghb_value_get_bool(ghb_array_get(data, 3));
+ const char *tmp = ghb_value_get_string(ghb_array_get(data, 1));
+ values = g_strsplit(tmp, "|", 10);
+
+ if (widget)
+ value = ghb_widget_string(widget);
+ else
+ value = ghb_dict_get_string_xform(ud->settings, widget_name);
+ while (values && values[jj])
{
- if (ghb_settings_combo_int(settings, "PtoPType") == 0)
+ if (values[jj][0] == '>')
{
- gint start, end;
- start = ghb_dict_get_int(settings, "start_point");
- end = ghb_dict_get_int(settings, "end_point");
- if (start == end)
- g_string_append_printf(str, "%d", start);
- else
- g_string_append_printf(str, "%d-%d", start, end);
+ gdouble dbl = g_strtod (&values[jj][1], NULL);
+ gdouble dvalue = ghb_widget_double(widget);
+ if (dvalue > dbl)
+ {
+ sensitive = TRUE;
+ break;
+ }
}
- p += strlen("{chapters}");
- }
- else if (!strncmp(p, "{time}", strlen("{time}")))
- {
- char st[6];
- struct tm *lt;
- time_t t = time(NULL);
- lt = localtime(&t);
- st[0] = 0;
- strftime(st, 6, "%H:%M", lt);
- g_string_append_printf(str, "%s", st);
- p += strlen("{time}");
- }
- else if (!strncmp(p, "{date}", strlen("{date}")))
- {
- char dt[11];
- struct tm *lt;
- time_t t = time(NULL);
- lt = localtime(&t);
- dt[0] = 0;
- strftime(dt, 11, "%Y-%m-%d", lt);
- g_string_append_printf(str, "%s", dt);
- p += strlen("{date}");
- }
- else if (!strncmp(p, "{quality}", strlen("{quality}")))
- {
- if (ghb_dict_get_bool(settings, "vquality_type_constant"))
+ else if (values[jj][0] == '<')
{
- gint vcodec;
- const char *vqname;
- double vquality;
- vcodec = ghb_settings_video_encoder_codec(settings, "VideoEncoder");
- vqname = hb_video_quality_get_name(vcodec);
- vquality = ghb_dict_get_double(settings, "VideoQualitySlider");
- g_string_append_printf(str, "%s%.3g", vqname, vquality);
+ gdouble dbl = g_strtod (&values[jj][1], NULL);
+ gdouble dvalue = ghb_widget_double(widget);
+ if (dvalue < dbl)
+ {
+ sensitive = TRUE;
+ break;
+ }
}
- p += strlen("{quality}");
- }
- else if (!strncmp(p, "{bitrate}", strlen("{bitrate}")))
- {
- if (ghb_dict_get_bool(settings, "vquality_type_bitrate"))
+ if (strcmp(values[jj], value) == 0)
{
- int vbitrate;
- vbitrate = ghb_dict_get_int(settings, "VideoAvgBitrate");
- g_string_append_printf(str, "%dkbps", vbitrate);
+ sensitive = TRUE;
+ break;
}
- p += strlen("{bitrate}");
+ jj++;
}
- else
+ sensitive = die ^ sensitive;
+ if (!sensitive)
{
- g_string_append_printf(str, "%c", *p);
- p++;
+ result = FALSE;
+ *out_hide |= hide;
}
+ g_strfreev (values);
+ g_free(value);
}
- g_string_append_printf(str, ".%s", extension);
- filename = g_string_free(str, FALSE);
- ghb_dict_set_string(settings, "dest_file", filename);
- g_free(filename);
}
+ return result;
}
-static void
-set_destination(signal_user_data_t *ud)
-{
- set_destination_settings(ud, ud->settings);
- ghb_ui_update(ud, "dest_file",
- ghb_dict_get_value(ud->settings, "dest_file"));
-}
-
-static gchar*
-get_file_label(const gchar *filename)
+void
+ghb_check_dependency(
+ signal_user_data_t *ud,
+ GtkWidget *widget,
+ const char *alt_name)
{
- gchar *base, *pos, *end;
+ GObject *dep_object;
+ const gchar *name;
+ GhbValue *array, *data;
+ gint count, ii;
+ const gchar *dep_name;
+ GType type;
- base = g_path_get_basename(filename);
- pos = strrchr(base, '.');
- if (pos != NULL)
+ if (widget != NULL)
{
- // If the last '.' is within 4 chars of end of name, assume
- // there is an extension we want to strip.
- end = &base[strlen(base) - 1];
- if (end - pos <= 4)
- *pos = 0;
+ type = G_OBJECT_TYPE(widget);
+ if (type == GTK_TYPE_COMBO_BOX)
+ if (gtk_combo_box_get_active(GTK_COMBO_BOX(widget)) < 0) return;
+ name = ghb_get_setting_key(widget);
}
- return base;
-}
+ else
+ name = alt_name;
-static gchar*
-resolve_drive_name(gchar *filename)
-{
-#if defined(_WIN32)
- if (filename[1] == ':')
+ g_debug("ghb_check_dependency() %s", name);
+
+ if (dep_map == NULL) return;
+ array = ghb_dict_get(dep_map, name);
+ count = ghb_array_len(array);
+ for (ii = 0; ii < count; ii++)
{
- gchar drive[4];
- gchar *name;
- gint dtype;
+ gboolean sensitive;
+ gboolean hide;
- g_strlcpy(drive, filename, 4);
- dtype = GetDriveType(drive);
- if (dtype == DRIVE_CDROM)
+ data = ghb_array_get(array, ii);
+ dep_name = ghb_value_get_string(data);
+ dep_object = gtk_builder_get_object(ud->builder, dep_name);
+ if (dep_object == NULL)
{
- gchar vname[51], fsname[51];
- GetVolumeInformation(drive, vname, 50, NULL,
- NULL, NULL, fsname, 50);
- name = g_strdup(vname);
- return name;
+ g_message("Failed to find dependent widget %s", dep_name);
+ continue;
+ }
+ sensitive = dep_check(ud, dep_name, &hide);
+ gtk_widget_set_sensitive(GTK_WIDGET(dep_object), sensitive);
+ gtk_widget_set_can_focus(GTK_WIDGET(dep_object), sensitive);
+ if (!sensitive && hide)
+ {
+ if (gtk_widget_get_visible(GTK_WIDGET(dep_object)))
+ {
+ gtk_widget_hide(GTK_WIDGET(dep_object));
+ }
+ }
+ else
+ {
+ if (!gtk_widget_get_visible(GTK_WIDGET(dep_object)))
+ {
+ gtk_widget_show_now(GTK_WIDGET(dep_object));
+ }
}
}
- return NULL;
-#else
- return NULL;
-#endif
}
-static gboolean
-update_source_label(signal_user_data_t *ud, const gchar *source)
+void
+ghb_check_all_depencencies(signal_user_data_t *ud)
{
- GStatBuf stat_buf;
- gchar *label = NULL;
- gint len;
- gchar **path;
- gchar *start;
- gchar *filename = g_strdup(source);
+ GhbDictIter iter;
+ const gchar *dep_name;
+ GhbValue *value;
+ GObject *dep_object;
- g_debug("update_source_label()");
- if (g_stat(filename, &stat_buf) == 0)
+ g_debug("ghb_check_all_depencencies ()");
+ if (rev_map == NULL) return;
+ iter = ghb_dict_iter_init(rev_map);
+ while (ghb_dict_iter_next(rev_map, &iter, &dep_name, &value))
{
- len = strlen(filename);
- if (S_ISDIR(stat_buf.st_mode))
- {
- // Skip dos drive letters
-#if defined(_WIN32)
- start = strchr(filename, ':');
-#else
- start = filename;
-#endif
- label = resolve_drive_name(filename);
- if (label != NULL)
- {
- if (uppers_and_unders(label))
- {
- camel_convert(label);
- }
- }
- else
- {
- if (filename[len-1] == G_DIR_SEPARATOR) filename[len-1] = 0;
- if (start != NULL)
- start++;
- else
- start = filename;
+ gboolean sensitive;
+ gboolean hide;
- path = g_strsplit(start, G_DIR_SEPARATOR_S, -1);
- len = g_strv_length (path);
- if ((len > 1) && (strcmp("VIDEO_TS", path[len-1]) == 0))
- {
- label = g_strdup(path[len-2]);
- if (uppers_and_unders(label))
- {
- camel_convert(label);
- }
- }
- else if (len > 0)
- {
- if (path[len-1][0] != 0)
- {
- label = g_strdup(path[len-1]);
- if (uppers_and_unders(label))
- {
- camel_convert(label);
- }
- }
- else
- label = g_strdup("new_video");
- }
- else
- label = g_strdup("new_video");
- g_strfreev (path);
- }
+ dep_object = gtk_builder_get_object (ud->builder, dep_name);
+ if (dep_object == NULL)
+ {
+ g_message("Failed to find dependent widget %s", dep_name);
+ continue;
}
- else if (S_ISBLK(stat_buf.st_mode))
+ sensitive = dep_check(ud, dep_name, &hide);
+ gtk_widget_set_sensitive(GTK_WIDGET(dep_object), sensitive);
+ gtk_widget_set_can_focus(GTK_WIDGET(dep_object), sensitive);
+ if (!sensitive && hide)
{
- // Is regular file or block dev.
- // Check to see if it is a dvd image
- label = ghb_dvd_volname(filename);
- if (label == NULL)
- {
- label = get_file_label(filename);
- }
- else
- {
- if (uppers_and_unders(label))
- {
- camel_convert(label);
- }
- }
+ gtk_widget_hide(GTK_WIDGET(dep_object));
}
else
{
- label = get_file_label(filename);
+ gtk_widget_show_now(GTK_WIDGET(dep_object));
}
}
- else
- {
- label = get_file_label(filename);
- }
- g_free(filename);
- GtkWidget *widget = GHB_WIDGET (ud->builder, "source_label");
- if (label != NULL)
- {
- gtk_label_set_text (GTK_LABEL(widget), label);
- ghb_dict_set_string(ud->globals, "volume", label);
- g_free(label);
- }
- else
- {
- label = _("No Title Found");
- gtk_label_set_text (GTK_LABEL(widget), label);
- ghb_dict_set_string(ud->globals, "volume", label);
- return FALSE;
- }
- return TRUE;
}
G_MODULE_EXPORT void
-chooser_file_selected_cb(GtkFileChooser *dialog, signal_user_data_t *ud)
+quit_action_cb(GSimpleAction *action, GVariant *param, signal_user_data_t *ud)
{
- gchar *name = gtk_file_chooser_get_filename (dialog);
- GtkTreeModel *store;
- GtkTreeIter iter;
- const gchar *device;
- gboolean foundit = FALSE;
- GtkComboBox *combo;
-
- g_debug("chooser_file_selected_cb ()");
-
- if (name == NULL) return;
- combo = GTK_COMBO_BOX(GHB_WIDGET(ud->builder, "source_device"));
- store = gtk_combo_box_get_model(combo);
- if (gtk_tree_model_get_iter_first(store, &iter))
+ gint state = ghb_get_queue_state();
+ if (state & (GHB_STATE_WORKING|GHB_STATE_SEARCHING))
{
- do
+ if (ghb_cancel_encode2(ud, _("Closing HandBrake will terminate encoding.\n")))
{
- gtk_tree_model_get(store, &iter, 0, &device, -1);
- if (strcmp(name, device) == 0)
- {
- foundit = TRUE;
- break;
- }
- } while (gtk_tree_model_iter_next(GTK_TREE_MODEL(store), &iter));
+ ghb_hb_cleanup(FALSE);
+ prune_logs(ud);
+ g_application_quit(G_APPLICATION(ud->app));
+ return;
+ }
+ return;
}
- if (foundit)
- gtk_combo_box_set_active_iter (combo, &iter);
- else
- gtk_combo_box_set_active (combo, 0);
-
- g_free(name);
+ ghb_hb_cleanup(FALSE);
+ prune_logs(ud);
+ g_application_quit(G_APPLICATION(ud->app));
}
-G_MODULE_EXPORT void
-dvd_device_changed_cb(GtkComboBoxText *combo, signal_user_data_t *ud)
+gboolean
+uppers_and_unders(gchar *str)
{
- GtkWidget *dialog;
- gint ii;
-
- g_debug("dvd_device_changed_cb ()");
- ii = gtk_combo_box_get_active (GTK_COMBO_BOX(combo));
- if (ii > 0)
+ if (str == NULL) return FALSE;
+ str = g_strchomp(g_strchug(str));
+ while (*str)
{
- const gchar *device;
- gchar *name;
-
- dialog = GHB_WIDGET(ud->builder, "source_dialog");
- device = gtk_combo_box_text_get_active_text(combo);
- // Protext against unexpected NULL return value
- if (device != NULL)
+ if (*str == ' ')
{
- name = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER(dialog));
- if (name == NULL || strcmp(name, device) != 0)
- gtk_file_chooser_select_filename (GTK_FILE_CHOOSER(dialog), device);
- if (name != NULL)
- g_free(name);
+ return FALSE;
+ }
+ if (*str >= 'a' && *str <= 'z')
+ {
+ return FALSE;
}
+ str++;
}
+ return TRUE;
}
-static void
-source_dialog_extra_widgets(
- signal_user_data_t *ud,
- GtkWidget *dialog)
+enum
{
- GtkComboBoxText *combo;
- GList *drives, *link;
+ CAMEL_FIRST_UPPER,
+ CAMEL_OTHER
+};
- g_debug("source_dialog_extra_widgets ()");
- combo = GTK_COMBO_BOX_TEXT(GHB_WIDGET(ud->builder, "source_device"));
- gtk_list_store_clear(GTK_LIST_STORE(
- gtk_combo_box_get_model(GTK_COMBO_BOX(combo))));
+void
+camel_convert(gchar *str)
+{
+ gint state = CAMEL_OTHER;
- link = drives = dvd_device_list();
- gtk_combo_box_text_append_text (combo, _("Not Selected"));
- while (link != NULL)
+ if (str == NULL) return;
+ while (*str)
{
- gchar *name = get_dvd_device_name(link->data);
- gtk_combo_box_text_append_text(combo, name);
- g_free(name);
- free_drive(link->data);
- link = link->next;
- }
- g_list_free(drives);
- gtk_combo_box_set_active(GTK_COMBO_BOX(combo), 0);
+ if (*str == '_') *str = ' ';
+ switch (state)
+ {
+ case CAMEL_OTHER:
+ {
+ if (*str >= 'A' && *str <= 'Z')
+ state = CAMEL_FIRST_UPPER;
+ else
+ state = CAMEL_OTHER;
+
+ } break;
+ case CAMEL_FIRST_UPPER:
+ {
+ if (*str >= 'A' && *str <= 'Z')
+ *str = *str - 'A' + 'a';
+ else
+ state = CAMEL_OTHER;
+ } break;
+ }
+ str++;
+ }
}
-static void break_duration(gint64 duration, gint *hh, gint *mm, gint *ss)
+#if defined(_WIN32)
+static gchar*
+get_dvd_device_name(gchar *device)
{
- *hh = duration / (60*60);
- *mm = (duration / 60) % 60;
- *ss = duration % 60;
+ return g_strdup(device);
+}
+#else
+static gchar*
+get_dvd_device_name(GDrive *gd)
+{
+ return g_drive_get_identifier(gd, G_VOLUME_IDENTIFIER_KIND_UNIX_DEVICE);
}
+#endif
+
+static GHashTable *volname_hash = NULL;
+#if GLIB_CHECK_VERSION(2, 32, 0)
+static GMutex volname_mutex_static;
+#endif
+static GMutex *volname_mutex;
static void
-update_title_duration(signal_user_data_t *ud)
+free_volname_key(gpointer data)
{
- gint hh, mm, ss, start, end;
- gchar *text;
- GtkWidget *widget;
- int title_id, titleindex;
- const hb_title_t *title;
+ if (data != NULL)
+ g_free(data);
+}
- title_id = ghb_dict_get_int(ud->settings, "title");
- title = ghb_lookup_title(title_id, &titleindex);
- widget = GHB_WIDGET (ud->builder, "title_duration");
+static void
+free_volname_value(gpointer data)
+{
+ if (data != NULL)
+ g_free(data);
+}
- if (ghb_settings_combo_int(ud->settings, "PtoPType") == 0)
+#if defined(_WIN32)
+static gchar*
+get_direct_dvd_volume_name(const gchar *drive)
+{
+ gchar *result = NULL;
+ gchar vname[51], fsname[51];
+
+ if (GetVolumeInformation(drive, vname, 50, NULL, NULL, NULL, fsname, 50))
{
- start = ghb_dict_get_int(ud->settings, "start_point");
- end = ghb_dict_get_int(ud->settings, "end_point");
- ghb_part_duration(title, start, end, &hh, &mm, &ss);
+ result = g_strdup_printf("%s", vname);
}
- else if (ghb_settings_combo_int(ud->settings, "PtoPType") == 1)
- {
- gint duration;
+ return result;
+}
+#else
+static gchar*
+get_direct_dvd_volume_name(const gchar *drive)
+{
+ gchar *result;
- start = ghb_dict_get_int(ud->settings, "start_point");
- end = ghb_dict_get_int(ud->settings, "end_point");
- duration = end - start;
- break_duration(duration, &hh, &mm, &ss);
- }
- else if (ghb_settings_combo_int(ud->settings, "PtoPType") == 2)
- {
- if (title != NULL)
- {
- gint64 frames;
- gint duration;
+ result = ghb_dvd_volname (drive);
+ return result;
+}
+#endif
- start = ghb_dict_get_int(ud->settings, "start_point");
- end = ghb_dict_get_int(ud->settings, "end_point");
- frames = end - start + 1;
- duration = frames * title->vrate.den / title->vrate.num;
- break_duration(duration, &hh, &mm, &ss);
- }
- else
+static gchar*
+get_dvd_volume_name(gpointer gd)
+{
+ gchar *label = NULL;
+ gchar *result;
+ gchar *drive;
+
+ drive = get_dvd_device_name(gd);
+ g_mutex_lock(volname_mutex);
+ label = g_strdup(g_hash_table_lookup(volname_hash, drive));
+ g_mutex_unlock(volname_mutex);
+ if (label != NULL)
+ {
+ if (uppers_and_unders(label))
{
- hh = mm = ss = 0;
+ camel_convert(label);
}
+#if defined(_WIN32)
+ result = g_strdup_printf("%s (%s)", label, drive);
+#else
+ result = g_strdup_printf("%s - %s", drive, label);
+#endif
+ g_free(label);
}
- text = g_strdup_printf("%02d:%02d:%02d", hh, mm, ss);
- gtk_label_set_text(GTK_LABEL(widget), text);
- g_free(text);
+ else
+ {
+ result = g_strdup_printf("%s", drive);
+ }
+ g_free(drive);
+ return result;
}
-void ghb_show_container_options(signal_user_data_t *ud)
+void
+ghb_volname_cache_init(void)
{
- GtkWidget *w1, *w2, *w3;
- w1 = GHB_WIDGET(ud->builder, "AlignAVStart");
- w2 = GHB_WIDGET(ud->builder, "Mp4HttpOptimize");
- w3 = GHB_WIDGET(ud->builder, "Mp4iPodCompatible");
-
- const char *mux_id;
- const hb_container_t *mux;
-
- mux_id = ghb_dict_get_string(ud->settings, "FileFormat");
- mux = ghb_lookup_container_by_name(mux_id);
-
- gint enc = ghb_settings_video_encoder_codec(ud->settings, "VideoEncoder");
-
- gtk_widget_set_visible(w1, (mux->format & HB_MUX_MASK_MP4));
- gtk_widget_set_visible(w2, (mux->format & HB_MUX_MASK_MP4));
- gtk_widget_set_visible(w3, (mux->format & HB_MUX_MASK_MP4) &&
- (enc == HB_VCODEC_X264_8BIT));
+#if GLIB_CHECK_VERSION(2, 32, 0)
+ g_mutex_init(&volname_mutex_static);
+ volname_mutex = &volname_mutex_static;
+#else
+ volname_mutex = g_mutex_new();
+#endif
+ volname_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
+ free_volname_key, free_volname_value);
}
static void
-adjustment_configure(
- GtkAdjustment *adj,
- double val,
- double min, double max,
- double step, double page, double page_sz)
+free_drive(gpointer drive)
{
- gtk_adjustment_configure(adj, val, min, max, step, page, page_sz);
+#if defined(_WIN32)
+ g_free(drive);
+#else
+ g_object_unref(drive);
+#endif
}
-static void
-spin_configure(signal_user_data_t *ud, char *name, double val, double min, double max)
+gpointer
+ghb_cache_volnames(signal_user_data_t *ud)
{
- GtkSpinButton *spin;
- GtkAdjustment *adj;
- double step, page, page_sz;
+ GList *link, *drives;
- spin = GTK_SPIN_BUTTON(GHB_WIDGET(ud->builder, name));
+ g_debug("ghb_cache_volnames()");
+ link = drives = dvd_device_list();
+ if (drives == NULL)
+ return NULL;
- adj = gtk_spin_button_get_adjustment(spin);
- step = gtk_adjustment_get_step_increment(adj);
- page = gtk_adjustment_get_page_increment(adj);
- page_sz = gtk_adjustment_get_page_size(adj);
+ g_mutex_lock(volname_mutex);
+ g_hash_table_remove_all(volname_hash);
+ while (link != NULL)
+ {
+ gchar *name, *drive;
- adjustment_configure(adj, val, min, max, step, page, page_sz);
-}
+#if !defined(_WIN32)
+ if (!g_drive_has_media (link->data))
+ {
+ g_object_unref(link->data);
+ link = link->next;
+ continue;
+ }
+#endif
+ drive = get_dvd_device_name(link->data);
+ name = get_direct_dvd_volume_name(drive);
-void
-ghb_scale_configure(
- signal_user_data_t *ud,
- char *name,
- double val, double min, double max,
- double step, double page,
- int digits, gboolean inverted)
-{
- GtkScale *scale;
- GtkAdjustment *adj;
- double page_sz;
+ if (drive != NULL && name != NULL)
+ {
+ g_hash_table_insert(volname_hash, drive, name);
+ }
+ else
+ {
+ if (drive != NULL)
+ g_free(drive);
+ if (name != NULL)
+ g_free(name);
+ }
- scale = GTK_SCALE(GHB_WIDGET(ud->builder, name));
+ free_drive(link->data);
+ link = link->next;
+ }
+ g_mutex_unlock(volname_mutex);
- adj = gtk_range_get_adjustment(GTK_RANGE(scale));
- page_sz = gtk_adjustment_get_page_size(adj);
+ g_list_free(drives);
- adjustment_configure(adj, val, min, max, step, page, page_sz);
+ g_idle_add((GSourceFunc)ghb_file_menu_add_dvd, ud);
- gtk_scale_set_digits(scale, digits);
- gtk_range_set_inverted(GTK_RANGE(scale), inverted);
+ return NULL;
}
-void
-ghb_set_widget_ranges(signal_user_data_t *ud, GhbValue *settings)
+static const gchar*
+get_extension(signal_user_data_t *ud, GhbValue *settings)
{
- int title_id, titleindex;
- const hb_title_t * title;
- double val;
+ const char *mux_id;
+ const hb_container_t *mux;
- title_id = ghb_dict_get_int(settings, "title");
- title = ghb_lookup_title(title_id, &titleindex);
+ mux_id = ghb_dict_get_string(settings, "FileFormat");
+ mux = ghb_lookup_container_by_name(mux_id);
- // Reconfigure the UI combo boxes
- ghb_update_ui_combo_box(ud, "AudioTrack", title, FALSE);
- ghb_update_ui_combo_box(ud, "SubtitleTrack", title, FALSE);
+ if ((mux->format & HB_MUX_MASK_MP4) &&
+ ghb_dict_get_bool(ud->prefs, "UseM4v"))
+ {
+ return "m4v";
+ }
+ return mux->default_extension;
+}
- if (title != NULL)
+static gboolean
+check_name_template(signal_user_data_t *ud, const char *str)
+{
+ if (ghb_dict_get_bool(ud->prefs, "auto_name"))
{
+ const gchar *template;
- // Set the limits of cropping. hb_set_anamorphic_size crashes if
- // you pass it a cropped width or height == 0.
- gint vbound, hbound;
- vbound = title->geometry.height;
- hbound = title->geometry.width;
+ template = ghb_dict_get_string(ud->prefs, "auto_name_template");
+ if (strstr(template, str) != NULL)
+ return TRUE;
+ }
+ return FALSE;
+}
- val = ghb_dict_get_int(ud->settings, "PictureTopCrop");
- spin_configure(ud, "PictureTopCrop", val, 0, vbound);
- val = ghb_dict_get_int(ud->settings, "PictureBottomCrop");
- spin_configure(ud, "PictureBottomCrop", val, 0, vbound);
- val = ghb_dict_get_int(ud->settings, "PictureLeftCrop");
- spin_configure(ud, "PictureLeftCrop", val, 0, hbound);
- val = ghb_dict_get_int(ud->settings, "PictureRightCrop");
- spin_configure(ud, "PictureRightCrop", val, 0, hbound);
+static void
+set_destination_settings(signal_user_data_t *ud, GhbValue *settings)
+{
+ const gchar *extension, *dest_file;
+ gchar *filename;
- gint duration = title->duration / 90000;
+ extension = get_extension(ud, settings);
- if (ghb_settings_combo_int(ud->settings, "PtoPType") == 0)
- {
- gint num_chapters = hb_list_count(title->list_chapter);
+ g_debug("set_destination_settings");
+ dest_file = ghb_dict_get_string(ud->settings, "dest_file");
+ if (dest_file == NULL)
+ {
+ // Initialize destination filename if it has no value yet.
+ // If auto-naming is disabled, this will be the default filename.
+ GString *str = g_string_new("");
+ const gchar *vol_name;
+ vol_name = ghb_dict_get_string(settings, "volume");
+ g_string_append_printf(str, "%s", vol_name);
+ g_string_append_printf(str, ".%s", extension);
+ filename = g_string_free(str, FALSE);
+ ghb_dict_set_string(settings, "dest_file", filename);
+ g_free(filename);
+ }
+ if (ghb_dict_get_bool(ud->prefs, "auto_name"))
+ {
+ GString *str = g_string_new("");
+ const gchar *p;
- val = ghb_dict_get_int(ud->settings, "start_point");
- spin_configure(ud, "start_point", val, 1, num_chapters);
- val = ghb_dict_get_int(ud->settings, "end_point");
- spin_configure(ud, "end_point", val, 1, num_chapters);
- }
- else if (ghb_settings_combo_int(ud->settings, "PtoPType") == 1)
- {
- val = ghb_dict_get_int(ud->settings, "start_point");
- spin_configure(ud, "start_point", val, 0, duration * 2 - 1);
- val = ghb_dict_get_int(ud->settings, "end_point");
- spin_configure(ud, "end_point", val, 0, duration * 2);
- }
- else if (ghb_settings_combo_int(ud->settings, "PtoPType") == 2)
+ p = ghb_dict_get_string(ud->prefs, "auto_name_template");
+ while (*p)
{
- gdouble max_frames;
- max_frames = (gdouble)duration *
- title->vrate.num / title->vrate.den;
-
- val = ghb_dict_get_int(ud->settings, "start_point");
- spin_configure(ud, "start_point", val, 1, max_frames * 2);
- val = ghb_dict_get_int(ud->settings, "end_point");
- spin_configure(ud, "end_point", val, 1, max_frames * 2);
+ if (!strncmp(p, "{source}", strlen("{source}")))
+ {
+ const gchar *vol_name;
+ vol_name = ghb_dict_get_string(settings, "volume");
+ g_string_append_printf(str, "%s", vol_name);
+ p += strlen("{source}");
+ }
+ else if (!strncmp(p, "{title}", strlen("{title}")))
+ {
+ gint title = ghb_dict_get_int(settings, "title");
+ if (title >= 0)
+ g_string_append_printf(str, "%d", title);
+ p += strlen("{title}");
+ }
+ else if (!strncmp(p, "{preset}", strlen("{preset}")))
+ {
+ const gchar *preset_name;
+ preset_name = ghb_dict_get_string(settings, "PresetName");
+ g_string_append_printf(str, "%s", preset_name);
+ p += strlen("{preset}");
+ }
+ else if (!strncmp(p, "{chapters}", strlen("{chapters}")))
+ {
+ if (ghb_settings_combo_int(settings, "PtoPType") == 0)
+ {
+ gint start, end;
+ start = ghb_dict_get_int(settings, "start_point");
+ end = ghb_dict_get_int(settings, "end_point");
+ if (start == end)
+ g_string_append_printf(str, "%d", start);
+ else
+ g_string_append_printf(str, "%d-%d", start, end);
+ }
+ p += strlen("{chapters}");
+ }
+ else if (!strncmp(p, "{time}", strlen("{time}")))
+ {
+ char st[6];
+ struct tm *lt;
+ time_t t = time(NULL);
+ lt = localtime(&t);
+ st[0] = 0;
+ strftime(st, 6, "%H:%M", lt);
+ g_string_append_printf(str, "%s", st);
+ p += strlen("{time}");
+ }
+ else if (!strncmp(p, "{date}", strlen("{date}")))
+ {
+ char dt[11];
+ struct tm *lt;
+ time_t t = time(NULL);
+ lt = localtime(&t);
+ dt[0] = 0;
+ strftime(dt, 11, "%Y-%m-%d", lt);
+ g_string_append_printf(str, "%s", dt);
+ p += strlen("{date}");
+ }
+ else if (!strncmp(p, "{quality}", strlen("{quality}")))
+ {
+ if (ghb_dict_get_bool(settings, "vquality_type_constant"))
+ {
+ gint vcodec;
+ const char *vqname;
+ double vquality;
+ vcodec = ghb_settings_video_encoder_codec(settings, "VideoEncoder");
+ vqname = hb_video_quality_get_name(vcodec);
+ vquality = ghb_dict_get_double(settings, "VideoQualitySlider");
+ g_string_append_printf(str, "%s%.3g", vqname, vquality);
+ }
+ p += strlen("{quality}");
+ }
+ else if (!strncmp(p, "{bitrate}", strlen("{bitrate}")))
+ {
+ if (ghb_dict_get_bool(settings, "vquality_type_bitrate"))
+ {
+ int vbitrate;
+ vbitrate = ghb_dict_get_int(settings, "VideoAvgBitrate");
+ g_string_append_printf(str, "%dkbps", vbitrate);
+ }
+ p += strlen("{bitrate}");
+ }
+ else
+ {
+ g_string_append_printf(str, "%c", *p);
+ p++;
+ }
}
-
- val = ghb_dict_get_int(ud->settings, "angle");
- spin_configure(ud, "angle", val, 1, title->angle_count);
+ g_string_append_printf(str, ".%s", extension);
+ filename = g_string_free(str, FALSE);
+ ghb_dict_set_string(settings, "dest_file", filename);
+ g_free(filename);
}
-
- float vqmin, vqmax, step, page;
- int inverted, digits;
-
- ghb_vquality_range(ud, &vqmin, &vqmax, &step, &page, &digits, &inverted);
- val = ghb_dict_get_double(ud->settings, "VideoQualitySlider");
- ghb_scale_configure(ud, "VideoQualitySlider", val, vqmin, vqmax,
- step, page, digits, inverted);
}
static void
-check_chapter_markers(signal_user_data_t *ud)
+set_destination(signal_user_data_t *ud)
{
- GtkWidget *widget;
- gint start, end;
-
- if (ghb_settings_combo_int(ud->settings, "PtoPType") == 0)
- {
- start = ghb_dict_get_int(ud->settings, "start_point");
- end = ghb_dict_get_int(ud->settings, "end_point");
- widget = GHB_WIDGET (ud->builder, "ChapterMarkers");
- gtk_widget_set_sensitive(widget, end > start);
- }
+ set_destination_settings(ud, ud->settings);
+ ghb_ui_update(ud, "dest_file",
+ ghb_dict_get_value(ud->settings, "dest_file"));
}
-void
-ghb_load_settings(signal_user_data_t * ud)
+static gchar*
+get_file_label(const gchar *filename)
{
- const char * fullname;
- int type;
- gboolean preset_modified;
- static gboolean busy = FALSE;
-
- if (busy)
- return;
- busy = TRUE;
+ gchar *base, *pos, *end;
- fullname = ghb_dict_get_string(ud->settings, "PresetFullName");
- type = ghb_dict_get_int(ud->settings, "Type");
- preset_modified = ghb_dict_get_bool(ud->settings, "preset_modified");
- if (preset_modified)
- {
- ghb_clear_presets_selection(ud);
- ghb_preset_menu_button_refresh(ud, fullname, type);
- }
- else
+ base = g_path_get_basename(filename);
+ pos = strrchr(base, '.');
+ if (pos != NULL)
{
- ghb_dict_set_bool(ud->settings, "preset_reload", TRUE);
- ghb_select_preset(ud, fullname, type);
- ghb_dict_set_bool(ud->settings, "preset_reload", FALSE);
+ // If the last '.' is within 4 chars of end of name, assume
+ // there is an extension we want to strip.
+ end = &base[strlen(base) - 1];
+ if (end - pos <= 4)
+ *pos = 0;
}
-
- busy = FALSE;
-
- ghb_load_post_settings(ud);
+ return base;
}
-void
-ghb_load_post_settings(signal_user_data_t * ud)
+static gchar*
+resolve_drive_name(gchar *filename)
{
- static gboolean busy = FALSE;
- if (busy)
- return;
- busy = TRUE;
-
- ud->dont_clear_presets = TRUE;
- ud->scale_busy = TRUE;
+#if defined(_WIN32)
+ if (filename[1] == ':')
+ {
+ gchar drive[4];
+ gchar *name;
+ gint dtype;
- ghb_set_widget_ranges(ud, ud->settings);
- ghb_check_all_depencencies(ud);
- ghb_show_container_options(ud);
- check_chapter_markers(ud);
+ g_strlcpy(drive, filename, 4);
+ dtype = GetDriveType(drive);
+ if (dtype == DRIVE_CDROM)
+ {
+ gchar vname[51], fsname[51];
+ GetVolumeInformation(drive, vname, 50, NULL,
+ NULL, NULL, fsname, 50);
+ name = g_strdup(vname);
+ return name;
+ }
+ }
+ return NULL;
+#else
+ return NULL;
+#endif
+}
- ghb_clear_audio_selection(ud->builder);
- ghb_clear_subtitle_selection(ud->builder);
- ghb_settings_to_ui(ud, ud->settings);
- ghb_audio_defaults_to_ui(ud);
- ghb_subtitle_defaults_to_ui(ud);
- ghb_audio_list_refresh_all(ud);
- ghb_subtitle_list_refresh_all(ud);
- ghb_chapter_list_refresh_all(ud);
- update_title_duration(ud);
- ghb_update_title_info(ud);
+static gboolean
+update_source_label(signal_user_data_t *ud, const gchar *source)
+{
+ GStatBuf stat_buf;
+ gchar *label = NULL;
+ gint len;
+ gchar **path;
+ gchar *start;
+ gchar *filename = g_strdup(source);
- ud->dont_clear_presets = FALSE;
- ud->scale_busy = FALSE;
- busy = FALSE;
+ g_debug("update_source_label()");
+ if (g_stat(filename, &stat_buf) == 0)
+ {
+ len = strlen(filename);
+ if (S_ISDIR(stat_buf.st_mode))
+ {
+ // Skip dos drive letters
+#if defined(_WIN32)
+ start = strchr(filename, ':');
+#else
+ start = filename;
+#endif
+ label = resolve_drive_name(filename);
+ if (label != NULL)
+ {
+ if (uppers_and_unders(label))
+ {
+ camel_convert(label);
+ }
+ }
+ else
+ {
+ if (filename[len-1] == G_DIR_SEPARATOR) filename[len-1] = 0;
+ if (start != NULL)
+ start++;
+ else
+ start = filename;
- ghb_picture_settings_deps(ud);
+ path = g_strsplit(start, G_DIR_SEPARATOR_S, -1);
+ len = g_strv_length (path);
+ if ((len > 1) && (strcmp("VIDEO_TS", path[len-1]) == 0))
+ {
+ label = g_strdup(path[len-2]);
+ if (uppers_and_unders(label))
+ {
+ camel_convert(label);
+ }
+ }
+ else if (len > 0)
+ {
+ if (path[len-1][0] != 0)
+ {
+ label = g_strdup(path[len-1]);
+ if (uppers_and_unders(label))
+ {
+ camel_convert(label);
+ }
+ }
+ else
+ label = g_strdup("new_video");
+ }
+ else
+ label = g_strdup("new_video");
+ g_strfreev (path);
+ }
+ }
+ else if (S_ISBLK(stat_buf.st_mode))
+ {
+ // Is regular file or block dev.
+ // Check to see if it is a dvd image
+ label = ghb_dvd_volname(filename);
+ if (label == NULL)
+ {
+ label = get_file_label(filename);
+ }
+ else
+ {
+ if (uppers_and_unders(label))
+ {
+ camel_convert(label);
+ }
+ }
+ }
+ else
+ {
+ label = get_file_label(filename);
+ }
+ }
+ else
+ {
+ label = get_file_label(filename);
+ }
+ g_free(filename);
+ GtkWidget *widget = GHB_WIDGET (ud->builder, "source_label");
+ if (label != NULL)
+ {
+ gtk_label_set_text (GTK_LABEL(widget), label);
+ ghb_dict_set_string(ud->globals, "volume", label);
+ g_free(label);
+ }
+ else
+ {
+ label = _("No Title Found");
+ gtk_label_set_text (GTK_LABEL(widget), label);
+ ghb_dict_set_string(ud->globals, "volume", label);
+ return FALSE;
+ }
+ return TRUE;
}
-static void
-show_scan_progress(signal_user_data_t *ud)
+G_MODULE_EXPORT void
+chooser_file_selected_cb(GtkFileChooser *dialog, signal_user_data_t *ud)
{
- GtkWidget * widget;
- GtkProgressBar * progress;
- GtkLabel * label;
+ gchar *name = gtk_file_chooser_get_filename (dialog);
+ GtkTreeModel *store;
+ GtkTreeIter iter;
+ const gchar *device;
+ gboolean foundit = FALSE;
+ GtkComboBox *combo;
- widget = GHB_WIDGET(ud->builder, "SourceInfoBox");
- gtk_widget_hide(widget);
+ g_debug("chooser_file_selected_cb ()");
- widget = GHB_WIDGET(ud->builder, "SourceScanBox");
- gtk_widget_show(widget);
+ if (name == NULL) return;
+ combo = GTK_COMBO_BOX(GHB_WIDGET(ud->builder, "source_device"));
+ store = gtk_combo_box_get_model(combo);
+ if (gtk_tree_model_get_iter_first(store, &iter))
+ {
+ do
+ {
+ gtk_tree_model_get(store, &iter, 0, &device, -1);
+ if (strcmp(name, device) == 0)
+ {
+ foundit = TRUE;
+ break;
+ }
+ } while (gtk_tree_model_iter_next(GTK_TREE_MODEL(store), &iter));
+ }
+ if (foundit)
+ gtk_combo_box_set_active_iter (combo, &iter);
+ else
+ gtk_combo_box_set_active (combo, 0);
- progress = GTK_PROGRESS_BAR(GHB_WIDGET(ud->builder, "scan_prog"));
- gtk_progress_bar_set_fraction(progress, 0);
+ g_free(name);
+}
- label = GTK_LABEL(GHB_WIDGET(ud->builder, "source_scan_label"));
- gtk_label_set_text( label, _("Scanning ...") );
+G_MODULE_EXPORT void
+dvd_device_changed_cb(GtkComboBoxText *combo, signal_user_data_t *ud)
+{
+ GtkWidget *dialog;
+ gint ii;
+
+ g_debug("dvd_device_changed_cb ()");
+ ii = gtk_combo_box_get_active (GTK_COMBO_BOX(combo));
+ if (ii > 0)
+ {
+ const gchar *device;
+ gchar *name;
+ dialog = GHB_WIDGET(ud->builder, "source_dialog");
+ device = gtk_combo_box_text_get_active_text(combo);
+ // Protext against unexpected NULL return value
+ if (device != NULL)
+ {
+ name = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER(dialog));
+ if (name == NULL || strcmp(name, device) != 0)
+ gtk_file_chooser_select_filename (GTK_FILE_CHOOSER(dialog), device);
+ if (name != NULL)
+ g_free(name);
+ }
+ }
}
static void
-hide_scan_progress(signal_user_data_t *ud)
+source_dialog_extra_widgets(
+ signal_user_data_t *ud,
+ GtkWidget *dialog)
{
- GtkWidget * widget;
- GtkProgressBar * progress;
+ GtkComboBoxText *combo;
+ GList *drives, *link;
- progress = GTK_PROGRESS_BAR(GHB_WIDGET(ud->builder, "scan_prog"));
- gtk_progress_bar_set_fraction(progress, 1.0);
+ g_debug("source_dialog_extra_widgets ()");
+ combo = GTK_COMBO_BOX_TEXT(GHB_WIDGET(ud->builder, "source_device"));
+ gtk_list_store_clear(GTK_LIST_STORE(
+ gtk_combo_box_get_model(GTK_COMBO_BOX(combo))));
- widget = GHB_WIDGET(ud->builder, "SourceScanBox");
- gtk_widget_hide(widget);
+ link = drives = dvd_device_list();
+ gtk_combo_box_text_append_text (combo, _("Not Selected"));
+ while (link != NULL)
+ {
+ gchar *name = get_dvd_device_name(link->data);
+ gtk_combo_box_text_append_text(combo, name);
+ g_free(name);
+ free_drive(link->data);
+ link = link->next;
+ }
+ g_list_free(drives);
+ gtk_combo_box_set_active(GTK_COMBO_BOX(combo), 0);
+}
- widget = GHB_WIDGET(ud->builder, "SourceInfoBox");
- gtk_widget_show(widget);
+static void break_duration(gint64 duration, gint *hh, gint *mm, gint *ss)
+{
+ *hh = duration / (60*60);
+ *mm = (duration / 60) % 60;
+ *ss = duration % 60;
}
static void
-start_scan(
- signal_user_data_t *ud,
- const gchar *path,
- gint title_id,
- gint preview_count)
+update_title_duration(signal_user_data_t *ud)
{
- GtkWidget *widget;
- ghb_status_t status;
-
- ghb_get_status(&status);
- if (status.scan.state != GHB_STATE_IDLE)
- return;
-
- widget = GHB_WIDGET(ud->builder, "sourcetoolbutton");
- gtk_tool_button_set_icon_name(GTK_TOOL_BUTTON(widget), "hb-stop");
- gtk_tool_button_set_label(GTK_TOOL_BUTTON(widget), _("Stop\nScan"));
- gtk_tool_item_set_tooltip_text(GTK_TOOL_ITEM(widget), _("Stop Scan"));
-
- widget = GHB_WIDGET(ud->builder, "source_open");
- gtk_widget_set_sensitive(widget, FALSE);
- widget = GHB_WIDGET(ud->builder, "source_title_open");
- gtk_widget_set_sensitive(widget, FALSE);
- ghb_backend_scan(path, title_id, preview_count,
- 90000L * ghb_dict_get_int(ud->prefs, "MinTitleDuration"));
-}
-
-gboolean
-ghb_idle_scan(signal_user_data_t *ud)
-{
- gchar *path;
- // ghb_do_scan replaces "scan_source" key in dict, so we must
- // make a copy of the string.
- path = g_strdup(ghb_dict_get_string(ud->globals, "scan_source"));
- ghb_do_scan(ud, path, 0, TRUE);
- g_free(path);
- return FALSE;
-}
-
-extern GhbValue *ghb_queue_edit_settings;
-static gchar *last_scan_file = NULL;
-
-void
-ghb_do_scan(
- signal_user_data_t *ud,
- const gchar *filename,
- gint title_id,
- gboolean force)
-{
- int titleindex;
+ gint hh, mm, ss, start, end;
+ gchar *text;
+ GtkWidget *widget;
+ int title_id, titleindex;
const hb_title_t *title;
- (void)title; // Silence "unused variable" warning
+ title_id = ghb_dict_get_int(ud->settings, "title");
+ title = ghb_lookup_title(title_id, &titleindex);
+ widget = GHB_WIDGET (ud->builder, "title_duration");
- g_debug("ghb_do_scan()");
- if (!force && last_scan_file != NULL &&
- strcmp(last_scan_file, filename) == 0)
+ if (ghb_settings_combo_int(ud->settings, "PtoPType") == 0)
{
- if (ghb_queue_edit_settings != NULL)
- {
- title_id = ghb_dict_get_int(ghb_queue_edit_settings, "title");
- title = ghb_lookup_title(title_id, &titleindex);
- ghb_array_replace(ud->settings_array, titleindex,
- ghb_queue_edit_settings);
- ud->settings = ghb_queue_edit_settings;
- ghb_load_settings(ud);
- ghb_queue_edit_settings = NULL;
- }
- else
- {
- title = ghb_lookup_title(title_id, &titleindex);
- load_all_titles(ud, titleindex);
- }
- return;
+ start = ghb_dict_get_int(ud->settings, "start_point");
+ end = ghb_dict_get_int(ud->settings, "end_point");
+ ghb_part_duration(title, start, end, &hh, &mm, &ss);
}
- if (last_scan_file != NULL)
- g_free(last_scan_file);
- last_scan_file = NULL;
- if (filename != NULL)
+ else if (ghb_settings_combo_int(ud->settings, "PtoPType") == 1)
{
- last_scan_file = g_strdup(filename);
- ghb_dict_set_string(ud->globals, "scan_source", filename);
- if (update_source_label(ud, filename))
- {
- const gchar *path;
- gint preview_count;
+ gint duration;
- show_scan_progress(ud);
- path = ghb_dict_get_string(ud->globals, "scan_source");
- prune_logs(ud);
+ start = ghb_dict_get_int(ud->settings, "start_point");
+ end = ghb_dict_get_int(ud->settings, "end_point");
+ duration = end - start;
+ break_duration(duration, &hh, &mm, &ss);
+ }
+ else if (ghb_settings_combo_int(ud->settings, "PtoPType") == 2)
+ {
+ if (title != NULL)
+ {
+ gint64 frames;
+ gint duration;
- preview_count = ghb_dict_get_int(ud->prefs, "preview_count");
- start_scan(ud, path, title_id, preview_count);
+ start = ghb_dict_get_int(ud->settings, "start_point");
+ end = ghb_dict_get_int(ud->settings, "end_point");
+ frames = end - start + 1;
+ duration = frames * title->vrate.den / title->vrate.num;
+ break_duration(duration, &hh, &mm, &ss);
}
else
{
- // TODO: error dialog
+ hh = mm = ss = 0;
}
}
+ text = g_strdup_printf("%02d:%02d:%02d", hh, mm, ss);
+ gtk_label_set_text(GTK_LABEL(widget), text);
+ g_free(text);
}
-static void
-do_source_dialog(gboolean single, signal_user_data_t *ud)
+void ghb_show_container_options(signal_user_data_t *ud)
{
- GtkWidget *dialog;
- const gchar *sourcename;
- gint response;
-
- g_debug("source_browse_clicked_cb ()");
- sourcename = ghb_dict_get_string(ud->globals, "scan_source");
- GtkWidget *widget;
- widget = GHB_WIDGET(ud->builder, "single_title_box");
- if (single)
- gtk_widget_show(widget);
- else
- gtk_widget_hide(widget);
- dialog = GHB_WIDGET(ud->builder, "source_dialog");
- source_dialog_extra_widgets(ud, dialog);
+ GtkWidget *w1, *w2, *w3;
+ w1 = GHB_WIDGET(ud->builder, "AlignAVStart");
+ w2 = GHB_WIDGET(ud->builder, "Mp4HttpOptimize");
+ w3 = GHB_WIDGET(ud->builder, "Mp4iPodCompatible");
- gtk_widget_show(dialog);
- gtk_file_chooser_select_filename(GTK_FILE_CHOOSER(dialog), sourcename);
+ const char *mux_id;
+ const hb_container_t *mux;
- response = gtk_dialog_run(GTK_DIALOG (dialog));
- gtk_widget_hide(dialog);
- if (response == GTK_RESPONSE_NO)
- {
- gchar *filename;
+ mux_id = ghb_dict_get_string(ud->settings, "FileFormat");
+ mux = ghb_lookup_container_by_name(mux_id);
- filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
- if (filename != NULL)
- {
- gint title_id;
+ gint enc = ghb_settings_video_encoder_codec(ud->settings, "VideoEncoder");
- if (single)
- title_id = ghb_dict_get_int(ud->settings, "single_title");
- else
- title_id = 0;
- // ghb_do_scan replaces "scan_source" key in dict, so we must
- // be finished with sourcename before calling ghb_do_scan
- // since the memory it references will be freed
- if (strcmp(sourcename, filename) != 0)
- {
- ghb_dict_set_string(ud->prefs, "default_source", filename);
- ghb_pref_save(ud->prefs, "default_source");
- ghb_dvd_set_current(filename, ud);
- }
- ghb_do_scan(ud, filename, title_id, TRUE);
- g_free(filename);
- }
- }
+ gtk_widget_set_visible(w1, (mux->format & HB_MUX_MASK_MP4));
+ gtk_widget_set_visible(w2, (mux->format & HB_MUX_MASK_MP4));
+ gtk_widget_set_visible(w3, (mux->format & HB_MUX_MASK_MP4) &&
+ (enc == HB_VCODEC_X264_8BIT));
}
-#if 0
-G_MODULE_EXPORT void
-source_button_clicked_cb(GtkButton *button, signal_user_data_t *ud)
-{
- ghb_status_t status;
- ghb_get_status(&status);
- if (status.scan.state & GHB_STATE_SCANNING)
- {
- ghb_backend_scan_stop();
- }
- else
- {
- do_source_dialog(FALSE, ud);
- }
-}
-#else
-G_MODULE_EXPORT void
-source_action_cb(GSimpleAction *action, GVariant *param,
- signal_user_data_t *ud)
+static void
+adjustment_configure(
+ GtkAdjustment *adj,
+ double val,
+ double min, double max,
+ double step, double page, double page_sz)
{
- ghb_status_t status;
- ghb_get_status(&status);
- if (status.scan.state & GHB_STATE_SCANNING)
- {
- ghb_backend_scan_stop();
- }
- else
- {
- do_source_dialog(FALSE, ud);
- }
+ gtk_adjustment_configure(adj, val, min, max, step, page, page_sz);
}
-#endif
-G_MODULE_EXPORT void
-single_title_action_cb(GSimpleAction *action, GVariant * param,
- signal_user_data_t *ud)
+static void
+spin_configure(signal_user_data_t *ud, char *name, double val, double min, double max)
{
- do_source_dialog(TRUE, ud);
-}
+ GtkSpinButton *spin;
+ GtkAdjustment *adj;
+ double step, page, page_sz;
-G_MODULE_EXPORT void
-dvd_source_activate_cb(GtkWidget *widget, signal_user_data_t *ud)
-{
- const gchar *filename;
- const gchar *sourcename;
+ spin = GTK_SPIN_BUTTON(GHB_WIDGET(ud->builder, name));
- // ghb_do_scan replaces "scan_source" key in dict, so we must
- // be finished with sourcename before calling ghb_do_scan
- // since the memory it references will be freed
- sourcename = ghb_dict_get_string(ud->globals, "scan_source");
- filename = gtk_buildable_get_name(GTK_BUILDABLE(widget));
- if (strcmp(sourcename, filename) != 0)
- {
- ghb_dict_set_string(ud->prefs, "default_source", filename);
- ghb_pref_save(ud->prefs, "default_source");
- ghb_dvd_set_current(filename, ud);
- }
- ghb_do_scan(ud, filename, 0, TRUE);
+ adj = gtk_spin_button_get_adjustment(spin);
+ step = gtk_adjustment_get_step_increment(adj);
+ page = gtk_adjustment_get_page_increment(adj);
+ page_sz = gtk_adjustment_get_page_size(adj);
+
+ adjustment_configure(adj, val, min, max, step, page, page_sz);
}
void
-ghb_update_destination_extension(signal_user_data_t *ud)
+ghb_scale_configure(
+ signal_user_data_t *ud,
+ char *name,
+ double val, double min, double max,
+ double step, double page,
+ int digits, gboolean inverted)
{
- static gchar *containers[] = {".mkv", ".mp4", ".m4v", ".error", NULL};
- gchar *filename;
- const gchar *extension;
- gint ii;
- GtkEntry *entry;
- static gboolean busy = FALSE;
+ GtkScale *scale;
+ GtkAdjustment *adj;
+ double page_sz;
- g_debug("ghb_update_destination_extension ()");
- // Since this function modifies the thing that triggers it's
- // invocation, check to see if busy to prevent accidental infinite
- // recursion.
- if (busy)
- return;
- busy = TRUE;
- extension = get_extension(ud, ud->settings);
- entry = GTK_ENTRY(GHB_WIDGET(ud->builder, "dest_file"));
- filename = g_strdup(gtk_entry_get_text(entry));
- for (ii = 0; containers[ii] != NULL; ii++)
+ scale = GTK_SCALE(GHB_WIDGET(ud->builder, name));
+
+ adj = gtk_range_get_adjustment(GTK_RANGE(scale));
+ page_sz = gtk_adjustment_get_page_size(adj);
+
+ adjustment_configure(adj, val, min, max, step, page, page_sz);
+
+ gtk_scale_set_digits(scale, digits);
+ gtk_range_set_inverted(GTK_RANGE(scale), inverted);
+}
+
+void
+ghb_set_widget_ranges(signal_user_data_t *ud, GhbValue *settings)
+{
+ int title_id, titleindex;
+ const hb_title_t * title;
+ double val;
+
+ title_id = ghb_dict_get_int(settings, "title");
+ title = ghb_lookup_title(title_id, &titleindex);
+
+ // Reconfigure the UI combo boxes
+ ghb_update_ui_combo_box(ud, "AudioTrack", title, FALSE);
+ ghb_update_ui_combo_box(ud, "SubtitleTrack", title, FALSE);
+
+ if (title != NULL)
{
- if (g_str_has_suffix(filename, containers[ii]))
+
+ // Set the limits of cropping. hb_set_anamorphic_size crashes if
+ // you pass it a cropped width or height == 0.
+ gint vbound, hbound;
+ vbound = title->geometry.height;
+ hbound = title->geometry.width;
+
+ val = ghb_dict_get_int(ud->settings, "PictureTopCrop");
+ spin_configure(ud, "PictureTopCrop", val, 0, vbound);
+ val = ghb_dict_get_int(ud->settings, "PictureBottomCrop");
+ spin_configure(ud, "PictureBottomCrop", val, 0, vbound);
+ val = ghb_dict_get_int(ud->settings, "PictureLeftCrop");
+ spin_configure(ud, "PictureLeftCrop", val, 0, hbound);
+ val = ghb_dict_get_int(ud->settings, "PictureRightCrop");
+ spin_configure(ud, "PictureRightCrop", val, 0, hbound);
+
+ gint duration = title->duration / 90000;
+
+ if (ghb_settings_combo_int(ud->settings, "PtoPType") == 0)
{
- gchar *pos;
- gchar *new_name;
+ gint num_chapters = hb_list_count(title->list_chapter);
- pos = g_strrstr( filename, "." );
- if (pos == NULL)
- {
- // No period? shouldn't happen
- break;
- }
- *pos = 0;
- if (strcmp(extension, &pos[1]) == 0)
- {
- // Extension is already correct
- break;
- }
- new_name = g_strjoin(".", filename, extension, NULL);
- ghb_ui_update(ud, "dest_file", ghb_string_value(new_name));
- g_free(new_name);
- break;
+ val = ghb_dict_get_int(ud->settings, "start_point");
+ spin_configure(ud, "start_point", val, 1, num_chapters);
+ val = ghb_dict_get_int(ud->settings, "end_point");
+ spin_configure(ud, "end_point", val, 1, num_chapters);
+ }
+ else if (ghb_settings_combo_int(ud->settings, "PtoPType") == 1)
+ {
+ val = ghb_dict_get_int(ud->settings, "start_point");
+ spin_configure(ud, "start_point", val, 0, duration * 2 - 1);
+ val = ghb_dict_get_int(ud->settings, "end_point");
+ spin_configure(ud, "end_point", val, 0, duration * 2);
+ }
+ else if (ghb_settings_combo_int(ud->settings, "PtoPType") == 2)
+ {
+ gdouble max_frames;
+ max_frames = (gdouble)duration *
+ title->vrate.num / title->vrate.den;
+
+ val = ghb_dict_get_int(ud->settings, "start_point");
+ spin_configure(ud, "start_point", val, 1, max_frames * 2);
+ val = ghb_dict_get_int(ud->settings, "end_point");
+ spin_configure(ud, "end_point", val, 1, max_frames * 2);
}
+
+ val = ghb_dict_get_int(ud->settings, "angle");
+ spin_configure(ud, "angle", val, 1, title->angle_count);
}
- g_free(filename);
- busy = FALSE;
+
+ float vqmin, vqmax, step, page;
+ int inverted, digits;
+
+ ghb_vquality_range(ud, &vqmin, &vqmax, &step, &page, &digits, &inverted);
+ val = ghb_dict_get_double(ud->settings, "VideoQualitySlider");
+ ghb_scale_configure(ud, "VideoQualitySlider", val, vqmin, vqmax,
+ step, page, digits, inverted);
}
static void
-destination_select_title(GtkEntry *entry)
+check_chapter_markers(signal_user_data_t *ud)
{
- const gchar *dest;
+ GtkWidget *widget;
gint start, end;
- dest = gtk_entry_get_text(entry);
- for (end = strlen(dest)-1; end > 0; end--)
+ if (ghb_settings_combo_int(ud->settings, "PtoPType") == 0)
{
- if (dest[end] == '.')
- {
- break;
- }
+ start = ghb_dict_get_int(ud->settings, "start_point");
+ end = ghb_dict_get_int(ud->settings, "end_point");
+ widget = GHB_WIDGET (ud->builder, "ChapterMarkers");
+ gtk_widget_set_sensitive(widget, end > start);
}
- for (start = end; start >= 0; start--)
+}
+
+void
+ghb_load_settings(signal_user_data_t * ud)
+{
+ const char * fullname;
+ int type;
+ gboolean preset_modified;
+ static gboolean busy = FALSE;
+
+ if (busy)
+ return;
+ busy = TRUE;
+
+ fullname = ghb_dict_get_string(ud->settings, "PresetFullName");
+ type = ghb_dict_get_int(ud->settings, "Type");
+ preset_modified = ghb_dict_get_bool(ud->settings, "preset_modified");
+ if (preset_modified)
{
- if (dest[start] == G_DIR_SEPARATOR)
- {
- start++;
- break;
- }
+ ghb_clear_presets_selection(ud);
+ ghb_preset_menu_button_refresh(ud, fullname, type);
}
- if (start < 0) start = 0;
- if (start < end)
+ else
{
- gtk_editable_select_region(GTK_EDITABLE(entry), start, end);
+ ghb_dict_set_bool(ud->settings, "preset_reload", TRUE);
+ ghb_select_preset(ud, fullname, type);
+ ghb_dict_set_bool(ud->settings, "preset_reload", FALSE);
}
+
+ busy = FALSE;
+
+ ghb_load_post_settings(ud);
}
-G_MODULE_EXPORT gboolean
-destination_grab_cb(
- GtkEntry *entry,
- signal_user_data_t *ud)
+void
+ghb_load_post_settings(signal_user_data_t * ud)
{
- destination_select_title(entry);
- return FALSE;
-}
+ static gboolean busy = FALSE;
+ if (busy)
+ return;
+ busy = TRUE;
-static gboolean update_default_destination = FALSE;
+ ud->dont_clear_presets = TRUE;
+ ud->scale_busy = TRUE;
-G_MODULE_EXPORT void
-dest_dir_set_cb(GtkFileChooserButton *dest_chooser, signal_user_data_t *ud)
-{
- const gchar *dest_file, *dest_dir;
- gchar *dest;
+ ghb_set_widget_ranges(ud, ud->settings);
+ ghb_check_all_depencencies(ud);
+ ghb_show_container_options(ud);
+ check_chapter_markers(ud);
- g_debug("dest_dir_set_cb ()");
- ghb_widget_to_setting(ud->settings, (GtkWidget*)dest_chooser);
- dest_file = ghb_dict_get_string(ud->settings, "dest_file");
- dest_dir = ghb_dict_get_string(ud->settings, "dest_dir");
- dest = g_strdup_printf("%s" G_DIR_SEPARATOR_S "%s", dest_dir, dest_file);
- ghb_dict_set_string(ud->settings, "destination", dest);
- GhbValue *dest_dict = ghb_get_job_dest_settings(ud->settings);
- ghb_dict_set_string(dest_dict, "File", dest);
- g_free(dest);
- update_default_destination = TRUE;
+ ghb_clear_audio_selection(ud->builder);
+ ghb_clear_subtitle_selection(ud->builder);
+ ghb_settings_to_ui(ud, ud->settings);
+ ghb_audio_defaults_to_ui(ud);
+ ghb_subtitle_defaults_to_ui(ud);
+ ghb_audio_list_refresh_all(ud);
+ ghb_subtitle_list_refresh_all(ud);
+ ghb_chapter_list_refresh_all(ud);
+ update_title_duration(ud);
+ ghb_update_title_info(ud);
+
+ ud->dont_clear_presets = FALSE;
+ ud->scale_busy = FALSE;
+ busy = FALSE;
+
+ ghb_picture_settings_deps(ud);
}
-G_MODULE_EXPORT void
-dest_file_changed_cb(GtkEntry *entry, signal_user_data_t *ud)
+static void
+show_scan_progress(signal_user_data_t *ud)
{
- const gchar *dest_file, *dest_dir;
- gchar *dest;
+ GtkWidget * widget;
+ GtkProgressBar * progress;
+ GtkLabel * label;
+
+ widget = GHB_WIDGET(ud->builder, "SourceInfoBox");
+ gtk_widget_hide(widget);
+
+ widget = GHB_WIDGET(ud->builder, "SourceScanBox");
+ gtk_widget_show(widget);
+
+ progress = GTK_PROGRESS_BAR(GHB_WIDGET(ud->builder, "scan_prog"));
+ gtk_progress_bar_set_fraction(progress, 0);
+
+ label = GTK_LABEL(GHB_WIDGET(ud->builder, "source_scan_label"));
+ gtk_label_set_text( label, _("Scanning ...") );
- g_debug("dest_file_changed_cb ()");
- ghb_update_destination_extension(ud);
- ghb_widget_to_setting(ud->settings, (GtkWidget*)entry);
- // This signal goes off with ever keystroke, so I'm putting this
- // update on the timer.
- dest_file = ghb_dict_get_string(ud->settings, "dest_file");
- dest_dir = ghb_dict_get_string(ud->settings, "dest_dir");
- dest = g_strdup_printf("%s" G_DIR_SEPARATOR_S "%s", dest_dir, dest_file);
- ghb_dict_set_string(ud->settings, "destination", dest);
- GhbValue *dest_dict = ghb_get_job_dest_settings(ud->settings);
- ghb_dict_set_string(dest_dict, "File", dest);
- g_free(dest);
- update_default_destination = TRUE;
}
-G_MODULE_EXPORT void
-destination_action_cb(GSimpleAction *action, GVariant *param,
- signal_user_data_t *ud)
+static void
+hide_scan_progress(signal_user_data_t *ud)
{
- GtkWidget *dialog;
- GtkEntry *entry;
- const gchar *destname;
- gchar *basename;
- GtkWindow *hb_window;
+ GtkWidget * widget;
+ GtkProgressBar * progress;
- hb_window = GTK_WINDOW(GHB_WIDGET(ud->builder, "hb_window"));
- destname = ghb_dict_get_string(ud->settings, "destination");
- dialog = gtk_file_chooser_dialog_new("Choose Destination",
- hb_window,
- GTK_FILE_CHOOSER_ACTION_SAVE,
- GHB_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
- GHB_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
- NULL);
- gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(dialog), destname);
- basename = g_path_get_basename(destname);
- gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(dialog), basename);
- g_free(basename);
- if (gtk_dialog_run(GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT)
- {
- char *filename, *dirname;
- GtkFileChooser *dest_chooser;
+ progress = GTK_PROGRESS_BAR(GHB_WIDGET(ud->builder, "scan_prog"));
+ gtk_progress_bar_set_fraction(progress, 1.0);
- filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
- basename = g_path_get_basename(filename);
- dirname = g_path_get_dirname(filename);
- entry = (GtkEntry*)GHB_WIDGET(ud->builder, "dest_file");
- gtk_entry_set_text(entry, basename);
- dest_chooser = GTK_FILE_CHOOSER(GHB_WIDGET(ud->builder, "dest_dir"));
- gtk_file_chooser_set_filename(dest_chooser, dirname);
- g_free (dirname);
- g_free (basename);
- g_free (filename);
- }
- gtk_widget_destroy(dialog);
+ widget = GHB_WIDGET(ud->builder, "SourceScanBox");
+ gtk_widget_hide(widget);
+
+ widget = GHB_WIDGET(ud->builder, "SourceInfoBox");
+ gtk_widget_show(widget);
}
-G_MODULE_EXPORT gboolean
-window_destroy_event_cb(GtkWidget *widget, GdkEvent *event, signal_user_data_t *ud)
+static void
+start_scan(
+ signal_user_data_t *ud,
+ const gchar *path,
+ gint title_id,
+ gint preview_count)
{
- g_debug("window_destroy_event_cb ()");
- ghb_hb_cleanup(FALSE);
- prune_logs(ud);
- g_application_quit(G_APPLICATION(ud->app));
+ GtkWidget *widget;
+ ghb_status_t status;
+
+ ghb_get_status(&status);
+ if (status.scan.state != GHB_STATE_IDLE)
+ return;
+
+ widget = GHB_WIDGET(ud->builder, "sourcetoolbutton");
+ gtk_tool_button_set_icon_name(GTK_TOOL_BUTTON(widget), "hb-stop");
+ gtk_tool_button_set_label(GTK_TOOL_BUTTON(widget), _("Stop\nScan"));
+ gtk_tool_item_set_tooltip_text(GTK_TOOL_ITEM(widget), _("Stop Scan"));
+
+ widget = GHB_WIDGET(ud->builder, "source_open");
+ gtk_widget_set_sensitive(widget, FALSE);
+ widget = GHB_WIDGET(ud->builder, "source_title_open");
+ gtk_widget_set_sensitive(widget, FALSE);
+ ghb_backend_scan(path, title_id, preview_count,
+ 90000L * ghb_dict_get_int(ud->prefs, "MinTitleDuration"));
+}
+
+gboolean
+ghb_idle_scan(signal_user_data_t *ud)
+{
+ gchar *path;
+ // ghb_do_scan replaces "scan_source" key in dict, so we must
+ // make a copy of the string.
+ path = g_strdup(ghb_dict_get_string(ud->globals, "scan_source"));
+ ghb_do_scan(ud, path, 0, TRUE);
+ g_free(path);
return FALSE;
}
-G_MODULE_EXPORT gboolean
-window_delete_event_cb(GtkWidget *widget, GdkEvent *event, signal_user_data_t *ud)
+extern GhbValue *ghb_queue_edit_settings;
+static gchar *last_scan_file = NULL;
+
+void
+ghb_do_scan(
+ signal_user_data_t *ud,
+ const gchar *filename,
+ gint title_id,
+ gboolean force)
{
- gint state = ghb_get_queue_state();
- g_debug("window_delete_event_cb ()");
- if (state & (GHB_STATE_WORKING|GHB_STATE_SEARCHING))
+ int titleindex;
+ const hb_title_t *title;
+
+ (void)title; // Silence "unused variable" warning
+
+ g_debug("ghb_do_scan()");
+ if (!force && last_scan_file != NULL &&
+ strcmp(last_scan_file, filename) == 0)
{
- if (ghb_cancel_encode2(ud, _("Closing HandBrake will terminate encoding.\n")))
+ if (ghb_queue_edit_settings != NULL)
{
- ghb_hb_cleanup(FALSE);
+ title_id = ghb_dict_get_int(ghb_queue_edit_settings, "title");
+ title = ghb_lookup_title(title_id, &titleindex);
+ ghb_array_replace(ud->settings_array, titleindex,
+ ghb_queue_edit_settings);
+ ud->settings = ghb_queue_edit_settings;
+ ghb_load_settings(ud);
+ ghb_queue_edit_settings = NULL;
+ }
+ else
+ {
+ title = ghb_lookup_title(title_id, &titleindex);
+ load_all_titles(ud, titleindex);
+ }
+ return;
+ }
+ if (last_scan_file != NULL)
+ g_free(last_scan_file);
+ last_scan_file = NULL;
+ if (filename != NULL)
+ {
+ last_scan_file = g_strdup(filename);
+ ghb_dict_set_string(ud->globals, "scan_source", filename);
+ if (update_source_label(ud, filename))
+ {
+ const gchar *path;
+ gint preview_count;
+
+ show_scan_progress(ud);
+ path = ghb_dict_get_string(ud->globals, "scan_source");
prune_logs(ud);
- g_application_quit(G_APPLICATION(ud->app));
- return FALSE;
+
+ preview_count = ghb_dict_get_int(ud->prefs, "preview_count");
+ start_scan(ud, path, title_id, preview_count);
+ }
+ else
+ {
+ // TODO: error dialog
}
- return TRUE;
}
- ghb_hb_cleanup(FALSE);
- prune_logs(ud);
- g_application_quit(G_APPLICATION(ud->app));
- return FALSE;
}
static void
-update_acodec(signal_user_data_t *ud)
+do_source_dialog(gboolean single, signal_user_data_t *ud)
{
- ghb_audio_list_refresh_all(ud);
- ghb_grey_combo_options(ud);
-}
+ GtkWidget *dialog;
+ const gchar *sourcename;
+ gint response;
-G_MODULE_EXPORT void
-container_changed_cb(GtkWidget *widget, signal_user_data_t *ud)
-{
- g_debug("container_changed_cb ()");
- ghb_widget_to_setting(ud->settings, widget);
- const char * mux_id = ghb_dict_get_string(ud->settings, "FileFormat");
- GhbValue *dest_dict = ghb_get_job_dest_settings(ud->settings);
- ghb_dict_set_string(dest_dict, "Mux", mux_id);
+ g_debug("source_browse_clicked_cb ()");
+ sourcename = ghb_dict_get_string(ud->globals, "scan_source");
+ GtkWidget *widget;
+ widget = GHB_WIDGET(ud->builder, "single_title_box");
+ if (single)
+ gtk_widget_show(widget);
+ else
+ gtk_widget_hide(widget);
+ dialog = GHB_WIDGET(ud->builder, "source_dialog");
+ source_dialog_extra_widgets(ud, dialog);
- const hb_container_t *mux = ghb_lookup_container_by_name(mux_id);
- if (!(mux->format & HB_MUX_MASK_MP4))
+ gtk_widget_show(dialog);
+ gtk_file_chooser_select_filename(GTK_FILE_CHOOSER(dialog), sourcename);
+
+ response = gtk_dialog_run(GTK_DIALOG (dialog));
+ gtk_widget_hide(dialog);
+ if (response == GTK_RESPONSE_NO)
{
- ghb_ui_update(ud, "AlignAVStart", ghb_boolean_value(FALSE));
- }
+ gchar *filename;
- ghb_check_dependency(ud, widget, NULL);
- ghb_show_container_options(ud);
- update_acodec(ud);
- ghb_update_destination_extension(ud);
- ghb_clear_presets_selection(ud);
- ghb_live_reset(ud);
- ghb_subtitle_prune(ud);
- ghb_subtitle_list_refresh_all(ud);
- ghb_audio_list_refresh_selected(ud);
+ filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
+ if (filename != NULL)
+ {
+ gint title_id;
+
+ if (single)
+ title_id = ghb_dict_get_int(ud->settings, "single_title");
+ else
+ title_id = 0;
+ // ghb_do_scan replaces "scan_source" key in dict, so we must
+ // be finished with sourcename before calling ghb_do_scan
+ // since the memory it references will be freed
+ if (strcmp(sourcename, filename) != 0)
+ {
+ ghb_dict_set_string(ud->prefs, "default_source", filename);
+ ghb_pref_save(ud->prefs, "default_source");
+ ghb_dvd_set_current(filename, ud);
+ }
+ ghb_do_scan(ud, filename, title_id, TRUE);
+ g_free(filename);
+ }
+ }
}
-static gchar*
-get_aspect_string(gint aspect_n, gint aspect_d)
+#if 0
+G_MODULE_EXPORT void
+source_button_clicked_cb(GtkButton *button, signal_user_data_t *ud)
{
- gchar *aspect;
-
- if (aspect_d < 10)
+ ghb_status_t status;
+ ghb_get_status(&status);
+ if (status.scan.state & GHB_STATE_SCANNING)
{
- aspect = g_strdup_printf("%d:%d", aspect_n, aspect_d);
+ ghb_backend_scan_stop();
}
else
{
- gdouble aspect_nf = (gdouble)aspect_n / aspect_d;
- aspect = g_strdup_printf("%.2f:1", aspect_nf);
+ do_source_dialog(FALSE, ud);
}
- return aspect;
}
-
-static gchar*
-get_rate_string(gint rate_num, gint rate_den)
+#else
+G_MODULE_EXPORT void
+source_action_cb(GSimpleAction *action, GVariant *param,
+ signal_user_data_t *ud)
{
- gdouble rate_f = (gdouble)rate_num / rate_den;
- gchar *rate_s;
-
- rate_s = g_strdup_printf("%.6g", rate_f);
- return rate_s;
+ ghb_status_t status;
+ ghb_get_status(&status);
+ if (status.scan.state & GHB_STATE_SCANNING)
+ {
+ ghb_backend_scan_stop();
+ }
+ else
+ {
+ do_source_dialog(FALSE, ud);
+ }
}
+#endif
-static void
-update_aspect_info(signal_user_data_t *ud)
+G_MODULE_EXPORT void
+single_title_action_cb(GSimpleAction *action, GVariant * param,
+ signal_user_data_t *ud)
{
+ do_source_dialog(TRUE, ud);
}
-static void
-update_crop_info(signal_user_data_t *ud)
+G_MODULE_EXPORT void
+dvd_source_activate_cb(GtkWidget *widget, signal_user_data_t *ud)
{
- GtkWidget *widget;
- gchar *text;
- gint width, height, crop[4] = {0,};
- gint title_id, titleindex;
- const hb_title_t *title;
+ const gchar *filename;
+ const gchar *sourcename;
- title_id = ghb_dict_get_int(ud->settings, "title");
- title = ghb_lookup_title(title_id, &titleindex);
- if (title != NULL)
+ // ghb_do_scan replaces "scan_source" key in dict, so we must
+ // be finished with sourcename before calling ghb_do_scan
+ // since the memory it references will be freed
+ sourcename = ghb_dict_get_string(ud->globals, "scan_source");
+ filename = gtk_buildable_get_name(GTK_BUILDABLE(widget));
+ if (strcmp(sourcename, filename) != 0)
{
- crop[0] = ghb_dict_get_int(ud->settings, "PictureTopCrop");
- crop[1] = ghb_dict_get_int(ud->settings, "PictureBottomCrop");
- crop[2] = ghb_dict_get_int(ud->settings, "PictureLeftCrop");
- crop[3] = ghb_dict_get_int(ud->settings, "PictureRightCrop");
- width = title->geometry.width - crop[2] - crop[3];
- height = title->geometry.height - crop[0] - crop[1];
- text = g_strdup_printf ("%d x %d", width, height);
- widget = GHB_WIDGET(ud->builder, "crop_dimensions2");
- gtk_label_set_text(GTK_LABEL(widget), text);
- g_free(text);
+ ghb_dict_set_string(ud->prefs, "default_source", filename);
+ ghb_pref_save(ud->prefs, "default_source");
+ ghb_dvd_set_current(filename, ud);
}
-}
-
-static void
-update_scale_info(signal_user_data_t *ud)
-{
+ ghb_do_scan(ud, filename, 0, TRUE);
}
void
-ghb_update_title_info(signal_user_data_t *ud)
+ghb_update_destination_extension(signal_user_data_t *ud)
{
- GtkWidget * widget;
- gchar * text;
- gchar * aspect;
- gchar * rate;
- int title_id, titleindex;
- int audio_count, subtitle_count;
- const hb_title_t * title;
- const hb_geometry_t * geo;
- gint aspect_n, aspect_d;
+ static gchar *containers[] = {".mkv", ".mp4", ".m4v", ".error", NULL};
+ gchar *filename;
+ const gchar *extension;
+ gint ii;
+ GtkEntry *entry;
+ static gboolean busy = FALSE;
- title_id = ghb_dict_get_int(ud->settings, "title");
- title = ghb_lookup_title(title_id, &titleindex);
- if (title == NULL)
+ g_debug("ghb_update_destination_extension ()");
+ // Since this function modifies the thing that triggers it's
+ // invocation, check to see if busy to prevent accidental infinite
+ // recursion.
+ if (busy)
return;
+ busy = TRUE;
+ extension = get_extension(ud, ud->settings);
+ entry = GTK_ENTRY(GHB_WIDGET(ud->builder, "dest_file"));
+ filename = g_strdup(gtk_entry_get_text(entry));
+ for (ii = 0; containers[ii] != NULL; ii++)
+ {
+ if (g_str_has_suffix(filename, containers[ii]))
+ {
+ gchar *pos;
+ gchar *new_name;
- update_title_duration(ud);
+ pos = g_strrstr( filename, "." );
+ if (pos == NULL)
+ {
+ // No period? shouldn't happen
+ break;
+ }
+ *pos = 0;
+ if (strcmp(extension, &pos[1]) == 0)
+ {
+ // Extension is already correct
+ break;
+ }
+ new_name = g_strjoin(".", filename, extension, NULL);
+ ghb_ui_update(ud, "dest_file", ghb_string_value(new_name));
+ g_free(new_name);
+ break;
+ }
+ }
+ g_free(filename);
+ busy = FALSE;
+}
- geo = &title->geometry;
- hb_reduce(&aspect_n, &aspect_d, geo->width * geo->par.num,
- geo->height * geo->par.den);
- aspect = get_aspect_string(aspect_n, aspect_d);
- rate = get_rate_string(title->vrate.num, title->vrate.den);
- audio_count = hb_list_count(title->list_audio);
- subtitle_count = hb_list_count(title->list_subtitle);
+static void
+destination_select_title(GtkEntry *entry)
+{
+ const gchar *dest;
+ gint start, end;
- text = g_strdup_printf(
- ", %dx%d (%dx%d), %s, %s FPS, %d Audio Track%s, %d Subtitle Track%s",
- geo->width, geo->height,
- geo->width * geo->par.num / geo->par.den, geo->height,
- aspect, rate,
- audio_count, audio_count == 1 ? "" : "s",
- subtitle_count, subtitle_count == 1 ? "" : "s");
+ dest = gtk_entry_get_text(entry);
+ for (end = strlen(dest)-1; end > 0; end--)
+ {
+ if (dest[end] == '.')
+ {
+ break;
+ }
+ }
+ for (start = end; start >= 0; start--)
+ {
+ if (dest[start] == G_DIR_SEPARATOR)
+ {
+ start++;
+ break;
+ }
+ }
+ if (start < 0) start = 0;
+ if (start < end)
+ {
+ gtk_editable_select_region(GTK_EDITABLE(entry), start, end);
+ }
+}
- widget = GHB_WIDGET(ud->builder, "source_info_label");
- gtk_label_set_text(GTK_LABEL(widget), text);
- free(text);
- free(aspect);
- free(rate);
+G_MODULE_EXPORT gboolean
+destination_grab_cb(
+ GtkEntry *entry,
+ signal_user_data_t *ud)
+{
+ destination_select_title(entry);
+ return FALSE;
+}
- ghb_update_display_aspect_label(ud);
+static gboolean update_default_destination = FALSE;
- update_crop_info(ud);
- update_aspect_info(ud);
- update_scale_info(ud);
+G_MODULE_EXPORT void
+dest_dir_set_cb(GtkFileChooserButton *dest_chooser, signal_user_data_t *ud)
+{
+ const gchar *dest_file, *dest_dir;
+ gchar *dest;
+
+ g_debug("dest_dir_set_cb ()");
+ ghb_widget_to_setting(ud->settings, (GtkWidget*)dest_chooser);
+ dest_file = ghb_dict_get_string(ud->settings, "dest_file");
+ dest_dir = ghb_dict_get_string(ud->settings, "dest_dir");
+ dest = g_strdup_printf("%s" G_DIR_SEPARATOR_S "%s", dest_dir, dest_file);
+ ghb_dict_set_string(ud->settings, "destination", dest);
+ GhbValue *dest_dict = ghb_get_job_dest_settings(ud->settings);
+ ghb_dict_set_string(dest_dict, "File", dest);
+ g_free(dest);
+ update_default_destination = TRUE;
}
-static void update_meta(GhbValue *settings, const char *name, const char *val)
+G_MODULE_EXPORT void
+dest_file_changed_cb(GtkEntry *entry, signal_user_data_t *ud)
{
- GhbValue *metadata = ghb_get_job_metadata_settings(settings);
+ const gchar *dest_file, *dest_dir;
+ gchar *dest;
- if (val == NULL)
- ghb_dict_remove(metadata, name);
- else
- ghb_dict_set_string(metadata, name, val);
+ g_debug("dest_file_changed_cb ()");
+ ghb_update_destination_extension(ud);
+ ghb_widget_to_setting(ud->settings, (GtkWidget*)entry);
+ // This signal goes off with ever keystroke, so I'm putting this
+ // update on the timer.
+ dest_file = ghb_dict_get_string(ud->settings, "dest_file");
+ dest_dir = ghb_dict_get_string(ud->settings, "dest_dir");
+ dest = g_strdup_printf("%s" G_DIR_SEPARATOR_S "%s", dest_dir, dest_file);
+ ghb_dict_set_string(ud->settings, "destination", dest);
+ GhbValue *dest_dict = ghb_get_job_dest_settings(ud->settings);
+ ghb_dict_set_string(dest_dict, "File", dest);
+ g_free(dest);
+ update_default_destination = TRUE;
}
-void
-ghb_update_summary_info(signal_user_data_t *ud)
+G_MODULE_EXPORT void
+destination_action_cb(GSimpleAction *action, GVariant *param,
+ signal_user_data_t *ud)
{
- GString * str;
- char * text;
- int title_id;
- GtkWidget * widget;
- GhbValue * titleDict;
+ GtkWidget *dialog;
+ GtkEntry *entry;
+ const gchar *destname;
+ gchar *basename;
+ GtkWindow *hb_window;
- title_id = ghb_dict_get_int(ud->settings, "title");
- titleDict = ghb_get_title_dict(title_id);
- if (titleDict == NULL)
+ hb_window = GTK_WINDOW(GHB_WIDGET(ud->builder, "hb_window"));
+ destname = ghb_dict_get_string(ud->settings, "destination");
+ dialog = gtk_file_chooser_dialog_new("Choose Destination",
+ hb_window,
+ GTK_FILE_CHOOSER_ACTION_SAVE,
+ GHB_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+ GHB_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
+ NULL);
+ gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(dialog), destname);
+ basename = g_path_get_basename(destname);
+ gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(dialog), basename);
+ g_free(basename);
+ if (gtk_dialog_run(GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT)
{
- // No title, clear summary
- widget = GHB_WIDGET(ud->builder, "tracks_summary");
- gtk_label_set_text(GTK_LABEL(widget), "");
- widget = GHB_WIDGET(ud->builder, "filters_summary");
- gtk_label_set_text(GTK_LABEL(widget), "");
- widget = GHB_WIDGET(ud->builder, "dimensions_summary");
- gtk_label_set_text(GTK_LABEL(widget), "--");
- widget = GHB_WIDGET(ud->builder, "preview_button_image");
- gtk_image_set_from_icon_name(GTK_IMAGE(widget), "hb-icon", 128);
- return;
+ char *filename, *dirname;
+ GtkFileChooser *dest_chooser;
+
+ filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
+ basename = g_path_get_basename(filename);
+ dirname = g_path_get_dirname(filename);
+ entry = (GtkEntry*)GHB_WIDGET(ud->builder, "dest_file");
+ gtk_entry_set_text(entry, basename);
+ dest_chooser = GTK_FILE_CHOOSER(GHB_WIDGET(ud->builder, "dest_dir"));
+ gtk_file_chooser_set_filename(dest_chooser, dirname);
+ g_free (dirname);
+ g_free (basename);
+ g_free (filename);
+ }
+ gtk_widget_destroy(dialog);
+}
+
+G_MODULE_EXPORT gboolean
+window_destroy_event_cb(GtkWidget *widget, GdkEvent *event, signal_user_data_t *ud)
+{
+ g_debug("window_destroy_event_cb ()");
+ ghb_hb_cleanup(FALSE);
+ prune_logs(ud);
+ g_application_quit(G_APPLICATION(ud->app));
+ return FALSE;
+}
+
+G_MODULE_EXPORT gboolean
+window_delete_event_cb(GtkWidget *widget, GdkEvent *event, signal_user_data_t *ud)
+{
+ gint state = ghb_get_queue_state();
+ g_debug("window_delete_event_cb ()");
+ if (state & (GHB_STATE_WORKING|GHB_STATE_SEARCHING))
+ {
+ if (ghb_cancel_encode2(ud, _("Closing HandBrake will terminate encoding.\n")))
+ {
+ ghb_hb_cleanup(FALSE);
+ prune_logs(ud);
+ g_application_quit(G_APPLICATION(ud->app));
+ return FALSE;
+ }
+ return TRUE;
+ }
+ ghb_hb_cleanup(FALSE);
+ prune_logs(ud);
+ g_application_quit(G_APPLICATION(ud->app));
+ return FALSE;
+}
+
+static void
+update_acodec(signal_user_data_t *ud)
+{
+ ghb_audio_list_refresh_all(ud);
+ ghb_grey_combo_options(ud);
+}
+
+G_MODULE_EXPORT void
+container_changed_cb(GtkWidget *widget, signal_user_data_t *ud)
+{
+ g_debug("container_changed_cb ()");
+ ghb_widget_to_setting(ud->settings, widget);
+ const char * mux_id = ghb_dict_get_string(ud->settings, "FileFormat");
+ GhbValue *dest_dict = ghb_get_job_dest_settings(ud->settings);
+ ghb_dict_set_string(dest_dict, "Mux", mux_id);
+
+ const hb_container_t *mux = ghb_lookup_container_by_name(mux_id);
+ if (!(mux->format & HB_MUX_MASK_MP4))
+ {
+ ghb_ui_update(ud, "AlignAVStart", ghb_boolean_value(FALSE));
+ }
+
+ ghb_check_dependency(ud, widget, NULL);
+ ghb_show_container_options(ud);
+ update_acodec(ud);
+ ghb_update_destination_extension(ud);
+ ghb_clear_presets_selection(ud);
+ ghb_live_reset(ud);
+ ghb_subtitle_prune(ud);
+ ghb_subtitle_list_refresh_all(ud);
+ ghb_audio_list_refresh_selected(ud);
+}
+
+static gchar*
+get_aspect_string(gint aspect_n, gint aspect_d)
+{
+ gchar *aspect;
+
+ if (aspect_d < 10)
+ {
+ aspect = g_strdup_printf("%d:%d", aspect_n, aspect_d);
+ }
+ else
+ {
+ gdouble aspect_nf = (gdouble)aspect_n / aspect_d;
+ aspect = g_strdup_printf("%.2f:1", aspect_nf);
+ }
+ return aspect;
+}
+
+static gchar*
+get_rate_string(gint rate_num, gint rate_den)
+{
+ gdouble rate_f = (gdouble)rate_num / rate_den;
+ gchar *rate_s;
+
+ rate_s = g_strdup_printf("%.6g", rate_f);
+ return rate_s;
+}
+
+static void
+update_aspect_info(signal_user_data_t *ud)
+{
+}
+
+static void
+update_crop_info(signal_user_data_t *ud)
+{
+ GtkWidget *widget;
+ gchar *text;
+ gint width, height, crop[4] = {0,};
+ gint title_id, titleindex;
+ const hb_title_t *title;
+
+ title_id = ghb_dict_get_int(ud->settings, "title");
+ title = ghb_lookup_title(title_id, &titleindex);
+ if (title != NULL)
+ {
+ crop[0] = ghb_dict_get_int(ud->settings, "PictureTopCrop");
+ crop[1] = ghb_dict_get_int(ud->settings, "PictureBottomCrop");
+ crop[2] = ghb_dict_get_int(ud->settings, "PictureLeftCrop");
+ crop[3] = ghb_dict_get_int(ud->settings, "PictureRightCrop");
+ width = title->geometry.width - crop[2] - crop[3];
+ height = title->geometry.height - crop[0] - crop[1];
+ text = g_strdup_printf ("%d x %d", width, height);
+ widget = GHB_WIDGET(ud->builder, "crop_dimensions2");
+ gtk_label_set_text(GTK_LABEL(widget), text);
+ g_free(text);
+ }
+}
+
+static void
+update_scale_info(signal_user_data_t *ud)
+{
+}
+
+void
+ghb_update_title_info(signal_user_data_t *ud)
+{
+ GtkWidget * widget;
+ gchar * text;
+ gchar * aspect;
+ gchar * rate;
+ int title_id, titleindex;
+ int audio_count, subtitle_count;
+ const hb_title_t * title;
+ const hb_geometry_t * geo;
+ gint aspect_n, aspect_d;
+
+ title_id = ghb_dict_get_int(ud->settings, "title");
+ title = ghb_lookup_title(title_id, &titleindex);
+ if (title == NULL)
+ return;
+
+ update_title_duration(ud);
+
+ geo = &title->geometry;
+ hb_reduce(&aspect_n, &aspect_d, geo->width * geo->par.num,
+ geo->height * geo->par.den);
+ aspect = get_aspect_string(aspect_n, aspect_d);
+ rate = get_rate_string(title->vrate.num, title->vrate.den);
+ audio_count = hb_list_count(title->list_audio);
+ subtitle_count = hb_list_count(title->list_subtitle);
+
+ text = g_strdup_printf(
+ ", %dx%d (%dx%d), %s, %s FPS, %d Audio Track%s, %d Subtitle Track%s",
+ geo->width, geo->height,
+ geo->width * geo->par.num / geo->par.den, geo->height,
+ aspect, rate,
+ audio_count, audio_count == 1 ? "" : "s",
+ subtitle_count, subtitle_count == 1 ? "" : "s");
+
+ widget = GHB_WIDGET(ud->builder, "source_info_label");
+ gtk_label_set_text(GTK_LABEL(widget), text);
+ free(text);
+ free(aspect);
+ free(rate);
+
+ ghb_update_display_aspect_label(ud);
+
+ update_crop_info(ud);
+ update_aspect_info(ud);
+ update_scale_info(ud);
+}
+
+static void update_meta(GhbValue *settings, const char *name, const char *val)
+{
+ GhbValue *metadata = ghb_get_job_metadata_settings(settings);
+
+ if (val == NULL)
+ ghb_dict_remove(metadata, name);
+ else
+ ghb_dict_set_string(metadata, name, val);
+}
+
+void
+ghb_update_summary_info(signal_user_data_t *ud)
+{
+ GString * str;
+ char * text;
+ int title_id;
+ GtkWidget * widget;
+ GhbValue * titleDict;
+
+ title_id = ghb_dict_get_int(ud->settings, "title");
+ titleDict = ghb_get_title_dict(title_id);
+ if (titleDict == NULL)
+ {
+ // No title, clear summary
+ widget = GHB_WIDGET(ud->builder, "tracks_summary");
+ gtk_label_set_text(GTK_LABEL(widget), "");
+ widget = GHB_WIDGET(ud->builder, "filters_summary");
+ gtk_label_set_text(GTK_LABEL(widget), "");
+ widget = GHB_WIDGET(ud->builder, "dimensions_summary");
+ gtk_label_set_text(GTK_LABEL(widget), "--");
+ widget = GHB_WIDGET(ud->builder, "preview_button_image");
+ gtk_image_set_from_icon_name(GTK_IMAGE(widget), "hb-icon", 128);
+ return;
}
// Video Track
status = ghb_dict_get_int(uiDict, "job_status");
if (status == GHB_QUEUE_PENDING)
{
- ghb_inhibit_gsm(ud);
+ ghb_inhibit_suspend(ud);
+printf("inhibited %d\n", suspend_inhibited);
submit_job(ud, queueDict);
ghb_update_pending(ud);
}
}
// Nothing pending
- ghb_uninhibit_gsm();
+ ghb_uninhibit_suspend(ud);
ghb_notify_done(ud);
ghb_update_pending(ud);
gtk_widget_hide(progress);
}
else
{
- ghb_uninhibit_gsm();
+ ghb_uninhibit_suspend(ud);
gtk_widget_hide(GTK_WIDGET(progress));
ghb_dict_set_bool(ud->globals, "SkipDiskFreeCheck", FALSE);
}
gtk_progress_bar_set_fraction (live_progress, status.live.progress);
g_free(status_str);
}
- if (status.live.state & GHB_STATE_WORKDONE)
- {
- switch( status.live.error )
- {
- case GHB_ERROR_NONE:
- {
- ghb_live_encode_done(ud, TRUE);
- } break;
- default:
- {
- ghb_live_encode_done(ud, FALSE);
- } break;
- }
- ghb_clear_live_state(GHB_STATE_WORKDONE);
- }
-}
-
-G_MODULE_EXPORT gboolean
-ghb_timer_cb(gpointer data)
-{
- signal_user_data_t *ud = (signal_user_data_t*)data;
-
- ghb_live_preview_progress(ud);
- ghb_backend_events(ud);
- if (update_default_destination)
- {
- const gchar *dest, *def_dest;
- gchar *dest_dir;
- dest = ghb_dict_get_string(ud->settings, "destination");
- dest_dir = g_path_get_dirname(dest);
- def_dest = ghb_dict_get_string(ud->prefs, "destination_dir");
- if (strcmp(dest_dir, def_dest) != 0)
- {
- ghb_dict_set_string(ud->prefs, "destination_dir", dest_dir);
- ghb_pref_save(ud->prefs, "destination_dir");
- }
- g_free(dest_dir);
- update_default_destination = FALSE;
- }
- if (update_preview)
- {
- g_debug("Updating preview\n");
- ghb_set_preview_image (ud);
- update_preview = FALSE;
- }
-
-#if !defined(_NO_UPDATE_CHECK)
- if (!appcast_busy)
- {
- const gchar *updates;
- updates = ghb_dict_get_string(ud->prefs, "check_updates");
- gint64 duration = 0;
- if (strcmp(updates, "daily") == 0)
- duration = 60 * 60 * 24;
- else if (strcmp(updates, "weekly") == 0)
- duration = 60 * 60 * 24 * 7;
- else if (strcmp(updates, "monthly") == 0)
- duration = 60 * 60 * 24 * 7;
-
- if (duration != 0)
- {
- gint64 last;
- time_t tt;
-
- last = ghb_dict_get_int(ud->prefs, "last_update_check");
- time(&tt);
- if (last + duration < tt)
- {
- ghb_dict_set_int(ud->prefs,
- "last_update_check", tt);
- ghb_pref_save(ud->prefs, "last_update_check");
- GHB_THREAD_NEW("Update Check", (GThreadFunc)ghb_check_update, ud);
- }
- }
- }
-#endif
- return TRUE;
-}
-
-gboolean scroll_at_bottom(signal_user_data_t *ud, const char *scroll)
-{
- GtkScrolledWindow *window;
- GtkAdjustment *adj;
- double val, upper, ps;
-
- window = GTK_SCROLLED_WINDOW(GHB_WIDGET(ud->builder, scroll));
- adj = gtk_scrolled_window_get_vadjustment(window);
- val = gtk_adjustment_get_value(adj);
- upper = gtk_adjustment_get_upper(adj);
- ps = gtk_adjustment_get_page_size(adj);
- return val >= upper - ps;
-}
-
-G_MODULE_EXPORT gboolean
-activity_scroll_to_bottom(signal_user_data_t *ud)
-{
- GtkScrolledWindow *window;
- GtkAdjustment *adj;
- double upper, ps;
-
- window = GTK_SCROLLED_WINDOW(GHB_WIDGET(ud->builder, "activity_scroll"));
- adj = gtk_scrolled_window_get_vadjustment(window);
- upper = gtk_adjustment_get_upper(adj);
- ps = gtk_adjustment_get_page_size(adj);
- gtk_adjustment_set_value(adj, upper - ps);
- return FALSE;
-}
-
-G_MODULE_EXPORT gboolean
-ghb_log_cb(GIOChannel *source, GIOCondition cond, gpointer data)
-{
- gchar *text = NULL;
- gsize length, outlength;
- GtkTextView *textview;
- GtkTextBuffer *buffer;
- GtkTextIter iter;
- GError *gerror = NULL;
- GIOStatus status;
-
- signal_user_data_t *ud = (signal_user_data_t*)data;
-
- status = g_io_channel_read_line (source, &text, &length, NULL, &gerror);
- // Trim nils from end of text, they cause g_io_channel_write_chars to
- // fail with an assertion that aborts
- while (length > 0 && text[length-1] == 0)
- length--;
- if (text != NULL && length > 0)
- {
- gboolean bottom = FALSE;
- gchar *utf8_text;
-
- bottom = scroll_at_bottom(ud, "activity_scroll");
- textview = GTK_TEXT_VIEW(GHB_WIDGET (ud->builder, "activity_view"));
- buffer = gtk_text_view_get_buffer (textview);
- gtk_text_buffer_get_end_iter(buffer, &iter);
- // Assume logging is in current locale
- utf8_text = g_locale_to_utf8(text, -1, NULL, &length, NULL);
- if (utf8_text != NULL)
- {
- gtk_text_buffer_insert(buffer, &iter, utf8_text, -1);
- if (bottom)
- {
- static guint scroll_tok = 0;
- GSource *source = NULL;
- if (scroll_tok > 0)
- source = g_main_context_find_source_by_id(NULL, scroll_tok);
- if (source != NULL)
- {
- g_source_remove(scroll_tok);
- }
- scroll_tok = g_idle_add((GSourceFunc)activity_scroll_to_bottom,
- ud);
- }
-#if defined(_WIN32)
- gsize one = 1;
- utf8_text[length-1] = '\r';
-#endif
- g_io_channel_write_chars (ud->activity_log, utf8_text,
- length, &outlength, NULL);
-#if defined(_WIN32)
- g_io_channel_write_chars (ud->activity_log, "\n",
- one, &one, NULL);
-#endif
- g_io_channel_flush(ud->activity_log, NULL);
- if (ud->job_activity_log)
- {
- g_io_channel_write_chars (ud->job_activity_log, utf8_text,
- length, &outlength, NULL);
-#if defined(_WIN32)
- g_io_channel_write_chars (ud->activity_log, "\n",
- one, &outlength, NULL);
-#endif
- g_io_channel_flush(ud->job_activity_log, NULL);
- }
- g_free(utf8_text);
- }
- }
- if (text != NULL)
- g_free(text);
-
- if (status != G_IO_STATUS_NORMAL)
- {
- // This should never happen, but if it does I would get into an
- // infinite loop. Returning false removes this callback.
- g_warning("Error while reading activity from pipe");
- if (gerror != NULL)
- {
- g_warning("%s", gerror->message);
- g_error_free (gerror);
- }
- return FALSE;
- }
- if (gerror != NULL)
- g_error_free (gerror);
- return TRUE;
-}
-
-static void
-update_activity_labels(signal_user_data_t *ud, gboolean active)
-{
- GtkToolButton *button;
-
- button = GTK_TOOL_BUTTON(GHB_WIDGET(ud->builder, "show_activity"));
-
- if (!active)
- {
- gtk_tool_button_set_label(button, "Show\nActivity");
- }
- else
- {
- gtk_tool_button_set_label(button, "Hide\nActivity");
- }
-}
-
-G_MODULE_EXPORT void
-show_activity_action_cb(GSimpleAction *action, GVariant *value,
- signal_user_data_t *ud)
-{
- GtkWidget * activity_window;
- gboolean state = g_variant_get_boolean(value);
-
- g_simple_action_set_state(action, value);
- activity_window = GHB_WIDGET(ud->builder, "activity_window");
- gtk_widget_set_visible(activity_window, state);
- update_activity_labels(ud, state);
-}
-
-G_MODULE_EXPORT gboolean
-presets_window_delete_cb(GtkWidget *xwidget, GdkEvent *event, signal_user_data_t *ud)
-{
- GSimpleAction * action;
- GVariant * state = g_variant_new_boolean(FALSE);
-
- action = G_SIMPLE_ACTION(g_action_map_lookup_action(
- G_ACTION_MAP(ud->app), "show-presets"));
- g_action_change_state(G_ACTION(action), state);
- return TRUE;
-}
-
-G_MODULE_EXPORT gboolean
-activity_window_delete_cb(GtkWidget *xwidget, GdkEvent *event, signal_user_data_t *ud)
-{
- gtk_widget_set_visible(xwidget, FALSE);
- GtkWidget *widget = GHB_WIDGET (ud->builder, "show_activity");
- gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(widget), FALSE);
- return TRUE;
-}
-
-void
-ghb_log(gchar *log, ...)
-{
- va_list args;
- time_t _now;
- struct tm *now;
- gchar fmt[362];
-
- _now = time(NULL);
- now = localtime( &_now );
- snprintf(fmt, 362, "[%02d:%02d:%02d] gtkgui: %s\n",
- now->tm_hour, now->tm_min, now->tm_sec, log);
- va_start(args, log);
- vfprintf(stderr, fmt, args);
- va_end(args);
-}
-
-static void
-browse_url(const gchar *url)
-{
-#if defined(_WIN32)
- ShellExecute(NULL, "open", url, NULL, NULL, SW_SHOWNORMAL);
-#else
- gboolean result;
- char *argv[] =
- {"xdg-open",NULL,NULL,NULL};
- argv[1] = (gchar*)url;
- result = g_spawn_async(NULL, argv, NULL, G_SPAWN_SEARCH_PATH, NULL,
- NULL, NULL, NULL);
- if (result) return;
-
- argv[0] = "gnome-open";
- result = g_spawn_async(NULL, argv, NULL, G_SPAWN_SEARCH_PATH, NULL,
- NULL, NULL, NULL);
- if (result) return;
-
- argv[0] = "kfmclient";
- argv[1] = "exec";
- argv[2] = (gchar*)url;
- result = g_spawn_async(NULL, argv, NULL, G_SPAWN_SEARCH_PATH, NULL,
- NULL, NULL, NULL);
- if (result) return;
-
- argv[0] = "firefox";
- argv[1] = (gchar*)url;
- argv[2] = NULL;
- result = g_spawn_async(NULL, argv, NULL, G_SPAWN_SEARCH_PATH, NULL,
- NULL, NULL, NULL);
-#endif
-}
-
-G_MODULE_EXPORT void
-about_action_cb(GSimpleAction *action, GVariant *param, signal_user_data_t *ud)
-{
- GtkWidget *widget = GHB_WIDGET (ud->builder, "hb_about");
- gchar *ver;
-
- ver = g_strdup_printf("%s (%s)", HB_PROJECT_VERSION, HB_PROJECT_BUILD_ARCH);
- gtk_about_dialog_set_version(GTK_ABOUT_DIALOG(widget), ver);
- g_free(ver);
- gtk_about_dialog_set_website(GTK_ABOUT_DIALOG(widget),
- HB_PROJECT_URL_WEBSITE);
- gtk_about_dialog_set_website_label(GTK_ABOUT_DIALOG(widget),
- HB_PROJECT_URL_WEBSITE);
- gtk_widget_show (widget);
-}
-
-#define HB_DOCS "https://handbrake.fr/docs/"
-
-G_MODULE_EXPORT void
-guide_action_cb(GSimpleAction *action, GVariant *param, signal_user_data_t *ud)
-{
- browse_url(HB_DOCS);
-}
-
-G_MODULE_EXPORT void
-hb_about_response_cb(GtkWidget *widget, gint response, signal_user_data_t *ud)
-{
- gtk_widget_hide (widget);
-}
-
-static void
-update_queue_labels(signal_user_data_t *ud)
-{
- GtkToolButton *button;
- gboolean active;
- gint pending;
- const gchar *show_hide;
- gchar *str;
-
- button = GTK_TOOL_BUTTON(GHB_WIDGET(ud->builder, "show_queue"));
- active = gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(button));
- pending = queue_pending_count(ud->queue);
-
- if (!active)
- {
- show_hide = _("Show\nQueue");
- }
- else
- {
- show_hide = _("Hide\nQueue");
- }
- if (pending > 0)
- {
- str = g_strdup_printf("%s (%d)", show_hide, pending);
- }
- else
+ if (status.live.state & GHB_STATE_WORKDONE)
{
- str = g_strdup_printf("%s", show_hide);
+ switch( status.live.error )
+ {
+ case GHB_ERROR_NONE:
+ {
+ ghb_live_encode_done(ud, TRUE);
+ } break;
+ default:
+ {
+ ghb_live_encode_done(ud, FALSE);
+ } break;
+ }
+ ghb_clear_live_state(GHB_STATE_WORKDONE);
}
- gtk_tool_button_set_label(button, str);
- g_free(str);
-}
-
-static void
-show_queue(signal_user_data_t *ud, gboolean show)
-{
- GtkWidget *tab;
- GtkStack *stack;
-
- stack = GTK_STACK(GHB_WIDGET(ud->builder, "QueueStack"));
- if (show)
- tab = GHB_WIDGET(ud->builder, "queue_tab");
- else
- tab = GHB_WIDGET(ud->builder, "settings_tab");
- gtk_stack_set_visible_child(stack, tab);
- update_queue_labels(ud);
-}
-
-G_MODULE_EXPORT void
-show_queue_action_cb(GSimpleAction *action, GVariant *value,
- signal_user_data_t *ud)
-{
- gboolean state = g_variant_get_boolean(value);
-
- g_simple_action_set_state(action, value);
- show_queue(ud, state);
}
-static void
-presets_window_set_visible(signal_user_data_t *ud, gboolean visible)
+G_MODULE_EXPORT gboolean
+ghb_timer_cb(gpointer data)
{
- GtkWidget * presets_window;
- GtkWidget * hb_window;
- int x, y;
+ signal_user_data_t *ud = (signal_user_data_t*)data;
- hb_window = GHB_WIDGET(ud->builder, "hb_window");
- if (!gtk_widget_is_visible(hb_window))
+ ghb_live_preview_progress(ud);
+ ghb_backend_events(ud);
+ if (update_default_destination)
{
- return;
+ const gchar *dest, *def_dest;
+ gchar *dest_dir;
+ dest = ghb_dict_get_string(ud->settings, "destination");
+ dest_dir = g_path_get_dirname(dest);
+ def_dest = ghb_dict_get_string(ud->prefs, "destination_dir");
+ if (strcmp(dest_dir, def_dest) != 0)
+ {
+ ghb_dict_set_string(ud->prefs, "destination_dir", dest_dir);
+ ghb_pref_save(ud->prefs, "destination_dir");
+ }
+ g_free(dest_dir);
+ update_default_destination = FALSE;
}
-
- int w, h;
- w = ghb_dict_get_int(ud->prefs, "presets_window_width");
- h = ghb_dict_get_int(ud->prefs, "presets_window_height");
-
- presets_window = GHB_WIDGET(ud->builder, "presets_window");
- if (w > 200 && h > 200)
+ if (update_preview)
{
- gtk_window_resize(GTK_WINDOW(presets_window), w, h);
+ g_debug("Updating preview\n");
+ ghb_set_preview_image (ud);
+ update_preview = FALSE;
}
- gtk_widget_set_visible(presets_window, visible);
- if (visible)
+
+#if !defined(_NO_UPDATE_CHECK)
+ if (!appcast_busy)
{
- gtk_window_get_position(GTK_WINDOW(hb_window), &x, &y);
- x -= w + 10;
- if (x < 0)
+ const gchar *updates;
+ updates = ghb_dict_get_string(ud->prefs, "check_updates");
+ gint64 duration = 0;
+ if (strcmp(updates, "daily") == 0)
+ duration = 60 * 60 * 24;
+ else if (strcmp(updates, "weekly") == 0)
+ duration = 60 * 60 * 24 * 7;
+ else if (strcmp(updates, "monthly") == 0)
+ duration = 60 * 60 * 24 * 7;
+
+ if (duration != 0)
{
- gtk_window_move(GTK_WINDOW(hb_window), w + 10, y);
- x = 0;
+ gint64 last;
+ time_t tt;
+
+ last = ghb_dict_get_int(ud->prefs, "last_update_check");
+ time(&tt);
+ if (last + duration < tt)
+ {
+ ghb_dict_set_int(ud->prefs,
+ "last_update_check", tt);
+ ghb_pref_save(ud->prefs, "last_update_check");
+ GHB_THREAD_NEW("Update Check", (GThreadFunc)ghb_check_update, ud);
+ }
}
- gtk_window_move(GTK_WINDOW(presets_window), x, y);
}
+#endif
+ return TRUE;
}
-G_MODULE_EXPORT void
-show_presets_action_cb(GSimpleAction *action, GVariant *value,
- signal_user_data_t *ud)
+gboolean scroll_at_bottom(signal_user_data_t *ud, const char *scroll)
{
- gboolean state = g_variant_get_boolean(value);
+ GtkScrolledWindow *window;
+ GtkAdjustment *adj;
+ double val, upper, ps;
- g_simple_action_set_state(action, value);
- presets_window_set_visible(ud, state);
+ window = GTK_SCROLLED_WINDOW(GHB_WIDGET(ud->builder, scroll));
+ adj = gtk_scrolled_window_get_vadjustment(window);
+ val = gtk_adjustment_get_value(adj);
+ upper = gtk_adjustment_get_upper(adj);
+ ps = gtk_adjustment_get_page_size(adj);
+ return val >= upper - ps;
}
-static void
-chapter_refresh_list_row_ui(
- GtkTreeModel *tm,
- GtkTreeIter *ti,
- GhbValue *chapter_list,
- const hb_title_t *title,
- int index)
+G_MODULE_EXPORT gboolean
+activity_scroll_to_bottom(signal_user_data_t *ud)
{
- const gchar *chapter;
- gchar *s_duration, *s_start;
- gint hh, mm, ss;
- gint64 duration, start;
+ GtkScrolledWindow *window;
+ GtkAdjustment *adj;
+ double upper, ps;
- // Update row with settings data
- g_debug("Updating chapter row ui");
- chapter = ghb_dict_get_string(ghb_array_get(chapter_list, index), "Name");
- duration = ghb_get_chapter_duration(title, index) / 90000;
- break_duration(duration, &hh, &mm, &ss);
- s_duration = g_strdup_printf("%02d:%02d:%02d", hh, mm, ss);
- start = ghb_get_chapter_start(title, index) / 90000;
- break_duration(start, &hh, &mm, &ss);
- s_start = g_strdup_printf("%02d:%02d:%02d", hh, mm, ss);
- gtk_list_store_set(GTK_LIST_STORE(tm), ti,
- 0, index+1,
- 1, s_start,
- 2, s_duration,
- 3, chapter,
- 4, TRUE,
- -1);
- g_free(s_duration);
- g_free(s_start);
+ window = GTK_SCROLLED_WINDOW(GHB_WIDGET(ud->builder, "activity_scroll"));
+ adj = gtk_scrolled_window_get_vadjustment(window);
+ upper = gtk_adjustment_get_upper(adj);
+ ps = gtk_adjustment_get_page_size(adj);
+ gtk_adjustment_set_value(adj, upper - ps);
+ return FALSE;
}
-static void
-ghb_clear_chapter_list_ui(GtkBuilder *builder)
+G_MODULE_EXPORT gboolean
+ghb_log_cb(GIOChannel *source, GIOCondition cond, gpointer data)
{
- GtkTreeView *tv;
- GtkListStore *ts;
-
- tv = GTK_TREE_VIEW(GHB_WIDGET(builder, "chapters_list"));
- ts = GTK_LIST_STORE(gtk_tree_view_get_model(tv));
- gtk_list_store_clear(ts);
-}
+ gchar *text = NULL;
+ gsize length, outlength;
+ GtkTextView *textview;
+ GtkTextBuffer *buffer;
+ GtkTextIter iter;
+ GError *gerror = NULL;
+ GIOStatus status;
-static void
-chapter_refresh_list_ui(signal_user_data_t *ud)
-{
- GhbValue *chapter_list;
- gint ii, count, tm_count;
- GtkTreeView *tv;
- GtkTreeModel *tm;
- GtkTreeIter ti;
- int title_id, titleindex;
- const hb_title_t *title;
+ signal_user_data_t *ud = (signal_user_data_t*)data;
- tv = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "chapters_list"));
- tm = gtk_tree_view_get_model(tv);
+ status = g_io_channel_read_line (source, &text, &length, NULL, &gerror);
+ // Trim nils from end of text, they cause g_io_channel_write_chars to
+ // fail with an assertion that aborts
+ while (length > 0 && text[length-1] == 0)
+ length--;
+ if (text != NULL && length > 0)
+ {
+ gboolean bottom = FALSE;
+ gchar *utf8_text;
- tm_count = gtk_tree_model_iter_n_children(tm, NULL);
+ bottom = scroll_at_bottom(ud, "activity_scroll");
+ textview = GTK_TEXT_VIEW(GHB_WIDGET (ud->builder, "activity_view"));
+ buffer = gtk_text_view_get_buffer (textview);
+ gtk_text_buffer_get_end_iter(buffer, &iter);
+ // Assume logging is in current locale
+ utf8_text = g_locale_to_utf8(text, -1, NULL, &length, NULL);
+ if (utf8_text != NULL)
+ {
+ gtk_text_buffer_insert(buffer, &iter, utf8_text, -1);
+ if (bottom)
+ {
+ static guint scroll_tok = 0;
+ GSource *source = NULL;
+ if (scroll_tok > 0)
+ source = g_main_context_find_source_by_id(NULL, scroll_tok);
+ if (source != NULL)
+ {
+ g_source_remove(scroll_tok);
+ }
+ scroll_tok = g_idle_add((GSourceFunc)activity_scroll_to_bottom,
+ ud);
+ }
+#if defined(_WIN32)
+ gsize one = 1;
+ utf8_text[length-1] = '\r';
+#endif
+ g_io_channel_write_chars (ud->activity_log, utf8_text,
+ length, &outlength, NULL);
+#if defined(_WIN32)
+ g_io_channel_write_chars (ud->activity_log, "\n",
+ one, &one, NULL);
+#endif
+ g_io_channel_flush(ud->activity_log, NULL);
+ if (ud->job_activity_log)
+ {
+ g_io_channel_write_chars (ud->job_activity_log, utf8_text,
+ length, &outlength, NULL);
+#if defined(_WIN32)
+ g_io_channel_write_chars (ud->activity_log, "\n",
+ one, &outlength, NULL);
+#endif
+ g_io_channel_flush(ud->job_activity_log, NULL);
+ }
+ g_free(utf8_text);
+ }
+ }
+ if (text != NULL)
+ g_free(text);
- title_id = ghb_dict_get_int(ud->settings, "title");
- title = ghb_lookup_title(title_id, &titleindex);
- chapter_list = ghb_get_job_chapter_list(ud->settings);
- count = ghb_array_len(chapter_list);
- if (count != tm_count)
+ if (status != G_IO_STATUS_NORMAL)
{
- ghb_clear_chapter_list_ui(ud->builder);
- for (ii = 0; ii < count; ii++)
+ // This should never happen, but if it does I would get into an
+ // infinite loop. Returning false removes this callback.
+ g_warning("Error while reading activity from pipe");
+ if (gerror != NULL)
{
- gtk_list_store_append(GTK_LIST_STORE(tm), &ti);
+ g_warning("%s", gerror->message);
+ g_error_free (gerror);
}
+ return FALSE;
}
- for (ii = 0; ii < count; ii++)
- {
- gtk_tree_model_iter_nth_child(tm, &ti, NULL, ii);
- chapter_refresh_list_row_ui(tm, &ti, chapter_list, title, ii);
- }
+ if (gerror != NULL)
+ g_error_free (gerror);
+ return TRUE;
}
-void
-ghb_chapter_list_refresh_all(signal_user_data_t *ud)
+static void
+update_activity_labels(signal_user_data_t *ud, gboolean active)
{
- chapter_refresh_list_ui(ud);
-}
+ GtkToolButton *button;
-static gint chapter_edit_key = 0;
+ button = GTK_TOOL_BUTTON(GHB_WIDGET(ud->builder, "show_activity"));
-G_MODULE_EXPORT gboolean
-chapter_keypress_cb(
- GhbCellRendererText *cell,
- GdkEventKey *event,
- signal_user_data_t *ud)
-{
- chapter_edit_key = event->keyval;
- return FALSE;
+ if (!active)
+ {
+ gtk_tool_button_set_label(button, "Show\nActivity");
+ }
+ else
+ {
+ gtk_tool_button_set_label(button, "Hide\nActivity");
+ }
}
G_MODULE_EXPORT void
-chapter_edited_cb(
- GhbCellRendererText *cell,
- gchar *path,
- gchar *text,
- signal_user_data_t *ud)
+show_activity_action_cb(GSimpleAction *action, GVariant *value,
+ signal_user_data_t *ud)
{
- GtkTreePath *treepath;
- GtkListStore *store;
- GtkTreeView *treeview;
- GtkTreeIter iter;
- gint index;
- gint *pi;
- gint row;
-
- g_debug("chapter_edited_cb ()");
- g_debug("path (%s)", path);
- g_debug("text (%s)", text);
- treeview = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "chapters_list"));
- store = GTK_LIST_STORE(gtk_tree_view_get_model(treeview));
- treepath = gtk_tree_path_new_from_string (path);
- pi = gtk_tree_path_get_indices(treepath);
- row = pi[0];
- gtk_tree_model_get_iter(GTK_TREE_MODEL(store), &iter, treepath);
- gtk_list_store_set(store, &iter,
- 3, text,
- 4, TRUE,
- -1);
- gtk_tree_model_get(GTK_TREE_MODEL(store), &iter, 0, &index, -1);
-
- const GhbValue *chapters;
- GhbValue *chapter;
-
- chapters = ghb_get_job_chapter_list(ud->settings);
- chapter = ghb_array_get(chapters, index-1);
- ghb_dict_set_string(chapter, "Name", text);
- if ((chapter_edit_key == GDK_KEY_Return || chapter_edit_key == GDK_KEY_Down) &&
- gtk_tree_model_iter_next(GTK_TREE_MODEL(store), &iter))
- {
- GtkTreeViewColumn *column;
+ GtkWidget * activity_window;
+ gboolean state = g_variant_get_boolean(value);
- gtk_tree_path_next(treepath);
- // When a cell has been edited, I want to advance to the
- // next cell and start editing it automatically.
- // Unfortunately, we may not be in a state here where
- // editing is allowed. This happens when the user selects
- // a new cell with the mouse instead of just hitting enter.
- // Some kind of Gtk quirk. widget_editable==NULL assertion.
- // Editing is enabled again once the selection event has been
- // processed. So I'm queueing up a callback to be called
- // when things go idle. There, I will advance to the next
- // cell and initiate editing.
- //
- // Now, you might be asking why I don't catch the keypress
- // event and determine what action to take based on that.
- // The Gtk developers in their infinite wisdom have made the
- // actual GtkEdit widget being used a private member of
- // GtkCellRendererText, so it can not be accessed to hang a
- // signal handler off of. And they also do not propagate the
- // keypress signals in any other way. So that information is lost.
- //g_idle_add((GSourceFunc)next_cell, ud);
- //
- // Keeping the above comment for posterity.
- // I got industrious and made my own CellTextRendererText that
- // passes on the key-press-event. So now I have much better
- // control of this.
- column = gtk_tree_view_get_column(treeview, 3);
- gtk_tree_view_set_cursor(treeview, treepath, column, TRUE);
- }
- else if (chapter_edit_key == GDK_KEY_Up && row > 0)
- {
- GtkTreeViewColumn *column;
- gtk_tree_path_prev(treepath);
- column = gtk_tree_view_get_column(treeview, 3);
- gtk_tree_view_set_cursor(treeview, treepath, column, TRUE);
- }
- gtk_tree_path_free (treepath);
+ g_simple_action_set_state(action, value);
+ activity_window = GHB_WIDGET(ud->builder, "activity_window");
+ gtk_widget_set_visible(activity_window, state);
+ update_activity_labels(ud, state);
}
-void
-debug_log_handler(const gchar *domain, GLogLevelFlags flags, const gchar *msg, gpointer data)
+G_MODULE_EXPORT gboolean
+presets_window_delete_cb(GtkWidget *xwidget, GdkEvent *event, signal_user_data_t *ud)
{
- signal_user_data_t *ud = (signal_user_data_t*)data;
+ GSimpleAction * action;
+ GVariant * state = g_variant_new_boolean(FALSE);
- if (ud->debug)
- {
- printf("%s: %s\n", domain, msg);
- }
+ action = G_SIMPLE_ACTION(g_action_map_lookup_action(
+ G_ACTION_MAP(ud->app), "show-presets"));
+ g_action_change_state(G_ACTION(action), state);
+ return TRUE;
}
-void
-warn_log_handler(const gchar *domain, GLogLevelFlags flags, const gchar *msg, gpointer data)
+G_MODULE_EXPORT gboolean
+activity_window_delete_cb(GtkWidget *xwidget, GdkEvent *event, signal_user_data_t *ud)
{
- printf("%s: %s\n", domain, msg);
+ gtk_widget_set_visible(xwidget, FALSE);
+ GtkWidget *widget = GHB_WIDGET (ud->builder, "show_activity");
+ gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(widget), FALSE);
+ return TRUE;
}
void
-ghb_hbfd(signal_user_data_t *ud, gboolean hbfd)
+ghb_log(gchar *log, ...)
{
- GtkWidget *widget;
- g_debug("ghb_hbfd");
- widget = GHB_WIDGET(ud->builder, "queue_pause");
- gtk_widget_set_visible(widget, !hbfd);
- widget = GHB_WIDGET(ud->builder, "queue_add");
- gtk_widget_set_visible(widget, !hbfd);
- widget = GHB_WIDGET(ud->builder, "show_queue");
- gtk_widget_set_visible(widget, !hbfd);
- widget = GHB_WIDGET(ud->builder, "show_activity");
- gtk_widget_set_visible(widget, !hbfd);
-
- widget = GHB_WIDGET(ud->builder, "container_box");
- gtk_widget_set_visible(widget, !hbfd);
- widget = GHB_WIDGET(ud->builder, "SettingsStackSwitcher");
- gtk_widget_set_visible(widget, !hbfd);
- widget = GHB_WIDGET(ud->builder, "SettingsStack");
- gtk_widget_set_visible(widget, !hbfd);
- widget = GHB_WIDGET(ud->builder, "presets_save");
- gtk_widget_set_visible(widget, !hbfd);
- widget = GHB_WIDGET(ud->builder, "presets_remove");
- gtk_widget_set_visible(widget, !hbfd);
- widget = GHB_WIDGET (ud->builder, "hb_window");
- gtk_window_resize(GTK_WINDOW(widget), 16, 16);
+ va_list args;
+ time_t _now;
+ struct tm *now;
+ gchar fmt[362];
+ _now = time(NULL);
+ now = localtime( &_now );
+ snprintf(fmt, 362, "[%02d:%02d:%02d] gtkgui: %s\n",
+ now->tm_hour, now->tm_min, now->tm_sec, log);
+ va_start(args, log);
+ vfprintf(stderr, fmt, args);
+ va_end(args);
}
-G_MODULE_EXPORT void
-hbfd_action_cb(GSimpleAction *action, GVariant *value, signal_user_data_t *ud)
+static void
+browse_url(const gchar *url)
{
- gboolean state = g_variant_get_boolean(value);
+#if defined(_WIN32)
+ ShellExecute(NULL, "open", url, NULL, NULL, SW_SHOWNORMAL);
+#else
+ gboolean result;
+ char *argv[] =
+ {"xdg-open",NULL,NULL,NULL};
+ argv[1] = (gchar*)url;
+ result = g_spawn_async(NULL, argv, NULL, G_SPAWN_SEARCH_PATH, NULL,
+ NULL, NULL, NULL);
+ if (result) return;
- g_simple_action_set_state(action, value);
- ghb_dict_set(ud->prefs, "hbfd", ghb_boolean_value(state));
- ghb_hbfd(ud, state);
- ghb_pref_save(ud->prefs, "hbfd");
-}
+ argv[0] = "gnome-open";
+ result = g_spawn_async(NULL, argv, NULL, G_SPAWN_SEARCH_PATH, NULL,
+ NULL, NULL, NULL);
+ if (result) return;
-G_MODULE_EXPORT void
-advanced_video_changed_cb(GtkWidget *widget, signal_user_data_t *ud)
-{
- g_debug("advanced_video_changed_cb");
- ghb_widget_to_setting(ud->prefs, widget);
- const gchar *name = ghb_get_setting_key(widget);
- ghb_pref_set(ud->prefs, name);
- ghb_show_hide_advanced_video(ud);
+ argv[0] = "kfmclient";
+ argv[1] = "exec";
+ argv[2] = (gchar*)url;
+ result = g_spawn_async(NULL, argv, NULL, G_SPAWN_SEARCH_PATH, NULL,
+ NULL, NULL, NULL);
+ if (result) return;
+
+ argv[0] = "firefox";
+ argv[1] = (gchar*)url;
+ argv[2] = NULL;
+ result = g_spawn_async(NULL, argv, NULL, G_SPAWN_SEARCH_PATH, NULL,
+ NULL, NULL, NULL);
+#endif
}
G_MODULE_EXPORT void
-pref_changed_cb(GtkWidget *widget, signal_user_data_t *ud)
+about_action_cb(GSimpleAction *action, GVariant *param, signal_user_data_t *ud)
{
- ghb_widget_to_setting (ud->prefs, widget);
+ GtkWidget *widget = GHB_WIDGET (ud->builder, "hb_about");
+ gchar *ver;
- ghb_check_dependency(ud, widget, NULL);
- const gchar *name = ghb_get_setting_key(widget);
- ghb_pref_set(ud->prefs, name);
+ ver = g_strdup_printf("%s (%s)", HB_PROJECT_VERSION, HB_PROJECT_BUILD_ARCH);
+ gtk_about_dialog_set_version(GTK_ABOUT_DIALOG(widget), ver);
+ g_free(ver);
+ gtk_about_dialog_set_website(GTK_ABOUT_DIALOG(widget),
+ HB_PROJECT_URL_WEBSITE);
+ gtk_about_dialog_set_website_label(GTK_ABOUT_DIALOG(widget),
+ HB_PROJECT_URL_WEBSITE);
+ gtk_widget_show (widget);
}
+#define HB_DOCS "https://handbrake.fr/docs/"
+
G_MODULE_EXPORT void
-log_level_changed_cb(GtkWidget *widget, signal_user_data_t *ud)
+guide_action_cb(GSimpleAction *action, GVariant *param, signal_user_data_t *ud)
{
- pref_changed_cb(widget, ud);
- int level = ghb_dict_get_int(ud->prefs, "LoggingLevel");
- ghb_log_level_set(level);
+ browse_url(HB_DOCS);
}
G_MODULE_EXPORT void
-use_m4v_changed_cb(GtkWidget *widget, signal_user_data_t *ud)
+hb_about_response_cb(GtkWidget *widget, gint response, signal_user_data_t *ud)
{
- g_debug("use_m4v_changed_cb");
- ghb_widget_to_setting (ud->prefs, widget);
- ghb_check_dependency(ud, widget, NULL);
- const gchar *name = ghb_get_setting_key(widget);
- ghb_pref_set(ud->prefs, name);
- ghb_update_destination_extension(ud);
+ gtk_widget_hide (widget);
}
-G_MODULE_EXPORT void
-vqual_granularity_changed_cb(GtkWidget *widget, signal_user_data_t *ud)
+static void
+update_queue_labels(signal_user_data_t *ud)
{
- g_debug("vqual_granularity_changed_cb");
- ghb_widget_to_setting (ud->prefs, widget);
- ghb_check_dependency(ud, widget, NULL);
-
- const gchar *name = ghb_get_setting_key(widget);
- ghb_pref_set(ud->prefs, name);
+ GtkToolButton *button;
+ gboolean active;
+ gint pending;
+ const gchar *show_hide;
+ gchar *str;
- float val, vqmin, vqmax, step, page;
- int inverted, digits;
+ button = GTK_TOOL_BUTTON(GHB_WIDGET(ud->builder, "show_queue"));
+ active = gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(button));
+ pending = queue_pending_count(ud->queue);
- ghb_vquality_range(ud, &vqmin, &vqmax, &step, &page, &digits, &inverted);
- val = ghb_dict_get_double(ud->settings, "VideoQualitySlider");
- ghb_scale_configure(ud, "VideoQualitySlider", val, vqmin, vqmax,
- step, page, digits, inverted);
+ if (!active)
+ {
+ show_hide = _("Show\nQueue");
+ }
+ else
+ {
+ show_hide = _("Hide\nQueue");
+ }
+ if (pending > 0)
+ {
+ str = g_strdup_printf("%s (%d)", show_hide, pending);
+ }
+ else
+ {
+ str = g_strdup_printf("%s", show_hide);
+ }
+ gtk_tool_button_set_label(button, str);
+ g_free(str);
}
-G_MODULE_EXPORT void
-tweaks_changed_cb(GtkWidget *widget, signal_user_data_t *ud)
+static void
+show_queue(signal_user_data_t *ud, gboolean show)
{
- g_debug("tweaks_changed_cb");
- ghb_widget_to_setting (ud->prefs, widget);
- const gchar *name = ghb_get_setting_key(widget);
- ghb_pref_set(ud->prefs, name);
+ GtkWidget *tab;
+ GtkStack *stack;
+
+ stack = GTK_STACK(GHB_WIDGET(ud->builder, "QueueStack"));
+ if (show)
+ tab = GHB_WIDGET(ud->builder, "queue_tab");
+ else
+ tab = GHB_WIDGET(ud->builder, "settings_tab");
+ gtk_stack_set_visible_child(stack, tab);
+ update_queue_labels(ud);
}
G_MODULE_EXPORT void
-hbfd_feature_changed_cb(GtkWidget *widget, signal_user_data_t *ud)
+show_queue_action_cb(GSimpleAction *action, GVariant *value,
+ signal_user_data_t *ud)
{
- ghb_widget_to_setting (ud->prefs, widget);
- const gchar *name = ghb_get_setting_key(widget);
- ghb_pref_set(ud->prefs, name);
+ gboolean state = g_variant_get_boolean(value);
- gboolean hbfd = ghb_dict_get_bool(ud->prefs, "hbfd_feature");
- if (hbfd)
- {
- const GhbValue *val;
- val = ghb_dict_get_value(ud->prefs, "hbfd");
- ghb_ui_settings_update(ud, ud->prefs, "hbfd", val);
- }
- widget = GHB_WIDGET(ud->builder, "hbfd");
- gtk_widget_set_visible(widget, hbfd);
+ g_simple_action_set_state(action, value);
+ show_queue(ud, state);
}
-gboolean
-ghb_file_menu_add_dvd(signal_user_data_t *ud)
+static void
+presets_window_set_visible(signal_user_data_t *ud, gboolean visible)
{
- GList *link, *drives;
- static GList *dvd_items = NULL;
-
- g_debug("ghb_file_menu_add_dvd()");
- GtkMenu *menu = GTK_MENU(GHB_WIDGET(ud->builder, "file_submenu"));
+ GtkWidget * presets_window;
+ GtkWidget * hb_window;
+ int x, y;
- // Clear previous dvd items from list
- link = dvd_items;
- while (link != NULL)
+ hb_window = GHB_WIDGET(ud->builder, "hb_window");
+ if (!gtk_widget_is_visible(hb_window))
{
- GtkWidget * widget = GTK_WIDGET(link->data);
- // widget_destroy automatically removes widget from container.
- gtk_widget_destroy(widget);
- link = link->next;
+ return;
}
- g_list_free(dvd_items);
- dvd_items = NULL;
-
- int pos = 5;
- link = drives = dvd_device_list();
- if (drives != NULL)
- {
- GtkWidget *widget = gtk_separator_menu_item_new();
- dvd_items = g_list_append(dvd_items, (gpointer)widget);
- gtk_menu_shell_insert(GTK_MENU_SHELL(menu), widget, pos++);
- gtk_widget_set_visible(widget, TRUE);
+ int w, h;
+ w = ghb_dict_get_int(ud->prefs, "presets_window_width");
+ h = ghb_dict_get_int(ud->prefs, "presets_window_height");
- while (link != NULL)
+ presets_window = GHB_WIDGET(ud->builder, "presets_window");
+ if (w > 200 && h > 200)
+ {
+ gtk_window_resize(GTK_WINDOW(presets_window), w, h);
+ }
+ gtk_widget_set_visible(presets_window, visible);
+ if (visible)
+ {
+ gtk_window_get_position(GTK_WINDOW(hb_window), &x, &y);
+ x -= w + 10;
+ if (x < 0)
{
- GtkWidget *widget;
- gchar *drive = get_dvd_device_name(link->data);
- gchar *name = get_dvd_volume_name(link->data);
-
- widget = gtk_menu_item_new_with_label(name);
- gtk_buildable_set_name(GTK_BUILDABLE(widget), drive);
- gtk_widget_set_tooltip_text(widget, _("Scan this DVD source"));
-
- dvd_items = g_list_append(dvd_items, (gpointer)widget);
- gtk_menu_shell_insert(GTK_MENU_SHELL(menu), widget, pos++);
-
- gtk_widget_set_visible(widget, TRUE);
-
- // Connect signal to action (menu item)
- g_signal_connect(widget, "activate",
- (GCallback)dvd_source_activate_cb, ud);
- g_free(name);
- g_free(drive);
- free_drive(link->data);
- link = link->next;
+ gtk_window_move(GTK_WINDOW(hb_window), w + 10, y);
+ x = 0;
}
-
- g_list_free(drives);
+ gtk_window_move(GTK_WINDOW(presets_window), x, y);
}
-
- return FALSE;
}
-gboolean ghb_is_cd(GDrive *gd);
-
-static GList*
-dvd_device_list()
+G_MODULE_EXPORT void
+show_presets_action_cb(GSimpleAction *action, GVariant *value,
+ signal_user_data_t *ud)
{
- 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;
+ gboolean state = g_variant_get_boolean(value);
- gvm = g_volume_monitor_get ();
- drives = g_volume_monitor_get_connected_drives (gvm);
- link = drives;
- while (link != NULL)
- {
- GDrive *gd;
+ g_simple_action_set_state(action, value);
+ presets_window_set_visible(ud, state);
+}
- 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
+static void
+chapter_refresh_list_row_ui(
+ GtkTreeModel *tm,
+ GtkTreeIter *ti,
+ GhbValue *chapter_list,
+ const hb_title_t *title,
+ int index)
+{
+ const gchar *chapter;
+ gchar *s_duration, *s_start;
+ gint hh, mm, ss;
+ gint64 duration, start;
- return dvd_devices;
+ // Update row with settings data
+ g_debug("Updating chapter row ui");
+ chapter = ghb_dict_get_string(ghb_array_get(chapter_list, index), "Name");
+ duration = ghb_get_chapter_duration(title, index) / 90000;
+ break_duration(duration, &hh, &mm, &ss);
+ s_duration = g_strdup_printf("%02d:%02d:%02d", hh, mm, ss);
+ start = ghb_get_chapter_start(title, index) / 90000;
+ break_duration(start, &hh, &mm, &ss);
+ s_start = g_strdup_printf("%02d:%02d:%02d", hh, mm, ss);
+ gtk_list_store_set(GTK_LIST_STORE(tm), ti,
+ 0, index+1,
+ 1, s_start,
+ 2, s_duration,
+ 3, chapter,
+ 4, TRUE,
+ -1);
+ g_free(s_duration);
+ g_free(s_start);
}
-#if defined(__linux__) && defined(_HAVE_GUDEV)
-static GUdevClient *udev_ctx = NULL;
-#endif
+static void
+ghb_clear_chapter_list_ui(GtkBuilder *builder)
+{
+ GtkTreeView *tv;
+ GtkListStore *ts;
-gboolean
-ghb_is_cd(GDrive *gd)
+ tv = GTK_TREE_VIEW(GHB_WIDGET(builder, "chapters_list"));
+ ts = GTK_LIST_STORE(gtk_tree_view_get_model(tv));
+ gtk_list_store_clear(ts);
+}
+
+static void
+chapter_refresh_list_ui(signal_user_data_t *ud)
{
-#if defined(__linux__) && defined(_HAVE_GUDEV)
- gchar *device;
- GUdevDevice *udd;
+ GhbValue *chapter_list;
+ gint ii, count, tm_count;
+ GtkTreeView *tv;
+ GtkTreeModel *tm;
+ GtkTreeIter ti;
+ int title_id, titleindex;
+ const hb_title_t *title;
- if (udev_ctx == NULL)
- return FALSE;
+ tv = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "chapters_list"));
+ tm = gtk_tree_view_get_model(tv);
- device = g_drive_get_identifier(gd, G_VOLUME_IDENTIFIER_KIND_UNIX_DEVICE);
- if (device == NULL)
- return FALSE;
+ tm_count = gtk_tree_model_iter_n_children(tm, NULL);
- udd = g_udev_client_query_by_device_file(udev_ctx, device);
- if (udd == NULL)
+ title_id = ghb_dict_get_int(ud->settings, "title");
+ title = ghb_lookup_title(title_id, &titleindex);
+ chapter_list = ghb_get_job_chapter_list(ud->settings);
+ count = ghb_array_len(chapter_list);
+ if (count != tm_count)
{
- g_message("udev: Failed to lookup device %s", device);
- g_free(device);
- return FALSE;
+ ghb_clear_chapter_list_ui(ud->builder);
+ for (ii = 0; ii < count; ii++)
+ {
+ gtk_list_store_append(GTK_LIST_STORE(tm), &ti);
+ }
+ }
+ for (ii = 0; ii < count; ii++)
+ {
+ gtk_tree_model_iter_nth_child(tm, &ti, NULL, ii);
+ chapter_refresh_list_row_ui(tm, &ti, chapter_list, title, ii);
}
- g_free(device);
-
- gint val;
- val = g_udev_device_get_property_as_int(udd, "ID_CDROM_DVD");
- g_object_unref(udd);
- if (val == 1)
- return TRUE;
-
- return FALSE;
-#else
- return FALSE;
-#endif
}
void
-ghb_udev_init()
+ghb_chapter_list_refresh_all(signal_user_data_t *ud)
{
-#if defined(__linux__) && defined(_HAVE_GUDEV)
- udev_ctx = g_udev_client_new(NULL);
-#endif
+ chapter_refresh_list_ui(ud);
}
-#if defined(_WIN32)
-static void
-handle_media_change(const gchar *device, gboolean insert, signal_user_data_t *ud)
+static gint chapter_edit_key = 0;
+
+G_MODULE_EXPORT gboolean
+chapter_keypress_cb(
+ GhbCellRendererText *cell,
+ GdkEventKey *event,
+ signal_user_data_t *ud)
{
- guint dtype;
- static gint ins_count = 0;
- static gint rem_count = 0;
+ chapter_edit_key = event->keyval;
+ return FALSE;
+}
- // 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)
+G_MODULE_EXPORT void
+chapter_edited_cb(
+ GhbCellRendererText *cell,
+ gchar *path,
+ gchar *text,
+ signal_user_data_t *ud)
+{
+ GtkTreePath *treepath;
+ GtkListStore *store;
+ GtkTreeView *treeview;
+ GtkTreeIter iter;
+ gint index;
+ gint *pi;
+ gint row;
+
+ g_debug("chapter_edited_cb ()");
+ g_debug("path (%s)", path);
+ g_debug("text (%s)", text);
+ treeview = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "chapters_list"));
+ store = GTK_LIST_STORE(gtk_tree_view_get_model(treeview));
+ treepath = gtk_tree_path_new_from_string (path);
+ pi = gtk_tree_path_get_indices(treepath);
+ row = pi[0];
+ gtk_tree_model_get_iter(GTK_TREE_MODEL(store), &iter, treepath);
+ gtk_list_store_set(store, &iter,
+ 3, text,
+ 4, TRUE,
+ -1);
+ gtk_tree_model_get(GTK_TREE_MODEL(store), &iter, 0, &index, -1);
+
+ const GhbValue *chapters;
+ GhbValue *chapter;
+
+ chapters = ghb_get_job_chapter_list(ud->settings);
+ chapter = ghb_array_get(chapters, index-1);
+ ghb_dict_set_string(chapter, "Name", text);
+ if ((chapter_edit_key == GDK_KEY_Return || chapter_edit_key == GDK_KEY_Down) &&
+ gtk_tree_model_iter_next(GTK_TREE_MODEL(store), &iter))
{
- rem_count = 0;
- ins_count++;
- if (ins_count == 2)
- {
- GHB_THREAD_NEW("Cache Volume Names",
- (GThreadFunc)ghb_cache_volnames, ud);
- if (ghb_dict_get_bool(ud->prefs, "AutoScan") &&
- ud->current_dvd_device != NULL &&
- strcmp(device, ud->current_dvd_device) == 0)
- {
- show_scan_progress(ud);
- update_source_label(ud, device);
- gint preview_count;
- preview_count = ghb_dict_get_int(ud->prefs, "preview_count");
- ghb_dict_set_string(ud->globals, "scan_source", device);
- start_scan(ud, device, 0, preview_count);
- }
- }
+ GtkTreeViewColumn *column;
+
+ gtk_tree_path_next(treepath);
+ // When a cell has been edited, I want to advance to the
+ // next cell and start editing it automatically.
+ // Unfortunately, we may not be in a state here where
+ // editing is allowed. This happens when the user selects
+ // a new cell with the mouse instead of just hitting enter.
+ // Some kind of Gtk quirk. widget_editable==NULL assertion.
+ // Editing is enabled again once the selection event has been
+ // processed. So I'm queueing up a callback to be called
+ // when things go idle. There, I will advance to the next
+ // cell and initiate editing.
+ //
+ // Now, you might be asking why I don't catch the keypress
+ // event and determine what action to take based on that.
+ // The Gtk developers in their infinite wisdom have made the
+ // actual GtkEdit widget being used a private member of
+ // GtkCellRendererText, so it can not be accessed to hang a
+ // signal handler off of. And they also do not propagate the
+ // keypress signals in any other way. So that information is lost.
+ //g_idle_add((GSourceFunc)next_cell, ud);
+ //
+ // Keeping the above comment for posterity.
+ // I got industrious and made my own CellTextRendererText that
+ // passes on the key-press-event. So now I have much better
+ // control of this.
+ column = gtk_tree_view_get_column(treeview, 3);
+ gtk_tree_view_set_cursor(treeview, treepath, column, TRUE);
}
- else
+ else if (chapter_edit_key == GDK_KEY_Up && row > 0)
{
- ins_count = 0;
- rem_count++;
- if (rem_count == 2)
- {
- GHB_THREAD_NEW("Cache Volume Names",
- (GThreadFunc)ghb_cache_volnames, ud);
- if (ud->current_dvd_device != NULL &&
- strcmp(device, ud->current_dvd_device) == 0)
- {
- ghb_hb_cleanup(TRUE);
- prune_logs(ud);
- ghb_dict_set_string(ud->globals, "scan_source", "/dev/null");
- start_scan(ud, "/dev/null", 0, 1);
- }
- }
+ GtkTreeViewColumn *column;
+ gtk_tree_path_prev(treepath);
+ column = gtk_tree_view_get_column(treeview, 3);
+ gtk_tree_view_set_cursor(treeview, treepath, column, TRUE);
}
+ gtk_tree_path_free (treepath);
}
-static gchar
-FindDriveFromMask(ULONG unitmask)
+void
+debug_log_handler(const gchar *domain, GLogLevelFlags flags, const gchar *msg, gpointer data)
{
- gchar cc;
- for (cc = 0; cc < 26; cc++)
+ signal_user_data_t *ud = (signal_user_data_t*)data;
+
+ if (ud->debug)
{
- if (unitmask & 0x01)
- return 'A' + cc;
- unitmask >>= 1;
+ printf("%s: %s\n", domain, msg);
}
- return 0;
}
void
-wm_drive_changed(MSG *msg, signal_user_data_t *ud)
+warn_log_handler(const gchar *domain, GLogLevelFlags flags, const gchar *msg, gpointer data)
{
- 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;
+ printf("%s: %s\n", domain, msg);
+}
- case DBT_DEVICEREMOVECOMPLETE:
- {
- if (bch->dbch_devicetype == DBT_DEVTYP_VOLUME)
- {
- PDEV_BROADCAST_VOLUME bcv = (PDEV_BROADCAST_VOLUME)bch;
+void
+ghb_hbfd(signal_user_data_t *ud, gboolean hbfd)
+{
+ GtkWidget *widget;
+ g_debug("ghb_hbfd");
+ widget = GHB_WIDGET(ud->builder, "queue_pause");
+ gtk_widget_set_visible(widget, !hbfd);
+ widget = GHB_WIDGET(ud->builder, "queue_add");
+ gtk_widget_set_visible(widget, !hbfd);
+ widget = GHB_WIDGET(ud->builder, "show_queue");
+ gtk_widget_set_visible(widget, !hbfd);
+ widget = GHB_WIDGET(ud->builder, "show_activity");
+ gtk_widget_set_visible(widget, !hbfd);
- if (bcv->dbcv_flags & DBTF_MEDIA)
- {
- drive[0] = FindDriveFromMask(bcv->dbcv_unitmask);
- handle_media_change(drive, FALSE, ud);
- }
- }
- } break;
- default: ;
- }
-}
+ widget = GHB_WIDGET(ud->builder, "container_box");
+ gtk_widget_set_visible(widget, !hbfd);
+ widget = GHB_WIDGET(ud->builder, "SettingsStackSwitcher");
+ gtk_widget_set_visible(widget, !hbfd);
+ widget = GHB_WIDGET(ud->builder, "SettingsStack");
+ gtk_widget_set_visible(widget, !hbfd);
+ widget = GHB_WIDGET(ud->builder, "presets_save");
+ gtk_widget_set_visible(widget, !hbfd);
+ widget = GHB_WIDGET(ud->builder, "presets_remove");
+ gtk_widget_set_visible(widget, !hbfd);
+ widget = GHB_WIDGET (ud->builder, "hb_window");
+ gtk_window_resize(GTK_WINDOW(widget), 16, 16);
-#else
+}
G_MODULE_EXPORT void
-drive_changed_cb(GVolumeMonitor *gvm, GDrive *gd, signal_user_data_t *ud)
+hbfd_action_cb(GSimpleAction *action, GVariant *value, signal_user_data_t *ud)
{
- gchar *device;
- gint state;
-
- g_debug("drive_changed_cb()");
- GHB_THREAD_NEW("Cache Volume Names", (GThreadFunc)ghb_cache_volnames, ud);
+ gboolean state = g_variant_get_boolean(value);
- 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_dict_get_bool(ud->prefs, "AutoScan"))
- {
- show_scan_progress(ud);
- update_source_label(ud, device);
- gint preview_count;
- preview_count = ghb_dict_get_int(ud->prefs, "preview_count");
- ghb_dict_set_string(ud->globals, "scan_source", device);
- start_scan(ud, device, 0, preview_count);
- }
- }
- else
- {
- ghb_hb_cleanup(TRUE);
- prune_logs(ud);
- ghb_dict_set_string(ud->globals, "scan_source", "/dev/null");
- start_scan(ud, "/dev/null", 0, 1);
- }
+ g_simple_action_set_state(action, value);
+ ghb_dict_set(ud->prefs, "hbfd", ghb_boolean_value(state));
+ ghb_hbfd(ud, state);
+ ghb_pref_save(ud->prefs, "hbfd");
}
-#endif
-
-#if !defined(_WIN32)
-#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()
+G_MODULE_EXPORT void
+advanced_video_changed_cb(GtkWidget *widget, signal_user_data_t *ud)
{
- gboolean can_suspend = FALSE;
-#if !defined(_WIN32)
- DBusGConnection *conn;
- DBusGProxy *proxy;
- GError *error = NULL;
- gboolean res;
+ g_debug("advanced_video_changed_cb");
+ ghb_widget_to_setting(ud->prefs, widget);
+ const gchar *name = ghb_get_setting_key(widget);
+ ghb_pref_set(ud->prefs, name);
+ ghb_show_hide_advanced_video(ud);
+}
+G_MODULE_EXPORT void
+pref_changed_cb(GtkWidget *widget, signal_user_data_t *ud)
+{
+ ghb_widget_to_setting (ud->prefs, widget);
- 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;
+ ghb_check_dependency(ud, widget, NULL);
+ const gchar *name = ghb_get_setting_key(widget);
+ ghb_pref_set(ud->prefs, name);
}
-static void
-ghb_suspend_gpm()
+G_MODULE_EXPORT void
+log_level_changed_cb(GtkWidget *widget, signal_user_data_t *ud)
{
-#if !defined(_WIN32)
- DBusGConnection *conn;
- DBusGProxy *proxy;
- GError *error = NULL;
- gboolean res;
-
+ pref_changed_cb(widget, ud);
+ int level = ghb_dict_get_int(ud->prefs, "LoggingLevel");
+ ghb_log_level_set(level);
+}
- 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
+G_MODULE_EXPORT void
+use_m4v_changed_cb(GtkWidget *widget, signal_user_data_t *ud)
+{
+ g_debug("use_m4v_changed_cb");
+ ghb_widget_to_setting (ud->prefs, widget);
+ ghb_check_dependency(ud, widget, NULL);
+ const gchar *name = ghb_get_setting_key(widget);
+ ghb_pref_set(ud->prefs, name);
+ ghb_update_destination_extension(ud);
}
-#if !defined(_WIN32)
-static gboolean
-ghb_can_shutdown_gpm()
+G_MODULE_EXPORT void
+vqual_granularity_changed_cb(GtkWidget *widget, signal_user_data_t *ud)
{
- gboolean can_shutdown = FALSE;
- DBusGConnection *conn;
- DBusGProxy *proxy;
- GError *error = NULL;
- gboolean res;
+ g_debug("vqual_granularity_changed_cb");
+ ghb_widget_to_setting (ud->prefs, widget);
+ ghb_check_dependency(ud, widget, NULL);
+ const gchar *name = ghb_get_setting_key(widget);
+ ghb_pref_set(ud->prefs, name);
- 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);
- return can_shutdown;
+ float val, vqmin, vqmax, step, page;
+ int inverted, digits;
+
+ ghb_vquality_range(ud, &vqmin, &vqmax, &step, &page, &digits, &inverted);
+ val = ghb_dict_get_double(ud->settings, "VideoQualitySlider");
+ ghb_scale_configure(ud, "VideoQualitySlider", val, vqmin, vqmax,
+ step, page, digits, inverted);
}
-#endif
-#if !defined(_WIN32)
-static void
-ghb_shutdown_gpm()
+G_MODULE_EXPORT void
+tweaks_changed_cb(GtkWidget *widget, signal_user_data_t *ud)
{
- DBusGConnection *conn;
- DBusGProxy *proxy;
- GError *error = NULL;
- gboolean res;
+ g_debug("tweaks_changed_cb");
+ ghb_widget_to_setting (ud->prefs, widget);
+ const gchar *name = ghb_get_setting_key(widget);
+ ghb_pref_set(ud->prefs, name);
+}
+G_MODULE_EXPORT void
+hbfd_feature_changed_cb(GtkWidget *widget, signal_user_data_t *ud)
+{
+ ghb_widget_to_setting (ud->prefs, widget);
+ const gchar *name = ghb_get_setting_key(widget);
+ ghb_pref_set(ud->prefs, name);
- 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)
+ gboolean hbfd = ghb_dict_get_bool(ud->prefs, "hbfd_feature");
+ if (hbfd)
{
- if (error != NULL)
- {
- g_warning("Shutdown failed: %s", error->message);
- g_error_free(error);
- }
- else
- g_warning("Shutdown failed");
+ const GhbValue *val;
+ val = ghb_dict_get_value(ud->prefs, "hbfd");
+ ghb_ui_settings_update(ud, ud->prefs, "hbfd", val);
}
- g_object_unref(G_OBJECT(proxy));
- dbus_g_connection_unref(conn);
+ widget = GHB_WIDGET(ud->builder, "hbfd");
+ gtk_widget_set_visible(widget, hbfd);
}
-#endif
-void
-ghb_inhibit_gpm()
+gboolean
+ghb_file_menu_add_dvd(signal_user_data_t *ud)
{
-#if !defined(_WIN32)
- DBusGConnection *conn;
- DBusGProxy *proxy;
- GError *error = NULL;
- gboolean res;
+ GList *link, *drives;
+ static GList *dvd_items = NULL;
+ g_debug("ghb_file_menu_add_dvd()");
+ GtkMenu *menu = GTK_MENU(GHB_WIDGET(ud->builder, "file_submenu"));
- 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)
+ // Clear previous dvd items from list
+ link = dvd_items;
+ while (link != NULL)
{
- g_warning("Could not get DBUS proxy: %s", GPM_DBUS_PM_SERVICE);
- dbus_g_connection_unref(conn);
- return;
+ GtkWidget * widget = GTK_WIDGET(link->data);
+ // widget_destroy automatically removes widget from container.
+ gtk_widget_destroy(widget);
+ link = link->next;
}
- 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)
+ g_list_free(dvd_items);
+ dvd_items = NULL;
+
+ int pos = 5;
+ link = drives = dvd_device_list();
+ if (drives != NULL)
{
- if (error != NULL)
+ GtkWidget *widget = gtk_separator_menu_item_new();
+ dvd_items = g_list_append(dvd_items, (gpointer)widget);
+
+ gtk_menu_shell_insert(GTK_MENU_SHELL(menu), widget, pos++);
+ gtk_widget_set_visible(widget, TRUE);
+
+ while (link != NULL)
{
- g_warning("Inhibit failed: %s", error->message);
- g_error_free(error);
- gpm_cookie = -1;
+ GtkWidget *widget;
+ gchar *drive = get_dvd_device_name(link->data);
+ gchar *name = get_dvd_volume_name(link->data);
+
+ widget = gtk_menu_item_new_with_label(name);
+ gtk_buildable_set_name(GTK_BUILDABLE(widget), drive);
+ gtk_widget_set_tooltip_text(widget, _("Scan this DVD source"));
+
+ dvd_items = g_list_append(dvd_items, (gpointer)widget);
+ gtk_menu_shell_insert(GTK_MENU_SHELL(menu), widget, pos++);
+
+ gtk_widget_set_visible(widget, TRUE);
+
+ // Connect signal to action (menu item)
+ g_signal_connect(widget, "activate",
+ (GCallback)dvd_source_activate_cb, ud);
+ g_free(name);
+ g_free(drive);
+ free_drive(link->data);
+ link = link->next;
}
- else
- g_warning("Inhibit failed");
- gpm_cookie = -1;
- gpm_inhibited = FALSE;
+
+ g_list_free(drives);
}
- g_object_unref(G_OBJECT(proxy));
- dbus_g_connection_unref(conn);
-#endif
+
+ return FALSE;
}
-void
-ghb_uninhibit_gpm()
+gboolean ghb_is_cd(GDrive *gd);
+
+static GList*
+dvd_device_list()
{
-#if !defined(_WIN32)
- DBusGConnection *conn;
- DBusGProxy *proxy;
- GError *error = NULL;
- gboolean res;
+ GList *dvd_devices = NULL;
- g_debug("ghb_uninhibit_gpm() gpm_cookie %u", gpm_cookie);
+#if defined(_WIN32)
+ gint ii, drives;
+ gchar drive[5];
- 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)
+ strcpy(drive, "A:" G_DIR_SEPARATOR_S);
+ drives = GetLogicalDrives();
+ for (ii = 0; ii < 26; ii++)
{
- g_warning("Could not get DBUS proxy: %s", GPM_DBUS_PM_SERVICE);
- dbus_g_connection_unref(conn);
- return;
+ 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;
}
- res = dbus_g_proxy_call(proxy, "UnInhibit", &error,
- G_TYPE_UINT, gpm_cookie,
- G_TYPE_INVALID,
- G_TYPE_INVALID);
- if (!res)
+#else
+ GVolumeMonitor *gvm;
+ GList *drives, *link;
+
+ gvm = g_volume_monitor_get ();
+ drives = g_volume_monitor_get_connected_drives (gvm);
+ link = drives;
+ while (link != NULL)
{
- if (error != NULL)
+ GDrive *gd;
+
+ gd = (GDrive*)link->data;
+ if (ghb_is_cd(gd))
{
- g_warning("UnInhibit failed: %s", error->message);
- g_error_free(error);
+ dvd_devices = g_list_append(dvd_devices, gd);
}
else
- g_warning("UnInhibit failed");
+ g_object_unref (gd);
+ link = link->next;
}
- gpm_inhibited = FALSE;
- dbus_g_connection_unref(conn);
- g_object_unref(G_OBJECT(proxy));
+ g_list_free(drives);
#endif
-}
-
-#if !defined(_WIN32)
-// For inhibit and shutdown
-#define GPM_DBUS_SM_SERVICE "org.gnome.SessionManager"
-#define GPM_DBUS_SM_PATH "/org/gnome/SessionManager"
-#define GPM_DBUS_SM_INTERFACE "org.gnome.SessionManager"
+ return dvd_devices;
+}
+#if defined(__linux__) && defined(_HAVE_GUDEV)
+static GUdevClient *udev_ctx = NULL;
#endif
-static gboolean
-ghb_can_shutdown_gsm()
+gboolean
+ghb_is_cd(GDrive *gd)
{
- gboolean can_shutdown = FALSE;
-#if !defined(_WIN32)
- DBusGConnection *conn;
- DBusGProxy *proxy;
- GError *error = NULL;
- gboolean res;
-
+#if defined(__linux__) && defined(_HAVE_GUDEV)
+ gchar *device;
+ GUdevDevice *udd;
- 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);
+ if (udev_ctx == NULL)
return FALSE;
- }
- proxy = dbus_g_proxy_new_for_name(conn, GPM_DBUS_SM_SERVICE,
- GPM_DBUS_SM_PATH, GPM_DBUS_SM_INTERFACE);
- if (proxy == NULL)
- {
- g_warning("Could not get DBUS proxy: %s", GPM_DBUS_SM_SERVICE);
- dbus_g_connection_unref(conn);
+
+ device = g_drive_get_identifier(gd, G_VOLUME_IDENTIFIER_KIND_UNIX_DEVICE);
+ if (device == NULL)
return FALSE;
- }
- res = dbus_g_proxy_call(proxy, "CanShutdown", &error,
- G_TYPE_INVALID,
- G_TYPE_BOOLEAN, &can_shutdown,
- G_TYPE_INVALID);
- g_object_unref(G_OBJECT(proxy));
- dbus_g_connection_unref(conn);
- if (!res)
+
+ udd = g_udev_client_query_by_device_file(udev_ctx, device);
+ if (udd == NULL)
{
- if (error != NULL)
- {
- g_error_free(error);
- }
- // Try to shutdown anyway
- can_shutdown = TRUE;
- // Try the gpm version
- return ghb_can_shutdown_gpm();
+ g_message("udev: Failed to lookup device %s", device);
+ g_free(device);
+ return FALSE;
}
+ g_free(device);
+
+ gint val;
+ val = g_udev_device_get_property_as_int(udd, "ID_CDROM_DVD");
+ g_object_unref(udd);
+ if (val == 1)
+ return TRUE;
+
+ return FALSE;
+#else
+ return FALSE;
#endif
- return can_shutdown;
}
-static void
-ghb_shutdown_gsm()
+void
+ghb_udev_init()
{
-#if !defined(_WIN32)
- DBusGConnection *conn;
- DBusGProxy *proxy;
- GError *error = NULL;
- gboolean res;
+#if defined(__linux__) && defined(_HAVE_GUDEV)
+ udev_ctx = g_udev_client_new(NULL);
+#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;
- 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);
+ // 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;
- }
- proxy = dbus_g_proxy_new_for_name(conn, GPM_DBUS_SM_SERVICE,
- GPM_DBUS_SM_PATH, GPM_DBUS_SM_INTERFACE);
- if (proxy == NULL)
+ if (insert)
{
- g_warning("Could not get DBUS proxy: %s", GPM_DBUS_SM_SERVICE);
- dbus_g_connection_unref(conn);
- return;
+ rem_count = 0;
+ ins_count++;
+ if (ins_count == 2)
+ {
+ GHB_THREAD_NEW("Cache Volume Names",
+ (GThreadFunc)ghb_cache_volnames, ud);
+ if (ghb_dict_get_bool(ud->prefs, "AutoScan") &&
+ ud->current_dvd_device != NULL &&
+ strcmp(device, ud->current_dvd_device) == 0)
+ {
+ show_scan_progress(ud);
+ update_source_label(ud, device);
+ gint preview_count;
+ preview_count = ghb_dict_get_int(ud->prefs, "preview_count");
+ ghb_dict_set_string(ud->globals, "scan_source", device);
+ start_scan(ud, device, 0, preview_count);
+ }
+ }
}
- res = dbus_g_proxy_call(proxy, "Shutdown", &error,
- G_TYPE_INVALID,
- G_TYPE_INVALID);
- g_object_unref(G_OBJECT(proxy));
- dbus_g_connection_unref(conn);
- if (!res)
+ else
{
- if (error != NULL)
+ ins_count = 0;
+ rem_count++;
+ if (rem_count == 2)
{
- g_error_free(error);
+ GHB_THREAD_NEW("Cache Volume Names",
+ (GThreadFunc)ghb_cache_volnames, ud);
+ if (ud->current_dvd_device != NULL &&
+ strcmp(device, ud->current_dvd_device) == 0)
+ {
+ ghb_hb_cleanup(TRUE);
+ prune_logs(ud);
+ ghb_dict_set_string(ud->globals, "scan_source", "/dev/null");
+ start_scan(ud, "/dev/null", 0, 1);
+ }
}
- // Try the gpm version
- ghb_shutdown_gpm();
}
-#endif
}
-void
-ghb_inhibit_gsm(signal_user_data_t *ud)
+static gchar
+FindDriveFromMask(ULONG unitmask)
{
-#if !defined(_WIN32)
- DBusGConnection *conn;
- DBusGProxy *proxy;
- GError *error = NULL;
- gboolean res;
- guint xid;
- GtkWidget *widget;
-
-
- if (gpm_inhibited)
- {
- // Already inhibited
- return;
- }
- g_debug("ghb_inhibit_gsm()");
- 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_SM_SERVICE,
- GPM_DBUS_SM_PATH, GPM_DBUS_SM_INTERFACE);
- if (proxy == NULL)
+ gchar cc;
+ for (cc = 0; cc < 26; cc++)
{
- g_warning("Could not get DBUS proxy: %s", GPM_DBUS_SM_SERVICE);
- dbus_g_connection_unref(conn);
- return;
+ if (unitmask & 0x01)
+ return 'A' + cc;
+ unitmask >>= 1;
}
- widget = GHB_WIDGET(ud->builder, "hb_window");
- xid = GDK_WINDOW_XID(gtk_widget_get_window(widget));
- res = dbus_g_proxy_call(proxy, "Inhibit", &error,
- G_TYPE_STRING, "ghb",
- G_TYPE_UINT, xid,
- G_TYPE_STRING, "Encoding",
- G_TYPE_UINT, 1 | 4,
- G_TYPE_INVALID,
- G_TYPE_UINT, &gpm_cookie,
- G_TYPE_INVALID);
- gpm_inhibited = TRUE;
- g_object_unref(G_OBJECT(proxy));
- dbus_g_connection_unref(conn);
- if (!res)
+ 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)
{
- if (error != NULL)
+ case DBT_DEVICEARRIVAL:
{
- g_error_free(error);
- gpm_cookie = -1;
- }
- gpm_cookie = -1;
- gpm_inhibited = FALSE;
- // Try the gpm version
- ghb_inhibit_gpm();
+ 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: ;
}
-#endif
}
-void
-ghb_uninhibit_gsm()
+#else
+
+G_MODULE_EXPORT void
+drive_changed_cb(GVolumeMonitor *gvm, GDrive *gd, signal_user_data_t *ud)
{
-#if !defined(_WIN32)
- DBusGConnection *conn;
- DBusGProxy *proxy;
- GError *error = NULL;
- gboolean res;
+ gchar *device;
+ gint state;
- g_debug("ghb_uninhibit_gsm() gpm_cookie %u", gpm_cookie);
+ g_debug("drive_changed_cb()");
+ GHB_THREAD_NEW("Cache Volume Names", (GThreadFunc)ghb_cache_volnames, ud);
- 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_SM_SERVICE,
- GPM_DBUS_SM_PATH, GPM_DBUS_SM_INTERFACE);
- if (proxy == 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 )
{
- g_warning("Could not get DBUS proxy: %s", GPM_DBUS_SM_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);
- dbus_g_connection_unref(conn);
- g_object_unref(G_OBJECT(proxy));
- if (!res)
+ if (g_drive_has_media(gd))
{
- if (error != NULL)
+ if (ghb_dict_get_bool(ud->prefs, "AutoScan"))
{
- g_error_free(error);
+ show_scan_progress(ud);
+ update_source_label(ud, device);
+ gint preview_count;
+ preview_count = ghb_dict_get_int(ud->prefs, "preview_count");
+ ghb_dict_set_string(ud->globals, "scan_source", device);
+ start_scan(ud, device, 0, preview_count);
}
- ghb_uninhibit_gpm();
}
- gpm_inhibited = FALSE;
-#endif
+ else
+ {
+ ghb_hb_cleanup(TRUE);
+ prune_logs(ud);
+ ghb_dict_set_string(ud->globals, "scan_source", "/dev/null");
+ start_scan(ud, "/dev/null", 0, 1);
+ }
}
+#endif
G_MODULE_EXPORT gboolean
easter_egg_cb(