2013-10-28 20:00:20 +00:00
// Copyright (C) 2013 Massachusetts Institute of Technology
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License version 2,
// as published by the Free Software Foundation.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
// Scratch HTML5 Player
// IO.js
// Tim Mickel, March 2012
// IO handles JSON communication and processing.
// We make the sprites and threads here.
'use strict' ;
var IO = function ( ) {
this . data = null ;
2014-09-08 15:52:23 -04:00
this . project _base = 'http://cdn.projects.scratch.mit.edu/internalapi/project/' ;
2013-10-28 20:00:20 +00:00
this . project _suffix = '/get/' ;
2014-09-08 15:52:23 -04:00
this . asset _base = 'http://cdn.assets.scratch.mit.edu/internalapi/asset/' ;
2013-10-28 20:00:20 +00:00
this . asset _suffix = '/get/' ;
this . soundbank _base = 'soundbank/' ;
this . spriteLayerCount = 0 ;
2013-11-01 22:44:51 -04:00
} ;
2013-10-28 20:00:20 +00:00
IO . prototype . loadProject = function ( project _id ) {
2014-04-09 01:17:50 -07:00
var self = this ;
2013-11-01 22:44:51 -04:00
$ . getJSON ( this . project _base + project _id + this . project _suffix , function ( data ) {
2014-04-09 01:17:50 -07:00
self . data = data ;
self . makeObjects ( ) ;
self . loadThreads ( ) ;
self . loadNotesDrums ( ) ;
2013-11-01 22:44:51 -04:00
runtime . loadStart ( ) ; // Try to run the project.
} ) ;
} ;
2013-10-28 20:00:20 +00:00
IO . prototype . soundRequest = function ( sound , sprite ) {
var request = new XMLHttpRequest ( ) ;
request . open ( 'GET' , this . asset _base + sound [ 'md5' ] + this . asset _suffix , true ) ;
request . responseType = 'arraybuffer' ;
request . onload = function ( ) {
var waveData = request . response ;
// Decode the waveData and populate a buffer channel with the samples
var snd = new SoundDecoder ( waveData ) ;
var samples = snd . getAllSamples ( ) ;
sound . buffer = runtime . audioContext . createBuffer ( 1 , samples . length , runtime . audioContext . sampleRate ) ;
var data = sound . buffer . getChannelData ( 0 ) ;
for ( var i = 0 ; i < data . length ; i ++ ) {
data [ i ] = samples [ i ] ;
}
sprite . soundsLoaded ++ ;
2013-11-01 22:44:51 -04:00
} ;
2013-10-28 20:00:20 +00:00
request . send ( ) ;
2013-11-01 22:44:51 -04:00
} ;
2013-10-28 20:00:20 +00:00
IO . prototype . loadNotesDrums = function ( ) {
var self = this ;
$ . each ( Instr . wavs , function ( name , file ) {
var request = new XMLHttpRequest ( ) ;
request . open ( 'GET' , self . soundbank _base + escape ( file ) , true ) ;
request . responseType = 'arraybuffer' ;
request . onload = function ( ) {
var waveData = new OffsetBuffer ( request . response ) ;
// Decode the waveData and populate a buffer channel with the samples
var info = WAVFile . decode ( request . response ) ;
waveData . offset = info . sampleDataStart ;
var soundBuffer = waveData . readBytes ( 2 * info . sampleCount ) ;
Instr . samples [ name ] = soundBuffer ;
Instr . wavsLoaded ++ ;
2013-11-01 22:44:51 -04:00
} ;
2013-10-28 20:00:20 +00:00
request . send ( ) ;
} ) ;
2013-11-01 22:44:51 -04:00
} ;
2013-10-28 20:00:20 +00:00
IO . prototype . makeObjects = function ( ) {
// Create the stage
runtime . stage = new Stage ( this . data ) ;
runtime . stage . attach ( runtime . scene ) ;
runtime . stage . attachPenLayer ( runtime . scene ) ;
runtime . stage . loadSounds ( ) ;
2013-10-30 21:16:15 +02:00
// Create the sprites and watchers
2013-11-04 22:28:23 +02:00
function createObj ( obj , sprite ) {
2013-10-28 20:00:20 +00:00
var newSprite ;
2013-11-04 22:28:23 +02:00
function createSprite ( obj ) {
var newSprite = new Sprite ( obj ) ;
2013-10-28 20:00:20 +00:00
newSprite . loadSounds ( ) ;
2013-11-04 22:28:23 +02:00
return newSprite ;
}
function createReporter ( obj , sprite ) {
var newSprite ;
if ( obj . listName ) { // list
if ( ! ( sprite === runtime . stage && ! runtime . stage . lists [ obj . listName ] ) ) { // for local lists, only if in sprite
newSprite = new List ( obj , sprite . objName ) ;
runtime . reporters . push ( newSprite ) ;
}
} else {
newSprite = new Reporter ( obj ) ;
runtime . reporters . push ( newSprite ) ;
}
return newSprite ;
}
2014-07-25 11:16:34 +01:00
if ( typeof ( obj . objName ) === "string" ) { // sprite
2013-11-04 22:28:23 +02:00
newSprite = createSprite ( obj ) ;
sprite = newSprite ;
2013-10-28 20:00:20 +00:00
} else {
2013-11-04 22:28:23 +02:00
newSprite = createReporter ( obj , sprite ) ;
2013-10-28 20:00:20 +00:00
}
2013-11-04 22:28:23 +02:00
if ( newSprite ) {
runtime . sprites . push ( newSprite ) ;
newSprite . attach ( runtime . scene ) ;
}
}
$ . each ( this . data . children , function ( index , obj ) {
createObj ( obj , runtime . stage ) ; // create children of stage - sprites, watchers, and stage's lists
} ) ;
2014-04-09 01:17:50 -07:00
$ . each ( runtime . sprites . filter ( function ( sprite ) { return sprite instanceof Sprite } ) , function ( index , sprite ) { // list of sprites
$ . each ( sprite . lists , function ( index , list ) {
2013-11-04 22:28:23 +02:00
createObj ( list , sprite ) ; // create local lists
} ) ;
2013-10-28 20:00:20 +00:00
} ) ;
2013-11-01 22:44:51 -04:00
} ;
2013-10-28 20:00:20 +00:00
IO . prototype . loadThreads = function ( ) {
var target = runtime . stage ;
var scripts = target . data . scripts ;
if ( scripts ) {
for ( var s in scripts ) {
target . stacks . push ( interp . makeBlockList ( scripts [ s ] [ 2 ] ) ) ;
}
}
$ . each ( this . data . children , function ( index , obj ) {
target = runtime . sprites [ index ] ;
if ( typeof ( target ) != 'undefined' && target . data && target . data . scripts ) {
$ . each ( target . data . scripts , function ( j , s ) {
target . stacks . push ( interp . makeBlockList ( s [ 2 ] ) ) ;
} ) ;
2013-11-01 22:44:51 -04:00
}
2013-10-28 20:00:20 +00:00
} ) ;
2013-11-01 22:44:51 -04:00
} ;
2013-10-28 20:00:20 +00:00
// Returns the number sprite we are rendering
// used for initial layering assignment
IO . prototype . getCount = function ( ) {
var rv = this . spriteLayerCount ;
this . spriteLayerCount ++ ;
return rv ;
2013-11-01 22:44:51 -04:00
} ;