bzr branch
/browse/iphone/tappity
| Line | Revision | Contents |
| 1 | 46 | // |
| 2 | // TappityClient.m |
|
| 3 | // tappity |
|
| 4 | // |
|
| 5 | // Created by döme on 25.10.2009. |
|
| 6 | // |
|
| 7 | ||
| 8 | 54 | /* |
| 9 | * Copyright (c) 2009 Doemoetoer Gulyas. |
|
| 10 | * All rights reserved. |
|
| 11 | * |
|
| 12 | * Redistribution and use in source and binary forms, with or without |
|
| 13 | * modification, are permitted provided that the following conditions |
|
| 14 | * are met: |
|
| 15 | * 1. Redistributions of source code must retain the above copyright |
|
| 16 | * notice, this list of conditions and the following disclaimer. |
|
| 17 | * 2. Redistributions in binary form must reproduce the above copyright |
|
| 18 | * notice, this list of conditions and the following disclaimer in the |
|
| 19 | * documentation and/or other materials provided with the distribution. |
|
| 20 | * 3. The name of the author may not be used to endorse or promote products |
|
| 21 | * derived from this software without specific prior written permission. |
|
| 22 | * |
|
| 23 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
|
| 24 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
|
| 25 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
|
| 26 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
|
| 27 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
|
| 28 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
|
| 29 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
|
| 30 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
|
| 31 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
|
| 32 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
|
| 33 | */ |
|
| 34 | ||
| 35 | 46 | #import "TappityClient.h" |
| 36 | #import "Tappity.h" |
|
| 37 | ||
| 38 | 52 | #include <sys/types.h> |
| 39 | 46 | #include <sys/socket.h> |
| 40 | #include <netdb.h> |
|
| 41 | #include <netinet/in.h> |
|
| 42 | #include <sys/time.h> |
|
| 43 | ||
| 44 | 49 | #import <CoreLocation/CoreLocation.h> |
| 45 | ||
| 46 | 46 | @implementation TappityClient |
| 47 | ||
| 48 | 48 | - (id) init |
| 49 | { |
|
| 50 | if (!(self = [super init])) |
|
| 51 | return nil; |
|
| 52 | 53 | |
| 53 | messenger = [[SocketMessenger alloc] init]; |
|
| 54 | ||
| 55 | [messenger setDelegate: self]; |
|
| 56 | 48 | |
| 57 | 53 | [messenger setReceiveDataOnMainThread: NO]; |
| 58 | [messenger setAutomaticallyReconnect: NO]; |
|
| 59 | 48 | |
| 60 | 49 | enableFeedbackVideoDisplay = YES; |
| 61 | ||
| 62 | 48 | return self; |
| 63 | } |
|
| 64 | ||
| 65 | 46 | |
| 66 | 52 | |
| 67 | 53 | - (void) connectionWasTerminated: (SocketMessenger*) theMessenger |
| 68 | { |
|
| 69 | NSLog(@"%s", _cmd); |
|
| 70 | if ([delegate respondsToSelector: @selector(connectionWasTerminated:)]) |
|
| 71 | [delegate connectionWasTerminated: theMessenger]; |
|
| 72 | } |
|
| 73 | 52 | |
| 74 | 53 | - (void) connectionWasEstablished: (SocketMessenger*) theMessenger |
| 75 | 46 | { |
| 76 | 51 | if (enableFeedbackVideoDisplay) |
| 77 | { |
|
| 78 | NSLog(@"enabling visual uplink"); |
|
| 79 | 53 | [messenger sendData: [NSData data] withIdentifier: kTapStartSendingVisualFeedback]; |
| 80 | 51 | } |
| 81 | 49 | } |
| 82 | ||
| 83 | ||
| 84 | - (void)locationManager:(CLLocationManager *)manager |
|
| 85 | didUpdateToLocation:(CLLocation *)newLoc |
|
| 86 | fromLocation:(CLLocation *)oldLocation |
|
| 87 | { |
|
| 88 | 50 | NSData* data = [NSKeyedArchiver archivedDataWithRootObject: newLoc]; |
| 89 | 49 | assert(data); |
| 90 | ||
| 91 | 53 | [messenger sendData: data withIdentifier: kTapLocation]; |
| 92 | 49 | |
| 93 | } |
|
| 94 | ||
| 95 | - (void)locationManager:(CLLocationManager *)manager didUpdateHeading:(CLHeading *)heading |
|
| 96 | { |
|
| 97 | 50 | NSData* data = [NSKeyedArchiver archivedDataWithRootObject: heading]; |
| 98 | 49 | assert(data); |
| 99 | ||
| 100 | 53 | [messenger sendData: data withIdentifier: kTapCompass]; |
| 101 | 48 | } |
| 102 | ||
| 103 | - (void) accelerometer: (UIAccelerometer *) accelerometer didAccelerate: (UIAcceleration*) acceleration |
|
| 104 | { |
|
| 105 | NSArray* ary = [NSArray arrayWithObjects: [NSNumber numberWithFloat: [acceleration x]], [NSNumber numberWithFloat: [acceleration y]], [NSNumber numberWithFloat: [acceleration z]], [NSNumber numberWithDouble: [acceleration timestamp]], nil]; |
|
| 106 | ||
| 107 | 50 | NSData* data = [NSPropertyListSerialization dataFromPropertyList: ary format: NSPropertyListBinaryFormat_v1_0 errorDescription: nil]; |
| 108 | 48 | assert(data); |
| 109 | ||
| 110 | 53 | [messenger sendData: data withIdentifier: kTapAcceleration]; |
| 111 | 47 | |
| 112 | 46 | } |
| 113 | ||
| 114 | ||
| 115 | - (void) recordApplicationEvent: (NSDictionary*) event |
|
| 116 | { |
|
| 117 | // NSLog(@"%@", event); |
|
| 118 | 61 | |
| 119 | 62 | CGRect screenRect = [[UIScreen mainScreen] bounds]; |
| 120 | ||
| 121 | 61 | long type = [[event objectForKey: @"Type"] integerValue]; |
| 122 | if ((type == 2005) || (type == 2007)) // suspend and quit events |
|
| 123 | return; |
|
| 124 | 62 | |
| 125 | if (type == 3001) // touch event |
|
| 126 | { |
|
| 127 | NSMutableDictionary* mdict = [event mutableCopy]; |
|
| 128 | |
|
| 129 | [mdict setObject: NSStringFromCGRect(screenRect) forKey: @"UIScreen bounds"]; |
|
| 130 | event = mdict; |
|
| 131 | } |
|
| 132 | 46 | |
| 133 | 50 | NSData* data = [NSPropertyListSerialization dataFromPropertyList: event format: NSPropertyListBinaryFormat_v1_0 errorDescription: nil]; |
| 134 | 46 | assert(data); |
| 135 | 53 | [messenger sendData: data withIdentifier: kTapRecordedEvent]; |
| 136 | 47 | } |
| 137 | ||
| 138 | ||
| 139 | 46 | |
| 140 | static size_t _write_i8(void* buf, uint8_t val) |
|
| 141 | { |
|
| 142 | memcpy(buf, &val, 1); |
|
| 143 | return 1; |
|
| 144 | } |
|
| 145 | ||
| 146 | static size_t _write_i16(void* buf, uint16_t val) |
|
| 147 | { |
|
| 148 | val = CFSwapInt16HostToBig(val); |
|
| 149 | memcpy(buf, &val, 2); |
|
| 150 | return 2; |
|
| 151 | } |
|
| 152 | ||
| 153 | static size_t _write_i32(void* buf, uint32_t val) |
|
| 154 | { |
|
| 155 | val = CFSwapInt32HostToBig(val); |
|
| 156 | memcpy(buf, &val, 4); |
|
| 157 | return 4; |
|
| 158 | } |
|
| 159 | ||
| 160 | static size_t _write_i64(void* buf, uint64_t val) |
|
| 161 | { |
|
| 162 | val = CFSwapInt64HostToBig(val); |
|
| 163 | memcpy(buf, &val, 8); |
|
| 164 | return 8; |
|
| 165 | } |
|
| 166 | ||
| 167 | static size_t _write_float(void* buf, float val) |
|
| 168 | { |
|
| 169 | CFSwappedFloat32 v = CFConvertFloat32HostToSwapped(val); |
|
| 170 | memcpy(buf, &v, 4); |
|
| 171 | return 4; |
|
| 172 | } |
|
| 173 | 49 | /* |
| 174 | 46 | static size_t _write_gspoint(void* buf, GSTouchPointRef p) |
| 175 | { |
|
| 176 | size_t bc = 0; |
|
| 177 | ||
| 178 | bc += _write_i32(buf+bc, p->unk0); |
|
| 179 | bc += _write_float(buf+bc, p->unk1); |
|
| 180 | bc += _write_float(buf+bc, p->touchSize); |
|
| 181 | bc += _write_float(buf+bc, p->x); |
|
| 182 | bc += _write_float(buf+bc, p->y); |
|
| 183 | bc += _write_i32(buf+bc, (uint32_t)p->window); |
|
| 184 | |
|
| 185 | return bc; |
|
| 186 | } |
|
| 187 | 49 | */ |
| 188 | 46 | /* |
| 189 | - (id) plistWithTouches: (NSSet*) touches |
|
| 190 | { |
|
| 191 | NSMutableArray* ary = [NSMutableArray array]; |
|
| 192 | |
|
| 193 | for (UITouch* touch in touches) |
|
| 194 | { |
|
| 195 | NSMutableData* tdata = [NSMutableData dataWithLength: sizeof(UITouch)]; |
|
| 196 | size_t bc = 0; |
|
| 197 | void* buf = [tdata mutableBytes]; |
|
| 198 | bc += _write_double(buf+bc, touch->_timestamp); |
|
| 199 | |
|
| 200 | } |
|
| 201 | |
|
| 202 | return ary; |
|
| 203 | } |
|
| 204 | */ |
|
| 205 | ||
| 206 | - (void) sendTouch: (UIEvent*) event inPhase: (int) phase |
|
| 207 | { |
|
| 208 | return; |
|
| 209 | 49 | /* |
| 210 | 46 | NSMutableDictionary* touchDict = [NSMutableDictionary dictionaryWithObjectsAndKeys: [NSNumber numberWithInt: kTapTouchEvent], TapIdKey, nil]; |
| 211 | ||
| 212 | // [touchDict setObject: [self touchesAsPlist: [event allTouches]] forKey: TapTouchesKey]; |
|
| 213 | ||
| 214 | GSEvent* gse = [event _gsEvent]; |
|
| 215 | ||
| 216 | NSMutableData* gsData = [NSMutableData dataWithLength: sizeof(GSEvent)]; |
|
| 217 | size_t bc = 0; |
|
| 218 | void* buf = [gsData mutableBytes]; |
|
| 219 | |
|
| 220 | bc += _write_i32(buf + bc, gse->type0); |
|
| 221 | bc += _write_i32(buf + bc, gse->type1); |
|
| 222 | bc += _write_i32(buf + bc, gse->r3); |
|
| 223 | bc += _write_float(buf + bc, gse->avgX0); |
|
| 224 | bc += _write_float(buf + bc, gse->avgY0); |
|
| 225 | bc += _write_float(buf + bc, gse->avgX1); |
|
| 226 | bc += _write_float(buf + bc, gse->avgY1); |
|
| 227 | bc += _write_i32(buf + bc, gse->processId); |
|
| 228 | bc += _write_i64(buf + bc, gse->timestamp); |
|
| 229 | bc += _write_i32(buf + bc, (uint32_t)gse->window); |
|
| 230 | bc += _write_i32(buf + bc, gse->r11); |
|
| 231 | bc += _write_i32(buf + bc, gse->type12); |
|
| 232 | bc += _write_i32(buf + bc, gse->gesture13); |
|
| 233 | bc += _write_i32(buf + bc, gse->gesture14); |
|
| 234 | bc += _write_i16(buf + bc, gse->numInitialTouches); |
|
| 235 | bc += _write_i16(buf + bc, gse->numCurrentTouches); |
|
| 236 | bc += _write_i32(buf + bc, gse->r16); |
|
| 237 | bc += _write_i32(buf + bc, gse->r17); |
|
| 238 | bc += _write_i32(buf + bc, gse->r18); |
|
| 239 | bc += _write_i32(buf + bc, gse->r19); |
|
| 240 | bc += _write_i32(buf + bc, gse->r20); |
|
| 241 | bc += _write_i32(buf + bc, gse->r21); |
|
| 242 | bc += _write_i8(buf + bc, gse->r22_0); |
|
| 243 | bc += _write_i8(buf + bc, gse->numPoints); |
|
| 244 | bc += _write_i8(buf + bc, gse->r22_2); |
|
| 245 | for (size_t i = 0; i < gse->numPoints; ++i) |
|
| 246 | bc += _write_gspoint(buf+bc, gse->points+i); |
|
| 247 | ||
| 248 | [touchDict setObject: gsData forKey: TapGSEventKey]; |
|
| 249 | [touchDict setObject: [NSNumber numberWithInt: phase] forKey: TapTouchPhaseKey]; |
|
| 250 | //[touchDict setObject: [self plistWithTouches: [event allTouches]] forKey: TapTouchesKey]; |
|
| 251 | ||
| 252 | NSData* data = [NSPropertyListSerialization dataFromPropertyList: touchDict format: NSPropertyListBinaryFormat_v1_0 errorDescription: nil]; |
|
| 253 | assert(data); |
|
| 254 | 47 | [self sendData: data]; |
| 255 | 49 | */ |
| 256 | 47 | } |
| 257 | ||
| 258 | 52 | - (void) stopUpdatingHeading |
| 259 | { |
|
| 260 | [lm stopUpdatingHeading]; |
|
| 261 | } |
|
| 262 | ||
| 263 | - (void) stopUpdatingLocation |
|
| 264 | { |
|
| 265 | [lm stopUpdatingLocation]; |
|
| 266 | } |
|
| 267 | ||
| 268 | - (void) startUpdatingHeading |
|
| 269 | { |
|
| 270 | if (!lm) |
|
| 271 | { |
|
| 272 | lm = [[CLLocationManager alloc] init]; |
|
| 273 | [lm setDelegate: self]; |
|
| 274 | } |
|
| 275 | if (enableCompass) |
|
| 276 | { |
|
| 277 | [lm setHeadingFilter: kCLHeadingFilterNone]; |
|
| 278 | [lm startUpdatingHeading]; |
|
| 279 | } |
|
| 280 | } |
|
| 281 | ||
| 282 | - (void) startUpdatingLocation |
|
| 283 | { |
|
| 284 | if (!lm) |
|
| 285 | { |
|
| 286 | lm = [[CLLocationManager alloc] init]; |
|
| 287 | [lm setDelegate: self]; |
|
| 288 | } |
|
| 289 | if (enableLocation) |
|
| 290 | { |
|
| 291 | [lm setDistanceFilter: kCLDistanceFilterNone]; |
|
| 292 | [lm setDesiredAccuracy: kCLLocationAccuracyBest]; |
|
| 293 | [lm startUpdatingLocation]; |
|
| 294 | } |
|
| 295 | } |
|
| 296 | ||
| 297 | - (void) setAccelerometerUpdateInterval: (NSNumber*) num |
|
| 298 | { |
|
| 299 | if (!enableAccelerometer) |
|
| 300 | return; |
|
| 301 | |
|
| 302 | [[UIAccelerometer sharedAccelerometer] setDelegate: self]; |
|
| 303 | [[UIAccelerometer sharedAccelerometer] setUpdateInterval: [num doubleValue]]; |
|
| 304 | } |
|
| 305 | ||
| 306 | 50 | - (void) dataReceived: (NSDictionary*) dataDict |
| 307 | 47 | { |
| 308 | 49 | |
| 309 | 52 | uint32_t messageId = [[dataDict objectForKey: SocketMessageIdKey] intValue]; |
| 310 | NSData* data = [dataDict objectForKey: SocketMessageDataKey]; |
|
| 311 | 50 | |
| 312 | switch (messageId) |
|
| 313 | { |
|
| 314 | case kTapRawScreenshot: |
|
| 315 | { |
|
| 316 | UIImage* img = [UIImage imageWithData: data]; |
|
| 317 | // NSLog(@"got image %@", img); |
|
| 318 | ||
| 319 | if(delegate) |
|
| 320 | [delegate setImage: img]; |
|
| 321 | ||
| 322 | break; |
|
| 323 | } |
|
| 324 | 61 | case kTapPlacedScreenshot: |
| 325 | { |
|
| 326 | NSDictionary* dict = [NSPropertyListSerialization propertyListFromData: data mutabilityOption: NSPropertyListImmutable format: nil errorDescription: nil]; |
|
| 327 | |
|
| 328 | UIImage* img = [UIImage imageWithData: [dict objectForKey: TapImageDataKey]]; |
|
| 329 | // NSLog(@"got image %@", img); |
|
| 330 | ||
| 331 | if(delegate) |
|
| 332 | [delegate setImage: img]; |
|
| 333 | ||
| 334 | break; |
|
| 335 | } |
|
| 336 | 52 | case kTapStartUpdatingHeading: |
| 337 | [self performSelectorOnMainThread: @selector(startUpdatingHeading) withObject: nil waitUntilDone: NO]; |
|
| 338 | break; |
|
| 339 | case kTapStopUpdatingHeading: |
|
| 340 | [self performSelectorOnMainThread: @selector(stopUpdatingHeading) withObject: nil waitUntilDone: NO]; |
|
| 341 | break; |
|
| 342 | case kTapStartUpdatingLocation: |
|
| 343 | [self performSelectorOnMainThread: @selector(startUpdatingLocation) withObject: nil waitUntilDone: NO]; |
|
| 344 | break; |
|
| 345 | case kTapStopUpdatingLocation: |
|
| 346 | [self performSelectorOnMainThread: @selector(stopUpdatingLocation) withObject: nil waitUntilDone: NO]; |
|
| 347 | break; |
|
| 348 | case kTapAccelerometerUpdateInterval: |
|
| 349 | { |
|
| 350 | CFSwappedFloat64 sf = *(CFSwappedFloat64*)[data bytes]; |
|
| 351 | [self performSelectorOnMainThread: @selector(setAccelerometerUpdateInterval:) withObject: [NSNumber numberWithDouble: CFConvertFloat64SwappedToHost(sf)] waitUntilDone: NO]; |
|
| 352 | break; |
|
| 353 | } |
|
| 354 | 50 | } |
| 355 | 48 | |
| 356 | 47 | [data release]; |
| 357 | 46 | } |
| 358 | ||
| 359 | 53 | - (void) connectToService: (NSNetService*) service |
| 360 | { |
|
| 361 | [messenger connectToService: service]; |
|
| 362 | } |
|
| 363 | ||
| 364 | - (void) terminateConnection |
|
| 365 | { |
|
| 366 | [messenger terminateConnection]; |
|
| 367 | } |
|
| 368 | ||
| 369 | ||
| 370 | 46 | - (void) dealloc |
| 371 | { |
|
| 372 | 53 | [messenger terminateConnection]; |
| 373 | [messenger release]; |
|
| 374 | [lm release]; |
|
| 375 | 46 | |
| 376 | [super dealloc]; |
|
| 377 | } |
|
| 378 | ||
| 379 | 49 | @synthesize delegate, enableAccelerometer, enableCompass, enableLocation, enableFeedbackVideoDisplay; |
| 380 | 46 | |
| 381 | @end |
Loggerhead 1.17 is a web-based interface for Bazaar branches