from xpra.log import Logger log = Logger("sound") gstlog = Logger("gstreamer") glib = import_glib() SINK_SHARED_DEFAULT_ATTRIBUTES = {"sync": False, "async": True, "qos": True} SINK_DEFAULT_ATTRIBUTES = { "pulsesink": { "client-name": "Xpra" }, } QUEUE_SILENT = envbool("XPRA_QUEUE_SILENT", False) QUEUE_TIME = get_queue_time(450) UNMUTE_DELAY = envint("XPRA_UNMUTE_DELAY", 1000) GRACE_PERIOD = envint("XPRA_SOUND_GRACE_PERIOD", 2000) #percentage: from 0 for no margin, to 200% which triples the buffer target MARGIN = max(0, min(200, envint("XPRA_SOUND_MARGIN", 50))) #how high we push up the min-level to prevent underruns: UNDERRUN_MIN_LEVEL = max(0, envint("XPRA_SOUND_UNDERRUN_MIN_LEVEL", 150)) GST_FORMAT_BYTES = 2 GST_FORMAT_TIME = 3 GST_FORMAT_BUFFERS = 4 BUFFER_FORMAT = GST_FORMAT_BUFFERS GST_APP_STREAM_TYPE_STREAM = 0 STREAM_TYPE = GST_APP_STREAM_TYPE_STREAM
import time from xpra.os_util import SIGNAMES, Queue from xpra.util import csv, AtomicInteger from xpra.sound.sound_pipeline import SoundPipeline from xpra.gtk_common.gobject_util import n_arg_signal, gobject from xpra.sound.gstreamer_util import get_source_plugins, plugin_str, get_encoder_formatter, get_encoder_default_options, normv, get_codecs, get_gst_version, get_queue_time, \ MP3, CODEC_ORDER, MUXER_DEFAULT_OPTIONS, ENCODER_NEEDS_AUDIOCONVERT, SOURCE_NEEDS_AUDIOCONVERT, MS_TO_NS, GST_QUEUE_LEAK_DOWNSTREAM from xpra.scripts.config import InitExit from xpra.log import Logger log = Logger("sound") gstlog = Logger("gstreamer") APPSINK = os.environ.get("XPRA_SOURCE_APPSINK", "appsink name=sink emit-signals=true max-buffers=10 drop=true sync=false async=false qos=false") JITTER = int(os.environ.get("XPRA_SOUND_SOURCE_JITTER", "0")) SOURCE_QUEUE_TIME = get_queue_time(50, "SOURCE_") BUFFER_TIME = int(os.environ.get("XPRA_SOUND_SOURCE_BUFFER_TIME", "0")) #ie: 64 LATENCY_TIME = int(os.environ.get("XPRA_SOUND_SOURCE_LATENCY_TIME", "0")) #ie: 32 SAVE_TO_FILE = os.environ.get("XPRA_SAVE_TO_FILE") generation = AtomicInteger() class SoundSource(SoundPipeline): __gsignals__ = SoundPipeline.__generic_signals__.copy() __gsignals__.update({ "new-buffer" : n_arg_signal(2), })
DEFAULT_SINK = "directsoundsink" if os.name == "posix": SINKS += ["alsasink", "osssink", "oss4sink", "jackaudiosink"] # SINK_SHARED_DEFAULT_ATTRIBUTES = {"sync" : False, # "async" : True} SINK_SHARED_DEFAULT_ATTRIBUTES = {"sync": False, "async": True, "qos": True} SINK_DEFAULT_ATTRIBUTES = {0: {"pulsesink": {"client": "Xpra"}}, 1: {"pulsesink": {"client-name": "Xpra"}}} DEFAULT_SINK = os.environ.get("XPRA_SOUND_SINK", DEFAULT_SINK) if DEFAULT_SINK not in SINKS: log.error("invalid default sound sink: '%s' is not in %s, using %s instead", DEFAULT_SINK, SINKS, SINKS[0]) DEFAULT_SINK = SINKS[0] QUEUE_SILENT = 0 QUEUE_TIME = get_queue_time(450) QUEUE_MIN_TIME = get_queue_time(QUEUE_TIME // 10 // MS_TO_NS, "MIN") assert QUEUE_MIN_TIME <= QUEUE_TIME VARIABLE_MIN_QUEUE = os.environ.get("XPRA_VARIABLE_MIN_QUEUE", "1") == "1" GST_FORMAT_BUFFERS = 4 def sink_has_device_attribute(sink): return sink not in ("autoaudiosink", "jackaudiosink", "directsoundsink") class SoundSink(SoundPipeline):
} SINK_DEFAULT_ATTRIBUTES = {0 : { "pulsesink" : {"client" : "Xpra"} }, 1 : { "pulsesink" : {"client-name" : "Xpra"} }, } DEFAULT_SINK = os.environ.get("XPRA_SOUND_SINK", DEFAULT_SINK) if DEFAULT_SINK not in SINKS: log.error("invalid default sound sink: '%s' is not in %s, using %s instead", DEFAULT_SINK, SINKS, SINKS[0]) DEFAULT_SINK = SINKS[0] QUEUE_SILENT = 0 QUEUE_TIME = get_queue_time(450) GRACE_PERIOD = int(os.environ.get("XPRA_SOUND_GRACE_PERIOD", "2000")) #percentage: from 0 for no margin, to 200% which triples the buffer target MARGIN = max(0, min(200, int(os.environ.get("XPRA_SOUND_MARGIN", "50")))) GST_FORMAT_BUFFERS = 4 class SoundSink(SoundPipeline): __gsignals__ = SoundPipeline.__generic_signals__.copy() __gsignals__.update({ "eos" : one_arg_signal, })
from xpra.gtk_common.gobject_util import n_arg_signal, gobject from xpra.sound.gstreamer_util import get_source_plugins, plugin_str, get_encoder_elements, get_encoder_default_options, normv, get_encoders, get_gst_version, get_queue_time, \ MP3, CODEC_ORDER, MUXER_DEFAULT_OPTIONS, ENCODER_NEEDS_AUDIOCONVERT, SOURCE_NEEDS_AUDIOCONVERT, MS_TO_NS, GST_QUEUE_LEAK_DOWNSTREAM from xpra.net.compression import compressed_wrapper from xpra.scripts.config import InitExit from xpra.log import Logger log = Logger("sound") gstlog = Logger("gstreamer") APPSINK = os.environ.get( "XPRA_SOURCE_APPSINK", "appsink name=sink emit-signals=true max-buffers=10 drop=true sync=false async=false qos=false" ) JITTER = envint("XPRA_SOUND_SOURCE_JITTER", 0) SOURCE_QUEUE_TIME = get_queue_time(50, "SOURCE_") BUFFER_TIME = envint("XPRA_SOUND_SOURCE_BUFFER_TIME", 0) #ie: 64 LATENCY_TIME = envint("XPRA_SOUND_SOURCE_LATENCY_TIME", 0) #ie: 32 BUNDLE_METADATA = envbool("XPRA_SOUND_BUNDLE_METADATA", True) SAVE_TO_FILE = os.environ.get("XPRA_SAVE_TO_FILE") generation = AtomicInteger() class SoundSource(SoundPipeline): __gsignals__ = SoundPipeline.__generic_signals__.copy() __gsignals__.update({ "new-buffer": n_arg_signal(3), })
} SINK_DEFAULT_ATTRIBUTES = {0 : { "pulsesink" : {"client" : "Xpra"} }, 1 : { "pulsesink" : {"client-name" : "Xpra"} }, } DEFAULT_SINK = os.environ.get("XPRA_SOUND_SINK", DEFAULT_SINK) if DEFAULT_SINK not in SINKS: log.error("invalid default sound sink: '%s' is not in %s, using %s instead", DEFAULT_SINK, SINKS, SINKS[0]) DEFAULT_SINK = SINKS[0] QUEUE_SILENT = 0 QUEUE_TIME = get_queue_time(450) QUEUE_MIN_TIME = get_queue_time(QUEUE_TIME//10//MS_TO_NS, "MIN") assert QUEUE_MIN_TIME<=QUEUE_TIME VARIABLE_MIN_QUEUE = os.environ.get("XPRA_VARIABLE_MIN_QUEUE", "1")=="1" GST_FORMAT_BUFFERS = 4 def sink_has_device_attribute(sink): return sink not in ("autoaudiosink", "jackaudiosink", "directsoundsink") class SoundSink(SoundPipeline): __gsignals__ = SoundPipeline.__generic_signals__.copy()