static void _mp_change(void) { if (_mp_setv) _mp_setv(_mpw[0].d.thumbbar.value); if (!(song_get_mode() & (MODE_PLAYING | MODE_PATTERN_LOOP))) { if (_mp_setv_noplay) _mp_setv_noplay(_mpw[0].d.thumbbar.value); } _mp_active = 2; }
static inline void draw_time(void) { char buf[16]; int is_playing = song_get_mode() & (MODE_PLAYING | MODE_PATTERN_LOOP); if (status.time_display == TIME_OFF || (status.time_display == TIME_PLAY_OFF && !is_playing)) return; /* this allows for 999 hours... that's like... 41 days... * who on earth leaves a tracker running for 41 days? */ sprintf(buf, "%3d:%02d:%02d", current_time.h % 1000, current_time.m % 60, current_time.s % 60); draw_text(buf, 69, 9, 0, 2); }
/* this does the lines for playing samples */ static void _draw_sample_play_marks(struct vgamem_overlay *r, song_sample_t * sample) { int n, x, y; int c; song_voice_t *channel; unsigned int *channel_list; if (song_get_mode() == MODE_STOPPED) return; song_lock_audio(); n = song_get_mix_state(&channel_list); while (n--) { channel = song_get_mix_channel(channel_list[n]); if (channel->current_sample_data != sample->data) continue; if (!channel->final_volume) continue; c = (channel->flags & (CHN_KEYOFF | CHN_NOTEFADE)) ? SAMPLE_BGMARK_COLOR : SAMPLE_MARK_COLOR; x = channel->position * (r->width - 1) / sample->length; if (x >= r->width) { /* this does, in fact, happen :( */ continue; } y = 0; do { /* unrolled 8 times */ vgamem_ovl_drawpixel(r, x, y++, c); vgamem_ovl_drawpixel(r, x, y++, c); vgamem_ovl_drawpixel(r, x, y++, c); vgamem_ovl_drawpixel(r, x, y++, c); vgamem_ovl_drawpixel(r, x, y++, c); vgamem_ovl_drawpixel(r, x, y++, c); vgamem_ovl_drawpixel(r, x, y++, c); vgamem_ovl_drawpixel(r, x, y++, c); } while (y < r->height); } song_unlock_audio(); }
/* return 1 -> the time changed; need to redraw */ static int check_time(void) { static int last_o = -1, last_r = -1, last_timep = -1; time_t timep = 0; int h, m, s; enum tracker_time_display td = status.time_display; int is_playing = song_get_mode() & (MODE_PLAYING | MODE_PATTERN_LOOP); int row, order; switch (td) { case TIME_PLAY_ELAPSED: td = (is_playing ? TIME_PLAYBACK : TIME_ELAPSED); break; case TIME_PLAY_CLOCK: td = (is_playing ? TIME_PLAYBACK : TIME_CLOCK); break; case TIME_PLAY_OFF: td = (is_playing ? TIME_PLAYBACK : TIME_OFF); break; default: break; } switch (td) { case TIME_OFF: h = m = s = 0; break; case TIME_PLAYBACK: h = (m = (s = song_get_current_time()) / 60) / 60; break; case TIME_ELAPSED: h = (m = (s = SDL_GetTicks() / 1000) / 60) / 60; break; case TIME_ABSOLUTE: /* absolute time shows the time of the current cursor position in the pattern editor :) */ if (status.current_page == PAGE_PATTERN_EDITOR) { row = get_current_row(); order = song_next_order_for_pattern(get_current_pattern()); } else { order = get_current_order(); row = 0; } if (order < 0) { s = m = h = 0; } else { if (last_o == order && last_r == row) { timep = last_timep; } else { last_timep = timep = song_get_length_to(order, row); last_o = order; last_r = row; } s = timep % 60; m = (timep / 60) % 60; h = (timep / 3600); } break; default: /* this will never happen */ case TIME_CLOCK: /* Impulse Tracker doesn't have this, but I always wanted it, so here 'tis. */ h = status.tmnow.tm_hour; m = status.tmnow.tm_min; s = status.tmnow.tm_sec; break; } if (h == current_time.h && m == current_time.m && s == current_time.s) { return 0; } current_time.h = h; current_time.m = m; current_time.s = s; return 1; }
/* returns 1 if the key was handled */ static int handle_key_global(struct key_event * k) { int i, ins_mode; if (_mp_active == 2 && (k->mouse == MOUSE_CLICK && k->state == KEY_RELEASE)) { status.flags |= NEED_UPDATE; dialog_destroy_all(); _mp_active = 0; // eat it... return 1; } if ((!_mp_active) && k->state == KEY_PRESS && k->mouse == MOUSE_CLICK) { if (k->x >= 63 && k->x <= 77 && k->y >= 6 && k->y <= 7) { status.vis_style++; status.vis_style %= VIS_SENTINEL; status.flags |= NEED_UPDATE; return 1; } else if (k->y == 5 && k->x == 50) { minipop_slide(kbd_get_current_octave(), "Octave", 0, 8, kbd_set_current_octave, NULL, 50, 5); return 1; } else if (k->y == 4 && k->x >= 50 && k->x <= 52) { minipop_slide(song_get_current_speed(), "Speed", 1, 255, song_set_current_speed, song_set_initial_speed, 51, 4); return 1; } else if (k->y == 4 && k->x >= 54 && k->x <= 56) { minipop_slide(song_get_current_tempo(), "Tempo", 32, 255, song_set_current_tempo, song_set_initial_tempo, 55, 4); return 1; } else if (k->y == 3 && k->x >= 50 && k-> x <= 77) { if (page_is_instrument_list(status.current_page) || status.current_page == PAGE_SAMPLE_LIST || (!(status.flags & CLASSIC_MODE) && (status.current_page == PAGE_ORDERLIST_PANNING || status.current_page == PAGE_ORDERLIST_VOLUMES))) ins_mode = 0; else ins_mode = song_is_instrument_mode(); if (ins_mode) { minipop_slide(instrument_get_current(), "!", status.current_page == PAGE_INSTRUMENT_LIST ? 1 : 0, 99 /* FIXME */, instrument_set, NULL, 58, 3); } else { minipop_slide(sample_get_current(), "@", status.current_page == PAGE_SAMPLE_LIST ? 1 : 0, 99 /* FIXME */, sample_set, NULL, 58, 3); } } else if (k->y == 7 && k->x >= 11 && k->x <= 17) { minipop_slide(get_current_row(), "Row", 0, song_get_rows_in_pattern(get_current_pattern()), set_current_row, NULL, 14, 7); return 1; } else if (k->y == 6 && k->x >= 11 && k->x <= 17) { minipop_slide(get_current_pattern(), "Pattern", 0, csf_get_num_patterns(current_song), set_current_pattern, NULL, 14, 6); return 1; } else if (k->y == 5 && k->x >= 11 && k->x <= 17) { minipop_slide(song_get_current_order(), "Order", 0, csf_get_num_orders(current_song), set_current_order, NULL, 14, 5); return 1; } } else if ((!_mp_active) && k->mouse == MOUSE_DBLCLICK) { if (k->y == 4 && k->x >= 11 && k->x <= 28) { set_page(PAGE_SAVE_MODULE); return 1; } else if (k->y == 3 && k->x >= 11 && k->x <= 35) { set_page(PAGE_SONG_VARIABLES); return 1; } } /* shortcut */ if (k->mouse != MOUSE_NONE) { return 0; } /* first, check the truly global keys (the ones that still work if * a dialog's open) */ switch (k->sym) { case SDLK_RETURN: if ((k->mod & KMOD_CTRL) && k->mod & KMOD_ALT) { if (k->state == KEY_PRESS) return 1; toggle_display_fullscreen(); return 1; } break; case SDLK_m: if (k->mod & KMOD_CTRL) { if (k->state == KEY_RELEASE) return 1; video_mousecursor(MOUSE_CYCLE_STATE); return 1; } break; case SDLK_d: if (k->mod & KMOD_CTRL) { if (k->state == KEY_RELEASE) return 1; /* argh */ i = SDL_WM_GrabInput(SDL_GRAB_QUERY); if (i == SDL_GRAB_QUERY) i = currently_grabbed; currently_grabbed = i = (i != SDL_GRAB_ON ? SDL_GRAB_ON : SDL_GRAB_OFF); SDL_WM_GrabInput(i); status_text_flash(i ? "Mouse and keyboard grabbed, press Ctrl+D to release" : "Mouse and keyboard released"); return 1; } break; case SDLK_i: /* reset audio stuff? */ if (k->mod & KMOD_CTRL) { if (k->state == KEY_RELEASE) return 1; audio_reinit(); return 1; } break; case SDLK_e: /* This should reset everything display-related. */ if (k->mod & KMOD_CTRL) { if (k->state == KEY_RELEASE) return 1; font_init(); status.flags |= NEED_UPDATE; return 1; } break; case SDLK_HOME: if (!(k->mod & KMOD_ALT)) break; if (status.flags & DISKWRITER_ACTIVE) break; if (k->state == KEY_RELEASE) return 0; kbd_set_current_octave(kbd_get_current_octave() - 1); return 1; case SDLK_END: if (!(k->mod & KMOD_ALT)) break; if (status.flags & DISKWRITER_ACTIVE) break; if (k->state == KEY_RELEASE) return 0; kbd_set_current_octave(kbd_get_current_octave() + 1); return 1; default: break; } /* next, if there's no dialog, check the rest of the keys */ if (status.flags & DISKWRITER_ACTIVE) return 0; switch (k->sym) { case SDLK_q: if (status.dialog_type != DIALOG_NONE) return 0; if (k->mod & KMOD_CTRL) { _mp_finish(NULL); if (k->state == KEY_PRESS) show_exit_prompt(); return 1; } break; case SDLK_n: if (status.dialog_type != DIALOG_NONE) return 0; if (k->mod & KMOD_CTRL) { _mp_finish(NULL); if (k->state == KEY_PRESS) new_song_dialog(); return 1; } break; case SDLK_g: if (status.dialog_type != DIALOG_NONE) return 0; if (k->mod & KMOD_CTRL) { _mp_finish(NULL); if (k->state == KEY_PRESS) show_song_timejump(); return 1; } break; case SDLK_p: if (status.dialog_type != DIALOG_NONE) return 0; if (k->mod & KMOD_CTRL) { _mp_finish(NULL); if (k->state == KEY_PRESS) show_song_length(); return 1; } break; case SDLK_F1: if (status.dialog_type != DIALOG_NONE) return 0; if (k->mod & KMOD_CTRL) { _mp_finish(NULL); if (k->state == KEY_PRESS) set_page(PAGE_CONFIG); } else if (k->mod & KMOD_SHIFT) { _mp_finish(NULL); if (k->state == KEY_PRESS) set_page(status.current_page == PAGE_MIDI ? PAGE_MIDI_OUTPUT : PAGE_MIDI); } else if (NO_MODIFIER(k->mod)) { _mp_finish(NULL); if (k->state == KEY_PRESS) set_page(PAGE_HELP); } else { break; } return 1; case SDLK_F2: if (k->mod & KMOD_CTRL) { if (status.current_page == PAGE_PATTERN_EDITOR) { _mp_finish(NULL); if (k->state == KEY_PRESS && status.dialog_type == DIALOG_NONE) { pattern_editor_length_edit(); } return 1; } if (status.dialog_type != DIALOG_NONE) return 0; } else if (NO_MODIFIER(k->mod)) { if (status.current_page == PAGE_PATTERN_EDITOR) { if (k->state == KEY_PRESS) { if (status.dialog_type & DIALOG_MENU) { return 0; } else if (status.dialog_type != DIALOG_NONE) { dialog_yes_NULL(); status.flags |= NEED_UPDATE; } else { _mp_finish(NULL); pattern_editor_display_options(); } } } else { if (status.dialog_type != DIALOG_NONE) return 0; _mp_finish(NULL); if (k->state == KEY_PRESS) set_page(PAGE_PATTERN_EDITOR); } return 1; } break; case SDLK_F3: if (status.dialog_type != DIALOG_NONE) return 0; if (NO_MODIFIER(k->mod)) { _mp_finish(NULL); if (k->state == KEY_PRESS) set_page(PAGE_SAMPLE_LIST); } else { _mp_finish(NULL); if (k->mod & KMOD_CTRL) set_page(PAGE_LIBRARY_SAMPLE); break; } return 1; case SDLK_F4: if (status.dialog_type != DIALOG_NONE) return 0; if (NO_MODIFIER(k->mod)) { if (status.current_page == PAGE_INSTRUMENT_LIST) return 0; _mp_finish(NULL); if (k->state == KEY_PRESS) set_page(PAGE_INSTRUMENT_LIST); } else { if (k->mod & KMOD_SHIFT) return 0; _mp_finish(NULL); if (k->mod & KMOD_CTRL) set_page(PAGE_LIBRARY_INSTRUMENT); break; } return 1; case SDLK_F5: if (k->mod & KMOD_CTRL) { _mp_finish(NULL); if (k->state == KEY_PRESS) song_start(); } else if (k->mod & KMOD_SHIFT) { if (status.dialog_type != DIALOG_NONE) return 0; _mp_finish(NULL); if (k->state == KEY_RELEASE) set_page(PAGE_PREFERENCES); } else if (NO_MODIFIER(k->mod)) { if (song_get_mode() == MODE_STOPPED || (song_get_mode() == MODE_SINGLE_STEP && status.current_page == PAGE_INFO)) { _mp_finish(NULL); if (k->state == KEY_PRESS) song_start(); } if (k->state == KEY_PRESS) { if (status.dialog_type != DIALOG_NONE) return 0; _mp_finish(NULL); set_page(PAGE_INFO); } } else { break; } return 1; case SDLK_F6: if (k->mod & KMOD_SHIFT) { _mp_finish(NULL); if (k->state == KEY_PRESS) song_start_at_order(get_current_order(), 0); } else if (NO_MODIFIER(k->mod)) { _mp_finish(NULL); if (k->state == KEY_PRESS) song_loop_pattern(get_current_pattern(), 0); } else { break; } return 1; case SDLK_F7: if (NO_MODIFIER(k->mod)) { _mp_finish(NULL); if (k->state == KEY_PRESS) play_song_from_mark(); } else { break; } return 1; case SDLK_F8: if (k->mod & KMOD_SHIFT) { if (k->state == KEY_PRESS) song_pause(); } else if (NO_MODIFIER(k->mod)) { _mp_finish(NULL); if (k->state == KEY_PRESS) song_stop(); status.flags |= NEED_UPDATE; } else { break; } return 1; case SDLK_F9: if (status.dialog_type != DIALOG_NONE) return 0; if (k->mod & KMOD_SHIFT) { _mp_finish(NULL); if (k->state == KEY_PRESS) set_page(PAGE_MESSAGE); } else if (NO_MODIFIER(k->mod)) { _mp_finish(NULL); if (k->state == KEY_PRESS) set_page(PAGE_LOAD_MODULE); } else { break; } return 1; case SDLK_l: case SDLK_r: if (status.dialog_type != DIALOG_NONE) return 0; if (k->mod & KMOD_CTRL) { _mp_finish(NULL); if (k->state == KEY_RELEASE) set_page(PAGE_LOAD_MODULE); } else { break; } return 1; case SDLK_s: if (status.dialog_type != DIALOG_NONE) return 0; if (k->mod & KMOD_CTRL) { _mp_finish(NULL); if (k->state == KEY_RELEASE) save_song_or_save_as(); } else { break; } return 1; case SDLK_w: /* Ctrl-W _IS_ in IT, and hands don't leave home row :) */ if (status.dialog_type != DIALOG_NONE) return 0; if (k->mod & KMOD_CTRL) { _mp_finish(NULL); if (k->state == KEY_RELEASE) set_page(PAGE_SAVE_MODULE); } else { break; } return 1; case SDLK_F10: if (status.dialog_type != DIALOG_NONE) return 0; if (k->mod & KMOD_ALT) break; if (k->mod & KMOD_CTRL) break; _mp_finish(NULL); if (k->mod & KMOD_SHIFT) { if (k->state == KEY_PRESS) set_page(PAGE_EXPORT_MODULE); } else { if (k->state == KEY_PRESS) set_page(PAGE_SAVE_MODULE); } return 1; case SDLK_F11: if (status.dialog_type != DIALOG_NONE) return 0; if (NO_MODIFIER(k->mod)) { _mp_finish(NULL); if (status.current_page == PAGE_ORDERLIST_PANNING) { if (k->state == KEY_PRESS) set_page(PAGE_ORDERLIST_VOLUMES); } else { if (k->state == KEY_PRESS) set_page(PAGE_ORDERLIST_PANNING); } } else if (k->mod & KMOD_CTRL) { if (k->state == KEY_PRESS) { _mp_finish(NULL); if (status.current_page == PAGE_LOG) { show_about(); } else { set_page(PAGE_LOG); } } } else if (k->state == KEY_PRESS && (k->mod & KMOD_ALT)) { _mp_finish(NULL); if (song_toggle_orderlist_locked()) status_text_flash("Order list locked"); else status_text_flash("Order list unlocked"); } else { break; } return 1; case SDLK_F12: if (status.dialog_type != DIALOG_NONE) return 0; if ((k->mod & KMOD_ALT) && status.current_page == PAGE_INFO) { _mp_finish(NULL); if (k->state == KEY_PRESS) set_page(PAGE_WATERFALL); } else if (k->mod & KMOD_CTRL) { _mp_finish(NULL); if (k->state == KEY_PRESS) set_page(PAGE_PALETTE_EDITOR); } else if (k->mod & KMOD_SHIFT) { _mp_finish(NULL); if (k->state == KEY_PRESS) { fontedit_return_page = status.current_page; set_page(PAGE_FONT_EDIT); } } else if (NO_MODIFIER(k->mod)) { _mp_finish(NULL); if (k->state == KEY_PRESS) set_page(PAGE_SONG_VARIABLES); } else { break; } return 1; /* hack alert */ case SDLK_f: if (!(k->mod & KMOD_CTRL)) return 0; /* fall through */ case SDLK_SCROLLOCK: if (status.dialog_type != DIALOG_NONE) return 0; _mp_finish(NULL); if (k->mod & KMOD_ALT) { if (k->state == KEY_PRESS) { midi_flags ^= (MIDI_DISABLE_RECORD); status_text_flash("MIDI Input %s", (midi_flags & MIDI_DISABLE_RECORD) ? "Disabled" : "Enabled"); } return 1; } else { /* os x steals plain scroll lock for brightness, * so catch ctrl+scroll lock here as well */ if (k->state == KEY_PRESS) { midi_playback_tracing = (playback_tracing = !playback_tracing); status_text_flash("Playback tracing %s", (playback_tracing ? "enabled" : "disabled")); } return 1; } default: if (status.dialog_type != DIALOG_NONE) return 0; break; } /* got a bit ugly here, sorry */ i = k->sym; if (k->mod & KMOD_ALT) { switch (i) { case SDLK_F1: i = 0; break; case SDLK_F2: i = 1; break; case SDLK_F3: i = 2; break; case SDLK_F4: i = 3; break; case SDLK_F5: i = 4; break; case SDLK_F6: i = 5; break; case SDLK_F7: i = 6; break; case SDLK_F8: i = 7; break; default: return 0; }; if (k->state == KEY_RELEASE) return 1; song_toggle_channel_mute(i); status.flags |= NEED_UPDATE; return 1; } /* oh well */ return 0; }
/* this is the important one */ void handle_key(struct key_event *k) { if (_handle_ime(k)) return; /* okay... */ if (!(status.flags & DISKWRITER_ACTIVE) && ACTIVE_PAGE.pre_handle_key) { if (ACTIVE_PAGE.pre_handle_key(k)) return; } if (handle_key_global(k)) return; if (!(status.flags & DISKWRITER_ACTIVE) && menu_handle_key(k)) return; if (widget_handle_key(k)) return; /* now check a couple other keys. */ switch (k->sym) { case SDLK_LEFT: if (k->state == KEY_RELEASE) return; if (status.flags & DISKWRITER_ACTIVE) return; if ((k->mod & KMOD_CTRL) && status.current_page != PAGE_PATTERN_EDITOR) { _mp_finish(NULL); if (song_get_mode() == MODE_PLAYING) song_set_current_order(song_get_current_order() - 1); return; } break; case SDLK_RIGHT: if (k->state == KEY_RELEASE) return; if (status.flags & DISKWRITER_ACTIVE) return; if ((k->mod & KMOD_CTRL) && status.current_page != PAGE_PATTERN_EDITOR) { _mp_finish(NULL); if (song_get_mode() == MODE_PLAYING) song_set_current_order(song_get_current_order() + 1); return; } break; case SDLK_ESCAPE: /* TODO | Page key handlers should return true/false depending on if the key was handled TODO | (same as with other handlers), and the escape key check should go *after* the TODO | page gets a chance to grab it. This way, the load sample page can switch back TODO | to the sample list on escape like it's supposed to. (The status.current_page TODO | checks above won't be necessary, either.) */ if (NO_MODIFIER(k->mod) && status.dialog_type == DIALOG_NONE && status.current_page != PAGE_LOAD_SAMPLE && status.current_page != PAGE_LOAD_INSTRUMENT) { if (k->state == KEY_RELEASE) return; if (_mp_active) { _mp_finish(NULL); return; } menu_show(); return; } break; case SDLK_SLASH: if (k->state == KEY_RELEASE) return; if (status.flags & DISKWRITER_ACTIVE) return; if (k->orig_sym == SDLK_KP_DIVIDE) { kbd_set_current_octave(kbd_get_current_octave() - 1); } return; case SDLK_ASTERISK: if (k->state == KEY_RELEASE) return; if (status.flags & DISKWRITER_ACTIVE) return; if (k->orig_sym == SDLK_KP_MULTIPLY) { kbd_set_current_octave(kbd_get_current_octave() + 1); } return; case SDLK_LEFTBRACKET: if (k->state == KEY_RELEASE) break; if (status.flags & DISKWRITER_ACTIVE) return; if (k->mod & KMOD_SHIFT) { song_set_current_speed(song_get_current_speed() - 1); status_text_flash("Speed set to %d frames per row", song_get_current_speed()); if (!(song_get_mode() & (MODE_PLAYING | MODE_PATTERN_LOOP))) { song_set_initial_speed(song_get_current_speed()); } } else if ((k->mod & KMOD_CTRL) && !(status.flags & CLASSIC_MODE)) { song_set_current_tempo(song_get_current_tempo() - 1); status_text_flash("Tempo set to %d frames per row", song_get_current_tempo()); if (!(song_get_mode() & (MODE_PLAYING | MODE_PATTERN_LOOP))) { song_set_initial_tempo(song_get_current_tempo()); } } else if (NO_MODIFIER(k->mod)) { song_set_current_global_volume(song_get_current_global_volume() - 1); status_text_flash("Global volume set to %d", song_get_current_global_volume()); if (!(song_get_mode() & (MODE_PLAYING | MODE_PATTERN_LOOP))) { song_set_initial_global_volume(song_get_current_global_volume()); } } return; case SDLK_RIGHTBRACKET: if (k->state == KEY_RELEASE) break; if (status.flags & DISKWRITER_ACTIVE) return; if (k->mod & KMOD_SHIFT) { song_set_current_speed(song_get_current_speed() + 1); status_text_flash("Speed set to %d frames per row", song_get_current_speed()); if (!(song_get_mode() & (MODE_PLAYING | MODE_PATTERN_LOOP))) { song_set_initial_speed(song_get_current_speed()); } } else if ((k->mod & KMOD_CTRL) && !(status.flags & CLASSIC_MODE)) { song_set_current_tempo(song_get_current_tempo() + 1); status_text_flash("Tempo set to %d frames per row", song_get_current_tempo()); if (!(song_get_mode() & (MODE_PLAYING | MODE_PATTERN_LOOP))) { song_set_initial_tempo(song_get_current_tempo()); } } else if (NO_MODIFIER(k->mod)) { song_set_current_global_volume(song_get_current_global_volume() + 1); status_text_flash("Global volume set to %d", song_get_current_global_volume()); if (!(song_get_mode() & (MODE_PLAYING | MODE_PATTERN_LOOP))) { song_set_initial_global_volume(song_get_current_global_volume()); } } return; default: break; } /* and if we STILL didn't handle the key, pass it to the page. * (or dialog, if one's active) */ if (status.dialog_type & DIALOG_BOX) { dialog_handle_key(k); } else { if (status.flags & DISKWRITER_ACTIVE) return; if (ACTIVE_PAGE.handle_key) ACTIVE_PAGE.handle_key(k); } }