summaryrefslogtreecommitdiff
path: root/example-scripts/gstreamer/source-nostream-music-from-folder.py
diff options
context:
space:
mode:
authorFlorian Zeitz <florob@babelmonkeys.de>2016-09-14 10:28:11 +0200
committerFlorian Zeitz <florob@babelmonkeys.de>2016-09-14 11:04:28 +0200
commit27f9bb1c2aeebae5c1482d9b5f33e990f6cfb68b (patch)
treed7675356585728007b0bad2422564abf1848426d /example-scripts/gstreamer/source-nostream-music-from-folder.py
parentd77da93cb911a12305c6a18c2b3f317f8499a2d0 (diff)
source-*.py examples: pep8ify
* One import per line * Indent by 4 spaces * Reformat multiline strings * Spaces around infix operators * Reformat argument lists * Reformat list literals
Diffstat (limited to 'example-scripts/gstreamer/source-nostream-music-from-folder.py')
-rwxr-xr-xexample-scripts/gstreamer/source-nostream-music-from-folder.py363
1 files changed, 193 insertions, 170 deletions
diff --git a/example-scripts/gstreamer/source-nostream-music-from-folder.py b/example-scripts/gstreamer/source-nostream-music-from-folder.py
index a176a7d..c804182 100755
--- a/example-scripts/gstreamer/source-nostream-music-from-folder.py
+++ b/example-scripts/gstreamer/source-nostream-music-from-folder.py
@@ -1,6 +1,12 @@
#!/usr/bin/env python3
-import os, sys, gi, signal, random
-import argparse, logging, pyinotify
+import os
+import sys
+import gi
+import signal
+import random
+import argparse
+import logging
+import pyinotify
gi.require_version('Gst', '1.0')
from gi.repository import Gst, GObject, GLib
@@ -9,189 +15,206 @@ from gi.repository import Gst, GObject, GLib
GObject.threads_init()
Gst.init([])
-class Directory(object):
- def __init__(self, path):
- self.log = logging.getLogger('Directory')
- self.path = path
- self.scheduled = False
- self.rescan()
-
- self.log.debug('setting up inotify watch for %s', self.path)
- wm = pyinotify.WatchManager()
- notifier = pyinotify.Notifier(wm,
- timeout=10,
- default_proc_fun=self.inotify_callback)
-
- wm.add_watch(
- self.path,
- #pyinotify.ALL_EVENTS,
- pyinotify.IN_DELETE | pyinotify.IN_CREATE | pyinotify.IN_MODIFY,
- rec=True)
-
- GLib.io_add_watch(
- notifier._fd,
- GLib.IO_IN,
- self.io_callback,
- notifier)
-
- def inotify_callback(self, notifier):
- self.log.info('inotify callback %s: %s', notifier.maskname, notifier.pathname)
- if not self.scheduled:
- self.scheduled = True
- GLib.timeout_add(100, self.rescan)
- return True
-
- def io_callback(self, source, condition, notifier):
- notifier.process_events()
- while notifier.check_events():
- notifier.read_events()
- notifier.process_events()
-
- return True
- def is_playable_file(self, filepath):
- root, ext = os.path.splitext(filepath)
- return ext in ['.mp3', '.ogg', '.oga', '.wav', '.m4a', '.flac', 'self.opus']
-
- def rescan(self):
- self.log.info('scanning directory %s', self.path)
- self.scheduled = False
-
- all_files = []
-
- for root, dirs, files in os.walk(self.path):
- files = filter(self.is_playable_file, files)
- files = map(lambda f: os.path.join(root, f), files)
- files = list(files)
-
- self.log.debug('found directory %s: %u playable file(s)', root, len(files))
- all_files.extend(files)
+class Directory(object):
- self.log.info('found %u playable files', len(all_files))
- self.files = all_files
+ def __init__(self, path):
+ self.log = logging.getLogger('Directory')
+ self.path = path
+ self.scheduled = False
+ self.rescan()
+
+ self.log.debug('setting up inotify watch for %s', self.path)
+ wm = pyinotify.WatchManager()
+ notifier = pyinotify.Notifier(
+ wm,
+ timeout=10,
+ default_proc_fun=self.inotify_callback
+ )
+
+ wm.add_watch(
+ self.path,
+ # pyinotify.ALL_EVENTS,
+ pyinotify.IN_DELETE | pyinotify.IN_CREATE | pyinotify.IN_MODIFY,
+ rec=True
+ )
+
+ GLib.io_add_watch(
+ notifier._fd,
+ GLib.IO_IN,
+ self.io_callback,
+ notifier
+ )
+
+ def inotify_callback(self, notifier):
+ self.log.info('inotify callback %s: %s',
+ notifier.maskname, notifier.pathname)
+ if not self.scheduled:
+ self.scheduled = True
+ GLib.timeout_add(100, self.rescan)
+ return True
+
+ def io_callback(self, source, condition, notifier):
+ notifier.process_events()
+ while notifier.check_events():
+ notifier.read_events()
+ notifier.process_events()
+
+ return True
+
+ def is_playable_file(self, filepath):
+ root, ext = os.path.splitext(filepath)
+ return ext in ['.mp3', '.ogg', '.oga', '.wav', '.m4a',
+ '.flac', 'self.opus']
+
+ def rescan(self):
+ self.log.info('scanning directory %s', self.path)
+ self.scheduled = False
+
+ all_files = []
+
+ for root, dirs, files in os.walk(self.path):
+ files = filter(self.is_playable_file, files)
+ files = map(lambda f: os.path.join(root, f), files)
+ files = list(files)
+
+ self.log.debug('found directory %s: %u playable file(s)',
+ root, len(files))
+ all_files.extend(files)
+
+ self.log.info('found %u playable files', len(all_files))
+ self.files = all_files
+
+ def get_random_file(self):
+ return random.choice(self.files)
+
+ def get_random_uri(self):
+ return 'file://' + self.get_random_file()
- def get_random_file(self):
- return random.choice(self.files)
- def get_random_uri(self):
- return 'file://'+self.get_random_file()
+class LoopSource(object):
+ def __init__(self, directory):
+ self.log = logging.getLogger('LoopSource')
+ self.directory = directory
+
+ pipeline = """
+ audioresample name=join !
+ audioconvert !
+ audio/x-raw,format=S16LE,channels=2,rate=48000,
+ layout=interleaved !
+ matroskamux !
+ tcpclientsink host=localhost port=18000
+ """
+
+ # Parsing Pipeline
+ self.log.debug('creating pipeline\n%s', pipeline)
+ self.pipeline = Gst.parse_launch(pipeline)
+
+ # Selecting inital URI
+ inital_uri = self.directory.get_random_uri()
+ self.log.info('initial track %s', inital_uri)
+
+ # Create decoder-element
+ self.src = Gst.ElementFactory.make('uridecodebin', None)
+ self.src.set_property('uri', inital_uri)
+ self.src.connect('pad-added', self.on_pad_added)
+ self.pipeline.add(self.src)
+
+ # Save pad on the Join-Element
+ self.joinpad = self.pipeline.get_by_name('join').get_static_pad('sink')
+
+ # Binding End-of-Stream-Signal on Source-Pipeline
+ self.pipeline.bus.add_signal_watch()
+ self.pipeline.bus.connect("message::eos", self.on_eos)
+ self.pipeline.bus.connect("message::error", self.on_error)
+
+ self.log.debug('setting pipeline to playing')
+ self.pipeline.set_state(Gst.State.PLAYING)
+
+ def on_pad_added(self, src, pad):
+ self.log.debug('new pad on decoder, setting pad-probe')
+ pad.add_probe(
+ Gst.PadProbeType.EVENT_DOWNSTREAM | Gst.PadProbeType.BLOCK,
+ self.on_pad_event
+ )
+ if self.joinpad.is_linked():
+ self.log.debug('unlinking with joinpad')
+ self.joinpad.unlink(self.joinpad.get_peer())
+
+ clock = self.pipeline.get_clock()
+ if clock:
+ runtime = clock.get_time() - self.pipeline.get_base_time()
+ self.log.debug('setting pad offset to pipeline runtime: %sns',
+ runtime)
+ pad.set_offset(runtime)
+
+ self.log.debug('linking with joinpad')
+ pad.link(self.joinpad)
+
+ def on_pad_event(self, pad, info):
+ event = info.get_event()
+ self.log.debug('event %s on pad %s', event.type, pad)
+
+ if event.type == Gst.EventType.EOS:
+ self.log.debug('scheduling next track and dropping EOS-Event')
+ GObject.idle_add(self.next_track)
+ return Gst.PadProbeReturn.DROP
+
+ return Gst.PadProbeReturn.PASS
+
+ def next_track(self):
+ next_uri = self.directory.get_random_uri()
+ self.log.info('next track %s', next_uri)
+
+ self.src.set_state(Gst.State.READY)
+ self.src.set_property('uri', next_uri)
+ self.src.set_state(Gst.State.PLAYING)
+ return False
+
+ def on_eos(self, bus, message):
+ self.log.info('received EOS-Event on bus, exiting')
+ sys.exit(1)
+
+ def on_error(self, bus, message):
+ self.log.warning('received Error-Event on bus, exiting')
+ (error, debug) = message.parse_error()
+ self.log.warning('Error-Details: #%u: %s', error.code, debug)
+ sys.exit(1)
-class LoopSource(object):
- def __init__(self, directory):
- self.log = logging.getLogger('LoopSource')
- self.directory = directory
-
- pipeline = """
- audioresample name=join !
- audioconvert !
- audio/x-raw,format=S16LE,channels=2,layout=interleaved,rate=48000 !
- matroskamux !
- tcpclientsink host=localhost port=18000
- """
-
- # Parsing Pipeline
- self.log.debug('creating pipeline\n%s', pipeline)
- self.pipeline = Gst.parse_launch(pipeline)
-
- # Selecting inital URI
- inital_uri = self.directory.get_random_uri()
- self.log.info('initial track %s', inital_uri)
-
- # Create decoder-element
- self.src = Gst.ElementFactory.make('uridecodebin', None)
- self.src.set_property('uri', inital_uri);
- self.src.connect('pad-added', self.on_pad_added)
- self.pipeline.add(self.src)
-
- # Save pad on the Join-Element
- self.joinpad = self.pipeline.get_by_name('join').get_static_pad('sink')
-
- # Binding End-of-Stream-Signal on Source-Pipeline
- self.pipeline.bus.add_signal_watch()
- self.pipeline.bus.connect("message::eos", self.on_eos)
- self.pipeline.bus.connect("message::error", self.on_error)
-
- self.log.debug('setting pipeline to playing')
- self.pipeline.set_state(Gst.State.PLAYING)
-
- def on_pad_added(self, src, pad):
- self.log.debug('new pad on decoder, setting pad-probe')
- pad.add_probe(Gst.PadProbeType.EVENT_DOWNSTREAM | Gst.PadProbeType.BLOCK, self.on_pad_event)
- if self.joinpad.is_linked():
- self.log.debug('unlinking with joinpad')
- self.joinpad.unlink(self.joinpad.get_peer())
-
- clock = self.pipeline.get_clock()
- if clock:
- runtime = clock.get_time() - self.pipeline.get_base_time()
- self.log.debug('setting pad offset to pipeline runtime: %sns', runtime)
- pad.set_offset(runtime)
-
- self.log.debug('linking with joinpad')
- pad.link(self.joinpad)
-
- def on_pad_event(self, pad, info):
- event = info.get_event()
- self.log.debug('event %s on pad %s', event.type, pad)
-
- if event.type == Gst.EventType.EOS:
- self.log.debug('scheduling next track and dropping EOS-Event')
- GObject.idle_add(self.next_track)
- return Gst.PadProbeReturn.DROP
-
- return Gst.PadProbeReturn.PASS
-
- def next_track(self):
- next_uri = self.directory.get_random_uri()
- self.log.info('next track %s', next_uri)
-
- self.src.set_state(Gst.State.READY)
- self.src.set_property('uri', next_uri);
- self.src.set_state(Gst.State.PLAYING)
- return False
-
- def on_eos(self, bus, message):
- self.log.info('received EOS-Event on bus, exiting')
- sys.exit(1)
-
- def on_error(self, bus, message):
- self.log.warning('received Error-Event on bus, exiting')
- (error, debug) = message.parse_error()
- self.log.warning('Error-Details: #%u: %s', error.code, debug)
- sys.exit(1)
def main():
- signal.signal(signal.SIGINT, signal.SIG_DFL)
+ signal.signal(signal.SIGINT, signal.SIG_DFL)
- parser = argparse.ArgumentParser(description='Voctocore Music-Source')
- parser.add_argument('directory')
+ parser = argparse.ArgumentParser(description='Voctocore Music-Source')
+ parser.add_argument('directory')
- parser.add_argument('-v|-vv', '--verbose', action='count', default=0,
- help="Also print INFO and DEBUG messages.")
+ parser.add_argument('-v|-vv', '--verbose', action='count', default=0,
+ help="Also print INFO and DEBUG messages.")
- args = parser.parse_args()
+ args = parser.parse_args()
- if args.verbose >= 2:
- level = logging.DEBUG
- elif args.verbose == 1:
- level = logging.INFO
- else:
- level = logging.WARNING
+ if args.verbose >= 2:
+ level = logging.DEBUG
+ elif args.verbose == 1:
+ level = logging.INFO
+ else:
+ level = logging.WARNING
- logging.basicConfig(
- level=level,
- format='%(levelname)8s %(name)s: %(message)s')
+ logging.basicConfig(
+ level=level,
+ format='%(levelname)8s %(name)s: %(message)s'
+ )
- directory = Directory(args.directory)
- src = LoopSource(directory)
+ directory = Directory(args.directory)
+ src = LoopSource(directory)
- mainloop = GObject.MainLoop()
- try:
- mainloop.run()
- except KeyboardInterrupt:
- print('Terminated via Ctrl-C')
+ mainloop = GObject.MainLoop()
+ try:
+ mainloop.run()
+ except KeyboardInterrupt:
+ print('Terminated via Ctrl-C')
if __name__ == '__main__':
- main()
+ main()