getting main flow of everything but don't know if it works
This commit is contained in:
@@ -1,5 +1,9 @@
|
||||
import {
|
||||
ConnectToLineRequest,
|
||||
RtcAnswerRequest,
|
||||
RtcCallRequest,
|
||||
RtcNewUserResponse,
|
||||
RtcReceiveAnswerResponse,
|
||||
ServerRequestChannels,
|
||||
ServerResponseChannels,
|
||||
SomeoneConnectedResponse,
|
||||
@@ -32,6 +36,9 @@ const config = loadConfig();
|
||||
const socketIdsToUserIds: {
|
||||
[socketId: string]: string;
|
||||
} = {};
|
||||
const userIdsToSocketIds: {
|
||||
[userId: string]: string;
|
||||
} = {};
|
||||
|
||||
export default function InitializeWs(io: any) {
|
||||
console.log("initializing web sockets");
|
||||
@@ -62,6 +69,7 @@ export default function InitializeWs(io: any) {
|
||||
const userInfo: JwtClaims = socket.userInfo;
|
||||
|
||||
socketIdsToUserIds[socket.id] = userInfo.userId.toString();
|
||||
userIdsToSocketIds[userInfo.userId.toString()] = socket.id;
|
||||
|
||||
console.log(
|
||||
`a user connected | user Id: ${userInfo.userId} and name: ${userInfo.name}`
|
||||
@@ -231,9 +239,35 @@ export default function InitializeWs(io: any) {
|
||||
// );
|
||||
// });
|
||||
|
||||
// tell the proper other user to create a local peer object for the one on one mesh connection
|
||||
socket.on(
|
||||
ServerRequestChannels.RTC_CALL_REQUEST,
|
||||
(req: RtcCallRequest) => {
|
||||
const userSocketId = userIdsToSocketIds[req.userIdToCall];
|
||||
|
||||
io.to(userSocketId).emit(
|
||||
`${ServerResponseChannels.RTC_NEW_USER_JOINED_RESPONSE_PREFIX}:${req.lineId}`,
|
||||
new RtcNewUserResponse(userInfo.userId, req.simplePeerSignal)
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
socket.on(
|
||||
ServerRequestChannels.RTC_ANSWER_REQUEST,
|
||||
(req: RtcAnswerRequest) => {
|
||||
const userSocketId = userIdsToSocketIds[req.userIdToCall];
|
||||
|
||||
io.to(userSocketId).emit(
|
||||
`${ServerResponseChannels.RTC_RECEIVING_ANSWER_RESPONSE_PREFIX}:${req.lineId}`,
|
||||
new RtcReceiveAnswerResponse(userInfo.userId, req.simplePeerSignal)
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
// ==== DISCONNECT ====
|
||||
socket.on("disconnect", () => {
|
||||
delete socketIdsToUserIds[socket.id];
|
||||
delete userIdsToSocketIds[userInfo.userId];
|
||||
|
||||
// get all of the rooms of this socket
|
||||
// notify everyone of this disconnection
|
||||
@@ -242,6 +276,10 @@ export default function InitializeWs(io: any) {
|
||||
console.log(
|
||||
`list of sockets mappings in memory: ${socketIdsToUserIds}`
|
||||
);
|
||||
|
||||
console.log(socket.rooms);
|
||||
|
||||
// ! NOTIFY ALL CONNECTED LINES SO THAT THEY CAN REMOVE FROM THEIR SESSION CONNECTED USERS ARRAY AND TUNED IN ARRAY
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -41,6 +41,9 @@ export enum ServerRequestChannels {
|
||||
|
||||
BROADCAST_TO_LINE = "BROADCAST_TO_LINE",
|
||||
STOP_BROADCAST_TO_LINE = "STOP_BROADCAST_TO_LINE",
|
||||
|
||||
RTC_CALL_REQUEST = "RTC_CALL_PREFIX",
|
||||
RTC_ANSWER_REQUEST = "RTC_ANSWER_REQUEST_PREFIX",
|
||||
}
|
||||
|
||||
export enum ServerResponseChannels {
|
||||
@@ -52,6 +55,10 @@ export enum ServerResponseChannels {
|
||||
|
||||
SOMEONE_STARTED_BROADCASTING = "SOMEONE_STARTED_BROADCASTING", //show their stream tracks
|
||||
SOMEONE_STOPPED_BROADCASTING = "SOMEONE_STOPPED_BROADCASTING", // stop showing their stream tracks
|
||||
|
||||
// sending to the correct room of tunedin folks AND also making sure it's the right event handler in the right handler for this component
|
||||
RTC_NEW_USER_JOINED_RESPONSE_PREFIX = "RTC_NEW_USER_JOINED_RESPONSE_PREFIX",
|
||||
RTC_RECEIVING_ANSWER_RESPONSE_PREFIX = "RTC_RECEIVING_ANSWER_RESPONSE_PREFIX",
|
||||
}
|
||||
|
||||
export default SocketChannels;
|
||||
@@ -107,3 +114,27 @@ export class UserStoppedBroadcastingResponse {
|
||||
export class SocketEmitter<T> {
|
||||
constructor(public channel: SocketChannels, data: T) {}
|
||||
}
|
||||
|
||||
export class RtcCallRequest {
|
||||
constructor(
|
||||
public lineId: string,
|
||||
public userIdToCall: string,
|
||||
public simplePeerSignal: any
|
||||
) {}
|
||||
}
|
||||
|
||||
export class RtcNewUserResponse {
|
||||
constructor(public newUserId: string, public simplePeerSignal: any) {}
|
||||
}
|
||||
|
||||
export class RtcAnswerRequest {
|
||||
constructor(
|
||||
public lineId: string,
|
||||
public userIdToCall: string,
|
||||
public simplePeerSignal: any
|
||||
) {}
|
||||
}
|
||||
|
||||
export class RtcReceiveAnswerResponse {
|
||||
constructor(public answererUserId: string, public simplePeerSignal: any) {}
|
||||
}
|
||||
|
||||
@@ -55,8 +55,8 @@
|
||||
[
|
||||
"@electron-forge/plugin-webpack",
|
||||
{
|
||||
"port": "4000",
|
||||
"loggerPort": "9001",
|
||||
"port": "4002",
|
||||
"loggerPort": "9005",
|
||||
"mainConfig": "./webpack.main.config.js",
|
||||
"devContentSecurityPolicy": "connect-src 'self' http://localhost:5000 ws://localhost:5000 'unsafe-eval'",
|
||||
"renderer": {
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
import { FiActivity, FiSun } from "react-icons/fi";
|
||||
import {
|
||||
RtcAnswerRequest,
|
||||
RtcCallRequest,
|
||||
RtcNewUserResponse,
|
||||
RtcReceiveAnswerResponse,
|
||||
ServerResponseChannels,
|
||||
SomeoneUntunedFromLineResponse,
|
||||
} from "@nirvana/core/sockets/channels";
|
||||
@@ -11,6 +15,7 @@ import LineIcon from "../lineIcon";
|
||||
import { LineMemberState } from "@nirvana/core/models/line.model";
|
||||
import MasterLineData from "@nirvana/core/models/masterLineData.model";
|
||||
import Peer from "simple-peer";
|
||||
import { ServerRequestChannels } from "../../../../../core/sockets/channels";
|
||||
import moment from "moment";
|
||||
import toast from "react-hot-toast";
|
||||
import { useGetUserDetails } from "../../../controller/index";
|
||||
@@ -157,6 +162,7 @@ export default function LineRow({
|
||||
{/* mounts and unmounts based on if in the room or now */}
|
||||
{isUserTunedIn && (
|
||||
<StreamRoom
|
||||
lineId={masterLineData.lineDetails._id.toString()}
|
||||
currentBroadcasters={masterLineData.currentBroadcastersUserIds}
|
||||
tunedInUsers={masterLineData.tunedInMemberIds}
|
||||
/>
|
||||
@@ -165,10 +171,14 @@ export default function LineRow({
|
||||
);
|
||||
}
|
||||
|
||||
type PeerMap = { [userId: string]: Peer };
|
||||
|
||||
function StreamRoom({
|
||||
lineId,
|
||||
tunedInUsers,
|
||||
currentBroadcasters,
|
||||
}: {
|
||||
lineId: string;
|
||||
tunedInUsers?: string[];
|
||||
currentBroadcasters?: string[];
|
||||
}) {
|
||||
@@ -176,65 +186,152 @@ function StreamRoom({
|
||||
// local stream specifically for this stream room
|
||||
const [localStream, setLocalStream] = useState<MediaStream>();
|
||||
const userStreamTagRef = useRef<HTMLVideoElement>(null);
|
||||
const { data: userDetails } = useGetUserDetails();
|
||||
|
||||
// local peer map of userIds to peers
|
||||
const [userPeers, setUserPeers] = useState<{ [userId: string]: Peer }>({});
|
||||
const [userPeers, setUserPeers] = useState<PeerMap>({});
|
||||
|
||||
// ws listen to events of user disconnecting and such or rely on tunedin members prop
|
||||
const { $ws } = useLineDataProvider();
|
||||
|
||||
useEffect(() => {
|
||||
navigator.mediaDevices
|
||||
.getUserMedia({
|
||||
video: false,
|
||||
audio: {
|
||||
echoCancellation: true,
|
||||
autoGainControl: true,
|
||||
},
|
||||
})
|
||||
.then((userStream) => {
|
||||
setLocalStream(userStream);
|
||||
if (userDetails) {
|
||||
navigator.mediaDevices
|
||||
.getUserMedia({
|
||||
video: false,
|
||||
audio: {
|
||||
echoCancellation: true,
|
||||
autoGainControl: true,
|
||||
},
|
||||
})
|
||||
.then((userStream) => {
|
||||
setLocalStream(userStream);
|
||||
|
||||
// if (userStreamTagRef?.current)
|
||||
// userStreamTagRef.current.srcObject = userStream;
|
||||
// if (userStreamTagRef?.current)
|
||||
// userStreamTagRef.current.srcObject = userStream;
|
||||
|
||||
// alternative to dom element
|
||||
// const audio = new Audio();
|
||||
// audio.autoplay = true;
|
||||
// audio.srcObject = userStream;
|
||||
// alternative to dom element
|
||||
// const audio = new Audio();
|
||||
// audio.autoplay = true;
|
||||
// audio.srcObject = userStream;
|
||||
|
||||
// test distortion to go away on disabling audio
|
||||
setTimeout(() => {
|
||||
console.log("stopping audio stream ");
|
||||
// test distortion to go away on disabling audio
|
||||
setTimeout(() => {
|
||||
console.log("stopping audio stream ");
|
||||
|
||||
userStream.getTracks().forEach((track) => {
|
||||
track.enabled = !track.enabled;
|
||||
userStream.getTracks().forEach((track) => {
|
||||
track.enabled = !track.enabled;
|
||||
|
||||
track.stop();
|
||||
track.stop();
|
||||
});
|
||||
}, 2000);
|
||||
|
||||
// take the initial list of tunedInUsers without my own id
|
||||
const everyOtherTunedUserId = tunedInUsers.filter(
|
||||
(tunedUserId) => tunedUserId !== userDetails?.user._id.toString()
|
||||
);
|
||||
|
||||
const localPeerConnections: PeerMap = {};
|
||||
|
||||
everyOtherTunedUserId.forEach((otherTunedInUserId) => {
|
||||
// create local peer objects for them
|
||||
const localPeerInitiator = new Peer({
|
||||
initiator: true,
|
||||
stream: userStream,
|
||||
trickle: false, // prevents the multiple tries on different ice servers and signal from getting called a bunch of times
|
||||
});
|
||||
|
||||
// set it for our map that we will iterate through to display streams in other child view
|
||||
localPeerConnections[otherTunedInUserId] = localPeerInitiator;
|
||||
|
||||
// notify each one with specific signal
|
||||
localPeerInitiator.on("signal", (signal) => {
|
||||
$ws.emit(
|
||||
ServerRequestChannels.RTC_CALL_REQUEST,
|
||||
new RtcCallRequest(lineId, otherTunedInUserId, signal)
|
||||
);
|
||||
});
|
||||
});
|
||||
}, 2000);
|
||||
|
||||
// take the initial list of tunedInUsers
|
||||
// create local peer objects for them
|
||||
// notify all of them individually
|
||||
//
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error(error);
|
||||
setUserPeers(localPeerConnections);
|
||||
|
||||
toast.error(
|
||||
"Make sure that you have permissions enabled and microphone connected"
|
||||
);
|
||||
});
|
||||
// answer calls
|
||||
$ws.on(
|
||||
`${ServerResponseChannels.RTC_NEW_USER_JOINED_RESPONSE_PREFIX}:${lineId}`,
|
||||
(res: RtcNewUserResponse) => {
|
||||
// create a local peer connection for this new user
|
||||
|
||||
$ws.on(
|
||||
ServerResponseChannels.SOMEONE_UNTUNED_FROM_LINE,
|
||||
(res: SomeoneUntunedFromLineResponse) => {
|
||||
// take the relevant userId
|
||||
res.userId;
|
||||
}
|
||||
);
|
||||
}, []);
|
||||
console.log(
|
||||
"ooo newbie joined room, I guess I will accept it and send him my signal"
|
||||
);
|
||||
|
||||
var peerForMeAndNewbie = new Peer({
|
||||
initiator: false,
|
||||
trickle: false, // prevents the multiple tries on different ice servers and signal from getting called a bunch of times
|
||||
stream: localStream, // add in my own stream that I got before
|
||||
});
|
||||
|
||||
peerForMeAndNewbie.on("signal", (signal) => {
|
||||
console.log(
|
||||
"as the answerer, I am going to send back my signal so that the newbie can update his local peer for me"
|
||||
);
|
||||
$ws.emit(
|
||||
ServerRequestChannels.RTC_ANSWER_REQUEST,
|
||||
new RtcAnswerRequest(lineId, res.newUserId, signal)
|
||||
);
|
||||
});
|
||||
|
||||
peerForMeAndNewbie.signal(res.simplePeerSignal);
|
||||
|
||||
setUserPeers((prevUsersPeers) => {
|
||||
const newUserPeers = { ...prevUsersPeers };
|
||||
|
||||
newUserPeers[res.newUserId] = peerForMeAndNewbie;
|
||||
|
||||
return newUserPeers;
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
// take care of answers recevied
|
||||
$ws.on(
|
||||
`${ServerResponseChannels.RTC_RECEIVING_ANSWER_RESPONSE_PREFIX}:${lineId}`,
|
||||
(res: RtcReceiveAnswerResponse) => {
|
||||
console.log("oooo some master received my call and accepted it");
|
||||
|
||||
// find the peer we created earlier for this master
|
||||
// ?is this okay? using the setter to get the current state?
|
||||
setUserPeers((previousUserPeersMap) => {
|
||||
const peerForAnswerer =
|
||||
previousUserPeersMap[res.answererUserId];
|
||||
|
||||
if (peerForAnswerer) {
|
||||
peerForAnswerer.signal(res.simplePeerSignal);
|
||||
} else {
|
||||
console.error(
|
||||
"could not find the peer we created before for this master"
|
||||
);
|
||||
}
|
||||
|
||||
return previousUserPeersMap;
|
||||
});
|
||||
}
|
||||
);
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error(error);
|
||||
|
||||
toast.error(
|
||||
"Make sure that you have permissions enabled and microphone connected"
|
||||
);
|
||||
});
|
||||
}
|
||||
}, [userDetails, setUserPeers]);
|
||||
|
||||
// calculate diff to clean our userPeerMap to unmount and detroy certain peer connections
|
||||
useEffect(() => {}, [tunedInUsers]);
|
||||
|
||||
// todo, someone tell the main object that I am finally connected after everything...different than tuned in
|
||||
|
||||
useEffect(() => {
|
||||
console.log("change in tuned in users in the streaming room!!!");
|
||||
@@ -245,13 +342,14 @@ function StreamRoom({
|
||||
<>
|
||||
<audio autoPlay ref={userStreamTagRef} muted />
|
||||
this is the video of people
|
||||
{Object.entries(userPeers).map(([userId, peer]) => (
|
||||
<PeerStreamRenderer
|
||||
key={userId}
|
||||
isBroadcasting={currentBroadcasters?.includes(userId)}
|
||||
peer={peer}
|
||||
/>
|
||||
))}
|
||||
{userPeers &&
|
||||
Object.entries(userPeers).map(([userId, peer]) => (
|
||||
<PeerStreamRenderer
|
||||
key={userId}
|
||||
isBroadcasting={currentBroadcasters?.includes(userId)}
|
||||
peer={peer}
|
||||
/>
|
||||
))}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user