From a0b55f6b96fe83c18ba8422d5ea92a47c8ef4747 Mon Sep 17 00:00:00 2001 From: Edouard DUPIN Date: Tue, 8 Mar 2022 16:14:10 +0100 Subject: [PATCH] [DEV] test streaming for communication ==> proto to keep --- back/karideo_back.iml | 63 +++++ back/pom.xml | 59 ++++- back/src/org/kar/karideo/ConfigVariable.java | 1 + back/src/org/kar/karideo/WebLauncher.java | 32 ++- .../kar/karideo/api/WebSocketResource.java | 124 ++++++++++ .../applicationWS/IndicationWebSocket.java | 23 ++ back/src/org/kar/karideo/internal/Log.java | 107 ++++---- front/src/app/app-routing.module.ts | 4 +- front/src/app/app.module.ts | 8 +- .../webrtc-stream-in/webrtc-stream-in.html | 6 + .../webrtc-stream-in/webrtc-stream-in.less | 12 + .../webrtc-stream-in/webrtc-stream-in.ts | 79 ++++++ .../webrtc-stream-out/webrtc-stream-out.html | 7 + .../webrtc-stream-out/webrtc-stream-out.less | 17 ++ .../webrtc-stream-out/webrtc-stream-out.ts | 116 +++++++++ .../src/app/scene/conference/conference.html | 16 ++ .../src/app/scene/conference/conference.less | 10 + front/src/app/scene/conference/conference.ts | 106 ++++++++ front/src/app/scene/conference/origin.js | 228 ++++++++++++++++++ front/src/app/scene/season/season.ts | 5 +- 20 files changed, 965 insertions(+), 58 deletions(-) create mode 100644 back/karideo_back.iml create mode 100644 back/src/org/kar/karideo/api/WebSocketResource.java create mode 100644 back/src/org/kar/karideo/applicationWS/IndicationWebSocket.java create mode 100644 front/src/app/component/webrtc-stream-in/webrtc-stream-in.html create mode 100644 front/src/app/component/webrtc-stream-in/webrtc-stream-in.less create mode 100644 front/src/app/component/webrtc-stream-in/webrtc-stream-in.ts create mode 100644 front/src/app/component/webrtc-stream-out/webrtc-stream-out.html create mode 100644 front/src/app/component/webrtc-stream-out/webrtc-stream-out.less create mode 100644 front/src/app/component/webrtc-stream-out/webrtc-stream-out.ts create mode 100644 front/src/app/scene/conference/conference.html create mode 100644 front/src/app/scene/conference/conference.less create mode 100644 front/src/app/scene/conference/conference.ts create mode 100644 front/src/app/scene/conference/origin.js diff --git a/back/karideo_back.iml b/back/karideo_back.iml new file mode 100644 index 0000000..09491e6 --- /dev/null +++ b/back/karideo_back.iml @@ -0,0 +1,63 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/back/pom.xml b/back/pom.xml index b9eb909..7dc8a21 100644 --- a/back/pom.xml +++ b/back/pom.xml @@ -55,6 +55,11 @@ javax.ws.rs-api 2.1.1 + + org.glassfish.jersey.media + jersey-media-sse + ${jersey.version} + com.sun.xml.bind jaxb-impl @@ -97,6 +102,58 @@ RELEASE compile + + javax.websocket + javax.websocket-api + 1.1 + provided + + + org.glassfish.tyrus + tyrus-server + 2.0.0 + + + org.glassfish.tyrus + tyrus-container-grizzly-server + 2.0.0 + + + + + + + + + + + + + + + + + + + + + + + + + + + jakarta.servlet + jakarta.servlet-api + 5.0.0 + provided + + + + + + + @@ -119,7 +176,7 @@ exec-maven-plugin 1.4.0 - io.scenarium.oauth.WebLauncher + org.kar.karideo.WebLauncher diff --git a/back/src/org/kar/karideo/ConfigVariable.java b/back/src/org/kar/karideo/ConfigVariable.java index e98075e..97eabb8 100644 --- a/back/src/org/kar/karideo/ConfigVariable.java +++ b/back/src/org/kar/karideo/ConfigVariable.java @@ -70,6 +70,7 @@ public class ConfigVariable { String out = System.getenv("org.kar.karideo.address"); if (out == null) { return "http://0.0.0.0:18080/karideo/api/"; + //return "http://0.0.0.0:18080"; } return out; } diff --git a/back/src/org/kar/karideo/WebLauncher.java b/back/src/org/kar/karideo/WebLauncher.java index 5502e92..962575f 100755 --- a/back/src/org/kar/karideo/WebLauncher.java +++ b/back/src/org/kar/karideo/WebLauncher.java @@ -1,20 +1,27 @@ package org.kar.karideo; import org.glassfish.grizzly.http.server.HttpServer; +import org.glassfish.grizzly.http.server.NetworkListener; import org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpServerFactory; import org.glassfish.jersey.media.multipart.MultiPartFeature; import org.glassfish.jersey.server.ResourceConfig; import org.kar.karideo.api.*; import org.kar.karideo.db.DBConfig; import org.glassfish.jersey.jackson.JacksonFeature; +import org.glassfish.jersey.logging.LoggingFeature; import javax.ws.rs.core.UriBuilder; + +import java.io.BufferedReader; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; +import java.io.InputStreamReader; +import java.lang.System.Logger.Level; import java.net.URI; import java.util.Properties; +import org.glassfish.tyrus.server.Server; public class WebLauncher { public static DBConfig dbConfig; @@ -53,7 +60,7 @@ public class WebLauncher { // add jackson to be discovenr when we are ins standalone server rc.register(JacksonFeature.class); // enable this to show low level request - //rc.property(LoggingFeature.LOGGING_FEATURE_LOGGER_LEVEL_SERVER, Level.WARNING.getName()); + rc.property(LoggingFeature.LOGGING_FEATURE_LOGGER_LEVEL_SERVER, Level.INFO.getName()); System.out.println("Connect on the BDD:"); System.out.println(" getDBHost: '" + ConfigVariable.getDBHost() + "'"); @@ -68,7 +75,12 @@ public class WebLauncher { ConfigVariable.getDBName()); System.out.println(" ==> " + dbConfig); System.out.println("OAuth service " + ConfigVariable.getRestOAuthServer()); - HttpServer server = GrizzlyHttpServerFactory.createHttpServer(getBaseURI(), rc); + HttpServer server = GrizzlyHttpServerFactory.createHttpServer(getBaseURI(), rc, false); + //HttpServer server = GrizzlyHttpServerFactory.createHttpServer(getBaseURI(), false); + + //startWsServer(); + + Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() { @Override public void run() { @@ -88,4 +100,20 @@ public class WebLauncher { e.printStackTrace(); } } + + public static void startWsServer() { + Server server = new Server("localhost", 8080, "/echo", null, WebSocketResource.class); + try { + server.start(); + //BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); + //System.out.print("Please press a key to stop the server."); + //reader.readLine(); + } catch (Exception e) { + throw new RuntimeException(e); + } finally { + //server.stop(); + } + + } + } diff --git a/back/src/org/kar/karideo/api/WebSocketResource.java b/back/src/org/kar/karideo/api/WebSocketResource.java new file mode 100644 index 0000000..677675c --- /dev/null +++ b/back/src/org/kar/karideo/api/WebSocketResource.java @@ -0,0 +1,124 @@ +package org.kar.karideo.api; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.concurrent.CountDownLatch; +import java.util.logging.Logger; + +import javax.websocket.ClientEndpoint; +import javax.websocket.CloseReason; +import javax.websocket.DeploymentException; +import javax.websocket.OnClose; +import javax.websocket.OnMessage; +import javax.websocket.OnOpen; +import javax.websocket.Session; +import javax.websocket.server.ServerEndpoint; + +import org.glassfish.tyrus.client.ClientManager; + + +@ServerEndpoint(value = "/echooo") +public class WebSocketResource { + private Logger logger = Logger.getLogger(this.getClass().getName()); + @OnOpen + public void onOpen(Session session) { + logger.info("Connected ... " + session.getId()); + try { + session.getBasicRemote().sendText("start"); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + + + @OnMessage + public String onMessage(String message, Session session) { + BufferedReader bufferRead = new BufferedReader(new InputStreamReader(System.in)); + try { + logger.info("Received ...." + message); + String userInput = bufferRead.readLine(); + return userInput; + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + @OnClose + public void onClose(Session session, CloseReason closeReason) { + logger.info(String.format("Session %s close because of %s", session.getId(), closeReason)); + } + +} + + + +// +//import java.io.IOException; +// +//import javax.websocket.OnClose; +//import javax.websocket.OnError; +//import javax.websocket.OnMessage; +//import javax.websocket.OnOpen; +//import javax.websocket.Session; +//import javax.websocket.server.ServerEndpoint; +// +//import org.glassfish.grizzly.http.HttpRequestPacket; +//import org.glassfish.grizzly.websockets.ProtocolHandler; +//import org.glassfish.grizzly.websockets.WebSocket; +//import org.glassfish.grizzly.websockets.WebSocketApplication; +//import org.glassfish.grizzly.websockets.WebSocketListener; +//import org.glassfish.grizzly.websockets.DataFrame; +//import org.kar.karideo.applicationWS.IndicationWebSocket; +//import org.kar.karideo.internal.Log; +// +// +// +// +//public class WebSocketResource extends WebSocketApplication { +// +// public void onMessage(WebSocket websocket, String frame) { +// Log.error("onMessage called.....with " + frame); +// websocket.send("server send : " + frame + "received"); +// try { +// Thread.sleep(2000L); +// } catch (InterruptedException e) { +// e.printStackTrace(); +// } +// websocket.send("server send : " + frame + "received again"); +// } +// +// @Override +// public WebSocket createSocket(ProtocolHandler handler, +// HttpRequestPacket requestPacket, WebSocketListener... listeners) { +// Log.error("createWebSocket called....."); +// return new IndicationWebSocket(handler, requestPacket, listeners); +// } +// +//// @Override +//// protected IndicationWebSocket createWebSocket(Connection connection, +//// ServerWebSocketMeta meta) { +//// Log.error("createWebSocket called....."); +//// return new IndicationWebSocket(connection, meta, null); +//// } +// +// @Override +// public boolean isApplicationRequest(HttpRequestPacket arg0) { +// Log.error("isApplicationRequest called....."); +// return true; +// } +// +// @Override +// public void onConnect(WebSocket socket) { +// Log.error("onConnect called....."); +// } +// +// @Override +// public void onClose(WebSocket websocket, DataFrame frame) { +// Log.error("onClose called....."); +// } +//} +// diff --git a/back/src/org/kar/karideo/applicationWS/IndicationWebSocket.java b/back/src/org/kar/karideo/applicationWS/IndicationWebSocket.java new file mode 100644 index 0000000..6efecdd --- /dev/null +++ b/back/src/org/kar/karideo/applicationWS/IndicationWebSocket.java @@ -0,0 +1,23 @@ +package org.kar.karideo.applicationWS; +// +//import org.glassfish.grizzly.http.HttpRequestPacket; +//import org.glassfish.grizzly.websockets.DefaultWebSocket; +//import org.glassfish.grizzly.websockets.ProtocolHandler; +//import org.glassfish.grizzly.websockets.WebSocketListener; +// +//public class IndicationWebSocket extends DefaultWebSocket { +// +// public IndicationWebSocket(ProtocolHandler handler, +// HttpRequestPacket requestPacket, WebSocketListener... listeners) { +// super(handler, requestPacket, listeners); +// } +// +// +//// public IndicationWebSocket(Connection connection, WebSocketMeta meta, +//// WebSocketHandler handler) { +//// super(connection, meta, handler); +//// } +// +// +//} +// diff --git a/back/src/org/kar/karideo/internal/Log.java b/back/src/org/kar/karideo/internal/Log.java index 411653b..55a92e9 100644 --- a/back/src/org/kar/karideo/internal/Log.java +++ b/back/src/org/kar/karideo/internal/Log.java @@ -1,60 +1,63 @@ package org.kar.karideo.internal; +import io.scenarium.logger.LogLevel; +import io.scenarium.logger.Logger; + //import io.scenarium.logger.LogLevel; //import io.scenarium.logger.Logger; public class Log { -// private static final String LIB_NAME = "logger"; -// private static final String LIB_NAME_DRAW = Logger.getDrawableName(LIB_NAME); -// private static final boolean PRINT_CRITICAL = Logger.getNeedPrint(LIB_NAME, LogLevel.CRITICAL); -// private static final boolean PRINT_ERROR = Logger.getNeedPrint(LIB_NAME, LogLevel.ERROR); -// private static final boolean PRINT_WARNING = Logger.getNeedPrint(LIB_NAME, LogLevel.WARNING); -// private static final boolean PRINT_INFO = Logger.getNeedPrint(LIB_NAME, LogLevel.INFO); -// private static final boolean PRINT_DEBUG = Logger.getNeedPrint(LIB_NAME, LogLevel.DEBUG); -// private static final boolean PRINT_VERBOSE = Logger.getNeedPrint(LIB_NAME, LogLevel.VERBOSE); -// private static final boolean PRINT_TODO = Logger.getNeedPrint(LIB_NAME, LogLevel.TODO); -// private static final boolean PRINT_PRINT = Logger.getNeedPrint(LIB_NAME, LogLevel.PRINT); -// -// private Log() {} -// -// public static void print(String data) { -// if (PRINT_PRINT) -// Logger.print(LIB_NAME_DRAW, data); -// } -// -// public static void todo(String data) { -// if (PRINT_TODO) -// Logger.todo(LIB_NAME_DRAW, data); -// } -// -// public static void critical(String data) { -// if (PRINT_CRITICAL) -// Logger.critical(LIB_NAME_DRAW, data); -// } -// -// public static void error(String data) { -// if (PRINT_ERROR) -// Logger.error(LIB_NAME_DRAW, data); -// } -// -// public static void warning(String data) { -// if (PRINT_WARNING) -// Logger.warning(LIB_NAME_DRAW, data); -// } -// -// public static void info(String data) { -// if (PRINT_INFO) -// Logger.info(LIB_NAME_DRAW, data); -// } -// -// public static void debug(String data) { -// if (PRINT_DEBUG) -// Logger.debug(LIB_NAME_DRAW, data); -// } -// -// public static void verbose(String data) { -// if (PRINT_VERBOSE) -// Logger.verbose(LIB_NAME_DRAW, data); -// } + private static final String LIB_NAME = "logger"; + private static final String LIB_NAME_DRAW = Logger.getDrawableName(LIB_NAME); + private static final boolean PRINT_CRITICAL = Logger.getNeedPrint(LIB_NAME, LogLevel.CRITICAL); + private static final boolean PRINT_ERROR = Logger.getNeedPrint(LIB_NAME, LogLevel.ERROR); + private static final boolean PRINT_WARNING = Logger.getNeedPrint(LIB_NAME, LogLevel.WARNING); + private static final boolean PRINT_INFO = Logger.getNeedPrint(LIB_NAME, LogLevel.INFO); + private static final boolean PRINT_DEBUG = Logger.getNeedPrint(LIB_NAME, LogLevel.DEBUG); + private static final boolean PRINT_VERBOSE = Logger.getNeedPrint(LIB_NAME, LogLevel.VERBOSE); + private static final boolean PRINT_TODO = Logger.getNeedPrint(LIB_NAME, LogLevel.TODO); + private static final boolean PRINT_PRINT = Logger.getNeedPrint(LIB_NAME, LogLevel.PRINT); + + private Log() {} + + public static void print(String data) { + if (PRINT_PRINT) + Logger.print(LIB_NAME_DRAW, data); + } + + public static void todo(String data) { + if (PRINT_TODO) + Logger.todo(LIB_NAME_DRAW, data); + } + + public static void critical(String data) { + if (PRINT_CRITICAL) + Logger.critical(LIB_NAME_DRAW, data); + } + + public static void error(String data) { + if (PRINT_ERROR) + Logger.error(LIB_NAME_DRAW, data); + } + + public static void warning(String data) { + if (PRINT_WARNING) + Logger.warning(LIB_NAME_DRAW, data); + } + + public static void info(String data) { + if (PRINT_INFO) + Logger.info(LIB_NAME_DRAW, data); + } + + public static void debug(String data) { + if (PRINT_DEBUG) + Logger.debug(LIB_NAME_DRAW, data); + } + + public static void verbose(String data) { + if (PRINT_VERBOSE) + Logger.verbose(LIB_NAME_DRAW, data); + } } diff --git a/front/src/app/app-routing.module.ts b/front/src/app/app-routing.module.ts index befa3d9..85ed4aa 100644 --- a/front/src/app/app-routing.module.ts +++ b/front/src/app/app-routing.module.ts @@ -7,6 +7,7 @@ import { NgModule } from '@angular/core'; import { Routes, RouterModule } from '@angular/router'; // CLI imports router import { ModuleWithProviders } from '@angular/core'; +import { ConferenceComponent } from './scene/conference/conference'; import { HomeScene } from './scene/home/home'; import { TypeScene } from './scene/type/type'; import { UniverseScene } from './scene/universe/universe'; @@ -30,6 +31,7 @@ const routes: Routes = [ { path: 'home', component: HomeScene }, { path: 'upload', component: UploadScene }, { path: 'type/:universe_id/:type_id/:series_id/:season_id/:video_id', component: TypeScene }, + { path: 'conference', component: ConferenceComponent }, { path: 'universe/:universe_id/:type_id/:series_id/:season_id/:video_id', component: UniverseScene }, @@ -67,4 +69,4 @@ export class AppRoutingModule {} export class AppRoutingModule { } //export const routing: ModuleWithProviders = RouterModule.forRoot(routes); - \ No newline at end of file + diff --git a/front/src/app/app.module.ts b/front/src/app/app.module.ts index b702a1a..6df5761 100644 --- a/front/src/app/app.module.ts +++ b/front/src/app/app.module.ts @@ -12,6 +12,8 @@ import { HttpClientModule } from '@angular/common/http'; import { FormsModule, ReactiveFormsModule } from '@angular/forms'; // this is needed for dynamic selection of the select import { AppRoutingModule } from './app-routing.module'; +import { WebRtcStreamInComponent } from './component/webrtc-stream-in/webrtc-stream-in'; +import { WebRtcStreamOutComponent } from './component/webrtc-stream-out/webrtc-stream-out'; import { UploadFileComponent } from './component/upload-file/upload-file'; import { TopMenuComponent } from './component/top-menu/top-menu'; import { ElementTypeComponent } from './component/element-type/element-type'; @@ -24,6 +26,7 @@ import { PopInCreateType } from './popin/create-type/create-type'; import { PopInUploadProgress } from './popin/upload-progress/upload-progress'; import { PopInDeleteConfirm } from './popin/delete-confirm/delete-confirm'; +import { ConferenceComponent } from './scene/conference/conference'; import { HelpScene } from './scene/help/help'; import { LoginScene } from './scene/login/login'; import { SignUpScene } from './scene/sign-up/sign-up'; @@ -91,7 +94,10 @@ import { AppComponent } from './app.component'; VideoEditScene, SeasonEditScene, SeriesEditScene, - UploadScene + WebRtcStreamInComponent, + WebRtcStreamOutComponent, + UploadScene, + ConferenceComponent, ], imports: [ BrowserModule, diff --git a/front/src/app/component/webrtc-stream-in/webrtc-stream-in.html b/front/src/app/component/webrtc-stream-in/webrtc-stream-in.html new file mode 100644 index 0000000..682dc6b --- /dev/null +++ b/front/src/app/component/webrtc-stream-in/webrtc-stream-in.html @@ -0,0 +1,6 @@ +
+
+ WebRtc Stream In + +
+
diff --git a/front/src/app/component/webrtc-stream-in/webrtc-stream-in.less b/front/src/app/component/webrtc-stream-in/webrtc-stream-in.less new file mode 100644 index 0000000..3d83e27 --- /dev/null +++ b/front/src/app/component/webrtc-stream-in/webrtc-stream-in.less @@ -0,0 +1,12 @@ +.borders { + height: 300px; + width: 400px; + margin: 20px auto; + border: 2px dashed #00F; + border-radius: 10px; +} + +.borders:hover { + cursor: pointer; + border: 2px dashed #0FF; +} diff --git a/front/src/app/component/webrtc-stream-in/webrtc-stream-in.ts b/front/src/app/component/webrtc-stream-in/webrtc-stream-in.ts new file mode 100644 index 0000000..b26719b --- /dev/null +++ b/front/src/app/component/webrtc-stream-in/webrtc-stream-in.ts @@ -0,0 +1,79 @@ +import { Component, OnInit, ViewChild} from '@angular/core'; + +import { Router } from "@angular/router"; + + +@Component({ + selector: 'webrtc-stream-in', + templateUrl: './webrtc-stream-in.html', + styleUrls: ['./webrtc-stream-in.less'] +}) +export class WebRtcStreamInComponent implements OnInit { + @ViewChild('videoElement') videoElement: any; + private videoElementNative = null; + private startTime; + constructor(private router: Router) { + + } + ngOnInit() { + + } + + ngAfterViewInit() { + this.videoElementNative = this.videoElement.nativeElement; + this.videoElementNative.disablePictureInPicture = true; + } + +offerOptions = { + offerToReceiveAudio: 1, + offerToReceiveVideo: 1 +}; +/* + call():void { + console.log('Starting call'); + startTime = window.performance.now(); + var videoTracks = localStream.getVideoTracks(); + var audioTracks = localStream.getAudioTracks(); + if (videoTracks.length > 0) { + trace('Using video device: ' + videoTracks[0].label); + } + if (audioTracks.length > 0) { + console.log('Using audio device: ' + audioTracks[0].label); + } + var servers = null; + pc1 = new RTCPeerConnection(servers); + trace('Created local peer connection object pc1'); + pc1.onicecandidate = function(e) { + onIceCandidate(pc1, e); + }; + + + pc2 = new RTCPeerConnection(servers); + trace('Created remote peer connection object pc2'); + pc2.onicecandidate = function(e) { + onIceCandidate(pc2, e); + }; + pc1.oniceconnectionstatechange = function(e) { + onIceStateChange(pc1, e); + }; + pc2.oniceconnectionstatechange = function(e) { + onIceStateChange(pc2, e); + }; + pc2.onaddstream = gotRemoteStream; + + + + pc1.addStream(localStream); + trace('Added local stream to pc1'); + + trace('pc1 createOffer start'); + pc1.createOffer( + offerOptions + ).then( + onCreateOfferSuccess, + onCreateSessionDescriptionError + ); + } +*/ + +} diff --git a/front/src/app/component/webrtc-stream-out/webrtc-stream-out.html b/front/src/app/component/webrtc-stream-out/webrtc-stream-out.html new file mode 100644 index 0000000..d863c14 --- /dev/null +++ b/front/src/app/component/webrtc-stream-out/webrtc-stream-out.html @@ -0,0 +1,7 @@ +
+
+ WebRtc Stream out + + +
+
diff --git a/front/src/app/component/webrtc-stream-out/webrtc-stream-out.less b/front/src/app/component/webrtc-stream-out/webrtc-stream-out.less new file mode 100644 index 0000000..18ede07 --- /dev/null +++ b/front/src/app/component/webrtc-stream-out/webrtc-stream-out.less @@ -0,0 +1,17 @@ +.borders { + height: 350px; + width: 450px; + margin: 20px auto; + border: 2px dashed #F00; + border-radius: 10px; +} + +.borders:hover { + cursor: pointer; + border: 2px dashed #0F0; +} +video { + height: 300px; + width: 400px; + border: 2px solid #F00; +} diff --git a/front/src/app/component/webrtc-stream-out/webrtc-stream-out.ts b/front/src/app/component/webrtc-stream-out/webrtc-stream-out.ts new file mode 100644 index 0000000..f683041 --- /dev/null +++ b/front/src/app/component/webrtc-stream-out/webrtc-stream-out.ts @@ -0,0 +1,116 @@ +import { Component, OnInit,Input, ViewChild, SimpleChanges} from '@angular/core'; + +import { Router } from "@angular/router"; + +@Component({ + selector: 'webrtc-stream-out', + templateUrl: './webrtc-stream-out.html', + styleUrls: ['./webrtc-stream-out.less'] +}) +export class WebRtcStreamOutComponent implements OnInit { + @ViewChild('videoElement') videoElement: any; + @Input() streamData: boolean; + private videoElementNative = null; + private startTime; + public sourceVideoStream = null; + public stream = null; +private rtcPearConnection; + offerOptions = { + offerToReceiveAudio: 1, + offerToReceiveVideo: 1 + }; + + constructor(private router: Router) { + + } + ngOnInit() { + this.startLocalStream(); + } + + ngAfterViewInit() { + this.videoElementNative = this.videoElement.nativeElement; + this.videoElementNative.disablePictureInPicture = true; + } + + ngOnChanges(changes: SimpleChanges) { + console.log("change input: " + JSON.stringify(changes)); + if (changes["streamData"]["previousValue"] != changes["streamData"]["currentValue"]) { + console.log(" streamData ==>" + changes["streamData"]["currentValue"]); + if (changes["streamData"]["currentValue"] == true) { + this.call(); + } + } + + // You can also use categoryId.previousValue and + // categoryId.firstChange for comparing old and new values + + } + startLocalStream():void { + console.log('Requesting local stream'); + let self = this; + navigator.mediaDevices.getUserMedia({ + audio: true, + video: true + }).then(function(stream) { + console.log('Received local stream'); + self.videoElementNative.srcObject = stream; + self.stream = stream; + }) + .catch(function(e) { + alert('getUserMedia() error: ' + e.name); + }); + } +/* +onIceCandidate(pc, event):void { + getOtherPc(pc).addIceCandidate(event.candidate) + .then( + function() { + onAddIceCandidateSuccess(pc); + }, + function(err) { + onAddIceCandidateError(pc, err); + } + ); + console.log(getName(pc) + ' ICE candidate: \n' + (event.candidate ? + event.candidate.candidate : '(null)')); +} +*/ + call():void { + console.log('Starting call'); + this.startTime = window.performance.now(); + if (this.stream == null){ + console.log("local stream is disable"); + return; + } + var videoTracks = this.stream.getVideoTracks(); + var audioTracks = this.stream.getAudioTracks(); + if (videoTracks.length > 0) { + console.log('Using video device: ' + videoTracks[0].label); + } + if (audioTracks.length > 0) { + console.log('Using audio device: ' + audioTracks[0].label); + } + var servers = null; + this.rtcPearConnection = new RTCPeerConnection(servers); + console.log('Created local peer connection object pc1'); + this.rtcPearConnection.onicecandidate = function(e) { + console.log("onicecandidate " + e); + }; + this.rtcPearConnection.oniceconnectionstatechange = function(e) { + console.log("oniceconnectionstatechange " + e); + }; + console.log('Added local stream [START]'); + this.rtcPearConnection.addStream(this.stream); + console.log('Added local stream [ END ]'); + + console.log('pc1 createOffer start'); + this.rtcPearConnection.createOffer( + this.offerOptions + ).then( function(e) { + console.log("create offer error " + JSON.stringify(e)); + } + ); + } + + +} diff --git a/front/src/app/scene/conference/conference.html b/front/src/app/scene/conference/conference.html new file mode 100644 index 0000000..7ce4338 --- /dev/null +++ b/front/src/app/scene/conference/conference.html @@ -0,0 +1,16 @@ +
+
+ Conference +
+ + +
+ +
+ + + + +
+ +
diff --git a/front/src/app/scene/conference/conference.less b/front/src/app/scene/conference/conference.less new file mode 100644 index 0000000..931854b --- /dev/null +++ b/front/src/app/scene/conference/conference.less @@ -0,0 +1,10 @@ + + +.container { + padding: 16px; +} + +.connectivityButton { + margin: 2% 2%; + width: 21%; +} diff --git a/front/src/app/scene/conference/conference.ts b/front/src/app/scene/conference/conference.ts new file mode 100644 index 0000000..e9d8821 --- /dev/null +++ b/front/src/app/scene/conference/conference.ts @@ -0,0 +1,106 @@ +/** @file + * @author Edouard DUPIN + * @copyright 2018, Edouard DUPIN, all right reserved + * @license PROPRIETARY (see license file) + */ + +import { Component, OnInit } from '@angular/core'; +import { Router, ActivatedRoute, ParamMap } from '@angular/router'; +import { Location } from '@angular/common'; +import { fadeInAnimation } from '../../_animations/index'; + +import { ArianeService } from '../../service/ariane'; +import { environment } from 'environments/environment'; + +@Component({ + selector: 'conference', + templateUrl: './conference.html', + styleUrls: ['./conference.less'], + animations: [fadeInAnimation], + host: { '[@fadeInAnimation]': '' } +}) + +export class ConferenceComponent implements OnInit { + //id_type = -1; + //id_univers = -1; + id_group = -1; + name: string = ""; + description: string = ""; + cover: string = "" + covers: Array = [] + saisons_error: string = ""; + saisons: Array = []; + videos_error: string = ""; + videos: Array = []; + constructor(private route: ActivatedRoute, + private router: Router, + private locate: Location, + private arianeService: ArianeService) { + + } + public streamOutRequested = false; + + ngOnInit() { + /* + + this.arianeService.updateManual(this.route.snapshot.paramMap); + //this.id_univers = parseInt(this.route.snapshot.paramMap.get('univers_id')); + //this.id_type = parseInt(this.route.snapshot.paramMap.get('type_id')); + this.id_group = this.arianeService.getGroupId(); + let self = this; + this.groupService.get(this.id_group) + .then(function(response) { + self.name = response.name; + self.description = response.description; + if (response.covers == undefined || response.covers == null || response.covers.length == 0) { + self.cover = null; + self.covers = []; + } else { + self.cover = self.groupService.getCoverUrl(response.covers[0]); + for (let iii=0; iii 0) { + console.log('Using video device: ' + videoTracks[0].label); + } + if (audioTracks.length > 0) { + console.log('Using audio device: ' + audioTracks[0].label); + } + var servers = null; + pc1 = new RTCPeerConnection(servers); + console.log('Created local peer connection object pc1'); + pc1.onicecandidate = function(e) { + onIceCandidate(pc1, e); + }; + + + pc2 = new RTCPeerConnection(servers); + console.log('Created remote peer connection object pc2'); + pc2.onicecandidate = function(e) { + onIceCandidate(pc2, e); + }; + pc1.oniceconnectionstatechange = function(e) { + onIceStateChange(pc1, e); + }; + pc2.oniceconnectionstatechange = function(e) { + onIceStateChange(pc2, e); + }; + pc2.onaddstream = gotRemoteStream; + + + + pc1.addStream(localStream); + console.log('Added local stream to pc1'); + + console.log('pc1 createOffer start'); + pc1.createOffer( + offerOptions + ).then( + onCreateOfferSuccess, + onCreateSessionDescriptionError + ); +} + +function onCreateSessionDescriptionError(error) { + console.log('Failed to create session description: ' + error.toString()); +} + +function onCreateOfferSuccess(desc) { + console.log('Offer from pc1\n' + desc.sdp); + console.log('pc1 setLocalDescription start'); + pc1.setLocalDescription(desc).then( + function() { + onSetLocalSuccess(pc1); + }, + onSetSessionDescriptionError + ); + console.log('pc2 setRemoteDescription start'); + pc2.setRemoteDescription(desc).then( + function() { + onSetRemoteSuccess(pc2); + }, + onSetSessionDescriptionError + ); + console.log('pc2 createAnswer start'); + // Since the 'remote' side has no media stream we need + // to pass in the right constraints in order for it to + // accept the incoming offer of audio and video. + pc2.createAnswer().then( + onCreateAnswerSuccess, + onCreateSessionDescriptionError + ); +} + +function onSetLocalSuccess(pc) { + console.log(getName(pc) + ' setLocalDescription complete'); +} + +function onSetRemoteSuccess(pc) { + console.log(getName(pc) + ' setRemoteDescription complete'); +} + +function onSetSessionDescriptionError(error) { + console.log('Failed to set session description: ' + error.toString()); +} + +function gotRemoteStream(e) { + remoteVideo.srcObject = e.stream; + console.log('pc2 received remote stream'); +} + +function onCreateAnswerSuccess(desc) { + console.log('Answer from pc2:\n' + desc.sdp); + console.log('pc2 setLocalDescription start'); + pc2.setLocalDescription(desc).then( + function() { + onSetLocalSuccess(pc2); + }, + onSetSessionDescriptionError + ); + console.log('pc1 setRemoteDescription start'); + pc1.setRemoteDescription(desc).then( + function() { + onSetRemoteSuccess(pc1); + }, + onSetSessionDescriptionError + ); +} +/* +function onIceCandidate(pc, event) { + getOtherPc(pc).addIceCandidate(event.candidate) + .then( + function() { + onAddIceCandidateSuccess(pc); + }, + function(err) { + onAddIceCandidateError(pc, err); + } + ); + console.log(getName(pc) + ' ICE candidate: \n' + (event.candidate ? + event.candidate.candidate : '(null)')); +} +*/ + +function onAddIceCandidateSuccess(pc) { + console.log(getName(pc) + ' addIceCandidate success'); +} + +function onAddIceCandidateError(pc, error) { + console.log(getName(pc) + ' failed to add ICE Candidate: ' + error.toString()); +} + +function onIceStateChange(pc, event) { + if (pc) { + console.log(getName(pc) + ' ICE state: ' + pc.iceConnectionState); + console.log('ICE state change event: ', event); + } +} + +function hangup() { + console.log('Ending call'); + pc1.close(); + pc2.close(); + pc1 = null; + pc2 = null; + hangupButton.disabled = true; + callButton.disabled = false; +} + +// logging utility +function console.log(arg) { + var now = (window.performance.now() / 1000).toFixed(3); + console.log(now + ': ', arg); +} diff --git a/front/src/app/scene/season/season.ts b/front/src/app/scene/season/season.ts index f9bcb96..81f2002 100644 --- a/front/src/app/scene/season/season.ts +++ b/front/src/app/scene/season/season.ts @@ -18,7 +18,9 @@ import { ArianeService } from '../../service/ariane'; templateUrl: './season.html', styleUrls: ['./season.less'], animations: [fadeInAnimation], - host: { '[@fadeInAnimation]': '' } + host: { + '[@fadeInAnimation]': '', + }, }) export class SeasonScene implements OnInit { name: string = ""; @@ -85,6 +87,7 @@ export class SeasonScene implements OnInit { } onSelectVideo(_event: any, _idSelected: number):void { + console.log("select video : " + _idSelected); this.arianeService.navigateVideo(_idSelected, _event.which==2, _event.ctrlKey); }