120 lines
3.8 KiB
Python
120 lines
3.8 KiB
Python
# Standard library imports
|
|
|
|
# PyQt imports
|
|
|
|
# Third party imports
|
|
from sqlalchemy import select, func
|
|
from sqlalchemy.orm import aliased
|
|
from classes import PlaylistRowObj
|
|
|
|
# App imports
|
|
from classes import TrackDTO
|
|
from models import db, Tracks, PlaylistRows, Playdates
|
|
|
|
|
|
def tracks_like_title(filter_str: str) -> list[TrackDTO]:
|
|
"""
|
|
Return tracks where title is like filter
|
|
"""
|
|
|
|
# TODO: add in playdates as per Tracks.search_titles
|
|
with db.Session() as session:
|
|
stmt = select(Tracks).where(Tracks.title.ilike(f"%{filter_str}%"))
|
|
results = (
|
|
session.execute(stmt).scalars().unique().all()
|
|
) # `scalars()` extracts ORM objects
|
|
return [
|
|
TrackDTO(**{k: v for k, v in vars(t).items() if not k.startswith("_")})
|
|
for t in results
|
|
]
|
|
|
|
|
|
def get_playlist_rows(playlist_id: int) -> list[PlaylistRowObj]:
|
|
# Alias PlaydatesTable for subquery
|
|
LatestPlaydate = aliased(Playdates)
|
|
|
|
# Subquery: latest playdate for each track
|
|
latest_playdate_subq = (
|
|
select(
|
|
LatestPlaydate.track_id,
|
|
func.max(LatestPlaydate.lastplayed).label("lastplayed")
|
|
)
|
|
.group_by(LatestPlaydate.track_id)
|
|
.subquery()
|
|
)
|
|
|
|
stmt = (
|
|
select(
|
|
PlaylistRows.id.label("playlistrow_id"),
|
|
PlaylistRows.row_number,
|
|
PlaylistRows.note,
|
|
PlaylistRows.played,
|
|
PlaylistRows.playlist_id,
|
|
Tracks.id.label("track_id"),
|
|
Tracks.artist,
|
|
Tracks.bitrate,
|
|
Tracks.duration,
|
|
Tracks.fade_at,
|
|
Tracks.intro,
|
|
Tracks.path,
|
|
Tracks.silence_at,
|
|
Tracks.start_gap,
|
|
Tracks.title,
|
|
latest_playdate_subq.c.lastplayed,
|
|
)
|
|
.outerjoin(Tracks, PlaylistRows.track_id == Tracks.id)
|
|
.outerjoin(latest_playdate_subq, Tracks.id == latest_playdate_subq.c.track_id)
|
|
.where(PlaylistRows.playlist_id == playlist_id)
|
|
.order_by(PlaylistRows.row_number)
|
|
)
|
|
|
|
with db.Session() as session:
|
|
results = session.execute(stmt).all()
|
|
|
|
dto_list = []
|
|
for row in results:
|
|
# Handle cases where track_id is None (no track associated)
|
|
if row.track_id is None:
|
|
dto = PlaylistRowObj(
|
|
artist="",
|
|
bitrate=0,
|
|
duration=0,
|
|
fade_at=0,
|
|
intro=None,
|
|
lastplayed=None,
|
|
note=row.note,
|
|
path="",
|
|
played=row.played,
|
|
playlist_id=row.playlist_id,
|
|
playlistrow_id=row.playlistrow_id,
|
|
row_number=row.row_number,
|
|
silence_at=0,
|
|
start_gap=0,
|
|
title="",
|
|
track_id=-1,
|
|
# Additional fields like row_fg, row_bg, etc., use default None values
|
|
)
|
|
else:
|
|
dto = PlaylistRowObj(
|
|
artist=row.artist,
|
|
bitrate=row.bitrate,
|
|
duration=row.duration,
|
|
fade_at=row.fade_at,
|
|
intro=row.intro,
|
|
lastplayed=row.lastplayed,
|
|
note=row.note,
|
|
path=row.path,
|
|
played=row.played,
|
|
playlist_id=row.playlist_id,
|
|
playlistrow_id=row.playlistrow_id,
|
|
row_number=row.row_number,
|
|
silence_at=row.silence_at,
|
|
start_gap=row.start_gap,
|
|
title=row.title,
|
|
track_id=row.track_id,
|
|
# Additional fields like row_fg, row_bg, etc., use default None values
|
|
)
|
|
dto_list.append(dto)
|
|
|
|
return dto_list
|