Skip to content

Commit

Permalink
Merge branch 'master' into fix/localstorage-conflicts
Browse files Browse the repository at this point in the history
  • Loading branch information
digisomni committed Sep 19, 2023
2 parents 7cbf99a + 13b6101 commit 5c56673
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 54 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ node_modules
.quasar
/dist

# Web workers copied from dependencies.
/public/js

# Cordova related directories and files
/src-cordova/node_modules
/src-cordova/platforms
Expand Down
38 changes: 38 additions & 0 deletions build_scripts/copyWorkers.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
//
// copyWorkers.js
//
// Copy web-worker scripts from the Web SDK to the application.
// This is for static scripts that cannot be included by `import` or `require`.
//
// Created by Giga on 18 September 2023.
// Copyright 2023 Vircadia contributors.
// Copyright 2023 DigiSomni LLC.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//

import { copyFileSync, existsSync, mkdirSync } from "fs";

// The workers to copy.
const workers = [
"vircadia-audio-input.js",
"vircadia-audio-input.js.map",
"vircadia-audio-output.js",
"vircadia-audio-output.js.map"
];
// The destination for the worker files.
const destination = "public/js/";

// Ensure the destination exists.
if (!existsSync(destination)) {
mkdirSync(destination, { recursive: true });
}

// Copy the worker files to the destination.
console.log("Copying workers...");
for (const worker of workers) {
copyFileSync(`node_modules/@vircadia/web-sdk/dist/${worker}`, `${destination}${worker}`);
console.log(" »\x1b[32m", worker, "\x1b[0m");
}
console.log("Done.\n");
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,13 @@
"author": "DigiSomni LLC | Vircadia Contributors",
"license": "Apache-2.0",
"scripts": {
"build": "npm run create-version && npm run build-quasar",
"dev": "npm run create-version && npm run build-quasar-dev",
"build": "npm run create-version && npm run copy-workers && npm run build-quasar",
"dev": "npm run create-version && npm run copy-workers && npm run build-quasar-dev",
"build-quasar": "quasar build",
"build-quasar-dev": "quasar dev",
"lint": "eslint --ext .js,.ts,.vue ./",
"create-version": "node build_scripts/createVersion.js",
"copy-workers": "node build_scripts/copyWorkers.mjs",
"update-contributors": "git-authors-cli"
},
"dependencies": {
Expand Down
80 changes: 28 additions & 52 deletions src/modules/scene/audio.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ export type SetAudioOutputCallback = (pStream: Nullable<MediaStream>) => void;
export class AudioManager {

// Function that sets the MediaStream from the domain to wherever it goes
private static _setAudioOutputFunction = undefined as unknown as SetAudioOutputCallback;
private static _setAudioOutputFunction: Nullable<SetAudioOutputCallback> = undefined;

/**
* Initialize the audio state.
Expand Down Expand Up @@ -97,19 +97,15 @@ export class AudioManager {
if (pState === ConnectionState.CONNECTED) {
Log.debug(Log.types.AUDIO, `AudioManager._handleActiveDomainStateChange: CONNECTED`);
// Domain is connected. Connect the inputs to the outputs
if (pDomain.AudioClient) {
// setup to wait for the audio device to get connected
pDomain.AudioClient.onStateChange.connect(this._handleDomainAudioStateChange.bind(this));
// but, if already connected, connect the audio end points
if (pDomain.AudioClient.clientState === AssignmentClientState.CONNECTED) {
await this._setupDomainAudio(pDomain);
}
// Setup to wait for the audio device to get connected
pDomain.AudioClient?.onStateChange.connect(this._handleDomainAudioStateChange.bind(this));
// but, if already connected, connect the audio end points
if (pDomain.AudioClient?.clientState === AssignmentClientState.CONNECTED) {
await this._setupDomainAudio(pDomain);
}
} else {
Log.debug(Log.types.AUDIO, `AudioManager._handleActiveDomainStateChange: ${Domain.stateToString(pState)}`);
if (this._setAudioOutputFunction) {
this._setAudioOutputFunction(undefined);
}
this._setAudioOutputFunction?.(undefined);
// The domain is not connected. If anything is connected, disconnect it
// TODO:
}
Expand Down Expand Up @@ -190,9 +186,7 @@ export class AudioManager {
private static _disconnectInputAndOutputStreams(pDomain: Domain): void {
if (pDomain.AudioClient && pDomain.AudioClient.Mixer) {
pDomain.AudioClient.Mixer.audioInput = null;
if (AudioManager._setAudioOutputFunction) {
AudioManager._setAudioOutputFunction(undefined);
}
AudioManager._setAudioOutputFunction?.(undefined);
}
}

Expand Down Expand Up @@ -234,32 +228,20 @@ export class AudioManager {
* @param pStream stream from user that should go to the domain
*/
public static async setAudioToDomain(pStream: Nullable<MediaStream>): Promise<void> {
if (DomainManager.ActiveDomain && DomainManager.ActiveDomain.AudioClient) {
if (DomainManager.ActiveDomain.AudioClient.clientState === AssignmentClientState.CONNECTED) {
const mixer = DomainManager.ActiveDomain?.AudioClient?.Mixer;
if (mixer) {
mixer.audioInput = pStream as MediaStream | null;
AudioManager.setDomainAudioMuted(mixer.inputMuted);
await AudioManager.setDomainAudioPlayPause(true);
}
}
const mixer = DomainManager.ActiveDomain?.AudioClient?.Mixer;
if (DomainManager.ActiveDomain?.AudioClient?.clientState === AssignmentClientState.CONNECTED && mixer) {
mixer.audioInput = pStream as MediaStream | null;
AudioManager.setDomainAudioMuted(mixer.inputMuted);
await AudioManager.setDomainAudioPlayPause(true);
}
}

// Set Play/Pause on domain audio.
public static async setDomainAudioPlayPause(pPlay: boolean): Promise<boolean> {
if (DomainManager.ActiveDomain && DomainManager.ActiveDomain.AudioClient) {
if (DomainManager.ActiveDomain.AudioClient.clientState === AssignmentClientState.CONNECTED) {
const mixer = DomainManager.ActiveDomain.AudioClient.Mixer;
if (mixer) {
if (pPlay) {
await mixer.play();
} else {
await mixer.pause();
}
return pPlay;
}
}
const mixer = DomainManager.ActiveDomain?.AudioClient?.Mixer;
if (DomainManager.ActiveDomain?.AudioClient?.clientState === AssignmentClientState.CONNECTED && mixer) {
await mixer[pPlay ? "play" : "pause"]();
return pPlay;
}
return false;
}
Expand All @@ -271,13 +253,9 @@ export class AudioManager {
*/
public static setDomainAudioMuted(pMute?: boolean): boolean {
const newMute = pMute ?? !applicationStore.audio.user.muted;
if (DomainManager.ActiveDomain && DomainManager.ActiveDomain.AudioClient) {
if (DomainManager.ActiveDomain.AudioClient.clientState === AssignmentClientState.CONNECTED) {
const mixer = DomainManager.ActiveDomain.AudioClient.Mixer;
if (mixer) {
mixer.inputMuted = newMute;
}
}
const mixer = DomainManager.ActiveDomain?.AudioClient?.Mixer;
if (DomainManager.ActiveDomain?.AudioClient?.clientState === AssignmentClientState.CONNECTED && mixer) {
mixer.inputMuted = newMute;
}
return newMute;
}
Expand Down Expand Up @@ -311,13 +289,11 @@ export class AudioManager {

// the output device has changed so set the domain stream to the output device
const audioClient = DomainManager.ActiveDomain?.AudioClient;
if (audioClient) {
if (audioClient.clientState === AssignmentClientState.CONNECTED) {
const domainStream = audioClient.domainAudioStream;
Log.debug(Log.types.AUDIO, `AudioManager.setAudioOutputStream: setting output. ${typeof domainStream}`);
if (AudioManager._setAudioOutputFunction) {
AudioManager._setAudioOutputFunction(domainStream);
}
if (audioClient?.clientState === AssignmentClientState.CONNECTED) {
const domainStream = audioClient.domainAudioStream;
Log.debug(Log.types.AUDIO, `AudioManager.setAudioOutputStream: setting output. ${typeof domainStream}`);
if (AudioManager._setAudioOutputFunction) {
AudioManager._setAudioOutputFunction(domainStream);
}
}
}
Expand Down Expand Up @@ -381,8 +357,8 @@ export class AudioManager {
* This routine will hang in the Promise waiting for the user to grant audio access.
* @returns a mediaStream as the user's audio input device
*/
public static async getAudioInputAccess(): Promise<MediaStream> {
let inputStream = undefined as unknown as MediaStream;
public static async getAudioInputAccess(): Promise<Nullable<MediaStream>> {
let inputStream: Nullable<MediaStream> = undefined;
if (navigator.mediaDevices) {
try {
const lastSessionInput = Config.getItem(USER_AUDIO_INPUT, "none");
Expand All @@ -406,7 +382,7 @@ export class AudioManager {
* is supplied in the call, this attempts to select that device.
* @param {MediaStream} pInitial an optional stream to prefer when selecting input device
*/
public static async setInitialInputAudioDevice(pInitial?: MediaStream): Promise<void> {
public static async setInitialInputAudioDevice(pInitial?: Nullable<MediaStream>): Promise<void> {
Log.debug(Log.types.AUDIO, `AudioManager.setInitialInputAudioDevice`);
try {
Log.debug(Log.types.AUDIO, `AudioManager: Set initial Input audio device.`);
Expand Down

0 comments on commit 5c56673

Please sign in to comment.