ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/truck/DashInterface/DashInterface.cpp
Revision: 51
Committed: 2008-03-09T14:24:55-07:00 (17 years, 3 months ago) by douglas
File size: 8203 byte(s)
Log Message:
Finish the renaming!

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

Properties

Name Value
svn:keywords Id