Add locking to music.py
Ensure nothing interrupts the stop - release - nullify sequence. Also don't limit how many concurrent fades there can be.
This commit is contained in:
parent
987db155a1
commit
73879c6a99
35
app/music.py
35
app/music.py
@ -8,6 +8,8 @@ from time import sleep
|
|||||||
|
|
||||||
from log import DEBUG, ERROR
|
from log import DEBUG, ERROR
|
||||||
|
|
||||||
|
lock = threading.Lock()
|
||||||
|
|
||||||
|
|
||||||
class Music:
|
class Music:
|
||||||
"""
|
"""
|
||||||
@ -16,7 +18,7 @@ class Music:
|
|||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.current_track_start_time = None
|
self.current_track_start_time = None
|
||||||
self.fading = False
|
self.fading = 0
|
||||||
self.VLC = vlc.Instance()
|
self.VLC = vlc.Instance()
|
||||||
self.player = None
|
self.player = None
|
||||||
self.track_path = None
|
self.track_path = None
|
||||||
@ -30,15 +32,16 @@ class Music:
|
|||||||
to hold up the UI during the fade.
|
to hold up the UI during the fade.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
with lock:
|
||||||
DEBUG("music.fade()", True)
|
DEBUG("music.fade()", True)
|
||||||
|
|
||||||
if not self.playing():
|
if not self.player:
|
||||||
return None
|
|
||||||
|
|
||||||
# Only allow one track to fade at a time
|
|
||||||
if self.fading:
|
|
||||||
return
|
return
|
||||||
self.fading = True
|
|
||||||
|
if not self.player.get_position() > 0 and self.player.is_playing():
|
||||||
|
return
|
||||||
|
|
||||||
|
self.fading += 1
|
||||||
|
|
||||||
thread = threading.Thread(target=self._fade)
|
thread = threading.Thread(target=self._fade)
|
||||||
thread.start()
|
thread.start()
|
||||||
@ -69,16 +72,18 @@ class Music:
|
|||||||
measures_to_reduce_by = 0
|
measures_to_reduce_by = 0
|
||||||
for i in range(1, steps + 1):
|
for i in range(1, steps + 1):
|
||||||
measures_to_reduce_by += i
|
measures_to_reduce_by += i
|
||||||
volume_factor = 1 - (measures_to_reduce_by / total_measures_count)
|
volume_factor = 1 - (
|
||||||
|
measures_to_reduce_by / total_measures_count)
|
||||||
p.audio_set_volume(int(self.max_volume * volume_factor))
|
p.audio_set_volume(int(self.max_volume * volume_factor))
|
||||||
sleep(sleep_time)
|
sleep(sleep_time)
|
||||||
|
|
||||||
self.stop(p)
|
self.stop(p)
|
||||||
self.fading = False
|
self.fading -= 1
|
||||||
|
|
||||||
def get_playtime(self):
|
def get_playtime(self):
|
||||||
"Return elapsed play time"
|
"Return elapsed play time"
|
||||||
|
|
||||||
|
with lock:
|
||||||
if not self.player:
|
if not self.player:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
@ -87,6 +92,7 @@ class Music:
|
|||||||
def get_position(self):
|
def get_position(self):
|
||||||
"Return current position"
|
"Return current position"
|
||||||
|
|
||||||
|
with lock:
|
||||||
DEBUG("music.get_position", True)
|
DEBUG("music.get_position", True)
|
||||||
|
|
||||||
return self.player.get_position()
|
return self.player.get_position()
|
||||||
@ -118,22 +124,25 @@ class Music:
|
|||||||
get_position seems more reliable.
|
get_position seems more reliable.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
with lock:
|
||||||
if self.player:
|
if self.player:
|
||||||
if self.player.get_position() > 0 and self.player.is_playing():
|
if self.player.get_position() > 0 and self.player.is_playing():
|
||||||
return True
|
return True
|
||||||
|
|
||||||
# We take a copy of the player when fading, so we could be
|
# We take a copy of the player when fading, so we could be
|
||||||
# playing in a fade nowFalse
|
# playing in a fade nowFalse
|
||||||
return self.fading
|
return self.fading > 0
|
||||||
|
|
||||||
def set_position(self, ms):
|
def set_position(self, ms):
|
||||||
"Set current play time in milliseconds from start"
|
"Set current play time in milliseconds from start"
|
||||||
|
|
||||||
|
with lock:
|
||||||
return self.player.set_time(ms)
|
return self.player.set_time(ms)
|
||||||
|
|
||||||
def set_volume(self, volume):
|
def set_volume(self, volume):
|
||||||
"Set maximum volume used for player"
|
"Set maximum volume used for player"
|
||||||
|
|
||||||
|
with lock:
|
||||||
if not self.player:
|
if not self.player:
|
||||||
return
|
return
|
||||||
|
|
||||||
@ -143,6 +152,7 @@ class Music:
|
|||||||
def stop(self, player=None):
|
def stop(self, player=None):
|
||||||
"Immediately stop playing"
|
"Immediately stop playing"
|
||||||
|
|
||||||
|
with lock:
|
||||||
DEBUG(f"music.stop(), {player=}", True)
|
DEBUG(f"music.stop(), {player=}", True)
|
||||||
|
|
||||||
if not player:
|
if not player:
|
||||||
@ -154,10 +164,9 @@ class Music:
|
|||||||
|
|
||||||
position = player.get_position()
|
position = player.get_position()
|
||||||
player.stop()
|
player.stop()
|
||||||
p = player
|
DEBUG(f"Releasing player {player=}", True)
|
||||||
|
player.release()
|
||||||
# Ensure we don't reference player after release
|
# Ensure we don't reference player after release
|
||||||
player = None
|
player = None
|
||||||
DEBUG(f"Releasing player {p=}", True)
|
|
||||||
p.release()
|
|
||||||
|
|
||||||
return position
|
return position
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user