コード例 #1
0
def osexpand(s, actual_username="", uid=0, gid=0, subs=None):
    def expanduser(s):
        if actual_username and s.startswith("~/"):
            #replace "~/" with "~$actual_username/"
            return os.path.expanduser("~%s/%s" % (actual_username, s[2:]))
        return os.path.expanduser(s)

    d = dict(subs or {})
    d.update({
        "PID": os.getpid(),
        "HOME": expanduser("~/"),
    })
    if os.name == "posix":
        d.update({
            "UID": uid or os.geteuid(),
            "GID": gid or os.getegid(),
        })
        if not OSX:
            from xpra.platform.xposix.paths import get_runtime_dir
            d["XDG_RUNTIME_DIR"] = os.environ.get("XDG_RUNTIME_DIR",
                                                  get_runtime_dir())
    if actual_username:
        d["USERNAME"] = actual_username
        d["USER"] = actual_username
    #first, expand the substitutions themselves,
    #as they may contain references to other variables:
    ssub = {}
    for k, v in d.items():
        ssub[k] = expanduser(shellsub(str(v), d))
    return os.path.expandvars(expanduser(shellsub(expanduser(s), ssub)))
コード例 #2
0
ファイル: audio_server.py プロジェクト: rudresh2319/Xpra
    def init_pulseaudio(self):
        soundlog("init_pulseaudio() pulseaudio=%s, pulseaudio_command=%s",
                 self.pulseaudio, self.pulseaudio_command)
        if self.pulseaudio is False:
            return
        if not self.pulseaudio_command:
            soundlog.warn("Warning: pulseaudio command is not defined")
            return
        #environment initialization:
        # 1) make sure that the sound subprocess will use the devices
        #    we define in the pulseaudio command
        #    (it is too difficult to parse the pulseaudio_command,
        #    so we just hope that it matches this):
        #    Note: speaker is the source and microphone the sink,
        #    because things are reversed on the server.
        os.environ.update({
            "XPRA_PULSE_SOURCE_DEVICE_NAME": "Xpra-Speaker",
            "XPRA_PULSE_SINK_DEVICE_NAME": "Xpra-Microphone",
        })
        # 2) whitelist the env vars that pulseaudio may use:
        PA_ENV_WHITELIST = (
            "DBUS_SESSION_BUS_ADDRESS",
            "DBUS_SESSION_BUS_PID",
            "DBUS_SESSION_BUS_WINDOWID",
            "DISPLAY",
            "HOME",
            "HOSTNAME",
            "LANG",
            "PATH",
            "PWD",
            "SHELL",
            "XAUTHORITY",
            "XDG_CURRENT_DESKTOP",
            "XDG_SESSION_TYPE",
            "XPRA_PULSE_SOURCE_DEVICE_NAME",
            "XPRA_PULSE_SINK_DEVICE_NAME",
        )
        env = dict((k, v) for k, v in self.get_child_env().items()
                   if k in PA_ENV_WHITELIST)
        # 3) use a private pulseaudio server, so each xpra
        #    session can have its own server,
        #    create a directory for each display:
        if PRIVATE_PULSEAUDIO and POSIX and not OSX:
            from xpra.platform.xposix.paths import _get_xpra_runtime_dir, get_runtime_dir
            rd = osexpand(get_runtime_dir())
            if not os.path.exists(rd) or not os.path.isdir(rd):
                log.warn("Warning: the runtime directory '%s' does not exist,")
                log.warn(" cannot start a private pulseaudio server")
            else:
                xpra_rd = _get_xpra_runtime_dir()
                assert xpra_rd, "bug: no xpra runtime dir"
                display = os.environ.get("DISPLAY")
                self.pulseaudio_private_dir = osexpand(
                    os.path.join(xpra_rd, "pulse-%s" % display))
                if not os.path.exists(self.pulseaudio_private_dir):
                    os.mkdir(self.pulseaudio_private_dir, 0o700)
                env["XDG_RUNTIME_DIR"] = self.pulseaudio_private_dir
                self.pulseaudio_private_socket = os.path.join(
                    self.pulseaudio_private_dir, "pulse", "native")
                os.environ[
                    "XPRA_PULSE_SERVER"] = self.pulseaudio_private_socket
        import shlex
        cmd = shlex.split(self.pulseaudio_command)
        cmd = list(osexpand(x) for x in cmd)
        #find the absolute path to the command:
        pa_cmd = cmd[0]
        if not os.path.isabs(pa_cmd):
            pa_path = None
            for x in os.environ.get("PATH", "").split(os.path.pathsep):
                t = os.path.join(x, pa_cmd)
                if os.path.exists(t):
                    pa_path = t
                    break
            if not pa_path:
                msg = "pulseaudio not started: '%s' command not found" % pa_cmd
                if self.pulseaudio is None:
                    soundlog.info(msg)
                else:
                    soundlog.warn(msg)
                return
            cmd[0] = pa_cmd
        started_at = monotonic_time()

        def pulseaudio_warning():
            soundlog.warn(
                "Warning: pulseaudio has terminated shortly after startup.")
            soundlog.warn(
                " pulseaudio is limited to a single instance per user account,"
            )
            soundlog.warn(" and one may be running already for user '%s'.",
                          get_username())
            soundlog.warn(
                " To avoid this warning, either fix the pulseaudio command line"
            )
            soundlog.warn(" or use the 'pulseaudio=no' option.")

        def pulseaudio_ended(proc):
            soundlog(
                "pulseaudio_ended(%s) pulseaudio_proc=%s, returncode=%s, closing=%s",
                proc, self.pulseaudio_proc, proc.returncode, self._closing)
            if self.pulseaudio_proc is None or self._closing:
                #cleared by cleanup already, ignore
                return
            elapsed = monotonic_time() - started_at
            if elapsed < 2:
                self.timeout_add(1000, pulseaudio_warning)
            else:
                soundlog.warn(
                    "Warning: the pulseaudio server process has terminated after %i seconds",
                    int(elapsed))
            self.pulseaudio_proc = None

        import subprocess
        try:
            soundlog("pulseaudio cmd=%s", " ".join(cmd))
            soundlog("pulseaudio env=%s", env)
            self.pulseaudio_proc = subprocess.Popen(cmd,
                                                    stdin=None,
                                                    env=env,
                                                    shell=False,
                                                    close_fds=True)
        except Exception as e:
            soundlog("Popen(%s)", cmd, exc_info=True)
            soundlog.error("Error: failed to start pulseaudio:")
            soundlog.error(" %s", e)
            return
        self.add_process(self.pulseaudio_proc,
                         "pulseaudio",
                         cmd,
                         ignore=True,
                         callback=pulseaudio_ended)
        if self.pulseaudio_proc:
            soundlog.info("pulseaudio server started with pid %s",
                          self.pulseaudio_proc.pid)
            if self.pulseaudio_private_socket:
                soundlog.info(" private server socket path:")
                soundlog.info(" '%s'", self.pulseaudio_private_socket)
                os.environ[
                    "PULSE_SERVER"] = "unix:%s" % self.pulseaudio_private_socket

            def configure_pulse():
                p = self.pulseaudio_proc
                if p is None or p.poll() is not None:
                    return
                for i, x in enumerate(self.pulseaudio_configure_commands):
                    proc = subprocess.Popen(x,
                                            stdin=None,
                                            env=env,
                                            shell=True,
                                            close_fds=True)
                    self.add_process(proc,
                                     "pulseaudio-configure-command-%i" % i,
                                     x,
                                     ignore=True)

            self.timeout_add(2 * 1000, configure_pulse)