Open an explorer.exe window at the location of the file when clicking
[pidgin-git.git] / pidgin / plugins / crazychat / cc_features.c
blob0b8a800ca6591f930e7fb89605f5a439f13e3c95
1 #include <assert.h>
2 #include <GL/gl.h>
3 #include <GL/glu.h>
4 #include "cc_interface.h"
5 #include "crazychat.h"
7 #include "Utilities.h"
8 #include "QTUtilities.h"
9 #include "camdata.h"
10 #include "camproc.h"
11 #include "util.h"
12 #include <unistd.h>
15 #ifdef __APPLE_CC__
16 #include <Carbon/Carbon.h>
17 #else
18 #include <Carbon.h>
19 #endif
21 /* temporarily including for development testing */
22 #include "cc_gtk_gl.h"
24 /* hard coding the webcam dimensions: BAD, but we're not probing hardware yet */
26 #define WEBCAM_X 644 /* webcam's x dim */
27 #define WEBCAM_Y 480 /* webcam's y dim */
29 /* default webcam timer callback delay */
30 #define WEBCAM_CALLBACK_DELAY 40 /* in ms */
32 int x_click, y_click;
33 int mode_change=0;
35 struct input_instance input_data;
37 /* move this to input_instance eventually */
39 UInt32 colorBuf[WEBCAM_Y][WEBCAM_X];
41 unsigned int (*colorBuf)[640];
42 int detection_mode=0;
43 int draw_mode=0; //0=pixels, 1=face
44 int easter_count;
45 static void *kickstart(void *data);
46 static void *facefind(void *data);
48 /**
49 * Resets the OpenGL viewport stuff on widget reconfiguration (resize,
50 * reposition)
51 * @param widget widget that got reconfigured
52 * @param event the configuration event
53 * @param data unused
54 * @return TRUE ( i don't know what FALSE would do )
56 static gboolean config_wrapper(GtkWidget *widget, GdkEventConfigure *event,
57 void *data);
59 /**
60 * Debug features test. Draws pixels directly to the frame buffer.
61 * @param widget widget that we're drawing
62 * @param event the draw event
63 * @param data array of pixels
64 * @return DUNNO
66 static gboolean mydraw(GtkWidget *widget, GdkEventExpose *event,
67 void *data);
69 /**
70 * Periodically querys the webcam for more data.
71 * @param instance webcam input instance data
72 * @return TRUE to stop other handler, FALSE to continue
74 static gboolean webcam_cb(struct input_instance *instance);
76 /**
77 * Init window code, adding our click callback.
78 * @param widget the window we clicked in
79 * @param instance webcam input instance data
81 static void init_cb(GtkWidget *widget, struct input_instance *instance);
83 /**
84 * Click callback
85 * @param widget the window we clicked in
86 * @param event the button click event structure
87 * @param instance input instance data
88 * @return TRUE to stop other handler, FALSE to continue
90 static gboolean click_cb(GtkWidget *widget, GdkEventButton *event,
91 struct input_instance *instance);
93 /**
94 * Button callback
95 * @param button the button we clicked on
96 * @param instance input instance data
98 static void button_cb(GtkWidget *button, struct input_instance *instance);
101 * Destroy callback. Called when the input processing window is destroyed.
102 * @param widget the window we clicked in
103 * @param cc crazychat global data structure
105 static void destroy_cb(GtkWidget *widget, struct crazychat *cc);
108 * Set feature material.
109 * @param entry model selector combo box entry
110 * @param material pointer to material we're setting
112 static void material_set(GtkWidget *entry, guint8 *material);
114 struct input_instance *init_input(struct crazychat *cc)
117 /*pthread_t userinput_t; // should we put this in a nicer wrapper?*/
118 struct draw_info *info;
119 struct input_instance *instance;
120 info = (struct draw_info*)malloc(sizeof(*info));
121 assert(info);
122 memset(info, 0, sizeof(*info));
123 info->timeout = TRUE;
124 info->delay_ms = DEFAULT_FRAME_DELAY;
125 info->data = &input_data;
126 instance = (struct input_instance*)info->data;
127 memset(instance, 0, sizeof(*instance));
128 instance->output.features = &instance->face;
129 EnterMovies();
130 filter_bank *bank;
131 bank = Filter_Initialize();
132 assert(CamProc(instance, bank) == noErr); // change this prototype-> no windows
133 instance->timer_id = g_timeout_add(WEBCAM_CALLBACK_DELAY,
134 (GSourceFunc)webcam_cb, instance);
135 /* THREAD_CREATE(&userinput_t, facefind, instance); // is this being created correctly?*/
136 struct window_box ret;
137 cc_new_gl_window(init_cb, config_wrapper, mydraw,
138 info, &ret);
139 instance->widget = ret.window;
140 gtk_window_set_title(GTK_WINDOW(ret.window), "Local User");
141 instance->box = ret.vbox;
142 GtkWidget *label = gtk_label_new("Click your face");
143 instance->label = label;
144 gtk_box_pack_start(GTK_BOX(ret.vbox), label, FALSE, FALSE, 0);
145 gtk_box_reorder_child(GTK_BOX(ret.vbox), label, 0);
146 gtk_widget_show(label);
147 GtkWidget *button = gtk_button_new_with_label("Confirm");
148 gtk_box_pack_start(GTK_BOX(ret.vbox), button, FALSE, FALSE, 0);
149 g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(button_cb),
150 instance);
151 instance->button = button;
152 gtk_widget_show(button);
154 GtkWidget *hbox = gtk_hbox_new(TRUE, 0);
155 gtk_box_pack_start(GTK_BOX(ret.vbox), hbox, FALSE, FALSE, 0);
156 gtk_widget_show(hbox);
158 GList *glist = NULL;
159 glist = g_list_append(glist, "Dog");
160 glist = g_list_append(glist, "Shark");
161 instance->model = pidgin_text_combo_box_entry_new(NULL, glist);
162 g_list_free(glist);
163 //gtk_combo_box_set_column_span_column(GTK_COMBO(model_combo),
164 // 10);
165 gtk_box_pack_start(GTK_BOX(hbox), instance->model, TRUE, TRUE, 0);
166 gtk_widget_show(instance->model);
168 glist = NULL;
169 glist = g_list_append(glist, "Red");
170 glist = g_list_append(glist, "Dark Brown");
171 glist = g_list_append(glist, "Light Brown");
172 glist = g_list_append(glist, "White");
173 glist = g_list_append(glist, "Green");
174 glist = g_list_append(glist, "Black");
175 instance->head = pidgin_text_combo_box_entry_new(NULL, glist);
176 g_list_free(glist);
177 //gtk_combo_box_set_column_span_column(GTK_COMBO(head_material_combo),
178 // 10);
179 gtk_box_pack_start(GTK_BOX(hbox), instance->head, TRUE, TRUE, 0);
180 gtk_widget_show(instance->head);
182 glist = NULL;
183 glist = g_list_append(glist, "Red");
184 glist = g_list_append(glist, "Dark Brown");
185 glist = g_list_append(glist, "Light Brown");
186 glist = g_list_append(glist, "White");
187 glist = g_list_append(glist, "Green");
188 glist = g_list_append(glist, "Black");
189 instance->appendage = pidgin_text_combo_box_entry_new(NULL, glist);
190 g_list_free(glist);
191 //gtk_combo_box_set_column_span_column(GTK_COMBO(appendage_material_combo), 10);
192 gtk_box_pack_start(GTK_BOX(hbox), instance->appendage,
193 TRUE, TRUE, 0);
194 gtk_widget_show(instance->appendage);
196 hbox = gtk_hbox_new(TRUE, 0);
197 gtk_box_pack_start(GTK_BOX(ret.vbox), hbox, FALSE, FALSE, 0);
198 gtk_widget_show(hbox);
200 glist = NULL;
201 glist = g_list_append(glist, "Red");
202 glist = g_list_append(glist, "Dark Brown");
203 glist = g_list_append(glist, "Light Brown");
204 glist = g_list_append(glist, "White");
205 glist = g_list_append(glist, "Green");
206 glist = g_list_append(glist, "Black");
207 instance->lid = pidgin_text_combo_box_entry_new(NULL, glist);
208 g_list_free(glist);
209 //gtk_combo_box_set_column_span_column(GTK_COMBO(lids_material_combo), 10);
210 gtk_box_pack_start(GTK_BOX(hbox), instance->lid, TRUE, TRUE, 0);
211 gtk_widget_show(instance->lid);
213 glist = NULL;
214 glist = g_list_append(glist, "Red");
215 glist = g_list_append(glist, "Dark Brown");
216 glist = g_list_append(glist, "Light Brown");
217 glist = g_list_append(glist, "White");
218 glist = g_list_append(glist, "Green");
219 glist = g_list_append(glist, "Black");
220 instance->left_iris = pidgin_text_combo_box_entry_new(NULL, glist);
221 g_list_free(glist);
222 //gtk_combo_box_set_column_span_column(GTK_COMBO(left_iris_material_combo), 10);
223 gtk_box_pack_start(GTK_BOX(hbox), instance->left_iris, TRUE, TRUE, 0);
224 gtk_widget_show(instance->left_iris);
227 glist = NULL;
228 glist = g_list_append(glist, "Red");
229 glist = g_list_append(glist, "Dark Brown");
230 glist = g_list_append(glist, "Light Brown");
231 glist = g_list_append(glist, "White");
232 glist = g_list_append(glist, "Green");
233 glist = g_list_append(glist, "Black");
234 instance->right_iris = pidgin_text_combo_box_entry_new(NULL, glist);
235 g_list_free(glist);
236 //gtk_combo_box_set_column_span_column(GTK_COMBO(right_iris_material_combo), 10);
237 gtk_box_pack_start(GTK_BOX(hbox), instance->right_iris, TRUE, TRUE, 0);
238 gtk_widget_show(instance->right_iris);
240 gtk_widget_add_events(ret.draw_area, GDK_BUTTON_PRESS_MASK);
241 g_signal_connect(G_OBJECT(ret.draw_area), "button_press_event",
242 G_CALLBACK(click_cb), instance);
243 g_signal_connect(G_OBJECT(ret.window), "destroy",
244 G_CALLBACK(destroy_cb), cc);
245 // gtk_widget_set_size_request(window, 640, 480);
246 gtk_window_set_default_size(GTK_WINDOW(ret.window),320,300);
249 GdkGeometry hints;
250 hints.max_width = 640;
251 hints.max_height = 480;
253 gtk_window_set_geometry_hints (GTK_WINDOW(ret.window),
254 NULL,
255 &hints,
256 GDK_HINT_MAX_SIZE);
257 gtk_widget_show(ret.window);
258 return instance;
261 static gboolean webcam_cb(struct input_instance *instance)
263 assert(instance);
264 QueryCam();
265 return TRUE;
268 static void *facefind(void *data)
270 fprintf(stderr, "waiting\n");
271 getchar();
272 fprintf(stderr,"got you");
273 detection_mode=1;
274 return;
277 void destroy_input(struct input_instance *instance)
279 extern filter_bank *bank;
280 assert(instance);
281 Filter_Destroy(bank);
282 g_source_remove(instance->timer_id);
283 Die();
284 ExitMovies();
287 static gboolean config_wrapper(GtkWidget *widget, GdkEventConfigure *event,
288 void *data)
292 GdkGLContext *glcontext = gtk_widget_get_gl_context(widget);
293 GdkGLDrawable *gldrawable = gtk_widget_get_gl_drawable(widget);
295 GLfloat w = widget->allocation.width;
296 GLfloat h = widget->allocation.height;
297 GLfloat aspect;
299 // fprintf(stderr,"Homicide %f %f %d\n", w,h,draw_mode);
301 if (draw_mode==1){
302 // fprintf(stderr, "Bad place to be- actually not so bad\n");
303 return configure(widget, event, data);
306 /*** OpenGL BEGIN ***/
307 if (!gdk_gl_drawable_gl_begin(gldrawable, glcontext))
308 return FALSE;
311 /* Undo all of the Model lighting here*/
313 // glDisable(GL_LIGHTING);
314 glDisable(GL_DEPTH_TEST);
315 // glDisable(GL_CULL_FACE);
316 // glDisable(GL_LIGHT0);
317 // glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
318 /* */
321 glViewport(0,-(h/14),w*2,h*2);
323 glMatrixMode(GL_PROJECTION);
324 glLoadIdentity();
325 gluOrtho2D(0,0,640,640);
326 glRasterPos2i(0,0);
327 glPixelZoom(-w/(1*640),(-h/(1*480)));
328 glMatrixMode(GL_MODELVIEW);
329 glLoadIdentity();
334 gdk_gl_drawable_gl_end(gldrawable);
335 /*** OpenGL END ***/
337 return TRUE;
340 static gboolean mydraw(GtkWidget *widget, GdkEventExpose *event,
341 void *data)
343 GdkGLContext *glcontext = gtk_widget_get_gl_context (widget);
344 GdkGLDrawable *gldrawable = gtk_widget_get_gl_drawable (widget);
345 struct input_instance *instance = (struct input_instance*)data;
346 unsigned int *boo;
347 struct cc_features *features = &instance->face;
349 char *string = gtk_entry_get_text(GTK_COMBO(instance->model)->entry);
350 if (!strcmp(string, "Dog")) {
351 features->kind = 0;
352 } else if (!strcmp(string, "Shark")) {
353 features->kind = 1;
356 material_set(GTK_ENTRY(GTK_COMBO(instance->head)->entry),
357 &features->head_color);
358 material_set(GTK_ENTRY(GTK_COMBO(instance->appendage)->entry),
359 &features->appendage_color);
360 material_set(GTK_ENTRY(GTK_COMBO(instance->lid)->entry),
361 &features->lid_color);
362 material_set(GTK_ENTRY(GTK_COMBO(instance->left_iris)->entry),
363 &features->left_iris_color);
364 material_set(GTK_ENTRY(GTK_COMBO(instance->left_iris)->entry),
365 &features->right_iris_color);
367 if (easter_count>0) {
368 easter_count--;
369 } else {
370 instance->face.mode = 0;
373 if (mode_change>0){
374 mode_change--;
375 config_wrapper(widget, event, data);
378 if (draw_mode==1){
379 instance->output.my_output=LOCAL;
380 return draw(widget,event,&instance->output);
384 boo = (unsigned int*)colorBuf;
386 assert(instance);
387 assert(gtk_widget_is_gl_capable(widget));
389 /*** OpenGL BEGIN ***/
391 if (!gdk_gl_drawable_gl_begin(gldrawable, glcontext)) {
392 // fprintf(stderr, "We're fucked this time.\n");
393 return FALSE;
396 glClearColor(0.0, 0.0, 0.0, 0.0);
397 glClear(GL_COLOR_BUFFER_BIT);
399 glDrawPixels(WEBCAM_X, WEBCAM_Y-70, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, boo);
401 if (gdk_gl_drawable_is_double_buffered(gldrawable))
402 gdk_gl_drawable_swap_buffers(gldrawable);
403 else
404 glFlush();
406 gdk_gl_drawable_gl_end(gldrawable);
408 /*** OpenGL END ***/
410 return TRUE;
413 static void init_cb(GtkWidget *widget, struct input_instance *instance)
415 // setupDrawlists(LOCAL);
416 // fprintf(stderr,"init_cb\n");
419 static gboolean click_cb(GtkWidget *widget, GdkEventButton *event,
420 struct input_instance *instance)
423 GLfloat w = widget->allocation.width;
424 GLfloat h = widget->allocation.height;
425 GLfloat aspect;
427 if (draw_mode==1) {
428 switch (event->button) {
429 case 1:
430 Debug("F U!\n");
431 instance->face.mode = 1;
432 easter_count = 5;
433 break;
434 case 3:
435 Debug("should never get here\n");
436 instance->face.mode = 2;
437 easter_count = 5;
438 break;
439 default:
440 instance->face.mode = 0;
441 break;
443 return FALSE;
446 x_click=(event->x*(640/w));
447 x_click=640-x_click;
448 y_click=(event->y-(h/14))*(480/(h-(h/14)));
449 detection_mode=1;
450 //Debug("@@@ x:%d y:%d\n", x_click, y_click);
452 gtk_label_set_text(instance->label,
453 "Put on the box, then press confirm.");
454 if (x_click <= 10) x_click=10;
455 if (x_click >= WEBCAM_X-10) x_click=WEBCAM_X-60;
456 if (y_click <= 10) y_click=10;
457 if (y_click >= WEBCAM_Y-10) y_click=WEBCAM_Y-60;
459 return FALSE;
462 static void button_cb(GtkWidget *button, struct input_instance *instance)
464 if (!draw_mode) { /* transition to face mode */
465 if (detection_mode == 0) { /* ignore confirm if no calibrate */
466 return;
468 setupLighting(instance->widget);
469 mode_change = 1;
470 gtk_button_set_label(GTK_BUTTON(button), "Calibrate");
471 gtk_label_set_label(instance->label,
472 "If things get too crazy, click Calibrate.");
473 } else { /* transition to calibration mode */
474 gtk_label_set_label(instance->label, "Click your face");
475 mode_change = 2;
476 gtk_button_set_label(GTK_BUTTON(button), "Confirm");
478 draw_mode = !draw_mode;
481 static void destroy_cb(GtkWidget *widget, struct crazychat *cc)
483 cc->features_state = 0;
484 destroy_input(cc->input_data);
485 cc->input_data = NULL;
488 static void material_set(GtkWidget *entry, guint8 *material)
490 char *string = gtk_entry_get_text(GTK_ENTRY(entry));
491 if (!strcmp(string, "Red")) {
492 *material = 0;
493 } else if (!strcmp(string, "Dark Brown")) {
494 *material = 1;
495 } else if (!strcmp(string, "Light Brown")) {
496 *material = 2;
497 } else if (!strcmp(string, "White")) {
498 *material = 3;
499 } else if (!strcmp(string, "Green")) {
500 *material = 4;
501 } else if (!strcmp(string, "Black")) {
502 *material = 5;