Mercurial > pidgin.yaz
comparison gtk/plugins/crazychat/cc_features.c @ 14191:009db0b357b5
This is a hand-crafted commit to migrate across subversion revisions
16854:16861, due to some vagaries of the way the original renames were
done. Witness that monotone can do in one revision what svn had to
spread across several.
author | Ethan Blanton <elb@pidgin.im> |
---|---|
date | Sat, 16 Dec 2006 04:59:55 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
14190:366be2ce35a7 | 14191:009db0b357b5 |
---|---|
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 } |