mirror of
https://github.com/redphx/better-xcloud.git
synced 2025-06-07 08:07:18 +02:00
Add shortcuts to control stream's volume
This commit is contained in:
parent
90df5d655f
commit
dcbae39042
@ -7,6 +7,8 @@ import { MkbHandler } from "./mkb/mkb-handler";
|
|||||||
import { StreamStats } from "./stream/stream-stats";
|
import { StreamStats } from "./stream/stream-stats";
|
||||||
import { MicrophoneShortcut } from "./shortcuts/shortcut-microphone";
|
import { MicrophoneShortcut } from "./shortcuts/shortcut-microphone";
|
||||||
import { StreamUiShortcut } from "./shortcuts/shortcut-stream-ui";
|
import { StreamUiShortcut } from "./shortcuts/shortcut-stream-ui";
|
||||||
|
import { PrefKey, getPref } from "@utils/preferences";
|
||||||
|
import { SoundShortcut } from "./shortcuts/shortcut-sound";
|
||||||
|
|
||||||
enum ShortcutAction {
|
enum ShortcutAction {
|
||||||
STREAM_SCREENSHOT_CAPTURE = 'stream-screenshot-capture',
|
STREAM_SCREENSHOT_CAPTURE = 'stream-screenshot-capture',
|
||||||
@ -92,6 +94,14 @@ export class ControllerShortcut {
|
|||||||
case ShortcutAction.STREAM_MENU_TOGGLE:
|
case ShortcutAction.STREAM_MENU_TOGGLE:
|
||||||
StreamUiShortcut.showHideStreamMenu();
|
StreamUiShortcut.showHideStreamMenu();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case ShortcutAction.STREAM_VOLUME_INC:
|
||||||
|
SoundShortcut.increaseGainNodeVolume(10);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ShortcutAction.STREAM_VOLUME_DEC:
|
||||||
|
SoundShortcut.decreaseGainNodeVolume(10);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -232,8 +242,8 @@ export class ControllerShortcut {
|
|||||||
[ShortcutAction.STREAM_MICROPHONE_TOGGLE]: [t('stream'), t('microphone'), t('toggle')],
|
[ShortcutAction.STREAM_MICROPHONE_TOGGLE]: [t('stream'), t('microphone'), t('toggle')],
|
||||||
[ShortcutAction.STREAM_MENU_TOGGLE]: [t('stream'), t('menu'), t('show')],
|
[ShortcutAction.STREAM_MENU_TOGGLE]: [t('stream'), t('menu'), t('show')],
|
||||||
// [ShortcutAction.STREAM_SOUND_TOGGLE]: [t('stream'), t('sound'), t('toggle')],
|
// [ShortcutAction.STREAM_SOUND_TOGGLE]: [t('stream'), t('sound'), t('toggle')],
|
||||||
// [ShortcutAction.STREAM_VOLUME_INC]: getPref(PrefKey.AUDIO_ENABLE_VOLUME_CONTROL) && [t('stream'), t('volume'), t('increase')],
|
[ShortcutAction.STREAM_VOLUME_INC]: getPref(PrefKey.AUDIO_ENABLE_VOLUME_CONTROL) && [t('stream'), t('volume'), t('increase')],
|
||||||
// [ShortcutAction.STREAM_VOLUME_DEC]: getPref(PrefKey.AUDIO_ENABLE_VOLUME_CONTROL) && [t('stream'), t('volume'), t('decrease')],
|
[ShortcutAction.STREAM_VOLUME_DEC]: getPref(PrefKey.AUDIO_ENABLE_VOLUME_CONTROL) && [t('stream'), t('volume'), t('decrease')],
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
53
src/modules/shortcuts/shortcut-sound.ts
Normal file
53
src/modules/shortcuts/shortcut-sound.ts
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
import { t } from "@utils/translation";
|
||||||
|
import { STATES } from "@utils/global";
|
||||||
|
import { PrefKey, getPref, setPref } from "@utils/preferences";
|
||||||
|
import { Toast } from "@utils/toast";
|
||||||
|
import { BxEvent } from "@/utils/bx-event";
|
||||||
|
import { ceilToNearest, floorToNearest } from "@/utils/utils";
|
||||||
|
|
||||||
|
export class SoundShortcut {
|
||||||
|
static increaseGainNodeVolume(amount: number) {
|
||||||
|
SoundShortcut.#adjustGainNodeVolume(amount);
|
||||||
|
}
|
||||||
|
|
||||||
|
static decreaseGainNodeVolume(amount: number) {
|
||||||
|
SoundShortcut.#adjustGainNodeVolume(-1 * Math.abs(amount));
|
||||||
|
}
|
||||||
|
|
||||||
|
static #adjustGainNodeVolume(amount: number): number {
|
||||||
|
if (!getPref(PrefKey.AUDIO_ENABLE_VOLUME_CONTROL)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const currentValue = getPref(PrefKey.AUDIO_VOLUME);
|
||||||
|
let nearestValue: number;
|
||||||
|
|
||||||
|
if (amount > 0) { // Increase
|
||||||
|
nearestValue = ceilToNearest(currentValue, amount);
|
||||||
|
} else { // Decrease
|
||||||
|
nearestValue = floorToNearest(currentValue, -1 * amount);
|
||||||
|
}
|
||||||
|
|
||||||
|
let newValue: number;
|
||||||
|
if (currentValue !== nearestValue) {
|
||||||
|
newValue = nearestValue;
|
||||||
|
} else {
|
||||||
|
newValue = currentValue + amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
newValue = setPref(PrefKey.AUDIO_VOLUME, newValue);
|
||||||
|
SoundShortcut.setGainNodeVolume(newValue);
|
||||||
|
|
||||||
|
// Show toast
|
||||||
|
Toast.show(`${t('stream')} ❯ ${t('volume')}`, newValue + '%', {instant: true});
|
||||||
|
BxEvent.dispatch(window, BxEvent.GAINNODE_VOLUME_CHANGED, {
|
||||||
|
volume: newValue,
|
||||||
|
});
|
||||||
|
|
||||||
|
return newValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
static setGainNodeVolume(value: number) {
|
||||||
|
STATES.currentStream.audioGainNode && (STATES.currentStream.audioGainNode.gain.value = value / 100);
|
||||||
|
}
|
||||||
|
}
|
@ -11,6 +11,7 @@ import { t } from "@utils/translation";
|
|||||||
import { VibrationManager } from "@modules/vibration-manager";
|
import { VibrationManager } from "@modules/vibration-manager";
|
||||||
import { Screenshot } from "@/utils/screenshot";
|
import { Screenshot } from "@/utils/screenshot";
|
||||||
import { ControllerShortcut } from "../controller-shortcut";
|
import { ControllerShortcut } from "../controller-shortcut";
|
||||||
|
import { SoundShortcut } from "../shortcuts/shortcut-sound";
|
||||||
|
|
||||||
|
|
||||||
export function localRedirect(path: string) {
|
export function localRedirect(path: string) {
|
||||||
@ -97,11 +98,20 @@ function setupQuickSettingsBar() {
|
|||||||
pref: PrefKey.AUDIO_VOLUME,
|
pref: PrefKey.AUDIO_VOLUME,
|
||||||
label: t('volume'),
|
label: t('volume'),
|
||||||
onChange: (e: any, value: number) => {
|
onChange: (e: any, value: number) => {
|
||||||
STATES.currentStream.audioGainNode && (STATES.currentStream.audioGainNode.gain.value = value / 100);
|
SoundShortcut.setGainNodeVolume(value);
|
||||||
},
|
},
|
||||||
params: {
|
params: {
|
||||||
disabled: !getPref(PrefKey.AUDIO_ENABLE_VOLUME_CONTROL),
|
disabled: !getPref(PrefKey.AUDIO_ENABLE_VOLUME_CONTROL),
|
||||||
},
|
},
|
||||||
|
onMounted: ($elm: HTMLElement) => {
|
||||||
|
const $range = $elm.querySelector('input[type=range') as HTMLInputElement;
|
||||||
|
window.addEventListener(BxEvent.GAINNODE_VOLUME_CHANGED, e => {
|
||||||
|
$range.value = (e as any).volume;
|
||||||
|
BxEvent.dispatch($range, 'input', {
|
||||||
|
ignoreOnChange: true,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
@ -36,6 +36,7 @@ export enum BxEvent {
|
|||||||
MICROPHONE_STATE_CHANGED = 'bx-microphone-state-changed',
|
MICROPHONE_STATE_CHANGED = 'bx-microphone-state-changed',
|
||||||
|
|
||||||
CAPTURE_SCREENSHOT = 'bx-capture-screenshot',
|
CAPTURE_SCREENSHOT = 'bx-capture-screenshot',
|
||||||
|
GAINNODE_VOLUME_CHANGED = 'bx-gainnode-volume-changed',
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum XcloudEvent {
|
export enum XcloudEvent {
|
||||||
|
@ -753,11 +753,13 @@ export class Preferences {
|
|||||||
return this.#prefs[key];
|
return this.#prefs[key];
|
||||||
}
|
}
|
||||||
|
|
||||||
set(key: PrefKey, value: any) {
|
set(key: PrefKey, value: any): any {
|
||||||
value = this.#validateValue(key, value);
|
value = this.#validateValue(key, value);
|
||||||
|
|
||||||
this.#prefs[key] = value;
|
this.#prefs[key] = value;
|
||||||
this.#updateStorage();
|
this.#updateStorage();
|
||||||
|
|
||||||
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
#updateStorage() {
|
#updateStorage() {
|
||||||
|
@ -183,7 +183,7 @@ export class SettingElement {
|
|||||||
$range.addEventListener('input', e => {
|
$range.addEventListener('input', e => {
|
||||||
value = parseInt((e.target as HTMLInputElement).value);
|
value = parseInt((e.target as HTMLInputElement).value);
|
||||||
$text.textContent = renderTextValue(value);
|
$text.textContent = renderTextValue(value);
|
||||||
onChange && onChange(e, value);
|
!(e as any).ignoreOnChange && onChange && onChange(e, value);
|
||||||
});
|
});
|
||||||
$wrapper.appendChild($range);
|
$wrapper.appendChild($range);
|
||||||
|
|
||||||
|
@ -15,7 +15,7 @@ export class Toast {
|
|||||||
static #timeout?: number | null;
|
static #timeout?: number | null;
|
||||||
static #DURATION = 3000;
|
static #DURATION = 3000;
|
||||||
|
|
||||||
static show(msg: string, status?: string, options: Partial<ToastOptions>={}) {
|
static show(msg: string, status?: string, options: Partial<ToastOptions> = {}) {
|
||||||
options = options || {};
|
options = options || {};
|
||||||
|
|
||||||
const args = Array.from(arguments) as [string, string, ToastOptions];
|
const args = Array.from(arguments) as [string, string, ToastOptions];
|
||||||
@ -43,7 +43,7 @@ export class Toast {
|
|||||||
// Get values from item
|
// Get values from item
|
||||||
const [msg, status, options] = Toast.#stack.shift()!;
|
const [msg, status, options] = Toast.#stack.shift()!;
|
||||||
|
|
||||||
if (options.html) {
|
if (options && options.html) {
|
||||||
Toast.#$msg.innerHTML = msg;
|
Toast.#$msg.innerHTML = msg;
|
||||||
} else {
|
} else {
|
||||||
Toast.#$msg.textContent = msg;
|
Toast.#$msg.textContent = msg;
|
||||||
|
@ -77,3 +77,16 @@ export function renderString(str: string, obj: any){
|
|||||||
return match;
|
return match;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export function ceilToNearest(value: number, interval: number): number {
|
||||||
|
return Math.ceil(value / interval) * interval;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function floorToNearest(value: number, interval: number): number {
|
||||||
|
return Math.floor(value / interval) * interval;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function roundToNearest(value: number, interval: number): number {
|
||||||
|
return Math.round(value / interval) * interval;
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user