ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/truck/DashInterface/DashInterface.cpp
Revision: 53
Committed: 2008-07-12T17:00:15-07:00 (16 years, 11 months ago) by douglas
File size: 8317 byte(s)
Log Message:
64bit cleanify.

File Contents

# Content
1 // Dash Interface
2 //
3 // Douglas Thrift
4 //
5 // $Id$
6
7 #include <algorithm>
8 #include <iomanip>
9 #include <iostream>
10 #include <sstream>
11
12 #include <foreach.hpp>
13 #include <hash.hpp>
14 #include <regex.hpp>
15 #include <scopes.hpp>
16 #include <timing.hpp>
17
18 #include <GPS.hpp>
19
20 #include <sys/types.h>
21 #include <sys/sysctl.h>
22 #include <sys/utsname.h>
23
24 #include "Display.hpp"
25 #include "MenuList.hpp"
26
27 bool debug(false);
28
29 class DashInterface;
30
31 void Buttons(Display::KeyActivity activity, DashInterface *interface);
32
33 class DashInterface
34 {
35 enum Mode { Uname, Music, English, Metric, Nautical, Menu } mode, previous;
36 enum { Running, Audio };
37 enum { Stopped, Paused, Playing } audio;
38 Timing::Time now;
39 Audacious::Audacious audacious;
40 //GPS::GPS gps;
41 Music::Library library;
42 MenuList *list;
43 bool append;
44 Display display;
45 Pthreads::ThreadMutex displayLock;
46
47 void Mode_(bool change = false)
48 {
49 if (mode != Menu)
50 {
51 char when[16];
52
53 std::strftime(when, sizeof (when), "%l:%M:%S %p %Z", Timing::LocalTime(now));
54
55 display.Set(2, 0, when);
56 }
57
58 switch (mode)
59 {
60 case Uname:
61 return Uname_(change);
62 case Music:
63 if (audacious.IsRunning())
64 {
65 int position(audacious.GetPlaylistPosition());
66 std::string artist(Filter(audacious.GetTupleFieldData(_B("artist"), position)));
67
68 artist.resize(20, ' ');
69 display.Set(0, 1, artist);
70
71 std::string title(Filter(audacious.GetTupleFieldData(_B("title"), position)));
72
73 title.resize(20, ' ');
74 display.Set(0, 2, title);
75
76 int played(audacious.GetOutputTime() / 1000);
77 int left(audacious.GetPlaylistTime(position) / 1000 - played);
78 char *times;
79
80 ::asprintf(&times, "%2i:%02i -%2i:%02i", played / 60, played % 60, left / 60, left % 60);
81
82 std::string times_(times);
83
84 std::free(times);
85
86 times_.resize(20, ' ');
87 display.Set(0, 3, times_);
88 }
89 else
90 {
91 display.Set(0, 1, std::string(20, ' '));
92 display.Set(0, 2, std::string(20, ' '));
93 display.Set(0, 3, _B(" -:-- - -:-- "));
94 }
95
96 return;
97 case English:
98 case Metric:
99 case Nautical:
100 display.Set(0, 1, _B("STUB: GPS ") + (mode == English ? _B("English ") : mode == Metric ? _B("Metric ") : _B("Nautical ")));
101 display.Set(0, 2, std::string(20, ' '));
102 display.Set(0, 3, std::string(20, ' '));
103
104 return;
105 case Menu:
106 if (change)
107 {
108 display.SetCursorPosition(19, 0);
109 display.SetCursorStyle(Display::InvertingBlinkingBlock);
110
111 append = true;
112 list = new TopList(display, audacious, append, library);
113
114 list->Render();
115 }
116 }
117 }
118
119 void Uname_(bool change = false)
120 {
121 if (!now || change)
122 {
123 utsname os;
124
125 ::uname(&os);
126
127 static Pcre::RegEx version(_B("^(\\d+\\.\\d+)-([A-Z])[A-Z]*(-p\\d+)?.*$"));
128 Pcre::RegEx::Match match(version(os.release));
129 std::string name(os.sysname + _B(" ") + match[1] + match[2] + match[3]);
130
131 name.resize(20, ' ');
132 display.Set(0, 1, name);
133 }
134
135 int mib[] = { CTL_KERN, KERN_BOOTTIME };
136 timeval boottime;
137 size_t size(sizeof (boottime));
138
139 if (now && ::sysctl(mib, 2, &boottime, &size, NULL, 0) != -1 && boottime.tv_sec != 0)
140 {
141 time_t uptime(now - boottime.tv_sec);
142
143 if (uptime > 60)
144 uptime += 30;
145
146 char *when;
147 int days(uptime / 86400);
148
149 uptime %= 86400;
150
151 int hours(uptime / 3600);
152
153 uptime %= 3600;
154
155 int minutes(uptime / 60), seconds(uptime % 60);
156
157 ::asprintf(&when, "%i+%02i:%02i:%02i", days, hours, minutes, seconds);
158
159 std::string then(when);
160
161 std::free(when);
162
163 then.resize(17, ' ');
164
165 if (change)
166 display.Set(0, 2, _B("up ") + then);
167 else
168 display.Set(3, 2, then);
169 }
170 else
171 display.Set(0, 2, _B("up -+--:--:-- "));
172
173 double averages[3];
174
175 if (::getloadavg(averages, 3) == -1 || !now)
176 display.Set(0, 3, _B("-.--, -.--, -.-- "));
177 else
178 {
179 char *load;
180
181 ::asprintf(&load, "%.2f, %.2f, %.2f", averages[0], averages[1] , averages[2]);
182
183 std::string load_(load);
184
185 std::free(load);
186
187 load_.resize(20, ' ');
188 display.Set(0, 3, load_);
189 }
190 }
191
192 void Buttons(Display::KeyActivity activity)
193 {
194 _synchronized (displayLock)
195 if (mode != Menu)
196 {
197 bool change(false);
198
199 switch (activity)
200 {
201 case Display::UpPress:
202 --mode;
203
204 goto change;
205 case Display::DownPress:
206 ++mode;
207
208 goto change;
209 case Display::LeftPress:
210 if (audacious.IsRunning())
211 audacious.PlaylistPrevious();
212
213 goto update;
214 case Display::RightPress:
215 if (audacious.IsRunning())
216 audacious.PlaylistNext();
217
218 goto update;
219 case Display::EnterPress:
220 previous = mode;
221 mode = Menu;
222
223 goto change;
224 case Display::ExitPress:
225 if (audacious.IsRunning())
226 audacious.PlayPause();
227
228 goto update;
229 default:
230 return;
231 }
232
233 change: change = true;
234
235 update: Mode_(change);
236 }
237 else
238 switch (activity)
239 {
240 case Display::UpPress:
241 return (--*list).Render();
242 case Display::DownPress:
243 return (++*list).Render();
244 case Display::LeftPress:
245 list = list->Left();
246
247 goto render;
248 case Display::RightPress:
249 list = list->Right();
250
251 goto render;
252 case Display::EnterPress:
253 list = list->Enter();
254
255 render: if (list != NULL)
256 return list->Render();
257
258 goto exit;
259 case Display::ExitPress:
260 delete list;
261
262 exit: mode = previous;
263
264 display.SetCursorStyle(Display::NoCursor);
265 display.Set(0, 0, _B(" "));
266 display.Set(18, 0, _B(" "));
267
268 Mode_(true);
269 default:
270 return;
271 }
272 }
273
274 public:
275 DashInterface(const std::string &device) : mode(Uname), audio(Stopped), display(device, reinterpret_cast<Display::Callback>(::Buttons), this)
276 {
277 _synchronized (displayLock)
278 {
279 display.Clear();
280 display.SetCursorStyle(Display::NoCursor);
281 display.SetBacklight(100);
282 display.Set(2, 0, _B("--:--:-- -- ---"));
283
284 display.Set(Running, Display::Green, 0);
285 display.Set(Running, Display::Red, 100);
286 display.Set(Audio, Display::Green, 0);
287 display.Set(Audio, Display::Red, 100);
288
289 uint8_t mask(Display::Up | Display::Enter | Display::Cancel | Display::Left | Display::Right | Display::Down);
290
291 display.KeyReporting(mask, mask);
292
293 Uname_();
294
295 display.Store();
296 display.Set(Running, Display::Green, 100);
297 display.Set(Running, Display::Red, 0);
298 }
299 }
300
301 void Run()
302 {
303 _forever
304 {
305 _synchronized (displayLock)
306 {
307 now = Timing::GetTimeOfDay();
308
309 if (audacious.IsRunning() && audacious.IsPlaying())
310 if (audacious.IsPaused())
311 {
312 if (audio != Paused)
313 {
314 display.Set(Audio, Display::Green, 100);
315 display.Set(Audio, Display::Red, 100);
316
317 audio = Paused;
318 }
319 }
320 else
321 {
322 if (audio != Playing)
323 {
324 display.Set(Audio, Display::Green, 100);
325 display.Set(Audio, Display::Red, 0);
326
327 audio = Playing;
328 }
329 }
330 else if (audio != Stopped)
331 {
332 display.Set(Audio, Display::Green, 0);
333 display.Set(Audio, Display::Red, 100);
334
335 audio = Stopped;
336 }
337
338 Mode_();
339 }
340
341 Timing::NanoSleep(Timing::Time(1) -= Timing::Time(0, Timing::GetTimeOfDay().GetNanoseconds()));
342 }
343 }
344
345 friend void Buttons(Display::KeyActivity activity, DashInterface *interface)
346 {
347 interface->Buttons(activity);
348 }
349
350 inline friend Mode &operator ++(Mode &mode)
351 {
352 return mode = Mode((mode + 1) % Menu);
353 }
354
355 inline friend Mode &operator --(Mode &mode)
356 {
357 return mode = Mode((Menu + mode - 1) % Menu);
358 }
359 };
360
361 int main(int argc, char *argv[])
362 {
363 std::string device;
364
365 {
366 Pcre::RegEx devicePath(_B("^-device=(/.+)$"));
367 Pcre::RegEx deviceNumber(_B("^-device=([0-9]+)$"));
368 Pcre::RegEx deviceName(_B("^-device=(.+)$"));
369
370 for (char **arg = argv + 1; *arg; ++arg)
371 {
372 Pcre::RegEx::Match match;
373
374 if (*arg == _B("-debug"))
375 debug = true;
376 else if (match = devicePath(*arg))
377 device = match[1];
378 else if (match = deviceNumber(*arg))
379 device = _B("/dev/cuaU") + match[1];
380 else if (match = deviceName(*arg))
381 device = _B("/dev/") + match[1];
382 else
383 goto usage;
384 }
385 }
386
387 if (device.empty())
388 {
389 usage: std::cout << _B("Usage: ") << argv[0] << _B(" [-debug] [-device=device]") << std::endl;
390
391 return 2;
392 }
393
394 try
395 {
396 DashInterface interface(device);
397
398 interface.Run();
399 }
400 catch (const std::exception &exception)
401 {
402 std::cerr << argv[0] << _B(": ") << exception.what() << std::endl;
403
404 return 1;
405 }
406
407 return 0;
408 }

Properties

Name Value
svn:keywords Id