aboutsummaryrefslogtreecommitdiff
path: root/src/sources/spotify.rs
blob: b23ea736150a05b490c9df3df55eb24c03bf979c (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
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 Spotify;

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

impl LyricsSource for Spotify {

    fn name(&self) -> String {
        "spotify".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.spotify.Client"); 
                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(())
    }
}