aboutsummaryrefslogtreecommitdiffstats
path: root/iPhone/CordovaLib/Classes/CDVSound.m
diff options
context:
space:
mode:
Diffstat (limited to 'iPhone/CordovaLib/Classes/CDVSound.m')
-rwxr-xr-xiPhone/CordovaLib/Classes/CDVSound.m156
1 files changed, 129 insertions, 27 deletions
diff --git a/iPhone/CordovaLib/Classes/CDVSound.m b/iPhone/CordovaLib/Classes/CDVSound.m
index f7a3adf..99515d7 100755
--- a/iPhone/CordovaLib/Classes/CDVSound.m
+++ b/iPhone/CordovaLib/Classes/CDVSound.m
@@ -18,19 +18,18 @@
*/
#import "CDVSound.h"
-#import "CDVViewController.h"
#import "NSArray+Comparisons.h"
+#import "CDVJSON.h"
#define DOCUMENTS_SCHEME_PREFIX @"documents://"
#define HTTP_SCHEME_PREFIX @"http://"
#define HTTPS_SCHEME_PREFIX @"https://"
+#define RECORDING_WAV @"wav"
@implementation CDVSound
@synthesize soundCache, avSession;
-// Maps a url for a resource path
-// "Naked" resource paths are assumed to be from the www folder as its base
- (NSURL*)urlForResource:(NSString*)resourcePath
{
NSURL* resourceURL = nil;
@@ -43,7 +42,8 @@
NSLog(@"Will use resource '%@' from the Internet.", resourcePath);
resourceURL = [NSURL URLWithString:resourcePath];
} else if ([resourcePath hasPrefix:DOCUMENTS_SCHEME_PREFIX]) {
- filePath = [resourcePath stringByReplacingOccurrencesOfString:DOCUMENTS_SCHEME_PREFIX withString:[NSString stringWithFormat:@"%@/", [CDVViewController applicationDocumentsDirectory]]];
+ NSString* docsPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0];
+ filePath = [resourcePath stringByReplacingOccurrencesOfString:DOCUMENTS_SCHEME_PREFIX withString:[NSString stringWithFormat:@"%@/", docsPath]];
NSLog(@"Will use resource '%@' from the documents folder with path = %@", resourcePath, filePath);
} else {
// attempt to find file path in www directory
@@ -70,9 +70,101 @@
return resourceURL;
}
-// Creates or gets the cached audio file resource object
+// Maps a url for a resource path for recording
+- (NSURL*)urlForRecording:(NSString*)resourcePath
+{
+ NSURL* resourceURL = nil;
+ NSString* filePath = nil;
+ NSString* docsPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0];
+
+ // first check for correct extension
+ if ([[resourcePath pathExtension] caseInsensitiveCompare:RECORDING_WAV] != NSOrderedSame) {
+ resourceURL = nil;
+ NSLog(@"Resource for recording must have %@ extension", RECORDING_WAV);
+ } else if ([resourcePath hasPrefix:DOCUMENTS_SCHEME_PREFIX]) {
+ // try to find Documents:// resources
+ filePath = [resourcePath stringByReplacingOccurrencesOfString:DOCUMENTS_SCHEME_PREFIX withString:[NSString stringWithFormat:@"%@/", docsPath]];
+ NSLog(@"Will use resource '%@' from the documents folder with path = %@", resourcePath, filePath);
+ } else {
+ // if resourcePath is not from FileSystem put in tmp dir, else attempt to use provided resource path
+ NSString* tmpPath = [NSTemporaryDirectory ()stringByStandardizingPath];
+ BOOL isTmp = [resourcePath rangeOfString:tmpPath].location != NSNotFound;
+ BOOL isDoc = [resourcePath rangeOfString:docsPath].location != NSNotFound;
+ if (!isTmp && !isDoc) {
+ // put in temp dir
+ filePath = [NSString stringWithFormat:@"%@/%@", tmpPath, resourcePath];
+ } else {
+ filePath = resourcePath;
+ }
+ }
+
+ if (filePath != nil) {
+ // create resourceURL
+ resourceURL = [NSURL fileURLWithPath:filePath];
+ }
+ return resourceURL;
+}
+
+// Maps a url for a resource path for playing
+// "Naked" resource paths are assumed to be from the www folder as its base
+- (NSURL*)urlForPlaying:(NSString*)resourcePath
+{
+ NSURL* resourceURL = nil;
+ NSString* filePath = nil;
+
+ // first try to find HTTP:// or Documents:// resources
+
+ if ([resourcePath hasPrefix:HTTP_SCHEME_PREFIX] || [resourcePath hasPrefix:HTTPS_SCHEME_PREFIX]) {
+ // if it is a http url, use it
+ NSLog(@"Will use resource '%@' from the Internet.", resourcePath);
+ resourceURL = [NSURL URLWithString:resourcePath];
+ } else if ([resourcePath hasPrefix:DOCUMENTS_SCHEME_PREFIX]) {
+ NSString* docsPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0];
+ filePath = [resourcePath stringByReplacingOccurrencesOfString:DOCUMENTS_SCHEME_PREFIX withString:[NSString stringWithFormat:@"%@/", docsPath]];
+ NSLog(@"Will use resource '%@' from the documents folder with path = %@", resourcePath, filePath);
+ } else {
+ // attempt to find file path in www directory or LocalFileSystem.TEMPORARY directory
+ filePath = [self.commandDelegate pathForResource:resourcePath];
+ if (filePath == nil) {
+ // see if this exists in the documents/temp directory from a previous recording
+ NSString* testPath = [NSString stringWithFormat:@"%@/%@", [NSTemporaryDirectory ()stringByStandardizingPath], resourcePath];
+ if ([[NSFileManager defaultManager] fileExistsAtPath:testPath]) {
+ // inefficient as existence will be checked again below but only way to determine if file exists from previous recording
+ filePath = testPath;
+ NSLog(@"Will attempt to use file resource from LocalFileSystem.TEMPORARY directory");
+ } else {
+ // attempt to use path provided
+ filePath = resourcePath;
+ NSLog(@"Will attempt to use file resource '%@'", filePath);
+ }
+ } else {
+ NSLog(@"Found resource '%@' in the web folder.", filePath);
+ }
+ }
+ // check that file exists for all but HTTP_SHEME_PREFIX
+ if (filePath != nil) {
+ // create resourceURL
+ resourceURL = [NSURL fileURLWithPath:filePath];
+ // try to access file
+ NSFileManager* fMgr = [NSFileManager defaultManager];
+ if (![fMgr fileExistsAtPath:filePath]) {
+ resourceURL = nil;
+ NSLog(@"Unknown resource '%@'", resourcePath);
+ }
+ }
+
+ return resourceURL;
+}
+
- (CDVAudioFile*)audioFileForResource:(NSString*)resourcePath withId:(NSString*)mediaId
{
+ // will maintain backwards compatibility with original implementation
+ return [self audioFileForResource:resourcePath withId:mediaId doValidation:YES forRecording:NO];
+}
+
+// Creates or gets the cached audio file resource object
+- (CDVAudioFile*)audioFileForResource:(NSString*)resourcePath withId:(NSString*)mediaId doValidation:(BOOL)bValidate forRecording:(BOOL)bRecord
+{
BOOL bError = NO;
CDVMediaError errcode = MEDIA_ERR_NONE_SUPPORTED;
NSString* errMsg = @"";
@@ -87,31 +179,37 @@
}
if (audioFile == nil) {
// validate resourcePath and create
-
if ((resourcePath == nil) || ![resourcePath isKindOfClass:[NSString class]] || [resourcePath isEqualToString:@""]) {
bError = YES;
errcode = MEDIA_ERR_ABORTED;
errMsg = @"invalid media src argument";
} else {
- resourceURL = [self urlForResource:resourcePath];
+ audioFile = [[CDVAudioFile alloc] init];
+ audioFile.resourcePath = resourcePath;
+ audioFile.resourceURL = nil; // validate resourceURL when actually play or record
+ [[self soundCache] setObject:audioFile forKey:mediaId];
+ }
+ }
+ if (bValidate && (audioFile.resourceURL == nil)) {
+ if (bRecord) {
+ resourceURL = [self urlForRecording:resourcePath];
+ } else {
+ resourceURL = [self urlForPlaying:resourcePath];
}
-
if (resourceURL == nil) {
bError = YES;
errcode = MEDIA_ERR_ABORTED;
errMsg = [NSString stringWithFormat:@"Cannot use audio file from resource '%@'", resourcePath];
- }
- if (bError) {
- // jsString = [NSString stringWithFormat: @"%@(\"%@\",%d,%d);", @"cordova.require('cordova/plugin/Media').onStatus", mediaId, MEDIA_ERROR, errcode];
- jsString = [NSString stringWithFormat:@"%@(\"%@\",%d,%@);", @"cordova.require('cordova/plugin/Media').onStatus", mediaId, MEDIA_ERROR, [self createMediaErrorWithCode:errcode message:errMsg]];
- [self.commandDelegate evalJs:jsString];
} else {
- audioFile = [[CDVAudioFile alloc] init];
- audioFile.resourcePath = resourcePath;
audioFile.resourceURL = resourceURL;
- [[self soundCache] setObject:audioFile forKey:mediaId];
}
}
+
+ if (bError) {
+ jsString = [NSString stringWithFormat:@"%@(\"%@\",%d,%@);", @"cordova.require('cordova/plugin/Media').onStatus", mediaId, MEDIA_ERROR, [self createMediaErrorWithCode:errcode message:errMsg]];
+ [self.commandDelegate evalJs:jsString];
+ }
+
return audioFile;
}
@@ -141,7 +239,7 @@
[errorDict setObject:[NSNumber numberWithUnsignedInt:code] forKey:@"code"];
[errorDict setObject:message ? message:@"" forKey:@"message"];
- return [errorDict cdvjk_JSONString];
+ return [errorDict JSONString];
}
- (void)create:(CDVInvokedUrlCommand*)command
@@ -149,7 +247,7 @@
NSString* mediaId = [command.arguments objectAtIndex:0];
NSString* resourcePath = [command.arguments objectAtIndex:1];
- CDVAudioFile* audioFile = [self audioFileForResource:resourcePath withId:mediaId];
+ CDVAudioFile* audioFile = [self audioFileForResource:resourcePath withId:mediaId doValidation:NO forRecording:NO];
if (audioFile == nil) {
NSString* errorMessage = [NSString stringWithFormat:@"Failed to initialize Media file with path %@", resourcePath];
@@ -193,9 +291,8 @@
BOOL bError = NO;
NSString* jsString = nil;
- CDVAudioFile* audioFile = [self audioFileForResource:resourcePath withId:mediaId];
-
- if (audioFile != nil) {
+ CDVAudioFile* audioFile = [self audioFileForResource:resourcePath withId:mediaId doValidation:YES forRecording:NO];
+ if ((audioFile != nil) && (audioFile.resourceURL != nil)) {
if (audioFile.player == nil) {
bError = [self prepareToPlay:audioFile withId:mediaId];
}
@@ -274,7 +371,12 @@
if ([resourceURL isFileURL]) {
audioFile.player = [[CDVAudioPlayer alloc] initWithContentsOfURL:resourceURL error:&playerError];
} else {
- NSURLRequest* request = [NSURLRequest requestWithURL:resourceURL];
+ NSMutableURLRequest* request = [NSMutableURLRequest requestWithURL:resourceURL];
+ NSString* userAgent = [self.commandDelegate userAgent];
+ if (userAgent) {
+ [request setValue:userAgent forHTTPHeaderField:@"User-Agent"];
+ }
+
NSURLResponse* __autoreleasing response = nil;
NSData* data = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&playerError];
if (playerError) {
@@ -411,11 +513,11 @@
#pragma unused(callbackId)
NSString* mediaId = [command.arguments objectAtIndex:0];
- CDVAudioFile* audioFile = [self audioFileForResource:[command.arguments objectAtIndex:1] withId:mediaId];
+ CDVAudioFile* audioFile = [self audioFileForResource:[command.arguments objectAtIndex:1] withId:mediaId doValidation:YES forRecording:YES];
NSString* jsString = nil;
NSString* errorMsg = @"";
- if (audioFile != nil) {
+ if ((audioFile != nil) && (audioFile.resourceURL != nil)) {
NSError* __autoreleasing error = nil;
if (audioFile.recorder != nil) {
@@ -462,9 +564,9 @@
jsString = [NSString stringWithFormat:@"%@(\"%@\",%d,%@);", @"cordova.require('cordova/plugin/Media').onStatus", mediaId, MEDIA_ERROR, [self createMediaErrorWithCode:MEDIA_ERR_ABORTED message:errorMsg]];
}
} else {
- // file does not exist
- NSLog(@"Could not start recording audio, file '%@' does not exist.", audioFile.resourcePath);
- 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"]];
+ // file did not validate
+ NSString* errorMsg = [NSString stringWithFormat:@"Could not record audio at '%@'", audioFile.resourcePath];
+ jsString = [NSString stringWithFormat:@"%@(\"%@\",%d,%@);", @"cordova.require('cordova/plugin/Media').onStatus", mediaId, MEDIA_ERROR, [self createMediaErrorWithCode:MEDIA_ERR_ABORTED message:errorMsg]];
}
if (jsString) {
[self.commandDelegate evalJs:jsString];