/
video.js
138 lines (123 loc) · 4.45 KB
/
video.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
import StateMachine from 'javascript-state-machine';
import StateMachineHistory from 'javascript-state-machine/lib/history';
import LoggerProxy from '../common/logs/logger-proxy';
import Media from '../media';
import MeetingUtil from '../meeting/util';
import {MEETING_VIDEO_STATE_MACHINE} from '../constants';
const handleTransition = (video) => {
if (video.mute && video.self) {
return MEETING_VIDEO_STATE_MACHINE.STATES.MUTE_SELF;
}
if (!video.mute && video.self) {
return MEETING_VIDEO_STATE_MACHINE.STATES.UNMUTE_SELF;
}
return null;
};
const doToggle = (transition, video, meeting) => {
Media.setLocalTrack(video.mute, meeting.mediaProperties.videoTrack);
const meetingAudio = meeting.audio;
const audioMuted = meetingAudio ? meetingAudio.muted : true;
return MeetingUtil.remoteUpdateAudioVideo(audioMuted, video.mute, meeting)
.then(() => {
LoggerProxy.logger.log(
`VideoStateMachine->onAfterToggle#${transition.event} fired! State changed from '${transition.from}' to '${
transition.to
}' with transition '${transition.transition}''.`
);
})
.catch((remoteUpdateError) => {
LoggerProxy.logger.log(
`VideoStateMachine->onBeforeToggle#${transition.event} fired! State failed to change with transition '${
transition.transition
}''. After local Video toggle failed, resetting remote also failed, meeting video in bad state with error: ${remoteUpdateError}.`
);
return Promise.reject(remoteUpdateError);
});
};
const VideoStateMachine = {
/**
*
* @param {Object} mediaDirection object containing media direction
* @param {Boolean} mediaDirection.sendVideo Whether or not to send video in the meeting
* @param {Meeting} meeting an instance of a Meeting
* @returns {Statemachine} returns a state machine instance
*/
create(mediaDirection, meeting) {
if (!mediaDirection.sendVideo) {
return undefined;
}
return new StateMachine({
transitions: [
{
name: MEETING_VIDEO_STATE_MACHINE.TRANSITIONS.TOGGLE,
from: '*',
/**
*
* @param {Object} video current video data for the transition {mute, self}
* @returns {String} a new state value for the transition
*/
to(video) {
return handleTransition(video) || this.state;
}
}
],
data: {
muted: false,
self: true
},
methods: {
/**
* Convenience function to tell whether we are muted or not
* @returns {Boolen} boolean that indicates whether the video is currently muted
*/
isMuted() {
return this.muted;
},
/**
* Convenience function to tell who last muted/unmuted the video
* @returns {Boolen} boolean that indicates whether the video was muted by the end user or server
*/
isSelf() {
return this.self;
},
/**
*
* @param {Object} video current video options to set on the state machine
* @param {Boolean} video.mute indicates if video is muted or not for a meeting
* @param {Boolean} video.self indicates whether the end user or server muted the video
* @returns {null}
*/
setData(video) {
this.muted = video.mute;
this.self = video.self;
},
/**
* Method that gets fired before the toggle state change.
* If this fails, return false will cancel the transition and the state will remain unchanged
* @param {Object} transition the StateMachine transition object
* @param {Object} video video options
* @returns {Object} this.data which contains {muted, self}
*/
onBeforeToggle(transition, video) {
if (transition.from !== transition.to) {
return doToggle(transition, video, meeting)
.then(() => Promise.resolve(this.data));
}
return Promise.resolve(this.data);
},
/**
*
* @param {Object} transition StateMachine transition
* @param {Object} video video options
* @returns {Object} this.data which contains {muted, self}
*/
onAfterToggle(transition, video) {
this.setData(video);
return Promise.resolve(this.data);
},
plugins: [new StateMachineHistory({max: 5})]
}
});
}
};
export default VideoStateMachine;