feat: Implement host system volume control and update player service to use it
Some checks failed
Backend CI / lint (push) Failing after 10s
Backend CI / test (push) Has been cancelled

This commit is contained in:
JSC
2025-09-27 03:33:11 +02:00
parent 0806d541f2
commit 4b8496d025
6 changed files with 375 additions and 58 deletions

View File

@@ -26,12 +26,17 @@ class TestPlayerState:
def test_init_creates_default_state(self) -> None:
"""Test that player state initializes with default values."""
state = PlayerState()
# Mock volume service to return a specific volume
with patch("app.services.player.volume_service") as mock_volume_service:
mock_volume_service.get_volume.return_value = 80
assert state.status == PlayerStatus.STOPPED
assert state.mode == PlayerMode.CONTINUOUS
assert state.volume == 80
assert state.previous_volume == 80
state = PlayerState()
assert state.status == PlayerStatus.STOPPED
assert state.mode == PlayerMode.CONTINUOUS
assert state.volume == 80
assert state.previous_volume == 80
mock_volume_service.get_volume.assert_called_once()
assert state.current_sound_id is None
assert state.current_sound_index is None
assert state.current_sound_position == 0
@@ -181,7 +186,9 @@ class TestPlayerService:
mock_socket_manager,
):
"""Create a player service instance for testing."""
return PlayerService(mock_db_session_factory)
with patch("app.services.player.volume_service") as mock_volume_service:
mock_volume_service.get_volume.return_value = 80
return PlayerService(mock_db_session_factory)
def test_init_creates_player_service(
self,
@@ -217,7 +224,8 @@ class TestPlayerService:
assert player_service._loop is not None
assert player_service._position_thread is not None
assert player_service._position_thread.daemon is True
player_service._player.audio_set_volume.assert_called_once_with(80)
# VLC is now always set to 100% volume
player_service._player.audio_set_volume.assert_called_once_with(100)
@pytest.mark.asyncio
async def test_stop_cleans_up_service(self, player_service) -> None:
@@ -399,23 +407,32 @@ class TestPlayerService:
@pytest.mark.asyncio
async def test_set_volume(self, player_service) -> None:
"""Test setting volume."""
with patch.object(player_service, "_broadcast_state", new_callable=AsyncMock):
await player_service.set_volume(75)
with patch("app.services.player.volume_service") as mock_volume_service:
with patch.object(player_service, "_broadcast_state", new_callable=AsyncMock):
mock_volume_service.is_muted.return_value = False
assert player_service.state.volume == 75
player_service._player.audio_set_volume.assert_called_once_with(75)
await player_service.set_volume(75)
assert player_service.state.volume == 75
# VLC volume is always set to 100%, host volume is controlled separately
player_service._player.audio_set_volume.assert_called_once_with(100)
# Verify host volume was set
mock_volume_service.set_volume.assert_called_once_with(75)
@pytest.mark.asyncio
async def test_set_volume_clamping(self, player_service) -> None:
"""Test volume clamping to valid range."""
with patch.object(player_service, "_broadcast_state", new_callable=AsyncMock):
# Test upper bound
await player_service.set_volume(150)
assert player_service.state.volume == 100
with patch("app.services.player.volume_service") as mock_volume_service:
with patch.object(player_service, "_broadcast_state", new_callable=AsyncMock):
mock_volume_service.is_muted.return_value = False
# Test lower bound
await player_service.set_volume(-10)
assert player_service.state.volume == 0
# Test upper bound
await player_service.set_volume(150)
assert player_service.state.volume == 100
# Test lower bound
await player_service.set_volume(-10)
assert player_service.state.volume == 0
@pytest.mark.asyncio
async def test_set_mode(self, player_service) -> None: