232 lines
7.6 KiB
Python
232 lines
7.6 KiB
Python
"""Music player API routes."""
|
|
|
|
from flask import Blueprint, jsonify, request
|
|
|
|
from app.services.decorators import require_auth
|
|
from app.services.error_handling_service import ErrorHandlingService
|
|
from app.services.music_player_service import music_player_service
|
|
|
|
bp = Blueprint("player", __name__)
|
|
|
|
|
|
@bp.route("/state", methods=["GET"])
|
|
@require_auth
|
|
def get_player_state():
|
|
"""Get current player state."""
|
|
try:
|
|
state = music_player_service.get_player_state()
|
|
return jsonify(state), 200
|
|
except Exception as e:
|
|
return ErrorHandlingService.handle_generic_error(e)
|
|
|
|
|
|
@bp.route("/play", methods=["POST"])
|
|
@require_auth
|
|
def play():
|
|
"""Start playback."""
|
|
try:
|
|
success = music_player_service.play()
|
|
if success:
|
|
return jsonify({"message": "Playback started"}), 200
|
|
return jsonify({"error": "Failed to start playback"}), 400
|
|
except Exception as e:
|
|
return ErrorHandlingService.handle_generic_error(e)
|
|
|
|
|
|
@bp.route("/pause", methods=["POST"])
|
|
@require_auth
|
|
def pause():
|
|
"""Pause playback."""
|
|
try:
|
|
success = music_player_service.pause()
|
|
if success:
|
|
return jsonify({"message": "Playback paused"}), 200
|
|
return jsonify({"error": "Failed to pause playback"}), 400
|
|
except Exception as e:
|
|
return ErrorHandlingService.handle_generic_error(e)
|
|
|
|
|
|
@bp.route("/stop", methods=["POST"])
|
|
@require_auth
|
|
def stop():
|
|
"""Stop playback."""
|
|
try:
|
|
success = music_player_service.stop()
|
|
if success:
|
|
return jsonify({"message": "Playback stopped"}), 200
|
|
return jsonify({"error": "Failed to stop playback"}), 400
|
|
except Exception as e:
|
|
return ErrorHandlingService.handle_generic_error(e)
|
|
|
|
|
|
@bp.route("/next", methods=["POST"])
|
|
@require_auth
|
|
def next_track():
|
|
"""Skip to next track."""
|
|
try:
|
|
success = music_player_service.next_track()
|
|
if success:
|
|
return jsonify({"message": "Skipped to next track"}), 200
|
|
return jsonify({"error": "Failed to skip to next track"}), 400
|
|
except Exception as e:
|
|
return ErrorHandlingService.handle_generic_error(e)
|
|
|
|
|
|
@bp.route("/previous", methods=["POST"])
|
|
@require_auth
|
|
def previous_track():
|
|
"""Skip to previous track."""
|
|
try:
|
|
success = music_player_service.previous_track()
|
|
if success:
|
|
return jsonify({"message": "Skipped to previous track"}), 200
|
|
return jsonify({"error": "Failed to skip to previous track"}), 400
|
|
except Exception as e:
|
|
return ErrorHandlingService.handle_generic_error(e)
|
|
|
|
|
|
@bp.route("/seek", methods=["POST"])
|
|
@require_auth
|
|
def seek():
|
|
"""Seek to position."""
|
|
try:
|
|
data = request.get_json()
|
|
if not data or "position" not in data:
|
|
return jsonify({"error": "Position required"}), 400
|
|
|
|
position = float(data["position"])
|
|
if not 0.0 <= position <= 1.0:
|
|
return jsonify({"error": "Position must be between 0.0 and 1.0"}), 400
|
|
|
|
success = music_player_service.seek(position)
|
|
if success:
|
|
return jsonify({"message": "Seek successful"}), 200
|
|
return jsonify({"error": "Failed to seek"}), 400
|
|
except (ValueError, TypeError):
|
|
return jsonify({"error": "Invalid position value"}), 400
|
|
except Exception as e:
|
|
return ErrorHandlingService.handle_generic_error(e)
|
|
|
|
|
|
@bp.route("/volume", methods=["POST"])
|
|
@require_auth
|
|
def set_volume():
|
|
"""Set volume."""
|
|
try:
|
|
data = request.get_json()
|
|
if not data or "volume" not in data:
|
|
return jsonify({"error": "Volume required"}), 400
|
|
|
|
volume = int(data["volume"])
|
|
if not 0 <= volume <= 100:
|
|
return jsonify({"error": "Volume must be between 0 and 100"}), 400
|
|
|
|
success = music_player_service.set_volume(volume)
|
|
if success:
|
|
return jsonify({"message": "Volume set successfully"}), 200
|
|
return jsonify({"error": "Failed to set volume"}), 400
|
|
except (ValueError, TypeError):
|
|
return jsonify({"error": "Invalid volume value"}), 400
|
|
except Exception as e:
|
|
return ErrorHandlingService.handle_generic_error(e)
|
|
|
|
|
|
@bp.route("/mode", methods=["POST"])
|
|
@require_auth
|
|
def set_play_mode():
|
|
"""Set play mode."""
|
|
try:
|
|
data = request.get_json()
|
|
if not data or "mode" not in data:
|
|
return jsonify({"error": "Mode required"}), 400
|
|
|
|
mode = data["mode"]
|
|
valid_modes = ["continuous", "loop-playlist", "loop-one", "random"]
|
|
if mode not in valid_modes:
|
|
return jsonify({"error": f"Mode must be one of: {', '.join(valid_modes)}"}), 400
|
|
|
|
success = music_player_service.set_play_mode(mode)
|
|
if success:
|
|
return jsonify({"message": "Play mode set successfully"}), 200
|
|
return jsonify({"error": "Failed to set play mode"}), 400
|
|
except Exception as e:
|
|
return ErrorHandlingService.handle_generic_error(e)
|
|
|
|
|
|
@bp.route("/playlist", methods=["POST"])
|
|
@require_auth
|
|
def load_playlist():
|
|
"""Load a playlist into the player."""
|
|
try:
|
|
data = request.get_json()
|
|
if not data or "playlist_id" not in data:
|
|
return jsonify({"error": "Playlist ID required"}), 400
|
|
|
|
playlist_id = int(data["playlist_id"])
|
|
success = music_player_service.load_playlist(playlist_id)
|
|
if success:
|
|
return jsonify({"message": "Playlist loaded successfully"}), 200
|
|
return jsonify({"error": "Failed to load playlist"}), 400
|
|
except (ValueError, TypeError):
|
|
return jsonify({"error": "Invalid playlist ID"}), 400
|
|
except Exception as e:
|
|
return ErrorHandlingService.handle_generic_error(e)
|
|
|
|
|
|
@bp.route("/play-track", methods=["POST"])
|
|
@require_auth
|
|
def play_track():
|
|
"""Play track at specific index."""
|
|
try:
|
|
data = request.get_json()
|
|
if not data or "index" not in data:
|
|
return jsonify({"error": "Track index required"}), 400
|
|
|
|
index = int(data["index"])
|
|
success = music_player_service.play_track_at_index(index)
|
|
if success:
|
|
return jsonify({"message": "Track playing"}), 200
|
|
return jsonify({"error": "Failed to play track"}), 400
|
|
except (ValueError, TypeError):
|
|
return jsonify({"error": "Invalid track index"}), 400
|
|
except Exception as e:
|
|
return ErrorHandlingService.handle_generic_error(e)
|
|
|
|
|
|
@bp.route("/start-instance", methods=["POST"])
|
|
@require_auth
|
|
def start_vlc_instance():
|
|
"""Start the VLC player instance."""
|
|
try:
|
|
success = music_player_service.start_vlc_instance()
|
|
if success:
|
|
return jsonify({"message": "VLC instance started successfully"}), 200
|
|
return jsonify({"error": "Failed to start VLC instance"}), 500
|
|
except Exception as e:
|
|
return ErrorHandlingService.handle_generic_error(e)
|
|
|
|
|
|
@bp.route("/stop-instance", methods=["POST"])
|
|
@require_auth
|
|
def stop_vlc_instance():
|
|
"""Stop the VLC player instance."""
|
|
try:
|
|
success = music_player_service.stop_vlc_instance()
|
|
if success:
|
|
return jsonify({"message": "VLC instance stopped successfully"}), 200
|
|
return jsonify({"error": "Failed to stop VLC instance"}), 500
|
|
except Exception as e:
|
|
return ErrorHandlingService.handle_generic_error(e)
|
|
|
|
|
|
|
|
@bp.route("/test-emit", methods=["POST"])
|
|
@require_auth
|
|
def test_emit():
|
|
"""Test SocketIO emission manually."""
|
|
try:
|
|
# Force emit player state
|
|
music_player_service._emit_player_state()
|
|
return jsonify({"message": "Test emission sent"}), 200
|
|
except Exception as e:
|
|
return ErrorHandlingService.handle_generic_error(e) |