mirror of
https://github.com/librespot-org/librespot.git
synced 2024-12-18 17:11:53 +00:00
commit
2fa69cdc6e
3 changed files with 878 additions and 121 deletions
891
Cargo.lock
generated
891
Cargo.lock
generated
File diff suppressed because it is too large
Load diff
|
@ -28,8 +28,8 @@ portaudio-rs = { version = "0.3", optional = true }
|
||||||
libpulse-sys = { version = "0.0.0", optional = true }
|
libpulse-sys = { version = "0.0.0", optional = true }
|
||||||
jack = { version = "0.5", optional = true }
|
jack = { version = "0.5", optional = true }
|
||||||
libc = { version = "0.2", optional = true }
|
libc = { version = "0.2", optional = true }
|
||||||
rodio = { version = "0.9", optional = true, default-features = false }
|
rodio = { version = "0.13", optional = true, default-features = false }
|
||||||
cpal = { version = "0.8", optional = true }
|
cpal = { version = "0.13", optional = true }
|
||||||
sdl2 = { version = "0.32", optional = true }
|
sdl2 = { version = "0.32", optional = true }
|
||||||
gstreamer = { version = "0.15", optional = true }
|
gstreamer = { version = "0.15", optional = true }
|
||||||
gstreamer-app = { version = "0.15", optional = true }
|
gstreamer-app = { version = "0.15", optional = true }
|
||||||
|
|
|
@ -1,88 +1,110 @@
|
||||||
use super::{Open, Sink};
|
use super::{Open, Sink};
|
||||||
extern crate cpal;
|
extern crate cpal;
|
||||||
extern crate rodio;
|
extern crate rodio;
|
||||||
|
use cpal::traits::{DeviceTrait, HostTrait};
|
||||||
use std::process::exit;
|
use std::process::exit;
|
||||||
use std::{io, thread, time};
|
use std::{io, thread, time};
|
||||||
|
|
||||||
pub struct RodioSink {
|
pub struct RodioSink {
|
||||||
rodio_sink: rodio::Sink,
|
rodio_sink: rodio::Sink,
|
||||||
|
// We have to keep hold of this object, or the Sink can't play...
|
||||||
|
#[allow(dead_code)]
|
||||||
|
stream: rodio::OutputStream,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn list_formats(ref device: &rodio::Device) {
|
fn list_formats(ref device: &rodio::Device) {
|
||||||
let default_fmt = match device.default_output_format() {
|
let default_fmt = match device.default_output_config() {
|
||||||
Ok(fmt) => cpal::SupportedFormat::from(fmt),
|
Ok(fmt) => cpal::SupportedStreamConfig::from(fmt),
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
warn!("Error getting default rodio::Sink format: {:?}", e);
|
warn!("Error getting default rodio::Sink config: {}", e);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
debug!(" Default config:");
|
||||||
|
debug!(" {:?}", default_fmt);
|
||||||
|
|
||||||
let mut output_formats = match device.supported_output_formats() {
|
let mut output_configs = match device.supported_output_configs() {
|
||||||
Ok(f) => f.peekable(),
|
Ok(f) => f.peekable(),
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
warn!("Error getting supported rodio::Sink formats: {:?}", e);
|
warn!("Error getting supported rodio::Sink configs: {}", e);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if output_formats.peek().is_some() {
|
if output_configs.peek().is_some() {
|
||||||
debug!(" Available formats:");
|
debug!(" Available configs:");
|
||||||
for format in output_formats {
|
for format in output_configs {
|
||||||
let s = format!(
|
debug!(" {:?}", format);
|
||||||
"{}ch, {:?}, min {:?}, max {:?}",
|
|
||||||
format.channels, format.data_type, format.min_sample_rate, format.max_sample_rate
|
|
||||||
);
|
|
||||||
if format == default_fmt {
|
|
||||||
debug!(" (default) {}", s);
|
|
||||||
} else {
|
|
||||||
debug!(" {:?}", format);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn list_outputs() {
|
fn list_outputs() {
|
||||||
let default_device = rodio::default_output_device().unwrap();
|
let default_device = get_default_device();
|
||||||
println!("Default Audio Device:\n {}", default_device.name());
|
let default_device_name = default_device.name().expect("cannot get output name");
|
||||||
|
println!("Default Audio Device:\n {}", default_device_name);
|
||||||
list_formats(&default_device);
|
list_formats(&default_device);
|
||||||
|
|
||||||
println!("Other Available Audio Devices:");
|
println!("Other Available Audio Devices:");
|
||||||
for device in rodio::output_devices() {
|
for device in cpal::default_host()
|
||||||
if device.name() != default_device.name() {
|
.output_devices()
|
||||||
println!(" {}", device.name());
|
.expect("cannot get list of output devices")
|
||||||
|
{
|
||||||
|
let device_name = device.name().expect("cannot get output name");
|
||||||
|
if device_name != default_device_name {
|
||||||
|
println!(" {}", device_name);
|
||||||
list_formats(&device);
|
list_formats(&device);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Open for RodioSink {
|
fn get_default_device() -> rodio::Device {
|
||||||
fn open(device: Option<String>) -> RodioSink {
|
cpal::default_host()
|
||||||
debug!("Using rodio sink");
|
.default_output_device()
|
||||||
|
.expect("no default output device available")
|
||||||
let mut rodio_device = rodio::default_output_device().expect("no output device available");
|
}
|
||||||
if device.is_some() {
|
|
||||||
let device_name = device.unwrap();
|
|
||||||
|
|
||||||
|
fn match_device(device: Option<String>) -> rodio::Device {
|
||||||
|
match device {
|
||||||
|
Some(device_name) => {
|
||||||
if device_name == "?".to_string() {
|
if device_name == "?".to_string() {
|
||||||
list_outputs();
|
list_outputs();
|
||||||
exit(0)
|
exit(0)
|
||||||
}
|
}
|
||||||
let mut found = false;
|
for d in cpal::default_host()
|
||||||
for d in rodio::output_devices() {
|
.output_devices()
|
||||||
if d.name() == device_name {
|
.expect("cannot get list of output devices")
|
||||||
rodio_device = d;
|
{
|
||||||
found = true;
|
if d.name().expect("cannot get output name") == device_name {
|
||||||
break;
|
return d;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !found {
|
println!("No output sink matching '{}' found.", device_name);
|
||||||
println!("No output sink matching '{}' found.", device_name);
|
exit(0)
|
||||||
exit(0)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
let sink = rodio::Sink::new(&rodio_device);
|
None => return get_default_device(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
RodioSink { rodio_sink: sink }
|
impl Open for RodioSink {
|
||||||
|
fn open(device: Option<String>) -> RodioSink {
|
||||||
|
debug!(
|
||||||
|
"Using rodio sink with cpal host: {:?}",
|
||||||
|
cpal::default_host().id()
|
||||||
|
);
|
||||||
|
|
||||||
|
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.");
|
||||||
|
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,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue