import time import random from sqlalchemy.sql.expression import func from database import SessionLocal, Track, Setting def get_active_profile(db): setting = db.query(Setting).filter(Setting.key == "active_profile").first() return setting.value if setting else "harmonic" def set_active_profile(profile_name: str): db = SessionLocal() try: setting = db.query(Setting).filter(Setting.key == "active_profile").first() if not setting: setting = Setting(key="active_profile", value=profile_name) db.add(setting) else: setting.value = profile_name db.commit() finally: db.close() def get_next_track(): db = SessionLocal() try: profile = get_active_profile(db) track = None # Only select from analyzed tracks base_query = db.query(Track).filter(Track.analyzed == True) # Avoid playing tracks that were played in the last hour one_hour_ago = int(time.time()) - 3600 pool_query = base_query.filter(Track.last_played < one_hour_ago) # Artist Separation Logic artist_sep_enabled = db.query(Setting).filter(Setting.key == "artist_separation_enabled").first() if artist_sep_enabled and artist_sep_enabled.value == "true": artist_sep_count_setting = db.query(Setting).filter(Setting.key == "artist_separation_count").first() sep_count = int(artist_sep_count_setting.value) if artist_sep_count_setting else 5 recent_tracks = db.query(Track).filter(Track.last_played > 0).order_by(Track.last_played.desc()).limit(sep_count).all() recent_artists = [t.artist for t in recent_tracks if t.artist] if recent_artists: filtered_query = pool_query.filter(~Track.artist.in_(recent_artists)) if filtered_query.count() > 0: pool_query = filtered_query if pool_query.count() == 0: # Fallback if all tracks were played recently or no tracks analyzed pool_query = base_query if profile == "high_energy": # Pick from most energetic tracks tracks = pool_query.order_by(Track.energy.desc()).limit(50).all() if tracks: track = random.choice(tracks) elif profile == "chill": # Pick from least energetic tracks tracks = pool_query.order_by(Track.energy.asc()).limit(50).all() if tracks: track = random.choice(tracks) elif profile == "harmonic": # Get last played track to match key/bpm last_played = base_query.order_by(Track.last_played.desc()).first() if last_played and last_played.key and last_played.bpm: # Find matching key and similar BPM (+- 10) track = pool_query.filter(Track.key == last_played.key)\ .filter(Track.bpm.between(last_played.bpm - 10, last_played.bpm + 10))\ .order_by(func.random()).first() # Fallback to random if no track found for profile or profile is 'random' if not track: track = pool_query.order_by(func.random()).first() if track: # Update last played track.last_played = int(time.time()) track.play_count += 1 db.commit() return {"id": track.id, "lufs": track.lufs} return None finally: db.close() def get_current_track(): db = SessionLocal() try: # The currently playing track is approximated as the most recently queued track track = db.query(Track).order_by(Track.last_played.desc()).first() if track and track.last_played > 0: return { "id": track.id, "title": track.title, "artist": track.artist, "bpm": track.bpm, "energy": track.energy, "lufs": track.lufs } return None finally: db.close() # Define available profiles for the WebUI AVAILABLE_PROFILES = [ {"id": "harmonic", "name": "Harmonic Mix", "description": "Attempts to match the key and BPM of the previously played track."}, {"id": "high_energy", "name": "High Energy", "description": "Prioritizes tracks with high RMS energy."}, {"id": "chill", "name": "Chill", "description": "Prioritizes low-energy, ambient tracks."}, {"id": "random", "name": "Random", "description": "Plays tracks randomly."} ]