aboutsummaryrefslogtreecommitdiffstats
AgeCommit message (Collapse)Author
2018-10-26LicenseHandler(addLicense:): Move license file to trash manuallyTeddy Wing
Get the trash directory and move the file there manually. Unfortunately, this doesn't do the renaming of the file if there's a name conflict, so we still need to look into how to deal with that. Thanks to Vincent Tourraine (https://stackoverflow.com/users/135712/vincent-tourraine) on Stack Overflow (https://stackoverflow.com/questions/46089964/how-do-i-get-rid-of-ios-version-is-partial-introduced-in-ios-x-warnings-in-xc/46274231#46274231) for explaining how to get rid of the `-Wunguarded-availability` warnings I was getting as a result of using `NSTrashDirectory`. Apparently using the availability macros doesn't silence the error. Since we're already checking for availability without `@available`, forcibly silence the warning here.
2018-10-26LicenseHandler(addLicense:): Delete license file instead of trashing itTeddy Wing
The trash/recycle method wasn't working because it was asynchronous. As a result, the file never got moved. Using `removeItemAtURL:error:` does work, and is available starting in OS 10.6. But I still don't like the idea of forcibly deleting files. What if the user licenses the program and deletes their license file, then somehow gets their only local copy deleted? Need to work out a different way of doing this.
2018-10-26main: Use `sysexits.h` constants as return valuesTeddy Wing
2018-10-26Add license file using `--license` argumentTeddy Wing
When a license path is passed in with `--license`, call `addLicense:`. Otherwise we run the license validator.
2018-10-26lib/dome-key-map: Update to exit after help outputTeddy Wing
2018-10-26main: Print version string when the `version` command line arg is passedTeddy Wing
Store the version string in code, as otherwise the only way to get it appears to be from Info.plist, and we don't have one of those in this application.
2018-10-26lib/dome-key-map: Update to include trial and command line updatesTeddy Wing
2018-10-25LicenseHandler: Move invalid license error message to a new methodTeddy Wing
This enables us to print the error message in both of the following cases: 1. Validating an existing key 2. Adding a new license key
2018-10-25LicenseHandler(addLicense:): Use `NSWorkspace` to move to trashTeddy Wing
The `trashItemAtURL:resultingItemURL:error:` method in `NSFileManager` is only available starting from Mac OS X 10.8. Replace this with a more compatible API call. At first I was thinking about using `NSWorkspace` `performFileOperation:source:destination:files:tag:`, since it works starting from 10.0. However, I'd need to remove the `license.plist` path component from the `NSURL` from `licensePath` in order to pass it to the `source:` argument. I found `NSURL` `URLByDeletingLastPathComponent`, which would make perfect sense, except it's only implemented starting in 10.6. At that point, I figured why not use `NSWorkspace` `recycleURLs:completionHandler:`, which exists starting in 10.6, and has a simpler interface than `performFileOperation:source:destination:files:tag:`. Import AppKit in order to be able to use `NSWorkspace`.
2018-10-25LicenseHandler: Implement `addLicense:` methodTeddy Wing
Copies the given license into XDG_DATA_HOME and validates it. This allows us to keep the user's license in a consistent location where it can be validated on every launch. Errors are printed to stderr. If the license file fails validation, it gets moved to the trash. The original license file passed in by the user will remain intact, only the one copied to XDG_DATA_HOME gets removed. Call the function from `main` with a temporary hard-coded value to test out the function. The real path value will come from a command-line argument. We may end up removing the `validateLicense` call and subsequent related code here if it always gets called anyway. Still not sure if it should look like: if (--license passed in) { [LicenseHandler addLicense:l]; } else { [LicenseHandler check]; } or if (--license passed in) { [LicenseHandler addLicense:l]; } [LicenseHandler check]; If the second, we should keep some kind of trashing functionality as otherwise a subsequent `addLicense:` call will result in an error like this: dome-key: error: “dome-key-license.plist” couldn’t be copied to “dome-key” because an item with the same name already exists. TODO: `trashItemAtURL:resultingItemURL:error:` was introduced in OS X 10.8. We need to change this to use an `NSWorkspace` method.
2018-10-25LicenseHandler: Handle `APSetKey` returning falseTeddy Wing
If `APSetKey()` returns false, the public key failed to get loaded by the AquaticPrime library, and we won't subsequently be able to `APVerifyLicenseFile()`. If `APSetKey()` fails, return `NO` from this `validateLicense` method.
2018-10-25LicenseHandler: Validate license filesTeddy Wing
Fill in the `check` method to have it validate a license file. If the file doesn't validate, prints an error message. A bunch of supporting methods to check if the license file at the program's prescribed path exists. Use AquaticPrime's CoreFoundation functions to validate the license file. Include my public key, generated by the "AquaticPrime Developer" app, with the CFStringAppend calls copied from the program's generated "Obfuscated Public Key" text box. Run the validation check on launch in `main.m`. Add an `eprintf` macro to print to stderr with a prepended program identifier.
2018-10-25XDG: Add methods to get the XDG_DATA_HOME pathTeddy Wing
Gets the path from the environment variable or uses the default path. Additionally provides a method for getting the "dome-key" subdirectory in XDG_DATA_HOME.
2018-10-24Add an `XDG` classTeddy Wing
For interacting with XDG directories.
2018-10-24LicenseHandler: Add method stubsTeddy Wing
2018-10-24Add `LicenseHandler`Teddy Wing
This class will encapsulate all license and trial handling.
2018-10-24DomeKey.xcodeproj: Change deployment target to 10.7Teddy Wing
Turns out the build had failed previously because the linked Rust library expects 10.7. Change the deployment target to match and now it works.
2018-10-24Makefile: Add a `clean` targetTeddy Wing
2018-10-24DomeKey.xcodeproj: Change deployment target to 10.6Teddy Wing
Include support for older OSes. The build currently fails with this target, so I'm going to look into what's going on. Unlikely to actually work on 10.6 since the Rust toolchain is built against 10.7, but should hopefully work from there.
2018-10-24DomeKey.xcodeproj: Add AquaticPrime source filesoTeddy Wing
Add the files to the project to compile them into the build.
2018-10-24Add 'lib/AquaticPrime' submoduleTeddy Wing
Will be using the `CoreFoundation` library code to handle licensing for DomeKey. Set this up as a sparse checkout to only checkout the `Source/CoreFoundation/` path from the repository. Doesn't seem like this is going to carry over for other people who `git submodule init` though. Not sure how this works. Found these resources on how to set up a sparse checkout: - https://briancoyner.github.io/2013/06/05/git-sparse-checkout.html - https://stackoverflow.com/questions/6238590/set-git-submodule-to-shallow-clone-sparse-checkout Followed a Stack Overflow post by 'max630' (https://stackoverflow.com/users/2303202/max630) to set up the submodule as a sparse checkout: git init # I did not find a way to add submodule in 1 step without checking out git clone --depth=1 --no-checkout ../sub sub git submodule add ../sub sub git submodule absorbgitdirs # note there is no "submodule.sub.sparsecheckout" key git -C sub config core.sparseCheckout true # note quoted wildcards to avoid their expansion by shell echo 'foo/*' >>.git/modules/sub/info/sparse-checkout git submodule update --force --checkout sub (https://stackoverflow.com/questions/45688121/how-to-do-submodule-sparse-checkout-with-git/45689692#45689692) Ran the following commands to set up the sparse checkout submodule based on the instructions in the post: $ git clone --no-checkout https://github.com/bdrister/AquaticPrime.git lib/AquaticPrime Cloning into 'lib/AquaticPrime'... remote: Enumerating objects: 797, done. remote: Total 797 (delta 0), reused 0 (delta 0), pack-reused 797 Receiving objects: 100% (797/797), 829.07 KiB | 599.00 KiB/s, done. Resolving deltas: 100% (343/343), done. $ git submodule add https://github.com/bdrister/AquaticPrime.git lib/AquaticPrime Adding existing repo at 'lib/AquaticPrime' to the index $ git submodule absorbgitdirs Migrating git directory of 'lib/AquaticPrime' from '.../DomeKey/lib/AquaticPrime/.git' to '.../DomeKey/.git/modules/lib/AquaticPrime' $ git -C lib/AquaticPrime config core.sparsecheckout true $ echo 'Source/CoreFoundation/' > .git/modules/lib/AquaticPrime/info/sparse-checkout $ git submodule update --force --checkout lib/AquaticPrime
2018-10-21Use new name for `config_read_from_file()`Teddy Wing
This function was renamed.
2018-10-20Update TODOTeddy Wing
Not permitting a custom config file or log file. They might be things that get added later, but don't feel necessary for launch.
2018-10-20Get timeout from configTeddy Wing
Pass the config through the app, and pass the timeout it contains to `HeadphoneKey`. This enables us to have a user-configurable timeout through a config file.
2018-10-20Use new `c_parse_args()` method signatureTeddy Wing
The function now takes a third `Config *` argument. Create a new config struct with `config_read_from_file()` and pass it to `c_parse_args()`. TODO: Rename `config_read_from_file`
2018-10-20lib/dome-key-map: Update for config file handlingTeddy Wing
Need to update `c_parse_args()` call to pass new third argument.
2018-10-18Update TODOTeddy Wing
2018-10-18lib/dome-key-map: Update to get special media keysoTeddy Wing
Key actions like `<VolumeDown>`, `<Play>`, etc.
2018-10-18Revert "Test code to press the "play" media key"Teddy Wing
This reverts commit d1954a7d49d010929f0444d4127dfe130a890a8e. This code has been moved to the `dome_key_event_source_simulator` repository to be included as a static library in our Rust static library.
2018-10-13Test code to press the "play" media keyTeddy Wing
Based on code from Albert https://stackoverflow.com/users/133374/albert and Nick Sweeting https://stackoverflow.com/users/2156113/nick-sweeting on Stack Overflow: - https://stackoverflow.com/questions/11045814/emulate-media-key-press-on-mac/11048135#11048135 - https://stackoverflow.com/questions/10459085/cocoa-simulate-macbook-upper-keys-multimedia-keys/50574159#50574159 Proof of concept code that simulates a key press of the "play" media key. Worked basically on the first try here, after the Rust version of the code giving me so much segfault hell. Going to adapt this to a generic function that I can pass as a pointer to the Rust code to call to send a media key event.
2018-10-10Update TODOTeddy Wing
2018-10-09Try moving MPRemoteCommandCenter to AppDelegateTeddy Wing
Wanted to see if moving this closer to the launch point of the application and also storing a reference to the command center in an ivar would change anything. It didn't, still doesn't appear to work for listening to Bluetooth button events.
2018-10-07HeadphoneKey: Try using `MPRemoteCommandCenter` to listen for media keysTeddy Wing
Try to use `MPRemoteCommandCenter` to get Bluetooth button input. Doesn't appear to work.
2018-10-07Try listening to Bluetooth headphone buttonsTeddy Wing
Second attempt at getting events from Bluetooth headphone buttons. This time with some code from KillerDeMouches and Josh Guice. The magic numbers make no sense to me. Would have loved to have constants, but hypothesizing that maybe they were gathered from direct input and event monitoring using Karabiner's event monitor. Unfortunately, this code didn't work for me. I still have to try it on a < 10.12 machine, as maybe it'll work there (_hopefully_, as there was very scarce material online about how to do this). My next attempt is going to be using `MPRemoteCommandCenter`. Hoping that will work, but it's only going to be a solution for >= 10.12.
2018-10-07main: Switch back to `NSApplication`Teddy Wing
Since media keys didn't work for Bluetooth button interception, revert back to `NSApplication` instead of our subclass.
2018-10-07Try listening to media keysTeddy Wing
Use Peter Maurer's mechanism for getting media key events. Code taken from a Rogue Amoeba article. My hope was that this would allow us to intercept Bluetooth headphone key presses. It didn't. I'll likely be reverting this code.
2018-10-06Add DKApplicationTeddy Wing
Will be used to override the `sendEvent:` method to try to intercept media key events as described in https://weblog.rogueamoeba.com/2007/09/29/. Trying to find out if intercepting these events will enable the program to work with Bluetooth headphones.
2018-10-06Update TODOTeddy Wing
2018-10-06Update TODOTeddy Wing
2018-10-06HeadphoneKey: Free `_state` when deallocatingTeddy Wing
2018-10-06main: Free the config objectTeddy Wing
2018-10-06Update TODOTeddy Wing
2018-10-06Makefile(run): Add the `--daemon` flag to the executableTeddy Wing
Now that the `--daemon` flag is required to go into daemon mode instead of it happening automatically, add this flag to the `run` target to give us the same behaviour we had before.
2018-10-06Mappings(dispatchReload): Return result of `notify_post()`Teddy Wing
Return this as the exit code so we can pass the information back to the client.
2018-10-06main: Run main NSApp code when the `--daemon` flag is passedTeddy Wing
2018-10-06Parse command line arguments with the `dome-key-map` libraryTeddy Wing
2018-10-05Set up IPC to enable reloading the mappings fileTeddy Wing
My original plan was to use an `NSXPCConnection` to handle the IPC for reloading mappings. For some background, this is what I'm envisioning: 1. DomeKey is running in the background 2. User wants to make a change to their config. Update `mappings.dkmap`. 3. The new mappings file needs to be re-parsed and reloaded into memory. The simplest thing we could do is just quit and relaunch DomeKey. but that's kind of a pain. So instead, we run something like this from the command line: $ dome-key --reload-mappings This will tell the running DomeKey process to update its mappings by reloading the mappings file. As I said, I was going to use `NSXPCConnection` for the IPC communication, as it had come up in my research for IPC mechanisms on OS X. I knew I didn't want to use a TCP socket as that seemed like too much overhead. The ability to pass messages to classes "directly" using `NSXPCConnection` was very appealing. However, I got a little lazy trying to learn it. It has a whole model for how the communication should work, including various procedures that need to be set up using its API. It started to feel like a bit of a pain. At that point I started looking into alternatives. One idea was to move the IPC into the Rust code and use Unix Domain Sockets (https://doc.rust-lang.org/std/os/unix/net/struct.UnixListener.html). I was tempted to go this route, but I wasn't a fan of the need to always be listening, the potential need to spawn a thread to reload the mappings to free up the main workload, the need to figure out a way to pass `State` (which keeps our parsed mappings in memory) around, and the fact that only plain strings are passed, instead of messages in the case of `NSXPCConnection`. I came across https://developer.apple.com/library/archive/documentation/MacOSX/Conceptual/OSX_Technology_Overview/SystemTechnology/SystemTechnology.html where I discovered BSD notifications and `notify.3`. This seemed to be the lightweight easy-to-use solution that I was looking for. After following a little sample code, it works like a charm.
2018-10-04Add a new `Mappings` classTeddy Wing
We'll reload the mappings file here.
2018-10-04Update TODOTeddy Wing
2018-10-04HeadphoneKey: Update for latest dome-key-map APITeddy Wing
There is no longer a return value for `c_run_key_action()`, and the `CKeyActionResult` struct no longer exists. Update the code to reflect this.