From f752ff57604eb937f6d16c20640d49c4832eb503 Mon Sep 17 00:00:00 2001 From: chrisgarrity Date: Tue, 14 Mar 2017 12:11:53 -0400 Subject: [PATCH] Fix formatting and restart bug MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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. --- ios/ScratchJr/src/IO.m | 70 +++-------- ios/ScratchJr/src/ScratchJr.h | 195 +++++++++++++++-------------- ios/ScratchJr/src/ViewController.m | 1 - src/iPad/iOS.js | 13 +- src/utils/ScratchAudio.js | 15 --- 5 files changed, 122 insertions(+), 172 deletions(-) diff --git a/ios/ScratchJr/src/IO.m b/ios/ScratchJr/src/IO.m index 91af298..d6af975 100644 --- a/ios/ScratchJr/src/IO.m +++ b/ios/ScratchJr/src/IO.m @@ -233,59 +233,24 @@ NSMutableDictionary *sounds; + (NSString *)registerSound:(NSString*)dir :(NSString*)name { NSURL *url; - if ([dir isEqual: @"Documents"]){ + if ([dir isEqual:@"Documents"]){ url = [self getDocumentPath: name]; } else { url = [self getResourcePath: [NSString stringWithFormat: @"%@%@", dir, name]]; } - NSLog (@"registering %@", url); NSError *error; AVAudioPlayer *snd = [[AVAudioPlayer alloc] initWithContentsOfURL: url error:&error]; - if (error == NULL) { + if (error == nil) { [sounds setObject:snd forKey:name]; + [snd prepareToPlay]; return [NSString stringWithFormat: @"%@,%f", name, snd.duration]; } - else { - - NSLog (@"%@", 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 { // TODO: make scratchJr pay attention to the mute // // audio type: respect the "Mute" if there are audio sounds @@ -294,12 +259,11 @@ NSMutableDictionary *sounds; // SessionCategoryPlayAndRecord : AVAudioSessionCategoryAmbient; // [[AVAudioSession sharedInstance] setCategory:audiotype error:nil]; AVAudioPlayer *snd = sounds[name]; - NSLog (@"play %@", snd); - if (snd == NULL) { + if (snd == nil) { return [NSString stringWithFormat: @"%@ not found", name]; } else { - [snd prepareToPlay]; + [snd setCurrentTime:0.0]; [snd play]; [NSTimer scheduledTimerWithTimeInterval: [snd duration] target: self selector: @selector(so\ undEnded:) userInfo:@{@"soundName": name} repeats: NO]; @@ -308,28 +272,22 @@ undEnded:) userInfo:@{@"soundName": name} repeats: NO]; } + (void)soundEnded:(NSTimer*)timer { - NSString *soundName = [[timer userInfo] objectForKey:@"soundName"]; - NSLog(@"%@", soundName); - if (sounds [soundName] == NULL) return; - NSString *callback = [NSString stringWithFormat: @"iOS.soundDone('%@');",soundName]; + NSString *soundName = [[timer userInfo] objectForKey:@"soundName"]; + if (sounds[soundName] == nil) return; + NSString *callback = [NSString stringWithFormat:@"iOS.soundDone('%@');", soundName]; UIWebView *webview = [ViewController webview]; - [webview stringByEvaluatingJavaScriptFromString: callback]; + [webview stringByEvaluatingJavaScriptFromString:callback]; } + + (NSString *)stopSound :(NSString*)name { AVAudioPlayer *snd = sounds[name]; - NSLog (@"stop %@", snd); - if (snd == NULL) { - return [NSString stringWithFormat: @"%@ not found", name]; - } - else { - [snd stop]; - return [NSString stringWithFormat: @"%@ stopped", name]; + if (snd == nil) { + return [NSString stringWithFormat:@"%@ not found", name]; } + [snd stop]; + return [NSString stringWithFormat:@"%@ stopped", name]; } - - - //////////////////////////// // File system //////////////////////////// diff --git a/ios/ScratchJr/src/ScratchJr.h b/ios/ScratchJr/src/ScratchJr.h index bfa8974..e94a8ca 100644 --- a/ios/ScratchJr/src/ScratchJr.h +++ b/ios/ScratchJr/src/ScratchJr.h @@ -6,15 +6,15 @@ @interface Database : NSObject -+ (NSString*)open:(NSString *)body; -+ (NSString*)close:(NSString *)str; ++ (NSString *)open:(NSString *)body; ++ (NSString *)close:(NSString *)str; + (void)initTables; + (void)runMigrations; -+ (NSArray*)findDataIn:(NSString *)stmtstr with:(NSArray *)values; ++ (NSArray *)findDataIn:(NSString *)stmtstr with:(NSArray *)values; // Exports -+ (NSString*) stmt: (NSString*) json; -+ (NSString*) query: (NSString*) json; ++ (NSString *)stmt:(NSString *)json; ++ (NSString *)query:(NSString *)json; @end @interface CameraMask : UIView @@ -30,10 +30,10 @@ @property float scale; @property NSString *usingCamera; --(void) switchOrientation:(int)orientation; --(id)initWithFrame:(CGRect)frame withScale:(float)scale; --(void) setCameraTo:(NSString*)dir; --(NSString*)getImageBase64:(NSData*)imgdata; +- (void)switchOrientation:(int)orientation; +- (id)initWithFrame:(CGRect)frame withScale:(float)scale; +- (void)setCameraTo:(NSString *)dir; +- (NSString *)getImageBase64:(NSData *)imgdata; @end @@ -51,120 +51,131 @@ @property AVCaptureStillImageOutput *stillImageOutput; -- (BOOL) setupSession; -+ (NSString*) cameraHasPermission; -- (void) closeSession; -- (NSUInteger) cameraCount; -- (BOOL) setCamera:(NSString *)mode; +- (BOOL)setupSession; ++ (NSString *)cameraHasPermission; +- (void)closeSession; +- (NSUInteger)cameraCount; +- (BOOL)setCamera:(NSString *)mode; - (AVCaptureConnection *)connectionWithMediaType:(NSString *)mediaType fromConnections:(NSArray *)connections; -- (void) captureStillImage; -- (void) autoFocusAtPoint:(CGPoint)point; -- (void) continuousFocusAtPoint:(CGPoint)point; +- (void)captureStillImage; +- (void)autoFocusAtPoint:(CGPoint)point; +- (void)continuousFocusAtPoint:(CGPoint)point; @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. @protocol ViewFinderDelegate @optional -- (void) viewFinderStillImageCaptured:(ViewFinder *)viewFinder; -- (void) viewFinderDeviceConfigurationChanged:(ViewFinder *)viewFinder; +- (void)viewFinderStillImageCaptured:(ViewFinder *)viewFinder; +- (void)viewFinderDeviceConfigurationChanged:(ViewFinder *)viewFinder; - (void)deviceOrientationDidChange; @end @interface RecordSound : NSObject + (NSString *)getPermission; -+ (void) setPermission; -+ (void) killRecording; ++ (void)setPermission; ++ (void)killRecording; // Exports -+ (NSString*) startRecord; -+ (NSString*) stopRecording; -+ (double) getVolume; -+ (NSString*) startPlay; -+ (NSString*) stopPlay; -+ (NSString*) recordclose:(NSString *)keep; ++ (NSString *)startRecord; ++ (NSString *)stopRecording; ++ (double)getVolume; ++ (NSString *)startPlay; ++ (NSString *)stopPlay; ++ (NSString *)recordclose:(NSString *)keep; @end @protocol JSExports /* Functions exported to JavaScript */ --(NSString*) hideSplash :(NSString *)body; --(void) askForPermission; --(NSString*) database_stmt: (NSString*) json; --(NSString*) database_query: (NSString*) json; --(NSString*) io_getmd5: (NSString*) str; --(NSString*) io_getsettings; --(void) io_cleanassets:(NSString*) fileType; --(NSString*) io_setfile:(NSString*)filename :(NSString*)base64ContentStr; --(NSString*) io_getfile:(NSString*)filename; --(NSString*) io_setmedia:(NSString*) base64ContentStr :(NSString*) extension; --(NSString*) io_setmedianame:(NSString*) contents :(NSString*) key :(NSString*) ext; --(NSString*) io_getmedia:(NSString*) filename; --(NSString*) io_getmediadata:(NSString*)filename :(int) offset :(int) length; --(NSString*) io_getmedialen:(NSString*)file :(NSString*)key; --(NSString*) io_getmediadone:(NSString*)filename; --(NSString*) io_remove:(NSString*)filename; --(NSString*) io_registersound:(NSString*) dir :(NSString*) name; --(NSString*) io_playsound:(NSString*) name; --(NSString*) io_stopsound:(NSString*) name; +- (NSString *)hideSplash:(NSString *)body; +- (void) askForPermission; +- (NSString *)database_stmt:(NSString *) json; +- (NSString *)database_query:(NSString *) json; +- (NSString *)io_getmd5:(NSString *) str; +- (NSString *)io_getsettings; +- (void)io_cleanassets:(NSString *)fileType; +- (NSString *)io_setfile:(NSString *)filename :(NSString *)base64ContentStr; +- (NSString *)io_getfile:(NSString *)filename; +- (NSString *)io_setmedia:(NSString *)base64ContentStr :(NSString *)extension; +- (NSString *)io_setmedianame:(NSString *)contents :(NSString *)key :(NSString *)ext; +- (NSString *)io_getmedia:(NSString *)filename; +- (NSString *)io_getmediadata:(NSString *)filename :(int)offset :(int)length; +- (NSString *)io_getmedialen:(NSString *)file :(NSString *)key; +- (NSString *)io_getmediadone:(NSString *)filename; +- (NSString *)io_remove:(NSString *)filename; +- (NSString *)io_registersound:(NSString *)dir :(NSString *)name; +- (NSString *)io_playsound:(NSString *)name; +- (NSString *)io_stopsound:(NSString *)name; --(NSString*) recordsound_recordstart; --(NSString*) recordsound_recordstop; --(NSString*) recordsound_volume; --(NSString*) recordsound_startplay; --(NSString*) recordsound_stopplay; --(NSString*) recordsound_recordclose:(NSString*) keep; +- (NSString *)recordsound_recordstart; +- (NSString *)recordsound_recordstop; +- (NSString *)recordsound_volume; +- (NSString *)recordsound_startplay; +- (NSString *)recordsound_stopplay; +- (NSString *)recordsound_recordclose:(NSString *)keep; --(NSString*) scratchjr_cameracheck; --(bool) scratchjr_has_multiple_cameras; --(NSString*) scratchjr_startfeed:(NSString*)str; --(NSString*) scratchjr_stopfeed; --(NSString*) scratchjr_choosecamera:(NSString *)body; --(NSString*) scratchjr_captureimage:(NSString*)onCameraCaptureComplete; -- (NSString*) sendSjrUsingShareDialog:(NSString*) fileName :(NSString*) emailSubject :(NSString*) emailBody :(int) shareType :(NSString*) b64data; --(NSString*) deviceName; --(NSString*) analyticsEvent:(NSString*) category :(NSString*) action :(NSString*) label :(NSNumber*) value; +- (NSString *)scratchjr_cameracheck; +- (bool) scratchjr_has_multiple_cameras; +- (NSString *)scratchjr_startfeed:(NSString *)str; +- (NSString *)scratchjr_stopfeed; +- (NSString *)scratchjr_choosecamera:(NSString *)body; +- (NSString *)scratchjr_captureimage:(NSString *)onCameraCaptureComplete; +- (NSString *)sendSjrUsingShareDialog:(NSString *)fileName + :(NSString *)emailSubject + :(NSString *)emailBody + :(int)shareType + :(NSString *)b64data; +- (NSString *) deviceName; +- (NSString *) analyticsEvent:(NSString *)category :(NSString *)action :(NSString *)label :(NSNumber*)value; @end @interface ViewController : UIViewController @property (nonatomic, readwrite, strong) JSContext *js; -+ (UIWebView*) webview; -+ (UIImageView*) splashScreen; -- (void) receiveProject:(NSString*) project; ++ (UIWebView *)webview; ++ (UIImageView *)splashScreen; +- (void)receiveProject:(NSString *)project; - (void)registerDefaultsFromSettingsBundle; - (void)reload; @end @interface ViewController (ViewFinderDelegate) -- (void) showShareEmail:(NSURL *) projectURL withName: (NSString*) name withSubject:(NSString*) subject withBody:(NSString*)body; -- (void) showShareAirdrop:(NSURL *) projectURL; +- (void)showShareEmail:(NSURL *)projectURL + withName:(NSString *)name + withSubject:(NSString *)subject + withBody:(NSString *)body; +- (void)showShareAirdrop:(NSURL *)projectURL; @end @interface IO : NSObject + (void)init:(ViewController*)vc; -+ (NSString*)getpath; -+ (NSString*)removeFile:(NSString *)str; -+ (NSURL*)getDocumentPath:(NSString *)name; -+ (NSString*) encodeBase64:(NSData*)theData; ++ (NSString *)getpath; ++ (NSString *)removeFile:(NSString *)str; ++ (NSURL *)getDocumentPath:(NSString *)name; ++ (NSString *)encodeBase64:(NSData *)theData; // Exports -+ (NSString*)getMD5:(NSString*)str; -+ (NSString*) getsettings; -+ (void) cleanassets:(NSString*)fileType; -+ (NSString*) setfile:(NSString*)filename :(NSString*)base64ContentStr; -+ (NSString*)getfile:(NSString *)filename; -+ (NSString*) setmedia:(NSString*) base64ContentStr :(NSString*) extension; -+ (NSString*) setmedianame:(NSString*) contents :(NSString*) key :(NSString*) ext; -+ (NSString*) getmedia:(NSString*) filename; -+ (NSString*) getmediadata:(NSString*)filename :(int) offset :(int) length; -+ (NSString*) getmedialen:(NSString*)file :(NSString*)key; -+ (NSString*) getmediadone:(NSString*)filename; -+ (NSString*) remove:(NSString*)filename; -+ (NSString*) sendSjrUsingShareDialog:(NSString*) fileName :(NSString*) emailSubject :(NSString*) emailBody :(int) shareType :(NSString*) b64data; -+(NSString *) registerSound:(NSString*) dir :(NSString*) name; -+(NSString *) playSound:(NSString*) name; -+(NSString *) stopSound:(NSString*) name; ++ (NSString *)getMD5:(NSString *)str; ++ (NSString *)getsettings; ++ (void) cleanassets:(NSString *)fileType; ++ (NSString *)setfile:(NSString *)filename :(NSString *)base64ContentStr; ++ (NSString *)getfile:(NSString *)filename; ++ (NSString *)setmedia:(NSString *)base64ContentStr :(NSString *)extension; ++ (NSString *)setmedianame:(NSString *)contents :(NSString *)key :(NSString *)ext; ++ (NSString *)getmedia:(NSString *)filename; ++ (NSString *)getmediadata:(NSString *)filename :(int)offset :(int)length; ++ (NSString *)getmedialen:(NSString *)file :(NSString *)key; ++ (NSString *)getmediadone:(NSString *)filename; ++ (NSString *)remove:(NSString *)filename; ++ (NSString *)sendSjrUsingShareDialog:(NSString *)fileName + :(NSString *)emailSubject + :(NSString *)emailBody + :(int)shareType + :(NSString *)b64data; ++ (NSString *)registerSound:(NSString *)dir :(NSString *)name; ++ (NSString *)playSound:(NSString *)name; ++ (NSString *)stopSound:(NSString *)name; @end @interface ScratchJr : NSObject @@ -173,12 +184,12 @@ + (void)reportImageError; + (void)cameraInit; + (void)cameraClose; -+ (NSString *) hideSplash :(NSString *)body; ++ (NSString *)hideSplash :(NSString *)body; // Exports -+(NSString*) cameracheck; -+(NSString*) startfeed:(NSString*)str; -+(NSString*) stopfeed; -+(NSString*) choosecamera:(NSString*) body; -+(NSString*) captureimage:(NSString*)onCameraCaptureComplete; ++ (NSString *)cameracheck; ++ (NSString *)startfeed:(NSString *)str; ++ (NSString *)stopfeed; ++ (NSString *)choosecamera:(NSString *)body; ++ (NSString *)captureimage:(NSString *)onCameraCaptureComplete; @end diff --git a/ios/ScratchJr/src/ViewController.m b/ios/ScratchJr/src/ViewController.m index 76c8a9c..71f9b22 100644 --- a/ios/ScratchJr/src/ViewController.m +++ b/ios/ScratchJr/src/ViewController.m @@ -78,7 +78,6 @@ JSContext *js; [defaultsToRegister setObject:[prefSpecification objectForKey:@"DefaultValue"] forKey:key]; } } - // NSLog(@"defaultsToRegister %@", defaultsToRegister); [[NSUserDefaults standardUserDefaults] registerDefaults:defaultsToRegister]; } diff --git a/src/iPad/iOS.js b/src/iPad/iOS.js index 7c028ec..7e25584 100644 --- a/src/iPad/iOS.js +++ b/src/iPad/iOS.js @@ -183,13 +183,12 @@ export default class iOS { // Sound functions - static registerSound (dir, name, fcn) { - var result = tabletInterface.io_registersound(dir, name); - if (fcn) { - fcn(result); - } + static registerSound (dir, name, fcn) { + var result = tabletInterface.io_registersound(dir, name); + if (fcn) { + fcn(result); } - + } static playSound (name, fcn) { var result = tabletInterface.io_playsound(name); @@ -372,8 +371,6 @@ export default class iOS { } } } - - } // Expose iOS methods for ScratchJr tablet sharing callbacks diff --git a/src/utils/ScratchAudio.js b/src/utils/ScratchAudio.js index bc9789b..7add306 100755 --- a/src/utils/ScratchAudio.js +++ b/src/utils/ScratchAudio.js @@ -48,18 +48,10 @@ export default class ScratchAudio { ScratchAudio.addSound(prefix + 'sounds/', defaultSounds[i], uiSounds); } 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) { var name = snd; - console.log(url+' '+snd); if (!isAndroid) { var whenDone = function (str) { if (str != 'error') { @@ -71,10 +63,8 @@ export default class ScratchAudio { if (fcn) { fcn(name); } - // dict [name].time = Number (result[1]); }; iOS.registerSound(url, snd, whenDone); - } else { // In Android, this is handled outside of JavaScript, so just place a stub here. dict[snd] = new Sound(url + snd); @@ -87,12 +77,9 @@ export default class ScratchAudio { static soundDone (name) { if (!projectSounds[name]) return; projectSounds[name].playing = false; - console.log(name); - } static loadProjectSound (md5, fcn) { - console.log(md5); if (!md5) { return; } @@ -101,7 +88,6 @@ export default class ScratchAudio { if (md5.indexOf('/') > -1) dir = 'HTML5/'; else if (md5.indexOf('wav') > -1) dir = 'Documents'; } - console.log('loadProjectSound: ' + dir + ' ' + md5); ScratchAudio.loadFromLocal(dir, md5, fcn); } @@ -111,7 +97,6 @@ export default class ScratchAudio { } ScratchAudio.addSound(dir, md5, projectSounds, fcn); } - } window.ScratchAudio = ScratchAudio;