love.audio = {} local window = infatuated.js.global.window local newAudio = window.infatuated.newAudio local newXMLHttpRequest = window.infatuated.newXMLHttpRequest local Source = class("Source", infatuated.classes.Object) infatuated.classes.Source = Source function Source:initialize(a, stype) infatuated.classes.Object.initialize(self) local reterr local obj local request = newXMLHttpRequest() request:open("GET", a, true) request.responseType = stype == "xm" and "arraybuffer" or "blob" function request:onload() if self.status ~= 200 then infatuated.print("Received non-200 status code") reterr = "failed to load audio" coroutine.resume(infatuated.thread) return end infatuated.print("Loaded audio blob") obj = self.response coroutine.resume(infatuated.thread) end function request:onerror() reterr = "failed to load audio" coroutine.resume(infatuated.thread) end request:send() coroutine.yield() assert(not reterr, reterr) if stype == "xm" then if infatuated.xmVirgin then infatuated.xmVirgin = false local p = 0 local reterr local function mp() p = p+1 if p >= 2 then coroutine.resume(infatuated.thread) end end local script1 = window.document:createElement("script") script1.type = "text/javascript" function script1:onload() infatuated.print("Loaded xm.js") mp() end function script1:onerror() infatuated.print("Failed to load xm.js") reterr = "failed to load xm.js" coroutine.resume() end script1.src = "xm.js" local script2 = window.document:createElement("script") script2.type = "text/javascript" function script2:onload() infatuated.print("Loaded xmeffects.js") mp() end function script2:onerror() infatuated.print("Failed to load xmeffects.js") reterr = "failed to load xmeffects.js" coroutine.resume() end script2.src = "xmeffects.js" infatuated.print("Loading xm.js") window.document.head:appendChild(script1) window.document.head:appendChild(script2) coroutine.yield() assert(not reterr, reterr) end local xmp = window.XMPlayer xmp:init() assert(xmp:load(obj), "failed to load xm audio") self._audio = xmp return end local audio = newAudio() function audio:oncanplaythrough() infatuated.print("Loaded audio") coroutine.resume(infatuated.thread) end function audio:onerror() reterr = "failed to load audio" coroutine.resume(infatuated.thread) end infatuated.print("Loading from audio blob") audio.src = window.URL:createObjectURL(obj) coroutine.yield() assert(not reterr, reterr) self._audio = audio end function Source:play() if infatuated.audioVirgin then infatuated.audioVirgin = true infatuated.msgbox:show( "Audio playback", "The game is attempting to play audio. Press 'OK' to continue.", {"OK"}, function() coroutine.resume(infatuated.thread) end ) coroutine.yield() end self._audio:play() end infatuated.audioVirgin = true infatuated.xmVirgin = true function love.audio.newSource(a, stype) stype = stype or "static" assert(type(a) == "string", "bad argument #1 to newSource (expected string") assert(type(stype) == "string", "bad argument #2 to newSource (expected string") infatuated.print("Loading audio from %q", a) a = infatuated.path..("/"..a):gsub("/%.%.", "/") if a:find("%.xm$") then return Source:new(a, "xm") else return Source:new(a) end end function love.audio.play(...) for _, source in ipairs({...}) do if source ~= 0 then -- hack assert(type(source) == "table" and source.typeOf and source:typeOf("Source"), "bad argument #".._.." to play (expected Source)") source:play() end end end function love.audio.stop() end