1import os 2import sys 3import time 4 5import asciinema.asciicast.events as ev 6from asciinema.term import raw, read_blocking 7 8 9class Player: 10 11 def play(self, asciicast, idle_time_limit=None, speed=1.0): 12 try: 13 stdin = open('/dev/tty') 14 with raw(stdin.fileno()): 15 self._play(asciicast, idle_time_limit, speed, stdin) 16 except Exception: 17 self._play(asciicast, idle_time_limit, speed, None) 18 19 def _play(self, asciicast, idle_time_limit, speed, stdin): 20 idle_time_limit = idle_time_limit or asciicast.idle_time_limit 21 22 stdout = asciicast.stdout_events() 23 stdout = ev.to_relative_time(stdout) 24 stdout = ev.cap_relative_time(stdout, idle_time_limit) 25 stdout = ev.to_absolute_time(stdout) 26 stdout = ev.adjust_speed(stdout, speed) 27 28 base_time = time.time() 29 ctrl_c = False 30 paused = False 31 pause_time = None 32 33 for t, _type, text in stdout: 34 delay = t - (time.time() - base_time) 35 36 while stdin and not ctrl_c and delay > 0: 37 if paused: 38 while True: 39 data = read_blocking(stdin.fileno(), 1000) 40 41 if 0x03 in data: # ctrl-c 42 ctrl_c = True 43 break 44 45 if 0x20 in data: # space 46 paused = False 47 base_time = base_time + (time.time() - pause_time) 48 break 49 50 if 0x2e in data: # period (dot) 51 delay = 0 52 pause_time = time.time() 53 base_time = pause_time - t 54 break 55 else: 56 data = read_blocking(stdin.fileno(), delay) 57 58 if not data: 59 break 60 61 if 0x03 in data: # ctrl-c 62 ctrl_c = True 63 break 64 65 if 0x20 in data: # space 66 paused = True 67 pause_time = time.time() 68 slept = t - (pause_time - base_time) 69 delay = delay - slept 70 71 if ctrl_c: 72 break 73 74 sys.stdout.write(text) 75 sys.stdout.flush() 76