95 lines
2.1 KiB
Python
95 lines
2.1 KiB
Python
import os
|
|
import threading
|
|
import vlc
|
|
|
|
from config import Config
|
|
from time import sleep
|
|
|
|
from log import DEBUG
|
|
|
|
|
|
class Music:
|
|
"""
|
|
Manage the playing of music tracks
|
|
"""
|
|
|
|
def __init__(self):
|
|
self.fading = False
|
|
self.player = None
|
|
self.track_path = None
|
|
|
|
def fade(self):
|
|
"""
|
|
Fade the currently playing track.
|
|
|
|
Return the current track path and position.
|
|
|
|
The actual management of fading runs in its own thread so as not
|
|
to hold up the UI during the fade.
|
|
"""
|
|
|
|
DEBUG("fade()")
|
|
|
|
if not self.playing():
|
|
return (None, None)
|
|
|
|
path = self.track_path
|
|
position = self.player.get_position()
|
|
|
|
thread = threading.Thread(target=self._fade)
|
|
thread.start()
|
|
|
|
return (path, position)
|
|
|
|
def _fade(self):
|
|
"""
|
|
Implementation of fading the current track in a separate thread.
|
|
"""
|
|
|
|
DEBUG("_fade()")
|
|
|
|
fade_time = Config.FADE_TIME / 1000
|
|
sleep_time = fade_time / Config.FADE_STEPS
|
|
step_percent = int((100 / Config.FADE_STEPS) * -1)
|
|
|
|
# Take a copy of current player to allow another track to be
|
|
# started without interfering here
|
|
p = self.player
|
|
for i in range(100, 0, step_percent):
|
|
p.audio_set_volume(i)
|
|
sleep(sleep_time)
|
|
|
|
p.pause()
|
|
p.release()
|
|
|
|
def get_playtime(self):
|
|
"Return elapsed play time"
|
|
|
|
return self.player.get_time()
|
|
|
|
def play(self, path):
|
|
"""
|
|
Start playing the track at path.
|
|
|
|
Raise AttributeError if path not found.
|
|
"""
|
|
|
|
DEBUG(f"play({path})")
|
|
|
|
if not os.access(path, os.R_OK):
|
|
raise AttributeError(f"Cannot access {path}")
|
|
|
|
self.track_path = path
|
|
|
|
self.player = vlc.MediaPlayer(path)
|
|
self.player.audio_set_volume(100)
|
|
self.player.play()
|
|
|
|
def playing(self):
|
|
"Return True if currently playing a track, else False"
|
|
|
|
if self.player:
|
|
return self.player.is_playing()
|
|
else:
|
|
return False
|