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