]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
FS-11370 [verto_communicator] verto may rely on device labels to assure correct mic...
authorMarcell Guilherme Costa da Silva <marcell@evolux.net.br>
Mon, 31 Dec 2018 20:38:53 +0000 (17:38 -0300)
committerMarcell Guilherme Costa da Silva <marcell@evolux.net.br>
Fri, 4 Jan 2019 01:14:05 +0000 (22:14 -0300)
html5/verto/js/src/jquery.FSRTC.js
html5/verto/js/src/jquery.verto.js
html5/verto/js/src/vendor/media-device-id.min.js [new file with mode: 0644]

index 28cd9a454917d8e2e34cdeded34732275f89263e..3b0ef04290e660b51bd67bb2761333176e279685 100644 (file)
                     audio: false,
                     video: { deviceId: params.useCamera },
                },
-               localVideo: self.options.localVideo,
+        localVideo: self.options.localVideo,
+        useCameraLabel: self.options.useCameraLabel,
+        useMicLabel: self.options.useMicLabel,
                onsuccess: function(e) {self.options.localVideoStream = e; console.log("local video ready");},
-               onerror: function(e) {console.error("local video error!");}
+               onerror: function(e) {console.error("local video error!", e);}
             });
        }
 
           video: mediaParams.video
         },
         video: mediaParams.useVideo,
+        useCameraLabel: self.options.useCameraLabel,
+        useMicLabel: self.options.useMicLabel,
         onsuccess: onSuccess,
         onerror: onError
       });
 
            if (obj.options.useMic !== "any") {
                //audio.optional = [{sourceId: obj.options.useMic}];
-               audio.deviceId = {exact: obj.options.useMic};
+               audio.deviceId = assignMediaIdToConstraint(obj.options.useMic);
            }
        }
 
                     audio: false,
                     video: { deviceId: obj.options.useCamera },
                },
-               localVideo: obj.options.localVideo,
+        localVideo: obj.options.localVideo,
+        useCameraLabel: obj.options.useCameraLabel,
+        useMicLabel: obj.options.useMicLabel,
                onsuccess: function(e) {obj.options.localVideoStream = e; console.log("local video ready");},
-               onerror: function(e) {console.error("local video error!");}
+               onerror: function(e) {console.error("local video error!", e); }
             });
        }
 
                
                if (obj.options.useCamera !== "any") {
                    //video.optional.push({sourceId: obj.options.useCamera});
-        video.deviceId = {
-          exact: obj.options.useCamera,
-        };
+        video = assignMediaIdToConstraint(obj.options.useCamera, video);
                }
 
                if (bestFrameRate) {
       onSuccess(self.options.useStream);
     }
     else if (mediaParams.audio || mediaParams.video) {
-
             getUserMedia({
                constraints: {
                     audio: mediaParams.audio,
                },
                video: mediaParams.useVideo,
                onsuccess: onSuccess,
-               onerror: onError
+        onerror: onError,
+        useCameraLabel: self.options.useCameraLabel,
+        useMicLabel: self.options.useMicLabel,
             });
 
        } else {
     el.style.display = 'none';
   }
 
-    function getUserMedia(options) {
-        var n = navigator,
-        media;
-        n.getMedia = n.getUserMedia;
-        n.getMedia(options.constraints || {
-            audio: true,
-            video: video_constraints
-        },
-        streaming, options.onerror ||
-        function(e) {
-            console.error(e);
-        });
+    function assureConstraintByLabel(constraint, fallbackLabel) {
+        if (fallbackLabel === undefined && constraint === undefined) {
+            return Promise.resolve(constraint);
+        }
+
+        if (typeof(assureMediaInputId) !== 'function') {
+            console.warn('Tried to use constraint fallbacks but did not found vendor function `assureMediaInputId` on window scope. Did you forget to import `vendor/media-device-id.js` before Verto?');
+            return Promise.resolve(constraint);
+        }
+
+        if (typeof(constraint) === 'object' && !constraint.deviceId) {
+            return Promise.resolve(constraint);
+        }
+
+        if (constraint.deviceId) {
+            if (typeof(constraint.deviceId) === 'string') {
+                return new Promise(function(resolve) {
+                    assureMediaInputId(fallbackLabel, constraint.deviceId).then(function(id) {
+                        resolve(Object.assign({}, constraint, { deviceId: id }));
+                    }).catch(function() {
+                        resolve(constraint);
+                    });
+                });
+            }
+
+            if (typeof(constraint.deviceId) === 'object' && typeof(constraint.deviceId.exact) === 'string') {
+                return new Promise(function(resolve) {
+                    assureMediaInputId(fallbackLabel, constraint.deviceId.exact).then(function(id) {
+                        resolve(assignMediaIdToConstraint(id, constraint));
+                    }).catch(function() {
+                        resolve(constraint);
+                    });
+                });
+            }
+        }
+
+        return Promise.resolve(constraint);
+    }
 
-        function streaming(stream) {
+    function trustyGetUserMedia(options, constraints) {
+        navigator.mediaDevices.getUserMedia(constraints).then(function(stream) {
             if (options.localVideo) {
-        activateLocalVideo(options.localVideo, stream);
+                activateLocalVideo(options.localVideo, stream);
             }
 
             if (options.onsuccess) {
                 options.onsuccess(stream);
             }
+        }).catch(options.onerror || function(e) {
+            console.error(e);
+        });
+    }
 
-            media = stream;
-        }
+    function assignMediaIdToConstraint(mediaId, rest) {
+        return Object.assign({}, rest || {}, { deviceId: { exact: mediaId } });
+    }
 
-        return media;
+    function getUserMedia(options) {
+        var constraints = options.constraints || {
+            audio: true,
+            video: video_constraints,
+        };
+
+        Promise.all([
+            assureConstraintByLabel(constraints.audio, options.useMicLabel),
+            assureConstraintByLabel(constraints.video, options.useCameraLabel),
+        ]).then(function(assurances) {
+            trustyGetUserMedia(options, { audio: assurances[0], video: assurances[1] });
+        }).catch(function(error) {
+            console.error('Unexpected error on media id assurance attempts:', error, 'Options:', options);
+        });
     }
 
     $.FSRTC.resSupported = function(w, h) {
        };
 
   if (cam !== "any") {
-    video.deviceId = {
-      exact: cam,
-    };
+    video = assignMediaIdToConstraint(cam, video);
   }
 
        getUserMedia({
index 6a4219fd56a273763e4a9f16df1611680111d10f..a3d66a93f520164636f56de5a683a61f0a41b011 100644 (file)
 
         if (args["useCamera"]) {
             verto.options.deviceParams["useCamera"] = args["useCamera"];
+            verto.options.deviceParams["useCameraLabel"] = args["useCameraLabel"];
         }
 
         var dialog = new $.verto.dialog($.verto.enum.direction.outbound, this, args);
            screenShare: false,
            useCamera: false,
            useMic: verto.options.deviceParams.useMic,
+           useMicLabel: verto.options.deviceParams.useMicLabel,
            useSpeak: verto.options.deviceParams.useSpeak,
             tag: verto.options.tag,
             localTag: verto.options.localTag,
 
        if (!dialog.params.screenShare) {
            dialog.params.useCamera = verto.options.deviceParams.useCamera;
+           dialog.params.useCameraLabel = verto.options.deviceParams.useCameraLabel;
        }
 
         dialog.verto = verto;
         dialog.attach = params.attach || false;
        dialog.screenShare = params.screenShare || false;
        dialog.useCamera = dialog.params.useCamera;
+       dialog.useCameraLabel = dialog.params.useCameraLabel;
        dialog.useMic = dialog.params.useMic;
+       dialog.useMicLabel = dialog.params.useMicLabel;
        dialog.useSpeak = dialog.params.useSpeak;
        
         if (dialog.params.callID) {
             iceServers: verto.options.iceServers,
             screenShare: dialog.screenShare,
             useCamera: dialog.useCamera,
+            useCameraLabel: dialog.useCameraLabel,
             useMic: dialog.useMic,
+            useMicLabel: dialog.useMicLabel,
             useSpeak: dialog.useSpeak,
       turnServer: verto.options.turnServer,
       useStream: dialog.params.useStream
                dialog.params.callee_id_number = params.callee_id_number;
 
                if (params.useCamera) {
-                   dialog.useCamera = params.useCamera;
+            dialog.useCamera = params.useCamera;
+            dialog.useCameraLabel = params.useCameraLabel;
                }
 
                if (params.useMic) {
-                   dialog.useMic = params.useMic;
+            dialog.useMic = params.useMic;
+            dialog.useMic = params.useMicLabel;
                }
 
                if (params.useSpeak) {
diff --git a/html5/verto/js/src/vendor/media-device-id.min.js b/html5/verto/js/src/vendor/media-device-id.min.js
new file mode 100644 (file)
index 0000000..16df327
--- /dev/null
@@ -0,0 +1 @@
+/* Under MIT License by Mazuh. Original source code at: https://github.com/Mazuh/media-device-id */ !function(t){var r={};function e(n){if(r[n])return r[n].exports;var o=r[n]={i:n,l:!1,exports:{}};return t[n].call(o.exports,o,o.exports,e),o.l=!0,o.exports}e.m=t,e.c=r,e.d=function(t,r,n){e.o(t,r)||Object.defineProperty(t,r,{enumerable:!0,get:n})},e.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},e.t=function(t,r){if(1&r&&(t=e(t)),8&r)return t;if(4&r&&"object"==typeof t&&t&&t.__esModule)return t;var n=Object.create(null);if(e.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:t}),2&r&&"string"!=typeof t)for(var o in t)e.d(n,o,function(r){return t[r]}.bind(null,o));return n},e.n=function(t){var r=t&&t.__esModule?function(){return t.default}:function(){return t};return e.d(r,"a",r),r},e.o=function(t,r){return Object.prototype.hasOwnProperty.call(t,r)},e.p="",e(e.s=2)}([function(t,r,e){t.exports=e(3)},function(t,r){function e(t,r,e,n,o,i,a){try{var u=t[i](a),c=u.value}catch(t){return void e(t)}u.done?r(c):Promise.resolve(c).then(n,o)}t.exports=function(t){return function(){var r=this,n=arguments;return new Promise(function(o,i){var a=t.apply(r,n);function u(t){e(a,o,i,u,c,"next",t)}function c(t){e(a,o,i,u,c,"throw",t)}u(void 0)})}}},function(t,r,e){"use strict";e.r(r),e.d(r,"assureMediaInputId",function(){return u});var n=e(0),o=e.n(n),i=e(1),a=e.n(i);function u(t,r,e){return c.apply(this,arguments)}function c(){return(c=a()(o.a.mark(function t(r,e,n){var i,a,u,c,f,s,l,h,p,v,d;return o.a.wrap(function(t){for(;;)switch(t.prev=t.next){case 0:return i=function(t){return t.kind.indexOf("input")>-1},t.next=3,navigator.mediaDevices.enumerateDevices().then(function(t){return{ok:t.filter(i)}}).catch(function(t){return{err:t}});case 3:if(!(a=t.sent).err){t.next=6;break}throw String(a.err);case 6:if(u=a.ok,c=function(t){return t&&t.label},f=u.every(c),s=function(t){return t.label&&t.label==r},l=function(t){return t.deviceId==e},h=function(t){return l(t)},p=u.find(h),v=function(t){return l(t)||s(t)},d=u.find(v),p||f){t.next=19;break}if(void 0===n){t.next=18;break}return t.abrupt("return",n);case 18:throw"Could not assure device, id is wrong and labels are unavailable";case 19:if(p||d){t.next=23;break}if(void 0===n){t.next=22;break}return t.abrupt("return",n);case 22:throw"Could not assure device, not found by label nor id";case 23:return t.abrupt("return",p?p.deviceId:d.deviceId);case 24:case"end":return t.stop()}},t,this)}))).apply(this,arguments)}void 0!==window&&(window.assureMediaInputId=u)},function(t,r,e){var n=function(){return this||"object"==typeof self&&self}()||Function("return this")(),o=n.regeneratorRuntime&&Object.getOwnPropertyNames(n).indexOf("regeneratorRuntime")>=0,i=o&&n.regeneratorRuntime;if(n.regeneratorRuntime=void 0,t.exports=e(4),o)n.regeneratorRuntime=i;else try{delete n.regeneratorRuntime}catch(t){n.regeneratorRuntime=void 0}},function(t,r){!function(r){"use strict";var e,n=Object.prototype,o=n.hasOwnProperty,i="function"==typeof Symbol?Symbol:{},a=i.iterator||"@@iterator",u=i.asyncIterator||"@@asyncIterator",c=i.toStringTag||"@@toStringTag",f="object"==typeof t,s=r.regeneratorRuntime;if(s)f&&(t.exports=s);else{(s=r.regeneratorRuntime=f?t.exports:{}).wrap=b;var l="suspendedStart",h="suspendedYield",p="executing",v="completed",d={},y={};y[a]=function(){return this};var g=Object.getPrototypeOf,m=g&&g(g(F([])));m&&m!==n&&o.call(m,a)&&(y=m);var w=O.prototype=L.prototype=Object.create(y);E.prototype=w.constructor=O,O.constructor=E,O[c]=E.displayName="GeneratorFunction",s.isGeneratorFunction=function(t){var r="function"==typeof t&&t.constructor;return!!r&&(r===E||"GeneratorFunction"===(r.displayName||r.name))},s.mark=function(t){return Object.setPrototypeOf?Object.setPrototypeOf(t,O):(t.__proto__=O,c in t||(t[c]="GeneratorFunction")),t.prototype=Object.create(w),t},s.awrap=function(t){return{__await:t}},j(_.prototype),_.prototype[u]=function(){return this},s.AsyncIterator=_,s.async=function(t,r,e,n){var o=new _(b(t,r,e,n));return s.isGeneratorFunction(r)?o:o.next().then(function(t){return t.done?t.value:o.next()})},j(w),w[c]="Generator",w[a]=function(){return this},w.toString=function(){return"[object Generator]"},s.keys=function(t){var r=[];for(var e in t)r.push(e);return r.reverse(),function e(){for(;r.length;){var n=r.pop();if(n in t)return e.value=n,e.done=!1,e}return e.done=!0,e}},s.values=F,N.prototype={constructor:N,reset:function(t){if(this.prev=0,this.next=0,this.sent=this._sent=e,this.done=!1,this.delegate=null,this.method="next",this.arg=e,this.tryEntries.forEach(I),!t)for(var r in this)"t"===r.charAt(0)&&o.call(this,r)&&!isNaN(+r.slice(1))&&(this[r]=e)},stop:function(){this.done=!0;var t=this.tryEntries[0].completion;if("throw"===t.type)throw t.arg;return this.rval},dispatchException:function(t){if(this.done)throw t;var r=this;function n(n,o){return u.type="throw",u.arg=t,r.next=n,o&&(r.method="next",r.arg=e),!!o}for(var i=this.tryEntries.length-1;i>=0;--i){var a=this.tryEntries[i],u=a.completion;if("root"===a.tryLoc)return n("end");if(a.tryLoc<=this.prev){var c=o.call(a,"catchLoc"),f=o.call(a,"finallyLoc");if(c&&f){if(this.prev<a.catchLoc)return n(a.catchLoc,!0);if(this.prev<a.finallyLoc)return n(a.finallyLoc)}else if(c){if(this.prev<a.catchLoc)return n(a.catchLoc,!0)}else{if(!f)throw new Error("try statement without catch or finally");if(this.prev<a.finallyLoc)return n(a.finallyLoc)}}}},abrupt:function(t,r){for(var e=this.tryEntries.length-1;e>=0;--e){var n=this.tryEntries[e];if(n.tryLoc<=this.prev&&o.call(n,"finallyLoc")&&this.prev<n.finallyLoc){var i=n;break}}i&&("break"===t||"continue"===t)&&i.tryLoc<=r&&r<=i.finallyLoc&&(i=null);var a=i?i.completion:{};return a.type=t,a.arg=r,i?(this.method="next",this.next=i.finallyLoc,d):this.complete(a)},complete:function(t,r){if("throw"===t.type)throw t.arg;return"break"===t.type||"continue"===t.type?this.next=t.arg:"return"===t.type?(this.rval=this.arg=t.arg,this.method="return",this.next="end"):"normal"===t.type&&r&&(this.next=r),d},finish:function(t){for(var r=this.tryEntries.length-1;r>=0;--r){var e=this.tryEntries[r];if(e.finallyLoc===t)return this.complete(e.completion,e.afterLoc),I(e),d}},catch:function(t){for(var r=this.tryEntries.length-1;r>=0;--r){var e=this.tryEntries[r];if(e.tryLoc===t){var n=e.completion;if("throw"===n.type){var o=n.arg;I(e)}return o}}throw new Error("illegal catch attempt")},delegateYield:function(t,r,n){return this.delegate={iterator:F(t),resultName:r,nextLoc:n},"next"===this.method&&(this.arg=e),d}}}function b(t,r,e,n){var o=r&&r.prototype instanceof L?r:L,i=Object.create(o.prototype),a=new N(n||[]);return i._invoke=function(t,r,e){var n=l;return function(o,i){if(n===p)throw new Error("Generator is already running");if(n===v){if("throw"===o)throw i;return R()}for(e.method=o,e.arg=i;;){var a=e.delegate;if(a){var u=k(a,e);if(u){if(u===d)continue;return u}}if("next"===e.method)e.sent=e._sent=e.arg;else if("throw"===e.method){if(n===l)throw n=v,e.arg;e.dispatchException(e.arg)}else"return"===e.method&&e.abrupt("return",e.arg);n=p;var c=x(t,r,e);if("normal"===c.type){if(n=e.done?v:h,c.arg===d)continue;return{value:c.arg,done:e.done}}"throw"===c.type&&(n=v,e.method="throw",e.arg=c.arg)}}}(t,e,a),i}function x(t,r,e){try{return{type:"normal",arg:t.call(r,e)}}catch(t){return{type:"throw",arg:t}}}function L(){}function E(){}function O(){}function j(t){["next","throw","return"].forEach(function(r){t[r]=function(t){return this._invoke(r,t)}})}function _(t){var r;this._invoke=function(e,n){function i(){return new Promise(function(r,i){!function r(e,n,i,a){var u=x(t[e],t,n);if("throw"!==u.type){var c=u.arg,f=c.value;return f&&"object"==typeof f&&o.call(f,"__await")?Promise.resolve(f.__await).then(function(t){r("next",t,i,a)},function(t){r("throw",t,i,a)}):Promise.resolve(f).then(function(t){c.value=t,i(c)},function(t){return r("throw",t,i,a)})}a(u.arg)}(e,n,r,i)})}return r=r?r.then(i,i):i()}}function k(t,r){var n=t.iterator[r.method];if(n===e){if(r.delegate=null,"throw"===r.method){if(t.iterator.return&&(r.method="return",r.arg=e,k(t,r),"throw"===r.method))return d;r.method="throw",r.arg=new TypeError("The iterator does not provide a 'throw' method")}return d}var o=x(n,t.iterator,r.arg);if("throw"===o.type)return r.method="throw",r.arg=o.arg,r.delegate=null,d;var i=o.arg;return i?i.done?(r[t.resultName]=i.value,r.next=t.nextLoc,"return"!==r.method&&(r.method="next",r.arg=e),r.delegate=null,d):i:(r.method="throw",r.arg=new TypeError("iterator result is not an object"),r.delegate=null,d)}function P(t){var r={tryLoc:t[0]};1 in t&&(r.catchLoc=t[1]),2 in t&&(r.finallyLoc=t[2],r.afterLoc=t[3]),this.tryEntries.push(r)}function I(t){var r=t.completion||{};r.type="normal",delete r.arg,t.completion=r}function N(t){this.tryEntries=[{tryLoc:"root"}],t.forEach(P,this),this.reset(!0)}function F(t){if(t){var r=t[a];if(r)return r.call(t);if("function"==typeof t.next)return t;if(!isNaN(t.length)){var n=-1,i=function r(){for(;++n<t.length;)if(o.call(t,n))return r.value=t[n],r.done=!1,r;return r.value=e,r.done=!0,r};return i.next=i}}return{next:R}}function R(){return{value:e,done:!0}}}(function(){return this||"object"==typeof self&&self}()||Function("return this")())}]);
\ No newline at end of file