UltraGrid
UltraGrid Low-Latency High-Resolution Transmission System
Loading...
Searching...
No Matches
alsa_common.h
Go to the documentation of this file.
1
5/*
6 * Copyright (c) 2015-2023 CESNET, z. s. p. o.
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, is permitted provided that the following conditions
11 * are met:
12 *
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 *
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 *
20 * 3. Neither the name of CESNET nor the names of its contributors may be
21 * used to endorse or promote products derived from this software without
22 * specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS
25 * "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING,
26 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
27 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
28 * EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
29 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
30 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
31 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
34 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
35 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 */
37
38#ifndef ALSA_COMMON_H
39#define ALSA_COMMON_H
40
41#include <alsa/asoundlib.h>
42#include <stdio.h>
43#include <stdlib.h>
44#include <string.h>
45
46#include "debug.h"
47#include "utils/color_out.h"
48#include "types.h"
49
50static inline void audio_alsa_probe(struct device_info **available_devices,
51 int *count,
52 const char **whitelist,
53 size_t whitelist_size)
54{
55 void **hints;
56 snd_device_name_hint(-1, "pcm", &hints);
57
58 size_t device_count = 0;
59 for (void **it = hints; *it != NULL; it++) device_count++;
60
61 *available_devices = calloc(device_count + 1 , sizeof(struct device_info));
62 strcpy((*available_devices)[0].dev, "");
63 strcpy((*available_devices)[0].name, "Default Linux audio");
64 *count = 1;
65
66 for(void **it = hints; *it != NULL; it++){
67 char *id = snd_device_name_get_hint(*it, "NAME");
68
69 bool whitelisted = false;
70 for(size_t i = 0; i < whitelist_size; i++){
71 if(strstr(id, whitelist[i])){
72 whitelisted = true;
73 break;
74 }
75 }
76 if(!whitelisted && whitelist_size > 0) {
77 free(id);
78 continue;
79 }
80
81 strcpy((*available_devices)[*count].dev, ":");
82 strncat((*available_devices)[*count].dev, id,
83 sizeof (*available_devices)[*count].dev -
84 strlen((*available_devices)[*count].dev) - 1);
85 free(id);
86
87 char *name = snd_device_name_get_hint(*it, "DESC");
88 char *tok = name;
89 while(tok){
90 char *newline = strchr(tok, '\n');
91 if(newline){
92 *newline = '\0';
93 strncat((*available_devices)[*count].name, tok,
94 sizeof (*available_devices)[*count].name -
95 strlen((*available_devices)[*count].name) - 1);
96 strncat((*available_devices)[*count].name, " - ",
97 sizeof (*available_devices)[*count].name -
98 strlen((*available_devices)[*count].name) - 1);
99 tok = newline + 1;
100 } else {
101 strncat((*available_devices)[*count].name, tok,
102 sizeof (*available_devices)[*count].name -
103 strlen((*available_devices)[*count].name) - 1);
104 tok = NULL;
105 }
106 }
107 free(name);
108 (*count)++;
109 }
110
111 snd_device_name_free_hint(hints);
112}
113
114static inline void audio_alsa_list_devices(void)
115{
116 struct device_info *available_devices;
117 int count;
118 audio_alsa_probe(&available_devices, &count, NULL, 0);
119 strcpy(available_devices[0].dev, "");
120 strcpy(available_devices[0].name, "default ALSA device (same as \"alsa:default\")");
121 for(int i = 0; i < count; i++){
122 const char * const id = available_devices[i].dev;
123 color_printf(TERM_FG_RED "\talsa%s" TERM_FG_RESET, id);
124 for (int j = 0; j < 30 - (int) strlen(id); ++j) putchar(' ');
125 printf(": %s\n", available_devices[i].name);
126 }
127 free(available_devices);
128}
129
130static const snd_pcm_format_t bps_to_snd_fmts[] = {
131 [0] = SND_PCM_FORMAT_UNKNOWN,
132 [1] = SND_PCM_FORMAT_U8,
133 [2] = SND_PCM_FORMAT_S16_LE,
134 [3] = SND_PCM_FORMAT_S24_3LE,
135 [4] = SND_PCM_FORMAT_S32_LE,
136};
137
144static int get_rate_near(snd_pcm_t *handle, snd_pcm_hw_params_t *params, unsigned int approx_val) {
145 int ret = 0;
146 int dir = 0;
147 int rc;
148 unsigned int rate = approx_val;
149 // try exact sample rate
150 rc = snd_pcm_hw_params_set_rate_min(handle, params, &rate, &dir);
151 if (rc != 0) {
152 dir = 1;
153 // or higher
154 rc = snd_pcm_hw_params_set_rate_min(handle, params, &rate, &dir);
155 }
156
157 if (rc == 0) {
158 // read the rate
159 rc = snd_pcm_hw_params_get_rate_min(params, &rate, NULL);
160 if (rc == 0) {
161 ret = rate;
162 }
163 // restore configuration space
164 rate = 0;
165 dir = 1;
166 rc = snd_pcm_hw_params_set_rate_min(handle, params, &rate, &dir);
167 assert(rc == 0);
168 }
169
170 // we did not succeed, try lower sample rate
171 if (ret == 0) {
172 unsigned int rate = approx_val;
173 dir = 0;
174 unsigned int orig_max;
175 rc = snd_pcm_hw_params_get_rate_max(params, &orig_max, NULL);
176 assert(rc == 0);
177
178 rc = snd_pcm_hw_params_set_rate_max(handle, params, &rate, &dir);
179 if (rc != 0) {
180 dir = -1;
181 rc = snd_pcm_hw_params_set_rate_max(handle, params, &rate, &dir);
182 }
183
184 if (rc == 0) {
185 rc = snd_pcm_hw_params_get_rate_max(params, &rate, NULL);
186 if (rc == 0) {
187 ret = rate;
188 }
189 // restore configuration space
190 dir = 0;
191 rc = snd_pcm_hw_params_set_rate_max(handle, params, &orig_max, &dir);
192 assert(rc == 0);
193 }
194 }
195 return ret;
196}
197
198static void print_alsa_device_info(snd_pcm_t *handle, const char *module_name) {
199 snd_pcm_info_t *info;
200 snd_pcm_info_alloca(&info);
201 if (snd_pcm_info(handle, info) == 0) {
202 log_msg(LOG_LEVEL_NOTICE, "%sUsing device: %s\n",
203 module_name, snd_pcm_info_get_name(info));
204 }
205}
206
207static const char *alsa_get_pcm_state_name(snd_pcm_state_t state) __attribute__((unused));
208static const char *alsa_get_pcm_state_name(snd_pcm_state_t state) {
209 switch (state) {
210 case SND_PCM_STATE_OPEN:
211 return "Open";
212 case SND_PCM_STATE_SETUP:
213 return "Setup installed";
214 case SND_PCM_STATE_PREPARED:
215 return "Ready to start";
216 case SND_PCM_STATE_RUNNING:
217 return "Running";
218 case SND_PCM_STATE_XRUN:
219 return "Stopped: underrun (playback) or overrun (capture) detected";
220 case SND_PCM_STATE_DRAINING:
221 return "Draining: running (playback) or stopped (capture)";
222 case SND_PCM_STATE_PAUSED:
223 return "Paused";
224 case SND_PCM_STATE_SUSPENDED:
225 return "Hardware is suspended";
226 case SND_PCM_STATE_DISCONNECTED:
227 return "Hardware is disconnected";
228 default:
229 return "(unknown)";
230 }
231}
232
233#endif // defined ALSA_COMMON_H
234
void ** state
static const snd_pcm_format_t bps_to_snd_fmts[]
static const char * alsa_get_pcm_state_name(snd_pcm_state_t state) __attribute__((unused))
static int get_rate_near(snd_pcm_t *handle, snd_pcm_hw_params_t *params, unsigned int approx_val)
static void audio_alsa_list_devices(void)
static void audio_alsa_probe(struct device_info **available_devices, int *count, const char **whitelist, size_t whitelist_size)
Definition alsa_common.h:50
static void print_alsa_device_info(snd_pcm_t *handle, const char *module_name)
int color_printf(const char *format,...)
#define TERM_FG_RED
Definition color_out.h:50
#define TERM_FG_RESET
Definition color_out.h:59
void log_msg(int level, const char *format,...)
Definition debug.cpp:130
#define LOG_LEVEL_NOTICE
information that may be interesting
Definition debug.h:61
int count
Definition hd-rum.c:44
struct __attribute__((packed))
Definition rtp.h:88
const char * name
Definition settings.cpp:193
char dev[1024]
Definition types.h:383
This file contains some common data types.