"""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)