ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/truck/DashInterface/DashInterface.cpp
Revision: 47
Committed: 2008-03-07T03:08:31-08:00 (17 years, 3 months ago) by douglas
File size: 8210 byte(s)
Log Message:
Progress, needs moar workz.

File Contents

# User Rev Content
1 douglas 22 // Dash Interface
2     //
3     // Douglas Thrift
4     //
5     // $Id$
6    
7 douglas 41 #include <algorithm>
8 douglas 33 #include <iomanip>
9 douglas 25 #include <iostream>
10 douglas 33 #include <sstream>
11 douglas 25
12     #include <foreach.hpp>
13     #include <hash.hpp>
14 douglas 26 #include <regex.hpp>
15 douglas 39 #include <scopes.hpp>
16 douglas 37 #include <timing.hpp>
17 douglas 25
18 douglas 24 #include <GPS.hpp>
19    
20 douglas 33 #include <sys/types.h>
21     #include <sys/sysctl.h>
22     #include <sys/utsname.h>
23    
24 douglas 26 #include "Display.hpp"
25 douglas 44 #include "MenuList.hpp"
26 douglas 26
27     bool debug(false);
28    
29 douglas 39 class DashInterface
30 douglas 33 {
31 douglas 41 enum Mode { Uname, Music, English, Metric, Nautical, Menu } mode, previous;
32 douglas 40 enum { Running, Audio };
33     enum { Stopped, Paused, Playing } audio;
34 douglas 39 Timing::Time now;
35 douglas 40 Audacious::Audacious audacious;
36 douglas 39 //GPS::GPS gps;
37 douglas 47 MusicLibrary::Library library;
38 douglas 44 MenuList *list;
39     bool append;
40 douglas 47 Display display;
41     Pthreads::ThreadMutex displayLock;
42 douglas 39
43     void Mode_(bool change = false)
44 douglas 35 {
45 douglas 46 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 douglas 39 switch (mode)
55     {
56     case Uname:
57 douglas 40 return Uname_(change);
58     case Music:
59     if (audacious.IsRunning())
60     {
61     int position(audacious.GetPlaylistPosition());
62 douglas 41 std::string artist(Filter(audacious.GetTupleFieldData(_B("artist"), position)));
63 douglas 33
64 douglas 42 artist.resize(20, ' ');
65     display.Set(0, 1, artist);
66 douglas 40
67 douglas 41 std::string title(Filter(audacious.GetTupleFieldData(_B("title"), position)));
68 douglas 40
69 douglas 42 title.resize(20, ' ');
70     display.Set(0, 2, title);
71 douglas 40
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 douglas 42 std::string times_(times);
79 douglas 40
80     std::free(times);
81 douglas 42
82     times_.resize(20, ' ');
83     display.Set(0, 3, times_);
84 douglas 40 }
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 douglas 39 case English:
94     case Metric:
95     case Nautical:
96 douglas 41 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 douglas 39 case Menu:
102 douglas 41 if (change)
103 douglas 44 {
104 douglas 46 display.SetCursorPosition(19, 0);
105 douglas 44 display.SetCursorStyle(Display::InvertingBlinkingBlock);
106    
107     append = true;
108 douglas 47 list = new TopList(display, audacious, append, library);
109 douglas 44
110     list->Render();
111     }
112 douglas 39 }
113     }
114 douglas 33
115 douglas 39 void Uname_(bool change = false)
116     {
117     if (!now || change)
118     {
119     utsname os;
120 douglas 33
121 douglas 39 ::uname(&os);
122 douglas 33
123 douglas 39 static Pcre::RegEx version(_B("^(\\d+\\.\\d+)-([A-Z])[A-Z]*(-p\\d+)?.*$"));
124     Pcre::RegEx::Match match(version(os.release));
125 douglas 40 std::string name(os.sysname + _B(" ") + match[1] + match[2] + match[3]);
126 douglas 33
127 douglas 42 name.resize(20, ' ');
128     display.Set(0, 1, name);
129 douglas 39 }
130 douglas 33
131 douglas 39 int mib[] = { CTL_KERN, KERN_BOOTTIME };
132     timeval boottime;
133     size_t size(sizeof (boottime));
134 douglas 33
135 douglas 39 if (now && ::sysctl(mib, 2, &boottime, &size, NULL, 0) != -1 && boottime.tv_sec != 0)
136     {
137     time_t uptime(now - boottime.tv_sec);
138 douglas 33
139 douglas 39 if (uptime > 60)
140     uptime += 30;
141 douglas 33
142 douglas 39 char *when;
143     int days(uptime / 86400);
144 douglas 33
145 douglas 39 uptime %= 86400;
146 douglas 33
147 douglas 39 int hours(uptime / 3600);
148 douglas 33
149 douglas 39 uptime %= 3600;
150 douglas 35
151 douglas 39 int minutes(uptime / 60), seconds(uptime % 60);
152 douglas 35
153 douglas 39 ::asprintf(&when, "%i+%02i:%02i:%02i", days, hours, minutes, seconds);
154 douglas 35
155 douglas 39 std::string then(when);
156 douglas 35
157 douglas 39 std::free(when);
158    
159 douglas 42 then.resize(17, ' ');
160    
161 douglas 39 if (change)
162     display.Set(0, 2, _B("up ") + then);
163     else
164     display.Set(3, 2, then);
165     }
166 douglas 35 else
167 douglas 39 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 douglas 42 std::string load_(load);
180 douglas 39
181     std::free(load);
182 douglas 42
183     load_.resize(20, ' ');
184     display.Set(0, 3, load_);
185 douglas 39 }
186 douglas 33 }
187    
188 douglas 39 void Buttons(Display::KeyActivity activity)
189     {
190     _synchronized (displayLock)
191     if (mode != Menu)
192     {
193     bool change(false);
194 douglas 33
195 douglas 39 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 douglas 41 if (audacious.IsRunning())
207     audacious.PlaylistPrevious();
208 douglas 39
209     goto update;
210     case Display::RightPress:
211 douglas 41 if (audacious.IsRunning())
212     audacious.PlaylistNext();
213 douglas 39
214     goto update;
215     case Display::EnterPress:
216 douglas 41 previous = mode;
217 douglas 39 mode = Menu;
218    
219     goto change;
220     case Display::ExitPress:
221 douglas 41 if (audacious.IsRunning())
222     audacious.PlayPause();
223 douglas 39
224     goto update;
225     default:
226     return;
227     }
228    
229     change: change = true;
230    
231     update: Mode_(change);
232     }
233     else
234 douglas 41 switch (activity)
235     {
236     case Display::UpPress:
237 douglas 46 return (--*list).Render();
238     case Display::DownPress:
239 douglas 44 return (++*list).Render();
240 douglas 41 case Display::LeftPress:
241 douglas 44 list = list->Left();
242    
243     goto render;
244 douglas 41 case Display::RightPress:
245 douglas 44 list = list->Right();
246    
247     goto render;
248 douglas 41 case Display::EnterPress:
249 douglas 44 list = list->Enter();
250    
251     render: if (list != NULL)
252     return list->Render();
253    
254     goto exit;
255 douglas 41 case Display::ExitPress:
256 douglas 44 delete list;
257 douglas 41
258 douglas 44 exit: mode = previous;
259    
260     display.SetCursorStyle(Display::NoCursor);
261 douglas 41 display.Set(0, 0, _B(" "));
262     display.Set(18, 0, _B(" "));
263    
264     Mode_(true);
265     default:
266     return;
267     }
268 douglas 39 }
269    
270     public:
271 douglas 47 DashInterface(const std::string &device) : mode(Uname), audio(Stopped), display(device, reinterpret_cast<Display::Callback>(::Buttons), this)
272 douglas 33 {
273 douglas 39 _synchronized (displayLock)
274     {
275     display.Clear();
276 douglas 46 display.SetCursorStyle(Display::NoCursor);
277 douglas 39 display.SetBacklight(100);
278     display.Set(2, 0, _B("--:--:-- -- ---"));
279 douglas 33
280 douglas 39 display.Set(Running, Display::Green, 0);
281     display.Set(Running, Display::Red, 100);
282 douglas 40 display.Set(Audio, Display::Green, 0);
283     display.Set(Audio, Display::Red, 100);
284 douglas 33
285 douglas 39 uint8_t mask(Display::Up | Display::Enter | Display::Cancel | Display::Left | Display::Right | Display::Down);
286 douglas 35
287 douglas 39 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 douglas 33 }
296    
297 douglas 39 void Run()
298     {
299     _forever
300     {
301     _synchronized (displayLock)
302     {
303     now = Timing::GetTimeOfDay();
304 douglas 37
305 douglas 40 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 douglas 39 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 douglas 22 int main(int argc, char *argv[])
358     {
359 douglas 26 std::string device;
360    
361 douglas 25 {
362 douglas 26 Pcre::RegEx devicePath(_B("^-device=(/.+)$"));
363     Pcre::RegEx deviceNumber(_B("^-device=([0-9]+)$"));
364     Pcre::RegEx deviceName(_B("^-device=(.+)$"));
365 douglas 25
366 douglas 26 for (char **arg = argv + 1; *arg; ++arg)
367 douglas 25 {
368 douglas 26 Pcre::RegEx::Match match;
369 douglas 25
370 douglas 26 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 douglas 25 }
381     }
382 douglas 26
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 douglas 39 DashInterface interface(device);
393 douglas 26
394 douglas 39 interface.Run();
395 douglas 26 }
396 douglas 25 catch (const std::exception &exception)
397     {
398     std::cerr << argv[0] << _B(": ") << exception.what() << std::endl;
399    
400     return 1;
401     }
402    
403 douglas 22 return 0;
404     }

Properties

Name Value
svn:keywords Id