summaryrefslogtreecommitdiff
path: root/audio.py
diff options
context:
space:
mode:
Diffstat (limited to 'audio.py')
-rwxr-xr-xaudio.py154
1 files changed, 0 insertions, 154 deletions
diff --git a/audio.py b/audio.py
deleted file mode 100755
index 37b0f7d..0000000
--- a/audio.py
+++ /dev/null
@@ -1,154 +0,0 @@
-#!/usr/bin/env python3
-
-"""Audio module for BLC.
-
-This module defines an AudioPlayer interface which allows for various audio backends to be used
-interchangeably. It also defines a bare-bones better-than-nothing "FFPlayer" implementation and
-a better "MPVPlayer" implementation.
-
-"DefaultAudioPlayer" should be used in general and will refer to MPVPlayer if available and
-FFPlayer otherwise.
-"""
-
-import atexit
-import subprocess as subp
-import time
-import warnings
-
-from abc import ABC, abstractmethod, abstractproperty
-
-def ttoti(t):
- """Convert seconds to milliseconds."""
- return int(1000*t + 0.5)
-
-def titot(ti):
- """Convert milliseconds to seconds."""
- return ti/1000
-
-class AudioPlayer(ABC):
- """Class for playing audio.
-
- All time indices must be integers in milliseconds.
- """
- @abstractmethod
- def play(self, start=-1):
- """Play the audio from the given time.
-
- If start is -1, play it from the current time index (e.g. if paused). If the player is
- already playing, throw an error.
- """
- return
-
- @abstractmethod
- def seek(self, t):
- """Seek to the given time index."""
- return
-
- @abstractmethod
- def pause(self):
- """Pause the player."""
- return
-
- @abstractmethod
- def stop(self):
- """Stop the player and reset to the first time index."""
- return
-
- @abstractproperty
- def volume(self):
- """Get or set the current volume."""
- return
-
- @abstractproperty
- def position(self) -> int:
- """The current position in milliseconds."""
- return
-
- @abstractproperty
- def playing(self) -> bool:
- """Return if the player is playing or not."""
- return
-
- def __init__(self, fname, args=()):
- self.fname = fname
- self.args = args
-
-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)
- 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
-
-try:
- import mpv
-except (OSError, ImportError):
- warnings.warn("mpv backend unavailable, falling back to ffplay", RuntimeWarning)
-
- DefaultAudioPlayer = FFPlayer