#!/bin/sh

# This script was made by MarcusTunimus. You can visit his website here: https://marcustunimus.com

# REQUIREMENTS: qdbus, playerctl and imagemagick
# Command (for apt): sudo apt install qdbus playerctl imagemagick
# You can search up how to do that and what the packages are on your respective distro.

# HOW TO SET IT UP PROPERLY:
# Create a folder that you would like to use that will contain both the cover images and the text that will contain the song information in a specific format for the current song playing. 
# After configuring this script, set the file as executable and run it. Then you will be able to use the files generated in OBS as an image for the cover and text for the output text.

# !!!IMPORTANT!!! MAKE SURE TO INPUT THE CORRECT SOURCE PATH TO THIS CONFIG FILE IN THE MAIN SCRIPT FILE!!!



# REQUIRED CONFIGURATION

MUSIC_PLAYER="" 
# Name of the music player you use. If you want to know what players are available to you, run the command below in the terminal.
# Command: qdbus org.mpris.MediaPlayer2.* | grep "org.mpris.MediaPlayer2." | sed 's/org.mpris.MediaPlayer2.//'

CURRENT_SONG_PLAYING_FOLDER_PATH="/path/to/CurrentSongPlaying"
# Full path to the FOLDER you want to have the cover image and the text file.

SUPPORT_CURRENT_SONG_PLAYING_COVER_IMAGE=
# If you want to process cover images for the music set this to "true" and fill in the rest of the REQUIRED CONFIGURATION or else set this to "false" or leave it unset.

DEFAULT_COVER_ART_IMAGE_PATH="/path/to/DefaultCover.png"
# REQUIRED ONLY IF SUPPORT_CURRENT_SONG_PLAYING_COVER_IMAGE=true
# Full path to the IMAGE FILE you want to have displayed when there is no cover image found for the current music playing.



#OPTIONAL CONFIGURATION

CURRENT_SONG_OUTPUT_FORMAT_FILE_NAME=""
# Name of the text file that will contain the formatted text for the current song playing. 
# Default value: "CurrentSongPlaying"

CURRENT_SONG_OUTPUT_FORMAT="\"{{ title }}\" - {{ artist }} | "
# Format of how the text information of the current song playing will be displayed.
# For the music title write "{{ title }}", for the album name write "{{ album }}" and for the artist name write "{{ artist }}".
# If you want to put quotation character write "\". Example: \"{{ title }}\" - {{ album }} - {{ artist }} | ".
# Default format: "{{ title }} - {{ album }} - {{ artist }}"

REFRESH_SECONDS=3
# How often you want to have the program check for this information. Lower refresh seconds will use up more CPU capacity due to the checking frequency.
# Default value: 3



# MORE OPTIONAL CONFIGURATION ONLY IF SUPPORT_CURRENT_SONG_PLAYING_COVER_IMAGE=true

IMAGE_FORMAT=""
# Format of the generated images. It is recommended to use "png" format for images as it supports transparency.
# Default: "png"

CURRENT_SONG_ART_DIMENSIONS=""
# Size you would like the cover image to be. Format: "(number)x(number)". Example: "500x500". 
# Default value: "50x50"
# Optional: You can add "!"" at the end to ignore aspect ratio but usually there will be no need to use it.
# Example: "500x500!"

CURRENT_SONG_PLAYING_COVER_FILE_NAME=""
# Name of the generated cover image file for the current song playing.
# Default: "cover"

COVER_ARTS_FOLDER_NAME=""
# Name of the folder that will contain all of the cover images.
# Default: "Covers"

NO_SONG_PLAYING_IMAGE_FILE_PATH=""
# Full path to the IMAGE FILE you want to have displayed when there is no music playing.
# If you dont have a suitable image, you can still write the path to a file and an invisible image will be generated for it.
# Default: "No_Cover"

OVERLAY_ART_IMAGE_PATH=""
# Full path to the IMAGE FILE you want to have overlayed on top of the cover image.

CURRENT_SONG_PLAYING_OVERLAYED_COVER_FILE_NAME=""
# Name of the generated cover image file for the current song playing with the mask applied to it. Make sure it is different than CURRENT_SONG_PLAYING_COVER_FILE_NAME.
# Default value: "_Overlayed"

MASK_ART_IMAGE_PATH=""
# Full path to the IMAGE FILE you want to use as a mask. Make sure it only has white and black colors.
# The white color will be visible on the image and the black color will be transparent on the image.

CURRENT_SONG_PLAYING_MASKED_COVER_FILE_NAME=""
# Name of the generated cover image file for the current song playing with the mask applied to it. Make sure it is different than CURRENT_SONG_PLAYING_COVER_FILE_NAME.
# Default value: "_Masked"

MASK_BEFORE_OVERLAY=
# If you want to have the mask applied before the overlay set this to "true" and fill in the rest of the REQUIRED CONFIGURATION or else set this to "false" or leave it unset.

LOCAL_ALBUM_ART_FOLDER_PATH=""
# THIS IS FOR SPOTIFY LOCAL FILES ART - YOU CAN LEAVE THIS EMPTY IF YOU ARE NOT USING IT. If you are using Spotify to play local files, the cover can't be accessed.
# If you want to have album art still appear while playing the song, you need to set this variable.
# !!! IMPORTANT: Make sure to add the cover image files of the albums to the folder with the same name as their respective albums. 
# !!! IMPORTANT: They must also be in the same format specified on "IMAGE_FORMAT" variable. You can also just rename the extension to the "IMAGE_FORMAT" variable.
# This method uses the metadata of the playing song to get the album name. 
# !!! IMPORTANT: IF YOUR FILE DOES NOT HAVE AN ALBUM NAME IN IT'S METADATA, IT WILL USE THE DEFAULT COVER ART THAT IS SET IN THE "DEFAULT_COVER_ART_IMAGE_PATH" VARIABLE.
# If your album art name contains illegal characters (The forward slash "/") for a file name, 
# remove those illegal characters from the file name when you create the cover art file in the folder.
# Example: "Album name: Fight/Flight Today" -> "File name: FightFlight Today.png" (png being the "IMAGE_FORMAT" variable)
# Full path to the folder of local album cover images. 



# Assigning default values to the variables.
if [ -z "$CURRENT_SONG_OUTPUT_FORMAT_FILE_NAME" ]; then
    CURRENT_SONG_OUTPUT_FORMAT_FILE_NAME="CurrentSongPlaying"
fi
if [ -z "$CURRENT_SONG_OUTPUT_FORMAT" ]; then
    CURRENT_SONG_OUTPUT_FORMAT="{{ title }} - {{ album }} - {{ artist }}"
fi
if [ -z "$REFRESH_SECONDS" ]; then
    REFRESH_SECONDS=3
fi

SAVED_SONG_PLAYING_ART_COVER_NAME="initial"
SAVED_SONG_FORMATTED_OUTPUT="initial"
COVER_ARTS_FOLDER_PATH=""
CURRENT_SONG_PLAYING_COVER_FILE_PATH=""

if [ $SUPPORT_CURRENT_SONG_PLAYING_COVER_IMAGE = true ]; then
    if [ -z "$IMAGE_FORMAT" ]; then
        IMAGE_FORMAT="png"
    fi
    if [ -z "$CURRENT_SONG_ART_DIMENSIONS" ]; then
        CURRENT_SONG_ART_DIMENSIONS="50x50"
    fi
    if [ -z "$CURRENT_SONG_PLAYING_COVER_FILE_NAME" ]; then
        CURRENT_SONG_PLAYING_COVER_FILE_NAME="cover"
    fi
    CURRENT_SONG_PLAYING_COVER_FILE_PATH="$CURRENT_SONG_PLAYING_FOLDER_PATH/$CURRENT_SONG_PLAYING_COVER_FILE_NAME.$IMAGE_FORMAT"
    if [ -z "$COVER_ARTS_FOLDER_NAME" ]; then
        COVER_ARTS_FOLDER_NAME="Covers"
    fi
    COVER_ARTS_FOLDER_PATH="$CURRENT_SONG_PLAYING_FOLDER_PATH/$COVER_ARTS_FOLDER_NAME"
    if [ -z "$NO_SONG_PLAYING_IMAGE_FILE_PATH" ]; then
        NO_SONG_PLAYING_IMAGE_FILE_PATH="$COVER_ARTS_FOLDER_PATH/No_Cover.$IMAGE_FORMAT"
    fi
    if [ -z "$CURRENT_SONG_PLAYING_OVERLAYED_COVER_FILE_NAME" ]; then
        CURRENT_SONG_PLAYING_OVERLAYED_COVER_FILE_NAME="_Overlayed"
    fi
    if [ -z "$CURRENT_SONG_PLAYING_MASKED_COVER_FILE_NAME" ]; then
        CURRENT_SONG_PLAYING_MASKED_COVER_FILE_NAME="_Masked"
    fi
    if [ -z "$MASK_BEFORE_OVERLAY" ]; then
        MASK_BEFORE_OVERLAY=false
    fi
    if [ ! -d "$COVER_ARTS_FOLDER_PATH" ]; then
        mkdir "$COVER_ARTS_FOLDER_PATH"
    fi
fi

# Creating the functions.
create_cover_image()
{
    # CREATE_COVER_IMAGE_NAME="${1}"
    # CREATE_COVER_IMAGE_SOURCE_PATH="${2}"

    CREATE_COVER_IMAGE_FILE_PATH="$COVER_ARTS_FOLDER_PATH/${1}.$IMAGE_FORMAT"

    if [ ! -f "$CREATE_COVER_IMAGE_FILE_PATH" ]; then
        convert "${2}" -resize "$CURRENT_SONG_ART_DIMENSIONS^" -gravity center -extent "$CURRENT_SONG_ART_DIMENSIONS" "$CREATE_COVER_IMAGE_FILE_PATH"
    fi
}

create_invisible_cover_image()
{
    # CREATE_INVISIBLE_COVER_IMAGE_FILE_PATH="${1}"

    convert -size "$CURRENT_SONG_ART_DIMENSIONS" xc:#00000000 "${1}"
}

create_cover_image_with_overlay()
{
    # CREATE_COVER_IMAGE_NAME="${1}"
    # CREATE_COVER_IMAGE_SOURCE_PATH="${2}"

    CREATE_COVER_IMAGE_WITH_OVERLAY_FILE_PATH="$COVER_ARTS_FOLDER_PATH/${1}$CURRENT_SONG_PLAYING_OVERLAYED_COVER_FILE_NAME.$IMAGE_FORMAT"

    if [ ! -z "$OVERLAY_ART_IMAGE_PATH" ]; then
        if [ ! -f "$CREATE_COVER_IMAGE_WITH_OVERLAY_FILE_PATH" ]; then
            convert "${2}" "$OVERLAY_ART_IMAGE_PATH" -resize "$CURRENT_SONG_ART_DIMENSIONS^" -gravity center -composite "$CREATE_COVER_IMAGE_WITH_OVERLAY_FILE_PATH"
        fi
    fi
}

create_cover_image_with_mask()
{
    # CREATE_COVER_IMAGE_NAME="${1}"
    # CREATE_COVER_IMAGE_SOURCE_PATH="${2}"

    CREATE_COVER_IMAGE_WITH_MASK_FILE_PATH="$COVER_ARTS_FOLDER_PATH/${1}$CURRENT_SONG_PLAYING_MASKED_COVER_FILE_NAME.$IMAGE_FORMAT"

    if [ ! -z "$MASK_ART_IMAGE_PATH" ]; then
        if [ ! -f "$CREATE_COVER_IMAGE_WITH_MASK_FILE_PATH" ]; then
            convert "${2}" "$MASK_ART_IMAGE_PATH" -resize "$CURRENT_SONG_ART_DIMENSIONS^" -gravity center -compose CopyOpacity -composite "$CREATE_COVER_IMAGE_WITH_MASK_FILE_PATH"
        fi
    fi
}

create_cover_images()
{
    # SOURCE_IMAGE="${1}"

    create_cover_image "$SAVED_SONG_PLAYING_ART_COVER_NAME" "${1}"

    if [ $MASK_BEFORE_OVERLAY ]; then
        if [ ! -z "$OVERLAY_ART_IMAGE_PATH" ]; then
            create_cover_image_with_overlay "$SAVED_SONG_PLAYING_ART_COVER_NAME" "${1}"

            create_cover_image_with_mask "$SAVED_SONG_PLAYING_ART_COVER_NAME$CURRENT_SONG_PLAYING_OVERLAYED_COVER_FILE_NAME" "$COVER_ARTS_FOLDER_PATH/$SAVED_SONG_PLAYING_ART_COVER_NAME$CURRENT_SONG_PLAYING_OVERLAYED_COVER_FILE_NAME.$IMAGE_FORMAT"
        else
            create_cover_image_with_mask "$SAVED_SONG_PLAYING_ART_COVER_NAME" "$COVER_ARTS_FOLDER_PATH/$SAVED_SONG_PLAYING_ART_COVER_NAME.$IMAGE_FORMAT"
        fi
    else
        if [ ! -z "$MASK_ART_IMAGE_PATH" ]; then
            create_cover_image_with_mask "$SAVED_SONG_PLAYING_ART_COVER_NAME" "${1}"

            create_cover_image_with_overlay "$SAVED_SONG_PLAYING_ART_COVER_NAME$CURRENT_SONG_PLAYING_MASKED_COVER_FILE_NAME" "$COVER_ARTS_FOLDER_PATH/$SAVED_SONG_PLAYING_ART_COVER_NAME$CURRENT_SONG_PLAYING_MASKED_COVER_FILE_NAME.$IMAGE_FORMAT"
        else
            create_cover_image_with_overlay "$SAVED_SONG_PLAYING_ART_COVER_NAME" "$COVER_ARTS_FOLDER_PATH/$SAVED_SONG_PLAYING_ART_COVER_NAME.$IMAGE_FORMAT"
        fi
    fi
}

update_current_song_playing_cover_soft_link()
{
    if ([ -z "$MASK_ART_IMAGE_PATH" ] && [ -z "$OVERLAY_ART_IMAGE_PATH" ]); then
        ln -sf "$COVER_ARTS_FOLDER_PATH/$SAVED_SONG_PLAYING_ART_COVER_NAME.$IMAGE_FORMAT" "$CURRENT_SONG_PLAYING_COVER_FILE_PATH"
    else
        FINAL_SAVED_SONG_PLAYING_ART_COVER_NAME="$SAVED_SONG_PLAYING_ART_COVER_NAME"

        if [ $MASK_BEFORE_OVERLAY ]; then
            if [ -z "$OVERLAY_ART_IMAGE_PATH" ]; then
                FINAL_SAVED_SONG_PLAYING_ART_COVER_NAME="$FINAL_SAVED_SONG_PLAYING_ART_COVER_NAME$CURRENT_SONG_PLAYING_MASKED_COVER_FILE_NAME"
            else
                FINAL_SAVED_SONG_PLAYING_ART_COVER_NAME="$FINAL_SAVED_SONG_PLAYING_ART_COVER_NAME$CURRENT_SONG_PLAYING_OVERLAYED_COVER_FILE_NAME$CURRENT_SONG_PLAYING_MASKED_COVER_FILE_NAME"
            fi
        else
            if [ -z "$MASK_ART_IMAGE_PATH" ]; then
                FINAL_SAVED_SONG_PLAYING_ART_COVER_NAME="$FINAL_SAVED_SONG_PLAYING_ART_COVER_NAME$CURRENT_SONG_PLAYING_OVERLAYED_COVER_FILE_NAME"
            else
                FINAL_SAVED_SONG_PLAYING_ART_COVER_NAME="$FINAL_SAVED_SONG_PLAYING_ART_COVER_NAME$CURRENT_SONG_PLAYING_MASKED_COVER_FILE_NAME$CURRENT_SONG_PLAYING_OVERLAYED_COVER_FILE_NAME"
            fi
        fi

        ln -sf "$COVER_ARTS_FOLDER_PATH/$FINAL_SAVED_SONG_PLAYING_ART_COVER_NAME.$IMAGE_FORMAT" "$CURRENT_SONG_PLAYING_COVER_FILE_PATH"
    fi
}

clear_current_song_information()
{
    if [ ! -z "$SAVED_SONG_FORMATTED_OUTPUT" ]; then
        SAVED_SONG_FORMATTED_OUTPUT=""
        echo $SAVED_SONG_FORMATTED_OUTPUT > "$CURRENT_SONG_PLAYING_FOLDER_PATH/$CURRENT_SONG_OUTPUT_FORMAT_FILE_NAME.txt"
    fi

    if [ $SUPPORT_CURRENT_SONG_PLAYING_COVER_IMAGE = true ]; then
        if [ ! -f "$NO_SONG_PLAYING_IMAGE_FILE_PATH" ]; then
            create_invisible_cover_image "$NO_SONG_PLAYING_IMAGE_FILE_PATH"
        fi

        if [ ! -z "$SAVED_SONG_PLAYING_ART_COVER_NAME" ]; then
            SAVED_SONG_PLAYING_ART_COVER_NAME=""

            ln -sf "$NO_SONG_PLAYING_IMAGE_FILE_PATH" "$CURRENT_SONG_PLAYING_COVER_FILE_PATH"
        fi
    fi
}

# Executing the main code.
while true; do
    CURRENT_SONG_STATUS="$(playerctl status --player="$MUSIC_PLAYER")"

    if [ "$CURRENT_SONG_STATUS" = "Playing" ]; then
        CURRENT_SONG_FORMATTED_OUTPUT="$(playerctl metadata --player="$MUSIC_PLAYER" --format "$CURRENT_SONG_OUTPUT_FORMAT")"

        if [ ! -z "$CURRENT_SONG_FORMATTED_OUTPUT" ]; then
            if [ "$SAVED_SONG_FORMATTED_OUTPUT" != "$CURRENT_SONG_FORMATTED_OUTPUT" ]; then
                echo $CURRENT_SONG_FORMATTED_OUTPUT > "$CURRENT_SONG_PLAYING_FOLDER_PATH/$CURRENT_SONG_OUTPUT_FORMAT_FILE_NAME.txt"
                SAVED_SONG_FORMATTED_OUTPUT="$CURRENT_SONG_PLAYING_FOLDER_PATH"
            fi

            if [ $SUPPORT_CURRENT_SONG_PLAYING_COVER_IMAGE = true ]; then
                CURRENT_SONG_ART_IMAGE_PATH=""
                CURRENT_SONG_PLAYING_ART_COVER_NAME="$(playerctl metadata --player="$MUSIC_PLAYER" --format "{{ album }}" | sed "s/\///g")" 

                if [ "$MUSIC_PLAYER" = "spotify" ]; then
                    CURRENT_SONG_ART_IMAGE_PATH="$(playerctl metadata --player=$MUSIC_PLAYER --format "{{ mpris:artUrl }}")"
                else
                    CURRENT_SONG_ART_IMAGE_PATH="$(playerctl metadata --player=$MUSIC_PLAYER --format "{{ mpris:artUrl }}" | sed "s/file://g" | sed 's/^..//' | sed "s/%20/ /g" | sed "s/%26/\&/g")"
                
                    if [ -z "$CURRENT_SONG_PLAYING_ART_COVER_NAME" ]; then
                        CURRENT_SONG_PLAYING_ART_COVER_NAME="$(playerctl metadata --player="$MUSIC_PLAYER" --format "{{ title }}" | sed "s/\///")"
                    fi
                fi

                if [ -z "$CURRENT_SONG_ART_IMAGE_PATH" ]; then
                    if [ "$MUSIC_PLAYER" = "spotify" ]; then
                        SPOPTIFY_LOCAL_SONG_ART_IMAGE_PATH="$LOCAL_ALBUM_ART_FOLDER_PATH/$CURRENT_SONG_PLAYING_ART_COVER_NAME.$IMAGE_FORMAT"

                        if ([ ! -z "$LOCAL_ALBUM_ART_FOLDER_PATH" ] && [ ! -z "$CURRENT_SONG_PLAYING_ART_COVER_NAME" ] && [ -f "$SPOPTIFY_LOCAL_SONG_ART_IMAGE_PATH" ]); then
                            CURRENT_SONG_ART_IMAGE_PATH="$SPOPTIFY_LOCAL_SONG_ART_IMAGE_PATH"

                            SAVED_SONG_PLAYING_ART_COVER_NAME="$CURRENT_SONG_PLAYING_ART_COVER_NAME"
                        else
                            SAVED_SONG_PLAYING_ART_COVER_NAME="default_image"
                        fi
                    else
                        SAVED_SONG_PLAYING_ART_COVER_NAME="default_image"
                    fi

                    if [ "$SAVED_SONG_PLAYING_ART_COVER_NAME" = "default_image" ]; then
                        create_cover_images "$DEFAULT_COVER_ART_IMAGE_PATH"

                        CURRENT_SONG_PLAYING_ART_COVER_NAME="default_image"
                    else
                        create_cover_images "$CURRENT_SONG_ART_IMAGE_PATH"
                    fi

                    update_current_song_playing_cover_soft_link
                fi

                if [ -z "$CURRENT_SONG_PLAYING_ART_COVER_NAME" ]; then
                    if [ "$SAVED_SONG_PLAYING_ART_COVER_NAME" != "default_image" ]; then
                        SAVED_SONG_PLAYING_ART_COVER_NAME="default_image"

                        create_cover_images "$DEFAULT_COVER_ART_IMAGE_PATH"

                        update_current_song_playing_cover_soft_link
                    fi
                elif [ "$CURRENT_SONG_PLAYING_ART_COVER_NAME" != "$SAVED_SONG_PLAYING_ART_COVER_NAME" ]; then
                    SAVED_SONG_PLAYING_ART_COVER_NAME="$CURRENT_SONG_PLAYING_ART_COVER_NAME"

                    create_cover_images "$CURRENT_SONG_ART_IMAGE_PATH"

                    update_current_song_playing_cover_soft_link
                fi
            fi
        else
            clear_current_song_information
        fi
    else
        clear_current_song_information
    fi

    sleep $REFRESH_SECONDS
done
