rust-libnotify/src/lib.rs

192 lines
5.5 KiB
Rust
Raw Normal View History

2015-03-10 07:46:54 +00:00
//! Rustic bindings to [libnotify](https://developer.gnome.org/libnotify/)
//!
//! ```rust
2015-11-02 23:50:27 +00:00
//!extern crate libnotify;
//!
//!fn main() {
//! let notify = libnotify::Context::new("hello").unwrap_or_else(|e| {
//! panic!("{}", e);
//! });
//! let body_text = Some("This is the optional body text.");
//! let n = notify.new_notification("This is the summary.", body_text, None)
//! .unwrap_or_else(|e| panic!("{}", e));
//! n.show().unwrap_or_else(|e| panic!("{}", e));
//!}
2015-03-10 07:46:54 +00:00
//!
//! ```
2015-03-25 18:04:43 +00:00
extern crate libnotify_sys as sys;
extern crate glib_2_0_sys as glib;
2015-09-19 07:42:17 +00:00
extern crate gtypes;
2015-11-02 23:49:12 +00:00
use std::ffi::{CStr, CString};
use std::marker::PhantomData;
use std::fmt;
2015-11-02 23:49:12 +00:00
use std::error::Error;
2015-11-02 22:55:35 +00:00
use gtypes::{TRUE, FALSE};
/// Error that can happen on context creation
#[derive(Debug)]
pub enum ContextCreationError {
/// Context already exists
AlreadyExists,
InitFailure,
2015-11-02 22:55:35 +00:00
NulError,
}
impl fmt::Display for ContextCreationError {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
use ContextCreationError::*;
match *self {
AlreadyExists => write!(f, "A Libnotify context already exists."),
InitFailure => write!(f, "Failed to initialize libnotify."),
2015-11-02 22:55:35 +00:00
NulError => write!(f, "Argument contains a nul character."),
}
}
}
#[derive(Debug)]
pub enum NotificationCreationError {
NulError,
2015-11-02 22:55:35 +00:00
Unknown,
}
impl fmt::Display for NotificationCreationError {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
use NotificationCreationError::*;
match *self {
NulError => write!(f, "Argument contains a nul character."),
2015-11-02 22:55:35 +00:00
Unknown => write!(f, "Unknown error"),
}
}
}
/// The context which within libnotify operates.
///
/// Only one context can exist at a time.
pub struct Context;
impl Context {
2015-03-08 16:07:50 +00:00
/// Create a new context
///
/// Arguments:
///
/// - app_name: The name of the application using the context
pub fn new(app_name: &str) -> Result<Context, ContextCreationError> {
unsafe {
if sys::notify_is_initted() == TRUE {
return Err(ContextCreationError::AlreadyExists);
}
let app_name = match CString::new(app_name) {
Ok(name) => name,
2015-11-02 22:55:35 +00:00
Err(_) => return Err(ContextCreationError::NulError),
};
if sys::notify_init(app_name.as_ptr()) == FALSE {
return Err(ContextCreationError::InitFailure);
}
}
Ok(Context)
}
2015-03-08 16:07:50 +00:00
/// Creates a new Notification.
///
/// Arguments:
///
/// - summary: Required summary text
/// - body: Optional body text
/// - icon: Optional icon theme icon name or filename
2015-11-02 22:55:35 +00:00
pub fn new_notification(&self,
summary: &str,
body: Option<&str>,
icon: Option<&str>)
-> Result<Notification, NotificationCreationError> {
let summary = match CString::new(summary) {
Ok(cstr) => cstr,
2015-11-02 22:55:35 +00:00
Err(_) => return Err(NotificationCreationError::NulError),
};
let body = match body {
Some(body) => match CString::new(body) {
Ok(cstr) => Some(cstr),
2015-11-02 22:55:35 +00:00
Err(_) => return Err(NotificationCreationError::NulError),
},
2015-11-02 22:55:35 +00:00
None => None,
};
let body_ptr = match body {
Some(body) => body.as_ptr(),
2015-11-02 22:55:35 +00:00
None => std::ptr::null(),
};
let icon = match icon {
Some(icon) => match CString::new(icon) {
Ok(cstr) => Some(cstr),
2015-11-02 22:55:35 +00:00
Err(_) => return Err(NotificationCreationError::NulError),
},
2015-11-02 22:55:35 +00:00
None => None,
};
let icon_ptr = match icon {
Some(icon) => icon.as_ptr(),
2015-11-02 22:55:35 +00:00
None => std::ptr::null(),
};
unsafe {
2015-11-02 22:55:35 +00:00
let n = sys::notify_notification_new(summary.as_ptr(), body_ptr, icon_ptr);
if n.is_null() {
return Err(NotificationCreationError::Unknown);
}
2015-11-02 22:55:35 +00:00
Ok(Notification {
handle: n,
_phantom: PhantomData,
})
}
}
}
impl Drop for Context {
fn drop(&mut self) {
unsafe {
sys::notify_uninit();
}
}
}
2015-03-08 16:07:50 +00:00
/// A passive pop-up notification
pub struct Notification<'a> {
handle: *mut sys::NotifyNotification,
2015-11-02 22:55:35 +00:00
_phantom: PhantomData<&'a Context>,
}
impl<'a> Notification<'a> {
2015-03-08 16:07:50 +00:00
/// Tells the notification server to display the notification
/// on the screen.
2015-11-02 23:49:12 +00:00
pub fn show(&'a self) -> Result<(), NotificationShowError> {
unsafe {
let mut err: *mut glib::GError = std::ptr::null_mut();
sys::notify_notification_show(self.handle, &mut err);
if !err.is_null() {
2015-11-02 23:49:12 +00:00
let result = Err(NotificationShowError {
message: CStr::from_ptr((*err).message).to_string_lossy().into_owned(),
});
glib::g_error_free(err);
2015-11-02 23:49:12 +00:00
return result;
}
2015-11-02 22:55:35 +00:00
return Ok(());
}
}
}
2015-11-02 23:49:12 +00:00
#[derive(Debug)]
pub struct NotificationShowError {
message: String,
}
impl fmt::Display for NotificationShowError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Error showing notification: {}", self.message)
}
}
impl Error for NotificationShowError {
fn description(&self) -> &str {
"Notification show error"
}
}