bzr branch
/browse/iphone/tappity
| Line | Revision | Contents |
| 1 | 46 | // |
| 2 | // Tappity.m |
|
| 3 | // tappity |
|
| 4 | // |
|
| 5 | // Created by döme on 25.10.2009. |
|
| 6 | // Copyright 2009 __MyCompanyName__. All rights reserved. |
|
| 7 | // |
|
| 8 | ||
| 9 | 47 | |
| 10 | #include <stdint.h> |
|
| 11 | #include <sys/socket.h> |
|
| 12 | #include <fcntl.h> |
|
| 13 | #include <termios.h> |
|
| 14 | #include <netinet/in.h> |
|
| 15 | #include <arpa/inet.h> |
|
| 16 | ||
| 17 | ||
| 18 | 46 | #import "Tappity.h" |
| 19 | ||
| 20 | 49 | //#import "GraphicsServices.h" |
| 21 | 46 | |
| 22 | NSString* TapIdKey = @"tapId"; |
|
| 23 | NSString* TapTouchesKey = @"tapTouches"; |
|
| 24 | NSString* TapGSEventKey = @"tapGSEvent"; |
|
| 25 | NSString* TapTouchPhaseKey = @"tapTouchPhase"; |
|
| 26 | NSString* TapRecordedEventKey = @"tapRecordedEvent"; |
|
| 27 | 48 | NSString* TapAccelerationKey = @"tapAcceleration"; |
| 28 | NSString* TapCompassKey = @"tapCompass"; |
|
| 29 | NSString* TapLocationKey = @"tapLocation"; |
|
| 30 | ||
| 31 | ||
| 32 | @interface Tappity (Private) |
|
| 33 | - (void) dataReceived: (NSData*) data; |
|
| 34 | @end |
|
| 35 | 47 | |
| 36 | 46 | @implementation Tappity |
| 37 | ||
| 38 | 47 | - (BOOL) threadActive: (id) key |
| 39 | { |
|
| 40 | return [[activeThreads objectForKey: key] boolValue]; |
|
| 41 | } |
|
| 42 | ||
| 43 | - (void) threadWillExit: (id) key |
|
| 44 | { |
|
| 45 | @synchronized (self) |
|
| 46 | { |
|
| 47 | [activeThreads removeObjectForKey: key]; |
|
| 48 | 49 | |
| 49 | if (![activeThreads count]) |
|
| 50 | { |
|
| 51 | close(commsSocket); |
|
| 52 | commsSocket = -1; |
|
| 53 | |
|
| 54 | |
|
| 55 | } |
|
| 56 | 47 | } |
| 57 | } |
|
| 58 | ||
| 59 | - (void) receivingThread: (id) info |
|
| 60 | { |
|
| 61 | NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; |
|
| 62 | ||
| 63 | @synchronized(self) |
|
| 64 | { |
|
| 65 | [self retain]; |
|
| 66 | } |
|
| 67 | ||
| 68 | while ([self threadActive: info]) |
|
| 69 | { |
|
| 70 | struct timeval tv; |
|
| 71 | fd_set readfds; |
|
| 72 | fd_set writefds; |
|
| 73 | fd_set errorfds; |
|
| 74 | 49 | int socket = -1; |
| 75 | 47 | int maxSocket = -1; |
| 76 | 49 | |
| 77 | @synchronized(self) |
|
| 78 | { |
|
| 79 | socket = commsSocket; |
|
| 80 | } |
|
| 81 | 47 | |
| 82 | tv.tv_sec = 1; |
|
| 83 | tv.tv_usec = 0; |
|
| 84 | ||
| 85 | FD_ZERO(&readfds); |
|
| 86 | FD_ZERO(&writefds); |
|
| 87 | FD_ZERO(&errorfds); |
|
| 88 | ||
| 89 | 49 | FD_SET(socket, &readfds); |
| 90 | FD_SET(socket, &errorfds); |
|
| 91 | maxSocket = MAX(maxSocket, socket); |
|
| 92 | 47 | |
| 93 | if (maxSocket < 0) |
|
| 94 | { |
|
| 95 | //printf("No sockets, sleeping for a bit...\n"); |
|
| 96 | usleep(1000000); |
|
| 97 | continue; |
|
| 98 | } |
|
| 99 | ||
| 100 | if (select(maxSocket+1, &readfds, &writefds, &errorfds, &tv) < 0) |
|
| 101 | { |
|
| 102 | perror("select"); |
|
| 103 | break; |
|
| 104 | } |
|
| 105 | ||
| 106 | 49 | if (FD_ISSET(socket, &readfds)) |
| 107 | 47 | { |
| 108 | //NSLog(@"receiving..."); |
|
| 109 | if (!expectedMessageSize) |
|
| 110 | { |
|
| 111 | uint32_t buf = 0; |
|
| 112 | int actuallyRead = 0; |
|
| 113 | |
|
| 114 | 49 | actuallyRead = recv(socket, &buf, sizeof(uint32_t), MSG_PEEK); |
| 115 | 47 | |
| 116 | if (actuallyRead == sizeof(uint32_t)) |
|
| 117 | { |
|
| 118 | 49 | actuallyRead = recv(socket, &buf, sizeof(uint32_t), 0); |
| 119 | 47 | expectedMessageSize = ntohl(buf); |
| 120 | currentData = [[NSMutableData alloc] initWithLength: expectedMessageSize]; |
|
| 121 | } |
|
| 122 | 48 | else if (actuallyRead == -1) |
| 123 | { |
|
| 124 | //close(commsSocket); |
|
| 125 | //self->commsSocket = 0; |
|
| 126 | if (errno != ETIMEDOUT) |
|
| 127 | { |
|
| 128 | printf("Connection dropped with error.\n"); |
|
| 129 | break; |
|
| 130 | } |
|
| 131 | 47 | } |
| 132 | 49 | else if (actuallyRead == 0) |
| 133 | { |
|
| 134 | printf("remote socket closed.\n"); |
|
| 135 | break; |
|
| 136 | } |
|
| 137 | 47 | } |
| 138 | else |
|
| 139 | { |
|
| 140 | size_t readAmount = expectedMessageSize - currentlyRead; |
|
| 141 | int actuallyRead = 0; |
|
| 142 | |
|
| 143 | 49 | actuallyRead = recv(socket, [currentData mutableBytes] + currentlyRead, readAmount, 0); |
| 144 | 47 | if (actuallyRead == -1) |
| 145 | { |
|
| 146 | printf("Connection dropped with error.\n"); |
|
| 147 | break; |
|
| 148 | } |
|
| 149 | 49 | else if (actuallyRead == 0) |
| 150 | { |
|
| 151 | printf("remote socket closed.\n"); |
|
| 152 | break; |
|
| 153 | } |
|
| 154 | ||
| 155 | 47 | currentlyRead += actuallyRead; |
| 156 | |
|
| 157 | if (currentlyRead == expectedMessageSize) |
|
| 158 | { |
|
| 159 | @synchronized(self) |
|
| 160 | { |
|
| 161 | expectedMessageSize = 0; |
|
| 162 | /* |
|
| 163 | if (!receivedPackets) |
|
| 164 | receivedPackets = [[NSMutableArray alloc] init]; |
|
| 165 | [receivedPackets addObject: currentData]; |
|
| 166 | [currentData release]; |
|
| 167 | */ |
|
| 168 | |
|
| 169 | } |
|
| 170 | 48 | |
| 171 | if (receiveDataOnMainThread) |
|
| 172 | [self performSelectorOnMainThread: @selector(dataReceived:) withObject: currentData waitUntilDone: NO]; |
|
| 173 | else |
|
| 174 | [self dataReceived: currentData]; |
|
| 175 | ||
| 176 | 47 | currentData = nil; |
| 177 | currentlyRead = 0; |
|
| 178 | } |
|
| 179 | } |
|
| 180 | ||
| 181 | } |
|
| 182 | } |
|
| 183 | |
|
| 184 | [self threadWillExit: info]; |
|
| 185 | ||
| 186 | @synchronized(self) |
|
| 187 | { |
|
| 188 | [self release]; |
|
| 189 | } |
|
| 190 | ||
| 191 | [info release]; |
|
| 192 | [pool drain]; |
|
| 193 | } |
|
| 194 | ||
| 195 | ||
| 196 | - (void) runThreadWithSelector: (SEL) selector |
|
| 197 | { |
|
| 198 | @synchronized(self) |
|
| 199 | { |
|
| 200 | if (!activeThreads) |
|
| 201 | activeThreads = [[NSMutableDictionary alloc] init]; |
|
| 202 | id number = [NSNumber numberWithInt: threadIds++]; |
|
| 203 | ||
| 204 | [activeThreads setObject: [NSNumber numberWithBool: YES] forKey: number]; |
|
| 205 | [NSThread detachNewThreadSelector: selector toTarget: self withObject: [number retain]]; |
|
| 206 | } |
|
| 207 | } |
|
| 208 | ||
| 209 | - (void) sendData: (NSData*) tapData |
|
| 210 | { |
|
| 211 | [sendLock lock]; |
|
| 212 | ||
| 213 | if (!sendQueue) |
|
| 214 | sendQueue = [[NSMutableArray alloc] init]; |
|
| 215 | ||
| 216 | [sendQueue addObject: tapData]; |
|
| 217 | |
|
| 218 | [sendLock signal]; |
|
| 219 | [sendLock unlock]; |
|
| 220 | |
|
| 221 | } |
|
| 222 | ||
| 223 | ||
| 224 | - (void) sendingThread: (id) info |
|
| 225 | { |
|
| 226 | NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; |
|
| 227 | ||
| 228 | @synchronized(self) |
|
| 229 | { |
|
| 230 | [self retain]; |
|
| 231 | } |
|
| 232 | ||
| 233 | while ([self threadActive: info]) |
|
| 234 | { |
|
| 235 | [sendLock lock]; |
|
| 236 | while (![sendQueue count]) |
|
| 237 | [sendLock wait]; |
|
| 238 | |
|
| 239 | //NSLog(@"sending"); |
|
| 240 | |
|
| 241 | NSData* data = [[sendQueue objectAtIndex: 0] retain]; |
|
| 242 | [sendQueue removeObjectAtIndex: 0]; |
|
| 243 | |
|
| 244 | [sendLock unlock]; |
|
| 245 | ||
| 246 | size_t sizeToSend = 4; |
|
| 247 | size_t dataSent = 0; |
|
| 248 | uint32_t header = htonl([data length]); |
|
| 249 | int err = 0; |
|
| 250 | 49 | int socket = -1; |
| 251 | |
|
| 252 | @synchronized(self) |
|
| 253 | { |
|
| 254 | socket = commsSocket; |
|
| 255 | } |
|
| 256 | 47 | |
| 257 | while (dataSent < sizeToSend) |
|
| 258 | { |
|
| 259 | 49 | if ((err = send(socket, &header + dataSent, sizeToSend - dataSent, 0)) == -1) |
| 260 | 47 | { |
| 261 | perror("send"); |
|
| 262 | break; |
|
| 263 | } |
|
| 264 | else |
|
| 265 | dataSent += err; |
|
| 266 | } |
|
| 267 | |
|
| 268 | if (err != -1) |
|
| 269 | { |
|
| 270 | sizeToSend = [data length]; |
|
| 271 | dataSent = 0; |
|
| 272 | while (dataSent < sizeToSend) |
|
| 273 | { |
|
| 274 | 49 | if ((err = send(socket, [data bytes] + dataSent, sizeToSend - dataSent, 0)) == -1) |
| 275 | 47 | { |
| 276 | perror("send"); |
|
| 277 | break; |
|
| 278 | } |
|
| 279 | else |
|
| 280 | dataSent += err; |
|
| 281 | |
|
| 282 | } |
|
| 283 | } |
|
| 284 | [data release]; |
|
| 285 | |
|
| 286 | if (err == -1) |
|
| 287 | break; |
|
| 288 | |
|
| 289 | } |
|
| 290 | |
|
| 291 | ||
| 292 | [self threadWillExit: info]; |
|
| 293 | ||
| 294 | @synchronized(self) |
|
| 295 | { |
|
| 296 | [self release]; |
|
| 297 | } |
|
| 298 | ||
| 299 | [info release]; |
|
| 300 | [pool drain]; |
|
| 301 | } |
|
| 302 | ||
| 303 | 46 | @end |
| 304 | ||
| 305 | @implementation UITouch (Synthesize) |
|
| 306 | ||
| 307 | - (id)initInView:(UIView *)view |
|
| 308 | { |
|
| 309 | self = [super init]; |
|
| 310 | if (self != nil) |
|
| 311 | { |
|
| 312 | CGRect frameInWindow; |
|
| 313 | if ([view isKindOfClass:[UIWindow class]]) |
|
| 314 | { |
|
| 315 | frameInWindow = view.frame; |
|
| 316 | } |
|
| 317 | else |
|
| 318 | { |
|
| 319 | frameInWindow = |
|
| 320 | [view.window convertRect:view.frame fromView:view.superview]; |
|
| 321 | } |
|
| 322 | |
|
| 323 | _tapCount = 1; |
|
| 324 | _locationInWindow = |
|
| 325 | CGPointMake( |
|
| 326 | frameInWindow.origin.x + 0.5 * frameInWindow.size.width, |
|
| 327 | frameInWindow.origin.y + 0.5 * frameInWindow.size.height); |
|
| 328 | _previousLocationInWindow = _locationInWindow; |
|
| 329 | ||
| 330 | UIView *target = [view.window hitTest:_locationInWindow withEvent:nil]; |
|
| 331 | _view = [target retain]; |
|
| 332 | _window = [view.window retain]; |
|
| 333 | _phase = UITouchPhaseBegan; |
|
| 334 | _touchFlags._firstTouchForView = 1; |
|
| 335 | _touchFlags._isTap = 1; |
|
| 336 | _timestamp = [NSDate timeIntervalSinceReferenceDate]; |
|
| 337 | } |
|
| 338 | return self; |
|
| 339 | } |
|
| 340 | ||
| 341 | - (void)changeToPhase:(UITouchPhase)phase |
|
| 342 | { |
|
| 343 | _phase = phase; |
|
| 344 | _timestamp = [NSDate timeIntervalSinceReferenceDate]; |
|
| 345 | } |
|
| 346 | ||
| 347 | @end |
|
| 348 | ||
| 349 | 49 | |
| 350 | /* |
|
| 351 | 46 | void _printGSPathPoint(GSTouchPointRef p) |
| 352 | { |
|
| 353 | // printf("P: 0x%08X 0x%08X 0x%08X 0x%08X (%G, %G)\n", p->unk0, p->unk1, p->unk2, p->unk5, p->x, p->y); |
|
| 354 | printf("P: 0x%08X %7G %7G (%G, %G)\n", p->unk0, p->unk1, p->touchSize, p->x, p->y); |
|
| 355 | } |
|
| 356 | ||
| 357 | void _printGSEvent(UIEvent* event) |
|
| 358 | { |
|
| 359 | GSEvent* e = [event _gsEvent]; |
|
| 360 | // printf("%p, %p\n", event, e); |
|
| 361 | // printf("0x%08X 0x%08X 0x%08X\n", e->unk1, e->unk2, e->unk3); |
|
| 362 | ||
| 363 | // printf("type0 0x%08X type1 0x%08X r3 0x%08X\n", e->type0, e->type1, e->r3); |
|
| 364 | // printf("type10 0x%08X r11 0x%08X type12 0x%08X\n", e->type10, e->r11, e->type12); |
|
| 365 | // printf("gesture12 0x%08X gesture14 0x%08X\n", e->gesture13, e->gesture14); |
|
| 366 | ||
| 367 | // printf("avg0 (%5G, %5G), avg1 (%5G, %5G)\n", e->avgX0, e->avgY0, e->avgX1, e->avgY1); |
|
| 368 | // printf("(%d) %d\n", e->numInitialTouches, e->numCurrentTouches); |
|
| 369 | // printf("unk16 0x%08X unk17 0x%08X unk18 0x%08X unk19 0x%08X\n", e->unk16, e->unk17, e->unk18, e->unk19); |
|
| 370 | // printf("r20 0x%08X r21 0x%08X\n", e->r20, e->r21); |
|
| 371 | printf("points %d\n", e->numPoints); |
|
| 372 | ||
| 373 | // printf("unk9 0x%08X unk10 0x%08X unk11 0x%08X unk12 0x%08X\n", e->unk9, e->unk10, e->unk11, e->unk12); |
|
| 374 | // printf("%u.%u\n", e->timestamp_s, e->timestamp_ns); |
|
| 375 | // printf("%G\n", (double)e->timestamp*1e-9); |
|
| 376 | // printf("unk12 0x%08X unk13 0x%08X unk14 0x%08X unk15 0x%08X\n", e->unk12, e->unk13, e->unk14, e->unk15); |
|
| 377 | for(size_t i = 0; i < e->numPoints; ++i) |
|
| 378 | _printGSPathPoint(e->points+i); |
|
| 379 | printf("\n"); |
|
| 380 | } |
|
| 381 | ||
| 382 | @implementation GSEvent |
|
| 383 | @end |
|
| 384 | 49 | */ |
| 385 | 46 |
Loggerhead 1.17 is a web-based interface for Bazaar branches