|
15 | 15 | #define MESSAGE_RESTRICTED @"Speech recognition restricted on this device"
|
16 | 16 | #define MESSAGE_NOT_DETERMINED @"Speech recognition not determined on this device"
|
17 | 17 | #define MESSAGE_ACCESS_DENIED_MICROPHONE @"User denied access to microphone"
|
| 18 | +#define MESSAGE_NOT_DETERMINED_MICROPHONE @"Microphone access not determined on this device" |
18 | 19 | #define MESSAGE_ONGOING @"Ongoing speech recognition"
|
19 | 20 |
|
20 | 21 | @interface SpeechRecognition()
|
@@ -58,100 +59,97 @@ - (void)startListening:(CDVInvokedUrlCommand*)command {
|
58 | 59 | return;
|
59 | 60 | }
|
60 | 61 |
|
61 |
| - [[AVAudioSession sharedInstance] requestRecordPermission:^(BOOL granted){ |
62 |
| - if (!granted) { |
63 |
| - NSLog(@"startListening() microphone access not authorized"); |
64 |
| - CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:MESSAGE_ACCESS_DENIED_MICROPHONE]; |
65 |
| - [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; |
66 |
| - return; |
67 |
| - } |
| 62 | + AVAudioSessionRecordPermission micStatus = [[AVAudioSession sharedInstance] recordPermission]; |
| 63 | + if (micStatus != AVAudioSessionRecordPermissionGranted) { |
| 64 | + NSLog(@"startListening() microphone access not authorized"); |
| 65 | + CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:MESSAGE_MISSING_PERMISSION]; |
| 66 | + [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; |
| 67 | + return; |
| 68 | + } |
68 | 69 |
|
69 |
| - NSString* language = [command argumentAtIndex:0 withDefault:DEFAULT_LANGUAGE]; |
70 |
| - int matches = [[command argumentAtIndex:1 withDefault:@(DEFAULT_MATCHES)] intValue]; |
71 |
| - BOOL showPartial = [[command argumentAtIndex:3 withDefault:@(NO)] boolValue]; |
| 70 | + NSString* language = [command argumentAtIndex:0 withDefault:DEFAULT_LANGUAGE]; |
| 71 | + int matches = [[command argumentAtIndex:1 withDefault:@(DEFAULT_MATCHES)] intValue]; |
| 72 | + BOOL showPartial = [[command argumentAtIndex:3 withDefault:@(NO)] boolValue]; |
72 | 73 |
|
73 |
| - NSLocale *locale = [[NSLocale alloc] initWithLocaleIdentifier:language]; |
74 |
| - self.speechRecognizer = [[SFSpeechRecognizer alloc] initWithLocale:locale]; |
75 |
| - self.audioEngine = [[AVAudioEngine alloc] init]; |
| 74 | + NSLocale *locale = [[NSLocale alloc] initWithLocaleIdentifier:language]; |
| 75 | + self.speechRecognizer = [[SFSpeechRecognizer alloc] initWithLocale:locale]; |
| 76 | + self.audioEngine = [[AVAudioEngine alloc] init]; |
76 | 77 |
|
77 |
| - // Cancel the previous task if it's running. |
78 |
| - if ( self.recognitionTask ) { |
79 |
| - [self.recognitionTask cancel]; |
80 |
| - self.recognitionTask = nil; |
81 |
| - } |
| 78 | + // Cancel the previous task if it's running. |
| 79 | + if ( self.recognitionTask ) { |
| 80 | + [self.recognitionTask cancel]; |
| 81 | + self.recognitionTask = nil; |
| 82 | + } |
82 | 83 |
|
83 |
| - AVAudioSession *audioSession = [AVAudioSession sharedInstance]; |
84 |
| - [audioSession setCategory:AVAudioSessionCategoryPlayAndRecord withOptions:AVAudioSessionCategoryOptionDefaultToSpeaker error:nil]; |
85 |
| - [audioSession setMode:AVAudioSessionModeDefault error:nil]; |
86 |
| - [audioSession setActive:YES withOptions:AVAudioSessionSetActiveOptionNotifyOthersOnDeactivation error:nil]; |
| 84 | + AVAudioSession *audioSession = [AVAudioSession sharedInstance]; |
| 85 | + [audioSession setCategory:AVAudioSessionCategoryPlayAndRecord withOptions:AVAudioSessionCategoryOptionDefaultToSpeaker error:nil]; |
| 86 | + [audioSession setMode:AVAudioSessionModeDefault error:nil]; |
| 87 | + [audioSession setActive:YES withOptions:AVAudioSessionSetActiveOptionNotifyOthersOnDeactivation error:nil]; |
87 | 88 |
|
88 |
| - self.recognitionRequest = [[SFSpeechAudioBufferRecognitionRequest alloc] init]; |
89 |
| - self.recognitionRequest.shouldReportPartialResults = showPartial; |
| 89 | + self.recognitionRequest = [[SFSpeechAudioBufferRecognitionRequest alloc] init]; |
| 90 | + self.recognitionRequest.shouldReportPartialResults = showPartial; |
90 | 91 |
|
91 |
| - AVAudioInputNode *inputNode = self.audioEngine.inputNode; |
92 |
| - AVAudioFormat *format = [inputNode outputFormatForBus:0]; |
| 92 | + AVAudioInputNode *inputNode = self.audioEngine.inputNode; |
| 93 | + AVAudioFormat *format = [inputNode outputFormatForBus:0]; |
93 | 94 |
|
94 |
| - self.recognitionTask = [self.speechRecognizer recognitionTaskWithRequest:self.recognitionRequest resultHandler:^(SFSpeechRecognitionResult *result, NSError *error) { |
| 95 | + self.recognitionTask = [self.speechRecognizer recognitionTaskWithRequest:self.recognitionRequest resultHandler:^(SFSpeechRecognitionResult *result, NSError *error) { |
95 | 96 |
|
96 |
| - if ( result ) { |
| 97 | + if ( result ) { |
97 | 98 |
|
98 |
| - NSMutableArray *resultArray = [[NSMutableArray alloc] init]; |
| 99 | + NSMutableArray *resultArray = [[NSMutableArray alloc] init]; |
99 | 100 |
|
100 |
| - int counter = 0; |
101 |
| - for ( SFTranscription *transcription in result.transcriptions ) { |
102 |
| - if (matches > 0 && counter < matches) { |
103 |
| - [resultArray addObject:transcription.formattedString]; |
104 |
| - } |
105 |
| - counter++; |
| 101 | + int counter = 0; |
| 102 | + for ( SFTranscription *transcription in result.transcriptions ) { |
| 103 | + if (matches > 0 && counter < matches) { |
| 104 | + [resultArray addObject:transcription.formattedString]; |
106 | 105 | }
|
| 106 | + counter++; |
| 107 | + } |
107 | 108 |
|
108 |
| - NSArray *transcriptions = [NSArray arrayWithArray:resultArray]; |
| 109 | + NSArray *transcriptions = [NSArray arrayWithArray:resultArray]; |
109 | 110 |
|
110 |
| - NSLog(@"startListening() recognitionTask result array: %@", transcriptions.description); |
| 111 | + NSLog(@"startListening() recognitionTask result array: %@", transcriptions.description); |
111 | 112 |
|
112 |
| - CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsArray:transcriptions]; |
113 |
| - if (showPartial){ |
114 |
| - [pluginResult setKeepCallbackAsBool:YES]; |
115 |
| - } |
116 |
| - [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; |
| 113 | + CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsArray:transcriptions]; |
| 114 | + if (showPartial){ |
| 115 | + [pluginResult setKeepCallbackAsBool:YES]; |
117 | 116 | }
|
| 117 | + [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; |
| 118 | + } |
118 | 119 |
|
119 |
| - if ( error ) { |
120 |
| - NSLog(@"startListening() recognitionTask error: %@", error.description); |
| 120 | + if ( error ) { |
| 121 | + NSLog(@"startListening() recognitionTask error: %@", error.description); |
121 | 122 |
|
122 |
| - [self.audioEngine stop]; |
123 |
| - [self.audioEngine.inputNode removeTapOnBus:0]; |
| 123 | + [self.audioEngine stop]; |
| 124 | + [self.audioEngine.inputNode removeTapOnBus:0]; |
124 | 125 |
|
125 |
| - self.recognitionRequest = nil; |
126 |
| - self.recognitionTask = nil; |
| 126 | + self.recognitionRequest = nil; |
| 127 | + self.recognitionTask = nil; |
127 | 128 |
|
128 |
| - CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:error.description]; |
129 |
| - if (showPartial){ |
130 |
| - [pluginResult setKeepCallbackAsBool:YES]; |
131 |
| - } |
132 |
| - [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; |
| 129 | + CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:error.description]; |
| 130 | + if (showPartial){ |
| 131 | + [pluginResult setKeepCallbackAsBool:YES]; |
133 | 132 | }
|
| 133 | + [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; |
| 134 | + } |
134 | 135 |
|
135 |
| - if ( result.isFinal ) { |
136 |
| - NSLog(@"startListening() recognitionTask isFinal"); |
137 |
| - |
138 |
| - [self.audioEngine stop]; |
139 |
| - [self.audioEngine.inputNode removeTapOnBus:0]; |
| 136 | + if ( result.isFinal ) { |
| 137 | + NSLog(@"startListening() recognitionTask isFinal"); |
140 | 138 |
|
141 |
| - self.recognitionRequest = nil; |
142 |
| - self.recognitionTask = nil; |
143 |
| - } |
144 |
| - }]; |
145 |
| - |
146 |
| - [inputNode installTapOnBus:0 bufferSize:1024 format:format block:^(AVAudioPCMBuffer *buffer, AVAudioTime *when) { |
147 |
| - [self.recognitionRequest appendAudioPCMBuffer:buffer]; |
148 |
| - }]; |
| 139 | + [self.audioEngine stop]; |
| 140 | + [self.audioEngine.inputNode removeTapOnBus:0]; |
149 | 141 |
|
150 |
| - [self.audioEngine prepare]; |
151 |
| - [self.audioEngine startAndReturnError:nil]; |
| 142 | + self.recognitionRequest = nil; |
| 143 | + self.recognitionTask = nil; |
| 144 | + } |
| 145 | + }]; |
152 | 146 |
|
| 147 | + [inputNode installTapOnBus:0 bufferSize:1024 format:format block:^(AVAudioPCMBuffer *buffer, AVAudioTime *when) { |
| 148 | + [self.recognitionRequest appendAudioPCMBuffer:buffer]; |
153 | 149 | }];
|
154 | 150 |
|
| 151 | + [self.audioEngine prepare]; |
| 152 | + [self.audioEngine startAndReturnError:nil]; |
155 | 153 | }
|
156 | 154 |
|
157 | 155 | - (void)stopListening:(CDVInvokedUrlCommand*)command {
|
@@ -183,18 +181,44 @@ - (void)getSupportedLanguages:(CDVInvokedUrlCommand*)command {
|
183 | 181 |
|
184 | 182 | - (void)hasPermission:(CDVInvokedUrlCommand*)command {
|
185 | 183 | SFSpeechRecognizerAuthorizationStatus status = [SFSpeechRecognizer authorizationStatus];
|
186 |
| - BOOL speechAuthGranted = (status == SFSpeechRecognizerAuthorizationStatusAuthorized); |
| 184 | + CDVPluginResult *pluginResult = nil; |
| 185 | + BOOL speechAuthGranted = NO; |
| 186 | + |
| 187 | + switch (status) { |
| 188 | + case SFSpeechRecognizerAuthorizationStatusAuthorized: |
| 189 | + pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK]; |
| 190 | + speechAuthGranted = YES; |
| 191 | + break; |
| 192 | + case SFSpeechRecognizerAuthorizationStatusDenied: |
| 193 | + pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:MESSAGE_ACCESS_DENIED]; |
| 194 | + break; |
| 195 | + case SFSpeechRecognizerAuthorizationStatusRestricted: |
| 196 | + pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:MESSAGE_RESTRICTED]; |
| 197 | + break; |
| 198 | + case SFSpeechRecognizerAuthorizationStatusNotDetermined: |
| 199 | + pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:MESSAGE_NOT_DETERMINED]; |
| 200 | + break; |
| 201 | + } |
187 | 202 |
|
188 | 203 | if (!speechAuthGranted) {
|
189 |
| - CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsBool:NO]; |
190 | 204 | [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
|
191 | 205 | return;
|
192 | 206 | }
|
193 | 207 |
|
194 |
| - [[AVAudioSession sharedInstance] requestRecordPermission:^(BOOL granted){ |
195 |
| - CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsBool:granted]; |
196 |
| - [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; |
197 |
| - }]; |
| 208 | + AVAudioSessionRecordPermission micStatus = [[AVAudioSession sharedInstance] recordPermission]; |
| 209 | + |
| 210 | + switch (micStatus) { |
| 211 | + case AVAudioSessionRecordPermissionGranted: |
| 212 | + break; |
| 213 | + case AVAudioSessionRecordPermissionDenied: |
| 214 | + pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:MESSAGE_ACCESS_DENIED_MICROPHONE]; |
| 215 | + break; |
| 216 | + case AVAudioSessionRecordPermissionUndetermined: |
| 217 | + pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:MESSAGE_NOT_DETERMINED_MICROPHONE]; |
| 218 | + break; |
| 219 | + } |
| 220 | + |
| 221 | + [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; |
198 | 222 | }
|
199 | 223 |
|
200 | 224 | - (void)requestPermission:(CDVInvokedUrlCommand*)command {
|
|
0 commit comments