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 47 by douglas, 2008-03-07T03:08:31-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 <regex.hpp>
15 + #include <scopes.hpp>
16 + #include <timing.hpp>
17  
12 #include <Audacious.hpp>
18   #include <GPS.hpp>
19  
20 < #include <sqlite3.h>
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 >        MusicLibrary::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 <        try
359 >        std::string device;
360 >
361          {
362 <                enum { Uname, Music, English, Metric, Nautical, Last } mode;
363 <                Audacious audacious;
364 <                GPS::GPS gps;
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 <                        gps.Query(_B("o"));
368 >                        Pcre::RegEx::Match match;
369  
370 <                        std::cout << gps.GetLatitude() << std::endl;
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;

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines