forked from abrasive/shairport
-
-
Notifications
You must be signed in to change notification settings - Fork 662
Expand file tree
/
Copy pathcommon.h
More file actions
643 lines (531 loc) · 25.9 KB
/
Copy pathcommon.h
File metadata and controls
643 lines (531 loc) · 25.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
#ifdef __cplusplus
extern "C" {
#endif
#ifndef _COMMON_H
#define _COMMON_H
#define _GNU_SOURCE
#include <sys/types.h> // for mode_t
#include <unistd.h> // for useconds_t
#include "config.h"
#include "definitions.h"
#include "mdns.h"
// service type to be offered
typedef enum {
APST_auto = 0,
APST_classic, // must be classic / airplay 1
APST_forced_classic, // must be classic / airplay 1 because no nqptp
APST_airplay2, // must be airplay 2; error if no NQPTP
} APST_t; // AirPlay Service Type
// struct sockaddr_in6 is bigger than struct sockaddr. derp
#ifdef AF_INET6
#define SOCKADDR struct sockaddr_storage
#define SAFAMILY ss_family
#else
#define SOCKADDR struct sockaddr
#define SAFAMILY sa_family
#endif
#if defined(CONFIG_CONVOLUTION)
// impulse response filter file status
typedef enum { ev_unchecked, ev_okay, ev_invalid } ir_file_evaluation;
// impulse response filter file record
typedef struct {
unsigned int samplerate; // initialized to 0, will be filter frame rate
unsigned int channels;
char *filename; // the parsed filename
} ir_file_info_t;
#endif
#if defined(CONFIG_DBUS_INTERFACE) || defined(CONFIG_MPRIS_INTERFACE)
#include <glib.h>
typedef enum {
DBT_default = 0,
DBT_system, // use the system bus
DBT_session, // use the session bus
} dbus_message_bus_t;
#endif
#define sps_extra_code_output_stalled 32768
#define sps_extra_code_output_state_cannot_make_ready 32769
// yeah/no/auto
typedef enum { YNA_AUTO = -1, YNA_NO = 0, YNA_YES = 1 } yna_type;
// yeah/no/dont-care
typedef enum { YNDK_DONT_KNOW = -1, YNDK_NO = 0, YNDK_YES = 1 } yndk_type;
typedef enum {
SS_LITTLE_ENDIAN = 0,
SS_PDP_ENDIAN,
SS_BIG_ENDIAN,
} endian_type;
typedef enum {
ST_basic = 0, // straight deletion or insertion of a frame in a 352-frame packet
ST_vernier, // interpolate from 352/1024 samples to 353/1025 or 351/1023
ST_soxr, // use libsoxr to make a 352 frame packet one frame longer or shorter
ST_auto, // use soxr if compiled for it and if the soxr_index is low enough
} stuffing_type;
typedef enum {
ST_stereo = 0,
ST_mono,
ST_reverse_stereo,
ST_left_only,
ST_right_only,
} playback_mode_type;
typedef enum {
VCP_standard = 0,
VCP_flat,
VCP_dasl_tapered,
} volume_control_profile_type;
typedef enum {
decoder_hammerton = 0,
decoder_apple_alac,
decoder_ffmpeg_alac,
} decoders_supported_type;
typedef enum {
disable_standby_off = 0,
disable_standby_auto,
disable_standby_always
} disable_standby_mode_type;
// the following enum is for the formats recognised -- currently only S16LE is recognised for input,
// so these are output only for the present
// ensure sps_format_sample_size_array and sps_format_description_string_array are in sync with
// this!
typedef enum {
SPS_FORMAT_UNKNOWN = 0,
SPS_FORMAT_S8,
SPS_FORMAT_LOWEST = SPS_FORMAT_S8,
SPS_FORMAT_U8,
SPS_FORMAT_S16_LE,
SPS_FORMAT_S16_BE,
SPS_FORMAT_S24_LE,
SPS_FORMAT_S24_BE,
SPS_FORMAT_S24_3LE,
SPS_FORMAT_S24_3BE,
SPS_FORMAT_S32_LE,
SPS_FORMAT_S32_BE,
SPS_FORMAT_HIGHEST_NATIVE = SPS_FORMAT_S32_BE,
SPS_FORMAT_S16,
SPS_FORMAT_S24,
SPS_FORMAT_S32,
SPS_FORMAT_AUTO,
SPS_FORMAT_INVALID,
} sps_format_t;
typedef enum {
SPS_RATE_UNKNOWN = 0,
SPS_RATE_5512,
SPS_RATE_LOWEST = SPS_RATE_5512,
SPS_RATE_8000,
SPS_RATE_11025,
SPS_RATE_16000,
SPS_RATE_22050,
SPS_RATE_32000,
SPS_RATE_44100,
SPS_RATE_48000,
SPS_RATE_64000,
SPS_RATE_88200,
SPS_RATE_96000,
SPS_RATE_176400,
SPS_RATE_192000,
SPS_RATE_352800,
SPS_RATE_384000,
SPS_RATE_HIGHEST = SPS_RATE_384000,
SPS_RATE_ILLEGAL,
} sps_rate_t;
// these sets omit the _UNKNOWN, _AUTO and _ILLEGAL values
#define SPS_FORMAT_SET (((1 << (SPS_FORMAT_HIGHEST_NATIVE + 1)) - 1) - (1 << SPS_FORMAT_UNKNOWN))
#define SPS_RATE_SET (((1 << (SPS_RATE_HIGHEST + 1)) - 1) - (1 << SPS_RATE_UNKNOWN))
// in SPS_CHANNEL_SET, bit 0 set means a channel set of no channels, bit 1 set means a channel set
// of 1 channel and so on to bit 31 meaning a channel set of 31 channels. We want to consider all
// possible channel sets apart from channel set 0.
#define SPS_GREATEST_CHANNEL_COUNT 31 // should be 32 to be fully in line with ALSA limits
#define SPS_CHANNEL_SET 0xFFFFFFFE // channel sets 31 to 1, but no channel set 0
// #define SPS_CHANNEL_SET (((1 << (SPS_GREATEST_CHANNEL_COUNT + 1)) - 1) - (1 << 0)) // channels 1
// to 31, not 0-based!
#ifndef CONFIG_AIRPLAY_2
#define SPS_FORMAT_NON_FFMPEG_SET SPS_FORMAT_SET
#define SPS_RATE_NON_FFMPEG_SET \
((1 << SPS_RATE_44100) | (1 << SPS_RATE_88200) | (1 << SPS_RATE_176400) | (1 << SPS_RATE_352800))
#define SPS_CHANNNEL_NON_FFMPEG_SET (1 << 2)
#endif
// up to 1048576 fps, but must be an even number
#define RATE_FROM_ENCODED_FORMAT(encoded_format) (((encoded_format >> 6) & 0x7FFFF) * 2)
#define RATE_TO_ENCODED_FORMAT(rate) (((rate / 2) & 0x7FFFF) << 6)
// up to 127 channels
#define CHANNELS_FROM_ENCODED_FORMAT(encoded_format) ((encoded_format >> 25) & 0x7F)
#define CHANNELS_TO_ENCODED_FORMAT(channels) ((channels & 0x7F) << 25)
// up to 64 different SPS_FORMATs
#define FORMAT_FROM_ENCODED_FORMAT(encoded_format) (encoded_format & 0x3F)
#define FORMAT_TO_ENCODED_FORMAT(format) (format & 0x3F)
const char *short_format_description(int32_t encoded_format);
const char *sps_format_description_string(sps_format_t format);
unsigned int sps_format_sample_size(sps_format_t format);
unsigned int sps_rate_actual_rate(sps_rate_t rate);
typedef struct {
double missing_port_dacp_scan_interval_seconds; // if no DACP port number can be found, check at
// these intervals
double resend_control_first_check_time; // wait this long before asking for a missing packet to be
// resent
double resend_control_check_interval_time; // wait this long between making requests
double resend_control_last_check_time; // if the packet is missing this close to the time of use,
// give up
int get_plist_metadata; // set to non-zero to get richer plist metadata
pthread_mutex_t lock;
config_t *cfg;
int endianness;
double airplay_volume; // stored here for reloading when necessary
double default_airplay_volume;
char *appName; // normally the app is called shairport-syn, but it may be symlinked
char *password;
char *service_name; // the name for the shairport service, e.g. "Shairport Sync Version %v running
// on host %h"
#ifdef CONFIG_PULSEAUDIO
char *pa_server; // the pulseaudio server address that Shairport Sync will play on.
char *pa_application_name; // the name under which Shairport Sync shows up as an "Application" in
// the Sound Preferences in most desktop Linuxes.
// Defaults to "Shairport Sync". Shairport Sync must be playing to see it.
char *pa_sink; // the name (or id) of the sink that Shairport Sync will play on.
#endif
#ifdef CONFIG_PIPEWIRE
char *pw_application_name; // the name under which Shairport Sync shows up as an "Application" in
// the Sound Preferences in most desktop Linuxes.
// Defaults to "Shairport Sync".
char *pw_node_name; // defaults to the application's name, usually "shairport-sync".
char *pw_sink_target; // leave this unset if you don't want to change the sink_target.
#endif
#ifdef CONFIG_METADATA
int metadata_enabled;
char *metadata_pipename;
char *metadata_sockaddr;
int metadata_sockport;
size_t metadata_sockmsglength;
int get_coverart;
double metadata_progress_interval; // 0 means no progress reports
#endif
#ifdef CONFIG_MQTT
int mqtt_enabled;
char *mqtt_hostname;
int mqtt_port;
char *mqtt_username;
char *mqtt_password;
char *mqtt_capath;
char *mqtt_cafile;
char *mqtt_certfile;
char *mqtt_keyfile;
char *mqtt_topic;
int mqtt_publish_raw;
int mqtt_publish_parsed;
int mqtt_publish_cover;
int mqtt_publish_retain;
int mqtt_enable_remote;
int mqtt_enable_autodiscovery;
char *mqtt_autodiscovery_prefix;
char *mqtt_empty_payload_substitute;
#endif
uint8_t ap1_prefix[6];
uint8_t hw_addr[8]; // only needs 6 but 8 is handy when converting this to a number
int port;
int udp_port_base;
int udp_port_range;
int ignore_volume_control;
int volume_max_db_set; // set to 1 if a maximum volume db has been set
int volume_max_db;
int no_sync; // disable synchronisation, even if it's available
int no_mmap; // disable use of mmap-based output, even if it's available
double resync_threshold; // if it gets out of whack by more than this number of seconds, do a
// resync. if zero, never do a resync.
int allow_session_interruption;
int timeout; // while in play mode, exit if no packets of audio come in for more than this number
// of seconds . Zero means never exit.
int dont_check_timeout; // this is used to maintain backward compatibility with the old -t option
// behaviour; only set by -t 0, cleared by everything else
char *output_name;
audio_output *output;
char *mdns_name;
mdns_backend *mdns;
int buffer_start_fill;
uint32_t userSuppliedLatency; // overrides all other latencies -- use with caution
uint32_t fixedLatencyOffset; // add this to all automatic latencies supplied to get the actual
// total latency
// the total latency will be limited to the min and max-latency values, if supplied
#ifdef CONFIG_LIBDAEMON
int daemonise;
int daemonise_store_pid; // don't try to save a PID file
char *piddir;
char *computed_piddir; // the actual pid directory to create, if any
char *pidfile;
#endif
int log_fd; // file descriptor of the file or pipe to log stuff to.
char *log_file_path; // path to file or pipe to log to, if any
int logOutputLevel; // log output level
int debugger_show_elapsed_time; // in the debug message, display the time since startup
int debugger_show_relative_time; // in the debug message, display the time since the last one
int debugger_show_file_and_line; // in the debug message, display the filename and line number
int statistics_requested, use_negotiated_latencies;
playback_mode_type playback_mode;
char *cmd_start, *cmd_stop, *cmd_set_volume, *cmd_unfixable;
char *cmd_active_start, *cmd_active_stop;
int cmd_blocking, cmd_start_returns_output;
double tolerance; // allow this much drift before attempting to correct it
stuffing_type packet_stuffing;
int soxr_delay_index;
int soxr_delay_threshold; // the soxr delay must be less or equal to this for soxr interpolation
// to be enabled under the auto setting
int decoders_supported;
int decoder_in_use;
char *configfile;
char *regtype; // The regtype is the service type followed by the protocol, separated by a dot, by
// default “_raop._tcp.” for AirPlay 1.
char *regtype2; // The regtype is the service type followed by the protocol, separated by a dot,
// by default “_raop._tcp.” for AirPlay 2.
char *interface; // a string containg the interface name, or NULL if nothing specified
int interface_index; // only valid if the interface string is non-NULL
double audio_backend_buffer_desired_length; // this will be the length in seconds of the
// audio backend buffer -- the DAC buffer for ALSA
double audio_backend_buffer_interpolation_threshold_in_seconds; // below this, soxr interpolation
// will not occur -- it'll be
// basic interpolation instead.
double audio_decoded_buffer_desired_length; // the length of the buffer of fully decoded audio
// prior to being sent to the output device
double disable_standby_mode_silence_threshold; // below this, silence will be added to the output
// buffer
double disable_standby_mode_silence_scan_interval; // check the threshold this often
double audio_backend_latency_offset; // this will be the offset in seconds to compensate for any
// fixed latency there might be in the audio path
int audio_backend_silent_lead_in_time_auto; // true if the lead-in time should be from as soon as
// packets are received
double audio_backend_silent_lead_in_time; // the length of the silence that should precede a play.
uint32_t minimum_free_buffer_headroom; // when effective latency is calculated, ensure this number
// of buffers are unallocated
double active_state_timeout; // the amount of time from when play ends to when the system leaves
// into the "active" mode.
uint32_t volume_range_db; // the range, in dB, from max dB to min dB. Zero means use the mixer's
// native range.
int volume_range_hw_priority; // when extending the volume range by combining sw and hw
// attenuators, lowering the volume, use all the hw attenuation
// before using
// sw attenuation
volume_control_profile_type volume_control_profile;
int output_format_auto_requested; // true if the configuration requests auto configuration
int output_rate_auto_requested; // true if the configuration requests auto configuration
uint32_t current_output_configuration;
// these are the formats/rate and channel configurations permitted by the settings or defaults
uint32_t format_set;
uint32_t rate_set;
uint32_t channel_set;
#ifdef CONFIG_CONVOLUTION
int convolution_enabled;
unsigned int convolution_ir_file_count;
ir_file_info_t *convolution_ir_files; // NULL or an array of information about all the impulse
// response files loaded
int convolution_ir_files_updated; // set to true if the convolution_ir_files are changed. Cleared
// when the convolver has been initialised
unsigned int convolution_threads; // number of threads in the convolver thread pool
float convolution_gain;
double convolution_max_length_in_seconds;
#endif
int loudness_enabled;
float loudness_reference_volume_db;
int alsa_use_hardware_mute;
double alsa_maximum_stall_time;
disable_standby_mode_type disable_standby_mode;
volatile int keep_dac_busy;
yna_type use_precision_timing; // defaults to no
#ifdef CONFIG_METADATA_HUB
char *cover_art_cache_dir;
int retain_coverart;
int scan_interval_when_active; // number of seconds between DACP server scans when playing
// something (1)
int scan_interval_when_inactive; // number of seconds between DACP server scans playing nothing
// (3)
int scan_max_bad_response_count; // number of successive bad results to ignore before giving up
// (10)
int scan_max_inactive_count; // number of scans to do before stopping if not made active again
// (about 15 minutes worth)
#endif
int disable_resend_requests; // set this to stop resend request being made for missing packets
double diagnostic_drop_packet_fraction; // pseudo randomly drop this fraction of packets, for
// debugging. Currently audio packets only...
#ifdef CONFIG_JACK
char *jack_client_name;
char *jack_autoconnect_pattern;
#ifdef CONFIG_SOXR
int jack_soxr_resample_quality;
#endif
#endif
void *gradients; // a linked list of the clock gradients discovered for all DACP IDs
// can't use IP numbers as they might be given to different devices
// can't get hold of MAC addresses.
// can't define the null linked list struct here
char *firmware_version;
// use these in information requests
char *model;
char *srcvers;
char *osvers;
#ifdef CONFIG_AIRPLAY_2
uint64_t airplay_features;
uint32_t airplay_statusflags;
char *airplay_fex; // a base64-encoded version of the airplay_features in little-endian form
char *airplay_device_id; // for the Bonjour advertisement and the GETINFO PList
char *airplay_pi; // UUID in the Bonjour advertisement and the GETINFO Plist
char *airplay_pgid; // UUID in the txtAirPlay data sent on the event channel
char *airplay_psi; // type 4 fixed UUID
uint8_t airplay_pk[32]; // public key
char *pk_string;
char *nqptp_shared_memory_interface_name; // client name for nqptp service
int enable_HK_Access_Control; // true if the device is part of an Apple Home
#endif
APST_t service_type; // APST_auto, APST_classic, APST_forced_classic, APST_airplay2
int unfixable_error_reported; // only report once.
uint64_t eight_channel_layout; // non-zero means enabled and is a channel layout
uint64_t six_channel_layout; // non-zero means enabled and is a channel layout
int mixdown_enable;
uint64_t mixdown_channel_layout; // if mixdown_enable is true, 0 signifies auto, based on number
// of channels
int output_channel_mapping_enable; // 0 means off, non-zero means on. If on and
// output_channel_map_size is 0, use the device's channel map
const char *output_channel_map[8]; // names of the output channels
unsigned int output_channel_map_size; // number of output channels
#if defined(CONFIG_DBUS_INTERFACE) || defined(CONFIG_MPRIS_INTERFACE)
dbus_message_bus_t dbus_default_message_bus;
#if defined(CONFIG_DBUS_INTERFACE)
dbus_message_bus_t dbus_service_bus_type;
#endif
#if defined(CONFIG_MPRIS_INTERFACE)
dbus_message_bus_t mpris_service_bus_type;
#endif
#endif
} shairport_cfg;
uint32_t nctohl(const uint8_t *p); // read 4 characters from *p and do ntohl on them
uint16_t nctohs(const uint8_t *p); // read 2 characters from *p and do ntohs on them
uint64_t nctoh64(const uint8_t *p); // read 8 characters from *p to a uint64_t
int try_to_open_pipe_for_writing(
const char *pathname); // open it without blocking if it's not hooked up
// based on http://burtleburtle.net/bob/rand/smallprng.html
void r64init(uint64_t seed);
uint64_t r64u();
int64_t r64i();
// if you are breaking in to a session, you need to avoid the ports of the current session
// if you are law-abiding, then you can reuse the ports.
// so, you can reset the free UDP ports minder when you're legit, and leave it otherwise
// the downside of using different ports each time is that it might make the firewall
// rules a bit more complex, as they need to allow more than the minimum three ports.
// a range of 10 is suggested anyway
void resetFreeUDPPort();
uint16_t nextFreeUDPPort();
extern volatile int debuglev;
// Thanks to https://stackoverflow.com/a/1597129 for the inspiration for this identifier generation
#define MAKEUNIQUEID2(x, y) x##y
#define MADEID(x, y) MAKEUNIQUEID2(x, y)
// do X once, and never again until the app is restarted
#define once(X) \
static int MADEID(once_flag_, __LINE__) = 0; \
if (MADEID(once_flag_, __LINE__) == 0) { \
X; \
MADEID(once_flag_, __LINE__) = 1; \
}
void getErrorText(char *destinationString, size_t destinationStringLength);
uint8_t *base64_dec(char *input, int *outlen);
char *base64_enc(uint8_t *input, int length);
char *base64_encode_so(const unsigned char *data, size_t input_length, char *encoded_data,
size_t *output_length);
#define RSA_MODE_AUTH (0)
#define RSA_MODE_KEY (1)
uint8_t *rsa_apply(uint8_t *input, int inlen, int *outlen, int mode);
// given a volume (0 to -30) and high and low attenuations in dB*100 (e.g. 0 to -6000 for 0 to -60
// dB), return an attenuation depending on a linear interpolation along the range
double flat_vol2attn(double vol, long max_db, long min_db);
// The intention behind dasl_tapered is that a given percentage change in volume should result in
// the same percentage change in perceived loudness. For instance, doubling the volume level should
// result in doubling the perceived loudness. With the range of AirPlay volume being from -30 to 0,
// doubling the volume from -22.5 to -15 results in an increase of 10 dB. Similarly, doubling the
// volume from -15 to 0 results in an increase of 10 dB. For compatibility with mixers having a
// restricted attenuation range (e.g. 30 dB), "dasl_tapered" will switch to a flat profile at low
// AirPlay volumes.
double dasl_tapered_vol2attn(double vol, long max_db, long min_db);
// given a volume (0 to -30) and high and low attenuations in dB*100 (e.g. 0 to -6000 for 0 to -60
// dB), return an attenuation depending on the transfer function
double vol2attn(double vol, long max_db, long min_db);
// return a time in nanoseconds
#ifdef COMPILE_FOR_LINUX_AND_FREEBSD_AND_CYGWIN_AND_OPENBSD
// Not defined for macOS
uint64_t get_realtime_in_ns(void);
#endif
uint64_t get_absolute_time_in_ns(void); // monotonic_raw or monotonic
uint64_t get_monotonic_time_in_ns(void); // NTP-disciplined
// time at startup for debugging timing
// extern uint64_t ns_time_at_startup, ns_time_at_last_debug_message;
// this is for reading an unsigned 32 bit number, such as an RTP timestamp
uint32_t uatoi(const char *nptr);
extern shairport_cfg config;
extern config_t config_file_stuff;
extern uint64_t minimum_dac_queue_size;
int config_lookup_non_empty_string(const config_t *cfg, const char *path, const char **value);
int config_set_lookup_bool(config_t *cfg, const char *where, int *dst);
int check_string_or_list_setting(config_setting_t *setting, const char *item);
int check_int_or_list_setting(config_setting_t *setting, const int item);
unsigned int config_get_string_settings_as_string_array(config_setting_t *setting,
const char ***result);
unsigned int config_get_int_settings_as_int_array(config_setting_t *setting, int **result);
APST_t string_to_service_type(const char *parameter, const char *setting_name);
void service_type_to_string(APST_t service_type, char *string_space);
void command_start(void);
void command_stop(void);
void command_execute(const char *command, const char *extra_argument, const int block);
void command_set_volume(double volume);
int mkpath(const char *path, mode_t mode);
#define pthread_mutex_lock_and_cleanup_push(mu) \
if (pthread_mutex_lock(mu) == 0) \
pthread_cleanup_push(mutex_unlock, (void *)mu)
int do_pthread_setname(pthread_t *restrict thread, const char *format, ...);
int named_pthread_create(pthread_t *restrict thread, const pthread_attr_t *restrict attr,
void *(*start_routine)(void *), void *restrict arg, const char *format,
...);
int named_pthread_create_with_priority(pthread_t *thread, int priority,
void *(*start_routine)(void *), void *arg,
const char *format, ...);
extern pthread_mutex_t r64_mutex;
#define r64_lock pthread_mutex_lock(&r64_mutex)
#define r64_unlock pthread_mutex_unlock(&r64_mutex)
char *get_version_string(); // mallocs a string space -- remember to free it afterwards
int64_t generate_zero_frames(char *outp, size_t number_of_frames, int with_dither,
int64_t random_number_in, uint32_t encoded_output_format);
int string_update_with_size(char **str, int *flag, char *s, size_t len);
// from https://stackoverflow.com/questions/13663617/memdup-function-in-c, with thanks
void *memdup(const void *mem, size_t size);
int bind_socket_and_port(int type, int ip_family, const char *self_ip_address, uint32_t scope_id,
uint16_t *port, int *sock);
uint16_t bind_UDP_port(int ip_family, const char *self_ip_address, uint32_t scope_id, int *sock);
// for pthread_push and pop
// careful with the difference between cleanup and unlock!
void malloc_cleanup(void *arg);
void socket_cleanup(void *arg);
void mutex_unlock(void *arg);
void mutex_cleanup(void *arg);
void rwlock_unlock(void *arg);
void cv_cleanup(void *arg);
void thread_cleanup(void *arg);
#ifdef CONFIG_AIRPLAY_2
void plist_cleanup(void *arg);
#endif
char *debug_malloc_hex_cstring(void *packet, size_t nread);
// from https://stackoverflow.com/questions/13663617/memdup-function-in-c, with thanks
// allocates memory and copies the content to it
// analogous to strndup;
void *memdup(const void *mem, size_t size);
int get_device_id(uint8_t *id, int int_length);
char *bnprintf(char *buffer, ssize_t max_bytes, const char *format, ...);
#ifdef CONFIG_CONVOLUTION
/* Parse comma-separated filenames with optional quotes from the input string
* Returns array of ir_file_info_t structs (caller must free both array and filenames)
* count is set to number of filenames found
* Returns NULL on error
*/
ir_file_info_t *parse_ir_filenames(const char *input, unsigned int *file_count);
// Access: files[i].filename, files[i].rate, files[i].evaluation
/* Do a quick sanity check on the files -- see if they can be opened as sound files */
void sanity_check_ir_files(const int option_print_level, ir_file_info_t *files, unsigned int count);
/* Free the array returned by parse_filenames */
void free_ir_filenames(ir_file_info_t *files, unsigned int file_count);
#endif
#ifdef CONFIG_USE_GIT_VERSION_STRING
extern char git_version_string[];
#endif
#endif // _COMMON_H
#ifdef __cplusplus
}
#endif