Skip to content

Commit

Permalink
Implement Hotkey Support
Browse files Browse the repository at this point in the history
This only works on Windows right now. It compiles on other platforms too,
but is stubbed out with a dummy implementation, that just never causes any
hotkey events.
  • Loading branch information
CryZe committed Apr 3, 2017
1 parent db5144e commit 34e760c
Show file tree
Hide file tree
Showing 21 changed files with 589 additions and 56 deletions.
10 changes: 5 additions & 5 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -94,11 +94,11 @@ before_cache:
# Travis can't cache files that are not readable by "others"
- chmod -R a+r $HOME/.cargo

branches:
only:
# release tags
- /^v\d+\.\d+\.\d+.*$/
- master
# branches:
# only:
# # release tags
# - /^v\d+\.\d+\.\d+.*$/
# - master

notifications:
email:
Expand Down
3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "livesplit-core"
version = "0.1.4"
version = "0.2.0"
authors = ["Christopher Serr <[email protected]>"]
documentation = "https://docs.rs/livesplit-core/"
repository = "https://github.com/CryZe/livesplit-core"
Expand All @@ -27,3 +27,4 @@ image = "0.12.3"
derive_more = "0.6.0"
derive-new = "0.4.0"
pdqsort = "0.1.2"
hotkey = { path = "hotkey" }
10 changes: 5 additions & 5 deletions appveyor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -73,11 +73,11 @@ cache:
- C:\Users\appveyor\.cargo\registry
- target

branches:
only:
# Release tags
- /^v\d+\.\d+\.\d+.*$/
- master
# branches:
# only:
# # Release tags
# - /^v\d+\.\d+\.\d+.*$/
# - master

notifications:
- provider: Email
Expand Down
2 changes: 1 addition & 1 deletion capi/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "livesplit-core-capi"
version = "0.1.4"
version = "0.2.0"
authors = ["Christopher Serr <[email protected]>"]

[dependencies]
Expand Down
42 changes: 29 additions & 13 deletions capi/bind_gen/src/csharp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use heck::{CamelCase, MixedCase};

fn get_type(ty: &Type, output: bool) -> &str {
match (ty.kind, ty.name.as_str()) {
(TypeKind::Ref, "c_char") => if output { "LSCCoreString" } else { "string" },
(TypeKind::Ref, "c_char") => if output { "LSCoreString" } else { "string" },
(TypeKind::Ref, _) |
(TypeKind::RefMut, _) => "IntPtr",
(_, t) if !ty.is_custom => {
Expand Down Expand Up @@ -36,15 +36,12 @@ pub fn write<W: Write>(mut writer: W, functions: &[Function]) -> Result<()> {
write!(writer,
"{}",
r#"using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.IO;
namespace LiveSplitCore
{
public class LiveSplitCoreNative
{"#)?;
{"#)?;

for function in functions {
let name = function.name.to_string();
Expand All @@ -53,23 +50,43 @@ namespace LiveSplitCore
let postfix = splits.next().unwrap();
if new_prefix != prefix {
if !prefix.is_empty() {
if prefix == "Run" {
write!(writer,
"{}",
r#"
public static IntPtr Parse(FileStream file)
{
var data = new byte[file.Length];
file.Read(data, 0, data.Length);
IntPtr pnt = Marshal.AllocHGlobal(data.Length);
try
{
Marshal.Copy(data, 0, pnt, data.Length);
return Parse(pnt, (UIntPtr)data.Length);
}
finally
{
Marshal.FreeHGlobal(pnt);
}
}"#)?;
}
writeln!(writer,
"{}",
r#"
}"#)?;
}"#)?;
}
write!(writer,
r#"
public static class {}
{{"#,
public static class {}
{{"#,
new_prefix)?;
}
prefix = new_prefix.to_string();

write!(writer,
r#"
[DllImport("livesplit_core", EntryPoint="{}")]
public static extern {} {}("#,
[DllImport("livesplit_core", EntryPoint="{}")]
public static extern {} {}("#,
&function.name,
get_type(&function.output, true),
postfix.to_camel_case())?;
Expand All @@ -94,10 +111,9 @@ namespace LiveSplitCore
writeln!(writer,
"{}",
r#"
}
}
internal class LSCoreString : SafeHandle
public class LSCoreString : SafeHandle
{
public LSCoreString() : base(IntPtr.Zero, false) { }
Expand Down
13 changes: 12 additions & 1 deletion capi/bind_gen/src/node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ pub fn write<W: Write>(mut writer: W, functions: &[Function]) -> Result<()> {
write!(writer,
"{}",
r#"var ffi = require('ffi');
let fs = require('fs');
var ls = ffi.Library('livesplit_core', {"#)?;

Expand Down Expand Up @@ -124,5 +125,15 @@ exports.{}_{} = function("#,
};"#)?;
}

Ok(())
writeln!(writer,
"{}",
r#"
exports.Run_parseFile = function(file) {
var data = fs.readFileSync(file);
var run = ls.Run_parse(data, data.byteLength);
if (run.isNull()) {
return null;
}
return run;
}"#)
}
32 changes: 32 additions & 0 deletions capi/src/hotkey_timer.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
use livesplit_core::HotkeyTimer;
use timer::OwnedTimer;
use timer_read_lock::OwnedTimerReadLock;
use timer_write_lock::OwnedTimerWriteLock;
use super::{alloc, own, acc, drop};
use std::ptr;

pub type OwnedHotkeyTimer = *mut HotkeyTimer;

#[no_mangle]
pub unsafe extern "C" fn HotkeyTimer_new(timer: OwnedTimer) -> OwnedHotkeyTimer {
if let Ok(timer) = HotkeyTimer::new(own(timer)) {
alloc(timer)
} else {
ptr::null_mut()
}
}

#[no_mangle]
pub unsafe extern "C" fn HotkeyTimer_drop(this: OwnedHotkeyTimer) {
drop(this);
}

#[no_mangle]
pub unsafe extern "C" fn HotkeyTimer_read(this: *const HotkeyTimer) -> OwnedTimerReadLock {
alloc(acc(this).read())
}

#[no_mangle]
pub unsafe extern "C" fn HotkeyTimer_write(this: *const HotkeyTimer) -> OwnedTimerWriteLock {
alloc(acc(this).write())
}
3 changes: 3 additions & 0 deletions capi/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use std::cell::{Cell, RefCell};
use std::mem;

pub mod timer;
pub mod hotkey_timer;
pub mod run;
pub mod segment_list;
pub mod segment;
Expand All @@ -32,6 +33,8 @@ pub mod sum_of_best_component_state;
pub mod possible_time_save_component;
pub mod possible_time_save_component_state;
pub mod run_editor;
pub mod timer_read_lock;
pub mod timer_write_lock;

use segment_history_element::SegmentHistoryElement;
use livesplit_core::{Time, TimeSpan};
Expand Down
9 changes: 7 additions & 2 deletions capi/src/run.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use livesplit_core::{Run, RunMetadata, TimeSpan, Segment, Attempt, parser};
use super::{alloc, drop, acc, own, output_str, output_time_span, acc_mut, str};
use livesplit_core::{Run, RunMetadata, TimeSpan, Segment, Attempt, parser, saver};
use super::{alloc, drop, acc, own, output_str, output_time_span, output_vec, acc_mut, str};
use segment_list::OwnedSegmentList;
use std::io::Cursor;
use std::{slice, ptr};
Expand Down Expand Up @@ -111,3 +111,8 @@ pub unsafe extern "C" fn Run_attempt_history_index(this: *const Run,
-> *const Attempt {
&acc(this).attempt_history()[index]
}

#[no_mangle]
pub unsafe extern "C" fn Run_save_as_lss(this: *const Run) -> *const c_char {
output_vec(|o| { saver::livesplit::save(acc(this), o).unwrap(); })
}
14 changes: 2 additions & 12 deletions capi/src/timer.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use livesplit_core::{Timer, TimeSpan, TimingMethod, TimerPhase, Run, saver};
use super::{alloc, own, acc_mut, drop, acc, output_str, output_vec, output_time_span};
use livesplit_core::{Timer, TimeSpan, TimingMethod, TimerPhase, Run};
use super::{alloc, own, acc_mut, drop, acc, output_str, output_time_span};
use run::OwnedRun;
use libc::c_char;

Expand All @@ -15,11 +15,6 @@ pub unsafe extern "C" fn Timer_drop(this: OwnedTimer) {
drop(this);
}

#[no_mangle]
pub unsafe extern "C" fn Timer_start(this: *mut Timer) {
acc_mut(this).start();
}

#[no_mangle]
pub unsafe extern "C" fn Timer_split(this: *mut Timer) {
acc_mut(this).split();
Expand Down Expand Up @@ -134,8 +129,3 @@ pub unsafe extern "C" fn Timer_clone_run(this: *const Timer) -> OwnedRun {
pub unsafe extern "C" fn Timer_print_debug(this: *const Timer) {
println!("{:#?}", acc(this));
}

#[no_mangle]
pub unsafe extern "C" fn Timer_save_run_as_lss(this: *const Timer) -> *const c_char {
output_vec(|o| { saver::livesplit::save(acc(this).run(), o).unwrap(); })
}
17 changes: 17 additions & 0 deletions capi/src/timer_read_lock.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
use livesplit_core::Timer;
use super::{drop, acc};
use std::sync::RwLockReadGuard;
use std::ops::Deref;

pub type TimerReadLock = RwLockReadGuard<'static, Timer>;
pub type OwnedTimerReadLock = *mut TimerReadLock;

#[no_mangle]
pub unsafe extern "C" fn TimerReadLock_drop(this: OwnedTimerReadLock) {
drop(this);
}

#[no_mangle]
pub unsafe extern "C" fn TimerReadLock_timer(this: *const TimerReadLock) -> *const Timer {
acc(this).deref()
}
17 changes: 17 additions & 0 deletions capi/src/timer_write_lock.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
use livesplit_core::Timer;
use super::{drop, acc_mut};
use std::sync::RwLockWriteGuard;
use std::ops::DerefMut;

pub type TimerWriteLock = RwLockWriteGuard<'static, Timer>;
pub type OwnedTimerWriteLock = *mut TimerWriteLock;

#[no_mangle]
pub unsafe extern "C" fn TimerWriteLock_drop(this: OwnedTimerWriteLock) {
drop(this);
}

#[no_mangle]
pub unsafe extern "C" fn TimerWriteLock_timer(this: *mut TimerWriteLock) -> *mut Timer {
acc_mut(this).deref_mut()
}
3 changes: 3 additions & 0 deletions hotkey/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
target/
**/*.rs.bk
Cargo.lock
11 changes: 11 additions & 0 deletions hotkey/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
[package]
name = "hotkey"
version = "0.1.0"
authors = ["Christopher Serr <[email protected]>"]

[target.'cfg(windows)'.dependencies]
winapi = "0.2.8"
user32-sys = "0.2.0"
kernel32-sys = "0.2.2"

[dependencies]
15 changes: 15 additions & 0 deletions hotkey/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#[cfg(windows)]
pub mod windows;
#[cfg(windows)]
pub use windows::*;

#[cfg(not(any(windows)))]
pub mod other;
#[cfg(not(any(windows)))]
pub use other::*;

#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
pub enum KeyEvent {
KeyUp(KeyCode),
KeyDown(KeyCode),
}
13 changes: 13 additions & 0 deletions hotkey/src/other/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
use KeyEvent;

#[derive(Debug, Eq, PartialEq, Hash, Copy, Clone)]
pub struct KeyCode;

pub struct Hook;

pub fn register_hook<F>(callback: F) -> Result<Hook, ()>
where F: FnMut(KeyEvent) + Send + 'static
{
drop(callback);
Ok(Hook)
}
Loading

0 comments on commit 34e760c

Please sign in to comment.