def get_pulse_defaults(device_name_match=None, want_monitor_device=True, input_or_output=None, remote=None, env_device_name=None): try: device = get_pulse_device(device_name_match, want_monitor_device, input_or_output, remote, env_device_name) except Exception as e: log.warn( "Warning: failed to identify the pulseaudio default device to use") log.warn(" %s", e) return {} if not device: return {} #make sure it is not muted: try: from xpra.sound.pulseaudio.pulseaudio_util import has_pa, set_source_mute, set_sink_mute if has_pa(): if input_or_output is True or want_monitor_device: set_source_mute(device, mute=False) elif input_or_output is False: set_sink_mute(device, mute=False) except Exception as e: log("device %s may still be muted: %s", device, e) return {"device": device}
def get_pulse_defaults(device_name_match=None, want_monitor_device=True, input_or_output=None, remote=None, xpra_device_name=None): device = get_pulse_device(device_name_match, want_monitor_device, input_or_output, remote, xpra_device_name) if not device: return {} #make sure it is not muted: try: from xpra.sound.pulseaudio.pulseaudio_util import has_pa, set_source_mute, set_sink_mute if has_pa(): if input_or_output is True or want_monitor_device: set_source_mute(device, mute=False) elif input_or_output is False: set_sink_mute(device, mute=False) except Exception as e: log("device %s may still be muted: %s", device, e) return {"device" : device}
def get_default_sink(): DEFAULT_SINK = os.environ.get("XPRA_SOUND_SINK") if DEFAULT_SINK: SINKS = get_sink_plugins() if DEFAULT_SINK not in SINKS: log.error("invalid default sound sink: '%s' is not in %s", DEFAULT_SINK, csv(SINKS)) else: return DEFAULT_SINK try: from xpra.sound.pulseaudio.pulseaudio_util import has_pa if has_pa(): return "pulsesink" except ImportError as e: log("get_default_sink() no pulsesink: %s", e) SINKS = get_sink_plugins() return SINKS[0]
def get_sink_plugins(): SINKS = [] if sys.platform.startswith("darwin"): SINKS.append("osxaudiosink") elif sys.platform.startswith("win"): SINKS.append("directsoundsink") SINKS.append("autoaudiosink") try: from xpra.sound.pulseaudio.pulseaudio_util import has_pa if has_pa(): SINKS.append("pulsesink") except ImportError as e: log("get_sink_plugins() no pulsesink: %s", e) if os.name == "posix": SINKS += ["alsasink", "osssink", "oss4sink", "jackaudiosink"] return SINKS
def get_sink_plugins(): SINKS = [] if sys.platform.startswith("darwin"): SINKS.append("osxaudiosink") elif sys.platform.startswith("win"): SINKS.append("directsoundsink") SINKS.append("autoaudiosink") try: from xpra.sound.pulseaudio.pulseaudio_util import has_pa if has_pa(): SINKS.append("pulsesink") except ImportError as e: log("get_sink_plugins() no pulsesink: %s", e) if os.name=="posix": SINKS += ["alsasink", "osssink", "oss4sink", "jackaudiosink"] return SINKS
def get_sink_plugins(): SINKS = [] if OSX: SINKS.append("osxaudiosink") elif WIN32: SINKS.append("directsoundsink") SINKS.append("wasapisink") SINKS.append("autoaudiosink") try: from xpra.sound.pulseaudio.pulseaudio_util import has_pa if has_pa(): SINKS.append("pulsesink") except ImportError as e: log("get_sink_plugins() no pulsesink: %s", e) if POSIX: SINKS += ["alsasink", "osssink", "oss4sink", "jackaudiosink"] return SINKS
def get_default_sink(): sink = os.environ.get("XPRA_SOUND_SINK") sinks = get_sink_plugins() if sink: if sink not in sinks: log.error("invalid default sound sink: '%s' is not in %s", sink, csv(sinks)) else: return sink try: from xpra.sound.pulseaudio.pulseaudio_util import has_pa, get_pactl_server if has_pa(): s = get_pactl_server() if not s: log("cannot connect to pulseaudio server?") else: return "pulsesink" except ImportError as e: log("get_default_sink() no pulsesink: %s", e) return sinks[0]
def get_source_plugins(): sources = [] try: from xpra.sound.pulseaudio.pulseaudio_util import has_pa #we have to put pulsesrc first if pulseaudio is installed #because using autoaudiosource does not work properly for us: #it may still choose pulse, but without choosing the right device. if has_pa(): sources.append("pulsesrc") except ImportError as e: log("get_source_plugins() no pulsesrc: %s", e) if OSX: sources.append("osxaudiosrc") elif WIN32: sources.append("directsoundsrc") sources.append("autoaudiosrc") if os.name == "posix": sources += ["alsasrc", "osssrc", "oss4src", "jackaudiosrc"] sources.append("audiotestsrc") return sources
def get_source_plugins(): sources = [] try: from xpra.sound.pulseaudio.pulseaudio_util import has_pa #we have to put pulsesrc first if pulseaudio is installed #because using autoaudiosource does not work properly for us: #it may still choose pulse, but without choosing the right device. if has_pa(): sources.append("pulsesrc") except ImportError as e: log("get_source_plugins() no pulsesrc: %s", e) if OSX: sources.append("osxaudiosrc") elif WIN32: sources.append("directsoundsrc") sources.append("autoaudiosrc") if os.name=="posix": sources += ["alsasrc", "jackaudiosrc", "osssrc", "oss4src", "osxaudiosrc", "jackaudiosrc"] sources.append("audiotestsrc") return sources
def get_default_source(): source = os.environ.get("XPRA_SOUND_SRC") sources = get_source_plugins() if source: if source not in sources: log.error("invalid default sound source: '%s' is not in %s", source, csv(sources)) else: return source try: from xpra.sound.pulseaudio.pulseaudio_util import has_pa, get_pactl_server if has_pa(): s = get_pactl_server() if not s: log("cannot connect to pulseaudio server?") else: return "pulsesrc" except ImportError as e: log("get_default_source() no pulsesrc: %s", e) for source in sources: if has_plugins(source): return source return None
def get_pulse_device(device_name_match=None, want_monitor_device=True, input_or_output=None, remote=None, env_device_name=None): """ choose the device to use """ log("get_pulse_device%s", (device_name_match, want_monitor_device, input_or_output, remote, env_device_name)) try: from xpra.sound.pulseaudio.pulseaudio_util import ( has_pa, get_pa_device_options, get_default_sink, get_pactl_server, get_pulse_id, ) if not has_pa(): log.warn("Warning: pulseaudio is not available!") return None except ImportError as e: log.warn("Warning: pulseaudio is not available!") log.warn(" %s", e) return None pa_server = get_pactl_server() log("get_pactl_server()=%s", pa_server) if remote: log("start sound, remote pulseaudio server=%s, local pulseaudio server=%s", remote.pulseaudio_server, pa_server) #only worth comparing if we have a real server string #one that starts with {UUID}unix:/.. if pa_server and pa_server.startswith("{") and \ remote.pulseaudio_server and remote.pulseaudio_server==pa_server: log.error("Error: sound is disabled to prevent a sound loop") log.error(" identical Pulseaudio server '%s'", pa_server) return None pa_id = get_pulse_id() log("start sound, client id=%s, server id=%s", remote.pulseaudio_id, pa_id) if remote.pulseaudio_id and remote.pulseaudio_id==pa_id: log.error("Error: sound is disabled to prevent a sound loop") log.error(" identical Pulseaudio ID '%s'", pa_id) return None device_type_str = "" if input_or_output is not None: device_type_str = "input" if input_or_output else "output" if want_monitor_device: device_type_str += " monitor" #def get_pa_device_options(monitors=False, input_or_output=None, ignored_devices=["bell-window-system"]) devices = get_pa_device_options(want_monitor_device, input_or_output) log("found %i pulseaudio %s device%s: %s", len(devices), device_type_str, engs(devices), devices) ignore = () if input_or_output is True: ignore = IGNORED_INPUT_DEVICES elif input_or_output is False: ignore = IGNORED_OUTPUT_DEVICES else: ignore = IGNORED_INPUT_DEVICES+IGNORED_OUTPUT_DEVICES if ignore and devices: #filter out the ignore list: filtered = {} for k,v in devices.items(): kl = bytestostr(k).strip().lower() vl = bytestostr(v).strip().lower() if kl not in ignore and vl not in ignore: filtered[k] = v devices = filtered if not devices: log.error("Error: sound forwarding is disabled") log.error(" could not detect any Pulseaudio %s devices", device_type_str) return None env_device = None if env_device_name: env_device = os.environ.get(env_device_name) #try to match one of the devices using the device name filters: if len(devices)>1: filters = [] matches = [] for match in (device_name_match, env_device): if not match: continue if match!=env_device: filters.append(match) match = match.lower() log("trying to match '%s' in devices=%s", match, devices) matches = dict((k,v) for k,v in devices.items() if (bytestostr(k).strip().lower().find(match)>=0 or bytestostr(v).strip().lower().find(match)>=0)) #log("matches(%s, %s)=%s", devices, match, matches) if len(matches)==1: log("found name match for '%s': %s", match, tuple(matches.items())[0]) break elif len(matches)>1: log.warn("Warning: Pulseaudio %s device name filter '%s'", device_type_str, match) log.warn(" matched %i devices", len(matches)) if filters or matches: if not matches: log.warn("Warning: Pulseaudio %s device name filter%s:", device_type_str, engs(filters)) log.warn(" %s", csv("'%s'" % x for x in filters)) log.warn(" did not match any of the devices found:") for k,v in devices.items(): log.warn(" * '%s'", k) log.warn(" '%s'", v) return None devices = matches #still have too many devices to choose from? if len(devices)>1: if want_monitor_device: #use the monitor of the default sink if we find it: default_sink = get_default_sink() default_monitor = default_sink+".monitor" if default_monitor in devices: device_name = devices.get(default_monitor) log.info("using monitor of default sink: %s", device_name) return default_monitor global WARNED_MULTIPLE_DEVICES if not WARNED_MULTIPLE_DEVICES: WARNED_MULTIPLE_DEVICES = True dtype = "audio" if want_monitor_device: dtype = "output monitor" elif input_or_output is False: dtype = "audio output" elif input_or_output is True: dtype = "audio input" log.info("found %i %s devices:", len(devices), dtype) for k,v in devices.items(): log.info(" * %s", bytestostr(v)) log.info(" %s", bytestostr(k)) if not env_device: #used already! log.info(" to select a specific one,") log.info(" use the environment variable '%s'", env_device_name) #default to first one: if USE_DEFAULT_DEVICE: log.info("using default pulseaudio device") return None #default to first one: device, device_name = tuple(devices.items())[0] log.info("using pulseaudio device:") log.info(" '%s'", bytestostr(device_name)) return device
def get_pulse_device(device_name_match=None, want_monitor_device=True, input_or_output=None, remote=None, xpra_device_name=None): """ choose the device to use """ try: from xpra.sound.pulseaudio.pulseaudio_util import has_pa, get_pa_device_options, get_default_sink, get_pulse_server, get_pulse_id if not has_pa(): log.warn("Warning: pulseaudio is not available!") return None except ImportError as e: log.warn("Warning: pulseaudio is not available!") log.warn(" %s", e) return None pa_server = get_pulse_server() if remote: log("start sound, remote pulseaudio server=%s, local pulseaudio server=%s", remote.pulseaudio_server, pa_server) #only worth comparing if we have a real server string #one that starts with {UUID}unix:/.. if pa_server and pa_server.startswith("{") and \ remote.pulseaudio_server and remote.pulseaudio_server==pa_server: log.error("Error: sound is disabled to prevent a sound loop") log.error(" identical Pulseaudio server '%s'", pa_server) return None pa_id = get_pulse_id() log("start sound, client id=%s, server id=%s", remote.pulseaudio_id, pa_id) if remote.pulseaudio_id and remote.pulseaudio_id==pa_id: log.error("Error: sound is disabled to prevent a sound loop") log.error(" identical Pulseaudio ID '%s'", pa_id) return None device_type_str = "" if input_or_output is not None: device_type_str = ["output", "input"][input_or_output] if want_monitor_device: device_type_str += " monitor" #def get_pa_device_options(monitors=False, input_or_output=None, ignored_devices=["bell-window-system"], log_errors=True) devices = get_pa_device_options(want_monitor_device, input_or_output) log("found %i pulseaudio %s device%s: %s", len(devices), device_type_str, engs(devices), devices) if len(devices)==0: log.error("Error: sound forwarding is disabled") log.error(" could not detect any Pulseaudio %s devices", device_type_str) return None #try to match one of the devices using the device name filters: if len(devices)>1: filters = [] matches = [] for match in (device_name_match, PULSEAUDIO_DEVICE_NAME, xpra_device_name): if not match: continue if match!=xpra_device_name: filters.append(match) match = match.lower() matches = dict((k,v) for k,v in devices.items() if k.lower().find(match)>=0 or v.lower().find(match)>=0) #log("matches(%s, %s)=%s", devices, match, matches) if len(matches)==1: log("found name match for '%s': %s", match, matches.items()[0]) break elif len(matches)>1: log.warn("Warning: Pulseaudio %s device name filter '%s'", device_type_str, match) log.warn(" matched %i devices", len(matches)) if filters or len(matches)>0: if len(matches)==0: log.warn("Warning: Pulseaudio %s device name filter%s:", device_type_str, engs(filters)) log.warn(" %s", csv("'%s'" % x for x in filters)) log.warn(" did not match any of the devices found:") for k,v in devices.items(): log.warn(" * '%s'", k) log.warn(" '%s'", v) return None devices = matches #still have too many devices to choose from? if len(devices)>1: if want_monitor_device: #use the monitor of the default sink if we find it: default_sink = get_default_sink() default_monitor = default_sink+".monitor" if default_monitor in devices: device_name = devices.get(default_monitor) log.info("using monitor of default sink: %s", device_name) return default_monitor global WARNED_MULTIPLE_DEVICES if not WARNED_MULTIPLE_DEVICES: WARNED_MULTIPLE_DEVICES = True if not PULSEAUDIO_DEVICE_NAME: #warned already dtype = "audio" if want_monitor_device: dtype = "output monitor" elif input_or_output is False: dtype = "audio input" elif input_or_output is True: dtype = "audio output" log.warn("Warning: found %i %s devices:", len(devices), dtype) for k,v in devices.items(): log.warn(" * %s", v) log.warn(" %s", k) if not PULSEAUDIO_DEVICE_NAME: #used already! log.warn(" to select a specific one,") log.warn(" use the environment variable XPRA_PULSEAUDIO_DEVICE_NAME") #default to first one: if USE_DEFAULT_DEVICE: log.info("using default pulseaudio device") return None #default to first one: device, device_name = devices.items()[0] log.info("using pulseaudio device:") log.info(" '%s'", device_name) return device
def get_pulse_defaults(device_name_match=None, want_monitor_device=True, input_or_output=None, remote=None, xpra_device_name=None): """ choose the device to use """ try: from xpra.sound.pulseaudio.pulseaudio_util import has_pa, get_pa_device_options, get_default_sink from xpra.sound.pulseaudio.pulseaudio_util import get_pulse_server, get_pulse_id, set_source_mute, set_sink_mute if not has_pa(): log.warn("Warning: pulseaudio is not available!") return None except ImportError as e: log.warn("Warning: pulseaudio is not available!") log.warn(" %s", e) return None pa_server = get_pulse_server() if remote: log( "start sound, remote pulseaudio server=%s, local pulseaudio server=%s", remote.pulseaudio_server, pa_server) #only worth comparing if we have a real server string #one that starts with {UUID}unix:/.. if pa_server and pa_server.startswith("{") and \ remote.pulseaudio_server and remote.pulseaudio_server==pa_server: log.error("Error: sound is disabled to prevent a sound loop") log.error(" identical Pulseaudio server '%s'", pa_server) return None pa_id = get_pulse_id() log("start sound, client id=%s, server id=%s", remote.pulseaudio_id, pa_id) if remote.pulseaudio_id and remote.pulseaudio_id == pa_id: log.error("Error: sound is disabled to prevent a sound loop") log.error(" identical Pulseaudio ID '%s'", pa_id) return None device_type_str = "" if input_or_output is not None: device_type_str = ["output", "input"][input_or_output] if want_monitor_device: device_type_str += " monitor" #def get_pa_device_options(monitors=False, input_or_output=None, ignored_devices=["bell-window-system"], log_errors=True) devices = get_pa_device_options(want_monitor_device, input_or_output) log("found %i pulseaudio %s device%s: %s", len(devices), device_type_str, engs(devices), devices) if len(devices) == 0: log.error("Error: sound forwarding is disabled") log.error(" could not detect any Pulseaudio %s devices", device_type_str) return None if len(devices) > 1: filters = [] matches = [] for match in (device_name_match, PULSEAUDIO_DEVICE_NAME, xpra_device_name): if not match: continue if match != xpra_device_name: filters.append(match) match = match.lower() matches = dict( (k, v) for k, v in devices.items() if k.lower().find(match) >= 0 or v.lower().find(match) >= 0) #log("matches(%s, %s)=%s", devices, match, matches) if len(matches) == 1: log("found name match for '%s': %s", match, matches.items()[0]) break elif len(matches) > 1: log.warn("Warning: Pulseaudio %s device name filter '%s'", device_type_str, match) log.warn(" matched %i devices", len(matches)) if filters or len(matches) > 0: if len(matches) == 0: log.warn("Warning: Pulseaudio %s device name filter%s:", device_type_str, engs(filters)) log.warn(" %s", csv("'%s'" % x for x in filters)) log.warn(" did not match the devices found:") for k, v in devices.items(): log.warn(" * '%s'", k) log.warn(" '%s'", v) return None devices = matches #default to first one: device, device_name = devices.items()[0] if len(devices) > 1: default_sink = get_default_sink() default_monitor = default_sink + ".monitor" global WARNED_MULTIPLE_DEVICES if not WARNED_MULTIPLE_DEVICES: WARNED_MULTIPLE_DEVICES = True if not PULSEAUDIO_DEVICE_NAME: #warned already log.warn("Warning: found %i audio devices:", len(devices)) for k, v in devices.items(): log.warn(" * %s", v) log.warn(" %s", k) if not PULSEAUDIO_DEVICE_NAME: #used already! log.warn(" to select a specific one,") log.warn( " use the environment variable XPRA_PULSEAUDIO_DEVICE_NAME" ) if default_monitor in devices: device = default_monitor device_name = devices.get(default_monitor) if not WARNED_MULTIPLE_DEVICES: log.warn("using monitor of default sink: %s", device_name) else: if not WARNED_MULTIPLE_DEVICES: log.warn("using the first device") log.info("using pulseaudio device:") log.info(" '%s'", device_name) #make sure it is not muted: if input_or_output is True or want_monitor_device: set_source_mute(device, mute=False) elif input_or_output is False: set_sink_mute(device, mute=False) return {"device": device}