diff 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
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/crazychat/cc_features.c	Tue Aug 09 07:10:23 2005 +0000
@@ -0,0 +1,522 @@
+#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);
+
+	GtkWidget *model_combo = gtk_combo_new();
+	GList *glist = NULL;
+
+	glist = g_list_append(glist, "Dog");
+	glist = g_list_append(glist, "Shark");
+	gtk_combo_set_popdown_strings(GTK_COMBO(model_combo), glist);
+	g_list_free(glist);
+	//gtk_combo_box_set_column_span_column(GTK_COMBO(model_combo),
+	//		10);
+	gtk_box_pack_start(GTK_BOX(hbox), model_combo, TRUE, TRUE, 0);
+	gtk_widget_show(model_combo);
+	instance->model = model_combo;
+
+	GtkWidget *head_material_combo = gtk_combo_new();
+	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");
+	gtk_combo_set_popdown_strings(GTK_COMBO(head_material_combo), 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), head_material_combo, TRUE, TRUE, 0);
+	gtk_widget_show(head_material_combo);
+	instance->head = head_material_combo;
+
+	GtkWidget *appendage_material_combo = gtk_combo_new();
+	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");
+	gtk_combo_set_popdown_strings(GTK_COMBO(appendage_material_combo),
+			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), appendage_material_combo,
+			TRUE, TRUE, 0);
+	gtk_widget_show(appendage_material_combo);
+	instance->appendage = appendage_material_combo;
+
+	hbox = gtk_hbox_new(TRUE, 0);
+	gtk_box_pack_start(GTK_BOX(ret.vbox), hbox, FALSE, FALSE, 0);
+	gtk_widget_show(hbox);
+	
+	GtkWidget *lids_material_combo = gtk_combo_new();
+	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");
+	gtk_combo_set_popdown_strings(GTK_COMBO(lids_material_combo), 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), lids_material_combo, TRUE, TRUE, 0);
+	gtk_widget_show(lids_material_combo);
+	instance->lid = lids_material_combo;
+
+	GtkWidget *left_iris_material_combo = gtk_combo_new();
+	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");
+	gtk_combo_set_popdown_strings(GTK_COMBO(left_iris_material_combo),
+			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), left_iris_material_combo,
+			TRUE, TRUE, 0);
+	gtk_widget_show(left_iris_material_combo);
+	instance->left_iris = left_iris_material_combo;
+
+	/*
+	GtkWidget *right_iris_material_combo = gtk_combo_new();
+	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");
+	gtk_combo_set_popdown_strings(GTK_COMBO(right_iris_material_combo),
+			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), right_iris_material_combo,
+			TRUE, TRUE, 0);
+	gtk_widget_show(right_iris_material_combo);
+	instance->right_iris = right_iris_material_combo;
+*/
+	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;
+	}
+}