mirror of https://github.com/OpenVidu/openvidu.git
openvidu-browser: StreamPropertyChangedEvent
parent
a20b878d7a
commit
15d879992a
|
@ -13,8 +13,7 @@ module.exports = {
|
||||||
exclude: [
|
exclude: [
|
||||||
"**/OpenViduInternal/Interfaces/Private/**",
|
"**/OpenViduInternal/Interfaces/Private/**",
|
||||||
"**/OpenViduInternal/WebRtcStats/WebRtcStats.ts",
|
"**/OpenViduInternal/WebRtcStats/WebRtcStats.ts",
|
||||||
"**/OpenViduInternal/WebRtcPeer/WebRtcPeer.ts",
|
"**/OpenViduInternal/WebRtcPeer/WebRtcPeer.ts"
|
||||||
"**/OpenViduInternal/Events/StreamPropertyChangedEvent.ts"
|
|
||||||
],
|
],
|
||||||
excludeExternals: true,
|
excludeExternals: true,
|
||||||
excludePrivate: true,
|
excludePrivate: true,
|
||||||
|
|
|
@ -123,10 +123,13 @@ export class Connection {
|
||||||
const streamOptions: InboundStreamOptions = {
|
const streamOptions: InboundStreamOptions = {
|
||||||
id: opts.id,
|
id: opts.id,
|
||||||
connection: this,
|
connection: this,
|
||||||
|
hasAudio: opts.hasAudio,
|
||||||
|
hasVideo: opts.hasVideo,
|
||||||
|
audioActive: opts.audioActive,
|
||||||
|
videoActive: opts.videoActive,
|
||||||
|
typeOfVideo: opts.typeOfVideo,
|
||||||
frameRate: opts.frameRate,
|
frameRate: opts.frameRate,
|
||||||
recvAudio: opts.audioActive,
|
videoDimensions: !!opts.videoDimensions ? JSON.parse(opts.videoDimensions) : undefined
|
||||||
recvVideo: opts.videoActive,
|
|
||||||
typeOfVideo: opts.typeOfVideo
|
|
||||||
};
|
};
|
||||||
const stream = new Stream(this.session, streamOptions);
|
const stream = new Stream(this.session, streamOptions);
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,7 @@ import { LocalRecorder } from './LocalRecorder';
|
||||||
import { Publisher } from './Publisher';
|
import { Publisher } from './Publisher';
|
||||||
import { Session } from './Session';
|
import { Session } from './Session';
|
||||||
import { Stream } from './Stream';
|
import { Stream } from './Stream';
|
||||||
|
import { StreamPropertyChangedEvent } from '../OpenViduInternal/Events/StreamPropertyChangedEvent';
|
||||||
import { Device } from '../OpenViduInternal/Interfaces/Public/Device';
|
import { Device } from '../OpenViduInternal/Interfaces/Public/Device';
|
||||||
import { OpenViduAdvancedConfiguration } from '../OpenViduInternal/Interfaces/Public/OpenViduAdvancedConfiguration';
|
import { OpenViduAdvancedConfiguration } from '../OpenViduInternal/Interfaces/Public/OpenViduAdvancedConfiguration';
|
||||||
import { PublisherProperties } from '../OpenViduInternal/Interfaces/Public/PublisherProperties';
|
import { PublisherProperties } from '../OpenViduInternal/Interfaces/Public/PublisherProperties';
|
||||||
|
@ -44,6 +45,10 @@ export class OpenVidu {
|
||||||
* @hidden
|
* @hidden
|
||||||
*/
|
*/
|
||||||
session: Session;
|
session: Session;
|
||||||
|
/**
|
||||||
|
* @hidden
|
||||||
|
*/
|
||||||
|
publishers: Publisher[] = [];
|
||||||
/**
|
/**
|
||||||
* @hidden
|
* @hidden
|
||||||
*/
|
*/
|
||||||
|
@ -71,6 +76,64 @@ export class OpenVidu {
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
console.info("'OpenVidu' initialized");
|
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', []);
|
publisher.emitEvent('accessDenied', []);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.publishers.push(publisher);
|
||||||
return publisher;
|
return publisher;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -510,6 +574,7 @@ export class OpenVidu {
|
||||||
recordingStarted: this.session.onRecordingStarted.bind(this.session),
|
recordingStarted: this.session.onRecordingStarted.bind(this.session),
|
||||||
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),
|
||||||
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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,10 +23,13 @@ import { EventDispatcher } from '../OpenViduInternal/Interfaces/Public/EventDisp
|
||||||
import { PublisherProperties } from '../OpenViduInternal/Interfaces/Public/PublisherProperties';
|
import { PublisherProperties } from '../OpenViduInternal/Interfaces/Public/PublisherProperties';
|
||||||
import { Event } from '../OpenViduInternal/Events/Event';
|
import { Event } from '../OpenViduInternal/Events/Event';
|
||||||
import { StreamEvent } from '../OpenViduInternal/Events/StreamEvent';
|
import { StreamEvent } from '../OpenViduInternal/Events/StreamEvent';
|
||||||
|
import { StreamPropertyChangedEvent } from '../OpenViduInternal/Events/StreamPropertyChangedEvent';
|
||||||
import { VideoElementEvent } from '../OpenViduInternal/Events/VideoElementEvent';
|
import { VideoElementEvent } from '../OpenViduInternal/Events/VideoElementEvent';
|
||||||
import { OpenViduError, OpenViduErrorName } from '../OpenViduInternal/Enums/OpenViduError';
|
import { OpenViduError, OpenViduErrorName } from '../OpenViduInternal/Enums/OpenViduError';
|
||||||
import { VideoInsertMode } from '../OpenViduInternal/Enums/VideoInsertMode';
|
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
|
* 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 properties: PublisherProperties;
|
||||||
private permissionDialogTimeout: NodeJS.Timer;
|
private permissionDialogTimeout: NodeJS.Timer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* hidden
|
||||||
|
*/
|
||||||
|
openvidu: OpenVidu;
|
||||||
/**
|
/**
|
||||||
* @hidden
|
* @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);
|
super(new Stream((!!openvidu.session) ? openvidu.session : new Session(openvidu), { publisherProperties: properties, mediaConstraints: {} }), targEl);
|
||||||
this.properties = properties;
|
this.properties = properties;
|
||||||
|
this.openvidu = openvidu;
|
||||||
|
|
||||||
this.stream.ee.on('local-stream-destroyed-by-disconnect', (reason: string) => {
|
this.stream.ee.on('local-stream-destroyed-by-disconnect', (reason: string) => {
|
||||||
const streamEvent = new StreamEvent(true, this, 'streamDestroyed', this.stream, reason);
|
const streamEvent = new StreamEvent(true, this, 'streamDestroyed', this.stream, reason);
|
||||||
this.ee.emitEvent('streamDestroyed', [streamEvent]);
|
this.emitEvent('streamDestroyed', [streamEvent]);
|
||||||
streamEvent.callDefaultBehaviour();
|
streamEvent.callDefaultBehavior();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Publish or unpublish the audio stream (if available). Calling this method twice in a row passing same value will have no effect
|
* 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
|
* @param value `true` to publish the audio stream, `false` to unpublish it
|
||||||
*/
|
*/
|
||||||
publishAudio(value: boolean): void {
|
publishAudio(value: boolean): void {
|
||||||
this.stream.getMediaStream().getAudioTracks().forEach((track) => {
|
if (this.stream.audioActive !== value) {
|
||||||
track.enabled = value;
|
this.stream.getMediaStream().getAudioTracks().forEach((track) => {
|
||||||
});
|
track.enabled = value;
|
||||||
console.info("'Publisher' has " + (value ? 'published' : 'unpublished') + ' its audio stream');
|
});
|
||||||
|
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
|
* 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
|
* @param value `true` to publish the video stream, `false` to unpublish it
|
||||||
*/
|
*/
|
||||||
publishVideo(value: boolean): void {
|
publishVideo(value: boolean): void {
|
||||||
this.stream.getMediaStream().getVideoTracks().forEach((track) => {
|
if (this.stream.videoActive !== value) {
|
||||||
track.enabled = value;
|
this.stream.getMediaStream().getVideoTracks().forEach((track) => {
|
||||||
});
|
track.enabled = value;
|
||||||
console.info("'Publisher' has " + (value ? 'published' : 'unpublished') + ' its video stream');
|
});
|
||||||
|
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 {
|
subscribeToRemote(value?: boolean): void {
|
||||||
value = (value !== undefined) ? value : true;
|
value = (value !== undefined) ? value : true;
|
||||||
|
@ -108,10 +185,10 @@ export class Publisher extends StreamManager {
|
||||||
super.on(type, handler);
|
super.on(type, handler);
|
||||||
if (type === 'streamCreated') {
|
if (type === 'streamCreated') {
|
||||||
if (!!this.stream && this.stream.isLocalStreamPublished) {
|
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 {
|
} else {
|
||||||
this.stream.ee.on('stream-created-by-publisher', () => {
|
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.paused === false &&
|
||||||
this.videos[0].video.ended === false &&
|
this.videos[0].video.ended === false &&
|
||||||
this.videos[0].video.readyState === 4) {
|
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 (type === 'accessAllowed') {
|
||||||
if (this.accessAllowed) {
|
if (this.accessAllowed) {
|
||||||
this.ee.emitEvent('accessAllowed');
|
this.emitEvent('accessAllowed', []);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (type === 'accessDenied') {
|
if (type === 'accessDenied') {
|
||||||
if (this.accessDenied) {
|
if (this.accessDenied) {
|
||||||
this.ee.emitEvent('accessDenied');
|
this.emitEvent('accessDenied', []);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return this;
|
return this;
|
||||||
|
@ -145,10 +222,10 @@ export class Publisher extends StreamManager {
|
||||||
super.once(type, handler);
|
super.once(type, handler);
|
||||||
if (type === 'streamCreated') {
|
if (type === 'streamCreated') {
|
||||||
if (!!this.stream && this.stream.isLocalStreamPublished) {
|
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 {
|
} else {
|
||||||
this.stream.ee.once('stream-created-by-publisher', () => {
|
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.paused === false &&
|
||||||
this.videos[0].video.ended === false &&
|
this.videos[0].video.ended === false &&
|
||||||
this.videos[0].video.readyState === 4) {
|
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 (type === 'accessAllowed') {
|
||||||
if (this.accessAllowed) {
|
if (this.accessAllowed) {
|
||||||
this.ee.emitEvent('accessAllowed');
|
this.emitEvent('accessAllowed', []);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (type === 'accessDenied') {
|
if (type === 'accessDenied') {
|
||||||
if (this.accessDenied) {
|
if (this.accessDenied) {
|
||||||
this.ee.emitEvent('accessDenied');
|
this.emitEvent('accessDenied', []);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return this;
|
return this;
|
||||||
|
@ -217,14 +294,76 @@ export class Publisher extends StreamManager {
|
||||||
// avoid early 'streamPlaying' event
|
// avoid early 'streamPlaying' event
|
||||||
this.stream.updateMediaStreamInVideos();
|
this.stream.updateMediaStreamInVideos();
|
||||||
}
|
}
|
||||||
this.stream.isLocalStreamReadyToPublish = true;
|
|
||||||
this.stream.ee.emitEvent('stream-ready-to-publish', []);
|
|
||||||
|
|
||||||
if (!!this.firstVideoElement) {
|
if (!!this.firstVideoElement) {
|
||||||
this.createVideoElement(this.firstVideoElement.targetElement, <VideoInsertMode>this.properties.insertMode);
|
this.createVideoElement(this.firstVideoElement.targetElement, <VideoInsertMode>this.properties.insertMode);
|
||||||
}
|
}
|
||||||
delete this.firstVideoElement;
|
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();
|
resolve();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -371,13 +510,6 @@ export class Publisher extends StreamManager {
|
||||||
this.stream.session = session;
|
this.stream.session = session;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @hidden
|
|
||||||
*/
|
|
||||||
emitEvent(type: string, eventArray: any[]): void {
|
|
||||||
this.ee.emitEvent(type, eventArray);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @hidden
|
* @hidden
|
||||||
*/
|
*/
|
||||||
|
@ -392,7 +524,7 @@ export class Publisher extends StreamManager {
|
||||||
|
|
||||||
private setPermissionDialogTimer(waitTime: number): void {
|
private setPermissionDialogTimer(waitTime: number): void {
|
||||||
this.permissionDialogTimeout = setTimeout(() => {
|
this.permissionDialogTimeout = setTimeout(() => {
|
||||||
this.ee.emitEvent('accessDialogOpened', []);
|
this.emitEvent('accessDialogOpened', []);
|
||||||
}, waitTime);
|
}, waitTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -400,7 +532,7 @@ export class Publisher extends StreamManager {
|
||||||
clearTimeout(this.permissionDialogTimeout);
|
clearTimeout(this.permissionDialogTimeout);
|
||||||
if ((Date.now() - startTime) > waitTime) {
|
if ((Date.now() - startTime) > waitTime) {
|
||||||
// Permission dialog was shown and now is closed
|
// 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 { SessionDisconnectedEvent } from '../OpenViduInternal/Events/SessionDisconnectedEvent';
|
||||||
import { SignalEvent } from '../OpenViduInternal/Events/SignalEvent';
|
import { SignalEvent } from '../OpenViduInternal/Events/SignalEvent';
|
||||||
import { StreamEvent } from '../OpenViduInternal/Events/StreamEvent';
|
import { StreamEvent } from '../OpenViduInternal/Events/StreamEvent';
|
||||||
|
import { StreamPropertyChangedEvent } from '../OpenViduInternal/Events/StreamPropertyChangedEvent';
|
||||||
import { OpenViduError, OpenViduErrorName } from '../OpenViduInternal/Enums/OpenViduError';
|
import { OpenViduError, OpenViduErrorName } from '../OpenViduInternal/Enums/OpenViduError';
|
||||||
import { VideoInsertMode } from '../OpenViduInternal/Enums/VideoInsertMode';
|
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)
|
* 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)).
|
* 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.
|
* 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.
|
* 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.
|
* 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)).
|
* 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.
|
* 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.
|
* 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.
|
* 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)
|
* 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)).
|
* 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.
|
* 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.
|
* 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.
|
* 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
|
* 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)).
|
* (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.
|
* 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.
|
* 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
|
* 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)).
|
* 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.
|
* 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.
|
* 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');
|
const streamEvent = new StreamEvent(true, publisher, 'streamDestroyed', publisher.stream, 'unpublish');
|
||||||
publisher.emitEvent('streamDestroyed', [streamEvent]);
|
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);
|
const streamEvent = new StreamEvent(true, this, 'streamDestroyed', stream, msg.reason);
|
||||||
this.ee.emitEvent('streamDestroyed', [streamEvent]);
|
this.ee.emitEvent('streamDestroyed', [streamEvent]);
|
||||||
streamEvent.callDefaultBehaviour();
|
streamEvent.callDefaultBehavior();
|
||||||
|
|
||||||
delete this.remoteStreamsCreated[stream.streamId];
|
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);
|
const streamEvent = new StreamEvent(true, this, 'streamDestroyed', connection.stream, msg.reason);
|
||||||
this.ee.emitEvent('streamDestroyed', [streamEvent]);
|
this.ee.emitEvent('streamDestroyed', [streamEvent]);
|
||||||
streamEvent.callDefaultBehaviour();
|
streamEvent.callDefaultBehavior();
|
||||||
|
|
||||||
// Deleting the remote stream
|
// Deleting the remote stream
|
||||||
const streamId: string = connection.stream.streamId;
|
const streamId: string = connection.stream.streamId;
|
||||||
|
@ -654,7 +655,7 @@ export class Session implements EventDispatcher {
|
||||||
|
|
||||||
const streamEvent = new StreamEvent(true, this, 'streamDestroyed', stream, 'forceDisconnect');
|
const streamEvent = new StreamEvent(true, this, 'streamDestroyed', stream, 'forceDisconnect');
|
||||||
this.ee.emitEvent('streamDestroyed', [streamEvent]);
|
this.ee.emitEvent('streamDestroyed', [streamEvent]);
|
||||||
streamEvent.callDefaultBehaviour();
|
streamEvent.callDefaultBehavior();
|
||||||
|
|
||||||
delete this.remoteStreamsCreated[stream.streamId];
|
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
|
* @hidden
|
||||||
*/
|
*/
|
||||||
|
@ -818,7 +859,7 @@ export class Session implements EventDispatcher {
|
||||||
// Make Session object dispatch 'sessionDisconnected' event (if it is not already disposed)
|
// Make Session object dispatch 'sessionDisconnected' event (if it is not already disposed)
|
||||||
const sessionDisconnectEvent = new SessionDisconnectedEvent(this, reason);
|
const sessionDisconnectEvent = new SessionDisconnectedEvent(this, reason);
|
||||||
this.ee.emitEvent('sessionDisconnected', [sessionDisconnectEvent]);
|
this.ee.emitEvent('sessionDisconnected', [sessionDisconnectEvent]);
|
||||||
sessionDisconnectEvent.callDefaultBehaviour();
|
sessionDisconnectEvent.callDefaultBehavior();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
console.warn('You were not connected to the session ' + this.sessionId);
|
console.warn('You were not connected to the session ' + this.sessionId);
|
||||||
|
@ -952,7 +993,7 @@ export class Session implements EventDispatcher {
|
||||||
{ urls: [stunUrl] },
|
{ urls: [stunUrl] },
|
||||||
{ urls: [turnUrl1, turnUrl2], username: turnUsername, credential: turnCredential }
|
{ urls: [turnUrl1, turnUrl2], username: turnUsername, credential: turnCredential }
|
||||||
];
|
];
|
||||||
console.log('TURN temp credentials [' + turnUsername + ':' + turnCredential + ']')
|
console.log('TURN temp credentials [' + turnUsername + ':' + turnCredential + ']');
|
||||||
}
|
}
|
||||||
if (!!role) {
|
if (!!role) {
|
||||||
this.openvidu.role = role;
|
this.openvidu.role = role;
|
||||||
|
|
|
@ -56,13 +56,30 @@ export class Stream {
|
||||||
*/
|
*/
|
||||||
hasAudio: boolean;
|
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
|
* Unique identifier of the stream
|
||||||
*/
|
*/
|
||||||
streamId: string;
|
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;
|
typeOfVideo?: string;
|
||||||
|
|
||||||
|
@ -71,6 +88,17 @@ export class Stream {
|
||||||
*/
|
*/
|
||||||
streamManager: StreamManager;
|
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
|
* @hidden
|
||||||
*/
|
*/
|
||||||
|
@ -119,26 +147,36 @@ export class Stream {
|
||||||
// InboundStreamOptions: stream belongs to a Subscriber
|
// InboundStreamOptions: stream belongs to a Subscriber
|
||||||
this.inboundStreamOpts = <InboundStreamOptions>options;
|
this.inboundStreamOpts = <InboundStreamOptions>options;
|
||||||
this.streamId = this.inboundStreamOpts.id;
|
this.streamId = this.inboundStreamOpts.id;
|
||||||
this.hasAudio = this.inboundStreamOpts.recvAudio;
|
this.hasAudio = this.inboundStreamOpts.hasAudio;
|
||||||
this.hasVideo = this.inboundStreamOpts.recvVideo;
|
this.hasVideo = this.inboundStreamOpts.hasVideo;
|
||||||
this.typeOfVideo = (!this.inboundStreamOpts.typeOfVideo) ? undefined : this.inboundStreamOpts.typeOfVideo;
|
if (this.hasAudio) {
|
||||||
this.frameRate = (this.inboundStreamOpts.frameRate === -1) ? undefined : this.inboundStreamOpts.frameRate;
|
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 {
|
} else {
|
||||||
// OutboundStreamOptions: stream belongs to a Publisher
|
// OutboundStreamOptions: stream belongs to a Publisher
|
||||||
this.outboundStreamOpts = <OutboundStreamOptions>options;
|
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.hasAudio = this.isSendAudio();
|
||||||
this.hasVideo = this.isSendVideo();
|
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', () => {
|
this.ee.on('mediastream-updated', () => {
|
||||||
|
@ -410,13 +448,21 @@ export class Stream {
|
||||||
console.debug('Sending SDP offer to publish as '
|
console.debug('Sending SDP offer to publish as '
|
||||||
+ this.streamId, sdpOfferParam);
|
+ 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', {
|
this.session.openvidu.sendRequest('publishVideo', {
|
||||||
sdpOffer: sdpOfferParam,
|
sdpOffer: sdpOfferParam,
|
||||||
doLoopback: this.displayMyRemote() || false,
|
doLoopback: this.displayMyRemote() || false,
|
||||||
audioActive: this.isSendAudio(),
|
hasAudio: this.isSendAudio(),
|
||||||
videoActive: this.isSendVideo(),
|
hasVideo: this.isSendVideo(),
|
||||||
typeOfVideo: ((this.isSendVideo()) ? (this.isSendScreen() ? 'SCREEN' : 'CAMERA') : ''),
|
audioActive: this.audioActive,
|
||||||
frameRate: !!this.frameRate ? this.frameRate : -1
|
videoActive: this.videoActive,
|
||||||
|
typeOfVideo,
|
||||||
|
frameRate: !!this.frameRate ? this.frameRate : -1,
|
||||||
|
videoDimensions: JSON.stringify(this.videoDimensions)
|
||||||
}, (error, response) => {
|
}, (error, response) => {
|
||||||
if (error) {
|
if (error) {
|
||||||
reject('Error on publishVideo: ' + JSON.stringify(error));
|
reject('Error on publishVideo: ' + JSON.stringify(error));
|
||||||
|
@ -426,7 +472,7 @@ export class Stream {
|
||||||
this.streamId = response.id;
|
this.streamId = response.id;
|
||||||
this.isLocalStreamPublished = true;
|
this.isLocalStreamPublished = true;
|
||||||
if (this.displayMyRemote()) {
|
if (this.displayMyRemote()) {
|
||||||
this.remotePeerSuccesfullyEstablished();
|
this.remotePeerSuccessfullyEstablished();
|
||||||
}
|
}
|
||||||
this.ee.emitEvent('stream-created-by-publisher');
|
this.ee.emitEvent('stream-created-by-publisher');
|
||||||
this.initWebRtcStats();
|
this.initWebRtcStats();
|
||||||
|
@ -457,8 +503,8 @@ export class Stream {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
|
|
||||||
const offerConstraints = {
|
const offerConstraints = {
|
||||||
audio: this.inboundStreamOpts.recvAudio,
|
audio: this.inboundStreamOpts.hasAudio,
|
||||||
video: this.inboundStreamOpts.recvVideo
|
video: this.inboundStreamOpts.hasVideo
|
||||||
};
|
};
|
||||||
console.debug("'Session.subscribe(Stream)' called. Constraints of generate SDP offer",
|
console.debug("'Session.subscribe(Stream)' called. Constraints of generate SDP offer",
|
||||||
offerConstraints);
|
offerConstraints);
|
||||||
|
@ -480,7 +526,7 @@ export class Stream {
|
||||||
reject(new Error('Error on recvVideoFrom: ' + JSON.stringify(error)));
|
reject(new Error('Error on recvVideoFrom: ' + JSON.stringify(error)));
|
||||||
} else {
|
} else {
|
||||||
this.webRtcPeer.processAnswer(response.sdpAnswer).then(() => {
|
this.webRtcPeer.processAnswer(response.sdpAnswer).then(() => {
|
||||||
this.remotePeerSuccesfullyEstablished();
|
this.remotePeerSuccessfullyEstablished();
|
||||||
this.initWebRtcStats();
|
this.initWebRtcStats();
|
||||||
resolve();
|
resolve();
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
|
@ -501,7 +547,7 @@ export class Stream {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private remotePeerSuccesfullyEstablished(): void {
|
private remotePeerSuccessfullyEstablished(): void {
|
||||||
this.mediaStream = this.webRtcPeer.pc.getRemoteStreams()[0];
|
this.mediaStream = this.webRtcPeer.pc.getRemoteStreams()[0];
|
||||||
console.debug('Peer remote stream', this.mediaStream);
|
console.debug('Peer remote stream', this.mediaStream);
|
||||||
|
|
||||||
|
|
|
@ -139,9 +139,9 @@ export class StreamManager implements EventDispatcher {
|
||||||
on(type: string, handler: (event: Event) => void): EventDispatcher {
|
on(type: string, handler: (event: Event) => void): EventDispatcher {
|
||||||
this.ee.on(type, event => {
|
this.ee.on(type, event => {
|
||||||
if (event) {
|
if (event) {
|
||||||
console.info("Event '" + type + "' triggered", event);
|
console.info("Event '" + type + "' triggered by '" + (this.remote ? 'Subscriber' : 'Publisher') + "'", event);
|
||||||
} else {
|
} else {
|
||||||
console.info("Event '" + type + "' triggered");
|
console.info("Event '" + type + "' triggered by '" + (this.remote ? 'Subscriber' : 'Publisher') + "'");
|
||||||
}
|
}
|
||||||
handler(event);
|
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) {
|
private pushNewStreamManagerVideo(streamManagerVideo: StreamManagerVideo) {
|
||||||
this.videos.push(streamManagerVideo);
|
this.videos.push(streamManagerVideo);
|
||||||
this.addPlayEventToFirstVideo();
|
this.addPlayEventToFirstVideo();
|
||||||
|
|
|
@ -22,49 +22,49 @@ export enum OpenViduErrorName {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Browser is not supported by OpenVidu.
|
* Browser is not supported by OpenVidu.
|
||||||
* Returned uppon unsuccessful [[Session.connect]]
|
* Returned upon unsuccessful [[Session.connect]]
|
||||||
*/
|
*/
|
||||||
BROWSER_NOT_SUPPORTED = 'BROWSER_NOT_SUPPORTED',
|
BROWSER_NOT_SUPPORTED = 'BROWSER_NOT_SUPPORTED',
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The user hasn't granted permissions to the required input device when the browser asked for them.
|
* 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',
|
DEVICE_ACCESS_DENIED = 'DEVICE_ACCESS_DENIED',
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The user hasn't granted permissions to capture some desktop screen when the browser asked for them.
|
* 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',
|
SCREEN_CAPTURE_DENIED = 'SCREEN_CAPTURE_DENIED',
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Browser does not support screen sharing.
|
* Browser does not support screen sharing.
|
||||||
* Returned uppon unsuccessful [[OpenVidu.initPublisher]]
|
* Returned upon unsuccessful [[OpenVidu.initPublisher]]
|
||||||
*/
|
*/
|
||||||
SCREEN_SHARING_NOT_SUPPORTED = 'SCREEN_SHARING_NOT_SUPPORTED',
|
SCREEN_SHARING_NOT_SUPPORTED = 'SCREEN_SHARING_NOT_SUPPORTED',
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Only for Chrome, there's no screen sharing extension installed
|
* 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',
|
SCREEN_EXTENSION_NOT_INSTALLED = 'SCREEN_EXTENSION_NOT_INSTALLED',
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Only for Chrome, the screen sharing extension is installed but is disabled
|
* 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',
|
SCREEN_EXTENSION_DISABLED = 'SCREEN_EXTENSION_DISABLED',
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* No video input device found with the provided deviceId (property [[PublisherProperties.videoSource]])
|
* 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',
|
INPUT_VIDEO_DEVICE_NOT_FOUND = 'INPUT_VIDEO_DEVICE_NOT_FOUND',
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* No audio input device found with the provided deviceId (property [[PublisherProperties.audioSource]])
|
* 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',
|
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
|
* 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).
|
* 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',
|
PUBLISHER_PROPERTIES_ERROR = 'PUBLISHER_PROPERTIES_ERROR',
|
||||||
|
|
||||||
|
|
|
@ -54,6 +54,6 @@ export class ConnectionEvent extends Event {
|
||||||
* @hidden
|
* @hidden
|
||||||
*/
|
*/
|
||||||
// tslint:disable-next-line:no-empty
|
// tslint:disable-next-line:no-empty
|
||||||
callDefaultBehaviour() { }
|
callDefaultBehavior() { }
|
||||||
|
|
||||||
}
|
}
|
|
@ -21,7 +21,7 @@ import { Session } from '../../OpenVidu/Session';
|
||||||
export abstract class Event {
|
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;
|
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)
|
* - `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
|
* 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() {
|
preventDefault() {
|
||||||
// tslint:disable-next-line:no-empty
|
// tslint:disable-next-line:no-empty
|
||||||
this.callDefaultBehaviour = () => { };
|
this.callDefaultBehavior = () => { };
|
||||||
this.hasBeenPrevented = true;
|
this.hasBeenPrevented = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract callDefaultBehaviour();
|
protected abstract callDefaultBehavior();
|
||||||
|
|
||||||
}
|
}
|
|
@ -57,6 +57,6 @@ export class PublisherSpeakingEvent extends Event {
|
||||||
* @hidden
|
* @hidden
|
||||||
*/
|
*/
|
||||||
// tslint:disable-next-line:no-empty
|
// tslint:disable-next-line:no-empty
|
||||||
callDefaultBehaviour() { }
|
callDefaultBehavior() { }
|
||||||
|
|
||||||
}
|
}
|
|
@ -56,6 +56,6 @@ export class RecordingEvent extends Event {
|
||||||
* @hidden
|
* @hidden
|
||||||
*/
|
*/
|
||||||
// tslint:disable-next-line:no-empty
|
// tslint:disable-next-line:no-empty
|
||||||
callDefaultBehaviour() { }
|
callDefaultBehavior() { }
|
||||||
|
|
||||||
}
|
}
|
|
@ -41,9 +41,9 @@ export class SessionDisconnectedEvent extends Event {
|
||||||
/**
|
/**
|
||||||
* @hidden
|
* @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;
|
const session = <Session>this.target;
|
||||||
|
|
||||||
|
|
|
@ -60,6 +60,6 @@ export class SignalEvent extends Event {
|
||||||
* @hidden
|
* @hidden
|
||||||
*/
|
*/
|
||||||
// tslint:disable-next-line:no-empty
|
// tslint:disable-next-line:no-empty
|
||||||
callDefaultBehaviour() { }
|
callDefaultBehavior() { }
|
||||||
|
|
||||||
}
|
}
|
|
@ -55,17 +55,27 @@ export class StreamEvent extends Event {
|
||||||
/**
|
/**
|
||||||
* @hidden
|
* @hidden
|
||||||
*/
|
*/
|
||||||
callDefaultBehaviour() {
|
callDefaultBehavior() {
|
||||||
if (this.type === 'streamDestroyed') {
|
if (this.type === 'streamDestroyed') {
|
||||||
|
|
||||||
if (this.target instanceof Session) {
|
if (this.target instanceof Session) {
|
||||||
// Remote Stream
|
// 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();
|
this.stream.disposeWebRtcPeer();
|
||||||
} else if (this.target instanceof Publisher) {
|
} else if (this.target instanceof Publisher) {
|
||||||
// Local Stream
|
// 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;
|
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
|
// Dispose the MediaStream local object
|
||||||
|
|
|
@ -35,6 +35,6 @@ export class StreamManagerEvent extends Event {
|
||||||
* @hidden
|
* @hidden
|
||||||
*/
|
*/
|
||||||
// tslint:disable-next-line:no-empty
|
// tslint:disable-next-line:no-empty
|
||||||
callDefaultBehaviour() { }
|
callDefaultBehavior() { }
|
||||||
|
|
||||||
}
|
}
|
|
@ -18,47 +18,59 @@
|
||||||
import { Event } from './Event';
|
import { Event } from './Event';
|
||||||
import { Session } from '../../OpenVidu/Session';
|
import { Session } from '../../OpenVidu/Session';
|
||||||
import { Stream } from '../../OpenVidu/Stream';
|
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 {
|
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;
|
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;
|
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;
|
newValue: Object;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Previous value of the property (after change)
|
* Previous value of the property (before change)
|
||||||
*/
|
*/
|
||||||
oldValue: Object;
|
oldValue: Object;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @hidden
|
* @hidden
|
||||||
*/
|
*/
|
||||||
constructor(target: Session, stream: Stream, changedProperty: string, newValue: Object, oldValue: Object) {
|
constructor(target: Session | StreamManager, stream: Stream, changedProperty: string, newValue: Object, oldValue: Object, reason: string) {
|
||||||
super(false, target, 'streamPropertyChangedEvent');
|
super(false, target, 'streamPropertyChanged');
|
||||||
this.stream = stream;
|
this.stream = stream;
|
||||||
this.changedProperty = changedProperty;
|
this.changedProperty = changedProperty;
|
||||||
this.newValue = newValue;
|
this.newValue = newValue;
|
||||||
this.oldValue = oldValue;
|
this.oldValue = oldValue;
|
||||||
|
this.reason = reason;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @hidden
|
* @hidden
|
||||||
*/
|
*/
|
||||||
// tslint:disable-next-line:no-empty
|
// tslint:disable-next-line:no-empty
|
||||||
callDefaultBehaviour() { }
|
callDefaultBehavior() { }
|
||||||
|
|
||||||
}
|
}
|
|
@ -44,6 +44,6 @@ export class VideoElementEvent extends Event {
|
||||||
* @hidden
|
* @hidden
|
||||||
*/
|
*/
|
||||||
// tslint:disable-next-line:no-empty
|
// tslint:disable-next-line:no-empty
|
||||||
callDefaultBehaviour() { }
|
callDefaultBehavior() { }
|
||||||
|
|
||||||
}
|
}
|
|
@ -20,8 +20,11 @@ import { Connection } from '../../../OpenVidu/Connection';
|
||||||
export interface InboundStreamOptions {
|
export interface InboundStreamOptions {
|
||||||
id: string;
|
id: string;
|
||||||
connection: Connection;
|
connection: Connection;
|
||||||
frameRate: number;
|
hasAudio: boolean;
|
||||||
recvAudio: boolean;
|
hasVideo: boolean;
|
||||||
recvVideo: boolean;
|
audioActive: boolean;
|
||||||
|
videoActive: boolean;
|
||||||
typeOfVideo: string;
|
typeOfVideo: string;
|
||||||
|
frameRate: number;
|
||||||
|
videoDimensions: { width: number, height: number };
|
||||||
}
|
}
|
|
@ -17,8 +17,11 @@
|
||||||
|
|
||||||
export interface StreamOptionsServer {
|
export interface StreamOptionsServer {
|
||||||
id: string;
|
id: string;
|
||||||
|
hasAudio: boolean;
|
||||||
|
hasVideo: boolean;
|
||||||
audioActive: boolean;
|
audioActive: boolean;
|
||||||
frameRate: number;
|
|
||||||
videoActive: boolean;
|
videoActive: boolean;
|
||||||
typeOfVideo: string;
|
typeOfVideo: string;
|
||||||
|
frameRate: number;
|
||||||
|
videoDimensions: string;
|
||||||
}
|
}
|
|
@ -32,7 +32,9 @@ export interface PublisherProperties {
|
||||||
audioSource?: string | MediaStreamTrack | boolean;
|
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;
|
frameRate?: number;
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,7 @@ export { SignalEvent } from './OpenViduInternal/Events/SignalEvent';
|
||||||
export { StreamEvent } from './OpenViduInternal/Events/StreamEvent';
|
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 { Device } from './OpenViduInternal/Interfaces/Public/Device';
|
export { Device } from './OpenViduInternal/Interfaces/Public/Device';
|
||||||
export { EventDispatcher } from './OpenViduInternal/Interfaces/Public/EventDispatcher';
|
export { EventDispatcher } from './OpenViduInternal/Interfaces/Public/EventDispatcher';
|
||||||
|
|
Loading…
Reference in New Issue