mirror of https://github.com/OpenVidu/openvidu.git
openvidu-browser: StreamPropertyChangedEvent
parent
a20b878d7a
commit
15d879992a
|
@ -13,8 +13,7 @@ module.exports = {
|
|||
exclude: [
|
||||
"**/OpenViduInternal/Interfaces/Private/**",
|
||||
"**/OpenViduInternal/WebRtcStats/WebRtcStats.ts",
|
||||
"**/OpenViduInternal/WebRtcPeer/WebRtcPeer.ts",
|
||||
"**/OpenViduInternal/Events/StreamPropertyChangedEvent.ts"
|
||||
"**/OpenViduInternal/WebRtcPeer/WebRtcPeer.ts"
|
||||
],
|
||||
excludeExternals: true,
|
||||
excludePrivate: true,
|
||||
|
|
|
@ -123,10 +123,13 @@ export class Connection {
|
|||
const streamOptions: InboundStreamOptions = {
|
||||
id: opts.id,
|
||||
connection: this,
|
||||
hasAudio: opts.hasAudio,
|
||||
hasVideo: opts.hasVideo,
|
||||
audioActive: opts.audioActive,
|
||||
videoActive: opts.videoActive,
|
||||
typeOfVideo: opts.typeOfVideo,
|
||||
frameRate: opts.frameRate,
|
||||
recvAudio: opts.audioActive,
|
||||
recvVideo: opts.videoActive,
|
||||
typeOfVideo: opts.typeOfVideo
|
||||
videoDimensions: !!opts.videoDimensions ? JSON.parse(opts.videoDimensions) : undefined
|
||||
};
|
||||
const stream = new Stream(this.session, streamOptions);
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@ import { LocalRecorder } from './LocalRecorder';
|
|||
import { Publisher } from './Publisher';
|
||||
import { Session } from './Session';
|
||||
import { Stream } from './Stream';
|
||||
import { StreamPropertyChangedEvent } from '../OpenViduInternal/Events/StreamPropertyChangedEvent';
|
||||
import { Device } from '../OpenViduInternal/Interfaces/Public/Device';
|
||||
import { OpenViduAdvancedConfiguration } from '../OpenViduInternal/Interfaces/Public/OpenViduAdvancedConfiguration';
|
||||
import { PublisherProperties } from '../OpenViduInternal/Interfaces/Public/PublisherProperties';
|
||||
|
@ -44,6 +45,10 @@ export class OpenVidu {
|
|||
* @hidden
|
||||
*/
|
||||
session: Session;
|
||||
/**
|
||||
* @hidden
|
||||
*/
|
||||
publishers: Publisher[] = [];
|
||||
/**
|
||||
* @hidden
|
||||
*/
|
||||
|
@ -71,6 +76,64 @@ export class OpenVidu {
|
|||
|
||||
constructor() {
|
||||
console.info("'OpenVidu' initialized");
|
||||
|
||||
if (platform.name!!.toLowerCase().indexOf('mobile') !== -1) {
|
||||
// Listen to orientationchange only on mobile browsers
|
||||
(<any>window).onorientationchange = () => {
|
||||
this.publishers.forEach(publisher => {
|
||||
if (!!publisher.stream && !!publisher.stream.hasVideo && !!publisher.stream.streamManager.videos[0]) {
|
||||
|
||||
let attempts = 0;
|
||||
|
||||
const oldWidth = publisher.stream.videoDimensions.width;
|
||||
const oldHeight = publisher.stream.videoDimensions.height;
|
||||
// New resolution got from different places for Chrome and Firefox. Chrome needs a videoWidth and videoHeight of a videoElement.
|
||||
// Firefox needs getSettings from the videoTrack
|
||||
let firefoxSettings = publisher.stream.getMediaStream().getVideoTracks()[0].getSettings();
|
||||
let newWidth = (platform.name!!.toLowerCase().indexOf('firefox') !== -1) ? firefoxSettings.width : publisher.videoReference.videoWidth;
|
||||
let newHeight = (platform.name!!.toLowerCase().indexOf('firefox') !== -1) ? firefoxSettings.height : publisher.videoReference.videoHeight;
|
||||
|
||||
const repeatUntilChange = setInterval(() => {
|
||||
firefoxSettings = publisher.stream.getMediaStream().getVideoTracks()[0].getSettings();
|
||||
newWidth = (platform.name!!.toLowerCase().indexOf('firefox') !== -1) ? firefoxSettings.width : publisher.videoReference.videoWidth;
|
||||
newHeight = (platform.name!!.toLowerCase().indexOf('firefox') !== -1) ? firefoxSettings.height : publisher.videoReference.videoHeight;
|
||||
sendStreamPropertyChangedEvent(oldWidth, oldHeight, newWidth, newHeight);
|
||||
}, 100);
|
||||
|
||||
const sendStreamPropertyChangedEvent = (oldWidth, oldHeight, newWidth, newHeight) => {
|
||||
attempts++;
|
||||
if (attempts > 4) {
|
||||
clearTimeout(repeatUntilChange);
|
||||
}
|
||||
if (newWidth !== oldWidth || newHeight !== oldHeight) {
|
||||
publisher.stream.videoDimensions = {
|
||||
width: newWidth || 0,
|
||||
height: newHeight || 0
|
||||
};
|
||||
const newValue = JSON.stringify(publisher.stream.videoDimensions);
|
||||
this.sendRequest(
|
||||
'streamPropertyChanged',
|
||||
{
|
||||
streamId: publisher.stream.streamId,
|
||||
property: 'videoDimensions',
|
||||
newValue,
|
||||
reason: 'deviceRotated'
|
||||
},
|
||||
(error, response) => {
|
||||
if (error) {
|
||||
console.error("Error sending 'streamPropertyChanged' event", error);
|
||||
} else {
|
||||
this.session.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent(this.session, publisher.stream, 'videoDimensions', newValue, { width: oldWidth, height: oldHeight }, 'deviceRotated')]);
|
||||
publisher.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent(publisher, publisher.stream, 'videoDimensions', newValue, { width: oldWidth, height: oldHeight }, 'deviceRotated')]);
|
||||
}
|
||||
});
|
||||
clearTimeout(repeatUntilChange);
|
||||
}
|
||||
};
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -163,6 +226,7 @@ export class OpenVidu {
|
|||
publisher.emitEvent('accessDenied', []);
|
||||
});
|
||||
|
||||
this.publishers.push(publisher);
|
||||
return publisher;
|
||||
}
|
||||
|
||||
|
@ -510,6 +574,7 @@ export class OpenVidu {
|
|||
recordingStarted: this.session.onRecordingStarted.bind(this.session),
|
||||
recordingStopped: this.session.onRecordingStopped.bind(this.session),
|
||||
sendMessage: this.session.onNewMessage.bind(this.session),
|
||||
streamPropertyChanged: this.session.onStreamPropertyChanged.bind(this.session),
|
||||
iceCandidate: this.session.recvIceCandidate.bind(this.session),
|
||||
mediaError: this.session.onMediaError.bind(this.session)
|
||||
}
|
||||
|
|
|
@ -23,10 +23,13 @@ import { EventDispatcher } from '../OpenViduInternal/Interfaces/Public/EventDisp
|
|||
import { PublisherProperties } from '../OpenViduInternal/Interfaces/Public/PublisherProperties';
|
||||
import { Event } from '../OpenViduInternal/Events/Event';
|
||||
import { StreamEvent } from '../OpenViduInternal/Events/StreamEvent';
|
||||
import { StreamPropertyChangedEvent } from '../OpenViduInternal/Events/StreamPropertyChangedEvent';
|
||||
import { VideoElementEvent } from '../OpenViduInternal/Events/VideoElementEvent';
|
||||
import { OpenViduError, OpenViduErrorName } from '../OpenViduInternal/Enums/OpenViduError';
|
||||
import { VideoInsertMode } from '../OpenViduInternal/Enums/VideoInsertMode';
|
||||
|
||||
import platform = require('platform');
|
||||
|
||||
|
||||
/**
|
||||
* Packs local media streams. Participants can publish it to a session. Initialized with [[OpenVidu.initPublisher]] method
|
||||
|
@ -52,47 +55,121 @@ export class Publisher extends StreamManager {
|
|||
private properties: PublisherProperties;
|
||||
private permissionDialogTimeout: NodeJS.Timer;
|
||||
|
||||
/**
|
||||
* hidden
|
||||
*/
|
||||
openvidu: OpenVidu;
|
||||
/**
|
||||
* @hidden
|
||||
*/
|
||||
constructor(targEl: string | HTMLElement, properties: PublisherProperties, private openvidu: OpenVidu) {
|
||||
videoReference: HTMLVideoElement;
|
||||
/**
|
||||
* @hidden
|
||||
*/
|
||||
screenShareResizeInterval: NodeJS.Timer;
|
||||
|
||||
/**
|
||||
* @hidden
|
||||
*/
|
||||
constructor(targEl: string | HTMLElement, properties: PublisherProperties, openvidu: OpenVidu) {
|
||||
super(new Stream((!!openvidu.session) ? openvidu.session : new Session(openvidu), { publisherProperties: properties, mediaConstraints: {} }), targEl);
|
||||
this.properties = properties;
|
||||
this.openvidu = openvidu;
|
||||
|
||||
this.stream.ee.on('local-stream-destroyed-by-disconnect', (reason: string) => {
|
||||
const streamEvent = new StreamEvent(true, this, 'streamDestroyed', this.stream, reason);
|
||||
this.ee.emitEvent('streamDestroyed', [streamEvent]);
|
||||
streamEvent.callDefaultBehaviour();
|
||||
this.emitEvent('streamDestroyed', [streamEvent]);
|
||||
streamEvent.callDefaultBehavior();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Publish or unpublish the audio stream (if available). Calling this method twice in a row passing same value will have no effect
|
||||
*
|
||||
* #### Events dispatched
|
||||
*
|
||||
* The [[Session]] object of the local participant will dispatch a `streamPropertyChanged` event with `changedProperty` set to `"audioActive"` and `reason` set to `"publishAudio"`
|
||||
* The [[Publisher]] object of the local participant will also dispatch the exact same event
|
||||
*
|
||||
* The [[Session]] object of every other participant connected to the session will dispatch a `streamPropertyChanged` event with `changedProperty` set to `"audioActive"` and `reason` set to `"publishAudio"`
|
||||
* The respective [[Subscriber]] object of every other participant receiving this Publisher's stream will also dispatch the exact same event
|
||||
*
|
||||
* See [[StreamPropertyChangedEvent]] to learn more.
|
||||
*
|
||||
* @param value `true` to publish the audio stream, `false` to unpublish it
|
||||
*/
|
||||
publishAudio(value: boolean): void {
|
||||
this.stream.getMediaStream().getAudioTracks().forEach((track) => {
|
||||
track.enabled = value;
|
||||
});
|
||||
console.info("'Publisher' has " + (value ? 'published' : 'unpublished') + ' its audio stream');
|
||||
if (this.stream.audioActive !== value) {
|
||||
this.stream.getMediaStream().getAudioTracks().forEach((track) => {
|
||||
track.enabled = value;
|
||||
});
|
||||
this.session.openvidu.sendRequest(
|
||||
'streamPropertyChanged',
|
||||
{
|
||||
streamId: this.stream.streamId,
|
||||
property: 'audioActive',
|
||||
newValue: value,
|
||||
reason: 'publishAudio'
|
||||
},
|
||||
(error, response) => {
|
||||
if (error) {
|
||||
console.error("Error sending 'streamPropertyChanged' event", error);
|
||||
} else {
|
||||
this.session.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent(this.session, this.stream, 'audioActive', value, !value, 'publishAudio')]);
|
||||
this.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent(this, this.stream, 'audioActive', value, !value, 'publishAudio')]);
|
||||
}
|
||||
});
|
||||
this.stream.audioActive = value;
|
||||
console.info("'Publisher' has " + (value ? 'published' : 'unpublished') + ' its audio stream');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Publish or unpublish the video stream (if available). Calling this method twice in a row passing same value will have no effect
|
||||
*
|
||||
* #### Events dispatched
|
||||
*
|
||||
* The [[Session]] object of the local participant will dispatch a `streamPropertyChanged` event with `changedProperty` set to `"videoActive"` and `reason` set to `"publishVideo"`
|
||||
* The [[Publisher]] object of the local participant will also dispatch the exact same event
|
||||
*
|
||||
* The [[Session]] object of every other participant connected to the session will dispatch a `streamPropertyChanged` event with `changedProperty` set to `"videoActive"` and `reason` set to `"publishVideo"`
|
||||
* The respective [[Subscriber]] object of every other participant receiving this Publisher's stream will also dispatch the exact same event
|
||||
*
|
||||
* See [[StreamPropertyChangedEvent]] to learn more.
|
||||
*
|
||||
* @param value `true` to publish the video stream, `false` to unpublish it
|
||||
*/
|
||||
publishVideo(value: boolean): void {
|
||||
this.stream.getMediaStream().getVideoTracks().forEach((track) => {
|
||||
track.enabled = value;
|
||||
});
|
||||
console.info("'Publisher' has " + (value ? 'published' : 'unpublished') + ' its video stream');
|
||||
if (this.stream.videoActive !== value) {
|
||||
this.stream.getMediaStream().getVideoTracks().forEach((track) => {
|
||||
track.enabled = value;
|
||||
});
|
||||
this.session.openvidu.sendRequest(
|
||||
'streamPropertyChanged',
|
||||
{
|
||||
streamId: this.stream.streamId,
|
||||
property: 'videoActive',
|
||||
newValue: value,
|
||||
reason: 'publishVideo'
|
||||
},
|
||||
(error, response) => {
|
||||
if (error) {
|
||||
console.error("Error sending 'streamPropertyChanged' event", error);
|
||||
} else {
|
||||
this.session.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent(this.session, this.stream, 'videoActive', value, !value, 'publishVideo')]);
|
||||
this.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent(this, this.stream, 'videoActive', value, !value, 'publishVideo')]);
|
||||
}
|
||||
});
|
||||
this.stream.videoActive = value;
|
||||
console.info("'Publisher' has " + (value ? 'published' : 'unpublished') + ' its video stream');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Call this method before [[Session.publish]] to subscribe to your Publisher's remote stream instead of using the local stream, as any other user would do.
|
||||
* Call this method before [[Session.publish]] if you prefer to subscribe to your Publisher's remote stream instead of using the local stream, as any other user would do.
|
||||
*/
|
||||
subscribeToRemote(value?: boolean): void {
|
||||
value = (value !== undefined) ? value : true;
|
||||
|
@ -108,10 +185,10 @@ export class Publisher extends StreamManager {
|
|||
super.on(type, handler);
|
||||
if (type === 'streamCreated') {
|
||||
if (!!this.stream && this.stream.isLocalStreamPublished) {
|
||||
this.ee.emitEvent('streamCreated', [new StreamEvent(false, this, 'streamCreated', this.stream, '')]);
|
||||
this.emitEvent('streamCreated', [new StreamEvent(false, this, 'streamCreated', this.stream, '')]);
|
||||
} else {
|
||||
this.stream.ee.on('stream-created-by-publisher', () => {
|
||||
this.ee.emitEvent('streamCreated', [new StreamEvent(false, this, 'streamCreated', this.stream, '')]);
|
||||
this.emitEvent('streamCreated', [new StreamEvent(false, this, 'streamCreated', this.stream, '')]);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -121,17 +198,17 @@ export class Publisher extends StreamManager {
|
|||
this.videos[0].video.paused === false &&
|
||||
this.videos[0].video.ended === false &&
|
||||
this.videos[0].video.readyState === 4) {
|
||||
this.ee.emitEvent('remoteVideoPlaying', [new VideoElementEvent(this.videos[0].video, this, 'remoteVideoPlaying')]);
|
||||
this.emitEvent('remoteVideoPlaying', [new VideoElementEvent(this.videos[0].video, this, 'remoteVideoPlaying')]);
|
||||
}
|
||||
}
|
||||
if (type === 'accessAllowed') {
|
||||
if (this.accessAllowed) {
|
||||
this.ee.emitEvent('accessAllowed');
|
||||
this.emitEvent('accessAllowed', []);
|
||||
}
|
||||
}
|
||||
if (type === 'accessDenied') {
|
||||
if (this.accessDenied) {
|
||||
this.ee.emitEvent('accessDenied');
|
||||
this.emitEvent('accessDenied', []);
|
||||
}
|
||||
}
|
||||
return this;
|
||||
|
@ -145,10 +222,10 @@ export class Publisher extends StreamManager {
|
|||
super.once(type, handler);
|
||||
if (type === 'streamCreated') {
|
||||
if (!!this.stream && this.stream.isLocalStreamPublished) {
|
||||
this.ee.emitEvent('streamCreated', [new StreamEvent(false, this, 'streamCreated', this.stream, '')]);
|
||||
this.emitEvent('streamCreated', [new StreamEvent(false, this, 'streamCreated', this.stream, '')]);
|
||||
} else {
|
||||
this.stream.ee.once('stream-created-by-publisher', () => {
|
||||
this.ee.emitEvent('streamCreated', [new StreamEvent(false, this, 'streamCreated', this.stream, '')]);
|
||||
this.emitEvent('streamCreated', [new StreamEvent(false, this, 'streamCreated', this.stream, '')]);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -158,17 +235,17 @@ export class Publisher extends StreamManager {
|
|||
this.videos[0].video.paused === false &&
|
||||
this.videos[0].video.ended === false &&
|
||||
this.videos[0].video.readyState === 4) {
|
||||
this.ee.emitEvent('remoteVideoPlaying', [new VideoElementEvent(this.videos[0].video, this, 'remoteVideoPlaying')]);
|
||||
this.emitEvent('remoteVideoPlaying', [new VideoElementEvent(this.videos[0].video, this, 'remoteVideoPlaying')]);
|
||||
}
|
||||
}
|
||||
if (type === 'accessAllowed') {
|
||||
if (this.accessAllowed) {
|
||||
this.ee.emitEvent('accessAllowed');
|
||||
this.emitEvent('accessAllowed', []);
|
||||
}
|
||||
}
|
||||
if (type === 'accessDenied') {
|
||||
if (this.accessDenied) {
|
||||
this.ee.emitEvent('accessDenied');
|
||||
this.emitEvent('accessDenied', []);
|
||||
}
|
||||
}
|
||||
return this;
|
||||
|
@ -217,14 +294,76 @@ export class Publisher extends StreamManager {
|
|||
// avoid early 'streamPlaying' event
|
||||
this.stream.updateMediaStreamInVideos();
|
||||
}
|
||||
this.stream.isLocalStreamReadyToPublish = true;
|
||||
this.stream.ee.emitEvent('stream-ready-to-publish', []);
|
||||
|
||||
if (!!this.firstVideoElement) {
|
||||
this.createVideoElement(this.firstVideoElement.targetElement, <VideoInsertMode>this.properties.insertMode);
|
||||
}
|
||||
delete this.firstVideoElement;
|
||||
|
||||
if (!this.stream.isSendScreen() && !!mediaStream.getVideoTracks()[0]) {
|
||||
// With no screen share, video dimension can be set directly from MediaStream (getSettings)
|
||||
// Orientation must be checked for mobile devices (width and height are reversed)
|
||||
const { width, height } = mediaStream.getVideoTracks()[0].getSettings();
|
||||
|
||||
if (platform.name!!.toLowerCase().indexOf('mobile') !== -1 && (window.innerHeight > window.innerWidth)) {
|
||||
// Mobile portrait mode
|
||||
this.stream.videoDimensions = {
|
||||
width: height || 0,
|
||||
height: width || 0
|
||||
};
|
||||
} else {
|
||||
this.stream.videoDimensions = {
|
||||
width: width || 0,
|
||||
height: height || 0
|
||||
};
|
||||
}
|
||||
|
||||
this.stream.isLocalStreamReadyToPublish = true;
|
||||
this.stream.ee.emitEvent('stream-ready-to-publish', []);
|
||||
} else {
|
||||
// With screen share, video dimension must be got from a video element (onloadedmetadata event)
|
||||
this.videoReference = document.createElement('video');
|
||||
this.videoReference.srcObject = mediaStream;
|
||||
this.videoReference.onloadedmetadata = () => {
|
||||
this.stream.videoDimensions = {
|
||||
width: this.videoReference.videoWidth,
|
||||
height: this.videoReference.videoHeight
|
||||
};
|
||||
this.screenShareResizeInterval = setInterval(() => {
|
||||
const firefoxSettings = mediaStream.getVideoTracks()[0].getSettings();
|
||||
const newWidth = (platform.name === 'Chrome') ? this.videoReference.videoWidth : firefoxSettings.width;
|
||||
const newHeight = (platform.name === 'Chrome') ? this.videoReference.videoHeight : firefoxSettings.height;
|
||||
if (this.stream.isLocalStreamPublished &&
|
||||
(newWidth !== this.stream.videoDimensions.width ||
|
||||
newHeight !== this.stream.videoDimensions.height)) {
|
||||
const oldValue = { width: this.stream.videoDimensions.width, height: this.stream.videoDimensions.height };
|
||||
this.stream.videoDimensions = {
|
||||
width: newWidth || 0,
|
||||
height: newHeight || 0
|
||||
};
|
||||
const newValue = JSON.stringify(this.stream.videoDimensions);
|
||||
this.session.openvidu.sendRequest(
|
||||
'streamPropertyChanged',
|
||||
{
|
||||
streamId: this.stream.streamId,
|
||||
property: 'videoDimensions',
|
||||
newValue,
|
||||
reason: 'screenResized'
|
||||
},
|
||||
(error, response) => {
|
||||
if (error) {
|
||||
console.error("Error sending 'streamPropertyChanged' event", error);
|
||||
} else {
|
||||
this.session.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent(this.session, this.stream, 'videoDimensions', newValue, oldValue, 'screenResized')]);
|
||||
this.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent(this, this.stream, 'videoDimensions', newValue, oldValue, 'screenResized')]);
|
||||
}
|
||||
});
|
||||
}
|
||||
}, 500);
|
||||
this.stream.isLocalStreamReadyToPublish = true;
|
||||
this.stream.ee.emitEvent('stream-ready-to-publish', []);
|
||||
};
|
||||
}
|
||||
resolve();
|
||||
};
|
||||
|
||||
|
@ -371,13 +510,6 @@ export class Publisher extends StreamManager {
|
|||
this.stream.session = session;
|
||||
}
|
||||
|
||||
/**
|
||||
* @hidden
|
||||
*/
|
||||
emitEvent(type: string, eventArray: any[]): void {
|
||||
this.ee.emitEvent(type, eventArray);
|
||||
}
|
||||
|
||||
/**
|
||||
* @hidden
|
||||
*/
|
||||
|
@ -392,7 +524,7 @@ export class Publisher extends StreamManager {
|
|||
|
||||
private setPermissionDialogTimer(waitTime: number): void {
|
||||
this.permissionDialogTimeout = setTimeout(() => {
|
||||
this.ee.emitEvent('accessDialogOpened', []);
|
||||
this.emitEvent('accessDialogOpened', []);
|
||||
}, waitTime);
|
||||
}
|
||||
|
||||
|
@ -400,7 +532,7 @@ export class Publisher extends StreamManager {
|
|||
clearTimeout(this.permissionDialogTimeout);
|
||||
if ((Date.now() - startTime) > waitTime) {
|
||||
// Permission dialog was shown and now is closed
|
||||
this.ee.emitEvent('accessDialogClosed', []);
|
||||
this.emitEvent('accessDialogClosed', []);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -33,6 +33,7 @@ import { RecordingEvent } from '../OpenViduInternal/Events/RecordingEvent';
|
|||
import { SessionDisconnectedEvent } from '../OpenViduInternal/Events/SessionDisconnectedEvent';
|
||||
import { SignalEvent } from '../OpenViduInternal/Events/SignalEvent';
|
||||
import { StreamEvent } from '../OpenViduInternal/Events/StreamEvent';
|
||||
import { StreamPropertyChangedEvent } from '../OpenViduInternal/Events/StreamPropertyChangedEvent';
|
||||
import { OpenViduError, OpenViduErrorName } from '../OpenViduInternal/Enums/OpenViduError';
|
||||
import { VideoInsertMode } from '../OpenViduInternal/Enums/VideoInsertMode';
|
||||
|
||||
|
@ -156,20 +157,20 @@ export class Session implements EventDispatcher {
|
|||
* This event will automatically unsubscribe the leaving participant from every Subscriber object of the session (this includes closing the WebRTCPeer connection and disposing all MediaStreamTracks)
|
||||
* and also deletes any HTML video element associated to each Subscriber (only those [created by OpenVidu Browser](/docs/how-do-i/manage-videos/#let-openvidu-take-care-of-the-video-players)).
|
||||
* For every video removed, each Subscriber object will dispatch a `videoElementDestroyed` event.
|
||||
* Call `event.preventDefault()` uppon event `sessionDisconnected` to avoid this behaviour and take care of disposing and cleaning all the Subscriber objects yourself.
|
||||
* Call `event.preventDefault()` upon event `sessionDisconnected` to avoid this behavior and take care of disposing and cleaning all the Subscriber objects yourself.
|
||||
* See [[SessionDisconnectedEvent]] and [[VideoElementEvent]] to learn more to learn more.
|
||||
*
|
||||
* The [[Publisher]] object of the local participant will dispatch a `streamDestroyed` event if there is a [[Publisher]] object publishing to the session.
|
||||
* This event will automatically stop all media tracks and delete any HTML video element associated to it (only those [created by OpenVidu Browser](/docs/how-do-i/manage-videos/#let-openvidu-take-care-of-the-video-players)).
|
||||
* For every video removed, the Publisher object will dispatch a `videoElementDestroyed` event.
|
||||
* Call `event.preventDefault()` uppon event `streamDestroyed` if you want to clean the Publisher object on your own or re-publish it in a different Session (to do so it is a mandatory requirement to call `Session.unpublish()`
|
||||
* Call `event.preventDefault()` upon event `streamDestroyed` if you want to clean the Publisher object on your own or re-publish it in a different Session (to do so it is a mandatory requirement to call `Session.unpublish()`
|
||||
* or/and `Session.disconnect()` in the previous session). See [[StreamEvent]] and [[VideoElementEvent]] to learn more.
|
||||
*
|
||||
* The [[Session]] object of every other participant connected to the session will dispatch a `streamDestroyed` event if the disconnected participant was publishing.
|
||||
* This event will automatically unsubscribe the Subscriber object from the session (this includes closing the WebRTCPeer connection and disposing all MediaStreamTracks)
|
||||
* and also deletes any HTML video element associated to that Subscriber (only those [created by OpenVidu Browser](/docs/how-do-i/manage-videos/#let-openvidu-take-care-of-the-video-players)).
|
||||
* For every video removed, the Subscriber object will dispatch a `videoElementDestroyed` event.
|
||||
* Call `event.preventDefault()` uppon event `streamDestroyed` to avoid this default behaviour and take care of disposing and cleaning the Subscriber object yourself.
|
||||
* Call `event.preventDefault()` upon event `streamDestroyed` to avoid this default behavior and take care of disposing and cleaning the Subscriber object yourself.
|
||||
* See [[StreamEvent]] and [[VideoElementEvent]] to learn more.
|
||||
*
|
||||
* The [[Session]] object of every other participant connected to the session will dispatch a `connectionDestroyed` event in any case. See [[ConnectionEvent]] to learn more.
|
||||
|
@ -362,13 +363,13 @@ export class Session implements EventDispatcher {
|
|||
* This event will automatically stop all media tracks and delete any HTML video element associated to this Publisher
|
||||
* (only those videos [created by OpenVidu Browser](/docs/how-do-i/manage-videos/#let-openvidu-take-care-of-the-video-players)).
|
||||
* For every video removed, the Publisher object will dispatch a `videoElementDestroyed` event.
|
||||
* Call `event.preventDefault()` uppon event `streamDestroyed` if you want to clean the Publisher object on your own or re-publish it in a different Session.
|
||||
* Call `event.preventDefault()` upon event `streamDestroyed` if you want to clean the Publisher object on your own or re-publish it in a different Session.
|
||||
*
|
||||
* The [[Session]] object of every other participant connected to the session will dispatch a `streamDestroyed` event.
|
||||
* This event will automatically unsubscribe the Subscriber object from the session (this includes closing the WebRTCPeer connection and disposing all MediaStreamTracks) and
|
||||
* delete any HTML video element associated to it (only those [created by OpenVidu Browser](/docs/how-do-i/manage-videos/#let-openvidu-take-care-of-the-video-players)).
|
||||
* For every video removed, the Subscriber object will dispatch a `videoElementDestroyed` event.
|
||||
* Call `event.preventDefault()` uppon event `streamDestroyed` to avoid this default behaviour and take care of disposing and cleaning the Subscriber object on your own.
|
||||
* Call `event.preventDefault()` upon event `streamDestroyed` to avoid this default behavior and take care of disposing and cleaning the Subscriber object on your own.
|
||||
*
|
||||
* See [[StreamEvent]] and [[VideoElementEvent]] to learn more.
|
||||
*/
|
||||
|
@ -400,7 +401,7 @@ export class Session implements EventDispatcher {
|
|||
|
||||
const streamEvent = new StreamEvent(true, publisher, 'streamDestroyed', publisher.stream, 'unpublish');
|
||||
publisher.emitEvent('streamDestroyed', [streamEvent]);
|
||||
streamEvent.callDefaultBehaviour();
|
||||
streamEvent.callDefaultBehavior();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -566,7 +567,7 @@ export class Session implements EventDispatcher {
|
|||
|
||||
const streamEvent = new StreamEvent(true, this, 'streamDestroyed', stream, msg.reason);
|
||||
this.ee.emitEvent('streamDestroyed', [streamEvent]);
|
||||
streamEvent.callDefaultBehaviour();
|
||||
streamEvent.callDefaultBehavior();
|
||||
|
||||
delete this.remoteStreamsCreated[stream.streamId];
|
||||
}
|
||||
|
@ -629,7 +630,7 @@ export class Session implements EventDispatcher {
|
|||
|
||||
const streamEvent = new StreamEvent(true, this, 'streamDestroyed', connection.stream, msg.reason);
|
||||
this.ee.emitEvent('streamDestroyed', [streamEvent]);
|
||||
streamEvent.callDefaultBehaviour();
|
||||
streamEvent.callDefaultBehavior();
|
||||
|
||||
// Deleting the remote stream
|
||||
const streamId: string = connection.stream.streamId;
|
||||
|
@ -654,7 +655,7 @@ export class Session implements EventDispatcher {
|
|||
|
||||
const streamEvent = new StreamEvent(true, this, 'streamDestroyed', stream, 'forceDisconnect');
|
||||
this.ee.emitEvent('streamDestroyed', [streamEvent]);
|
||||
streamEvent.callDefaultBehaviour();
|
||||
streamEvent.callDefaultBehavior();
|
||||
|
||||
delete this.remoteStreamsCreated[stream.streamId];
|
||||
}
|
||||
|
@ -686,6 +687,46 @@ export class Session implements EventDispatcher {
|
|||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @hidden
|
||||
*/
|
||||
onStreamPropertyChanged(msg): void {
|
||||
this.getRemoteConnection(msg.connectionId, 'Remote connection ' + msg.connectionId + " unknown when 'onStreamPropertyChanged'. " +
|
||||
'Existing remote connections: ' + JSON.stringify(Object.keys(this.remoteConnections)))
|
||||
|
||||
.then(connection => {
|
||||
if (!!connection.stream && connection.stream.streamId === msg.streamId) {
|
||||
const stream = connection.stream;
|
||||
let oldValue;
|
||||
switch (msg.property) {
|
||||
case 'audioActive':
|
||||
oldValue = stream.audioActive;
|
||||
msg.newValue = msg.newValue === 'true';
|
||||
stream.audioActive = msg.newValue;
|
||||
break;
|
||||
case 'videoActive':
|
||||
oldValue = stream.videoActive;
|
||||
msg.newValue = msg.newValue === 'true';
|
||||
stream.videoActive = msg.newValue;
|
||||
break;
|
||||
case 'videoDimensions':
|
||||
oldValue = stream.videoDimensions;
|
||||
msg.newValue = JSON.parse(JSON.parse(msg.newValue));
|
||||
stream.videoDimensions = msg.newValue;
|
||||
break;
|
||||
}
|
||||
|
||||
this.ee.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent(this, stream, msg.property, msg.newValue, oldValue, msg.reason)]);
|
||||
stream.streamManager.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent(stream.streamManager, stream, msg.property, msg.newValue, oldValue, msg.reason)]);
|
||||
} else {
|
||||
console.error("No stream with streamId '" + msg.streamId + "' found for connection '" + msg.connectionId + "' on 'streamPropertyChanged' event");
|
||||
}
|
||||
})
|
||||
.catch(openViduError => {
|
||||
console.error(openViduError);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @hidden
|
||||
*/
|
||||
|
@ -818,7 +859,7 @@ export class Session implements EventDispatcher {
|
|||
// Make Session object dispatch 'sessionDisconnected' event (if it is not already disposed)
|
||||
const sessionDisconnectEvent = new SessionDisconnectedEvent(this, reason);
|
||||
this.ee.emitEvent('sessionDisconnected', [sessionDisconnectEvent]);
|
||||
sessionDisconnectEvent.callDefaultBehaviour();
|
||||
sessionDisconnectEvent.callDefaultBehavior();
|
||||
}
|
||||
} else {
|
||||
console.warn('You were not connected to the session ' + this.sessionId);
|
||||
|
@ -952,7 +993,7 @@ export class Session implements EventDispatcher {
|
|||
{ urls: [stunUrl] },
|
||||
{ urls: [turnUrl1, turnUrl2], username: turnUsername, credential: turnCredential }
|
||||
];
|
||||
console.log('TURN temp credentials [' + turnUsername + ':' + turnCredential + ']')
|
||||
console.log('TURN temp credentials [' + turnUsername + ':' + turnCredential + ']');
|
||||
}
|
||||
if (!!role) {
|
||||
this.openvidu.role = role;
|
||||
|
|
|
@ -56,13 +56,30 @@ export class Stream {
|
|||
*/
|
||||
hasAudio: boolean;
|
||||
|
||||
/**
|
||||
* Whether the stream has the video track muted or unmuted. If [[hasVideo]] is false, this property is undefined.
|
||||
*
|
||||
* This property may change if the Publisher publishing the stream calls [[Publisher.publishVideo]]. Whenever this happens a [[StreamPropertyChangedEvent]] will be dispatched
|
||||
* by the Session object as well as by the affected Subscriber/Publisher object
|
||||
*/
|
||||
videoActive: boolean;
|
||||
|
||||
/**
|
||||
* Whether the stream has the audio track muted or unmuted. If [[hasAudio]] is false, this property is undefined
|
||||
*
|
||||
* This property may change if the Publisher publishing the stream calls [[Publisher.publishAudio]]. Whenever this happens a [[StreamPropertyChangedEvent]] will be dispatched
|
||||
* by the Session object as well as by the affected Subscriber/Publisher object
|
||||
*/
|
||||
audioActive: boolean;
|
||||
|
||||
/**
|
||||
* Unique identifier of the stream
|
||||
*/
|
||||
streamId: string;
|
||||
|
||||
/**
|
||||
* `"CAMERA"` or `"SCREEN"`. *undefined* if stream is audio-only
|
||||
* `"CAMERA"`, `"SCREEN"` or `"CUSTOM"` (the latter when [[PublisherProperties.videoSource]] is a MediaStreamTrack when calling [[OpenVidu.initPublisher]]).
|
||||
* If [[hasVideo]] is false, this property is undefined
|
||||
*/
|
||||
typeOfVideo?: string;
|
||||
|
||||
|
@ -71,6 +88,17 @@ export class Stream {
|
|||
*/
|
||||
streamManager: StreamManager;
|
||||
|
||||
/**
|
||||
* Width and height in pixels of the encoded video stream. If [[hasVideo]] is false, this property is undefined
|
||||
*
|
||||
* This property may change if the Publisher that is publishing:
|
||||
* - If it is a mobile device, whenever the user rotates the device.
|
||||
* - If it is screen-sharing, whenever the user changes the size of the captured window.
|
||||
*
|
||||
* Whenever this happens a [[StreamPropertyChangedEvent]] will be dispatched by the Session object as well as by the affected Subscriber/Publisher object
|
||||
*/
|
||||
videoDimensions: { width: number, height: number };
|
||||
|
||||
/**
|
||||
* @hidden
|
||||
*/
|
||||
|
@ -119,26 +147,36 @@ export class Stream {
|
|||
// InboundStreamOptions: stream belongs to a Subscriber
|
||||
this.inboundStreamOpts = <InboundStreamOptions>options;
|
||||
this.streamId = this.inboundStreamOpts.id;
|
||||
this.hasAudio = this.inboundStreamOpts.recvAudio;
|
||||
this.hasVideo = this.inboundStreamOpts.recvVideo;
|
||||
this.typeOfVideo = (!this.inboundStreamOpts.typeOfVideo) ? undefined : this.inboundStreamOpts.typeOfVideo;
|
||||
this.frameRate = (this.inboundStreamOpts.frameRate === -1) ? undefined : this.inboundStreamOpts.frameRate;
|
||||
this.hasAudio = this.inboundStreamOpts.hasAudio;
|
||||
this.hasVideo = this.inboundStreamOpts.hasVideo;
|
||||
if (this.hasAudio) {
|
||||
this.audioActive = this.inboundStreamOpts.audioActive;
|
||||
}
|
||||
if (this.hasVideo) {
|
||||
this.videoActive = this.inboundStreamOpts.videoActive;
|
||||
this.typeOfVideo = (!this.inboundStreamOpts.typeOfVideo) ? undefined : this.inboundStreamOpts.typeOfVideo;
|
||||
this.frameRate = (this.inboundStreamOpts.frameRate === -1) ? undefined : this.inboundStreamOpts.frameRate;
|
||||
this.videoDimensions = this.inboundStreamOpts.videoDimensions;
|
||||
}
|
||||
} else {
|
||||
// OutboundStreamOptions: stream belongs to a Publisher
|
||||
this.outboundStreamOpts = <OutboundStreamOptions>options;
|
||||
|
||||
if (this.isSendVideo()) {
|
||||
if (this.isSendScreen()) {
|
||||
this.typeOfVideo = 'SCREEN';
|
||||
} else {
|
||||
this.typeOfVideo = 'CAMERA';
|
||||
}
|
||||
this.frameRate = this.outboundStreamOpts.publisherProperties.frameRate;
|
||||
} else {
|
||||
delete this.typeOfVideo;
|
||||
}
|
||||
this.hasAudio = this.isSendAudio();
|
||||
this.hasVideo = this.isSendVideo();
|
||||
|
||||
if (this.hasAudio) {
|
||||
this.audioActive = !!this.outboundStreamOpts.publisherProperties.publishAudio;
|
||||
}
|
||||
if (this.hasVideo) {
|
||||
this.videoActive = !!this.outboundStreamOpts.publisherProperties.publishVideo;
|
||||
this.frameRate = this.outboundStreamOpts.publisherProperties.frameRate;
|
||||
if (this.outboundStreamOpts.publisherProperties.videoSource instanceof MediaStreamTrack) {
|
||||
this.typeOfVideo = 'CUSTOM';
|
||||
} else {
|
||||
this.typeOfVideo = this.isSendScreen() ? 'SCREEN' : 'CAMERA';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.ee.on('mediastream-updated', () => {
|
||||
|
@ -410,13 +448,21 @@ export class Stream {
|
|||
console.debug('Sending SDP offer to publish as '
|
||||
+ this.streamId, sdpOfferParam);
|
||||
|
||||
let typeOfVideo = '';
|
||||
if (this.isSendVideo()) {
|
||||
typeOfVideo = this.outboundStreamOpts.publisherProperties.videoSource instanceof MediaStreamTrack ? 'CUSTOM' : (this.isSendScreen() ? 'SCREEN' : 'CAMERA');
|
||||
}
|
||||
|
||||
this.session.openvidu.sendRequest('publishVideo', {
|
||||
sdpOffer: sdpOfferParam,
|
||||
doLoopback: this.displayMyRemote() || false,
|
||||
audioActive: this.isSendAudio(),
|
||||
videoActive: this.isSendVideo(),
|
||||
typeOfVideo: ((this.isSendVideo()) ? (this.isSendScreen() ? 'SCREEN' : 'CAMERA') : ''),
|
||||
frameRate: !!this.frameRate ? this.frameRate : -1
|
||||
hasAudio: this.isSendAudio(),
|
||||
hasVideo: this.isSendVideo(),
|
||||
audioActive: this.audioActive,
|
||||
videoActive: this.videoActive,
|
||||
typeOfVideo,
|
||||
frameRate: !!this.frameRate ? this.frameRate : -1,
|
||||
videoDimensions: JSON.stringify(this.videoDimensions)
|
||||
}, (error, response) => {
|
||||
if (error) {
|
||||
reject('Error on publishVideo: ' + JSON.stringify(error));
|
||||
|
@ -426,7 +472,7 @@ export class Stream {
|
|||
this.streamId = response.id;
|
||||
this.isLocalStreamPublished = true;
|
||||
if (this.displayMyRemote()) {
|
||||
this.remotePeerSuccesfullyEstablished();
|
||||
this.remotePeerSuccessfullyEstablished();
|
||||
}
|
||||
this.ee.emitEvent('stream-created-by-publisher');
|
||||
this.initWebRtcStats();
|
||||
|
@ -457,8 +503,8 @@ export class Stream {
|
|||
return new Promise((resolve, reject) => {
|
||||
|
||||
const offerConstraints = {
|
||||
audio: this.inboundStreamOpts.recvAudio,
|
||||
video: this.inboundStreamOpts.recvVideo
|
||||
audio: this.inboundStreamOpts.hasAudio,
|
||||
video: this.inboundStreamOpts.hasVideo
|
||||
};
|
||||
console.debug("'Session.subscribe(Stream)' called. Constraints of generate SDP offer",
|
||||
offerConstraints);
|
||||
|
@ -480,7 +526,7 @@ export class Stream {
|
|||
reject(new Error('Error on recvVideoFrom: ' + JSON.stringify(error)));
|
||||
} else {
|
||||
this.webRtcPeer.processAnswer(response.sdpAnswer).then(() => {
|
||||
this.remotePeerSuccesfullyEstablished();
|
||||
this.remotePeerSuccessfullyEstablished();
|
||||
this.initWebRtcStats();
|
||||
resolve();
|
||||
}).catch(error => {
|
||||
|
@ -501,7 +547,7 @@ export class Stream {
|
|||
});
|
||||
}
|
||||
|
||||
private remotePeerSuccesfullyEstablished(): void {
|
||||
private remotePeerSuccessfullyEstablished(): void {
|
||||
this.mediaStream = this.webRtcPeer.pc.getRemoteStreams()[0];
|
||||
console.debug('Peer remote stream', this.mediaStream);
|
||||
|
||||
|
|
|
@ -139,9 +139,9 @@ export class StreamManager implements EventDispatcher {
|
|||
on(type: string, handler: (event: Event) => void): EventDispatcher {
|
||||
this.ee.on(type, event => {
|
||||
if (event) {
|
||||
console.info("Event '" + type + "' triggered", event);
|
||||
console.info("Event '" + type + "' triggered by '" + (this.remote ? 'Subscriber' : 'Publisher') + "'", event);
|
||||
} else {
|
||||
console.info("Event '" + type + "' triggered");
|
||||
console.info("Event '" + type + "' triggered by '" + (this.remote ? 'Subscriber' : 'Publisher') + "'");
|
||||
}
|
||||
handler(event);
|
||||
});
|
||||
|
@ -399,6 +399,13 @@ export class StreamManager implements EventDispatcher {
|
|||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @hidden
|
||||
*/
|
||||
emitEvent(type: string, eventArray: any[]): void {
|
||||
this.ee.emitEvent(type, eventArray);
|
||||
}
|
||||
|
||||
private pushNewStreamManagerVideo(streamManagerVideo: StreamManagerVideo) {
|
||||
this.videos.push(streamManagerVideo);
|
||||
this.addPlayEventToFirstVideo();
|
||||
|
|
|
@ -22,49 +22,49 @@ export enum OpenViduErrorName {
|
|||
|
||||
/**
|
||||
* Browser is not supported by OpenVidu.
|
||||
* Returned uppon unsuccessful [[Session.connect]]
|
||||
* Returned upon unsuccessful [[Session.connect]]
|
||||
*/
|
||||
BROWSER_NOT_SUPPORTED = 'BROWSER_NOT_SUPPORTED',
|
||||
|
||||
/**
|
||||
* The user hasn't granted permissions to the required input device when the browser asked for them.
|
||||
* Returned uppon unsuccessful [[OpenVidu.initPublisher]] or [[OpenVidu.getUserMedia]]
|
||||
* Returned upon unsuccessful [[OpenVidu.initPublisher]] or [[OpenVidu.getUserMedia]]
|
||||
*/
|
||||
DEVICE_ACCESS_DENIED = 'DEVICE_ACCESS_DENIED',
|
||||
|
||||
/**
|
||||
* The user hasn't granted permissions to capture some desktop screen when the browser asked for them.
|
||||
* Returned uppon unsuccessful [[OpenVidu.initPublisher]] or [[OpenVidu.getUserMedia]]
|
||||
* Returned upon unsuccessful [[OpenVidu.initPublisher]] or [[OpenVidu.getUserMedia]]
|
||||
*/
|
||||
SCREEN_CAPTURE_DENIED = 'SCREEN_CAPTURE_DENIED',
|
||||
|
||||
/**
|
||||
* Browser does not support screen sharing.
|
||||
* Returned uppon unsuccessful [[OpenVidu.initPublisher]]
|
||||
* Returned upon unsuccessful [[OpenVidu.initPublisher]]
|
||||
*/
|
||||
SCREEN_SHARING_NOT_SUPPORTED = 'SCREEN_SHARING_NOT_SUPPORTED',
|
||||
|
||||
/**
|
||||
* Only for Chrome, there's no screen sharing extension installed
|
||||
* Returned uppon unsuccessful [[OpenVidu.initPublisher]]
|
||||
* Returned upon unsuccessful [[OpenVidu.initPublisher]]
|
||||
*/
|
||||
SCREEN_EXTENSION_NOT_INSTALLED = 'SCREEN_EXTENSION_NOT_INSTALLED',
|
||||
|
||||
/**
|
||||
* Only for Chrome, the screen sharing extension is installed but is disabled
|
||||
* Returned uppon unsuccessful [[OpenVidu.initPublisher]]
|
||||
* Returned upon unsuccessful [[OpenVidu.initPublisher]]
|
||||
*/
|
||||
SCREEN_EXTENSION_DISABLED = 'SCREEN_EXTENSION_DISABLED',
|
||||
|
||||
/**
|
||||
* No video input device found with the provided deviceId (property [[PublisherProperties.videoSource]])
|
||||
* Returned uppon unsuccessful [[OpenVidu.initPublisher]]
|
||||
* Returned upon unsuccessful [[OpenVidu.initPublisher]]
|
||||
*/
|
||||
INPUT_VIDEO_DEVICE_NOT_FOUND = 'INPUT_VIDEO_DEVICE_NOT_FOUND',
|
||||
|
||||
/**
|
||||
* No audio input device found with the provided deviceId (property [[PublisherProperties.audioSource]])
|
||||
* Returned uppon unsuccessful [[OpenVidu.initPublisher]]
|
||||
* Returned upon unsuccessful [[OpenVidu.initPublisher]]
|
||||
*/
|
||||
INPUT_AUDIO_DEVICE_NOT_FOUND = 'INPUT_AUDIO_DEVICE_NOT_FOUND',
|
||||
|
||||
|
@ -77,7 +77,7 @@ export enum OpenViduErrorName {
|
|||
/**
|
||||
* Some media property of [[PublisherProperties]] such as `frameRate` or `resolution` is not supported
|
||||
* by the input devices (whenever it is possible they are automatically adjusted to the most similar value).
|
||||
* Returned uppon unsuccessful [[OpenVidu.initPublisher]]
|
||||
* Returned upon unsuccessful [[OpenVidu.initPublisher]]
|
||||
*/
|
||||
PUBLISHER_PROPERTIES_ERROR = 'PUBLISHER_PROPERTIES_ERROR',
|
||||
|
||||
|
|
|
@ -54,6 +54,6 @@ export class ConnectionEvent extends Event {
|
|||
* @hidden
|
||||
*/
|
||||
// tslint:disable-next-line:no-empty
|
||||
callDefaultBehaviour() { }
|
||||
callDefaultBehavior() { }
|
||||
|
||||
}
|
|
@ -21,7 +21,7 @@ import { Session } from '../../OpenVidu/Session';
|
|||
export abstract class Event {
|
||||
|
||||
/**
|
||||
* Whether the event has a default behaviour that may be prevented by calling [[Event.preventDefault]]
|
||||
* Whether the event has a default behavior that may be prevented by calling [[Event.preventDefault]]
|
||||
*/
|
||||
cancelable: boolean;
|
||||
|
||||
|
@ -54,7 +54,7 @@ export abstract class Event {
|
|||
}
|
||||
|
||||
/**
|
||||
* Prevents the default behaviour of the event. The following events have a default behaviour:
|
||||
* Prevents the default behavior of the event. The following events have a default behavior:
|
||||
*
|
||||
* - `sessionDisconnected`: dispatched by [[Session]] object, automatically unsubscribes the leaving participant from every Subscriber object of the session (this includes closing the WebRTCPeer connection and disposing all MediaStreamTracks)
|
||||
* and also deletes any HTML video element associated to each Subscriber (only those created by OpenVidu Browser, either by passing a valid parameter as `targetElement` in method [[Session.subscribe]] or
|
||||
|
@ -69,10 +69,10 @@ export abstract class Event {
|
|||
*/
|
||||
preventDefault() {
|
||||
// tslint:disable-next-line:no-empty
|
||||
this.callDefaultBehaviour = () => { };
|
||||
this.callDefaultBehavior = () => { };
|
||||
this.hasBeenPrevented = true;
|
||||
}
|
||||
|
||||
protected abstract callDefaultBehaviour();
|
||||
protected abstract callDefaultBehavior();
|
||||
|
||||
}
|
|
@ -57,6 +57,6 @@ export class PublisherSpeakingEvent extends Event {
|
|||
* @hidden
|
||||
*/
|
||||
// tslint:disable-next-line:no-empty
|
||||
callDefaultBehaviour() { }
|
||||
callDefaultBehavior() { }
|
||||
|
||||
}
|
|
@ -56,6 +56,6 @@ export class RecordingEvent extends Event {
|
|||
* @hidden
|
||||
*/
|
||||
// tslint:disable-next-line:no-empty
|
||||
callDefaultBehaviour() { }
|
||||
callDefaultBehavior() { }
|
||||
|
||||
}
|
|
@ -41,9 +41,9 @@ export class SessionDisconnectedEvent extends Event {
|
|||
/**
|
||||
* @hidden
|
||||
*/
|
||||
callDefaultBehaviour() {
|
||||
callDefaultBehavior() {
|
||||
|
||||
console.info("Calling default behaviour upon '" + this.type + "' event dispatched by 'Session'");
|
||||
console.info("Calling default behavior upon '" + this.type + "' event dispatched by 'Session'");
|
||||
|
||||
const session = <Session>this.target;
|
||||
|
||||
|
|
|
@ -60,6 +60,6 @@ export class SignalEvent extends Event {
|
|||
* @hidden
|
||||
*/
|
||||
// tslint:disable-next-line:no-empty
|
||||
callDefaultBehaviour() { }
|
||||
callDefaultBehavior() { }
|
||||
|
||||
}
|
|
@ -55,17 +55,27 @@ export class StreamEvent extends Event {
|
|||
/**
|
||||
* @hidden
|
||||
*/
|
||||
callDefaultBehaviour() {
|
||||
callDefaultBehavior() {
|
||||
if (this.type === 'streamDestroyed') {
|
||||
|
||||
if (this.target instanceof Session) {
|
||||
// Remote Stream
|
||||
console.info("Calling default behaviour upon '" + this.type + "' event dispatched by 'Session'");
|
||||
console.info("Calling default behavior upon '" + this.type + "' event dispatched by 'Session'");
|
||||
this.stream.disposeWebRtcPeer();
|
||||
} else if (this.target instanceof Publisher) {
|
||||
// Local Stream
|
||||
console.info("Calling default behaviour upon '" + this.type + "' event dispatched by 'Publisher'");
|
||||
console.info("Calling default behavior upon '" + this.type + "' event dispatched by 'Publisher'");
|
||||
clearInterval((<Publisher>this.target).screenShareResizeInterval);
|
||||
this.stream.isLocalStreamReadyToPublish = false;
|
||||
|
||||
// Delete Publisher object from OpenVidu publishers array
|
||||
const openviduPublishers = (<Publisher>this.target).openvidu.publishers;
|
||||
for (let i = 0; i < openviduPublishers.length; i++) {
|
||||
if (openviduPublishers[i] === (<Publisher>this.target)) {
|
||||
openviduPublishers.splice(i, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Dispose the MediaStream local object
|
||||
|
|
|
@ -35,6 +35,6 @@ export class StreamManagerEvent extends Event {
|
|||
* @hidden
|
||||
*/
|
||||
// tslint:disable-next-line:no-empty
|
||||
callDefaultBehaviour() { }
|
||||
callDefaultBehavior() { }
|
||||
|
||||
}
|
|
@ -18,47 +18,59 @@
|
|||
import { Event } from './Event';
|
||||
import { Session } from '../../OpenVidu/Session';
|
||||
import { Stream } from '../../OpenVidu/Stream';
|
||||
import { StreamManager } from '../../OpenVidu/StreamManager';
|
||||
|
||||
/**
|
||||
* Defines event `streamPropertyChangedEvent` dispatched by [[Session]]
|
||||
* Defines event `streamPropertyChanged` dispatched by [[Session]] as well as by [[StreamManager]] ([[Publisher]] and [[Subscriber]]).
|
||||
* This event is fired when any remote stream (owned by a Subscriber) or local stream (owned by a Publisher) undergoes
|
||||
* any change in any of its mutable properties (see [[changedProperty]]).
|
||||
*/
|
||||
export class StreamPropertyChangedEvent extends Event {
|
||||
|
||||
/**
|
||||
* The Stream whose property has changed
|
||||
* The Stream whose property has changed. You can always identify the user publishing the changed stream by consulting property [[Stream.connection]]
|
||||
*/
|
||||
stream: Stream;
|
||||
|
||||
/**
|
||||
* The property of the stream that changed. This value is either `"hasAudio"`, `"hasVideo"` or `"videoDimensions"`
|
||||
* The property of the stream that changed. This value is either `"videoActive"`, `"audioActive"` or `"videoDimensions"`
|
||||
*/
|
||||
changedProperty: string;
|
||||
|
||||
/**
|
||||
* New value of the property (before change)
|
||||
* Cause of the change on the stream's property:
|
||||
* - For `videoActive`: `"publishVideo"`
|
||||
* - For `audioActive`: `"publishAudio"`
|
||||
* - For `videoDimensions`: `"deviceRotated"` or `"screenResized"`
|
||||
*/
|
||||
reason: string;
|
||||
|
||||
/**
|
||||
* New value of the property (after change, current value)
|
||||
*/
|
||||
newValue: Object;
|
||||
|
||||
/**
|
||||
* Previous value of the property (after change)
|
||||
* Previous value of the property (before change)
|
||||
*/
|
||||
oldValue: Object;
|
||||
|
||||
/**
|
||||
* @hidden
|
||||
*/
|
||||
constructor(target: Session, stream: Stream, changedProperty: string, newValue: Object, oldValue: Object) {
|
||||
super(false, target, 'streamPropertyChangedEvent');
|
||||
constructor(target: Session | StreamManager, stream: Stream, changedProperty: string, newValue: Object, oldValue: Object, reason: string) {
|
||||
super(false, target, 'streamPropertyChanged');
|
||||
this.stream = stream;
|
||||
this.changedProperty = changedProperty;
|
||||
this.newValue = newValue;
|
||||
this.oldValue = oldValue;
|
||||
this.reason = reason;
|
||||
}
|
||||
|
||||
/**
|
||||
* @hidden
|
||||
*/
|
||||
// tslint:disable-next-line:no-empty
|
||||
callDefaultBehaviour() { }
|
||||
callDefaultBehavior() { }
|
||||
|
||||
}
|
|
@ -44,6 +44,6 @@ export class VideoElementEvent extends Event {
|
|||
* @hidden
|
||||
*/
|
||||
// tslint:disable-next-line:no-empty
|
||||
callDefaultBehaviour() { }
|
||||
callDefaultBehavior() { }
|
||||
|
||||
}
|
|
@ -20,8 +20,11 @@ import { Connection } from '../../../OpenVidu/Connection';
|
|||
export interface InboundStreamOptions {
|
||||
id: string;
|
||||
connection: Connection;
|
||||
frameRate: number;
|
||||
recvAudio: boolean;
|
||||
recvVideo: boolean;
|
||||
hasAudio: boolean;
|
||||
hasVideo: boolean;
|
||||
audioActive: boolean;
|
||||
videoActive: boolean;
|
||||
typeOfVideo: string;
|
||||
frameRate: number;
|
||||
videoDimensions: { width: number, height: number };
|
||||
}
|
|
@ -17,8 +17,11 @@
|
|||
|
||||
export interface StreamOptionsServer {
|
||||
id: string;
|
||||
hasAudio: boolean;
|
||||
hasVideo: boolean;
|
||||
audioActive: boolean;
|
||||
frameRate: number;
|
||||
videoActive: boolean;
|
||||
typeOfVideo: string;
|
||||
frameRate: number;
|
||||
videoDimensions: string;
|
||||
}
|
|
@ -32,7 +32,9 @@ export interface PublisherProperties {
|
|||
audioSource?: string | MediaStreamTrack | boolean;
|
||||
|
||||
/**
|
||||
* Desired framerate of the video in frames per second
|
||||
* Desired framerate of the video in frames per second.
|
||||
* Limiting the framerate has always effect on browsers Chrome and Opera. Firefox requires that the input device explicitly supports the desired framerate.
|
||||
* @default undefined
|
||||
*/
|
||||
frameRate?: number;
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@ export { SignalEvent } from './OpenViduInternal/Events/SignalEvent';
|
|||
export { StreamEvent } from './OpenViduInternal/Events/StreamEvent';
|
||||
export { StreamManagerEvent } from './OpenViduInternal/Events/StreamManagerEvent';
|
||||
export { VideoElementEvent } from './OpenViduInternal/Events/VideoElementEvent';
|
||||
export { StreamPropertyChangedEvent } from './OpenViduInternal/Events/StreamPropertyChangedEvent';
|
||||
|
||||
export { Device } from './OpenViduInternal/Interfaces/Public/Device';
|
||||
export { EventDispatcher } from './OpenViduInternal/Interfaces/Public/EventDispatcher';
|
||||
|
|
Loading…
Reference in New Issue