refactor recording and stuff

This commit is contained in:
Marks Polakovs 2020-04-10 15:13:27 +02:00
parent 1e9f6aeaed
commit 96aa986e08
5 changed files with 82 additions and 22 deletions

1
Jenkinsfile vendored
View file

@ -70,6 +70,7 @@ pipeline {
steps { steps {
sshagent(credentials: ['ury']) { sshagent(credentials: ['ury']) {
sh 'scp -v -o StrictHostKeyChecking=no server.py liquidsoap@dolby.ury:/opt/webstudioserver/server.py' sh 'scp -v -o StrictHostKeyChecking=no server.py liquidsoap@dolby.ury:/opt/webstudioserver/server.py'
sh 'scp -v -o StrictHostKeyChecking=no requirements.txt liquidsoap@dolby.ury:/opt/webstudioserver/requirements.txt'
} }
} }
} }

View file

@ -7,11 +7,12 @@ import * as NavbarState from "../navbar/state";
import { ConnectionStateEnum, Streamer } from "./streamer"; import { ConnectionStateEnum, Streamer } from "./streamer";
import { RecordingStreamer } from "./recording_streamer"; import { RecordingStreamer } from "./recording_streamer";
export let streamer: Streamer | null = null; export let streamer: WebRTCStreamer | null = null;
interface BroadcastState { interface BroadcastState {
tracklisting: boolean; tracklisting: boolean;
connectionState: ConnectionStateEnum; connectionState: ConnectionStateEnum;
recordingState: ConnectionStateEnum;
} }
const broadcastState = createSlice({ const broadcastState = createSlice({
@ -19,6 +20,7 @@ const broadcastState = createSlice({
initialState: { initialState: {
tracklisting: false, tracklisting: false,
connectionState: "NOT_CONNECTED", connectionState: "NOT_CONNECTED",
recordingState: "NOT_CONNECTED"
} as BroadcastState, } as BroadcastState,
reducers: { reducers: {
toggleTracklisting(state) { toggleTracklisting(state) {
@ -27,6 +29,9 @@ const broadcastState = createSlice({
setConnectionState(state, action: PayloadAction<ConnectionStateEnum>) { setConnectionState(state, action: PayloadAction<ConnectionStateEnum>) {
state.connectionState = action.payload; state.connectionState = action.payload;
}, },
setRecordingState(state, action: PayloadAction<ConnectionStateEnum>) {
state.recordingState = action.payload;
},
}, },
}); });
@ -71,34 +76,46 @@ export function sendTracklistStart(trackid: number): Promise<TrackListItem> {
}); });
} }
const RECORD = false; export const startStreaming = (): AppThunk => async (dispatch, getState) => {
if (!getState().session.userCanBroadcast) {
export const connect = (): AppThunk => async (dispatch, getState) => { dispatch(
if (RECORD) { NavbarState.showAlert({
streamer = new RecordingStreamer(MixerState.destination.stream); color: "warning",
} else { content: "You are not WebStudio Trained and cannot go live.",
if (!getState().session.userCanBroadcast) { closure: 7000,
dispatch( })
NavbarState.showAlert({ );
color: "warning", return;
content: "You are not WebStudio Trained and cannot go live.",
closure: 7000,
})
);
return;
}
streamer = new WebRTCStreamer(MixerState.destination.stream);
} }
streamer = new WebRTCStreamer(MixerState.destination.stream);
streamer.addConnectionStateListener((state) => { streamer.addConnectionStateListener((state) => {
dispatch(broadcastState.actions.setConnectionState(state)); dispatch(broadcastState.actions.setConnectionState(state));
}); });
await streamer.start(); await streamer.start();
}; };
export const disconnect = (): AppThunk => async (dispatch) => { export const stopStreaming = (): AppThunk => async (dispatch) => {
if (streamer) { if (streamer) {
await streamer.stop(); await streamer.stop();
} else { } else {
console.warn("disconnect called with no streamer!"); console.warn("disconnect called with no streamer!");
} }
}; };
let recorder: RecordingStreamer;
export const startRecording = (): AppThunk => async dispatch => {
recorder = new RecordingStreamer(MixerState.destination.stream);
recorder.addConnectionStateListener((state) => {
dispatch(broadcastState.actions.setConnectionState(state));
});
await recorder.start();
}
export const stopRecording = (): AppThunk => async dispatch => {
if (recorder) {
await recorder.stop();
} else {
console.warn("stopRecording called with no recorder!");
}
}

View file

@ -12,6 +12,7 @@ export function NavBar() {
const dispatch = useDispatch(); const dispatch = useDispatch();
const sessionState = useSelector((state: RootState) => state.session); const sessionState = useSelector((state: RootState) => state.session);
const broadcastState = useSelector((state: RootState) => state.broadcast); const broadcastState = useSelector((state: RootState) => state.broadcast);
const settings = useSelector((state: RootState) => state.settings);
const redirect_url = encodeURIComponent(window.location.toString()); const redirect_url = encodeURIComponent(window.location.toString());
return ( return (
<> <>
@ -42,6 +43,25 @@ export function NavBar() {
: "Not Tracklisting"}{" "} : "Not Tracklisting"}{" "}
</button> </button>
</li> </li>
{settings.enableRecording && (
<li className="nav-item nav-link">
<button
className=""
onClick={() =>
dispatch(
broadcastState.recordingState ===
"NOT_CONNECTED"
? BroadcastState.startRecording()
: BroadcastState.stopRecording()
)
}
>
{broadcastState.recordingState === "NOT_CONNECTED"
? "Start Recording"
: "Stop Recording"}
</button>
</li>
)}
<li className="nav-item nav-link"> <li className="nav-item nav-link">
<button <button
className="" className=""
@ -49,8 +69,8 @@ export function NavBar() {
dispatch( dispatch(
broadcastState.connectionState === broadcastState.connectionState ===
"NOT_CONNECTED" "NOT_CONNECTED"
? BroadcastState.connect() ? BroadcastState.startStreaming()
: BroadcastState.disconnect() : BroadcastState.stopStreaming()
) )
} }
> >

View file

@ -27,6 +27,24 @@ export function AdvancedTab() {
Show showplan debugging information Show showplan debugging information
</label> </label>
</div> </div>
<div className="form-check">
<input
className="form-check-input"
type="checkbox"
checked={settings.enableRecording}
onChange={(e) =>
dispatch(
changeSetting({
key: "enableRecording",
val: e.target.checked,
})
)
}
/>
<label className="form-check-label">
Enable recording
</label>
</div>
</> </>
); );
} }

View file

@ -2,11 +2,15 @@ import { createSlice, PayloadAction } from "@reduxjs/toolkit";
interface Settings { interface Settings {
showDebugInfo: boolean; showDebugInfo: boolean;
enableRecording: boolean;
} }
const settingsState = createSlice({ const settingsState = createSlice({
name: "settings", name: "settings",
initialState: {} as Settings, initialState: {
showDebugInfo: false,
enableRecording: false
} as Settings,
reducers: { reducers: {
changeSetting<K extends keyof Settings>(state: Settings, action: PayloadAction<{ key: K, val: Settings[K] }>) { changeSetting<K extends keyof Settings>(state: Settings, action: PayloadAction<{ key: K, val: Settings[K] }>) {
state[action.payload.key] = action.payload.val; state[action.payload.key] = action.payload.val;