Tüm .config dosyaları ilk yedekleme
This commit is contained in:
BIN
discord/0.0.129/modules/discord_voice/discord_voice.node
Normal file
BIN
discord/0.0.129/modules/discord_voice/discord_voice.node
Normal file
Binary file not shown.
534
discord/0.0.129/modules/discord_voice/index.js
Normal file
534
discord/0.0.129/modules/discord_voice/index.js
Normal file
@@ -0,0 +1,534 @@
|
||||
/* eslint-disable no-console */
|
||||
// eslint-disable-next-line import/no-unresolved, import/extensions
|
||||
const VoiceEngine = require('./discord_voice.node');
|
||||
const fs = require('fs');
|
||||
const os = require('os');
|
||||
const process = require('process');
|
||||
const path = require('path');
|
||||
|
||||
const isElectronRenderer =
|
||||
typeof window !== 'undefined' && window != null && window.DiscordNative && window.DiscordNative.isRenderer;
|
||||
|
||||
const appSettings = isElectronRenderer ? window.DiscordNative.settings : global.appSettings;
|
||||
const features = isElectronRenderer ? window.DiscordNative.features : global.features;
|
||||
const mainArgv = isElectronRenderer ? window.DiscordNative.processUtils.getMainArgvSync() : [];
|
||||
|
||||
let dataDirectory;
|
||||
if (isElectronRenderer) {
|
||||
try {
|
||||
dataDirectory =
|
||||
isElectronRenderer && window.DiscordNative.fileManager.getModuleDataPathSync
|
||||
? path.join(window.DiscordNative.fileManager.getModuleDataPathSync(), 'discord_voice')
|
||||
: null;
|
||||
} catch (e) {
|
||||
console.error('Failed to get data directory: ', e);
|
||||
}
|
||||
if (dataDirectory != null) {
|
||||
try {
|
||||
fs.mkdirSync(dataDirectory, {recursive: true});
|
||||
} catch (e) {
|
||||
console.warn("Couldn't create voice data directory ", dataDirectory, ':', e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Init logging
|
||||
const isFileManagerAvailable = window?.DiscordNative?.fileManager;
|
||||
const isLogDirAvailable = isFileManagerAvailable?.getAndCreateLogDirectorySync;
|
||||
let logDirectory;
|
||||
if (isLogDirAvailable) {
|
||||
logDirectory = window.DiscordNative.fileManager.getAndCreateLogDirectorySync();
|
||||
// TODO If/when we move away from utilizing webRTC logging in voice:
|
||||
// This module uses a different approach to the log-level, particularly an integer value rather than a string.
|
||||
// We should eventually try to align on the string approach (and querying it from our common settings) used by other modules.
|
||||
// logLevel = window.DiscordNative.fileManager.logLevelSync();
|
||||
} else {
|
||||
console.warn('Unable to find log directory');
|
||||
}
|
||||
|
||||
const defaultAudioSubsystem = process.platform === 'win32' ? 'experimental' : 'standard';
|
||||
const audioSubsystem = appSettings
|
||||
? appSettings.getSync('audioSubsystem', defaultAudioSubsystem)
|
||||
: defaultAudioSubsystem;
|
||||
const offloadAdmControls = appSettings ? appSettings.getSync('offloadAdmControls', false) : false;
|
||||
const debugLogging = appSettings ? appSettings.getSync('debugLogging', true) : true;
|
||||
const maxLogBytesRaw = appSettings ? appSettings.getSync('maxLogBytes', 5000000) : 5000000;
|
||||
// Clamp to [1, 2^32-1] to safely fit in a size_t on both 32-bit and 64-bit platforms; reject NaN/Infinity/negatives/zero.
|
||||
const maxLogBytes =
|
||||
Number.isFinite(maxLogBytesRaw) && maxLogBytesRaw > 0 ? Math.min(Math.trunc(maxLogBytesRaw), 0xffffffff) : 5000000;
|
||||
const asyncVideoInputDeviceInit = appSettings ? appSettings.getSync('asyncVideoInputDeviceInit', false) : false;
|
||||
|
||||
function versionGreaterThanOrEqual(v1, v2) {
|
||||
const v1parts = v1.split('.').map(Number);
|
||||
const v2parts = v2.split('.').map(Number);
|
||||
|
||||
for (let i = 0; i < Math.max(v1parts.length, v2parts.length); i++) {
|
||||
const num1 = i < v1parts.length ? v1parts[i] : 0;
|
||||
const num2 = i < v2parts.length ? v2parts[i] : 0;
|
||||
if (num1 > num2) return true;
|
||||
if (num1 < num2) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function parseArguments(args) {
|
||||
const parsed = {
|
||||
'log-level': -1,
|
||||
};
|
||||
|
||||
const descriptions = {
|
||||
'log-level': 'Logging level.',
|
||||
'use-fake-video-capture': 'Use fake video capture device.',
|
||||
'use-file-for-fake-video-capture': 'Use local file for fake video capture.',
|
||||
'use-fake-audio-capture': 'Use fake audio capture device.',
|
||||
'use-files-for-fake-audio-capture': 'Use local files for fake audio capture.',
|
||||
};
|
||||
|
||||
for (let i = 0; i < args.length; i++) {
|
||||
const parts = args[i].split('=');
|
||||
const arg = parts[0];
|
||||
const inlineValue = parts.slice(1).join('='); // Join the rest back together in case there are '=' in the value
|
||||
|
||||
function getValue() {
|
||||
if (inlineValue !== undefined) {
|
||||
return inlineValue;
|
||||
}
|
||||
return args[++i];
|
||||
}
|
||||
|
||||
switch (arg) {
|
||||
case '-h':
|
||||
case '--help':
|
||||
console.log('Help requested:');
|
||||
for (const [key, value] of Object.entries(descriptions)) {
|
||||
console.log(`--${key}: ${value}`);
|
||||
}
|
||||
process.exit(0);
|
||||
break;
|
||||
case '--log-level':
|
||||
parsed['log-level'] = parseInt(getValue(), 10);
|
||||
break;
|
||||
case '--use-fake-video-capture':
|
||||
parsed['use-fake-video-capture'] = true;
|
||||
break;
|
||||
case '--use-file-for-fake-video-capture':
|
||||
parsed['use-file-for-fake-video-capture'] = getValue();
|
||||
break;
|
||||
case '--use-fake-audio-capture':
|
||||
parsed['use-fake-audio-capture'] = true;
|
||||
break;
|
||||
case '--use-files-for-fake-audio-capture':
|
||||
parsed['use-files-for-fake-audio-capture'] = getValue();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return parsed;
|
||||
}
|
||||
|
||||
const argv = parseArguments(mainArgv.slice(1));
|
||||
const logLevel = argv['log-level'] === -1 ? (debugLogging ? 2 : -1) : argv['log-level'];
|
||||
const useFakeVideoCapture = argv['use-fake-video-capture'];
|
||||
const useFileForFakeVideoCapture = argv['use-file-for-fake-video-capture'];
|
||||
const useFakeAudioCapture = argv['use-fake-audio-capture'];
|
||||
const useFilesForFakeAudioCapture = argv['use-files-for-fake-audio-capture'];
|
||||
|
||||
features.declareSupported('voice_panning');
|
||||
features.declareSupported('voice_multiple_connections');
|
||||
features.declareSupported('media_devices');
|
||||
features.declareSupported('media_video');
|
||||
features.declareSupported('debug_logging');
|
||||
features.declareSupported('set_audio_device_by_id');
|
||||
features.declareSupported('set_video_device_by_id');
|
||||
features.declareSupported('loopback');
|
||||
features.declareSupported('experiment_config');
|
||||
features.declareSupported('remote_locus_network_control');
|
||||
//features.declareSupported('connection_replay');
|
||||
features.declareSupported('simulcast');
|
||||
features.declareSupported('simulcast_bugfix');
|
||||
features.declareSupported('direct_video');
|
||||
features.declareSupported('electron_video');
|
||||
features.declareSupported('fixed_keyframe_interval');
|
||||
features.declareSupported('first_frame_callback');
|
||||
features.declareSupported('remote_user_multi_stream');
|
||||
features.declareSupported('go_live_hardware');
|
||||
features.declareSupported('bandwidth_estimation_experiments');
|
||||
features.declareSupported('mls_pairwise_fingerprints');
|
||||
features.declareSupported('soundshare');
|
||||
features.declareSupported('screen_soundshare');
|
||||
features.declareSupported('offload_adm_controls');
|
||||
features.declareSupported('audio_codec_red');
|
||||
features.declareSupported('sidechain_compression');
|
||||
features.declareSupported('async_video_input_device_init');
|
||||
features.declareSupported('port_aware_latency_testing');
|
||||
|
||||
if (process.platform === 'darwin') {
|
||||
features.declareSupported('screen_capture_kit');
|
||||
if (versionGreaterThanOrEqual(os.release(), '23.0.0')) {
|
||||
features.declareSupported('native_screenshare_picker');
|
||||
}
|
||||
}
|
||||
|
||||
if (process.platform === 'linux') {
|
||||
// from WebRTC DesktopCapturer::IsRunningUnderWayland()
|
||||
const sessionType = process.env.XDG_SESSION_TYPE;
|
||||
const isUnderWayland = sessionType?.startsWith('wayland') && process.env.WAYLAND_DISPLAY != null;
|
||||
|
||||
const currentDesktop = process.env.XDG_CURRENT_DESKTOP;
|
||||
// we only want to enable the gamescope capturer if we're running in a non-nested gamescope session
|
||||
const isUnderGamescope =
|
||||
!isUnderWayland && currentDesktop?.includes('gamescope') && process.env.GAMESCOPE_WAYLAND_DISPLAY != null;
|
||||
const isVaapiEnabled = VoiceEngine.isVaapiEnabled();
|
||||
|
||||
if (isUnderWayland) {
|
||||
features.declareSupported('native_screenshare_picker');
|
||||
}
|
||||
if (isVaapiEnabled) {
|
||||
features.declareSupported('vaapi');
|
||||
}
|
||||
if (isUnderGamescope && isVaapiEnabled) {
|
||||
// ensure we have access to the pipewire socket
|
||||
const runtimeDir = process.env.PIPEWIRE_RUNTIME_DIR || process.env.XDG_RUNTIME_DIR || process.env.USERPROFILE;
|
||||
if (runtimeDir) {
|
||||
const socketName = runtimeDir + '/' + (process.env.PIPEWIRE_REMOTE || 'pipewire-0');
|
||||
const sstat = fs.statSync(socketName, {throwIfNoEntry: false});
|
||||
if (sstat && sstat.isSocket()) {
|
||||
features.declareSupported('gamescope_capture');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
process.platform === 'win32'
|
||||
|| process.platform === 'linux'
|
||||
|| (process.platform === 'darwin' && versionGreaterThanOrEqual(os.release(), '16.0.0'))
|
||||
) {
|
||||
features.declareSupported('mediapipe');
|
||||
features.declareSupported('mediapipe_animated');
|
||||
}
|
||||
|
||||
if (process.platform === 'win32' || process.platform === 'darwin' || process.platform === 'linux') {
|
||||
features.declareSupported('image_quality_measurement');
|
||||
}
|
||||
|
||||
if (process.platform === 'win32') {
|
||||
features.declareSupported('voice_legacy_subsystem');
|
||||
features.declareSupported('wumpus_video');
|
||||
features.declareSupported('hybrid_video');
|
||||
features.declareSupported('elevated_hook');
|
||||
features.declareSupported('soundshare_loopback');
|
||||
features.declareSupported('screen_previews');
|
||||
features.declareSupported('window_previews');
|
||||
features.declareSupported('audio_debug_state');
|
||||
features.declareSupported('video_effects');
|
||||
features.declareSupported('voice_experimental_subsystem');
|
||||
features.declareSupported('voice_automatic_subsystem');
|
||||
features.declareSupported('voice_subsystem_deferred_switch');
|
||||
features.declareSupported('voice_bypass_system_audio_input_processing');
|
||||
features.declareSupported('clips');
|
||||
}
|
||||
|
||||
function bindConnectionInstance(instance) {
|
||||
return {
|
||||
destroy: () => instance.destroy(),
|
||||
|
||||
setTransportOptions: (options) => instance.setTransportOptions(options),
|
||||
setSelfMute: (mute) => instance.setSelfMute(mute),
|
||||
setSelfDeafen: (deaf) => instance.setSelfDeafen(deaf),
|
||||
|
||||
mergeUsers: (users) => instance.mergeUsers(users),
|
||||
destroyUser: (userId) => instance.destroyUser(userId),
|
||||
|
||||
prepareSecureFramesTransition: (transitionId, version, callback) =>
|
||||
instance.prepareSecureFramesTransition(transitionId, version, callback),
|
||||
prepareSecureFramesEpoch: (epoch, version, groupId) => instance.prepareSecureFramesEpoch(epoch, version, groupId),
|
||||
executeSecureFramesTransition: (transitionId) => instance.executeSecureFramesTransition(transitionId),
|
||||
|
||||
updateMLSExternalSender: (externalSenderPackage) => instance.updateMLSExternalSender(externalSenderPackage),
|
||||
getMLSKeyPackage: (callback) => instance.getMLSKeyPackage(callback),
|
||||
processMLSProposals: (message, callback) => instance.processMLSProposals(message, callback),
|
||||
prepareMLSCommitTransition: (transitionId, commit, callback) =>
|
||||
instance.prepareMLSCommitTransition(transitionId, commit, callback),
|
||||
processMLSWelcome: (transitionId, welcome, callback) => instance.processMLSWelcome(transitionId, welcome, callback),
|
||||
getMLSPairwiseFingerprint: (version, userId, callback) =>
|
||||
instance.getMLSPairwiseFingerprint(version, userId, callback),
|
||||
setOnMLSFailureCallback: (callback) => instance.setOnMLSFailureCallback(callback),
|
||||
setSecureFramesStateUpdateCallback: (callback) => instance.setSecureFramesStateUpdateCallback(callback),
|
||||
|
||||
setLocalVolume: (userId, volume) => instance.setLocalVolume(userId, volume),
|
||||
setLocalMute: (userId, mute) => instance.setLocalMute(userId, mute),
|
||||
fastUdpReconnect: () => instance.fastUdpReconnect(),
|
||||
setLocalPan: (userId, left, right) => instance.setLocalPan(userId, left, right),
|
||||
setDisableLocalVideo: (userId, disabled) => instance.setDisableLocalVideo(userId, disabled),
|
||||
|
||||
setMinimumOutputDelay: (delay) => instance.setMinimumOutputDelay(delay),
|
||||
getEncryptionModes: (callback) => instance.getEncryptionModes(callback),
|
||||
configureConnectionRetries: (baseDelay, maxDelay, maxAttempts) =>
|
||||
instance.configureConnectionRetries(baseDelay, maxDelay, maxAttempts),
|
||||
setOnSpeakingCallback: (callback) => instance.setOnSpeakingCallback(callback),
|
||||
setOnNativeMuteChangedCallback: (callback) => instance.setOnNativeMuteChangedCallback?.(callback),
|
||||
setOnSpeakingWhileMutedCallback: (callback) => instance.setOnSpeakingWhileMutedCallback(callback),
|
||||
setPingInterval: (interval) => instance.setPingInterval(interval),
|
||||
setPingCallback: (callback) => instance.setPingCallback(callback),
|
||||
setPingTimeoutCallback: (callback) => instance.setPingTimeoutCallback(callback),
|
||||
setRemoteUserSpeakingStatus: (userId, speaking) => instance.setRemoteUserSpeakingStatus(userId, speaking),
|
||||
setRemoteUserCanHavePriority: (userId, canHavePriority) =>
|
||||
instance.setRemoteUserCanHavePriority(userId, canHavePriority),
|
||||
|
||||
setOnVideoCallback: (callback) => instance.setOnVideoCallback(callback),
|
||||
setOnFirstFrameCallback: (callback) => instance.setOnFirstFrameCallback(callback),
|
||||
setOnFirstFrameDeliveredStatsCallback: (callback) => instance.setOnFirstFrameDeliveredStatsCallback(callback),
|
||||
setOnFirstFrameEncryptedStatsCallback: (callback) => instance.setOnFirstFrameEncryptedStatsCallback(callback),
|
||||
setVideoBroadcast: (broadcasting) => instance.setVideoBroadcast(broadcasting),
|
||||
setDesktopSource: (id, videoHook, type) => instance.setDesktopSource(id, videoHook, type),
|
||||
setDesktopSourceWithOptions: (options) => instance.setDesktopSourceWithOptions(options),
|
||||
setGoLiveDevices: (options) => instance.setGoLiveDevices(options),
|
||||
clearGoLiveDevices: () => instance.clearGoLiveDevices(),
|
||||
clearDesktopSource: () => instance.clearDesktopSource(),
|
||||
setDesktopSourceStatusCallback: (callback) => instance.setDesktopSourceStatusCallback(callback),
|
||||
setOnDesktopSourceEnded: (callback) => instance.setOnDesktopSourceEnded(callback),
|
||||
setOnSoundshare: (callback) => instance.setOnSoundshare(callback),
|
||||
setOnSoundshareEnded: (callback) => instance.setOnSoundshareEnded(callback),
|
||||
setOnSoundshareFailed: (callback) => instance.setOnSoundshareFailed(callback),
|
||||
setPTTActive: (active, priority, muteOverride) => instance.setPTTActive(active, priority, muteOverride),
|
||||
getStats: (callback) => instance.getStats(callback),
|
||||
getFilteredStats: (filter, callback) => instance.getFilteredStats(filter, callback),
|
||||
startReplay: () => instance.startReplay(),
|
||||
setClipRecordUser: (userId, dataType, shouldRecord) => instance.setClipRecordUser(userId, dataType, shouldRecord),
|
||||
setRtcLogMarker: (marker) => instance.setRtcLogMarker(marker),
|
||||
startSamplesLocalPlayback: (samplesId, options, channels, callback) =>
|
||||
instance.startSamplesLocalPlayback(samplesId, options, channels, callback),
|
||||
stopSamplesLocalPlayback: (sourceId) => instance.stopSamplesLocalPlayback(sourceId),
|
||||
stopAllSamplesLocalPlayback: () => instance.stopAllSamplesLocalPlayback(),
|
||||
setOnVideoEncoderFallbackCallback: (codecName) => instance.setOnVideoEncoderFallbackCallback(codecName),
|
||||
setOnVideoDecoderFallbackCallback: (codecName) => instance.setOnVideoDecoderFallbackCallback(codecName),
|
||||
setOnRtcpMessageCallback: (callback) => instance.setOnRtcpMessageCallback?.(callback),
|
||||
presentDesktopSourcePicker: (style) => instance.presentDesktopSourcePicker(style),
|
||||
};
|
||||
}
|
||||
|
||||
VoiceEngine.createTransport = VoiceEngine._createTransport;
|
||||
|
||||
if (isElectronRenderer) {
|
||||
VoiceEngine.setImageDataAllocator((width, height) => new window.ImageData(width, height));
|
||||
}
|
||||
|
||||
VoiceEngine.createVoiceConnectionWithOptions = function (userId, connectionOptions, onConnectCallback) {
|
||||
const instance = new VoiceEngine.VoiceConnection(userId, connectionOptions, onConnectCallback);
|
||||
return bindConnectionInstance(instance);
|
||||
};
|
||||
VoiceEngine.createOwnStreamConnectionWithOptions = VoiceEngine.createVoiceConnectionWithOptions;
|
||||
|
||||
// TODO(dyc): |audioEngineId| is vestigial and does not actually get used.
|
||||
// "default" was (we deleted audio engine IDs with the removal of android's
|
||||
// separate gameAudio engine) hardcoded within nativelib. update the API to
|
||||
// reflect this.
|
||||
VoiceEngine.createReplayConnection = function (audioEngineId, callback, replayLog) {
|
||||
if (replayLog == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return bindConnectionInstance(new VoiceEngine.VoiceReplayConnection(replayLog, audioEngineId, callback));
|
||||
};
|
||||
|
||||
const setAudioSubsystemInternal = function (subsystem, forceRestart) {
|
||||
if (appSettings == null) {
|
||||
log('warn', 'Unable to access app settings.');
|
||||
return;
|
||||
}
|
||||
|
||||
appSettings.set('audioSubsystem', subsystem);
|
||||
|
||||
if (isElectronRenderer) {
|
||||
if (forceRestart) {
|
||||
// DANGER: any unconditional call to setAudioSubsytem will bootloop if we don't
|
||||
// debounce noop changes.
|
||||
if (subsystem === audioSubsystem) {
|
||||
return;
|
||||
}
|
||||
window.DiscordNative.app.relaunch();
|
||||
} else {
|
||||
console.log(`Deferring audio subsystem switch to ${subsystem} until next restart.`);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
VoiceEngine.setAudioSubsystem = function (subsystem) {
|
||||
setAudioSubsystemInternal(subsystem, true);
|
||||
};
|
||||
|
||||
VoiceEngine.queueAudioSubsystem = function (subsystem) {
|
||||
setAudioSubsystemInternal(subsystem, false);
|
||||
};
|
||||
|
||||
VoiceEngine.setOffloadAdmControls = function (doOffload) {
|
||||
appSettings.set('offloadAdmControls', doOffload);
|
||||
};
|
||||
|
||||
VoiceEngine.setAsyncVideoInputDeviceInitSetting = function (enable) {
|
||||
appSettings.set('asyncVideoInputDeviceInit', enable);
|
||||
};
|
||||
|
||||
VoiceEngine.setDebugLogging = function (enable) {
|
||||
if (appSettings == null) {
|
||||
log('warn', 'Unable to access app settings.');
|
||||
return;
|
||||
}
|
||||
|
||||
if (debugLogging === enable) {
|
||||
return;
|
||||
}
|
||||
|
||||
appSettings.set('debugLogging', enable);
|
||||
|
||||
if (isElectronRenderer) {
|
||||
window.DiscordNative.app.relaunch();
|
||||
}
|
||||
};
|
||||
|
||||
VoiceEngine.getDebugLogging = function () {
|
||||
return debugLogging;
|
||||
};
|
||||
|
||||
const videoStreams = {};
|
||||
const directVideoStreams = {};
|
||||
|
||||
let activeSinksChangeCallback;
|
||||
VoiceEngine.setActiveSinksChangeCallback = function (callback) {
|
||||
activeSinksChangeCallback = callback;
|
||||
};
|
||||
|
||||
function notifyActiveSinksChange(streamId) {
|
||||
if (activeSinksChangeCallback == null) {
|
||||
return;
|
||||
}
|
||||
const sinks = videoStreams[streamId];
|
||||
const hasVideoStreamSink = sinks != null && sinks.size > 0;
|
||||
const hasDirectVideoStreamSink = directVideoStreams[streamId] != null;
|
||||
|
||||
activeSinksChangeCallback(streamId, hasVideoStreamSink || hasDirectVideoStreamSink);
|
||||
}
|
||||
|
||||
// [adill] NB: with context isolation it has become extremely costly (both memory & performance) to provide the image
|
||||
// data directly to clients at any reasonably fast interval so we've replaced setVideoOutputSink with a direct canvas
|
||||
// renderer via addVideoOutputSink
|
||||
const setVideoOutputSink = VoiceEngine.setVideoOutputSink;
|
||||
const clearVideoOutputSink = (streamId) => {
|
||||
// [adill] NB: if you don't pass a frame callback setVideoOutputSink clears the sink
|
||||
setVideoOutputSink(streamId);
|
||||
};
|
||||
const signalVideoOutputSinkReady = VoiceEngine.signalVideoOutputSinkReady;
|
||||
delete VoiceEngine.setVideoOutputSink;
|
||||
delete VoiceEngine.signalVideoOutputSinkReady;
|
||||
|
||||
function addVideoOutputSinkInternal(sinkId, streamId, frameCallback) {
|
||||
let sinks = videoStreams[streamId];
|
||||
if (sinks == null) {
|
||||
sinks = videoStreams[streamId] = new Map();
|
||||
}
|
||||
|
||||
// notifyActiveSinksChange relies on videoStreams having the correct state
|
||||
const needsToSubscribeToFrames = sinks.size === 0;
|
||||
sinks.set(sinkId, frameCallback);
|
||||
|
||||
if (needsToSubscribeToFrames) {
|
||||
log('info', `Subscribing to frames for streamId ${streamId}`);
|
||||
const onFrame = (imageData) => {
|
||||
const sinks = videoStreams[streamId];
|
||||
if (sinks != null) {
|
||||
for (const callback of sinks.values()) {
|
||||
if (callback != null) {
|
||||
callback(imageData);
|
||||
}
|
||||
}
|
||||
}
|
||||
signalVideoOutputSinkReady(streamId);
|
||||
};
|
||||
setVideoOutputSink(streamId, onFrame, true);
|
||||
notifyActiveSinksChange(streamId);
|
||||
}
|
||||
}
|
||||
|
||||
function removeVideoOutputSink(sinkId, streamId) {
|
||||
const sinks = videoStreams[streamId];
|
||||
if (sinks != null) {
|
||||
sinks.delete(sinkId);
|
||||
if (sinks.size === 0) {
|
||||
delete videoStreams[streamId];
|
||||
log('info', `Unsubscribing from frames for streamId ${streamId}`);
|
||||
clearVideoOutputSink(streamId);
|
||||
notifyActiveSinksChange(streamId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// We wrap the direct video calls so we can keep track of all active
|
||||
// video output sinks
|
||||
const addDirectVideoOutputSink_ = VoiceEngine.addDirectVideoOutputSink;
|
||||
const removeDirectVideoOutputSink_ = VoiceEngine.removeDirectVideoOutputSink;
|
||||
VoiceEngine.addDirectVideoOutputSink = function (streamId) {
|
||||
log('info', `Subscribing to direct frames for streamId ${streamId}`);
|
||||
addDirectVideoOutputSink_(streamId);
|
||||
directVideoStreams[streamId] = true;
|
||||
notifyActiveSinksChange(streamId);
|
||||
};
|
||||
VoiceEngine.removeDirectVideoOutputSink = function (streamId) {
|
||||
log('info', `Unsubscribing from direct frames for streamId ${streamId}`);
|
||||
removeDirectVideoOutputSink_(streamId);
|
||||
delete directVideoStreams[streamId];
|
||||
notifyActiveSinksChange(streamId);
|
||||
};
|
||||
|
||||
let sinkId = 0;
|
||||
VoiceEngine.getNextVideoOutputFrame = function (streamId) {
|
||||
const nextVideoFrameSinkId = `getNextVideoFrame_${++sinkId}`;
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
setTimeout(() => {
|
||||
removeVideoOutputSink(nextVideoFrameSinkId, streamId);
|
||||
reject(new Error('getNextVideoOutputFrame timeout'));
|
||||
}, 5000);
|
||||
|
||||
addVideoOutputSinkInternal(nextVideoFrameSinkId, streamId, (imageData) => {
|
||||
removeVideoOutputSink(nextVideoFrameSinkId, streamId);
|
||||
resolve({
|
||||
width: imageData.width,
|
||||
height: imageData.height,
|
||||
data: new Uint8ClampedArray(imageData.data.buffer),
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
function log(level, message) {
|
||||
const consoleLogFn = (() => {
|
||||
if (!['trace', 'debug', 'info', 'warn', 'error', 'log'].includes(level)) {
|
||||
return console.info;
|
||||
}
|
||||
return console[level];
|
||||
})();
|
||||
consoleLogFn(message);
|
||||
|
||||
// Note: this currently races with the VoiceEngine initialization,
|
||||
// not all logs may get logged here early in the process
|
||||
VoiceEngine.consoleLog(level, message);
|
||||
}
|
||||
|
||||
console.log(`Initializing voice engine with audio subsystem: ${audioSubsystem}`);
|
||||
VoiceEngine.platform = process.platform;
|
||||
VoiceEngine.initialize({
|
||||
audioSubsystem,
|
||||
logLevel,
|
||||
dataDirectory,
|
||||
logDirectory,
|
||||
maxLogBytes,
|
||||
useFakeVideoCapture,
|
||||
useFileForFakeVideoCapture,
|
||||
useFakeAudioCapture,
|
||||
useFilesForFakeAudioCapture,
|
||||
offloadAdmControls,
|
||||
asyncVideoInputDeviceInit,
|
||||
});
|
||||
|
||||
module.exports = VoiceEngine;
|
||||
BIN
discord/0.0.129/modules/discord_voice/libmediapipe.so
Normal file
BIN
discord/0.0.129/modules/discord_voice/libmediapipe.so
Normal file
Binary file not shown.
11
discord/0.0.129/modules/discord_voice/manifest.json
Normal file
11
discord/0.0.129/modules/discord_voice/manifest.json
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"files": [
|
||||
"discord_voice.node",
|
||||
"selfie_segmentation.tflite",
|
||||
"selfie_segmentation_landscape.tflite",
|
||||
"libmediapipe.so",
|
||||
"package.json",
|
||||
"index.js",
|
||||
"manifest.json"
|
||||
]
|
||||
}
|
||||
3
discord/0.0.129/modules/discord_voice/package.json
Normal file
3
discord/0.0.129/modules/discord_voice/package.json
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"private": "true"
|
||||
}
|
||||
BIN
discord/0.0.129/modules/discord_voice/selfie_segmentation.tflite
Normal file
BIN
discord/0.0.129/modules/discord_voice/selfie_segmentation.tflite
Normal file
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user