diff --git a/frontend/react/src/audio/audiomanager.ts b/frontend/react/src/audio/audiomanager.ts
index e64a5a22..94c1a0cb 100644
--- a/frontend/react/src/audio/audiomanager.ts
+++ b/frontend/react/src/audio/audiomanager.ts
@@ -54,7 +54,10 @@ export class AudioManager {
/* Connect the audio websocket */
let res = this.#address.match(/(?:http|https):\/\/(.+):/);
let wsAddress = res ? res[1] : this.#address;
- this.#socket = new WebSocket(`wss://refugees.dcsolympus.com/audio`);
+ if (this.#address.includes("https"))
+ this.#socket = new WebSocket(`wss://${wsAddress}/${getApp().getConfig()['WSAddress']}`);
+ else
+ this.#socket = new WebSocket(`ws://${wsAddress}:${getApp().getConfig()['WSPort']}`);
/* Log the opening of the connection */
this.#socket.addEventListener("open", (event) => {
@@ -63,7 +66,7 @@ export class AudioManager {
/* Log any websocket errors */
this.#socket.addEventListener("error", (event) => {
- console.log(event);
+ console.log("An error occurred while connecting the WebSocket: " + event);
});
/* Handle the reception of a new message */
diff --git a/frontend/react/src/audio/unitsink.ts b/frontend/react/src/audio/unitsink.ts
index 9d587bdf..7539577e 100644
--- a/frontend/react/src/audio/unitsink.ts
+++ b/frontend/react/src/audio/unitsink.ts
@@ -37,7 +37,7 @@ export class UnitSink extends AudioSink {
});
Object.keys(this.#unitPipelines).forEach((unitID) => {
- if (!(unitID in getApp().getAudioManager().getSRSClientsUnitIDs())) {
+ if (!(getApp().getAudioManager().getSRSClientsUnitIDs().includes(parseInt(unitID)))) {
delete this.#unitPipelines[unitID];
}
});
diff --git a/frontend/react/src/ui/panels/components/menu.tsx b/frontend/react/src/ui/panels/components/menu.tsx
index 34069b9c..aa8f5456 100644
--- a/frontend/react/src/ui/panels/components/menu.tsx
+++ b/frontend/react/src/ui/panels/components/menu.tsx
@@ -29,12 +29,13 @@ export function Menu(props: {
>
@@ -78,13 +79,9 @@ export function Menu(props: {
`}
onClick={() => setHide(!hide)}
>
- {hide ? (
-
- ) : (
-
- )}
+ {hide ? : }
)}
diff --git a/frontend/react/src/ui/panels/unitcontrolmenu.tsx b/frontend/react/src/ui/panels/unitcontrolmenu.tsx
index f7566309..2a89a0fb 100644
--- a/frontend/react/src/ui/panels/unitcontrolmenu.tsx
+++ b/frontend/react/src/ui/panels/unitcontrolmenu.tsx
@@ -49,6 +49,7 @@ import { OlNumberInput } from "../components/olnumberinput";
import { Radio, TACAN } from "../../interfaces";
import { OlStringInput } from "../components/olstringinput";
import { OlFrequencyInput } from "../components/olfrequencyinput";
+import { UnitSink } from "../../audio/unitsink";
export function UnitControlMenu(props: { open: boolean; onClose: () => void }) {
const [selectedUnits, setSelectedUnits] = useState([] as Unit[]);
@@ -62,11 +63,12 @@ export function UnitControlMenu(props: { open: boolean; onClose: () => void }) {
emissionsCountermeasures: undefined as undefined | string,
shotsScatter: undefined as undefined | number,
shotsIntensity: undefined as undefined | number,
- operateAs: undefined as undefined | string,
+ operateAs: undefined as undefined | Coalition,
followRoads: undefined as undefined | boolean,
isActiveAWACS: undefined as undefined | boolean,
isActiveTanker: undefined as undefined | boolean,
onOff: undefined as undefined | boolean,
+ isAudioSink: undefined as undefined | boolean,
});
const [selectionFilter, setSelectionFilter] = useState({
control: {
@@ -209,6 +211,18 @@ export function UnitControlMenu(props: { open: boolean; onClose: () => void }) {
onOff: (unit: Unit) => {
return unit.getOnOff();
},
+ isAudioSink: (unit: Unit) => {
+ return (
+ getApp()?.getAudioManager().getSinks().filter((sink) => {
+ return sink instanceof UnitSink}).length > 0 &&
+ getApp()
+ ?.getAudioManager()
+ .getSinks()
+ .find((sink) => {
+ return sink instanceof UnitSink && sink.getUnit() === unit;
+ }) !== undefined
+ );
+ },
} as { [key in keyof typeof selectedUnitsData]: (unit: Unit) => void };
var updatedData = selectedUnitsData;
@@ -974,10 +988,48 @@ export function UnitControlMenu(props: { open: boolean; onClose: () => void }) {
}}
/>
-
{/* ============== Unit active toggle END ============== */}
>
)}
+ {/* ============== Audio sink toggle START ============== */}
+
+
+ Enable loudspeakers
+
+
{
+ selectedUnits.forEach((unit) => {
+ if (!selectedUnitsData.isAudioSink) {
+ getApp()?.getAudioManager().addUnitSink(unit);
+ setSelectedUnitsData({
+ ...selectedUnitsData,
+ isAudioSink: true,
+ });
+ } else {
+ let sink = getApp()
+ ?.getAudioManager()
+ .getSinks()
+ .find((sink) => {
+ return sink instanceof UnitSink && sink.getUnit() === unit;
+ });
+ if (sink !== undefined) getApp()?.getAudioManager().removeSink(sink);
+
+ setSelectedUnitsData({
+ ...selectedUnitsData,
+ isAudioSink: false,
+ });
+ }
+ });
+ }}
+ />
+
+ {/* ============== Audio sink toggle END ============== */}
)}
{/* ============== Advanced settings START ============== */}
diff --git a/frontend/react/src/unit/unit.ts b/frontend/react/src/unit/unit.ts
index 52830d0b..9f97c328 100644
--- a/frontend/react/src/unit/unit.ts
+++ b/frontend/react/src/unit/unit.ts
@@ -849,20 +849,7 @@ export abstract class Unit extends CustomMarker {
if (targetPosition) getApp().getUnitsManager().addDestination(targetPosition, false, 0, units);
}
);
-
- contextActionSet.addContextAction(
- this,
- "speaker",
- "Make audio source",
- "Make this unit an audio source (loudspeakers)",
- faVolumeHigh,
- null,
- (units: Unit[], _1, _2) => {
- units.forEach((unit) => getApp().getAudioManager().addUnitSink(unit));
- },
- { executeImmediately: true }
- );
-
+
contextActionSet.addDefaultContextAction(this, "default", "Set destination", "", faRoute, null, (units: Unit[], targetUnit, targetPosition) => {
if (targetPosition) {
getApp().getUnitsManager().clearDestinations(units);
diff --git a/olympus.json b/olympus.json
index a5a316ed..c02ba47d 100644
--- a/olympus.json
+++ b/olympus.json
@@ -36,6 +36,7 @@
},
"audio": {
"SRSPort": 5002,
- "WSPort": 4000
+ "WSPort": 4000,
+ "WSAddress": "audio"
}
}