Exemplo n.º 1
0
def get_xauthority_path(display_name, username, uid, gid):
    assert POSIX

    def pathexpand(s):
        return osexpand(s, actual_username=username, uid=uid, gid=gid)

    from xpra.platform.xposix.paths import _get_xpra_runtime_dir
    if PRIVATE_XAUTH:
        d = _get_xpra_runtime_dir()
        if XAUTH_PER_DISPLAY:
            filename = "Xauthority-%s" % display_name.lstrip(":")
        else:
            filename = "Xauthority"
    else:
        d = "~/"
        filename = ".Xauthority"
    return os.path.join(pathexpand(d), filename)
Exemplo n.º 2
0
    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)