2018-09-02 19:22:28 +00:00
"use strict" ;
2018-12-02 15:07:43 +00:00
var Uint64 = require ( "../wType/uint64" ) ;
var Address = require ( "../wType/address" ) ;
2018-09-02 19:22:28 +00:00
var Controller = require ( "./controller" ) ;
var Button = require ( "./button" ) ;
2018-12-02 15:07:43 +00:00
var ImageById = require ( "./imageById" ) ;
2018-09-02 19:22:28 +00:00
var Vocabulary = require ( "./vocabulary" ) ;
2018-12-17 17:15:58 +00:00
var Audio = require ( "./file/audio" ) ;
2019-01-24 19:54:16 +00:00
var Model = require ( "./localModel" ) ;
2018-12-17 17:15:58 +00:00
2018-09-02 19:22:28 +00:00
var Enum = require ( "../utils/enum" ) ;
2018-12-17 17:15:58 +00:00
var StateMachine = require ( "../utils/stateMachine" ) ;
2018-09-02 19:22:28 +00:00
var Player = Controller . inherit ( {
className : "Player" ,
constructor : function ( addr ) {
Controller . fn . constructor . call ( this , addr ) ;
this . controls = Object . create ( null ) ;
this . views = Object . create ( null ) ;
2018-12-02 15:07:43 +00:00
this . mode = PlayerMode . straight . playback ;
2019-01-24 19:54:16 +00:00
this . progress = new ProgressModel ( ) ;
2019-01-30 20:36:33 +00:00
this . volume = new Slider ( ) ;
this . volume . setValue ( 1 ) ;
2019-01-26 18:54:22 +00:00
this . progress . on ( "seekingStart" , this . _onSeekingStart , this ) ;
this . progress . on ( "seekingEnd" , this . _onSeekingEnd , this ) ;
2019-01-30 20:36:33 +00:00
this . progress . enable ( false ) ;
this . volume . on ( "value" , this . _onVolume , this ) ;
2018-12-17 17:15:58 +00:00
this . _audio = null ;
this . _createStateMachine ( ) ;
2019-01-03 00:26:42 +00:00
this . _createPlayingInfrastructure ( ) ;
2018-09-02 19:22:28 +00:00
this . addHandler ( "get" ) ;
this . addHandler ( "viewsChange" ) ;
2018-12-17 17:15:58 +00:00
this . addHandler ( "play" ) ;
this . addHandler ( "pause" ) ;
2019-01-24 19:54:16 +00:00
2019-01-26 18:54:22 +00:00
this . _playbackInterval = setInterval ( this . _onInterval . bind ( this ) , intervalPrecision ) ;
2018-12-17 17:15:58 +00:00
} ,
destructor : function ( ) {
2019-01-24 19:54:16 +00:00
this . _clearInterval ( this . _playbackInterval ) ;
this . _destroyPlayingInfrastructure ( ) ;
2018-12-17 17:15:58 +00:00
this . _fsm . destructor ( ) ;
2019-01-24 19:54:16 +00:00
this . progress . destructor ( ) ;
2018-12-17 17:15:58 +00:00
Controller . fn . destructor . call ( this ) ;
2018-09-02 19:22:28 +00:00
} ,
_addControl : function ( type , address ) {
var t = type . valueOf ( ) ;
if ( this . controls [ t ] !== undefined ) {
throw new Error ( "An attempt to add multiple instances of " + ItemType . reversed [ t ] + " into Player" ) ;
}
if ( ItemType . reversed [ t ] !== undefined ) {
switch ( t ) {
case ItemType . straight . playPause :
2019-01-03 00:26:42 +00:00
case ItemType . straight . prev :
case ItemType . straight . next :
2018-09-02 19:22:28 +00:00
var btn = new Button ( address . clone ( ) ) ;
btn . itemType = t ;
this . controls [ t ] = btn ;
this . addController ( btn ) ;
2018-10-28 21:32:44 +00:00
this . trigger ( "newElement" , btn , t ) ;
2018-09-02 19:22:28 +00:00
break ;
default :
2019-01-03 00:26:42 +00:00
this . trigger ( "serviceMessage" , "An attempt to add ItemType " + ItemType . reversed [ t ] + " to controls of the Player, but it's not qualified to be a control" , 1 ) ;
2018-09-02 19:22:28 +00:00
}
} else {
2019-01-03 00:26:42 +00:00
this . trigger ( "serviceMessage" , "An unrecgnized item ItemType in Player: " + t , 1 ) ;
2018-09-02 19:22:28 +00:00
}
} ,
_addView : function ( type , address ) {
var t = type . valueOf ( ) ;
2018-12-02 15:07:43 +00:00
var ctrl ;
var supported = false ;
2018-09-02 19:22:28 +00:00
if ( this . views [ t ] !== undefined ) {
throw new Error ( "An attempt to add multiple instances of " + ItemType . reversed [ t ] + " into Player" ) ;
}
if ( ItemType . reversed [ t ] !== undefined ) {
switch ( t ) {
case ItemType . straight . queue :
2019-01-03 00:26:42 +00:00
this . trigger ( "serviceMessage" , "Queue is not supported yet in Player" , 1 ) ;
2018-09-02 19:22:28 +00:00
break ;
case ItemType . straight . currentPlayback :
2018-12-02 15:07:43 +00:00
ctrl = new Vocabulary ( address . clone ( ) ) ;
2019-01-26 18:54:22 +00:00
ctrl . on ( "newElement" , this . _onNewPlaybackElement , this ) ;
ctrl . on ( "removeElement" , this . _onRemovePlaybackElement , this ) ;
2018-12-02 15:07:43 +00:00
supported = true ;
break ;
case ItemType . straight . picture :
ctrl = new ImageById ( null , address . back ( ) ) ;
ctrl . ItemType = t ;
this . views [ t ] = ctrl ;
this . trigger ( "newElement" , ctrl , t ) ;
supported = false ; //just to avoid adding with addController, since ImageById is not a controller
2018-10-28 21:32:44 +00:00
break ;
2018-09-02 19:22:28 +00:00
default :
2019-01-03 00:26:42 +00:00
this . trigger ( "serviceMessage" , "An attempt to add ItemType " + ItemType . reversed [ t ] + " to views of the Player, but it's not qualified to be a view" , 1 ) ;
2018-09-02 19:22:28 +00:00
}
} else {
2019-01-03 00:26:42 +00:00
this . trigger ( "serviceMessage" , "An unrecognized item ItemType in Player: " + t , 1 ) ;
2018-09-02 19:22:28 +00:00
}
2018-12-02 15:07:43 +00:00
if ( supported ) {
ctrl . ItemType = t ;
this . views [ t ] = ctrl ;
this . addController ( ctrl ) ;
this . trigger ( "newElement" , ctrl , t ) ;
}
2018-09-02 19:22:28 +00:00
} ,
2019-01-26 18:54:22 +00:00
_checkIfEnough : function ( ) {
var diff = this . _currentTime - this . _seekingTime - this . _ctx . currentTime ;
if ( diff > threshold ) {
this . _fsm . manipulation ( "enough" ) ;
} else {
this . _fsm . manipulation ( "notEnough" ) ;
}
} ,
2019-01-24 19:54:16 +00:00
_createPlayingInfrastructure : function ( ) {
this . _ctx = new AudioContext ( ) ;
this . _decoder = new Mp3Decoder ( ) ;
2019-01-30 20:36:33 +00:00
this . _gainNode = this . _ctx . createGain ( ) ;
this . _gainNode . connect ( this . _ctx . destination ) ;
2019-01-24 19:54:16 +00:00
this . _currentTime = 0 ;
2019-01-26 18:54:22 +00:00
this . _seekingTime = 0 ;
this . _buffers = [ ] ;
this . _sources = [ ] ;
2019-01-24 19:54:16 +00:00
this . _ctx . suspend ( ) ;
} ,
2019-01-26 18:54:22 +00:00
_createStateMachine : function ( ) {
this . _fsm = new StateMachine ( "initial" , graphs [ this . mode ] ) ;
this . _fsm . on ( "stateChanged" , this . _onStateChanged , this ) ;
} ,
2019-01-24 19:54:16 +00:00
_destroyPlayingInfrastructure : function ( ) {
this . _ctx . close ( ) ;
this . _decoder . delete ( ) ;
2019-01-03 00:26:42 +00:00
} ,
2019-01-26 18:54:22 +00:00
getCurrentPlaybackTime : function ( ) {
return this . _ctx . currentTime + this . _seekingTime ;
2018-12-17 17:15:58 +00:00
} ,
2018-09-02 19:22:28 +00:00
_h _get : function ( ev ) {
var data = ev . getData ( ) ;
var controls = data . at ( "controls" ) ;
var views = data . at ( "views" ) ;
2018-12-02 15:07:43 +00:00
var mode = data . at ( "mode" ) . valueOf ( ) ;
2018-09-02 19:22:28 +00:00
var size , i , vc ;
size = controls . length ( ) ;
for ( i = 0 ; i < size ; ++ i ) {
vc = controls . at ( i ) ;
this . _addControl ( vc . at ( "type" ) , vc . at ( "address" ) ) ;
}
size = views . length ( ) ;
for ( i = 0 ; i < size ; ++ i ) {
vc = views . at ( i ) ;
2018-10-28 21:32:44 +00:00
this . _addView ( vc . at ( "type" ) , vc . at ( "address" ) ) ;
2018-09-02 19:22:28 +00:00
}
2018-10-28 21:32:44 +00:00
2018-12-02 15:07:43 +00:00
if ( this . mode !== mode ) {
if ( PlayerMode . reversed [ mode ] === undefined ) {
throw new Error ( "Unsupported mode of player: " + mode ) ;
}
this . mode = mode ;
}
2018-10-28 21:32:44 +00:00
this . initialized = true ;
this . trigger ( "data" ) ;
2018-09-02 19:22:28 +00:00
} ,
2018-12-17 17:15:58 +00:00
_h _pause : function ( ev ) {
2018-12-21 21:21:12 +00:00
this . _fsm . manipulation ( "pause" ) ;
2018-12-17 17:15:58 +00:00
} ,
_h _play : function ( ev ) {
this . _fsm . manipulation ( "play" ) ;
} ,
2018-09-02 19:22:28 +00:00
_h _viewsChange : function ( ev ) {
var data = ev . getData ( ) ;
var add = data . at ( "add" ) ;
var remove = data . at ( "remove" ) ;
var size , i , vc ;
size = remove . length ( ) ;
for ( i = 0 ; i < size ; ++ i ) {
2019-01-03 00:26:42 +00:00
this . _removeView ( remove . at ( i ) . valueOf ( ) ) ;
2018-09-02 19:22:28 +00:00
}
size = add . length ( ) ;
for ( i = 0 ; i < size ; ++ i ) {
vc = add . at ( i ) ;
2018-10-28 21:32:44 +00:00
this . _addView ( vc . at ( "type" ) , vc . at ( "address" ) ) ;
2018-09-02 19:22:28 +00:00
}
} ,
2019-01-24 19:54:16 +00:00
_onAudioNewSlice : function ( frames ) {
var arr = new Uint8Array ( frames . valueOf ( ) ) ;
this . _decoder . addFragment ( arr ) ;
while ( this . _decoder . hasMore ( ) ) {
var sb = this . _decoder . decode ( 9999 ) ;
if ( sb === undefined ) {
break ;
} else {
2019-01-26 18:54:22 +00:00
this . _buffers . push ( sb ) ;
var startTime = this . _currentTime - this . _seekingTime ;
if ( startTime < this . _ctx . currentTime ) {
var offset = startTime - this . _ctx . currentTime + sb . duration ;
if ( offset > 0 ) {
var src = this . _ctx . createBufferSource ( ) ;
src . buffer = sb ;
2019-01-30 20:36:33 +00:00
src . connect ( this . _gainNode ) ;
2019-01-26 18:54:22 +00:00
src . start ( 0 , Math . abs ( startTime - this . _ctx . currentTime ) ) ;
this . _sources . push ( src ) ;
}
} else {
var src = this . _ctx . createBufferSource ( ) ;
src . buffer = sb ;
2019-01-30 20:36:33 +00:00
src . connect ( this . _gainNode ) ;
2019-01-26 18:54:22 +00:00
src . start ( startTime ) ;
this . _sources . push ( src ) ;
}
2019-01-24 19:54:16 +00:00
this . _currentTime += sb . duration ;
}
}
this . progress . setLoad ( this . _currentTime / this . _audio . getDuration ( ) ) ;
2018-12-21 21:21:12 +00:00
2018-12-17 17:15:58 +00:00
this . _fsm . manipulation ( "newFrames" ) ;
if ( this . _audio . hasMore ( ) ) {
2019-01-24 19:54:16 +00:00
this . _audio . requestSlice ( audioPortion ) ;
2018-12-17 17:15:58 +00:00
} else {
this . _fsm . manipulation ( "noMoreFrames" ) ;
}
} ,
2019-01-03 00:26:42 +00:00
_onControllerReady : function ( ) {
this . _fsm . manipulation ( "controllerReady" ) ;
} ,
2019-01-24 19:54:16 +00:00
_onInterval : function ( ) {
2019-01-26 18:54:22 +00:00
if ( this . _audio && this . _audio . initialized && seekingStates . indexOf ( this . _fsm . state ( ) ) === - 1 ) {
var duration = this . _audio . getDuration ( ) ;
2019-01-30 20:36:33 +00:00
this . progress . setValue ( this . getCurrentPlaybackTime ( ) / duration ) ;
2019-01-26 18:54:22 +00:00
this . _checkIfEnough ( ) ;
2019-01-30 20:36:33 +00:00
if ( this . progress . value >= 0.9999 ) {
2019-01-26 18:54:22 +00:00
var next = this . controls [ ItemType . straight . next ] ;
if ( next && next . enabled ) {
next . activate ( ) ;
} else {
2019-01-27 17:32:19 +00:00
this . _fsm . manipulation ( "pause" ) ;
this . _onSeekingStart ( ) ;
this . _onSeek ( 0 ) ;
this . _onSeekingEnd ( 0 ) ;
this . controls [ ItemType . straight . playPause ] . activate ( ) ;
2019-01-26 18:54:22 +00:00
}
}
2019-01-24 19:54:16 +00:00
}
} ,
2019-01-26 18:54:22 +00:00
_onNewPlaybackElement : function ( key , element ) {
2018-12-02 15:07:43 +00:00
switch ( key ) {
case "image" :
var address = new Address ( [ "images" , element . toString ( ) ] ) ;
this . _addView ( new Uint64 ( ItemType . straight . picture ) , address ) ;
address . destructor ( ) ;
break ;
2018-12-17 17:15:58 +00:00
case "audio" :
if ( this . mode === PlayerMode . straight . playback ) {
this . _audio = new Audio ( new Address ( [ "music" , element . toString ( ) ] ) ) ;
this . addForeignController ( "Corax" , this . _audio ) ;
2019-01-24 19:54:16 +00:00
this . _audio . on ( "slice" , this . _onAudioNewSlice , this ) ;
2019-01-03 00:26:42 +00:00
this . _audio . on ( "ready" , this . _onControllerReady , this ) ;
2018-12-17 17:15:58 +00:00
this . _fsm . manipulation ( "controller" ) ;
}
break ;
2018-12-02 15:07:43 +00:00
}
} ,
2019-01-26 18:54:22 +00:00
_onRemovePlaybackElement : function ( key ) {
2018-12-02 15:07:43 +00:00
switch ( key ) {
case "image" :
2019-01-03 00:26:42 +00:00
this . _removeView ( ItemType . straight . picture ) ;
2018-12-02 15:07:43 +00:00
break ;
2018-12-17 17:15:58 +00:00
case "audio" :
this . removeForeignController ( this . _audio ) ;
this . _audio . destructor ( ) ;
this . _audio = null ;
}
} ,
2019-01-26 18:54:22 +00:00
_onSeekingStart : function ( ) {
this . _fsm . manipulation ( "startSeeking" ) ;
} ,
_onSeekingEnd : function ( progress ) {
if ( seekingStates . indexOf ( this . _fsm . state ( ) ) !== - 1 ) {
for ( var i = 0 ; i < this . _sources . length ; ++ i ) {
this . _sources [ i ] . stop ( ) ;
}
this . _sources = [ ] ;
var ct = this . getCurrentPlaybackTime ( ) ;
var duration = this . _audio . getDuration ( ) ;
var targetTime = duration * progress ;
this . _seekingTime += targetTime - ct ;
var nc = 0 ;
for ( var i = 0 ; i < this . _buffers . length ; ++ i ) {
var buffer = this . _buffers [ i ] ;
var startTime = nc - targetTime ;
if ( startTime < 0 ) {
var offset = startTime + buffer . duration ;
if ( offset > 0 ) {
var src = this . _ctx . createBufferSource ( ) ;
src . buffer = buffer ;
2019-01-30 20:36:33 +00:00
src . connect ( this . _gainNode ) ;
2019-01-26 18:54:22 +00:00
src . start ( 0 , Math . abs ( startTime ) ) ;
this . _sources . push ( src ) ;
}
} else {
var src = this . _ctx . createBufferSource ( ) ;
src . buffer = buffer ;
2019-01-30 20:36:33 +00:00
src . connect ( this . _gainNode ) ;
2019-01-26 18:54:22 +00:00
src . start ( this . _ctx . currentTime + startTime ) ;
this . _sources . push ( src ) ;
}
nc += buffer . duration ;
}
}
this . _fsm . manipulation ( "stopSeeking" ) ;
} ,
2018-12-17 17:15:58 +00:00
_onStateChanged : function ( e ) {
switch ( e . newState ) {
case "initial" :
2019-01-03 00:26:42 +00:00
if ( e . manipulation === "noController" ) {
2019-01-30 20:36:33 +00:00
this . progress . enable ( false ) ;
2019-01-03 00:26:42 +00:00
this . removeForeignController ( this . _audio ) ;
this . _audio . destructor ( ) ;
this . _audio = null ;
2019-01-24 19:54:16 +00:00
this . _destroyPlayingInfrastructure ( ) ;
2019-01-03 00:26:42 +00:00
this . _createPlayingInfrastructure ( ) ;
}
2018-12-17 17:15:58 +00:00
break ;
case "initialPlaying" :
2019-01-03 00:26:42 +00:00
if ( e . manipulation === "noController" ) {
2019-01-30 20:36:33 +00:00
this . progress . enable ( false ) ;
2019-01-24 19:54:16 +00:00
this . _ctx . suspend ( ) ;
2019-01-03 00:26:42 +00:00
this . removeForeignController ( this . _audio ) ;
this . audio . destructor ( ) ;
this . _audio = null ;
2019-01-24 19:54:16 +00:00
this . _destroyPlayingInfrastructure ( ) ;
2019-01-03 00:26:42 +00:00
this . _createPlayingInfrastructure ( ) ;
}
2018-12-17 17:15:58 +00:00
break ;
2019-01-03 00:26:42 +00:00
case "controllerNotReady" :
break
case "controllerNotReadyPlaying" :
break
2018-12-17 17:15:58 +00:00
case "hasController" :
break ;
case "hasControllerPlaying" :
if ( this . _audio . hasMore ( ) ) {
2019-01-24 19:54:16 +00:00
this . _audio . requestSlice ( audioPortion ) ;
2018-12-17 17:15:58 +00:00
} else {
this . _fsm . manipulation ( "noMoreFrames" ) ;
}
break ;
2019-01-26 18:54:22 +00:00
case "buffering" :
2019-01-30 20:36:33 +00:00
if ( e . oldState === "hasController" ) {
this . progress . enable ( true ) ;
}
2019-01-26 18:54:22 +00:00
break ;
case "bufferingPlaying" :
if ( e . oldState === "playing" ) {
this . _ctx . suspend ( ) ;
2019-01-30 20:36:33 +00:00
} else if ( e . oldState === "hasControllerPlaying" ) {
this . progress . enable ( true ) ;
2019-01-26 18:54:22 +00:00
}
break ;
case "seeking" :
break ;
case "seekingPlaying" :
if ( e . oldState === "playing" ) {
this . _ctx . suspend ( ) ;
}
break ;
case "seekingAllLoaded" :
break ;
case "seekingPlayingAllLoaded" :
if ( e . oldState === "playingAllLoaded" ) {
this . _ctx . suspend ( ) ;
}
break ;
2018-12-17 17:15:58 +00:00
case "paused" :
switch ( e . oldState ) {
case "playing" :
2019-01-24 19:54:16 +00:00
this . _ctx . suspend ( ) ;
2018-12-17 17:15:58 +00:00
break ;
}
break ;
case "pausedAllLoaded" :
switch ( e . oldState ) {
case "playingAllLoaded" :
2019-01-24 19:54:16 +00:00
this . _ctx . suspend ( ) ;
2018-12-17 17:15:58 +00:00
break ;
}
break ;
case "playing" :
2019-01-24 19:54:16 +00:00
this . _ctx . resume ( ) ;
2018-12-17 17:15:58 +00:00
break ;
case "playingAllLoaded" :
switch ( e . oldState ) {
case "pausedAllLoaded" :
2019-01-26 18:54:22 +00:00
case "bufferingPlaying" :
case "seekingPlayingAllLoaded" :
2019-01-24 19:54:16 +00:00
this . _ctx . resume ( ) ;
2018-12-17 17:15:58 +00:00
break ;
}
break ;
2018-12-02 15:07:43 +00:00
}
} ,
2019-01-30 20:36:33 +00:00
_onVolume : function ( volume ) {
this . _gainNode . gain . cancelScheduledValues ( this . _ctx . currentTime ) ;
this . _gainNode . gain . exponentialRampToValueAtTime ( volume , this . _ctx . currentTime + 0.01 ) ;
} ,
2018-09-02 19:22:28 +00:00
_removeControl : function ( type ) {
2019-01-03 00:26:42 +00:00
var ctrl = this . controls [ type ] ;
if ( ctrl !== undefined ) {
this . trigger ( "removeElement" , type ) ;
this . removeController ( ctrl ) ;
ctrl . destructor ( ) ;
}
2018-09-02 19:22:28 +00:00
} ,
_removeView : function ( type ) {
2019-01-03 00:26:42 +00:00
var view = this . views [ type ] ;
if ( view !== undefined ) {
this . trigger ( "removeElement" , type ) ;
if ( type !== ItemType . straight . picture ) {
this . removeController ( view ) ;
}
if ( type === ItemType . straight . currentPlayback ) {
if ( this . views [ ItemType . straight . picture ] ) {
this . _removeView ( ItemType . straight . picture ) ;
}
this . _fsm . manipulation ( "noController" ) ;
}
delete this . views [ type ] ;
view . destructor ( ) ;
}
2018-09-02 19:22:28 +00:00
}
} ) ;
var ItemType = new Enum ( "ItemType" ) ;
ItemType . add ( "playPause" ) ;
ItemType . add ( "currentPlayback" ) ;
ItemType . add ( "queue" ) ;
2018-12-02 15:07:43 +00:00
ItemType . add ( "picture" ) ;
2019-01-03 00:26:42 +00:00
ItemType . add ( "prev" ) ;
ItemType . add ( "next" ) ;
2018-12-02 15:07:43 +00:00
var PlayerMode = new Enum ( "PlayerMode" ) ;
PlayerMode . add ( "playback" ) ;
2018-09-02 19:22:28 +00:00
Player . ItemType = ItemType ;
2018-12-17 17:15:58 +00:00
var graphs = Object . create ( null ) ;
graphs [ PlayerMode . straight . playback ] = {
"initial" : {
2019-01-03 00:26:42 +00:00
controller : "controllerNotReady" ,
2018-12-17 17:15:58 +00:00
play : "initialPlaying"
} ,
"initialPlaying" : {
pause : "initial" ,
2019-01-03 00:26:42 +00:00
controller : "controllerNotReadyPlaying"
} ,
"controllerNotReady" : {
play : "controllerNotReadyPlaying" ,
controllerReady : "hasController"
} ,
"controllerNotReadyPlaying" : {
pause : "controllerNotReady" ,
controllerReady : "hasControllerPlaying"
2018-12-17 17:15:58 +00:00
} ,
"hasController" : {
2019-01-26 18:54:22 +00:00
newFrames : "bufferingPlaying" ,
2019-01-03 00:26:42 +00:00
play : "hasControllerPlaying" ,
noController : "initial"
2018-12-17 17:15:58 +00:00
} ,
"hasControllerPlaying" : {
2019-01-26 18:54:22 +00:00
newFrames : "bufferingPlaying" ,
2019-01-03 00:26:42 +00:00
pause : "hasController" ,
noController : "initialPlaying"
2018-12-17 17:15:58 +00:00
} ,
2019-01-26 18:54:22 +00:00
"buffering" : {
play : "bufferingPlaying" ,
enough : "paused" ,
noMoreFrames : "pausedAllLoaded" ,
startSeeking : "seeking" ,
noController : "initial"
} ,
"bufferingPlaying" : {
pause : "buffering" ,
enough : "playing" ,
noMoreFrames : "playingAllLoaded" ,
startSeeking : "seekingPlaying" ,
noController : "initialPlaying"
} ,
"seeking" : {
stopSeeking : "buffering" ,
noMoreFrames : "seekingAllLoaded" ,
noController : "initial"
} ,
"seekingPlaying" : {
stopSeeking : "bufferingPlaying" ,
noMoreFrames : "playingAllLoaded" ,
noController : "initialPlaying"
} ,
"seekingAllLoaded" : {
stopSeeking : "pausedAllLoaded" ,
noController : "initial"
} ,
"seekingPlayingAllLoaded" : {
stopSeeking : "playingAllLoaded" ,
noController : "initialPlaying"
} ,
2018-12-17 17:15:58 +00:00
"paused" : {
play : "playing" ,
2019-01-26 18:54:22 +00:00
notEnough : "buffering" ,
2019-01-03 00:26:42 +00:00
noController : "initial" ,
2019-01-26 18:54:22 +00:00
noMoreFrames : "pausedAllLoaded" ,
startSeeking : "seeking"
2018-12-17 17:15:58 +00:00
} ,
"pausedAllLoaded" : {
2019-01-03 00:26:42 +00:00
play : "playingAllLoaded" ,
2019-01-26 18:54:22 +00:00
noController : "initial" ,
startSeeking : "seekingAllLoaded"
2018-12-17 17:15:58 +00:00
} ,
"playing" : {
2018-12-21 21:21:12 +00:00
pause : "paused" ,
2019-01-26 18:54:22 +00:00
notEnough : "bufferingPlaying" ,
2019-01-03 00:26:42 +00:00
noMoreFrames : "playingAllLoaded" ,
2019-01-26 18:54:22 +00:00
noController : "initialPlaying" ,
startSeeking : "seekingPlaying"
2018-12-17 17:15:58 +00:00
} ,
"playingAllLoaded" : {
2019-01-03 00:26:42 +00:00
pause : "pausedAllLoaded" ,
2019-01-26 18:54:22 +00:00
noController : "initialPlaying" ,
startSeeking : "seekingPlayingAllLoaded"
2018-12-17 17:15:58 +00:00
}
}
2019-01-26 18:54:22 +00:00
var seekingStates = [ "seeking" , "seekingPlaying" , "seekingAllLoaded" , "seekingPlayingAllLoaded" ]
2018-12-17 17:15:58 +00:00
2019-01-26 18:54:22 +00:00
var audioPortion = 1024 * 50 ; //bytes to download for each portion
var threshold = 2 ; //seconds to buffer before playing
var intervalPrecision = 100 ; //millisecond of how often to check the playback
2019-01-24 19:54:16 +00:00
2019-01-30 20:36:33 +00:00
var Slider = Model . inherit ( {
className : "Slider" ,
2019-01-24 19:54:16 +00:00
constructor : function ( properties ) {
Model . fn . constructor . call ( this , properties ) ;
2019-01-30 20:36:33 +00:00
this . enabled = true ;
this . value = 0 ;
2019-01-24 19:54:16 +00:00
this . initialized = true ;
} ,
2019-01-30 20:36:33 +00:00
enable : function ( en ) {
if ( en !== this . enabled ) {
this . enabled = en ;
this . trigger ( "enabled" , en ) ;
}
} ,
setValue : function ( p ) {
if ( p !== this . value ) {
this . value = p ;
this . trigger ( "value" , p ) ;
}
}
} ) ;
var ProgressModel = Slider . inherit ( {
className : "ProgressModel" ,
constructor : function ( properties ) {
Slider . fn . constructor . call ( this , properties ) ;
this . value = 0 ;
} ,
2019-01-24 19:54:16 +00:00
setLoad : function ( l ) {
if ( l !== this . load ) {
this . load = l ;
this . trigger ( "load" , l ) ;
}
}
} ) ;
2018-09-02 19:22:28 +00:00
module . exports = Player ;