import spotipy import spotipy.util import tkinter as ttk from tkinter import ttk as tk import random import json import sv_ttk from urllib.request import urlopen import requests from time import sleep import sys import os import pyautogui import threading import platform import syncedlyrics import textwrap # 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$" def wait_for_connection(): while True: try: urlopen('http://142.250.189.174', timeout=1) return True except: pass # 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 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() 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 def createToken(): spotify = spotipy.Spotify(auth=token) return spotify spotify = createToken() # Create the tkinter window root = ttk.Tk() root.title("Media Controller") root.geometry("480x320") 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") lyrics_img = ttk.PhotoImage(file="icons/lyrics.png") # 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() frame_artist_song = tk.Frame(root) frame_controls = tk.Frame(root) lyrics_button = tk.Frame(root) root.grid_rowconfigure(0, weight=1) root.grid_rowconfigure(1, weight=1) root.grid_rowconfigure(2, weight=1) root.grid_rowconfigure(3, weight=1) root.grid_columnconfigure(0, weight=1) root.grid_columnconfigure(1, weight=1) root.grid_columnconfigure(2, weight=1) # Create the media control buttons and a text label play_button = ttk.Button(frame_controls, image=play_img, command=play, borderwidth=0, relief=None) pause_button = ttk.Button(frame_controls, image=pause_img, command=pause, borderwidth=0) next_button = ttk.Button(frame_controls, image=next_img, command=next, borderwidth=0) previous_button = ttk.Button(frame_controls, image=previous_img, command=previous, 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", 32)) song_label = tk.Label(frame_artist_song, text="", font=("Helvetica", 24)) 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=480) 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(root, text="", font=("Helvetica", 32)) loadLyrics_button = ttk.Button(lyrics_button, image=lyrics_img, command=loadLyrics_pressed, borderwidth=0) now_playing_button = tk.Button(root, text="Now Playing", command=unloadLyrics_pressed) root.bind("", search) play_button.bind("<>", lambda e: frame_artist_song.focus()) # Function to update the song label with the current track's name def update_song_label(): global lrc # Get the current playback information try: current_playback = spotify.current_playback() except (spotipy.exceptions.SpotifyException, requests.exceptions.HTTPError): createToken() pass # 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: try: track_name = current_playback["item"]["name"] pass except TypeError: sleep(1) update_song_label() 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) print(track_progress_formatted) 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=wrapped_lyric) root.after(850, 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 + "]") 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=0, column=1) elif playing_status == False: pause_button.grid_forget() play_button.grid(row=0, column=1) 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=1, column=1, pady=(0,5)) frame_controls.grid(row=2, column=1, pady=(20,0)) loadLyrics_button.grid() device_name_label.grid(pady=(0,5)) artist_label.grid() song_label.grid() previous_button.grid(row=0, column=0, padx=(0,10)) play_button.grid(row=0, column=1) next_button.grid(row=0, column=2, padx=(10,0)) progress_bar.grid(row=3, column=1) def unloadNow_playing(): volumeslider_button.grid_forget() frame_artist_song.grid_forget() frame_controls.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() 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(): now_playing_button.grid(row=0, column=1) lyrics_label.grid(row=1, column=1, pady=20) def unloadLyrics(): now_playing_button.grid_forget() lyrics_label.grid_forget() # Start updating the song label wait_for_connection() loadNow_playing() update_song_label() # Run the GUI root.mainloop()