From bc83d62339d9a6c1b8f59bc38601ef3386b36750 Mon Sep 17 00:00:00 2001 From: Jonas Herzig Date: Sun, 2 Dec 2018 18:32:53 +0100 Subject: [PATCH 01/23] Add WebRTC support, drop UDPTunnel support --- README.md | 47 +++++++++++++++++------------------------------ app/index.js | 50 ++++++++++++++++++++++++-------------------------- app/voice.js | 23 +++++++++-------------- package.json | 8 +------- 4 files changed, 51 insertions(+), 77 deletions(-) diff --git a/README.md b/README.md index 3c770f4..53de11f 100644 --- a/README.md +++ b/README.md @@ -1,15 +1,16 @@ # mumble-web +Note: This WebRTC branch is not backwards compatible with the current release, i.e. it expects the server/proxy to support WebRTC which neither websockify nor Grumble do. Also note that it requires an extension to the Mumble protocol which has not yet been stabilized and as such may change at any time, so make sure to keep mumble-web and mumble-web-proxy in sync. + mumble-web is an HTML5 [Mumble] client for use in modern browsers. -A live demo is running [here](https://voice.johni0702.de/?address=voice.johni0702.de&port=443/demo). +A live demo is running [here](https://voice.johni0702.de/webrtc/?address=voice.johni0702.de&port=443/demo). The Mumble protocol uses TCP for control and UDP for voice. Running in a browser, both are unavailable to this client. -Instead Websockets are used for all communications. +Instead Websockets are used for control and WebRTC is used for voice. -libopus, libcelt (0.7.1) and libsamplerate, compiled to JS via emscripten, are used for audio decoding. -Therefore, at the moment only the Opus and CELT Alpha codecs are supported. +Therefore, only the Opus codec is supported. Quite a few features, most noticeably all administrative functionallity, are still missing. @@ -18,10 +19,10 @@ administrative functionallity, are still missing. #### Download mumble-web can either be installed directly from npm with `npm install -g mumble-web` -or from git: +or from git (webrtc branch only from git for now): ``` -git clone https://github.com/johni0702/mumble-web +git clone -b webrtc https://github.com/johni0702/mumble-web cd mumble-web npm install npm run build @@ -34,30 +35,11 @@ Either way you will end up with a `dist` folder that contains the static page. #### Setup At the time of writing this there do not seem to be any Mumble servers -which natively support Websockets. To use this client with any standard mumble -server, websockify must be set up (preferably on the same machine that the +which natively support Websockets+WebRTC. To use this client with any standard mumble +server, [mumble-web-proxy] must be set up (preferably on the same machine that the Mumble server is running on). -You can install websockify via your package manager `apt install websockify` or -manually from the [websockify GitHub page]. Note that while some versions might -function better than others, the python version generally seems to be the best. - -There are two basic ways you can use websockify with mumble-web: -- Standalone, use websockify for both, websockets and serving static files -- Proxied, let your favorite web server serve static files and proxy websocket connections to websockify - -##### Standalone -This is the simplest but at the same time least flexible configuration. -``` -websockify --cert=mycert.crt --key=mykey.key --ssl-only --ssl-target --web=path/to/dist 443 mumbleserver:64738 -``` - -##### Proxied -This configuration allows you to run websockify on a machine that already has -another webserver running. -``` -websockify --ssl-target 64737 mumbleserver:64738 -``` +Additionally you will need some web server to serve static files and terminate the secure websocket connection (mumble-web-proxy only supports insecure ones). A sample configuration for nginx that allows access to mumble-web at `https://voice.example.com/` and connecting at `wss://voice.example.com/demo` @@ -73,7 +55,7 @@ server { root /path/to/dist; } location /demo { - proxy_pass http://websockify:64737; + proxy_pass http://proxybox:64737; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection $connection_upgrade; @@ -85,6 +67,11 @@ map $http_upgrade $connection_upgrade { '' close; } ``` +where `proxybox` is the machine running mumble-web-proxy (may be `localhost`): +``` +mumble-web-proxy --listen-ws 64737 --server mumbleserver:64738 +``` +If your mumble-web-proxy is running behind a NAT or firewall, take note of the respective section in its README. ### Configuration The `app/config.js` file contains default values and descriptions for all configuration options. @@ -133,6 +120,6 @@ See [here](https://docs.google.com/document/d/1uPF7XWY_dXTKVKV7jZQ2KmsI19wn9-kFR ISC [Mumble]: https://wiki.mumble.info/wiki/Main_Page -[websockify GitHub page]: https://github.com/novnc/websockify +[mumble-web-proxy]: https://github.com/johni0702/mumble-web-proxy [MetroMumble]: https://github.com/xPoke/MetroMumble [Matrix]: https://matrix.org diff --git a/app/index.js b/app/index.js index 5c67d0f..3094cc6 100644 --- a/app/index.js +++ b/app/index.js @@ -1,10 +1,8 @@ import 'stream-browserify' // see https://github.com/ericgundrum/pouch-websocket-sync-example/commit/2a4437b013092cc7b2cd84cf1499172c84a963a3 -import 'subworkers' // polyfill for https://bugs.chromium.org/p/chromium/issues/detail?id=31666 import url from 'url' import ByteBuffer from 'bytebuffer' import MumbleClient from 'mumble-client' -import WorkerBasedMumbleConnector from './worker-client' -import BufferQueueNode from 'web-audio-buffer-queue' +import mumbleConnect from 'mumble-client-websocket' import audioContext from 'audio-context' import ko from 'knockout' import _dompurify from 'dompurify' @@ -267,7 +265,7 @@ class GlobalBindings { constructor (config) { this.config = config this.settings = new Settings(config.settings) - this.connector = new WorkerBasedMumbleConnector() + this.connector = { connect: mumbleConnect } this.client = null this.userContextMenu = new ContextMenu() this.channelContextMenu = new ContextMenu() @@ -339,14 +337,15 @@ class GlobalBindings { log('Connecting to server ', host) - // Note: This call needs to be delayed until the user has interacted with - // the page in some way (which at this point they have), see: https://goo.gl/7K7WLu - this.connector.setSampleRate(audioContext().sampleRate) - // TODO: token this.connector.connect(`wss://${host}:${port}`, { username: username, - password: password + password: password, + webrtc: { + enabled: true, + mic: micStream, + audioContext: audioContext() + } }).done(client => { log('Connected!') @@ -563,24 +562,18 @@ class GlobalBindings { } }).on('voice', stream => { console.log(`User ${user.username} started takling`) - var userNode = new BufferQueueNode({ - audioContext: audioContext() - }) - userNode.connect(audioContext().destination) - + if (stream.target === 'normal') { + ui.talking('on') + } else if (stream.target === 'shout') { + ui.talking('shout') + } else if (stream.target === 'whisper') { + ui.talking('whisper') + } stream.on('data', data => { - if (data.target === 'normal') { - ui.talking('on') - } else if (data.target === 'shout') { - ui.talking('shout') - } else if (data.target === 'whisper') { - ui.talking('whisper') - } - userNode.write(data.buffer) + // mumble-client is in WebRTC mode, no pcm data should arrive this way }).on('end', () => { console.log(`User ${user.username} stopped takling`) ui.talking('off') - userNode.end() }) }) } @@ -929,7 +922,9 @@ window.onload = function () { req.send() } ui.connectDialog.joinOnly(useJoinDialog) - ko.applyBindings(ui) + userMediaPromise.then(() => { + ko.applyBindings(ui) + }) } window.onresize = () => ui.updateSize() @@ -981,10 +976,11 @@ function userToState () { return flags.join(', ') } +var micStream var voiceHandler var testVoiceHandler -initVoice(data => { +var userMediaPromise = initVoice(data => { if (testVoiceHandler) { testVoiceHandler.write(data) } @@ -996,6 +992,8 @@ initVoice(data => { } else if (voiceHandler) { voiceHandler.write(data) } +}).then(userMedia => { + micStream = userMedia }, err => { - log('Cannot initialize user media. Microphone will not work:', err) + window.alert('Failed to initialize user media\nRefresh page to retry.\n' + err) }) diff --git a/app/voice.js b/app/voice.js index 6b048de..8ada072 100644 --- a/app/voice.js +++ b/app/voice.js @@ -1,7 +1,6 @@ import { Writable } from 'stream' import MicrophoneStream from 'microphone-stream' import audioContext from 'audio-context' -import getUserMedia from 'getusermedia' import keyboardjs from 'keyboardjs' import vad from 'voice-activity-detection' import DropStream from 'drop-stream' @@ -33,8 +32,7 @@ class VoiceHandler extends Writable { return this._outbound } - // Note: the samplesPerPacket argument is handled in worker.js and not passed on - this._outbound = this._client.createVoiceStream(this._settings.samplesPerPacket) + this._outbound = this._client.createVoiceStream() this.emit('started_talking') } @@ -160,16 +158,13 @@ export class VADVoiceHandler extends VoiceHandler { var theUserMedia = null -export function initVoice (onData, onUserMediaError) { - getUserMedia({ audio: true }, (err, userMedia) => { - if (err) { - onUserMediaError(err) - } else { - theUserMedia = userMedia - var micStream = new MicrophoneStream(userMedia, { objectMode: true, bufferSize: 1024 }) - micStream.on('data', data => { - onData(Buffer.from(data.getChannelData(0).buffer)) - }) - } +export function initVoice (onData) { + return window.navigator.mediaDevices.getUserMedia({ audio: true }).then((userMedia) => { + theUserMedia = userMedia + var micStream = new MicrophoneStream(userMedia, { objectMode: true, bufferSize: 1024 }) + micStream.on('data', data => { + onData(Buffer.from(data.getChannelData(0).buffer)) + }) + return userMedia }) } diff --git a/package.json b/package.json index 55e4ef2..7afb4cd 100644 --- a/package.json +++ b/package.json @@ -30,7 +30,6 @@ "duplex-maker": "^1.0.0", "extract-loader": "^0.1.0", "file-loader": "^0.9.0", - "getusermedia": "^2.0.0", "html-loader": "^0.4.4", "json-loader": "^0.5.4", "keyboardjs": "^2.3.4", @@ -42,16 +41,11 @@ "regexp-replace-loader": "0.0.1", "sass-loader": "^4.1.1", "stream-chunker": "^1.2.8", - "subworkers": "^1.0.1", "to-arraybuffer": "^1.0.1", "transform-loader": "^0.2.3", "voice-activity-detection": "johni0702/voice-activity-detection#9f8bd90", "webpack": "^1.13.3", - "webworkify-webpack": "^1.1.8", - "libsamplerate.js": "^1.0.0", - "mumble-client-codecs-browser": "^1.2.0", "mumble-client-websocket": "^1.0.0", - "mumble-client": "^1.3.0", - "web-audio-buffer-queue": "^1.1.0" + "mumble-client": "github:johni0702/mumble-client#8124ee7" } } From 0367d33737aec7e6db1857e61a15afff1d37e07e Mon Sep 17 00:00:00 2001 From: Jonas Herzig Date: Sat, 15 Dec 2018 19:28:40 +0100 Subject: [PATCH 02/23] Update mumble-client to get WebRTC working on Chrome --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 7afb4cd..749960f 100644 --- a/package.json +++ b/package.json @@ -46,6 +46,6 @@ "voice-activity-detection": "johni0702/voice-activity-detection#9f8bd90", "webpack": "^1.13.3", "mumble-client-websocket": "^1.0.0", - "mumble-client": "github:johni0702/mumble-client#8124ee7" + "mumble-client": "github:johni0702/mumble-client#b81a3bd" } } From 5faf9017ba81535901ca5d719de072c041af676b Mon Sep 17 00:00:00 2001 From: Jonas Herzig Date: Wed, 30 Jan 2019 17:16:33 +0100 Subject: [PATCH 03/23] Fix mumble-client not being built correctly (fixes #42) --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 749960f..659eba4 100644 --- a/package.json +++ b/package.json @@ -46,6 +46,6 @@ "voice-activity-detection": "johni0702/voice-activity-detection#9f8bd90", "webpack": "^1.13.3", "mumble-client-websocket": "^1.0.0", - "mumble-client": "github:johni0702/mumble-client#b81a3bd" + "mumble-client": "github:johni0702/mumble-client#a5cb0d7" } } From 6030aa8f2ee10f4eb0d9240694f67228a53f1816 Mon Sep 17 00:00:00 2001 From: Jonas Herzig Date: Tue, 5 Feb 2019 15:28:30 +0100 Subject: [PATCH 04/23] Update mumble-web to work around reconnection issue in FF See commit ddf8424 in mumble-client --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 659eba4..7f57b87 100644 --- a/package.json +++ b/package.json @@ -46,6 +46,6 @@ "voice-activity-detection": "johni0702/voice-activity-detection#9f8bd90", "webpack": "^1.13.3", "mumble-client-websocket": "^1.0.0", - "mumble-client": "github:johni0702/mumble-client#a5cb0d7" + "mumble-client": "github:johni0702/mumble-client#ddf8424" } } From 41fa124b8f85ab3e41fef37b4f961b9bdbcc91e0 Mon Sep 17 00:00:00 2001 From: Jonas Herzig Date: Wed, 6 Feb 2019 14:21:13 +0100 Subject: [PATCH 05/23] Add artificial delay of 150ms to mic for VAD VAD can only tell whether the user is talking after ~150ms, so we need to delay the microphone stream for 150ms when it's in use. --- app/index.js | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/app/index.js b/app/index.js index 3094cc6..ca93067 100644 --- a/app/index.js +++ b/app/index.js @@ -337,14 +337,22 @@ class GlobalBindings { log('Connecting to server ', host) + let ctx = audioContext() + if (!this._delayedMicNode) { + this._micNode = ctx.createMediaStreamSource(this._micStream) + this._delayNode = ctx.createDelay() + this._delayNode.delayTime.value = 0.15 + this._delayedMicNode = ctx.createMediaStreamDestination() + } + // TODO: token this.connector.connect(`wss://${host}:${port}`, { username: username, password: password, webrtc: { enabled: true, - mic: micStream, - audioContext: audioContext() + mic: this._delayedMicNode.stream, + audioContext: ctx } }).done(client => { log('Connected!') @@ -695,6 +703,15 @@ class GlobalBindings { voiceHandler.setMute(true) } + this._micNode.disconnect() + this._delayNode.disconnect() + if (mode === 'vad') { + this._micNode.connect(this._delayNode) + this._delayNode.connect(this._delayedMicNode) + } else { + this._micNode.connect(this._delayedMicNode) + } + this.client.setAudioQuality( this.settings.audioBitrate, this.settings.samplesPerPacket @@ -976,7 +993,6 @@ function userToState () { return flags.join(', ') } -var micStream var voiceHandler var testVoiceHandler @@ -993,7 +1009,7 @@ var userMediaPromise = initVoice(data => { voiceHandler.write(data) } }).then(userMedia => { - micStream = userMedia + ui._micStream = userMedia }, err => { window.alert('Failed to initialize user media\nRefresh page to retry.\n' + err) }) From 36d54c48b7d424c0315e3d2273ad0cc41adfc829 Mon Sep 17 00:00:00 2001 From: Jonas Herzig Date: Mon, 4 May 2020 19:28:06 +0200 Subject: [PATCH 06/23] Update mumble-client to fix empty ice candidates --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 9a02bcc..42ee7ee 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5775,8 +5775,8 @@ "dev": true }, "mumble-client": { - "version": "github:johni0702/mumble-client#ddf84245ff5d10a4f1913f0bbd864127ff044571", - "from": "github:johni0702/mumble-client#ddf8424", + "version": "github:johni0702/mumble-client#f73a08bcb223c530326d44484a357380dfe3e6ee", + "from": "github:johni0702/mumble-client#f73a08b", "dev": true, "requires": { "drop-stream": "^0.1.1", diff --git a/package.json b/package.json index 9bc2235..40c1c09 100644 --- a/package.json +++ b/package.json @@ -38,7 +38,7 @@ "knockout": "^3.5.1", "lodash.assign": "^4.2.0", "microphone-stream": "^5.0.1", - "mumble-client": "github:johni0702/mumble-client#ddf8424", + "mumble-client": "github:johni0702/mumble-client#f73a08b", "mumble-client-websocket": "^1.0.0", "node-sass": "^4.13.1", "raw-loader": "^4.0.0", From f055401f06947774bf7e711db69aaaaeb18876fd Mon Sep 17 00:00:00 2001 From: Jonas Herzig Date: Mon, 4 May 2020 20:57:03 +0200 Subject: [PATCH 07/23] Remove patch-package patches We don't need patch-package for the webrtc version because we don't use mumble-client-codecs-browser. --- .../mumble-client-codecs-browser+1.2.0.patch | 183 ------------------ 1 file changed, 183 deletions(-) delete mode 100644 patches/mumble-client-codecs-browser+1.2.0.patch diff --git a/patches/mumble-client-codecs-browser+1.2.0.patch b/patches/mumble-client-codecs-browser+1.2.0.patch deleted file mode 100644 index bd042df..0000000 --- a/patches/mumble-client-codecs-browser+1.2.0.patch +++ /dev/null @@ -1,183 +0,0 @@ -diff --git a/node_modules/mumble-client-codecs-browser/lib/decode-worker.js b/node_modules/mumble-client-codecs-browser/lib/decode-worker.js -index 3925f29..be9af92 100644 ---- a/node_modules/mumble-client-codecs-browser/lib/decode-worker.js -+++ b/node_modules/mumble-client-codecs-browser/lib/decode-worker.js -@@ -1,10 +1,6 @@ - 'use strict'; - --Object.defineProperty(exports, "__esModule", { -- value: true --}); - --exports.default = function (self) { - var opusDecoder, celt7Decoder; - self.addEventListener('message', function (e) { - var data = e.data; -@@ -55,10 +51,12 @@ exports.default = function (self) { - }, [_decoded.buffer]); - } - }); --}; -+ - - var _libopus = require('libopus.js'); - - var _libcelt = require('libcelt7.js'); - - var MUMBLE_SAMPLE_RATE = 48000; -+ -+export default null -\ No newline at end of file -diff --git a/node_modules/mumble-client-codecs-browser/lib/decoder-stream.js b/node_modules/mumble-client-codecs-browser/lib/decoder-stream.js -index 6cfda8b..28a9549 100644 ---- a/node_modules/mumble-client-codecs-browser/lib/decoder-stream.js -+++ b/node_modules/mumble-client-codecs-browser/lib/decoder-stream.js -@@ -1,9 +1,5 @@ - 'use strict'; - --Object.defineProperty(exports, "__esModule", { -- value: true --}); -- - var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); - - var _stream = require('stream'); -@@ -12,17 +8,11 @@ var _reusePool = require('reuse-pool'); - - var _reusePool2 = _interopRequireDefault(_reusePool); - --var _webworkify = require('webworkify'); -- --var _webworkify2 = _interopRequireDefault(_webworkify); -- - var _toArraybuffer = require('to-arraybuffer'); - - var _toArraybuffer2 = _interopRequireDefault(_toArraybuffer); - --var _decodeWorker = require('./decode-worker'); -- --var _decodeWorker2 = _interopRequireDefault(_decodeWorker); -+import DecodeWorker from './decode-worker'; - - function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -@@ -33,7 +23,7 @@ function _possibleConstructorReturn(self, call) { if (!self) { throw new Referen - function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } - - var pool = (0, _reusePool2.default)(function () { -- return (0, _webworkify2.default)(_decodeWorker2.default); -+ return new DecodeWorker(); - }); - // Prepare first worker - pool.recycle(pool.get()); -@@ -48,11 +38,6 @@ var DecoderStream = function (_Transform) { - - _this._worker = pool.get(); - _this._worker.onmessage = function (msg) { -- if (_this._worker.objectURL) { -- // The object URL can now be revoked as the worker has been loaded -- window.URL.revokeObjectURL(_this._worker.objectURL); -- _this._worker.objectURL = null; -- } - _this._onMessage(msg.data); - }; - return _this; -@@ -112,4 +97,5 @@ var DecoderStream = function (_Transform) { - return DecoderStream; - }(_stream.Transform); - --exports.default = DecoderStream; -\ No newline at end of file -+//exports.default = DecoderStream; -+export default DecoderStream -\ No newline at end of file -diff --git a/node_modules/mumble-client-codecs-browser/lib/encode-worker.js b/node_modules/mumble-client-codecs-browser/lib/encode-worker.js -index f7187ab..c2ebaa3 100644 ---- a/node_modules/mumble-client-codecs-browser/lib/encode-worker.js -+++ b/node_modules/mumble-client-codecs-browser/lib/encode-worker.js -@@ -1,10 +1,6 @@ - 'use strict'; - --Object.defineProperty(exports, "__esModule", { -- value: true --}); - --exports.default = function (self) { - var opusEncoder, celt7Encoder; - var bitrate; - self.addEventListener('message', function (e) { -@@ -70,7 +66,7 @@ exports.default = function (self) { - }, [_buffer]); - } - }); --}; -+ - - var _libopus = require('libopus.js'); - -@@ -83,3 +79,5 @@ var _toArraybuffer2 = _interopRequireDefault(_toArraybuffer); - function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - - var MUMBLE_SAMPLE_RATE = 48000; -+ -+export default null -\ No newline at end of file -diff --git a/node_modules/mumble-client-codecs-browser/lib/encoder-stream.js b/node_modules/mumble-client-codecs-browser/lib/encoder-stream.js -index 021f131..eeb9189 100644 ---- a/node_modules/mumble-client-codecs-browser/lib/encoder-stream.js -+++ b/node_modules/mumble-client-codecs-browser/lib/encoder-stream.js -@@ -1,9 +1,5 @@ - 'use strict'; - --Object.defineProperty(exports, "__esModule", { -- value: true --}); -- - var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); - - var _stream = require('stream'); -@@ -12,13 +8,7 @@ var _reusePool = require('reuse-pool'); - - var _reusePool2 = _interopRequireDefault(_reusePool); - --var _webworkify = require('webworkify'); -- --var _webworkify2 = _interopRequireDefault(_webworkify); -- --var _encodeWorker = require('./encode-worker'); -- --var _encodeWorker2 = _interopRequireDefault(_encodeWorker); -+import EncodeWorker from './encode-worker' - - function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -@@ -29,7 +19,7 @@ function _possibleConstructorReturn(self, call) { if (!self) { throw new Referen - function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } - - var pool = (0, _reusePool2.default)(function () { -- return (0, _webworkify2.default)(_encodeWorker2.default); -+ return new EncodeWorker(); - }); - // Prepare first worker - pool.recycle(pool.get()); -@@ -46,11 +36,6 @@ var EncoderStream = function (_Transform) { - - _this._worker = pool.get(); - _this._worker.onmessage = function (msg) { -- if (_this._worker.objectURL) { -- // The object URL can now be revoked as the worker has been loaded -- window.URL.revokeObjectURL(_this._worker.objectURL); -- _this._worker.objectURL = null; -- } - _this._onMessage(msg.data); - }; - return _this; -@@ -96,4 +81,5 @@ var EncoderStream = function (_Transform) { - return EncoderStream; - }(_stream.Transform); - --exports.default = EncoderStream; -\ No newline at end of file -+//exports.default = EncoderStream; -+export default EncoderStream -\ No newline at end of file From c76355f2558dc32deaac0745b27611714ab9d8ad Mon Sep 17 00:00:00 2001 From: Jonas Herzig Date: Mon, 4 May 2020 20:58:16 +0200 Subject: [PATCH 08/23] Revert "Add note about WebRTC version to README (see #93)" This reverts commit 511051025fcba0c15eca083e597d92a5219011e1. We only want the note on the master branch. --- README.md | 5 ----- 1 file changed, 5 deletions(-) diff --git a/README.md b/README.md index 4f072d7..3998917 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,3 @@ -**If you do not have specific requirements, please consider using the `webrtc` version instead: https://github.com/Johni0702/mumble-web/tree/webrtc (note that setup instructions differ significantly). -It should be near identical in features but less susceptible to performance issues. If you are having trouble with the `webrtc` version, please let us know.** - -PRs, unless webrtc-specific, should still target `master`. - # mumble-web Note: This WebRTC branch is not backwards compatible with the current release, i.e. it expects the server/proxy to support WebRTC which neither websockify nor Grumble do. Also note that it requires an extension to the Mumble protocol which has not yet been stabilized and as such may change at any time, so make sure to keep mumble-web and mumble-web-proxy in sync. From 456a2fcf8c019e6281e0ded41aaab4e5576e1222 Mon Sep 17 00:00:00 2001 From: Jonas Herzig Date: Tue, 5 May 2020 13:19:56 +0200 Subject: [PATCH 09/23] Fix multiple versions of `mumble-client` being bundled See https://github.com/Johni0702/mumble-web/issues/93#issuecomment-623986066 --- package-lock.json | 6 ++---- package.json | 2 +- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index 42ee7ee..fa14bdf 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5825,12 +5825,10 @@ } }, "mumble-client-websocket": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/mumble-client-websocket/-/mumble-client-websocket-1.0.0.tgz", - "integrity": "sha1-QFT8SJgnFYo6bP4iw0oYxRdnoL8=", + "version": "github:johni0702/mumble-client-websocket#5b0ed8dc2eaa904d21cd9d11ab7a19558f13701a", + "from": "github:johni0702/mumble-client-websocket#5b0ed8d", "dev": true, "requires": { - "mumble-client": "^1.0.0", "promise": "^7.1.1", "websocket-stream": "^3.2.1" } diff --git a/package.json b/package.json index 40c1c09..7221850 100644 --- a/package.json +++ b/package.json @@ -39,7 +39,7 @@ "lodash.assign": "^4.2.0", "microphone-stream": "^5.0.1", "mumble-client": "github:johni0702/mumble-client#f73a08b", - "mumble-client-websocket": "^1.0.0", + "mumble-client-websocket": "github:johni0702/mumble-client-websocket#5b0ed8d", "node-sass": "^4.13.1", "raw-loader": "^4.0.0", "regexp-replace-loader": "1.0.1", From 73407fa904bf1939ba3bf62c65db3355b3563e7c Mon Sep 17 00:00:00 2001 From: joker-x Date: Tue, 21 Jul 2020 08:23:27 +0200 Subject: [PATCH 10/23] Responsive improvements --- app/index.html | 1 + themes/MetroMumbleLight/main.scss | 46 +++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+) diff --git a/app/index.html b/app/index.html index 349addf..b87bea1 100644 --- a/app/index.html +++ b/app/index.html @@ -2,6 +2,7 @@ + diff --git a/themes/MetroMumbleLight/main.scss b/themes/MetroMumbleLight/main.scss index fbdc413..aeca56a 100644 --- a/themes/MetroMumbleLight/main.scss +++ b/themes/MetroMumbleLight/main.scss @@ -537,3 +537,49 @@ form { .minimal .user-status { height: 19px; } + +/* Mobile view */ + +@media only screen and (max-width: 600px) { + + .toolbar-horizontal ~ .channel-root-container, .toolbar-vertical ~ .channel-root-container { + height:calc(100% - 440px); + position:static; + width:100%; + } + + .toolbar-horizontal ~ .chat, .toolbar-vertical ~ .chat { + position:fixed; + bottom: 60px; + left:0; + width:100%; + height:330px; + y-overflow:auto; + font-size:0.8em; + z-index:10; + } + + .toolbar-vertical { + flex-direction: row; + height: 36px; + margin-top: 4px; + margin-left: 1%; + padding-left: 5px; + } + + #message-box { + margin: 10px 5px 10px 5px; + padding: 10px; + height: 2em; + font-size: 1.2em; + font-weight: bold; + } + + .handle-vertical, .handle-horizontal { + display: none; + } + + .dialog { + min-width: 350px; + } +} From 53992a1f59ba22f29e0b4ab2a275c9e5ffe341b7 Mon Sep 17 00:00:00 2001 From: joker-x Date: Tue, 21 Jul 2020 09:58:54 +0200 Subject: [PATCH 11/23] Apply mobile view if height >= 600px and width >= 320px only --- themes/MetroMumbleLight/main.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/themes/MetroMumbleLight/main.scss b/themes/MetroMumbleLight/main.scss index aeca56a..84dd800 100644 --- a/themes/MetroMumbleLight/main.scss +++ b/themes/MetroMumbleLight/main.scss @@ -540,7 +540,7 @@ form { /* Mobile view */ -@media only screen and (max-width: 600px) { +@media only screen and (max-width: 600px) and (min-width: 320px) and (min-height: 600px) { .toolbar-horizontal ~ .channel-root-container, .toolbar-vertical ~ .channel-root-container { height:calc(100% - 440px); From 335f46603ac57dfd4375a6b0de7de5cbbf2f0335 Mon Sep 17 00:00:00 2001 From: mspecht Date: Tue, 6 Oct 2020 16:34:01 +0200 Subject: [PATCH 12/23] Add tooltips and alt texts to toolbar buttons --- app/index.html | 40 ++++++++++++++++++++++++++-------------- app/index.js | 25 +++++++++++++++++++++++++ loc/en.json | 13 +++++++++++++ 3 files changed, 64 insertions(+), 14 deletions(-) diff --git a/app/index.html b/app/index.html index b87bea1..02e600a 100644 --- a/app/index.html +++ b/app/index.html @@ -463,40 +463,52 @@
- - + Switch Orientation + Switch Orientation + rel="connect" src="/svg/applications-internet.svg" + title="Connect to Server" alt="Connection"> + css: { disabled: !thisUser() }" + title="Information" alt="Information">
+ rel="mute" src="/svg/audio-input-microphone.svg" + title="Mute" alt="Mute"> + rel="unmute" src="/svg/audio-input-microphone-muted.svg" + title="Unmute" alt="Unmute"> + rel="deaf" src="/svg/audio-output.svg" + title="Deafen" alt="Deafen"> + rel="undeaf" src="/svg/audio-output-deafened.svg" + title="Undeafen" alt="Undeafen"> + rel="record" src="/svg/media-record.svg" + title="Record" alt="Record">
+ rel="comment" src="/svg/toolbar-comment.svg" + title="Comment" alt="Comment">
+ rel="settings" src="/svg/config_basic.svg" + title="Settings" alt="Settings">
+ rel="Source Code" src="/svg/source-code.svg" + title="Open Soure Code" alt="Open Source Code">