def __init__(self, src_type=DEFAULT_SRC, src_options={}, codec=MP3, encoder_options={}): assert src_type in SOURCES encoder, fmt = get_encoder_formatter(codec) SoundPipeline.__init__(self, codec) self.add_signals(self.__generic_signals__) self.src_type = src_type source_str = plugin_str(src_type, src_options) encoder_str = plugin_str(encoder, encoder_options) pipeline_els = [source_str] if AUDIOCONVERT: pipeline_els += ["audioconvert"] if AUDIORESAMPLE: pipeline_els += [ "audioresample", "audio/x-raw-int,rate=44100,channels=2"] pipeline_els += [encoder_str, fmt, "appsink name=sink"] self.setup_pipeline_and_bus(pipeline_els) self.sink = self.pipeline.get_by_name("sink") self.sink.set_property("emit-signals", True) self.sink.set_property("max-buffers", 10) self.sink.set_property("drop", False) self.sink.set_property("sync", True) self.sink.set_property("qos", False) self.sink.connect("new-buffer", self.on_new_buffer) self.sink.connect("new-preroll", self.on_new_preroll)
def cleanup(self): if self.volume_timer != 0: glib.source_remove(self.volume_timer) self.volume_timer = 0 SoundPipeline.cleanup(self) self.sink_type = "" self.src = None
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, src_type=DEFAULT_SRC, src_options={}, codec=MP3, volume=1.0, encoder_options={}): assert src_type in SOURCES encoder, fmt = get_encoder_formatter(codec) SoundPipeline.__init__(self, codec) self.src_type = src_type source_str = plugin_str(src_type, src_options) encoder_str = plugin_str(encoder, encoder_options) fmt_str = plugin_str(fmt, MUXER_DEFAULT_OPTIONS.get(fmt, {})) pipeline_els = [source_str] if AUDIOCONVERT: pipeline_els += ["audioconvert"] if AUDIORESAMPLE: pipeline_els += [ "audioresample", "audio/x-raw-int,rate=44100,channels=2"] pipeline_els.append("volume name=volume volume=%s" % volume) pipeline_els += [encoder_str, fmt_str, "appsink name=sink"] self.setup_pipeline_and_bus(pipeline_els) self.volume = self.pipeline.get_by_name("volume") self.sink = self.pipeline.get_by_name("sink") self.sink.set_property("emit-signals", True) self.sink.set_property("max-buffers", 10) self.sink.set_property("drop", False) self.sink.set_property("sync", True) self.sink.set_property("qos", False) 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, src_type=DEFAULT_SRC, src_options={}, codec=MP3, encoder_options={}): assert src_type in SOURCES encoder, fmt = get_encoder_formatter(codec) SoundPipeline.__init__(self, codec) self.src_type = src_type source_str = plugin_str(src_type, src_options) encoder_str = plugin_str(encoder, encoder_options) pipeline_els = [source_str] if AUDIOCONVERT: pipeline_els += ["audioconvert"] if AUDIORESAMPLE: pipeline_els += [ "audioresample", "audio/x-raw-int,rate=44100,channels=2" ] pipeline_els += [encoder_str, fmt, "appsink name=sink"] self.setup_pipeline_and_bus(pipeline_els) self.sink = self.pipeline.get_by_name("sink") self.sink.set_property("emit-signals", True) self.sink.set_property("max-buffers", 10) self.sink.set_property("drop", False) self.sink.set_property("sync", True) self.sink.set_property("qos", False) self.sink.connect("new-buffer", self.on_new_buffer) self.sink.connect("new-preroll", self.on_new_preroll)
def cleanup(self): if self.volume_timer!=0: glib.source_remove(self.volume_timer) self.volume_timer = 0 SoundPipeline.cleanup(self) self.sink_type = "" self.src = None
def __init__(self, src_type=DEFAULT_SRC, src_options={}, codec=MP3, encoder_options={}): assert src_type in SOURCES encoders = get_encoders(codec) assert len(encoders) > 0, "no encoders found for %s" % codec SoundPipeline.__init__(self, codec) self.src_type = src_type source_str = plugin_str(src_type, src_options) encoder = encoders[0] encoder_str = plugin_str(encoder, encoder_options) pipeline_els = [source_str] pipeline_els += [ "audioconvert", "audioresample", encoder_str, "appsink name=sink" ] self.setup_pipeline_and_bus(pipeline_els) self.sink = self.pipeline.get_by_name("sink") self.sink.set_property("emit-signals", True) self.sink.set_property("max-buffers", 10) self.sink.set_property("drop", False) self.sink.set_property("sync", True) self.sink.set_property("qos", False) self.sink.connect("new-buffer", self.on_new_buffer) self.sink.connect("new-preroll", self.on_new_preroll)
def cleanup(self): SoundPipeline.cleanup(self) self.src_type = "" self.sink = None self.caps = None f = self.file if f: self.file = None f.close()
def __init__(self, sink_type=None, sink_options={}, codecs=CODECS, codec_options={}, volume=1.0): if not sink_type: sink_type = DEFAULT_SINK assert sink_type in SINKS, "invalid sink: %s" % sink_type matching = [x for x in CODEC_ORDER if (x in codecs and x in CODECS)] log("SoundSink(..) found matching codecs %s", matching) assert len(matching) > 0, "no matching codecs between arguments %s and supported list %s" % (codecs, CODECS) codec = matching[0] decoder, parser = get_decoder_parser(codec) SoundPipeline.__init__(self, codec) self.sink_type = sink_type decoder_str = plugin_str(decoder, codec_options) pipeline_els = [] pipeline_els.append( "appsrc" + " name=src" + " emit-signals=0" + " block=0" + " is-live=0" + " stream-type=stream" + " format=%s" % GST_FORMAT_BUFFERS ) 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=%s" % QUEUE_MIN_TIME, "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 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.queue_state = "starting" 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, sink_type=None, sink_options={}, codecs=CODECS, codec_options={}, volume=1.0): if not sink_type: sink_type = DEFAULT_SINK assert sink_type in SINKS, "invalid sink: %s" % sink_type matching = [x for x in CODEC_ORDER if (x in codecs and x in CODECS)] log("SoundSink(..) found matching codecs %s", matching) assert len(matching)>0, "no matching codecs between arguments %s and supported list %s" % (codecs, CODECS) codec = matching[0] decoder, parser = get_decoder_parser(codec) SoundPipeline.__init__(self, codec) self.sink_type = sink_type decoder_str = plugin_str(decoder, codec_options) pipeline_els = [] pipeline_els.append("appsrc"+ " name=src"+ " emit-signals=0"+ " block=0"+ " is-live=0"+ " stream-type=stream"+ " format=%s" % GST_FORMAT_BUFFERS) 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=%s" % QUEUE_MIN_TIME, "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 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.queue_state = "starting" 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, sink_type=DEFAULT_SINK, options={}, codec=MP3, decoder_options={}): assert sink_type in SINKS, "invalid sink: %s" % sink_type decoder, parser = get_decoder_parser(codec) SoundPipeline.__init__(self, codec) self.sink_type = sink_type decoder_str = plugin_str(decoder, decoder_options) pipeline_els = [] pipeline_els.append("appsrc name=src") pipeline_els.append(parser) pipeline_els.append(decoder_str) if VOLUME: pipeline_els.append("volume name=volume") pipeline_els.append("audioconvert") pipeline_els.append("audioresample") if QUEUE: 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: 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 get_info(self) -> dict: info = SoundPipeline.get_info(self) if QUEUE_TIME>0 and self.queue: clt = self.queue.get_property("current-level-time") qmax = self.queue.get_property("max-size-time") qmin = self.queue.get_property("min-threshold-time") info["queue"] = { "min" : qmin//MS_TO_NS, "max" : qmax//MS_TO_NS, "cur" : clt//MS_TO_NS, "pct" : min(QUEUE_TIME, clt)*100//qmax, "overruns" : self.overruns, "underruns" : self.underruns, "state" : self.queue_state, } info["sink"] = self.get_element_properties( self.sink, "buffer-time", "latency-time", #"next_sample", "eos_rendering", "async", "blocksize", "enable-last-sample", "max-bitrate", "max-lateness", #"processing-deadline", "qos", "render-delay", "sync", "throttle-time", "ts-offset", ) return info
def get_info(self) -> dict: info = SoundPipeline.get_info(self) if QUEUE_TIME>0 and self.queue: clt = self.queue.get_property("current-level-time") qmax = self.queue.get_property("max-size-time") qmin = self.queue.get_property("min-threshold-time") info["queue"] = { "min" : qmin//MS_TO_NS, "max" : qmax//MS_TO_NS, "cur" : clt//MS_TO_NS, "pct" : min(QUEUE_TIME, clt)*100//qmax, "overruns" : self.overruns, "underruns" : self.underruns, "state" : self.queue_state, } sink_info = info.setdefault("sink", {}) for x in ( "buffer-time", "latency-time", #"next_sample", "eos_rendering", "async", "blocksize", "enable-last-sample", "max-bitrate", "max-lateness", "processing-deadline", "qos", "render-delay", "sync", "throttle-time", "ts-offset", ): try: v = self.sink.get_property(x) if v>=0: sink_info[x] = v except Exception as e: log.warn("Warning: %s", e) return info
def get_info(self) -> dict: info = SoundPipeline.get_info(self) if self.queue: info["queue"] = { "cur": self.queue.get_property("current-level-time") // MS_TO_NS } if CUTTER_THRESHOLD > 0 and (self.min_timestamp or self.max_timestamp): info["cutter.min-timestamp"] = self.min_timestamp info["cutter.max-timestamp"] = self.max_timestamp if self.buffer_latency: for x in ("actual-buffer-time", "actual-latency-time"): v = self.src.get_property(x) if v >= 0: info[x] = v src_info = info.setdefault("src", {}) for x in ( "actual-buffer-time", "actual-latency-time", "buffer-time", "latency-time", "provide-clock", ): try: v = self.src.get_property(x) if v >= 0: src_info[x] = v except Exception as e: log.warn("Warning: %s", e) return info
def get_info(self): info = SoundPipeline.get_info(self) if QUEUE_TIME>0: clt = self.queue.get_property("current-level-time") info["queue.used_pct"] = int(min(QUEUE_TIME, clt)*100.0/QUEUE_TIME) info["queue.overruns"] = self.overruns info["queue.state"] = self.queue_state return info
def __init__(self, sink_type=DEFAULT_SINK, options={}, codec=MP3, decoder_options={}): assert sink_type in SINKS, "invalid sink: %s" % sink_type decoder, parser = get_decoder_parser(codec) SoundPipeline.__init__(self, codec) self.sink_type = sink_type decoder_str = plugin_str(decoder, decoder_options) pipeline_els = [] pipeline_els.append("appsrc"+ " name=src"+ " max-bytes=32768"+ " emit-signals=0"+ " block=0"+ " is-live=0"+ " stream-type=stream"+ " format=4") pipeline_els.append(parser) pipeline_els.append(decoder_str) pipeline_els.append("audioconvert") pipeline_els.append("audioresample") queue_el = ["queue", "name=queue", "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)) pipeline_els.append(sink_type) self.setup_pipeline_and_bus(pipeline_els) self.src = self.pipeline.get_by_name("src") self.queue = self.pipeline.get_by_name("queue") self.overruns = 0 self.queue_state = "starting" 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) if FAKE_OVERRUN>0: def fake_overrun(*args): self.emit("overrun", 500) gobject.timeout_add(FAKE_OVERRUN*1000, fake_overrun)
def get_info(self): info = SoundPipeline.get_info(self) if self.queue: info["queue"] = {"cur" : self.queue.get_property("current-level-time")//MS_TO_NS} if self.buffer_latency: for x in ("actual-buffer-time", "actual-latency-time"): v = self.src.get_property(x) if v>=0: info[x] = v return info
def get_info(self): info = SoundPipeline.get_info(self) if QUEUE_TIME>0: clt = self.queue.get_property("current-level-time") updict(info, "queue", { "time" : int(QUEUE_TIME/MS_TO_NS), "min_time" : int(QUEUE_MIN_TIME/MS_TO_NS), "used_pct" : int(min(QUEUE_TIME, clt)*100.0/QUEUE_TIME), "used" : int(clt/MS_TO_NS), "overruns" : self.overruns, "state" : self.queue_state}) return info
def __init__(self, sink_type=DEFAULT_SINK, options={}, codec=MP3, decoder_options={}): assert sink_type in SINKS, "invalid sink: %s" % sink_type decoder, parser = get_decoder_parser(codec) SoundPipeline.__init__(self, codec) self.sink_type = sink_type decoder_str = plugin_str(decoder, decoder_options) pipeline_els = [] pipeline_els.append("appsrc name=src") pipeline_els.append(parser) pipeline_els.append(decoder_str) if VOLUME: pipeline_els.append("volume name=volume") pipeline_els.append("audioconvert") pipeline_els.append("audioresample") if QUEUE: 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: 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 decoder, parser = get_decoder_parser(codec) SoundPipeline.__init__(self, codec) self.add_signals(self.__generic_signals__) self.sink_type = sink_type decoder_str = plugin_str(decoder, decoder_options) pipeline_els = [] pipeline_els.append("appsrc"+ " name=src"+ " max-bytes=32768"+ " emit-signals=0"+ " block=0"+ " is-live=0"+ " stream-type=stream"+ " format=4") pipeline_els.append(parser) pipeline_els.append(decoder_str) pipeline_els.append("audioconvert") pipeline_els.append("audioresample") queue_el = "queue" + \ " name=queue"+ \ " 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(queue_el) pipeline_els.append(sink_type) self.setup_pipeline_and_bus(pipeline_els) self.src = self.pipeline.get_by_name("src") self.queue = self.pipeline.get_by_name("queue") self.overruns = 0 self.queue_state = "starting" 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 get_info(self) -> dict: info = SoundPipeline.get_info(self) if self.queue: info["queue"] = {"cur" : self.queue.get_property("current-level-time")//MS_TO_NS} if CUTTER_THRESHOLD>0 and (self.min_timestamp or self.max_timestamp): info["cutter.min-timestamp"] = self.min_timestamp info["cutter.max-timestamp"] = self.max_timestamp if self.buffer_latency: for x in ("actual-buffer-time", "actual-latency-time"): v = self.src.get_property(x) if v>=0: info[x] = v return info
def __init__(self, src_type=DEFAULT_SRC, src_options={}, codec=MP3, encoder_options={}): assert src_type in SOURCES encoders = get_encoders(codec) assert len(encoders)>0, "no encoders found for %s" % codec SoundPipeline.__init__(self, codec) self.src_type = src_type source_str = plugin_str(src_type, src_options) encoder = encoders[0] encoder_str = plugin_str(encoder, encoder_options) pipeline_els = [source_str] pipeline_els += ["audioconvert", "audioresample", encoder_str, "appsink name=sink"] self.setup_pipeline_and_bus(pipeline_els) self.sink = self.pipeline.get_by_name("sink") self.sink.set_property("emit-signals", True) self.sink.set_property("max-buffers", 10) self.sink.set_property("drop", False) self.sink.set_property("sync", True) self.sink.set_property("qos", False) self.sink.connect("new-buffer", self.on_new_buffer) self.sink.connect("new-preroll", self.on_new_preroll)
def get_info(self): info = SoundPipeline.get_info(self) if QUEUE_TIME>0: clt = self.queue.get_property("current-level-time") qmax = self.queue.get_property("max-size-time") qmin = self.queue.get_property("min-threshold-time") updict(info, "queue", { "min" : qmin//MS_TO_NS, "max" : qmax//MS_TO_NS, "cur" : clt//MS_TO_NS, "pct" : min(QUEUE_TIME, clt)*100//qmax, "overruns" : self.overruns, "underruns" : self.underruns, "state" : self.queue_state}) return info
def get_info(self): info = SoundPipeline.get_info(self) if QUEUE_TIME > 0: clt = self.queue.get_property("current-level-time") updict( info, "queue", { "time": int(QUEUE_TIME / MS_TO_NS), "min_time": int(QUEUE_MIN_TIME / MS_TO_NS), "used_pct": int(min(QUEUE_TIME, clt) * 100.0 / QUEUE_TIME), "used": int(clt / MS_TO_NS), "overruns": self.overruns, "state": self.queue_state, }, ) return info
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) 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.level_lock = Lock() 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=%s" % STREAM_TYPE, "format=%s" % BUFFER_FORMAT] 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=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 cleanup(self): SoundPipeline.cleanup(self) self.sink_type = "" self.src = None
def __init__(self, src_type=None, src_options={}, codecs=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 - will use a test source") 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: %s", monitor_device) src_type = "pulsesrc" default_src_options = {"device" : monitor_device} src_options = default_src_options src_options.update(src_options) assert src_type in get_source_plugins(), "invalid source plugin '%s'" % src_type matching = [x for x in CODEC_ORDER if (x in codecs and x in CODECS)] log("SoundSource(..) found matching codecs %s", matching) assert len(matching)>0, "no matching codecs between arguments %s and supported list %s" % (codecs, CODECS) 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) encoder_str = plugin_str(encoder, codec_options) fmt_str = plugin_str(fmt, MUXER_DEFAULT_OPTIONS.get(fmt, {})) pipeline_els = [source_str] if AUDIOCONVERT: pipeline_els += ["audioconvert"] if AUDIORESAMPLE: pipeline_els += [ "audioresample", "audio/x-raw-int,rate=44100,channels=2"] pipeline_els.append("volume name=volume volume=%s" % volume) if QUEUE_TIME>0: queue_el = ["queue", "name=queue", "max-size-buffers=0", "max-size-bytes=0", "max-size-time=%s" % QUEUE_TIME, "leaky=%s" % QUEUE_LEAK] pipeline_els.append(" ".join(queue_el)) pipeline_els += [encoder_str, fmt_str, "appsink name=sink"] self.setup_pipeline_and_bus(pipeline_els) self.volume = self.pipeline.get_by_name("volume") self.sink = self.pipeline.get_by_name("sink") self.sink.set_property("emit-signals", True) self.sink.set_property("max-buffers", 10) #0? self.sink.set_property("drop", False) self.sink.set_property("sync", True) #False? self.sink.set_property("qos", False) 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, 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 start(self): SoundPipeline.start(self) self.timeout_add(UNMUTE_DELAY, self.start_adjust_volume)
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 __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 cleanup(self): SoundPipeline.cleanup(self) self.src_type = "" self.sink = None self.caps = None
def cleanup(self): SoundPipeline.cleanup(self) self.cancel_volume_timer() self.sink_type = "" self.src = None
def get_info(self): info = SoundPipeline.get_info(self) if self.caps: info["caps"] = self.caps return info
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 __init__(self, src_type=None, src_options={}, codecs=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 - will use a test source" ) 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: %s", monitor_device) src_type = "pulsesrc" default_src_options = {"device": monitor_device} src_options = default_src_options src_options.update(src_options) assert src_type in get_source_plugins( ), "invalid source plugin '%s'" % src_type matching = [x for x in CODEC_ORDER if (x in codecs and x in CODECS)] log("SoundSource(..) found matching codecs %s", matching) assert len( matching ) > 0, "no matching codecs between arguments %s and supported list %s" % ( codecs, CODECS) 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) encoder_str = plugin_str(encoder, codec_options) fmt_str = plugin_str(fmt, MUXER_DEFAULT_OPTIONS.get(fmt, {})) pipeline_els = [source_str] if AUDIOCONVERT: pipeline_els += ["audioconvert"] if AUDIORESAMPLE: pipeline_els += [ "audioresample", "audio/x-raw-int,rate=44100,channels=2" ] pipeline_els.append("volume name=volume volume=%s" % volume) if QUEUE_TIME > 0: queue_el = [ "queue", "name=queue", "max-size-buffers=0", "max-size-bytes=0", "max-size-time=%s" % QUEUE_TIME, "leaky=%s" % QUEUE_LEAK ] pipeline_els.append(" ".join(queue_el)) pipeline_els += [encoder_str, fmt_str, "appsink name=sink"] self.setup_pipeline_and_bus(pipeline_els) self.volume = self.pipeline.get_by_name("volume") self.sink = self.pipeline.get_by_name("sink") self.sink.set_property("emit-signals", True) self.sink.set_property("max-buffers", 10) #0? self.sink.set_property("drop", False) self.sink.set_property("sync", True) #False? self.sink.set_property("qos", False) 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)