1/*
2 *  A simple PCM loopback utility
3 *  Copyright (c) 2010 by Jaroslav Kysela <perex@perex.cz>
4 *
5 *   This program is free software; you can redistribute it and/or modify
6 *   it under the terms of the GNU General Public License as published by
7 *   the Free Software Foundation; either version 2 of the License, or
8 *   (at your option) any later version.
9 *
10 *   This program is distributed in the hope that it will be useful,
11 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
12 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 *   GNU General Public License for more details.
14 *
15 *   You should have received a copy of the GNU General Public License
16 *   along with this program; if not, write to the Free Software
17 *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
18 *
19 */
20
21#include "aconfig.h"
22#ifdef HAVE_SAMPLERATE_H
23#define USE_SAMPLERATE
24#include <samplerate.h>
25#else
26enum {
27	SRC_SINC_BEST_QUALITY	= 0,
28	SRC_SINC_MEDIUM_QUALITY	= 1,
29	SRC_SINC_FASTEST	= 2,
30	SRC_ZERO_ORDER_HOLD	= 3,
31	SRC_LINEAR		= 4
32};
33#endif
34
35#define MAX_ARGS	128
36#define MAX_MIXERS	64
37
38#if 0
39#define FILE_PWRITE "/tmp/alsaloop.praw"
40#define FILE_CWRITE "/tmp/alsaloop.craw"
41#endif
42
43#define WORKAROUND_SERIALOPEN	(1<<0)
44
45typedef enum _sync_type {
46	SYNC_TYPE_NONE = 0,
47	SYNC_TYPE_SIMPLE,	/* add or remove samples */
48	SYNC_TYPE_CAPTRATESHIFT,
49	SYNC_TYPE_PLAYRATESHIFT,
50	SYNC_TYPE_SAMPLERATE,
51	SYNC_TYPE_AUTO,		/* order: CAPTRATESHIFT, PLAYRATESHIFT, */
52				/*        SAMPLERATE, SIMPLE */
53	SYNC_TYPE_LAST = SYNC_TYPE_AUTO
54} sync_type_t;
55
56typedef enum _slave_type {
57	SLAVE_TYPE_AUTO = 0,
58	SLAVE_TYPE_ON = 1,
59	SLAVE_TYPE_OFF = 2,
60	SLAVE_TYPE_LAST = SLAVE_TYPE_OFF
61} slave_type_t;
62
63struct loopback_control {
64	snd_ctl_elem_id_t *id;
65	snd_ctl_elem_info_t *info;
66	snd_ctl_elem_value_t *value;
67};
68
69struct loopback_mixer {
70	unsigned int skip:1;
71	struct loopback_control src;
72	struct loopback_control dst;
73	struct loopback_mixer *next;
74};
75
76struct loopback_ossmixer {
77	unsigned int skip:1;
78	const char *alsa_id;
79	int alsa_index;
80	const char *oss_id;
81	struct loopback_ossmixer *next;
82};
83
84struct loopback_handle {
85	struct loopback *loopback;
86	char *device;
87	char *ctldev;
88	char *id;
89	int card_number;
90	snd_pcm_t *handle;
91	snd_pcm_access_t access;
92	snd_pcm_format_t format;
93	unsigned int rate;
94	unsigned int rate_req;
95	unsigned int channels;
96	unsigned int buffer_size;
97	unsigned int period_size;
98	snd_pcm_uframes_t avail_min;
99	unsigned int buffer_size_req;
100	unsigned int period_size_req;
101	unsigned int frame_size;
102	unsigned int resample:1;	/* do resample */
103	unsigned int nblock:1;		/* do block (period size) transfers */
104	unsigned int xrun_pending:1;
105	unsigned int pollfd_count;
106	/* I/O job */
107	char *buf;			/* I/O buffer */
108	snd_pcm_uframes_t buf_pos;	/* I/O position */
109	snd_pcm_uframes_t buf_count;	/* filled samples */
110	snd_pcm_uframes_t buf_size;	/* buffer size in frames */
111	snd_pcm_uframes_t buf_over;	/* capture buffer overflow */
112	int stall;
113	/* statistics */
114	snd_pcm_uframes_t max;
115	unsigned long long counter;
116	unsigned long sync_point;	/* in samples */
117	snd_pcm_sframes_t last_delay;
118	double pitch;
119	snd_pcm_uframes_t total_queued;
120	/* control */
121	snd_ctl_t *ctl;
122	unsigned int ctl_pollfd_count;
123	snd_ctl_elem_value_t *ctl_notify;
124	snd_ctl_elem_value_t *ctl_rate_shift;
125	snd_ctl_elem_value_t *ctl_pitch;
126	snd_ctl_elem_value_t *ctl_active;
127	snd_ctl_elem_value_t *ctl_format;
128	snd_ctl_elem_value_t *ctl_rate;
129	snd_ctl_elem_value_t *ctl_channels;
130	char *prateshift_name; /* ascii name for the playback rate shift ctl elem */
131};
132
133struct loopback {
134	char *id;
135	struct loopback_handle *capt;
136	struct loopback_handle *play;
137	snd_pcm_uframes_t latency;	/* final latency in frames */
138	unsigned int latency_req;	/* in frames */
139	unsigned int latency_reqtime;	/* in us */
140	unsigned long loop_time;	/* ~0 = unlimited (in seconds) */
141	unsigned long long loop_limit;	/* ~0 = unlimited (in frames) */
142	snd_output_t *output;
143	snd_output_t *state;
144	int pollfd_count;
145	int active_pollfd_count;
146	unsigned int linked:1;		/* linked streams */
147	unsigned int reinit:1;
148	unsigned int running:1;
149	unsigned int stop_pending:1;
150	snd_pcm_uframes_t stop_count;
151	sync_type_t sync;		/* type of sync */
152	slave_type_t slave;
153	int thread;			/* thread number */
154	unsigned int wake;
155	/* statistics */
156	double pitch;
157	double pitch_delta;
158	snd_pcm_sframes_t pitch_diff;
159	snd_pcm_sframes_t pitch_diff_min;
160	snd_pcm_sframes_t pitch_diff_max;
161	unsigned int total_queued_count;
162	snd_timestamp_t tstamp_start;
163	snd_timestamp_t tstamp_end;
164	/* xrun profiling */
165	unsigned int xrun:1;		/* xrun profiling */
166	snd_timestamp_t xrun_last_update;
167	snd_timestamp_t xrun_last_wake0;
168	snd_timestamp_t xrun_last_wake;
169	snd_timestamp_t xrun_last_check0;
170	snd_timestamp_t xrun_last_check;
171	snd_pcm_sframes_t xrun_last_pdelay;
172	snd_pcm_sframes_t xrun_last_cdelay;
173	snd_pcm_uframes_t xrun_buf_pcount;
174	snd_pcm_uframes_t xrun_buf_ccount;
175	unsigned int xrun_out_frames;
176	long xrun_max_proctime;
177	double xrun_max_missing;
178	/* control mixer */
179	struct loopback_mixer *controls;
180	struct loopback_ossmixer *oss_controls;
181	/* sample rate */
182	unsigned int use_samplerate:1;
183#ifdef USE_SAMPLERATE
184	unsigned int src_enable:1;
185	int src_converter_type;
186	SRC_STATE *src_state;
187	SRC_DATA src_data;
188	unsigned int src_out_frames;
189#endif
190#ifdef FILE_CWRITE
191	FILE *cfile;
192#endif
193#ifdef FILE_PWRITE
194	FILE *pfile;
195#endif
196};
197
198extern int verbose;
199extern int workarounds;
200extern int use_syslog;
201
202#define logit(priority, fmt, args...) do {		\
203	if (use_syslog)					\
204		syslog(priority, fmt, ##args);		\
205	else						\
206		fprintf(stderr, fmt, ##args);		\
207} while (0)
208
209int pcmjob_init(struct loopback *loop);
210int pcmjob_done(struct loopback *loop);
211int pcmjob_start(struct loopback *loop);
212int pcmjob_stop(struct loopback *loop);
213int pcmjob_pollfds_init(struct loopback *loop, struct pollfd *fds);
214int pcmjob_pollfds_handle(struct loopback *loop, struct pollfd *fds);
215void pcmjob_state(struct loopback *loop);
216
217int control_parse_id(const char *str, snd_ctl_elem_id_t *id);
218int control_id_match(snd_ctl_elem_id_t *id1, snd_ctl_elem_id_t *id2);
219int control_init(struct loopback *loop);
220int control_done(struct loopback *loop);
221int control_event(struct loopback_handle *lhandle, snd_ctl_event_t *ev);
222