root/wmgui/main.c @ a09a4eea431c232fa82b3b1a9a728c8b07345d4f

Revision a09a4eea431c232fa82b3b1a9a728c8b07345d4f, 40.4 KB (checked in by dsmith <dsmith@…>, 6 years ago)

deprecated cwiid_{connect,disconnect,command}, added cwiid_{open,close,request_status,set_led,set_rumble,set_rpt_mode}

git-svn-id: http://abstrakraft.org/cwiid/svn/trunk@116 918edb2d-ff29-0410-9de2-eb38e7f22bc7

  • Property mode set to 100644
Line 
1/* Copyright (C) 2007 L. Donnie Smith <cwiid@abstrakraft.org>
2 *
3 *  This program is free software; you can redistribute it and/or modify
4 *  it under the terms of the GNU General Public License as published by
5 *  the Free Software Foundation; either version 2 of the License, or
6 *  (at your option) any later version.
7 *
8 *  This program is distributed in the hope that it will be useful,
9 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
10 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 *  GNU General Public License for more details.
12 *
13 *  You should have received a copy of the GNU General Public License
14 *  along with this program; if not, write to the Free Software
15 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
16 *
17 *  ChangeLog:
18 *  2007-05-16 L. Donnie Smith <cwiid@abstrakraft.org>
19 *  * changed cwiid_{connect,disconnect,command} to
20 *    cwiid_{open,close,request_status|set_led|set_rumble|set_rpt_mode}
21 *
22 *  2007-05-14 L. Donnie Smith <cwiid@abstrakraft.org>
23 *  * added timestamp to message callback
24 *  * use cwiid_get_acc_cal to get acc calibration values
25 *
26 *  2007-04-24 L. Donnie Smith <cwiid@abstrakraft.org>
27 *  * updated for API overhaul
28 *
29 *  2007-04-09 L. Donnie Smith <cwiid@abstrakraft.org>
30 *  * updated for libcwiid rename
31 *
32 *  2007-04-08 L. Donnie Smith <cwiid@anstrakraft.org>
33 *  * fixed signed/unsigned comparison warning in btnRead_clicked
34 *
35 *  2007-04-04 L. Donnie Smith <cwiid@abstrakraft.org>
36 *  * disconnect on cwiid_mesg_error
37 *
38 *  2007-04-03 L. Donnie Smith <cwiid@abstrakraft.org>
39 *  * commented custom cwiid_err (causing Xlib errors)
40 *
41 *  2007-03-01 L. Donnie Smith <cwiid@abstrakraft.org>
42 *  * Initial Changelog
43 *  * type audit (stdint, const, char booleans)
44 */
45
46#define APP_NAME                "CWiid wmgui"
47#define APP_COPYRIGHT   "Copyright (C) 2007 L. Donnie Smith " \
48                        "<cwiid@abstrakraft.org>"
49#define APP_COMMENTS    "Wiimote GUI"
50
51#include <ctype.h>
52#include <float.h>
53#include <math.h>
54#include <stdio.h>
55#include <stdint.h>
56#include <string.h>
57#include <stdlib.h>
58#include <unistd.h>
59
60#include <glib.h>
61#include <gtk/gtk.h>
62
63#include "interface.h"
64#include "support.h"
65
66#include <bluetooth/bluetooth.h>
67#include "cwiid.h"
68
69#define PI      3.14159265358979323
70
71struct stick {
72        char valid;
73        uint8_t x;
74        uint8_t y;
75        uint8_t max;
76};
77
78/* Globals */
79cwiid_wiimote_t *wiimote = NULL;
80bdaddr_t bdaddr;
81struct acc_cal wm_cal, nc_cal;
82struct cwiid_ir_mesg ir_data;
83struct stick nc_stick;
84struct stick cc_l_stick, cc_r_stick;
85
86/* Widgets */
87GtkWidget *winMain;
88GtkWidget *winRW;
89GtkWidget *winDialog;
90GtkWidget *menuConnect, *menuDisconnect, *menuQuit, *menuRW, *menuAbout;
91GtkWidget *chkAcc, *chkIR, *chkExt;
92GtkWidget *chkLED1, *chkLED2, *chkLED3, *chkLED4;
93GtkWidget *chkRumble;
94GtkWidget *evUp, *evDown, *evLeft, *evRight, *evA, *evB,
95          *evMinus, *evPlus, *evHome, *ev1, *ev2;
96GtkWidget *lblUp, *lblDown, *lblLeft, *lblRight, *lblA, *lblB,
97          *lblMinus, *lblPlus, *lblHome, *lbl1, *lbl2;
98GtkWidget *lblAccX, *lblAccY, *lblAccZ;
99GtkWidget *lblAccXVal, *lblAccYVal, *lblAccZVal;
100GtkWidget *progAccX, *progAccY, *progAccZ;
101GtkWidget *lblAcc, *lblRoll, *lblPitch;
102GtkWidget *lblAccVal, *lblRollVal, *lblPitchVal;
103GtkWidget *lblIR;
104GtkWidget *drawIR;
105GtkWidget *lblNC;
106GtkWidget *drawNCStick;
107GtkWidget *evNCC, *evNCZ;
108GtkWidget *lblNCC, *lblNCZ;
109GtkWidget *lblNCAccX, *lblNCAccY, *lblNCAccZ;
110GtkWidget *lblNCAccXVal, *lblNCAccYVal, *lblNCAccZVal;
111GtkWidget *progNCAccX, *progNCAccY, *progNCAccZ;
112GtkWidget *lblNCAcc, *lblNCRoll, *lblNCPitch;
113GtkWidget *lblNCAccVal, *lblNCRollVal, *lblNCPitchVal;
114GtkWidget *evCCUp, *evCCDown, *evCCLeft, *evCCRight, *evCCMinus, *evCCPlus,
115          *evCCHome, *evCCA, *evCCB, *evCCX, *evCCY, *evCCZL, *evCCZR;
116GtkWidget *lblCCUp, *lblCCDown, *lblCCLeft, *lblCCRight, *lblCCMinus,
117          *lblCCPlus, *lblCCHome, *lblCCA, *lblCCB, *lblCCX, *lblCCY, *lblCCZL,
118          *lblCCZR;
119GtkWidget *drawCCLStick, *drawCCRStick;
120GtkWidget *evCCL, *evCCR;
121GtkWidget *lblCCL, *lblCCR;
122GtkWidget *lblCCLVal, *lblCCRVal;
123GtkWidget *progCCL, *progCCR;
124GtkWidget *statConnection, *statBattery, *statExtension;
125GtkWidget *txtReadOffset, *txtReadLen;
126GtkWidget *radReadEEPROM, *radReadReg;
127GtkWidget *btnRead;
128GtkWidget *txtWriteOffset, *txtWriteData;
129GtkWidget *radWriteEEPROM, *radWriteReg;
130GtkWidget *btnWrite;
131GtkWidget *tvRW;
132GtkWidget *btnRWClose;
133GtkWidget *btnBeep;
134
135GtkTextBuffer *tbRW;
136
137GdkColor btn_on, btn_off;
138
139/* Utility functions */
140void set_gui_state();
141void clear_widgets();
142void clear_acc_widgets();
143void clear_ir_data();
144void clear_nunchuk_widgets();
145void clear_classic_widgets();
146void message(GtkMessageType type, const gchar *message, GtkWindow *parent);
147void status(const gchar *status);
148
149/* GTK Callbacks */
150gboolean winMain_delete_event(void);
151gboolean winRW_delete_event(void);
152void menuConnect_activate(void);
153void menuDisconnect_activate(void);
154void menuQuit_activate(void);
155void menuRW_activate(void);
156void menuAbout_activate(void);
157void chkAcc_toggled(void);
158void chkIR_toggled(void);
159void chkExt_toggled(void);
160void chkLED_toggled(void);
161void chkRumble_toggled(void);
162void drawIR_expose_event(void);
163void drawStick_expose_event(GtkWidget *, GdkEventExpose *, struct stick *);
164void btnRead_clicked(void);
165void btnWrite_clicked(void);
166void btnRWClose_clicked(void);
167void btnBeep_clicked(void);
168
169void set_report_mode(void);
170
171/* Wiimote Callback */
172cwiid_mesg_callback_t cwiid_callback;
173
174/* Wiimote Handler Functions */
175void cwiid_btn(struct cwiid_btn_mesg *);
176void cwiid_acc(struct cwiid_acc_mesg *);
177void cwiid_ir(struct cwiid_ir_mesg *);
178void cwiid_nunchuk(struct cwiid_nunchuk_mesg *);
179void cwiid_classic(struct cwiid_classic_mesg *);
180
181/* GetOpt */
182#define OPTSTRING       "h"
183extern char *optarg;
184extern int optind, opterr, optopt;
185
186#define USAGE "usage:%s [-h] [BDADDR]\n"
187
188/*
189cwiid_err_t err;
190
191void err(int id, const char *s, ...)
192{
193        message(GTK_MESSAGE_ERROR, s, GTK_WINDOW(winMain));
194}
195*/
196
197int main (int argc, char *argv[])
198{
199        int c;
200        char *str_addr;
201
202        gtk_set_locale ();
203        gtk_init (&argc, &argv);
204
205        if (!g_thread_supported()) {
206                g_thread_init(NULL);
207        }
208        gdk_threads_init();
209        gdk_threads_enter();
210
211        /* cwiid_set_err(err); */
212
213        /* Parse Options */
214        while ((c = getopt(argc, argv, OPTSTRING)) != -1) {
215                switch (c) {
216                case 'h':
217                        printf(USAGE, argv[0]);
218                        return 0;
219                        break;
220                case '?':
221                        return -1;
222                        break;
223                default:
224                        printf("unknown command-line option: -%c\n", c);
225                        break;
226                }
227        }
228
229        /* BDADDR */
230        if (optind < argc) {
231                if (str2ba(argv[optind], &bdaddr)) {
232                        printf("invalid bdaddr\n");
233                        bdaddr = *BDADDR_ANY;
234                }
235                optind++;
236                if (optind < argc) {
237                        printf("invalid command-line\n");
238                        printf(USAGE, argv[0]);
239                        return -1;
240                }
241        }
242        else if ((str_addr = getenv(WIIMOTE_BDADDR)) != NULL) {
243                if (str2ba(str_addr, &bdaddr)) {
244                        printf("invalid address in %s\n", WIIMOTE_BDADDR);
245                        bdaddr = *BDADDR_ANY;
246                }
247        }
248        else {
249                bdaddr = *BDADDR_ANY;
250        }               
251
252        /* Create the window */
253        winMain = create_winMain();
254        winRW = create_winRW();
255
256        /* Lookup Widgets */
257        menuConnect = lookup_widget(winMain, "menuConnect");
258        menuDisconnect = lookup_widget(winMain, "menuDisconnect");
259        menuQuit = lookup_widget(winMain, "menuQuit");
260        menuRW = lookup_widget(winMain, "menuRW");
261        menuAbout = lookup_widget(winMain, "menuAbout");
262        chkAcc = lookup_widget(winMain, "chkAcc");
263        chkIR = lookup_widget(winMain, "chkIR");
264        chkExt = lookup_widget(winMain, "chkExt");
265        chkLED1 = lookup_widget(winMain, "chkLED1");
266        chkLED2 = lookup_widget(winMain, "chkLED2");
267        chkLED3 = lookup_widget(winMain, "chkLED3");
268        chkLED4 = lookup_widget(winMain, "chkLED4");
269        chkRumble = lookup_widget(winMain, "chkRumble");
270        evUp = lookup_widget(winMain, "evUp");
271        evDown = lookup_widget(winMain, "evDown");
272        evLeft = lookup_widget(winMain, "evLeft");
273        evRight = lookup_widget(winMain, "evRight");
274        evA = lookup_widget(winMain, "evA");
275        evB = lookup_widget(winMain, "evB");
276        evMinus = lookup_widget(winMain, "evMinus");
277        evPlus = lookup_widget(winMain, "evPlus");
278        evHome = lookup_widget(winMain, "evHome");
279        ev1 = lookup_widget(winMain, "ev1");
280        ev2 = lookup_widget(winMain, "ev2");
281        lblUp = lookup_widget(winMain, "lblUp");
282        lblDown = lookup_widget(winMain, "lblDown");
283        lblLeft = lookup_widget(winMain, "lblLeft");
284        lblRight = lookup_widget(winMain, "lblRight");
285        lblA = lookup_widget(winMain, "lblA");
286        lblB = lookup_widget(winMain, "lblB");
287        lblMinus = lookup_widget(winMain, "lblMinus");
288        lblPlus = lookup_widget(winMain, "lblPlus");
289        lblHome = lookup_widget(winMain, "lblHome");
290        lbl1 = lookup_widget(winMain, "lbl1");
291        lbl2 = lookup_widget(winMain, "lbl2");
292        lblAccX = lookup_widget(winMain, "lblAccX");
293        lblAccY = lookup_widget(winMain, "lblAccY");
294        lblAccZ = lookup_widget(winMain, "lblAccZ");
295        lblAccXVal = lookup_widget(winMain, "lblAccXVal");
296        lblAccYVal = lookup_widget(winMain, "lblAccYVal");
297        lblAccZVal = lookup_widget(winMain, "lblAccZVal");
298        progAccX = lookup_widget(winMain, "progAccX");
299        progAccY = lookup_widget(winMain, "progAccY");
300        progAccZ = lookup_widget(winMain, "progAccZ");
301        lblAcc = lookup_widget(winMain, "lblAcc");
302        lblRoll = lookup_widget(winMain, "lblRoll");
303        lblPitch = lookup_widget(winMain, "lblPitch");
304        lblAccVal = lookup_widget(winMain, "lblAccVal");
305        lblRollVal = lookup_widget(winMain, "lblRollVal");
306        lblPitchVal = lookup_widget(winMain, "lblPitchVal");
307        lblIR = lookup_widget(winMain, "lblIR");
308        drawIR = lookup_widget(winMain, "drawIR");
309        lblNC = lookup_widget(winMain, "lblNC");
310        drawNCStick = lookup_widget(winMain, "drawNCStick");
311        evNCC = lookup_widget(winMain, "evNCC");
312        evNCZ = lookup_widget(winMain, "evNCZ");
313        lblNCC = lookup_widget(winMain, "lblNCC");
314        lblNCZ = lookup_widget(winMain, "lblNCZ");
315        lblNCAccX = lookup_widget(winMain, "lblNCAccX");
316        lblNCAccY = lookup_widget(winMain, "lblNCAccY");
317        lblNCAccZ = lookup_widget(winMain, "lblNCAccZ");
318        lblNCAccXVal = lookup_widget(winMain, "lblNCAccXVal");
319        lblNCAccYVal = lookup_widget(winMain, "lblNCAccYVal");
320        lblNCAccZVal = lookup_widget(winMain, "lblNCAccZVal");
321        progNCAccX = lookup_widget(winMain, "progNCAccX");
322        progNCAccY = lookup_widget(winMain, "progNCAccY");
323        progNCAccZ = lookup_widget(winMain, "progNCAccZ");
324        lblNCAcc = lookup_widget(winMain, "lblNCAcc");
325        lblNCRoll = lookup_widget(winMain, "lblNCRoll");
326        lblNCPitch = lookup_widget(winMain, "lblNCPitch");
327        lblNCAccVal = lookup_widget(winMain, "lblNCAccVal");
328        lblNCRollVal = lookup_widget(winMain, "lblNCRollVal");
329        lblNCPitchVal = lookup_widget(winMain, "lblNCPitchVal");
330        evCCUp = lookup_widget(winMain, "evCCUp");
331        evCCDown = lookup_widget(winMain, "evCCDown");
332        evCCLeft = lookup_widget(winMain, "evCCLeft");
333        evCCRight = lookup_widget(winMain, "evCCRight");
334        evCCMinus = lookup_widget(winMain, "evCCMinus");
335        evCCPlus = lookup_widget(winMain, "evCCPlus");
336        evCCHome = lookup_widget(winMain, "evCCHome");
337        evCCA = lookup_widget(winMain, "evCCA");
338        evCCB = lookup_widget(winMain, "evCCB");
339        evCCX = lookup_widget(winMain, "evCCX");
340        evCCY = lookup_widget(winMain, "evCCY");
341        evCCZL = lookup_widget(winMain, "evCCZL");
342        evCCZR = lookup_widget(winMain, "evCCZR");
343        lblCCUp = lookup_widget(winMain, "lblCCUp");
344        lblCCDown = lookup_widget(winMain, "lblCCDown");
345        lblCCLeft = lookup_widget(winMain, "lblCCLeft");
346        lblCCRight = lookup_widget(winMain, "lblCCRight");
347        lblCCMinus = lookup_widget(winMain, "lblCCMinus");
348        lblCCPlus = lookup_widget(winMain, "lblCCPlus");
349        lblCCHome = lookup_widget(winMain, "lblCCHome");
350        lblCCA = lookup_widget(winMain, "lblCCA");
351        lblCCB = lookup_widget(winMain, "lblCCB");
352        lblCCX = lookup_widget(winMain, "lblCCX");
353        lblCCY = lookup_widget(winMain, "lblCCY");
354        lblCCZL = lookup_widget(winMain, "lblCCZL");
355        lblCCZR = lookup_widget(winMain, "lblCCZR");
356        drawCCLStick = lookup_widget(winMain, "drawCCLStick");
357        drawCCRStick = lookup_widget(winMain, "drawCCRStick");
358        evCCL = lookup_widget(winMain, "evCCL");
359        evCCR = lookup_widget(winMain, "evCCR");
360        lblCCL = lookup_widget(winMain, "lblCCL");
361        lblCCR = lookup_widget(winMain, "lblCCR");
362        lblCCLVal = lookup_widget(winMain, "lblCCLVal");
363        lblCCRVal = lookup_widget(winMain, "lblCCRVal");
364        progCCL = lookup_widget(winMain, "progCCL");
365        progCCR = lookup_widget(winMain, "progCCR");
366        statConnection = lookup_widget(winMain, "statConnection");
367        statBattery = lookup_widget(winMain, "statBattery");
368        statExtension = lookup_widget(winMain, "statExtension");
369        txtReadOffset = lookup_widget(winRW, "txtReadOffset");
370        txtReadLen = lookup_widget(winRW, "txtReadLen");
371        radReadEEPROM = lookup_widget(winRW, "radReadEEPROM");
372        radReadReg = lookup_widget(winRW, "radReadReg");
373        btnRead = lookup_widget(winRW, "btnRead");
374        txtWriteOffset = lookup_widget(winRW, "txtWriteOffset");
375        txtWriteData = lookup_widget(winRW, "txtWriteData");
376        radWriteEEPROM = lookup_widget(winRW, "radWriteEEPROM");
377        radWriteReg = lookup_widget(winRW, "radWriteReg");
378        btnWrite = lookup_widget(winRW, "btnWrite");
379        tvRW = lookup_widget(winRW, "tvRW");
380        btnRWClose = lookup_widget(winRW, "btnRWClose");
381        btnBeep = lookup_widget(winMain, "btnBeep");
382       
383        tbRW = gtk_text_view_get_buffer(GTK_TEXT_VIEW(tvRW));
384
385        /* Connect Callbacks */
386        g_signal_connect(winMain, "delete_event", G_CALLBACK(winMain_delete_event),
387                         NULL);
388        g_signal_connect(winRW, "delete_event", G_CALLBACK(winRW_delete_event),
389                         NULL);
390        g_signal_connect(menuConnect, "activate", G_CALLBACK(menuConnect_activate),
391                         NULL);
392        g_signal_connect(menuDisconnect, "activate",
393                         G_CALLBACK(menuDisconnect_activate), NULL);
394        g_signal_connect(menuQuit, "activate", G_CALLBACK(menuQuit_activate),
395                         NULL);
396        g_signal_connect(menuRW, "activate", G_CALLBACK(menuRW_activate), NULL);
397        g_signal_connect(menuAbout, "activate", G_CALLBACK(menuAbout_activate),
398                         NULL);
399        g_signal_connect(chkAcc, "toggled", G_CALLBACK(chkAcc_toggled), NULL);
400        g_signal_connect(chkIR, "toggled", G_CALLBACK(chkIR_toggled), NULL);
401        g_signal_connect(chkExt, "toggled", G_CALLBACK(chkExt_toggled), NULL);
402        g_signal_connect(chkLED1, "toggled", G_CALLBACK(chkLED_toggled), NULL);
403        g_signal_connect(chkLED2, "toggled", G_CALLBACK(chkLED_toggled), NULL);
404        g_signal_connect(chkLED3, "toggled", G_CALLBACK(chkLED_toggled), NULL);
405        g_signal_connect(chkLED4, "toggled", G_CALLBACK(chkLED_toggled), NULL);
406        g_signal_connect(chkRumble, "toggled", G_CALLBACK(chkRumble_toggled),
407                         NULL);
408        g_signal_connect(drawIR, "expose_event",
409                         G_CALLBACK(drawIR_expose_event), NULL);
410        g_signal_connect(drawNCStick, "expose_event",
411                         G_CALLBACK(drawStick_expose_event), &nc_stick);
412        g_signal_connect(drawCCLStick, "expose_event",
413                         G_CALLBACK(drawStick_expose_event), &cc_l_stick);
414        g_signal_connect(drawCCRStick, "expose_event",
415                         G_CALLBACK(drawStick_expose_event), &cc_r_stick);
416        g_signal_connect(btnRead, "clicked", G_CALLBACK(btnRead_clicked), NULL);
417        g_signal_connect(btnWrite, "clicked", G_CALLBACK(btnWrite_clicked), NULL);
418        g_signal_connect(btnRWClose, "clicked", G_CALLBACK(btnRWClose_clicked),
419                         NULL);
420        g_signal_connect(btnBeep, "clicked", G_CALLBACK(btnBeep_clicked), NULL);
421
422        /* Initialize */
423        btn_on.red = 0; btn_on.blue = 0; btn_on.green = 0xFFFF;
424        btn_off = gtk_widget_get_style(evUp)->bg[GTK_STATE_NORMAL];
425
426        nc_stick.max = 0xFF;
427        cc_l_stick.max = CWIID_CLASSIC_L_STICK_MAX;
428        cc_r_stick.max = CWIID_CLASSIC_R_STICK_MAX;
429
430        set_gui_state();
431        clear_widgets();
432        status("No connection");
433
434        gtk_widget_show(winMain);
435
436        gtk_main();
437        gdk_threads_leave();
438        return 0;
439}
440
441void message(GtkMessageType type, const gchar *message, GtkWindow *parent)
442{
443        GtkWidget *dialog;
444
445        dialog = gtk_message_dialog_new(parent, 0, type, GTK_BUTTONS_OK, message);
446        gtk_dialog_run(GTK_DIALOG(dialog));
447        gtk_widget_destroy(dialog);
448}
449
450void status(const gchar *status)
451{
452        gtk_statusbar_push(GTK_STATUSBAR(statConnection), 0, status);
453}
454
455void set_gui_state()
456{
457        gboolean connected;
458        gboolean acc_active;
459        gboolean ext_active;
460
461        connected = wiimote ? TRUE : FALSE;
462        /* Set Input Widget Sensitivities */
463        gtk_widget_set_sensitive(menuConnect, !connected);
464        gtk_widget_set_sensitive(menuDisconnect, connected);
465        gtk_widget_set_sensitive(chkLED1, connected);
466        gtk_widget_set_sensitive(chkLED2, connected);
467        gtk_widget_set_sensitive(chkLED3, connected);
468        gtk_widget_set_sensitive(chkLED4, connected);
469        gtk_widget_set_sensitive(chkRumble, connected);
470        gtk_widget_set_sensitive(btnRead, connected);
471        gtk_widget_set_sensitive(btnWrite, connected);
472
473        /* Set Button Sensitivities */
474        gtk_widget_set_sensitive(lblUp, connected);
475        gtk_widget_set_sensitive(lblDown, connected);
476        gtk_widget_set_sensitive(lblLeft, connected);
477        gtk_widget_set_sensitive(lblRight, connected);
478        gtk_widget_set_sensitive(lblA, connected);
479        gtk_widget_set_sensitive(lblB, connected);
480        gtk_widget_set_sensitive(lblMinus, connected);
481        gtk_widget_set_sensitive(lblPlus, connected);
482        gtk_widget_set_sensitive(lblHome, connected);
483        gtk_widget_set_sensitive(lbl1, connected);
484        gtk_widget_set_sensitive(lbl2, connected);
485
486        acc_active = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(chkAcc));
487        /* Set Acc Widget Sensitivities */
488        gtk_widget_set_sensitive(lblAccX, acc_active);
489        gtk_widget_set_sensitive(lblAccY, acc_active);
490        gtk_widget_set_sensitive(lblAccZ, acc_active);
491        gtk_widget_set_sensitive(lblAccXVal, acc_active);
492        gtk_widget_set_sensitive(lblAccYVal, acc_active);
493        gtk_widget_set_sensitive(lblAccZVal, acc_active);
494        gtk_widget_set_sensitive(progAccX, acc_active);
495        gtk_widget_set_sensitive(progAccY, acc_active);
496        gtk_widget_set_sensitive(progAccZ, acc_active);
497        gtk_widget_set_sensitive(lblAcc, acc_active);
498        gtk_widget_set_sensitive(lblRoll, acc_active);
499        gtk_widget_set_sensitive(lblPitch, acc_active);
500        gtk_widget_set_sensitive(lblAccVal, acc_active);
501        gtk_widget_set_sensitive(lblRollVal, acc_active);
502        gtk_widget_set_sensitive(lblPitchVal, acc_active);
503
504        /* Set IC Widget Sensitivities */
505        gtk_widget_set_sensitive(lblIR,
506      gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(chkIR)));
507
508        ext_active = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(chkExt));
509        /* Set Extension Widget Sensitivities */
510        gtk_widget_set_sensitive(lblNCC, ext_active);
511        gtk_widget_set_sensitive(lblNCZ, ext_active);
512        gtk_widget_set_sensitive(lblNCAccX, ext_active);
513        gtk_widget_set_sensitive(lblNCAccY, ext_active);
514        gtk_widget_set_sensitive(lblNCAccZ, ext_active);
515        gtk_widget_set_sensitive(lblNCAccXVal, ext_active);
516        gtk_widget_set_sensitive(lblNCAccYVal, ext_active);
517        gtk_widget_set_sensitive(lblNCAccZVal, ext_active);
518        gtk_widget_set_sensitive(progNCAccX, ext_active);
519        gtk_widget_set_sensitive(progNCAccY, ext_active);
520        gtk_widget_set_sensitive(progNCAccZ, ext_active);
521        gtk_widget_set_sensitive(lblNCAcc, ext_active);
522        gtk_widget_set_sensitive(lblNCRoll, ext_active);
523        gtk_widget_set_sensitive(lblNCPitch, ext_active);
524        gtk_widget_set_sensitive(lblNCAccVal, ext_active);
525        gtk_widget_set_sensitive(lblNCRollVal, ext_active);
526        gtk_widget_set_sensitive(lblNCPitchVal, ext_active);
527        gtk_widget_set_sensitive(lblCCUp, ext_active);
528        gtk_widget_set_sensitive(lblCCDown, ext_active);
529        gtk_widget_set_sensitive(lblCCLeft, ext_active);
530        gtk_widget_set_sensitive(lblCCRight, ext_active);
531        gtk_widget_set_sensitive(lblCCMinus, ext_active);
532        gtk_widget_set_sensitive(lblCCPlus, ext_active);
533        gtk_widget_set_sensitive(lblCCHome, ext_active);
534        gtk_widget_set_sensitive(lblCCA, ext_active);
535        gtk_widget_set_sensitive(lblCCB, ext_active);
536        gtk_widget_set_sensitive(lblCCX, ext_active);
537        gtk_widget_set_sensitive(lblCCY, ext_active);
538        gtk_widget_set_sensitive(lblCCZL, ext_active);
539        gtk_widget_set_sensitive(lblCCZR, ext_active);
540        gtk_widget_set_sensitive(lblCCL, ext_active);
541        gtk_widget_set_sensitive(lblCCR, ext_active);
542        gtk_widget_set_sensitive(lblCCLVal, ext_active);
543        gtk_widget_set_sensitive(lblCCRVal, ext_active);
544        gtk_widget_set_sensitive(progCCL, ext_active);
545        gtk_widget_set_sensitive(progCCR, ext_active);
546}
547
548void clear_widgets()
549{
550        gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(chkLED1), FALSE);
551        gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(chkLED2), FALSE);
552        gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(chkLED3), FALSE);
553        gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(chkLED4), FALSE);
554        gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(chkRumble), FALSE);
555
556        gtk_statusbar_push(GTK_STATUSBAR(statBattery), 0, "");
557        gtk_statusbar_push(GTK_STATUSBAR(statExtension), 0, "");
558
559        clear_acc_widgets();
560        clear_ir_data();
561        clear_nunchuk_widgets();
562        clear_classic_widgets();
563}
564
565void clear_acc_widgets()
566{
567        gtk_label_set_text(GTK_LABEL(lblAccXVal), "0");
568        gtk_label_set_text(GTK_LABEL(lblAccYVal), "0");
569        gtk_label_set_text(GTK_LABEL(lblAccZVal), "0");
570        gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(progAccX), 0.0);
571        gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(progAccY), 0.0);
572        gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(progAccZ), 0.0);
573        gtk_label_set_text(GTK_LABEL(lblAccVal), "0");
574        gtk_label_set_text(GTK_LABEL(lblRollVal), "0");
575        gtk_label_set_text(GTK_LABEL(lblPitchVal), "0");
576}
577
578void clear_ir_data()
579{
580        int i;
581
582        for (i=0; i < CWIID_IR_SRC_COUNT; i++) {
583                ir_data.src[i].pos[CWIID_X] = -1;
584                ir_data.src[i].pos[CWIID_Y] = -1;
585                ir_data.src[i].size = -1;
586        }
587        gtk_widget_queue_draw(drawIR);
588}
589
590void clear_nunchuk_widgets()
591{
592        nc_stick.valid = 0;
593        gtk_widget_queue_draw(drawNCStick);
594
595        gtk_label_set_text(GTK_LABEL(lblNCAccXVal), "0");
596        gtk_label_set_text(GTK_LABEL(lblNCAccYVal), "0");
597        gtk_label_set_text(GTK_LABEL(lblNCAccZVal), "0");
598        gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(progNCAccX), 0.0);
599        gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(progNCAccY), 0.0);
600        gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(progNCAccZ), 0.0);
601        gtk_label_set_text(GTK_LABEL(lblNCAccVal), "0");
602        gtk_label_set_text(GTK_LABEL(lblNCRollVal), "0");
603        gtk_label_set_text(GTK_LABEL(lblNCPitchVal), "0");
604}
605
606void clear_classic_widgets()
607{
608        cc_l_stick.valid = 0;
609        gtk_widget_queue_draw(drawCCLStick);
610        cc_r_stick.valid = 0;
611        gtk_widget_queue_draw(drawCCRStick);
612
613        gtk_label_set_text(GTK_LABEL(lblCCLVal), "0");
614        gtk_label_set_text(GTK_LABEL(lblCCRVal), "0");
615        gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(progCCL), 0.0);
616        gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(progCCR), 0.0);
617}
618
619gboolean winMain_delete_event(void)
620{
621        menuQuit_activate();
622        return FALSE;
623}
624
625gboolean winRW_delete_event(void)
626{
627        btnRWClose_clicked();
628        return TRUE;
629}
630
631void menuConnect_activate(void)
632{
633        char reset_bdaddr = 0;
634
635        if (bacmp(&bdaddr, BDADDR_ANY) == 0) {
636                reset_bdaddr = 1;
637        }
638        message(GTK_MESSAGE_INFO,
639                "Put Wiimote in discoverable mode (press 1+2) and press OK",
640                 GTK_WINDOW(winMain));
641        if ((wiimote = cwiid_open(&bdaddr, CWIID_FLAG_MESG_IFC)) == NULL) {
642                message(GTK_MESSAGE_ERROR, "Unable to connect", GTK_WINDOW(winMain));
643                status("No connection");
644        }
645        else if (cwiid_set_mesg_callback(wiimote, &cwiid_callback)) {
646                message(GTK_MESSAGE_ERROR, "Error setting callback",
647                        GTK_WINDOW(winMain));
648                if (cwiid_close(wiimote)) {
649                        message(GTK_MESSAGE_ERROR, "Error on disconnect",
650                                GTK_WINDOW(winMain));
651                }
652                wiimote = NULL;
653                status("No connection");
654        }
655        else {
656                status("Connected");
657                if (cwiid_get_acc_cal(wiimote, CWIID_EXT_NONE, &wm_cal)) {
658                        message(GTK_MESSAGE_ERROR, "Unable to retrieve accelerometer "
659                                "calibration", GTK_WINDOW(winMain));
660                }
661                set_gui_state();
662                set_report_mode();
663                cwiid_request_status(wiimote);
664        }
665
666        if (reset_bdaddr) {
667                bdaddr = *BDADDR_ANY;
668        }
669}
670
671void menuDisconnect_activate(void)
672{
673        if (cwiid_close(wiimote)) {
674                message(GTK_MESSAGE_ERROR, "Error on disconnect", GTK_WINDOW(winMain));
675        }
676        wiimote = NULL;
677        status("No connection");
678        clear_widgets();
679        set_gui_state();
680}
681
682void menuQuit_activate(void)
683{
684        if (wiimote) {
685                menuDisconnect_activate();
686        }
687        gtk_main_quit();
688}
689
690void menuRW_activate(void)
691{
692        gtk_widget_show(winRW);
693}
694
695void menuAbout_activate(void)
696{
697        gtk_show_about_dialog(GTK_WINDOW(winMain),
698                              "name", APP_NAME,
699                              "version", CWIID_VERSION,
700                              "copyright", APP_COPYRIGHT,
701                              "comments", APP_COMMENTS,
702                              NULL);
703}
704
705void chkAcc_toggled(void)
706{
707        if (wiimote) {
708                set_report_mode();
709        }
710        if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(chkAcc))) {
711                clear_acc_widgets();
712        }
713        set_gui_state();
714}
715
716void chkIR_toggled(void)
717{
718        if (wiimote) {
719                set_report_mode();
720        }
721        if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(chkIR))) {
722                clear_ir_data();
723        }
724        set_gui_state();
725}
726
727void chkExt_toggled(void)
728{
729        if (wiimote) {
730                set_report_mode();
731        }
732        if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(chkExt))) {
733                clear_nunchuk_widgets();
734                clear_classic_widgets();
735        }
736        set_gui_state();
737}
738
739void chkLED_toggled(void)
740{
741        uint8_t LED_state;
742
743        if (wiimote) {
744                LED_state =
745                  (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(chkLED1))
746                    ? CWIID_LED1_ON : 0) |
747                  (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(chkLED2))
748                    ? CWIID_LED2_ON : 0) |
749                  (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(chkLED3))
750                    ? CWIID_LED3_ON : 0) |
751                  (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(chkLED4))
752                    ? CWIID_LED4_ON : 0);
753                if (cwiid_set_led(wiimote, LED_state)) {
754                        message(GTK_MESSAGE_ERROR, "error setting LEDs",
755                                GTK_WINDOW(winMain));
756                }
757        }
758}
759
760void chkRumble_toggled(void)
761{
762        if (wiimote) {
763                if (cwiid_set_rumble(wiimote,
764                  gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(chkRumble)))) {
765                        message(GTK_MESSAGE_ERROR, "error setting rumble",
766                                GTK_WINDOW(winMain));
767                }
768        }
769}
770
771void drawIR_expose_event(void)
772{
773        int i;
774        int size;
775        gint width, height;
776
777        gdk_window_get_geometry(drawIR->window, NULL, NULL, &width, &height, NULL);
778
779        for (i=0; i < CWIID_IR_SRC_COUNT; i++) {
780                if (ir_data.src[i].valid) {
781                        if (ir_data.src[i].size == -1) {
782                                size = 3;
783                        }
784                        else {
785                                size = ir_data.src[i].size+1;
786                        }
787                        gdk_draw_arc(drawIR->window,
788                                     drawIR->style->fg_gc[GTK_WIDGET_STATE(drawIR)],
789                                     TRUE,
790                                                 ir_data.src[i].pos[CWIID_X] * width / CWIID_IR_X_MAX,
791                                                 height - ir_data.src[i].pos[CWIID_Y] * height /
792                                              CWIID_IR_Y_MAX,
793                                                 size, size,
794                                                 0, 64 * 360);
795                }
796        }
797}
798
799void drawStick_expose_event(GtkWidget *drawStick, GdkEventExpose *event,
800                            struct stick *stick)
801{
802        gint width, height;
803
804        gdk_window_get_geometry(drawStick->window, NULL, NULL, &width, &height,
805                                NULL);
806        gdk_draw_arc(drawStick->window,
807                     drawStick->style->fg_gc[GTK_WIDGET_STATE(drawStick)],
808                                 FALSE,
809                                 0, 0, width-1, height-1, 0, 64*360);
810        if (stick->valid) {
811                gdk_draw_arc(drawStick->window,
812                             drawStick->style->fg_gc[GTK_WIDGET_STATE(drawStick)],
813                             TRUE,
814                             (double)stick->x/stick->max*width - 2,
815                             (1 - (double)stick->y/stick->max)*height - 2,
816                             3, 3, 0, 64*360);
817        }
818}
819
820void btnRead_clicked(void)
821{
822        static unsigned char buf[CWIID_MAX_READ_LEN];
823        static char txt[CWIID_MAX_READ_LEN*4+50]; /* 3 chars per byte, with
824                                                     * plenty extra */
825        GtkTextIter text_iter;
826        GtkTextMark *p_text_mark;
827        char *cursor;
828        unsigned int offset, len;
829        int flags;
830        unsigned int i;
831
832        /* Decode arguments */
833        offset = strtol(gtk_entry_get_text(GTK_ENTRY(txtReadOffset)), &cursor, 16);
834        if (*cursor != '\0') {
835                message(GTK_MESSAGE_ERROR, "Invalid read offset", GTK_WINDOW(winRW));
836        }
837
838        len = strtol(gtk_entry_get_text(GTK_ENTRY(txtReadLen)), &cursor, 16);
839        if (*cursor != '\0') {
840                message(GTK_MESSAGE_ERROR, "Invalid read len", GTK_WINDOW(winRW));
841        }
842        if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(radReadReg))) {
843                flags = CWIID_RW_REG;
844        }
845        else {
846                flags = CWIID_RW_EEPROM;
847        }
848
849        /* Make the call */
850        if (cwiid_read(wiimote, flags, offset, len, buf)) {
851                message(GTK_MESSAGE_ERROR, "Wiimote read error", GTK_WINDOW(winRW));
852        }
853        else {
854                /* construct the hexedit-style string */
855                cursor=txt;
856                sprintf(cursor, "0x%08X:", offset & ~0xF);
857                cursor+=11;
858                for (i=0; i < (offset & 0xF); i++) {
859                        sprintf(cursor, "   ");
860                        cursor+=3;
861                }
862                for (i=0; i < len; i++) {
863                        if ((((i + offset) & 0xF) == 0) && (i!=0)) {
864                                sprintf(cursor, "\n0x%08X:", offset+i);
865                                cursor+=12;
866                        }
867                        if (((i +offset) & 0x7) == 0) {
868                                sprintf(cursor, " ");
869                                cursor++;
870                        }
871                        sprintf(cursor, "%02X ", buf[i]);
872                        cursor+=3;
873                }
874                sprintf(cursor, "\n\n");
875
876                gtk_text_buffer_get_end_iter(tbRW, &text_iter);
877                p_text_mark = gtk_text_buffer_create_mark(tbRW, NULL, &text_iter,
878                                                          TRUE);
879                gtk_text_buffer_insert(tbRW, &text_iter, txt, -1);
880                gtk_text_view_scroll_to_mark(GTK_TEXT_VIEW(tvRW), p_text_mark, 0.01,
881                                             TRUE, 0.0, 0.0);
882        }
883}
884
885char chartox(char c)
886{
887        char str[2];
888        char *endptr;
889        int val;
890
891        str[0] = c;
892        str[1] = '\0';
893        val = strtol(str, &endptr, 16);
894        if (*endptr != '\0') {
895                return -1;
896        }
897
898        return (char)val;
899}
900
901#define MAX_WRITE_LEN   0x20
902void btnWrite_clicked(void)
903{
904        static unsigned char buf[MAX_WRITE_LEN];
905        char *cursor, *data;
906        uint32_t offset;
907        uint16_t len;
908        uint8_t flags;
909
910        /* Decode arguments */
911        offset = strtol(gtk_entry_get_text(GTK_ENTRY(txtWriteOffset)), &cursor, 16);
912        if (*cursor != '\0') {
913                message(GTK_MESSAGE_ERROR, "Invalid read offset", GTK_WINDOW(winRW));
914        }
915
916        if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(radWriteReg))) {
917                flags = CWIID_RW_REG;
918        }
919        else {
920                flags = CWIID_RW_EEPROM;
921        }
922
923        data = (char *) gtk_entry_get_text(GTK_ENTRY(txtWriteData));
924        cursor = data;
925        len = 0;
926        while (*cursor != '\0') {
927                if (len > MAX_WRITE_LEN) {
928                        message(GTK_MESSAGE_ERROR, "Message too long", GTK_WINDOW(winRW));
929                        return;
930                }
931                /* Trim Leading spaces */
932                while (*cursor == ' ') {
933                        cursor++;
934                }
935                /* Test for end */
936                if (*cursor == '\0') {
937                        break;
938                }
939                /* Read first nibble */
940                if (!isxdigit((int)*cursor)) {
941                        message(GTK_MESSAGE_ERROR, "Invalid write data",
942                                GTK_WINDOW(winRW));
943                        return;
944                }
945                buf[len] = chartox(*cursor)<<4;
946
947                /* Read second nibble */
948                cursor++;
949                if (!isxdigit((int)*cursor)) {
950                        message(GTK_MESSAGE_ERROR,
951                                "Invalid write data (digits must come in pairs)",
952                                GTK_WINDOW(winRW));
953                        return;
954                }
955                buf[len] = buf[len] | chartox(*cursor);
956
957                cursor++;
958                len++;
959        }
960
961        if (len == 0) {
962                message(GTK_MESSAGE_ERROR, "No write data", GTK_WINDOW(winRW));
963                return;
964        }
965
966        /* Make the call */
967        if (cwiid_write(wiimote, flags, offset, len, buf)) {
968                message(GTK_MESSAGE_ERROR, "Wiimote write error", GTK_WINDOW(winRW));
969        }
970        else {
971                message(GTK_MESSAGE_INFO, "Wiimote write successful",
972                        GTK_WINDOW(winRW));
973        }
974}
975
976void btnRWClose_clicked(void)
977{
978        gtk_widget_hide(winRW);
979}
980
981void btnBeep_clicked(void)
982{
983        /*if (cwiid_beep(wiimote)) {
984                message(GTK_MESSAGE_ERROR, "Wiimote sound error", GTK_WINDOW(winMain));
985        }*/
986}
987
988void set_report_mode(void)
989{
990        uint8_t rpt_mode;
991       
992        rpt_mode = CWIID_RPT_STATUS | CWIID_RPT_BTN;
993
994        if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(chkIR))) {
995                rpt_mode |= CWIID_RPT_IR;
996        }
997        if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(chkAcc))) {
998                rpt_mode |= CWIID_RPT_ACC;
999        }
1000        if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(chkExt))) {
1001                rpt_mode |= CWIID_RPT_EXT;
1002        }
1003        if (cwiid_set_rpt_mode(wiimote, rpt_mode)) {
1004                message(GTK_MESSAGE_ERROR, "error setting report mode",
1005                        GTK_WINDOW(winMain));
1006        }
1007}
1008
1009#define BATTERY_STR_LEN 14      /* "Battery: 100%" + '\0' */
1010void cwiid_callback(cwiid_wiimote_t *wiimote, int mesg_count,
1011                    union cwiid_mesg mesg_array[], struct timespec *timestamp)
1012{
1013        int i;
1014        char battery[BATTERY_STR_LEN];
1015        char *ext_str;
1016        static enum cwiid_ext_type ext_type = CWIID_EXT_NONE;
1017
1018        gdk_threads_enter();
1019        for (i=0; i < mesg_count; i++) {
1020                switch (mesg_array[i].type) {
1021                case CWIID_MESG_STATUS:
1022                        snprintf(battery, BATTERY_STR_LEN,"Battery:%d%%",
1023                                 (int) (100.0 * mesg_array[i].status_mesg.battery /
1024                                        CWIID_BATTERY_MAX));
1025                        gtk_statusbar_push(GTK_STATUSBAR(statBattery), 0, battery);
1026                        switch (mesg_array[i].status_mesg.ext_type) {
1027                        case CWIID_EXT_NONE:
1028                                ext_str = "No extension";
1029                                break;
1030                        case CWIID_EXT_NUNCHUK:
1031                                ext_str = "Nunchuk";
1032                                if (ext_type != CWIID_EXT_NUNCHUK) {
1033                                        if (cwiid_get_acc_cal(wiimote, CWIID_EXT_NUNCHUK,
1034                                                              &nc_cal)) {
1035                                                message(GTK_MESSAGE_ERROR,
1036                                                        "Unable to retrieve accelerometer calibration",
1037                                                        GTK_WINDOW(winMain));
1038                                        }
1039                                }
1040                                break;
1041                        case CWIID_EXT_CLASSIC:
1042                                ext_str = "Classic controller";
1043                                break;
1044                        case CWIID_EXT_UNKNOWN:
1045                                ext_str = "Unknown extension";
1046                                break;
1047                        }
1048                        gtk_statusbar_push(GTK_STATUSBAR(statExtension), 0, ext_str);
1049                        clear_nunchuk_widgets();
1050                        clear_classic_widgets();
1051                        ext_type = mesg_array[i].status_mesg.ext_type;
1052                        break;
1053                case CWIID_MESG_BTN:
1054                        cwiid_btn(&mesg_array[i].btn_mesg);
1055                        break;
1056                case CWIID_MESG_ACC:
1057                        cwiid_acc(&mesg_array[i].acc_mesg);
1058                        break;
1059                case CWIID_MESG_IR:
1060                        cwiid_ir(&mesg_array[i].ir_mesg);
1061                        break;
1062                case CWIID_MESG_NUNCHUK:
1063                        cwiid_nunchuk(&mesg_array[i].nunchuk_mesg);
1064                        break;
1065                case CWIID_MESG_CLASSIC:
1066                        cwiid_classic(&mesg_array[i].classic_mesg);
1067                        break;
1068                case CWIID_MESG_ERROR:
1069                        menuDisconnect_activate();
1070                        break;
1071                default:
1072                        break;
1073                }
1074        }
1075        gdk_flush();
1076        gdk_threads_leave();
1077}
1078
1079void cwiid_btn(struct cwiid_btn_mesg *mesg)
1080{
1081        gtk_widget_modify_bg(evUp, GTK_STATE_NORMAL,
1082            (mesg->buttons & CWIID_BTN_UP) ? &btn_on : &btn_off);
1083        gtk_widget_modify_bg(evDown, GTK_STATE_NORMAL,
1084            (mesg->buttons & CWIID_BTN_DOWN) ? &btn_on : &btn_off);
1085        gtk_widget_modify_bg(evLeft, GTK_STATE_NORMAL,
1086            (mesg->buttons & CWIID_BTN_LEFT) ? &btn_on : &btn_off);
1087        gtk_widget_modify_bg(evRight, GTK_STATE_NORMAL,
1088            (mesg->buttons & CWIID_BTN_RIGHT) ? &btn_on : &btn_off);
1089        gtk_widget_modify_bg(evA, GTK_STATE_NORMAL,
1090            (mesg->buttons & CWIID_BTN_A) ? &btn_on : &btn_off);
1091        gtk_widget_modify_bg(evB, GTK_STATE_NORMAL,
1092            (mesg->buttons & CWIID_BTN_B) ? &btn_on : &btn_off);
1093        gtk_widget_modify_bg(evMinus, GTK_STATE_NORMAL,
1094            (mesg->buttons & CWIID_BTN_MINUS) ? &btn_on : &btn_off);
1095        gtk_widget_modify_bg(evPlus, GTK_STATE_NORMAL,
1096            (mesg->buttons & CWIID_BTN_PLUS) ? &btn_on : &btn_off);
1097        gtk_widget_modify_bg(evHome, GTK_STATE_NORMAL,
1098            (mesg->buttons & CWIID_BTN_HOME) ? &btn_on : &btn_off);
1099        gtk_widget_modify_bg(ev1, GTK_STATE_NORMAL,
1100            (mesg->buttons & CWIID_BTN_1) ? &btn_on : &btn_off);
1101        gtk_widget_modify_bg(ev2, GTK_STATE_NORMAL,
1102            (mesg->buttons & CWIID_BTN_2) ? &btn_on : &btn_off);
1103}
1104
1105#define LBLVAL_LEN 6
1106void cwiid_acc(struct cwiid_acc_mesg *mesg)
1107{
1108        static gchar str[LBLVAL_LEN];
1109        double a_x, a_y, a_z, a;
1110        double roll, pitch;
1111       
1112        if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(chkAcc))) {
1113                g_snprintf(str, LBLVAL_LEN, "%X", mesg->acc[CWIID_X]);
1114                gtk_label_set_text(GTK_LABEL(lblAccXVal), str);
1115                gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(progAccX),
1116                                              (double)mesg->acc[CWIID_X]/0xFF);
1117                g_snprintf(str, LBLVAL_LEN, "%X", mesg->acc[CWIID_Y]);
1118                gtk_label_set_text(GTK_LABEL(lblAccYVal), str);
1119                gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(progAccY),
1120                                              (double)mesg->acc[CWIID_Y]/0xFF);
1121                g_snprintf(str, LBLVAL_LEN, "%X", mesg->acc[CWIID_Z]);
1122                gtk_label_set_text(GTK_LABEL(lblAccZVal), str);
1123                gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(progAccZ),
1124                                              (double)mesg->acc[CWIID_Z]/0xFF);
1125
1126                a_x = ((double)mesg->acc[CWIID_X] - wm_cal.zero[CWIID_X]) /
1127                      (wm_cal.one[CWIID_X] - wm_cal.zero[CWIID_X]);
1128                a_y = ((double)mesg->acc[CWIID_Y] - wm_cal.zero[CWIID_Y]) /
1129                      (wm_cal.one[CWIID_Y] - wm_cal.zero[CWIID_Y]);
1130                a_z = ((double)mesg->acc[CWIID_Z] - wm_cal.zero[CWIID_Z]) /
1131                      (wm_cal.one[CWIID_Z] - wm_cal.zero[CWIID_Z]);
1132                a = sqrt(pow(a_x,2)+pow(a_y,2)+pow(a_z,2));
1133
1134                roll = atan(a_x/a_z);
1135                if (a_z <= 0.0) {
1136                        roll += PI * ((a_x > 0.0) ? 1 : -1);
1137                }
1138                roll *= -1;
1139
1140                pitch = atan(a_y/a_z*cos(roll));
1141
1142                g_snprintf(str, LBLVAL_LEN, "%.2f", a);
1143                gtk_label_set_text(GTK_LABEL(lblAccVal), str);
1144                g_snprintf(str, LBLVAL_LEN, "%.2f", roll);
1145                gtk_label_set_text(GTK_LABEL(lblRollVal), str);
1146                g_snprintf(str, LBLVAL_LEN, "%.2f", pitch);
1147                gtk_label_set_text(GTK_LABEL(lblPitchVal), str);
1148        }
1149}
1150
1151void cwiid_ir(struct cwiid_ir_mesg *mesg)
1152{
1153        if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(chkIR))) {
1154                /* memcpy(&ir_data, mesg, sizeof(struct cwiid_ir_mesg)); */
1155                ir_data = *mesg;
1156                gtk_widget_queue_draw(drawIR);
1157        }
1158}
1159
1160void cwiid_nunchuk(struct cwiid_nunchuk_mesg *mesg)
1161{
1162        static gchar str[LBLVAL_LEN];
1163        double a_x, a_y, a_z, a;
1164        double roll, pitch;
1165       
1166        if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(chkExt))) {
1167                gtk_widget_modify_bg(evNCC, GTK_STATE_NORMAL,
1168                    (mesg->buttons & CWIID_NUNCHUK_BTN_C) ? &btn_on : &btn_off);
1169                gtk_widget_modify_bg(evNCZ, GTK_STATE_NORMAL,
1170                    (mesg->buttons & CWIID_NUNCHUK_BTN_Z) ? &btn_on : &btn_off);
1171
1172                nc_stick.valid = 1;
1173                nc_stick.x = mesg->stick[CWIID_X];
1174                nc_stick.y = mesg->stick[CWIID_Y];
1175                gtk_widget_queue_draw(drawNCStick);
1176
1177                g_snprintf(str, LBLVAL_LEN, "%X", mesg->acc[CWIID_X]);
1178                gtk_label_set_text(GTK_LABEL(lblNCAccXVal), str);
1179                gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(progNCAccX),
1180                                              (double)mesg->acc[CWIID_X]/0xFF);
1181                g_snprintf(str, LBLVAL_LEN, "%X", mesg->acc[CWIID_Y]);
1182                gtk_label_set_text(GTK_LABEL(lblNCAccYVal), str);
1183                gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(progNCAccY),
1184                                              (double)mesg->acc[CWIID_Y]/0xFF);
1185                g_snprintf(str, LBLVAL_LEN, "%X", mesg->acc[CWIID_Z]);
1186                gtk_label_set_text(GTK_LABEL(lblNCAccZVal), str);
1187                gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(progNCAccZ),
1188                                              (double)mesg->acc[CWIID_Z]/0xFF);
1189
1190                /* TODO: get nunchuk calibration */
1191                a_x = ((double)mesg->acc[CWIID_X] - nc_cal.zero[CWIID_X]) /
1192                      (nc_cal.one[CWIID_X] - nc_cal.zero[CWIID_X]);
1193                a_y = ((double)mesg->acc[CWIID_Y] - nc_cal.zero[CWIID_Y]) /
1194                      (nc_cal.one[CWIID_Y] - nc_cal.zero[CWIID_Y]);
1195                a_z = ((double)mesg->acc[CWIID_Z] - nc_cal.zero[CWIID_Z]) /
1196                      (nc_cal.one[CWIID_Z] - nc_cal.zero[CWIID_Z]);
1197                a = sqrt(pow(a_x,2)+pow(a_y,2)+pow(a_z,2));
1198                roll = atan(a_x/a_z);
1199                if (a_z <= 0.0) {
1200                        roll += PI * ((a_x > 0.0) ? 1 : -1);
1201                }
1202                roll *= -1;
1203
1204                pitch = atan(a_y/a_z*cos(roll));
1205
1206                g_snprintf(str, LBLVAL_LEN, "%.2f", a);
1207                gtk_label_set_text(GTK_LABEL(lblNCAccVal), str);
1208                g_snprintf(str, LBLVAL_LEN, "%.2f", roll);
1209                gtk_label_set_text(GTK_LABEL(lblNCRollVal), str);
1210                g_snprintf(str, LBLVAL_LEN, "%.2f", pitch);
1211                gtk_label_set_text(GTK_LABEL(lblNCPitchVal), str);
1212        }
1213}
1214
1215void cwiid_classic(struct cwiid_classic_mesg *mesg)
1216{
1217        static gchar str[LBLVAL_LEN];
1218
1219        if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(chkExt))) {
1220                gtk_widget_modify_bg(evCCUp, GTK_STATE_NORMAL,
1221                    (mesg->buttons & CWIID_CLASSIC_BTN_UP) ? &btn_on : &btn_off);
1222                gtk_widget_modify_bg(evCCDown, GTK_STATE_NORMAL,
1223                    (mesg->buttons & CWIID_CLASSIC_BTN_DOWN) ? &btn_on : &btn_off);
1224                gtk_widget_modify_bg(evCCLeft, GTK_STATE_NORMAL,
1225                    (mesg->buttons & CWIID_CLASSIC_BTN_LEFT) ? &btn_on : &btn_off);
1226                gtk_widget_modify_bg(evCCRight, GTK_STATE_NORMAL,
1227                    (mesg->buttons & CWIID_CLASSIC_BTN_RIGHT) ? &btn_on : &btn_off);
1228                gtk_widget_modify_bg(evCCMinus, GTK_STATE_NORMAL,
1229                    (mesg->buttons & CWIID_CLASSIC_BTN_MINUS) ? &btn_on : &btn_off);
1230                gtk_widget_modify_bg(evCCPlus, GTK_STATE_NORMAL,
1231                    (mesg->buttons & CWIID_CLASSIC_BTN_PLUS) ? &btn_on : &btn_off);
1232                gtk_widget_modify_bg(evCCHome, GTK_STATE_NORMAL,
1233                    (mesg->buttons & CWIID_CLASSIC_BTN_HOME) ? &btn_on : &btn_off);
1234                gtk_widget_modify_bg(evCCA, GTK_STATE_NORMAL,
1235                    (mesg->buttons & CWIID_CLASSIC_BTN_A) ? &btn_on : &btn_off);
1236                gtk_widget_modify_bg(evCCB, GTK_STATE_NORMAL,
1237                    (mesg->buttons & CWIID_CLASSIC_BTN_B) ? &btn_on : &btn_off);
1238                gtk_widget_modify_bg(evCCX, GTK_STATE_NORMAL,
1239                    (mesg->buttons & CWIID_CLASSIC_BTN_X) ? &btn_on : &btn_off);
1240                gtk_widget_modify_bg(evCCY, GTK_STATE_NORMAL,
1241                    (mesg->buttons & CWIID_CLASSIC_BTN_Y) ? &btn_on : &btn_off);
1242                gtk_widget_modify_bg(evCCZL, GTK_STATE_NORMAL,
1243                    (mesg->buttons & CWIID_CLASSIC_BTN_ZL) ? &btn_on : &btn_off);
1244                gtk_widget_modify_bg(evCCZR, GTK_STATE_NORMAL,
1245                    (mesg->buttons & CWIID_CLASSIC_BTN_ZR) ? &btn_on : &btn_off);
1246
1247                cc_l_stick.valid = 1;
1248                cc_l_stick.x = mesg->l_stick[CWIID_X];
1249                cc_l_stick.y = mesg->l_stick[CWIID_Y];
1250                gtk_widget_queue_draw(drawCCLStick);
1251
1252                cc_r_stick.valid = 1;
1253                cc_r_stick.x = mesg->r_stick[CWIID_X];
1254                cc_r_stick.y = mesg->r_stick[CWIID_Y];
1255                gtk_widget_queue_draw(drawCCRStick);
1256               
1257                g_snprintf(str, LBLVAL_LEN, "%X", mesg->l);
1258                gtk_label_set_text(GTK_LABEL(lblCCLVal), str);
1259                gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(progCCL),
1260                                              (double)mesg->l/CWIID_CLASSIC_LR_MAX);
1261                gtk_widget_modify_bg(evCCL, GTK_STATE_NORMAL,
1262                    (mesg->buttons & CWIID_CLASSIC_BTN_L) ? &btn_on : &btn_off);
1263                g_snprintf(str, LBLVAL_LEN, "%X", mesg->r);
1264                gtk_label_set_text(GTK_LABEL(lblCCRVal), str);
1265                gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(progCCR),
1266                                              (double)mesg->r/CWIID_CLASSIC_LR_MAX);
1267                gtk_widget_modify_bg(evCCR, GTK_STATE_NORMAL,
1268                    (mesg->buttons & CWIID_CLASSIC_BTN_R) ? &btn_on : &btn_off);
1269        }
1270}
1271
Note: See TracBrowser for help on using the browser.