Source: lib/videoMail.js

var Janus = require('../externals/janus.nojquery');
var Promise = require('bluebird/js/release/bluebird');


/**
 * VideoMail usecase
 * @class
 * @classdesc VideoMail usecase
 * @param  {object} onEvents       Event handlers: onRecording, onStopped
 * @param  {object} domElements    DOM elements: videomail
 * @param  {object} options        Available options: stream
 * @return {Promise}               VideoMail methods: startRecording, stopRecording, toggleAudio, toggleVideo
 * @example
 * var onEvents = {
 *     onRecording: function() {
 *          // Recording
 *     },
 *     onStopped: function() {
 *          // Stopped
 *     }
 * };
 *
 * var domElements = {
 *     videomail: document.getElementById('videomail')
 * };
 *
 * var options = {
 *     stream: {
 *         audioEnabled: true,
 *         videoEnabled: true,
 *         aDeviceId: null,
 *         vDeviceId: null
 *     }
 * };
 *
 * usecases.videoMail(onEvents, domElements, options)
 *     .then(function(action) {
 *          // Use Case has been atacched succesfully
 *          ...
 *     })
 *     .catch(function(cause) {
 *         // Error attaching the Use Case
 *         console.log("Error Attach " + cause );
 *     })
 */
var videoMail = function(onEvents, domElements, options) {

    var videomailHandle = null;
    var recordingId = null;
    var bandwidth = 1024 * 1024;

    // Stream options
    var streamOptions = (options && options.stream) ? options.stream : {};
    if(!streamOptions.audioEnabled) streamOptions.audioEnabled = false;
    if(!streamOptions.videoEnabled) streamOptions.videoEnabled = false;
    if(!streamOptions.aDeviceId) streamOptions.aDeviceId = undefined;
    if(!streamOptions.vDeviceId) streamOptions.vDeviceId = undefined;

    /**
     * Close the current UseCase. It's recommended combine with disconnect method
     * @return {nothing}
     * @example
     * action.closeUsecase();
     * myVideoApp.disconnect(); // Recommended
     */
    var closeUsecase = function() {
        if(domElements) {
            for (var element in domElements) {
                if (!domElements.hasOwnProperty(element)) continue;
                var obj = domElements[element];
                if(obj && obj.innerHTML) obj.innerHTML = '';
            }
        }
    };

    /**
     * The User sends a request to start recording a Video message
     * @param  {string} recordPrefix  Prefix record
     * @param  {string} name          File name
     * @return {nothing}
     * @example
     * action.startRecording('__default__', 'MyRecordMobile');
     */
    var startRecording = function(recordPrefix, name) {
        var fullname = recordPrefix + "VideoMail-" + name + "-" + Date.now();
        // bitrate and keyframe interval can be set at any time:
        // before, after, during recording
        videomailHandle.send({
            'message': {
                'request': 'configure',
                'video-bitrate-max': bandwidth, // a quarter megabit
                'video-keyframe-interval': 15000 // 15 seconds
            }
        });
        videomailHandle.createOffer(
            {
                media: { // Publishers are sendonly
                    audioRecv: false,
                    audioSend: streamOptions.audioEnabled || false,
                    videoRecv: false,
                    videoSend: streamOptions.videoEnabled || false,
                    data: false,
                    audio: {
    					deviceId: {
    						exact: streamOptions.aDeviceId
    					}
    				},
    				video: {
    					deviceId: {
    						exact: streamOptions.vDeviceId
    					}
    				}
                },
                // By default, it's sendrecv for audio and video...
                success: function(jsep) {
                    Janus.debug("Got SDP!");
                    Janus.debug(jsep);
                    var body = { "request": "record", "name": fullname };
                    videomailHandle.send({"message": body, "jsep": jsep});
                },
                error: function(error) {
                    Janus.error("WebRTC error...", error);
                    videomailHandle.hangup();
                }
        });
    };

    /**
     * The User sends a request to stop recording the current Video message
     * @return {nothing}
     * @example
     * action.stopRecording();
     */
    var stopRecording = function() {
        var request = { "request": "stop" };
    	videomailHandle.send({"message": request});
    	videomailHandle.hangup();
    };

    /**
     * Toggle Audio stream (Mute/Unmute)
     * @return {boolean} Is audio muted?
     * @example
     * action.toggleAudio(); // true or false
     */
    var toggleAudio = function() {
        if (videomailHandle.isAudioMuted()) videomailHandle.unmuteAudio();
        else videomailHandle.muteAudio();
        return videomailHandle.isAudioMuted();
    };

    /**
     * Toggle Video stream (Mute/Unmute)
     * @return {boolean} Is video muted?
     * @example
     * action.toggleVideo(); // true or false
     */
    var toggleVideo = function() {
        if (videomailHandle.isVideoMuted()) videomailHandle.unmuteVideo();
        else videomailHandle.muteVideo();
        return videomailHandle.isVideoMuted();
    };

    return new Promise(function (resolve, reject) {
        window.VideoRTC.connection.handle.attach({
            plugin: "janus.plugin.recordplay",
            success: function(pluginHandle) {
                videomailHandle = pluginHandle;
                resolve({
                    closeUsecase: closeUsecase,
                    startRecording: startRecording,
                    stopRecording: stopRecording,
                    toggleAudio: toggleAudio,
                    toggleVideo: toggleVideo
                });
            },
            error: function(cause) {
                Janus.error("  -- Error attaching plugin...", cause);
                reject(cause);
            },
            consentDialog: function(on) {
                // Nothing
            },
            onmessage: function(msg, jsep) {
                var result = msg["result"];
                if(result !== null && result !== undefined) {
					if(result["status"] !== undefined && result["status"] !== null) {
						var event = result["status"];
						if(event === 'recording') {
							// Got an ANSWER to our recording OFFER
							if(jsep !== null && jsep !== undefined)
								videomailHandle.handleRemoteJsep({jsep: jsep});
							var id = result["id"];
							if(id !== null && id !== undefined) {
								Janus.log("The ID of the current recording is " + id);
								recordingId = id;
							}
                            if(onEvents && onEvents.onRecording) onEvents.onRecording();
						} else if(event === 'slow_link') {
							var uplink = result["uplink"];
							if(uplink !== 0) {
								// Janus detected issues when receiving our media, let's slow down
								bandwidth = parseInt(bandwidth / 1.5);
								videomailHandle.send({
									'message': {
										'request': 'configure',
										'video-bitrate-max': bandwidth, // Reduce the bitrate
										'video-keyframe-interval': 15000 // Keep the 15 seconds key frame interval
									}
								});
							}
						} else if(event === 'stopped') {
							Janus.log("Session has stopped!");
							var id = result["id"];
							if(recordingId !== null && recordingId !== undefined) {
								if(recordingId !== id) {
									Janus.warn("Not a stop to our recording?");
									return;
								}
							}
                            var container = domElements.videomail;
                            container.innerHTML = '';
							videomailHandle.hangup();
                            if(recordingId !== null && onEvents && onEvents.onStopped) onEvents.onStopped();
                            recordingId = null;
						}
					}
				}
            },
            onlocalstream: function(stream) {
                Janus.debug(" ::: Got a local stream :::");
                var container = domElements.videomail;
                container.innerHTML = '<video autoplay poster="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" id="vmail"></video>';
                var videoElem = document.getElementById('vmail');
                Janus.attachMediaStream(videoElem, stream);
                videoElem.muted = true;

                var videoTracks = stream.getVideoTracks();
                if(videoTracks === null || videoTracks === undefined || videoTracks.length === 0) {
                    // No remote video
                    var nodeNoCamera = document.createElement('div');
                    nodeNoCamera.innerHTML = 'No camera available';
                    nodeNoCamera.style.position = "relative";
                    nodeNoCamera.style.height = "100%";
                    nodeNoCamera.style.width = "100%";
                    nodeNoCamera.style.top = "100%";
                    nodeNoCamera.style.left = "50%";
                    nodeNoCamera.style.transform = "translate(-50%,-50%)";
                    nodeNoCamera.className = "no-camera-available";
                    container.insertBefore(nodeNoCamera, container.firstChild);
                }
            },
            onremotestream: function(stream) {
                // Nothing
            },
            oncleanup: function() {
                var container = domElements.videomail;
                container.innerHTML = '';
            },
            detached: function() {
                // Nothing
            }
        });
    });

};

exports.videoMail = videoMail;