<commit_before>var util = require('util');
var hark = require('hark');
var webrtcSupport = require('webrtcsupport');
var getUserMedia = require('getusermedia');
var getScreenMedia = require('getscreenmedia');
var WildEmitter = require('wildemitter');
var GainController = require('mediastream-gain');
var mockconsole = require('mockconsole');


function LocalMedia(opts) {
    WildEmitter.call(this);

    var config = this.config = {
        autoAdjustMic: false,
        detectSpeakingEvents: false,
        audioFallback: false,
        media: {
            audio: true,
            video: true
        },
        logger: mockconsole
    };

    var item;
    for (item in opts) {
        this.config[item] = opts[item];
    }

    this.logger = config.logger;
    this._log = this.logger.log.bind(this.logger, 'LocalMedia:');
    this._logerror = this.logger.error.bind(this.logger, 'LocalMedia:');

    this.screenSharingSupport = webrtcSupport.supportScreenSharing;

    this.localStreams = [];
    this.localScreens = [];

    if (!webrtcSupport.supportGetUserMedia) {
        this._logerror('Your browser does not support local media capture.');
    }
}

util.inherits(LocalMedia, WildEmitter);


LocalMedia.prototype.start = function (mediaConstraints, cb) {
    var self = this;
    var constraints = mediaConstraints || this.config.media;

    getUserMedia(constraints, function (err, stream) {

        if (!err) {
            if (constraints.audio && self.config.detectSpeakingEvents) {
                self.setupAudioMonitor(stream, self.config.harkOptions);
            }
            self.localStreams.push(stream);

            if (self.config.autoAdjustMic) {
                self.gainController = new GainController(stream);
                // start out somewhat muted if we can track audio
                self.setMicIfEnabled(0.5);
            }

            // TODO: might need to migrate to the video tracks onended
            // FIXME: firefox does not seem to trigger this...
            stream.onended = function () {
                /*
                var idx = self.localStreams.indexOf(stream);
                if (idx > -1) {
                    self.localScreens.splice(idx, 1);
                }
                self.emit('localStreamStopped', stream);
                */
            };

            self.emit('localStream', stream);
        } else {
            // Fallback for users without a camera
            if (self.config.audioFallback && err.name === 'DevicesNotFoundError' && constraints.video !== false) {
                constraints.video = false;
                self.start(constraints, cb);
                return;
            }
        }
        if (cb) {
            return cb(err, stream);
        }
    });
};

LocalMedia.prototype.stop = function (stream) {
    var self = this;
    // FIXME: duplicates cleanup code until fixed in FF
    if (stream) {
        stream.getTracks().forEach(function (track) { track.stop(); });
        var idx = self.localStreams.indexOf(stream);
        if (idx > -1) {
            self.emit('localStreamStopped', stream);
            self.localStreams = self.localStreams.splice(idx, 1);
        } else {
            idx = self.localScreens.indexOf(stream);
            if (idx > -1) {
                self.emit('localScreenStopped', stream);
                self.localScreens = self.localScreens.splice(idx, 1);
            }
        }
    } else {
        this.stopStreams();
        this.stopScreenShare();
    }
};

LocalMedia.prototype.stopStreams = function () {
    var self = this;
    if (this.audioMonitor) {
        this.audioMonitor.stop();
        delete this.audioMonitor;
    }
    this.localStreams.forEach(function (stream) {
        stream.getTracks().forEach(function (track) { track.stop(); });
        self.emit('localStreamStopped', stream);
    });
    this.localStreams = [];
};

LocalMedia.prototype.startScreenShare = function (cb) {
    var self = this;
    getScreenMedia(function (err, stream) {
        if (!err) {
            self.localScreens.push(stream);

            // TODO: might need to migrate to the video tracks onended
            // Firefox does not support .onended but it does not support
            // screensharing either
            stream.onended = function () {
                var idx = self.localScreens.indexOf(stream);
                if (idx > -1) {
                    self.localScreens.splice(idx, 1);
                }
                self.emit('localScreenStopped', stream);
            };
            self.emit('localScreen', stream);
        }

        // enable the callback
        if (cb) {
            return cb(err, stream);
        }
    });
};

LocalMedia.prototype.stopScreenShare = function (stream) {
    var self = this;
    if (stream) {
        stream.getTracks().forEach(function (track) { track.stop(); });
        this.emit('localScreenStopped', stream);
    } else {
        this.localScreens.forEach(function (stream) {
            stream.getTracks().forEach(function (track) { track.stop(); });
            self.emit('localScreenStopped', stream);
        });
        this.localScreens = [];<commit_msg>fix for LocalMedia.stop for specific stream (#8)<commit_after>var util = require('util');
var hark = require('hark');
var webrtcSupport = require('webrtcsupport');
var getUserMedia = require('getusermedia');
var getScreenMedia = require('getscreenmedia');
var WildEmitter = require('wildemitter');
var GainController = require('mediastream-gain');
var mockconsole = require('mockconsole');


function LocalMedia(opts) {
    WildEmitter.call(this);

    var config = this.config = {
        autoAdjustMic: false,
        detectSpeakingEvents: false,
        audioFallback: false,
        media: {
            audio: true,
            video: true
        },
        logger: mockconsole
    };

    var item;
    for (item in opts) {
        this.config[item] = opts[item];
    }

    this.logger = config.logger;
    this._log = this.logger.log.bind(this.logger, 'LocalMedia:');
    this._logerror = this.logger.error.bind(this.logger, 'LocalMedia:');

    this.screenSharingSupport = webrtcSupport.supportScreenSharing;

    this.localStreams = [];
    this.localScreens = [];

    if (!webrtcSupport.supportGetUserMedia) {
        this._logerror('Your browser does not support local media capture.');
    }
}

util.inherits(LocalMedia, WildEmitter);


LocalMedia.prototype.start = function (mediaConstraints, cb) {
    var self = this;
    var constraints = mediaConstraints || this.config.media;

    getUserMedia(constraints, function (err, stream) {

        if (!err) {
            if (constraints.audio && self.config.detectSpeakingEvents) {
                self.setupAudioMonitor(stream, self.config.harkOptions);
            }
            self.localStreams.push(stream);

            if (self.config.autoAdjustMic) {
                self.gainController = new GainController(stream);
                // start out somewhat muted if we can track audio
                self.setMicIfEnabled(0.5);
            }

            // TODO: might need to migrate to the video tracks onended
            // FIXME: firefox does not seem to trigger this...
            stream.onended = function () {
                /*
                var idx = self.localStreams.indexOf(stream);
                if (idx > -1) {
                    self.localScreens.splice(idx, 1);
                }
                self.emit('localStreamStopped', stream);
                */
            };

            self.emit('localStream', stream);
        } else {
            // Fallback for users without a camera
            if (self.config.audioFallback && err.name === 'DevicesNotFoundError' && constraints.video !== false) {
                constraints.video = false;
                self.start(constraints, cb);
                return;
            }
        }
        if (cb) {
            return cb(err, stream);
        }
    });
};

LocalMedia.prototype.stop = function (stream) {
    // FIXME: duplicates cleanup code until fixed in FF
    if (stream) {
        stream.getTracks().forEach(function (track) { track.stop(); });
        var idx = this.localStreams.indexOf(stream);
        if (idx > -1) {
            this.emit('localStreamStopped', stream);
            this.localStreams.splice(idx, 1);
        } else {
            idx = this.localScreens.indexOf(stream);
            if (idx > -1) {
                this.emit('localScreenStopped', stream);
                this.localScreens.splice(idx, 1);
            }
        }
    } else {
        this.stopStreams();
        this.stopScreenShare();
    }
};

LocalMedia.prototype.stopStreams = function () {
    var self = this;
    if (this.audioMonitor) {
        this.audioMonitor.stop();
        delete this.audioMonitor;
    }
    this.localStreams.forEach(function (stream) {
        stream.getTracks().forEach(function (track) { track.stop(); });
        self.emit('localStreamStopped', stream);
    });
    this.localStreams = [];
};

LocalMedia.prototype.startScreenShare = function (cb) {
    var self = this;
    getScreenMedia(function (err, stream) {
        if (!err) {
            self.localScreens.push(stream);

            // TODO: might need to migrate to the video tracks onended
            // Firefox does not support .onended but it does not support
            // screensharing either
            stream.onended = function () {
                var idx = self.localScreens.indexOf(stream);
                if (idx > -1) {
                    self.localScreens.splice(idx, 1);
                }
                self.emit('localScreenStopped', stream);
            };
            self.emit('localScreen', stream);
        }

        // enable the callback
        if (cb) {
            return cb(err, stream);
        }
    });
};

LocalMedia.prototype.stopScreenShare = function (stream) {
    var self = this;
    if (stream) {
        stream.getTracks().forEach(function (track) { track.stop(); });
        var idx = this.localScreens.indexOf(stream);
        if (idx > -1) {
            this.emit('localScreenStopped', stream);
            this.localScreens.splice(idx, 1);
        }
    } else {
        this.localScreens.forEach(function (stream) {
            stream.getTracks().forEach(function (track) { track.stop(); });
            self.emit('localScreenStopped', stream);
        });
        this.localScreens = [];
{'fraction_non_alphanumeric': 0.12194888484732459, 'fraction_numerical': 0.0022015889729108833, 'mean_word_length': 1.9639716312056739, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 12, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4563276', 'n_tokens_mistral': 2945, 'n_tokens_neox': 2830, 'n_words': 625}