|
import os |
|
import gradio as gr |
|
import spotipy |
|
import uvicorn |
|
from urllib import request |
|
from fastapi import FastAPI |
|
from starlette.middleware.sessions import SessionMiddleware |
|
from starlette.responses import HTMLResponse, RedirectResponse |
|
from starlette.requests import Request as SRequest |
|
from fastapi.responses import HTMLResponse |
|
from fastapi.responses import RedirectResponse |
|
|
|
from src.playlist_builder import * |
|
from src.evolutionary_alrogithm import Population, simple_mutation, simple_crossover, THUMBS_UP, THUMBS_DOWN, ADD_TO_PLAYLIST |
|
from src.spotipy_utils import get_auth_manager |
|
|
|
NUM_SONGS = 9 |
|
DEFAULT_MUTATION_SIZE = 0.25 |
|
SONG_CHOICES = [THUMBS_UP, THUMBS_DOWN, ADD_TO_PLAYLIST] |
|
|
|
OPTIONS_TITLE = """# 🧬 Options""" |
|
APP_HEADER = """# Evolutionary Playlist Builder""" |
|
EXPLORATION_HEADER = """## Rate of Exploration""" |
|
PLAYLIST_HEADER = """## Current Playlist""" |
|
|
|
|
|
FAST_API_KEY = os.environ["FAST_API_KEY"] |
|
app = FastAPI() |
|
app.add_middleware(SessionMiddleware, secret_key=FAST_API_KEY) |
|
|
|
@app.get('/', response_class=HTMLResponse) |
|
async def homepage(request: SRequest): |
|
auth_manager = get_auth_manager() |
|
|
|
auth_url = auth_manager.get_authorize_url() |
|
return "<a href='" + auth_url + "'>Login to Spotify</a>" |
|
|
|
|
|
def initialize_playlist_builder(): |
|
demo = gr.Blocks() |
|
with demo: |
|
gr.Markdown(APP_HEADER) |
|
|
|
with gr.Row(): |
|
|
|
do_crossover = gr.State(False) |
|
do_mutation = gr.State(False) |
|
|
|
population = Population(NUM_SONGS, DEFAULT_MUTATION_SIZE, mutation_function=simple_mutation, crossover_function=simple_crossover) |
|
population_state = gr.State(population) |
|
|
|
|
|
initial_traversal_history = population.generate_traversal_viz() |
|
|
|
|
|
with gr.Column(): |
|
gr.Markdown( |
|
f""" |
|
This app is still in development mode so if you want the ability to add a playlist to your library, email carterward4@gmail.com with your name, spotify email, and the subject as PLAYLIST ACCESS REQUEST. |
|
""") |
|
|
|
options = gr.Box(visible=False) |
|
with options: |
|
gr.Markdown(OPTIONS_TITLE) |
|
|
|
crossover_radio = gr.Radio(choices=CROSSOVER_OPTIONS, value=None, label="Crossover?") |
|
|
|
mutation_radio = gr.Radio(choices=MUTATION_OPTIONS, value=None, label="Mutate?") |
|
|
|
gr.Markdown(EXPLORATION_HEADER, visible=False) |
|
|
|
mutation_size_slider = gr.Slider(minimum=0.0, maximum=1.0, value=DEFAULT_MUTATION_SIZE |
|
, interactive=True, show_label=False, visible=False) |
|
|
|
history_block = gr.Plot(initial_traversal_history, label="Search History") |
|
|
|
gr.Markdown(PLAYLIST_HEADER) |
|
|
|
playlist_display = gr.TextArea(value=population.get_playlist_block_value(), max_lines=10000, show_label=False) |
|
|
|
playlist_name = gr.Textbox(interactive=True, label="Enter the name for this playlist!") |
|
|
|
add_playlist = gr.Button(value="Add Playlist to Spotify Library") |
|
|
|
playlist_added_message = gr.Markdown(ADDED_TO_PLAYLIST, visible=False) |
|
|
|
|
|
index_blocks = [] |
|
name_blocks = [] |
|
image_blocks = [] |
|
dropdown_blocks = [] |
|
preview_blocks = [] |
|
|
|
with gr.Column(): |
|
|
|
seed_option = gr.Radio(SEED_OPTIONS, value=SEED_OPTIONS[-1], label="Seed generation?", show_label=True) |
|
seed_options_container = gr.Box(visible=False) |
|
with seed_options_container: |
|
seed_track_search = gr.Textbox(value = None, interactive=True, label="Enter the track name!", show_label=True) |
|
seed_artist_search = gr.Textbox(value = None, interactive=True, label="Enter the artist name!", show_label=True) |
|
search_button = gr.Button(value = "Search for seed!") |
|
search_results = gr.Dropdown(label="Search result options", interactive=True) |
|
|
|
|
|
pop_container = gr.Box(visible=False) |
|
with pop_container: |
|
for row in range(0, population.size, 3): |
|
with gr.Row(): |
|
for col in range(3): |
|
with gr.Box(): |
|
track_index = row + col |
|
if track_index < len(population.pop): |
|
current_song = population.pop[track_index] |
|
song_preview = current_song.get_preview_url() |
|
track_image = gr.Image(value=current_song.get_image_url(), show_label=False, visible=True).style(height=175, width=175) |
|
track_title = gr.Markdown(value=f"{current_song.name} by {current_song.artist}", show_label=False) |
|
track_dropdown = gr.Dropdown(SONG_CHOICES, label = track_index, show_label=False) |
|
else: |
|
track_image = None |
|
song_preview = None |
|
track_image = gr.Image(value=None, show_label=False, visible=True).style(height=175, width=175) |
|
track_title = gr.Markdown(value=f"", show_label=False, visible=True) |
|
track_dropdown = gr.Dropdown(SONG_CHOICES, label = track_index, show_label=False, visible=True) |
|
|
|
|
|
index_blocks.append(gr.TextArea(value=track_index, visible=False)) |
|
|
|
image_blocks.append(track_image) |
|
|
|
name_blocks.append(track_title) |
|
|
|
dropdown_blocks.append(track_dropdown) |
|
|
|
if song_preview: |
|
preview_blocks.append(gr.Audio(value=song_preview, show_label=False)) |
|
else: |
|
preview_blocks.append(gr.Audio(value=song_preview, show_label=False, visible=False)) |
|
with gr.Box(): |
|
next_generation = gr.Button(value="Next Generation").style(full_width=True) |
|
|
|
|
|
|
|
crossover_radio.change( |
|
fn=set_crossover_option, |
|
inputs=[crossover_radio], |
|
outputs=[do_crossover] |
|
) |
|
|
|
mutation_radio.change( |
|
fn=set_mutation_option, |
|
inputs=[population_state, do_crossover, mutation_radio], |
|
outputs=[mutation_size_slider, crossover_radio, do_crossover, do_mutation, population_state] |
|
) |
|
|
|
mutation_size_slider.change( |
|
fn=update_mutation_size, |
|
inputs=[population_state, mutation_size_slider], |
|
outputs=[population_state] |
|
) |
|
|
|
seed_option.change( |
|
fn=change_seed_option, |
|
inputs=[seed_option, population_state], |
|
outputs=[seed_options_container, options, seed_track_search, seed_artist_search, search_results, population_state] |
|
) |
|
|
|
search_button.click( |
|
fn=search_for_seed, |
|
inputs=[population_state, seed_artist_search, seed_track_search], |
|
outputs=[population_state, search_results] |
|
) |
|
|
|
search_results.change( |
|
fn=set_pop_seed, |
|
inputs=[population_state, search_results], |
|
outputs=[population_state] |
|
) |
|
|
|
|
|
for index_block, dropdown_block in zip(index_blocks, dropdown_blocks): |
|
dropdown_block.change( |
|
fn=set_track_state, |
|
inputs=[population_state, index_block, dropdown_block], |
|
outputs=[population_state] |
|
) |
|
|
|
|
|
next_generation.click( |
|
fn=get_next_generation, |
|
inputs=[population_state, do_mutation, do_crossover], |
|
outputs=[pop_container, options, population_state, playlist_display, *image_blocks, *name_blocks, *dropdown_blocks, *preview_blocks, history_block] |
|
) |
|
|
|
add_playlist.click( |
|
fn=add_playlist_to_spotify, |
|
inputs=[population_state, playlist_name], |
|
outputs=[playlist_added_message] |
|
) |
|
|
|
|
|
|
|
|
|
|
|
|
|
return demo |
|
|
|
|
|
gradio_app = initialize_playlist_builder() |
|
playlist_app = gr.mount_gradio_app(app, gradio_app, "/gradio", gradio_api_url="http://localhost:7860/") |
|
uvicorn.run(app, host="0.0.0.0", port=7860) |
|
|