Fix formatting and restart bug

In the current system you can’t have the same sound playing more than once at the same time - this is how it was implemented on Android, so we used the same restriction on iOS.

However in the previous version if you interrupted the sound to play it again, it continued from where it was instead of starting over. So it didn’t appear to do anything. Added resetting the current time to 0.0 on play to restart sounds.
This commit is contained in:
chrisgarrity 2017-03-14 12:11:53 -04:00
parent e9d0d0d7be
commit f752ff5760
5 changed files with 122 additions and 172 deletions

View file

@ -233,59 +233,24 @@ NSMutableDictionary *sounds;
+ (NSString *)registerSound:(NSString*)dir :(NSString*)name { + (NSString *)registerSound:(NSString*)dir :(NSString*)name {
NSURL *url; NSURL *url;
if ([dir isEqual: @"Documents"]){ if ([dir isEqual:@"Documents"]){
url = [self getDocumentPath: name]; url = [self getDocumentPath: name];
} }
else { else {
url = [self getResourcePath: [NSString stringWithFormat: @"%@%@", dir, name]]; url = [self getResourcePath: [NSString stringWithFormat: @"%@%@", dir, name]];
} }
NSLog (@"registering %@", url);
NSError *error; NSError *error;
AVAudioPlayer *snd = [[AVAudioPlayer alloc] initWithContentsOfURL: url error:&error]; AVAudioPlayer *snd = [[AVAudioPlayer alloc] initWithContentsOfURL: url error:&error];
if (error == NULL) { if (error == nil) {
[sounds setObject:snd forKey:name]; [sounds setObject:snd forKey:name];
[snd prepareToPlay];
return [NSString stringWithFormat: @"%@,%f", name, snd.duration]; return [NSString stringWithFormat: @"%@,%f", name, snd.duration];
} }
else {
NSLog (@"%@", error);
}
return @"error"; return @"error";
} }
// +(NSString *)playSound:(NSString*)name {
// // get the sound either from Documents (user defined sounds)
// // or from the HTML5 bundle.
// NSURL *url = ([dir isEqual: @"Documents"]) ? [self getDocumentPath: name] : [self getResou\
// rcePath: [NSString stringWithFormat: @"%@%@", dir, name]];
//
// // audio type: respect the "Mute" if there are audio sounds
// // ignore the Mute if it is from recording / playback and Runtime.
// NSString *audiotype = ([dir isEqual: @"Documents"] || [name isEqual:@"pop.mp3"]) ? AVAudio\
// SessionCategoryPlayAndRecord : AVAudioSessionCategoryAmbient;
// [[AVAudioSession sharedInstance] setCategory:audiotype error:nil];
//
// NSError *error;
// AVAudioPlayer *snd = [[AVAudioPlayer alloc] initWithContentsOfURL: url error:&error];
//
// if (error == NULL) {
// snd.numberOfLoops = 0;
// [snd prepareToPlay];
// [snd play];
// NSString *id = [self setSoundTimeout: snd];
// NSString *result = [NSString stringWithFormat: @"%@,%f", id, [snd duration]];
// NSLog (@"%@", result);
// return result;
// }
// else {
// NSLog (@"%@", error);
// return @"error";
// }
// }
+ (NSString *)playSound :(NSString*)name { + (NSString *)playSound :(NSString*)name {
// TODO: make scratchJr pay attention to the mute // TODO: make scratchJr pay attention to the mute
// // audio type: respect the "Mute" if there are audio sounds // // audio type: respect the "Mute" if there are audio sounds
@ -294,12 +259,11 @@ NSMutableDictionary *sounds;
// SessionCategoryPlayAndRecord : AVAudioSessionCategoryAmbient; // SessionCategoryPlayAndRecord : AVAudioSessionCategoryAmbient;
// [[AVAudioSession sharedInstance] setCategory:audiotype error:nil]; // [[AVAudioSession sharedInstance] setCategory:audiotype error:nil];
AVAudioPlayer *snd = sounds[name]; AVAudioPlayer *snd = sounds[name];
NSLog (@"play %@", snd); if (snd == nil) {
if (snd == NULL) {
return [NSString stringWithFormat: @"%@ not found", name]; return [NSString stringWithFormat: @"%@ not found", name];
} }
else { else {
[snd prepareToPlay]; [snd setCurrentTime:0.0];
[snd play]; [snd play];
[NSTimer scheduledTimerWithTimeInterval: [snd duration] target: self selector: @selector(so\ [NSTimer scheduledTimerWithTimeInterval: [snd duration] target: self selector: @selector(so\
undEnded:) userInfo:@{@"soundName": name} repeats: NO]; undEnded:) userInfo:@{@"soundName": name} repeats: NO];
@ -308,28 +272,22 @@ undEnded:) userInfo:@{@"soundName": name} repeats: NO];
} }
+ (void)soundEnded:(NSTimer*)timer { + (void)soundEnded:(NSTimer*)timer {
NSString *soundName = [[timer userInfo] objectForKey:@"soundName"]; NSString *soundName = [[timer userInfo] objectForKey:@"soundName"];
NSLog(@"%@", soundName); if (sounds[soundName] == nil) return;
if (sounds [soundName] == NULL) return; NSString *callback = [NSString stringWithFormat:@"iOS.soundDone('%@');", soundName];
NSString *callback = [NSString stringWithFormat: @"iOS.soundDone('%@');",soundName];
UIWebView *webview = [ViewController webview]; UIWebView *webview = [ViewController webview];
[webview stringByEvaluatingJavaScriptFromString: callback]; [webview stringByEvaluatingJavaScriptFromString:callback];
} }
+ (NSString *)stopSound :(NSString*)name { + (NSString *)stopSound :(NSString*)name {
AVAudioPlayer *snd = sounds[name]; AVAudioPlayer *snd = sounds[name];
NSLog (@"stop %@", snd); if (snd == nil) {
if (snd == NULL) { return [NSString stringWithFormat:@"%@ not found", name];
return [NSString stringWithFormat: @"%@ not found", name];
}
else {
[snd stop];
return [NSString stringWithFormat: @"%@ stopped", name];
} }
[snd stop];
return [NSString stringWithFormat:@"%@ stopped", name];
} }
//////////////////////////// ////////////////////////////
// File system // File system
//////////////////////////// ////////////////////////////

View file

@ -6,15 +6,15 @@
@interface Database : NSObject @interface Database : NSObject
+ (NSString*)open:(NSString *)body; + (NSString *)open:(NSString *)body;
+ (NSString*)close:(NSString *)str; + (NSString *)close:(NSString *)str;
+ (void)initTables; + (void)initTables;
+ (void)runMigrations; + (void)runMigrations;
+ (NSArray*)findDataIn:(NSString *)stmtstr with:(NSArray *)values; + (NSArray *)findDataIn:(NSString *)stmtstr with:(NSArray *)values;
// Exports // Exports
+ (NSString*) stmt: (NSString*) json; + (NSString *)stmt:(NSString *)json;
+ (NSString*) query: (NSString*) json; + (NSString *)query:(NSString *)json;
@end @end
@interface CameraMask : UIView @interface CameraMask : UIView
@ -30,10 +30,10 @@
@property float scale; @property float scale;
@property NSString *usingCamera; @property NSString *usingCamera;
-(void) switchOrientation:(int)orientation; - (void)switchOrientation:(int)orientation;
-(id)initWithFrame:(CGRect)frame withScale:(float)scale; - (id)initWithFrame:(CGRect)frame withScale:(float)scale;
-(void) setCameraTo:(NSString*)dir; - (void)setCameraTo:(NSString *)dir;
-(NSString*)getImageBase64:(NSData*)imgdata; - (NSString *)getImageBase64:(NSData *)imgdata;
@end @end
@ -51,120 +51,131 @@
@property AVCaptureStillImageOutput *stillImageOutput; @property AVCaptureStillImageOutput *stillImageOutput;
- (BOOL) setupSession; - (BOOL)setupSession;
+ (NSString*) cameraHasPermission; + (NSString *)cameraHasPermission;
- (void) closeSession; - (void)closeSession;
- (NSUInteger) cameraCount; - (NSUInteger)cameraCount;
- (BOOL) setCamera:(NSString *)mode; - (BOOL)setCamera:(NSString *)mode;
- (AVCaptureConnection *)connectionWithMediaType:(NSString *)mediaType fromConnections:(NSArray *)connections; - (AVCaptureConnection *)connectionWithMediaType:(NSString *)mediaType fromConnections:(NSArray *)connections;
- (void) captureStillImage; - (void)captureStillImage;
- (void) autoFocusAtPoint:(CGPoint)point; - (void)autoFocusAtPoint:(CGPoint)point;
- (void) continuousFocusAtPoint:(CGPoint)point; - (void)continuousFocusAtPoint:(CGPoint)point;
@end @end
// These delegate methods can be called on any arbitrary thread. If the delegate does something with the UI when called, make sure to send it to the main thread. // These delegate methods can be called on any arbitrary thread. If the delegate does something with the UI when called, make sure to send it to the main thread.
@protocol ViewFinderDelegate <NSObject> @protocol ViewFinderDelegate <NSObject>
@optional @optional
- (void) viewFinderStillImageCaptured:(ViewFinder *)viewFinder; - (void)viewFinderStillImageCaptured:(ViewFinder *)viewFinder;
- (void) viewFinderDeviceConfigurationChanged:(ViewFinder *)viewFinder; - (void)viewFinderDeviceConfigurationChanged:(ViewFinder *)viewFinder;
- (void)deviceOrientationDidChange; - (void)deviceOrientationDidChange;
@end @end
@interface RecordSound : NSObject @interface RecordSound : NSObject
+ (NSString *)getPermission; + (NSString *)getPermission;
+ (void) setPermission; + (void)setPermission;
+ (void) killRecording; + (void)killRecording;
// Exports // Exports
+ (NSString*) startRecord; + (NSString *)startRecord;
+ (NSString*) stopRecording; + (NSString *)stopRecording;
+ (double) getVolume; + (double)getVolume;
+ (NSString*) startPlay; + (NSString *)startPlay;
+ (NSString*) stopPlay; + (NSString *)stopPlay;
+ (NSString*) recordclose:(NSString *)keep; + (NSString *)recordclose:(NSString *)keep;
@end @end
@protocol JSExports <JSExport> @protocol JSExports <JSExport>
/* Functions exported to JavaScript */ /* Functions exported to JavaScript */
-(NSString*) hideSplash :(NSString *)body; - (NSString *)hideSplash:(NSString *)body;
-(void) askForPermission; - (void) askForPermission;
-(NSString*) database_stmt: (NSString*) json; - (NSString *)database_stmt:(NSString *) json;
-(NSString*) database_query: (NSString*) json; - (NSString *)database_query:(NSString *) json;
-(NSString*) io_getmd5: (NSString*) str; - (NSString *)io_getmd5:(NSString *) str;
-(NSString*) io_getsettings; - (NSString *)io_getsettings;
-(void) io_cleanassets:(NSString*) fileType; - (void)io_cleanassets:(NSString *)fileType;
-(NSString*) io_setfile:(NSString*)filename :(NSString*)base64ContentStr; - (NSString *)io_setfile:(NSString *)filename :(NSString *)base64ContentStr;
-(NSString*) io_getfile:(NSString*)filename; - (NSString *)io_getfile:(NSString *)filename;
-(NSString*) io_setmedia:(NSString*) base64ContentStr :(NSString*) extension; - (NSString *)io_setmedia:(NSString *)base64ContentStr :(NSString *)extension;
-(NSString*) io_setmedianame:(NSString*) contents :(NSString*) key :(NSString*) ext; - (NSString *)io_setmedianame:(NSString *)contents :(NSString *)key :(NSString *)ext;
-(NSString*) io_getmedia:(NSString*) filename; - (NSString *)io_getmedia:(NSString *)filename;
-(NSString*) io_getmediadata:(NSString*)filename :(int) offset :(int) length; - (NSString *)io_getmediadata:(NSString *)filename :(int)offset :(int)length;
-(NSString*) io_getmedialen:(NSString*)file :(NSString*)key; - (NSString *)io_getmedialen:(NSString *)file :(NSString *)key;
-(NSString*) io_getmediadone:(NSString*)filename; - (NSString *)io_getmediadone:(NSString *)filename;
-(NSString*) io_remove:(NSString*)filename; - (NSString *)io_remove:(NSString *)filename;
-(NSString*) io_registersound:(NSString*) dir :(NSString*) name; - (NSString *)io_registersound:(NSString *)dir :(NSString *)name;
-(NSString*) io_playsound:(NSString*) name; - (NSString *)io_playsound:(NSString *)name;
-(NSString*) io_stopsound:(NSString*) name; - (NSString *)io_stopsound:(NSString *)name;
-(NSString*) recordsound_recordstart; - (NSString *)recordsound_recordstart;
-(NSString*) recordsound_recordstop; - (NSString *)recordsound_recordstop;
-(NSString*) recordsound_volume; - (NSString *)recordsound_volume;
-(NSString*) recordsound_startplay; - (NSString *)recordsound_startplay;
-(NSString*) recordsound_stopplay; - (NSString *)recordsound_stopplay;
-(NSString*) recordsound_recordclose:(NSString*) keep; - (NSString *)recordsound_recordclose:(NSString *)keep;
-(NSString*) scratchjr_cameracheck; - (NSString *)scratchjr_cameracheck;
-(bool) scratchjr_has_multiple_cameras; - (bool) scratchjr_has_multiple_cameras;
-(NSString*) scratchjr_startfeed:(NSString*)str; - (NSString *)scratchjr_startfeed:(NSString *)str;
-(NSString*) scratchjr_stopfeed; - (NSString *)scratchjr_stopfeed;
-(NSString*) scratchjr_choosecamera:(NSString *)body; - (NSString *)scratchjr_choosecamera:(NSString *)body;
-(NSString*) scratchjr_captureimage:(NSString*)onCameraCaptureComplete; - (NSString *)scratchjr_captureimage:(NSString *)onCameraCaptureComplete;
- (NSString*) sendSjrUsingShareDialog:(NSString*) fileName :(NSString*) emailSubject :(NSString*) emailBody :(int) shareType :(NSString*) b64data; - (NSString *)sendSjrUsingShareDialog:(NSString *)fileName
-(NSString*) deviceName; :(NSString *)emailSubject
-(NSString*) analyticsEvent:(NSString*) category :(NSString*) action :(NSString*) label :(NSNumber*) value; :(NSString *)emailBody
:(int)shareType
:(NSString *)b64data;
- (NSString *) deviceName;
- (NSString *) analyticsEvent:(NSString *)category :(NSString *)action :(NSString *)label :(NSNumber*)value;
@end @end
@interface ViewController : UIViewController <JSExports,UIWebViewDelegate,MFMailComposeViewControllerDelegate> @interface ViewController : UIViewController <JSExports,UIWebViewDelegate,MFMailComposeViewControllerDelegate>
@property (nonatomic, readwrite, strong) JSContext *js; @property (nonatomic, readwrite, strong) JSContext *js;
+ (UIWebView*) webview; + (UIWebView *)webview;
+ (UIImageView*) splashScreen; + (UIImageView *)splashScreen;
- (void) receiveProject:(NSString*) project; - (void)receiveProject:(NSString *)project;
- (void)registerDefaultsFromSettingsBundle; - (void)registerDefaultsFromSettingsBundle;
- (void)reload; - (void)reload;
@end @end
@interface ViewController (ViewFinderDelegate) <ViewFinderDelegate> @interface ViewController (ViewFinderDelegate) <ViewFinderDelegate>
- (void) showShareEmail:(NSURL *) projectURL withName: (NSString*) name withSubject:(NSString*) subject withBody:(NSString*)body; - (void)showShareEmail:(NSURL *)projectURL
- (void) showShareAirdrop:(NSURL *) projectURL; withName:(NSString *)name
withSubject:(NSString *)subject
withBody:(NSString *)body;
- (void)showShareAirdrop:(NSURL *)projectURL;
@end @end
@interface IO : NSObject @interface IO : NSObject
+ (void)init:(ViewController*)vc; + (void)init:(ViewController*)vc;
+ (NSString*)getpath; + (NSString *)getpath;
+ (NSString*)removeFile:(NSString *)str; + (NSString *)removeFile:(NSString *)str;
+ (NSURL*)getDocumentPath:(NSString *)name; + (NSURL *)getDocumentPath:(NSString *)name;
+ (NSString*) encodeBase64:(NSData*)theData; + (NSString *)encodeBase64:(NSData *)theData;
// Exports // Exports
+ (NSString*)getMD5:(NSString*)str; + (NSString *)getMD5:(NSString *)str;
+ (NSString*) getsettings; + (NSString *)getsettings;
+ (void) cleanassets:(NSString*)fileType; + (void) cleanassets:(NSString *)fileType;
+ (NSString*) setfile:(NSString*)filename :(NSString*)base64ContentStr; + (NSString *)setfile:(NSString *)filename :(NSString *)base64ContentStr;
+ (NSString*)getfile:(NSString *)filename; + (NSString *)getfile:(NSString *)filename;
+ (NSString*) setmedia:(NSString*) base64ContentStr :(NSString*) extension; + (NSString *)setmedia:(NSString *)base64ContentStr :(NSString *)extension;
+ (NSString*) setmedianame:(NSString*) contents :(NSString*) key :(NSString*) ext; + (NSString *)setmedianame:(NSString *)contents :(NSString *)key :(NSString *)ext;
+ (NSString*) getmedia:(NSString*) filename; + (NSString *)getmedia:(NSString *)filename;
+ (NSString*) getmediadata:(NSString*)filename :(int) offset :(int) length; + (NSString *)getmediadata:(NSString *)filename :(int)offset :(int)length;
+ (NSString*) getmedialen:(NSString*)file :(NSString*)key; + (NSString *)getmedialen:(NSString *)file :(NSString *)key;
+ (NSString*) getmediadone:(NSString*)filename; + (NSString *)getmediadone:(NSString *)filename;
+ (NSString*) remove:(NSString*)filename; + (NSString *)remove:(NSString *)filename;
+ (NSString*) sendSjrUsingShareDialog:(NSString*) fileName :(NSString*) emailSubject :(NSString*) emailBody :(int) shareType :(NSString*) b64data; + (NSString *)sendSjrUsingShareDialog:(NSString *)fileName
+(NSString *) registerSound:(NSString*) dir :(NSString*) name; :(NSString *)emailSubject
+(NSString *) playSound:(NSString*) name; :(NSString *)emailBody
+(NSString *) stopSound:(NSString*) name; :(int)shareType
:(NSString *)b64data;
+ (NSString *)registerSound:(NSString *)dir :(NSString *)name;
+ (NSString *)playSound:(NSString *)name;
+ (NSString *)stopSound:(NSString *)name;
@end @end
@interface ScratchJr : NSObject @interface ScratchJr : NSObject
@ -173,12 +184,12 @@
+ (void)reportImageError; + (void)reportImageError;
+ (void)cameraInit; + (void)cameraInit;
+ (void)cameraClose; + (void)cameraClose;
+ (NSString *) hideSplash :(NSString *)body; + (NSString *)hideSplash :(NSString *)body;
// Exports // Exports
+(NSString*) cameracheck; + (NSString *)cameracheck;
+(NSString*) startfeed:(NSString*)str; + (NSString *)startfeed:(NSString *)str;
+(NSString*) stopfeed; + (NSString *)stopfeed;
+(NSString*) choosecamera:(NSString*) body; + (NSString *)choosecamera:(NSString *)body;
+(NSString*) captureimage:(NSString*)onCameraCaptureComplete; + (NSString *)captureimage:(NSString *)onCameraCaptureComplete;
@end @end

View file

@ -78,7 +78,6 @@ JSContext *js;
[defaultsToRegister setObject:[prefSpecification objectForKey:@"DefaultValue"] forKey:key]; [defaultsToRegister setObject:[prefSpecification objectForKey:@"DefaultValue"] forKey:key];
} }
} }
// NSLog(@"defaultsToRegister %@", defaultsToRegister);
[[NSUserDefaults standardUserDefaults] registerDefaults:defaultsToRegister]; [[NSUserDefaults standardUserDefaults] registerDefaults:defaultsToRegister];
} }

View file

@ -183,13 +183,12 @@ export default class iOS {
// Sound functions // Sound functions
static registerSound (dir, name, fcn) { static registerSound (dir, name, fcn) {
var result = tabletInterface.io_registersound(dir, name); var result = tabletInterface.io_registersound(dir, name);
if (fcn) { if (fcn) {
fcn(result); fcn(result);
}
} }
}
static playSound (name, fcn) { static playSound (name, fcn) {
var result = tabletInterface.io_playsound(name); var result = tabletInterface.io_playsound(name);
@ -372,8 +371,6 @@ export default class iOS {
} }
} }
} }
} }
// Expose iOS methods for ScratchJr tablet sharing callbacks // Expose iOS methods for ScratchJr tablet sharing callbacks

View file

@ -48,18 +48,10 @@ export default class ScratchAudio {
ScratchAudio.addSound(prefix + 'sounds/', defaultSounds[i], uiSounds); ScratchAudio.addSound(prefix + 'sounds/', defaultSounds[i], uiSounds);
} }
ScratchAudio.addSound(prefix, 'pop.mp3', projectSounds); ScratchAudio.addSound(prefix, 'pop.mp3', projectSounds);
// } else {
// for (var j=0; j < defaultSounds.length; j++) {
// iOS.registerSound('HTML5/sounds/', defaultSounds[j], ScratchAudio.UIsoundLoaded );
// }
// iOS.registerSound('HTML5/', 'pop.mp3', ScratchAudio.UIsoundLoaded );
// }
} }
static addSound (url, snd, dict, fcn) { static addSound (url, snd, dict, fcn) {
var name = snd; var name = snd;
console.log(url+' '+snd);
if (!isAndroid) { if (!isAndroid) {
var whenDone = function (str) { var whenDone = function (str) {
if (str != 'error') { if (str != 'error') {
@ -71,10 +63,8 @@ export default class ScratchAudio {
if (fcn) { if (fcn) {
fcn(name); fcn(name);
} }
// dict [name].time = Number (result[1]);
}; };
iOS.registerSound(url, snd, whenDone); iOS.registerSound(url, snd, whenDone);
} else { } else {
// In Android, this is handled outside of JavaScript, so just place a stub here. // In Android, this is handled outside of JavaScript, so just place a stub here.
dict[snd] = new Sound(url + snd); dict[snd] = new Sound(url + snd);
@ -87,12 +77,9 @@ export default class ScratchAudio {
static soundDone (name) { static soundDone (name) {
if (!projectSounds[name]) return; if (!projectSounds[name]) return;
projectSounds[name].playing = false; projectSounds[name].playing = false;
console.log(name);
} }
static loadProjectSound (md5, fcn) { static loadProjectSound (md5, fcn) {
console.log(md5);
if (!md5) { if (!md5) {
return; return;
} }
@ -101,7 +88,6 @@ export default class ScratchAudio {
if (md5.indexOf('/') > -1) dir = 'HTML5/'; if (md5.indexOf('/') > -1) dir = 'HTML5/';
else if (md5.indexOf('wav') > -1) dir = 'Documents'; else if (md5.indexOf('wav') > -1) dir = 'Documents';
} }
console.log('loadProjectSound: ' + dir + ' ' + md5);
ScratchAudio.loadFromLocal(dir, md5, fcn); ScratchAudio.loadFromLocal(dir, md5, fcn);
} }
@ -111,7 +97,6 @@ export default class ScratchAudio {
} }
ScratchAudio.addSound(dir, md5, projectSounds, fcn); ScratchAudio.addSound(dir, md5, projectSounds, fcn);
} }
} }
window.ScratchAudio = ScratchAudio; window.ScratchAudio = ScratchAudio;