[alarm] Added media_repeat configuration.

This commit is contained in:
Fabio Manganiello 2023-12-18 13:46:45 +01:00
parent 52fd64a162
commit cfc7a5a6a0
Signed by untrusted user: blacklight
GPG key ID: D90FBA7F76362774
5 changed files with 94 additions and 19 deletions

View file

@ -70,7 +70,8 @@ export default {
newAlarm: { newAlarm: {
condition_type: 'cron', condition_type: 'cron',
when: '* * * * *', when: '* * * * *',
audio_volume: this.$root.config?.alarm?.audio_volume ?? 100 audio_volume: this.$root.config?.alarm?.audio_volume ?? 100,
media_repeat: true,
}, },
} }
}, },

View file

@ -109,6 +109,29 @@
</div> </div>
</div> </div>
<div class="row item">
<label>
<div class="name">
<label>
<i class="icon fas fa-repeat" />
Repeat Media
</label>
<br />
<span class="subtext">
<span class="text">
Whether to repeat the media resource when it finishes playing
if the alarm is still running.
</span>
</span>
</div>
<div class="value">
<ToggleSwitch :value="editForm.media_repeat"
@input="editForm.media_repeat = $event.target.checked" />
</div>
</label>
</div>
<div class="row item"> <div class="row item">
<div class="name"> <div class="name">
<label> <label>
@ -202,6 +225,7 @@ import Slider from "@/components/elements/Slider"
import CronEditor from "@/components/elements/CronEditor" import CronEditor from "@/components/elements/CronEditor"
import FileSelector from "@/components/elements/FileSelector" import FileSelector from "@/components/elements/FileSelector"
import TimeInterval from "@/components/elements/TimeInterval" import TimeInterval from "@/components/elements/TimeInterval"
import ToggleSwitch from "@/components/elements/ToggleSwitch"
import Utils from "@/Utils" import Utils from "@/Utils"
export default { export default {
@ -214,6 +238,7 @@ export default {
ProcedureEditor, ProcedureEditor,
Slider, Slider,
TimeInterval, TimeInterval,
ToggleSwitch,
}, },
props: { props: {
@ -265,6 +290,7 @@ export default {
[ [
'media', 'media',
'media_plugin', 'media_plugin',
'media_repeat',
'name', 'name',
'snooze_interval', 'snooze_interval',
'dismiss_interval', 'dismiss_interval',

View file

@ -24,6 +24,7 @@ if not is_defined('alarm'):
state = Column(String, nullable=False, default='UNKNOWN') state = Column(String, nullable=False, default='UNKNOWN')
media = Column(String, nullable=True) media = Column(String, nullable=True)
media_plugin = Column(String, nullable=True) media_plugin = Column(String, nullable=True)
media_repeat = Column(Boolean, nullable=False, default=True)
audio_volume = Column(Integer, nullable=True) audio_volume = Column(Integer, nullable=True)
snooze_interval = Column(Integer, nullable=True) snooze_interval = Column(Integer, nullable=True)
dismiss_interval = Column(Integer, nullable=True) dismiss_interval = Column(Integer, nullable=True)

View file

@ -42,7 +42,19 @@ class AlarmPlugin(RunnablePlugin, EntityManager):
when: '0 7 * * 1-5' when: '0 7 * * 1-5'
media: ~/path/your_ringtone.mp3 media: ~/path/your_ringtone.mp3
audio_volume: 10 # 10% audio_volume: 10 # 10%
snooze_interval: 300 # 5 minutes snooze
# Repeat the played media resource until the alarm is
# snoozed/dismissed (default: true)
media_repeat: true
# Wait 5 minutes between a snooze and another run
snooze_interval: 300
# After 10 minutes with no manual snooze/dismiss,
# stop the alarm
dismiss_interval: 600
# Actions to be executed when the alarm goes on
actions: actions:
- action: tts.say - action: tts.say
args: args:
@ -263,6 +275,7 @@ class AlarmPlugin(RunnablePlugin, EntityManager):
name: Optional[str] = None, name: Optional[str] = None,
media: Optional[str] = None, media: Optional[str] = None,
media_plugin: Optional[str] = None, media_plugin: Optional[str] = None,
media_repeat: bool = True,
audio_file: Optional[str] = None, audio_file: Optional[str] = None,
audio_volume: Optional[Union[int, float]] = None, audio_volume: Optional[Union[int, float]] = None,
enabled: bool = True, enabled: bool = True,
@ -276,6 +289,7 @@ class AlarmPlugin(RunnablePlugin, EntityManager):
enabled=enabled, enabled=enabled,
media=media or audio_file, media=media or audio_file,
media_plugin=media_plugin or self.media_plugin, media_plugin=media_plugin or self.media_plugin,
media_repeat=media_repeat,
audio_volume=audio_volume, audio_volume=audio_volume,
snooze_interval=snooze_interval or self.snooze_interval, snooze_interval=snooze_interval or self.snooze_interval,
dismiss_interval=dismiss_interval or self.dismiss_interval, dismiss_interval=dismiss_interval or self.dismiss_interval,
@ -322,6 +336,7 @@ class AlarmPlugin(RunnablePlugin, EntityManager):
name: Optional[str] = None, name: Optional[str] = None,
media: Optional[str] = None, media: Optional[str] = None,
media_plugin: Optional[str] = None, media_plugin: Optional[str] = None,
media_repeat: bool = True,
audio_file: Optional[str] = None, audio_file: Optional[str] = None,
audio_volume: Optional[Union[int, float]] = None, audio_volume: Optional[Union[int, float]] = None,
enabled: bool = True, enabled: bool = True,
@ -340,6 +355,8 @@ class AlarmPlugin(RunnablePlugin, EntityManager):
:param name: Alarm name. :param name: Alarm name.
:param media: Path of the audio file to be played. :param media: Path of the audio file to be played.
:param media_plugin: Override the default media plugin for this alarm. :param media_plugin: Override the default media plugin for this alarm.
:param media_repeat: Repeat the played media resource until the alarm
is snoozed/dismissed (default: True).
:param audio_volume: Volume of the audio. :param audio_volume: Volume of the audio.
:param enabled: Whether the new alarm should be enabled (default: True). :param enabled: Whether the new alarm should be enabled (default: True).
:param snooze_interval: Snooze seconds before playing the alarm again. :param snooze_interval: Snooze seconds before playing the alarm again.
@ -355,6 +372,7 @@ class AlarmPlugin(RunnablePlugin, EntityManager):
when=when, when=when,
media=media, media=media,
media_plugin=media_plugin, media_plugin=media_plugin,
media_repeat=media_repeat,
audio_file=audio_file, audio_file=audio_file,
actions=actions or [], actions=actions or [],
name=name, name=name,
@ -373,6 +391,7 @@ class AlarmPlugin(RunnablePlugin, EntityManager):
actions: Optional[list] = None, actions: Optional[list] = None,
media: Optional[str] = None, media: Optional[str] = None,
media_plugin: Optional[str] = None, media_plugin: Optional[str] = None,
media_repeat: Optional[bool] = None,
audio_volume: Optional[Union[int, float]] = None, audio_volume: Optional[Union[int, float]] = None,
enabled: Optional[bool] = None, enabled: Optional[bool] = None,
snooze_interval: Optional[float] = None, snooze_interval: Optional[float] = None,
@ -394,6 +413,8 @@ class AlarmPlugin(RunnablePlugin, EntityManager):
:param actions: List of actions to be executed. :param actions: List of actions to be executed.
:param media: Path of the audio file to be played. :param media: Path of the audio file to be played.
:param media_plugin: Override the default media plugin for this alarm. :param media_plugin: Override the default media plugin for this alarm.
:param media_repeat: Repeat the played media resource until the alarm
is snoozed/dismissed (default: True).
:param audio_volume: Volume of the audio. :param audio_volume: Volume of the audio.
:param enabled: Whether the new alarm should be enabled. :param enabled: Whether the new alarm should be enabled.
:param snooze_interval: Snooze seconds before playing the alarm again. :param snooze_interval: Snooze seconds before playing the alarm again.
@ -418,6 +439,9 @@ class AlarmPlugin(RunnablePlugin, EntityManager):
when=when or alarm.when, when=when or alarm.when,
media=media or alarm.media, media=media or alarm.media,
media_plugin=media_plugin or alarm.media_plugin or self.media_plugin, media_plugin=media_plugin or alarm.media_plugin or self.media_plugin,
media_repeat=media_repeat
if media_repeat is not None
else alarm.media_repeat,
actions=actions if actions is not None else (alarm.actions or []), actions=actions if actions is not None else (alarm.actions or []),
name=new_name or name, name=new_name or name,
enabled=enabled if enabled is not None else alarm.is_enabled(), enabled=enabled if enabled is not None else alarm.is_enabled(),
@ -531,6 +555,7 @@ class AlarmPlugin(RunnablePlugin, EntityManager):
"enabled": true, "enabled": true,
"media": "/path/to/media.mp3", "media": "/path/to/media.mp3",
"media_plugin": "media.vlc", "media_plugin": "media.vlc",
"media_repeat": true,
"audio_volume": 10, "audio_volume": 10,
"snooze_interval": 300, "snooze_interval": 300,
"dismiss_interval": 300, "dismiss_interval": 300,

View file

@ -59,6 +59,7 @@ class Alarm:
name: Optional[str] = None, name: Optional[str] = None,
media: Optional[str] = None, media: Optional[str] = None,
media_plugin: Optional[str] = None, media_plugin: Optional[str] = None,
media_repeat: bool = True,
audio_volume: Optional[Union[int, float]] = None, audio_volume: Optional[Union[int, float]] = None,
snooze_interval: float = 300, snooze_interval: float = 300,
dismiss_interval: float = 300, dismiss_interval: float = 300,
@ -74,6 +75,7 @@ class Alarm:
self.name = name or f'Alarm_{self.id}' self.name = name or f'Alarm_{self.id}'
self.media = self._get_media_resource(media) self.media = self._get_media_resource(media)
self.media_plugin = media_plugin self.media_plugin = media_plugin
self.media_repeat = media_repeat
self.audio_volume = audio_volume self.audio_volume = audio_volume
self.snooze_interval = snooze_interval self.snooze_interval = snooze_interval
self.dismiss_interval = dismiss_interval self.dismiss_interval = dismiss_interval
@ -291,6 +293,39 @@ class Alarm:
self.actions.execute() self.actions.execute()
def _on_running(self):
sleep_time = None
while not self.should_stop():
plugin_status = self._get_media_plugin().status().output
if not isinstance(plugin_status, dict):
self.wait_stop(self.poll_interval)
continue
state = plugin_status.get('state')
if state == PlayerState.STOP.value:
if self.state == AlarmState.SNOOZED:
sleep_time = self._runtime_snooze_interval
else:
if (
self.media_repeat
and self.state != AlarmState.DISMISSED
and not self.should_stop()
):
self.wait_stop(self.poll_interval)
if not self.should_stop():
self.play_audio()
continue
self.state = AlarmState.WAITING
break
self._on_change()
self.wait_stop(self.poll_interval)
return sleep_time
def alarm_callback(self): def alarm_callback(self):
while not self.should_stop(): while not self.should_stop():
if self.is_enabled(): if self.is_enabled():
@ -302,23 +337,7 @@ class Alarm:
self.wait_stop(self.poll_interval) self.wait_stop(self.poll_interval)
sleep_time = None sleep_time = None
if self.state == AlarmState.RUNNING: if self.state == AlarmState.RUNNING:
while not self.should_stop(): sleep_time = self._on_running()
plugin_status = self._get_media_plugin().status().output
if not isinstance(plugin_status, dict):
self.wait_stop(self.poll_interval)
continue
state = plugin_status.get('state')
if state == PlayerState.STOP.value:
if self.state == AlarmState.SNOOZED:
sleep_time = self._runtime_snooze_interval
else:
self.state = AlarmState.WAITING
break
self._on_change()
self.wait_stop(self.poll_interval)
if self.state == AlarmState.SNOOZED: if self.state == AlarmState.SNOOZED:
sleep_time = self._runtime_snooze_interval sleep_time = self._runtime_snooze_interval
@ -357,6 +376,7 @@ class Alarm:
'state': self.state.name, 'state': self.state.name,
'media': self.media, 'media': self.media,
'media_plugin': self.media_plugin, 'media_plugin': self.media_plugin,
'media_repeat': self.media_repeat,
'audio_volume': self.audio_volume, 'audio_volume': self.audio_volume,
'snooze_interval': self.snooze_interval, 'snooze_interval': self.snooze_interval,
'dismiss_interval': self.dismiss_interval, 'dismiss_interval': self.dismiss_interval,
@ -372,6 +392,7 @@ class Alarm:
name=str(alarm.name), name=str(alarm.name),
media=alarm.media, # type: ignore media=alarm.media, # type: ignore
media_plugin=kwargs.pop('media_plugin', alarm.media_plugin), # type: ignore media_plugin=kwargs.pop('media_plugin', alarm.media_plugin), # type: ignore
media_repeat=alarm.media_repeat, # type: ignore
audio_volume=alarm.audio_volume, # type: ignore audio_volume=alarm.audio_volume, # type: ignore
actions=alarm.actions, # type: ignore actions=alarm.actions, # type: ignore
snooze_interval=alarm.snooze_interval, # type: ignore snooze_interval=alarm.snooze_interval, # type: ignore
@ -391,6 +412,7 @@ class Alarm:
next_run=self.get_next(), next_run=self.get_next(),
media=self.media, media=self.media,
media_plugin=self.media_plugin, media_plugin=self.media_plugin,
media_repeat=self.media_repeat,
audio_volume=self.audio_volume, audio_volume=self.audio_volume,
actions=[ actions=[
Request.to_dict(req) if isinstance(req, Request) else req Request.to_dict(req) if isinstance(req, Request) else req