extern crate glib;
extern crate dbus;
use dbus::arg::{Variant, RefArg};
use dbus::{Connection, BusType, tree, Path, SignalArgs};
use dbus::tree::{Interface, MTFn, Factory};
use std::collections::HashMap;
use std::rc::Rc;
use std::cell::Cell;
use std::cell::RefCell;
use std::sync::Arc;
use generated::mediaplayer2::org_mpris_media_player2_server;
use generated::mediaplayer2_player::{org_mpris_media_player2_player_server, OrgFreedesktopDBusPropertiesPropertiesChanged};
use OrgMprisMediaPlayer2Player;
use OrgMprisMediaPlayer2;
use Metadata;
use PlaybackStatus;
use LoopStatus;
pub struct MprisPlayer{
connection: Arc<Connection>,
factory: Arc<Factory<MTFn<TData>, TData>>,
can_quit: Cell<bool>, fullscreen: Cell<bool>, can_set_fullscreen: Cell<bool>, can_raise: Cell<bool>, has_track_list: Cell<bool>, identify: String, desktop_entry: String, supported_uri_schemes: RefCell<Vec<String>>, supported_mime_types: RefCell<Vec<String>>,
playback_status: Cell<PlaybackStatus>, loop_status: Cell<LoopStatus>, rate: Cell<f64>, shuffle: Cell<bool>, metadata: RefCell<Metadata>, volume: Cell<f64>, position: Cell<i64>, minimum_rate: Cell<f64>, maximum_rate: Cell<f64>, can_go_next: Cell<bool>, can_go_previous: Cell<bool>, can_play: Cell<bool>, can_pause: Cell<bool>, can_seek: Cell<bool>, can_control: Cell<bool>,
raise_cb: RefCell<Vec<Rc<RefCell<FnMut()>>>>,
quit_cb: RefCell<Vec<Rc<RefCell<FnMut()>>>>,
next_cb: RefCell<Vec<Rc<RefCell<FnMut()>>>>,
previous_cb: RefCell<Vec<Rc<RefCell<FnMut()>>>>,
pause_cb: RefCell<Vec<Rc<RefCell<FnMut()>>>>,
play_pause_cb: RefCell<Vec<Rc<RefCell<FnMut()>>>>,
stop_cb: RefCell<Vec<Rc<RefCell<FnMut()>>>>,
play_cb: RefCell<Vec<Rc<RefCell<FnMut()>>>>,
seek_cb: RefCell<Vec<Rc<RefCell<FnMut(i64)>>>>,
open_uri_cb: RefCell<Vec<Rc<RefCell<FnMut(&str)>>>>,
fullscreen_cb: RefCell<Vec<Rc<RefCell<FnMut(bool)>>>>,
loop_status_cb: RefCell<Vec<Rc<RefCell<FnMut(LoopStatus)>>>>,
rate_cb: RefCell<Vec<Rc<RefCell<FnMut(f64)>>>>,
shuffle_cb: RefCell<Vec<Rc<RefCell<FnMut(bool)>>>>,
volume_cb: RefCell<Vec<Rc<RefCell<FnMut(f64)>>>>,
}
impl MprisPlayer{
pub fn new(mpris_name: String, identify: String, desktop_entry: String) -> Arc<Self>{
let connection = Arc::new(Connection::get_private(BusType::Session).unwrap());
let factory = Arc::new(Factory::new_fn());
let mpris_player = Arc::new(MprisPlayer{
connection,
factory,
can_quit: Cell::new(false),
fullscreen: Cell::new(false),
can_set_fullscreen: Cell::new(false),
can_raise: Cell::new(false),
has_track_list: Cell::new(false),
identify,
desktop_entry,
supported_uri_schemes: RefCell::new(Vec::new()),
supported_mime_types: RefCell::new(Vec::new()),
playback_status: Cell::new(PlaybackStatus::Paused),
loop_status: Cell::new(LoopStatus::None),
rate: Cell::new(0_f64),
shuffle: Cell::new(false),
metadata: RefCell::new(Metadata::new()),
volume: Cell::new(0_f64),
position: Cell::new(0),
minimum_rate: Cell::new(0_f64),
maximum_rate: Cell::new(0_f64),
can_go_next: Cell::new(true),
can_go_previous: Cell::new(true),
can_play: Cell::new(true),
can_pause: Cell::new(true),
can_seek: Cell::new(false),
can_control: Cell::new(true),
raise_cb: RefCell::new(Vec::new()),
quit_cb: RefCell::new(Vec::new()),
next_cb: RefCell::new(Vec::new()),
previous_cb: RefCell::new(Vec::new()),
pause_cb: RefCell::new(Vec::new()),
play_pause_cb: RefCell::new(Vec::new()),
stop_cb: RefCell::new(Vec::new()),
play_cb: RefCell::new(Vec::new()),
seek_cb: RefCell::new(Vec::new()),
open_uri_cb: RefCell::new(Vec::new()),
fullscreen_cb: RefCell::new(Vec::new()),
loop_status_cb: RefCell::new(Vec::new()),
rate_cb: RefCell::new(Vec::new()),
shuffle_cb: RefCell::new(Vec::new()),
volume_cb: RefCell::new(Vec::new()),
});
let root_iface: Interface<MTFn<TData>, TData> = org_mpris_media_player2_server(&mpris_player.factory, (), |m| {
let a: &Arc<MprisPlayer> = m.path.get_data();
let b: &MprisPlayer = &a;
b
});
let player_iface: Interface<MTFn<TData>, TData> = org_mpris_media_player2_player_server(&mpris_player.factory, (), |m| {
let a: &Arc<MprisPlayer> = m.path.get_data();
let b: &MprisPlayer = &a;
b
});
let mut tree = mpris_player.factory.tree(());
tree = tree.add(mpris_player.factory.object_path("/org/mpris/MediaPlayer2", mpris_player.clone())
.introspectable()
.add(root_iface)
.add(player_iface)
);
mpris_player.connection.register_name(&format!("org.mpris.MediaPlayer2.{}", mpris_name), 0).unwrap();
tree.set_registered(&mpris_player.connection, true).unwrap();
mpris_player.connection.add_handler(tree);
let connection = mpris_player.connection.clone();
glib::source::timeout_add_local(250, move||{
connection.incoming(5).next();
glib::Continue(true)
});
mpris_player
}
pub fn property_changed<T: 'static>(&self, name: String, value: T) where T: dbus::arg::RefArg {
let mut changed_properties = HashMap::new();
let x = Box::new(value) as Box<RefArg>;
changed_properties.insert(name, Variant(x));
let signal = OrgFreedesktopDBusPropertiesPropertiesChanged {
changed_properties,
interface_name: "org.mpris.MediaPlayer2.Player".to_string(),
invalidated_properties: Vec::new(),
};
self.connection.send(signal.to_emit_message(&Path::new("/org/mpris/MediaPlayer2").unwrap())).unwrap();
}
pub fn set_supported_mime_types(&self, value: Vec<String>){
*self.supported_mime_types.borrow_mut() = value;
self.property_changed("SupportedMimeTypes".to_string(), self.get_supported_mime_types().unwrap());
}
pub fn set_supported_uri_schemes(&self, value: Vec<String>){
*self.supported_uri_schemes.borrow_mut() = value;
self.property_changed("SupportedUriSchemes".to_string(), self.get_supported_uri_schemes().unwrap());
}
pub fn set_can_quit(&self, value: bool){
self.can_quit.set(value);
self.property_changed("CanQuit".to_string(), self.get_can_quit().unwrap());
}
pub fn set_can_raise(&self, value: bool){
self.can_raise.set(value);
self.property_changed("CanRaise".to_string(), self.get_can_raise().unwrap());
}
pub fn set_can_set_fullscreen(&self, value: bool){
self.can_set_fullscreen.set(value);
self.property_changed("CanSetFullscreen".to_string(), self.get_can_set_fullscreen().unwrap());
}
pub fn set_has_track_list(&self, value: bool){
self.has_track_list.set(value);
self.property_changed("HasTrackList".to_string(), self.get_has_track_list().unwrap());
}
pub fn set_playback_status(&self, value: PlaybackStatus){
self.playback_status.set(value);
self.property_changed("PlaybackStatus".to_string(), self.get_playback_status().unwrap());
}
pub fn set_loop_status(&self, value: LoopStatus){
self.loop_status.set(value);
self.property_changed("LoopStatus".to_string(), self.get_loop_status().unwrap());
}
pub fn set_metadata(&self, metadata: Metadata){
*self.metadata.borrow_mut() = metadata;
self.property_changed("Metadata".to_string(), self.get_metadata().unwrap());
}
pub fn set_position(&self, value: i64){
self.position.set(value);
self.property_changed("Position".to_string(), self.get_position().unwrap());
}
pub fn set_minimum_rate(&self, value: f64){
self.minimum_rate.set(value);
self.property_changed("MinimumRate".to_string(), self.get_minimum_rate().unwrap());
}
pub fn set_maximum_rate(&self, value: f64){
self.maximum_rate.set(value);
self.property_changed("MaximumRate".to_string(), self.get_maximum_rate().unwrap());
}
pub fn set_can_go_next(&self, value: bool){
self.can_go_next.set(value);
self.property_changed("CanGoNext".to_string(), self.get_can_go_next().unwrap());
}
pub fn set_can_go_previous(&self, value: bool){
self.can_go_previous.set(value);
self.property_changed("CanPrevious".to_string(), self.get_can_go_previous().unwrap());
}
pub fn set_can_play(&self, value: bool){
self.can_play.set(value);
self.property_changed("CanPlay".to_string(), self.get_can_play().unwrap());
}
pub fn set_can_pause(&self, value: bool){
self.can_pause.set(value);
self.property_changed("CanPause".to_string(), self.get_can_pause().unwrap());
}
pub fn set_can_seek(&self, value: bool){
self.can_seek.set(value);
self.property_changed("CanSeek".to_string(), self.get_can_seek().unwrap());
}
pub fn set_can_control(&self, value: bool){
self.can_control.set(value);
self.property_changed("CanControl".to_string(), self.get_can_control().unwrap());
}
pub fn connect_raise<F: FnMut()+'static>(&self, callback: F) {
let cell = Rc::new(RefCell::new(callback));
self.raise_cb.borrow_mut().push(cell);
}
pub fn connect_quit<F: FnMut()+'static>(&self, callback: F) {
let cell = Rc::new(RefCell::new(callback));
self.quit_cb.borrow_mut().push(cell);
}
pub fn connect_next<F: FnMut()+'static>(&self, callback: F) {
let cell = Rc::new(RefCell::new(callback));
self.next_cb.borrow_mut().push(cell);
}
pub fn connect_previous<F: FnMut()+'static>(&self, callback: F) {
let cell = Rc::new(RefCell::new(callback));
self.previous_cb.borrow_mut().push(cell);
}
pub fn connect_pause<F: FnMut()+'static>(&self, callback: F) {
let cell = Rc::new(RefCell::new(callback));
self.pause_cb.borrow_mut().push(cell);
}
pub fn connect_play_pause<F: FnMut()+'static>(&self, callback: F) {
let cell = Rc::new(RefCell::new(callback));
self.play_pause_cb.borrow_mut().push(cell);
}
pub fn connect_stop<F: FnMut()+'static>(&self, callback: F) {
let cell = Rc::new(RefCell::new(callback));
self.stop_cb.borrow_mut().push(cell);
}
pub fn connect_play<F: FnMut()+'static>(&self, callback: F) {
let cell = Rc::new(RefCell::new(callback));
self.play_cb.borrow_mut().push(cell);
}
pub fn connect_seek<F: FnMut(i64)+'static>(&self, callback: F) {
let cell = Rc::new(RefCell::new(callback));
self.seek_cb.borrow_mut().push(cell);
}
pub fn connect_open_uri<F: FnMut(&str)+'static>(&self, callback: F) {
let cell = Rc::new(RefCell::new(callback));
self.open_uri_cb.borrow_mut().push(cell);
}
pub fn connect_fullscreen<F: FnMut(bool)+'static>(&self, callback: F) {
let cell = Rc::new(RefCell::new(callback));
self.fullscreen_cb.borrow_mut().push(cell);
}
pub fn connect_loop_status<F: FnMut(LoopStatus)+'static>(&self, callback: F) {
let cell = Rc::new(RefCell::new(callback));
self.loop_status_cb.borrow_mut().push(cell);
}
pub fn connect_rate<F: FnMut(f64)+'static>(&self, callback: F) {
let cell = Rc::new(RefCell::new(callback));
self.rate_cb.borrow_mut().push(cell);
}
pub fn connect_shuffle<F: FnMut(bool)+'static>(&self, callback: F) {
let cell = Rc::new(RefCell::new(callback));
self.shuffle_cb.borrow_mut().push(cell);
}
pub fn connect_volume<F: FnMut(f64)+'static>(&self, callback: F) {
let cell = Rc::new(RefCell::new(callback));
self.volume_cb.borrow_mut().push(cell);
}
}
impl OrgMprisMediaPlayer2 for MprisPlayer {
type Err = tree::MethodErr;
fn raise(&self) -> Result<(), Self::Err> {
for callback in self.raise_cb.borrow_mut().iter() {
let mut closure = callback.borrow_mut(); (&mut *closure)();
}
Ok(())
}
fn quit(&self) -> Result<(), Self::Err> {
for callback in self.quit_cb.borrow_mut().iter() {
let mut closure = callback.borrow_mut(); (&mut *closure)();
}
Ok(())
}
fn get_can_quit(&self) -> Result<bool, Self::Err> {
Ok(self.can_quit.get())
}
fn get_fullscreen(&self) -> Result<bool, Self::Err> {
Ok(self.fullscreen.get())
}
fn set_fullscreen(&self, value: bool) -> Result<(), Self::Err> {
self.fullscreen.set(value);
self.property_changed("Fullscreen".to_string(), self.get_fullscreen().unwrap());
for callback in self.fullscreen_cb.borrow_mut().iter() {
let mut closure = callback.borrow_mut(); (&mut *closure)(value);
}
Ok(())
}
fn get_can_set_fullscreen(&self) -> Result<bool, Self::Err> {
Ok(self.can_set_fullscreen.get())
}
fn get_can_raise(&self) -> Result<bool, Self::Err> {
Ok(self.can_raise.get())
}
fn get_has_track_list(&self) -> Result<bool, Self::Err> {
Ok(self.has_track_list.get())
}
fn get_identity(&self) -> Result<String, Self::Err> {
Ok(self.identify.clone())
}
fn get_desktop_entry(&self) -> Result<String, Self::Err> {
Ok(self.desktop_entry.clone())
}
fn get_supported_uri_schemes(&self) -> Result<Vec<String>, Self::Err> {
Ok(self.supported_uri_schemes.borrow().to_vec())
}
fn get_supported_mime_types(&self) -> Result<Vec<String>, Self::Err> {
Ok(self.supported_mime_types.borrow().to_vec())
}
}
impl OrgMprisMediaPlayer2Player for MprisPlayer {
type Err = tree::MethodErr;
fn next(&self) -> Result<(), Self::Err> {
for callback in self.next_cb.borrow_mut().iter() {
let mut closure = callback.borrow_mut(); (&mut *closure)();
}
Ok(())
}
fn previous(&self) -> Result<(), Self::Err> {
for callback in self.previous_cb.borrow_mut().iter() {
let mut closure = callback.borrow_mut(); (&mut *closure)();
}
Ok(())
}
fn pause(&self) -> Result<(), Self::Err> {
for callback in self.pause_cb.borrow_mut().iter() {
let mut closure = callback.borrow_mut(); (&mut *closure)();
}
Ok(())
}
fn play_pause(&self) -> Result<(), Self::Err> {
for callback in self.play_pause_cb.borrow_mut().iter() {
let mut closure = callback.borrow_mut(); (&mut *closure)();
}
Ok(())
}
fn stop(&self) -> Result<(), Self::Err> {
for callback in self.stop_cb.borrow_mut().iter() {
let mut closure = callback.borrow_mut(); (&mut *closure)();
}
Ok(())
}
fn play(&self) -> Result<(), Self::Err> {
for callback in self.play_cb.borrow_mut().iter() {
let mut closure = callback.borrow_mut(); (&mut *closure)();
}
Ok(())
}
fn seek(&self, offset: i64) -> Result<(), Self::Err> {
for callback in self.seek_cb.borrow_mut().iter() {
let mut closure = callback.borrow_mut(); (&mut *closure)(offset);
}
Ok(())
}
fn set_position(&self, _track_id: dbus::Path, position: i64) -> Result<(), Self::Err> {
self.position.set(position);
self.property_changed("Position".to_string(), self.get_position().unwrap());
Ok(())
}
fn open_uri(&self, uri: &str) -> Result<(), Self::Err> {
for callback in self.open_uri_cb.borrow_mut().iter() {
let mut closure = callback.borrow_mut(); (&mut *closure)(uri);
}
Ok(())
}
fn get_playback_status(&self) -> Result<String, Self::Err> {
Ok(self.playback_status.get().value())
}
fn get_loop_status(&self) -> Result<String, Self::Err> {
Ok(self.loop_status.get().value())
}
fn set_loop_status(&self, value: String) -> Result<(), Self::Err> {
let ls = match value.as_ref() {
"Track" => LoopStatus::Track,
"Playlist" => LoopStatus::Playlist,
_ => LoopStatus::None,
};
self.loop_status.set(ls.clone());
self.property_changed("LoopStatus".to_string(), self.get_loop_status().unwrap());
for callback in self.loop_status_cb.borrow_mut().iter() {
let mut closure = callback.borrow_mut(); (&mut *closure)(ls);
}
Ok(())
}
fn get_rate(&self) -> Result<f64, Self::Err> {
Ok(self.rate.get())
}
fn set_rate(&self, value: f64) -> Result<(), Self::Err> {
self.rate.set(value);
self.property_changed("Rate".to_string(), self.get_rate().unwrap());
for callback in self.rate_cb.borrow_mut().iter() {
let mut closure = callback.borrow_mut(); (&mut *closure)(value);
}
Ok(())
}
fn get_shuffle(&self) -> Result<bool, Self::Err> {
Ok(self.shuffle.get())
}
fn set_shuffle(&self, value: bool) -> Result<(), Self::Err> {
self.shuffle.set(value);
self.property_changed("Shuffle".to_string(), self.get_volume().unwrap());
for callback in self.shuffle_cb.borrow_mut().iter() {
let mut closure = callback.borrow_mut(); (&mut *closure)(value);
}
Ok(())
}
fn get_metadata(&self) -> Result<HashMap<String, Variant<Box<RefArg + 'static>>>, Self::Err> {
let metadata = self.metadata.borrow().to_hashmap();
Ok(metadata)
}
fn get_volume(&self) -> Result<f64, Self::Err> {
Ok(self.volume.get())
}
fn set_volume(&self, value: f64) -> Result<(), Self::Err> {
self.volume.set(value);
self.property_changed("Volume".to_string(), self.get_volume().unwrap());
for callback in self.volume_cb.borrow_mut().iter() {
let mut closure = callback.borrow_mut(); (&mut *closure)(value);
}
Ok(())
}
fn get_position(&self) -> Result<i64, Self::Err> {
Ok(self.position.get())
}
fn get_minimum_rate(&self) -> Result<f64, Self::Err> {
Ok(self.minimum_rate.get())
}
fn get_maximum_rate(&self) -> Result<f64, Self::Err> {
Ok(self.maximum_rate.get())
}
fn get_can_go_next(&self) -> Result<bool, Self::Err> {
Ok(self.can_go_next.get())
}
fn get_can_go_previous(&self) -> Result<bool, Self::Err> {
Ok(self.can_go_previous.get())
}
fn get_can_play(&self) -> Result<bool, Self::Err> {
Ok(self.can_play.get())
}
fn get_can_pause(&self) -> Result<bool, Self::Err> {
Ok(self.can_pause.get())
}
fn get_can_seek(&self) -> Result<bool, Self::Err> {
Ok(self.can_seek.get())
}
fn get_can_control(&self) -> Result<bool, Self::Err> {
Ok(self.can_control.get())
}
}
impl ::std::fmt::Debug for MprisPlayer{
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
write!(f, "mprisplayer")
}
}
#[derive(Copy, Clone, Default, Debug)]
pub struct TData;
impl tree::DataType for TData {
type Tree = ();
type ObjectPath = Arc<MprisPlayer>;
type Property = ();
type Interface = ();
type Method = ();
type Signal = ();
}