import {ExtRooms, RefreshUserPositionFunction} from "../Model/Websocket/ExtRoom";
import {ExtRoomsInterface} from "../Model/Websocket/ExtRoomsInterface";
import {World} from "../Model/World";
-import { uuid } from 'uuidv4';
+import {Group} from "_Model/Group";
enum SockerIoEvent {
CONNECTION = "connection",
this.shareUsersPosition();
//don't send only function because the context will be not this
- this.World = new World((user1 : string, user2 : string) => {
- this.connectedUser(user1, user2);
- }, (user1 : string, user2 : string) => {
- this.disConnectedUser(user1, user2);
+ this.World = new World((user1 : string, user2 : string, group: Group) => {
+ this.connectedUser(user1, user2, group);
+ }, (user1 : string, user2 : string, group: Group) => {
+ this.disConnectedUser(user1, user2, group);
});
}
}
//connected user
- connectedUser(user1 : string, user2 : string){
+ connectedUser(user1 : string, user2 : string, group : Group) {
+ if(!group){
+ return;
+ }
/* TODO manager room and group user to enter and leave */
- let roomId = uuid();
- let clients : Array<any> = Object.values(this.Io.sockets.sockets);
- let User1 = clients.find((user : ExSocketInterface) => user.userId === user1);
- let User2 = clients.find((user : ExSocketInterface) => user.userId === user2);
+ let clients: Array<any> = Object.values(this.Io.sockets.sockets);
+ let User1 = clients.find((user: ExSocketInterface) => user.userId === user1);
+ let User2 = clients.find((user: ExSocketInterface) => user.userId === user2);
- if(User1) {
- this.joinWebRtcRoom(User1, roomId);
+ if (User1) {
+ this.joinWebRtcRoom(User1, group.getId());
}
- if(User2) {
- this.joinWebRtcRoom(User2, roomId);
+ if (User2) {
+ this.joinWebRtcRoom(User2, group.getId());
}
}
//connected user
- disConnectedUser(user1 : string, user2 : string){
+ disConnectedUser(user1 : string, user2 : string, group : Group){
console.log("disConnectedUser => user1", user1);
console.log("disConnectedUser => user2", user2);
+ console.log("group", group);
}
}
import {MessageUserPosition} from "./Websocket/MessageUserPosition";
import { World } from "./World";
import { UserInterface } from "./UserInterface";
+import {uuid} from "uuidv4";
export class Group {
static readonly MAX_PER_GROUP = 4;
+ private id: string;
private users: UserInterface[];
- private connectCallback: (user1: string, user2: string) => void;
- private disconnectCallback: (user1: string, user2: string) => void;
+ private connectCallback: (user1: string, user2: string, group: Group) => void;
+ private disconnectCallback: (user1: string, user2: string, group: Group) => void;
- constructor(users: UserInterface[], connectCallback: (user1: string, user2: string) => void, disconnectCallback: (user1: string, user2: string) => void) {
+ constructor(users: UserInterface[],
+ connectCallback: (user1: string, user2: string, group: Group) => void,
+ disconnectCallback: (user1: string, user2: string, group: Group) => void
+ ) {
this.users = [];
this.connectCallback = connectCallback;
this.disconnectCallback = disconnectCallback;
+ this.id = uuid();
users.forEach((user: UserInterface) => {
this.join(user);
return this.users;
}
+ getId() : string{
+ return this.id;
+ }
+
isFull(): boolean {
return this.users.length >= Group.MAX_PER_GROUP;
}
join(user: UserInterface): void
{
// Broadcast on the right event
- this.users.forEach((groupUser: UserInterface) => {
- this.connectCallback(user.id, groupUser.id);
- });
+ for(let i = 0; i < this.users.length; i++){
+ let groupUser : UserInterface = this.users[i];
+ this.connectCallback(user.id, groupUser.id, this);
+ }
this.users.push(user);
user.group = this;
}
private users: Map<string, UserInterface>;
private groups: Group[];
- private connectCallback: (user1: string, user2: string) => void;
- private disconnectCallback: (user1: string, user2: string) => void;
+ private connectCallback: (user1: string, user2: string, group: Group) => void;
+ private disconnectCallback: (user1: string, user2: string, group: Group) => void;
- constructor(connectCallback: (user1: string, user2: string) => void, disconnectCallback: (user1: string, user2: string) => void)
+ constructor(connectCallback: (user1: string, user2: string, group: Group) => void, disconnectCallback: (user1: string, user2: string, group: Group) => void)
{
this.users = new Map<string, UserInterface>();
this.groups = [];
// If the user is not part of a group:
// should he join a group?
let closestUser: UserInterface|null = this.searchClosestAvailableUser(user);
-
if (closestUser !== null) {
// Is the closest user part of a group?
if (typeof closestUser.group === 'undefined') {
closestUser.group.join(user);
}
}
-
}
- // TODO : vérifier qu'ils ne sont pas déja dans un groupe plein
+ // TODO : vérifier qu'ils ne sont pas déja dans un groupe plein
}
/**
<script src="bundle.js"></script>
<div id="webRtc" class="webrtc">
<div id="activeCam" class="activeCam">
- </div>
- <div id="myCam" class="myCam">
<video id="myCamVideo" autoplay></video>
</div>
<div class="btn-cam-action active">
.webrtc{
display: none;
+ position: absolute;
+ right: 0px;
+ height: 100%;
+ width: 300px;
}
.webrtc.active{
display: block;
}
-.webrtc, .activeCam{
- position: absolute;
- left: 0;
- top: 0;
- width: 100%;
- height: 100%;
- background: black;
-}
+.webrtc, .activeCam{}
.activeCam video{
position: absolute;
- width: 100%;
- height: 100%;
+ width: 300px;
+ height: 20%;
+ top: 10px;
+ right: 10px;
+ margin: 5px;
+ background-color: white;
}
-
-/*CSS size for 2 - 3 elements*/
-video:nth-child(1):nth-last-child(3),
-video:nth-child(2):nth-last-child(2),
-video:nth-child(3):nth-last-child(1),
-video:nth-child(1):nth-last-child(2),
-video:nth-child(2):nth-last-child(1){
- width: 50%;
-}
-video:nth-child(1):nth-last-child(3),
-video:nth-child(2):nth-last-child(2),
-video:nth-child(3):nth-last-child(1){
- height: 50%;
+.activeCam video#myCamVideo{
+ width: 200px;
+ height: 100px;
}
-/*CSS position for 2 elements*/
-video:nth-child(1):nth-last-child(2){
- left: 0;
-}
-video:nth-child(2):nth-last-child(1){
- left: 50%;
+/*CSS size for 2 - 3 elements*/
+.activeCam video:nth-child(1){
+ /*this is for camera of user*/
+ top: 75%;
}
-
-/*CSS position for 3 elements*/
-video:nth-child(1):nth-last-child(3){
- top: 0;
- left: 0;
+.activeCam video:nth-child(2){
+ top: 0%;
}
-video:nth-child(2):nth-last-child(2){
- top: 0;
- left: 50%;
+.activeCam video:nth-child(3){
+ top: 25%;
}
-video:nth-child(3):nth-last-child(1) {
+.activeCam video:nth-child(4) {
top: 50%;
- left: 25%;
}
-.myCam{
- height: 200px;
- width: 300px;
- position: absolute;
- right: 10px;
- background: black;
- border: none;
- bottom: 20px;
- max-height: 17%;
- max-width: 17%;
- opacity: 1;
- display: block;
- transition: opacity 1s;
-}
-.myCam video{
- width: 100%;
- height: 100%;
-}
+/*btn animation*/
.btn-cam-action div{
cursor: pointer;
position: absolute;
width: 64px;
height: 64px;
background: #666;
- left: 6vw;
box-shadow: 2px 2px 24px #444;
border-radius: 48px;
- transform: translateX(calc(-6vw - 96px));
+ transform: translateY(12vw);
transition-timing-function: ease-in-out;
+ bottom: 20px;
}
.webrtc:hover .btn-cam-action.active div{
- transform: translateX(0);
+ transform: translateY(0);
}
.btn-cam-action div:hover{
background: #407cf7;
transition: 280ms;
}
.btn-micro{
- bottom: 277px;
transition: all .3s;
+ left: 168px;
}
.btn-video{
- bottom: 177px;
transition: all .2s;
+ left: 84px;
}
.btn-call{
- bottom: 77px;
transition: all .1s;
+ left: 0px;
}
.btn-cam-action div img{
height: 32px;
left: calc(48px - 35px);
position: relative;
}
+
+/*Phone Animation*/
.phone-open{
position: absolute;
border-radius: 50%;
animation: none;
cursor: pointer;
}
-
@keyframes phone-move {
0% {
left: calc(50% - 70px);
userId: string;
PlayerValue: string;
userInputManager: UserInputManager;
+ previousMove: string;
constructor(
userId: string,
direction = PlayerAnimationNames.None;
this.stop();
}
- this.sharePosition(direction);
+ if(this.previousMove !== PlayerAnimationNames.None || direction !== PlayerAnimationNames.None){
+ this.sharePosition(direction);
+ }
+ this.previousMove = direction;
}
private sharePosition(direction: string) {
export interface SimplePeerInterface {
}
-
+enum PeerConnexionStatus{
+ DISABLED = 1,
+ ACTIVATED = 2
+}
export class SimplePeer {
- Connexion: ConnexionInterface;
- MediaManager: MediaManager;
- WebRtcRoomId: string;
- Users: Array<any>;
+ private Connexion: ConnexionInterface;
+ private MediaManager: MediaManager;
+ private WebRtcRoomId: string;
+ private Users: Array<any>;
+
+ private PeerConnexionArray: Array<any> = new Array<any>();
- PeerConnexionArray: Array<any> = new Array<any>();
+ private PeerConnexionStatus : number = PeerConnexionStatus.DISABLED;
constructor(Connexion: ConnexionInterface, WebRtcRoomId: string = "test-webrtc") {
this.Connexion = Connexion;
});
//when button to call is clicked, start video
- this.MediaManager.getElementActivePhone().addEventListener("click", () => {
+ /*this.MediaManager.getElementActivePhone().addEventListener("click", () => {
this.startWebRtc();
this.disablePhone();
+ });*/
+
+ return this.MediaManager.getCamera().then((stream: MediaStream) => {
+ this.MediaManager.activeVisio();
+ this.MediaManager.localStream = stream;
});
}
/**
* server has two person connected, start the meet
*/
- startWebRtc() {
- this.MediaManager.activeVisio();
- return this.MediaManager.getCamera().then((stream: MediaStream) => {
- this.MediaManager.localStream = stream;
+ private startWebRtc() {
+ //create pear connexion
+ this.createPeerConnexion();
- //create pear connexion
- this.createPeerConnexion();
+ //receive signal by gemer
+ this.Connexion.receiveWebrtcSignal((message: string) => {
+ this.receiveWebrtcSignal(message);
+ });
- //receive signal by gemer
- this.Connexion.receiveWebrtcSignal((message: string) => {
- this.receiveWebrtcSignal(message);
- });
- }).catch((err) => {
- console.error(err);
+ // add media or new media for all peer connexion
+ this.Users.forEach((user: any) => {
+ this.addMedia(user.userId);
});
+
+ //change status to manage other user
+ this.PeerConnexionStatus = PeerConnexionStatus.ACTIVATED;
}
/**
*
* @param message
*/
- receiveWebrtcStart(message: string) {
+ private receiveWebrtcStart(message: string) {
let data = JSON.parse(message);
this.WebRtcRoomId = data.roomId;
this.Users = data.clients;
- //active button for player
- this.activePhone();
+ console.log("receiveWebrtcStart", this.Users);
+
+ //start connexion
+ this.startWebRtc();
}
- createPeerConnexion() {
+ private createPeerConnexion() {
this.Users.forEach((user: any) => {
- if(this.PeerConnexionArray[user.userId]){
+ if (this.PeerConnexionArray[user.userId]) {
return;
}
this.MediaManager.addActiveVideo(user.userId);
- this.PeerConnexionArray[user.userId] = new Peer({initiator: user.initiator});
+ console.info("createPeerConnexion => create peerConexion", user);
+ this.PeerConnexionArray[user.userId] = new Peer({
+ initiator: user.initiator,
+ config: { iceServers: [{ urls: 'stun:stun.l.google.com:19302' }, { urls: 'stun:global.stun.twilio.com:3478?transport=udp' }] }
+ });
+
+ //add lof info PeerConnexionArray
+ this.PeerConnexionArray[user.userId]._debug = console.info;
this.PeerConnexionArray[user.userId].on('signal', (data: any) => {
+ console.info("createPeerConnexion => sendWebrtcSignal : "+user.userId, data);
this.sendWebrtcSignal(data, user.userId);
});
});
this.PeerConnexionArray[user.userId].on('close', () => {
+ console.info("createPeerConnexion => close", user.userId);
this.closeConnexion(user.userId);
});
this.addMedia(user.userId);
});
-
}
- closeConnexion(userId : string){
+ private closeConnexion(userId : string){
// @ts-ignore
this.PeerConnexionArray[userId] = null;
this.MediaManager.removeActiveVideo(userId)
* @param userId
* @param data
*/
- sendWebrtcSignal(data: any, userId : string) {
+ private sendWebrtcSignal(data: any, userId : string) {
this.Connexion.sendWebrtcSignal(data, this.WebRtcRoomId, null, userId);
}
*
* @param message
*/
- receiveWebrtcSignal(message: string) {
+ private receiveWebrtcSignal(message: string) {
let data = JSON.parse(message);
+ console.log("receiveWebrtcSignal", data);
+ console.log("this.PeerConnexionArray[data.userId]", this.PeerConnexionArray[data.userId]);
if(!this.PeerConnexionArray[data.userId]){
return;
}
* @param userId
* @param stream
*/
- stream(userId : any, stream: MediaStream) {
+ private stream(userId : any, stream: MediaStream) {
this.MediaManager.remoteVideo[userId].srcObject = stream;
}
*
* @param userId
*/
- addMedia (userId : any) {
- this.PeerConnexionArray[userId].addStream(this.MediaManager.localStream) // <- add streams to peer dynamically
+ private addMedia (userId : any = null) {
+ if (!this.MediaManager.localStream || !this.PeerConnexionArray[userId]) {
+ return;
+ }
+ this.PeerConnexionArray[userId].addStream(this.MediaManager.localStream) // <- add streams to peer dynamically
+ return;
}
- activePhone(){
+ private activePhone(){
this.MediaManager.activePhoneOpen();
}
- disablePhone(){
+ private disablePhone(){
this.MediaManager.disablePhoneOpen();
}
}
\ No newline at end of file