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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines