1 //! Info about connected audio devices
2 
3 use ll;
4 use util::{to_pa_result, pa_time_to_duration};
5 use hostapi::HostApiIndex;
6 use pa::PaError;
7 use std::time::Duration;
8 use std::ffi::CStr;
9 
10 /// Index of a Device
11 pub type DeviceIndex = u32;
12 
13 /// Information for a specific device
14 pub struct DeviceInfo
15 {
16     /// Human readable name
17     pub name: String,
18 
19     /// Index of the host API this device belongs to
20     pub host_api: HostApiIndex,
21 
22     /// Maximal number of input channels that can be used
23     pub max_input_channels: u32,
24 
25     /// Maximal number of ouput channels that can be used
26     pub max_output_channels: u32,
27 
28     /// Default input latency for interactive performance
29     pub default_low_input_latency: Duration,
30 
31     /// Default output latency for interactive performance
32     pub default_low_output_latency: Duration,
33 
34     /// Default input latency for robust non-interactive applications
35     pub default_high_input_latency: Duration,
36 
37     /// Default output latency for robust non-interactive applications
38     pub default_high_output_latency: Duration,
39 
40     /// Default sample rate
41     pub default_sample_rate: f64,
42 }
43 
44 impl DeviceInfo
45 {
from_ll(input: &ll::PaDeviceInfo) -> DeviceInfo46     fn from_ll(input: &ll::PaDeviceInfo) -> DeviceInfo
47     {
48         DeviceInfo
49         {
50             name: String::from_utf8_lossy(unsafe { CStr::from_ptr(input.name).to_bytes() }).into_owned(),
51             host_api: input.hostApi as HostApiIndex,
52             max_input_channels: input.maxInputChannels as u32,
53             max_output_channels: input.maxOutputChannels as u32,
54             default_low_input_latency: pa_time_to_duration(input.defaultLowInputLatency),
55             default_low_output_latency: pa_time_to_duration(input.defaultLowOutputLatency),
56             default_high_input_latency: pa_time_to_duration(input.defaultHighInputLatency),
57             default_high_output_latency: pa_time_to_duration(input.defaultHighOutputLatency),
58             default_sample_rate: input.defaultSampleRate,
59         }
60     }
61 }
62 
63 /// Retrieve the number of available devices.
get_count() -> Result<u32, PaError>64 pub fn get_count() -> Result<u32, PaError>
65 {
66     match unsafe { ll::Pa_GetDeviceCount() }
67     {
68         n if n >= 0 => Ok(n as u32),
69         m => to_pa_result(m).map(|_| 0),
70     }
71 }
72 
73 /// Retrieve the index of the default input device
74 ///
75 /// Will return None when none are available.
get_default_input_index() -> Option<DeviceIndex>76 pub fn get_default_input_index() -> Option<DeviceIndex>
77 {
78     match unsafe { ll::Pa_GetDefaultInputDevice() }
79     {
80         n if n >= 0 => Some(n as u32),
81         _ => None,
82     }
83 }
84 
85 /// Retrieve the index of the default output device
86 ///
87 /// Will return None when none are available.
get_default_output_index() -> Option<DeviceIndex>88 pub fn get_default_output_index() -> Option<DeviceIndex>
89 {
90     match unsafe { ll::Pa_GetDefaultOutputDevice() }
91     {
92         n if n >= 0 => Some(n as u32),
93         _ => None,
94     }
95 }
96 
97 /// Get info about a particular device
98 ///
99 /// Returns None when the index is out of range.
get_info(index: DeviceIndex) -> Option<DeviceInfo>100 pub fn get_info(index: DeviceIndex) -> Option<DeviceInfo>
101 {
102     unsafe
103     {
104         match ll::Pa_GetDeviceInfo(index as i32) {
105             p if p.is_null() => None,
106             p => Some(DeviceInfo::from_ll(&*p)),
107         }
108     }
109 }
110 
111 /// Converts a device index from a specific host API to a global device index
112 ///
113 /// Returns Err(InvalidHostApi) when the host_api is out of range, and Err(InvalidDevice) when
114 /// host_api_device_index is out of range.
115 ///
116 /// ```
117 /// // We retrieve the index of device 3 of api 1
118 /// let device_index = match portaudio_rs::device::get_from_host_api_device_index(1, 3)
119 /// {
120 ///     Ok(n) => n,
121 ///     Err(e) => { println!("Error: {:?}", e); return },
122 /// };
123 /// ```
get_from_host_api_device_index(host_api: HostApiIndex, host_api_device_index: u32) -> Result<DeviceIndex, PaError>124 pub fn get_from_host_api_device_index(host_api: HostApiIndex, host_api_device_index: u32) -> Result<DeviceIndex, PaError>
125 {
126     match unsafe { ll::Pa_HostApiDeviceIndexToDeviceIndex(host_api as i32, host_api_device_index as i32) }
127     {
128         n if n >= 0 => Ok(n as DeviceIndex),
129         m => to_pa_result(m).map(|_| 0),
130     }
131 }
132