1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
use ffi::*;

use std::sync::mpsc::{self,channel,Receiver};

use message::Message;
use util::*;
use reference::Reference;
use object::Object;

static REMOVE_WATCH_MESSAGE_STR: &'static str = "gstreamer1.0-rs_remove_watch_message";

unsafe impl Sync for Bus {}
unsafe impl Send for Bus {}

pub struct Bus{
    bus: Object
}

impl Bus{
    pub unsafe fn new(bus: *mut GstBus) -> Option<Bus>{
        Object::new(bus as *mut GstObject).map(|obj| Bus{bus: obj})
    }

    pub fn add_watch<W: Watch>(&mut self, watch: W) -> u32{
        unsafe{
            let watch: Box<Watch> = Box::new(watch);
            let watch: *mut Box<Watch> = Box::into_raw(Box::new(watch));
            gst_bus_add_watch (self.gst_bus_mut(), Some(bus_callback), mem::transmute(watch))
        }
    }

    pub fn remove_watch(&mut self) -> bool{
        unsafe{
            let message_cstr = CString::new(REMOVE_WATCH_MESSAGE_STR).unwrap();
            let structure = gst_structure_new(message_cstr.as_ptr(), ptr::null());
            let message = gst_message_new_application(ptr::null_mut(), structure);
            gst_bus_post(self.gst_bus_mut(), message) != 0
        }
    }

    pub fn receiver(&mut self) -> Receiver<Message>{
		let (watch,receiver) = channel();
		self.add_watch(watch);
		receiver
	}

    pub unsafe fn gst_bus(&self) -> *const GstBus{
        self.bus.gst_object() as *const GstBus
    }

    pub unsafe fn gst_bus_mut(&mut self) -> *mut GstBus{
        self.bus.gst_object_mut() as *mut GstBus
    }
}

extern "C" fn bus_callback(_bus: *mut GstBus, msg: *mut GstMessage, data: gpointer) -> gboolean {
    unsafe{
        let alive = {
            let mut watch: &mut Box<Watch> = mem::transmute(data);
            match Message::new(msg){
                Some(Message::Application(app_msg)) => {
                    let structure = gst_message_get_structure(app_msg);
                    let cname = gst_structure_get_name(structure);
                    if from_c_str!(cname) == REMOVE_WATCH_MESSAGE_STR{
                        false
                    }else{
                        watch.call(Message::Application(app_msg))
                    }
                }
    			Some(msg) => watch.call(msg),
    			None => true,
            }
        };
        if !alive{
            Box::from_raw(data);
        }
        if alive {1} else {0}
    }
}

pub trait Watch: Send{
    fn call(&mut self, msg: Message) -> bool;
}

impl Watch for mpsc::Sender<Message>{
	fn call(&mut self, msg: Message) -> bool{
        self.send(msg).is_ok()
	}
}

impl Reference for Bus{
    fn reference(&self) -> Bus{
        Bus{ bus: self.bus.reference() }
    }
}