feat: Add Liquidsoap DJ controls via telnet integration

- Implement 5 DJ control API endpoints (skip, reload, queue, metadata, queue-status)
- Update Liquidsoap config to support dynamic track queuing with request.queue
- Add comprehensive DJ control tests to test-server.sh with dynamic track ID fetching
- Add test result logging with timestamped log files
- Update .gitignore to exclude test result logs
- Change liquidsoap-queue-track to use queue.push command
This commit is contained in:
glenneth 2025-10-12 06:34:37 +03:00 committed by Glenn Thompson
parent 78fa57012b
commit f101ff5757
4 changed files with 110 additions and 6 deletions

1
.gitignore vendored
View File

@ -44,5 +44,6 @@ docker-compose.yml.backup.*
*.log
logs/
performance-logs/
test-results-*.log
# Temporary files

View File

@ -334,7 +334,7 @@
(defun liquidsoap-queue-track (file-path)
"Queue a specific track in Liquidsoap"
(liquidsoap-telnet-command (format nil "request.push ~A" file-path)))
(liquidsoap-telnet-command (format nil "queue.push ~A" file-path)))
(defun parse-liquidsoap-metadata (metadata-string)
"Parse Liquidsoap metadata string into artist/title/album"

View File

@ -19,10 +19,13 @@ settings.server.telnet.set(true)
settings.server.telnet.port.set(1234)
settings.server.telnet.bind_addr.set("0.0.0.0")
# Create request queue for dynamic track queuing (DJ controls)
queue = request.queue(id="queue")
# Create playlist source from generated M3U file
# This file is managed by Asteroid's stream control system
# Falls back to directory scan if playlist file doesn't exist
radio = playlist(
playlist_managed = playlist(
id="managed_playlist",
mode="normal", # Play in order (not randomized)
reload=30, # Check for playlist updates every 30 seconds
reload_mode="seconds", # Reload every N seconds (prevents running out of tracks)
@ -30,14 +33,19 @@ radio = playlist(
)
# Fallback to directory scan if playlist file is empty/missing
radio_fallback = playlist.safe(
playlist_fallback = playlist.safe(
id="music",
mode="randomize",
reload=3600,
"/app/music/"
)
# Use main playlist, fall back to directory scan
radio = fallback(track_sensitive=false, [radio, radio_fallback])
# Combine sources: queue (highest priority), managed playlist, then fallback to directory scan
radio = fallback(track_sensitive=true, [queue, playlist_managed, playlist_fallback])
# Add some audio processing
radio = amplify(1.0, radio)
radio = normalize(radio)
# Simple crossfade for smooth transitions
radio = crossfade(

View File

@ -15,6 +15,7 @@ NC='\033[0m' # No Color
BASE_URL="${ASTEROID_URL:-http://localhost:8080}"
API_BASE="${BASE_URL}/api/asteroid"
VERBOSE="${VERBOSE:-0}"
LOG_FILE="test-results-$(date +%Y%m%d-%H%M%S).log"
# Test counters
TESTS_RUN=0
@ -22,28 +23,39 @@ TESTS_PASSED=0
TESTS_FAILED=0
# Helper functions
log_to_file() {
# Strip ANSI color codes for log file
echo "$1" | sed 's/\x1b\[[0-9;]*m//g' >> "$LOG_FILE"
}
print_header() {
local msg="\n========================================\n$1\n========================================\n"
echo -e "\n${BLUE}========================================${NC}"
echo -e "${BLUE}$1${NC}"
echo -e "${BLUE}========================================${NC}\n"
log_to_file "$msg"
}
print_test() {
echo -e "${YELLOW}TEST:${NC} $1"
log_to_file "TEST: $1"
}
print_pass() {
echo -e "${GREEN}✓ PASS:${NC} $1"
log_to_file "✓ PASS: $1"
TESTS_PASSED=$((TESTS_PASSED + 1))
}
print_fail() {
echo -e "${RED}✗ FAIL:${NC} $1"
log_to_file "✗ FAIL: $1"
TESTS_FAILED=$((TESTS_FAILED + 1))
}
print_info() {
echo -e "${BLUE}INFO:${NC} $1"
log_to_file "INFO: $1"
}
# Test function wrapper
@ -212,6 +224,66 @@ test_playlist_endpoints() {
print_info "Note: Playlist creation requires authentication"
}
# Test DJ Control Endpoints (Liquidsoap telnet integration)
test_dj_control_endpoints() {
print_header "Testing DJ Control Endpoints"
print_info "Note: DJ control endpoints require admin authentication"
# Test metadata endpoint (available to authenticated users)
test_api_endpoint "/dj/metadata" \
"DJ metadata endpoint" \
"metadata"
# Test queue status endpoint
test_api_endpoint "/dj/queue-status" \
"DJ queue status endpoint" \
"queue"
# Test skip track endpoint (requires admin)
run_test "DJ skip track endpoint"
local skip_response=$(curl -s -X POST "${API_BASE}/dj/skip")
if echo "$skip_response" | grep -q "status"; then
print_pass "DJ skip track endpoint responds"
else
print_fail "DJ skip track endpoint not responding"
fi
# Test reload playlist endpoint (requires admin)
run_test "DJ reload playlist endpoint"
local reload_response=$(curl -s -X POST "${API_BASE}/dj/reload-playlist")
if echo "$reload_response" | grep -q "status"; then
print_pass "DJ reload playlist endpoint responds"
else
print_fail "DJ reload playlist endpoint not responding"
fi
# Test queue track endpoint with dynamic track ID
run_test "DJ queue track endpoint"
# Fetch a random track ID from the database
local track_response=$(curl -s "${API_BASE}/tracks?page=1&per-page=1")
# Extract track ID using grep (works without jq)
local track_id=$(echo "$track_response" | grep -o '"id":[0-9]*' | head -1 | grep -o '[0-9]*')
if [ -n "$track_id" ]; then
print_info "Using track ID: $track_id for queue test"
local queue_response=$(curl -s -X POST "${API_BASE}/dj/queue?track-id=${track_id}")
if echo "$queue_response" | grep -q "queued successfully\|Track not found"; then
print_pass "DJ queue track endpoint responds (track ID: $track_id)"
else
print_fail "DJ queue track endpoint not responding properly"
if [ $VERBOSE -eq 1 ]; then
echo "Response: $queue_response"
fi
fi
else
print_info "No tracks available in database, skipping queue test"
fi
}
# Test Page Endpoints (HTML pages)
test_page_endpoints() {
print_header "Testing HTML Page Endpoints"
@ -278,21 +350,42 @@ test_api_format() {
print_summary() {
print_header "Test Summary"
local summary="Tests Run: $TESTS_RUN\nTests Passed: $TESTS_PASSED\nTests Failed: $TESTS_FAILED"
echo "Tests Run: $TESTS_RUN"
echo -e "Tests Passed: ${GREEN}$TESTS_PASSED${NC}"
echo -e "Tests Failed: ${RED}$TESTS_FAILED${NC}"
log_to_file "$summary"
if [ $TESTS_FAILED -eq 0 ]; then
echo -e "\n${GREEN}✓ All tests passed!${NC}\n"
log_to_file "\n✓ All tests passed!\n"
echo -e "${BLUE}Log file saved to: ${LOG_FILE}${NC}\n"
exit 0
else
echo -e "\n${RED}✗ Some tests failed${NC}\n"
log_to_file "\n✗ Some tests failed\n"
echo -e "${BLUE}Log file saved to: ${LOG_FILE}${NC}\n"
exit 1
fi
}
# Main test execution
main() {
# Initialize log file with header
cat > "$LOG_FILE" << EOF
╔═══════════════════════════════════════════════════════════════╗
║ Asteroid Radio Server Test Suite ║
║ Test Results Log ║
╚═══════════════════════════════════════════════════════════════╝
Test Run Date: $(date '+%Y-%m-%d %H:%M:%S')
Server URL: ${BASE_URL}
API Base: ${API_BASE}
Verbose Mode: ${VERBOSE}
EOF
echo -e "${BLUE}"
echo "╔═══════════════════════════════════════╗"
echo "║ Asteroid Radio Server Test Suite ║"
@ -301,6 +394,7 @@ main() {
print_info "Testing server at: ${BASE_URL}"
print_info "Verbose mode: ${VERBOSE}"
print_info "Log file: ${LOG_FILE}"
echo ""
# Run all test suites
@ -310,6 +404,7 @@ main() {
test_track_endpoints
test_player_endpoints
test_playlist_endpoints
test_dj_control_endpoints
test_admin_endpoints
test_page_endpoints
test_static_files