import spotipy import spotipy.util import tkinter as ttk from tkinter import ttk as tk import random import json import requests import io from PIL import Image import urllib.request import os from win10toast import ToastNotifier import sv_ttk from librespot.core import Session from librespot.metadata import TrackId from librespot.audio.decoders import AudioQuality, VorbisOnlyAudioQuality # 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" # Get the user's Spotify authorization token scope = "user-read-playback-state,user-modify-playback-state" token = spotipy.util.prompt_for_user_token(username, scope, client_id, client_secret, redirect_uri) session = Session.Builder() \ .user_pass("thebrandon45", "Mariposa2502$") \ .create() # Create a Spotify object with the user's authorization token spotify = spotipy.Spotify(auth=token) # Create the tkinter window root = ttk.Tk() root.title("Media Controller") root.attributes("-topmost", True) sv_ttk.use_dark_theme() # tkinter 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) # elif not searched.startswith(":"): # search_results = spotify.search(q=searched, type='track,artist,album,playlist') # searched_track_id = search_results[0]["items"]["uri"] # print(searched_track_id) # spotify.start_playback(uris=searched_track_id) def start_playback_on_device(): device_selections = devices_list.curselection() list_of_devices = spotify.devices() device_id = list_of_devices["devices"][device_selections[0]]["id"] spotify.transfer_playback(device_id=device_id) toast = ToastNotifier() toast.show_toast("Spotify Media Controller", "Playback started on " + list_of_devices["devices"][device_selections[0]]["name"], duration=5, threaded=True) def get_devices(): 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"]) # devices_list_one = list_of_devices["devices"][0]["name"] # devices_list_two = list_of_devices["devices"][1]["name"] # devices_list.insert(0, devices_list_one) # devices_list.insert(1, devices_list_two) get_devices_button.pack_forget() hide_devices_button.pack() devices_list.pack() start_playback_on_device_button.pack() def hide_devices(): get_devices_button.pack() devices_list.pack_forget() start_playback_on_device_button.pack_forget() hide_devices_button.pack_forget() # def start_local_playback(): # track_id = TrackId.from_uri("spotify:track:0CiZrDrw1traECxGLXolm7") # stream = session.content_feeder().load(track_id, VorbisOnlyAudioQuality(AudioQuality.VERY_HIGH), False, None) # stream.input_stream().read(1024) # def audioanalysis(): # current_playback = spotify.current_playback() # track_id = current_playback["item"]["id"] # audio_analysis = spotify.audio_analysis(track_id) # audio_analysis_label.pack() # audio_analysis_label.config(text=audio_analysis) # frame = tk.Frame(root) # frame2 = tk.Frame(root) # Create the media control buttons and a text label play_button = tk.Button(root, text="Play", command=play) pause_button = tk.Button(root, text="Pause", command=pause) next_button = tk.Button(root, text="Next", command=next) previous_button = tk.Button(root, text="Previous", command=previous) 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_=0, to=100, orient=ttk.HORIZONTAL, command=volumeslider) #doaudio_analysis = tk.Button(root, text="Audio Analysis", command=doaudioanalysis) artist_label = tk.Label(root, text="") song_label = tk.Label(root, text="") 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"]) # audio_analysis_button = tk.Button(root, text="Audio Analysis", command=audioanalysis) # audio_analysis_label = tk.Label(root, text="") devices_list = ttk.Listbox(root, selectmode=ttk.SINGLE) progress_bar = tk.Progressbar(root, orient=ttk.HORIZONTAL, length=180) # Play music locally # start_local_playback_button = tk.Button(root, text="Start Local Playback", command=start_local_playback) # album_image_label = tk.Label(root, image="") #audio_analysis = tk.Label(root, text="") #track_label = tk.Label(root, text="") # frame.pack() # frame2.pack() # Place the media control buttons and text label on the window username_label.pack() maxvolume_button.pack() minvolume_button.pack() randomvolume_button.pack() volumeslider_button.pack() artist_label.pack() song_label.pack() #doaudio_analysis.pack() #audio_analysis.pack() play_button.pack() pause_button.pack() next_button.pack() previous_button.pack() track_combined_label.pack() progress_bar.pack() track_search.pack() track_search_button.pack() get_devices_button.pack() # start_local_playback_button.pack() # audio_analysis_button.pack() # album_image_label.pack() root.bind("", search) # Function to update the song label with the current track's name def update_song_label(): # 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: 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 the current track's name track_name = current_playback["item"]["name"] artist_name = current_playback["item"]["artists"][0]["name"] track_progress = current_playback["progress_ms"] track_duration = current_playback["item"]["duration_ms"] # album_image_url = current_playback["item"]["album"]["images"][0]["url"] # track_id = current_playback["item"]["id"] # Set the text of the song label to the track's name song_label.config(text=track_name) artist_label.config(text=artist_name) track_progress_label.config(text=((track_progress//(1000*60))%60, "m", (track_progress//1000)%60, "s")) track_duration_label.config(text=((track_duration//(1000*60))%60, "m", (track_duration//1000)%60, "s")) progress_bar.config(maximum=track_duration) progress_bar.config(value=track_progress) # urllib.request.urlretrieve(album_image_url, "album_image.jpg") # image_data = tk.PhotoImage("album_image.jpg") # album_image_label.config(image=image_data) 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 track_combined_label.config(text=("{}:{:02d} / {}:{:02d}".format(track_progress_min, track_progress_sec, track_duration_min, track_duration_sec))) # track_combined_label.config(text=((track_progress//(1000*60))%60, ":", (track_progress//1000)%60, "/", (track_duration//(1000*60))%60, ":", (track_duration//1000)%60)) # track_label.config(text=track_id) # print(json.dumps(current_playback, indent=4, sort_keys=True)) # Update the song label every 1 second root.after(1000, update_song_label) # Start updating the song label update_song_label() # Run the GUI root.mainloop()