why cant rodio find my default output device? - rust

I'm creating a Sink and an OutputStreamHandle in rodio like this, just like the example in the docs does it.
let (_stream, stream_handle) = rodio::OutputStream::try_default().unwrap();
let sink = rodio::Sink::try_new(&stream_handle).unwrap();
When I go to actually play anything I run this
let source = rodio::Decoder::new(std::fs::File::open(audio.path).unwrap()).unwrap();
println!("{:?}", self.stream_handle.play_raw(source.convert_samples()));
it prints Err(NoDevice) to the console, even though I have set my default device to my headphones in the windows settings. I even tried it on my Linux laptop and it still can't find a default output device.
Using a Sink also doesn't work.
let source = rodio::Decoder::new(std::fs::File::open(audio.path).unwrap()).unwrap();
self.sink.append(source);

Related

Why can I not recieve serial data using Rust?

I've been trying to read serial data from a Feather M0, but for some reason I can't read the data into a buffer. This device is for sure outputting serial data, and both PlatformIO and the Arduino IDE show serial data in their respective serial monitors. However, it will timeout when I'm reading it in Rust, every single time, no matter what timeout value I have it set to. Here is my code:
// First, find the serial port
let port_info = find_receiver();
// If we didn't find a port, then we can't continue
if port_info.is_none() {
panic!("Could not find a serial port");
}
let mut port = serialport::new(port_info.unwrap().port_name, 9600)
.timeout(Duration::from_millis(1000))
.open()
.expect("Could not open serial port");
let mut serial_buf: Vec<u8> = vec![0; 8];
loop {
let n = port.read_exact(serial_buf.as_mut_slice()).unwrap();
println!("Buffer is {:?}", serial_buf);
}
The find_reciever() function simply scans the open ports and returns the one that I want to connect to. I'm on Windows, so in this case it's usually COM9 or COM12. I would like this to be a cross-platform application, so I'm not using the open_native() function that serialport provides.
I've tried varrying the size of the buffer from 1 byte to 1000, I've trying different versions of read into the port, I've tried skipping over timeout errors, and I've tried directly outputting the read bytes to io::Stdout. Any ideas on what to do?
Apparently, the serialport crate that I was using requires you to set the command
port.write_data_terminal_ready(true);
in order for it to start reading data. On Linux this works perfectly fine without it. Rip 4 hours trying to change what IO reader I was using.

Playing audio from url in Rust

I have used rodio crate for playing audio from local file, by going through docs, but not able to figure out how to play audio using url.
Here is a simple example using blocking reqwest. This downloads the entire audio file into memory before it starts playing.
use std::io::{Write, Read, Cursor};
use rodio::Source;
fn main() {
// Remember to add the "blocking" feature in the Cargo.toml for reqwest
let resp = reqwest::blocking::get("http://websrvr90va.audiovideoweb.com/va90web25003/companions/Foundations%20of%20Rock/13.01.mp3")
.unwrap();
let mut cursor = Cursor::new(resp.bytes().unwrap()); // Adds Read and Seek to the bytes via Cursor
let source = rodio::Decoder::new(cursor).unwrap(); // Decoder requires it's source to impl both Read and Seek
let device = rodio::default_output_device().unwrap();
rodio::play_raw(&device, source.convert_samples()); // Plays on a different thread
loop {} // Don't exit immediately, so we can hear the audio
}
If you want to implement actual streaming, where parts of the audio file is downloaded then played, and more gets fetched later as it is needed, it gets quite a bit more complicated. See this entry about partial downloads in the Rust Cookbook: https://rust-lang-nursery.github.io/rust-cookbook/web/clients/download.html#make-a-partial-download-with-http-range-headers
I believe it can also be done easier with async reqwest, but I am still experimenting with that myself.

Micropython and Bluetooth on ESP32

I know the support for bluetooth is still under development but it seems to cover everything I need at this point so I decided to give it a try.
I just want to simulate reading from a source of data (a EKG machine) so I came up with this code:
from ubluetooth import BLE
from ubluetooth import FLAG_READ, FLAG_NOTIFY, FLAG_WRITE
import time
ekg_data = [-305,-431,-131,440 ,1158,1424,1445,1623,1500,1018,142 ,-384,-324,-414,-77 ,334 ,-372,-154,366 ,7613,1461,1403,6133,-179,-381,-224,-135,-168,-208,-187,-181,-180,-160,-160,-151,-150,-151,-138,-141,-128,-118,-106,-798,-677,-430,-253,-122,98 ,133 ,281 ,354 ,390 ,519 ,475 ,558 ,565 ,533 ,593 ,458 ,377 ,107 ,-335,-719,-116,-129,-132,-131,-119,-122,-111,-106,-105,-935,-971,-877,-841,-841,-725,-757,-660,-641,-660,-554,-592,-496,-473,-486,-387,-431,-350,-364,-347,-208,-365,-362]
bt = BLE()
bt.active(True)
print('----')
print(bt.config('mac'))
print(bt.config('gap_name'))
HR_UUID = bluetooth.UUID(0x180D)
HR_CHAR = (bluetooth.UUID(0x2A37), bluetooth.FLAG_READ | bluetooth.FLAG_NOTIFY,)
HR_SERVICE = (HR_UUID, (HR_CHAR,),)
SERVICES = (HR_SERVICE,)
((ekg,),) = bt.gatts_register_services(SERVICES)
# bt.gap_advertise(100, 'MicroPython EKG')
count = 0
while True:
if count >= len(ekg_data):
count = 0
bt.gatts_write(ekg, ekg_data[count].to_bytes(2, 'big'))
print(ekg_data[count])
time.sleep_ms(1000)
count += 1
Now the code compiles and runs (I can see the output on the console) but I cannot find the device in my bluetooth app (I am using the nordic app)
Does anyone with more knowledge on that area can tell me if I am overlooking something? I tried to take the advertising off and on because I thought I might be overriding something with it but that didn't help too...
I think your code is missing multiple things.
First, you are not setting (irq) which is (Event Handling) for Micropython(As you can see from the docs or in their Github codes.
Also, I can't see you setting the buffer or any stuff like that, please revise the examples for what you asking here. Good job btw.

How can I know when a Rodio source or sink is done?

I'm trying to play some sounds with rodio.
I am creating a Source and putting it into a Sink, but how can I know when one or the other has stopped playing? For example, I want to move to the next song after the first.
let device = rodio::default_output_device().unwrap();
let sink = Sink::new(&device);
let file = File::open(path).unwrap();
let source = rodio::Decoder::new(BufReader::new(file)).unwrap();
sink.append(source);
I have found nothing in the rodio docs about a callback or something similar. There is a Done struct, but it's not clear to me how to use it, or even if is the thing I'm looking for.
I think you're looking for the Sink::done which returns true if there are no more samples within the sink to play.

Auto focus camera without preview

I am running Win10 IoT on a pi 2. I need to be able to take pictures that are focused but cannot get the focus working. The application is a background app so I don't have a way of previewing the camera on a display. Is there any way of doing this? Currently I have
await _mediaCapture.StartPreviewAsync();
_mediaCapture.VideoDeviceController.FocusControl.Configure(new FocusSettings
{
Mode = FocusMode.Continuous,
WaitForFocus = true
});
await _mediaCapture.VideoDeviceController.FocusControl.FocusAsync();
await _mediaCapture.CapturePhotoToStreamAsync(ImageEncodingProperties.CreateJpeg(), stream);
await _mediaCapture.StopPreviewAsync();
but I am getting the error
WinRT information: Preview sink not set
when I try to focus. All of the examples I've seen online show that the preview is output to a control and I assume it wires a sink up automagically. Is there a way to do this manually through code? Possibly without the preview?
I wonder if the code may work even without FocusControl.
I propose you follow Customer Media Sink implementation example and use of StartPreviewToCustomSinkIdAsync method described at http://www.codeproject.com/Tips/772038/Custom-Media-Sink-for-Use-with-Media-Foundation-To
I didn't find a way to do this. I ended up converting the background app to a UI app with a Page containing a CaptureElement control in order to preview and focus.
Instead of adding a UI, just create a CaptureElement and set the source to the _mediaCapture before calling await _mediaCapture.StartPreviewAsync();
Something like:
_captureElement = new CaptureElement { Stretch = Stretch.Uniform };
_mediaCapture = new MediaCapture();
await _mediaCapture.InitializeAsync(...);
_captureElement.Source = _mediaCapture;
await _mediaCapture.StartPreviewAsync();

Resources