[web] Instant mixes support albums and playlists too
All checks were successful
Deploy to mopidy1 / deploy (push) Successful in 10s
All checks were successful
Deploy to mopidy1 / deploy (push) Successful in 10s
This commit is contained in:
@ -236,10 +236,10 @@
|
|||||||
|
|
||||||
<div class="card" style="order: 1; grid-column: 1 / -1;">
|
<div class="card" style="order: 1; grid-column: 1 / -1;">
|
||||||
<h3>Instant Mix</h3>
|
<h3>Instant Mix</h3>
|
||||||
<p>Generate a mix or insert into queue based on a track URI (same genre + similar artists).</p>
|
<p>Generate a mix from a track, album, artist, or playlist URI (same genre + similar artists).</p>
|
||||||
<div class="field" style="flex-direction: column; gap: 0.5rem;">
|
<div class="field" style="flex-direction: column; gap: 0.5rem;">
|
||||||
<div style="display: flex; gap: 0.5rem;">
|
<div style="display: flex; gap: 0.5rem;">
|
||||||
<input id="instant-uri-input" type="text" placeholder="e.g. local:track:456" style="flex: 2;" />
|
<input id="instant-uri-input" type="text" placeholder="e.g. local:track:456 or local:album:123 or mopidy:playlist:..." style="flex: 2;" />
|
||||||
<input id="instant-limit-input" type="number" value="15" min="1" max="500" style="flex: 0 0 70px;" />
|
<input id="instant-limit-input" type="number" value="15" min="1" max="500" style="flex: 0 0 70px;" />
|
||||||
</div>
|
</div>
|
||||||
<div style="display: flex; gap: 0.5rem;">
|
<div style="display: flex; gap: 0.5rem;">
|
||||||
|
|||||||
@ -166,30 +166,24 @@ class InstantMixHandler(tornado.web.RequestHandler):
|
|||||||
|
|
||||||
def post(self) -> None:
|
def post(self) -> None:
|
||||||
data = json.loads(self.request.body)
|
data = json.loads(self.request.body)
|
||||||
track_uri = data.get("uri", "")
|
uri = data.get("uri", "")
|
||||||
limit = data.get("limit", 50)
|
limit = data.get("limit", 50)
|
||||||
if not track_uri:
|
if not uri:
|
||||||
self.set_status(400)
|
self.set_status(400)
|
||||||
self.write({"error": "Missing 'uri' in request body"})
|
self.write({"error": "Missing 'uri' in request body"})
|
||||||
return
|
return
|
||||||
tracks = build_instant_mix(self.core, track_uri, limit, uris=self.uris)
|
|
||||||
|
seed = self._resolve_seed_track(uri)
|
||||||
|
if not seed or not seed.uri:
|
||||||
|
self.write({"playlist": None, "tracks": 0})
|
||||||
|
return
|
||||||
|
|
||||||
|
tracks = build_instant_mix(self.core, seed.uri, limit, uris=self.uris)
|
||||||
if not tracks:
|
if not tracks:
|
||||||
self.write({"playlist": None, "tracks": 0})
|
self.write({"playlist": None, "tracks": 0})
|
||||||
return
|
return
|
||||||
|
|
||||||
try:
|
seed_name = seed.name or "Instant Mix"
|
||||||
lookup_result = self.core.library.lookup([track_uri]).get()
|
|
||||||
except Exception:
|
|
||||||
logger.exception("Track lookup failed for %s", track_uri)
|
|
||||||
self.write({"playlist": None, "tracks": 0})
|
|
||||||
return
|
|
||||||
seed_name = "Instant Mix"
|
|
||||||
for uri_tracks in lookup_result.values():
|
|
||||||
for t in uri_tracks:
|
|
||||||
if t.name:
|
|
||||||
seed_name = t.name
|
|
||||||
break
|
|
||||||
|
|
||||||
playlist = save_smart_playlist(
|
playlist = save_smart_playlist(
|
||||||
self.core, self.prefix, f"Instant Mix: {seed_name}", tracks,
|
self.core, self.prefix, f"Instant Mix: {seed_name}", tracks,
|
||||||
playlist_dir=self.playlist_dir,
|
playlist_dir=self.playlist_dir,
|
||||||
@ -204,6 +198,25 @@ class InstantMixHandler(tornado.web.RequestHandler):
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def _resolve_seed_track(self, uri: str):
|
||||||
|
try:
|
||||||
|
lookup = self.core.library.lookup([uri]).get()
|
||||||
|
except Exception:
|
||||||
|
lookup = None
|
||||||
|
if lookup:
|
||||||
|
tracks = [t for ts in lookup.values() for t in (ts or []) if t.uri]
|
||||||
|
if tracks:
|
||||||
|
return random.choice(tracks)
|
||||||
|
try:
|
||||||
|
pl = self.core.playlists.lookup(uri).get()
|
||||||
|
except Exception:
|
||||||
|
pl = None
|
||||||
|
if pl and pl.tracks:
|
||||||
|
valid = [t for t in pl.tracks if t.uri]
|
||||||
|
if valid:
|
||||||
|
return random.choice(valid)
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
class PlaylistMixHandler(tornado.web.RequestHandler):
|
class PlaylistMixHandler(tornado.web.RequestHandler):
|
||||||
def initialize(
|
def initialize(
|
||||||
|
|||||||
Reference in New Issue
Block a user