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); |