From bd54faee86b44ee1532a9058275f64762d14a2f9 Mon Sep 17 00:00:00 2001 From: Martin Klampfer <martin.klampfer@fairkom.eu> Date: Thu, 17 Jun 2021 20:09:06 +0200 Subject: [PATCH] sliders now correctly control original floor volume per-channel added the component TranslationSettings which contains the volume sliders --- .../ui/components/actions-bar/component.jsx | 5 +- .../ui/components/translations/component.jsx | 20 ++-- .../user-list/user-list-content/component.jsx | 11 +++ .../user-list/user-list-content/container.jsx | 3 + .../translation-settings/component.jsx | 93 +++++++++++++++++++ .../translation-settings/styles.scss | 5 + .../ui/services/audio-manager/index.js | 28 +++--- bigbluebutton-html5/public/locales/de.json | 3 +- bigbluebutton-html5/public/locales/en.json | 3 +- 9 files changed, 137 insertions(+), 34 deletions(-) create mode 100644 bigbluebutton-html5/imports/ui/components/user-list/user-list-content/translation-settings/component.jsx create mode 100644 bigbluebutton-html5/imports/ui/components/user-list/user-list-content/translation-settings/styles.scss diff --git a/bigbluebutton-html5/imports/ui/components/actions-bar/component.jsx b/bigbluebutton-html5/imports/ui/components/actions-bar/component.jsx index 8283f3f2dd..1196be6c5f 100755 --- a/bigbluebutton-html5/imports/ui/components/actions-bar/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/actions-bar/component.jsx @@ -122,10 +122,11 @@ class ActionsBar extends PureComponent { } } if (result) { + AudioManager.setTranslationFloorVolumeByExt(languageExtension); // AudioManager.setFloorOutputVolume(FLOOR_TRANSLATION_VOLUME); - // transaudio.volume = 1 + transaudio.volume = 1 } else { - // AudioManager.setFloorOutputVolume(1.0); + AudioManager.setFloorOutputVolume(1.0); } } }, 500); diff --git a/bigbluebutton-html5/imports/ui/components/translations/component.jsx b/bigbluebutton-html5/imports/ui/components/translations/component.jsx index 07daf538d3..ddd019dade 100644 --- a/bigbluebutton-html5/imports/ui/components/translations/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/translations/component.jsx @@ -7,6 +7,7 @@ import { makeCall } from '/imports/ui/services/api'; import Meeting from "/imports/ui/services/meeting"; import Button from '/imports/ui/components/button/component'; import AudioManager from '/imports/ui/services/audio-manager'; +import TranslationManager from '/imports/ui/services/translation-manager'; const intlMessages = defineMessages({ translationsTitle: { @@ -63,6 +64,10 @@ class Translations extends Component{ }) } + componentDidUpdate() { + TranslationManager.$languagesChanged.next(null); + } + createEditForm = () => { if( this.state.languages.length < 8 ){ this.state.languages.push({name:"?", edit:"true"}) @@ -77,6 +82,7 @@ class Translations extends Component{ this.state.languages[index].name = name; this.state.languages[index].edit = false; this.setState(this.state) + } deletionHandler = (index)=>{ @@ -118,7 +124,6 @@ class Translations extends Component{ active: false, warning: null, speechDetectionThreshold: AudioManager.$translatorSpeechDetectionThresholdChanged.value, - channelVolume: AudioManager.translationChannelVolume } componentWillUnmount() { @@ -137,15 +142,6 @@ class Translations extends Component{ pEvent.preventDefault(); } - setTranslationChannelVolume(pEvent) { - if(pEvent.target.dataset.hasOwnProperty("ext")) { - AudioManager.$translationChannelVolumeChanged.next({ - extension: pEvent.target.dataset["ext"], - volume: pEvent.target.value / 100 - }); - } - } - render() { const { intl, @@ -190,9 +186,7 @@ class Translations extends Component{ deletionHandler={this.deletionHandler} intl={intl} /> - <div> - <input type="range" data-ext={index} id="volume" name="volume" min="0" max="100" value={this.state.channelVolume[index]} onChange={this.setTranslationChannelVolume.bind(this)}/> - </div> + </div>); } }, this)} diff --git a/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/component.jsx b/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/component.jsx index 108e0e14f3..5441c46c75 100755 --- a/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/component.jsx @@ -6,6 +6,7 @@ import UserMessages from './user-messages/container'; import UserNotesContainer from './user-notes/container'; import UserCaptionsContainer from './user-captions/container'; import WaitingUsers from './waiting-users/component'; +import TranslationSettings from "./translation-settings/component"; import UserPolls from './user-polls/component'; import Translations from "./translations/component" import BreakoutRoomItem from './breakout-room/component'; @@ -50,6 +51,7 @@ class UserContent extends PureComponent { startedChats, amIModerator, meetingIsBreakout, + hasLanguages } = this.props; return ( @@ -95,6 +97,15 @@ class UserContent extends PureComponent { ) : null } + {hasLanguages ? ( + <TranslationSettings + {...{ + intl, + }} + /> + ) : null + } + {amIModerator && !meetingIsBreakout ? ( <Translations diff --git a/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/container.jsx b/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/container.jsx index 2debb419b1..6a6e42644d 100644 --- a/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/container.jsx +++ b/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/container.jsx @@ -6,6 +6,7 @@ import Storage from '/imports/ui/services/storage/session'; import UserContent from './component'; import GuestUsers from '/imports/api/guest-users/'; import { UsersContext } from '/imports/ui/components/components-data/users-context/context'; +import ActionsBarService from "../../actions-bar/service"; const CLOSED_CHAT_LIST_KEY = 'closedChatList'; const STARTED_CHAT_LIST_KEY = 'startedChatList'; @@ -32,4 +33,6 @@ export default withTracker(() => ({ approved: false, denied: false, }).fetch(), + hasLanguages: ActionsBarService.hasLanguages(), + }))(UserContentContainer); diff --git a/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/translation-settings/component.jsx b/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/translation-settings/component.jsx new file mode 100644 index 0000000000..a061beebfc --- /dev/null +++ b/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/translation-settings/component.jsx @@ -0,0 +1,93 @@ +import {styles} from "./styles.scss"; +import {styles as cstyles} from '/imports/ui/components/user-list/user-list-content/styles'; + +import React, {Component} from 'react'; +import {defineMessages} from 'react-intl'; +import AudioManager from '/imports/ui/services/audio-manager'; +import Meeting from "../../../../services/meeting"; + + +const intlMessages = defineMessages({ + originLanguage: { + id: 'app.translation.language.origin', + description: 'Name of origin language', + defaultMessage: 'Floor', + }, + noneLanguage: { + id: 'app.translation.language.none', + description: 'Name of none language', + defaultMessage: 'None', + }, + originalVolume: { + id: 'app.translation.language.originalVolume', + description: 'Name of original volume header', + defaultMessage: 'None', + } +}); + +class TranslationSettings extends Component { + + state = { + languages: [], + translationOriginalVolume: AudioManager.translationOriginalVolume + }; + + componentDidMount() { + + this.getLanguages(); + } + + getLanguages() { + Meeting.getLanguages().then(languages => { + languages.push({ + name: this.props.intl.formatMessage(this.props.translator ? intlMessages.noneLanguage : intlMessages.originLanguage), + extension: -1, + }); + + this.setState({languages: languages}) + + }) + this.forceUpdate(); + } + + setTranslationOriginalVolume(pEvent) { + if (pEvent.target.dataset.hasOwnProperty("ext")) { + AudioManager.$translationOriginalVolumeChanged.next({ + extension: pEvent.target.dataset["ext"], + volume: pEvent.target.value + }); + } + } + + render() { + const { + intl, + } = this.props; + + return ( + <div key={"translation-settings"}> + <div className={cstyles.container}> + <h2 className={cstyles.smallTitle}> + {intl.formatMessage(intlMessages.originalVolume)} + </h2> + </div> + {this.state.languages.map(function (language, index) { + if(language.extension >= 0) return ( + <div className={styles.translationOriginalVolumePanel}> + <div>{language.name}:</div> + + <input type="range" data-ext={index} id="volume" name="volume" min="0" max="1" step=".01" + defaultValue={this.state.translationOriginalVolume[index]} + onChange={this.setTranslationOriginalVolume.bind(this)}/> + </div> + ) + }, this) + } + </div> + + + ); + } +} + +export default TranslationSettings; diff --git a/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/translation-settings/styles.scss b/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/translation-settings/styles.scss new file mode 100644 index 0000000000..fb34f051e8 --- /dev/null +++ b/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/translation-settings/styles.scss @@ -0,0 +1,5 @@ +@import "../styles.scss"; + +.translationOriginalVolumePanel { + margin: 8px 0 8px 4px; +} diff --git a/bigbluebutton-html5/imports/ui/services/audio-manager/index.js b/bigbluebutton-html5/imports/ui/services/audio-manager/index.js index 09d3b183d8..8a8b56090e 100755 --- a/bigbluebutton-html5/imports/ui/services/audio-manager/index.js +++ b/bigbluebutton-html5/imports/ui/services/audio-manager/index.js @@ -61,8 +61,8 @@ class AudioManager { this.$translatorSpeakingChanged = new BehaviorSubject(false) this.$translatorChannelLanguageExtensionChanged = new BehaviorSubject(-1); - this.$translationChannelVolumeChanged = new BehaviorSubject({ extension: -1, volume: 0 }); - this.translationChannelVolume = []; + this.$translationOriginalVolumeChanged = new BehaviorSubject({ extension: -1, volume: 0 }); + this.translationOriginalVolume = []; this.defineProperties({ isMuted: false, @@ -107,22 +107,14 @@ class AudioManager { } }); - this.$translationChannelVolumeChanged.subscribe((pLang) => { + this.$translationOriginalVolumeChanged.subscribe((pLang) => { if( pLang.hasOwnProperty("extension") && pLang.hasOwnProperty("volume") ) { - this.translationChannelVolume[pLang.extension] = pLang.volume; - - let tCExt = parseInt((this.translationLanguageExtension+ '').charAt(2)); - if(tCExt == pLang.extension) { - let audioElement = document.getElementById("remote-media"); - if(audioElement) audioElement.volume = pLang.volume; - } + this.translationOriginalVolume[pLang.extension] = pLang.volume; } }) - - } init(userData, audioEventHandler) { @@ -834,11 +826,6 @@ class AudioManager { //create a dummy stream that does nothing at all let ac = new AudioContext(); let dest = ac.createMediaStreamDestination(); - let audioElement = document.getElementById("translation-media"); - let tIdx = parseInt((languageExtension+ '').charAt(2)); - if(audioElement) audioElement.volume = - Array.isArray(this.translationChannelVolume) && typeof this.translationChannelVolume[tIdx] !== 'undefined' ? - this.translationChannelVolume[tIdx] : 1; if (languageExtension >= 0) { const callOptions = { @@ -932,6 +919,13 @@ class AudioManager { } + setTranslationFloorVolumeByExt(pExt) { + let tIdx = parseInt((pExt+ '').charAt(2)); + let tVol = Array.isArray(this.translationOriginalVolume) && typeof this.translationOriginalVolume[tIdx] !== 'undefined' ? + this.translationOriginalVolume[tIdx] : 1; + this.setFloorOutputVolume(tVol); + } + setFloorOutputVolume(volume) { const floorMediaElement = document.querySelector(MEDIA_TAG); floorMediaElement.volume = volume; diff --git a/bigbluebutton-html5/public/locales/de.json b/bigbluebutton-html5/public/locales/de.json index 8158b754af..cfd63cdd1e 100644 --- a/bigbluebutton-html5/public/locales/de.json +++ b/bigbluebutton-html5/public/locales/de.json @@ -821,7 +821,8 @@ "app.translation.filterMarker.languageListening": "hören", "app.translation.filterMarker.languageTranslating": "sprechen", "app.translation.speechDetectionThresholdInfo": "Sprachschwellenwert f. Übersetzer (-100 bis 0)", - "app.translation.speechDetectionThresholdExplanation": "The system tries to recognize when you are actually speaking while interpreting. The volume of the original audio is then lowered for the listeners so they can hear your voice. The center of the mic-symbol in the mute-button turns solid when speech is recognized. Use this feedback to fine-tune the threshold to your current setup. Change this setting from -100 (most sensitive / always on) to 0 (least sensitive / disabled). Click \"set\" to activate the new setting. This affects only you in the current session. Changes are not saved. Tip: Make sure your microphone provides a decent audio-level without clipping (check system mixer-settings)." + "app.translation.speechDetectionThresholdExplanation": "The system tries to recognize when you are actually speaking while interpreting. The volume of the original audio is then lowered for the listeners so they can hear your voice. The center of the mic-symbol in the mute-button turns solid when speech is recognized. Use this feedback to fine-tune the threshold to your current setup. Change this setting from -100 (most sensitive / always on) to 0 (least sensitive / disabled). Click \"set\" to activate the new setting. This affects only you in the current session. Changes are not saved. Tip: Make sure your microphone provides a decent audio-level without clipping (check system mixer-settings).", + "app.translation.language.originalVolume": "Original-Laustärke" } diff --git a/bigbluebutton-html5/public/locales/en.json b/bigbluebutton-html5/public/locales/en.json index 44476c33b3..78853232ff 100755 --- a/bigbluebutton-html5/public/locales/en.json +++ b/bigbluebutton-html5/public/locales/en.json @@ -832,6 +832,7 @@ "app.translation.filterMarker.languageListening": "listening", "app.translation.filterMarker.languageTranslating": "speaking", "app.translation.speechDetectionThresholdInfo": "Speech detection threshold (-100 to 0)", - "app.translation.speechDetectionThresholdExplanation": "The system tries to recognize when you are actually speaking while interpreting. The volume of the original audio is then lowered for the listeners so they can hear your voice. The center of the mic-symbol in the mute-button turns solid when speech is recognized. Use this feedback to fine-tune the threshold to your current setup. Change this setting from -100 (most sensitive / always on) to 0 (least sensitive / disabled). Click \"set\" to activate the new setting. This affects only you in the current session. Changes are not saved. Tip: Make sure your microphone provides a decent audio-level without clipping (check system mixer-settings)." + "app.translation.speechDetectionThresholdExplanation": "The system tries to recognize when you are actually speaking while interpreting. The volume of the original audio is then lowered for the listeners so they can hear your voice. The center of the mic-symbol in the mute-button turns solid when speech is recognized. Use this feedback to fine-tune the threshold to your current setup. Change this setting from -100 (most sensitive / always on) to 0 (least sensitive / disabled). Click \"set\" to activate the new setting. This affects only you in the current session. Changes are not saved. Tip: Make sure your microphone provides a decent audio-level without clipping (check system mixer-settings).", + "app.translation.language.originalVolume": "Original Volume" } -- GitLab