1use crate::gamepad::GamepadManager;
2use crate::*;
3use alloc::boxed::Box;
4use core::cell::Cell;
5use core::fmt::Display;
6use core::marker::PhantomData;
7use core::net::{IpAddr, Ipv4Addr, SocketAddr};
8use std::io::{Read, Write};
9use std::net::{SocketAddrV4, TcpListener, TcpStream, UdpSocket};
10use std::path::PathBuf;
11use std::sync::mpsc;
12
13const UDP_PORT_MIN: u16 = 3110;
14const UDP_PORT_MAX: u16 = 3117;
15const TCP_PORT_MIN: u16 = 3210;
16const TCP_PORT_MAX: u16 = 3217;
17const AUDIO_BUF_SIZE: usize = SAMPLE_RATE as usize / 6;
18
19static NAMES: &[&str] = &[
20 "j0vial-dharm4",
21 "angry-6r4d13y",
22 "nic3-5ugar",
23 "quirky-5co06ie",
24 "r31ax3d-s0phie",
25 "sh4rp-7oni",
26 "boring-5ky",
27 "m4gica1-5i3nn4",
28 "b0ring-che57er",
29 "shy-a5tr0",
30];
31
32#[derive(Clone)]
33pub struct DeviceConfig {
34 pub root: PathBuf,
36
37 pub tcp_ip: IpAddr,
39
40 pub udp_ip: IpAddr,
42
43 pub peers: Vec<IpAddr>,
45
46 pub wav: Option<PathBuf>,
48
49 pub mute: bool,
51}
52
53impl Default for DeviceConfig {
54 fn default() -> Self {
55 let localhost = IpAddr::V4(Ipv4Addr::LOCALHOST);
56 Self {
57 root: PathBuf::new(),
58 tcp_ip: localhost,
59 udp_ip: localhost,
60 peers: vec![localhost],
61 wav: None,
62 mute: false,
63 }
64 }
65}
66
67pub struct DeviceImpl<'a> {
68 config: DeviceConfig,
69 start: std::time::Instant,
71 gamepad: GamepadManager,
73 audio: Option<AudioWriter>,
75 wifi_status: firefly_types::wifi::Status,
76 network: NetworkImpl<'a>,
77 serial: SerialImpl,
78 tcp_conn: Option<TcpStream>,
79}
80
81impl<'a> DeviceImpl<'a> {
82 pub fn new(config: DeviceConfig) -> Self {
83 let mut audio = None;
84 #[cfg(not(target_os = "android"))]
85 if !config.mute {
86 audio = start_audio(&config);
87 }
88 Self {
89 start: std::time::Instant::now(),
90 gamepad: GamepadManager::new(),
91 audio,
92 config,
93 wifi_status: firefly_types::wifi::Status::Stopped,
94 network: NetworkImpl::new(),
95 serial: SerialImpl::new(),
96 tcp_conn: None,
97 }
98 }
99
100 pub fn update_input(&mut self, input: InputState) {
102 self.gamepad.update_input(input)
103 }
104
105 pub fn alloc_psram(&self, size: usize) -> Vec<u8> {
106 Vec::with_capacity(size)
107 }
108}
109
110impl<'a> Device for DeviceImpl<'a> {
111 type Dir = DirImpl;
112
113 fn now(&self) -> Instant {
114 let now = std::time::Instant::now();
115 let dur = now.duration_since(self.start);
116 Instant {
117 us: dur.as_micros() as u32,
118 }
119 }
120
121 fn delay(&self, d: Duration) {
122 let dur = core::time::Duration::from_micros(d.us as u64);
123 std::thread::sleep(dur);
124 }
125
126 fn read_input(&mut self) -> Option<InputState> {
127 self.gamepad.read_input()
128 }
129
130 fn get_name(&mut self) -> Option<&'static str> {
131 let addr = self.network.local_addr?;
132 let IpAddr::V4(ip) = addr.ip() else {
133 return None;
134 };
135 let port = addr.port();
136 if port == UDP_PORT_MIN {
137 return None;
138 }
139 let hash = (ip.to_bits() + u32::from(port)) % 10;
140 let name = NAMES[hash as usize];
141 Some(name)
142 }
143
144 fn log_debug<D: Display>(&mut self, src: &str, msg: D) {
145 println!("DEBUG({src}): {msg}");
146 }
147
148 fn log_error<D: Display>(&mut self, src: &str, msg: D) {
149 eprintln!("ERROR({src}): {msg}");
150 }
151
152 fn random(&mut self) -> u32 {
153 rand::random()
154 }
155
156 fn open_dir(&mut self, path: &[&str]) -> Result<Self::Dir, FSError> {
157 let path: PathBuf = path.iter().collect();
158 let path = self.config.root.join(path);
159 if !path.exists() {
160 return Err(FSError::NotFound);
161 }
162 if !path.is_dir() {
163 return Err(FSError::OpenedFileAsDir);
164 }
165 Ok(DirImpl { path })
166 }
167
168 fn has_headphones(&mut self) -> bool {
169 false
170 }
171
172 fn get_audio_buffer(&mut self) -> &mut [i16] {
173 match &mut self.audio {
174 Some(audio) => audio.get_write_buf(),
175 None => &mut [][..],
176 }
177 }
178
179 #[cfg(target_os = "android")]
180 fn get_battery_status(&mut self) -> Option<BatteryStatus> {
181 None
182 }
183
184 #[cfg(not(target_os = "android"))]
185 fn get_battery_status(&mut self) -> Option<BatteryStatus> {
186 Some(BatteryStatus {
187 voltage: 40_000,
188 connected: false,
189 full: false,
190 })
191 }
192
193 fn write_main_flash(&mut self, _offset: u32, _data: &[u8]) -> Result<(), &'static str> {
194 Ok(())
195 }
196
197 fn write_io_flash(&mut self, _offset: u32, _data: &[u8]) -> NetworkResult<()> {
198 Ok(())
199 }
200
201 fn switch_main_partition(&mut self, _part: u8) -> Result<(), &'static str> {
202 Ok(())
203 }
204
205 fn switch_io_partition(&mut self, _part: u8) -> NetworkResult<()> {
206 Ok(())
207 }
208}
209
210pub struct DirImpl {
211 path: PathBuf,
212}
213
214impl Dir for DirImpl {
215 type Read = File;
216 type Write = File;
217
218 fn open_file(&mut self, name: &str) -> Result<Self::Read, FSError> {
219 let path = self.path.join(name);
220 let file = std::fs::File::open(path)?;
221 Ok(File { file })
222 }
223
224 fn create_file(&mut self, name: &str) -> Result<Self::Write, FSError> {
225 let path = self.path.join(name);
226 if let Some(parent) = path.parent() {
227 _ = std::fs::create_dir_all(parent);
228 }
229 let file = std::fs::File::create(path)?;
230 Ok(File { file })
231 }
232
233 fn append_file(&mut self, name: &str) -> Result<Self::Write, FSError> {
234 let path = self.path.join(name);
235 let mut opts = std::fs::OpenOptions::new();
236 let file = opts.append(true).open(path)?;
237 Ok(File { file })
238 }
239
240 fn get_file_size(&mut self, name: &str) -> Result<u32, FSError> {
241 let path = self.path.join(name);
242 let meta = std::fs::metadata(path)?;
243 Ok(meta.len() as u32)
244 }
245
246 fn remove_file(&mut self, name: &str) -> Result<(), FSError> {
247 let path = self.path.join(name);
248 let res = std::fs::remove_file(path);
249 match res {
250 Ok(_) => Ok(()),
251 Err(err) => match err.kind() {
252 std::io::ErrorKind::NotFound => Ok(()),
253 _ => Err(err.into()),
254 },
255 }
256 }
257
258 fn create_dir(&mut self, name: &str) -> Result<(), FSError> {
259 let path = self.path.join(name);
260 std::fs::create_dir(path)?;
261 Ok(())
262 }
263
264 fn remove_dir(self) -> Result<(), FSError> {
265 let res = std::fs::remove_dir_all(&self.path);
266 match res {
267 Ok(_) => Ok(()),
268 Err(err) => match err.kind() {
269 std::io::ErrorKind::NotFound => Ok(()),
270 _ => Err(err.into()),
271 },
272 }
273 }
274
275 fn iter_dir<F>(&mut self, mut f: F) -> Result<(), FSError>
276 where
277 F: FnMut(EntryKind, &[u8]),
278 {
279 let entries = std::fs::read_dir(&self.path)?;
280 for entry in entries {
281 let entry = entry?;
282 let path = entry.path();
283 let kind = if path.is_dir() {
284 EntryKind::Dir
285 } else if path.is_file() {
286 EntryKind::File
287 } else {
288 continue;
289 };
290 let fname = entry.file_name();
291 let fname = fname.as_encoded_bytes();
292 f(kind, fname);
293 }
294 Ok(())
295 }
296}
297
298pub struct File {
299 file: std::fs::File,
300}
301
302impl embedded_io::ErrorType for File {
303 type Error = std::io::Error;
304}
305
306impl embedded_io::Read for File {
307 fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
308 std::io::Read::read(&mut self.file, buf)
309 }
310}
311
312impl embedded_io::Seek for File {
313 fn seek(&mut self, pos: embedded_io::SeekFrom) -> Result<u64, Self::Error> {
314 let pos = match pos {
315 embedded_io::SeekFrom::Start(n) => std::io::SeekFrom::Start(n),
316 embedded_io::SeekFrom::End(n) => std::io::SeekFrom::End(n),
317 embedded_io::SeekFrom::Current(n) => std::io::SeekFrom::Current(n),
318 };
319 std::io::Seek::seek(&mut self.file, pos)
320 }
321}
322
323impl embedded_io::Write for File {
324 fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
325 std::io::Write::write(&mut self.file, buf)
326 }
327
328 fn flush(&mut self) -> Result<(), Self::Error> {
329 std::io::Write::flush(&mut self.file)
330 }
331}
332
333pub struct NetworkImpl<'a> {
334 worker: Cell<Option<UdpWorker>>,
335 r_in: mpsc::Receiver<NetMessage>,
336 s_out: mpsc::Sender<NetMessage>,
337 s_stop: mpsc::Sender<()>,
338 local_addr: Option<SocketAddr>,
339 _life: &'a PhantomData<()>,
340}
341
342impl<'a> NetworkImpl<'a> {
343 fn new() -> Self {
344 let (s_in, r_in) = mpsc::channel();
345 let (s_out, r_out) = mpsc::channel();
346 let (s_stop, r_stop) = mpsc::channel();
347 let worker = Cell::new(Some(UdpWorker {
348 s_in,
349 r_out,
350 r_stop,
351 }));
352 Self {
353 worker,
354 r_in,
355 s_out,
356 s_stop,
357 local_addr: None,
358 _life: &PhantomData,
359 }
360 }
361}
362
363pub type Addr = SocketAddr;
364
365impl<'a> Network for DeviceImpl<'a> {
366 type Addr = SocketAddr;
367
368 fn net_local_addr(&self) -> SocketAddr {
369 self.network.local_addr.unwrap()
370 }
371
372 fn net_start(&mut self) -> NetworkResult<()> {
373 let worker = self.network.worker.replace(None);
374 let Some(worker) = worker else {
375 return Ok(());
376 };
377 let local_addr = worker.start(self.config.udp_ip)?;
378 self.network.local_addr = Some(local_addr);
379 Ok(())
380 }
381
382 fn net_stop(&mut self) -> NetworkResult<()> {
383 _ = self.network.s_stop.send(());
384 self.network = NetworkImpl::new();
385 Ok(())
386 }
387
388 fn net_advertise(&mut self) -> NetworkResult<()> {
389 let hello = b"HELLO".to_owned();
390 let hello: Box<[u8]> = Box::new(hello);
391 for ip in &self.config.peers {
392 for port in UDP_PORT_MIN..=UDP_PORT_MAX {
393 let addr = SocketAddr::new(*ip, port);
394 let res = self.network.s_out.send((addr, hello.clone()));
395 if res.is_err() {
396 return Err(NetworkError::NetThreadDeallocated);
397 }
398 }
399 }
400 Ok(())
401 }
402
403 fn net_recv(&mut self) -> NetworkResult<Option<(Self::Addr, Box<[u8]>)>> {
404 Ok(self.network.r_in.try_recv().ok())
405 }
406
407 fn net_send(&mut self, addr: Self::Addr, data: &[u8]) -> NetworkResult<()> {
408 if data.len() >= 200 {
409 return Err(NetworkError::OutMessageTooBig);
410 };
411 let msg = data.to_vec().into_boxed_slice();
412 let res = self.network.s_out.send((addr, msg));
413 if res.is_err() {
414 return Err(NetworkError::NetThreadDeallocated);
415 }
416 Ok(())
417 }
418
419 fn net_send_status(&mut self, _: Self::Addr) -> NetworkResult<firefly_types::spi::SendStatus> {
420 Ok(firefly_types::spi::SendStatus::Empty)
421 }
422}
423
424pub struct SerialImpl {
425 worker: Cell<Option<TcpWorker>>,
426 r_in: mpsc::Receiver<SerialMessage>,
427 s_out: mpsc::Sender<SerialMessage>,
428 s_stop: mpsc::Sender<()>,
429}
430
431impl SerialImpl {
432 fn new() -> Self {
433 let (s_in, r_in) = mpsc::channel();
434 let (s_out, r_out) = mpsc::channel();
435 let (s_stop, r_stop) = mpsc::channel();
436 let worker = TcpWorker {
437 s_in,
438 r_out,
439 r_stop,
440 };
441 let worker = Cell::new(Some(worker));
442 Self {
443 worker,
444 r_in,
445 s_out,
446 s_stop,
447 }
448 }
449}
450
451impl Serial for DeviceImpl<'_> {
452 fn serial_start(&mut self) -> NetworkResult<()> {
453 let worker = self.serial.worker.replace(None);
454 let Some(worker) = worker else {
455 return Ok(());
456 };
457 worker.start(self.config.tcp_ip)?;
458 Ok(())
459 }
460
461 fn serial_stop(&mut self) -> NetworkResult<()> {
462 _ = self.serial.s_stop.send(());
463 Ok(())
464 }
465
466 fn serial_recv(&mut self) -> NetworkResult<Option<Box<[u8]>>> {
467 Ok(self.serial.r_in.try_recv().ok())
468 }
469
470 fn serial_send(&mut self, data: &[u8]) -> NetworkResult<()> {
471 if data.len() >= 200 {
472 return Err(NetworkError::OutMessageTooBig);
473 };
474 let msg = data.to_vec().into_boxed_slice();
475 let res = self.serial.s_out.send(msg);
476 if res.is_err() {
477 return Err(NetworkError::NetThreadDeallocated);
478 }
479 Ok(())
480 }
481}
482
483impl Wifi for DeviceImpl<'_> {
484 fn wifi_scan(&mut self) -> NetworkResult<[String; 6]> {
485 let points = ["Default Network", "", "", "", "", ""];
486 let points = points.map(|s| s.to_string());
487 Ok(points)
488 }
489
490 fn wifi_connect(&mut self, ssid: &str, pass: &str) -> NetworkResult<()> {
491 use firefly_types::wifi::{DisconnectReason, Status};
492 self.wifi_status = if ssid != "Default Network" {
493 Status::Disconnected(DisconnectReason::NoApFound)
494 } else if pass == "invalid" {
495 Status::Disconnected(DisconnectReason::AuthFail)
496 } else {
497 Status::Initializing
498 };
499 Ok(())
500 }
501
502 fn wifi_status(&mut self) -> NetworkResult<u8> {
503 use firefly_types::wifi::Status;
504 if self.wifi_status == Status::Initializing {
505 self.wifi_status = Status::Connected;
506 }
507 Ok(self.wifi_status.into())
508 }
509
510 fn wifi_disconnect(&mut self) -> NetworkResult<()> {
511 self.wifi_status = firefly_types::wifi::Status::Stopped;
512 Ok(())
513 }
514
515 fn tcp_connect(&mut self, ip: u32, port: u16) -> NetworkResult<()> {
516 use firefly_types::wifi::Status;
517 if self.wifi_status != Status::Connected {
518 return Err(NetworkError::Error("not connected to wifi"));
519 }
520 let ip = Ipv4Addr::new(
521 (ip >> 24) as u8,
522 (ip >> 16) as u8,
523 (ip >> 8) as u8,
524 ip as u8,
525 );
526 let addr = SocketAddrV4::new(ip, port);
527 let Ok(stream) = TcpStream::connect(addr) else {
528 return Err(NetworkError::CannotBind);
529 };
530 _ = stream.set_nonblocking(true);
531 self.tcp_conn = Some(stream);
532 Ok(())
533 }
534
535 fn tcp_status(&mut self) -> NetworkResult<u8> {
536 let Some(stream) = &mut self.tcp_conn else {
537 return Ok(1);
538 };
539 if stream.peer_addr().is_err() {
540 return Ok(1);
541 }
542 Ok(5)
543 }
544
545 fn tcp_send(&mut self, data: &[u8]) -> NetworkResult<()> {
546 let Some(stream) = &mut self.tcp_conn else {
547 return Err(NetworkError::NotInitialized);
548 };
549 let res = stream.write_all(data);
550 if let Err(err) = res {
551 let err = alloc::format!("{err}");
552 return Err(NetworkError::OwnedError(err));
553 }
554 Ok(())
555 }
556
557 fn tcp_recv(&mut self) -> NetworkResult<Box<[u8]>> {
558 let Some(stream) = &mut self.tcp_conn else {
559 return Err(NetworkError::NotInitialized);
560 };
561 let mut buf = vec![0; 80];
562 let n = match stream.read(&mut buf) {
563 Ok(n) => n,
564 Err(err) => {
565 if err.kind() == std::io::ErrorKind::WouldBlock {
566 0
567 } else {
568 return Err(NetworkError::Error("failed to read incoming TCP data"));
569 }
570 }
571 };
572 buf.truncate(n);
573 Ok(buf.into_boxed_slice())
574 }
575
576 fn tcp_close(&mut self) -> NetworkResult<()> {
577 let Some(stream) = self.tcp_conn.take() else {
578 return Ok(());
579 };
580 _ = stream.shutdown(std::net::Shutdown::Both);
581 Ok(())
582 }
583}
584
585type NetMessage = (SocketAddr, Box<[u8]>);
586type SerialMessage = Box<[u8]>;
587
588struct UdpWorker {
589 s_in: mpsc::Sender<NetMessage>,
590 r_out: mpsc::Receiver<NetMessage>,
591 r_stop: mpsc::Receiver<()>,
592}
593
594impl UdpWorker {
595 fn start(self, ip: IpAddr) -> Result<SocketAddr, NetworkError> {
596 let addrs: Vec<_> = (UDP_PORT_MIN..=UDP_PORT_MAX)
597 .map(|port| SocketAddr::new(ip, port))
598 .collect();
599 let socket = match UdpSocket::bind(&addrs[..]) {
600 Ok(socket) => socket,
601 Err(_) => return Err(NetworkError::CannotBind),
602 };
603 let timeout = std::time::Duration::from_millis(10);
604 socket.set_read_timeout(Some(timeout)).unwrap();
605 if let Ok(addr) = socket.local_addr() {
606 println!("listening on {addr}/udp");
607 } else {
608 println!("listening a UDP port");
609 }
610 let local_addr = socket.local_addr().unwrap();
611 std::thread::spawn(move || {
612 loop {
613 match self.r_stop.try_recv() {
614 Ok(_) | Err(mpsc::TryRecvError::Disconnected) => {
615 break;
616 }
617 Err(mpsc::TryRecvError::Empty) => {}
618 }
619 let mut buf = vec![0; 64];
620 if let Ok((size, addr)) = socket.recv_from(&mut buf) {
621 if size == 0 {
622 continue;
623 }
624 buf.truncate(size);
625 let buf = buf.into_boxed_slice();
626 _ = self.s_in.send((addr, buf));
627 }
628 if let Ok((addr, buf)) = self.r_out.try_recv() {
629 if addr == local_addr {
630 continue;
631 }
632 _ = socket.send_to(&buf, addr);
633 }
634 }
635 });
636 Ok(local_addr)
637 }
638}
639
640struct TcpWorker {
641 s_in: mpsc::Sender<SerialMessage>,
642 r_out: mpsc::Receiver<SerialMessage>,
643 r_stop: mpsc::Receiver<()>,
644}
645
646impl TcpWorker {
647 fn start(self, ip: IpAddr) -> Result<(), NetworkError> {
648 let addrs: Vec<_> = (TCP_PORT_MIN..=TCP_PORT_MAX)
649 .map(|port| SocketAddr::new(ip, port))
650 .collect();
651 let Ok(socket) = TcpListener::bind(&addrs[..]) else {
652 return Err(NetworkError::CannotBind);
653 };
654 socket.set_nonblocking(true).unwrap();
655 std::thread::spawn(move || {
656 let mut streams = RingBuf::new();
657 loop {
658 match self.r_stop.try_recv() {
659 Ok(_) | Err(mpsc::TryRecvError::Disconnected) => {
660 break;
661 }
662 Err(mpsc::TryRecvError::Empty) => {}
663 }
664
665 if let Ok((stream, _addr)) = socket.accept() {
666 stream.set_nonblocking(true).unwrap();
667 streams.push(stream);
668 };
669
670 for stream in streams.iter_mut() {
671 let mut buf = vec![0; 200];
672 let Ok(size) = stream.read(&mut buf) else {
673 continue;
674 };
675 if size == 0 {
676 continue;
677 }
678 buf.truncate(size);
679 let buf = buf.into_boxed_slice();
680 _ = self.s_in.send(buf);
681 }
682 if let Ok(buf) = self.r_out.try_recv() {
683 for stream in streams.iter_mut() {
684 _ = stream.write_all(&buf)
685 }
686 }
687 }
688 });
689 Ok(())
690 }
691}
692
693struct RingBuf {
698 data: [Option<TcpStream>; 4],
699 next: usize,
700}
701
702impl RingBuf {
703 fn new() -> Self {
704 Self {
705 data: [None, None, None, None],
706 next: 0,
707 }
708 }
709
710 fn push(&mut self, val: TcpStream) {
711 self.data[self.next] = Some(val);
712 self.next = (self.next + 1) % 4
713 }
714
715 fn iter_mut(&mut self) -> impl Iterator<Item = &mut TcpStream> {
716 self.data.iter_mut().filter_map(Option::as_mut)
717 }
718}
719
720#[cfg(not(target_os = "android"))]
721fn start_audio(config: &DeviceConfig) -> Option<AudioWriter> {
722 let wav = if let Some(filename) = &config.wav {
723 let spec = hound::WavSpec {
724 channels: 2,
725 sample_rate: SAMPLE_RATE,
726 bits_per_sample: 16,
727 sample_format: hound::SampleFormat::Int,
728 };
729 let writer = hound::WavWriter::create(filename, spec).unwrap();
730 Some(writer)
731 } else {
732 None
733 };
734
735 let (send, recv) = mpsc::sync_channel(AUDIO_BUF_SIZE);
736 let Ok(mut stream) = rodio::OutputStreamBuilder::open_default_stream() else {
737 eprintln!("WARNING: audio device is not available, sound will be disabled");
738 return None;
739 };
740 stream.log_on_drop(false);
741 let mixer = stream.mixer();
742 let source = AudioReader { wav, recv };
743 mixer.add(source);
744 let audio = AudioWriter {
745 buf: [0; AUDIO_BUF_SIZE],
746 pending_from: 0,
747 pending_to: 0,
748 send,
749 _stream: stream,
750 };
751 Some(audio)
752}
753
754struct AudioWriter {
755 buf: [i16; AUDIO_BUF_SIZE],
756 send: mpsc::SyncSender<i16>,
757 pending_from: usize,
758 pending_to: usize,
759 #[cfg(not(target_os = "android"))]
760 _stream: rodio::OutputStream,
761}
762
763impl AudioWriter {
764 fn consume(&mut self) {
765 while self.pending_from > self.pending_to {
766 let byte = self.buf[self.pending_from];
767 let res = self.send.try_send(byte);
768 if res.is_err() {
769 return;
770 }
771 if self.pending_from < self.buf.len() {
772 self.pending_from += 1;
773 } else {
774 self.pending_from = 0;
775 }
776 }
777 while self.pending_from < self.pending_to {
778 let byte = self.buf[self.pending_from];
779 let res = self.send.try_send(byte);
780 if res.is_err() {
781 return;
782 }
783 self.pending_from += 1;
784 }
785 }
786
787 fn get_write_buf(&mut self) -> &mut [i16] {
788 self.consume();
789 if self.pending_from == self.pending_to {
790 self.pending_from = 0;
791 self.pending_to = self.buf.len();
792 return &mut self.buf;
793 }
794 if self.pending_from < self.pending_to {
795 let start = self.pending_to;
796 self.pending_to = self.buf.len();
797 return &mut self.buf[start..self.pending_to];
798 }
799 &mut []
800 }
801}
802
803#[cfg(not(target_os = "android"))]
804struct AudioReader {
805 wav: Option<hound::WavWriter<std::io::BufWriter<std::fs::File>>>,
806 recv: mpsc::Receiver<i16>,
807}
808
809#[cfg(not(target_os = "android"))]
810impl rodio::Source for AudioReader {
811 fn current_span_len(&self) -> Option<usize> {
812 None
813 }
814
815 fn channels(&self) -> u16 {
816 2
817 }
818
819 fn sample_rate(&self) -> u32 {
820 SAMPLE_RATE
821 }
822
823 fn total_duration(&self) -> Option<core::time::Duration> {
824 None
825 }
826}
827
828#[cfg(not(target_os = "android"))]
829impl Iterator for AudioReader {
830 type Item = f32;
831
832 fn next(&mut self) -> Option<Self::Item> {
833 let s = self.recv.try_recv().unwrap_or_default();
834 if let Some(wav) = self.wav.as_mut() {
835 wav.write_sample(s).unwrap()
836 }
837 let s = f32::from(s) / f32::from(i16::MAX);
838 Some(s)
839 }
840}