rodio.rs 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. use super::{Open, Sink};
  2. extern crate cpal;
  3. extern crate rodio;
  4. use std::process::exit;
  5. use std::{io, thread, time};
  6. pub struct RodioSink {
  7. rodio_sink: rodio::Sink,
  8. }
  9. fn list_formats(ref device: &rodio::Device) {
  10. let default_fmt = match device.default_output_format() {
  11. Ok(fmt) => cpal::SupportedFormat::from(fmt),
  12. Err(e) => {
  13. warn!("Error getting default rodio::Sink format: {:?}", e);
  14. return;
  15. }
  16. };
  17. let mut output_formats = match device.supported_output_formats() {
  18. Ok(f) => f.peekable(),
  19. Err(e) => {
  20. warn!("Error getting supported rodio::Sink formats: {:?}", e);
  21. return;
  22. }
  23. };
  24. if output_formats.peek().is_some() {
  25. debug!(" Available formats:");
  26. for format in output_formats {
  27. let s = format!(
  28. "{}ch, {:?}, min {:?}, max {:?}",
  29. format.channels, format.data_type, format.min_sample_rate, format.max_sample_rate
  30. );
  31. if format == default_fmt {
  32. debug!(" (default) {}", s);
  33. } else {
  34. debug!(" {:?}", format);
  35. }
  36. }
  37. }
  38. }
  39. fn list_outputs() {
  40. let default_device = rodio::default_output_device().unwrap();
  41. println!("Default Audio Device:\n {}", default_device.name());
  42. list_formats(&default_device);
  43. println!("Other Available Audio Devices:");
  44. for device in rodio::output_devices() {
  45. if device.name() != default_device.name() {
  46. println!(" {}", device.name());
  47. list_formats(&device);
  48. }
  49. }
  50. }
  51. impl Open for RodioSink {
  52. fn open(device: Option<String>) -> RodioSink {
  53. debug!("Using rodio sink");
  54. let mut rodio_device = rodio::default_output_device().expect("no output device available");
  55. if device.is_some() {
  56. let device_name = device.unwrap();
  57. if device_name == "?".to_string() {
  58. list_outputs();
  59. exit(0)
  60. }
  61. let mut found = false;
  62. for d in rodio::output_devices() {
  63. if d.name() == device_name {
  64. rodio_device = d;
  65. found = true;
  66. break;
  67. }
  68. }
  69. if !found {
  70. println!("No output sink matching '{}' found.", device_name);
  71. exit(0)
  72. }
  73. }
  74. let sink = rodio::Sink::new(&rodio_device);
  75. RodioSink { rodio_sink: sink }
  76. }
  77. }
  78. impl Sink for RodioSink {
  79. fn start(&mut self) -> io::Result<()> {
  80. // More similar to an "unpause" than "play". Doesn't undo "stop".
  81. // self.rodio_sink.play();
  82. Ok(())
  83. }
  84. fn stop(&mut self) -> io::Result<()> {
  85. // This will immediately stop playback, but the sink is then unusable.
  86. // We just have to let the current buffer play till the end.
  87. // self.rodio_sink.stop();
  88. Ok(())
  89. }
  90. fn write(&mut self, data: &[i16]) -> io::Result<()> {
  91. let source = rodio::buffer::SamplesBuffer::new(2, 44100, data);
  92. self.rodio_sink.append(source);
  93. // Chunk sizes seem to be about 256 to 3000 ish items long.
  94. // Assuming they're on average 1628 then a half second buffer is:
  95. // 44100 elements --> about 27 chunks
  96. while self.rodio_sink.len() > 26 {
  97. // sleep and wait for rodio to drain a bit
  98. thread::sleep(time::Duration::from_millis(10));
  99. }
  100. Ok(())
  101. }
  102. }