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



commit 9f858bafe414b76eff50ebd2c6639b10c2db9fd7
Author: Vadim Rutkovsky <vrutkovs redhat com>
Date:   Fri May 17 13:22:49 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/AlbumWidget.ui       |    4 +-
 data/ArtistAlbumWidget.ui |    4 +-
 data/application.css      |    5 --
 src/player.js             |    3 +-
 src/view.js               |   55 ++++++++++++++++++++---
 src/widgets.js            |  107 ++++++++++++++++++++++++++-------------------
 6 files changed, 115 insertions(+), 63 deletions(-)
---
diff --git a/data/AlbumWidget.ui b/data/AlbumWidget.ui
index b11333c..5573fc0 100644
--- a/data/AlbumWidget.ui
+++ b/data/AlbumWidget.ui
@@ -218,8 +218,8 @@
       <column type="gchararray"/>
       <!-- column-name gboolean1 -->
       <column type="gboolean"/>
-      <!-- column-name GdkPixbuf1 -->
-      <column type="GdkPixbuf"/>
+      <!-- column-name gchararray4 -->
+      <column type="gchararray"/>
       <!-- column-name GObject1 -->
       <column type="GObject"/>
       <!-- column-name gboolean2 -->
diff --git a/data/ArtistAlbumWidget.ui b/data/ArtistAlbumWidget.ui
index cf84412..f6c4115 100644
--- a/data/ArtistAlbumWidget.ui
+++ b/data/ArtistAlbumWidget.ui
@@ -126,8 +126,8 @@
       <column type="gchararray"/>
       <!-- column-name gboolean1 -->
       <column type="gboolean"/>
-      <!-- column-name GdkPixbuf1 -->
-      <column type="GdkPixbuf"/>
+      <!-- column-name gchararray4 -->
+      <column type="gchararray"/>
       <!-- column-name GObject1 -->
       <column type="GObject"/>
       <!-- column-name gboolean2 -->
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 552eaa6..0715fd5 100644
--- a/src/player.js
+++ b/src/player.js
@@ -24,10 +24,10 @@ 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;
-const GdkPixbug = imports.gi.GdkPixbuf;
 const Signals = imports.signals;
 const Gdk = imports.gi.Gdk;
 
@@ -58,6 +58,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 8085651..08a0781 100644
--- a/src/view.js
+++ b/src/view.js
@@ -41,6 +41,9 @@ const AlbumArtCache = imports.albumArtCache;
 const Grilo = imports.grilo;
 const albumArtCache = AlbumArtCache.AlbumArtCache.getDefault();
 
+const nowPlayingIconName = 'media-playback-start-symbolic';
+const errorIconName = 'dialog-error-symbolic';
+
 function extractFileName(uri) {
     var exp = /^.*[\\\/]|[.][^.]*$/g;
     return unescape(uri.replace(exp, ''));
@@ -122,7 +125,8 @@ const ViewContainer = new Lang.Class({
             GObject.TYPE_STRING,
             GdkPixbuf.Pixbuf,
             GObject.TYPE_OBJECT,
-            GObject.TYPE_BOOLEAN
+            GObject.TYPE_BOOLEAN,
+            GObject.TYPE_STRING,
         ]);
         this.view = new Gd.MainView({
             shadow_type:    Gtk.ShadowType.NONE
@@ -223,11 +227,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, nowPlayingIconName]
+                    );
+            } 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, errorIconName]
+                    );
+            }
             GLib.idle_add(300, Lang.bind(this, this._updateAlbumArt, item, iter));
         }
     },
@@ -357,11 +372,26 @@ 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, 4) != errorIconName) {
+            this.player.setPlaylist("Songs", null, this._model, iter, 5);
+            this.player.setPlaying(true);
+        }
+    },
+
+    updateModel: function(player, playlist, currentIter){
+        if (playlist != this._model){
+            return false;}
+        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) {
@@ -371,6 +401,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, "icon_name", 4);
+        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 083f97d..4075424 100644
--- a/src/widgets.js
+++ b/src/widgets.js
@@ -21,7 +21,6 @@
 const Gtk = imports.gi.Gtk;
 const Gdk = imports.gi.Gdk;
 const Gd = imports.gi.Gd;
-const GdkPixbuf = imports.gi.GdkPixbuf;
 const Gio = imports.gi.Gio;
 const GLib = imports.gi.GLib;
 const GObject = imports.gi.GObject;
@@ -35,9 +34,8 @@ const grilo = Grilo.grilo;
 const AlbumArtCache = imports.albumArtCache;
 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 nowPlayingIconName = 'media-playback-start-symbolic';
+const errorIconName = 'dialog-error-symbolic';
 
 const AlbumWidget = new Lang.Class({
     Name: "AlbumWidget",
@@ -59,15 +57,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) != errorIconName) {
+                    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,15 +100,15 @@ 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);
         nowPlayingSymbolRenderer.set_property("yalign", 0.6);
-        columnNowPlaying.pack_start(nowPlayingSymbolRenderer, false)
-        columnNowPlaying.set_property('fixed-width', 24)
+        columnNowPlaying.pack_start(nowPlayingSymbolRenderer, false);
+        columnNowPlaying.set_property('fixed-width', 24);
         columnNowPlaying.add_attribute(nowPlayingSymbolRenderer, "visible", 3);
-        listWidget.insert_column(columnNowPlaying, 0)
+        columnNowPlaying.add_attribute(nowPlayingSymbolRenderer, "icon_name", 4);
+        listWidget.insert_column(columnNowPlaying, 0);
 
         let typeRenderer =
             new Gd.StyledTextRenderer({ xpad: 16 });
@@ -120,8 +121,7 @@ const AlbumWidget = new Lang.Class({
         cols[0].clear_attributes(typeRenderer);
         cols[0].add_attribute(typeRenderer, "markup", 0);
 
-        let durationRenderer =
-            new Gd.StyledTextRenderer({ xpad: 16 });
+        let durationRenderer = new Gd.StyledTextRenderer({ xpad: 16 });
         durationRenderer.add_class('dim-label');
         durationRenderer.set_property("ellipsize", 3);
         durationRenderer.set_property("xalign", 1.0);
@@ -134,6 +134,7 @@ const AlbumWidget = new Lang.Class({
                 durationRenderer.text = this.player.secondsToString(duration);
             }));
     },
+
     update: function (artist, album, item) {
         let released_date = item.get_publication_date();
         if (released_date != null) {
@@ -149,29 +150,28 @@ const AlbumWidget = new Lang.Class({
             this.model = cachedPlaylist;
             this.updateModel(this.player, cachedPlaylist, this.player.currentTrack);
         } else {
-            this.model = Gtk.ListStore.new([
-                GObject.TYPE_STRING, /*title*/
-                GObject.TYPE_STRING,
-                GObject.TYPE_STRING,
-                GObject.TYPE_BOOLEAN,/*icon shown*/
-                GdkPixbuf.Pixbuf,    /*icon*/
-                GObject.TYPE_OBJECT, /*song object*/
-                GObject.TYPE_BOOLEAN
-            ]);
             var tracks = [];
             grilo.getAlbumSongs(item.get_id(), Lang.bind(this, function (source, prefs, track) {
                 if (track != null) {
                     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, nowPlayingIconName, track ]);
+                    } catch(err) {
+                        log("failed to discover url " + track.get_url());
+                        this.model.set(iter,
+                            [0, 1, 2, 3, 4, 5],
+                            [ escapedTitle, "", "", true, errorIconName, track ]);
+                    }
+
                     this.ui.get_object("running_length_label_info").set_text(
                         (parseInt(duration/60) + 1) + " min");
+
                     this.emit("track-added")
                 }
             }));
@@ -247,7 +247,7 @@ const ArtistAlbums = new Lang.Class({
                 GObject.TYPE_STRING,
                 GObject.TYPE_STRING,
                 GObject.TYPE_BOOLEAN,/*icon shown*/
-                GdkPixbuf.Pixbuf,    /*icon*/
+                GObject.TYPE_STRING, /*icon*/
                 GObject.TYPE_OBJECT, /*song object*/
                 GObject.TYPE_BOOLEAN
                 ]);
@@ -284,6 +284,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();
@@ -308,7 +311,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,19 +369,32 @@ 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_alignment(0.0,0.6);
-                    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, nowPlayingIconName, track]);
+                        songWidget.nowPlayingSign = ui.get_object("image1");
+                        songWidget.nowPlayingSign.set_from_icon_name(nowPlayingIconName, 
Gtk.IconSize.BUTTON);
+                        songWidget.nowPlayingSign.set_no_show_all("true");
+                        songWidget.nowPlayingSign.set_alignment(0.0,0.6);
+                        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, errorIconName, track ]);
+                        songWidget.nowPlayingSign = ui.get_object("image1");
+                        songWidget.nowPlayingSign.set_from_icon_name(errorIconName, Gtk.IconSize.BUTTON);
+                        songWidget.nowPlayingSign.set_alignment(0.0,0.6);
+                        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]