call widget delegate after 1 sec delay. this gives ui time to show points and user...
[zxing.git] / iphone / ZXingWidget / ZXingWidgetController.m
1 /**
2  * Copyright 2009 Jeff Verkoeyen
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *    http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #import "ZXingWidgetController.h"
18 #import "Decoder.h"
19 #import "NSString+HTML.h"
20 #import "ResultParser.h"
21 #import "ParsedResult.h"
22 #import "ResultAction.h"
23 #include <sys/types.h>
24 #include <sys/sysctl.h>
25
26 #define CAMERA_SCALAR 1.12412 // scalar = (480 / (2048 / 480))
27 #define FIRST_TAKE_DELAY 1.0
28
29 CGImageRef UIGetScreenImage();
30
31 @implementation ZXingWidgetController
32 @synthesize result, actions, showCancel, delegate;
33
34 - (id)initWithDelegate:(id<ZXingDelegate>)scanDelegate {
35         if (self = [super init]) {
36                 [self setDelegate:scanDelegate];
37                 showCancel = true;
38                 self.wantsFullScreenLayout = YES;
39                 self.sourceType = UIImagePickerControllerSourceTypeCamera;
40                 float zoomFactor = CAMERA_SCALAR;
41                 if ([self fixedFocus]) {
42                         zoomFactor *= 1.5;
43                 }
44                 self.cameraViewTransform = CGAffineTransformScale(
45                                         self.cameraViewTransform, zoomFactor, zoomFactor);
46                 overlayView = [[OverlayView alloc] initWithCancelEnabled:showCancel frame:[UIScreen mainScreen].bounds];
47                 [overlayView setDelegate:self];
48                 self.sourceType = UIImagePickerControllerSourceTypeCamera;
49                 self.showsCameraControls = NO;
50                 self.cameraOverlayView = overlayView;
51                 self.allowsEditing = NO; // [[NSUserDefaults standardUserDefaults] boolForKey:@"allowEditing"];
52         }
53         
54         return self;
55 }
56
57 - (void)dealloc {
58         AudioServicesDisposeSystemSoundID(beepSound);
59         [overlayView dealloc];
60         [super dealloc];
61 }
62
63 - (void)cancelled {
64         NSLog(@"cancelled called in ZXingWidgetController");
65         wasCancelled = true;
66         if (delegate != nil) {
67                 [delegate cancelled];
68         }
69 }
70
71 - (NSString *)getPlatform {
72         size_t size;
73     sysctlbyname("hw.machine", NULL, &size, NULL, 0);
74     char *machine = malloc(size);
75     sysctlbyname("hw.machine", machine, &size, NULL, 0);
76     NSString *platform = [NSString stringWithCString:machine encoding:NSASCIIStringEncoding];
77     free(machine);
78         return platform;
79 }
80
81 - (BOOL)fixedFocus {
82         NSString *platform = [self getPlatform];
83         if ([platform isEqualToString:@"iPhone1,1"] ||
84                 [platform isEqualToString:@"iPhone1,2"]) return true;
85         return false;
86 }
87
88 - (void)viewDidLoad {
89         [super viewDidLoad];
90         NSBundle *mainBundle = [NSBundle mainBundle];
91         OSStatus error = AudioServicesCreateSystemSoundID((CFURLRef)[NSURL fileURLWithPath:[mainBundle pathForResource:@"beep-beep" ofType:@"caf"] isDirectory:NO], &beepSound);
92         if (error != kAudioServicesNoError) {
93                 NSLog(@"Problem loading nearSound.caf");
94         }       
95 }
96
97 - (void)viewDidAppear:(BOOL)animated {
98     [super viewDidAppear:animated];
99         [overlayView setPoints:nil];
100         wasCancelled = false;
101         [NSTimer scheduledTimerWithTimeInterval: FIRST_TAKE_DELAY
102                                                                          target: self
103                                                                    selector: @selector(takePicture:)
104                                                                    userInfo: nil
105                                                                         repeats: NO];
106 }
107
108 - (void)takePicture:(NSTimer*)theTimer {
109         CGImageRef capture = UIGetScreenImage();
110         UIImage *scrn = [UIImage imageWithCGImage:CGImageCreateWithImageInRect(capture, [overlayView cropRect])];
111         Decoder *d = [[Decoder alloc] init];
112         d.delegate = self;
113         CGRect cropRect = overlayView.cropRect;
114         cropRect.origin.x = 0.0;
115         cropRect.origin.y = 0.0;
116         NSLog(@"crop rect %f, %f, %f, %f", cropRect.origin.x, cropRect.origin.y, cropRect.size.width, cropRect.size.height);
117         [d decodeImage:scrn cropRect:cropRect];
118 }
119
120 // DecoderDelegate methods
121
122 - (void)decoder:(Decoder *)decoder willDecodeImage:(UIImage *)image usingSubset:(UIImage *)subset{
123         NSLog(@"DecoderViewController MessageWhileDecodingWithDimensions: Decoding image (%.0fx%.0f) ...", image.size.width, image.size.height);
124 }
125
126 - (void)decoder:(Decoder *)decoder
127   decodingImage:(UIImage *)image
128     usingSubset:(UIImage *)subset
129        progress:(NSString *)message {
130         NSLog(@"decoding image %@", message);
131 }
132
133 - (void)presentResultForString:(NSString *)resultString {
134         NSLog(@"in presentResultForString()");
135         self.result = [ResultParser parsedResultForString:resultString];
136         AudioServicesPlaySystemSound(beepSound);
137 #ifdef DEBUG
138         NSLog(@"result string = %@", resultString);
139         NSLog(@"result has %d actions", actions ? 0 : actions.count);
140 #endif
141         //      [self updateToolbar];
142 }
143
144 - (void)presentResultPoints:(NSArray *)resultPoints
145                    forImage:(UIImage *)image
146                 usingSubset:(UIImage *)subset {
147         // simply add the points to the image view
148         NSLog(@"got points for display");
149         [overlayView setPoints:resultPoints];
150 }
151
152 - (void)decoder:(Decoder *)decoder didDecodeImage:(UIImage *)image usingSubset:(UIImage *)subset withResult:(TwoDDecoderResult *)twoDResult {
153         //      [self presentResultForString:twoDResult.text];
154         NSLog(@"decoded image!!");
155         [self presentResultPoints:[twoDResult points] forImage:image usingSubset:subset];
156         // now, in a selector, call the delegate to give this overlay time to show the points
157         [self performSelector:@selector(alertDelegate:) withObject:[[twoDResult text] copy] afterDelay:1.0];
158         decoder.delegate = nil;
159         [decoder release];
160 }
161
162 - (void)alertDelegate:(id)text {        
163         if (delegate != nil) {
164                 [delegate scanResult:text];
165         }
166 }
167
168 - (void)decoder:(Decoder *)decoder failedToDecodeImage:(UIImage *)image usingSubset:(UIImage *)subset reason:(NSString *)reason {
169         decoder.delegate = nil;
170         [decoder release];
171         [overlayView setPoints:nil];
172         if (!wasCancelled) {
173                 [self takePicture:nil];
174         }
175         //[self updateToolbar];
176 }
177
178 @end