1 /***
2   This file is part of PulseAudio.
3 
4   Copyright 2004-2006 Lennart Poettering
5   Copyright 2006 Pierre Ossman <ossman@cendio.se> for Cendio AB
6 
7   PulseAudio is free software; you can redistribute it and/or modify
8   it under the terms of the GNU Lesser General Public License as published
9   by the Free Software Foundation; either version 2.1 of the License,
10   or (at your option) any later version.
11 
12   PulseAudio is distributed in the hope that it will be useful, but
13   WITHOUT ANY WARRANTY; without even the implied warranty of
14   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15   General Public License for more details.
16 
17   You should have received a copy of the GNU Lesser General Public License
18   along with PulseAudio; if not, see <http://www.gnu.org/licenses/>.
19 ***/
20 
21 
22 #ifndef PULSE_COMPAT_H
23 #define PULSE_COMPAT_H
24 
25 #ifdef __cplusplus
26 extern "C" {
27 #else
28 #include <stdbool.h>
29 #endif
30 
31 #include <stdio.h>
32 #include <stdarg.h>
33 #include <stdint.h>
34 #include <inttypes.h>
35 #include <stdlib.h>
36 #include <unistd.h>
37 
38 typedef struct pa_core pa_core;
39 
40 typedef void *(*pa_copy_func_t)(const void *p);
41 typedef void (*pa_free_cb_t)(void *p);
42 
43 #ifdef __GNUC__
44 #define PA_LIKELY(x) (__builtin_expect(!!(x),1))
45 #define PA_UNLIKELY(x) (__builtin_expect(!!(x),0))
46 #define PA_PRINTF_FUNC(fmt, arg1) __attribute__((format(printf, fmt, arg1)))
47 #else
48 #define PA_LIKELY(x) (x)
49 #define PA_UNLIKELY(x) (x)
50 #define PA_PRINTF_FUNC(fmt, arg1)
51 #endif
52 
53 #define PA_MIN(a,b)                    \
54 ({                                     \
55         __typeof__(a) _a = (a);        \
56         __typeof__(b) _b = (b);        \
57         PA_LIKELY(_a < _b) ? _a : _b;  \
58 })
59 #define PA_MAX(a,b)                    \
60 ({                                     \
61         __typeof__(a) _a = (a);        \
62         __typeof__(b) _b = (b);        \
63         PA_LIKELY(_a > _b) ? _a : _b;  \
64 })
65 #define PA_CLAMP_UNLIKELY(v,low,high)                 \
66 ({                                                    \
67         __typeof__(v) _v = (v);                       \
68         __typeof__(low) _low = (low);                 \
69         __typeof__(high) _high = (high);              \
70         PA_MIN(PA_MAX(_v, _low), _high);              \
71 })
72 
73 #define PA_PTR_TO_UINT(p) ((unsigned int) ((uintptr_t) (p)))
74 #define PA_UINT_TO_PTR(u) ((void*) ((uintptr_t) (u)))
75 
76 #include "array.h"
77 #include "llist.h"
78 #include "hashmap.h"
79 #include "dynarray.h"
80 #include "idxset.h"
81 #include "proplist.h"
82 
83 typedef enum pa_direction {
84 	PA_DIRECTION_OUTPUT = 0x0001U,  /**< Output direction */
85 	PA_DIRECTION_INPUT = 0x0002U    /**< Input direction */
86 } pa_direction_t;
87 
88 /* This enum replaces pa_port_available_t (defined in pulse/def.h) for
89  * internal use, so make sure both enum types stay in sync. */
90 typedef enum pa_available {
91 	PA_AVAILABLE_UNKNOWN = 0,
92 	PA_AVAILABLE_NO = 1,
93 	PA_AVAILABLE_YES = 2,
94 } pa_available_t;
95 
96 #define PA_RATE_MAX (48000U*8U)
97 
98 typedef enum pa_sample_format {
99 	PA_SAMPLE_U8,		/**< Unsigned 8 Bit PCM */
100 	PA_SAMPLE_ALAW,		/**< 8 Bit a-Law */
101 	PA_SAMPLE_ULAW,		/**< 8 Bit mu-Law */
102 	PA_SAMPLE_S16LE,	/**< Signed 16 Bit PCM, little endian (PC) */
103 	PA_SAMPLE_S16BE,	/**< Signed 16 Bit PCM, big endian */
104 	PA_SAMPLE_FLOAT32LE,	/**< 32 Bit IEEE floating point, little endian (PC), range -1.0 to 1.0 */
105 	PA_SAMPLE_FLOAT32BE,	/**< 32 Bit IEEE floating point, big endian, range -1.0 to 1.0 */
106 	PA_SAMPLE_S32LE,	/**< Signed 32 Bit PCM, little endian (PC) */
107 	PA_SAMPLE_S32BE,	/**< Signed 32 Bit PCM, big endian */
108 	PA_SAMPLE_S24LE,	/**< Signed 24 Bit PCM packed, little endian (PC). \since 0.9.15 */
109 	PA_SAMPLE_S24BE,	/**< Signed 24 Bit PCM packed, big endian. \since 0.9.15 */
110 	PA_SAMPLE_S24_32LE,	/**< Signed 24 Bit PCM in LSB of 32 Bit words, little endian (PC). \since 0.9.15 */
111 	PA_SAMPLE_S24_32BE,	/**< Signed 24 Bit PCM in LSB of 32 Bit words, big endian. \since 0.9.15 */
112 	PA_SAMPLE_MAX,		/**< Upper limit of valid sample types */
113 	PA_SAMPLE_INVALID = -1	/**< An invalid value */
114 } pa_sample_format_t;
115 
pa_sample_format_valid(unsigned format)116 static inline int pa_sample_format_valid(unsigned format)
117 {
118 	return format < PA_SAMPLE_MAX;
119 }
120 
121 #ifdef WORDS_BIGENDIAN
122 #define PA_SAMPLE_S16NE PA_SAMPLE_S16BE
123 #define PA_SAMPLE_FLOAT32NE PA_SAMPLE_FLOAT32BE
124 #define PA_SAMPLE_S32NE PA_SAMPLE_S32BE
125 #define PA_SAMPLE_S24NE PA_SAMPLE_S24BE
126 #define PA_SAMPLE_S24_32NE PA_SAMPLE_S24_32BE
127 #define PA_SAMPLE_S16RE PA_SAMPLE_S16LE
128 #define PA_SAMPLE_FLOAT32RE PA_SAMPLE_FLOAT32LE
129 #define PA_SAMPLE_S32RE PA_SAMPLE_S32LE
130 #define PA_SAMPLE_S24RE PA_SAMPLE_S24LE
131 #define PA_SAMPLE_S24_32RE PA_SAMPLE_S24_32LE
132 #else
133 #define PA_SAMPLE_S16NE PA_SAMPLE_S16LE
134 #define PA_SAMPLE_FLOAT32NE PA_SAMPLE_FLOAT32LE
135 #define PA_SAMPLE_S32NE PA_SAMPLE_S32LE
136 #define PA_SAMPLE_S24NE PA_SAMPLE_S24LE
137 #define PA_SAMPLE_S24_32NE PA_SAMPLE_S24_32LE
138 #define PA_SAMPLE_S16RE PA_SAMPLE_S16BE
139 #define PA_SAMPLE_FLOAT32RE PA_SAMPLE_FLOAT32BE
140 #define PA_SAMPLE_S32RE PA_SAMPLE_S32BE
141 #define PA_SAMPLE_S24RE PA_SAMPLE_S24BE
142 #define PA_SAMPLE_S24_32RE PA_SAMPLE_S24_32BE
143 #endif
144 
145 static const size_t pa_sample_size_table[] = {
146     [PA_SAMPLE_U8] = 1,
147     [PA_SAMPLE_ULAW] = 1,
148     [PA_SAMPLE_ALAW] = 1,
149     [PA_SAMPLE_S16LE] = 2,
150     [PA_SAMPLE_S16BE] = 2,
151     [PA_SAMPLE_FLOAT32LE] = 4,
152     [PA_SAMPLE_FLOAT32BE] = 4,
153     [PA_SAMPLE_S32LE] = 4,
154     [PA_SAMPLE_S32BE] = 4,
155     [PA_SAMPLE_S24LE] = 3,
156     [PA_SAMPLE_S24BE] = 3,
157     [PA_SAMPLE_S24_32LE] = 4,
158     [PA_SAMPLE_S24_32BE] = 4
159 };
160 
pa_sample_format_to_string(pa_sample_format_t f)161 static inline const char *pa_sample_format_to_string(pa_sample_format_t f)
162 {
163 	static const char* const table[]= {
164 		[PA_SAMPLE_U8] = "u8",
165 		[PA_SAMPLE_ALAW] = "aLaw",
166 		[PA_SAMPLE_ULAW] = "uLaw",
167 		[PA_SAMPLE_S16LE] = "s16le",
168 		[PA_SAMPLE_S16BE] = "s16be",
169 		[PA_SAMPLE_FLOAT32LE] = "float32le",
170 		[PA_SAMPLE_FLOAT32BE] = "float32be",
171 		[PA_SAMPLE_S32LE] = "s32le",
172 		[PA_SAMPLE_S32BE] = "s32be",
173 		[PA_SAMPLE_S24LE] = "s24le",
174 		[PA_SAMPLE_S24BE] = "s24be",
175 		[PA_SAMPLE_S24_32LE] = "s24-32le",
176 		[PA_SAMPLE_S24_32BE] = "s24-32be",
177 	};
178 
179 	if (!pa_sample_format_valid(f))
180 	        return NULL;
181 	return table[f];
182 }
183 
184 typedef struct pa_sample_spec {
185 	pa_sample_format_t format;
186 	uint32_t rate;
187 	uint8_t channels;
188 } pa_sample_spec;
189 
190 typedef uint64_t pa_usec_t;
191 #define PA_MSEC_PER_SEC ((pa_usec_t) 1000ULL)
192 #define PA_USEC_PER_SEC ((pa_usec_t) 1000000ULL)
193 #define PA_USEC_PER_MSEC ((pa_usec_t) 1000ULL)
194 
pa_usec_to_bytes(pa_usec_t t,const pa_sample_spec * spec)195 static inline size_t pa_usec_to_bytes(pa_usec_t t, const pa_sample_spec *spec) {
196     return (size_t) (((t * spec->rate) / PA_USEC_PER_SEC)) *
197 	    (pa_sample_size_table[spec->format] * spec->channels);
198 }
199 
pa_sample_rate_valid(uint32_t rate)200 static inline int pa_sample_rate_valid(uint32_t rate) {
201     return rate > 0 && rate <= PA_RATE_MAX * 101 / 100;
202 }
203 
pa_frame_size(const pa_sample_spec * spec)204 static inline size_t pa_frame_size(const pa_sample_spec *spec) {
205     return pa_sample_size_table[spec->format] * spec->channels;
206 }
207 
208 typedef enum pa_log_level {
209 	PA_LOG_ERROR  = 0,    /* Error messages */
210 	PA_LOG_WARN   = 1,    /* Warning messages */
211 	PA_LOG_NOTICE = 2,    /* Notice messages */
212 	PA_LOG_INFO   = 3,    /* Info messages */
213 	PA_LOG_DEBUG  = 4,    /* Debug messages */
214 	PA_LOG_LEVEL_MAX
215 } pa_log_level_t;
216 
217 extern int _acp_log_level;
218 extern acp_log_func _acp_log_func;
219 extern void * _acp_log_data;
220 
221 #define pa_log_level_enabled(lev) (_acp_log_level >= (int)(lev))
222 
223 #define pa_log_levelv_meta(lev,f,l,func,fmt,ap)                         \
224 ({                                                                      \
225         if (pa_log_level_enabled (lev) && _acp_log_func)                \
226                 _acp_log_func(_acp_log_data,lev,f,l,func,fmt,ap);			\
227 })
228 
pa_log_level_meta(enum pa_log_level level,const char * file,int line,const char * func,const char * fmt,...)229 static inline PA_PRINTF_FUNC(5, 6) void pa_log_level_meta(enum pa_log_level level,
230            const char *file, int line, const char *func,
231            const char *fmt, ...)
232 {
233 	va_list args;
234 	va_start(args,fmt);
235 	pa_log_levelv_meta(level,file,line,func,fmt,args);
236 	va_end(args);
237 }
238 
239 #define pa_logl(lev,fmt,...)	pa_log_level_meta(lev,__FILE__, __LINE__, __func__, fmt, ##__VA_ARGS__)
240 #define pa_log_error(fmt,...)	pa_logl(PA_LOG_ERROR, fmt, ##__VA_ARGS__)
241 #define pa_log_warn(fmt,...)	pa_logl(PA_LOG_WARN, fmt, ##__VA_ARGS__)
242 #define pa_log_notice(fmt,...)	pa_logl(PA_LOG_NOTICE, fmt, ##__VA_ARGS__)
243 #define pa_log_info(fmt,...)	pa_logl(PA_LOG_INFO, fmt, ##__VA_ARGS__)
244 #define pa_log_debug(fmt,...)	pa_logl(PA_LOG_DEBUG, fmt, ##__VA_ARGS__)
245 #define pa_log			pa_log_error
246 
247 #define pa_assert_se(expr)                                              \
248         do {                                                            \
249                 if (PA_UNLIKELY(!(expr))) {                             \
250                         fprintf(stderr, "'%s' failed at %s:%u %s()\n",  \
251                                 #expr , __FILE__, __LINE__, __func__);  \
252                         abort();                                        \
253                 }                                                       \
254         } while (false)
255 
256 #define pa_assert(expr)                                                 \
257         do {                                                            \
258                 if (PA_UNLIKELY(!(expr))) {                             \
259                         fprintf(stderr, "'%s' failed at %s:%u %s()\n",  \
260                                 #expr , __FILE__, __LINE__, __func__);  \
261                         abort();                                        \
262                 }                                                       \
263         } while (false)
264 
265 #define pa_assert_not_reached()                                                \
266         do {                                                                    \
267                 fprintf(stderr, "Code should not be reached at %s:%u %s()\n",   \
268                                 __FILE__, __LINE__, __func__);                  \
269                 abort();                                                        \
270         } while (false)
271 
272 
273 #define pa_memzero(x,l) (memset((x), 0, (l)))
274 #define pa_zero(x)      (pa_memzero(&(x), sizeof(x)))
275 
276 #define PA_ELEMENTSOF(x) (sizeof(x)/sizeof((x)[0]))
277 
278 #define pa_streq(a,b) (!strcmp((a),(b)))
279 #define pa_strneq(a,b,n) (!strncmp((a),(b),(n)))
280 #define pa_strnull(s)	((s) ? (s) : "null")
281 #define pa_startswith(s,pfx)	(strstr(s, pfx) == s)
282 
283 PA_PRINTF_FUNC(3, 0)
pa_vsnprintf(char * str,size_t size,const char * format,va_list ap)284 static inline size_t pa_vsnprintf(char *str, size_t size, const char *format, va_list ap)
285 {
286 	int ret;
287 
288 	pa_assert(str);
289 	pa_assert(size > 0);
290 	pa_assert(format);
291 
292 	ret = vsnprintf(str, size, format, ap);
293 
294 	str[size-1] = 0;
295 
296 	if (ret < 0)
297 		return strlen(str);
298 
299 	if ((size_t) ret > size-1)
300 		return size-1;
301 
302 	return (size_t) ret;
303 }
304 
305 PA_PRINTF_FUNC(3, 4)
pa_snprintf(char * str,size_t size,const char * format,...)306 static inline size_t pa_snprintf(char *str, size_t size, const char *format, ...)
307 {
308 	size_t ret;
309 	va_list ap;
310 
311 	pa_assert(str);
312 	pa_assert(size > 0);
313 	pa_assert(format);
314 
315 	va_start(ap, format);
316 	ret = pa_vsnprintf(str, size, format, ap);
317 	va_end(ap);
318 
319 	return ret;
320 }
321 
322 #define pa_xstrdup(s)		((s) != NULL ? strdup(s) : NULL)
323 #define pa_xstrndup(s,n)	((s) != NULL ? strndup(s,n) : NULL)
324 #define pa_xfree		free
325 #define pa_xmalloc		malloc
326 #define pa_xnew0(t,n)		calloc(n, sizeof(t))
327 #define pa_xnew(t,n)		pa_xnew0(t,n)
328 #define pa_xrealloc		realloc
329 #define pa_xrenew(t,p,n)	((t*) realloc(p, (n)*sizeof(t)))
330 
pa_xmemdup(const void * p,size_t l)331 static inline void* pa_xmemdup(const void *p, size_t l) {
332 	return memcpy(malloc(l), p, l);
333 
334 }
335 #define pa_xnewdup(t,p,n) ((t*) pa_xmemdup((p), (n)*sizeof(t)))
336 
pa_xfreev(void ** a)337 static inline void pa_xfreev(void**a)
338 {
339 	int i;
340 	for (i = 0; a && a[i]; i++)
341                 free(a[i]);
342         free(a);
343 }
pa_xstrfreev(char ** a)344 static inline void pa_xstrfreev(char **a) {
345     pa_xfreev((void**)a);
346 }
347 
348 
349 #define pa_cstrerror	strerror
350 
351 #define PA_PATH_SEP		"/"
352 #define PA_PATH_SEP_CHAR	'/'
353 
354 #define PA_WHITESPACE "\n\r \t"
355 
pa_sprintf_malloc(const char * fmt,...)356 static PA_PRINTF_FUNC(1,2) inline char *pa_sprintf_malloc(const char *fmt, ...)
357 {
358 	char *res;
359 	va_list args;
360 	va_start(args, fmt);
361 	if (vasprintf(&res, fmt, args) < 0)
362 		res = NULL;
363 	va_end(args);
364 	return res;
365 }
366 
367 #define pa_fopen_cloexec(f,m)	fopen(f,m"e")
368 
pa_path_get_filename(const char * p)369 static inline char *pa_path_get_filename(const char *p)
370 {
371     char *fn;
372     if (!p)
373         return NULL;
374     if ((fn = strrchr(p, PA_PATH_SEP_CHAR)))
375         return fn+1;
376     return (char*) p;
377 }
378 
pa_is_path_absolute(const char * fn)379 static inline bool pa_is_path_absolute(const char *fn)
380 {
381     return *fn == PA_PATH_SEP_CHAR;
382 }
383 
pa_maybe_prefix_path(const char * path,const char * prefix)384 static inline char* pa_maybe_prefix_path(const char *path, const char *prefix)
385 {
386     if (pa_is_path_absolute(path))
387         return pa_xstrdup(path);
388     return pa_sprintf_malloc("%s" PA_PATH_SEP "%s", prefix, path);
389 }
390 
pa_endswith(const char * s,const char * sfx)391 static inline bool pa_endswith(const char *s, const char *sfx)
392 {
393 	size_t l1, l2;
394 	l1 = strlen(s);
395 	l2 = strlen(sfx);
396 	return l1 >= l2 && pa_streq(s + l1 - l2, sfx);
397 }
398 
pa_replace(const char * s,const char * a,const char * b)399 static inline char *pa_replace(const char*s, const char*a, const char *b)
400 {
401 	struct pa_array res;
402 	size_t an, bn;
403 
404 	an = strlen(a);
405 	bn = strlen(b);
406 	pa_array_init(&res, an);
407 
408 	for (;;) {
409 		const char *p;
410 
411 		if (!(p = strstr(s, a)))
412 			break;
413 
414 		pa_array_add_data(&res, s, p-s);
415 		pa_array_add_data(&res, b, bn);
416 		s = p + an;
417 	}
418 	pa_array_add_data(&res, s, strlen(s) + 1);
419 	return res.data;
420 }
421 
pa_split(const char * c,const char * delimiter,const char ** state)422 static inline char *pa_split(const char *c, const char *delimiter, const char**state)
423 {
424     const char *current = *state ? *state : c;
425     size_t l;
426     if (!*current)
427         return NULL;
428     l = strcspn(current, delimiter);
429     *state = current+l;
430     if (**state)
431         (*state)++;
432     return pa_xstrndup(current, l);
433 }
434 
pa_split_spaces(const char * c,const char ** state)435 static inline char *pa_split_spaces(const char *c, const char **state)
436 {
437     const char *current = *state ? *state : c;
438     size_t l;
439     if (!*current || *c == 0)
440         return NULL;
441     current += strspn(current, PA_WHITESPACE);
442     l = strcspn(current, PA_WHITESPACE);
443     *state = current+l;
444     return pa_xstrndup(current, l);
445 }
446 
pa_split_spaces_strv(const char * s)447 static inline char **pa_split_spaces_strv(const char *s)
448 {
449     char **t, *e;
450     unsigned i = 0, n = 8;
451     const char *state = NULL;
452 
453     t = pa_xnew(char*, n);
454     while ((e = pa_split_spaces(s, &state))) {
455         t[i++] = e;
456         if (i >= n) {
457             n *= 2;
458             t = pa_xrenew(char*, t, n);
459         }
460     }
461     if (i <= 0) {
462         pa_xfree(t);
463         return NULL;
464     }
465     t[i] = NULL;
466     return t;
467 }
468 
pa_str_strip_suffix(const char * str,const char * suffix)469 static inline char* pa_str_strip_suffix(const char *str, const char *suffix)
470 {
471     size_t str_l, suf_l, prefix;
472     char *ret;
473 
474     str_l = strlen(str);
475     suf_l = strlen(suffix);
476 
477     if (str_l < suf_l)
478         return NULL;
479     prefix = str_l - suf_l;
480     if (!pa_streq(&str[prefix], suffix))
481         return NULL;
482     ret = pa_xmalloc(prefix + 1);
483     memcpy(ret, str, prefix);
484     ret[prefix] = '\0';
485     return ret;
486 }
487 
pa_split_in_place(const char * c,const char * delimiter,size_t * n,const char ** state)488 static inline const char *pa_split_in_place(const char *c, const char *delimiter, size_t *n, const char**state)
489 {
490     const char *current = *state ? *state : c;
491     size_t l;
492     if (!*current)
493         return NULL;
494     l = strcspn(current, delimiter);
495     *state = current+l;
496     if (**state)
497         (*state)++;
498     *n = l;
499     return current;
500 }
501 
pa_split_spaces_in_place(const char * c,size_t * n,const char ** state)502 static inline const char *pa_split_spaces_in_place(const char *c, size_t *n, const char **state)
503 {
504     const char *current = *state ? *state : c;
505     size_t l;
506     if (!*current || *c == 0)
507         return NULL;
508     current += strspn(current, PA_WHITESPACE);
509     l = strcspn(current, PA_WHITESPACE);
510     *state = current+l;
511     *n = l;
512     return current;
513 }
514 
pa_str_in_list_spaces(const char * haystack,const char * needle)515 static inline bool pa_str_in_list_spaces(const char *haystack, const char *needle)
516 {
517     const char *s;
518     size_t n;
519     const char *state = NULL;
520 
521     if (!haystack || !needle)
522         return false;
523 
524     while ((s = pa_split_spaces_in_place(haystack, &n, &state))) {
525         if (pa_strneq(needle, s, n))
526             return true;
527     }
528 
529     return false;
530 }
531 
pa_strip(char * s)532 static inline char *pa_strip(char *s)
533 {
534     char *e, *l = NULL;
535     s += strspn(s, PA_WHITESPACE);
536     for (e = s; *e; e++)
537         if (!strchr(PA_WHITESPACE, *e))
538             l = e;
539     if (l)
540         *(l+1) = 0;
541     else
542         *s = 0;
543     return s;
544 }
545 
pa_atod(const char * s,double * ret_d)546 static inline int pa_atod(const char *s, double *ret_d)
547 {
548 	char *x;
549 	*ret_d = strtod(s, &x);
550 	return 0;
551 }
pa_atoi(const char * s,int32_t * ret_i)552 static inline int pa_atoi(const char *s, int32_t *ret_i)
553 {
554 	*ret_i = (int32_t) atoi(s);
555 	return 0;
556 }
pa_atou(const char * s,uint32_t * ret_u)557 static inline int pa_atou(const char *s, uint32_t *ret_u)
558 {
559 	*ret_u = (uint32_t) atoi(s);
560 	return 0;
561 }
pa_atol(const char * s,long * ret_l)562 static inline int pa_atol(const char *s, long *ret_l)
563 {
564 	char *x;
565 	*ret_l = strtol(s, &x, 0);
566 	return 0;
567 }
568 
pa_parse_boolean(const char * v)569 static inline int pa_parse_boolean(const char *v)
570 {
571 	if (pa_streq(v, "1") || !strcasecmp(v, "y") || !strcasecmp(v, "t")
572 	    || !strcasecmp(v, "yes") || !strcasecmp(v, "true") || !strcasecmp(v, "on"))
573 		return 1;
574 	else if (pa_streq(v, "0") || !strcasecmp(v, "n") || !strcasecmp(v, "f")
575 	    || !strcasecmp(v, "no") || !strcasecmp(v, "false") || !strcasecmp(v, "off"))
576 		return 0;
577 	errno = EINVAL;
578 	return -1;
579 }
580 
pa_yes_no(bool b)581 static inline const char *pa_yes_no(bool b) {
582     return b ? "yes" : "no";
583 }
584 
pa_strna(const char * x)585 static inline const char *pa_strna(const char *x) {
586     return x ? x : "n/a";
587 }
588 
pa_sample_spec_init(pa_sample_spec * spec)589 static inline pa_sample_spec* pa_sample_spec_init(pa_sample_spec *spec)
590 {
591     spec->format = PA_SAMPLE_INVALID;
592     spec->rate = 0;
593     spec->channels = 0;
594     return spec;
595 }
596 
pa_readlink(const char * p)597 static inline char *pa_readlink(const char *p) {
598 #ifdef HAVE_READLINK
599     size_t l = 100;
600 
601     for (;;) {
602         char *c;
603         ssize_t n;
604 
605         c = pa_xmalloc(l);
606 
607         if ((n = readlink(p, c, l-1)) < 0) {
608             pa_xfree(c);
609             return NULL;
610         }
611 
612         if ((size_t) n < l-1) {
613             c[n] = 0;
614             return c;
615         }
616 
617         pa_xfree(c);
618         l *= 2;
619     }
620 #else
621     return NULL;
622 #endif
623 }
624 
625 #include <spa/support/i18n.h>
626 
627 extern struct spa_i18n *acp_i18n;
628 
629 #define _(String)  spa_i18n_text(acp_i18n, String)
630 #ifdef gettext_noop
631 #define N_(String) gettext_noop(String)
632 #else
633 #define N_(String) (String)
634 #endif
635 
636 #include "channelmap.h"
637 #include "volume.h"
638 
639 #ifdef __cplusplus
640 }
641 #endif
642 
643 #endif /* PULSE_COMPAT_H */
644