ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/truck/DashInterface/DashInterface.cpp
Revision: 42
Committed: 2008-03-06T13:04:20-08:00 (17 years, 3 months ago) by douglas
File size: 7926 byte(s)
Log Message:
Beginnings of a menu?

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 41 #include <iconv.hpp>
15 douglas 26 #include <regex.hpp>
16 douglas 39 #include <scopes.hpp>
17 douglas 37 #include <timing.hpp>
18 douglas 25
19 douglas 24 #include <Audacious.hpp>
20     #include <GPS.hpp>
21    
22 douglas 33 #include <sys/types.h>
23     #include <sys/sysctl.h>
24     #include <sys/utsname.h>
25    
26 douglas 26 #include "Display.hpp"
27    
28     bool debug(false);
29    
30 douglas 39 class DashInterface
31 douglas 33 {
32 douglas 41 enum Mode { Uname, Music, English, Metric, Nautical, Menu } mode, previous;
33 douglas 40 enum { Running, Audio };
34     enum { Stopped, Paused, Playing } audio;
35 douglas 41 enum Level { Top, Artist, Album, Song } level;
36 douglas 39 Timing::Time now;
37 douglas 41 IConv::IConv ascii;
38 douglas 39 Display display;
39     Pthreads::ThreadMutex displayLock;
40 douglas 40 Audacious::Audacious audacious;
41 douglas 39 //GPS::GPS gps;
42    
43 douglas 41 inline std::string Filter(const std::string input)
44     {
45     std::string output(ascii.Convert(input));
46    
47 douglas 42 std::replace(output.begin(), output.end(), '~', '\xce');
48 douglas 41
49     return output;
50     }
51    
52 douglas 39 void Mode_(bool change = false)
53 douglas 35 {
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     level = Top;
104 douglas 39 }
105     }
106 douglas 33
107 douglas 39 void Uname_(bool change = false)
108     {
109     if (!now || change)
110     {
111     utsname os;
112 douglas 33
113 douglas 39 ::uname(&os);
114 douglas 33
115 douglas 39 static Pcre::RegEx version(_B("^(\\d+\\.\\d+)-([A-Z])[A-Z]*(-p\\d+)?.*$"));
116     Pcre::RegEx::Match match(version(os.release));
117 douglas 40 std::string name(os.sysname + _B(" ") + match[1] + match[2] + match[3]);
118 douglas 33
119 douglas 42 name.resize(20, ' ');
120     display.Set(0, 1, name);
121 douglas 39 }
122 douglas 33
123 douglas 39 int mib[] = { CTL_KERN, KERN_BOOTTIME };
124     timeval boottime;
125     size_t size(sizeof (boottime));
126 douglas 33
127 douglas 39 if (now && ::sysctl(mib, 2, &boottime, &size, NULL, 0) != -1 && boottime.tv_sec != 0)
128     {
129     time_t uptime(now - boottime.tv_sec);
130 douglas 33
131 douglas 39 if (uptime > 60)
132     uptime += 30;
133 douglas 33
134 douglas 39 char *when;
135     int days(uptime / 86400);
136 douglas 33
137 douglas 39 uptime %= 86400;
138 douglas 33
139 douglas 39 int hours(uptime / 3600);
140 douglas 33
141 douglas 39 uptime %= 3600;
142 douglas 35
143 douglas 39 int minutes(uptime / 60), seconds(uptime % 60);
144 douglas 35
145 douglas 39 ::asprintf(&when, "%i+%02i:%02i:%02i", days, hours, minutes, seconds);
146 douglas 35
147 douglas 39 std::string then(when);
148 douglas 35
149 douglas 39 std::free(when);
150    
151 douglas 42 then.resize(17, ' ');
152    
153 douglas 39 if (change)
154     display.Set(0, 2, _B("up ") + then);
155     else
156     display.Set(3, 2, then);
157     }
158 douglas 35 else
159 douglas 39 display.Set(0, 2, _B("up -+--:--:-- "));
160    
161     double averages[3];
162    
163     if (::getloadavg(averages, 3) == -1 || !now)
164     display.Set(0, 3, _B("-.--, -.--, -.-- "));
165     else
166     {
167     char *load;
168    
169     ::asprintf(&load, "%.2f, %.2f, %.2f", averages[0], averages[1] , averages[2]);
170    
171 douglas 42 std::string load_(load);
172 douglas 39
173     std::free(load);
174 douglas 42
175     load_.resize(20, ' ');
176     display.Set(0, 3, load_);
177 douglas 39 }
178 douglas 33 }
179    
180 douglas 39 void Buttons(Display::KeyActivity activity)
181     {
182     _synchronized (displayLock)
183     if (mode != Menu)
184     {
185     bool change(false);
186 douglas 33
187 douglas 39 switch (activity)
188     {
189     case Display::UpPress:
190     --mode;
191    
192     goto change;
193     case Display::DownPress:
194     ++mode;
195    
196     goto change;
197     case Display::LeftPress:
198 douglas 41 if (audacious.IsRunning())
199     audacious.PlaylistPrevious();
200 douglas 39
201     goto update;
202     case Display::RightPress:
203 douglas 41 if (audacious.IsRunning())
204     audacious.PlaylistNext();
205 douglas 39
206     goto update;
207     case Display::EnterPress:
208 douglas 41 previous = mode;
209 douglas 39 mode = Menu;
210    
211     goto change;
212     case Display::ExitPress:
213 douglas 41 if (audacious.IsRunning())
214     audacious.PlayPause();
215 douglas 39
216     goto update;
217     default:
218     return;
219     }
220    
221     change: change = true;
222    
223     update: Mode_(change);
224     }
225     else
226 douglas 41 switch (activity)
227     {
228     case Display::UpPress:
229     case Display::DownPress:
230     case Display::LeftPress:
231     case Display::RightPress:
232     case Display::EnterPress:
233     return;
234     case Display::ExitPress:
235     mode = previous;
236    
237     display.Set(0, 0, _B(" "));
238     display.Set(18, 0, _B(" "));
239    
240     Mode_(true);
241     default:
242     return;
243     }
244 douglas 39 }
245    
246     public:
247 douglas 41 DashInterface(const std::string &device) : mode(Uname), audio(Stopped), ascii(_B("ASCII//TRANSLIT//IGNORE"), _B("UTF-8")), display(device, reinterpret_cast<Display::Callback>(::Buttons), this)
248 douglas 33 {
249 douglas 39 _synchronized (displayLock)
250     {
251     display.Clear();
252     display.SetBacklight(100);
253     display.Set(2, 0, _B("--:--:-- -- ---"));
254 douglas 33
255 douglas 39 display.Set(Running, Display::Green, 0);
256     display.Set(Running, Display::Red, 100);
257 douglas 40 display.Set(Audio, Display::Green, 0);
258     display.Set(Audio, Display::Red, 100);
259 douglas 33
260 douglas 39 uint8_t mask(Display::Up | Display::Enter | Display::Cancel | Display::Left | Display::Right | Display::Down);
261 douglas 35
262 douglas 39 display.KeyReporting(mask, mask);
263    
264     Uname_();
265    
266     display.Store();
267     display.Set(Running, Display::Green, 100);
268     display.Set(Running, Display::Red, 0);
269     }
270 douglas 33 }
271    
272 douglas 39 void Run()
273     {
274     _forever
275     {
276     _synchronized (displayLock)
277     {
278     now = Timing::GetTimeOfDay();
279 douglas 37
280 douglas 39 if (mode != Menu)
281     {
282     char when[16];
283 douglas 37
284 douglas 39 std::strftime(when, sizeof (when), "%l:%M:%S %p %Z", std::localtime(now));
285 douglas 37
286 douglas 39 display.Set(2, 0, when);
287     }
288    
289 douglas 40 if (audacious.IsRunning() && audacious.IsPlaying())
290     if (audacious.IsPaused())
291     {
292     if (audio != Paused)
293     {
294     display.Set(Audio, Display::Green, 100);
295     display.Set(Audio, Display::Red, 100);
296    
297     audio = Paused;
298     }
299     }
300     else
301     {
302     if (audio != Playing)
303     {
304     display.Set(Audio, Display::Green, 100);
305     display.Set(Audio, Display::Red, 0);
306    
307     audio = Playing;
308     }
309     }
310     else if (audio != Stopped)
311     {
312     display.Set(Audio, Display::Green, 0);
313     display.Set(Audio, Display::Red, 100);
314    
315     audio = Stopped;
316     }
317    
318 douglas 39 Mode_();
319     }
320    
321     Timing::NanoSleep(Timing::Time(1) -= Timing::GetTimeOfDay().GetNanoseconds());
322     }
323     }
324    
325     friend void Buttons(Display::KeyActivity activity, DashInterface *interface)
326     {
327     interface->Buttons(activity);
328     }
329    
330     inline friend Mode &operator ++(Mode &mode)
331     {
332     return mode = Mode((mode + 1) % Menu);
333     }
334    
335     inline friend Mode &operator --(Mode &mode)
336     {
337     return mode = Mode((Menu + mode - 1) % Menu);
338     }
339     };
340    
341 douglas 22 int main(int argc, char *argv[])
342     {
343 douglas 26 std::string device;
344    
345 douglas 25 {
346 douglas 26 Pcre::RegEx devicePath(_B("^-device=(/.+)$"));
347     Pcre::RegEx deviceNumber(_B("^-device=([0-9]+)$"));
348     Pcre::RegEx deviceName(_B("^-device=(.+)$"));
349 douglas 25
350 douglas 26 for (char **arg = argv + 1; *arg; ++arg)
351 douglas 25 {
352 douglas 26 Pcre::RegEx::Match match;
353 douglas 25
354 douglas 26 if (*arg == _B("-debug"))
355     debug = true;
356     else if (match = devicePath(*arg))
357     device = match[1];
358     else if (match = deviceNumber(*arg))
359     device = _B("/dev/cuaU") + match[1];
360     else if (match = deviceName(*arg))
361     device = _B("/dev/") + match[1];
362     else
363     goto usage;
364 douglas 25 }
365     }
366 douglas 26
367     if (device.empty())
368     {
369     usage: std::cout << _B("Usage: ") << argv[0] << _B(" [-debug] [-device=device]") << std::endl;
370    
371     return 2;
372     }
373    
374     try
375     {
376 douglas 39 DashInterface interface(device);
377 douglas 26
378 douglas 39 interface.Run();
379 douglas 26 }
380 douglas 25 catch (const std::exception &exception)
381     {
382     std::cerr << argv[0] << _B(": ") << exception.what() << std::endl;
383    
384     return 1;
385     }
386    
387 douglas 22 return 0;
388     }

Properties

Name Value
svn:keywords Id