diff --git a/GuiManager/Image-Animation/SetImage.int b/GuiManager/Image-Animation/SetImage.int index 70539c1..cf6b37e 100644 --- a/GuiManager/Image-Animation/SetImage.int +++ b/GuiManager/Image-Animation/SetImage.int @@ -1,12 +1,15 @@ +print(love.filesystem.createDirectory("Cache")) local multi,thread = require("multi"):init() -local GLOBAL,THREAD = require("multi.integration.loveManager"):init() -local func = THREAD:newFunction(function(path) - require("love.image") +GLOBAL,THREAD = require("multi.integration.loveManager"):init() +local queue = multi:newSystemThreadedJobQueue(16) +local LoadImage = queue:newFunction(function(path) return love.image.newImageData(path) end) -local load = THREAD:newFunction(function(path) +local DownloadImage = queue:newFunction(function(url,hash) + print = THREAD:getConsole().print require("love.image") require("love.filesystem") + require("love.data") local http = require("socket.http") local request = require("luajit-request") function download(path) @@ -16,10 +19,20 @@ local load = THREAD:newFunction(function(path) return http.request(path) end end - return love.image.newImageData(love.filesystem.newFileData((download(path)),"temp"..path:sub(-4,-1))) + local data = download(url) + function IsImage(str) + return str:find("\0")~=nil -- Image Data will contain nul character + end + love.filesystem.createDirectory("Cache") + if IsImage(data or "") then + love.filesystem.write("Cache/"..hash..".jpg", data) + return love.image.newImageData("Cache/"..hash..".jpg") + else + return "noimage" + end end) local cache = {} -function gui:SetImage(i,inthread) +function gui:SetImage(i,inthread,backup) if not i then return end if type(i) == "userdata" and i:type() == "Image" then self.Image=i @@ -31,7 +44,20 @@ function gui:SetImage(i,inthread) self:SetImage(cache[i]) else if i:match([[https?://]]) then - load(i).connect(function(img) + local hash = love.data.encode("string", "hex",love.data.hash("md5", i)) + if love.filesystem.getInfo("Cache/"..hash..".jpg") then + self:SetImage("Cache/"..hash..".jpg") + return + end + DownloadImage(i,hash).connect(function(img) + if img == "noimage" then + print("Need backup") + if backup then + return self:SetImage(backup) + else + return nil + end + end self.Image = love.graphics.newImage(img) cache[i]=self.Image self.ImageHeigth=self.Image:getHeight() diff --git a/app.lua b/app.lua index 8ae1c70..1c43253 100644 --- a/app.lua +++ b/app.lua @@ -13,55 +13,40 @@ local headersize = 80 local menusize = 350 local spdt = .005 local spd = 7 -local sliderActive = false -local mm,bb -- keep at top -local slider = thread:newFunction(function() - local menu,button = mm,bb - if sliderActive then return end - sliderActive = true - if not menu.Visible then - menu.Visible = true - for i=menusize/5,1,-1 do - menu:SetDualDim(-i*spd) - thread.sleep(spdt) - end - menu:SetDualDim(0) - button:SetImage("images/menuX.png") - else - for i=1,menusize/5 do - thread.sleep(spdt) - menu:SetDualDim(-i*spd) - end - menu.Visible = false - button:SetImage("images/menu.png") - end - sliderActive = false -end) +local head function app.createPage(name,path) local page = require("pages/"..path).init(app.workspace:newFullFrame(name),app.workspace) page.Color = theme.menu table.insert(app.pages,page) page.Visible = false - page:SetDualDim(nil,nil,nil,nil,.1,.1,.8,.8) - page:setRoundness(10,10,180) function page:Goto() for i,v in pairs(app.pages) do v.Visible = false end page.Visible = true end - local button = app.menu:newTextLabel(name,name,0,(#app.pages-1)*(headersize/2),0,headersize/2,0,0,1) + local button + if head == app.header then + button = head:newTextButton(name,name,5,0,100,60) + else + button = head:newTextButton(name,name,5,0,100,60,1) + end + button:centerY() + head = button button:fitFont() button.Color = theme.menuitem button:OnReleased(function() + page:Goto() - slider() end) + print("done") return page end local function init(a) + love.filesystem.setIdentity("MangaPro") app.header = a:newFrame(0,0,0,headersize,0,0,1) + head = app.header app.header.Color = theme.header app.workspace = a:newFrame(0,headersize,0,-headersize,0,0,1,1) app.menu = a:newFrame(0,headersize,menusize,-headersize,0,0,0,1) @@ -73,15 +58,9 @@ local function init(a) end) app.workspace.Color = Color.Black app.menu.Visible = false - local menubutton = app.header:newImageLabel("images/menu.png",0,0,headersize,headersize) - menubutton.BorderSize = 0 - mm,bb = app.menu,menubutton - menubutton:OnReleased(function() - slider() - end) local search = app.createPage("Search","search") app.createPage("Favorites","favs") - search:Goto() + --search:Goto() end return { init = init diff --git a/images/notfound.png b/images/notfound.png new file mode 100644 index 0000000..acf5686 Binary files /dev/null and b/images/notfound.png differ diff --git a/manga/init.lua b/manga/init.lua index fdabd42..bd16567 100644 --- a/manga/init.lua +++ b/manga/init.lua @@ -2,7 +2,12 @@ multi,thread = require("multi"):init() THREAD = multi.integration.THREAD local m = {} m.azlist = {} -m.init = THREAD:newFunction(function() +local queue = multi:newSystemThreadedJobQueue(16) +queue:doToAll(function() + multi,thread = require("multi"):init() + http = require("socket.http") -- This is important +end) +m.init = queue:newFunction("init",function() local http = require("socket.http") local list = http.request("http://www.mangareader.net/alphabetical") return list @@ -26,7 +31,7 @@ function m.storeList(list) return titles end -- returns manga -m.getManga = THREAD:newFunction(function(title) +m.getManga = queue:newFunction("queue",function(title) local http = require("socket.http") local manga = http.request(title.Link) local tab = {} @@ -47,16 +52,11 @@ m.getManga = THREAD:newFunction(function(title) end return tab end) -local queue = multi:newSystemThreadedJobQueue(16) -queue:doToAll(function() - multi,thread = require("multi"):init() - http = require("socket.http") -- This is important -end) -queue:registerFunction("getImage",function(pageurl) +m.getImage = queue:newFunction("getImage",function(pageurl) local page = http.request(pageurl) return page:match([[id="imgholder.-src="([^"]*)]]) end) -queue:registerFunction("getPages",function(manga,chapter) +m._getPages = queue:newFunction("getPages",function(manga,chapter) local tab = {} local page = http.request(manga.Chapters[chapter].Link) tab.pages = {page:match([[id="imgholder.-src="([^"]*)]])} @@ -70,23 +70,13 @@ end) m.getPages = function(manga,chapter) local http = require("socket.http") local tab = {} - local cc = 0 - local done = false local page = http.request(manga.Chapters[chapter].Link) tab.pages = {page:match([[id="imgholder.-src="([^"]*)]])} tab.nextChapter = "http://www.mangareader.net"..page:match([[Next Chapter:.-href="([^"]*)]]) - local lastJob - local conn = queue.OnJobCompleted(function(jid,link) - table.insert(tab.pages,link) - cc=cc+1 - if jid==lastJob then - done = true - end - end) - local count = 0 for link,page in page:gmatch([[]]) do - lastJob = queue:pushJob("getImage","http://www.mangareader.net"..link) - count = count + 1 + m._getPages("http://www.mangareader.net"..link).connect(function(link) + table.insert(tab.pages,link) + end) end thread.hold(function() return done diff --git a/multi/init.lua b/multi/init.lua index b53af81..da2eb76 100644 --- a/multi/init.lua +++ b/multi/init.lua @@ -1071,7 +1071,7 @@ end function multi:newLoop(func) local c=self:newBase() c.Type='loop' - local start=self.clock() + local start=clock() local funcs = {} if func then funcs={func} @@ -1246,7 +1246,7 @@ function multi:newTStep(start,reset,count,set) c.skip=skip or 0 c.count=count or 1*think c.funcE={} - c.timer=self.clock() + c.timer=clock() c.set=set or 1 c.funcS={} function c:Update(start,reset,count,set) @@ -1255,12 +1255,12 @@ function multi:newTStep(start,reset,count,set) self.endAt=reset or self.endAt self.set=set or self.set self.count=count or self.count or 1 - self.timer=self.clock() + self.timer=clock() self:Resume() return self end function c:Act() - if self.clock()-self.timer>=self.set then + if clock()-self.timer>=self.set then self:Reset() if self.pos==self.start then for fe=1,#self.funcS do @@ -1298,7 +1298,7 @@ function multi:newTStep(start,reset,count,set) end function c:Reset(n) if n then self.set=n end - self.timer=self.clock() + self.timer=clock() self:Resume() return self end @@ -1475,7 +1475,6 @@ function multi.holdFor(n,func) end) end function thread:newFunction(func,holdme) - local done = false return function(...) local rets, err local function wait(no) @@ -1488,9 +1487,12 @@ function thread:newFunction(func,holdme) end end) else - while not rets do + while not rets and not err do multi.scheduler:Act() end + if err then + return nil,err + end return unpack(rets) end end @@ -1504,11 +1506,11 @@ function thread:newFunction(func,holdme) isTFunc = true, wait = wait, connect = function(f) - t.OnDeath(function(self,status,...) if done == false then f(...) done = true end end) - t.OnError(function(self,err) if done == false then f(self,err) done = true end end) + t.OnDeath(function(self,status,...) f(...) end) + t.OnError(function(self,err) f(err) end) end } - return temp,temp,temp,temp,temp,temp,temp + return temp end end function thread.run(func) @@ -1557,41 +1559,41 @@ function multi:newThread(name,func,...) if type(name) == "function" then name = "Thread#"..threadCount end - local env = {} - setmetatable(env,{ - __index = Gref, - __newindex = function(t,k,v) - if type(v)=="function" then - rawset(t,k,thread:newFunction(v)) - else - if type(v)=="table" then - if v.isTFunc then - if not _G["_stack_"] or #_G["_stack_"]==0 then - _G["_stack_"] = {} - local s = _G["_stack_"] - local a,b,c,d,e,f,g = v.wait(true) - table.insert(s,a) - table.insert(s,b) - table.insert(s,c) - table.insert(s,d) - table.insert(s,e) - table.insert(s,f) - local x = table.remove(_G["_stack_"]) - rawset(t,k,x) - else - local x = table.remove(_G["_stack_"]) - rawset(t,k,x) - end - else - Gref[k]=v - end - else - Gref[k]=v - end - end - end - }) - setfenv(func,env) + -- local env = {} + -- setmetatable(env,{ + -- __index = Gref, + -- __newindex = function(t,k,v) + -- if type(v)=="function" then + -- rawset(t,k,thread:newFunction(v)) + -- else + -- if type(v)=="table" then + -- if v.isTFunc then + -- if not _G["_stack_"] or #_G["_stack_"]==0 then + -- _G["_stack_"] = {} + -- local s = _G["_stack_"] + -- local a,b,c,d,e,f,g = v.wait(true) + -- table.insert(s,a) + -- table.insert(s,b) + -- table.insert(s,c) + -- table.insert(s,d) + -- table.insert(s,e) + -- table.insert(s,f) + -- local x = table.remove(_G["_stack_"]) + -- rawset(t,k,x) + -- else + -- local x = table.remove(_G["_stack_"]) + -- rawset(t,k,x) + -- end + -- else + -- Gref[k]=v + -- end + -- else + -- Gref[k]=v + -- end + -- end + -- end + -- }) + -- setfenv(func,env) local c={} c.TempRets = {nil,nil,nil,nil,nil,nil,nil,nil,nil,nil} c.startArgs = {...} @@ -1676,8 +1678,13 @@ function multi.initThreads(justThreads) local r1,r2,r3,r4,r5,r6 local ret,_ local function CheckRets(i) - if ret~=nil then + if ret~=nil and not(threads[i].isError) then if not threads[i] then return end + if not _ then + threads[i].isError = true + threads[i].TempRets[1] = ret + return + end threads[i].TempRets[1] = ret threads[i].TempRets[2] = r1 threads[i].TempRets[3] = r2 @@ -1740,24 +1747,23 @@ function multi.initThreads(justThreads) end multi.scheduler:OnLoop(function(self) for i=#threads,1,-1 do - if not threads[i].__started then + if threads[i].isError then + threads[i].OnError:Fire(threads[i],unpack(threads[i].TempRets)) + table.remove(threads,i) + end + if threads[i] and not threads[i].__started then if coroutine.running() ~= threads[i].thread then - _,ret,r1,r2,r3,r4,r5,r6=coroutine.resume(threads[i].thread,t0,t1,t2,t3,t4,t5,t6) - CheckRets(i) + _,ret,r1,r2,r3,r4,r5,r6=coroutine.resume(threads[i].thread,unpack(threads[i].startArgs)) end threads[i].__started = true helper(i) end - if not _ then - threads[i].OnError:Fire(threads[i],ret) + if threads[i] and not _ then + threads[i].OnError:Fire(threads[i],unpack(threads[i].TempRets)) + threads[i].isError = true end if threads[i] and coroutine.status(threads[i].thread)=="dead" then - local tr = threads[i].TempRets - if ret == nil then - threads[i].OnDeath:Fire(threads[i],"ended",tr[1],tr[2],tr[3],tr[4],tr[5],tr[6],tr[7]) - else - threads[i].OnDeath:Fire(threads[i],"ended",ret,r1,r2,r3,r4,r5,r6) - end + threads[i].OnDeath:Fire(threads[i],"ended",unpack(threads[i].TempRets or {})) table.remove(threads,i) elseif threads[i] and threads[i].task == "skip" then threads[i].pos = threads[i].pos + 1 @@ -1995,6 +2001,21 @@ function multi:newHyperThreadedProcess(name) return c end -- Multi runners +function multi:lightloop() + if not isRunning then + local Loop=self.Mainloop + while true do + for _D=#Loop,1,-1 do + if Loop[_D].Active then + self.CID=_D + if not protect then + Loop[_D]:Act() + end + end + end + end + end +end function multi:mainloop(settings) multi.OnPreLoad:Fire() multi.defaultSettings = settings or multi.defaultSettings diff --git a/multi/integration/lanesManager/extensions.lua b/multi/integration/lanesManager/extensions.lua index 7c93108..e2092a1 100644 --- a/multi/integration/lanesManager/extensions.lua +++ b/multi/integration/lanesManager/extensions.lua @@ -80,6 +80,33 @@ function multi:newSystemThreadedJobQueue(n) function c:pushJob(name,...) queueJob:push{name,jid,{...}} jid = jid + 1 + return jid-1 + end + local nFunc = 0 + function c:newFunction(name,func,holup) -- This registers with the queue + if type(name)=="function" then + holup = func + func = name + name = "JQ_Function_"..nFunc + end + nFunc = nFunc + 1 + c:registerFunction(name,func) + return thread:newFunction(function(...) + local id = c:pushJob(name,...) + local link + local rets + link = c.OnJobCompleted(function(jid,...) + if id==jid then + rets = {...} + link:Remove() + end + end) + return thread.hold(function() + if rets then + return unpack(rets) + end + end) + end,holup),name end multi:newThread("JobQueueManager",function() while true do diff --git a/multi/integration/lanesManager/init.lua b/multi/integration/lanesManager/init.lua index 6e187e5..ba4163d 100644 --- a/multi/integration/lanesManager/init.lua +++ b/multi/integration/lanesManager/init.lua @@ -43,6 +43,13 @@ end -- Step 2 set up the Linda objects local __GlobalLinda = lanes.linda() -- handles global stuff local __SleepingLinda = lanes.linda() -- handles sleeping stuff +local __ConsoleLinda = lanes.linda() -- handles console stuff +multi:newLoop(function() + local _,data = __ConsoleLinda:receive(0, "Q") + if data then + print(unpack(data)) + end +end) local GLOBAL,THREAD = require("multi.integration.lanesManager.threads").init(__GlobalLinda,__SleepingLinda) local threads = {} local count = 1 @@ -77,7 +84,10 @@ function multi:newSystemThread(name, func, ...) local args = {...} c.thread = lanes.gen(table.concat(c.loadString,","),{globals={ THREAD_NAME=name, - THREAD_ID=count + THREAD_ID=count, + THREAD = THREAD, + GLOBAL = GLOBAL, + _Console = __ConsoleLinda },priority=c.priority}, func)(unpack(args)) count = count + 1 function c:kill() diff --git a/multi/integration/lanesManager/threads.lua b/multi/integration/lanesManager/threads.lua index e761e08..4ff74f5 100644 --- a/multi/integration/lanesManager/threads.lua +++ b/multi/integration/lanesManager/threads.lua @@ -54,6 +54,18 @@ local function INIT(__GlobalLinda,__SleepingLinda) function THREAD.getCores() return THREAD.__CORES end + function THREAD.getConsole() + local c = {} + c.queue = _Console + function c.print(...) + c.queue:send("Q", {...}) + end + function c.error(err) + c.queue:push{"ERROR in <"..__THREADNAME__..">: "..err,__THREADID__} + error(err) + end + return c + end function THREAD.getThreads() return GLOBAL.__THREADS__ end diff --git a/multi/integration/loveManager/extensions.lua b/multi/integration/loveManager/extensions.lua index 08f8dd3..9c53733 100644 --- a/multi/integration/loveManager/extensions.lua +++ b/multi/integration/loveManager/extensions.lua @@ -100,6 +100,32 @@ function multi:newSystemThreadedJobQueue(n) self.queue:push{name,self.id,...} return self.id end + local nFunc = 0 + function c:newFunction(name,func,holup) -- This registers with the queue + if type(name)=="function" then + holup = func + func = name + name = "JQ_Function_"..nFunc + end + nFunc = nFunc + 1 + c:registerFunction(name,func) + return thread:newFunction(function(...) + local id = c:pushJob(name,...) + local link + local rets + link = c.OnJobCompleted(function(jid,...) + if id==jid then + rets = {...} + link:Remove() + end + end) + return thread.hold(function() + if rets then + return unpack(rets) + end + end) + end,holup),name + end multi:newThread("jobManager",function() while true do thread.yield() @@ -154,7 +180,7 @@ function multi:newSystemThreadedJobQueue(n) queueReturn:push(tab) end end - end):OnError(function(...) + end).OnError(function(...) error(...) end) multi:newThread("Idler",function() diff --git a/multi/integration/loveManager/init.lua b/multi/integration/loveManager/init.lua index 14a3c9e..cf2054d 100644 --- a/multi/integration/loveManager/init.lua +++ b/multi/integration/loveManager/init.lua @@ -47,9 +47,11 @@ local THREAD = require("multi.integration.loveManager.threads") local GLOBAL = THREAD.getGlobal() local THREAD_ID = 1 local OBJECT_ID = 0 +local stf = 0 function THREAD:newFunction(func,holup) + stf = stf + 1 return function(...) - local t = multi:newSystemThread("SystemThreadedFunction"..math.random(0,999999999),func,...) + local t = multi:newSystemThread("STF"..stf,func,...) return thread:newFunction(function() return thread.hold(function() if t.stab["returns"] then diff --git a/pages/search.lua b/pages/search.lua index c022961..7a2a985 100644 --- a/pages/search.lua +++ b/pages/search.lua @@ -5,7 +5,7 @@ local titles multi:newThread(function() titles = mangaReader.storeList(mangaReader.init()) end) -local scale = 2 +local scale = 1 local mangaSize = { x=200/scale, y=288/scale @@ -52,6 +52,26 @@ for i=65,90 do end local function init(page,workspace) local holder = page:newFrame("",15,80,-30,-95,0,0,1,1) + function addManga(manga,v) + local temp = holder:newImageButton(nil,0,0,mangaSize.x,mangaSize.y) + local text = temp:newTextLabel(v.Title,v.Title,0,-30,0,30,0,1,1) + text.Visibility = .6 + text.Color = Color.Black + text.TextColor = Color.White + text.TextFormat = "center" + text:fitFont() + temp.BorderSize = 2 + temp:SetImage(manga.Cover,nil,"Images/notfound.png") + temp:OnReleased(function(b,self) + print("Manga",v.Title) + end) + end + page:OnMouseWheelMoved(function(self,x,y) + holder:Move(0,y*60) + if holder.offset.pos.y>85 then + holder:SetDualDim(nil,85) + end + end) holder.Visibility = 0 holder.BorderSize = 0 page.ClipDescendants = true @@ -65,12 +85,16 @@ local function init(page,workspace) holder:SetDualDim((page.width-size)/2) end) local nav = page:newFrame(10,10,-20,40,0,0,1) - local SBL = page:newFrame(0,55,540,20) + local SBL = page:newFrame(0,55,0,40,0,0,1) + SBL.BorderSize = 0 for i,v in pairs(chars) do - local temp = SBL:newTextLabel(v,v,(i-1)*20,0,20,20) + local temp = SBL:newTextLabel(v,v,0,0,0,0,(i-1)/27,0,1/27,1) temp.Color = theme.button - temp:fitFont() + multi.setTimeout(function() + temp:fitFont() + end,.1) temp:OnReleased(thread:newFunction(function() + holder:SetDualDim(nil,85) thread.hold(function() return titles end) local list = searchBy(temp.text) local c = holder:getChildren() @@ -78,12 +102,9 @@ local function init(page,workspace) c[i]:Destroy() end for i,v in pairs(list) do - thread.sleep(.5) - local manga = mangaReader.getManga(v).connect(function(manga) - print(v.Title,manga.Cover) - local temp = holder:newImageButton(nil,0,0,mangaSize.x,mangaSize.y) - temp.BorderSize = 2 - temp:SetImage(manga.Cover) + thread.yield() + mangaReader.getManga(v).connect(function(manga) + addManga(manga,v) end) end end)) @@ -92,7 +113,6 @@ local function init(page,workspace) local temp = holder:newImageLabel("images/test.jpg",0,0,mangaSize.x,mangaSize.y) temp.BorderSize = 2 ]] - SBL:centerX() nav.Color = theme.header nav:setRoundness(5,5,60) local search = nav:newTextButton("Search","Search",5,5,60,-10,0,0,0,1) @@ -100,12 +120,17 @@ local function init(page,workspace) search:fitFont() local bar = nav:newTextBox("","",70,5,-75,-10,0,0,1,1) search:OnReleased(thread:newFunction(function() + holder:SetDualDim(nil,85) thread.hold(function() return titles end) - -- tprint(searchBy("a")) - -- tprint(searchFor(bar.text)) - -- local manga = mangaReader.getManga(title) - -- local page = mangaReader.getPages(manga,1) - -- print(page) + local list = searchFor(bar.text) + for i,v in pairs(list) do + mangaReader.getManga(v).connect(function(manga) + addManga(manga,v) + end) + -- local manga = mangaReader.getManga(title) + -- local page = mangaReader.getPages(manga,1) + end + print(page) end)) bar:fitFont() bar.Color = theme.input