#include #include #include #include #define WIDTH 38 #define HEIGHT 23 #define V4L "/usr/bin/v4l2-ctl -c %s=%d" #define SAVEFILE "/boot/camera.txt" #define DEBUG false typedef struct { char name[30]; // Internal Control Name char display[25]; // Friendly Control Name int min; // Minimum Control Value int max; // Maximum Control Value int init; // Default Control Value int value; // Current Control Value bool hasoptions; // Enables Options char options[20][20]; // Option Array } control; control controls[] = { {"brightness", "Brightness", 0, 100, 50, 50}, {"contrast", "Contrast", -100, 100, 0, 0}, {"saturation", "Saturation", -100, 100, 0, 0}, {"red_balance", "Red", 1, 7999, 1000, 1000}, {"blue_balance", "Blue", 1, 7999, 1000, 1000}, {"horizontal_flip", "Horizontal Flip", 0, 1, 0, 0}, {"vertical_flip", "Vertical Flip", 0, 1, 0, 0}, {"power_line_frequency", "Powerline Frequency", 0, 3, 1, 1, true, {"Off ","50Hz","60Hz","Auto"}}, {"sharpness", "Sharpness", -100, 100, 0, 0}, {"color_effects", "Colour Effects", 0, 15, 0, 0, true, {"None ","Black & White","Sepia ","Negative ","Emboss ","Sketch ","Sky Blue ","Grass Green ","Skin Whiten ","Vivid ","Aqua ","Art Freeze ","Silhouette ","Solarization ","Antique ","Set Cb/Cr "}}, {"rotate", "Rotate", 0, 3, 0, 0, true, {"0 ","90 ","180","270"}}, {"color_effects_cbcr", "Chroma", 0, 65535, 32896, 32896}, {"auto_exposure", "Manual Exposure", 0, 1, 0, 0}, {"exposure_time_absolute", "Exposure Time", 1, 10000, 1000, 1000}, {"exposure_dynamic_framerate", "Dynamic Framerate", 0, 1, 0, 0}, {"auto_exposure_bias", "Auto Exposure Bias", 0, 24, 12, 12}, {"white_balance_auto_preset", "White Balance Preset", 0, 10, 1, 1, true, {"Manual ","Auto ","Incandescent ","Fluorescent ","Fluorescent H","Horizon ","Daylight ","Flash ","Cloudy ","Shade ","Greyworld "}}, {"image_stabilization","Image Stabilisation", 0, 1, 0, 0}, {"iso_sensitivity", "ISO Sensitivity", 0, 4, 0, 0}, {"iso_sensitivity_auto", "ISO Auto", 0, 1, 1, 1}, {"exposure_metering_mode", "Exposure Metering", 0, 2, 0, 0, true, {"Average ", "Center Weighted", "Spot "}}, }; int n_controls = sizeof(controls) / sizeof(control); void apply(int highlight); void apply_all(); void reset(); void print_menu(WINDOW *menu_win, int highlight); void menu_item(WINDOW *menu_win, int i, int y, int x); void load(); void save(); int main() { WINDOW *menu_win; int highlight = 0; int increment = 0; bool quit = false; int c; initscr(); clear(); noecho(); cbreak(); menu_win = newwin(HEIGHT, WIDTH, 0, 0); keypad(menu_win, TRUE); mvprintw(1, WIDTH+1, "Up/Down Navigate"); mvprintw(2, WIDTH+1, "Left/Right Adjust"); mvprintw(3, WIDTH+1, "PgDn/PgUp Jump Adjust"); mvprintw(4, WIDTH+1, "Enter Apply"); mvprintw(6, WIDTH+1, "A Apply All"); mvprintw(7, WIDTH+1, "R Reset All"); mvprintw(8, WIDTH+1, "D Default"); mvprintw(9, WIDTH+1, "N Minimum"); mvprintw(10, WIDTH+1, "M Maximum"); mvprintw(11, WIDTH+1, "L Load"); mvprintw(12, WIDTH+1, "S Save"); mvprintw(13, WIDTH+1, "Q Quit"); refresh(); print_menu(menu_win, highlight); while(!quit) { c = wgetch(menu_win); mvprintw(24, 0, "%*s", 80, " "); // Clear Status Bar refresh(); switch(c) { case KEY_UP: if(highlight <= 0) highlight = n_controls-1; else highlight--; break; case KEY_DOWN: if(highlight >= n_controls-1) highlight = 0; else highlight++; break; case KEY_LEFT: if (controls[highlight].value > controls[highlight].min) controls[highlight].value--; break; case KEY_RIGHT: if (controls[highlight].value < controls[highlight].max) controls[highlight].value++; break; case 338: // Page Down increment = (int)(controls[highlight].max - controls[highlight].min)/10; if (controls[highlight].value-increment >= controls[highlight].min) { controls[highlight].value-=increment; } else { controls[highlight].value = controls[highlight].min; } break; case 339: // Page Up increment = (int)(controls[highlight].max - controls[highlight].min)/10; if (controls[highlight].value+increment <= controls[highlight].max) { controls[highlight].value+=increment; } else { controls[highlight].value = controls[highlight].max; } break; case 'N': case 'n': controls[highlight].value = controls[highlight].min; break; case 'M': case 'm': controls[highlight].value = controls[highlight].max; break; case 'D': case 'd': controls[highlight].value = controls[highlight].init; break; case 'A': case 'a': apply_all(); break; case 'R': case 'r': reset(); break; case 10: // Enter apply(highlight); break; case 'L': case 'l': if (!DEBUG) load(); break; case 'S': case 's': if (!DEBUG) save(); break; case 'Q': case 'q': quit = true; break; default: if (DEBUG) { mvprintw(24, 0, "Character %3d '%c'", c, c); refresh(); } break; } print_menu(menu_win, highlight); } clrtoeol(); refresh(); endwin(); return 0; } void apply(int highlight) { int value=0; if (strcmp(controls[highlight].name, "rotate") == 0) // Handle Rotate Special Case { value = atoi(controls[highlight].options[controls[highlight].value]); } else { value = controls[highlight].value; } if (DEBUG) { mvprintw(24, 0, V4L, controls[highlight].name, value); } else { char cmd[100]; sprintf(cmd, V4L, controls[highlight].name, value); system(cmd); } refresh(); } void reset() { for (int i = 0; i < n_controls; i++) { controls[i].value = controls[i].init; } } void apply_all() { for (int i = 0; i < n_controls; i++) { apply(i); } } void load() { FILE *fp = fopen(SAVEFILE, "r"); char name[30]; int value; if (fp != NULL) { while (fscanf(fp,"%[^=]=%d\r\n", name, &value) == 2) // Assume control=value file format { for (int i = 0; i < n_controls; i++) { if (strcmp(name, controls[i].name) == 0) { if (strcmp(name, "rotate") == 0) value = (int)value/90; controls[i].value = value; break; } } } refresh(); fclose(fp); } else { mvprintw(24, 0, "Cannot load %s", SAVEFILE); refresh(); } } void save() { FILE *fp = fopen(SAVEFILE, "w"); // Overwrite existing file if (fp != NULL) { for (int i = 0; i < n_controls; i++) { int value=0; if (controls[i].value != controls[i].init) { if (strcmp(controls[i].name, "rotate") == 0) { value = atoi(controls[i].options[controls[i].value]); } else { value = controls[i].value; } fprintf(fp, "%s=%d\r\n", controls[i].name, value); } } fclose(fp); } else { mvprintw(24, 0, "Cannot save %s", SAVEFILE); refresh(); } } void print_menu(WINDOW *menu_win, int highlight) { int x, y, i; x = 2; y = 1; box(menu_win, 0, 0); for (i = 0; i < n_controls; i++) { if (highlight == i) { wattron(menu_win, A_REVERSE); menu_item(menu_win, i, y, x); wattroff(menu_win, A_REVERSE); } else menu_item(menu_win, i, y, x); y++; } wrefresh(menu_win); } void menu_item(WINDOW *menu_win, int i, int y, int x) { if (controls[i].hasoptions) { mvwprintw(menu_win, y, x, "%s %s", controls[i].display, controls[i].options[controls[i].value]); } else { mvwprintw(menu_win, y, x, "%s %5d", controls[i].display, controls[i].value); } }