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