This repository has been archived by the owner on Nov 3, 2021. It is now read-only.
/
sound.js
186 lines (169 loc) · 6.62 KB
/
sound.js
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
/* global getSupportedNetworkInfo, URL, MozActivity */
/**
* Handle sound panel functionality
*/
define(function(require) {
'use strict';
var ForwardLock = require('shared/omadrm/fl');
var SettingsListener = require('shared/settings_listener');
var Sound = function() {
this.elements = null;
this.tones = null;
};
Sound.prototype = {
/**
* initialization
*/
init: function sound_init(elements) {
this.elements = elements;
if (window.navigator.mozMobileConnections) {
var mobileConnections = window.navigator.mozMobileConnections;
// Show the touch tone selector if and only if we're on a CDMA network
var toneSelector = this.elements.toneSelector;
Array.prototype.forEach.call(mobileConnections,
function(mobileConnection) {
getSupportedNetworkInfo(mobileConnection, function(result) {
toneSelector.hidden = toneSelector.hidden && !result.cdma;
});
});
}
// initialize the ring tone and alert tone menus.
this._configureTones();
this._handleTones();
},
uninit: function sound_uninit() {
this.elements = null;
this.tones = null;
},
_configureTones: function sound_configureTones() {
/**
* This array has one element for each selectable tone that appears in the
* "Tones" section of ../elements/sound.html.
*/
this.tones = [{
pickType: 'alerttone',
settingsKey: 'notification.ringtone',
allowNone: true, // Allow "None" as a choice for alert tones.
button: this.elements.alertTone
}];
// If we're a telephone, then show the section for ringtones, too.
if (navigator.mozTelephony) {
this.tones.push({
pickType: 'ringtone',
settingsKey: 'dialer.ringtone',
allowNone: false, // The ringer must always have an actual sound.
button: this.elements.ringTone
});
this.elements.ringer.hidden = false;
}
},
_handleTones: function sound_handleTones() {
var _ = navigator.mozL10n.get;
var self = this;
// For each kind of tone, hook up the button that will allow the user
// to select a sound for that kind of tone.
this.tones.forEach(function(tone) {
var namekey = tone.settingsKey + '.name';
// The button looks like a select element. By default it just reads
// "change". But we want it to display the name of the current tone.
// So we look up that name in the settings database.
SettingsListener.observe(namekey, '', function(tonename) {
tone.button.textContent = tonename || _('change');
});
// When the user clicks the button, we launch an activity that lets
// the user select new ringtone.
tone.button.onclick = function() {
/**
* Before we can start the Pick activity, we need to know if there
* is locked content on the phone because we don't want the user to
* see "Purchased Media" as a choice if there isn't any purchased
* media on the phone. The ForwardLock secret key is not generated
* until it is needed, so we can use its existance to
* determine whether to show the Purchased Media app.
*/
ForwardLock.getKey(function(secret) {
var activity = new MozActivity({
name: 'pick',
data: {
type: tone.pickType,
allowNone: tone.allowNone,
// If we have a secret then there is locked content on the phone
// so include it as a choice for the user
includeLocked: (secret !== null)
}
});
activity.onsuccess = function() {
var blob = activity.result.blob; // The returned ringtone sound
var name = activity.result.name; // The name of this ringtone
if (!blob) {
if (tone.allowNone) {
// If we allow a null blob, then everything is okay
self._setRingtone(blob, name, tone.settingsKey);
} else {
// Otherwise this is an error and we should not change the
// current setting. (The ringtones app should never return
// a null blob if allowNone is false, but other apps might.)
alert(_('unplayable-ringtone'));
}
return;
}
// If we got a locked ringtone, we have to unlock it first
if (blob.type.split('/')[1] === ForwardLock.mimeSubtype) {
ForwardLock.unlockBlob(secret, blob, function(unlocked) {
self._checkRingtone(unlocked, name, tone);
});
} else { // Otherwise we can just use the blob directly.
self._checkRingtone(blob, name, tone);
}
};
});
};
});
},
/**
* Make sure that the blob we got from the activity is actually
* a playable audio file. It would be very bad to set an corrupt
* blob as a ringtone because then the phone wouldn't ring!
*/
_checkRingtone: function sound_checkRingtone(blob, name, tone) {
var _ = navigator.mozL10n.get;
var oldRingtoneName = tone.button.textContent;
tone.button.textContent = _('savingringtone');
var player = new Audio();
player.preload = 'metadata';
player.src = URL.createObjectURL(blob);
player.oncanplay = function() {
release();
// this will update the button text
this._setRingtone(blob, name, tone.settingsKey);
}.bind(this);
player.onerror = function() {
release();
tone.button.textContent = oldRingtoneName;
alert(_('unplayable-ringtone'));
};
function release() {
URL.revokeObjectURL(player.src);
player.removeAttribute('src');
player.load();
}
},
/*
* Save the sound in the settings db so that other apps can
* use it.
* Also save the sound name in the db so we can display it in the future.
* And update the button text to the new name now.
*/
_setRingtone: function sound_setRingtone(blob, name, settingsKey) {
// Update the settings database. This will cause the button
// text to change as well because of the SettingsListener above.
var values = {};
values[settingsKey] = blob;
values[settingsKey + '.name'] = name || '';
navigator.mozSettings.createLock().set(values);
}
};
return function ctor_sound() {
return new Sound();
};
});