summaryrefslogtreecommitdiff
path: root/chromium/chrome/browser/resources/chromeos/emulator/audio_settings.js
blob: 739c21c6689f9a00afb3ab19507627ff3e53d96a (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
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

/** @enum {string} */ var AudioNodeType = {
  HEADPHONE: 'HEADPHONE',
  MIC: 'MIC',
  USB: 'USB',
  BLUETOOTH: 'BLUETOOTH',
  HDMI: 'HDMI',
  INTERNAL_SPEAKER: 'INTERNAL_SPEAKER',
  INTERNAL_MIC: 'INTERNAL_MIC',
  KEYBOARD_MIC: 'KEYBOARD_MIC',
  AOKR: 'AOKR',
  POST_MIX_LOOPBACK: 'POST_MIX_LOOPBACK',
  POST_DSP_LOOPBACK: 'POST_DSP_LOOPBACK',
  OTHER: 'OTHER',
};

/**
 * An audio node. Based on the struct AudioNode found in audio_node.h.
 * @constructor
 */
var AudioNode = function() {
  // Whether node will input or output audio.
  this.isInput = false;

  // Node ID. Set to 3000 because predefined output and input
  // nodes use 10000's and 20000's respectively and |nodeCount| will append it.
  this.id = '3000';

  // Display name of the node. When this is empty, cras will automatically
  // use |this.deviceName| as the display name.
  this.name = '';

  // The text label of the selected node name.
  this.deviceName = 'New Device';

  // Based on the AudioNodeType enum.
  this.type = AudioNodeType.OTHER;

  // Whether the node is active or not.
  this.active = false;

  // The time the node was plugged in (in seconds).
  this.pluggedTime = 0;
};

Polymer({
  is: 'audio-settings',

  properties: {
    /**
     * An AudioNode which is currently being edited.
     * @type {AudioNode}
     */
    currentEditableObject: {
      type: Object,
      value: function() { return {}; }
    },

    /**
     * The index of the audio node which is currently being edited.
     * This is initially set to -1 (i.e. no node selected) becuase no devices
     * have been copied.
     */
    currentEditIndex: {type: Number, value: function() { return -1; }},

    /**
     * A counter that will auto increment everytime a new node is added
     * or copied and used to set a new id. This allows the |AudioNode.id|
     * to allows be unique.
     */
    nodeCount: {type: Number, value: function() { return 0; }},

    /**
     * A set of audio nodes.
     * @type !Array<!AudioNode>
     */
    nodes: {type: Array, value: function() { return []; }},

    /**
     * A set of options for the possible audio node types.
     * AudioNodeType |type| is based on the AudioType emumation.
     * @type {!Array<!{name: string, type: string}>}
     */
    nodeTypeOptions: {
      type: Array,
      value: function() {
        return [
          {name: 'Headphones', type: AudioNodeType.HEADPHONE},
          {name: 'Mic', type: AudioNodeType.MIC},
          {name: 'Usb', type: AudioNodeType.USB},
          {name: 'Bluetooth', type: AudioNodeType.BLUETOOTH},
          {name: 'HDMI', type: AudioNodeType.HDMI},
          {name: 'Internal Speaker', type: AudioNodeType.INTERNAL_SPEAKER},
          {name: 'Internal Mic', type: AudioNodeType.INTERNAL_MIC},
          {name: 'Keyboard Mic', type: AudioNodeType.KEYBOARD_MIC},
          {name: 'Aokr', type: AudioNodeType.AOKR},
          {name: 'Post Mix Loopback', type: AudioNodeType.POST_MIX_LOOPBACK},
          {name: 'Post Dsp Loopback', type: AudioNodeType.POST_DSP_LOOPBACK},
          {name: 'Other', type: AudioNodeType.OTHER}
        ];
      }
    },

    /**
     * The title to be displayed in a heading element for the element.
     */
    title: {type: String},
  },

  ready: function() {
    this.title = 'Audio';
  },

  initialize: function() {
    if (!this.initialized) {
      chrome.send('requestAudioNodes');
      this.initialized = true;
    }
  },

  /**
   * Adds a new node with default settings to the list of nodes.
   */
  appendNewNode: function() {
    var newNode = new AudioNode();
    newNode.id += this.nodeCount;
    this.nodeCount++;
    this.push('nodes', newNode);
  },

  /**
   * This adds or modifies an audio node to the AudioNodeList.
   * @param {model: {index: number}} e Event with a model containing
   *     the index in |nodes| to add.
   */
  insertAudioNode: function(e) {
    // Create a new audio node and add all the properties from |nodes[i]|.
    var info = this.nodes[e.model.index];
    chrome.send('insertAudioNode', [info]);
  },

  /**
   * This adds/modifies the audio node |nodes[currentEditIndex]| to/from the
   * AudioNodeList.
   * @param {model: {index: number}} e Event with a model containing
   *     the index in |nodes| to add.
   */
  insertEditedAudioNode: function(e) {
    // Insert a new node or update an existing node using all the properties
    // in |node|.
    var node = this.nodes[this.currentEditIndex];
    chrome.send('insertAudioNode', [node]);
  },

  /**
   * Removes the audio node with id |id|.
   * @param {model: {index: number}} e Event with a model containing
   *     the index in |nodes| to add.
   */
  removeAudioNode: function(e) {
    var info = this.nodes[e.model.index];
    chrome.send('removeAudioNode', [info.id]);
  },

  /**
   * Called on "copy" button from the device list clicked. Creates a copy of
   * the selected node.
   * @param {Event} event Contains event data. |event.model.index| is the index
   *     of the item which the target is contained in.
   */
  copyDevice: function(event) {
    // Create a shallow copy of the selected device.
    var newNode = new AudioNode();
    Object.assign(newNode, this.nodes[event.model.index]);
    newNode.name += ' (Copy)';
    newNode.deviceName += ' (Copy)';
    newNode.id += this.nodeCount;
    this.nodeCount++;

    this.push('nodes', newNode);
  },

  /**
   * Shows a modal dialog to edit the selected node's properties.
   * @param {Event} event Contains event data. |event.model.index| is the index
   *     of the item which the target is contained in.
   */
  showEditModal: function(event) {
    var index = event.model.index;
    this.currentEditIndex = index;
    this.currentEditableObject = this.nodes[index];
    this.$.editModal.toggle();
  },

  /**
   * Called by the WebUI which provides a list of nodes.
   * @param {!Array<!AudioNode>} nodeList A list of audio nodes.
   */
  updateAudioNodes: function(nodeList) {
    /** @type {!Array<!AudioNode>} */ var newNodeList = [];
    for (var i = 0; i < nodeList.length; ++i) {
      // Create a new audio node and add all the properties from |nodeList[i]|.
      var node = new AudioNode();
      Object.assign(node, nodeList[i]);
      newNodeList.push(node);
    }
    this.nodes = newNodeList;
  }
});