├── .gitignore ├── .project ├── .settings └── com.aptana.editor.common.prefs ├── CHANGELOG.txt ├── Classes ├── .DS_Store ├── .gitignore ├── ComMfoggSquarecameraModule.h ├── ComMfoggSquarecameraModule.m ├── ComMfoggSquarecameraModuleAssets.h ├── ComMfoggSquarecameraModuleAssets.m ├── ComMfoggSquarecameraView.h ├── ComMfoggSquarecameraView.m ├── ComMfoggSquarecameraViewProxy.h └── ComMfoggSquarecameraViewProxy.m ├── ComMfoggSquarecamera_Prefix.pch ├── LICENSE ├── LICENSE.txt ├── README.md ├── SquareCamera.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ ├── xcshareddata │ │ └── SquareCamera.xccheckout │ └── xcuserdata │ │ ├── USuck.xcuserdatad │ │ └── UserInterfaceState.xcuserstate │ │ └── mfogg.xcuserdatad │ │ ├── UserInterfaceState.xcuserstate │ │ └── WorkspaceSettings.xcsettings └── xcuserdata │ ├── USuck.xcuserdatad │ └── xcschemes │ │ ├── Build & Test.xcscheme │ │ ├── SquareCamera.xcscheme │ │ └── xcschememanagement.plist │ └── mfogg.xcuserdatad │ ├── xcdebugger │ ├── Breakpoints.xcbkptlist │ └── Breakpoints_v2.xcbkptlist │ └── xcschemes │ ├── Build & Test.xcscheme │ ├── SquareCamera.xcscheme │ └── xcschememanagement.plist ├── assets └── README ├── build.py ├── dist ├── .DS_Store ├── com.mfogg.squarecamera-iphone-0.2.zip ├── com.mfogg.squarecamera-iphone-0.3.zip ├── com.mfogg.squarecamera-iphone-0.4.zip ├── com.mfogg.squarecamera-iphone-0.5.zip ├── com.mfogg.squarecamera-iphone-0.6.zip ├── com.mfogg.squarecamera-iphone-0.7.1.zip ├── com.mfogg.squarecamera-iphone-0.7.zip └── com.mfogg.squarecamera-iphone-0.8.0.zip ├── documentation └── index.md ├── example └── app.js ├── hooks ├── README ├── add.py ├── install.py ├── remove.py └── uninstall.py ├── manifest ├── module.xcconfig ├── platform └── README ├── timodule.xml └── titanium.xcconfig /.gitignore: -------------------------------------------------------------------------------- 1 | tmp 2 | bin 3 | build 4 | /.DS_Store 5 | /dist/.DS_Store 6 | -------------------------------------------------------------------------------- /.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | SquareCamera 4 | 5 | 6 | 7 | 8 | 9 | com.appcelerator.titanium.core.builder 10 | 11 | 12 | 13 | 14 | com.aptana.ide.core.unifiedBuilder 15 | 16 | 17 | 18 | 19 | 20 | com.appcelerator.titanium.mobile.module.nature 21 | com.aptana.projects.webnature 22 | 23 | 24 | -------------------------------------------------------------------------------- /.settings/com.aptana.editor.common.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | selectUserAgents=com.appcelerator.titanium.mobile.module.nature\:iphone 3 | -------------------------------------------------------------------------------- /CHANGELOG.txt: -------------------------------------------------------------------------------- 1 | 0.7 : Added 2D Code detection option. 2 | -------------------------------------------------------------------------------- /Classes/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikefogg/SquareCamera/032d632b19929a4596177c6e9029bc0deb78c06e/Classes/.DS_Store -------------------------------------------------------------------------------- /Classes/.gitignore: -------------------------------------------------------------------------------- 1 | ComMfoggSquarecamera.h 2 | ComMfoggSquarecamera.m 3 | -------------------------------------------------------------------------------- /Classes/ComMfoggSquarecameraModule.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Appcelerator Titanium Mobile 3 | * Copyright (c) 2009-2013 by Appcelerator, Inc. All Rights Reserved. 4 | * Licensed under the terms of the Apache Public License 5 | * Please see the LICENSE included with this distribution for details. 6 | */ 7 | #import "TiModule.h" 8 | #import "TiUIView.h" 9 | #import "TiBase.h" 10 | #import "TiHost.h" 11 | #import "TiUtils.h" 12 | 13 | #import "TiBlob.h" 14 | 15 | 16 | #import 17 | #import 18 | #import 19 | #import 20 | #import 21 | #import 22 | #import 23 | #import 24 | #import 25 | #import 26 | 27 | NS_ENUM(NSInteger, AVSessionPresetType) 28 | { 29 | LOW_QUALITY = 0, 30 | MEDIUM_QUALITY = 1, 31 | HIGH_QUALITY = 2, 32 | HD_QUALITY = 3 33 | }; 34 | 35 | @interface ComMfoggSquarecameraModule : TiModule 36 | { 37 | } 38 | 39 | @property (strong, nonatomic) UIWindow *window; 40 | 41 | @end -------------------------------------------------------------------------------- /Classes/ComMfoggSquarecameraModule.m: -------------------------------------------------------------------------------- 1 | /** 2 | * Your Copyright Here 3 | * 4 | * Appcelerator Titanium is Copyright (c) 2009-2010 by Appcelerator, Inc. 5 | * and licensed under the Apache Public License (version 2) 6 | */ 7 | #import "ComMfoggSquarecameraModule.h" 8 | 9 | 10 | @implementation ComMfoggSquarecameraModule 11 | 12 | #pragma mark Internal 13 | 14 | // this is generated for your module, please do not change it 15 | -(id)moduleGUID 16 | { 17 | return @"af2428c0-0bcf-4757-9838-3bbd7c558dd0"; 18 | } 19 | 20 | // this is generated for your module, please do not change it 21 | -(NSString*)moduleId 22 | { 23 | return @"com.mfogg.squarecamera"; 24 | } 25 | 26 | /* Add some quality constants */ 27 | MAKE_SYSTEM_PROP(QUALITY_HD, HD_QUALITY); 28 | MAKE_SYSTEM_PROP(QUALITY_HIGH, HIGH_QUALITY); 29 | MAKE_SYSTEM_PROP(QUALITY_MEDIUM, MEDIUM_QUALITY); 30 | MAKE_SYSTEM_PROP(QUALITY_LOW, LOW_QUALITY); 31 | 32 | #pragma mark Lifecycle 33 | 34 | -(void)startup 35 | { 36 | // this method is called when the module is first loaded 37 | // you *must* call the superclass 38 | [super startup]; 39 | 40 | NSLog(@"[INFO] %@ loaded",self); 41 | } 42 | 43 | -(void)shutdown:(id)sender 44 | { 45 | // this method is called when the module is being unloaded 46 | // typically this is during shutdown. make sure you don't do too 47 | // much processing here or the app will be quit forceably 48 | 49 | // you *must* call the superclass 50 | [super shutdown:sender]; 51 | } 52 | 53 | #pragma mark Cleanup 54 | 55 | -(void)dealloc 56 | { 57 | // release any resources that have been retained by the module 58 | [super dealloc]; 59 | } 60 | 61 | #pragma mark Internal Memory Management 62 | 63 | -(void)didReceiveMemoryWarning:(NSNotification*)notification 64 | { 65 | // optionally release any resources that can be dynamically 66 | // reloaded once memory is available - such as caches 67 | [super didReceiveMemoryWarning:notification]; 68 | } 69 | 70 | #pragma mark Listener Notifications 71 | 72 | -(void)_listenerAdded:(NSString *)type count:(int)count 73 | { 74 | if (count == 1 && [type isEqualToString:@"my_event"]) 75 | { 76 | // the first (of potentially many) listener is being added 77 | // for event named 'my_event' 78 | } 79 | } 80 | 81 | -(void)_listenerRemoved:(NSString *)type count:(int)count 82 | { 83 | if (count == 0 && [type isEqualToString:@"my_event"]) 84 | { 85 | // the last listener called for event named 'my_event' has 86 | // been removed, we can optionally clean up any resources 87 | // since no body is listening at this point for that event 88 | } 89 | } 90 | 91 | @end 92 | -------------------------------------------------------------------------------- /Classes/ComMfoggSquarecameraModuleAssets.h: -------------------------------------------------------------------------------- 1 | /** 2 | * This is a generated file. Do not edit or your changes will be lost 3 | */ 4 | 5 | @interface ComMfoggSquarecameraModuleAssets : NSObject 6 | { 7 | } 8 | - (NSData*) moduleAsset; 9 | - (NSData*) resolveModuleAsset:(NSString*)path; 10 | 11 | @end 12 | -------------------------------------------------------------------------------- /Classes/ComMfoggSquarecameraModuleAssets.m: -------------------------------------------------------------------------------- 1 | /** 2 | * This is a generated file. Do not edit or your changes will be lost 3 | */ 4 | #import "ComMfoggSquarecameraModuleAssets.h" 5 | 6 | extern NSData* filterDataInRange(NSData* thedata, NSRange range); 7 | 8 | @implementation ComMfoggSquarecameraModuleAssets 9 | 10 | - (NSData*) moduleAsset 11 | { 12 | //##TI_AUTOGEN_BEGIN asset 13 | //Compiler generates code for asset here 14 | return nil; // DEFAULT BEHAVIOR 15 | //##TI_AUTOGEN_END asset 16 | } 17 | 18 | - (NSData*) resolveModuleAsset:(NSString*)path 19 | { 20 | //##TI_AUTOGEN_BEGIN resolve_asset 21 | //Compiler generates code for asset resolution here 22 | return nil; // DEFAULT BEHAVIOR 23 | //##TI_AUTOGEN_END resolve_asset 24 | } 25 | 26 | @end 27 | -------------------------------------------------------------------------------- /Classes/ComMfoggSquarecameraView.h: -------------------------------------------------------------------------------- 1 | /** 2 | * SquareCamera Titanium Module 3 | * 4 | * learning/tests/dev/etc... 5 | * 6 | * original author : Mike Fogg : blirpit : 2013 7 | * 8 | * modifications / attempts to fix / general fist thumping : Kosso : August 2013 9 | * . 10 | */ 11 | 12 | #import "TiUIView.h" 13 | #import "TiBase.h" 14 | #import "TiHost.h" 15 | #import "TiUtils.h" 16 | #import "TiBlob.h" 17 | 18 | 19 | #import 20 | #import 21 | #import 22 | #import 23 | #import 24 | #import 25 | #import 26 | #import 27 | #import 28 | #import 29 | 30 | @interface ComMfoggSquarecameraView : TiUIView 31 | { 32 | UIView *square; 33 | UIView *flashView; 34 | dispatch_queue_t videoDataOutputQueue; 35 | } 36 | 37 | @property (nonatomic, strong) AVCaptureSession *captureSession; 38 | @property (nonatomic, strong) AVCaptureVideoPreviewLayer *prevLayer; 39 | @property (nonatomic, assign) AVCaptureVideoOrientation *orientation; 40 | @property (nonatomic,retain) AVCaptureDeviceInput *videoInput; 41 | @property (nonatomic,retain) AVCaptureDeviceInput *audioInput; 42 | @property (nonatomic, retain) AVCaptureStillImageOutput *stillImageOutput; 43 | @property (nonatomic, retain) AVCaptureVideoDataOutput *videoDataOutput; 44 | @property (nonatomic, retain) UIImageView *stillImage; 45 | @property (nonatomic, retain) AVCaptureDevice *captureDevice; 46 | @property (nonatomic, retain) NSString *camera; 47 | @property (nonatomic, retain) NSDictionary *barcodeDict; 48 | @property (nonatomic, retain) NSArray *barcodeTypes; 49 | @property (nonatomic) Boolean flashOn; 50 | @property (nonatomic) BOOL adjustingExposure; 51 | @property (nonatomic, assign) BOOL detectCodes; 52 | @property (nonatomic, assign) BOOL forceHorizontal; 53 | @property (nonatomic, retain) NSString *frontQuality; 54 | @property (nonatomic, retain) NSString *backQuality; 55 | @property (nonatomic, retain) NSDictionary *scanCrop; 56 | @property (nonatomic) BOOL scanCropPreview; 57 | 58 | @end 59 | -------------------------------------------------------------------------------- /Classes/ComMfoggSquarecameraView.m: -------------------------------------------------------------------------------- 1 | 2 | // original via github.com/mikefogg/SquareCamera 3 | 4 | // Modifications / Attempts to fix using ramdom bit of code found here and there : Kosso : August 2013 5 | 6 | // April 4 2015 : Kosso added built-in 2D QR/barcode detection option. Set dectectCodes:true|false when creating the camera view. 7 | 8 | #import "ComMfoggSquarecameraModule.h" 9 | #import "ComMfoggSquarecameraView.h" 10 | #import "ComMfoggSquarecameraViewProxy.h" 11 | #import 12 | #import 13 | #import 14 | 15 | 16 | @implementation ComMfoggSquarecameraView 17 | 18 | // used for KVO observation of the @"capturingStillImage" property to perform flash bulb animation 19 | static const NSString *AVCaptureStillImageIsCapturingStillImageContext = @"AVCaptureStillImageIsCapturingStillImageContext"; 20 | 21 | - (void) dealloc 22 | { 23 | [self teardownAVCapture]; 24 | 25 | self.prevLayer = nil; 26 | self.stillImage = nil; 27 | self.stillImageOutput = nil; 28 | self.captureDevice = nil; 29 | 30 | RELEASE_TO_NIL(square); 31 | }; 32 | 33 | -(void)initializeState 34 | { 35 | [super initializeState]; 36 | 37 | self.prevLayer = nil; 38 | self.stillImage = nil; 39 | self.stillImageOutput = nil; 40 | self.captureDevice = nil; 41 | 42 | // Set defaults 43 | self.camera = @"back"; // Default camera is 'back' 44 | self.frontQuality = AVCaptureSessionPresetHigh; // Default front quality is high 45 | self.backQuality = AVCaptureSessionPreset1920x1080; // Default back quality is HD 46 | self.scanCropPreview = ([self.proxy valueForKey:@"scanCropPreview"] != nil) ? [[self.proxy valueForKey:@"scanCropPreview"] boolValue] : false; 47 | self.scanCrop = ([self.proxy valueForKey:@"scanCrop"] != nil) ? [self.proxy valueForKey:@"scanCrop"] : nil; 48 | self.barcodeTypes = ([self.proxy valueForKey:@"barcodeTypes"] != nil) ? [self.proxy valueForKey:@"barcodeTypes"] : @[]; 49 | 50 | // Barcode Options 51 | self.barcodeDict = [[NSDictionary alloc] initWithObjectsAndKeys: 52 | AVMetadataObjectTypeUPCECode, @"UPCE", 53 | AVMetadataObjectTypeCode39Code, @"Code39", 54 | AVMetadataObjectTypeCode39Mod43Code, @"Code39Mod43", 55 | AVMetadataObjectTypeEAN13Code, @"EAN13", 56 | AVMetadataObjectTypeEAN8Code, @"EAN8", 57 | AVMetadataObjectTypeCode93Code, @"Code93", 58 | AVMetadataObjectTypeCode128Code, @"Code128", 59 | AVMetadataObjectTypePDF417Code, @"PDF417", 60 | AVMetadataObjectTypeQRCode, @"QR", 61 | AVMetadataObjectTypeAztecCode, @"Aztec", 62 | AVMetadataObjectTypeInterleaved2of5Code, @"Interleaved2of5", 63 | AVMetadataObjectTypeITF14Code, @"ITF14", 64 | AVMetadataObjectTypeDataMatrixCode, @"DataMatrix", 65 | nil]; 66 | 67 | }; 68 | 69 | -(void)frameSizeChanged:(CGRect)frame bounds:(CGRect)bounds 70 | { 71 | // This is initializing the square view 72 | [TiUtils setView:self.square positionRect:bounds]; 73 | 74 | if(self.captureSession){ 75 | if(![self.captureSession isRunning]){ 76 | [self.captureSession startRunning]; 77 | 78 | if([self.proxy _hasListeners:@"stateChange"]){ 79 | NSDictionary *event = [NSDictionary dictionaryWithObjectsAndKeys: 80 | @"resumed", @"state", 81 | nil]; 82 | [self.proxy fireEvent:@"stateChange" withObject:event]; 83 | } 84 | }; 85 | }; 86 | }; 87 | 88 | - (void)turnFlashOn:(id)args 89 | { 90 | if([self.captureDevice lockForConfiguration:true]){ 91 | if([self.captureDevice isFlashModeSupported:AVCaptureFlashModeOn]){ 92 | [self.captureDevice setTorchMode:AVCaptureTorchModeOn]; 93 | self.flashOn = YES; 94 | [self.captureDevice lockForConfiguration:false]; 95 | if([self.proxy _hasListeners:@"onFlashOn"]){ 96 | [self.proxy fireEvent:@"onFlashOn"]; 97 | } 98 | }; 99 | }; 100 | }; 101 | 102 | - (void)turnFlashOff:(id)args 103 | { 104 | if([self.captureDevice lockForConfiguration:true]){ 105 | if([self.captureDevice isFlashModeSupported:AVCaptureFlashModeOn]){ 106 | [self.captureDevice setTorchMode:AVCaptureTorchModeOff]; 107 | self.flashOn = NO; 108 | [self.captureDevice lockForConfiguration:false]; 109 | if([self.proxy _hasListeners:@"onFlashOff"]){ 110 | [self.proxy fireEvent:@"onFlashOff"]; 111 | } 112 | }; 113 | }; 114 | }; 115 | 116 | // utility routine to display error alert if takePicture fails 117 | - (void)displayErrorOnMainQueue:(NSError *)error withMessage:(NSString *)message 118 | { 119 | dispatch_async(dispatch_get_main_queue(), ^(void) { 120 | UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:[NSString stringWithFormat:@"%@ (%d)", message, (int)[error code]] 121 | message:[error localizedDescription] 122 | delegate:nil 123 | cancelButtonTitle:@"Dismiss" 124 | otherButtonTitles:nil]; 125 | [alertView show]; 126 | [alertView release]; 127 | }); 128 | }; 129 | 130 | - (void)takePhoto:(id)args 131 | { 132 | 133 | AVCaptureConnection *stillImageConnection = nil; 134 | 135 | for (AVCaptureConnection *connection in self.stillImageOutput.connections) 136 | { 137 | for (AVCaptureInputPort *port in [connection inputPorts]) 138 | { 139 | if ([[port mediaType] isEqual:AVMediaTypeVideo] ) 140 | { 141 | stillImageConnection = connection; 142 | break; 143 | } 144 | } 145 | if (stillImageConnection) { break; } 146 | } 147 | 148 | UIDeviceOrientation curDeviceOrientation = [[UIDevice currentDevice] orientation]; 149 | 150 | [self.stillImageOutput captureStillImageAsynchronouslyFromConnection:stillImageConnection completionHandler: ^(CMSampleBufferRef imageSampleBuffer, NSError *error) 151 | { 152 | 153 | CFDictionaryRef exifAttachments = CMGetAttachment(imageSampleBuffer, kCGImagePropertyExifDictionary, NULL); 154 | if (exifAttachments) { 155 | NSLog(@"[INFO] imageSampleBuffer Exif attachments: %@", exifAttachments); 156 | } else { 157 | NSLog(@"[INFO] No imageSampleBuffer Exif attachments"); 158 | } 159 | 160 | NSData *imageData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageSampleBuffer]; 161 | 162 | UIImage *image = [[UIImage alloc] initWithData:imageData]; 163 | 164 | CGSize size = image.size; // this will be the full size of the screen 165 | 166 | NSLog(@"image.size : %@", NSStringFromCGSize(size)); 167 | 168 | CGFloat image_width = self.stillImage.frame.size.width*2; 169 | CGFloat image_height = self.stillImage.frame.size.height*2; 170 | 171 | CGRect cropRect = CGRectMake( 172 | 0, 173 | 0, 174 | image_width, 175 | image_height 176 | ); 177 | 178 | NSLog(@"cropRect : %@", NSStringFromCGRect(cropRect)); 179 | 180 | 181 | CGRect customImageRect = CGRectMake( 182 | -((((cropRect.size.width/size.width)*size.height)-cropRect.size.height)/2), 183 | 0, 184 | ((cropRect.size.width/size.width)*size.height), 185 | cropRect.size.width); 186 | 187 | UIGraphicsBeginImageContext(cropRect.size); 188 | CGContextRef context = UIGraphicsGetCurrentContext(); 189 | 190 | CGContextScaleCTM(context, 1.0, -1.0); 191 | CGContextRotateCTM(context, -M_PI/2); 192 | 193 | CGContextDrawImage(context, customImageRect, 194 | image.CGImage); 195 | 196 | UIImage *croppedImage = UIGraphicsGetImageFromCurrentImageContext(); 197 | UIGraphicsEndImageContext(); 198 | 199 | TiBlob *imageBlob = [[TiBlob alloc] initWithImage:[self flipImage:croppedImage]]; // maybe try image here 200 | NSDictionary *event = [NSDictionary dictionaryWithObjectsAndKeys: 201 | self.camera, @"camera", 202 | imageBlob, @"media", 203 | nil]; 204 | 205 | // HURRAH! 206 | [self.proxy fireEvent:@"success" withObject:event]; 207 | 208 | }]; 209 | }; 210 | 211 | -(UIImage *)flipImage:(UIImage *)img 212 | { 213 | UIImage* flippedImage = img; 214 | 215 | if([self.camera isEqualToString: @"front"]){ 216 | flippedImage = [UIImage imageWithCGImage:img.CGImage scale:img.scale orientation:(img.imageOrientation + 4) % 8]; 217 | }; 218 | 219 | return flippedImage; 220 | }; 221 | 222 | -(void)setCamera_:(id)value 223 | { 224 | NSString *camera = [TiUtils stringValue:value]; 225 | 226 | if (![camera isEqualToString: @"front"] && ![camera isEqualToString: @"back"]) { 227 | NSLog(@"[ERROR] Attempted to set camera that is not front or back... ignoring."); 228 | } else { 229 | self.camera = camera; 230 | 231 | [self setCaptureDevice]; 232 | 233 | NSDictionary *event = [NSDictionary dictionaryWithObjectsAndKeys: 234 | self.camera, @"camera", 235 | nil]; 236 | if([self.proxy _hasListeners:@"onCameraChange"]){ 237 | [self.proxy fireEvent:@"onCameraChange" withObject:event]; 238 | } 239 | } 240 | }; 241 | 242 | -(void)setFrontQuality_:(id)value 243 | { 244 | self.frontQuality = [self qualityFromValue:value]; 245 | }; 246 | 247 | -(void)setBackQuality_:(id)value 248 | { 249 | self.backQuality = [self qualityFromValue:value]; 250 | }; 251 | 252 | -(NSString *)qualityFromValue:(id)value 253 | { 254 | switch ([value integerValue]) 255 | { 256 | case LOW_QUALITY: 257 | return AVCaptureSessionPresetLow; 258 | break; 259 | case MEDIUM_QUALITY: 260 | return AVCaptureSessionPresetMedium; 261 | break; 262 | case HIGH_QUALITY: 263 | return AVCaptureSessionPresetHigh; 264 | break; 265 | case HD_QUALITY: 266 | return AVCaptureSessionPreset1920x1080; 267 | break; 268 | default: 269 | return AVCaptureSessionPresetHigh; 270 | break; 271 | } 272 | } 273 | 274 | -(void)pause:(id)args 275 | { 276 | if(self.captureSession){ 277 | if([self.captureSession isRunning]){ 278 | [self.captureSession stopRunning]; 279 | if([self.proxy _hasListeners:@"stateChange"]){ 280 | NSDictionary *event = [NSDictionary dictionaryWithObjectsAndKeys: 281 | @"paused", @"state", 282 | nil]; 283 | 284 | [self.proxy fireEvent:@"stateChange" withObject:event]; 285 | } 286 | } else { 287 | NSLog(@"[ERROR] Attempted to pause an already paused session... ignoring."); 288 | }; 289 | } else { 290 | NSLog(@"[ERROR] Attempted to pause the camera before it was started... ignoring."); 291 | }; 292 | }; 293 | 294 | -(void)resume:(id)args 295 | { 296 | if(self.captureSession){ 297 | if(![self.captureSession isRunning]){ 298 | [self.captureSession startRunning]; 299 | 300 | if([self.proxy _hasListeners:@"stateChange"]){ 301 | NSDictionary *event = [NSDictionary dictionaryWithObjectsAndKeys: 302 | @"resumed", @"state", 303 | nil]; 304 | 305 | [self.proxy fireEvent:@"stateChange" withObject:event]; 306 | } 307 | } else { 308 | NSLog(@"[ERROR] Attempted to resume an already running session... ignoring."); 309 | }; 310 | } else { 311 | NSLog(@"[ERROR] Attempted to resume the camera before it was started... ignoring."); 312 | }; 313 | }; 314 | 315 | -(void)setCaptureDevice 316 | { 317 | AVCaptureDevicePosition desiredPosition; 318 | NSString *quality; 319 | 320 | if ([self.camera isEqualToString: @"back"]) { 321 | desiredPosition = AVCaptureDevicePositionBack; 322 | quality = self.backQuality; 323 | } else { 324 | desiredPosition = AVCaptureDevicePositionFront; 325 | quality = self.frontQuality; 326 | }; 327 | 328 | for (AVCaptureDevice *d in [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo]) { 329 | if ([d position] == desiredPosition) { 330 | [self.captureSession beginConfiguration]; 331 | 332 | AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:d error:nil]; 333 | 334 | for (AVCaptureInput *oldInput in [self.captureSession inputs]) { 335 | [self.captureSession removeInput:oldInput]; 336 | }; 337 | 338 | // Reset to high before changing incase the new camera cannot handle an already specified preset 339 | [self.captureSession setSessionPreset:AVCaptureSessionPresetMedium]; 340 | 341 | [self.captureSession addInput:input]; 342 | 343 | [self.captureSession commitConfiguration]; 344 | 345 | // Now set it to the new session preset 346 | if ([self.captureSession canSetSessionPreset:quality] == YES) { 347 | // If you can set to this quality, do it! 348 | NSLog(@"[INFO] Setting camera quality to: %@", quality); 349 | self.captureSession.sessionPreset = quality; 350 | } else { 351 | // If not... fallback to high quality 352 | NSLog(@"[WARN]: Can not use camera quality '%@'. Defaulting to High.", quality); 353 | self.captureSession.sessionPreset = AVCaptureSessionPresetHigh; 354 | }; 355 | 356 | // Set the focus to expect a close-range if using barcode scanning 357 | if (self.detectCodes && [d isAutoFocusRangeRestrictionSupported]) { 358 | NSLog(@"[INFO]: Setting the autofocus range to near!"); 359 | 360 | if ([d lockForConfiguration:nil]) { 361 | d.autoFocusRangeRestriction = AVCaptureAutoFocusRangeRestrictionNear; 362 | d.focusMode = AVCaptureFocusModeContinuousAutoFocus; 363 | [d unlockForConfiguration]; 364 | } 365 | } 366 | 367 | break; 368 | }; 369 | }; 370 | }; 371 | 372 | -(UIView*)square 373 | { 374 | if (square == nil) { 375 | 376 | square = [[UIView alloc] initWithFrame:[self frame]]; 377 | [self addSubview:square]; 378 | 379 | self.stillImage = [[UIImageView alloc] init]; 380 | self.stillImage.frame = [square bounds]; 381 | [self addSubview:self.stillImage]; 382 | 383 | if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) { 384 | 385 | self.captureSession = [[AVCaptureSession alloc] init]; 386 | 387 | self.prevLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:self.captureSession]; 388 | 389 | // ------- rotate 390 | if(self.forceHorizontal){ 391 | UIDeviceOrientation curDeviceOrientation = [[UIDevice currentDevice] orientation]; 392 | 393 | float_t angle=0; 394 | angle=-M_PI/2; 395 | if ((long)curDeviceOrientation==4){ 396 | angle = M_PI/2; 397 | } 398 | 399 | CATransform3D transform = CATransform3DMakeRotation(angle, 0, 0, 1.0); 400 | self.prevLayer.transform =transform; 401 | curDeviceOrientation = nil; 402 | } 403 | // -------- 404 | 405 | 406 | self.prevLayer.frame = self.square.bounds; 407 | self.prevLayer.videoGravity = AVLayerVideoGravityResizeAspectFill; 408 | [self.square.layer addSublayer:self.prevLayer]; 409 | 410 | self.captureDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo]; 411 | 412 | if([self.captureDevice lockForConfiguration:true]){ 413 | 414 | if([self.captureDevice isFlashModeSupported:AVCaptureFlashModeOff]){ 415 | [self.captureDevice setFlashMode:AVCaptureFlashModeOff]; 416 | self.flashOn = NO; 417 | }; 418 | 419 | [self.captureDevice lockForConfiguration:false]; 420 | }; 421 | 422 | // Set the default camera 423 | [self setCaptureDevice]; 424 | 425 | NSError *error = nil; 426 | 427 | self.videoDataOutput = [[[AVCaptureVideoDataOutput alloc] init] autorelease]; 428 | [self.videoDataOutput setAlwaysDiscardsLateVideoFrames:YES]; // discard if the data output queue is blocked (as we process the still image) 429 | 430 | // Now do the dispatch queue .. 431 | videoDataOutputQueue = dispatch_queue_create("videoDataOutputQueue", DISPATCH_QUEUE_SERIAL); 432 | 433 | [self.videoDataOutput setSampleBufferDelegate:self queue:videoDataOutputQueue]; 434 | 435 | self.stillImageOutput = [[AVCaptureStillImageOutput alloc] init]; 436 | 437 | [self.stillImageOutput addObserver:self forKeyPath:@"capturingStillImage" options:NSKeyValueObservingOptionNew context:AVCaptureStillImageIsCapturingStillImageContext]; 438 | 439 | NSDictionary *outputSettings = [[NSDictionary alloc] initWithObjectsAndKeys: AVVideoCodecJPEG, AVVideoCodecKey, nil]; 440 | [self.stillImageOutput setOutputSettings:outputSettings]; 441 | 442 | [self.captureSession addOutput:self.stillImageOutput]; 443 | 444 | [outputSettings release]; 445 | 446 | NSDictionary *rgbOutputSettings = [NSDictionary dictionaryWithObject: 447 | [NSNumber numberWithInt:kCMPixelFormat_32BGRA] forKey:(id)kCVPixelBufferPixelFormatTypeKey]; 448 | 449 | [self.videoDataOutput setVideoSettings:rgbOutputSettings]; 450 | 451 | [self.captureSession addOutput:self.videoDataOutput]; 452 | 453 | if(self.detectCodes){ 454 | 455 | // Kosso : Add built-in 2d code detection. Requires iOS 7+ 456 | AVCaptureMetadataOutput *metadataOutput = [[AVCaptureMetadataOutput alloc] init]; 457 | [self.captureSession addOutput:metadataOutput]; 458 | [metadataOutput setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()]; 459 | 460 | if([self.barcodeTypes count] > 0){ 461 | NSMutableArray *metadataOutputTypes = [NSMutableArray array]; 462 | 463 | for(NSString * barcode in self.barcodeTypes) { 464 | if(barcode != nil){ 465 | if([self.barcodeDict objectForKey:barcode] != nil){ 466 | NSLog([NSString stringWithFormat:@"Listening for barcode type: %@", barcode]); 467 | [metadataOutputTypes addObject:[self.barcodeDict objectForKey:barcode]]; 468 | } else { 469 | NSLog([NSString stringWithFormat:@"Unknown barcode type: %@", barcode]); 470 | } 471 | } else { 472 | NSLog([NSString stringWithFormat:@"barcode is nil :("]); 473 | } 474 | } 475 | 476 | // Set these output types only 477 | [metadataOutput setMetadataObjectTypes:metadataOutputTypes]; 478 | } else { 479 | // Non set! Add them all :) 480 | [metadataOutput setMetadataObjectTypes:@[AVMetadataObjectTypeEAN8Code, AVMetadataObjectTypeCode39Mod43Code, AVMetadataObjectTypeUPCECode, AVMetadataObjectTypeCode39Code, AVMetadataObjectTypeQRCode, AVMetadataObjectTypeEAN13Code, AVMetadataObjectTypeDataMatrixCode, AVMetadataObjectTypeAztecCode]]; 481 | } 482 | 483 | // Add the scanCrop after you startRunning it 484 | if(self.scanCrop){ 485 | CGRect visibleMetadataOutputRect = [self.prevLayer metadataOutputRectOfInterestForRect:[self formatScanCrop:[self.prevLayer frame]]]; 486 | metadataOutput.rectOfInterest = visibleMetadataOutputRect; 487 | 488 | // Now should we show you a preview? 489 | if(self.scanCropPreview){ 490 | UIView* scan_overlay_view = [[UIView alloc]initWithFrame:[self formatScanCrop:[self frame]]]; 491 | scan_overlay_view.backgroundColor = [UIColor redColor]; 492 | scan_overlay_view.alpha = 0.35; 493 | 494 | [self addSubview:scan_overlay_view]; 495 | } 496 | } 497 | } 498 | 499 | [[self.videoDataOutput connectionWithMediaType:AVMediaTypeVideo] setEnabled:NO]; 500 | 501 | UIGestureRecognizer* gr = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(didTapGesture:)]; 502 | [self.square addGestureRecognizer:gr]; 503 | 504 | // and off we go! ... 505 | if(![self.captureSession isRunning]){ 506 | [self.captureSession startRunning]; 507 | 508 | if([self.proxy _hasListeners:@"stateChange"]){ 509 | NSDictionary *event = [NSDictionary dictionaryWithObjectsAndKeys: 510 | @"started", @"state", 511 | nil]; 512 | 513 | [self.proxy fireEvent:@"stateChange" withObject:event]; 514 | } 515 | } else { 516 | NSLog(@"[INFO] Attempted to start a session that's already running... ignoring."); 517 | }; 518 | 519 | } else { 520 | // If camera is NOT avaialble 521 | [self.proxy fireEvent:@"noCamera"]; 522 | }; 523 | }; 524 | 525 | return square; 526 | }; 527 | 528 | - (void)setPoint:(CGPoint)p 529 | { 530 | CGSize viewSize = self.square.bounds.size; 531 | CGPoint pointOfInterest = CGPointMake(p.y / viewSize.height, 532 | 1.0 - p.x / viewSize.width); 533 | 534 | AVCaptureDevice* videoCaptureDevice = 535 | [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo]; 536 | 537 | NSError* error = nil; 538 | if ([videoCaptureDevice lockForConfiguration:&error]) { 539 | 540 | if ([videoCaptureDevice isFocusPointOfInterestSupported] && 541 | [videoCaptureDevice isFocusModeSupported:AVCaptureFocusModeAutoFocus]) { 542 | NSLog(@"[INFO] Tap focus"); 543 | videoCaptureDevice.focusPointOfInterest = pointOfInterest; 544 | videoCaptureDevice.focusMode = AVCaptureFocusModeAutoFocus; 545 | } 546 | 547 | if ([videoCaptureDevice isExposurePointOfInterestSupported] && 548 | [videoCaptureDevice isExposureModeSupported:AVCaptureExposureModeContinuousAutoExposure]){ 549 | NSLog(@"[INFO] Tap exposure"); 550 | self.adjustingExposure = YES; 551 | videoCaptureDevice.exposurePointOfInterest = pointOfInterest; 552 | videoCaptureDevice.exposureMode = AVCaptureExposureModeContinuousAutoExposure; 553 | } 554 | 555 | [videoCaptureDevice unlockForConfiguration]; 556 | } else { 557 | NSLog(@"%s|[ERROR] %@", __PRETTY_FUNCTION__, error); 558 | } 559 | } 560 | 561 | -(CGRect)formatScanCrop:(CGRect)frame 562 | { 563 | CGFloat prev_x,prev_y,prev_width,prev_height; 564 | 565 | prev_x = [[self.scanCrop objectForKey:@"x"] floatValue]; 566 | prev_y = [[self.scanCrop objectForKey:@"y"] floatValue]; 567 | prev_width = [[self.scanCrop objectForKey:@"width"] floatValue]; 568 | prev_height = [[self.scanCrop objectForKey:@"height"] floatValue]; 569 | 570 | return CGRectMake(prev_x, prev_y, prev_width, prev_height); 571 | } 572 | 573 | - (void)didTapGesture:(UITapGestureRecognizer*)tgr 574 | { 575 | CGPoint p = [tgr locationInView:tgr.view]; 576 | [self setPoint:p]; 577 | } 578 | 579 | - (void)teardownAVCapture 580 | { 581 | 582 | // NSLog(@"[INFO] TEAR DOWN CAPTURE"); 583 | 584 | [self.captureSession removeInput:self.videoInput]; 585 | [self.captureSession removeOutput:self.videoDataOutput]; 586 | 587 | [self.captureSession removeInput:self.videoInput]; 588 | [self.captureSession removeOutput:self.videoDataOutput]; 589 | 590 | [self.captureSession stopRunning]; 591 | 592 | NSDictionary *event = [NSDictionary dictionaryWithObjectsAndKeys: 593 | @"stopped", @"state", 594 | nil]; 595 | 596 | [self.proxy fireEvent:@"stateChange" withObject:event]; 597 | 598 | [_videoDataOutput release]; 599 | if (videoDataOutputQueue) 600 | dispatch_release(videoDataOutputQueue); 601 | [self.stillImageOutput removeObserver:self forKeyPath:@"capturingStillImage"]; 602 | [self.stillImageOutput release]; 603 | [self.prevLayer removeFromSuperlayer]; 604 | [self.prevLayer release]; 605 | }; 606 | 607 | // perform a flash bulb animation using KVO to monitor the value of the capturingStillImage property of the AVCaptureStillImageOutput class 608 | - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context 609 | { 610 | if ( context == AVCaptureStillImageIsCapturingStillImageContext ) { 611 | BOOL isCapturingStillImage = [[change objectForKey:NSKeyValueChangeNewKey] boolValue]; 612 | if ( isCapturingStillImage ) { 613 | // do flash bulb like animation 614 | flashView = [[UIView alloc] initWithFrame:[self.stillImage frame]]; 615 | [flashView setBackgroundColor:[UIColor whiteColor]]; 616 | [flashView setAlpha:0.f]; 617 | 618 | [self addSubview:flashView]; 619 | // fade it in 620 | [UIView animateWithDuration:.3f 621 | animations:^{ 622 | [flashView setAlpha:1.f]; 623 | } 624 | ]; 625 | } else { 626 | // fade it out 627 | [UIView animateWithDuration:.3f 628 | animations:^{ 629 | [flashView setAlpha:0.f]; 630 | } 631 | completion:^(BOOL finished){ 632 | // get rid of it 633 | [flashView removeFromSuperview]; 634 | [flashView release]; 635 | flashView = nil; 636 | } 637 | ]; 638 | } 639 | } 640 | }; 641 | 642 | -(void)setDetectCodes_:(id)arg 643 | { 644 | self.detectCodes = [TiUtils boolValue:arg def:NO]; 645 | } 646 | 647 | 648 | -(BOOL) detectCodes { 649 | return _detectCodes; 650 | } 651 | 652 | -(void)setForceHorizontal_:(id)arg 653 | { 654 | self.forceHorizontal = [TiUtils boolValue:arg def:NO]; 655 | } 656 | 657 | 658 | -(BOOL) forceHorizontal { 659 | return _forceHorizontal; 660 | } 661 | 662 | // utility routing used during image capture to set up capture orientation 663 | - (AVCaptureVideoOrientation)avOrientationForDeviceOrientation:(UIDeviceOrientation)deviceOrientation 664 | { 665 | AVCaptureVideoOrientation result = deviceOrientation; 666 | if ( deviceOrientation == UIDeviceOrientationLandscapeLeft ) 667 | result = AVCaptureVideoOrientationLandscapeRight; 668 | else if ( deviceOrientation == UIDeviceOrientationLandscapeRight ) 669 | result = AVCaptureVideoOrientationLandscapeLeft; 670 | return result; 671 | }; 672 | 673 | #pragma mark AVCaptureMetadataOutputObjectsDelegate 674 | 675 | - (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection 676 | { 677 | 678 | for(AVMetadataObject *metadataObject in metadataObjects) 679 | { 680 | AVMetadataMachineReadableCodeObject *readableObject = (AVMetadataMachineReadableCodeObject *)metadataObject; 681 | 682 | // NSLog(@"[INFO] Code value : = %@", readableObject.stringValue); 683 | // NSLog(@"[INFO] Code type : = %@", metadataObject.type); 684 | 685 | NSString *code_type = @""; 686 | 687 | if([metadataObject.type isEqualToString:AVMetadataObjectTypeQRCode]) 688 | { 689 | code_type = @"QRCode"; 690 | } 691 | else if ([metadataObject.type isEqualToString:AVMetadataObjectTypeEAN13Code]) 692 | { 693 | code_type = @"EAN13Code"; 694 | } 695 | else if ([metadataObject.type isEqualToString:AVMetadataObjectTypeCode39Code]) 696 | { 697 | code_type = @"Code39Code"; 698 | } 699 | else if ([metadataObject.type isEqualToString:AVMetadataObjectTypeCode39Mod43Code]) 700 | { 701 | code_type = @"Code39Mod43Code"; 702 | } 703 | else if ([metadataObject.type isEqualToString:AVMetadataObjectTypeEAN8Code]) 704 | { 705 | code_type = @"EAN8Code"; 706 | } 707 | else if ([metadataObject.type isEqualToString:AVMetadataObjectTypeCode93Code]) 708 | { 709 | code_type = @"Code93Code"; 710 | } 711 | else if ([metadataObject.type isEqualToString:AVMetadataObjectTypeCode128Code]) 712 | { 713 | code_type = @"Code128Code"; 714 | } 715 | else if ([metadataObject.type isEqualToString:AVMetadataObjectTypePDF417Code]) 716 | { 717 | code_type = @"PDF417Code"; 718 | } 719 | else if ([metadataObject.type isEqualToString:AVMetadataObjectTypeAztecCode]) 720 | { 721 | code_type = @"AztecCode"; 722 | } 723 | else if ([metadataObject.type isEqualToString:AVMetadataObjectTypeInterleaved2of5Code]) 724 | { 725 | code_type = @"Interleaved2of5Code"; 726 | } 727 | else if ([metadataObject.type isEqualToString:AVMetadataObjectTypeITF14Code]) 728 | { 729 | code_type = @"ITF14Code"; 730 | } 731 | else if ([metadataObject.type isEqualToString:AVMetadataObjectTypeDataMatrixCode]) 732 | { 733 | code_type = @"DataMatrixCode"; 734 | } 735 | 736 | if([self.proxy _hasListeners:@"code"]){ 737 | NSDictionary *event = [NSDictionary dictionaryWithObjectsAndKeys: 738 | readableObject.stringValue, @"value", 739 | code_type, @"codeType", 740 | nil]; 741 | [self.proxy fireEvent:@"code" withObject:event]; 742 | } 743 | } 744 | } 745 | 746 | @end 747 | -------------------------------------------------------------------------------- /Classes/ComMfoggSquarecameraViewProxy.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Appcelerator Titanium Mobile 3 | * Copyright (c) 2009-2013 by Appcelerator, Inc. All Rights Reserved. 4 | * Licensed under the terms of the Apache Public License 5 | * Please see the LICENSE included with this distribution for details. 6 | */ 7 | #import "TiViewProxy.h" 8 | #import "TiUtils.h" 9 | 10 | @interface ComMfoggSquarecameraViewProxy : TiViewProxy { 11 | 12 | } 13 | 14 | @end 15 | -------------------------------------------------------------------------------- /Classes/ComMfoggSquarecameraViewProxy.m: -------------------------------------------------------------------------------- 1 | /** 2 | * Appcelerator Titanium Mobile 3 | * Copyright (c) 2009-2013 by Appcelerator, Inc. All Rights Reserved. 4 | * Licensed under the terms of the Apache Public License 5 | * Please see the LICENSE included with this distribution for details. 6 | */ 7 | 8 | #import "ComMfoggSquarecameraViewProxy.h" 9 | #import "ComMfoggSquarecameraView.h" 10 | #import "TiUtils.h" 11 | 12 | @implementation ComMfoggSquarecameraViewProxy 13 | 14 | #ifndef USE_VIEW_FOR_UI_METHOD 15 | #define USE_VIEW_FOR_UI_METHOD(methodname)\ 16 | -(void)methodname:(id)args\ 17 | {\ 18 | [self makeViewPerformSelector:@selector(methodname:) withObject:args createIfNeeded:YES waitUntilDone:NO];\ 19 | } 20 | #endif 21 | 22 | USE_VIEW_FOR_UI_METHOD(takePhoto); 23 | USE_VIEW_FOR_UI_METHOD(turnFlashOn); 24 | USE_VIEW_FOR_UI_METHOD(turnFlashOff); 25 | USE_VIEW_FOR_UI_METHOD(pause); 26 | USE_VIEW_FOR_UI_METHOD(resume); 27 | 28 | @end 29 | -------------------------------------------------------------------------------- /ComMfoggSquarecamera_Prefix.pch: -------------------------------------------------------------------------------- 1 | 2 | #ifdef __OBJC__ 3 | #import 4 | #endif 5 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | TODO: place your license here and we'll include it in the module distribution 2 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Place your license text here. This file will be incorporated with your app at package time. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Appcelerator Titanium :: SquareCamera 2 | 3 | An Appcelerator Titanium module that uses AVFoundation to allow for a much more customizable camera. 4 | 5 | I have wanted (multiple times now) the option of being able to customize the camera size, shape, and functionality without just using the camera overlay. This lets you do that :) 6 | 7 | * __NOTE:__ The name can be misleading, the camera __does not__ HAVE to be a square :) 8 | 9 |

Supports

10 | 11 |

Devices

12 | - iPhone (Tested with 3G, 3GS, 4, 4s, 5, 5c and 5s, 6, and 6s) 13 | - iPad (Tested with multiple iPads) 14 | - iPod Touch 15 | 16 |

iOS Versions

17 | - 6.0+ (up to the latest iOS 8) 18 | - [7.0+ for 2d code detection in module version 0.7] 19 | 20 |

Titanium SDK Versions

21 | - 3.2.0 22 | - 3.2.1 23 | - 3.2.3 24 | - 3.3.X 25 | - 3.4.0 26 | - 3.4.1 27 | - 3.4.2 28 | - 3.5.0.GA 29 | - 5.0.0.GA 30 | - 5.0.2.GA 31 | 32 | * __Note:__ I am sure it works on many more versions than this, but these are just the one's I've used 33 | 34 |

Setup

35 | 36 | Include the module in your tiapp.xml: 37 | 38 |

 39 | com.mfogg.squarecamera
 40 | 
 41 | 
42 | 43 |

Usage

44 | 45 |

 46 | var SquareCamera = require('com.mfogg.squarecamera'); // Initialize the SquareCamera module
 47 | 
 48 | // open a single window
 49 | var win = Ti.UI.createWindow({backgroundColor:"#eee"});
 50 | 
 51 | var camera_view = SquareCamera.createView({
 52 |   top: 0,
 53 |   height: 320,
 54 |   width: 320,
 55 |   backgroundColor: "#fff",
 56 |   frontQuality: SquareCamera.QUALITY_HIGH, // Optional Defaults to QUALITY_HIGH
 57 |   backQuality: SquareCamera.QUALITY_HD, // Optional Defaults to QUALITY_HD
 58 |   camera: "back" // Optional "back" or "front",
 59 |   forceHorizontal: true, // Optional sets the camera to horizontal mode if you app is horizontal only (Default false)
 60 |   detectCodes: true, // Since version 0.7 : optional boolean to activate 2d code detection. Dection fires "code" event contaning e.codeType and e.value -All codes types are supported. Will not work on iPhone 4 with iOS 7 (crashes upon adding SquareCamera to view).
 61 |   scanCrop: { // Available since v 0.8
 62 |     x: ((Ti.Platform.displayCaps.platformWidth-220)/2),
 63 |     y: ((Ti.Platform.displayCaps.platformHeight-220)/2),
 64 |     width: 220,
 65 |     height: 220
 66 |   },
 67 |   scanCropPreview: true, // Available since v 0.8
 68 |   barcodeTypes: [  // Available since v 0.8
 69 |     "UPCE",
 70 |     "UPCA",
 71 |     "EAN13",
 72 |     "CODE128"
 73 |   ]
 74 | });
 75 | 
 76 | var label_message = Ti.UI.createLabel({
 77 |     height:Ti.UI.SIZE,
 78 |     left:10,
 79 |     right:10,
 80 |     text:'ready',
 81 |     top:330,
 82 | });
 83 | 
 84 | var image_preview = Ti.UI.createImageView({
 85 |   right: 10,
 86 |   bottom: 10,
 87 |   width: 160,
 88 |   borderWidth:1,
 89 |   borderColor:'#ddd',
 90 |   height: 160,
 91 |   backgroundColor: '#444'
 92 | });
 93 | 
 94 | camera_view.addEventListener("success", function(e){
 95 |   image_preview.image = e.media;
 96 | });
 97 | 
 98 | win.add(cameraView);
 99 | // Since 0.7 : 2d code detection. Requires detectCodes:true on the camera view.
100 | camera_view.addEventListener("code", function(e){
101 |   label_message.text = e.codeType+' : '+e.value;
102 | });
103 | 
104 | win.add(cameraView);
105 | win.add(label_message);
106 | win.add(image_preview);
107 | win.open();
108 | 
109 | 
110 | * __NOTE:__ The created view (ex. 'camera_view' above) can have other views added on top of it to act as a camera overlay (exactly how you would a standard Ti.UI.view) 111 | 112 |

Camera Quality

113 | 114 | You are now able to change the quality when initializing the camera by setting frontQuality and backQuality parameters. 115 | 116 |

117 | SquareCamera.QUALITY_LOW // AVCaptureSessionPresetLow
118 | SquareCamera.QUALITY_MEDIUM // AVCaptureSessionPresetMedium
119 | SquareCamera.QUALITY_HIGH // AVCaptureSessionPresetHigh
120 | SquareCamera.QUALITY_HD // AVCaptureSessionPreset1920x1080 (Note: back camera only)
121 | 
122 | 123 |

Detect Codes

124 | 125 | As of 0.7 @kosso added the ability to detect barcodes. I've extended this functionality to allow you to: 126 | 127 |

Set a certain area of the screen that is able to detect codes using scanCrop:

128 | 129 |

130 | scanCrop: {
131 |   x: 0,
132 |   y: 0,
133 |   width: 220,
134 |   height: 220
135 | }
136 | 
137 | 
138 | 139 |

Make the scanCrop area slightly red for testing/debugging:

140 | 141 |

142 | scanCropPreview: true
143 | 
144 | 
145 | 146 |

Set which types of barcodes you'd like to scan when the view is initialized:

147 | 148 |

149 | barcodeTypes: [
150 |   "UPCE",
151 |   "EAN13"
152 | ]
153 | 
154 | Available Code Types:
155 |  UPCE
156 |  Code39
157 |  Code39Mod43
158 |  EAN13
159 |  EAN8
160 |  Code93
161 |  Code128
162 |  PDF417
163 |  QR
164 |  Aztec
165 |  Interleaved2of5
166 |  ITF14
167 |  DataMatrix
168 | 
169 | 
170 | 171 | Note: Apple supports UPC-A by returning EAN13 with a leading zero (see https://developer.apple.com/library/ios/technotes/tn2325/_index.html#//apple_ref/doc/uid/DTS40013824-CH1-IS_UPC_A_SUPPORTED_) 172 | 173 |

Functions

174 | 175 |

camera_view.takePhoto();

176 | 177 | Takes the photo (and fires the "success" event) 178 | 179 |

camera_view.turnFlashOff();

180 | 181 | Turns the flash off (and fires the "onFlashOff" event) 182 | 183 |

camera_view.turnFlashOn();

184 | 185 | Turns the flash on (and fires the "onFlashOn" event) 186 | 187 |

camera_view.setCamera(camera);

188 | 189 | Takes the parameters "front" or "back" to change the position of the camera (and fires the "onCameraChange" event) 190 | 191 |

camera_view.pause();

192 | 193 | Pauses the camera feed (and fires the "onStateChange" event with the state param "paused") 194 | 195 |

camera_view.resume();

196 | 197 | Resumes the camera feed (and fires the "onStateChange" event with the state param "resumed") 198 | 199 |

Listeners

200 | 201 |

"success"

202 | 203 | Will fire when a picture is taken. 204 | 205 |

206 | camera_view.addEventListener("success", function(e){
207 | 
208 |   Ti.API.info(JSON.stringify(e));
209 | 
210 |   Ti.API.info(e.media); // The actual blob data
211 |   Ti.API.info(e.camera); // The "front" or "back" string for where the picture was taken
212 | 
213 |   image_preview.image = e.media;
214 | });
215 | 
216 | 
217 | 218 |

"onFlashOn"

219 | 220 | Will fire when the flash is turned on. 221 | 222 |

223 | camera_view.addEventListener("onFlashOn", function(e){
224 |   Ti.API.info("Flash Turned On");
225 | });
226 | 
227 | 
228 | 229 |

"onFlashOff"

230 | 231 | Will fire when the flash is turned off. 232 | 233 |

234 | camera_view.addEventListener("onFlashOff", function(e){
235 |   Ti.API.info("Flash Turned Off");
236 | });
237 | 
238 | 
239 | 240 |

"onCameraChange"

241 | 242 | Will fire when the camera is changed between front and back 243 | 244 |

245 | camera_view.addEventListener("onCameraChange", function(e){
246 |   // e.camera returns one of:
247 |   //   "front" : using the front camera
248 |   //   "back" : using the back camera
249 | 
250 |   Ti.API.info("Now using the "+e.camera+" camera"); // See what camera we're now using
251 | });
252 | 
253 | 
254 | 255 |

"onStateChange"

256 | 257 | Will fire when the camera itself changes states 258 | 259 |

260 | // Event that listens for the camera to switch
261 | camera_view.addEventListener("stateChange", function(e){
262 |   // Camera state change event:
263 |   //   "started" : The camera has started running!
264 |   //   "stopped" : The camera has been stopped (and is being torn down)
265 |   //   "paused" : You've paused the camera
266 |   //   "resumed" : You've resumed the camera after pausing
267 | 
268 |   // e.state = The new state of the camera (one of the above options)
269 | 
270 |   Ti.API.info("Camera state changed to "+e.state);
271 | });
272 | 
273 | 
274 | 275 |

"code"

276 | 277 | Since 0.7. Fires when detectCodes:true 278 | 279 | * __Note:__ detectCodes:true crashes iPhone 4 when SquareCamera view is added and made visible 280 | 281 |

282 | camera_view.addEventListener("code", function(e){
283 |   // returns :
284 |   //   e.value : The value.
285 |   //   e.codeType : The 2D Code Type
286 |   /*
287 |   Available Code Types:
288 |    UPCECode
289 |    Code39Code
290 |    Code39Mod43Code
291 |    EAN13Code
292 |    EAN8Code
293 |    Code93Code
294 |    Code128Code
295 |    PDF417Code
296 |    QRCode
297 |    AztecCode
298 |    Interleaved2of5Code
299 |    ITF14Code
300 |    DataMatrixCode
301 |   */
302 | 
303 |   Ti.API.info("2D code detected : "+e.codeType+' : '+e.value);
304 | 
305 | });
306 | 
307 | 
308 | 309 |

Known Issues and Future Improvements

310 | 311 | 1. Android support 312 | 2. detectCodes:true crashes iPhone 4 when SquareCamera view is added and made visible. Probably won't be fixed since iPhone 4 no longer getting iOS updates from Apple. 313 | 314 | ... anything else :) 315 | 316 |

Please let me know if you'd like any additions or something isn't working!

317 | 318 |

License

319 | Do whatever you want, however you want, whenever you want. And if you find a problem on your way, let me know so I can fix it for my own apps too :) 320 | 321 |

Other Stuff

322 | 323 |

Contributors (TONS of thanks!)

324 | @Kosso 325 | @reymundolopez 326 | @yuhsak 327 | -------------------------------------------------------------------------------- /SquareCamera.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXAggregateTarget section */ 10 | 24416B8111C4CA220047AFDD /* Build & Test */ = { 11 | isa = PBXAggregateTarget; 12 | buildConfigurationList = 24416B8A11C4CA520047AFDD /* Build configuration list for PBXAggregateTarget "Build & Test" */; 13 | buildPhases = ( 14 | 24416B8011C4CA220047AFDD /* ShellScript */, 15 | ); 16 | dependencies = ( 17 | 24416B8511C4CA280047AFDD /* PBXTargetDependency */, 18 | ); 19 | name = "Build & Test"; 20 | productName = "Build & test"; 21 | }; 22 | /* End PBXAggregateTarget section */ 23 | 24 | /* Begin PBXBuildFile section */ 25 | 24DE9E1111C5FE74003F90F6 /* ComMfoggSquarecameraModuleAssets.h in Headers */ = {isa = PBXBuildFile; fileRef = 24DE9E0F11C5FE74003F90F6 /* ComMfoggSquarecameraModuleAssets.h */; }; 26 | 24DE9E1211C5FE74003F90F6 /* ComMfoggSquarecameraModuleAssets.m in Sources */ = {isa = PBXBuildFile; fileRef = 24DE9E1011C5FE74003F90F6 /* ComMfoggSquarecameraModuleAssets.m */; }; 27 | AA747D9F0F9514B9006C5449 /* ComMfoggSquarecamera_Prefix.pch in Headers */ = {isa = PBXBuildFile; fileRef = AA747D9E0F9514B9006C5449 /* ComMfoggSquarecamera_Prefix.pch */; }; 28 | F73DE1FE176295D800CF9F6E /* ComMfoggSquarecameraView.h in Headers */ = {isa = PBXBuildFile; fileRef = F73DE1FA176295D800CF9F6E /* ComMfoggSquarecameraView.h */; }; 29 | F73DE200176295D800CF9F6E /* ComMfoggSquarecameraViewProxy.h in Headers */ = {isa = PBXBuildFile; fileRef = F73DE1FC176295D800CF9F6E /* ComMfoggSquarecameraViewProxy.h */; }; 30 | F73DE201176295D800CF9F6E /* ComMfoggSquarecameraViewProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = F73DE1FD176295D800CF9F6E /* ComMfoggSquarecameraViewProxy.m */; }; 31 | F74BA96C1762B37D004CE26C /* ComMfoggSquarecameraView.m in Sources */ = {isa = PBXBuildFile; fileRef = F74BA96B1762B37D004CE26C /* ComMfoggSquarecameraView.m */; }; 32 | F7A21889176278B400BE60E9 /* ComMfoggSquarecameraModule.h in Headers */ = {isa = PBXBuildFile; fileRef = F7A21887176278B400BE60E9 /* ComMfoggSquarecameraModule.h */; }; 33 | F7A2188A176278B400BE60E9 /* ComMfoggSquarecameraModule.m in Sources */ = {isa = PBXBuildFile; fileRef = F7A21888176278B400BE60E9 /* ComMfoggSquarecameraModule.m */; }; 34 | F7A218931762834800BE60E9 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F7A2188B1762834800BE60E9 /* CoreGraphics.framework */; }; 35 | F7A218941762834800BE60E9 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F7A2188C1762834800BE60E9 /* UIKit.framework */; }; 36 | F7A218951762834800BE60E9 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F7A2188D1762834800BE60E9 /* Foundation.framework */; }; 37 | F7A218961762834800BE60E9 /* AVFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F7A2188E1762834800BE60E9 /* AVFoundation.framework */; }; 38 | F7A218971762834800BE60E9 /* CoreVideo.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F7A2188F1762834800BE60E9 /* CoreVideo.framework */; }; 39 | F7A218981762834800BE60E9 /* CoreMedia.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F7A218901762834800BE60E9 /* CoreMedia.framework */; }; 40 | F7A218991762834800BE60E9 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F7A218911762834800BE60E9 /* QuartzCore.framework */; }; 41 | F7A2189A1762834800BE60E9 /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F7A218921762834800BE60E9 /* AudioToolbox.framework */; }; 42 | /* End PBXBuildFile section */ 43 | 44 | /* Begin PBXContainerItemProxy section */ 45 | 24416B8411C4CA280047AFDD /* PBXContainerItemProxy */ = { 46 | isa = PBXContainerItemProxy; 47 | containerPortal = 0867D690FE84028FC02AAC07 /* Project object */; 48 | proxyType = 1; 49 | remoteGlobalIDString = D2AAC07D0554694100DB518D; 50 | remoteInfo = SquareCamera; 51 | }; 52 | /* End PBXContainerItemProxy section */ 53 | 54 | /* Begin PBXFileReference section */ 55 | 24DD6D1B1134B66800162E58 /* titanium.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = titanium.xcconfig; sourceTree = ""; }; 56 | 24DE9E0F11C5FE74003F90F6 /* ComMfoggSquarecameraModuleAssets.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ComMfoggSquarecameraModuleAssets.h; path = Classes/ComMfoggSquarecameraModuleAssets.h; sourceTree = ""; }; 57 | 24DE9E1011C5FE74003F90F6 /* ComMfoggSquarecameraModuleAssets.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ComMfoggSquarecameraModuleAssets.m; path = Classes/ComMfoggSquarecameraModuleAssets.m; sourceTree = ""; }; 58 | AA747D9E0F9514B9006C5449 /* ComMfoggSquarecamera_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ComMfoggSquarecamera_Prefix.pch; sourceTree = SOURCE_ROOT; }; 59 | D2AAC07E0554694100DB518D /* libComMfoggSquarecamera.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libComMfoggSquarecamera.a; sourceTree = BUILT_PRODUCTS_DIR; }; 60 | F73DE1FA176295D800CF9F6E /* ComMfoggSquarecameraView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ComMfoggSquarecameraView.h; path = Classes/ComMfoggSquarecameraView.h; sourceTree = ""; }; 61 | F73DE1FC176295D800CF9F6E /* ComMfoggSquarecameraViewProxy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ComMfoggSquarecameraViewProxy.h; path = Classes/ComMfoggSquarecameraViewProxy.h; sourceTree = ""; }; 62 | F73DE1FD176295D800CF9F6E /* ComMfoggSquarecameraViewProxy.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ComMfoggSquarecameraViewProxy.m; path = Classes/ComMfoggSquarecameraViewProxy.m; sourceTree = ""; }; 63 | F74BA96B1762B37D004CE26C /* ComMfoggSquarecameraView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ComMfoggSquarecameraView.m; path = Classes/ComMfoggSquarecameraView.m; sourceTree = ""; }; 64 | F7A21887176278B400BE60E9 /* ComMfoggSquarecameraModule.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ComMfoggSquarecameraModule.h; path = Classes/ComMfoggSquarecameraModule.h; sourceTree = ""; }; 65 | F7A21888176278B400BE60E9 /* ComMfoggSquarecameraModule.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ComMfoggSquarecameraModule.m; path = Classes/ComMfoggSquarecameraModule.m; sourceTree = ""; }; 66 | F7A2188B1762834800BE60E9 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = CoreGraphics.framework; sourceTree = ""; }; 67 | F7A2188C1762834800BE60E9 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = UIKit.framework; sourceTree = ""; }; 68 | F7A2188D1762834800BE60E9 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = Foundation.framework; sourceTree = ""; }; 69 | F7A2188E1762834800BE60E9 /* AVFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = AVFoundation.framework; sourceTree = ""; }; 70 | F7A2188F1762834800BE60E9 /* CoreVideo.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = CoreVideo.framework; sourceTree = ""; }; 71 | F7A218901762834800BE60E9 /* CoreMedia.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = CoreMedia.framework; sourceTree = ""; }; 72 | F7A218911762834800BE60E9 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = QuartzCore.framework; sourceTree = ""; }; 73 | F7A218921762834800BE60E9 /* AudioToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = AudioToolbox.framework; sourceTree = ""; }; 74 | /* End PBXFileReference section */ 75 | 76 | /* Begin PBXFrameworksBuildPhase section */ 77 | D2AAC07C0554694100DB518D /* Frameworks */ = { 78 | isa = PBXFrameworksBuildPhase; 79 | buildActionMask = 2147483647; 80 | files = ( 81 | F7A218931762834800BE60E9 /* CoreGraphics.framework in Frameworks */, 82 | F7A218941762834800BE60E9 /* UIKit.framework in Frameworks */, 83 | F7A218951762834800BE60E9 /* Foundation.framework in Frameworks */, 84 | F7A218961762834800BE60E9 /* AVFoundation.framework in Frameworks */, 85 | F7A218971762834800BE60E9 /* CoreVideo.framework in Frameworks */, 86 | F7A218981762834800BE60E9 /* CoreMedia.framework in Frameworks */, 87 | F7A218991762834800BE60E9 /* QuartzCore.framework in Frameworks */, 88 | F7A2189A1762834800BE60E9 /* AudioToolbox.framework in Frameworks */, 89 | ); 90 | runOnlyForDeploymentPostprocessing = 0; 91 | }; 92 | /* End PBXFrameworksBuildPhase section */ 93 | 94 | /* Begin PBXGroup section */ 95 | 034768DFFF38A50411DB9C8B /* Products */ = { 96 | isa = PBXGroup; 97 | children = ( 98 | D2AAC07E0554694100DB518D /* libComMfoggSquarecamera.a */, 99 | ); 100 | name = Products; 101 | sourceTree = ""; 102 | }; 103 | 0867D691FE84028FC02AAC07 /* SquareCamera */ = { 104 | isa = PBXGroup; 105 | children = ( 106 | 08FB77AEFE84172EC02AAC07 /* Classes */, 107 | 32C88DFF0371C24200C91783 /* Other Sources */, 108 | 0867D69AFE84028FC02AAC07 /* Frameworks */, 109 | 034768DFFF38A50411DB9C8B /* Products */, 110 | ); 111 | name = SquareCamera; 112 | sourceTree = ""; 113 | }; 114 | 0867D69AFE84028FC02AAC07 /* Frameworks */ = { 115 | isa = PBXGroup; 116 | children = ( 117 | F7A2188B1762834800BE60E9 /* CoreGraphics.framework */, 118 | F7A2188C1762834800BE60E9 /* UIKit.framework */, 119 | F7A2188D1762834800BE60E9 /* Foundation.framework */, 120 | F7A2188E1762834800BE60E9 /* AVFoundation.framework */, 121 | F7A2188F1762834800BE60E9 /* CoreVideo.framework */, 122 | F7A218901762834800BE60E9 /* CoreMedia.framework */, 123 | F7A218911762834800BE60E9 /* QuartzCore.framework */, 124 | F7A218921762834800BE60E9 /* AudioToolbox.framework */, 125 | ); 126 | name = Frameworks; 127 | sourceTree = ""; 128 | }; 129 | 08FB77AEFE84172EC02AAC07 /* Classes */ = { 130 | isa = PBXGroup; 131 | children = ( 132 | 24DE9E0F11C5FE74003F90F6 /* ComMfoggSquarecameraModuleAssets.h */, 133 | 24DE9E1011C5FE74003F90F6 /* ComMfoggSquarecameraModuleAssets.m */, 134 | F7A21887176278B400BE60E9 /* ComMfoggSquarecameraModule.h */, 135 | F7A21888176278B400BE60E9 /* ComMfoggSquarecameraModule.m */, 136 | F74BA96B1762B37D004CE26C /* ComMfoggSquarecameraView.m */, 137 | F73DE1FA176295D800CF9F6E /* ComMfoggSquarecameraView.h */, 138 | F73DE1FC176295D800CF9F6E /* ComMfoggSquarecameraViewProxy.h */, 139 | F73DE1FD176295D800CF9F6E /* ComMfoggSquarecameraViewProxy.m */, 140 | ); 141 | name = Classes; 142 | sourceTree = ""; 143 | }; 144 | 32C88DFF0371C24200C91783 /* Other Sources */ = { 145 | isa = PBXGroup; 146 | children = ( 147 | AA747D9E0F9514B9006C5449 /* ComMfoggSquarecamera_Prefix.pch */, 148 | 24DD6D1B1134B66800162E58 /* titanium.xcconfig */, 149 | ); 150 | name = "Other Sources"; 151 | sourceTree = ""; 152 | }; 153 | /* End PBXGroup section */ 154 | 155 | /* Begin PBXHeadersBuildPhase section */ 156 | D2AAC07A0554694100DB518D /* Headers */ = { 157 | isa = PBXHeadersBuildPhase; 158 | buildActionMask = 2147483647; 159 | files = ( 160 | AA747D9F0F9514B9006C5449 /* ComMfoggSquarecamera_Prefix.pch in Headers */, 161 | 24DE9E1111C5FE74003F90F6 /* ComMfoggSquarecameraModuleAssets.h in Headers */, 162 | F7A21889176278B400BE60E9 /* ComMfoggSquarecameraModule.h in Headers */, 163 | F73DE1FE176295D800CF9F6E /* ComMfoggSquarecameraView.h in Headers */, 164 | F73DE200176295D800CF9F6E /* ComMfoggSquarecameraViewProxy.h in Headers */, 165 | ); 166 | runOnlyForDeploymentPostprocessing = 0; 167 | }; 168 | /* End PBXHeadersBuildPhase section */ 169 | 170 | /* Begin PBXNativeTarget section */ 171 | D2AAC07D0554694100DB518D /* SquareCamera */ = { 172 | isa = PBXNativeTarget; 173 | buildConfigurationList = 1DEB921E08733DC00010E9CD /* Build configuration list for PBXNativeTarget "SquareCamera" */; 174 | buildPhases = ( 175 | D2AAC07A0554694100DB518D /* Headers */, 176 | D2AAC07B0554694100DB518D /* Sources */, 177 | D2AAC07C0554694100DB518D /* Frameworks */, 178 | ); 179 | buildRules = ( 180 | ); 181 | dependencies = ( 182 | ); 183 | name = SquareCamera; 184 | productName = SquareCamera; 185 | productReference = D2AAC07E0554694100DB518D /* libComMfoggSquarecamera.a */; 186 | productType = "com.apple.product-type.library.static"; 187 | }; 188 | /* End PBXNativeTarget section */ 189 | 190 | /* Begin PBXProject section */ 191 | 0867D690FE84028FC02AAC07 /* Project object */ = { 192 | isa = PBXProject; 193 | attributes = { 194 | LastUpgradeCheck = 0610; 195 | }; 196 | buildConfigurationList = 1DEB922208733DC00010E9CD /* Build configuration list for PBXProject "SquareCamera" */; 197 | compatibilityVersion = "Xcode 3.2"; 198 | developmentRegion = English; 199 | hasScannedForEncodings = 1; 200 | knownRegions = ( 201 | English, 202 | Japanese, 203 | French, 204 | German, 205 | ); 206 | mainGroup = 0867D691FE84028FC02AAC07 /* SquareCamera */; 207 | productRefGroup = 034768DFFF38A50411DB9C8B /* Products */; 208 | projectDirPath = ""; 209 | projectRoot = ""; 210 | targets = ( 211 | D2AAC07D0554694100DB518D /* SquareCamera */, 212 | 24416B8111C4CA220047AFDD /* Build & Test */, 213 | ); 214 | }; 215 | /* End PBXProject section */ 216 | 217 | /* Begin PBXShellScriptBuildPhase section */ 218 | 24416B8011C4CA220047AFDD /* ShellScript */ = { 219 | isa = PBXShellScriptBuildPhase; 220 | buildActionMask = 2147483647; 221 | files = ( 222 | ); 223 | inputPaths = ( 224 | ); 225 | outputPaths = ( 226 | ); 227 | runOnlyForDeploymentPostprocessing = 0; 228 | shellPath = /bin/sh; 229 | shellScript = "# shell script goes here\n\npython \"${TITANIUM_SDK}/titanium.py\" run --dir=\"${PROJECT_DIR}\"\nexit $?\n"; 230 | }; 231 | /* End PBXShellScriptBuildPhase section */ 232 | 233 | /* Begin PBXSourcesBuildPhase section */ 234 | D2AAC07B0554694100DB518D /* Sources */ = { 235 | isa = PBXSourcesBuildPhase; 236 | buildActionMask = 2147483647; 237 | files = ( 238 | 24DE9E1211C5FE74003F90F6 /* ComMfoggSquarecameraModuleAssets.m in Sources */, 239 | F7A2188A176278B400BE60E9 /* ComMfoggSquarecameraModule.m in Sources */, 240 | F73DE201176295D800CF9F6E /* ComMfoggSquarecameraViewProxy.m in Sources */, 241 | F74BA96C1762B37D004CE26C /* ComMfoggSquarecameraView.m in Sources */, 242 | ); 243 | runOnlyForDeploymentPostprocessing = 0; 244 | }; 245 | /* End PBXSourcesBuildPhase section */ 246 | 247 | /* Begin PBXTargetDependency section */ 248 | 24416B8511C4CA280047AFDD /* PBXTargetDependency */ = { 249 | isa = PBXTargetDependency; 250 | target = D2AAC07D0554694100DB518D /* SquareCamera */; 251 | targetProxy = 24416B8411C4CA280047AFDD /* PBXContainerItemProxy */; 252 | }; 253 | /* End PBXTargetDependency section */ 254 | 255 | /* Begin XCBuildConfiguration section */ 256 | 1DEB921F08733DC00010E9CD /* Debug */ = { 257 | isa = XCBuildConfiguration; 258 | baseConfigurationReference = 24DD6D1B1134B66800162E58 /* titanium.xcconfig */; 259 | buildSettings = { 260 | CODE_SIGN_IDENTITY = "iPhone Developer"; 261 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 262 | DSTROOT = /tmp/ComMfoggSquarecamera.dst; 263 | FRAMEWORK_SEARCH_PATHS = ( 264 | "$(inherited)", 265 | "\"$(SRCROOT)\"", 266 | ); 267 | GCC_C_LANGUAGE_STANDARD = c99; 268 | GCC_OPTIMIZATION_LEVEL = 0; 269 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 270 | GCC_PREFIX_HEADER = ComMfoggSquarecamera_Prefix.pch; 271 | GCC_PREPROCESSOR_DEFINITIONS = "TI_VERSION=$(TI_VERSION)"; 272 | GCC_TREAT_WARNINGS_AS_ERRORS = NO; 273 | GCC_VERSION = ""; 274 | GCC_WARN_ABOUT_RETURN_TYPE = NO; 275 | GCC_WARN_MISSING_PARENTHESES = NO; 276 | GCC_WARN_SHADOW = NO; 277 | GCC_WARN_STRICT_SELECTOR_MATCH = NO; 278 | GCC_WARN_UNUSED_FUNCTION = YES; 279 | GCC_WARN_UNUSED_PARAMETER = NO; 280 | GCC_WARN_UNUSED_VALUE = NO; 281 | GCC_WARN_UNUSED_VARIABLE = NO; 282 | INSTALL_PATH = /usr/local/lib; 283 | LIBRARY_SEARCH_PATHS = ""; 284 | OTHER_CFLAGS = ( 285 | "-DDEBUG", 286 | "-DTI_POST_1_2", 287 | ); 288 | OTHER_LDFLAGS = "-ObjC"; 289 | PRODUCT_NAME = ComMfoggSquarecamera; 290 | PROVISIONING_PROFILE = ""; 291 | "PROVISIONING_PROFILE[sdk=iphoneos*]" = ""; 292 | RUN_CLANG_STATIC_ANALYZER = NO; 293 | SDKROOT = iphoneos; 294 | USER_HEADER_SEARCH_PATHS = ""; 295 | }; 296 | name = Debug; 297 | }; 298 | 1DEB922008733DC00010E9CD /* Release */ = { 299 | isa = XCBuildConfiguration; 300 | baseConfigurationReference = 24DD6D1B1134B66800162E58 /* titanium.xcconfig */; 301 | buildSettings = { 302 | ALWAYS_SEARCH_USER_PATHS = NO; 303 | DSTROOT = /tmp/ComMfoggSquarecamera.dst; 304 | FRAMEWORK_SEARCH_PATHS = ( 305 | "$(inherited)", 306 | "\"$(SRCROOT)\"", 307 | ); 308 | GCC_C_LANGUAGE_STANDARD = c99; 309 | GCC_MODEL_TUNING = G5; 310 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 311 | GCC_PREFIX_HEADER = ComMfoggSquarecamera_Prefix.pch; 312 | GCC_PREPROCESSOR_DEFINITIONS = "TI_VERSION=$(TI_VERSION)"; 313 | GCC_TREAT_WARNINGS_AS_ERRORS = NO; 314 | GCC_VERSION = ""; 315 | GCC_WARN_ABOUT_RETURN_TYPE = NO; 316 | GCC_WARN_MISSING_PARENTHESES = NO; 317 | GCC_WARN_SHADOW = NO; 318 | GCC_WARN_STRICT_SELECTOR_MATCH = NO; 319 | GCC_WARN_UNUSED_FUNCTION = YES; 320 | GCC_WARN_UNUSED_PARAMETER = NO; 321 | GCC_WARN_UNUSED_VALUE = NO; 322 | GCC_WARN_UNUSED_VARIABLE = NO; 323 | INSTALL_PATH = /usr/local/lib; 324 | IPHONEOS_DEPLOYMENT_TARGET = 4.0; 325 | LIBRARY_SEARCH_PATHS = ""; 326 | OTHER_CFLAGS = "-DTI_POST_1_2"; 327 | OTHER_LDFLAGS = "-ObjC"; 328 | PRODUCT_NAME = ComMfoggSquarecamera; 329 | RUN_CLANG_STATIC_ANALYZER = NO; 330 | SDKROOT = iphoneos; 331 | USER_HEADER_SEARCH_PATHS = ""; 332 | }; 333 | name = Release; 334 | }; 335 | 1DEB922308733DC00010E9CD /* Debug */ = { 336 | isa = XCBuildConfiguration; 337 | baseConfigurationReference = 24DD6D1B1134B66800162E58 /* titanium.xcconfig */; 338 | buildSettings = { 339 | CODE_SIGN_IDENTITY = "iPhone Developer"; 340 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 341 | DSTROOT = /tmp/ComMfoggSquarecamera.dst; 342 | GCC_C_LANGUAGE_STANDARD = c99; 343 | GCC_OPTIMIZATION_LEVEL = 0; 344 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 345 | GCC_PREFIX_HEADER = ComMfoggSquarecamera_Prefix.pch; 346 | GCC_PREPROCESSOR_DEFINITIONS = "TI_VERSION=$(TI_VERSION)"; 347 | GCC_TREAT_WARNINGS_AS_ERRORS = NO; 348 | GCC_VERSION = ""; 349 | GCC_WARN_ABOUT_RETURN_TYPE = NO; 350 | GCC_WARN_MISSING_PARENTHESES = NO; 351 | GCC_WARN_SHADOW = NO; 352 | GCC_WARN_STRICT_SELECTOR_MATCH = NO; 353 | GCC_WARN_UNUSED_FUNCTION = YES; 354 | GCC_WARN_UNUSED_PARAMETER = NO; 355 | GCC_WARN_UNUSED_VALUE = NO; 356 | GCC_WARN_UNUSED_VARIABLE = NO; 357 | INSTALL_PATH = /usr/local/lib; 358 | IPHONEOS_DEPLOYMENT_TARGET = 6.0; 359 | ONLY_ACTIVE_ARCH = YES; 360 | OTHER_CFLAGS = ( 361 | "-DDEBUG", 362 | "-DTI_POST_1_2", 363 | ); 364 | OTHER_LDFLAGS = "-ObjC"; 365 | PRODUCT_NAME = ComMfoggSquarecamera; 366 | PROVISIONING_PROFILE = ""; 367 | "PROVISIONING_PROFILE[sdk=iphoneos*]" = ""; 368 | RUN_CLANG_STATIC_ANALYZER = NO; 369 | SDKROOT = iphoneos; 370 | USER_HEADER_SEARCH_PATHS = ""; 371 | }; 372 | name = Debug; 373 | }; 374 | 1DEB922408733DC00010E9CD /* Release */ = { 375 | isa = XCBuildConfiguration; 376 | baseConfigurationReference = 24DD6D1B1134B66800162E58 /* titanium.xcconfig */; 377 | buildSettings = { 378 | ALWAYS_SEARCH_USER_PATHS = NO; 379 | DSTROOT = /tmp/ComMfoggSquarecamera.dst; 380 | GCC_C_LANGUAGE_STANDARD = c99; 381 | GCC_MODEL_TUNING = G5; 382 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 383 | GCC_PREFIX_HEADER = ComMfoggSquarecamera_Prefix.pch; 384 | GCC_PREPROCESSOR_DEFINITIONS = "TI_VERSION=$(TI_VERSION)"; 385 | GCC_TREAT_WARNINGS_AS_ERRORS = NO; 386 | GCC_VERSION = ""; 387 | GCC_WARN_ABOUT_RETURN_TYPE = NO; 388 | GCC_WARN_MISSING_PARENTHESES = NO; 389 | GCC_WARN_SHADOW = NO; 390 | GCC_WARN_STRICT_SELECTOR_MATCH = NO; 391 | GCC_WARN_UNUSED_FUNCTION = YES; 392 | GCC_WARN_UNUSED_PARAMETER = NO; 393 | GCC_WARN_UNUSED_VALUE = NO; 394 | GCC_WARN_UNUSED_VARIABLE = NO; 395 | INSTALL_PATH = /usr/local/lib; 396 | IPHONEOS_DEPLOYMENT_TARGET = 6.0; 397 | OTHER_CFLAGS = "-DTI_POST_1_2"; 398 | OTHER_LDFLAGS = "-ObjC"; 399 | PRODUCT_NAME = ComMfoggSquarecamera; 400 | RUN_CLANG_STATIC_ANALYZER = NO; 401 | SDKROOT = iphoneos; 402 | USER_HEADER_SEARCH_PATHS = ""; 403 | }; 404 | name = Release; 405 | }; 406 | 24416B8211C4CA220047AFDD /* Debug */ = { 407 | isa = XCBuildConfiguration; 408 | baseConfigurationReference = 24DD6D1B1134B66800162E58 /* titanium.xcconfig */; 409 | buildSettings = { 410 | COPY_PHASE_STRIP = NO; 411 | GCC_DYNAMIC_NO_PIC = NO; 412 | GCC_OPTIMIZATION_LEVEL = 0; 413 | PRODUCT_NAME = "Build & test"; 414 | }; 415 | name = Debug; 416 | }; 417 | 24416B8311C4CA220047AFDD /* Release */ = { 418 | isa = XCBuildConfiguration; 419 | baseConfigurationReference = 24DD6D1B1134B66800162E58 /* titanium.xcconfig */; 420 | buildSettings = { 421 | COPY_PHASE_STRIP = YES; 422 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 423 | GCC_ENABLE_FIX_AND_CONTINUE = NO; 424 | PRODUCT_NAME = "Build & test"; 425 | ZERO_LINK = NO; 426 | }; 427 | name = Release; 428 | }; 429 | /* End XCBuildConfiguration section */ 430 | 431 | /* Begin XCConfigurationList section */ 432 | 1DEB921E08733DC00010E9CD /* Build configuration list for PBXNativeTarget "SquareCamera" */ = { 433 | isa = XCConfigurationList; 434 | buildConfigurations = ( 435 | 1DEB921F08733DC00010E9CD /* Debug */, 436 | 1DEB922008733DC00010E9CD /* Release */, 437 | ); 438 | defaultConfigurationIsVisible = 0; 439 | defaultConfigurationName = Release; 440 | }; 441 | 1DEB922208733DC00010E9CD /* Build configuration list for PBXProject "SquareCamera" */ = { 442 | isa = XCConfigurationList; 443 | buildConfigurations = ( 444 | 1DEB922308733DC00010E9CD /* Debug */, 445 | 1DEB922408733DC00010E9CD /* Release */, 446 | ); 447 | defaultConfigurationIsVisible = 0; 448 | defaultConfigurationName = Release; 449 | }; 450 | 24416B8A11C4CA520047AFDD /* Build configuration list for PBXAggregateTarget "Build & Test" */ = { 451 | isa = XCConfigurationList; 452 | buildConfigurations = ( 453 | 24416B8211C4CA220047AFDD /* Debug */, 454 | 24416B8311C4CA220047AFDD /* Release */, 455 | ); 456 | defaultConfigurationIsVisible = 0; 457 | defaultConfigurationName = Release; 458 | }; 459 | /* End XCConfigurationList section */ 460 | }; 461 | rootObject = 0867D690FE84028FC02AAC07 /* Project object */; 462 | } 463 | -------------------------------------------------------------------------------- /SquareCamera.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /SquareCamera.xcodeproj/project.xcworkspace/xcshareddata/SquareCamera.xccheckout: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDESourceControlProjectFavoriteDictionaryKey 6 | 7 | IDESourceControlProjectIdentifier 8 | 097B2CDC-C548-479D-9230-98B5E872D50D 9 | IDESourceControlProjectName 10 | SquareCamera 11 | IDESourceControlProjectOriginsDictionary 12 | 13 | 46306E89B77703788D338366CDD8BB9E9966CB60 14 | github.com:mikefogg/SquareCamera.git 15 | 16 | IDESourceControlProjectPath 17 | SquareCamera.xcodeproj 18 | IDESourceControlProjectRelativeInstallPathDictionary 19 | 20 | 46306E89B77703788D338366CDD8BB9E9966CB60 21 | ../.. 22 | 23 | IDESourceControlProjectURL 24 | github.com:mikefogg/SquareCamera.git 25 | IDESourceControlProjectVersion 26 | 111 27 | IDESourceControlProjectWCCIdentifier 28 | 46306E89B77703788D338366CDD8BB9E9966CB60 29 | IDESourceControlProjectWCConfigurations 30 | 31 | 32 | IDESourceControlRepositoryExtensionIdentifierKey 33 | public.vcs.git 34 | IDESourceControlWCCIdentifierKey 35 | 46306E89B77703788D338366CDD8BB9E9966CB60 36 | IDESourceControlWCCName 37 | SquareCamera 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /SquareCamera.xcodeproj/project.xcworkspace/xcuserdata/USuck.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikefogg/SquareCamera/032d632b19929a4596177c6e9029bc0deb78c06e/SquareCamera.xcodeproj/project.xcworkspace/xcuserdata/USuck.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /SquareCamera.xcodeproj/project.xcworkspace/xcuserdata/mfogg.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikefogg/SquareCamera/032d632b19929a4596177c6e9029bc0deb78c06e/SquareCamera.xcodeproj/project.xcworkspace/xcuserdata/mfogg.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /SquareCamera.xcodeproj/project.xcworkspace/xcuserdata/mfogg.xcuserdatad/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | BuildLocationStyle 6 | UseAppPreferences 7 | CustomBuildLocationType 8 | RelativeToDerivedData 9 | DerivedDataLocationStyle 10 | Default 11 | HasAskedToTakeAutomaticSnapshotBeforeSignificantChanges 12 | 13 | IssueFilterStyle 14 | ShowActiveSchemeOnly 15 | LiveSourceIssuesEnabled 16 | 17 | SnapshotAutomaticallyBeforeSignificantChanges 18 | 19 | SnapshotLocationStyle 20 | Default 21 | 22 | 23 | -------------------------------------------------------------------------------- /SquareCamera.xcodeproj/xcuserdata/USuck.xcuserdatad/xcschemes/Build & Test.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 42 | 43 | 49 | 50 | 51 | 52 | 53 | 54 | 60 | 61 | 67 | 68 | 69 | 70 | 72 | 73 | 76 | 77 | 78 | -------------------------------------------------------------------------------- /SquareCamera.xcodeproj/xcuserdata/USuck.xcuserdatad/xcschemes/SquareCamera.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 42 | 43 | 49 | 50 | 51 | 52 | 53 | 54 | 60 | 61 | 67 | 68 | 69 | 70 | 72 | 73 | 76 | 77 | 78 | -------------------------------------------------------------------------------- /SquareCamera.xcodeproj/xcuserdata/USuck.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | Build & Test.xcscheme 8 | 9 | orderHint 10 | 1 11 | 12 | SquareCamera.xcscheme 13 | 14 | orderHint 15 | 0 16 | 17 | 18 | SuppressBuildableAutocreation 19 | 20 | 24416B8111C4CA220047AFDD 21 | 22 | primary 23 | 24 | 25 | D2AAC07D0554694100DB518D 26 | 27 | primary 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /SquareCamera.xcodeproj/xcuserdata/mfogg.xcuserdatad/xcdebugger/Breakpoints.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /SquareCamera.xcodeproj/xcuserdata/mfogg.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 8 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /SquareCamera.xcodeproj/xcuserdata/mfogg.xcuserdatad/xcschemes/Build & Test.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 42 | 43 | 49 | 50 | 51 | 52 | 53 | 54 | 60 | 61 | 63 | 64 | 67 | 68 | 69 | -------------------------------------------------------------------------------- /SquareCamera.xcodeproj/xcuserdata/mfogg.xcuserdatad/xcschemes/SquareCamera.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 42 | 43 | 49 | 50 | 51 | 52 | 53 | 54 | 60 | 61 | 63 | 64 | 67 | 68 | 69 | -------------------------------------------------------------------------------- /SquareCamera.xcodeproj/xcuserdata/mfogg.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | Build & Test.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | SquareCamera.xcscheme 13 | 14 | orderHint 15 | 1 16 | 17 | 18 | SuppressBuildableAutocreation 19 | 20 | 24416B8111C4CA220047AFDD 21 | 22 | primary 23 | 24 | 25 | D2AAC07D0554694100DB518D 26 | 27 | primary 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /assets/README: -------------------------------------------------------------------------------- 1 | Place your assets like PNG files in this directory and they will be packaged with your module. 2 | 3 | If you create a file named com.mfogg.squarecamera.js in this directory, it will be 4 | compiled and used as your module. This allows you to run pure Javascript 5 | modules that are pre-compiled. 6 | 7 | -------------------------------------------------------------------------------- /build.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # Appcelerator Titanium Module Packager 4 | # 5 | # 6 | import os, subprocess, sys, glob, string 7 | import zipfile 8 | from datetime import date 9 | 10 | cwd = os.path.abspath(os.path.dirname(sys._getframe(0).f_code.co_filename)) 11 | os.chdir(cwd) 12 | required_module_keys = ['name','version','moduleid','description','copyright','license','copyright','platform','minsdk'] 13 | module_defaults = { 14 | 'description':'My module', 15 | 'author': 'Your Name', 16 | 'license' : 'Specify your license', 17 | 'copyright' : 'Copyright (c) %s by Your Company' % str(date.today().year), 18 | } 19 | module_license_default = "TODO: place your license here and we'll include it in the module distribution" 20 | 21 | def find_sdk(config): 22 | sdk = config['TITANIUM_SDK'] 23 | return os.path.expandvars(os.path.expanduser(sdk)) 24 | 25 | def replace_vars(config,token): 26 | idx = token.find('$(') 27 | while idx != -1: 28 | idx2 = token.find(')',idx+2) 29 | if idx2 == -1: break 30 | key = token[idx+2:idx2] 31 | if not config.has_key(key): break 32 | token = token.replace('$(%s)' % key, config[key]) 33 | idx = token.find('$(') 34 | return token 35 | 36 | 37 | def read_ti_xcconfig(): 38 | contents = open(os.path.join(cwd,'titanium.xcconfig')).read() 39 | config = {} 40 | for line in contents.splitlines(False): 41 | line = line.strip() 42 | if line[0:2]=='//': continue 43 | idx = line.find('=') 44 | if idx > 0: 45 | key = line[0:idx].strip() 46 | value = line[idx+1:].strip() 47 | config[key] = replace_vars(config,value) 48 | return config 49 | 50 | def generate_doc(config): 51 | docdir = os.path.join(cwd,'documentation') 52 | if not os.path.exists(docdir): 53 | print "Couldn't find documentation file at: %s" % docdir 54 | return None 55 | 56 | try: 57 | import markdown2 as markdown 58 | except ImportError: 59 | import markdown 60 | documentation = [] 61 | for file in os.listdir(docdir): 62 | if file in ignoreFiles or os.path.isdir(os.path.join(docdir, file)): 63 | continue 64 | md = open(os.path.join(docdir,file)).read() 65 | html = markdown.markdown(md) 66 | documentation.append({file:html}); 67 | return documentation 68 | 69 | def compile_js(manifest,config): 70 | js_file = os.path.join(cwd,'assets','com.mfogg.squarecamera.js') 71 | if not os.path.exists(js_file): return 72 | 73 | from compiler import Compiler 74 | try: 75 | import json 76 | except: 77 | import simplejson as json 78 | 79 | compiler = Compiler(cwd, manifest['moduleid'], manifest['name'], 'commonjs') 80 | root_asset, module_assets = compiler.compile_module() 81 | 82 | root_asset_content = """ 83 | %s 84 | 85 | return filterDataInRange([NSData dataWithBytesNoCopy:data length:sizeof(data) freeWhenDone:NO], ranges[0]); 86 | """ % root_asset 87 | 88 | module_asset_content = """ 89 | %s 90 | 91 | NSNumber *index = [map objectForKey:path]; 92 | if (index == nil) { 93 | return nil; 94 | } 95 | return filterDataInRange([NSData dataWithBytesNoCopy:data length:sizeof(data) freeWhenDone:NO], ranges[index.integerValue]); 96 | """ % module_assets 97 | 98 | from tools import splice_code 99 | 100 | assets_router = os.path.join(cwd,'Classes','ComMfoggSquarecameraModuleAssets.m') 101 | splice_code(assets_router, 'asset', root_asset_content) 102 | splice_code(assets_router, 'resolve_asset', module_asset_content) 103 | 104 | # Generate the exports after crawling all of the available JS source 105 | exports = open('metadata.json','w') 106 | json.dump({'exports':compiler.exports }, exports) 107 | exports.close() 108 | 109 | def die(msg): 110 | print msg 111 | sys.exit(1) 112 | 113 | def warn(msg): 114 | print "[WARN] %s" % msg 115 | 116 | def validate_license(): 117 | c = open(os.path.join(cwd,'LICENSE')).read() 118 | if c.find(module_license_default)!=-1: 119 | warn('please update the LICENSE file with your license text before distributing') 120 | 121 | def validate_manifest(): 122 | path = os.path.join(cwd,'manifest') 123 | f = open(path) 124 | if not os.path.exists(path): die("missing %s" % path) 125 | manifest = {} 126 | for line in f.readlines(): 127 | line = line.strip() 128 | if line[0:1]=='#': continue 129 | if line.find(':') < 0: continue 130 | key,value = line.split(':') 131 | manifest[key.strip()]=value.strip() 132 | for key in required_module_keys: 133 | if not manifest.has_key(key): die("missing required manifest key '%s'" % key) 134 | if module_defaults.has_key(key): 135 | defvalue = module_defaults[key] 136 | curvalue = manifest[key] 137 | if curvalue==defvalue: warn("please update the manifest key: '%s' to a non-default value" % key) 138 | return manifest,path 139 | 140 | ignoreFiles = ['.DS_Store','.gitignore','libTitanium.a','titanium.jar','README'] 141 | ignoreDirs = ['.DS_Store','.svn','.git','CVSROOT'] 142 | 143 | def zip_dir(zf,dir,basepath,ignoreExt=[]): 144 | if not os.path.exists(dir): return 145 | for root, dirs, files in os.walk(dir): 146 | for name in ignoreDirs: 147 | if name in dirs: 148 | dirs.remove(name) # don't visit ignored directories 149 | for file in files: 150 | if file in ignoreFiles: continue 151 | e = os.path.splitext(file) 152 | if len(e) == 2 and e[1] in ignoreExt: continue 153 | from_ = os.path.join(root, file) 154 | to_ = from_.replace(dir, '%s/%s'%(basepath,dir), 1) 155 | zf.write(from_, to_) 156 | 157 | def glob_libfiles(): 158 | files = [] 159 | for libfile in glob.glob('build/**/*.a'): 160 | if libfile.find('Release-')!=-1: 161 | files.append(libfile) 162 | return files 163 | 164 | def build_module(manifest,config): 165 | from tools import ensure_dev_path 166 | ensure_dev_path() 167 | 168 | rc = os.system("xcodebuild -sdk iphoneos -configuration Release") 169 | if rc != 0: 170 | die("xcodebuild failed") 171 | rc = os.system("xcodebuild -sdk iphonesimulator -configuration Release") 172 | if rc != 0: 173 | die("xcodebuild failed") 174 | # build the merged library using lipo 175 | moduleid = manifest['moduleid'] 176 | libpaths = '' 177 | for libfile in glob_libfiles(): 178 | libpaths+='%s ' % libfile 179 | 180 | os.system("lipo %s -create -output build/lib%s.a" %(libpaths,moduleid)) 181 | 182 | def package_module(manifest,mf,config): 183 | name = manifest['name'].lower() 184 | moduleid = manifest['moduleid'].lower() 185 | version = manifest['version'] 186 | modulezip = '%s-iphone-%s.zip' % (moduleid,version) 187 | if os.path.exists(modulezip): os.remove(modulezip) 188 | zf = zipfile.ZipFile(modulezip, 'w', zipfile.ZIP_DEFLATED) 189 | modulepath = 'modules/iphone/%s/%s' % (moduleid,version) 190 | zf.write(mf,'%s/manifest' % modulepath) 191 | libname = 'lib%s.a' % moduleid 192 | zf.write('build/%s' % libname, '%s/%s' % (modulepath,libname)) 193 | docs = generate_doc(config) 194 | if docs!=None: 195 | for doc in docs: 196 | for file, html in doc.iteritems(): 197 | filename = string.replace(file,'.md','.html') 198 | zf.writestr('%s/documentation/%s'%(modulepath,filename),html) 199 | zip_dir(zf,'assets',modulepath,['.pyc','.js']) 200 | zip_dir(zf,'example',modulepath,['.pyc']) 201 | zip_dir(zf,'platform',modulepath,['.pyc','.js']) 202 | zf.write('LICENSE','%s/LICENSE' % modulepath) 203 | zf.write('module.xcconfig','%s/module.xcconfig' % modulepath) 204 | exports_file = 'metadata.json' 205 | if os.path.exists(exports_file): 206 | zf.write(exports_file, '%s/%s' % (modulepath, exports_file)) 207 | zf.close() 208 | 209 | 210 | if __name__ == '__main__': 211 | manifest,mf = validate_manifest() 212 | validate_license() 213 | config = read_ti_xcconfig() 214 | 215 | sdk = find_sdk(config) 216 | sys.path.insert(0,os.path.join(sdk,'iphone')) 217 | sys.path.append(os.path.join(sdk, "common")) 218 | 219 | compile_js(manifest,config) 220 | build_module(manifest,config) 221 | package_module(manifest,mf,config) 222 | sys.exit(0) 223 | 224 | -------------------------------------------------------------------------------- /dist/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikefogg/SquareCamera/032d632b19929a4596177c6e9029bc0deb78c06e/dist/.DS_Store -------------------------------------------------------------------------------- /dist/com.mfogg.squarecamera-iphone-0.2.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikefogg/SquareCamera/032d632b19929a4596177c6e9029bc0deb78c06e/dist/com.mfogg.squarecamera-iphone-0.2.zip -------------------------------------------------------------------------------- /dist/com.mfogg.squarecamera-iphone-0.3.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikefogg/SquareCamera/032d632b19929a4596177c6e9029bc0deb78c06e/dist/com.mfogg.squarecamera-iphone-0.3.zip -------------------------------------------------------------------------------- /dist/com.mfogg.squarecamera-iphone-0.4.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikefogg/SquareCamera/032d632b19929a4596177c6e9029bc0deb78c06e/dist/com.mfogg.squarecamera-iphone-0.4.zip -------------------------------------------------------------------------------- /dist/com.mfogg.squarecamera-iphone-0.5.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikefogg/SquareCamera/032d632b19929a4596177c6e9029bc0deb78c06e/dist/com.mfogg.squarecamera-iphone-0.5.zip -------------------------------------------------------------------------------- /dist/com.mfogg.squarecamera-iphone-0.6.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikefogg/SquareCamera/032d632b19929a4596177c6e9029bc0deb78c06e/dist/com.mfogg.squarecamera-iphone-0.6.zip -------------------------------------------------------------------------------- /dist/com.mfogg.squarecamera-iphone-0.7.1.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikefogg/SquareCamera/032d632b19929a4596177c6e9029bc0deb78c06e/dist/com.mfogg.squarecamera-iphone-0.7.1.zip -------------------------------------------------------------------------------- /dist/com.mfogg.squarecamera-iphone-0.7.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikefogg/SquareCamera/032d632b19929a4596177c6e9029bc0deb78c06e/dist/com.mfogg.squarecamera-iphone-0.7.zip -------------------------------------------------------------------------------- /dist/com.mfogg.squarecamera-iphone-0.8.0.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikefogg/SquareCamera/032d632b19929a4596177c6e9029bc0deb78c06e/dist/com.mfogg.squarecamera-iphone-0.8.0.zip -------------------------------------------------------------------------------- /documentation/index.md: -------------------------------------------------------------------------------- 1 | Appcelerator Titanium :: SquareCamera 2 | ============= 3 | 4 | An Appcelerator Titanium module that uses AVFoundation to allow for a much more customizable camera. 5 | 6 | I have wanted (multiple times now) the option of being able to customize the camera size, shape, and functionality without just using the camera overlay. This lets you do that :) 7 | 8 | * __NOTE:__ The name can be misleading, the camera __does not__ HAVE to be a square :) 9 | 10 |

Supports

11 | 12 |

Devices

13 | - iPhone (Tested with 3G, 3GS, 4, 4s, 5, 5c and 5s, and 6) 14 | - iPad (Tested with multiple iPads) 15 | - iPod Touch 16 | 17 |

iOS Versions

18 | - 6.0+ (up to the latest iOS 8) 19 | 20 |

Titanium SDK Versions

21 | - 3.2.0 22 | - 3.2.1 23 | - 3.2.3 24 | - 3.3.X 25 | - 3.4.0 26 | - 3.4.0 27 | - 3.4.1 28 | - 3.4.2 29 | 30 | * __Note:__ I am sure it works on many more versions than this, but these are just the one's I've used 31 | 32 |

Setup

33 | 34 | Include the module in your tiapp.xml: 35 | 36 |

 37 | com.mfogg.squarecamera
 38 | 
 39 | 
40 | 41 |

Usage

42 | 43 |

 44 | var SquareCamera = require('com.mfogg.squarecamera'); // Initialize the SquareCamera module
 45 | 
 46 | // open a single window
 47 | var win = Ti.UI.createWindow({backgroundColor:"#eee"});
 48 | 
 49 | var camera_view = SquareCamera.createView({
 50 |   top: 0,
 51 |   height: 320,
 52 |   width: 320,
 53 |   backgroundColor: "#fff",
 54 |   frontQuality: SquareCamera.QUALITY_HIGH, // Optional Defaults to QUALITY_HIGH
 55 |   backQuality: SquareCamera.QUALITY_HD, // Optional Defaults to QUALITY_HD
 56 |   camera: "back" // Optional "back" or "front"
 57 | });
 58 | 
 59 | var image_preview = Ti.UI.createImageView({
 60 |   right: 10,
 61 |   bottom: 10,
 62 |   width: 160,
 63 |   borderWidth:1,
 64 |   borderColor:'#ddd',
 65 |   height: 160,
 66 |   backgroundColor: '#444'
 67 | });
 68 | 
 69 | camera_view.addEventListener("success", function(e){
 70 |   image_preview.image = e.media;
 71 | });
 72 | 
 73 | win.add(cameraView);
 74 | win.add(image_preview);
 75 | win.open();
 76 | 
 77 | 
78 | * __NOTE:__ The created view (ex. 'camera_view' above) can have other views added on top of it to act as a camera overlay (exactly how you would a standard Ti.UI.view) 79 | 80 |

Camera Quality

81 | 82 | You are now able to change the quality when initializing the camera by setting frontQuality and backQuality parameters. 83 | 84 |

 85 | SquareCamera.QUALITY_LOW // AVCaptureSessionPresetLow
 86 | SquareCamera.QUALITY_MEDIUM // AVCaptureSessionPresetMedium
 87 | SquareCamera.QUALITY_HIGH // AVCaptureSessionPresetHigh
 88 | SquareCamera.QUALITY_HD // AVCaptureSessionPreset1920x1080 (Note: back camera only)
 89 | 
 90 | 
91 | 92 |

Functions

93 | 94 |

camera_view.takePhoto();

95 | 96 | Takes the photo (and fires the "success" event) 97 | 98 |

camera_view.turnFlashOff();

99 | 100 | Turns the flash off (and fires the "onFlashOff" event) 101 | 102 |

camera_view.turnFlashOn();

103 | 104 | Turns the flash on (and fires the "onFlashOn" event) 105 | 106 |

camera_view.setCamera(camera);

107 | 108 | Takes the parameters "front" or "back" to change the position of the camera (and fires the "onCameraChange" event) 109 | 110 |

camera_view.pause();

111 | 112 | Pauses the camera feed (and fires the "onStateChange" event with the state param "paused") 113 | 114 |

camera_view.resume();

115 | 116 | Resumes the camera feed (and fires the "onStateChange" event with the state param "resumed") 117 | 118 |

Listeners

119 | 120 |

"success"

121 | 122 | Will fire when a picture is taken. 123 | 124 |

125 | camera_view.addEventListener("success", function(e){
126 | 
127 |   Ti.API.info(JSON.stringify(e));
128 | 
129 |   Ti.API.info(e.media); // The actual blob data
130 |   Ti.API.info(e.camera); // The "front" or "back" string for where the picture was taken
131 | 
132 |   image_preview.image = e.media;
133 | });
134 | 
135 | 
136 | 137 |

"onFlashOn"

138 | 139 | Will fire when the flash is turned on. 140 | 141 |

142 | camera_view.addEventListener("onFlashOn", function(e){
143 |   Ti.API.info("Flash Turned On");
144 | });
145 | 
146 | 
147 | 148 |

"onFlashOff"

149 | 150 | Will fire when the flash is turned off. 151 | 152 |

153 | camera_view.addEventListener("onFlashOff", function(e){
154 |   Ti.API.info("Flash Turned Off");
155 | });
156 | 
157 | 
158 | 159 |

"onCameraChange"

160 | 161 | Will fire when the camera is changed between front and back 162 | 163 |

164 | camera_view.addEventListener("onCameraChange", function(e){
165 |   // e.camera returns one of:
166 |   //   "front" : using the front camera
167 |   //   "back" : using the back camera
168 |   
169 |   Ti.API.info("Now using the "+e.camera+" camera"); // See what camera we're now using
170 | });
171 | 
172 | 
173 | 174 |

"onStateChange"

175 | 176 | Will fire when the camera itself changes states 177 | 178 |

179 | // Event that listens for the camera to switch
180 | camera_view.addEventListener("stateChange", function(e){
181 |   // Camera state change event:
182 |   //   "started" : The camera has started running!
183 |   //   "stopped" : The camera has been stopped (and is being torn down)
184 |   //   "paused" : You've paused the camera
185 |   //   "resumed" : You've resumed the camera after pausing
186 |   
187 |   // e.state = The new state of the camera (one of the above options)
188 |   
189 |   Ti.API.info("Camera state changed to "+e.state);
190 | });
191 | 
192 | 
193 | 194 |

Known Issues and Future Improvements

195 | 196 | 1. Android support 197 | 198 | ... anything else :) 199 | 200 |

Please let me know if you'd like any additions or something isn't working!

201 | 202 |

License

203 | Do whatever you want, however you want, whenever you want. And if you find a problem on your way, let me know so I can fix it for my own apps too :) 204 | 205 |

Other Stuff

206 | 207 |

Contributors (TONS of thanks!)

208 | @Kosso 209 | @reymundolopez 210 | -------------------------------------------------------------------------------- /example/app.js: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * SquareCamera Titanium Module. 4 | * 5 | * Original Author : Mike Fogg : github.com/mikefogg : June 2013 6 | * 7 | */ 8 | 9 | 10 | var SquareCamera = require('com.mfogg.squarecamera'); 11 | Ti.API.info("module is => " + SquareCamera); 12 | 13 | // open a single window 14 | var win = Ti.UI.createWindow({backgroundColor:"#eee"}); 15 | 16 | var camera_view = SquareCamera.createView({ 17 | top: 0, 18 | height: 320, 19 | width: 320, 20 | frontQuality: SquareCamera.QUALITY_HIGH, 21 | backQuality: SquareCamera.QUALITY_HD, 22 | backgroundColor: "#fff", 23 | camera: "front", // Set the view to open with the front camera 24 | detectCodes: true, // Available since v 0.7 25 | scanCrop: { // Available since v 0.8 26 | x: ((Ti.Platform.displayCaps.platformWidth-220)/2), 27 | y: ((Ti.Platform.displayCaps.platformHeight-220)/2), 28 | width: 220, 29 | height: 220 30 | }, 31 | scanCropPreview: true, // Available since v 0.8 32 | barcodeTypes: [ // Available since v 0.8 33 | "UPCE", 34 | "UPCA", 35 | "EAN13", 36 | "CODE128" 37 | ] 38 | }); 39 | 40 | var label_message = Ti.UI.createLabel({ 41 | height:Ti.UI.SIZE, 42 | left:10, 43 | right:10, 44 | text:'No Code', 45 | font:{fontSize:10,fontFamily:'Helvetica Neue'}, 46 | bottom: 100 47 | }); 48 | 49 | var image_preview = Ti.UI.createImageView({ 50 | right: 10, 51 | bottom: 10, 52 | width: 160, 53 | borderWidth:1, 54 | borderColor:'#ddd', 55 | height: 160, 56 | backgroundColor: '#444', 57 | image: 'loading_bg_sq.png' 58 | }); 59 | 60 | // Event that listens for the flash to turn on 61 | camera_view.addEventListener("onFlashOn", function(e){ 62 | flash.title = "Flash On"; 63 | }); 64 | 65 | // Event that listens for the flash to turn off 66 | camera_view.addEventListener("onFlashOff", function(e){ 67 | flash.title = "Flash Off"; 68 | }); 69 | 70 | // Event that listens for the camera to switch 71 | camera_view.addEventListener("onCameraChange", function(e){ 72 | // New e.camera actually returns one of: 73 | // "front" : using the front camera 74 | // "back" : using the back camera 75 | 76 | Ti.API.info("Now using the "+e.camera+" camera"); // See what camera we're now using 77 | }); 78 | 79 | // Event that listens for a photo to be taken 80 | camera_view.addEventListener("success", function(e){ 81 | 82 | Ti.API.info(JSON.stringify(e)); 83 | 84 | Ti.API.info(e.media); // The actual blob 85 | Ti.API.info(e.camera); // The "front" or "back" string for where the picture was taken 86 | 87 | image_preview.image = e.media; 88 | }); 89 | 90 | // Event that listens for the camera to switch 91 | camera_view.addEventListener("stateChange", function(e){ 92 | // Camera state change event: 93 | // "started" : The camera has started running! 94 | // "stopped" : The camera has been stopped (and is being torn down) 95 | // "paused" : You've paused the camera 96 | // "resumed" : You've resumed the camera after pausing 97 | 98 | // e.state = The new state of the camera (one of the above options) 99 | 100 | Ti.API.info("Camera state changed to "+e.state); 101 | }); 102 | 103 | // Since 0.7 : 2d code detection. Requires detectCodes:true on the camera view. 104 | camera_view.addEventListener("code", function(e){ 105 | label_message.text = e.codeType+' : '+e.value; 106 | }); 107 | 108 | // Take Photo Button 109 | var take_photo = Ti.UI.createView({ 110 | backgroundColor:"#6ac88d", 111 | height:60, 112 | left:10, 113 | width:90, 114 | bottom:10, 115 | borderRadius:30 116 | }); 117 | 118 | win.add(label_message); 119 | win.add(image_preview); 120 | 121 | take_photo.addEventListener("click", function(e){ 122 | camera_view.takePhoto(); 123 | }); 124 | 125 | win.add(take_photo); 126 | 127 | // Flash 128 | 129 | var flash_on = false; //Flash defaults to 'Off' 130 | 131 | var flash = Ti.UI.createButton({ 132 | top: 330, 133 | left: 10, 134 | borderWidth:0, 135 | borderRadius:20, 136 | width:90, 137 | height:40, 138 | color:'#444', 139 | title:'Flash Off', 140 | font:{fontSize:12,fontFamily:'Helvetica Neue'}, 141 | backgroundColor:'#aca476', 142 | backgroundSelectedColor:'#aca476', 143 | borderColor:'#aca476' 144 | }); 145 | 146 | flash.addEventListener("click", function(e){ 147 | if(flash_on == true){ 148 | camera_view.turnFlashOff(); 149 | flash_on = false; 150 | } else { 151 | camera_view.turnFlashOn(); 152 | flash_on = true; 153 | }; 154 | }); 155 | 156 | win.add(flash); 157 | 158 | // Pause the camera 159 | var pause = Ti.UI.createButton({ 160 | top: 380, 161 | left: 10, 162 | borderWidth:0, 163 | borderRadius:20, 164 | width:90, 165 | height:40, 166 | color:'#444', 167 | title:'Pause', 168 | font:{fontSize:12,fontFamily:'Helvetica Neue'}, 169 | backgroundColor:'#aca476', 170 | backgroundSelectedColor:'#aca476', 171 | borderColor:'#aca476' 172 | }); 173 | 174 | pause.addEventListener("click", function(e){ 175 | camera_view.pause(); 176 | }); 177 | 178 | win.add(pause); 179 | 180 | // Pause the camera 181 | var resume = Ti.UI.createButton({ 182 | top: 430, 183 | left: 10, 184 | borderWidth:0, 185 | borderRadius:20, 186 | width:90, 187 | height:40, 188 | color:'#444', 189 | title:'Resume', 190 | font:{fontSize:12,fontFamily:'Helvetica Neue'}, 191 | backgroundColor:'#aca476', 192 | backgroundSelectedColor:'#aca476', 193 | borderColor:'#aca476' 194 | }); 195 | 196 | resume.addEventListener("click", function(e){ 197 | camera_view.resume(); 198 | }); 199 | 200 | win.add(resume); 201 | 202 | // Switch Camera 203 | 204 | var change_camera = Ti.UI.createButton({ 205 | top: 330, 206 | right: 10, 207 | borderWidth:0, 208 | borderRadius:20, 209 | width:90, 210 | height:40, 211 | color:'#444', 212 | title:'camera', 213 | font:{fontSize:12,fontFamily:'Helvetica Neue'}, 214 | backgroundColor:'#aca476', 215 | backgroundSelectedColor:'#aca476', 216 | borderColor:'#aca476' 217 | }); 218 | 219 | change_camera.addEventListener("click", function(e){ 220 | if(camera_view.camera == "front"){ 221 | camera_view.camera = "back"; 222 | } else { 223 | camera_view.camera = "front"; 224 | }; 225 | }); 226 | 227 | win.add(change_camera); 228 | 229 | win.add(camera_view); 230 | win.open(); 231 | -------------------------------------------------------------------------------- /hooks/README: -------------------------------------------------------------------------------- 1 | These files are not yet supported as of 1.4.0 but will be in a near future release. 2 | -------------------------------------------------------------------------------- /hooks/add.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # This is the module project add hook that will be 4 | # called when your module is added to a project 5 | # 6 | import os, sys 7 | 8 | def dequote(s): 9 | if s[0:1] == '"': 10 | return s[1:-1] 11 | return s 12 | 13 | def main(args,argc): 14 | # You will get the following command line arguments 15 | # in the following order: 16 | # 17 | # project_dir = the full path to the project root directory 18 | # project_type = the type of project (desktop, mobile, ipad) 19 | # project_name = the name of the project 20 | # 21 | project_dir = dequote(os.path.expanduser(args[1])) 22 | project_type = dequote(args[2]) 23 | project_name = dequote(args[3]) 24 | 25 | # TODO: write your add hook here (optional) 26 | 27 | 28 | # exit 29 | sys.exit(0) 30 | 31 | 32 | 33 | if __name__ == '__main__': 34 | main(sys.argv,len(sys.argv)) 35 | 36 | -------------------------------------------------------------------------------- /hooks/install.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # This is the module install hook that will be 4 | # called when your module is first installed 5 | # 6 | import os, sys 7 | 8 | def main(args,argc): 9 | 10 | # TODO: write your install hook here (optional) 11 | 12 | # exit 13 | sys.exit(0) 14 | 15 | 16 | 17 | if __name__ == '__main__': 18 | main(sys.argv,len(sys.argv)) 19 | 20 | -------------------------------------------------------------------------------- /hooks/remove.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # This is the module project remove hook that will be 4 | # called when your module is remove from a project 5 | # 6 | import os, sys 7 | 8 | def dequote(s): 9 | if s[0:1] == '"': 10 | return s[1:-1] 11 | return s 12 | 13 | def main(args,argc): 14 | # You will get the following command line arguments 15 | # in the following order: 16 | # 17 | # project_dir = the full path to the project root directory 18 | # project_type = the type of project (desktop, mobile, ipad) 19 | # project_name = the name of the project 20 | # 21 | project_dir = dequote(os.path.expanduser(args[1])) 22 | project_type = dequote(args[2]) 23 | project_name = dequote(args[3]) 24 | 25 | # TODO: write your remove hook here (optional) 26 | 27 | # exit 28 | sys.exit(0) 29 | 30 | 31 | 32 | if __name__ == '__main__': 33 | main(sys.argv,len(sys.argv)) 34 | 35 | -------------------------------------------------------------------------------- /hooks/uninstall.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # This is the module uninstall hook that will be 4 | # called when your module is uninstalled 5 | # 6 | import os, sys 7 | 8 | def main(args,argc): 9 | 10 | # TODO: write your uninstall hook here (optional) 11 | 12 | # exit 13 | sys.exit(0) 14 | 15 | 16 | if __name__ == '__main__': 17 | main(sys.argv,len(sys.argv)) 18 | 19 | -------------------------------------------------------------------------------- /manifest: -------------------------------------------------------------------------------- 1 | # 2 | # this is your module manifest and used by Titanium 3 | # during compilation, packaging, distribution, etc. 4 | # 5 | version: 0.8.0 6 | description: SquareCamera - Titanium Module using AVFoundation for the camera. Kosso - Now with optional 2d code detection. 7 | author: Mike Fogg - Modifications - Kosso 8 | license: MIT 9 | copyright: Copyright (c) 2013 - 2015 by Mike Fogg 10 | 11 | 12 | # these should not be edited 13 | name: SquareCamera 14 | moduleid: com.mfogg.squarecamera 15 | guid: 9b17e85f-00c8-45ba-a279-d1373a0e2e90 16 | architectures: armv7 arm64 i386 x86_64 17 | platform: iphone 18 | minsdk: 5.0.0.GA 19 | -------------------------------------------------------------------------------- /module.xcconfig: -------------------------------------------------------------------------------- 1 | // 2 | // PLACE ANY BUILD DEFINITIONS IN THIS FILE AND THEY WILL BE 3 | // PICKED UP DURING THE APP BUILD FOR YOUR MODULE 4 | // 5 | // see the following webpage for instructions on the settings 6 | // for this file: 7 | // http://developer.apple.com/mac/library/documentation/DeveloperTools/Conceptual/XcodeBuildSystem/400-Build_Configurations/build_configs.html 8 | // 9 | 10 | // 11 | // How to add a Framework (example) 12 | // 13 | OTHER_LDFLAGS=$(inherited) -framework AVFoundation -framework AudioToolbox -framework CoreGraphics -framework UIKit -framework Foundation -framework CoreVideo -framework CoreMedia -framework QuartzCore -framework ImageIO 14 | // 15 | // Adding a framework for a specific version(s) of iPhone: 16 | // 17 | // OTHER_LDFLAGS[sdk=iphoneos4*]=$(inherited) -framework Foo 18 | // OTHER_LDFLAGS[sdk=iphonesimulator4*]=$(inherited) -framework Foo 19 | // 20 | // 21 | // How to add a compiler define: 22 | // 23 | // OTHER_CFLAGS=$(inherited) -DFOO=1 24 | // 25 | // 26 | // IMPORTANT NOTE: always use $(inherited) in your overrides 27 | // 28 | -------------------------------------------------------------------------------- /platform/README: -------------------------------------------------------------------------------- 1 | You can place platform-specific files here in sub-folders named "android" and/or "iphone", just as you can with normal Titanium Mobile SDK projects. Any folders and files you place here will be merged with the platform-specific files in a Titanium Mobile project that uses this module. 2 | 3 | When a Titanium Mobile project that uses this module is built, the files from this platform/ folder will be treated the same as files (if any) from the Titanium Mobile project's platform/ folder. 4 | -------------------------------------------------------------------------------- /timodule.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /titanium.xcconfig: -------------------------------------------------------------------------------- 1 | // 2 | // 3 | // CHANGE THESE VALUES TO REFLECT THE VERSION (AND LOCATION IF DIFFERENT) 4 | // OF YOUR TITANIUM SDK YOU'RE BUILDING FOR 5 | // 6 | // 7 | TITANIUM_SDK_VERSION = 5.3.1.GA 8 | 9 | 10 | // 11 | // THESE SHOULD BE OK GENERALLY AS-IS 12 | // 13 | TITANIUM_SDK = $HOME/Library/Application Support/Titanium/mobilesdk/osx/$(TITANIUM_SDK_VERSION) 14 | TITANIUM_BASE_SDK = "$(TITANIUM_SDK)/iphone/include" 15 | TITANIUM_BASE_SDK2 = "$(TITANIUM_SDK)/iphone/include/TiCore" 16 | HEADER_SEARCH_PATHS= $(TITANIUM_BASE_SDK) $(TITANIUM_BASE_SDK2) 17 | --------------------------------------------------------------------------------