summaryrefslogtreecommitdiff
path: root/presentty/presentty.py
diff options
context:
space:
mode:
Diffstat (limited to 'presentty/presentty.py')
-rw-r--r--presentty/presentty.py162
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
16import argparse
17import os
18import sys
19import time
20
21import urwid
22
23import slide
24import server
25import rst
26import palette
27
28
29class 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
133def 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()