overte/scripts/system/selectAudioDevice.js
2017-03-24 18:19:34 -07:00

259 lines
10 KiB
JavaScript

"use strict";
//
// audioDeviceExample.js
// examples
//
// Created by Brad Hefta-Gaub on 3/22/14
// Copyright 2013 High Fidelity, Inc.
//
// This is an example script that demonstrates use of the Menu object
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
(function() { // BEGIN LOCAL_SCOPE
if (typeof String.prototype.startsWith != 'function') {
String.prototype.startsWith = function (str){
return this.slice(0, str.length) == str;
};
}
if (typeof String.prototype.endsWith != 'function') {
String.prototype.endsWith = function (str){
return this.slice(-str.length) == str;
};
}
if (typeof String.prototype.trimStartsWith != 'function') {
String.prototype.trimStartsWith = function (str){
if (this.startsWith(str)) {
return this.substr(str.length);
}
return this;
};
}
if (typeof String.prototype.trimEndsWith != 'function') {
String.prototype.trimEndsWith = function (str){
if (this.endsWith(str)) {
return this.substr(0,this.length - str.length);
}
return this;
};
}
/****************************************
VAR DEFINITIONS
****************************************/
const INPUT_DEVICE_SETTING = "audio_input_device";
const OUTPUT_DEVICE_SETTING = "audio_output_device";
var audioDevicesList = [];
// Some HMDs (like Oculus CV1) have a built in audio device. If they
// do, then this function will handle switching to that device automatically
// when you goActive with the HMD active.
var wasHmdActive = false; // assume it's not active to start
var switchedAudioInputToHMD = false;
var switchedAudioOutputToHMD = false;
var previousSelectedInputAudioDevice = "";
var previousSelectedOutputAudioDevice = "";
/****************************************
BEGIN FUNCTION DEFINITIONS
****************************************/
function setupAudioMenus() {
Menu.menuItemEvent.disconnect(menuItemEvent);
/* Setup audio input devices */
Menu.addSeparator("Audio", "Input Audio Device");
var inputDevices = AudioDevice.getInputDevices();
print("selectAudioDevice: Audio input devices: " + inputDevices);
for (var i = 0; i < inputDevices.length; i++) {
var menuItem = "Use " + inputDevices[i] + " for Input";
Menu.addMenuItem({
menuName: "Audio",
menuItemName: menuItem,
isCheckable: true,
isChecked: inputDevices[i] == AudioDevice.getInputDevice()
});
audioDevicesList.push(menuItem);
}
/* Setup audio output devices */
Menu.addSeparator("Audio", "Output Audio Device");
var outputDevices = AudioDevice.getOutputDevices();
print("selectAudioDevice: Audio output devices: " + outputDevices);
for (var i = 0; i < outputDevices.length; i++) {
var menuItem = "Use " + outputDevices[i] + " for Output";
Menu.addMenuItem({
menuName: "Audio",
menuItemName: menuItem,
isCheckable: true,
isChecked: outputDevices[i] == AudioDevice.getOutputDevice()
});
audioDevicesList.push(menuItem);
}
Menu.menuItemEvent.connect(menuItemEvent);
}
function checkDeviceMismatch() {
var inputDeviceSetting = Settings.getValue(INPUT_DEVICE_SETTING);
var interfaceInputDevice = AudioDevice.getInputDevice();
if (interfaceInputDevice != inputDeviceSetting) {
print("selectAudioDevice: Input Setting & Device mismatch! Input SETTING:", inputDeviceSetting, "Input DEVICE IN USE:", AudioDevice.getInputDevice());
switchAudioDevice(true, inputDeviceSetting);
}
var outputDeviceSetting = Settings.getValue(OUTPUT_DEVICE_SETTING);
var interfaceOutputDevice = AudioDevice.getOutputDevice();
if (interfaceOutputDevice != outputDeviceSetting) {
print("selectAudioDevice: Output Setting & Device mismatch! Output SETTING:", outputDeviceSetting, "Output DEVICE IN USE:", interfaceOutputDevice);
switchAudioDevice(false, outputDeviceSetting);
}
}
function removeAudioMenus() {
Menu.removeSeparator("Audio", "Input Audio Device");
Menu.removeSeparator("Audio", "Output Audio Device");
for (var index = 0; index < audioDevicesList.length; index++) {
if (Menu.menuItemExists("Audio", audioDevicesList[index])) {
Menu.removeMenuItem("Audio", audioDevicesList[index]);
}
}
Menu.removeMenu("Audio > Devices");
audioDevicesList = [];
}
function onDevicechanged() {
print("selectAudioDevice: System audio device changed. Removing and replacing Audio Menus...");
removeAudioMenus();
setupAudioMenus();
checkDeviceMismatch();
}
function menuItemEvent(menuItem) {
if (menuItem.startsWith("Use ")) {
if (menuItem.endsWith(" for Input")) {
var selectedDevice = menuItem.trimStartsWith("Use ").trimEndsWith(" for Input");
print("selectAudioDevice: User selected a new Audio Input Device: " + selectedDevice);
switchAudioDevice(true, selectedDevice);
} else if (menuItem.endsWith(" for Output")) {
var selectedDevice = menuItem.trimStartsWith("Use ").trimEndsWith(" for Output");
print("selectAudioDevice: User selected a new Audio Output Device: " + selectedDevice);
switchAudioDevice(false, selectedDevice);
} else {
print("selectAudioDevice: Invalid Audio menuItem! Doesn't end with 'for Input' or 'for Output'")
}
}
}
function switchAudioDevice(isInput, device) {
if (isInput) {
print("selectAudioDevice: Switching audio INPUT device to:", device);
if (AudioDevice.setInputDevice(device)) {
Settings.setValue(INPUT_DEVICE_SETTING, device);
} else {
print("selectAudioDevice: Error setting audio input device!")
}
} else {
print("selectAudioDevice: Switching audio OUTPUT device to:", device);
if (AudioDevice.setOutputDevice(device)) {
Settings.setValue(OUTPUT_DEVICE_SETTING, device);
} else {
print("selectAudioDevice: Error setting audio output device!")
}
}
removeAudioMenus();
setupAudioMenus();
}
function restoreAudio() {
if (switchedAudioInputToHMD) {
print("selectAudioDevice: Switching back from HMD preferred audio input to: " + previousSelectedInputAudioDevice);
switchAudioDevice(true, previousSelectedInputAudioDevice);
switchedAudioInputToHMD = false;
}
if (switchedAudioOutputToHMD) {
print("selectAudioDevice: Switching back from HMD preferred audio output to: " + previousSelectedOutputAudioDevice);
switchAudioDevice(false, previousSelectedOutputAudioDevice);
switchedAudioOutputToHMD = false;
}
}
function checkHMDAudio() {
// HMD Active state is changing; handle switching
if (HMD.active != wasHmdActive) {
print("selectAudioDevice: HMD Active state changed!");
// We're putting the HMD on; switch to those devices
if (HMD.active) {
print("selectAudioDevice: HMD is now Active.");
var hmdPreferredAudioInput = HMD.preferredAudioInput();
var hmdPreferredAudioOutput = HMD.preferredAudioOutput();
print("selectAudioDevice: hmdPreferredAudioInput: " + hmdPreferredAudioInput);
print("selectAudioDevice: hmdPreferredAudioOutput: " + hmdPreferredAudioOutput);
if (hmdPreferredAudioInput !== "") {
print("selectAudioDevice: HMD has preferred audio input device.");
previousSelectedInputAudioDevice = Settings.getValue(INPUT_DEVICE_SETTING);
print("selectAudioDevice: previousSelectedInputAudioDevice: " + previousSelectedInputAudioDevice);
if (hmdPreferredAudioInput != previousSelectedInputAudioDevice) {
print("selectAudioDevice: Switching Audio Input device to HMD preferred device: " + hmdPreferredAudioInput);
switchedAudioInputToHMD = true;
switchAudioDevice(true, hmdPreferredAudioInput);
}
}
if (hmdPreferredAudioOutput !== "") {
print("selectAudioDevice: HMD has preferred audio output device.");
previousSelectedOutputAudioDevice = Settings.getValue(OUTPUT_DEVICE_SETTING);
print("selectAudioDevice: previousSelectedOutputAudioDevice: " + previousSelectedOutputAudioDevice);
if (hmdPreferredAudioOutput != previousSelectedOutputAudioDevice) {
print("selectAudioDevice: Switching Audio Output device to HMD preferred device: " + hmdPreferredAudioOutput);
switchedAudioOutputToHMD = true;
switchAudioDevice(false, hmdPreferredAudioOutput);
}
}
} else {
print("selectAudioDevice: HMD no longer active. Restoring audio I/O devices...");
restoreAudio();
}
}
wasHmdActive = HMD.active;
}
/****************************************
END FUNCTION DEFINITIONS
****************************************/
/****************************************
BEGIN SCRIPT BODY
****************************************/
// Have a small delay before the menus get setup so the audio devices can switch to the last selected ones
Script.setTimeout(function () {
print("selectAudioDevice: Connecting deviceChanged(), displayModeChanged(), and menuItemEvent()");
AudioDevice.deviceChanged.connect(onDevicechanged);
HMD.displayModeChanged.connect(checkHMDAudio);
Menu.menuItemEvent.connect(menuItemEvent);
print("selectAudioDevice: Setting up Audio > Devices menu for the first time");
setupAudioMenus();
checkDeviceMismatch();
print("selectAudioDevice: Checking HMD audio status...")
checkHMDAudio();
}, 3000);
print("selectAudioDevice: Connecting scriptEnding()");
Script.scriptEnding.connect(function () {
restoreAudio();
removeAudioMenus();
Menu.menuItemEvent.disconnect(menuItemEvent);
HMD.displayModeChanged.disconnect(checkHMDAudio);
AudioDevice.deviceChanged.disconnect(onDevicechanged);
});
}()); // END LOCAL_SCOPE