Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New card actions: play, pause, prev, next, toggle, repeat, shuffle #2179

Merged
merged 19 commits into from
Jan 4, 2024
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 14 additions & 1 deletion documentation/developers/docker.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,20 @@ They can be run individually or in combination. To do that, we use
### Mac

1. [Install Docker & Compose (Mac)](https://docs.docker.com/docker-for-mac/install/)
2. [Install pulseaudio](https://gist.github.com/seongyongkim/b7d630a03e74c7ab1c6b53473b592712) (Other references: [[1]](https://devops.datenkollektiv.de/running-a-docker-soundbox-on-mac.html), [[2]](https://stackoverflow.com/a/50939994/1062438))
2. Install pulseaudio
1. Use Homebrew to install
```
$ brew install pulseaudio
```
2. Enable pulseaudio network capabilities. In an editor, open `/opt/homebrew/Cellar/pulseaudio/16.1/etc/pulse/default.pa` (you might need to adapt this path to your own system settings). Uncomment the following line.
```
load-module module-native-protocol-tcp
```
3. Restart the pulseaudio service
```
$ brew services restart pulseaudio
```
4. If you have trouble with your audio, try these resources to troubleshoot: [[1]](https://gist.github.com/seongyongkim/b7d630a03e74c7ab1c6b53473b592712), [[2]](https://devops.datenkollektiv.de/running-a-docker-soundbox-on-mac.html), [[3]](https://stackoverflow.com/a/50939994/1062438)

> [!NOTE]
> In order for Pulseaudio to work properly with Docker on your Mac, you need to start Pulseaudio in a specific way. Otherwise MPD will throw an exception. See [Pulseaudio issues on Mac](#pulseaudio-issue-on-mac) for more info.
Expand Down
49 changes: 48 additions & 1 deletion src/jukebox/components/playermpd/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -340,6 +340,20 @@ def shuffle(self, random):
# As long as we don't work with waiting lists (aka playlist), this implementation is ok!
self.mpd_retry_with_mutex(self.mpd_client.random, 1 if random else 0)

@plugs.tag
def set_shuffle(self, option='toggle'):
pabera marked this conversation as resolved.
Show resolved Hide resolved
if option == 'toggle':
if self.mpd_status['random'] == '0':
self.shuffle(1)
else:
self.shuffle(0)
elif option == 'enable':
self.shuffle(1)
elif option == 'disable':
self.shuffle(0)
else:
logger.error(f"'{option}' does not exist for set_shuffle")

@plugs.tag
def rewind(self):
"""
Expand All @@ -363,7 +377,6 @@ def replay(self):
@plugs.tag
def toggle(self):
pabera marked this conversation as resolved.
Show resolved Hide resolved
"""Toggle pause state, i.e. do a pause / resume depending on current state"""
logger.debug("Toggle")
with self.mpd_lock:
self.mpd_client.pause()

Expand Down Expand Up @@ -394,6 +407,40 @@ def repeatmode(self, mode):
self.mpd_client.repeat(repeat)
self.mpd_client.single(single)

@plugs.tag
def set_repeat(self, option='toggle'):
pabera marked this conversation as resolved.
Show resolved Hide resolved
if option == 'toggle':
if self.mpd_status['repeat'] == '0':
self.repeatmode('repeat')
elif self.mpd_status['repeat'] == '1' and self.mpd_status['single'] == '0':
self.repeatmode('single')
else:
self.repeatmode(None)
elif option == 'toggle_repeat':
self.toggle_repeat()
elif option == 'toggle_repeat_single':
self.toggle_repeat_single()
elif option == 'enable_repeat':
self.repeatmode('repeat')
elif option == 'enable_repeat_single':
self.repeatmode('single')
elif option == 'disable':
self.repeatmode(None)
else:
logger.error(f"'{option}' does not exist for set_repeat")

def toggle_repeat(self):
pabera marked this conversation as resolved.
Show resolved Hide resolved
if self.mpd_status['repeat'] == '0':
self.repeatmode('repeat')
else:
self.repeatmode(None)

def toggle_repeat_single(self):
pabera marked this conversation as resolved.
Show resolved Hide resolved
if self.mpd_status['single'] == '0':
self.repeatmode('single')
else:
self.repeatmode(None)

@plugs.tag
def get_current_song(self, param):
return self.mpd_status
Expand Down
18 changes: 18 additions & 0 deletions src/jukebox/components/rpc_command_alias.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,12 @@
'package': 'player',
'plugin': 'ctrl',
'method': 'play_folder'},
'play': {
'package': 'player',
'plugin': 'ctrl',
'method': 'play',
'note': 'Play the currently selected song',
'ignore_card_removal_action': True},
'pause': {
'package': 'player',
'plugin': 'ctrl',
Expand All @@ -57,6 +63,18 @@
'plugin': 'ctrl',
'method': 'toggle',
'ignore_card_removal_action': True},
'set_shuffle': {
'package': 'player',
'plugin': 'ctrl',
'method': 'set_shuffle',
'note': 'Shuffle',
'ignore_card_removal_action': True},
'set_repeat': {
'package': 'player',
'plugin': 'ctrl',
'method': 'set_repeat',
'note': 'Repeat',
'ignore_card_removal_action': True},

# VOLUME
'set_volume': {
Expand Down
42 changes: 33 additions & 9 deletions src/webapp/public/locales/de/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,14 @@
"timer_fade_volume": "Fade volume",
"toggle_output": "Audio-Ausgang umschalten",
"sync_rfidcards_all": "Alle Audiodateien und Karteneinträge synchronisieren",
"sync_rfidcards_change_on_rfid_scan": "Aktivierung ändern für 'on RFID scan' "
"sync_rfidcards_change_on_rfid_scan": "Aktivierung ändern für 'on RFID scan'",
"next_song": "Nächster Song",
"pause": "Pause",
"play": "Abspielen",
"prev_song": "Vorheriger Song",
"set_shuffle": "Zufallswiedergabe",
"set_repeat": "Wiedergabe wiederholen",
"toggle": "Abspielen/Pause umschalten"
}
},
"controls-selector": {
Expand Down Expand Up @@ -56,8 +63,25 @@
"no-music-selected": "Es ist keine Musik ausgewählt.",
"loading-song-error": "Während des Ladens des Songs ist ein Fehler aufgetreten."
},
"volume": {
"title": "Lautstärke Stufen"
"audio": {
"repeat": {
"description": "Wähle den zu setzenden Status.",
"label-toggle": "Umschalten - Schaltet durch 1) Wiedergabeliste Wiederholen, 2) Song Wiederholen, 3) Wiederholen Deaktiveren",
"label-toggle-repeat": "Wiedergabeliste Wiederholen umschalten",
"label-toggle-repeat-single": "Song Wiederholen umschalten",
"label-enable-repeat": "Wiedergabeliste Wiederholen aktivieren",
"label-enable-repeat-single": "Song Wiederholen aktivieren",
"label-disable": "Wiederholen deaktivieren"
},
"shuffle": {
"description": "Wähle den zu setzenden Status.",
"label-toggle": "Umschalten",
"label-enable": "Aktivieren",
"label-disable": "Deaktivieren"
},
"volume": {
"title": "Volume steps"
pabera marked this conversation as resolved.
Show resolved Hide resolved
}
},
"timers": {
"description": "Wähle die Anzahl der Minuten nachdem die Aktion ausgeführt werden soll."
Expand Down Expand Up @@ -138,16 +162,16 @@
"player": {
"controls": {
"shuffle": {
"activate": "Shuffle aktivieren",
"deactivate": "Shuffle deaktivieren"
"enable": "Zufallswiedergabe aktivieren",
"disable": "Zufallswiedergabe deaktivieren"
},
"skip": "Zurück",
"prev_song": "Zurück",
"play": "Abspielen",
"pause": "Pause",
"next": "Weiter",
"next_song": "Weiter",
"repeat": {
"activate": "Wiederholen aktivieren",
"activate-single": "1 Wiederholen aktivieren",
"activate": "Wiedergabeliste Wiederholen aktivieren",
"activate-single": "Song Wiederholen aktivieren",
"deactivate": "Wiederholen deaktivieren"
}
},
Expand Down
39 changes: 32 additions & 7 deletions src/webapp/public/locales/en/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,14 @@
"timer_fade_volume": "Fade volume",
"toggle_output": "Toggle audio output",
"sync_rfidcards_all": "Sync all audiofiles and card entries",
"sync_rfidcards_change_on_rfid_scan": "Change activation of 'on RFID scan'"
"sync_rfidcards_change_on_rfid_scan": "Change activation of 'on RFID scan'",
"next_song": "Next song",
"pause": "Pause",
"play": "Play",
"prev_song": "Previous song",
"set_shuffle": "Shuffle",
"set_repeat": "Repeat",
"toggle": "Toggle Play/Pause"
}
},
"controls-selector": {
Expand Down Expand Up @@ -56,8 +63,25 @@
"no-music-selected": "No music selected",
"loading-song-error": "An error occurred while loading song."
},
"volume": {
"title": "Volume steps"
"audio": {
"repeat": {
"description": "Choose the state to set.",
"label-toggle": "Toggle - Loops through 1) Repeat playlist, 2) Repeat song, 3) Disable repeat",
"label-toggle-repeat": "Toggle Repeat Playlist",
"label-toggle-repeat-single": "Toggle Repeat Song",
"label-enable-repeat": "Enable Repeat Playlist",
"label-enable-repeat-single": "Enable Repeat Song",
"label-disable": "Disable"
},
"shuffle": {
"description": "Choose the state to set.",
"label-toggle": "Toggle",
"label-enable": "Enable",
"label-disable": "Disable"
},
"volume": {
"title": "Volume steps"
}
},
"timers": {
"description": "Choose the amount of minutes you want the action to be performed."
Expand Down Expand Up @@ -138,13 +162,13 @@
"player": {
"controls": {
"shuffle": {
"activate": "Activate shuffle",
"deactivate": "Deactivate shuffle"
"enable": "Enable shuffle",
"disable": "Disable shuffle"
},
"skip": "Skip previous track",
"prev_song": "Skip to previous track",
"play": "Play",
"pause": "Pause",
"next": "Skip next track",
"next_song": "Skip to next track",
"repeat": {
"activate": "Activate repeat",
pabera marked this conversation as resolved.
Show resolved Hide resolved
"activate-single": "Activate single repeat",
Expand Down Expand Up @@ -207,6 +231,7 @@
},
"secondswipe": {
"title": "Second Swipe",
"description": "Second action after the same card swiped again",
"restart": "Restart playlist",
"toggle": "Toggle pause / play",
"skip": "Skip to next track",
Expand Down
19 changes: 13 additions & 6 deletions src/webapp/src/commands/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -82,25 +82,32 @@ const commands = {
plugin: 'ctrl',
method: 'pause',
},
previous: {
prev_song: {
_package: 'player',
plugin: 'ctrl',
method: 'prev',
},
next: {
next_song: {
_package: 'player',
plugin: 'ctrl',
method: 'next',
},
shuffle: {
toggle: {
_package: 'player',
plugin: 'ctrl',
method: 'shuffle',
method: 'toggle',
},
repeat: {
set_shuffle: {
_package: 'player',
plugin: 'ctrl',
method: 'repeatmode',
method: 'set_shuffle',
argKeys: ['option'],
},
set_repeat: {
_package: 'player',
plugin: 'ctrl',
method: 'set_repeat',
argKeys: ['option'],
},
seek: {
_package: 'player',
Expand Down
34 changes: 32 additions & 2 deletions src/webapp/src/components/Cards/controls/actions/audio/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@ import React from 'react';

import CommandSelector from '../../command-selector';
import SliderChangeVolume from './slider-change-volume';
import OptionsSelector from '../../options-selector';

import { getActionAndCommand } from '../../../utils';

const SelectVolume = ({
const SelectAudioVolume = ({
actionData,
handleActionDataChange,
}) => {
Expand All @@ -23,8 +24,37 @@ const SelectVolume = ({
handleActionDataChange={handleActionDataChange}
/>
}
{command === 'set_shuffle' &&
<OptionsSelector
actionType="audio_shuffle"
actionData={actionData}
handleActionDataChange={handleActionDataChange}
optionLabel="cards.controls.actions.audio.shuffle.description"
options={[
{ labelKey: 'cards.controls.actions.audio.shuffle.label-toggle', value: 'toggle' },
{ labelKey: 'cards.controls.actions.audio.shuffle.label-enable', value: 'enable' },
{ labelKey: 'cards.controls.actions.audio.shuffle.label-disable', value: 'disable' },
]}
/>
}
{command === 'set_repeat' &&
<OptionsSelector
actionType="audio_repeat"
actionData={actionData}
handleActionDataChange={handleActionDataChange}
optionLabel="cards.controls.actions.audio.repeat.description"
options={[
{ labelKey: 'cards.controls.actions.audio.repeat.label-toggle', value: 'toggle' },
{ labelKey: 'cards.controls.actions.audio.repeat.label-toggle-repeat', value: 'toggle_repeat' },
{ labelKey: 'cards.controls.actions.audio.repeat.label-toggle-repeat-single', value: 'toggle_repeat_single' },
{ labelKey: 'cards.controls.actions.audio.repeat.label-enable-repeat', value: 'enable_repeat' },
{ labelKey: 'cards.controls.actions.audio.repeat.label-enable-repeat-single', value: 'enable_repeat_single' },
{ labelKey: 'cards.controls.actions.audio.repeat.label-disable', value: 'disable' },
]}
/>
}
</>
);
};

export default SelectVolume;
export default SelectAudioVolume;
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,12 @@ const SliderChangeVolume = ({
<Grid container alignItems="center" sx={{ marginTop: '20px' }}>
<Grid item xs={12}>
<Typography>
{t('cards.controls.actions.volume.title')}
{t('cards.controls.actions.audio.volume.title')}
</Typography>
<Stack spacing={2} direction="row" alignItems="center">
<Remove />
<Slider
aria-label={t('cards.controls.actions.volume.title')}
aria-label={t('cards.controls.actions.audio.volume.title')}
value={step || 0}
marks={marks}
step={1}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React from 'react';

import CommandSelector from '../../command-selector';
import OptionsSelector from '../../options-selector';
import ChangeOnRfidScan from './rfidcards/change-on-rfid-scan-options';
pabera marked this conversation as resolved.
Show resolved Hide resolved

import { getActionAndCommand } from '../../../utils';
Expand All @@ -18,9 +19,16 @@ const SelectSynchronisation = ({
handleActionDataChange={handleActionDataChange}
/>
{command === 'sync_rfidcards_change_on_rfid_scan' &&
<ChangeOnRfidScan
<OptionsSelector
actionType="sync_rfidcards_change_on_rfid_scan"
actionData={actionData}
handleActionDataChange={handleActionDataChange}
optionLabel="cards.controls.actions.synchronisation.rfidcards.description"
options={[
{ labelKey: 'cards.controls.actions.synchronisation.rfidcards.label-toggle', value: 'toggle' },
{ labelKey: 'cards.controls.actions.synchronisation.rfidcards.label-enable', value: 'enable' },
{ labelKey: 'cards.controls.actions.synchronisation.rfidcards.label-disable', value: 'disable' },
]}
/>
}
</>
Expand Down
Loading