+ return cookieToButtonMapping;
+}
+
+- (NSString*) validCookieSubstring: (NSString*) cookieString {
+ if (cookieString == nil || [cookieString length] == 0) return nil;
+ NSEnumerator* keyEnum = [[self cookieToButtonMapping] keyEnumerator];
+ NSString* key;
+ while(key = [keyEnum nextObject]) {
+ NSRange range = [cookieString rangeOfString:key];
+ if (range.location == 0) return key;
+ }
+ return nil;
+}
+
+- (void) sendSimulatedPlusMinusEvent: (id) time {
+ BOOL startSimulateHold = NO;
+ AppleRemoteEventIdentifier event = lastPlusMinusEvent;
+ @synchronized(self) {
+ startSimulateHold = (lastPlusMinusEvent>0 && lastPlusMinusEventTime == [time doubleValue]);
+ }
+ if (startSimulateHold) {
+ lastEventSimulatedHold = YES;
+ event = (event==kRemoteButtonVolume_Plus) ? kRemoteButtonVolume_Plus_Hold : kRemoteButtonVolume_Minus_Hold;
+ [delegate appleRemoteButton:event pressedDown: YES clickCount: 1];
+ }
+}
+
+- (void) sendRemoteButtonEvent: (AppleRemoteEventIdentifier) event pressedDown: (BOOL) pressedDown {
+ if (delegate) {
+ if (simulatePlusMinusHold) {
+ if (event == kRemoteButtonVolume_Plus || event == kRemoteButtonVolume_Minus) {
+ if (pressedDown) {
+ lastPlusMinusEvent = event;
+ lastPlusMinusEventTime = [NSDate timeIntervalSinceReferenceDate];
+ [self performSelector:@selector(sendSimulatedPlusMinusEvent:)
+ withObject:[NSNumber numberWithDouble:lastPlusMinusEventTime]
+ afterDelay:HOLD_RECOGNITION_TIME_INTERVAL];
+ return;
+ } else {
+ if (lastEventSimulatedHold) {
+ event = (event==kRemoteButtonVolume_Plus) ? kRemoteButtonVolume_Plus_Hold : kRemoteButtonVolume_Minus_Hold;
+ lastPlusMinusEvent = 0;
+ lastEventSimulatedHold = NO;
+ } else {
+ @synchronized(self) {
+ lastPlusMinusEvent = 0;
+ }
+ pressedDown = YES;
+ }
+ }
+ }
+ }
+
+ if (([self clickCountEnabledButtons] & event) == event) {
+ if (pressedDown==NO && (event == kRemoteButtonVolume_Minus || event == kRemoteButtonVolume_Plus)) {
+ return; // this one is triggered automatically by the handler
+ }
+ NSNumber* eventNumber;
+ NSNumber* timeNumber;
+ @synchronized(self) {
+ lastClickCountEventTime = [NSDate timeIntervalSinceReferenceDate];
+ if (lastClickCountEvent == event) {
+ eventClickCount = eventClickCount + 1;
+ } else {
+ eventClickCount = 1;
+ }
+ lastClickCountEvent = event;
+ timeNumber = [NSNumber numberWithDouble:lastClickCountEventTime];
+ eventNumber= [NSNumber numberWithUnsignedInt:event];
+ }
+ [self performSelector: @selector(executeClickCountEvent:)
+ withObject: [NSArray arrayWithObjects:eventNumber, timeNumber, nil]
+ afterDelay: maxClickTimeDifference];
+ } else {
+ [delegate appleRemoteButton:event pressedDown: pressedDown clickCount:1];
+ }
+ }
+}
+
+- (void) executeClickCountEvent: (NSArray*) values {
+ AppleRemoteEventIdentifier event = [[values objectAtIndex: 0] unsignedIntValue];
+ NSTimeInterval eventTimePoint = [[values objectAtIndex: 1] doubleValue];
+
+ BOOL finishedClicking = NO;
+ int finalClickCount = eventClickCount;
+
+ @synchronized(self) {
+ finishedClicking = (event != lastClickCountEvent || eventTimePoint == lastClickCountEventTime);
+ if (finishedClicking) eventClickCount = 0;
+ }
+
+ if (finishedClicking) {
+ [delegate appleRemoteButton:event pressedDown: YES clickCount:finalClickCount];
+ if ([self simulatesPlusMinusHold]==NO && (event == kRemoteButtonVolume_Minus || event == kRemoteButtonVolume_Plus)) {
+ // trigger a button release event, too
+ [NSThread sleepUntilDate: [NSDate dateWithTimeIntervalSinceNow:0.1]];
+ [delegate appleRemoteButton:event pressedDown: NO clickCount:finalClickCount];
+ }
+ }
+