diff options
Diffstat (limited to 'main-sdl.c')
| -rw-r--r-- | main-sdl.c | 245 |
1 files changed, 215 insertions, 30 deletions
| @@ -10,22 +10,31 @@ | |||
| 10 | #include <termios.h> | 10 | #include <termios.h> |
| 11 | #include <unistd.h> | 11 | #include <unistd.h> |
| 12 | #include <dirent.h> | 12 | #include <dirent.h> |
| 13 | #include <pwd.h> | ||
| 13 | 14 | ||
| 14 | #include <SDL2/SDL.h> | 15 | #include <SDL2/SDL.h> |
| 15 | #include "display.h" | 16 | #include "display.h" |
| 16 | #include "config.h" | 17 | #include "config.h" |
| 17 | #include "engine.h" | 18 | #include "engine.h" |
| 19 | #include "calib.h" | ||
| 18 | 20 | ||
| 19 | /*** | 21 | /*** |
| 20 | Global config and status values | 22 | Global config and status values |
| 21 | ***/ | 23 | ***/ |
| 22 | 24 | ||
| 23 | /* Window width and height */ | 25 | /* Window width and height */ |
| 24 | // const int g_width = 1024, g_height = 768; | 26 | enum { |
| 25 | const int g_width = 800, g_height = 600; | 27 | HARFE_WIDTH = 1024, |
| 28 | HARFE_HEIGHT = 768, | ||
| 29 | SCREEN_WIDTH = 800, | ||
| 30 | SCREEN_HEIGHT = 600 | ||
| 31 | }; | ||
| 26 | 32 | ||
| 27 | int g_harfe_connected = 0; | 33 | int g_harfe_connected = 0; |
| 28 | int g_harfe_fd = -1; | 34 | int g_harfe_fd = -1; |
| 35 | int g_importing_config = 0; | ||
| 36 | ConfigSource g_config_source = source_none; | ||
| 37 | int g_calibration_running = 0; | ||
| 29 | 38 | ||
| 30 | static char * | 39 | static char * |
| 31 | find_harfe() | 40 | find_harfe() |
| @@ -150,6 +159,13 @@ harfe_worker(void) | |||
| 150 | free(portname); | 159 | free(portname); |
| 151 | g_harfe_connected = 1; | 160 | g_harfe_connected = 1; |
| 152 | 161 | ||
| 162 | /* Get remote config (if any) */ | ||
| 163 | config_reset(); | ||
| 164 | write(g_harfe_fd, "S2\n", 3); | ||
| 165 | usleep(50); | ||
| 166 | g_importing_config = 1; | ||
| 167 | write(g_harfe_fd, "I\n", 2); | ||
| 168 | |||
| 153 | while (running) { | 169 | while (running) { |
| 154 | while (text_fill < sizeof(text) && !memchr(text, '\n', text_fill)) { | 170 | while (text_fill < sizeof(text) && !memchr(text, '\n', text_fill)) { |
| 155 | ssize_t b = read(g_harfe_fd, text + text_fill, sizeof(text) - text_fill); | 171 | ssize_t b = read(g_harfe_fd, text + text_fill, sizeof(text) - text_fill); |
| @@ -178,15 +194,29 @@ harfe_worker(void) | |||
| 178 | if (text_fill && lineend[-1] == '\r') | 194 | if (text_fill && lineend[-1] == '\r') |
| 179 | lineend[-1] = 0; | 195 | lineend[-1] = 0; |
| 180 | printf( "%s\n", text ); | 196 | printf( "%s\n", text ); |
| 181 | int num_points = sscanf(text, "%04d:%04d %04d:%04d %04d:%04d %04d:%04d", &p[0].x, &p[0].y, &p[1].x, &p[1].y, &p[2].x, &p[2].y, &p[3].x, &p[3].y); | ||
| 182 | 197 | ||
| 183 | ptime = now(); | 198 | if (g_importing_config) { |
| 184 | for (i = 0; i < num_points / 2; ++i) { | 199 | if (!strcmp(text, "-- DONE")) { |
| 200 | g_importing_config = 0; | ||
| 201 | g_config_source = source_harfe; | ||
| 202 | } else | ||
| 203 | config_handle_line(text); | ||
| 204 | } else { | ||
| 205 | |||
| 206 | int num_points = sscanf(text, "%04d:%04d %04d:%04d %04d:%04d %04d:%04d", &p[0].x, &p[0].y, &p[1].x, &p[1].y, &p[2].x, &p[2].y, &p[3].x, &p[3].y); | ||
| 207 | |||
| 208 | ptime = now(); | ||
| 209 | for (i = 0; i < num_points / 2; ++i) { | ||
| 185 | // printf("%04d:%04d\n", p[i].x, p[i].y); | 210 | // printf("%04d:%04d\n", p[i].x, p[i].y); |
| 186 | engine_handle_point(p + i, ptime); | 211 | |
| 187 | } | 212 | if (!g_calibration_running) |
| 188 | if (num_points > 1 || *text == '-') | 213 | engine_handle_point(p + i, ptime); |
| 214 | else | ||
| 215 | calib_handle_point(p + i, ptime); | ||
| 216 | } | ||
| 217 | if (num_points > 1 || *text == '-') | ||
| 189 | ++g_events; | 218 | ++g_events; |
| 219 | } | ||
| 190 | 220 | ||
| 191 | consumed = lineend - text + 1; | 221 | consumed = lineend - text + 1; |
| 192 | memmove(text, lineend + 1, text_fill - consumed); | 222 | memmove(text, lineend + 1, text_fill - consumed); |
| @@ -226,6 +256,36 @@ config_parse(char *config_file) | |||
| 226 | } | 256 | } |
| 227 | 257 | ||
| 228 | fclose(fh); | 258 | fclose(fh); |
| 259 | g_config_source = source_file; | ||
| 260 | } | ||
| 261 | |||
| 262 | static void | ||
| 263 | calib_fetch() { | ||
| 264 | int default_notes[] = { 60, 62, 64, 65, 67, 69, 71, 72, 74, 76, 77, 79, 81, 83 }; | ||
| 265 | int i, result_count; | ||
| 266 | LLine *result = calib_get_results(&result_count); | ||
| 267 | |||
| 268 | config_reset(); | ||
| 269 | g_string_count = result_count; | ||
| 270 | |||
| 271 | g_min_y = 0; g_max_y = 1024; | ||
| 272 | |||
| 273 | for (i=0; i<g_string_count; ++i) { | ||
| 274 | LLine *l = result + i; | ||
| 275 | |||
| 276 | if (l->p0.y > g_min_y) | ||
| 277 | g_min_y = l->p0.y; | ||
| 278 | if (l->p1.y < g_max_y) | ||
| 279 | g_max_y = l->p1.y; | ||
| 280 | |||
| 281 | g_string_conf[i].line = *l; | ||
| 282 | g_string_conf[i].mode = midi_three_octaves; | ||
| 283 | g_string_conf[i].channel = i; | ||
| 284 | g_string_conf[i].note = default_notes[i]; | ||
| 285 | g_string_conf[i].modifier = pitch_bend_up; | ||
| 286 | } | ||
| 287 | |||
| 288 | g_config_source = source_edit; | ||
| 229 | } | 289 | } |
| 230 | 290 | ||
| 231 | int | 291 | int |
| @@ -236,48 +296,153 @@ main(int argc, char **argv) | |||
| 236 | pthread_t thread_id; | 296 | pthread_t thread_id; |
| 237 | uint32_t runtime; | 297 | uint32_t runtime; |
| 238 | static int last_click_x, last_click_y, last_mouse_event; | 298 | static int last_click_x, last_click_y, last_mouse_event; |
| 299 | static int g_up_pressed = 0, g_down_pressed = 0; | ||
| 239 | 300 | ||
| 240 | display_init(g_width, g_height); | 301 | display_init(SCREEN_WIDTH, SCREEN_HEIGHT, HARFE_WIDTH, HARFE_HEIGHT); |
| 241 | engine_init(); | 302 | engine_init(); |
| 242 | config_parse("config_midi"); | 303 | // config_parse("config_midi"); |
| 243 | 304 | ||
| 244 | pthread_create(&thread_id, NULL, worker, NULL); | 305 | pthread_create(&thread_id, NULL, worker, NULL); |
| 245 | 306 | ||
| 307 | /* | ||
| 308 | E - Export config to Harfe (with implicite write to SD) | ||
| 309 | I - Import config from Harfe | ||
| 310 | W - Write config on Harfe to SD (no implicite Transfer) | ||
| 311 | |||
| 312 | S - Save config to local file | ||
| 313 | L - Load config from local default (config_midi) | ||
| 314 | |||
| 315 | Y - Invert String order | ||
| 316 | |||
| 317 | Q - Reset local Config | ||
| 318 | C - Start calibration | ||
| 319 | M - Play MIDI C through Harfe | ||
| 320 | */ | ||
| 321 | |||
| 246 | /* Spin and let call back do all the work */ | 322 | /* Spin and let call back do all the work */ |
| 247 | while (1) { | 323 | while (1) { |
| 248 | SDL_WaitEventTimeout(&ev, 10); | 324 | SDL_WaitEventTimeout(&ev, 10); |
| 249 | switch (ev.type) { | 325 | switch (ev.type) { |
| 250 | case SDL_QUIT: | 326 | case SDL_QUIT: |
| 251 | exit(0); | 327 | exit(0); |
| 252 | case SDL_KEYDOWN: | 328 | case SDL_KEYUP: |
| 329 | if (ev.key.keysym.scancode == SDL_SCANCODE_UP) g_up_pressed = 0; | ||
| 330 | if (ev.key.keysym.scancode == SDL_SCANCODE_DOWN) g_down_pressed = 0; | ||
| 331 | break; | ||
| 332 | case SDL_KEYDOWN: | ||
| 253 | /* | 333 | /* |
| 254 | if( ev.key.keysym.sym >= SDLK_1 && ev.key.keysym.sym <= SDLK_9 ) | 334 | if ( ev.key.keysym.sym >= SDLK_1 && ev.key.keysym.sym <= SDLK_9 ) |
| 255 | engine_select_string( ev.key.keysym.sym - SDLK_1 ); | 335 | engine_select_string( ev.key.keysym.sym - SDLK_1 ); |
| 256 | if( ev.key.keysym.sym == SDLK_BACKSPACE || ev.key.keysym.sym == SDLK_DELETE ) | 336 | if ( ev.key.keysym.sym == SDLK_BACKSPACE || ev.key.keysym.sym == SDLK_DELETE ) |
| 257 | engine_delete_selected_string( ); | 337 | engine_delete_selected_string( ); |
| 258 | if( ev.key.keysym.sym == SDLK_d ) { | 338 | if ( ev.key.keysym.sym == SDLK_d ) { |
| 259 | g_stringsdescending = 1 - g_stringsdescending; | 339 | g_stringsdescending = 1 - g_stringsdescending; |
| 260 | printf( "String order (left to right) is now %sscending.\n", g_stringsdescending ? "de" : "a" ); | 340 | printf( "String order (left to right) is now %sscending.\n", g_stringsdescending ? "de" : "a" ); |
| 261 | } | 341 | } |
| 262 | */ | 342 | */ |
| 263 | if( ev.key.keysym.scancode == SDL_SCANCODE_R) { | 343 | if ( ev.key.keysym.scancode == SDL_SCANCODE_0) |
| 264 | fprintf( stderr, "re-read config\n" ); | 344 | engine_select_config(sel_none); |
| 265 | write(g_harfe_fd, "R\n", 2); | 345 | if ( ev.key.keysym.scancode == SDL_SCANCODE_1) |
| 346 | engine_select_config(sel_min_y); | ||
| 347 | if ( ev.key.keysym.scancode == SDL_SCANCODE_2) | ||
| 348 | engine_select_config(sel_max_y); | ||
| 349 | if ( ev.key.keysym.scancode == SDL_SCANCODE_3) | ||
| 350 | engine_select_config(sel_2_oct); | ||
| 351 | if ( ev.key.keysym.scancode == SDL_SCANCODE_4) | ||
| 352 | engine_select_config(sel_3_oct_top); | ||
| 353 | if ( ev.key.keysym.scancode == SDL_SCANCODE_5) | ||
| 354 | engine_select_config(sel_3_oct_bottom); | ||
| 355 | |||
| 356 | if ( ev.key.keysym.scancode == SDL_SCANCODE_UP && ! g_up_pressed++) | ||
| 357 | engine_change_selected(1); | ||
| 358 | if ( ev.key.keysym.scancode == SDL_SCANCODE_DOWN && ! g_down_pressed++) | ||
| 359 | engine_change_selected(-1); | ||
| 360 | |||
| 361 | if ( ev.key.keysym.scancode == SDL_SCANCODE_S) { /* export locally */ | ||
| 362 | const char *homeDir = getenv("HOME"); | ||
| 363 | char savefile[512], date[32], confdump[512]; | ||
| 364 | time_t t = time(NULL); | ||
| 365 | struct tm *tmp = localtime(&t); | ||
| 366 | int fd; | ||
| 367 | size_t len; | ||
| 368 | |||
| 369 | if (!homeDir) { | ||
| 370 | struct passwd* pwd = getpwuid(getuid()); | ||
| 371 | if (pwd) | ||
| 372 | homeDir = (const char*)pwd->pw_dir; | ||
| 373 | } | ||
| 374 | strftime(date, sizeof(date), "%Y-%m-%d-%H-%M-%S", tmp); | ||
| 375 | snprintf( savefile, sizeof(savefile), "%s/Laserharfe-%s.cfg", homeDir, date); | ||
| 376 | fd = open(savefile, O_WRONLY | O_CREAT | O_TRUNC, 0644); | ||
| 377 | |||
| 378 | len = config_dumpglobals( confdump, sizeof(confdump)); | ||
| 379 | write(fd, confdump, len ); | ||
| 380 | for (i=0; i<g_string_count; ++i) { | ||
| 381 | len = config_dumpstring(i, confdump, sizeof(confdump)); | ||
| 382 | write(fd, confdump, len ); | ||
| 383 | } | ||
| 384 | close(fd); | ||
| 385 | } | ||
| 386 | if (ev.key.keysym.scancode == SDL_SCANCODE_W) { | ||
| 387 | fprintf( stderr, "write remote config\n" ); | ||
| 388 | write(g_harfe_fd, "W\n", 2); | ||
| 389 | } | ||
| 390 | if (ev.key.keysym.scancode == SDL_SCANCODE_I) { | ||
| 391 | fprintf( stderr, "dump config\n" ); | ||
| 392 | config_reset(); | ||
| 393 | g_importing_config = 1; | ||
| 394 | write(g_harfe_fd, "I\n", 2); | ||
| 395 | } | ||
| 396 | if (ev.key.keysym.scancode == SDL_SCANCODE_Q) | ||
| 397 | config_reset(); | ||
| 398 | if (ev.key.keysym.scancode == SDL_SCANCODE_L) | ||
| 399 | config_parse("config_midi"); | ||
| 400 | if (ev.key.keysym.scancode == SDL_SCANCODE_Y) { | ||
| 401 | for (i=0; i<g_string_count/2; ++i) { | ||
| 402 | LLine temp = g_string_conf[i].line; | ||
| 403 | g_string_conf[i].line = g_string_conf[g_string_count-i-1].line; | ||
| 404 | g_string_conf[g_string_count-i-1].line = temp; | ||
| 405 | } | ||
| 406 | g_config_source = source_edit; | ||
| 407 | } | ||
| 408 | if (ev.key.keysym.scancode == SDL_SCANCODE_X) { | ||
| 409 | g_midi_three_octave_split_inverse ^= 1; | ||
| 410 | g_config_source = source_edit; | ||
| 266 | } | 411 | } |
| 267 | if( ev.key.keysym.scancode == SDL_SCANCODE_D) { | 412 | #ifdef CALIB_DEBUG |
| 268 | fprintf( stderr, "Dumping\n" ); | 413 | if ( ev.key.keysym.scancode == SDL_SCANCODE_SPACE) |
| 269 | write(g_harfe_fd, "D\n", 2); | 414 | if (g_calibration_running) |
| 415 | calib_next(10); | ||
| 416 | #endif | ||
| 417 | if ( ev.key.keysym.scancode == SDL_SCANCODE_C) { | ||
| 418 | if (g_calibration_running) | ||
| 419 | calib_fetch(); | ||
| 420 | else | ||
| 421 | calib_init(); | ||
| 422 | g_calibration_running = 1 - g_calibration_running; | ||
| 270 | } | 423 | } |
| 271 | if( ev.key.keysym.scancode == SDL_SCANCODE_C) { | 424 | if ( ev.key.keysym.scancode == SDL_SCANCODE_E) { |
| 272 | char confdump[512]; | 425 | char confdump[512]; |
| 273 | config_dumpglobals( confdump, sizeof(confdump)); | 426 | if (!g_harfe_connected) { |
| 274 | fputs( confdump, stderr); | 427 | display_messagebox( "Not connected", "Can't write config if Harfe is not connected."); |
| 428 | break; | ||
| 429 | } | ||
| 430 | if ((int)g_config_source < 2) { | ||
| 431 | display_messagebox( "No changes", "Config is unchanged. Won't write config to Harfe."); | ||
| 432 | break; | ||
| 433 | } | ||
| 434 | write(g_harfe_fd, "E\n", 2); | ||
| 435 | size_t len = config_dumpglobals( confdump, sizeof(confdump)); | ||
| 436 | write(g_harfe_fd, confdump, len ); | ||
| 275 | for (i=0; i<g_string_count; ++i) { | 437 | for (i=0; i<g_string_count; ++i) { |
| 276 | config_dumpstring(i, confdump, sizeof(confdump)); | 438 | len = config_dumpstring(i, confdump, sizeof(confdump)); |
| 277 | fputs( confdump, stderr); | 439 | write(g_harfe_fd, confdump, len ); |
| 278 | } | 440 | } |
| 441 | write(g_harfe_fd, "-- DONE\n", 8); /* End dump marker */ | ||
| 442 | write(g_harfe_fd, "W\n", 2); /* Remote write to SD */ | ||
| 443 | g_config_source = source_harfe; | ||
| 279 | } | 444 | } |
| 280 | if( ev.key.keysym.scancode == SDL_SCANCODE_M) { | 445 | if ( ev.key.keysym.scancode == SDL_SCANCODE_M) { |
| 281 | fprintf( stderr, "MIDIing on %d\n", g_harfe_fd ); | 446 | fprintf( stderr, "MIDIing on %d\n", g_harfe_fd ); |
| 282 | if (g_harfe_connected && (g_harfe_fd != -1)) | 447 | if (g_harfe_connected && (g_harfe_fd != -1)) |
| 283 | write(g_harfe_fd, "ME20020\nM824C00\n", 16); | 448 | write(g_harfe_fd, "ME20020\nM824C00\n", 16); |
| @@ -285,20 +450,40 @@ main(int argc, char **argv) | |||
| 285 | break; | 450 | break; |
| 286 | case SDL_MOUSEBUTTONDOWN: | 451 | case SDL_MOUSEBUTTONDOWN: |
| 287 | /* | 452 | /* |
| 288 | if( ( g_last_mouse_event / 1000 ) != ( engine_now( ) / 1000 ) || ev.button.x != last_click_x || ev.button.y != last_click_y ) | 453 | if ( ( g_last_mouse_event / 1000 ) != ( engine_now( ) / 1000 ) || ev.button.x != last_click_x || ev.button.y != last_click_y ) |
| 289 | engine_process_mouse( ev.button.x, ev.button.y ); | 454 | engine_process_mouse( ev.button.x, ev.button.y ); |
| 290 | last_click_x = ev.button.x; | 455 | last_click_x = ev.button.x; |
| 291 | last_click_y = ev.button.y; | 456 | last_click_y = ev.button.y; |
| 292 | last_mouse_event = engine_now( ); | 457 | last_mouse_event = engine_now( ); |
| 293 | */ | 458 | */ |
| 459 | { | ||
| 460 | LPoint p = { display_scale_screen_to_harfe(ev.button.x), 768 - display_scale_screen_to_harfe(ev.button.y) }; | ||
| 461 | engine_handle_point(&p, now()); | ||
| 462 | } | ||
| 294 | break; | 463 | break; |
| 464 | case SDL_DROPFILE: { // In case if dropped file | ||
| 465 | char t[512]; | ||
| 466 | int ret; | ||
| 467 | snprintf( t, sizeof(t), "Do you want to import config file %s?\n", ev.drop.file); | ||
| 468 | if ((ret= display_messagebox_yesno("Import Laserharfe config", t))) | ||
| 469 | config_parse(ev.drop.file); | ||
| 470 | printf( "Dropped: %s (%d)\n", ev.drop.file, ret ); | ||
| 471 | break; | ||
| 472 | } | ||
| 473 | |||
| 295 | } | 474 | } |
| 475 | if (!g_calibration_running || !g_importing_config) | ||
| 476 | engine_checksilence(now()); | ||
| 296 | 477 | ||
| 297 | engine_checksilence(now()); | ||
| 298 | runtime = now(); | 478 | runtime = now(); |
| 299 | if (runtime - g_lastredraw > 30) { | 479 | if (runtime - g_lastredraw > 30 && !g_importing_config) { |
| 300 | g_lastredraw = runtime; | 480 | g_lastredraw = runtime; |
| 301 | engine_redraw(); | 481 | |
| 482 | if (!g_calibration_running) | ||
| 483 | engine_redraw(); | ||
| 484 | else | ||
| 485 | calib_redraw(); | ||
| 486 | |||
| 302 | } | 487 | } |
| 303 | if (runtime / 1000 - g_last_avg > 10) { | 488 | if (runtime / 1000 - g_last_avg > 10) { |
| 304 | printf("avg: %i\n", g_events / 10); | 489 | printf("avg: %i\n", g_events / 10); |
