xpra icon
Bug tracker and wiki

This bug tracker and wiki are being discontinued
please use https://github.com/Xpra-org/xpra instead.


Ticket #849: sound-clean-split-gstreamer.patch

File sound-clean-split-gstreamer.patch, 22.4 KB (added by Antoine Martin, 6 years ago)

work on completely removing any gstreamer imports from the client and server: everything goes through the wrapper, and we only call it once to probe

  • xpra/client/gtk_base/bug_report.py

     
    9595        from xpra.codecs.loader import codec_versions, load_codecs
    9696        load_codecs()
    9797        try:
    98             from xpra.sound.gstreamer_util import get_info as get_sound_info
     98            from xpra.sound.wrapper import query_sound
     99            def get_sound_info():
     100                return query_sound()
    99101        except:
    100102            get_sound_info = None
    101103        if self.opengl_info:
  • xpra/client/gtk_base/session_info.py

     
    169169        tb.new_row("Pango",     client_vinfo("pango"),      server_vinfo("pango"))
    170170        tb.new_row("Python", label(python_platform.python_version()), label(server_version_info("server.python.version", "python_version", "python.version")))
    171171
    172         cl_gst_v, cl_pygst_v = "", ""
    173172        try:
    174             from xpra.sound.gstreamer_util import gst_version as cl_gst_v, pygst_version as cl_pygst_v
     173            from xpra.sound.wrapper import query_sound
     174            props = query_sound()
    175175        except Exception as e:
    176             log("cannot load gstreamer: %s", e)
    177         tb.new_row("GStreamer", label(make_version_str(cl_gst_v)), label(server_version_info("sound.gst.version", "gst_version")))
    178         tb.new_row("pygst", label(make_version_str(cl_pygst_v)), label(server_version_info("sound.pygst.version", "pygst_version")))
     176            log("cannot load sound information: %s", e)
     177            props = {}
     178        gst_version = props.get("gst.version", "")
     179        pygst_version = props.get("pygst.version", "")
     180        tb.new_row("GStreamer", label(make_version_str(gst_version)), label(server_version_info("sound.gst.version", "gst_version")))
     181        tb.new_row("pygst", label(make_version_str(pygst_version)), label(server_version_info("sound.pygst.version", "pygst_version")))
    179182        tb.new_row("OpenGL", label(make_version_str(self.client.opengl_props.get("opengl", "n/a"))), label("n/a"))
    180183        tb.new_row("OpenGL Vendor", label(make_version_str(self.client.opengl_props.get("vendor", ""))), label("n/a"))
    181184        tb.new_row("PyOpenGL", label(make_version_str(self.client.opengl_props.get("pyopengl", "n/a"))), label("n/a"))
  • xpra/client/ui_client_base.py

     
    134134        self.encoding = None
    135135
    136136        #sound:
    137         try:
    138             from xpra.sound.gstreamer_util import has_gst
    139         except:
    140             has_gst = False
    141137        self.sound_source_plugin = None
    142         self.speaker_allowed = has_gst
     138        self.speaker_allowed = False
    143139        self.speaker_enabled = False
    144140        self.speaker_codecs = []
    145         self.microphone_allowed = has_gst
     141        self.microphone_allowed = False
    146142        self.microphone_enabled = False
    147143        self.microphone_codecs = []
    148         if has_gst:
    149             try:
    150                 from xpra.sound.wrapper import get_sound_codecs
    151                 self.speaker_codecs = get_sound_codecs(True, False)
    152                 self.speaker_allowed = len(self.speaker_codecs)>0
    153                 self.microphone_codecs = get_sound_codecs(False, False)
    154                 self.microphone_allowed = len(self.microphone_codecs)>0
    155             except Exception as e:
    156                 soundlog("sound support unavailable: %s", e)
    157         soundlog("speaker_allowed=%s, speaker_codecs=%s", self.speaker_allowed, csv(self.speaker_codecs))
    158         soundlog("microphone_allowed=%s, microphone_codecs=%s", self.microphone_allowed, csv(self.microphone_codecs))
    159144        self.av_sync = False
    160145        #sound state:
    161146        self.on_sink_ready = None
     
    272257        self.supports_mmap = MMAP_SUPPORTED and opts.mmap
    273258        self.mmap_group = opts.mmap_group
    274259
     260        self.sound_properties = {}
     261        self.sound_source_plugin = opts.sound_source
     262        self.speaker_allowed = sound_option(opts.speaker) in ("on", "off")
     263        self.microphone_allowed = sound_option(opts.microphone) in ("on", "off")
    275264        try:
    276             from xpra.sound.gstreamer_util import has_gst
    277         except:
    278             has_gst = False
    279         self.sound_source_plugin = opts.sound_source
    280         self.speaker_allowed = sound_option(opts.speaker) in ("on", "off") and has_gst
    281         self.speaker_enabled = sound_option(opts.speaker)=="on" and has_gst
    282         self.microphone_allowed = sound_option(opts.microphone) in ("on", "off") and has_gst
    283         self.microphone_enabled = sound_option(opts.microphone)=="on" and has_gst
     265            from xpra.sound.wrapper import query_sound
     266            self.sound_properties = query_sound()
     267        except Exception as e:
     268            soundlog("sound support unavailable: %s", e)
     269        self.speaker_allowed = self.speaker_allowed and bool(self.sound_properties)
     270        self.microphone_allowed = self.microphone_allowed and bool(self.sound_properties)
     271        self.speaker_enabled = sound_option(opts.speaker)=="on" and bool(self.sound_properties)
     272        self.microphone_enabled = sound_option(opts.microphone)=="on" and bool(self.sound_properties)
    284273        if opts.speaker_codec:
    285274            self.speaker_codecs = opts.speaker_codec
    286275        if len(self.speaker_codecs)==0 and self.speaker_allowed:
     
    290279        if len(self.microphone_codecs)==0 and self.microphone_allowed:
    291280            self.microphone_allowed = False
    292281        self.av_sync = opts.av_sync
     282        soundlog("speaker_allowed=%s, speaker_codecs=%s", self.speaker_allowed, csv(self.speaker_codecs))
     283        soundlog("microphone_allowed=%s, microphone_codecs=%s", self.microphone_allowed, csv(self.microphone_codecs))
     284        soundlog("av-sync=%s", self.av_sync)
    293285
    294286        self.readonly = opts.readonly
    295287        self.windows_enabled = opts.windows
     
    11401132            import xpra.sound
    11411133            log("loaded %s", xpra.sound)
    11421134            try:
    1143                 from xpra.sound.gstreamer_util import has_gst, get_info as get_gst_info
     1135                FIXME:
     1136                #from xpra.sound.gstreamer_util import has_gst, get_info as get_gst_info
    11441137                sound_caps.update(get_gst_info(receive=self.speaker_allowed, send=self.microphone_allowed,
    11451138                                     receive_codecs=self.speaker_codecs, send_codecs=self.microphone_codecs))
    11461139            except Exception as e:
     
    15921585        soundlog("start_sending_sound()")
    15931586        assert self.microphone_allowed, "microphone forwarding is disabled"
    15941587        assert self.server_sound_receive, "client support for receiving sound is disabled"
    1595         from xpra.sound.gstreamer_util import ALLOW_SOUND_LOOP
     1588        from xpra.sound.sound_util import ALLOW_SOUND_LOOP
    15961589        if self._remote_machine_id and self._remote_machine_id==get_machine_id() and not ALLOW_SOUND_LOOP:
    15971590            #looks like we're on the same machine, verify it's a different user:
    15981591            if self._remote_uuid==get_user_uuid():
     
    16671660            log.error("cannot start receiving sound: support not enabled on the server")
    16681661            return
    16691662        #choose a codec:
    1670         from xpra.sound.gstreamer_util import CODEC_ORDER
     1663        from xpra.sound.sound_util import CODEC_ORDER
    16711664        matching_codecs = [x for x in self.server_sound_encoders if x in self.speaker_codecs]
    16721665        ordered_codecs = [x for x in CODEC_ORDER if x in matching_codecs]
    16731666        if len(ordered_codecs)==0:
  • xpra/scripts/main.py

     
    674674                        h.append(" * %-16s: %s" % (k,v))
    675675                raise InitInfo("known logging filters: \n%s" % "\n".join(h))
    676676    if options.sound_source=="help":
    677         from xpra.sound.gstreamer_util import NAME_TO_INFO_PLUGIN
     677        from xpra.sound.sound_util import NAME_TO_INFO_PLUGIN
    678678        try:
    679             from xpra.sound.wrapper import query_sound_sources
    680             source_plugins = query_sound_sources()
     679            from xpra.sound.wrapper import query_sound
     680            source_plugins = query_sound().get("sources", [])
    681681        except Exception as e:
    682682            raise InitInfo(e)
    683683            source_plugins = []
     
    757757    print("")
    758758
    759759def show_sound_codec_help(is_server, speaker_codecs, microphone_codecs):
    760     from xpra.sound.gstreamer_util import has_gst
    761     from xpra.sound.wrapper import get_sound_codecs
    762     if not has_gst:
     760    from xpra.sound.wrapper import query_sound
     761    props = query_sound()
     762    if not props:
    763763        return "sound is not supported - gstreamer not present or not accessible"
    764764    info = []
    765     all_speaker_codecs = get_sound_codecs(True, is_server)
     765    all_speaker_codecs = props.get("decoders")
    766766    invalid_sc = [x for x in speaker_codecs if x not in all_speaker_codecs]
    767767    hs = "help" in speaker_codecs
    768768    if hs:
     
    774774    elif len(speaker_codecs)==0:
    775775        speaker_codecs += all_speaker_codecs
    776776
    777     all_microphone_codecs = get_sound_codecs(True, is_server)
     777    all_microphone_codecs = props.get("decoders")
    778778    invalid_mc = [x for x in microphone_codecs if x not in all_microphone_codecs]
    779779    hm = "help" in microphone_codecs
    780780    if hm:
  • xpra/server/server_base.py

     
    3434    SERVER_EXIT, SERVER_ERROR, SERVER_SHUTDOWN, DETACH_REQUEST, NEW_CLIENT, DONE, IDLE_TIMEOUT
    3535from xpra.net.bytestreams import set_socket_timeout
    3636from xpra.platform import get_username
     37from xpra.platform.paths import get_icon_filename
    3738from xpra.child_reaper import reaper_cleanup
    3839from xpra.scripts.config import python_platform, parse_bool_or_int
    3940from xpra.scripts.main import sound_option
     
    392393
    393394    def init_sound_options(self, sound_source_plugin, speaker, speaker_codec, microphone, microphone_codec):
    394395        try:
    395             from xpra.sound.gstreamer_util import has_gst
    396             from xpra.sound.wrapper import get_sound_codecs
     396            from xpra.sound.wrapper import query_sound
     397            props = query_sound()
    397398        except Exception as e:
    398             log("cannot load gstreamer: %s", e)
    399             has_gst = False
    400         log("init_sound_options%s has_gst=%s", (sound_source_plugin, speaker, speaker_codec, microphone, microphone_codec), has_gst)
     399            log("cannot load sound support: %s", e)
     400            props = {}
     401        log("init_sound_options%s properties=%s", (sound_source_plugin, speaker, speaker_codec, microphone, microphone_codec), props)
    401402        self.sound_source_plugin = sound_source_plugin
    402         self.supports_speaker = sound_option(speaker) in ("on", "off") and has_gst
    403         self.supports_microphone = sound_option(microphone) in ("on", "off") and has_gst
     403        self.supports_speaker = sound_option(speaker) in ("on", "off") and bool(props)
     404        self.supports_microphone = sound_option(microphone) in ("on", "off") and bool(props)
    404405        self.speaker_codecs = speaker_codec
    405406        if len(self.speaker_codecs)==0 and self.supports_speaker:
    406             self.speaker_codecs = get_sound_codecs(True, True)
     407            self.speaker_codecs = props.get("encoders")
    407408            self.supports_speaker = len(self.speaker_codecs)>0
    408409        self.microphone_codecs = microphone_codec
    409410        if len(self.microphone_codecs)==0 and self.supports_microphone:
    410             self.microphone_codecs = get_sound_codecs(False, False)
     411            self.microphone_codecs = props.get("decoders")
    411412            self.supports_microphone = len(self.microphone_codecs)>0
    412413        try:
    413             from xpra.platform.paths import get_icon_filename
    414414            from xpra.sound.pulseaudio_util import set_icon_path
    415415            set_icon_path(get_icon_filename("xpra.png"))
    416416        except Exception as e:
  • xpra/server/source.py

     
    800800            soundlog.warn("not starting sound as we are suspended")
    801801            return
    802802        try:
    803             from xpra.sound.gstreamer_util import ALLOW_SOUND_LOOP
     803            from xpra.sound.sound_util import ALLOW_SOUND_LOOP
    804804            from xpra.sound.wrapper import start_sending_sound
    805805            if self.machine_id and self.machine_id==get_machine_id() and not ALLOW_SOUND_LOOP:
    806806                #looks like we're on the same machine, verify it's a different user:
     
    990990            cinfo = ""
    991991            if ss:
    992992                try:
    993                     from xpra.sound.gstreamer_util import ENCODER_LATENCY
     993                    from xpra.sound.sound_util import ENCODER_LATENCY
    994994                    encoder_latency = ENCODER_LATENCY.get(ss.codec, 0)
    995995                    cinfo = "%s " % ss.codec
    996996                except Exception as e:
     
    11691169        if self.wants_sound:
    11701170            sound_caps = {}
    11711171            try:
    1172                 from xpra.sound.gstreamer_util import get_info as get_gst_info
     1172                #from xpra.sound.gstreamer_util import get_info as get_gst_info
     1173                FIXME:
    11731174                sound_caps.update(get_gst_info(receive=self.supports_microphone, send=self.supports_speaker,
    11741175                                 receive_codecs=self.speaker_codecs, send_codecs=self.microphone_codecs))
    11751176            except ImportError:
  • xpra/sound/gstreamer_util.py

     
    77import sys
    88import os
    99
     10from xpra.sound.sound_util import CODEC_ORDER, VORBIS, OPUS, FLAC, MP3, WAV, WAVPACK, SPEEX
    1011from xpra.log import Logger
    1112log = Logger("sound")
    1213
     
    2728    return queue_time
    2829
    2930
    30 ALLOW_SOUND_LOOP = os.environ.get("XPRA_ALLOW_SOUND_LOOP", "0")=="1"
    3131GSTREAMER1 = os.environ.get("XPRA_GSTREAMER1", "0")=="1"
    3232MONITOR_DEVICE_NAME = os.environ.get("XPRA_MONITOR_DEVICE_NAME", "")
    3333def force_enabled(codec_name):
     
    5151    "pulsesrc"      : "Pulseaudio",
    5252    "jacksrc"       : "JACK Audio Connection Kit",
    5353    }
    54 NAME_TO_INFO_PLUGIN = {
    55     "auto"          : "Wrapper audio source for automatically detected audio source",
    56     "alsa"          : "Read from a sound card via ALSA",
    57     "oss"           : "Capture from a sound card via OSS",
    58     "oss4"          : "Capture from a sound card via OSS version 4",
    59     "jack"          : "Captures audio from a JACK server",
    60     "osx"           : "Input from a sound card in OS X",
    61     "test"          : "Creates audio test signals of given frequency and volume",
    62     "pulse"         : "Captures audio from a PulseAudio server",
    63     "direct"        : "directsoundsrc",
    64     }
    6554
    6655
    67 VORBIS = "vorbis"
    68 AAC = "aac"
    69 FLAC = "flac"
    70 MP3 = "mp3"
    71 WAV = "wav"
    72 OPUS = "opus"
    73 SPEEX = "speex"
    74 WAVPACK = "wavpack"
    75 
    7656#format: encoder, container-formatter, decoder, container-parser
    7757#we keep multiple options here for the same encoding
    7858#and will populate the ones that are actually available into the "CODECS" dict
     
    9676OGG = "ogg"
    9777MUX_OPTIONS = [
    9878               (GDP,    "gdppay",   "gdpdepay"),
    99                (OGG,    "oggmux"    "oggdemux")
     79               (OGG,    "oggmux",   "oggdemux"),
    10080              ]
    10181
    10282#these encoders require an "audioconvert" element:
     
    121101                               },
    122102           }
    123103
    124 #based on the encoder options above:
    125 ENCODER_LATENCY = {
    126         MP3         : 250,
    127         FLAC        : 50,
    128         WAV         : 0,
    129         WAVPACK     : 600,
    130         OPUS        : 0,
    131         SPEEX       : 0,
    132        }
    133104
    134 CODEC_ORDER = [VORBIS, OPUS, FLAC, MP3, WAV, WAVPACK, SPEEX]    #AAC is untested
    135 
    136 
    137105gst = None
    138106has_gst = False
    139107
  • xpra/sound/sound_util.py

     
     1#!/usr/bin/env python
     2# This file is part of Xpra.
     3# Copyright (C) 2010-2015 Antoine Martin <antoine@devloop.org.uk>
     4# Xpra is released under the terms of the GNU GPL v2, or, at your option, any
     5# later version. See the file COPYING for details.
     6
     7import os
     8
     9ALLOW_SOUND_LOOP = os.environ.get("XPRA_ALLOW_SOUND_LOOP", "0")=="1"
     10
     11VORBIS = "vorbis"
     12AAC = "aac"
     13FLAC = "flac"
     14MP3 = "mp3"
     15WAV = "wav"
     16OPUS = "opus"
     17SPEEX = "speex"
     18WAVPACK = "wavpack"
     19
     20CODEC_ORDER = [VORBIS, OPUS, FLAC, MP3, WAV, WAVPACK, SPEEX]    #AAC is untested
     21
     22NAME_TO_INFO_PLUGIN = {
     23    "auto"          : "Wrapper audio source for automatically detected audio source",
     24    "alsa"          : "Read from a sound card via ALSA",
     25    "oss"           : "Capture from a sound card via OSS",
     26    "oss4"          : "Capture from a sound card via OSS version 4",
     27    "jack"          : "Captures audio from a JACK server",
     28    "osx"           : "Input from a sound card in OS X",
     29    "test"          : "Creates audio test signals of given frequency and volume",
     30    "pulse"         : "Captures audio from a PulseAudio server",
     31    "direct"        : "directsoundsrc",
     32    }
     33
     34#based on the encoder options defined in gstreamer util..
     35ENCODER_LATENCY = {
     36        MP3         : 250,
     37        FLAC        : 50,
     38        WAV         : 0,
     39        WAVPACK     : 600,
     40        OPUS        : 0,
     41        SPEEX       : 0,
     42       }
  • xpra/sound/wrapper.py

    Property changes on: xpra/sound/sound_util.py
    ___________________________________________________________________
    Added: svn:executable
    ## -0,0 +1 ##
    +*
    \ No newline at end of property
     
    55
    66import os
    77import time
     8import sys
    89
    910from xpra.net.subprocess_wrapper import subprocess_caller, subprocess_callee, glib, exec_kwargs, exec_env
    1011from xpra.platform.paths import get_sound_command
    1112from xpra.util import AdHocStruct
    12 from xpra.scripts.config import InitExit
     13from xpra.scripts.config import InitExit, InitException
    1314from xpra.log import Logger
    1415log = Logger("sound")
    1516
     
    110111        subproc = sound_play
    111112        info = "play"
    112113    elif mode=="_sound_query":
    113         if len(args)!=1:
    114             raise Exception("invalid number of arguments for sound query: %s (one subcommand required)" % len(args))
    115         subcommand = args[0]
    116         from xpra.sound.gstreamer_util import get_available_source_plugins, can_decode, can_encode
    117         if subcommand=="encoders":
    118             v = can_encode()
    119         elif subcommand=="decoders":
    120             v = can_decode()
    121         elif subcommand=="sources":
    122             v = get_available_source_plugins()
    123         else:
    124             raise Exception("invalid subcommand: %s" % subcommand)
    125         print("%s=%s" % (subcommand, ",".join(v)))
     114        from xpra.sound.gstreamer_util import get_available_source_plugins, can_decode, can_encode, get_muxers, get_demuxers, \
     115                            gst_version, pygst_version, get_all_plugin_names
     116        d = {"encoders"         : can_encode(),
     117             "decoders"         : can_decode(),
     118             "sources"          : get_available_source_plugins(),
     119             "muxers"           : get_muxers(),
     120             "demuxers"         : get_demuxers(),
     121             "gst.version"      : gst_version,
     122             "pygst.version"    : pygst_version,
     123             "plugins"          : get_all_plugin_names(),
     124            }
     125        for k,v in d.items():
     126            print("%s=%s" % (k, ",".join(v)))
    126127        return 0
    127128    else:
    128129        log.error("unknown mode: %s" % mode)
     
    151152        return 0
    152153    except InitExit as e:
    153154        log.error("%s: %s", info, e)
     155        return e.status
     156    except InitException as e:
     157        log.error("%s: %s", info, e)
    154158        return 1
    155159    except Exception:
    156160        log.error("run_sound%s error", (mode, error_cb, options, args), exc_info=True)
     
    324328        log.error("failed to start sound sink", exc_info=True)
    325329        return None
    326330
    327 def query_sound(subcommand):
    328     import sys
     331def query_sound():
    329332    import subprocess
    330     command = get_sound_command()+["_sound_query", subcommand]
     333    command = get_sound_command()+["_sound_query"]
    331334    _add_debug_args(command)
    332335    kwargs = exec_kwargs()
    333336    env = exec_env()
    334     log("query_sound(%s) command=%s, env=%s, kwargs=%s", subcommand, command, env, kwargs)
     337    log("query_sound() command=%s, env=%s, kwargs=%s", command, env, kwargs)
    335338    proc = subprocess.Popen(command, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=sys.stderr.fileno(), env=env, **kwargs)
    336339    out, err = proc.communicate(None)
    337     log("query_sound(%s) process returned %s", subcommand, proc.returncode)
    338     log("query_sound(%s) out=%s, err=%s", subcommand, out, err)
     340    log("query_sound() process returned %s", proc.returncode)
     341    log("query_sound() out=%s, err=%s", out, err)
    339342    if proc.returncode!=0:
    340         return []
    341     mline = "%s=" % subcommand      #ie: "decoders="
     343        return {}
     344    d = {}
    342345    for x in out.decode("utf8").splitlines():
    343         if x.startswith(mline):
    344             return x[len(mline):].split(",")
    345     return []
    346 
    347 def query_sound_sources():
    348     return query_sound("sources")
    349 
    350 def query_sound_encoders():
    351     return query_sound("encoders")
    352 
    353 def query_sound_decoders():
    354     return query_sound("decoders")
    355 
    356 def query_sound_muxers():
    357     return query_sound("muxers")
    358 
    359 def query_sound_demuxers():
    360     return query_sound("demuxers")
    361 
    362 
    363 def get_sound_codecs(is_speaker, is_server):
    364     from xpra.sound.gstreamer_util import has_gst
    365     if not has_gst:
    366         return []
    367     try:
    368         if (is_server and is_speaker) or (not is_server and not is_speaker):
    369             return query_sound_encoders()
    370         else:
    371             return query_sound_decoders()
    372     except Exception as e:
    373         log.warn("failed to get list of codecs: %s" % e)
    374         return []
     346        kv = x.split("=", 1)
     347        if len(kv)==2:
     348            #ie: kv = ["decoders", "mp3,vorbis"]
     349            d[kv[0]] = kv[1].split(",")     #d["decoders"] = ["mp3", "vorbis"]
     350    return d