+void
+ghb_inhibit_gsm(signal_user_data_t *ud)
+{
+#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)
+ {
+ g_warning("Could not get DBUS proxy: %s", GPM_DBUS_SM_SERVICE);
+ dbus_g_connection_unref(conn);
+ return;
+ }
+ widget = GHB_WIDGET(ud->builder, "hb_window");
+ xid = GDK_DRAWABLE_XID(widget->window);
+ 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)
+ {
+ if (error != NULL)
+ {
+ g_error_free(error);
+ gpm_cookie = -1;
+ }
+ gpm_cookie = -1;
+ gpm_inhibited = FALSE;
+ // Try the gpm version
+ ghb_inhibit_gpm();
+ }
+#endif
+}
+
+void
+ghb_uninhibit_gsm()
+{
+#if !defined(_WIN32)
+ DBusGConnection *conn;
+ DBusGProxy *proxy;
+ GError *error = NULL;
+ gboolean res;
+
+ g_debug("ghb_uninhibit_gsm() gpm_cookie %u", gpm_cookie);
+
+ if (!gpm_inhibited)
+ {
+ // Not inhibited
+ return;
+ }
+ conn = dbus_g_bus_get(DBUS_BUS_SESSION, &error);
+ if (error != NULL)
+ {
+ g_warning("DBUS cannot connect: %s", error->message);
+ g_error_free(error);
+ return;
+ }
+ proxy = dbus_g_proxy_new_for_name(conn, GPM_DBUS_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, gpm_cookie,
+ G_TYPE_INVALID,
+ G_TYPE_INVALID);
+ dbus_g_connection_unref(conn);
+ g_object_unref(G_OBJECT(proxy));
+ if (!res)
+ {
+ if (error != NULL)
+ {
+ g_error_free(error);
+ }
+ ghb_uninhibit_gpm();
+ }
+ gpm_inhibited = FALSE;
+#endif
+}
+
+void
+ghb_hal_init()
+{
+#if !defined(_WIN32)
+ DBusGConnection *gconn;
+ DBusConnection *conn;
+ GError *gerror = NULL;
+ DBusError error;
+ char **devices;
+ int nr;
+
+ dbus_init ();
+
+ if (!(hal_ctx = libhal_ctx_new ())) {
+ g_warning ("failed to create a HAL context!");
+ return;
+ }
+
+ gconn = dbus_g_bus_get(DBUS_BUS_SYSTEM, &gerror);
+ if (gerror != NULL)
+ {
+ g_warning("DBUS cannot connect: %s", gerror->message);
+ g_error_free(gerror);
+ return;
+ }
+ conn = dbus_g_connection_get_connection(gconn);
+ libhal_ctx_set_dbus_connection (hal_ctx, conn);
+ dbus_error_init (&error);
+ if (!libhal_ctx_init (hal_ctx, &error)) {
+ g_warning ("libhal_ctx_init failed: %s", error.message ? error.message : "unknown");
+ dbus_error_free (&error);
+ libhal_ctx_free (hal_ctx);
+ dbus_g_connection_unref(gconn);
+ hal_ctx = NULL;
+ return;
+ }
+
+ /*
+ * Do something to ping the HAL daemon - the above functions will
+ * succeed even if hald is not running, so long as DBUS is. But we
+ * want to exit silently if hald is not running, to behave on
+ * pre-2.6 systems.
+ */
+ if (!(devices = libhal_get_all_devices (hal_ctx, &nr, &error))) {
+ g_warning ("seems that HAL is not running: %s", error.message ? error.message : "unknown");
+ dbus_error_free (&error);
+
+ libhal_ctx_shutdown (hal_ctx, NULL);
+ libhal_ctx_free (hal_ctx);
+ hal_ctx = NULL;
+ dbus_g_connection_unref(gconn);
+ return;
+ }
+
+ libhal_free_string_array (devices);
+ dbus_g_connection_unref(gconn);
+#endif
+}
+
+G_MODULE_EXPORT gboolean
+tweak_setting_cb(
+ GtkWidget *widget,
+ GdkEventButton *event,
+ signal_user_data_t *ud)
+{
+ const gchar *name;
+ gchar *tweak_name;
+ gboolean ret = FALSE;
+ gboolean allow_tweaks;
+
+ g_debug("press %d %d", event->type, event->button);
+ allow_tweaks = ghb_settings_get_boolean(ud->settings, "allow_tweaks");
+ if (allow_tweaks && event->type == GDK_BUTTON_PRESS && event->button == 3)
+ { // Its a right mouse click
+ GtkWidget *dialog;
+ GtkEntry *entry;
+ GtkResponseType response;
+ gchar *tweak = NULL;
+
+ name = gtk_widget_get_name(widget);
+ if (g_str_has_prefix(name, "tweak_"))
+ {
+ tweak_name = g_strdup(name);
+ }
+ else
+ {
+ tweak_name = g_strdup_printf("tweak_%s", name);
+ }
+
+ tweak = ghb_settings_get_string (ud->settings, tweak_name);
+ dialog = GHB_WIDGET(ud->builder, "tweak_dialog");
+ gtk_window_set_title(GTK_WINDOW(dialog), tweak_name);
+ entry = GTK_ENTRY(GHB_WIDGET(ud->builder, "tweak_setting"));
+ if (tweak)
+ {
+ gtk_entry_set_text(entry, tweak);
+ g_free(tweak);
+ }
+ response = gtk_dialog_run(GTK_DIALOG(dialog));
+ gtk_widget_hide(dialog);
+ if (response == GTK_RESPONSE_OK)
+ {
+ tweak = (gchar*)gtk_entry_get_text(entry);
+ if (ghb_validate_filter_string(tweak, -1))
+ ghb_settings_set_string(ud->settings, tweak_name, tweak);
+ else
+ {
+ gchar *message;
+ message = g_strdup_printf(
+ "Invalid Settings:\n%s",
+ tweak);
+ ghb_message_dialog(GTK_MESSAGE_ERROR, message, "Cancel", NULL);
+ g_free(message);
+ }
+ }
+ g_free(tweak_name);
+ ret = TRUE;
+ }
+ return ret;
+}
+
+G_MODULE_EXPORT gboolean
+easter_egg_cb(
+ GtkWidget *widget,
+ GdkEventButton *event,
+ signal_user_data_t *ud)
+{
+ g_debug("press %d %d", event->type, event->button);
+ if (event->type == GDK_3BUTTON_PRESS && event->button == 1)
+ { // Its a tripple left mouse button click
+ GtkWidget *widget;
+ widget = GHB_WIDGET(ud->builder, "allow_tweaks");
+ gtk_widget_show(widget);
+ widget = GHB_WIDGET(ud->builder, "hbfd_feature");
+ gtk_widget_show(widget);
+ }
+ else if (event->type == GDK_BUTTON_PRESS && event->button == 1)
+ {
+ GtkWidget *widget;
+ widget = GHB_WIDGET(ud->builder, "allow_tweaks");
+ gtk_widget_hide(widget);
+ widget = GHB_WIDGET(ud->builder, "hbfd_feature");
+ gtk_widget_hide(widget);
+ }
+ return FALSE;
+}
+
+G_MODULE_EXPORT gchar*
+format_deblock_cb(GtkScale *scale, gdouble val, signal_user_data_t *ud)
+{
+ if (val < 5.0)
+ {
+ return g_strdup_printf("Off");
+ }
+ else
+ {
+ return g_strdup_printf("%d", (gint)val);
+ }
+}
+
+G_MODULE_EXPORT gchar*
+format_drc_cb(GtkScale *scale, gdouble val, signal_user_data_t *ud)
+{
+ if (val <= 0.0)
+ {
+ return g_strdup_printf("Off");
+ }
+ else
+ {
+ return g_strdup_printf("%.1f", val);
+ }
+}
+
+G_MODULE_EXPORT gchar*
+format_vquality_cb(GtkScale *scale, gdouble val, signal_user_data_t *ud)
+{
+ gint vcodec = ghb_settings_combo_int(ud->settings, "VideoEncoder");
+ switch (vcodec)
+ {
+ case HB_VCODEC_X264:
+ {
+ return g_strdup_printf("RF: %.4g", val);
+ } break;
+
+ case HB_VCODEC_FFMPEG:
+ {
+ return g_strdup_printf("QP: %d", (int)val);
+ } break;
+
+ case HB_VCODEC_THEORA:
+ {
+ return g_strdup_printf("QP: %d", (int)val);
+ } break;
+
+ default:
+ {
+ } break;
+ }
+ return g_strdup_printf("QP: %.4g", val);
+}
+
+static void
+process_appcast(signal_user_data_t *ud)
+{
+ gchar *description = NULL, *build = NULL, *version = NULL, *msg;
+#if !defined(_WIN32)
+ GtkWidget *window;
+ static GtkWidget *html = NULL;
+#endif
+ GtkWidget *dialog, *label;
+ gint response, ibuild = 0, skip;
+
+ if (ud->appcast == NULL || ud->appcast_len < 15 ||
+ strncmp(&(ud->appcast[9]), "200 OK", 6))
+ {
+ goto done;
+ }
+ ghb_appcast_parse(ud->appcast, &description, &build, &version);
+ if (build)
+ ibuild = g_strtod(build, NULL);
+ skip = ghb_settings_get_int(ud->settings, "update_skip_version");
+ if (description == NULL || build == NULL || version == NULL
+ || ibuild <= hb_get_build(NULL) || skip == ibuild)
+ {
+ goto done;
+ }
+ msg = g_strdup_printf("HandBrake %s/%s is now available (you have %s/%d).",
+ version, build, hb_get_version(NULL), hb_get_build(NULL));
+ label = GHB_WIDGET(ud->builder, "update_message");
+ gtk_label_set_text(GTK_LABEL(label), msg);
+
+#if !defined(_WIN32)
+ if (html == NULL)
+ {
+ html = webkit_web_view_new();
+ window = GHB_WIDGET(ud->builder, "update_scroll");
+ gtk_container_add(GTK_CONTAINER(window), html);
+ // Show it
+ gtk_widget_set_size_request(html, 420, 240);
+ gtk_widget_show(html);
+ }
+ webkit_web_view_open(WEBKIT_WEB_VIEW(html), description);
+#endif
+ dialog = GHB_WIDGET(ud->builder, "update_dialog");
+ response = gtk_dialog_run(GTK_DIALOG(dialog));
+ gtk_widget_hide(dialog);
+ if (response == GTK_RESPONSE_OK)
+ {
+ // Skip
+ ghb_settings_set_int(ud->settings, "update_skip_version", ibuild);
+ ghb_pref_save(ud->settings, "update_skip_version");
+ }
+ g_free(msg);
+
+done:
+ if (description) g_free(description);
+ if (build) g_free(build);
+ if (version) g_free(version);
+ g_free(ud->appcast);
+ ud->appcast_len = 0;
+ ud->appcast = NULL;
+ appcast_busy = FALSE;
+}
+
+void
+ghb_net_close(GIOChannel *ioc)
+{
+ gint fd;
+
+ g_debug("ghb_net_close");
+ if (ioc == NULL) return;
+ fd = g_io_channel_unix_get_fd(ioc);
+ close(fd);
+ g_io_channel_unref(ioc);
+}
+
+G_MODULE_EXPORT gboolean
+ghb_net_recv_cb(GIOChannel *ioc, GIOCondition cond, gpointer data)
+{
+ gchar buf[2048];
+ gsize len;
+ GError *gerror = NULL;
+ GIOStatus status;
+
+ g_debug("ghb_net_recv_cb");
+ signal_user_data_t *ud = (signal_user_data_t*)data;
+
+ status = g_io_channel_read_chars (ioc, buf, 2048, &len, &gerror);
+ if ((status == G_IO_STATUS_NORMAL || status == G_IO_STATUS_EOF) &&
+ len > 0)
+ {
+ gint new_len = ud->appcast_len + len;
+ ud->appcast = g_realloc(ud->appcast, new_len + 1);
+ memcpy(&(ud->appcast[ud->appcast_len]), buf, len);
+ ud->appcast_len = new_len;
+ }
+ if (status == G_IO_STATUS_EOF)
+ {
+ ud->appcast[ud->appcast_len] = 0;
+ ghb_net_close(ioc);
+ process_appcast(ud);
+ return FALSE;
+ }
+ return TRUE;
+}
+
+GIOChannel*
+ghb_net_open(signal_user_data_t *ud, gchar *address, gint port)
+{
+ GIOChannel *ioc;
+ gint fd;
+
+ struct sockaddr_in sock;
+ struct hostent * host;
+
+ g_debug("ghb_net_open");
+ if( !( host = gethostbyname( address ) ) )
+ {
+ g_warning( "gethostbyname failed (%s)", address );
+ appcast_busy = FALSE;
+ return NULL;
+ }
+
+ memset( &sock, 0, sizeof( struct sockaddr_in ) );
+ sock.sin_family = host->h_addrtype;
+ sock.sin_port = htons( port );
+ memcpy( &sock.sin_addr, host->h_addr, host->h_length );
+
+ fd = socket(host->h_addrtype, SOCK_STREAM, 0);
+ if( fd < 0 )
+ {
+ g_debug( "socket failed" );
+ appcast_busy = FALSE;
+ return NULL;
+ }
+
+ if(connect(fd, (struct sockaddr*)&sock, sizeof(struct sockaddr_in )) < 0 )
+ {
+ g_debug( "connect failed" );
+ appcast_busy = FALSE;
+ return NULL;
+ }
+ ioc = g_io_channel_unix_new(fd);
+ g_io_channel_set_encoding (ioc, NULL, NULL);
+ g_io_channel_set_flags(ioc, G_IO_FLAG_NONBLOCK, NULL);
+ g_io_add_watch (ioc, G_IO_IN, ghb_net_recv_cb, (gpointer)ud );
+
+ return ioc;
+}
+
+gpointer
+ghb_check_update(signal_user_data_t *ud)
+{
+ gchar *query;
+ gsize len;
+ GIOChannel *ioc;
+ GError *gerror = NULL;
+ GRegex *regex;
+ GMatchInfo *mi;
+ gchar *host, *appcast;
+
+ g_debug("ghb_check_update");
+ appcast_busy = TRUE;
+ regex = g_regex_new("^http://(.+)/(.+)$", 0, 0, NULL);
+ if (!g_regex_match(regex, HB_PROJECT_URL_APPCAST, 0, &mi))
+ {
+ return NULL;
+ }
+
+ host = g_match_info_fetch(mi, 1);
+ appcast = g_match_info_fetch(mi, 2);
+
+ if (host == NULL || appcast == NULL)
+ return NULL;
+
+ query = g_strdup_printf( "GET /%s HTTP/1.0\r\nHost: %s\r\n\r\n",
+ appcast, host);
+
+ ioc = ghb_net_open(ud, host, 80);
+ if (ioc == NULL)
+ return NULL;
+
+ g_io_channel_write_chars(ioc, query, strlen(query), &len, &gerror);
+ g_io_channel_flush(ioc, &gerror);
+ g_free(query);
+ g_free(host);
+ g_free(appcast);
+ g_match_info_free(mi);
+ g_regex_unref(regex);
+ return NULL;
+}
+
+G_MODULE_EXPORT gboolean
+hb_visibility_event_cb(
+ GtkWidget *widget,
+ GdkEventVisibility *vs,
+ signal_user_data_t *ud)
+{
+ ud->hb_visibility = vs->state;
+ return FALSE;
+}
+
+G_MODULE_EXPORT void
+status_activate_cb(GtkStatusIcon *si, signal_user_data_t *ud)
+{
+ GtkWindow *window;
+ GdkWindowState state;
+
+ window = GTK_WINDOW(GHB_WIDGET(ud->builder, "hb_window"));
+ state = gdk_window_get_state(GTK_WIDGET(window)->window);
+ if ((state & GDK_WINDOW_STATE_ICONIFIED) ||
+ (ud->hb_visibility != GDK_VISIBILITY_UNOBSCURED))
+ {
+ gtk_window_present(window);
+ gtk_window_set_skip_taskbar_hint(window, FALSE);
+ }
+ else
+ {
+ gtk_window_set_skip_taskbar_hint(window, TRUE);
+ gtk_window_iconify(window);
+ }
+}
+
+#if !defined(_WIN32)
+G_MODULE_EXPORT void
+notify_closed_cb(NotifyNotification *notification, signal_user_data_t *ud)
+{
+ g_object_unref(G_OBJECT(notification));
+}
+#endif
+
+void
+ghb_notify_done(signal_user_data_t *ud)
+{
+ GtkStatusIcon *si;
+
+ if (ghb_settings_combo_int(ud->settings, "WhenComplete") == 0)
+ return;
+
+ si = GTK_STATUS_ICON(GHB_OBJECT(ud->builder, "hb_status"));
+
+#if !defined(_WIN32)
+ NotifyNotification *notification;
+ notification = notify_notification_new(
+ "Encode Complete",
+ "Put down that cocktail, Your HandBrake queue is done!",
+ "hb-icon",
+ NULL);
+ notify_notification_attach_to_status_icon(notification, si);
+ g_signal_connect(notification, "closed", (GCallback)notify_closed_cb, ud);
+ notify_notification_show(notification, NULL);
+#endif
+
+ if (ghb_settings_combo_int(ud->settings, "WhenComplete") == 3)
+ {
+ if (ghb_can_shutdown_gsm())
+ {
+ ghb_countdown_dialog(GTK_MESSAGE_WARNING,
+ "Your encode is complete.",
+ "Shutting down the computer",
+ "Cancel", (GSourceFunc)shutdown_cb, 60);
+ }
+ }
+ if (ghb_settings_combo_int(ud->settings, "WhenComplete") == 2)
+ {
+ if (ghb_can_suspend_gpm())
+ {
+ ghb_countdown_dialog(GTK_MESSAGE_WARNING,
+ "Your encode is complete.",
+ "Putting computer to sleep",
+ "Cancel", (GSourceFunc)suspend_cb, 60);
+ }
+ }
+}