├── server_side └── etc │ ├── janus │ ├── janus.plugin.videocall.cfg │ ├── janus.plugin.sip.cfg │ ├── janus.transport.websockets.cfg │ ├── janus.plugin.videoroom.cfg │ └── janus.cfg │ └── init.d │ └── janus ├── public_html └── meetme │ ├── images │ ├── favicon.ico │ ├── novideo.jpg │ ├── speaking.png │ ├── video-icon-114-184619.png │ ├── video-icon-120-184619.png │ ├── video-icon-144-184619.png │ ├── video-icon-152-184619.png │ ├── video-icon-16-184619.png │ ├── video-icon-24-184619.png │ ├── video-icon-32-184619.png │ ├── video-icon-48-184619.png │ ├── video-icon-512-184619.png │ ├── video-icon-57-184619.png │ ├── video-icon-64-184619.png │ └── video-icon-72-184619.png │ ├── fonts │ ├── glyphicons-halflings-regular.eot │ ├── glyphicons-halflings-regular.ttf │ ├── glyphicons-halflings-regular.woff │ └── glyphicons-halflings-regular.woff2 │ ├── css │ ├── meetme_plug.css │ └── meetme.css │ ├── js │ ├── meetme_config.js │ ├── meetme_plug.js │ ├── url.min.js │ ├── meetme_lang.js │ ├── jquery.titlealert.js │ ├── bootbox.min.js │ ├── meetme.js │ ├── bootstrap.min.js │ └── adapter.min.js │ ├── index.html │ └── help.html ├── .gitignore ├── LICENSE.md └── README.md /server_side/etc/janus/janus.plugin.videocall.cfg: -------------------------------------------------------------------------------- 1 | ; The Video Call plugin doesn't need any configuration 2 | -------------------------------------------------------------------------------- /public_html/meetme/images/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/antonraharja/meetme/HEAD/public_html/meetme/images/favicon.ico -------------------------------------------------------------------------------- /public_html/meetme/images/novideo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/antonraharja/meetme/HEAD/public_html/meetme/images/novideo.jpg -------------------------------------------------------------------------------- /public_html/meetme/images/speaking.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/antonraharja/meetme/HEAD/public_html/meetme/images/speaking.png -------------------------------------------------------------------------------- /public_html/meetme/images/video-icon-114-184619.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/antonraharja/meetme/HEAD/public_html/meetme/images/video-icon-114-184619.png -------------------------------------------------------------------------------- /public_html/meetme/images/video-icon-120-184619.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/antonraharja/meetme/HEAD/public_html/meetme/images/video-icon-120-184619.png -------------------------------------------------------------------------------- /public_html/meetme/images/video-icon-144-184619.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/antonraharja/meetme/HEAD/public_html/meetme/images/video-icon-144-184619.png -------------------------------------------------------------------------------- /public_html/meetme/images/video-icon-152-184619.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/antonraharja/meetme/HEAD/public_html/meetme/images/video-icon-152-184619.png -------------------------------------------------------------------------------- /public_html/meetme/images/video-icon-16-184619.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/antonraharja/meetme/HEAD/public_html/meetme/images/video-icon-16-184619.png -------------------------------------------------------------------------------- /public_html/meetme/images/video-icon-24-184619.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/antonraharja/meetme/HEAD/public_html/meetme/images/video-icon-24-184619.png -------------------------------------------------------------------------------- /public_html/meetme/images/video-icon-32-184619.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/antonraharja/meetme/HEAD/public_html/meetme/images/video-icon-32-184619.png -------------------------------------------------------------------------------- /public_html/meetme/images/video-icon-48-184619.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/antonraharja/meetme/HEAD/public_html/meetme/images/video-icon-48-184619.png -------------------------------------------------------------------------------- /public_html/meetme/images/video-icon-512-184619.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/antonraharja/meetme/HEAD/public_html/meetme/images/video-icon-512-184619.png -------------------------------------------------------------------------------- /public_html/meetme/images/video-icon-57-184619.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/antonraharja/meetme/HEAD/public_html/meetme/images/video-icon-57-184619.png -------------------------------------------------------------------------------- /public_html/meetme/images/video-icon-64-184619.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/antonraharja/meetme/HEAD/public_html/meetme/images/video-icon-64-184619.png -------------------------------------------------------------------------------- /public_html/meetme/images/video-icon-72-184619.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/antonraharja/meetme/HEAD/public_html/meetme/images/video-icon-72-184619.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | test/ 2 | public_html/meetme/test.html 3 | public_html/meetme/js/test.js 4 | public_html/meetme/meetme-test.html 5 | public_html/meetme/js/meetme-test.js 6 | -------------------------------------------------------------------------------- /public_html/meetme/fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/antonraharja/meetme/HEAD/public_html/meetme/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /public_html/meetme/fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/antonraharja/meetme/HEAD/public_html/meetme/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /public_html/meetme/fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/antonraharja/meetme/HEAD/public_html/meetme/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /public_html/meetme/fonts/glyphicons-halflings-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/antonraharja/meetme/HEAD/public_html/meetme/fonts/glyphicons-halflings-regular.woff2 -------------------------------------------------------------------------------- /server_side/etc/janus/janus.plugin.sip.cfg: -------------------------------------------------------------------------------- 1 | [general] 2 | ;local_ip = 202.153.128.62 3 | keepalive_interval = 15 4 | behind_nat = no 5 | user_agent = meetme.id 6 | register_ttl = 600 7 | -------------------------------------------------------------------------------- /public_html/meetme/css/meetme_plug.css: -------------------------------------------------------------------------------- 1 | #plug-whiteboard-tab, #plug-screenshare-tab { 2 | position: relative; 3 | overflow: hidden; 4 | margin: 0 auto; 5 | padding: 0px !important; 6 | } 7 | -------------------------------------------------------------------------------- /server_side/etc/janus/janus.transport.websockets.cfg: -------------------------------------------------------------------------------- 1 | [general] 2 | ws = no 3 | ws_port = 8188 4 | wss = yes 5 | wss_port = 8989 6 | ws_logging = 7 7 | 8 | [admin] 9 | admin_ws = no 10 | admin_ws_port = 7188 11 | admin_wss = no 12 | admin_wss_port = 7989 13 | 14 | [certificates] 15 | cert_pem = /etc/ssl/meetme.id.pem 16 | cert_key = /etc/ssl/meetme.id.key 17 | -------------------------------------------------------------------------------- /public_html/meetme/js/meetme_config.js: -------------------------------------------------------------------------------- 1 | var server = "wss://meetme.id/gateway"; 2 | var iceServers = [ 3 | {urls: "stun:stun.meetme.id:443"}, 4 | {urls: "turn:turn.meetme.id:443?transport=tcp", credential: "public", username: "public"} 5 | ]; 6 | var videoBoxWidth = 160; 7 | var videoBoxHeight = 120; 8 | var videoBoxLargeWidth = "100%"; 9 | var videoBoxLargeHeight = "auto"; 10 | var maxVideoBox = 16; 11 | var maxBitRate = 64000; 12 | var defaultResolution = "lowres"; // lowres, stdres, hires 13 | var debugLevel = "all" 14 | var audioCodec = "opus"; 15 | var videoCodec = "vp8"; 16 | var windowTitle = "meetme.id"; 17 | var plugURL = "https://meetme.id/wb/theboard"; 18 | -------------------------------------------------------------------------------- /public_html/meetme/js/meetme_plug.js: -------------------------------------------------------------------------------- 1 | var plugURLParams; 2 | 3 | (window.onpopstate = function () { 4 | var match, 5 | pl = /\+/g, 6 | search = /([^&=]+)=?([^&]*)/g, 7 | decode = function (s) { return decodeURIComponent(s.replace(pl, " ")); }, 8 | query = window.location.search.substring(1); 9 | 10 | plugURLParams = {}; 11 | while (match = search.exec(query)) 12 | plugURLParams[decode(match[1])] = decode(match[2]); 13 | })(); 14 | 15 | var plugRoomId = parseInt(plugURLParams["room"]); 16 | 17 | function plugLoadIframe(iframeName, url) { 18 | var $iframe = $('#' + iframeName); 19 | 20 | if ( $iframe.length ) { 21 | $iframe.attr('src',url); 22 | 23 | return false; 24 | } 25 | 26 | return true; 27 | } 28 | -------------------------------------------------------------------------------- /server_side/etc/janus/janus.plugin.videoroom.cfg: -------------------------------------------------------------------------------- 1 | ; [] 2 | ; description = This is my awesome room 3 | ; is_private = yes|no (whether this room should be in the public list, default=yes) 4 | ; secret = 5 | ; pin = 6 | ; publishers = (e.g., 6 for a video 7 | ; conference or 1 for a webinar) 8 | ; bitrate = (e.g., 128000) 9 | ; fir_freq = (0=disable) 10 | ; audiocodec = opus|isac32|isac16|pcmu|pcma (audio codec to force on publishers, default=opus) 11 | ; videocodec = vp8|vp9|h264 (video codec to force on publishers, default=vp8) 12 | ; record = true|false (whether this room should be recorded, default=false) 13 | ; rec_dir = 14 | 15 | ;[1234] 16 | ;description = Demo Room 17 | ;secret = adminpwd 18 | ;publishers = 6 19 | ;bitrate = 128000 20 | ;fir_freq = 10 21 | ;audiocodec = opus 22 | ;videocodec = vp8 23 | ;record = false 24 | ;rec_dir = /tmp/janus-videoroom 25 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 [Anton Raharja](http://antonraharja.com) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /server_side/etc/janus/janus.cfg: -------------------------------------------------------------------------------- 1 | [general] 2 | configs_folder = /opt/janus/etc/janus 3 | plugins_folder = /opt/janus/lib/janus/plugins 4 | transports_folder = /opt/janus/lib/janus/transports 5 | log_to_stdout = false 6 | log_to_file = /var/log/janus.log 7 | daemonize = true 8 | pid_file = /var/run/janus.pid 9 | ;interface = 202.153.128.62 10 | debug_level = 4 11 | debug_timestamps = yes 12 | ;api_secret = janusrocks 13 | ;token_auth = yes 14 | ;admin_secret = janusoverlord 15 | 16 | [certificates] 17 | cert_pem = /etc/ssl/meetme.id.pem 18 | cert_key = /etc/ssl/meetme.id.key 19 | 20 | [media] 21 | ;ipv6 = true 22 | max_nack_queue = 300 23 | rtp_port_range = 50000-60000 24 | dtls_mtu = 1200 25 | force-bundle = true 26 | force-rtcp-mux = true 27 | 28 | [nat] 29 | ;stun_server = stun.teleponrakyat.id 30 | ;stun_port = 3478 31 | nice_debug = false 32 | ;ice_lite = true 33 | ;ice_tcp = true 34 | ;nat_1_1_mapping = 1.2.3.4 35 | ;turn_server = turn.meetme.id 36 | ;turn_port = 443 37 | ;turn_type = tcp 38 | ;turn_user = janus 39 | ;turn_pwd = janus 40 | ;turn_rest_api = http://yourbackend.com/path/to/api 41 | ;turn_rest_api_key = anyapikeyyoumayhaveset 42 | ;ice_enforce_list = eth0,202.163.128.62 43 | ;ice_ignore_list = vmnet8,192.168.0.1,10.0.0.1 44 | 45 | [plugins] 46 | disable = libjanus_audiobridge.so,libjanus_echotest.so,libjanus_recordplay.so,libjanus_streaming.so,libjanus_voicemail.so 47 | 48 | [transports] 49 | ; disable = libjanus_rabbitmq.so 50 | disable = libjanus_http.so 51 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # meetme 2 | 3 | WebRTC online meeting room. Powered by Janus WebRTC gateway. 4 | 5 | Item | Data 6 | ---------- | ---------------------------------------- 7 | Version | 2 8 | Maintainer | [Anton Raharja](http://antonraharja.com) 9 | License | [MIT License](LICENSE.md) 10 | 11 | # Changelog 12 | 13 | Changes up to today: 14 | 15 | - Modification of videoroom plugin demo web app 16 | - Add dynamic room creation 17 | - Add labels for easy translation 18 | - Add a large video box and small video boxes 19 | - Add a chat box for chatting between room members 20 | - Add side tab URL, the example is to show whiteboard 21 | - Early work on enhancing the user interface 22 | 23 | # Usage 24 | 25 | Live example of this project is [meetme.id](https://meetme.id). 26 | Enter your name and room number, click the join button and share the room number with your friends to start the video conference. 27 | 28 | # Installation 29 | 30 | Installation steps: 31 | 32 | - Drop all files in `public_html` to your own web document root or folder 33 | - Make sure that the server has HTTPS enabled 34 | - Modify source codes, mainly `index.html`, `meetme.css` and `meetme*.js`, as you wish 35 | - Do not touch janus.js and other js files other than `meetme*.js` unless you know what you're doing 36 | 37 | Please note: 38 | 39 | - You do not need to always use [meetme.id](https://meetme.id) infrastructure, you can install [Janus WebRTC Gateway](https://janus.conf.meetecho.com/) on your server and use it instead 40 | - You also don't need to use STUN/TURN if your Janus server is not in the Internet and not serving clients over the Internet, comment `iceServers` option on `meetme_config.js` 41 | -------------------------------------------------------------------------------- /server_side/etc/init.d/janus: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | ### BEGIN INIT INFO 4 | # Provides: Janus 5 | # Required-Start: $remote_fs $syslog 6 | # Required-Stop: $remote_fs $syslog 7 | # Default-Start: 2 3 4 5 8 | # Default-Stop: 0 1 6 9 | # Short-Description: Janus WebRTC gateway 10 | # Description: Janus WebRTC gateway 11 | ### END INIT INFO 12 | 13 | DAEMON=/opt/janus/bin/janus 14 | DAEMON_NAME=janus 15 | 16 | # Add any command line options for your daemon here 17 | DAEMON_OPTS="-D -o" 18 | 19 | # This next line determines what user the script runs as. 20 | # Root generally not recommended but necessary if you are using the Raspberry Pi GPIO from Python. 21 | DAEMON_USER=root 22 | 23 | # The process ID of the script when it runs is stored here: 24 | PIDFILE=/var/run/$DAEMON_NAME.pid 25 | 26 | . /lib/lsb/init-functions 27 | 28 | do_start () { 29 | log_daemon_msg "Starting system $DAEMON_NAME daemon" 30 | start-stop-daemon --start --background --no-close --pidfile $PIDFILE --make-pidfile --user $DAEMON_USER --chuid $DAEMON_USER --startas $DAEMON -- $DAEMON_OPTS >> /var/log/$DAEMON_NAME.log 2>&1 31 | log_end_msg $? 32 | } 33 | do_stop () { 34 | log_daemon_msg "Stopping system $DAEMON_NAME daemon" 35 | start-stop-daemon --stop --pidfile $PIDFILE --retry 10 36 | log_end_msg $? 37 | } 38 | 39 | case "$1" in 40 | 41 | start|stop) 42 | do_${1} 43 | ;; 44 | 45 | restart|reload|force-reload) 46 | do_stop 47 | do_start 48 | ;; 49 | 50 | status) 51 | status_of_proc "$DAEMON_NAME" "$DAEMON" && exit 0 || exit $? 52 | ;; 53 | 54 | *) 55 | echo "Usage: /etc/init.d/$DAEMON_NAME {start|stop|restart|status}" 56 | exit 1 57 | ;; 58 | 59 | esac 60 | exit 0 61 | -------------------------------------------------------------------------------- /public_html/meetme/js/url.min.js: -------------------------------------------------------------------------------- 1 | /*! js-url - v2.3.0 - 2016-03-10 */window.url=function(){function a(){}function b(a){return decodeURIComponent(a.replace(/\+/g," "))}function c(a,b){var c=a.charAt(0),d=b.split(c);return c===a?d:(a=parseInt(a.substring(1),10),d[0>a?d.length+a:a-1])}function d(a,c){for(var d=a.charAt(0),e=c.split("&"),f=[],g={},h=[],i=a.substring(1),j=0,k=e.length;k>j;j++)if(f=e[j].match(/(.*?)=(.*)/),f||(f=[e[j],e[j],""]),""!==f[1].replace(/\s/g,"")){if(f[2]=b(f[2]||""),i===f[1])return f[2];h=f[1].match(/(.*)\[([0-9]+)\]/),h?(g[h[1]]=g[h[1]]||[],g[h[1]][h[2]]=f[2]):g[f[1]]=f[2]}return d===a?g:g[i]}return function(b,e){var f,g={};if("tld?"===b)return a();if(e=e||window.location.toString(),!b)return e;if(b=b.toString(),f=e.match(/^mailto:([^\/].+)/))g.protocol="mailto",g.email=f[1];else{if((f=e.match(/(.*?)\/#\!(.*)/))&&(e=f[1]+f[2]),(f=e.match(/(.*?)#(.*)/))&&(g.hash=f[2],e=f[1]),g.hash&&b.match(/^#/))return d(b,g.hash);if((f=e.match(/(.*?)\?(.*)/))&&(g.query=f[2],e=f[1]),g.query&&b.match(/^\?/))return d(b,g.query);if((f=e.match(/(.*?)\:?\/\/(.*)/))&&(g.protocol=f[1].toLowerCase(),e=f[2]),(f=e.match(/(.*?)(\/.*)/))&&(g.path=f[2],e=f[1]),g.path=(g.path||"").replace(/^([^\/])/,"/$1").replace(/\/$/,""),b.match(/^[\-0-9]+$/)&&(b=b.replace(/^([^\/])/,"/$1")),b.match(/^\//))return c(b,g.path.substring(1));if(f=c("/-1",g.path.substring(1)),f&&(f=f.match(/(.*?)\.(.*)/))&&(g.file=f[0],g.filename=f[1],g.fileext=f[2]),(f=e.match(/(.*)\:([0-9]+)$/))&&(g.port=f[2],e=f[1]),(f=e.match(/(.*?)@(.*)/))&&(g.auth=f[1],e=f[2]),g.auth&&(f=g.auth.match(/(.*)\:(.*)/),g.user=f?f[1]:g.auth,g.pass=f?f[2]:void 0),g.hostname=e.toLowerCase(),"."===b.charAt(0))return c(b,g.hostname);a()&&(f=g.hostname.match(a()),f&&(g.tld=f[3],g.domain=f[2]?f[2]+"."+f[3]:void 0,g.sub=f[1]||void 0)),g.port=g.port||("https"===g.protocol?"443":"80"),g.protocol=g.protocol||("443"===g.port?"https":"http")}return b in g?g[b]:"{}"===b?g:void 0}}(),"undefined"!=typeof jQuery&&jQuery.extend({url:function(a,b){return window.url(a,b)}}); -------------------------------------------------------------------------------- /public_html/meetme/js/meetme_lang.js: -------------------------------------------------------------------------------- 1 | //var labelEnterRoom = "Enter room number"; 2 | var labelEnterRoom = "Masukkan nomor ruangan"; 3 | 4 | //var labelDisplayName = "Enter your name"; 5 | var labelDisplayName = "Masukkan nama anda"; 6 | 7 | //var labelNoRemoteVideo = "No remote video available"; 8 | //var labelNoRemoteVideo = "Tidak ada video"; 9 | var labelNoRemoteVideo = ""; 10 | 11 | //var labelNoWebcam = "No webcam available"; 12 | //var labelNoWebcam = "Tidak ada webcam"; 13 | var labelNoWebcam = ""; 14 | 15 | //var lebelSpeaking = "Currently speaking"; 16 | //var lebelSpeaking = "Sedang berbicara"; 17 | var labelSpeaking = ""; 18 | 19 | //var labelNoWebRTC = "No WebRTC support available"; 20 | var labelNoWebRTC = "Tidak ada dukungan WebRTC"; 21 | 22 | //var labelStartPublishing = "Start publishing"; 23 | var labelStartPublishing = "Masuk"; 24 | 25 | var labelStopPublishing = ""; 26 | 27 | //var labelRoom = "Room"; 28 | var labelRoom = "Ruangan"; 29 | 30 | //var labelRoomNumber = "Room #"; 31 | var labelRoomNumber = "#"; 32 | 33 | //var labelInvalidRoomNumber = "Room number is 1-10 digits only"; 34 | var labelInvalidRoomNumber = "Nomor ruangan antara 1-10 digit"; 35 | 36 | //var labelRoomNumericOnly = "Room number is numeric only"; 37 | var labelRoomNumericOnly = "Ruangan hanya angka saja"; 38 | 39 | //var labelDisplayNameAlphanumeric = "Name is alphanumeric and spaces only"; 40 | var labelDisplayNameAlphanumeric = "Nama hanya boleh alphanumeric dan spasi saja"; 41 | 42 | // labelMuteOn means mute is OFF, publisher will send the audio 43 | var labelMuteOn = ""; 44 | 45 | // labelMuteOff means mute is actually ON and publisher will NOT send the audio 46 | var labelMuteOff = ""; 47 | 48 | // labelPauseOn means mute is OFF, publisher will send the video 49 | var labelPauseOn = ""; 50 | 51 | // labelPauseOff means mute is actually ON and publisher will NOT send the video 52 | var labelPauseOff = ""; 53 | 54 | //var labelConfirmExit = "Are you sure you want to exit ?"; 55 | var labelConfirmExit = "Yakin ingin keluar dari ruang meeting ?"; 56 | 57 | //var labelRefreshWarning = "You are about to refresh this page, you will be forced to exit the meeting room"; 58 | var labelRefreshWarning = "Anda akan melakukan refresh/close halaman ini, apabila dilanjutkan maka anda akan keluar dari ruang meeting"; 59 | 60 | //var labelUserJoinChat = " joins the room"; 61 | var labelUserJoinChat = " telah bergabung"; 62 | 63 | //var labelUserLeaveChat = " is leaving"; 64 | var labelUserLeaveChat = " telah keluar"; 65 | 66 | //var labelChatRead = "Ready"; 67 | var labelChatReady = "Ready"; 68 | 69 | //var labelChatNotificationHeader = "New message"; 70 | var labelChatNotificationHeader = "Ada pesan baru"; 71 | -------------------------------------------------------------------------------- /public_html/meetme/js/jquery.titlealert.js: -------------------------------------------------------------------------------- 1 | /*!! 2 | * Title Alert 0.7 3 | * 4 | * Copyright (c) 2009 ESN | http://esn.me 5 | * Jonatan Heyman | http://heyman.info 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | */ 17 | 18 | /* 19 | * @name jQuery.titleAlert 20 | * @projectDescription Show alert message in the browser title bar 21 | * @author Jonatan Heyman | http://heyman.info 22 | * @version 0.7.0 23 | * @license MIT License 24 | * 25 | * @id jQuery.titleAlert 26 | * @param {String} text The text that should be flashed in the browser title 27 | * @param {Object} settings Optional set of settings. 28 | * @option {Number} interval The flashing interval in milliseconds (default: 500). 29 | * @option {Number} originalTitleInterval Time in milliseconds that the original title is diplayed for. If null the time is the same as interval (default: null). 30 | * @option {Number} duration The total lenght of the flashing before it is automatically stopped. Zero means infinite (default: 0). 31 | * @option {Boolean} stopOnFocus If true, the flashing will stop when the window gets focus (default: true). 32 | * @option {Boolean} stopOnMouseMove If true, the flashing will stop when the browser window recieves a mousemove event. (default:false). 33 | * @option {Boolean} requireBlur Experimental. If true, the call will be ignored unless the window is out of focus (default: false). 34 | * Known issues: Firefox doesn't recognize tab switching as blur, and there are some minor IE problems as well. 35 | * 36 | * @example $.titleAlert("Hello World!", {requireBlur:true, stopOnFocus:true, duration:10000, interval:500}); 37 | * @desc Flash title bar with text "Hello World!", if the window doesn't have focus, for 10 seconds or until window gets focused, with an interval of 500ms 38 | */ 39 | ;(function($){ 40 | $.titleAlert = function(text, settings) { 41 | // check if it currently flashing something, if so reset it 42 | if ($.titleAlert._running) 43 | $.titleAlert.stop(); 44 | 45 | // override default settings with specified settings 46 | $.titleAlert._settings = settings = $.extend( {}, $.titleAlert.defaults, settings); 47 | 48 | // if it's required that the window doesn't have focus, and it has, just return 49 | if (settings.requireBlur && $.titleAlert.hasFocus) 50 | return; 51 | 52 | // originalTitleInterval defaults to interval if not set 53 | settings.originalTitleInterval = settings.originalTitleInterval || settings.interval; 54 | 55 | $.titleAlert._running = true; 56 | $.titleAlert._initialText = document.title; 57 | document.title = text; 58 | var showingAlertTitle = true; 59 | var switchTitle = function() { 60 | // WTF! Sometimes Internet Explorer 6 calls the interval function an extra time! 61 | if (!$.titleAlert._running) 62 | return; 63 | 64 | showingAlertTitle = !showingAlertTitle; 65 | document.title = (showingAlertTitle ? text : $.titleAlert._initialText); 66 | $.titleAlert._intervalToken = setTimeout(switchTitle, (showingAlertTitle ? settings.interval : settings.originalTitleInterval)); 67 | } 68 | $.titleAlert._intervalToken = setTimeout(switchTitle, settings.interval); 69 | 70 | if (settings.stopOnMouseMove) { 71 | $(document).mousemove(function(event) { 72 | $(this).unbind(event); 73 | $.titleAlert.stop(); 74 | }); 75 | } 76 | 77 | // check if a duration is specified 78 | if (settings.duration > 0) { 79 | $.titleAlert._timeoutToken = setTimeout(function() { 80 | $.titleAlert.stop(); 81 | }, settings.duration); 82 | } 83 | }; 84 | 85 | // default settings 86 | $.titleAlert.defaults = { 87 | interval: 500, 88 | originalTitleInterval: null, 89 | duration:0, 90 | stopOnFocus: true, 91 | requireBlur: false, 92 | stopOnMouseMove: false 93 | }; 94 | 95 | // stop current title flash 96 | $.titleAlert.stop = function() { 97 | if (!$.titleAlert._running) 98 | return; 99 | 100 | clearTimeout($.titleAlert._intervalToken); 101 | clearTimeout($.titleAlert._timeoutToken); 102 | document.title = $.titleAlert._initialText; 103 | 104 | $.titleAlert._timeoutToken = null; 105 | $.titleAlert._intervalToken = null; 106 | $.titleAlert._initialText = null; 107 | $.titleAlert._running = false; 108 | $.titleAlert._settings = null; 109 | } 110 | 111 | $.titleAlert.hasFocus = true; 112 | $.titleAlert._running = false; 113 | $.titleAlert._intervalToken = null; 114 | $.titleAlert._timeoutToken = null; 115 | $.titleAlert._initialText = null; 116 | $.titleAlert._settings = null; 117 | 118 | 119 | $.titleAlert._focus = function () { 120 | $.titleAlert.hasFocus = true; 121 | 122 | if ($.titleAlert._running && $.titleAlert._settings.stopOnFocus) { 123 | var initialText = $.titleAlert._initialText; 124 | $.titleAlert.stop(); 125 | 126 | // ugly hack because of a bug in Chrome which causes a change of document.title immediately after tab switch 127 | // to have no effect on the browser title 128 | setTimeout(function() { 129 | if ($.titleAlert._running) 130 | return; 131 | document.title = "."; 132 | document.title = initialText; 133 | }, 1000); 134 | } 135 | }; 136 | $.titleAlert._blur = function () { 137 | $.titleAlert.hasFocus = false; 138 | }; 139 | 140 | // bind focus and blur event handlers 141 | $(window).bind("focus", $.titleAlert._focus); 142 | $(window).bind("blur", $.titleAlert._blur); 143 | })(jQuery); 144 | -------------------------------------------------------------------------------- /public_html/meetme/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | meetme.id 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 57 | 58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 | 67 | 68 |
69 |
70 |
71 |
72 |
73 |
74 |

75 | Ruang meeting online 76 |

77 |
78 |
79 |
80 | 81 | 82 | 83 |
84 |
85 |
86 | 87 | 88 | 89 |
90 |
91 | 92 | 93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 | 105 | 106 | 107 | 108 | 109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 | 142 |
143 | 144 | 145 |
146 |
147 | 148 | 149 |
150 |
151 | 152 | 153 | 154 | 155 | 156 | 161 | 162 | 163 | 164 | 165 | 166 | -------------------------------------------------------------------------------- /public_html/meetme/help.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | meetme.id 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 52 | 53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |

68 | Cara menggunakan 69 |

70 |
71 |
72 |
73 |

Berikut adalah petunjuk singkat bagaimana menggunakan layanan:

74 |
    75 |
  1. Masukkan nama anda di input field Nama anda diatas
  2. 76 |
      77 |
    • Singkat saja dan hanya gunakan huruf saja, boleh dengan spasi
    • 78 |
    79 |
  3. Masukkan nomor ruang meeting di input field Nomor ruangan diatas
  4. 80 |
      81 |
    • Nomor ruangan adalah angka antara 1 sampai 9999999999
    • 82 |
    • Apabila ruangan kosong maka akan dibuatkan otomatis untuk anda
    • 83 |
    • Apabila sudah ada orang lain maka anda bergabung dalam ruangan tersebut
    • 84 |
    85 |
  5. Klik tombol Masuk untuk membuat atau bergabung dalam ruang meeting online
  6. 86 |
87 |

Catatan penting:

88 |
    89 |
  • Gunakan Chrome, Firefox atau Opera yang terbaru, Safari membutuhkan plugin Temasys, IE dan Edge tidak berjalan baik
  • 90 |
  • Layanan berjalan dengan baik di Android namun tidak berjalan di iOS dan mungkin juga di Windows Phone
  • 91 |
  • Video webcam anda adalah yang namanya berwarna biru
  • 92 |
  • Saat anda masuk ruang meeting suara anda di-mute, klik tombol berbentuk speaker-off warna merah di kanan atas layar untuk berbicara
  • 93 |
  • Bandwidth yang dibutuhkan per video stream adalah sekitar 64kbps sampai 128kbps sudah termasuk video, voice dan data
  • 94 |
95 |
96 |
97 |
98 |
99 |
100 |

101 | Syarat dan ketentuan berlaku 102 |

103 |
104 |
105 |
106 |

Perhatian, dengan masuk di salah satu ruang meeting online disini maka:

107 |
    108 |
  • Anda setuju untuk berhati-hati karena tidak ada mekanisme registrasi atau validasi pengguna layanan disini
  • 109 |
  • Anda setuju untuk memperhatikan dengan siapa anda berbicara
  • 110 |
  • Anda setuju untuk memastikan anda benar kenal dengan rekan diskusi anda di ruang meeting ini
  • 111 |
  • Anda setuju untuk tidak memberikan informasi pribadi atau sensitif lainnya disini
  • 112 |
  • Anda setuju untuk tidak menggunakan layanan ini untuk mendukung dan/atau melaksanakan kegiatan yang melanggar hukum di Indonesia
  • 113 |
  • Anda setuju bahwa pengelola dan/atau penyelenggara layanan ini tidak dapat ikut bertanggung-jawab atas kegiatan yang anda lakukan
  • 114 |
115 |
116 |
117 |
118 |
119 |
120 |

121 | Tentang pengelolaan layanan 122 |

123 |
124 |
125 |
126 |

Pengelolaan layanan:

127 |
    128 |
  • Ini adalah layanan gratis dengan tujuan untuk mempelajari teknologi komunikasi berbasis IP
  • 129 |
  • Layanan ini dikelola oleh perorangan dan dijalankan dengan SLA best effort
  • 130 |
  • Infrastruktur yang ada kemampuannya terbatas karena berbagi dengan layanan lain yaitu Telepon Rakyat, mohon gunakan layanan dengan bijak
  • 131 |
  • Lokasi server berada di IDC 3D Duren Tiga Jakarta, bandwidth server lebar di dalam negri namun terbatas untuk luar negri
  • 132 |
133 |
134 |
135 |
136 |
137 |
138 |

139 | Kontak 140 |

141 |
142 |
143 |
144 |

Anda menemui masalah ?

145 | 146 | 147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | -------------------------------------------------------------------------------- /public_html/meetme/js/bootbox.min.js: -------------------------------------------------------------------------------- 1 | /** 2 | * bootbox.js v4.4.0 3 | * 4 | * http://bootboxjs.com/license.txt 5 | */ 6 | !function(a,b){"use strict";"function"==typeof define&&define.amd?define(["jquery"],b):"object"==typeof exports?module.exports=b(require("jquery")):a.bootbox=b(a.jQuery)}(this,function a(b,c){"use strict";function d(a){var b=q[o.locale];return b?b[a]:q.en[a]}function e(a,c,d){a.stopPropagation(),a.preventDefault();var e=b.isFunction(d)&&d.call(c,a)===!1;e||c.modal("hide")}function f(a){var b,c=0;for(b in a)c++;return c}function g(a,c){var d=0;b.each(a,function(a,b){c(a,b,d++)})}function h(a){var c,d;if("object"!=typeof a)throw new Error("Please supply an object of options");if(!a.message)throw new Error("Please specify a message");return a=b.extend({},o,a),a.buttons||(a.buttons={}),c=a.buttons,d=f(c),g(c,function(a,e,f){if(b.isFunction(e)&&(e=c[a]={callback:e}),"object"!==b.type(e))throw new Error("button with key "+a+" must be an object");e.label||(e.label=a),e.className||(e.className=2>=d&&f===d-1?"btn-primary":"btn-default")}),a}function i(a,b){var c=a.length,d={};if(1>c||c>2)throw new Error("Invalid argument length");return 2===c||"string"==typeof a[0]?(d[b[0]]=a[0],d[b[1]]=a[1]):d=a[0],d}function j(a,c,d){return b.extend(!0,{},a,i(c,d))}function k(a,b,c,d){var e={className:"bootbox-"+a,buttons:l.apply(null,b)};return m(j(e,d,c),b)}function l(){for(var a={},b=0,c=arguments.length;c>b;b++){var e=arguments[b],f=e.toLowerCase(),g=e.toUpperCase();a[f]={label:d(g)}}return a}function m(a,b){var d={};return g(b,function(a,b){d[b]=!0}),g(a.buttons,function(a){if(d[a]===c)throw new Error("button key "+a+" is not allowed (options are "+b.join("\n")+")")}),a}var n={dialog:"",header:"",footer:"",closeButton:"",form:"
",inputs:{text:"",textarea:"",email:"",select:"",checkbox:"
",date:"",time:"",number:"",password:""}},o={locale:"en",backdrop:"static",animate:!0,className:null,closeButton:!0,show:!0,container:"body"},p={};p.alert=function(){var a;if(a=k("alert",["ok"],["message","callback"],arguments),a.callback&&!b.isFunction(a.callback))throw new Error("alert requires callback property to be a function when provided");return a.buttons.ok.callback=a.onEscape=function(){return b.isFunction(a.callback)?a.callback.call(this):!0},p.dialog(a)},p.confirm=function(){var a;if(a=k("confirm",["cancel","confirm"],["message","callback"],arguments),a.buttons.cancel.callback=a.onEscape=function(){return a.callback.call(this,!1)},a.buttons.confirm.callback=function(){return a.callback.call(this,!0)},!b.isFunction(a.callback))throw new Error("confirm requires a callback");return p.dialog(a)},p.prompt=function(){var a,d,e,f,h,i,k;if(f=b(n.form),d={className:"bootbox-prompt",buttons:l("cancel","confirm"),value:"",inputType:"text"},a=m(j(d,arguments,["title","callback"]),["cancel","confirm"]),i=a.show===c?!0:a.show,a.message=f,a.buttons.cancel.callback=a.onEscape=function(){return a.callback.call(this,null)},a.buttons.confirm.callback=function(){var c;switch(a.inputType){case"text":case"textarea":case"email":case"select":case"date":case"time":case"number":case"password":c=h.val();break;case"checkbox":var d=h.find("input:checked");c=[],g(d,function(a,d){c.push(b(d).val())})}return a.callback.call(this,c)},a.show=!1,!a.title)throw new Error("prompt requires a title");if(!b.isFunction(a.callback))throw new Error("prompt requires a callback");if(!n.inputs[a.inputType])throw new Error("invalid prompt type");switch(h=b(n.inputs[a.inputType]),a.inputType){case"text":case"textarea":case"email":case"date":case"time":case"number":case"password":h.val(a.value);break;case"select":var o={};if(k=a.inputOptions||[],!b.isArray(k))throw new Error("Please pass an array of input options");if(!k.length)throw new Error("prompt with select requires options");g(k,function(a,d){var e=h;if(d.value===c||d.text===c)throw new Error("given options in wrong format");d.group&&(o[d.group]||(o[d.group]=b("").attr("label",d.group)),e=o[d.group]),e.append("")}),g(o,function(a,b){h.append(b)}),h.val(a.value);break;case"checkbox":var q=b.isArray(a.value)?a.value:[a.value];if(k=a.inputOptions||[],!k.length)throw new Error("prompt with checkbox requires options");if(!k[0].value||!k[0].text)throw new Error("given options in wrong format");h=b("
"),g(k,function(c,d){var e=b(n.inputs[a.inputType]);e.find("input").attr("value",d.value),e.find("label").append(d.text),g(q,function(a,b){b===d.value&&e.find("input").prop("checked",!0)}),h.append(e)})}return a.placeholder&&h.attr("placeholder",a.placeholder),a.pattern&&h.attr("pattern",a.pattern),a.maxlength&&h.attr("maxlength",a.maxlength),f.append(h),f.on("submit",function(a){a.preventDefault(),a.stopPropagation(),e.find(".btn-primary").click()}),e=p.dialog(a),e.off("shown.bs.modal"),e.on("shown.bs.modal",function(){h.focus()}),i===!0&&e.modal("show"),e},p.dialog=function(a){a=h(a);var d=b(n.dialog),f=d.find(".modal-dialog"),i=d.find(".modal-body"),j=a.buttons,k="",l={onEscape:a.onEscape};if(b.fn.modal===c)throw new Error("$.fn.modal is not defined; please double check you have included the Bootstrap JavaScript library. See http://getbootstrap.com/javascript/ for more details.");if(g(j,function(a,b){k+="",l[a]=b.callback}),i.find(".bootbox-body").html(a.message),a.animate===!0&&d.addClass("fade"),a.className&&d.addClass(a.className),"large"===a.size?f.addClass("modal-lg"):"small"===a.size&&f.addClass("modal-sm"),a.title&&i.before(n.header),a.closeButton){var m=b(n.closeButton);a.title?d.find(".modal-header").prepend(m):m.css("margin-top","-10px").prependTo(i)}return a.title&&d.find(".modal-title").html(a.title),k.length&&(i.after(n.footer),d.find(".modal-footer").html(k)),d.on("hidden.bs.modal",function(a){a.target===this&&d.remove()}),d.on("shown.bs.modal",function(){d.find(".btn-primary:first").focus()}),"static"!==a.backdrop&&d.on("click.dismiss.bs.modal",function(a){d.children(".modal-backdrop").length&&(a.currentTarget=d.children(".modal-backdrop").get(0)),a.target===a.currentTarget&&d.trigger("escape.close.bb")}),d.on("escape.close.bb",function(a){l.onEscape&&e(a,d,l.onEscape)}),d.on("click",".modal-footer button",function(a){var c=b(this).data("bb-handler");e(a,d,l[c])}),d.on("click",".bootbox-close-button",function(a){e(a,d,l.onEscape)}),d.on("keyup",function(a){27===a.which&&d.trigger("escape.close.bb")}),b(a.container).append(d),d.modal({backdrop:a.backdrop?"static":!1,keyboard:!1,show:!1}),a.show&&d.modal("show"),d},p.setDefaults=function(){var a={};2===arguments.length?a[arguments[0]]=arguments[1]:a=arguments[0],b.extend(o,a)},p.hideAll=function(){return b(".bootbox").modal("hide"),p};var q={bg_BG:{OK:"Ок",CANCEL:"Отказ",CONFIRM:"Потвърждавам"},br:{OK:"OK",CANCEL:"Cancelar",CONFIRM:"Sim"},cs:{OK:"OK",CANCEL:"Zrušit",CONFIRM:"Potvrdit"},da:{OK:"OK",CANCEL:"Annuller",CONFIRM:"Accepter"},de:{OK:"OK",CANCEL:"Abbrechen",CONFIRM:"Akzeptieren"},el:{OK:"Εντάξει",CANCEL:"Ακύρωση",CONFIRM:"Επιβεβαίωση"},en:{OK:"OK",CANCEL:"Cancel",CONFIRM:"OK"},es:{OK:"OK",CANCEL:"Cancelar",CONFIRM:"Aceptar"},et:{OK:"OK",CANCEL:"Katkesta",CONFIRM:"OK"},fa:{OK:"قبول",CANCEL:"لغو",CONFIRM:"تایید"},fi:{OK:"OK",CANCEL:"Peruuta",CONFIRM:"OK"},fr:{OK:"OK",CANCEL:"Annuler",CONFIRM:"D'accord"},he:{OK:"אישור",CANCEL:"ביטול",CONFIRM:"אישור"},hu:{OK:"OK",CANCEL:"Mégsem",CONFIRM:"Megerősít"},hr:{OK:"OK",CANCEL:"Odustani",CONFIRM:"Potvrdi"},id:{OK:"OK",CANCEL:"Batal",CONFIRM:"OK"},it:{OK:"OK",CANCEL:"Annulla",CONFIRM:"Conferma"},ja:{OK:"OK",CANCEL:"キャンセル",CONFIRM:"確認"},lt:{OK:"Gerai",CANCEL:"Atšaukti",CONFIRM:"Patvirtinti"},lv:{OK:"Labi",CANCEL:"Atcelt",CONFIRM:"Apstiprināt"},nl:{OK:"OK",CANCEL:"Annuleren",CONFIRM:"Accepteren"},no:{OK:"OK",CANCEL:"Avbryt",CONFIRM:"OK"},pl:{OK:"OK",CANCEL:"Anuluj",CONFIRM:"Potwierdź"},pt:{OK:"OK",CANCEL:"Cancelar",CONFIRM:"Confirmar"},ru:{OK:"OK",CANCEL:"Отмена",CONFIRM:"Применить"},sq:{OK:"OK",CANCEL:"Anulo",CONFIRM:"Prano"},sv:{OK:"OK",CANCEL:"Avbryt",CONFIRM:"OK"},th:{OK:"ตกลง",CANCEL:"ยกเลิก",CONFIRM:"ยืนยัน"},tr:{OK:"Tamam",CANCEL:"İptal",CONFIRM:"Onayla"},zh_CN:{OK:"OK",CANCEL:"取消",CONFIRM:"确认"},zh_TW:{OK:"OK",CANCEL:"取消",CONFIRM:"確認"}};return p.addLocale=function(a,c){return b.each(["OK","CANCEL","CONFIRM"],function(a,b){if(!c[b])throw new Error("Please supply a translation for '"+b+"'")}),q[a]={OK:c.OK,CANCEL:c.CANCEL,CONFIRM:c.CONFIRM},p},p.removeLocale=function(a){return delete q[a],p},p.setLocale=function(a){return p.setDefaults("locale",a)},p.init=function(c){return a(c||b)},p}); -------------------------------------------------------------------------------- /public_html/meetme/css/meetme.css: -------------------------------------------------------------------------------- 1 | html, 2 | body { 3 | width: 100%; 4 | height: 100%; 5 | } 6 | 7 | body { 8 | font-family: "Source Sans Pro","Helvetica Neue",Helvetica,Arial,sans-serif; 9 | background-color: #3B3C3D; 10 | } 11 | 12 | .nopadding { 13 | padding: 0 !important; 14 | margin: 0 !important; 15 | } 16 | 17 | video { 18 | -moz-transform: scale(-1, 1); 19 | -webkit-transform: scale(-1, 1); 20 | -o-transform: scale(-1, 1); 21 | -ms-transform: scale(-1, 1); 22 | transform: scale(-1, 1); 23 | background-color: #4D545E; 24 | width: 100% 25 | height: auto; 26 | } 27 | 28 | .videobox, .videobox-novideo { 29 | margin: 0px !important; 30 | padding: 0px !important; 31 | max-width: 640px; 32 | max-height: 480px; 33 | } 34 | 35 | #mute, #pause, #unpublish { 36 | margin-left: 5px; 37 | } 38 | 39 | #restartbox { 40 | width: 160px; 41 | height: 120px; 42 | background-image: url('../images/novideo.jpg'); 43 | background-size: 160px 120px; 44 | } 45 | 46 | #restartbox p { 47 | margin-left: 15px; 48 | } 49 | 50 | #notifbox, #roomdesc { 51 | font-size: larger; 52 | margin-top: 15px; 53 | } 54 | 55 | #meetmebox { 56 | position: relative; 57 | overflow: hidden; 58 | margin: 0 auto; 59 | padding: 0px !important; 60 | max-width: 1280px; 61 | } 62 | 63 | #meetmebox-plug { 64 | position: relative; 65 | overflow: hidden; 66 | margin: 0px !important; 67 | padding: 0px !important; 68 | max-width: 800px; 69 | max-height: 600px; 70 | } 71 | 72 | #videofocus { 73 | position: relative; 74 | overflow: hidden; 75 | margin: 0px !important; 76 | padding: 0px !important; 77 | max-width: 640px; 78 | max-height: 480px; 79 | } 80 | 81 | #videolocal, div[id*='videoremote'] { 82 | position: relative; 83 | overflow: hidden; 84 | margin: 0px !important; 85 | padding: 0px !important; 86 | } 87 | 88 | #meetmeheader { 89 | margin: 0 auto; 90 | padding-top: 20px; 91 | padding-bottom: 20px; 92 | max-width: 1310px; 93 | } 94 | 95 | #chatboxinput { 96 | /* background-color: #95A5A6; */ 97 | } 98 | 99 | #chatboxcontent { 100 | width: 100%; 101 | height: 300px; 102 | overflow: auto; 103 | background-color: #95A5A6; 104 | color: #22313F; 105 | } 106 | 107 | #chatboxcontent > div { 108 | background: #F0F0F0; 109 | margin: 5px; 110 | width: 85%; 111 | padding: 5px 10px 5px 10px; 112 | } 113 | 114 | #chatboxcontent > div > time { 115 | border-radius: 3px; 116 | float: right; 117 | color: #D35400; 118 | } 119 | 120 | .incoming-messages{ 121 | border-radius: 3px; 122 | float: left; 123 | } 124 | 125 | .outgoing-messages{ 126 | border-radius: 3px; 127 | float: right; 128 | } 129 | 130 | .notification-messages{ 131 | margin: 10px; 132 | float: right; 133 | color: snow; 134 | width: 85%; 135 | } 136 | 137 | .chat-box { 138 | font:normal normal 11px/1.4 Tahoma,Verdana,Sans-Serif; 139 | color:#333; 140 | width: 300px; /* Chatbox width */ 141 | border:1px solid #344150; 142 | border-bottom:none; 143 | background-color: #95A5A6; 144 | position:fixed; 145 | right:10px; 146 | bottom:0; 147 | z-index:9999; 148 | -webkit-box-shadow:1px 1px 5px rgba(0,0,0,.2); 149 | -moz-box-shadow:1px 1px 5px rgba(0,0,0,.2); 150 | box-shadow:1px 1px 5px rgba(0,0,0,.2); 151 | display:none; 152 | } 153 | 154 | .chat-box > input[type="checkbox"] { 155 | display:block; 156 | margin:0 0; 157 | padding:0 0; 158 | position:absolute; 159 | top:0; 160 | right:0; 161 | left:0; 162 | width:100%; 163 | height:26px; 164 | z-index:4; 165 | cursor:pointer; 166 | opacity:0; 167 | filter:alpha(opacity=0); 168 | } 169 | 170 | blink, .blink { 171 | -webkit-animation: blink 1s step-end infinite; 172 | -moz-animation: blink 1s step-end infinite; 173 | -o-animation: blink 1s step-end infinite; 174 | animation: blink 1s step-end infinite; 175 | } 176 | 177 | @-webkit-keyframes blink { 178 | 67% { opacity: 0 } 179 | } 180 | 181 | @-moz-keyframes blink { 182 | 67% { opacity: 0 } 183 | } 184 | 185 | @-o-keyframes blink { 186 | 67% { opacity: 0 } 187 | } 188 | 189 | @keyframes blink { 190 | 67% { opacity: 0 } 191 | } 192 | 193 | .chat-box > label { 194 | display:block; 195 | height:24px; 196 | line-height:24px; 197 | background-color: #344150; 198 | color: #F0F0F0; 199 | font-weight:bold; 200 | padding:0 1em 1px; 201 | margin-bottom: 0px !important; 202 | } 203 | 204 | .chat-box > label:before {content:attr(data-collapsed)} 205 | 206 | .chat-box .chat-box-content { 207 | display:none; 208 | } 209 | 210 | /* hover state */ 211 | .chat-box > input[type="checkbox"]:hover + label {background-color: #404D5A} 212 | 213 | /* checked state */ 214 | .chat-box > input[type="checkbox"]:checked + label {background-color: #212A35} 215 | .chat-box > input[type="checkbox"]:checked + label:before {content:attr(data-expanded)} 216 | .chat-box > input[type="checkbox"]:checked ~ .chat-box-content {display:block} 217 | 218 | @media screen and (min-width: 1300px) { 219 | .container { 220 | width: auto; 221 | } 222 | 223 | .chat-box { 224 | width: 300px; 225 | } 226 | 227 | #chatboxcontent { 228 | height: 300px; 229 | } 230 | 231 | #meetmeheader { 232 | width: 1280px; 233 | } 234 | 235 | #meetmebox { 236 | width: 1280px; 237 | } 238 | 239 | #meetmebox-plug { 240 | width: 800px; 241 | height: 600px; 242 | } 243 | 244 | #meetmebox-videos { 245 | width: 480px; 246 | height: 240px; 247 | overflow-y: visible; 248 | } 249 | 250 | #videofocus, #videofocus img, #videofocus video { 251 | width: 480px; 252 | height: 360px; 253 | } 254 | 255 | #videolocal, div[id*='videoremote'] { 256 | width: 160px; 257 | height: 120px; 258 | } 259 | 260 | #videolocal img, #videolocal video, div[id*='videoremote'] img, div[id*='videoremote'] video { 261 | width: 160px; 262 | height: 120px; 263 | } 264 | } 265 | 266 | /* width 1280px */ 267 | @media screen and (max-width: 1280px) { 268 | .container { 269 | width: auto; 270 | } 271 | 272 | .chat-box { 273 | width: 300px; 274 | } 275 | 276 | #chatboxcontent { 277 | height: 300px; 278 | } 279 | 280 | #meetmeheader { 281 | width: 1120px; 282 | } 283 | 284 | #meetmebox { 285 | width: 1120px; 286 | } 287 | 288 | #meetmebox-plug { 289 | width: 640px; 290 | height: 480px; 291 | } 292 | 293 | #meetmebox-videos { 294 | width: 480px; 295 | height: 120px; 296 | overflow-y: visible; 297 | } 298 | 299 | #videofocus, #videofocus img, #videofocus video { 300 | width: 480px; 301 | height: 360px; 302 | } 303 | 304 | #videolocal, div[id*='videoremote'] { 305 | width: 160px; 306 | } 307 | 308 | #videolocal img, #videolocal video, div[id*='videoremote'] img, div[id*='videoremote'] video { 309 | width: 160px; 310 | height: 120px; 311 | } 312 | } 313 | 314 | /* width 1024px */ 315 | @media screen and (max-width: 1024px) { 316 | .container { 317 | width: auto; 318 | } 319 | 320 | .chat-box { 321 | width: 300px; 322 | } 323 | 324 | #chatboxcontent { 325 | height: 300px; 326 | } 327 | 328 | #meetmeheader { 329 | width: 960px; 330 | } 331 | 332 | #meetmebox { 333 | width: 960px; 334 | } 335 | 336 | #meetmebox-plug { 337 | width: 640px; 338 | height: 480px; 339 | } 340 | 341 | #meetmebox-videos { 342 | width: 320px; 343 | height: 240px; 344 | overflow-y: visible; 345 | } 346 | 347 | #videofocus, #videofocus img, #videofocus video { 348 | width: 320px; 349 | height: 240px; 350 | } 351 | 352 | #videolocal, div[id*='videoremote'] { 353 | width: 160px; 354 | } 355 | 356 | #videolocal img, #videolocal video, div[id*='videoremote'] img, div[id*='videoremote'] video { 357 | width: 160px; 358 | height: 120px; 359 | } 360 | } 361 | 362 | /* width 768px */ 363 | @media screen and (max-width: 768px) { 364 | .container { 365 | width: auto; 366 | } 367 | 368 | .chat-box { 369 | width: 300px; 370 | } 371 | 372 | #chatboxcontent { 373 | height: 300px; 374 | } 375 | 376 | #meetmeheader { 377 | width: 640px; 378 | } 379 | 380 | #meetmebox { 381 | width: 640px; 382 | } 383 | 384 | #meetmebox-videos { 385 | width: 640px; 386 | height: 240px; 387 | overflow-y: visible; 388 | } 389 | 390 | #videofocus, #meetmebox-plug { 391 | width: 640px; 392 | height: 480px; 393 | } 394 | 395 | #videofocus img, #videofocus video { 396 | width: 640px; 397 | height: 480px; 398 | } 399 | 400 | #videolocal, div[id*='videoremote'] { 401 | width: 160px; 402 | } 403 | 404 | #videolocal img, #videolocal video, div[id*='videoremote'] img, div[id*='videoremote'] video { 405 | width: 160px; 406 | height: 120px; 407 | } 408 | } 409 | 410 | /* width 640px */ 411 | @media screen and (max-width: 640px) { 412 | .container { 413 | width: auto; 414 | } 415 | 416 | .chat-box { 417 | width: 240px; 418 | } 419 | 420 | #chatboxcontent { 421 | height: 240px; 422 | } 423 | 424 | #meetmeheader { 425 | width: 520px; 426 | } 427 | 428 | #meetmebox { 429 | width: 520px; 430 | } 431 | 432 | #meetmebox-videos { 433 | width: 520px; 434 | height: 390px; 435 | overflow-y: visible; 436 | } 437 | 438 | #videofocus, #meetmebox-plug { 439 | width: 520px; 440 | height: 390px; 441 | } 442 | 443 | #videofocus img, #videofocus video { 444 | width: 520px; 445 | height: 390px; 446 | } 447 | 448 | #videolocal, div[id*='videoremote'] { 449 | width: 130px; 450 | } 451 | 452 | #videolocal img, #videolocal video, div[id*='videoremote'] img, div[id*='videoremote'] video { 453 | width: 130px; 454 | height: 97px; 455 | } 456 | } 457 | 458 | /* width 425px */ 459 | @media screen and (max-width: 425px) { 460 | .container { 461 | width: auto; 462 | } 463 | 464 | .chat-box { 465 | width: 240px; 466 | } 467 | 468 | #chatboxcontent { 469 | height: 240px; 470 | } 471 | 472 | #meetmeheader { 473 | width: 390px; 474 | } 475 | 476 | #meetmebox { 477 | width: 390px; 478 | } 479 | 480 | #meetmebox-videos { 481 | width: 390px; 482 | height: 292px; 483 | overflow-y: visible; 484 | } 485 | 486 | #videofocus, #meetmebox-plug { 487 | width: 390px; 488 | height: 292px; 489 | } 490 | 491 | #videofocus img, #videofocus video { 492 | width: 390px; 493 | height: 292px; 494 | } 495 | 496 | #videolocal, div[id*='videoremote'] { 497 | width: 130px; 498 | } 499 | 500 | #videolocal img, #videolocal video, div[id*='videoremote'] img, div[id*='videoremote'] video { 501 | width: 130px; 502 | height: 97px; 503 | } 504 | } 505 | 506 | /* width 384px */ 507 | @media screen and (max-width: 384px) { 508 | .container { 509 | width: auto; 510 | } 511 | 512 | .chat-box { 513 | width: 240px; 514 | } 515 | 516 | #chatboxcontent { 517 | height: 240px; 518 | } 519 | 520 | #meetmeheader { 521 | width: 320px; 522 | } 523 | 524 | #meetmebox { 525 | width: 320px; 526 | } 527 | 528 | #meetmebox-videos { 529 | width: 320px; 530 | height: 240px; 531 | overflow-y: visible; 532 | } 533 | 534 | #videofocus, #meetmebox-plug { 535 | width: 320px; 536 | height: 240px; 537 | } 538 | 539 | #videofocus img, #videofocus video { 540 | width: 320px; 541 | height: 240px; 542 | } 543 | 544 | #videolocal, div[id*='videoremote'] { 545 | width: 160px; 546 | } 547 | 548 | #videolocal img, #videolocal video, div[id*='videoremote'] img, div[id*='videoremote'] video { 549 | width: 160px; 550 | height: 120px; 551 | } 552 | } 553 | 554 | 555 | /* width 320px */ 556 | @media screen and (max-width: 320px) { 557 | .container { 558 | width: auto; 559 | } 560 | 561 | .chat-box { 562 | width: 240px; 563 | } 564 | 565 | #chatboxcontent { 566 | height: 240px; 567 | } 568 | 569 | #meetmeheader { 570 | width: 260px; 571 | } 572 | 573 | #meetmebox { 574 | width: 260px; 575 | } 576 | 577 | #meetmebox-videos { 578 | width: 260px; 579 | height: 195px; 580 | overflow-y: visible; 581 | } 582 | 583 | #videofocus, #meetmebox-plug { 584 | width: 260px; 585 | height: 195px; 586 | } 587 | 588 | #videofocus img, #videofocus video { 589 | width: 260px; 590 | height: 195px; 591 | } 592 | 593 | #videolocal, div[id*='videoremote'] { 594 | width: 130px; 595 | } 596 | 597 | #videolocal img, #videolocal video, div[id*='videoremote'] img, div[id*='videoremote'] video { 598 | width: 130px; 599 | height: 97px; 600 | } 601 | } 602 | -------------------------------------------------------------------------------- /public_html/meetme/js/meetme.js: -------------------------------------------------------------------------------- 1 | var janus = null; 2 | var mcu = null; 3 | 4 | var myDisplayName = null; 5 | var myRoomNumber = null; 6 | var myID = null; 7 | 8 | var feeds = []; 9 | var bitrateTimer = []; 10 | 11 | var isSpeakingId = null; 12 | 13 | var membercount = 0; 14 | 15 | var shortcut = null; 16 | 17 | $(document).ready(function() { 18 | 19 | // fixme anton - first thing first, set window title 20 | window.document.title = windowTitle; 21 | $('#servicename').html(windowTitle); 22 | 23 | // shortcut 24 | shortcut = $.url(1); 25 | if (shortcut.length > 0) { 26 | $('#joinroomnow #roomnumber').val(shortcut); 27 | //$('#joinroomnow #join').trigger('click'); 28 | } 29 | 30 | // Initialize the library (all console debuggers enabled) 31 | Janus.init({debug: debugLevel, callback: function() { 32 | $(this).attr('disabled', true).unbind('click'); 33 | 34 | // Make sure the browser supports WebRTC 35 | if(!Janus.isWebrtcSupported()) { 36 | bootbox.alert(labelNoWebRTC); 37 | return; 38 | } 39 | 40 | // fixme anton - confirm refresh 41 | window.onbeforeunload = function() { 42 | if (membercount > 0) { 43 | Janus.log("Confirmed unload"); 44 | return labelRefreshWarning; 45 | } 46 | } 47 | 48 | // fixme anton - original janus onbeforeunload 49 | window.onunload = function() { 50 | Janus.log("Closing window"); 51 | for(var s in Janus.sessions) { 52 | if(Janus.sessions[s] !== null && Janus.sessions[s] !== undefined && Janus.sessions[s].destroyOnUnload) { 53 | Janus.log("Destroying session " + s); 54 | Janus.sessions[s].destroy(); 55 | } 56 | } 57 | } 58 | 59 | // Create session 60 | janus = new Janus({ 61 | server: server, 62 | iceServers: iceServers, 63 | success: function() { 64 | // Attach to video room test plugin 65 | janus.attach({ 66 | plugin: "janus.plugin.videoroom", 67 | success: function(pluginHandle) { 68 | mcu = pluginHandle; 69 | Janus.log("Plugin attached! (" + mcu.getPlugin() + ", id=" + mcu.getId() + ")"); 70 | Janus.log(" -- This is a publisher/manager"); 71 | $('#joinroom').removeClass('hide').show(); 72 | $('#joinroomnow').removeClass('hide').show(); 73 | $('#join').click(joinRoomNumber); 74 | $('#displayname').focus(); 75 | }, 76 | error: function(error) { 77 | Janus.error(" -- Error attaching plugin...", error); 78 | bootbox.alert("Error attaching plugin... " + error); 79 | }, 80 | consentDialog: function(on) { 81 | // fixme anton - no need 82 | }, 83 | onmessage: function(msg, jsep) { 84 | Janus.debug(" ::: Got a message (publisher) :::"); 85 | Janus.debug("message: "+JSON.stringify(msg)); 86 | var event = msg["videoroom"]; 87 | Janus.debug("Event: " + event); 88 | if(event != undefined && event != null) { 89 | if(event === "joined") { 90 | // Publisher/manager created, negotiate WebRTC and attach to existing feeds, if any 91 | myID = msg["id"]; 92 | Janus.log("Successfully joined room " + msg["room"] + " with ID " + myID); 93 | publishOwnFeed(true); 94 | // Any new feed to attach to? 95 | if(msg["publishers"] !== undefined && msg["publishers"] !== null) { 96 | var list = msg["publishers"]; 97 | Janus.debug("Got a list of available publishers/feeds:"); 98 | Janus.debug(list); 99 | for(var f in list) { 100 | var id = list[f]["id"]; 101 | var display = list[f]["display"]; 102 | Janus.debug(" >> [" + id + "] " + display); 103 | newRemoteFeed(id, display) 104 | } 105 | } 106 | } else if(event === "destroyed") { 107 | // The room has been destroyed 108 | Janus.warn("The room has been destroyed!"); 109 | bootbox.alert(error, function() { 110 | membercount = 0; 111 | window.location.reload(); 112 | }); 113 | } else if(event === "event") { 114 | // Any new feed to attach to? 115 | if(msg["publishers"] !== undefined && msg["publishers"] !== null) { 116 | var list = msg["publishers"]; 117 | Janus.debug("Got a list of available publishers/feeds:"); 118 | Janus.debug(list); 119 | for(var f in list) { 120 | var id = list[f]["id"]; 121 | var display = list[f]["display"]; 122 | Janus.debug(" >> [" + id + "] " + display); 123 | newRemoteFeed(id, display) 124 | } 125 | } else if(msg["leaving"] !== undefined && msg["leaving"] !== null) { 126 | // One of the publishers has gone away? 127 | var leaving = msg["leaving"]; 128 | Janus.log("Publisher left: " + leaving); 129 | var remoteFeed = null; 130 | for(var i=1; i'); 190 | // Add a 'displayname' label 191 | $('#videolocal').append(''+myDisplayName+''); 192 | // Add an 'unpublish' button 193 | $('#unpublish').removeClass('hide').html(labelStopPublishing).click(unpublishOwnFeed); 194 | // Add a 'mute' button 195 | $('#mute').removeClass('hide').append(labelMuteOn).click(toggleMute) 196 | // Add a 'pause' button 197 | $('#pause').removeClass('hide').append(labelPauseOn).click(togglePause) 198 | // fixme anton - starts muted 199 | toggleMute(); 200 | // Add welcome notif 201 | $('#roomdesc').removeClass().addClass('label label-default').html(labelRoomNumber+myRoomNumber); 202 | // Add plugs 203 | $('#meetmebox-plug').append(''); 204 | // set publisher video as large video 205 | setLargeVideo('videolocal'); 206 | } 207 | // $('#publisher').removeClass('hide').html(myDisplayName).show(); 208 | attachMediaStream($('#myvideo').get(0), stream); 209 | $("#myvideo").get(0).muted = "muted"; 210 | var videoTracks = stream.getVideoTracks(); 211 | if(videoTracks === null || videoTracks === undefined || videoTracks.length === 0) { 212 | // No webcam 213 | $('#myvideo').hide(); 214 | $('#videolocal').append('
'+labelNoWebcam+'
'); 215 | } 216 | membercount++; 217 | // fixme anton - dont flash on localstream it will obstruct flashes on remotestream 218 | //flashTitle(membercount); 219 | }, 220 | ondataopen: function(data) { 221 | Janus.log("The DataChannel is available!"); 222 | $("#statusDataChannel").html("Ready"); 223 | 224 | $('#chat-box').show(); 225 | }, 226 | onremotestream: function(stream) { 227 | // The publisher stream is sendonly, we don't expect anything here 228 | }, 229 | oncleanup: function() { 230 | Janus.log(" ::: Got a cleanup notification: we are unpublished now :::"); 231 | // fixme anton - just reload the window 232 | membercount = 0; 233 | window.location.reload(); 234 | //membercount--; 235 | //flashTitle(membercount); 236 | //$('#videolocal').html('
'+myDisplayName+'
',trigger:"hover focus",title:"",delay:0,html:!1,container:!1,viewport:{selector:"body",padding:0}},c.prototype.init=function(b,c,d){if(this.enabled=!0,this.type=b,this.$element=a(c),this.options=this.getOptions(d),this.$viewport=this.options.viewport&&a(a.isFunction(this.options.viewport)?this.options.viewport.call(this,this.$element):this.options.viewport.selector||this.options.viewport),this.inState={click:!1,hover:!1,focus:!1},this.$element[0]instanceof document.constructor&&!this.options.selector)throw new Error("`selector` option must be specified when initializing "+this.type+" on the window.document object!");for(var e=this.options.trigger.split(" "),f=e.length;f--;){var g=e[f];if("click"==g)this.$element.on("click."+this.type,this.options.selector,a.proxy(this.toggle,this));else if("manual"!=g){var h="hover"==g?"mouseenter":"focusin",i="hover"==g?"mouseleave":"focusout";this.$element.on(h+"."+this.type,this.options.selector,a.proxy(this.enter,this)),this.$element.on(i+"."+this.type,this.options.selector,a.proxy(this.leave,this))}}this.options.selector?this._options=a.extend({},this.options,{trigger:"manual",selector:""}):this.fixTitle()},c.prototype.getDefaults=function(){return c.DEFAULTS},c.prototype.getOptions=function(b){return b=a.extend({},this.getDefaults(),this.$element.data(),b),b.delay&&"number"==typeof b.delay&&(b.delay={show:b.delay,hide:b.delay}),b},c.prototype.getDelegateOptions=function(){var b={},c=this.getDefaults();return this._options&&a.each(this._options,function(a,d){c[a]!=d&&(b[a]=d)}),b},c.prototype.enter=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget).data("bs."+this.type);return c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c)),b instanceof a.Event&&(c.inState["focusin"==b.type?"focus":"hover"]=!0),c.tip().hasClass("in")||"in"==c.hoverState?void(c.hoverState="in"):(clearTimeout(c.timeout),c.hoverState="in",c.options.delay&&c.options.delay.show?void(c.timeout=setTimeout(function(){"in"==c.hoverState&&c.show()},c.options.delay.show)):c.show())},c.prototype.isInStateTrue=function(){for(var a in this.inState)if(this.inState[a])return!0;return!1},c.prototype.leave=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget).data("bs."+this.type);return c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c)),b instanceof a.Event&&(c.inState["focusout"==b.type?"focus":"hover"]=!1),c.isInStateTrue()?void 0:(clearTimeout(c.timeout),c.hoverState="out",c.options.delay&&c.options.delay.hide?void(c.timeout=setTimeout(function(){"out"==c.hoverState&&c.hide()},c.options.delay.hide)):c.hide())},c.prototype.show=function(){var b=a.Event("show.bs."+this.type);if(this.hasContent()&&this.enabled){this.$element.trigger(b);var d=a.contains(this.$element[0].ownerDocument.documentElement,this.$element[0]);if(b.isDefaultPrevented()||!d)return;var e=this,f=this.tip(),g=this.getUID(this.type);this.setContent(),f.attr("id",g),this.$element.attr("aria-describedby",g),this.options.animation&&f.addClass("fade");var h="function"==typeof this.options.placement?this.options.placement.call(this,f[0],this.$element[0]):this.options.placement,i=/\s?auto?\s?/i,j=i.test(h);j&&(h=h.replace(i,"")||"top"),f.detach().css({top:0,left:0,display:"block"}).addClass(h).data("bs."+this.type,this),this.options.container?f.appendTo(this.options.container):f.insertAfter(this.$element),this.$element.trigger("inserted.bs."+this.type);var k=this.getPosition(),l=f[0].offsetWidth,m=f[0].offsetHeight;if(j){var n=h,o=this.getPosition(this.$viewport);h="bottom"==h&&k.bottom+m>o.bottom?"top":"top"==h&&k.top-mo.width?"left":"left"==h&&k.left-lg.top+g.height&&(e.top=g.top+g.height-i)}else{var j=b.left-f,k=b.left+f+c;jg.right&&(e.left=g.left+g.width-k)}return e},c.prototype.getTitle=function(){var a,b=this.$element,c=this.options;return a=b.attr("data-original-title")||("function"==typeof c.title?c.title.call(b[0]):c.title)},c.prototype.getUID=function(a){do a+=~~(1e6*Math.random());while(document.getElementById(a));return a},c.prototype.tip=function(){if(!this.$tip&&(this.$tip=a(this.options.template),1!=this.$tip.length))throw new Error(this.type+" `template` option must consist of exactly 1 top-level element!");return this.$tip},c.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".tooltip-arrow")},c.prototype.enable=function(){this.enabled=!0},c.prototype.disable=function(){this.enabled=!1},c.prototype.toggleEnabled=function(){this.enabled=!this.enabled},c.prototype.toggle=function(b){var c=this;b&&(c=a(b.currentTarget).data("bs."+this.type),c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c))),b?(c.inState.click=!c.inState.click,c.isInStateTrue()?c.enter(c):c.leave(c)):c.tip().hasClass("in")?c.leave(c):c.enter(c)},c.prototype.destroy=function(){var a=this;clearTimeout(this.timeout),this.hide(function(){a.$element.off("."+a.type).removeData("bs."+a.type),a.$tip&&a.$tip.detach(),a.$tip=null,a.$arrow=null,a.$viewport=null})};var d=a.fn.tooltip;a.fn.tooltip=b,a.fn.tooltip.Constructor=c,a.fn.tooltip.noConflict=function(){return a.fn.tooltip=d,this}}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.popover"),f="object"==typeof b&&b;(e||!/destroy|hide/.test(b))&&(e||d.data("bs.popover",e=new c(this,f)),"string"==typeof b&&e[b]())})}var c=function(a,b){this.init("popover",a,b)};if(!a.fn.tooltip)throw new Error("Popover requires tooltip.js");c.VERSION="3.3.6",c.DEFAULTS=a.extend({},a.fn.tooltip.Constructor.DEFAULTS,{placement:"right",trigger:"click",content:"",template:''}),c.prototype=a.extend({},a.fn.tooltip.Constructor.prototype),c.prototype.constructor=c,c.prototype.getDefaults=function(){return c.DEFAULTS},c.prototype.setContent=function(){var a=this.tip(),b=this.getTitle(),c=this.getContent();a.find(".popover-title")[this.options.html?"html":"text"](b),a.find(".popover-content").children().detach().end()[this.options.html?"string"==typeof c?"html":"append":"text"](c),a.removeClass("fade top bottom left right in"),a.find(".popover-title").html()||a.find(".popover-title").hide()},c.prototype.hasContent=function(){return this.getTitle()||this.getContent()},c.prototype.getContent=function(){var a=this.$element,b=this.options;return a.attr("data-content")||("function"==typeof b.content?b.content.call(a[0]):b.content)},c.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".arrow")};var d=a.fn.popover;a.fn.popover=b,a.fn.popover.Constructor=c,a.fn.popover.noConflict=function(){return a.fn.popover=d,this}}(jQuery),+function(a){"use strict";function b(c,d){this.$body=a(document.body),this.$scrollElement=a(a(c).is(document.body)?window:c),this.options=a.extend({},b.DEFAULTS,d),this.selector=(this.options.target||"")+" .nav li > a",this.offsets=[],this.targets=[],this.activeTarget=null,this.scrollHeight=0,this.$scrollElement.on("scroll.bs.scrollspy",a.proxy(this.process,this)),this.refresh(),this.process()}function c(c){return this.each(function(){var d=a(this),e=d.data("bs.scrollspy"),f="object"==typeof c&&c;e||d.data("bs.scrollspy",e=new b(this,f)),"string"==typeof c&&e[c]()})}b.VERSION="3.3.6",b.DEFAULTS={offset:10},b.prototype.getScrollHeight=function(){return this.$scrollElement[0].scrollHeight||Math.max(this.$body[0].scrollHeight,document.documentElement.scrollHeight)},b.prototype.refresh=function(){var b=this,c="offset",d=0;this.offsets=[],this.targets=[],this.scrollHeight=this.getScrollHeight(),a.isWindow(this.$scrollElement[0])||(c="position",d=this.$scrollElement.scrollTop()),this.$body.find(this.selector).map(function(){var b=a(this),e=b.data("target")||b.attr("href"),f=/^#./.test(e)&&a(e);return f&&f.length&&f.is(":visible")&&[[f[c]().top+d,e]]||null}).sort(function(a,b){return a[0]-b[0]}).each(function(){b.offsets.push(this[0]),b.targets.push(this[1])})},b.prototype.process=function(){var a,b=this.$scrollElement.scrollTop()+this.options.offset,c=this.getScrollHeight(),d=this.options.offset+c-this.$scrollElement.height(),e=this.offsets,f=this.targets,g=this.activeTarget;if(this.scrollHeight!=c&&this.refresh(),b>=d)return g!=(a=f[f.length-1])&&this.activate(a);if(g&&b=e[a]&&(void 0===e[a+1]||b .dropdown-menu > .active").removeClass("active").end().find('[data-toggle="tab"]').attr("aria-expanded",!1),b.addClass("active").find('[data-toggle="tab"]').attr("aria-expanded",!0),h?(b[0].offsetWidth,b.addClass("in")):b.removeClass("fade"),b.parent(".dropdown-menu").length&&b.closest("li.dropdown").addClass("active").end().find('[data-toggle="tab"]').attr("aria-expanded",!0),e&&e()}var g=d.find("> .active"),h=e&&a.support.transition&&(g.length&&g.hasClass("fade")||!!d.find("> .fade").length);g.length&&h?g.one("bsTransitionEnd",f).emulateTransitionEnd(c.TRANSITION_DURATION):f(),g.removeClass("in")};var d=a.fn.tab;a.fn.tab=b,a.fn.tab.Constructor=c,a.fn.tab.noConflict=function(){return a.fn.tab=d,this};var e=function(c){c.preventDefault(),b.call(a(this),"show")};a(document).on("click.bs.tab.data-api",'[data-toggle="tab"]',e).on("click.bs.tab.data-api",'[data-toggle="pill"]',e)}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.affix"),f="object"==typeof b&&b;e||d.data("bs.affix",e=new c(this,f)),"string"==typeof b&&e[b]()})}var c=function(b,d){this.options=a.extend({},c.DEFAULTS,d),this.$target=a(this.options.target).on("scroll.bs.affix.data-api",a.proxy(this.checkPosition,this)).on("click.bs.affix.data-api",a.proxy(this.checkPositionWithEventLoop,this)),this.$element=a(b),this.affixed=null,this.unpin=null,this.pinnedOffset=null,this.checkPosition()};c.VERSION="3.3.6",c.RESET="affix affix-top affix-bottom",c.DEFAULTS={offset:0,target:window},c.prototype.getState=function(a,b,c,d){var e=this.$target.scrollTop(),f=this.$element.offset(),g=this.$target.height();if(null!=c&&"top"==this.affixed)return c>e?"top":!1;if("bottom"==this.affixed)return null!=c?e+this.unpin<=f.top?!1:"bottom":a-d>=e+g?!1:"bottom";var h=null==this.affixed,i=h?e:f.top,j=h?g:b;return null!=c&&c>=e?"top":null!=d&&i+j>=a-d?"bottom":!1},c.prototype.getPinnedOffset=function(){if(this.pinnedOffset)return this.pinnedOffset;this.$element.removeClass(c.RESET).addClass("affix");var a=this.$target.scrollTop(),b=this.$element.offset();return this.pinnedOffset=b.top-a},c.prototype.checkPositionWithEventLoop=function(){setTimeout(a.proxy(this.checkPosition,this),1)},c.prototype.checkPosition=function(){if(this.$element.is(":visible")){var b=this.$element.height(),d=this.options.offset,e=d.top,f=d.bottom,g=Math.max(a(document).height(),a(document.body).height());"object"!=typeof d&&(f=e=d),"function"==typeof e&&(e=d.top(this.$element)),"function"==typeof f&&(f=d.bottom(this.$element));var h=this.getState(g,b,e,f);if(this.affixed!=h){null!=this.unpin&&this.$element.css("top","");var i="affix"+(h?"-"+h:""),j=a.Event(i+".bs.affix");if(this.$element.trigger(j),j.isDefaultPrevented())return;this.affixed=h,this.unpin="bottom"==h?this.getPinnedOffset():null,this.$element.removeClass(c.RESET).addClass(i).trigger(i.replace("affix","affixed")+".bs.affix")}"bottom"==h&&this.$element.offset({top:g-b-f})}};var d=a.fn.affix;a.fn.affix=b,a.fn.affix.Constructor=c,a.fn.affix.noConflict=function(){return a.fn.affix=d,this},a(window).on("load",function(){a('[data-spy="affix"]').each(function(){var c=a(this),d=c.data();d.offset=d.offset||{},null!=d.offsetBottom&&(d.offset.bottom=d.offsetBottom),null!=d.offsetTop&&(d.offset.top=d.offsetTop),b.call(c,d)})})}(jQuery); -------------------------------------------------------------------------------- /public_html/meetme/js/adapter.min.js: -------------------------------------------------------------------------------- 1 | /*! adapterjs - v0.13.2 - 2016-03-18 */ 2 | function trace(text){if("\n"===text[text.length-1]&&(text=text.substring(0,text.length-1)),window.performance){var now=(window.performance.now()/1e3).toFixed(3);webrtcUtils.log(now+": "+text)}else webrtcUtils.log(text)}function requestUserMedia(constraints){return new Promise(function(resolve,reject){getUserMedia(constraints,resolve,reject)})}var AdapterJS=AdapterJS||{};if("undefined"!=typeof exports&&(module.exports=AdapterJS),AdapterJS.options=AdapterJS.options||{},AdapterJS.VERSION="0.13.2",AdapterJS.onwebrtcready=AdapterJS.onwebrtcready||function(isUsingPlugin){},AdapterJS._onwebrtcreadies=[],AdapterJS.webRTCReady=function(callback){if("function"!=typeof callback)throw new Error("Callback provided is not a function");!0===AdapterJS.onwebrtcreadyDone?callback(null!==AdapterJS.WebRTCPlugin.plugin):AdapterJS._onwebrtcreadies.push(callback)},AdapterJS.WebRTCPlugin=AdapterJS.WebRTCPlugin||{},AdapterJS.WebRTCPlugin.pluginInfo={prefix:"Tem",plugName:"TemWebRTCPlugin",pluginId:"plugin0",type:"application/x-temwebrtcplugin",onload:"__TemWebRTCReady0",portalLink:"http://skylink.io/plugin/",downloadLink:null,companyName:"Temasys"},navigator.platform.match(/^Mac/i)?AdapterJS.WebRTCPlugin.pluginInfo.downloadLink="http://bit.ly/1n77hco":navigator.platform.match(/^Win/i)&&(AdapterJS.WebRTCPlugin.pluginInfo.downloadLink="http://bit.ly/1kkS4FN"),AdapterJS.WebRTCPlugin.TAGS={NONE:"none",AUDIO:"audio",VIDEO:"video"},AdapterJS.WebRTCPlugin.pageId=Math.random().toString(36).slice(2),AdapterJS.WebRTCPlugin.plugin=null,AdapterJS.WebRTCPlugin.setLogLevel=null,AdapterJS.WebRTCPlugin.defineWebRTCInterface=null,AdapterJS.WebRTCPlugin.isPluginInstalled=null,AdapterJS.WebRTCPlugin.pluginInjectionInterval=null,AdapterJS.WebRTCPlugin.injectPlugin=null,AdapterJS.WebRTCPlugin.PLUGIN_STATES={NONE:0,INITIALIZING:1,INJECTING:2,INJECTED:3,READY:4},AdapterJS.WebRTCPlugin.pluginState=AdapterJS.WebRTCPlugin.PLUGIN_STATES.NONE,AdapterJS.onwebrtcreadyDone=!1,AdapterJS.WebRTCPlugin.PLUGIN_LOG_LEVELS={NONE:"NONE",ERROR:"ERROR",WARNING:"WARNING",INFO:"INFO",VERBOSE:"VERBOSE",SENSITIVE:"SENSITIVE"},AdapterJS.WebRTCPlugin.WaitForPluginReady=null,AdapterJS.WebRTCPlugin.callWhenPluginReady=null,__TemWebRTCReady0=function(){if("complete"===document.readyState)AdapterJS.WebRTCPlugin.pluginState=AdapterJS.WebRTCPlugin.PLUGIN_STATES.READY,AdapterJS.maybeThroughWebRTCReady();else var timer=setInterval(function(){"complete"===document.readyState&&(clearInterval(timer),AdapterJS.WebRTCPlugin.pluginState=AdapterJS.WebRTCPlugin.PLUGIN_STATES.READY,AdapterJS.maybeThroughWebRTCReady())},100)},AdapterJS.maybeThroughWebRTCReady=function(){AdapterJS.onwebrtcreadyDone||(AdapterJS.onwebrtcreadyDone=!0,AdapterJS._onwebrtcreadies.length?AdapterJS._onwebrtcreadies.forEach(function(callback){"function"==typeof callback&&callback(null!==AdapterJS.WebRTCPlugin.plugin)}):"function"==typeof AdapterJS.onwebrtcready&&AdapterJS.onwebrtcready(null!==AdapterJS.WebRTCPlugin.plugin))},AdapterJS.TEXT={PLUGIN:{REQUIRE_INSTALLATION:"This website requires you to install a WebRTC-enabling plugin to work on this browser.",NOT_SUPPORTED:"Your browser does not support WebRTC.",BUTTON:"Install Now"},REFRESH:{REQUIRE_REFRESH:"Please refresh page",BUTTON:"Refresh Page"}},AdapterJS._iceConnectionStates={starting:"starting",checking:"checking",connected:"connected",completed:"connected",done:"completed",disconnected:"disconnected",failed:"failed",closed:"closed"},AdapterJS._iceConnectionFiredStates=[],AdapterJS.isDefined=null,AdapterJS.parseWebrtcDetectedBrowser=function(){var hasMatch=null;window.opr&&opr.addons||window.opera||navigator.userAgent.indexOf(" OPR/")>=0?(webrtcDetectedBrowser="opera",webrtcDetectedType="webkit",webrtcMinimumVersion=26,hasMatch=/OPR\/(\d+)/i.exec(navigator.userAgent)||[],webrtcDetectedVersion=parseInt(hasMatch[1],10)):"undefined"!=typeof InstallTrigger?webrtcDetectedType="moz":Object.prototype.toString.call(window.HTMLElement).indexOf("Constructor")>0?(webrtcDetectedBrowser="safari",webrtcDetectedType="plugin",webrtcMinimumVersion=7,hasMatch=/version\/(\d+)/i.exec(navigator.userAgent)||[],webrtcDetectedVersion=parseInt(hasMatch[1],10)):document.documentMode?(webrtcDetectedBrowser="IE",webrtcDetectedType="plugin",webrtcMinimumVersion=9,hasMatch=/\brv[ :]+(\d+)/g.exec(navigator.userAgent)||[],webrtcDetectedVersion=parseInt(hasMatch[1]||"0",10),webrtcDetectedVersion||(hasMatch=/\bMSIE[ :]+(\d+)/g.exec(navigator.userAgent)||[],webrtcDetectedVersion=parseInt(hasMatch[1]||"0",10))):window.StyleMedia?webrtcDetectedType="":window.chrome&&window.chrome.webstore?webrtcDetectedType="webkit":"chrome"!==webrtcDetectedBrowser&&"opera"!==webrtcDetectedBrowser||!window.CSS||(webrtcDetectedBrowser="blink"),window.webrtcDetectedBrowser=webrtcDetectedBrowser,window.webrtcDetectedVersion=webrtcDetectedVersion,window.webrtcMinimumVersion=webrtcMinimumVersion},AdapterJS.addEvent=function(elem,evnt,func){elem.addEventListener?elem.addEventListener(evnt,func,!1):elem.attachEvent?elem.attachEvent("on"+evnt,func):elem[evnt]=func},AdapterJS.renderNotificationBar=function(text,buttonText,buttonLink,openNewTab,displayRefreshBar){if("complete"===document.readyState){var w=window,i=document.createElement("iframe");i.name="adapterjs-alert",i.style.position="fixed",i.style.top="-41px",i.style.left=0,i.style.right=0,i.style.width="100%",i.style.height="40px",i.style.backgroundColor="#ffffe1",i.style.border="none",i.style.borderBottom="1px solid #888888",i.style.zIndex="9999999","string"==typeof i.style.webkitTransition?i.style.webkitTransition="all .5s ease-out":"string"==typeof i.style.transition&&(i.style.transition="all .5s ease-out"),document.body.appendChild(i);var c=i.contentWindow?i.contentWindow:i.contentDocument.document?i.contentDocument.document:i.contentDocument;c.document.open(),c.document.write(''+text+""),buttonText&&buttonLink?(c.document.write(''),c.document.close(),AdapterJS.addEvent(c.document.getElementById("okay"),"click",function(e){displayRefreshBar&&AdapterJS.renderNotificationBar(AdapterJS.TEXT.EXTENSION?AdapterJS.TEXT.EXTENSION.REQUIRE_REFRESH:AdapterJS.TEXT.REFRESH.REQUIRE_REFRESH,AdapterJS.TEXT.REFRESH.BUTTON,"javascript:location.reload()"),window.open(buttonLink,openNewTab?"_blank":"_top"),e.preventDefault();try{e.cancelBubble=!0}catch(error){}var pluginInstallInterval=setInterval(function(){isIE||navigator.plugins.refresh(!1),AdapterJS.WebRTCPlugin.isPluginInstalled(AdapterJS.WebRTCPlugin.pluginInfo.prefix,AdapterJS.WebRTCPlugin.pluginInfo.plugName,function(){clearInterval(pluginInstallInterval),AdapterJS.WebRTCPlugin.defineWebRTCInterface()},function(){})},500)}),AdapterJS.addEvent(c.document.getElementById("cancel"),"click",function(e){w.document.body.removeChild(i)})):c.document.close(),setTimeout(function(){"string"==typeof i.style.webkitTransform?i.style.webkitTransform="translateY(40px)":"string"==typeof i.style.transform?i.style.transform="translateY(40px)":i.style.top="0px"},300)}},webrtcDetectedType=null,checkMediaDataChannelSettings=function(peerBrowserAgent,peerBrowserVersion,callback,constraints){if("function"==typeof callback){var beOfferer=!0,isLocalFirefox="firefox"===webrtcDetectedBrowser,isLocalFirefoxInterop="moz"===webrtcDetectedType&&webrtcDetectedVersion>30,isPeerFirefox="firefox"===peerBrowserAgent;if(isLocalFirefox&&isPeerFirefox||isLocalFirefoxInterop)try{delete constraints.mandatory.MozDontOfferDataChannel}catch(error){}else isLocalFirefox&&!isPeerFirefox&&(constraints.mandatory.MozDontOfferDataChannel=!0);if(!isLocalFirefox)for(var prop in constraints.mandatory)constraints.mandatory.hasOwnProperty(prop)&&-1!==prop.indexOf("Moz")&&delete constraints.mandatory[prop];!isLocalFirefox||isPeerFirefox||isLocalFirefoxInterop||(beOfferer=!1),callback(beOfferer,constraints)}},checkIceConnectionState=function(peerId,iceConnectionState,callback){"function"==typeof callback&&(peerId=peerId?peerId:"peer",AdapterJS._iceConnectionFiredStates[peerId]&&iceConnectionState!==AdapterJS._iceConnectionStates.disconnected&&iceConnectionState!==AdapterJS._iceConnectionStates.failed&&iceConnectionState!==AdapterJS._iceConnectionStates.closed||(AdapterJS._iceConnectionFiredStates[peerId]=[]),iceConnectionState=AdapterJS._iceConnectionStates[iceConnectionState],AdapterJS._iceConnectionFiredStates[peerId].indexOf(iceConnectionState)<0&&(AdapterJS._iceConnectionFiredStates[peerId].push(iceConnectionState),iceConnectionState===AdapterJS._iceConnectionStates.connected&&setTimeout(function(){AdapterJS._iceConnectionFiredStates[peerId].push(AdapterJS._iceConnectionStates.done),callback(AdapterJS._iceConnectionStates.done)},1e3),callback(iceConnectionState)))},createIceServer=null,createIceServers=null,RTCPeerConnection=null,RTCSessionDescription="function"==typeof RTCSessionDescription?RTCSessionDescription:null,RTCIceCandidate="function"==typeof RTCIceCandidate?RTCIceCandidate:null,getUserMedia=null,attachMediaStream=null,reattachMediaStream=null,webrtcDetectedBrowser=null,webrtcDetectedVersion=null,webrtcMinimumVersion=null,navigator.mozGetUserMedia||navigator.webkitGetUserMedia||navigator.mediaDevices&&navigator.userAgent.match(/Edge\/(\d+).(\d+)$/)){var getUserMedia=null,attachMediaStream=null,reattachMediaStream=null,webrtcDetectedBrowser=null,webrtcDetectedVersion=null,webrtcMinimumVersion=null,webrtcUtils={log:function(){"undefined"!=typeof module||"function"==typeof require&&"function"==typeof define},extractVersion:function(uastring,expr,pos){var match=uastring.match(expr);return match&&match.length>=pos&&parseInt(match[pos],10)}};if("object"==typeof window&&(!window.HTMLMediaElement||"srcObject"in window.HTMLMediaElement.prototype||Object.defineProperty(window.HTMLMediaElement.prototype,"srcObject",{get:function(){return"mozSrcObject"in this?this.mozSrcObject:this._srcObject},set:function(stream){"mozSrcObject"in this?this.mozSrcObject=stream:(this._srcObject=stream,this.src=URL.createObjectURL(stream))}}),getUserMedia=window.navigator&&window.navigator.getUserMedia),attachMediaStream=function(element,stream){element.srcObject=stream},reattachMediaStream=function(to,from){to.srcObject=from.srcObject},"undefined"!=typeof window&&window.navigator)if(navigator.mozGetUserMedia){if(webrtcUtils.log("This appears to be Firefox"),webrtcDetectedBrowser="firefox",webrtcDetectedVersion=webrtcUtils.extractVersion(navigator.userAgent,/Firefox\/([0-9]+)\./,1),webrtcMinimumVersion=31,window.RTCPeerConnection||(window.RTCPeerConnection=function(pcConfig,pcConstraints){if(38>webrtcDetectedVersion&&pcConfig&&pcConfig.iceServers){for(var newIceServers=[],i=0;iwebrtcDetectedVersion&&(webrtcUtils.log("spec: "+JSON.stringify(constraints)),constraints.audio&&(constraints.audio=constraintsToFF37(constraints.audio)),constraints.video&&(constraints.video=constraintsToFF37(constraints.video)),webrtcUtils.log("ff37: "+JSON.stringify(constraints))),navigator.mozGetUserMedia(constraints,onSuccess,onError)},navigator.getUserMedia=getUserMedia,navigator.mediaDevices||(navigator.mediaDevices={getUserMedia:requestUserMedia,addEventListener:function(){},removeEventListener:function(){}}),navigator.mediaDevices.enumerateDevices=navigator.mediaDevices.enumerateDevices||function(){return new Promise(function(resolve){var infos=[{kind:"audioinput",deviceId:"default",label:"",groupId:""},{kind:"videoinput",deviceId:"default",label:"",groupId:""}];resolve(infos)})},41>webrtcDetectedVersion){var orgEnumerateDevices=navigator.mediaDevices.enumerateDevices.bind(navigator.mediaDevices);navigator.mediaDevices.enumerateDevices=function(){return orgEnumerateDevices().then(void 0,function(e){if("NotFoundError"===e.name)return[];throw e})}}}else if(navigator.webkitGetUserMedia&&window.webkitRTCPeerConnection){webrtcUtils.log("This appears to be Chrome"),webrtcDetectedBrowser="chrome",webrtcDetectedVersion=webrtcUtils.extractVersion(navigator.userAgent,/Chrom(e|ium)\/([0-9]+)\./,2),webrtcMinimumVersion=38,window.RTCPeerConnection=function(pcConfig,pcConstraints){pcConfig&&pcConfig.iceTransportPolicy&&(pcConfig.iceTransports=pcConfig.iceTransportPolicy);var pc=new webkitRTCPeerConnection(pcConfig,pcConstraints),origGetStats=pc.getStats.bind(pc);return pc.getStats=function(selector,successCallback,errorCallback){var self=this,args=arguments;if(arguments.length>0&&"function"==typeof selector)return origGetStats(selector,successCallback);var fixChromeStats=function(response){var standardReport={},reports=response.result();return reports.forEach(function(report){var standardStats={id:report.id,timestamp:report.timestamp,type:report.type};report.names().forEach(function(name){standardStats[name]=report.stat(name)}),standardReport[standardStats.id]=standardStats}),standardReport};if(arguments.length>=2){var successCallbackWrapper=function(response){args[1](fixChromeStats(response))};return origGetStats.apply(this,[successCallbackWrapper,arguments[0]])}return new Promise(function(resolve,reject){1===args.length&&null===selector?origGetStats.apply(self,[function(response){resolve.apply(null,[fixChromeStats(response)])},reject]):origGetStats.apply(self,[resolve,reject])})},pc},webkitRTCPeerConnection.generateCertificate&&Object.defineProperty(window.RTCPeerConnection,"generateCertificate",{get:function(){return arguments.length?webkitRTCPeerConnection.generateCertificate.apply(null,arguments):webkitRTCPeerConnection.generateCertificate}}),["createOffer","createAnswer"].forEach(function(method){var nativeMethod=webkitRTCPeerConnection.prototype[method];webkitRTCPeerConnection.prototype[method]=function(){var self=this;if(arguments.length<1||1===arguments.length&&"object"==typeof arguments[0]){var opts=1===arguments.length?arguments[0]:void 0;return new Promise(function(resolve,reject){nativeMethod.apply(self,[resolve,reject,opts])})}return nativeMethod.apply(this,arguments)}}),["setLocalDescription","setRemoteDescription","addIceCandidate"].forEach(function(method){var nativeMethod=webkitRTCPeerConnection.prototype[method];webkitRTCPeerConnection.prototype[method]=function(){var args=arguments,self=this;return new Promise(function(resolve,reject){nativeMethod.apply(self,[args[0],function(){resolve(),args.length>=2&&args[1].apply(null,[])},function(err){reject(err),args.length>=3&&args[2].apply(null,[err])}])})}});var constraintsToChrome=function(c){if("object"!=typeof c||c.mandatory||c.optional)return c;var cc={};return Object.keys(c).forEach(function(key){if("require"!==key&&"advanced"!==key&&"mediaSource"!==key){var r="object"==typeof c[key]?c[key]:{ideal:c[key]};void 0!==r.exact&&"number"==typeof r.exact&&(r.min=r.max=r.exact);var oldname=function(prefix,name){return prefix?prefix+name.charAt(0).toUpperCase()+name.slice(1):"deviceId"===name?"sourceId":name};if(void 0!==r.ideal){cc.optional=cc.optional||[];var oc={};"number"==typeof r.ideal?(oc[oldname("min",key)]=r.ideal,cc.optional.push(oc),oc={},oc[oldname("max",key)]=r.ideal,cc.optional.push(oc)):(oc[oldname("",key)]=r.ideal,cc.optional.push(oc))}void 0!==r.exact&&"number"!=typeof r.exact?(cc.mandatory=cc.mandatory||{},cc.mandatory[oldname("",key)]=r.exact):["min","max"].forEach(function(mix){void 0!==r[mix]&&(cc.mandatory=cc.mandatory||{},cc.mandatory[oldname(mix,key)]=r[mix])})}}),c.advanced&&(cc.optional=(cc.optional||[]).concat(c.advanced)),cc};if(getUserMedia=function(constraints,onSuccess,onError){return constraints.audio&&(constraints.audio=constraintsToChrome(constraints.audio)),constraints.video&&(constraints.video=constraintsToChrome(constraints.video)),webrtcUtils.log("chrome: "+JSON.stringify(constraints)),navigator.webkitGetUserMedia(constraints,onSuccess,onError)},navigator.getUserMedia=getUserMedia,navigator.mediaDevices||(navigator.mediaDevices={getUserMedia:requestUserMedia,enumerateDevices:function(){return new Promise(function(resolve){var kinds={audio:"audioinput",video:"videoinput"};return MediaStreamTrack.getSources(function(devices){resolve(devices.map(function(device){return{label:device.label,kind:kinds[device.kind],deviceId:device.id,groupId:""}}))})})}}),navigator.mediaDevices.getUserMedia){var origGetUserMedia=navigator.mediaDevices.getUserMedia.bind(navigator.mediaDevices);navigator.mediaDevices.getUserMedia=function(c){return webrtcUtils.log("spec: "+JSON.stringify(c)),c.audio=constraintsToChrome(c.audio),c.video=constraintsToChrome(c.video),webrtcUtils.log("chrome: "+JSON.stringify(c)),origGetUserMedia(c)}}else navigator.mediaDevices.getUserMedia=function(constraints){return requestUserMedia(constraints)};"undefined"==typeof navigator.mediaDevices.addEventListener&&(navigator.mediaDevices.addEventListener=function(){webrtcUtils.log("Dummy mediaDevices.addEventListener called.")}),"undefined"==typeof navigator.mediaDevices.removeEventListener&&(navigator.mediaDevices.removeEventListener=function(){webrtcUtils.log("Dummy mediaDevices.removeEventListener called.")}),attachMediaStream=function(element,stream){webrtcDetectedVersion>=43?element.srcObject=stream:"undefined"!=typeof element.src?element.src=URL.createObjectURL(stream):webrtcUtils.log("Error attaching stream to element.")},reattachMediaStream=function(to,from){webrtcDetectedVersion>=43?to.srcObject=from.srcObject:to.src=from.src}}else if(navigator.mediaDevices&&navigator.userAgent.match(/Edge\/(\d+).(\d+)$/)){if(webrtcUtils.log("This appears to be Edge"),webrtcDetectedBrowser="edge",webrtcDetectedVersion=webrtcUtils.extractVersion(navigator.userAgent,/Edge\/(\d+).(\d+)$/,2),webrtcMinimumVersion=10547,window.RTCIceGatherer){var generateIdentifier=function(){return Math.random().toString(36).substr(2,10)},localCName=generateIdentifier(),SDPUtils={};SDPUtils.splitLines=function(blob){return blob.trim().split("\n").map(function(line){return line.trim()})},SDPUtils.splitSections=function(blob){var parts=blob.split("\r\nm=");return parts.map(function(part,index){return(index>0?"m="+part:part).trim()+"\r\n"})},SDPUtils.matchPrefix=function(blob,prefix){return SDPUtils.splitLines(blob).filter(function(line){return 0===line.indexOf(prefix)})},SDPUtils.parseCandidate=function(line){var parts;parts=0===line.indexOf("a=candidate:")?line.substring(12).split(" "):line.substring(10).split(" ");for(var candidate={foundation:parts[0],component:parts[1],protocol:parts[2].toLowerCase(),priority:parseInt(parts[3],10),ip:parts[4],port:parseInt(parts[5],10),type:parts[7]},i=8;i-1?(parts.attribute=line.substr(sp+1,colon-sp-1),parts.value=line.substr(colon+1)):parts.attribute=line.substr(sp+1),parts},SDPUtils.getDtlsParameters=function(mediaSection,sessionpart){var lines=SDPUtils.splitLines(mediaSection);lines=lines.concat(SDPUtils.splitLines(sessionpart));var fpLine=lines.filter(function(line){return 0===line.indexOf("a=fingerprint:")})[0].substr(14),dtlsParameters={role:"auto",fingerprints:[{algorithm:fpLine.split(" ")[0],value:fpLine.split(" ")[1]}]};return dtlsParameters},SDPUtils.writeDtlsParameters=function(params,setupType){var sdp="a=setup:"+setupType+"\r\n";return params.fingerprints.forEach(function(fp){sdp+="a=fingerprint:"+fp.algorithm+" "+fp.value+"\r\n"}),sdp},SDPUtils.getIceParameters=function(mediaSection,sessionpart){var lines=SDPUtils.splitLines(mediaSection);lines=lines.concat(SDPUtils.splitLines(sessionpart));var iceParameters={usernameFragment:lines.filter(function(line){return 0===line.indexOf("a=ice-ufrag:")})[0].substr(12),password:lines.filter(function(line){return 0===line.indexOf("a=ice-pwd:")})[0].substr(10)};return iceParameters},SDPUtils.writeIceParameters=function(params){return"a=ice-ufrag:"+params.usernameFragment+"\r\na=ice-pwd:"+params.password+"\r\n"},SDPUtils.parseRtpParameters=function(mediaSection){for(var description={codecs:[],headerExtensions:[],fecMechanisms:[],rtcp:[]},lines=SDPUtils.splitLines(mediaSection),mline=lines[0].split(" "),i=3;i0?"9":"0",sdp+=" UDP/TLS/RTP/SAVPF ",sdp+=caps.codecs.map(function(codec){return void 0!==codec.preferredPayloadType?codec.preferredPayloadType:codec.payloadType}).join(" ")+"\r\n",sdp+="c=IN IP4 0.0.0.0\r\n",sdp+="a=rtcp:9 IN IP4 0.0.0.0\r\n",caps.codecs.forEach(function(codec){sdp+=SDPUtils.writeRtpMap(codec),sdp+=SDPUtils.writeFtmp(codec),sdp+=SDPUtils.writeRtcpFb(codec)}),sdp+="a=rtcp-mux\r\n"},SDPUtils.writeSessionBoilerplate=function(){return"v=0\r\no=thisisadapterortc 8169639915646943137 2 IN IP4 127.0.0.1\r\ns=-\r\nt=0 0\r\n"},SDPUtils.writeMediaSection=function(transceiver,caps,type,stream){var sdp=SDPUtils.writeRtpDescription(transceiver.kind,caps);if(sdp+=SDPUtils.writeIceParameters(transceiver.iceGatherer.getLocalParameters()),sdp+=SDPUtils.writeDtlsParameters(transceiver.dtlsTransport.getLocalParameters(),"offer"===type?"actpass":"active"),sdp+="a=mid:"+transceiver.mid+"\r\n",sdp+=transceiver.rtpSender&&transceiver.rtpReceiver?"a=sendrecv\r\n":transceiver.rtpSender?"a=sendonly\r\n":transceiver.rtpReceiver?"a=recvonly\r\n":"a=inactive\r\n",transceiver.rtpSender){var msid="msid:"+stream.id+" "+transceiver.rtpSender.track.id+"\r\n";sdp+="a="+msid,sdp+="a=ssrc:"+transceiver.sendSsrc+" "+msid}return sdp+="a=ssrc:"+transceiver.sendSsrc+" cname:"+localCName+"\r\n"},SDPUtils.getDirection=function(mediaSection,sessionpart){for(var lines=SDPUtils.splitLines(mediaSection),i=0;i-1&&(this.localStreams.splice(idx,1),this._maybeFireNegotiationNeeded())},window.RTCPeerConnection.prototype._getCommonCapabilities=function(localCapabilities,remoteCapabilities){var commonCapabilities={codecs:[],headerExtensions:[],fecMechanisms:[]};return localCapabilities.codecs.forEach(function(lCodec){for(var i=0;i0,!1)}})}switch(this.localDescription=description, 3 | description.type){case"offer":this._updateSignalingState("have-local-offer");break;case"answer":this._updateSignalingState("stable");break;default:throw new TypeError('unsupported type "'+description.type+'"')}var hasCallback=arguments.length>1&&"function"==typeof arguments[1];if(hasCallback){var cb=arguments[1];window.setTimeout(function(){cb(),self._emitBufferedCandidates()},0)}var p=Promise.resolve();return p.then(function(){hasCallback||window.setTimeout(self._emitBufferedCandidates.bind(self),0)}),p},window.RTCPeerConnection.prototype.setRemoteDescription=function(description){var self=this,stream=new MediaStream,sections=SDPUtils.splitSections(description.sdp),sessionpart=sections.shift();switch(sections.forEach(function(mediaSection,sdpMLineIndex){var transceiver,iceGatherer,iceTransport,dtlsTransport,rtpSender,rtpReceiver,sendSsrc,recvSsrc,localCapabilities,remoteIceParameters,remoteDtlsParameters,lines=SDPUtils.splitLines(mediaSection),mline=lines[0].substr(2).split(" "),kind=mline[0],rejected="0"===mline[1],direction=SDPUtils.getDirection(mediaSection,sessionpart),remoteCapabilities=SDPUtils.parseRtpParameters(mediaSection);rejected||(remoteIceParameters=SDPUtils.getIceParameters(mediaSection,sessionpart),remoteDtlsParameters=SDPUtils.getDtlsParameters(mediaSection,sessionpart));var cname,mid=SDPUtils.matchPrefix(mediaSection,"a=mid:")[0].substr(6),remoteSsrc=SDPUtils.matchPrefix(mediaSection,"a=ssrc:").map(function(line){return SDPUtils.parseSsrcMedia(line)}).filter(function(obj){return"cname"===obj.attribute})[0];if(remoteSsrc&&(recvSsrc=parseInt(remoteSsrc.ssrc,10),cname=remoteSsrc.value),"offer"===description.type){var transports=self._createIceAndDtlsTransports(mid,sdpMLineIndex);if(localCapabilities=RTCRtpReceiver.getCapabilities(kind),sendSsrc=1001*(2*sdpMLineIndex+2),rtpReceiver=new RTCRtpReceiver(transports.dtlsTransport,kind),stream.addTrack(rtpReceiver.track),self.localStreams.length>0&&self.localStreams[0].getTracks().length>=sdpMLineIndex){var localtrack=self.localStreams[0].getTracks()[sdpMLineIndex];rtpSender=new RTCRtpSender(localtrack,transports.dtlsTransport)}self.transceivers[sdpMLineIndex]={iceGatherer:transports.iceGatherer,iceTransport:transports.iceTransport,dtlsTransport:transports.dtlsTransport,localCapabilities:localCapabilities,remoteCapabilities:remoteCapabilities,rtpSender:rtpSender,rtpReceiver:rtpReceiver,kind:kind,mid:mid,cname:cname,sendSsrc:sendSsrc,recvSsrc:recvSsrc},self._transceive(self.transceivers[sdpMLineIndex],!1,"sendrecv"===direction||"sendonly"===direction)}else"answer"!==description.type||rejected||(transceiver=self.transceivers[sdpMLineIndex],iceGatherer=transceiver.iceGatherer,iceTransport=transceiver.iceTransport,dtlsTransport=transceiver.dtlsTransport,rtpSender=transceiver.rtpSender,rtpReceiver=transceiver.rtpReceiver,sendSsrc=transceiver.sendSsrc,localCapabilities=transceiver.localCapabilities,self.transceivers[sdpMLineIndex].recvSsrc=recvSsrc,self.transceivers[sdpMLineIndex].remoteCapabilities=remoteCapabilities,self.transceivers[sdpMLineIndex].cname=cname,iceTransport.start(iceGatherer,remoteIceParameters,"controlling"),dtlsTransport.start(remoteDtlsParameters),self._transceive(transceiver,"sendrecv"===direction||"recvonly"===direction,"sendrecv"===direction||"sendonly"===direction),!rtpReceiver||"sendrecv"!==direction&&"sendonly"!==direction?delete transceiver.rtpReceiver:stream.addTrack(rtpReceiver.track))}),this.remoteDescription=description,description.type){case"offer":this._updateSignalingState("have-remote-offer");break;case"answer":this._updateSignalingState("stable");break;default:throw new TypeError('unsupported type "'+description.type+'"')}return window.setTimeout(function(){null!==self.onaddstream&&stream.getTracks().length&&(self.remoteStreams.push(stream),window.setTimeout(function(){self.onaddstream({stream:stream})},0))},0),arguments.length>1&&"function"==typeof arguments[1]&&window.setTimeout(arguments[1],0),Promise.resolve()},window.RTCPeerConnection.prototype.close=function(){this.transceivers.forEach(function(transceiver){transceiver.iceTransport&&transceiver.iceTransport.stop(),transceiver.dtlsTransport&&transceiver.dtlsTransport.stop(),transceiver.rtpSender&&transceiver.rtpSender.stop(),transceiver.rtpReceiver&&transceiver.rtpReceiver.stop()}),this._updateSignalingState("closed")},window.RTCPeerConnection.prototype._updateSignalingState=function(newState){this.signalingState=newState,null!==this.onsignalingstatechange&&this.onsignalingstatechange()},window.RTCPeerConnection.prototype._maybeFireNegotiationNeeded=function(){null!==this.onnegotiationneeded&&this.onnegotiationneeded()},window.RTCPeerConnection.prototype._updateConnectionState=function(){var newState,self=this,states={"new":0,closed:0,connecting:0,checking:0,connected:0,completed:0,failed:0};this.transceivers.forEach(function(transceiver){states[transceiver.iceTransport.state]++,states[transceiver.dtlsTransport.state]++}),states.connected+=states.completed,newState="new",states.failed>0?newState="failed":states.connecting>0||states.checking>0?newState="connecting":states.disconnected>0?newState="disconnected":states["new"]>0?newState="new":(states.connecting>0||states.completed>0)&&(newState="connected"),newState!==self.iceConnectionState&&(self.iceConnectionState=newState,null!==this.oniceconnectionstatechange&&this.oniceconnectionstatechange())},window.RTCPeerConnection.prototype.createOffer=function(){var self=this;if(this._pendingOffer)throw new Error("createOffer called while there is a pending offer.");var offerOptions;1===arguments.length&&"function"!=typeof arguments[0]?offerOptions=arguments[0]:3===arguments.length&&(offerOptions=arguments[2]);var tracks=[],numAudioTracks=0,numVideoTracks=0;if(this.localStreams.length&&(numAudioTracks=this.localStreams[0].getAudioTracks().length,numVideoTracks=this.localStreams[0].getVideoTracks().length),offerOptions){if(offerOptions.mandatory||offerOptions.optional)throw new TypeError("Legacy mandatory/optional constraints not supported.");void 0!==offerOptions.offerToReceiveAudio&&(numAudioTracks=offerOptions.offerToReceiveAudio),void 0!==offerOptions.offerToReceiveVideo&&(numVideoTracks=offerOptions.offerToReceiveVideo)}for(this.localStreams.length&&this.localStreams[0].getTracks().forEach(function(track){tracks.push({kind:track.kind,track:track,wantReceive:"audio"===track.kind?numAudioTracks>0:numVideoTracks>0}),"audio"===track.kind?numAudioTracks--:"video"===track.kind&&numVideoTracks--});numAudioTracks>0||numVideoTracks>0;)numAudioTracks>0&&(tracks.push({kind:"audio",wantReceive:!0}),numAudioTracks--),numVideoTracks>0&&(tracks.push({kind:"video",wantReceive:!0}),numVideoTracks--);var sdp=SDPUtils.writeSessionBoilerplate(),transceivers=[];tracks.forEach(function(mline,sdpMLineIndex){var rtpSender,rtpReceiver,track=mline.track,kind=mline.kind,mid=generateIdentifier(),transports=self._createIceAndDtlsTransports(mid,sdpMLineIndex),localCapabilities=RTCRtpSender.getCapabilities(kind),sendSsrc=1001*(2*sdpMLineIndex+1);track&&(rtpSender=new RTCRtpSender(track,transports.dtlsTransport)),mline.wantReceive&&(rtpReceiver=new RTCRtpReceiver(transports.dtlsTransport,kind)),transceivers[sdpMLineIndex]={iceGatherer:transports.iceGatherer,iceTransport:transports.iceTransport,dtlsTransport:transports.dtlsTransport,localCapabilities:localCapabilities,remoteCapabilities:null,rtpSender:rtpSender,rtpReceiver:rtpReceiver,kind:kind,mid:mid,sendSsrc:sendSsrc,recvSsrc:null};var transceiver=transceivers[sdpMLineIndex];sdp+=SDPUtils.writeMediaSection(transceiver,transceiver.localCapabilities,"offer",self.localStreams[0])}),this._pendingOffer=transceivers;var desc=new RTCSessionDescription({type:"offer",sdp:sdp});return arguments.length&&"function"==typeof arguments[0]&&window.setTimeout(arguments[0],0,desc),Promise.resolve(desc)},window.RTCPeerConnection.prototype.createAnswer=function(){var answerOptions,self=this;1===arguments.length&&"function"!=typeof arguments[0]?answerOptions=arguments[0]:3===arguments.length&&(answerOptions=arguments[2]);var sdp=SDPUtils.writeSessionBoilerplate();this.transceivers.forEach(function(transceiver){var commonCapabilities=self._getCommonCapabilities(transceiver.localCapabilities,transceiver.remoteCapabilities);sdp+=SDPUtils.writeMediaSection(transceiver,commonCapabilities,"answer",self.localStreams[0])});var desc=new RTCSessionDescription({type:"answer",sdp:sdp});return arguments.length&&"function"==typeof arguments[0]&&window.setTimeout(arguments[0],0,desc),Promise.resolve(desc)},window.RTCPeerConnection.prototype.addIceCandidate=function(candidate){var mLineIndex=candidate.sdpMLineIndex;if(candidate.sdpMid)for(var i=0;i0?SDPUtils.parseCandidate(candidate.candidate):{};if("tcp"===cand.protocol&&0===cand.port)return;if("1"!==cand.component)return;"endOfCandidates"===cand.type&&(cand={}),transceiver.iceTransport.addRemoteCandidate(cand)}return arguments.length>1&&"function"==typeof arguments[1]&&window.setTimeout(arguments[1],0),Promise.resolve()},window.RTCPeerConnection.prototype.getStats=function(){var promises=[];this.transceivers.forEach(function(transceiver){["rtpSender","rtpReceiver","iceGatherer","iceTransport","dtlsTransport"].forEach(function(method){transceiver[method]&&promises.push(transceiver[method].getStats())})});var cb=arguments.length>1&&"function"==typeof arguments[1]&&arguments[1];return new Promise(function(resolve){var results={};Promise.all(promises).then(function(res){res.forEach(function(result){Object.keys(result).forEach(function(id){results[id]=result[id]})}),cb&&window.setTimeout(cb,0,results),resolve(results)})})}}}else webrtcUtils.log("Browser does not appear to be WebRTC-capable");else webrtcUtils.log("This does not appear to be a browser"),webrtcDetectedBrowser="not a browser";var webrtcTesting={};try{Object.defineProperty(webrtcTesting,"version",{set:function(version){webrtcDetectedVersion=version}})}catch(e){}AdapterJS.parseWebrtcDetectedBrowser(),navigator.mozGetUserMedia?(MediaStreamTrack.getSources=function(successCb){setTimeout(function(){var infos=[{kind:"audio",id:"default",label:"",facing:""},{kind:"video",id:"default",label:"",facing:""}];successCb(infos)},0)},createIceServer=function(url,username,password){var iceServer=null,urlParts=url.split(":");if(0===urlParts[0].indexOf("stun"))iceServer={urls:[url]};else if(0===urlParts[0].indexOf("turn"))if(27>webrtcDetectedVersion){var turnUrlParts=url.split("?");(1===turnUrlParts.length||0===turnUrlParts[1].indexOf("transport=udp"))&&(iceServer={urls:[turnUrlParts[0]],credential:password,username:username})}else iceServer={urls:[url],credential:password,username:username};return iceServer},createIceServers=function(urls,username,password){var iceServers=[];for(i=0;i=34)iceServers={urls:urls,credential:password,username:username};else for(i=0;i=webrtcDetectedVersion){var frag=document.createDocumentFragment();for(AdapterJS.WebRTCPlugin.plugin=document.createElement("div"),AdapterJS.WebRTCPlugin.plugin.innerHTML=' '+(AdapterJS.options.getAllCams?'':"")+"";AdapterJS.WebRTCPlugin.plugin.firstChild;)frag.appendChild(AdapterJS.WebRTCPlugin.plugin.firstChild);document.body.appendChild(frag),AdapterJS.WebRTCPlugin.plugin=document.getElementById(AdapterJS.WebRTCPlugin.pluginInfo.pluginId)}else AdapterJS.WebRTCPlugin.plugin=document.createElement("object"),AdapterJS.WebRTCPlugin.plugin.id=AdapterJS.WebRTCPlugin.pluginInfo.pluginId,isIE?(AdapterJS.WebRTCPlugin.plugin.width="1px",AdapterJS.WebRTCPlugin.plugin.height="1px"):(AdapterJS.WebRTCPlugin.plugin.width="0px",AdapterJS.WebRTCPlugin.plugin.height="0px"),AdapterJS.WebRTCPlugin.plugin.type=AdapterJS.WebRTCPlugin.pluginInfo.type,AdapterJS.WebRTCPlugin.plugin.innerHTML=' '+(AdapterJS.options.getAllCams?'':"")+'',document.body.appendChild(AdapterJS.WebRTCPlugin.plugin);AdapterJS.WebRTCPlugin.pluginState=AdapterJS.WebRTCPlugin.PLUGIN_STATES.INJECTED}},AdapterJS.WebRTCPlugin.isPluginInstalled=function(comName,plugName,installedCb,notInstalledCb){if(isIE){try{new ActiveXObject(comName+"."+plugName)}catch(e){return void notInstalledCb()}installedCb()}else{for(var pluginArray=navigator.plugins,i=0;i=0)return void installedCb();notInstalledCb()}},AdapterJS.WebRTCPlugin.defineWebRTCInterface=function(){AdapterJS.WebRTCPlugin.pluginState!==AdapterJS.WebRTCPlugin.PLUGIN_STATES.READY&&(AdapterJS.WebRTCPlugin.pluginState=AdapterJS.WebRTCPlugin.PLUGIN_STATES.INITIALIZING,AdapterJS.isDefined=function(variable){return null!==variable&&void 0!==variable},createIceServer=function(url,username,password){var iceServer=null,urlParts=url.split(":");return 0===urlParts[0].indexOf("stun")?iceServer={url:url,hasCredentials:!1}:0===urlParts[0].indexOf("turn")&&(iceServer={url:url,hasCredentials:!0,credential:password,username:username}),iceServer},createIceServers=function(urls,username,password){for(var iceServers=[],i=0;i1)return AdapterJS.WebRTCPlugin.plugin.PeerConnection(servers);var iceServers=null;if(servers&&Array.isArray(servers.iceServers)){iceServers=servers.iceServers;for(var i=0;i ';temp.firstChild;)frag.appendChild(temp.firstChild);var height="",width="";element.clientWidth||element.clientHeight?(width=element.clientWidth,height=element.clientHeight):(element.width||element.height)&&(width=element.width,height=element.height),element.parentNode.insertBefore(frag,element),frag=document.getElementById(elementId),frag.width=width,frag.height=height,element.parentNode.removeChild(element)}else{for(var children=element.children,i=0;i!==children.length;++i)if("streamId"===children[i].name){children[i].value=streamId;break}element.setStreamId(streamId)}var newElement=document.getElementById(elementId);return AdapterJS.forwardEventHandlers(newElement,element,Object.getPrototypeOf(element)),newElement}},reattachMediaStream=function(to,from){for(var stream=null,children=from.children,i=0;i!==children.length;++i)if("streamId"===children[i].name){AdapterJS.WebRTCPlugin.WaitForPluginReady(),stream=AdapterJS.WebRTCPlugin.plugin.getStreamWithId(AdapterJS.WebRTCPlugin.pageId,children[i].value);break}return null!==stream?attachMediaStream(to,stream):void 0},window.attachMediaStream=attachMediaStream,window.reattachMediaStream=reattachMediaStream,window.getUserMedia=getUserMedia,AdapterJS.attachMediaStream=attachMediaStream,AdapterJS.reattachMediaStream=reattachMediaStream,AdapterJS.getUserMedia=getUserMedia,AdapterJS.forwardEventHandlers=function(destElem,srcElem,prototype){properties=Object.getOwnPropertyNames(prototype);for(var prop in properties)prop&&(propName=properties[prop],"function"==typeof propName.slice&&"on"===propName.slice(0,2)&&"function"==typeof srcElem[propName]&&AdapterJS.addEvent(destElem,propName.slice(2),srcElem[propName]));var subPrototype=Object.getPrototypeOf(prototype);subPrototype&&AdapterJS.forwardEventHandlers(destElem,srcElem,subPrototype)},RTCIceCandidate=function(candidate){return candidate.sdpMid||(candidate.sdpMid=""),AdapterJS.WebRTCPlugin.WaitForPluginReady(),AdapterJS.WebRTCPlugin.plugin.ConstructIceCandidate(candidate.sdpMid,candidate.sdpMLineIndex,candidate.candidate)},AdapterJS.addEvent(document,"readystatechange",AdapterJS.WebRTCPlugin.injectPlugin),AdapterJS.WebRTCPlugin.injectPlugin())},AdapterJS.WebRTCPlugin.pluginNeededButNotInstalledCb=AdapterJS.WebRTCPlugin.pluginNeededButNotInstalledCb||function(){AdapterJS.addEvent(document,"readystatechange",AdapterJS.WebRTCPlugin.pluginNeededButNotInstalledCbPriv),AdapterJS.WebRTCPlugin.pluginNeededButNotInstalledCbPriv()},AdapterJS.WebRTCPlugin.pluginNeededButNotInstalledCbPriv=function(){if(!AdapterJS.options.hidePluginInstallPrompt){var downloadLink=AdapterJS.WebRTCPlugin.pluginInfo.downloadLink;if(downloadLink){var popupString;popupString=AdapterJS.WebRTCPlugin.pluginInfo.portalLink?'This website requires you to install the '+AdapterJS.WebRTCPlugin.pluginInfo.companyName+" WebRTC Plugin to work on this browser.":AdapterJS.TEXT.PLUGIN.REQUIRE_INSTALLATION,AdapterJS.renderNotificationBar(popupString,AdapterJS.TEXT.PLUGIN.BUTTON,downloadLink)}else AdapterJS.renderNotificationBar(AdapterJS.TEXT.PLUGIN.NOT_SUPPORTED)}},AdapterJS.WebRTCPlugin.isPluginInstalled(AdapterJS.WebRTCPlugin.pluginInfo.prefix,AdapterJS.WebRTCPlugin.pluginInfo.plugName,AdapterJS.WebRTCPlugin.defineWebRTCInterface,AdapterJS.WebRTCPlugin.pluginNeededButNotInstalledCb); --------------------------------------------------------------------------------