API Docs for: 1.0.1

File: js\grape\resource\audio.js

define(['../class', '../env', './cacheable', '../utils'], function (Class, Env, Cacheable, Utils) {
    /*global Audio, AudioBuffer, Media, Cordova*/
    //TODOv2 partial preload for large files
    var defaultPlayOpts = {
        volume: 100
    };

    /*jshint newcap:false */
    /*global webkitAudioContext */
    var context = typeof webkitAudioContext === 'function' ? new webkitAudioContext() : null;

    var canPlay = (function () {
        var extensions, formats, i, max, canPlayTypes, audio, can;
        if (typeof Audio === 'function') {
            extensions = ['mp3', 'wav', 'ogg'];
            formats = ['audio/mpeg', 'audio/wav; codecs="1"', 'audio/ogg; codecs="vorbis"'];
            audio = new Audio();
            canPlayTypes = {};
            for (i = 0, max = extensions.length; i < max; ++i) {
                can = audio.canPlayType(formats[i]);
                if (can === 'maybe' || can === 'probably') {
                    canPlayTypes[extensions[i]] = true;
                }
            }
            return canPlayTypes;
        } else {
            return {};
        }
    })();

    function getPhoneGapPath() {
        var path = window.location.pathname;
        return 'file://' + path.substr(0, path.length - 10);
    }

    /**
     * Represents a sound. It decides from the extension of the given url which to use.
     *
     * @class Grape.Audio
     * @uses Grape.Cacheable
     * @constructor
     * @param {Object} opts Audio options
     * @param {String} url1 Audio URL
     * @param {String} url2 Audio URL fallback if url1 extension is not supported
     * @param {String} url3 Audio URL fallback if url2 extension is not supported
     */
    return Class('Audio', Cacheable, {
        init: function (opts, url1, url2, url3) {
            var url = null,
                urls, i;
            if (typeof opts === 'string') { //no opts given
                url3 = url2;
                url2 = url1;
                url1 = opts;
                opts = {}; //todov2 use
            }


            urls = [url1, url2, url3];
            for (i = 0; i < urls.length; ++i) {
                if (urls[i] && canPlay[urls[i].substring(urls[i].length - 3)]) {
                    url = urls[i];
                    break;
                }
            }
            if (url === null) {
                //TODOv2 warning None of the given formats is supported by your browser!
            }

            this.url = url;
        },
        'override loadResource': function (onFinish, onError) { //TODOv2 preload phonegap audio
            if (Env.node) {
                onFinish(null);
            } else if (location.protocol !== 'file:' && typeof Blob === 'function') { //load as blob
                Utils.ajax(this.url, {responseType: 'arraybuffer'}, function (response) {
                    if (context && typeof intel==='undefined') {
                        context.decodeAudioData(response, function (buffer) {
                            onFinish(buffer);
                        });
                    } else {
                        var blob = new Blob([response], {type: 'audio'});
                        onFinish({
                            url: URL.createObjectURL(blob),
                            blob: blob
                        });
                    }
                }, function () {
                    onError();
                });
            } else if (typeof Audio === 'function' && typeof Cordova === 'undefined') {
                //TODOv2 IE9 loads a sound multiple times
                var a = new Audio();
                a.src = this.url;
                a.addEventListener('canplaythrough', function () {
                    var arr = [];
                    arr.next = 0;
                    for (var i = 0; i < 8; ++i) {
                        arr[i] = a.cloneNode(false);
                    }
                    onFinish(arr);
                }, false);
                a.load();
            } else if (typeof Media === 'function') {
                onFinish('cordova');
            } else {
                //No audio support
                onFinish(null);
            }
        },
        'override getResourceKey': function () {
            return this.url;
        },
        'override process': function (buffer) {
            this.buffer = buffer;
        },
        /**
         * Plays the audio.
         *
         * @method play
         */
        'play': function (opts) {
            var src, snd;
            if (this.buffer === undefined) {
                throw new Error('Audio is not loaded yet.');
            }
            opts = opts || defaultPlayOpts; //TODOv2 use

            //TODOv2 separate to classes instead of instanceof
            if (this.buffer === null) { //no sound

            } else if (typeof this.buffer === 'object' && this.buffer.url) { //loading created a blob url
                snd = new Audio(this.buffer.url);
                snd.play();
            } else if (context && this.buffer instanceof AudioBuffer) {//webAudio
                src = context.createBufferSource();
                src.buffer = this.buffer;
                src.connect(context.destination);
                src.noteOn(0);
            } else if (typeof Audio === 'function' && typeof Cordova === 'undefined' && this.buffer instanceof Array) { //IE9
                snd = this.buffer[this.buffer.next++];
                if (this.buffer.next === this.buffer.length) {
                    this.buffer.next = 0;
                }
                snd.play();
            } else if (typeof Media !== 'undefined') { //Cordova
                src = getPhoneGapPath() + this.url;
                snd = new Media(src, function () {
                    snd.release();
                }, function () {
                    //TODOv2 handle error
                });
                snd.play();
            }
        }
    });
});