mirror of
https://github.com/librespot-org/librespot.git
synced 2025-10-04 10:19:27 +02:00
ogg passthrough
rename
This commit is contained in:
parent
f483075b2c
commit
34bc286d9b
20 changed files with 404 additions and 98 deletions
|
@ -1,4 +1,5 @@
|
|||
use super::{Open, Sink};
|
||||
use crate::audio::AudioPacket;
|
||||
use alsa::device_name::HintIter;
|
||||
use alsa::pcm::{Access, Format, Frames, HwParams, PCM};
|
||||
use alsa::{Direction, Error, ValueOr};
|
||||
|
@ -124,8 +125,9 @@ impl Sink for AlsaSink {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn write(&mut self, data: &[i16]) -> io::Result<()> {
|
||||
fn write(&mut self, packet: &AudioPacket) -> io::Result<()> {
|
||||
let mut processed_data = 0;
|
||||
let data = packet.samples();
|
||||
while processed_data < data.len() {
|
||||
let data_to_buffer = min(
|
||||
self.buffer.capacity() - self.buffer.len(),
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
use super::{Open, Sink};
|
||||
use crate::audio::AudioPacket;
|
||||
use gst::prelude::*;
|
||||
use gst::*;
|
||||
use std::sync::mpsc::{sync_channel, SyncSender};
|
||||
|
@ -104,9 +105,9 @@ impl Sink for GstreamerSink {
|
|||
fn stop(&mut self) -> io::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
fn write(&mut self, data: &[i16]) -> io::Result<()> {
|
||||
fn write(&mut self, packet: &AudioPacket) -> io::Result<()> {
|
||||
// Copy expensively (in to_vec()) to avoid thread synchronization
|
||||
let deighta: &[u8] = data.as_bytes();
|
||||
let deighta: &[u8] = packet.samples().as_bytes();
|
||||
self.tx
|
||||
.send(deighta.to_vec())
|
||||
.expect("tx send failed in write function");
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
use super::{Open, Sink};
|
||||
use crate::audio::AudioPacket;
|
||||
use jack::{
|
||||
AsyncClient, AudioOut, Client, ClientOptions, Control, Port, ProcessHandler, ProcessScope,
|
||||
};
|
||||
|
@ -73,8 +74,8 @@ impl Sink for JackSink {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn write(&mut self, data: &[i16]) -> io::Result<()> {
|
||||
for s in data.iter() {
|
||||
fn write(&mut self, packet: &AudioPacket) -> io::Result<()> {
|
||||
for s in packet.samples().iter() {
|
||||
let res = self.send.send(*s);
|
||||
if res.is_err() {
|
||||
error!("jackaudio: cannot write to channel");
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
use crate::audio::AudioPacket;
|
||||
use std::io;
|
||||
|
||||
pub trait Open {
|
||||
|
@ -7,7 +8,7 @@ pub trait Open {
|
|||
pub trait Sink {
|
||||
fn start(&mut self) -> io::Result<()>;
|
||||
fn stop(&mut self) -> io::Result<()>;
|
||||
fn write(&mut self, data: &[i16]) -> io::Result<()>;
|
||||
fn write(&mut self, packet: &AudioPacket) -> io::Result<()>;
|
||||
}
|
||||
|
||||
fn mk_sink<S: Sink + Open + 'static>(device: Option<String>) -> Box<dyn Sink> {
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
use super::{Open, Sink};
|
||||
use crate::audio::AudioPacket;
|
||||
use std::fs::OpenOptions;
|
||||
use std::io::{self, Write};
|
||||
use std::mem;
|
||||
|
@ -26,12 +27,15 @@ impl Sink for StdoutSink {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn write(&mut self, data: &[i16]) -> io::Result<()> {
|
||||
let data: &[u8] = unsafe {
|
||||
slice::from_raw_parts(
|
||||
data.as_ptr() as *const u8,
|
||||
data.len() * mem::size_of::<i16>(),
|
||||
)
|
||||
fn write(&mut self, packet: &AudioPacket) -> io::Result<()> {
|
||||
let data: &[u8] = match packet {
|
||||
AudioPacket::Samples(data) => unsafe {
|
||||
slice::from_raw_parts(
|
||||
data.as_ptr() as *const u8,
|
||||
data.len() * mem::size_of::<i16>(),
|
||||
)
|
||||
},
|
||||
AudioPacket::OggData(data) => data,
|
||||
};
|
||||
|
||||
self.0.write_all(data)?;
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
use super::{Open, Sink};
|
||||
use crate::audio::AudioPacket;
|
||||
use portaudio_rs;
|
||||
use portaudio_rs::device::{get_default_output_index, DeviceIndex, DeviceInfo};
|
||||
use portaudio_rs::stream::*;
|
||||
|
@ -95,8 +96,8 @@ impl<'a> Sink for PortAudioSink<'a> {
|
|||
self.0 = None;
|
||||
Ok(())
|
||||
}
|
||||
fn write(&mut self, data: &[i16]) -> io::Result<()> {
|
||||
match self.0.as_mut().unwrap().write(data) {
|
||||
fn write(&mut self, packet: &AudioPacket) -> io::Result<()> {
|
||||
match self.0.as_mut().unwrap().write(packet.samples()) {
|
||||
Ok(_) => (),
|
||||
Err(portaudio_rs::PaError::OutputUnderflowed) => error!("PortAudio write underflow"),
|
||||
Err(e) => panic!("PA Error {}", e),
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
use super::{Open, Sink};
|
||||
use crate::audio::AudioPacket;
|
||||
use libpulse_binding::{self as pulse, stream::Direction};
|
||||
use libpulse_simple_binding::Simple;
|
||||
use std::io;
|
||||
|
@ -65,13 +66,17 @@ impl Sink for PulseAudioSink {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn write(&mut self, data: &[i16]) -> io::Result<()> {
|
||||
fn write(&mut self, packet: &AudioPacket) -> io::Result<()> {
|
||||
if let Some(s) = &self.s {
|
||||
// SAFETY: An i16 consists of two bytes, so that the given slice can be interpreted
|
||||
// as a byte array of double length. Each byte pointer is validly aligned, and so
|
||||
// is the newly created slice.
|
||||
let d: &[u8] =
|
||||
unsafe { std::slice::from_raw_parts(data.as_ptr() as *const u8, data.len() * 2) };
|
||||
let d: &[u8] = unsafe {
|
||||
std::slice::from_raw_parts(
|
||||
packet.samples().as_ptr() as *const u8,
|
||||
packet.samples().len() * 2,
|
||||
)
|
||||
};
|
||||
|
||||
match s.write(d) {
|
||||
Ok(_) => Ok(()),
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
use super::{Open, Sink};
|
||||
extern crate cpal;
|
||||
extern crate rodio;
|
||||
use crate::audio::AudioPacket;
|
||||
use cpal::traits::{DeviceTrait, HostTrait};
|
||||
use std::process::exit;
|
||||
use std::{io, thread, time};
|
||||
|
@ -164,8 +165,8 @@ impl Sink for RodioSink {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn write(&mut self, data: &[i16]) -> io::Result<()> {
|
||||
let source = rodio::buffer::SamplesBuffer::new(2, 44100, data);
|
||||
fn write(&mut self, packet: &AudioPacket) -> io::Result<()> {
|
||||
let source = rodio::buffer::SamplesBuffer::new(2, 44100, packet.samples());
|
||||
self.rodio_sink.append(source);
|
||||
|
||||
// Chunk sizes seem to be about 256 to 3000 ish items long.
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
use super::{Open, Sink};
|
||||
use crate::audio::AudioPacket;
|
||||
use sdl2::audio::{AudioQueue, AudioSpecDesired};
|
||||
use std::{io, thread, time};
|
||||
|
||||
|
@ -45,12 +46,12 @@ impl Sink for SdlSink {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn write(&mut self, data: &[i16]) -> io::Result<()> {
|
||||
fn write(&mut self, packet: &AudioPacket) -> io::Result<()> {
|
||||
while self.queue.size() > (2 * 2 * 44_100) {
|
||||
// sleep and wait for sdl thread to drain the queue a bit
|
||||
thread::sleep(time::Duration::from_millis(10));
|
||||
}
|
||||
self.queue.queue(data);
|
||||
self.queue.queue(packet.samples());
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
use super::{Open, Sink};
|
||||
use crate::audio::AudioPacket;
|
||||
use shell_words::split;
|
||||
use std::io::{self, Write};
|
||||
use std::mem;
|
||||
|
@ -43,11 +44,11 @@ impl Sink for SubprocessSink {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn write(&mut self, data: &[i16]) -> io::Result<()> {
|
||||
fn write(&mut self, packet: &AudioPacket) -> io::Result<()> {
|
||||
let data: &[u8] = unsafe {
|
||||
slice::from_raw_parts(
|
||||
data.as_ptr() as *const u8,
|
||||
data.len() * mem::size_of::<i16>(),
|
||||
packet.samples().as_ptr() as *const u8,
|
||||
packet.samples().len() * mem::size_of::<i16>(),
|
||||
)
|
||||
};
|
||||
if let Some(child) = &mut self.child {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue