comparison plugins/crazychat/cc_features.c @ 11218:ed017b9c532d

[gaim-migrate @ 13350] crazychat commit, first one. committer: Tailor Script <tailor@pidgin.im>
author Charlie Stockman <chuckleberry>
date Tue, 09 Aug 2005 07:10:23 +0000
parents
children
comparison
equal deleted inserted replaced
11217:f854402837ba 11218:ed017b9c532d
1 #include <assert.h>
2 #include <GL/gl.h>
3 #include <GL/glu.h>
4 #include "cc_interface.h"
5 #include "crazychat.h"
6
7 #include "Utilities.h"
8 #include "QTUtilities.h"
9 #include "camdata.h"
10 #include "camproc.h"
11 #include "util.h"
12 #include <unistd.h>
13
14
15 #ifdef __APPLE_CC__
16 #include <Carbon/Carbon.h>
17 #else
18 #include <Carbon.h>
19 #endif
20
21 /* temporarily including for development testing */
22 #include "cc_gtk_gl.h"
23
24 /* hard coding the webcam dimensions: BAD, but we're not probing hardware yet */
25
26 #define WEBCAM_X 644 /* webcam's x dim */
27 #define WEBCAM_Y 480 /* webcam's y dim */
28
29 /* default webcam timer callback delay */
30 #define WEBCAM_CALLBACK_DELAY 40 /* in ms */
31
32 int x_click, y_click;
33 int mode_change=0;
34
35 struct input_instance input_data;
36
37 /* move this to input_instance eventually */
38 /*
39 UInt32 colorBuf[WEBCAM_Y][WEBCAM_X];
40 */
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);
47
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 )
55 */
56 static gboolean config_wrapper(GtkWidget *widget, GdkEventConfigure *event,
57 void *data);
58
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
65 */
66 static gboolean mydraw(GtkWidget *widget, GdkEventExpose *event,
67 void *data);
68
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
73 */
74 static gboolean webcam_cb(struct input_instance *instance);
75
76 /**
77 * Init window code, adding our click callback.
78 * @param widget the window we clicked in
79 * @param instance webcam input instance data
80 */
81 static void init_cb(GtkWidget *widget, struct input_instance *instance);
82
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
89 */
90 static gboolean click_cb(GtkWidget *widget, GdkEventButton *event,
91 struct input_instance *instance);
92
93 /**
94 * Button callback
95 * @param button the button we clicked on
96 * @param instance input instance data
97 */
98 static void button_cb(GtkWidget *button, struct input_instance *instance);
99
100 /**
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
104 */
105 static void destroy_cb(GtkWidget *widget, struct crazychat *cc);
106
107 /**
108 * Set feature material.
109 * @param entry model selector combo box entry
110 * @param material pointer to material we're setting
111 */
112 static void material_set(GtkWidget *entry, guint8 *material);
113
114 struct input_instance *init_input(struct crazychat *cc)
115 {
116
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);
153
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);
157
158 GtkWidget *model_combo = gtk_combo_new();
159 GList *glist = NULL;
160
161 glist = g_list_append(glist, "Dog");
162 glist = g_list_append(glist, "Shark");
163 gtk_combo_set_popdown_strings(GTK_COMBO(model_combo), glist);
164 g_list_free(glist);
165 //gtk_combo_box_set_column_span_column(GTK_COMBO(model_combo),
166 // 10);
167 gtk_box_pack_start(GTK_BOX(hbox), model_combo, TRUE, TRUE, 0);
168 gtk_widget_show(model_combo);
169 instance->model = model_combo;
170
171 GtkWidget *head_material_combo = gtk_combo_new();
172 glist = NULL;
173 glist = g_list_append(glist, "Red");
174 glist = g_list_append(glist, "Dark Brown");
175 glist = g_list_append(glist, "Light Brown");
176 glist = g_list_append(glist, "White");
177 glist = g_list_append(glist, "Green");
178 glist = g_list_append(glist, "Black");
179 gtk_combo_set_popdown_strings(GTK_COMBO(head_material_combo), glist);
180 g_list_free(glist);
181 //gtk_combo_box_set_column_span_column(GTK_COMBO(head_material_combo),
182 // 10);
183 gtk_box_pack_start(GTK_BOX(hbox), head_material_combo, TRUE, TRUE, 0);
184 gtk_widget_show(head_material_combo);
185 instance->head = head_material_combo;
186
187 GtkWidget *appendage_material_combo = gtk_combo_new();
188 glist = NULL;
189 glist = g_list_append(glist, "Red");
190 glist = g_list_append(glist, "Dark Brown");
191 glist = g_list_append(glist, "Light Brown");
192 glist = g_list_append(glist, "White");
193 glist = g_list_append(glist, "Green");
194 glist = g_list_append(glist, "Black");
195 gtk_combo_set_popdown_strings(GTK_COMBO(appendage_material_combo),
196 glist);
197 g_list_free(glist);
198 //gtk_combo_box_set_column_span_column(GTK_COMBO(appendage_material_combo), 10);
199 gtk_box_pack_start(GTK_BOX(hbox), appendage_material_combo,
200 TRUE, TRUE, 0);
201 gtk_widget_show(appendage_material_combo);
202 instance->appendage = appendage_material_combo;
203
204 hbox = gtk_hbox_new(TRUE, 0);
205 gtk_box_pack_start(GTK_BOX(ret.vbox), hbox, FALSE, FALSE, 0);
206 gtk_widget_show(hbox);
207
208 GtkWidget *lids_material_combo = gtk_combo_new();
209 glist = NULL;
210 glist = g_list_append(glist, "Red");
211 glist = g_list_append(glist, "Dark Brown");
212 glist = g_list_append(glist, "Light Brown");
213 glist = g_list_append(glist, "White");
214 glist = g_list_append(glist, "Green");
215 glist = g_list_append(glist, "Black");
216 gtk_combo_set_popdown_strings(GTK_COMBO(lids_material_combo), glist);
217 g_list_free(glist);
218 //gtk_combo_box_set_column_span_column(GTK_COMBO(lids_material_combo), 10);
219 gtk_box_pack_start(GTK_BOX(hbox), lids_material_combo, TRUE, TRUE, 0);
220 gtk_widget_show(lids_material_combo);
221 instance->lid = lids_material_combo;
222
223 GtkWidget *left_iris_material_combo = gtk_combo_new();
224 glist = NULL;
225 glist = g_list_append(glist, "Red");
226 glist = g_list_append(glist, "Dark Brown");
227 glist = g_list_append(glist, "Light Brown");
228 glist = g_list_append(glist, "White");
229 glist = g_list_append(glist, "Green");
230 glist = g_list_append(glist, "Black");
231 gtk_combo_set_popdown_strings(GTK_COMBO(left_iris_material_combo),
232 glist);
233 g_list_free(glist);
234 //gtk_combo_box_set_column_span_column(GTK_COMBO(left_iris_material_combo), 10);
235 gtk_box_pack_start(GTK_BOX(hbox), left_iris_material_combo,
236 TRUE, TRUE, 0);
237 gtk_widget_show(left_iris_material_combo);
238 instance->left_iris = left_iris_material_combo;
239
240 /*
241 GtkWidget *right_iris_material_combo = gtk_combo_new();
242 glist = NULL;
243 glist = g_list_append(glist, "Red");
244 glist = g_list_append(glist, "Dark Brown");
245 glist = g_list_append(glist, "Light Brown");
246 glist = g_list_append(glist, "White");
247 glist = g_list_append(glist, "Green");
248 glist = g_list_append(glist, "Black");
249 gtk_combo_set_popdown_strings(GTK_COMBO(right_iris_material_combo),
250 glist);
251 g_list_free(glist);
252 //gtk_combo_box_set_column_span_column(GTK_COMBO(right_iris_material_combo), 10);
253 gtk_box_pack_start(GTK_BOX(hbox), right_iris_material_combo,
254 TRUE, TRUE, 0);
255 gtk_widget_show(right_iris_material_combo);
256 instance->right_iris = right_iris_material_combo;
257 */
258 gtk_widget_add_events(ret.draw_area, GDK_BUTTON_PRESS_MASK);
259 g_signal_connect(G_OBJECT(ret.draw_area), "button_press_event",
260 G_CALLBACK(click_cb), instance);
261 g_signal_connect(G_OBJECT(ret.window), "destroy",
262 G_CALLBACK(destroy_cb), cc);
263 // gtk_widget_set_size_request(window, 640, 480);
264 gtk_window_set_default_size(GTK_WINDOW(ret.window),320,300);
265
266
267 GdkGeometry hints;
268 hints.max_width = 640;
269 hints.max_height = 480;
270
271 gtk_window_set_geometry_hints (GTK_WINDOW(ret.window),
272 NULL,
273 &hints,
274 GDK_HINT_MAX_SIZE);
275 gtk_widget_show(ret.window);
276 return instance;
277 }
278
279 static gboolean webcam_cb(struct input_instance *instance)
280 {
281 assert(instance);
282 QueryCam();
283 return TRUE;
284 }
285
286 static void *facefind(void *data)
287 {
288 fprintf(stderr, "waiting\n");
289 getchar();
290 fprintf(stderr,"got you");
291 detection_mode=1;
292 return;
293 }
294
295 void destroy_input(struct input_instance *instance)
296 {
297 extern filter_bank *bank;
298 assert(instance);
299 Filter_Destroy(bank);
300 g_source_remove(instance->timer_id);
301 Die();
302 ExitMovies();
303 }
304
305 static gboolean config_wrapper(GtkWidget *widget, GdkEventConfigure *event,
306 void *data)
307 {
308
309
310 GdkGLContext *glcontext = gtk_widget_get_gl_context(widget);
311 GdkGLDrawable *gldrawable = gtk_widget_get_gl_drawable(widget);
312
313 GLfloat w = widget->allocation.width;
314 GLfloat h = widget->allocation.height;
315 GLfloat aspect;
316
317 // fprintf(stderr,"Homicide %f %f %d\n", w,h,draw_mode);
318
319 if (draw_mode==1){
320 // fprintf(stderr, "Bad place to be- actually not so bad\n");
321 return configure(widget, event, data);
322 }
323
324 /*** OpenGL BEGIN ***/
325 if (!gdk_gl_drawable_gl_begin(gldrawable, glcontext))
326 return FALSE;
327
328
329 /* Undo all of the Model lighting here*/
330
331 // glDisable(GL_LIGHTING);
332 glDisable(GL_DEPTH_TEST);
333 // glDisable(GL_CULL_FACE);
334 // glDisable(GL_LIGHT0);
335 // glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
336 /* */
337
338
339 glViewport(0,-(h/14),w*2,h*2);
340
341 glMatrixMode(GL_PROJECTION);
342 glLoadIdentity();
343 gluOrtho2D(0,0,640,640);
344 glRasterPos2i(0,0);
345 glPixelZoom(-w/(1*640),(-h/(1*480)));
346 glMatrixMode(GL_MODELVIEW);
347 glLoadIdentity();
348
349
350
351
352 gdk_gl_drawable_gl_end(gldrawable);
353 /*** OpenGL END ***/
354
355 return TRUE;
356 }
357
358 static gboolean mydraw(GtkWidget *widget, GdkEventExpose *event,
359 void *data)
360 {
361 GdkGLContext *glcontext = gtk_widget_get_gl_context (widget);
362 GdkGLDrawable *gldrawable = gtk_widget_get_gl_drawable (widget);
363 struct input_instance *instance = (struct input_instance*)data;
364 unsigned int *boo;
365 struct cc_features *features = &instance->face;
366
367 char *string = gtk_entry_get_text(GTK_COMBO(instance->model)->entry);
368 if (!strcmp(string, "Dog")) {
369 features->kind = 0;
370 } else if (!strcmp(string, "Shark")) {
371 features->kind = 1;
372 }
373
374 material_set(GTK_ENTRY(GTK_COMBO(instance->head)->entry),
375 &features->head_color);
376 material_set(GTK_ENTRY(GTK_COMBO(instance->appendage)->entry),
377 &features->appendage_color);
378 material_set(GTK_ENTRY(GTK_COMBO(instance->lid)->entry),
379 &features->lid_color);
380 material_set(GTK_ENTRY(GTK_COMBO(instance->left_iris)->entry),
381 &features->left_iris_color);
382 material_set(GTK_ENTRY(GTK_COMBO(instance->left_iris)->entry),
383 &features->right_iris_color);
384
385 if (easter_count>0) {
386 easter_count--;
387 } else {
388 instance->face.mode = 0;
389 }
390
391 if (mode_change>0){
392 mode_change--;
393 config_wrapper(widget, event, data);
394 }
395
396 if (draw_mode==1){
397 instance->output.my_output=LOCAL;
398 return draw(widget,event,&instance->output);
399 }
400
401
402 boo = (unsigned int*)colorBuf;
403
404 assert(instance);
405 assert(gtk_widget_is_gl_capable(widget));
406
407 /*** OpenGL BEGIN ***/
408
409 if (!gdk_gl_drawable_gl_begin(gldrawable, glcontext)) {
410 // fprintf(stderr, "We're fucked this time.\n");
411 return FALSE;
412 }
413
414 glClearColor(0.0, 0.0, 0.0, 0.0);
415 glClear(GL_COLOR_BUFFER_BIT);
416
417 glDrawPixels(WEBCAM_X, WEBCAM_Y-70, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, boo);
418
419 if (gdk_gl_drawable_is_double_buffered(gldrawable))
420 gdk_gl_drawable_swap_buffers(gldrawable);
421 else
422 glFlush();
423
424 gdk_gl_drawable_gl_end(gldrawable);
425
426 /*** OpenGL END ***/
427
428 return TRUE;
429 }
430
431 static void init_cb(GtkWidget *widget, struct input_instance *instance)
432 {
433 setupDrawlists(LOCAL);
434 // fprintf(stderr,"init_cb\n");
435 }
436
437 static gboolean click_cb(GtkWidget *widget, GdkEventButton *event,
438 struct input_instance *instance)
439 {
440
441 GLfloat w = widget->allocation.width;
442 GLfloat h = widget->allocation.height;
443 GLfloat aspect;
444
445 if (draw_mode==1) {
446 switch (event->button) {
447 case 1:
448 Debug("F U!\n");
449 instance->face.mode = 1;
450 easter_count = 5;
451 break;
452 case 3:
453 Debug("should never get here\n");
454 instance->face.mode = 2;
455 easter_count = 5;
456 break;
457 default:
458 instance->face.mode = 0;
459 break;
460 }
461 return FALSE;
462 }
463
464 x_click=(event->x*(640/w));
465 x_click=640-x_click;
466 y_click=(event->y-(h/14))*(480/(h-(h/14)));
467 detection_mode=1;
468 //Debug("@@@ x:%d y:%d\n", x_click, y_click);
469
470 gtk_label_set_text(instance->label,
471 "Put on the box, then press confirm.");
472 if (x_click <= 10) x_click=10;
473 if (x_click >= WEBCAM_X-10) x_click=WEBCAM_X-60;
474 if (y_click <= 10) y_click=10;
475 if (y_click >= WEBCAM_Y-10) y_click=WEBCAM_Y-60;
476
477 return FALSE;
478 }
479
480 static void button_cb(GtkWidget *button, struct input_instance *instance)
481 {
482 if (!draw_mode) { /* transition to face mode */
483 if (detection_mode == 0) { /* ignore confirm if no calibrate */
484 return;
485 }
486 setupLighting(instance->widget);
487 mode_change = 1;
488 gtk_button_set_label(GTK_BUTTON(button), "Calibrate");
489 gtk_label_set_label(instance->label,
490 "If things get too crazy, click Calibrate.");
491 } else { /* transition to calibration mode */
492 gtk_label_set_label(instance->label, "Click your face");
493 mode_change = 2;
494 gtk_button_set_label(GTK_BUTTON(button), "Confirm");
495 }
496 draw_mode = !draw_mode;
497 }
498
499 static void destroy_cb(GtkWidget *widget, struct crazychat *cc)
500 {
501 cc->features_state = 0;
502 destroy_input(cc->input_data);
503 cc->input_data = NULL;
504 }
505
506 static void material_set(GtkWidget *entry, guint8 *material)
507 {
508 char *string = gtk_entry_get_text(GTK_ENTRY(entry));
509 if (!strcmp(string, "Red")) {
510 *material = 0;
511 } else if (!strcmp(string, "Dark Brown")) {
512 *material = 1;
513 } else if (!strcmp(string, "Light Brown")) {
514 *material = 2;
515 } else if (!strcmp(string, "White")) {
516 *material = 3;
517 } else if (!strcmp(string, "Green")) {
518 *material = 4;
519 } else if (!strcmp(string, "Black")) {
520 *material = 5;
521 }
522 }