extern crate objc;
extern crate objc_foundation;
extern crate cocoa;
+extern crate libc;
pub use self::rustnsobject::NSCallback;
use std::sync::mpsc::Sender;
+use std::ptr;
+use std::ffi::CStr;
use std::thread::sleep;
use std::time::Duration;
fn add_separator(&mut self);
fn add_label(&mut self, label: &str);
fn add_item(&mut self, item: &str, callback: NSCallback, selected: bool) -> *mut Object;
+ fn add_quit(&mut self, label: &str);
fn update_item(&mut self, item: *mut Object, label: &str);
fn sel_item(&mut self, sender: u64);
fn unsel_item(&mut self, sender: u64);
};
bar.app.setActivationPolicy_(NSApplicationActivationPolicyAccessory);
msg_send![bar.status_bar_item, setHighlightMode:YES];
- let img = NSString::alloc(nil).init_str("spotify.png");
+ let img_path = match bundled_resource_path("spotify", "png") {
+ Some(path) => path,
+ None => "spotify.png".to_string(),
+ };
+ let img = NSString::alloc(nil).init_str(&img_path);
let icon = NSImage::alloc(nil).initWithContentsOfFile_(img);
+ //let icon = NSImage::alloc(nil).initWithContentsOfFile_(img);
+ //let icon = NSImage::imageNamed_(img, img);
NSButton::setTitle_(bar.status_bar_item, NSString::alloc(nil).init_str("connectr"));
bar.status_bar_item.button().setImage_(icon);
bar.status_bar_item.setMenu_(bar.menu_bar);
self.menu_bar.addItem_(app_menu_item);
}
}
+ fn add_quit(&mut self, label: &str) {
+ unsafe {
+ let txt = NSString::alloc(nil).init_str(label);
+ let quit_key = NSString::alloc(nil).init_str("");
+ let app_menu_item = NSMenuItem::alloc(nil)
+ .initWithTitle_action_keyEquivalent_(txt, sel!(terminate:), quit_key)
+ .autorelease();
+ self.menu_bar.addItem_(app_menu_item);
+ }
+ }
fn add_separator(&mut self) {
unsafe {
let cls = Class::get("NSMenuItem").unwrap();
}
}
}
+
+pub fn osx_alert(text: &str) {
+ unsafe {
+ let ns_text = NSString::alloc(nil).init_str(text);
+ let button = NSString::alloc(nil).init_str("ok");
+ let cls = Class::get("NSAlert").unwrap();
+ let alert: *mut Object = msg_send![cls, alloc];
+ let _ = msg_send![alert, init];
+ let _ = msg_send![alert, setMessageText: ns_text];
+ let _ = msg_send![alert, addButtonWithTitle: button];
+ let _ = msg_send![alert, runModal];
+ }
+}
+
+pub fn bundled_resource_path(name: &str, extension: &str) -> Option<String> {
+ unsafe {
+ let cls = Class::get("NSBundle").unwrap();
+ let bundle: *mut Object = msg_send![cls, mainBundle];
+ let res = NSString::alloc(nil).init_str(name);
+ let ext = NSString::alloc(nil).init_str(extension);
+ let ini: *mut Object = msg_send![bundle, pathForResource:res ofType:ext];
+ let cstr: *const libc::c_char = msg_send![ini, UTF8String];
+ if cstr != ptr::null() {
+ let rstr = CStr::from_ptr(cstr).to_string_lossy().into_owned();
+ return Some(rstr);
+ }
+ None
+ }
+}
extern crate time;
+#[cfg(target_os = "macos")]
+use super::osx;
+
+use std::env;
+use std::fs;
+use std::path;
+
+const INIFILE: &'static str = ".connectr.ini";
+
pub struct Settings {
pub port: u32,
pub secret: String,
pub presets: Vec<(String,String)>,
}
+#[cfg(target_os = "macos")]
+fn bundled_ini() -> String {
+ match osx::bundled_resource_path("connectr", "ini") {
+ Some(path) => path,
+ None => String::new(),
+ }
+}
+
+#[cfg(not(target_os = "macos"))]
+fn bundled_ini() -> String {
+ String::new()
+}
+
+fn inifile() -> String {
+ // Try to load INI file from home directory
+ let path = format!("{}/{}", env::home_dir().unwrap().display(), INIFILE);
+ if path::Path::new(&path).exists() {
+ return path
+ }
+
+ // If it doesn't exist, try to copy the template from the app bundle, if
+ // such a thing exists.
+ let bundle_ini = bundled_ini();
+ if path::Path::new(&bundle_ini).exists() {
+ let _ = fs::copy(bundle_ini, path.clone());
+ }
+ path
+}
+
pub fn read_settings() -> Option<Settings> {
- let conf = Ini::load_from_file("connectr.ini").unwrap();
+ let conf = match Ini::load_from_file(&inifile()) {
+ Ok(c) => c,
+ Err(_) => {
+ // No connectr.ini found. Generate a junk one in-memory, which
+ // will fail shortly after with the nice error message.
+ let mut c = Ini::new();
+ c.with_section(Some("connectr".to_owned()))
+ .set("port", 5657.to_string());
+ c.with_section(Some("application".to_owned()))
+ .set("secret", "<PLACEHOLDER>".to_string())
+ .set("client_id", "<PLACEHOLDER>".to_string());
+ c
+ }
+ };
let section = conf.section(Some("connectr".to_owned())).unwrap();
let port = section.get("port").unwrap().parse().unwrap();
pub type SettingsError = String;
pub fn save_tokens(access: &str, refresh: &str, expire_utc: u64) -> Result<(), SettingsError> {
- let mut conf = Ini::load_from_file("connectr.ini").unwrap();
+ let mut conf = Ini::load_from_file(&inifile()).unwrap();
conf.with_section(Some("tokens".to_owned()))
.set("access", access)
.set("refresh", refresh)
.set("expire", expire_utc.to_string());
- conf.write_to_file("connectr.ini").unwrap();
+ conf.write_to_file(&inifile()).unwrap();
Ok(())
}