import spotipy from spotipy.oauth2 import SpotifyOAuth 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 # Get the user's Spotify authorization token scope = "user-read-playback-state,user-modify-playback-state" # Create a Spotify object with the user's authorization token spotify = spotipy.Spotify(auth_manager=SpotifyOAuth(client_id=client_id, client_secret=client_secret, redirect_uri=redirect_uri, scope=scope, requests_timeout=30)) bg_color = "#000000" count = 0 # 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 start_playback_on_device(): device_selections = devices_list.curselection() list_of_devices = spotify.devices() 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(): # count +=1 # if count >= 277: 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) 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) 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") album_art_img = "" frame_artist_song = ttk.Frame(root, width=(1280/3), height=400, 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.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.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) 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) 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) 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)) lyrics_label = tk.Label(lyrics_label_frame, text="", font=("Helvetica", 32), wraplength=(1280/3), justify=ttk.CENTER, background=bg_color) album_art_label = tk.Label(album_art_frame, image=album_art_img) play_button.bind("", lambda e:play()) pause_button.bind("", lambda e:pause()) next_button.bind("", lambda e:next()) previous_button.bind("", 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 current_playback = spotify.current_playback() # If there is no current playback, set the text of the song label to "No playback" if current_playback is None: 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"] 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 if track_name == song_label.cget("text"): track_progress_formatted = ("{}:{:02d}".format(track_progress_min, track_progress_sec)) 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] lyrics_label.config(text=lyric) root.after(800, update_song_label) else: device_name_label.config(text=device_name) song_label.config(text=track_name) artist_label.config(text=artist_name) 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) root.after(500, update_song_label) 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(): frame_artist_song.grid(row=0, column=1, rowspan=3, pady=(20,0)) 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(): 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() 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() # Start updating the song label # setup() loadNow_playing() update_song_label() # Run the GUI root.mainloop()