'Session.unpublish(Publisher)' feature working

pull/30/head
pabloFuente 2018-01-10 15:00:52 +01:00
parent fcf535dea4
commit f348b5380a
8 changed files with 162 additions and 128 deletions

View File

@ -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 {

View File

@ -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
}]);

View File

@ -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));
}
}

View File

@ -1,4 +1,4 @@
import { Stream, StreamOptions, VideoOptions } from '../OpenViduInternal/Stream';
import { Stream, StreamOptions } from '../OpenViduInternal/Stream';
import EventEmitter = require('wolfy87-eventemitter');

View File

@ -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 );

View File

@ -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) {

View File

@ -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
}]);
}
}

View File

@ -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) {