mirror of
https://github.com/librespot-org/librespot.git
synced 2024-12-18 17:11:53 +00:00
Add initial Spirc support.
This commit is contained in:
parent
addc1fce22
commit
7897070bb7
2 changed files with 47 additions and 12 deletions
29
src/main.rs
29
src/main.rs
|
@ -1,10 +1,12 @@
|
||||||
#![crate_name = "librespot"]
|
#![crate_name = "librespot"]
|
||||||
|
|
||||||
#![feature(plugin,zero_one,iter_arith,slice_position_elem,slice_bytes,bitset,mpsc_select,arc_weak,append)]
|
#![feature(plugin,zero_one,iter_arith,slice_position_elem,slice_bytes,bitset,mpsc_select,arc_weak,append)]
|
||||||
|
#![allow(unused_imports,dead_code)]
|
||||||
|
|
||||||
#![plugin(protobuf_macros)]
|
#![plugin(protobuf_macros)]
|
||||||
#[macro_use] extern crate lazy_static;
|
#[macro_use] extern crate lazy_static;
|
||||||
|
|
||||||
|
|
||||||
extern crate byteorder;
|
extern crate byteorder;
|
||||||
extern crate crypto;
|
extern crate crypto;
|
||||||
extern crate gmp;
|
extern crate gmp;
|
||||||
|
@ -35,19 +37,20 @@ use std::clone::Clone;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::{Read, Write};
|
use std::io::{Read, Write};
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
use std::sync::mpsc;
|
||||||
|
|
||||||
use metadata::{MetadataCache, AlbumRef, ArtistRef, TrackRef};
|
use metadata::{MetadataCache, AlbumRef, ArtistRef, TrackRef};
|
||||||
use session::{Config, Session};
|
use session::{Config, Session};
|
||||||
use util::SpotifyId;
|
use util::SpotifyId;
|
||||||
use player::Player;
|
use player::Player;
|
||||||
|
use mercury::{MercuryRequest, MercuryMethod};
|
||||||
|
use librespot_protocol as protocol;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let mut args = std::env::args().skip(1);
|
let mut args = std::env::args().skip(1);
|
||||||
let mut appkey_file = File::open(Path::new(&args.next().unwrap())).unwrap();
|
let mut appkey_file = File::open(Path::new(&args.next().unwrap())).unwrap();
|
||||||
let username = args.next().unwrap();
|
let username = args.next().unwrap();
|
||||||
let password = args.next().unwrap();
|
let password = args.next().unwrap();
|
||||||
let track_uri = args.next().unwrap();
|
|
||||||
let track_id = SpotifyId::from_base62(track_uri.split(':').nth(2).unwrap());
|
|
||||||
|
|
||||||
let mut appkey = Vec::new();
|
let mut appkey = Vec::new();
|
||||||
appkey_file.read_to_end(&mut appkey).unwrap();
|
appkey_file.read_to_end(&mut appkey).unwrap();
|
||||||
|
@ -63,8 +66,28 @@ fn main() {
|
||||||
|
|
||||||
let mut cache = MetadataCache::new(session.metadata.clone());
|
let mut cache = MetadataCache::new(session.metadata.clone());
|
||||||
|
|
||||||
|
let (tx, rx) = mpsc::channel();
|
||||||
|
|
||||||
print_track(&mut cache, track_id);
|
session.mercury.send(MercuryRequest{
|
||||||
|
method: MercuryMethod::SUB,
|
||||||
|
uri: "hm://remote/user/lietar/v23".to_string(),
|
||||||
|
content_type: None,
|
||||||
|
callback: Some(tx)
|
||||||
|
}).unwrap();
|
||||||
|
|
||||||
|
for pkt in rx.iter() {
|
||||||
|
let frame : protocol::spirc::Frame =
|
||||||
|
protobuf::parse_from_bytes(pkt.payload.front().unwrap()).unwrap();
|
||||||
|
|
||||||
|
if frame.get_device_state().get_is_active() &&
|
||||||
|
frame.has_state() {
|
||||||
|
let index = frame.get_state().get_playing_track_index();
|
||||||
|
let ref track = frame.get_state().get_track()[index as usize];
|
||||||
|
println!("{}", frame.get_device_state().get_name());
|
||||||
|
print_track(&mut cache, SpotifyId::from_raw(track.get_gid()));
|
||||||
|
println!("");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
session.poll();
|
session.poll();
|
||||||
|
|
|
@ -23,7 +23,7 @@ pub struct MercuryRequest {
|
||||||
pub method: MercuryMethod,
|
pub method: MercuryMethod,
|
||||||
pub uri: String,
|
pub uri: String,
|
||||||
pub content_type: Option<String>,
|
pub content_type: Option<String>,
|
||||||
pub callback: MercuryCallback
|
pub callback: Option<MercuryCallback>
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -32,17 +32,18 @@ pub struct MercuryResponse {
|
||||||
pub payload: LinkedList<Vec<u8>>
|
pub payload: LinkedList<Vec<u8>>
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type MercuryCallback = Option<mpsc::Sender<MercuryResponse>>;
|
pub type MercuryCallback = mpsc::Sender<MercuryResponse>;
|
||||||
|
|
||||||
pub struct MercuryPending {
|
pub struct MercuryPending {
|
||||||
parts: LinkedList<Vec<u8>>,
|
parts: LinkedList<Vec<u8>>,
|
||||||
partial: Option<Vec<u8>>,
|
partial: Option<Vec<u8>>,
|
||||||
callback: MercuryCallback,
|
callback: Option<MercuryCallback>
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct MercuryManager {
|
pub struct MercuryManager {
|
||||||
next_seq: u32,
|
next_seq: u32,
|
||||||
pending: HashMap<Vec<u8>, MercuryPending>,
|
pending: HashMap<Vec<u8>, MercuryPending>,
|
||||||
|
subscriptions: HashMap<String, MercuryCallback>,
|
||||||
|
|
||||||
requests: mpsc::Receiver<MercuryRequest>,
|
requests: mpsc::Receiver<MercuryRequest>,
|
||||||
packet_tx: mpsc::Sender<Packet>,
|
packet_tx: mpsc::Sender<Packet>,
|
||||||
|
@ -69,6 +70,7 @@ impl MercuryManager {
|
||||||
(MercuryManager {
|
(MercuryManager {
|
||||||
next_seq: 0,
|
next_seq: 0,
|
||||||
pending: HashMap::new(),
|
pending: HashMap::new(),
|
||||||
|
subscriptions: HashMap::new(),
|
||||||
|
|
||||||
requests: req_rx,
|
requests: req_rx,
|
||||||
packet_rx: pkt_rx,
|
packet_rx: pkt_rx,
|
||||||
|
@ -93,11 +95,15 @@ impl MercuryManager {
|
||||||
data: data
|
data: data
|
||||||
}).unwrap();
|
}).unwrap();
|
||||||
|
|
||||||
self.pending.insert(seq.to_vec(), MercuryPending{
|
if req.method != MercuryMethod::SUB {
|
||||||
parts: LinkedList::new(),
|
self.pending.insert(seq.to_vec(), MercuryPending{
|
||||||
partial: None,
|
parts: LinkedList::new(),
|
||||||
callback: req.callback,
|
partial: None,
|
||||||
});
|
callback: req.callback,
|
||||||
|
});
|
||||||
|
} else if let Some(cb) = req.callback {
|
||||||
|
self.subscriptions.insert(req.uri, cb);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_part(mut s: &mut Read) -> Vec<u8> {
|
fn parse_part(mut s: &mut Read) -> Vec<u8> {
|
||||||
|
@ -117,7 +123,13 @@ impl MercuryManager {
|
||||||
let header : protocol::mercury::Header =
|
let header : protocol::mercury::Header =
|
||||||
protobuf::parse_from_bytes(&header_data).unwrap();
|
protobuf::parse_from_bytes(&header_data).unwrap();
|
||||||
|
|
||||||
if let Some(ref ch) = pending.callback {
|
let callback = if cmd == 0xb5 {
|
||||||
|
self.subscriptions.get(header.get_uri())
|
||||||
|
} else {
|
||||||
|
pending.callback.as_ref()
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some(ref ch) = callback {
|
||||||
ch.send(MercuryResponse{
|
ch.send(MercuryResponse{
|
||||||
uri: header.get_uri().to_string(),
|
uri: header.get_uri().to_string(),
|
||||||
payload: pending.parts
|
payload: pending.parts
|
||||||
|
|
Loading…
Reference in a new issue