Skip to content

Commit

Permalink
Merge branch 'main' into youtube-node
Browse files Browse the repository at this point in the history
  • Loading branch information
besidev authored Dec 4, 2023
2 parents 22fcc76 + 923e11e commit f0fb6b8
Show file tree
Hide file tree
Showing 17 changed files with 857 additions and 4 deletions.
9 changes: 5 additions & 4 deletions gradle.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
JPRO_PLATFORM_VERSION = 0.2.7-SNAPSHOT
JPRO_VERSION = 2023.3.1

JPRO_VERSION = 2023.3.2-SNAPSHOT
JAVAFX_VERSION = 17.0.9
SIMPLEFX_VERSION = 3.2.27
JMEMORYBUDDY_VERSION = 0.5.1
Expand All @@ -13,7 +14,7 @@ ENSEMBLE_GRADLE_PLUGIN_VERSION=0.1.0-SNAPSHOT
JAVACPP_VERSION = 1.5.9
JAVACV_VERSION = 1.5.9
JSON_VERSION = 20231013
CONTROLSFX_VERSION = 11.1.2
CONTROLSFX_VERSION = 11.2.0
FLEXMARK_VERSION=0.64.8
JETBRAINS_ANNOTATIONS_VERSION = 24.0.1
AUTH0_JAVAJWT_VERSION = 4.4.0
Expand All @@ -23,11 +24,11 @@ JAKARTA_VALIDATION_VERSION = 3.0.2
CSSFX_VERSION = 11.5.1
IKONLI_VERSION = 12.3.1
ATLANTAFX_VERSION = 2.0.1
COMMONS_IO_VERSION = 2.15.0
COMMONS_IO_VERSION = 2.15.1
JUNIT_VERSION = 5.10.1
ASSERTJ_VERSION = 3.24.2
HAMCREST_VERSION = 2.2
MOCKITO_VERSION = 5.7.0
MOCKITO_VERSION = 5.8.0
TESTFX_VERSION = 4.0.17
SLF4J_API_VERSION = 2.0.9
LOGBACK_VERSION = 1.4.11
3 changes: 3 additions & 0 deletions jpro-webrtc/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
dependencies {
implementation "com.sandec.jpro:jpro-webapi:$JPRO_VERSION"
}
22 changes: 22 additions & 0 deletions jpro-webrtc/example/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
plugins {
id 'org.openjfx.javafxplugin'
id 'jpro-gradle-plugin'
}

//mainClassName = "one.jpro.platform.webrtc.example.simple.WebRTCSimple"
mainClassName = "one.jpro.platform.webrtc.example.videoroom.VideoRoomApp"

application {
mainClass = "$mainClassName"
mainModule = moduleName
}

dependencies {
implementation project(':jpro-webrtc')
implementation project(':jpro-routing:core')
}

javafx {
version = "$JAVAFX_VERSION"
modules = ['javafx.graphics', 'javafx.controls', 'javafx.swing', 'javafx.fxml', 'javafx.media', 'javafx.web']
}
9 changes: 9 additions & 0 deletions jpro-webrtc/example/src/main/java/module-info.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
module one.jpro.platform.webrtc.example {
requires one.jpro.platform.webrtc;
requires javafx.controls;
requires jpro.webapi;
requires one.jpro.platform.routing.core;

exports one.jpro.platform.webrtc.example.simple;
exports one.jpro.platform.webrtc.example.videoroom;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package one.jpro.platform.webrtc.example.simple;

import com.jpro.webapi.JProApplication;
import com.jpro.webapi.JSVariable;
import javafx.collections.ListChangeListener;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import one.jpro.platform.webrtc.MediaStream;
import one.jpro.platform.webrtc.RTCDetails;
import one.jpro.platform.webrtc.RTCPeerConnection;
import one.jpro.platform.webrtc.VideoFrame;

public class WebRTCSimple extends JProApplication {

@Override
public void start(Stage primaryStage) throws Exception {

var pin = new VBox();

//var rtc = new RTCPeerConnection(getWebAPI());
var rtc1 = new RTCPeerConnection(getWebAPI());
var rtc2 = new RTCPeerConnection(getWebAPI());

var video1 = new VideoFrame(getWebAPI());
var video2 = new VideoFrame(getWebAPI());

rtc1.tracks.addListener((ListChangeListener<? super JSVariable>) change -> {
while(change.next()) {
if(change.wasAdded()) {
video1.setStream(change.getAddedSubList().get(0));
}
}
});
rtc2.tracks.addListener((ListChangeListener<? super JSVariable>) change -> {
while(change.next()) {
if(change.wasAdded()) {
video2.setStream(change.getAddedSubList().get(0));
}
}
});

var f1 = MediaStream.getCameraStream(rtc1.getWebAPI()).js.thenAccept(stream -> {
rtc1.addStream(stream);
});
var f2 = MediaStream.getCameraStream(rtc2.getWebAPI()).js.thenAccept(stream -> {
rtc2.addStream(stream);
});

(f1.thenCompose(a -> f2)).thenAccept( r ->
RTCPeerConnection.connectConnections(rtc1, rtc2)
);

var WebRTCLabel = new Label("WebRTC");
WebRTCLabel.setStyle("-fx-font-size: 20px;");
pin.getChildren().add(WebRTCLabel);
pin.getChildren().add(new RTCDetails(rtc1));
pin.getChildren().add(video1);
pin.getChildren().add(new Label(" ---------------- "));

pin.getChildren().add(new RTCDetails(rtc2));
pin.getChildren().add(video2);

//pin.getChildren().add(createLabel("signalingState", rtc.tracks));

primaryStage.setScene(new Scene(pin));

primaryStage.show();
}



}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package one.jpro.platform.webrtc.example.videoroom;

import one.jpro.platform.routing.Filters;
import one.jpro.platform.routing.Route;
import one.jpro.platform.routing.RouteApp;
import one.jpro.platform.routing.RouteUtils;
import one.jpro.platform.webrtc.example.videoroom.page.OverviewPage;
import one.jpro.platform.webrtc.example.videoroom.page.VideoRoomPage;
import simplefx.experimental.parts.FXFuture;

import java.util.regex.Pattern;

import static one.jpro.platform.routing.RouteUtils.viewFromNode;

public class VideoRoomApp extends RouteApp {

static Pattern roomPattern = Pattern.compile("/room/([0-9a-fA-F]*)");

@Override
public Route createRoute() {

getScene().getStylesheets().add("/one/jpro/platform/webrtc/example/videoroom/videoroom.css");

// / -> overview
// /room/id -> room
return Route.empty()
.and(RouteUtils.getNode("/", (r) -> new OverviewPage()))
.and(r -> {
System.out.println("path: " + r.path());
var matcher = roomPattern.matcher(r.path());
if(matcher.matches()) {
var roomID = matcher.group(1);
return FXFuture.unit(viewFromNode(new VideoRoomPage(roomID, getWebAPI())));
} else {
return FXFuture.unit(null);
}
})
.filter(Filters.FullscreenFilter(true));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
package one.jpro.platform.webrtc.example.videoroom.model;

import com.jpro.webapi.JSVariable;
import com.jpro.webapi.WebAPI;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ListChangeListener;
import javafx.collections.ObservableList;
import one.jpro.platform.webrtc.MediaStream;
import one.jpro.platform.webrtc.RTCPeerConnection;
import one.jpro.platform.webrtc.VideoFrame;

public class VideoRoom {
static ObservableList<VideoRoom> rooms = FXCollections.observableArrayList();

public String id;
ObservableList<User> users = FXCollections.observableArrayList();

public VideoRoom(String id) {
this.id = id;
}


public static VideoRoom getOrCreateRoom(String id) {
for(VideoRoom room : rooms) {
if(room.id.equals(id)) {
return room;
}
}
VideoRoom room = new VideoRoom(id);
rooms.add(room);
return room;
}

public void addUserAndCreateConnections(User user) {
for(User otherUser : users) {
createWebRTCUserVideo(user, otherUser);
}
users.add(user);
}

public static void createWebRTCUserVideo(User user1, User user2) {
var webAPI1 = user1.webAPI;
var webAPI2 = user2.webAPI;

var rtc1 = new RTCPeerConnection(webAPI1);
var rtc2 = new RTCPeerConnection(webAPI2);

var video1 = new VideoFrame(webAPI1);
var video2 = new VideoFrame(webAPI2);

rtc1.tracks.addListener((ListChangeListener<? super JSVariable>) change -> {
System.out.println("tracks size for user 1: " + rtc1.tracks.size());
while(change.next()) {
if(change.wasAdded()) {
video1.setStream(change.getAddedSubList().get(0));
}
}
});
rtc2.tracks.addListener((ListChangeListener<? super JSVariable>) change -> {
System.out.println("tracks size for user 2: " + rtc2.tracks.size());
while(change.next()) {
if(change.wasAdded()) {
video2.setStream(change.getAddedSubList().get(0));
}
}
});

user1.mediaStream.addListener((observable, oldValue, newValue) -> {
try {
//rtc1.removeAllTracks();
rtc1.removeStream(oldValue);
newValue.js.thenAccept(stream -> {
rtc1.addStream(stream);
});
} catch (Exception e) {
e.printStackTrace();
}
});
user2.mediaStream.addListener((observable, oldValue, newValue) -> {
try {
//rtc2.removeAllTracks();
rtc2.removeStream(oldValue);
newValue.js.thenAccept(stream -> {
rtc2.addStream(stream);
});
} catch (Exception e) {
e.printStackTrace();
}
});
var f1 = user1.mediaStream.get().js.thenAccept(stream -> {
rtc1.addStream(stream);
});
var f2 = user2.mediaStream.get().js.thenAccept(stream -> {
rtc2.addStream(stream);
});

(f1.thenCompose(a -> f2)).thenAccept( r ->
RTCPeerConnection.connectConnections(rtc1, rtc2)
);

user1.userVideos.add(new UserVideo(user2, video1, rtc1));

user2.userVideos.add(new UserVideo(user1, video2, rtc2));
}

public static ObservableList<VideoRoom> getRooms() {
return rooms;
}


/**
* A user in a room
*/
public static class User {

public User(String name, MediaStream mediaStream, WebAPI webAPI) {
this.name.set(name);
this.mediaStream = new SimpleObjectProperty<>(mediaStream);
this.webAPI = webAPI;
}

public WebAPI webAPI;
public StringProperty name = new SimpleStringProperty("User");

public SimpleObjectProperty<MediaStream> mediaStream;

public ObservableList<UserVideo> userVideos = FXCollections.observableArrayList();
}

/**
* The video of a user in a room accessed by a specific user
*/
public static class UserVideo {

UserVideo (User user, VideoFrame videoFrame, RTCPeerConnection connection) {
this.user = user;
this.videoFrame = videoFrame;
this.connection = connection;
}

public User user;
public VideoFrame videoFrame;
public RTCPeerConnection connection;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package one.jpro.platform.webrtc.example.videoroom.page;

import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.VBox;
import one.jpro.platform.routing.LinkUtil;

public class OverviewPage extends VBox {

public OverviewPage() {
getStyleClass().add("page");
getStyleClass().add("overview-page");
var overview = new Label("Overview");
overview.getStyleClass().add("title");
getChildren().add(overview);

int randomId = (int) (Math.random() * 1000);
var button = new Button("Create Room");
LinkUtil.setLink(button, "/room/" + randomId);
getChildren().add(button);
}
}
Loading

0 comments on commit f0fb6b8

Please sign in to comment.