Пример #1
0
int main(int argc, char *argv[])
{
    SAPO_BROKER_T *sb;
    BrokerMessage *m;

    sb = sb_new(HOST, PORT, TYPE);

    if (!sb) {
        printf("%s", sb_error());
        exit(-1);
    }

    if (sb_connect(sb) != SB_OK) {
        printf("%s", sb_error());
        exit(-1);
    }

    if (sb_subscribe(sb, EQUEUE_VIRTUAL_QUEUE, TOPIC) != SB_OK) {
        printf("%s", sb_error());
        exit(-1);
    }

    while ((m = sb_receive(sb)) != NULL) {
        printf("%s\n", m->payload);
		sb_send_ack( sb, m);
		sb_free_message(m);
	}

    printf("Exiting: %s\n", sb_error());
}
Пример #2
0
int ui_get_machine_move ()
{
	byte *move;
	if (player_to_play == HUMAN || ui_stopped)
		return FALSE;
	if (!opt_infile)
	{
		move = move_fread_ack (move_fin);
		if (!move)
		{
			sb_error ("Couldn't make move\n", TRUE);
			ui_stopped = TRUE;
			sb_update ();
			return FALSE;
		}
		if (opt_logfile)
			move_fwrite (move, opt_logfile);
	}
	else 		// file mode
	{
		//TODO: should communicate the move to the engine
		move = move_fread (opt_infile);
		if (opt_logfile)
			move_fwrite (move, opt_logfile);
	}
	board_apply_refresh (move, NULL);
	if (!game_single_player)
		cur_pos.player = (cur_pos.player == WHITE ? BLACK : WHITE);
	cur_pos.num_moves ++;
	sound_play (SOUND_MACHINE_MOVE);
	ui_check_who_won ();
	sb_update ();
	ui_send_make_move ();
	return FALSE;
}
Пример #3
0
gboolean prefs_load_scores (gchar *name)
{
	gchar *scorefile;
	FILE *in;
	char linebuf[128];
	int i;
	gamename = name;
	if (!prefs_first_time ()) return FALSE;
	scorefile = g_strdup_printf ("%s/%s/%s", getenv("HOME"), 
			".gtkboard/scores", name);
	in = fopen (scorefile, "r");
	if (!in) 
	{ 
		g_free (scorefile);		
		num_highscores = 0;
		return FALSE;
	}
	for (i=0; !feof (in) && i < MAX_HIGHSCORES;)
	{
		gchar **realline;
		gchar ** score_fields;
		/*
		if (fscanf (in, "%[^$]$%[^$]$%d$%d\n", 
				scores[i].name, scores[i].score, 
				&scores[i].time, &scores[i].date) == EOF)*/
		//scanf is buggy!!! - %[] shouldn't strip leading whitespace but does
		if (!fgets (linebuf, 128, in))
			break;
		realline = g_strsplit (linebuf, "#", -1);
		score_fields = g_strsplit (realline[0], "$", -1);
		if (!score_fields[0] || !score_fields[1])
		{
			g_strfreev (realline);
			g_strfreev (score_fields);
			continue;
		}
		if (!score_fields[2] || !score_fields[3])
		{
			sb_error ("Error loading scores file", FALSE);
			g_strfreev (realline);
			g_strfreev (score_fields);
			break;
		}
		strncpy (scores[i].name, score_fields[0], 31);
		strncpy (scores[i].score, score_fields[1], 31);
		scores[i].time = atoi(score_fields[2]);
		scores[i].date = atoi(score_fields[3]);
		g_strfreev (realline);
		g_strfreev (score_fields);
		i++;
	}
	num_highscores = i;
	fclose (in);
	g_free (scorefile);
	return TRUE;
}
Пример #4
0
static int
init_image_storage() {
	DIR *dir;
	struct dirent d, *pd;
	int pfxlen = strlen(PHOTO_PREFIX);
	int maxseq = 0;
	char path[128];
	//
	if(sb_conf_readv("photo_dir", path, sizeof(path)) != NULL) {
		photo_dir = strdup(path);
	}
	//
	if((dir = opendir(photo_dir)) == NULL) {
		sb_error("video encoder: cannot open image storage (%s).\n", photo_dir);
		return -1;
	}
	while(readdir_r(dir, &d, &pd) == 0) {
		char *ptr;
		int seq = 0;
		if(pd == NULL)
			break;
		if(strncmp(d.d_name, PHOTO_PREFIX, pfxlen) != 0)
			continue;
		ptr = d.d_name + pfxlen;
		while(*ptr && isdigit(*ptr)) {
			seq *= 10;
			seq += *ptr - '0';
			ptr++;
		}
		if(*ptr++ != '.')
			continue;
		if(strcmp(ptr, PHOTO_EXT) != 0)
			continue;
		if(seq > maxseq)
			maxseq = seq;
	}
	closedir(dir);
	//
	photo_seq = maxseq + 1;
	sb_error("video encoder: photo image stored from sequenuce #%d\n", photo_seq);
	return 0;
}
Пример #5
0
static int
vencoder_reconfigure(int iid, sb_ioctl_reconfigure_t *reconf) {
	if(vencoder_initialized == 0) {
		sb_error("video encoder: reconfigure failed - not initialized?\n");
		return SB_IOCTL_ERR_NOTINITIALIZED;
	}
	if(reconf->bitrateKbps > 0
	|| reconf->framerate_n > 0) {
		unsigned int framerate = 0;
		if(reconf->framerate_n > 0 && reconf->framerate_d > 0) {
			framerate = (((reconf->framerate_d-1) & 0x0ffff)<<16) | (reconf->framerate_n & 0x0ffff);
		} else if(reconf->framerate_n > 0) {
			framerate = reconf->framerate_n & 0x0ffff;
		}
		if(omx_streamer_reconfigure(&omxe[reconf->id], reconf->bitrateKbps, framerate, reconf->width, reconf->height) < 0) {
			sb_error("video encoder: reconfigure failed.\n");
			return -1;
		}
	}
	return 0;
}
Пример #6
0
static int
vencoder_start(void *arg) {
	int iid;
#ifdef SAVEFILE
	if(fout == NULL) {
		fout = fopen(SAVEFILE, "wb");
	}
#endif
	if(vencoder_started != 0)
		return 0;
	vencoder_started = 1;
	for(iid = 0; iid < 1/*video_source_channels()*/; iid++) {
		if(pthread_create(&vencoder_tid[iid], NULL, vencoder_threadproc, NULL) != 0) {
			vencoder_started = 0;
			sb_error("video encoder: create thread failed.\n");
			return -1;
		}
	}
	sb_error("video encdoer: all started (%d)\n", iid);
	return 0;
}
Пример #7
0
static int
vencoder_stop(void *arg) {
	int iid;
	void *ignored;
#ifdef SAVEFILE
	if(fout != NULL) {
		fout = NULL;
	}
#endif
	if(vencoder_started == 0)
		return 0;
	vencoder_started = 0;
	for(iid = 0; iid < 1/*video_source_channels()*/; iid++) {
		pthread_join(vencoder_tid[iid], &ignored);
	}
	sb_error("video encdoer: all stopped (%d)\n", iid);
	return 0;
}
Пример #8
0
static int
vencoder_deinit(void *arg) {
	int iid;
	for(iid = 0; iid < 1/*video_source_channels()*/; iid++) {
		if(_sps[iid] != NULL)	free(_sps[iid]);
		if(_pps[iid] != NULL)	free(_pps[iid]);
		omx_streamer_deinit(&omxe[iid]);
	}
	//
	bzero(_sps, sizeof(_sps));
	bzero(_pps, sizeof(_pps));
	bzero(_spslen, sizeof(_spslen));
	bzero(_ppslen, sizeof(_ppslen));
	bzero(vencoder_tid, sizeof(vencoder_tid));
	//
	vencoder_initialized = 0;
	sb_error("video encoder: OMX deinitialized.\n");
	return 0;
}
Пример #9
0
static int
vencoder_ioctl(int command, int argsize, void *arg) {
	int ret = 0;
	sb_ioctl_buffer_t *buf = (sb_ioctl_buffer_t*) arg;
	sb_ioctl_reconfigure_t *reconf = NULL;
	//
	switch(command) {
	case SB_IOCTL_GETSPS:
		if(argsize != sizeof(sb_ioctl_buffer_t))
			return SB_IOCTL_ERR_INVALID_ARGUMENT;
		if((ret = vencoder_get_sps_pps(buf->id)) < 0)
			break;
		if(buf->size < _spslen[buf->id])
			return SB_IOCTL_ERR_BUFFERSIZE;
		buf->size = _spslen[buf->id];
		bcopy(_sps[buf->id], buf->ptr, buf->size);
		break;
	case SB_IOCTL_GETPPS:
		if(argsize != sizeof(sb_ioctl_buffer_t))
			return SB_IOCTL_ERR_INVALID_ARGUMENT;
		if((ret = vencoder_get_sps_pps(buf->id)) < 0)
			break;
		if(buf->size < _spslen[buf->id])
			return SB_IOCTL_ERR_BUFFERSIZE;
		buf->size = _ppslen[buf->id];
		bcopy(_pps[buf->id], buf->ptr, buf->size);
		break;
	case SB_IOCTL_RECONFIGURE:
		reconf = (sb_ioctl_reconfigure_t*) arg;
		if(argsize != sizeof(sb_ioctl_reconfigure_t))
			return SB_IOCTL_ERR_INVALID_ARGUMENT;
		if(vencoder_reconfigure(buf->id, reconf) < 0) {
			sb_error("video encoder: reconfigure to bitrate to %dKbps failed\n", reconf->bitrateKbps);
			ret = -1;
		}
		break;
	default:
		ret = SB_IOCTL_ERR_NOTSUPPORTED;
		break;
	}
	return ret;
}
Пример #10
0
/**
 * Handle controller system messages.
 *
 * @param [in] msg Pointer to the message.
 * @return 1 if the message is a known control message, or 0 if it is not.
 */
int
ctrlsys_handle_message(unsigned char *buf, unsigned int size) {
	ctrlmsg_system_t *msg = (ctrlmsg_system_t*) buf;
	if(msg == NULL)
		return 1;
	if(size < sizeof(ctrlmsg_system_t))
		return 0;
	if(msg->msgtype != CTRL_MSGTYPE_SYSTEM)
		return 0;
	if(msg->subtype > CTRL_MSGSYS_SUBTYPE_MAX) {
		sb_error("system-message: unknown subtype (%02x)\n", msg->subtype);
		return 1;
	}
	if(ctrlsys_handler_list[msg->subtype] == NULL)
		return 1;
	if(ctrlsys_ntoh(msg) != 0)
		return 1;
	ctrlsys_handler_list[msg->subtype](msg);
	return 1;
}
Пример #11
0
static void
camera_control(void *msg, int msglen) {
	sdlmsg_mouse_t *m = (sdlmsg_mouse_t*) msg;
	if(vencoder_initialized == 0)
		return;
	if(msglen != ntohs(m->msgsize)) {
		sb_error("video source: ctrl message length mismatched. (%d != %d)\n",
			msglen, ntohs(m->msgsize));
		return;
	}
	//
	// XXX: all are in char-type, no endian conversion is required
	if(m->msgtype != SDL_EVENT_MSGTYPE_MOUSEKEY)
		return;
	if(m->mousebutton != 1)
		return;
	if(m->is_pressed == 0) {
		// do camera shot: call /usr/bin/raspistill -n -w 2592 -h 1944 -q 95 -e jpg -o $file
		char filename[256];
		char cmd[512];
		struct stat s;
		snprintf(filename, sizeof(filename), "%s/%s%04d.%s",
			photo_dir, PHOTO_PREFIX, photo_seq++, PHOTO_EXT);
		snprintf(cmd, sizeof(cmd),
			"/usr/bin/raspistill -n -w 2592 -h 1944 -q 95 -e jpg -o %s", filename);
		if(omx_streamer_suspend(&omxe[0]) < 0) {
			sb_error("video encoder: suspend failed.\n");
			return;
		}
		//
		sb_error("video encoder: taking camera shot ... (%s)\n", cmd);
		system(cmd);
		if(stat(filename, &s) == 0 && s.st_size > 0) {
			sb_error("video encoder: done (%s: %d bytes saved).\n", filename, s.st_size);
		} else {
			sb_error("video encoder: camera shot failed.\n");
		}
		//
		if(omx_streamer_resume(&omxe[0]) < 0) {
			sb_error("video encoder: resume failed.\n");
			return;
		}
	}
	return;
}
Пример #12
0
gboolean prefs_save_scores (gchar *name)
{
	gchar *scorefile;
	FILE *out;
	char linebuf[128];
	int i;
	if (!prefs_first_time ()) return FALSE;
	scorefile = g_strdup_printf ("%s/%s/%s", getenv("HOME"), 
			".gtkboard/scores", name);
	out = fopen (scorefile, "w");
	if (!out) 
	{ 
		gchar *tempstr;
		sb_error (tempstr = g_strdup_printf 
				("couldn't write to %s", scorefile),
				FALSE);
		fprintf (stderr, "%s\n", tempstr);
		g_free (tempstr);
		g_free (scorefile);		
		return FALSE;
	}
	fprintf (out, "#This is the gtkboard highscores file for the game %s\n"
			"#The format is: name$score$time taken in ms$date (time (2))\n"
			"#VERSION=0.10.0\n"
			, gamename);
	for (i=0; i < num_highscores; i++)
	{
		fprintf (out, "%s$%s$%d$%d\n", 
				scores[i].name, scores[i].score, 
				scores[i].time, scores[i].date);
	}
	fclose (out);
	g_free (scorefile);
	gamename = NULL;
	return TRUE;
}
Пример #13
0
static int
vencoder_get_sps_pps(int iid) {
	const unsigned char *s, *p;
	int ssize, psize;
	//
	if(vencoder_initialized == 0) {
		sb_error("video encoder: get SPS/PPS failed - not initialized?\n");
		return SB_IOCTL_ERR_NOTINITIALIZED;
	}
	if(_sps[iid] != NULL)
		return 0;
	if((s = omx_streamer_get_h264_sps(&omxe[iid], &ssize)) == NULL) {
		sb_error("video encoder: get SPS failed.\n");
		return SB_IOCTL_ERR_NOTFOUND;
	}
	if((p = omx_streamer_get_h264_pps(&omxe[iid], &psize)) == NULL) {
		sb_error("video encoder: get PPS failed.\n");
		return SB_IOCTL_ERR_NOTFOUND;
	}
	if((_sps[iid] = (char*) malloc(ssize)) == NULL) {
		sb_error("video encoder: get SPS/PPS failed - alloc sps failed.\n");
		return SB_IOCTL_ERR_NOMEM;
	}
	if((_pps[iid] = (char*) malloc(psize)) == NULL) {
		free(_sps[iid]);
		_sps[iid] = NULL;
		sb_error("video encoder: get SPS/PPS failed - alloc pps failed.\n");
		return SB_IOCTL_ERR_NOMEM;
	}
	bcopy(s, _sps[iid], ssize);
	bcopy(p, _pps[iid], psize);
	_spslen[iid] = ssize;
	_ppslen[iid] = psize;
	//
	sb_error("video encoder: sps=%d; pps=%d\n", _spslen[iid], _ppslen[iid]);
	return 0;
}
Пример #14
0
/// TODO
static void *
vencoder_threadproc(void *arg) {
	// arg is pointer to source pipename
	int cid;
	struct RTSPConf *rtspconf = NULL;
	//
	long long basePts = -1LL, newpts = 0LL, pts = -1LL, ptsSync = 0LL;
	pthread_mutex_t condMutex = PTHREAD_MUTEX_INITIALIZER;
	pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
	//
	struct timeval pkttv;
	//
	int video_written = 0;
	//
	rtspconf = rtspconf_global();
	cid = 0;
	// start encoding
	if(omx_streamer_start(&omxe[cid]) < 0) {
		sb_error("video encoder: start streamer failed.\n");
		goto video_quit;
	}
	//
	sb_error("video encoding started: tid=%ld.\n", sb_gettid());
	//
	while(vencoder_started != 0 && encoder_running() > 0) {
		//
		AVPacket pkt;
		unsigned char *enc;
		int encsize;
		// handle pts
		if(basePts == -1LL) {
			basePts = omxe[cid].frame_out;
			ptsSync = encoder_pts_sync(rtspconf->video_fps);
			newpts = ptsSync;
		} else {
			newpts = ptsSync + omxe[cid].frame_out - basePts;
		}
		//
		if((enc = omx_streamer_get(&omxe[cid], &encsize)) == NULL) {
			sb_error("video encoder: encode failed.\n");
			break;
		}
		if(encsize == 0)
			continue;
		// pts must be monotonically increasing
		if(newpts > pts) {
			pts = newpts;
		} else {
			pts++;
		}
		// send packet
#ifdef SAVEFILE
		if(fout != NULL)
			fwrite(enc, sizeof(char), encsize, fout);
#endif
#if 0		// XXX: data check
		do {
			unsigned char *ptr, *nextptr;
			int offset, nextoffset, left = encsize;
			sb_error("XXX: %d bytes encoded ---------------\n", encsize);
			if((ptr = sb_find_startcode(enc, enc+encsize, &offset)) != enc) {
				sb_error("XXX: cannot find a start code\n");
				break;
			}
			while(ptr != NULL) {
				int nalsize;
				nextptr = sb_find_startcode(ptr+4, enc+encsize, &nextoffset);
				nalsize = nextptr != NULL ? nextptr-ptr : enc+encsize-ptr;
				sb_error("XXX: nal_t=%d, size=%d\n", ptr[offset] & 0x1f, nalsize);
				ptr = nextptr;
				offset = nextoffset;
			}
		} while(0);
#endif
		pkt.data = enc;
		pkt.size = encsize;
		if(encoder_send_packet("video-encoder", cid, &pkt, pkt.pts, NULL/*&pkttv*/) < 0) {
			goto video_quit;
		}
		if(video_written == 0) {
			video_written = 1;
			sb_error("first video frame written (pts=%lld)\n", pts);
		}
	}
	//
video_quit:
	//
	if(omx_streamer_prepare_stop(&omxe[cid]) < 0) {
		sb_error("streamer: prepare stop failed.\n");
	}
	//
	if(omx_streamer_stop(&omxe[cid]) < 0) {
		sb_error("streamer: start streamer failed.\n");
	}
	//
	sb_error("video encoder: thread terminated (tid=%ld).\n", sb_gettid());
	//
	return NULL;
}
Пример #15
0
static int
vencoder_init(void *arg) {
	int iid, width, height, fps, bitrate, gopsize;
	int vsmode[3];
	char *pipefmt = (char*) arg;
	struct RTSPConf *rtspconf = rtspconf_global();
	omx_streamer_config_t sc;
	//
	if(rtspconf == NULL) {
		sb_error("video encoder: no configuration found\n");
		return -1;
	}
	if(vencoder_initialized != 0)
		return 0;
	//
	iid = 0;
	//
	if(sb_conf_readints("video-source-v4l-mode", vsmode, 3) == 3) {
		sb_error("video encoder: use user config: %d %d %d\n",
				vsmode[0], vsmode[1], vsmode[2]);
		width = vsmode[1];
		height = vsmode[2];
	} else {
		width = 640;
		height = 480;
	}
	if((fps = sb_conf_readint("video-fps")) <= 1) {
		fps = 24;
	}
	if((bitrate = sb_conf_mapreadint("video-specific", "b")) < 1000000) {
		bitrate = 3000000;
	}
	if((gopsize = sb_conf_mapreadint("video-specific", "g")) < 5) {
		gopsize = fps;
	}
	// search for photo seq
	if(init_image_storage() < 0) {
		return -1;
	}
	// register a dummy video source: only once
	if(vsource_initialized == 0) {
		vsource_config_t config;
		bzero(&config, sizeof(config));
		config.curr_width = width;
		config.curr_height = height;
		config.curr_stride = width;
		if(video_source_setup_ex(&config, 1) < 0) {
			sb_error("video encoder: setup dummy source failed (%dx%d)\n", width, height);
			return -1;
		}
		sb_error("video encoder: dummy source configured (%dx%d)\n", width, height);
		vsource_initialized = 1;
	}
	//
	sb_error("video encoder: mode=(ignored) (%dx%d), fps=%d\n",
		width, height, fps);
	// load configs
	bzero(&sc, sizeof(sc));
	sc.camera_sharpness = sb_omx_load_int("omx-camera-sharpness", -100, 100, OSCAM_DEF_SHARPNESS);
	sc.camera_contrast = sb_omx_load_int("omx-camera-contrast", -100, 100, OSCAM_DEF_CONTRAST);
	sc.camera_brightness = sb_omx_load_int("omx-camera-brightness", 0, 100, OSCAM_DEF_BRIGHTNESS);
	sc.camera_saturation = sb_omx_load_int("omx-camera-saturation", -100, 100, OSCAM_DEF_SATURATION);
	sc.camera_ev = sb_omx_load_int("omx-camera-ev", -10, 10, OSCAM_DEF_EXPOSURE_VALUE_COMPENSATION);
	sc.camera_iso = sb_omx_load_int("omx-camera-iso", 100, 800, OSCAM_DEF_EXPOSURE_ISO_SENSITIVITY);
	sc.camera_iso_auto = sb_omx_load_bool("omx-camera-iso-auto", OSCAM_DEF_EXPOSURE_AUTO_SENSITIVITY);
	sc.camera_frame_stabilisation = sb_omx_load_bool("omx-camera-frame-stabilisation", OSCAM_DEF_FRAME_STABILISATION);
	sc.camera_flip_horizon = sb_omx_load_bool("omx-camera-flip-horizon", OSCAM_DEF_FLIP_HORIZONTAL);
	sc.camera_flip_vertical = sb_omx_load_bool("omx-camera-flip-vertical", OSCAM_DEF_FLIP_VERTICAL);
	sc.camera_whitebalance =
		(enum OMX_WHITEBALCONTROLTYPE) sb_omx_load_int("camera-omx-whitebalance", 0, (int) OMX_WhiteBalControlMax, (int) OSCAM_DEF_WHITE_BALANCE_CONTROL);
	sc.camera_filter =
		(enum OMX_IMAGEFILTERTYPE) sb_omx_load_int("camera-omx-filter", (int) OMX_ImageFilterNone, (int) OMX_ImageFilterMax, (int) OSCAM_DEF_IMAGE_FILTER);
	//
	if(omx_streamer_init(&omxe[iid], NULL, width, height, fps, 1, bitrate, gopsize) < 0) {
		sb_error("video encoder: init failed.\n");
		return -1;
	}
	// register a dummy control
	ctrl_server_setreplay(camera_control);
	sb_error("video encoder: dummy control enabled.\n");
	//
	vencoder_initialized = 1;
	sb_error("video encoder: initialized (%d channels).\n", iid+1);
	return 0;
init_failed:
	vencoder_deinit(NULL);
	return -1;
}
Пример #16
0
//! handles mouse clicks as well as key presses
gint board_signal_handler (GtkWidget *widget, GdkEventButton *event, 
		gpointer data)
/* FIXME: clean up this function */
{
	int row, col, pixel_x, pixel_y, type;
	int status = 0;
	byte *move = NULL;
	int *rmove = NULL;
	GtkboardEvent our_event;
	MoveInfo minfo = {NULL, NULL, NULL, NULL, NULL};
	if (!opt_game) return FALSE;
	if (ui_gameover) return FALSE;
	if (event->type == GDK_KEY_PRESS && 
			!(((GdkEventKey *)event)->state & (GDK_CONTROL_MASK | GDK_MOD1_MASK)))
	{
		if (!game_getmove_kb && !game_event_handler) return FALSE;
		if (game_event_handler) 
		{
			our_event.type = GTKBOARD_KEY_PRESS;
			our_event.key = ((GdkEventKey *)event)->keyval;
			status = game_event_handler (&cur_pos, &our_event, &minfo);
			move = minfo.move;
			rmove = minfo.rmove;
		}
		else //(if game_getmove_kb)
			status = game_getmove_kb (&cur_pos, 
				((GdkEventKey *)event)->keyval, &move, &rmove);
	}
	else
	{
		if (event->type == GDK_BUTTON_PRESS || event->type == GDK_BUTTON_RELEASE)
		{
			if (player_to_play != HUMAN)
			{
				sb_message ("Machine's turn", FALSE);
				return FALSE;
			}
			if (!impl_check()) { sb_error ("Not yet implemented", TRUE); 
				return FALSE; }
		}
		if (!game_getmove && !game_event_handler) {return FALSE;}
		board_get_cell (event, &row, &col, &pixel_x, &pixel_y);
		if (!(row >= 0 && row < board_wid)) return FALSE;
		if (!(col >= 0 && col < board_heit)) return FALSE;
		switch (event->type)
		{
			case GDK_BUTTON_PRESS:
				type = GTKBOARD_BUTTON_PRESS; break;
			case GDK_BUTTON_RELEASE:
				type = GTKBOARD_BUTTON_RELEASE; break;
			case GDK_MOTION_NOTIFY:
				type = GTKBOARD_MOTION_NOTIFY; break;
			case GDK_LEAVE_NOTIFY:
				type = GTKBOARD_LEAVE_NOTIFY; break;
			default:
				return FALSE;
		}
		if (game_event_handler)
		{
			our_event.type = type;
			our_event.x = row;
			our_event.y = col;
			our_event.pixel_x = pixel_x;
			our_event.pixel_y = pixel_y;
			status = game_event_handler (&cur_pos, &our_event, &minfo);
			move = minfo.move;
			rmove = minfo.rmove;
		}
		else
			status = game_getmove (&cur_pos, row, col, 
					type, cur_pos.player, &move, &rmove);
		if (status < 0)
		{
			gchar *tmpstr = minfo.help_message ? 
				g_strdup_printf ("Illegal move: %s", minfo.help_message) 
				: g_strdup_printf ("Illegal move");
			sb_error (tmpstr, FALSE);
			g_free (tmpstr);
			sound_play (SOUND_ILLEGAL_MOVE);
		}
	}
	if (status <= 0)
	{
		ui_make_human_move (NULL, rmove);
		if (rmove)
			menu_start_stop_game (NULL, MENU_START_GAME); 
		return FALSE;
	}
	sound_play (SOUND_USER_MOVE);
	menu_start_stop_game (NULL, MENU_START_GAME); 
	ui_make_human_move (move, rmove);
	return FALSE;
}