not sure what changes i made tbh

This commit is contained in:
Brandon4466
2023-01-21 00:48:00 -08:00
parent 319542f470
commit dcd2fc068f
8 changed files with 578 additions and 211 deletions

1
.cache Normal file
View File

@@ -0,0 +1 @@
{"access_token": "BQB6UF8iw-WD97zuAcBy3j1JRn-HI3CUOYi-cFI0CG72nxPGXPkHdzOse6jAIVBrkkGgzDlqdgbGJWoEqzLFr60Ri9dKwIPjfOzDMrghO4Qm86r_ks81plxBDTqbmmJCpv518cFsu_w5JFEhGa6AruwxzYWrLhcZAPkAGCFGub-nj0gaWZnHGEyRBTdU5w", "token_type": "Bearer", "expires_in": 3600, "scope": "user-modify-playback-state user-read-playback-state", "expires_at": 1674288882, "refresh_token": "AQANdyTU2KRSkgJSsueOmP3-n3VFXKSeh90xje6HINu6becuKHhx0tauC4ruB7v6GbtRd45wkF13AsUXjGDHxRMSvGFky2KBhck6sEZTSJID0qd4pmsWoC8xOvzFzsAlaeA"}

View File

@@ -1 +0,0 @@
{"access_token": "BQBDvdX_R5Ytk8IWYKvSfQ-xvTD3fJHLEXy5-EwVm6ukngDvG5Hlz6F0LWdjLuUMVmcJi24IYljaF2l396aeE0kcnX8X12rYcyMpy6kIUH3i_jL1xg4egPSZ8Lr41l7xHIw7BJQkuXN-yewbNo2quC_i32BtpYncurovWcSKYjLjfO8LC9_L7Z3IWhu1bw", "token_type": "Bearer", "expires_in": 3600, "scope": "user-modify-playback-state user-read-playback-state", "expires_at": 1673754361, "refresh_token": "AQBb9zPnT-MmK7H70IzzenfZBz1VV-0eZWhD73x2br6xQPx1jctO-uuGZu38EvvXapCpdJZ8oLAk4Z4Ci2gmZGGfMsmsofMNVB402gjRrSzfV94BpkuYJtyV0fS5bSK5Nrg"}

24
install.sh Normal file
View File

@@ -0,0 +1,24 @@
echo "Downloading Spotify GUI"
curl http://files.bbrunson.com/spotify-gui/install.zip -o install.zip
echo "This installation requires sudo privileges"
sudo ls
echo "Installing Python 3"
sudo apt-get install -y python3 python3-distutils python3-tk
echo "Installing Pip 3"
curl -s https://bootstrap.pypa.io/get-pip.py | python3
echo "Installing spotify-gui to /opt"
sudo mkdir -p /opt/spotify-gui
sudo unzip -o install.zip -d /opt
sudo chmod +x /opt/spotify-gui/update.py
echo "Installing dependencies"
echo -e "librespot\nPillow\nPyAutoGUI\nrequests\nspotipy\nsv_ttk\nsyncedlyrics" > requirements.txt
sudo mv requirements.txt /opt/spotify-gui/requirements.txt
sudo pip3 install -r /opt/spotify-gui/requirements.txt
echo "Creating systemd service"
echo -e "[Unit]\nDescription=Spotify GUI\nAfter=network-online.target\nWants=network-online.target\n[Service]\nType=simple\nUser=pi\nWorkingDirectory=/opt/spotify-gui\nExecStart=xinit ./start.sh $* -- :0 vt$XDG_VTNR -nocursor\n[Install]\nWantedBy=multi-user.target" > spotify-gui.service
sudo mv spotify-gui.service /etc/systemd/system/spotify-gui.service
sudo chmod +x /etc/systemd/system/spotify-gui.service
sudo systemctl daemon-reload
sudo systemctl enable spotify-gui.service
echo "Installation complete. Updating and starting Spotify GUI."
sudo service spotify-gui start

472
program-embedded-util.py Normal file
View File

@@ -0,0 +1,472 @@
import spotipy
import spotipy.util
import tkinter as ttk
from tkinter import ttk as tk
import sv_ttk
import requests
import os
import syncedlyrics
from PIL import Image, ImageTk
from io import BytesIO
import math
from time import sleep
# Set the Spotify app's client ID and client secret
client_id = "69b82a34d0fb40be80b020eae8e80f25"
client_secret = "455575b0e3db44acbbfaa0c419bc3c10"
redirect_uri = "http://127.0.0.1:8888/callback"
# Set the user's Spotify username
username = "thebrandon45"
password = "Mariposa2502$"
os.environ["DISPLAY"] = ":0"
def setup():
checkDisplay()
def checkDisplay():
while True:
if os.name == 'posix':
if "DISPLAY" in os.environ:
break
else:
sleep(0.25)
pass
else:
break
# def wait_for_display():
# while True:
# try:
# test = ttk.Tk()
# test.destroy()
# return True
# except:
# pass
# Get the user's Spotify authorization token
scope = "user-read-playback-state,user-modify-playback-state"
# if len(sys.argv) == 1:
# pass
# elif sys.argv[1] == "--setup":
# try:
# os.remove(".cache-" + username)
# except OSError:
# pass
# elif sys.argv[1] == "--clear":
# os.remove(".cache-" + username)
# sys.exit("Deleting token from cache and exiting...")
# elif sys.argv[1] == "--clearChromeCache":
# if os.name() == "posix":
# os.system("rm -rf ~/.cache/chromium")
# os.system("rm -rf ~/.config/chromium")
# sys.exit("Deleting Chrome cache and exiting...")
# def oauthLogin():
# if os.path.isfile(".cache-" + username) == False:
# sleep(25)
# pyautogui.press('tab')
# pyautogui.press('tab')
# pyautogui.press('tab')
# pyautogui.press('tab')
# pyautogui.write(username)
# pyautogui.press('tab')
# pyautogui.write(password)
# pyautogui.press('enter')
# sleep(90)
# if platform.system() == "Linux":
# os.system("killall chromium-browser")
# threading.Thread(target=oauthLogin).start()
# oauthLogin()
# Create a Spotify object with the user's authorization token
def createToken():
token = spotipy.util.prompt_for_user_token(username, scope, client_id, client_secret, redirect_uri)
spotify = spotipy.Spotify(auth=token)
return spotify
spotify = createToken()
bg_color = "#000000"
# Create the tkinter window
root = ttk.Tk()
root.title("Media Controller")
root.geometry("1280x400")
root.attributes("-topmost", True)
root.overrideredirect(1)
sv_ttk.use_dark_theme()
# Function to call the Spotify API to play the current track
def play():
spotify.start_playback()
# Function to call the Spotify API to pause the current track
def pause():
spotify.pause_playback()
def next():
spotify.next_track()
def previous():
spotify.previous_track()
# def maxvolume():
# spotify.volume(100)
# def minvolume():
# spotify.volume(0)
# def randomvolume():
# spotify.volume(random.randint(0,100))
# def volumeslider(self):
# spotify.volume(int(volumeslider_button.get()))
# def search(event):
# searched = track_search.get()
# if searched.startswith(":t"):
# track_searched_isolated = searched.replace(":t", "")
# track_search_results = spotify.search(q='track:' + track_searched_isolated, type='track')
# searched_track_id = track_search_results["tracks"]["items"][0]["id"]
# spotify.start_playback(uris=["spotify:track:" + searched_track_id])
# if searched.startswith(":a"):
# artist_searched_isolated = searched.replace(":a", "")
# artist_search_results = spotify.search(q='artist:' + artist_searched_isolated, type='artist')
# searched_artist_id = artist_search_results["artists"]["items"][0]["uri"]
# spotify.start_playback(context_uri=searched_artist_id)
# if searched.startswith(":l"):
# album_searched_isolated = searched.replace(":l", "")
# album_search_results = spotify.search(q='album:' + album_searched_isolated, type='album')
# searched_album_id = album_search_results["albums"]["items"][0]["uri"]
# spotify.start_playback(context_uri=searched_album_id)
# if searched.startswith(":p"):
# playlist_searched_isolated = searched.replace(":p", "")
# playlist_search_results = spotify.search(q='playlist:' + playlist_searched_isolated, type='playlist')
# searched_playlist_id = playlist_search_results["playlists"]["items"][0]["uri"]
# spotify.start_playback(context_uri=searched_playlist_id)
def start_playback_on_device():
device_selections = devices_list.curselection()
try:
list_of_devices = spotify.devices()
except (spotipy.exceptions.SpotifyException, requests.exceptions.HTTPError):
createToken()
pass
list_of_devices = spotify.devices()
device_id = list_of_devices["devices"][device_selections[0]]["id"]
spotify.transfer_playback(device_id=device_id)
def get_devices():
list_of_devices = spotify.devices()
unloadNow_playing()
if list_of_devices == "{'devices': []}":
unloadDevices_list()
loadSearching_Devices()
root.after(1000, get_devices)
else:
current_playback = spotify.current_playback()
if current_playback != None:
unloadSearching_Devices()
unloadDevices_list()
loadNow_playing()
update_song_label()
else:
unloadSearching_Devices()
loadDevices_list()
devices_list.delete(0, ttk.END)
try:
list_of_devices = spotify.devices()
except (spotipy.exceptions.SpotifyException, requests.exceptions.HTTPError):
createToken()
pass
list_of_devices = spotify.devices()
for num_of_device, garbage in enumerate(list_of_devices["devices"]):
devices_list.insert(num_of_device, list_of_devices["devices"][num_of_device]["name"])
root.after(6500, get_devices)
# def loadLyrics_pressed():
# unloadNow_playing()
# loadLyrics()
# def unloadLyrics_pressed():
# unloadLyrics()
# loadNow_playing()
# def hide_devices():
# get_devices_button.grid()
# devices_list.grid_remove()
# start_playback_on_device_button.grid_remove()
# hide_devices_button.grid_remove()
play_img = ttk.PhotoImage(file="icons/play-circle-x2.png")
pause_img = ttk.PhotoImage(file="icons/pause-circle-x2.png")
next_img = ttk.PhotoImage(file="icons/skip-next-x2.png")
previous_img = ttk.PhotoImage(file="icons/skip-previous-x2.png")
play_img_black = ttk.PhotoImage(file="icons/play-circle-x2-black.png")
pause_img_black = ttk.PhotoImage(file="icons/pause-circle-x2-black.png")
next_img_black = ttk.PhotoImage(file="icons/skip-next-x2-black.png")
previous_img_black = ttk.PhotoImage(file="icons/skip-previous-x2-black.png")
# lyrics_img = ttk.PhotoImage(file="icons/lyrics.png")
album_art_img = ""
# album_art_img = ttk.PhotoImage(file="album_art.png")
# canvas = ttk.Canvas(root, width=480, height=320)
# canvas.create_image(0, 0, image=album_art_img, anchor="nw")
# canvas.grid()
# canvas = ttk.Canvas(root, width=480, height=320)
frame_artist_song = ttk.Frame(root, width=(1280/3), height=400, bg=bg_color)
# frame_controls = tk.Frame(root)
# lyrics_button = tk.Frame(root)
album_art_frame = ttk.Frame(root, bg=bg_color)
lyrics_label_frame = ttk.Frame(root, width=(1280/3), height=400, bg=bg_color)
lyrics_label_frame.grid_propagate(0)
root.grid_rowconfigure(0, weight=1)
root.grid_rowconfigure(1, weight=1)
root.grid_rowconfigure(2, weight=1)
root.grid_columnconfigure(0, weight=1)
root.grid_columnconfigure(1, weight=1)
# root.grid_columnconfigure(2, weight=1)
root.configure(background=bg_color)
lyrics_label_frame.grid_rowconfigure(0, weight=1)
lyrics_label_frame.grid_columnconfigure(0, weight=1)
# Create the media control buttons and a text label
play_button = ttk.Label(frame_artist_song, image=play_img, borderwidth=0)
pause_button = ttk.Label(frame_artist_song, image=pause_img, borderwidth=0)
next_button = ttk.Label(frame_artist_song, image=next_img, borderwidth=0)
previous_button = ttk.Label(frame_artist_song, image=previous_img, borderwidth=0)
# maxvolume_button = tk.Button(root, text="Max Volume", command=maxvolume)
# minvolume_button = tk.Button(root, text="Min Volume", command=minvolume)
# randomvolume_button = tk.Button(root, text="Random Volume", command=randomvolume)
# volumeslider_button = tk.Scale(root, from_=100, to=0, orient=ttk.VERTICAL, length=240, command=volumeslider)
#doaudio_analysis = tk.Button(root, text="Audio Analysis", command=doaudioanalysis)
artist_label = tk.Label(frame_artist_song, text="", font=("Helvetica", 24), wraplength=(1280/3), justify=ttk.CENTER, background=bg_color)
song_label = tk.Label(frame_artist_song, text="", font=("Helvetica", 32), wraplength=(1280/3), justify=ttk.CENTER, background=bg_color)
# track_progress_label = tk.Label(root, text="")
# track_duration_label = tk.Label(root, text="")
# track_combined_label = tk.Label(root, text="")
# track_search = tk.Entry(root, text="")
# track_search_button = tk.Button(root, text="Search", command=search)
get_devices_button = tk.Button(root, text="Get Devices", command=get_devices)
start_playback_on_device_button = tk.Button(root, text="Start Playback on Device", command=start_playback_on_device)
# hide_devices_button = tk.Button(root, text="Hide Devices", command=hide_devices)
# username_label = tk.Label(root, text="Username: " + spotify.me()["display_name"])
devices_list = ttk.Listbox(root, selectmode=ttk.SINGLE, font=("Helvetica", 18))
progress_bar = tk.Progressbar(root, orient=ttk.HORIZONTAL, length=1280)
searching_for_devices_label = tk.Label(root, text="Searching for Devices...", font=("Helvetica", 24))
device_name_label = tk.Label(frame_artist_song, text="", font=("Helvetica", 12))
# background_image_label = tk.Label(root, image=album_art_img)
lyrics_label = tk.Label(lyrics_label_frame, text="", font=("Helvetica", 32), wraplength=(1280/3), justify=ttk.CENTER, background=bg_color)
# loadLyrics_button = ttk.Button(lyrics_button, image=lyrics_img, command=loadLyrics_pressed, borderwidth=0)
# album_art_canvas = ttk.Canvas(root)
# album_art_canvas_create_image = album_art_canvas.create_image(0, 0, image=album_art_img)
album_art_label = tk.Label(album_art_frame, image=album_art_img)
# root.bind("<Return>", search)
# lyrics_label.bind("<Button-1>", lambda e:unloadLyrics_pressed())
play_button.bind("<Button-1>", lambda e:play())
pause_button.bind("<Button-1>", lambda e:pause())
next_button.bind("<Button-1>", lambda e:next())
previous_button.bind("<Button-1>", lambda e:previous())
# Function to update the song label with the current track's name
def update_song_label():
global lrc
global album_art_img
# Get the current playback information
while True:
try:
current_playback = spotify.current_playback()
break
except (spotipy.exceptions.SpotifyException, requests.exceptions.HTTPError, requests.exceptions.ReadTimeout):
createToken()
sleep(0.25)
# If there is no current playback, set the text of the song label to "No playback"
if current_playback is None:
# nothing_playing_obj = '{"item": {"artists": [{"name": "Nothing Playing"}],"duration_ms": 0,"name": "Nothing Playing"},"progress_ms": 0}'
# current_playback = json.loads(nothing_playing_obj)
get_devices()
# Update the song label every 1 second
else:
track_name = current_playback["item"]["name"]
artist_name = current_playback["item"]["artists"][0]["name"]
track_duration = current_playback["item"]["duration_ms"]
track_progress = current_playback["progress_ms"]
# current_volume = current_playback["device"]["volume_percent"]
playing_status = current_playback["is_playing"]
device_name = current_playback["device"]["name"]
album_art_url = current_playback["item"]["album"]["images"][0]["url"]
track_progress_min = track_progress//(1000*60)%60
track_progress_sec = (track_progress//1000)%60
# track_duration_min = track_duration//(1000*60)%60
# track_duration_sec = (track_duration//1000)%60
# open_url = urlopen(album_art_url)
# raw_image_data = open_url.read()
# open_url.close()
# album_art = ImageTk.PhotoImage(data=raw_image_data)
# background_image_label.config(image=album_art)
# print(background_image_label.cget("image"))
# if raw_image_data == background_image_label.cget("image"):
# print("this is the same image")
# else:
# pass
# loadNow_playing()
if track_name == song_label.cget("text"):
track_progress_formatted = ("{}:{:02d}".format(track_progress_min, track_progress_sec))
# track_progress_label.config(text=track_progress_formatted)
progress_bar.config(maximum=track_duration)
progress_bar.config(value=track_progress)
for line in str(lrc).splitlines():
if track_progress_formatted in line:
lyric = line.split("]")[1]
# wrapped_lyric = textwrap.fill(lyric, 21)
lyrics_label.config(text=lyric)
root.after(800, update_song_label)
else:
# album_art_data = Image.open(requests.get(album_art_url, stream=True).raw)
# album_art_data.save("album_art.jpg")
device_name_label.config(text=device_name)
song_label.config(text=track_name)
artist_label.config(text=artist_name)
# track_duration_label.config(text=("{}:{:02d}".format(track_duration_min, track_duration_sec)))
# volumeslider_button.set(value=current_volume)
lyrics_label.config(text="")
lrc = syncedlyrics.search("[" + track_name + "] [" + artist_name + "]")
album_art_img_data = requests.get(album_art_url).content
album_art_img_open = Image.open(BytesIO(album_art_img_data))
album_art_img = ImageTk.PhotoImage(album_art_img_open.resize((300,300)))
album_art_label.config(image=album_art_img)
bg_color_img = album_art_img_open.resize((1,1), resample=0)
bg_color_img_pixel = bg_color_img.getpixel((0,0))
bg_color = "#" + '%02x%02x%02x' % (bg_color_img_pixel)
root.config(background=bg_color)
frame_artist_song.config(background=bg_color)
device_name_label.config(background=bg_color)
song_label.config(background=bg_color)
artist_label.config(background=bg_color)
play_button.config(background=bg_color)
pause_button.config(background=bg_color)
next_button.config(background=bg_color)
previous_button.config(background=bg_color)
lyrics_label_frame.config(background=bg_color)
lyrics_label.config(background=bg_color)
if math.sqrt(0.299 * (bg_color_img_pixel[0] ** 2) + 0.587 * (bg_color_img_pixel[1] ** 2) + 0.114 * (bg_color_img_pixel[2] ** 2)) > 170:
song_label.config(foreground="black")
artist_label.config(foreground="black")
device_name_label.config(foreground="black")
lyrics_label.config(foreground="black")
play_button.config(image=play_img_black)
pause_button.config(image=pause_img_black)
next_button.config(image=next_img_black)
previous_button.config(image=previous_img_black)
else:
song_label.config(foreground="white")
artist_label.config(foreground="white")
device_name_label.config(foreground="white")
lyrics_label.config(foreground="white")
play_button.config(image=play_img)
pause_button.config(image=pause_img)
next_button.config(image=next_img)
previous_button.config(image=previous_img)
# album_art_label.grid_forget()
# album_art_label.grid()
root.after(500, update_song_label)
# if album_art_url == "12345":
# open_url = urlopen(album_art_url)
# raw_image_data = open_url.read()
# open_url.close()
# album_art = ImageTk.PhotoImage(data=raw_image_data)
# background_image_label.config(image=album_art)
# else:
# pass
if playing_status == True:
play_button.grid_forget()
pause_button.grid(row=3, column=1, pady=(100,0))
elif playing_status == False:
pause_button.grid_forget()
play_button.grid(row=3, column=1, pady=(100,0))
else:
pass
def loadNow_playing():
# background_image_label.place(x=0, y=0)
# volumeslider_button.grid(row=1, column=1, rowspan=3, sticky="e", padx=(0,20))
# lyrics_button.grid(row=1, column=1, padx=(0,380))
frame_artist_song.grid(row=0, column=1, rowspan=3, pady=(20,0))
# frame_controls.grid(row=2, column=1)
# loadLyrics_button.grid()
device_name_label.grid(row=0, column=1)
artist_label.grid(row=2, column=1)
song_label.grid(row=1, column=1)
previous_button.grid(row=3, column=1, padx=(0,200), pady=(100,0))
play_button.grid(row=3, column=1, pady=(100,0))
next_button.grid(row=3, column=1, padx=(200,0), pady=(100,0))
progress_bar.grid(row=3, column=0, columnspan=3)
album_art_frame.grid(row=0, column=0, rowspan=4)
album_art_label.grid(sticky="w")
lyrics_label_frame.grid(row=0, column=2, rowspan=4)
lyrics_label.grid()
def unloadNow_playing():
# volumeslider_button.grid_forget()
# frame_artist_song.grid_forget()
# frame_controls.grid_forget()
device_name_label.grid_forget()
artist_label.grid_forget()
song_label.grid_forget()
previous_button.grid_forget()
play_button.grid_forget()
next_button.grid_forget()
progress_bar.grid_forget()
# loadLyrics_button.grid_forget()
# lyrics_label_frame.grid_forget()
lyrics_label.grid_forget()
album_art_label.grid_forget()
def loadDevices_list():
devices_list.grid(row=1, column=1, pady=10)
start_playback_on_device_button.grid(row=0, column=1, ipadx=40, ipady=40)
def unloadDevices_list():
devices_list.grid_forget()
start_playback_on_device_button.grid_forget()
def loadSearching_Devices():
searching_for_devices_label.grid()
def unloadSearching_Devices():
searching_for_devices_label.grid_forget()
# def loadLyrics():
# album_art_frame.grid(row=0, column=1)
# album_art_label.grid()
# lyrics_label.grid(row=0, column=1)
# def unloadLyrics():
# album_art_frame.grid_forget()
# album_art_label.grid_forget()
# lyrics_label.grid_forget()
# Start updating the song label
setup()
loadNow_playing()
update_song_label()
# Run the GUI
root.mainloop()

View File

@@ -1,19 +1,15 @@
import spotipy import spotipy
import spotipy.util from spotipy.oauth2 import SpotifyOAuth
import tkinter as ttk import tkinter as ttk
from tkinter import ttk as tk from tkinter import ttk as tk
import random
import sv_ttk import sv_ttk
from urllib.request import urlopen
import requests import requests
from time import sleep
import sys
import os import os
import platform
import syncedlyrics import syncedlyrics
from PIL import Image, ImageTk from PIL import Image, ImageTk
from io import BytesIO from io import BytesIO
import math import math
from time import sleep
# Set the Spotify app's client ID and client secret # Set the Spotify app's client ID and client secret
client_id = "69b82a34d0fb40be80b020eae8e80f25" client_id = "69b82a34d0fb40be80b020eae8e80f25"
@@ -24,70 +20,31 @@ redirect_uri = "http://127.0.0.1:8888/callback"
username = "thebrandon45" username = "thebrandon45"
password = "Mariposa2502$" password = "Mariposa2502$"
def wait_for_connection(): # os.environ["DISPLAY"] = ":0"
while True:
try:
urlopen('http://142.250.189.174', timeout=1)
return True
except:
pass
# def wait_for_display(): # def setup():
# checkDisplay()
# def checkDisplay():
# while True: # while True:
# try: # if os.name == 'posix':
# test = ttk.Tk() # if "DISPLAY" in os.environ:
# test.destroy() # break
# return True # else:
# except: # sleep(0.25)
# pass # pass
# else:
# break
# Get the user's Spotify authorization token # Get the user's Spotify authorization token
scope = "user-read-playback-state,user-modify-playback-state" scope = "user-read-playback-state,user-modify-playback-state"
if len(sys.argv) == 1:
pass
elif sys.argv[1] == "--setup":
try:
os.remove(".cache-" + username)
except OSError:
pass
elif sys.argv[1] == "--clear":
os.remove(".cache-" + username)
sys.exit("Deleting token from cache and exiting...")
elif sys.argv[1] == "--clearChromeCache":
if platform.system() == "Linux":
os.system("rm -rf ~/.cache/chromium")
os.system("rm -rf ~/.config/chromium")
sys.exit("Deleting Chrome cache and exiting...")
# def oauthLogin():
# if os.path.isfile(".cache-" + username) == False:
# sleep(25)
# pyautogui.press('tab')
# pyautogui.press('tab')
# pyautogui.press('tab')
# pyautogui.press('tab')
# pyautogui.write(username)
# pyautogui.press('tab')
# pyautogui.write(password)
# pyautogui.press('enter')
# sleep(90)
# if platform.system() == "Linux":
# os.system("killall chromium-browser")
# threading.Thread(target=oauthLogin).start()
# oauthLogin()
token = spotipy.util.prompt_for_user_token(username, scope, client_id, client_secret, redirect_uri)
# Create a Spotify object with the user's authorization token # Create a Spotify object with the user's authorization token
def createToken(): spotify = spotipy.Spotify(auth_manager=SpotifyOAuth(client_id=client_id, client_secret=client_secret, redirect_uri=redirect_uri, scope=scope, requests_timeout=30))
spotify = spotipy.Spotify(auth=token)
return spotify
spotify = createToken()
bg_color = "#000000" bg_color = "#000000"
count = 0
# Create the tkinter window # Create the tkinter window
root = ttk.Tk() root = ttk.Tk()
@@ -111,54 +68,19 @@ def next():
def previous(): def previous():
spotify.previous_track() spotify.previous_track()
def maxvolume():
spotify.volume(100)
def minvolume():
spotify.volume(0)
def randomvolume():
spotify.volume(random.randint(0,100))
def volumeslider(self):
spotify.volume(int(volumeslider_button.get()))
def search(event):
searched = track_search.get()
if searched.startswith(":t"):
track_searched_isolated = searched.replace(":t", "")
track_search_results = spotify.search(q='track:' + track_searched_isolated, type='track')
searched_track_id = track_search_results["tracks"]["items"][0]["id"]
spotify.start_playback(uris=["spotify:track:" + searched_track_id])
if searched.startswith(":a"):
artist_searched_isolated = searched.replace(":a", "")
artist_search_results = spotify.search(q='artist:' + artist_searched_isolated, type='artist')
searched_artist_id = artist_search_results["artists"]["items"][0]["uri"]
spotify.start_playback(context_uri=searched_artist_id)
if searched.startswith(":l"):
album_searched_isolated = searched.replace(":l", "")
album_search_results = spotify.search(q='album:' + album_searched_isolated, type='album')
searched_album_id = album_search_results["albums"]["items"][0]["uri"]
spotify.start_playback(context_uri=searched_album_id)
if searched.startswith(":p"):
playlist_searched_isolated = searched.replace(":p", "")
playlist_search_results = spotify.search(q='playlist:' + playlist_searched_isolated, type='playlist')
searched_playlist_id = playlist_search_results["playlists"]["items"][0]["uri"]
spotify.start_playback(context_uri=searched_playlist_id)
def start_playback_on_device(): def start_playback_on_device():
device_selections = devices_list.curselection() device_selections = devices_list.curselection()
try: list_of_devices = spotify.devices()
list_of_devices = spotify.devices()
except (spotipy.exceptions.SpotifyException, requests.exceptions.HTTPError):
createToken()
pass
list_of_devices = spotify.devices() list_of_devices = spotify.devices()
device_id = list_of_devices["devices"][device_selections[0]]["id"] device_id = list_of_devices["devices"][device_selections[0]]["id"]
spotify.transfer_playback(device_id=device_id) spotify.transfer_playback(device_id=device_id)
def get_devices(): def get_devices():
# count +=1
# if count >= 277:
list_of_devices = spotify.devices() list_of_devices = spotify.devices()
unloadNow_playing() unloadNow_playing()
if list_of_devices == "{'devices': []}": if list_of_devices == "{'devices': []}":
@@ -176,30 +98,11 @@ def get_devices():
unloadSearching_Devices() unloadSearching_Devices()
loadDevices_list() loadDevices_list()
devices_list.delete(0, ttk.END) devices_list.delete(0, ttk.END)
try:
list_of_devices = spotify.devices()
except (spotipy.exceptions.SpotifyException, requests.exceptions.HTTPError):
createToken()
pass
list_of_devices = spotify.devices() list_of_devices = spotify.devices()
for num_of_device, garbage in enumerate(list_of_devices["devices"]): for num_of_device, garbage in enumerate(list_of_devices["devices"]):
devices_list.insert(num_of_device, list_of_devices["devices"][num_of_device]["name"]) devices_list.insert(num_of_device, list_of_devices["devices"][num_of_device]["name"])
root.after(6500, get_devices) root.after(6500, get_devices)
def loadLyrics_pressed():
unloadNow_playing()
loadLyrics()
def unloadLyrics_pressed():
unloadLyrics()
loadNow_playing()
# def hide_devices():
# get_devices_button.grid()
# devices_list.grid_remove()
# start_playback_on_device_button.grid_remove()
# hide_devices_button.grid_remove()
play_img = ttk.PhotoImage(file="icons/play-circle-x2.png") play_img = ttk.PhotoImage(file="icons/play-circle-x2.png")
@@ -210,19 +113,10 @@ play_img_black = ttk.PhotoImage(file="icons/play-circle-x2-black.png")
pause_img_black = ttk.PhotoImage(file="icons/pause-circle-x2-black.png") pause_img_black = ttk.PhotoImage(file="icons/pause-circle-x2-black.png")
next_img_black = ttk.PhotoImage(file="icons/skip-next-x2-black.png") next_img_black = ttk.PhotoImage(file="icons/skip-next-x2-black.png")
previous_img_black = ttk.PhotoImage(file="icons/skip-previous-x2-black.png") previous_img_black = ttk.PhotoImage(file="icons/skip-previous-x2-black.png")
# lyrics_img = ttk.PhotoImage(file="icons/lyrics.png")
album_art_img = "" album_art_img = ""
# album_art_img = ttk.PhotoImage(file="album_art.png")
# canvas = ttk.Canvas(root, width=480, height=320)
# canvas.create_image(0, 0, image=album_art_img, anchor="nw")
# canvas.grid()
canvas = ttk.Canvas(root, width=480, height=320)
frame_artist_song = ttk.Frame(root, width=(1280/3), height=400, bg=bg_color) frame_artist_song = ttk.Frame(root, width=(1280/3), height=400, bg=bg_color)
# frame_controls = tk.Frame(root)
# lyrics_button = tk.Frame(root)
album_art_frame = ttk.Frame(root, bg=bg_color) album_art_frame = ttk.Frame(root, bg=bg_color)
lyrics_label_frame = ttk.Frame(root, width=(1280/3), height=400, bg=bg_color) lyrics_label_frame = ttk.Frame(root, width=(1280/3), height=400, bg=bg_color)
lyrics_label_frame.grid_propagate(0) lyrics_label_frame.grid_propagate(0)
@@ -232,7 +126,6 @@ root.grid_rowconfigure(1, weight=1)
root.grid_rowconfigure(2, weight=1) root.grid_rowconfigure(2, weight=1)
root.grid_columnconfigure(0, weight=1) root.grid_columnconfigure(0, weight=1)
root.grid_columnconfigure(1, weight=1) root.grid_columnconfigure(1, weight=1)
# root.grid_columnconfigure(2, weight=1)
root.configure(background=bg_color) root.configure(background=bg_color)
@@ -244,35 +137,18 @@ play_button = ttk.Label(frame_artist_song, image=play_img, borderwidth=0)
pause_button = ttk.Label(frame_artist_song, image=pause_img, borderwidth=0) pause_button = ttk.Label(frame_artist_song, image=pause_img, borderwidth=0)
next_button = ttk.Label(frame_artist_song, image=next_img, borderwidth=0) next_button = ttk.Label(frame_artist_song, image=next_img, borderwidth=0)
previous_button = ttk.Label(frame_artist_song, image=previous_img, borderwidth=0) previous_button = ttk.Label(frame_artist_song, image=previous_img, borderwidth=0)
maxvolume_button = tk.Button(root, text="Max Volume", command=maxvolume) artist_label = tk.Label(frame_artist_song, text="", font=("Helvetica", 24), wraplength=(1280/3), justify=ttk.CENTER, background=bg_color)
minvolume_button = tk.Button(root, text="Min Volume", command=minvolume) song_label = tk.Label(frame_artist_song, text="", font=("Helvetica", 32), wraplength=(1280/3), justify=ttk.CENTER, background=bg_color)
randomvolume_button = tk.Button(root, text="Random Volume", command=randomvolume)
volumeslider_button = tk.Scale(root, from_=100, to=0, orient=ttk.VERTICAL, length=240, command=volumeslider)
#doaudio_analysis = tk.Button(root, text="Audio Analysis", command=doaudioanalysis)
artist_label = tk.Label(frame_artist_song, text="", font=("Helvetica", 32), wraplength=(1280/3), justify=ttk.CENTER, background=bg_color)
song_label = tk.Label(frame_artist_song, text="", font=("Helvetica", 24), wraplength=(1280/3), justify=ttk.CENTER, background=bg_color)
track_progress_label = tk.Label(root, text="")
track_duration_label = tk.Label(root, text="")
# track_combined_label = tk.Label(root, text="")
track_search = tk.Entry(root, text="")
track_search_button = tk.Button(root, text="Search", command=search)
get_devices_button = tk.Button(root, text="Get Devices", command=get_devices) get_devices_button = tk.Button(root, text="Get Devices", command=get_devices)
start_playback_on_device_button = tk.Button(root, text="Start Playback on Device", command=start_playback_on_device) start_playback_on_device_button = tk.Button(root, text="Start Playback on Device", command=start_playback_on_device)
# hide_devices_button = tk.Button(root, text="Hide Devices", command=hide_devices)
username_label = tk.Label(root, text="Username: " + spotify.me()["display_name"])
devices_list = ttk.Listbox(root, selectmode=ttk.SINGLE, font=("Helvetica", 18)) devices_list = ttk.Listbox(root, selectmode=ttk.SINGLE, font=("Helvetica", 18))
progress_bar = tk.Progressbar(root, orient=ttk.HORIZONTAL, length=1280) progress_bar = tk.Progressbar(root, orient=ttk.HORIZONTAL, length=1280)
searching_for_devices_label = tk.Label(root, text="Searching for Devices...", font=("Helvetica", 24)) searching_for_devices_label = tk.Label(root, text="Searching for Devices...", font=("Helvetica", 24))
device_name_label = tk.Label(frame_artist_song, text="", font=("Helvetica", 12)) device_name_label = tk.Label(frame_artist_song, text="", font=("Helvetica", 12))
# background_image_label = tk.Label(root, image=album_art_img)
lyrics_label = tk.Label(lyrics_label_frame, text="", font=("Helvetica", 32), wraplength=(1280/3), justify=ttk.CENTER, background=bg_color) lyrics_label = tk.Label(lyrics_label_frame, text="", font=("Helvetica", 32), wraplength=(1280/3), justify=ttk.CENTER, background=bg_color)
# loadLyrics_button = ttk.Button(lyrics_button, image=lyrics_img, command=loadLyrics_pressed, borderwidth=0)
# album_art_canvas = ttk.Canvas(root)
# album_art_canvas_create_image = album_art_canvas.create_image(0, 0, image=album_art_img)
album_art_label = tk.Label(album_art_frame, image=album_art_img) album_art_label = tk.Label(album_art_frame, image=album_art_img)
root.bind("<Return>", search)
lyrics_label.bind("<Button-1>", lambda e:unloadLyrics_pressed())
play_button.bind("<Button-1>", lambda e:play()) play_button.bind("<Button-1>", lambda e:play())
pause_button.bind("<Button-1>", lambda e:pause()) pause_button.bind("<Button-1>", lambda e:pause())
next_button.bind("<Button-1>", lambda e:next()) next_button.bind("<Button-1>", lambda e:next())
@@ -283,16 +159,9 @@ def update_song_label():
global lrc global lrc
global album_art_img global album_art_img
# Get the current playback information # Get the current playback information
while True: current_playback = spotify.current_playback()
try:
current_playback = spotify.current_playback()
break
except (spotipy.exceptions.SpotifyException, requests.exceptions.HTTPError):
createToken()
# If there is no current playback, set the text of the song label to "No playback" # If there is no current playback, set the text of the song label to "No playback"
if current_playback is None: if current_playback is None:
# nothing_playing_obj = '{"item": {"artists": [{"name": "Nothing Playing"}],"duration_ms": 0,"name": "Nothing Playing"},"progress_ms": 0}'
# current_playback = json.loads(nothing_playing_obj)
get_devices() get_devices()
# Update the song label every 1 second # Update the song label every 1 second
else: else:
@@ -300,44 +169,24 @@ def update_song_label():
artist_name = current_playback["item"]["artists"][0]["name"] artist_name = current_playback["item"]["artists"][0]["name"]
track_duration = current_playback["item"]["duration_ms"] track_duration = current_playback["item"]["duration_ms"]
track_progress = current_playback["progress_ms"] track_progress = current_playback["progress_ms"]
current_volume = current_playback["device"]["volume_percent"]
playing_status = current_playback["is_playing"] playing_status = current_playback["is_playing"]
device_name = current_playback["device"]["name"] device_name = current_playback["device"]["name"]
album_art_url = current_playback["item"]["album"]["images"][0]["url"] album_art_url = current_playback["item"]["album"]["images"][0]["url"]
track_progress_min = track_progress//(1000*60)%60 track_progress_min = track_progress//(1000*60)%60
track_progress_sec = (track_progress//1000)%60 track_progress_sec = (track_progress//1000)%60
track_duration_min = track_duration//(1000*60)%60
track_duration_sec = (track_duration//1000)%60
# open_url = urlopen(album_art_url)
# raw_image_data = open_url.read()
# open_url.close()
# album_art = ImageTk.PhotoImage(data=raw_image_data)
# background_image_label.config(image=album_art)
# print(background_image_label.cget("image"))
# if raw_image_data == background_image_label.cget("image"):
# print("this is the same image")
# else:
# pass
# loadNow_playing()
if track_name == song_label.cget("text"): if track_name == song_label.cget("text"):
track_progress_formatted = ("{}:{:02d}".format(track_progress_min, track_progress_sec)) track_progress_formatted = ("{}:{:02d}".format(track_progress_min, track_progress_sec))
track_progress_label.config(text=track_progress_formatted)
progress_bar.config(maximum=track_duration) progress_bar.config(maximum=track_duration)
progress_bar.config(value=track_progress) progress_bar.config(value=track_progress)
for line in str(lrc).splitlines(): for line in str(lrc).splitlines():
if track_progress_formatted in line: if track_progress_formatted in line:
lyric = line.split("]")[1] lyric = line.split("]")[1]
# wrapped_lyric = textwrap.fill(lyric, 21)
lyrics_label.config(text=lyric) lyrics_label.config(text=lyric)
root.after(800, update_song_label) root.after(800, update_song_label)
else: else:
# album_art_data = Image.open(requests.get(album_art_url, stream=True).raw)
# album_art_data.save("album_art.jpg")
device_name_label.config(text=device_name) device_name_label.config(text=device_name)
song_label.config(text=track_name) song_label.config(text=track_name)
artist_label.config(text=artist_name) artist_label.config(text=artist_name)
track_duration_label.config(text=("{}:{:02d}".format(track_duration_min, track_duration_sec)))
volumeslider_button.set(value=current_volume)
lyrics_label.config(text="") lyrics_label.config(text="")
lrc = syncedlyrics.search("[" + track_name + "] [" + artist_name + "]") lrc = syncedlyrics.search("[" + track_name + "] [" + artist_name + "]")
album_art_img_data = requests.get(album_art_url).content album_art_img_data = requests.get(album_art_url).content
@@ -358,7 +207,7 @@ def update_song_label():
previous_button.config(background=bg_color) previous_button.config(background=bg_color)
lyrics_label_frame.config(background=bg_color) lyrics_label_frame.config(background=bg_color)
lyrics_label.config(background=bg_color) lyrics_label.config(background=bg_color)
if math.sqrt(0.299 * (bg_color_img_pixel[0] ** 2) + 0.587 * (bg_color_img_pixel[1] ** 2) + 0.114 * (bg_color_img_pixel[2] ** 2)) > 186: if math.sqrt(0.299 * (bg_color_img_pixel[0] ** 2) + 0.587 * (bg_color_img_pixel[1] ** 2) + 0.114 * (bg_color_img_pixel[2] ** 2)) > 170:
song_label.config(foreground="black") song_label.config(foreground="black")
artist_label.config(foreground="black") artist_label.config(foreground="black")
device_name_label.config(foreground="black") device_name_label.config(foreground="black")
@@ -376,17 +225,7 @@ def update_song_label():
pause_button.config(image=pause_img) pause_button.config(image=pause_img)
next_button.config(image=next_img) next_button.config(image=next_img)
previous_button.config(image=previous_img) previous_button.config(image=previous_img)
# album_art_label.grid_forget()
# album_art_label.grid()
root.after(500, update_song_label) root.after(500, update_song_label)
# if album_art_url == "12345":
# open_url = urlopen(album_art_url)
# raw_image_data = open_url.read()
# open_url.close()
# album_art = ImageTk.PhotoImage(data=raw_image_data)
# background_image_label.config(image=album_art)
# else:
# pass
if playing_status == True: if playing_status == True:
play_button.grid_forget() play_button.grid_forget()
pause_button.grid(row=3, column=1, pady=(100,0)) pause_button.grid(row=3, column=1, pady=(100,0))
@@ -397,15 +236,10 @@ def update_song_label():
pass pass
def loadNow_playing(): def loadNow_playing():
# background_image_label.place(x=0, y=0)
# volumeslider_button.grid(row=1, column=1, rowspan=3, sticky="e", padx=(0,20))
# lyrics_button.grid(row=1, column=1, padx=(0,380))
frame_artist_song.grid(row=0, column=1, rowspan=3, pady=(20,0)) frame_artist_song.grid(row=0, column=1, rowspan=3, pady=(20,0))
# frame_controls.grid(row=2, column=1)
# loadLyrics_button.grid()
device_name_label.grid(row=0, column=1) device_name_label.grid(row=0, column=1)
artist_label.grid(row=1, column=1) artist_label.grid(row=2, column=1)
song_label.grid(row=2, column=1) song_label.grid(row=1, column=1)
previous_button.grid(row=3, column=1, padx=(0,200), pady=(100,0)) previous_button.grid(row=3, column=1, padx=(0,200), pady=(100,0))
play_button.grid(row=3, column=1, pady=(100,0)) play_button.grid(row=3, column=1, pady=(100,0))
next_button.grid(row=3, column=1, padx=(200,0), pady=(100,0)) next_button.grid(row=3, column=1, padx=(200,0), pady=(100,0))
@@ -416,16 +250,15 @@ def loadNow_playing():
lyrics_label.grid() lyrics_label.grid()
def unloadNow_playing(): def unloadNow_playing():
volumeslider_button.grid_forget() device_name_label.grid_forget()
frame_artist_song.grid_forget()
# frame_controls.grid_forget()
artist_label.grid_forget() artist_label.grid_forget()
song_label.grid_forget() song_label.grid_forget()
previous_button.grid_forget() previous_button.grid_forget()
play_button.grid_forget() play_button.grid_forget()
next_button.grid_forget() next_button.grid_forget()
progress_bar.grid_forget() progress_bar.grid_forget()
# loadLyrics_button.grid_forget() lyrics_label.grid_forget()
album_art_label.grid_forget()
def loadDevices_list(): def loadDevices_list():
devices_list.grid(row=1, column=1, pady=10) devices_list.grid(row=1, column=1, pady=10)
@@ -441,18 +274,9 @@ def loadSearching_Devices():
def unloadSearching_Devices(): def unloadSearching_Devices():
searching_for_devices_label.grid_forget() searching_for_devices_label.grid_forget()
def loadLyrics():
album_art_frame.grid(row=0, column=1)
album_art_label.grid()
lyrics_label.grid(row=0, column=1)
def unloadLyrics():
album_art_frame.grid_forget()
album_art_label.grid_forget()
lyrics_label.grid_forget()
# Start updating the song label # Start updating the song label
wait_for_connection() # setup()
loadNow_playing() loadNow_playing()
update_song_label() update_song_label()

11
spotify-gui.service Normal file
View File

@@ -0,0 +1,11 @@
[Unit]
Description=Spotify GUI
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=pi
WorkingDirectory=/opt/spotify-gui
ExecStart=xinit ./start.sh $* -- :0 vt$XDG_VTNR -nocursor
[Install]
WantedBy=multi-user.target

View File

@@ -9,3 +9,21 @@ selection resets after 1 second on devices list; need to remove root.after in up
01/14/23: 01/14/23:
smooth progress bar smooth progress bar
01/15/23:
turns off screen and stops polling api after inactivity, reauthenticates when
screen is turned back on
01/18/23:
turn off screen when holding down on album art.
01/20/2023:
background gradient
01/21/2023:
it errors on "track_name = current_playback["item"]["name"]"
'TypeError: NoneType', current_playback is None basically... even though there is already an if statement checking if it is None.
ERROR HAPPENS ON SOME KIDZ BOP SONGS???
01/21/2023:
add canvas videos to background if available. USE: https://github.com/Delitefully/spotify-canvas-downloader/blob/master/src/canvas.py

18
update.py Normal file
View File

@@ -0,0 +1,18 @@
import urllib
from urllib.request import urlopen
from zipfile import ZipFile
from io import BytesIO
while True:
try:
urlopen('http://bbrunson.com', timeout=1)
break
except:
pass
try:
with ZipFile(BytesIO((urlopen('http://files.bbrunson.com/spotify-gui/update.zip')).read())) as zipObj:
zipObj.extractall()
except urllib.error.HTTPError:
pass
exec(open('program-embedded.py').read())