Skip to content

Commit

Permalink
Merge pull request #116 from librespot-org/jackaudio
Browse files Browse the repository at this point in the history
Jackaudio Support. Closes #93.

Move keymaster to core

Move keymaster to core

Modularise discovery.
  • Loading branch information
sashahilton00 committed Feb 8, 2018
2 parents 59782fe + b22f252 commit 75ce97a
Show file tree
Hide file tree
Showing 7 changed files with 125 additions and 4 deletions.
35 changes: 35 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ url = "1.3"
alsa = { git = "https://github.com/plietar/rust-alsa", optional = true }
portaudio-rs = { version = "0.3.0", optional = true }
libpulse-sys = { version = "0.0.0", optional = true }
jack = { version = "0.5.3", optional = true }
libc = { version = "0.2", optional = true }
dns-sd = { version = "0.1.3", optional = true }

Expand All @@ -65,6 +66,7 @@ protobuf_macros = { git = "https://github.com/plietar/rust-protobuf-macros", fea
alsa-backend = ["alsa"]
portaudio-backend = ["portaudio-rs"]
pulseaudio-backend = ["libpulse-sys", "libc"]
jackaudio-backend = ["jack"]

with-tremor = ["librespot-audio/with-tremor"]
with-lewton = ["librespot-audio/with-lewton"]
Expand Down
4 changes: 2 additions & 2 deletions src/keymaster.rs → core/src/keymaster.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use futures::Future;
use serde_json;

use core::mercury::MercuryError;
use core::session::Session;
use mercury::MercuryError;
use session::Session;

#[derive(Deserialize, Debug, Clone)]
#[serde(rename_all = "camelCase")]
Expand Down
1 change: 1 addition & 0 deletions core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ pub mod cache;
pub mod channel;
pub mod config;
pub mod diffie_hellman;
pub mod keymaster;
pub mod mercury;
pub mod session;
pub mod util;
Expand Down
75 changes: 75 additions & 0 deletions src/audio_backend/jackaudio.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
use std::io;
use super::{Open, Sink};
use jack::prelude::{AudioOutPort, AudioOutSpec, Client, JackControl, ProcessScope, AsyncClient, client_options, ProcessHandler, Port };
use std::sync::mpsc::{sync_channel, SyncSender, Receiver};

pub struct JackSink {
send: SyncSender<i16>,
active_client: AsyncClient<(),JackData>,
}

pub struct JackData {
rec: Receiver<i16>,
port_l: Port<AudioOutSpec>,
port_r: Port<AudioOutSpec>,
}

fn pcm_to_f32(sample: i16) -> f32 {
sample as f32 / 32768.0;
}

impl ProcessHandler for JackData {
fn process(&mut self, _: &Client, ps: &ProcessScope) -> JackControl {
// get output port buffers
let mut out_r = AudioOutPort::new(&mut self.port_r, ps);
let mut out_l = AudioOutPort::new(&mut self.port_l, ps);
let buf_r: &mut [f32] = &mut out_r;
let buf_l: &mut [f32] = &mut out_l;
// get queue iterator
let mut queue_iter = self.rec.try_iter();

let buf_size = buf_r.len();
for i in 0..buf_size {
buf_r[i] = pcm_to_f32(queue_iter.next().unwrap_or(0));
buf_l[i] = pcm_to_f32(queue_iter.next().unwrap_or(0));
}
JackControl::Continue
}
}

impl Open for JackSink {
fn open(client_name: Option<String>) -> JackSink {
info!("Using jack sink!");

let client_name = client_name.unwrap_or("librespot".to_string());
let (client, _status) = Client::new(&client_name[..], client_options::NO_START_SERVER).unwrap();
let ch_r = client.register_port("out_0", AudioOutSpec::default()).unwrap();
let ch_l = client.register_port("out_1", AudioOutSpec::default()).unwrap();
// buffer for samples from librespot (~10ms)
let (tx, rx) = sync_channel(2*1024*4);
let jack_data = JackData { rec: rx, port_l: ch_l, port_r: ch_r };
let active_client = AsyncClient::new(client, (), jack_data).unwrap();

JackSink { send: tx, active_client: active_client }
}
}

impl Sink for JackSink {
fn start(&mut self) -> io::Result<()> {
Ok(())
}

fn stop(&mut self) -> io::Result<()> {
Ok(())
}

fn write(&mut self, data: &[i16]) -> io::Result<()> {
for s in data.iter() {
let res = self.send.send(*s);
if res.is_err() {
error!("jackaudio: cannot write to channel");
}
}
Ok(())
}
}
7 changes: 7 additions & 0 deletions src/audio_backend/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@ mod pulseaudio;
#[cfg(feature = "pulseaudio-backend")]
use self::pulseaudio::PulseAudioSink;

#[cfg(feature = "jackaudio-backend")]
mod jackaudio;
#[cfg(feature = "jackaudio-backend")]
use self::jackaudio::JackSink;

mod pipe;
use self::pipe::StdoutSink;

Expand All @@ -41,6 +46,8 @@ pub const BACKENDS : &'static [
("portaudio", mk_sink::<PortAudioSink>),
#[cfg(feature = "pulseaudio-backend")]
("pulseaudio", mk_sink::<PulseAudioSink>),
#[cfg(feature = "jackaudio-backend")]
("jackaudio", mk_sink::<JackSink>),
("pipe", mk_sink::<StdoutSink>),
];

Expand Down
5 changes: 3 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

#[macro_use] extern crate log;
#[macro_use] extern crate serde_json;
#[macro_use] extern crate serde_derive;

extern crate base64;
extern crate crypto;
Expand All @@ -30,6 +29,9 @@ extern crate portaudio_rs;
#[cfg(feature = "libpulse-sys")]
extern crate libpulse_sys;

#[cfg(feature = "jackaudio-backend")]
extern crate jack;

#[cfg(feature = "libc")]
extern crate libc;

Expand All @@ -41,7 +43,6 @@ extern crate mdns;

pub mod audio_backend;
pub mod discovery;
pub mod keymaster;
pub mod mixer;
pub mod player;

Expand Down

0 comments on commit 75ce97a

Please sign in to comment.