/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mangui.hls.stream {
    import org.mangui.hls.controller.BufferThresholdController;
    import org.mangui.hls.event.HLSPlayMetrics;
    import org.mangui.hls.event.HLSError;
    import org.mangui.hls.event.HLSEvent;
    import org.mangui.hls.constant.HLSSeekStates;
    import org.mangui.hls.constant.HLSPlayStates;
    import org.mangui.hls.flv.FLVTag;
    import org.mangui.hls.HLS;
    import org.mangui.hls.HLSSettings;
    import org.mangui.hls.utils.Hex;

    import flash.events.Event;
    import flash.events.NetStatusEvent;
    import flash.events.TimerEvent;
    import flash.net.*;
    import flash.utils.*;

    CONFIG::LOGGING {
        import org.mangui.hls.utils.Log;
    }
    /** Class that overrides standard flash.net.NetStream class, keeps the buffer filled, handles seek and play state
     *
     * play state transition :
     * 				FROM								TO								condition
     *  HLSPlayStates.IDLE              	HLSPlayStates.PLAYING_BUFFERING     play()/play2()/seek() called
     *  HLSPlayStates.PLAYING_BUFFERING  	HLSPlayStates.PLAYING  				buflen > minBufferLength
     *  HLSPlayStates.PAUSED_BUFFERING  	HLSPlayStates.PAUSED  				buflen > minBufferLength
     *  HLSPlayStates.PLAYING  				HLSPlayStates.PLAYING_BUFFERING  	buflen < lowBufferLength
     *  HLSPlayStates.PAUSED  				HLSPlayStates.PAUSED_BUFFERING  	buflen < lowBufferLength
     */
    public class HLSNetStream extends NetStream {
        /** Reference to the framework controller. **/
        private var _hls : HLS;
        /** reference to buffer threshold controller */
        private var _bufferThresholdController : BufferThresholdController;
        /** FLV Tag Buffer . **/
        private var _streamBuffer : StreamBuffer;
        /** Timer used to check buffer and position. **/
        private var _timer : Timer;
        /** Current playback state. **/
        private var _playbackState : String;
        /** Current seek state. **/
        private var _seekState : String;
        /** current playback level **/
        private var _playbackLevel : int;
        /** Netstream client proxy */
        private var _client : HLSNetStreamClient;

        /** Create the buffer. **/
        public function HLSNetStream(connection : NetConnection, hls : HLS, streamBuffer : StreamBuffer) : void {
            super(connection);
            super.bufferTime = 0.1;
            _hls = hls;
            _bufferThresholdController = new BufferThresholdController(hls);
            _streamBuffer = streamBuffer;
            _playbackState = HLSPlayStates.IDLE;
            _seekState = HLSSeekStates.IDLE;
            _timer = new Timer(100, 0);
            _timer.addEventListener(TimerEvent.TIMER, _checkBuffer);
            _client = new HLSNetStreamClient();
            _client.registerCallback("onHLSFragmentChange", onHLSFragmentChange);
            _client.registerCallback("onID3Data", onID3Data);
            super.client = _client;
        };

        public function onHLSFragmentChange(level : int, seqnum : int, cc : int, audio_only : Boolean, program_date : Number, width : int, height : int, ... tags) : void {
            CONFIG::LOGGING {
                Log.debug("playing fragment(level/sn/cc):" + level + "/" + seqnum + "/" + cc);
            }
            _playbackLevel = level;
            var tag_list : Array = new Array();
            for (var i : uint = 0; i < tags.length; i++) {
                tag_list.push(tags[i]);
                CONFIG::LOGGING {
                    Log.debug("custom tag:" + tags[i]);
                }
            }
            _hls.dispatchEvent(new HLSEvent(HLSEvent.FRAGMENT_PLAYING, new HLSPlayMetrics(level, seqnum, cc, audio_only, program_date, width, height, tag_list)));
        }

        // function is called by SCRIPT in FLV
        public function onID3Data(data : ByteArray) : void {
            var dump : String = "unset";

            // we dump the content as hex to get it to the Javascript in the browser.
            // from lots of searching, we could use base64, but even then, the decode would
            // not be native, so hex actually seems more efficient
            dump = Hex.fromArray(data);

            CONFIG::LOGGING {
                Log.debug("id3:" + dump);
            }
            _hls.dispatchEvent(new HLSEvent(HLSEvent.ID3_UPDATED, dump));
        }

        /** timer function, check/update NetStream state, and append tags if needed **/
        private function _checkBuffer(e : Event) : void {
            var buffer : Number = this.bufferLength;
            // Log.info("netstream/total:" + super.bufferLength + "/" + this.bufferLength);
            // Set playback state. no need to check buffer status if seeking
            if (_seekState != HLSSeekStates.SEEKING) {
                // check low buffer condition
                if (buffer <= 0.1) {
                    if (_streamBuffer.reachedEnd) {
                        // Last tag done? Then append sequence end.
                        super.appendBytesAction(NetStreamAppendBytesAction.END_SEQUENCE);
                        super.appendBytes(new ByteArray());
                        // reach end of playlist + playback complete (as buffer is empty).
                        // stop timer, report event and switch to IDLE mode.
                        _timer.stop();
                        CONFIG::LOGGING {
                            Log.debug("reached end of VOD playlist, notify playback complete");
                        }
                        _hls.dispatchEvent(new HLSEvent(HLSEvent.PLAYBACK_COMPLETE));
                        _setPlaybackState(HLSPlayStates.IDLE);
                        _setSeekState(HLSSeekStates.IDLE);
                        return;
                    } else {
                        // buffer <= 0.1 and not EOS, pause playback
                        super.pause();
                    }
                }
                // if buffer len is below lowBufferLength, get into buffering state
                if (!_streamBuffer.reachedEnd && buffer < _bufferThresholdController.lowBufferLength) {
                    if (_playbackState == HLSPlayStates.PLAYING) {
                        // low buffer condition and play state. switch to play buffering state
                        _setPlaybackState(HLSPlayStates.PLAYING_BUFFERING);
                    } else if (_playbackState == HLSPlayStates.PAUSED) {
                        // low buffer condition and pause state. switch to paused buffering state
                        _setPlaybackState(HLSPlayStates.PAUSED_BUFFERING);
                    }
                }
                // if buffer len is above minBufferLength, get out of buffering state
                if (buffer >= _bufferThresholdController.minBufferLength || _streamBuffer.reachedEnd) {
                    if (_playbackState == HLSPlayStates.PLAYING_BUFFERING) {
                        CONFIG::LOGGING {
                            Log.debug("resume playback");
                        }
                        // resume playback in case it was paused, this can happen if buffer was in really low condition (less than 0.1s)
                        super.resume();
                        _setPlaybackState(HLSPlayStates.PLAYING);
                    } else if (_playbackState == HLSPlayStates.PAUSED_BUFFERING) {
                        _setPlaybackState(HLSPlayStates.PAUSED);
                    }
                }
            }
        };

        /** Return the current playback state. **/
        public function get playbackState() : String {
            return _playbackState;
        };

        /** Return the current seek state. **/
        public function get seekState() : String {
            return _seekState;
        };

        /** Return the current playback quality level **/
        public function get playbackLevel() : int {
            return _playbackLevel;
        };

        /** append tags to NetStream **/
        public function appendTags(tags : Vector.<FLVTag>) : void {
            if (_seekState == HLSSeekStates.SEEKING) {
                /* this is our first injection after seek(),
                let's flush netstream now
                this is to avoid black screen during seek command */
                super.close();
                CONFIG::FLASH_11_1 {
                    try {
                        super.useHardwareDecoder = HLSSettings.useHardwareVideoDecoder;
                    } catch(e : Error) {
                    }
                }
                super.play(null);
                super.appendBytesAction(NetStreamAppendBytesAction.RESET_SEEK);
                // immediatly pause NetStream, it will be resumed when enough data will be buffered in the NetStream
                super.pause();

//                for each (var tag : FLVTag in tags) {
//                    CONFIG::LOGGING {
//                        Log.debug2('inject type/dts/pts:' + tag.typeString + '/' + tag.dts + '/' + tag.pts);
//                    }
//                }
            }
            // append all tags
            for each (var tagBuffer : FLVTag in tags) {
                try {
                    if (tagBuffer.type == FLVTag.DISCONTINUITY) {
                        super.appendBytesAction(NetStreamAppendBytesAction.RESET_BEGIN);
                        super.appendBytes(FLVTag.getHeader());
                    }
                    super.appendBytes(tagBuffer.data);
                } catch (error : Error) {
                    var hlsError : HLSError = new HLSError(HLSError.TAG_APPENDING_ERROR, null, tagBuffer.type + ": " + error.message);
                    _hls.dispatchEvent(new HLSEvent(HLSEvent.ERROR, hlsError));
                }
            }
            if (_seekState == HLSSeekStates.SEEKING) {
                // dispatch event to mimic NetStream behaviour
                dispatchEvent(new NetStatusEvent(NetStatusEvent.NET_STATUS, false, false, {code:"NetStream.Seek.Notify", level:"status"}));
                _setSeekState(HLSSeekStates.SEEKED);
            }
        };

        /** Change playback state. **/
        private function _setPlaybackState(state : String) : void {
            if (state != _playbackState) {
                CONFIG::LOGGING {
                    Log.debug('[PLAYBACK_STATE] from ' + _playbackState + ' to ' + state);
                }
                _playbackState = state;
                _hls.dispatchEvent(new HLSEvent(HLSEvent.PLAYBACK_STATE, _playbackState));
            }
        };

        /** Change seeking state. **/
        private function _setSeekState(state : String) : void {
            if (state != _seekState) {
                CONFIG::LOGGING {
                    Log.debug('[SEEK_STATE] from ' + _seekState + ' to ' + state);
                }
                _seekState = state;
                _hls.dispatchEvent(new HLSEvent(HLSEvent.SEEK_STATE, _seekState));
            }
        };

        override public function play(...args) : void {
            var _playStart : Number;
            if (args.length >= 2) {
                _playStart = Number(args[1]);
            } else {
                _playStart = -1;
            }
            CONFIG::LOGGING {
                Log.info("HLSNetStream:play(" + _playStart + ")");
            }
            seek(_playStart);
            _setPlaybackState(HLSPlayStates.PLAYING_BUFFERING);
        }

        override public function play2(param : NetStreamPlayOptions) : void {
            CONFIG::LOGGING {
                Log.info("HLSNetStream:play2(" + param.start + ")");
            }
            seek(param.start);
            _setPlaybackState(HLSPlayStates.PLAYING_BUFFERING);
        }

        /** Pause playback. **/
        override public function pause() : void {
            CONFIG::LOGGING {
                Log.info("HLSNetStream:pause");
            }
            if (_playbackState == HLSPlayStates.PLAYING) {
                super.pause();
                _setPlaybackState(HLSPlayStates.PAUSED);
            } else if (_playbackState == HLSPlayStates.PLAYING_BUFFERING) {
                super.pause();
                _setPlaybackState(HLSPlayStates.PAUSED_BUFFERING);
            }
        };

        /** Resume playback. **/
        override public function resume() : void {
            CONFIG::LOGGING {
                Log.info("HLSNetStream:resume");
            }
            if (_playbackState == HLSPlayStates.PAUSED) {
                super.resume();
                _setPlaybackState(HLSPlayStates.PLAYING);
            } else if (_playbackState == HLSPlayStates.PAUSED_BUFFERING) {
                // dont resume NetStream here, it will be resumed by Timer. this avoids resuming playback while seeking is in progress
                _setPlaybackState(HLSPlayStates.PLAYING_BUFFERING);
            }
        };

        /** get Buffer Length  **/
        override public function get bufferLength() : Number {
            return netStreamBufferLength + _streamBuffer.bufferLength;
        };

        /** get Back Buffer Length  **/
        override public function get backBufferLength() : Number {
            return _streamBuffer.backBufferLength;
        };

        public function get netStreamBufferLength() : Number {
            if (_seekState == HLSSeekStates.SEEKING) {
                return 0;
            } else {
                return super.bufferLength;
            }
        };

        /** Start playing data in the buffer. **/
        override public function seek(position : Number) : void {
            CONFIG::LOGGING {
                Log.info("HLSNetStream:seek(" + position + ")");
            }
            _streamBuffer.seek(position);
            _setSeekState(HLSSeekStates.SEEKING);
            /* if HLS was in paused state before seeking,
             * switch to paused buffering state
             * otherwise, switch to playing buffering state
             */
            switch(_playbackState) {
                case HLSPlayStates.PAUSED:
                case HLSPlayStates.PAUSED_BUFFERING:
                    _setPlaybackState(HLSPlayStates.PAUSED_BUFFERING);
                    break;
                case HLSPlayStates.IDLE:
                case HLSPlayStates.PLAYING:
                case HLSPlayStates.PLAYING_BUFFERING:
                    _setPlaybackState(HLSPlayStates.PLAYING_BUFFERING);
                    break;
                default:
                    break;
            }
            /* always pause NetStream while seeking, even if we are in play state
             * in that case, NetStream will be resumed during next call to appendTags()
             */
            super.pause();
            _timer.start();
        };

        public override function set client(client : Object) : void {
            _client.delegate = client;
        };

        public override function get client() : Object {
            return _client.delegate;
        }

        /** Stop playback. **/
        override public function close() : void {
            CONFIG::LOGGING {
                Log.info("HLSNetStream:close");
            }
            super.close();
            _streamBuffer.stop();
            _timer.stop();
            _setPlaybackState(HLSPlayStates.IDLE);
            _setSeekState(HLSSeekStates.IDLE);
        };

        public function dispose_() : void {
            close();
            _bufferThresholdController.dispose();
        }
    }
}

/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mangui.hls.stream {
    import org.mangui.hls.controller.BufferThresholdController;
    import org.mangui.hls.event.HLSPlayMetrics;
    import org.mangui.hls.event.HLSError;
    import org.mangui.hls.event.HLSEvent;
    import org.mangui.hls.constant.HLSSeekStates;
    import org.mangui.hls.constant.HLSPlayStates;
    import org.mangui.hls.flv.FLVTag;
    import org.mangui.hls.HLS;
    import org.mangui.hls.HLSSettings;
    import org.mangui.hls.utils.Hex;

    import flash.events.Event;
    import flash.events.NetStatusEvent;
    import flash.events.TimerEvent;
    import flash.net.*;
    import flash.utils.*;

    CONFIG::LOGGING {
        import org.mangui.hls.utils.Log;
    }
    /** Class that overrides standard flash.net.NetStream class, keeps the buffer filled, handles seek and play state
     *
     * play state transition :
     * 				FROM								TO								condition
     *  HLSPlayStates.IDLE              	HLSPlayStates.PLAYING_BUFFERING     play()/play2()/seek() called
     *  HLSPlayStates.PLAYING_BUFFERING  	HLSPlayStates.PLAYING  				buflen > minBufferLength
     *  HLSPlayStates.PAUSED_BUFFERING  	HLSPlayStates.PAUSED  				buflen > minBufferLength
     *  HLSPlayStates.PLAYING  				HLSPlayStates.PLAYING_BUFFERING  	buflen < lowBufferLength
     *  HLSPlayStates.PAUSED  				HLSPlayStates.PAUSED_BUFFERING  	buflen < lowBufferLength
     */
    public class HLSNetStream extends NetStream {
        /** Reference to the framework controller. **/
        private var _hls : HLS;
        /** reference to buffer threshold controller */
        private var _bufferThresholdController : BufferThresholdController;
        /** FLV Tag Buffer . **/
        private var _streamBuffer : StreamBuffer;
        /** Timer used to check buffer and position. **/
        private var _timer : Timer;
        /** Current playback state. **/
        private var _playbackState : String;
        /** Current seek state. **/
        private var _seekState : String;
        /** current playback level **/
        private var _playbackLevel : int;
        /** Netstream client proxy */
        private var _client : HLSNetStreamClient;

        /** Create the buffer. **/
        public function HLSNetStream(connection : NetConnection, hls : HLS, streamBuffer : StreamBuffer) : void {
            super(connection);
            super.bufferTime = 0.1;
            _hls = hls;
            _bufferThresholdController = new BufferThresholdController(hls);
            _streamBuffer = streamBuffer;
            _playbackState = HLSPlayStates.IDLE;
            _seekState = HLSSeekStates.IDLE;
            _timer = new Timer(100, 0);
            _timer.addEventListener(TimerEvent.TIMER, _checkBuffer);
            _client = new HLSNetStreamClient();
            _client.registerCallback("onHLSFragmentChange", onHLSFragmentChange);
            _client.registerCallback("onID3Data", onID3Data);
            super.client = _client;
        };

        public function onHLSFragmentChange(level : int, seqnum : int, cc : int, audio_only : Boolean, program_date : Number, width : int, height : int, ... tags) : void {
            CONFIG::LOGGING {
                Log.debug("playing fragment(level/sn/cc):" + level + "/" + seqnum + "/" + cc);
            }
            _playbackLevel = level;
            var tag_list : Array = new Array();
            for (var i : uint = 0; i < tags.length; i++) {
                tag_list.push(tags[i]);
                CONFIG::LOGGING {
                    Log.debug("custom tag:" + tags[i]);
                }
            }
            _hls.dispatchEvent(new HLSEvent(HLSEvent.FRAGMENT_PLAYING, new HLSPlayMetrics(level, seqnum, cc, audio_only, program_date, width, height, tag_list)));
        }

        // function is called by SCRIPT in FLV
        public function onID3Data(data : ByteArray) : void {
            // we dump the content as hex to get it to the Javascript in the browser.
            // from lots of searching, we could use base64, but even then, the decode would
            // not be native, so hex actually seems more efficient
            var dump : String = Hex.fromArray(data);
            CONFIG::LOGGING {
                Log.debug("id3:" + dump);
            }
            _hls.dispatchEvent(new HLSEvent(HLSEvent.ID3_UPDATED, dump));
        }

        /** timer function, check/update NetStream state, and append tags if needed **/
        private function _checkBuffer(e : Event) : void {
            var buffer : Number = this.bufferLength;
            // Log.info("netstream/total:" + super.bufferLength + "/" + this.bufferLength);
            // Set playback state. no need to check buffer status if seeking
            if (_seekState != HLSSeekStates.SEEKING) {
                // check low buffer condition
                if (buffer <= 0.1) {
                    if (_streamBuffer.reachedEnd) {
                        // Last tag done? Then append sequence end.
                        super.appendBytesAction(NetStreamAppendBytesAction.END_SEQUENCE);
                        super.appendBytes(new ByteArray());
                        // reach end of playlist + playback complete (as buffer is empty).
                        // stop timer, report event and switch to IDLE mode.
                        _timer.stop();
                        CONFIG::LOGGING {
                            Log.debug("reached end of VOD playlist, notify playback complete");
                        }
                        _hls.dispatchEvent(new HLSEvent(HLSEvent.PLAYBACK_COMPLETE));
                        _setPlaybackState(HLSPlayStates.IDLE);
                        _setSeekState(HLSSeekStates.IDLE);
                        return;
                    } else {
                        // buffer <= 0.1 and not EOS, pause playback
                        super.pause();
                    }
                }
                // if buffer len is below lowBufferLength, get into buffering state
                if (!_streamBuffer.reachedEnd && buffer < _bufferThresholdController.lowBufferLength) {
                    if (_playbackState == HLSPlayStates.PLAYING) {
                        // low buffer condition and play state. switch to play buffering state
                        _setPlaybackState(HLSPlayStates.PLAYING_BUFFERING);
                    } else if (_playbackState == HLSPlayStates.PAUSED) {
                        // low buffer condition and pause state. switch to paused buffering state
                        _setPlaybackState(HLSPlayStates.PAUSED_BUFFERING);
                    }
                }
                // if buffer len is above minBufferLength, get out of buffering state
                if (buffer >= _bufferThresholdController.minBufferLength || _streamBuffer.reachedEnd) {
                    if (_playbackState == HLSPlayStates.PLAYING_BUFFERING) {
                        CONFIG::LOGGING {
                            Log.debug("resume playback");
                        }
                        // resume playback in case it was paused, this can happen if buffer was in really low condition (less than 0.1s)
                        super.resume();
                        _setPlaybackState(HLSPlayStates.PLAYING);
                    } else if (_playbackState == HLSPlayStates.PAUSED_BUFFERING) {
                        _setPlaybackState(HLSPlayStates.PAUSED);
                    }
                }
            }
        };

        /** Return the current playback state. **/
        public function get playbackState() : String {
            return _playbackState;
        };

        /** Return the current seek state. **/
        public function get seekState() : String {
            return _seekState;
        };

        /** Return the current playback quality level **/
        public function get playbackLevel() : int {
            return _playbackLevel;
        };

        /** append tags to NetStream **/
        public function appendTags(tags : Vector.<FLVTag>) : void {
            if (_seekState == HLSSeekStates.SEEKING) {
                /* this is our first injection after seek(),
                let's flush netstream now
                this is to avoid black screen during seek command */
                super.close();
                CONFIG::FLASH_11_1 {
                    try {
                        super.useHardwareDecoder = HLSSettings.useHardwareVideoDecoder;
                    } catch(e : Error) {
                    }
                }
                super.play(null);
                super.appendBytesAction(NetStreamAppendBytesAction.RESET_SEEK);
                // immediatly pause NetStream, it will be resumed when enough data will be buffered in the NetStream
                super.pause();

//                for each (var tag : FLVTag in tags) {
//                    CONFIG::LOGGING {
//                        Log.debug2('inject type/dts/pts:' + tag.typeString + '/' + tag.dts + '/' + tag.pts);
//                    }
//                }
            }
            // append all tags
            for each (var tagBuffer : FLVTag in tags) {
                try {
                    if (tagBuffer.type == FLVTag.DISCONTINUITY) {
                        super.appendBytesAction(NetStreamAppendBytesAction.RESET_BEGIN);
                        super.appendBytes(FLVTag.getHeader());
                    }
                    super.appendBytes(tagBuffer.data);
                } catch (error : Error) {
                    var hlsError : HLSError = new HLSError(HLSError.TAG_APPENDING_ERROR, null, tagBuffer.type + ": " + error.message);
                    _hls.dispatchEvent(new HLSEvent(HLSEvent.ERROR, hlsError));
                }
            }
            if (_seekState == HLSSeekStates.SEEKING) {
                // dispatch event to mimic NetStream behaviour
                dispatchEvent(new NetStatusEvent(NetStatusEvent.NET_STATUS, false, false, {code:"NetStream.Seek.Notify", level:"status"}));
                _setSeekState(HLSSeekStates.SEEKED);
            }
        };

        /** Change playback state. **/
        private function _setPlaybackState(state : String) : void {
            if (state != _playbackState) {
                CONFIG::LOGGING {
                    Log.debug('[PLAYBACK_STATE] from ' + _playbackState + ' to ' + state);
                }
                _playbackState = state;
                _hls.dispatchEvent(new HLSEvent(HLSEvent.PLAYBACK_STATE, _playbackState));
            }
        };

        /** Change seeking state. **/
        private function _setSeekState(state : String) : void {
            if (state != _seekState) {
                CONFIG::LOGGING {
                    Log.debug('[SEEK_STATE] from ' + _seekState + ' to ' + state);
                }
                _seekState = state;
                _hls.dispatchEvent(new HLSEvent(HLSEvent.SEEK_STATE, _seekState));
            }
        };

        override public function play(...args) : void {
            var _playStart : Number;
            if (args.length >= 2) {
                _playStart = Number(args[1]);
            } else {
                _playStart = -1;
            }
            CONFIG::LOGGING {
                Log.info("HLSNetStream:play(" + _playStart + ")");
            }
            seek(_playStart);
            _setPlaybackState(HLSPlayStates.PLAYING_BUFFERING);
        }

        override public function play2(param : NetStreamPlayOptions) : void {
            CONFIG::LOGGING {
                Log.info("HLSNetStream:play2(" + param.start + ")");
            }
            seek(param.start);
            _setPlaybackState(HLSPlayStates.PLAYING_BUFFERING);
        }

        /** Pause playback. **/
        override public function pause() : void {
            CONFIG::LOGGING {
                Log.info("HLSNetStream:pause");
            }
            if (_playbackState == HLSPlayStates.PLAYING) {
                super.pause();
                _setPlaybackState(HLSPlayStates.PAUSED);
            } else if (_playbackState == HLSPlayStates.PLAYING_BUFFERING) {
                super.pause();
                _setPlaybackState(HLSPlayStates.PAUSED_BUFFERING);
            }
        };

        /** Resume playback. **/
        override public function resume() : void {
            CONFIG::LOGGING {
                Log.info("HLSNetStream:resume");
            }
            if (_playbackState == HLSPlayStates.PAUSED) {
                super.resume();
                _setPlaybackState(HLSPlayStates.PLAYING);
            } else if (_playbackState == HLSPlayStates.PAUSED_BUFFERING) {
                // dont resume NetStream here, it will be resumed by Timer. this avoids resuming playback while seeking is in progress
                _setPlaybackState(HLSPlayStates.PLAYING_BUFFERING);
            }
        };

        /** get Buffer Length  **/
        override public function get bufferLength() : Number {
            return netStreamBufferLength + _streamBuffer.bufferLength;
        };

        /** get Back Buffer Length  **/
        override public function get backBufferLength() : Number {
            return _streamBuffer.backBufferLength;
        };

        public function get netStreamBufferLength() : Number {
            if (_seekState == HLSSeekStates.SEEKING) {
                return 0;
            } else {
                return super.bufferLength;
            }
        };

        /** Start playing data in the buffer. **/
        override public function seek(position : Number) : void {
            CONFIG::LOGGING {
                Log.info("HLSNetStream:seek(" + position + ")");
            }
            _streamBuffer.seek(position);
            _setSeekState(HLSSeekStates.SEEKING);
            /* if HLS was in paused state before seeking,
             * switch to paused buffering state
             * otherwise, switch to playing buffering state
             */
            switch(_playbackState) {
                case HLSPlayStates.PAUSED:
                case HLSPlayStates.PAUSED_BUFFERING:
                    _setPlaybackState(HLSPlayStates.PAUSED_BUFFERING);
                    break;
                case HLSPlayStates.IDLE:
                case HLSPlayStates.PLAYING:
                case HLSPlayStates.PLAYING_BUFFERING:
                    _setPlaybackState(HLSPlayStates.PLAYING_BUFFERING);
                    break;
                default:
                    break;
            }
            /* always pause NetStream while seeking, even if we are in play state
             * in that case, NetStream will be resumed during next call to appendTags()
             */
            super.pause();
            _timer.start();
        };

        public override function set client(client : Object) : void {
            _client.delegate = client;
        };

        public override function get client() : Object {
            return _client.delegate;
        }

        /** Stop playback. **/
        override public function close() : void {
            CONFIG::LOGGING {
                Log.info("HLSNetStream:close");
            }
            super.close();
            _streamBuffer.stop();
            _timer.stop();
            _setPlaybackState(HLSPlayStates.IDLE);
            _setSeekState(HLSSeekStates.IDLE);
        };

        public function dispose_() : void {
            close();
            _bufferThresholdController.dispose();
        }
    }
}

remove useless assignement

remove useless assignement


/**
 * User: MerlinDS
 * Date: 12.07.2014
 * Time: 21:38
 */
package com.merlinds.miracle_tool.views.alerts {
	import com.merlinds.miracle_tool.view.interfaces.IResizable;
	import com.merlinds.miracle_tool.views.components.containers.DialogWindow;

	import flash.display.DisplayObject;

	import flash.display.DisplayObjectContainer;
	import flash.display.Shape;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.utils.setTimeout;

	public class AlertView extends Sprite implements IResizable{

		private var _dialogs:Sprite;
		private var _modalBlocker:Shape;
		//==============================================================================
		//{region							PUBLIC METHODS
		public function AlertView(parent:DisplayObjectContainer = null) {
			super();
			_modalBlocker = super.addChild(new Shape()) as Shape;
			_dialogs = super.addChild(new Sprite()) as Sprite;
			parent.addChild(this);
		}

		public function setSize(w:Number, h:Number):void {
			this.visible = false;
			_modalBlocker.graphics.clear();
			_modalBlocker.graphics.beginFill(0x000000, 0.3);
			_modalBlocker.graphics.drawRect(0, 0, w, h);
			_modalBlocker.graphics.endFill();
			_modalBlocker.visible = false;
			if(_dialogs.numChildren > 0){
				for(var i:int = 0; i < _dialogs.numChildren; i++){
					var child:DisplayObject = _dialogs.getChildAt(i);
					child.x = this.width - child.width >> 1;
					child.y = this.height - child.height >> 1;
				}
				_dialogs.visible =  true;
			}
		}

		override public function addChild(child:DisplayObject):DisplayObject {
			child.addEventListener(Event.ADDED_TO_STAGE, this.childAddedHandler);
			return _dialogs.addChild(child);
		}

		override public function removeChild(child:DisplayObject):DisplayObject {
			// when super.removeChild will be executed numChildren will be equals 0
			if(_dialogs.numChildren == 1){
				this.visible =  false;
			}
			return _dialogs.removeChild(child);
		}

		//} endregion PUBLIC METHODS ===================================================

		//==============================================================================
		//{region						PRIVATE\PROTECTED METHODS
		private function childAddedHandler(event:Event):void {
			var child:DisplayObject = event.target as DisplayObject;
			child.removeEventListener(Event.ADDED_TO_STAGE, this.childAddedHandler);
			//only on next frame//Hack for minimal comps
			setTimeout(function():void{
				child.x = width - child.width >> 1;
				child.y = height - child.height >> 1;
				visible = true;
				_modalBlocker.visible = (child as DialogWindow).modal;
			}, 0);
		}
		//} endregion PRIVATE\PROTECTED METHODS ========================================

		//==============================================================================
		//{region							EVENTS HANDLERS
		//} endregion EVENTS HANDLERS ==================================================

		//==============================================================================
		//{region							GETTERS/SETTERS
		//} endregion GETTERS/SETTERS ==================================================
	}
}

/**
 * User: MerlinDS
 * Date: 12.07.2014
 * Time: 21:38
 */
package com.merlinds.miracle_tool.views.alerts {
	import com.merlinds.miracle_tool.view.interfaces.IResizable;
	import com.merlinds.miracle_tool.views.components.containers.DialogWindow;

	import flash.display.DisplayObject;

	import flash.display.DisplayObjectContainer;
	import flash.display.Shape;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.utils.setTimeout;

	public class AlertView extends Sprite implements IResizable{

		private var _dialogs:Sprite;
		private var _modalBlocker:Shape;
		//==============================================================================
		//{region							PUBLIC METHODS
		public function AlertView(parent:DisplayObjectContainer = null) {
			super();
			_modalBlocker = super.addChild(new Shape()) as Shape;
			_dialogs = super.addChild(new Sprite()) as Sprite;
			parent.addChild(this);
		}

		public function setSize(w:Number, h:Number):void {
			this.visible = false;
			_modalBlocker.graphics.clear();
			_modalBlocker.graphics.beginFill(0x000000, 0.3);
			_modalBlocker.graphics.drawRect(0, 0, w, h);
			_modalBlocker.graphics.endFill();
			_modalBlocker.visible = false;
			if(_dialogs.numChildren > 0){
				for(var i:int = 0; i < _dialogs.numChildren; i++){
					var child:DisplayObject = _dialogs.getChildAt(i);
					child.x = this.width - child.width >> 1;
					child.y = this.height - child.height >> 1;
					_modalBlocker.visible = (child as DialogWindow).modal;
				}
				this.visible =  true;
			}
		}

		override public function addChild(child:DisplayObject):DisplayObject {
			child.addEventListener(Event.ADDED_TO_STAGE, this.childAddedHandler);
			return _dialogs.addChild(child);
		}

		override public function removeChild(child:DisplayObject):DisplayObject {
			// when super.removeChild will be executed numChildren will be equals 0
			if(_dialogs.numChildren == 1){
				this.visible =  false;
			}
			return _dialogs.removeChild(child);
		}

		//} endregion PUBLIC METHODS ===================================================

		//==============================================================================
		//{region						PRIVATE\PROTECTED METHODS
		private function childAddedHandler(event:Event):void {
			var child:DisplayObject = event.target as DisplayObject;
			child.removeEventListener(Event.ADDED_TO_STAGE, this.childAddedHandler);
			//only on next frame//Hack for minimal comps
			setTimeout(function():void{
				child.x = width - child.width >> 1;
				child.y = height - child.height >> 1;
				visible = true;
				_modalBlocker.visible = (child as DialogWindow).modal;
			}, 0);
		}
		//} endregion PRIVATE\PROTECTED METHODS ========================================

		//==============================================================================
		//{region							EVENTS HANDLERS
		//} endregion EVENTS HANDLERS ==================================================

		//==============================================================================
		//{region							GETTERS/SETTERS
		//} endregion GETTERS/SETTERS ==================================================
	}
}

Create dialog fix

Create dialog fix


package org.postgresql.febe {
    import flash.events.EventDispatcher;
    import org.postgresql.febe.message.AuthenticationRequest;
    import org.postgresql.febe.message.BackendKeyData;
    import org.postgresql.febe.message.Bind;
    import org.postgresql.febe.message.BindComplete;
    import org.postgresql.febe.message.CloseComplete;
    import org.postgresql.febe.message.CommandComplete;
    import org.postgresql.febe.message.DataRow;
    import org.postgresql.febe.message.EmptyQueryResponse;
    import org.postgresql.febe.message.ErrorResponse;
    import org.postgresql.febe.message.IBEMessage;
    import org.postgresql.febe.message.IFEMessage;
    import org.postgresql.febe.message.NoData;
    import org.postgresql.febe.message.NoticeResponse;
    import org.postgresql.febe.message.ParameterDescription;
    import org.postgresql.febe.message.ParameterStatus;
    import org.postgresql.febe.message.ParseComplete;
    import org.postgresql.febe.message.PortalSuspended;
    import org.postgresql.febe.message.ReadyForQuery;
    import org.postgresql.febe.message.RowDescription;
    import org.postgresql.io.ByteDataStream;
    import org.postgresql.io.DataStreamErrorEvent;
    import org.postgresql.io.DataStreamEvent;
    import org.postgresql.io.IDataStream;
    import org.postgresql.log.ILogger;
    import org.postgresql.log.Log;
    import org.postgresql.util.format;

    public class MessageStream extends EventDispatcher implements IMessageStream {

        private static const LOGGER:ILogger = Log.getLogger(MessageStream);

        // Commented-out messages are part of the protocol but unimplemented. COPY
        // will probably be implemented at some point; the function call (fastpath)
        // subprotocol probably will not be
        public static const backendMessageTypes:Object = {
            'R': AuthenticationRequest,
            'K': BackendKeyData,
            'B': Bind,
            'C': CommandComplete,
          /*'d': CopyData,
            'c': CopyDone,
            'G': CopyInResponse,
            'H': CopyOutResponse */
            '3': CloseComplete,
            'D': DataRow,
            'I': EmptyQueryResponse,
            'E': ErrorResponse,
          /*'V': FunctionCallResponse */
            'n': NoData,
            'N': NoticeResponse,
            't': ParameterDescription,
            'S': ParameterStatus,
            '1': ParseComplete,
            '2': BindComplete,
            's': PortalSuspended,
            'Z': ReadyForQuery,
            'T': RowDescription
        };

        private var _dataStream:IDataStream;
        private var _onDisconnected:Function;

        private var _nextMessageType:int;
        private var _nextMessageLen:int;

        public function MessageStream(stream:IDataStream) {
            _dataStream = stream;
            _dataStream.addEventListener(DataStreamEvent.PROGRESS, handleStreamData);
            _dataStream.addEventListener(DataStreamErrorEvent.ERROR, handleError);

            _nextMessageType = -1;
            _nextMessageLen = -1;
        }

        private function handleStreamData(e:DataStreamEvent):void {
            while (_dataStream.connected &&
                   (_nextMessageLen == -1 && _dataStream.bytesAvailable >= 5 /* len + type */) ||
                   (_nextMessageLen != -1 && _dataStream.bytesAvailable >= _nextMessageLen)) {
                if (_nextMessageLen == -1) {
                    _nextMessageType = _dataStream.readByte();
                    // FEBE encodes the message length as including the size
                    // of the length field itself. This does not work well for
                    // our purposes (it would make a number of things more confusing
                    // than necessary), so we subtract the size of the length field.
                    _nextMessageLen = _dataStream.readInt() - 4;
                } else {
                    // TODO: We should not have to copy the message to its own array: we
                    // should wrap the stream in something that sets an arbitrary hard limit
                    // to the number of bytes this particular message can read.
                    var messageBytes:ByteDataStream = new ByteDataStream();
                    _dataStream.readBytes(messageBytes, 0, _nextMessageLen);
                    var nextTypeCode:String = String.fromCharCode(_nextMessageType);
                    var nextMessageClass:Class = backendMessageTypes[nextTypeCode];
                    if (!nextMessageClass) {
                        var msg:String = format("No message class found for message type {0}", nextTypeCode);
                        dispatchEvent(new MessageStreamErrorEvent(MessageStreamErrorEvent.ERROR, msg));
                    } else {
                        try {
                            var nextMessage:IBEMessage = new nextMessageClass();
                            nextMessage.read(messageBytes);
                            LOGGER.debug('<= {0}', nextMessage);
                            dispatchEvent(new MessageEvent(MessageEvent.RECEIVED, nextMessage));
                        } catch (e:Error) {
                            dispatchEvent(new MessageStreamErrorEvent(MessageStreamErrorEvent.ERROR, e.message));
                        } finally {
                            // TODO: we should probably try sync in the catch or something: it's rather
                            // optimistic to assume that this finally clause will work for the failure case
                            _nextMessageType = -1;
                            _nextMessageLen = -1;
                        }
                    }
                }
            }
            dispatchEvent(new MessageStreamEvent(MessageStreamEvent.BATCH_COMPLETE));
        }

        private function handleError(e:DataStreamErrorEvent):void {
            dispatchEvent(new MessageStreamErrorEvent(MessageStreamErrorEvent.ERROR, e.text));
        }

        public function send(message:IFEMessage):void {
            LOGGER.debug('=> {0}', message);
            message.write(_dataStream);
            // TODO: we can eventually expose flush() in the IMessageBroker interface
            // to support flushing a batch of message instead of each individual message.
            // For now, we just keep this simple.
            _dataStream.flush();
            dispatchEvent(new MessageEvent(MessageEvent.SENT, message));
        }

        public function get connected():Boolean {
            return _dataStream.connected;
        }

        public function close():void {
            _dataStream.close();
        }

    }
}

package org.postgresql.febe {
    import flash.events.EventDispatcher;
    import org.postgresql.febe.message.AuthenticationRequest;
    import org.postgresql.febe.message.BackendKeyData;
    import org.postgresql.febe.message.Bind;
    import org.postgresql.febe.message.BindComplete;
    import org.postgresql.febe.message.CloseComplete;
    import org.postgresql.febe.message.CommandComplete;
    import org.postgresql.febe.message.DataRow;
    import org.postgresql.febe.message.EmptyQueryResponse;
    import org.postgresql.febe.message.ErrorResponse;
    import org.postgresql.febe.message.IBEMessage;
    import org.postgresql.febe.message.IFEMessage;
    import org.postgresql.febe.message.NoData;
    import org.postgresql.febe.message.NoticeResponse;
    import org.postgresql.febe.message.ParameterDescription;
    import org.postgresql.febe.message.ParameterStatus;
    import org.postgresql.febe.message.ParseComplete;
    import org.postgresql.febe.message.PortalSuspended;
    import org.postgresql.febe.message.ReadyForQuery;
    import org.postgresql.febe.message.RowDescription;
    import org.postgresql.io.ByteDataStream;
    import org.postgresql.io.DataStreamErrorEvent;
    import org.postgresql.io.DataStreamEvent;
    import org.postgresql.io.IDataStream;
    import org.postgresql.log.ILogger;
    import org.postgresql.log.Log;
    import org.postgresql.util.assert;
    import org.postgresql.util.format;

    public class MessageStream extends EventDispatcher implements IMessageStream {

        private static const LOGGER:ILogger = Log.getLogger(MessageStream);

        // Commented-out messages are part of the protocol but unimplemented. COPY
        // will probably be implemented at some point; the function call (fastpath)
        // subprotocol probably will not be
        public static const backendMessageTypes:Object = {
            'R': AuthenticationRequest,
            'K': BackendKeyData,
            'B': Bind,
            'C': CommandComplete,
          /*'d': CopyData,
            'c': CopyDone,
            'G': CopyInResponse,
            'H': CopyOutResponse */
            '3': CloseComplete,
            'D': DataRow,
            'I': EmptyQueryResponse,
            'E': ErrorResponse,
          /*'V': FunctionCallResponse */
            'n': NoData,
            'N': NoticeResponse,
            't': ParameterDescription,
            'S': ParameterStatus,
            '1': ParseComplete,
            '2': BindComplete,
            's': PortalSuspended,
            'Z': ReadyForQuery,
            'T': RowDescription
        };

        private var _dataStream:IDataStream;
        private var _onDisconnected:Function;

        private var _nextMessageType:int;
        private var _nextMessageLen:int;

        public function MessageStream(stream:IDataStream) {
            _dataStream = stream;
            _dataStream.addEventListener(DataStreamEvent.PROGRESS, handleStreamData);
            _dataStream.addEventListener(DataStreamErrorEvent.ERROR, handleError);

            _nextMessageType = -1;
            _nextMessageLen = -1;
        }

        private function handleStreamData(e:DataStreamEvent):void {
            while (_dataStream.connected &&
                   (_nextMessageLen == -1 && _dataStream.bytesAvailable >= 5 /* len + type */) ||
                   (_nextMessageLen != -1 && _dataStream.bytesAvailable >= _nextMessageLen)) {
                if (_nextMessageLen == -1) {
                    _nextMessageType = _dataStream.readByte();
                    // FEBE encodes the message length as including the size
                    // of the length field itself. This does not work well for
                    // our purposes (it would make a number of things more confusing
                    // than necessary), so we subtract the size of the length field.
                    _nextMessageLen = _dataStream.readInt() - 4;
                    LOGGER.debug("Waiting for {0} more bytes ({1} available)", _nextMessageLen, _dataStream.bytesAvailable);
                } else {
                    LOGGER.debug("Reading message of {0} bytes ({1} available)", _nextMessageLen, _dataStream.bytesAvailable);
                    // TODO: We should not have to copy the message to its own array: we
                    // should wrap the stream in something that sets an arbitrary hard limit
                    // to the number of bytes this particular message can read.
                    var messageBytes:ByteDataStream = new ByteDataStream();
                    if (_nextMessageLen > 0) {
                        // N.B.: If
                        _dataStream.readBytes(messageBytes, 0, _nextMessageLen);
                    }
                    assert("Unexpected amount of data was read off the stream", messageBytes.length == _nextMessageLen);
                    var nextTypeCode:String = String.fromCharCode(_nextMessageType);
                    var nextMessageClass:Class = backendMessageTypes[nextTypeCode];
                    if (!nextMessageClass) {
                        var msg:String = format("No message class found for message type {0}", nextTypeCode);
                        dispatchEvent(new MessageStreamErrorEvent(MessageStreamErrorEvent.ERROR, msg));
                    } else {
                        try {
                            var nextMessage:IBEMessage = new nextMessageClass();
                            nextMessage.read(messageBytes);
                            LOGGER.debug('<= {0}', nextMessage);
                            dispatchEvent(new MessageEvent(MessageEvent.RECEIVED, nextMessage));
                        } catch (e:Error) {
                            dispatchEvent(new MessageStreamErrorEvent(MessageStreamErrorEvent.ERROR, e.message));
                        } finally {
                            // TODO: we should probably try sync in the catch or something: it's rather
                            // optimistic to assume that this finally clause will work for the failure case
                            _nextMessageType = -1;
                            _nextMessageLen = -1;
                        }
                    }
                }
            }
            dispatchEvent(new MessageStreamEvent(MessageStreamEvent.BATCH_COMPLETE));
        }

        private function handleError(e:DataStreamErrorEvent):void {
            dispatchEvent(new MessageStreamErrorEvent(MessageStreamErrorEvent.ERROR, e.text));
        }

        public function send(message:IFEMessage):void {
            LOGGER.debug('=> {0}', message);
            message.write(_dataStream);
            // TODO: we can eventually expose flush() in the IMessageBroker interface
            // to support flushing a batch of message instead of each individual message.
            // For now, we just keep this simple.
            _dataStream.flush();
            dispatchEvent(new MessageEvent(MessageEvent.SENT, message));
        }

        public function get connected():Boolean {
            return _dataStream.connected;
        }

        public function close():void {
            _dataStream.close();
        }

    }
}

Fix reading of 0-payload-length backend messages; additional debugging.


package Controller.logic
{
	import Controller.ArgumentController;

	import Model.AGORAModel;
	import Model.ArgumentTypeModel;
	import Model.StatementModel;

	import ValueObjects.AGORAParameters;

	import components.ArgSelector;
	import components.ArgumentPanel;
	import components.MenuPanel;

	import classes.Language;

	import mx.controls.Alert;
	import mx.core.FlexGlobals;

	public class ModusTollens extends ParentArg
	{
		public var andOr:String;
		private var _isExp:Boolean;
		private static var instance:ModusTollens;

		public function ModusTollens()
		{
			langTypes = ["If-then","Implies","Whenever","Only if","Provided that","Sufficient condition","Necessary condition"];
			//dbLangTypeNames = ["ifthen","implies","whenever","onlyif","providedthat","sufficient","necessary"];
			expLangTypes = ["Only if"];	// Expandable with both And and Or
			label = AGORAParameters.getInstance().MOD_TOL;

		}

		public static function getInstance():ModusTollens{
			if(instance == null){
				instance = new ModusTollens;
			}
			return instance;
		}

		override public function getLabel():String{
			return label;
		}

		override public function formText(argumentTypeModel:ArgumentTypeModel):void{
			var output:String = "";
			var reasonText:String = "";
			var reasonModels:Vector.<StatementModel> = argumentTypeModel.reasonModels;
			var claimModel:StatementModel = argumentTypeModel.claimModel;
			var argSelector:ArgSelector = MenuPanel(FlexGlobals.topLevelApplication.map.agoraMap.menuPanelsHash[argumentTypeModel.ID]).schemeSelector;
			var i:int;

			switch(argumentTypeModel.language){
				case langTypes[0]:
					reasonText = reasonModels[0].statement.positiveText;
					output = Language.lookup("ArgIf") + claimModel.statement.positiveText +
						Language.lookup("ArgThen") + reasonText;
					break;
				case langTypes[1]:
					output = claimModel.statement.positiveText + Language.lookup("ArgImplies") + reasonModels[0].statement.positiveText;
					break;
				case langTypes[2]:
					reasonText = reasonModels[0].statement.positiveText;
					output = Language.lookup("ArgWhenever") + claimModel.statement.positiveText + ", " + reasonText;
					break;
				case langTypes[3]:
					//if many reasons
					var params:AGORAParameters = AGORAParameters.getInstance();
					if(argumentTypeModel.reasonModels.length > 1 && argumentTypeModel.lSubOption == null){
						output = "Select how you want to connect the reasons"; //TODO: Translate
						argSelector.andor.x = argSelector.typeSelector.x + argSelector.typeSelector.width;
						argSelector.andor.dataProvider = [params.AND, params.OR];
						argSelector.andor.visible = argSelector.typeSelector.visible;
						//if one reason
					}else if(argumentTypeModel.reasonModels.length == 1){
						reasonText = reasonModels[0].statement.positiveText;
						output = claimModel.statement.positiveText + Language.lookup("ArgOnlyIf");
						output = output + reasonText;
					}else{
						output = claimModel.statement.positiveText + Language.lookup("ArgOnlyIf");
						for(i=0; i<reasonModels.length - 1; i++){
							reasonText = reasonText + reasonModels[i].statement.positiveText + " " + argumentTypeModel.lSubOption + " ";
						}
						reasonText = reasonText + reasonModels[reasonModels.length - 1].statement.positiveText;
						output = output + reasonText;
						argSelector.andor.x = argSelector.typeSelector.x + argSelector.typeSelector.width;
						argSelector.andor.dataProvider = [params.AND, params.OR];
						argSelector.andor.visible = argSelector.typeSelector.visible;
					}
					break;
				case langTypes[4]:
					//provided that
					reasonText = reasonModels[0].statement.positiveText ;
					output = reasonText + Language.lookup("ArgProvidedThat") + claimModel.statement.positiveText;
					break;
				case langTypes[5]:
					//sufficient condition
					reasonText = reasonModels[0].statement.positiveText;
					output = claimModel.statement.positiveText + Language.lookup("ArgSufficientCond") + reasonText;
					break;
				case langTypes[6]:
					//necessary condition
					reasonText = reasonModels[0].statement.positiveText
					output = reasonText + Language.lookup("ArgNecessaryCond") + claimModel.statement.positiveText;
					break;
			}

			argumentTypeModel.inferenceModel.statements[0].text = claimModel.statement.text;
			argumentTypeModel.inferenceModel.statements[1].text = reasonText;
			argumentTypeModel.inferenceModel.statement.text = output;
		}

		override public function formTextWithSubOption(argumentTypeModel:ArgumentTypeModel):void{
			//must be only if:
			var output:String = "";
			var reasonModels:Vector.<StatementModel> = argumentTypeModel.reasonModels;
			var claimModel:StatementModel = argumentTypeModel.claimModel;
			var argSelector:ArgSelector = MenuPanel(FlexGlobals.topLevelApplication.map.agoraMap.menuPanelsHash[argumentTypeModel.ID]).schemeSelector;
			var i:int;

			if(argumentTypeModel.language == langTypes[4]){
				output = claimModel.statement.positiveText + Language.lookup("ArgOnlyIf") + reasonModels[0].statement.positiveText;
				for(i=1; i < reasonModels.length; i++){
					output = " " + argumentTypeModel.lSubOption + " " + reasonModels[i].statement.positiveText;
				}
			}
			else{
				trace("ModusTollens::formTextWithSubOption: Should not be any other language type other than only if");
			}

			argumentTypeModel.inferenceModel.statement.text = output;
		}

		override public function deleteLinks(argumentTypeModel:ArgumentTypeModel):void{
			var reasonModels:Vector.<StatementModel> = argumentTypeModel.reasonModels;
			var claimModel:StatementModel = argumentTypeModel.claimModel;
			//var inferenceModel:StatementModel = argumentTypeModel.inferenceModel;
			//if first claim's argument, then make it non-negative
			if(claimModel.firstClaim){
				claimModel.negated = false;
				//the first inference statement is the one to be removed
			}
			removeDependence(claimModel.statement, argumentTypeModel.inferenceModel.statements[0]);
			//make reason models non-negative
			for each(var reason:StatementModel in reasonModels){
				reason.negated = false;
				removeDependence(reason.statement, argumentTypeModel.inferenceModel.statements[1]);
			}
		}

		override public function link(argumentTypeModel:ArgumentTypeModel):void{
			var reasonModels:Vector.<StatementModel> = argumentTypeModel.reasonModels;
			var claimModel:StatementModel = argumentTypeModel.claimModel;
			var inferenceModel:StatementModel = argumentTypeModel.inferenceModel;

			if(claimModel.firstClaim){
				claimModel.negated = true;
			}

			inferenceModel.connectingString = StatementModel.IMPLICATION;

			//claimModel.statement.forwardList.push(inferenceModel.statements[0]);
			claimModel.statement.addDependentStatement(inferenceModel.statements[0]);

			for each(var reason:StatementModel in reasonModels){
				reason.negated = true;
				//reason.statement.forwardList.push(inferenceModel.statements[1]);
				reason.statement.addDependentStatement(inferenceModel.statements[1]);
			}
		}
	}
}

package Controller.logic
{
	import Controller.ArgumentController;

	import Model.AGORAModel;
	import Model.ArgumentTypeModel;
	import Model.StatementModel;

	import ValueObjects.AGORAParameters;

	import components.ArgSelector;
	import components.ArgumentPanel;
	import components.MenuPanel;

	import classes.Language;

	import mx.controls.Alert;
	import mx.core.FlexGlobals;

	public class ModusTollens extends ParentArg
	{
		public var andOr:String;
		private var _isExp:Boolean;
		private static var instance:ModusTollens;

		public function ModusTollens()
		{
			langTypes = ["If-then","Implies","Whenever","Only if","Provided that","Sufficient condition","Necessary condition"];
			//dbLangTypeNames = ["ifthen","implies","whenever","onlyif","providedthat","sufficient","necessary"];
			expLangTypes = ["Only if"];	// Expandable with both And and Or
			label = AGORAParameters.getInstance().MOD_TOL;

		}

		public static function getInstance():ModusTollens{
			if(instance == null){
				instance = new ModusTollens;
			}
			return instance;
		}

		override public function getLabel():String{
			return label;
		}

		override public function formText(argumentTypeModel:ArgumentTypeModel):void{
			var output:String = "";
			var reasonText:String = "";
			var reasonModels:Vector.<StatementModel> = argumentTypeModel.reasonModels;
			var claimModel:StatementModel = argumentTypeModel.claimModel;
			var argSelector:ArgSelector = MenuPanel(FlexGlobals.topLevelApplication.map.agoraMap.menuPanelsHash[argumentTypeModel.ID]).schemeSelector;
			var i:int;

			switch(argumentTypeModel.language){
				case langTypes[0]:
					reasonText = reasonModels[0].statement.positiveText;
					output = Language.lookup("ArgIf") + claimModel.statement.positiveText +
						Language.lookup("ArgThen") + reasonText;
					break;
				case langTypes[1]:
					output = claimModel.statement.positiveText + Language.lookup("ArgImplies") + reasonModels[0].statement.positiveText;
					break;
				case langTypes[2]:
					reasonText = reasonModels[0].statement.positiveText;
					output = Language.lookup("ArgWhenever") + claimModel.statement.positiveText + ", " + reasonText;
					break;
				case langTypes[3]:
					//if many reasons
					var params:AGORAParameters = AGORAParameters.getInstance();
					if(argumentTypeModel.reasonModels.length > 1 && argumentTypeModel.lSubOption == null){
						output = Language.lookup("SelectLanguageType");
						argSelector.andor.x = argSelector.typeSelector.x + argSelector.typeSelector.width;
						argSelector.andor.dataProvider = [params.AND, params.OR];
						argSelector.andor.visible = argSelector.typeSelector.visible;
						//if one reason
					}else if(argumentTypeModel.reasonModels.length == 1){
						reasonText = reasonModels[0].statement.positiveText;
						output = claimModel.statement.positiveText + Language.lookup("ArgOnlyIf");
						output = output + reasonText;
					}else{
						output = claimModel.statement.positiveText + Language.lookup("ArgOnlyIf");
						for(i=0; i<reasonModels.length - 1; i++){
							reasonText = reasonText + reasonModels[i].statement.positiveText + " " + argumentTypeModel.lSubOption + " ";
						}
						reasonText = reasonText + reasonModels[reasonModels.length - 1].statement.positiveText;
						output = output + reasonText;
						argSelector.andor.x = argSelector.typeSelector.x + argSelector.typeSelector.width;
						argSelector.andor.dataProvider = [params.AND, params.OR];
						argSelector.andor.visible = argSelector.typeSelector.visible;
					}
					break;
				case langTypes[4]:
					//provided that
					reasonText = reasonModels[0].statement.positiveText ;
					output = reasonText + Language.lookup("ArgProvidedThat") + claimModel.statement.positiveText;
					break;
				case langTypes[5]:
					//sufficient condition
					reasonText = reasonModels[0].statement.positiveText;
					output = claimModel.statement.positiveText + Language.lookup("ArgSufficientCond") + reasonText;
					break;
				case langTypes[6]:
					//necessary condition
					reasonText = reasonModels[0].statement.positiveText
					output = reasonText + Language.lookup("ArgNecessaryCond") + claimModel.statement.positiveText;
					break;
			}

			argumentTypeModel.inferenceModel.statements[0].text = claimModel.statement.text;
			argumentTypeModel.inferenceModel.statements[1].text = reasonText;
			argumentTypeModel.inferenceModel.statement.text = output;
		}

		override public function formTextWithSubOption(argumentTypeModel:ArgumentTypeModel):void{
			//must be only if:
			var output:String = "";
			var reasonModels:Vector.<StatementModel> = argumentTypeModel.reasonModels;
			var claimModel:StatementModel = argumentTypeModel.claimModel;
			var argSelector:ArgSelector = MenuPanel(FlexGlobals.topLevelApplication.map.agoraMap.menuPanelsHash[argumentTypeModel.ID]).schemeSelector;
			var i:int;

			if(argumentTypeModel.language == langTypes[4]){
				output = claimModel.statement.positiveText + Language.lookup("ArgOnlyIf") + reasonModels[0].statement.positiveText;
				for(i=1; i < reasonModels.length; i++){
					output = " " + argumentTypeModel.lSubOption + " " + reasonModels[i].statement.positiveText;
				}
			}
			else{
				trace("ModusTollens::formTextWithSubOption: Should not be any other language type other than only if");
			}

			argumentTypeModel.inferenceModel.statement.text = output;
		}

		override public function deleteLinks(argumentTypeModel:ArgumentTypeModel):void{
			var reasonModels:Vector.<StatementModel> = argumentTypeModel.reasonModels;
			var claimModel:StatementModel = argumentTypeModel.claimModel;
			//var inferenceModel:StatementModel = argumentTypeModel.inferenceModel;
			//if first claim's argument, then make it non-negative
			if(claimModel.firstClaim){
				claimModel.negated = false;
				//the first inference statement is the one to be removed
			}
			removeDependence(claimModel.statement, argumentTypeModel.inferenceModel.statements[0]);
			//make reason models non-negative
			for each(var reason:StatementModel in reasonModels){
				reason.negated = false;
				removeDependence(reason.statement, argumentTypeModel.inferenceModel.statements[1]);
			}
		}

		override public function link(argumentTypeModel:ArgumentTypeModel):void{
			var reasonModels:Vector.<StatementModel> = argumentTypeModel.reasonModels;
			var claimModel:StatementModel = argumentTypeModel.claimModel;
			var inferenceModel:StatementModel = argumentTypeModel.inferenceModel;

			if(claimModel.firstClaim){
				claimModel.negated = true;
			}

			inferenceModel.connectingString = StatementModel.IMPLICATION;

			//claimModel.statement.forwardList.push(inferenceModel.statements[0]);
			claimModel.statement.addDependentStatement(inferenceModel.statements[0]);

			for each(var reason:StatementModel in reasonModels){
				reason.negated = true;
				//reason.statement.forwardList.push(inferenceModel.statements[1]);
				reason.statement.addDependentStatement(inferenceModel.statements[1]);
			}
		}
	}
}

Add help text to MT

Add help text to MT


/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mangui.hls.controller {
    import org.mangui.hls.constant.HLSLoaderTypes;
    import org.mangui.hls.event.HLSEvent;
    import org.mangui.hls.event.HLSLoadMetrics;
    import org.mangui.hls.HLS;
    import org.mangui.hls.HLSSettings;

    CONFIG::LOGGING {
        import org.mangui.hls.utils.Log;
    }
    /** Class that manages buffer threshold values (minBufferLength/lowBufferLength)
     */
    public class BufferThresholdController {
        /** Reference to the HLS controller. **/
        private var _hls : HLS;
        // max nb of samples used for bw checking. the bigger it is, the more conservative it is.
        private static const MAX_SAMPLES : int = 30;
        private var _bw : Vector.<Number>;
        private var _nbSamples : uint;
        private var _targetduration : Number;
        private var _minBufferLength : Number;

        /** Create the loader. **/
        public function BufferThresholdController(hls : HLS) : void {
            _hls = hls;
            _hls.addEventListener(HLSEvent.MANIFEST_LOADED, _manifestLoadedHandler);
            _hls.addEventListener(HLSEvent.TAGS_LOADED, _fragmentLoadedHandler);
            _hls.addEventListener(HLSEvent.FRAGMENT_LOADED, _fragmentLoadedHandler);
        };

        public function dispose() : void {
            _hls.removeEventListener(HLSEvent.MANIFEST_LOADED, _manifestLoadedHandler);
            _hls.removeEventListener(HLSEvent.TAGS_LOADED, _fragmentLoadedHandler);
            _hls.removeEventListener(HLSEvent.FRAGMENT_LOADED, _fragmentLoadedHandler);
        }

        public function get minBufferLength() : Number {
            if (HLSSettings.minBufferLength == -1) {
                return _minBufferLength;
            } else {
                return HLSSettings.minBufferLength;
            }
        }

        public function get lowBufferLength() : Number {
            if (HLSSettings.minBufferLength == -1) {
                // in automode, low buffer threshold should be less than min auto buffer
                return Math.min(minBufferLength / 2, HLSSettings.lowBufferLength);
            } else {
                return HLSSettings.lowBufferLength;
            }
        }

        private function _manifestLoadedHandler(event : HLSEvent) : void {
            _nbSamples = 0;
            _targetduration = event.levels[_hls.startLevel].targetduration;
            _bw = new Vector.<Number>(MAX_SAMPLES);
            _minBufferLength = _targetduration;
        };

        private function _fragmentLoadedHandler(event : HLSEvent) : void {
            var metrics : HLSLoadMetrics = event.loadMetrics;
            // only monitor main fragment metrics for buffer threshold computing
            if(metrics.type == HLSLoaderTypes.FRAGMENT_MAIN) {
                var cur_bw : Number = metrics.bandwidth;
                _bw[_nbSamples % MAX_SAMPLES] = cur_bw;
                _nbSamples++;

                // compute min bw on MAX_SAMPLES
                var minBw : Number = Number.POSITIVE_INFINITY;
                var samples_max : int = Math.min(_nbSamples, MAX_SAMPLES);
                for (var i : int = 0; i < samples_max; i++) {
                    minBw = Math.min(minBw, _bw[i]);
                }

                // give more weight to current bandwidth
                var bw_ratio : Number = 2 * cur_bw / (minBw + cur_bw);

                /* predict time to dl next segment using a conservative approach.
                 *
                 * heuristic is as follow :
                 *
                 * time to dl next segment = time to dl current segment *  (playlist target duration / current segment duration) * bw_ratio
                 *                           \---------------------------------------------------------------------------------/
                 *                                  this part is a simple rule by 3, assuming we keep same dl bandwidth
                 *  bw ratio is the conservative factor, assuming that next segment will be downloaded with min bandwidth
                 */
                _minBufferLength = metrics.processing_duration * (_targetduration / metrics.duration) * bw_ratio;
                // avoid min > max
                if (HLSSettings.maxBufferLength) {
                    _minBufferLength = Math.min(HLSSettings.maxBufferLength, _minBufferLength);
                }
                CONFIG::LOGGING {
                    Log.debug2("AutoBufferController:minBufferLength:" + _minBufferLength);
                }
            };
        }
    }
}

/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mangui.hls.controller {
    import org.mangui.hls.constant.HLSLoaderTypes;
    import org.mangui.hls.event.HLSEvent;
    import org.mangui.hls.event.HLSLoadMetrics;
    import org.mangui.hls.HLS;
    import org.mangui.hls.HLSSettings;

    CONFIG::LOGGING {
        import org.mangui.hls.utils.Log;
    }
    /** Class that manages buffer threshold values (minBufferLength/lowBufferLength)
     */
    public class BufferThresholdController {
        /** Reference to the HLS controller. **/
        private var _hls : HLS;
        // max nb of samples used for bw checking. the bigger it is, the more conservative it is.
        private static const MAX_SAMPLES : int = 30;
        private var _bw : Vector.<Number>;
        private var _nbSamples : uint;
        private var _targetduration : Number;
        private var _minBufferLength : Number;

        /** Create the loader. **/
        public function BufferThresholdController(hls : HLS) : void {
            _hls = hls;
            _hls.addEventListener(HLSEvent.MANIFEST_LOADED, _manifestLoadedHandler);
            _hls.addEventListener(HLSEvent.TAGS_LOADED, _fragmentLoadedHandler);
            _hls.addEventListener(HLSEvent.FRAGMENT_LOADED, _fragmentLoadedHandler);
        };

        public function dispose() : void {
            _hls.removeEventListener(HLSEvent.MANIFEST_LOADED, _manifestLoadedHandler);
            _hls.removeEventListener(HLSEvent.TAGS_LOADED, _fragmentLoadedHandler);
            _hls.removeEventListener(HLSEvent.FRAGMENT_LOADED, _fragmentLoadedHandler);
        }

        public function get minBufferLength() : Number {
            if (HLSSettings.minBufferLength == -1) {
                return _minBufferLength;
            } else {
                return HLSSettings.minBufferLength;
            }
        }

        public function get lowBufferLength() : Number {
            if (HLSSettings.minBufferLength == -1) {
                // in automode, low buffer threshold should be less than min auto buffer
                return Math.min(minBufferLength / 2, HLSSettings.lowBufferLength);
            } else {
                return HLSSettings.lowBufferLength;
            }
        }

        private function _manifestLoadedHandler(event : HLSEvent) : void {
            _nbSamples = 0;
            _targetduration = event.levels[_hls.startLevel].targetduration;
            _bw = new Vector.<Number>(MAX_SAMPLES,true);
            _minBufferLength = _targetduration;
        };

        private function _fragmentLoadedHandler(event : HLSEvent) : void {
            var metrics : HLSLoadMetrics = event.loadMetrics;
            // only monitor main fragment metrics for buffer threshold computing
            if(metrics.type == HLSLoaderTypes.FRAGMENT_MAIN) {
                var cur_bw : Number = metrics.bandwidth;
                _bw[_nbSamples % MAX_SAMPLES] = cur_bw;
                _nbSamples++;

                // compute min bw on MAX_SAMPLES
                var minBw : Number = Number.POSITIVE_INFINITY;
                var samples_max : int = Math.min(_nbSamples, MAX_SAMPLES);
                for (var i : int = 0; i < samples_max; i++) {
                    minBw = Math.min(minBw, _bw[i]);
                }

                // give more weight to current bandwidth
                var bw_ratio : Number = 2 * cur_bw / (minBw + cur_bw);

                /* predict time to dl next segment using a conservative approach.
                 *
                 * heuristic is as follow :
                 *
                 * time to dl next segment = time to dl current segment *  (playlist target duration / current segment duration) * bw_ratio
                 *                           \---------------------------------------------------------------------------------/
                 *                                  this part is a simple rule by 3, assuming we keep same dl bandwidth
                 *  bw ratio is the conservative factor, assuming that next segment will be downloaded with min bandwidth
                 */
                _minBufferLength = metrics.processing_duration * (_targetduration / metrics.duration) * bw_ratio;
                // avoid min > max
                if (HLSSettings.maxBufferLength) {
                    _minBufferLength = Math.min(HLSSettings.maxBufferLength, _minBufferLength);
                }
                CONFIG::LOGGING {
                    Log.debug2("AutoBufferController:minBufferLength:" + _minBufferLength);
                }
            };
        }
    }
}

optimize fixed length vector instantiation


//
// $Id$
//
// Thane - an enhancement of Mozilla/Adobe's Tamarin project with partial Flash Player compatibility
// Copyright (C) 2008-2009 Three Rings Design, Inc.
//
// Redistribution and use in source and binary forms, with or without modification, are permitted
// provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
//    conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright notice, this list of
//    conditions and the following disclaimer in the documentation and/or other materials provided
//    with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
// PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

package flash.utils {

import avmplus.Domain;

public function describeType (c :Object) :XML
{
    throw new Error("describeType() Not implemented");
}

public function getDefinitionByName (name :String) :Class
{
    return Domain.currentDomain.getClass(name.replace("::", "."));
}

public function getQualifiedClassName (c :*) :String
{
    return Domain.currentDomain.getClassName(c);
}

public function getQualifiedSuperclassName (c :*) :String
{
    throw new Error("getQualifiedSuperclassName() not implemented");
}

}

//
// $Id$
//
// Thane - an enhancement of Mozilla/Adobe's Tamarin project with partial Flash Player compatibility
// Copyright (C) 2008-2009 Three Rings Design, Inc.
//
// Redistribution and use in source and binary forms, with or without modification, are permitted
// provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
//    conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright notice, this list of
//    conditions and the following disclaimer in the documentation and/or other materials provided
//    with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
// PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

package flash.utils {

import avmplus.describeType;
import avmplus.FLASH10_FLAGS;
import avmplus.Domain;

public function describeType (c :Object) :XML
{
    return avmplus.describeType(c, FLASH10_FLAGS);
}

public function describeTypeWithFlags (value :*, flags :uint) :XML
{
    return avmplus.describeType(value, flags);
}

public function getDefinitionByName (name :String) :Class
{
    return avmplus.Domain.currentDomain.getClass(name.replace("::", "."));
}

public function getQualifiedClassName (c :*) :String
{
    // TODO: This function now exists in avmplus.*, see core/DescribeType.as
    return avmplus.Domain.currentDomain.getClassName(c);
}

public function getQualifiedSuperclassName (c :*) :String
{
    // TODO: This function now exists in avmplus.*, see core/DescribeType.as
    throw new Error("getQualifiedSuperclassName() not implemented");
}

}

Use the new fancy describeType() implementation in Tamarin. It's hopefully functionally identical to the one in the client. This probably obsoletes the Thane/Client environment fiddling we do in Narya.


/*
 * Copyright 2014 Mozilla Foundation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package flash.net {
public final class NetStreamMulticastInfo {
  public function NetStreamMulticastInfo(sendDataBytesPerSecond:Number, sendControlBytesPerSecond:Number, receiveDataBytesPerSecond:Number, receiveControlBytesPerSecond:Number, bytesPushedToPeers:Number, fragmentsPushedToPeers:Number, bytesRequestedByPeers:Number, fragmentsRequestedByPeers:Number, bytesPushedFromPeers:Number, fragmentsPushedFromPeers:Number, bytesRequestedFromPeers:Number, fragmentsRequestedFromPeers:Number, sendControlBytesPerSecondToServer:Number, receiveDataBytesPerSecondFromServer:Number, bytesReceivedFromServer:Number, fragmentsReceivedFromServer:Number, receiveDataBytesPerSecondFromIPMulticast:Number, bytesReceivedFromIPMulticast:Number, fragmentsReceivedFromIPMulticast:Number) {
    this._sendDataBytesPerSecond = sendDataBytesPerSecond;
    this._sendControlBytesPerSecond = sendControlBytesPerSecond;
    this._receiveDataBytesPerSecond = receiveDataBytesPerSecond;
    this._receiveControlBytesPerSecond = receiveControlBytesPerSecond;
    this._bytesPushedToPeers = bytesPushedToPeers;
    this._fragmentsPushedToPeers = fragmentsPushedToPeers;
    this._bytesRequestedByPeers = bytesRequestedByPeers;
    this._fragmentsRequestedByPeers = fragmentsRequestedByPeers;
    this._bytesPushedFromPeers = bytesPushedFromPeers;
    this._fragmentsPushedFromPeers = fragmentsPushedFromPeers;
    this._bytesRequestedFromPeers = bytesRequestedFromPeers;
    this._fragmentsRequestedFromPeers = fragmentsRequestedFromPeers;
    this._sendControlBytesPerSecondToServer = sendControlBytesPerSecondToServer;
    this._receiveDataBytesPerSecondFromServer = receiveDataBytesPerSecondFromServer;
    this._bytesReceivedFromServer = bytesReceivedFromServer;
    this._fragmentsReceivedFromServer = fragmentsReceivedFromServer;
    this._receiveDataBytesPerSecondFromIPMulticast = receiveDataBytesPerSecondFromIPMulticast;
    this._bytesReceivedFromIPMulticast = bytesReceivedFromIPMulticast;
    this._fragmentsReceivedFromIPMulticast = fragmentsReceivedFromIPMulticast;
  }
  public function get sendDataBytesPerSecond():Number {
    return _sendDataBytesPerSecond;
  }
  public function get sendControlBytesPerSecond():Number {
    return _sendControlBytesPerSecond;
  }
  public function get receiveDataBytesPerSecond():Number {
    return _receiveDataBytesPerSecond;
  }
  public function get receiveControlBytesPerSecond():Number {
    return _receiveControlBytesPerSecond;
  }
  public function get bytesPushedToPeers():Number {
    return _bytesPushedToPeers;
  }
  public function get fragmentsPushedToPeers():Number {
    return _fragmentsPushedToPeers;
  }
  public function get bytesRequestedByPeers():Number {
    return _bytesRequestedByPeers;
  }
  public function get fragmentsRequestedByPeers():Number {
    return _fragmentsRequestedByPeers;
  }
  public function get bytesPushedFromPeers():Number {
    return _bytesPushedFromPeers;
  }
  public function get fragmentsPushedFromPeers():Number {
    return _fragmentsPushedFromPeers;
  }
  public function get bytesRequestedFromPeers():Number {
    return _bytesRequestedFromPeers;
  }
  public function get fragmentsRequestedFromPeers():Number {
    return _fragmentsRequestedFromPeers;
  }
  public function get sendControlBytesPerSecondToServer():Number {
    return _sendControlBytesPerSecondToServer;
  }
  public function get receiveDataBytesPerSecondFromServer():Number {
    return _receiveDataBytesPerSecondFromServer;
  }
  public function get bytesReceivedFromServer():Number {
    return _bytesReceivedFromServer;
  }
  public function get fragmentsReceivedFromServer():Number {
    return _fragmentsReceivedFromServer;
  }
  public function get receiveDataBytesPerSecondFromIPMulticast():Number {
    return _receiveDataBytesPerSecondFromIPMulticast;
  }
  public function get bytesReceivedFromIPMulticast():Number {
    return _bytesReceivedFromIPMulticast;
  }
  public function get fragmentsReceivedFromIPMulticast():Number {
    return _fragmentsReceivedFromIPMulticast;
  }
  public function toString():String {
    notImplemented("toString");
    return "";
  }

  private var _sendDataBytesPerSecond:Number;
  private var _sendControlBytesPerSecond:Number;
  private var _receiveDataBytesPerSecond:Number;
  private var _receiveControlBytesPerSecond:Number;
  private var _bytesPushedToPeers:Number;
  private var _fragmentsPushedToPeers:Number;
  private var _bytesRequestedByPeers:Number;
  private var _fragmentsRequestedByPeers:Number;
  private var _bytesPushedFromPeers:Number;
  private var _fragmentsPushedFromPeers:Number;
  private var _bytesRequestedFromPeers:Number;
  private var _fragmentsRequestedFromPeers:Number;
  private var _sendControlBytesPerSecondToServer:Number;
  private var _receiveDataBytesPerSecondFromServer:Number;
  private var _bytesReceivedFromServer:Number;
  private var _fragmentsReceivedFromServer:Number;
  private var _receiveDataBytesPerSecondFromIPMulticast:Number;
  private var _bytesReceivedFromIPMulticast:Number;
  private var _fragmentsReceivedFromIPMulticast:Number;
}
}

/*
 * Copyright 2014 Mozilla Foundation
 *
 * Licensed under the Apache License, Version 2.0 (the 'License');
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an 'AS IS' BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package flash.net {
public final class NetStreamMulticastInfo {
  public function NetStreamMulticastInfo(sendDataBytesPerSecond: Number,
                                         sendControlBytesPerSecond: Number,
                                         receiveDataBytesPerSecond: Number,
                                         receiveControlBytesPerSecond: Number,
                                         bytesPushedToPeers: Number, fragmentsPushedToPeers: Number,
                                         bytesRequestedByPeers: Number,
                                         fragmentsRequestedByPeers: Number,
                                         bytesPushedFromPeers: Number,
                                         fragmentsPushedFromPeers: Number,
                                         bytesRequestedFromPeers: Number,
                                         fragmentsRequestedFromPeers: Number,
                                         sendControlBytesPerSecondToServer: Number,
                                         receiveDataBytesPerSecondFromServer: Number,
                                         bytesReceivedFromServer: Number,
                                         fragmentsReceivedFromServer: Number,
                                         receiveDataBytesPerSecondFromIPMulticast: Number,
                                         bytesReceivedFromIPMulticast: Number,
                                         fragmentsReceivedFromIPMulticast: Number)
  {
    this._sendDataBytesPerSecond = sendDataBytesPerSecond;
    this._sendControlBytesPerSecond = sendControlBytesPerSecond;
    this._receiveDataBytesPerSecond = receiveDataBytesPerSecond;
    this._receiveControlBytesPerSecond = receiveControlBytesPerSecond;
    this._bytesPushedToPeers = bytesPushedToPeers;
    this._fragmentsPushedToPeers = fragmentsPushedToPeers;
    this._bytesRequestedByPeers = bytesRequestedByPeers;
    this._fragmentsRequestedByPeers = fragmentsRequestedByPeers;
    this._bytesPushedFromPeers = bytesPushedFromPeers;
    this._fragmentsPushedFromPeers = fragmentsPushedFromPeers;
    this._bytesRequestedFromPeers = bytesRequestedFromPeers;
    this._fragmentsRequestedFromPeers = fragmentsRequestedFromPeers;
    this._sendControlBytesPerSecondToServer = sendControlBytesPerSecondToServer;
    this._receiveDataBytesPerSecondFromServer = receiveDataBytesPerSecondFromServer;
    this._bytesReceivedFromServer = bytesReceivedFromServer;
    this._fragmentsReceivedFromServer = fragmentsReceivedFromServer;
    this._receiveDataBytesPerSecondFromIPMulticast = receiveDataBytesPerSecondFromIPMulticast;
    this._bytesReceivedFromIPMulticast = bytesReceivedFromIPMulticast;
    this._fragmentsReceivedFromIPMulticast = fragmentsReceivedFromIPMulticast;
  }
  private var _sendDataBytesPerSecond: Number;
  private var _sendControlBytesPerSecond: Number;
  private var _receiveDataBytesPerSecond: Number;
  private var _receiveControlBytesPerSecond: Number;
  private var _bytesPushedToPeers: Number;
  private var _fragmentsPushedToPeers: Number;
  private var _bytesRequestedByPeers: Number;
  private var _fragmentsRequestedByPeers: Number;
  private var _bytesPushedFromPeers: Number;
  private var _fragmentsPushedFromPeers: Number;
  private var _bytesRequestedFromPeers: Number;
  private var _fragmentsRequestedFromPeers: Number;
  private var _sendControlBytesPerSecondToServer: Number;
  private var _receiveDataBytesPerSecondFromServer: Number;
  private var _bytesReceivedFromServer: Number;
  private var _fragmentsReceivedFromServer: Number;
  private var _receiveDataBytesPerSecondFromIPMulticast: Number;
  private var _bytesReceivedFromIPMulticast: Number;
  private var _fragmentsReceivedFromIPMulticast: Number;
  public function get sendDataBytesPerSecond(): Number {
    return _sendDataBytesPerSecond;
  }
  public function get sendControlBytesPerSecond(): Number {
    return _sendControlBytesPerSecond;
  }
  public function get receiveDataBytesPerSecond(): Number {
    return _receiveDataBytesPerSecond;
  }
  public function get receiveControlBytesPerSecond(): Number {
    return _receiveControlBytesPerSecond;
  }
  public function get bytesPushedToPeers(): Number {
    return _bytesPushedToPeers;
  }
  public function get fragmentsPushedToPeers(): Number {
    return _fragmentsPushedToPeers;
  }
  public function get bytesRequestedByPeers(): Number {
    return _bytesRequestedByPeers;
  }
  public function get fragmentsRequestedByPeers(): Number {
    return _fragmentsRequestedByPeers;
  }
  public function get bytesPushedFromPeers(): Number {
    return _bytesPushedFromPeers;
  }
  public function get fragmentsPushedFromPeers(): Number {
    return _fragmentsPushedFromPeers;
  }
  public function get bytesRequestedFromPeers(): Number {
    return _bytesRequestedFromPeers;
  }
  public function get fragmentsRequestedFromPeers(): Number {
    return _fragmentsRequestedFromPeers;
  }
  public function get sendControlBytesPerSecondToServer(): Number {
    return _sendControlBytesPerSecondToServer;
  }
  public function get receiveDataBytesPerSecondFromServer(): Number {
    return _receiveDataBytesPerSecondFromServer;
  }
  public function get bytesReceivedFromServer(): Number {
    return _bytesReceivedFromServer;
  }
  public function get fragmentsReceivedFromServer(): Number {
    return _fragmentsReceivedFromServer;
  }
  public function get receiveDataBytesPerSecondFromIPMulticast(): Number {
    return _receiveDataBytesPerSecondFromIPMulticast;
  }
  public function get bytesReceivedFromIPMulticast(): Number {
    return _bytesReceivedFromIPMulticast;
  }
  public function get fragmentsReceivedFromIPMulticast(): Number {
    return _fragmentsReceivedFromIPMulticast;
  }
  public function toString(): String {
    return 'sendDataBytesPerSecond=' + _sendDataBytesPerSecond +
           ' sendControlBytesPerSecond=' + _sendControlBytesPerSecond +
           ' receiveDataBytesPerSecond=' + _receiveDataBytesPerSecond +
           ' receiveControlBytesPerSecond=' + _receiveControlBytesPerSecond +
           ' bytesPushedToPeers=' + _bytesPushedToPeers +
           ' fragmentsPushedToPeers=' + _fragmentsPushedToPeers +
           ' bytesRequestedByPeers=' + _bytesRequestedByPeers +
           ' fragmentsRequestedByPeers=' + _fragmentsRequestedByPeers +
           ' bytesPushedFromPeers=' + _bytesPushedFromPeers +
           ' fragmentsPushedFromPeers=' + _fragmentsPushedFromPeers +
           ' bytesRequestedFromPeers=' + _bytesRequestedFromPeers +
           ' fragmentsRequestedFromPeers=' + _fragmentsRequestedFromPeers +
           ' sendControlBytesPerSecondToServer=' + _sendControlBytesPerSecondToServer +
           ' receiveDataBytesPerSecondFromServer=' + _receiveDataBytesPerSecondFromServer +
           ' bytesReceivedFromServer=' + _bytesReceivedFromServer +
           ' fragmentsReceivedFromServer=' + _fragmentsReceivedFromServer +
           ' receiveDataBytesPerSecondFromIPMulticast=' + _receiveDataBytesPerSecondFromIPMulticast +
           ' bytesReceivedFromIPMulticast=' + _bytesReceivedFromIPMulticast +
           ' fragmentsReceivedFromIPMulticast=' + _fragmentsReceivedFromIPMulticast;
  }
}
}

Implement NetStreamMulticastInfo#toString

And reformat the file