def get_client_info(self, ci): #version info: ctype = ci.strget("type", "unknown") title = "%s client version" % ctype title += caps_to_version(ci) chost = ci.strget("hostname") conn_info = "" if chost: conn_info = "connected from %s " % chost cinfo = ci.dictget("connection") if cinfo: cinfo = typedict(cinfo) conn_info += "using %s %s" % (cinfo.strget("type"), cinfo.strget("protocol-type")) conn_info += ", with %s and %s" % (cinfo.strget("encoder"), cinfo.strget("compressor")) gl_info = self.get_gl_info(ci.dictget("opengl")) #audio audio_info = [] for mode in ("speaker", "microphone"): audio_info.append(self._audio_info(ci, mode)) audio_info.append(self._avsync_info(ci)) #batch delay / latency: b_info = typedict(ci.dictget("batch", {})) bi_info = typedict(b_info.dictget("delay", {})) bcur = bi_info.intget("cur") bavg = bi_info.intget("avg") batch_info = "batch delay: %i (%i)" % ( bcur, bavg, ) #client latency: pl = self.slidictget("connection", "client", "ping_latency") lcur = pl.intget("cur") lavg = pl.intget("avg") lmin = pl.intget("min") bl_color = GREEN if bcur > 50 or (lcur > 20 and lcur > 2 * lmin): bl_color = YELLOW elif bcur > 100 or (lcur > 20 and lcur > 3 * lmin): bl_color = RED batch_latency = batch_info.ljust(24) + "latency: %i (%i)" % (lcur, lavg) #speed / quality: edict = typedict(ci.dictget("encoding") or {}) qs_info = "" qs_color = GREEN if edict: sinfo = typedict(edict.dictget("speed") or {}) if sinfo: cur = sinfo.intget("cur") avg = sinfo.intget("avg") qs_info = "speed: %s%% (avg: %s%%)" % (cur, avg) qinfo = typedict(edict.dictget("quality") or {}) if qinfo: qs_info = qs_info.ljust(24) cur = qinfo.intget("cur") avg = qinfo.intget("avg") qs_info += "quality: %s%% (avg: %s%%)" % (cur, avg) if avg < 70: qs_color = YELLOW if avg < 50: qs_color = RED return tuple((s, c) for s, c in ( (title, WHITE), (conn_info, WHITE), (gl_info, WHITE), (csv(audio_info), WHITE), (batch_latency, bl_color), (qs_info, qs_color), ) if s)
def do_update_screen(self): self.log("do_update_screen()") #c = self.stdscr.getch() #if c==curses.KEY_RESIZE: height, width = self.stdscr.getmaxyx() #log.info("update_screen() %ix%i", height, width) title = get_title() sli = self.server_last_info def _addstr(pad, y, x, s, *args): if len(s) + x >= width - pad: s = s[:max(0, width - x - 2 - pad)] + ".." self.stdscr.addstr(y, x, s, *args) def addstr_main(y, x, s, *args): _addstr(0, y, x, s, *args) def addstr_box(y, x, s, *args): _addstr(2, y, x, s, *args) try: x = max(0, width // 2 - len(title) // 2) addstr_main(0, x, title, curses.A_BOLD) if height <= 1: return server_info = self.slidictget("server") build = self.slidictget("server", "build") vstr = caps_to_version(build) mode = server_info.strget("mode", "server") python_info = typedict(server_info.dictget("python", {})) bits = python_info.intget("bits", 32) server_str = "Xpra %s server version %s %i-bit" % (mode, vstr, bits) proxy_info = self.slidictget("proxy") if proxy_info: proxy_platform_info = typedict( proxy_info.dictget("platform", {})) proxy_platform = proxy_platform_info.strget("") proxy_release = proxy_platform_info.strget("release") proxy_build_info = typedict(proxy_info.dictget("build", {})) proxy_version = proxy_build_info.strget("version") proxy_distro = proxy_info.strget("linux_distribution") server_str += " via: %s proxy version %s" % (platform_name( proxy_platform, proxy_distro or proxy_release), std(proxy_version or "unknown")) addstr_main(1, 0, server_str) if height <= 2: return #load and uptime: now = datetime.now() uptime = "" elapsed_time = server_info.intget("elapsed_time") if elapsed_time: td = timedelta(seconds=elapsed_time) uptime = " up %s" % str(td).lstrip("0:") clients_info = self.slidictget("clients") nclients = clients_info.intget("") load_average = "" load = sli.inttupleget("load") if load and len(load) == 3: float_load = tuple(v / 1000.0 for v in load) load_average = ", load average: %1.2f, %1.2f, %1.2f" % float_load addstr_main( 2, 0, "xpra top - %s%s, %2i users%s" % (now.strftime("%H:%M:%S"), uptime, nclients, load_average)) if height <= 3: return thread_info = self.slidictget("threads") rinfo = "%i threads" % thread_info.intget("count") server_pid = server_info.intget("pid", 0) if server_pid: rinfo += ", pid %i" % server_pid machine_id = server_info.get("machine-id") if machine_id is None or machine_id == get_machine_id(): try: process = self.psprocess.get(server_pid) if not process: import psutil process = psutil.Process(server_pid) self.psprocess[server_pid] = process else: cpu = process.cpu_percent() rinfo += ", %i%% CPU" % (cpu) except Exception: pass cpuinfo = self.slidictget("cpuinfo") if cpuinfo: rinfo += ", %s" % cpuinfo.strget("hz_actual") elapsed = monotonic_time() - self.server_last_info_time color = WHITE if self.server_last_info_time == 0: rinfo += " - no server data" elif elapsed > 2: rinfo += " - last updated %i seconds ago" % elapsed color = RED addstr_main(3, 0, rinfo, curses.color_pair(color)) if height <= 4: return #display: dinfo = [] server = self.slidictget("server") rws = server.intpair("root_window_size", None) if rws: sinfo = "%ix%i display" % (rws[0], rws[1]) mds = server.intpair("max_desktop_size") if mds: sinfo += " (max %ix%i)" % (mds[0], mds[1]) dinfo.append(sinfo) cursor_info = self.slidictget("cursor") if cursor_info: cx, cy = cursor_info.inttupleget("position", (0, 0)) dinfo.append("cursor at %ix%i" % (cx, cy)) display_info = self.slidictget("display") pid = display_info.intget("pid") if pid: dinfo.append("pid %i" % pid) addstr_main(4, 0, csv(dinfo)) if height <= 5: return hpos = 5 gl_info = self.get_gl_info(display_info.dictget("opengl")) if gl_info: addstr_main(5, 0, gl_info) hpos += 1 if hpos < height - 3: hpos += 1 if nclients == 0: addstr_main(hpos, 0, "no clients connected") else: addstr_main( hpos, 0, "%i client%s connected:" % (nclients, engs(nclients))) hpos += 1 client_info = self.slidictget("client") client_no = 0 while True: ci = client_info.dictget(client_no) if not ci: break client_no += 1 ci = typedict(ci) session_id = ci.strget("session-id") if session_id: #don't show ourselves: if session_id == self.session_id: continue elif not ci.boolget("windows", True): #for older servers, hide any client that doesn't display windows: continue ci = self.get_client_info(ci) l = len(ci) if hpos + 2 + l > height: if hpos < height: more = nclients - client_no addstr_box( hpos, 0, "%i client%s not shown" % (more, engs(more)), curses.A_BOLD) break self.box(1, hpos, width - 2, 2 + l) for i, info in enumerate(ci): info_text, color = info cpair = curses.color_pair(color) addstr_box(hpos + i + 1, 2, info_text, cpair) hpos += 2 + l windows = self.slidictget("windows") if hpos < height - 3: hpos += 1 addstr_main(hpos, 0, "%i window%s:" % (len(windows), engs(windows))) hpos += 1 wins = tuple(windows.values()) nwindows = len(wins) for win_no, win in enumerate(wins): wi = self.get_window_info(typedict(win)) l = len(wi) if hpos + 2 + l > height: if hpos < height: more = nwindows - win_no addstr_main(hpos, 0, "terminal window is too small: %i window%s not shown" % \ (more, engs(more)), curses.A_BOLD) break self.box(1, hpos, width - 2, 2 + l) for i, info in enumerate(wi): info_text, color = info cpair = curses.color_pair(color) addstr_box(hpos + i + 1, 2, info_text, cpair) hpos += 2 + l except Exception as e: self.err(e)