Skip to main content

v4l/
context.rs

1use std::fs;
2use std::path::{Path, PathBuf};
3
4/// Returns a list of devices currently known to the system
5///
6/// # Example
7///
8/// ```
9/// use v4l::context;
10/// for dev in context::enum_devices() {
11///     print!("{}{}", dev.index(), dev.name().unwrap());
12/// }
13/// ```
14pub fn enum_devices() -> Vec<Node> {
15    let mut devices = Vec::new();
16
17    let entries = fs::read_dir("/dev");
18    if let Ok(entries) = entries {
19        for dentry in entries {
20            let dentry = match dentry {
21                Ok(dentry) => dentry,
22                Err(_) => continue,
23            };
24
25            let file_name = dentry.file_name();
26            let file_name = file_name.to_str().unwrap();
27
28            if file_name.starts_with("video") {
29                let node = Node::new(dentry.path());
30                devices.push(node);
31            }
32        }
33    }
34
35    devices
36}
37
38/// Represents a video4linux device node
39pub struct Node {
40    /// Device node path
41    path: PathBuf,
42}
43
44impl Node {
45    /// Returns a device node observer by path
46    ///
47    /// The device is opened in read only mode.
48    ///
49    /// # Arguments
50    ///
51    /// * `path` - Node path (usually a character device or sysfs entry)
52    ///
53    /// # Example
54    ///
55    /// ```
56    /// use v4l::context::Node;
57    /// let node = Node::new("/dev/video0");
58    /// ```
59    pub fn new<P: AsRef<Path>>(path: P) -> Self {
60        Node {
61            path: PathBuf::from(path.as_ref()),
62        }
63    }
64
65    /// Returns the absolute path of the device node
66    pub fn path(&self) -> &Path {
67        &self.path
68    }
69
70    /// Returns the index of the device node
71    pub fn index(&self) -> usize {
72        let file_name = self.path.file_name().unwrap();
73
74        let mut index_str = String::new();
75        for c in file_name.to_str().unwrap().chars() {
76            if !c.is_ascii_digit() {
77                continue;
78            }
79
80            index_str.push(c);
81        }
82
83        let index = index_str.parse::<usize>();
84        index.unwrap()
85    }
86
87    /// Returns name of the device by parsing its sysfs entry
88    pub fn name(&self) -> Option<String> {
89        let index = self.index();
90        let path = format!("{}{}{}", "/sys/class/video4linux/video", index, "/name");
91        let name = fs::read_to_string(path);
92        match name {
93            Ok(name) => Some(name.trim().to_string()),
94            Err(_) => None,
95        }
96    }
97}