Changed name from lastN to spotlights

master
Håvar Aambø Fosstveit 2018-10-29 16:05:54 +01:00
parent ed5ef29fba
commit aeaaa010c5
6 changed files with 183 additions and 47 deletions

View File

@ -3,7 +3,7 @@ import * as mediasoupClient from 'mediasoup-client';
import Logger from './Logger'; import Logger from './Logger';
import hark from 'hark'; import hark from 'hark';
import ScreenShare from './ScreenShare'; import ScreenShare from './ScreenShare';
import LastN from './LastN'; import Spotlights from './Spotlights';
import { getSignalingUrl } from './urlFactory'; import { getSignalingUrl } from './urlFactory';
import * as cookiesManager from './cookiesManager'; import * as cookiesManager from './cookiesManager';
import * as requestActions from './redux/requestActions'; import * as requestActions from './redux/requestActions';
@ -21,7 +21,7 @@ const ROOM_OPTIONS =
requestTimeout : requestTimeout, requestTimeout : requestTimeout,
transportOptions : transportOptions, transportOptions : transportOptions,
turnServers : turnServers, turnServers : turnServers,
lastN : 2 maxSpotlights : 4
}; };
const VIDEO_CONSTRAINS = const VIDEO_CONSTRAINS =
@ -72,11 +72,11 @@ export default class RoomClient
this._room = new mediasoupClient.Room(ROOM_OPTIONS); this._room = new mediasoupClient.Room(ROOM_OPTIONS);
this._room.roomId = roomId; this._room.roomId = roomId;
// LastN speakers // Max spotlights
this._lastNSpeakers = ROOM_OPTIONS.lastN; this._maxSpotlights = ROOM_OPTIONS.maxSpotlights;
// Array of lastN speakers // Manager of spotlight
this._lastN = new LastN(this._lastNSpeakers, this._room); this._spotlights = new Spotlights(this._maxSpotlights, this._room);
// Transport for sending. // Transport for sending.
this._sendTransport = null; this._sendTransport = null;
@ -315,7 +315,7 @@ export default class RoomClient
lastN.splice(index, 1); lastN.splice(index, 1);
this._lastN.addSpeakerList(lastN); this._spotlights.addSpeakerList(lastN);
} }
} }
catch (error) catch (error)
@ -340,16 +340,16 @@ export default class RoomClient
this._micProducer.resume(); this._micProducer.resume();
} }
// Updated consumers based on lastN // Updated consumers based on spotlights
async updateSpeakers(speakers) async updateSpotlights(spotlights)
{ {
logger.debug('updateSpeakers()'); logger.debug('updateSpotlights()');
try try
{ {
for (const peer of this._room.peers) for (const peer of this._room.peers)
{ {
if (speakers.indexOf(peer.name) > -1) // Resume video for speaker if (spotlights.indexOf(peer.name) > -1) // Resume video for speaker
{ {
for (const consumer of peer.consumers) for (const consumer of peer.consumers)
{ {
@ -373,7 +373,7 @@ export default class RoomClient
} }
catch (error) catch (error)
{ {
logger.error('updateSpeakers() failed: %o', error); logger.error('updateSpotlights() failed: %o', error);
} }
} }
@ -1036,7 +1036,7 @@ export default class RoomClient
stateActions.setRoomActiveSpeaker(peerName)); stateActions.setRoomActiveSpeaker(peerName));
if (peerName && peerName !== this._peerName) if (peerName && peerName !== this._peerName)
this._lastN.handleActiveSpeaker(peerName); this._spotlights.handleActiveSpeaker(peerName);
}); });
this._signalingSocket.on('display-name-changed', (data) => this._signalingSocket.on('display-name-changed', (data) =>
@ -1228,10 +1228,10 @@ export default class RoomClient
this.notify('You are in the room'); this.notify('You are in the room');
this._lastN.on('lastn-updated', (lastN) => this._spotlights.on('spotlights-updated', (spotlights) =>
{ {
this._dispatch(stateActions.setLastN(lastN)); this._dispatch(stateActions.setSpotlights(spotlights));
this.updateSpeakers(lastN); this.updateSpotlights(spotlights);
}); });
const peers = this._room.peers; const peers = this._room.peers;
@ -1241,7 +1241,7 @@ export default class RoomClient
this._handlePeer(peer, { notify: false }); this._handlePeer(peer, { notify: false });
} }
this._lastN.start(); this._spotlights.start();
} }
catch (error) catch (error)
{ {
@ -1831,7 +1831,8 @@ export default class RoomClient
// Receive the consumer (if we can). // Receive the consumer (if we can).
if (consumer.supported) if (consumer.supported)
{ {
if (consumer.kind === 'video' && !this._lastN.peerInLastN(consumer.peer.name)) if (consumer.kind === 'video' &&
!this._spotlights.peerInSpotlights(consumer.peer.name))
{ // Start paused { // Start paused
logger.debug( logger.debug(
'consumer paused by default'); 'consumer paused by default');

View File

@ -0,0 +1,135 @@
import { EventEmitter } from 'events';
import Logger from './Logger';
const logger = new Logger('Spotlight');
export default class Spotlights extends EventEmitter
{
constructor(maxSpotlights, room)
{
super();
this._room = room;
this._maxSpotlights = maxSpotlights;
this._peerList = [];
this._currentSpotlights = [];
this._started = false;
}
start()
{
const peers = this._room.peers;
for (const peer of peers)
{
this._handlePeer(peer);
}
this._handleRoom();
this._started = true;
this._spotlightsUpdated();
}
peerInSpotlights(peerName)
{
if (this._started)
{
return this._currentSpotlights.indexOf(peerName) !== -1;
}
else
{
return false;
}
}
_handleRoom()
{
this._room.on('newpeer', (peer) =>
{
logger.debug(
'room "newpeer" event [name:"%s", peer:%o]', peer.name, peer);
this._handlePeer(peer);
});
}
addSpeakerList(speakerList)
{
this._peerList = [ ...new Set([ ...speakerList, ...this._peerList ]) ];
if (this._started)
this._spotlightsUpdated();
}
_handlePeer(peer)
{
logger.debug('_handlePeer() [peerName:"%s"]', peer.name);
if (this._peerList.indexOf(peer.name) === -1) // We don't have this peer in the list
{
peer.on('close', () =>
{
const index = this._peerList.indexOf(peer.name);
if (index > -1) // We have this peer in the list, remove
{
this._peerList.splice(index, 1);
this._spotlightsUpdated();
}
});
logger.debug('_handlePeer() | adding peer [peerName:"%s"]', peer.name);
this._peerList.push(peer.name);
this._spotlightsUpdated();
}
}
handleActiveSpeaker(peerName)
{
logger.debug('handleActiveSpeaker() [peerName:"%s"]', peerName);
const index = this._peerList.indexOf(peerName);
if (index > -1)
{
this._peerList.splice(index, 1);
this._peerList = [ peerName ].concat(this._peerList);
this._spotlightsUpdated();
}
}
_spotlightsUpdated()
{
if (
!this._arraysEqual(
this._currentSpotlights, this._peerList.slice(0, this._maxSpotlights)
)
)
{
logger.debug('_spotlightsUpdated() | spotlights updated, emitting');
this._currentSpotlights = this._peerList.slice(0, this._maxSpotlights);
this.emit('spotlights-updated', this._currentSpotlights);
}
else
logger.debug('_spotlightsUpdated() | spotlights not updated');
}
_arraysEqual(arr1, arr2)
{
if (arr1.length !== arr2.length)
return false;
for (let i = arr1.length; i--;)
{
if (arr1[i] !== arr2[i])
return false;
}
return true;
}
}

View File

@ -114,7 +114,7 @@ class Filmstrip extends Component
render() render()
{ {
const { peers, advancedMode, lastN, lastNLength } = this.props; const { peers, advancedMode, spotlights, spotlightsLength } = this.props;
const activePeerName = this.getActivePeerName(); const activePeerName = this.getActivePeerName();
@ -143,7 +143,7 @@ class Filmstrip extends Component
Object.keys(peers).map((peerName) => Object.keys(peers).map((peerName) =>
{ {
return ( return (
lastN.find((lastNElement) => lastNElement === peerName)? spotlights.find((spotlightsElement) => spotlightsElement === peerName)?
<div <div
key={peerName} key={peerName}
onClick={() => this.props.setSelectedPeer(peerName)} onClick={() => this.props.setSelectedPeer(peerName)}
@ -166,9 +166,9 @@ class Filmstrip extends Component
</div> </div>
</div> </div>
<div className='hidden-peer-container'> <div className='hidden-peer-container'>
{ (lastNLength<Object.keys(peers).length)? { (spotlightsLength<Object.keys(peers).length)?
<HiddenPeers <HiddenPeers
lastNLength={Object.keys(peers).length-lastNLength} spotlightsLength={Object.keys(peers).length-spotlightsLength}
/>:null />:null
} }
</div> </div>
@ -186,13 +186,13 @@ Filmstrip.propTypes = {
myName : PropTypes.string.isRequired, myName : PropTypes.string.isRequired,
selectedPeerName : PropTypes.string, selectedPeerName : PropTypes.string,
setSelectedPeer : PropTypes.func.isRequired, setSelectedPeer : PropTypes.func.isRequired,
lastNLength : PropTypes.number, spotlightsLength : PropTypes.number,
lastN : PropTypes.array.isRequired spotlights : PropTypes.array.isRequired
}; };
const mapStateToProps = (state) => const mapStateToProps = (state) =>
{ {
const lastNLength = state.room.lastN ? state.room.lastN.length : 0; const spotlightsLength = state.room.spotlights ? state.room.spotlights.length : 0;
return { return {
activeSpeakerName : state.room.activeSpeakerName, activeSpeakerName : state.room.activeSpeakerName,
@ -200,8 +200,8 @@ const mapStateToProps = (state) =>
peers : state.peers, peers : state.peers,
consumers : state.consumers, consumers : state.consumers,
myName : state.me.name, myName : state.me.name,
lastN : state.room.lastN, spotlights : state.room.spotlights,
lastNLength spotlightsLength
}; };
}; };

View File

@ -93,8 +93,8 @@ class Peers extends React.Component
advancedMode, advancedMode,
activeSpeakerName, activeSpeakerName,
peers, peers,
lastN, spotlights,
lastNLength spotlightsLength
} = this.props; } = this.props;
const style = const style =
@ -109,8 +109,8 @@ class Peers extends React.Component
peers.map((peer) => peers.map((peer) =>
{ {
return ( return (
(lastN.find(function(lastNElement) (spotlights.find(function(spotlightsElement)
{ return lastNElement == peer.name; }))? { return spotlightsElement == peer.name; }))?
<Appear key={peer.name} duration={1000}> <Appear key={peer.name} duration={1000}>
<div <div
className={classnames('peer-container', { className={classnames('peer-container', {
@ -129,9 +129,9 @@ class Peers extends React.Component
}) })
} }
<div className='hidden-peer-container'> <div className='hidden-peer-container'>
{ (lastNLength<peers.length)? { (spotlightsLength<peers.length)?
<HiddenPeers <HiddenPeers
lastNLength={peers.length-lastNLength} spotlightsLength={peers.length-spotlightsLength}
/>:null />:null
} }
</div> </div>
@ -146,24 +146,24 @@ Peers.propTypes =
peers : PropTypes.arrayOf(appPropTypes.Peer).isRequired, peers : PropTypes.arrayOf(appPropTypes.Peer).isRequired,
boxes : PropTypes.number, boxes : PropTypes.number,
activeSpeakerName : PropTypes.string, activeSpeakerName : PropTypes.string,
lastNLength : PropTypes.number, spotlightsLength : PropTypes.number,
lastN : PropTypes.array.isRequired spotlights : PropTypes.array.isRequired
}; };
const mapStateToProps = (state) => const mapStateToProps = (state) =>
{ {
const peers = Object.values(state.peers); const peers = Object.values(state.peers);
const lastN = state.room.lastN; const spotlights = state.room.spotlights;
const lastNLength = lastN ? state.room.lastN.length : 0; const spotlightsLength = spotlights ? state.room.spotlights.length : 0;
const boxes = lastNLength + Object.values(state.consumers) const boxes = spotlightsLength + Object.values(state.consumers)
.filter((consumer) => consumer.source === 'screen').length; .filter((consumer) => consumer.source === 'screen').length;
return { return {
peers, peers,
boxes, boxes,
activeSpeakerName : state.room.activeSpeakerName, activeSpeakerName : state.room.activeSpeakerName,
lastN, spotlights,
lastNLength spotlightsLength
}; };
}; };

View File

@ -9,7 +9,7 @@ const initialState =
toolbarsVisible : true, toolbarsVisible : true,
mode : 'democratic', mode : 'democratic',
selectedPeerName : null, selectedPeerName : null,
lastN : [] spotlights : []
}; };
const room = (state = initialState, action) => const room = (state = initialState, action) =>
@ -84,11 +84,11 @@ const room = (state = initialState, action) =>
}; };
} }
case 'SET_LASTN': case 'SET_SPOTLIGHTS':
{ {
const { lastN } = action.payload; const { spotlights } = action.payload;
return { ...state, lastN }; return { ...state, spotlights };
} }
default: default:

View File

@ -494,8 +494,8 @@ export const setSelectedPeer = (selectedPeerName) =>
payload : { selectedPeerName } payload : { selectedPeerName }
}); });
export const setLastN = (lastN) => export const setSpotlights = (spotlights) =>
({ ({
type : 'SET_LASTN', type : 'SET_SPOTLIGHTS',
payload : { lastN } payload : { spotlights }
}); });