openvidu-browser: filter events feature

pull/105/head
pabloFuente 2018-08-03 14:56:36 +02:00
parent 9bc5128aa3
commit 07bf11b1c5
7 changed files with 185 additions and 7 deletions

View File

@ -575,6 +575,7 @@ export class OpenVidu {
recordingStopped: this.session.onRecordingStopped.bind(this.session), recordingStopped: this.session.onRecordingStopped.bind(this.session),
sendMessage: this.session.onNewMessage.bind(this.session), sendMessage: this.session.onNewMessage.bind(this.session),
streamPropertyChanged: this.session.onStreamPropertyChanged.bind(this.session), streamPropertyChanged: this.session.onStreamPropertyChanged.bind(this.session),
filterEventDispatched: this.session.onFilterEventDispatched.bind(this.session),
iceCandidate: this.session.recvIceCandidate.bind(this.session), iceCandidate: this.session.recvIceCandidate.bind(this.session),
mediaError: this.session.onMediaError.bind(this.session) mediaError: this.session.onMediaError.bind(this.session)
} }

View File

@ -29,6 +29,7 @@ import { ConnectionOptions } from '../OpenViduInternal/Interfaces/Private/Connec
import { ObjMap } from '../OpenViduInternal/Interfaces/Private/ObjMap'; import { ObjMap } from '../OpenViduInternal/Interfaces/Private/ObjMap';
import { SessionOptions } from '../OpenViduInternal/Interfaces/Private/SessionOptions'; import { SessionOptions } from '../OpenViduInternal/Interfaces/Private/SessionOptions';
import { ConnectionEvent } from '../OpenViduInternal/Events/ConnectionEvent'; import { ConnectionEvent } from '../OpenViduInternal/Events/ConnectionEvent';
import { FilterEvent } from '../OpenViduInternal/Events/FilterEvent';
import { PublisherSpeakingEvent } from '../OpenViduInternal/Events/PublisherSpeakingEvent'; import { PublisherSpeakingEvent } from '../OpenViduInternal/Events/PublisherSpeakingEvent';
import { RecordingEvent } from '../OpenViduInternal/Events/RecordingEvent'; import { RecordingEvent } from '../OpenViduInternal/Events/RecordingEvent';
import { SessionDisconnectedEvent } from '../OpenViduInternal/Events/SessionDisconnectedEvent'; import { SessionDisconnectedEvent } from '../OpenViduInternal/Events/SessionDisconnectedEvent';
@ -589,6 +590,51 @@ export class Session implements EventDispatcher {
}); });
} }
addFilterEventListener(stream: Stream, eventType: string): Promise<any> {
return new Promise((resolve, reject) => {
console.info('Adding filter event listener to event ' + eventType + ' to stream ' + stream.streamId);
this.openvidu.sendRequest(
'addFilterEventListener',
{ streamId: stream.streamId, type: eventType },
(error, response) => {
if (error) {
console.error('Error adding filter event listener to event ' + eventType + 'for Stream ' + stream.streamId, error);
if (error.code === 401) {
reject(new OpenViduError(OpenViduErrorName.OPENVIDU_PERMISSION_DENIED, "You don't have permissions to add a filter event listener"));
} else {
reject(error);
}
} else {
console.info('Filter event listener to event ' + eventType + ' successfully applied on Stream ' + stream.streamId);
resolve();
}
}
);
});
}
removeFilterEventListener(stream: Stream, eventType: string): Promise<any> {
return new Promise((resolve, reject) => {
console.info('Removing filter event listener to event ' + eventType + ' to stream ' + stream.streamId);
this.openvidu.sendRequest(
'removeFilterEventListener',
{ streamId: stream.streamId, type: eventType },
(error, response) => {
if (error) {
console.error('Error removing filter event listener to event ' + eventType + 'for Stream ' + stream.streamId, error);
if (error.code === 401) {
reject(new OpenViduError(OpenViduErrorName.OPENVIDU_PERMISSION_DENIED, "You don't have permissions to add a filter event listener"));
} else {
reject(error);
}
} else {
console.info('Filter event listener to event ' + eventType + ' successfully removed on Stream ' + stream.streamId);
resolve();
}
}
);
});
}
/** /**
* Sends one signal. `signal` object has the following optional properties: * Sends one signal. `signal` object has the following optional properties:
@ -638,7 +684,7 @@ export class Session implements EventDispatcher {
/** /**
* See [[EventDispatcher.on]] * See [[EventDispatcher.on]]
*/ */
on(type: string, handler: (event: SessionDisconnectedEvent | SignalEvent | StreamEvent | ConnectionEvent | PublisherSpeakingEvent | RecordingEvent) => void): EventDispatcher { on(type: string, handler: (event: SessionDisconnectedEvent | SignalEvent | StreamEvent | ConnectionEvent | PublisherSpeakingEvent | RecordingEvent | FilterEvent) => void): EventDispatcher {
this.ee.on(type, event => { this.ee.on(type, event => {
if (event) { if (event) {
@ -1006,6 +1052,21 @@ export class Session implements EventDispatcher {
this.ee.emitEvent('recordingStopped', [new RecordingEvent(this, 'recordingStopped', response.id, response.name)]); this.ee.emitEvent('recordingStopped', [new RecordingEvent(this, 'recordingStopped', response.id, response.name)]);
} }
/**
* @hidden
* response = {connectionId: string, streamId: string, type: string, data: Object}
*/
onFilterEventDispatched(response): void {
const connectionId: string = response.connectionId;
const streamId: string = response.streamId;
this.getConnection(connectionId, 'No connection found for connectionId ' + connectionId)
.then(connection => {
const stream: Stream = connection.stream;
stream.ee.emitEvent('filterEventDispatched', [new FilterEvent(stream, stream.filter, response.eventType, response.data)]);
this.ee.emitEvent('filterEventDispatched', [new FilterEvent(stream, stream.filter, response.eventType, response.data)]);
});
}
/** /**
* @hidden * @hidden
*/ */

View File

@ -16,8 +16,10 @@
*/ */
import { Connection } from './Connection'; import { Connection } from './Connection';
import { Event } from '../OpenViduInternal/Events/Event';
import { Session } from './Session'; import { Session } from './Session';
import { StreamManager } from './StreamManager'; import { StreamManager } from './StreamManager';
import { EventDispatcher } from '../OpenViduInternal/Interfaces/Public/EventDispatcher';
import { InboundStreamOptions } from '../OpenViduInternal/Interfaces/Private/InboundStreamOptions'; import { InboundStreamOptions } from '../OpenViduInternal/Interfaces/Private/InboundStreamOptions';
import { OutboundStreamOptions } from '../OpenViduInternal/Interfaces/Private/OutboundStreamOptions'; import { OutboundStreamOptions } from '../OpenViduInternal/Interfaces/Private/OutboundStreamOptions';
import { WebRtcPeer, WebRtcPeerSendonly, WebRtcPeerRecvonly, WebRtcPeerSendrecv } from '../OpenViduInternal/WebRtcPeer/WebRtcPeer'; import { WebRtcPeer, WebRtcPeerSendonly, WebRtcPeerRecvonly, WebRtcPeerSendrecv } from '../OpenViduInternal/WebRtcPeer/WebRtcPeer';
@ -34,7 +36,7 @@ import { OpenViduError, OpenViduErrorName } from '../OpenViduInternal/Enums/Open
* Each [[Publisher]] and [[Subscriber]] has an attribute of type Stream, as they give access * Each [[Publisher]] and [[Subscriber]] has an attribute of type Stream, as they give access
* to one of them (sending and receiving it, respectively) * to one of them (sending and receiving it, respectively)
*/ */
export class Stream { export class Stream implements EventDispatcher {
/** /**
* The Connection object that is publishing the stream * The Connection object that is publishing the stream
@ -215,6 +217,51 @@ export class Stream {
} }
/**
* See [[EventDispatcher.on]]
*/
on(type: string, handler: (event: Event) => void): EventDispatcher {
this.ee.on(type, event => {
if (event) {
console.info("Event '" + type + "' triggered by stream '" + this.streamId + "'", event);
} else {
console.info("Event '" + type + "' triggered by stream '" + this.streamId + "'");
}
handler(event);
});
return this;
}
/**
* See [[EventDispatcher.once]]
*/
once(type: string, handler: (event: Event) => void): EventDispatcher {
this.ee.once(type, event => {
if (event) {
console.info("Event '" + type + "' triggered once by stream '" + this.streamId + "'", event);
} else {
console.info("Event '" + type + "' triggered once by stream '" + this.streamId + "'");
}
handler(event);
});
return this;
}
/**
* See [[EventDispatcher.off]]
*/
off(type: string, handler?: (event: Event) => void): EventDispatcher {
if (!handler) {
this.ee.removeAllListeners(type);
} else {
this.ee.off(type, handler);
}
return this;
}
/* Hidden methods */ /* Hidden methods */
/** /**

View File

@ -17,6 +17,7 @@
import { StreamManager } from '../../OpenVidu/StreamManager'; import { StreamManager } from '../../OpenVidu/StreamManager';
import { Session } from '../../OpenVidu/Session'; import { Session } from '../../OpenVidu/Session';
import { Stream } from '../../OpenVidu/Stream';
export abstract class Event { export abstract class Event {
@ -28,7 +29,7 @@ export abstract class Event {
/** /**
* The object that dispatched the event * The object that dispatched the event
*/ */
target: Session | StreamManager; target: Session | Stream | StreamManager;
/** /**
* The type of event. This is the same string you pass as first parameter when calling method `on()` of any object implementing [[EventDispatcher]] interface * The type of event. This is the same string you pass as first parameter when calling method `on()` of any object implementing [[EventDispatcher]] interface
@ -40,7 +41,7 @@ export abstract class Event {
/** /**
* @hidden * @hidden
*/ */
constructor(cancelable: boolean, target: Session | StreamManager, type: string) { constructor(cancelable: boolean, target: Session | Stream | StreamManager, type: string) {
this.cancelable = cancelable; this.cancelable = cancelable;
this.target = target; this.target = target;
this.type = type; this.type = type;

View File

@ -0,0 +1,60 @@
/*
* (C) Copyright 2017-2018 OpenVidu (https://openvidu.io/)
*
* 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.
*
*/
import { Event } from './Event';
import { Stream } from '../../OpenVidu/Stream';
import { Filter } from '../Interfaces/Public/Filter';
/**
* Defines the following events:
* - `filterEventDispatched`: dispatched by [[Stream]]. Only triggered if `Stream.on('filterEventDispatched', event => {})` was called
*/
export class FilterEvent extends Event {
/**
* Filter affected
*/
filter: Filter;
/**
* Type of the event
*/
eventType: string;
/**
* Data of the event
*/
data: Object;
/**
* @hidden
*/
constructor(target: Stream, filter: Filter, eventType: string, data: Object) {
super(false, target, 'filterEventDispatched');
this.filter = filter;
this.eventType = eventType;
this.data = data;
}
/**
* @hidden
*/
// tslint:disable-next-line:no-empty
callDefaultBehavior() { }
}

View File

@ -22,14 +22,21 @@ export interface Filter {
/** /**
* Type of filter applied. This is the name of the remote class identifying the filter to apply in Kurento Media Server. * Type of filter applied. This is the name of the remote class identifying the filter to apply in Kurento Media Server.
* For example: `"FaceOverlayFilter"`, `"GStreamerFilter"`. If `undefined` no filter is applied to the Stream * For example: `"FaceOverlayFilter"`, `"GStreamerFilter"`.
*
* You can get this property in `*.kmd.json` files defining the Kurento filters: for GStreamerFilter that's
* [here](https://github.com/Kurento/kms-filters/blob/53a452fac71d61795952e3d2202156c6b00f6d65/src/server/interface/filters.GStreamerFilter.kmd.json#L4)
*/ */
type?: string; type?: string;
/** /**
* Parameters used to initialized the filter. * Parameters used to initialized the filter.
* These correspond to the constructor parameters used in the filter in Kurento Media Server. * These correspond to the constructor parameters used in the filter in Kurento Media Server (except for `mediaPipeline` parameter, which is never needed).
* For example: for `filter.type = "GStreamerFilter"` could be `filter.options = {"command": "pitch pitch=0.8 tempo=1.0"}` *
* For example: for `filter.type = "GStreamerFilter"` could be `filter.options = {"command": "videobalance saturation=0.0"}`
*
* You can get this property in `*.kmd.json` files defining the Kurento filters: for GStreamerFilter that's
* [here](https://github.com/Kurento/kms-filters/blob/53a452fac71d61795952e3d2202156c6b00f6d65/src/server/interface/filters.GStreamerFilter.kmd.json#L13-L31)
*/ */
options?: Object; options?: Object;

View File

@ -21,6 +21,7 @@ export { StreamEvent } from './OpenViduInternal/Events/StreamEvent';
export { StreamManagerEvent } from './OpenViduInternal/Events/StreamManagerEvent'; export { StreamManagerEvent } from './OpenViduInternal/Events/StreamManagerEvent';
export { VideoElementEvent } from './OpenViduInternal/Events/VideoElementEvent'; export { VideoElementEvent } from './OpenViduInternal/Events/VideoElementEvent';
export { StreamPropertyChangedEvent } from './OpenViduInternal/Events/StreamPropertyChangedEvent'; export { StreamPropertyChangedEvent } from './OpenViduInternal/Events/StreamPropertyChangedEvent';
export { FilterEvent } from './OpenViduInternal/Events/FilterEvent';
export { Capabilities } from './OpenViduInternal/Interfaces/Public/Capabilities'; export { Capabilities } from './OpenViduInternal/Interfaces/Public/Capabilities';
export { Device } from './OpenViduInternal/Interfaces/Public/Device'; export { Device } from './OpenViduInternal/Interfaces/Public/Device';