def __init__(self, src_type=None, src_options={}, codecs=get_codecs(), codec_options={}, volume=1.0): if not src_type: from xpra.sound.pulseaudio_util import get_pa_device_options monitor_devices = get_pa_device_options(True, False) log.info("found pulseaudio monitor devices: %s", monitor_devices) if len(monitor_devices)==0: log.warn("could not detect any pulseaudio monitor devices") log.warn(" a test source will be used instead") src_type = "audiotestsrc" default_src_options = {"wave":2, "freq":100, "volume":0.4} else: monitor_device = monitor_devices.items()[0][0] log.info("using pulseaudio source device:") log.info(" '%s'", monitor_device) src_type = "pulsesrc" default_src_options = {"device" : monitor_device} src_options = default_src_options if src_type not in get_source_plugins(): raise InitExit(1, "invalid source plugin '%s', valid options are: %s" % (src_type, ",".join(get_source_plugins()))) matching = [x for x in CODEC_ORDER if (x in codecs and x in get_codecs())] log("SoundSource(..) 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_codecs().keys()))) codec = matching[0] encoder, fmt = get_encoder_formatter(codec) SoundPipeline.__init__(self, codec) self.src_type = src_type source_str = plugin_str(src_type, src_options) #FIXME: this is ugly and relies on the fact that we don't pass any codec options to work! encoder_str = plugin_str(encoder, codec_options or ENCODER_DEFAULT_OPTIONS.get(encoder, {})) fmt_str = plugin_str(fmt, MUXER_DEFAULT_OPTIONS.get(fmt, {})) pipeline_els = [source_str] if encoder in ENCODER_NEEDS_AUDIOCONVERT or src_type in SOURCE_NEEDS_AUDIOCONVERT: pipeline_els += ["audioconvert"] pipeline_els.append("volume name=volume volume=%s" % volume) pipeline_els += [encoder_str, fmt_str, APPSINK] self.setup_pipeline_and_bus(pipeline_els) self.volume = self.pipeline.get_by_name("volume") self.sink = self.pipeline.get_by_name("sink") try: if get_gst_version()<(1,0): self.sink.set_property("enable-last-buffer", False) else: self.sink.set_property("enable-last-sample", False) except Exception as e: log("failed to disable last buffer: %s", e) self.caps = None self.skipped_caps = set() if JITTER>0: self.jitter_queue = Queue() try: #Gst 1.0: self.sink.connect("new-sample", self.on_new_sample) self.sink.connect("new-preroll", self.on_new_preroll1) except: #Gst 0.10: self.sink.connect("new-buffer", self.on_new_buffer) self.sink.connect("new-preroll", self.on_new_preroll0)
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.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() from xpra.sound.gstreamer_util import gst_major_version, get_gst_version #anything older than this may cause problems (ie: centos 6.x) #because the attributes may not exist if get_gst_version() >= (0, 10, 36): sink_attributes.update( SINK_DEFAULT_ATTRIBUTES.get(gst_major_version, {}).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 get_gst_version() < (1, ): self.add_data = self.add_data0 else: self.add_data = self.add_data1 if self.queue: if not QUEUE_SILENT: if get_gst_version() < (1, ): self.queue.connect("overrun", self.queue_overrun0) self.queue.connect("underrun", self.queue_underrun0) self.queue.connect("running", self.queue_running0) self.queue.connect("pushing", self.queue_pushing0) else: self.queue.connect("overrun", self.queue_overrun1) self.queue.connect("underrun", self.queue_underrun1) self.queue.connect("running", self.queue_running1) self.queue.connect("pushing", self.queue_pushing1) else: #older versions may not have the "silent" attribute, #in which case we will emit the signals for nothing try: self.queue.set_property("silent", False) except Exception as e: log("cannot silence the queue %s: %s", self.queue, e)
def __init__(self, src_type=None, src_options={}, codecs=get_codecs(), codec_options={}, volume=1.0): if not src_type: try: from xpra.sound.pulseaudio.pulseaudio_util import get_pa_device_options monitor_devices = get_pa_device_options(True, False) log.info("found pulseaudio monitor devices: %s", monitor_devices) except ImportError as e: log.warn("Warning: pulseaudio is not available!") log.warn(" %s", e) monitor_devices = [] if len(monitor_devices)==0: log.warn("could not detect any pulseaudio monitor devices") log.warn(" a test source will be used instead") src_type = "audiotestsrc" default_src_options = {"wave":2, "freq":100, "volume":0.4} else: monitor_device = monitor_devices.items()[0][0] log.info("using pulseaudio source device:") log.info(" '%s'", monitor_device) src_type = "pulsesrc" default_src_options = {"device" : monitor_device} src_options = default_src_options if src_type not in get_source_plugins(): raise InitExit(1, "invalid source plugin '%s', valid options are: %s" % (src_type, ",".join(get_source_plugins()))) matching = [x for x in CODEC_ORDER if (x in codecs and x in get_codecs())] log("SoundSource(..) 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_codecs().keys()))) codec = matching[0] encoder, fmt = get_encoder_formatter(codec) self.queue = None self.caps = None self.volume = None self.sink = None self.src = None self.src_type = src_type self.buffer_latency = False self.jitter_queue = None self.file = None SoundPipeline.__init__(self, codec) src_options["name"] = "src" source_str = plugin_str(src_type, src_options) #FIXME: this is ugly and relies on the fact that we don't pass any codec options to work! encoder_str = plugin_str(encoder, codec_options or get_encoder_default_options(encoder)) fmt_str = plugin_str(fmt, MUXER_DEFAULT_OPTIONS.get(fmt, {})) pipeline_els = [source_str] if SOURCE_QUEUE_TIME>0: queue_el = ["queue", "name=queue", "min-threshold-time=0", "max-size-buffers=0", "max-size-bytes=0", "max-size-time=%s" % (SOURCE_QUEUE_TIME*MS_TO_NS), "leaky=%s" % GST_QUEUE_LEAK_DOWNSTREAM] pipeline_els += [" ".join(queue_el)] if encoder in ENCODER_NEEDS_AUDIOCONVERT or src_type in SOURCE_NEEDS_AUDIOCONVERT: pipeline_els += ["audioconvert"] pipeline_els.append("volume name=volume volume=%s" % volume) pipeline_els += [encoder_str, fmt_str, APPSINK] if not self.setup_pipeline_and_bus(pipeline_els): return self.volume = self.pipeline.get_by_name("volume") self.sink = self.pipeline.get_by_name("sink") if SOURCE_QUEUE_TIME>0: self.queue = self.pipeline.get_by_name("queue") if self.queue: try: self.queue.set_property("silent", True) except Exception as e: log("cannot make queue silent: %s", e) try: if get_gst_version()<(1,0): self.sink.set_property("enable-last-buffer", False) else: self.sink.set_property("enable-last-sample", False) except Exception as e: log("failed to disable last buffer: %s", e) self.skipped_caps = set() if JITTER>0: self.jitter_queue = Queue() try: #Gst 1.0: self.sink.connect("new-sample", self.on_new_sample) self.sink.connect("new-preroll", self.on_new_preroll1) except: #Gst 0.10: self.sink.connect("new-buffer", self.on_new_buffer) self.sink.connect("new-preroll", self.on_new_preroll0) self.src = self.pipeline.get_by_name("src") try: for x in ("actual-buffer-time", "actual-latency-time"): #don't comment this out, it is used to verify the attributes are present: gstlog("initial %s: %s", x, self.src.get_property(x)) self.buffer_latency = True except Exception as e: log.info("source %s does not support 'buffer-time' or 'latency-time':", self.src_type) log.info(" %s", e) else: #if the env vars have been set, try to honour the settings: global BUFFER_TIME, LATENCY_TIME if BUFFER_TIME>0: if BUFFER_TIME<LATENCY_TIME: log.warn("Warning: latency (%ims) must be lower than the buffer time (%ims)", LATENCY_TIME, BUFFER_TIME) else: log("latency tuning for %s, will try to set buffer-time=%i, latency-time=%i", src_type, BUFFER_TIME, LATENCY_TIME) def settime(attr, v): try: cval = self.src.get_property(attr) gstlog("default: %s=%i", attr, cval//1000) if v>=0: self.src.set_property(attr, v*1000) gstlog("overriding with: %s=%i", attr, v) except Exception as e: log.warn("source %s does not support '%s': %s", self.src_type, attr, e) settime("buffer-time", BUFFER_TIME) settime("latency-time", LATENCY_TIME) gen = generation.increase() if SAVE_TO_FILE is not None: parts = codec.split("+") if len(parts)>1: filename = SAVE_TO_FILE+str(gen)+"-"+parts[0]+".%s" % parts[1] else: filename = SAVE_TO_FILE+str(gen)+".%s" % codec self.file = open(filename, 'wb') log.info("saving %s stream to %s", codec, filename)
def run_sound(mode, error_cb, options, args): """ this function just parses command line arguments to feed into the sound subprocess class, which in turn just feeds them into the sound pipeline class (sink.py or src.py) """ from xpra.gtk_common.gobject_compat import want_gtk3 want_gtk3(True) gst = import_gst() if not gst: return 1 info = mode.replace("_sound_", "") #ie: "_sound_record" -> "record" from xpra.platform import program_context with program_context("Xpra-Audio-%s" % info, "Xpra Audio %s" % info): log("run_sound(%s, %s, %s, %s) gst=%s", mode, error_cb, options, args, gst) if mode == "_sound_record": subproc = sound_record elif mode == "_sound_play": subproc = sound_play elif mode == "_sound_query": plugins = get_all_plugin_names() sources = [x for x in get_source_plugins() if x in plugins] sinks = [x for x in get_sink_plugins() if x in plugins] from xpra.sound.gstreamer_util import get_gst_version, get_pygst_version d = { "encoders": can_encode(), "decoders": can_decode(), "sources": sources, "source.default": get_default_source() or "", "sinks": sinks, "sink.default": get_default_sink() or "", "muxers": get_muxers(), "demuxers": get_demuxers(), "gst.version": [int(x) for x in get_gst_version()], "pygst.version": get_pygst_version(), "plugins": plugins, "python.version": sys.version_info[:3], "python.bits": BITS, } if BUNDLE_METADATA: d["bundle-metadata"] = True for k, v in d.items(): if type(v) in (list, tuple): v = ",".join(str(x) for x in v) print("%s=%s" % (k, v)) return 0 else: log.error("unknown mode: %s" % mode) return 1 assert len(args) >= 6, "not enough arguments" #the plugin to use (ie: 'pulsesrc' for src.py or 'autoaudiosink' for sink.py) plugin = args[2] #plugin options (ie: "device=monitor_device,something=value") options = parse_simple_dict(args[3]) #codecs: codecs = [x.strip() for x in args[4].split(",")] #codec options: codec_options = parse_simple_dict(args[5]) #volume (optional): try: volume = int(args[6]) except: volume = 1.0 ss = None try: ss = subproc(plugin, options, codecs, codec_options, volume) ss.start() return 0 except InitExit as e: log.error("%s: %s", info, e) return e.status except InitException as e: log.error("%s: %s", info, e) return 1 except Exception: log.error("run_sound%s error", (mode, error_cb, options, args), exc_info=True) return 1 finally: if ss: ss.stop()
def __init__(self, sink_type=None, sink_options={}, codecs=get_codecs(), codec_options={}, volume=1.0): if not sink_type: sink_type = DEFAULT_SINK if sink_type not in SINKS: raise InitExit(1, "invalid sink: %s" % sink_type) matching = [x for x in CODEC_ORDER if (x in codecs and x in get_codecs())] 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_codecs().keys()))) codec = matching[0] decoder, parser = get_decoder_parser(codec) SoundPipeline.__init__(self, codec) self.sink_type = sink_type self.levels = deque(maxlen=100) decoder_str = plugin_str(decoder, codec_options) pipeline_els = [] appsrc_el = ["appsrc", "do-timestamp=1", "name=src", "emit-signals=0", "block=0", "is-live=0", "stream-type=stream", "format=%s" % GST_FORMAT_BUFFERS] pipeline_els.append(" ".join(appsrc_el)) pipeline_els.append(parser) pipeline_els.append(decoder_str) pipeline_els.append("audioconvert") pipeline_els.append("audioresample") pipeline_els.append("volume name=volume volume=%s" % volume) queue_el = ["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] if QUEUE_SILENT: queue_el.append("silent=%s" % QUEUE_SILENT) pipeline_els.append(" ".join(queue_el)) sink_attributes = SINK_SHARED_DEFAULT_ATTRIBUTES.copy() from xpra.sound.gstreamer_util import gst_major_version, get_gst_version #anything older than this may cause problems (ie: centos 6.x) #because the attributes may not exist if get_gst_version()>=(0, 10, 36): sink_attributes.update(SINK_DEFAULT_ATTRIBUTES.get(gst_major_version, {}).get(sink_type, {})) sink_attributes.update(sink_options) sink_str = plugin_str(sink_type, sink_attributes) pipeline_els.append(sink_str) self.setup_pipeline_and_bus(pipeline_els) self.volume = self.pipeline.get_by_name("volume") self.src = self.pipeline.get_by_name("src") self.queue = self.pipeline.get_by_name("queue") self.overruns = 0 self.underruns = 0 self.overrun_events = deque(maxlen=100) self.underrun_events = deque(maxlen=100) self.queue_state = "starting" self.last_underrun = 0 self.last_overrun = 0 self.last_max_update = time.time() self.level_lock = Lock() if QUEUE_SILENT==0: 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 __init__(self, src_type=None, src_options={}, codecs=get_encoders(), codec_options={}, volume=1.0): if not src_type: try: from xpra.sound.pulseaudio.pulseaudio_util import get_pa_device_options monitor_devices = get_pa_device_options(True, False) log.info("found pulseaudio monitor devices: %s", monitor_devices) except ImportError as e: log.warn("Warning: pulseaudio is not available!") log.warn(" %s", e) monitor_devices = [] if len(monitor_devices) == 0: log.warn("could not detect any pulseaudio monitor devices") log.warn(" a test source will be used instead") src_type = "audiotestsrc" default_src_options = {"wave": 2, "freq": 100, "volume": 0.4} else: monitor_device = monitor_devices.items()[0][0] log.info("using pulseaudio source device:") log.info(" '%s'", monitor_device) src_type = "pulsesrc" default_src_options = {"device": monitor_device} src_options = default_src_options if src_type not in get_source_plugins(): raise InitExit( 1, "invalid source plugin '%s', valid options are: %s" % (src_type, ",".join(get_source_plugins()))) matching = [ x for x in CODEC_ORDER if (x in codecs and x in get_encoders()) ] log("SoundSource(..) 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_encoders().keys()))) codec = matching[0] encoder, fmt, stream_compressor = get_encoder_elements(codec) SoundPipeline.__init__(self, codec) self.queue = None self.caps = None self.volume = None self.sink = None self.src = None self.src_type = src_type self.pending_metadata = [] self.buffer_latency = True self.jitter_queue = None self.file = None self.container_format = (fmt or "").replace("mux", "").replace("pay", "") self.stream_compressor = stream_compressor src_options["name"] = "src" source_str = plugin_str(src_type, src_options) #FIXME: this is ugly and relies on the fact that we don't pass any codec options to work! pipeline_els = [source_str] if SOURCE_QUEUE_TIME > 0: queue_el = [ "queue", "name=queue", "min-threshold-time=0", "max-size-buffers=0", "max-size-bytes=0", "max-size-time=%s" % (SOURCE_QUEUE_TIME * MS_TO_NS), "leaky=%s" % GST_QUEUE_LEAK_DOWNSTREAM ] pipeline_els += [" ".join(queue_el)] if encoder in ENCODER_NEEDS_AUDIOCONVERT or src_type in SOURCE_NEEDS_AUDIOCONVERT: pipeline_els += ["audioconvert"] pipeline_els.append("volume name=volume volume=%s" % volume) if encoder: encoder_str = plugin_str( encoder, codec_options or get_encoder_default_options(encoder)) pipeline_els.append(encoder_str) if fmt: fmt_str = plugin_str(fmt, MUXER_DEFAULT_OPTIONS.get(fmt, {})) pipeline_els.append(fmt_str) pipeline_els.append(APPSINK) if not self.setup_pipeline_and_bus(pipeline_els): return self.volume = self.pipeline.get_by_name("volume") self.sink = self.pipeline.get_by_name("sink") if SOURCE_QUEUE_TIME > 0: self.queue = self.pipeline.get_by_name("queue") if self.queue: try: self.queue.set_property("silent", True) except Exception as e: log("cannot make queue silent: %s", e) try: if get_gst_version() < (1, 0): self.sink.set_property("enable-last-buffer", False) else: self.sink.set_property("enable-last-sample", False) except Exception as e: log("failed to disable last buffer: %s", e) self.skipped_caps = set() if JITTER > 0: self.jitter_queue = Queue() try: #Gst 1.0: self.sink.connect("new-sample", self.on_new_sample) self.sink.connect("new-preroll", self.on_new_preroll1) except: #Gst 0.10: self.sink.connect("new-buffer", self.on_new_buffer) self.sink.connect("new-preroll", self.on_new_preroll0) self.src = self.pipeline.get_by_name("src") try: for x in ("actual-buffer-time", "actual-latency-time"): #don't comment this out, it is used to verify the attributes are present: try: gstlog("initial %s: %s", x, self.src.get_property(x)) except Exception as e: self.buffer_latency = False except Exception as e: log.info( "source %s does not support 'buffer-time' or 'latency-time':", self.src_type) log.info(" %s", e) else: #if the env vars have been set, try to honour the settings: global BUFFER_TIME, LATENCY_TIME if BUFFER_TIME > 0: if BUFFER_TIME < LATENCY_TIME: log.warn( "Warning: latency (%ims) must be lower than the buffer time (%ims)", LATENCY_TIME, BUFFER_TIME) else: log( "latency tuning for %s, will try to set buffer-time=%i, latency-time=%i", src_type, BUFFER_TIME, LATENCY_TIME) def settime(attr, v): try: cval = self.src.get_property(attr) gstlog("default: %s=%i", attr, cval // 1000) if v >= 0: self.src.set_property(attr, v * 1000) gstlog("overriding with: %s=%i", attr, v) except Exception as e: log.warn("source %s does not support '%s': %s", self.src_type, attr, e) settime("buffer-time", BUFFER_TIME) settime("latency-time", LATENCY_TIME) gen = generation.increase() if SAVE_TO_FILE is not None: parts = codec.split("+") if len(parts) > 1: filename = SAVE_TO_FILE + str( gen) + "-" + parts[0] + ".%s" % parts[1] else: filename = SAVE_TO_FILE + str(gen) + ".%s" % codec self.file = open(filename, 'wb') log.info("saving %s stream to %s", codec, filename)
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() from xpra.sound.gstreamer_util import gst_major_version, get_gst_version #anything older than this may cause problems (ie: centos 6.x) #because the attributes may not exist if get_gst_version()>=(0, 10, 36): sink_attributes.update(SINK_DEFAULT_ATTRIBUTES.get(gst_major_version, {}).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 get_gst_version()<(1, ): self.add_data = self.add_data0 else: self.add_data = self.add_data1 if self.queue: if not QUEUE_SILENT: if get_gst_version()<(1, ): self.queue.connect("overrun", self.queue_overrun0) self.queue.connect("underrun", self.queue_underrun0) self.queue.connect("running", self.queue_running0) self.queue.connect("pushing", self.queue_pushing0) else: self.queue.connect("overrun", self.queue_overrun1) self.queue.connect("underrun", self.queue_underrun1) self.queue.connect("running", self.queue_running1) self.queue.connect("pushing", self.queue_pushing1) else: #older versions may not have the "silent" attribute, #in which case we will emit the signals for nothing try: self.queue.set_property("silent", False) except Exception as e: log("cannot silence the queue %s: %s", self.queue, e)