Use Web audio API

This commit is contained in:
Bruno Ribeito
2018-01-08 20:53:26 +00:00
parent be18507df6
commit b75f52734d
4 changed files with 73 additions and 39 deletions
+3
View File
@@ -352,3 +352,6 @@ export interface ITheme {
brightCyan?: string;
brightWhite?: string;
}
export interface ISoundManager {
playBellSound(): void;
}
+61
View File
@@ -0,0 +1,61 @@
/**
* Copyright (c) 2018 The xterm.js authors. All rights reserved.
* @license MIT
*/
import { ITerminal, ISoundManager } from './Interfaces';
// Source: https://freesound.org/people/altemark/sounds/45759/
// This sound is released under the Creative Commons Attribution 3.0 Unported
// (CC BY 3.0) license. It was created by 'altemark'. No modifications have been
// made, apart from the conversion to base64.
export const DefaultBellSound = 'data:audio/wav;base64,UklGRigBAABXQVZFZm10IBAAAAABAAEARKwAAIhYAQACABAAZGF0YQQBAADpAFgCwAMlBZoG/wdmCcoKRAypDQ8PbRDBEQQTOxRtFYcWlBePGIUZXhoiG88bcBz7HHIdzh0WHlMeZx51HmkeUx4WHs8dah0AHXwc3hs9G4saxRnyGBIYGBcQFv8U4RPAEoYRQBACD70NWwwHC6gJOwjWBloF7gOBAhABkf8b/qv8R/ve+Xf4Ife79W/0JfPZ8Z/wde9N7ijtE+wU6xvqM+lb6H7nw+YX5mrlxuQz5Mzje+Ma49fioeKD4nXiYeJy4pHitOL04j/jn+MN5IPkFOWs5U3mDefM55/ogOl36m7rdOyE7abuyu8D8Unyj/Pg9D/2qfcb+Yn6/vuK/Qj/lAAlAg==';
export class SoundManager implements ISoundManager {
private _terminal: ITerminal;
private _audioContext: AudioContext;
constructor(_terminal: ITerminal) {
this._terminal = _terminal;
}
public playBellSound(): void {
if (!this._audioContext) {
this._audioContext = new (window.AudioContext || window.webkitAudioContext)();
}
if (this._audioContext) {
let bellAudioSource = this._audioContext.createBufferSource();
let context = this._audioContext;
this._audioContext.decodeAudioData(this.base64ToArrayBuffer(this.removeMimeType(this._terminal.options.bellSound)), function (buffer) {
bellAudioSource.buffer = buffer;
bellAudioSource.connect(context.destination);
bellAudioSource.start(0);
});
}
else {
console.warn('Sorry, but the Web Audio API is not supported by your browser. Please, consider upgrading to the latest version');
}
}
private base64ToArrayBuffer(base64: string): ArrayBuffer {
const binaryString = window.atob(base64);
const len = binaryString.length;
let bytes = new Uint8Array(len);
for (let i = 0; i < len; i++) {
bytes[i] = binaryString.charCodeAt(i);
}
return bytes.buffer;
}
private removeMimeType(dataURI: string): string {
// Split the input to get the mime-type and the data itself
const SplitURI = dataURI.split(',');
// Return only the data
return SplitURI[1];
}
}
+9 -29
View File
@@ -40,7 +40,7 @@ import { MouseHelper } from './utils/MouseHelper';
import { CHARSETS } from './Charsets';
import { CustomKeyEventHandler, Charset, LinkMatcherHandler, LinkMatcherValidationCallback, CharData, LineData } from './Types';
import { ITerminal, IBrowser, ITerminalOptions, IInputHandlingTerminal, ILinkMatcherOptions, IViewport, ICompositionHelper, ITheme, ILinkifier } from './Interfaces';
import { BellSound } from './utils/Sounds';
import { DefaultBellSound, SoundManager } from './SoundManager';
import { DEFAULT_ANSI_COLORS } from './renderer/ColorManager';
import { IMouseZoneManager } from './input/Interfaces';
import { MouseZoneManager } from './input/MouseZoneManager';
@@ -70,7 +70,7 @@ const DEFAULT_OPTIONS: ITerminalOptions = {
termName: 'xterm',
cursorBlink: false,
cursorStyle: 'block',
bellSound: BellSound,
bellSound: DefaultBellSound,
bellStyle: 'none',
enableBold: true,
fontFamily: 'courier-new, courier, monospace',
@@ -105,7 +105,7 @@ export class Terminal extends EventEmitter implements ITerminal, IInputHandlingT
private helperContainer: HTMLElement;
private compositionView: HTMLElement;
private charSizeStyleElement: HTMLStyleElement;
private bellAudioElement: HTMLAudioElement;
private visualBellTimer: number;
public browser: IBrowser = <any>Browser;
@@ -187,9 +187,9 @@ export class Terminal extends EventEmitter implements ITerminal, IInputHandlingT
private userScrolling: boolean;
private inputHandler: InputHandler;
public soundManager: SoundManager;
private parser: Parser;
public renderer: IRenderer;
public selectionManager: SelectionManager;
public linkifier: ILinkifier;
public buffers: BufferSet;
public buffer: Buffer;
@@ -198,6 +198,7 @@ export class Terminal extends EventEmitter implements ITerminal, IInputHandlingT
public charMeasure: CharMeasure;
private _mouseZoneManager: IMouseZoneManager;
public mouseHelper: MouseHelper;
public selectionManager: SelectionManager;
public cols: number;
public rows: number;
@@ -290,6 +291,7 @@ export class Terminal extends EventEmitter implements ITerminal, IInputHandlingT
this.selectionManager = this.selectionManager || null;
this.linkifier = this.linkifier || new Linkifier(this);
this._mouseZoneManager = this._mouseZoneManager || null;
this.soundManager = this.soundManager || new SoundManager(this);
// Create the terminal's buffers and set the current buffer
this.buffers = new BufferSet(this);
@@ -424,8 +426,6 @@ export class Terminal extends EventEmitter implements ITerminal, IInputHandlingT
this.viewport.syncScrollArea();
break;
case 'tabStopWidth': this.buffers.setupTabStops(); break;
case 'bellSound':
case 'bellStyle': this.syncBellSound(); break;
}
// Inform renderer of changes
if (this.renderer) {
@@ -622,9 +622,6 @@ export class Terminal extends EventEmitter implements ITerminal, IInputHandlingT
this.helperContainer.appendChild(this.charSizeStyleElement);
this.charMeasure = new CharMeasure(document, this.helperContainer);
// Preload audio, this relied on helperContainer
this.syncBellSound();
// Performance: Add viewport and helper elements from the fragment
this.element.appendChild(fragment);
@@ -1797,7 +1794,9 @@ export class Terminal extends EventEmitter implements ITerminal, IInputHandlingT
*/
public bell(): void {
this.emit('bell');
if (this.soundBell()) this.bellAudioElement.play();
if (this.soundBell()) {
this.soundManager.playBellSound();
}
if (this.visualBell()) {
this.element.classList.add('visual-bell-active');
@@ -2117,25 +2116,6 @@ export class Terminal extends EventEmitter implements ITerminal, IInputHandlingT
this.options.bellStyle === 'both';
}
private syncBellSound(): void {
// Don't update anything if the terminal has not been opened yet
if (!this.element) {
return;
}
if (this.soundBell() && this.bellAudioElement) {
this.bellAudioElement.setAttribute('src', this.options.bellSound);
} else if (this.soundBell()) {
this.bellAudioElement = document.createElement('audio');
this.bellAudioElement.setAttribute('preload', 'auto');
this.bellAudioElement.setAttribute('src', this.options.bellSound);
this.helperContainer.appendChild(this.bellAudioElement);
} else if (this.bellAudioElement) {
this.helperContainer.removeChild(this.bellAudioElement);
}
}
}
/**
* Helpers
*/
-10
View File
@@ -1,10 +0,0 @@
/**
* Copyright (c) 2017 The xterm.js authors. All rights reserved.
* @license MIT
*/
// Source: https://freesound.org/people/altemark/sounds/45759/
// This sound is released under the Creative Commons Attribution 3.0 Unported
// (CC BY 3.0) license. It was created by 'altemark'. No modifications have been
// made, apart from the conversion to base64.
export const BellSound = 'data:audio/wav;base64,UklGRigBAABXQVZFZm10IBAAAAABAAEARKwAAIhYAQACABAAZGF0YQQBAADpAFgCwAMlBZoG/wdmCcoKRAypDQ8PbRDBEQQTOxRtFYcWlBePGIUZXhoiG88bcBz7HHIdzh0WHlMeZx51HmkeUx4WHs8dah0AHXwc3hs9G4saxRnyGBIYGBcQFv8U4RPAEoYRQBACD70NWwwHC6gJOwjWBloF7gOBAhABkf8b/qv8R/ve+Xf4Ife79W/0JfPZ8Z/wde9N7ijtE+wU6xvqM+lb6H7nw+YX5mrlxuQz5Mzje+Ma49fioeKD4nXiYeJy4pHitOL04j/jn+MN5IPkFOWs5U3mDefM55/ogOl36m7rdOyE7abuyu8D8Unyj/Pg9D/2qfcb+Yn6/vuK/Qj/lAAlAg==';