rodio.rs 3.4 KB

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