| Age | Commit message (Collapse) | Author |
|
|
|
Including this flag will tell the program to play interface audio
(namely the sounds for mode activated & deactivated).
|
|
Take a function pointer argument that will be called whenever a mode is
activated or deactivated. We'll be using this on the Objective-C side to
play audio when the mode changes.
|
|
Mirror the `map::run_key_action()` function and add an extra `PlayAudio`
argument, which will control whether audio cues are played when a mode
is activated or deactivated.
The Objective-C code will pass in this value based on the value of a
`Config` setting, which will have come from a command line argument.
|
|
Give a namespace to our C functions to minimise chances of conflicts.
|
|
This argument is no longer used, as the current mode is tracked in
`State`.
|
|
Remove some unnecessary things. We aren't using `MapKind` any more, so
it can be removed.
|
|
|
|
Wrap the function in an `extern "C"` function, make it public, and
export it.
|
|
Should print the version of the program. Doesn't actually do any
printing in Rust, because the Rust library's version number is different
from the DomeKey program version. We just indicate to the Objective-C
code that it should print the version number.
|
|
Add a new argument that allows users to pass in the path to a license
file. Doing so should get picked up by the Objective-C code which will
copy and validate the license.
In order for the Objective-C code to pick up the path string, we add a
`license` field to the `Config.Args` struct.
The new `license` field is a `*mut c_char`, which means we can't derive
Default any more and need to implement a custom `Default` impl for
`Args`.
Additionally, 'getopts' gives us a Rust string (of course), which needs
to be converted into a raw `CString` before we can stick it in the
`license` field in `Args`. I previously wrote `dkeprintln` to be able to
print an error here at the conversion point between `CString` and raw C
string.
Since we used `CString#into_raw()`, we need to call `from_raw()` on the
pointer to free it, otherwise we end up with a memory leak. This
necessitated adding some additional code to `config_free()` to free the
`license` field if non-null.
In order to access `config.args.license` from within `config_free()`, I
also needed to make the `args` and `license` struct fields public, since
the free function is in a different module. Instead of making only those
two fields public, I decided to make them all public, as all the fields
are technically accessible from C code, and are needed by that C code.
Finally, move the module declaration of `prefix_println` to the top of
the module list instead of listing it alphabetically, because otherwise
any modules declared before it (like `config`) don't get access to its
macro. Also add a `#[macro_use]` attribute to the module declaration
because we do want to export its macro.
(https://stackoverflow.com/questions/26731243/how-do-i-use-a-macro-across-module-files#comment78329437_31749071)
|
|
This new module will contain functions to calculate trial days.
Here we implement a function to calculate the days remaining in a trial
period.
If there are less than 0 days remaining, it returns an error result.
Couldn't use 'error-chain' because it was complaining about `Debug` and
`PartialEq` not being defined. Don't know if it's possible to implement
those traits on 'error-chain''s ErrorKind`, but it was complicated
enough that I ended up not bothering. Went with 'quick_error' instead to
create a custom error type without having to `impl` all the required
traits.
|
|
For the same reason that we renamed the Rust version of this function to
`get_config`, rename this function also. (Since we're not necessarily
getting the config from a file.)
|
|
Enables us to get a `Config` struct from the config file in the
Objective-C app, which will then be passed to the `parse_args()`
function to be further filled in.
|
|
A new function that will read a TOML config file. Doesn't currently
access the filesystem. This commit is mostly supporting code to allow
that to work.
* Add the 'toml' crate
* `parse_args()`: Take a mutable `Config` and return that config instead
of creating a new one. The recipe will now be to read the config from
a file first and then pass that config to this function to be updated.
* Modify `c_parse_args()` to take a `*Config` and mirror the new method
signature of `parse_args()`
|
|
This new field will be used by the calling Objective-C code as the
timeout between multi-button maps.
It will be defined in a `config.toml` file in the XDG config directory,
with a default if unspecified. That part of the code hasn't been written
yet, but we've prepared by deriving Serde `Deserialize` on the `Config`
struct in order to deserialise a TOML config file.
The latest Serde is v1.0.80, but we can't use it because 'cbindgen'
depends on an older version. We had been using 'cbindgen' v0.6.3, which
depends on serde v1.0.21. Decided to update 'cbindgen' in order to use a
newer version of Serde, but that puts us at v1.0.58 instead of the
latest:
error: failed to select a version for `serde_derive`.
... required by package `cbindgen v0.6.6`
... which is depended on by `dome-key-map v0.0.1 (file:///Users/tw/Documents/Development/dome-key-map)`
versions that meet the requirements `= 1.0.58` are: 1.0.58
all possible versions conflict with previously selected packages.
previously selected package `serde_derive v1.0.80`
... which is depended on by `dome-key-map v0.0.1 (file:///Users/tw/Documents/Development/dome-key-map)`
failed to select a version for `serde_derive` which could resolve this conflict
|
|
Add this new key type to the enum and enable it to be `tap()`ped like
the others.
Made `NXKey` a type alias instead of a struct to allow us to refer to
any of the NX key constants using the `NXKey` type. This also meant
moving those NX constants outside of the `NXKey` impl and into the top
level. May end up wrapping them back up in some kind of namespace later.
Adjusted the public-ness of some functions to support this change.
|
|
Added a build of `libdome_key_event_source_simulator.a` to the root of
the project to test running the function from Rust. Works. Needs to be
built with custom `RUSTFLAGS` in order to build:
$ RUSTFLAGS="-L ." cargo test dktest
We'll need to figure out how to add this to the Rust build script.
Now that we know it works, we can integrate the static library more
permanently into the project.
|
|
Otherwise we aren't able to pass it to the `config_free()` function.
|
|
Otherwise it gets freed too early by Rust. Add (re-add) a free function
for it too now that we know it must be freed manually.
|
|
I was getting this error when I brought the library into the Objective-C
application:
Undefined symbols for architecture x86_64:
"_parse_args", referenced from:
_main in main.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Ended up renaming my FFI function to `c_parse_args()` (like with
`c_run_key_action()`) which fixed this. Going to have to rename those to
use a `dome_key_` prefix eventually.
Then, my `args` argument didn't have the right type. It had a `*const
c_char` type, which is a string, when it should have been an array of
strings. We just needed a double pointer. A Stack Overflow answer from
Tibor Benke (https://stackoverflow.com/users/3989982/tibor-benke) proved
helpful in this regard:
fn foo(argc: c_int, argv: *const *const c_char);
https://stackoverflow.com/questions/34379641/how-do-i-convert-rust-args-into-the-argc-and-argv-c-equivalents/34379937#34379937
Update the `map()` call to account for the new type, and check that we
don't have any null pointers within the array.
Finally, shift the first (command name) argument off the list when
parsing options as suggested in the 'getopts' doc example.
|
|
We want to be able to access the fields in `Config`, so make them
accessible across the FFI boundary.
* Return a regular, not boxed, `Config` from `parse_args()`.
* Add `repr(C)`s on our structs (had forgotten how this worked in
961b3b0b2d33a2c632fbc093b61e2c2d4dc07f70).
* Delete the `config_free()` function as I think the stuct doesn't need
to be freed being a POD struct. Hopefully that's the case.
|
|
This will allow us to parse command line arguments starting from a C
argv array (hopefully).
|
|
Get rid of the return values on `c_run_key_action()` and
`run_key_action_for_mode()`.
The reason why we returned a result previously was to feed information
back to the Objective-C caller to run subsequent parts of the pipeline,
like storing the current in-mode and simulating key presses. Now that
both of those are handled by the Rust code, we have no more need for
these return structs.
Get rid of the return values to clean up the code a bit.
|
|
This reverts commit 16cd3895f7b111544927d71904aab912d9abbf59. See that
commit message for details.
|
|
Such a pain. As soon as I clear one set of compilation errors, another
set crops up. The last one was like the following:
error[E0277]: the trait bound `K: std::default::Default` is not satisfied
--> src/cocoa_bridge.rs:117:1
|
117 | / pub extern "C" fn state_new<K>() -> *mut State<K>
118 | | where K: KeyCodeConvertible {
119 | | Box::into_raw(Box::new(State::default()))
120 | | }
| |_^ the trait `std::default::Default` is not implemented for `K`
|
= help: consider adding a `where K: std::default::Default` bound
note: required by `cocoa_bridge::State`
--> src/cocoa_bridge.rs:100:1
|
100 | / pub struct State<K: KeyCodeConvertible>
101 | | where K: Default {
102 | | in_mode: Option<Vec<HeadphoneButton>>,
103 | | map_group: Option<MapGroup<K>>,
104 | | }
| |_^
error[E0277]: the trait bound `K: std::default::Default` is not satisfied
I'm done with this. Just going to make a darn enum of 'autopilot's
`Character` and `KeyCode` structs so I don't have to deal with this
mess.
|
|
Trying to see if this works. If I call the init function over FFI and
then call functions that use the error macro, will logging work?
|
|
Currently untested. This function is supposed to get a mapping file from
the XDG config directory, parse it, and load it into the state.
|
|
Instead of letting the Objective-C code keep track of `in_mode` by
passing it around in `CKeyActionResult`, keep track of it in a `State`
struct.
Derive `Clone` on `HeadphoneButton` to resolve this error:
error[E0277]: the trait bound `parser::HeadphoneButton: std::clone::Clone` is not satisfied
--> src/cocoa_bridge.rs:273:38
|
273 | state.in_mode = Some(trigger.to_vec());
| ^^^^^^ the trait `std::clone::Clone` is not implemented for `parser::HeadphoneButton`
|
|
The plan is to use this as an opaque pointer to be passed between the
Objective-C code and Rust code. It will contain the current mode (if in
a mode) and the parsed `MapGroup` definitions.
For now just some code inspired by the Rust FFI Omnibus
(http://jakegoulding.com/rust-ffi-omnibus/objects/) to create and free a
`State`.
|
|
Add a new `moder.c` based on `includer.c` to test getting a mode and
then getting an action for a mode mapping.
Doesn't completely work currently. Right now all I get is this output:
$ ./moder
2
Segmentation fault: 11
Clearly I'm messing up something with the pointer in
`c_run_key_action()`. Not sure what it is yet.
Changed `CKeyActionResult.in_mode` to be a `Trigger` instead of a
`HeadphoneButton` list. That allows us to pass it directly into the
second argument of `c_run_key_action()` without converting.
But maybe the pointer value isn't living long enough? Not sure what the
problem is yet.
|
|
Add a new field for `in_mode` to the result struct. Return it if
`run_key_action_for_mode()` gives us a `Some` value for it. Removed the
`match` on `action` now that we have a second `Option` type.
|
|
When `trigger` is a mode instead of a map, return a `KeyActionResult`
with the `in_mode` field set to `trigger`.
The `MapKind` enum didn't really fit with the mode here. I couldn't use
`MapKind::{Map,Command}` for this `KeyActionResult` because the trigger
is for a mode, which is neither of those two.
At first I tried to add `Mode` as an option on `MapKind`, but that would
have caused problems. We'd be required to add `MapKind::Mode` as an
additional match arm in the two places we match against the kind in
`run_key_action_for_mode()`, and in that match arm we'd just have to log
an error because a `Mode` kind should never occur in those cases.
Instead of having a useless match arm that only serves to log an error,
I'd much rather not allow it in the first place.
Leaving `MapKind` the same allows us to keep our existing code the way
it is without adding unnecessary functionality.
In order to be able to declare a type of "Mode", though, I ended up
creating a new type that replicates `MapKind` (since I can't just extend
the enum to a new type) and adds a `Mode` option. This `ActionKind` is
only used for `KeyActionResult`, and `MapKind` is used for `Map`s and
`MapAction`s.
|
|
Add a nullable `mode` argument like `trigger`. Change `trigger` to make
it non-nullable again.
We can now pass a mode trigger in from FFI and handle it in our Rust
function.
|
|
Actually, now that I think about it, the trigger argument shouldn't be
nullable, since one should always be passed in. But this was really more
of a test to make sure we could do the same for a new `mode` argument,
which will also be a `Trigger`, but which might be null.
|
|
Our new `Trigger` type groups together the two arguments this function
used to take into a single type.
|
|
For better namespacing and local context information. Thank goodness
'cbindgen' supports this.
|
|
Make a test `includer.c` program that includes the Rust library and
calls our `c_run_key_action()` to see if it actually works. Currently it
doesn't, we get `(null)` printed to stdout.
Add a Makefile with the build command for the C program.
cbindgen.toml:
Remove `KeyActionResult` from exported types, as the `Option` field it
contains caused `gcc` to complain.
cocoa_bridge.rs:
* Comment out all 'cocoa' crate related code as the 'cocoa' code was
interfering with GCC compilation as a result of my not linking to
Cocoa frameworks.
* Add a new test map definition that corresponds with the one we look
for in `includer.c`.
parser.rs:
Add `#[repr(C)]` to `MapKind` because it needs to be exported in the
library and generated into our C header file.
|
|
Add a new `CKeyActionResult` that uses a `char *` instead of an
`Option<CString>`. Make our `c_run_key_action()` return this type
instead of `KeyActionResult`. Include some code to handle the
translation between the two types.
Names for now are just temporary so I can get something working. We'll
re-think proper names once I've tested this manually and have something
somewhat working.
|
|
Add a new wrapper function for `run_key_action` that uses C appropriate
inputs & outputs and calls into our Rusty `run_key_action`. This new
function now correctly gets a header generated for it by 'cbindgen'.
Immense thanks to Jake Goulding on the Rust FFI Omnibus for showing me
how to pass a slice argument from C:
http://jakegoulding.com/rust-ffi-omnibus/slice_arguments/
In order to pass the slice from C, we need to pass a C array and its
length to the function. Cool.
|
|
* Add the 'cbindgen' crate to help us auto-generate a C header for our
exported FFI enums/structs/functions
* Add a `build.rs` to generate the C header using cbindgen
* Add a rough config for 'cbindgen'
* Export everything from the `cocoa_bridge` crate to include the
`KeyActionResult` struct
* Commit the C header generated by 'cbindgen'
Looks promising. We do, however, have some things to correct. We can't
use `Option` in C, for instance, so we'll need to fix that in our
`KeyActionResult`. Similarly, we need to rework the `run_key_action()`
function to make it accessible as a C interface. Right now it returns an
`Option`, which isn't going to work, and I'm not sure if the slice input
translates. That (any maybe more) is why it doesn't get generated by
'cbindgen' into the header output file.
|