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