diff options
Diffstat (limited to 'presentty/presentty.py')
-rw-r--r-- | presentty/presentty.py | 162 |
1 files changed, 162 insertions, 0 deletions
diff --git a/presentty/presentty.py b/presentty/presentty.py new file mode 100644 index 0000000..35e19c1 --- /dev/null +++ b/presentty/presentty.py | |||
@@ -0,0 +1,162 @@ | |||
1 | # Copyright (C) 2015 James E. Blair <corvus@gnu.org> | ||
2 | # | ||
3 | # This program is free software: you can redistribute it and/or modify | ||
4 | # it under the terms of the GNU General Public License as published by | ||
5 | # the Free Software Foundation, either version 3 of the License, or | ||
6 | # (at your option) any later version. | ||
7 | # | ||
8 | # This program is distributed in the hope that it will be useful, | ||
9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | # GNU General Public License for more details. | ||
12 | # | ||
13 | # You should have received a copy of the GNU General Public License | ||
14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
15 | |||
16 | import argparse | ||
17 | import os | ||
18 | import sys | ||
19 | import time | ||
20 | |||
21 | import urwid | ||
22 | |||
23 | import slide | ||
24 | import server | ||
25 | import rst | ||
26 | import palette | ||
27 | |||
28 | |||
29 | class Presenter(object): | ||
30 | def __init__(self, palette): | ||
31 | blank = urwid.Text(u'') | ||
32 | self.blank = slide.UrwidSlide('Blank', None, blank, | ||
33 | palette['_default']) | ||
34 | self.current = self.blank | ||
35 | self.program = [] | ||
36 | self.palette = palette | ||
37 | self.pos = -1 | ||
38 | self.loop = urwid.MainLoop(self.blank, | ||
39 | unhandled_input=self.unhandledInput) | ||
40 | self.loop.screen.set_terminal_properties(colors=256) | ||
41 | |||
42 | self.server_pipe_in = self.loop.watch_pipe(self.serverData) | ||
43 | r,w = os.pipe() | ||
44 | self.server_pipe_out_read = os.fdopen(r) | ||
45 | self.server_pipe_out_write = w | ||
46 | self.server = server.ConsoleServer(self) | ||
47 | self.server.start() | ||
48 | |||
49 | def serverData(self, data): | ||
50 | parts = data.split() | ||
51 | if parts[0] == 'jump': | ||
52 | try: | ||
53 | index = int(parts[1]) | ||
54 | except Exception: | ||
55 | os.write(self.server_pipe_out_write, 'err\n') | ||
56 | return | ||
57 | if index < 0 or index > len(self.program)-1: | ||
58 | os.write(self.server_pipe_out_write, 'err\n') | ||
59 | return | ||
60 | self.transitionTo(index) | ||
61 | os.write(self.server_pipe_out_write, 'ok\n') | ||
62 | elif parts[0] == 'next': | ||
63 | self.nextSlide() | ||
64 | os.write(self.server_pipe_out_write, 'ok\n') | ||
65 | elif parts[0] == 'prev': | ||
66 | self.prevSlide() | ||
67 | os.write(self.server_pipe_out_write, 'ok\n') | ||
68 | |||
69 | def setProgram(self, program): | ||
70 | self.program = program | ||
71 | |||
72 | def run(self): | ||
73 | self.loop.set_alarm_in(0, self.nextSlide) | ||
74 | self.loop.run() | ||
75 | |||
76 | def unhandledInput(self, key): | ||
77 | if key in ('right', 'page down'): | ||
78 | self.nextSlide() | ||
79 | elif key in ('left', 'page up'): | ||
80 | self.prevSlide() | ||
81 | |||
82 | def transitionTo(self, index, forward=True): | ||
83 | self.pos = index | ||
84 | current_slide = self.current | ||
85 | new_slide = self.program[index] | ||
86 | if forward: | ||
87 | transition = new_slide.transition | ||
88 | new_slide.resetProgressive() | ||
89 | else: | ||
90 | transition = current_slide.transition | ||
91 | new_slide.resetProgressive(True) | ||
92 | current_slide.stopAnimation() | ||
93 | if forward: | ||
94 | transition.setTargets(current_slide, new_slide) | ||
95 | else: | ||
96 | transition.setTargets(new_slide, current_slide) | ||
97 | self.loop.widget = transition | ||
98 | duration = transition.getDuration() | ||
99 | start = time.time() | ||
100 | now = start | ||
101 | end = start + duration | ||
102 | while duration: | ||
103 | if forward: | ||
104 | progress = min(1-((end-now)/duration), 1.0) | ||
105 | else: | ||
106 | progress = max(((end-now)/duration), 0.0) | ||
107 | transition.setProgress(progress) | ||
108 | self.loop.draw_screen() | ||
109 | now = time.time() | ||
110 | if now >= end: | ||
111 | break | ||
112 | end = time.time() | ||
113 | self.loop.widget = new_slide | ||
114 | self.current = new_slide | ||
115 | self.loop.draw_screen() | ||
116 | current_slide.resetAnimation() | ||
117 | new_slide.startAnimation(self.loop) | ||
118 | |||
119 | def nextSlide(self, loop=None, data=None): | ||
120 | if self.current.nextProgressive(): | ||
121 | return | ||
122 | if self.pos+1 == len(self.program): | ||
123 | return | ||
124 | self.transitionTo(self.pos+1) | ||
125 | |||
126 | def prevSlide(self, loop=None, data=None): | ||
127 | if self.current.prevProgressive(): | ||
128 | return | ||
129 | if self.pos == 0: | ||
130 | return | ||
131 | self.transitionTo(self.pos-1, forward=False) | ||
132 | |||
133 | def main(): | ||
134 | parser = argparse.ArgumentParser( | ||
135 | description='Console-based presentation system') | ||
136 | parser.add_argument('--light', dest='light', | ||
137 | default=False, | ||
138 | action='store_true', | ||
139 | help='use a black on white palette') | ||
140 | parser.add_argument('--warnings', dest='warnings', | ||
141 | default=False, | ||
142 | action='store_true', | ||
143 | help='print RST parser warnings and exit if any') | ||
144 | parser.add_argument('file', | ||
145 | help='presentation file (RST)') | ||
146 | args = parser.parse_args() | ||
147 | if args.light: | ||
148 | plt = palette.LIGHT_PALETTE | ||
149 | else: | ||
150 | plt = palette.DARK_PALETTE | ||
151 | hinter = slide.ScreenHinter() | ||
152 | parser = rst.PresentationParser(plt, hinter) | ||
153 | program = parser.parse(open(args.file).read(), args.file) | ||
154 | if args.warnings: | ||
155 | w = parser.warnings.getvalue() | ||
156 | if w: | ||
157 | print w | ||
158 | sys.exit(1) | ||
159 | p = Presenter(plt) | ||
160 | p.setProgram(program) | ||
161 | hinter.setScreen(p.loop.screen) | ||
162 | p.run() | ||