Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // by megaloler! (megaloler9000@gmail.com)
- // a custom 100% midi-controlled live loop-based sequencer for the launchkey mini!
- #include <stdio.h>
- #include <stdlib.h>
- #include <unistd.h>
- #include <signal.h>
- #include <alsa/asoundlib.h>
- #define ALSA_CLIENT_NAME "LaunchSEQ"
- #define MAX_PATTERN_EVENTS 4096
- #define MAX_SONG_PATTERNS 16
- #define MAX_SONG_SCENES 128
- #define MAX_SONG_PATCHES 128
- #define MAX_QUEUE_SIZE 8192
- #define METRONOME_PULSE_FRAMES_PER_BEAT 16
- typedef struct
- {
- int patch;
- int events_length;
- snd_seq_event_t events[MAX_PATTERN_EVENTS];
- } Pattern;
- typedef struct
- {
- int scene_pattern_masks[MAX_SONG_SCENES];
- Pattern patterns[MAX_SONG_PATTERNS];
- int measures_per_pattern;
- int beats_per_measure;
- int bpm;
- int ticks_per_beat;
- int quantize;
- } Song;
- Song *new_song()
- {
- Song *song = malloc(sizeof *song);
- song->measures_per_pattern = 4;
- song->beats_per_measure = 4;
- song->bpm = 125;
- song->ticks_per_beat = 64;
- song->quantize = 128;
- int i;
- for(i = 0; i < MAX_SONG_SCENES; i++)
- {
- song->scene_pattern_masks[i] = 0;
- }
- for(i = 0; i < MAX_SONG_PATTERNS; i++)
- {
- song->patterns[i].patch = 0;
- }
- int a;
- for(i = 0; i < MAX_SONG_PATTERNS; i++)
- {
- song->patterns[a].events_length = 0;
- }
- return song;
- }
- typedef enum
- {
- MODE_SONG,
- MODE_LOOP,
- MODE_RECORD
- } PlayMode;
- typedef enum
- {
- SCREEN_PATTERN,
- SCREEN_SONG,
- SCREEN_PATCH
- } Screen;
- int current_scene = 0;
- int playing = 0;
- PlayMode current_mode = MODE_LOOP;
- Screen current_screen = SCREEN_PATTERN;
- Song *song;
- int pressed_pads = 0;
- int first_pressed_pad = 0;
- void clear_pattern(int pattern)
- {
- song->patterns[pattern].events_length = 0;
- }
- void record_event(int pattern, snd_seq_event_t event)
- {
- song->patterns[pattern].events[song->patterns[pattern].events_length++] = event;
- }
- int get_mask(int pad)
- {
- return 1 << pad;
- }
- void set_pad_pressed_state(int pad, int state)
- {
- int mask = get_mask(pad);
- if(state)
- {
- pressed_pads |= mask;
- }
- else
- {
- pressed_pads &= ~mask;
- }
- }
- void set_pad_pressed(int pad)
- {
- set_pad_pressed_state(pad, 1);
- }
- void clear_pad_pressed(int pad)
- {
- set_pad_pressed_state(pad, 0);
- }
- int get_pad_pressed(int pad)
- {
- int mask = get_mask(pad);
- return pressed_pads & mask;
- }
- int get_scene_pattern_mask(int scene)
- {
- return song->scene_pattern_masks[scene];
- }
- int get_current_pattern_mask()
- {
- return get_scene_pattern_mask(current_scene);
- }
- void set_scene_pattern_mask(int scene, int mask)
- {
- song->scene_pattern_masks[scene] = mask;
- }
- void set_current_pattern_mask(int mask)
- {
- set_scene_pattern_mask(current_scene, mask);
- }
- void set_pattern_enabled_state(int pattern, int state)
- {
- int mask = get_mask(pattern);
- if(state)
- {
- set_current_pattern_mask(get_current_pattern_mask() | mask);
- }
- else
- {
- set_current_pattern_mask(get_current_pattern_mask() & ~mask);
- }
- }
- void toggle_pattern_enabled_state(int pattern)
- {
- int mask = get_mask(pattern);
- set_current_pattern_mask(get_current_pattern_mask() ^ mask);
- }
- void set_pattern_enabled(int pattern)
- {
- set_pattern_enabled_state(pattern, 1);
- }
- void clear_pattern_enabled(int pattern)
- {
- set_pattern_enabled_state(pattern, 0);
- }
- int get_pattern_enabled(int pattern)
- {
- int mask = get_mask(pattern);
- return get_current_pattern_mask() & mask;
- }
- void solo_pressed_patterns()
- {
- set_current_pattern_mask(pressed_pads);
- }
- void erase_pressed_patterns()
- {
- int i;
- for(i = 0; i < MAX_SONG_PATTERNS; i++)
- {
- if(pressed_pads & (1 << i)) clear_pattern(i);
- }
- }
- void set_current_scene(int scene)
- {
- while(scene < 0) scene += MAX_SONG_SCENES;
- current_scene = scene % MAX_SONG_SCENES;
- }
- void increment_current_scene()
- {
- set_current_scene(current_scene + 1);
- }
- void decrement_current_scene()
- {
- set_current_scene(current_scene - 1);
- }
- int get_pattern_patch(int pattern)
- {
- return song->patterns[pattern].patch;
- }
- void change_program(int channel, int program);
- void set_pattern_patch(int pattern, int patch)
- {
- while(patch < 0) patch += MAX_SONG_PATCHES;
- song->patterns[pattern].patch = patch % MAX_SONG_PATCHES;
- change_program(pattern, patch);
- }
- void increment_pattern_patch(int pattern)
- {
- int patch = get_pattern_patch(pattern);
- set_pattern_patch(pattern, patch + 1);
- }
- void decrement_pattern_patch(int pattern)
- {
- int patch = get_pattern_patch(pattern);
- set_pattern_patch(pattern, patch - 1);
- }
- int get_first_selected_pattern()
- {
- int i;
- for(i = 0; i < MAX_SONG_PATTERNS; i++)
- {
- if(pressed_pads & (1 << i)) return i;
- }
- return -1;
- }
- void increment_first_selected_patch()
- {
- increment_pattern_patch(get_first_selected_pattern());
- }
- void decrement_first_selected_patch()
- {
- decrement_pattern_patch(get_first_selected_pattern());
- }
- int get_first_selected_patch()
- {
- return get_pattern_patch(get_first_selected_pattern());
- }
- int set_selected_patterns_patch(int patch)
- {
- int i;
- for(i = 0; i < MAX_SONG_PATTERNS; i++)
- {
- if(pressed_pads & (1 << i)) set_pattern_patch(i, patch);
- }
- }
- void queue_queue();
- void clear_queue();
- snd_seq_tick_time_t get_tick();
- snd_seq_tick_time_t tick = 0;
- int toggle_playing() // make all these functions cleaner and just simply return ints
- {
- playing = !playing;
- clear_queue();
- if(playing)
- {
- tick = get_tick();
- queue_queue();
- }
- return playing;
- }
- int toggle_mode()
- {
- switch(current_mode)
- {
- case MODE_LOOP:
- current_mode = MODE_RECORD;
- break;
- case MODE_RECORD:
- current_mode = MODE_SONG;
- break;
- case MODE_SONG:
- current_mode = MODE_LOOP;
- break;
- }
- return current_mode;
- }
- snd_seq_t *seq_handle;
- int launch_key_in_port_1_id;
- int launch_key_in_port_2_id;
- int midi_out_port_id;
- int launch_key_out_port_2_id;
- int queue_id;
- void pulse_metronome(snd_seq_tick_time_t tick, int color, int sound, int percussion_note);
- int new_led_color(int red, int green);
- snd_seq_tick_time_t next_tick;
- void queue_queue()
- {
- snd_seq_tick_time_t end_tick = song->ticks_per_beat;
- end_tick *= song->beats_per_measure;
- end_tick *= song->measures_per_pattern;
- next_tick = tick + end_tick;
- snd_seq_event_t event;
- snd_seq_ev_clear(&event);
- event.type = SND_SEQ_EVENT_ECHO;
- snd_seq_ev_schedule_tick(&event, queue_id, 0, next_tick);
- snd_seq_ev_set_dest(&event, snd_seq_client_id(seq_handle), launch_key_in_port_1_id);
- snd_seq_event_output_direct(seq_handle, &event);
- int mask = get_current_pattern_mask();
- int count = 0;
- int i;
- for(i = 0; i < MAX_SONG_PATTERNS; i++)
- {
- if(mask & (1 << i))
- {
- int note_on_events_tick[128];
- int note_on_events_quantized[128];
- int a;
- for(a = 0; a < 128; a++)
- {
- note_on_events_tick[a] = -1;
- }
- for(a = 0; a < song->patterns[i].events_length; a++)
- {
- count++;
- event = song->patterns[i].events[a];
- snd_seq_tick_time_t dt = event.time.tick;
- if(event.type == SND_SEQ_EVENT_NOTEON)
- {
- note_on_events_tick[event.data.note.note] = dt;
- int q = song->quantize;
- q = 1 << q;
- dt += q / 2;
- dt /= q;
- dt *= q;
- note_on_events_quantized[event.data.note.note] = dt;
- }
- else if(event.type == SND_SEQ_EVENT_NOTEOFF)
- {
- if(note_on_events_tick[event.data.note.note] != -1)
- {
- int length = dt - note_on_events_tick[event.data.note.note];
- dt = note_on_events_quantized[event.data.note.note] + length;
- note_on_events_tick[event.data.note.note] = -1;
- }
- }
- snd_seq_ev_schedule_tick(&event, queue_id, 0, tick + dt);
- snd_seq_ev_set_source(&event, midi_out_port_id);
- snd_seq_ev_set_subs(&event);
- snd_seq_event_output_direct(seq_handle, &event);
- }
- change_program(i, song->patterns[i].patch);
- }
- }
- for(i = 0; i < song->measures_per_pattern; i++)
- {
- int a;
- for(a = 0; a < song->beats_per_measure; a++)
- {
- int note;
- if(i == 0 && a == 0)
- {
- note = 75;
- }
- else if(a == 0)
- {
- note = 76;
- }
- else
- {
- note = 77;
- }
- int beat = a + i * song->beats_per_measure;
- pulse_metronome(tick + beat * song->ticks_per_beat, a == 0 ? 0 : (i == song->measures_per_pattern - 1 ? 2 : 1), count == 0, note);
- }
- }
- }
- snd_seq_tick_time_t get_tick()
- {
- snd_seq_queue_status_t *status;
- snd_seq_tick_time_t current_tick;
- snd_seq_queue_status_malloc(&status);
- snd_seq_get_queue_status(seq_handle, queue_id, status);
- current_tick = snd_seq_queue_status_get_tick_time(status);
- snd_seq_queue_status_free(status);
- return current_tick;
- }
- void set_tempo(int bpm, int ppq)
- {
- snd_seq_queue_tempo_t *queue_tempo;
- snd_seq_queue_tempo_malloc(&queue_tempo);
- int tempo = (int)(6e7 / ((double)bpm * (double)ppq) * (double)ppq);
- snd_seq_queue_tempo_set_tempo(queue_tempo, tempo);
- snd_seq_queue_tempo_set_ppq(queue_tempo, ppq);
- snd_seq_set_queue_tempo(seq_handle, queue_id, queue_tempo);
- snd_seq_queue_tempo_free(queue_tempo);
- }
- void change_tempo(int bpm)
- {
- song->bpm = bpm;
- set_tempo(song->bpm, song->ticks_per_beat);
- }
- int new_queue()
- {
- int id = snd_seq_alloc_queue(seq_handle);
- snd_seq_set_client_pool_output(seq_handle, MAX_QUEUE_SIZE);
- return id;
- }
- void init_queue()
- {
- queue_id = new_queue();
- set_tempo(song->bpm, song->ticks_per_beat);
- snd_seq_start_queue(seq_handle, queue_id, NULL);
- snd_seq_drain_output(seq_handle);
- }
- void clear_queue()
- {
- snd_seq_remove_events_t *remove_ev;
- snd_seq_remove_events_malloc(&remove_ev);
- snd_seq_remove_events_set_queue(remove_ev, queue_id);
- snd_seq_remove_events_set_condition(remove_ev, SND_SEQ_REMOVE_OUTPUT | SND_SEQ_REMOVE_IGNORE_OFF);
- snd_seq_remove_events(seq_handle, remove_ev);
- snd_seq_remove_events_free(remove_ev);
- }
- snd_seq_t *open_client()
- {
- snd_seq_t *handle;
- if(snd_seq_open(&handle, "default", SND_SEQ_OPEN_DUPLEX, 0) < 0)
- {
- fprintf(stderr, "Error opening ALSA sequencer.\n");
- return -1;
- }
- snd_seq_set_client_name(handle, ALSA_CLIENT_NAME);
- return handle;
- }
- int new_port(snd_seq_t *handle, char *name, int flags)
- {
- int id = snd_seq_create_simple_port(handle, name, flags, SND_SEQ_PORT_TYPE_APPLICATION);
- if(id < 0)
- {
- fprintf(stderr, "Error creating sequencer port.\n");
- return -1;
- }
- return id;
- }
- int new_in_port(snd_seq_t *handle, char *name)
- {
- return new_port(handle, name, SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_SUBS_WRITE);
- }
- int new_out_port(snd_seq_t *handle, char *name)
- {
- return new_port(handle, name, SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_SUBS_READ);
- }
- int init_alsa()
- {
- if((seq_handle = open_client()) < 0) return -1;
- if((launch_key_in_port_1_id = new_in_port(seq_handle, "LaunchKey MIDI 1")) < 0) return -1;
- if((launch_key_in_port_2_id = new_in_port(seq_handle, "LaunchKey MIDI 2")) < 0) return -1;
- if((midi_out_port_id = new_out_port(seq_handle, "MIDI Out")) < 0) return -1;
- if((launch_key_out_port_2_id = new_out_port(seq_handle, "LaunchKey MIDI 2")) < 0) return -1;
- return 0;
- }
- void change_program(int channel, int program)
- {
- snd_seq_event_t event;
- snd_seq_ev_clear(&event);
- snd_seq_ev_set_pgmchange(&event, channel, program);
- snd_seq_ev_set_subs(&event);
- snd_seq_ev_set_source(&event, midi_out_port_id);
- snd_seq_ev_set_direct(&event);
- snd_seq_event_output_direct(seq_handle, &event);
- }
- int control_note_queue = 0;
- void play_note(int note, int velocity, int channel, int ticks, int tick)
- {
- snd_seq_event_t event;
- snd_seq_ev_clear(&event);
- snd_seq_ev_set_note(&event, channel, note, velocity, ticks);
- snd_seq_ev_set_subs(&event);
- snd_seq_ev_set_source(&event, midi_out_port_id);
- snd_seq_ev_schedule_tick(&event, queue_id, 0, tick);
- snd_seq_event_output_direct(seq_handle, &event);
- }
- void send_control_noteon_with_velocity(int note, int velocity)
- {
- snd_seq_event_t event;
- snd_seq_ev_clear(&event);
- snd_seq_ev_set_noteon(&event, 0, note, velocity);
- snd_seq_ev_set_subs(&event);
- snd_seq_ev_set_source(&event, launch_key_out_port_2_id);
- if(control_note_queue)
- {
- snd_seq_ev_schedule_tick(&event, queue_id, 0, control_note_queue);
- control_note_queue = 0;
- }
- else
- {
- snd_seq_ev_set_direct(&event);
- }
- snd_seq_event_output_direct(seq_handle, &event);
- }
- void send_control_noteon(int note)
- {
- send_control_noteon_with_velocity(note, 127);
- }
- void send_control_noteoff(int note)
- {
- snd_seq_event_t event;
- snd_seq_ev_clear(&event);
- snd_seq_ev_set_noteoff(&event, 0, note, 0);
- snd_seq_ev_set_subs(&event);
- snd_seq_ev_set_direct(&event);
- snd_seq_ev_set_source(&event, launch_key_out_port_2_id);
- snd_seq_event_output_direct(seq_handle, &event);
- }
- void enable_in_control()
- {
- send_control_noteon(12);
- }
- void disable_in_control()
- {
- send_control_noteon_with_velocity(12, 0);
- }
- void show_in_control()
- {
- send_control_noteon(10);
- }
- void hide_in_control()
- {
- send_control_noteon_with_velocity(10, 0);
- }
- int led_id_to_pad_id(led_id)
- {
- switch(led_id)
- {
- case 0:
- return 96;
- case 1:
- return 97;
- case 2:
- return 98;
- case 3:
- return 99;
- case 4:
- return 100;
- case 5:
- return 101;
- case 6:
- return 102;
- case 7:
- return 103;
- case 8:
- return 112;
- case 9:
- return 113;
- case 10:
- return 114;
- case 11:
- return 115;
- case 12:
- return 116;
- case 13:
- return 117;
- case 14:
- return 118;
- case 15:
- return 119;
- case 16:
- return 104;
- case 17:
- return 120;
- default:
- return 0;
- }
- }
- int new_led_color(int red, int green)
- {
- return red + (green << 4);
- }
- void set_led(int led_id, int color)
- {
- int pad_id = led_id_to_pad_id(led_id);
- send_control_noteon_with_velocity(pad_id, color);
- }
- int get_led_id_by_xy(int x, int y)
- {
- if(x < 0 || y < 0 || x > 8 || y > 1) return;
- if(x == 8)
- {
- return y ? 17 : 16;
- }
- else
- {
- return x + y * 8;
- }
- }
- void set_led_xy(int x, int y, int color)
- {
- int led_id = get_led_id_by_xy(x, y);
- set_led(led_id, color);
- }
- void set_led_rect(int x, int y, int w, int h, int color)
- {
- int ox = x;
- int oy = y;
- int mx = x+w;
- int my = y+h;
- for(x=ox; x<mx; x++)
- {
- for(y=oy; y<my; y++)
- {
- set_led_xy(x, y, color);
- }
- }
- }
- void set_led_row(int y, int color)
- {
- set_led_rect(0, y, 9, 1, color);
- }
- void set_led_column(int x, int color)
- {
- set_led_rect(x, 0, 1, 2, color);
- }
- void led_fill(int color)
- {
- set_led_rect(0, 0, 9, 2, color);
- }
- void led_clear()
- {
- led_fill(0);
- }
- void led_test()
- {
- set_led_column(0, new_led_color(2, 0));
- set_led_column(1, new_led_color(3, 0));
- set_led_column(2, new_led_color(3, 1));
- set_led_column(3, new_led_color(3, 2));
- set_led_column(4, new_led_color(3, 3));
- set_led_column(5, new_led_color(2, 3));
- set_led_column(6, new_led_color(1, 3));
- set_led_column(7, new_led_color(0, 3));
- set_led_column(8, new_led_color(0, 2));
- }
- void led_test_2()
- {
- set_led_column(8, new_led_color(2, 0));
- set_led_column(7, new_led_color(3, 0));
- set_led_column(6, new_led_color(3, 1));
- set_led_column(5, new_led_color(3, 2));
- set_led_column(4, new_led_color(3, 3));
- set_led_column(3, new_led_color(2, 3));
- set_led_column(2, new_led_color(1, 3));
- set_led_column(1, new_led_color(0, 3));
- set_led_column(0, new_led_color(0, 2));
- }
- void led_test_3()
- {
- set_led_row(0, new_led_color(3, 0));
- set_led_row(1, new_led_color(0, 3));
- }
- void led_test_4()
- {
- set_led_xy(0, 0, new_led_color(0, 0));
- set_led_xy(1, 0, new_led_color(0, 1));
- set_led_xy(2, 0, new_led_color(0, 2));
- set_led_xy(3, 0, new_led_color(0, 3));
- set_led_xy(0, 1, new_led_color(0, 0));
- set_led_xy(1, 1, new_led_color(1, 1));
- set_led_xy(2, 1, new_led_color(2, 2));
- set_led_xy(3, 1, new_led_color(3, 3));
- set_led_xy(4, 0, new_led_color(0, 0));
- set_led_xy(5, 0, new_led_color(1, 0));
- set_led_xy(6, 0, new_led_color(2, 0));
- set_led_xy(7, 0, new_led_color(3, 0));
- set_led_xy(4, 1, new_led_color(4, 1));
- set_led_xy(5, 1, new_led_color(1, 4));
- set_led_xy(6, 1, new_led_color(3, 1));
- set_led_xy(7, 1, new_led_color(1, 3));
- set_led_xy(8, 0, new_led_color(3, 2));
- set_led_xy(8, 1, new_led_color(2, 3));
- }
- void pulse_metronome(snd_seq_tick_time_t tick, int color, int sound, int percussion_note)
- {
- int i = 0;
- int brightness = 4;
- while(brightness)
- {
- brightness--;
- int c;
- if(color == 0)
- {
- c = new_led_color(brightness, 0);
- }
- else if(color == 1)
- {
- c = new_led_color(0, brightness);
- }
- else if(color == 2)
- {
- c = new_led_color(brightness, brightness);
- }
- control_note_queue = tick + i * (song->ticks_per_beat / METRONOME_PULSE_FRAMES_PER_BEAT);
- set_led_xy(8, 0, c);
- i++;
- }
- if(sound) play_note(percussion_note, 63, 9, 10, tick);
- }
- int get_pad_x(int pad)
- {
- if(pad < 16)
- {
- return pad % 8;
- }
- else
- {
- return 8;
- }
- }
- int get_pad_y(int pad)
- {
- if(pad < 16)
- {
- return pad / 8;
- }
- else if(pad == 16)
- {
- return 0;
- }
- else if(pad == 17)
- {
- return 1;
- }
- }
- int set_digit(number, base, digit, replacement_value)
- {
- int i;
- for(i = 0; i < digit; i++)
- {
- replacement_value *= base;
- }
- int place_holder_value = number;
- for(i = 0; i < digit; i++)
- {
- place_holder_value /= base;
- }
- place_holder_value %= base;
- for(i = 0; i < digit; i++)
- {
- place_holder_value *= base;
- }
- number -= place_holder_value;
- number += replacement_value;
- return number;
- }
- void display_number(number)
- {
- led_clear();
- int digit_0 = number % 8;
- number /= 8;
- int digit_1 = number % 8;
- number /= 8;
- int digit_2 = number % 2;
- set_led_xy(digit_0, 0, new_led_color(3, 0));
- set_led_xy(digit_1, 1, new_led_color(3, 3));
- set_led_xy(8, digit_2, new_led_color(1, 3));
- }
- int replace_number_screen_value(num)
- {
- if(current_screen == SCREEN_SONG)
- {
- current_scene = num;
- }
- else if(current_screen == SCREEN_PATCH)
- {
- set_selected_patterns_patch(num);
- }
- display_number(num);
- }
- int get_number_screen_value()
- {
- int num;
- if(current_screen == SCREEN_SONG)
- {
- num = current_scene;
- }
- else if(current_screen == SCREEN_PATCH)
- {
- num = get_first_selected_patch();
- }
- return num;
- }
- void pattern_screen_update_play_button()
- {
- if(playing)
- {
- set_led(16, new_led_color(0, 3));
- }
- else
- {
- set_led(16, new_led_color(0, 0));
- }
- }
- void pattern_screen_update_mode_button()
- {
- switch(current_mode)
- {
- case MODE_SONG:
- set_led(17, new_led_color(0, 0));
- break;
- case MODE_LOOP:
- set_led(17, new_led_color(0, 3));
- break;
- case MODE_RECORD:
- set_led(17, new_led_color(3, 0));
- break;
- }
- }
- void pattern_screen_update_pad(int pad)
- {
- if(pad < 16)
- {
- if(get_pad_pressed(pad))
- {
- set_led(pad, new_led_color(3, 0));
- }
- else
- {
- if(get_pattern_enabled(pad))
- {
- if(song->patterns[pad].events_length)
- {
- set_led(pad, new_led_color(3, 3));
- }
- else
- {
- set_led(pad, new_led_color(0, 3));
- }
- }
- else
- {
- if(song->patterns[pad].events_length)
- {
- set_led(pad, new_led_color(0, 0));
- }
- else
- {
- set_led(pad, new_led_color(0, 0));
- }
- }
- }
- }
- else if(pad == 16)
- {
- pattern_screen_update_play_button();
- }
- else if(pad == 17)
- {
- pattern_screen_update_mode_button();
- }
- }
- void pattern_screen_update_pads()
- {
- int i;
- for(i = 0; i < 18; i++)
- {
- pattern_screen_update_pad(i);
- }
- }
- void pattern_screen()
- {
- current_screen = SCREEN_PATTERN;
- pattern_screen_update_pads();
- }
- void patch_screen()
- {
- current_screen = SCREEN_PATCH;
- first_pressed_pad = get_first_selected_pattern();
- display_number(get_first_selected_patch());
- }
- void song_screen()
- {
- current_screen = SCREEN_SONG;
- display_number(current_scene);
- }
- void init_screen()
- {
- enable_in_control();
- pattern_screen();
- }
- void play_press()
- {
- switch(current_screen)
- {
- case SCREEN_PATTERN:
- if(pressed_pads)
- {
- solo_pressed_patterns();
- pressed_pads = 0;
- pattern_screen_update_pads();
- }
- else
- {
- toggle_playing();
- pattern_screen_update_play_button();
- }
- break;
- case SCREEN_SONG:
- case SCREEN_PATCH: ;
- int num = get_number_screen_value();
- num = set_digit(num, 8, 2, 0);
- replace_number_screen_value(num);
- break;
- }
- }
- void play_release()
- {
- }
- void mode_press()
- {
- switch(current_screen)
- {
- case SCREEN_PATTERN:
- if(pressed_pads)
- {
- erase_pressed_patterns();
- pressed_pads = 0;
- pattern_screen_update_pads();
- }
- else
- {
- toggle_mode();
- pattern_screen_update_mode_button();
- }
- break;
- case SCREEN_SONG:
- case SCREEN_PATCH: ;
- int num = get_number_screen_value();
- num = set_digit(num, 8, 2, 1);
- replace_number_screen_value(num);
- break;
- }
- }
- void mode_release()
- {
- }
- void pad_press(int pad)
- {
- switch(current_screen)
- {
- case SCREEN_PATTERN:
- set_pad_pressed(pad);
- pattern_screen_update_pad(pad);
- break;
- case SCREEN_SONG:
- case SCREEN_PATCH: ;
- int x = get_pad_x(pad);
- int y = get_pad_y(pad);
- int num = get_number_screen_value();
- num = set_digit(num, 8, y, x);
- replace_number_screen_value(num);
- break;
- }
- }
- void pad_release(int pad)
- {
- switch(current_screen)
- {
- case SCREEN_PATTERN:
- if(get_pad_pressed(pad))
- {
- clear_pad_pressed(pad);
- toggle_pattern_enabled_state(pad);
- pattern_screen_update_pad(pad);
- }
- break;
- case SCREEN_SONG:
- break;
- case SCREEN_PATCH: ;
- if(pad == first_pressed_pad)
- {
- pressed_pads = 0;
- pattern_screen();
- }
- break;
- }
- }
- void arrow_presed(int up)
- {
- switch(current_screen)
- {
- case SCREEN_PATTERN:
- if(pressed_pads)
- {
- patch_screen();
- int num = get_number_screen_value();
- if(up)
- {
- num = (num + 1) % MAX_SONG_PATCHES;
- }
- else
- {
- num--;
- while(num < 0) num += MAX_SONG_PATCHES;
- }
- replace_number_screen_value(num);
- }
- else
- {
- if(up)
- {
- increment_current_scene();
- }
- else
- {
- decrement_current_scene();
- }
- song_screen();
- }
- break;
- case SCREEN_SONG:
- break;
- case SCREEN_PATCH: ;
- int num = get_number_screen_value();
- if(up)
- {
- num = (num + 1) % MAX_SONG_PATCHES;
- }
- else
- {
- num--;
- while(num < 0) num += MAX_SONG_PATCHES;
- }
- replace_number_screen_value(num);
- break;
- }
- }
- void left()
- {
- arrow_presed(0);
- }
- void right()
- {
- arrow_presed(1);
- }
- void up()
- {
- right();
- }
- void down()
- {
- left();
- }
- void horizontal_release()
- {
- switch(current_screen)
- {
- case SCREEN_PATTERN:
- case SCREEN_PATCH:
- break;
- case SCREEN_SONG: ;
- pressed_pads = 0;
- pattern_screen();
- break;
- }
- }
- void vertical_release()
- {
- horizontal_release();
- }
- void pass_event(snd_seq_event_t *event)
- {
- snd_seq_ev_set_subs(event);
- snd_seq_ev_set_direct(event);
- snd_seq_ev_set_source(event, midi_out_port_id);
- snd_seq_event_output_direct(seq_handle, event);
- if(current_mode == MODE_RECORD)
- {
- int chan = event->data.note.channel;
- if(!playing)
- {
- toggle_playing();
- pattern_screen_update_play_button();
- }
- snd_seq_event_t e = *event;
- snd_seq_tick_time_t dt = get_tick() - tick;
- e.time.tick = dt;
- record_event(chan, e);
- if(current_screen == SCREEN_PATTERN)
- {
- set_pattern_enabled(chan);
- pattern_screen_update_pad(chan);
- }
- }
- }
- void handle_event(snd_seq_event_t *event)
- {
- int is_port_1 = event->dest.port == launch_key_in_port_1_id ? 1 : 0;
- int is_port_2 = event->dest.port == launch_key_in_port_2_id ? 1 : 0;
- switch(event->type)
- {
- case SND_SEQ_EVENT_PORT_SUBSCRIBED:
- case SND_SEQ_EVENT_PORT_CHANGE:
- case SND_SEQ_EVENT_CLIENT_START:
- case SND_SEQ_EVENT_CLIENT_CHANGE:
- init_screen();
- break;
- case SND_SEQ_EVENT_ECHO:
- if(current_mode == MODE_SONG)
- {
- increment_current_scene();
- if(current_screen == SCREEN_PATTERN)
- {
- pattern_screen_update_pads();
- }
- }
- tick = next_tick;
- queue_queue();
- break;
- case SND_SEQ_EVENT_NOTEON:
- if(is_port_2)
- {
- switch(event->data.note.note)
- {
- case 10:
- pattern_screen();
- break;
- case 104:
- play_press();
- break;
- case 120:
- mode_press();
- break;
- case 96:
- pad_press(0);
- break;
- case 97:
- pad_press(1);
- break;
- case 98:
- pad_press(2);
- break;
- case 99:
- pad_press(3);
- break;
- case 100:
- pad_press(4);
- break;
- case 101:
- pad_press(5);
- break;
- case 102:
- pad_press(6);
- break;
- case 103:
- pad_press(7);
- break;
- case 112:
- pad_press(8);
- break;
- case 113:
- pad_press(9);
- break;
- case 114:
- pad_press(10);
- break;
- case 115:
- pad_press(11);
- break;
- case 116:
- pad_press(12);
- break;
- case 117:
- pad_press(13);
- break;
- case 118:
- pad_press(14);
- break;
- case 119:
- pad_press(15);
- break;
- }
- }
- else
- {
- pass_event(event);
- }
- break;
- case SND_SEQ_EVENT_NOTEOFF:
- if(is_port_2)
- {
- switch(event->data.note.note)
- {
- case 104:
- play_release();
- break;
- case 120:
- mode_release();
- break;
- case 96:
- pad_release(0);
- break;
- case 97:
- pad_release(1);
- break;
- case 98:
- pad_release(2);
- break;
- case 99:
- pad_release(3);
- break;
- case 100:
- pad_release(4);
- break;
- case 101:
- pad_release(5);
- break;
- case 102:
- pad_release(6);
- break;
- case 103:
- pad_release(7);
- break;
- case 112:
- pad_release(8);
- break;
- case 113:
- pad_release(9);
- break;
- case 114:
- pad_release(10);
- break;
- case 115:
- pad_release(11);
- break;
- case 116:
- pad_release(12);
- break;
- case 117:
- pad_release(13);
- break;
- case 118:
- pad_release(14);
- break;
- case 119:
- pad_release(15);
- break;
- }
- }
- else
- {
- pass_event(event);
- }
- break;
- case SND_SEQ_EVENT_CONTROLLER:
- if(is_port_2)
- {
- switch(event->data.control.param)
- {
- case 27:
- song->quantize = event->data.control.value / 16;
- break;
- case 28:
- change_tempo(event->data.control.value * 3 / 2 + 32);
- break;
- }
- if(event->data.control.value)
- {
- switch(event->data.control.param)
- {
- case 104:
- up();
- break;
- case 105:
- down();
- break;
- case 106:
- left();
- break;
- case 107:
- right();
- break;
- }
- }
- else
- {
- switch(event->data.control.param)
- {
- case 104:
- case 105:
- vertical_release();
- break;
- case 106:
- case 107:
- horizontal_release();
- break;
- }
- }
- }
- else
- {
- switch(event->data.control.param)
- {
- case 104:
- case 105:
- case 106:
- case 107:
- init_screen();
- break;
- }
- pass_event(event);
- }
- break;
- case SND_SEQ_EVENT_PITCHBEND:
- pass_event(event);
- break;
- }
- }
- void sigterm_exit(int sig)
- {
- printf("Cleaning up...\n");
- sleep(1);
- snd_seq_stop_queue(seq_handle, queue_id, NULL);
- snd_seq_free_queue(seq_handle, queue_id);
- exit(0);
- }
- int main(int argc, char *argv[])
- {
- if(init_alsa() < 0)
- {
- fprintf(stderr, "Error initializing.\n");
- exit(1);
- }
- song = new_song();
- init_queue();
- signal(SIGINT, sigterm_exit);
- signal(SIGTERM, sigterm_exit);
- int l1;
- int npfd = snd_seq_poll_descriptors_count(seq_handle, POLLIN);
- struct pollfd *pfd = (struct pollfd *)alloca(npfd * sizeof(struct pollfd));
- snd_seq_poll_descriptors(seq_handle, pfd, npfd, POLLIN);
- snd_seq_event_t *event;
- while(1)
- {
- if(poll(pfd, npfd, 100000) > 0)
- {
- for(l1 = 0; l1 < npfd; l1++)
- {
- if(pfd[l1].revents > 0)
- {
- do
- {
- snd_seq_event_input(seq_handle, &event);
- handle_event(event);
- snd_seq_free_event(event);
- } while(snd_seq_event_input_pending(seq_handle, 0) > 0);
- }
- }
- }
- }
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement