elkowar / eww

ElKowars wacky widgets
https://elkowar.github.io/eww
MIT License
9.48k stars 386 forks source link

[BUG] background-image property does not work with remote images #742

Open Madeleaan opened 1 year ago

Madeleaan commented 1 year ago

Checklist before submitting an issue

Description of the bug

When using the background-image property on a box, it can render local files, but it does not render remote files. Does not work with either http or https. #719 has already reported this, however it got closed as "not planned" and it looks like it does not work for me as well. I noticed that when i select any remote file, the gtk+ style property is just url("data:image/png;base64,").

Reproducing the issue

(defwidget testwidget []
    (box :class "test"))
.test { 
    background-image: url("https://i.scdn.co/image/ab67616d0000b273015c484a7aca592df1a77828"); 
    background-size: cover;
    min-height: 24px;
    min-width: 24px;
}

Expected behaviour

Should render the image like it does with local files

rshchekotov commented 1 year ago

While this is being fixed, I thought I'd share my (probably obvious) hack to get this to work.

Note: I use the fish-shell and fish-scripts, but it should be trivial to translate them to bash and the likes:

~/config/scripts/audio-control.fish

set -l command $argv[1]
# other 'subcommands', etc.
if [ "$command" = "art" ]
  set -l art_thumb_cache "$HOME/.cache/music-thumbs"
  if not [ -d "$art_thumb_cache" ]
    mkdir -p "$art_thumb_cache"
  end
  set -l art_url (playerctl metadata mpris:artUrl)
  if string match -q "https://*" "$art_url"
    set -l art_name (basename "$art_url")
    set -l art_path "$art_thumb_cache/$art_name"
    if not [ -f "$art_path" ]
      curl -fLo "$art_path" "$art_url"
    end
    echo "$art_path"
  else
    echo "$art_url"
  end
end

and then: ~/config/eww/eww.yuck

(defpoll music_cover_art :interval "1s" "~/config/scripts/audio-control.fish art")

;; within the widget, where you want to use it:
(box :class "music-song-cover-art"
  :style "background-image: url(\"${music_cover_art}\");")

As I said this is a hack and it'd be great if this were supported out-of-the-box, but this hack comes with the additional benefit that you have manual control over the cache.

Edit: the cleanup script is UNTESTED: run at your own peril A smart scripter may be able to implement an LFU-cache )), I guess something along the lines of:

function cleanup
  set dir_path "$HOME/.cache/music-thumbs/"
  set file_list (find $dir_path -type f -printf "%A@ %p\n" | sort -rn | cut -d " " -f2-)
  set num_files_to_remove (math (count $file_list) - 64)

  if test $num_files_to_remove -gt 0
    for file in (seq $num_files_to_remove)
      set file_to_remove (echo $file_list[$file])
      rm $file_to_remove
    end
  end
end
Wunderharke commented 1 year ago

Is this won't fix or are there any news?

houdini-21 commented 11 months ago

Hi! I have the same problem. To solve it, I programmed this script in bash. In my case, I just want to get the image from Spotify, but you can modify it according to your needs.

What the script does is to get the URL of the image and cache it to display it as a local image. Also, to make sure that the image is always up to date, every time the script runs, it will delete all cached images, ensuring that no unnecessary images are saved.

#!/bin/bash

# Get the album art URL using playerctl
art_url=$(playerctl metadata --format '{{ (mpris:artUrl) }}' --player=spotify)

# Check if the art URL exists
if [ -n "$art_url" ]; then
    # Get the cache directory location
    cache_dir="$HOME/.album_art_cache"

    # Create the cache directory if it doesn't exist
    mkdir -p "$cache_dir"

    # Delete all images in the cache
    rm -f "$cache_dir"/*

    # Get the file name from the URL (last part of the URL)
    filename=$(basename "$art_url")

    # Create the full file path in the cache
    cache_path="$cache_dir/$filename"

    # Download the image
    wget -O "$cache_path" "$art_url" > /dev/null 2>&1

    # Display the path to the cached image
    echo "$cache_path"
else
    echo "Failed to get the album art URL."
fi

eww variable

(defpoll imgSong :interval "1s" "widgets/scripts/getImage.sh")
TheStachelfisch commented 5 months ago

I reworked the scripts above a bit and created a better one. This uses XDG_RUNTIME_DIR to save on disk-writes, doesn't have any dependency on wget, checks if an image is actually a link and returns an already-downloaded image instead of downloading it again.

But most importantly it uses listening now instead of interval-based polling.

To add this, add the deflisten variable to your window and create a file containing the script. You can change the initial image to whatever you want, I left it blank.

(deflisten music-image :initial "" "bash ./location-to/your-script")
#!/usr/bin/env bash

playerctl metadata --format "{{mpris:artUrl}}" --follow | while IFS= read -r line; do
    if [[ $line == *"http"* ]]; then
        cache_dir="$XDG_RUNTIME_DIR/album_art_cache"
        mkdir -p "$cache_dir"
        file_name=$(basename "$line")
        file_path="$cache_dir/$file_name"

        # Check if file exists
        if [ -e "$file_path" ]; then
            # File exists, return path immediately
            echo "file://$file_path"
        else 
            curl --output "$file_path" "$line" > /dev/null 2>&1
            echo "file://$file_path"
        fi 
    else
        # artUrl doesn't have a link, nothing to do
        echo "$line"
    fi
done
githubber6800 commented 1 month ago

I have discovered on my machine, installing gnome in its entirety fixes it, installing gtk 2,3,4 on their own don't though. It'll be interesting to see if installing gnome fixes it for anyone else and hopefully someone can isolate what specifically does it, so you don't have to have gnome.

hypernova7 commented 1 month ago

Please check if you have installed gdk-pixbuf2 and webkit2gtk

githubber6800 commented 4 weeks ago

Installing them along side gtk did not change anything unfortunately.

hypernova7 commented 4 weeks ago

@githubber6800 Currently these are the shared libraries that eww uses, check that you have them installed using dpkg -l | grep -i <package-name>

libgdk-3.so.0 libpango-1.0.so.0 libgdk_pixbuf-2.0.so.0 libcairo-gobject.so.2 libcairo.so.2 libgobject-2.0.so.0 libglib-2.0.so.0 libdbusmenu-gtk3.so.4 libgtk-3.so.0 libgio-2.0.so.0 libgtk-layer-shell.so.0 libgcc_s.so.1 libm.so.6 libc.so.6 ld-linux-x86-64.so.2

Checked with readelf -d ./target/release/eww

quadraplat commented 3 weeks ago

install gvfs for remote urls in gtk css