1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
|
"""Module for FFPlay-based audio player."""
import atexit
import subprocess as subp
import time
from .interface import AudioPlayer
from .util import ttoti, titot
class FFPlayer(AudioPlayer):
"""Audio player using ffplay.
Note that this is incredibly bad: the current position is guessed based on the start time of
the subprocess (meaning startup time of the ffplay process is counted in the current
position), no preloading of files is done, seeking is inaccurate and requires killing and
restarting the ffplay process, volume is ignored, and more. This is due to the fact that you
can't provide input to ffplay because it uses SDL exclusively for input (even though it can
be run without SDL?) so any change requires restarting the process. Use MPVPlayer if
possible.
"""
def play(self, start=-1):
if self.playing:
raise ValueError("Already playing")
if start != -1:
self.start = titot(start)
if self.start <= 0.1:
self.start = 0
self.player = subp.Popen(["ffplay", "-nodisp", "-autoexit", "-ss", str(self.start), *self.args, self.fname],
stdin=subp.DEVNULL, stdout=subp.DEVNULL, stderr=subp.DEVNULL)
atexit.register(self.stop)
self.start_time = time.monotonic()
def stop(self):
if not self.playing:
return
self.player.terminate()
atexit.unregister(self.stop)
self.player = None
self.start = 0
def seek(self, t):
if self.playing:
self.stop()
self.start = titot(t)
self.play()
else:
self.start = titot(t)
def pause(self):
if not self.playing:
return
self.stop()
self.start = self.start + time.monotonic()
@property
def position(self):
if not self.playing:
return self.start
return ttoti(self.start + time.monotonic() - self.start_time)
@property
def volume(self):
return 100
@volume.setter
def volume(self, vol):
return
@property
def playing(self):
if self.player is not None:
if self.player.poll() is not None:
self.player = None
return self.player is not None
def __init__(self, fname, args=()):
super().__init__(fname, args=args)
self.player = None
self.start = 0
self.start_time = 0
|