You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
asciinema.org/app/assets/javascripts/player/movie.js.coffee

220 lines
4.2 KiB
CoffeeScript

class AsciiIo.Movie
MIN_DELAY: 0.01
12 years ago
constructor: (@options) ->
_.extend(this, Backbone.Events)
@reset()
@startTimeReporter()
reset: ->
@frameNo = 0
@dataIndex = 0
@completedFramesTime = 0
@playing = false
@lastFrameAt = undefined
@framesProcessed = 0
@clearPauseState()
@trigger 'reset'
call: (method, args...) ->
@[method].apply this, args
now: ->
(new Date()).getTime()
timing: ->
12 years ago
@options.timing
data: ->
12 years ago
@options.stdout_data
play: ->
return if @isPlaying()
if @isFinished()
@restart()
else if @isPaused()
@resume()
else
@start()
start: ->
@playing = true
12 years ago
@trigger 'started'
@lastFrameAt = @now()
@nextFrame()
stop: ->
@playing = false
@cancelNextFrameProcessing()
now = @now()
@adjustFrameWaitTime(now)
@pausedAt = now
cancelNextFrameProcessing: ->
clearInterval @nextFrameTimeoutId
adjustFrameWaitTime: (now) ->
resumedAt = @resumedAt or @lastFrameAt
currentWaitTime = now - resumedAt
@totalFrameWaitTime += currentWaitTime
restart: ->
@reset()
@start()
pause: ->
return if @isPaused()
@stop()
@trigger 'paused'
resume: ->
return if @isPlaying()
@playing = true
@resumedAt = @now()
frame = @timing()[@frameNo]
[delay, count] = frame
delayMs = delay * 1000
delayLeft = delayMs - @totalFrameWaitTime
@processFrameWithDelay(delayLeft)
@trigger 'resumed'
togglePlay: ->
if @isPlaying() then @pause() else @play()
isPlaying: ->
@playing
isPaused: ->
!@isPlaying() and !@isFinished() and @frameNo > 0
isFinished: ->
12 years ago
!@isPlaying() and @frameNo >= @timing().length
seek: (percent) ->
13 years ago
@stop()
@rewindTo(percent)
@resume()
rewindTo: (percent) ->
12 years ago
duration = @options.duration
requestedTime = duration * percent / 100
13 years ago
frameNo = 0
time = 0
totalCount = 0
delay = undefined
count = undefined
13 years ago
while time < requestedTime
13 years ago
[delay, count] = @timing()[frameNo]
if time + delay >= requestedTime
break
13 years ago
time += delay
totalCount += count
frameNo += 1
@frameNo = frameNo
@completedFramesTime = time * 1000
@dataIndex = totalCount
13 years ago
data = @data().slice(0, totalCount)
@trigger 'reset'
@trigger 'data', [data]
@lastFrameAt = @now()
wait = requestedTime - time
@totalFrameWaitTime = wait * 1000
startTimeReporter: ->
@timeReportId = setInterval(
=> @trigger('time', @currentTime())
500
)
stopTimeReporter: ->
clearInterval @timeReportId
currentTime: ->
@completedFramesTime + @currentFrameTime()
currentFrameTime: ->
if @isPlaying()
@playingFrameTime()
else if @isPaused()
@pausedFrameTime()
else
0
playingFrameTime: ->
if @frameWasPaused()
@currentFrameWithPauseTime()
else
@currentFrameWithNoPauseTime()
frameWasPaused: ->
!!@pausedAt
currentFrameWithPauseTime: ->
@totalFrameWaitTime + @sinceResumeTime()
currentFrameWithNoPauseTime: ->
@now() - @lastFrameAt
sinceResumeTime: ->
@now() - @resumedAt
pausedFrameTime: ->
@totalFrameWaitTime
clearPauseState: ->
@pausedAt = undefined
@resumedAt = undefined
@totalFrameWaitTime = 0
nextFrame: ->
if frame = @timing()[@frameNo]
[delay, count] = frame
if delay <= @MIN_DELAY and @framesProcessed < 100
@framesProcessed += 1
@processFrame()
else
@framesProcessed = 0
realDelay = delay * 1000 * (1.0 / @options.speed)
@processFrameWithDelay(realDelay)
true
else
@playing = false
@trigger 'finished'
false
13 years ago
processFrameWithDelay: (delay) ->
@nextFrameTimeoutId = setTimeout(
=>
@trigger 'wakeup'
@processFrame()
delay
)
13 years ago
processFrame: ->
frame = @timing()[@frameNo]
[delay, count] = frame
13 years ago
frameData = @data().slice(@dataIndex, @dataIndex + count)
@trigger 'data', [frameData]
13 years ago
@frameNo += 1
@dataIndex += count
@completedFramesTime += delay * 1000
@lastFrameAt = @now()
13 years ago
@clearPauseState()
@nextFrame()