Jerry Ma
Jerry Ma

Reputation: 521

gjs/gnome-shell-extension: read remote jpg image from url and set as icon

I am trying to improve a gnome-shell-extension by allowing retrieving of remote image (jpg) and set as icon for a certain widget.

Here is what I got so far, but it does not work, due to mismatch of data type:

// allow remote album art url
const GdkPixbuf = imports.gi.GdkPixbuf;
const Soup = imports.gi.Soup;
const _httpSession = new Soup.SessionAsync();
Soup.Session.prototype.add_feature.call(_httpSession, new Soup.ProxyResolverDefault());
function getAlbumArt(url, callback) {
    var request = Soup.Message.new('GET', url);
    _httpSession.queue_message(request, function(_httpSession, message) {
        if (message.status_code !== 200) {
          callback(message.status_code, null);
          return;
        } else {
          var albumart = request.response_body_data;
          // this line gives error message:
          // JS ERROR: Error: Expected type guint8 for Argument 'data' 
          // but got type 'object'
          // getAlbumArt/<@~/.local/share/gnome-shell/extensions
          // /[email protected]/streamMenu.js:42
          var icon = GdkPixbuf.Pixbuf.new_from_inline(albumart, true);
          callback(null, icon);
        };
    });

Here is the callback:

....
            log('try retrieve albumart: ' + filePath);
            if(GLib.file_test(iconPath, GLib.FileTest.EXISTS)){
                let file = Gio.File.new_for_path(iconPath)
                let icon = new Gio.FileIcon({file:file});
                this._albumArt.gicon = icon;
            } else if (filePath.indexOf('http') == 0) {
                log('try retrieve from url: ' + filePath);
                getAlbumArt(filePath, function(code, icon){
                    if (code) {
                        this._albumArt.gicon = icon;
                    } else {
                        this._albumArt.hide();
                    }
                });
            }

....

My question is, how to parse the response, which is a jpg image, so that I can set the widget icon with it? Thank you very much!

Upvotes: 0

Views: 1124

Answers (2)

Pikachunakapika
Pikachunakapika

Reputation: 1

For anyone still having the same problem here is my solution:

_httpSession.queue_message(request, function(_httpSession, message) {
    
    let buffer = message.response_body.flatten();
    let bytes = buffer.get_data();
    let gicon = Gio.BytesIcon.new(bytes);

    // your code here

});

Upvotes: 0

Juan Casilla
Juan Casilla

Reputation: 56

I was able achieve this by simply doing:

const St = imports.gi.St;
const Gio = imports.gi.Gio;
// ...

this.icon = new St.Icon()

// ...
let url = 'https://some.url'
let icon = Gio.icon_new_for_string(url);
this.icon.set_gicon(icon);

And it will automatically download it.

I had been struggling for hours with this issue until I finally figured out a way to do it with a local image cache (downloading the image and storing it in an icons/ folder). Then I tried this approach for fun (just to see what would happen, expecting it to fail miserably), and guess what? It just worked. This is not mentioned anywhere in the very scarce documentation I was able to find.

Upvotes: 2

Related Questions