UNPKG

4.8 kBJavaScriptView Raw
1import filter from 'lodash/filter';
2import orderBy from 'lodash/orderBy';
3
4export const getLocalSubscriptionToTrack = (state, id, mediaTag) => {
5 return _getSubscriptionToTrack(state.local, id, mediaTag);
6};
7
8export const getLocalIsSubscribedToTrack = (state, id, mediaTag) => {
9 return _getSubscriptionToTrack(state.local, id, mediaTag) === true;
10};
11
12// NOTE: only meant for use in P2P mode, where we have access to remote
13// participants' subscriptions info.
14export const getRemoteParticipantIsSubscribedToLocalTrack = (
15 state,
16 id,
17 mediaTag
18) => {
19 return (
20 _getSubscriptionToTrack(
21 state.participants[id],
22 state.local.public.id,
23 mediaTag
24 ) === true
25 );
26};
27
28// type is "cam" or "screen"
29// kind is "video" or "audio"
30export const getLocalTrack = (state, type, kind) => {
31 return (
32 state.local.streams &&
33 state.local.streams[type] &&
34 state.local.streams[type].stream &&
35 state.local.streams[type].stream[
36 `get${kind === 'video' ? 'Video' : 'Audio'}Tracks`
37 ]()[0]
38 );
39};
40
41// kind is "video" or "audio"
42// for standard tracks, type is "cam" or "screen"
43// for custom tracks, type is the mediaTag
44export const getRemoteTrack = (state, participantId, type, kind) => {
45 const streamEntry = _getRemoteStreamEntry(state, participantId, type, kind);
46 return streamEntry && streamEntry.pendingTrack;
47};
48
49// type is "cam" or "screen"
50// kind is "video" or "audio"
51export const getIsRemoteTrackLoading = (state, participantId, type, kind) => {
52 const participant = state.participants && state.participants[participantId];
53 const loadedTracks =
54 participant && participant.public && participant.public.loadedTracks;
55 if (loadedTracks) {
56 if (type === 'cam') {
57 return !loadedTracks[kind];
58 } else if (type === 'screen') {
59 return !loadedTracks[
60 `screen${kind.charAt(0).toUpperCase() + kind.slice(1)}`
61 ];
62 } else {
63 return !loadedTracks[type];
64 }
65 }
66 return false;
67};
68
69// NOTE: maps 'avatar' to true. 'avatar' is deprecated with the new prebuilt ui
70// and is currently accessed directly from redux anyway (not via this selector)
71// where it's needed.
72const _getSubscriptionToTrack = (subscriber, subscribeeId, mediaTag) => {
73 // if we don't have a participant record at all, assume that
74 // false is the safest thing to return, here
75 if (!subscriber) {
76 return false;
77 }
78 const mapToTrueFalseStaged = (subscription) => {
79 switch (subscription) {
80 case 'avatar':
81 return true;
82 case 'staged':
83 return subscription;
84 default:
85 // boolean or undefined
86 return !!subscription;
87 }
88 };
89 const sTracks = subscriber.public.subscribedTracks;
90 // Below shows the return values for all the various versions of sTracks
91 // { ALL: true } -> true
92 // { ALL: false } -> false
93 // { ALL: 'staged' } -> 'staged'
94 // { ALL: 'avatar' } -> true
95 // undefined -> true // this should never happen
96 // {}, -> false
97 // { p2id: { }} -> false
98 // { p2id: { mediaTag: true }} -> true
99 // { p2id: { mediaTag: false }} -> false
100 // { p2id: { mediaTag: 'staged' }} -> 'staged'
101 // { p2id: { mediaTag: 'avatar' }} -> true
102 if (!(sTracks && sTracks[subscribeeId])) {
103 return sTracks ? mapToTrueFalseStaged(sTracks.ALL) : true;
104 }
105
106 return mapToTrueFalseStaged(sTracks[subscribeeId][mediaTag]);
107};
108
109const _getRemoteStreamEntry = (state, participantId, type, kind) => {
110 let streams = orderBy(
111 filter(
112 state.streams,
113 (s) =>
114 s.participantId === participantId &&
115 s.type === type &&
116 s.pendingTrack &&
117 s.pendingTrack.kind === kind
118 ),
119 'starttime',
120 'desc'
121 );
122 return streams && streams[0];
123};
124
125export const getLocalCustomTrack = (state, trackEntryKey) => {
126 const trackEntries = state.local.public.customTracks;
127 if (!(trackEntries && trackEntries[trackEntryKey])) {
128 return;
129 }
130 return trackEntries[trackEntryKey].track;
131};
132
133export const getRemoteCustomTrack = (state, participantId, mediaTag, kind) => {
134 // for now, we only support sfu mode for custom tracks. the streamId is always
135 // prepended with "soup-" sfu-mode tracks. ("streamId" is a very old name that
136 // dates from the era of transitional support for tracks, rather than streams,
137 // in the WebRTC spec.)
138 const streamId = 'soup-' + mediaTag;
139 let streams = orderBy(
140 filter(
141 state.streams,
142 (s) =>
143 s.participantId === participantId &&
144 s.streamId === streamId &&
145 s.pendingTrack &&
146 s.pendingTrack.kind === kind
147 ),
148 'starttime',
149 'desc'
150 );
151 return streams && streams[0] && streams[0].pendingTrack;
152};