aboutsummaryrefslogtreecommitdiff
path: root/src/sources/apple_music.rs
blob: cb36f5c4d2fa980be4820c0980132e2ee4c28f29 (plain)
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
use std::ffi::CStr;
use std::io::Result;

use cocoa::{base::nil, foundation::NSString};
use objc::{class, msg_send, sel, sel_impl, runtime::Object};
use objc_id::Id;

use crate::Track;

use super::LyricsSource;

pub struct AppleMusic;

impl AppleMusic {
    pub fn new() -> Self {
        AppleMusic
    }
}

impl LyricsSource for AppleMusic {

    fn name(&self) -> String {
        "apple_music".to_string()
    }

    fn current_track(&self) -> Option<Track> {
        unsafe {
            let app: Id<Object> = {
                let cls = class!(SBApplication);
                let bundle_identifier = NSString::alloc(nil).init_str("com.apple.Music"); 
                let app: *mut Object = msg_send![cls, applicationWithBundleIdentifier:bundle_identifier];
                Id::from_ptr(app)
            };

            if msg_send![app, isRunning] {
                let current_track: *mut Object = msg_send![app, currentTrack];
                if !current_track.is_null() {
                    let name_raw: *mut Object = msg_send![current_track, name];
                    let artist_raw: *mut Object = msg_send![current_track, artist];

                    let name_ptr: *const i8 = msg_send![name_raw, UTF8String];
                    let artist_ptr: *const i8 = msg_send![artist_raw, UTF8String];

                    let name = CStr::from_ptr(name_ptr).to_string_lossy().into_owned();
                    let artist = CStr::from_ptr(artist_ptr).to_string_lossy().into_owned();


                    return Some(Track {
                        name,
                        artist
                    })
                }
            }
        }
        None
    }

    fn disable(&self) -> Result<()> {
        Ok(())
    }

    fn enable(&self) -> Result<()> {
        Ok(())
    }

    fn reset(&self) -> Result<()> {
        Ok(())
    }
}