ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/truck/DashInterface/DashInterface.cpp
Revision: 40
Committed: 2008-03-05T20:23:58-08:00 (17 years, 3 months ago) by douglas
File size: 6982 byte(s)
Log Message:
Woo! Hmm, more stuffs.

File Contents

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

Properties

Name Value
svn:keywords Id