'use strict';

var browserDetails = require('webrtc-adapter').default.browserDetails;
var uuid_v1 = require('uuid/v1');
var util = require('./util');
var connections = {};
var LOCAL_CACHED_VIDEO = "-LOCAL_CACHED_VIDEO";
var REMOTE_CACHED_VIDEO = "-REMOTE_CACHED_VIDEO";
var extensionId;
var defaultConstraints;
var logger;
var LOG_PREFIX = "webrtc";
var audioContext;
var createMicGainNode;
var microphoneGain;
var constants = require('./constants');
var validBrowsers = ["firefox", "chrome", "safari"];

var createConnection = function (options) {
    return new Promise(function (resolve, reject) {

        var id = options.id;
        var connectionConfig = options.connectionConfig || {"iceServers": []};
        var connectionConstraints = options.connectionConstraints || {};
        if (!connectionConstraints.hasOwnProperty("optional")) {
            connectionConstraints.optional = [{"DtlsSrtpKeyAgreement": true}];
        }
        connectionConfig.bundlePolicy = "max-compat";
        var connection = new RTCPeerConnection(connectionConfig, connectionConstraints);
        //unidirectional display
        var display = options.display;
        //bidirectional local
        var localDisplay = options.localDisplay;
        //bidirectional remote
        var remoteDisplay = options.remoteDisplay;
        var bidirectional = options.bidirectional;
        var localVideo;
        //tweak for custom video players #WCS-1511
        var remoteVideo = options.remoteVideo;
        var videoCams = [];
        var switchCamCount = 0;
        var mics = [];
        var switchMicCount = 0;
        var customStream = options.customStream;
        var currentAudioTrack;
        var currentVideoTrack;
        var systemSoundTrack;
        var constraints = options.constraints ? options.constraints : {};
        var screenShare = false;
        var playoutDelay = options.playoutDelay;

        if (bidirectional) {
            localVideo = getCacheInstance(localDisplay);
            if (localVideo) {
                //made for safari, if sip call without audio and video, because function playFirstVideo() creates a video element
                if (localVideo.srcObject) {
                    localVideo.id = id + "-local";
                    connection.addStream(localVideo.srcObject);
                } else {
                    localVideo = null;
                }
            }
            remoteVideo = getCacheInstance(remoteDisplay);
            if (!remoteVideo) {
                remoteVideo = document.createElement('video');
                remoteDisplay.appendChild(remoteVideo);
            }
            remoteVideo.id = id + "-remote";

            if (options.audioOutputId && typeof remoteVideo.setSinkId !== "undefined") {
                remoteVideo.setSinkId(options.audioOutputId);
            }
            /**
             * Workaround for Android 6, 7, Chrome 61.
             * https://bugs.chromium.org/p/chromium/issues/detail?id=769622
             */
            remoteVideo.style = "border-radius: 1px";
        } else {
            //tweak for custom video players. In order to put MediaStream in srcObject #WCS-1511
            if (!remoteVideo) {
                var cachedVideo = getCacheInstance(display);
                if (!cachedVideo || cachedVideo.id.indexOf(REMOTE_CACHED_VIDEO) !== -1 || !cachedVideo.srcObject) {
                    if (cachedVideo) {
                        remoteVideo = cachedVideo;
                    } else {
                        remoteVideo = document.createElement('video');
                        display.appendChild(remoteVideo);
                    }
                    remoteVideo.id = id;
                    if (options.audioOutputId && typeof remoteVideo.setSinkId !== "undefined") {
                        remoteVideo.setSinkId(options.audioOutputId);
                    }
                    /**
                     * Workaround for Android 6, 7, Chrome 61.
                     * https://bugs.chromium.org/p/chromium/issues/detail?id=769622
                     */
                    remoteVideo.style = "border-radius: 1px";
                } else {
                    localVideo = cachedVideo;
                    localVideo.id = id;
                    connection.addStream(localVideo.srcObject);
                }
            }
        }
        if (localVideo) {
            var videoTrack = localVideo.srcObject.getVideoTracks()[0];
            if (videoTrack) {
                listDevices(false).then(function (devices) {
                    devices.video.forEach(function (device) {
                        if (videoTrack.label === device.label) {
                            switchCamCount = videoCams.length;
                        }
                        videoCams.push(device.id);
                    })
                });
            }
            var audioTrack = localVideo.srcObject.getAudioTracks()[0];
            if (audioTrack) {
                listDevices(false).then(function (devices) {
                    devices.audio.forEach(function (device) {
                        if (audioTrack.label === device.label) {
                            switchMicCount = mics.length;
                        }
                        mics.push(device.id);
                    })
                });
            }
        }
        connection.ontrack = function (event) {
            if (remoteVideo) {
                remoteVideo.srcObject = event.streams[0];
                remoteVideo.onloadedmetadata = function (e) {
                    if (remoteVideo) {
                        remoteVideo.play().catch(function (e) {
                            if (validBrowsers.includes(browserDetails.browser)) {
                                //WCS-1698. fixed autoplay in chromium based browsers
                                //WCS-2375. fixed autoplay in ios safari
                                logger.info(LOG_PREFIX, "Autoplay detected! Trying to play a video with a muted sound...");
                                remoteVideo.muted = true;
                                remoteVideo.play();
                            } else {
                                logger.error(LOG_PREFIX, e);
                            }
                        });
                    }
                };
            }

            //WCS-2904 check playoutDelay to prevent TypeError in some browsers
            if (playoutDelay !== undefined) {
                //WCS-2771 add playback delay
                connection.getReceivers().forEach((track) => {
                    if (track.playoutDelayHint === undefined) {
                        logger.warn("playout delay unsupported");
                    }
                    track.playoutDelayHint = playoutDelay;
                });
            }
        };
        connection.onremovestream = function (event) {
            if (remoteVideo) {
                remoteVideo.pause();
            }
        };
        connection.onsignalingstatechange = function (event) {
        };
        connection.oniceconnectionstatechange = function (event) {
        };
        connection.onicecandidate = function (event) {
            if (event.candidate != null) {
                logger.debug(LOG_PREFIX, "Added icecandidate: " + event.candidate.candidate);
            }
        };
        var state = function () {
            return connection.signalingState;
        };
        var close = function (cacheCamera) {
            if (remoteVideo) {
                removeVideoElement(remoteVideo);
                //tweak for custom video players #WCS-1511
                if (!options.remoteVideo) {
                    remoteVideo.id = remoteVideo.id + REMOTE_CACHED_VIDEO;
                }
                remoteVideo = null;
            }
            if (localVideo && !getCacheInstance((localDisplay || display)) && cacheCamera) {
                localVideo.id = localVideo.id + LOCAL_CACHED_VIDEO;
                unmuteAudio();
                unmuteVideo();
                localVideo = null;
            } else if (localVideo) {
                localVideo.id = localVideo.id + LOCAL_CACHED_VIDEO;
                removeVideoElement(localVideo);
                localVideo = null;
            }
            if (connection.signalingState !== "closed") {
                connection.close();
            }
            delete connections[id];
        };
        var createOffer = function (options) {
            return new Promise(function (resolve, reject) {
                var hasAudio = true;
                var hasVideo = true;
                if (localVideo) {
                    if (!localVideo.srcObject.getAudioTracks()[0]) {
                        hasAudio = false;
                    }
                    if (!localVideo.srcObject.getVideoTracks()[0]) {
                        hasVideo = false;
                        options.receiveVideo = false;
                    }
                } else if (browserDetails.browser == "safari" && !connection.getTransceivers().length) {
                    if (options.receiveAudio) {
                        connection.addTransceiver('audio', {direction: "recvonly"});
                    }
                    if (options.receiveVideo) {
                        connection.addTransceiver('video', {direction: "recvonly"});
                    }
                }
                var constraints = {
                    offerToReceiveAudio: options.receiveAudio ? 1 : 0,
                    offerToReceiveVideo: options.receiveVideo ? 1 : 0
                };

                //create offer and set local sdp
                connection.createOffer(constraints).then(function (offer) {
                    connection.setLocalDescription(offer).then(function () {
                        var o = {};
                        o.sdp = util.stripCodecs(offer.sdp, options.stripCodecs);
                        o.hasAudio = hasAudio;
                        o.hasVideo = hasVideo;
                        resolve(o);
                    });
                });
            });
        };
        var createAnswer = function (options) {
            return new Promise(function (resolve, reject) {
                //create offer and set local sdp
                connection.createAnswer().then(function (answer) {
                    connection.setLocalDescription(answer).then(function () {
                        resolve(util.stripCodecs(answer.sdp, options.stripCodecs));
                    });
                });
            });
        };
        var changeAudioCodec = function (codec) {
            return false;
        };
        var setRemoteSdp = function (sdp) {
            logger.debug(LOG_PREFIX, "setRemoteSDP:");
            logger.debug(LOG_PREFIX, sdp);
            return new Promise(function (resolve, reject) {
                var sdpType;
                if (connection.signalingState == 'have-local-offer') {
                    sdpType = 'answer';
                } else {
                    sdpType = 'offer';
                }
                var rtcSdp = new RTCSessionDescription({
                    type: sdpType,
                    sdp: sdp
                });
                connection.setRemoteDescription(rtcSdp).then(function () {
                    //use in edge for ice
                    if (browserDetails.browser == "edge") {
                        // var sdpArray = sdp.split("\n");
                        // var i;
                        // for (i = 0; i < sdpArray.length; i++) {
                        //     if (sdpArray[i].indexOf("m=video") == 0) {
                        //         break;
                        //     }
                        //     if (sdpArray[i].indexOf("a=candidate:1 1") == 0 || sdpArray[i].indexOf("a=candidate:2 1") == 0) {
                        //         var rtcIceCandidate = new RTCIceCandidate({
                        //             candidate: sdpArray[i],
                        //             sdpMid: "audio",
                        //             sdpMLineIndex: 0
                        //         });
                        //         connection.addIceCandidate(rtcIceCandidate);
                        //     }
                        // }
                        // var video = false;
                        // for (i = 0; i < sdpArray.length; i++) {
                        //     if (sdpArray[i].indexOf("m=video") == 0) {
                        //         video = true;
                        //     }
                        //     if (video && (sdpArray[i].indexOf("a=candidate:1 1") == 0 || sdpArray[i].indexOf("a=candidate:2 1") == 0)) {
                        //         var rtcIceCandidate2 = new RTCIceCandidate({
                        //             candidate: sdpArray[i],
                        //             sdpMid: "video",
                        //             sdpMLineIndex: 1
                        //         });
                        //         connection.addIceCandidate(rtcIceCandidate2);
                        //     }
                        // }
                        // WCS-2204. fixed InvalidStateError
                        // connection.addIceCandidate(null);
                    }
                    resolve();
                }).catch(function (error) {
                    reject(error);
                });
            });
        };

        var setAudioOutputId = function (id) {
            if (remoteVideo) {
                //WCS-2063. fixed output device switch
                if (browserDetails.browser == "edge") {
                    var srcObject = remoteVideo.srcObject;
                    remoteVideo.srcObject = null;
                    var res = remoteVideo.setSinkId(id);
                    remoteVideo.srcObject = srcObject;
                    return res;
                }
                return remoteVideo.setSinkId(id);
            }
        };

        var getVolume = function () {
            if (remoteVideo && remoteVideo.srcObject && remoteVideo.srcObject.getAudioTracks().length > 0) {
                //return remoteVideo.srcObject.getAudioTracks()[0].volume * 100;
                return remoteVideo.volume * 100;
            }
            return -1;
        };

        var setVolume = function (volume) {
            if (remoteVideo && remoteVideo.srcObject && remoteVideo.srcObject.getAudioTracks().length > 0) {
                remoteVideo.volume = volume / 100;
            }
        };

        var unmuteRemoteAudio = function () {
            if (remoteVideo && remoteVideo.srcObject && remoteVideo.srcObject.getAudioTracks().length > 0) {
                remoteVideo.muted = false;
            }
        };

        var muteRemoteAudio = function () {
            if (remoteVideo && remoteVideo.srcObject && remoteVideo.srcObject.getAudioTracks().length > 0) {
                remoteVideo.muted = true;
            }
        };

        var isRemoteAudioMuted = function () {
            if (remoteVideo && remoteVideo.srcObject && remoteVideo.srcObject.getAudioTracks().length > 0) {
                return remoteVideo.muted;
            }
            return true;
        };

        var setMicrophoneGain = function (volume) {
            if (microphoneGain) {
                microphoneGain.gain.value = volume / 100;
            }
        };

        var muteAudio = function () {
            if (localVideo && localVideo.srcObject && localVideo.srcObject.getAudioTracks().length > 0) {
                localVideo.srcObject.getAudioTracks()[0].enabled = false;
            }
        };
        var unmuteAudio = function () {
            if (localVideo && localVideo.srcObject && localVideo.srcObject.getAudioTracks().length > 0) {
                localVideo.srcObject.getAudioTracks()[0].enabled = true;
            }
        };

        var isAudioMuted = function () {
            if (localVideo && localVideo.srcObject && localVideo.srcObject.getAudioTracks().length > 0) {
                return !localVideo.srcObject.getAudioTracks()[0].enabled;
            }
            return true;
        };
        var muteVideo = function () {
            if (localVideo && localVideo.srcObject && localVideo.srcObject.getVideoTracks().length > 0) {
                localVideo.srcObject.getVideoTracks()[0].enabled = false;
            }
        };
        var unmuteVideo = function () {
            if (localVideo && localVideo.srcObject && localVideo.srcObject.getVideoTracks().length > 0) {
                localVideo.srcObject.getVideoTracks()[0].enabled = true;
            }
        };
        var isVideoMuted = function () {
            if (localVideo && localVideo.srcObject && localVideo.srcObject.getVideoTracks().length > 0) {
                return !localVideo.srcObject.getVideoTracks()[0].enabled;
            }
            return true;
        };
        var getStat = function (callbackFn, nativeStats) {
            var browser = browserDetails.browser;
            var result = {outboundStream: {}, inboundStream: {}, otherStats: []};
            if (connection && validBrowsers.includes(browser)) {
                if (nativeStats) {
                    return connection.getStats(null);
                } else {
                    connection.getStats(null).then(function (stat) {
                        if (stat) {
                            stat.forEach(function (report) {
                                if (!report.isRemote) {
                                    if (report.type == 'outbound-rtp') {
                                        fillStatObject(result.outboundStream, report);
                                        if (report.mediaType == 'video') {
                                            var vSettings = localVideo.srcObject.getVideoTracks()[0].getSettings();
                                            result.outboundStream[report.mediaType].height = vSettings.height;
                                            result.outboundStream[report.mediaType].width = vSettings.width;
                                        }
                                    } else if (report.type == 'inbound-rtp') {
                                        fillStatObject(result.inboundStream, report);
                                        if (report.mediaType == 'video' && remoteVideo != undefined) {
                                            result.inboundStream[report.mediaType].height = remoteVideo.videoHeight;
                                            result.inboundStream[report.mediaType].width = remoteVideo.videoWidth;
                                        }
                                    }
                                }
                            });

                        }
                        callbackFn(result);
                    });
                }
            }
        };

        function fillStatObject(obj, report) {
            var mediaType = report.mediaType;
            obj[mediaType] = {};
            //WCS-1922, currentRemoteDescription - browser compatibilitySection: Chrome 70, FF 57, Safari 11
            var description = connection.currentRemoteDescription != undefined ? connection.currentRemoteDescription : connection.remoteDescription;
            var codec = util.getCurrentCodecAndSampleRate(description.sdp, mediaType);
            obj[mediaType]["codec"] = codec.name;
            obj[mediaType]["codecRate"] = codec.sampleRate;
            Object.keys(report).forEach(function (key) {
                if (key.startsWith("bytes") || key.startsWith("packets") || key.indexOf("Count") != -1) {
                    obj[mediaType][key] = report[key];
                }
            });
        }

        var fullScreen = function () {
            var video = document.getElementById(id);
            if (video) {
                if (!document.fullscreenElement && !document.mozFullScreenElement &&
                    !document.webkitFullscreenElement && !document.msFullscreenElement) {
                    if (video.requestFullscreen) {
                        video.requestFullscreen();
                    } else if (video.msRequestFullscreen) {
                        video.msRequestFullscreen();
                    } else if (video.mozRequestFullScreen) {
                        video.mozRequestFullScreen();
                    } else if (video.webkitRequestFullscreen) {
                        video.webkitRequestFullscreen();
                    } else if (video.webkitEnterFullscreen) {
                        video.webkitEnterFullscreen();
                        //hack for iOS safari. Video is getting paused when switching from fullscreen to normal mode.
                        video.addEventListener("pause", function () {
                            video.play();
                        });
                    }
                } else {
                    if (document.exitFullscreen) {
                        document.exitFullscreen();
                    } else if (document.msExitFullscreen) {
                        document.msExitFullscreen();
                    } else if (document.mozCancelFullScreen) {
                        document.mozCancelFullScreen();
                    } else if (document.webkitExitFullscreen) {
                        document.webkitExitFullscreen();
                    }
                }
            }
        };

        var switchCam = function (deviceId) {
            return new Promise(function (resolve, reject) {
                if (localVideo && localVideo.srcObject && videoCams.length > 1 && !customStream && !screenShare) {
                    connection.getSenders().forEach(function (sender) {
                        if (sender.track.kind === 'audio') return;
                        switchCamCount = (switchCamCount + 1) % videoCams.length;
                        sender.track.stop();
                        var cam = (typeof deviceId !== "undefined") ? deviceId : videoCams[switchCamCount];
                        //use the settings that were set during connection initiation
                        var clonedConstraints = Object.assign({}, constraints);
                        clonedConstraints.video.deviceId = {exact: cam};
                        clonedConstraints.audio = false;
                        navigator.mediaDevices.getUserMedia(clonedConstraints).then(function (newStream) {
                            var newVideoTrack = newStream.getVideoTracks()[0];
                            newVideoTrack.enabled = localVideo.srcObject.getVideoTracks()[0].enabled;
                            var audioTrack = localVideo.srcObject.getAudioTracks()[0];
                            sender.replaceTrack(newVideoTrack);
                            localVideo.srcObject = newStream;
                            // On Safari mobile _newStream_ doesn't contain audio track, so we need to add track from previous stream
                            if (localVideo.srcObject.getAudioTracks().length == 0 && audioTrack) {
                                localVideo.srcObject.addTrack(audioTrack);
                            }
                            logger.info("Switch camera to " + cam);
                            resolve(cam);
                        }).catch(function (reason) {
                            logger.error(LOG_PREFIX, reason);
                            reject(reason);
                        });
                    });
                } else {
                    reject(constants.ERROR_INFO.CAN_NOT_SWITCH_CAM);
                }
            });

        };

        var switchMic = function (deviceId) {
            return new Promise(function (resolve, reject) {
                if (localVideo && localVideo.srcObject && mics.length > 1 && !customStream) {
                    connection.getSenders().forEach(function (sender) {
                        if (sender.track.kind === 'video') return;
                        switchMicCount = (switchMicCount + 1) % mics.length;
                        sender.track.stop();
                        if (microphoneGain) {
                            microphoneGain.release();
                        }
                        var mic = (typeof deviceId !== "undefined") ? deviceId : mics[switchMicCount];
                        //use the settings that were set during connection initiation
                        var clonedConstraints = Object.assign({}, constraints);
                        clonedConstraints.audio.deviceId = {exact: mic};
                        clonedConstraints.video = false;
                        navigator.mediaDevices.getUserMedia(clonedConstraints).then(function (newStream) {
                            if (microphoneGain) {
                                var currentGain = microphoneGain.gain.value;
                                microphoneGain = createGainNode(newStream);
                                microphoneGain.gain.value = currentGain;
                            }
                            var newAudioTrack = newStream.getAudioTracks()[0];
                            newAudioTrack.enabled = localVideo.srcObject.getAudioTracks()[0].enabled;
                            currentAudioTrack = newAudioTrack;
                            var videoTrack = localVideo.srcObject.getVideoTracks()[0];
                            if (systemSoundTrack) {
                                var mixedTrack = mixAudioTracks(new MediaStream([newAudioTrack]), new MediaStream([systemSoundTrack]));
                                mixedTrack.enabled = newAudioTrack.enabled;
                                sender.replaceTrack(mixedTrack);
                                localVideo.srcObject = new MediaStream([mixedTrack]);
                            } else {
                                sender.replaceTrack(newAudioTrack);
                                localVideo.srcObject = newStream;
                            }
                            if (videoTrack) {
                                localVideo.srcObject.addTrack(videoTrack);
                            }
                            logger.info("Switch mic to " + mic);
                            resolve(mic);
                        }).catch(function (reason) {
                            logger.error(LOG_PREFIX, reason);
                            reject(reason);
                        });
                    });
                } else {
                    reject(constants.ERROR_INFO.CAN_NOT_SWITCH_MIC);
                }
            });
        };

        var switchToScreen = function (source, woExtension) {
            return new Promise(function (resolve, reject) {
                if (!screenShare) {
                    var clonedConstraints = {
                        video: Object.assign({}, constraints.video),
                        audio: Object.assign({}, constraints.audio)
                    };
                    if (browserDetails.browser === 'firefox') {
                        clonedConstraints.video.mediaSource = source;
                    }
                    if (window.chrome && woExtension) {
                        getScreenDeviceIdWoExtension(clonedConstraints).then(function (screenSharingConstraints) {
                            navigator.mediaDevices.getDisplayMedia(screenSharingConstraints).then(
                                (stream) => {
                                    processScreenStream(stream, resolve);
                                }).catch(reject);
                        });
                        return;
                    }
                    getScreenDeviceId(clonedConstraints).then(function (screenSharingConstraints) {
                        clonedConstraints.sourceId = screenSharingConstraints.sourceId;
                        if (screenSharingConstraints.audioMandatory) {
                            clonedConstraints.audio = {
                                mandatory: screenSharingConstraints.audioMandatory,
                                optional: []
                            };
                        } else {
                            delete clonedConstraints.audio;
                        }
                        if (browserDetails.browser == "firefox") {
                            clonedConstraints.video = screenSharingConstraints;
                        } else if (browserDetails.browser == "chrome") {
                            delete clonedConstraints.video;
                            clonedConstraints.video = {
                                mandatory: screenSharingConstraints.mandatory
                            }
                        }
                        navigator.mediaDevices.getUserMedia(clonedConstraints).then(function (stream) {
                            processScreenStream(stream, resolve);
                        }).catch(function (reason) {
                            logger.error(reason);
                            reject(reason);
                        });
                    }).catch(function (reason) {
                        logger.error(reason);
                        reject(reason);
                    });
                }
            });
        };

        var processScreenStream = function (stream, resolve) {
            connection.getSenders().forEach(function (sender) {
                if (sender.track.kind === 'audio') return;
                currentAudioTrack = localVideo.srcObject.getAudioTracks()[0];
                currentVideoTrack = localVideo.srcObject.getVideoTracks()[0];
                var newVideoTrack = stream.getVideoTracks()[0];
                newVideoTrack.enabled = currentVideoTrack.enabled;
                sender.replaceTrack(newVideoTrack);
                localVideo.srcObject = stream;
                if (stream.getAudioTracks()[0]) {
                    systemSoundTrack = stream.getAudioTracks()[0];
                    connection.getSenders().forEach(function (sender) {
                        if (sender.track.kind === 'video') return;
                        var mixedTrack = mixAudioTracks(stream, new MediaStream([sender.track]));
                        mixedTrack.enabled = currentAudioTrack.enabled;
                        sender.replaceTrack(mixedTrack);
                        localVideo.srcObject.removeTrack(stream.getAudioTracks()[0]);
                        localVideo.srcObject.addTrack(mixedTrack);
                        currentAudioTrack.enabled = true;
                    });
                } else {
                    localVideo.srcObject.addTrack(currentAudioTrack);
                }
            });
            logger.info("Switch to screen");
            screenShare = true;
            resolve();
        };

        var switchToCam = function () {
            if (screenShare) {
                connection.getSenders().forEach(function (sender) {
                    if (sender.track.kind === 'audio') return;
                    currentVideoTrack.enabled = sender.track.enabled;
                    sender.track.stop();
                    localVideo.srcObject = new MediaStream([currentVideoTrack]);
                    sender.replaceTrack(currentVideoTrack);
                    if (currentAudioTrack) {
                        connection.getSenders().forEach(function (sender) {
                            if (sender.track.kind === 'video') return;
                            if (systemSoundTrack) {
                                currentAudioTrack.enabled = sender.track.enabled;
                                sender.track.stop();
                                systemSoundTrack.stop();
                                systemSoundTrack = null;
                                sender.replaceTrack(currentAudioTrack);
                            }
                            localVideo.srcObject.addTrack(currentAudioTrack);
                        });
                    }
                });
            }
            logger.info("Switch to cam");
            screenShare = false;
        };

        var exports = {};
        exports.state = state;
        exports.createOffer = createOffer;
        exports.createAnswer = createAnswer;
        exports.setRemoteSdp = setRemoteSdp;
        exports.changeAudioCodec = changeAudioCodec;
        exports.close = close;
        exports.setAudioOutputId = setAudioOutputId;
        exports.setVolume = setVolume;
        exports.unmuteRemoteAudio = unmuteRemoteAudio;
        exports.muteRemoteAudio = muteRemoteAudio;
        exports.isRemoteAudioMuted = isRemoteAudioMuted;
        exports.setMicrophoneGain = setMicrophoneGain;
        exports.getVolume = getVolume;
        exports.muteAudio = muteAudio;
        exports.unmuteAudio = unmuteAudio;
        exports.isAudioMuted = isAudioMuted;
        exports.muteVideo = muteVideo;
        exports.unmuteVideo = unmuteVideo;
        exports.isVideoMuted = isVideoMuted;
        exports.getStats = getStat;
        exports.fullScreen = fullScreen;
        exports.switchCam = switchCam;
        exports.switchMic = switchMic;
        exports.switchToScreen = switchToScreen;
        exports.switchToCam = switchToCam;
        connections[id] = exports;
        resolve(exports);
    });
};

var mixAudioTracks = function (stream1, stream2) {
    var stream1Sound = audioContext.createMediaStreamSource(stream1);
    var stream2Sound = audioContext.createMediaStreamSource(stream2);
    var destination = audioContext.createMediaStreamDestination();
    var newStream = destination.stream;
    stream1Sound.connect(destination);
    stream2Sound.connect(destination);
    return newStream.getAudioTracks()[0];
};

var getMediaAccess = function (constraints, display, disableConstraintsNormalization) {
    return new Promise(function (resolve, reject) {

        if (!constraints) {
            constraints = defaultConstraints;
        }

        if (!disableConstraintsNormalization) {
            constraints = normalizeConstraints(constraints);
        }

        var cacheInstance = getCacheInstance(display);
        if (cacheInstance && cacheInstance.srcObject && JSON.stringify(display.mediaTrackConstraints) == JSON.stringify(constraints) && !constraints.customStream) {
            resolve(display);
            return;
        }

        display.mediaTrackConstraints = constraints;

        releaseMedia(display);

        if (!constraints.video && !constraints.audio && !constraints.customStream) {
            resolve(display);
            return;
        }
        //check if this is screen sharing
        if (constraints.video && constraints.video.type && constraints.video.type == "screen") {
            delete constraints.video.type;
            if (window.chrome && constraints.video.withoutExtension) {
                getScreenDeviceIdWoExtension(constraints).then(function (screenSharingConstraints) {
                    getScreenAccessWoExtension(screenSharingConstraints, constraints.audio);
                });
                return;
            }
            var requestAudioConstraints = null;
            getScreenDeviceId(constraints).then(function (screenSharingConstraints) {
                //copy constraints
                constraints.sourceId = screenSharingConstraints.sourceId;
                requestAudioConstraints = constraints.audio;
                if (screenSharingConstraints.audioMandatory) {
                    constraints.audio = {
                        mandatory: screenSharingConstraints.audioMandatory,
                        optional: []
                    };
                } else {
                    if (window.chrome) {
                        constraints.audio = false;
                    }
                }
                delete screenSharingConstraints.audioMandatory;
                delete screenSharingConstraints.sourceId;

                for (var prop in screenSharingConstraints) {
                    if (screenSharingConstraints.hasOwnProperty(prop)) {
                        constraints.video[prop] = screenSharingConstraints[prop];
                    }
                }
                if (browserDetails.browser == "chrome") {
                    delete constraints.video.frameRate;
                    delete constraints.video.height;
                    delete constraints.video.width;
                    delete constraints.systemSound;
                }
                getAccess(constraints, true, requestAudioConstraints);
            }, reject);
        } else {
            getAccess(constraints);
        }

        function getScreenAccessWoExtension(constraints, requestAudioConstraints) {
            //WCS-1952. exact constraints and system audio are not supported!
            navigator.mediaDevices.getDisplayMedia(constraints).then(
                (stream) => {
                    loadVideo(display, stream, true, requestAudioConstraints, resolve, constraints);
                }).catch(reject);
        }

        function getAccess(constraints, screenShare, requestAudioConstraints) {
            logger.info(LOG_PREFIX, constraints);
            if (constraints.customStream) {
                //get tracks if we have at least one defined constraint
                if (constraints.audio || constraints.video) {
                    //remove customStream from constraints before passing to GUM
                    var normalizedConstraints = {
                        audio: constraints.audio ? constraints.audio : false,
                        video: constraints.video ? constraints.video : false
                    };
                    navigator.getUserMedia(normalizedConstraints, function (stream) {
                        //add resulting tracks to customStream
                        stream.getTracks().forEach(function (track) {
                            constraints.customStream.addTrack(track);
                        });
                        //display customStream
                        loadVideo(display, constraints.customStream, screenShare, requestAudioConstraints, resolve, constraints);
                    }, reject);
                } else {
                    //display customStream
                    loadVideo(display, constraints.customStream, screenShare, requestAudioConstraints, resolve, constraints);
                }
            } else {
                navigator.getUserMedia(constraints, function (stream) {
                    loadVideo(display, stream, screenShare, requestAudioConstraints, resolve, constraints);
                }, reject);
            }
        }
    });
};

var loadVideo = function (display, stream, screenShare, requestAudioConstraints, resolve, constraints) {
    var video = getCacheInstance(display);
    if (!video) {
        video = document.createElement('video');
        display.appendChild(video);
    }
    if (createMicGainNode && stream.getAudioTracks().length > 0 && browserDetails.browser == "chrome") {
        //WCS-1696. We need to start audioContext to work with gain control
        audioContext.resume();
        microphoneGain = createGainNode(stream);
    }
    video.id = uuid_v1() + LOCAL_CACHED_VIDEO;
    video.srcObject = stream;
    //mute audio
    video.muted = true;
    video.onloadedmetadata = function (e) {
        if (screenShare && !window.chrome) {
            setScreenResolution(video, stream, constraints);
        }
        video.play();
    };
    if (constraints.systemSound && browserDetails.browser == "chrome") {
        addSystemSound();
    } else {
        resolveCallback();
    }

    function resolveCallback() {
        // This hack for chrome only, firefox supports screen-sharing + audio natively
        if (requestAudioConstraints && browserDetails.browser == "chrome") {
            logger.info(LOG_PREFIX, "Request for audio stream");
            navigator.getUserMedia({audio: requestAudioConstraints}, function (stream) {
                logger.info(LOG_PREFIX, "Got audio stream, add it to video stream");
                if (video.srcObject.getAudioTracks()[0]) {
                    var mixedTrack = mixAudioTracks(stream, video.srcObject);
                    var originalTrack = video.srcObject.getAudioTracks()[0];
                    video.srcObject.removeTrack(originalTrack);
                    video.srcObject.addTrack(mixedTrack);
                } else {
                    video.srcObject.addTrack(stream.getAudioTracks()[0]);
                }
                resolve(display);
            });
        } else {
            resolve(display);
        }
    }

    function addSystemSound() {
        chrome.runtime.sendMessage(extensionId, {type: "isInstalled"}, function (response) {
            if (response) {
                chrome.runtime.sendMessage(extensionId, {type: "getSourceId"}, function (response) {
                    if (response.error) {
                        resolveCallback();
                        logger.error(LOG_PREFIX, response.error);
                    } else {
                        if (response.systemSoundAccess) {
                            var constraints = {
                                audio: {
                                    mandatory: {
                                        chromeMediaSource: 'desktop',
                                        chromeMediaSourceId: response.sourceId,
                                        echoCancellation: true
                                    },
                                    optional: []
                                },
                                video: {
                                    mandatory: {
                                        chromeMediaSource: 'desktop',
                                        chromeMediaSourceId: response.sourceId
                                    },
                                    optional: []
                                }
                            };
                            navigator.getUserMedia(constraints, function (audioStream) {
                                if (stream.getAudioTracks().length > 0) {
                                    var originalAudioTrack = stream.getAudioTracks()[0];
                                    var mixedTrack = mixAudioTracks(stream, audioStream);
                                    stream.addTrack(mixedTrack);
                                    stream.removeTrack(originalAudioTrack);
                                } else {
                                    stream.addTrack(audioStream.getAudioTracks()[0]);
                                }
                                resolveCallback();
                            }, function (reason) {
                                resolveCallback();
                                logger.error(LOG_PREFIX, reason);
                            });
                        } else {
                            resolveCallback();
                            logger.error(LOG_PREFIX, "System sound: access is denied by the user");
                        }
                    }
                });
            } else {
                resolveCallback();
            }
        });
    }
};

var createGainNode = function (stream) {
    var audioCtx = audioContext;
    var source = audioCtx.createMediaStreamSource(stream);
    var gainNode = audioCtx.createGain();
    var destination = audioCtx.createMediaStreamDestination();
    var outputStream = destination.stream;
    source.connect(gainNode);
    gainNode.connect(destination);
    var sourceAudioTrack = stream.getAudioTracks()[0];
    gainNode.sourceAudioTrack = sourceAudioTrack;
    gainNode.release = function () {
        this.sourceAudioTrack.stop();
        this.disconnect();
    };
    stream.addTrack(outputStream.getAudioTracks()[0]);
    stream.removeTrack(sourceAudioTrack);
    return gainNode;
};

//Fix to set screen resolution for screen sharing in Firefox
var setScreenResolution = function (video, stream, constraints) {
    var newHeight;
    var newWidth;
    var videoRatio;
    if (video.videoWidth > video.videoHeight) {
        videoRatio = video.videoWidth / video.videoHeight;
        newHeight = constraints.video.videoWidth / videoRatio;
        newWidth = constraints.video.videoWidth;
    } else {
        videoRatio = video.videoHeight / video.videoWidth;
        newWidth = constraints.video.videoHeight / videoRatio;
        newHeight = constraints.video.videoHeight;
    }
    console.log("videoRatio === " + videoRatio);
    stream.getVideoTracks()[0].applyConstraints({height: newHeight, width: newWidth});
};

//for chrome
var getScreenDeviceIdWoExtension = function (constraints) {
    return new Promise(function (resolve, reject) {
        //WCS-1952. exact constraints are not supported.
        //WCS-1986. added audio: true to constraints.
        resolve({
            video: true,
            audio: true
        });
    });
};

var getScreenDeviceId = function (constraints) {
    return new Promise(function (resolve, reject) {
        var o = {};
        if (window.chrome) {
            chrome.runtime.sendMessage(extensionId, {type: "isInstalled"}, function (response) {
                //WCS-1972. fixed "TypeError"
                if (response) {
                    o.maxWidth = constraints && constraints.video && constraints.video.width ? constraints.video.width : 320;
                    o.maxHeight = constraints && constraints.video && constraints.video.height ? constraints.video.height : 240;
                    o.maxFrameRate = constraints && constraints.video && constraints.video.frameRate && constraints.video.frameRate.ideal ? constraints.video.frameRate.ideal : 30;

                    o.chromeMediaSource = "desktop";
                    chrome.runtime.sendMessage(extensionId, {type: "getSourceId"}, function (response) {
                        if (response.error) {
                            reject(new Error("Screen access denied"));
                        } else {
                            o.chromeMediaSourceId = response.sourceId;
                            var result = {
                                mandatory: o,
                                sourceId: response.sourceId
                            };
                            if (response.systemSoundAccess) {
                                result.audioMandatory = {
                                    chromeMediaSource: "desktop",
                                    chromeMediaSourceId: response.sourceId,
                                    echoCancellation: true
                                }
                            }
                            resolve(result);
                        }
                    });
                } else {
                    reject(new Error("Screen sharing extension is not available"));
                }
            });
        } else {
            //firefox case
            o.mediaSource = constraints.video.mediaSource;

            o.width = {};
            o.height = {};
            o.frameRate = {
                min: constraints.video.frameRate.max,
                max: constraints.video.frameRate.max
            };
            o.videoWidth = constraints.video.width;
            o.videoHeight = constraints.video.height;
            resolve(o);
        }
    });
};

var releaseMedia = function (display) {
    var video = getCacheInstance(display);
    if (video) {
        removeVideoElement(video);
        return true;
    }
    return false;
};

function getCacheInstance(display) {
    if (!display) return;
    var i;
    for (i = 0; i < display.children.length; i++) {
        if (display.children[i] && (display.children[i].id.indexOf(LOCAL_CACHED_VIDEO) != -1 || display.children[i].id.indexOf(REMOTE_CACHED_VIDEO) != -1)) {
            logger.info(LOG_PREFIX, "FOUND WEBRTC CACHED INSTANCE, id " + display.children[i].id);
            return display.children[i];
        }
    }
}

function removeVideoElement(video) {
    if (video.srcObject) {
        //pause
        video.pause();
        //stop media tracks
        var tracks = video.srcObject.getTracks();
        for (var i = 0; i < tracks.length; i++) {
            tracks[i].stop();
            if (video.id.indexOf(LOCAL_CACHED_VIDEO) != -1 && tracks[i].kind == 'audio' && microphoneGain) {
                microphoneGain.release();
            }
        }
        video.srcObject = null;
    }
}

/**
 * Check WebRTC available
 *
 * @returns {boolean} webrtc available
 */
var available = function () {
    //return (adapter.browserDetails.browser != "edge") ? navigator.getUserMedia && RTCPeerConnection : false;
    return ('getUserMedia' in navigator && 'RTCPeerConnection' in window);
};

var listDevices = function (labels, kind, deviceConstraints) {
    //WCS-1963. added deviceConstraints.
    if (!deviceConstraints) {
        deviceConstraints = {
            audio: true,
            video: true
        }
    }
    if (!kind) {
        kind = constants.MEDIA_DEVICE_KIND.INPUT;
    } else if (kind == "all") {
        kind = "";
    }
    var getConstraints = function (devices) {
        var constraints = {};
        for (var i = 0; i < devices.length; i++) {
            var device = devices[i];
            if (device.kind.indexOf("audio" + kind) === 0 && deviceConstraints.audio) {
                constraints.audio = true;
            } else if (device.kind.indexOf("video" + kind) === 0 && deviceConstraints.video) {
                constraints.video = true;
            } else {
                logger.debug(LOG_PREFIX, "unknown device " + device.kind + " id " + device.deviceId);
            }
        }
        return constraints;
    };

    var getList = function (devices) {
        var list = {
            audio: [],
            video: []
        };

        var micCount = 0;
        var outputCount = 0;
        var camCount = 0;
        for (var i = 0; i < devices.length; i++) {
            var device = devices[i];
            var ret = {
                id: device.deviceId,
                label: device.label
            };
            if (device.kind.indexOf("audio" + kind) === 0 && device.deviceId != "communications") {
                ret.type = (device.kind == "audioinput") ? "mic" : "speaker";
                if (ret.type == "mic" && ret.label == "") {
                    ret.label = 'microphone' + ++micCount;
                }
                if (ret.type == "speaker" && ret.label == "") {
                    ret.label = 'speaker' + ++outputCount;
                }
                list.audio.push(ret);
            } else if (device.kind.indexOf("video" + kind) === 0) {
                if (ret.label == "") {
                    ret.label = 'camera' + ++camCount;
                }
                ret.type = "camera";
                list.video.push(ret);
            } else {
                logger.debug(LOG_PREFIX, "unknown device " + device.kind + " id " + device.deviceId);
            }
        }
        return list;
    };

    return new Promise(function (resolve, reject) {
        navigator.mediaDevices.enumerateDevices().then(function (devices) {
            if (labels) {
                //WCS-2708. Fixed uncaught exception if no camera and mic
                var constraints = getConstraints(devices);
                if (Object.keys(constraints).length === 0) {
                    reject(new Error(kind + " media devices not found"));
                    return;
                }
                navigator.getUserMedia(constraints, function (stream) {
                    navigator.mediaDevices.enumerateDevices().then(function (devicesWithLabales) {
                        resolve(getList(devicesWithLabales));
                        stream.getTracks().forEach(function (track) {
                            track.stop();
                        });
                    }, reject);
                }, reject);
            } else {
                resolve(getList(devices));
            }
        }, reject);

    });
};

function normalizeConstraints(constraints) {
    //WCS-2010. fixed TypeError after publish->stop->publish
    //WCS-2373. fixed customStream
    var customStream = constraints.customStream;
    constraints = JSON.parse(JSON.stringify(constraints));
    constraints.customStream = customStream;
    if (constraints.video) {
        if (constraints.video === true) {
            constraints.video = {};
        }
        if (typeof constraints.video === 'object') {
            var width = constraints.video.width;
            var height = constraints.video.height;
            if (browserDetails.browser == "safari") {
                if (!width || !height) {
                    constraints.video.width = {min: 320, max: 640};
                    constraints.video.height = {min: 240, max: 480};
                } else if (typeof width !== 'object' || typeof height !== 'object') {
                    constraints.video.width = {min: width, max: width};
                    constraints.video.height = {min: height, max: height};
                }
            } else if (isNaN(width) || width === 0 || isNaN(height) || height === 0) {
                constraints.video.width = 320;
                constraints.video.height = 240;
            }

            //WCS-1972. fixed "TypeError"
            // Set default FPS value
            var frameRate = (!constraints.video.frameRate || constraints.video.frameRate == 0) ? 30 : constraints.video.frameRate;
            constraints.video.frameRate = {
                ideal: frameRate
            };
        }
    }

    if (constraints.audio) {
        // The WebRTC AEC implementation doesn't work well on stereophonic sound and makes mono on output
        if (constraints.audio.stereo) {
            constraints.audio.echoCancellation = false;
            constraints.audio.googEchoCancellation = false
        }
    }
    return constraints;
}

var playFirstSound = function () {
    if (audioContext) {
        var buffer = audioContext.createBuffer(1, 441, 44100);
        var output = buffer.getChannelData(0);
        for (var i = 0; i < output.length; i++) {
            output[i] = 0;
        }
        var source = audioContext.createBufferSource();
        source.buffer = buffer;
        // Connect to output (speakers)
        source.connect(audioContext.destination);
        // Play sound
        if (source.start) {
            source.start(0);
        } else if (source.play) {
            source.play(0);
        } else if (source.noteOn) {
            source.noteOn(0);
        }
        return true;
    }
    return false;
};

var playFirstVideo = function (display, isLocal, src) {
    return new Promise(function (resolve, reject) {
        if (!getCacheInstance(display)) {
            var video = document.createElement('video');
            video.setAttribute("playsinline", "");
            video.setAttribute("webkit-playsinline", "");
            video.id = uuid_v1() + (isLocal ? LOCAL_CACHED_VIDEO : REMOTE_CACHED_VIDEO);

            //in WCS-1560 we removed video.play() call, because it triggers the “Unhandled Promise Rejection” exception in iOS Safari
            //in WCS-2160 we rolled back the changes made in WCS-1560 due to no audio on first playback in iOS Safari
            if (src) {
                video.src = src;
                video.play().then(function () {
                    display.appendChild(video);
                    resolve();
                }).catch(function () {
                    //WCS-2375. fixed autoplay in ios safari
                    logger.info(LOG_PREFIX, "Autoplay detected! Trying to play a video with a muted sound...");
                    video.muted = true;
                    video.play().then(function () {
                        display.appendChild(video);
                        resolve();
                    });
                    //WCS-2375. low power mode suspends video play
                    video.onsuspend = function (event) {
                        reject();
                    };
                });
                return;
            }
        }
        resolve();
    });
};

module.exports = {
    createConnection: createConnection,
    getMediaAccess: getMediaAccess,
    releaseMedia: releaseMedia,
    listDevices: listDevices,
    playFirstSound: playFirstSound,
    playFirstVideo: playFirstVideo,
    available: available,
    configure: function (configuration) {
        extensionId = configuration.extensionId;
        defaultConstraints = configuration.constraints;
        audioContext = configuration.audioContext;
        logger = configuration.logger;
        createMicGainNode = (typeof configuration.createMicGainNode !== 'undefined') ? configuration.createMicGainNode : true;
        logger.info(LOG_PREFIX, "Initialized");
    }
};

{'repo_name': 'flashphoner/flashphoner_client', 'stars': '141', 'repo_language': 'JavaScript', 'file_name': 'scope_settings.xml', 'mime_type': 'text/plain', 'hash': 1678574254838134994, 'source_dataset': 'data'}


;*****************************************************************************
;* dct-32.asm: h264 encoder library
;*****************************************************************************
;* Copyright (C) 2003-2008 x264 project
;*
;* Authors: Loren Merritt <lorenm@u.washington.edu>
;*          Holger Lubitz <holger@lubitz.org>
;*          Laurent Aimar <fenrir@via.ecp.fr>
;*          Min Chen <chenm001.163.com>
;*          Christian Heine <sennindemokrit@gmx.net>
;*
;* This program is free software; you can redistribute it and/or modify
;* it under the terms of the GNU General Public License as published by
;* the Free Software Foundation; either version 2 of the License, or
;* (at your option) any later version.
;*
;* This program is distributed in the hope that it will be useful,
;* but WITHOUT ANY WARRANTY; without even the implied warranty of
;* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;* GNU General Public License for more details.
;*
;* You should have received a copy of the GNU General Public License
;* along with this program; if not, write to the Free Software
;* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111, USA.
;*****************************************************************************

%include "x86inc.asm"
%include "x86util.asm"

SECTION .text

cextern pw_32
cextern hsub_mul

; in: m0..m7
; out: 0,4,6 in mem, rest in regs
%macro DCT8_1D 9
    SUMSUB_BA  m%8, m%1      ; %8 = s07, %1 = d07
    SUMSUB_BA  m%7, m%2      ; %7 = s16, %2 = d16
    SUMSUB_BA  m%6, m%3      ; %6 = s25, %3 = d25
    SUMSUB_BA  m%5, m%4      ; %5 = s34, %4 = d34
    SUMSUB_BA  m%5, m%8      ; %5 = a0,  %8 = a2
    SUMSUB_BA  m%6, m%7      ; %6 = a1,  %7 = a3
    SUMSUB_BA  m%6, m%5      ; %6 = dst0, %5 = dst4
    mova    [%9+0x00], m%6
    mova    [%9+0x40], m%5
    mova    m%6, m%7         ; a3
    psraw   m%6, 1           ; a3>>1
    paddw   m%6, m%8         ; a2 + (a3>>1)
    psraw   m%8, 1           ; a2>>1
    psubw   m%8, m%7         ; (a2>>1) - a3
    mova    [%9+0x60], m%8
    mova    m%5, m%3
    psraw   m%5, 1
    paddw   m%5, m%3         ; d25+(d25>>1)
    mova    m%7, m%1
    psubw   m%7, m%4         ; a5 = d07-d34-(d25+(d25>>1))
    psubw   m%7, m%5
    mova    m%5, m%2
    psraw   m%5, 1
    paddw   m%5, m%2         ; d16+(d16>>1)
    mova    m%8, m%1
    paddw   m%8, m%4
    psubw   m%8, m%5         ; a6 = d07+d34-(d16+(d16>>1))
    mova    m%5, m%1
    psraw   m%5, 1
    paddw   m%5, m%1         ; d07+(d07>>1)
    paddw   m%5, m%2
    paddw   m%5, m%3         ; a4 = d16+d25+(d07+(d07>>1))
    mova    m%1, m%4
    psraw   m%1, 1
    paddw   m%1, m%4         ; d34+(d34>>1)
    paddw   m%1, m%2
    psubw   m%1, m%3         ; a7 = d16-d25+(d34+(d34>>1))
    mova    m%4, m%1
    psraw   m%4, 2
    paddw   m%4, m%5         ; a4 + (a7>>2)
    mova    m%3, m%8
    psraw   m%3, 2
    paddw   m%3, m%7         ; a5 + (a6>>2)
    psraw   m%5, 2
    psraw   m%7, 2
    psubw   m%5, m%1         ; (a4>>2) - a7
    psubw   m%8, m%7         ; a6 - (a5>>2)
    SWAP %2, %4, %3, %6, %8, %5
%endmacro

; in: 0,4 in mem, rest in regs
; out: m0..m7
%macro IDCT8_1D 9
    mova      m%1, m%3
    mova      m%5, m%7
    psraw     m%3, 1
    psraw     m%7, 1
    psubw     m%3, m%5
    paddw     m%7, m%1
    mova      m%5, m%2
    psraw     m%5, 1
    paddw     m%5, m%2
    paddw     m%5, m%4
    paddw     m%5, m%6
    mova      m%1, m%6
    psraw     m%1, 1
    paddw     m%1, m%6
    paddw     m%1, m%8
    psubw     m%1, m%2
    psubw     m%2, m%4
    psubw     m%6, m%4
    paddw     m%2, m%8
    psubw     m%6, m%8
    psraw     m%4, 1
    psraw     m%8, 1
    psubw     m%2, m%4
    psubw     m%6, m%8
    mova      m%4, m%5
    mova      m%8, m%1
    psraw     m%4, 2
    psraw     m%8, 2
    paddw     m%4, m%6
    paddw     m%8, m%2
    psraw     m%6, 2
    psraw     m%2, 2
    psubw     m%5, m%6
    psubw     m%2, m%1
    mova      m%1, [%9+0x00]
    mova      m%6, [%9+0x40]
    SUMSUB_BA m%6, m%1
    SUMSUB_BA m%7, m%6
    SUMSUB_BA m%3, m%1
    SUMSUB_BA m%5, m%7
    SUMSUB_BA m%2, m%3
    SUMSUB_BA m%8, m%1
    SUMSUB_BA m%4, m%6
    SWAP %1, %5, %6
    SWAP %3, %8, %7
%endmacro

INIT_MMX
ALIGN 16
load_diff_4x8_mmx:
    LOAD_DIFF m0, m7, none, [r1+0*FENC_STRIDE], [r2+0*FDEC_STRIDE]
    LOAD_DIFF m1, m7, none, [r1+1*FENC_STRIDE], [r2+1*FDEC_STRIDE]
    LOAD_DIFF m2, m7, none, [r1+2*FENC_STRIDE], [r2+2*FDEC_STRIDE]
    LOAD_DIFF m3, m7, none, [r1+3*FENC_STRIDE], [r2+3*FDEC_STRIDE]
    LOAD_DIFF m4, m7, none, [r1+4*FENC_STRIDE], [r2+4*FDEC_STRIDE]
    LOAD_DIFF m5, m7, none, [r1+5*FENC_STRIDE], [r2+5*FDEC_STRIDE]
    movq  [r0], m0
    LOAD_DIFF m6, m7, none, [r1+6*FENC_STRIDE], [r2+6*FDEC_STRIDE]
    LOAD_DIFF m7, m0, none, [r1+7*FENC_STRIDE], [r2+7*FDEC_STRIDE]
    movq  m0, [r0]
    ret

INIT_MMX
ALIGN 16
dct8_mmx:
    DCT8_1D 0,1,2,3,4,5,6,7,r0
    SAVE_MM_PERMUTATION dct8_mmx
    ret

%macro SPILL_SHUFFLE 3-* ; ptr, list of regs, list of memory offsets
    %xdefine %%base %1
    %rep %0/2
    %xdefine %%tmp m%2
    %rotate %0/2
    mova [%%base + %2*16], %%tmp
    %rotate 1-%0/2
    %endrep
%endmacro

%macro UNSPILL_SHUFFLE 3-*
    %xdefine %%base %1
    %rep %0/2
    %xdefine %%tmp m%2
    %rotate %0/2
    mova %%tmp, [%%base + %2*16]
    %rotate 1-%0/2
    %endrep
%endmacro

%macro SPILL 2+ ; assume offsets are the same as reg numbers
    SPILL_SHUFFLE %1, %2, %2
%endmacro

%macro UNSPILL 2+
    UNSPILL_SHUFFLE %1, %2, %2
%endmacro

;-----------------------------------------------------------------------------
; void sub8x8_dct8( int16_t dct[8][8], uint8_t *pix1, uint8_t *pix2 )
;-----------------------------------------------------------------------------
cglobal sub8x8_dct8_mmx, 3,3
global sub8x8_dct8_mmx.skip_prologue
.skip_prologue:
    INIT_MMX
    call load_diff_4x8_mmx
    call dct8_mmx
    UNSPILL r0, 0
    TRANSPOSE4x4W 0,1,2,3,4
    SPILL r0, 0,1,2,3
    UNSPILL r0, 4,6
    TRANSPOSE4x4W 4,5,6,7,0
    SPILL r0, 4,5,6,7
    INIT_MMX
    add   r1, 4
    add   r2, 4
    add   r0, 8
    call load_diff_4x8_mmx
    sub   r1, 4
    sub   r2, 4
    call dct8_mmx
    sub   r0, 8
    UNSPILL r0+8, 4,6
    TRANSPOSE4x4W 4,5,6,7,0
    SPILL r0+8, 4,5,6,7
    UNSPILL r0+8, 0
    TRANSPOSE4x4W 0,1,2,3,5
    UNSPILL r0, 4,5,6,7
    SPILL_SHUFFLE r0, 0,1,2,3, 4,5,6,7
    movq  mm4, m6 ; depends on the permutation to not produce conflicts
    movq  mm0, m4
    movq  mm1, m5
    movq  mm2, mm4
    movq  mm3, m7
    INIT_MMX
    UNSPILL r0+8, 4,5,6,7
    add   r0, 8
    call dct8_mmx
    sub   r0, 8
    SPILL r0+8, 1,2,3,5,7
    INIT_MMX
    UNSPILL r0, 0,1,2,3,4,5,6,7
    call dct8_mmx
    SPILL r0, 1,2,3,5,7
    ret

INIT_MMX
ALIGN 16
idct8_mmx:
    IDCT8_1D 0,1,2,3,4,5,6,7,r1
    SAVE_MM_PERMUTATION idct8_mmx
    ret

%macro ADD_STORE_ROW 3
    movq  m1, [r0+%1*FDEC_STRIDE]
    movq  m2, m1
    punpcklbw m1, m0
    punpckhbw m2, m0
    paddw m1, %2
    paddw m2, %3
    packuswb m1, m2
    movq  [r0+%1*FDEC_STRIDE], m1
%endmacro

;-----------------------------------------------------------------------------
; void add8x8_idct8( uint8_t *dst, int16_t dct[8][8] )
;-----------------------------------------------------------------------------
cglobal add8x8_idct8_mmx, 2,2
global add8x8_idct8_mmx.skip_prologue
.skip_prologue:
    INIT_MMX
    add word [r1], 32
    UNSPILL r1, 1,2,3,5,6,7
    call idct8_mmx
    SPILL r1, 7
    TRANSPOSE4x4W 0,1,2,3,7
    SPILL r1, 0,1,2,3
    UNSPILL r1, 7
    TRANSPOSE4x4W 4,5,6,7,0
    SPILL r1, 4,5,6,7
    INIT_MMX
    UNSPILL r1+8, 1,2,3,5,6,7
    add r1, 8
    call idct8_mmx
    sub r1, 8
    SPILL r1+8, 7
    TRANSPOSE4x4W 0,1,2,3,7
    SPILL r1+8, 0,1,2,3
    UNSPILL r1+8, 7
    TRANSPOSE4x4W 4,5,6,7,0
    SPILL r1+8, 4,5,6,7
    INIT_MMX
    movq  m3, [r1+0x08]
    movq  m0, [r1+0x40]
    movq  [r1+0x40], m3
    movq  [r1+0x08], m0
    ; memory layout at this time:
    ; A0------ A1------
    ; B0------ F0------
    ; C0------ G0------
    ; D0------ H0------
    ; E0------ E1------
    ; B1------ F1------
    ; C1------ G1------
    ; D1------ H1------
    UNSPILL_SHUFFLE r1, 1,2,3, 5,6,7
    UNSPILL r1+8, 5,6,7
    add r1, 8
    call idct8_mmx
    sub r1, 8
    psraw m0, 6
    psraw m1, 6
    psraw m2, 6
    psraw m3, 6
    psraw m4, 6
    psraw m5, 6
    psraw m6, 6
    psraw m7, 6
    movq  [r1+0x08], m0 ; mm4
    movq  [r1+0x48], m4 ; mm5
    movq  [r1+0x58], m5 ; mm0
    movq  [r1+0x68], m6 ; mm2
    movq  [r1+0x78], m7 ; mm6
    movq  mm5, [r1+0x18]
    movq  mm6, [r1+0x28]
    movq  [r1+0x18], m1 ; mm1
    movq  [r1+0x28], m2 ; mm7
    movq  mm7, [r1+0x38]
    movq  [r1+0x38], m3 ; mm3
    movq  mm1, [r1+0x10]
    movq  mm2, [r1+0x20]
    movq  mm3, [r1+0x30]
    call idct8_mmx
    psraw m0, 6
    psraw m1, 6
    psraw m2, 6
    psraw m3, 6
    psraw m4, 6
    psraw m5, 6
    psraw m6, 6
    psraw m7, 6
    SPILL r1, 0,1,2
    pxor  m0, m0
    ADD_STORE_ROW 0, [r1+0x00], [r1+0x08]
    ADD_STORE_ROW 1, [r1+0x10], [r1+0x18]
    ADD_STORE_ROW 2, [r1+0x20], [r1+0x28]
    ADD_STORE_ROW 3, m3, [r1+0x38]
    ADD_STORE_ROW 4, m4, [r1+0x48]
    ADD_STORE_ROW 5, m5, [r1+0x58]
    ADD_STORE_ROW 6, m6, [r1+0x68]
    ADD_STORE_ROW 7, m7, [r1+0x78]
    ret

INIT_XMM
%macro DCT_SUB8 1
cglobal sub8x8_dct_%1, 3,3
    add r2, 4*FDEC_STRIDE
global sub8x8_dct_%1.skip_prologue
.skip_prologue:
%ifnidn %1, sse2
    mova m7, [hsub_mul]
%endif
    LOAD_DIFF8x4 0, 1, 2, 3, 6, 7, r1, r2-4*FDEC_STRIDE
    SPILL r0, 1,2
    SWAP 2, 7
    LOAD_DIFF8x4 4, 5, 6, 7, 1, 2, r1, r2-4*FDEC_STRIDE
    UNSPILL r0, 1
    SPILL r0, 7
    SWAP 2, 7
    UNSPILL r0, 2
    DCT4_1D 0, 1, 2, 3, 7
    TRANSPOSE2x4x4W 0, 1, 2, 3, 7
    UNSPILL r0, 7
    SPILL r0, 2
    DCT4_1D 4, 5, 6, 7, 2
    TRANSPOSE2x4x4W 4, 5, 6, 7, 2
    UNSPILL r0, 2
    SPILL r0, 6
    DCT4_1D 0, 1, 2, 3, 6
    UNSPILL r0, 6
    STORE_DCT 0, 1, 2, 3, r0, 0
    DCT4_1D 4, 5, 6, 7, 3
    STORE_DCT 4, 5, 6, 7, r0, 64
    ret

;-----------------------------------------------------------------------------
; void sub8x8_dct8( int16_t dct[8][8], uint8_t *pix1, uint8_t *pix2 )
;-----------------------------------------------------------------------------
cglobal sub8x8_dct8_%1, 3,3
    add r2, 4*FDEC_STRIDE
global sub8x8_dct8_%1.skip_prologue
.skip_prologue:
%ifidn %1, sse2
    LOAD_DIFF m0, m7, none, [r1+0*FENC_STRIDE], [r2-4*FDEC_STRIDE]
    LOAD_DIFF m1, m7, none, [r1+1*FENC_STRIDE], [r2-3*FDEC_STRIDE]
    LOAD_DIFF m2, m7, none, [r1+2*FENC_STRIDE], [r2-2*FDEC_STRIDE]
    LOAD_DIFF m3, m7, none, [r1+3*FENC_STRIDE], [r2-1*FDEC_STRIDE]
    LOAD_DIFF m4, m7, none, [r1+4*FENC_STRIDE], [r2+0*FDEC_STRIDE]
    LOAD_DIFF m5, m7, none, [r1+5*FENC_STRIDE], [r2+1*FDEC_STRIDE]
    SPILL r0, 0
    LOAD_DIFF m6, m7, none, [r1+6*FENC_STRIDE], [r2+2*FDEC_STRIDE]
    LOAD_DIFF m7, m0, none, [r1+7*FENC_STRIDE], [r2+3*FDEC_STRIDE]
    UNSPILL r0, 0
%else
    mova m7, [hsub_mul]
    LOAD_DIFF8x4 0, 1, 2, 3, 4, 7, r1, r2-4*FDEC_STRIDE
    SPILL r0, 0,1
    SWAP 1, 7
    LOAD_DIFF8x4 4, 5, 6, 7, 0, 1, r1, r2-4*FDEC_STRIDE
    UNSPILL r0, 0,1
%endif
    DCT8_1D 0,1,2,3,4,5,6,7,r0
    UNSPILL r0, 0,4
    TRANSPOSE8x8W 0,1,2,3,4,5,6,7,[r0+0x60],[r0+0x40],1
    UNSPILL r0, 4
    DCT8_1D 0,1,2,3,4,5,6,7,r0
    SPILL r0, 1,2,3,5,7
    ret
%endmacro

%define LOAD_DIFF8x4 LOAD_DIFF8x4_SSE2
%define movdqa movaps
%define punpcklqdq movlhps
DCT_SUB8 sse2
%undef movdqa
%undef punpcklqdq
%define LOAD_DIFF8x4 LOAD_DIFF8x4_SSSE3
DCT_SUB8 ssse3

;-----------------------------------------------------------------------------
; void add8x8_idct( uint8_t *pix, int16_t dct[4][4][4] )
;-----------------------------------------------------------------------------
cglobal add8x8_idct_sse2, 2,2
    add r0, 4*FDEC_STRIDE
global add8x8_idct_sse2.skip_prologue
.skip_prologue:
    UNSPILL_SHUFFLE r1, 0,2,1,3, 0,1,2,3
    SBUTTERFLY qdq, 0, 1, 4
    SBUTTERFLY qdq, 2, 3, 4
    UNSPILL_SHUFFLE r1, 4,6,5,7, 4,5,6,7
    SPILL r1, 0
    SBUTTERFLY qdq, 4, 5, 0
    SBUTTERFLY qdq, 6, 7, 0
    UNSPILL r1,0
    IDCT4_1D 0,1,2,3,r1
    SPILL r1, 4
    TRANSPOSE2x4x4W 0,1,2,3,4
    UNSPILL r1, 4
    IDCT4_1D 4,5,6,7,r1
    SPILL r1, 0
    TRANSPOSE2x4x4W 4,5,6,7,0
    UNSPILL r1, 0
    paddw m0, [pw_32]
    IDCT4_1D 0,1,2,3,r1
    paddw m4, [pw_32]
    IDCT4_1D 4,5,6,7,r1
    SPILL r1, 6,7
    pxor m7, m7
    DIFFx2 m0, m1, m6, m7, [r0-4*FDEC_STRIDE], [r0-3*FDEC_STRIDE]; m5
    DIFFx2 m2, m3, m6, m7, [r0-2*FDEC_STRIDE], [r0-1*FDEC_STRIDE]; m5
    UNSPILL_SHUFFLE r1, 0,2, 6,7
    DIFFx2 m4, m5, m6, m7, [r0+0*FDEC_STRIDE], [r0+1*FDEC_STRIDE]; m5
    DIFFx2 m0, m2, m6, m7, [r0+2*FDEC_STRIDE], [r0+3*FDEC_STRIDE]; m5
    STORE_IDCT m1, m3, m5, m2
    ret

;-----------------------------------------------------------------------------
; void add8x8_idct8( uint8_t *p_dst, int16_t dct[8][8] )
;-----------------------------------------------------------------------------
cglobal add8x8_idct8_sse2, 2,2
    add r0, 4*FDEC_STRIDE
global add8x8_idct8_sse2.skip_prologue
.skip_prologue:
    UNSPILL r1, 1,2,3,5,6,7
    IDCT8_1D   0,1,2,3,4,5,6,7,r1
    SPILL r1, 6
    TRANSPOSE8x8W 0,1,2,3,4,5,6,7,[r1+0x60],[r1+0x40],1
    paddw      m0, [pw_32]
    SPILL r1, 0
    IDCT8_1D   0,1,2,3,4,5,6,7,r1
    SPILL r1, 6,7
    pxor       m7, m7
    DIFFx2 m0, m1, m6, m7, [r0-4*FDEC_STRIDE], [r0-3*FDEC_STRIDE]; m5
    DIFFx2 m2, m3, m6, m7, [r0-2*FDEC_STRIDE], [r0-1*FDEC_STRIDE]; m5
    UNSPILL_SHUFFLE r1, 0,2, 6,7
    DIFFx2 m4, m5, m6, m7, [r0+0*FDEC_STRIDE], [r0+1*FDEC_STRIDE]; m5
    DIFFx2 m0, m2, m6, m7, [r0+2*FDEC_STRIDE], [r0+3*FDEC_STRIDE]; m5
    STORE_IDCT m1, m3, m5, m2
    ret

{'repo_name': 'google/sagetv', 'stars': '238', 'repo_language': 'Java', 'file_name': 'MpegMux.h', 'mime_type': 'text/x-c++', 'hash': -1167054179653710514, 'source_dataset': 'data'}


#include "stdafx.h"
#include "r2.h"
#include "../xrRender/ResourceManager.h"
#include "../xrRender/fbasicvisual.h"
#include "../../xrEngine/fmesh.h"
#include "../../xrEngine/xrLevel.h"
#include "../../xrEngine/x_ray.h"
#include "../../xrEngine/IGame_Persistent.h"
#include "../../xrCore/stream_reader.h"

#include "../xrRender/dxRenderDeviceRender.h"

#pragma warning(push)
#pragma warning(disable:4995)
#include <malloc.h>
#pragma warning(pop)

void CRender::level_Load(IReader* fs)
{
	R_ASSERT						(0!=g_pGameLevel);
	R_ASSERT						(!b_loaded);

	// Begin
	pApp->LoadBegin					();
	dxRenderDeviceRender::Instance().Resources->DeferredLoad	(TRUE);
	IReader*						chunk;

	// Shaders
	g_pGamePersistent->LoadTitle		("st_loading_shaders");
	{
		chunk = fs->open_chunk		(fsL_SHADERS);
		R_ASSERT2					(chunk,"Level doesn't builded correctly.");
		u32 count = chunk->r_u32	();
		Shaders.resize				(count);
		for(u32 i=0; i<count; i++)	// skip first shader as "reserved" one
		{
			string512				n_sh,n_tlist;
			LPCSTR			n		= LPCSTR(chunk->pointer());
			chunk->skip_stringZ		();
			if (0==n[0])			continue;
			strcpy_s					(n_sh,n);
			LPSTR			delim	= strchr(n_sh,'/');
			*delim					= 0;
			strcpy_s					(n_tlist,delim+1);
			Shaders[i]				= dxRenderDeviceRender::Instance().Resources->Create(n_sh,n_tlist);
		}
		chunk->close();
	}

	// Components
	Wallmarks					= new CWallmarksEngine();
	Details						= new CDetailManager();

	if	(!g_dedicated_server)	{
		// VB,IB,SWI
		g_pGamePersistent->LoadTitle("st_loading_geometry");
		{
			CStreamReader			*geom = FS.rs_open("$level$","level.geom");
			R_ASSERT2				(geom, "level.geom");
			LoadBuffers				(geom,FALSE);
			LoadSWIs				(geom);
			FS.r_close				(geom);
		}

		//...and alternate/fast geometry
		{
			CStreamReader			*geom = FS.rs_open("$level$","level.geomx");
			R_ASSERT2				(geom, "level.geomX");
			LoadBuffers				(geom,TRUE);
			FS.r_close				(geom);
		}

		// Visuals
		g_pGamePersistent->LoadTitle("st_loading_spatial_db");
		chunk						= fs->open_chunk(fsL_VISUALS);
		LoadVisuals					(chunk);
		chunk->close				();

		// Details
		g_pGamePersistent->LoadTitle("st_loading_details");
		Details->Load				();
	}

	// Sectors
	g_pGamePersistent->LoadTitle("st_loading_sectors_portals");
	LoadSectors					(fs);

	// HOM
	HOM.Load					();

	// Lights
	// pApp->LoadTitle			("Loading lights...");
	LoadLights					(fs);

	// End
	pApp->LoadEnd				();

	// sanity-clear
	lstLODs.clear				();
	lstLODgroups.clear			();
	mapLOD.clear				();

	// signal loaded
	b_loaded					= TRUE	;
}

void CRender::level_Unload()
{
	if (0==g_pGameLevel)		return;
	if (!b_loaded)				return;

	u32 I;

	// HOM
	HOM.Unload				();

	//*** Details
	Details->Unload			();

	//*** Sectors
	// 1.
	xr_delete				(rmPortals);
	pLastSector				= 0;
	vLastCameraPos.set		(0,0,0);
	// 2.
	for (I=0; I<Sectors.size(); I++)	xr_delete(Sectors[I]);
	Sectors.clear			();
	// 3.
	for (I=0; I<Portals.size(); I++)	xr_delete(Portals[I]);
	Portals.clear			();

	//*** Lights
	// Glows.Unload			();
	Lights.Unload			();

	//*** Visuals
	for (I=0; I<Visuals.size(); I++)
	{
		Visuals[I]->Release();
		xr_delete(Visuals[I]);
	}
	Visuals.clear			();

	//*** SWI
	for (I=0; I<SWIs.size();I++)xr_free	(SWIs[I].sw);
	SWIs.clear				();

	//*** VB/IB
	for (I=0; I<nVB.size(); I++)	_RELEASE(nVB[I]);
	for (I=0; I<xVB.size(); I++)	_RELEASE(xVB[I]);
	nVB.clear(); xVB.clear();
	for (I=0; I<nIB.size(); I++)	_RELEASE(nIB[I]);
	for (I=0; I<xIB.size(); I++)	_RELEASE(xIB[I]);
	nIB.clear(); xIB.clear();
	nDC.clear(); xDC.clear();

	//*** Components
	xr_delete					(Details);
	xr_delete					(Wallmarks);

	//*** Shaders
	Shaders.clear_and_free		();
	b_loaded					= FALSE;
}

void CRender::LoadBuffers		(CStreamReader *base_fs,	BOOL _alternative)
{
	R_ASSERT2					(base_fs,"Could not load geometry. File not found.");
	dxRenderDeviceRender::Instance().Resources->Evict		();
	u32	dwUsage					= D3DUSAGE_WRITEONLY;

	xr_vector<VertexDeclarator>				&_DC	= _alternative?xDC:nDC;
	xr_vector<IDirect3DVertexBuffer9*>		&_VB	= _alternative?xVB:nVB;
	xr_vector<IDirect3DIndexBuffer9*>		&_IB	= _alternative?xIB:nIB;

	// Vertex buffers
	{
		// Use DX9-style declarators
		CStreamReader			*fs	= base_fs->open_chunk(fsL_VB);
		R_ASSERT2				(fs,"Could not load geometry. File 'level.geom?' corrupted.");
		u32 count				= fs->r_u32();
		_DC.resize				(count);
		_VB.resize				(count);
		for (u32 i=0; i<count; i++)
		{
			// decl
//			D3DVERTEXELEMENT9*	dcl		= (D3DVERTEXELEMENT9*) fs().pointer();
			u32					buffer_size = (MAXD3DDECLLENGTH+1)*sizeof(D3DVERTEXELEMENT9);
			D3DVERTEXELEMENT9	*dcl = (D3DVERTEXELEMENT9*)_alloca(buffer_size);
			fs->r				(dcl,buffer_size);
			fs->advance			(-(int)buffer_size);

			u32 dcl_len			= D3DXGetDeclLength		(dcl)+1;
			_DC[i].resize		(dcl_len);
			fs->r				(_DC[i].begin(),dcl_len*sizeof(D3DVERTEXELEMENT9));

			// count, size
			u32 vCount			= fs->r_u32	();
			u32 vSize			= D3DXGetDeclVertexSize	(dcl,0);
			Msg	("* [Loading VB] %d verts, %d Kb",vCount,(vCount*vSize)/1024);

			// Create and fill
			BYTE*	pData		= 0;
			R_CHK				(HW.pDevice->CreateVertexBuffer(vCount*vSize,dwUsage,0,D3DPOOL_MANAGED,&_VB[i],0));
			R_CHK				(_VB[i]->Lock(0,0,(void**)&pData,0));
//			CopyMemory			(pData,fs().pointer(),vCount*vSize);
			fs->r				(pData,vCount*vSize);
			_VB[i]->Unlock		();

//			fs->advance			(vCount*vSize);
		}
		fs->close				();
	}

	// Index buffers
	{
		CStreamReader			*fs	= base_fs->open_chunk(fsL_IB);
		u32 count				= fs->r_u32();
		_IB.resize				(count);
		for (u32 i=0; i<count; i++)
		{
			u32 iCount			= fs->r_u32	();
			Msg("* [Loading IB] %d indices, %d Kb",iCount,(iCount*2)/1024);

			// Create and fill
			BYTE*	pData		= 0;
			R_CHK				(HW.pDevice->CreateIndexBuffer(iCount*2,dwUsage,D3DFMT_INDEX16,D3DPOOL_MANAGED,&_IB[i],0));
			R_CHK				(_IB[i]->Lock(0,0,(void**)&pData,0));
//			CopyMemory			(pData,fs().pointer(),iCount*2);
			fs->r				(pData,iCount*2);
			_IB[i]->Unlock		();

//			fs().advance		(iCount*2);
		}
		fs->close				();
	}
}

void CRender::LoadVisuals(IReader *fs)
{
	IReader*		chunk	= 0;
	u32			index	= 0;
	dxRender_Visual*		V		= 0;
	ogf_header		H;

	while ((chunk=fs->open_chunk(index))!=0)
	{
		chunk->r_chunk_safe			(OGF_HEADER,&H,sizeof(H));
		V = Models->Instance_Create	(H.type);
		V->Load(0,chunk,0);
		Visuals.push_back(V);

		chunk->close();
		index++;
	}
}

void CRender::LoadLights(IReader *fs)
{
	// lights
	Lights.Load	(fs);
	Lights.LoadHemi();
}

struct b_portal
{
	u16				sector_front;
	u16				sector_back;
	svector<Fvector,6>	vertices;
};

void CRender::LoadSectors(IReader* fs)
{
	// allocate memory for portals
	u32 size = fs->find_chunk(fsL_PORTALS);
	R_ASSERT(0==size%sizeof(b_portal));
	u32 count = size/sizeof(b_portal);
	Portals.resize	(count);
	for (u32 c=0; c<count; c++)
		Portals[c]	= new CPortal();

	// load sectors
	IReader* S = fs->open_chunk(fsL_SECTORS);
	for (u32 i=0; ; i++)
	{
		IReader* P = S->open_chunk(i);
		if (0==P) break;

		CSector* __S		= new CSector();
		__S->load			(*P);
		Sectors.push_back	(__S);

		P->close();
	}
	S->close();

	// load portals
	if (count)
	{
		CDB::Collector	CL;
		fs->find_chunk	(fsL_PORTALS);
		for (i=0; i<count; i++)
		{
			b_portal	P;
			fs->r		(&P,sizeof(P));
			CPortal*	__P	= (CPortal*)Portals[i];
			__P->Setup	(P.vertices.begin(),P.vertices.size(),
				(CSector*)getSector(P.sector_front),
				(CSector*)getSector(P.sector_back));
			for (u32 j=2; j<P.vertices.size(); j++)
				CL.add_face_packed_D(
				P.vertices[0],P.vertices[j-1],P.vertices[j],
				u32(i)
				);
		}
		if (CL.getTS()<2)
		{
			Fvector					v1,v2,v3;
			v1.set					(-20000.f,-20000.f,-20000.f);
			v2.set					(-20001.f,-20001.f,-20001.f);
			v3.set					(-20002.f,-20002.f,-20002.f);
			CL.add_face_packed_D	(v1,v2,v3,0);
		}

		// build portal model
		rmPortals = new CDB::MODEL();
		rmPortals->build	(CL.getV(),int(CL.getVS()),CL.getT(),int(CL.getTS()));
	} else {
		rmPortals = 0;
	}

	// debug
	//	for (int d=0; d<Sectors.size(); d++)
	//		Sectors[d]->DebugDump	();

	pLastSector = 0;
}

void CRender::LoadSWIs(CStreamReader* base_fs)
{
	// allocate memory for portals
	if (base_fs->find_chunk(fsL_SWIS)){
		CStreamReader		*fs	= base_fs->open_chunk(fsL_SWIS);
		u32 item_count		= fs->r_u32();

		xr_vector<FSlideWindowItem>::iterator it	= SWIs.begin();
		xr_vector<FSlideWindowItem>::iterator it_e	= SWIs.end();

		for(;it!=it_e;++it)
			xr_free( (*it).sw );

		SWIs.clear_not_free();

		SWIs.resize			(item_count);
		for (u32 c=0; c<item_count; c++){
			FSlideWindowItem& swi = SWIs[c];
			swi.reserved[0]	= fs->r_u32();
			swi.reserved[1]	= fs->r_u32();
			swi.reserved[2]	= fs->r_u32();
			swi.reserved[3]	= fs->r_u32();
			swi.count		= fs->r_u32();
			VERIFY			(NULL==swi.sw);
			swi.sw			= xr_alloc<FSlideWindow> (swi.count);
			fs->r			(swi.sw,sizeof(FSlideWindow)*swi.count);
		}
		fs->close			();
	}
}

{'repo_name': 'OpenXRay/xray-15', 'stars': '145', 'repo_language': 'C++', 'file_name': 'pem.h', 'mime_type': 'text/x-c', 'hash': 2648468058828233856, 'source_dataset': 'data'}


<!-- Adobe Analytics for Red Hat - DPAL (DTM Property Auto-Loader) - part 1/2 -->
<script id="dpal" src="https://www.redhat.com/dtm.js" type="text/javascript"></script>
<!-- Google Analytics for kie team: Global site tag (gtag.js) -->
<script async src="https://www.googletagmanager.com/gtag/js?id={html-googleAnalyticsId}"></script>
<script>
    window.dataLayer = window.dataLayer || [];
    function gtag(){dataLayer.push(arguments);}
    gtag('js', new Date());

    gtag('config', '{html-googleAnalyticsId}');
</script>

<!-- Collapsed Table of Content -->
<link rel="stylesheet" href="website/jstree/style.css" />
<link rel="stylesheet" href="website/toc.css" />

{'repo_name': 'kiegroup/optaplanner', 'stars': '1643', 'repo_language': 'Java', 'file_name': 'runExamples.bat', 'mime_type': 'text/x-msdos-batch', 'hash': -3032065358116838941, 'source_dataset': 'data'}


/* 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/. */

import React from 'react';
import { withTheme } from '../../../cn';
import Icon from '../..';
import { IconProps } from '../../icon';

class IconEmoney extends React.PureComponent<IconProps> {
    render() {
        return (
            <Icon
                { ...this.props }
                name="emoney"
            />
        );
    }
}

export default withTheme<IconProps, IconEmoney>(IconEmoney);

{'repo_name': 'alfa-laboratory/arui-feather', 'stars': '532', 'repo_language': 'TypeScript', 'file_name': 'setup.ts', 'mime_type': 'text/x-java', 'hash': 49222935095247396, 'source_dataset': 'data'}


package main

import (
	"flag"
	"os"
	"os/signal"
	"syscall"
	"time"

	"context"
	"go-common/app/service/live/xlottery/conf"
	"go-common/app/service/live/xlottery/server/grpc"
	"go-common/app/service/live/xlottery/server/http"
	"go-common/app/service/live/xlottery/service"
	ecode "go-common/library/ecode/tip"
	"go-common/library/log"
	"go-common/library/net/trace"
)

func main() {
	flag.Parse()
	if err := conf.Init(); err != nil {
		panic(err)
	}
	log.Init(conf.Conf.Log)
	defer log.Close()
	log.Info("lottery-service start")
	trace.Init(conf.Conf.Tracer)
	defer trace.Close()
	ecode.Init(conf.Conf.Ecode)
	svc := service.New(conf.Conf)
	gsvr := grpc.Init(conf.Conf)
	http.Init(conf.Conf, svc)
	c := make(chan os.Signal, 1)
	signal.Notify(c, syscall.SIGHUP, syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT)
	for {
		s := <-c
		log.Info("get a signal %s", s.String())
		switch s {
		case syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT:
			gsvr.Shutdown(context.Background())
			svc.Close()
			log.Info("lottery-service exit")
			time.Sleep(time.Second)
			return
		case syscall.SIGHUP:
		default:
			return
		}
	}
}

{'repo_name': 'whjstc/openbilibili-go-common-1', 'stars': '173', 'repo_language': 'Go', 'file_name': 'achievement_test.go', 'mime_type': 'text/plain', 'hash': -3526037828856202451, 'source_dataset': 'data'}


; RUN: llc < %s -mtriple=powerpc-apple-darwin10.0
; rdar://7819990

%0 = type { i32 }
%1 = type { i64 }
%struct.Buffer = type { [1024 x i8], i64, i64, i64 }
%struct.InStream = type { %struct.Buffer, %0, %1, i32*, %struct.InStreamMethods* }
%struct.InStreamMethods = type { void (%struct.InStream*, i8*, i32)*, void (%struct.InStream*, i64)*, i64 (%struct.InStream*)*, void (%struct.InStream*)* }

define i64 @t(%struct.InStream* %is) nounwind optsize ssp {
entry:
  br i1 undef, label %is_read_byte.exit, label %bb.i

bb.i:                                             ; preds = %entry
  br label %is_read_byte.exit

is_read_byte.exit:                                ; preds = %bb.i, %entry
  br i1 undef, label %is_read_byte.exit22, label %bb.i21

bb.i21:                                           ; preds = %is_read_byte.exit
  unreachable

is_read_byte.exit22:                              ; preds = %is_read_byte.exit
  br i1 undef, label %is_read_byte.exit19, label %bb.i18

bb.i18:                                           ; preds = %is_read_byte.exit22
  br label %is_read_byte.exit19

is_read_byte.exit19:                              ; preds = %bb.i18, %is_read_byte.exit22
  br i1 undef, label %is_read_byte.exit16, label %bb.i15

bb.i15:                                           ; preds = %is_read_byte.exit19
  unreachable

is_read_byte.exit16:                              ; preds = %is_read_byte.exit19
  %0 = shl i64 undef, 32                          ; <i64> [#uses=1]
  br i1 undef, label %is_read_byte.exit13, label %bb.i12

bb.i12:                                           ; preds = %is_read_byte.exit16
  unreachable

is_read_byte.exit13:                              ; preds = %is_read_byte.exit16
  %1 = shl i64 undef, 24                          ; <i64> [#uses=1]
  br i1 undef, label %is_read_byte.exit10, label %bb.i9

bb.i9:                                            ; preds = %is_read_byte.exit13
  unreachable

is_read_byte.exit10:                              ; preds = %is_read_byte.exit13
  %2 = shl i64 undef, 16                          ; <i64> [#uses=1]
  br i1 undef, label %is_read_byte.exit7, label %bb.i6

bb.i6:                                            ; preds = %is_read_byte.exit10
  br label %is_read_byte.exit7

is_read_byte.exit7:                               ; preds = %bb.i6, %is_read_byte.exit10
  %3 = shl i64 undef, 8                           ; <i64> [#uses=1]
  br i1 undef, label %is_read_byte.exit4, label %bb.i3

bb.i3:                                            ; preds = %is_read_byte.exit7
  unreachable

is_read_byte.exit4:                               ; preds = %is_read_byte.exit7
  %4 = or i64 0, %0                               ; <i64> [#uses=1]
  %5 = or i64 %4, %1                              ; <i64> [#uses=1]
  %6 = or i64 %5, %2                              ; <i64> [#uses=1]
  %7 = or i64 %6, %3                              ; <i64> [#uses=1]
  %8 = or i64 %7, 0                               ; <i64> [#uses=1]
  ret i64 %8
}

{'repo_name': 'llvm-dcpu16/llvm-dcpu16', 'stars': '207', 'repo_language': 'C++', 'file_name': 'executionengine_ocaml.c', 'mime_type': 'text/x-c', 'hash': -921817308227523192, 'source_dataset': 'data'}


//
// detail/reactive_socket_accept_op.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//

#ifndef ASIO_DETAIL_REACTIVE_SOCKET_ACCEPT_OP_HPP
#define ASIO_DETAIL_REACTIVE_SOCKET_ACCEPT_OP_HPP

#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)

#include "asio/detail/config.hpp"
#include "asio/detail/bind_handler.hpp"
#include "asio/detail/fenced_block.hpp"
#include "asio/detail/handler_alloc_helpers.hpp"
#include "asio/detail/handler_invoke_helpers.hpp"
#include "asio/detail/handler_work.hpp"
#include "asio/detail/memory.hpp"
#include "asio/detail/reactor_op.hpp"
#include "asio/detail/socket_holder.hpp"
#include "asio/detail/socket_ops.hpp"

#include "asio/detail/push_options.hpp"

namespace asio {
namespace detail {

template <typename Socket, typename Protocol>
class reactive_socket_accept_op_base : public reactor_op
{
public:
  reactive_socket_accept_op_base(const asio::error_code& success_ec,
      socket_type socket, socket_ops::state_type state, Socket& peer,
      const Protocol& protocol, typename Protocol::endpoint* peer_endpoint,
      func_type complete_func)
    : reactor_op(success_ec,
        &reactive_socket_accept_op_base::do_perform, complete_func),
      socket_(socket),
      state_(state),
      peer_(peer),
      protocol_(protocol),
      peer_endpoint_(peer_endpoint),
      addrlen_(peer_endpoint ? peer_endpoint->capacity() : 0)
  {
  }

  static status do_perform(reactor_op* base)
  {
    reactive_socket_accept_op_base* o(
        static_cast<reactive_socket_accept_op_base*>(base));

    socket_type new_socket = invalid_socket;
    status result = socket_ops::non_blocking_accept(o->socket_,
        o->state_, o->peer_endpoint_ ? o->peer_endpoint_->data() : 0,
        o->peer_endpoint_ ? &o->addrlen_ : 0, o->ec_, new_socket)
    ? done : not_done;
    o->new_socket_.reset(new_socket);

    ASIO_HANDLER_REACTOR_OPERATION((*o, "non_blocking_accept", o->ec_));

    return result;
  }

  void do_assign()
  {
    if (new_socket_.get() != invalid_socket)
    {
      if (peer_endpoint_)
        peer_endpoint_->resize(addrlen_);
      peer_.assign(protocol_, new_socket_.get(), ec_);
      if (!ec_)
        new_socket_.release();
    }
  }

private:
  socket_type socket_;
  socket_ops::state_type state_;
  socket_holder new_socket_;
  Socket& peer_;
  Protocol protocol_;
  typename Protocol::endpoint* peer_endpoint_;
  std::size_t addrlen_;
};

template <typename Socket, typename Protocol,
    typename Handler, typename IoExecutor>
class reactive_socket_accept_op :
  public reactive_socket_accept_op_base<Socket, Protocol>
{
public:
  ASIO_DEFINE_HANDLER_PTR(reactive_socket_accept_op);

  reactive_socket_accept_op(const asio::error_code& success_ec,
      socket_type socket, socket_ops::state_type state, Socket& peer,
      const Protocol& protocol, typename Protocol::endpoint* peer_endpoint,
      Handler& handler, const IoExecutor& io_ex)
    : reactive_socket_accept_op_base<Socket, Protocol>(
        success_ec, socket, state, peer, protocol, peer_endpoint,
        &reactive_socket_accept_op::do_complete),
      handler_(ASIO_MOVE_CAST(Handler)(handler)),
      work_(handler_, io_ex)
  {
  }

  static void do_complete(void* owner, operation* base,
      const asio::error_code& /*ec*/,
      std::size_t /*bytes_transferred*/)
  {
    // Take ownership of the handler object.
    reactive_socket_accept_op* o(static_cast<reactive_socket_accept_op*>(base));
    ptr p = { asio::detail::addressof(o->handler_), o, o };

    // On success, assign new connection to peer socket object.
    if (owner)
      o->do_assign();

    ASIO_HANDLER_COMPLETION((*o));

    // Take ownership of the operation's outstanding work.
    handler_work<Handler, IoExecutor> w(
        ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)(
          o->work_));

    // Make a copy of the handler so that the memory can be deallocated before
    // the upcall is made. Even if we're not about to make an upcall, a
    // sub-object of the handler may be the true owner of the memory associated
    // with the handler. Consequently, a local copy of the handler is required
    // to ensure that any owning sub-object remains valid until after we have
    // deallocated the memory here.
    detail::binder1<Handler, asio::error_code>
      handler(o->handler_, o->ec_);
    p.h = asio::detail::addressof(handler.handler_);
    p.reset();

    // Make the upcall if required.
    if (owner)
    {
      fenced_block b(fenced_block::half);
      ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_));
      w.complete(handler, handler.handler_);
      ASIO_HANDLER_INVOCATION_END;
    }
  }

private:
  Handler handler_;
  handler_work<Handler, IoExecutor> work_;
};

#if defined(ASIO_HAS_MOVE)

template <typename Protocol, typename PeerIoExecutor,
    typename Handler, typename IoExecutor>
class reactive_socket_move_accept_op :
  private Protocol::socket::template rebind_executor<PeerIoExecutor>::other,
  public reactive_socket_accept_op_base<
    typename Protocol::socket::template rebind_executor<PeerIoExecutor>::other,
    Protocol>
{
public:
  ASIO_DEFINE_HANDLER_PTR(reactive_socket_move_accept_op);

  reactive_socket_move_accept_op(const asio::error_code& success_ec,
      const PeerIoExecutor& peer_io_ex, socket_type socket,
      socket_ops::state_type state, const Protocol& protocol,
      typename Protocol::endpoint* peer_endpoint, Handler& handler,
      const IoExecutor& io_ex)
    : peer_socket_type(peer_io_ex),
      reactive_socket_accept_op_base<peer_socket_type, Protocol>(
        success_ec, socket, state, *this, protocol, peer_endpoint,
        &reactive_socket_move_accept_op::do_complete),
      handler_(ASIO_MOVE_CAST(Handler)(handler)),
      work_(handler_, io_ex)
  {
  }

  static void do_complete(void* owner, operation* base,
      const asio::error_code& /*ec*/,
      std::size_t /*bytes_transferred*/)
  {
    // Take ownership of the handler object.
    reactive_socket_move_accept_op* o(
        static_cast<reactive_socket_move_accept_op*>(base));
    ptr p = { asio::detail::addressof(o->handler_), o, o };

    // On success, assign new connection to peer socket object.
    if (owner)
      o->do_assign();

    ASIO_HANDLER_COMPLETION((*o));

    // Take ownership of the operation's outstanding work.
    handler_work<Handler, IoExecutor> w(
        ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)(
          o->work_));

    // Make a copy of the handler so that the memory can be deallocated before
    // the upcall is made. Even if we're not about to make an upcall, a
    // sub-object of the handler may be the true owner of the memory associated
    // with the handler. Consequently, a local copy of the handler is required
    // to ensure that any owning sub-object remains valid until after we have
    // deallocated the memory here.
    detail::move_binder2<Handler,
      asio::error_code, peer_socket_type>
        handler(0, ASIO_MOVE_CAST(Handler)(o->handler_), o->ec_,
          ASIO_MOVE_CAST(peer_socket_type)(*o));
    p.h = asio::detail::addressof(handler.handler_);
    p.reset();

    // Make the upcall if required.
    if (owner)
    {
      fenced_block b(fenced_block::half);
      ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, "..."));
      w.complete(handler, handler.handler_);
      ASIO_HANDLER_INVOCATION_END;
    }
  }

private:
  typedef typename Protocol::socket::template
    rebind_executor<PeerIoExecutor>::other peer_socket_type;

  Handler handler_;
  handler_work<Handler, IoExecutor> work_;
};

#endif // defined(ASIO_HAS_MOVE)

} // namespace detail
} // namespace asio

#include "asio/detail/pop_options.hpp"

#endif // ASIO_DETAIL_REACTIVE_SOCKET_ACCEPT_OP_HPP

{'repo_name': 'pqrs-org/Karabiner-Elements', 'stars': '11032', 'repo_language': 'C++', 'file_name': 'settings.json', 'mime_type': 'text/plain', 'hash': 3952158780210485180, 'source_dataset': 'data'}


{'repo_name': 'tomakehurst/wiremock', 'stars': '3947', 'repo_language': 'Java', 'file_name': 'index.html', 'mime_type': 'text/html', 'hash': 4813154987416521444, 'source_dataset': 'data'}


<?xml version="1.0" ?>

<building name="Soapmakers Worshop" game_type="Workshop" game_subtype="Custom" game_custom="SOAP_MAKER" file="workshop.png">

	<!-- benches wall -->
	<if>
		<!-- replace this with position index if required -->
		<BuildingOccupancy value="3" />
		<!-- benches -->
		<include file="wsFPTub.xml"/>
	</if>
	<else>
		<HaveFloor/>
		<include file="wsUpperBorder.xml"/>
	</else>
	<!-- end benches wall -->

	<!-- contents -->

	<if>
		<and>
			<not><BuildingOccupancy value="1" /></not>
			<PositionIndex value=7 />
		</and>
		<if>
			<HaveFloor/>
			<rotate>
				<sprite index=164 />
				<sprite index=165 />
				<sprite index=164 />
				<sprite index=165 />
			</rotate>
		</if>
		<else>
			<rotate>
				<sprite index=177 />
				<sprite index=178 />
				<sprite index=177 />
				<sprite index=178 />
			</rotate>
			<rotate>
				<sprite index=164 offsetx=2 />
				<sprite index=165 offsetx=2 />
				<sprite index=164 offsetx=2 />
				<sprite index=165 offsetx=2 />
			</rotate>
		</else>
	</if>

	<else>
		<and>
			<HaveFloor />
			<PositionIndex value=0 />
		</and>
		<sprite index = 222 color="building" pattern_index="1" />
		<sprite index = 223 />
	</else>

	<if>
		<BuildingOccupancy value="3" />
		<if>
			<PositionIndex value=2 />
			<sprite index=155/>
		</if>
		<if>
			<PositionIndex value=5 />
			<sprite index=155/>
		</if>
	</if>
	<else>
		<not><HaveFloor/></not>
		<empty/>
	</else>

	<include file="ws3x3Blueprint.xml"/>
	<include file="wsLowerBorder.xml"/>

</building>

{'repo_name': 'DFHack/stonesense', 'stars': '308', 'repo_language': 'C++', 'file_name': 'readme.txt', 'mime_type': 'text/plain', 'hash': -270869598802489556, 'source_dataset': 'data'}