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 26 by douglas, 2008-02-23T13:35:09-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          std::string device;
# Line 54 | Line 400 | usage: std::cout << _B("Usage: ") << arg
400  
401          try
402          {
403 <                //enum Mode { Uname, Music, English, Metric, Nautical, Last } mode(Uname);
58 <                //Audacious audacious;
59 <                Display display(device);
60 <
61 <                display.Ping("Hello!");
62 <
63 <                /*GPS::GPS gps;
64 <
65 <                gps.Query(_B("o"));
403 >                DashInterface interface(device);
404  
405 <                std::cout << gps.GetLatitude() << std::endl;*/
405 >                interface.Run();
406          }
407          catch (const std::exception &exception)
408          {

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines