Mercurial > pidgin.yaz
view pidgin/plugins/crazychat/cc_features.c @ 29846:414886d7a51c
propagate from branch 'im.pidgin.pidgin' (head d6650bbce66004cf205e9f60ef96626783db72e8)
to branch 'im.pidgin.cpw.rekkanoryo.icqxstatus' (head 4491e1af4a9262cd67501541c84475c417386ced)
author | Richard Laager <rlaager@wiktel.com> |
---|---|
date | Wed, 26 Nov 2008 22:14:34 +0000 |
parents | a2b4eac83902 |
children | a8cc50c2279f |
line wrap: on
line source
#include <assert.h> #include <GL/gl.h> #include <GL/glu.h> #include "cc_interface.h" #include "crazychat.h" #include "Utilities.h" #include "QTUtilities.h" #include "camdata.h" #include "camproc.h" #include "util.h" #include <unistd.h> #ifdef __APPLE_CC__ #include <Carbon/Carbon.h> #else #include <Carbon.h> #endif /* temporarily including for development testing */ #include "cc_gtk_gl.h" /* hard coding the webcam dimensions: BAD, but we're not probing hardware yet */ #define WEBCAM_X 644 /* webcam's x dim */ #define WEBCAM_Y 480 /* webcam's y dim */ /* default webcam timer callback delay */ #define WEBCAM_CALLBACK_DELAY 40 /* in ms */ int x_click, y_click; int mode_change=0; struct input_instance input_data; /* move this to input_instance eventually */ /* UInt32 colorBuf[WEBCAM_Y][WEBCAM_X]; */ unsigned int (*colorBuf)[640]; int detection_mode=0; int draw_mode=0; //0=pixels, 1=face int easter_count; static void *kickstart(void *data); static void *facefind(void *data); /** * Resets the OpenGL viewport stuff on widget reconfiguration (resize, * reposition) * @param widget widget that got reconfigured * @param event the configuration event * @param data unused * @return TRUE ( i don't know what FALSE would do ) */ static gboolean config_wrapper(GtkWidget *widget, GdkEventConfigure *event, void *data); /** * Debug features test. Draws pixels directly to the frame buffer. * @param widget widget that we're drawing * @param event the draw event * @param data array of pixels * @return DUNNO */ static gboolean mydraw(GtkWidget *widget, GdkEventExpose *event, void *data); /** * Periodically querys the webcam for more data. * @param instance webcam input instance data * @return TRUE to stop other handler, FALSE to continue */ static gboolean webcam_cb(struct input_instance *instance); /** * Init window code, adding our click callback. * @param widget the window we clicked in * @param instance webcam input instance data */ static void init_cb(GtkWidget *widget, struct input_instance *instance); /** * Click callback * @param widget the window we clicked in * @param event the button click event structure * @param instance input instance data * @return TRUE to stop other handler, FALSE to continue */ static gboolean click_cb(GtkWidget *widget, GdkEventButton *event, struct input_instance *instance); /** * Button callback * @param button the button we clicked on * @param instance input instance data */ static void button_cb(GtkWidget *button, struct input_instance *instance); /** * Destroy callback. Called when the input processing window is destroyed. * @param widget the window we clicked in * @param cc crazychat global data structure */ static void destroy_cb(GtkWidget *widget, struct crazychat *cc); /** * Set feature material. * @param entry model selector combo box entry * @param material pointer to material we're setting */ static void material_set(GtkWidget *entry, guint8 *material); struct input_instance *init_input(struct crazychat *cc) { /*pthread_t userinput_t; // should we put this in a nicer wrapper?*/ struct draw_info *info; struct input_instance *instance; info = (struct draw_info*)malloc(sizeof(*info)); assert(info); memset(info, 0, sizeof(*info)); info->timeout = TRUE; info->delay_ms = DEFAULT_FRAME_DELAY; info->data = &input_data; instance = (struct input_instance*)info->data; memset(instance, 0, sizeof(*instance)); instance->output.features = &instance->face; EnterMovies(); filter_bank *bank; bank = Filter_Initialize(); assert(CamProc(instance, bank) == noErr); // change this prototype-> no windows instance->timer_id = g_timeout_add(WEBCAM_CALLBACK_DELAY, (GSourceFunc)webcam_cb, instance); /* THREAD_CREATE(&userinput_t, facefind, instance); // is this being created correctly?*/ struct window_box ret; cc_new_gl_window(init_cb, config_wrapper, mydraw, info, &ret); instance->widget = ret.window; gtk_window_set_title(GTK_WINDOW(ret.window), "Local User"); instance->box = ret.vbox; GtkWidget *label = gtk_label_new("Click your face"); instance->label = label; gtk_box_pack_start(GTK_BOX(ret.vbox), label, FALSE, FALSE, 0); gtk_box_reorder_child(GTK_BOX(ret.vbox), label, 0); gtk_widget_show(label); GtkWidget *button = gtk_button_new_with_label("Confirm"); gtk_box_pack_start(GTK_BOX(ret.vbox), button, FALSE, FALSE, 0); g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(button_cb), instance); instance->button = button; gtk_widget_show(button); GtkWidget *hbox = gtk_hbox_new(TRUE, 0); gtk_box_pack_start(GTK_BOX(ret.vbox), hbox, FALSE, FALSE, 0); gtk_widget_show(hbox); GList *glist = NULL; glist = g_list_append(glist, "Dog"); glist = g_list_append(glist, "Shark"); instance->model = pidgin_text_combo_box_entry_new(NULL, glist); g_list_free(glist); //gtk_combo_box_set_column_span_column(GTK_COMBO(model_combo), // 10); gtk_box_pack_start(GTK_BOX(hbox), instance->model, TRUE, TRUE, 0); gtk_widget_show(instance->model); glist = NULL; glist = g_list_append(glist, "Red"); glist = g_list_append(glist, "Dark Brown"); glist = g_list_append(glist, "Light Brown"); glist = g_list_append(glist, "White"); glist = g_list_append(glist, "Green"); glist = g_list_append(glist, "Black"); instance->head = pidgin_text_combo_box_entry_new(NULL, glist); g_list_free(glist); //gtk_combo_box_set_column_span_column(GTK_COMBO(head_material_combo), // 10); gtk_box_pack_start(GTK_BOX(hbox), instance->head, TRUE, TRUE, 0); gtk_widget_show(instance->head); glist = NULL; glist = g_list_append(glist, "Red"); glist = g_list_append(glist, "Dark Brown"); glist = g_list_append(glist, "Light Brown"); glist = g_list_append(glist, "White"); glist = g_list_append(glist, "Green"); glist = g_list_append(glist, "Black"); instance->appendage = pidgin_text_combo_box_entry_new(NULL, glist); g_list_free(glist); //gtk_combo_box_set_column_span_column(GTK_COMBO(appendage_material_combo), 10); gtk_box_pack_start(GTK_BOX(hbox), instance->appendage, TRUE, TRUE, 0); gtk_widget_show(instance->appendage); hbox = gtk_hbox_new(TRUE, 0); gtk_box_pack_start(GTK_BOX(ret.vbox), hbox, FALSE, FALSE, 0); gtk_widget_show(hbox); glist = NULL; glist = g_list_append(glist, "Red"); glist = g_list_append(glist, "Dark Brown"); glist = g_list_append(glist, "Light Brown"); glist = g_list_append(glist, "White"); glist = g_list_append(glist, "Green"); glist = g_list_append(glist, "Black"); instance->lid = pidgin_text_combo_box_entry_new(NULL, glist); g_list_free(glist); //gtk_combo_box_set_column_span_column(GTK_COMBO(lids_material_combo), 10); gtk_box_pack_start(GTK_BOX(hbox), instance->lid, TRUE, TRUE, 0); gtk_widget_show(instance->lid); glist = NULL; glist = g_list_append(glist, "Red"); glist = g_list_append(glist, "Dark Brown"); glist = g_list_append(glist, "Light Brown"); glist = g_list_append(glist, "White"); glist = g_list_append(glist, "Green"); glist = g_list_append(glist, "Black"); instance->left_iris = pidgin_text_combo_box_entry_new(NULL, glist); g_list_free(glist); //gtk_combo_box_set_column_span_column(GTK_COMBO(left_iris_material_combo), 10); gtk_box_pack_start(GTK_BOX(hbox), instance->left_iris, TRUE, TRUE, 0); gtk_widget_show(instance->left_iris); /* glist = NULL; glist = g_list_append(glist, "Red"); glist = g_list_append(glist, "Dark Brown"); glist = g_list_append(glist, "Light Brown"); glist = g_list_append(glist, "White"); glist = g_list_append(glist, "Green"); glist = g_list_append(glist, "Black"); instance->right_iris = pidgin_text_combo_box_entry_new(NULL, glist); g_list_free(glist); //gtk_combo_box_set_column_span_column(GTK_COMBO(right_iris_material_combo), 10); gtk_box_pack_start(GTK_BOX(hbox), instance->right_iris, TRUE, TRUE, 0); gtk_widget_show(instance->right_iris); */ gtk_widget_add_events(ret.draw_area, GDK_BUTTON_PRESS_MASK); g_signal_connect(G_OBJECT(ret.draw_area), "button_press_event", G_CALLBACK(click_cb), instance); g_signal_connect(G_OBJECT(ret.window), "destroy", G_CALLBACK(destroy_cb), cc); // gtk_widget_set_size_request(window, 640, 480); gtk_window_set_default_size(GTK_WINDOW(ret.window),320,300); GdkGeometry hints; hints.max_width = 640; hints.max_height = 480; gtk_window_set_geometry_hints (GTK_WINDOW(ret.window), NULL, &hints, GDK_HINT_MAX_SIZE); gtk_widget_show(ret.window); return instance; } static gboolean webcam_cb(struct input_instance *instance) { assert(instance); QueryCam(); return TRUE; } static void *facefind(void *data) { fprintf(stderr, "waiting\n"); getchar(); fprintf(stderr,"got you"); detection_mode=1; return; } void destroy_input(struct input_instance *instance) { extern filter_bank *bank; assert(instance); Filter_Destroy(bank); g_source_remove(instance->timer_id); Die(); ExitMovies(); } static gboolean config_wrapper(GtkWidget *widget, GdkEventConfigure *event, void *data) { GdkGLContext *glcontext = gtk_widget_get_gl_context(widget); GdkGLDrawable *gldrawable = gtk_widget_get_gl_drawable(widget); GLfloat w = widget->allocation.width; GLfloat h = widget->allocation.height; GLfloat aspect; // fprintf(stderr,"Homicide %f %f %d\n", w,h,draw_mode); if (draw_mode==1){ // fprintf(stderr, "Bad place to be- actually not so bad\n"); return configure(widget, event, data); } /*** OpenGL BEGIN ***/ if (!gdk_gl_drawable_gl_begin(gldrawable, glcontext)) return FALSE; /* Undo all of the Model lighting here*/ // glDisable(GL_LIGHTING); glDisable(GL_DEPTH_TEST); // glDisable(GL_CULL_FACE); // glDisable(GL_LIGHT0); // glClearColor(1.0f, 1.0f, 1.0f, 1.0f); /* */ glViewport(0,-(h/14),w*2,h*2); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluOrtho2D(0,0,640,640); glRasterPos2i(0,0); glPixelZoom(-w/(1*640),(-h/(1*480))); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); gdk_gl_drawable_gl_end(gldrawable); /*** OpenGL END ***/ return TRUE; } static gboolean mydraw(GtkWidget *widget, GdkEventExpose *event, void *data) { GdkGLContext *glcontext = gtk_widget_get_gl_context (widget); GdkGLDrawable *gldrawable = gtk_widget_get_gl_drawable (widget); struct input_instance *instance = (struct input_instance*)data; unsigned int *boo; struct cc_features *features = &instance->face; char *string = gtk_entry_get_text(GTK_COMBO(instance->model)->entry); if (!strcmp(string, "Dog")) { features->kind = 0; } else if (!strcmp(string, "Shark")) { features->kind = 1; } material_set(GTK_ENTRY(GTK_COMBO(instance->head)->entry), &features->head_color); material_set(GTK_ENTRY(GTK_COMBO(instance->appendage)->entry), &features->appendage_color); material_set(GTK_ENTRY(GTK_COMBO(instance->lid)->entry), &features->lid_color); material_set(GTK_ENTRY(GTK_COMBO(instance->left_iris)->entry), &features->left_iris_color); material_set(GTK_ENTRY(GTK_COMBO(instance->left_iris)->entry), &features->right_iris_color); if (easter_count>0) { easter_count--; } else { instance->face.mode = 0; } if (mode_change>0){ mode_change--; config_wrapper(widget, event, data); } if (draw_mode==1){ instance->output.my_output=LOCAL; return draw(widget,event,&instance->output); } boo = (unsigned int*)colorBuf; assert(instance); assert(gtk_widget_is_gl_capable(widget)); /*** OpenGL BEGIN ***/ if (!gdk_gl_drawable_gl_begin(gldrawable, glcontext)) { // fprintf(stderr, "We're fucked this time.\n"); return FALSE; } glClearColor(0.0, 0.0, 0.0, 0.0); glClear(GL_COLOR_BUFFER_BIT); glDrawPixels(WEBCAM_X, WEBCAM_Y-70, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, boo); if (gdk_gl_drawable_is_double_buffered(gldrawable)) gdk_gl_drawable_swap_buffers(gldrawable); else glFlush(); gdk_gl_drawable_gl_end(gldrawable); /*** OpenGL END ***/ return TRUE; } static void init_cb(GtkWidget *widget, struct input_instance *instance) { // setupDrawlists(LOCAL); // fprintf(stderr,"init_cb\n"); } static gboolean click_cb(GtkWidget *widget, GdkEventButton *event, struct input_instance *instance) { GLfloat w = widget->allocation.width; GLfloat h = widget->allocation.height; GLfloat aspect; if (draw_mode==1) { switch (event->button) { case 1: Debug("F U!\n"); instance->face.mode = 1; easter_count = 5; break; case 3: Debug("should never get here\n"); instance->face.mode = 2; easter_count = 5; break; default: instance->face.mode = 0; break; } return FALSE; } x_click=(event->x*(640/w)); x_click=640-x_click; y_click=(event->y-(h/14))*(480/(h-(h/14))); detection_mode=1; //Debug("@@@ x:%d y:%d\n", x_click, y_click); gtk_label_set_text(instance->label, "Put on the box, then press confirm."); if (x_click <= 10) x_click=10; if (x_click >= WEBCAM_X-10) x_click=WEBCAM_X-60; if (y_click <= 10) y_click=10; if (y_click >= WEBCAM_Y-10) y_click=WEBCAM_Y-60; return FALSE; } static void button_cb(GtkWidget *button, struct input_instance *instance) { if (!draw_mode) { /* transition to face mode */ if (detection_mode == 0) { /* ignore confirm if no calibrate */ return; } setupLighting(instance->widget); mode_change = 1; gtk_button_set_label(GTK_BUTTON(button), "Calibrate"); gtk_label_set_label(instance->label, "If things get too crazy, click Calibrate."); } else { /* transition to calibration mode */ gtk_label_set_label(instance->label, "Click your face"); mode_change = 2; gtk_button_set_label(GTK_BUTTON(button), "Confirm"); } draw_mode = !draw_mode; } static void destroy_cb(GtkWidget *widget, struct crazychat *cc) { cc->features_state = 0; destroy_input(cc->input_data); cc->input_data = NULL; } static void material_set(GtkWidget *entry, guint8 *material) { char *string = gtk_entry_get_text(GTK_ENTRY(entry)); if (!strcmp(string, "Red")) { *material = 0; } else if (!strcmp(string, "Dark Brown")) { *material = 1; } else if (!strcmp(string, "Light Brown")) { *material = 2; } else if (!strcmp(string, "White")) { *material = 3; } else if (!strcmp(string, "Green")) { *material = 4; } else if (!strcmp(string, "Black")) { *material = 5; } }