--!movie
--!encoding=utf-8
global $
global gFile
global gConnections
----------------------------------------
-- Accelerated download using multiple concurrent http connections (asynchronous/non-blocking mode)
----------------------------------------
on startMovie
_player.debugPlaybackEnabled = 1
-- libs
$.import("curl")
$.import("file")
-- config
tUrl = "http://valentin.dasdeck.com/xtras/curl_xtra/.test/test.mp3"
tFilename = $.PATH & "download_accelerated.mp3"
sectionCnt = 4 -- number of concurrent connections to use
-- load section downloader class
SectionDownloadClass = $.include($.PATH & "section_download.ls")
-- do a quick http head request (sync)
ch = $.curl.init()
ch.setOption($.curl.CURLOPT.URL, tUrl)
ch.setOption($.curl.CURLOPT.HEADER, 1)
ch.setOption($.curl.CURLOPT.NOBODY, 1)
res = ch.exec(1)
ch = VOID
-- parse headers, extract size
headers = $.curl.parseHeaders(res.readRawString(res.length))
tSize = integer(headers["Content-Length"])
if voidP(tSize) then
put "ERROR: Could't determine download size! Aborting."
exit -- or switch to single standard GET download?
end if
if headers["Accept-Ranges"]<>"bytes" then
put "ERROR: Server doesn't seem to support multiple connections!"
sectionCnt = 1
end if
-- create empyt file
gFile = $.file.fopen(tFilename, "wb")
-- initialize/resize empty file to destination size
$.file.fseek(gFile, tSize-1)
$.file.fwritebytes(gFile, bytearray(1))
$.file.fseek(gFile, 0)
-- if previous initialization didn't work, initialize manually
-- if $.file.fsize(gFile)<>tSize then
-- bufSize = 1024*1024 -- 1 MB
-- buf = bytearray(bufSize)
-- cnt = tSize/bufSize
-- repeat with i = 1 to cnt
-- $.file.fwrite(gFile, buf)
-- end repeat
-- restSize = tSize mod bufSize
-- if restSize then $.file.fwrite(gFile, bytearray(restSize))
-- $.file.fseek(gFile, 0)
-- end if
-- download using <sectionCnt> connections
gConnections = []
sectionSize = tSize / sectionCnt
startByte = 0
repeat with i = 1 to sectionCnt
if i=sectionCnt then numBytes=sectionSize+(tSize mod sectionCnt)
else numBytes=sectionSize
conn = SectionDownloadClass.new(tUrl, gFile, startByte, numBytes, #slotSectionFinished)
gConnections.add(conn)
startByte = startByte + numBytes
end repeat
end
----------------------------------------
-- @callback
----------------------------------------
on slotSectionFinished (section, ok)
if voidP(gFile) then return -- file already closed
put "SECTION DOWNLOAD FINISHED:" && section.range && "SUCCESS="&ok
if not ok then
put "ERROR: Partial download failed! Aborting."
$.file.fdelete(gFile)
$.file.fclose(gFile)
$.file.gFile = VOID
gConnections = VOID
exit
end if
gConnections.deleteOne(section)
if gConnections.count=0 then
put "TOTAL DOWNLOAD FINISHED, FILE SUCCESFULLY DOWNLOADED!"
$.file.fclose(gFile)
gFile = VOID
end if
end