<commit_before>//
// Flambe - Rapid game development
// https://github.com/aduros/flambe/blob/master/LICENSE.txt

package flambe.platform.html;

import js.Dom;
import js.Lib;

import haxe.Http;

import flambe.asset.AssetEntry;
import flambe.asset.Manifest;
import flambe.util.Signal0;
import flambe.util.Signal1;

class HtmlAssetPackLoader extends BasicAssetPackLoader
{
    public function new (platform :HtmlPlatform, manifest :Manifest)
    {
        super(platform, manifest);
    }

    override private function loadEntry (url :String, entry :AssetEntry)
    {
        switch (entry.type) {
        case Image:
            var image :Dynamic = untyped __new__("Image");
            image.onload = function (_) {
#if debug
                if (image.width > 1024 || image.height > 1024) {
                    Log.warn("Images larger than 1024px on a side will prevent GPU acceleration" +
                        " on some platforms (iOS)", ["url", url,
                        "width", image.width, "height", image.height]);
                }
#end
                var texture = _platform.getRenderer().createTexture(image);
                if (texture != null) {
                    handleLoad(entry, texture);
                } else {
                    handleTextureError(entry);
                }
            };
            image.onerror = function (_) {
                handleError(entry, "Failed to load image");
            };

            // If this browser supports Blob, load the image data over XHR to benefit from progress
            // events, otherwise just set the src directly
            if (supportsBlob()) {
                sendRequest(url, entry, "blob", function (blob) {
                    image.addEventListener("load", function (_) {
                        _URL.revokeObjectURL(image.src);
                    }, false);
                    image.src = _URL.createObjectURL(blob);
                });
            } else {
                image.src = url;
            }

        case Audio:
            // If we made it this far, we definitely support audio and can play this asset
            if (WebAudioSound.supported) {
                sendRequest(url, entry, "arraybuffer", function (buffer) {
                    WebAudioSound.ctx.decodeAudioData(buffer, function (decoded) {
                        handleLoad(entry, new WebAudioSound(decoded));
                    }, function () {
                        // Happens in iOS 6 beta for some sounds that should be able to play. It
                        // seems that monochannel audio will always fail, try converting to stereo.
                        // Since this happens unpredictably, continue with a DummySound rather than
                        // rejecting the entire asset pack.
                        Log.warn("Couldn't decode Web Audio, ignoring this asset." +
                            " Is this a buggy browser?", ["url", url]);
                        handleLoad(entry, DummySound.getInstance());
                    });
                });

            } else {
                var audio :Dynamic = Lib.document.createElement("audio");
                audio.preload = "auto"; // Hint that we want to preload the entire file

                // Maintain a hard reference to the audio during loading to prevent GC on some
                // browsers
                var ref = ++_mediaRefCount;
                if (_mediaElements == null) {
                    _mediaElements = new IntHash();
                }
                _mediaElements.set(ref, audio);

                var events = new EventGroup();
                events.addDisposingListener(audio, "canplaythrough", function (_) {
                    _mediaElements.remove(ref);
                    handleLoad(entry, new HtmlSound(audio));
                });
                events.addDisposingListener(audio, "error", function (_) {
                    _mediaElements.remove(ref);
                    handleError(entry, "Failed to load audio: " + audio.error.code);
                });


                // TODO(bruno): Handle progress events
                audio.src = url;
                audio.load();
            }

        case Data:
            sendRequest(url, entry, "text", function (text) {
                handleLoad(entry, text);
            });
        }
    }

    override private function getAudioFormats () :Array<String>
    {
        if (_audioFormats == null) {
            _audioFormats = detectAudioFormats();
        }
        return _audioFormats;
    }

    private function sendRequest (url :String, entry :AssetEntry, responseType :String, onLoad :Dynamic -> Void)
    {<commit_msg>Use an EventGroup to ensure all listeners get cleaned out after loading.<commit_after>//
// Flambe - Rapid game development
// https://github.com/aduros/flambe/blob/master/LICENSE.txt

package flambe.platform.html;

import js.Dom;
import js.Lib;

import haxe.Http;

import flambe.asset.AssetEntry;
import flambe.asset.Manifest;
import flambe.util.Signal0;
import flambe.util.Signal1;

class HtmlAssetPackLoader extends BasicAssetPackLoader
{
    public function new (platform :HtmlPlatform, manifest :Manifest)
    {
        super(platform, manifest);
    }

    override private function loadEntry (url :String, entry :AssetEntry)
    {
        switch (entry.type) {
        case Image:
            var image :Dynamic = untyped __new__("Image");
            var events = new EventGroup();

            events.addDisposingListener(image, "load", function (_) {
#if debug
                if (image.width > 1024 || image.height > 1024) {
                    Log.warn("Images larger than 1024px on a side will prevent GPU acceleration" +
                        " on some platforms (iOS)", ["url", url,
                        "width", image.width, "height", image.height]);
                }
#end
                if (supportsBlob()) {
                    // Reclaim memory previously allocated by createObjectURL
                    _URL.revokeObjectURL(image.src);
                }

                var texture = _platform.getRenderer().createTexture(image);
                if (texture != null) {
                    handleLoad(entry, texture);
                } else {
                    handleTextureError(entry);
                }
            });
            events.addDisposingListener(image, "error", function (_) {
                handleError(entry, "Failed to load image");
            });

            // If this browser supports Blob, load the image data over XHR to benefit from progress
            // events, otherwise just set the src directly
            if (supportsBlob()) {
                sendRequest(url, entry, "blob", function (blob) {
                    image.src = _URL.createObjectURL(blob);
                });
            } else {
                image.src = url;
            }

        case Audio:
            // If we made it this far, we definitely support audio and can play this asset
            if (WebAudioSound.supported) {
                sendRequest(url, entry, "arraybuffer", function (buffer) {
                    WebAudioSound.ctx.decodeAudioData(buffer, function (decoded) {
                        handleLoad(entry, new WebAudioSound(decoded));
                    }, function () {
                        // Happens in iOS 6 beta for some sounds that should be able to play. It
                        // seems that monochannel audio will always fail, try converting to stereo.
                        // Since this happens unpredictably, continue with a DummySound rather than
                        // rejecting the entire asset pack.
                        Log.warn("Couldn't decode Web Audio, ignoring this asset." +
                            " Is this a buggy browser?", ["url", url]);
                        handleLoad(entry, DummySound.getInstance());
                    });
                });

            } else {
                var audio :Dynamic = Lib.document.createElement("audio");
                audio.preload = "auto"; // Hint that we want to preload the entire file

                // Maintain a hard reference to the audio during loading to prevent GC on some
                // browsers
                var ref = ++_mediaRefCount;
                if (_mediaElements == null) {
                    _mediaElements = new IntHash();
                }
                _mediaElements.set(ref, audio);

                var events = new EventGroup();
                events.addDisposingListener(audio, "canplaythrough", function (_) {
                    _mediaElements.remove(ref);
                    handleLoad(entry, new HtmlSound(audio));
                });
                events.addDisposingListener(audio, "error", function (_) {
                    _mediaElements.remove(ref);
                    handleError(entry, "Failed to load audio: " + audio.error.code);
                });

                // TODO(bruno): Handle progress events
                audio.src = url;
                audio.load();
            }

        case Data:
            sendRequest(url, entry, "text", function (text) {
                handleLoad(entry, text);
            });
        }
    }

    override private function getAudioFormats () :Array<String>
    {
        if (_audioFormats == null) {
            _audioFormats = detectAudioFormats();
        }
        return _audioFormats;
    }

    private function sendRequest (url :String, entry :AssetEntry, responseType :String, onLoad :Dynamic -> Void)
    {
{'fraction_non_alphanumeric': 0.09331797235023041, 'fraction_numerical': 0.003142019271051529, 'mean_word_length': 1.5362549800796812, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 11, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2005039', 'n_tokens_mistral': 2395, 'n_tokens_neox': 2218, 'n_words': 680}