Files
spotify-gui/program.py
Brandon4466 fcb3132d6a - volume slider of device will be grabbed on start
- if no music is playing, device list will appear that keeps searching
2022-12-17 02:53:07 -08:00

284 lines
11 KiB
Python

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("-fullscreen", True)
root.overrideredirect(1)
# root.geometry("380x160")
sv_ttk.use_dark_theme()
# tkinter theme
# Function to call the Spotify API to play the current track
def play():
play_button.grid_forget()
pause_button.grid(row=0, column=1)
spotify.start_playback()
# Function to call the Spotify API to pause the current track
def pause():
pause_button.grid_forget()
play_button.grid(row=0, column=1)
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)
play_img = ttk.PhotoImage(file="icons/play-circle.png")
pause_img = ttk.PhotoImage(file="icons/pause-circle.png")
next_img = ttk.PhotoImage(file="icons/skip-next.png")
previous_img = ttk.PhotoImage(file="icons/skip-previous.png")
frame_artist_song = tk.Frame(root)
frame_controls = tk.Frame(root)
# 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, command=volumeslider)
#doaudio_analysis = tk.Button(root, text="Audio Analysis", command=doaudioanalysis)
artist_label = tk.Label(frame_artist_song, text="")
song_label = tk.Label(frame_artist_song, 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=300)
# 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="")
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)
# frame.pack()
# frame2.pack()
# Place the media control buttons and text label on the window
# username_label.grid(row=0, column=0, columnspan=2)
# minvolume_button.grid(row=1, column=1, sticky="e", padx=(0,5))
# maxvolume_button.grid()
# randomvolume_button.grid()
volumeslider_button.grid(row=1, column=1, rowspan=3, sticky="e", padx=(0,5))
frame_artist_song.grid(row=1, column=1, pady=(20,5))
frame_controls.grid(row=2, column=1, pady=(20,0))
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))
# track_progress_label.grid(row=3, column=0, pady=(20,5), padx=10)
progress_bar.grid(row=3, column=1, pady=(20,5))
# track_duration_label.grid(row=3, column=2, pady=(20,5), padx=10)
# pause_button.grid()
# track_combined_label.grid()
# track_search.grid()
# track_search_button.grid()
# get_devices_button.grid()
#doaudio_analysis.pack()
#audio_analysis.pack()
# start_local_playback_button.pack()
# audio_analysis_button.pack()
# album_image_label.pack()
root.bind("<Return>", 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_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_progress_label.config(text=("{}:{:02d}".format(track_progress_min, track_progress_sec)))
track_duration_label.config(text=("{}:{:02d}".format(track_duration_min, track_duration_sec)))
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_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()