[gnome-music] Make loading of cover art asynchronous



commit e579c2344ab194d7d0b4db1a6b945d8d4845c22f
Author: Arnel A. Borja <kyoushuu yahoo com>
Date:   Sat Jun 1 14:10:39 2013 +0800

    Make loading of cover art asynchronous
    
    https://bugzilla.gnome.org/show_bug.cgi?id=700443

 src/albumArtCache.js |   71 ++++++++++++++++++++++++++++++++++---------------
 src/player.js        |   11 +++++--
 src/view.js          |   56 +++++++++++++++++++++------------------
 src/widgets.js       |   68 ++++++++++++++++++++++++++---------------------
 4 files changed, 125 insertions(+), 81 deletions(-)
---
diff --git a/src/albumArtCache.js b/src/albumArtCache.js
index 5390d61..91e906f 100644
--- a/src/albumArtCache.js
+++ b/src/albumArtCache.js
@@ -52,9 +52,55 @@ const AlbumArtCache = new Lang.Class({
         }
     },
 
-    lookup: function(size, artist, album) {
-        var key, path;
+    _tryLoad: function(size, artist, album, i, callback) {
+        var key, path, file;
 
+        if (i >= this._keybuilder_funcs.length) {
+            callback(null);
+            return;
+        }
+
+        key = this._keybuilder_funcs[i].call(this, artist, album);
+        path = GLib.build_filenamev([this.cacheDir, key + ".jpeg"]);
+        file = Gio.File.new_for_path(path);
+
+        file.read_async(GLib.PRIORITY_DEFAULT, null, Lang.bind(this,
+            function(object, res) {
+                try {
+                    let stream = object.read_finish(res);
+                    GdkPixbuf.Pixbuf.new_from_stream_async(stream, null, Lang.bind(this,
+                        function(source, res) {
+                            try {
+                                let pixbuf = GdkPixbuf.Pixbuf.new_from_stream_finish(res),
+                                    width = pixbuf.get_width(),
+                                    height = pixbuf.get_height();
+                                if (width >= size || height >= size) {
+                                    let scale = Math.max(width, height)/size;
+                                    callback(pixbuf.scale_simple(width/scale, height/scale, 2));
+
+                                    return;
+                                }
+                            }
+                            catch (error) {
+                                if (this.logLookupErrors)
+                                    print ("ERROR:", error);
+                            }
+
+                            this._tryLoad(size, artist, album, ++i, callback);
+                        }));
+
+                    return;
+                }
+                catch (error) {
+                    if (this.logLookupErrors)
+                        print ("ERROR:", error);
+                }
+
+                this._tryLoad(size, artist, album, ++i, callback);
+            }));
+    },
+
+    lookup: function(size, artist, album, callback) {
         if (artist == null) {
             artist = " ";
         }
@@ -63,26 +109,7 @@ const AlbumArtCache = new Lang.Class({
             album = " ";
         }
 
-        for (var i = 0; i < this._keybuilder_funcs.length; i++)
-        {
-            try {
-                key = this._keybuilder_funcs[i].call (this, artist, album);
-                path = GLib.build_filenamev([this.cacheDir, key + ".jpeg"]);
-                let pixbuf = GdkPixbuf.Pixbuf.new_from_file(path),
-                    width = pixbuf.get_width(),
-                    height = pixbuf.get_height();
-                if (width >= size || height >= size) {
-                    let scale = Math.max(width, height)/size;
-                    return pixbuf.scale_simple(width/scale, height/scale, 2);
-                }
-            }
-            catch (error) {
-                if (this.logLookupErrors)
-                    print ("ERROR:", error);
-            }
-        }
-
-        return null;
+        this._tryLoad(size, artist, album, 0, callback);
     },
 
     normalizeAndHash: function(input, utf8Only, utf8) {
diff --git a/src/player.js b/src/player.js
index f6ce1dd..18c4b05 100644
--- a/src/player.js
+++ b/src/player.js
@@ -56,6 +56,7 @@ const Player = new Lang.Class({
         this._lastState = Gst.State.PAUSED;
         this.repeat = RepeatType.NONE;
         this.cache = AlbumArtCache.AlbumArtCache.getDefault();
+        this._symbolicIcon = this.cache.makeDefaultIcon(ART_SIZE, ART_SIZE);
 
         Gst.init(null, 0);
         this.discoverer = new GstPbutils.Discoverer();
@@ -132,7 +133,6 @@ const Player = new Lang.Class({
     },
 
     load: function(media) {
-        var pixbuf;
         this._setDuration(media.get_duration());
         this.songTotalTimeLabel.set_label(this.secondsToString (media.get_duration()));
         this.progressScale.sensitive = true;
@@ -149,8 +149,13 @@ const Player = new Lang.Class({
             this.prevBtn.set_sensitive(true);
         else
             this.prevBtn.set_sensitive(false);
-        pixbuf = this.cache.lookup (ART_SIZE, media.get_artist (), media.get_string(Grl.METADATA_KEY_ALBUM));
-        this.coverImg.set_from_pixbuf (pixbuf);
+        this.coverImg.set_from_pixbuf(this._symbolicIcon);
+        this.cache.lookup(ART_SIZE, media.get_artist(), media.get_string(Grl.METADATA_KEY_ALBUM), 
Lang.bind(this,
+            function(pixbuf) {
+                if (pixbuf != null) {
+                    this.coverImg.set_from_pixbuf(pixbuf);
+                }
+            }));
 
         if (media.get_title() != null) {
             this.titleLabel.set_label(media.get_title());
diff --git a/src/view.js b/src/view.js
index 5a62618..3f4aff9 100644
--- a/src/view.js
+++ b/src/view.js
@@ -216,33 +216,37 @@ const ViewContainer = new Lang.Class({
             artist = item.get_author();
         if (item.get_string(Grl.METADATA_KEY_ARTIST) != null)
             artist = item.get_string(Grl.METADATA_KEY_ARTIST)
-        var icon = albumArtCache.lookup(this._iconHeight, artist, item.get_string(Grl.METADATA_KEY_ALBUM));
-        if (icon != null) {
-            icon = albumArtCache.makeIconFrame(icon)
-            this._model.set_value(iter, 4, icon);
-            return false;
-        }
-        var options = Grl.OperationOptions.new(null);
-        options.set_flags (Grl.ResolutionFlags.FULL | Grl.ResolutionFlags.IDLE_RELAY);
-        grilo.tracker.resolve(
-            item,
-            [Grl.METADATA_KEY_THUMBNAIL],
-            options,
-            Lang.bind(this,
-            function(source, param, item) {
-                var uri = item.get_thumbnail();
-                albumArtCache.getFromUri(uri,
-                    artist,
-                    item.get_string(Grl.METADATA_KEY_ALBUM),
-                    this._iconWidth,
-                    this._iconHeight,
-                    Lang.bind(this,
-                        function (icon) {
-                            icon = albumArtCache.makeIconFrame(icon);
-                            this._model.set_value(iter, 4, icon);
-                        }))
+        albumArtCache.lookup(this._iconHeight, artist, item.get_string(Grl.METADATA_KEY_ALBUM), 
Lang.bind(this,
+            function(icon) {
+                if (icon != null) {
+                    icon = albumArtCache.makeIconFrame(icon)
+                    this._model.set_value(iter, 4, icon);
+                    this.emit("album-art-updated");
+                }
+                else {
+                    var options = Grl.OperationOptions.new(null);
+                    options.set_flags(Grl.ResolutionFlags.FULL | Grl.ResolutionFlags.IDLE_RELAY);
+                    grilo.tracker.resolve(
+                        item,
+                        [Grl.METADATA_KEY_THUMBNAIL],
+                        options,
+                        Lang.bind(this,
+                        function(source, param, item) {
+                            var uri = item.get_thumbnail();
+                            albumArtCache.getFromUri(uri,
+                                artist,
+                                item.get_string(Grl.METADATA_KEY_ALBUM),
+                                this._iconWidth,
+                                this._iconHeight,
+                                Lang.bind(this,
+                                    function(icon) {
+                                        icon = albumArtCache.makeIconFrame(icon);
+                                        this._model.set_value(iter, 4, icon);
+                                        this.emit("album-art-updated");
+                                    }))
+                        }));
+                }
             }));
-        this.emit("album-art-updated");
         return false;
     },
 
diff --git a/src/widgets.js b/src/widgets.js
index ce92498..2b1e724 100644
--- a/src/widgets.js
+++ b/src/widgets.js
@@ -100,6 +100,7 @@ const AlbumWidget = new Lang.Class({
         this.player = player;
         this.hbox = new Gtk.HBox ();
         this.iterToClean = null;
+        this._symbolicIcon = albumArtCache.makeDefaultIcon(256, 256);
 
         this.ui = new Gtk.Builder();
         this.ui.add_from_resource('/org/gnome/music/AlbumWidget.ui');
@@ -207,10 +208,6 @@ const AlbumWidget = new Lang.Class({
         }
         let duration = 0;
         this.album = album;
-        let pixbuf = albumArtCache.lookup (256, artist, item.get_string(Grl.METADATA_KEY_ALBUM));
-        if (pixbuf == null)
-            pixbuf = albumArtCache.makeDefaultIcon(256, 256);
-        this.ui.get_object("cover").set_from_pixbuf (pixbuf);
 
         // if the active queue has been set by this album,
         // use it as model, otherwise build the liststore
@@ -236,19 +233,28 @@ const AlbumWidget = new Lang.Class({
                     duration = duration + track.get_duration();
                     let iter = this.model.append();
                     let escapedTitle = GLib.markup_escape_text(track.get_title(), track.get_title().length);
+                    this.ui.get_object("cover").set_from_pixbuf(this._symbolicIcon);
                     try{
                         this.player.discoverer.discover_uri(track.get_url());
                         this.model.set(iter,
                             [0, 1, 2, 3, 4, 5, 6, 7],
-                            [ escapedTitle, "", "", "", pixbuf, track, false, nowPlayingIconName ]);
+                            [ escapedTitle, "", "", "", this._symbolicIcon, track, false, nowPlayingIconName 
]);
                     } catch(err) {
                         log(err.message);
                         log("failed to discover url " + track.get_url());
                         this.model.set(iter,
                             [0, 1, 2, 3, 4, 5, 6, 7],
-                            [ escapedTitle, "", "", "", pixbuf, track, true, errorIconName ]);
+                            [ escapedTitle, "", "", "", this._symbolicIcon, track, true, errorIconName ]);
                     }
 
+                    albumArtCache.lookup(256, artist, item.get_string(Grl.METADATA_KEY_ALBUM), 
Lang.bind(this,
+                        function(pixbuf) {
+                            if (pixbuf != null) {
+                                this.ui.get_object("cover").set_from_pixbuf(pixbuf);
+                                this.model.set(iter, [4], [pixbuf]);
+                            }
+                        }));
+
                     this.ui.get_object("running_length_label_info").set_text(
                         (parseInt(duration/60) + 1) + " min");
 
@@ -576,31 +582,33 @@ const ArtistAlbumWidget = new Lang.Class({
     },
 
     _updateAlbumArt: function() {
-        let pixbuf = albumArtCache.lookup (128, this.artist, this.album.get_title());
-        if (pixbuf != null)
-            this.ui.get_object("cover").set_from_pixbuf(pixbuf);
-        else {
-            var options = Grl.OperationOptions.new(null);
-            options.set_flags (Grl.ResolutionFlags.FULL | Grl.ResolutionFlags.IDLE_RELAY);
-            grilo.tracker.resolve(
-                this.album,
-                [Grl.METADATA_KEY_THUMBNAIL],
-                options,
-                Lang.bind(this,
-                function(source, param, item) {
-                    var uri = this.album.get_thumbnail();
-                    albumArtCache.getFromUri(uri,
-                        this.artist,
-                        this.album.get_title(),
-                        128,
-                        128,
+        albumArtCache.lookup(128, this.artist, this.album.get_title(), Lang.bind(this,
+            function(pixbuf) {
+                if (pixbuf != null)
+                    this.ui.get_object("cover").set_from_pixbuf(pixbuf);
+                else {
+                    var options = Grl.OperationOptions.new(null);
+                    options.set_flags(Grl.ResolutionFlags.FULL | Grl.ResolutionFlags.IDLE_RELAY);
+                    grilo.tracker.resolve(
+                        this.album,
+                        [Grl.METADATA_KEY_THUMBNAIL],
+                        options,
                         Lang.bind(this,
-                            function (pixbuf) {
-                                pixbuf = albumArtCache.makeIconFrame(pixbuf);
-                                this.ui.get_object("cover").set_from_pixbuf(pixbuf);
-                            }))
-                }));
-        }
+                        function(source, param, item) {
+                            var uri = this.album.get_thumbnail();
+                            albumArtCache.getFromUri(uri,
+                                this.artist,
+                                this.album.get_title(),
+                                128,
+                                128,
+                                Lang.bind(this,
+                                    function(pixbuf) {
+                                        pixbuf = albumArtCache.makeIconFrame(pixbuf);
+                                        this.ui.get_object("cover").set_from_pixbuf(pixbuf);
+                                    }))
+                        }));
+                }
+            }));
     },
 
     trackSelected: function(widget, iter) {


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]