auto-login headless login added
This commit is contained in:
@@ -1 +1 @@
|
|||||||
{"access_token": "BQDi5JTAjQCSNArackjHJE8bQ3Gbb_MDBdIUHEbiKZRAzA0k3PSJRd-1IytW8Ez0OQSZnLczyhp3rl2ZB7vdklSz0lTn2b4yTYgLYe2jBrmznYsnTOHAkaNFWtYjy5skxrq6xV24MSoLsZocXFd96ozn-1Hc3752XMmq4hVkBFUR5I3WlTFc9IHdOjjCVA", "token_type": "Bearer", "expires_in": 3600, "scope": "user-modify-playback-state user-read-playback-state", "expires_at": 1671273275, "refresh_token": "AQAQRkRkmOxwR34lsJu_mpG4wxEFiNuJ1FIdmHYN5j0dClEEqMRqPPFX8jM3cQTQkRpeXXyi3xPQ8YImc7Fc-PH1CKTvyARy9VkMKXIes4-l6ijO9fVMyCNwbI0IGvpfrqE"}
|
{"access_token": "BQAqKVHJsNl_kpE1qwGfqWAnFRKSPdrXMdJUuIkquM2H0gqmIeQFJJfNoOwib9R0JKFSvB7ZUyB1IlpzyHBAY0QQpvqdqorQXj4fraqgHVUCvQpb7Bg6ee4wn_urnF7nSzaZe7fnNEHZIH18XqSCSx73XoPk-UdTkvi3kxxOO6vH8tsAah7GHEUnrMlG7g", "token_type": "Bearer", "expires_in": 3600, "refresh_token": "AQDs4x9WTbYtoqePbR9tvRWCcJHs1Hh3vrXpIHBtBdkJIDJ-Mu14B-vLEqOnowqw1HzZI5H5ytOFS2y9xBCcDyDU0uMA_D0MRPtujyCUYb9sdnD-D6WC2fN7bFiGeoo-YAo", "scope": "user-modify-playback-state user-read-playback-state", "expires_at": 1673401175}
|
||||||
BIN
album_art.jpg
Normal file
BIN
album_art.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 57 KiB |
BIN
album_art.png
Normal file
BIN
album_art.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 21 KiB |
@@ -5,6 +5,14 @@ from tkinter import ttk as tk
|
|||||||
import random
|
import random
|
||||||
import json
|
import json
|
||||||
import sv_ttk
|
import sv_ttk
|
||||||
|
from urllib.request import urlopen
|
||||||
|
import requests
|
||||||
|
from time import sleep
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
import pyautogui
|
||||||
|
import threading
|
||||||
|
import platform
|
||||||
|
|
||||||
# Set the Spotify app's client ID and client secret
|
# Set the Spotify app's client ID and client secret
|
||||||
client_id = "69b82a34d0fb40be80b020eae8e80f25"
|
client_id = "69b82a34d0fb40be80b020eae8e80f25"
|
||||||
@@ -13,11 +21,61 @@ redirect_uri = "http://127.0.0.1:8888/callback"
|
|||||||
|
|
||||||
# Set the user's Spotify username
|
# Set the user's Spotify username
|
||||||
username = "thebrandon45"
|
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
|
# Get the user's Spotify authorization token
|
||||||
scope = "user-read-playback-state,user-modify-playback-state"
|
scope = "user-read-playback-state,user-modify-playback-state"
|
||||||
token = spotipy.util.prompt_for_user_token(username, scope, client_id, client_secret, redirect_uri)
|
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
|
# Create a Spotify object with the user's authorization token
|
||||||
spotify = spotipy.Spotify(auth=token)
|
spotify = spotipy.Spotify(auth=token)
|
||||||
|
|
||||||
@@ -29,12 +87,6 @@ root.attributes("-topmost", True)
|
|||||||
root.overrideredirect(1)
|
root.overrideredirect(1)
|
||||||
sv_ttk.use_dark_theme()
|
sv_ttk.use_dark_theme()
|
||||||
|
|
||||||
rootDevices = ttk.Tk()
|
|
||||||
rootDevices.title("Media Controller")
|
|
||||||
rootDevices.geometry("480x320")
|
|
||||||
rootDevices.attributes("-topmost", True)
|
|
||||||
rootDevices.overrideredirect(1)
|
|
||||||
|
|
||||||
# Function to call the Spotify API to play the current track
|
# Function to call the Spotify API to play the current track
|
||||||
def play():
|
def play():
|
||||||
spotify.start_playback()
|
spotify.start_playback()
|
||||||
@@ -90,27 +142,45 @@ def start_playback_on_device():
|
|||||||
device_id = list_of_devices["devices"][device_selections[0]]["id"]
|
device_id = list_of_devices["devices"][device_selections[0]]["id"]
|
||||||
spotify.transfer_playback(device_id=device_id)
|
spotify.transfer_playback(device_id=device_id)
|
||||||
|
|
||||||
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"])
|
|
||||||
get_devices_button.pack_forget()
|
|
||||||
hide_devices_button.pack()
|
|
||||||
devices_list.pack()
|
|
||||||
start_playback_on_device_button.pack()
|
|
||||||
|
|
||||||
def hide_devices():
|
def get_devices():
|
||||||
get_devices_button.pack()
|
list_of_devices = spotify.devices()
|
||||||
devices_list.pack_forget()
|
unloadNow_playing()
|
||||||
start_playback_on_device_button.pack_forget()
|
if list_of_devices == "{'devices': []}":
|
||||||
hide_devices_button.pack_forget()
|
unloadDevices_list()
|
||||||
|
loadSearching_Devices()
|
||||||
|
root.after(1000, get_devices)
|
||||||
|
else:
|
||||||
|
current_playback = spotify.current_playback()
|
||||||
|
if current_playback != None:
|
||||||
|
unloadSearching_Devices()
|
||||||
|
unloadDevices_list()
|
||||||
|
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)
|
||||||
|
|
||||||
|
# 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")
|
play_img = ttk.PhotoImage(file="icons/play-circle-x2.png")
|
||||||
pause_img = ttk.PhotoImage(file="icons/pause-circle-x2.png")
|
pause_img = ttk.PhotoImage(file="icons/pause-circle-x2.png")
|
||||||
next_img = ttk.PhotoImage(file="icons/skip-next-x2.png")
|
next_img = ttk.PhotoImage(file="icons/skip-next-x2.png")
|
||||||
previous_img = ttk.PhotoImage(file="icons/skip-previous-x2.png")
|
previous_img = ttk.PhotoImage(file="icons/skip-previous-x2.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_artist_song = tk.Frame(root)
|
||||||
frame_controls = tk.Frame(root)
|
frame_controls = tk.Frame(root)
|
||||||
@@ -133,30 +203,22 @@ minvolume_button = tk.Button(root, text="Min Volume", command=minvolume)
|
|||||||
randomvolume_button = tk.Button(root, text="Random Volume", command=randomvolume)
|
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)
|
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)
|
#doaudio_analysis = tk.Button(root, text="Audio Analysis", command=doaudioanalysis)
|
||||||
artist_label = tk.Label(frame_artist_song, text="", font=("Helvetica", 24))
|
artist_label = tk.Label(frame_artist_song, text="", font=("Helvetica", 32))
|
||||||
song_label = tk.Label(frame_artist_song, text="", font=("Helvetica", 24))
|
song_label = tk.Label(frame_artist_song, text="", font=("Helvetica", 24))
|
||||||
track_progress_label = tk.Label(root, text="")
|
track_progress_label = tk.Label(root, text="")
|
||||||
track_duration_label = tk.Label(root, text="")
|
track_duration_label = tk.Label(root, text="")
|
||||||
track_combined_label = tk.Label(root, text="")
|
# track_combined_label = tk.Label(root, text="")
|
||||||
track_search = tk.Entry(root, text="")
|
track_search = tk.Entry(root, text="")
|
||||||
track_search_button = tk.Button(root, text="Search", command=search)
|
track_search_button = tk.Button(root, text="Search", command=search)
|
||||||
get_devices_button = tk.Button(root, text="Get Devices", command=get_devices)
|
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)
|
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)
|
# hide_devices_button = tk.Button(root, text="Hide Devices", command=hide_devices)
|
||||||
username_label = tk.Label(root, text="Username: " + spotify.me()["display_name"])
|
username_label = tk.Label(root, text="Username: " + spotify.me()["display_name"])
|
||||||
devices_list = ttk.Listbox(root, selectmode=ttk.SINGLE)
|
devices_list = ttk.Listbox(root, selectmode=ttk.SINGLE, font=("Helvetica", 18))
|
||||||
|
|
||||||
progress_bar = tk.Progressbar(root, orient=ttk.HORIZONTAL, length=480)
|
progress_bar = tk.Progressbar(root, orient=ttk.HORIZONTAL, length=480)
|
||||||
volumeslider_button.grid(row=1, column=1, rowspan=3, sticky="e", padx=(0,20))
|
searching_for_devices_label = tk.Label(root, text="Searching for Devices...", font=("Helvetica", 24))
|
||||||
frame_artist_song.grid(row=1, column=1, pady=(20,5))
|
device_name_label = tk.Label(frame_artist_song, text="", font=("Helvetica", 12))
|
||||||
frame_controls.grid(row=2, column=1, pady=(20,0))
|
# background_image_label = tk.Label(root, image=album_art_img)
|
||||||
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, pady=(20,0))
|
|
||||||
|
|
||||||
root.bind("<Return>", search)
|
root.bind("<Return>", search)
|
||||||
|
|
||||||
@@ -168,45 +230,106 @@ def update_song_label():
|
|||||||
if current_playback is None:
|
if current_playback is None:
|
||||||
# nothing_playing_obj = '{"item": {"artists": [{"name": "Nothing Playing"}],"duration_ms": 0,"name": "Nothing Playing"},"progress_ms": 0}'
|
# nothing_playing_obj = '{"item": {"artists": [{"name": "Nothing Playing"}],"duration_ms": 0,"name": "Nothing Playing"},"progress_ms": 0}'
|
||||||
# current_playback = json.loads(nothing_playing_obj)
|
# current_playback = json.loads(nothing_playing_obj)
|
||||||
track_name = "Nothing Playing"
|
get_devices()
|
||||||
artist_name = "Nothing Playing"
|
# Update the song label every 1 second
|
||||||
track_progress = 0
|
|
||||||
track_duration = 0
|
|
||||||
current_volume = 0
|
|
||||||
playing_status = False
|
|
||||||
else:
|
else:
|
||||||
track_name = current_playback["item"]["name"]
|
track_name = current_playback["item"]["name"]
|
||||||
artist_name = current_playback["item"]["artists"][0]["name"]
|
artist_name = current_playback["item"]["artists"][0]["name"]
|
||||||
track_progress = current_playback["progress_ms"]
|
|
||||||
track_duration = current_playback["item"]["duration_ms"]
|
track_duration = current_playback["item"]["duration_ms"]
|
||||||
|
track_progress = current_playback["progress_ms"]
|
||||||
current_volume = current_playback["device"]["volume_percent"]
|
current_volume = current_playback["device"]["volume_percent"]
|
||||||
playing_status = current_playback["is_playing"]
|
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_label.config(text=("{}:{:02d}".format(track_progress_min, track_progress_sec)))
|
||||||
|
progress_bar.config(maximum=track_duration)
|
||||||
|
progress_bar.config(value=track_progress)
|
||||||
|
root.after(1000, 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)
|
||||||
|
root.after(1000, 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))
|
||||||
|
frame_artist_song.grid(row=1, column=1, pady=(0,5))
|
||||||
|
frame_controls.grid(row=2, column=1, pady=(20,0))
|
||||||
|
device_name_label.grid(pady=(0,10))
|
||||||
|
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()
|
||||||
|
|
||||||
|
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()
|
||||||
|
|
||||||
# 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)
|
|
||||||
track_combined_label.config(text=("{}:{:02d} / {}:{:02d}".format(track_progress_min, track_progress_sec, track_duration_min, track_duration_sec)))
|
|
||||||
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
|
|
||||||
|
|
||||||
# Update the song label every 1 second
|
|
||||||
root.after(1000, update_song_label)
|
|
||||||
|
|
||||||
# Start updating the song label
|
# Start updating the song label
|
||||||
|
|
||||||
|
wait_for_connection()
|
||||||
update_song_label()
|
update_song_label()
|
||||||
|
|
||||||
# Run the GUI
|
# Run the GUI
|
||||||
|
|||||||
8
spotify-gui.code-workspace
Normal file
8
spotify-gui.code-workspace
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"folders": [
|
||||||
|
{
|
||||||
|
"path": "."
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"settings": {}
|
||||||
|
}
|
||||||
BIN
spotify-gui.zip
BIN
spotify-gui.zip
Binary file not shown.
370
testing.txt
370
testing.txt
@@ -39,190 +39,7 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"available_markets": [
|
"available_markets": [
|
||||||
"AD",
|
"US"
|
||||||
"AE",
|
|
||||||
"AG",
|
|
||||||
"AL",
|
|
||||||
"AM",
|
|
||||||
"AO",
|
|
||||||
"AR",
|
|
||||||
"AT",
|
|
||||||
"AU",
|
|
||||||
"AZ",
|
|
||||||
"BA",
|
|
||||||
"BB",
|
|
||||||
"BD",
|
|
||||||
"BE",
|
|
||||||
"BF",
|
|
||||||
"BG",
|
|
||||||
"BH",
|
|
||||||
"BI",
|
|
||||||
"BJ",
|
|
||||||
"BN",
|
|
||||||
"BO",
|
|
||||||
"BR",
|
|
||||||
"BS",
|
|
||||||
"BT",
|
|
||||||
"BW",
|
|
||||||
"BY",
|
|
||||||
"BZ",
|
|
||||||
"CA",
|
|
||||||
"CD",
|
|
||||||
"CG",
|
|
||||||
"CH",
|
|
||||||
"CI",
|
|
||||||
"CL",
|
|
||||||
"CM",
|
|
||||||
"CO",
|
|
||||||
"CR",
|
|
||||||
"CV",
|
|
||||||
"CW",
|
|
||||||
"CY",
|
|
||||||
"CZ",
|
|
||||||
"DE",
|
|
||||||
"DJ",
|
|
||||||
"DK",
|
|
||||||
"DM",
|
|
||||||
"DO",
|
|
||||||
"DZ",
|
|
||||||
"EC",
|
|
||||||
"EE",
|
|
||||||
"EG",
|
|
||||||
"ES",
|
|
||||||
"ET",
|
|
||||||
"FI",
|
|
||||||
"FJ",
|
|
||||||
"FM",
|
|
||||||
"FR",
|
|
||||||
"GA",
|
|
||||||
"GB",
|
|
||||||
"GD",
|
|
||||||
"GE",
|
|
||||||
"GH",
|
|
||||||
"GM",
|
|
||||||
"GN",
|
|
||||||
"GQ",
|
|
||||||
"GR",
|
|
||||||
"GT",
|
|
||||||
"GW",
|
|
||||||
"GY",
|
|
||||||
"HK",
|
|
||||||
"HN",
|
|
||||||
"HR",
|
|
||||||
"HT",
|
|
||||||
"HU",
|
|
||||||
"ID",
|
|
||||||
"IE",
|
|
||||||
"IL",
|
|
||||||
"IN",
|
|
||||||
"IQ",
|
|
||||||
"IS",
|
|
||||||
"IT",
|
|
||||||
"JM",
|
|
||||||
"JO",
|
|
||||||
"JP",
|
|
||||||
"KE",
|
|
||||||
"KG",
|
|
||||||
"KH",
|
|
||||||
"KI",
|
|
||||||
"KM",
|
|
||||||
"KN",
|
|
||||||
"KR",
|
|
||||||
"KW",
|
|
||||||
"KZ",
|
|
||||||
"LA",
|
|
||||||
"LB",
|
|
||||||
"LC",
|
|
||||||
"LI",
|
|
||||||
"LK",
|
|
||||||
"LR",
|
|
||||||
"LS",
|
|
||||||
"LT",
|
|
||||||
"LU",
|
|
||||||
"LV",
|
|
||||||
"LY",
|
|
||||||
"MA",
|
|
||||||
"MC",
|
|
||||||
"MD",
|
|
||||||
"ME",
|
|
||||||
"MG",
|
|
||||||
"MH",
|
|
||||||
"MK",
|
|
||||||
"ML",
|
|
||||||
"MN",
|
|
||||||
"MO",
|
|
||||||
"MR",
|
|
||||||
"MT",
|
|
||||||
"MU",
|
|
||||||
"MV",
|
|
||||||
"MW",
|
|
||||||
"MX",
|
|
||||||
"MY",
|
|
||||||
"MZ",
|
|
||||||
"NA",
|
|
||||||
"NE",
|
|
||||||
"NG",
|
|
||||||
"NI",
|
|
||||||
"NL",
|
|
||||||
"NO",
|
|
||||||
"NP",
|
|
||||||
"NR",
|
|
||||||
"NZ",
|
|
||||||
"OM",
|
|
||||||
"PA",
|
|
||||||
"PE",
|
|
||||||
"PG",
|
|
||||||
"PH",
|
|
||||||
"PK",
|
|
||||||
"PL",
|
|
||||||
"PS",
|
|
||||||
"PT",
|
|
||||||
"PW",
|
|
||||||
"PY",
|
|
||||||
"QA",
|
|
||||||
"RO",
|
|
||||||
"RS",
|
|
||||||
"RW",
|
|
||||||
"SA",
|
|
||||||
"SB",
|
|
||||||
"SC",
|
|
||||||
"SE",
|
|
||||||
"SG",
|
|
||||||
"SI",
|
|
||||||
"SK",
|
|
||||||
"SL",
|
|
||||||
"SM",
|
|
||||||
"SN",
|
|
||||||
"SR",
|
|
||||||
"ST",
|
|
||||||
"SV",
|
|
||||||
"SZ",
|
|
||||||
"TD",
|
|
||||||
"TG",
|
|
||||||
"TH",
|
|
||||||
"TJ",
|
|
||||||
"TL",
|
|
||||||
"TN",
|
|
||||||
"TO",
|
|
||||||
"TR",
|
|
||||||
"TT",
|
|
||||||
"TV",
|
|
||||||
"TW",
|
|
||||||
"TZ",
|
|
||||||
"UA",
|
|
||||||
"UG",
|
|
||||||
"US",
|
|
||||||
"UY",
|
|
||||||
"UZ",
|
|
||||||
"VC",
|
|
||||||
"VE",
|
|
||||||
"VN",
|
|
||||||
"VU",
|
|
||||||
"WS",
|
|
||||||
"XK",
|
|
||||||
"ZA",
|
|
||||||
"ZM",
|
|
||||||
"ZW"
|
|
||||||
],
|
],
|
||||||
"external_urls": {
|
"external_urls": {
|
||||||
"spotify": "https://open.spotify.com/album/4qJXgmxckQ2YDBurSy42AS"
|
"spotify": "https://open.spotify.com/album/4qJXgmxckQ2YDBurSy42AS"
|
||||||
@@ -266,190 +83,7 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"available_markets": [
|
"available_markets": [
|
||||||
"AD",
|
"US"
|
||||||
"AE",
|
|
||||||
"AG",
|
|
||||||
"AL",
|
|
||||||
"AM",
|
|
||||||
"AO",
|
|
||||||
"AR",
|
|
||||||
"AT",
|
|
||||||
"AU",
|
|
||||||
"AZ",
|
|
||||||
"BA",
|
|
||||||
"BB",
|
|
||||||
"BD",
|
|
||||||
"BE",
|
|
||||||
"BF",
|
|
||||||
"BG",
|
|
||||||
"BH",
|
|
||||||
"BI",
|
|
||||||
"BJ",
|
|
||||||
"BN",
|
|
||||||
"BO",
|
|
||||||
"BR",
|
|
||||||
"BS",
|
|
||||||
"BT",
|
|
||||||
"BW",
|
|
||||||
"BY",
|
|
||||||
"BZ",
|
|
||||||
"CA",
|
|
||||||
"CD",
|
|
||||||
"CG",
|
|
||||||
"CH",
|
|
||||||
"CI",
|
|
||||||
"CL",
|
|
||||||
"CM",
|
|
||||||
"CO",
|
|
||||||
"CR",
|
|
||||||
"CV",
|
|
||||||
"CW",
|
|
||||||
"CY",
|
|
||||||
"CZ",
|
|
||||||
"DE",
|
|
||||||
"DJ",
|
|
||||||
"DK",
|
|
||||||
"DM",
|
|
||||||
"DO",
|
|
||||||
"DZ",
|
|
||||||
"EC",
|
|
||||||
"EE",
|
|
||||||
"EG",
|
|
||||||
"ES",
|
|
||||||
"ET",
|
|
||||||
"FI",
|
|
||||||
"FJ",
|
|
||||||
"FM",
|
|
||||||
"FR",
|
|
||||||
"GA",
|
|
||||||
"GB",
|
|
||||||
"GD",
|
|
||||||
"GE",
|
|
||||||
"GH",
|
|
||||||
"GM",
|
|
||||||
"GN",
|
|
||||||
"GQ",
|
|
||||||
"GR",
|
|
||||||
"GT",
|
|
||||||
"GW",
|
|
||||||
"GY",
|
|
||||||
"HK",
|
|
||||||
"HN",
|
|
||||||
"HR",
|
|
||||||
"HT",
|
|
||||||
"HU",
|
|
||||||
"ID",
|
|
||||||
"IE",
|
|
||||||
"IL",
|
|
||||||
"IN",
|
|
||||||
"IQ",
|
|
||||||
"IS",
|
|
||||||
"IT",
|
|
||||||
"JM",
|
|
||||||
"JO",
|
|
||||||
"JP",
|
|
||||||
"KE",
|
|
||||||
"KG",
|
|
||||||
"KH",
|
|
||||||
"KI",
|
|
||||||
"KM",
|
|
||||||
"KN",
|
|
||||||
"KR",
|
|
||||||
"KW",
|
|
||||||
"KZ",
|
|
||||||
"LA",
|
|
||||||
"LB",
|
|
||||||
"LC",
|
|
||||||
"LI",
|
|
||||||
"LK",
|
|
||||||
"LR",
|
|
||||||
"LS",
|
|
||||||
"LT",
|
|
||||||
"LU",
|
|
||||||
"LV",
|
|
||||||
"LY",
|
|
||||||
"MA",
|
|
||||||
"MC",
|
|
||||||
"MD",
|
|
||||||
"ME",
|
|
||||||
"MG",
|
|
||||||
"MH",
|
|
||||||
"MK",
|
|
||||||
"ML",
|
|
||||||
"MN",
|
|
||||||
"MO",
|
|
||||||
"MR",
|
|
||||||
"MT",
|
|
||||||
"MU",
|
|
||||||
"MV",
|
|
||||||
"MW",
|
|
||||||
"MX",
|
|
||||||
"MY",
|
|
||||||
"MZ",
|
|
||||||
"NA",
|
|
||||||
"NE",
|
|
||||||
"NG",
|
|
||||||
"NI",
|
|
||||||
"NL",
|
|
||||||
"NO",
|
|
||||||
"NP",
|
|
||||||
"NR",
|
|
||||||
"NZ",
|
|
||||||
"OM",
|
|
||||||
"PA",
|
|
||||||
"PE",
|
|
||||||
"PG",
|
|
||||||
"PH",
|
|
||||||
"PK",
|
|
||||||
"PL",
|
|
||||||
"PS",
|
|
||||||
"PT",
|
|
||||||
"PW",
|
|
||||||
"PY",
|
|
||||||
"QA",
|
|
||||||
"RO",
|
|
||||||
"RS",
|
|
||||||
"RW",
|
|
||||||
"SA",
|
|
||||||
"SB",
|
|
||||||
"SC",
|
|
||||||
"SE",
|
|
||||||
"SG",
|
|
||||||
"SI",
|
|
||||||
"SK",
|
|
||||||
"SL",
|
|
||||||
"SM",
|
|
||||||
"SN",
|
|
||||||
"SR",
|
|
||||||
"ST",
|
|
||||||
"SV",
|
|
||||||
"SZ",
|
|
||||||
"TD",
|
|
||||||
"TG",
|
|
||||||
"TH",
|
|
||||||
"TJ",
|
|
||||||
"TL",
|
|
||||||
"TN",
|
|
||||||
"TO",
|
|
||||||
"TR",
|
|
||||||
"TT",
|
|
||||||
"TV",
|
|
||||||
"TW",
|
|
||||||
"TZ",
|
|
||||||
"UA",
|
|
||||||
"UG",
|
|
||||||
"US",
|
|
||||||
"UY",
|
|
||||||
"UZ",
|
|
||||||
"VC",
|
|
||||||
"VE",
|
|
||||||
"VN",
|
|
||||||
"VU",
|
|
||||||
"WS",
|
|
||||||
"XK",
|
|
||||||
"ZA",
|
|
||||||
"ZM",
|
|
||||||
"ZW"
|
|
||||||
],
|
],
|
||||||
"disc_number": 1,
|
"disc_number": 1,
|
||||||
"duration_ms": 154792,
|
"duration_ms": 154792,
|
||||||
|
|||||||
5
todo.txt
5
todo.txt
@@ -1,2 +1,7 @@
|
|||||||
update volume slider from spotify every 10 seconds (probably going to need a new function for it)
|
update volume slider from spotify every 10 seconds (probably going to need a new function for it)
|
||||||
add clause for if nothing is playing is returend from spotify then present list of devices to chose where to start playback on
|
add clause for if nothing is playing is returend from spotify then present list of devices to chose where to start playback on
|
||||||
|
wrap all grid elements in a function, call that function from the start_playback_on_device function; right now it sometimes doesn't load the artist and title
|
||||||
|
selection resets after 1 second on devices list; need to remove root.after in update_song_label function and call that function from the start_playback_on_device function
|
||||||
|
and have that have a root.after to loop for refreshing devices... or find other way to make the root.after not deselect current selection in list.
|
||||||
|
|
||||||
|
last thing i was doing: BACKGROUND ALBUM ART IMAGE
|
||||||
Reference in New Issue
Block a user