Skip to content

Commit

Permalink
Merge pull request #878 from npezza93/add-bell-sound
Browse files Browse the repository at this point in the history
If bell() gets called emit bell event and add default bell sound
  • Loading branch information
Tyriar authored Aug 19, 2017
2 parents ae0d5e4 + 1f930c1 commit 9ab17de
Show file tree
Hide file tree
Showing 9 changed files with 85 additions and 22 deletions.
11 changes: 11 additions & 0 deletions demo/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,17 @@ <h2>Options</h2>
</select>
</label>
</p>
<p>
<label>
bellStyle
<select id="option-bell-style">
<option value="">none</option>
<option value="sound">sound</option>
<option value="visual">visual</option>
<option value="both">both</option>
</select>
</label>
</p>
<p>
<label>scrollback <input type="number" id="option-scrollback" value="1000" /></label>
</p>
Expand Down
6 changes: 5 additions & 1 deletion demo/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ var terminalContainer = document.getElementById('terminal-container'),
cursorBlink: document.querySelector('#option-cursor-blink'),
cursorStyle: document.querySelector('#option-cursor-style'),
scrollback: document.querySelector('#option-scrollback'),
tabstopwidth: document.querySelector('#option-tabstopwidth')
tabstopwidth: document.querySelector('#option-tabstopwidth'),
bellStyle: document.querySelector('#option-bell-style')
},
colsElement = document.getElementById('cols'),
rowsElement = document.getElementById('rows');
Expand Down Expand Up @@ -53,6 +54,9 @@ optionElements.cursorBlink.addEventListener('change', function () {
optionElements.cursorStyle.addEventListener('change', function () {
term.setOption('cursorStyle', optionElements.cursorStyle.value);
});
optionElements.bellStyle.addEventListener('change', function () {
term.setOption('bellStyle', optionElements.bellStyle.value);
});
optionElements.scrollback.addEventListener('change', function () {
term.setOption('scrollback', parseInt(optionElements.scrollback.value, 10));
});
Expand Down
9 changes: 1 addition & 8 deletions src/InputHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,14 +106,7 @@ export class InputHandler implements IInputHandler {
* Bell (Ctrl-G).
*/
public bell(): void {
if (!this._terminal.options.visualBell) {
return;
}
this._terminal.element.style.borderColor = 'white';
setTimeout(() => this._terminal.element.style.borderColor = '', 10);
if (this._terminal.options.popOnBell) {
this._terminal.focus();
}
this._terminal.bell();
}

/**
Expand Down
5 changes: 3 additions & 2 deletions src/Interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ export interface IInputHandlingTerminal extends IEventEmitter {
viewport: IViewport;
selectionManager: ISelectionManager;

bell(): void;
focus(): void;
convertEol: boolean;
updateRange(y: number): void;
Expand All @@ -113,6 +114,8 @@ export interface IInputHandlingTerminal extends IEventEmitter {
}

export interface ITerminalOptions {
bellSound?: string;
bellStyle?: string;
cancelEvents?: boolean;
colors?: string[];
cols?: number;
Expand All @@ -123,14 +126,12 @@ export interface ITerminalOptions {
disableStdin?: boolean;
geometry?: [number, number];
handler?: (data: string) => void;
popOnBell?: boolean;
rows?: number;
screenKeys?: boolean;
scrollback?: number;
tabStopWidth?: number;
termName?: string;
useFlowControl?: boolean;
visualBell?: boolean;
}

export interface IBuffer {
Expand Down
48 changes: 40 additions & 8 deletions src/Terminal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ import { CHARSETS } from './Charsets';
import { getRawByteCoords } from './utils/Mouse';
import { CustomKeyEventHandler, Charset, LinkMatcherHandler, LinkMatcherValidationCallback, CharData, LineData, Option, StringOption, BooleanOption, StringArrayOption, NumberOption, GeometryOption, HandlerOption } from './Types';
import { ITerminal, IBrowser, ITerminalOptions, IInputHandlingTerminal, ILinkMatcherOptions, IViewport, ICompositionHelper } from './Interfaces';
import { BellSound } from './utils/Sounds';

// Declare for RequireJS in loadAddon
declare var define: any;
Expand Down Expand Up @@ -147,8 +148,8 @@ const DEFAULT_OPTIONS: ITerminalOptions = {
geometry: [80, 24],
cursorBlink: false,
cursorStyle: 'block',
visualBell: false,
popOnBell: false,
bellSound: BellSound,
bellStyle: null,
scrollback: 1000,
screenKeys: false,
debug: false,
Expand Down Expand Up @@ -178,6 +179,8 @@ 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;

Expand Down Expand Up @@ -482,6 +485,7 @@ export class Terminal extends EventEmitter implements ITerminal, IInputHandlingT
this.viewport.syncScrollArea();
break;
case 'tabStopWidth': this.setupStops(); break;
case 'bellStyle': this.preloadBellSound(); break;
}
}

Expand Down Expand Up @@ -689,6 +693,9 @@ export class Terminal extends EventEmitter implements ITerminal, IInputHandlingT
this.viewportScrollArea.classList.add('xterm-scroll-area');
this.viewportElement.appendChild(this.viewportScrollArea);

// preload audio
this.preloadBellSound();

// Create the selection container.
this.selectionContainer = document.createElement('div');
this.selectionContainer.classList.add('xterm-selection');
Expand Down Expand Up @@ -1874,12 +1881,16 @@ export class Terminal extends EventEmitter implements ITerminal, IInputHandlingT
* Note: We could do sweet things with webaudio here
*/
public bell(): void {
if (!this.options.visualBell) return;
this.element.style.borderColor = 'white';
setTimeout(() => {
this.element.style.borderColor = '';
}, 10);
if (this.options.popOnBell) this.focus();
this.emit('bell');
if (this.soundBell()) this.bellAudioElement.play();

if (this.visualBell()) {
this.element.classList.add('visual-bell-active');
clearTimeout(this.visualBellTimer);
this.visualBellTimer = window.setTimeout(() => {
this.element.classList.remove('visual-bell-active');
}, 200);
}
}

/**
Expand Down Expand Up @@ -2271,6 +2282,27 @@ export class Terminal extends EventEmitter implements ITerminal, IInputHandlingT

return matchColorCache[hash] = li;
}

private visualBell(): boolean {
return this.options.bellStyle === 'visual' ||
this.options.bellStyle === 'both';
}

private soundBell(): boolean {
return this.options.bellStyle === 'sound' ||
this.options.bellStyle === 'both';
}

private preloadBellSound(): void {
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);
}
}
}

/**
Expand Down
5 changes: 2 additions & 3 deletions src/Types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,11 @@ export type BooleanOption =
'cursorBlink' |
'debug' |
'disableStdin' |
'popOnBell' |
'screenKeys' |
'useFlowControl' |
'visualBell';
'useFlowControl';
export type StringOption =
'cursorStyle' |
'bellStyle' |
'termName';
export type StringArrayOption = 'colors';
export type NumberOption =
Expand Down
9 changes: 9 additions & 0 deletions src/utils/Sounds.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/**
* @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==';
4 changes: 4 additions & 0 deletions src/utils/TestUtils.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,10 @@ export class MockInputHandlingTerminal implements IInputHandlingTerminal {
throw new Error('Method not implemented.');
}
convertEol: boolean;
bell(): void {
throw new Error('Method not implemented.');
}

updateRange(y: number): void {
throw new Error('Method not implemented.');
}
Expand Down
10 changes: 10 additions & 0 deletions src/xterm.css
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@

.terminal .terminal-cursor {
position: relative;
transition: opacity 150ms ease;
}

.terminal:not(.focus) .terminal-cursor {
Expand All @@ -108,6 +109,7 @@
content: '';
position: absolute;
background-color: #fff;
transition: opacity 150ms ease;
}

.terminal.focus.xterm-cursor-style-bar:not(.xterm-cursor-blink-on) .terminal-cursor::before {
Expand All @@ -124,6 +126,14 @@
height: 1px;
}

.terminal.focus.xterm-cursor-style-block.visual-bell-active .terminal-cursor {
opacity: 0.5;
}
.terminal.focus.xterm-cursor-style-bar.visual-bell-active .terminal-cursor::before,
.terminal.focus.xterm-cursor-style-underline.visual-bell-active .terminal-cursor::before {
opacity: 0;
}

.terminal .composition-view {
background: #000;
color: #FFF;
Expand Down

0 comments on commit 9ab17de

Please sign in to comment.