[gnome-music] Add error symbol nearby the tracks, which cannot be played due to missing codecs. Also implements no



commit 33f0263d2d3fa4935d583d95e978b2984e748dfb
Author: Vadim Rutkovsky <vrutkovs redhat com>
Date:   Tue May 14 14:25:43 2013 +0200

    Add error symbol nearby the tracks, which cannot be played due to missing codecs. Also implements now 
playing icon status for Songs view
    
    https://bugzilla.gnome.org/show_bug.cgi?id=699762

 data/application.css |    5 ---
 src/player.js        |    2 +
 src/view.js          |   57 ++++++++++++++++++++++++++++++-----
 src/widgets.js       |   82 ++++++++++++++++++++++++++++++++++----------------
 4 files changed, 107 insertions(+), 39 deletions(-)
---
diff --git a/data/application.css b/data/application.css
index dc16ea0..107fbca 100644
--- a/data/application.css
+++ b/data/application.css
@@ -26,11 +26,6 @@
 }
 
 .songs-list {
-    border-width: 0 0 0 1px;
-    border-style: solid;
-    border-color: shade(@borders, 0.90);
-    padding: 0 1px;
-
     box-shadow: inset 0 -1px shade(@borders, 1.30);
     background-color: @theme_bg_color;
 }
diff --git a/src/player.js b/src/player.js
index 6368d78..874378a 100644
--- a/src/player.js
+++ b/src/player.js
@@ -24,6 +24,7 @@ const Lang = imports.lang;
 const Gtk = imports.gi.Gtk;
 const Gd = imports.gi.Gd;
 const Gst = imports.gi.Gst;
+const GstPbutils = imports.gi.GstPbutils;
 const GLib = imports.gi.GLib;
 const GObject = imports.gi.GObject;
 const Grl = imports.gi.Grl;
@@ -58,6 +59,7 @@ const Player = new Lang.Class({
         this.cache = AlbumArtCache.AlbumArtCache.getDefault();
 
         Gst.init(null, 0);
+        this.discoverer = new GstPbutils.Discoverer();
         this.player = Gst.ElementFactory.make("playbin", "player");
         this.bus = this.player.get_bus();
         this.bus.add_signal_watch();
diff --git a/src/view.js b/src/view.js
index 3fe4b5d..0a85a3c 100644
--- a/src/view.js
+++ b/src/view.js
@@ -41,6 +41,13 @@ const AlbumArtCache = imports.albumArtCache;
 const Grilo = imports.grilo;
 const albumArtCache = AlbumArtCache.AlbumArtCache.getDefault();
 
+const nowPlayingPixbuf = GdkPixbuf.Pixbuf.new_from_file_at_scale(
+        "/usr/share/icons/gnome/scalable/actions/media-playback-start-symbolic.svg",
+        -1, 16, true);
+const errorPixbuf = GdkPixbuf.Pixbuf.new_from_file_at_scale(
+        "/usr/share/icons/gnome/scalable/status/dialog-error-symbolic.svg",
+        -1, 16, true);
+
 function extractFileName(uri) {
     var exp = /^.*[\\\/]|[.][^.]*$/g;
     return unescape(uri.replace(exp, ''));
@@ -122,7 +129,8 @@ const ViewContainer = new Lang.Class({
             GObject.TYPE_STRING,
             GdkPixbuf.Pixbuf,
             GObject.TYPE_OBJECT,
-            GObject.TYPE_BOOLEAN
+            GObject.TYPE_BOOLEAN,
+            GdkPixbuf.Pixbuf,
         ]);
         this.view = new Gd.MainView({
             shadow_type:    Gtk.ShadowType.NONE
@@ -212,11 +220,22 @@ const ViewContainer = new Lang.Class({
             if ((item.get_title() == null) && (item.get_url() != null)) {
                 item.set_title (extractFileName(item.get_url()));
             }
-            this._model.set(
-                    iter,
-                    [0, 1, 2, 3, 4, 5],
-                    [toString(item.get_id()), "", item.get_title(), artist, this._symbolicIcon, item]
-                );
+            try{
+                if (item.get_url())
+                    this.player.discoverer.discover_uri(item.get_url());
+                this._model.set(
+                        iter,
+                        [0, 1, 2, 3, 4, 5, 6, 7],
+                        [toString(item.get_id()), "", item.get_title(), artist, this._symbolicIcon, item, 
false, nowPlayingPixbuf]
+                    );
+            } catch(err) {
+                log("failed to discover url " + item.get_url());
+                this._model.set(
+                        iter,
+                        [0, 1, 2, 3, 4, 5, 6, 7],
+                        [toString(item.get_id()), "", item.get_title(), artist, this._symbolicIcon, item, 
true, errorPixbuf]
+                    );
+            }
             GLib.idle_add(300, Lang.bind(this, this._updateAlbumArt, item, iter));
         }
     },
@@ -346,11 +365,24 @@ const Songs = new Lang.Class({
         this._symbolicIcon = albumArtCache.makeDefaultIcon(this._iconHeight, this._iconWidth)
         this._addListRenderers();
         this.player = player;
+        this.player.connect('playlist-item-changed', Lang.bind(this, this.updateModel));
     },
 
     _onItemActivated: function (widget, id, path) {
-        this.player.setPlaylist("Songs", null, this._model, this._model.get_iter(path)[1], 5);
-        this.player.setPlaying(true);
+        var iter = this._model.get_iter(path)[1]
+        if (this._model.get_value(iter, 7) != errorPixbuf) {
+            this.player.setPlaylist("Songs", null, this._model, iter, 5);
+            this.player.setPlaying(true);
+        }
+    },
+
+    updateModel: function(player, playlist, currentIter){
+        if (this.iterToClean){
+            this._model.set_value(this.iterToClean, 6, false);
+        }
+        this._model.set_value(currentIter, 6, true);
+        this.iterToClean = currentIter.copy();
+        return false;
     },
 
     _addItem: function(source, param, item) {
@@ -360,6 +392,15 @@ const Songs = new Lang.Class({
     _addListRenderers: function() {
         let listWidget = this.view.get_generic_view();
 
+        let nowPlayingSymbolRenderer = new Gtk.CellRendererPixbuf({ xpad: 0 });
+        var columnNowPlaying = new Gtk.TreeViewColumn();
+        nowPlayingSymbolRenderer.set_property("xalign", 1.0);
+        columnNowPlaying.pack_start(nowPlayingSymbolRenderer, false)
+        columnNowPlaying.set_property('fixed-width', 24)
+        columnNowPlaying.add_attribute(nowPlayingSymbolRenderer, "visible", 6);
+        columnNowPlaying.add_attribute(nowPlayingSymbolRenderer, "pixbuf", 7);
+        listWidget.insert_column(columnNowPlaying, 0)
+
         let typeRenderer =
             new Gd.StyledTextRenderer({ xpad: 0 });
         typeRenderer.add_class('dim-label');
diff --git a/src/widgets.js b/src/widgets.js
index 21aef63..9486c28 100644
--- a/src/widgets.js
+++ b/src/widgets.js
@@ -38,6 +38,9 @@ const albumArtCache = AlbumArtCache.AlbumArtCache.getDefault();
 const nowPlayingPixbuf = GdkPixbuf.Pixbuf.new_from_file_at_scale(
         "/usr/share/icons/gnome/scalable/actions/media-playback-start-symbolic.svg",
         -1, 16, true);
+const errorPixbuf = GdkPixbuf.Pixbuf.new_from_file_at_scale(
+        "/usr/share/icons/gnome/scalable/status/dialog-error-symbolic.svg",
+        -1, 16, true);
 
 const AlbumWidget = new Lang.Class({
     Name: "AlbumWidget",
@@ -59,15 +62,18 @@ const AlbumWidget = new Lang.Class({
         this.album=null;
         this.view.connect('item-activated', Lang.bind(this,
             function(widget, id, path) {
-                this.player.stop();
-                if (this.iterToClean && this.player.playlistId == this.album){
-                    let item = this.model.get_value(this.iterToClean, 5);
-                    this.model.set_value(this.iterToClean, 0, item.get_title());
-                    // Hide now playing icon
-                    this.model.set_value(this.iterToClean, 3, false);
+                let iter = this.model.get_iter(path)[1];
+                if (this.model.get_value(iter, 4) != errorPixbuf) {
+                    this.player.stop();
+                    if (this.iterToClean && this.player.playlistId == this.album){
+                        let item = this.model.get_value(this.iterToClean, 5);
+                        this.model.set_value(this.iterToClean, 0, item.get_title());
+                        // Hide now playing icon
+                        this.model.set_value(this.iterToClean, 3, false);
+                    }
+                    this.player.setPlaylist("Album", this.album, this.model, iter, 5);
+                    this.player.setPlaying(true);
                 }
-                this.player.setPlaylist("Album", this.album, this.model, this.model.get_iter(path)[1], 5);
-                this.player.setPlaying(true);
             })
         );
 
@@ -99,13 +105,13 @@ const AlbumWidget = new Lang.Class({
         cells[1].visible = false
 
         let nowPlayingSymbolRenderer = new Gtk.CellRendererPixbuf({ xpad: 0 });
-        nowPlayingSymbolRenderer.pixbuf = nowPlayingPixbuf;
 
         var columnNowPlaying = new Gtk.TreeViewColumn();
         nowPlayingSymbolRenderer.set_property("xalign", 1.0);
         columnNowPlaying.pack_start(nowPlayingSymbolRenderer, false)
         columnNowPlaying.set_property('fixed-width', 24)
         columnNowPlaying.add_attribute(nowPlayingSymbolRenderer, "visible", 3);
+        columnNowPlaying.add_attribute(nowPlayingSymbolRenderer, "pixbuf", 4);
         listWidget.insert_column(columnNowPlaying, 0)
 
         let typeRenderer =
@@ -153,7 +159,7 @@ const AlbumWidget = new Lang.Class({
                 GObject.TYPE_STRING,
                 GObject.TYPE_STRING,
                 GObject.TYPE_BOOLEAN,/*icon shown*/
-                GdkPixbuf.Pixbuf,    /*icon*/
+                GdkPixbuf.Pixbuf,    /*icon to display*/
                 GObject.TYPE_OBJECT, /*song object*/
                 GObject.TYPE_BOOLEAN
             ]);
@@ -163,14 +169,22 @@ const AlbumWidget = new Lang.Class({
                     tracks.push(track);
                     duration = duration + track.get_duration();
                     let iter = this.model.append();
-                    let path = "/usr/share/icons/gnome/scalable/actions/media-playback-start-symbolic.svg";
-                    let pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_scale(path, -1, 16, true);
-                    let escapedTitle = GLib.markup_escape_text(track.get_title(), -1);
-                    this.model.set(iter,
-                        [0, 1, 2, 3, 4, 5],
-                        [ escapedTitle, "", "", false, nowPlayingPixbuf, track ]);
+                    let escapedTitle = GLib.markup_escape_text(track.get_title(), track.get_title().length);
+                    try{
+                        this.player.discoverer.discover_uri(track.get_url());
+                        this.model.set(iter,
+                            [0, 1, 2, 3, 4, 5],
+                            [ escapedTitle, "", "", false, nowPlayingPixbuf, track ]);
+                    } catch(err) {
+                        log("failed to discover url " + track.get_url());
+                        this.model.set(iter,
+                            [0, 1, 2, 3, 4, 5],
+                            [ escapedTitle, "", "", true, errorPixbuf, track ]);
+                    }
+
                     this.ui.get_object("running_length_label_info").set_text(
                         (parseInt(duration/60) + 1) + " min");
+
                     this.emit("track-added")
                 }
             }));
@@ -283,6 +297,9 @@ const ArtistAlbums = new Lang.Class({
             let song = playlist.get_value(iter, 5);
             let songWidget = song.songWidget;
 
+            if (!songWidget.can_be_played)
+                continue
+
             let escapedTitle = GLib.markup_escape_text(song.get_title(), -1);
             if (song == currentSong){
                 songWidget.nowPlayingSign.show();
@@ -307,7 +324,8 @@ const ArtistAlbums = new Lang.Class({
             let song = this.model.get_value(iter, 5);
             let songWidget = song.songWidget;
             let escapedTitle = GLib.markup_escape_text(song.get_title(), -1);
-            songWidget.nowPlayingSign.hide();
+            if (songWidget.can_be_played)
+                songWidget.nowPlayingSign.hide();
             songWidget.title.set_markup("<span>" + escapedTitle + "</span>");
         } while(this.model.iter_next(iter));
         return false;
@@ -365,18 +383,30 @@ const ArtistAlbumWidget = new Lang.Class({
                         parseInt((i)%(this.tracks.length/2)), 1, 1);
                     track.songWidget = songWidget;
                     let iter = model.append();
-                    model.set(iter,
-                            [0, 1, 2, 3, 4, 5],
-                            [ track.get_title(), "", "", false, pixbuf, track]);
-
                     songWidget.iter = iter;
                     songWidget.model = model;
-                    songWidget.connect('button-release-event', Lang.bind(
-                                                            this, this.trackSelected));
                     songWidget.title = ui.get_object("title");
-                    songWidget.nowPlayingSign = ui.get_object("image1");
-                    songWidget.nowPlayingSign.set_from_pixbuf(nowPlayingPixbuf);
-                    songWidget.nowPlayingSign.set_no_show_all("true");
+
+                    try{
+                        this.player.discoverer.discover_uri(track.get_url());
+                        model.set(iter,
+                            [0, 1, 2, 3, 4, 5],
+                            [ track.get_title(), "", "", false, nowPlayingPixbuf, track]);
+                        songWidget.nowPlayingSign = ui.get_object("image1");
+                        songWidget.nowPlayingSign.set_from_pixbuf(nowPlayingPixbuf);
+                        songWidget.nowPlayingSign.set_no_show_all("true");
+                        songWidget.can_be_played = true;
+                        songWidget.connect('button-release-event', Lang.bind(
+                                                                this, this.trackSelected));
+                    } catch(err) {
+                        log("failed to discover url " + track.get_url());
+                        this.model.set(iter,
+                            [0, 1, 2, 3, 4, 5],
+                            [ track.get_title(), "", "", true, errorPixbuf, track ]);
+                        songWidget.nowPlayingSign = ui.get_object("image1");
+                        songWidget.nowPlayingSign.set_from_pixbuf(errorPixbuf);
+                        songWidget.can_be_played = false;
+                    }
                 }
                 this.ui.get_object("grid1").show_all();
                 this.emit("tracks-loaded");


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