def __init__(self, mgr): self.mgr = mgr self.mainwin = TextWindow(mgr, 32, 24, 0, 0, kb_event=self.kb_event, cursor_off=True) self.ctrlwin = None self.ctrlwin_timeout = time.time() + 20 self.edlin = None self.show_offset = 0 self.max_lines = 16 self.f_index_str = '1234567890ABCDEFGHI' self.f_index = str2zx(self.f_index_str) self.actual_lines = 0 self.charmap = [15] * 256 self.build_charmap() self.cam = None self.camout = None self.app_state = AppState.SHOW self.replay_ix = 0 self.delay_s = 3.0 self.event = mgr.schedule_event(self.periodic, 1.0, 5.0) self.contrast = 0.5 self.brightness = 1.0 self.invert = False self.h_v_rot = 0 # H/V flip or rotate status as three LSB bits self.floyd_stb = False self.applied_rot = None self.check_show_ctrlwin() self.movie = [] self.last_pic = None
class AppShell: def __init__(self, mgr): self.mainwin = TextWindow(mgr, 30, 22, 1, 1, border=WindowBorderFrame(), kb_event=self.kb_event) #run('cmd',shell=True,stdout=self,stderr=self,stdin=self) #self.proc = Popen(['python','C:\\Users\\Holmatic\\workspace\\serial\\src\\apps\\file_browser.py'],shell=True,stdin=PIPE, stdout=PIPE, stderr=PIPE, universal_newlines=True) self.proc = Popen('cmd', shell=True, stdin=PIPE, stdout=PIPE, stderr=PIPE, universal_newlines=True) self.revent = mgr.schedule_event(self.periodic, 0.5, 0.5) print("AppShell starts...") self.outThread = Thread(target=self.out_handler_thread, args=(self.proc.stdout, )) self.errThread = Thread(target=self.out_handler_thread, args=(self.proc.stderr, )) self.outThread.start() self.errThread.start() # todo exit def out_handler_thread(self, p): print("out_handler_thread starts...") #self.event.set() while True: # print("read data: ") data = p.read(1) #.decode("utf-8") if not data: break z = str2zx(data) sys.stdout.write(data) sys.stdout.flush() for c in z: self.mainwin.prtchar(c) print("Shell Out") def periodic(self): pass #self.event.wait(timeout=0.1) def kb_event(self, win, char): if char == 12: self.mainwin.close() app.clear() # TODO clear threads else: win.prtchar(char) s = zx2str([char]) #if s=='\n': s='\r\n' self.proc.stdin.write(s) self.proc.stdin.flush()
def __init__(self,mgr): self.mainwin=TextWindow(mgr,30,22,1,1,border=WindowBorderFrame(),kb_event=self.kb_event, cursor_off=True) self.print_help() #run('cmd',shell=True,stdout=self,stderr=self,stdin=self) #self.proc = Popen(['python','C:\\Users\\Holmatic\\workspace\\serial\\src\\apps\\file_browser.py'],shell=True,stdin=PIPE, stdout=PIPE, stderr=PIPE, universal_newlines=True) self.proc = None self.revent=mgr.schedule_event(self.periodic,0.5,0.5) self.outThread = None self.errThread = None
def kb_event(self, win, zxchar): #win.prtchar(zxchar) bright = {'1': 1.5, '2': 1.2, '3': 1.0, '4': 0.83, '5': 0.67} contr = {'6': 0.2, '7': 0.33, '8': 0.5, '9': 0.8, '0': 1.2} s = zx2str([zxchar]) if s in 'xX' or zxchar == 12: self.close() return elif s in 'fF': self.delay_s = 0.15 elif s in 'sS': self.delay_s = 3.0 elif s in 'dD': self.floyd_stb = not self.floyd_stb elif s in 'iI': self.invert = not self.invert elif s in 'rR': self.h_v_rot += 1 elif s in 'pP': if self.app_state == AppState.SHOW: self.app_state = AppState.PIC_QUERY_YN if self.ctrlwin: self.ctrlwin.close() self.ctrlwin = TextWindow(self.mgr, 10, 1, 18, 19, border=WindowBorderFrame(), kb_event=self.kb_event_query, cursor_off=True) self.ctrlwin.prttxt(str2zx('save? Y/N', upper_inv=True)) elif s in 'mM': self.movie.clear() self.replay_ix = 0 if self.app_state == AppState.SHOW: self.app_state = AppState.MOVIE_REC if self.ctrlwin: self.ctrlwin.close() self.ctrlwin = TextWindow(self.mgr, 13, 1, 17, 19, border=WindowBorderFrame(), kb_event=self.kb_event_query, cursor_off=True) self.ctrlwin.prttxt(str2zx('recording', upper_inv=True)) elif s in bright: self.brightness = bright[s] elif s in contr: self.contrast = contr[s] # TODO invers, save_pic, help, exit self.ctrlwin_timeout = time.time() + 3 self.check_show_ctrlwin() self.event.reschedule(0.2, 5.0)
def __init__(self, mgr): self.mrg = mgr self.mainwin = TextWindow(mgr, 18, 12, 6, 5, border=WindowBorderFrameShadow(), kb_event=self.kb_event, cursor_off=True) self.print_help()
def end_movie_rec(self): self.app_state = AppState.MOVIE_QUERY_YN if self.ctrlwin: self.ctrlwin.close() self.ctrlwin = TextWindow(self.mgr, 10, 1, 18, 19, border=WindowBorderFrame(), kb_event=self.kb_event_query, cursor_off=True) self.ctrlwin.prttxt(str2zx('save? Y/N', upper_inv=True))
class MediaViewerCam: def __init__(self, mgr, filepath): self.mgr = mgr self.mainwin = TextWindow(mgr, 32, 24, 0, 0, kb_event=self.kb_event, cursor_off=True) self.filepath = filepath self.delay_s = 0.25 self.event = None self.pic_or_movie = bytes() self.pic_or_movie = filepath.open('rb').read() self.current_read_pos = 0 self.show_next() if len(self.pic_or_movie) >= 2 * BYTES_PER_SCR: self.event = mgr.schedule_event(self.periodic, self.delay_s, self.delay_s) def show_next(self): if len(self.pic_or_movie) >= BYTES_PER_SCR: if self.current_read_pos >= len(self.pic_or_movie): self.current_read_pos = 0 for row in range(NUM_ROWS): for col in range(BYTES_PER_ROW): self.mainwin.setchar_raw( self.pic_or_movie[self.current_read_pos], col, row) self.current_read_pos += 1 def periodic(self): self.show_next() def __enter__(self): return self def __exit__(self, _type, _value, _traceback): self.close() def close(self): if self.event: self.event.remove() self.event = None if self.mainwin: self.mainwin.close() self.mainwin = None def kb_event(self, win, zxchar): self.close()
def __init__(self, mgr): self.mgr = mgr self.mainwin = TextWindow(mgr, 32, 24, 0, 0, kb_event=self.kb_event, cursor_off=True) self.show_offset = 0 self.max_lines = 20 self.do_exit = False self.url = 'https://forum.tlienhard.com/phpBB3/viewforum.php?f=2' #print(r.text) self.show()
def __init__(self, mgr, filepath): self.mgr = mgr self.mainwin = TextWindow(mgr, 32, 24, 0, 0, kb_event=self.kb_event, cursor_off=True) self.filepath = filepath self.delay_s = 0.25 self.event = None self.pic_or_movie = bytes() self.pic_or_movie = filepath.open('rb').read() self.current_read_pos = 0 self.show_next() if len(self.pic_or_movie) >= 2 * BYTES_PER_SCR: self.event = mgr.schedule_event(self.periodic, self.delay_s, self.delay_s)
def check_show_ctrlwin(self): if not self.ctrlwin: self.ctrlwin = TextWindow(self.mgr, 14, 13, 14, 9, border=WindowBorderFrame( str2zx('ZX LIVE CAM')), kb_event=self.kb_event, cursor_off=True) self.ctrlwin.prttxt( str2zx('F fast S slow\n\nD dith I invrt', upper_inv=True)) self.ctrlwin.prttxt(str2zx('\nP pic M movie\n', upper_inv=True)) self.ctrlwin.prttxt( str2zx('\nR rotate\n\n1-5 brightness6-0 contrast\n\nX exit', upper_inv=True)) elif time.time() > self.ctrlwin_timeout: self.ctrlwin.close() self.ctrlwin = None
def __init__(self, mgr): self.mgr = mgr self.mainwin = TextWindow(mgr, 30, 22, 1, 1, border=WindowBorderFrame(), kb_event=self.kb_event, cursor_off=True) self.homecwd = Path.cwd().parent / 'zxroot' self.cwd = self.homecwd self.cwdfiles = [] self.show_offset = 0 self.max_lines = 16 self.f_index_str = '1234567890ABCDEFGHI' self.f_index = str2zx(self.f_index_str) self.actual_lines = 0 self.get_dir() self.show_dir()
def __init__(self, mgr): self.mgr = mgr self.mainwin = TextWindow(mgr, 32, 20, 0, 0) self.inp_win = TextWindow(mgr, 30, 2, 1, 21, border=WindowBorderFrame(), kb_event=self.kb_event, cursor_off=True) self.ed = None self.nick = 'zx-user' self.server = "irc.zxq.de" self.pword = '' self.port = 6667 self.inp_mode = InpMode.MENU self.listener = ListenerThread(self.mainwin) self.choose_site() self.revent = mgr.schedule_event(self.periodic, 2, 2) self.channel = ''
def __init__(self, mgr): self.mainwin = TextWindow(mgr, 30, 22, 1, 1, border=WindowBorderFrame(), kb_event=self.kb_event) #run('cmd',shell=True,stdout=self,stderr=self,stdin=self) #self.proc = Popen(['python','C:\\Users\\Holmatic\\workspace\\serial\\src\\apps\\file_browser.py'],shell=True,stdin=PIPE, stdout=PIPE, stderr=PIPE, universal_newlines=True) self.proc = Popen('cmd', shell=True, stdin=PIPE, stdout=PIPE, stderr=PIPE, universal_newlines=True) self.revent = mgr.schedule_event(self.periodic, 0.5, 0.5) print("AppShell starts...") self.outThread = Thread(target=self.out_handler_thread, args=(self.proc.stdout, )) self.errThread = Thread(target=self.out_handler_thread, args=(self.proc.stderr, )) self.outThread.start() self.errThread.start()
def kb_event_query(self, win, zxchar): #win.prtchar(zxchar) s = zx2str([zxchar]) if self.app_state in (AppState.PIC_QUERY_NAME, AppState.MOVIE_QUERY_NAME): if zxchar in (117, 118): # enter,break if zxchar == 118: # enter self.edlin.kb_event(zxchar) if self.app_state == AppState.PIC_QUERY_NAME: if self.edlin.val: # safe pic name = zx2str(self.edlin.val, to_lower=True).strip() #path mwin = self.mgr.show_msg_win(str2zx("save pic ..")) p = zxpi_paths.get_current_work_path() / 'pics' if not p.exists(): p.mkdir(parents=True) n = p / (name + '.zxscr') with n.open('wb') as f: lrg = self.calc_lrg_from_array(self.last_pic) nr, nc = lrg.shape for row in range(nr): #for col in range(nc): f.write(bytes([v for v in lrg[row]])) print("Saved to", str(n)) mwin.close() elif self.app_state == AppState.MOVIE_QUERY_NAME: if self.edlin.val: # save movie name = zx2str(self.edlin.val, to_lower=True).strip() #path pth = zxpi_paths.get_current_work_path() / 'movies' if not pth.exists(): pth.mkdir(parents=True) n = pth / (name + '.zxmovie') mwin = self.mgr.show_msg_win( str2zx("save movie ..")) mv_dat = bytearray() with n.open('wb') as f: for p in self.movie: lrg = self.calc_lrg_from_array(p) nr, nc = lrg.shape for row in range(nr): #for col in range(nc): rowdat = bytearray( [v for v in lrg[row]]) mv_dat += rowdat f.write(rowdat) print("Saved as", str(n)) self.mgr.update(0.1) n = pth / (name + '.p') with n.open('wb') as f: f.write( create_comp_viewer(compress_scr(mv_dat))) mwin.close() if self.edlin: self.edlin.close() self.edlin = None self.app_state = AppState.SHOW self.ctrlwin_timeout = 0 if self.ctrlwin: self.ctrlwin.close() self.ctrlwin = None else: self.edlin.kb_event(zxchar) elif self.app_state in (AppState.MOVIE_REC, ): self.end_movie_rec() else: if s in 'yYzZ': if self.app_state in (AppState.PIC_QUERY_YN, AppState.MOVIE_QUERY_YN): self.app_state = AppState.PIC_QUERY_NAME if self.app_state == AppState.PIC_QUERY_YN else AppState.MOVIE_QUERY_NAME if self.ctrlwin: self.ctrlwin.close() self.ctrlwin = TextWindow(self.mgr, 12, 2, 18, 19, border=WindowBorderFrame(), kb_event=self.kb_event_query, cursor_off=True) self.ctrlwin.prttxt(str2zx('file name:', upper_inv=True)) self.edlin = LinEd(self.ctrlwin, 0, 1, 11, maxchar=255, history=None) else: self.app_state = AppState.SHOW if self.ctrlwin: self.ctrlwin.close() self.ctrlwin = None self.event.reschedule(0.2, 5.0)
class Updater: def __init__(self,mgr): self.mainwin=TextWindow(mgr,30,22,1,1,border=WindowBorderFrame(),kb_event=self.kb_event, cursor_off=True) self.print_help() #run('cmd',shell=True,stdout=self,stderr=self,stdin=self) #self.proc = Popen(['python','C:\\Users\\Holmatic\\workspace\\serial\\src\\apps\\file_browser.py'],shell=True,stdin=PIPE, stdout=PIPE, stderr=PIPE, universal_newlines=True) self.proc = None self.revent=mgr.schedule_event(self.periodic,0.5,0.5) self.outThread = None self.errThread = None def print_help(self): self.mainwin.prttxt(str2zx('\n\n',upper_inv=True )) self.mainwin.prttxt(str2zx(' ZXPI ONLINE UPDATER ',inverse=True )) self.mainwin.prttxt(str2zx('\n\n U start update \n\n X exit\n\n',upper_inv=True )) # todo exit def start(self): self.mainwin.cls() self.mainwin.prttxt(str2zx('\nstart update attempt...\n',upper_inv=True )) self.proc = Popen( ['git','pull','origin','master'] ,shell=False,stdin=PIPE, stdout=PIPE, stderr=PIPE, universal_newlines=True) self.outThread = Thread(target=self.out_handler_thread, args=(self.proc.stdout,)) self.errThread = Thread(target=self.out_handler_thread, args=(self.proc.stderr,)) self.outThread.start() self.errThread.start() def end_cleanup(self): if self.proc is not None: if self.proc.poll() is not None: self.proc=None # done if self.proc is None: if self.outThread != None: self.outThread.join(3) self.outThread = None if self.errThread != None: self.errThread.join(3) self.errThread = None def close(self): self.mainwin.close() def out_handler_thread(self,p): print("out_handler_thread starts...") #self.event.set() try: while True: # print("read data: ") data = p.read(1)#.decode("utf-8") if not data: break z=str2zx(data) sys.stdout.write(data) sys.stdout.flush() for c in z: self.mainwin.prtchar(c) finally: print("Shell Out") def periodic(self): if self.proc is not None: # ongoing, see if done if self.proc.poll() is not None: self.end_cleanup() self.print_help() pass#self.event.wait(timeout=0.1) def kb_event(self,win,zxchar): s=zx2str( [zxchar] ) if s in 'xX' or zxchar==12: if self.proc: self.proc.terminate() else: self.close() self.active=False self.mainwin.close() self.revent.remove() app.clear() return elif s in 'uU': if self.proc is None: self.start()
class Shutdown: def __init__(self, mgr): self.mrg = mgr self.mainwin = TextWindow(mgr, 18, 12, 6, 5, border=WindowBorderFrameShadow(), kb_event=self.kb_event, cursor_off=True) self.print_help() def print_help(self): self.mainwin.prttxt(str2zx('\n', upper_inv=True)) self.mainwin.prttxt(str2zx(' ZXPI SHUTDOWN \n', inverse=True)) self.mainwin.prttxt( str2zx('\n\n S shut down pi \n\n X return + go on\n', upper_inv=True)) def close(self): self.mainwin.close() def kb_event(self, win, zxchar): s = zx2str([zxchar]) if s in 'sS' or zxchar == 12: if "Linux" in platform.system(): self.mainwin.cls() self.mainwin.prttxt( str2zx('\nshutdown initiated\n\n good bye.', upper_inv=True)) self.mrg.update(wait_till_sync_done=True) subprocess.run( ["sudo", "shutdown", "-h", "0"] ) # sudo is reqired if the process was started via /etc/rc.local else: self.mainwin.prttxt( str2zx('\nshutdown not supported on %s host.' % (platform.system()), upper_inv=False)) elif s in 'xX': self.close() app.clear() return elif s in 'uU': if self.proc is None: self.start() else: self.mainwin.cls() self.print_help()
class AppFileBrowser: def __init__(self, mgr): self.mgr = mgr self.mainwin = TextWindow(mgr, 30, 22, 1, 1, border=WindowBorderFrame(), kb_event=self.kb_event, cursor_off=True) self.homecwd = Path.cwd().parent / 'zxroot' self.cwd = self.homecwd self.cwdfiles = [] self.show_offset = 0 self.max_lines = 16 self.f_index_str = '1234567890ABCDEFGHI' self.f_index = str2zx(self.f_index_str) self.actual_lines = 0 self.get_dir() self.show_dir() def get_dir(self): try: self.cwdfiles = [e for e in self.cwd.iterdir()] self.cwdfiles.sort() except PermissionError: print("PermissionError") self.show_offset = 0 def show_dir(self): self.mainwin.cls() xs = self.mainwin.xsize # current path self.mainwin.prttxt(str2zx(str(self.cwd)[-xs:])) # directory self.mainwin.set_prtpos(0, 2) numf = len(self.cwdfiles) actual_lines = min(self.max_lines, numf - self.show_offset) for linenum in range(actual_lines): f = self.cwdfiles[linenum + self.show_offset] dirchar = 4 if f.is_dir() else ZXCHAR_BLANK self.mainwin.prttxt([ self.f_index[linenum] | ZXCHAR_INV_FLG, ZXCHAR_BLANK, dirchar ] + str2zx(f.name[:xs - 4] + '\n')) self.mainwin.set_prtpos(0, self.max_lines + 2) # Show bas to orient if numf <= self.max_lines: self.mainwin.prttxt(str2zx('_' * xs)) else: s1 = self.show_offset * xs // numf s2 = s1 + actual_lines * xs // numf for i in range(xs): self.mainwin.prtchar(131 if s1 <= i <= s2 else 9) self.mainwin.set_prtpos(1, self.max_lines + 4) self.mainwin.prttxt( str2zx('%s-%s' % (self.f_index_str[0], self.f_index_str[actual_lines - 1]), inverse=True)) self.mainwin.prttxt(str2zx(':select', upper_inv=True)) self.mainwin.prttxt( str2zx(' Prev', upper_inv=True if self.show_offset > 0 else False)) self.mainwin.prttxt( str2zx(' Next', upper_inv=True if self.show_offset + self.max_lines < len(self.cwdfiles) else False)) self.mainwin.prttxt( str2zx(' Up', upper_inv=True if self.cwd.parents else False)) def kb_event(self, win, zxchar): #win.prtchar(zxchar) s = zx2str([zxchar]) redraw = False if s in 'nN': self.show_offset += self.max_lines redraw = True elif zxchar == 12: # break mwin = self.mgr.show_msg_win(str2zx("exit. bye.")) raise Exception('Exit') elif s in 'pP': self.show_offset -= self.max_lines redraw = True elif s in 'uUxX': if self.cwd.parents: self.cwd = self.cwd.parents[0] self.get_dir() redraw = True elif s in 'hH': # Home directory self.cwd = self.homecwd self.get_dir() redraw = True elif s in 'wW': self.mgr.show_dialog(str2zx('press NEWLINE', upper_inv=True)) elif zxchar in self.f_index: ix = self.f_index.index(zxchar) + self.show_offset if ix < len(self.cwdfiles): fi = self.cwdfiles[ix] if fi.is_dir(): self.cwd = fi self.get_dir() redraw = True elif fi.suffix.lower() == '.p': name = str(fi) print("LOAD ", name) mwin = self.mgr.show_msg_win( str2zx("load %s .." % (fi.stem))) mwin.close() self.mgr.server.load_p_file(name) #time.sleep(0.5) # todo remove, was just for diag elif fi.suffix.lower() == '.py': mwin = self.mgr.show_msg_win( str2zx("open %s .." % (fi.stem))) try: spath = self.cwdfiles[ix] target = Path.cwd( ) / 'apps' / 'tmp' / self.cwdfiles[ix].name if spath != target: copyfile(str(spath), str(target)) print("Copy from ", str(spath)) print("Copy to ", str(target)) module = "apps.tmp." + fi.stem # we are already in apps newmod = importlib.import_module(module) importlib.reload(newmod) mwin.close() newmod.start(self.mgr) except Exception as e: mwin.close() print(e) traceback.print_exc() self.mgr.show_dialog(str2zx("error loading module")) # eval("print(globals())") # print("Eval GLOB",modcmd) # eval("print(globals())", globals()) # r=eval(modcmd, globals()) # print("LOADed PYTHON ") elif fi.suffix.lower() in ('.zxscr', '.zxmovie'): try: apps.media_viewer.start(self.mgr, fi) except Exception as e: print(e) traceback.print_exc() self.mgr.show_dialog(str2zx("error showing file")) if redraw: self.show_offset = min(self.show_offset, len(self.cwdfiles) - 2) self.show_offset = max(0, self.show_offset) self.show_dir()
class AppPiCam: def __init__(self, mgr): self.mgr = mgr self.mainwin = TextWindow(mgr, 32, 24, 0, 0, kb_event=self.kb_event, cursor_off=True) self.ctrlwin = None self.ctrlwin_timeout = time.time() + 20 self.edlin = None self.show_offset = 0 self.max_lines = 16 self.f_index_str = '1234567890ABCDEFGHI' self.f_index = str2zx(self.f_index_str) self.actual_lines = 0 self.charmap = [15] * 256 self.build_charmap() self.cam = None self.camout = None self.app_state = AppState.SHOW self.replay_ix = 0 self.delay_s = 3.0 self.event = mgr.schedule_event(self.periodic, 1.0, 5.0) self.contrast = 0.5 self.brightness = 1.0 self.invert = False self.h_v_rot = 0 # H/V flip or rotate status as three LSB bits self.floyd_stb = False self.applied_rot = None self.check_show_ctrlwin() self.movie = [] self.last_pic = None def __enter__(self): return self def __exit__(self, _type, _value, _traceback): self.close() def close(self): self.app_state = AppState.STOP if self.event: self.event.remove() self.event = None if self.camout is not None: self.camout.close() self.camout = None if self.cam is not None: self.cam.close() self.cam = None if self.mainwin: self.mainwin.close() self.mainwin = None if self.ctrlwin: self.ctrlwin.close() self.ctrlwin = None def check_show_ctrlwin(self): if not self.ctrlwin: self.ctrlwin = TextWindow(self.mgr, 14, 13, 14, 9, border=WindowBorderFrame( str2zx('ZX LIVE CAM')), kb_event=self.kb_event, cursor_off=True) self.ctrlwin.prttxt( str2zx('F fast S slow\n\nD dith I invrt', upper_inv=True)) self.ctrlwin.prttxt(str2zx('\nP pic M movie\n', upper_inv=True)) self.ctrlwin.prttxt( str2zx('\nR rotate\n\n1-5 brightness6-0 contrast\n\nX exit', upper_inv=True)) elif time.time() > self.ctrlwin_timeout: self.ctrlwin.close() self.ctrlwin = None def show_help(self): self.mainwin.prttxt( str2zx('\n ZX LIVE CAMERA \n\n', inverse=True)) self.mainwin.prttxt( str2zx( '\n\n NEWLINE to start\n\n F fast update S slow update\n\n D dithering\n\n I invert', upper_inv=True)) self.mainwin.prttxt( str2zx('\n\n R rotate\n\n 1-5 bright\n\n 6-0 contrast\n\n X exit', upper_inv=True)) def periodic(self): startt = time.time() if self.app_state == AppState.SHOW: if self.ctrlwin and time.time() > self.ctrlwin_timeout: self.ctrlwin.close() self.ctrlwin = None if self.app_state in (AppState.SHOW, AppState.MOVIE_REC): self.last_pic = self.get_img_mono() self.mgr.update(0.08) # allow for kb inp response if self.app_state in (AppState.SHOW, AppState.MOVIE_REC): lrg = self.calc_lrg_from_array(self.last_pic) self.show_lrg(lrg) if self.app_state == AppState.MOVIE_REC: if len(self.movie) < 50: self.movie.append(self.last_pic) self.ctrlwin.set_prtpos(0, 0) self.ctrlwin.prttxt( str2zx('recording %02d' % len(self.movie), upper_inv=True)) else: self.end_movie_rec() evt_t = time.time() - startt self.event.reschedule(max(0.08, self.delay_s - evt_t), 5.0) elif self.app_state in (AppState.MOVIE_QUERY_YN, AppState.MOVIE_QUERY_NAME): if len(self.movie): if self.replay_ix >= len(self.movie): self.replay_ix = 0 lrg = self.calc_lrg_from_array(self.movie[self.replay_ix]) self.show_lrg(lrg) self.replay_ix += 1 evt_t = time.time() - startt self.event.reschedule(max(0.08, self.delay_s - evt_t), 5.0) def build_charmap(self): for pul in range(4): for pur in range(4): for pll in range(4): for plr in range(4): c = 15 ix = pul * 64 + pur * 16 + pll * 4 + plr al = (pul, pur, pll, plr) up = (pul, pur) lo = (pll, plr) if 0 not in al and 3 not in al: # just grey if sum(al) / len(al) > 1.5: c = 8 # fits to brighter edges else: c = 136 # fits to darker edges elif 0 not in up and 3 not in up and 2 not in lo and 3 not in lo: # upper grey, low black c = 138 elif 0 not in up and 3 not in up and 0 not in lo and 1 not in lo: # upper grey, low white c = 10 elif 0 not in lo and 3 not in lo and 2 not in up and 3 not in up: # low grey, upper black c = 137 elif 0 not in lo and 3 not in lo and 0 not in up and 1 not in up: # low grey, upper white c = 9 else: # binary c = 0 if pul <= 1: c += 1 if pur <= 1: c += 2 if pll <= 1: c += 4 if plr <= 1: c = c ^ 0x87 self.charmap[ix] = c #print (self.charmap) def get_img_mono(self): a = None if cam_available: if self.cam is None: self.cam = picamera.PiCamera() if self.camout is None: self.camout = picamera.array.PiYUVArray(self.cam) self.cam.resolution = (64, 48) else: self.camout.truncate(0) rotate = self.h_v_rot & 1 if rotate != self.applied_rot: self.cam.resolution = (48, 64) if rotate else (64, 48) self.applied_rot = rotate self.cam.capture(self.camout, 'yuv', use_video_port=True) a = self.camout.array[:, :, 0] if rotate: a = numpy.transpose(a) else: a = pickle.loads(p) return a def show_lrg(self, a): nr, nc = a.shape for row in range(nr): for col in range(nc): self.mainwin.setchar_raw(a[row, col], col, row) def calc_lrg_from_array(self, a): #calculate the mean value etc t = time.time() if self.h_v_rot & 4: a = numpy.fliplr(a) # H flip if self.h_v_rot & 2: a = numpy.flipud(a) # V flip if self.invert: a = 255 - a m = a.mean() / self.brightness s = a.std() * self.contrast * (1 if cam_available else random.gauss( 1.0, 0.1)) # add some dynamics if no camera is there l0 = m - s l1 = m l2 = m + s nr, nc = a.shape # optional flody-steinberg if self.floyd_stb: l0 = max(0, int(m - 2 * s)) l2 = min(255, int(m + 2 * s)) for row in range(0, nr): for col in range(0, nc): p = a[row, col] n = l2 if p > l1 else l0 err = p - n a[row, col] = n if col < nc - 1: a[row, col + 1] += err * 7 // 16 if row < nr - 1: if col >= 1: a[row + 1, col - 1] += err * 3 // 16 a[row + 1, col] += err * 5 // 16 if col < nc - 1: a[row + 1, col + 1] += err * 1 // 16 brightmap = [ 0 if b <= l0 else 3 if b >= l2 else 1 if b < l1 else 2 for b in range(256) ] #print(brightmap) #print(a.mean(),a.std()) va = numpy.zeros((nr // 2, nc // 2), dtype=int) for row in range(0, nr, 2): for col in range(0, nc, 2): # get the four points that make up a character code = 0 for b in (a[row, col], a[row, col + 1], a[row + 1, col], a[row + 1, col + 1]): code *= 4 if 0: # this seems to be much slower than the lookup below! if b < l0: c = 0 elif b > l2: c = 3 elif b < l1: c = 1 else: c = 2 code += c if c != brightmap[b]: print("FAIL") else: code += brightmap[b] va[row // 2, col // 2] = self.charmap[code] #self.mainwin.setchar_raw(self.charmap[code], col//2, row//2) #print("Display took %.2fus."%((time.time()-t)*1000000) ) # now er have an 8bit code that we map for the proper char return va def end_movie_rec(self): self.app_state = AppState.MOVIE_QUERY_YN if self.ctrlwin: self.ctrlwin.close() self.ctrlwin = TextWindow(self.mgr, 10, 1, 18, 19, border=WindowBorderFrame(), kb_event=self.kb_event_query, cursor_off=True) self.ctrlwin.prttxt(str2zx('save? Y/N', upper_inv=True)) def kb_event(self, win, zxchar): #win.prtchar(zxchar) bright = {'1': 1.5, '2': 1.2, '3': 1.0, '4': 0.83, '5': 0.67} contr = {'6': 0.2, '7': 0.33, '8': 0.5, '9': 0.8, '0': 1.2} s = zx2str([zxchar]) if s in 'xX' or zxchar == 12: self.close() return elif s in 'fF': self.delay_s = 0.15 elif s in 'sS': self.delay_s = 3.0 elif s in 'dD': self.floyd_stb = not self.floyd_stb elif s in 'iI': self.invert = not self.invert elif s in 'rR': self.h_v_rot += 1 elif s in 'pP': if self.app_state == AppState.SHOW: self.app_state = AppState.PIC_QUERY_YN if self.ctrlwin: self.ctrlwin.close() self.ctrlwin = TextWindow(self.mgr, 10, 1, 18, 19, border=WindowBorderFrame(), kb_event=self.kb_event_query, cursor_off=True) self.ctrlwin.prttxt(str2zx('save? Y/N', upper_inv=True)) elif s in 'mM': self.movie.clear() self.replay_ix = 0 if self.app_state == AppState.SHOW: self.app_state = AppState.MOVIE_REC if self.ctrlwin: self.ctrlwin.close() self.ctrlwin = TextWindow(self.mgr, 13, 1, 17, 19, border=WindowBorderFrame(), kb_event=self.kb_event_query, cursor_off=True) self.ctrlwin.prttxt(str2zx('recording', upper_inv=True)) elif s in bright: self.brightness = bright[s] elif s in contr: self.contrast = contr[s] # TODO invers, save_pic, help, exit self.ctrlwin_timeout = time.time() + 3 self.check_show_ctrlwin() self.event.reschedule(0.2, 5.0) def kb_event_query(self, win, zxchar): #win.prtchar(zxchar) s = zx2str([zxchar]) if self.app_state in (AppState.PIC_QUERY_NAME, AppState.MOVIE_QUERY_NAME): if zxchar in (117, 118): # enter,break if zxchar == 118: # enter self.edlin.kb_event(zxchar) if self.app_state == AppState.PIC_QUERY_NAME: if self.edlin.val: # safe pic name = zx2str(self.edlin.val, to_lower=True).strip() #path mwin = self.mgr.show_msg_win(str2zx("save pic ..")) p = zxpi_paths.get_current_work_path() / 'pics' if not p.exists(): p.mkdir(parents=True) n = p / (name + '.zxscr') with n.open('wb') as f: lrg = self.calc_lrg_from_array(self.last_pic) nr, nc = lrg.shape for row in range(nr): #for col in range(nc): f.write(bytes([v for v in lrg[row]])) print("Saved to", str(n)) mwin.close() elif self.app_state == AppState.MOVIE_QUERY_NAME: if self.edlin.val: # save movie name = zx2str(self.edlin.val, to_lower=True).strip() #path pth = zxpi_paths.get_current_work_path() / 'movies' if not pth.exists(): pth.mkdir(parents=True) n = pth / (name + '.zxmovie') mwin = self.mgr.show_msg_win( str2zx("save movie ..")) mv_dat = bytearray() with n.open('wb') as f: for p in self.movie: lrg = self.calc_lrg_from_array(p) nr, nc = lrg.shape for row in range(nr): #for col in range(nc): rowdat = bytearray( [v for v in lrg[row]]) mv_dat += rowdat f.write(rowdat) print("Saved as", str(n)) self.mgr.update(0.1) n = pth / (name + '.p') with n.open('wb') as f: f.write( create_comp_viewer(compress_scr(mv_dat))) mwin.close() if self.edlin: self.edlin.close() self.edlin = None self.app_state = AppState.SHOW self.ctrlwin_timeout = 0 if self.ctrlwin: self.ctrlwin.close() self.ctrlwin = None else: self.edlin.kb_event(zxchar) elif self.app_state in (AppState.MOVIE_REC, ): self.end_movie_rec() else: if s in 'yYzZ': if self.app_state in (AppState.PIC_QUERY_YN, AppState.MOVIE_QUERY_YN): self.app_state = AppState.PIC_QUERY_NAME if self.app_state == AppState.PIC_QUERY_YN else AppState.MOVIE_QUERY_NAME if self.ctrlwin: self.ctrlwin.close() self.ctrlwin = TextWindow(self.mgr, 12, 2, 18, 19, border=WindowBorderFrame(), kb_event=self.kb_event_query, cursor_off=True) self.ctrlwin.prttxt(str2zx('file name:', upper_inv=True)) self.edlin = LinEd(self.ctrlwin, 0, 1, 11, maxchar=255, history=None) else: self.app_state = AppState.SHOW if self.ctrlwin: self.ctrlwin.close() self.ctrlwin = None self.event.reschedule(0.2, 5.0)
class IrcClient: def __init__(self, mgr): self.mgr = mgr self.mainwin = TextWindow(mgr, 32, 20, 0, 0) self.inp_win = TextWindow(mgr, 30, 2, 1, 21, border=WindowBorderFrame(), kb_event=self.kb_event, cursor_off=True) self.ed = None self.nick = 'zx-user' self.server = "irc.zxq.de" self.pword = '' self.port = 6667 self.inp_mode = InpMode.MENU self.listener = ListenerThread(self.mainwin) self.choose_site() self.revent = mgr.schedule_event(self.periodic, 2, 2) self.channel = '' def periodic(self): if self.inp_mode == InpMode.ONLINE and not self.listener.conn: self.mainwin.prttxt(str2zx('\n\nDISCONNECT\n\n', upper_inv=True)) self.disconnect() self.mgr.update(1.5) self.choose_site() def choose_site(self): self.mainwin.cls() self.mainwin.prttxt(str2zx('\n\n', upper_inv=True)) self.mainwin.prttxt( str2zx(' ZXPI IRC CHAT CLIENT ', inverse=True)) self.mainwin.prttxt( str2zx('\n\n N >nick (%s)' % (self.nick), upper_inv=True)) self.mainwin.prttxt( str2zx('\n\n S >server (%s)' % (self.server), upper_inv=True)) self.mainwin.prttxt( str2zx('\n\n P >port (%d)' % (self.port), upper_inv=True)) self.mainwin.prttxt( str2zx('\n\n W >password (%s)' % ('*' * len(self.pword) if len(self.pword) else 'none'), upper_inv=True)) self.mainwin.prttxt( str2zx('\n\n C connect \n\n\n X exit\n\n', upper_inv=True)) self.inp_win.cls() self.inp_win.prttxt(str2zx('please select')) def connect(self): self.revent.reschedule(15.0, 1.0) # give 3 sec for connect self.listener.start((self.server, self.port), self.nick, self.pword) self.inp_mode = InpMode.ONLINE self.mainwin.cls() self.mainwin.prttxt( str2zx('\n\nCONNECT to %s..\n\n' % (self.server), upper_inv=True)) def disconnect(self): self.listener.close() self.inp_mode = InpMode.MENU def close(self): self.revent.remove() self.disconnect() if self.ed: self.ed.close() self.mainwin.close() self.inp_win.close() def kb_event(self, win, char): if self.inp_mode == InpMode.MENU: if char == 56: # S self.inp_win.cls() self.inp_win.prttxt( str2zx(' please enter server address: ', inverse=True)) self.ed = LinEd(self.inp_win, 0, 1, 29, 255, bytes(str2zx(self.server))) self.inp_mode = InpMode.INP_SRV elif char == 53: # P self.inp_win.cls() self.inp_win.prttxt( str2zx(' please enter port number: ', inverse=True)) self.ed = LinEd(self.inp_win, 0, 1, 6, 5, bytes(str2zx(str(self.port)))) self.inp_mode = InpMode.INP_PORT elif char == 60: # W self.inp_win.cls() self.inp_win.prttxt( str2zx(' please enter pass word: ', inverse=True)) self.ed = LinEd(self.inp_win, 0, 1, 29, 255) self.inp_mode = InpMode.INP_PWORD elif char == 51: # N self.inp_win.cls() self.inp_win.prttxt( str2zx(' please enter nickname: ', inverse=True)) self.ed = LinEd(self.inp_win, 0, 1, 29, 255, bytes(str2zx(self.nick))) self.inp_mode = InpMode.INP_NICK elif char == 40: # C self.inp_win.cls() self.inp_win.prttxt( str2zx(' /join /part /quit /help', inverse=False)) self.ed = LinEd(self.inp_win, 0, 1, 29, 255) self.connect() elif char == 61 or char == 117: # x or break self.close() app.clear() # TODO clear threads elif self.inp_mode in (InpMode.INP_SRV, InpMode.INP_PORT, InpMode.INP_PWORD, InpMode.INP_NICK): if char in (117, 118): # enter,break if char == 118: # enter if self.inp_mode == InpMode.INP_SRV: if self.ed.val.strip(): self.server = zx2str(self.ed.val, to_lower=True) if self.inp_mode == InpMode.INP_NICK: if self.ed.val.strip(): self.nick = zx2str(self.ed.val, to_lower=True) elif self.inp_mode == InpMode.INP_PWORD: self.pword = zx2str(self.ed.val, to_lower=True) else: try: self.port = int(zx2str(self.ed.val)) except: pass self.ed.close() self.ed = None self.inp_mode = InpMode.MENU self.choose_site() else: self.ed.kb_event(char) elif self.inp_mode == InpMode.ONLINE: if char == 118: # enter s = zx2str(self.ed.val, to_lower=True).strip() self.ed.clear() if s.startswith("/q"): self.listener.send('QUIT :bye\r\n') time.sleep(0.1) self.disconnect() self.ed.close() self.ed = None self.inp_mode = InpMode.MENU self.choose_site() elif s.startswith("/join ") and len(s.split()) == 2: self.channel = '#' + s.split()[1] self.listener.send('JOIN %s\r\n' % (self.channel)) elif s.startswith("/part") and self.channel: self.listener.send('PART %s\r\n' % (self.channel)) self.channel = '' elif s.startswith("/list"): self.listener.send('LIST\r\n') elif s.startswith("/names"): self.listener.send('NAMES %s\r\n' % (self.channel)) elif s.startswith("/h"): self.mainwin.cls() z = str2zx('\n\n HELP on the irc client usage \n\n', inverse=True) z += str2zx( '\n/JOIN <mychannel> join channel\n (just omit the hash tag)\n', upper_inv=True) z += str2zx('\n/PART leave the channel\n', upper_inv=True) z += str2zx('\n/NAMES show who is there\n', upper_inv=True) z += str2zx('\n/LIST list all channels\n', upper_inv=True) z += str2zx('\n/QUIT exit from server\n', upper_inv=True) z += str2zx( '\n after joining, type a message to all users in that channel\n', upper_inv=True) z += str2zx('\n have fun \n', inverse=True) self.mainwin.prttxt(z) elif s.startswith("/"): z = str2zx('\n??? unknown cmd %s' % (s.strip())) self.mainwin.prttxt(z) else: self.listener.send('PRIVMSG %s :%s\r\n' % (self.channel, s)) z = str2zx('\n<%s> %s' % (self.nick, s.strip())) self.mainwin.prttxt(z) else: self.ed.kb_event(char)
class AppWebZxForumDe: def __init__(self, mgr): self.mgr = mgr self.mainwin = TextWindow(mgr, 32, 24, 0, 0, kb_event=self.kb_event, cursor_off=True) self.show_offset = 0 self.max_lines = 20 self.do_exit = False self.url = 'https://forum.tlienhard.com/phpBB3/viewforum.php?f=2' #print(r.text) self.show() def show(self): self.mainwin.cls() self.mainwin.prttxt( str2zx("wait for \n" + self.url[:28] + '..\n', upper_inv=False)) self.mgr.update(wait_till_sync_done=True) while True: try: r = requests.get(self.url, timeout=7.0) if r.status_code == requests.codes.ok: break self.mainwin.prttxt( str2zx("retrieved %d, try again..\n" % (r.status_code), upper_inv=False)) except ConnectionError as e: self.mainwin.prttxt( str2zx("error %s, try again..\n" % (str(e)), upper_inv=False)) except requests.RequestException as e: self.mainwin.prttxt( str2zx("retrieved %s, try again..\n" % (str(e)), upper_inv=False)) self.mgr.update(0.5) if self.do_exit: return self.mainwin.prttxt(str2zx("parse..\n", upper_inv=False)) self.mgr.update(wait_till_sync_done=True) if self.do_exit: return #print(r.text) parser = MyHTMLParser() parser.feed(r.text) self.mainwin.cls() self.mainwin.prttxt(str2zx(self.url[:32], inverse=True)) self.mainwin.prttxt([ZXCHAR_NEWLINE] + [10] * 32) d = parser.out_data lines = 0 for entry in d: hd, nm, dt = entry numchar = len(hd) + len(nm) + len(dt) + 1 numlines = (numchar + 31) // 32 addspc = ' ' * (32 * numlines - numchar) if lines + numlines + 1 > self.max_lines: break lines += numlines + 1 self.mainwin.prttxt(str2zx(hd, upper_inv=False)) self.mainwin.prttxt(str2zx(addspc)) self.mainwin.prttxt(str2zx(nm, inverse=True)) self.mainwin.prttxt(str2zx(' ')) self.mainwin.prttxt(str2zx(dt, inverse=False)) self.mainwin.prttxt([10] * 32) def close(self): if self.mainwin is not None: self.mainwin.close() self.mainwin = None def kb_event(self, win, zxchar): #win.prtchar(zxchar) s = zx2str([zxchar]) if s in 'xXuU' or zxchar == 12: self.do_exit = True self.close() else: self.show()