mirror of https://github.com/OpenVidu/openvidu.git
Initial OpenVidu platform commit
parent
ad2a6ceb5c
commit
103377996a
|
@ -0,0 +1,13 @@
|
|||
(C) Copyright 2016 Kurento (http://kurento.org)
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
|
@ -0,0 +1,257 @@
|
|||
[![][KurentoImage]][Kurento]
|
||||
|
||||
Copyright © 2013-2016 [Kurento]. Licensed under [LGPL v2.1 License].
|
||||
|
||||
kurento-room
|
||||
============
|
||||
|
||||
Kurento Room is composed by several modules to offer group communications by
|
||||
means of WebRTC. These modules are:
|
||||
|
||||
* `kurento-room-sdk` - module that provides a management interface for
|
||||
developers of multimedia conferences (rooms) applications in Java
|
||||
* `kurento-room-server` - Kurento’s own implementation of a room API, it
|
||||
provides the WebSockets API for the communications between room clients and
|
||||
the server.
|
||||
* `kurento-room-client` - Java library that uses WebSockets and JSON-RPC to
|
||||
interact with the server-side of the Room API. Can be used to implement the
|
||||
client-side of a room application.
|
||||
* `kurento-room-client-js` - Javascript library that acts as wrapper for several
|
||||
JS APIs (WebRTC, WebSockets, Kurento Utils). Can be used to implement the
|
||||
client-side of a room application.
|
||||
* `kurento-room-demo` - demonstration project, contains the client-side
|
||||
implementation (HTML, Javascript, graphic resources) and embeds the room
|
||||
server to provide the functionality required for group communications
|
||||
* `kurento-room-test` - integration and functionality tests for the basic room
|
||||
server application
|
||||
* `kurento-room-demo-test` - integration and functionality tests for the demo
|
||||
application.
|
||||
|
||||
There is extensive documentation on each of these components together with a
|
||||
tutorial based on the Room demo. This documentation can be easily generated in
|
||||
HTML format from the [kurento-room-doc](./kurento-room-doc/README.md) project.
|
||||
|
||||
Dependencies
|
||||
------------
|
||||
|
||||
These are some of the design and architecture requirements that an application
|
||||
has to fulfill in order to integrate the Room API:
|
||||
|
||||
* include the SDK module to its dependencies list
|
||||
* create one of the two `RoomManager` types as a singleton instance by
|
||||
providing implementations for the following interfaces:
|
||||
* `RoomEventHandler`
|
||||
* `KurentoClientProvider`
|
||||
* develop the client-side of the application for devices that support WebRTC
|
||||
(*hint:* or use our *client-js* library and take a look at the demo's client
|
||||
implementation)
|
||||
* design a room signaling protocol that will be used between the clients and
|
||||
the server (*hint:* or use the WebSockets API from `kurento-room-server`)
|
||||
* implement a handler for clients' requests on the server-side, that will
|
||||
use the `RoomManager` to process these requests (*hint:* JSON-RPC handler
|
||||
from `kurento-room-server`)
|
||||
* choose a response and notification mechanism for the communication with the
|
||||
clients (*hint:* JSON-RPC notification service from `kurento-room-server`)
|
||||
|
||||
About the technology stacks that can or should be used to implement a Rooms
|
||||
application:
|
||||
|
||||
* WebSockets for the communications between the server and the clients
|
||||
* Spring and Spring Boot for the easy configuration and integration with some
|
||||
of Kurento's modules. It also provides a WebSockets library.
|
||||
|
||||
And of course, the main requirement is at least one installation of the Kurento
|
||||
Media Server, accessible to the room application.
|
||||
|
||||
Running the demo
|
||||
----------------
|
||||
|
||||
For a quick initial contact with the framework, we recommend running the demo
|
||||
application and observing the exchange of Websocket messages between the clients
|
||||
and the server.
|
||||
|
||||
Currently, the demo is only supported for Ubuntu 14.04 LTS 64bits.
|
||||
|
||||
After cloning the tutorial, it can be executed directly from the terminal by
|
||||
using Maven's `exec` plugin. To make sure the demo's
|
||||
build and execution works smoothly, a stable release (or tag) is checked out
|
||||
before proceeding with the build (prevents missing dependencies, given that in
|
||||
Kurento *master* is the development branch):
|
||||
|
||||
```
|
||||
$ git clone git@github.com:Kurento/kurento-room.git
|
||||
$ cd kurento-room
|
||||
$ git checkout 6.1.0
|
||||
$ cd kurento-room-demo
|
||||
$ mvn compile exec:java
|
||||
```
|
||||
|
||||
Now open the following URL in a WebRTC-compatible browser and connect to a new
|
||||
room by providing the desired user and room names:
|
||||
|
||||
```
|
||||
http://localhost:8080
|
||||
```
|
||||
|
||||
Configuring the demo
|
||||
--------------------
|
||||
|
||||
There are a couple of interesting options or properties that might have to be
|
||||
modified for the demo to function properly.
|
||||
|
||||
The properties file, **kroomdemo.conf.json**, used in the demo's execution as
|
||||
described above, is located in the folder `src/main/resources` and its
|
||||
contents are the following:
|
||||
|
||||
{
|
||||
"kms": {
|
||||
"uris": ["ws://localhost:8888/kurento","ws://127.0.0.1:8888/kurento"]
|
||||
},
|
||||
"app": {
|
||||
"uri": "http://localhost:8080/"
|
||||
},
|
||||
"kurento": {
|
||||
"client": {
|
||||
//milliseconds
|
||||
"requestTimeout": 20000
|
||||
}
|
||||
},
|
||||
"demo": {
|
||||
//mario-wings.png or wizard.png
|
||||
"hatUrl": "mario-wings.png"
|
||||
"hatCoords": {
|
||||
// mario-wings hat
|
||||
"offsetXPercent": -0.35F,
|
||||
"offsetYPercent": -1.2F,
|
||||
"widthPercent": 1.6F,
|
||||
"heightPercent": 1.6F
|
||||
|
||||
//wizard hat
|
||||
//"offsetXPercent": -0.2F,
|
||||
//"offsetYPercent": -1.35F,
|
||||
//"widthPercent": 1.5F,
|
||||
//"heightPercent": 1.5F
|
||||
},
|
||||
"loopback" : {
|
||||
"remote": false,
|
||||
//matters only when remote is true
|
||||
"andLocal": false
|
||||
},
|
||||
"authRegex": ".*",
|
||||
"kmsLimit": 10
|
||||
}
|
||||
}
|
||||
|
||||
These properties can be overwritten on the command-line when starting
|
||||
the demo server:
|
||||
|
||||
```
|
||||
$ mvn compile exec:java -Dkms.uris=[\"ws://192.168.1.99:9001/kurento\"]
|
||||
```
|
||||
|
||||
In this example, we've instructed the demo to use a different URI of a running
|
||||
KMS instance when creating the `KurentoClient` required by the Room API.
|
||||
|
||||
More details on the demo's configuration and execution can be found in the demo's
|
||||
[README page](./kurento-room-demo/README.md) or in the Room API
|
||||
[documentation](./kurento-room-doc/README.md) .
|
||||
|
||||
What is Kurento
|
||||
---------------
|
||||
|
||||
Kurento is an open source software project providing a platform suitable
|
||||
for creating modular applications with advanced real-time communication
|
||||
capabilities. For knowing more about Kurento, please visit the Kurento
|
||||
project website: http://www.kurento.org.
|
||||
|
||||
Kurento is part of [FIWARE]. For further information on the relationship of
|
||||
FIWARE and Kurento check the [Kurento FIWARE Catalog Entry]
|
||||
|
||||
Kurento is part of the [NUBOMEDIA] research initiative.
|
||||
|
||||
Documentation
|
||||
-------------
|
||||
|
||||
The Kurento project provides detailed [documentation] including tutorials,
|
||||
installation and development guides. A simplified version of the documentation
|
||||
can be found on [readthedocs.org]. The [Open API specification] a.k.a. Kurento
|
||||
Protocol is also available on [apiary.io].
|
||||
|
||||
Source
|
||||
------
|
||||
|
||||
Code for other Kurento projects can be found in the [GitHub Kurento Group].
|
||||
|
||||
News and Website
|
||||
----------------
|
||||
|
||||
Check the [Kurento blog]
|
||||
Follow us on Twitter @[kurentoms].
|
||||
|
||||
Issue tracker
|
||||
-------------
|
||||
|
||||
Issues and bug reports should be posted to the [GitHub Kurento bugtracker]
|
||||
|
||||
Licensing and distribution
|
||||
--------------------------
|
||||
|
||||
Software associated to Kurento is provided as open source under GNU Library or
|
||||
"Lesser" General Public License, version 2.1 (LGPL-2.1). Please check the
|
||||
specific terms and conditions linked to this open source license at
|
||||
http://opensource.org/licenses/LGPL-2.1. Please note that software derived as a
|
||||
result of modifying the source code of Kurento software in order to fix a bug
|
||||
or incorporate enhancements is considered a derivative work of the product.
|
||||
Software that merely uses or aggregates (i.e. links to) an otherwise unmodified
|
||||
version of existing software is not considered a derivative work.
|
||||
|
||||
Contribution policy
|
||||
-------------------
|
||||
|
||||
You can contribute to the Kurento community through bug-reports, bug-fixes, new
|
||||
code or new documentation. For contributing to the Kurento community, drop a
|
||||
post to the [Kurento Public Mailing List] providing full information about your
|
||||
contribution and its value. In your contributions, you must comply with the
|
||||
following guidelines
|
||||
|
||||
* You must specify the specific contents of your contribution either through a
|
||||
detailed bug description, through a pull-request or through a patch.
|
||||
* You must specify the licensing restrictions of the code you contribute.
|
||||
* For newly created code to be incorporated in the Kurento code-base, you must
|
||||
accept Kurento to own the code copyright, so that its open source nature is
|
||||
guaranteed.
|
||||
* You must justify appropriately the need and value of your contribution. The
|
||||
Kurento project has no obligations in relation to accepting contributions
|
||||
from third parties.
|
||||
* The Kurento project leaders have the right of asking for further
|
||||
explanations, tests or validations of any code contributed to the community
|
||||
before it being incorporated into the Kurento code-base. You must be ready to
|
||||
addressing all these kind of concerns before having your code approved.
|
||||
|
||||
Support
|
||||
-------
|
||||
|
||||
The Kurento project provides community support through the [Kurento Public
|
||||
Mailing List] and through [StackOverflow] using the tags *kurento* and
|
||||
*fiware-kurento*.
|
||||
|
||||
Before asking for support, please read first the [Kurento Netiquette Guidelines]
|
||||
|
||||
[documentation]: http://www.kurento.org/documentation
|
||||
[FIWARE]: http://www.fiware.org
|
||||
[GitHub Kurento bugtracker]: https://github.com/Kurento/bugtracker/issues
|
||||
[GitHub Kurento Group]: https://github.com/kurento
|
||||
[kurentoms]: http://twitter.com/kurentoms
|
||||
[Kurento]: http://kurento.org
|
||||
[Kurento Blog]: http://www.kurento.org/blog
|
||||
[Kurento FIWARE Catalog Entry]: http://catalogue.fiware.org/enablers/stream-oriented-kurento
|
||||
[Kurento Netiquette Guidelines]: http://www.kurento.org/blog/kurento-netiquette-guidelines
|
||||
[Kurento Public Mailing list]: https://groups.google.com/forum/#!forum/kurento
|
||||
[KurentoImage]: https://secure.gravatar.com/avatar/21a2a12c56b2a91c8918d5779f1778bf?s=120
|
||||
[LGPL v2.1 License]: http://www.gnu.org/licenses/lgpl-2.1.html
|
||||
[NUBOMEDIA]: http://www.nubomedia.eu
|
||||
[StackOverflow]: http://stackoverflow.com/search?q=kurento
|
||||
[Read-the-docs]: http://read-the-docs.readthedocs.org/
|
||||
[readthedocs.org]: http://kurento.readthedocs.org/
|
||||
[Open API specification]: http://kurento.github.io/doc-kurento/
|
||||
[apiary.io]: http://docs.streamoriented.apiary.io/
|
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"directory" : "static/bower_components"
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry kind="src" output="target/classes" path="src/main/java">
|
||||
<attributes>
|
||||
<attribute name="optional" value="true"/>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources">
|
||||
<attributes>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="src" output="target/test-classes" path="src/test/java">
|
||||
<attributes>
|
||||
<attribute name="optional" value="true"/>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8">
|
||||
<attributes>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
|
||||
<attributes>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="output" path="target/classes"/>
|
||||
</classpath>
|
|
@ -0,0 +1 @@
|
|||
/target/
|
|
@ -0,0 +1,23 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>kurento-room-client-js</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.m2e.core.maven2Builder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||
<nature>org.eclipse.m2e.core.maven2Nature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
|
@ -0,0 +1,3 @@
|
|||
eclipse.preferences.version=1
|
||||
encoding//src/main/resources=UTF-8
|
||||
encoding/<project>=UTF-8
|
|
@ -0,0 +1,5 @@
|
|||
eclipse.preferences.version=1
|
||||
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
|
||||
org.eclipse.jdt.core.compiler.compliance=1.8
|
||||
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
|
||||
org.eclipse.jdt.core.compiler.source=1.8
|
|
@ -0,0 +1,4 @@
|
|||
activeProfiles=
|
||||
eclipse.preferences.version=1
|
||||
resolveWorkspaceProjects=true
|
||||
version=1
|
|
@ -0,0 +1,118 @@
|
|||
[](http://www.apache.org/licenses/LICENSE-2.0)
|
||||
[](http://doc-kurento-room.readthedocs.org/en/latest/)
|
||||
[](https://hub.docker.com/r/fiware/stream-oriented-kurento/)
|
||||
[](http://stackoverflow.com/questions/tagged/kurento)
|
||||
|
||||
[![][KurentoImage]][Kurento]
|
||||
|
||||
Copyright © 2013-2016 [Kurento]. Licensed under [Apache 2.0 License].
|
||||
|
||||
kurento-room-client-js
|
||||
======================
|
||||
|
||||
Kurento Room Client JS is a Javascript library that can be used to implement
|
||||
the client-side of group communications applications based on WebRTC.
|
||||
It uses WebSockets and JSON-RPC to interact with the server-side of the Room API.
|
||||
|
||||
What is Kurento
|
||||
---------------
|
||||
|
||||
Kurento is an open source software project providing a platform suitable
|
||||
for creating modular applications with advanced real-time communication
|
||||
capabilities. For knowing more about Kurento, please visit the Kurento
|
||||
project website: http://www.kurento.org.
|
||||
|
||||
Kurento is part of [FIWARE]. For further information on the relationship of
|
||||
FIWARE and Kurento check the [Kurento FIWARE Catalog Entry]
|
||||
|
||||
Kurento is part of the [NUBOMEDIA] research initiative.
|
||||
|
||||
Documentation
|
||||
-------------
|
||||
|
||||
The Kurento project provides detailed [documentation] including tutorials,
|
||||
installation and development guides. A simplified version of the documentation
|
||||
can be found on [readthedocs.org]. The [Open API specification] a.k.a. Kurento
|
||||
Protocol is also available on [apiary.io].
|
||||
|
||||
Source
|
||||
------
|
||||
|
||||
Code for other Kurento projects can be found in the [GitHub Kurento Group].
|
||||
|
||||
News and Website
|
||||
----------------
|
||||
|
||||
Check the [Kurento blog]
|
||||
Follow us on Twitter @[kurentoms].
|
||||
|
||||
Issue tracker
|
||||
-------------
|
||||
|
||||
Issues and bug reports should be posted to the [GitHub Kurento bugtracker]
|
||||
|
||||
Licensing and distribution
|
||||
--------------------------
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
Contribution policy
|
||||
-------------------
|
||||
|
||||
You can contribute to the Kurento community through bug-reports, bug-fixes, new
|
||||
code or new documentation. For contributing to the Kurento community, drop a
|
||||
post to the [Kurento Public Mailing List] providing full information about your
|
||||
contribution and its value. In your contributions, you must comply with the
|
||||
following guidelines
|
||||
|
||||
* You must specify the specific contents of your contribution either through a
|
||||
detailed bug description, through a pull-request or through a patch.
|
||||
* You must specify the licensing restrictions of the code you contribute.
|
||||
* For newly created code to be incorporated in the Kurento code-base, you must
|
||||
accept Kurento to own the code copyright, so that its open source nature is
|
||||
guaranteed.
|
||||
* You must justify appropriately the need and value of your contribution. The
|
||||
Kurento project has no obligations in relation to accepting contributions
|
||||
from third parties.
|
||||
* The Kurento project leaders have the right of asking for further
|
||||
explanations, tests or validations of any code contributed to the community
|
||||
before it being incorporated into the Kurento code-base. You must be ready to
|
||||
addressing all these kind of concerns before having your code approved.
|
||||
|
||||
Support
|
||||
-------
|
||||
|
||||
The Kurento project provides community support through the [Kurento Public
|
||||
Mailing List] and through [StackOverflow] using the tags *kurento* and
|
||||
*fiware-kurento*.
|
||||
|
||||
Before asking for support, please read first the [Kurento Netiquette Guidelines]
|
||||
|
||||
[documentation]: http://www.kurento.org/documentation
|
||||
[FIWARE]: http://www.fiware.org
|
||||
[GitHub Kurento bugtracker]: https://github.com/Kurento/bugtracker/issues
|
||||
[GitHub Kurento Group]: https://github.com/kurento
|
||||
[kurentoms]: http://twitter.com/kurentoms
|
||||
[Kurento]: http://kurento.org
|
||||
[Kurento Blog]: http://www.kurento.org/blog
|
||||
[Kurento FIWARE Catalog Entry]: http://catalogue.fiware.org/enablers/stream-oriented-kurento
|
||||
[Kurento Netiquette Guidelines]: http://www.kurento.org/blog/kurento-netiquette-guidelines
|
||||
[Kurento Public Mailing list]: https://groups.google.com/forum/#!forum/kurento
|
||||
[KurentoImage]: https://secure.gravatar.com/avatar/21a2a12c56b2a91c8918d5779f1778bf?s=120
|
||||
[Apache 2.0 License]: http://www.apache.org/licenses/LICENSE-2.0
|
||||
[NUBOMEDIA]: http://www.nubomedia.eu
|
||||
[StackOverflow]: http://stackoverflow.com/search?q=kurento
|
||||
[Read-the-docs]: http://read-the-docs.readthedocs.org/
|
||||
[readthedocs.org]: http://kurento.readthedocs.org/
|
||||
[Open API specification]: http://kurento.github.io/doc-kurento/
|
||||
[apiary.io]: http://docs.streamoriented.apiary.io/
|
|
@ -0,0 +1,119 @@
|
|||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>org.openvidu</groupId>
|
||||
<artifactId>openvidu</artifactId>
|
||||
<version>6.6.1-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>openvidu-client-js</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>Kurento Room Client JS</name>
|
||||
<description>
|
||||
Kurento Room JS library for the client-side
|
||||
</description>
|
||||
<url>http://www.kurento.org/docs/${project.version}</url>
|
||||
|
||||
<licenses>
|
||||
<license>
|
||||
<name>Apache 2.0</name>
|
||||
<url>http://www.apache.org/licenses/LICENSE-2.0</url>
|
||||
<distribution>repo</distribution>
|
||||
</license>
|
||||
</licenses>
|
||||
|
||||
<organization>
|
||||
<name>Kurento</name>
|
||||
<url>http://www.kurento.org</url>
|
||||
</organization>
|
||||
|
||||
<scm>
|
||||
<url>${openvidu.scm.url}</url>
|
||||
<connection>scm:git:${openvidu.scm.connection}</connection>
|
||||
<developerConnection>scm:git:${openvidu.scm.connection}</developerConnection>
|
||||
<tag>develop</tag>
|
||||
</scm>
|
||||
|
||||
<developers>
|
||||
<developer>
|
||||
<id>kurento.org</id>
|
||||
<name>-kurento.org Community</name>
|
||||
<organization>Kurento.org</organization>
|
||||
<organizationUrl>http://www.kurento.org</organizationUrl>
|
||||
</developer>
|
||||
</developers>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>exec-maven-plugin</artifactId>
|
||||
<configuration>
|
||||
<mainClass>${start-class}</mainClass>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>src/main/resources</directory>
|
||||
<filtering>false</filtering>
|
||||
</resource>
|
||||
</resources>
|
||||
</build>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.kurento</groupId>
|
||||
<artifactId>kurento-utils-js</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.kurento</groupId>
|
||||
<artifactId>kurento-jsonrpc-js</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.webjars.bower</groupId>
|
||||
<artifactId>adapter.js</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.webjars.bower</groupId>
|
||||
<artifactId>EventEmitter.js</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<profiles>
|
||||
<profile>
|
||||
<id>default</id>
|
||||
<activation>
|
||||
<property>
|
||||
<name>default</name>
|
||||
<value>true</value>
|
||||
</property>
|
||||
</activation>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<configuration>
|
||||
<skipTests>true</skipTests>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-failsafe-plugin</artifactId>
|
||||
<configuration>
|
||||
<skipTests>true</skipTests>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</profile>
|
||||
</profiles>
|
||||
|
||||
</project>
|
39
openvidu-client-js/src/main/resources/static/bower_components/adapter.js/.bower.json
vendored
Normal file
39
openvidu-client-js/src/main/resources/static/bower_components/adapter.js/.bower.json
vendored
Normal file
|
@ -0,0 +1,39 @@
|
|||
{
|
||||
"name": "webrtc-adapter",
|
||||
"version": "0.2.3",
|
||||
"description": "A shim to insulate apps from WebRTC spec changes and prefix differences",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/webrtc/adapter.git"
|
||||
},
|
||||
"authors": [
|
||||
"The WebRTC project authors (http://www.webrtc.org/)"
|
||||
],
|
||||
"main": "adapter.js",
|
||||
"moduleType": [
|
||||
"globals"
|
||||
],
|
||||
"ignore": [
|
||||
"test/*"
|
||||
],
|
||||
"keywords": [
|
||||
"WebRTC",
|
||||
"PeerConnection",
|
||||
"RTCPeerConnection",
|
||||
"getUserMedia",
|
||||
"Chrome",
|
||||
"Chromium",
|
||||
"Firefox"
|
||||
],
|
||||
"license": "BSD-3-Clause",
|
||||
"homepage": "https://github.com/webrtc/adapter",
|
||||
"_release": "0.2.3",
|
||||
"_resolution": {
|
||||
"type": "version",
|
||||
"tag": "v0.2.3",
|
||||
"commit": "c51190130048443ec853f95d0a89362c4c79931a"
|
||||
},
|
||||
"_source": "git://github.com/webrtc/adapter.git",
|
||||
"_target": "*",
|
||||
"_originalSource": "adapter.js"
|
||||
}
|
3
openvidu-client-js/src/main/resources/static/bower_components/adapter.js/.gitignore
vendored
Normal file
3
openvidu-client-js/src/main/resources/static/bower_components/adapter.js/.gitignore
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
browsers/
|
||||
node_modules/
|
||||
*~
|
3
openvidu-client-js/src/main/resources/static/bower_components/adapter.js/.jscsrc
vendored
Normal file
3
openvidu-client-js/src/main/resources/static/bower_components/adapter.js/.jscsrc
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"preset": "google"
|
||||
}
|
53
openvidu-client-js/src/main/resources/static/bower_components/adapter.js/.jshintrc
vendored
Normal file
53
openvidu-client-js/src/main/resources/static/bower_components/adapter.js/.jshintrc
vendored
Normal file
|
@ -0,0 +1,53 @@
|
|||
{
|
||||
"browser": true,
|
||||
"camelcase": true,
|
||||
"curly": true,
|
||||
"devel": true,
|
||||
"eqeqeq": true,
|
||||
"forin": false,
|
||||
"globalstrict": true,
|
||||
"quotmark": "single",
|
||||
"undef": true,
|
||||
"unused": "strict",
|
||||
"globals": {
|
||||
"addExplicitTest": true,
|
||||
"addTest": true,
|
||||
"arrayAverage": true,
|
||||
"arrayMax": true,
|
||||
"arrayMin": true,
|
||||
"attachMediaStream": true,
|
||||
"attachMediaStream": true,
|
||||
"audioContext": true,
|
||||
"AudioContext": true,
|
||||
"Call": true,
|
||||
"createIceServers": true,
|
||||
"createIceServer": true,
|
||||
"createLineChart": true,
|
||||
"define": true,
|
||||
"doGetUserMedia": true,
|
||||
"expectEquals": true,
|
||||
"getUserMedia": true,
|
||||
"getUserMedia": true,
|
||||
"ga": true,
|
||||
"GumHandler": true,
|
||||
"MediaStreamTrack": true,
|
||||
"reattachMediaStream": true,
|
||||
"report": true,
|
||||
"reportBug": true,
|
||||
"reportError": true,
|
||||
"reportFatal": true,
|
||||
"reportInfo": true,
|
||||
"reportSuccess": true,
|
||||
"RTCIceCandidate": true,
|
||||
"RTCPeerConnection": true,
|
||||
"RTCSessionDescription": true,
|
||||
"setTestProgress": true,
|
||||
"setTimeoutWithProgressBar": true,
|
||||
"Ssim": true,
|
||||
"StatisticsAggregate": true,
|
||||
"testFinished": true,
|
||||
"trace": true,
|
||||
"webrtcDetectedBrowser": true,
|
||||
"webrtcDetectedVersion": true
|
||||
}
|
||||
}
|
34
openvidu-client-js/src/main/resources/static/bower_components/adapter.js/.travis.yml
vendored
Normal file
34
openvidu-client-js/src/main/resources/static/bower_components/adapter.js/.travis.yml
vendored
Normal file
|
@ -0,0 +1,34 @@
|
|||
sudo: false
|
||||
language: node_js
|
||||
node_js:
|
||||
- 0.10
|
||||
|
||||
env:
|
||||
matrix:
|
||||
- BROWSER=chrome BVER=stable
|
||||
- BROWSER=chrome BVER=beta
|
||||
- BROWSER=chrome BVER=unstable
|
||||
- BROWSER=firefox BVER=stable
|
||||
- BROWSER=firefox BVER=beta
|
||||
- BROWSER=firefox BVER=unstable
|
||||
- BROWSER=firefox BVER=esr
|
||||
|
||||
matrix:
|
||||
fast_finish: true
|
||||
|
||||
allow_failures:
|
||||
- env: BROWSER=chrome BVER=unstable
|
||||
- env: BROWSER=firefox BVER=unstable
|
||||
|
||||
before_script:
|
||||
- ./node_modules/travis-multirunner/setup.sh
|
||||
- export DISPLAY=:99.0
|
||||
- sh -e /etc/init.d/xvfb start
|
||||
|
||||
script:
|
||||
- node_modules/.bin/grunt
|
||||
- npm test
|
||||
|
||||
after_failure:
|
||||
- for file in *.log; do echo $file; echo "======================"; cat $file; done || true
|
||||
|
15
openvidu-client-js/src/main/resources/static/bower_components/adapter.js/CONTRIBUTING.md
vendored
Normal file
15
openvidu-client-js/src/main/resources/static/bower_components/adapter.js/CONTRIBUTING.md
vendored
Normal file
|
@ -0,0 +1,15 @@
|
|||
WebRTC welcomes patches/pulls for features and bug fixes.
|
||||
|
||||
For contributors external to Google, follow the instructions given in the [Google Individual Contributor License Agreement](https://cla.developers.google.com/about/google-individual).
|
||||
|
||||
In all cases, contributors must sign a contributor license agreement before a contribution can be accepted. Please complete the agreement for an [individual](https://developers.google.com/open-source/cla/individual) or a [corporation](https://developers.google.com/open-source/cla/corporate) as appropriate.
|
||||
|
||||
If you plan to add a significant component or large chunk of code, we recommend you bring this up on the [webrtc-discuss group](https://groups.google.com/forum/#!forum/discuss-webrtc) for a design discussion before writing code.
|
||||
|
||||
If appropriate, write a unit test which demonstrates that your code functions as expected. Tests are the best way to ensure that future contributors do not break your code accidentally.
|
||||
|
||||
To request a change or addition, you must [submit a pull request](https://help.github.com/categories/collaborating/).
|
||||
|
||||
WebRTC developers monitor outstanding pull requests. They may request changes to the pull request before accepting. They will also verify that a CLA has been signed.
|
||||
|
||||
The [Developer's Guide](https://bit.ly/webrtcdevguide) for this repo has more detailed information about code style, structure and validation.
|
40
openvidu-client-js/src/main/resources/static/bower_components/adapter.js/Gruntfile.js
vendored
Normal file
40
openvidu-client-js/src/main/resources/static/bower_components/adapter.js/Gruntfile.js
vendored
Normal file
|
@ -0,0 +1,40 @@
|
|||
'use strict';
|
||||
|
||||
/* For jshint: */
|
||||
/* globals module, require */
|
||||
|
||||
module.exports = function(grunt) {
|
||||
grunt.initConfig({
|
||||
pkg: grunt.file.readJSON('package.json'),
|
||||
githooks: {
|
||||
all: {
|
||||
'pre-commit': 'jshint jscs'
|
||||
}
|
||||
},
|
||||
jshint: {
|
||||
options: {
|
||||
jshintrc: '.jshintrc'
|
||||
},
|
||||
files: ['adapter.js', 'test/*.js']
|
||||
},
|
||||
jscs: {
|
||||
src: ['adapter.js', 'test/*.js'],
|
||||
options: {
|
||||
config: '.jscsrc',
|
||||
'excludeFiles': [
|
||||
]
|
||||
}
|
||||
},
|
||||
testling: {
|
||||
files: 'test/test.js'
|
||||
}
|
||||
});
|
||||
|
||||
grunt.loadNpmTasks('grunt-contrib-jshint');
|
||||
grunt.loadNpmTasks('grunt-jscs');
|
||||
grunt.loadNpmTasks('grunt-githooks');
|
||||
grunt.registerTask('verify-require', 'Verifies the script can be required in a node context', function () {
|
||||
require('./adapter');
|
||||
});
|
||||
grunt.registerTask('default', ['jshint', 'jscs', 'verify-require']);
|
||||
};
|
29
openvidu-client-js/src/main/resources/static/bower_components/adapter.js/LICENSE.md
vendored
Normal file
29
openvidu-client-js/src/main/resources/static/bower_components/adapter.js/LICENSE.md
vendored
Normal file
|
@ -0,0 +1,29 @@
|
|||
Copyright (c) 2014, The WebRTC project authors. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
|
||||
* Neither the name of Google nor the names of its contributors may
|
||||
be used to endorse or promote products derived from this software
|
||||
without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
14
openvidu-client-js/src/main/resources/static/bower_components/adapter.js/README-w3c-tests.md
vendored
Normal file
14
openvidu-client-js/src/main/resources/static/bower_components/adapter.js/README-w3c-tests.md
vendored
Normal file
|
@ -0,0 +1,14 @@
|
|||
How to use adapter with W3C tests
|
||||
---------------------------------
|
||||
|
||||
If you want to test that the adapter works with the W3C tests, execute
|
||||
the following (where TESTDIR is the root of the web-platform-tests repo):
|
||||
|
||||
- (cd $TESTDIR; git checkout master; git checkout -b some-unused-branch-name)
|
||||
- cat adapter.js > $TESTDIR/common/vendor-prefix.js
|
||||
- Run the tests according to $TESTDIR/README.md
|
||||
|
||||
WebRTC-specific tests are found in "mediacapture-streams" and "webrtc".
|
||||
With the adapter installed, the tests should run *without* vendor prefixes.
|
||||
|
||||
Note: Not all of the W3C tests are updated to be spec-conformant.
|
65
openvidu-client-js/src/main/resources/static/bower_components/adapter.js/README.md
vendored
Normal file
65
openvidu-client-js/src/main/resources/static/bower_components/adapter.js/README.md
vendored
Normal file
|
@ -0,0 +1,65 @@
|
|||
[](https://travis-ci.org/webrtc/adapter)
|
||||
|
||||
# WebRTC adapter #
|
||||
[adapter.js] is a shim to insulate apps from spec changes and prefix differences. In fact, the standards and protocols used for WebRTC implementations are highly stable, and there are only a few prefixed names. For full interop information, see [webrtc.org/web-apis/interop](http://www.webrtc.org/web-apis/interop).
|
||||
|
||||
## Install ##
|
||||
|
||||
#### Bower
|
||||
```bash
|
||||
bower install webrtc-adapter
|
||||
```
|
||||
|
||||
#### NPM
|
||||
```bash
|
||||
npm install webrtc-adapter-test
|
||||
```
|
||||
|
||||
## Inclusion on Browser ##
|
||||
|
||||
#### Bower
|
||||
```html
|
||||
<script src="bower_components/webrtc-adapter/adapter.js"></script>
|
||||
```
|
||||
|
||||
#### NPM
|
||||
Copy to desired location in your src tree or use a minify/vulcanize tool (node_modules is usually not published with the code).
|
||||
See [webrtc/samples repo](https://github.com/webrtc/samples/blob/master/package.json) as an example on how you can do this.
|
||||
|
||||
## Development ##
|
||||
Detailed information on developing in the [webrtc](https://github.com/webrtc) github repo can be found in the [WebRTC GitHub repo developer's guide](https://docs.google.com/document/d/1tn1t6LW2ffzGuYTK3366w1fhTkkzsSvHsBnOHoDfRzY/edit?pli=1#heading=h.e3366rrgmkdk).
|
||||
|
||||
This guide assumes you are running a Debian based Linux distribution (travis-multirunner currently fetches .deb browser packages).
|
||||
|
||||
#### Clone the repo in desired folder
|
||||
```bash
|
||||
git clone https://github.com/webrtc/adapter.git
|
||||
```
|
||||
|
||||
#### Install npm dependencies
|
||||
```bash
|
||||
sudo npm install
|
||||
```
|
||||
|
||||
#### Run tests
|
||||
Runs the tests in test/tests.js using testling.
|
||||
```bash
|
||||
npm test
|
||||
```
|
||||
|
||||
#### Change browser and channel/version for testing
|
||||
Chrome stable is currently installed as the default browser for the tests.
|
||||
|
||||
Currently Chrome and Firefox are supported, check [travis-multirunner](https://github.com/DamonOehlman/travis-multirunner/blob/master/) repo for updates around this.
|
||||
Firefox channels supported are stable, beta and nightly.
|
||||
Chrome channels supported on Linux are stable, beta and unstable.
|
||||
|
||||
To select a different browser and/or channel version, change environment variables BROWSER and BVER, then you can rerun the tests with the new browser.
|
||||
```bash
|
||||
export BROWSER=firefox BVER=nightly
|
||||
```
|
||||
|
||||
Alternatively you can also do it without changing environment variables.
|
||||
```bash
|
||||
BROWSER=firefox BVER=nightly npm test
|
||||
```
|
536
openvidu-client-js/src/main/resources/static/bower_components/adapter.js/adapter.js
vendored
Normal file
536
openvidu-client-js/src/main/resources/static/bower_components/adapter.js/adapter.js
vendored
Normal file
|
@ -0,0 +1,536 @@
|
|||
/*
|
||||
* Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree.
|
||||
*/
|
||||
|
||||
/* More information about these options at jshint.com/docs/options */
|
||||
/* jshint browser: true, camelcase: true, curly: true, devel: true,
|
||||
eqeqeq: true, forin: false, globalstrict: true, node: true,
|
||||
quotmark: single, undef: true, unused: strict */
|
||||
/* global mozRTCIceCandidate, mozRTCPeerConnection, Promise,
|
||||
mozRTCSessionDescription, webkitRTCPeerConnection, MediaStreamTrack */
|
||||
/* exported trace,requestUserMedia */
|
||||
|
||||
'use strict';
|
||||
|
||||
var getUserMedia = null;
|
||||
var attachMediaStream = null;
|
||||
var reattachMediaStream = null;
|
||||
var webrtcDetectedBrowser = null;
|
||||
var webrtcDetectedVersion = null;
|
||||
var webrtcMinimumVersion = null;
|
||||
var webrtcUtils = {
|
||||
log: function() {
|
||||
// suppress console.log output when being included as a module.
|
||||
if (typeof module !== 'undefined' ||
|
||||
typeof require === 'function' && typeof define === 'function') {
|
||||
return;
|
||||
}
|
||||
console.log.apply(console, arguments);
|
||||
}
|
||||
};
|
||||
|
||||
function trace(text) {
|
||||
// This function is used for logging.
|
||||
if (text[text.length - 1] === '\n') {
|
||||
text = text.substring(0, text.length - 1);
|
||||
}
|
||||
if (window.performance) {
|
||||
var now = (window.performance.now() / 1000).toFixed(3);
|
||||
webrtcUtils.log(now + ': ' + text);
|
||||
} else {
|
||||
webrtcUtils.log(text);
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof window === 'object') {
|
||||
if (window.HTMLMediaElement &&
|
||||
!('srcObject' in window.HTMLMediaElement.prototype)) {
|
||||
// Shim the srcObject property, once, when HTMLMediaElement is found.
|
||||
Object.defineProperty(window.HTMLMediaElement.prototype, 'srcObject', {
|
||||
get: function() {
|
||||
// If prefixed srcObject property exists, return it.
|
||||
// Otherwise use the shimmed property, _srcObject
|
||||
return 'mozSrcObject' in this ? this.mozSrcObject : this._srcObject;
|
||||
},
|
||||
set: function(stream) {
|
||||
if ('mozSrcObject' in this) {
|
||||
this.mozSrcObject = stream;
|
||||
} else {
|
||||
// Use _srcObject as a private property for this shim
|
||||
this._srcObject = stream;
|
||||
// TODO: revokeObjectUrl(this.src) when !stream to release resources?
|
||||
this.src = URL.createObjectURL(stream);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
// Proxy existing globals
|
||||
getUserMedia = window.navigator && window.navigator.getUserMedia;
|
||||
}
|
||||
|
||||
// Attach a media stream to an element.
|
||||
attachMediaStream = function(element, stream) {
|
||||
element.srcObject = stream;
|
||||
};
|
||||
|
||||
reattachMediaStream = function(to, from) {
|
||||
to.srcObject = from.srcObject;
|
||||
};
|
||||
|
||||
if (typeof window === 'undefined' || !window.navigator) {
|
||||
webrtcUtils.log('This does not appear to be a browser');
|
||||
webrtcDetectedBrowser = 'not a browser';
|
||||
} else if (navigator.mozGetUserMedia && window.mozRTCPeerConnection) {
|
||||
webrtcUtils.log('This appears to be Firefox');
|
||||
|
||||
webrtcDetectedBrowser = 'firefox';
|
||||
|
||||
// the detected firefox version.
|
||||
webrtcDetectedVersion =
|
||||
parseInt(navigator.userAgent.match(/Firefox\/([0-9]+)\./)[1], 10);
|
||||
|
||||
// the minimum firefox version still supported by adapter.
|
||||
webrtcMinimumVersion = 31;
|
||||
|
||||
// The RTCPeerConnection object.
|
||||
window.RTCPeerConnection = function(pcConfig, pcConstraints) {
|
||||
if (webrtcDetectedVersion < 38) {
|
||||
// .urls is not supported in FF < 38.
|
||||
// create RTCIceServers with a single url.
|
||||
if (pcConfig && pcConfig.iceServers) {
|
||||
var newIceServers = [];
|
||||
for (var i = 0; i < pcConfig.iceServers.length; i++) {
|
||||
var server = pcConfig.iceServers[i];
|
||||
if (server.hasOwnProperty('urls')) {
|
||||
for (var j = 0; j < server.urls.length; j++) {
|
||||
var newServer = {
|
||||
url: server.urls[j]
|
||||
};
|
||||
if (server.urls[j].indexOf('turn') === 0) {
|
||||
newServer.username = server.username;
|
||||
newServer.credential = server.credential;
|
||||
}
|
||||
newIceServers.push(newServer);
|
||||
}
|
||||
} else {
|
||||
newIceServers.push(pcConfig.iceServers[i]);
|
||||
}
|
||||
}
|
||||
pcConfig.iceServers = newIceServers;
|
||||
}
|
||||
}
|
||||
return new mozRTCPeerConnection(pcConfig, pcConstraints); // jscs:ignore requireCapitalizedConstructors
|
||||
};
|
||||
|
||||
// The RTCSessionDescription object.
|
||||
window.RTCSessionDescription = mozRTCSessionDescription;
|
||||
|
||||
// The RTCIceCandidate object.
|
||||
window.RTCIceCandidate = mozRTCIceCandidate;
|
||||
|
||||
// getUserMedia constraints shim.
|
||||
getUserMedia = function(constraints, onSuccess, onError) {
|
||||
var constraintsToFF37 = function(c) {
|
||||
if (typeof c !== 'object' || c.require) {
|
||||
return c;
|
||||
}
|
||||
var require = [];
|
||||
Object.keys(c).forEach(function(key) {
|
||||
if (key === 'require' || key === 'advanced' || key === 'mediaSource') {
|
||||
return;
|
||||
}
|
||||
var r = c[key] = (typeof c[key] === 'object') ?
|
||||
c[key] : {ideal: c[key]};
|
||||
if (r.min !== undefined ||
|
||||
r.max !== undefined || r.exact !== undefined) {
|
||||
require.push(key);
|
||||
}
|
||||
if (r.exact !== undefined) {
|
||||
if (typeof r.exact === 'number') {
|
||||
r.min = r.max = r.exact;
|
||||
} else {
|
||||
c[key] = r.exact;
|
||||
}
|
||||
delete r.exact;
|
||||
}
|
||||
if (r.ideal !== undefined) {
|
||||
c.advanced = c.advanced || [];
|
||||
var oc = {};
|
||||
if (typeof r.ideal === 'number') {
|
||||
oc[key] = {min: r.ideal, max: r.ideal};
|
||||
} else {
|
||||
oc[key] = r.ideal;
|
||||
}
|
||||
c.advanced.push(oc);
|
||||
delete r.ideal;
|
||||
if (!Object.keys(r).length) {
|
||||
delete c[key];
|
||||
}
|
||||
}
|
||||
});
|
||||
if (require.length) {
|
||||
c.require = require;
|
||||
}
|
||||
return c;
|
||||
};
|
||||
if (webrtcDetectedVersion < 38) {
|
||||
webrtcUtils.log('spec: ' + JSON.stringify(constraints));
|
||||
if (constraints.audio) {
|
||||
constraints.audio = constraintsToFF37(constraints.audio);
|
||||
}
|
||||
if (constraints.video) {
|
||||
constraints.video = constraintsToFF37(constraints.video);
|
||||
}
|
||||
webrtcUtils.log('ff37: ' + JSON.stringify(constraints));
|
||||
}
|
||||
return navigator.mozGetUserMedia(constraints, onSuccess, onError);
|
||||
};
|
||||
|
||||
navigator.getUserMedia = getUserMedia;
|
||||
|
||||
// Shim for mediaDevices on older versions.
|
||||
if (!navigator.mediaDevices) {
|
||||
navigator.mediaDevices = {getUserMedia: requestUserMedia,
|
||||
addEventListener: function() { },
|
||||
removeEventListener: function() { }
|
||||
};
|
||||
}
|
||||
navigator.mediaDevices.enumerateDevices =
|
||||
navigator.mediaDevices.enumerateDevices || function() {
|
||||
return new Promise(function(resolve) {
|
||||
var infos = [
|
||||
{kind: 'audioinput', deviceId: 'default', label: '', groupId: ''},
|
||||
{kind: 'videoinput', deviceId: 'default', label: '', groupId: ''}
|
||||
];
|
||||
resolve(infos);
|
||||
});
|
||||
};
|
||||
|
||||
if (webrtcDetectedVersion < 41) {
|
||||
// Work around http://bugzil.la/1169665
|
||||
var orgEnumerateDevices =
|
||||
navigator.mediaDevices.enumerateDevices.bind(navigator.mediaDevices);
|
||||
navigator.mediaDevices.enumerateDevices = function() {
|
||||
return orgEnumerateDevices().catch(function(e) {
|
||||
if (e.name === 'NotFoundError') {
|
||||
return [];
|
||||
}
|
||||
throw e;
|
||||
});
|
||||
};
|
||||
}
|
||||
} else if (navigator.webkitGetUserMedia && !!window.chrome) {
|
||||
webrtcUtils.log('This appears to be Chrome');
|
||||
|
||||
webrtcDetectedBrowser = 'chrome';
|
||||
|
||||
// the detected chrome version.
|
||||
webrtcDetectedVersion =
|
||||
parseInt(navigator.userAgent.match(/Chrom(e|ium)\/([0-9]+)\./)[2], 10);
|
||||
|
||||
// the minimum chrome version still supported by adapter.
|
||||
webrtcMinimumVersion = 38;
|
||||
|
||||
// The RTCPeerConnection object.
|
||||
window.RTCPeerConnection = function(pcConfig, pcConstraints) {
|
||||
// Translate iceTransportPolicy to iceTransports,
|
||||
// see https://code.google.com/p/webrtc/issues/detail?id=4869
|
||||
if (pcConfig && pcConfig.iceTransportPolicy) {
|
||||
pcConfig.iceTransports = pcConfig.iceTransportPolicy;
|
||||
}
|
||||
|
||||
var pc = new webkitRTCPeerConnection(pcConfig, pcConstraints); // jscs:ignore requireCapitalizedConstructors
|
||||
var origGetStats = pc.getStats.bind(pc);
|
||||
pc.getStats = function(selector, successCallback, errorCallback) { // jshint ignore: line
|
||||
var self = this;
|
||||
var args = arguments;
|
||||
|
||||
// If selector is a function then we are in the old style stats so just
|
||||
// pass back the original getStats format to avoid breaking old users.
|
||||
if (arguments.length > 0 && typeof selector === 'function') {
|
||||
return origGetStats(selector, successCallback);
|
||||
}
|
||||
|
||||
var fixChromeStats = function(response) {
|
||||
var standardReport = {};
|
||||
var reports = response.result();
|
||||
reports.forEach(function(report) {
|
||||
var standardStats = {
|
||||
id: report.id,
|
||||
timestamp: report.timestamp,
|
||||
type: report.type
|
||||
};
|
||||
report.names().forEach(function(name) {
|
||||
standardStats[name] = report.stat(name);
|
||||
});
|
||||
standardReport[standardStats.id] = standardStats;
|
||||
});
|
||||
|
||||
return standardReport;
|
||||
};
|
||||
|
||||
if (arguments.length >= 2) {
|
||||
var successCallbackWrapper = function(response) {
|
||||
args[1](fixChromeStats(response));
|
||||
};
|
||||
|
||||
return origGetStats.apply(this, [successCallbackWrapper, arguments[0]]);
|
||||
}
|
||||
|
||||
// promise-support
|
||||
return new Promise(function(resolve, reject) {
|
||||
if (args.length === 1 && selector === null) {
|
||||
origGetStats.apply(self, [
|
||||
function(response) {
|
||||
resolve.apply(null, [fixChromeStats(response)]);
|
||||
}, reject]);
|
||||
} else {
|
||||
origGetStats.apply(self, [resolve, reject]);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
return pc;
|
||||
};
|
||||
|
||||
// add promise support
|
||||
['createOffer', 'createAnswer'].forEach(function(method) {
|
||||
var nativeMethod = webkitRTCPeerConnection.prototype[method];
|
||||
webkitRTCPeerConnection.prototype[method] = function() {
|
||||
var self = this;
|
||||
if (arguments.length < 1 || (arguments.length === 1 &&
|
||||
typeof(arguments[0]) === 'object')) {
|
||||
var opts = arguments.length === 1 ? arguments[0] : undefined;
|
||||
return new Promise(function(resolve, reject) {
|
||||
nativeMethod.apply(self, [resolve, reject, opts]);
|
||||
});
|
||||
} else {
|
||||
return nativeMethod.apply(this, arguments);
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
['setLocalDescription', 'setRemoteDescription',
|
||||
'addIceCandidate'].forEach(function(method) {
|
||||
var nativeMethod = webkitRTCPeerConnection.prototype[method];
|
||||
webkitRTCPeerConnection.prototype[method] = function() {
|
||||
var args = arguments;
|
||||
var self = this;
|
||||
return new Promise(function(resolve, reject) {
|
||||
nativeMethod.apply(self, [args[0],
|
||||
function() {
|
||||
resolve();
|
||||
if (args.length >= 2) {
|
||||
args[1].apply(null, []);
|
||||
}
|
||||
},
|
||||
function(err) {
|
||||
reject(err);
|
||||
if (args.length >= 3) {
|
||||
args[2].apply(null, [err]);
|
||||
}
|
||||
}]
|
||||
);
|
||||
});
|
||||
};
|
||||
});
|
||||
|
||||
// getUserMedia constraints shim.
|
||||
var constraintsToChrome = function(c) {
|
||||
if (typeof c !== 'object' || c.mandatory || c.optional) {
|
||||
return c;
|
||||
}
|
||||
var cc = {};
|
||||
Object.keys(c).forEach(function(key) {
|
||||
if (key === 'require' || key === 'advanced' || key === 'mediaSource') {
|
||||
return;
|
||||
}
|
||||
var r = (typeof c[key] === 'object') ? c[key] : {ideal: c[key]};
|
||||
if (r.exact !== undefined && typeof r.exact === 'number') {
|
||||
r.min = r.max = r.exact;
|
||||
}
|
||||
var oldname = function(prefix, name) {
|
||||
if (prefix) {
|
||||
return prefix + name.charAt(0).toUpperCase() + name.slice(1);
|
||||
}
|
||||
return (name === 'deviceId') ? 'sourceId' : name;
|
||||
};
|
||||
if (r.ideal !== undefined) {
|
||||
cc.optional = cc.optional || [];
|
||||
var oc = {};
|
||||
if (typeof r.ideal === 'number') {
|
||||
oc[oldname('min', key)] = r.ideal;
|
||||
cc.optional.push(oc);
|
||||
oc = {};
|
||||
oc[oldname('max', key)] = r.ideal;
|
||||
cc.optional.push(oc);
|
||||
} else {
|
||||
oc[oldname('', key)] = r.ideal;
|
||||
cc.optional.push(oc);
|
||||
}
|
||||
}
|
||||
if (r.exact !== undefined && typeof r.exact !== 'number') {
|
||||
cc.mandatory = cc.mandatory || {};
|
||||
cc.mandatory[oldname('', key)] = r.exact;
|
||||
} else {
|
||||
['min', 'max'].forEach(function(mix) {
|
||||
if (r[mix] !== undefined) {
|
||||
cc.mandatory = cc.mandatory || {};
|
||||
cc.mandatory[oldname(mix, key)] = r[mix];
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
if (c.advanced) {
|
||||
cc.optional = (cc.optional || []).concat(c.advanced);
|
||||
}
|
||||
return cc;
|
||||
};
|
||||
|
||||
getUserMedia = function(constraints, onSuccess, onError) {
|
||||
if (constraints.audio) {
|
||||
constraints.audio = constraintsToChrome(constraints.audio);
|
||||
}
|
||||
if (constraints.video) {
|
||||
constraints.video = constraintsToChrome(constraints.video);
|
||||
}
|
||||
webrtcUtils.log('chrome: ' + JSON.stringify(constraints));
|
||||
return navigator.webkitGetUserMedia(constraints, onSuccess, onError);
|
||||
};
|
||||
navigator.getUserMedia = getUserMedia;
|
||||
|
||||
if (!navigator.mediaDevices) {
|
||||
navigator.mediaDevices = {getUserMedia: requestUserMedia,
|
||||
enumerateDevices: function() {
|
||||
return new Promise(function(resolve) {
|
||||
var kinds = {audio: 'audioinput', video: 'videoinput'};
|
||||
return MediaStreamTrack.getSources(function(devices) {
|
||||
resolve(devices.map(function(device) {
|
||||
return {label: device.label,
|
||||
kind: kinds[device.kind],
|
||||
deviceId: device.id,
|
||||
groupId: ''};
|
||||
}));
|
||||
});
|
||||
});
|
||||
}};
|
||||
}
|
||||
|
||||
// A shim for getUserMedia method on the mediaDevices object.
|
||||
// TODO(KaptenJansson) remove once implemented in Chrome stable.
|
||||
if (!navigator.mediaDevices.getUserMedia) {
|
||||
navigator.mediaDevices.getUserMedia = function(constraints) {
|
||||
return requestUserMedia(constraints);
|
||||
};
|
||||
} else {
|
||||
// Even though Chrome 45 has navigator.mediaDevices and a getUserMedia
|
||||
// function which returns a Promise, it does not accept spec-style
|
||||
// constraints.
|
||||
var origGetUserMedia = navigator.mediaDevices.getUserMedia.
|
||||
bind(navigator.mediaDevices);
|
||||
navigator.mediaDevices.getUserMedia = function(c) {
|
||||
webrtcUtils.log('spec: ' + JSON.stringify(c)); // whitespace for alignment
|
||||
c.audio = constraintsToChrome(c.audio);
|
||||
c.video = constraintsToChrome(c.video);
|
||||
webrtcUtils.log('chrome: ' + JSON.stringify(c));
|
||||
return origGetUserMedia(c);
|
||||
};
|
||||
}
|
||||
|
||||
// Dummy devicechange event methods.
|
||||
// TODO(KaptenJansson) remove once implemented in Chrome stable.
|
||||
if (typeof navigator.mediaDevices.addEventListener === 'undefined') {
|
||||
navigator.mediaDevices.addEventListener = function() {
|
||||
webrtcUtils.log('Dummy mediaDevices.addEventListener called.');
|
||||
};
|
||||
}
|
||||
if (typeof navigator.mediaDevices.removeEventListener === 'undefined') {
|
||||
navigator.mediaDevices.removeEventListener = function() {
|
||||
webrtcUtils.log('Dummy mediaDevices.removeEventListener called.');
|
||||
};
|
||||
}
|
||||
|
||||
// Attach a media stream to an element.
|
||||
attachMediaStream = function(element, stream) {
|
||||
if (webrtcDetectedVersion >= 43) {
|
||||
element.srcObject = stream;
|
||||
} else if (typeof element.src !== 'undefined') {
|
||||
element.src = URL.createObjectURL(stream);
|
||||
} else {
|
||||
webrtcUtils.log('Error attaching stream to element.');
|
||||
}
|
||||
};
|
||||
reattachMediaStream = function(to, from) {
|
||||
if (webrtcDetectedVersion >= 43) {
|
||||
to.srcObject = from.srcObject;
|
||||
} else {
|
||||
to.src = from.src;
|
||||
}
|
||||
};
|
||||
|
||||
} else if (navigator.mediaDevices && navigator.userAgent.match(
|
||||
/Edge\/(\d+).(\d+)$/)) {
|
||||
webrtcUtils.log('This appears to be Edge');
|
||||
webrtcDetectedBrowser = 'edge';
|
||||
|
||||
webrtcDetectedVersion =
|
||||
parseInt(navigator.userAgent.match(/Edge\/(\d+).(\d+)$/)[2], 10);
|
||||
|
||||
// the minimum version still supported by adapter.
|
||||
webrtcMinimumVersion = 12;
|
||||
} else {
|
||||
webrtcUtils.log('Browser does not appear to be WebRTC-capable');
|
||||
}
|
||||
|
||||
// Returns the result of getUserMedia as a Promise.
|
||||
function requestUserMedia(constraints) {
|
||||
return new Promise(function(resolve, reject) {
|
||||
getUserMedia(constraints, resolve, reject);
|
||||
});
|
||||
}
|
||||
|
||||
var webrtcTesting = {};
|
||||
Object.defineProperty(webrtcTesting, 'version', {
|
||||
set: function(version) {
|
||||
webrtcDetectedVersion = version;
|
||||
}
|
||||
});
|
||||
|
||||
if (typeof module !== 'undefined') {
|
||||
var RTCPeerConnection;
|
||||
if (typeof window !== 'undefined') {
|
||||
RTCPeerConnection = window.RTCPeerConnection;
|
||||
}
|
||||
module.exports = {
|
||||
RTCPeerConnection: RTCPeerConnection,
|
||||
getUserMedia: getUserMedia,
|
||||
attachMediaStream: attachMediaStream,
|
||||
reattachMediaStream: reattachMediaStream,
|
||||
webrtcDetectedBrowser: webrtcDetectedBrowser,
|
||||
webrtcDetectedVersion: webrtcDetectedVersion,
|
||||
webrtcMinimumVersion: webrtcMinimumVersion,
|
||||
webrtcTesting: webrtcTesting
|
||||
//requestUserMedia: not exposed on purpose.
|
||||
//trace: not exposed on purpose.
|
||||
};
|
||||
} else if ((typeof require === 'function') && (typeof define === 'function')) {
|
||||
// Expose objects and functions when RequireJS is doing the loading.
|
||||
define([], function() {
|
||||
return {
|
||||
RTCPeerConnection: window.RTCPeerConnection,
|
||||
getUserMedia: getUserMedia,
|
||||
attachMediaStream: attachMediaStream,
|
||||
reattachMediaStream: reattachMediaStream,
|
||||
webrtcDetectedBrowser: webrtcDetectedBrowser,
|
||||
webrtcDetectedVersion: webrtcDetectedVersion,
|
||||
webrtcMinimumVersion: webrtcMinimumVersion,
|
||||
webrtcTesting: webrtcTesting
|
||||
//requestUserMedia: not exposed on purpose.
|
||||
//trace: not exposed on purpose.
|
||||
};
|
||||
});
|
||||
}
|
29
openvidu-client-js/src/main/resources/static/bower_components/adapter.js/bower.json
vendored
Normal file
29
openvidu-client-js/src/main/resources/static/bower_components/adapter.js/bower.json
vendored
Normal file
|
@ -0,0 +1,29 @@
|
|||
{
|
||||
"name": "webrtc-adapter",
|
||||
"version": "0.2.3",
|
||||
"description": "A shim to insulate apps from WebRTC spec changes and prefix differences",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/webrtc/adapter.git"
|
||||
},
|
||||
"authors": [
|
||||
"The WebRTC project authors (http://www.webrtc.org/)"
|
||||
],
|
||||
"main": "adapter.js",
|
||||
"moduleType": [
|
||||
"globals"
|
||||
],
|
||||
"ignore": [
|
||||
"test/*"
|
||||
],
|
||||
"keywords": [
|
||||
"WebRTC",
|
||||
"PeerConnection",
|
||||
"RTCPeerConnection",
|
||||
"getUserMedia",
|
||||
"Chrome",
|
||||
"Chromium",
|
||||
"Firefox"
|
||||
],
|
||||
"license": "BSD-3-Clause"
|
||||
}
|
30
openvidu-client-js/src/main/resources/static/bower_components/adapter.js/package.json
vendored
Normal file
30
openvidu-client-js/src/main/resources/static/bower_components/adapter.js/package.json
vendored
Normal file
|
@ -0,0 +1,30 @@
|
|||
{
|
||||
"name": "webrtc-adapter-test",
|
||||
"version": "0.2.3",
|
||||
"description": "Hide browser differences in WebRTC APIs (test package name)",
|
||||
"license": "BSD-3-Clause",
|
||||
"main": "adapter.js",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/webrtc/adapter.git"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "test/run-tests"
|
||||
},
|
||||
"testling": {
|
||||
"files": "test/test.js"
|
||||
},
|
||||
"devDependencies": {
|
||||
"browserify": "^10.2.1",
|
||||
"grunt": "^0.4.5",
|
||||
"grunt-cli": ">=0.1.9",
|
||||
"grunt-contrib-jshint": "^0.11.2",
|
||||
"grunt-contrib-nodeunit": "~0.4.1",
|
||||
"grunt-contrib-uglify": "^0.9.1",
|
||||
"grunt-githooks": "^0.3.1",
|
||||
"grunt-jscs": "^2.0.0",
|
||||
"tape": "^4.0.0",
|
||||
"testling": "^1.7.1",
|
||||
"travis-multirunner": "^2.6.0"
|
||||
}
|
||||
}
|
Binary file not shown.
After Width: | Height: | Size: 9.5 KiB |
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,26 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry kind="src" output="target/classes" path="src/main/java">
|
||||
<attributes>
|
||||
<attribute name="optional" value="true"/>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="src" output="target/test-classes" path="src/test/java">
|
||||
<attributes>
|
||||
<attribute name="optional" value="true"/>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8">
|
||||
<attributes>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
|
||||
<attributes>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="output" path="target/classes"/>
|
||||
</classpath>
|
|
@ -0,0 +1 @@
|
|||
/target/
|
|
@ -0,0 +1,23 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>kurento-room-client-openvic</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.m2e.core.maven2Builder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||
<nature>org.eclipse.m2e.core.maven2Nature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
|
@ -0,0 +1,4 @@
|
|||
eclipse.preferences.version=1
|
||||
encoding//src/main/java=UTF-8
|
||||
encoding//src/test/java=UTF-8
|
||||
encoding/<project>=UTF-8
|
|
@ -0,0 +1,5 @@
|
|||
eclipse.preferences.version=1
|
||||
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
|
||||
org.eclipse.jdt.core.compiler.compliance=1.8
|
||||
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
|
||||
org.eclipse.jdt.core.compiler.source=1.8
|
|
@ -0,0 +1,4 @@
|
|||
activeProfiles=
|
||||
eclipse.preferences.version=1
|
||||
resolveWorkspaceProjects=true
|
||||
version=1
|
|
@ -0,0 +1,119 @@
|
|||
[](http://www.apache.org/licenses/LICENSE-2.0)
|
||||
[](http://doc-kurento-room.readthedocs.org/en/latest/)
|
||||
[](https://hub.docker.com/r/fiware/stream-oriented-kurento/)
|
||||
[](http://stackoverflow.com/questions/tagged/kurento)
|
||||
|
||||
[![][KurentoImage]][Kurento]
|
||||
|
||||
Copyright © 2013-2016 [Kurento]. Licensed under [Apache 2.0 License].
|
||||
|
||||
kurento-room-client
|
||||
======================
|
||||
|
||||
Kurento Room Client contains the Java client-side of group
|
||||
communications applications based on WebRTC.
|
||||
It uses WebSockets and JSON-RPC to interact with the server-side
|
||||
of the Room API.
|
||||
|
||||
What is Kurento
|
||||
---------------
|
||||
|
||||
Kurento is an open source software project providing a platform suitable
|
||||
for creating modular applications with advanced real-time communication
|
||||
capabilities. For knowing more about Kurento, please visit the Kurento
|
||||
project website: http://www.kurento.org.
|
||||
|
||||
Kurento is part of [FIWARE]. For further information on the relationship of
|
||||
FIWARE and Kurento check the [Kurento FIWARE Catalog Entry]
|
||||
|
||||
Kurento is part of the [NUBOMEDIA] research initiative.
|
||||
|
||||
Documentation
|
||||
-------------
|
||||
|
||||
The Kurento project provides detailed [documentation] including tutorials,
|
||||
installation and development guides. A simplified version of the documentation
|
||||
can be found on [readthedocs.org]. The [Open API specification] a.k.a. Kurento
|
||||
Protocol is also available on [apiary.io].
|
||||
|
||||
Source
|
||||
------
|
||||
|
||||
Code for other Kurento projects can be found in the [GitHub Kurento Group].
|
||||
|
||||
News and Website
|
||||
----------------
|
||||
|
||||
Check the [Kurento blog]
|
||||
Follow us on Twitter @[kurentoms].
|
||||
|
||||
Issue tracker
|
||||
-------------
|
||||
|
||||
Issues and bug reports should be posted to the [GitHub Kurento bugtracker]
|
||||
|
||||
Licensing and distribution
|
||||
--------------------------
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
Contribution policy
|
||||
-------------------
|
||||
|
||||
You can contribute to the Kurento community through bug-reports, bug-fixes, new
|
||||
code or new documentation. For contributing to the Kurento community, drop a
|
||||
post to the [Kurento Public Mailing List] providing full information about your
|
||||
contribution and its value. In your contributions, you must comply with the
|
||||
following guidelines
|
||||
|
||||
* You must specify the specific contents of your contribution either through a
|
||||
detailed bug description, through a pull-request or through a patch.
|
||||
* You must specify the licensing restrictions of the code you contribute.
|
||||
* For newly created code to be incorporated in the Kurento code-base, you must
|
||||
accept Kurento to own the code copyright, so that its open source nature is
|
||||
guaranteed.
|
||||
* You must justify appropriately the need and value of your contribution. The
|
||||
Kurento project has no obligations in relation to accepting contributions
|
||||
from third parties.
|
||||
* The Kurento project leaders have the right of asking for further
|
||||
explanations, tests or validations of any code contributed to the community
|
||||
before it being incorporated into the Kurento code-base. You must be ready to
|
||||
addressing all these kind of concerns before having your code approved.
|
||||
|
||||
Support
|
||||
-------
|
||||
|
||||
The Kurento project provides community support through the [Kurento Public
|
||||
Mailing List] and through [StackOverflow] using the tags *kurento* and
|
||||
*fiware-kurento*.
|
||||
|
||||
Before asking for support, please read first the [Kurento Netiquette Guidelines]
|
||||
|
||||
[documentation]: http://www.kurento.org/documentation
|
||||
[FIWARE]: http://www.fiware.org
|
||||
[GitHub Kurento bugtracker]: https://github.com/Kurento/bugtracker/issues
|
||||
[GitHub Kurento Group]: https://github.com/kurento
|
||||
[kurentoms]: http://twitter.com/kurentoms
|
||||
[Kurento]: http://kurento.org
|
||||
[Kurento Blog]: http://www.kurento.org/blog
|
||||
[Kurento FIWARE Catalog Entry]: http://catalogue.fiware.org/enablers/stream-oriented-kurento
|
||||
[Kurento Netiquette Guidelines]: http://www.kurento.org/blog/kurento-netiquette-guidelines
|
||||
[Kurento Public Mailing list]: https://groups.google.com/forum/#!forum/kurento
|
||||
[KurentoImage]: https://secure.gravatar.com/avatar/21a2a12c56b2a91c8918d5779f1778bf?s=120
|
||||
[Apache 2.0 License]: http://www.apache.org/licenses/LICENSE-2.0
|
||||
[NUBOMEDIA]: http://www.nubomedia.eu
|
||||
[StackOverflow]: http://stackoverflow.com/search?q=kurento
|
||||
[Read-the-docs]: http://read-the-docs.readthedocs.org/
|
||||
[readthedocs.org]: http://kurento.readthedocs.org/
|
||||
[Open API specification]: http://kurento.github.io/doc-kurento/
|
||||
[apiary.io]: http://docs.streamoriented.apiary.io/
|
|
@ -0,0 +1,104 @@
|
|||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>org.openvidu</groupId>
|
||||
<artifactId>openvidu</artifactId>
|
||||
<version>6.6.1-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>openvidu-client</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>Kurento Room Client</name>
|
||||
<description>
|
||||
Kurento Room library for the client-side of Kurento Room Server
|
||||
</description>
|
||||
<url>http://www.kurento.org/docs/${project.version}</url>
|
||||
|
||||
<licenses>
|
||||
<license>
|
||||
<name>Apache 2.0</name>
|
||||
<url>http://www.apache.org/licenses/LICENSE-2.0</url>
|
||||
<distribution>repo</distribution>
|
||||
</license>
|
||||
</licenses>
|
||||
|
||||
<organization>
|
||||
<name>Kurento</name>
|
||||
<url>http://www.kurento.org</url>
|
||||
</organization>
|
||||
|
||||
<scm>
|
||||
<url>${openvidu.scm.url}</url>
|
||||
<connection>scm:git:${openvidu.scm.connection}</connection>
|
||||
<developerConnection>scm:git:${openvidu.scm.connection}</developerConnection>
|
||||
<tag>develop</tag>
|
||||
</scm>
|
||||
|
||||
<developers>
|
||||
<developer>
|
||||
<id>kurento.org</id>
|
||||
<name>-kurento.org Community</name>
|
||||
<organization>Kurento.org</organization>
|
||||
<organizationUrl>http://www.kurento.org</organizationUrl>
|
||||
</developer>
|
||||
</developers>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.kurento</groupId>
|
||||
<artifactId>kurento-jsonrpc-client</artifactId>
|
||||
</dependency>
|
||||
<!-- <dependency>
|
||||
<groupId>org.openvidu</groupId>
|
||||
<artifactId>openvidu-server</artifactId>
|
||||
</dependency>-->
|
||||
<dependency>
|
||||
<groupId>org.kurento</groupId>
|
||||
<artifactId>kurento-jsonrpc-client-jetty</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-core</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<profiles>
|
||||
<profile>
|
||||
<id>default</id>
|
||||
<activation>
|
||||
<property>
|
||||
<name>default</name>
|
||||
<value>true</value>
|
||||
</property>
|
||||
</activation>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<configuration>
|
||||
<skipTests>true</skipTests>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-failsafe-plugin</artifactId>
|
||||
<configuration>
|
||||
<skipTests>true</skipTests>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</profile>
|
||||
</profiles>
|
||||
|
||||
</project>
|
|
@ -0,0 +1,222 @@
|
|||
/*
|
||||
* (C) Copyright 2015 Kurento (http://kurento.org/)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.openvidu.client;
|
||||
|
||||
import static org.openvidu.client.internal.ProtocolElements.CUSTOMREQUEST_METHOD;
|
||||
import static org.openvidu.client.internal.ProtocolElements.JOINROOM_DATACHANNELS_PARAM;
|
||||
import static org.openvidu.client.internal.ProtocolElements.JOINROOM_METHOD;
|
||||
import static org.openvidu.client.internal.ProtocolElements.JOINROOM_PEERID_PARAM;
|
||||
import static org.openvidu.client.internal.ProtocolElements.JOINROOM_PEERSTREAMID_PARAM;
|
||||
import static org.openvidu.client.internal.ProtocolElements.JOINROOM_PEERSTREAMS_PARAM;
|
||||
import static org.openvidu.client.internal.ProtocolElements.JOINROOM_ROOM_PARAM;
|
||||
import static org.openvidu.client.internal.ProtocolElements.JOINROOM_USER_PARAM;
|
||||
import static org.openvidu.client.internal.ProtocolElements.LEAVEROOM_METHOD;
|
||||
import static org.openvidu.client.internal.ProtocolElements.ONICECANDIDATE_CANDIDATE_PARAM;
|
||||
import static org.openvidu.client.internal.ProtocolElements.ONICECANDIDATE_EPNAME_PARAM;
|
||||
import static org.openvidu.client.internal.ProtocolElements.ONICECANDIDATE_METHOD;
|
||||
import static org.openvidu.client.internal.ProtocolElements.ONICECANDIDATE_SDPMIDPARAM;
|
||||
import static org.openvidu.client.internal.ProtocolElements.ONICECANDIDATE_SDPMLINEINDEX_PARAM;
|
||||
import static org.openvidu.client.internal.ProtocolElements.PUBLISHVIDEO_DOLOOPBACK_PARAM;
|
||||
import static org.openvidu.client.internal.ProtocolElements.PUBLISHVIDEO_METHOD;
|
||||
import static org.openvidu.client.internal.ProtocolElements.PUBLISHVIDEO_SDPANSWER_PARAM;
|
||||
import static org.openvidu.client.internal.ProtocolElements.PUBLISHVIDEO_SDPOFFER_PARAM;
|
||||
import static org.openvidu.client.internal.ProtocolElements.RECEIVEVIDEO_METHOD;
|
||||
import static org.openvidu.client.internal.ProtocolElements.RECEIVEVIDEO_SDPANSWER_PARAM;
|
||||
import static org.openvidu.client.internal.ProtocolElements.RECEIVEVIDEO_SDPOFFER_PARAM;
|
||||
import static org.openvidu.client.internal.ProtocolElements.RECEIVEVIDEO_SENDER_PARAM;
|
||||
import static org.openvidu.client.internal.ProtocolElements.SENDMESSAGE_MESSAGE_PARAM;
|
||||
import static org.openvidu.client.internal.ProtocolElements.SENDMESSAGE_ROOM_METHOD;
|
||||
import static org.openvidu.client.internal.ProtocolElements.SENDMESSAGE_ROOM_PARAM;
|
||||
import static org.openvidu.client.internal.ProtocolElements.SENDMESSAGE_USER_PARAM;
|
||||
import static org.openvidu.client.internal.ProtocolElements.UNPUBLISHVIDEO_METHOD;
|
||||
import static org.openvidu.client.internal.ProtocolElements.UNSUBSCRIBEFROMVIDEO_METHOD;
|
||||
import static org.openvidu.client.internal.ProtocolElements.UNSUBSCRIBEFROMVIDEO_SENDER_PARAM;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.jetty.util.ssl.SslContextFactory;
|
||||
import org.kurento.jsonrpc.client.JsonRpcClient;
|
||||
import org.kurento.jsonrpc.client.JsonRpcClientWebSocket;
|
||||
import org.kurento.jsonrpc.client.JsonRpcWSConnectionListener;
|
||||
import org.openvidu.client.internal.JsonRoomUtils;
|
||||
import org.openvidu.client.internal.Notification;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
/**
|
||||
* Java client for the room server.
|
||||
*
|
||||
* @author <a href="mailto:rvlad@naevatec.com">Radu Tom Vlad</a>
|
||||
*/
|
||||
public class OpenViduClient {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(OpenViduClient.class);
|
||||
|
||||
private JsonRpcClient client;
|
||||
private ServerJsonRpcHandler handler;
|
||||
|
||||
public OpenViduClient(String wsUri) {
|
||||
this(new JsonRpcClientWebSocket(wsUri, new JsonRpcWSConnectionListener() {
|
||||
|
||||
@Override
|
||||
public void reconnected(boolean sameServer) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disconnected() {
|
||||
log.warn("JsonRpcWebsocket connection: Disconnected");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void connectionFailed() {
|
||||
log.warn("JsonRpcWebsocket connection: Connection failed");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void connected() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reconnecting() {
|
||||
log.warn("JsonRpcWebsocket connection: is reconnecting");
|
||||
}
|
||||
}, new SslContextFactory(true)));
|
||||
}
|
||||
|
||||
public OpenViduClient(JsonRpcClient client) {
|
||||
this.client = client;
|
||||
this.handler = new ServerJsonRpcHandler();
|
||||
this.client.setServerRequestHandler(this.handler);
|
||||
}
|
||||
|
||||
public OpenViduClient(JsonRpcClient client, ServerJsonRpcHandler handler) {
|
||||
this.client = client;
|
||||
this.handler = handler;
|
||||
this.client.setServerRequestHandler(this.handler);
|
||||
}
|
||||
|
||||
public void close() throws IOException {
|
||||
this.client.close();
|
||||
}
|
||||
|
||||
public Map<String, List<String>> joinRoom(String roomName, String userName, Boolean dataChannels)
|
||||
throws IOException {
|
||||
JsonObject params = new JsonObject();
|
||||
params.addProperty(JOINROOM_ROOM_PARAM, roomName);
|
||||
params.addProperty(JOINROOM_USER_PARAM, userName);
|
||||
if (dataChannels != null) {
|
||||
params.addProperty(JOINROOM_DATACHANNELS_PARAM, dataChannels);
|
||||
}
|
||||
JsonElement result = client.sendRequest(JOINROOM_METHOD, params);
|
||||
Map<String, List<String>> peers = new HashMap<String, List<String>>();
|
||||
JsonArray jsonPeers = JsonRoomUtils.getResponseProperty(result, "value", JsonArray.class);
|
||||
if (jsonPeers.size() > 0) {
|
||||
Iterator<JsonElement> peerIt = jsonPeers.iterator();
|
||||
while (peerIt.hasNext()) {
|
||||
JsonElement peer = peerIt.next();
|
||||
String peerId = JsonRoomUtils.getResponseProperty(peer, JOINROOM_PEERID_PARAM,
|
||||
String.class);
|
||||
List<String> streams = new ArrayList<String>();
|
||||
JsonArray jsonStreams = JsonRoomUtils.getResponseProperty(peer, JOINROOM_PEERSTREAMS_PARAM,
|
||||
JsonArray.class, true);
|
||||
if (jsonStreams != null) {
|
||||
Iterator<JsonElement> streamIt = jsonStreams.iterator();
|
||||
while (streamIt.hasNext()) {
|
||||
streams.add(JsonRoomUtils.getResponseProperty(streamIt.next(),
|
||||
JOINROOM_PEERSTREAMID_PARAM, String.class));
|
||||
}
|
||||
}
|
||||
peers.put(peerId, streams);
|
||||
}
|
||||
}
|
||||
return peers;
|
||||
}
|
||||
|
||||
public void leaveRoom() throws IOException {
|
||||
client.sendRequest(LEAVEROOM_METHOD, new JsonObject());
|
||||
}
|
||||
|
||||
public String publishVideo(String sdpOffer, boolean doLoopback) throws IOException {
|
||||
JsonObject params = new JsonObject();
|
||||
params.addProperty(PUBLISHVIDEO_SDPOFFER_PARAM, sdpOffer);
|
||||
params.addProperty(PUBLISHVIDEO_DOLOOPBACK_PARAM, doLoopback);
|
||||
JsonElement result = client.sendRequest(PUBLISHVIDEO_METHOD, params);
|
||||
return JsonRoomUtils.getResponseProperty(result, PUBLISHVIDEO_SDPANSWER_PARAM, String.class);
|
||||
}
|
||||
|
||||
public void unpublishVideo() throws IOException {
|
||||
client.sendRequest(UNPUBLISHVIDEO_METHOD, new JsonObject());
|
||||
}
|
||||
|
||||
// sender should look like 'username_streamId'
|
||||
public String receiveVideoFrom(String sender, String sdpOffer) throws IOException {
|
||||
JsonObject params = new JsonObject();
|
||||
params.addProperty(RECEIVEVIDEO_SENDER_PARAM, sender);
|
||||
params.addProperty(RECEIVEVIDEO_SDPOFFER_PARAM, sdpOffer);
|
||||
JsonElement result = client.sendRequest(RECEIVEVIDEO_METHOD, params);
|
||||
return JsonRoomUtils.getResponseProperty(result, RECEIVEVIDEO_SDPANSWER_PARAM, String.class);
|
||||
}
|
||||
|
||||
// sender should look like 'username_streamId'
|
||||
public void unsubscribeFromVideo(String sender) throws IOException {
|
||||
JsonObject params = new JsonObject();
|
||||
params.addProperty(UNSUBSCRIBEFROMVIDEO_SENDER_PARAM, sender);
|
||||
client.sendRequest(UNSUBSCRIBEFROMVIDEO_METHOD, params);
|
||||
}
|
||||
|
||||
public void onIceCandidate(String endpointName, String candidate, String sdpMid,
|
||||
int sdpMLineIndex) throws IOException {
|
||||
JsonObject params = new JsonObject();
|
||||
params.addProperty(ONICECANDIDATE_EPNAME_PARAM, endpointName);
|
||||
params.addProperty(ONICECANDIDATE_CANDIDATE_PARAM, candidate);
|
||||
params.addProperty(ONICECANDIDATE_SDPMIDPARAM, sdpMid);
|
||||
params.addProperty(ONICECANDIDATE_SDPMLINEINDEX_PARAM, sdpMLineIndex);
|
||||
client.sendRequest(ONICECANDIDATE_METHOD, params);
|
||||
}
|
||||
|
||||
public void sendMessage(String userName, String roomName, String message) throws IOException {
|
||||
JsonObject params = new JsonObject();
|
||||
params.addProperty(SENDMESSAGE_USER_PARAM, userName);
|
||||
params.addProperty(SENDMESSAGE_ROOM_PARAM, roomName);
|
||||
params.addProperty(SENDMESSAGE_MESSAGE_PARAM, message);
|
||||
client.sendRequest(SENDMESSAGE_ROOM_METHOD, params);
|
||||
}
|
||||
|
||||
public JsonElement customRequest(JsonObject customReqParams) throws IOException {
|
||||
return client.sendRequest(CUSTOMREQUEST_METHOD, customReqParams);
|
||||
}
|
||||
|
||||
/**
|
||||
* Polls the notifications list maintained by this client to obtain new events sent by server.
|
||||
* This method blocks until there is a notification to return. This is a one-time operation for
|
||||
* the returned element.
|
||||
*
|
||||
* @return a server notification object, null when interrupted while waiting
|
||||
*/
|
||||
public Notification getServerNotification() {
|
||||
return this.handler.getNotification();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,72 @@
|
|||
/*
|
||||
* (C) Copyright 2015 Kurento (http://kurento.org/)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package org.openvidu.client;
|
||||
|
||||
public class OpenViduException extends RuntimeException {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public static enum Code {
|
||||
GENERIC_ERROR_CODE(999),
|
||||
|
||||
TRANSPORT_ERROR_CODE(803), TRANSPORT_RESPONSE_ERROR_CODE(802), TRANSPORT_REQUEST_ERROR_CODE(
|
||||
801),
|
||||
|
||||
MEDIA_MUTE_ERROR_CODE(307), MEDIA_NOT_A_WEB_ENDPOINT_ERROR_CODE(
|
||||
306), MEDIA_RTP_ENDPOINT_ERROR_CODE(305), MEDIA_WEBRTC_ENDPOINT_ERROR_CODE(
|
||||
304), MEDIA_ENDPOINT_ERROR_CODE(
|
||||
303), MEDIA_SDP_ERROR_CODE(302), MEDIA_GENERIC_ERROR_CODE(301),
|
||||
|
||||
ROOM_CANNOT_BE_CREATED_ERROR_CODE(204), ROOM_CLOSED_ERROR_CODE(203), ROOM_NOT_FOUND_ERROR_CODE(
|
||||
202), ROOM_GENERIC_ERROR_CODE(201),
|
||||
|
||||
USER_NOT_STREAMING_ERROR_CODE(105), EXISTING_USER_IN_ROOM_ERROR_CODE(
|
||||
104), USER_CLOSED_ERROR_CODE(
|
||||
103), USER_NOT_FOUND_ERROR_CODE(102), USER_GENERIC_ERROR_CODE(101);
|
||||
|
||||
private int value;
|
||||
|
||||
private Code(int value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public int getValue() {
|
||||
return this.value;
|
||||
}
|
||||
}
|
||||
|
||||
private Code code = Code.GENERIC_ERROR_CODE;
|
||||
|
||||
public OpenViduException(Code code, String message) {
|
||||
super(message);
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
public Code getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public int getCodeValue() {
|
||||
return code.getValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Code: " + getCodeValue() + " " + super.toString();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,221 @@
|
|||
/*
|
||||
* (C) Copyright 2015 Kurento (http://kurento.org/)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.openvidu.client;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ArrayBlockingQueue;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
|
||||
import org.kurento.jsonrpc.DefaultJsonRpcHandler;
|
||||
import org.kurento.jsonrpc.Transaction;
|
||||
import org.kurento.jsonrpc.message.Request;
|
||||
import org.openvidu.client.internal.IceCandidate;
|
||||
import org.openvidu.client.internal.IceCandidateInfo;
|
||||
import org.openvidu.client.internal.JsonRoomUtils;
|
||||
import org.openvidu.client.internal.MediaErrorInfo;
|
||||
import org.openvidu.client.internal.Notification;
|
||||
import org.openvidu.client.internal.ParticipantEvictedInfo;
|
||||
import org.openvidu.client.internal.ParticipantJoinedInfo;
|
||||
import org.openvidu.client.internal.ParticipantLeftInfo;
|
||||
import org.openvidu.client.internal.ParticipantPublishedInfo;
|
||||
import org.openvidu.client.internal.ParticipantUnpublishedInfo;
|
||||
import org.openvidu.client.internal.ProtocolElements;
|
||||
import org.openvidu.client.internal.RoomClosedInfo;
|
||||
import org.openvidu.client.internal.SendMessageInfo;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
/**
|
||||
* Service that handles server JSON-RPC events.
|
||||
*
|
||||
* @author <a href="mailto:rvlad@naevatec.com">Radu Tom Vlad</a>
|
||||
*/
|
||||
public class ServerJsonRpcHandler extends DefaultJsonRpcHandler<JsonObject> {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(ServerJsonRpcHandler.class);
|
||||
|
||||
private BlockingQueue<Notification> notifications = new ArrayBlockingQueue<Notification>(100);
|
||||
|
||||
@Override
|
||||
public void handleRequest(Transaction transaction, Request<JsonObject> request) throws Exception {
|
||||
Notification notif = null;
|
||||
try {
|
||||
switch (request.getMethod()) {
|
||||
case ProtocolElements.ICECANDIDATE_METHOD:
|
||||
notif = iceCandidate(transaction, request);
|
||||
break;
|
||||
case ProtocolElements.MEDIAERROR_METHOD:
|
||||
notif = mediaError(transaction, request);
|
||||
break;
|
||||
case ProtocolElements.PARTICIPANTJOINED_METHOD:
|
||||
notif = participantJoined(transaction, request);
|
||||
break;
|
||||
case ProtocolElements.PARTICIPANTLEFT_METHOD:
|
||||
notif = participantLeft(transaction, request);
|
||||
break;
|
||||
case ProtocolElements.PARTICIPANTEVICTED_METHOD:
|
||||
notif = participantEvicted(transaction, request);
|
||||
break;
|
||||
case ProtocolElements.PARTICIPANTPUBLISHED_METHOD:
|
||||
notif = participantPublished(transaction, request);
|
||||
break;
|
||||
case ProtocolElements.PARTICIPANTUNPUBLISHED_METHOD:
|
||||
notif = participantUnpublished(transaction, request);
|
||||
break;
|
||||
case ProtocolElements.ROOMCLOSED_METHOD:
|
||||
notif = roomClosed(transaction, request);
|
||||
break;
|
||||
case ProtocolElements.PARTICIPANTSENDMESSAGE_METHOD:
|
||||
notif = participantSendMessage(transaction, request);
|
||||
break;
|
||||
default:
|
||||
throw new Exception("Unrecognized request " + request.getMethod());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("Exception processing request {}", request, e);
|
||||
transaction.sendError(e);
|
||||
return;
|
||||
}
|
||||
if (notif != null) {
|
||||
try {
|
||||
notifications.put(notif);
|
||||
log.debug("Enqueued notification {}", notif);
|
||||
} catch (InterruptedException e) {
|
||||
log.warn("Interrupted when enqueuing notification {}", notif, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Notification participantSendMessage(Transaction transaction,
|
||||
Request<JsonObject> request) {
|
||||
String room = JsonRoomUtils.getRequestParam(request,
|
||||
ProtocolElements.PARTICIPANTSENDMESSAGE_ROOM_PARAM, String.class);
|
||||
String user = JsonRoomUtils.getRequestParam(request,
|
||||
ProtocolElements.PARTICIPANTSENDMESSAGE_USER_PARAM, String.class);
|
||||
String message = JsonRoomUtils.getRequestParam(request,
|
||||
ProtocolElements.PARTICIPANTSENDMESSAGE_MESSAGE_PARAM, String.class);
|
||||
SendMessageInfo eventInfo = new SendMessageInfo(room, user, message);
|
||||
log.debug("Recvd send message event {}", eventInfo);
|
||||
return eventInfo;
|
||||
}
|
||||
|
||||
private Notification roomClosed(Transaction transaction, Request<JsonObject> request) {
|
||||
String room = JsonRoomUtils.getRequestParam(request, ProtocolElements.ROOMCLOSED_ROOM_PARAM,
|
||||
String.class);
|
||||
RoomClosedInfo eventInfo = new RoomClosedInfo(room);
|
||||
log.debug("Recvd room closed event {}", eventInfo);
|
||||
return eventInfo;
|
||||
}
|
||||
|
||||
private Notification participantUnpublished(Transaction transaction,
|
||||
Request<JsonObject> request) {
|
||||
String name = JsonRoomUtils.getRequestParam(request,
|
||||
ProtocolElements.PARTICIPANTUNPUBLISHED_NAME_PARAM, String.class);
|
||||
ParticipantUnpublishedInfo eventInfo = new ParticipantUnpublishedInfo(name);
|
||||
log.debug("Recvd participant unpublished event {}", eventInfo);
|
||||
return eventInfo;
|
||||
}
|
||||
|
||||
private Notification participantPublished(Transaction transaction, Request<JsonObject> request) {
|
||||
String id = JsonRoomUtils.getRequestParam(request,
|
||||
ProtocolElements.PARTICIPANTPUBLISHED_USER_PARAM, String.class);
|
||||
JsonArray jsonStreams = JsonRoomUtils.getRequestParam(request,
|
||||
ProtocolElements.PARTICIPANTPUBLISHED_STREAMS_PARAM, JsonArray.class);
|
||||
Iterator<JsonElement> streamIt = jsonStreams.iterator();
|
||||
List<String> streams = new ArrayList<String>();
|
||||
while (streamIt.hasNext()) {
|
||||
streams.add(JsonRoomUtils.getResponseProperty(streamIt.next(),
|
||||
ProtocolElements.PARTICIPANTPUBLISHED_STREAMID_PARAM, String.class));
|
||||
}
|
||||
ParticipantPublishedInfo eventInfo = new ParticipantPublishedInfo(id, streams);
|
||||
log.debug("Recvd published event {}", eventInfo);
|
||||
return eventInfo;
|
||||
}
|
||||
|
||||
private Notification participantEvicted(Transaction transaction, Request<JsonObject> request) {
|
||||
ParticipantEvictedInfo eventInfo = new ParticipantEvictedInfo();
|
||||
log.debug("Recvd participant evicted event {}", eventInfo);
|
||||
return eventInfo;
|
||||
}
|
||||
|
||||
private Notification participantLeft(Transaction transaction, Request<JsonObject> request) {
|
||||
String name = JsonRoomUtils.getRequestParam(request,
|
||||
ProtocolElements.PARTICIPANTLEFT_NAME_PARAM, String.class);
|
||||
ParticipantLeftInfo eventInfo = new ParticipantLeftInfo(name);
|
||||
log.debug("Recvd participant left event {}", eventInfo);
|
||||
return eventInfo;
|
||||
}
|
||||
|
||||
private Notification participantJoined(Transaction transaction, Request<JsonObject> request) {
|
||||
String id = JsonRoomUtils.getRequestParam(request,
|
||||
ProtocolElements.PARTICIPANTJOINED_USER_PARAM, String.class);
|
||||
ParticipantJoinedInfo eventInfo = new ParticipantJoinedInfo(id);
|
||||
log.debug("Recvd participant joined event {}", eventInfo);
|
||||
return eventInfo;
|
||||
}
|
||||
|
||||
private Notification mediaError(Transaction transaction, Request<JsonObject> request) {
|
||||
String description = JsonRoomUtils.getRequestParam(request,
|
||||
ProtocolElements.MEDIAERROR_ERROR_PARAM, String.class);
|
||||
MediaErrorInfo eventInfo = new MediaErrorInfo(description);
|
||||
log.debug("Recvd media error event {}", eventInfo);
|
||||
return eventInfo;
|
||||
}
|
||||
|
||||
private Notification iceCandidate(Transaction transaction, Request<JsonObject> request) {
|
||||
|
||||
String candidate = JsonRoomUtils.getRequestParam(request,
|
||||
ProtocolElements.ICECANDIDATE_CANDIDATE_PARAM, String.class);
|
||||
String sdpMid = JsonRoomUtils.getRequestParam(request,
|
||||
ProtocolElements.ICECANDIDATE_SDPMID_PARAM, String.class);
|
||||
int sdpMLineIndex = JsonRoomUtils.getRequestParam(request,
|
||||
ProtocolElements.ICECANDIDATE_SDPMLINEINDEX_PARAM, Integer.class);
|
||||
|
||||
IceCandidate iceCandidate = new IceCandidate(candidate, sdpMid, sdpMLineIndex);
|
||||
|
||||
String endpoint = JsonRoomUtils.getRequestParam(request,
|
||||
ProtocolElements.ICECANDIDATE_EPNAME_PARAM, String.class);
|
||||
|
||||
IceCandidateInfo eventInfo = new IceCandidateInfo(iceCandidate, endpoint);
|
||||
log.debug("Recvd ICE candidate event {}", eventInfo);
|
||||
|
||||
return eventInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Blocks until an element is available and then returns it by removing it from the queue.
|
||||
*
|
||||
* @return a {@link Notification} from the queue, null when interrupted
|
||||
* @see BlockingQueue#take()
|
||||
*/
|
||||
public Notification getNotification() {
|
||||
try {
|
||||
Notification notif = notifications.take();
|
||||
log.debug("Dequeued notification {}", notif);
|
||||
return notif;
|
||||
} catch (InterruptedException e) {
|
||||
log.info("Interrupted while polling notifications' queue");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
package org.openvidu.client.internal;
|
||||
|
||||
public class IceCandidate {
|
||||
|
||||
private String candidate;
|
||||
private String sdpMid;
|
||||
private int sdpMLineIndex;
|
||||
|
||||
public IceCandidate(String candidate, String sdpMid, int sdpMLineIndex) {
|
||||
super();
|
||||
this.candidate = candidate;
|
||||
this.sdpMid = sdpMid;
|
||||
this.sdpMLineIndex = sdpMLineIndex;
|
||||
}
|
||||
|
||||
public String getCandidate() {
|
||||
return candidate;
|
||||
}
|
||||
|
||||
public String getSdpMid() {
|
||||
return sdpMid;
|
||||
}
|
||||
|
||||
public int getSdpMLineIndex() {
|
||||
return sdpMLineIndex;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "IceCandidate [candidate=" + candidate + ", sdpMid=" + sdpMid + ", sdpMLineIndex="
|
||||
+ sdpMLineIndex + "]";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
/*
|
||||
* (C) Copyright 2015 Kurento (http://kurento.org/)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.openvidu.client.internal;
|
||||
|
||||
/**
|
||||
* @see Notification
|
||||
*
|
||||
* @author <a href="mailto:rvlad@naevatec.com">Radu Tom Vlad</a>
|
||||
*/
|
||||
public class IceCandidateInfo extends Notification {
|
||||
|
||||
private IceCandidate iceCandidate;
|
||||
private String endpointName;
|
||||
|
||||
public IceCandidateInfo(IceCandidate iceCandidate, String endpointName) {
|
||||
super(ProtocolElements.ICECANDIDATE_METHOD);
|
||||
this.iceCandidate = iceCandidate;
|
||||
this.endpointName = endpointName;
|
||||
}
|
||||
|
||||
public IceCandidate getIceCandidate() {
|
||||
return iceCandidate;
|
||||
}
|
||||
|
||||
public void setIceCandidate(IceCandidate iceCandidate) {
|
||||
this.iceCandidate = iceCandidate;
|
||||
}
|
||||
|
||||
public String getEndpointName() {
|
||||
return endpointName;
|
||||
}
|
||||
|
||||
public void setEndpointName(String endpointName) {
|
||||
this.endpointName = endpointName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append("[");
|
||||
if (getMethod() != null) {
|
||||
builder.append("method=").append(getMethod()).append(", ");
|
||||
}
|
||||
if (endpointName != null) {
|
||||
builder.append("endpointName=").append(endpointName).append(", ");
|
||||
}
|
||||
if (iceCandidate != null) {
|
||||
builder.append("iceCandidate=[sdpMLineIndex= ").append(iceCandidate.getSdpMLineIndex())
|
||||
.append(", sdpMid=").append(iceCandidate.getSdpMid()).append(", candidate=")
|
||||
.append(iceCandidate.getCandidate()).append("]");
|
||||
}
|
||||
builder.append("]");
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,106 @@
|
|||
/*
|
||||
* (C) Copyright 2015 Kurento (http://kurento.org/)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.openvidu.client.internal;
|
||||
|
||||
import org.kurento.jsonrpc.message.Request;
|
||||
import org.openvidu.client.OpenViduException;
|
||||
import org.openvidu.client.OpenViduException.Code;
|
||||
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
/**
|
||||
* JSON tools for extracting info from request or response elements.
|
||||
*
|
||||
* @author <a href="mailto:rvlad@naevatec.com">Radu Tom Vlad</a>
|
||||
*/
|
||||
public class JsonRoomUtils {
|
||||
|
||||
public static <T> T getRequestParam(Request<JsonObject> request, String paramName, Class<T> type) {
|
||||
return getRequestParam(request, paramName, type, false);
|
||||
}
|
||||
|
||||
public static <T> T getRequestParam(Request<JsonObject> request, String paramName, Class<T> type,
|
||||
boolean allowNull) {
|
||||
JsonObject params = request.getParams();
|
||||
if (params == null) {
|
||||
if (!allowNull) {
|
||||
throw new OpenViduException(Code.TRANSPORT_REQUEST_ERROR_CODE,
|
||||
"Invalid request lacking parameter '" + paramName + "'");
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return getConverted(params.get(paramName), paramName, type, allowNull);
|
||||
}
|
||||
|
||||
public static <T> T getResponseProperty(JsonElement result, String property, Class<T> type) {
|
||||
return getResponseProperty(result, property, type, false);
|
||||
}
|
||||
|
||||
public static <T> T getResponseProperty(JsonElement result, String property, Class<T> type,
|
||||
boolean allowNull) {
|
||||
if (!(result instanceof JsonObject)) {
|
||||
throw new OpenViduException(Code.TRANSPORT_RESPONSE_ERROR_CODE,
|
||||
"Invalid response format. The response '" + result + "' should be a Json object");
|
||||
}
|
||||
return getConverted(result.getAsJsonObject().get(property), property, type, allowNull);
|
||||
}
|
||||
|
||||
public static JsonArray getResponseArray(JsonElement result) {
|
||||
if (!result.isJsonArray()) {
|
||||
throw new OpenViduException(Code.TRANSPORT_RESPONSE_ERROR_CODE,
|
||||
"Invalid response format. The response '" + result + "' should be a Json array");
|
||||
}
|
||||
return result.getAsJsonArray();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private static <T> T getConverted(JsonElement paramValue, String property, Class<T> type,
|
||||
boolean allowNull) {
|
||||
if (paramValue == null) {
|
||||
if (allowNull) {
|
||||
return null;
|
||||
} else {
|
||||
throw new OpenViduException(Code.TRANSPORT_ERROR_CODE, "Invalid method lacking parameter '"
|
||||
+ property + "'");
|
||||
}
|
||||
}
|
||||
|
||||
if (type == String.class) {
|
||||
if (paramValue.isJsonPrimitive()) {
|
||||
return (T) paramValue.getAsString();
|
||||
}
|
||||
}
|
||||
|
||||
if (type == Integer.class) {
|
||||
if (paramValue.isJsonPrimitive()) {
|
||||
return (T) Integer.valueOf(paramValue.getAsInt());
|
||||
}
|
||||
}
|
||||
|
||||
if (type == JsonArray.class) {
|
||||
if (paramValue.isJsonArray()) {
|
||||
return (T) paramValue.getAsJsonArray();
|
||||
}
|
||||
}
|
||||
|
||||
throw new OpenViduException(Code.TRANSPORT_ERROR_CODE, "Param '" + property + "' with value '"
|
||||
+ paramValue + "' is not a " + type.getName());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
* (C) Copyright 2015 Kurento (http://kurento.org/)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.openvidu.client.internal;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author <a href="mailto:rvlad@naevatec.com">Radu Tom Vlad</a>
|
||||
*
|
||||
* @see Notification
|
||||
*/
|
||||
public class MediaErrorInfo extends Notification {
|
||||
|
||||
private String description;
|
||||
|
||||
public MediaErrorInfo(String description) {
|
||||
super(ProtocolElements.MEDIAERROR_METHOD);
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append("[");
|
||||
if (getMethod() != null) {
|
||||
builder.append("method=").append(getMethod()).append(", ");
|
||||
}
|
||||
if (description != null) {
|
||||
builder.append("description=").append(description);
|
||||
}
|
||||
builder.append("]");
|
||||
return builder.toString();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,90 @@
|
|||
/*
|
||||
* (C) Copyright 2015 Kurento (http://kurento.org/)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.openvidu.client.internal;
|
||||
|
||||
/**
|
||||
* Wrapper for server events.
|
||||
*
|
||||
* @author <a href="mailto:rvlad@naevatec.com">Radu Tom Vlad</a>
|
||||
*/
|
||||
public abstract class Notification {
|
||||
|
||||
public enum Method {
|
||||
ICECANDIDATE_METHOD(ProtocolElements.ICECANDIDATE_METHOD), MEDIAERROR_METHOD(
|
||||
ProtocolElements.MEDIAERROR_METHOD), PARTICIPANTJOINED_METHOD(
|
||||
ProtocolElements.PARTICIPANTJOINED_METHOD), PARTICIPANTLEFT_METHOD(
|
||||
ProtocolElements.PARTICIPANTLEFT_METHOD), PARTICIPANTEVICTED_METHOD(
|
||||
ProtocolElements.PARTICIPANTEVICTED_METHOD), PARTICIPANTPUBLISHED_METHOD(
|
||||
ProtocolElements.PARTICIPANTPUBLISHED_METHOD), PARTICIPANTUNPUBLISHED_METHOD(
|
||||
ProtocolElements.PARTICIPANTUNPUBLISHED_METHOD), ROOMCLOSED_METHOD(
|
||||
ProtocolElements.ROOMCLOSED_METHOD), PARTICIPANTSENDMESSAGE_METHOD(
|
||||
ProtocolElements.PARTICIPANTSENDMESSAGE_METHOD);
|
||||
|
||||
private String methodValue;
|
||||
|
||||
private Method(String val) {
|
||||
this.methodValue = val;
|
||||
}
|
||||
|
||||
public String getMethodValue() {
|
||||
return methodValue;
|
||||
}
|
||||
|
||||
public static Method getFromValue(String val) {
|
||||
for (Method m : Method.values()) {
|
||||
if (m.methodValue.equals(val)) {
|
||||
return m;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getMethodValue().toString();
|
||||
}
|
||||
}
|
||||
|
||||
private Method method;
|
||||
|
||||
public Notification(Method method) {
|
||||
this.setMethod(method);
|
||||
}
|
||||
|
||||
public Notification(String methodValue) {
|
||||
this(Method.getFromValue(methodValue));
|
||||
}
|
||||
|
||||
public Method getMethod() {
|
||||
return method;
|
||||
}
|
||||
|
||||
public void setMethod(Method method) {
|
||||
this.method = method;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append("[");
|
||||
if (method != null) {
|
||||
builder.append("method=").append(method);
|
||||
}
|
||||
builder.append("]");
|
||||
return builder.toString();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* (C) Copyright 2015 Kurento (http://kurento.org/)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.openvidu.client.internal;
|
||||
|
||||
/**
|
||||
* @see Notification
|
||||
*
|
||||
* @author <a href="mailto:rvlad@naevatec.com">Radu Tom Vlad</a>
|
||||
*/
|
||||
public class ParticipantEvictedInfo extends Notification {
|
||||
|
||||
public ParticipantEvictedInfo() {
|
||||
super(ProtocolElements.PARTICIPANTEVICTED_METHOD);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
* (C) Copyright 2015 Kurento (http://kurento.org/)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.openvidu.client.internal;
|
||||
|
||||
/**
|
||||
* @see Notification
|
||||
*
|
||||
* @author <a href="mailto:rvlad@naevatec.com">Radu Tom Vlad</a>
|
||||
*/
|
||||
public class ParticipantJoinedInfo extends Notification {
|
||||
|
||||
private String id;
|
||||
|
||||
public ParticipantJoinedInfo(String id) {
|
||||
super(ProtocolElements.PARTICIPANTJOINED_METHOD);
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append("[");
|
||||
if (getMethod() != null) {
|
||||
builder.append("method=").append(getMethod()).append(", ");
|
||||
}
|
||||
if (id != null) {
|
||||
builder.append("id=").append(id);
|
||||
}
|
||||
builder.append("]");
|
||||
return builder.toString();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
* (C) Copyright 2015 Kurento (http://kurento.org/)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.openvidu.client.internal;
|
||||
|
||||
/**
|
||||
* @see Notification
|
||||
*
|
||||
* @author <a href="mailto:rvlad@naevatec.com">Radu Tom Vlad</a>
|
||||
*/
|
||||
public class ParticipantLeftInfo extends Notification {
|
||||
|
||||
private String name;
|
||||
|
||||
public ParticipantLeftInfo(String name) {
|
||||
super(ProtocolElements.PARTICIPANTLEFT_METHOD);
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append("[");
|
||||
if (getMethod() != null) {
|
||||
builder.append("method=").append(getMethod()).append(", ");
|
||||
}
|
||||
if (name != null) {
|
||||
builder.append("name=").append(name);
|
||||
}
|
||||
builder.append("]");
|
||||
return builder.toString();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
* (C) Copyright 2015 Kurento (http://kurento.org/)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.openvidu.client.internal;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @see Notification
|
||||
*
|
||||
* @author <a href="mailto:rvlad@naevatec.com">Radu Tom Vlad</a>
|
||||
*/
|
||||
public class ParticipantPublishedInfo extends Notification {
|
||||
|
||||
private String id;
|
||||
private List<String> streams;
|
||||
|
||||
public ParticipantPublishedInfo(String id, List<String> streams) {
|
||||
super(ProtocolElements.PARTICIPANTPUBLISHED_METHOD);
|
||||
this.id = id;
|
||||
this.streams = streams;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public List<String> getStreams() {
|
||||
return streams;
|
||||
}
|
||||
|
||||
public void setStreams(List<String> streams) {
|
||||
this.streams = streams;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append("[");
|
||||
if (getMethod() != null) {
|
||||
builder.append("method=").append(getMethod()).append(", ");
|
||||
}
|
||||
if (id != null) {
|
||||
builder.append("id=").append(id).append(", ");
|
||||
}
|
||||
if (streams != null) {
|
||||
builder.append("streams=").append(streams);
|
||||
}
|
||||
builder.append("]");
|
||||
return builder.toString();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
* (C) Copyright 2015 Kurento (http://kurento.org/)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.openvidu.client.internal;
|
||||
|
||||
/**
|
||||
* @see Notification
|
||||
*
|
||||
* @author <a href="mailto:rvlad@naevatec.com">Radu Tom Vlad</a>
|
||||
*/
|
||||
public class ParticipantUnpublishedInfo extends Notification {
|
||||
|
||||
private String name;
|
||||
|
||||
public ParticipantUnpublishedInfo(String name) {
|
||||
super(ProtocolElements.PARTICIPANTUNPUBLISHED_METHOD);
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append("[");
|
||||
if (getMethod() != null) {
|
||||
builder.append("method=").append(getMethod()).append(", ");
|
||||
}
|
||||
if (name != null) {
|
||||
builder.append("name=").append(name);
|
||||
}
|
||||
builder.append("]");
|
||||
return builder.toString();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,102 @@
|
|||
/*
|
||||
* (C) Copyright 2015 Kurento (http://kurento.org/)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.openvidu.client.internal;
|
||||
|
||||
/**
|
||||
* This class defines constant values of client-server messages and their parameters.
|
||||
*
|
||||
* @author <a href="mailto:rvlad@naevatec.com">Radu Tom Vlad</a>
|
||||
*/
|
||||
public class ProtocolElements {
|
||||
|
||||
// ---------------------------- CLIENT REQUESTS -----------------------
|
||||
|
||||
public static final String SENDMESSAGE_ROOM_METHOD = "sendMessage";
|
||||
public static final String SENDMESSAGE_USER_PARAM = "userMessage";
|
||||
public static final String SENDMESSAGE_ROOM_PARAM = "roomMessage";
|
||||
public static final String SENDMESSAGE_MESSAGE_PARAM = "message";
|
||||
|
||||
public static final String LEAVEROOM_METHOD = "leaveRoom";
|
||||
|
||||
public static final String JOINROOM_METHOD = "joinRoom";
|
||||
public static final String JOINROOM_USER_PARAM = "user";
|
||||
public static final String JOINROOM_ROOM_PARAM = "room";
|
||||
public static final String JOINROOM_DATACHANNELS_PARAM = "dataChannels";
|
||||
public static final String JOINROOM_PEERID_PARAM = "id";
|
||||
public static final String JOINROOM_PEERSTREAMS_PARAM = "streams";
|
||||
public static final String JOINROOM_PEERSTREAMID_PARAM = "id";
|
||||
|
||||
public static final String PUBLISHVIDEO_METHOD = "publishVideo";
|
||||
public static final String PUBLISHVIDEO_SDPOFFER_PARAM = "sdpOffer";
|
||||
public static final String PUBLISHVIDEO_DOLOOPBACK_PARAM = "doLoopback";
|
||||
public static final String PUBLISHVIDEO_SDPANSWER_PARAM = "sdpAnswer";
|
||||
|
||||
public static final String UNPUBLISHVIDEO_METHOD = "unpublishVideo";
|
||||
|
||||
public static final String RECEIVEVIDEO_METHOD = "receiveVideoFrom";
|
||||
public static final String RECEIVEVIDEO_SDPOFFER_PARAM = "sdpOffer";
|
||||
public static final String RECEIVEVIDEO_SENDER_PARAM = "sender";
|
||||
public static final String RECEIVEVIDEO_SDPANSWER_PARAM = "sdpAnswer";
|
||||
|
||||
public static final String UNSUBSCRIBEFROMVIDEO_METHOD = "unsubscribeFromVideo";
|
||||
public static final String UNSUBSCRIBEFROMVIDEO_SENDER_PARAM = "sender";
|
||||
|
||||
public static final String ONICECANDIDATE_METHOD = "onIceCandidate";
|
||||
public static final String ONICECANDIDATE_EPNAME_PARAM = "endpointName";
|
||||
public static final String ONICECANDIDATE_CANDIDATE_PARAM = "candidate";
|
||||
public static final String ONICECANDIDATE_SDPMIDPARAM = "sdpMid";
|
||||
public static final String ONICECANDIDATE_SDPMLINEINDEX_PARAM = "sdpMLineIndex";
|
||||
|
||||
public static final String CUSTOMREQUEST_METHOD = "customRequest";
|
||||
|
||||
// ---------------------------- SERVER RESPONSES & EVENTS -----------------
|
||||
|
||||
public static final String PARTICIPANTJOINED_METHOD = "participantJoined";
|
||||
public static final String PARTICIPANTJOINED_USER_PARAM = "id";
|
||||
|
||||
public static final String PARTICIPANTLEFT_METHOD = "participantLeft";
|
||||
public static final String PARTICIPANTLEFT_NAME_PARAM = "name";
|
||||
|
||||
public static final String PARTICIPANTEVICTED_METHOD = "participantEvicted";
|
||||
|
||||
public static final String PARTICIPANTPUBLISHED_METHOD = "participantPublished";
|
||||
public static final String PARTICIPANTPUBLISHED_USER_PARAM = "id";
|
||||
public static final String PARTICIPANTPUBLISHED_STREAMS_PARAM = "streams";
|
||||
public static final String PARTICIPANTPUBLISHED_STREAMID_PARAM = "id";
|
||||
|
||||
public static final String PARTICIPANTUNPUBLISHED_METHOD = "participantUnpublished";
|
||||
public static final String PARTICIPANTUNPUBLISHED_NAME_PARAM = "name";
|
||||
|
||||
public static final String PARTICIPANTSENDMESSAGE_METHOD = "sendMessage";
|
||||
public static final String PARTICIPANTSENDMESSAGE_USER_PARAM = "user";
|
||||
public static final String PARTICIPANTSENDMESSAGE_ROOM_PARAM = "room";
|
||||
public static final String PARTICIPANTSENDMESSAGE_MESSAGE_PARAM = "message";
|
||||
|
||||
public static final String ROOMCLOSED_METHOD = "roomClosed";
|
||||
public static final String ROOMCLOSED_ROOM_PARAM = "room";
|
||||
|
||||
public static final String MEDIAERROR_METHOD = "mediaError";
|
||||
public static final String MEDIAERROR_ERROR_PARAM = "error";
|
||||
|
||||
public static final String ICECANDIDATE_METHOD = "iceCandidate";
|
||||
public static final String ICECANDIDATE_EPNAME_PARAM = "endpointName";
|
||||
public static final String ICECANDIDATE_CANDIDATE_PARAM = "candidate";
|
||||
public static final String ICECANDIDATE_SDPMID_PARAM = "sdpMid";
|
||||
public static final String ICECANDIDATE_SDPMLINEINDEX_PARAM = "sdpMLineIndex";
|
||||
|
||||
public static final String CUSTOM_NOTIFICATION = "custonNotification";
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
* (C) Copyright 2015 Kurento (http://kurento.org/)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.openvidu.client.internal;
|
||||
|
||||
/**
|
||||
* @see Notification
|
||||
*
|
||||
* @author <a href="mailto:rvlad@naevatec.com">Radu Tom Vlad</a>
|
||||
*/
|
||||
public class RoomClosedInfo extends Notification {
|
||||
|
||||
private String room;
|
||||
|
||||
public RoomClosedInfo(String room) {
|
||||
super(ProtocolElements.ROOMCLOSED_METHOD);
|
||||
this.room = room;
|
||||
}
|
||||
|
||||
public String getRoom() {
|
||||
return room;
|
||||
}
|
||||
|
||||
public void setRoom(String room) {
|
||||
this.room = room;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append("[");
|
||||
if (getMethod() != null) {
|
||||
builder.append("method=").append(getMethod()).append(", ");
|
||||
}
|
||||
if (room != null) {
|
||||
builder.append("room=").append(room);
|
||||
}
|
||||
builder.append("]");
|
||||
return builder.toString();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,80 @@
|
|||
/*
|
||||
* (C) Copyright 2015 Kurento (http://kurento.org/)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.openvidu.client.internal;
|
||||
|
||||
/**
|
||||
* @see Notification
|
||||
*
|
||||
* @author <a href="mailto:rvlad@naevatec.com">Radu Tom Vlad</a>
|
||||
*/
|
||||
public class SendMessageInfo extends Notification {
|
||||
|
||||
private String room;
|
||||
private String user;
|
||||
private String message;
|
||||
|
||||
public SendMessageInfo(String room, String user, String message) {
|
||||
super(ProtocolElements.PARTICIPANTSENDMESSAGE_METHOD);
|
||||
this.room = room;
|
||||
this.user = user;
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
public String getRoom() {
|
||||
return room;
|
||||
}
|
||||
|
||||
public void setRoom(String room) {
|
||||
this.room = room;
|
||||
}
|
||||
|
||||
public String getUser() {
|
||||
return user;
|
||||
}
|
||||
|
||||
public void setUser(String user) {
|
||||
this.user = user;
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
public void setMessage(String message) {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append("[");
|
||||
if (getMethod() != null) {
|
||||
builder.append("method=").append(getMethod()).append(", ");
|
||||
}
|
||||
if (room != null) {
|
||||
builder.append("room=").append(room).append(", ");
|
||||
}
|
||||
if (user != null) {
|
||||
builder.append("user=").append(user).append(", ");
|
||||
}
|
||||
if (message != null) {
|
||||
builder.append("message=").append(message);
|
||||
}
|
||||
builder.append("]");
|
||||
return builder.toString();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,73 @@
|
|||
/*
|
||||
* (C) Copyright 2016 Kurento (http://kurento.org/)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.openvidu.client.test;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.openvidu.client.internal.ProtocolElements.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.kurento.jsonrpc.client.JsonRpcClient;
|
||||
import org.openvidu.client.OpenViduClient;
|
||||
import org.openvidu.client.ServerJsonRpcHandler;
|
||||
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
/**
|
||||
* Unit tests for the room client protocol.
|
||||
*
|
||||
* @author Radu Tom Vlad (rvlad@naevatec.com)
|
||||
* @since 6.3.1
|
||||
*/
|
||||
public class OpenViduClientTest {
|
||||
|
||||
private OpenViduClient client;
|
||||
private ServerJsonRpcHandler serverHandler;
|
||||
private JsonRpcClient jsonRpcClient;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
jsonRpcClient = mock(JsonRpcClient.class);
|
||||
serverHandler = new ServerJsonRpcHandler();
|
||||
client = new OpenViduClient(jsonRpcClient, serverHandler);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRoomJoin() throws IOException {
|
||||
JsonObject params = new JsonObject();
|
||||
params.addProperty(JOINROOM_ROOM_PARAM, "room");
|
||||
params.addProperty(JOINROOM_USER_PARAM, "user");
|
||||
|
||||
JsonObject result = new JsonObject();
|
||||
JsonArray value = new JsonArray();
|
||||
result.add("value", value);
|
||||
|
||||
Map<String, List<String>> joinResult = new HashMap<String, List<String>>();
|
||||
|
||||
when(jsonRpcClient.sendRequest(JOINROOM_METHOD, params)).thenReturn(result);
|
||||
assertThat(client.joinRoom("room", "user", null), is(joinResult));
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"directory" : "static/bower_components"
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry kind="src" output="target/classes" path="src/main/java">
|
||||
<attributes>
|
||||
<attribute name="optional" value="true"/>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources">
|
||||
<attributes>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="src" output="target/test-classes" path="src/test/java">
|
||||
<attributes>
|
||||
<attribute name="optional" value="true"/>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8">
|
||||
<attributes>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
|
||||
<attributes>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry excluding="**" kind="src" output="target/test-classes" path="src/test/resources">
|
||||
<attributes>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="output" path="target/classes"/>
|
||||
</classpath>
|
|
@ -0,0 +1 @@
|
|||
/target/
|
|
@ -0,0 +1,23 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>kurento-room-demo</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.m2e.core.maven2Builder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||
<nature>org.eclipse.m2e.core.maven2Nature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
|
@ -0,0 +1,6 @@
|
|||
eclipse.preferences.version=1
|
||||
encoding//src/main/java=UTF-8
|
||||
encoding//src/main/resources=UTF-8
|
||||
encoding//src/test/java=UTF-8
|
||||
encoding//src/test/resources=UTF-8
|
||||
encoding/<project>=UTF-8
|
|
@ -0,0 +1,5 @@
|
|||
eclipse.preferences.version=1
|
||||
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
|
||||
org.eclipse.jdt.core.compiler.compliance=1.8
|
||||
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
|
||||
org.eclipse.jdt.core.compiler.source=1.8
|
|
@ -0,0 +1,4 @@
|
|||
activeProfiles=
|
||||
eclipse.preferences.version=1
|
||||
resolveWorkspaceProjects=true
|
||||
version=1
|
|
@ -0,0 +1,202 @@
|
|||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
|
@ -0,0 +1,13 @@
|
|||
(C) Copyright 2016 Kurento (http://kurento.org)
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
|
@ -0,0 +1,125 @@
|
|||
[](http://www.apache.org/licenses/LICENSE-2.0)
|
||||
[](http://doc-kurento-room.readthedocs.org/en/latest/)
|
||||
[](https://hub.docker.com/r/fiware/stream-oriented-kurento/)
|
||||
[](http://stackoverflow.com/questions/tagged/kurento)
|
||||
|
||||
[![][KurentoImage]][Kurento]
|
||||
|
||||
Copyright © 2013-2016 [Kurento]. Licensed under [Apache 2.0 License].
|
||||
|
||||
kurento-room-demo
|
||||
=================
|
||||
|
||||
Kurento Room Demo implements the group communications with WebRTC using
|
||||
services from Kurento Room Server.
|
||||
|
||||
The client-side implementation of this demo application is an AngularJS module
|
||||
that uses the KurentoRoom.js library from the room server package.
|
||||
It also integrates the room server's Spring application for the server-side
|
||||
of the Room API. This API is made up of the Room SDK and the signaling
|
||||
component. For client-server communications the API uses JSON-RPC messages
|
||||
over WebSockets.
|
||||
|
||||
|
||||
What is Kurento
|
||||
---------------
|
||||
|
||||
Kurento is an open source software project providing a platform suitable
|
||||
for creating modular applications with advanced real-time communication
|
||||
capabilities. For knowing more about Kurento, please visit the Kurento
|
||||
project website: http://www.kurento.org.
|
||||
|
||||
Kurento is part of [FIWARE]. For further information on the relationship of
|
||||
FIWARE and Kurento check the [Kurento FIWARE Catalog Entry]
|
||||
|
||||
Kurento is part of the [NUBOMEDIA] research initiative.
|
||||
|
||||
Documentation
|
||||
-------------
|
||||
|
||||
The Kurento project provides detailed [documentation] including tutorials,
|
||||
installation and development guides. A simplified version of the documentation
|
||||
can be found on [readthedocs.org]. The [Open API specification] a.k.a. Kurento
|
||||
Protocol is also available on [apiary.io].
|
||||
|
||||
Source
|
||||
------
|
||||
|
||||
Code for other Kurento projects can be found in the [GitHub Kurento Group].
|
||||
|
||||
News and Website
|
||||
----------------
|
||||
|
||||
Check the [Kurento blog]
|
||||
Follow us on Twitter @[kurentoms].
|
||||
|
||||
Issue tracker
|
||||
-------------
|
||||
|
||||
Issues and bug reports should be posted to the [GitHub Kurento bugtracker]
|
||||
|
||||
Licensing and distribution
|
||||
--------------------------
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
Contribution policy
|
||||
-------------------
|
||||
|
||||
You can contribute to the Kurento community through bug-reports, bug-fixes, new
|
||||
code or new documentation. For contributing to the Kurento community, drop a
|
||||
post to the [Kurento Public Mailing List] providing full information about your
|
||||
contribution and its value. In your contributions, you must comply with the
|
||||
following guidelines
|
||||
|
||||
* You must specify the specific contents of your contribution either through a
|
||||
detailed bug description, through a pull-request or through a patch.
|
||||
* You must specify the licensing restrictions of the code you contribute.
|
||||
* For newly created code to be incorporated in the Kurento code-base, you must
|
||||
accept Kurento to own the code copyright, so that its open source nature is
|
||||
guaranteed.
|
||||
* You must justify appropriately the need and value of your contribution. The
|
||||
Kurento project has no obligations in relation to accepting contributions
|
||||
from third parties.
|
||||
* The Kurento project leaders have the right of asking for further
|
||||
explanations, tests or validations of any code contributed to the community
|
||||
before it being incorporated into the Kurento code-base. You must be ready to
|
||||
addressing all these kind of concerns before having your code approved.
|
||||
|
||||
Support
|
||||
-------
|
||||
|
||||
The Kurento project provides community support through the [Kurento Public
|
||||
Mailing List] and through [StackOverflow] using the tags *kurento* and
|
||||
*fiware-kurento*.
|
||||
|
||||
Before asking for support, please read first the [Kurento Netiquette Guidelines]
|
||||
|
||||
[documentation]: http://www.kurento.org/documentation
|
||||
[FIWARE]: http://www.fiware.org
|
||||
[GitHub Kurento bugtracker]: https://github.com/Kurento/bugtracker/issues
|
||||
[GitHub Kurento Group]: https://github.com/kurento
|
||||
[kurentoms]: http://twitter.com/kurentoms
|
||||
[Kurento]: http://kurento.org
|
||||
[Kurento Blog]: http://www.kurento.org/blog
|
||||
[Kurento FIWARE Catalog Entry]: http://catalogue.fiware.org/enablers/stream-oriented-kurento
|
||||
[Kurento Netiquette Guidelines]: http://www.kurento.org/blog/kurento-netiquette-guidelines
|
||||
[Kurento Public Mailing list]: https://groups.google.com/forum/#!forum/kurento
|
||||
[KurentoImage]: https://secure.gravatar.com/avatar/21a2a12c56b2a91c8918d5779f1778bf?s=120
|
||||
[Apache 2.0 License]: http://www.apache.org/licenses/LICENSE-2.0
|
||||
[NUBOMEDIA]: http://www.nubomedia.eu
|
||||
[StackOverflow]: http://stackoverflow.com/search?q=kurento
|
||||
[Read-the-docs]: http://read-the-docs.readthedocs.org/
|
||||
[readthedocs.org]: http://kurento.readthedocs.org/
|
||||
[Open API specification]: http://kurento.github.io/doc-kurento/
|
||||
[apiary.io]: http://docs.streamoriented.apiary.io/
|
|
@ -0,0 +1,35 @@
|
|||
[](http://www.apache.org/licenses/LICENSE-2.0)
|
||||
[](http://doc-kurento.readthedocs.org/en/latest/)
|
||||
[](https://hub.docker.com/r/fiware/stream-oriented-kurento/)
|
||||
[](http://stackoverflow.com/questions/tagged/kurento)
|
||||
|
||||
${project.name}
|
||||
======================
|
||||
|
||||
The ${project.name} implements multimedia group communications with WebRTC using services from
|
||||
Kurento Room Server.
|
||||
|
||||
There are complete instructions on how to deploy the demo binary:
|
||||
http://doc-kurento-room.readthedocs.org/en/current/demo_deployment.html
|
||||
|
||||
Installation instructions
|
||||
-------------------------
|
||||
|
||||
By running `sudo ./bin/install.sh`, the jar file containing the demo will be copied into
|
||||
_/var/lib/kurento_, and the startup script will be put in _/etc/init.d/${project.artifactId}_. Once
|
||||
the demo is installed, it can be managed as a regular service with
|
||||
|
||||
```
|
||||
sudo service ${project.artifactId} {start|stop|restart}
|
||||
```
|
||||
If you want to change the port, you can do so by editing the file _/etc/kurento/${project.artifactId}.properties_.
|
||||
|
||||
Quick start instructions
|
||||
------------------------
|
||||
|
||||
By running `./bin/start.sh` the jar file containing the demo will be started right away, from the
|
||||
_files/_ folder.
|
||||
|
||||
Press `Control-C` to stop its execution.
|
||||
|
||||
If you want to change the port, you can do so by editing the file _files/${project.artifactId}.properties_.
|
|
@ -0,0 +1,50 @@
|
|||
#!/bin/bash
|
||||
|
||||
# ${project.description} installer for Ubuntu >= 14.04
|
||||
if [ `id -u` -ne 0 ]; then
|
||||
echo ""
|
||||
echo "Only root can install Kurento"
|
||||
echo ""
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Installing kurento-room-sfu-demo"
|
||||
|
||||
APP_HOME=$(dirname $(dirname $(readlink -f $0)))
|
||||
APP_NAME=${project.artifactId}
|
||||
|
||||
useradd -d /var/kurento/ kurento
|
||||
|
||||
SYSTEMD=$(pidof systemd && echo "systemd" || echo "other")
|
||||
|
||||
# Install binaries
|
||||
mkdir -p /var/lib/kurento
|
||||
chown kurento /var/lib/kurento
|
||||
install -o kurento -g root $APP_HOME/lib/$APP_NAME.jar /var/lib/kurento/
|
||||
install -o kurento -g root $APP_HOME/config/$APP_NAME.conf /var/lib/kurento/
|
||||
install -o kurento -g root $APP_HOME/config/$APP_NAME.properties /var/lib/kurento/
|
||||
install -o kurento -g root $APP_HOME/support-files/keystore.jks /var/lib/kurento/
|
||||
ln -s /var/lib/kurento/$APP_NAME.jar /etc/init.d/$APP_NAME
|
||||
chmod 755 /etc/init.d/$APP_NAME
|
||||
|
||||
mkdir -p /etc/kurento/
|
||||
install -o kurento -g root $APP_HOME/config/app.conf.json /etc/kurento/$APP_NAME.conf.json
|
||||
install -o kurento -g root $APP_HOME/support-files/log4j.properties /etc/kurento/$APP_NAME-log4j.properties
|
||||
|
||||
mkdir -p /var/log/kurento
|
||||
chown kurento /var/log/kurento
|
||||
|
||||
|
||||
if [[ "$SYSTEMD" != "other" ]]; then
|
||||
install -o root -g root $APP_HOME/support-files/systemd.service /etc/systemd/system/$APP_NAME.service
|
||||
sudo systemctl daemon-reload
|
||||
# enable at startup
|
||||
[ -z "$NOENABLE" ] && systemctl enable $APP_NAME || echo "App not enabled"
|
||||
# start service
|
||||
[ -z "$NOSTART" ] && systemctl start $APP_NAME || echo "App not started"
|
||||
else
|
||||
# enable at startup
|
||||
[ -z "$NOENABLE" ] && update-rc.d $APP_NAME defaults || echo "App not enabled"
|
||||
# start service
|
||||
[ -z "$NOSTART" ] && service $APP_NAME start || echo "App not started"
|
||||
fi
|
|
@ -0,0 +1,50 @@
|
|||
{
|
||||
"kms": {
|
||||
"uris": ["ws://localhost:8888/kurento", "ws://127.0.0.1:8888/kurento"]
|
||||
},
|
||||
"app": {
|
||||
//has to accessible from the KMS in order to load filter imgs
|
||||
"uri": "https://localhost:8443/"
|
||||
},
|
||||
"kurento": {
|
||||
"client": {
|
||||
//milliseconds
|
||||
"requestTimeout": 20000
|
||||
}
|
||||
},
|
||||
"demo": {
|
||||
//marker or hat
|
||||
"filterType" : "marker",
|
||||
|
||||
//markerdetector img(s) in order of preference
|
||||
"markerUrls": {
|
||||
"0": "kurento-rect-logo.png",
|
||||
"1": "twi-logo.png"
|
||||
},
|
||||
|
||||
//mario-wings.png or wizard.png
|
||||
"hatUrl": "mario-wings.png",
|
||||
"hatCoords": {
|
||||
// mario-wings hat
|
||||
"offsetXPercent": -0.35F,
|
||||
"offsetYPercent": -1.2F,
|
||||
"widthPercent": 1.6F,
|
||||
"heightPercent": 1.6F
|
||||
|
||||
//wizard hat
|
||||
//"offsetXPercent": -0.2F,
|
||||
//"offsetYPercent": -1.35F,
|
||||
//"widthPercent": 1.5F,
|
||||
//"heightPercent": 1.5F
|
||||
},
|
||||
"loopback" : {
|
||||
"remote": true,
|
||||
//matters only when remote is true
|
||||
"andLocal": false
|
||||
},
|
||||
"authRegex": ".*",
|
||||
"kmsLimit": 1000
|
||||
},
|
||||
"updateSpeakerInterval": 1800,
|
||||
"thresholdSpeaker": -50
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
APP_NAME=${project.artifactId}
|
||||
LOG_FOLDER=/var/log/kurento
|
||||
LOG_FILENAME=boot.log
|
||||
JAVA_OPTS="-Dspring.config.location=file:/var/lib/kurento/${project.artifactId}.properties -DconfigFilePath=/etc/kurento/${project.artifactId}.conf.json -Dlogging.config=/etc/kurento/${project.artifactId}-log4j.properties -XX:+HeapDumpOnOutOfMemoryError"
|
|
@ -0,0 +1,7 @@
|
|||
server.port: 8443
|
||||
server.address: 0.0.0.0
|
||||
server.ssl.key-store: keystore.jks
|
||||
server.ssl.key-store-password: kurento
|
||||
server.ssl.keyStoreType: JKS
|
||||
server.ssl.keyAlias: kurento-selfsigned
|
||||
server.context-path: /
|
Binary file not shown.
|
@ -0,0 +1,17 @@
|
|||
log4j.rootLogger=INFO,CONSOLE
|
||||
log4j.logger.org.kurento=DEBUG
|
||||
|
||||
# Appenders
|
||||
log4j.threshold=ALL
|
||||
|
||||
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
|
||||
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
|
||||
log4j.appender.CONSOLE.layout.ConversionPattern=%d{ISO8601} %-5p %c [%t] (%F:%L) - %m%n
|
||||
|
||||
log4j.appender.file=org.apache.log4j.RollingFileAppender
|
||||
log4j.appender.file.File=${application.log.file}
|
||||
log4j.appender.file.ImmediateFlush=true
|
||||
log4j.appender.file.MaxFileSize=10MB
|
||||
log4j.appender.file.MaxBackupIndex=50
|
||||
log4j.appender.file.layout=org.apache.log4j.PatternLayout
|
||||
log4j.appender.file.layout.ConversionPattern=%d{ISO8601} %-5p [%t] %c{2} (%M(%L)) - %m%n
|
|
@ -0,0 +1,9 @@
|
|||
[Unit]
|
||||
Description=${project.description}
|
||||
|
||||
[Service]
|
||||
User=kurento
|
||||
ExecStart=/var/lib/kurento/${project.artifactId}.jar run
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
|
@ -0,0 +1,234 @@
|
|||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>org.openvidu</groupId>
|
||||
<artifactId>openvidu</artifactId>
|
||||
<version>6.6.1-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>openvidu-demo</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>Kurento Room Demo</name>
|
||||
<description>Kurento Room Demo application</description>
|
||||
<url>http://www.kurento.org/docs/${project.version}</url>
|
||||
|
||||
<licenses>
|
||||
<license>
|
||||
<name>Apache 2.0</name>
|
||||
<url>http://www.apache.org/licenses/LICENSE-2.0</url>
|
||||
<distribution>repo</distribution>
|
||||
</license>
|
||||
</licenses>
|
||||
|
||||
<organization>
|
||||
<name>Kurento</name>
|
||||
<url>http://www.kurento.org</url>
|
||||
</organization>
|
||||
|
||||
<scm>
|
||||
<url>${openvidu.scm.url}</url>
|
||||
<connection>scm:git:${openvidu.scm.connection}</connection>
|
||||
<developerConnection>scm:git:${openvidu.scm.connection}</developerConnection>
|
||||
<tag>develop</tag>
|
||||
</scm>
|
||||
|
||||
<developers>
|
||||
<developer>
|
||||
<id>kurento.org</id>
|
||||
<name>-kurento.org Community</name>
|
||||
<organization>Kurento.org</organization>
|
||||
<organizationUrl>http://www.kurento.org</organizationUrl>
|
||||
</developer>
|
||||
</developers>
|
||||
|
||||
<properties>
|
||||
<!-- Main class -->
|
||||
<start-class>org.openvidu.room.demo.KurentoRoomDemoApp</start-class>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.openvidu</groupId>
|
||||
<artifactId>openvidu-server</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-logging</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.openvidu</groupId>
|
||||
<artifactId>openvidu-client-js</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.openvidu</groupId>
|
||||
<artifactId>openvidu-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.kurento.module</groupId>
|
||||
<artifactId>markerdetector</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-log4j2</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.webjars</groupId>
|
||||
<artifactId>webjars-locator</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.webjars.bower</groupId>
|
||||
<artifactId>jquery</artifactId>
|
||||
<version>2.2.4</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.webjars</groupId>
|
||||
<artifactId>jquery-ui</artifactId>
|
||||
<version>1.11.4</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.webjars.bower</groupId>
|
||||
<artifactId>angular</artifactId>
|
||||
<version>1.5.7</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.webjars.bower</groupId>
|
||||
<artifactId>angular-route</artifactId>
|
||||
<version>1.5.7</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.webjars.bower</groupId>
|
||||
<artifactId>angular-fullscreen</artifactId>
|
||||
<version>1.0.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.webjars.bower</groupId>
|
||||
<artifactId>material-design-iconic-font</artifactId>
|
||||
<version>1.1.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.webjars.bower</groupId>
|
||||
<artifactId>lumx</artifactId>
|
||||
<version>0.2.50</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.webjars.bower</groupId>
|
||||
<artifactId>angular-clipboard</artifactId>
|
||||
<version>1.4.2</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<!-- Filtering resources (${label}) -->
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>src/main/resources</directory>
|
||||
<filtering>false</filtering>
|
||||
</resource>
|
||||
<resource>
|
||||
<directory>src/main/resources</directory>
|
||||
<filtering>true</filtering>
|
||||
<includes>
|
||||
<include>banner.txt</include>
|
||||
</includes>
|
||||
</resource>
|
||||
</resources>
|
||||
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
<configuration>
|
||||
<mainClass>${start-class}</mainClass>
|
||||
<layout>ZIP</layout>
|
||||
<executable>true</executable>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>repackage</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
|
||||
<!-- Call to bower install when compiling -->
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>exec-maven-plugin</artifactId>
|
||||
<configuration>
|
||||
<mainClass>${start-class}</mainClass>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-assembly-plugin</artifactId>
|
||||
<configuration>
|
||||
<descriptor>src/assembly/bin.xml</descriptor>
|
||||
<finalName>${project.artifactId}-${project.version}</finalName>
|
||||
<appendAssemblyId>false</appendAssemblyId>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>single</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-antrun-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<configuration>
|
||||
<tasks>
|
||||
<copy
|
||||
file="${project.build.directory}/target/${project.artifactId}-${project.version}-bin.zip"
|
||||
tofile="${project.build.directory}/target/${project.artifactId}-${project.version}.zip" />
|
||||
</tasks>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<profiles>
|
||||
<profile>
|
||||
<id>default</id>
|
||||
<activation>
|
||||
<activeByDefault>true</activeByDefault>
|
||||
</activation>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<configuration>
|
||||
<skipTests>true</skipTests>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-failsafe-plugin</artifactId>
|
||||
<configuration>
|
||||
<skipTests>true</skipTests>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</profile>
|
||||
<profile>
|
||||
<id>integration</id>
|
||||
</profile>
|
||||
</profiles>
|
||||
</project>
|
|
@ -0,0 +1,50 @@
|
|||
<assembly
|
||||
xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
|
||||
<id>bin</id>
|
||||
<formats>
|
||||
<format>zip</format>
|
||||
</formats>
|
||||
<includeBaseDirectory>false</includeBaseDirectory>
|
||||
|
||||
<files>
|
||||
<file>
|
||||
<source>target/${project.artifactId}-${project.version}.jar</source>
|
||||
<outputDirectory>lib</outputDirectory>
|
||||
<destName>${project.artifactId}.jar</destName>
|
||||
</file>
|
||||
<file>
|
||||
<source>package/config/application.conf</source>
|
||||
<outputDirectory></outputDirectory>
|
||||
<destName>config/${project.artifactId}.conf</destName>
|
||||
<filtered>true</filtered>
|
||||
</file>
|
||||
<file>
|
||||
<source>package/config/application.properties</source>
|
||||
<outputDirectory></outputDirectory>
|
||||
<destName>config/${project.artifactId}.properties</destName>
|
||||
<filtered>true</filtered>
|
||||
</file>
|
||||
<file>
|
||||
<source>package/support-files/keystore.jks</source>
|
||||
<outputDirectory></outputDirectory>
|
||||
<destName>support-files/keystore.jks</destName>
|
||||
<filtered>false</filtered>
|
||||
</file>
|
||||
</files>
|
||||
|
||||
<fileSets>
|
||||
<fileSet>
|
||||
<directory>package</directory>
|
||||
<outputDirectory></outputDirectory>
|
||||
<excludes>
|
||||
<exclude>config/application.conf</exclude>
|
||||
<exclude>config/application.properties</exclude>
|
||||
<exclude>support-files/keystore.jks</exclude>
|
||||
</excludes>
|
||||
<filtered>true</filtered>
|
||||
</fileSet>
|
||||
</fileSets>
|
||||
</assembly>
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
* (C) Copyright 2015 Kurento (http://kurento.org/)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.openvidu.demo;
|
||||
|
||||
class ClientConfig {
|
||||
private boolean loopbackRemote;
|
||||
private boolean loopbackAndLocal;
|
||||
private String filterRequestParam;
|
||||
|
||||
public boolean isLoopbackRemote() {
|
||||
return loopbackRemote;
|
||||
}
|
||||
|
||||
public void setLoopbackRemote(boolean loopbackRemote) {
|
||||
this.loopbackRemote = loopbackRemote;
|
||||
}
|
||||
|
||||
public boolean isLoopbackAndLocal() {
|
||||
return loopbackAndLocal;
|
||||
}
|
||||
|
||||
public void setLoopbackAndLocal(boolean loopbackAndLocal) {
|
||||
this.loopbackAndLocal = loopbackAndLocal;
|
||||
}
|
||||
|
||||
public String getFilterRequestParam() {
|
||||
return filterRequestParam;
|
||||
}
|
||||
|
||||
public void setFilterRequestParam(String filterRequestParam) {
|
||||
this.filterRequestParam = filterRequestParam;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append("Loopback [remote=").append(loopbackRemote).append(", andLocal=")
|
||||
.append(loopbackAndLocal).append("], filterRequestParam=").append(filterRequestParam);
|
||||
return builder.toString();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,90 @@
|
|||
/*
|
||||
* (C) Copyright 2016 Kurento (http://kurento.org/)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
package org.openvidu.demo;
|
||||
|
||||
import org.kurento.commons.PropertiesManager;
|
||||
import org.openvidu.client.OpenViduException;
|
||||
import org.openvidu.server.core.NotificationRoomManager;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.ResponseStatus;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
/**
|
||||
* Rest controller for the room demo app.
|
||||
*
|
||||
* @author Radu Tom Vlad (rvlad@naevatec.com)
|
||||
* @since 6.0.0
|
||||
*/
|
||||
@RestController
|
||||
public class DemoController {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(DemoController.class);
|
||||
|
||||
private final static boolean DEMO_LOOPBACK_REMOTE = PropertiesManager
|
||||
.getProperty("demo.loopback.remote", false);
|
||||
private final static boolean DEMO_LOOPBACK_AND_LOCAL = PropertiesManager
|
||||
.getProperty("demo.loopback.andLocal", false);
|
||||
|
||||
private static ClientConfig config;
|
||||
|
||||
static {
|
||||
config = new ClientConfig();
|
||||
config.setLoopbackRemote(DEMO_LOOPBACK_REMOTE);
|
||||
config.setLoopbackAndLocal(DEMO_LOOPBACK_AND_LOCAL);
|
||||
config.setFilterRequestParam(
|
||||
KmsFilterType.parseType(OpenViduSampleApp.DEMO_FILTER_TYPE).getCustomRequestParam());
|
||||
log.info("Set client config: {}", config);
|
||||
}
|
||||
|
||||
@Autowired
|
||||
private NotificationRoomManager roomManager;
|
||||
|
||||
@ResponseStatus(value = HttpStatus.NOT_FOUND)
|
||||
public class ResourceNotFoundException extends RuntimeException {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public ResourceNotFoundException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
}
|
||||
|
||||
@RequestMapping("/close")
|
||||
public void closeRoom(@RequestParam("room") String room) {
|
||||
log.warn("Trying to close the room '{}'", room);
|
||||
if (!roomManager.getRooms().contains(room)) {
|
||||
log.warn("Unable to close room '{}', not found.", room);
|
||||
throw new ResourceNotFoundException("Room '" + room + "' not found");
|
||||
}
|
||||
try {
|
||||
roomManager.closeRoom(room);
|
||||
} catch (OpenViduException e) {
|
||||
log.warn("Error closing room {}", room, e);
|
||||
throw new ResourceNotFoundException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@RequestMapping("/getClientConfig")
|
||||
public ClientConfig clientConfig() {
|
||||
log.debug("Sending client config {}", config);
|
||||
return config;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,169 @@
|
|||
/*
|
||||
* (C) Copyright 2015 Kurento (http://kurento.org/)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.openvidu.demo;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.SortedMap;
|
||||
|
||||
import org.kurento.client.FaceOverlayFilter;
|
||||
import org.kurento.client.MediaElement;
|
||||
import org.kurento.jsonrpc.Transaction;
|
||||
import org.kurento.jsonrpc.message.Request;
|
||||
import org.openvidu.server.core.NotificationRoomManager;
|
||||
import org.openvidu.server.core.api.pojo.ParticipantRequest;
|
||||
import org.openvidu.server.rpc.JsonRpcUserControl;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
/**
|
||||
* User control that applies a media filter when publishing video.
|
||||
*
|
||||
* @author Radu Tom Vlad (rvlad@naevatec.com)
|
||||
*/
|
||||
public class DemoJsonRpcUserControl extends JsonRpcUserControl {
|
||||
|
||||
private static final String SESSION_ATTRIBUTE_FILTER = "customFilter";
|
||||
private static final String MARKER_ID = "markerFilterId";
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(DemoJsonRpcUserControl.class);
|
||||
|
||||
private KmsFilterType filterType = KmsFilterType.HAT;
|
||||
|
||||
private String hatUrl;
|
||||
private float offsetXPercent;
|
||||
private float offsetYPercent;
|
||||
private float widthPercent;
|
||||
private float heightPercent;
|
||||
|
||||
private SortedMap<Integer, String> markerUrls;
|
||||
|
||||
public DemoJsonRpcUserControl(NotificationRoomManager roomManager) {
|
||||
super(roomManager);
|
||||
}
|
||||
|
||||
public void setFilterType(KmsFilterType type) {
|
||||
this.filterType = type;
|
||||
}
|
||||
|
||||
public void setHatUrl(String hatUrl) {
|
||||
this.hatUrl = hatUrl;
|
||||
log.info("Hat URL: {}", hatUrl);
|
||||
}
|
||||
|
||||
public void setMarkerUrls(SortedMap<Integer, String> urls) {
|
||||
this.markerUrls = urls;
|
||||
log.info("Marker URL: {}", markerUrls);
|
||||
}
|
||||
|
||||
public void setHatCoords(JsonObject hatCoords) {
|
||||
if (hatCoords.get("offsetXPercent") != null) {
|
||||
offsetXPercent = hatCoords.get("offsetXPercent").getAsFloat();
|
||||
}
|
||||
if (hatCoords.get("offsetYPercent") != null) {
|
||||
offsetYPercent = hatCoords.get("offsetYPercent").getAsFloat();
|
||||
}
|
||||
if (hatCoords.get("widthPercent") != null) {
|
||||
widthPercent = hatCoords.get("widthPercent").getAsFloat();
|
||||
}
|
||||
if (hatCoords.get("heightPercent") != null) {
|
||||
heightPercent = hatCoords.get("heightPercent").getAsFloat();
|
||||
}
|
||||
log.info("Hat coords:\n\toffsetXPercent = {}\n\toffsetYPercent = {}"
|
||||
+ "\n\twidthPercent = {}\n\theightPercent = {}", offsetXPercent, offsetYPercent,
|
||||
widthPercent, heightPercent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void customRequest(Transaction transaction, Request<JsonObject> request,
|
||||
ParticipantRequest participantRequest) {
|
||||
try {
|
||||
if (request.getParams() == null
|
||||
|| request.getParams().get(filterType.getCustomRequestParam()) == null) {
|
||||
throw new RuntimeException(
|
||||
"Request element '" + filterType.getCustomRequestParam() + "' is missing");
|
||||
}
|
||||
switch (filterType) {
|
||||
case MARKER:
|
||||
handleMarkerRequest(transaction, request, participantRequest);
|
||||
break;
|
||||
case HAT:
|
||||
default:
|
||||
handleHatRequest(transaction, request, participantRequest);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("Unable to handle custom request", e);
|
||||
try {
|
||||
transaction.sendError(e);
|
||||
} catch (IOException e1) {
|
||||
log.warn("Unable to send error response", e1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void handleHatRequest(Transaction transaction, Request<JsonObject> request,
|
||||
ParticipantRequest participantRequest) throws IOException {
|
||||
boolean filterOn = request.getParams().get(filterType.getCustomRequestParam()).getAsBoolean();
|
||||
String pid = participantRequest.getParticipantId();
|
||||
if (filterOn) {
|
||||
if (transaction.getSession().getAttributes().containsKey(SESSION_ATTRIBUTE_FILTER)) {
|
||||
throw new RuntimeException(filterType + " filter already on");
|
||||
}
|
||||
log.info("Applying {} filter to session {}", filterType, pid);
|
||||
|
||||
FaceOverlayFilter filter =
|
||||
new FaceOverlayFilter.Builder(roomManager.getPipeline(pid)).build();
|
||||
filter.setOverlayedImage(this.hatUrl, this.offsetXPercent, this.offsetYPercent,
|
||||
this.widthPercent, this.heightPercent);
|
||||
|
||||
addFilter(transaction, pid, filter);
|
||||
} else {
|
||||
removeFilter(transaction, pid);
|
||||
}
|
||||
transaction.sendResponse(new JsonObject());
|
||||
}
|
||||
|
||||
private void handleMarkerRequest(final Transaction transaction, Request<JsonObject> request,
|
||||
ParticipantRequest participantRequest) throws IOException {
|
||||
Integer currentUrlIndex =
|
||||
request.getParams().get(filterType.getCustomRequestParam()).getAsInt();
|
||||
String pid = participantRequest.getParticipantId();
|
||||
|
||||
roomManager.updateFilter(roomManager.getRoomManager().getRoomName(pid), MARKER_ID);
|
||||
|
||||
JsonObject result = new JsonObject();
|
||||
// TODO: Change RPC to remove next index requirement
|
||||
// result.addProperty(filterType.getCustomRequestParam(), 0);
|
||||
transaction.sendResponse(result);
|
||||
}
|
||||
|
||||
private void addFilter(Transaction transaction, String pid, MediaElement filter) {
|
||||
roomManager.addMediaElement(pid, filter);
|
||||
transaction.getSession().getAttributes().put(SESSION_ATTRIBUTE_FILTER, filter);
|
||||
}
|
||||
|
||||
private void removeFilter(Transaction transaction, String pid) {
|
||||
if (!transaction.getSession().getAttributes().containsKey(SESSION_ATTRIBUTE_FILTER)) {
|
||||
throw new RuntimeException("This user has no " + filterType + " filter yet");
|
||||
}
|
||||
log.info("Removing {} filter from session {}", filterType, pid);
|
||||
roomManager.removeMediaElement(pid,
|
||||
(MediaElement) transaction.getSession().getAttributes().get(SESSION_ATTRIBUTE_FILTER));
|
||||
transaction.getSession().getAttributes().remove(SESSION_ATTRIBUTE_FILTER);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,121 @@
|
|||
package org.openvidu.demo;
|
||||
|
||||
import java.util.SortedMap;
|
||||
|
||||
import org.kurento.client.Continuation;
|
||||
import org.kurento.client.Filter;
|
||||
import org.kurento.module.markerdetector.ArMarkerdetector;
|
||||
import org.openvidu.client.internal.ProtocolElements;
|
||||
import org.openvidu.server.core.api.UserNotificationService;
|
||||
import org.openvidu.server.core.internal.DefaultNotificationRoomHandler;
|
||||
import org.openvidu.server.core.internal.Participant;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
public class DemoNotificationRoomHandler extends DefaultNotificationRoomHandler {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(DemoNotificationRoomHandler.class);
|
||||
private SortedMap<Integer, String> markerUrls;
|
||||
|
||||
private UserNotificationService notifService;
|
||||
|
||||
public DemoNotificationRoomHandler(UserNotificationService notifService) {
|
||||
super(notifService);
|
||||
|
||||
this.notifService = notifService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateFilter(String roomName, Participant participant, String filterId,
|
||||
String state) {
|
||||
Integer newState = -1;
|
||||
|
||||
if (state != null) {
|
||||
newState = Integer.parseInt(state);
|
||||
}
|
||||
|
||||
String url = markerUrls.get(newState);
|
||||
|
||||
JsonObject notificationParams = new JsonObject();
|
||||
notificationParams.addProperty("MarkerFilterState", newState);
|
||||
|
||||
notifService.sendNotification(participant.getId(), ProtocolElements.CUSTOM_NOTIFICATION,
|
||||
notificationParams);
|
||||
|
||||
ArMarkerdetector newFilter;
|
||||
Filter filter = participant.getFilterElement(filterId);
|
||||
|
||||
if (filter == null) {
|
||||
newFilter = new ArMarkerdetector.Builder(participant.getPipeline()).build();
|
||||
log.info("New {} filter for participant {}", filterId, participant.getId());
|
||||
participant.addFilterElement(filterId, newFilter);
|
||||
} else {
|
||||
log.info("Reusing {} filter in participant {}", filterId, participant.getId());
|
||||
newFilter = (ArMarkerdetector) filter;
|
||||
}
|
||||
|
||||
if (url != null) {
|
||||
newFilter.setOverlayImage(url, new Continuation<Void>() {
|
||||
@Override
|
||||
public void onSuccess(Void result) throws Exception {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(Throwable cause) throws Exception {
|
||||
|
||||
}
|
||||
});
|
||||
newFilter.setOverlayScale(1.0F, new Continuation<Void>() {
|
||||
@Override
|
||||
public void onSuccess(Void result) throws Exception {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(Throwable cause) throws Exception {
|
||||
|
||||
}
|
||||
});
|
||||
} else {
|
||||
newFilter.setOverlayScale(0.0001F, new Continuation<Void>() {
|
||||
@Override
|
||||
public void onSuccess(Void result) throws Exception {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(Throwable cause) throws Exception {
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getNextFilterState(String filterId, String oldState) {
|
||||
Integer currentUrlIndex;
|
||||
|
||||
if (oldState == null) {
|
||||
currentUrlIndex = -1;
|
||||
} else {
|
||||
currentUrlIndex = Integer.parseInt(oldState);
|
||||
}
|
||||
|
||||
Integer nextIndex = -1; // disable filter
|
||||
|
||||
if (currentUrlIndex < markerUrls.firstKey()) {
|
||||
nextIndex = markerUrls.firstKey(); // enable filter using first URL
|
||||
} else if (currentUrlIndex < markerUrls.lastKey()) {
|
||||
nextIndex = markerUrls.tailMap(currentUrlIndex + 1).firstKey();
|
||||
}
|
||||
|
||||
return nextIndex.toString();
|
||||
}
|
||||
|
||||
public void setMarkerUrls(SortedMap<Integer, String> markerUrls) {
|
||||
this.markerUrls = markerUrls;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,128 @@
|
|||
/*
|
||||
* (C) Copyright 2015 Kurento (http://kurento.org/)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.openvidu.demo;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.kurento.client.KurentoClient;
|
||||
import org.kurento.jsonrpc.Session;
|
||||
import org.openvidu.client.OpenViduException;
|
||||
import org.openvidu.server.core.internal.DefaultKurentoClientSessionInfo;
|
||||
import org.openvidu.server.kms.Kms;
|
||||
import org.openvidu.server.kms.KmsManager;
|
||||
import org.openvidu.server.kms.MaxWebRtcLoadManager;
|
||||
import org.openvidu.server.rpc.JsonRpcNotificationService;
|
||||
import org.openvidu.server.rpc.ParticipantSession;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
/**
|
||||
* KMS manager for the room demo app.
|
||||
*
|
||||
* @author Radu Tom Vlad (rvlad@naevatec.com)
|
||||
* @since 6.0.0
|
||||
*/
|
||||
public class FixedNKmsManager extends KmsManager {
|
||||
private static final Logger log = LoggerFactory.getLogger(FixedNKmsManager.class);
|
||||
|
||||
private String authRegex;
|
||||
private static Pattern authPattern = null;
|
||||
|
||||
@Autowired
|
||||
private JsonRpcNotificationService notificationService;
|
||||
|
||||
public FixedNKmsManager(List<String> kmsWsUri) {
|
||||
for (String uri : kmsWsUri) {
|
||||
this.addKms(new Kms(KurentoClient.create(uri), uri));
|
||||
}
|
||||
}
|
||||
|
||||
public FixedNKmsManager(List<String> kmsWsUri, int kmsLoadLimit) {
|
||||
for (String uri : kmsWsUri) {
|
||||
Kms kms = new Kms(KurentoClient.create(uri), uri);
|
||||
kms.setLoadManager(new MaxWebRtcLoadManager(kmsLoadLimit));
|
||||
this.addKms(kms);
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void setAuthRegex(String regex) {
|
||||
this.authRegex = regex != null ? regex.trim() : null;
|
||||
if (authRegex != null && !authRegex.isEmpty()) {
|
||||
authPattern = Pattern.compile(authRegex, Pattern.UNICODE_CASE | Pattern.CASE_INSENSITIVE);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized Kms getKms(DefaultKurentoClientSessionInfo sessionInfo) {
|
||||
String userName = null;
|
||||
String participantId = sessionInfo.getParticipantId();
|
||||
Session session = notificationService.getSession(participantId);
|
||||
if (session != null) {
|
||||
Object sessionValue = session.getAttributes().get(ParticipantSession.SESSION_KEY);
|
||||
if (sessionValue != null) {
|
||||
ParticipantSession participantSession = (ParticipantSession) sessionValue;
|
||||
userName = participantSession.getParticipantName();
|
||||
}
|
||||
}
|
||||
if (userName == null) {
|
||||
log.warn("Unable to find user name in session {}", participantId);
|
||||
throw new OpenViduException(OpenViduException.Code.ROOM_CANNOT_BE_CREATED_ERROR_CODE,
|
||||
"Not enough information");
|
||||
}
|
||||
if (!canCreateRoom(userName)) {
|
||||
throw new OpenViduException(OpenViduException.Code.ROOM_CANNOT_BE_CREATED_ERROR_CODE,
|
||||
"User cannot create a new room");
|
||||
}
|
||||
Kms kms = null;
|
||||
String type = "";
|
||||
boolean hq = isUserHQ(userName);
|
||||
if (hq) {
|
||||
kms = getLessLoadedKms();
|
||||
} else {
|
||||
kms = getNextLessLoadedKms();
|
||||
if (!kms.allowMoreElements()) {
|
||||
kms = getLessLoadedKms();
|
||||
} else {
|
||||
type = "next ";
|
||||
}
|
||||
}
|
||||
if (!kms.allowMoreElements()) {
|
||||
log.debug(
|
||||
"Was trying Kms which has no resources left: highQ={}, " + "{}less loaded KMS, uri={}",
|
||||
hq, type, kms.getUri());
|
||||
throw new OpenViduException(OpenViduException.Code.ROOM_CANNOT_BE_CREATED_ERROR_CODE,
|
||||
"No resources left to create new room");
|
||||
}
|
||||
log.debug("Offering Kms: highQ={}, {}less loaded KMS, uri={}", hq, type, kms.getUri());
|
||||
return kms;
|
||||
}
|
||||
|
||||
private boolean isUserHQ(String userName) {
|
||||
return userName.toLowerCase().startsWith("special");
|
||||
}
|
||||
|
||||
private boolean canCreateRoom(String userName) {
|
||||
if (authPattern == null) {
|
||||
return true;
|
||||
}
|
||||
Matcher m = authPattern.matcher(userName);
|
||||
return m.matches();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* (C) Copyright 2016 Kurento (http://kurento.org/)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
package org.openvidu.demo;
|
||||
|
||||
/**
|
||||
* @author Radu Tom Vlad (radutom.vlad@gmail.com)
|
||||
* @since 6.5.1
|
||||
*/
|
||||
public enum KmsFilterType {
|
||||
HAT("hat", "hat"), MARKER("marker", "marker");
|
||||
|
||||
private String typeValue;
|
||||
private String customRequestParam;
|
||||
|
||||
private KmsFilterType(String val, String customRequestParam) {
|
||||
this.typeValue = val;
|
||||
this.customRequestParam = customRequestParam;
|
||||
}
|
||||
|
||||
public String getCustomRequestParam() {
|
||||
return customRequestParam;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param val
|
||||
* filter type String value, ignoring case
|
||||
* @return the filter type, {@link #HAT} if none found
|
||||
*/
|
||||
public static KmsFilterType parseType(String val) {
|
||||
for (KmsFilterType t : KmsFilterType.values()) {
|
||||
if (t.typeValue.equalsIgnoreCase(val)) {
|
||||
return t;
|
||||
}
|
||||
}
|
||||
return HAT;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,177 @@
|
|||
/*
|
||||
* (C) Copyright 2014 Kurento (http://kurento.org/)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.openvidu.demo;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.SortedMap;
|
||||
import java.util.TreeMap;
|
||||
|
||||
import org.kurento.commons.ConfigFileManager;
|
||||
import org.kurento.commons.PropertiesManager;
|
||||
import org.kurento.jsonrpc.JsonUtils;
|
||||
import org.openvidu.server.OpenViduServer;
|
||||
import org.openvidu.server.core.NotificationRoomManager;
|
||||
import org.openvidu.server.kms.KmsManager;
|
||||
import org.openvidu.server.rpc.JsonRpcUserControl;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
import static org.kurento.commons.PropertiesManager.getPropertyJson;
|
||||
|
||||
/**
|
||||
* Demo application for Kurento Room, extends the Room Server application class. Uses the Room
|
||||
* Client JS library for the web client, which is built with AngularJS and lumx.
|
||||
*
|
||||
* @author Micael Gallego (micael.gallego@gmail.com)
|
||||
* @author Radu Tom Vlad (rvlad@naevatec.com)
|
||||
* @since 5.0.0
|
||||
*/
|
||||
public class OpenViduSampleApp extends OpenViduServer {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(OpenViduSampleApp.class);
|
||||
|
||||
public final static String KROOMDEMO_CFG_FILENAME = "kurento-room-demo.conf.json";
|
||||
|
||||
private static JsonObject DEFAULT_HAT_COORDS = new JsonObject();
|
||||
private static JsonObject DEFAULT_MARKER_URLS = new JsonObject();
|
||||
|
||||
static {
|
||||
ConfigFileManager.loadConfigFile(KROOMDEMO_CFG_FILENAME);
|
||||
DEFAULT_HAT_COORDS.addProperty("offsetXPercent", -0.35F);
|
||||
DEFAULT_HAT_COORDS.addProperty("offsetYPercent", -1.2F);
|
||||
DEFAULT_HAT_COORDS.addProperty("widthPercent", 1.6F);
|
||||
DEFAULT_HAT_COORDS.addProperty("heightPercent", 1.6F);
|
||||
|
||||
DEFAULT_MARKER_URLS.addProperty("0", "kurento-rect-logo.png");
|
||||
}
|
||||
|
||||
private static final String IMG_FOLDER = "img/";
|
||||
|
||||
private final static String DEFAULT_APP_SERVER_URL =
|
||||
PropertiesManager.getProperty("app.uri", "https://localhost:8443");
|
||||
private final static String APP_SERVER_URL =
|
||||
System.getProperty("app.server.url", DEFAULT_APP_SERVER_URL);
|
||||
|
||||
private final Integer DEMO_KMS_NODE_LIMIT = PropertiesManager.getProperty("demo.kmsLimit", 1000);
|
||||
private final String DEMO_AUTH_REGEX = PropertiesManager.getProperty("demo.authRegex");
|
||||
|
||||
public final static String DEMO_FILTER_TYPE =
|
||||
PropertiesManager.getProperty("demo.filterType", "hat");
|
||||
|
||||
private final String DEMO_HAT_URL =
|
||||
PropertiesManager.getProperty("demo.hatUrl", "mario-wings.png");
|
||||
private final JsonObject DEMO_HAT_COORDS = PropertiesManager
|
||||
.getPropertyJson("demo.hatCoords", DEFAULT_HAT_COORDS.toString(), JsonObject.class);
|
||||
|
||||
private final JsonObject DEMO_MARKER_URLS = PropertiesManager
|
||||
.getPropertyJson("demo.markerUrls", DEFAULT_MARKER_URLS.toString(), JsonObject.class);
|
||||
|
||||
@Override
|
||||
public KmsManager kmsManager() {
|
||||
JsonArray kmsUris = getPropertyJson(OpenViduServer.KMSS_URIS_PROPERTY,
|
||||
OpenViduServer.KMSS_URIS_DEFAULT, JsonArray.class);
|
||||
List<String> kmsWsUris = JsonUtils.toStringList(kmsUris);
|
||||
|
||||
log.info("Configuring Kurento Room Server to use the following kmss: {}", kmsWsUris);
|
||||
|
||||
FixedNKmsManager fixedKmsManager = new FixedNKmsManager(kmsWsUris, DEMO_KMS_NODE_LIMIT);
|
||||
fixedKmsManager.setAuthRegex(DEMO_AUTH_REGEX);
|
||||
log.debug("Authorization regex for new rooms: {}", DEMO_AUTH_REGEX);
|
||||
return fixedKmsManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonRpcUserControl userControl() {
|
||||
DemoJsonRpcUserControl uc = new DemoJsonRpcUserControl(roomManager());
|
||||
|
||||
KmsFilterType type = KmsFilterType.parseType(DEMO_FILTER_TYPE);
|
||||
log.info("Configuring demo with filter type: {} (parsed is {})", DEMO_FILTER_TYPE, type);
|
||||
|
||||
uc.setFilterType(type);
|
||||
|
||||
switch (type) {
|
||||
case MARKER:
|
||||
SortedMap<Integer, String> sortedUrls = new TreeMap<>();
|
||||
getMarkerUrls(sortedUrls);
|
||||
uc.setMarkerUrls(sortedUrls);
|
||||
break;
|
||||
case HAT:
|
||||
default:
|
||||
uc.setHatUrl(getFullUrl(DEMO_HAT_URL));
|
||||
uc.setHatCoords(DEMO_HAT_COORDS);
|
||||
}
|
||||
|
||||
return uc;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public NotificationRoomManager roomManager() {
|
||||
DemoNotificationRoomHandler notificationRoomHandler =
|
||||
new DemoNotificationRoomHandler(notificationService());
|
||||
|
||||
KmsFilterType type = KmsFilterType.parseType(DEMO_FILTER_TYPE);
|
||||
|
||||
switch (type) {
|
||||
case MARKER:
|
||||
SortedMap<Integer, String> sortedUrls = new TreeMap<>();
|
||||
getMarkerUrls(sortedUrls);
|
||||
|
||||
notificationRoomHandler.setMarkerUrls(sortedUrls);
|
||||
break;
|
||||
default:
|
||||
}
|
||||
|
||||
return new NotificationRoomManager(notificationRoomHandler, kmsManager());
|
||||
}
|
||||
|
||||
private void getMarkerUrls(SortedMap<Integer, String> sortedUrls) {
|
||||
for (Entry<String, JsonElement> entry : DEMO_MARKER_URLS.entrySet()) {
|
||||
try {
|
||||
Integer order = Integer.parseInt(entry.getKey());
|
||||
if (order < 0) {
|
||||
throw new Exception("Illegal configuration, marker url index has to be positive");
|
||||
}
|
||||
String url = entry.getValue().getAsString();
|
||||
sortedUrls.put(order, getFullUrl(url));
|
||||
} catch (Exception e) {
|
||||
log.warn("Unable to process marker url [{}] from config file {}", entry,
|
||||
KROOMDEMO_CFG_FILENAME, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static String getFullUrl(String url) {
|
||||
if (APP_SERVER_URL.endsWith("/")) {
|
||||
return APP_SERVER_URL + IMG_FOLDER + url;
|
||||
} else {
|
||||
return APP_SERVER_URL + "/" + IMG_FOLDER + url;
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
log.info("Using /dev/urandom for secure random generation");
|
||||
System.setProperty("java.security.egd", "file:/dev/./urandom");
|
||||
SpringApplication.run(OpenViduSampleApp.class, args);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
server.port: 8443
|
||||
server.address: 0.0.0.0
|
||||
server.ssl.key-store: classpath:keystore.jks
|
||||
server.ssl.key-store-password: kurento
|
||||
server.ssl.keyStoreType: JKS
|
||||
server.ssl.keyAlias: kurento-selfsigned
|
||||
server.context-path: /
|
|
@ -0,0 +1,9 @@
|
|||
|
||||
.------------------------------------.
|
||||
| |
|
||||
| | |/ / _ _ _ ___ _ _| |_ ___ |
|
||||
| | ' < || | '_/ -_) ' \ _/ _ \ |
|
||||
| |_|\_\_,_|_| \___|_||_\__\___/ |
|
||||
| |
|
||||
'------------------------------------'
|
||||
version ${project.version}
|
Binary file not shown.
|
@ -0,0 +1,49 @@
|
|||
{
|
||||
"kms": {
|
||||
"uris": ["ws://localhost:8888/kurento", "ws://127.0.0.1:8888/kurento"]
|
||||
},
|
||||
"app": {
|
||||
//has to accessible from the KMS in order to load filter imgs
|
||||
"uri": "https://localhost:8443/"
|
||||
},
|
||||
"kurento": {
|
||||
"client": {
|
||||
//milliseconds
|
||||
"requestTimeout": 20000
|
||||
}
|
||||
},
|
||||
"demo": {
|
||||
//marker or hat
|
||||
"filterType" : "marker",
|
||||
|
||||
//markerdetector img(s) in order of preference
|
||||
"markerUrls": {
|
||||
"0": "kurento-rect-logo.png"
|
||||
},
|
||||
|
||||
//mario-wings.png or wizard.png
|
||||
"hatUrl": "mario-wings.png",
|
||||
"hatCoords": {
|
||||
// mario-wings hat
|
||||
"offsetXPercent": -0.35F,
|
||||
"offsetYPercent": -1.2F,
|
||||
"widthPercent": 1.6F,
|
||||
"heightPercent": 1.6F
|
||||
|
||||
//wizard hat
|
||||
//"offsetXPercent": -0.2F,
|
||||
//"offsetYPercent": -1.35F,
|
||||
//"widthPercent": 1.5F,
|
||||
//"heightPercent": 1.5F
|
||||
},
|
||||
"loopback" : {
|
||||
"remote": true,
|
||||
//matters only when remote is true
|
||||
"andLocal": false
|
||||
},
|
||||
"authRegex": ".*",
|
||||
"kmsLimit": 1000
|
||||
},
|
||||
"updateSpeakerInterval": 1800,
|
||||
"thresholdSpeaker": -50
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
log4j.rootLogger=WARN,CONSOLE
|
||||
log4j.logger.org.kurento=INFO
|
||||
log4j.logger.org.kurento.room=DEBUG
|
||||
|
||||
# Appenders
|
||||
log4j.threshold=ALL
|
||||
|
||||
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
|
||||
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
|
||||
log4j.appender.CONSOLE.layout.ConversionPattern=%d{HH:mm:ss,SSS} %-5p %c [%t] (%F:%L) - %m%n
|
|
@ -0,0 +1,35 @@
|
|||
var kurento_room = angular.module('kurento_room', ['ngRoute', 'FBAngular', 'lumx', 'angular-clipboard']);
|
||||
|
||||
kurento_room.config(['$routeProvider', function ($routeProvider) {
|
||||
$routeProvider
|
||||
.when('/', {
|
||||
templateUrl: 'angular/login/login.html',
|
||||
controller: 'loginController'
|
||||
})
|
||||
.when('/login', {
|
||||
templateUrl: 'angular/login/login.html',
|
||||
controller: 'loginController'
|
||||
})
|
||||
.when('/rooms/:existingRoomName', {
|
||||
templateUrl: 'angular/login/login.html',
|
||||
controller: 'loginController'
|
||||
})
|
||||
.when('/call', {
|
||||
templateUrl: 'angular/call/call.html',
|
||||
controller: 'callController',
|
||||
resolve: {
|
||||
factory: checkRouting
|
||||
}
|
||||
})
|
||||
.otherwise('/'); //redirect to login
|
||||
}]);
|
||||
|
||||
var checkRouting= function ($rootScope, $location) {
|
||||
if ($rootScope.isParticipant) {
|
||||
return true;
|
||||
} else {
|
||||
console.log('Not a participant, routing to login');
|
||||
$location.path($rootScope.contextpath + '/');
|
||||
return false;
|
||||
}
|
||||
};
|
|
@ -0,0 +1,67 @@
|
|||
|
||||
<div id="room">
|
||||
|
||||
<div id="content">
|
||||
|
||||
<div id="main-video">
|
||||
|
||||
<!--big videos-->
|
||||
|
||||
</div>
|
||||
|
||||
<div id="logo">
|
||||
<img src="img/kurento.png" />
|
||||
</div>
|
||||
|
||||
<div id="room-name">{{roomName}}</div>
|
||||
<div class="mb" align="right" style="margin: 1em; padding-bottom: 5px" id="buttonActions">
|
||||
<button class="btn btn--xl btn--fab mdi" ng-class="filterStyle" lx-ripple ng-click="applyFilter()" id="filterButton" title="Filter toggle"></button> <!--filter-->
|
||||
<button class="btn btn--xl btn--brown btn--fab mdi md-recent-actors" lx-ripple ng-click="disableMainSpeaker()" id="buttonMainSpeaker" title="Main Speaker toggle"></button> <!--disable Main Speaker-->
|
||||
<button class="btn btn--xl btn--teal btn--fab mdi md-volume-up" lx-ripple ng-click="onOffVolume()" id="buttonVolume" title="Audio toggle"></button> <!--mute audio-->
|
||||
<button class="btn btn--xl btn--grey btn--fab mdi md-videocam" lx-ripple ng-click="onOffVideocam()" id="buttonVideocam" title="Video toggle"></button> <!--mute video-->
|
||||
<button class="btn btn--xl btn--blue-grey btn--fab mdi md-not-interested" lx-ripple ng-click="disconnectStream()" id="buttonDisconnect" title="Disconnect media stream"></button> <!--unpublish or unsubscribe media-->
|
||||
<button class="btn btn--xl btn--red btn--fab mdi md-call-end " lx-ripple ng-click="leaveRoom()" id="buttonLeaveRoom" title="Leave room"></button> <!--colgar-->
|
||||
<button class="btn btn--xl btn--green btn--fab mdi md-fullscreen" lx-ripple ng-click="goFullscreen()" title="Fullscreen"></button> <!--fullscreen-->
|
||||
<button class="btn btn--xl btn--blue btn--fab mdi md-chat" lx-ripple ng-click="toggleChat()" title="Chat toggle"></button> <!--chat-->
|
||||
</div>
|
||||
|
||||
<div id="participants">
|
||||
|
||||
<!--small videos-->
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<!--CHAT-->
|
||||
|
||||
<div class="toggler" style="width: 20%;height: 100%;float: right" >
|
||||
<div id="effect" style="display:none">
|
||||
<!--head-->
|
||||
<div>
|
||||
<strong>Chat</strong>
|
||||
<button class="btn btn--s btn--blue btn--icon mdi md-close" lx-ripple ng-click="toggleChat()" id="button"></button> <!--close-->
|
||||
</div>
|
||||
|
||||
<div id="chatDiv" style="height: 30em; overflow: scroll;">
|
||||
<div id="messages">
|
||||
<ul class="list" >
|
||||
|
||||
<!--chat messages with scroll-->
|
||||
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!--message and button to send-->
|
||||
<div>
|
||||
<form>
|
||||
<lx-text-field label="Message">
|
||||
<input id="inputMessage" type="text" ng-model="message">
|
||||
</lx-text-field>
|
||||
<button type="submit" class="btn btn--m btn--green btn--raised" lx-ripple ng-click="sendMessage()">Send</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
|
@ -0,0 +1,194 @@
|
|||
/*
|
||||
* @author Micael Gallego (micael.gallego@gmail.com)
|
||||
* @author Raquel Díaz González
|
||||
*/
|
||||
|
||||
kurento_room.controller('callController', function ($scope, $window, ServiceParticipant, ServiceRoom, Fullscreen, LxNotificationService) {
|
||||
|
||||
$scope.roomName = ServiceRoom.getRoomName();
|
||||
$scope.userName = ServiceRoom.getUserName();
|
||||
$scope.participants = ServiceParticipant.getParticipants();
|
||||
$scope.kurento = ServiceRoom.getKurento();
|
||||
$scope.filter = ServiceRoom.getFilterRequestParam();
|
||||
|
||||
$scope.leaveRoom = function () {
|
||||
|
||||
ServiceRoom.closeKurento();
|
||||
|
||||
ServiceParticipant.removeParticipants();
|
||||
|
||||
//redirect to login
|
||||
$window.location.href = '#/login';
|
||||
};
|
||||
|
||||
window.onbeforeunload = function () {
|
||||
//not necessary if not connected
|
||||
if (ServiceParticipant.isConnected()) {
|
||||
ServiceRoom.closeKurento();
|
||||
}
|
||||
};
|
||||
|
||||
$scope.$on("$locationChangeStart", function () {
|
||||
console.log("Changed location to: " + document.location);
|
||||
if (ServiceParticipant.isConnected()) {
|
||||
ServiceRoom.closeKurento();
|
||||
ServiceParticipant.removeParticipants();
|
||||
}
|
||||
});
|
||||
|
||||
$scope.goFullscreen = function () {
|
||||
|
||||
if (Fullscreen.isEnabled())
|
||||
Fullscreen.cancel();
|
||||
else
|
||||
Fullscreen.all();
|
||||
|
||||
};
|
||||
|
||||
$scope.disableMainSpeaker = function (value) {
|
||||
|
||||
var element = document.getElementById("buttonMainSpeaker");
|
||||
if (element.classList.contains("md-person")) { //on
|
||||
element.classList.remove("md-person");
|
||||
element.classList.add("md-recent-actors");
|
||||
ServiceParticipant.enableMainSpeaker();
|
||||
} else { //off
|
||||
element.classList.remove("md-recent-actors");
|
||||
element.classList.add("md-person");
|
||||
ServiceParticipant.disableMainSpeaker();
|
||||
}
|
||||
}
|
||||
|
||||
$scope.onOffVolume = function () {
|
||||
var localStream = ServiceRoom.getLocalStream();
|
||||
var element = document.getElementById("buttonVolume");
|
||||
if (element.classList.contains("md-volume-off")) { //on
|
||||
element.classList.remove("md-volume-off");
|
||||
element.classList.add("md-volume-up");
|
||||
localStream.audioEnabled = true;
|
||||
} else { //off
|
||||
element.classList.remove("md-volume-up");
|
||||
element.classList.add("md-volume-off");
|
||||
localStream.audioEnabled = false;
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
$scope.onOffVideocam = function () {
|
||||
var localStream = ServiceRoom.getLocalStream();
|
||||
var element = document.getElementById("buttonVideocam");
|
||||
if (element.classList.contains("md-videocam-off")) {//on
|
||||
element.classList.remove("md-videocam-off");
|
||||
element.classList.add("md-videocam");
|
||||
localStream.videoEnabled = true;
|
||||
} else {//off
|
||||
element.classList.remove("md-videocam");
|
||||
element.classList.add("md-videocam-off");
|
||||
localStream.videoEnabled = false;
|
||||
}
|
||||
};
|
||||
|
||||
$scope.disconnectStream = function () {
|
||||
var localStream = ServiceRoom.getLocalStream();
|
||||
var participant = ServiceParticipant.getMainParticipant();
|
||||
if (!localStream || !participant) {
|
||||
LxNotificationService.alert('Error!', "Not connected yet", 'Ok', function (answer) {
|
||||
});
|
||||
return false;
|
||||
}
|
||||
ServiceParticipant.disconnectParticipant(participant);
|
||||
ServiceRoom.getKurento().disconnectParticipant(participant.getStream());
|
||||
}
|
||||
|
||||
//chat
|
||||
$scope.message;
|
||||
|
||||
$scope.sendMessage = function () {
|
||||
console.log("Sending message", $scope.message);
|
||||
var kurento = ServiceRoom.getKurento();
|
||||
kurento.sendMessage($scope.roomName, $scope.userName, $scope.message);
|
||||
$scope.message = "";
|
||||
};
|
||||
|
||||
//open or close chat when click in chat button
|
||||
$scope.toggleChat = function () {
|
||||
var selectedEffect = "slide";
|
||||
// most effect types need no options passed by default
|
||||
var options = {direction: "right"};
|
||||
if ($("#effect").is(':visible')) {
|
||||
$("#content").animate({width: '100%'}, 500);
|
||||
} else {
|
||||
$("#content").animate({width: '80%'}, 500);
|
||||
}
|
||||
// run the effect
|
||||
$("#effect").toggle(selectedEffect, options, 500);
|
||||
};
|
||||
|
||||
var style = {
|
||||
hat: {
|
||||
"-1": "btn--indigo md-mood",
|
||||
"0": "btn--amber md-face-unlock"
|
||||
},
|
||||
marker: {
|
||||
"-1": "btn--indigo md-grid-off",
|
||||
"0": "btn--amber md-grid-on",
|
||||
"1": "btn--red md-grid-on"
|
||||
}
|
||||
};
|
||||
|
||||
$scope.filterIndex = "-1"; //off
|
||||
$scope.filterState;
|
||||
$scope.filterStyle;
|
||||
updateFilterValues();
|
||||
|
||||
function updateFilterValues() {
|
||||
$scope.filterState = parseInt($scope.filterIndex) < 0 ? "off" : "on";
|
||||
$scope.filterStyle = style[$scope.filter][$scope.filterIndex];
|
||||
}
|
||||
|
||||
$scope.applyFilter = function () {
|
||||
var reqParams = {};
|
||||
if ($scope.filter === "marker") {
|
||||
reqParams[$scope.filter] = parseInt($scope.filterIndex);
|
||||
} else {
|
||||
if (parseInt($scope.filterIndex) < 0) { //off -> on
|
||||
$scope.filterIndex = "0";
|
||||
reqParams[$scope.filter] = true;
|
||||
} else { //on -> off
|
||||
$scope.filterIndex = "-1";
|
||||
reqParams[$scope.filter] = false;
|
||||
}
|
||||
}
|
||||
|
||||
ServiceRoom.getKurento().sendCustomRequest(reqParams, function (error, response) {
|
||||
if (error) {
|
||||
console.error("Unable to toggle filter, currently " +
|
||||
$scope.filterState, error);
|
||||
LxNotificationService.alert('Error!',
|
||||
"Unable to toggle filter, currently " + $scope.filterState,
|
||||
'Ok', function (answer) {
|
||||
});
|
||||
return false;
|
||||
} else {
|
||||
if ($scope.filter === "marker") {
|
||||
return;
|
||||
}
|
||||
|
||||
updateFilterValues();
|
||||
console.log("Toggled filter " + $scope.filterState + " (idx " +
|
||||
$scope.filterIndex + ")");
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
ServiceParticipant.addEventListener("marker-filter-status-changed", function (status) {
|
||||
console.log("Filter status changed", status);
|
||||
if ($scope.filter === "marker") {
|
||||
$scope.filterIndex = status;
|
||||
updateFilterValues();
|
||||
$scope.$apply();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
|
||||
<div class="join">
|
||||
<div id="join-title">Kurento Room</div>
|
||||
|
||||
<div class="card" id="join">
|
||||
<form role="form" ng-submit="register(room)" accept-charset="UTF-8">
|
||||
|
||||
<div class="card__content">
|
||||
<lx-text-field label="Username" error="!nameValidation(room.userName)">
|
||||
<input type="text" id="name" ng-model="room.userName" required>
|
||||
</lx-text-field>
|
||||
|
||||
<span class="text-field-error" ng-if="!nameValidation(room.userName)">Invalid, please use:
|
||||
<em>a-zA-Z0-9</em></span>
|
||||
|
||||
<div class="grid">
|
||||
|
||||
<div ng-class="roomPickerClass">
|
||||
<lx-text-field label="{{roomPickerLabel}}" error="!nameValidation(room.roomName)">
|
||||
<input type="text" id="roomName" ng-model="room.roomName" required
|
||||
ng-change="nameValidation(room.roomName) && updateRoomUrl(room.roomName)"
|
||||
ng-disabled="existingRoomName">
|
||||
</lx-text-field>
|
||||
|
||||
<span class="text-field-error" ng-if="!nameValidation(room.roomName)">Allowed chars:
|
||||
<em>a-zA-Z0-9</em></span>
|
||||
</div>
|
||||
|
||||
<div class="grid__col6" ng-if="!existingRoomName">
|
||||
<lx-select ng-model="room.roomName" placeholder="Current rooms" choices="listRooms" floating-label>
|
||||
<lx-select-selected>
|
||||
{{ $selected }}
|
||||
</lx-select-selected>
|
||||
|
||||
<lx-select-choices>
|
||||
{{ $choice }}
|
||||
</lx-select-choices>
|
||||
</lx-select>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="card__actions">
|
||||
<div class="grid">
|
||||
<div class="grid__col6">
|
||||
<button class="btn btn--l btn--blue btn--raised" lx-ripple type="button" ng-click="clear()" title="Clear fields">Clear</button>
|
||||
</div>
|
||||
<div class="grid__col6">
|
||||
<button id="joinBtn" class="btn btn--l btn--green btn--raised" lx-ripple type="submit" ng-disabled="!nameValidation(room.userName) || !nameValidation(room.roomName) || joinInProcess">Join room!</button>
|
||||
</div>
|
||||
</div>
|
||||
<br>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div class="card bgc-grey-600 roomUrl" ng-if="!existingRoomName">
|
||||
<div class="card__content">
|
||||
<lx-text-field label="Share this URL for direct room access" theme="dark">
|
||||
<input type="text" id="roomUrlId" ng-model="roomUrl" ng-disabled="true">
|
||||
</lx-text-field>
|
||||
</div>
|
||||
|
||||
<div class="card__actions">
|
||||
<button class="btn btn--l btn--grey btn--raised" lx-ripple type="button" clipboard
|
||||
text="roomUrl" ng-disabled="!nameValidation(room.roomName)">Copy to clipboard</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
|
@ -0,0 +1,210 @@
|
|||
/*
|
||||
* @author Micael Gallego (micael.gallego@gmail.com)
|
||||
* @author Radu Tom Vlad
|
||||
*/
|
||||
|
||||
kurento_room.controller('loginController', function($scope, $rootScope, $http,
|
||||
$window, $routeParams, ServiceParticipant, ServiceRoom, LxNotificationService) {
|
||||
|
||||
$scope.existingRoomName = false;
|
||||
$scope.roomPickerClass = 'grid__col6';
|
||||
$scope.roomPickerLabel = 'Room';
|
||||
var name = $routeParams["existingRoomName"];
|
||||
if (name && name.length > 0) {
|
||||
$scope.room = {
|
||||
roomName: name
|
||||
}
|
||||
$scope.existingRoomName = true;
|
||||
$scope.roomPickerClass = 'grid__col';
|
||||
$scope.roomPickerLabel = 'Fixed room name';
|
||||
}
|
||||
|
||||
$scope.nameValidation = function(name) {
|
||||
return /^[a-zA-Z0-9]+$/.test(name);
|
||||
};
|
||||
|
||||
$rootScope.isParticipant = false;
|
||||
|
||||
var contextpath = (location.pathname == '/') ? '' : location.pathname;
|
||||
|
||||
$rootScope.contextpath = (location.pathname == '/') ? '' : location.pathname;
|
||||
|
||||
var roomsFragment = $rootScope.contextpath.endsWith('/') ? '#/rooms/' : '/#/rooms/';
|
||||
|
||||
$http.get($rootScope.contextpath + '/getAllRooms').success(function(data, status, headers, config) {
|
||||
console.log(JSON.stringify(data));
|
||||
$scope.listRooms = data;
|
||||
}).error(function(data, status, headers, config) {});
|
||||
|
||||
$http.get($rootScope.contextpath + '/getClientConfig').success(function(data, status, headers, config) {
|
||||
console.log(JSON.stringify(data));
|
||||
$scope.clientConfig = data;
|
||||
}).error(function(data, status, headers, config) {});
|
||||
|
||||
$http.get($rootScope.contextpath + '/getUpdateSpeakerInterval').success(function(data, status, headers, config) {
|
||||
$scope.updateSpeakerInterval = data
|
||||
}).error(function(data, status, headers, config) {});
|
||||
|
||||
$http.get($rootScope.contextpath + '/getThresholdSpeaker').success(function(data, status, headers, config) {
|
||||
$scope.thresholdSpeaker = data
|
||||
}).error(function(data, status, headers, config) {});
|
||||
|
||||
$scope.register = function(room) {
|
||||
|
||||
if (!room)
|
||||
ServiceParticipant.showError($window, LxNotificationService, {
|
||||
error: {
|
||||
message: "Username and room fields are both required"
|
||||
}
|
||||
}, contextpath);
|
||||
|
||||
$scope.userName = room.userName;
|
||||
$scope.roomName = room.roomName;
|
||||
|
||||
var wsUri = 'wss://' + location.host + $rootScope.contextpath + '/room';
|
||||
|
||||
//show loopback stream from server
|
||||
var displayPublished = $scope.clientConfig.loopbackRemote || false;
|
||||
//also show local stream when display my remote
|
||||
var mirrorLocal = $scope.clientConfig.loopbackAndLocal || false;
|
||||
|
||||
var kurento = KurentoRoom(wsUri, function(error, kurento) {
|
||||
|
||||
if (error) {
|
||||
return console.error('Error in KurentoRoom client', error);
|
||||
}
|
||||
|
||||
//TODO token should be generated by the server or a 3rd-party component
|
||||
//kurento.setRpcParams({token : "securityToken"});
|
||||
|
||||
room = kurento.Room({
|
||||
room: $scope.roomName,
|
||||
user: $scope.userName,
|
||||
updateSpeakerInterval: $scope.updateSpeakerInterval,
|
||||
thresholdSpeaker: $scope.thresholdSpeaker
|
||||
});
|
||||
|
||||
var localStream = kurento.Stream(room, {
|
||||
audio: true,
|
||||
video: true,
|
||||
data: false
|
||||
});
|
||||
|
||||
localStream.addEventListener("access-accepted", function() {
|
||||
room.addEventListener("room-connected", function(roomEvent) {
|
||||
var streams = roomEvent.streams;
|
||||
if (displayPublished) {
|
||||
localStream.subscribeToMyRemote();
|
||||
}
|
||||
localStream.publish();
|
||||
ServiceRoom.setLocalStream(localStream.getWebRtcPeer());
|
||||
for (var i = 0; i < streams.length; i++) {
|
||||
ServiceParticipant.addParticipant(streams[i]);
|
||||
}
|
||||
});
|
||||
|
||||
room.addEventListener("stream-published", function(streamEvent) {
|
||||
ServiceParticipant.addLocalParticipant(localStream);
|
||||
if (mirrorLocal && localStream.displayMyRemote()) {
|
||||
var localVideo = kurento.Stream(room, {
|
||||
video: true,
|
||||
id: "localStream"
|
||||
});
|
||||
localVideo.mirrorLocalStream(localStream.getWrStream());
|
||||
ServiceParticipant.addLocalMirror(localVideo);
|
||||
}
|
||||
});
|
||||
|
||||
room.addEventListener("stream-added", function(streamEvent) {
|
||||
ServiceParticipant.addParticipant(streamEvent.stream);
|
||||
});
|
||||
|
||||
room.addEventListener("stream-removed", function(streamEvent) {
|
||||
ServiceParticipant.removeParticipantByStream(streamEvent.stream);
|
||||
});
|
||||
|
||||
room.addEventListener("newMessage", function(msg) {
|
||||
ServiceParticipant.showMessage(msg.room, msg.user, msg.message);
|
||||
});
|
||||
|
||||
room.addEventListener("error-room", function(error) {
|
||||
ServiceParticipant.showError($window, LxNotificationService, error, contextpath);
|
||||
});
|
||||
|
||||
room.addEventListener("error-media", function(msg) {
|
||||
ServiceParticipant.alertMediaError($window, LxNotificationService, msg.error, contextPath, function(answer) {
|
||||
console.warn("Leave room because of error: " + answer);
|
||||
if (answer) {
|
||||
kurento.close(true);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
room.addEventListener("room-closed", function(msg) {
|
||||
if (msg.room !== $scope.roomName) {
|
||||
console.error("Closed room name doesn't match this room's name",
|
||||
msg.room, $scope.roomName);
|
||||
} else {
|
||||
kurento.close(true);
|
||||
ServiceParticipant.forceClose($window, LxNotificationService, 'Room ' +
|
||||
msg.room + ' has been forcibly closed from server', contextpath);
|
||||
}
|
||||
});
|
||||
|
||||
room.addEventListener("lost-connection", function(msg) {
|
||||
kurento.close(true);
|
||||
ServiceParticipant.forceClose($window, LxNotificationService,
|
||||
'Lost connection with room "' + msg.room +
|
||||
'". Please try reloading the webpage...');
|
||||
}, contextpath);
|
||||
|
||||
room.addEventListener("stream-stopped-speaking", function(participantId) {
|
||||
ServiceParticipant.streamStoppedSpeaking(participantId);
|
||||
});
|
||||
|
||||
room.addEventListener("stream-speaking", function(participantId) {
|
||||
ServiceParticipant.streamSpeaking(participantId);
|
||||
});
|
||||
|
||||
room.addEventListener("update-main-speaker", function(participantId) {
|
||||
ServiceParticipant.updateMainSpeaker(participantId);
|
||||
});
|
||||
|
||||
room.addEventListener("custom-message-received", function(data) {
|
||||
if (data.params.MarkerFilterState !== undefined) {
|
||||
ServiceParticipant.changeMarkerFilterStatus(data.params.MarkerFilterState);
|
||||
}
|
||||
});
|
||||
|
||||
room.connect();
|
||||
});
|
||||
|
||||
localStream.addEventListener("access-denied", function() {
|
||||
ServiceParticipant.showError($window, LxNotificationService, {
|
||||
error: {
|
||||
message: "Access not granted to camera and microphone"
|
||||
}
|
||||
});
|
||||
}, contextpath);
|
||||
localStream.init();
|
||||
});
|
||||
|
||||
//save kurento & roomName & userName in service
|
||||
ServiceRoom.setKurento(kurento);
|
||||
ServiceRoom.setRoomName($scope.roomName);
|
||||
ServiceRoom.setUserName($scope.userName);
|
||||
ServiceRoom.setFilterRequestParam($scope.clientConfig.filterRequestParam);
|
||||
|
||||
$rootScope.isParticipant = true;
|
||||
|
||||
//redirect to call
|
||||
$window.location.href = '#/call';
|
||||
};
|
||||
$scope.clear = function() {
|
||||
$scope.room = "";
|
||||
$scope.updateRoomUrl();
|
||||
};
|
||||
$scope.updateRoomUrl = function(roomName) {
|
||||
$scope.roomUrl = (roomName && roomName.length > 0) ? location.protocol + '//' + location.host + $rootScope.contextpath + roomsFragment + roomName : '';
|
||||
};
|
||||
});
|
|
@ -0,0 +1,399 @@
|
|||
/*
|
||||
* (C) Copyright 2016 Kurento (http://kurento.org/)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
function AppParticipant(stream) {
|
||||
|
||||
this.stream = stream;
|
||||
this.videoElement;
|
||||
this.thumbnailId;
|
||||
this.mainVideo;
|
||||
var that = this;
|
||||
|
||||
this.getStream = function () {
|
||||
return this.stream;
|
||||
}
|
||||
|
||||
this.setMain = function () {
|
||||
that.videoElement.className += " active-video";
|
||||
var mainVideosParent = document.getElementById('main-video');
|
||||
|
||||
if (elementExists(that.mainVideo)) {
|
||||
$(that.mainVideo).show();
|
||||
} else {
|
||||
that.mainVideo = stream.playOnlyVideo(mainVideosParent, that.thumbnailId);
|
||||
}
|
||||
}
|
||||
|
||||
this.removeMain = function () {
|
||||
$(that.videoElement).removeClass("active-video");
|
||||
if (elementExists(that.mainVideo)) {
|
||||
$(that.mainVideo).hide();
|
||||
} else {
|
||||
console.warn(stream.getGlobalID() + ': no main video element to remove');
|
||||
}
|
||||
}
|
||||
|
||||
this.remove = function () {
|
||||
if (that.videoElement !== undefined) {
|
||||
if (that.videoElement.parentNode !== null) {
|
||||
that.videoElement.parentNode.removeChild(that.videoElement);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function elementExists(element) {
|
||||
return element !== undefined && element.id !== undefined && $('#' + element.id).length > 0;
|
||||
}
|
||||
|
||||
function playVideo() {
|
||||
|
||||
that.thumbnailId = "video-" + stream.getGlobalID();
|
||||
|
||||
that.videoElement = document.createElement('div');
|
||||
that.videoElement.setAttribute("id", that.thumbnailId);
|
||||
that.videoElement.className = "video";
|
||||
|
||||
var speakerSpeakingVolumen = document.createElement('div');
|
||||
speakerSpeakingVolumen.setAttribute("id", "speaker" + that.thumbnailId);
|
||||
speakerSpeakingVolumen.className = 'btn--m btn--green btn--fab mdi md-volume-up blinking';
|
||||
speakerSpeakingVolumen.style.position = "absolute";
|
||||
speakerSpeakingVolumen.style.left = "3%";
|
||||
speakerSpeakingVolumen.style.top = "60%";
|
||||
speakerSpeakingVolumen.style.zIndex = "100";
|
||||
speakerSpeakingVolumen.style.display = "none";
|
||||
that.videoElement.appendChild(speakerSpeakingVolumen);
|
||||
|
||||
document.getElementById("participants").appendChild(that.videoElement);
|
||||
that.stream.playThumbnail(that.thumbnailId);
|
||||
}
|
||||
|
||||
playVideo();
|
||||
}
|
||||
|
||||
function Participants() {
|
||||
|
||||
var mainParticipant;
|
||||
var localParticipant;
|
||||
var mirrorParticipant;
|
||||
var participants = {};
|
||||
var roomName;
|
||||
var that = this;
|
||||
var connected = true;
|
||||
var displayingRelogin = false;
|
||||
var mainSpeaker = true;
|
||||
|
||||
var ee = new EventEmitter();
|
||||
|
||||
this.isConnected = function () {
|
||||
return connected;
|
||||
}
|
||||
|
||||
this.getRoomName = function () {
|
||||
console.log("room - getRoom " + roomName);
|
||||
roomName = room.name;
|
||||
return roomName;
|
||||
};
|
||||
|
||||
this.getMainParticipant = function () {
|
||||
return mainParticipant;
|
||||
}
|
||||
|
||||
function updateVideoStyle() {
|
||||
var MAX_WIDTH = 14;
|
||||
var numParticipants = Object.keys(participants).length;
|
||||
var maxParticipantsWithMaxWidth = 98 / MAX_WIDTH;
|
||||
|
||||
if (numParticipants > maxParticipantsWithMaxWidth) {
|
||||
$('.video').css({
|
||||
"width": (98 / numParticipants) + "%"
|
||||
});
|
||||
} else {
|
||||
$('.video').css({
|
||||
"width": MAX_WIDTH + "%"
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
function updateMainParticipant(participant) {
|
||||
if (!mainParticipant || (mainParticipant != participant)) {
|
||||
if (mainParticipant) {
|
||||
mainParticipant.removeMain();
|
||||
}
|
||||
mainParticipant = participant;
|
||||
mainParticipant.setMain();
|
||||
}
|
||||
}
|
||||
|
||||
this.addLocalParticipant = function (stream) {
|
||||
localParticipant = that.addParticipant(stream);
|
||||
mainParticipant = localParticipant;
|
||||
mainParticipant.setMain();
|
||||
};
|
||||
|
||||
this.addLocalMirror = function (stream) {
|
||||
mirrorParticipant = that.addParticipant(stream);
|
||||
};
|
||||
|
||||
this.addParticipant = function (stream) {
|
||||
|
||||
var participant = new AppParticipant(stream);
|
||||
participants[stream.getGlobalID()] = participant;
|
||||
|
||||
updateVideoStyle();
|
||||
|
||||
$(participant.videoElement).click(function (e) {
|
||||
updateMainParticipant(participant);
|
||||
});
|
||||
|
||||
//updateMainParticipant(participant);
|
||||
|
||||
return participant;
|
||||
};
|
||||
|
||||
this.removeParticipantByStream = function (stream) {
|
||||
this.removeParticipant(stream.getGlobalID());
|
||||
};
|
||||
|
||||
this.disconnectParticipant = function (appParticipant) {
|
||||
this.removeParticipant(appParticipant.getStream().getGlobalID());
|
||||
};
|
||||
|
||||
this.removeParticipant = function (streamId) {
|
||||
var participant = participants[streamId];
|
||||
delete participants[streamId];
|
||||
participant.remove();
|
||||
|
||||
if (mirrorParticipant) {
|
||||
var otherLocal = null;
|
||||
if (participant === localParticipant) {
|
||||
otherLocal = mirrorParticipant;
|
||||
}
|
||||
if (participant === mirrorParticipant) {
|
||||
otherLocal = localParticipant;
|
||||
}
|
||||
if (otherLocal) {
|
||||
console.log("Removed local participant (or mirror) so removing the other local as well");
|
||||
delete participants[otherLocal.getStream().getGlobalID()];
|
||||
otherLocal.remove();
|
||||
}
|
||||
}
|
||||
|
||||
//setting main
|
||||
if (mainParticipant && mainParticipant === participant) {
|
||||
var mainIsLocal = false;
|
||||
if (localParticipant) {
|
||||
if (participant !== localParticipant && participant !== mirrorParticipant) {
|
||||
mainParticipant = localParticipant;
|
||||
mainIsLocal = true;
|
||||
} else {
|
||||
localParticipant = null;
|
||||
mirrorParticipant = null;
|
||||
}
|
||||
}
|
||||
if (!mainIsLocal) {
|
||||
var keys = Object.keys(participants);
|
||||
if (keys.length > 0) {
|
||||
mainParticipant = participants[keys[0]];
|
||||
} else {
|
||||
mainParticipant = null;
|
||||
}
|
||||
}
|
||||
if (mainParticipant) {
|
||||
mainParticipant.setMain();
|
||||
console.log("Main video from " + mainParticipant.getStream().getGlobalID());
|
||||
} else
|
||||
console.error("No media streams left to display");
|
||||
}
|
||||
|
||||
updateVideoStyle();
|
||||
};
|
||||
|
||||
//only called when leaving the room
|
||||
this.removeParticipants = function () {
|
||||
connected = false;
|
||||
for (var index in participants) {
|
||||
var participant = participants[index];
|
||||
participant.remove();
|
||||
}
|
||||
participants = [];
|
||||
};
|
||||
|
||||
this.getParticipants = function () {
|
||||
return participants;
|
||||
};
|
||||
|
||||
this.enableMainSpeaker = function () {
|
||||
mainSpeaker = true;
|
||||
}
|
||||
|
||||
this.disableMainSpeaker = function () {
|
||||
mainSpeaker = false;
|
||||
}
|
||||
|
||||
// Open the chat automatically when a message is received
|
||||
function autoOpenChat() {
|
||||
var selectedEffect = "slide";
|
||||
var options = {direction: "right"};
|
||||
if ($("#effect").is(':hidden')) {
|
||||
$("#content").animate({width: '80%'}, 500);
|
||||
$("#effect").toggle(selectedEffect, options, 500);
|
||||
}
|
||||
};
|
||||
|
||||
this.showMessage = function (room, user, message) {
|
||||
var ul = document.getElementsByClassName("list");
|
||||
|
||||
var chatDiv = document.getElementById('chatDiv');
|
||||
var messages = $("#messages");
|
||||
var updateScroll = true;
|
||||
if (messages.outerHeight() - chatDiv.scrollTop > chatDiv.offsetHeight) {
|
||||
updateScroll = false;
|
||||
}
|
||||
|
||||
var vetext = localParticipant.videoElement.textContent || localParticipant.videoElement.innerText;
|
||||
var localUser = vetext.replace("_webcam", "");
|
||||
if (user === localUser) { //me
|
||||
|
||||
var li = document.createElement('li');
|
||||
li.className = "list-row list-row--has-primary list-row--has-separator";
|
||||
var div1 = document.createElement("div1");
|
||||
div1.className = "list-secondary-tile";
|
||||
var img = document.createElement("img");
|
||||
img.className = "list-primary-tile__img";
|
||||
img.setAttribute("src", "http://ui.lumapps.com/images/placeholder/2-square.jpg");
|
||||
var div2 = document.createElement('div');
|
||||
div2.className = "list-content-tile list-content-tile--two-lines";
|
||||
var strong = document.createElement('strong');
|
||||
strong.innerHTML = user;
|
||||
var span = document.createElement('span');
|
||||
span.innerHTML = message;
|
||||
div2.appendChild(strong);
|
||||
div2.appendChild(span);
|
||||
div1.appendChild(img);
|
||||
li.appendChild(div1);
|
||||
li.appendChild(div2);
|
||||
ul[0].appendChild(li);
|
||||
|
||||
} else {//others
|
||||
|
||||
var li = document.createElement('li');
|
||||
li.className = "list-row list-row--has-primary list-row--has-separator";
|
||||
var div1 = document.createElement("div1");
|
||||
div1.className = "list-primary-tile";
|
||||
var img = document.createElement("img");
|
||||
img.className = "list-primary-tile__img";
|
||||
img.setAttribute("src", "http://ui.lumapps.com/images/placeholder/1-square.jpg");
|
||||
var div2 = document.createElement('div');
|
||||
div2.className = "list-content-tile list-content-tile--two-lines";
|
||||
var strong = document.createElement('strong');
|
||||
strong.innerHTML = user;
|
||||
var span = document.createElement('span');
|
||||
span.innerHTML = message;
|
||||
div2.appendChild(strong);
|
||||
div2.appendChild(span);
|
||||
div1.appendChild(img);
|
||||
li.appendChild(div1);
|
||||
li.appendChild(div2);
|
||||
ul[0].appendChild(li);
|
||||
autoOpenChat();
|
||||
}
|
||||
|
||||
if (updateScroll) {
|
||||
chatDiv.scrollTop = messages.outerHeight();
|
||||
}
|
||||
};
|
||||
|
||||
this.showError = function ($window, LxNotificationService, e, contextPath) {
|
||||
if (displayingRelogin) {
|
||||
console.warn('Already displaying an alert that leads to relogin');
|
||||
return false;
|
||||
}
|
||||
displayingRelogin = true;
|
||||
that.removeParticipants();
|
||||
LxNotificationService.alert('Error!', e.error.message, 'Reconnect', function (answer) {
|
||||
displayingRelogin = false;
|
||||
relogin($window, contextPath);
|
||||
});
|
||||
};
|
||||
|
||||
this.forceClose = function ($window, LxNotificationService, msg, contextPath) {
|
||||
if (displayingRelogin) {
|
||||
console.warn('Already displaying an alert that leads to relogin');
|
||||
return false;
|
||||
}
|
||||
displayingRelogin = true;
|
||||
that.removeParticipants();
|
||||
LxNotificationService.alert('Warning!', msg, 'Reload', function (answer) {
|
||||
displayingRelogin = false;
|
||||
relogin($window, contextPath);
|
||||
});
|
||||
};
|
||||
|
||||
this.alertMediaError = function ($window, LxNotificationService, msg, contextPath, callback) {
|
||||
if (displayingRelogin) {
|
||||
console.warn('Already displaying an alert that leads to relogin');
|
||||
return false;
|
||||
}
|
||||
LxNotificationService.confirm('Warning!', 'Server media error: ' + msg
|
||||
+ ". Please reconnect.", {cancel: 'Disagree', ok: 'Agree'},
|
||||
function (answer) {
|
||||
console.log("User agrees upon media error: " + answer);
|
||||
if (answer) {
|
||||
that.removeParticipants();
|
||||
relogin($window, contextPath);
|
||||
}
|
||||
if (typeof callback === "function") {
|
||||
callback(answer);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
function relogin($window, contextPath) {
|
||||
//TODO call leaveRoom() in kurento
|
||||
contextPath = contextPath || '/';
|
||||
$window.location.href = contextPath; //'#/login';
|
||||
}
|
||||
|
||||
this.streamSpeaking = function (participantId) {
|
||||
if (participants[participantId.participantId] != undefined)
|
||||
document.getElementById("speaker" + participants[participantId.participantId].thumbnailId).style.display = '';
|
||||
}
|
||||
|
||||
this.streamStoppedSpeaking = function (participantId) {
|
||||
if (participants[participantId.participantId] != undefined)
|
||||
document.getElementById("speaker" + participants[participantId.participantId].thumbnailId).style.display = "none";
|
||||
}
|
||||
|
||||
this.updateMainSpeaker = function (participantId) {
|
||||
if (participants[participantId.participantId] != undefined) {
|
||||
if (mainSpeaker)
|
||||
updateMainParticipant(participants[participantId.participantId]);
|
||||
}
|
||||
}
|
||||
|
||||
this.changeMarkerFilterStatus = function (status) {
|
||||
this.emitEvent("marker-filter-status-changed", [status]);
|
||||
console.log("New filter status: " + status);
|
||||
};
|
||||
|
||||
this.addEventListener = function (eventName, listener) {
|
||||
ee.addListener(eventName, listener);
|
||||
};
|
||||
|
||||
this.emitEvent = function (eventName, eventsArray) {
|
||||
ee.emitEvent(eventName, eventsArray);
|
||||
};
|
||||
}
|
9
openvidu-demo/src/main/resources/static/angular/services/serviceParticipant.js
vendored
Normal file
9
openvidu-demo/src/main/resources/static/angular/services/serviceParticipant.js
vendored
Normal file
|
@ -0,0 +1,9 @@
|
|||
/*
|
||||
* @author Raquel Díaz González
|
||||
*/
|
||||
|
||||
kurento_room.factory('ServiceParticipant', function () {
|
||||
|
||||
return new Participants();
|
||||
|
||||
});
|
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
* @author Raquel Díaz González
|
||||
*/
|
||||
|
||||
kurento_room.service('ServiceRoom', function () {
|
||||
|
||||
var kurento;
|
||||
var roomName;
|
||||
var userName;
|
||||
var localStream;
|
||||
var filterRequestParam;
|
||||
|
||||
this.getKurento = function () {
|
||||
return kurento;
|
||||
};
|
||||
|
||||
this.getRoomName = function () {
|
||||
return roomName;
|
||||
};
|
||||
|
||||
this.setKurento = function (value) {
|
||||
kurento = value;
|
||||
};
|
||||
|
||||
this.setRoomName = function (value) {
|
||||
roomName = value;
|
||||
};
|
||||
|
||||
this.getLocalStream = function () {
|
||||
return localStream;
|
||||
};
|
||||
|
||||
this.setLocalStream = function (value) {
|
||||
localStream = value;
|
||||
};
|
||||
|
||||
this.getUserName = function () {
|
||||
return userName;
|
||||
};
|
||||
|
||||
this.setUserName = function (value) {
|
||||
userName = value;
|
||||
};
|
||||
|
||||
this.closeKurento = function () {
|
||||
if (kurento && kurento instanceof KurentoRoom) {
|
||||
kurento.close();
|
||||
} else {
|
||||
console.log('KurentoRoom instance is not set');
|
||||
}
|
||||
};
|
||||
|
||||
this.getFilterRequestParam = function () {
|
||||
return filterRequestParam;
|
||||
};
|
||||
|
||||
this.setFilterRequestParam = function (value) {
|
||||
filterRequestParam = value;
|
||||
};
|
||||
});
|
|
@ -0,0 +1,56 @@
|
|||
/* cyrillic-ext */
|
||||
@font-face {
|
||||
font-family: 'Open Sans';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: local('Open Sans'), local('OpenSans'), url(//fonts.gstatic.com/s/opensans/v13/K88pR3goAWT7BTt32Z01mxJtnKITppOI_IvcXXDNrsc.woff2) format('woff2');
|
||||
unicode-range: U+0460-052F, U+20B4, U+2DE0-2DFF, U+A640-A69F;
|
||||
}
|
||||
/* cyrillic */
|
||||
@font-face {
|
||||
font-family: 'Open Sans';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: local('Open Sans'), local('OpenSans'), url(//fonts.gstatic.com/s/opensans/v13/RjgO7rYTmqiVp7vzi-Q5URJtnKITppOI_IvcXXDNrsc.woff2) format('woff2');
|
||||
unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
|
||||
}
|
||||
/* greek-ext */
|
||||
@font-face {
|
||||
font-family: 'Open Sans';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: local('Open Sans'), local('OpenSans'), url(//fonts.gstatic.com/s/opensans/v13/LWCjsQkB6EMdfHrEVqA1KRJtnKITppOI_IvcXXDNrsc.woff2) format('woff2');
|
||||
unicode-range: U+1F00-1FFF;
|
||||
}
|
||||
/* greek */
|
||||
@font-face {
|
||||
font-family: 'Open Sans';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: local('Open Sans'), local('OpenSans'), url(//fonts.gstatic.com/s/opensans/v13/xozscpT2726on7jbcb_pAhJtnKITppOI_IvcXXDNrsc.woff2) format('woff2');
|
||||
unicode-range: U+0370-03FF;
|
||||
}
|
||||
/* vietnamese */
|
||||
@font-face {
|
||||
font-family: 'Open Sans';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: local('Open Sans'), local('OpenSans'), url(//fonts.gstatic.com/s/opensans/v13/59ZRklaO5bWGqF5A9baEERJtnKITppOI_IvcXXDNrsc.woff2) format('woff2');
|
||||
unicode-range: U+0102-0103, U+1EA0-1EF1, U+20AB;
|
||||
}
|
||||
/* latin-ext */
|
||||
@font-face {
|
||||
font-family: 'Open Sans';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: local('Open Sans'), local('OpenSans'), url(//fonts.gstatic.com/s/opensans/v13/u-WUoqrET9fUeobQW7jkRRJtnKITppOI_IvcXXDNrsc.woff2) format('woff2');
|
||||
unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF;
|
||||
}
|
||||
/* latin */
|
||||
@font-face {
|
||||
font-family: 'Open Sans';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: local('Open Sans'), local('OpenSans'), url(//fonts.gstatic.com/s/opensans/v13/cJZKeOuBrn4kERxqtaUH3VtXRa8TVwTICgirnJhmVJw.woff2) format('woff2');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000;
|
||||
}
|
|
@ -0,0 +1,240 @@
|
|||
html, body {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
#buttonActions>button{
|
||||
font-size: 1.9rem;
|
||||
}
|
||||
|
||||
#room{
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
* {
|
||||
margin: 0px;
|
||||
padding: 0px;
|
||||
overflow: hidden
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: 'Open Sans', sans-serif;
|
||||
}
|
||||
|
||||
.roomUrl {
|
||||
margin: 40px auto 30px;
|
||||
}
|
||||
|
||||
#main-video {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
#main-video>video {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
#main-video video {
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
video {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#content {
|
||||
background-color: black;
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
right: 70%;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#participants {
|
||||
position: absolute;
|
||||
bottom: 0px;
|
||||
right: 0px;
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
float: right;
|
||||
margin: 1em;
|
||||
}
|
||||
|
||||
.name {
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
bottom: 0px;
|
||||
left: 0px;
|
||||
z-index: 99;
|
||||
background-color: transparent;
|
||||
margin: 0.5em;
|
||||
text-shadow: 0px 0px 10px #000000;
|
||||
}
|
||||
|
||||
.active-video {
|
||||
border: 2px solid white;
|
||||
}
|
||||
|
||||
.active-audio {
|
||||
border: 2px solid blue;
|
||||
}
|
||||
|
||||
.blinking {
|
||||
|
||||
animation-name: blinking;
|
||||
animation-duration: 2s;
|
||||
animation-timing-function: linear;
|
||||
animation-iteration-count: infinite;
|
||||
|
||||
-webkit-animation-name: blinking;
|
||||
-webkit-animation-duration: 2s;
|
||||
-webkit-animation-timing-function: linear;
|
||||
-webkit-animation-iteration-count: infinite;
|
||||
}
|
||||
|
||||
@-moz-keyframes blinking{
|
||||
0% { opacity: 1.0; }
|
||||
50% { opacity: 0.0; }
|
||||
100% { opacity: 1.0; }
|
||||
}
|
||||
|
||||
@-webkit-keyframes blinking {
|
||||
0% { opacity: 1.0; }
|
||||
50% { opacity: 0.0; }
|
||||
100% { opacity: 1.0; }
|
||||
}
|
||||
|
||||
@keyframes blinking {
|
||||
0% { opacity: 1.0; }
|
||||
50% { opacity: 0.0; }
|
||||
100% { opacity: 1.0; }
|
||||
}
|
||||
|
||||
.video {
|
||||
width: 23%;
|
||||
/* whatever width you want */
|
||||
position: relative;
|
||||
float: right;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.video:after {
|
||||
padding-top: 56.25%;
|
||||
/* 16:9 ratio */
|
||||
display: block;
|
||||
content: '';
|
||||
}
|
||||
|
||||
.video>div {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
/* fill parent */
|
||||
background-color: #000000;
|
||||
/* let's see it! */
|
||||
color: white;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
/* align horizontal */
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
#logo {
|
||||
position: absolute;
|
||||
display: inline;
|
||||
left: 0px;
|
||||
top: 0px;
|
||||
margin: 1em;
|
||||
}
|
||||
|
||||
#room-name {
|
||||
display: inline;
|
||||
width: 100%;
|
||||
position: absolute;
|
||||
margin: auto;
|
||||
background-color: transparent;
|
||||
margin: 0.5em;
|
||||
text-shadow: 0px 0px 10px #000000;
|
||||
text-align: center;
|
||||
color: white;
|
||||
font-weight: bold;
|
||||
font-size: 2em;
|
||||
}
|
||||
|
||||
.join {
|
||||
position: relative;
|
||||
margin: auto;
|
||||
width: 500px;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
#join-title {
|
||||
display: inline-flex;
|
||||
font-size: 1.5em;
|
||||
font-weight: bold;
|
||||
color: #555;
|
||||
padding-left: 70px;
|
||||
padding-bottom: 35px;
|
||||
padding-top: 35px;
|
||||
background-image: url("../img/kurento.png");
|
||||
background-repeat: no-repeat;
|
||||
background-position: left;
|
||||
margin: auto 0 auto 0;
|
||||
}
|
||||
|
||||
/*.join p {
|
||||
margin: 20px 0 0;
|
||||
}
|
||||
|
||||
.join p:first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.join input[type=text], .join input[type=password] {
|
||||
width: 278px;
|
||||
}
|
||||
|
||||
.join p.submit {
|
||||
text-align: center;
|
||||
}*/
|
||||
|
||||
:-moz-placeholder {
|
||||
color: #c9c9c9 !important;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
::-webkit-input-placeholder {
|
||||
color: #ccc;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
/*chat effect*/
|
||||
|
||||
#effect {
|
||||
position: relative;
|
||||
padding: 0.4em;
|
||||
}
|
||||
|
||||
.card__content {
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
.card__actions {
|
||||
border-top-width: 0px;
|
||||
}
|
Binary file not shown.
After Width: | Height: | Size: 32 KiB |
Binary file not shown.
After Width: | Height: | Size: 6.3 KiB |
Binary file not shown.
After Width: | Height: | Size: 41 KiB |
Binary file not shown.
After Width: | Height: | Size: 7.6 KiB |
Binary file not shown.
After Width: | Height: | Size: 12 KiB |
|
@ -0,0 +1,53 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<title>Kurento Room Demo</title>
|
||||
<meta name="author" content="kurento.org">
|
||||
<link rel="shortcut icon" href="img/kurento.png" type="image/png" />
|
||||
|
||||
<!-- Bower CSS styles -->
|
||||
<link type="text/css" rel="stylesheet"
|
||||
href="webjars/jquery-ui/jquery-ui.min.css">
|
||||
<link type="text/css" rel="stylesheet"
|
||||
href="webjars/material-design-iconic-font/css/material-design-iconic-font.min.css">
|
||||
<link type="text/css" rel="stylesheet"
|
||||
href="webjars/lumx/dist/css/lumx.css">
|
||||
|
||||
<!-- Custom CSS styles -->
|
||||
<link type="text/css" rel="stylesheet" href="./css/room.css" />
|
||||
<link type="text/css" rel="stylesheet" href="./css/googleapis-fonts.css">
|
||||
|
||||
<!-- Bower JavaScript dependencies -->
|
||||
<script src="webjars/adapter.js/adapter.js"></script>
|
||||
<script src="webjars/jquery/dist/jquery.min.js"></script>
|
||||
<script src="webjars/jquery-ui/jquery-ui.min.js"></script>
|
||||
<script src="webjars/angular/angular.min.js"></script>
|
||||
<script src="webjars/angular-clipboard/angular-clipboard.js"></script>
|
||||
<script src="webjars/angular-route/angular-route.js"></script>
|
||||
<script src="webjars/angular-fullscreen/src/angular-fullscreen.js"></script>
|
||||
<script src="webjars/velocity/velocity.js"></script>
|
||||
<script src="webjars/moment/min/moment-with-locales.min.js"></script>
|
||||
<script src="webjars/lumx/dist/js/lumx.min.js"></script>
|
||||
<script src="webjars/EventEmitter.js/EventEmitter.min.js"></script>
|
||||
|
||||
<!-- Kurento JavaScript dependencies -->
|
||||
<script src="./js/kurento-utils.js"></script>
|
||||
<script src="./js/kurento-jsonrpc.js"></script>
|
||||
<script src="./js/KurentoRoom.js"></script>
|
||||
|
||||
<!-- Custom JavaScript dependencies -->
|
||||
<script src="./angular/app.js"></script>
|
||||
<script src="./angular/call/callController.js"></script>
|
||||
<script src="./angular/login/loginController.js"></script>
|
||||
<script src="./angular/services/Participants.js"></script>
|
||||
<script src="./angular/services/serviceParticipant.js"></script>
|
||||
<script src="./angular/services/serviceRoom.js"></script>
|
||||
</head>
|
||||
|
||||
<body ng-app="kurento_room">
|
||||
<div ng-view>
|
||||
<!--display the view (login/call) with route system-->
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* (C) Copyright 2015 Kurento (http://kurento.org/)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.openvidu.test.demo;
|
||||
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.util.Collection;
|
||||
|
||||
import org.junit.runners.Parameterized.Parameters;
|
||||
import org.kurento.test.browser.WebPageType;
|
||||
import org.openvidu.test.browser.AddRemoveUsers;
|
||||
|
||||
/**
|
||||
* @see AddRemoveUsers
|
||||
* @author Radu Tom Vlad (rvlad@naevatec.com)
|
||||
*/
|
||||
public class AddRemoveUsersDemoTest extends AddRemoveUsers {
|
||||
|
||||
@Override
|
||||
public void setupBrowserTest() throws InterruptedException {
|
||||
webPageType = WebPageType.ROOT;
|
||||
super.setupBrowserTest();
|
||||
}
|
||||
|
||||
@Parameters(name = "{index}: {0}")
|
||||
public static Collection<Object[]> data() {
|
||||
return localChromes(MethodHandles.lookup().lookupClass().getSimpleName(), NUM_USERS,
|
||||
WebPageType.ROOT);
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue