summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Connors <benconnors@outlook.com>2019-05-30 20:29:03 -0400
committerBen Connors <benconnors@outlook.com>2019-05-30 20:29:03 -0400
commit8f430752f2b5a508dabe76fccfaf3f129a562e4b (patch)
treed65a7801e855c4c07efd709e8d136373f26e4506
parent9c464c705ef8ef0ecc2aa674beaaf89460e70d3d (diff)
Clean up audio submodule
- Implement MPVPlayer - Restructure into submodule, split files
-rw-r--r--blc/audio/__init__.py23
-rw-r--r--[-rwxr-xr-x]blc/audio/ffplay.py (renamed from blc/audio.py)78
-rwxr-xr-xblc/audio/interface.py53
-rw-r--r--blc/audio/mpv.py48
-rw-r--r--blc/audio/util.py9
5 files changed, 136 insertions, 75 deletions
diff --git a/blc/audio/__init__.py b/blc/audio/__init__.py
new file mode 100644
index 0000000..ebb9067
--- /dev/null
+++ b/blc/audio/__init__.py
@@ -0,0 +1,23 @@
+"""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.
+"""
+
+from .interface import AudioPlayer
+from .ffplay import FFPlayer
+
+
+__all__ = ["AudioPlayer", "FFPlayer", "DefaultAudioPlayer"]
+
+try:
+ from .mpv import MPVPlayer
+ __all__.append("MPVPlayer")
+ DefaultAudioPlayer = MPVPlayer
+except ImportError as e:
+ print(e)
+ DefaultAudioPlayer = FFPlayer
diff --git a/blc/audio.py b/blc/audio/ffplay.py
index 9df8853..306351a 100755..100644
--- a/blc/audio.py
+++ b/blc/audio/ffplay.py
@@ -1,77 +1,11 @@
-#!/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.
-"""
+"""Module for FFPlay-based audio player."""
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
+from .interface import AudioPlayer
+from .util import ttoti, titot
class FFPlayer(AudioPlayer):
"""Audio player using ffplay.
@@ -147,10 +81,4 @@ class FFPlayer(AudioPlayer):
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
diff --git a/blc/audio/interface.py b/blc/audio/interface.py
new file mode 100755
index 0000000..fff19cf
--- /dev/null
+++ b/blc/audio/interface.py
@@ -0,0 +1,53 @@
+#!/usr/bin/env python3
+
+"""Module for the AudioPlayer interface."""
+
+from abc import ABC, abstractmethod, abstractproperty
+
+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) -> int:
+ """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
diff --git a/blc/audio/mpv.py b/blc/audio/mpv.py
new file mode 100644
index 0000000..da21494
--- /dev/null
+++ b/blc/audio/mpv.py
@@ -0,0 +1,48 @@
+"""Module for using MPV as the AudioPlayer backend."""
+
+import mpv
+
+from .interface import AudioPlayer
+from .util import titot, ttoti
+
+class MPVPlayer(AudioPlayer):
+ """Class for using MPV as an audio player."""
+ @property
+ def position(self):
+ return ttoti(self.player.time_pos)
+
+ def play(self, start=-1):
+ ## TODO: Raise error if already playing?
+ self.player.pause = False
+
+ def pause(self):
+ self.player.pause = True
+
+ def seek(self, t):
+ self.player.seek(titot(t), reference="absolute", precision="exact")
+
+ def stop(self):
+ self.player.pause = True
+ self.seek(0)
+
+ @property
+ def volume(self) -> int:
+ return int(self.player.volume)
+
+ @volume.setter
+ def volume(self, value):
+ self.player.volume = value
+
+ @property
+ def playing(self) -> bool:
+ if self.started:
+ return not (self.player.pause or self.player.eof_reached)
+ return False
+
+ def __init__(self, fname, args=()):
+ super().__init__(fname, args)
+ self.player = mpv.MPV()
+ self.player.pause = True
+ self.player.keep_open = True
+ self.started = False
+ self.player.loadfile(fname)
diff --git a/blc/audio/util.py b/blc/audio/util.py
new file mode 100644
index 0000000..ed8345b
--- /dev/null
+++ b/blc/audio/util.py
@@ -0,0 +1,9 @@
+"""Various AudioPlayer utilities."""
+
+def ttoti(t):
+ """Convert seconds to milliseconds."""
+ return int(1000*t + 0.5)
+
+def titot(ti):
+ """Convert milliseconds to seconds."""
+ return ti/1000