Age | Commit message (Collapse) | Author |
|
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.
|
|
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.
|
|
|
|
When a license path is passed in with `--license`, call `addLicense:`.
Otherwise we run the license validator.
|
|
|
|
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.
|
|
|
|
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
|
|
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`.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
For interacting with XDG directories.
|
|
|
|
This class will encapsulate all license and trial handling.
|
|
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.
|
|
|
|
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.
|
|
Add the files to the project to compile them into the build.
|
|
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
|
|
This function was renamed.
|
|
Not permitting a custom config file or log file. They might be things
that get added later, but don't feel necessary for launch.
|
|
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.
|
|
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`
|
|
Need to update `c_parse_args()` call to pass new third argument.
|
|
|
|
Key actions like `<VolumeDown>`, `<Play>`, etc.
|
|
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.
|
|
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.
|
|
|
|
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.
|
|
Try to use `MPRemoteCommandCenter` to get Bluetooth button input.
Doesn't appear to work.
|
|
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.
|
|
Since media keys didn't work for Bluetooth button interception, revert
back to `NSApplication` instead of our subclass.
|
|
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.
|
|
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.
|
|
|
|
|
|
|
|
|
|
|
|
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.
|
|
Return this as the exit code so we can pass the information back to the
client.
|
|
|
|
|
|
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.
|
|
We'll reload the mappings file here.
|
|
|
|
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.
|