SG 3 سال پیش
والد
کامیت
ec854a77a2
3فایلهای تغییر یافته به همراه236 افزوده شده و 0 حذف شده
  1. 182 0
      view/tracker_view.c
  2. 29 0
      view/tracker_view.h
  3. 25 0
      zero_tracker.c

+ 182 - 0
view/tracker_view.c

@@ -0,0 +1,182 @@
+#include "tracker_view.h"
+#include <gui/elements.h>
+#include <furi.h>
+
+typedef struct {
+    const Song* song;
+    uint8_t order_list_index;
+    uint8_t row;
+} TrackerViewModel;
+
+struct TrackerView {
+    View* view;
+    void* back_context;
+    TrackerViewCallback back_callback;
+};
+
+static Channel* get_current_channel(TrackerViewModel* model) {
+    uint8_t channel_id = 0;
+    uint8_t pattern_id = model->song->order_list[model->order_list_index];
+    Pattern* pattern = &model->song->patterns[pattern_id];
+    return &pattern->channels[channel_id];
+}
+
+static const char* get_note_from_id(uint8_t note) {
+#define NOTE_COUNT 12
+    const char* notes[NOTE_COUNT] = {
+        "C ",
+        "C#",
+        "D ",
+        "D#",
+        "E ",
+        "F ",
+        "F#",
+        "G ",
+        "G#",
+        "A ",
+        "A#",
+        "B ",
+    };
+    return notes[(note) % NOTE_COUNT];
+#undef NOTE_COUNT
+}
+
+static uint8_t get_octave_from_id(uint8_t note) {
+    return ((note) / 12) + 2;
+}
+
+static uint8_t get_first_row_id(uint8_t row) {
+    return (row / 10) * 10;
+}
+
+static void
+    draw_row(Canvas* canvas, uint8_t i, Channel* channel, uint8_t row, FuriString* buffer) {
+    uint8_t x = 12 * (i + 1);
+    uint8_t first_row_id = get_first_row_id(row);
+    uint8_t current_row_id = first_row_id + i;
+
+    if((current_row_id) >= 64) {
+        return;
+    }
+
+    Row current_row = channel->rows[current_row_id];
+    uint8_t note = current_row & ROW_NOTE_MASK;
+    uint8_t effect = (current_row >> 6) & ROW_EFFECT_MASK;
+    uint8_t data = (current_row >> 10) & ROW_EFFECT_DATA_MASK;
+
+    if(current_row_id == row) {
+        canvas_set_color(canvas, ColorBlack);
+        canvas_draw_line(canvas, x - 9, 1, x - 9, 62);
+        canvas_draw_box(canvas, x - 8, 0, 9, 64);
+        canvas_draw_line(canvas, x + 1, 1, x + 1, 62);
+        canvas_set_color(canvas, ColorWhite);
+    }
+
+    furi_string_printf(buffer, "%02X", current_row_id);
+    canvas_draw_str(canvas, x, 61, furi_string_get_cstr(buffer));
+
+    if(note > 0 && note < NOTE_OFF) {
+        furi_string_printf(
+            buffer, "%s%d", get_note_from_id(note - 1), get_octave_from_id(note - 1));
+        canvas_draw_str(canvas, x, 44, furi_string_get_cstr(buffer));
+    } else if(note == NOTE_OFF) {
+        canvas_draw_str(canvas, x, 44, "OFF");
+    } else {
+        canvas_draw_str(canvas, x, 44, "---");
+    }
+
+    if(effect == 0 && data == 0) {
+        canvas_draw_str(canvas, x, 21, "-");
+        canvas_draw_str(canvas, x, 12, "--");
+    } else {
+        furi_string_printf(buffer, "%X", effect);
+        canvas_draw_str(canvas, x, 21, furi_string_get_cstr(buffer));
+
+        if(effect == EffectArpeggio || effect == EffectVibrato) {
+            uint8_t data_x = EFFECT_DATA_GET_X(data);
+            uint8_t data_y = EFFECT_DATA_GET_Y(data);
+            furi_string_printf(buffer, "%d%d", data_x, data_y);
+            canvas_draw_str(canvas, x, 12, furi_string_get_cstr(buffer));
+        } else {
+            furi_string_printf(buffer, "%02X", data);
+            canvas_draw_str(canvas, x, 12, furi_string_get_cstr(buffer));
+        }
+    }
+
+    if(current_row_id == row) {
+        canvas_set_color(canvas, ColorBlack);
+    }
+}
+
+static void tracker_view_draw_callback(Canvas* canvas, void* _model) {
+    TrackerViewModel* model = _model;
+    if(model->song == NULL) {
+        return;
+    }
+
+    canvas_set_font_direction(canvas, CanvasDirectionBottomToTop);
+    canvas_set_font(canvas, FontKeyboard);
+
+    Channel* channel = get_current_channel(model);
+    FuriString* buffer = furi_string_alloc();
+
+    for(uint8_t i = 0; i < 10; i++) {
+        draw_row(canvas, i, channel, model->row, buffer);
+    }
+    furi_string_free(buffer);
+}
+
+static bool tracker_view_input_callback(InputEvent* event, void* context) {
+    TrackerView* tracker_view = context;
+
+    if(tracker_view->back_callback) {
+        if(event->type == InputTypeShort && event->key == InputKeyBack) {
+            tracker_view->back_callback(tracker_view->back_context);
+            return true;
+        }
+    }
+    return false;
+}
+
+TrackerView* tracker_view_alloc() {
+    TrackerView* tracker_view = malloc(sizeof(TrackerView));
+    tracker_view->view = view_alloc();
+    view_allocate_model(tracker_view->view, ViewModelTypeLocking, sizeof(TrackerViewModel));
+    view_set_context(tracker_view->view, tracker_view);
+    view_set_draw_callback(tracker_view->view, (ViewDrawCallback)tracker_view_draw_callback);
+    view_set_input_callback(tracker_view->view, (ViewInputCallback)tracker_view_input_callback);
+    return tracker_view;
+}
+
+void tracker_view_free(TrackerView* tracker_view) {
+    view_free(tracker_view->view);
+    free(tracker_view);
+}
+
+View* tracker_view_get_view(TrackerView* tracker_view) {
+    return tracker_view->view;
+}
+
+void tracker_view_set_back_callback(
+    TrackerView* tracker_view,
+    TrackerViewCallback callback,
+    void* context) {
+    tracker_view->back_callback = callback;
+    tracker_view->back_context = context;
+}
+
+void tracker_view_set_song(TrackerView* tracker_view, const Song* song) {
+    with_view_model(
+        tracker_view->view, TrackerViewModel * model, { model->song = song; }, true);
+}
+
+void tracker_view_set_position(TrackerView* tracker_view, uint8_t order_list_index, uint8_t row) {
+    with_view_model(
+        tracker_view->view,
+        TrackerViewModel * model,
+        {
+            model->order_list_index = order_list_index;
+            model->row = row;
+        },
+        true);
+}

+ 29 - 0
view/tracker_view.h

@@ -0,0 +1,29 @@
+#include <gui/view.h>
+#include "../tracker_engine/tracker.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct TrackerView TrackerView;
+
+TrackerView* tracker_view_alloc();
+
+void tracker_view_free(TrackerView* tracker_view);
+
+View* tracker_view_get_view(TrackerView* tracker_view);
+
+typedef void (*TrackerViewCallback)(void* context);
+
+void tracker_view_set_back_callback(
+    TrackerView* tracker_view,
+    TrackerViewCallback callback,
+    void* context);
+
+void tracker_view_set_song(TrackerView* tracker_view, const Song* song);
+
+void tracker_view_set_position(TrackerView* tracker_view, uint8_t order_list_index, uint8_t row);
+
+#ifdef __cplusplus
+}
+#endif

+ 25 - 0
zero_tracker.c

@@ -1,6 +1,10 @@
 #include <furi.h>
+#include <gui/gui.h>
+#include <gui/view_dispatcher.h>
+#include <notification/notification_messages.h>
 #include "zero_tracker.h"
 #include "tracker_engine/tracker.h"
+#include "view/tracker_view.h"
 
 // Channel p_0_channels[] = {
 //     {
@@ -479,6 +483,17 @@ void tracker_message(TrackerMessage message, void* context) {
 int32_t zero_tracker_app(void* p) {
     UNUSED(p);
 
+    NotificationApp* notification = furi_record_open(RECORD_NOTIFICATION);
+    notification_message(notification, &sequence_display_backlight_enforce_on);
+
+    Gui* gui = furi_record_open(RECORD_GUI);
+    ViewDispatcher* view_dispatcher = view_dispatcher_alloc();
+    TrackerView* tracker_view = tracker_view_alloc();
+    tracker_view_set_song(tracker_view, &song);
+    view_dispatcher_add_view(view_dispatcher, 0, tracker_view_get_view(tracker_view));
+    view_dispatcher_attach_to_gui(view_dispatcher, gui, ViewDispatcherTypeFullscreen);
+    view_dispatcher_switch_to_view(view_dispatcher, 0);
+
     FuriMessageQueue* queue = furi_message_queue_alloc(8, sizeof(TrackerMessage));
     Tracker* tracker = tracker_alloc();
     tracker_set_message_callback(tracker, tracker_message, queue);
@@ -493,6 +508,7 @@ int32_t zero_tracker_app(void* p) {
                 uint8_t order_list_index = message.data.position.order_list_index;
                 uint8_t row = message.data.position.row;
                 uint8_t pattern = song.order_list[order_list_index];
+                tracker_view_set_position(tracker_view, order_list_index, row);
                 FURI_LOG_I("Tracker", "O:%d P:%d R:%d", order_list_index, pattern, row);
             } else if(message.type == TrackerEndOfSong) {
                 FURI_LOG_I("Tracker", "End of song");
@@ -505,5 +521,14 @@ int32_t zero_tracker_app(void* p) {
     tracker_free(tracker);
     furi_message_queue_free(queue);
 
+    view_dispatcher_remove_view(view_dispatcher, 0);
+    tracker_view_free(tracker_view);
+    view_dispatcher_free(view_dispatcher);
+
+    notification_message(notification, &sequence_display_backlight_enforce_auto);
+
+    furi_record_close(RECORD_NOTIFICATION);
+    furi_record_close(RECORD_GUI);
+
     return 0;
 }