diff -Naur sushi-3.18.0/configure.ac sushi-3.18.0-gst3/configure.ac --- sushi-3.18.0/configure.ac 2015-09-23 01:04:59.000000000 +0200 +++ sushi-3.18.0-gst3/configure.ac 2016-01-20 04:31:56.590327121 +0100 @@ -62,7 +62,7 @@ clutter-x11-1.0 >= $CLUTTER_MIN_VERSION gtk+-3.0 >= $GTK_MIN_VERSION clutter-gtk-1.0 >= $CLUTTER_GTK_MIN_VERSION - clutter-gst-2.0 + clutter-gst-3.0 gstreamer-1.0 gstreamer-pbutils-1.0 gstreamer-tag-1.0 diff -Naur sushi-3.18.0/src/js/viewers/audio.js sushi-3.18.0-gst3/src/js/viewers/audio.js --- sushi-3.18.0/src/js/viewers/audio.js 2015-07-22 21:26:54.000000000 +0200 +++ sushi-3.18.0-gst3/src/js/viewers/audio.js 2016-01-20 04:32:12.657744887 +0100 @@ -23,6 +23,7 @@ * */ +const GdkPixbuf = imports.gi.GdkPixbuf; const Gio = imports.gi.Gio; const Gst = imports.gi.Gst; const Gtk = imports.gi.Gtk; @@ -254,7 +255,8 @@ }, createToolbar : function () { - this._mainToolbar = new Gtk.Toolbar(); + this._mainToolbar = new Gtk.Toolbar({ margin_start: Constants.TOOLBAR_SPACING, + margin_end: Constants.TOOLBAR_SPACING }); this._mainToolbar.get_style_context().add_class('osd'); this._mainToolbar.set_icon_size(Gtk.IconSize.MENU); this._mainToolbar.show(); diff -Naur sushi-3.18.0/src/js/viewers/gst.js sushi-3.18.0-gst3/src/js/viewers/gst.js --- sushi-3.18.0/src/js/viewers/gst.js 2015-07-22 21:26:54.000000000 +0200 +++ sushi-3.18.0-gst3/src/js/viewers/gst.js 2016-01-20 04:31:56.590327121 +0100 @@ -23,7 +23,7 @@ * */ -imports.gi.versions.ClutterGst = '2.0'; +imports.gi.versions.ClutterGst = '3.0'; const ClutterGst = imports.gi.ClutterGst; const Clutter = imports.gi.Clutter; const Gdk = imports.gi.Gdk; @@ -60,29 +60,33 @@ }, clear : function() { - this._video.playing = false; + this._player.playing = false; }, _createVideo : function(file) { - this._video = - new ClutterGst.VideoTexture({ sync_size: false }); + this._player = new ClutterGst.Playback(); + this._video = new Clutter.Actor({ + content: new ClutterGst.Aspectratio({ + player: this._player + }) + }); - this._video.set_uri(file.get_uri()); - this._video.playing = true; + this._player.set_uri(file.get_uri()); + this._player.playing = true; this._videoSizeChangeId = - this._video.connect('size-change', - Lang.bind(this, - this._onVideoSizeChange)); - this._video.connect('notify::playing', - Lang.bind(this, - this._onVideoPlayingChange)); - this._video.connect('notify::progress', - Lang.bind(this, - this._onVideoProgressChange)); - this._video.connect('notify::duration', - Lang.bind(this, - this._onVideoDurationChange)); + this._player.connect('size-change', + Lang.bind(this, + this._onVideoSizeChange)); + this._player.connect('notify::playing', + Lang.bind(this, + this._onVideoPlayingChange)); + this._player.connect('notify::progress', + Lang.bind(this, + this._onVideoProgressChange)); + this._player.connect('notify::duration', + Lang.bind(this, + this._onVideoDurationChange)); }, _updateProgressBar : function() { @@ -90,7 +94,7 @@ return; this._isSettingValue = true; - this._progressBar.set_value(this._video.progress * 1000); + this._progressBar.set_value(this._player.progress * 1000); this._isSettingValue = false; }, @@ -99,7 +103,7 @@ return; let currentTime = - Math.floor(this._video.duration * this._video.progress); + Math.floor(this._player.duration * this._player.progress); this._currentLabel.set_text(Utils.formatTimeString(currentTime)); }, @@ -108,7 +112,7 @@ if (!this._mainToolbar) return; - let totalTime = this._video.duration; + let totalTime = this._player.duration; this._durationLabel.set_text(Utils.formatTimeString(totalTime)); }, @@ -123,7 +127,7 @@ }, _onVideoPlayingChange : function() { - if (this._video.playing) + if (this._player.playing) this._toolbarPlay.set_icon_name('media-playback-pause-symbolic'); else { @@ -166,8 +170,8 @@ this._toolbarPlay.connect('clicked', Lang.bind(this, function () { - let playing = !this._video.playing; - this._video.playing = playing; + let playing = !this._player.playing; + this._player.playing = playing; })); this._progressBar = @@ -178,7 +182,7 @@ this._progressBar.connect('value-changed', Lang.bind(this, function() { if(!this._isSettingValue) - this._video.progress = this._progressBar.get_value() / 1000; + this._player.progress = this._progressBar.get_value() / 1000; })); item = new Gtk.ToolItem(); @@ -200,7 +204,7 @@ return this._toolbarActor; }, - _onVideoSizeChange : function(video, width, height) { + _onVideoSizeChange : function(player, width, height) { this._videoWidth = width; this._videoHeight = height; diff -Naur sushi-3.18.0/src/libsushi/sushi-cover-art.c sushi-3.18.0-gst3/src/libsushi/sushi-cover-art.c --- sushi-3.18.0/src/libsushi/sushi-cover-art.c 2014-11-20 18:17:19.000000000 +0100 +++ sushi-3.18.0-gst3/src/libsushi/sushi-cover-art.c 2016-01-20 04:32:06.798592077 +0100 @@ -155,61 +155,41 @@ } typedef struct { - SushiCoverArtFetcher *self; - GSimpleAsyncResult *result; gchar *artist; gchar *album; -} FetchUriJob; +} FetchUriTaskData; static void -fetch_uri_job_free (gpointer user_data) +fetch_uri_task_data_free (gpointer user_data) { - FetchUriJob *data = user_data; + FetchUriTaskData *data = user_data; - g_clear_object (&data->self); - g_clear_object (&data->result); g_free (data->artist); g_free (data->album); - g_slice_free (FetchUriJob, data); + g_slice_free (FetchUriTaskData, data); } -static FetchUriJob * -fetch_uri_job_new (SushiCoverArtFetcher *self, - const gchar *artist, - const gchar *album, - GAsyncReadyCallback callback, - gpointer user_data) +static FetchUriTaskData * +fetch_uri_task_data_new (const gchar *artist, + const gchar *album) { - FetchUriJob *retval; + FetchUriTaskData *retval; - retval = g_slice_new0 (FetchUriJob); + retval = g_slice_new0 (FetchUriTaskData); retval->artist = g_strdup (artist); retval->album = g_strdup (album); - retval->self = g_object_ref (self); - retval->result = g_simple_async_result_new (G_OBJECT (self), callback, user_data, - sushi_cover_art_fetcher_get_uri_for_track_async); return retval; } -static gboolean -fetch_uri_job_callback (gpointer user_data) -{ - FetchUriJob *job = user_data; - - g_simple_async_result_complete (job->result); - fetch_uri_job_free (job); - - return FALSE; -} - -static gboolean -fetch_uri_job (GIOSchedulerJob *sched_job, - GCancellable *cancellable, - gpointer user_data) +static void +fetch_uri_job (GTask *task, + gpointer source_object, + gpointer task_data, + GCancellable *cancellable) { - FetchUriJob *job = user_data; + FetchUriTaskData *data = task_data; Mb5Metadata metadata; Mb5Query query; Mb5Release release; @@ -224,7 +204,7 @@ param_values = g_new (gchar*, 3); param_names[0] = g_strdup ("query"); - param_values[0] = g_strdup_printf ("artist:\"%s\" AND release:\"%s\"", job->artist, job->album); + param_values[0] = g_strdup_printf ("artist:\"%s\" AND release:\"%s\"", data->artist, data->album); param_names[1] = g_strdup ("limit"); param_values[1] = g_strdup ("10"); @@ -258,21 +238,16 @@ if (retval == NULL) { /* FIXME: do we need a better error? */ - g_simple_async_result_set_error (job->result, - G_IO_ERROR, - 0, "%s", - "Error getting the ASIN from MusicBrainz"); + g_task_return_new_error (task, + G_IO_ERROR, + 0, "%s", + "Error getting the ASIN from MusicBrainz"); } else { - g_simple_async_result_set_op_res_gpointer (job->result, - retval, NULL); + g_task_return_pointer (task, retval, g_free); } - g_io_scheduler_job_send_to_mainloop_async (sched_job, - fetch_uri_job_callback, - job, NULL); g_strfreev (param_names); g_strfreev (param_values); - return FALSE; } static gchar * @@ -280,15 +255,7 @@ GAsyncResult *result, GError **error) { - gchar *retval; - - if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), - error)) - return NULL; - - retval = g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (result)); - - return retval; + return g_task_propagate_pointer (G_TASK (result), error); } static void @@ -298,12 +265,12 @@ GAsyncReadyCallback callback, gpointer user_data) { - FetchUriJob *job; + FetchUriTaskData *data = fetch_uri_task_data_new (artist, album); + GTask *task = g_task_new (G_OBJECT (self), NULL, callback, user_data); + g_task_set_task_data (task, data, fetch_uri_task_data_free); - job = fetch_uri_job_new (self, artist, album, callback, user_data); - g_io_scheduler_push_job (fetch_uri_job, - job, NULL, - G_PRIORITY_DEFAULT, NULL); + g_task_run_in_thread (task, fetch_uri_job); + g_object_unref (task); } static GFile * diff -Naur sushi-3.18.0/src/libsushi/sushi-file-loader.c sushi-3.18.0-gst3/src/libsushi/sushi-file-loader.c --- sushi-3.18.0/src/libsushi/sushi-file-loader.c 2014-11-20 18:17:19.000000000 +0100 +++ sushi-3.18.0-gst3/src/libsushi/sushi-file-loader.c 2016-01-20 04:32:09.724668363 +0100 @@ -590,7 +590,7 @@ return NULL; retval = gtk_icon_info_load_icon (info, &error); - gtk_icon_info_free (info); + g_object_unref (info); if (error != NULL) { gchar *uri; diff -Naur sushi-3.18.0/src/libsushi/sushi-font-widget.c sushi-3.18.0-gst3/src/libsushi/sushi-font-widget.c --- sushi-3.18.0/src/libsushi/sushi-font-widget.c 2015-07-22 21:26:54.000000000 +0200 +++ sushi-3.18.0-gst3/src/libsushi/sushi-font-widget.c 2016-01-20 04:32:23.257021423 +0100 @@ -1,5 +1,6 @@ /* * Copyright (C) 2011 Red Hat, Inc. + * Copyright (C) 2014 Khaled Hosny . * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -26,6 +27,7 @@ #include "sushi-font-widget.h" #include "sushi-font-loader.h" +#include #include enum { @@ -68,6 +70,112 @@ static const gchar uppercase_text_stock[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; static const gchar punctuation_text_stock[] = "0123456789.:,;(*!?')"; +static void +text_to_glyphs (cairo_t *cr, + const gchar *text, + cairo_glyph_t **glyphs, + int *num_glyphs) +{ + PangoAttribute *fallback_attr; + PangoAttrList *attr_list; + PangoContext *context; + PangoDirection base_dir; + GList *items; + GList *visual_items; + FT_Face ft_face; + hb_font_t *hb_font; + gdouble x = 0, y = 0; + gint i; + gdouble x_scale, y_scale; + + *num_glyphs = 0; + *glyphs = NULL; + + base_dir = pango_find_base_dir (text, -1); + + cairo_scaled_font_t *cr_font = cairo_get_scaled_font (cr); + ft_face = cairo_ft_scaled_font_lock_face (cr_font); + hb_font = hb_ft_font_create (ft_face, NULL); + + cairo_surface_t *target = cairo_get_target (cr); + cairo_surface_get_device_scale (target, &x_scale, &y_scale); + + /* We abuse pango itemazation to split text into script and direction + * runs, since we use our fonts directly no through pango, we don't + * bother changing the default font, but we disable font fallback as + * pango will split runs at font change */ + context = pango_cairo_create_context (cr); + attr_list = pango_attr_list_new (); + fallback_attr = pango_attr_fallback_new (FALSE); + pango_attr_list_insert (attr_list, fallback_attr); + items = pango_itemize_with_base_dir (context, base_dir, + text, 0, strlen (text), + attr_list, NULL); + g_object_unref (context); + pango_attr_list_unref (attr_list); + + /* reorder the items in the visual order */ + visual_items = pango_reorder_items (items); + + while (visual_items) { + PangoItem *item; + PangoAnalysis analysis; + hb_buffer_t *hb_buffer; + hb_glyph_info_t *hb_glyphs; + hb_glyph_position_t *hb_positions; + gint n; + + item = visual_items->data; + analysis = item->analysis; + + hb_buffer = hb_buffer_create (); + hb_buffer_add_utf8 (hb_buffer, text, -1, item->offset, item->length); + hb_buffer_set_script (hb_buffer, hb_glib_script_to_script (analysis.script)); + hb_buffer_set_language (hb_buffer, hb_language_from_string (pango_language_to_string (analysis.language), -1)); + hb_buffer_set_direction (hb_buffer, analysis.level % 2 ? HB_DIRECTION_RTL : HB_DIRECTION_LTR); + + hb_shape (hb_font, hb_buffer, NULL, 0); + + n = hb_buffer_get_length (hb_buffer); + hb_glyphs = hb_buffer_get_glyph_infos (hb_buffer, NULL); + hb_positions = hb_buffer_get_glyph_positions (hb_buffer, NULL); + + *glyphs = g_renew (cairo_glyph_t, *glyphs, *num_glyphs + n); + + for (i = 0; i < n; i++) { + (*glyphs)[*num_glyphs + i].index = hb_glyphs[i].codepoint; + (*glyphs)[*num_glyphs + i].x = x + (hb_positions[i].x_offset / (64. * x_scale)); + (*glyphs)[*num_glyphs + i].y = y - (hb_positions[i].y_offset / (64. * y_scale)); + x += (hb_positions[i].x_advance / (64. * x_scale)); + y -= (hb_positions[i].y_advance / (64. * y_scale)); + } + + *num_glyphs += n; + + hb_buffer_destroy (hb_buffer); + + visual_items = visual_items->next; + } + + g_list_free_full (visual_items, (GDestroyNotify) pango_item_free); + g_list_free_full (items, (GDestroyNotify) pango_item_free); + + hb_font_destroy (hb_font); + cairo_ft_scaled_font_unlock_face (cr_font); +} + +static void +text_extents (cairo_t *cr, + const char *text, + cairo_text_extents_t *extents) +{ + cairo_glyph_t *glyphs; + gint num_glyphs; + text_to_glyphs (cr, text, &glyphs, &num_glyphs); + cairo_glyph_extents (cr, glyphs, num_glyphs, extents); + g_free (glyphs); +} + /* adapted from gnome-utils:font-viewer/font-view.c * * Copyright (C) 2002-2003 James Henstridge @@ -84,13 +192,18 @@ { cairo_font_extents_t font_extents; cairo_text_extents_t extents; + cairo_glyph_t *glyphs; GtkTextDirection text_dir; gint pos_x; + gint num_glyphs; + gint i; text_dir = gtk_widget_get_direction (GTK_WIDGET (self)); + text_to_glyphs (cr, text, &glyphs, &num_glyphs); + cairo_font_extents (cr, &font_extents); - cairo_text_extents (cr, text, &extents); + cairo_glyph_extents (cr, glyphs, num_glyphs, &extents); if (pos_y != NULL) *pos_y += font_extents.ascent + font_extents.descent + @@ -102,8 +215,15 @@ extents.x_advance - padding.right; } + for (i = 0; i < num_glyphs; i++) { + glyphs[i].x += pos_x; + glyphs[i].y += *pos_y; + } + cairo_move_to (cr, pos_x, *pos_y); - cairo_show_text (cr, text); + cairo_show_glyphs (cr, glyphs, num_glyphs); + + g_free (glyphs); *pos_y += LINE_SPACING / 2; } @@ -113,29 +233,20 @@ const gchar *text) { gunichar *string; - glong len, idx, map; - FT_CharMap charmap; - gboolean retval = FALSE; + glong len, idx; + gboolean retval = TRUE; string = g_utf8_to_ucs4_fast (text, -1, &len); - for (map = 0; map < face->num_charmaps; map++) { - charmap = face->charmaps[map]; - FT_Set_Charmap (face, charmap); - - retval = TRUE; + FT_Select_Charmap (face, FT_ENCODING_UNICODE); - for (idx = 0; idx < len; idx++) { - gunichar c = string[idx]; + for (idx = 0; idx < len; idx++) { + gunichar c = string[idx]; - if (!FT_Get_Char_Index (face, c)) { - retval = FALSE; - break; - } - } - - if (retval) + if (!FT_Get_Char_Index (face, c)) { + retval = FALSE; break; + } } g_free (string); @@ -371,7 +482,7 @@ if (self->priv->font_name != NULL) { cairo_set_font_size (cr, title_size); cairo_font_extents (cr, &font_extents); - cairo_text_extents (cr, self->priv->font_name, &extents); + text_extents (cr, self->priv->font_name, &extents); pixmap_height += font_extents.ascent + font_extents.descent + extents.y_advance + LINE_SPACING; pixmap_width = MAX (pixmap_width, extents.width + padding.left + padding.right); @@ -382,21 +493,21 @@ cairo_font_extents (cr, &font_extents); if (self->priv->lowercase_text != NULL) { - cairo_text_extents (cr, self->priv->lowercase_text, &extents); + text_extents (cr, self->priv->lowercase_text, &extents); pixmap_height += font_extents.ascent + font_extents.descent + extents.y_advance + LINE_SPACING; pixmap_width = MAX (pixmap_width, extents.width + padding.left + padding.right); } if (self->priv->uppercase_text != NULL) { - cairo_text_extents (cr, self->priv->uppercase_text, &extents); + text_extents (cr, self->priv->uppercase_text, &extents); pixmap_height += font_extents.ascent + font_extents.descent + extents.y_advance + LINE_SPACING; pixmap_width = MAX (pixmap_width, extents.width + padding.left + padding.right); } if (self->priv->punctuation_text != NULL) { - cairo_text_extents (cr, self->priv->punctuation_text, &extents); + text_extents (cr, self->priv->punctuation_text, &extents); pixmap_height += font_extents.ascent + font_extents.descent + extents.y_advance + LINE_SPACING; pixmap_width = MAX (pixmap_width, extents.width + padding.left + padding.right); @@ -408,7 +519,7 @@ for (i = 0; i < n_sizes; i++) { cairo_set_font_size (cr, sizes[i]); cairo_font_extents (cr, &font_extents); - cairo_text_extents (cr, self->priv->sample_string, &extents); + text_extents (cr, self->priv->sample_string, &extents); pixmap_height += font_extents.ascent + font_extents.descent + extents.y_advance + LINE_SPACING; pixmap_width = MAX (pixmap_width, extents.width + padding.left + padding.right); @@ -529,7 +640,8 @@ for (i = 0; i < n_sizes; i++) { cairo_set_font_size (cr, sizes[i]); - draw_string (self, cr, padding, self->priv->sample_string, &pos_y); + if (self->priv->sample_string != NULL) + draw_string (self, cr, padding, self->priv->sample_string, &pos_y); if (pos_y > allocated_height) break; } diff -Naur sushi-3.18.0/src/libsushi/sushi-font-widget.h sushi-3.18.0-gst3/src/libsushi/sushi-font-widget.h --- sushi-3.18.0/src/libsushi/sushi-font-widget.h 2014-11-20 18:17:19.000000000 +0100 +++ sushi-3.18.0-gst3/src/libsushi/sushi-font-widget.h 2016-01-20 04:32:15.922830073 +0100 @@ -29,6 +29,7 @@ #include #include #include +#include G_BEGIN_DECLS diff -Naur sushi-3.18.0/src/libsushi/sushi-utils.c sushi-3.18.0-gst3/src/libsushi/sushi-utils.c --- sushi-3.18.0/src/libsushi/sushi-utils.c 2015-07-19 19:41:51.000000000 +0200 +++ sushi-3.18.0-gst3/src/libsushi/sushi-utils.c 2016-01-20 04:31:59.474401978 +0100 @@ -25,7 +25,11 @@ #include "sushi-utils.h" +#include + +#ifdef GDK_WINDOWING_X11 #include +#endif /** * sushi_create_foreign_window: @@ -36,10 +40,12 @@ GdkWindow * sushi_create_foreign_window (guint xid) { - GdkWindow *retval; + GdkWindow *retval = NULL; - retval = gdk_x11_window_foreign_new_for_display (gdk_display_get_default (), - xid); +#ifdef GDK_WINDOWING_X11 + if (GDK_IS_X11_DISPLAY (gdk_display_get_default ())) + retval = gdk_x11_window_foreign_new_for_display (gdk_display_get_default (), xid); +#endif return retval; }