ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/truck/DashInterface/DashInterface.cpp
(Generate patch)

Comparing DashInterface/DashInterface.cpp (file contents):
Revision 25 by douglas, 2008-02-09T01:39:22-08:00 vs.
Revision 46 by douglas, 2008-03-06T19:47:57-08:00

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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines