<commit_before>
#include "sequencer.h"

#define zoom_to_sequencer_x(sr)       (1 << (MAX_ZOOM - (sr)->zoom))

#define grid_to_sequencer_x(sr, gx)   (((gx) + (sr)->x)                        \
                                       * (1 << (MAX_ZOOM - (sr)->zoom)))

#define grid_to_sequencer_y(sr, gy)   ((sr)->layout->scale->offsets[           \
                                           ((gy) + (sr)->y)                    \
                                           % (sr)->layout->scale->num_notes    \
                                       ]                                       \
                                       + (sr)->layout->root_note               \
                                       + NUM_NOTES * (                         \
                                           ((gy) + (sr)->y)                    \
                                           / sr->layout->scale->num_notes      \
                                       ))

void sequence_init(Sequence* s, u8 channel)
{
    s->channel = channel;
    s->playhead = 0;
    s->flags = 0x00;

    for (u8 i = 0; i < SEQUENCE_LENGTH; i++)
    {
        s->notes[i].note_number = -1;
        s->notes[i].velocity = -1;
    }
}

void sequence_kill_note(Sequence* s)
{
    Note* n = &s->notes[s->playhead];
    if (n->note_number != -1)
    {
        hal_send_midi(
            USBSTANDALONE, NOTEOFF | s->channel,
            n->note_number, n->velocity);
    }
}

void sequencer_init(Sequencer* sr, Layout* l)
{
    sr->layout = l;
    sr->tempo = bpm_to_khz(DEFAULT_TEMPO);
    sr->timer = 0;
    sr->zoom = 0;
    sr->active_sequence = 0;
    sr->soloed_tracks = 0;
    sr->x = 0;
    sr->y = 0;
    sr->flags = 0x00;

    for (u8 i = 0; i < GRID_SIZE; i++)
    {
        sequence_init(&sr->sequences[i], i);
    }
}

void sequencer_set_octave(Sequencer* sr, u8 octave)
{
    sr->y = octave * sr->layout->scale->num_notes;
}

/*******************************************************************************
 * Drawing
 ******************************************************************************/

void sequencer_play_draw(Sequencer* sr)
{
    u8 play_index = LAST_PLAY;
    const u8* color = off_color;


    for (u8 i = 0; i < GRID_SIZE; i++)
    {
        Sequence* s = &sr->sequences[i];

        if (flag_is_set(sr->flags, ARM_HELD))
        {
            color = flag_is_set(s->flags, ARMED)
                ? number_colors[0]
                : off_color;
        }
        else if (flag_is_set(sr->flags, SELECT_HELD))
        {
            color = sr->active_sequence == i
                ? number_colors[2]
                : off_color;
        }
        else if (flag_is_set(sr->flags, MUTE_HELD))
        {
            color = flag_is_set(s->flags, MUTED)
                ? number_colors[0]
                : off_color;
        }
        else if (flag_is_set(sr->flags, SOLO_HELD))
        {
            color = flag_is_set(s->flags, SOLOED)
                ? number_colors[3]
                : off_color;
        }
        else
        {
            color = (flag_is_set(s->flags, PLAYING)
                     || flag_is_set(s->flags, QUEUED))
                ? sequence_colors[i]
                : off_color;
        }

        plot_pad(play_index, color);

        play_index -= PLAY_GAP;
    }
}

void sequencer_grid_draw(Sequencer* sr)
{
    u8 scale_deg = sr->y % sr->layout->scale->num_notes;
    u8 octave = sr->y / sr->layout->scale->num_notes;
    Sequence* s = &sr->sequences[sr->active_sequence];
    u8 index = FIRST_PAD;
    u8 zoom = zoom_to_sequencer_x(sr);

    for (u8 y = 0; y < GRID_SIZE; y++)
    {
        u8 note_number = sr->layout->scale->offsets[scale_deg]<commit_msg>The record arm button now indicates whether any sequences are actively recording.<commit_after>
#include "sequencer.h"

#define zoom_to_sequencer_x(sr)       (1 << (MAX_ZOOM - (sr)->zoom))

#define grid_to_sequencer_x(sr, gx)   (((gx) + (sr)->x)                        \
                                       * (1 << (MAX_ZOOM - (sr)->zoom)))

#define grid_to_sequencer_y(sr, gy)   ((sr)->layout->scale->offsets[           \
                                           ((gy) + (sr)->y)                    \
                                           % (sr)->layout->scale->num_notes    \
                                       ]                                       \
                                       + (sr)->layout->root_note               \
                                       + NUM_NOTES * (                         \
                                           ((gy) + (sr)->y)                    \
                                           / sr->layout->scale->num_notes      \
                                       ))

void sequence_init(Sequence* s, u8 channel)
{
    s->channel = channel;
    s->playhead = 0;
    s->flags = 0x00;

    for (u8 i = 0; i < SEQUENCE_LENGTH; i++)
    {
        s->notes[i].note_number = -1;
        s->notes[i].velocity = -1;
    }
}

void sequence_kill_note(Sequence* s)
{
    Note* n = &s->notes[s->playhead];
    if (n->note_number != -1)
    {
        hal_send_midi(
            USBSTANDALONE, NOTEOFF | s->channel,
            n->note_number, n->velocity);
    }
}

void sequencer_init(Sequencer* sr, Layout* l)
{
    sr->layout = l;
    sr->tempo = bpm_to_khz(DEFAULT_TEMPO);
    sr->timer = 0;
    sr->zoom = 0;
    sr->active_sequence = 0;
    sr->soloed_tracks = 0;
    sr->x = 0;
    sr->y = 0;
    sr->flags = 0x00;

    for (u8 i = 0; i < GRID_SIZE; i++)
    {
        sequence_init(&sr->sequences[i], i);
    }
}

void sequencer_set_octave(Sequencer* sr, u8 octave)
{
    sr->y = octave * sr->layout->scale->num_notes;
}

/*******************************************************************************
 * Drawing
 ******************************************************************************/

void sequencer_play_draw(Sequencer* sr)
{
    u8 play_index = LAST_PLAY;
    const u8* color = off_color;
    u8 recording_active = 0;

    for (u8 i = 0; i < GRID_SIZE; i++)
    {
        Sequence* s = &sr->sequences[i];

        if (flag_is_set(sr->flags, ARM_HELD))
        {
            color = flag_is_set(s->flags, ARMED)
                ? number_colors[0]
                : off_color;
        }
        else if (flag_is_set(sr->flags, SELECT_HELD))
        {
            color = sr->active_sequence == i
                ? number_colors[2]
                : off_color;
        }
        else if (flag_is_set(sr->flags, MUTE_HELD))
        {
            color = flag_is_set(s->flags, MUTED)
                ? number_colors[0]
                : off_color;
        }
        else if (flag_is_set(sr->flags, SOLO_HELD))
        {
            color = flag_is_set(s->flags, SOLOED)
                ? number_colors[3]
                : off_color;
        }
        else
        {
            color = (flag_is_set(s->flags, PLAYING)
                     || flag_is_set(s->flags, QUEUED))
                ? sequence_colors[i]
                : off_color;
        }

        recording_active |= flag_is_set(s->flags, ARMED)
            && (flag_is_set(s->flags, PLAYING)
                || flag_is_set(s->flags, QUEUED));
        plot_pad(play_index, color);

        play_index -= PLAY_GAP;
    }

    plot_pad(RECORD_ARM, recording_active ? number_colors[0] : off_color);
}

void sequencer_grid_draw(Sequencer* sr)
{
    u8 scale_deg = sr->y % sr->layout->scale->num_notes;
    u8 octave = sr->y / sr->layout->scale->num_notes;
    Sequence* s = &sr->sequences[sr->active_sequence];
    u8 index = FIRST_PAD;
    u8 zoom = zoom_to_sequencer_x(sr);

    for (u8 y = 0; y < GRID_SIZE; y++)
    {
        u8 note_number = sr->layout->scale->offsets[scale_deg]
{'fraction_non_alphanumeric': 0.16980641808496816, 'fraction_numerical': 0.010523580615824348, 'mean_word_length': 1.4299242424242424, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 136, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 36, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5852197', 'n_tokens_mistral': 2604, 'n_tokens_neox': 2410, 'n_words': 430}