-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Expand file tree
/
Copy pathAudioLevelObserver.ts
More file actions
127 lines (108 loc) · 3.2 KB
/
AudioLevelObserver.ts
File metadata and controls
127 lines (108 loc) · 3.2 KB
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
import { Logger } from './Logger';
import { EnhancedEventEmitter } from './enhancedEvents';
import type {
AudioLevelObserver,
AudioLevelObserverVolume,
AudioLevelObserverEvents,
AudioLevelObserverObserver,
AudioLevelObserverObserverEvents,
} from './AudioLevelObserverTypes';
import type { RtpObserver } from './RtpObserverTypes';
import { RtpObserverImpl, RtpObserverConstructorOptions } from './RtpObserver';
import type { Producer } from './ProducerTypes';
import type { AppData } from './types';
import * as fbsUtils from './fbsUtils';
import { Event, Notification } from './fbs/notification';
import * as FbsAudioLevelObserver from './fbs/audio-level-observer';
type AudioLevelObserverConstructorOptions<AudioLevelObserverAppData> =
RtpObserverConstructorOptions<AudioLevelObserverAppData>;
const logger = new Logger('AudioLevelObserver');
export class AudioLevelObserverImpl<
AudioLevelObserverAppData extends AppData = AppData,
>
extends RtpObserverImpl<
AudioLevelObserverAppData,
AudioLevelObserverEvents,
AudioLevelObserverObserver
>
implements RtpObserver, AudioLevelObserver
{
constructor(
options: AudioLevelObserverConstructorOptions<AudioLevelObserverAppData>
) {
const observer: AudioLevelObserverObserver =
new EnhancedEventEmitter<AudioLevelObserverObserverEvents>();
super(options, observer);
this.handleWorkerNotifications();
this.handleListenerError();
}
get type(): 'audiolevel' {
return 'audiolevel';
}
override get observer(): AudioLevelObserverObserver {
return super.observer;
}
private handleWorkerNotifications(): void {
this.channel.on(
this.internal.rtpObserverId,
(event: Event, data?: Notification) => {
switch (event) {
case Event.AUDIOLEVELOBSERVER_VOLUMES: {
const notification =
new FbsAudioLevelObserver.VolumesNotification();
data!.body(notification);
// Get the corresponding Producer instance and remove entries with
// no Producer (it may have been closed in the meanwhile).
const volumes: AudioLevelObserverVolume[] = fbsUtils
.parseVector(notification, 'volumes', parseVolume)
.map(
({
producerId,
volume,
}: {
producerId: string;
volume: number;
}) => ({
producer: this.getProducerById(producerId)!,
volume,
})
)
.filter(({ producer }: { producer: Producer }) => producer);
if (volumes.length > 0) {
this.safeEmit('volumes', volumes);
// Emit observer event.
this.observer.safeEmit('volumes', volumes);
}
break;
}
case Event.AUDIOLEVELOBSERVER_SILENCE: {
this.safeEmit('silence');
// Emit observer event.
this.observer.safeEmit('silence');
break;
}
default: {
logger.error(`ignoring unknown event "${event}"`);
}
}
}
);
}
private handleListenerError(): void {
this.on('listenererror', (eventName, error) => {
logger.error(
`event listener threw an error [eventName:${eventName}]:`,
error
);
});
}
}
function parseVolume(binary: FbsAudioLevelObserver.Volume): {
producerId: string;
volume: number;
} {
return {
producerId: binary.producerId()!,
volume: binary.volume(),
};
}