def __init__(self, sink_type=DEFAULT_SINK, options={}, codec=MP3, decoder_options={}): assert sink_type in SINKS, "invalid sink: %s" % sink_type decoders = get_decoders(codec) assert len(decoders) > 0, "no decoders found for %s" % codec SoundPipeline.__init__(self, codec) self.sink_type = sink_type decoder = decoders[0] decoder_str = plugin_str(decoder, decoder_options) pipeline_els = [] pipeline_els.append("appsrc name=src") pipeline_els.append("mp3parse") pipeline_els.append(decoder_str) pipeline_els.append("volume name=volume") pipeline_els.append("audioconvert") pipeline_els.append("audioresample") if QUEUE_TIME > 0: pipeline_els.append("queue name=queue max-size-time=%s leaky=%s" % (QUEUE_TIME, QUEUE_LEAK)) else: pipeline_els.append("queue leaky=%s" % QUEUE_LEAK) pipeline_els.append(sink_type) self.setup_pipeline_and_bus(pipeline_els) self.volume = self.pipeline.get_by_name("volume") self.src = self.pipeline.get_by_name("src") self.src.set_property('emit-signals', True) self.src.set_property('stream-type', 'stream') self.src.set_property('block', False) self.src.set_property('format', 4) self.src.set_property('is-live', True) if QUEUE_TIME > 0: self.queue = self.pipeline.get_by_name("queue") def overrun(*args): debug("sound sink queue overrun") def underrun(*args): debug("sound sink queue underrun") self.queue.connect("overrun", overrun) self.queue.connect("underrun", underrun) else: self.queue = None self.src.connect("need-data", self.need_data) self.src.connect("enough-data", self.on_enough_data)
def __init__(self, sink_type=DEFAULT_SINK, options={}, codec=MP3, decoder_options={}): assert sink_type in SINKS, "invalid sink: %s" % sink_type decoders = get_decoders(codec) assert len(decoders)>0, "no decoders found for %s" % codec SoundPipeline.__init__(self, codec) self.sink_type = sink_type decoder = decoders[0] decoder_str = plugin_str(decoder, decoder_options) pipeline_els = [] pipeline_els.append("appsrc name=src") pipeline_els.append("mp3parse") pipeline_els.append(decoder_str) pipeline_els.append("volume name=volume") pipeline_els.append("audioconvert") pipeline_els.append("audioresample") if QUEUE_TIME>0: pipeline_els.append("queue name=queue max-size-time=%s leaky=%s" % (QUEUE_TIME, QUEUE_LEAK)) else: pipeline_els.append("queue leaky=%s" % QUEUE_LEAK) pipeline_els.append(sink_type) self.setup_pipeline_and_bus(pipeline_els) self.volume = self.pipeline.get_by_name("volume") self.src = self.pipeline.get_by_name("src") self.src.set_property('emit-signals', True) self.src.set_property('stream-type', 'stream') self.src.set_property('block', False) self.src.set_property('format', 4) self.src.set_property('is-live', True) if QUEUE_TIME>0: self.queue = self.pipeline.get_by_name("queue") def overrun(*args): debug("sound sink queue overrun") def underrun(*args): debug("sound sink queue underrun") self.queue.connect("overrun", overrun) self.queue.connect("underrun", underrun) else: self.queue = None self.src.connect("need-data", self.need_data) self.src.connect("enough-data", self.on_enough_data)
def __init__(self, sink_type=None, sink_options={}, codecs=get_decoders(), codec_options={}, volume=1.0): if not sink_type: sink_type = get_default_sink() if sink_type not in get_sink_plugins(): raise InitExit(1, "invalid sink: %s" % sink_type) matching = [ x for x in CODEC_ORDER if (x in codecs and x in get_decoders()) ] log("SoundSink(..) found matching codecs %s", matching) if not matching: raise InitExit( 1, "no matching codecs between arguments '%s' and supported list '%s'" % (csv(codecs), csv(get_decoders().keys()))) codec = matching[0] decoder, parser, stream_compressor = get_decoder_elements(codec) SoundPipeline.__init__(self, codec) self.container_format = (parser or "").replace("demux", "").replace("depay", "") self.sink_type = sink_type self.stream_compressor = stream_compressor log("container format=%s, stream_compressor=%s, sink type=%s", self.container_format, self.stream_compressor, self.sink_type) self.levels = deque(maxlen=100) self.volume = None self.src = None self.queue = None self.normal_volume = volume self.target_volume = volume self.volume_timer = 0 self.overruns = 0 self.underruns = 0 self.overrun_events = deque(maxlen=100) self.queue_state = "starting" self.last_data = None self.last_underrun = 0 self.last_overrun = 0 self.refill = True self.last_max_update = monotonic_time() self.last_min_update = monotonic_time() self.level_lock = Lock() pipeline_els = [] appsrc_el = [ "appsrc", #"do-timestamp=1", "name=src", "emit-signals=0", "block=0", "is-live=0", "stream-type=%s" % STREAM_TYPE, "format=%s" % BUFFER_FORMAT ] pipeline_els.append(" ".join(appsrc_el)) if parser: pipeline_els.append(parser) if decoder: decoder_str = plugin_str(decoder, codec_options) pipeline_els.append(decoder_str) pipeline_els.append("audioconvert") pipeline_els.append("audioresample") if QUEUE_TIME > 0: pipeline_els.append(" ".join([ "queue", "name=queue", "min-threshold-time=0", "max-size-buffers=0", "max-size-bytes=0", "max-size-time=%s" % QUEUE_TIME, "leaky=%s" % QUEUE_LEAK ])) pipeline_els.append("volume name=volume volume=0") sink_attributes = SINK_SHARED_DEFAULT_ATTRIBUTES.copy() #anything older than this may cause problems (ie: centos 6.x) #because the attributes may not exist sink_attributes.update(SINK_DEFAULT_ATTRIBUTES.get(sink_type, {})) get_options_cb = DEFAULT_SINK_PLUGIN_OPTIONS.get( sink_type.replace("sink", "")) if get_options_cb: v = get_options_cb() log("%s()=%s", get_options_cb, v) sink_attributes.update(v) sink_attributes.update(sink_options) sink_str = plugin_str(sink_type, sink_attributes) pipeline_els.append(sink_str) if not self.setup_pipeline_and_bus(pipeline_els): return self.volume = self.pipeline.get_by_name("volume") self.src = self.pipeline.get_by_name("src") self.queue = self.pipeline.get_by_name("queue") if self.queue: if QUEUE_SILENT: self.queue.set_property("silent", False) else: self.queue.connect("overrun", self.queue_overrun) self.queue.connect("underrun", self.queue_underrun) self.queue.connect("running", self.queue_running) self.queue.connect("pushing", self.queue_pushing)
def main(): from xpra.platform import program_context with program_context("Sound-Record"): args = sys.argv log.enable_debug() import os.path if len(args) not in (2, 3): print("usage: %s [-v|--verbose] filename [codec]" % sys.argv[0]) return 1 filename = args[1] if not os.path.exists(filename): print("file %s does not exist" % filename) return 2 decoders = get_decoders() if len(args) == 3: codec = args[2] if codec not in decoders: print("invalid codec: %s" % codec) print("only supported: %s" % str(decoders.keys())) return 2 codecs = [codec] else: codec = None parts = filename.split(".") if len(parts) > 1: extension = parts[-1] if extension.lower() in codecs: codec = extension.lower() print("guessed codec %s from file extension %s" % (codec, extension)) if codec is None: print("assuming this is an mp3 file...") codec = MP3 codecs = [codec] log.enable_debug() with open(filename, "rb") as f: data = f.read() print("loaded %s bytes from %s" % (len(data), filename)) #force no leak since we push all the data at once global QUEUE_LEAK, QUEUE_SILENT QUEUE_LEAK = GST_QUEUE_NO_LEAK QUEUE_SILENT = True ss = SoundSink(codecs=codecs) def eos(*args): print("eos%s" % (args, )) glib.idle_add(glib_mainloop.quit) ss.connect("eos", eos) ss.start() glib_mainloop = glib.MainLoop() import signal def deadly_signal(*_args): glib.idle_add(ss.stop) glib.idle_add(glib_mainloop.quit) def force_quit(_sig, _frame): sys.exit() signal.signal(signal.SIGINT, force_quit) signal.signal(signal.SIGTERM, force_quit) signal.signal(signal.SIGINT, deadly_signal) signal.signal(signal.SIGTERM, deadly_signal) def check_for_end(*_args): qtime = ss.queue.get_property("current-level-time") // MS_TO_NS if qtime <= 0: log.info("underrun (end of stream)") thread.start_new_thread(ss.stop, ()) glib.timeout_add(500, glib_mainloop.quit) return False return True glib.timeout_add(1000, check_for_end) glib.idle_add(ss.add_data, data) glib_mainloop.run() return 0
def __init__(self, sink_type=None, sink_options={}, codecs=get_decoders(), codec_options={}, volume=1.0): if not sink_type: sink_type = get_default_sink() if sink_type not in get_sink_plugins(): raise InitExit(1, "invalid sink: %s" % sink_type) matching = [x for x in CODEC_ORDER if (x in codecs and x in get_decoders())] log("SoundSink(..) found matching codecs %s", matching) if not matching: raise InitExit(1, "no matching codecs between arguments '%s' and supported list '%s'" % (csv(codecs), csv(get_decoders().keys()))) codec = matching[0] decoder, parser, self.stream_compressor = get_decoder_elements(codec) SoundPipeline.__init__(self, codec) self.container_format = (parser or "").replace("demux", "").replace("depay", "") self.sink_type = sink_type self.levels = deque(maxlen=100) self.volume = None self.src = None self.queue = None self.normal_volume = volume self.target_volume = volume self.volume_timer = 0 self.overruns = 0 self.underruns = 0 self.overrun_events = deque(maxlen=100) self.queue_state = "starting" self.last_data = None self.last_underrun = 0 self.last_overrun = 0 self.last_max_update = time.time() self.last_min_update = time.time() self.level_lock = Lock() pipeline_els = [] appsrc_el = ["appsrc", "do-timestamp=1", "name=src", "emit-signals=0", "block=0", "is-live=0", "stream-type=%s" % STREAM_TYPE, "format=%s" % BUFFER_FORMAT] pipeline_els.append(" ".join(appsrc_el)) if parser: pipeline_els.append(parser) if decoder: decoder_str = plugin_str(decoder, codec_options) pipeline_els.append(decoder_str) pipeline_els.append("audioconvert") pipeline_els.append("audioresample") pipeline_els.append("volume name=volume volume=0") if QUEUE_TIME>0: pipeline_els.append(" ".join(["queue", "name=queue", "min-threshold-time=0", "max-size-buffers=0", "max-size-bytes=0", "max-size-time=%s" % QUEUE_TIME, "leaky=%s" % QUEUE_LEAK])) sink_attributes = SINK_SHARED_DEFAULT_ATTRIBUTES.copy() #anything older than this may cause problems (ie: centos 6.x) #because the attributes may not exist sink_attributes.update(SINK_DEFAULT_ATTRIBUTES.get(sink_type, {})) get_options_cb = DEFAULT_SINK_PLUGIN_OPTIONS.get(sink_type.replace("sink", "")) if get_options_cb: v = get_options_cb() log("%s()=%s", get_options_cb, v) sink_attributes.update(v) sink_attributes.update(sink_options) sink_str = plugin_str(sink_type, sink_attributes) pipeline_els.append(sink_str) if not self.setup_pipeline_and_bus(pipeline_els): return self.volume = self.pipeline.get_by_name("volume") self.src = self.pipeline.get_by_name("src") self.queue = self.pipeline.get_by_name("queue") if self.queue: if QUEUE_SILENT: self.queue.set_property("silent", False) else: self.queue.connect("overrun", self.queue_overrun) self.queue.connect("underrun", self.queue_underrun) self.queue.connect("running", self.queue_running) self.queue.connect("pushing", self.queue_pushing)
def main(): from xpra.platform import program_context with program_context("Sound-Record"): args = sys.argv log.enable_debug() import os.path if len(args) not in (2, 3): print("usage: %s [-v|--verbose] filename [codec]" % sys.argv[0]) return 1 filename = args[1] if not os.path.exists(filename): print("file %s does not exist" % filename) return 2 decoders = get_decoders() if len(args)==3: codec = args[2] if codec not in decoders: print("invalid codec: %s" % codec) print("only supported: %s" % str(decoders.keys())) return 2 codecs = [codec] else: codec = None parts = filename.split(".") if len(parts)>1: extension = parts[-1] if extension.lower() in codecs: codec = extension.lower() print("guessed codec %s from file extension %s" % (codec, extension)) if codec is None: print("assuming this is an mp3 file...") codec = MP3 codecs = [codec] log.enable_debug() with open(filename, "rb") as f: data = f.read() print("loaded %s bytes from %s" % (len(data), filename)) #force no leak since we push all the data at once global QUEUE_LEAK, QUEUE_SILENT QUEUE_LEAK = GST_QUEUE_NO_LEAK QUEUE_SILENT = True ss = SoundSink(codecs=codecs) def eos(*args): print("eos") glib.idle_add(glib_mainloop.quit) ss.connect("eos", eos) ss.start() glib_mainloop = glib.MainLoop() import signal def deadly_signal(*args): glib.idle_add(ss.stop) glib.idle_add(glib_mainloop.quit) def force_quit(sig, frame): sys.exit() signal.signal(signal.SIGINT, force_quit) signal.signal(signal.SIGTERM, force_quit) from xpra.gtk_common.gobject_compat import is_gtk3 if not is_gtk3(): signal.signal(signal.SIGINT, deadly_signal) signal.signal(signal.SIGTERM, deadly_signal) def check_for_end(*args): qtime = ss.queue.get_property("current-level-time")//MS_TO_NS if qtime<=0: log.info("underrun (end of stream)") thread.start_new_thread(ss.stop, ()) glib.timeout_add(500, glib_mainloop.quit) return False return True glib.timeout_add(1000, check_for_end) glib.idle_add(ss.add_data, data) glib_mainloop.run() return 0