mirror of https://github.com/OpenVidu/openvidu.git
'Session.unpublish(Publisher)' feature working
parent
fcf535dea4
commit
f348b5380a
|
@ -58,6 +58,7 @@ export class OpenVidu {
|
|||
|
||||
initPublisher(parentId: string, cameraOptions?: any, callback?: Function): any {
|
||||
if (this.checkSystemRequirements()) {
|
||||
this.openVidu.storedPublisherOptions = cameraOptions;
|
||||
let publisher: Publisher;
|
||||
if (cameraOptions != null) {
|
||||
|
||||
|
@ -81,8 +82,8 @@ export class OpenVidu {
|
|||
return publisher;
|
||||
|
||||
} else {
|
||||
if (adapter.browserDetails.browser === 'firefox' && adapter.browserDetails.version >= 52) {
|
||||
publisher = new Publisher(this.openVidu.initPublisherScreen(parentId, callback), parentId, true);
|
||||
if (adapter.browserDetails.browser === 'firefox' && adapter.browserDetails.version >= 52) {
|
||||
screenSharingAuto.getScreenId((error, sourceId, screenConstraints) => {
|
||||
cameraOptions = {
|
||||
sendAudio: cameraOptions.audio,
|
||||
|
@ -156,7 +157,6 @@ export class OpenVidu {
|
|||
console.error('getScreenId error', error);
|
||||
return;
|
||||
});
|
||||
publisher = new Publisher(this.openVidu.initPublisherScreen(parentId, callback), parentId, true);
|
||||
console.info("'Publisher' initialized");
|
||||
return publisher;
|
||||
} else {
|
||||
|
|
|
@ -5,14 +5,14 @@
|
|||
*
|
||||
* stream.hasAudio(); stream.hasVideo(); stream.hasData();
|
||||
*/
|
||||
import { Stream, StreamOptions, VideoOptions } from '../OpenViduInternal/Stream';
|
||||
import { Stream, StreamOptions } from '../OpenViduInternal/Stream';
|
||||
import { Session } from './Session';
|
||||
|
||||
import EventEmitter = require('wolfy87-eventemitter');
|
||||
|
||||
export class Publisher {
|
||||
|
||||
private ee = new EventEmitter();
|
||||
ee = new EventEmitter();
|
||||
|
||||
accessAllowed = false;
|
||||
element: Element;
|
||||
|
@ -25,13 +25,9 @@ export class Publisher {
|
|||
this.stream = stream;
|
||||
this.isScreenRequested = isScreenRequested;
|
||||
|
||||
this.stream.addEventListener('camera-access-changed', (event) => {
|
||||
this.accessAllowed = event.accessAllowed;
|
||||
if (this.accessAllowed) {
|
||||
this.ee.emitEvent('accessAllowed');
|
||||
} else {
|
||||
this.ee.emitEvent('accessDenied');
|
||||
}
|
||||
// Listens to the deactivation of the default behaviour upon the deletion of a Stream object
|
||||
this.ee.addListener('stream-destroyed-default', event => {
|
||||
event.stream.removeVideo();
|
||||
});
|
||||
|
||||
if (document.getElementById(parentId) != null) {
|
||||
|
@ -72,7 +68,6 @@ export class Publisher {
|
|||
this.ee.emitEvent('streamCreated', [{ stream: this.stream }]);
|
||||
} else {
|
||||
this.stream.addEventListener('stream-created-by-publisher', () => {
|
||||
console.warn('Publisher emitting streamCreated');
|
||||
this.ee.emitEvent('streamCreated', [{ stream: this.stream }]);
|
||||
});
|
||||
}
|
||||
|
@ -83,7 +78,7 @@ export class Publisher {
|
|||
element: this.stream.getVideoElement()
|
||||
}]);
|
||||
} else {
|
||||
this.stream.addOnceEventListener('video-element-created-by-stream', (element) => {
|
||||
this.stream.addEventListener('video-element-created-by-stream', (element) => {
|
||||
this.id = element.id;
|
||||
this.ee.emitEvent('videoElementCreated', [{
|
||||
element: element.element
|
||||
|
@ -102,7 +97,7 @@ export class Publisher {
|
|||
element: this.stream.getVideoElement()
|
||||
}]);
|
||||
} else {
|
||||
this.stream.addOnceEventListener('video-is-playing', (element) => {
|
||||
this.stream.addEventListener('video-is-playing', (element) => {
|
||||
this.ee.emitEvent('videoPlaying', [{
|
||||
element: element.element
|
||||
}]);
|
||||
|
@ -120,7 +115,7 @@ export class Publisher {
|
|||
element: this.stream.getVideoElement()
|
||||
}]);
|
||||
} else {
|
||||
this.stream.addOnceEventListener('remote-video-is-playing', (element) => {
|
||||
this.stream.addEventListener('remote-video-is-playing', (element) => {
|
||||
this.ee.emitEvent('remoteVideoPlaying', [{
|
||||
element: element.element
|
||||
}]);
|
||||
|
|
|
@ -76,19 +76,37 @@ export class Session {
|
|||
}
|
||||
|
||||
publish(publisher: Publisher) {
|
||||
if (publisher.isScreenRequested && !publisher.stream.isScreenRequestedReady) {
|
||||
if (!publisher.stream.isPublisherPublished) { // 'Session.unpublish(Publisher)' has NOT been called
|
||||
if (publisher.isScreenRequested) { // Screen sharing Publisher
|
||||
if (!publisher.stream.isScreenRequestedReady) { // Screen video stream is not available yet
|
||||
publisher.stream.addOnceEventListener('screen-ready', () => {
|
||||
publisher.session = this;
|
||||
publisher.stream.publish();
|
||||
this.streamPublish(publisher);
|
||||
});
|
||||
} else {
|
||||
publisher.session = this;
|
||||
publisher.stream.publish();
|
||||
} else { // // Screen video stream is already available
|
||||
this.streamPublish(publisher);
|
||||
}
|
||||
} else { // Audio-Video Publisher
|
||||
this.streamPublish(publisher);
|
||||
}
|
||||
} else { // 'Session.unpublish(Publisher)' has been called
|
||||
let mypublisher = this.openVidu.initPublisher(publisher.stream.getParentId(), this.openVidu.openVidu.storedPublisherOptions);
|
||||
if (mypublisher.isScreenRequested && !mypublisher.stream.isScreenRequestedReady) { // Screen sharing Publisher and video stream not available yet
|
||||
mypublisher.stream.addOnceEventListener('screen-ready', () => {
|
||||
this.streamPublish(mypublisher);
|
||||
});
|
||||
} else { // Video stream already available
|
||||
this.streamPublish(mypublisher);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private streamPublish(publisher: Publisher) {
|
||||
publisher.session = this;
|
||||
publisher.stream.publish();
|
||||
}
|
||||
|
||||
unpublish(publisher: Publisher) {
|
||||
this.session.unpublish(publisher.stream);
|
||||
this.session.unpublish(publisher);
|
||||
}
|
||||
|
||||
on(eventName: string, callback) {
|
||||
|
@ -144,7 +162,7 @@ export class Session {
|
|||
signalMessage['data'] = signal.data ? signal.data : '';
|
||||
signalMessage['type'] = signal.type ? signal.type : '';
|
||||
|
||||
this.openVidu.openVidu.sendMessage(this.sessionId, this.connection.connectionId, JSON.stringify(signalMessage));
|
||||
this.openVidu.openVidu.sendMessage(JSON.stringify(signalMessage));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { Stream, StreamOptions, VideoOptions } from '../OpenViduInternal/Stream';
|
||||
import { Stream, StreamOptions } from '../OpenViduInternal/Stream';
|
||||
|
||||
import EventEmitter = require('wolfy87-eventemitter');
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@ export class Connection {
|
|||
public data: string;
|
||||
public creationTime: number;
|
||||
private streams: ObjMap<Stream> = {};
|
||||
private streamsOpts: StreamOptions[] = [];
|
||||
private streamsOpts: StreamOptions;
|
||||
|
||||
constructor( private openVidu: OpenViduInternal, private local: boolean, private room: SessionInternal, private options?: ConnectionOptions ) {
|
||||
|
||||
|
@ -41,6 +41,12 @@ export class Connection {
|
|||
this.room.getStreams()[stream.streamId] = stream;
|
||||
}
|
||||
|
||||
removeStream( key: string ) {
|
||||
delete this.streams[key];
|
||||
delete this.room.getStreams()[key];
|
||||
delete this.streamsOpts;
|
||||
}
|
||||
|
||||
getStreams() {
|
||||
return this.streams;
|
||||
}
|
||||
|
@ -88,7 +94,7 @@ export class Connection {
|
|||
let stream = new Stream(this.openVidu, false, this.room, streamOpts );
|
||||
|
||||
this.addStream( stream );
|
||||
this.streamsOpts.push( streamOpts );
|
||||
this.streamsOpts = streamOpts;
|
||||
}
|
||||
|
||||
console.info("Remote 'Connection' with 'connectionId' [" + this.connectionId + "] is now configured for receiving Streams with options: ", this.streamsOpts );
|
||||
|
|
|
@ -35,6 +35,7 @@ export class OpenViduInternal {
|
|||
|
||||
constructor() { };
|
||||
|
||||
storedPublisherOptions: any;
|
||||
|
||||
/* NEW METHODS */
|
||||
initSession(sessionId) {
|
||||
|
@ -66,7 +67,9 @@ export class OpenViduInternal {
|
|||
}
|
||||
|
||||
initPublisherScreen(parentId: string, callback?): Stream {
|
||||
if (!this.camera) {
|
||||
this.camera = new Stream(this, true, this.session, 'screen-options');
|
||||
}
|
||||
this.camera.addOnceEventListener('can-request-screen', () => {
|
||||
this.camera.requestCameraAccess((error, camera) => {
|
||||
if (error) {
|
||||
|
@ -121,14 +124,6 @@ export class OpenViduInternal {
|
|||
return videoElement;
|
||||
}
|
||||
|
||||
initPublisher(cameraOptions: any, callback) {
|
||||
this.getCamera(cameraOptions);
|
||||
this.camera.requestCameraAccess((error, camera) => {
|
||||
if (error) callback(error);
|
||||
else callback(undefined);
|
||||
});
|
||||
}
|
||||
|
||||
getLocalStream() {
|
||||
return this.camera;
|
||||
}
|
||||
|
@ -187,26 +182,18 @@ export class OpenViduInternal {
|
|||
//notifications
|
||||
participantJoined: this.onParticipantJoined.bind(this),
|
||||
participantPublished: this.onParticipantPublished.bind(this),
|
||||
participantUnpublished: this.onParticipantLeft.bind(this),
|
||||
participantUnpublished: this.onParticipantUnpublished.bind(this),
|
||||
participantLeft: this.onParticipantLeft.bind(this),
|
||||
participantEvicted: this.onParticipantEvicted.bind(this),
|
||||
sendMessage: this.onNewMessage.bind(this),
|
||||
iceCandidate: this.iceCandidateEvent.bind(this),
|
||||
mediaError: this.onMediaError.bind(this),
|
||||
custonNotification: this.customNotification.bind(this)
|
||||
}
|
||||
};
|
||||
|
||||
this.jsonRpcClient = new RpcBuilder.clients.JsonRpcClient(config);
|
||||
}
|
||||
|
||||
|
||||
private customNotification(params) {
|
||||
if (this.isRoomAvailable()) {
|
||||
this.session.emitEvent("custom-message-received", [{ params: params }]);
|
||||
}
|
||||
}
|
||||
|
||||
private connectCallback(error) {
|
||||
if (error) {
|
||||
this.callback(error);
|
||||
|
@ -258,6 +245,12 @@ export class OpenViduInternal {
|
|||
}
|
||||
}
|
||||
|
||||
private onParticipantUnpublished(params) {
|
||||
if (this.isRoomAvailable()) {
|
||||
this.session.onParticipantUnpublished(params);
|
||||
}
|
||||
}
|
||||
|
||||
private onParticipantLeft(params) {
|
||||
if (this.isRoomAvailable()) {
|
||||
this.session.onParticipantLeft(params);
|
||||
|
@ -358,11 +351,9 @@ export class OpenViduInternal {
|
|||
};
|
||||
|
||||
//CHAT
|
||||
sendMessage(room, user, message) {
|
||||
sendMessage(message) {
|
||||
this.sendRequest('sendMessage', {
|
||||
message: message,
|
||||
userMessage: user,
|
||||
roomMessage: room
|
||||
message: message
|
||||
}, function (error, response) {
|
||||
if (error) {
|
||||
console.error(error);
|
||||
|
@ -370,11 +361,6 @@ export class OpenViduInternal {
|
|||
});
|
||||
};
|
||||
|
||||
sendCustomRequest(params, callback) {
|
||||
this.sendRequest('customRequest', params, callback);
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
toggleLocalVideoTrack(activate: boolean) {
|
||||
|
|
|
@ -2,6 +2,7 @@ import { Stream } from './Stream';
|
|||
import { OpenViduInternal } from './OpenViduInternal';
|
||||
import { Connection, ConnectionOptions } from './Connection';
|
||||
import EventEmitter = require('wolfy87-eventemitter');
|
||||
import { Publisher } from '../OpenVidu/Publisher';
|
||||
|
||||
const SECRET_PARAM = '?secret=';
|
||||
|
||||
|
@ -177,10 +178,6 @@ export class SessionInternal {
|
|||
}
|
||||
});
|
||||
}
|
||||
|
||||
publish() {
|
||||
this.openVidu.getCamera().publish();
|
||||
}
|
||||
/* NEW METHODS */
|
||||
|
||||
|
||||
|
@ -244,17 +241,18 @@ export class SessionInternal {
|
|||
stream.subscribe();
|
||||
}
|
||||
|
||||
unsubscribe(stream) {
|
||||
console.info("Unsubscribing from " + stream.streamId);
|
||||
unsubscribe(stream: Stream) {
|
||||
console.info("Unsubscribing from " + stream.connection.connectionId);
|
||||
this.openVidu.sendRequest('unsubscribeFromVideo', {
|
||||
sender: stream.streamId
|
||||
sender: stream.connection.connectionId
|
||||
},
|
||||
function (error, response) {
|
||||
(error, response) => {
|
||||
if (error) {
|
||||
console.error("Error unsubscribing from Subscriber", error);
|
||||
} else {
|
||||
console.info("Unsubscribed correctly from " + stream.streamId);
|
||||
console.info("Unsubscribed correctly from " + stream.connection.connectionId);
|
||||
}
|
||||
stream.dispose();
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -293,11 +291,44 @@ export class SessionInternal {
|
|||
stream.subscribe();
|
||||
}
|
||||
this.ee.emitEvent('streamCreated', [{ stream }]);
|
||||
|
||||
// Adding the remote stream to the OpenVidu object
|
||||
this.openVidu.getRemoteStreams().push(stream);
|
||||
}
|
||||
}
|
||||
|
||||
onParticipantUnpublished(msg) {
|
||||
let connection: Connection = this.participants[msg.name];
|
||||
|
||||
if (connection !== undefined) {
|
||||
|
||||
let streams = connection.getStreams();
|
||||
for (let key in streams) {
|
||||
this.ee.emitEvent('streamDestroyed', [{
|
||||
stream: streams[key],
|
||||
preventDefault: () => { this.ee.removeEvent('stream-destroyed-default'); }
|
||||
}]);
|
||||
this.ee.emitEvent('stream-destroyed-default', [{
|
||||
stream: streams[key]
|
||||
}]);
|
||||
|
||||
// Deleting the removed stream from the OpenVidu object
|
||||
let index = this.openVidu.getRemoteStreams().indexOf(streams[key]);
|
||||
let stream = this.openVidu.getRemoteStreams()[index];
|
||||
|
||||
|
||||
stream.dispose();
|
||||
this.openVidu.getRemoteStreams().splice(index, 1);
|
||||
delete this.streams[stream.streamId];
|
||||
|
||||
}
|
||||
} else {
|
||||
console.warn("Participant " + msg.name
|
||||
+ " unknown. Participants: "
|
||||
+ JSON.stringify(this.participants));
|
||||
}
|
||||
}
|
||||
|
||||
onParticipantJoined(msg) {
|
||||
|
||||
let connection = new Connection(this.openVidu, false, this, msg);
|
||||
|
@ -325,7 +356,7 @@ export class SessionInternal {
|
|||
|
||||
onParticipantLeft(msg) {
|
||||
|
||||
let connection = this.participants[msg.name];
|
||||
let connection: Connection = this.participants[msg.name];
|
||||
|
||||
if (connection !== undefined) {
|
||||
delete this.participants[msg.name];
|
||||
|
@ -516,21 +547,22 @@ export class SessionInternal {
|
|||
}
|
||||
}
|
||||
|
||||
unpublish(stream: Stream) {
|
||||
unpublish(publisher: Publisher) {
|
||||
|
||||
let connection = stream.getParticipant();
|
||||
if (!connection) {
|
||||
console.error("Stream to disconnect has no participant", stream);
|
||||
let stream = publisher.stream;
|
||||
|
||||
if (!stream.connection) {
|
||||
console.error("The associated Connection object of this Publisher is null", stream);
|
||||
return;
|
||||
}
|
||||
} else if (stream.connection !== this.localParticipant) {
|
||||
console.error("The associated Connection object of this Publisher is not your local Connection." +
|
||||
"Only moderators can force unpublish on remote Streams via 'forceUnpublish' method", stream);
|
||||
return;
|
||||
} else {
|
||||
stream.dispose();
|
||||
|
||||
if (connection === this.localParticipant) {
|
||||
console.info("Unpublishing local media (" + stream.connection.connectionId + ")");
|
||||
|
||||
delete this.participants[connection.connectionId];
|
||||
connection.dispose();
|
||||
|
||||
console.info("Unpublishing my media (I'm " + connection.connectionId + ")");
|
||||
delete this.localParticipant;
|
||||
this.openVidu.sendRequest('unpublishVideo', function (error, response) {
|
||||
if (error) {
|
||||
console.error(error);
|
||||
|
@ -538,6 +570,17 @@ export class SessionInternal {
|
|||
console.info("Media unpublished correctly");
|
||||
}
|
||||
});
|
||||
|
||||
stream.isReadyToPublish = false;
|
||||
stream.isScreenRequestedReady = false;
|
||||
|
||||
publisher.ee.emitEvent('streamDestroyed', [{
|
||||
stream: publisher.stream,
|
||||
preventDefault: () => { this.ee.removeEvent('stream-destroyed-default'); }
|
||||
}]);
|
||||
publisher.ee.emitEvent('stream-destroyed-default', [{
|
||||
stream: publisher.stream
|
||||
}]);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -45,11 +45,6 @@ export interface StreamOptions {
|
|||
mediaConstraints: any;
|
||||
}
|
||||
|
||||
export interface VideoOptions {
|
||||
thumb: string;
|
||||
video: HTMLVideoElement;
|
||||
}
|
||||
|
||||
export class Stream {
|
||||
|
||||
public connection: Connection;
|
||||
|
@ -62,8 +57,6 @@ export class Stream {
|
|||
private wrStream: MediaStream;
|
||||
private wp: any;
|
||||
private video: HTMLVideoElement;
|
||||
private videoElements: VideoOptions[] = [];
|
||||
private elements: HTMLDivElement[] = [];
|
||||
private speechEvent: any;
|
||||
private recvVideo: boolean;
|
||||
private recvAudio: boolean;
|
||||
|
@ -79,7 +72,7 @@ export class Stream {
|
|||
private activeAudio = true;
|
||||
private activeVideo = true;
|
||||
|
||||
private videoSrcObject: MediaStream | null;
|
||||
private videoSrcObject: MediaStream;
|
||||
private parentId: string;
|
||||
public isReadyToPublish: boolean = false;
|
||||
public isPublisherPublished: boolean = false;
|
||||
|
@ -122,6 +115,7 @@ export class Stream {
|
|||
removeVideo();
|
||||
|
||||
removeVideo(parentElement?) {
|
||||
if (this.video) {
|
||||
if (typeof parentElement === "string") {
|
||||
document.getElementById(parentElement)!.removeChild(this.video);
|
||||
} else if (parentElement instanceof Element) {
|
||||
|
@ -132,6 +126,8 @@ export class Stream {
|
|||
document.getElementById(this.parentId)!.removeChild(this.video);
|
||||
}
|
||||
}
|
||||
delete this.video;
|
||||
}
|
||||
}
|
||||
|
||||
getVideoElement(): HTMLVideoElement {
|
||||
|
@ -142,6 +138,10 @@ export class Stream {
|
|||
this.video = video;
|
||||
}
|
||||
|
||||
getParentId() {
|
||||
return this.parentId;
|
||||
}
|
||||
|
||||
getRecvVideo() {
|
||||
return this.recvVideo;
|
||||
}
|
||||
|
@ -259,11 +259,6 @@ export class Stream {
|
|||
this.video.controls = false;
|
||||
this.video.srcObject = this.videoSrcObject;
|
||||
|
||||
this.videoElements.push({
|
||||
thumb: thumbnailId,
|
||||
video: this.video
|
||||
});
|
||||
|
||||
if (this.local && !this.displayMyRemote()) {
|
||||
this.video.muted = true;
|
||||
this.video.oncanplay = () => {
|
||||
|
@ -307,8 +302,6 @@ export class Stream {
|
|||
thumbnail.appendChild(container);
|
||||
}
|
||||
|
||||
this.elements.push(container);
|
||||
|
||||
let name = document.createElement('div');
|
||||
container.appendChild(name);
|
||||
let userName = this.streamId.replace('_webcam', '');
|
||||
|
@ -598,26 +591,23 @@ export class Stream {
|
|||
|
||||
}
|
||||
}
|
||||
for (let videoElement of this.videoElements) {
|
||||
let thumbnailId = videoElement.thumb;
|
||||
let video = videoElement.video;
|
||||
video.srcObject = this.wrStream;
|
||||
video.oncanplay = () => {
|
||||
//let thumbnailId = this.video.thumb;
|
||||
this.video.srcObject = this.wrStream;
|
||||
this.video.oncanplay = () => {
|
||||
if (this.local && this.displayMyRemote()) {
|
||||
console.info("Your own remote 'Stream' with id [" + this.streamId + "] video is now playing");
|
||||
this.ee.emitEvent('remote-video-is-playing', [{
|
||||
element: video
|
||||
element: this.video
|
||||
}]);
|
||||
} else if (!this.local && !this.displayMyRemote()) {
|
||||
console.info("Remote 'Stream' with id [" + this.streamId + "] video is now playing");
|
||||
this.ee.emitEvent('video-is-playing', [{
|
||||
element: video
|
||||
element: this.video
|
||||
}]);
|
||||
}
|
||||
//show(thumbnailId);
|
||||
//this.hideSpinner(this.streamId);
|
||||
};
|
||||
}
|
||||
this.room.emitEvent('stream-subscribed', [{
|
||||
stream: this
|
||||
}]);
|
||||
|
@ -657,10 +647,6 @@ export class Stream {
|
|||
}
|
||||
}
|
||||
|
||||
this.elements.forEach(e => disposeElement(e));
|
||||
|
||||
//this.videoElements.forEach(ve => disposeElement(ve.video));
|
||||
|
||||
disposeElement("progress-" + this.streamId);
|
||||
|
||||
if (this.wp) {
|
||||
|
|
Loading…
Reference in New Issue