• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
26 enum {
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 
45 typedef 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 
56 typedef 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 
63 struct 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 
69 struct loopback_mixer {
70 	unsigned int skip:1;
71 	struct loopback_control src;
72 	struct loopback_control dst;
73 	struct loopback_mixer *next;
74 };
75 
76 struct 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 
84 struct 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 
133 struct 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 
198 extern int verbose;
199 extern int workarounds;
200 extern 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 
209 int pcmjob_init(struct loopback *loop);
210 int pcmjob_done(struct loopback *loop);
211 int pcmjob_start(struct loopback *loop);
212 int pcmjob_stop(struct loopback *loop);
213 int pcmjob_pollfds_init(struct loopback *loop, struct pollfd *fds);
214 int pcmjob_pollfds_handle(struct loopback *loop, struct pollfd *fds);
215 void pcmjob_state(struct loopback *loop);
216 
217 int control_parse_id(const char *str, snd_ctl_elem_id_t *id);
218 int control_id_match(snd_ctl_elem_id_t *id1, snd_ctl_elem_id_t *id2);
219 int control_init(struct loopback *loop);
220 int control_done(struct loopback *loop);
221 int control_event(struct loopback_handle *lhandle, snd_ctl_event_t *ev);
222