1 // Copyright 2022 The ChromiumOS Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 use std::fs::File;
6 use std::fs::OpenOptions;
7 use std::io::Error as IOError;
8 use std::io::Seek;
9 use std::io::SeekFrom;
10 use std::io::Write;
11 use std::path::Path;
12
13 use audio_streams::NoopStreamSourceGenerator;
14 use audio_util::FileStreamSourceGenerator;
15 use base::error;
16 use base::open_file;
17 use base::AsRawDescriptor;
18 use base::RawDescriptor;
19 use thiserror::Error as ThisError;
20
21 use crate::virtio::snd::common_backend::SndData;
22 use crate::virtio::snd::constants::VIRTIO_SND_D_OUTPUT;
23 use crate::virtio::snd::parameters::Parameters;
24 use crate::virtio::snd::sys::SysAudioStreamSourceGenerator;
25
26 #[derive(ThisError, Debug)]
27 pub enum Error {
28 #[error("Failed to allocate space: {0}")]
29 AllocateSpace(IOError),
30 #[error("Failed to open file: {0}")]
31 OpenFile(base::Error),
32 }
33
allocate_space(mut file: &File, size: usize) -> Result<(), Error>34 fn allocate_space(mut file: &File, size: usize) -> Result<(), Error> {
35 file.seek(SeekFrom::Start(size as u64))
36 .map_err(Error::AllocateSpace)?;
37 file.write_all(&[0]).map_err(Error::AllocateSpace)?;
38 file.seek(SeekFrom::Start(0))
39 .map_err(Error::AllocateSpace)?;
40 Ok(())
41 }
42
open_playback_file(dir_path: &String, stream_id: usize) -> Result<File, Error>43 fn open_playback_file(dir_path: &String, stream_id: usize) -> Result<File, Error> {
44 let file_name = format!("stream-{}.out", stream_id);
45 let file_path = Path::new(dir_path).join(file_name);
46 let file = open_file(
47 file_path,
48 OpenOptions::new().read(true).create(true).write(true),
49 )
50 .map_err(Error::OpenFile)?;
51 Ok(file)
52 }
53
create_file_stream_source_generators( params: &Parameters, snd_data: &SndData, keep_rds: &mut Vec<RawDescriptor>, ) -> Result<Vec<SysAudioStreamSourceGenerator>, Error>54 pub(crate) fn create_file_stream_source_generators(
55 params: &Parameters,
56 snd_data: &SndData,
57 keep_rds: &mut Vec<RawDescriptor>,
58 ) -> Result<Vec<SysAudioStreamSourceGenerator>, Error> {
59 let mut generators = Vec::new();
60
61 for (stream, pcm_info) in snd_data.pcm_info.iter().enumerate() {
62 let generator: SysAudioStreamSourceGenerator = if pcm_info.direction == VIRTIO_SND_D_OUTPUT
63 {
64 let file = open_playback_file(¶ms.playback_path, stream)?;
65 allocate_space(&file, params.playback_size)?;
66 keep_rds.push(file.as_raw_descriptor());
67
68 Box::new(FileStreamSourceGenerator::new(file, params.playback_size))
69 } else {
70 // Capture is not supported yet
71 Box::new(NoopStreamSourceGenerator::new())
72 };
73
74 generators.push(generator);
75 }
76 Ok(generators)
77 }
78