4 #include "cc_interface.h"
8 #include "QTUtilities.h"
16 #include <Carbon/Carbon.h>
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 */
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];
43 int draw_mode
=0; //0=pixels, 1=face
45 static void *kickstart(void *data
);
46 static void *facefind(void *data
);
49 * Resets the OpenGL viewport stuff on widget reconfiguration (resize,
51 * @param widget widget that got reconfigured
52 * @param event the configuration event
54 * @return TRUE ( i don't know what FALSE would do )
56 static gboolean
config_wrapper(GtkWidget
*widget
, GdkEventConfigure
*event
,
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
66 static gboolean
mydraw(GtkWidget
*widget
, GdkEventExpose
*event
,
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
);
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
);
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
);
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
));
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
;
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
,
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
),
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
);
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
);
163 //gtk_combo_box_set_column_span_column(GTK_COMBO(model_combo),
165 gtk_box_pack_start(GTK_BOX(hbox
), instance
->model
, TRUE
, TRUE
, 0);
166 gtk_widget_show(instance
->model
);
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
);
177 //gtk_combo_box_set_column_span_column(GTK_COMBO(head_material_combo),
179 gtk_box_pack_start(GTK_BOX(hbox
), instance
->head
, TRUE
, TRUE
, 0);
180 gtk_widget_show(instance
->head
);
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
);
191 //gtk_combo_box_set_column_span_column(GTK_COMBO(appendage_material_combo), 10);
192 gtk_box_pack_start(GTK_BOX(hbox
), instance
->appendage
,
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
);
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
);
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
);
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
);
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
);
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);
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);
250 hints
.max_width
= 640;
251 hints
.max_height
= 480;
253 gtk_window_set_geometry_hints (GTK_WINDOW(ret
.window
),
257 gtk_widget_show(ret
.window
);
261 static gboolean
webcam_cb(struct input_instance
*instance
)
268 static void *facefind(void *data
)
270 fprintf(stderr
, "waiting\n");
272 fprintf(stderr
,"got you");
277 void destroy_input(struct input_instance
*instance
)
279 extern filter_bank
*bank
;
281 Filter_Destroy(bank
);
282 g_source_remove(instance
->timer_id
);
287 static gboolean
config_wrapper(GtkWidget
*widget
, GdkEventConfigure
*event
,
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
;
299 // fprintf(stderr,"Homicide %f %f %d\n", w,h,draw_mode);
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
))
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);
321 glViewport(0,-(h
/14),w
*2,h
*2);
323 glMatrixMode(GL_PROJECTION
);
325 gluOrtho2D(0,0,640,640);
327 glPixelZoom(-w
/(1*640),(-h
/(1*480)));
328 glMatrixMode(GL_MODELVIEW
);
334 gdk_gl_drawable_gl_end(gldrawable
);
340 static gboolean
mydraw(GtkWidget
*widget
, GdkEventExpose
*event
,
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
;
347 struct cc_features
*features
= &instance
->face
;
349 char *string
= gtk_entry_get_text(GTK_COMBO(instance
->model
)->entry
);
350 if (!strcmp(string
, "Dog")) {
352 } else if (!strcmp(string
, "Shark")) {
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) {
370 instance
->face
.mode
= 0;
375 config_wrapper(widget
, event
, data
);
379 instance
->output
.my_output
=LOCAL
;
380 return draw(widget
,event
,&instance
->output
);
384 boo
= (unsigned int*)colorBuf
;
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");
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
);
406 gdk_gl_drawable_gl_end(gldrawable
);
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
;
428 switch (event
->button
) {
431 instance
->face
.mode
= 1;
435 Debug("should never get here\n");
436 instance
->face
.mode
= 2;
440 instance
->face
.mode
= 0;
446 x_click
=(event
->x
*(640/w
));
448 y_click
=(event
->y
-(h
/14))*(480/(h
-(h
/14)));
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;
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 */
468 setupLighting(instance
->widget
);
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");
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")) {
493 } else if (!strcmp(string
, "Dark Brown")) {
495 } else if (!strcmp(string
, "Light Brown")) {
497 } else if (!strcmp(string
, "White")) {
499 } else if (!strcmp(string
, "Green")) {
501 } else if (!strcmp(string
, "Black")) {