From 46d60df1ecf2e091b0f70f550d605431ec1ef991 Mon Sep 17 00:00:00 2001 From: 20kdc Date: Fri, 8 Jun 2018 16:26:29 +0100 Subject: [PATCH 1/3] app-pclogix-upload and app-rsctrl Yes, I made sure to ask Mimiru about permission to target the uploader there. --- repository/apps/app-pclogix-upload.lua | 36 +++++++++++ repository/apps/app-rsctrl.lua | 62 +++++++++++++++++++ repository/data/app-claw/local.lua | 34 ++++++++++ .../docs/repoauthors/app-pclogix-upload | 2 + repository/docs/repoauthors/app-rsctrl | 2 + 5 files changed, 136 insertions(+) create mode 100644 repository/apps/app-pclogix-upload.lua create mode 100644 repository/apps/app-rsctrl.lua create mode 100644 repository/docs/repoauthors/app-pclogix-upload create mode 100644 repository/docs/repoauthors/app-rsctrl diff --git a/repository/apps/app-pclogix-upload.lua b/repository/apps/app-pclogix-upload.lua new file mode 100644 index 0000000..e039631 --- /dev/null +++ b/repository/apps/app-pclogix-upload.lua @@ -0,0 +1,36 @@ +-- This is released into the public domain. +-- No warranty is provided, implied or otherwise. +-- app-pclogix-upload: Upload to PCLogix Hastebin (paste.pc-logix.com) +local inet = neo.requireAccess("c.internet", "to upload").list()() +assert(inet, "no internet card") +local event = require("event")(neo) +local neoux = require("neoux")(event, neo) + +local f = neoux.fileDialog(false) +if not f then return end +local data = f.read("*a") +f.close() + +local s = inet.request("http://paste.pc-logix.com/documents", data) +assert(s, "no socket") +s.finishConnect() +local code, msg = s.response() +local res = tostring(code) .. " " .. tostring(msg) .. "\n" +while true do + local chk, err = s.read(neo.readBufSize) + if not chk then + res = res .. "\n" .. tostring(err) + break + end + if chk == "" then + event.sleepTo(os.uptime() + 0.05) + else + res = res .. chk + end +end +res = res .. "\nPrefix ID with http://paste.pc-logix.com/raw/" +neoux.startDialog(res, "result", true) +s.close() +-- that's a hastebin client for OC! +-- done! now I'll upload this with itself. +-- - 20kdc \ No newline at end of file diff --git a/repository/apps/app-rsctrl.lua b/repository/apps/app-rsctrl.lua new file mode 100644 index 0000000..e890d78 --- /dev/null +++ b/repository/apps/app-rsctrl.lua @@ -0,0 +1,62 @@ +-- This is released into the public domain. +-- No warranty is provided, implied or otherwise. + +-- app-rsctrl: redstone control + +local event = require("event")(neo) +local neoux = require("neoux")(event, neo) +local rs = neo.requireAccess("c.redstone", "redstone control") +neo.requireAccess("s.h.redstone_changed", "updating to new input") +local running = true +local window +--123456789012345678901234567890123456789012345 +--PPPPPPPP-PPPP-PPPP-PPPPPPPPPPPP Wake=[x] +-- D=y[x] U=y[x] N=y[x] S=y[x] W=y[x] E=y[x] +local function mainGen() + local ctrls = {} + local prs = 0 + for pri in rs.list() do + prs = prs + 1 + local ins = {} + local outs = {} + local wt = pri.getWakeThreshold() + for i = 0, 5 do + ins[i + 1] = pri.getInput(i) + outs[i + 1] = pri.getOutput(i) + end + table.insert(ctrls, neoux.tcrawview(1, (prs * 2) - 1, { + unicode.safeTextFormat(pri.address), + string.format(" D=%01x U=%01x N=%01x S=%01x W=%01x E=%01x", table.unpack(ins)) + })) + table.insert(ctrls, neoux.tcrawview(38, (prs * 2) - 1, { + "Wake=" + })) + table.insert(ctrls, neoux.tcfield(43, (prs * 2) - 1, 3, function (tx) + if tx then + wt = math.floor(tonumber("0x" .. tx:sub(-1)) or 0) + pri.setWakeThreshold(wt) + end + return string.format("%01x", wt) + end)) + for i = 0, 5 do + table.insert(ctrls, neoux.tcfield(6 + (i * 7), prs * 2, 3, function (tx) + if tx then + outs[i + 1] = tonumber("0x" .. tx:sub(-1)) or 0 + pri.setOutput(i, outs[i + 1]) + end + return string.format("%01x", outs[i + 1]) + end)) + end + end + return 45, prs * 2, nil, neoux.tcwindow(45, prs * 2, ctrls, function () + window.close() + running = false + end, 0xFFFFFF, 0) +end +window = neoux.create(mainGen()) +while running do + local hv = event.pull() + if hv == "redstone_changed" then + window.reset(mainGen()) + end +end \ No newline at end of file diff --git a/repository/data/app-claw/local.lua b/repository/data/app-claw/local.lua index 81c0278..f44920e 100644 --- a/repository/data/app-claw/local.lua +++ b/repository/data/app-claw/local.lua @@ -130,6 +130,40 @@ return { "data/app-metamachine/lucaboot.lua" }, }, + ["app-pclogix-upload"] = { + desc = "paste.pc-logix.com text uploader", + v = 0, + deps = { + "neo", + "zzz-license-pd" + }, + dirs = { + "apps", + "docs", + "docs/repoauthors" + }, + files = { + "apps/app-pclogix-upload.lua", + "docs/repoauthors/app-pclogix-upload" + }, + }, + ["app-rsctrl"] = { + desc = "Redstone control", + v = 0, + deps = { + "neo", + "zzz-license-pd" + }, + dirs = { + "apps", + "docs", + "docs/repoauthors" + }, + files = { + "apps/app-rsctrl.lua", + "docs/repoauthors/app-rsctrl" + }, + }, ["app-launchbar"] = { desc = "Application launcher bar", v = 0, diff --git a/repository/docs/repoauthors/app-pclogix-upload b/repository/docs/repoauthors/app-pclogix-upload new file mode 100644 index 0000000..6610380 --- /dev/null +++ b/repository/docs/repoauthors/app-pclogix-upload @@ -0,0 +1,2 @@ +repository/apps/app-pclogix-upload.lua: 20kdc, Public Domain + diff --git a/repository/docs/repoauthors/app-rsctrl b/repository/docs/repoauthors/app-rsctrl new file mode 100644 index 0000000..95e1132 --- /dev/null +++ b/repository/docs/repoauthors/app-rsctrl @@ -0,0 +1,2 @@ +repository/apps/app-rsctrl.lua: 20kdc, Public Domain + From 4c12bb548a75fed6c8e33b8afd25e6b0ecac70c1 Mon Sep 17 00:00:00 2001 From: 20kdc Date: Fri, 8 Jun 2018 19:43:19 +0100 Subject: [PATCH 2/3] Add app-nbcompose and the library for it "knbs". --- repository/apps/app-nbcompose.lua | 345 ++++++++++++++++++++++ repository/data/app-claw/local.lua | 35 +++ repository/docs/repoauthors/app-nbcompose | 2 + repository/docs/repoauthors/lib-knbs | 2 + repository/libs/knbs.lua | 203 +++++++++++++ 5 files changed, 587 insertions(+) create mode 100644 repository/apps/app-nbcompose.lua create mode 100644 repository/docs/repoauthors/app-nbcompose create mode 100644 repository/docs/repoauthors/lib-knbs create mode 100644 repository/libs/knbs.lua diff --git a/repository/apps/app-nbcompose.lua b/repository/apps/app-nbcompose.lua new file mode 100644 index 0000000..c7417d1 --- /dev/null +++ b/repository/apps/app-nbcompose.lua @@ -0,0 +1,345 @@ +-- This is released into the public domain. +-- No warranty is provided, implied or otherwise. + +-- app-nbcompose.lua : Music! +-- Authors: 20kdc + +local nb = neo.requireAccess("c.iron_noteblock", "noteblocks").list()() +local ic = neo.requireAccess("x.neo.pub.base", "fs") + +local event = require("event")(neo) +local neoux = require("neoux")(event, neo) + +local iTranslation = { + [0] = 0, -- piano / air (def) + 4, -- double bass / wood (def) + 1, -- bass drum / stone (def) + 2, -- snare drum / sand (def) + 3, -- click / glass (def) +-- JUST GIVE UP + 4, -- guitar / wool + 5, -- flute / clay + 6, -- bell / gold + 6, -- chime / pice + 6, -- xylo / bone +} +local instKey = { + [2] = 0, + [3] = 1, + [4] = 2, + [5] = 3, + [6] = 4, + [144] = 5, + [7] = 5, + [8] = 6, + [9] = 7, + [10] = 8, + [11] = 9 +} +local noteKey = "1q2w3er5t6yu8i9o0pzsxdcvg" +-- Application State +local fileData +local uptime = os.uptime() +local songPosition = 0 +local selectionL, selectionR = -8, -9 +local running = true +local playing = false +local timerExistsFlag = false +local window +local defInst = 0 +-- +local tick -- Tick function for timer making + +local file = require("knbs").new() +-- Window width is always 50. Height is layers + 3, for the top bar. + +local theStatusBar, theNotePane, genMain + +local function updateStatusAndPane() + if theStatusBar.update then theStatusBar.update(window) end + if theNotePane then + for _, v in ipairs(theNotePane) do + v.update(window) + end + end +end + +local function commonKey(a, c, f) + if a == 32 then + playing = not playing + theStatusBar.update(window) + if playing then + if not timerExistsFlag then + uptime = os.uptime() + event.runAt(uptime, tick) + timerExistsFlag = true + end + end + elseif a == 91 then + selectionL = songPosition + updateStatusAndPane() + elseif a == 93 then + selectionR = songPosition + updateStatusAndPane() + elseif c == 203 and (f.shift or f.rshift) then + songPosition = 0 + updateStatusAndPane() + elseif c == 205 and (f.shift or f.rshift) then + songPosition = file.length + updateStatusAndPane() + elseif c == 203 then + songPosition = math.max(0, songPosition - 1) + updateStatusAndPane() + elseif c == 205 then + songPosition = songPosition + 1 + updateStatusAndPane() + end +end + +theStatusBar = { + x = 1, + y = 3, + w = 50, + h = 1, + selectable = true, + line = function (window, x, y, lined, bg, fg, selected) + if selected then + bg, fg = fg, bg + end + window.span(x, y, ((playing and "Playing") or "Paused") .. " (SPACE) ; " .. (songPosition + 1) .. "/" .. file.length .. " ([Shift-]←/→)", bg, fg) + end, + key = function (window, update, a, c, d, f) + if not d then return end + commonKey(a, c, f) + end +} + +local function genLayers() + theStatusBar.update = nil + theNotePane = nil + local layers = {} + for i = 1, file.height do + local layer = i - 1 + table.insert(layers, neoux.tcfield(1, i + 1, 40, function (tx) + file.layers[layer][1] = tx or file.layers[layer][1] + return file.layers[layer][1] + end)) + table.insert(layers, neoux.tcrawview(42, i + 1, {"Vol."})) + table.insert(layers, neoux.tcfield(46, i + 1, 5, function (tx) + if tx then + file.layers[layer][2] = math.max(0, math.min(255, math.floor(tonumber(tx) or 0))) + end + return tostring(file.layers[layer][2]) + end)) + end + return 50, file.height + 1, nil, neoux.tcwindow(50, file.height + 1, { + neoux.tcbutton(1, 1, "Purge Extra Layers", function (w) + local knbs = require("knbs") + local layerCount = knbs.correctSongLH(file) + knbs.resizeLayers(file, layerCount) + w.reset(genLayers()) + end), + neoux.tcbutton(21, 1, "Del.Last", function (w) + require("knbs").resizeLayers(file, file.height - 1) + w.reset(genLayers()) + end), + neoux.tcbutton(31, 1, "Append", function (w) + require("knbs").resizeLayers(file, file.height + 1) + w.reset(genLayers()) + end), + table.unpack(layers) + }, function (w) + w.reset(genMain()) + end, 0xFFFFFF, 0) +end +function genMain() + theNotePane = {} + for l = 1, file.height do + local layer = l - 1 + theNotePane[l] = { + x = 1, + y = 3 + l, + w = 50, + h = 1, + selectable = true, + line = function (window, x, y, lined, bg, fg, selected) + if selected then + bg, fg = fg, bg + end + local text = "" + for i = 1, 5 do + local noteL, noteR = " ", " " + local tick = songPosition + i - 3 + if songPosition == tick then + noteL = "[" + noteR = "]" + end + if selectionR >= selectionL then + if selectionL == tick then + noteL = "{" + end + if selectionR == tick then + noteR = "}" + end + end + text = text .. noteL + local fd = file.ticks[tick] + fd = fd and fd[layer] + if fd then + text = text .. string.format(" %02i/%02i", fd[1], fd[2]) + else + text = text .. " " + end + text = text .. noteR + end + window.span(x, y, text, bg, fg) + end, + key = function (window, update, a, c, d, f) + if not d then return end + commonKey(a, c, f) + if a == 8 then + if file.ticks[songPosition] then + file.ticks[songPosition][layer] = nil + require("knbs").correctSongLH(file) + update() + theStatusBar.update(window) + end + elseif instKey[c] and (f.shift or f.rshift) then + file.ticks[songPosition] = file.ticks[songPosition] or {} + defInst = instKey[c] + local nt = 45 + if file.ticks[songPosition][layer] then + file.ticks[songPosition][layer][1] = defInst + nt = file.ticks[songPosition][layer][2] + end + nb.playNote(iTranslation[defInst] or 0, nt - 33, file.layers[layer][2] / 100) + require("knbs").correctSongLH(file) + update() + theStatusBar.update(window) + elseif a >= 0 and a < 256 and noteKey:find(string.char(a), 1, true) then + file.ticks[songPosition] = file.ticks[songPosition] or {} + local note = noteKey:find(string.char(a), 1, true) - 1 + file.ticks[songPosition][layer] = {defInst, note + 33} + nb.playNote(iTranslation[defInst] or 0, note, file.layers[layer][2] / 100) + require("knbs").correctSongLH(file) + update() + theStatusBar.update(window) + elseif a == 123 then + if selectionR >= selectionL then + local storage = {} + for i = selectionL, selectionR do + storage[i] = file.ticks[i] and file.ticks[i][layer] and {table.unpack(file.ticks[i][layer])} + end + for i = selectionL, selectionR do + local p = songPosition + (i - selectionL) + file.ticks[p] = file.ticks[p] or {} + file.ticks[p][layer] = storage[i] + end + require("knbs").correctSongLH(file) + update() + theStatusBar.update(window) + end + end + end + } + end + -- We totally lie about the height here to tcwindow. "Bit of a cheat, but who's counting", anyone? + -- It is explicitly documented that the width and height are for background drawing, BTW. + return 50, file.height + 3, nil, neoux.tcwindow(50, 3, { + neoux.tcfield(1, 1, 20, function (tx) + file.name = tx or file.name + return file.name + end), + neoux.tcfield(21, 1, 15, function (tx) + file.transcriptor = tx or file.transcriptor + return file.transcriptor + end), + neoux.tcfield(36, 1, 15, function (tx) + file.songwriter = tx or file.songwriter + return file.songwriter + end), + neoux.tcbutton(1, 2, "New", function (w) + file = require("knbs").new() + songPosition = 0 + playing = false + window.reset(genMain()) + end), + neoux.tcbutton(6, 2, "Load", function (w) + neoux.fileDialog(false, function (f) + if not f then return end + file = nil + file = require("knbs").deserialize(f.read("*a")) + f.close() + songPosition = 0 + playing = false + window.reset(genMain()) + end) + end), + neoux.tcbutton(12, 2, "Save", function (w) + neoux.fileDialog(true, function (f) + if not f then return end + require("knbs").serialize(file, f.write) + f.close() + end) + end), + neoux.tcbutton(18, 2, "Ds.L", function (w) + neoux.fileDialog(false, function (f) + if not f then return end + file.description = f.read("*a") + f.close() + end) + end), + neoux.tcbutton(24, 2, "Ds.S", function (w) + neoux.fileDialog(true, function (f) + if not f then return end + f.write(file.description) + f.close() + end) + end), + neoux.tcbutton(30, 2, "Layers", function (w) + window.reset(genLayers()) + end), + neoux.tcrawview(39, 2, {"qT/S"}), + neoux.tcfield(43, 2, 8, function (tx) + if tx then + local txn = tonumber(tx) or 0 + file.tempo = math.min(math.max(0, math.floor(txn * 4)), 65535) + end + return tostring(math.floor(file.tempo / 25)) + end), + theStatusBar, + table.unpack(theNotePane) + }, function (w) + w.close() + running = false + end, 0xFFFFFF, 0) +end + +function tick() + if playing then + -- Stop the user from entering such a low tempo that stuff freezes by: + -- 1. Stopping tempo from going too low to cause /0 + -- 2. Ensuring timer is at most 1 second away + local temp = 1 / math.max(file.tempo / 100, 0.01) + if os.uptime() >= uptime + temp then + -- execute at this song position + if file.ticks[songPosition] then + for i = 0, file.height - 1 do + local tck = file.ticks[songPosition][i] + if tck then + nb.playNote(iTranslation[tck[1]] or 0, tck[2] - 33, file.layers[i][2] / 100) + end + end + end + songPosition = songPosition + 1 + if songPosition >= file.length then songPosition = 0 end + updateStatusAndPane() + uptime = uptime + temp + end + event.runAt(math.min(os.uptime() + 1, uptime + temp), tick) + else + timerExistsFlag = false + end +end +window = neoux.create(genMain()) +while running do event.pull() end diff --git a/repository/data/app-claw/local.lua b/repository/data/app-claw/local.lua index f44920e..98b09e5 100644 --- a/repository/data/app-claw/local.lua +++ b/repository/data/app-claw/local.lua @@ -164,6 +164,24 @@ return { "docs/repoauthors/app-rsctrl" }, }, + ["app-nbcompose"] = { + desc = "Music player/composer using the NBS format", + v = 0, + deps = { + "neo", + "lib-knbs", + "zzz-license-pd" + }, + dirs = { + "apps", + "docs", + "docs/repoauthors" + }, + files = { + "apps/app-nbcompose.lua", + "docs/repoauthors/app-nbcompose" + }, + }, ["app-launchbar"] = { desc = "Application launcher bar", v = 0, @@ -198,6 +216,23 @@ return { "docs/repoauthors/app-slaunch" }, }, + -- libraries + ["lib-knbs"] = { + desc = "NBS reader/writer library", + v = 0, + deps = { + "zzz-license-pd" + }, + dirs = { + "libs", + "docs", + "docs/repoauthors" + }, + files = { + "libs/knbs.lua", + "docs/repoauthors/lib-knbs" + }, + }, -- licenses (MUST BE IMMUTABLE) ["zzz-license-pd"] = { desc = "license file 'Public Domain'", diff --git a/repository/docs/repoauthors/app-nbcompose b/repository/docs/repoauthors/app-nbcompose new file mode 100644 index 0000000..fbe5fe4 --- /dev/null +++ b/repository/docs/repoauthors/app-nbcompose @@ -0,0 +1,2 @@ +repository/apps/app-nbcompose.lua: 20kdc, Public Domain + diff --git a/repository/docs/repoauthors/lib-knbs b/repository/docs/repoauthors/lib-knbs new file mode 100644 index 0000000..d460ac2 --- /dev/null +++ b/repository/docs/repoauthors/lib-knbs @@ -0,0 +1,2 @@ +repository/libs/knbs.lua: 20kdc, Public Domain + diff --git a/repository/libs/knbs.lua b/repository/libs/knbs.lua new file mode 100644 index 0000000..3ce12b4 --- /dev/null +++ b/repository/libs/knbs.lua @@ -0,0 +1,203 @@ +-- This is released into the public domain. +-- No warranty is provided, implied or otherwise. + +-- knbs.lua : Partial .nbs (Note Block Studio) R/W library +-- Does not support custom instruments! +-- Authors: 20kdc + +local function dsu16(str) + return + str:byte(1) + + (str:byte(2) * 256), + str:sub(3) +end +local function dsu32(str) + local a, str = dsu16(str) + local b, str = dsu16(str) + return a + (b * 0x10000), str +end +local function dsstr(str) + local a, str = dsu32(str) + return str:sub(1, a), str:sub(a + 1) +end +local function su16(i, wr) + wr(string.char(i % 0x100, math.floor(i / 0x100))) +end +local function su32(i, wr) + su16(i % 0x10000, wr) + su16(math.floor(i / 0x10000), wr) +end +local function sstr(str, wr) + su32(#str, wr) + wr(str) +end + +return { + new = function () + return { + length = 1, + height = 1, + name = "New Song", + transcriptor = "Mr.Anderson", + songwriter = "Morpheus", + description = "A blank song.", + tempo = 200, + autosave = 0, + autosaveMin = 60, + timeSignature = 4, + usageMin = 0, usageLeft = 0, usageRight = 0, usageAdd = 0, usageRm = 0, + importName = "", + ci = "", + ticks = { + [0] = { + [0] = {0, 33} + } + }, + layers = { + [0] = {"L0", 100} + } + } + end, + deserialize = function (str) + local nbs = {} + nbs.length, str = dsu16(str) + nbs.length = nbs.length + 1 -- hmph! + nbs.height, str = dsu16(str) + nbs.name, str = dsstr(str) + nbs.transcriptor, str = dsstr(str) + nbs.songwriter, str = dsstr(str) + nbs.description, str = dsstr(str) + nbs.tempo, str = dsu16(str) + nbs.autosave, str = str:byte(), str:sub(2) + nbs.autosaveMin, str = str:byte(), str:sub(2) + nbs.timeSignature, str = str:byte(), str:sub(2) + nbs.usageMin, str = dsu32(str) + nbs.usageLeft, str = dsu32(str) + nbs.usageRight, str = dsu32(str) + nbs.usageAdd, str = dsu32(str) + nbs.usageRm, str = dsu32(str) + nbs.importName, str = dsstr(str) + -- ticks[tick][layer] = key + nbs.ticks = {} + local tick = -1 + while true do + local ntJ + ntJ, str = dsu16(str) + if ntJ == 0 then break end + tick = tick + ntJ + local tickData = {} + nbs.ticks[tick] = tickData + local layer = -1 + while true do + local lJ + lJ, str = dsu16(str) + if lJ == 0 then break end + layer = layer + lJ + local ins = str:byte(1) + local key = str:byte(2) + str = str:sub(3) + local layerData = {ins, key} + if layer < nbs.height then + tickData[layer] = layerData + -- else: drop the invalid note + end + end + end + -- nbs.layers[layer] = {name, volume} + nbs.layers = {} + if str ~= "" then + for i = 0, nbs.height - 1 do + nbs.layers[i] = {} + nbs.layers[i][1], str = dsstr(str) + nbs.layers[i][2], str = str:byte(), str:sub(2) + end + else + for i = 0, nbs.height - 1 do + nbs.layers[i] = {"L" .. i, 100} + end + end + nbs.ci = str + return nbs + end, + resizeLayers = function (nbs, layers) + -- make all layers after target layer go away + for i = layers, nbs.height - 1 do + nbs.layers[i] = nil + end + -- add layers up to target + for i = nbs.height - 1, layers - 1 do + nbs.layers[i] = {"L" .. i, 100} + end + -- clean up song + for k, v in pairs(nbs.ticks) do + for lk, lv in pairs(v) do + if lk >= layers then + v[lk] = nil + end + end + end + nbs.height = layers + end, + -- Corrects length, height (should not be necessary in correct applications!), and clears out unused tick columns. + -- Returns the actual effective height, which can be passed to resizeLayers to remove dead weight. + correctSongLH = function (nbs) + nbs.length = 1 + nbs.height = 0 + for k, v in pairs(nbs.layers) do + nbs.height = math.max(nbs.height, k + 1) + end + local eH = 0 + for k, v in pairs(nbs.ticks) do + local ok = false + for lk, lv in pairs(v) do + ok = true + eH = math.max(eH, lk + 1) + end + if not ok then + nbs.ticks[k] = nil + else + nbs.length = math.max(nbs.length, k + 1) + end + end + return eH + end, + serialize = function (nbs, wr) + su16(math.max(0, nbs.length - 1), wr) + su16(nbs.height, wr) + sstr(nbs.name, wr) + sstr(nbs.transcriptor, wr) + sstr(nbs.songwriter, wr) + sstr(nbs.description, wr) + su16(nbs.tempo, wr) + wr(string.char(nbs.autosave, nbs.autosaveMin, nbs.timeSignature)) + su32(nbs.usageMin, wr) + su32(nbs.usageLeft, wr) + su32(nbs.usageRight, wr) + su32(nbs.usageAdd, wr) + su32(nbs.usageRm, wr) + sstr(nbs.importName, wr) + local ptr = -1 + for i = 0, nbs.length - 1 do + if nbs.ticks[i] then + su16(i - ptr, wr) + ptr = i + local lp = -1 + for j = 0, nbs.height - 1 do + local id = nbs.ticks[i][j] + if id then + su16(j - lp, wr) + lp = j + wr(string.char(id[1], id[2])) + end + end + su16(0, wr) + end + end + su16(0, wr) + for i = 0, nbs.height - 1 do + sstr(nbs.layers[i][1], wr) + wr(string.char(nbs.layers[i][2])) + end + wr(nbs.ci) + end +} From e1530057a62db05cffbae5870f93d15eab7e5a8e Mon Sep 17 00:00:00 2001 From: 20kdc Date: Sat, 9 Jun 2018 22:55:35 +0100 Subject: [PATCH 3/3] Fix nbcompose and knbs bugs --- repository/apps/app-nbcompose.lua | 16 ++++++++++------ repository/data/app-claw/local.lua | 4 ++-- repository/libs/knbs.lua | 2 +- 3 files changed, 13 insertions(+), 9 deletions(-) diff --git a/repository/apps/app-nbcompose.lua b/repository/apps/app-nbcompose.lua index c7417d1..f97c208 100644 --- a/repository/apps/app-nbcompose.lua +++ b/repository/apps/app-nbcompose.lua @@ -212,7 +212,9 @@ function genMain() file.ticks[songPosition][layer][1] = defInst nt = file.ticks[songPosition][layer][2] end - nb.playNote(iTranslation[defInst] or 0, nt - 33, file.layers[layer][2] / 100) + if nb then + nb.playNote(iTranslation[defInst] or 0, nt - 33, file.layers[layer][2] / 100) + end require("knbs").correctSongLH(file) update() theStatusBar.update(window) @@ -220,7 +222,9 @@ function genMain() file.ticks[songPosition] = file.ticks[songPosition] or {} local note = noteKey:find(string.char(a), 1, true) - 1 file.ticks[songPosition][layer] = {defInst, note + 33} - nb.playNote(iTranslation[defInst] or 0, note, file.layers[layer][2] / 100) + if nb then + nb.playNote(iTranslation[defInst] or 0, note, file.layers[layer][2] / 100) + end require("knbs").correctSongLH(file) update() theStatusBar.update(window) @@ -299,13 +303,13 @@ function genMain() neoux.tcbutton(30, 2, "Layers", function (w) window.reset(genLayers()) end), - neoux.tcrawview(39, 2, {"qT/S"}), + neoux.tcrawview(39, 2, {"cT/S"}), neoux.tcfield(43, 2, 8, function (tx) if tx then local txn = tonumber(tx) or 0 - file.tempo = math.min(math.max(0, math.floor(txn * 4)), 65535) + file.tempo = math.min(math.max(0, math.floor(txn)), 65535) end - return tostring(math.floor(file.tempo / 25)) + return tostring(file.tempo) end), theStatusBar, table.unpack(theNotePane) @@ -323,7 +327,7 @@ function tick() local temp = 1 / math.max(file.tempo / 100, 0.01) if os.uptime() >= uptime + temp then -- execute at this song position - if file.ticks[songPosition] then + if file.ticks[songPosition] and nb then for i = 0, file.height - 1 do local tck = file.ticks[songPosition][i] if tck then diff --git a/repository/data/app-claw/local.lua b/repository/data/app-claw/local.lua index 98b09e5..454c749 100644 --- a/repository/data/app-claw/local.lua +++ b/repository/data/app-claw/local.lua @@ -166,7 +166,7 @@ return { }, ["app-nbcompose"] = { desc = "Music player/composer using the NBS format", - v = 0, + v = 1, deps = { "neo", "lib-knbs", @@ -219,7 +219,7 @@ return { -- libraries ["lib-knbs"] = { desc = "NBS reader/writer library", - v = 0, + v = 1, deps = { "zzz-license-pd" }, diff --git a/repository/libs/knbs.lua b/repository/libs/knbs.lua index 3ce12b4..818affd 100644 --- a/repository/libs/knbs.lua +++ b/repository/libs/knbs.lua @@ -125,7 +125,7 @@ return { nbs.layers[i] = nil end -- add layers up to target - for i = nbs.height - 1, layers - 1 do + for i = nbs.height, layers - 1 do nbs.layers[i] = {"L" .. i, 100} end -- clean up song