Skip to content
Newer
Older
100755 661 lines (562 sloc) 25.8 KB
364ac7a @hollyschinsky Initial Project Checkin
authored Oct 19, 2012
1 /*
2 Licensed to the Apache Software Foundation (ASF) under one
3 or more contributor license agreements. See the NOTICE file
4 distributed with this work for additional information
5 regarding copyright ownership. The ASF licenses this file
6 to you under the Apache License, Version 2.0 (the
7 "License"); you may not use this file except in compliance
8 with the License. You may obtain a copy of the License at
9
10 http://www.apache.org/licenses/LICENSE-2.0
11
12 Unless required by applicable law or agreed to in writing,
13 software distributed under the License is distributed on an
14 "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 KIND, either express or implied. See the License for the
16 specific language governing permissions and limitations
17 under the License.
18 */
19
20
21 #import "CDVSound.h"
22 #import "CDVViewController.h"
23 #import "NSArray+Comparisons.h"
24
25 #define DOCUMENTS_SCHEME_PREFIX @"documents://"
26 #define HTTP_SCHEME_PREFIX @"http://"
27 #define HTTPS_SCHEME_PREFIX @"https://"
28
29 @implementation CDVSound
30
31 @synthesize soundCache, avSession;
32
33 // Maps a url for a resource path
34 // "Naked" resource paths are assumed to be from the www folder as its base
35 - (NSURL*) urlForResource:(NSString*)resourcePath
36 {
37 NSURL* resourceURL = nil;
38 NSString* filePath = nil;
39
40 // first try to find HTTP:// or Documents:// resources
41
42 if ([resourcePath hasPrefix:HTTP_SCHEME_PREFIX] || [resourcePath hasPrefix:HTTPS_SCHEME_PREFIX]){
43 // if it is a http url, use it
44 NSLog(@"Will use resource '%@' from the Internet.", resourcePath);
45 resourceURL = [NSURL URLWithString:resourcePath];
46 } else if ([resourcePath hasPrefix:DOCUMENTS_SCHEME_PREFIX]) {
47 filePath = [resourcePath stringByReplacingOccurrencesOfString:DOCUMENTS_SCHEME_PREFIX withString:[NSString stringWithFormat:@"%@/",[CDVViewController applicationDocumentsDirectory]]];
48 NSLog(@"Will use resource '%@' from the documents folder with path = %@", resourcePath, filePath);
49 } else {
50 // attempt to find file path in www directory
51 filePath = [self.commandDelegate pathForResource:resourcePath];
52 if (filePath != nil) {
53 NSLog(@"Found resource '%@' in the web folder.", filePath);
54 }else {
55 filePath = resourcePath;
56 NSLog(@"Will attempt to use file resource '%@'", filePath);
57
58 }
59
60 }
61 // check that file exists for all but HTTP_SHEME_PREFIX
62 if(filePath != nil) {
63 // try to access file
64 NSFileManager* fMgr = [[NSFileManager alloc] init];
65 if (![fMgr fileExistsAtPath:filePath]) {
66 resourceURL = nil;
67 NSLog(@"Unknown resource '%@'", resourcePath);
68 } else {
69 // it's a valid file url, use it
70 resourceURL = [NSURL fileURLWithPath:filePath];
71 }
72 }
73 return resourceURL;
74 }
75
76 // Creates or gets the cached audio file resource object
77 - (CDVAudioFile*) audioFileForResource:(NSString*) resourcePath withId: (NSString*)mediaId
78 {
79 BOOL bError = NO;
80 CDVMediaError errcode = MEDIA_ERR_NONE_SUPPORTED;
81 NSString* errMsg = @"";
82 NSString* jsString = nil;
83 CDVAudioFile* audioFile = nil;
84 NSURL* resourceURL = nil;
85
86 if ([self soundCache] == nil) {
87 [self setSoundCache: [NSMutableDictionary dictionaryWithCapacity:1]];
88 }else {
89 audioFile = [[self soundCache] objectForKey: mediaId];
90 }
91 if (audioFile == nil){
92 // validate resourcePath and create
93
94 if (resourcePath == nil || ![resourcePath isKindOfClass:[NSString class]] || [resourcePath isEqualToString:@""]){
95 bError = YES;
96 errcode = MEDIA_ERR_ABORTED;
97 errMsg = @"invalid media src argument";
98 } else {
99 resourceURL = [self urlForResource:resourcePath];
100 }
101
102 if (resourceURL == nil) {
103 bError = YES;
104 errcode = MEDIA_ERR_ABORTED;
105 errMsg = [NSString stringWithFormat: @"Cannot use audio file from resource '%@'", resourcePath];
106 }
107 if (bError) {
108 //jsString = [NSString stringWithFormat: @"%@(\"%@\",%d,%d);", @"cordova.require('cordova/plugin/Media').onStatus", mediaId, MEDIA_ERROR, errcode];
109 jsString = [NSString stringWithFormat: @"%@(\"%@\",%d,%@);", @"cordova.require('cordova/plugin/Media').onStatus", mediaId, MEDIA_ERROR,[self createMediaErrorWithCode: errcode message: errMsg]];
110 [super writeJavascript:jsString];
111 } else {
112 audioFile = [[CDVAudioFile alloc] init];
113 audioFile.resourcePath = resourcePath;
114 audioFile.resourceURL = resourceURL;
115 [[self soundCache] setObject:audioFile forKey: mediaId];
116 }
117 }
118 return audioFile;
119 }
120 // returns whether or not audioSession is available - creates it if necessary
121 - (BOOL) hasAudioSession
122 {
123 BOOL bSession = YES;
124 if (!self.avSession) {
125 NSError* error = nil;
126
127 self.avSession = [AVAudioSession sharedInstance];
128 if (error) {
129 // is not fatal if can't get AVAudioSession , just log the error
130 NSLog(@"error creating audio session: %@", [[error userInfo] description]);
131 self.avSession = nil;
132 bSession = NO;
133 }
134 }
135 return bSession;
136 }
137 // helper function to create a error object string
138 - (NSString*) createMediaErrorWithCode: (CDVMediaError) code message: (NSString*) message
139 {
140 NSMutableDictionary* errorDict = [NSMutableDictionary dictionaryWithCapacity:2];
141 [errorDict setObject: [NSNumber numberWithUnsignedInt: code] forKey:@"code"];
142 [errorDict setObject: message ? message : @"" forKey: @"message"];
143 return [errorDict cdvjk_JSONString];
144
145 }
146 // DEPRECATED
147 - (void) play:(CDVInvokedUrlCommand*)command
148 {
149 NSLog(@"play is DEPRECATED! Use startPlayingAudio.");
150 [self startPlayingAudio:command];
151 }
152
153 - (void) create:(CDVInvokedUrlCommand*)command
154 {
155 NSString* callbackId = command.callbackId;
156 NSString* mediaId = [command.arguments objectAtIndex:0];
157 NSString* resourcePath = [command.arguments objectAtIndex:1];
158
159 CDVPluginResult* result;
160 CDVAudioFile* audioFile = [self audioFileForResource:resourcePath withId: mediaId];
161
162 if (audioFile == nil) {
163 NSString* errorMessage = [NSString stringWithFormat:@"Failed to initialize Media file with path %@", resourcePath];
164 NSString* jsString = [NSString stringWithFormat: @"%@(\"%@\",%d,%@);", @"cordova.require('cordova/plugin/Media').onStatus", mediaId, MEDIA_ERROR,[self createMediaErrorWithCode: MEDIA_ERR_ABORTED message: errorMessage]];
165 [super writeJavascript:jsString];
166 } else {
167 result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK];
168 [super writeJavascript:[result toSuccessCallbackString:callbackId]];
169 }
170 }
171
172 - (void) setVolume:(CDVInvokedUrlCommand*)command
173 {
174 NSString* callbackId = command.callbackId;
175 #pragma unused(callbackId)
176 NSString* mediaId = [command.arguments objectAtIndex:0];
177 NSNumber* volume = [command.arguments objectAtIndex:1 withDefault:[NSNumber numberWithFloat:1.0]];
178
179 CDVAudioFile* audioFile;
180 if ([self soundCache] == nil) {
181 [self setSoundCache: [NSMutableDictionary dictionaryWithCapacity:1]];
182 } else {
183 audioFile = [[self soundCache] objectForKey: mediaId];
184 audioFile.volume = volume;
185 [[self soundCache] setObject:audioFile forKey:mediaId];
186 }
187
188 // don't care for any callbacks
189 }
190
191 - (void) startPlayingAudio:(CDVInvokedUrlCommand*)command
192 {
193 NSString* callbackId = command.callbackId;
194 #pragma unused(callbackId)
195 NSString* mediaId = [command.arguments objectAtIndex:0];
196 NSString* resourcePath = [command.arguments objectAtIndex:1];
197 NSDictionary* options = [command.arguments objectAtIndex:2 withDefault:nil];
198
199 BOOL bError = NO;
200 NSString* jsString = nil;
201
202 CDVAudioFile* audioFile = [self audioFileForResource:resourcePath withId: mediaId];
203
204 if (audioFile != nil) {
205 if (audioFile.player == nil){
206 bError = [self prepareToPlay:audioFile withId:mediaId];
207 }
208 if (!bError){
209 // audioFile.player != nil or player was sucessfully created
210 // get the audioSession and set the category to allow Playing when device is locked or ring/silent switch engaged
211 if ([self hasAudioSession]) {
212 NSError* __autoreleasing err = nil;
213 NSNumber* playAudioWhenScreenIsLocked = [options objectForKey:@"playAudioWhenScreenIsLocked"];
214 BOOL bPlayAudioWhenScreenIsLocked = YES;
215 if (playAudioWhenScreenIsLocked != nil) {
216 bPlayAudioWhenScreenIsLocked = [playAudioWhenScreenIsLocked boolValue];
217 }
218
219 NSString* sessionCategory = bPlayAudioWhenScreenIsLocked? AVAudioSessionCategoryPlayback : AVAudioSessionCategorySoloAmbient;
220 [self.avSession setCategory:sessionCategory error:&err];
221 if (![self.avSession setActive: YES error: &err]){
222 // other audio with higher priority that does not allow mixing could cause this to fail
223 NSLog(@"Unable to play audio: %@", [err localizedFailureReason]);
224 bError = YES;
225 }
226 }
227 if (!bError) {
228 NSLog(@"Playing audio sample '%@'", audioFile.resourcePath);
229 NSNumber* loopOption = [options objectForKey:@"numberOfLoops"];
230 NSInteger numberOfLoops = 0;
231 if (loopOption != nil) {
232 numberOfLoops = [loopOption intValue] - 1;
233 }
234 audioFile.player.numberOfLoops = numberOfLoops;
235 if(audioFile.player.isPlaying){
236 [audioFile.player stop];
237 audioFile.player.currentTime = 0;
238 }
239 if (audioFile.volume != nil) {
240 audioFile.player.volume = [audioFile.volume floatValue];
241 }
242
243 [audioFile.player play];
244 double position = round(audioFile.player.duration * 1000)/1000;
245 jsString = [NSString stringWithFormat: @"%@(\"%@\",%d,%.3f);\n%@(\"%@\",%d,%d);", @"cordova.require('cordova/plugin/Media').onStatus", mediaId, MEDIA_DURATION, position, @"cordova.require('cordova/plugin/Media').onStatus", mediaId, MEDIA_STATE, MEDIA_RUNNING];
246 [super writeJavascript:jsString];
247
248 }
249 }
250 if (bError) {
251 /* I don't see a problem playing previously recorded audio so removing this section - BG
252 NSError* error;
253 // try loading it one more time, in case the file was recorded previously
254 audioFile.player = [[ AVAudioPlayer alloc ] initWithContentsOfURL:audioFile.resourceURL error:&error];
255 if (error != nil) {
256 NSLog(@"Failed to initialize AVAudioPlayer: %@\n", error);
257 audioFile.player = nil;
258 } else {
259 NSLog(@"Playing audio sample '%@'", audioFile.resourcePath);
260 audioFile.player.numberOfLoops = numberOfLoops;
261 [audioFile.player play];
262 } */
263 // error creating the session or player
264 //jsString = [NSString stringWithFormat: @"%@(\"%@\",%d,%d);", @"cordova.require('cordova/plugin/Media').onStatus", mediaId, MEDIA_ERROR, MEDIA_ERR_NONE_SUPPORTED];
265 jsString = [NSString stringWithFormat: @"%@(\"%@\",%d,%@);", @"cordova.require('cordova/plugin/Media').onStatus", mediaId, MEDIA_ERROR, [self createMediaErrorWithCode: MEDIA_ERR_NONE_SUPPORTED message: nil]];
266 [super writeJavascript:jsString];
267 }
268 }
269 // else audioFile was nil - error already returned from audioFile for resource
270 return;
271 }
272 - (BOOL) prepareToPlay: (CDVAudioFile*) audioFile withId: (NSString*) mediaId
273 {
274 BOOL bError = NO;
275 NSError* __autoreleasing playerError = nil;
276
277 // create the player
278 NSURL* resourceURL = audioFile.resourceURL;
279 if ([resourceURL isFileURL]) {
280 audioFile.player = [[ CDVAudioPlayer alloc ] initWithContentsOfURL:resourceURL error:&playerError];
281 } else {
282 NSURLRequest *request = [NSURLRequest requestWithURL:resourceURL];
283 NSURLResponse * __autoreleasing response = nil;
284 NSData* data = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&playerError];
285 if (playerError) {
286 NSLog(@"Unable to download audio from: %@", [resourceURL absoluteString]);
287 } else {
288
289 // bug in AVAudioPlayer when playing downloaded data in NSData - we have to download the file and play from disk
290 CFUUIDRef uuidRef = CFUUIDCreate(kCFAllocatorDefault);
291 CFStringRef uuidString = CFUUIDCreateString(kCFAllocatorDefault, uuidRef);
292 NSString* filePath = [NSString stringWithFormat:@"%@/%@.mp3", [NSTemporaryDirectory() stringByStandardizingPath], uuidString];
293 CFRelease(uuidString);
294 CFRelease(uuidRef);
295
296 [data writeToFile:filePath atomically:YES];
297 NSURL* fileURL = [NSURL fileURLWithPath:filePath];
298 audioFile.player = [[ CDVAudioPlayer alloc ] initWithContentsOfURL:fileURL error:&playerError];
299 }
300 }
301
302 if (playerError != nil) {
303 NSLog(@"Failed to initialize AVAudioPlayer: %@\n", [playerError localizedDescription]);
304 audioFile.player = nil;
305 if (self.avSession) {
306 [self.avSession setActive:NO error:nil];
307 }
308 bError = YES;
309 } else {
310 audioFile.player.mediaId = mediaId;
311 audioFile.player.delegate = self;
312 bError = ![audioFile.player prepareToPlay];
313 }
314 return bError;
315 }
316
317 // if no errors sets status to starting and calls successCallback with no parameters
318 // Calls the success call back immediately as there is no mechanism to determine that the file is loaded
319 // other than the return from prepareToPlay. Thus, IMHO not really worth calling
320
321 - (void) prepare:(CDVInvokedUrlCommand*)command
322 {
323 NSLog(@"prepare is DEPRECATED! Recoding will be prepared when startPlayingAudio is called");
324
325 NSString* callbackId = command.callbackId;
326
327 NSString* mediaId = [command.arguments objectAtIndex:0];
328 BOOL bError = NO;
329 CDVMediaStates state = MEDIA_STARTING;
330 NSString* jsString = nil;
331
332 CDVAudioFile* audioFile = [[self soundCache] objectForKey: mediaId];
333 if (audioFile == nil) {
334 // did not already exist, try to create
335 audioFile = [self audioFileForResource:[command.arguments objectAtIndex:1] withId: mediaId];
336 if (audioFile == nil) {
337 // create failed
338 bError = YES;
339 } else {
340 bError = [self prepareToPlay:audioFile withId:mediaId];
341 }
342 } else {
343 // audioFile already existed in the cache no need to prepare it again, indicate state
344 if (audioFile.player && [audioFile.player isPlaying]) {
345 state = MEDIA_RUNNING;
346 }
347 }
348
349 if (!bError) {
350
351 // NSLog(@"Prepared audio sample '%@' for playback.", audioFile.resourcePath);
352 CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK];
353 jsString = [NSString stringWithFormat: @"%@(\"%@\",%d,%d);\n%@", @"cordova.require('cordova/plugin/Media').onStatus", mediaId, MEDIA_STATE, state, [result toSuccessCallbackString:callbackId]];
354
355 } else {
356 jsString = [NSString stringWithFormat: @"%@(\"%@\",%d,%@);", @"cordova.require('cordova/plugin/Media').onStatus", mediaId, MEDIA_ERROR, [self createMediaErrorWithCode: MEDIA_ERR_NONE_SUPPORTED message: nil]];
357 }
358 if (jsString) {
359 [super writeJavascript:jsString];
360 }
361
362 }
363
364 // DEPRECATED
365 - (void) stop:(CDVInvokedUrlCommand*)command
366 {
367 NSLog(@"stop is DEPRECATED! Use stopPlayingAudio.");
368 [self stopPlayingAudio:command];
369 }
370
371 - (void) stopPlayingAudio:(CDVInvokedUrlCommand*)command
372 {
373 NSString* mediaId = [command.arguments objectAtIndex:0];
374 CDVAudioFile* audioFile = [[self soundCache] objectForKey: mediaId];
375 NSString* jsString = nil;
376
377 if (audioFile != nil && audioFile.player!= nil) {
378 NSLog(@"Stopped playing audio sample '%@'", audioFile.resourcePath);
379 [audioFile.player stop];
380 audioFile.player.currentTime = 0;
381 jsString = [NSString stringWithFormat: @"%@(\"%@\",%d,%d);", @"cordova.require('cordova/plugin/Media').onStatus", mediaId, MEDIA_STATE, MEDIA_STOPPED];
382 } // ignore if no media playing
383 if (jsString){
384 [super writeJavascript: jsString];
385 }
386 }
387 // DEPRECATED
388 - (void) pause:(CDVInvokedUrlCommand*)command
389 {
390 NSLog(@"pause is DEPRECATED! Use pausePlayingAudio.");
391 [self pausePlayingAudio:command];
392 }
393
394 - (void) pausePlayingAudio:(CDVInvokedUrlCommand*)command
395 {
396 NSString* mediaId = [command.arguments objectAtIndex:0];
397 NSString* jsString = nil;
398 CDVAudioFile* audioFile = [[self soundCache] objectForKey: mediaId];
399
400 if (audioFile != nil && audioFile.player != nil) {
401 NSLog(@"Paused playing audio sample '%@'", audioFile.resourcePath);
402 [audioFile.player pause];
403 jsString = [NSString stringWithFormat: @"%@(\"%@\",%d,%d);", @"cordova.require('cordova/plugin/Media').onStatus", mediaId, MEDIA_STATE, MEDIA_PAUSED];
404 }
405 // ignore if no media playing
406
407
408 if (jsString){
409 [super writeJavascript: jsString];
410 }
411
412
413 }
414 - (void) seekToAudio:(CDVInvokedUrlCommand*)command
415 {
416 //args:
417 // 0 = Media id
418 // 1 = path to resource
419 // 2 = seek to location in milliseconds
420
421 NSString* mediaId = [command.arguments objectAtIndex:0];
422
423 CDVAudioFile* audioFile = [[self soundCache] objectForKey: mediaId];
424 double position = [[command.arguments objectAtIndex:1] doubleValue];
425
426 if (audioFile != nil && audioFile.player != nil && position){
427 double posInSeconds = position/1000;
428 audioFile.player.currentTime = posInSeconds;
429 NSString* jsString = [NSString stringWithFormat: @"%@(\"%@\",%d,%f);", @"cordova.require('cordova/plugin/Media').onStatus", mediaId, MEDIA_POSITION, posInSeconds];
430
431 [super writeJavascript: jsString];
432
433 }
434
435 return;
436
437 }
438
439 - (void) release:(CDVInvokedUrlCommand*)command
440 {
441 NSString* mediaId = [command.arguments objectAtIndex:0];
442
443 if (mediaId != nil){
444 CDVAudioFile* audioFile = [[self soundCache] objectForKey: mediaId];
445 if (audioFile != nil){
446 if (audioFile.player && [audioFile.player isPlaying]){
447 [audioFile.player stop];
448 }
449 if(audioFile.recorder && [audioFile.recorder isRecording]){
450 [audioFile.recorder stop];
451 }
452 if (self.avSession) {
453 [self.avSession setActive:NO error: nil];
454 self.avSession = nil;
455 }
456 [[self soundCache] removeObjectForKey: mediaId];
457 NSLog(@"Media with id %@ released", mediaId);
458 }
459 }
460 }
461 // DEPRECATED
462 - (void) getCurrentPosition:(CDVInvokedUrlCommand*)command
463 {
464 NSLog(@"getCurrentPosition is DEPRECATED! Use getCurrentPositionAudio.");
465 [self getCurrentPositionAudio:command];
466 }
467
468 - (void) getCurrentPositionAudio:(CDVInvokedUrlCommand*)command
469 {
470 NSString* callbackId = command.callbackId;
471 NSString* mediaId = [command.arguments objectAtIndex:0];
472 #pragma unused(mediaId)
473 CDVAudioFile* audioFile = [[self soundCache] objectForKey: mediaId];
474 double position = -1;
475
476 if (audioFile != nil && audioFile.player != nil && [audioFile.player isPlaying]){
477 position = round(audioFile.player.currentTime *1000)/1000;
478 }
479 CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDouble: position];
480 NSString* jsString = [NSString stringWithFormat: @"%@(\"%@\",%d,%.3f);\n%@", @"cordova.require('cordova/plugin/Media').onStatus", mediaId, MEDIA_POSITION, position, [result toSuccessCallbackString:callbackId]];
481 [super writeJavascript:jsString];
482
483 return;
484
485 }
486 // DEPRECATED
487 - (void) startAudioRecord:(CDVInvokedUrlCommand*)command
488 {
489 NSLog(@"startAudioRecord is DEPRECATED! Use startRecordingAudio.");
490 [self startRecordingAudio:command];
491 }
492
493 - (void) startRecordingAudio:(CDVInvokedUrlCommand*)command
494 {
495 NSString* callbackId = command.callbackId;
496 #pragma unused(callbackId)
497
498 NSString* mediaId = [command.arguments objectAtIndex:0];
499 CDVAudioFile* audioFile = [self audioFileForResource:[command.arguments objectAtIndex:1] withId: mediaId];
500 NSString* jsString = nil;
501 NSString* errorMsg = @"";
502
503 if (audioFile != nil) {
504
505 NSError* __autoreleasing error = nil;
506
507 if (audioFile.recorder != nil) {
508 [audioFile.recorder stop];
509 audioFile.recorder = nil;
510 }
511 // get the audioSession and set the category to allow recording when device is locked or ring/silent switch engaged
512 if ([self hasAudioSession]) {
513 [self.avSession setCategory:AVAudioSessionCategoryRecord error:nil];
514 if (![self.avSession setActive: YES error: &error]){
515 // other audio with higher priority that does not allow mixing could cause this to fail
516 errorMsg = [NSString stringWithFormat: @"Unable to record audio: %@", [error localizedFailureReason]];
517 //jsString = [NSString stringWithFormat: @"%@(\"%@\",%d,%d);", @"cordova.require('cordova/plugin/Media').onStatus", mediaId, MEDIA_ERROR, MEDIA_ERR_ABORTED];
518 jsString = [NSString stringWithFormat: @"%@(\"%@\",%d,%@);", @"cordova.require('cordova/plugin/Media').onStatus", mediaId, MEDIA_ERROR, [self createMediaErrorWithCode: MEDIA_ERR_ABORTED message: errorMsg] ];
519 [super writeJavascript:jsString];
520 return;
521 }
522 }
523
524 // create a new recorder for each start record
525 audioFile.recorder = [[CDVAudioRecorder alloc] initWithURL:audioFile.resourceURL settings:nil error:&error];
526
527 if (error != nil) {
528 errorMsg = [NSString stringWithFormat: @"Failed to initialize AVAudioRecorder: %@\n", [error localizedFailureReason]];
529 audioFile.recorder = nil;
530 if (self.avSession) {
531 [self.avSession setActive:NO error:nil];
532 }
533 //jsString = [NSString stringWithFormat: @"%@(\"%@\",%d,%d);", @"cordova.require('cordova/plugin/Media').onStatus", mediaId, MEDIA_ERROR, MEDIA_ERR_ABORTED];
534 jsString = [NSString stringWithFormat: @"%@(\"%@\",%d,%@);", @"cordova.require('cordova/plugin/Media').onStatus", mediaId, MEDIA_ERROR, [self createMediaErrorWithCode: MEDIA_ERR_ABORTED message: errorMsg]];
535
536 } else {
537 audioFile.recorder.delegate = self;
538 audioFile.recorder.mediaId = mediaId;
539 [audioFile.recorder record];
540 NSLog(@"Started recording audio sample '%@'", audioFile.resourcePath);
541 jsString = [NSString stringWithFormat: @"%@(\"%@\",%d,%d);", @"cordova.require('cordova/plugin/Media').onStatus", mediaId, MEDIA_STATE, MEDIA_RUNNING];
542 }
543 } else {
544 // file does not exist
545 NSLog(@"Could not start recording audio, file '%@' does not exist.", audioFile.resourcePath);
546 jsString = [NSString stringWithFormat: @"%@(\"%@\",%d,%@);", @"cordova.require('cordova/plugin/Media').onStatus", mediaId, MEDIA_ERROR, [self createMediaErrorWithCode: MEDIA_ERR_ABORTED message: @"File to record to does not exist"]];
547 }
548 if (jsString) {
549 [super writeJavascript:jsString];
550 }
551 return;
552 }
553 // DEPRECATED
554 - (void) stopAudioRecord:(CDVInvokedUrlCommand*)command
555 {
556 NSLog(@"stopAudioRecord is DEPRECATED! Use stopRecordingAudio.");
557 [self stopRecordingAudio:command];
558 }
559
560 - (void) stopRecordingAudio:(CDVInvokedUrlCommand*)command
561 {
562 NSString* mediaId = [command.arguments objectAtIndex:0];
563
564 CDVAudioFile* audioFile = [[self soundCache] objectForKey: mediaId];
565 NSString* jsString = nil;
566
567 if (audioFile != nil && audioFile.recorder != nil) {
568 NSLog(@"Stopped recording audio sample '%@'", audioFile.resourcePath);
569 [audioFile.recorder stop];
570 // no callback - that will happen in audioRecorderDidFinishRecording
571 }
572 // ignore if no media recording
573 if (jsString) {
574 [super writeJavascript:jsString];
575 }}
576
577 - (void)audioRecorderDidFinishRecording:(AVAudioRecorder*)recorder successfully:(BOOL)flag
578 {
579
580 CDVAudioRecorder* aRecorder = (CDVAudioRecorder*)recorder;
581 NSString* mediaId = aRecorder.mediaId;
582 CDVAudioFile* audioFile = [[self soundCache] objectForKey: mediaId];
583 NSString* jsString = nil;
584
585
586 if (audioFile != nil) {
587 NSLog(@"Finished recording audio sample '%@'", audioFile.resourcePath);
588 }
589 if (flag){
590 jsString = [NSString stringWithFormat: @"%@(\"%@\",%d,%d);", @"cordova.require('cordova/plugin/Media').onStatus", mediaId, MEDIA_STATE, MEDIA_STOPPED];
591 } else {
592 //jsString = [NSString stringWithFormat: @"%@(\"%@\",%d,%d);", @"cordova.require('cordova/plugin/Media').onStatus", mediaId, MEDIA_ERROR, MEDIA_ERR_DECODE];
593 jsString = [NSString stringWithFormat: @"%@(\"%@\",%d,%@);", @"cordova.require('cordova/plugin/Media').onStatus", mediaId, MEDIA_ERROR, [self createMediaErrorWithCode: MEDIA_ERR_DECODE message:nil]];
594 }
595 if (self.avSession) {
596 [self.avSession setActive:NO error:nil];
597 }
598 [super writeJavascript:jsString];
599
600 }
601
602 - (void)audioPlayerDidFinishPlaying:(AVAudioPlayer*)player successfully:(BOOL)flag
603 {
604 CDVAudioPlayer* aPlayer = (CDVAudioPlayer*)player;
605 NSString* mediaId = aPlayer.mediaId;
606 CDVAudioFile* audioFile = [[self soundCache] objectForKey: mediaId];
607 NSString* jsString = nil;
608
609 if (audioFile != nil) {
610 NSLog(@"Finished playing audio sample '%@'", audioFile.resourcePath);
611 }
612 if (flag){
613 jsString = [NSString stringWithFormat: @"%@(\"%@\",%d,%d);", @"cordova.require('cordova/plugin/Media').onStatus", mediaId, MEDIA_STATE, MEDIA_STOPPED];
614
615 } else {
616 //jsString = [NSString stringWithFormat: @"%@(\"%@\",%d,%d);", @"cordova.require('cordova/plugin/Media').onStatus", mediaId, MEDIA_ERROR, MEDIA_ERR_DECODE];
617 jsString = [NSString stringWithFormat: @"%@(\"%@\",%d,%@);", @"cordova.require('cordova/plugin/Media').onStatus", mediaId, MEDIA_ERROR, [self createMediaErrorWithCode: MEDIA_ERR_DECODE message:nil]];
618
619 }
620 if (self.avSession) {
621 [self.avSession setActive:NO error:nil];
622 }
623 [super writeJavascript: jsString];
624
625 }
626
627 - (void) onMemoryWarning
628 {
629 [[self soundCache] removeAllObjects];
630 [self setSoundCache: nil];
631 [self setAvSession: nil];
632
633 [super onMemoryWarning];
634 }
635 - (void) dealloc
636 {
637 [[self soundCache] removeAllObjects];
638
639 }
640 @end
641
642 @implementation CDVAudioFile
643
644 @synthesize resourcePath;
645 @synthesize resourceURL;
646 @synthesize player, volume;
647 @synthesize recorder;
648
649
650 @end
651 @implementation CDVAudioPlayer
652 @synthesize mediaId;
653
654 @end
655
656 @implementation CDVAudioRecorder
657 @synthesize mediaId;
658
659 @end
660
Something went wrong with that request. Please try again.