annyang_rails 0.2.0 → 0.2.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- ODY0NWUzZjVhZDkzNzE4NzU0ZWUxMGFkY2UwYzhkMGE3MGJmZGY0Zg==
4
+ YzE5NzFjZmY0ZTNhZThlOTA2NWExMDJjZGU5Y2VhYmRiYTY5NDY4OQ==
5
5
  data.tar.gz: !binary |-
6
- MzFjZjZiZmVlMGU5NzkwMDMyNzY5NWM5YmQ0YjNlOThlM2QyZjUxYw==
6
+ OTM1Njc4ZTAxYTgzOTIyYzQxYmIwZWY2MmI2M2I3NjM4YjQwMTk3OQ==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- MjI5MmI3MWEyYTFiMTkzN2E0NTU2MDNiNDkzZWFmY2U2MWFhMjM2Y2M2ZWZj
10
- ZjQ1NGVkMTg2NzA0M2ViYWQ5ZTRkZjA1NTlhNTZmYzhjNjA2ODAyNjA5YWE2
11
- OWVlMWI0NzIzNjY0ZDkwY2ExMjRiOGE3ZTUxOTI1YjRjNjFkOTI=
9
+ MDRhMjgwNGRmNjIyNjc3MjA5ZjhmN2E0YTE4MDc4ZWE3MzkzMzQ5Njk1MDkz
10
+ MWI5YjQ0NTFjYzE2Y2I1YTQzZDU5MzE5YTQ5MzA3NzdkYTk3N2ExZWU5ZmE1
11
+ MTNhOWY1NWM1NTJjY2IxM2E1N2VmNzRlNDAzODRjMmUzYWFmYWE=
12
12
  data.tar.gz: !binary |-
13
- MjA2NWI5YTcwMDNhNDg0YTQ3MTQxMTU2NzM1YTFmYWU2ZmU0M2Q4YWNjMTE5
14
- NmU1YmRiZDZhNzkzNGZmNDMyYzRhNGU2YWU4MDFlNTI2YTY1NmZjN2M2Yjcx
15
- MTEyOWY0NjM4MjdhMGZmZWQ3ZGVkMjJiMjQ4NTEwZWJjYjhhMTQ=
13
+ NGE5MTI5NzJkMjM4OThjMTU5OWE1ZTk3ZTdlMGIyOWE5ZWQzZTRjMmIzYjZi
14
+ M2UxNDVmZWI1ZWNjNDM0MTk4YTlkMDhhN2Q1OWZlZjliMDc0ODg4NzlhODBm
15
+ ZTk0Y2VhM2RlYTM0YTQ2N2Q1NGE5NDIwM2FhOTUwMGU4YjM4MDI=
@@ -1,20 +1,23 @@
1
- /*! annyang - speech recognition in js
2
- * version : 0.2.0
3
- * author : Tal Ater @TalAter
4
- * license : MIT
5
- * https://www.TalAter.com/annyang/
6
- * https://github.com/TalAter/annyang
7
- */
1
+ //! annyang
2
+ //! version : 0.2.0
3
+ //! author : Tal Ater @TalAter
4
+ //! license : MIT
5
+ //! https://www.TalAter.com/annyang/
8
6
  (function () {
9
7
  "use strict";
10
8
 
9
+ // Save a reference to the global object (window in the browser)
11
10
  var root = this;
11
+
12
+ // Get the SpeechRecognition object, while handling browser prefixes
12
13
  var SpeechRecognition = root.webkitSpeechRecognition ||
13
14
  root.mozSpeechRecognition ||
14
15
  root.msSpeechRecognition ||
15
16
  root.oSpeechRecognition ||
16
17
  root.SpeechRecognition;
18
+
17
19
  // Check browser support
20
+ // This is done as early as possible, to make it as fast as possible for unsupported browsers
18
21
  if ( !SpeechRecognition ) {
19
22
  root.annyang = null;
20
23
  return null;
@@ -23,12 +26,12 @@
23
26
  var commandsList;
24
27
  var recognition;
25
28
  var lang = 'en-US';
26
- var callbacks = { start: [], error: [], end: [], result: [], resultMatch: [], resultNoMatch: [] };
29
+ var callbacks = { start: [], error: [], end: [], result: [], resultMatch: [], resultNoMatch: [], errorNetwork: [], errorPermissionBlocked: [], errorPermissionDenied: [] };
27
30
  var autoRestart;
31
+ var lastStartedAt = 0;
28
32
  var debugState = false;
29
33
  var debugStyle = 'font-weight: bold; color: #00f;';
30
34
 
31
-
32
35
  // The command matching code is a modified version of Backbone.Router by Jeremy Ashkenas, under the MIT license.
33
36
  var optionalParam = /\s*\((.*?)\)\s*/g;
34
37
  var optionalRegex = /(\(\?:[^)]+\))\?/g;
@@ -46,13 +49,17 @@
46
49
  return new RegExp('^' + command + '$', 'i');
47
50
  };
48
51
 
52
+ // This method receives an array of callbacks to iterate over, and invokes each of them
49
53
  var invokeCallbacks = function(callbacks) {
50
54
  for (var j = 0, l = callbacks.length; j < l; j++) {
51
- callbacks[j].apply(this);
55
+ callbacks[j].callback.apply(callbacks[j].context);
52
56
  }
53
57
  };
54
58
 
55
59
  root.annyang = {
60
+ // Initialize annyang with a list of commands to recognize.
61
+ // e.g. annyang.init({'hello :name': helloFunction})
62
+ // annyang understands commands with named variables, splats, and optional words.
56
63
  init: function(commands) {
57
64
 
58
65
  // Abort previous instances of recognition already running
@@ -60,21 +67,48 @@
60
67
  recognition.abort();
61
68
  }
62
69
 
63
- // initiate
70
+ // initiate SpeechRecognition
64
71
  recognition = new SpeechRecognition();
65
72
 
73
+ // Set the max number of alternative transcripts to try and match with a command
66
74
  recognition.maxAlternatives = 5;
67
75
  recognition.continuous = true;
76
+ // Sets the language to the default 'en-US'. This can be changed with annyang.setLanguage()
68
77
  recognition.lang = lang;
69
78
 
70
79
  recognition.onstart = function() { invokeCallbacks(callbacks.start); };
71
80
 
72
- recognition.onerror = function() { invokeCallbacks(callbacks.error); };
81
+ recognition.onerror = function(event) {
82
+ invokeCallbacks(callbacks.error);
83
+ switch (event.error) {
84
+ case 'network':
85
+ invokeCallbacks(callbacks.errorNetwork);
86
+ break;
87
+ case 'not-allowed':
88
+ case 'service-not-allowed':
89
+ // if permission to use the mic is denied, turn off auto-restart
90
+ autoRestart = false;
91
+ // determine if permission was denied by user or automatically.
92
+ if (new Date().getTime()-lastStartedAt < 200) {
93
+ invokeCallbacks(callbacks.errorPermissionBlocked);
94
+ } else {
95
+ invokeCallbacks(callbacks.errorPermissionDenied);
96
+ }
97
+ break;
98
+ }
99
+ };
73
100
 
74
101
  recognition.onend = function() {
75
102
  invokeCallbacks(callbacks.end);
103
+ // annyang will auto restart if it is closed automatically and not by user action.
76
104
  if (autoRestart) {
77
- root.annyang.start();
105
+ // play nicely with the browser, and never restart annyang automatically more than once per second
106
+ var timeSinceLastStart = new Date().getTime()-lastStartedAt;
107
+ if (timeSinceLastStart < 1000) {
108
+ setTimeout(root.annyang.start, 1000-timeSinceLastStart);
109
+ } else {
110
+ root.annyang.start();
111
+ }
78
112
  }
79
113
  };
80
114
 
@@ -82,12 +116,15 @@
82
116
  invokeCallbacks(callbacks.result);
83
117
  var results = event.results[event.resultIndex];
84
118
  var commandText;
119
+ // go over each of the 5 results and alternative results received (we've set maxAlternatives to 5 above)
85
120
  for (var i = 0; i<results.length; i++) {
121
+ // the text recognized
86
122
  commandText = results[i].transcript.trim();
87
123
  if (debugState) {
88
124
  root.console.log('Speech recognized: %c'+commandText, debugStyle);
89
125
  }
90
126
 
127
+ // try and match recognized text to one of the commands on the list
91
128
  for (var j = 0, l = commandsList.length; j < l; j++) {
92
129
  var result = commandsList[j].command.exec(commandText);
93
130
  if (result) {
@@ -98,6 +135,7 @@
98
135
  root.console.log('with parameters', parameters);
99
136
  }
100
137
  }
138
+ // execute the matched command
101
139
  commandsList[j].callback.apply(this, parameters);
102
140
  invokeCallbacks(callbacks.resultMatch);
103
141
  return true;
@@ -113,21 +151,28 @@
113
151
  this.addCommands(commands);
114
152
  },
115
153
 
154
+ // Start listening (asking for permission first, if needed).
155
+ // Call this after you've initialized annyang with commands.
156
+ // Receives an optional options object:
157
+ // { autoRestart: true }
116
158
  start: function(options) {
117
159
  options = options || {};
118
- if (typeof options.autoRestart !== 'undefined') {
160
+ if (options.autoRestart !== void 0) {
119
161
  autoRestart = !!options.autoRestart;
120
162
  } else {
121
163
  autoRestart = true;
122
164
  }
165
+ lastStartedAt = new Date().getTime();
123
166
  recognition.start();
124
167
  },
125
168
 
169
+ // abort the listening session (aka stop)
126
170
  abort: function() {
127
171
  autoRestart = false;
128
172
  recognition.abort();
129
173
  },
130
174
 
175
+ // Turn on output of debug messages to the console. Ugly, but super-handy!
131
176
  debug: function(newState) {
132
177
  if (arguments.length > 0) {
133
178
  debugState = !!newState;
@@ -136,6 +181,8 @@
136
181
  }
137
182
  },
138
183
 
184
+ // Set the language the user will speak in. If not called, defaults to 'en-US'.
185
+ // e.g. 'fr-FR' (French-France), 'es-CR' (Español-Costa Rica)
139
186
  setLanguage: function(language) {
140
187
  lang = language;
141
188
  if (recognition && recognition.abort) {
@@ -143,6 +190,7 @@
143
190
  }
144
191
  },
145
192
 
193
+ // Add additional commands that annyang will respond to. Similar in syntax to annyang.init()
146
194
  addCommands: function(commands) {
147
195
  var cb,
148
196
  command;
@@ -163,10 +211,10 @@
163
211
  }
164
212
  },
165
213
 
166
- /**
167
- * Lets the user add a callback of one of 6 types: start, error, end, result, resultMatch, resultNoMatch
168
- */
169
- addCallback: function(type, callback) {
214
+ // Lets the user add a callback of one of 9 types:
215
+ // start, error, end, result, resultMatch, resultNoMatch, errorNetwork, errorPermissionBlocked, errorPermissionDenied
216
+ // Can also optionally receive a context for the callback function as the third argument
217
+ addCallback: function(type, callback, context) {
170
218
  if (callbacks[type] === void 0) {
171
219
  return;
172
220
  }
@@ -174,7 +222,7 @@
174
222
  if (typeof cb !== 'function') {
175
223
  return;
176
224
  }
177
- callbacks[type].push(cb);
225
+ callbacks[type].push({callback: cb, context: context || this});
178
226
  }
179
227
  };
180
228
 
@@ -1,3 +1,3 @@
1
1
  module AnnyangRails
2
- VERSION = "0.2.0"
2
+ VERSION = "0.2.0.1"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: annyang_rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.2.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Guy Israeli
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-09-16 00:00:00.000000000 Z
11
+ date: 2013-10-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler