Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion sources/Application/Model/Config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
#define MIDI_DEVICE_LEN 4

static const char *lineOutOptions[3] = {"HP Low", "HP High", "Line Level"};
static const char *midiDeviceList[MIDI_DEVICE_LEN] = {"OFF", "TRS", "USB",
static const char *midiDeviceList[MIDI_DEVICE_LEN] = {"Off", "TRS", "USB",
"TRS+USB"};
static const char *midiSendSync[2] = {"Off", "Send"};
static const char *midiClockSyncOptions[2] = {"Internal", "External"};
Expand Down
7 changes: 4 additions & 3 deletions sources/Application/Player/Player.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include "Application/Player/TablePlayback.h"
#include "Application/Utils/char.h"
#include "Application/Views/BaseClasses/ViewEvent.h"
#include "Foundation/Constants/SpecialCharacters.h"
#include "PlayerMixer.h"
#include "Services/Midi/MidiService.h"
#include "System/Console/n_assert.h"
Expand Down Expand Up @@ -277,14 +278,14 @@ const char *Player::GetLiveIndicator(int channel) {
case QM_PHRASESTART:
case QM_TICKSTART:
if (!IsChannelMuted(channel)) {
return (">");
return (char_indicator_position_s);
} else {
return ("-");
return (char_indicator_positionMuted_s);
}
break;
case QM_CHAINSTOP:
case QM_PHRASESTOP:
return "_";
return char_playback_pause_s;
break;
case QM_NONE:
break;
Expand Down
3 changes: 2 additions & 1 deletion sources/Application/Utils/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ add_library(application_utils
HexBuffers.cpp
char.cpp
fixed.cpp
stringutils.cpp
stringutils.cpp
DrawTools.cpp
)

target_link_libraries(application_utils PUBLIC
Expand Down
71 changes: 71 additions & 0 deletions sources/Application/Utils/DrawTools.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/*
* SPDX-License-Identifier: BSD-3-Clause
*
* Copyright (c) 2026 xiphonics, inc.
*
* This file is part of the picoTracker firmware
*/

#include "DrawTools.h"
#include "Application/AppWindow.h"
#include "Foundation/Constants/SpecialCharacters.h"

void DrawBorder(View &view, int x, int y, int width, int height,
const GUITextProperties &props, const char *charset) {
char line[SCREEN_WIDTH + 1];
memset(line, charset[4], width);
line[width] = 0;

line[0] = charset[0]; // top left
line[width - 1] = charset[1]; // top right
view.DrawString(x, y, line, props);

line[0] = charset[2]; // bottom left
line[width - 1] = charset[3]; // bottom right
view.DrawString(x, y + height - 1, line, props);

char vline[2] = {charset[5], 0}; // vertical line
for (int i = 1; i < height - 1; i++) {
view.DrawString(x, y + i, vline, props);
view.DrawString(x + width - 1, y + i, vline, props);
}
}

void DrawDoubleBorder(View &view, int x, int y, int width, int height,
const GUITextProperties &props) {
DrawBorder(view, x, y, width, height, props, char_border_double_charset);
}

void DrawSingleBorder(View &view, int x, int y, int width, int height,
const GUITextProperties &props) {
DrawBorder(view, x, y, width, height, props, char_border_single_charset);
}

void DrawScrollBar(View &view, int topIndex, int totalItems, int pageSize) {
if (totalItems <= pageSize) {
return; // no scrollbar needed
}

GUITextProperties props;
GUITextProperties inv;
inv.invert_ = true;
view.SetColor(CD_NORMAL);

// Thumb size represents the ratio of visible items to total items
int thumbSize = std::max(1, (pageSize * pageSize) / totalItems);

// Thumb position: map topIndex (0 to maxScroll) onto available scrollbar
// space
int maxScroll = totalItems - pageSize;
int availableSpace = pageSize - thumbSize;
int thumbPos = (topIndex * availableSpace) / maxScroll;

Trace::Error("%d total, %d thumb size, %d maxScroll, %d thumbPos", totalItems,
thumbSize, maxScroll, thumbPos);
for (int y = 0; y < pageSize; y++) {
bool thumb = y >= thumbPos && y < thumbPos + thumbSize;
view.DrawString(SCREEN_WIDTH - 1, 2 + y,
thumb ? char_block_full_s : char_border_single_vertical_s,
props);
}
}
17 changes: 17 additions & 0 deletions sources/Application/Utils/DrawTools.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/*
* SPDX-License-Identifier: BSD-3-Clause
*
* Copyright (c) 2026 xiphonics, inc.
*
* This file is part of the picoTracker firmware
*/

#include "Application/Views/BaseClasses/View.h"

void DrawBorder(View &view, int x, int y, int width, int height,
const GUITextProperties &props, const char *charset);
void DrawDoubleBorder(View &view, int x, int y, int width, int height,
const GUITextProperties &props);
void DrawSingleBorder(View &view, int x, int y, int width, int height,
const GUITextProperties &props);
void DrawScrollBar(View &view, int topIndex, int totalItems, int pageSize);
99 changes: 55 additions & 44 deletions sources/Application/Utils/HelpLegend.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,104 +15,115 @@
// chars
static char **getHelpLegend(FourCC command) {
static char *result[2];
result[1] = (char *)("bb at speed aa");

result[1] = (char *)"";

switch (command) {
case FourCC::InstrumentCommandKill:
result[0] = (char *)("KILl:--bb, stop playing");
result[1] = (char *)("after bb ticks");
result[0] = (char *)"KILl: --bb, stop playing";
result[1] = (char *)"after bb ticks";
break;
case FourCC::InstrumentCommandLoopOfset:
result[0] = (char *)("Loop OFset: Shift loop");
result[1] = (char *)("start & end values aaaa");
result[0] = (char *)"Loop OFset: aaaa shift";
result[1] = (char *)"loop start & end by aaaa";
break;
case FourCC::InstrumentCommandArpeggiator:
result[0] = (char *)("ARPeggio: Cycle through");
result[1] = (char *)("relative pitches");
result[0] = (char *)"ARPeggio: abcd, cycle";
result[1] = (char *)"rel. pitches +a,+b,+c,+d";
break;
case FourCC::InstrumentCommandVolume:
result[0] = (char *)("VOLume:aabb, reach volume");
result[0] = (char *)"VOLume: aabb, approach";
result[1] = (char *)"volume bb at speed aa";
break;
case FourCC::InstrumentCommandVelocity:
result[0] = (char *)("VELocity:--bb,");
result[1] = (char *)("MIDI velocity");
result[0] = (char *)"VELocity: --bb, send MIDI";
result[1] = (char *)"velocity bb";
break;
case FourCC::InstrumentCommandPitchSlide:
result[0] = (char *)("Pitch SLide:aabb, to pitch");
result[0] = (char *)"Pitch SLide: aabb, slide";
result[1] = (char *)"to pitch bb at speed aa";
break;
case FourCC::InstrumentCommandHop:
result[0] = (char *)("Hop:aabb, hop to bb");
result[1] = (char *)("aa times");
result[0] = (char *)"HOP: aabb, hop to bb";
result[1] = (char *)"aa times";
break;
case FourCC::InstrumentCommandLegato:
result[0] = (char *)("Legato:aabb, slide");
result[1] = (char *)("to pitch bb at speed aa");
result[0] = (char *)"LEGato: aabb, slide";
result[1] = (char *)"to pitch bb at speed aa";
break;
case FourCC::InstrumentCommandRetrigger:
result[0] = (char *)("Retrigger:aabb retrigger");
result[1] = (char *)("loop bb ticks at speed aa");
result[0] = (char *)"ReTriGger: aabb retrigger";
result[1] = (char *)"loop bb ticks at speed aa";
break;
case FourCC::InstrumentCommandTempo:
result[0] = (char *)("Tempo:--bb, set tempo to");
result[1] = (char *)("hex value bb");
result[0] = (char *)"TemPO: --bb, set tempo to";
result[1] = (char *)"hex value bb";
break;
case FourCC::InstrumentCommandMidiCC:
result[0] = (char *)("MIDI CC:aabb, ");
result[1] = (char *)("CC message aa value bb");
result[0] = (char *)"Midi CC: aabb, send";
result[1] = (char *)"CC message aa value bb";
break;
case FourCC::InstrumentCommandMidiPC:
result[0] = (char *)("MIDI Program Change:aabb,");
result[1] = (char *)("send program change bb");
result[0] = (char *)"Midi Program Change: --bb";
result[1] = (char *)"send program change bb";
break;
case FourCC::InstrumentCommandPlayOfset:
result[0] = (char *)("Play OFfset:aabb, jump abs");
result[1] = (char *)("to aa or move rel bb chunks");
result[0] = (char *)"Play OFfset: aabb, go abs";
result[1] = (char *)"to aa or move rel bb chunks";
break;
case FourCC::InstrumentCommandFilterResonance:
result[0] = (char *)("FiLTer&Res:aabb, cutoff aa");
result[1] = (char *)("resonance bb");
result[0] = (char *)"Filter ReS: aabb, set";
result[1] = (char *)"resonance bb at speed aa";
break;
case FourCC::InstrumentCommandLowPassFilter:
result[0] = (char *)("FiLTeR:aabb, resonance to");
result[0] = (char *)"FiLTer: aabb, set cutoff";
result[1] = (char *)"aa & resonance bb";
break;
case FourCC::InstrumentCommandTable:
result[0] = (char *)("TaBLe:--bb, run table bb");
result[0] = (char *)"TaBLe: --bb, run table bb";
break;
case FourCC::InstrumentCommandCrush:
result[0] = (char *)("drive&CruSH:aa-b,");
result[1] = (char *)("drive aa crush -b");
result[0] = (char *)"drive & CruSH: aa-b, set";
result[1] = (char *)"drive aa & crush b";
break;
case FourCC::InstrumentCommandFilterCut:
result[0] = (char *)("FilterCuToff:aabb, cutoff");
result[0] = (char *)"FilterCuToff: aabb, set";
result[1] = (char *)"cutoff bb at speed aa";
break;
case FourCC::InstrumentCommandPan:
result[0] = (char *)("PAN:aabb, pan to value");
result[0] = (char *)"PAN: aabb, pan to value,";
result[1] = (char *)"00 is left, FF is right";
break;
case FourCC::InstrumentCommandGroove:
result[0] = (char *)("GRooVe:aabb, set groove bb");
result[1] = (char *)("if aa > 0, set all tracks");
result[0] = (char *)"GRooVe: aabb, set groove";
result[1] = (char *)"bb, if aa>0 set all tracks";
break;
case FourCC::InstrumentCommandInstrumentRetrigger:
result[0] = (char *)("InstrumentReTrig:aabb,");
result[1] = (char *)("trig&transpose aa speed bb");
result[0] = (char *)"InstrumentReTrig: aabb,";
result[1] = (char *)"trig & transp. aa speed bb";
break;
case FourCC::InstrumentCommandPitchFineTune:
result[0] = (char *)("PitchFineTune:aabb, tune");
result[0] = (char *)"PitchFineTune: aabb, tune";
result[1] = (char *)"offset bb at speed bb";
break;
case FourCC::InstrumentCommandDelay:
result[0] = (char *)("Delay:--bb, delay bb tics");
result[0] = (char *)"DeLaY: --bb, delay by bb";
result[1] = (char *)"tics";
break;
case FourCC::InstrumentCommandStop:
result[0] = (char *)("Stop playing song now");
result[0] = (char *)"SToP: Stop playing the";
result[1] = (char *)"song now";
break;
case FourCC::InstrumentCommandGateOff:
result[0] = (char *)("GateOff (Synth only)");
result[0] = (char *)"Gate OFf: Set the gate";
result[1] = (char *)"off for synths only";
break;
case FourCC::InstrumentCommandMidiChord:
result[0] = (char *)("MIDI Chord:abcd");
result[1] = (char *)("send rel notes:+a,+b,+c,+d");
result[0] = (char *)"Midi CHord: abcd";
result[1] = (char *)"Send rel notes: +a,+b,+c,+d";
break;
default:
result[0] = result[1] = (char *)("");
result[0] = result[1] = (char *)"";
break;
}
return result;
Expand Down
17 changes: 4 additions & 13 deletions sources/Application/Views/BaseClasses/ModalView.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@

#include "ModalView.h"
#include "Application/AppWindow.h"
#include "Application/Utils/DrawTools.h"
#include "Foundation/Constants/SpecialCharacters.h"

ModalView::ModalView(View &v)
: View(v.w_, v.viewData_), finished_(false), returnCode_(0){};
Expand Down Expand Up @@ -63,16 +65,5 @@ void ModalView::SetWindow(int width, int height) {

SetColor(CD_ACCENT);
GUITextProperties props;
props.invert_ = true;
char line[SCREEN_WIDTH + 1];
memset(line, ' ', SCREEN_WIDTH);
line[SCREEN_WIDTH] = '\0';
line[width + 4] = 0;
DrawString(-2, -2, line, props);
DrawString(-2, height + 1, line, props);
line[1] = 0;
for (int i = 0; i < height + 2; i++) {
DrawString(-2, i - 1, line, props);
DrawString(width + 1, i - 1, line, props);
}
};
DrawDoubleBorder(*this, -2, -2, width + 4, height + 4, props);
}
6 changes: 6 additions & 0 deletions sources/Application/Views/BaseClasses/UIActionField.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

#include "UIActionField.h"
#include "Application/AppWindow.h"
#include "Foundation/Constants/SpecialCharacters.h"
#include "ViewUtils.h"
#include <string.h>

Expand All @@ -31,6 +32,11 @@ void UIActionField::Draw(GUIWindow &w, int offset) {
((AppWindow &)w).SetColor(CD_HILITE2);
props.invert_ = true;
w.DrawString(name_, position, props);
props.invert_ = false;
w.DrawString(char_button_border_left_s, position - GUIPoint(1, 0), props);
w.DrawString(char_button_border_right_s,
position + GUIPoint(strlen(name_), 0), props);

} else {
// enforce max field length
char buffer[MAX_FIELD_WIDTH + 1];
Expand Down
Loading