int main(void) { cfg_opt_t sub_opts[] = { CFG_BOOL("bool", cfg_false, CFGF_NONE), CFG_STR("string", NULL, CFGF_NONE), CFG_INT("int", 0, CFGF_NONE), CFG_FLOAT("float", 0.0, CFGF_NONE), CFG_END() }; cfg_opt_t opts[] = { CFG_BOOL_LIST("bool", cfg_false, CFGF_NONE), CFG_STR_LIST("string", NULL, CFGF_NONE), CFG_INT_LIST("int", 0, CFGF_NONE), CFG_FLOAT_LIST("float", "0.0", CFGF_NONE), CFG_SEC("sub", sub_opts, CFGF_MULTI | CFGF_TITLE | CFGF_NO_TITLE_DUPES), CFG_END() }; char *cmd = NULL; const char *reply; int res; int i; cfg = cfg_init(opts, CFGF_NONE); for (;;) { printf("cli> "); fflush(stdout); if (cmd) free(cmd); cmd = input_cmd(); if (!cmd) exit(0); res = split_cmd(cmd); if (res < 0) { printf("Parse error\n"); continue; } if (cmdc == 0) continue; for (i = 0; cmds[i].cmd; ++i) { if (strcmp(cmdv[0], cmds[i].cmd)) continue; reply = cmds[i].handler(cmdc, cmdv); if (!reply) exit(0); printf("%s", reply); break; } if (!cmds[i].cmd) printf("Unknown command\n"); } cfg_free(cfg); return 0; }
/****************************************************************************** Description.: Input Value.: Return Value: ******************************************************************************/ void cam_cleanup(void *arg) { static unsigned char first_run=1; if ( !first_run ) { DBG("already cleaned up ressources\n"); return; } first_run = 0; IPRINT("cleaning up ressources allocated by input thread\n"); /* restore behaviour of the LED to auto */ input_cmd(IN_CMD_LED_AUTO, 0); close_v4l2(videoIn); if (videoIn->tmpbuffer != NULL) free(videoIn->tmpbuffer); if (videoIn != NULL) free(videoIn); if (pglobal->buf != NULL) free(pglobal->buf); }
int input_cmd(in_cmd_type cmd, int value) { int res=0; static int pan=0; static int tilt=0; static int pan_tilt_valid=-1; const int one_degree = ONE_DEGREE; IPRINT("received command %d (value: %d) for input plugin\n", cmd, value); if ( cmd != IN_CMD_RESET_PAN_TILT_NO_MUTEX ) pthread_mutex_lock( &controls_mutex ); DBG("pan: %d, tilt: %d, valid: %d\n", pan, tilt, pan_tilt_valid); switch (cmd) { case IN_CMD_HELLO: fprintf(stderr, "Hello from input plugin\n"); break; case IN_CMD_RESET_PAN_TILT: case IN_CMD_RESET_PAN_TILT_NO_MUTEX: DBG("about to set all pan/tilt to default position\n"); DBG("uvcPanTilt(videoIn, 0, 0, 3) != 0 )\n"); pan_tilt_valid = 1; pan = tilt = 0; break; case IN_CMD_PAN_SET: DBG("set pan to %d\n", value); if ( pan_tilt_valid != 1 ) input_cmd(IN_CMD_RESET_PAN_TILT_NO_MUTEX, 0); /* limit pan-value to min and max */ value = MIN(MAX(value*one_degree, MIN_PAN), MAX_PAN); /* calculate the relative degrees to move to the desired absolute pan-value */ if( (res = value - pan) == 0 ) { /* do not move if this would mean to move by 0 degrees */ res = pan; break; } /* move it */ pan = value; DBG("res = uvcPanTilt(videoIn, %d, 0, 0)\n", res); DBG("pan: %d\n", pan); break; case IN_CMD_PAN_PLUS: DBG("pan +\n"); if ( pan_tilt_valid != 1 ) input_cmd(IN_CMD_RESET_PAN_TILT_NO_MUTEX, 0); if ( (MAX_PAN) > (pan+one_degree) ) { pan += one_degree; DBG("res = uvcPanTilt(videoIn, one_degree, 0, 0)\n"); } DBG("pan: %d\n", pan); break; case IN_CMD_PAN_MINUS: DBG("pan -\n"); if ( pan_tilt_valid != 1 ) input_cmd(IN_CMD_RESET_PAN_TILT_NO_MUTEX, 0); if ( (MIN_PAN) < (pan-one_degree) ) { pan -= one_degree; DBG("res = uvcPanTilt(videoIn, -one_degree, 0, 0)\n"); } DBG("pan: %d\n", pan); break; default: DBG("some other value, ignored\n"); } if ( cmd != IN_CMD_RESET_PAN_TILT_NO_MUTEX ) pthread_mutex_unlock( &controls_mutex ); return res; }
/****************************************************************************** Description.: This function initializes the plugin. It parses the commandline- parameter and stores the default and parsed values in the appropriate variables. Input Value.: param contains among others the command-line string Return Value: 0 if everything is fine 1 if "--help" was triggered, in this case the calling programm should stop running and leave. ******************************************************************************/ int input_init(input_parameter *param) { char *argv[MAX_ARGUMENTS]={NULL}, *dev = "/dev/video0", *s; int argc=1, width=640, height=480, fps=5, format=V4L2_PIX_FMT_MJPEG, i; in_cmd_type led = IN_CMD_LED_AUTO; /* initialize the mutes variable */ if( pthread_mutex_init(&controls_mutex, NULL) != 0 ) { IPRINT("could not initialize mutex variable\n"); exit(EXIT_FAILURE); } /* convert the single parameter-string to an array of strings */ argv[0] = INPUT_PLUGIN_NAME; if ( param->parameter_string != NULL && strlen(param->parameter_string) != 0 ) { char *arg=NULL, *saveptr=NULL, *token=NULL; arg=(char *)strdup(param->parameter_string); if ( strchr(arg, ' ') != NULL ) { token=strtok_r(arg, " ", &saveptr); if ( token != NULL ) { argv[argc] = strdup(token); argc++; while ( (token=strtok_r(NULL, " ", &saveptr)) != NULL ) { argv[argc] = strdup(token); argc++; if (argc >= MAX_ARGUMENTS) { IPRINT("ERROR: too many arguments to input plugin\n"); return 1; } } } } } /* show all parameters for DBG purposes */ for (i=0; i<argc; i++) { DBG("argv[%d]=%s\n", i, argv[i]); } /* parse the parameters */ reset_getopt(); while(1) { int option_index = 0, c=0; static struct option long_options[] = \ { {"h", no_argument, 0, 0}, {"help", no_argument, 0, 0}, {"d", required_argument, 0, 0}, {"device", required_argument, 0, 0}, {"r", required_argument, 0, 0}, {"resolution", required_argument, 0, 0}, {"f", required_argument, 0, 0}, {"fps", required_argument, 0, 0}, {"y", no_argument, 0, 0}, {"yuv", no_argument, 0, 0}, {"q", required_argument, 0, 0}, {"quality", required_argument, 0, 0}, {"m", required_argument, 0, 0}, {"minimum_size", required_argument, 0, 0}, {"n", no_argument, 0, 0}, {"no_dynctrl", no_argument, 0, 0}, {"l", required_argument, 0, 0}, {"led", required_argument, 0, 0}, {0, 0, 0, 0} }; /* parsing all parameters according to the list above is sufficent */ c = getopt_long_only(argc, argv, "", long_options, &option_index); /* no more options to parse */ if (c == -1) break; /* unrecognized option */ if (c == '?'){ help(); return 1; } /* dispatch the given options */ switch (option_index) { /* h, help */ case 0: case 1: DBG("case 0,1\n"); help(); return 1; break; /* d, device */ case 2: case 3: DBG("case 2,3\n"); dev = strdup(optarg); break; /* r, resolution */ case 4: case 5: DBG("case 4,5\n"); width = -1; height = -1; /* try to find the resolution in lookup table "resolutions" */ for ( i=0; i < LENGTH_OF(resolutions); i++ ) { if ( strcmp(resolutions[i].string, optarg) == 0 ) { width = resolutions[i].width; height = resolutions[i].height; } } /* done if width and height were set */ if(width != -1 && height != -1) break; /* parse value as decimal value */ width = strtol(optarg, &s, 10); height = strtol(s+1, NULL, 10); break; /* f, fps */ case 6: case 7: DBG("case 6,7\n"); fps=atoi(optarg); break; /* y, yuv */ case 8: case 9: DBG("case 8,9\n"); format = V4L2_PIX_FMT_YUYV; break; /* q, quality */ case 10: case 11: DBG("case 10,11\n"); format = V4L2_PIX_FMT_YUYV; gquality = MIN(MAX(atoi(optarg), 0), 100); break; /* m, minimum_size */ case 12: case 13: DBG("case 12,13\n"); minimum_size = MAX(atoi(optarg), 0); break; /* n, no_dynctrl */ case 14: case 15: DBG("case 14,15\n"); dynctrls = 0; break; /* l, led */ case 16: case 17: DBG("case 16,17\n"); if ( strcmp("on", optarg) == 0 ) { led = IN_CMD_LED_ON; } else if ( strcmp("off", optarg) == 0 ) { led = IN_CMD_LED_OFF; } else if ( strcmp("auto", optarg) == 0 ) { led = IN_CMD_LED_AUTO; } else if ( strcmp("blink", optarg) == 0 ) { led = IN_CMD_LED_BLINK; } break; default: DBG("default case\n"); help(); return 1; } } /* keep a pointer to the global variables */ pglobal = param->global; /* allocate webcam datastructure */ videoIn = malloc(sizeof(struct vdIn)); if ( videoIn == NULL ) { IPRINT("not enough memory for videoIn\n"); exit(EXIT_FAILURE); } memset(videoIn, 0, sizeof(struct vdIn)); /* display the parsed values */ IPRINT("Using V4L2 device.: %s\n", dev); IPRINT("Desired Resolution: %i x %i\n", width, height); IPRINT("Frames Per Second.: %i\n", fps); IPRINT("Format............: %s\n", (format==V4L2_PIX_FMT_YUYV)?"YUV":"MJPEG"); if ( format == V4L2_PIX_FMT_YUYV ) IPRINT("JPEG Quality......: %d\n", gquality); /* open video device and prepare data structure */ if (init_videoIn(videoIn, dev, width, height, fps, format, 1) < 0) { IPRINT("init_VideoIn failed\n"); closelog(); exit(EXIT_FAILURE); } /* * recent linux-uvc driver (revision > ~#125) requires to use dynctrls * for pan/tilt/focus/... * dynctrls must get initialized */ if (dynctrls) initDynCtrls(videoIn->fd); /* * switch the LED according to the command line parameters (if any) */ input_cmd(led, 0); return 0; }
/****************************************************************************** Description.: process commands, allows to set certain runtime configurations and settings like pan/tilt, colors, saturation etc. Input Value.: * cmd specifies the command, a complete list is maintained in the file "input.h" * value is used for commands that make use of a parameter. Return Value: depends in the command, for most cases 0 means no errors and -1 signals an error. This is just rule of thumb, not more! ******************************************************************************/ int input_cmd(in_cmd_type cmd, int value) { int res=0; static int pan=0, tilt=0, pan_tilt_valid=-1; static int focus=-1; const int one_degree = ONE_DEGREE; /* certain commands do not need the mutex */ if ( cmd != IN_CMD_RESET_PAN_TILT_NO_MUTEX ) pthread_mutex_lock( &controls_mutex ); switch (cmd) { case IN_CMD_HELLO: fprintf(stderr, "Hello from input plugin\n"); break; case IN_CMD_RESET: DBG("about to reset all image controls to defaults\n"); res = v4l2ResetControl(videoIn, V4L2_CID_BRIGHTNESS); res |= v4l2ResetControl(videoIn, V4L2_CID_CONTRAST); res |= v4l2ResetControl(videoIn, V4L2_CID_SATURATION); res |= v4l2ResetControl(videoIn, V4L2_CID_GAIN); if ( res != 0 ) res = -1; break; case IN_CMD_RESET_PAN_TILT: case IN_CMD_RESET_PAN_TILT_NO_MUTEX: DBG("about to set pan/tilt to default position\n"); if ( uvcPanTilt(videoIn->fd, 0, 0, 3) != 0 ) { res = -1; break; } pan_tilt_valid = 1; pan = tilt = 0; sleep(4); break; case IN_CMD_PAN_SET: DBG("set pan to %d degrees\n", value); /* in order to calculate absolute positions we must check for initialized values */ if ( pan_tilt_valid != 1 ) { if ( input_cmd(IN_CMD_RESET_PAN_TILT_NO_MUTEX, 0) == -1 ) { res = -1; break; } } /* limit pan-value to min and max, multiply it with constant "one_degree" */ value = MIN(MAX(value*one_degree, MIN_PAN), MAX_PAN); /* calculate the relative degrees to move to the desired absolute pan-value */ if( (res = value - pan) == 0 ) { /* do not move if this would mean to move by 0 degrees */ res = pan/one_degree; break; } /* move it */ pan = value; uvcPanTilt(videoIn->fd, res, 0, 0); res = pan/one_degree; DBG("pan: %d\n", pan); break; case IN_CMD_PAN_PLUS: DBG("pan +\n"); if ( pan_tilt_valid != 1 ) { if ( input_cmd(IN_CMD_RESET_PAN_TILT_NO_MUTEX, 0) == -1 ) { res = -1; break; } } if ( (MAX_PAN) >= (pan+MIN_RES) ) { pan += MIN_RES; uvcPanTilt(videoIn->fd, MIN_RES, 0, 0); } res = pan/one_degree; DBG("pan: %d\n", pan); break; case IN_CMD_PAN_MINUS: DBG("pan -\n"); if ( pan_tilt_valid != 1 ) { if ( input_cmd(IN_CMD_RESET_PAN_TILT_NO_MUTEX, 0) == -1 ) { res = -1; break; } } if ( (MIN_PAN) <= (pan-MIN_RES) ) { pan -= MIN_RES; uvcPanTilt(videoIn->fd, -MIN_RES, 0, 0); } res = pan/one_degree; DBG("pan: %d\n", pan); break; case IN_CMD_TILT_SET: DBG("set tilt to %d degrees\n", value); if ( pan_tilt_valid != 1 ) { if ( input_cmd(IN_CMD_RESET_PAN_TILT_NO_MUTEX, 0) == -1 ) { res = -1; break; } } /* limit pan-value to min and max, multiply it with constant "one_degree" */ value = MIN(MAX(value*one_degree, MIN_TILT), MAX_TILT); /* calculate the relative degrees to move to the desired absolute pan-value */ if( (res = value - tilt) == 0 ) { /* do not move if this would mean to move by 0 degrees */ res = tilt/one_degree; break; } /* move it */ tilt = value; uvcPanTilt(videoIn->fd, 0, res, 0); res = tilt/one_degree; DBG("tilt: %d\n", tilt); break; case IN_CMD_TILT_PLUS: DBG("tilt +\n"); if ( pan_tilt_valid != 1 ) { if ( input_cmd(IN_CMD_RESET_PAN_TILT_NO_MUTEX, 0) == -1 ) { res = -1; break; } } if ( (MAX_TILT) >= (tilt+MIN_RES) ) { tilt += MIN_RES; uvcPanTilt(videoIn->fd, 0, MIN_RES, 0); } res = tilt/one_degree; DBG("tilt: %d\n", tilt); break; case IN_CMD_TILT_MINUS: DBG("tilt -\n"); if ( pan_tilt_valid != 1 ) { if ( input_cmd(IN_CMD_RESET_PAN_TILT_NO_MUTEX, 0) == -1 ) { res = -1; break; } } if ( (MIN_TILT) <= (tilt-MIN_RES) ) { tilt -= MIN_RES; uvcPanTilt(videoIn->fd, 0, -MIN_RES, 0); } res = tilt/one_degree; DBG("tilt: %d\n", tilt); break; case IN_CMD_SATURATION_PLUS: DBG("saturation + (%d)\n", v4l2GetControl (videoIn, V4L2_CID_SATURATION)); res = v4l2UpControl(videoIn, V4L2_CID_SATURATION); break; case IN_CMD_SATURATION_MINUS: DBG("saturation - (%d)\n", v4l2GetControl (videoIn, V4L2_CID_SATURATION)); res = v4l2DownControl(videoIn, V4L2_CID_SATURATION); break; case IN_CMD_CONTRAST_PLUS: DBG("contrast + (%d)\n", v4l2GetControl (videoIn, V4L2_CID_CONTRAST)); res = v4l2UpControl(videoIn, V4L2_CID_CONTRAST); break; case IN_CMD_CONTRAST_MINUS: DBG("contrast - (%d)\n", v4l2GetControl (videoIn, V4L2_CID_CONTRAST)); res = v4l2DownControl(videoIn, V4L2_CID_CONTRAST); break; case IN_CMD_BRIGHTNESS_PLUS: DBG("brightness + (%d)\n", v4l2GetControl (videoIn, V4L2_CID_BRIGHTNESS)); res = v4l2UpControl(videoIn, V4L2_CID_BRIGHTNESS); break; case IN_CMD_BRIGHTNESS_MINUS: DBG("brightness - (%d)\n", v4l2GetControl (videoIn, V4L2_CID_BRIGHTNESS)); res = v4l2DownControl(videoIn, V4L2_CID_BRIGHTNESS); break; case IN_CMD_GAIN_PLUS: DBG("gain + (%d)\n", v4l2GetControl (videoIn, V4L2_CID_GAIN)); res = v4l2UpControl(videoIn, V4L2_CID_GAIN); break; case IN_CMD_GAIN_MINUS: DBG("gain - (%d)\n", v4l2GetControl (videoIn, V4L2_CID_GAIN)); res = v4l2DownControl(videoIn, V4L2_CID_GAIN); break; case IN_CMD_FOCUS_PLUS: DBG("focus + (%d)\n", focus); value=MIN(MAX(focus+10,0),255); if ( (res = v4l2SetControl(videoIn, V4L2_CID_FOCUS_LOGITECH, value)) == 0) { focus = value; } res = focus; break; case IN_CMD_FOCUS_MINUS: DBG("focus - (%d)\n", focus); value=MIN(MAX(focus-10,0),255); if ( (res = v4l2SetControl(videoIn, V4L2_CID_FOCUS_LOGITECH, value)) == 0) { focus = value; } res = focus; break; case IN_CMD_FOCUS_SET: value=MIN(MAX(value,0),255); DBG("set focus to %d\n", value); if ( (res = v4l2SetControl(videoIn, V4L2_CID_FOCUS_LOGITECH, value)) == 0) { focus = value; } res = focus; break; /* switch the webcam LED permanently on */ case IN_CMD_LED_ON: res = v4l2SetControl(videoIn, V4L2_CID_LED1_MODE_LOGITECH, 1); break; /* switch the webcam LED permanently off */ case IN_CMD_LED_OFF: res = v4l2SetControl(videoIn, V4L2_CID_LED1_MODE_LOGITECH, 0); break; /* switch the webcam LED on if streaming, off if not streaming */ case IN_CMD_LED_AUTO: res = v4l2SetControl(videoIn, V4L2_CID_LED1_MODE_LOGITECH, 3); break; /* let the webcam LED blink at a given hardcoded intervall */ case IN_CMD_LED_BLINK: res = v4l2SetControl(videoIn, V4L2_CID_LED1_MODE_LOGITECH, 2); res = v4l2SetControl(videoIn, V4L2_CID_LED1_FREQUENCY_LOGITECH, 255); break; default: DBG("nothing matched\n"); res = -1; } if ( cmd != IN_CMD_RESET_PAN_TILT_NO_MUTEX ) pthread_mutex_unlock( &controls_mutex ); return res; }
int main() { fp = fopen("log.txt", "w"); log_time(); fprintf(fp, "Start Programm\n"); int target_floor, target_room; int view_flag = 1; building *building_list = (building *) malloc(sizeof(building)); log_time(); fprintf(fp, "init building_list\n"); init(building_list); add_floor(building_list, FALSE); add_room(building_list, FALSE); add_room(building_list, FALSE); add_room(building_list, FALSE); while (1) { fflush(fp); if (view_flag) view_building(building_list, TRUE); else { view_room(building_list, target_floor, target_room); } switch (input_cmd()) { case 1: { // [1] 건물 확장 switch (input_extend_cmd()) { case 1: { // [1] 층 확장 add_floor(building_list, TRUE); break; } case 2: { // [2] 방 확장 add_room(building_list, TRUE); break; } } break; } case 2: { // [2] View 변환 if (view_flag) { printf("특정 방 내부 보여주기 로 View가 변환되었습니다.\n"); printf("층과 호수를 입력하세요\n"); if (tts_flag) { system("pico2wave -w test.wav \"Translated the view into the specific room viewing.\""); system("aplay -q test.wav"); system("pico2wave -w test.wav \"Input floor number and room number\""); system("aplay -q test.wav"); } scanf("%d %d", &target_floor, &target_room); view_flag = 0; } else { printf("전체 방 보여주기 로 View가 변환되었습니다.\n"); if (tts_flag) { system("pico2wave -w test.wav \"Translated the view into the total room viewing.\""); system("aplay -q test.wav"); } view_flag = 1; } break; } case 3: { // [3] 방 별 칸 변환 change_space(building_list); break; } case 4: { // [4] 칸 별 사람 이름 변환 change_name(building_list); break; } case 5: { search_name(building_list); break; } case 6: { // [6] TTS ON/OFF if (tts_flag) { printf("TTS를 사용하지않습니다.\n"); tts_flag = 0; } else { printf("TTS를 사용합니다.\n"); system("pico2wave -w test.wav \"From now, Use text to speach.\""); system("aplay -q test.wav"); tts_flag = 1; } break; } case 7: { // [5] 종료 printf("\n프로그램을 종료합니다.\n"); if (tts_flag) { system("pico2wave -w test.wav \"Exit Program.\""); system("aplay -q test.wav"); } return 0; break; } } } return 0; }