Quellcode durchsuchen

Allow device type to be chosen.

Fix #187
Paul Lietar vor 7 Jahren
Ursprung
Commit
72070b6ce0
8 geänderte Dateien mit 242 neuen und 132 gelöschten Zeilen
  1. 3 3
      Cargo.lock
  2. 11 10
      src/authentication/discovery.rs
  3. 123 0
      src/config.rs
  4. 3 2
      src/lib.rs
  5. 78 57
      src/main.rs
  6. 12 6
      src/player.rs
  7. 5 48
      src/session.rs
  8. 7 6
      src/spirc.rs

+ 3 - 3
Cargo.lock

@@ -25,7 +25,7 @@ dependencies = [
  "protobuf_macros 0.6.0 (git+https://github.com/plietar/rust-protobuf-macros)",
  "rand 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
  "rpassword 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rust-crypto 0.2.36 (git+https://github.com/awmath/rust-crypto.git?branch=avx2)",
  "serde 0.9.15 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_derive 0.9.15 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_json 0.9.10 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -528,7 +528,7 @@ dependencies = [
 [[package]]
 name = "rust-crypto"
 version = "0.2.36"
-source = "registry+https://github.com/rust-lang/crates.io-index"
+source = "git+https://github.com/awmath/rust-crypto.git?branch=avx2#394c247254dbe2ac5d44483232cf335d10cf0260"
 dependencies = [
  "gcc 0.3.45 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1019,7 +1019,7 @@ dependencies = [
 "checksum regex 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4278c17d0f6d62dfef0ab00028feb45bd7d2102843f80763474eeb1be8a10c01"
 "checksum regex-syntax 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9191b1f57603095f105d317e375d19b1c9c5c3185ea9633a99a6dcbed04457"
 "checksum rpassword 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ec4bdede957362ec6fdd550f7e79c6d14cad2bc26b2d062786234c6ee0cb27bb"
-"checksum rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)" = "f76d05d3993fd5f4af9434e8e436db163a12a9d40e1a58a726f27a01dfd12a2a"
+"checksum rust-crypto 0.2.36 (git+https://github.com/awmath/rust-crypto.git?branch=avx2)" = "<none>"
 "checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda"
 "checksum rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "c5f5376ea5e30ce23c03eb77cbe4962b988deead10910c372b226388b594c084"
 "checksum scoped-tls 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f417c22df063e9450888a7561788e9bd46d3bb3c1466435b4eccb903807f147d"

+ 11 - 10
src/authentication/discovery.rs

@@ -19,19 +19,20 @@ use url;
 
 use authentication::Credentials;
 use util;
+use config::ConnectConfig;
 
 #[derive(Clone)]
 struct Discovery(Arc<DiscoveryInner>);
 struct DiscoveryInner {
+    config: ConnectConfig,
+    device_id: String,
     private_key: BigUint,
     public_key: BigUint,
-    device_id: String,
-    device_name: String,
     tx: mpsc::UnboundedSender<Credentials>,
 }
 
 impl Discovery {
-    pub fn new(device_name: String, device_id: String)
+    pub fn new(config: ConnectConfig, device_id: String)
         -> (Discovery, mpsc::UnboundedReceiver<Credentials>)
     {
         let (tx, rx) = mpsc::unbounded();
@@ -41,8 +42,8 @@ impl Discovery {
         let public_key = util::powm(&DH_GENERATOR, &private_key, &DH_PRIME);
 
         let discovery = Discovery(Arc::new(DiscoveryInner {
-            device_name: device_name.to_owned(),
-            device_id: device_id.to_owned(),
+            config: config,
+            device_id: device_id,
             private_key: private_key,
             public_key: public_key,
             tx: tx,
@@ -65,10 +66,10 @@ impl Discovery {
             "spotifyError": 0,
             "version": "2.1.0",
             "deviceID": (self.0.device_id),
-            "remoteName": (self.0.device_name),
+            "remoteName": (self.0.config.name),
             "activeUser": "",
             "publicKey": (public_key),
-            "deviceType": "UNKNOWN",
+            "deviceType": (self.0.config.device_type.to_string().to_uppercase()),
             "libraryVersion": "0.1.0",
             "accountReq": "PREMIUM",
             "brandDisplayName": "librespot",
@@ -206,10 +207,10 @@ pub struct DiscoveryStream {
     task: Box<Future<Item=(), Error=io::Error>>,
 }
 
-pub fn discovery(handle: &Handle, device_name: String, device_id: String)
+pub fn discovery(handle: &Handle, config: ConnectConfig, device_id: String)
     -> io::Result<DiscoveryStream>
 {
-    let (discovery, creds_rx) = Discovery::new(device_name.clone(), device_id);
+    let (discovery, creds_rx) = Discovery::new(config.clone(), device_id);
 
     let listener = TcpListener::bind(&"0.0.0.0:0".parse().unwrap(), handle)?;
     let addr = listener.local_addr()?;
@@ -224,7 +225,7 @@ pub fn discovery(handle: &Handle, device_name: String, device_id: String)
     let responder = mdns::Responder::spawn(&handle)?;
     let svc = responder.register(
         "_spotify-connect._tcp".to_owned(),
-        device_name,
+        config.name,
         addr.port(),
         &["VERSION=1.0", "CPath=/"]);
 

+ 123 - 0
src/config.rs

@@ -0,0 +1,123 @@
+use uuid::Uuid;
+use std::str::FromStr;
+use std::fmt;
+
+use version;
+
+#[derive(Clone, Copy, Debug, Hash, PartialOrd, Ord, PartialEq, Eq)]
+pub enum Bitrate {
+    Bitrate96,
+    Bitrate160,
+    Bitrate320,
+}
+
+impl FromStr for Bitrate {
+    type Err = ();
+    fn from_str(s: &str) -> Result<Self, Self::Err> {
+        match s {
+            "96" => Ok(Bitrate::Bitrate96),
+            "160" => Ok(Bitrate::Bitrate160),
+            "320" => Ok(Bitrate::Bitrate320),
+            _ => Err(()),
+        }
+    }
+}
+
+impl Default for Bitrate {
+    fn default() -> Bitrate {
+        Bitrate::Bitrate160
+    }
+}
+
+#[derive(Clone, Copy, Debug, Hash, PartialOrd, Ord, PartialEq, Eq)]
+pub enum DeviceType {
+    Unknown = 0,
+    Computer = 1,
+    Tablet = 2,
+    Smartphone = 3,
+    Speaker = 4,
+    TV = 5,
+    AVR = 6,
+    STB = 7,
+    AudioDongle = 8,
+}
+
+impl FromStr for DeviceType {
+    type Err = ();
+    fn from_str(s: &str) -> Result<Self, Self::Err> {
+        use self::DeviceType::*;
+        match s.to_lowercase().as_ref() {
+            "computer" => Ok(Computer),
+            "tablet" => Ok(Tablet),
+            "smartphone" => Ok(Smartphone),
+            "speaker" => Ok(Speaker),
+            "tv" => Ok(TV),
+            "avr" => Ok(AVR),
+            "stb" => Ok(STB),
+            "audiodongle" => Ok(AudioDongle),
+            _ => Err(()),
+        }
+    }
+}
+
+impl fmt::Display for DeviceType {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        use self::DeviceType::*;
+        match *self {
+            Unknown => f.write_str("Unknown"),
+            Computer => f.write_str("Computer"),
+            Tablet => f.write_str("Tablet"),
+            Smartphone => f.write_str("Smartphone"),
+            Speaker => f.write_str("Speaker"),
+            TV => f.write_str("TV"),
+            AVR => f.write_str("AVR"),
+            STB => f.write_str("STB"),
+            AudioDongle => f.write_str("AudioDongle"),
+        }
+    }
+}
+
+impl Default for DeviceType {
+    fn default() -> DeviceType {
+        DeviceType::Speaker
+    }
+}
+
+#[derive(Clone,Debug)]
+pub struct SessionConfig {
+    pub user_agent: String,
+    pub device_id: String,
+}
+
+impl Default for SessionConfig {
+    fn default() -> SessionConfig {
+        let device_id = Uuid::new_v4().hyphenated().to_string();
+        SessionConfig {
+            user_agent: version::version_string(),
+            device_id: device_id,
+        }
+    }
+}
+
+#[derive(Clone,Debug)]
+pub struct PlayerConfig {
+    pub bitrate: Bitrate,
+    pub onstart: Option<String>,
+    pub onstop: Option<String>,
+}
+
+impl Default for PlayerConfig {
+    fn default() -> PlayerConfig {
+        PlayerConfig {
+            bitrate: Bitrate::default(),
+            onstart: None,
+            onstop: None,
+        }
+    }
+}
+
+#[derive(Clone,Debug)]
+pub struct ConnectConfig {
+    pub name: String,
+    pub device_type: DeviceType,
+}

+ 3 - 2
src/lib.rs

@@ -61,14 +61,15 @@ pub mod audio_key;
 pub mod authentication;
 pub mod cache;
 pub mod channel;
+pub mod config;
 pub mod diffie_hellman;
+pub mod keymaster;
 pub mod mercury;
 pub mod metadata;
+pub mod mixer;
 pub mod player;
 pub mod session;
 pub mod util;
 pub mod version;
-pub mod mixer;
-pub mod keymaster;
 
 include!(concat!(env!("OUT_DIR"), "/lib.rs"));

+ 78 - 57
src/main.rs

@@ -26,7 +26,8 @@ use librespot::authentication::discovery::{discovery, DiscoveryStream};
 use librespot::audio_backend::{self, Sink, BACKENDS};
 use librespot::cache::Cache;
 use librespot::player::Player;
-use librespot::session::{Bitrate, Config, Session};
+use librespot::session::Session;
+use librespot::config::{Bitrate, DeviceType, PlayerConfig, SessionConfig, ConnectConfig};
 use librespot::mixer::{self, Mixer};
 
 use librespot::version;
@@ -76,9 +77,10 @@ struct Setup {
 
     mixer: fn() -> Box<Mixer>,
 
-    name: String,
     cache: Option<Cache>,
-    config: Config,
+    player_config: PlayerConfig,
+    session_config: SessionConfig,
+    connect_config: ConnectConfig,
     credentials: Option<Credentials>,
     enable_discovery: bool,
 }
@@ -88,6 +90,7 @@ fn setup(args: &[String]) -> Setup {
     opts.optopt("c", "cache", "Path to a directory where files will be cached.", "CACHE")
         .optflag("", "disable-audio-cache", "Disable caching of the audio data.")
         .reqopt("n", "name", "Device name", "NAME")
+        .optopt("", "device-type", "Displayed device type", "DEVICE_TYPE")
         .optopt("b", "bitrate", "Bitrate (96, 160 or 320). Defaults to 160", "BITRATE")
         .optopt("", "onstart", "Run PROGRAM when playback is about to begin.", "PROGRAM")
         .optopt("", "onstop", "Run PROGRAM when playback has ended.", "PROGRAM")
@@ -125,45 +128,69 @@ fn setup(args: &[String]) -> Setup {
     let backend = audio_backend::find(backend_name)
         .expect("Invalid backend");
 
+    let device = matches.opt_str("device");
+
     let mixer_name = matches.opt_str("mixer");
     let mixer = mixer::find(mixer_name.as_ref())
         .expect("Invalid mixer");
 
-    let bitrate = matches.opt_str("b").as_ref()
-        .map(|bitrate| Bitrate::from_str(bitrate).expect("Invalid bitrate"))
-        .unwrap_or(Bitrate::Bitrate160);
-
     let name = matches.opt_str("name").unwrap();
-    let device_id = librespot::session::device_id(&name);
     let use_audio_cache = !matches.opt_present("disable-audio-cache");
 
     let cache = matches.opt_str("c").map(|cache_location| {
         Cache::new(PathBuf::from(cache_location), use_audio_cache)
     });
 
-    let cached_credentials = cache.as_ref().and_then(Cache::credentials);
+    let credentials = {
+        let cached_credentials = cache.as_ref().and_then(Cache::credentials);
 
-    let credentials = get_credentials(matches.opt_str("username"),
-                                      matches.opt_str("password"),
-                                      cached_credentials);
+        get_credentials(
+            matches.opt_str("username"),
+            matches.opt_str("password"),
+            cached_credentials
+        )
+    };
 
-    let enable_discovery = !matches.opt_present("disable-discovery");
+    let session_config = {
+        let device_id = librespot::session::device_id(&name);
 
-    let config = Config {
-        user_agent: version::version_string(),
-        device_id: device_id,
-        bitrate: bitrate,
-        onstart: matches.opt_str("onstart"),
-        onstop: matches.opt_str("onstop"),
+        SessionConfig {
+            user_agent: version::version_string(),
+            device_id: device_id,
+        }
     };
 
-    let device = matches.opt_str("device");
+    let player_config = {
+        let bitrate = matches.opt_str("b").as_ref()
+            .map(|bitrate| Bitrate::from_str(bitrate).expect("Invalid bitrate"))
+            .unwrap_or(Bitrate::default());
+
+        PlayerConfig {
+            bitrate: bitrate,
+            onstart: matches.opt_str("onstart"),
+            onstop: matches.opt_str("onstop"),
+        }
+    };
+
+    let connect_config = {
+        let device_type = matches.opt_str("device-type").as_ref()
+            .map(|device_type| DeviceType::from_str(device_type).expect("Invalid device type"))
+            .unwrap_or(DeviceType::default());
+
+        ConnectConfig {
+            name: name,
+            device_type: device_type,
+        }
+    };
+
+    let enable_discovery = !matches.opt_present("disable-discovery");
 
     Setup {
-        name: name,
         backend: backend,
         cache: cache,
-        config: config,
+        session_config: session_config,
+        player_config: player_config,
+        connect_config: connect_config,
         credentials: credentials,
         device: device,
         enable_discovery: enable_discovery,
@@ -172,9 +199,10 @@ fn setup(args: &[String]) -> Setup {
 }
 
 struct Main {
-    name: String,
     cache: Option<Cache>,
-    config: Config,
+    player_config: PlayerConfig,
+    session_config: SessionConfig,
+    connect_config: ConnectConfig,
     backend: fn(Option<String>) -> Box<Sink>,
     device: Option<String>,
     mixer: fn() -> Box<Mixer>,
@@ -191,22 +219,16 @@ struct Main {
 }
 
 impl Main {
-    fn new(handle: Handle,
-           name: String,
-           config: Config,
-           cache: Option<Cache>,
-           backend: fn(Option<String>) -> Box<Sink>,
-           device: Option<String>,
-           mixer: fn() -> Box<Mixer>) -> Main
-    {
-        Main {
+    fn new(handle: Handle, setup: Setup) -> Main {
+        let mut task = Main {
             handle: handle.clone(),
-            name: name,
-            cache: cache,
-            config: config,
-            backend: backend,
-            device: device,
-            mixer: mixer,
+            cache: setup.cache,
+            session_config: setup.session_config,
+            player_config: setup.player_config,
+            connect_config: setup.connect_config,
+            backend: setup.backend,
+            device: setup.device,
+            mixer: setup.mixer,
 
             connect: Box::new(futures::future::empty()),
             discovery: None,
@@ -214,18 +236,24 @@ impl Main {
             spirc_task: None,
             shutdown: false,
             signal: tokio_signal::ctrl_c(&handle).flatten_stream().boxed(),
+        };
+
+        if setup.enable_discovery {
+            let config = task.connect_config.clone();
+            let device_id = task.session_config.device_id.clone();
+
+            task.discovery = Some(discovery(&handle, config, device_id).unwrap());
         }
-    }
 
-    fn discovery(&mut self) {
-        let device_id = self.config.device_id.clone();
-        let name = self.name.clone();
+        if let Some(credentials) = setup.credentials {
+            task.credentials(credentials);
+        }
 
-        self.discovery = Some(discovery(&self.handle, name, device_id).unwrap());
+        task
     }
 
     fn credentials(&mut self, credentials: Credentials) {
-        let config = self.config.clone();
+        let config = self.session_config.clone();
         let handle = self.handle.clone();
 
         let connection = Session::connect(config, credentials, self.cache.clone(), handle);
@@ -260,14 +288,16 @@ impl Future for Main {
                 self.connect = Box::new(futures::future::empty());
                 let device = self.device.clone();
                 let mixer = (self.mixer)();
+                let player_config = self.player_config.clone();
+                let connect_config = self.connect_config.clone();
 
                 let audio_filter = mixer.get_audio_filter();
                 let backend = self.backend;
-                let player = Player::new(session.clone(), audio_filter, move || {
+                let player = Player::new(player_config, session.clone(), audio_filter, move || {
                     (backend)(device)
                 });
 
-                let (spirc, spirc_task) = Spirc::new(self.name.clone(), session, player, mixer);
+                let (spirc, spirc_task) = Spirc::new(connect_config, session, player, mixer);
                 self.spirc = Some(spirc);
                 self.spirc_task = Some(spirc_task);
 
@@ -309,16 +339,7 @@ fn main() {
     let handle = core.handle();
 
     let args: Vec<String> = std::env::args().collect();
-    let Setup { name, backend, config, device, cache, enable_discovery, credentials, mixer } = setup(&args);
-
-    let mut task = Main::new(handle, name, config, cache, backend, device, mixer);
-    if enable_discovery {
-        task.discovery();
-    }
-    if let Some(credentials) = credentials {
-        task.credentials(credentials);
-    }
 
-    core.run(task).unwrap()
+    core.run(Main::new(handle, setup(&args))).unwrap()
 }
 

+ 12 - 6
src/player.rs

@@ -12,9 +12,10 @@ use audio_backend::Sink;
 use audio_decrypt::AudioDecrypt;
 use audio_file::AudioFile;
 use metadata::{FileFormat, Track};
-use session::{Bitrate, Session};
+use session::Session;
 use mixer::AudioFilter;
 use util::{self, SpotifyId, Subfile};
+use config::{Bitrate, PlayerConfig};
 
 #[derive(Clone)]
 pub struct Player {
@@ -23,6 +24,7 @@ pub struct Player {
 
 struct PlayerInternal {
     session: Session,
+    config: PlayerConfig,
     commands: std::sync::mpsc::Receiver<PlayerCommand>,
 
     state: PlayerState,
@@ -39,8 +41,11 @@ enum PlayerCommand {
 }
 
 impl Player {
-    pub fn new<F>(session: Session, audio_filter: Option<Box<AudioFilter + Send>>, sink_builder: F) -> Player
-        where F: FnOnce() -> Box<Sink> + Send + 'static {
+    pub fn new<F>(config: PlayerConfig, session: Session,
+                  audio_filter: Option<Box<AudioFilter + Send>>,
+                  sink_builder: F) -> Player
+        where F: FnOnce() -> Box<Sink> + Send + 'static
+    {
         let (cmd_tx, cmd_rx) = std::sync::mpsc::channel();
 
         thread::spawn(move || {
@@ -48,6 +53,7 @@ impl Player {
 
             let internal = PlayerInternal {
                 session: session,
+                config: config,
                 commands: cmd_rx,
 
                 state: PlayerState::Stopped,
@@ -314,13 +320,13 @@ impl PlayerInternal {
     }
 
     fn run_onstart(&self) {
-        if let Some(ref program) = self.session.config().onstart {
+        if let Some(ref program) = self.config.onstart {
             util::run_program(program)
         }
     }
 
     fn run_onstop(&self) {
-        if let Some(ref program) = self.session.config().onstop {
+        if let Some(ref program) = self.config.onstop {
             util::run_program(program)
         }
     }
@@ -353,7 +359,7 @@ impl PlayerInternal {
             }
         };
 
-        let format = match self.session.config().bitrate {
+        let format = match self.config.bitrate {
             Bitrate::Bitrate96 => FileFormat::OGG_VORBIS_96,
             Bitrate::Bitrate160 => FileFormat::OGG_VORBIS_160,
             Bitrate::Bitrate320 => FileFormat::OGG_VORBIS_320,

+ 5 - 48
src/session.rs

@@ -3,20 +3,17 @@ use crypto::sha1::Sha1;
 use futures::sync::mpsc;
 use futures::{Future, Stream, BoxFuture, IntoFuture, Poll, Async};
 use std::io;
-use std::result::Result;
-use std::str::FromStr;
 use std::sync::{RwLock, Arc, Weak};
 use tokio_core::io::EasyBuf;
 use tokio_core::reactor::{Handle, Remote};
 use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};
-use uuid::Uuid;
 
 use apresolve::apresolve_or_fallback;
 use authentication::Credentials;
 use cache::Cache;
 use component::Lazy;
 use connection;
-use version;
+use config::SessionConfig;
 
 use audio_key::AudioKeyManager;
 use channel::ChannelManager;
@@ -24,53 +21,13 @@ use mercury::MercuryManager;
 use metadata::MetadataManager;
 use audio_file::AudioFileManager;
 
-#[derive(Clone, Copy, Debug, PartialOrd, Ord, PartialEq, Eq)]
-pub enum Bitrate {
-    Bitrate96,
-    Bitrate160,
-    Bitrate320,
-}
-impl FromStr for Bitrate {
-    type Err = String;
-    fn from_str(s: &str) -> Result<Self, Self::Err> {
-        match s {
-            "96" => Ok(Bitrate::Bitrate96),
-            "160" => Ok(Bitrate::Bitrate160),
-            "320" => Ok(Bitrate::Bitrate320),
-            _ => Err(s.into()),
-        }
-    }
-}
-
-#[derive(Clone)]
-pub struct Config {
-    pub user_agent: String,
-    pub device_id: String,
-    pub bitrate: Bitrate,
-    pub onstart: Option<String>,
-    pub onstop: Option<String>,
-}
-
-impl Default for Config {
-    fn default() -> Config {
-        let device_id = Uuid::new_v4().hyphenated().to_string();
-        Config {
-            user_agent: version::version_string(),
-            device_id: device_id,
-            bitrate: Bitrate::Bitrate160,
-            onstart: None,
-            onstop: None,
-        }
-    }
-}
-
 pub struct SessionData {
     country: String,
     canonical_username: String,
 }
 
 pub struct SessionInternal {
-    config: Config,
+    config: SessionConfig,
     data: RwLock<SessionData>,
 
     tx_connection: mpsc::UnboundedSender<(u8, Vec<u8>)>,
@@ -99,7 +56,7 @@ pub fn device_id(name: &str) -> String {
 }
 
 impl Session {
-    pub fn connect(config: Config, credentials: Credentials,
+    pub fn connect(config: SessionConfig, credentials: Credentials,
                    cache: Option<Cache>, handle: Handle)
         -> Box<Future<Item=Session, Error=io::Error>>
     {
@@ -135,7 +92,7 @@ impl Session {
     }
 
     fn create(handle: &Handle, transport: connection::Transport,
-              config: Config, cache: Option<Cache>, username: String)
+              config: SessionConfig, cache: Option<Cache>, username: String)
         -> (Session, BoxFuture<(), io::Error>)
     {
         let (sink, stream) = transport.split();
@@ -240,7 +197,7 @@ impl Session {
         self.0.cache.as_ref()
     }
 
-    pub fn config(&self) -> &Config {
+    pub fn config(&self) -> &SessionConfig {
         &self.0.config
     }
 

+ 7 - 6
src/spirc.rs

@@ -5,9 +5,10 @@ use futures::sync::{oneshot, mpsc};
 use futures::{Future, Stream, Sink, Async, Poll, BoxFuture};
 use protobuf::{self, Message};
 
+use config::ConnectConfig;
 use mercury::MercuryError;
-use player::Player;
 use mixer::Mixer;
+use player::Player;
 use session::Session;
 use util::{now_ms, SpotifyId, SeqGenerator};
 use version;
@@ -59,13 +60,13 @@ fn initial_state() -> State {
     })
 }
 
-fn initial_device_state(name: String, volume: u16) -> DeviceState {
+fn initial_device_state(config: ConnectConfig, volume: u16) -> DeviceState {
     protobuf_init!(DeviceState::new(), {
         sw_version: version::version_string(),
         is_active: false,
         can_play: true,
         volume: volume as u32,
-        name: name,
+        name: config.name,
         capabilities => [
             @{
                 typ: protocol::spirc::CapabilityType::kCanBePlayer,
@@ -73,7 +74,7 @@ fn initial_device_state(name: String, volume: u16) -> DeviceState {
             },
             @{
                 typ: protocol::spirc::CapabilityType::kDeviceType,
-                intValue => [5]
+                intValue => [config.device_type as i64]
             },
             @{
                 typ: protocol::spirc::CapabilityType::kGaiaEqConnectId,
@@ -118,7 +119,7 @@ fn initial_device_state(name: String, volume: u16) -> DeviceState {
 }
 
 impl Spirc {
-    pub fn new(name: String, session: Session, player: Player, mixer: Box<Mixer>)
+    pub fn new(config: ConnectConfig, session: Session, player: Player, mixer: Box<Mixer>)
         -> (Spirc, SpircTask)
     {
         debug!("new Spirc[{}]", session.session_id());
@@ -141,7 +142,7 @@ impl Spirc {
         let (cmd_tx, cmd_rx) = mpsc::unbounded();
 
         let volume = 0xFFFF;
-        let device = initial_device_state(name, volume);
+        let device = initial_device_state(config, volume);
         mixer.set_volume(volume);
 
         let mut task = SpircTask {