A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita audio rust zig deno mpris rockbox mpd
at master 160 lines 5.6 kB view raw
1use local_ip_addr::get_local_ip_address; 2use mdns_sd::ServiceInfo; 3use serde::{Deserialize, Serialize}; 4 5pub const CHROMECAST_SERVICE_NAME: &str = "_googlecast._tcp.local."; 6pub const AIRPLAY_SERVICE_NAME: &str = "_raop._tcp.local."; 7pub const ROCKBOX_SERVICE_NAME: &str = "_rockbox._tcp.local."; 8pub const XBMC_SERVICE_NAME: &str = "_xbmc-jsonrpc-h._tcp.local."; 9 10pub const AIRPLAY_DEVICE: &str = "AirPlay"; 11pub const CHROMECAST_DEVICE: &str = "Chromecast"; 12pub const XBMC_DEVICE: &str = "XBMC"; 13pub const MUSIC_PLAYER_DEVICE: &str = "MusicPlayer"; 14pub const UPNP_DLNA_DEVICE: &str = "UPnP/DLNA"; 15pub const ROCKBOX_DEVICE: &str = "Rockbox"; 16 17#[derive(Default, Clone, Serialize, Deserialize)] 18pub struct Device { 19 pub id: String, 20 pub name: String, 21 pub host: String, 22 pub ip: String, 23 pub port: u16, 24 pub service: String, 25 pub app: String, 26 pub is_connected: bool, 27 pub base_url: Option<String>, 28 pub is_cast_device: bool, 29 pub is_source_device: bool, 30 pub is_current_device: bool, 31} 32 33impl Device { 34 pub fn with_base_url(&mut self, base_url: Option<String>) -> Self { 35 self.base_url = base_url; 36 self.clone() 37 } 38} 39 40impl From<ServiceInfo> for Device { 41 fn from(srv: ServiceInfo) -> Self { 42 if srv.get_fullname().contains("xbmc") { 43 return Self { 44 id: srv.get_fullname().to_owned(), 45 name: srv 46 .get_fullname() 47 .replace(XBMC_SERVICE_NAME, "") 48 .replace(".", "") 49 .to_owned(), 50 host: srv 51 .get_hostname() 52 .split_at(srv.get_hostname().len() - 1) 53 .0 54 .to_owned(), 55 ip: srv.get_addresses().iter().next().unwrap().to_string(), 56 port: srv.get_port(), 57 service: srv.get_fullname().to_owned(), 58 app: "xbmc".to_owned(), 59 is_connected: false, 60 base_url: None, 61 is_cast_device: true, 62 is_source_device: true, 63 is_current_device: false, 64 }; 65 } 66 67 if srv.get_fullname().contains(ROCKBOX_SERVICE_NAME) { 68 let device_id = srv 69 .get_fullname() 70 .replace(ROCKBOX_SERVICE_NAME, "") 71 .split("-") 72 .collect::<Vec<&str>>()[1] 73 .replace(".", "") 74 .to_owned(); 75 76 let is_current_device = device_id == "device_id" 77 && srv.get_fullname().split("-").collect::<Vec<&str>>()[0].to_owned() == "http"; 78 79 let mut addresses = srv.get_addresses().iter(); 80 let mut ip = addresses.next().unwrap().to_string(); 81 82 if is_current_device { 83 ip = get_local_ip_address().unwrap(); 84 } 85 86 return Self { 87 id: device_id.clone(), 88 name: srv 89 .get_properties() 90 .get("device_name") 91 .unwrap_or(&device_id.clone()) 92 .to_string(), 93 host: srv 94 .get_hostname() 95 .split_at(srv.get_hostname().len() - 1) 96 .0 97 .to_owned(), 98 ip, 99 port: srv.get_port(), 100 service: srv.get_fullname().split("-").collect::<Vec<&str>>()[0].to_owned(), 101 app: "rockbox".to_owned(), 102 is_connected: false, 103 base_url: None, 104 is_cast_device: true, 105 is_source_device: true, 106 is_current_device, 107 }; 108 } 109 110 if srv.get_fullname().contains(CHROMECAST_SERVICE_NAME) { 111 return Self { 112 id: srv.get_properties().get("id").unwrap().to_owned(), 113 name: srv.get_properties().get("fn").unwrap().to_owned(), 114 host: srv 115 .get_hostname() 116 .split_at(srv.get_hostname().len() - 1) 117 .0 118 .to_owned(), 119 ip: srv.get_addresses().iter().next().unwrap().to_string(), 120 port: srv.get_port(), 121 service: srv.get_fullname().to_owned(), 122 app: "chromecast".to_owned(), 123 is_connected: false, 124 base_url: None, 125 is_cast_device: true, 126 is_source_device: false, 127 is_current_device: false, 128 }; 129 } 130 131 if srv.get_fullname().contains(AIRPLAY_SERVICE_NAME) { 132 let name = srv.get_fullname().split("@").collect::<Vec<&str>>()[1] 133 .replace(AIRPLAY_SERVICE_NAME, "") 134 .to_owned(); 135 let name = name.split_at(name.len() - 1).0.to_owned(); 136 return Self { 137 id: srv.get_fullname().to_owned(), 138 name, 139 host: srv 140 .get_hostname() 141 .split_at(srv.get_hostname().len() - 1) 142 .0 143 .to_owned(), 144 ip: srv.get_addresses().iter().next().unwrap().to_string(), 145 port: srv.get_port(), 146 service: srv.get_fullname().to_owned(), 147 app: "airplay".to_owned(), 148 is_connected: false, 149 base_url: None, 150 is_cast_device: true, 151 is_source_device: false, 152 is_current_device: false, 153 }; 154 } 155 156 Self { 157 ..Default::default() 158 } 159 } 160}