Skip to content

Commit

Permalink
Add JackHost devices to rodio-backend
Browse files Browse the repository at this point in the history
  • Loading branch information
Lcchy committed Dec 13, 2020
1 parent 8ff1dc2 commit 659ea26
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 26 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ portaudio-backend = ["librespot-playback/portaudio-backend"]
pulseaudio-backend = ["librespot-playback/pulseaudio-backend"]
jackaudio-backend = ["librespot-playback/jackaudio-backend"]
rodio-backend = ["librespot-playback/rodio-backend"]
rodiojack-backend = ["librespot-playback/rodiojack-backend"]
sdl-backend = ["librespot-playback/sdl-backend"]
gstreamer-backend = ["librespot-playback/gstreamer-backend"]

Expand Down
3 changes: 2 additions & 1 deletion playback/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ alsa-backend = ["alsa"]
portaudio-backend = ["portaudio-rs"]
pulseaudio-backend = ["libpulse-sys", "libc"]
jackaudio-backend = ["jack"]
rodio-backend = ["rodio", "cpal"]
rodio-backend = ["rodio", "cpal/jack"]
rodiojack-backend = ["rodio", "cpal/jack"]
sdl-backend = ["sdl2"]
gstreamer-backend = ["gstreamer", "gstreamer-app", "glib", "zerocopy"]
75 changes: 50 additions & 25 deletions playback/src/audio_backend/rodio.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
use super::{Open, Sink};
extern crate cpal;
extern crate rodio;
use cpal::traits::{DeviceTrait, HostTrait};
use std::process::exit;
use std::{io, thread, time};
use cpal::{HostId, traits::{DeviceTrait, HostTrait}};

pub struct RodioSink {
rodio_sink: rodio::Sink,
Expand Down Expand Up @@ -46,14 +46,18 @@ fn list_outputs() {
list_formats(&default_device);

println!("Other Available Audio Devices:");
for device in cpal::default_host()
.output_devices()
.expect("cannot get list of output devices")
{
let device_name = device.name().expect("cannot get output name");
if device_name != default_device_name {
for host in cpal::available_hosts() {
let found_devices = cpal::host_from_id(host)
.expect(&format!("Host {:?} not found", host))
.output_devices().expect(&format!("Cannot get list of output devices of Host: {:?}", host));
for device in found_devices {
let device_name = device.name().expect("cannot get output name");
if device_name != default_device_name {
println!(" {}", device_name);
println!(" {}", device_name);
list_formats(&device);
println!(" {}", device_name);
list_formats(&device);
}
}
}
}
Expand All @@ -71,40 +75,61 @@ fn match_device(device: Option<String>) -> rodio::Device {
list_outputs();
exit(0)
}
for d in cpal::default_host()
.output_devices()
.expect("cannot get list of output devices")
{
if d.name().expect("cannot get output name") == device_name {
return d;
for host in cpal::available_hosts() {
let found_devices = cpal::host_from_id(host)
.expect(&format!("Host {:?} not found", host))
.output_devices().expect(&format!("Cannot get list of output devices of Host: {:?}", host));
for d in found_devices {
if d.name().expect("cannot get output name") == device_name {
return d;
}
}
}
println!("No output sink matching '{}' found.", device_name);
exit(0)
}
},
None => return get_default_device(),
}
}

fn get_host_id(device: &Option<String>) -> HostId {
match device {
Some(device_name) => {
if *device_name == "?".to_string() {
list_outputs();
exit(0)
}
for host in cpal::available_hosts() {
let found_devices = cpal::host_from_id(host)
.expect(&format!("Host {:?} not found", host))
.output_devices().expect(&format!("Cannot get list of output devices of Host: {:?}", host));
for d in found_devices {
if d.name().expect("cannot get output name") == *device_name {
return host;
}
}
}
println!("No output sink matching '{}' found.", device_name);
exit(0)
},
None => return cpal::default_host().id(),
}
}

impl Open for RodioSink {
fn open(device: Option<String>) -> RodioSink {
debug!(
"Using rodio sink with cpal host: {:?}",
cpal::default_host().id()
);


debug!("Using rodio sink with cpal host: {:?}", get_host_id(&device));

let rodio_device = match_device(device);
debug!("Using cpal device");
let stream = rodio::OutputStream::try_from_device(&rodio_device)
.expect("Couldn't open output stream.");
let stream = rodio::OutputStream::try_from_device(&rodio_device).expect("Couldn't open output stream.");
debug!("Using rodio stream");
let sink = rodio::Sink::try_new(&stream.1).expect("Couldn't create output sink.");
debug!("Using rodio sink");

RodioSink {
rodio_sink: sink,
stream: stream.0,
}
RodioSink { rodio_sink: sink, stream: stream.0 }
}
}

Expand Down

1 comment on commit 659ea26

@Lcchy
Copy link
Owner Author

@Lcchy Lcchy commented on 659ea26 Dec 13, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This makes rodio check for alsa and jack every time as it cycles through all possible hosts, looking for devices and hence giving at least one error message as jack and alsa are exclusive. Usage is not affected by this.
A maybe better solution is to use jack only in a separate backend. See branch rodio_jack for this

Please sign in to comment.