1*f0687c8aSRaman Tenneti#!/usr/bin/python3 2*f0687c8aSRaman Tenneti 3*f0687c8aSRaman Tennetiimport urwid 4*f0687c8aSRaman Tennetiimport pykms 5*f0687c8aSRaman Tenneti 6*f0687c8aSRaman Tennetidef exit_on_q(key): 7*f0687c8aSRaman Tenneti if key in ('q', 'Q'): 8*f0687c8aSRaman Tenneti raise urwid.ExitMainLoop() 9*f0687c8aSRaman Tenneti elif key == 'a': 10*f0687c8aSRaman Tenneti apply_mode() 11*f0687c8aSRaman Tenneti 12*f0687c8aSRaman Tennetialarm_handle = None 13*f0687c8aSRaman Tenneti 14*f0687c8aSRaman Tennetidef recalc_info(l, d): 15*f0687c8aSRaman Tenneti global alarm_handle 16*f0687c8aSRaman Tenneti 17*f0687c8aSRaman Tenneti alarm_handle = None 18*f0687c8aSRaman Tenneti 19*f0687c8aSRaman Tenneti for w in recalc_list: 20*f0687c8aSRaman Tenneti w.recalc() 21*f0687c8aSRaman Tenneti 22*f0687c8aSRaman Tennetidef div_or_zero(n, d): 23*f0687c8aSRaman Tenneti if d == 0: 24*f0687c8aSRaman Tenneti return 0 25*f0687c8aSRaman Tenneti else: 26*f0687c8aSRaman Tenneti return n / d 27*f0687c8aSRaman Tenneti 28*f0687c8aSRaman Tenneticlass MyIntEdit(urwid.IntEdit): 29*f0687c8aSRaman Tenneti _metaclass_ = urwid.signals.MetaSignals 30*f0687c8aSRaman Tenneti signals = ['value_change'] 31*f0687c8aSRaman Tenneti 32*f0687c8aSRaman Tenneti def __init__(self, caption, calc=None): 33*f0687c8aSRaman Tenneti self._myval = 0 34*f0687c8aSRaman Tenneti self._disable_change = False 35*f0687c8aSRaman Tenneti self._calc = calc 36*f0687c8aSRaman Tenneti self._updlist = None 37*f0687c8aSRaman Tenneti 38*f0687c8aSRaman Tenneti super().__init__(caption, 0) 39*f0687c8aSRaman Tenneti 40*f0687c8aSRaman Tenneti def set_edit_text(self, text): 41*f0687c8aSRaman Tenneti global alarm_handle 42*f0687c8aSRaman Tenneti 43*f0687c8aSRaman Tenneti super().set_edit_text(text) 44*f0687c8aSRaman Tenneti newtext = super().get_edit_text() 45*f0687c8aSRaman Tenneti new_val = int(newtext) if newtext != "" else 0 46*f0687c8aSRaman Tenneti if new_val != self._myval: 47*f0687c8aSRaman Tenneti self._myval = new_val 48*f0687c8aSRaman Tenneti if not self._disable_change: 49*f0687c8aSRaman Tenneti urwid.emit_signal(self, 'value_change', self, self._myval) 50*f0687c8aSRaman Tenneti 51*f0687c8aSRaman Tenneti if alarm_handle == None: 52*f0687c8aSRaman Tenneti alarm_handle = loop.set_alarm_in(0, recalc_info) 53*f0687c8aSRaman Tenneti 54*f0687c8aSRaman Tenneti if self._updlist != None: 55*f0687c8aSRaman Tenneti for w in self._updlist: 56*f0687c8aSRaman Tenneti w.recalc() 57*f0687c8aSRaman Tenneti 58*f0687c8aSRaman Tenneti def recalc(self): 59*f0687c8aSRaman Tenneti self._disable_change = True 60*f0687c8aSRaman Tenneti self.set_val(self._calc()) 61*f0687c8aSRaman Tenneti self._disable_change = False 62*f0687c8aSRaman Tenneti 63*f0687c8aSRaman Tenneti def set_val(self, val): 64*f0687c8aSRaman Tenneti self.set_edit_text(str(int(val))) 65*f0687c8aSRaman Tenneti 66*f0687c8aSRaman Tenneti def get_val(self): 67*f0687c8aSRaman Tenneti return self._myval 68*f0687c8aSRaman Tenneti 69*f0687c8aSRaman Tenneti def set_updlist(self, list): 70*f0687c8aSRaman Tenneti self._updlist = list 71*f0687c8aSRaman Tenneti 72*f0687c8aSRaman Tenneti def keypress(self, size, key): 73*f0687c8aSRaman Tenneti if key == '+': 74*f0687c8aSRaman Tenneti self.set_edit_text(str(self.value() + 1)) 75*f0687c8aSRaman Tenneti elif key == '-': 76*f0687c8aSRaman Tenneti self.set_edit_text(str(self.value() - 1)) 77*f0687c8aSRaman Tenneti else: 78*f0687c8aSRaman Tenneti return super().keypress(size, key) 79*f0687c8aSRaman Tenneti 80*f0687c8aSRaman Tenneticlass MyIntText(urwid.Text): 81*f0687c8aSRaman Tenneti def __init__(self, fmt, calc=None): 82*f0687c8aSRaman Tenneti super().__init__("") 83*f0687c8aSRaman Tenneti self._fmt = fmt 84*f0687c8aSRaman Tenneti self._calc = calc 85*f0687c8aSRaman Tenneti 86*f0687c8aSRaman Tenneti def recalc(self): 87*f0687c8aSRaman Tenneti val = self._calc() 88*f0687c8aSRaman Tenneti super().set_text(self._fmt.format(val)) 89*f0687c8aSRaman Tenneti 90*f0687c8aSRaman Tennetidef khz_to_ps(khz): 91*f0687c8aSRaman Tenneti if khz == 0: 92*f0687c8aSRaman Tenneti return 0 93*f0687c8aSRaman Tenneti else: 94*f0687c8aSRaman Tenneti return 1.0 / khz * 1000 * 1000 * 1000 95*f0687c8aSRaman Tenneti 96*f0687c8aSRaman Tennetidef khz_to_us(khz): 97*f0687c8aSRaman Tenneti if khz == 0: 98*f0687c8aSRaman Tenneti return 0 99*f0687c8aSRaman Tenneti else: 100*f0687c8aSRaman Tenneti return 1.0 / khz * 1000 101*f0687c8aSRaman Tenneti 102*f0687c8aSRaman Tennetipclk_khz_widget = MyIntEdit(u"pclk (kHz) ") 103*f0687c8aSRaman Tennetipclk_ps_widget = MyIntText(fmt="pclk {:.2f} ps", calc = lambda: khz_to_ps(pclk_khz_widget.get_val())) 104*f0687c8aSRaman Tenneti 105*f0687c8aSRaman Tennetipclk_widgets = [pclk_khz_widget, pclk_ps_widget] 106*f0687c8aSRaman Tenneti 107*f0687c8aSRaman Tennetipclk_columns = urwid.LineBox(urwid.Columns(pclk_widgets), title = "Pixel clock") 108*f0687c8aSRaman Tenneti 109*f0687c8aSRaman Tenneti# Horizontal widgets 110*f0687c8aSRaman Tenneti 111*f0687c8aSRaman Tennetihdisp_widget = MyIntEdit(u"hdisp ", calc = lambda: hdisp2_widget.get_val()) 112*f0687c8aSRaman Tennetihfp_widget = MyIntEdit(u"hfp ", calc = lambda: hss_widget.get_val() - hdisp_widget.get_val()) 113*f0687c8aSRaman Tennetihsw_widget = MyIntEdit(u"hsw ", calc = lambda: hse_widget.get_val() - hss_widget.get_val()) 114*f0687c8aSRaman Tennetihbp_widget = MyIntEdit(u"hbp ", calc = lambda: htot_widget.get_val() - hse_widget.get_val()) 115*f0687c8aSRaman Tenneti 116*f0687c8aSRaman Tennetihdisp2_widget = MyIntEdit(u"hdisp ", calc = lambda: hdisp_widget.get_val()) 117*f0687c8aSRaman Tennetihss_widget = MyIntEdit(u"hss ", 118*f0687c8aSRaman Tenneti calc = lambda: hdisp_widget.get_val() + hfp_widget.get_val()) 119*f0687c8aSRaman Tennetihse_widget = MyIntEdit(u"hse ", 120*f0687c8aSRaman Tenneti calc = lambda: hdisp_widget.get_val() + hfp_widget.get_val() + hsw_widget.get_val()) 121*f0687c8aSRaman Tennetihtot_widget = MyIntEdit(u"htot ", 122*f0687c8aSRaman Tenneti calc = lambda: hdisp_widget.get_val() + hfp_widget.get_val() + hsw_widget.get_val() + hbp_widget.get_val()) 123*f0687c8aSRaman Tenneti 124*f0687c8aSRaman Tennetihwidgets1 = [hdisp_widget, hfp_widget, hsw_widget, hbp_widget] 125*f0687c8aSRaman Tennetihwidgets2 = [hdisp2_widget, hss_widget, hse_widget, htot_widget] 126*f0687c8aSRaman Tenneti 127*f0687c8aSRaman Tennetihoriz_pile1 = urwid.Pile(hwidgets1) 128*f0687c8aSRaman Tennetihoriz_pile2 = urwid.Pile(hwidgets2) 129*f0687c8aSRaman Tenneti 130*f0687c8aSRaman Tennetih_columns = urwid.LineBox(urwid.Columns([(15, horiz_pile1), (15, horiz_pile2)]), title = "Horizontal") 131*f0687c8aSRaman Tenneti 132*f0687c8aSRaman Tenneti# Vertical columns 133*f0687c8aSRaman Tenneti 134*f0687c8aSRaman Tennetivdisp_widget = MyIntEdit(u"vdisp ", calc = lambda: vdisp2_widget.get_val()) 135*f0687c8aSRaman Tennetivfp_widget = MyIntEdit(u"vfp ", calc = lambda: vss_widget.get_val() - vdisp_widget.get_val()) 136*f0687c8aSRaman Tennetivsw_widget = MyIntEdit(u"vsw ", calc = lambda: vse_widget.get_val() - vss_widget.get_val()) 137*f0687c8aSRaman Tennetivbp_widget = MyIntEdit(u"vbp ", calc = lambda: vtot_widget.get_val() - vse_widget.get_val()) 138*f0687c8aSRaman Tenneti 139*f0687c8aSRaman Tennetivdisp2_widget = MyIntEdit(u"vdisp ", calc = lambda: vdisp_widget.get_val()) 140*f0687c8aSRaman Tennetivss_widget = MyIntEdit(u"vss ", 141*f0687c8aSRaman Tenneti calc = lambda: vdisp_widget.get_val() + vfp_widget.get_val()) 142*f0687c8aSRaman Tennetivse_widget = MyIntEdit(u"vse ", 143*f0687c8aSRaman Tenneti calc = lambda: vdisp_widget.get_val() + vfp_widget.get_val() + vsw_widget.get_val()) 144*f0687c8aSRaman Tennetivtot_widget = MyIntEdit(u"vtot ", 145*f0687c8aSRaman Tenneti calc = lambda: vdisp_widget.get_val() + vfp_widget.get_val() + vsw_widget.get_val() + vbp_widget.get_val()) 146*f0687c8aSRaman Tenneti 147*f0687c8aSRaman Tennetivwidgets1 = [vdisp_widget, vfp_widget, vsw_widget, vbp_widget] 148*f0687c8aSRaman Tennetivwidgets2 = [vdisp2_widget, vss_widget, vse_widget, vtot_widget] 149*f0687c8aSRaman Tenneti 150*f0687c8aSRaman Tennetivert_pile1 = urwid.Pile(vwidgets1) 151*f0687c8aSRaman Tennetivert_pile2 = urwid.Pile(vwidgets2) 152*f0687c8aSRaman Tenneti 153*f0687c8aSRaman Tennetiv_columns = urwid.LineBox(urwid.Columns([(15, vert_pile1), (15, vert_pile2)]), title = "Vertical") 154*f0687c8aSRaman Tenneti 155*f0687c8aSRaman Tenneti# Info widgets 156*f0687c8aSRaman Tenneti 157*f0687c8aSRaman Tennetiline_us_widget = MyIntText(fmt="line {:.2f} us", 158*f0687c8aSRaman Tenneti calc = lambda: khz_to_us(pclk_khz_widget.get_val()) * htot_widget.get_val()) 159*f0687c8aSRaman Tennetiline_khz_widget = MyIntText(fmt="line {:.2f} kHz", 160*f0687c8aSRaman Tenneti calc = lambda: div_or_zero(pclk_khz_widget.get_val(), htot_widget.get_val())) 161*f0687c8aSRaman Tenneti 162*f0687c8aSRaman Tennetiframe_tot_widget = MyIntText(fmt="tot {} pix", 163*f0687c8aSRaman Tenneti calc = lambda: htot_widget.get_val() * vtot_widget.get_val()) 164*f0687c8aSRaman Tennetiframe_us_widget = MyIntText(fmt="frame {:.2f} ms", 165*f0687c8aSRaman Tenneti calc = lambda: khz_to_us(pclk_khz_widget.get_val()) * htot_widget.get_val() * vtot_widget.get_val() / 1000) 166*f0687c8aSRaman Tennetiframe_khz_widget = MyIntText(fmt="frame {:.2f} Hz", 167*f0687c8aSRaman Tenneti calc = lambda: div_or_zero(pclk_khz_widget.get_val() * 1000, htot_widget.get_val() * vtot_widget.get_val())) 168*f0687c8aSRaman Tenneti 169*f0687c8aSRaman Tennetiinfo_box = urwid.LineBox(urwid.Pile([line_us_widget, line_khz_widget, urwid.Divider(), frame_tot_widget, frame_us_widget, frame_khz_widget]), title = "Info") 170*f0687c8aSRaman Tenneti 171*f0687c8aSRaman Tenneti# Set update lists 172*f0687c8aSRaman Tenneti 173*f0687c8aSRaman Tennetirecalc_list = [ pclk_ps_widget, line_us_widget, line_khz_widget, frame_tot_widget, frame_us_widget, frame_khz_widget ] 174*f0687c8aSRaman Tenneti 175*f0687c8aSRaman Tennetihdisp_widget.set_updlist([hdisp2_widget, hss_widget, hse_widget, htot_widget]) 176*f0687c8aSRaman Tennetihfp_widget.set_updlist([hss_widget, hse_widget, htot_widget]) 177*f0687c8aSRaman Tennetihsw_widget.set_updlist([hse_widget, htot_widget]) 178*f0687c8aSRaman Tennetihbp_widget.set_updlist([htot_widget]) 179*f0687c8aSRaman Tennetihdisp2_widget.set_updlist([hdisp_widget, hfp_widget]) 180*f0687c8aSRaman Tennetihss_widget.set_updlist([hfp_widget, hsw_widget]) 181*f0687c8aSRaman Tennetihse_widget.set_updlist([hsw_widget, hbp_widget]) 182*f0687c8aSRaman Tennetihtot_widget.set_updlist([hbp_widget]) 183*f0687c8aSRaman Tenneti 184*f0687c8aSRaman Tennetivdisp_widget.set_updlist([vdisp2_widget, vss_widget, vse_widget, vtot_widget]) 185*f0687c8aSRaman Tennetivfp_widget.set_updlist([vss_widget, vse_widget, vtot_widget]) 186*f0687c8aSRaman Tennetivsw_widget.set_updlist([vse_widget, vtot_widget]) 187*f0687c8aSRaman Tennetivbp_widget.set_updlist([vtot_widget]) 188*f0687c8aSRaman Tennetivdisp2_widget.set_updlist([vdisp_widget, vfp_widget]) 189*f0687c8aSRaman Tennetivss_widget.set_updlist([vfp_widget, vsw_widget]) 190*f0687c8aSRaman Tennetivse_widget.set_updlist([vsw_widget, vbp_widget]) 191*f0687c8aSRaman Tennetivtot_widget.set_updlist([vbp_widget]) 192*f0687c8aSRaman Tenneti 193*f0687c8aSRaman Tenneti# Flags 194*f0687c8aSRaman Tenneti 195*f0687c8aSRaman Tennetifb = None 196*f0687c8aSRaman Tenneti 197*f0687c8aSRaman TennetiDRM_MODE_FLAG_PHSYNC = (1<<0) 198*f0687c8aSRaman TennetiDRM_MODE_FLAG_NHSYNC = (1<<1) 199*f0687c8aSRaman TennetiDRM_MODE_FLAG_PVSYNC = (1<<2) 200*f0687c8aSRaman TennetiDRM_MODE_FLAG_NVSYNC = (1<<3) 201*f0687c8aSRaman TennetiDRM_MODE_FLAG_INTERLACE = (1<<4) 202*f0687c8aSRaman TennetiDRM_MODE_FLAG_DBLCLK = (1<<12) 203*f0687c8aSRaman Tenneti 204*f0687c8aSRaman Tennetidef mode_is_ilace(mode): 205*f0687c8aSRaman Tenneti return (mode.flags & DRM_MODE_FLAG_INTERLACE) != 0 206*f0687c8aSRaman Tenneti 207*f0687c8aSRaman Tennetidef apply_mode(): 208*f0687c8aSRaman Tenneti global fb 209*f0687c8aSRaman Tenneti 210*f0687c8aSRaman Tenneti mode = pykms.Videomode() 211*f0687c8aSRaman Tenneti mode.clock = pclk_khz_widget.get_val() 212*f0687c8aSRaman Tenneti 213*f0687c8aSRaman Tenneti mode.hdisplay = hdisp2_widget.get_val() 214*f0687c8aSRaman Tenneti mode.hsync_start = hss_widget.get_val() 215*f0687c8aSRaman Tenneti mode.hsync_end = hse_widget.get_val() 216*f0687c8aSRaman Tenneti mode.htotal = htot_widget.get_val() 217*f0687c8aSRaman Tenneti 218*f0687c8aSRaman Tenneti mode.vdisplay = vdisp2_widget.get_val() 219*f0687c8aSRaman Tenneti mode.vsync_start = vss_widget.get_val() 220*f0687c8aSRaman Tenneti mode.vsync_end = vse_widget.get_val() 221*f0687c8aSRaman Tenneti mode.vtotal = vtot_widget.get_val() 222*f0687c8aSRaman Tenneti 223*f0687c8aSRaman Tenneti if ilace_box.state: 224*f0687c8aSRaman Tenneti mode.flags |= DRM_MODE_FLAG_INTERLACE 225*f0687c8aSRaman Tenneti 226*f0687c8aSRaman Tenneti if dblclk_box.state: 227*f0687c8aSRaman Tenneti mode.flags |= DRM_MODE_FLAG_DBLCLK 228*f0687c8aSRaman Tenneti 229*f0687c8aSRaman Tenneti if hsync_pol.state == True: 230*f0687c8aSRaman Tenneti mode.flags |= DRM_MODE_FLAG_PHSYNC 231*f0687c8aSRaman Tenneti elif hsync_pol.state == False: 232*f0687c8aSRaman Tenneti mode.flags |= DRM_MODE_FLAG_NHSYNC 233*f0687c8aSRaman Tenneti 234*f0687c8aSRaman Tenneti if vsync_pol.state == True: 235*f0687c8aSRaman Tenneti mode.flags |= DRM_MODE_FLAG_PVSYNC 236*f0687c8aSRaman Tenneti elif vsync_pol.state == False: 237*f0687c8aSRaman Tenneti mode.flags |= DRM_MODE_FLAG_NVSYNC 238*f0687c8aSRaman Tenneti 239*f0687c8aSRaman Tenneti fb = pykms.DumbFramebuffer(card, mode.hdisplay, mode.vdisplay, "XR24"); 240*f0687c8aSRaman Tenneti pykms.draw_test_pattern(fb); 241*f0687c8aSRaman Tenneti 242*f0687c8aSRaman Tenneti crtc.set_mode(conn, fb, mode) 243*f0687c8aSRaman Tenneti 244*f0687c8aSRaman Tennetidef read_mode(mode): 245*f0687c8aSRaman Tenneti pclk_khz_widget.set_val(mode.clock) 246*f0687c8aSRaman Tenneti hdisp2_widget.set_val(mode.hdisplay) 247*f0687c8aSRaman Tenneti hss_widget.set_val(mode.hsync_start) 248*f0687c8aSRaman Tenneti hse_widget.set_val(mode.hsync_end) 249*f0687c8aSRaman Tenneti htot_widget.set_val(mode.htotal) 250*f0687c8aSRaman Tenneti 251*f0687c8aSRaman Tenneti vdisp2_widget.set_val(mode.vdisplay) 252*f0687c8aSRaman Tenneti vss_widget.set_val(mode.vsync_start) 253*f0687c8aSRaman Tenneti vse_widget.set_val(mode.vsync_end) 254*f0687c8aSRaman Tenneti vtot_widget.set_val(mode.vtotal) 255*f0687c8aSRaman Tenneti 256*f0687c8aSRaman Tenneti ilace_box.set_state(mode_is_ilace(mode)) 257*f0687c8aSRaman Tenneti dblclk_box.set_state((mode.flags & DRM_MODE_FLAG_DBLCLK) != 0) 258*f0687c8aSRaman Tenneti 259*f0687c8aSRaman Tenneti sync = 'mixed' 260*f0687c8aSRaman Tenneti if (mode.flags & DRM_MODE_FLAG_PHSYNC) != 0: 261*f0687c8aSRaman Tenneti sync = True 262*f0687c8aSRaman Tenneti elif (mode.flags & DRM_MODE_FLAG_NHSYNC) != 0: 263*f0687c8aSRaman Tenneti sync = False 264*f0687c8aSRaman Tenneti hsync_pol.set_state(sync) 265*f0687c8aSRaman Tenneti 266*f0687c8aSRaman Tenneti sync = 'mixed' 267*f0687c8aSRaman Tenneti if (mode.flags & DRM_MODE_FLAG_PVSYNC) != 0: 268*f0687c8aSRaman Tenneti sync = True 269*f0687c8aSRaman Tenneti elif (mode.flags & DRM_MODE_FLAG_NVSYNC) != 0: 270*f0687c8aSRaman Tenneti sync = False 271*f0687c8aSRaman Tenneti vsync_pol.set_state(sync) 272*f0687c8aSRaman Tenneti 273*f0687c8aSRaman Tennetidef apply_press(w): 274*f0687c8aSRaman Tenneti apply_mode() 275*f0687c8aSRaman Tenneti 276*f0687c8aSRaman Tennetiilace_box = urwid.CheckBox('interlace') 277*f0687c8aSRaman Tennetihsync_pol = urwid.CheckBox('hsync positive', has_mixed=True) 278*f0687c8aSRaman Tennetivsync_pol = urwid.CheckBox('vsync positive', has_mixed=True) 279*f0687c8aSRaman Tennetidblclk_box = urwid.CheckBox('double clock') 280*f0687c8aSRaman Tenneti 281*f0687c8aSRaman Tennetiflags_pile = urwid.LineBox(urwid.Pile([ilace_box, hsync_pol, vsync_pol, dblclk_box]), title = "Flags") 282*f0687c8aSRaman Tenneti 283*f0687c8aSRaman Tennetiapply_button = urwid.LineBox(urwid.Padding(urwid.Button('apply', on_press=apply_press))) 284*f0687c8aSRaman Tenneti 285*f0687c8aSRaman Tenneti# Main 286*f0687c8aSRaman Tenneti 287*f0687c8aSRaman Tennetidef mode_press(w, mode): 288*f0687c8aSRaman Tenneti read_mode(mode) 289*f0687c8aSRaman Tenneti 290*f0687c8aSRaman Tennetidef mode_to_str(mode): 291*f0687c8aSRaman Tenneti return "{}@{}{}".format(mode.name, mode.vrefresh, "i" if mode_is_ilace(mode) else "") 292*f0687c8aSRaman Tenneti 293*f0687c8aSRaman Tennetimode_buttons = [] 294*f0687c8aSRaman Tenneti 295*f0687c8aSRaman Tenneticard = pykms.Card() 296*f0687c8aSRaman Tenneti 297*f0687c8aSRaman Tennetires = pykms.ResourceManager(card) 298*f0687c8aSRaman Tenneticonn = res.reserve_connector() 299*f0687c8aSRaman Tenneticrtc = res.reserve_crtc(conn) 300*f0687c8aSRaman Tennetiplane = res.reserve_generic_plane(crtc) 301*f0687c8aSRaman Tennetimodes = conn.get_modes() 302*f0687c8aSRaman Tennetii = 0 303*f0687c8aSRaman Tennetifor m in modes: 304*f0687c8aSRaman Tenneti mode_buttons.append(urwid.Button(mode_to_str(m), on_press=mode_press, user_data=m)) 305*f0687c8aSRaman Tenneti i += 1 306*f0687c8aSRaman Tenneti 307*f0687c8aSRaman Tennetimodes_pile = urwid.LineBox(urwid.Pile(mode_buttons), title = "Video modes") 308*f0687c8aSRaman Tenneti 309*f0687c8aSRaman Tennetimain_pile = urwid.Pile([modes_pile, pclk_columns, urwid.Columns([ h_columns, v_columns ]), info_box, flags_pile, apply_button]) 310*f0687c8aSRaman Tenneti 311*f0687c8aSRaman Tennetimain_columns = urwid.Filler(main_pile, valign='top') 312*f0687c8aSRaman Tenneti 313*f0687c8aSRaman Tennetiloop = urwid.MainLoop(main_columns, unhandled_input=exit_on_q, handle_mouse=False) 314*f0687c8aSRaman Tenneti 315*f0687c8aSRaman Tenneti# select the first mode 316*f0687c8aSRaman Tennetimode_press(None, modes[0]) 317*f0687c8aSRaman Tenneti 318*f0687c8aSRaman Tennetiloop.run() 319*f0687c8aSRaman Tenneti 320*f0687c8aSRaman Tennetifb = None 321