xpra icon
Bug tracker and wiki

Ticket #2349: cache-sound-query.patch

File cache-sound-query.patch, 12.1 KB (added by Antoine Martin, 16 months ago)

cache sound query data

  • xpra/platform/darwin/paths.py

     
    9494    dirs.append("/etc/xpra")
    9595    return dirs
    9696
     97def do_get_system_cache_dirs():
     98    return []
     99
     100
    97101def do_get_ssh_conf_dirs():
    98102    return ["/private/etc", "/etc/ssh", "/usr/local/etc/ssh", "~/.ssh", "~/ssh"]
    99103
     
    113117    dirs.append("~/.xpra")
    114118    return dirs
    115119
     120def do_get_user_cache_dirs(uid):
     121    if uid is None:
     122        uid = os.getuid()
     123    dirs = []
     124    if uid>0:
     125        dirs.append(os.path.join("~/.cache", "xpra"))
     126    return dirs
     127
     128
    116129def do_get_default_log_dirs():
    117130    dirs = []
    118131    try:
  • xpra/platform/paths.py

     
    4545    #overriden in all platforms
    4646    return []
    4747
     48def get_system_cache_dirs():
     49    return envaslist_or_delegate("XPRA_SYSTEM_CACHE_DIRS", do_get_system_cache_dirs)
     50def do_get_system_cache_dirs():
     51    #overriden in all platforms
     52    return []
    4853
     54
    4955def get_ssh_conf_dirs():
    5056    return envaslist_or_delegate("XPRA_SSH_CONF_DIRS", do_get_ssh_conf_dirs)
    5157def do_get_ssh_conf_dirs():
     
    6268def do_get_user_conf_dirs(_uid):
    6369    return []
    6470
     71def get_user_cache_dirs(uid=None):
     72    return envaslist_or_delegate("XPRA_USER_CACHE_DIRS", do_get_user_cache_dirs, uid)
     73def do_get_user_cache_dirs(_uid):
     74    return []
     75
    6576def get_default_conf_dirs():
    6677    return envaslist_or_delegate("XPRA_DEFAULT_CONF_DIRS", do_get_default_conf_dirs)
    6778def do_get_default_conf_dirs():
     
    267278                "do_get_install_prefix",
    268279                "do_get_default_conf_dirs",
    269280                "do_get_system_conf_dirs",
     281                "do_get_system_cache_dirs",
    270282                "do_get_ssh_conf_dirs",
    271283                "do_get_ssh_known_hosts_files",
    272284                "do_get_user_conf_dirs",
     285                "do_get_user_cache_dirs",
    273286                "do_get_socket_dirs",
    274287                "do_get_default_log_dirs",
    275288                "do_get_download_dir",
     
    285298        "install"           : {"prefix" : get_install_prefix()},
    286299        "default_conf"      : {"dirs"   : get_default_conf_dirs()},
    287300        "system_conf"       : {"dirs"   : get_system_conf_dirs()},
     301        "system_cache"      : {"dirs"   : get_system_cache_dirs()},
    288302        "ssh_conf"          : {"dirs"   : get_ssh_conf_dirs()},
    289303        "user_conf"         : {"dirs"   : get_user_conf_dirs()},
     304        "user_cache"        : {"dirs"   : get_user_cache_dirs()},
    290305        "socket"            : {"dirs"   : get_socket_dirs()},
    291306        "log"               : {"dirs"   : get_default_log_dirs()},
    292307        "download"          : {"dir"    : get_download_dir()},
  • xpra/platform/win32/paths.py

     
    7474    #ie: C:\ProgramData\Xpra
    7575    return [os.path.join(get_program_data_dir(), u"Xpra")]
    7676
     77def do_get_system_cache_dirs():
     78    return []
     79
     80
    7781def do_get_ssh_conf_dirs():
    7882    from xpra.scripts.config import python_platform
    7983    if python_platform.architecture()[0]=="32bit":
     
    104108    #ie: "C:\Users\<user name>\AppData\Roaming"
    105109    return [_get_data_dir()]
    106110
     111def do_get_user_cache_dirs(_uid):
     112    return [_get_data_dir()]
    107113
     114
    108115def do_get_desktop_background_paths():
    109116    try:
    110117        try:
  • xpra/platform/xposix/paths.py

     
    111111            dirs.append(idir)
    112112    return dirs
    113113
     114def do_get_system_cache_dirs():
     115    return ["/var/cache/xpra"]
    114116
     117
    115118def do_get_user_conf_dirs(uid):
    116119    #per-user configuration location:
    117120    #(but never use /root/.xpra)
     
    123126        dirs.append("~/.xpra")
    124127    return dirs
    125128
     129def do_get_user_cache_dirs(uid):
     130    if uid is None:
     131        uid = os.getuid()
     132    dirs = []
     133    if uid>0:
     134        dirs.append(os.path.join("~/.cache", "xpra"))
     135    return dirs
    126136
     137
    127138def get_runtime_dir():
    128139    runtime_dir = os.environ.get("XDG_RUNTIME_DIR")
    129140    if runtime_dir:
  • xpra/sound/wrapper.py

     
    1414    )
    1515from xpra.net.subprocess_wrapper import subprocess_caller, subprocess_callee, exec_kwargs, exec_env
    1616from xpra.platform.paths import get_sound_command
    17 from xpra.os_util import WIN32, OSX, POSIX, BITS, monotonic_time, bytestostr
    18 from xpra.util import typedict, parse_simple_dict, envint, envbool
     17from xpra.os_util import (
     18    WIN32, OSX, POSIX, BITS,
     19    monotonic_time, bytestostr, getuid, umask_context, osexpand, pollwait,
     20    )
     21from xpra.util import typedict, parse_simple_dict, envint, envbool, repr_ellipsized
    1922from xpra.scripts.config import InitExit, InitException
    2023from xpra.log import Logger
    2124log = Logger("sound")
     
    397400        log.error("failed to start sound sink", exc_info=True)
    398401        return None
    399402
     403def get_gst_registry_time():
     404    gstreg = os.environ.get("GST_REGISTRY")
     405    if gstreg:
     406        regpaths = [gstreg]
     407    else:
     408        cache_home = os.environ.get("XDG_CACHE_HOME", osexpand("~/.cache"))
     409        import glob
     410        regpaths = glob.glob("%s/gstreamer-*/registry*.bin" % cache_home)
     411    log("query_sound() lookin for a registry file in %s", regpaths)
     412    cache_ts = 0
     413    for gstreg in regpaths:
     414        if not os.path.exists(gstreg) or not os.path.isfile(gstreg):
     415            continue
     416        try:
     417            cts = max(os.path.getctime(gstreg), os.path.getmtime(gstreg))
     418            log("ctime(%s)=%s", gstreg, cts)
     419        except (OSError, IOError):
     420            log("os.path.getctype(%s)", gstreg, exc_info=True)
     421            continue
     422        cache_ts = max(cts, cache_ts)
     423    return cache_ts
     424
    400425def query_sound():
     426    from xpra.platform.paths import get_system_cache_dirs, get_user_cache_dirs
     427    filename = "gstreamer-python%i-cache.txt" % (sys.version_info[0])
     428    data = None
    401429    if QUERY_CACHE:
    402         #first find the timestamp on the gstreamer registry file:
    403         gstreg = os.environ.get("GST_REGISTRY")
    404         if gstreg:
    405             regpaths = [gstreg]
    406         else:
    407             cache_home = os.environ.get("XDG_CACHE_HOME", os.path.expanduser("~/.cache"))
    408             import glob
    409             regpaths = glob.glob("%s/gstreamer-*/registry-*.bin" % cache_home)
    410         ts = 0
    411         for gstreg in regpaths:
    412             if not os.path.exists(gstreg) or not os.path.isfile(gstreg):
    413                 continue
    414             try:
    415                 cts = os.path.getctime(gstreg)
    416                 log("ctime(%s)=%s", gstreg, cts)
    417             except (OSError, IOError):
    418                 log("os.path.getctype(%s)", gstreg, exc_info=True)
    419                 continue
    420             ts = max(cts, ts)
    421         if ts>0:
    422             #ok we have a timestamp we can compare with,
    423             #now try to find our cache file:
    424             from xpra.platform.paths import get_system_conf_dirs
    425             dirs = get_system_conf_dirs()
    426             filename = "gstreamer-python%i-cache.txt" % (sys.version_info[0])
     430        #try to ensure that the registry is up to date:
     431        command = "gst-inspect-1.0"
     432        try:
     433            from subprocess import DEVNULL
     434        except ImportError:
     435            DEVNULL = open(os.devnull, 'wb')
     436        import subprocess
     437        log("running '%s'", command)
     438        proc = subprocess.Popen(command, stdin=DEVNULL, stdout=DEVNULL, close_fds=True, shell=True)
     439        r = pollwait(proc, 10)
     440        log("'%s' returned %s", command, r)
     441        if r==0:
     442            #first find the timestamp of the gstreamer registry file:
     443            cache_ts = get_gst_registry_time()
     444            if cache_ts>0:
     445                #ok we have a timestamp we can compare with,
     446                #now try to find our cache file:
     447                sys_dirs = get_system_cache_dirs()
     448                user_dirs = get_user_cache_dirs()
     449                dirs = sys_dirs + user_dirs
     450                cache_times = {}
     451                log("query_sound() lookin for a cache file in %s", dirs)
     452                for d in dirs:
     453                    cache = os.path.join(osexpand(d), filename)
     454                    if not os.path.exists(cache) or not os.path.isfile(cache):
     455                        continue
     456                    try:
     457                        cts = os.path.getctime(cache)
     458                    except (OSError, IOError):
     459                        continue
     460                    log("ctime(%s)=%s", cache, cts)
     461                    if cts and cts<cache_ts:
     462                        log("query_sound() cache file '%s' out of date", cache)
     463                        if getuid()==0 or d in user_dirs:
     464                            try:
     465                                os.unlink(cache)
     466                            except (OSError, IOError):
     467                                log("unlink(%s)", cache, exc_info=True)
     468                        continue
     469                    cache_times[cts] = cache
     470                #we found some valid cache files:
     471                while cache_times:
     472                    #use the latest one:
     473                    best = max(cache_times.keys())
     474                    cache = cache_times.pop(best)
     475                    try:
     476                        with open(cache, 'rb') as f:
     477                            data = f.read()
     478                            if data:
     479                                log("query_sound() using cached data from '%s'", cache)
     480                                break
     481                    except (OSError, IOError):
     482                        log("failed to read cache file '%s'", cache, exc_info=True)
     483    if not data:
     484        data = do_query_sound()
     485        if QUERY_CACHE and data:
     486            #try to save it somewhere:
     487            sys_dirs = get_system_cache_dirs()
     488            user_dirs = get_user_cache_dirs()
     489            if getuid()==0:
     490                dirs = sys_dirs + user_dirs
     491            else:
     492                dirs = user_dirs
    427493            for d in dirs:
     494                d = osexpand(d)
     495                if not os.path.exists(d):
     496                    try:
     497                        os.mkdir(d, 0o755)
     498                    except (OSError, IOError):
     499                        log("mkdir(%s)", d, exc_info=True)
     500                        continue
    428501                cache = os.path.join(d, filename)
    429                 if not os.path.exists(cache):
    430                     continue
    431                 if os.path.getctime(cache)<os.path.getctime(src_file):
    432                     log("query_sound() cache file out of date")
    433                     return "binary file out of date"
    434     v = do_query_sound()
    435     if QUERY_CACHE:
    436         pass
    437     return v
     502                try:
     503                    with umask_context(0o022):
     504                        with open(cache, 'wb') as f:
     505                            f.write(data)
     506                    log("query_sound() cached data in '%s'", cache)
     507                    break
     508                except (OSError, IOError):
     509                    log("write(%s)", cache, exc_info=True)
     510    return parse_query_sound(data)
    438511
    439512def do_query_sound():
    440513    import subprocess
     
    449522    log("query_sound() process returned %s", proc.returncode)
    450523    log("query_sound() out=%s, err=%s", out, err)
    451524    if proc.returncode!=0:
    452         return typedict()
     525        return None
     526    return out
     527
     528def parse_query_sound(data):
    453529    d = typedict()
    454     for x in out.splitlines():
     530    if not data:
     531        return d
     532    for x in data.splitlines():
    455533        kv = x.split(b"=", 1)
    456534        if len(kv)==2:
    457535            #ie: kv = ["decoders", "mp3,vorbis"]
     
    461539                v = [bytestostr(x) for x in v.split(b",")]
    462540            #d["decoders"] = ["mp3", "vorbis"]
    463541            d[bytestostr(k)] = v
    464     log("query_sound()=%s", d)
     542    log("parse_query_sound(%s)=%s", repr_ellipsized(str(data)), d)
    465543    return d