diff options
author | Teddy Wing | 2018-08-21 05:45:16 +0200 |
---|---|---|
committer | Teddy Wing | 2018-08-21 06:06:47 +0200 |
commit | 9ebf6a1461f6322691abc5f6547fcf6eb6f2dae4 (patch) | |
tree | e11470629bb6b8c5264c371bcced64b349c26777 | |
parent | 4e62e8ad7abf833a3d2cb7ddfe01161e91c648ad (diff) | |
download | DomeKey-9ebf6a1461f6322691abc5f6547fcf6eb6f2dae4.tar.bz2 |
HeadphoneKey: Add system for handling dead keys
We need a way to listen for multiple presses of the headphone buttons.
Once a timeout has been reached, the recorded button presses that
happened within the space of the timeout will be those used for
performing an associated action.
We add an enum for headphone buttons to give them an easy name to refer
to.
The default timeout between button presses before an action gets
executed is 1000 milliseconds. This will be customisable later with a
configuration file.
Already pressed "dead" keys within the timeout are stored in
`_key_buffer`. This buffer gets cleared when we run an action. I you've
pressed a headphone button key, we always try to run an action, so this
will always get cleared, even if no mapping action is found.
I decided to start `_key_buffer` with a capacity of 5 at random because
that seemed like more than enough button presses for a single mapping.
handleDeadKey::
- In order to append a `HeadphoneButton` from our enum, I needed to
convert it to an `id` type because `NSArray` doesn't allow anything
else.
- Call `maybeRunAction` with our timeout. Before doing this, make sure
we cancel any previous delayed calls to `maybeRunAction` because they
might be executed before the most recent headphone button press and
thus run the wrong action. Cancelling enables us to only run the
action once the timeout has elapsed after the most recent headphone
button press.
maybeRunAction:
- Just log the headphone button presses for now.
- Remove all presses from `_key_buffer` so to make way for a new key
mapping.
- I'm now thinking I should rename this method to remove the `maybe`.
Since the `performSelector` gets cancelled outside of this method, the
"maybe" doesn't make sense to me here any more.
-rw-r--r-- | DomeKey/HeadphoneKey.h | 12 | ||||
-rw-r--r-- | DomeKey/HeadphoneKey.m | 27 |
2 files changed, 39 insertions, 0 deletions
diff --git a/DomeKey/HeadphoneKey.h b/DomeKey/HeadphoneKey.h index 0d4e729..c1b8e85 100644 --- a/DomeKey/HeadphoneKey.h +++ b/DomeKey/HeadphoneKey.h @@ -14,8 +14,20 @@ typedef enum KeyPress : BOOL { KeyPressUp = NO } KeyPress; +typedef enum HeadphoneButton : NSUInteger { + HeadphoneButton_Play, + HeadphoneButton_Up, + HeadphoneButton_Down +} HeadphoneButton; + +static const unsigned int TIMEOUT_MILLISECONDS = 1000; + @interface HeadphoneKey : NSObject { NSArray *_mikeys; + NSMutableArray *_key_buffer; } +- (void)handleDeadKey:(HeadphoneButton)button; +- (void)maybeRunAction; + @end diff --git a/DomeKey/HeadphoneKey.m b/DomeKey/HeadphoneKey.m index 0593173..d5fdb8d 100644 --- a/DomeKey/HeadphoneKey.m +++ b/DomeKey/HeadphoneKey.m @@ -14,6 +14,8 @@ { self = [super init]; if (self) { + _key_buffer = [[NSMutableArray alloc] initWithCapacity:5]; + _mikeys = [DDHidAppleMikey allMikeys]; [_mikeys makeObjectsPerformSelector:@selector(setDelegate:) withObject:self]; @@ -32,15 +34,40 @@ switch (usageId) { case kHIDUsage_Csmr_PlayOrPause: NSLog(@"Middle"); + [self handleDeadKey:HeadphoneButton_Play]; break; case kHIDUsage_Csmr_VolumeIncrement: NSLog(@"Top"); + [self handleDeadKey:HeadphoneButton_Up]; break; case kHIDUsage_Csmr_VolumeDecrement: NSLog(@"Bottom"); + [self handleDeadKey:HeadphoneButton_Down]; break; } } } +- (void)handleDeadKey:(HeadphoneButton)button +{ + NSNumber *storable_button = [NSNumber numberWithUnsignedInteger:button]; + [_key_buffer addObject:storable_button]; + + [NSObject cancelPreviousPerformRequestsWithTarget:self + selector:@selector(maybeRunAction) + object:nil]; + + NSTimeInterval timeout_seconds = TIMEOUT_MILLISECONDS / 1000.0; + [self performSelector:@selector(maybeRunAction) + withObject:nil + afterDelay:timeout_seconds]; +} + +- (void)maybeRunAction +{ + NSLog(@"%@", _key_buffer); + + [_key_buffer removeAllObjects]; +} + @end |