mirror of
https://github.com/curioustorvald/tsvm.git
synced 2026-06-06 05:28:31 +09:00
taut: minor bugfixes
This commit is contained in:
2
.idea/runConfigurations/AppLoader.xml
generated
2
.idea/runConfigurations/AppLoader.xml
generated
@@ -3,7 +3,7 @@
|
||||
<option name="ALTERNATIVE_JRE_PATH" value="21" />
|
||||
<option name="MAIN_CLASS_NAME" value="net.torvald.tsvm.AppLoader" />
|
||||
<module name="tsvm_executable" />
|
||||
<option name="VM_PARAMETERS" value="-ea --upgrade-module-path=lib/compiler-23.1.10.jar:lib/compiler-management-23.1.10.jar:lib/truffle-compiler-23.1.10.jar:lib/truffle-api-23.1.10.jar:lib/truffle-runtime-23.1.10.jar:lib/polyglot-23.1.10.jar:lib/collections-23.1.10.jar:lib/word-23.1.10.jar:lib/nativeimage-23.1.10.jar:lib/jniutils-23.1.10.jar -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI --add-exports=java.base/jdk.internal.misc=jdk.internal.vm.compiler" />
|
||||
<option name="VM_PARAMETERS" value="-ea --upgrade-module-path=lib/compiler-23.1.10.jar:lib/compiler-management-23.1.10.jar:lib/truffle-compiler-23.1.10.jar:lib/truffle-api-23.1.10.jar:lib/truffle-runtime-23.1.10.jar:lib/polyglot-23.1.10.jar:lib/collections-23.1.10.jar:lib/word-23.1.10.jar:lib/nativeimage-23.1.10.jar:lib/jniutils-23.1.10.jar -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI -XX:+UseZGC -XX:+UseDynamicNumberOfGCThreads --add-exports=java.base/jdk.internal.misc=jdk.internal.vm.compiler" />
|
||||
<extension name="coverage">
|
||||
<pattern>
|
||||
<option name="PATTERN" value="net.torvald.tsvm.*" />
|
||||
|
||||
2
.idea/runConfigurations/TsvmEmulator.xml
generated
2
.idea/runConfigurations/TsvmEmulator.xml
generated
@@ -2,7 +2,7 @@
|
||||
<configuration default="false" name="TsvmEmulator" type="Application" factoryName="Application" nameIsGenerated="true">
|
||||
<option name="MAIN_CLASS_NAME" value="net.torvald.tsvm.TsvmEmulator" />
|
||||
<module name="tsvm_executable" />
|
||||
<option name="VM_PARAMETERS" value="-ea --upgrade-module-path=lib/compiler-23.1.10.jar:lib/compiler-management-23.1.10.jar:lib/truffle-compiler-23.1.10.jar:lib/truffle-api-23.1.10.jar:lib/truffle-runtime-23.1.10.jar:lib/polyglot-23.1.10.jar:lib/collections-23.1.10.jar:lib/word-23.1.10.jar:lib/nativeimage-23.1.10.jar:lib/jniutils-23.1.10.jar -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI --add-exports=java.base/jdk.internal.misc=jdk.internal.vm.compiler" />
|
||||
<option name="VM_PARAMETERS" value="-ea --upgrade-module-path=lib/compiler-23.1.10.jar:lib/compiler-management-23.1.10.jar:lib/truffle-compiler-23.1.10.jar:lib/truffle-api-23.1.10.jar:lib/truffle-runtime-23.1.10.jar:lib/polyglot-23.1.10.jar:lib/collections-23.1.10.jar:lib/word-23.1.10.jar:lib/nativeimage-23.1.10.jar:lib/jniutils-23.1.10.jar -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI -XX:+UseZGC -XX:+UseDynamicNumberOfGCThreads --add-exports=java.base/jdk.internal.misc=jdk.internal.vm.compiler" />
|
||||
<extension name="coverage">
|
||||
<pattern>
|
||||
<option name="PATTERN" value="net.torvald.tsvm.*" />
|
||||
|
||||
@@ -552,6 +552,10 @@ const VOCSIZE_ORDERS = Math.floor((SCRW - 8) / 4)
|
||||
const VIEW_TIMELINE = 0
|
||||
const VIEW_CUES = 1
|
||||
const VIEW_PATTERN_DETAILS = 2
|
||||
const VIEW_SAMPLES = 3
|
||||
const VIEW_INSTRMNT = 4
|
||||
const VIEW_PROJECT = 5
|
||||
const VIEW_FILE = 6
|
||||
|
||||
const colPlayback = 86
|
||||
const colHighlight = 41
|
||||
@@ -840,7 +844,8 @@ function drawControlHint() {
|
||||
// ['q','Quit'],
|
||||
]
|
||||
|
||||
let hintElems = [hintElemTimeline, hintElemOrders, hintElemPatterns]
|
||||
const hintElemExternal = [['Tab','Panel']]
|
||||
let hintElems = [hintElemTimeline, hintElemOrders, hintElemPatterns, hintElemExternal, hintElemExternal, hintElemExternal, hintElemExternal]
|
||||
|
||||
// erase current line
|
||||
con.move(SCRH, 1)
|
||||
@@ -1156,6 +1161,22 @@ function resetAudioDevice() {
|
||||
audio.stop(PLAYHEAD)
|
||||
}
|
||||
|
||||
function applyMuteTransition(toPanel) {
|
||||
if (toPanel === VIEW_PATTERN_DETAILS) {
|
||||
timelineMuteSnapshot = voiceMutes.slice()
|
||||
if (voiceMutes[0]) {
|
||||
voiceMutes[0] = false
|
||||
audio.setVoiceMute(PLAYHEAD, 0, false)
|
||||
}
|
||||
} else if (toPanel === VIEW_TIMELINE && timelineMuteSnapshot !== null) {
|
||||
for (let i = 0; i < song.numVoices; i++) {
|
||||
voiceMutes[i] = timelineMuteSnapshot[i]
|
||||
audio.setVoiceMute(PLAYHEAD, i, voiceMutes[i])
|
||||
}
|
||||
timelineMuteSnapshot = null
|
||||
}
|
||||
}
|
||||
|
||||
function redrawFull() { drawAll() }
|
||||
|
||||
function redrawPanel() {
|
||||
@@ -1273,7 +1294,7 @@ function timelineInput(wo, event) {
|
||||
const oldVoiceOff = voiceOff
|
||||
const prevVox = cursorVox
|
||||
let triedCross = false
|
||||
if (shiftDown) {
|
||||
if (shiftDown || timelineRowStyle > 0) {
|
||||
cursorVox += dir * moveDelta
|
||||
timelineColCursor = dir > 0 ? 0 : 5
|
||||
} else {
|
||||
@@ -1750,8 +1771,33 @@ function patternsInput(wo, event) {
|
||||
|
||||
const panelTimeline = new win.WindowObject(1, PTNVIEW_OFFSET_Y, SCRW, PTNVIEW_HEIGHT, timelineInput, drawTimelineContents, undefined, ()=>{})
|
||||
const panelOrders = new win.WindowObject(1, PTNVIEW_OFFSET_Y, SCRW, PTNVIEW_HEIGHT, ordersInput, drawOrdersContents, undefined, ()=>{})
|
||||
const panelPatterns = new win.WindowObject(1, PTNVIEW_OFFSET_Y, SCRW, PTNVIEW_HEIGHT, patternsInput, drawPatternsContents, undefined, ()=>{})
|
||||
const panels = [panelTimeline, panelOrders, panelPatterns]
|
||||
const panelPatterns = new win.WindowObject(1, PTNVIEW_OFFSET_Y, SCRW, PTNVIEW_HEIGHT, patternsInput, drawPatternsContents, undefined, ()=>{})
|
||||
|
||||
// External sub-program panels: drawContents launches the sub-program synchronously.
|
||||
// The sub-program draws rows 4+ and does NOT touch rows 1-3 (drawn by taut.js before launch).
|
||||
// On exit, the sub-program sets _G.taut_nextPanel to request a tab switch.
|
||||
function makeExternalPanelDraw(progName) {
|
||||
return function(wo) {
|
||||
_G.taut_nextPanel = undefined
|
||||
_G.shell.execute(`${progName} ${fullPathObj.full} ${currentPanel}`)
|
||||
}
|
||||
}
|
||||
|
||||
function drawProjectContents(wo) {
|
||||
fillLine(PTNVIEW_OFFSET_Y - 1, colVoiceHdr, 255)
|
||||
for (let y = PTNVIEW_OFFSET_Y; y < SCRH; y++) fillLine(y, colBackPtn, 255)
|
||||
con.move(PTNVIEW_OFFSET_Y + 2, 3)
|
||||
con.color_pair(colStatus, 255)
|
||||
print('[Project settings — not yet implemented]')
|
||||
}
|
||||
function externalPanelInput(wo, event) {}
|
||||
|
||||
const panelSamples = new win.WindowObject(1, PTNVIEW_OFFSET_Y, SCRW, PTNVIEW_HEIGHT, externalPanelInput, makeExternalPanelDraw('taut_sampleedit'), undefined, ()=>{})
|
||||
const panelInstrmnt = new win.WindowObject(1, PTNVIEW_OFFSET_Y, SCRW, PTNVIEW_HEIGHT, externalPanelInput, makeExternalPanelDraw('taut_instredit'), undefined, ()=>{})
|
||||
const panelProject = new win.WindowObject(1, PTNVIEW_OFFSET_Y, SCRW, PTNVIEW_HEIGHT, externalPanelInput, drawProjectContents, undefined, ()=>{})
|
||||
const panelFile = new win.WindowObject(1, PTNVIEW_OFFSET_Y, SCRW, PTNVIEW_HEIGHT, externalPanelInput, makeExternalPanelDraw('taut_fileop'), undefined, ()=>{})
|
||||
|
||||
const panels = [panelTimeline, panelOrders, panelPatterns, panelSamples, panelInstrmnt, panelProject, panelFile]
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// PLAYBACK STATE
|
||||
@@ -1925,6 +1971,11 @@ function updatePlayback() {
|
||||
clampCursor()
|
||||
if (currentPanel === VIEW_TIMELINE) redrawPanel()
|
||||
else if (currentPanel === VIEW_PATTERN_DETAILS && song.numPats > 0) { simStateKey = ''; redrawPanel() }
|
||||
else if (currentPanel === VIEW_CUES) {
|
||||
if (cueIdx < ordersScroll) ordersScroll = cueIdx
|
||||
if (cueIdx >= ordersScroll + PTNVIEW_HEIGHT) ordersScroll = Math.max(0, cueIdx - PTNVIEW_HEIGHT + 1)
|
||||
drawOrdersContents()
|
||||
}
|
||||
} else if (previewActive || nowCue === cueIdx) {
|
||||
const oldCursor = cursorRow
|
||||
const oldScroll = scrollRow
|
||||
@@ -2152,7 +2203,17 @@ taud.uploadTaudFile(fullPathObj.full, 0, PLAYHEAD)
|
||||
audio.setMasterVolume(PLAYHEAD, 255)
|
||||
audio.setMasterPan(PLAYHEAD, 128)
|
||||
|
||||
function isExternalPanel(p) {
|
||||
return p === VIEW_SAMPLES || p === VIEW_INSTRMNT || p === VIEW_FILE
|
||||
}
|
||||
|
||||
// Launching a sub-program from inside an input.withEvent callback causes the triggering
|
||||
// Tab event to leak into the sub-program's own withEvent call (the event hasn't been
|
||||
// consumed yet when the callback is still executing). We avoid this by deferring the
|
||||
// actual shell.execute until after withEvent returns.
|
||||
let exitFlag = false
|
||||
let pendingExternalDraw = false
|
||||
|
||||
while (!exitFlag) {
|
||||
input.withEvent(event => {
|
||||
if (event[0] !== "key_down") return
|
||||
@@ -2166,28 +2227,18 @@ while (!exitFlag) {
|
||||
}
|
||||
|
||||
if (keyJustHit && keysym === "<TAB>") {
|
||||
const prevPanel = currentPanel
|
||||
currentPanel = (currentPanel + (shiftDown ? -1 : 1))
|
||||
if (currentPanel < 0) currentPanel += panels.length
|
||||
currentPanel = currentPanel % panels.length
|
||||
|
||||
if (currentPanel === VIEW_PATTERN_DETAILS) {
|
||||
// Entering Patterns: save mute state and ensure voice 0 (preview voice) is audible
|
||||
timelineMuteSnapshot = voiceMutes.slice()
|
||||
if (voiceMutes[0]) {
|
||||
voiceMutes[0] = false
|
||||
audio.setVoiceMute(PLAYHEAD, 0, false)
|
||||
}
|
||||
} else if (currentPanel === VIEW_TIMELINE && timelineMuteSnapshot !== null) {
|
||||
// Returning to Timeline: restore saved mute state
|
||||
for (let i = 0; i < song.numVoices; i++) {
|
||||
voiceMutes[i] = timelineMuteSnapshot[i]
|
||||
audio.setVoiceMute(PLAYHEAD, i, voiceMutes[i])
|
||||
}
|
||||
timelineMuteSnapshot = null
|
||||
applyMuteTransition(currentPanel)
|
||||
if (isExternalPanel(currentPanel)) {
|
||||
// Redraw header now so the tab highlight is visible immediately,
|
||||
// but defer the actual sub-program launch to after withEvent returns.
|
||||
con.clear(); drawAlwaysOnElems(); drawControlHint()
|
||||
pendingExternalDraw = true
|
||||
} else {
|
||||
drawAll()
|
||||
}
|
||||
|
||||
drawAll()
|
||||
return
|
||||
}
|
||||
|
||||
@@ -2199,6 +2250,24 @@ while (!exitFlag) {
|
||||
panels[currentPanel].processInput(event)
|
||||
})
|
||||
|
||||
// Launch external sub-program OUTSIDE the withEvent callback so the triggering
|
||||
// Tab event is fully consumed before the sub-program's event loop begins.
|
||||
if (pendingExternalDraw) {
|
||||
pendingExternalDraw = false
|
||||
redrawPanel()
|
||||
while (_G.taut_nextPanel !== undefined && _G.taut_nextPanel !== null) {
|
||||
currentPanel = _G.taut_nextPanel
|
||||
_G.taut_nextPanel = undefined
|
||||
applyMuteTransition(currentPanel)
|
||||
if (isExternalPanel(currentPanel)) {
|
||||
con.clear(); drawAlwaysOnElems(); drawControlHint()
|
||||
redrawPanel()
|
||||
} else {
|
||||
drawAll()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (playbackMode !== PLAYMODE_NONE) updatePlayback()
|
||||
}
|
||||
|
||||
|
||||
@@ -1 +1,77 @@
|
||||
// filesystem navigator for Taut
|
||||
/**
|
||||
* TAUT File Operations
|
||||
* Sub-program launched by taut.js when the File tab is active.
|
||||
* Rows 1-3 are owned by the parent; this program draws rows 4+.
|
||||
*
|
||||
* exec_args[1] = path to .taud file
|
||||
* Sets _G.taut_nextPanel before returning to request a panel switch.
|
||||
*
|
||||
* Created by minjaesong on 2026-04-27
|
||||
*/
|
||||
|
||||
const win = require("wintex")
|
||||
|
||||
const PANEL_COUNT = 7
|
||||
const MY_PANEL = 6 // VIEW_FILE
|
||||
|
||||
const [SCRH, SCRW] = con.getmaxyx()
|
||||
const PANEL_Y = 4
|
||||
const PANEL_H = SCRH - PANEL_Y
|
||||
|
||||
const colStatus = 253
|
||||
const colContent = 240
|
||||
const colHdr = 239
|
||||
|
||||
function drawFileOpContents(wo) {
|
||||
for (let y = PANEL_Y; y < SCRH; y++) {
|
||||
con.move(y, 1)
|
||||
con.color_pair(colContent, 255)
|
||||
print(' '.repeat(SCRW))
|
||||
}
|
||||
con.move(PANEL_Y + 1, 3)
|
||||
con.color_pair(colHdr, 255)
|
||||
print('[ File ]')
|
||||
con.move(PANEL_Y + 3, 3)
|
||||
con.color_pair(colStatus, 255)
|
||||
print('placeholder — not yet implemented')
|
||||
}
|
||||
|
||||
function drawHints() {
|
||||
con.move(SCRH, 1)
|
||||
con.color_pair(colStatus, 255)
|
||||
print(' '.repeat(SCRW - 1))
|
||||
con.move(SCRH, 1)
|
||||
con.color_pair(colHdr, 255); print('Tab ')
|
||||
con.color_pair(colStatus, 255); print('Panel')
|
||||
}
|
||||
|
||||
function fileOpInput(wo, event) {
|
||||
// placeholder — no interaction yet
|
||||
}
|
||||
|
||||
const panel = new win.WindowObject(1, PANEL_Y, SCRW, PANEL_H, fileOpInput, drawFileOpContents, undefined, ()=>{})
|
||||
|
||||
panel.drawContents()
|
||||
drawHints()
|
||||
|
||||
let done = false
|
||||
while (!done) {
|
||||
input.withEvent(event => {
|
||||
if (event[0] !== 'key_down') return
|
||||
const keysym = event[1]
|
||||
const keyJustHit = (1 == event[2])
|
||||
const shiftDown = (event.includes(59) || event.includes(60))
|
||||
|
||||
if (!keyJustHit) return
|
||||
|
||||
if (keysym === '<TAB>') {
|
||||
_G.taut_nextPanel = (MY_PANEL + (shiftDown ? -1 : 1) + PANEL_COUNT) % PANEL_COUNT
|
||||
done = true
|
||||
return
|
||||
}
|
||||
|
||||
panel.processInput(event)
|
||||
})
|
||||
}
|
||||
|
||||
return 0
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
/**
|
||||
* TAUT Instrument Editor
|
||||
* Sub-program launched by taut.js when the Instrmnt tab is active.
|
||||
* Rows 1-3 are owned by the parent; this program draws rows 4+.
|
||||
*
|
||||
* exec_args[1] = path to .taud file
|
||||
* Sets _G.taut_nextPanel before returning to request a panel switch.
|
||||
*
|
||||
* Created by minjaesong on 2026-04-27
|
||||
*/
|
||||
|
||||
const win = require("wintex")
|
||||
|
||||
const PANEL_COUNT = 7
|
||||
const MY_PANEL = 4 // VIEW_INSTRMNT
|
||||
|
||||
const [SCRH, SCRW] = con.getmaxyx()
|
||||
const PANEL_Y = 4
|
||||
const PANEL_H = SCRH - PANEL_Y
|
||||
|
||||
const colStatus = 253
|
||||
const colContent = 240
|
||||
const colHdr = 239
|
||||
|
||||
function drawInstEditContents(wo) {
|
||||
for (let y = PANEL_Y; y < SCRH; y++) {
|
||||
con.move(y, 1)
|
||||
con.color_pair(colContent, 255)
|
||||
print(' '.repeat(SCRW))
|
||||
}
|
||||
con.move(PANEL_Y + 1, 3)
|
||||
con.color_pair(colHdr, 255)
|
||||
print('[ Instrument Editor ]')
|
||||
con.move(PANEL_Y + 3, 3)
|
||||
con.color_pair(colStatus, 255)
|
||||
print('placeholder — not yet implemented')
|
||||
}
|
||||
|
||||
function drawHints() {
|
||||
con.move(SCRH, 1)
|
||||
con.color_pair(colStatus, 255)
|
||||
print(' '.repeat(SCRW - 1))
|
||||
con.move(SCRH, 1)
|
||||
con.color_pair(colHdr, 255); print('Tab ')
|
||||
con.color_pair(colStatus, 255); print('Panel')
|
||||
}
|
||||
|
||||
function instEditInput(wo, event) {
|
||||
// placeholder — no interaction yet
|
||||
}
|
||||
|
||||
const panel = new win.WindowObject(1, PANEL_Y, SCRW, PANEL_H, instEditInput, drawInstEditContents, undefined, ()=>{})
|
||||
|
||||
panel.drawContents()
|
||||
drawHints()
|
||||
|
||||
let done = false
|
||||
while (!done) {
|
||||
input.withEvent(event => {
|
||||
if (event[0] !== 'key_down') return
|
||||
const keysym = event[1]
|
||||
const keyJustHit = (1 == event[2])
|
||||
const shiftDown = (event.includes(59) || event.includes(60))
|
||||
|
||||
if (!keyJustHit) return
|
||||
|
||||
if (keysym === '<TAB>') {
|
||||
_G.taut_nextPanel = (MY_PANEL + (shiftDown ? -1 : 1) + PANEL_COUNT) % PANEL_COUNT
|
||||
done = true
|
||||
return
|
||||
}
|
||||
|
||||
panel.processInput(event)
|
||||
})
|
||||
}
|
||||
|
||||
return 0
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
/**
|
||||
* TAUT Sample Editor
|
||||
* Sub-program launched by taut.js when the Samples tab is active.
|
||||
* Rows 1-3 are owned by the parent; this program draws rows 4+.
|
||||
*
|
||||
* exec_args[1] = path to .taud file
|
||||
* Sets _G.taut_nextPanel before returning to request a panel switch.
|
||||
*
|
||||
* Created by minjaesong on 2026-04-27
|
||||
*/
|
||||
|
||||
const win = require("wintex")
|
||||
|
||||
const PANEL_COUNT = 7
|
||||
const MY_PANEL = 3 // VIEW_SAMPLES
|
||||
|
||||
const [SCRH, SCRW] = con.getmaxyx()
|
||||
const PANEL_Y = 4
|
||||
const PANEL_H = SCRH - PANEL_Y
|
||||
|
||||
const colStatus = 253
|
||||
const colContent = 240
|
||||
const colHdr = 239
|
||||
|
||||
function drawSampleEditContents(wo) {
|
||||
for (let y = PANEL_Y; y < SCRH; y++) {
|
||||
con.move(y, 1)
|
||||
con.color_pair(colContent, 255)
|
||||
print(' '.repeat(SCRW))
|
||||
}
|
||||
con.move(PANEL_Y + 1, 3)
|
||||
con.color_pair(colHdr, 255)
|
||||
print('[ Sample Editor ]')
|
||||
con.move(PANEL_Y + 3, 3)
|
||||
con.color_pair(colStatus, 255)
|
||||
print('placeholder — not yet implemented')
|
||||
}
|
||||
|
||||
function drawHints() {
|
||||
con.move(SCRH, 1)
|
||||
con.color_pair(colStatus, 255)
|
||||
print(' '.repeat(SCRW - 1))
|
||||
con.move(SCRH, 1)
|
||||
con.color_pair(colHdr, 255); print('Tab ')
|
||||
con.color_pair(colStatus, 255); print('Panel')
|
||||
}
|
||||
|
||||
function sampleEditInput(wo, event) {
|
||||
// placeholder — no interaction yet
|
||||
}
|
||||
|
||||
const panel = new win.WindowObject(1, PANEL_Y, SCRW, PANEL_H, sampleEditInput, drawSampleEditContents, undefined, ()=>{})
|
||||
|
||||
panel.drawContents()
|
||||
drawHints()
|
||||
|
||||
let done = false
|
||||
while (!done) {
|
||||
input.withEvent(event => {
|
||||
if (event[0] !== 'key_down') return
|
||||
const keysym = event[1]
|
||||
const keyJustHit = (1 == event[2])
|
||||
const shiftDown = (event.includes(59) || event.includes(60))
|
||||
|
||||
if (!keyJustHit) return
|
||||
|
||||
if (keysym === '<TAB>') {
|
||||
_G.taut_nextPanel = (MY_PANEL + (shiftDown ? -1 : 1) + PANEL_COUNT) % PANEL_COUNT
|
||||
done = true
|
||||
return
|
||||
}
|
||||
|
||||
panel.processInput(event)
|
||||
})
|
||||
}
|
||||
|
||||
return 0
|
||||
|
||||
Reference in New Issue
Block a user