ayatana-commits team mailing list archive
-
ayatana-commits team
-
Mailing list archive
-
Message #02208
[Merge] lp:~cjcurran/indicator-sound/remote-art-handling into lp:indicator-sound
Conor Curran has proposed merging lp:~cjcurran/indicator-sound/remote-art-handling into lp:indicator-sound.
Requested reviews:
Indicator Applet Developers (indicator-applet-developers)
Related bugs:
#627505 Crashes if Rhythmbox is playing from Last.FM
https://bugs.launchpad.net/bugs/627505
- Deals with last fm plugin for rhythmbox which uses remote artwork. Dynamically remote artwork will now be fetched asynchronously, rounded and exposed.
--
https://code.launchpad.net/~cjcurran/indicator-sound/remote-art-handling/+merge/34396
Your team ayatana-commits is subscribed to branch lp:indicator-sound.
=== modified file 'src/Makefile.am'
--- src/Makefile.am 2010-08-27 11:25:47 +0000
+++ src/Makefile.am 2010-09-02 10:31:05 +0000
@@ -67,7 +67,9 @@
player-controller.vala \
mpris2-controller.vala \
player-item.vala \
- familiar-players-db.vala
+ familiar-players-db.vala \
+ fetch-file.vala
+
music_bridge_VALAFLAGS = \
--ccode \
@@ -81,7 +83,9 @@
--pkg Dbusmenu-Glib-0.2 \
--pkg common-defs \
--pkg dbus-glib-1 \
- --pkg gio-unix-2.0
+ --pkg gio-unix-2.0 \
+ --pkg gdk-pixbuf-2.0
+
$(MAINTAINER_VALAFLAGS)
=== modified file 'src/common-defs.h'
--- src/common-defs.h 2010-08-24 15:22:35 +0000
+++ src/common-defs.h 2010-09-02 10:31:05 +0000
@@ -25,6 +25,7 @@
#define SIGNAL_SINK_AVAILABLE_UPDATE "SinkAvailableUpdate"
#define DBUSMENU_PROPERTY_EMPTY -1
+#define DBUSMENU_PLAYER_ITEM_REMOTE_FILEPATH "/tmp/indicator-sound-downloaded-album-art"
/* DBUS Custom Items */
#define DBUSMENU_VOLUME_MENUITEM_TYPE "x-canonical-ido-volume-type"
=== added file 'src/fetch-file.vala'
--- src/fetch-file.vala 1970-01-01 00:00:00 +0000
+++ src/fetch-file.vala 2010-09-02 10:31:05 +0000
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2010 Canonical, Ltd.
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License
+ * version 3.0 as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3.0 for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Authors
+ * Gordon Allott <gord.allott@xxxxxxxxxxxxx>
+ * Conor Curran <conor.curran@xxxxxxxxxxxxx>
+ */
+
+public class FetchFile : Object
+{
+ /* public variables */
+ public string uri {get; construct;}
+ public string intended_property {get; construct;}
+
+ /* private variables */
+ private DataInputStream stream;
+ private File? file;
+ private ByteArray data;
+
+ /* public signals */
+ public signal void failed ();
+ public signal void completed (ByteArray data, string property);
+
+ public FetchFile (string uri, string prop)
+ {
+ Object (uri: uri, intended_property: prop);
+ }
+
+ construct
+ {
+ this.file = File.new_for_uri(this.uri);
+ this.data = new ByteArray ();
+ }
+
+ public async void fetch_data ()
+ {
+ try {
+ this.stream = new DataInputStream(this.file.read(null));
+ this.stream.set_byte_order (DataStreamByteOrder.LITTLE_ENDIAN);
+ } catch (GLib.Error e) {
+ this.failed ();
+ }
+ this.read_something_async ();
+ }
+
+ private async void read_something_async ()
+ {
+ ssize_t size = 1024;
+ uint8[] buffer = new uint8[size];
+
+ ssize_t bufsize = 1;
+ do {
+ try {
+ bufsize = yield this.stream.read_async (buffer, size, GLib.Priority.DEFAULT, null);
+ if (bufsize < 1) { break;}
+
+ if (bufsize != size)
+ {
+ uint8[] cpybuf = new uint8[bufsize];
+ Memory.copy (cpybuf, buffer, bufsize);
+ this.data.append (cpybuf);
+ }
+ else
+ {
+ this.data.append (buffer);
+ }
+ } catch (Error e) {
+ this.failed ();
+ }
+ } while (bufsize > 0);
+ this.completed (this.data, this.intended_property);
+ }
+}
=== modified file 'src/metadata-menu-item.vala'
--- src/metadata-menu-item.vala 2010-08-24 16:59:15 +0000
+++ src/metadata-menu-item.vala 2010-09-02 10:31:05 +0000
@@ -17,7 +17,6 @@
with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-using Dbusmenu;
using Gee;
using DbusmenuMetadata;
=== modified file 'src/metadata-widget.c'
--- src/metadata-widget.c 2010-08-25 19:29:39 +0000
+++ src/metadata-widget.c 2010-09-02 10:31:05 +0000
@@ -36,6 +36,7 @@
GtkWidget* album_art;
GString* image_path;
GString* old_image_path;
+ GString* remote_image_path;
GtkWidget* artist_label;
GtkWidget* piece_label;
GtkWidget* container_label;
@@ -69,7 +70,7 @@
MetadataWidget* metadata,
GdkPixbuf *source);
-
+static void draw_album_art_placeholder(GtkWidget *metadata);
G_DEFINE_TYPE (MetadataWidget, metadata_widget, GTK_TYPE_MENU_ITEM);
@@ -104,6 +105,7 @@
priv->album_art = gtk_image_new();
priv->image_path = g_string_new(dbusmenu_menuitem_property_get(twin_item, DBUSMENU_METADATA_MENUITEM_ARTURL));
priv->old_image_path = g_string_new("");
+ priv->remote_image_path = g_string_new(DBUSMENU_PLAYER_ITEM_REMOTE_FILEPATH);
g_debug("Metadata::At startup and image path = %s", priv->image_path->str);
g_signal_connect(priv->album_art, "expose-event",
@@ -178,7 +180,7 @@
/**
* We override the expose method to enable primitive drawing of the
- * empty album art image (and soon rounded rectangles on the album art)
+ * empty album art image and rounded rectangles on the album art.
*/
static gboolean
metadata_image_expose (GtkWidget *metadata, GdkEventExpose *event, gpointer user_data)
@@ -186,24 +188,37 @@
g_return_val_if_fail(IS_METADATA_WIDGET(user_data), FALSE);
MetadataWidget* widget = METADATA_WIDGET(user_data);
MetadataWidgetPrivate * priv = METADATA_WIDGET_GET_PRIVATE(widget);
-
+ g_debug("expose");
if(priv->image_path->len > 0){
-
- if(g_string_equal(priv->image_path, priv->old_image_path) == FALSE){
+ if(g_string_equal(priv->image_path, priv->old_image_path) == FALSE ||
+ (g_string_equal(priv->image_path, priv->remote_image_path) == TRUE &&
+ g_string_equal(priv->old_image_path, priv->remote_image_path) == FALSE)){
+ g_debug("and we are in");
GdkPixbuf* pixbuf;
pixbuf = gdk_pixbuf_new_from_file(priv->image_path->str, NULL);
- g_debug("metadata_widget_expose, album art update -> pixbuf from %s",
- priv->image_path->str);
+ g_debug("metadata_load_new_image -> pixbuf from %s",
+ priv->image_path->str);
+ if(GDK_IS_PIXBUF(pixbuf) == FALSE){
+ g_debug("problem loading the downloaded image just use the placeholder instead");
+ draw_album_art_placeholder(metadata);
+ return TRUE;
+ }
pixbuf = gdk_pixbuf_scale_simple(pixbuf,60, 60, GDK_INTERP_BILINEAR);
image_set_from_pixbuf (metadata, widget, pixbuf);
g_string_erase(priv->old_image_path, 0, -1);
g_string_overwrite(priv->old_image_path, 0, priv->image_path->str);
- g_object_unref(pixbuf);
+ g_object_unref(pixbuf);
}
return FALSE;
}
-
+ draw_album_art_placeholder(metadata);
+ return TRUE;
+}
+
+static void draw_album_art_placeholder(GtkWidget *metadata)
+{
+
cairo_t *cr;
cr = gdk_cairo_create (metadata->window);
GtkAllocation alloc;
@@ -255,8 +270,7 @@
g_object_unref(pcontext);
g_string_free (string, TRUE);
cairo_destroy (cr);
-
- return TRUE;
+
}
/* Suppress/consume keyevents */
@@ -315,6 +329,12 @@
else if(g_ascii_strcasecmp(DBUSMENU_METADATA_MENUITEM_ARTURL, property) == 0){
g_string_erase(priv->image_path, 0, -1);
g_string_overwrite(priv->image_path, 0, g_value_get_string (value));
+ // Basically force expose the reload the image because we have an image update
+ // but we are using remote images i.e. the same file path but different images
+ if(g_string_equal(priv->image_path, priv->remote_image_path) == TRUE){
+ g_string_erase(priv->old_image_path, 0, -1);
+ gtk_widget_queue_draw(GTK_WIDGET(mitem));
+ }
}
}
=== modified file 'src/player-item.vala'
--- src/player-item.vala 2010-08-24 16:59:15 +0000
+++ src/player-item.vala 2010-09-02 10:31:05 +0000
@@ -19,13 +19,16 @@
using Dbusmenu;
using Gee;
+using Gdk;
+using DbusmenuPlayer;
public class PlayerItem : Dbusmenu.Menuitem
{
public PlayerController owner {get; construct;}
public string item_type { get; construct; }
private const int EMPTY = -1;
-
+ private FetchFile fetcher;
+
public PlayerItem(string type)
{
Object(item_type: type);
@@ -61,14 +64,23 @@
debug("with value : %s", update);
// Special case for the arturl URI's.
if(property.contains("mpris:artUrl")){
- try{
- update = Filename.from_uri(update.strip());
+ if(update.has_prefix("http://")){
+ // This is asyncronous so handle it offline
+ this.fetch_remote_art(update.strip(), property);
+ continue;
}
- catch(ConvertError e){
- warning("Problem converting URI %s to file path", update);
+ else{
+ // The file is local, just parse the string
+ try{
+ update = Filename.from_uri(update.strip());
+ }
+ catch(ConvertError e){
+ warning("Problem converting URI %s to file path",
+ update);
+ }
}
}
- this.property_set(property, update);
+ this.property_set(property, update);
}
else if (v.holds (typeof (int))){
debug("with value : %i", v.get_int());
@@ -101,5 +113,34 @@
}
return false;
}
+
+ public void fetch_remote_art(string uri, string prop)
+ {
+ this.fetcher = new FetchFile (uri, prop);
+ this.fetcher.failed.connect (() => { this.on_fetcher_failed ();});
+ this.fetcher.completed.connect (this.on_fetcher_completed);
+ this.fetcher.fetch_data ();
+ }
+
+ private void on_fetcher_failed ()
+ {
+ warning("on_fetcher_failed -> could not fetch artwork");
+ }
+
+ private void on_fetcher_completed(ByteArray update, string property)
+ {
+ try{
+ PixbufLoader loader = new PixbufLoader ();
+ loader.write (update.data, update.len);
+ loader.close ();
+ Pixbuf icon = loader.get_pixbuf ();
+ icon.save (ITEM_REMOTE_FILEPATH, loader.get_format().get_name());
+ this.property_set(property, ITEM_REMOTE_FILEPATH);
+ }
+ catch(GLib.Error e){
+ warning("Problem fetching file from the interweb - error: %s",
+ e.message);
+ }
+ }
}
=== modified file 'src/sound-service.c'
--- src/sound-service.c 2010-08-25 19:33:25 +0000
+++ src/sound-service.c 2010-09-02 10:31:05 +0000
@@ -40,14 +40,13 @@
{
if (mainloop != NULL) {
g_debug("Service shutdown !");
- // TODO: uncomment for release !!
+ //TODO: uncomment for release !!
close_pulse_activites();
g_main_loop_quit(mainloop);
}
return;
}
-
/**
main:
**/
=== modified file 'vapi/common-defs.vapi'
--- vapi/common-defs.vapi 2010-07-21 09:56:15 +0000
+++ vapi/common-defs.vapi 2010-09-02 10:31:05 +0000
@@ -1,6 +1,6 @@
/*
Copyright 2010 Canonical Ltd.
-
+
Authors:
Conor Curran <conor.curran@xxxxxxxxxxxxx>
@@ -27,6 +27,11 @@
}
[CCode (cheader_filename = "common-defs.h")]
+namespace DbusmenuPlayer{
+ public const string ITEM_REMOTE_FILEPATH;
+}
+
+[CCode (cheader_filename = "common-defs.h")]
namespace DbusmenuTransport{
public const string MENUITEM_TYPE;
public const string MENUITEM_PLAY_STATE;
Follow ups