Example #1
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, 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)
Example #2
0
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 gst_version, pygst_version
            import struct
            bits = struct.calcsize("P")*8
            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 gst_version],
                 "pygst.version"    : 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()
Example #3
0
File: sink.py Project: ljmljz/xpra
from xpra.sound.gstreamer_util import plugin_str, get_decoder_parser, get_queue_time, normv, get_codecs, get_default_sink, get_sink_plugins, \
                                        MP3, CODEC_ORDER, gst, QUEUE_LEAK, GST_QUEUE_NO_LEAK, MS_TO_NS, DEFAULT_SINK_PLUGIN_OPTIONS
from xpra.gtk_common.gobject_compat import import_glib

from xpra.scripts.config import InitExit
from xpra.util import csv
from xpra.os_util import thread
from xpra.log import Logger
log = Logger("sound")
gstlog = Logger("gstreamer")

glib = import_glib()


SINKS = get_sink_plugins()
DEFAULT_SINK = get_default_sink()

SINK_SHARED_DEFAULT_ATTRIBUTES = {"sync"    : False,
                                  "async"   : True,
                                  "qos"     : True
                                  }

SINK_DEFAULT_ATTRIBUTES = {0 : {
                                "pulsesink"  : {"client" : "Xpra"}
                               },
                           1 : {
                                "pulsesink"  : {"client-name" : "Xpra"}
                               },
                          }

QUEUE_SILENT = os.environ.get("XPRA_QUEUE_SILENT", "0")=="1"
Example #4
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)
Example #5
0
from xpra.sound.sound_pipeline import SoundPipeline
from xpra.gtk_common.gobject_util import one_arg_signal, gobject
from xpra.sound.gstreamer_util import plugin_str, get_decoder_parser, get_queue_time, normv, get_codecs, get_default_sink, get_sink_plugins, \
                                        MP3, CODEC_ORDER, gst, QUEUE_LEAK, GST_QUEUE_NO_LEAK, MS_TO_NS, DEFAULT_SINK_PLUGIN_OPTIONS

from xpra.scripts.config import InitExit
from xpra.util import csv
from xpra.os_util import thread
from xpra.log import Logger
log = Logger("sound")
gstlog = Logger("gstreamer")


SINKS = get_sink_plugins()
DEFAULT_SINK = get_default_sink()

SINK_SHARED_DEFAULT_ATTRIBUTES = {"sync"    : False,
                                  "async"   : True,
                                  "qos"     : True
                                  }

SINK_DEFAULT_ATTRIBUTES = {0 : {
                                "pulsesink"  : {"client" : "Xpra"}
                               },
                           1 : {
                                "pulsesink"  : {"client-name" : "Xpra"}
                               },
                          }

QUEUE_SILENT = 0