Ticket #486: info-namespace-v2.patch
File info-namespace-v2.patch, 111.0 KB (added by , 6 years ago) |
---|
-
xpra/child_reaper.py
12 12 import os, sys 13 13 import signal 14 14 15 from xpra.util import updict16 15 from xpra.log import Logger 17 16 log = Logger("server", "util") 18 17 … … 186 185 187 186 def get_info(self): 188 187 iv = list(self._proc_info) 189 info = {"children" : len(iv),190 "children.dead": len([x for x in iv if x.dead]),191 "children.ignored" : len([x for x in iv if x.ignore])}188 info = {"children" : {"" : len(iv), 189 "dead" : len([x for x in iv if x.dead]), 190 "ignored" : len([x for x in iv if x.ignore])}} 192 191 pi = sorted(self._proc_info, key=lambda x: x.pid, reverse=True) 192 cinfo = {} 193 193 for i, procinfo in enumerate(pi): 194 d = dict((k,getattr(procinfo,k)) for k in ("name", "command", "ignore", "forget", "returncode", "dead", "pid")) 195 updict(info, "child[%i]" % i, d) 194 d = {} 195 for k in ("name", "command", "ignore", "forget", "returncode", "dead", "pid"): 196 v = getattr(procinfo, k) 197 if v is None: 198 continue 199 d[k] = v 200 cinfo[i] = d 201 info["child"] = cinfo 196 202 return info -
xpra/client/gl/gtk_compat.py
27 27 28 28 def get_info(): 29 29 return { 30 "gdkgl .version" : GdkGLExt._version,31 "gtkgl .version" : GtkGLExt._version,30 "gdkgl" : {"version" : GdkGLExt._version}, 31 "gtkgl" : {"version" : GtkGLExt._version}, 32 32 } 33 33 gdkgl = GdkGLExt 34 34 gtkgl = GtkGLExt … … 74 74 return None 75 75 76 76 def get_info(): 77 def v(x): 78 return {"version" : x} 77 79 return { 78 "pygdkglext .version" : gdkgl.pygdkglext_version,79 "gtkglext .version" : gtkgl.gtkglext_version,80 "gdkglext .version" : gdkgl.gdkglext_version,81 "gdkgl .version" : gdkgl.query_version()80 "pygdkglext" : v(gdkgl.pygdkglext_version), 81 "gtkglext" : v(gtkgl.gtkglext_version), 82 "gdkglext" : v(gdkgl.gdkglext_version), 83 "gdkgl" : v(gdkgl.query_version()) 82 84 } 83 85 84 86 class GLContextManager(object): -
xpra/client/gtk_base/bug_report.py
18 18 19 19 from xpra.gtk_common.gtk_util import gtk_main, add_close_accel, scaled_image, pixbuf_new_from_file, get_display_info, \ 20 20 JUSTIFY_LEFT, WIN_POS_CENTER, STATE_NORMAL, FILE_CHOOSER_ACTION_SAVE, choose_file, get_gtk_version_info 21 from xpra.util import nonl, updict,strtobytes21 from xpra.util import nonl, strtobytes 22 22 from xpra.log import Logger 23 23 log = Logger("util") 24 24 … … 136 136 "env" : os.environ, 137 137 "config" : read_xpra_defaults(), 138 138 }.items(): 139 updict(d, k, v)139 d[k] = v 140 140 return d 141 141 get_screenshot, take_screenshot_fn = None, None 142 142 #screenshot: may have OS-specific code -
xpra/client/gtk_base/session_info.py
67 67 elapsed = now-startt 68 68 return int(total/elapsed), total_n/elapsed, mins, avgs, maxs 69 69 70 def dictlook(d, k, fallback=None): 71 #deal with old-style non-namespaced dicts first: 72 #"batch.delay.avg" 73 if d is None: 74 return fallback 75 v = d.get(k) 76 if v is not None: 77 return v 78 parts = k.split(".") 79 #["batch", "delay", "avg"] 80 v = d 81 for p in parts: 82 try: 83 v = v.get(p) 84 except: 85 return fallback 86 return v 70 87 88 71 89 class SessionInfo(gtk.Window): 72 90 73 91 def __init__(self, client, session_name, window_icon_pixbuf, conn, get_pixbuf): … … 135 153 return version or "unknown" 136 154 def server_info(*prop_names): 137 155 for x in prop_names: 138 v = scaps.capsget(x)156 v = dictlook(scaps, x) 139 157 if v is not None: 140 158 return v 141 if self.client.server_last_info: 142 v = self.client.server_last_info.get(x) 159 v = dictlook(self.client.server_last_info, x) 143 160 if v is not None: 144 161 return v 145 162 return None … … 160 177 gtk_version_info = get_gtk_version_info() 161 178 def client_vinfo(prop, fallback="unknown"): 162 179 k = "%s.version" % prop 163 return label(make_version_str( gtk_version_info.get(k, fallback)))180 return label(make_version_str(dictlook(gtk_version_info, k, fallback))) 164 181 def server_vinfo(prop): 165 182 k = "%s.version" % prop 166 183 fk = "%s_version" % prop … … 521 538 info = ss.get_info() 522 539 if info: 523 540 info = typedict(info) 524 self.sound_out_queue_cur.append(info.intget("queue.cur")) 525 self.sound_out_queue_min.append(info.intget("queue.min")) 526 self.sound_out_queue_max.append(info.intget("queue.max")) 541 def intlookup(k): 542 return int(dictlook(info, k, 0)) 543 self.sound_out_queue_cur.append(intlookup("queue.cur")) 544 self.sound_out_queue_min.append(intlookup("queue.min")) 545 self.sound_out_queue_max.append(intlookup("queue.max")) 527 546 return not self.is_closed 528 547 529 548 def populate(self, *args): … … 574 593 if self.client.server_last_info: 575 594 #populate running averages for graphs: 576 595 def getavg(name): 577 return self.client.server_last_info.get("%s.avg" % name)596 return dictlook(self.client.server_last_info, "%s.avg" % name) 578 597 def addavg(l, name): 579 598 v = getavg(name) 580 599 if v: … … 780 799 return "" 781 800 altv = "" 782 801 if alt: 783 altv = self.client.server_last_info.get((alt+"."+suffix).encode(), "")784 return self.client.server_last_info.get((prefix+"."+suffix).encode(), altv)802 altv = dictlook(self.client.server_last_info, (alt+"."+suffix).encode(), "") 803 return dictlook(self.client.server_last_info, (prefix+"."+suffix).encode(), altv) 785 804 786 805 def values_from_info(self, prefix, alt=None): 787 806 def getv(suffix): … … 799 818 values = [] 800 819 for wid in self.client._window_to_id.values(): 801 820 for window_prop in window_props: 802 v = self.client.server_last_info.get("window[%s].%s.%s" % (wid, window_prop, suffix))821 v = dictlook(self.client.server_last_info, "window[%s].%s.%s" % (wid, window_prop, suffix)) 803 822 if v is not None: 804 823 values.append(v) 805 824 break … … 903 922 #remove all the current labels: 904 923 for x in self.encoder_info_box.get_children(): 905 924 self.encoder_info_box.remove(x) 906 window_encoder_stats = {}907 925 if self.client.server_last_info: 908 #We are interested in data like: 909 #window[1].encoder=x264 910 #window[1].encoder.frames=1 911 #window[1].encoder.fps=25 912 for k,v in self.client.server_last_info.items(): 913 k = bytestostr(k) 914 if not k.startswith("window["): 915 continue 916 pos = k.find("].encoder") 917 if pos<=0: 918 continue 919 try: 920 wid_str = k[len("window["):pos] #ie: "1" 921 wid = int(wid_str) 922 except: 923 #wid_str may be invalid, ie: 924 #window[1].pipeline_option[1].encoder=video_spec(xpra.codecs.enc_x264.encoder.Encoder) 925 # -> wid_str= "1].pipeline_option[1" 926 continue 927 ekey = k[(pos+len("].encoder")):] #ie: "" or ".frames" 928 if ekey.startswith("."): 929 ekey = ekey[1:] 930 if ekey=="build_config": 931 continue 932 window_encoder_stats.setdefault(wid, {})[ekey] = v 933 #print("window_encoder_stats=%s" % window_encoder_stats) 926 window_encoder_stats = self.get_window_encoder_stats() 927 #log("window_encoder_stats=%s", window_encoder_stats) 934 928 for wid, props in window_encoder_stats.items(): 935 929 l = label("%s (%s)" % (wid, bytestostr(props.get("")))) 936 930 l.show() … … 939 933 self.encoder_info_box.add(l) 940 934 return True 941 935 936 def get_window_encoder_stats(self): 937 window_encoder_stats = {} 938 #new-style server with namespace: 939 window_dict = self.client.server_last_info.get("window") 940 log.warn("window_dict=%s", window_dict) 941 if window_dict and isinstance(window_dict, dict): 942 for k,v in window_dict.items(): 943 try: 944 wid = int(k) 945 encoder_stats = v.get("encoder") 946 if encoder_stats: 947 window_encoder_stats[wid] = encoder_stats 948 except: 949 pass 950 return window_encoder_stats 951 #fallback code, we are interested in string data like: 952 #window[1].encoder=x264 953 #window[1].encoder.frames=1 954 #window[1].encoder.fps=25 955 for k,v in self.client.server_last_info.items(): 956 k = bytestostr(k) 957 if not k.startswith("window["): 958 continue 959 pos = k.find("].encoder") 960 if pos<=0: 961 continue 962 try: 963 wid_str = k[len("window["):pos] #ie: "1" 964 wid = int(wid_str) 965 except: 966 #wid_str may be invalid, ie: 967 #window[1].pipeline_option[1].encoder=video_spec(xpra.codecs.enc_x264.encoder.Encoder) 968 # -> wid_str= "1].pipeline_option[1" 969 continue 970 ekey = k[(pos+len("].encoder")):] #ie: "" or ".frames" 971 if ekey.startswith("."): 972 ekey = ekey[1:] 973 if ekey=="build_config": 974 continue 975 window_encoder_stats.setdefault(wid, {})[ekey] = v 976 return window_encoder_stats 977 978 942 979 def populate_graphs(self, *args): 943 980 if self.client.server_info_request: 944 981 self.client.send_info_request() -
xpra/client/ui_client_base.py
1404 1404 "windows" : self.windows_enabled, 1405 1405 "show-desktop" : True, 1406 1406 "system_tray" : self.client_supports_system_tray, 1407 "info-namespace" : True, 1407 1408 #window meta data and handling: 1408 1409 "generic_window_types" : True, 1409 1410 "server-window-move-resize" : True, … … 2420 2421 ss.add_data(data, metadata) 2421 2422 if self.av_sync and self.server_av_sync: 2422 2423 info = ss.get_info() 2423 queue_used = info.get("queue.cur") 2424 queue_used = info.get("queue.cur") or info.get("queue", {}).get("cur") 2424 2425 if queue_used is None: 2425 2426 return 2426 2427 delta = (self.queue_used_sent or 0)-queue_used -
xpra/clipboard/clipboard_base.py
23 23 from xpra.gtk_common.gtk_util import GetClipboard, PROPERTY_CHANGE_MASK 24 24 from xpra.gtk_common.nested_main import NestedMainLoop 25 25 from xpra.net.compression import Uncompressed 26 from xpra.util import csv 26 from xpra.util import csv, updict 27 27 28 28 29 29 MIN_CLIPBOARD_COMPRESSION_SIZE = 512 … … 91 91 "want_targets" : self._want_targets, 92 92 } 93 93 for clipboard, proxy in self._clipboard_proxies.items(): 94 for k,v in proxy.get_info().items(): 95 info["%s.%s" % (clipboard, k)] = v 94 info[clipboard] = proxy.get_info() 96 95 return info 97 96 98 97 def cleanup(self): … … 463 462 "enabled" : self._enabled, 464 463 "greedy_client" : self._greedy_client, 465 464 "blocked_owner_change" : self._block_owner_change, 466 "event.selection_request" : self._selection_request_events,467 "event.selection_get" : self._selection_get_events,468 "event.selection_clear" : self._selection_clear_events,469 "event.got_token" : self._got_token_events,470 "event.sent_token" : self._sent_token_events,471 "event.get_contents" : self._get_contents_events,472 "event.request_contents" : self._request_contents_events,473 465 } 466 updict(info, "event", { 467 "selection_request" : self._selection_request_events, 468 "selection_get" : self._selection_get_events, 469 "selection_clear" : self._selection_clear_events, 470 "got_token" : self._got_token_events, 471 "sent_token" : self._sent_token_events, 472 "get_contents" : self._get_contents_events, 473 "request_contents" : self._request_contents_events}) 474 474 return info 475 475 476 476 def cleanup(self): -
xpra/codecs/csc_opencl/colorspace_converter.py
13 13 import pyopencl #@UnresolvedImport 14 14 from pyopencl import mem_flags #@UnresolvedImport 15 15 16 from xpra.util import updict,engs16 from xpra.util import engs 17 17 from xpra.os_util import _memoryview 18 18 19 19 PREFERRED_DEVICE_TYPE = os.environ.get("XPRA_OPENCL_DEVICE_TYPE", "GPU") … … 486 486 "version.cl_header" : pyopencl.get_cl_header_version(), 487 487 "opengl" : pyopencl.have_gl(), 488 488 #"kernels" : KERNELS_DEFS.keys() 489 "pyopencl" : get_pyopencl_info(), 489 490 } 490 updict(info, "pyopencl", get_pyopencl_info())491 491 if selected_platform: 492 updict(info, "platform",{492 info["platform"] = { 493 493 "name" : selected_platform.name, 494 494 "vendor" : selected_platform.vendor, 495 495 "devices" : len(selected_platform.get_devices()), 496 } )496 } 497 497 if selected_device: 498 if hasattr(selected_device, "opencl_c_version"): 499 info["device.opencl_c_version"] = getattr(selected_device, "opencl_c_version") 500 updict(info, "device", { 498 dinfo = { 501 499 "type" : device_type(selected_device), 502 500 "name" : selected_device.name.strip(), 503 501 "version" : selected_device.version, … … 504 502 "max_work_group_size" : selected_device.max_work_group_size, 505 503 "max_work_item_dimensions" : selected_device.max_work_item_dimensions, 506 504 "max_work_item_sizes" : selected_device.max_work_item_sizes, 507 "max-size" : selected_device_max_size}) 505 "max-size" : selected_device_max_size} 506 if hasattr(selected_device, "opencl_c_version"): 507 dinfo["opencl_c_version"] = getattr(selected_device, "opencl_c_version") 508 info["device"] = dinfo 508 509 return info 509 510 510 511 -
xpra/codecs/enc_ffmpeg/__init__.py
1 # This file is part of Xpra. 2 # Copyright (C) 2016 Antoine Martin <antoine@devloop.org.uk> 3 # Xpra is released under the terms of the GNU GPL v2, or, at your option, any 4 # later version. See the file COPYING for details. -
xpra/codecs/enc_ffmpeg/encoder.pyx
1 # This file is part of Xpra. 2 # Copyright (C) 2012-2014 Antoine Martin <antoine@devloop.org.uk> 3 # Xpra is released under the terms of the GNU GPL v2, or, at your option, any 4 # later version. See the file COPYING for details. 5 6 import weakref 7 from xpra.log import Logger 8 log = Logger("decoder", "ffmpeg") 9 10 from xpra.codecs.codec_constants import get_subsampling_divs 11 from xpra.codecs.image_wrapper import ImageWrapper 12 from xpra.codecs.libav_common.av_log cimport override_logger, restore_logger #@UnresolvedImport 13 from xpra.util import bytestostr 14 15 16 ctypedef unsigned long size_t 17 ctypedef unsigned char uint8_t 18 19 20 cdef extern from "../../buffers/buffers.h": 21 object memory_as_pybuffer(void* ptr, Py_ssize_t buf_len, int readonly) 22 int object_as_buffer(object obj, const void ** buffer, Py_ssize_t * buffer_len) 23 int get_buffer_api_version() 24 25 cdef extern from "string.h": 26 void * memcpy(void * destination, void * source, size_t num) nogil 27 void * memset(void * ptr, int value, size_t num) nogil 28 void free(void * ptr) nogil 29 30 31 cdef extern from "../../inline.h": 32 pass 33 34 cdef extern from "../../buffers/memalign.h": 35 void *xmemalign(size_t size) 36 37 38 cdef extern from "libavutil/mem.h": 39 void av_free(void *ptr) 40 41 cdef extern from "libavutil/error.h": 42 int av_strerror(int errnum, char *errbuf, size_t errbuf_size) 43 44 cdef extern from "libavcodec/version.h": 45 int LIBAVCODEC_VERSION_MAJOR 46 int LIBAVCODEC_VERSION_MINOR 47 int LIBAVCODEC_VERSION_MICRO 48 49 #why can't we define this inside the avcodec.h section? (beats me) 50 ctypedef unsigned int AVCodecID 51 ctypedef long AVPixelFormat 52 53 54 cdef extern from "libavutil/pixfmt.h": 55 AVPixelFormat AV_PIX_FMT_NONE 56 AVPixelFormat AV_PIX_FMT_YUV420P 57 58 cdef extern from "libavcodec/avcodec.h": 59 int CODEC_FLAG2_FAST 60 61 ctypedef struct AVFrame: 62 uint8_t **data 63 int *linesize 64 int format 65 void *opaque 66 ctypedef struct AVCodec: 67 pass 68 ctypedef struct AVDictionary: 69 pass 70 ctypedef struct AVPacket: 71 uint8_t *data 72 int size 73 74 ctypedef struct AVCodecContext: 75 int width 76 int height 77 AVPixelFormat pix_fmt 78 int thread_safe_callbacks 79 int thread_count 80 int thread_type 81 int flags 82 int flags2 83 int refcounted_frames 84 85 AVCodecID AV_CODEC_ID_H264 86 AVCodecID AV_CODEC_ID_H265 87 AVCodecID AV_CODEC_ID_VP8 88 AVCodecID AV_CODEC_ID_VP9 89 AVCodecID AV_CODEC_ID_MPEG4 90 91 #init and free: 92 void avcodec_register_all() 93 AVCodec *avcodec_find_decoder(AVCodecID id) 94 AVCodecContext *avcodec_alloc_context3(const AVCodec *codec) 95 int avcodec_open2(AVCodecContext *avctx, const AVCodec *codec, AVDictionary **options) 96 AVFrame* av_frame_alloc() 97 void av_frame_free(AVFrame **frame) 98 int avcodec_close(AVCodecContext *avctx) 99 100 #actual decoding: 101 void av_init_packet(AVPacket *pkt) nogil 102 void avcodec_get_frame_defaults(AVFrame *frame) nogil 103 int avcodec_decode_video2(AVCodecContext *avctx, AVFrame *picture, 104 int *got_picture_ptr, const AVPacket *avpkt) nogil 105 106 void av_frame_unref(AVFrame *frame) nogil 107 108 109 FORMAT_TO_ENUM = { 110 "YUV420P" : AV_PIX_FMT_YUV420P, 111 "YUV422P" : AV_PIX_FMT_YUV422P, 112 "YUV444P" : AV_PIX_FMT_YUV444P, 113 "RGB" : AV_PIX_FMT_RGB24, 114 "XRGB" : AV_PIX_FMT_0RGB, 115 "BGRX" : AV_PIX_FMT_BGR0, 116 "ARGB" : AV_PIX_FMT_ARGB, 117 "BGRA" : AV_PIX_FMT_BGRA, 118 "GBRP" : AV_PIX_FMT_GBRP, 119 } 120 121 COLORSPACES = FORMAT_TO_ENUM.keys() 122 ENUM_TO_FORMAT = {} 123 for pix_fmt, av_enum in FORMAT_TO_ENUM.items(): 124 ENUM_TO_FORMAT[av_enum] = pix_fmt 125 126 def get_version(): 127 return (LIBAVCODEC_VERSION_MAJOR, LIBAVCODEC_VERSION_MINOR, LIBAVCODEC_VERSION_MICRO) 128 129 avcodec_register_all() 130 CODECS = [] 131 if avcodec_find_decoder(AV_CODEC_ID_H264)!=NULL: 132 CODECS.append("h264") 133 if avcodec_find_decoder(AV_CODEC_ID_VP8)!=NULL: 134 CODECS.append("vp8") 135 if avcodec_find_decoder(AV_CODEC_ID_VP9)!=NULL: 136 CODECS.append("vp9") 137 if avcodec_find_decoder(AV_CODEC_ID_H265)!=NULL: 138 CODECS.append("h265") 139 if avcodec_find_decoder(AV_CODEC_ID_MPEG4)!=NULL: 140 CODECS.append("mpeg4") 141 log("enc_ffmpeg.init_module: CODECS=%s", CODECS) 142 143 144 def init_module(): 145 log("enc_ffmpeg.init_module()") 146 override_logger() 147 148 def cleanup_module(): 149 log("enc_ffmpeg.cleanup_module()") 150 restore_logger() 151 152 def get_type(): 153 return "ffmpeg" 154 155 def get_info(): 156 f = {} 157 for e in get_encodings(): 158 f["formats.%s" % e] = get_input_colorspaces(e) 159 return {"version" : get_version(), 160 "encodings" : get_encodings(), 161 "buffer_api" : get_buffer_api_version(), 162 "formats" : f, 163 } 164 165 def get_encodings(): 166 global CODECS 167 return CODECS 168 169 def get_input_colorspaces(encoding): 170 return ["YUV420P"] 171 172 def get_output_colorspace(encoding, csc): 173 if encoding not in CODECS: 174 return "" 175 return "YUV420P" 176 177 178 cdef void clear_frame(AVFrame *frame): 179 assert frame!=NULL, "frame is not set!" 180 for i in range(4): 181 frame.data[i] = NULL 182 183 184 cdef class AVFrameWrapper: 185 """ 186 Wraps an AVFrame so we can free it 187 once both xpra and avcodec are done with it. 188 """ 189 cdef AVCodecContext *avctx 190 cdef AVFrame *frame 191 cdef int xpra_freed 192 193 cdef set_context(self, AVCodecContext *avctx, AVFrame *frame): 194 self.avctx = avctx 195 self.frame = frame 196 log("%s.set_context(%#x, %#x)", self, <unsigned long> avctx, <unsigned long> frame) 197 198 def __dealloc__(self): 199 #By the time this wrapper is garbage collected, 200 #we must have freed it! 201 assert self.frame==NULL and self.avctx==NULL, "frame was freed by both, but not actually freed!" 202 203 def __str__(self): 204 if self.frame==NULL: 205 return "AVFrameWrapper(NULL)" 206 return "AVFrameWrapper(%#x)" % <unsigned long> self.frame 207 208 def xpra_free(self): 209 log("%s.xpra_free()", self) 210 self.free() 211 212 cdef free(self): 213 log("%s.free() context=%#x, frame=%#x", self, <unsigned long> self.avctx, <unsigned long> self.frame) 214 if self.avctx!=NULL and self.frame!=NULL: 215 av_frame_unref(self.frame) 216 self.frame = NULL 217 self.avctx = NULL 218 219 220 class AVImageWrapper(ImageWrapper): 221 """ 222 Wrapper which allows us to call xpra_free on the decoder 223 when the image is freed, or once we have made a copy of the pixels. 224 """ 225 226 def __repr__(self): #@DuplicatedSignature 227 return ImageWrapper.__repr__(self)+"-(%s)" % self.av_frame 228 229 def free(self): #@DuplicatedSignature 230 log("AVImageWrapper.free()") 231 ImageWrapper.free(self) 232 self.xpra_free_frame() 233 234 def clone_pixel_data(self): 235 log("AVImageWrapper.clone_pixel_data()") 236 ImageWrapper.clone_pixel_data(self) 237 self.xpra_free_frame() 238 239 def xpra_free_frame(self): 240 av_frame = self.av_frame 241 log("AVImageWrapper.xpra_free_frame() av_frame=%s", av_frame) 242 if av_frame: 243 self.av_frame = None 244 av_frame.xpra_free() 245 246 247 cdef class Encoder: 248 """ 249 This wraps the AVCodecContext and its configuration, 250 also tracks AVFrames. 251 It also handles reconstructing a single ImageWrapper 252 constructed from 3-pass decoding (see plane_sizes). 253 """ 254 cdef AVCodec *codec 255 cdef AVCodecContext *codec_ctx 256 cdef AVPixelFormat pix_fmt 257 cdef AVPixelFormat actual_pix_fmt 258 cdef object colorspace 259 cdef object weakref_images 260 cdef AVFrame *av_frame 261 #this is the actual number of images we have returned 262 cdef unsigned long frames 263 cdef int width 264 cdef int height 265 cdef object encoding 266 267 cdef object __weakref__ 268 269 def init_context(self, encoding, int width, int height, colorspace): 270 cdef int r 271 cdef int i 272 assert encoding in CODECS 273 self.encoding = encoding 274 self.width = width 275 self.height = height 276 assert colorspace in COLORSPACES, "invalid colorspace: %s" % colorspace 277 self.colorspace = "" 278 for x in COLORSPACES: 279 if x==colorspace: 280 self.colorspace = x 281 break 282 if not self.colorspace: 283 log.error("invalid pixel format: %s", colorspace) 284 return False 285 self.pix_fmt = FORMAT_TO_ENUM.get(colorspace, AV_PIX_FMT_NONE) 286 if self.pix_fmt==AV_PIX_FMT_NONE: 287 log.error("invalid pixel format: %s", colorspace) 288 return False 289 self.actual_pix_fmt = self.pix_fmt 290 291 avcodec_register_all() 292 293 cdef AVCodecID CodecID 294 if self.encoding=="h264": 295 CodecID = AV_CODEC_ID_H264 296 elif self.encoding=="h265": 297 CodecID = AV_CODEC_ID_H265 298 elif self.encoding=="vp8": 299 CodecID = AV_CODEC_ID_VP8 300 elif self.encoding=="vp9": 301 CodecID = AV_CODEC_ID_VP9 302 elif self.encoding=="mpeg4": 303 CodecID = AV_CODEC_ID_MPEG4 304 else: 305 raise Exception("invalid codec; %s" % self.encoding) 306 self.codec = avcodec_find_decoder(CodecID) 307 if self.codec==NULL: 308 log.error("codec %s not found!" % self.encoding) 309 return False 310 311 #from here on, we have to call clean_decoder(): 312 self.codec_ctx = avcodec_alloc_context3(self.codec) 313 if self.codec_ctx==NULL: 314 log.error("failed to allocate codec context!") 315 self.clean_decoder() 316 return False 317 318 self.codec_ctx.refcounted_frames = 1 319 self.codec_ctx.width = width 320 self.codec_ctx.height = height 321 self.codec_ctx.pix_fmt = self.pix_fmt 322 #self.codec_ctx.get_buffer2 = avcodec_get_buffer2 323 #self.codec_ctx.release_buffer = avcodec_release_buffer 324 self.codec_ctx.thread_safe_callbacks = 1 325 self.codec_ctx.thread_type = 2 #FF_THREAD_SLICE: allow more than one thread per frame 326 self.codec_ctx.thread_count = 0 #auto 327 self.codec_ctx.flags2 |= CODEC_FLAG2_FAST #may cause "no deblock across slices" - which should be fine 328 r = avcodec_open2(self.codec_ctx, self.codec, NULL) 329 if r<0: 330 log.error("could not open codec: %s", self.av_error_str(r)) 331 self.clean_decoder() 332 return False 333 #up to 3 AVFrame objects used: 334 self.av_frame = av_frame_alloc() 335 if self.av_frame==NULL: 336 log.error("could not allocate an AVFrame for decoding") 337 self.clean_decoder() 338 return False 339 self.frames = 0 340 #to keep track of images not freed yet: 341 #(we want a weakref.WeakSet() but this is python2.7+ only..) 342 self.weakref_images = [] 343 #register this decoder in the global dictionary: 344 log("dec_avcodec.Decoder.init_context(%s, %s, %s) self=%s", width, height, colorspace, self.get_info()) 345 return True 346 347 def clean(self): 348 self.clean_decoder() 349 self.codec = NULL 350 self.pix_fmt = 0 351 self.actual_pix_fmt = 0 352 self.colorspace = "" 353 self.weakref_images = [] 354 self.av_frame = NULL #should be redundant 355 self.frames = 0 356 self.width = 0 357 self.height = 0 358 self.encoding = "" 359 360 361 def clean_decoder(self): 362 cdef int r, i 363 log("%s.clean_decoder()", self) 364 #we may have images handed out, ensure we don't reference any memory 365 #that needs to be freed using avcodec_release_buffer(..) 366 #as this requires the context to still be valid! 367 #copying the pixels should ensure we free the AVFrameWrapper associated with it: 368 if self.weakref_images: 369 images = [y for y in [x() for x in self.weakref_images] if y is not None] 370 self.weakref_images = [] 371 log("clean_decoder() cloning pixels for images still in use: %s", images) 372 for img in images: 373 if not img.freed: 374 img.clone_pixel_data() 375 376 if self.av_frame!=NULL: 377 log("clean_decoder() freeing AVFrame: %#x", <unsigned long> self.av_frame) 378 av_frame_free(&self.av_frame) 379 #redundant: self.frame = NULL 380 381 cdef unsigned long ctx_key #@DuplicatedSignature 382 log("clean_decoder() freeing AVCodecContext: %#x", <unsigned long> self.codec_ctx) 383 if self.codec_ctx!=NULL: 384 r = avcodec_close(self.codec_ctx) 385 if r!=0: 386 log.warn("error closing decoder context %#x: %s", <unsigned long> self.codec_ctx, self.av_error_str(r)) 387 av_free(self.codec_ctx) 388 self.codec_ctx = NULL 389 log("clean_decoder() done") 390 391 cdef av_error_str(self, errnum): 392 cdef char[128] err_str 393 cdef int i = 0 394 if av_strerror(errnum, err_str, 128)==0: 395 while i<128 and err_str[i]!=0: 396 i += 1 397 return bytestostr(err_str[:i]) 398 return str(errnum) 399 400 def __repr__(self): #@DuplicatedSignature 401 if self.is_closed(): 402 return "dec_avcodec.Decoder(*closed*)" 403 return "dec_avcodec.Decoder(%s)" % self.get_info() 404 405 def get_info(self): #@DuplicatedSignature 406 info = {"version" : get_version(), 407 "encoding" : self.encoding, 408 "formats" : get_input_colorspaces(self.encoding), 409 "type" : self.get_type(), 410 "frames" : self.frames, 411 "width" : self.width, 412 "height" : self.height, 413 } 414 if self.colorspace: 415 info["colorspace"] = self.colorspace 416 info["actual_colorspace"] = self.get_actual_colorspace() 417 if not self.is_closed(): 418 info["decoder_width"] = self.codec_ctx.width 419 info["decoder_height"] = self.codec_ctx.height 420 else: 421 info["closed"] = True 422 return info 423 424 def is_closed(self): 425 return self.codec_ctx==NULL 426 427 def __dealloc__(self): #@DuplicatedSignature 428 self.clean() 429 430 def get_width(self): 431 return self.width 432 433 def get_height(self): 434 return self.height 435 436 def get_encoding(self): 437 return self.encoding 438 439 def get_type(self): #@DuplicatedSignature 440 return "avcodec" 441 442 def decompress_image(self, input, options): 443 cdef unsigned char * padded_buf = NULL 444 cdef const unsigned char * buf = NULL 445 cdef Py_ssize_t buf_len = 0 446 cdef int size 447 cdef int len = 0 448 cdef int nplanes 449 cdef int got_picture 450 cdef AVPacket avpkt 451 cdef unsigned long frame_key #@DuplicatedSignature 452 cdef AVFrameWrapper framewrapper 453 cdef AVFrame *av_frame 454 cdef object img 455 assert self.codec_ctx!=NULL, "no codec context! (not initialized or already closed)" 456 assert self.codec!=NULL 457 458 #copy the whole input buffer into a padded C buffer: 459 assert object_as_buffer(input, <const void**> &buf, &buf_len)==0 460 padded_buf = <unsigned char *> xmemalign(buf_len+128) 461 memcpy(padded_buf, buf, buf_len) 462 memset(padded_buf+buf_len, 0, 128) 463 464 #note: plain RGB output, will redefine those: 465 out = [] 466 strides = [] 467 outsize = 0 468 469 #ensure we can detect if the frame buffer got allocated: 470 clear_frame(self.av_frame) 471 #now safe to run without gil: 472 with nogil: 473 av_init_packet(&avpkt) 474 avpkt.data = <uint8_t *> (padded_buf) 475 avpkt.size = buf_len 476 len = avcodec_decode_video2(self.codec_ctx, self.av_frame, &got_picture, &avpkt) 477 if len<0: 478 av_frame_unref(self.av_frame) 479 log("%s.decompress_image(%s:%s, %s) avcodec_decode_video2 failure: %s", self, type(input), buf_len, options, self.av_error_str(len)) 480 log.error("avcodec_decode_video2 %s decoding failure:", self.encoding) 481 log.error(" %s", self.av_error_str(len)) 482 return None 483 if len==0: 484 av_frame_unref(self.av_frame) 485 log("%s.decompress_image(%s:%s, %s) avcodec_decode_video2 failed to decode the stream", self, type(input), buf_len, options) 486 log.error("avcodec_decode_video2 %s decoding failure - no stream", self.encoding) 487 return None 488 489 if self.actual_pix_fmt!=self.av_frame.format: 490 if self.av_frame.format==-1: 491 log.error("avcodec error decoding %i bytes of %s data", buf_len, self.encoding) 492 log.error(" frame %i", self.frames) 493 log.error(" options=%s", options) 494 log.error(" decoder state:") 495 for k,v in self.get_info().items(): 496 log.error(" %s = %s", k, v) 497 return None 498 self.actual_pix_fmt = self.av_frame.format 499 if self.actual_pix_fmt not in ENUM_TO_FORMAT: 500 av_frame_unref(self.av_frame) 501 log.error("unknown output pixel format: %s, expected %s (%s)", self.actual_pix_fmt, self.pix_fmt, self.colorspace) 502 return None 503 log("avcodec actual output pixel format is %s (%s), expected %s (%s)", self.actual_pix_fmt, self.get_actual_colorspace(), self.pix_fmt, self.colorspace) 504 505 cs = self.get_actual_colorspace() 506 if cs.endswith("P"): 507 divs = get_subsampling_divs(cs) 508 nplanes = 3 509 for i in range(3): 510 _, dy = divs[i] 511 if dy==1: 512 height = self.codec_ctx.height 513 elif dy==2: 514 height = (self.codec_ctx.height+1)>>1 515 else: 516 av_frame_unref(self.av_frame) 517 raise Exception("invalid height divisor %s" % dy) 518 stride = self.av_frame.linesize[i] 519 size = height * stride 520 outsize += size 521 522 out.append(memory_as_pybuffer(<void *>self.av_frame.data[i], size, True)) 523 strides.append(stride) 524 log("decompress_image() read back yuv plane %s: %s bytes", i, size) 525 else: 526 #RGB mode: "out" is a single buffer 527 strides = self.av_frame.linesize[0]+self.av_frame.linesize[1]+self.av_frame.linesize[2] 528 outsize = self.codec_ctx.height * strides 529 out = memory_as_pybuffer(<void *>self.av_frame.data[0], outsize, True) 530 nplanes = 0 531 log("decompress_image() read back rgb buffer: %s bytes", outsize) 532 533 #FIXME: we could lose track of framewrappers if an error occurs before the end: 534 framewrapper = AVFrameWrapper() 535 framewrapper.set_context(self.codec_ctx, self.av_frame) 536 537 if outsize==0: 538 av_frame_unref(self.av_frame) 539 raise Exception("output size is zero!") 540 541 free(padded_buf) 542 assert self.codec_ctx.width>=self.width, "codec width is smaller than our width: %s<%s" % (self.codec_ctx.width, self.width) 543 assert self.codec_ctx.height>=self.height, "codec height is smaller than our height: %s<%s" % (self.codec_ctx.height, self.height) 544 img = AVImageWrapper(0, 0, self.width, self.height, out, cs, 24, strides, nplanes, thread_safe=False) 545 img.av_frame = framewrapper 546 self.frames += 1 547 #add to weakref list after cleaning it up: 548 self.weakref_images = [x for x in self.weakref_images if x() is not None] 549 self.weakref_images.append(weakref.ref(img)) 550 log("%s.decompress_image(%s:%s, %s)=%s", self, type(input), buf_len, options, img) 551 return img 552 553 554 def get_colorspace(self): 555 return self.colorspace 556 557 def get_actual_colorspace(self): 558 return ENUM_TO_FORMAT.get(self.actual_pix_fmt, "unknown/invalid") 559 560 561 def selftest(full=False): 562 global CODECS 563 from xpra.codecs.codec_checks import testdecoder 564 from xpra.codecs.dec_avcodec2 import decoder 565 global CODECS 566 CODECS = testdecoder(decoder, full) -
xpra/codecs/mkv/__init__.py
1 # This file is part of Xpra. 2 # Copyright (C) 2016 Antoine Martin <antoine@devloop.org.uk> 3 # Xpra is released under the terms of the GNU GPL v2, or, at your option, any 4 # later version. See the file COPYING for details. -
xpra/codecs/mkv/muxer.pyx
1 # This file is part of Xpra. 2 # Copyright (C) 2016 Antoine Martin <antoine@devloop.org.uk> 3 # Xpra is released under the terms of the GNU GPL v2, or, at your option, any 4 # later version. See the file COPYING for details. 5 6 import time 7 import os 8 9 from xpra.log import Logger 10 log = Logger("encoder", "mkv") 11 12 from libc.stdint cimport int64_t 13 14 cdef extern from "string.h": 15 void *memset(void *ptr, int value, size_t num) nogil 16 void free(void *ptr) nogil 17 18 cdef extern from "../../buffers/memalign.h": 19 void *xmemalign(size_t size) 20 21 cdef extern from "../../buffers/buffers.h": 22 int object_as_buffer(object obj, const void ** buffer, Py_ssize_t * buffer_len) 23 int get_buffer_api_version() 24 25 26 cdef extern from "libmkv.h": 27 pass 28 29 cdef class Muxer: 30 cdef object __weakref__ 31 32 #init_context(w, h, src_format, encoding, quality, speed, scaling, options) 33 def init_context(self, int width, int height, src_format, dst_formats, encoding, int quality, int speed, scaling, options): #@DuplicatedSignature 34 pass -
xpra/codecs/nvenc4/encoder.pyx
16 16 from pycuda.driver import memcpy_htod 17 17 from pycuda.compiler import compile 18 18 19 from xpra.util import AtomicInteger, updict,engs, csv, pver19 from xpra.util import AtomicInteger, engs, csv, pver 20 20 from xpra.os_util import _memoryview 21 21 from xpra.codecs.cuda_common.cuda_context import init_all_devices, get_devices, select_device, \ 22 22 get_cuda_info, get_pycuda_info, device_info, reset_state, \ … … 1587 1587 "bitrate" : self.target_bitrate, 1588 1588 "quality" : self.quality, 1589 1589 "speed" : self.speed, 1590 "lossless" : self.lossless, 1591 "lossless.supported": LOSSLESS_ENABLED, 1592 "lossless.threshold": LOSSLESS_THRESHOLD, 1593 "yuv444.supported" : YUV444_ENABLED, 1594 "yuv444.threshold" : YUV444_THRESHOLD, 1590 "lossless" : { 1591 "" : self.lossless, 1592 "supported" : LOSSLESS_ENABLED, 1593 "threshold" : LOSSLESS_THRESHOLD 1594 }, 1595 "yuv444" : { 1596 "supported" : YUV444_ENABLED, 1597 "threshold" : YUV444_THRESHOLD, 1598 }, 1599 "cuda-device" : self.cuda_device_info, 1600 "cuda" : self.cuda_info, 1601 "pycuda" : self.pycuda_info, 1595 1602 }) 1596 1603 if self.scaling!=(1,1): 1597 1604 info.update({ … … 1598 1605 "input_width" : self.input_width, 1599 1606 "input_height" : self.input_height, 1600 1607 "scaling" : self.scaling}) 1601 updict(info, "cuda", self.cuda_device_info)1602 updict(info, "cuda", self.cuda_info)1603 updict(info, "pycuda", self.pycuda_info)1604 1608 if self.src_format: 1605 1609 info["src_format"] = self.src_format 1606 1610 if self.pixel_format: -
xpra/codecs/nvenc5/encoder.pyx
16 16 from pycuda.driver import memcpy_htod 17 17 from pycuda.compiler import compile 18 18 19 from xpra.util import AtomicInteger, updict,engs, csv, pver19 from xpra.util import AtomicInteger, engs, csv, pver 20 20 from xpra.os_util import _memoryview 21 21 from xpra.codecs.cuda_common.cuda_context import init_all_devices, get_devices, select_device, \ 22 22 get_cuda_info, get_pycuda_info, device_info, reset_state, \ … … 1625 1625 "bitrate" : self.target_bitrate, 1626 1626 "quality" : self.quality, 1627 1627 "speed" : self.speed, 1628 "lossless" : self.lossless, 1629 "lossless.supported": LOSSLESS_ENABLED, 1630 "lossless.threshold": LOSSLESS_THRESHOLD, 1631 "yuv444.supported" : YUV444_ENABLED, 1632 "yuv444.threshold" : YUV444_THRESHOLD, 1628 "lossless" : { 1629 "" : self.lossless, 1630 "supported" : LOSSLESS_ENABLED, 1631 "threshold" : LOSSLESS_THRESHOLD 1632 }, 1633 "yuv444" : { 1634 "supported" : YUV444_ENABLED, 1635 "threshold" : YUV444_THRESHOLD, 1636 }, 1637 "cuda-device" : self.cuda_device_info, 1638 "cuda" : self.cuda_info, 1639 "pycuda" : self.pycuda_info, 1633 1640 }) 1634 1641 if self.scaling!=(1,1): 1635 1642 info.update({ … … 1636 1643 "input_width" : self.input_width, 1637 1644 "input_height" : self.input_height, 1638 1645 "scaling" : self.scaling}) 1639 updict(info, "cuda", self.cuda_device_info)1640 updict(info, "cuda", self.cuda_info)1641 updict(info, "pycuda", self.pycuda_info)1642 1646 if self.src_format: 1643 1647 info["src_format"] = self.src_format 1644 1648 if self.pixel_format: -
xpra/codecs/nvenc6/encoder.pyx
16 16 from pycuda.driver import memcpy_htod 17 17 from pycuda.compiler import compile 18 18 19 from xpra.util import AtomicInteger, updict,engs, csv, pver19 from xpra.util import AtomicInteger, engs, csv, pver 20 20 from xpra.os_util import _memoryview 21 21 from xpra.codecs.cuda_common.cuda_context import init_all_devices, get_devices, select_device, \ 22 22 get_cuda_info, get_pycuda_info, device_info, reset_state, \ … … 1696 1696 "bitrate" : self.target_bitrate, 1697 1697 "quality" : self.quality, 1698 1698 "speed" : self.speed, 1699 "lossless" : self.lossless, 1700 "lossless.supported": LOSSLESS_ENABLED, 1701 "lossless.threshold": LOSSLESS_THRESHOLD, 1702 "yuv444.supported" : YUV444_ENABLED, 1703 "yuv444.threshold" : YUV444_THRESHOLD, 1699 "lossless" : { 1700 "" : self.lossless, 1701 "supported" : LOSSLESS_ENABLED, 1702 "threshold" : LOSSLESS_THRESHOLD 1703 }, 1704 "yuv444" : { 1705 "supported" : YUV444_ENABLED, 1706 "threshold" : YUV444_THRESHOLD, 1707 }, 1708 "cuda-device" : self.cuda_device_info, 1709 "cuda" : self.cuda_info, 1710 "pycuda" : self.pycuda_info, 1704 1711 }) 1705 1712 if self.scaling!=(1,1): 1706 1713 info.update({ … … 1707 1714 "input_width" : self.input_width, 1708 1715 "input_height" : self.input_height, 1709 1716 "scaling" : self.scaling}) 1710 updict(info, "cuda", self.cuda_device_info)1711 updict(info, "cuda", self.cuda_info)1712 updict(info, "pycuda", self.pycuda_info)1713 1717 if self.src_format: 1714 1718 info["src_format"] = self.src_format 1715 1719 if self.pixel_format: -
xpra/codecs/ogg/__init__.py
1 # This file is part of Xpra. 2 # Copyright (C) 2016 Antoine Martin <antoine@devloop.org.uk> 3 # Xpra is released under the terms of the GNU GPL v2, or, at your option, any 4 # later version. See the file COPYING for details. -
xpra/codecs/ogg/muxer.pyx
1 # This file is part of Xpra. 2 # Copyright (C) 2016 Antoine Martin <antoine@devloop.org.uk> 3 # Xpra is released under the terms of the GNU GPL v2, or, at your option, any 4 # later version. See the file COPYING for details. 5 6 import time 7 import os 8 9 from xpra.log import Logger 10 log = Logger("encoder", "mkv") 11 12 from libc.stdint cimport int64_t 13 14 cdef extern from "string.h": 15 void *memset(void *ptr, int value, size_t num) nogil 16 void free(void *ptr) nogil 17 18 cdef extern from "../../buffers/memalign.h": 19 void *xmemalign(size_t size) 20 21 cdef extern from "../../buffers/buffers.h": 22 int object_as_buffer(object obj, const void ** buffer, Py_ssize_t * buffer_len) 23 int get_buffer_api_version() 24 25 26 cdef extern from "ogg/ogg.h": 27 pass 28 29 cdef class Muxer: 30 cdef object __weakref__ 31 32 #init_context(w, h, src_format, encoding, quality, speed, scaling, options) 33 def init_context(self, int width, int height, src_format, dst_formats, encoding, int quality, int speed, scaling, options): #@DuplicatedSignature 34 pass -
xpra/net/bytestreams.py
215 215 d = Connection.get_info(self) 216 216 try: 217 217 d["type"] = "pipe" 218 d["pipe .read.fd"] = self._read_fd219 d["pipe.write.fd"] = self._write_fd218 d["pipe"] = {"read" : {"fd" : self._read_fd}, 219 "write" : {"fd" : self._write_fd}} 220 220 except: 221 221 pass 222 222 return d … … 255 255 d["type"] = "socket" 256 256 s = self._socket 257 257 if s: 258 from xpra.util import updict 259 updict(d, "socket", { 258 d["socket"] = { 260 259 "fileno" : s.fileno(), 261 260 "timeout" : int(1000*(s.gettimeout() or 0)), 262 261 "family" : s.family, 263 262 "proto" : s.proto, 264 "type" : s.type} )263 "type" : s.type} 265 264 except: 266 265 log.warn("failed to get socket information", exc_info=True) 267 266 return d -
xpra/net/protocol.py
20 20 cryptolog = Logger("network", "crypto") 21 21 22 22 from xpra.os_util import Queue, strtobytes 23 from xpra.util import repr_ellipsized, updict,csv23 from xpra.util import repr_ellipsized, csv 24 24 from xpra.net import ConnectionClosedException 25 25 from xpra.net.bytestreams import ABORT 26 26 from xpra.net import compression … … 210 210 211 211 def get_info(self, alias_info=True): 212 212 info = { 213 "input.packetcount" : self.input_packetcount,214 "input.raw_packetcount" : self.input_raw_packetcount,215 "input.cipher" : self.cipher_in_name or "",216 "input.cipher.padding" : self.cipher_in_padding,217 "output.packetcount" : self.output_packetcount,218 "output.raw_packetcount": self.output_raw_packetcount,219 "output.cipher" : self.cipher_out_name or "",220 "output.cipher.padding" : self.cipher_out_padding,221 213 "large_packets" : self.large_packets, 222 214 "compression_level" : self.compression_level, 223 "max_packet_size" : self.max_packet_size} 224 updict(info, "input.count", self.input_stats) 225 updict(info, "output.count", self.output_stats) 215 "max_packet_size" : self.max_packet_size, 216 "input" : { 217 "packetcount" : self.input_packetcount, 218 "raw_packetcount" : self.input_raw_packetcount, 219 "count" : self.input_stats, 220 "cipher" : {"": self.cipher_in_name or "", 221 "padding" : self.cipher_in_padding, 222 }, 223 }, 224 "output" : { 225 "packetcount" : self.output_packetcount, 226 "raw_packetcount" : self.output_raw_packetcount, 227 "count" : self.output_stats, 228 "cipher" : {"": self.cipher_out_name or "", 229 "padding" : self.cipher_out_padding 230 }, 231 }, 232 } 226 233 c = self._compress 227 234 if c: 228 235 info["compressor"] = compression.get_compressor_name(self._compress) … … 233 240 else: 234 241 info["encoder"] = packet_encoding.get_encoder_name(self._encoder) 235 242 if alias_info: 236 for k,v in self.send_aliases.items(): 237 info["send_alias." + str(k)] = v 238 info["send_alias." + str(v)] = k 239 for k,v in self.receive_aliases.items(): 240 info["receive_alias." + str(k)] = v 241 info["receive_alias." + str(v)] = k 243 info["send_alias"] = self.send_aliases 244 info["receive_alias"] = self.receive_aliases 242 245 c = self._conn 243 246 if c: 244 247 try: … … 248 251 info["has_more"] = self._source_has_more.is_set() 249 252 for t in (self._write_thread, self._read_thread, self._read_parser_thread, self._write_format_thread): 250 253 if t: 251 info ["thread.%s" %t.name] = t.is_alive()254 info.setdefault("thread", {})[t.name] = t.is_alive() 252 255 return info 253 256 254 257 -
xpra/net/pycrypto_backend.py
20 20 pass 21 21 22 22 def get_info(): 23 caps = {"backend" : "pycrypto",24 "pycrypto" : "True",25 "pycrypto.version" : Crypto.__version__}26 23 try: 27 24 from Crypto.PublicKey import _fastmath 28 25 except: 29 26 _fastmath = None 30 caps["pycrypto.fastmath"] = _fastmath is not None 31 return caps 27 return {"backend" : "pycrypto", 28 "pycrypto" : {"" : True, 29 "version" : Crypto.__version__}, 30 "fastmath" : _fastmath is not None} 32 31 33 32 34 33 def get_key(password, key_salt, block_size, iterations): -
xpra/net/pycryptography_backend.py
65 65 import cryptography 66 66 return {"backend" : "python-cryptography", 67 67 "backends" : [ci(x) for x in getattr(backend, "_backends", [])], 68 "python-cryptography" : True, 69 "python-cryptography.version" : cryptography.__version__} 68 "python-cryptography" : {"" : True, 69 "version" : cryptography.__version__} 70 } 70 71 71 72 def get_key(password, key_salt, block_size, iterations): 72 73 global backend -
xpra/platform/darwin/shadow_server.py
113 113 114 114 def get_info(self, proto): 115 115 info = GTKServerBase.get_info(self, proto) 116 info ["features.shadow"] = True117 info ["server.type"] = "Python/gtk2/osx-shadow"116 info.setdefault("features", {})["shadow"] = True 117 info.setdefault("server", {})["type"] = "Python/gtk2/osx-shadow" 118 118 return info -
xpra/platform/gui.py
150 150 return str(v) 151 151 def fnames(l): 152 152 return [fname(x) for x in l] 153 info ={153 return { 154 154 "native_tray_menu_helpers" : fnames(get_native_tray_menu_helper_classes()), 155 155 "native_trays" : fnames(get_native_tray_classes()), 156 156 "native_system_trays" : fnames(get_native_system_tray_classes()), … … 161 161 "desktops" : get_number_of_desktops(), 162 162 "desktop_names" : get_desktop_names(), 163 163 "vertical-refresh" : get_vrefresh(), 164 "double_click.time" : get_double_click_time(),165 "double_click.distance" : get_double_click_distance(),166 164 "fixed_cursor_size" : get_fixed_cursor_size(), 167 165 "cursor_size" : get_cursor_size(), 168 "dpi.x" : get_xdpi(),169 "dpi.y" : get_ydpi(),170 166 "icon_size" : get_icon_size(), 167 "double_click" : { 168 "time" : get_double_click_time(), 169 "distance" : get_double_click_distance(), 170 }, 171 "dpi" : { 172 "x" : get_xdpi(), 173 "y" : get_ydpi(), 174 }, 175 "antialias" : get_antialias_info(), 176 "window_frame" : get_window_frame_sizes(), 171 177 } 172 from xpra.util import updict173 updict(info, "antialias", get_antialias_info())174 updict(info, "window_frame", get_window_frame_sizes())175 return info176 178 177 179 get_info = get_info_base 178 180 -
xpra/platform/paths.py
206 206 207 207 def get_info(): 208 208 return { 209 "install .prefix" : get_install_prefix(),210 "default_conf .dirs" : get_default_conf_dirs(),211 "system_conf .dirs" : get_system_conf_dirs(),212 "user_conf .dirs" : get_user_conf_dirs(),213 "socket .dirs" : get_socket_dirs(),214 "log .dir" : get_default_log_dir(),215 "download .dir" : get_download_dir(),216 "app .dir" : get_app_dir(),217 "app .default.dir" : default_get_app_dir(),209 "install" : {"prefix" : get_install_prefix()}, 210 "default_conf" : {"dirs" : get_default_conf_dirs()}, 211 "system_conf" : {"dirs" : get_system_conf_dirs()}, 212 "user_conf" : {"dirs" : get_user_conf_dirs()}, 213 "socket" : {"dirs" : get_socket_dirs()}, 214 "log" : {"dir" : get_default_log_dir()}, 215 "download" : {"dir" : get_download_dir()}, 216 "app" : {"dir" : get_app_dir()}, 217 "app" : {"default" : {"dir" : default_get_app_dir()}}, 218 218 "resources" : get_resources_dir(), 219 219 "icons" : get_icon_dir(), 220 220 "home" : os.path.expanduser("~"), -
xpra/platform/printing.py
68 68 69 69 70 70 def get_info(): 71 return { 72 "mimetypes" : get_mimetypes(), 73 "mimetypes.default" : DEFAULT_MIMETYPES, 71 return {"mimetypes" : {"" : get_mimetypes(), 72 "default" : DEFAULT_MIMETYPES} 74 73 } 75 74 76 75 -
xpra/platform/pycups_printing.py
416 416 417 417 def get_info(): 418 418 from xpra.platform.printing import get_mimetypes, DEFAULT_MIMETYPES 419 return { 420 "mimetypes" : get_mimetypes(), 421 "mimetypes.default" : DEFAULT_MIMETYPES, 419 return {"mimetypes" : {"" : get_mimetypes(), 420 "default" : DEFAULT_MIMETYPES, 421 "printers" : MIMETYPE_TO_PRINTER, 422 "ppd" : MIMETYPE_TO_PPD}, 423 "mimetype" : {"default" : DEFAULT_MIMETYPE}, 422 424 "simulate-failure" : SIMULATE_PRINT_FAILURE, 423 425 "allow-user" : ALLOW, 424 426 "raw-mode" : RAW_MODE, 425 427 "generic" : GENERIC, 426 428 "tmpdir" : FORWARDER_TMPDIR, 427 "mimetype.default" : DEFAULT_MIMETYPE,428 429 "lpadmin" : LPADMIN, 429 430 "lpinfo" : LPINFO, 430 431 "forwarder" : FORWARDER_BACKEND, … … 431 432 "skipped-printers" : SKIPPED_PRINTERS, 432 433 "add-local-printers": ADD_LOCAL_PRINTERS, 433 434 "printer-prefix" : PRINTER_PREFIX, 434 "cups-dbus.default" : DEFAULT_CUPS_DBUS, 435 "cups-dbus" : CUPS_DBUS, 436 "cups-dbus.poll-delay" : POLLING_DELAY, 437 "mimetypes.printers": MIMETYPE_TO_PRINTER, 438 "mimetypes.ppd" : MIMETYPE_TO_PPD, 435 "cups-dbus" : {"" : CUPS_DBUS, 436 "default" : DEFAULT_CUPS_DBUS, 437 "poll-delay" : POLLING_DELAY}, 439 438 "cups.default-options" : DEFAULT_CUPS_OPTIONS, 440 "printers .predefined" : UNPROBED_PRINTER_DEFS,441 "printers" : get_printer_definitions(),439 "printers" : {"" : get_printer_definitions(), 440 "predefined" : UNPROBED_PRINTER_DEFS}, 442 441 } 443 442 444 443 -
xpra/platform/win32/keyboard_config.py
36 36 def __repr__(self): 37 37 return "win32.KeyboardConfig" 38 38 39 def get_info(self):40 info = KeyboardConfigBase.get_info(self)41 return info42 39 43 44 40 def parse_options(self, props): 45 41 return KeyboardConfigBase.parse_options(self, props) 46 42 … … 122 118 #no useful mapping: 123 119 "ICO_CLEAR" : "IcoClr", 124 120 "ICO_HELP" : "Help", 121 "DIVIDE" : "KP_Divide", 125 122 "MULTIPLY" : "KP_Multiply", 123 "SUBTRACT" : "KP_Substract", 124 "ADD" : "KP_Add", 126 125 "NONAME" : "NoSymbol", 127 126 "NUMPAD0" : "KP_0", 128 127 "NUMPAD1" : "KP_1", … … 167 166 "OEM_PA1" : "OemPa1", 168 167 "OEM_PA2" : "OemPa2", 169 168 "OEM_PA3" : "OemPa3", 170 "OEM_PLUS" : "plus",169 #"OEM_PLUS" : "equal", 171 170 "OEM_RESET" : "Reset", 172 171 "OEM_WSCTRL" : "WsCtrl", 173 172 "PA1" : "Pa1", 173 "OEM_102" : "backslash", 174 174 #missing:? 175 175 #"PACKET" : "Packet", 176 176 "PLAY" : "Play", … … 263 263 "VOLUME_UP" : "XF86AudioRaiseVolume", 264 264 "XBUTTON1" : "X1", 265 265 "XBUTTON2" : "X2", 266 "BRACKET_LEFT" : "bracketleft", 267 "BRACKET_RIGHT" : "bracketright", 268 "BRACE_LEFT" : "braceleft", 269 "BRACE_RIGHT" : "braceright", 270 "COLON" : "colon", 271 "SEMICOLON" : "semicolon", 272 "APOSTROPHE" : "apostrophe", 273 "AT" : "at", 274 "NUMBER_SIGN" : "numbersign", 275 "COMMA" : "comma", 276 "LESS" : "less", 277 "EQUAL" : "equal", 278 "GREATER" : "greater", 279 "PERIOD" : "period", 280 "SLASH" : "slash", 281 "QUESTION" : "question", 282 "BAR" : "bar", 283 "EXCLAM" : "exclam", 284 "QUOTEDBL" : "quotedbl", 285 "STERLING" : "sterling", 286 "DOLLAR" : "dollar", 287 "PERCENT" : "percent", 288 "ASCIICIRCUM" : "asciicircum", 289 "AMPERSAND" : "ampersand", 290 "ASTERISK" : "asterisk", 291 "PARENLEFT" : "parenleft", 292 "PARENRIGHT" : "parenright", 293 "UNDERSCORE" : "underscore", 294 "BACKSLASH" : "backslash", 295 "GRAVE" : "grave", 266 296 } 267 297 268 298 #these aren't defined in win32con... 269 299 DEFS = { 300 "EXCLAM" : 33, 301 "QUOTEDBL" : 34, 302 "NUMBER_SIGN" : 35, 303 "DOLLAR" : 36, 304 "PERCENT" : 37, 305 "AMPERSAND" : 38, 306 "APOSTROPHE" : 39, 307 "PARENLEFT" : 40, 308 "PARENRIGHT" : 41, 309 "ASTERISK" : 42, 310 "COMMA" : 44, 311 "PERIOD" : 46, 312 "SLASH" : 47, 313 "COLON" : 58, 314 "SEMICOLON" : 59, 315 "LESS" : 60, 316 "EQUAL" : 61, 317 "GREATER" : 62, 318 "QUESTION" : 63, 319 "AT" : 64, 320 "BRACKET_LEFT" : 91, 321 "BACKSLASH" : 92, 322 "BRACKET_RIGHT" : 93, 323 "ASCIICIRCUM" : 94, 324 "UNDERSCORE" : 95, 325 "GRAVE" : 96, 326 "BRACE_LEFT" : 123, 327 "BAR" : 124, 328 "BRACE_RIGHT" : 125, 329 "ASCIITILDE" : 126, 330 "STERLING" : 156, 270 331 "SLEEP" : 0x5F, 271 332 "OEM_FJ_JISHO" : 0x92, 272 333 "OEM_FJ_MASSHOU" : 0x93, … … 313 374 "OEM_FINISH" : 0xF1, 314 375 "OEM_ENLW" : 0xF4, 315 376 "OEM_BACKTAB" : 0xF5, 316 "ASCIITILDE" : 65107, #aka 0x00fe53 377 "ASCIITILDE" : 126, 378 #"ASCIITILDE" : 65107, #aka 0x00fe53 317 379 "DEAD_GRAVE" : 65104, #aka 0x00fe50 318 380 } 319 381 -
xpra/platform/win32/shadow_server.py
393 393 394 394 def get_info(self, proto): 395 395 info = GTKServerBase.get_info(self, proto) 396 info["features.shadow"] = True 397 info["server.type"] = "Python/gtk2/win32-shadow" 398 info["server.tray"] = self.tray 399 info["server.tray-icon"] = self.tray_icon or "" 396 info.setdefault("features", {})["shadow"] = True 397 info.setdefault("server", { 398 "type" : "Python/gtk2/win32-shadow", 399 "tray" : self.tray, 400 "tray-icon" :self.tray_icon or ""}) 400 401 return info 401 402 402 403 -
xpra/platform/xposix/gui.py
15 15 traylog = Logger("posix", "menu") 16 16 menulog = Logger("posix", "menu") 17 17 18 from xpra.util import iround 18 from xpra.util import iround, updict 19 19 from xpra.gtk_common.gobject_compat import get_xid, is_gtk3 20 20 21 21 device_bell = None … … 456 456 s = _get_xsettings() 457 457 if s: 458 458 serial, values = s 459 i["xsettings.serial"] = serial459 xi = {"serial" : serial} 460 460 for _,name,value,_ in values: 461 i["xsettings.%s" % name] = value 462 i["dpi.xsettings"] = _get_xsettings_dpi() 463 i["dpi.randr"] = _get_randr_dpi() 461 xi[name] = value 462 i["xsettings"] = xi 463 i.setdefault("dpi", { 464 "xsettings" : _get_xsettings_dpi(), 465 "randr" : _get_randr_dpi() 466 }) 464 467 return i 465 468 466 469 -
xpra/server/gtk_server_base.py
25 25 gtk_main_quit_on_fatal_exceptions_disable) 26 26 from xpra.server.server_base import ServerBase 27 27 from xpra.gtk_common.gtk_util import get_gtk_version_info, gtk_main 28 from xpra.util import updict29 28 30 29 31 30 class GTKServerBase(ServerBase): … … 88 87 89 88 def do_get_info(self, proto, *args): 90 89 info = ServerBase.do_get_info(self, proto, *args) 91 updict(info, "server", get_gtk_version_info())92 info.update({93 "server.type" : "Python/gtk-x11",94 "features.randr" : self.randr})90 vi = get_gtk_version_info() 91 vi["type"] = "Python/gtk-x11" 92 info.setdefault("server", {}).update(vi) 93 info.setdefault("features", {})["randr"] = self.randr 95 94 return info 96 95 97 96 def get_root_window_size(self): -
xpra/server/proxy/proxy_instance_process.py
352 352 353 353 354 354 def get_proxy_info(self, proto): 355 info = {"proxy.version" : local_version} 356 def upp(d): 357 updict(info, "proxy", d) 358 upp(get_server_info()) 359 upp(get_thread_info(proto)) 355 sinfo = {} 356 sinfo.update(get_server_info()) 357 sinfo.update(get_thread_info(proto)) 358 info = {"proxy" : { 359 "version" : local_version, 360 "" : sinfo, 361 } 362 } 360 363 info.update(self.get_encoder_info()) 361 364 return info 362 365 -
xpra/server/proxy/proxy_server.py
257 257 i = 0 258 258 for p,v in self.processes.items(): 259 259 d,_ = v 260 info[ "proxy[%s].display" % i] = d261 info["proxy[%s].live" % i] = p.is_alive()262 info["proxy[%s].pid" % i] = p.pid260 info[i] = {"display" : d, 261 "live" : p.is_alive(), 262 "pid" : p.pid} 263 263 i += 1 264 264 info["proxies"] = len(self.processes) 265 265 return info -
xpra/server/server_base.py
1772 1772 "y" : self.ydpi 1773 1773 }) 1774 1774 updict(info, "antialias", self.antialias) 1775 info["cursor .size"] = self.cursor_size1775 info["cursor"] = {"size" : self.cursor_size} 1776 1776 log("get_info took %.1fms", 1000.0*(time.time()-start)) 1777 1777 return info 1778 1778 … … 1835 1835 "repeat.interval" : self.key_repeat_interval, 1836 1836 "keys_pressed" : self.keys_pressed.values(), 1837 1837 "modifiers" : self.xkbmap_mod_meanings} 1838 if self.keyboard_config: 1839 for k,v in self.keyboard_config.get_info().items(): 1840 if v is not None: 1841 info[k] = v 1838 kc = self.keyboard_config 1839 if kc: 1840 info.update(kc.get_info()) 1842 1841 return info 1843 1842 1844 1843 def get_clipboard_info(self): … … 1851 1850 "virtual-video-devices" : self.virtual_video_devices} 1852 1851 1853 1852 def do_get_info(self, proto, server_sources=None, window_ids=None): 1854 info = {"server .python.version" : python_platform.python_version()}1853 info = {"server" : {"python" : {"version" : python_platform.python_version()}}} 1855 1854 1856 1855 def up(prefix, d, suffix=""): 1857 1856 updict(info, prefix, d, suffix) … … 1870 1869 1871 1870 info["windows"] = len([window for window in list(self._id_to_window.values()) if window.is_managed()]) 1872 1871 # other clients: 1873 info["clients"] = len([p for p in self._server_sources.keys() if p!=proto])1874 info["clients.unauthenticated"] = len([p for p in self._potential_protocols if ((p is not proto) and (p not in self._server_sources.keys()))])1872 info["clients"] = {"" : len([p for p in self._server_sources.keys() if p!=proto]), 1873 "unauthenticated" : len([p for p in self._potential_protocols if ((p is not proto) and (p not in self._server_sources.keys()))])} 1875 1874 #find the server source to report on: 1876 1875 n = len(server_sources or []) 1877 1876 if n==1: … … 1879 1878 up("client", ss.get_info()) 1880 1879 info.update(ss.get_window_info(window_ids)) 1881 1880 elif n>1: 1881 cinfo = {} 1882 1882 for i, ss in enumerate(server_sources): 1883 up("client[%i]" % i, ss.get_info()) 1884 wi = ss.get_window_info(window_ids) 1885 up("client[%i]" % i, wi) 1886 #this means that the last source overrides previous ones 1887 #(bad decision was made on the namespace for this..) 1888 info.update(wi) 1883 sinfo = ss.get_info() 1884 sinfo.update(ss.get_window_info(window_ids)) 1885 cinfo[i] = sinfo 1886 up("client", cinfo) 1889 1887 return info 1890 1888 1891 1889 def add_windows_info(self, info, window_ids): 1890 winfo = {} 1892 1891 for wid, window in self._id_to_window.items(): 1893 1892 if window_ids is not None and wid not in window_ids: 1894 1893 continue 1895 for k,v in self.get_window_info(window).items(): 1896 wp = "window[%s]." % wid 1897 info[wp + k] = v 1894 winfo[wid] = self.get_window_info(window) 1895 updict(info, "window", winfo) 1898 1896 1899 1897 def get_window_info(self, window): 1900 1898 from xpra.server.source import make_window_metadata -
xpra/server/server_core.py
40 40 from xpra.make_thread import make_thread 41 41 from xpra.scripts.fdproxy import XpraProxy 42 42 from xpra.server.control_command import ControlError, HelloCommand, HelpCommand, DebugControl 43 from xpra.util import csv, typedict, updict, repr_ellipsized, dump_all_frames, \43 from xpra.util import csv, typedict, updict, flatten_dict, repr_ellipsized, dump_all_frames, \ 44 44 SERVER_SHUTDOWN, SERVER_UPGRADE, LOGIN_TIMEOUT, DONE, PROTOCOL_ERROR, SERVER_ERROR, VERSION_ERROR, CLIENT_REQUEST 45 45 46 46 main_thread = threading.current_thread() … … 877 877 self.get_all_info(self.do_send_info, proto) 878 878 879 879 def do_send_info(self, proto, info): 880 proto.send_now(("hello", info))880 proto.send_now(("hello", flatten_dict(info))) 881 881 882 882 def get_all_info(self, callback, proto=None, *args): 883 883 ui_info = self.get_ui_info(proto, *args) … … 928 928 "executable" : sys.executable, 929 929 }) 930 930 if self.session_name: 931 info["session .name"] = self.session_name931 info["session"] = {"name" : self.session_name} 932 932 if self.child_reaper: 933 933 info.update(self.child_reaper.get_info()) 934 934 return info -
xpra/server/source.py
41 41 from xpra.make_thread import make_thread 42 42 from xpra.os_util import platform_name, Queue, get_machine_id, get_user_uuid 43 43 from xpra.server.background_worker import add_work_item 44 from xpra.util import csv, std, typedict, updict, get_screen_info, CLIENT_PING_TIMEOUT, WORKSPACE_UNSET, DEFAULT_METADATA_SUPPORTED44 from xpra.util import csv, std, typedict, updict, flatten_dict, notypedict, get_screen_info, CLIENT_PING_TIMEOUT, WORKSPACE_UNSET, DEFAULT_METADATA_SUPPORTED 45 45 46 46 47 47 NOYIELD = os.environ.get("XPRA_YIELD") is None … … 371 371 self.client_release = None 372 372 self.client_proxy = False 373 373 self.auto_refresh_delay = 0 374 self.info_namespace = False 374 375 self.send_cursors = False 375 376 self.send_bell = False 376 377 self.send_notifications = False … … 665 666 self.lzo = c.boolget("lzo", False) and compression.use_lzo 666 667 self.send_windows = self.ui_client and c.boolget("windows", True) 667 668 self.pointer_grabs = c.boolget("pointer.grabs") 669 self.info_namespace = c.boolget("info-namespace") 668 670 self.send_cursors = self.send_windows and c.boolget("cursors") 669 671 self.send_bell = c.boolget("bell") 670 672 self.send_notifications = c.boolget("notifications") … … 1350 1352 "suspended" : self.suspended, 1351 1353 } 1352 1354 if self.desktop_size_unscaled: 1353 info["desktop_size .unscaled"] = self.desktop_size_unscaled1355 info["desktop_size"] = {"unscaled" : self.desktop_size_unscaled} 1354 1356 1355 1357 def addattr(k, name): 1356 1358 v = getattr(self, name) … … 1360 1362 addattr(x, "client_"+x) 1361 1363 #encoding: 1362 1364 info.update({ 1363 "encodings" : self.encodings, 1364 "encodings.core" : self.core_encodings, 1365 "encoding.default" : self.default_encoding or "" 1366 }) 1367 def up(prefix, d): 1368 updict(info, prefix, d) 1369 up("encoding", self.default_encoding_options) 1370 up("encoding", self.encoding_options) 1371 up("icons", self.icons_encoding_options) 1372 up("connection", self.protocol.get_info()) 1373 up("av-sync", {"client.delay" : self.av_sync_delay, 1374 "total" : self.av_sync_delay_total, 1375 "delta" : self.av_sync_delta}) 1365 "encodings" : { 1366 "" : self.encodings, 1367 "core" : self.core_encodings 1368 }, 1369 "icons" : self.icons_encoding_options, 1370 "connection" : self.protocol.get_info(), 1371 "av-sync" : { 1372 "client" : {"delay" : self.av_sync_delay}, 1373 "total" : self.av_sync_delay_total, 1374 "delta" : self.av_sync_delta, 1375 }, 1376 }) 1377 einfo = {"default" : self.default_encoding or ""} 1378 einfo.update(self.default_encoding_options) 1379 einfo.update(self.encoding_options) 1380 info.setdefault("encoding", {}).update(einfo) 1376 1381 if self.window_frame_sizes: 1377 up("window.frame-sizes", self.window_frame_sizes)1382 info.setdefault("window", {}).update({"frame-sizes" : self.window_frame_sizes}) 1378 1383 if self.window_filters: 1379 1384 i = 0 1385 finfo = {} 1380 1386 for uuid, f in self.window_filters: 1381 1387 if uuid==self.uuid: 1382 info["window-filter[%i]" %i] = str(f)1388 finfo[i] = str(f) 1383 1389 i += 1 1390 info["window-filter"] = finfo 1384 1391 info.update(self.get_sound_info()) 1385 1392 info.update(self.get_features_info()) 1386 1393 info.update(self.get_screen_info()) … … 1420 1427 if prop is None: 1421 1428 return {"state" : "inactive"} 1422 1429 return prop.get_info() 1423 info = {} 1430 info = { 1431 "speaker" : sound_info(self.supports_speaker, self.sound_source), 1432 "microphone" : sound_info(self.supports_microphone, self.sound_sink), 1433 } 1424 1434 for prop in ("pulseaudio_id", "pulseaudio_server"): 1425 1435 v = getattr(self, prop) 1426 1436 if v is not None: 1427 1437 info[prop] = v 1428 for k,v in sound_info(self.supports_speaker, self.sound_source).items():1429 info["speaker.%s" % k] = v1430 for k,v in sound_info(self.supports_microphone, self.sound_sink).items():1431 info["microphone.%s" % k] = v1432 1438 return info 1433 1439 1434 1440 def get_window_info(self, window_ids=[]): … … 1435 1441 """ 1436 1442 Adds encoding and window specific information 1437 1443 """ 1438 info = { 1439 "damage.compression_queue.size.current" : self.encode_work_queue.qsize(), 1440 "damage.packet_queue.size.current" : len(self.packet_queue), 1441 } 1444 info = {"damage" : { 1445 "compression_queue" : {"size" : {"current" : self.encode_work_queue.qsize()}}, 1446 "packet_queue" : {"size" : {"current" : len(self.packet_queue)}}, 1447 }, 1448 "batch" : self.global_batch_config.get_info(), 1449 } 1442 1450 qpixels = [x[2] for x in list(self.packet_queue)] 1443 1451 add_list_stats(info, "packet_queue_pixels", qpixels) 1444 1452 if len(qpixels)>0: 1445 info["packet_queue_pixels .current"] = qpixels[-1]1453 info["packet_queue_pixels"] = {"current" : qpixels[-1]} 1446 1454 1447 1455 info.update(self.statistics.get_info()) 1448 1456 … … 1450 1458 total_pixels = 0 1451 1459 total_time = 0.0 1452 1460 in_latencies, out_latencies = [], [] 1461 winfo = {} 1453 1462 for wid in window_ids: 1454 1463 ws = self.window_sources.get(wid) 1455 1464 if ws is None: 1456 1465 continue 1457 1466 #per-window source stats: 1458 updict(info, "window[%i]" % wid, ws.get_info())1467 winfo[wid] = ws.get_info() 1459 1468 #collect stats for global averages: 1460 1469 for _, _, pixels, _, _, encoding_time in list(ws.statistics.encoding_stats): 1461 1470 total_pixels += pixels … … 1462 1471 total_time += encoding_time 1463 1472 in_latencies += [x*1000 for _, _, _, x in list(ws.statistics.damage_in_latency)] 1464 1473 out_latencies += [x*1000 for _, _, _, x in list(ws.statistics.damage_out_latency)] 1474 info["window"] = winfo 1465 1475 v = 0 1466 1476 if total_time>0: 1467 1477 v = int(total_pixels / total_time) 1468 info ["encoding.pixels_encoded_per_second"] = v1478 info.setdefault("encoding", {})["pixels_encoded_per_second"] = v 1469 1479 add_list_stats(info, "damage.in_latency", in_latencies, show_percentile=[9]) 1470 1480 add_list_stats(info, "damage.out_latency", out_latencies, show_percentile=[9]) 1471 updict(info, "batch", self.global_batch_config.get_info())1472 1481 return info 1473 1482 1474 1483 1475 1484 def send_info_response(self, info): 1476 self.send("info-response", info) 1485 if self.info_namespace: 1486 v = notypedict(info) 1487 else: 1488 v = flatten_dict(info) 1489 self.send("info-response", v) 1477 1490 1478 1491 1479 1492 def send_server_event(self, *args): -
xpra/server/source_stats.py
144 144 145 145 146 146 def get_info(self): 147 info = { 148 "damage.events" : self.damage_events_count, 149 "damage.packets_sent" : self.packet_count, 150 "encoding.decode_errors" : self.decode_errors, 147 info = {"damage" : { 148 "events" : self.damage_events_count, 149 "packets_sent" : self.packet_count, 150 }, 151 "encoding" : {"decode_errors" : self.decode_errors}, 151 152 } 152 153 qsizes = [x for _,x in list(self.compression_work_qsizes)] 153 154 add_list_stats(info, "damage.data_queue.size", qsizes) -
xpra/server/window/window_source.py
47 47 LOG_THEME_DEFAULT_ICONS = os.environ.get("XPRA_LOG_THEME_DEFAULT_ICONS", "0")=="1" 48 48 49 49 50 from xpra.util import updict51 50 from xpra.os_util import StringIOClass, memoryview_to_bytes 52 51 from xpra.server.window.window_stats import WindowPerformanceStatistics 53 52 from xpra.server.window.batch_config import DamageBatchConfig … … 316 315 """ 317 316 Add window specific stats 318 317 """ 318 #"encoding" info: 319 einfo = self.get_quality_speed_info() 320 einfo.update({ 321 "" : self.encoding, 322 "lossless_threshold" : { 323 "base" : self._lossless_threshold_base, 324 "pixel_boost" : self._lossless_threshold_pixel_boost 325 }, 326 }) 327 try: 328 #ie: get_strict_encoding -> "strict_encoding" 329 einfo["selection"] = self.get_best_encoding.__name__.replace("get_", "") 330 except: 331 pass 332 333 #"encodings" info: 334 esinfo = { 335 "" : self.encodings, 336 "core" : self.core_encodings, 337 "auto-refresh" : self.client_refresh_encodings, 338 } 339 larm = self.last_auto_refresh_message 340 if larm: 341 esinfo = {"auto-refresh" : { 342 "last-event" : { 343 "elapsed" : int(1000*(time.time()-larm[0])), 344 "message" : larm[1], 345 } 346 } 347 } 348 349 now = time.time() 350 buckets_info = {} 351 for i,x in enumerate(self.delta_pixel_data): 352 if x: 353 w, h, pixel_format, coding, store, buflen, _, hits, last_used = x 354 buckets_info[i] = w, h, pixel_format, coding, store, buflen, hits, int((now-last_used)*1000) 319 355 info = { 320 356 "dimensions" : self.window_dimensions, 321 "encoding" : self.encoding, 322 "suspended" : self.suspended or False 323 } 324 def up(prefix, d): 325 updict(info, prefix, d) 326 327 up("av-sync", {"current" : self.av_sync_delay, 328 "target" : self.av_sync_delay_target}) 329 #heuristics 330 up("encoding.lossless_threshold", { 331 "base" : self._lossless_threshold_base, 332 "pixel_boost" : self._lossless_threshold_pixel_boost}) 333 up("encoding", { 357 "suspended" : self.suspended or False, 358 "av-sync" : { 359 "current" : self.av_sync_delay, 360 "target" : self.av_sync_delay_target 361 }, 362 "encoding" : einfo, 363 "encodings" : esinfo, 334 364 "rgb_threshold" : self._rgb_auto_threshold, 335 365 "mmap" : bool(self._mmap) and (self._mmap_size>0), 336 366 "last_used" : self.encoding_last_used or "", 337 367 "full-frames-only" : self.full_frames_only, 338 368 "supports-transparency" : self.supports_transparency, 339 "delta" : self.supports_delta, 340 "delta.buckets" : self.delta_buckets, 341 }) 369 "delta" : {"" : self.supports_delta, 370 "buckets" : self.delta_buckets, 371 "bucket" : buckets_info, 372 }, 373 "property" : self.get_property_info(), 374 "batch" : self.batch_config.get_info(), 375 "soft-timeout" : { 376 "expired" : self.soft_expired, 377 "max" : self.max_soft_expired, 378 }, 379 "rgb_formats" : self.rgb_formats, 380 "icons" : self.icons_encoding_options, 381 } 342 382 if self.pixel_format: 343 383 info["pixel-format"] = self.pixel_format 344 now = time.time()345 for i,x in enumerate(self.delta_pixel_data):346 if x:347 w, h, pixel_format, coding, store, buflen, _, hits, last_used = x348 info["encoding.delta.bucket[%s]" % i] = w, h, pixel_format, coding, store, buflen, hits, int((now-last_used)*1000)349 up("encoding", self.get_quality_speed_info())350 try:351 #ie: get_strict_encoding -> "strict_encoding"352 info["encoding.selection"] = self.get_best_encoding.__name__.replace("get_", "")353 except:354 pass355 up("property", self.get_property_info())356 up("batch", self.batch_config.get_info())357 up("soft-timeout", {358 "expired" : self.soft_expired,359 "max" : self.max_soft_expired360 })361 up("encodings", {362 "" : self.encodings,363 "core" : self.core_encodings,364 "auto-refresh" : self.client_refresh_encodings,365 "rgb_formats" : self.rgb_formats,366 })367 larm = self.last_auto_refresh_message368 if larm:369 up("encodings.auto-refresh.last-event", {370 "elapsed" : int(1000*(time.time()-larm[0])),371 "message" : larm[1],372 })373 up("icons", self.icons_encoding_options)374 384 idata = self.window_icon_data 375 385 if idata: 376 386 pixel_data, stride, w, h = idata 377 up("icon", { 378 "width" : w, 379 "height" : h, 380 "stride" : stride, 381 "bytes" : len(pixel_data) 382 }) 383 387 info["icon"] = { 388 "width" : w, 389 "height" : h, 390 "stride" : stride, 391 "bytes" : len(pixel_data) 392 } 384 393 info.update(self.statistics.get_info()) 385 394 return info 386 395 -
xpra/server/window/window_stats.py
153 153 154 154 155 155 def get_info(self): 156 info = { 157 "damage.events" : self.damage_events_count,158 "damage.packets_sent" : self.packet_count}156 info = {"damage" : {"events" : self.damage_events_count, 157 "packets_sent" : self.packet_count} 158 } 159 159 #encoding stats: 160 160 if len(self.encoding_stats)>0: 161 161 estats = list(self.encoding_stats) -
xpra/server/window/window_video_source.py
15 15 from xpra.server.window.region import merge_all #@UnresolvedImport 16 16 from xpra.server.window.video_subregion import VideoSubregion 17 17 from xpra.codecs.loader import PREFERED_ENCODING_ORDER, EDGE_ENCODING_ORDER 18 from xpra.util import updict,parse_scaling_value, engs18 from xpra.util import parse_scaling_value, engs 19 19 from xpra.log import Logger 20 20 21 21 log = Logger("encoding") … … 144 144 145 145 def get_info(self): 146 146 info = WindowSource.get_info(self) 147 def up(prefix, d):148 updict(info, prefix, d)149 147 sr = self.video_subregion 150 148 if sr: 151 up("video_subregion", sr.get_info())149 info["video_subregion"] = sr.get_info() 152 150 info["scaling"] = self.actual_scaling 153 151 csce = self._csc_encoder 154 152 if csce: 155 info["csc"] = csce.get_type() 156 up("csc", csce.get_info()) 153 info["csc"] = csce.get_info() 157 154 ve = self._video_encoder 158 155 if ve: 159 info["encoder"] = ve.get_type() 160 up("encoder", ve.get_info()) 161 up("encoding.pipeline_param", self.get_pipeline_info()) 162 info["encodings.non-video"] = self.non_video_encodings 163 info["encodings.edge"] = self.edge_encoding or "" 156 info["encoder"] = ve.get_info() 157 info.setdefault("encodings", {}).update({ 158 "non-video" : self.non_video_encodings, 159 "edge" : self.edge_encoding or "", 160 }) 161 einfo = {"pipeline_param" : self.get_pipeline_info()} 164 162 if self._last_pipeline_check>0: 165 info["encoding.pipeline_last_check"] = int(1000*(time.time()-self._last_pipeline_check))163 einfo["pipeline_last_check"] = int(1000*(time.time()-self._last_pipeline_check)) 166 164 lps = self.last_pipeline_scores 167 165 if lps: 166 popts = {} 168 167 for i, lp in enumerate(lps): 169 up("encoding.pipeline_option[%s]" % i, self.get_pipeline_score_info(*lp)) 168 popts[i] = self.get_pipeline_score_info(*lp) 169 einfo["pipeline_option"] = popts 170 info.setdefault("encoding", {}).update(einfo) 170 171 return info 171 172 172 173 def get_pipeline_info(self): -
xpra/simple_stats.py
7 7 # Simple statistical functions 8 8 9 9 from math import sqrt, pow 10 from xpra.util import updict 10 11 11 12 def to_std_unit(v, unit=1000): 12 13 if v>=unit**3: … … 69 70 return values_to_scaled_values(absolute_to_diff_values(data), scale_unit=scale_unit, min_scaled_value=min_scaled_value, num_values=num_values) 70 71 71 72 def add_weighted_list_stats(info, basename, weighted_values, show_percentile=False): 73 updict(info, basename, get_weighted_list_stats(weighted_values, show_percentile)) 74 75 def get_weighted_list_stats(weighted_values, show_percentile=False): 72 76 values = [x for x, _ in weighted_values] 73 77 if len(values)==0: 74 return 75 info["%s.min" % basename] = int(min(values)) 76 info["%s.max" % basename] = int(max(values)) 78 return {} 77 79 #weighted mean: 78 80 tw = 0 79 81 tv = 0 … … 81 83 tw += w 82 84 tv += v * w 83 85 avg = tv/tw 84 info["%s.avg" % basename] = int(avg) 86 stats = { 87 "min" : int(min(values)), 88 "max" : int(max(values)), 89 "avg" : int(avg), 90 } 85 91 if show_percentile: 86 92 #percentile 87 93 svalues = sorted(values) … … 88 94 for i in range(1,10): 89 95 pct = i*10 90 96 index = len(values)*i//10 91 info["%s.%sp" % (basename, pct)] = int(svalues[index]) 97 stats["%ip" % pct] = int(svalues[index]) 98 return stats 92 99 100 93 101 def find_invpow(x, n): 94 102 """Finds the integer component of the n'th root of x, 95 103 an integer such that y ** n <= x < (y + 1) ** n. … … 109 117 return mid + 1 110 118 111 119 def add_list_stats(info, basename, in_values, show_percentile=[5, 8, 9], show_dev=False): 120 updict(info, basename, get_list_stats(in_values, show_percentile, show_dev)) 121 122 def get_list_stats(in_values, show_percentile=[5, 8, 9], show_dev=False): 112 123 #this may be backed by a deque/list whichi is used by other threads 113 124 #so make a copy before use: 114 125 values = list(in_values) 115 126 if len(values)==0: 116 return 117 info["%s.cur" % basename] = int(values[-1]) 118 info["%s.min" % basename] = int(min(values)) 119 info["%s.max" % basename] = int(max(values)) 127 return {} 120 128 #arithmetic mean 121 129 avg = sum(values)/len(values) 122 info["%s.avg" % basename] = int(avg) 130 lstats = { 131 "cur" : int(values[-1]), 132 "min" : int(min(values)), 133 "max" : int(max(values)), 134 "avg" : int(avg), 135 } 123 136 if show_dev: 124 137 p = 1 #geometric mean 125 138 h = 0 #harmonic mean … … 133 146 var += (x-avg)**2 134 147 #standard deviation: 135 148 std = sqrt(var/len(values)) 136 info["%s.std" % basename] = int(std)149 lstats["std"] = int(std) 137 150 if avg!=0: 138 151 #coefficient of variation 139 info["%s.cv_pct" % basename] = int(100.0*std/avg)152 lstats["cv_pct"] = int(100.0*std/avg) 140 153 if counter>0 and p<float('inf'): 141 154 #geometric mean 142 155 try: … … 143 156 v = int(pow(p, 1.0/counter)) 144 157 except OverflowError: 145 158 v = find_invpow(p, counter) 146 info["%s.gm" % basename] = v159 lstats["gm"] = v 147 160 if h!=0: 148 161 #harmonic mean 149 info["%s.h" % basename] = int(counter/h)162 lstats["h"] = int(counter/h) 150 163 if show_percentile: 151 164 #percentile 152 165 svalues = sorted(values) … … 153 166 for i in show_percentile: 154 167 pct = i*10 155 168 index = len(values)*i//10 156 info["%s.%sp" % (basename, pct)] = int(svalues[index]) 169 lstats["%ip" % pct] = int(svalues[index]) 170 return lstats -
xpra/sound/pulseaudio/pulseaudio_pactl_util.py
174 174 175 175 176 176 def get_info(): 177 info = {178 "pulseaudio.wrapper": "pactl",179 "pulseaudio.found" : has_pa(),180 "pulseaudio.id" : get_pulse_id(),181 "pulseaudio.server" : get_pulse_server(False),182 }183 177 i = 0 178 dinfo = {} 184 179 for monitors in (True, False): 185 180 for io in (True, False): 186 181 devices = get_pa_device_options(monitors, io, log_errors=False) 187 182 for d,name in devices.items(): 188 info["device.%s" %d] = name183 dinfo[d] = name 189 184 i += 1 190 info["devices"] = i 191 return info 185 return { 186 "device" : dinfo, 187 "devices" : i, 188 "pulseaudio" : { 189 "wrapper" : "pactl", 190 "found" : has_pa(), 191 "id" : get_pulse_id(), 192 "server" : get_pulse_server(False), 193 } 194 } 192 195 193 196 194 197 def main(): -
xpra/sound/sink.py
14 14 MP3, CODEC_ORDER, gst, QUEUE_LEAK, GST_QUEUE_NO_LEAK, MS_TO_NS 15 15 16 16 from xpra.scripts.config import InitExit 17 from xpra.util import updict,csv17 from xpra.util import csv 18 18 from xpra.os_util import thread 19 19 from xpra.log import Logger 20 20 log = Logger("sound") … … 251 251 clt = self.queue.get_property("current-level-time") 252 252 qmax = self.queue.get_property("max-size-time") 253 253 qmin = self.queue.get_property("min-threshold-time") 254 updict(info, "queue", { 255 "min" : qmin//MS_TO_NS, 256 "max" : qmax//MS_TO_NS, 257 "cur" : clt//MS_TO_NS, 258 "pct" : min(QUEUE_TIME, clt)*100//qmax, 259 "overruns" : self.overruns, 260 "underruns" : self.underruns, 261 "state" : self.queue_state}) 254 info["queue"] = { 255 "min" : qmin//MS_TO_NS, 256 "max" : qmax//MS_TO_NS, 257 "cur" : clt//MS_TO_NS, 258 "pct" : min(QUEUE_TIME, clt)*100//qmax, 259 "overruns" : self.overruns, 260 "underruns" : self.underruns, 261 "state" : self.queue_state 262 } 262 263 return info 263 264 264 265 def add_data(self, data, metadata=None): -
xpra/sound/src.py
173 173 if self.caps: 174 174 info["caps"] = self.caps 175 175 if self.queue: 176 info["queue .cur"] = self.queue.get_property("current-level-time")//MS_TO_NS176 info["queue"] = {"cur" : self.queue.get_property("current-level-time")//MS_TO_NS} 177 177 if self.buffer_latency: 178 178 for x in ("actual-buffer-time", "actual-latency-time"): 179 179 v = self.src.get_property(x) -
xpra/util.py
500 500 return int(v+0.5) 501 501 502 502 503 def notypedict(info): 504 def ntd(d): 505 for k in list(d.keys()): 506 v = d[k] 507 if isinstance(v, dict): 508 d[k] = ntd(v) 509 return dict(d) 510 return ntd(info) 511 512 def flatten_dict(info): 513 to = {} 514 def add_dict(path, d): 515 for k,v in d.items(): 516 if path: 517 npath = path+"."+str(k) 518 else: 519 npath = str(k) 520 if isinstance(v, dict): 521 add_dict(npath, v) 522 elif v is not None: 523 to[npath] = v 524 add_dict(None, info) 525 return to 526 503 527 #used for merging dicts with a prefix and suffix 504 528 #non-None values get added to <todict> with a prefix and optional suffix 505 529 def updict(todict, prefix, d, suffix=""): -
xpra/x11/server.py
287 287 288 288 def do_get_info(self, proto, server_sources, window_ids): 289 289 info = X11ServerBase.do_get_info(self, proto, server_sources, window_ids) 290 info["focused"] = self._has_focus291 info["grabbed"] = self._has_grab292 290 log("do_get_info: adding cursor=%s", self.last_cursor_data) 291 info.update({ 292 "focused" : self._has_focus, 293 "grabbed" : self._has_grab, 294 "cursor" : self.get_cursor_info(), 295 }) 296 return info 297 298 def get_cursor_info(self): 299 #(NOT from UI thread) 293 300 #copy to prevent race: 294 301 cd = self.last_cursor_data 295 302 if cd is None: 296 info["cursor"] = "None" 297 else: 298 info["cursor.is_default"] = bool(self.default_cursor_data and len(self.default_cursor_data)>=8 and len(cd)>=8 and cd[7]==cd[7]) 299 #all but pixels: 300 for i, x in enumerate(("x", "y", "width", "height", "xhot", "yhot", "serial", None, "name")): 301 if x: 302 v = cd[i] or "" 303 info["cursor." + x] = v 304 return info 303 return {"" : "None"} 304 cinfo = {"is_default" : bool(self.default_cursor_data and len(self.default_cursor_data)>=8 and len(cd)>=8 and cd[7]==cd[7])} 305 #all but pixels: 306 for i, x in enumerate(("x", "y", "width", "height", "xhot", "yhot", "serial", None, "name")): 307 if x: 308 v = cd[i] or "" 309 cinfo[x] = v 310 return cinfo 305 311 306 312 def get_ui_info(self, proto, wids=None, *args): 307 313 info = X11ServerBase.get_ui_info(self, proto, wids, *args) … … 309 315 wm = self._wm 310 316 if wm: 311 317 info["window-manager-name"] = wm.get_net_wm_name() 318 info.setdefault("cursor", {}).update(self.get_ui_cursor_info()) 319 return info 320 321 def get_ui_cursor_info(self): 322 #(from UI thread) 312 323 #now cursor size info: 313 324 display = gtk.gdk.display_get_default() 314 325 pos = display.get_default_screen().get_root_window().get_pointer()[:2] 315 info["cursor.position"] = pos326 cinfo = {"position" : pos} 316 327 for prop, size in {"default" : display.get_default_cursor_size(), 317 328 "max" : display.get_maximal_cursor_size()}.items(): 318 329 if size is None: 319 330 continue 320 info["cursor.%s_size" % prop] = size321 return info331 cinfo["%s_size" % prop] = size 332 return cinfo 322 333 323 334 324 335 def get_window_info(self, window): 325 336 info = X11ServerBase.get_window_info(self, window) 326 info["focused"] = self._has_focus and self._window_to_id.get(window, -1)==self._has_focus 327 info["grabbed"] = self._has_grab and self._window_to_id.get(window, -1)==self._has_grab 328 info["geometry"] = window.get_property("geometry") 329 info["shown"] = self._desktop_manager.is_shown(window) 337 info.update({ 338 "focused" : self._has_focus and self._window_to_id.get(window, -1)==self._has_focus, 339 "grabbed" : self._has_grab and self._window_to_id.get(window, -1)==self._has_grab, 340 "geometry" : window.get_property("geometry"), 341 "shown" : self._desktop_manager.is_shown(window), 342 }) 330 343 try: 331 344 info["client-geometry"] = self._desktop_manager.window_geometry(window) 332 345 except: -
xpra/x11/server_keyboard_config.py
65 65 66 66 def get_info(self): 67 67 info = KeyboardConfigBase.get_info(self) 68 info["modifiers.filter"] = self.modifiers_filter69 68 #keycodes: 70 69 if self.keycode_translation: 71 70 for kc, keycode in self.keycode_translation.items(): … … 82 81 info["keymap.%s" % i] = (keyval, name, keycode, group, level) 83 82 i += 1 84 83 #modifiers: 84 modinfo = {} 85 modsinfo = {} 86 modinfo["filter"] = self.modifiers_filter 85 87 if self.modifier_client_keycodes: 86 88 for mod, keys in self.modifier_client_keycodes.items(): 87 info["modifier." + mod + ".client_keys"] = keys89 modinfo.setdefault(mod, {})["client_keys"] = keys 88 90 if self.keynames_for_mod: 89 91 for mod, keys in self.keynames_for_mod.items(): 90 info["modifier." + mod + ".keys"] = tuple(keys)92 modinfo.setdefault(mod, {})["keys"] = tuple(keys) 91 93 if self.keycodes_for_modifier_keynames: 92 94 for mod, keys in self.keycodes_for_modifier_keynames.items(): 93 info["modifier." + mod + ".keycodes"] = tuple(keys)95 modinfo.setdefault(mod, {})["keycodes"] = tuple(keys) 94 96 if self.xkbmap_mod_meanings: 95 97 for mod, mod_name in self.xkbmap_mod_meanings.items(): 96 info["modifier." + mod ] = mod_name 97 if self.xkbmap_x11_keycodes: 98 for keycode, keysyms in self.xkbmap_x11_keycodes.items(): 99 info["x11_keycode." + str(keycode) ] = keysyms 98 modinfo[mod] = mod_name 99 info["x11_keycode"] = self.xkbmap_x11_keycodes 100 100 for x in ("print", "layout", "variant"): 101 101 v = getattr(self, "xkbmap_"+x) 102 102 if v: … … 104 104 for x in ("nuisance", ): 105 105 v = getattr(self, "xkbmap_mod_"+x) 106 106 if v: 107 info["modifiers."+x] = list(v)107 modsinfo[x] = list(v) 108 108 for x in ("managed", "pointermissing"): 109 109 v = getattr(self, "xkbmap_mod_"+x) 110 110 if v: 111 info["modifiers."+x] = v 111 modsinfo[x] = v 112 info["modifier"] = modinfo 113 info["modifiers"] = modsinfo 112 114 log("keyboard info: %s", "\n".join(["%s=%s" % (k,v) for k,v in info.items()])) 113 115 return info 114 116 -
xpra/x11/shadow_x11_server.py
95 95 96 96 def get_info(self, proto): 97 97 info = X11ServerBase.get_info(self, proto) 98 info ["features.shadow"] = True99 info ["server.type"] = "Python/gtk2/x11-shadow"98 info.setdefault("features", {})["shadow"] = True 99 info.setdefault("server", {})["type"] = "Python/gtk2/x11-shadow" 100 100 return info -
xpra/x11/x11_server_base.py
127 127 v = parts[1].strip() 128 128 self.opengl_props[k] = v 129 129 else: 130 self.opengl_props["error"] = str(err) 130 self.opengl_props["error"] = str(err).strip("\n\r") 131 131 except Exception as e: 132 132 gllog.warn("Warning: failed to query OpenGL properties") 133 133 gllog.warn(" %s", e) … … 214 214 return capabilities 215 215 216 216 def do_get_info(self, proto, server_sources, window_ids): 217 from xpra.util import updict218 217 info = GTKServerBase.do_get_info(self, proto, server_sources, window_ids) 219 218 if self.opengl_props: 220 updict(info, "opengl", self.opengl_props) 221 info["server.type"] = "Python/gtk/x11" 219 info["opengl"] = self.opengl_props 220 #this is added here because the server keyboard config doesn't know about "keys_pressed".. 221 info["keyboard"] = { 222 "state" : {"keys_pressed" : list(self.keys_pressed.keys())}, 223 "fast-switching" : True, 224 } 222 225 try: 226 fx = find_libfakeXinerama() 227 except: 228 fx = None 229 sinfo = {"type" : "Python/gtk/x11", 230 "fakeXinerama" : self.fake_xinerama and bool(fx), 231 "libfakeXinerama" : fx or "", 232 "Xkb" : X11Keyboard.hasXkb(), 233 "XTest" : X11Keyboard.hasXTest()} 234 try: 223 235 from xpra.x11.gtk2.composite import CompositeHelper 224 info["server.XShm"] = CompositeHelper.XShmEnabled236 sinfo["XShm"] = CompositeHelper.XShmEnabled 225 237 except: 226 238 pass 227 239 #randr: … … 228 240 try: 229 241 sizes = RandR.get_screen_sizes() 230 242 if self.randr and len(sizes)>=0: 231 info["server.randr.options"] = list(reversed(sorted(sizes)))243 sinfo["randr"] = {"options" : list(reversed(sorted(sizes)))} 232 244 except: 233 245 pass 234 try: 235 fx = find_libfakeXinerama() 236 except: 237 fx = None 238 info["server.fakeXinerama"] = self.fake_xinerama and bool(fx) 239 info["server.libfakeXinerama"] = fx or "" 240 #this is added here because the server keyboard config doesn't know about "keys_pressed".. 241 info["keyboard.state.keys_pressed"] = list(self.keys_pressed.keys()) 242 info["keyboard.fast-switching"] = True 243 info["server.Xkb"] = X11Keyboard.hasXkb() 244 info["server.XTest"] = X11Keyboard.hasXTest() 246 info["server"] = sinfo 245 247 return info 246 248 247 249 def get_window_info(self, window):