+ DBusError error;
+ char **devices;
+ int nr;
+
+ if (!dbus_init ())
+ return;
+
+ if (!(hal_ctx = libhal_ctx_new ())) {
+ g_warning ("failed to create a HAL context!");
+ return;
+ }
+
+ libhal_ctx_set_dbus_connection (hal_ctx, dbus_connection);
+ 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);
+ 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);
+ return;
+ }
+
+ libhal_free_string_array (devices);
+
+ //gvm_hal_claim_branch ("/org/freedesktop/Hal/devices/local");
+}
+
+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;
+}
+
+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;
+}
+
+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);
+ }
+}
+
+gchar*
+format_vquality_cb(GtkScale *scale, gdouble val, signal_user_data_t *ud)
+{
+ if (ghb_settings_get_boolean(ud->settings, "directqp"))
+ {
+ gint vcodec = ghb_settings_combo_int(ud->settings, "VideoEncoder");
+ // Only x264 and ffmpeg currently support direct qp/crf entry
+ if (vcodec != HB_VCODEC_X264 && vcodec != HB_VCODEC_FFMPEG)
+ {
+ val *= 100;
+ return g_strdup_printf("%.1f", val);
+ }
+ return g_strdup_printf("%d", (gint)val);
+ }
+ else
+ {
+ val *= 100;
+ return g_strdup_printf("%.1f", val);
+ }
+}
+
+static void
+html_link_cb(GtkHTML *html, const gchar *url, signal_user_data_t *ud)
+{
+ browse_url(url);
+}
+
+static gpointer check_stable_update(signal_user_data_t *ud);
+static gboolean stable_update_lock = FALSE;
+
+static void
+process_appcast(signal_user_data_t *ud)
+{
+ gchar *description = NULL, *build = NULL, *version = NULL, *msg;
+ GtkWidget *html, *window, *dialog, *label;
+ gint response, ibuild = 0, skip;
+
+ if (ud->appcast == NULL || ud->appcast_len < 15 ||
+ strncmp(&(ud->appcast[9]), "200 OK", 6))
+ {
+ if (!stable_update_lock && HB_BUILD % 100)
+ g_idle_add((GSourceFunc)check_stable_update, ud);
+ 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_BUILD || skip == ibuild)
+ {
+ if (!stable_update_lock && HB_BUILD % 100)
+ g_thread_create((GThreadFunc)check_stable_update, ud, FALSE, NULL);
+ goto done;
+ }
+ msg = g_strdup_printf("HandBrake %s/%s is now available (you have %s/%d).",
+ version, build, HB_VERSION, HB_BUILD);
+ label = GHB_WIDGET(ud->builder, "update_message");
+ gtk_label_set_text(GTK_LABEL(label), msg);
+ html = gtk_html_new_from_string(description, -1);
+ g_signal_connect(html, "link_clicked", G_CALLBACK(html_link_cb), ud);
+ window = GHB_WIDGET(ud->builder, "update_scroll");
+ gtk_container_add(GTK_CONTAINER(window), html);
+ // Show it
+ dialog = GHB_WIDGET(ud->builder, "update_dialog");
+ gtk_widget_set_size_request(html, 420, 240);
+ gtk_widget_show(html);
+ response = gtk_dialog_run(GTK_DIALOG(dialog));
+ gtk_widget_hide(dialog);
+ gtk_widget_destroy(html);
+ 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;
+}
+
+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);
+}
+
+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 );
+ 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" );
+ return NULL;
+ }
+
+ if(connect(fd, (struct sockaddr*)&sock, sizeof(struct sockaddr_in )) < 0 )
+ {
+ g_debug( "connect failed" );
+ 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;
+
+ g_debug("ghb_check_update");
+ if (HB_BUILD % 100)
+ {
+ query =
+ "GET /appcast_unstable.xml HTTP/1.0\r\nHost: handbrake.fr\r\n\r\n";
+ }
+ else
+ {
+ stable_update_lock = TRUE;
+ query = "GET /appcast.xml HTTP/1.0\r\nHost: handbrake.fr\r\n\r\n";
+ }
+ ioc = ghb_net_open(ud, "handbrake.fr", 80);
+ if (ioc == NULL)
+ return NULL;
+
+ g_io_channel_write_chars(ioc, query, strlen(query), &len, &gerror);
+ g_io_channel_flush(ioc, &gerror);
+ // This function is initiated by g_idle_add. Must return false
+ // so that it is not called again
+ return NULL;
+}
+
+static gpointer
+check_stable_update(signal_user_data_t *ud)
+{
+ gchar *query;
+ gsize len;
+ GIOChannel *ioc;
+ GError *gerror = NULL;
+
+ g_debug("check_stable_update");
+ stable_update_lock = TRUE;
+ query = "GET /appcast.xml HTTP/1.0\r\nHost: handbrake.fr\r\n\r\n";
+ ioc = ghb_net_open(ud, "handbrake.fr", 80);
+ if (ioc == NULL)
+ return NULL;
+
+ g_io_channel_write_chars(ioc, query, strlen(query), &len, &gerror);
+ g_io_channel_flush(ioc, &gerror);
+ // This function is initiated by g_idle_add. Must return false
+ // so that it is not called again
+ return NULL;