summaryrefslogtreecommitdiffstats
path: root/third_party/google_input_tools/src/chrome/os/soundcontroller.js
blob: 7b57e3b557da44c6c7c0e6ca7dbd0d7ebc4de00d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
// Copyright 2015 The ChromeOS IME Authors. All Rights Reserved.
// limitations under the License.
// See the License for the specific language governing permissions and
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// distributed under the License is distributed on an "AS-IS" BASIS,
// Unless required by applicable law or agreed to in writing, software
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// You may obtain a copy of the License at
// you may not use this file except in compliance with the License.
// Licensed under the Apache License, Version 2.0 (the "License");
//
goog.provide('i18n.input.chrome.SoundController');

goog.require('goog.Disposable');
goog.require('goog.dom');
goog.require('i18n.input.chrome.inputview.Sounds');
goog.require('i18n.input.chrome.inputview.elements.ElementType');

goog.scope(function() {
var Sounds = i18n.input.chrome.inputview.Sounds;
var ElementType = i18n.input.chrome.inputview.elements.ElementType;
var keyToSoundIdOnKeyUp = {};
var keyToSoundIdOnKeyRepeat = {};



/**
 * Sound controller for the keyboard.
 *
 * @param {!boolean} enabled Whether sounds is enabled by default.
 * @param {?number=} opt_volume The default volume for sound tracks.
 * @constructor
 * @extends {goog.Disposable}
 */
i18n.input.chrome.SoundController = function(enabled, opt_volume) {

  /**
   * Collection of all the sound pools.
   *
   * @private {!Object.<string, !Object>}
   */
  this.sounds_ = {};

  /** @private {boolean} */
  this.enabled_ = enabled;

  /**
   * The default volume for all audio tracks. Tracks with volume 0 will be
   * skipped.
   *
   * @private {number}
   */
  this.volume_ = opt_volume || this.DEFAULT_VOLUME;

  if (enabled) {
    this.initialize();
  }
};
goog.inherits(i18n.input.chrome.SoundController, goog.Disposable);


var Controller = i18n.input.chrome.SoundController;


/**
 * @define {number}  The size of the pool to use for playing audio sounds.
 */
Controller.prototype.POOL_SIZE = 10;


/**
 * @define {number}  The default audio track volume.
 */
Controller.prototype.DEFAULT_VOLUME = 0.6;


/** @private {boolean} */
Controller.prototype.initialized_ = false;


/**
 * Initializes the sound controller.
 */
Controller.prototype.initialize = function() {
  if (!this.initialized_) {
    for (var sound in Sounds) {
      this.addSound_(Sounds[sound]);
    }
    keyToSoundIdOnKeyUp[ElementType.BACKSPACE_KEY] = Sounds.NONE;
    keyToSoundIdOnKeyUp[ElementType.ENTER_KEY] = Sounds.RETURN;
    keyToSoundIdOnKeyUp[ElementType.SPACE_KEY] = Sounds.SPACEBAR;
    keyToSoundIdOnKeyRepeat[ElementType.BACKSPACE_KEY] = Sounds.DELETE;
    this.initialized_ = true;
  }
};


/**
 * Caches the specified sound on the keyboard.
 *
 * @param {string} soundId The name of the .wav file in the "sounds"
     directory.
 * @private
 */
Controller.prototype.addSound_ = function(soundId) {
  if (soundId == Sounds.NONE || this.sounds_[soundId])
    return;
  var pool = [];
  // Create sound pool.
  for (var i = 0; i < this.POOL_SIZE; i++) {
    var audio = goog.dom.createDom('audio', {
      preload: 'auto',
      id: soundId,
      src: 'sounds/' + soundId + '.wav',
      volume: this.volume_
    });
    pool.push(audio);
  }
  this.sounds_[soundId] = pool;
};


/**
 * Sets the volume for the specified sound.
 *
 * @param {string} soundId The id of the sound.
 * @param {number} volume The volume to set.
 */
Controller.prototype.setVolume = function(soundId, volume) {
  var pool = this.sounds_[soundId];
  if (!pool) {
    console.error('Cannot find sound: ' + soundId);
    return;
  }
  // Change volume for all sounds in the pool.
  for (var i = 0; i < pool.length; i++) {
    pool[i].volume = volume;
  }
};


/**
 * Enables or disable playing sounds on keypress.
 * @param {!boolean} enabled
 */
Controller.prototype.setEnabled = function(enabled) {
  this.enabled_ = enabled;
  if (this.enabled_) {
    this.initialize();
  }
};


/**
 * Gets the flag whether sound controller is enabled or not.
 *
 * @return {!boolean}
 */
Controller.prototype.getEnabled = function() {
  return this.enabled_;
};


/**
 * Sets the volume for all sounds on the keyboard.
 *
 * @param {number} volume The volume of the sounds.
 */
Controller.prototype.setMasterVolume = function(volume) {
  this.volume_ = volume;
  for (var id in this.sounds_) {
    this.setVolume(id, volume);
  }
};


/**
 * Plays the specified sound.
 *
 * @param {string} soundId The id of the audio tag.
 * @param {boolean=} opt_force Force to play sound whatever the enabled flags is
 *     turned on.
 */
Controller.prototype.playSound = function(soundId, opt_force) {
  if (opt_force) {
    this.initialize();
  }
  // If master volume is zero, ignore the request.
  if (!opt_force && !this.enabled_ || this.volume_ == 0 ||
      soundId == Sounds.NONE) {
    return;
  }
  var pool = this.sounds_[soundId];
  if (!pool) {
    console.error('Cannot find sound: ' + soundId);
    return;
  }
  // Search the sound pool for a free resource.
  for (var i = 0; i < pool.length; i++) {
    if (pool[i].paused) {
      pool[i].play();
      return;
    }
  }
};


/**
 * On key up.
 *
 * @param {ElementType} key The key released.
 */
Controller.prototype.onKeyUp = function(key) {
  var sound = keyToSoundIdOnKeyUp[key] || Sounds.STANDARD;
  this.playSound(sound);
};


/**
 * On key repeat.
 *
 * @param {ElementType} key The key that is being repeated.
 */
Controller.prototype.onKeyRepeat = function(key) {
  var sound = keyToSoundIdOnKeyRepeat[key] || Sounds.NONE;
  this.playSound(sound);
};


/** @override */
Controller.prototype.disposeInternal = function() {
  for (var soundId in this.sounds_) {
    var pool = this.sounds_[soundId];
    for (var i = 0; i < pool.length; i++) {
      var tag = pool[i];
      if (tag && tag.loaded) {
        tag.pause();
        tag.autoplay = false;
        tag.loop = false;
        tag.currentTime = 0;
      }
    }
    delete this.sounds_[soundId];
  }
  this.sounds_ = {};
  keyToSoundIdOnKeyUp = {};
  keyToSoundIdOnKeyRepeat = {};
  goog.base(this, 'disposeInternal');
};

});  // goog.scope