podchat-browser
Version:
Javascript SDK to use POD's Chat Service - Browser Only
640 lines (559 loc) • 21.9 kB
JavaScript
;
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.DeviceManager = DeviceManager;
var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
var _typeof2 = _interopRequireDefault(require("@babel/runtime/helpers/typeof"));
var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
require("../constants.js");
var _errorHandler = require("../errorHandler.js");
function MediaStreamManager() {
var deviceStreams = {
videoIn: null,
audioIn: null,
audioOut: null,
screenShare: null,
deviceChangeFlag: false
};
return {
setAudioInput: function setAudioInput(stream) {
deviceStreams.audioIn = stream;
},
setVideoInput: function setVideoInput(stream) {
deviceStreams.videoIn = stream;
},
setScreenShareInput: function setScreenShareInput(stream) {
deviceStreams.screenShare = stream;
},
getVideoInput: function getVideoInput() {
return deviceStreams.videoIn;
},
getAudioInput: function getAudioInput() {
return deviceStreams.audioIn;
},
getScreenShareInput: function getScreenShareInput() {
return deviceStreams.screenShare;
},
stopAudioInput: function stopAudioInput() {
return (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee() {
return _regenerator["default"].wrap(function _callee$(_context) {
while (1) {
switch (_context.prev = _context.next) {
case 0:
if (deviceStreams.audioIn) {
_context.next = 2;
break;
}
return _context.abrupt("return");
case 2:
deviceStreams.audioIn.getTracks().forEach(function (track) {
if (!!track) {
track.stop();
}
deviceStreams.audioIn = null;
});
case 3:
case "end":
return _context.stop();
}
}
}, _callee);
}))();
},
stopVideoInput: function stopVideoInput() {
return (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee2() {
return _regenerator["default"].wrap(function _callee2$(_context2) {
while (1) {
switch (_context2.prev = _context2.next) {
case 0:
if (deviceStreams.videoIn) {
_context2.next = 2;
break;
}
return _context2.abrupt("return");
case 2:
deviceStreams.videoIn.getTracks().forEach(function (track) {
track.stop();
deviceStreams.videoIn = null;
});
case 3:
case "end":
return _context2.stop();
}
}
}, _callee2);
}))();
},
stopScreenShareInput: function stopScreenShareInput() {
return (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee3() {
return _regenerator["default"].wrap(function _callee3$(_context3) {
while (1) {
switch (_context3.prev = _context3.next) {
case 0:
if (deviceStreams.screenShare) {
_context3.next = 2;
break;
}
return _context3.abrupt("return");
case 2:
deviceStreams.screenShare.getTracks().forEach(function (track) {
track.stop();
});
deviceStreams.screenShare = null;
case 4:
case "end":
return _context3.stop();
}
}
}, _callee3);
}))();
}
};
}
function DeviceManager(app) {
var config = {
mediaStreams: new MediaStreamManager(),
streamsMetada: {
audioInWatcherId: null
},
permissionRequests: [],
isProcessingPermissionRequests: false
};
var deviceManager = {
getInputDevicePermission: function getInputDevicePermission(_ref) {
var _ref$audio = _ref.audio,
audio = _ref$audio === void 0 ? false : _ref$audio,
_ref$video = _ref.video,
video = _ref$video === void 0 ? false : _ref$video;
return new Promise(function (resolve, reject) {
if (video && config.mediaStreams.getVideoInput()) {
resolve(config.mediaStreams.getVideoInput());
return;
}
if (audio && config.mediaStreams.getAudioInput()) {
resolve(config.mediaStreams.getAudioInput());
return;
}
navigator.mediaDevices.getUserMedia({
audio: audio,
video: video
}).then(function (stream) {
if (audio) config.mediaStreams.setAudioInput(stream);
if (video) config.mediaStreams.setVideoInput(stream);
resolve(stream);
})["catch"](function (error) {
app.chatEvents.fireEvent('callEvents', {
type: 'CALL_ERROR',
code: audio ? 12401 : 12400,
message: error // environmentDetails: getSDKCallDetails()
});
reject(app.errorHandler.handleError(audio ? 12401 : 12400));
});
});
},
canChooseAudioOutputDevice: function canChooseAudioOutputDevice() {
return !!navigator.mediaDevices.selectAudioOutput;
},
changeAudioOutputDevice: function changeAudioOutputDevice() {
if (!navigator.mediaDevices.selectAudioOutput) {
console.warn("selectAudioOutput() not supported.");
return;
} //Display prompt and log selected device or error
navigator.mediaDevices.selectAudioOutput().then(function (device) {
console.log(device.kind + ": " + device.label + " id = " + device.deviceId);
})["catch"](function (err) {
console.log(err.name + ": " + err.message);
});
},
replaceVideoStream: function replaceVideoStream(newStream, callback) {
var call = app.call.currentCall();
if (call) {
var user = app.call.currentCall().users().get(app.store.user.get().id);
user.replaceVideoStream(newStream, callback);
return;
} else {
config.mediaStreams.setVideoInput(newStream);
}
},
changeMediaDevice: function changeMediaDevice(params, callback) {
var user = app.call.currentCall().users().get(app.store.user.get().id);
var config = {
deviceId: {
exact: params.deviceId
}
};
if (params.deviceType === 'audioIn') {
user.changeAudioStream(params.deviceId, callback);
} else if (params.deviceType === 'audioOut') {
app.call.currentCall().users().switchSpeakers(params.deviceId, callback);
} else if (params.deviceType === 'videoIn') {
config = Object.assign(config, {
width: 320,
framerate: 10
});
user.changeVideoStream(params.deviceId, callback);
} // callback && callback({hasError: false, deviceId: params.deviceId});
},
getMediaDevices: function getMediaDevices(callback) {
var _navigator$mediaDevic;
if (!((_navigator$mediaDevic = navigator.mediaDevices) !== null && _navigator$mediaDevic !== void 0 && _navigator$mediaDevic.enumerateDevices)) {
callback && callback({
hasError: true
});
} else {
navigator.mediaDevices.getUserMedia({
audio: true
}).then(function (stream) {
navigator.mediaDevices.enumerateDevices().then(function (devices) {
var my_devices = {
audioinput: [],
videoinput: [],
audiooutput: []
};
devices.forEach(function (device) {
var _my_devices$kind;
var kind = device.kind,
label = device.label,
deviceId = device.deviceId,
groupId = device.groupId;
var active;
if (kind == 'videoinput') {
active = deviceId == app.preferredMediaDevices.get('videoIn');
} else if (kind == 'audioinput') {
active = deviceId == app.preferredMediaDevices.get('audioIn');
} else if (kind == 'audiooutput') {
active = deviceId == app.preferredMediaDevices.get('audioOut');
}
(_my_devices$kind = my_devices[kind]) === null || _my_devices$kind === void 0 ? void 0 : _my_devices$kind.push({
label: label,
deviceId: deviceId,
groupId: groupId,
active: active
});
}); // check browser is safari
if (/^((?!chrome|android).)*safari/i.test(navigator.userAgent)) {
var _my_devices$audiooutp;
(_my_devices$audiooutp = my_devices['audiooutput']) === null || _my_devices$audiooutp === void 0 ? void 0 : _my_devices$audiooutp.push({
label: 'اسپیکر پیش فرض سیستم',
deviceId: '',
groupId: '',
active: true
});
}
stream.getTracks().forEach(function (item) {
return item.stop();
}); // deviceManager.mediaStreams.stopAudioInput();
callback && callback({
hasError: false,
devices: my_devices
});
})["catch"](function (err) {
callback && callback({
hasError: false,
message: err.message,
devices: []
}); // reject(err)
console.error("".concat(err.name, ": ").concat(err.message));
});
})["catch"](function (err) {
callback && callback({
hasError: false,
message: err.message,
devices: []
}); // reject(err)
console.error("".concat(err.name, ": ").concat(err.message));
});
if (!navigator.mediaDevices.ondevicechange) {
navigator.mediaDevices.ondevicechange = deviceManager.handleDeviceChange;
}
}
},
removeDuplicateGroupIds: function removeDuplicateGroupIds(input) {
var repeated_group_id = '';
var hasDefault = {
audioinput: false,
videoinput: false,
audiooutput: false
};
var result = {};
var uniqueGroupIds = {};
var _loop = function _loop(key) {
uniqueGroupIds[key] = new Set();
if (input.hasOwnProperty(key)) {
result[key] = (0, _toConsumableArray2["default"])(input[key]).reverse().filter(function (item) {
if (uniqueGroupIds[key].has(item.groupId)) {
repeated_group_id = item.groupId;
return false;
} else {
uniqueGroupIds[key].add(item.groupId);
return true;
}
}); // change default value of object if groupId repeated
var index = result[key].findIndex(function (data) {
return data.groupId === repeated_group_id;
});
if (index > -1) {
hasDefault[key] = true;
result[key][index]['default'] = true;
}
} // if no repeated groupId
if (!hasDefault[key]) {
result[key][result[key].length - 1]['default'] = true;
}
};
for (var key in input) {
_loop(key);
}
return result;
},
handleDeviceChange: function handleDeviceChange(event) {
if (!deviceManager.deviceChangeFlag) {
deviceManager.deviceChangeFlag = true;
deviceManager.getMediaDevices(function (_ref2) {
var hasError = _ref2.hasError,
devices = _ref2.devices;
app.chatEvents.fireEvent('callEvents', {
type: 'USER_MEDIA_DEVICES_CHANGED',
result: devices
});
});
setTimeout(function () {
deviceManager.deviceChangeFlag = false;
}, 1000);
}
},
grantScreenSharePermission: function grantScreenSharePermission(_ref3) {
var _ref3$closeStream = _ref3.closeStream,
closeStream = _ref3$closeStream === void 0 ? false : _ref3$closeStream;
var callback = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
return new Promise(function (resolve, reject) {
if (config.mediaStreams.getScreenShareInput()) {
if (!config.mediaStreams.getScreenShareInput().active) {
config.mediaStreams.stopScreenShareInput(); // resolve(config.mediaStreams.getScreenShareInput());
} else {
// console.log("exists resolving")
resolve(config.mediaStreams.getScreenShareInput());
return;
}
}
navigator.mediaDevices.getDisplayMedia({
audio: false,
video: true
}).then(function (stream) {
config.mediaStreams.setScreenShareInput(stream);
if (closeStream) {
config.mediaStreams.stopScreenShareInput();
}
callback && callback({
hasError: false
});
resolve(stream);
})["catch"](function (e) {
var error = app.errorHandler.raiseError(_errorHandler.errorList.SCREENSHARE_PERMISSION_ERROR, callback, true, {
eventName: 'callEvents',
eventType: 'CALL_ERROR'
});
reject(error);
});
});
},
executePermissionRequest: function executePermissionRequest(_ref4) {
var video = _ref4.video,
audio = _ref4.audio,
closeStream = _ref4.closeStream,
callback = _ref4.callback;
config.isProcessingPermissionRequests = true;
return new Promise( /*#__PURE__*/function () {
var _ref5 = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee4(resolve, reject) {
var res, parsedError;
return _regenerator["default"].wrap(function _callee4$(_context4) {
while (1) {
switch (_context4.prev = _context4.next) {
case 0:
_context4.prev = 0;
if (!audio) {
_context4.next = 4;
break;
}
_context4.next = 4;
return deviceManager.getInputDevicePermission({
audio: audio
});
case 4:
if (!video) {
_context4.next = 7;
break;
}
_context4.next = 7;
return deviceManager.getInputDevicePermission({
video: video
});
case 7:
if (closeStream) {
if (audio) config.mediaStreams.stopAudioInput();
if (video) config.mediaStreams.stopVideoInput();
}
if (callback) {
res = {
hasError: false
};
if (video) {
res.videoStream = config.mediaStreams.getVideoInput();
}
if (audio) {
res.audioStream = config.mediaStreams.getAudioInput();
}
callback(res);
}
resolve({
hasError: false
});
_context4.next = 17;
break;
case 12:
_context4.prev = 12;
_context4.t0 = _context4["catch"](0);
parsedError = {
hasError: true,
errorCode: _context4.t0.code,
errorMessage: _context4.t0.message
};
if (callback) callback(parsedError);
reject(parsedError);
case 17:
config.isProcessingPermissionRequests = false;
return _context4.abrupt("return", deviceManager.maybeGoToNext());
case 19:
case "end":
return _context4.stop();
}
}
}, _callee4, null, [[0, 12]]);
}));
return function (_x, _x2) {
return _ref5.apply(this, arguments);
};
}());
},
maybeGoToNext: function maybeGoToNext() {
if (!config.isProcessingPermissionRequests && config.permissionRequests.length) {
deviceManager.executePermissionRequest(config.permissionRequests.shift());
}
},
grantUserMediaDevicesPermissions: function grantUserMediaDevicesPermissions(_ref6) {
var _ref6$video = _ref6.video,
video = _ref6$video === void 0 ? false : _ref6$video,
_ref6$audio = _ref6.audio,
audio = _ref6$audio === void 0 ? false : _ref6$audio,
_ref6$closeStream = _ref6.closeStream,
closeStream = _ref6$closeStream === void 0 ? false : _ref6$closeStream;
var callback = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
if (app.preferredMediaDevices.get('videoIn')) {
if (video) {
if ((0, _typeof2["default"])(video) == 'object') {
if (!video.deviceId) video.deviceId = {
exact: app.preferredMediaDevices.get('videoIn')
};
} else {
video = {
deviceId: {
exact: app.preferredMediaDevices.get('videoIn')
}
};
}
}
}
if (app.preferredMediaDevices.get('audioIn')) {
if (audio) {
if ((0, _typeof2["default"])(audio) == 'object') {
if (!audio.deviceId) audio.deviceId = {
exact: app.preferredMediaDevices.get('audioIn')
};
} else {
audio = {
deviceId: {
exact: app.preferredMediaDevices.get('audioIn')
}
};
}
}
}
config.permissionRequests.push({
video: video,
audio: audio,
closeStream: closeStream,
callback: callback
});
deviceManager.maybeGoToNext();
},
mediaStreams: config.mediaStreams,
watchAudioInputStream: function watchAudioInputStream(callErrorHandler) {
config.streamsMetada.audioInWatcherId && clearInterval(config.streamsMetada.audioInWatcherId);
config.streamsMetada.audioInWatcherId = setInterval(function () {
var _config$mediaStreams$;
if (!config.mediaStreams.getAudioInput()) {
clearInterval(config.streamsMetada.audioInWatcherId);
return;
}
var audioTracks = (_config$mediaStreams$ = config.mediaStreams.getAudioInput()) === null || _config$mediaStreams$ === void 0 ? void 0 : _config$mediaStreams$.getAudioTracks();
if (audioTracks.length === 0) {
callErrorHandler(_errorHandler.errorList.NO_AUDIO_TRACKS_AVAILABLE, null, true, {});
clearInterval(config.streamsMetada.audioInWatcherId); // No audio from microphone has been captured
return;
} // We asked for the microphone so one track
var track = audioTracks[0];
if (track.muted) {
// Track is muted which means that the track is unable to provide media data.
// When muted, a track can't be unmuted.
// This track will no more provide data...
callErrorHandler(_errorHandler.errorList.AUDIO_TRACK_MUTED, null, true, {});
clearInterval(config.streamsMetada.audioInWatcherId);
}
if (!track.enabled) {
// Track is disabled (muted for telephonist) which means that the track provides silence instead of real data.
// When disabled, a track can be enabled again.
// When in that case, user can't be heard until track is enabled again.
callErrorHandler(_errorHandler.errorList.AUDIO_TRACK_DISABLED, null, true, {});
}
if (track.readyState === "ended") {
// Possibly a disconnection of the device
// When ended, a track can't be active again
// This track will no more provide data
callErrorHandler(_errorHandler.errorList.AUDIO_TRACK_ENDED, null, true, {});
clearInterval(config.streamsMetada.audioInWatcherId);
}
}, 10000);
},
onCallEnd: function onCallEnd() {
return (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee5() {
return _regenerator["default"].wrap(function _callee5$(_context5) {
while (1) {
switch (_context5.prev = _context5.next) {
case 0:
config.permissionRequests = [];
config.isProcessingPermissionRequests = false;
_context5.next = 4;
return config.mediaStreams.stopAudioInput();
case 4:
_context5.next = 6;
return config.mediaStreams.stopVideoInput();
case 6:
_context5.next = 8;
return config.mediaStreams.stopScreenShareInput();
case 8:
navigator.mediaDevices.ondevicechange = null;
case 9:
case "end":
return _context5.stop();
}
}
}, _callee5);
}))();
}
};
return deviceManager;
}
;