1
0

Signaling seems to be working better now; loads and player state changes persist existing connections.

Signed-off-by: James Ketrenos <james_eikona@ketrenos.com>
This commit is contained in:
James Ketrenos 2022-03-16 01:58:33 -07:00
parent 80fad00cc9
commit 67e319e2c5
3 changed files with 80 additions and 81 deletions

View File

@ -13,7 +13,6 @@ import { GlobalContext } from "./GlobalContext.js";
//import { PingPong } from "./PingPong.js"; //import { PingPong } from "./PingPong.js";
import { PlayerList } from "./PlayerList.js"; import { PlayerList } from "./PlayerList.js";
import { Chat } from "./Chat.js"; import { Chat } from "./Chat.js";
import { MediaAgent } from "./MediaControl.js";
import { Board } from "./Board.js"; import { Board } from "./Board.js";
import { Actions } from "./Actions.js"; import { Actions } from "./Actions.js";
import { base, gamesPath } from './Common.js'; import { base, gamesPath } from './Common.js';
@ -40,7 +39,6 @@ const Table = () => {
const [ name, setName ] = useState(""); const [ name, setName ] = useState("");
const [ error, setError ] = useState(undefined); const [ error, setError ] = useState(undefined);
const [ warning, setWarning ] = useState(undefined); const [ warning, setWarning ] = useState(undefined);
const [ peers, setPeers ] = useState({});
const [loaded, setLoaded] = useState(false); const [loaded, setLoaded] = useState(false);
const [state, setState] = useState(undefined); const [state, setState] = useState(undefined);
@ -49,14 +47,10 @@ const Table = () => {
const [buildActive, setBuildActive] = useState(false); const [buildActive, setBuildActive] = useState(false);
const [cardActive, setCardActive] = useState(undefined); const [cardActive, setCardActive] = useState(undefined);
const [winnerDismissed, setWinnerDismissed] = useState(undefined); const [winnerDismissed, setWinnerDismissed] = useState(undefined);
const [global, setGlobal] = useState({ setPeers }); const [global, setGlobal] = useState({});
const [count, setCount] = useState(0); const [count, setCount] = useState(0);
const fields = [ 'id', 'state', 'color', 'name', 'private' ]; const fields = [ 'id', 'state', 'color', 'name', 'private' ];
useEffect(() => {
console.log(`app - media-agent - peers`, peers);
}, [peers]);
const onWsOpen = (event) => { const onWsOpen = (event) => {
console.log(`ws: open`); console.log(`ws: open`);
setError(""); setError("");
@ -163,14 +157,12 @@ const Table = () => {
if (global.ws !== connection if (global.ws !== connection
|| global.name !== name || global.name !== name
|| global.gameId !== gameId || global.gameId !== gameId) {
|| global.peers !== peers) {
console.log(`board - (app) - setting global`, global, console.log(`board - (app) - setting global`, global,
{connection, name, gameId, peers}); {connection, name, gameId});
setGlobal({ setGlobal({
ws: connection, ws: connection,
name, gameId, peers, name, gameId
setPeers
}); });
} }
@ -313,7 +305,6 @@ const Table = () => {
console.log(`board - (app) - Render with ws: ${ws ? '!' : ''}NULL, connection: ${connection ? '!' : ''}NULL`); console.log(`board - (app) - Render with ws: ${ws ? '!' : ''}NULL, connection: ${connection ? '!' : ''}NULL`);
return <GlobalContext.Provider value={global}> return <GlobalContext.Provider value={global}>
<MediaAgent/>
{ /* <PingPong/> */ } { /* <PingPong/> */ }
<div className="Table"> <div className="Table">
<Activities/> <Activities/>

View File

@ -20,13 +20,13 @@ const Video = ({ srcObject, local, ...props }) => {
return; return;
} }
const ref = refVideo.current; const ref = refVideo.current;
if (debug) console.log('<video> bind'); if (debug) console.log('media-controls <video> bind');
ref.srcObject = srcObject; ref.srcObject = srcObject;
if (local) { if (local) {
ref.muted = true; ref.muted = true;
} }
return () => { return () => {
if (debug) console.log('<video> unbind'); if (debug) console.log('media-controls <video> unbind');
if (ref) { if (ref) {
ref.srcObject = undefined; ref.srcObject = undefined;
} }
@ -35,26 +35,23 @@ const Video = ({ srcObject, local, ...props }) => {
return <video ref={refVideo} {...props} />; return <video ref={refVideo} {...props} />;
} }
const MediaAgent = () => { const MediaAgent = ({setPeers}) => {
const { name, ws, peers, setPeers } = useContext(GlobalContext); const { name, ws } = useContext(GlobalContext);
const [ peers ] = useState({});
const [stream, setStream] = useState(undefined); const [stream, setStream] = useState(undefined);
const onTrack = useCallback((event) => { const onTrack = useCallback((event) => {
const connection = event.target; const connection = event.target;
console.log("media-agent - ontrack", event);
if (debug) console.log("ontrack", event); for (let peer in peers) {
for (let key in peers) { if (peers[peer].connection === connection) {
if (peers[key].connection === connection) { console.log(`media-agent - ontrack - remote ${peer} stream assigned.`);
Object.assign(peers[key].attributes, { Object.assign(peers[peer].attributes, {
srcObject: event.streams[0] srcObject: event.streams[0]
}); });
} }
} }
}, [peers]);
if (debug) console.log(`media-agent - ontrack - remote`, peers);
setPeers(Object.assign({}, peers));
}, [peers, setPeers]);
const refOnTrack = useRef(onTrack); const refOnTrack = useRef(onTrack);
const sendMessage = useCallback((data) => { const sendMessage = useCallback((data) => {
@ -66,12 +63,13 @@ const MediaAgent = () => {
console.log('media-agent - Signaling server said to add peer:', config); console.log('media-agent - Signaling server said to add peer:', config);
if (!stream) { if (!stream) {
console.log(`No local media stream`); console.log(`media-agent - No local media stream`);
return; return;
} }
const peer_id = config.peer_id; const peer_id = config.peer_id;
if (peer_id in peers) { if (peer_id in peers) {
/* This is normal */
console.log(`media-agent - addPeer - ${peer_id} already in peers`); console.log(`media-agent - addPeer - ${peer_id} already in peers`);
return; return;
} }
@ -92,16 +90,14 @@ const MediaAgent = () => {
credential: "1!viagenie" credential: "1!viagenie"
} }
*/ */
] ]
}); });
peers[peer_id] = { peers[peer_id] = {
name: peer_id,
connection, connection,
muted: false, initialized: false,
videoOn: true, attributes: {}
attributes: {
}
}; };
console.log(`media-agent - addPeer - remote`, peers); console.log(`media-agent - addPeer - remote`, peers);
setPeers(Object.assign({}, peers)); setPeers(Object.assign({}, peers));
@ -113,7 +109,7 @@ const MediaAgent = () => {
connection.addEventListener('icecandidateerror', (event) => { connection.addEventListener('icecandidateerror', (event) => {
if (event.errorCode === 701) { if (event.errorCode === 701) {
if (connection.icegatheringstate === 'gathering') { if (connection.icegatheringstate === 'gathering') {
console.log(`Unable to reach host: ${event.url}`); console.log(`media-agent - Unable to reach host: ${event.url}`);
} else { } else {
console.error(`media-agent - icecandidateerror - `, event.errorCode, event.hostcandidate, event.url, event.errorText); console.error(`media-agent - icecandidateerror - `, event.errorCode, event.hostcandidate, event.url, event.errorText);
} }
@ -122,18 +118,18 @@ const MediaAgent = () => {
connection.onicecandidate = (event) => { connection.onicecandidate = (event) => {
if (!event.candidate) { if (!event.candidate) {
console.error(`media-agent - icecanditate - gathering is complete: ${connection.connectionState}`); console.log(`media-agent - icecanditate - gathering is complete: ${connection.connectionState}`);
return; return;
} }
/* If a srflx candidate was found, notify that the STUN server works! */ /* If a srflx candidate was found, notify that the STUN server works! */
if (event.candidate.type === "srflx"){ if (event.candidate.type === "srflx"){
console.log("The STUN server is reachable!"); console.log("media-agent - The STUN server is reachable!");
console.log(` Your Public IP Address is: ${event.candidate.address}`); console.log(`media-agent - Your Public IP Address is: ${event.candidate.address}`);
} }
/* If a relay candidate was found, notify that the TURN server works! */ /* If a relay candidate was found, notify that the TURN server works! */
if (event.candidate.type === "relay"){ if (event.candidate.type === "relay"){
console.log("The TURN server is reachable !"); console.log("media-agent - The TURN server is reachable !");
} }
console.log(`media-agent - onicecandidate - `, event.candidate); console.log(`media-agent - onicecandidate - `, event.candidate);
@ -147,7 +143,7 @@ const MediaAgent = () => {
}); });
}; };
connection.ontrack = e => refOnTrack.current(e);; connection.ontrack = e => refOnTrack.current(e);
/* Add our local stream */ /* Add our local stream */
connection.addStream(stream); connection.addStream(stream);
@ -267,7 +263,7 @@ const MediaAgent = () => {
const refWsMessage = useRef(onWsMessage); const refWsMessage = useRef(onWsMessage);
const onWsClose = (event) => { const onWsClose = (event) => {
console.log(`${name} Disconnected from signaling server`); console.log(`media-agent - ${name} Disconnected from signaling server`);
/* Tear down all of our peer connections and remove all the /* Tear down all of our peer connections and remove all the
* media divs when we disconnect */ * media divs when we disconnect */
for (let peer_id in peers) { for (let peer_id in peers) {
@ -280,7 +276,7 @@ const MediaAgent = () => {
for (let id in peers) { for (let id in peers) {
delete peers[id]; delete peers[id];
} }
if (debug) console.log(`media-agent - close - local or remote?`, peers); if (debug) console.log(`media-agent - close`, peers);
setPeers(Object.assign({}, peers)); setPeers(Object.assign({}, peers));
} }
const refWsClose = useRef(onWsClose); const refWsClose = useRef(onWsClose);
@ -314,9 +310,9 @@ const MediaAgent = () => {
if (!(name in peers)) { if (!(name in peers)) {
update = true; update = true;
peers[name] = { peers[name] = {
name: name,
local: true, local: true,
muted: true, initialized: false,
videoOn: false,
attributes: { attributes: {
local: true, local: true,
srcObject: stream srcObject: stream
@ -331,8 +327,9 @@ const MediaAgent = () => {
update = true; update = true;
} }
} }
if (update) { if (update) {
if (debug) console.log(`media-agent - Adding local`, peers); if (debug) console.log(`media-agent - Setting global peers`, peers);
setPeers(Object.assign({}, peers)); setPeers(Object.assign({}, peers));
} }
}, [peers, name, setPeers, stream]); }, [peers, name, setPeers, stream]);
@ -345,7 +342,7 @@ const MediaAgent = () => {
const setup_local_media = () => { const setup_local_media = () => {
/* Ask user for permission to use the computers microphone and/or camera, /* Ask user for permission to use the computers microphone and/or camera,
* attach it to an <audio> or <video> tag if they give us access. */ * attach it to an <audio> or <video> tag if they give us access. */
console.log("Requesting access to local audio / video inputs"); console.log("media-agent - Requesting access to local audio / video inputs");
navigator.getUserMedia = (navigator.getUserMedia || navigator.getUserMedia = (navigator.getUserMedia ||
navigator.webkitGetUserMedia || navigator.webkitGetUserMedia ||
@ -354,7 +351,7 @@ const MediaAgent = () => {
return navigator.mediaDevices.getUserMedia({audio: true, video: true}) return navigator.mediaDevices.getUserMedia({audio: true, video: true})
.then((media) => { /* user accepted access to a/v */ .then((media) => { /* user accepted access to a/v */
console.log("Access granted to audio/video"); console.log("media-agent - Access granted to audio/video");
media.getVideoTracks().forEach((track) => { media.getVideoTracks().forEach((track) => {
track.applyConstraints({ track.applyConstraints({
"video": { "video": {
@ -378,80 +375,88 @@ const MediaAgent = () => {
sendMessage({ type: 'join' }); sendMessage({ type: 'join' });
} }
if (debug) console.log(`media-agent - WebSocket open request. Attempting to create local media.`) let abort = false;
if (!stream) { if (!stream) {
if (debug) console.log(`media-agent - WebSocket open request. Attempting to create local media.`);
setup_local_media().then((media) => { setup_local_media().then((media) => {
/* once the user has given us access to their /* once the user has given us access to their
* microphone/camcorder, join the channel and start peering up */ * microphone/camcorder, join the channel and start peering up */
setStream(media); if (abort) {
join(); console.log(`media-agent - aborting setting local media`);
} else {
setStream(media);
join();
}
}).catch((error) => { /* user denied access to a/v */ }).catch((error) => { /* user denied access to a/v */
console.error(error); console.error(error);
console.log("Access denied for audio/video"); console.log("media-agent - Access denied for audio/video");
}); });
} }
}, [ws, setStream, stream, peers, name, sendMessage]);
return <></>; return () => {
abort = true;
console.log(`media-agent - abort media setup!`);
};
}, [ws, setStream, stream, name, sendMessage]);
return <></>;
} }
const MediaControl = ({isSelf, peer}) => { const MediaControl = ({isSelf, peer}) => {
const { peers } = useContext(GlobalContext);
const [control, setControl] = useState(undefined);
const [media, setMedia] = useState(undefined); const [media, setMedia] = useState(undefined);
const [muted, setMuted] = useState(undefined); const [muted, setMuted] = useState(undefined);
const [videoOn, setVideoOn] = useState(undefined); const [videoOn, setVideoOn] = useState(undefined);
useEffect(() => { useEffect(() => {
setControl(peers[peer]); if (!peer) {
}, [peer, peers, setControl]); setMedia(undefined);
return;
}
if (peer.local) {
setMuted(true);
setVideoOn(false);
} else {
setMuted(false);
setVideoOn(true);
}
setMedia(peer);
}, [peer, setMedia, setMuted, setVideoOn]);
const toggleMute = (event) => { const toggleMute = (event) => {
if (debug) console.log(`MediaControl - toggleMute`, !muted); if (debug) console.log(`MediaControl - toggleMute - ${peer.name}`, !muted);
setMuted(!muted); setMuted(!muted);
event.stopPropagation(); event.stopPropagation();
} }
const toggleVideo = (event) => { const toggleVideo = (event) => {
if (debug) console.log(`MediaControl - toggleVideo`, !videoOn); if (debug) console.log(`MediaControl - toggleVideo - ${peer.name}`, !videoOn);
setVideoOn(!videoOn); setVideoOn(!videoOn);
event.stopPropagation(); event.stopPropagation();
} }
useEffect(() => { useEffect(() => {
if (!control) { if (!media) {
setMedia(undefined);
return; return;
} }
setMuted(control.muted); if (media.attributes.srcObject) {
setVideoOn(control.videoOn); media.attributes.srcObject.getAudioTracks().forEach((track) => {
setMedia(control);
}, [control, setMedia]);
useEffect(() => {
if (!control) {
return;
}
if (control.attributes.srcObject) {
control.attributes.srcObject.getAudioTracks().forEach((track) => {
track.enabled = !muted; track.enabled = !muted;
}); });
} }
}, [control, muted]); }, [media, muted]);
useEffect(() => { useEffect(() => {
if (!control) { if (!media) {
return; return;
} }
if (control.attributes.srcObject) { if (media.attributes.srcObject) {
control.attributes.srcObject.getVideoTracks().forEach((track) => { media.attributes.srcObject.getVideoTracks().forEach((track) => {
track.enabled = videoOn; track.enabled = videoOn;
}); });
} }
}, [control, videoOn]); }, [media, videoOn]);
if (!control) { if (!media) {
return <div className="MediaControl"> return <div className="MediaControl">
<div> <div>
{ isSelf && <MicOff color={'disabled'}/> } { isSelf && <MicOff color={'disabled'}/> }

View File

@ -4,7 +4,8 @@ import List from '@material-ui/core/List';
import "./PlayerList.css"; import "./PlayerList.css";
import { PlayerColor } from './PlayerColor.js'; import { PlayerColor } from './PlayerColor.js';
import { MediaControl } from "./MediaControl.js"; import { MediaAgent, MediaControl } from "./MediaControl.js";
import { GlobalContext } from "./GlobalContext.js"; import { GlobalContext } from "./GlobalContext.js";
const PlayerList = () => { const PlayerList = () => {
@ -13,6 +14,7 @@ const PlayerList = () => {
const [unselected, setUneslected] = useState([]); const [unselected, setUneslected] = useState([]);
const [state, setState] = useState('lobby'); const [state, setState] = useState('lobby');
const [color, setColor] = useState(undefined); const [color, setColor] = useState(undefined);
const [peers, setPeers] = useState({});
const onWsMessage = (event) => { const onWsMessage = (event) => {
const data = JSON.parse(event.data); const data = JSON.parse(event.data);
@ -113,7 +115,7 @@ const PlayerList = () => {
<div className="Name">{name ? name : 'Available' }</div> <div className="Name">{name ? name : 'Available' }</div>
{ name && !item.live && <div className="NoNetwork"></div> } { name && !item.live && <div className="NoNetwork"></div> }
</div> </div>
{ name && item.live && <MediaControl peer={name} isSelf={item.color === color}/> } { name && item.live && <MediaControl peer={peers[name]} isSelf={item.color === color}/> }
{ !name && <div></div> } { !name && <div></div> }
</div> </div>
); );
@ -122,12 +124,13 @@ const PlayerList = () => {
const waiting = unselected.map((player) => { const waiting = unselected.map((player) => {
return <div className={player === name ? 'Self' : ''} key={player}> return <div className={player === name ? 'Self' : ''} key={player}>
<div>{ player }</div> <div>{ player }</div>
<MediaControl peer={player} isSelf={name === player}/> <MediaControl peer={peers[name]} isSelf={name === player}/>
</div> </div>
}); });
return ( return (
<Paper className="PlayerList"> <Paper className="PlayerList">
<MediaAgent setPeers={setPeers}/>
<List className="PlayerSelector"> <List className="PlayerSelector">
{ playerElements } { playerElements }
</List> </List>