diff --git a/.buildconfig b/.buildconfig index b267cd2..4ab3db0 100644 --- a/.buildconfig +++ b/.buildconfig @@ -1,3 +1,3 @@ KMODS=extra/net/base,extra/getgpu,extra/sound -KRELEASE=1.30 +KRELEASE=1.41 KCUSTOMNAME=default diff --git a/base/hooks.lua b/base/hooks.lua index a437953..c4e803b 100644 --- a/base/hooks.lua +++ b/base/hooks.lua @@ -9,7 +9,7 @@ do function k.hooks.add(name, func) checkArg(1, name, "string") checkArg(2, func, "function") - + hooks[name] = hooks[name] or {} table.insert(hooks[name], func) end @@ -17,7 +17,7 @@ do function k.hooks.call(name, ...) checkArg(1, name, "string") - k.log(k.loglevels.debug, "calling hook ", name) + k.logio:write(":: calling hook " .. name .. "\n") if hooks[name] then for k, v in ipairs(hooks[name]) do v(...) diff --git a/base/load.lua b/base/load.lua index 0848d8f..380929f 100644 --- a/base/load.lua +++ b/base/load.lua @@ -94,6 +94,8 @@ if (not k.cmdline.no_force_yields) then if not ok then return nil, err end + + local ysq = {} return function(...) local last_yield = computer.uptime() local old_iyield = env.__internal_yield @@ -102,13 +104,16 @@ if (not k.cmdline.no_force_yields) then env.__internal_yield = function() if computer.uptime() - last_yield >= max_time then last_yield = computer.uptime() - coroutine.yield(0.05) + local msg = table.pack(old_cyield(0.05)) + if msg.n > 0 then ysq[#ysq+1] = msg end end end env.coroutine.yield = function(...) last_yield = computer.uptime() - coroutine.yield(...) + local msg = table.pack(old_cyield(...)) + ysq[#ysq+1] = msg + return table.unpack(table.remove(ysq, 1)) end local result = table.pack(ok(...)) diff --git a/base/stdlib/package.lua b/base/stdlib/package.lua index 550f10c..67e6468 100644 --- a/base/stdlib/package.lua +++ b/base/stdlib/package.lua @@ -17,7 +17,7 @@ do } package.loaded = loaded - package.path = "/lib/?.lua;/lib/lib?.lua;/lib/?/init.lua" + package.path = "/lib/?.lua;/lib/lib?.lua;/lib/?/init.lua;/usr/lib/?.lua;/usr/lib/lib?.lua;/usr/lib/?/init.lua" local fs = k.fs.api diff --git a/base/thread.lua b/base/thread.lua index 6026af5..208767b 100644 --- a/base/thread.lua +++ b/base/thread.lua @@ -10,6 +10,11 @@ do local old_coroutine = coroutine local _coroutine = {} _G.coroutine = _coroutine + -- [[ + k.hooks.add("sandbox", function() + k.userspace.coroutine = old_coroutine + end) + --]] function _coroutine.create(func) checkArg(1, func, "function") diff --git a/base/tty.lua b/base/tty.lua index 2a56852..de9cfea 100644 --- a/base/tty.lua +++ b/base/tty.lua @@ -170,6 +170,8 @@ do if n == 0 then self.fg = colors[8] self.bg = colors[1] + self.gpu.setForeground(self.fg) + self.gpu.setBackground(self.bg) self.attributes.echo = true elseif n == 8 then self.attributes.echo = false diff --git a/base/util.lua b/base/util.lua index ffb1efa..13d67e1 100644 --- a/base/util.lua +++ b/base/util.lua @@ -134,11 +134,13 @@ do if self.closed and #self.rb == 0 then return nil end - while #self.rb < n and not self.closed do - if self.from ~= 0 then - k.scheduler.info().data.self.resume_next = self.from + if not self.closed then + while #self.rb < n do + if self.from ~= 0 then + k.scheduler.info().data.self.resume_next = self.from + end + coroutine.yield() end - coroutine.yield() end local data = self.rb:sub(1, n) self.rb = self.rb:sub(n + 1) @@ -163,11 +165,13 @@ do end function util.make_pipe() - return k.create_fstream(setmetatable({ + local new = k.create_fstream(setmetatable({ from = 0, -- the process providing output to = 0, -- the process reading input rb = "", }, {__index = _pipe}), "rw") + new.buffer_mode = "none" + return new end k.hooks.add("sandbox", function() diff --git a/extra/sound.lua b/extra/sound.lua index b03edaf..1cf9030 100644 --- a/extra/sound.lua +++ b/extra/sound.lua @@ -1,88 +1,77 @@ --- sound subsystem for Cynosure -- +-- sound api v2: emulate the sound card for everything -- k.log(k.loglevels.info, "extra/sound") do - k.log(k.loglevels.debug, "registering sound-related component detection") + local api = {} + local tiers = { + internal = 0, + beep = 1, + noise = 2, + sound = 3, + [0] = "internal", + "beep", + "noise", + "sound" + } - local api = { - MAX_CHANNELS = 1, - CARD_TYPE = "computer.beep", -- also beep, noise, sound - voice = { - SQUARE = "square", - SINE = "sine", - TRIANGLE = "triangle", - SAWTOOTH = "sawtooth", - NOISE = "noise", - } + local available = { + internal = 1, + beep = 0, + noise = 0, + sound = 0, } - local component_cache = {} - - -- all handlers must contain: - -- a table of supported voices - -- the maximum number of channels - -- a play(tab) function to play simultaneous notes - -- through { frequency, ms[, volume][, voice] } pairs contained in - -- `tab` - -- a mode(chan, voice) function to set the voice - -- for each channel - local card_handlers = { - ["computer.beep"] = { - voices = { [api.voice.SINE] = true }, - channels = 1, - play = function(tab) - local freq, dur = table.unpack(select(2, next(tab))) - dur = dur / 1000 -- ms -> s - computer.beep(freq, dur) - end + local proxies = { + internal = { + [computer.address()] = { + beep = function(tab) + return computer.beep(tab[1][1], tab[1][2]) + end + } }, - --#include "extra/sound/beep.lua" - --#include "extra/sound/noise.lua" - --#include "extra/sound/sound.lua" + beep = {}, + noise = {}, + sound = {} } + + local current = "internal" + local caddr = computer.address() - function api.play(notes) - checkArg(1, notes, "table") - return card_handlers[api.CARD_TYPE].play(notes) - end - - local chandler = function(s, add, typ) - s = s == "component_added" - if s then - if typ == "beep" or typ == "noise" or typ == "sound" then - local card = component_cache[typ] or add - if type(card) == "string" then - component_cache[typ] = component.proxy(card) - end - end - elseif component_cache[typ] and component_cache[typ].address == add then - component_cache[typ] = component.list(typ, true)() - if component_cache[typ] then - component_cache[typ] = component.proxy(component_cache[typ]) + local function component_changed(sig, addr, ctype) + if sig == "component_added" then + if tiers[ctype] and tiers[ctype] > tiers[current] then + current = ctype + available[ctype] = math.max(1, available[ctype] + 1) + proxies[ctype][addr] = component.proxy(addr) end - end - if component_cache.sound or component_cache.noise or - component_cache.beep then - api.MAX_CHANNELS = 8 - else - api.MAX_CHANNELS = 1 - end - if component_cache.sound then - api.CARD_TYPE = "sound" - elseif component_cache.noise then - api.CARD_TYPE = "noise" - elseif component_cache.beep then - api.CARD_TYPE = "beep" else - api.CARD_TYPE = "computer.beep" + if tiers[ctype] then + available[ctype] = math.min(0, available[ctype] - 1) + proxies[ctype][addr] = nil + if caddr == addr then + for i=#tiers, 0, -1 do + if available[tiers[i]] > 0 then + current = tiers[i] + caddr = next(proxies[current]) + end + end + end + end end end - local id = k.event.register("component_added", chandler) - k.event.register("component_removed", chandler) + k.event.register("component_added", component_changed) + k.event.register("component_removed", component_changed) + + local handlers = { + internal = {play = select(2, next(proxies.internal)).beep}, + --#include "extra/sound/beep.lua" + --#include "extra/sound/noise.lua" + --#include "extra/sound/sound.lua" + } - k.hooks.add("sandbox", function() - k.userspace.package.loaded.sound = package.protect(api) - end) + function api.play(notes) + return handlers[current].play(notes) + end end diff --git a/extra/sound/beep.lua b/extra/sound/beep.lua index e2760ef..e69de29 100644 --- a/extra/sound/beep.lua +++ b/extra/sound/beep.lua @@ -1,18 +0,0 @@ - beep = { - voices = { [api.voice.SINE] = true }, - channels = 8, - play = function(tab) - local bcard = component_cache.beep - if bcard then - local o = tab - tab = {} - for i=1, #o, 1 do - tab[o[i][1]] = o[i][2] / 1000 - end - bcard.play(tab) - else - return nil, "no beep card installed" - end - end, - mode = function() end - }, diff --git a/extra/sound/noise.lua b/extra/sound/noise.lua index 19f3163..e69de29 100644 --- a/extra/sound/noise.lua +++ b/extra/sound/noise.lua @@ -1,15 +0,0 @@ - noise = { - voices = { [api.voice.SQUARE] = true, [api.voice.SINE] = true, - [api.voice.TRIANGLE] = true, [api.voice.SAWTOOTH] = true }, - channels = 8, - play = function(tab) - local card = component_cache.noise - if card then - for i=1, #tab, 1 do - if tab[i][4] then card.setMode(i, card.modes[tab[i][4]]) end - tab[i] = { tab[i][1], tab[i][2] / 100} - end - card.play(tab) - end - end, - }, diff --git a/extra/sound/sound.lua b/extra/sound/sound.lua index c96bf40..e69de29 100644 --- a/extra/sound/sound.lua +++ b/extra/sound/sound.lua @@ -1,24 +0,0 @@ - sound = { - voices = { [api.voice.SQUARE] = true, [api.voice.SINE] = true, - [api.voice.TRIANGLE] = true, [api.voice.SAWTOOTH] = true, - [api.voice.NOISE] = true }, - channels = 8, - play = function(tab) - local card = component_cache.sound - if card then - local dur = 0 - for i in pairs(tab) do - local freq, _dur, vol, voi = table.unpack(tab[i]) - dur = math.max(dur, _dur) - card.open(i) - card.setFrequency(i, freq) - card.setADSR(i, 0, _dur, 0.25, _dur // 2) - if vol then card.setVolume(i, vol / 100) end - if voi then card.setWave(i, card.modes[voi]) end - end - card.delay(dur or 0) - for i=1, 10, 1 do card.process() end - for i=1, #tab, 1 do card.close(i) end - end - end, - }, diff --git a/extra/sound_old.lua b/extra/sound_old.lua new file mode 100644 index 0000000..b03edaf --- /dev/null +++ b/extra/sound_old.lua @@ -0,0 +1,88 @@ +-- sound subsystem for Cynosure -- + +k.log(k.loglevels.info, "extra/sound") + +do + k.log(k.loglevels.debug, "registering sound-related component detection") + + local api = { + MAX_CHANNELS = 1, + CARD_TYPE = "computer.beep", -- also beep, noise, sound + voice = { + SQUARE = "square", + SINE = "sine", + TRIANGLE = "triangle", + SAWTOOTH = "sawtooth", + NOISE = "noise", + } + } + + local component_cache = {} + + -- all handlers must contain: + -- a table of supported voices + -- the maximum number of channels + -- a play(tab) function to play simultaneous notes + -- through { frequency, ms[, volume][, voice] } pairs contained in + -- `tab` + -- a mode(chan, voice) function to set the voice + -- for each channel + local card_handlers = { + ["computer.beep"] = { + voices = { [api.voice.SINE] = true }, + channels = 1, + play = function(tab) + local freq, dur = table.unpack(select(2, next(tab))) + dur = dur / 1000 -- ms -> s + computer.beep(freq, dur) + end + }, + --#include "extra/sound/beep.lua" + --#include "extra/sound/noise.lua" + --#include "extra/sound/sound.lua" + } + + function api.play(notes) + checkArg(1, notes, "table") + return card_handlers[api.CARD_TYPE].play(notes) + end + + local chandler = function(s, add, typ) + s = s == "component_added" + if s then + if typ == "beep" or typ == "noise" or typ == "sound" then + local card = component_cache[typ] or add + if type(card) == "string" then + component_cache[typ] = component.proxy(card) + end + end + elseif component_cache[typ] and component_cache[typ].address == add then + component_cache[typ] = component.list(typ, true)() + if component_cache[typ] then + component_cache[typ] = component.proxy(component_cache[typ]) + end + end + if component_cache.sound or component_cache.noise or + component_cache.beep then + api.MAX_CHANNELS = 8 + else + api.MAX_CHANNELS = 1 + end + if component_cache.sound then + api.CARD_TYPE = "sound" + elseif component_cache.noise then + api.CARD_TYPE = "noise" + elseif component_cache.beep then + api.CARD_TYPE = "beep" + else + api.CARD_TYPE = "computer.beep" + end + end + + local id = k.event.register("component_added", chandler) + k.event.register("component_removed", chandler) + + k.hooks.add("sandbox", function() + k.userspace.package.loaded.sound = package.protect(api) + end) +end diff --git a/extra/sound_old/beep.lua b/extra/sound_old/beep.lua new file mode 100644 index 0000000..e2760ef --- /dev/null +++ b/extra/sound_old/beep.lua @@ -0,0 +1,18 @@ + beep = { + voices = { [api.voice.SINE] = true }, + channels = 8, + play = function(tab) + local bcard = component_cache.beep + if bcard then + local o = tab + tab = {} + for i=1, #o, 1 do + tab[o[i][1]] = o[i][2] / 1000 + end + bcard.play(tab) + else + return nil, "no beep card installed" + end + end, + mode = function() end + }, diff --git a/extra/sound_old/noise.lua b/extra/sound_old/noise.lua new file mode 100644 index 0000000..19f3163 --- /dev/null +++ b/extra/sound_old/noise.lua @@ -0,0 +1,15 @@ + noise = { + voices = { [api.voice.SQUARE] = true, [api.voice.SINE] = true, + [api.voice.TRIANGLE] = true, [api.voice.SAWTOOTH] = true }, + channels = 8, + play = function(tab) + local card = component_cache.noise + if card then + for i=1, #tab, 1 do + if tab[i][4] then card.setMode(i, card.modes[tab[i][4]]) end + tab[i] = { tab[i][1], tab[i][2] / 100} + end + card.play(tab) + end + end, + }, diff --git a/extra/sound_old/sound.lua b/extra/sound_old/sound.lua new file mode 100644 index 0000000..c96bf40 --- /dev/null +++ b/extra/sound_old/sound.lua @@ -0,0 +1,24 @@ + sound = { + voices = { [api.voice.SQUARE] = true, [api.voice.SINE] = true, + [api.voice.TRIANGLE] = true, [api.voice.SAWTOOTH] = true, + [api.voice.NOISE] = true }, + channels = 8, + play = function(tab) + local card = component_cache.sound + if card then + local dur = 0 + for i in pairs(tab) do + local freq, _dur, vol, voi = table.unpack(tab[i]) + dur = math.max(dur, _dur) + card.open(i) + card.setFrequency(i, freq) + card.setADSR(i, 0, _dur, 0.25, _dur // 2) + if vol then card.setVolume(i, vol / 100) end + if voi then card.setWave(i, card.modes[voi]) end + end + card.delay(dur or 0) + for i=1, 10, 1 do card.process() end + for i=1, #tab, 1 do card.close(i) end + end + end, + },