Files
spotify-gui/program-embedded-util.py
2023-01-21 00:48:00 -08:00

472 lines
19 KiB
Python

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()