137 lines
3.7 KiB
Python
137 lines
3.7 KiB
Python
"""Track management endpoints."""
|
|
from fastapi import APIRouter, Depends, HTTPException, Query
|
|
from sqlalchemy.orm import Session
|
|
from typing import List, Optional
|
|
from uuid import UUID
|
|
|
|
from ...models.database import get_db
|
|
from ...models import crud
|
|
from ...models.schema import AudioTrack
|
|
|
|
router = APIRouter()
|
|
|
|
|
|
@router.get("", response_model=dict)
|
|
async def get_tracks(
|
|
skip: int = Query(0, ge=0),
|
|
limit: int = Query(100, ge=1, le=500),
|
|
genre: Optional[str] = None,
|
|
mood: Optional[str] = None,
|
|
bpm_min: Optional[float] = Query(None, ge=0, le=300),
|
|
bpm_max: Optional[float] = Query(None, ge=0, le=300),
|
|
energy_min: Optional[float] = Query(None, ge=0, le=1),
|
|
energy_max: Optional[float] = Query(None, ge=0, le=1),
|
|
has_vocals: Optional[bool] = None,
|
|
key: Optional[str] = None,
|
|
instrument: Optional[str] = None,
|
|
tempo_range: Optional[str] = Query(None, regex="^(slow|medium|fast)$"),
|
|
sort_by: str = Query("analyzed_at", regex="^(analyzed_at|tempo_bpm|duration_seconds|filename|energy)$"),
|
|
sort_desc: bool = True,
|
|
db: Session = Depends(get_db),
|
|
):
|
|
"""Get tracks with filters and pagination.
|
|
|
|
Args:
|
|
skip: Number of records to skip
|
|
limit: Maximum number of records
|
|
genre: Filter by genre
|
|
mood: Filter by mood
|
|
bpm_min: Minimum BPM
|
|
bpm_max: Maximum BPM
|
|
energy_min: Minimum energy
|
|
energy_max: Maximum energy
|
|
has_vocals: Filter by vocal presence
|
|
key: Filter by musical key
|
|
instrument: Filter by instrument
|
|
tempo_range: Filter by tempo range (slow: <100, medium: 100-140, fast: >140)
|
|
sort_by: Field to sort by
|
|
sort_desc: Sort descending
|
|
db: Database session
|
|
|
|
Returns:
|
|
Paginated list of tracks with total count
|
|
"""
|
|
# Convert tempo_range to bpm_min/bpm_max
|
|
if tempo_range:
|
|
if tempo_range == "slow":
|
|
bpm_max = 100.0 if bpm_max is None else min(bpm_max, 100.0)
|
|
elif tempo_range == "medium":
|
|
bpm_min = 100.0 if bpm_min is None else max(bpm_min, 100.0)
|
|
bpm_max = 140.0 if bpm_max is None else min(bpm_max, 140.0)
|
|
elif tempo_range == "fast":
|
|
bpm_min = 140.0 if bpm_min is None else max(bpm_min, 140.0)
|
|
|
|
tracks, total = crud.get_tracks(
|
|
db=db,
|
|
skip=skip,
|
|
limit=limit,
|
|
genre=genre,
|
|
mood=mood,
|
|
bpm_min=bpm_min,
|
|
bpm_max=bpm_max,
|
|
energy_min=energy_min,
|
|
energy_max=energy_max,
|
|
has_vocals=has_vocals,
|
|
key=key,
|
|
instrument=instrument,
|
|
sort_by=sort_by,
|
|
sort_desc=sort_desc,
|
|
)
|
|
|
|
return {
|
|
"tracks": [track.to_dict() for track in tracks],
|
|
"total": total,
|
|
"skip": skip,
|
|
"limit": limit,
|
|
}
|
|
|
|
|
|
@router.get("/{track_id}")
|
|
async def get_track(
|
|
track_id: UUID,
|
|
db: Session = Depends(get_db),
|
|
):
|
|
"""Get track by ID.
|
|
|
|
Args:
|
|
track_id: Track UUID
|
|
db: Database session
|
|
|
|
Returns:
|
|
Track details
|
|
|
|
Raises:
|
|
HTTPException: 404 if track not found
|
|
"""
|
|
track = crud.get_track_by_id(db, track_id)
|
|
|
|
if not track:
|
|
raise HTTPException(status_code=404, detail="Track not found")
|
|
|
|
return track.to_dict()
|
|
|
|
|
|
@router.delete("/{track_id}")
|
|
async def delete_track(
|
|
track_id: UUID,
|
|
db: Session = Depends(get_db),
|
|
):
|
|
"""Delete track by ID.
|
|
|
|
Args:
|
|
track_id: Track UUID
|
|
db: Database session
|
|
|
|
Returns:
|
|
Success message
|
|
|
|
Raises:
|
|
HTTPException: 404 if track not found
|
|
"""
|
|
success = crud.delete_track(db, track_id)
|
|
|
|
if not success:
|
|
raise HTTPException(status_code=404, detail="Track not found")
|
|
|
|
return {"message": "Track deleted successfully", "track_id": str(track_id)}
|