diff --git a/src/assets/icons/icon.tsx b/src/assets/icons/icon.tsx
new file mode 100644
index 00000000..e84bf61a
--- /dev/null
+++ b/src/assets/icons/icon.tsx
@@ -0,0 +1,12 @@
+import styled from "@emotion/styled";
+import MicMute from "./mic_off.svg";
+import MicUnmute from "./mic_on.svg";
+
+const Icon = styled.img`
+ width: 8rem;
+ padding-right: 1em;
+`;
+
+export const MicMuted = () => ;
+
+export const MicUnmuted = () => ;
diff --git a/src/assets/icons/mic_off.svg b/src/assets/icons/mic_off.svg
new file mode 100644
index 00000000..3b7b7b8a
--- /dev/null
+++ b/src/assets/icons/mic_off.svg
@@ -0,0 +1,5 @@
+
\ No newline at end of file
diff --git a/src/assets/icons/mic_on.svg b/src/assets/icons/mic_on.svg
new file mode 100644
index 00000000..eafe0658
--- /dev/null
+++ b/src/assets/icons/mic_on.svg
@@ -0,0 +1,9 @@
+
\ No newline at end of file
diff --git a/src/components/production-line/production-line.tsx b/src/components/production-line/production-line.tsx
index dbb04072..6ea0672d 100644
--- a/src/components/production-line/production-line.tsx
+++ b/src/components/production-line/production-line.tsx
@@ -9,16 +9,25 @@ import { ActionButton } from "../landing-page/form-elements.tsx";
import { UserList } from "./user-list.tsx";
import { API } from "../../api/api.ts";
import { noop } from "../../helpers.ts";
+import { MicMuted, MicUnmuted } from "../../assets/icons/icon.tsx";
import { Spinner } from "../loader/loader.tsx";
const TempDiv = styled.div`
padding: 1rem;
`;
+
+const UserControlBtn = styled.button`
+ background-color: transparent;
+ border-color: transparent;
+`;
+
export const ProductionLine: FC = () => {
// const { productionId, lineId } = useParams();
- const [{ joinProductionOptions }, dispatch] = useGlobalState();
+ const [{ joinProductionOptions, mediaStreamInput }, dispatch] =
+ useGlobalState();
const navigate = useNavigate();
const audioContainerRef = useRef(null);
+ const [micMute, setMicMute] = useState(true);
const [participants, setParticipants] = useState<
{ name: string; sessionid: string }[] | null
>(null);
@@ -81,7 +90,15 @@ export const ProductionLine: FC = () => {
navigate("/");
};
- // Mute/Unmute mic
+ useEffect(() => {
+ if (mediaStreamInput) {
+ mediaStreamInput.getTracks().forEach((track) => {
+ // eslint-disable-next-line no-param-reassign
+ track.enabled = !micMute;
+ });
+ }
+ }, [mediaStreamInput, micMute]);
+
// Mute/Unmute speaker
// Show active sink and mic
// Exit button (link to /, clear production from state)
@@ -95,6 +112,11 @@ export const ProductionLine: FC = () => {
{!loading && (
<>
Production View
+
+ setMicMute(!micMute)}>
+ {micMute ? : }
+
+
{audioElements.length && (
Incoming Audio Channels: {audioElements.length}
diff --git a/src/components/production-line/use-rtc-connection.ts b/src/components/production-line/use-rtc-connection.ts
index 04fc2438..a19860b2 100644
--- a/src/components/production-line/use-rtc-connection.ts
+++ b/src/components/production-line/use-rtc-connection.ts
@@ -198,6 +198,11 @@ export const useRtcConnection = ({
rtcPeerConnection,
inputAudioStream,
});
+
+ dispatch({
+ type: "CONNECTED_MEDIASTREAM",
+ payload: inputAudioStream,
+ });
}
const { teardown } = establishConnection({
@@ -217,6 +222,11 @@ export const useRtcConnection = ({
onConnectionStateChange
);
+ dispatch({
+ type: "CONNECTED_MEDIASTREAM",
+ payload: null,
+ });
+
rtcPeerConnection.close();
};
}, [
diff --git a/src/global-state/global-state-actions.ts b/src/global-state/global-state-actions.ts
index b81f5c55..53522e7b 100644
--- a/src/global-state/global-state-actions.ts
+++ b/src/global-state/global-state-actions.ts
@@ -5,7 +5,8 @@ export type TGlobalStateAction =
| TProductionCreated
| TProductionListFetched
| TUpdateDevicesAction
- | TUpdateJoinProductionOptions;
+ | TUpdateJoinProductionOptions
+ | TMediaStream;
export type TPublishError = {
type: "ERROR";
@@ -29,3 +30,8 @@ export type TUpdateJoinProductionOptions = {
type: "UPDATE_JOIN_PRODUCTION_OPTIONS";
payload: TJoinProductionOptions | null;
};
+
+export type TMediaStream = {
+ type: "CONNECTED_MEDIASTREAM";
+ payload: MediaStream | null;
+};
diff --git a/src/global-state/global-state-reducer.ts b/src/global-state/global-state-reducer.ts
index b397fbd2..ed1a95e8 100644
--- a/src/global-state/global-state-reducer.ts
+++ b/src/global-state/global-state-reducer.ts
@@ -9,6 +9,7 @@ const initialGlobalState: TGlobalState = {
reloadProductionList: true,
devices: null,
joinProductionOptions: null,
+ mediaStreamInput: null,
};
const globalReducer: Reducer = (
@@ -43,6 +44,11 @@ const globalReducer: Reducer = (
...state,
joinProductionOptions: action.payload,
};
+ case "CONNECTED_MEDIASTREAM":
+ return {
+ ...state,
+ mediaStreamInput: action.payload,
+ };
default:
return state;
}
diff --git a/src/global-state/types.ts b/src/global-state/types.ts
index acadd021..8eb0b69c 100644
--- a/src/global-state/types.ts
+++ b/src/global-state/types.ts
@@ -9,4 +9,5 @@ export type TGlobalState = {
reloadProductionList: boolean;
devices: MediaDeviceInfo[] | null;
joinProductionOptions: TJoinProductionOptions | null;
+ mediaStreamInput: MediaStream | null;
};