root/wmgui/main.c

Revision 11004aad1d57dad8aaea25a3b78c356e4a867aea, 43.1 kB (checked in by L. Donnie Smith <donnie.smith@…>, 2 years ago)

added motionplus interface to wmgui

  • Property mode set to 100644
Line 
1/* Copyright (C) 2007 L. Donnie Smith <donnie.smith@gatech.edu>
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 */
18
19#ifdef HAVE_CONFIG_H
20#include "config.h"
21#endif
22
23#define APP_NAME                "CWiid wmgui"
24#define APP_VERSION             PACKAGE_VERSION
25#define APP_COPYRIGHT   "Copyright (C) 2007 L. Donnie Smith " \
26                        "<donnie.smith@gatech.edu>"
27#define APP_COMMENTS    "Wiimote GUI"
28
29#include <ctype.h>
30#include <float.h>
31#include <math.h>
32#include <stdio.h>
33#include <stdint.h>
34#include <string.h>
35#include <stdlib.h>
36#include <unistd.h>
37
38#include <glib.h>
39#include <gtk/gtk.h>
40
41#include "interface.h"
42#include "support.h"
43
44#include <bluetooth/bluetooth.h>
45#include "cwiid.h"
46
47#define PI      3.14159265358979323
48
49struct stick {
50        char valid;
51        uint8_t x;
52        uint8_t y;
53        uint8_t max;
54};
55
56/* Globals */
57cwiid_wiimote_t *wiimote = NULL;
58bdaddr_t bdaddr;
59struct acc_cal wm_cal, nc_cal;
60struct cwiid_ir_mesg ir_data;
61struct stick nc_stick;
62struct stick cc_l_stick, cc_r_stick;
63
64/* Widgets */
65GtkWidget *winMain;
66GtkWidget *winRW;
67GtkWidget *winDialog;
68GtkWidget *menuConnect, *menuDisconnect, *menuQuit, *menuRW, *menuAbout;
69GtkWidget *chkAcc, *chkIR, *chkExt;
70GtkWidget *chkLED1, *chkLED2, *chkLED3, *chkLED4;
71GtkWidget *chkRumble;
72GtkWidget *evUp, *evDown, *evLeft, *evRight, *evA, *evB,
73          *evMinus, *evPlus, *evHome, *ev1, *ev2;
74GtkWidget *lblUp, *lblDown, *lblLeft, *lblRight, *lblA, *lblB,
75          *lblMinus, *lblPlus, *lblHome, *lbl1, *lbl2;
76GtkWidget *lblAccX, *lblAccY, *lblAccZ;
77GtkWidget *lblAccXVal, *lblAccYVal, *lblAccZVal;
78GtkWidget *progAccX, *progAccY, *progAccZ;
79GtkWidget *lblAcc, *lblRoll, *lblPitch;
80GtkWidget *lblAccVal, *lblRollVal, *lblPitchVal;
81GtkWidget *lblIR;
82GtkWidget *drawIR;
83GtkWidget *lblNC;
84GtkWidget *drawNCStick;
85GtkWidget *evNCC, *evNCZ;
86GtkWidget *lblNCC, *lblNCZ;
87GtkWidget *lblNCAccX, *lblNCAccY, *lblNCAccZ;
88GtkWidget *lblNCAccXVal, *lblNCAccYVal, *lblNCAccZVal;
89GtkWidget *progNCAccX, *progNCAccY, *progNCAccZ;
90GtkWidget *lblNCAcc, *lblNCRoll, *lblNCPitch;
91GtkWidget *lblNCAccVal, *lblNCRollVal, *lblNCPitchVal;
92GtkWidget *evCCUp, *evCCDown, *evCCLeft, *evCCRight, *evCCMinus, *evCCPlus,
93          *evCCHome, *evCCA, *evCCB, *evCCX, *evCCY, *evCCZL, *evCCZR;
94GtkWidget *lblCCUp, *lblCCDown, *lblCCLeft, *lblCCRight, *lblCCMinus,
95          *lblCCPlus, *lblCCHome, *lblCCA, *lblCCB, *lblCCX, *lblCCY, *lblCCZL,
96          *lblCCZR;
97GtkWidget *drawCCLStick, *drawCCRStick;
98GtkWidget *evCCL, *evCCR;
99GtkWidget *lblCCL, *lblCCR;
100GtkWidget *lblCCLVal, *lblCCRVal;
101GtkWidget *progCCL, *progCCR;
102GtkWidget *lblMPPhi, *lblMPTheta, *lblMPPsi;
103GtkWidget *lblMPPhiVal, *lblMPThetaVal, *lblMPPsiVal;
104GtkWidget *lblMPPhiSlow, *lblMPThetaSlow, *lblMPPsiSlow;
105GtkWidget *evMPPhiSlow, *evMPThetaSlow, *evMPPsiSlow;
106GtkWidget *progMPPhi, *progMPTheta, *progMPPsi;
107GtkWidget *statConnection, *statBattery, *statExtension;
108GtkWidget *txtReadOffset, *txtReadLen;
109GtkWidget *radReadEEPROM, *radReadReg;
110GtkWidget *btnRead;
111GtkWidget *txtWriteOffset, *txtWriteData;
112GtkWidget *radWriteEEPROM, *radWriteReg;
113GtkWidget *btnWrite;
114GtkWidget *tvRW;
115GtkWidget *btnRWClose;
116GtkWidget *btnBeep;
117
118GtkTextBuffer *tbRW;
119
120GdkColor btn_on, btn_off;
121
122/* Utility functions */
123void set_gui_state();
124void clear_widgets();
125void clear_acc_widgets();
126void clear_ir_data();
127void clear_nunchuk_widgets();
128void clear_classic_widgets();
129void clear_motionplus_widgets();
130void message(GtkMessageType type, const gchar *message, GtkWindow *parent);
131void status(const gchar *status);
132
133/* GTK Callbacks */
134gboolean winMain_delete_event(void);
135gboolean winRW_delete_event(void);
136void menuConnect_activate(void);
137void menuDisconnect_activate(void);
138void menuQuit_activate(void);
139void menuRW_activate(void);
140void menuAbout_activate(void);
141void chkAcc_toggled(void);
142void chkIR_toggled(void);
143void chkExt_toggled(void);
144void chkLED_toggled(void);
145void chkRumble_toggled(void);
146void drawIR_expose_event(void);
147void drawStick_expose_event(GtkWidget *, GdkEventExpose *, struct stick *);
148void btnRead_clicked(void);
149void btnWrite_clicked(void);
150void btnRWClose_clicked(void);
151void btnBeep_clicked(void);
152
153void set_report_mode(void);
154
155/* Wiimote Callback */
156cwiid_mesg_callback_t cwiid_callback;
157
158/* Wiimote Handler Functions */
159void cwiid_btn(struct cwiid_btn_mesg *);
160void cwiid_acc(struct cwiid_acc_mesg *);
161void cwiid_ir(struct cwiid_ir_mesg *);
162void cwiid_nunchuk(struct cwiid_nunchuk_mesg *);
163void cwiid_classic(struct cwiid_classic_mesg *);
164void cwiid_motionplus(struct cwiid_motionplus_mesg *);
165
166/* GetOpt */
167#define OPTSTRING       "h"
168extern char *optarg;
169extern int optind, opterr, optopt;
170
171#define USAGE "usage:%s [-h] [BDADDR]\n"
172
173/*
174cwiid_err_t err;
175
176void err(int id, const char *s, ...)
177{
178        message(GTK_MESSAGE_ERROR, s, GTK_WINDOW(winMain));
179}
180*/
181
182int main (int argc, char *argv[])
183{
184        int c;
185        char *str_addr;
186
187        gtk_set_locale ();
188        gtk_init (&argc, &argv);
189
190        if (!g_thread_supported()) {
191                g_thread_init(NULL);
192        }
193        gdk_threads_init();
194        gdk_threads_enter();
195
196        /* cwiid_set_err(err); */
197
198        /* Parse Options */
199        while ((c = getopt(argc, argv, OPTSTRING)) != -1) {
200                switch (c) {
201                case 'h':
202                        printf(USAGE, argv[0]);
203                        return 0;
204                        break;
205                case '?':
206                        return -1;
207                        break;
208                default:
209                        printf("unknown command-line option: -%c\n", c);
210                        break;
211                }
212        }
213
214        /* BDADDR */
215        if (optind < argc) {
216                if (str2ba(argv[optind], &bdaddr)) {
217                        printf("invalid bdaddr\n");
218                        bdaddr = *BDADDR_ANY;
219                }
220                optind++;
221                if (optind < argc) {
222                        printf("invalid command-line\n");
223                        printf(USAGE, argv[0]);
224                        return -1;
225                }
226        }
227        else if ((str_addr = getenv(WIIMOTE_BDADDR)) != NULL) {
228                if (str2ba(str_addr, &bdaddr)) {
229                        printf("invalid address in %s\n", WIIMOTE_BDADDR);
230                        bdaddr = *BDADDR_ANY;
231                }
232        }
233        else {
234                bdaddr = *BDADDR_ANY;
235        }               
236
237        /* Create the window */
238        winMain = create_winMain();
239        winRW = create_winRW();
240
241        /* Lookup Widgets */
242        menuConnect = lookup_widget(winMain, "menuConnect");
243        menuDisconnect = lookup_widget(winMain, "menuDisconnect");
244        menuQuit = lookup_widget(winMain, "menuQuit");
245        menuRW = lookup_widget(winMain, "menuRW");
246        menuAbout = lookup_widget(winMain, "menuAbout");
247        chkAcc = lookup_widget(winMain, "chkAcc");
248        chkIR = lookup_widget(winMain, "chkIR");
249        chkExt = lookup_widget(winMain, "chkExt");
250        chkLED1 = lookup_widget(winMain, "chkLED1");
251        chkLED2 = lookup_widget(winMain, "chkLED2");
252        chkLED3 = lookup_widget(winMain, "chkLED3");
253        chkLED4 = lookup_widget(winMain, "chkLED4");
254        chkRumble = lookup_widget(winMain, "chkRumble");
255        evUp = lookup_widget(winMain, "evUp");
256        evDown = lookup_widget(winMain, "evDown");
257        evLeft = lookup_widget(winMain, "evLeft");
258        evRight = lookup_widget(winMain, "evRight");
259        evA = lookup_widget(winMain, "evA");
260        evB = lookup_widget(winMain, "evB");
261        evMinus = lookup_widget(winMain, "evMinus");
262        evPlus = lookup_widget(winMain, "evPlus");
263        evHome = lookup_widget(winMain, "evHome");
264        ev1 = lookup_widget(winMain, "ev1");
265        ev2 = lookup_widget(winMain, "ev2");
266        lblUp = lookup_widget(winMain, "lblUp");
267        lblDown = lookup_widget(winMain, "lblDown");
268        lblLeft = lookup_widget(winMain, "lblLeft");
269        lblRight = lookup_widget(winMain, "lblRight");
270        lblA = lookup_widget(winMain, "lblA");
271        lblB = lookup_widget(winMain, "lblB");
272        lblMinus = lookup_widget(winMain, "lblMinus");
273        lblPlus = lookup_widget(winMain, "lblPlus");
274        lblHome = lookup_widget(winMain, "lblHome");
275        lbl1 = lookup_widget(winMain, "lbl1");
276        lbl2 = lookup_widget(winMain, "lbl2");
277        lblAccX = lookup_widget(winMain, "lblAccX");
278        lblAccY = lookup_widget(winMain, "lblAccY");
279        lblAccZ = lookup_widget(winMain, "lblAccZ");
280        lblAccXVal = lookup_widget(winMain, "lblAccXVal");
281        lblAccYVal = lookup_widget(winMain, "lblAccYVal");
282        lblAccZVal = lookup_widget(winMain, "lblAccZVal");
283        progAccX = lookup_widget(winMain, "progAccX");
284        progAccY = lookup_widget(winMain, "progAccY");
285        progAccZ = lookup_widget(winMain, "progAccZ");
286        lblAcc = lookup_widget(winMain, "lblAcc");
287        lblRoll = lookup_widget(winMain, "lblRoll");
288        lblPitch = lookup_widget(winMain, "lblPitch");
289        lblAccVal = lookup_widget(winMain, "lblAccVal");
290        lblRollVal = lookup_widget(winMain, "lblRollVal");
291        lblPitchVal = lookup_widget(winMain, "lblPitchVal");
292        lblIR = lookup_widget(winMain, "lblIR");
293        drawIR = lookup_widget(winMain, "drawIR");
294        lblNC = lookup_widget(winMain, "lblNC");
295        drawNCStick = lookup_widget(winMain, "drawNCStick");
296        evNCC = lookup_widget(winMain, "evNCC");
297        evNCZ = lookup_widget(winMain, "evNCZ");
298        lblNCC = lookup_widget(winMain, "lblNCC");
299        lblNCZ = lookup_widget(winMain, "lblNCZ");
300        lblNCAccX = lookup_widget(winMain, "lblNCAccX");
301        lblNCAccY = lookup_widget(winMain, "lblNCAccY");
302        lblNCAccZ = lookup_widget(winMain, "lblNCAccZ");
303        lblNCAccXVal = lookup_widget(winMain, "lblNCAccXVal");
304        lblNCAccYVal = lookup_widget(winMain, "lblNCAccYVal");
305        lblNCAccZVal = lookup_widget(winMain, "lblNCAccZVal");
306        progNCAccX = lookup_widget(winMain, "progNCAccX");
307        progNCAccY = lookup_widget(winMain, "progNCAccY");
308        progNCAccZ = lookup_widget(winMain, "progNCAccZ");
309        lblNCAcc = lookup_widget(winMain, "lblNCAcc");
310        lblNCRoll = lookup_widget(winMain, "lblNCRoll");
311        lblNCPitch = lookup_widget(winMain, "lblNCPitch");
312        lblNCAccVal = lookup_widget(winMain, "lblNCAccVal");
313        lblNCRollVal = lookup_widget(winMain, "lblNCRollVal");
314        lblNCPitchVal = lookup_widget(winMain, "lblNCPitchVal");
315        evCCUp = lookup_widget(winMain, "evCCUp");
316        evCCDown = lookup_widget(winMain, "evCCDown");
317        evCCLeft = lookup_widget(winMain, "evCCLeft");
318        evCCRight = lookup_widget(winMain, "evCCRight");
319        evCCMinus = lookup_widget(winMain, "evCCMinus");
320        evCCPlus = lookup_widget(winMain, "evCCPlus");
321        evCCHome = lookup_widget(winMain, "evCCHome");
322        evCCA = lookup_widget(winMain, "evCCA");
323        evCCB = lookup_widget(winMain, "evCCB");
324        evCCX = lookup_widget(winMain, "evCCX");
325        evCCY = lookup_widget(winMain, "evCCY");
326        evCCZL = lookup_widget(winMain, "evCCZL");
327        evCCZR = lookup_widget(winMain, "evCCZR");
328        lblCCUp = lookup_widget(winMain, "lblCCUp");
329        lblCCDown = lookup_widget(winMain, "lblCCDown");
330        lblCCLeft = lookup_widget(winMain, "lblCCLeft");
331        lblCCRight = lookup_widget(winMain, "lblCCRight");
332        lblCCMinus = lookup_widget(winMain, "lblCCMinus");
333        lblCCPlus = lookup_widget(winMain, "lblCCPlus");
334        lblCCHome = lookup_widget(winMain, "lblCCHome");
335        lblCCA = lookup_widget(winMain, "lblCCA");
336        lblCCB = lookup_widget(winMain, "lblCCB");
337        lblCCX = lookup_widget(winMain, "lblCCX");
338        lblCCY = lookup_widget(winMain, "lblCCY");
339        lblCCZL = lookup_widget(winMain, "lblCCZL");
340        lblCCZR = lookup_widget(winMain, "lblCCZR");
341        drawCCLStick = lookup_widget(winMain, "drawCCLStick");
342        drawCCRStick = lookup_widget(winMain, "drawCCRStick");
343        evCCL = lookup_widget(winMain, "evCCL");
344        evCCR = lookup_widget(winMain, "evCCR");
345        lblCCL = lookup_widget(winMain, "lblCCL");
346        lblCCR = lookup_widget(winMain, "lblCCR");
347        lblCCLVal = lookup_widget(winMain, "lblCCLVal");
348        lblCCRVal = lookup_widget(winMain, "lblCCRVal");
349        progCCL = lookup_widget(winMain, "progCCL");
350        progCCR = lookup_widget(winMain, "progCCR");
351        lblMPPhi = lookup_widget(winMain, "lblMPPhi");
352        lblMPTheta = lookup_widget(winMain, "lblMPTheta");
353        lblMPPsi = lookup_widget(winMain, "lblMPPsi");
354        lblMPPhiVal = lookup_widget(winMain, "lblMPPhiVal");
355        lblMPThetaVal = lookup_widget(winMain, "lblMPThetaVal");
356        lblMPPsiVal = lookup_widget(winMain, "lblMPPsiVal");
357        evMPPhiSlow = lookup_widget(winMain, "evMPPhiSlow");
358        evMPThetaSlow = lookup_widget(winMain, "evMPThetaSlow");
359        evMPPsiSlow = lookup_widget(winMain, "evMPPsiSlow");
360        lblMPPhiSlow = lookup_widget(winMain, "lblMPPhiSlow");
361        lblMPThetaSlow = lookup_widget(winMain, "lblMPThetaSlow");
362        lblMPPsiSlow = lookup_widget(winMain, "lblMPPsiSlow");
363        progMPPhi = lookup_widget(winMain, "progMPPhi");
364        progMPTheta = lookup_widget(winMain, "progMPTheta");
365        progMPPsi = lookup_widget(winMain, "progMPPsi");
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        gtk_widget_set_sensitive(lblMPPhi, ext_active);
547        gtk_widget_set_sensitive(lblMPTheta, ext_active);
548        gtk_widget_set_sensitive(lblMPPsi       , ext_active);
549        gtk_widget_set_sensitive(lblMPPhiVal, ext_active);
550        gtk_widget_set_sensitive(lblMPThetaVal, ext_active);
551        gtk_widget_set_sensitive(lblMPPsiVal, ext_active);
552        gtk_widget_set_sensitive(lblMPPhiSlow, ext_active);
553        gtk_widget_set_sensitive(lblMPThetaSlow, ext_active);
554        gtk_widget_set_sensitive(lblMPPsiSlow, ext_active);
555        gtk_widget_set_sensitive(progMPPhi, ext_active);
556        gtk_widget_set_sensitive(progMPTheta, ext_active);
557        gtk_widget_set_sensitive(progMPPsi, ext_active);
558}
559
560void clear_widgets()
561{
562        gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(chkLED1), FALSE);
563        gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(chkLED2), FALSE);
564        gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(chkLED3), FALSE);
565        gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(chkLED4), FALSE);
566        gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(chkRumble), FALSE);
567
568        gtk_statusbar_push(GTK_STATUSBAR(statBattery), 0, "");
569        gtk_statusbar_push(GTK_STATUSBAR(statExtension), 0, "");
570
571        clear_acc_widgets();
572        clear_ir_data();
573        clear_nunchuk_widgets();
574        clear_classic_widgets();
575        clear_motionplus_widgets();
576}
577
578void clear_acc_widgets()
579{
580        gtk_label_set_text(GTK_LABEL(lblAccXVal), "0");
581        gtk_label_set_text(GTK_LABEL(lblAccYVal), "0");
582        gtk_label_set_text(GTK_LABEL(lblAccZVal), "0");
583        gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(progAccX), 0.0);
584        gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(progAccY), 0.0);
585        gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(progAccZ), 0.0);
586        gtk_label_set_text(GTK_LABEL(lblAccVal), "0");
587        gtk_label_set_text(GTK_LABEL(lblRollVal), "0");
588        gtk_label_set_text(GTK_LABEL(lblPitchVal), "0");
589}
590
591void clear_ir_data()
592{
593        int i;
594
595        for (i=0; i < CWIID_IR_SRC_COUNT; i++) {
596                ir_data.src[i].pos[CWIID_X] = -1;
597                ir_data.src[i].pos[CWIID_Y] = -1;
598                ir_data.src[i].size = -1;
599        }
600        gtk_widget_queue_draw(drawIR);
601}
602
603void clear_nunchuk_widgets()
604{
605        nc_stick.valid = 0;
606        gtk_widget_queue_draw(drawNCStick);
607
608        gtk_label_set_text(GTK_LABEL(lblNCAccXVal), "0");
609        gtk_label_set_text(GTK_LABEL(lblNCAccYVal), "0");
610        gtk_label_set_text(GTK_LABEL(lblNCAccZVal), "0");
611        gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(progNCAccX), 0.0);
612        gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(progNCAccY), 0.0);
613        gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(progNCAccZ), 0.0);
614        gtk_label_set_text(GTK_LABEL(lblNCAccVal), "0");
615        gtk_label_set_text(GTK_LABEL(lblNCRollVal), "0");
616        gtk_label_set_text(GTK_LABEL(lblNCPitchVal), "0");
617}
618
619void clear_classic_widgets()
620{
621        cc_l_stick.valid = 0;
622        gtk_widget_queue_draw(drawCCLStick);
623        cc_r_stick.valid = 0;
624        gtk_widget_queue_draw(drawCCRStick);
625
626        gtk_label_set_text(GTK_LABEL(lblCCLVal), "0");
627        gtk_label_set_text(GTK_LABEL(lblCCRVal), "0");
628        gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(progCCL), 0.0);
629        gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(progCCR), 0.0);
630}
631
632void clear_motionplus_widgets()
633{
634        gtk_label_set_text(GTK_LABEL(lblMPPhiVal), "0");
635        gtk_label_set_text(GTK_LABEL(lblMPThetaVal), "0");
636        gtk_label_set_text(GTK_LABEL(lblMPPsiVal), "0");
637        gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(progMPPhi), 0.0);
638        gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(progMPTheta), 0.0);
639        gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(progMPPsi), 0.0);
640}
641
642gboolean winMain_delete_event(void)
643{
644        menuQuit_activate();
645        return FALSE;
646}
647
648gboolean winRW_delete_event(void)
649{
650        btnRWClose_clicked();
651        return TRUE;
652}
653
654void menuConnect_activate(void)
655{
656        char reset_bdaddr = 0;
657
658        if (bacmp(&bdaddr, BDADDR_ANY) == 0) {
659                reset_bdaddr = 1;
660        }
661        message(GTK_MESSAGE_INFO,
662                "Put Wiimote in discoverable mode (press 1+2) and press OK",
663                 GTK_WINDOW(winMain));
664        if ((wiimote = cwiid_open(&bdaddr, CWIID_FLAG_MESG_IFC)) == NULL) {
665                message(GTK_MESSAGE_ERROR, "Unable to connect", GTK_WINDOW(winMain));
666                status("No connection");
667        }
668        else if (cwiid_set_mesg_callback(wiimote, &cwiid_callback)) {
669                message(GTK_MESSAGE_ERROR, "Error setting callback",
670                        GTK_WINDOW(winMain));
671                if (cwiid_close(wiimote)) {
672                        message(GTK_MESSAGE_ERROR, "Error on disconnect",
673                                GTK_WINDOW(winMain));
674                }
675                wiimote = NULL;
676                status("No connection");
677        }
678        else {
679                status("Connected");
680                if (cwiid_get_acc_cal(wiimote, CWIID_EXT_NONE, &wm_cal)) {
681                        message(GTK_MESSAGE_ERROR, "Unable to retrieve accelerometer "
682                                "calibration", GTK_WINDOW(winMain));
683                }
684                set_gui_state();
685                set_report_mode();
686                cwiid_enable(wiimote, CWIID_FLAG_MOTIONPLUS);
687                cwiid_request_status(wiimote);
688        }
689
690        if (reset_bdaddr) {
691                bdaddr = *BDADDR_ANY;
692        }
693}
694
695void menuDisconnect_activate(void)
696{
697        if (cwiid_close(wiimote)) {
698                message(GTK_MESSAGE_ERROR, "Error on disconnect", GTK_WINDOW(winMain));
699        }
700        wiimote = NULL;
701        status("No connection");
702        clear_widgets();
703        set_gui_state();
704}
705
706void menuQuit_activate(void)
707{
708        if (wiimote) {
709                menuDisconnect_activate();
710        }
711        gtk_main_quit();
712}
713
714void menuRW_activate(void)
715{
716        gtk_widget_show(winRW);
717}
718
719void menuAbout_activate(void)
720{
721        gtk_show_about_dialog(GTK_WINDOW(winMain),
722                              "name", APP_NAME,
723                              "version", APP_VERSION,
724                              "copyright", APP_COPYRIGHT,
725                              "comments", APP_COMMENTS,
726                              NULL);
727}
728
729void chkAcc_toggled(void)
730{
731        if (wiimote) {
732                set_report_mode();
733        }
734        if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(chkAcc))) {
735                clear_acc_widgets();
736        }
737        set_gui_state();
738}
739
740void chkIR_toggled(void)
741{
742        if (wiimote) {
743                set_report_mode();
744        }
745        if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(chkIR))) {
746                clear_ir_data();
747        }
748        set_gui_state();
749}
750
751void chkExt_toggled(void)
752{
753        if (wiimote) {
754                set_report_mode();
755        }
756        if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(chkExt))) {
757                clear_nunchuk_widgets();
758                clear_classic_widgets();
759                clear_motionplus_widgets();
760        }
761        set_gui_state();
762}
763
764void chkLED_toggled(void)
765{
766        uint8_t LED_state;
767
768        if (wiimote) {
769                LED_state =
770                  (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(chkLED1))
771                    ? CWIID_LED1_ON : 0) |
772                  (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(chkLED2))
773                    ? CWIID_LED2_ON : 0) |
774                  (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(chkLED3))
775                    ? CWIID_LED3_ON : 0) |
776                  (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(chkLED4))
777                    ? CWIID_LED4_ON : 0);
778                if (cwiid_set_led(wiimote, LED_state)) {
779                        message(GTK_MESSAGE_ERROR, "error setting LEDs",
780                                GTK_WINDOW(winMain));
781                }
782        }
783}
784
785void chkRumble_toggled(void)
786{
787        if (wiimote) {
788                if (cwiid_set_rumble(wiimote,
789                  gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(chkRumble)))) {
790                        message(GTK_MESSAGE_ERROR, "error setting rumble",
791                                GTK_WINDOW(winMain));
792                }
793        }
794}
795
796void drawIR_expose_event(void)
797{
798        int i;
799        int size;
800        gint width, height;
801
802        gdk_window_get_geometry(drawIR->window, NULL, NULL, &width, &height, NULL);
803
804        for (i=0; i < CWIID_IR_SRC_COUNT; i++) {
805                if (ir_data.src[i].valid) {
806                        if (ir_data.src[i].size == -1) {
807                                size = 3;
808                        }
809                        else {
810                                size = ir_data.src[i].size+1;
811                        }
812                        gdk_draw_arc(drawIR->window,
813                                     drawIR->style->fg_gc[GTK_WIDGET_STATE(drawIR)],
814                                     TRUE,
815                                                 ir_data.src[i].pos[CWIID_X] * width / CWIID_IR_X_MAX,
816                                                 height - ir_data.src[i].pos[CWIID_Y] * height /
817                                              CWIID_IR_Y_MAX,
818                                                 size, size,
819                                                 0, 64 * 360);
820                }
821        }
822}
823
824void drawStick_expose_event(GtkWidget *drawStick, GdkEventExpose *event,
825                            struct stick *stick)
826{
827        gint width, height;
828
829        gdk_window_get_geometry(drawStick->window, NULL, NULL, &width, &height,
830                                NULL);
831        gdk_draw_arc(drawStick->window,
832                     drawStick->style->fg_gc[GTK_WIDGET_STATE(drawStick)],
833                                 FALSE,
834                                 0, 0, width-1, height-1, 0, 64*360);
835        if (stick->valid) {
836                gdk_draw_arc(drawStick->window,
837                             drawStick->style->fg_gc[GTK_WIDGET_STATE(drawStick)],
838                             TRUE,
839                             (double)stick->x/stick->max*width - 2,
840                             (1 - (double)stick->y/stick->max)*height - 2,
841                             3, 3, 0, 64*360);
842        }
843}
844
845void btnRead_clicked(void)
846{
847        static unsigned char buf[CWIID_MAX_READ_LEN];
848        static char txt[CWIID_MAX_READ_LEN*4+50]; /* 3 chars per byte, with
849                                                     * plenty extra */
850        GtkTextIter text_iter;
851        GtkTextMark *p_text_mark;
852        char *cursor;
853        unsigned int offset, len;
854        int flags;
855        unsigned int i;
856
857        /* Decode arguments */
858        offset = strtol(gtk_entry_get_text(GTK_ENTRY(txtReadOffset)), &cursor, 16);
859        if (*cursor != '\0') {
860                message(GTK_MESSAGE_ERROR, "Invalid read offset", GTK_WINDOW(winRW));
861        }
862
863        len = strtol(gtk_entry_get_text(GTK_ENTRY(txtReadLen)), &cursor, 16);
864        if (*cursor != '\0') {
865                message(GTK_MESSAGE_ERROR, "Invalid read len", GTK_WINDOW(winRW));
866        }
867        if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(radReadReg))) {
868                flags = CWIID_RW_REG;
869        }
870        else {
871                flags = CWIID_RW_EEPROM;
872        }
873
874        /* Make the call */
875        if (cwiid_read(wiimote, flags, offset, len, buf)) {
876                message(GTK_MESSAGE_ERROR, "Wiimote read error", GTK_WINDOW(winRW));
877        }
878        else {
879                /* construct the hexedit-style string */
880                cursor=txt;
881                sprintf(cursor, "0x%08X:", offset & ~0xF);
882                cursor+=11;
883                for (i=0; i < (offset & 0xF); i++) {
884                        sprintf(cursor, "   ");
885                        cursor+=3;
886                }
887                for (i=0; i < len; i++) {
888                        if ((((i + offset) & 0xF) == 0) && (i!=0)) {
889                                sprintf(cursor, "\n0x%08X:", offset+i);
890                                cursor+=12;
891                        }
892                        if (((i +offset) & 0x7) == 0) {
893                                sprintf(cursor, " ");
894                                cursor++;
895                        }
896                        sprintf(cursor, "%02X ", buf[i]);
897                        cursor+=3;
898                }
899                sprintf(cursor, "\n\n");
900
901                gtk_text_buffer_get_end_iter(tbRW, &text_iter);
902                p_text_mark = gtk_text_buffer_create_mark(tbRW, NULL, &text_iter,
903                                                          TRUE);
904                gtk_text_buffer_insert(tbRW, &text_iter, txt, -1);
905                gtk_text_view_scroll_to_mark(GTK_TEXT_VIEW(tvRW), p_text_mark, 0.01,
906                                             TRUE, 0.0, 0.0);
907        }
908}
909
910char chartox(char c)
911{
912        char str[2];
913        char *endptr;
914        int val;
915
916        str[0] = c;
917        str[1] = '\0';
918        val = strtol(str, &endptr, 16);
919        if (*endptr != '\0') {
920                return -1;
921        }
922
923        return (char)val;
924}
925
926#define MAX_WRITE_LEN   0x20
927void btnWrite_clicked(void)
928{
929        static unsigned char buf[MAX_WRITE_LEN];
930        char *cursor, *data;
931        uint32_t offset;
932        uint16_t len;
933        uint8_t flags;
934
935        /* Decode arguments */
936        offset = strtol(gtk_entry_get_text(GTK_ENTRY(txtWriteOffset)), &cursor, 16);
937        if (*cursor != '\0') {
938                message(GTK_MESSAGE_ERROR, "Invalid read offset", GTK_WINDOW(winRW));
939        }
940
941        if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(radWriteReg))) {
942                flags = CWIID_RW_REG;
943        }
944        else {
945                flags = CWIID_RW_EEPROM;
946        }
947
948        data = (char *) gtk_entry_get_text(GTK_ENTRY(txtWriteData));
949        cursor = data;
950        len = 0;
951        while (*cursor != '\0') {
952                if (len > MAX_WRITE_LEN) {
953                        message(GTK_MESSAGE_ERROR, "Message too long", GTK_WINDOW(winRW));
954                        return;
955                }
956                /* Trim Leading spaces */
957                while (*cursor == ' ') {
958                        cursor++;
959                }
960                /* Test for end */
961                if (*cursor == '\0') {
962                        break;
963                }
964                /* Read first nibble */
965                if (!isxdigit((int)*cursor)) {
966                        message(GTK_MESSAGE_ERROR, "Invalid write data",
967                                GTK_WINDOW(winRW));
968                        return;
969                }
970                buf[len] = chartox(*cursor)<<4;
971
972                /* Read second nibble */
973                cursor++;
974                if (!isxdigit((int)*cursor)) {
975                        message(GTK_MESSAGE_ERROR,
976                                "Invalid write data (digits must come in pairs)",
977                                GTK_WINDOW(winRW));
978                        return;
979                }
980                buf[len] = buf[len] | chartox(*cursor);
981
982                cursor++;
983                len++;
984        }
985
986        if (len == 0) {
987                message(GTK_MESSAGE_ERROR, "No write data", GTK_WINDOW(winRW));
988                return;
989        }
990
991        /* Make the call */
992        if (cwiid_write(wiimote, flags, offset, len, buf)) {
993                message(GTK_MESSAGE_ERROR, "Wiimote write error", GTK_WINDOW(winRW));
994        }
995        else {
996                message(GTK_MESSAGE_INFO, "Wiimote write successful",
997                        GTK_WINDOW(winRW));
998        }
999}
1000
1001void btnRWClose_clicked(void)
1002{
1003        gtk_widget_hide(winRW);
1004}
1005
1006void btnBeep_clicked(void)
1007{
1008        /*if (cwiid_beep(wiimote)) {
1009                message(GTK_MESSAGE_ERROR, "Wiimote sound error", GTK_WINDOW(winMain));
1010        }*/
1011}
1012
1013void set_report_mode(void)
1014{
1015        uint8_t rpt_mode;
1016       
1017        rpt_mode = CWIID_RPT_STATUS | CWIID_RPT_BTN;
1018
1019        if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(chkIR))) {
1020                rpt_mode |= CWIID_RPT_IR;
1021        }
1022        if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(chkAcc))) {
1023                rpt_mode |= CWIID_RPT_ACC;
1024        }
1025        if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(chkExt))) {
1026                rpt_mode |= CWIID_RPT_EXT;
1027        }
1028        if (cwiid_set_rpt_mode(wiimote, rpt_mode)) {
1029                message(GTK_MESSAGE_ERROR, "error setting report mode",
1030                        GTK_WINDOW(winMain));
1031        }
1032}
1033
1034#define BATTERY_STR_LEN 14      /* "Battery: 100%" + '\0' */
1035void cwiid_callback(cwiid_wiimote_t *wiimote, int mesg_count,
1036                    union cwiid_mesg mesg_array[], struct timespec *timestamp)
1037{
1038        int i;
1039        char battery[BATTERY_STR_LEN];
1040        char *ext_str;
1041        static enum cwiid_ext_type ext_type = CWIID_EXT_NONE;
1042
1043        gdk_threads_enter();
1044        for (i=0; i < mesg_count; i++) {
1045                switch (mesg_array[i].type) {
1046                case CWIID_MESG_STATUS:
1047                        snprintf(battery, BATTERY_STR_LEN,"Battery:%d%%",
1048                                 (int) (100.0 * mesg_array[i].status_mesg.battery /
1049                                        CWIID_BATTERY_MAX));
1050                        gtk_statusbar_push(GTK_STATUSBAR(statBattery), 0, battery);
1051                        switch (mesg_array[i].status_mesg.ext_type) {
1052                        case CWIID_EXT_NONE:
1053                                ext_str = "No extension";
1054                                break;
1055                        case CWIID_EXT_NUNCHUK:
1056                                ext_str = "Nunchuk";
1057                                if (ext_type != CWIID_EXT_NUNCHUK) {
1058                                        if (cwiid_get_acc_cal(wiimote, CWIID_EXT_NUNCHUK,
1059                                                              &nc_cal)) {
1060                                                message(GTK_MESSAGE_ERROR,
1061                                                        "Unable to retrieve accelerometer calibration",
1062                                                        GTK_WINDOW(winMain));
1063                                        }
1064                                }
1065                                break;
1066                        case CWIID_EXT_CLASSIC:
1067                                ext_str = "Classic controller";
1068                                break;
1069                        case CWIID_EXT_MOTIONPLUS:
1070                                ext_str = "MotionPlus";
1071                                break;
1072                        case CWIID_EXT_UNKNOWN:
1073                                ext_str = "Unknown extension";
1074                                break;
1075                        }
1076                        gtk_statusbar_push(GTK_STATUSBAR(statExtension), 0, ext_str);
1077                        clear_nunchuk_widgets();
1078                        clear_classic_widgets();
1079                        clear_motionplus_widgets();
1080                        ext_type = mesg_array[i].status_mesg.ext_type;
1081                        break;
1082                case CWIID_MESG_BTN:
1083                        cwiid_btn(&mesg_array[i].btn_mesg);
1084                        break;
1085                case CWIID_MESG_ACC:
1086                        cwiid_acc(&mesg_array[i].acc_mesg);
1087                        break;
1088                case CWIID_MESG_IR:
1089                        cwiid_ir(&mesg_array[i].ir_mesg);
1090                        break;
1091                case CWIID_MESG_NUNCHUK:
1092                        cwiid_nunchuk(&mesg_array[i].nunchuk_mesg);
1093                        break;
1094                case CWIID_MESG_CLASSIC:
1095                        cwiid_classic(&mesg_array[i].classic_mesg);
1096                        break;
1097                case CWIID_MESG_MOTIONPLUS:
1098                        cwiid_motionplus(&mesg_array[i].motionplus_mesg);
1099                        break;
1100                case CWIID_MESG_ERROR:
1101                        menuDisconnect_activate();
1102                        break;
1103                default:
1104                        break;
1105                }
1106        }
1107        gdk_flush();
1108        gdk_threads_leave();
1109}
1110
1111void cwiid_btn(struct cwiid_btn_mesg *mesg)
1112{
1113        gtk_widget_modify_bg(evUp, GTK_STATE_NORMAL,
1114            (mesg->buttons & CWIID_BTN_UP) ? &btn_on : &btn_off);
1115        gtk_widget_modify_bg(evDown, GTK_STATE_NORMAL,
1116            (mesg->buttons & CWIID_BTN_DOWN) ? &btn_on : &btn_off);
1117        gtk_widget_modify_bg(evLeft, GTK_STATE_NORMAL,
1118            (mesg->buttons & CWIID_BTN_LEFT) ? &btn_on : &btn_off);
1119        gtk_widget_modify_bg(evRight, GTK_STATE_NORMAL,
1120            (mesg->buttons & CWIID_BTN_RIGHT) ? &btn_on : &btn_off);
1121        gtk_widget_modify_bg(evA, GTK_STATE_NORMAL,
1122            (mesg->buttons & CWIID_BTN_A) ? &btn_on : &btn_off);
1123        gtk_widget_modify_bg(evB, GTK_STATE_NORMAL,
1124            (mesg->buttons & CWIID_BTN_B) ? &btn_on : &btn_off);
1125        gtk_widget_modify_bg(evMinus, GTK_STATE_NORMAL,
1126            (mesg->buttons & CWIID_BTN_MINUS) ? &btn_on : &btn_off);
1127        gtk_widget_modify_bg(evPlus, GTK_STATE_NORMAL,
1128            (mesg->buttons & CWIID_BTN_PLUS) ? &btn_on : &btn_off);
1129        gtk_widget_modify_bg(evHome, GTK_STATE_NORMAL,
1130            (mesg->buttons & CWIID_BTN_HOME) ? &btn_on : &btn_off);
1131        gtk_widget_modify_bg(ev1, GTK_STATE_NORMAL,
1132            (mesg->buttons & CWIID_BTN_1) ? &btn_on : &btn_off);
1133        gtk_widget_modify_bg(ev2, GTK_STATE_NORMAL,
1134            (mesg->buttons & CWIID_BTN_2) ? &btn_on : &btn_off);
1135}
1136
1137#define LBLVAL_LEN 6
1138void cwiid_acc(struct cwiid_acc_mesg *mesg)
1139{
1140        static gchar str[LBLVAL_LEN];
1141        double a_x, a_y, a_z, a;
1142        double roll, pitch;
1143       
1144        if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(chkAcc))) {
1145                g_snprintf(str, LBLVAL_LEN, "%X", mesg->acc[CWIID_X]);
1146                gtk_label_set_text(GTK_LABEL(lblAccXVal), str);
1147                gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(progAccX),
1148                                              (double)mesg->acc[CWIID_X]/0xFF);
1149                g_snprintf(str, LBLVAL_LEN, "%X", mesg->acc[CWIID_Y]);
1150                gtk_label_set_text(GTK_LABEL(lblAccYVal), str);
1151                gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(progAccY),
1152                                              (double)mesg->acc[CWIID_Y]/0xFF);
1153                g_snprintf(str, LBLVAL_LEN, "%X", mesg->acc[CWIID_Z]);
1154                gtk_label_set_text(GTK_LABEL(lblAccZVal), str);
1155                gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(progAccZ),
1156                                              (double)mesg->acc[CWIID_Z]/0xFF);
1157
1158                a_x = ((double)mesg->acc[CWIID_X] - wm_cal.zero[CWIID_X]) /
1159                      (wm_cal.one[CWIID_X] - wm_cal.zero[CWIID_X]);
1160                a_y = ((double)mesg->acc[CWIID_Y] - wm_cal.zero[CWIID_Y]) /
1161                      (wm_cal.one[CWIID_Y] - wm_cal.zero[CWIID_Y]);
1162                a_z = ((double)mesg->acc[CWIID_Z] - wm_cal.zero[CWIID_Z]) /
1163                      (wm_cal.one[CWIID_Z] - wm_cal.zero[CWIID_Z]);
1164                a = sqrt(pow(a_x,2)+pow(a_y,2)+pow(a_z,2));
1165
1166                roll = atan(a_x/a_z);
1167                if (a_z <= 0.0) {
1168                        roll += PI * ((a_x > 0.0) ? 1 : -1);
1169                }
1170                roll *= -1;
1171
1172                pitch = atan(a_y/a_z*cos(roll));
1173
1174                g_snprintf(str, LBLVAL_LEN, "%.2f", a);
1175                gtk_label_set_text(GTK_LABEL(lblAccVal), str);
1176                g_snprintf(str, LBLVAL_LEN, "%.2f", roll);
1177                gtk_label_set_text(GTK_LABEL(lblRollVal), str);
1178                g_snprintf(str, LBLVAL_LEN, "%.2f", pitch);
1179                gtk_label_set_text(GTK_LABEL(lblPitchVal), str);
1180        }
1181}
1182
1183void cwiid_ir(struct cwiid_ir_mesg *mesg)
1184{
1185        if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(chkIR))) {
1186                /* memcpy(&ir_data, mesg, sizeof(struct cwiid_ir_mesg)); */
1187                ir_data = *mesg;
1188                gtk_widget_queue_draw(drawIR);
1189        }
1190}
1191
1192void cwiid_nunchuk(struct cwiid_nunchuk_mesg *mesg)
1193{
1194        static gchar str[LBLVAL_LEN];
1195        double a_x, a_y, a_z, a;
1196        double roll, pitch;
1197       
1198        if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(chkExt))) {
1199                gtk_widget_modify_bg(evNCC, GTK_STATE_NORMAL,
1200                    (mesg->buttons & CWIID_NUNCHUK_BTN_C) ? &btn_on : &btn_off);
1201                gtk_widget_modify_bg(evNCZ, GTK_STATE_NORMAL,
1202                    (mesg->buttons & CWIID_NUNCHUK_BTN_Z) ? &btn_on : &btn_off);
1203
1204                nc_stick.valid = 1;
1205                nc_stick.x = mesg->stick[CWIID_X];
1206                nc_stick.y = mesg->stick[CWIID_Y];
1207                gtk_widget_queue_draw(drawNCStick);
1208
1209                g_snprintf(str, LBLVAL_LEN, "%X", mesg->acc[CWIID_X]);
1210                gtk_label_set_text(GTK_LABEL(lblNCAccXVal), str);
1211                gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(progNCAccX),
1212                                              (double)mesg->acc[CWIID_X]/0xFF);
1213                g_snprintf(str, LBLVAL_LEN, "%X", mesg->acc[CWIID_Y]);
1214                gtk_label_set_text(GTK_LABEL(lblNCAccYVal), str);
1215                gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(progNCAccY),
1216                                              (double)mesg->acc[CWIID_Y]/0xFF);
1217                g_snprintf(str, LBLVAL_LEN, "%X", mesg->acc[CWIID_Z]);
1218                gtk_label_set_text(GTK_LABEL(lblNCAccZVal), str);
1219                gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(progNCAccZ),
1220                                              (double)mesg->acc[CWIID_Z]/0xFF);
1221
1222                /* TODO: get nunchuk calibration */
1223                a_x = ((double)mesg->acc[CWIID_X] - nc_cal.zero[CWIID_X]) /
1224                      (nc_cal.one[CWIID_X] - nc_cal.zero[CWIID_X]);
1225                a_y = ((double)mesg->acc[CWIID_Y] - nc_cal.zero[CWIID_Y]) /
1226                      (nc_cal.one[CWIID_Y] - nc_cal.zero[CWIID_Y]);
1227                a_z = ((double)mesg->acc[CWIID_Z] - nc_cal.zero[CWIID_Z]) /
1228                      (nc_cal.one[CWIID_Z] - nc_cal.zero[CWIID_Z]);
1229                a = sqrt(pow(a_x,2)+pow(a_y,2)+pow(a_z,2));
1230                roll = atan(a_x/a_z);
1231                if (a_z <= 0.0) {
1232                        roll += PI * ((a_x > 0.0) ? 1 : -1);
1233                }
1234                roll *= -1;
1235
1236                pitch = atan(a_y/a_z*cos(roll));
1237
1238                g_snprintf(str, LBLVAL_LEN, "%.2f", a);
1239                gtk_label_set_text(GTK_LABEL(lblNCAccVal), str);
1240                g_snprintf(str, LBLVAL_LEN, "%.2f", roll);
1241                gtk_label_set_text(GTK_LABEL(lblNCRollVal), str);
1242                g_snprintf(str, LBLVAL_LEN, "%.2f", pitch);
1243                gtk_label_set_text(GTK_LABEL(lblNCPitchVal), str);
1244        }
1245}
1246
1247void cwiid_classic(struct cwiid_classic_mesg *mesg)
1248{
1249        static gchar str[LBLVAL_LEN];
1250
1251        if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(chkExt))) {
1252                gtk_widget_modify_bg(evCCUp, GTK_STATE_NORMAL,
1253                    (mesg->buttons & CWIID_CLASSIC_BTN_UP) ? &btn_on : &btn_off);
1254                gtk_widget_modify_bg(evCCDown, GTK_STATE_NORMAL,
1255                    (mesg->buttons & CWIID_CLASSIC_BTN_DOWN) ? &btn_on : &btn_off);
1256                gtk_widget_modify_bg(evCCLeft, GTK_STATE_NORMAL,
1257                    (mesg->buttons & CWIID_CLASSIC_BTN_LEFT) ? &btn_on : &btn_off);
1258                gtk_widget_modify_bg(evCCRight, GTK_STATE_NORMAL,
1259                    (mesg->buttons & CWIID_CLASSIC_BTN_RIGHT) ? &btn_on : &btn_off);
1260                gtk_widget_modify_bg(evCCMinus, GTK_STATE_NORMAL,
1261                    (mesg->buttons & CWIID_CLASSIC_BTN_MINUS) ? &btn_on : &btn_off);
1262                gtk_widget_modify_bg(evCCPlus, GTK_STATE_NORMAL,
1263                    (mesg->buttons & CWIID_CLASSIC_BTN_PLUS) ? &btn_on : &btn_off);
1264                gtk_widget_modify_bg(evCCHome, GTK_STATE_NORMAL,
1265                    (mesg->buttons & CWIID_CLASSIC_BTN_HOME) ? &btn_on : &btn_off);
1266                gtk_widget_modify_bg(evCCA, GTK_STATE_NORMAL,
1267                    (mesg->buttons & CWIID_CLASSIC_BTN_A) ? &btn_on : &btn_off);
1268                gtk_widget_modify_bg(evCCB, GTK_STATE_NORMAL,
1269                    (mesg->buttons & CWIID_CLASSIC_BTN_B) ? &btn_on : &btn_off);
1270                gtk_widget_modify_bg(evCCX, GTK_STATE_NORMAL,
1271                    (mesg->buttons & CWIID_CLASSIC_BTN_X) ? &btn_on : &btn_off);
1272                gtk_widget_modify_bg(evCCY, GTK_STATE_NORMAL,
1273                    (mesg->buttons & CWIID_CLASSIC_BTN_Y) ? &btn_on : &btn_off);
1274                gtk_widget_modify_bg(evCCZL, GTK_STATE_NORMAL,
1275                    (mesg->buttons & CWIID_CLASSIC_BTN_ZL) ? &btn_on : &btn_off);
1276                gtk_widget_modify_bg(evCCZR, GTK_STATE_NORMAL,
1277                    (mesg->buttons & CWIID_CLASSIC_BTN_ZR) ? &btn_on : &btn_off);
1278
1279                cc_l_stick.valid = 1;
1280                cc_l_stick.x = mesg->l_stick[CWIID_X];
1281                cc_l_stick.y = mesg->l_stick[CWIID_Y];
1282                gtk_widget_queue_draw(drawCCLStick);
1283
1284                cc_r_stick.valid = 1;
1285                cc_r_stick.x = mesg->r_stick[CWIID_X];
1286                cc_r_stick.y = mesg->r_stick[CWIID_Y];
1287                gtk_widget_queue_draw(drawCCRStick);
1288               
1289                g_snprintf(str, LBLVAL_LEN, "%X", mesg->l);
1290                gtk_label_set_text(GTK_LABEL(lblCCLVal), str);
1291                gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(progCCL),
1292                                              (double)mesg->l/CWIID_CLASSIC_LR_MAX);
1293                gtk_widget_modify_bg(evCCL, GTK_STATE_NORMAL,
1294                    (mesg->buttons & CWIID_CLASSIC_BTN_L) ? &btn_on : &btn_off);
1295                g_snprintf(str, LBLVAL_LEN, "%X", mesg->r);
1296                gtk_label_set_text(GTK_LABEL(lblCCRVal), str);
1297                gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(progCCR),
1298                                              (double)mesg->r/CWIID_CLASSIC_LR_MAX);
1299                gtk_widget_modify_bg(evCCR, GTK_STATE_NORMAL,
1300                    (mesg->buttons & CWIID_CLASSIC_BTN_R) ? &btn_on : &btn_off);
1301        }
1302}
1303
1304void cwiid_motionplus(struct cwiid_motionplus_mesg *mesg)
1305{
1306        static gchar str[LBLVAL_LEN];
1307       
1308        if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(chkExt))) {
1309                gtk_widget_modify_bg(evMPPhiSlow, GTK_STATE_NORMAL,
1310                    (mesg->low_speed[CWIID_PHI]) ? &btn_on : &btn_off);
1311                gtk_widget_modify_bg(evMPThetaSlow, GTK_STATE_NORMAL,
1312                    (mesg->low_speed[CWIID_THETA]) ? &btn_on : &btn_off);
1313                gtk_widget_modify_bg(evMPPsiSlow, GTK_STATE_NORMAL,
1314                    (mesg->low_speed[CWIID_PSI]) ? &btn_on : &btn_off);
1315
1316                g_snprintf(str, LBLVAL_LEN, "%X", mesg->angle_rate[CWIID_PHI]);
1317                gtk_label_set_text(GTK_LABEL(lblMPPhiVal), str);
1318                gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(progMPPhi),
1319                                              (double)mesg->angle_rate[CWIID_PHI]/0x4000);
1320                g_snprintf(str, LBLVAL_LEN, "%X", mesg->angle_rate[CWIID_THETA]);
1321                gtk_label_set_text(GTK_LABEL(lblMPThetaVal), str);
1322                gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(progMPTheta),
1323                                              (double)mesg->angle_rate[CWIID_THETA]/0x4000);
1324                g_snprintf(str, LBLVAL_LEN, "%X", mesg->angle_rate[CWIID_PSI]);
1325                gtk_label_set_text(GTK_LABEL(lblMPPsiVal), str);
1326                gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(progMPPsi),
1327                                              (double)mesg->angle_rate[CWIID_PSI]/0x4000);
1328        }
1329}
Note: See TracBrowser for help on using the browser.