Barely working basic playback
This commit is contained in:
parent
98a443e298
commit
9b5198a6ce
19 changed files with 406 additions and 24 deletions
|
@ -4,3 +4,4 @@ configure_file(class.js class.js)
|
|||
configure_file(subscribable.js subscribable.js)
|
||||
configure_file(globalMethods.js globalMethods.js)
|
||||
configure_file(enum.js enum.js)
|
||||
configure_file(stateMachine.js stateMachine)
|
||||
|
|
33
libjs/utils/stateMachine.js
Normal file
33
libjs/utils/stateMachine.js
Normal file
|
@ -0,0 +1,33 @@
|
|||
"use strict";
|
||||
|
||||
var Subscribable = require("./subscribable");
|
||||
|
||||
var StateMachine = Subscribable.inherit({
|
||||
className: "StateMachine",
|
||||
constructor: function (initialState, graph) {
|
||||
Subscribable.fn.constructor.call(this);
|
||||
|
||||
this._state = initialState;
|
||||
this._graph = graph;
|
||||
},
|
||||
manipulation: function (name) {
|
||||
var newState = this._graph[this._state][name];
|
||||
if (newState) {
|
||||
var oldState = this._state;
|
||||
this._state = newState;
|
||||
|
||||
this.trigger("stateChanged", {
|
||||
newState: newState,
|
||||
manipulation: name,
|
||||
oldState: oldState
|
||||
});
|
||||
} else {
|
||||
this.trigger("stateMissed");
|
||||
}
|
||||
},
|
||||
state: function () {
|
||||
return this._state;
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = StateMachine;
|
|
@ -17,5 +17,6 @@ configure_file(localModel.js localModel.js)
|
|||
configure_file(catalogue.js catalogue.js)
|
||||
configure_file(imagePane.js imagePane.js)
|
||||
configure_file(file/file.js file/file.js)
|
||||
configure_file(file/audio.js file/audio.js)
|
||||
configure_file(player.js player.js)
|
||||
configure_file(imageById.js imageById.js)
|
||||
|
|
69
libjs/wController/file/audio.js
Normal file
69
libjs/wController/file/audio.js
Normal file
|
@ -0,0 +1,69 @@
|
|||
"use strict";
|
||||
|
||||
var File = require("./file");
|
||||
var Vocabulary = require("../../wType/vocabulary");
|
||||
var Uint64 = require("../../wType/uint64");
|
||||
|
||||
var Audio = File.inherit({
|
||||
className: "Audio",
|
||||
constructor: function Audio(addr) {
|
||||
File.fn.constructor.call(this, addr);
|
||||
|
||||
this._loadedFrames = 0;
|
||||
this._totalFrames = 0;
|
||||
this._waitingForFrames = false;
|
||||
this._portions = [];
|
||||
|
||||
this.addHandler("responseFrames");
|
||||
},
|
||||
hasMore: function() {
|
||||
return this._totalFrames > this._loadedFrames;
|
||||
},
|
||||
_getAdditional: function(add) {
|
||||
var ac = File.fn._getAdditional.call(this, add);
|
||||
|
||||
if (ac) {
|
||||
this._loadedFrames = 0;
|
||||
this._totalFrames = this._additional.at("framesAmount").valueOf();
|
||||
this._waitingForFrames = false;
|
||||
}
|
||||
|
||||
this.initialized = true;
|
||||
return ac;
|
||||
},
|
||||
_h_responseFrames: function(ev) {
|
||||
if (this._waitingForFrames === true) {
|
||||
var data = ev.getData();
|
||||
|
||||
var success = data.at("result").valueOf();
|
||||
if (success === 0) {
|
||||
var amount = data.at("amount").valueOf();
|
||||
var blob = data.at("data").clone();
|
||||
this._loadedFrames += amount;
|
||||
this._waitingForFrames = false;
|
||||
this._portions.push(blob);
|
||||
this.trigger("newFrames", blob);
|
||||
}
|
||||
}
|
||||
},
|
||||
requestMore: function() {
|
||||
if (!this._waitingForFrames) {
|
||||
if (this._registered && this._subscribed) {
|
||||
var allowed = this._totalFrames - this._loadedFrames;
|
||||
|
||||
if (allowed > 0) {
|
||||
var vc = new Vocabulary();
|
||||
vc.insert("index", new Uint64(this._loadedFrames));
|
||||
vc.insert("amount", new Uint64(Math.min(framePortion, allowed)));
|
||||
|
||||
this.send(vc, "requestFrames");
|
||||
this._waitingForFrames = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
var framePortion = 10;
|
||||
|
||||
module.exports = Audio;
|
|
@ -7,7 +7,10 @@ var Controller = require("./controller");
|
|||
var Button = require("./button");
|
||||
var ImageById = require("./imageById");
|
||||
var Vocabulary = require("./vocabulary");
|
||||
var Audio = require("./file/audio");
|
||||
|
||||
var Enum = require("../utils/enum");
|
||||
var StateMachine = require("../utils/stateMachine");
|
||||
|
||||
var Player = Controller.inherit({
|
||||
className: "Player",
|
||||
|
@ -17,9 +20,24 @@ var Player = Controller.inherit({
|
|||
this.controls = Object.create(null);
|
||||
this.views = Object.create(null);
|
||||
this.mode = PlayerMode.straight.playback;
|
||||
this._audio = null;
|
||||
this._sound = new window.Audio();
|
||||
this._ctx = new AudioContext();
|
||||
this._currentTime = 0;
|
||||
this._createStateMachine();
|
||||
this._proxySchedule = this._schedule.bind(this);
|
||||
|
||||
this.addHandler("get");
|
||||
this.addHandler("viewsChange");
|
||||
this.addHandler("play");
|
||||
this.addHandler("pause");
|
||||
},
|
||||
destructor: function() {
|
||||
this._fsm.destructor();
|
||||
this._sound.pause();
|
||||
this._ctx.close();
|
||||
|
||||
Controller.fn.destructor.call(this);
|
||||
},
|
||||
_addControl: function(type, address) {
|
||||
var t = type.valueOf();
|
||||
|
@ -87,6 +105,10 @@ var Player = Controller.inherit({
|
|||
this.trigger("newElement", ctrl, t);
|
||||
}
|
||||
},
|
||||
_createStateMachine: function() {
|
||||
this._fsm = new StateMachine("initial", graphs[this.mode]);
|
||||
this._fsm.on("stateChanged", this._onStateChanged, this);
|
||||
},
|
||||
_h_get: function(ev) {
|
||||
var data = ev.getData();
|
||||
|
||||
|
@ -117,6 +139,12 @@ var Player = Controller.inherit({
|
|||
this.initialized = true;
|
||||
this.trigger("data");
|
||||
},
|
||||
_h_pause: function(ev) {
|
||||
this._fsm.manipulation("plause");
|
||||
},
|
||||
_h_play: function(ev) {
|
||||
this._fsm.manipulation("play");
|
||||
},
|
||||
_h_viewsChange: function(ev) {
|
||||
var data = ev.getData();
|
||||
|
||||
|
@ -135,6 +163,15 @@ var Player = Controller.inherit({
|
|||
this._addView(vc.at("type"), vc.at("address"));
|
||||
}
|
||||
},
|
||||
_onAudioNewFrames: function(frames) {
|
||||
this._ctx.decodeAudioData(frames.valueOf(), this._proxySchedule);
|
||||
this._fsm.manipulation("newFrames");
|
||||
if (this._audio.hasMore()) {
|
||||
this._audio.requestMore();
|
||||
} else {
|
||||
this._fsm.manipulation("noMoreFrames");
|
||||
}
|
||||
},
|
||||
_onNewPlayBackElement: function(key, element) {
|
||||
switch (key) {
|
||||
case "image":
|
||||
|
@ -142,6 +179,14 @@ var Player = Controller.inherit({
|
|||
this._addView(new Uint64(ItemType.straight.picture), address);
|
||||
address.destructor();
|
||||
break;
|
||||
case "audio":
|
||||
if (this.mode === PlayerMode.straight.playback) {
|
||||
this._audio = new Audio(new Address(["music", element.toString()]));
|
||||
this.addForeignController("Corax", this._audio);
|
||||
this._audio.on("newFrames", this._onAudioNewFrames, this);
|
||||
this._fsm.manipulation("controller");
|
||||
}
|
||||
break;
|
||||
}
|
||||
},
|
||||
_onNewRemoveBackElement: function(key) {
|
||||
|
@ -149,6 +194,51 @@ var Player = Controller.inherit({
|
|||
case "image":
|
||||
this._removeView(new Uint64(ItemType.straight.picture));
|
||||
break;
|
||||
case "audio":
|
||||
this.removeForeignController(this._audio);
|
||||
this._audio.destructor();
|
||||
this._audio = null;
|
||||
}
|
||||
},
|
||||
_onStateChanged: function(e) {
|
||||
switch (e.newState) {
|
||||
case "initial":
|
||||
break;
|
||||
case "initialPlaying":
|
||||
break;
|
||||
case "hasController":
|
||||
break;
|
||||
case "hasControllerPlaying":
|
||||
if (this._audio.hasMore()) {
|
||||
this._audio.requestMore();
|
||||
} else {
|
||||
this._fsm.manipulation("noMoreFrames");
|
||||
}
|
||||
break;
|
||||
case "paused":
|
||||
switch (e.oldState) {
|
||||
case "playing":
|
||||
this._sound.pause();
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case "pausedAllLoaded":
|
||||
switch (e.oldState) {
|
||||
case "playingAllLoaded":
|
||||
this._sound.pause();
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case "playing":
|
||||
this._sound.play();
|
||||
break;
|
||||
case "playingAllLoaded":
|
||||
switch (e.oldState) {
|
||||
case "pausedAllLoaded":
|
||||
this._sound.play();
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
},
|
||||
_removeControl: function(type) {
|
||||
|
@ -156,6 +246,14 @@ var Player = Controller.inherit({
|
|||
},
|
||||
_removeView: function(type) {
|
||||
//TODO
|
||||
},
|
||||
_schedule: function(buffer) {
|
||||
var source = this._ctx.createBufferSource();
|
||||
source.buffer = buffer;
|
||||
source.connect(this._ctx.destination);
|
||||
|
||||
source.start(this._currentTime);
|
||||
this._currentTime += buffer.duration;
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -170,4 +268,38 @@ PlayerMode.add("playback");
|
|||
|
||||
Player.ItemType = ItemType;
|
||||
|
||||
var graphs = Object.create(null);
|
||||
graphs[PlayerMode.straight.playback] = {
|
||||
"initial": {
|
||||
controller: "hasController",
|
||||
play: "initialPlaying"
|
||||
},
|
||||
"initialPlaying": {
|
||||
pause: "initial",
|
||||
controller: "hasControllerPlaying"
|
||||
},
|
||||
"hasController": {
|
||||
newFrames: "paused",
|
||||
play: "hasControllerPlaying"
|
||||
},
|
||||
"hasControllerPlaying": {
|
||||
newFrames: "playing",
|
||||
pause: "hasController"
|
||||
},
|
||||
"paused": {
|
||||
play: "playing",
|
||||
noMoreFrames: "pausedAllLoaded"
|
||||
},
|
||||
"pausedAllLoaded": {
|
||||
play: "playingAllLoaded"
|
||||
},
|
||||
"playing": {
|
||||
pause: "pause",
|
||||
noMoreFrames: "playingAllLoaded"
|
||||
},
|
||||
"playingAllLoaded": {
|
||||
pause: "pausedAllLoaded"
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Player;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue