aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAlex Parrill <[email protected]>2019-06-05 22:26:21 -0400
committerMatthew Collins <[email protected]>2019-06-09 23:50:11 +0100
commit99051706e18f66f2e63494242dda41e7a7256971 (patch)
tree13024d70399eb3fa57b106cec85d85874a8f629a /src
parent0.5.1 (and 0.5.0 for sys) (diff)
downloadsteamworks-rs-99051706e18f66f2e63494242dda41e7a7256971.tar.xz
steamworks-rs-99051706e18f66f2e63494242dda41e7a7256971.zip
Add Utils::set_warning_callback for logging Steam warnings
Diffstat (limited to 'src')
-rw-r--r--src/lib.rs2
-rw-r--r--src/utils.rs54
2 files changed, 55 insertions, 1 deletions
diff --git a/src/lib.rs b/src/lib.rs
index ce40d56..1bcf828 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -5,6 +5,8 @@ extern crate steamworks_sys as sys;
extern crate failure;
#[macro_use]
extern crate bitflags;
+#[macro_use]
+extern crate lazy_static;
mod error;
pub use crate::error::*;
diff --git a/src/utils.rs b/src/utils.rs
index 34ba6c9..3d569b3 100644
--- a/src/utils.rs
+++ b/src/utils.rs
@@ -1,6 +1,12 @@
use super::*;
+use libc::c_char;
+use std::ffi::CStr;
+use std::panic;
+use std::process::abort;
+use std::sync::RwLock;
+
/// Access to the steam utils interface
pub struct Utils<Manager> {
pub(crate) utils: *mut sys::ISteamUtils,
@@ -14,6 +20,36 @@ pub enum NotificationPosition {
BottomRight,
}
+lazy_static!{
+ /// Global rust warning callback
+ static ref WARNING_CALLBACK: RwLock<Option<Box<Fn(i32, &CStr) + Send + Sync>>> = RwLock::new(None);
+}
+
+/// C function to pass as the real callback, which forwards to the `WARNING_CALLBACK` if any
+unsafe extern "cdecl" fn c_warning_callback(level: i32, msg: *const c_char) {
+ let lock = WARNING_CALLBACK.read().expect("warning func lock poisoned");
+ let cb = match lock.as_ref() {
+ Some(cb) => cb,
+ None => { return; }
+ };
+
+ let s = CStr::from_ptr(msg);
+
+ let res = panic::catch_unwind(panic::AssertUnwindSafe(||
+ cb(level, s)
+ ));
+ if let Err(err) = res {
+ if let Some(err) = err.downcast_ref::<&str>() {
+ println!("Steam warning callback paniced: {}", err);
+ } else if let Some(err) = err.downcast_ref::<String>() {
+ println!("Steam warning callback paniced: {}", err);
+ } else {
+ println!("Steam warning callback paniced");
+ }
+ abort();
+ }
+}
+
impl <Manager> Utils<Manager> {
/// Returns the app ID of the current process
pub fn app_id(&self) -> AppId {
@@ -47,4 +83,20 @@ impl <Manager> Utils<Manager> {
sys::SteamAPI_ISteamUtils_SetOverlayNotificationPosition(self.utils, position);
}
}
-} \ No newline at end of file
+
+ /// Sets the Steam warning callback, which is called to emit warning messages.
+ ///
+ /// The passed-in function takes two arguments: a severity level (0 = info, 1 = warning) and
+ /// the message itself.
+ ///
+ /// See [Steamwork's debugging page](https://partner.steamgames.com/doc/sdk/api/debugging) for more info.
+ pub fn set_warning_callback<F>(&self, cb: F)
+ where F: Fn(i32, &CStr) + Send + Sync + 'static
+ {
+ let mut lock = WARNING_CALLBACK.write().expect("warning func lock poisoned");
+ *lock = Some(Box::new(cb));
+ unsafe {
+ sys::SteamAPI_ISteamUtils_SetWarningMessageHook(self.utils, c_warning_callback);
+ }
+ }
+}