2 * PCM - Direct Stream Mixing
3 * Copyright (c) 2003 by Jaroslav Kysela <perex@perex.cz>
6 * This library is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU Lesser General Public License as
8 * published by the Free Software Foundation; either version 2.1 of
9 * the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include "pcm_local.h"
24 #define DIRECT_IPC_SEMS 1
25 #define DIRECT_IPC_SEM_CLIENT 0
27 typedef void (mix_areas_t)(unsigned int size,
28 volatile void *dst, void *src,
29 volatile signed int *sum, size_t dst_step,
30 size_t src_step, size_t sum_step);
32 typedef void (mix_areas_16_t)(unsigned int size,
33 volatile signed short *dst, signed short *src,
34 volatile signed int *sum, size_t dst_step,
35 size_t src_step, size_t sum_step);
37 typedef void (mix_areas_32_t)(unsigned int size,
38 volatile signed int *dst, signed int *src,
39 volatile signed int *sum, size_t dst_step,
40 size_t src_step, size_t sum_step);
42 typedef void (mix_areas_24_t)(unsigned int size,
43 volatile unsigned char *dst, unsigned char *src,
44 volatile signed int *sum, size_t dst_step,
45 size_t src_step, size_t sum_step);
47 typedef void (mix_areas_u8_t)(unsigned int size,
48 volatile unsigned char *dst, unsigned char *src,
49 volatile signed int *sum, size_t dst_step,
50 size_t src_step, size_t sum_step);
53 snd_pcm_format_t format;
58 snd_pcm_sframes_t period_size;
59 snd_pcm_sframes_t buffer_size;
63 /* shared among direct plugin clients - be careful to be 32/64bit compatible! */
65 unsigned int magic; /* magic number */
66 char socket_name[256]; /* name of communication socket */
67 snd_pcm_type_t type; /* PCM type (currently only hw) */
72 snd_interval_t buffer_size;
73 snd_interval_t buffer_time;
74 snd_interval_t period_size;
75 snd_interval_t period_time;
76 snd_interval_t periods;
79 /* copied to slave PCMs */
80 snd_pcm_access_t access;
81 snd_pcm_format_t format;
82 snd_pcm_subformat_t subformat;
83 unsigned int channels;
85 unsigned int period_size;
86 unsigned int period_time;
87 snd_interval_t periods;
88 unsigned int monotonic;
89 snd_pcm_tstamp_t tstamp_mode;
90 unsigned int period_step;
91 unsigned int sleep_min; /* not used */
92 unsigned int avail_min;
93 unsigned int start_threshold;
94 unsigned int stop_threshold;
95 unsigned int silence_threshold;
96 unsigned int silence_size;
97 unsigned int xfer_align; /* not used */
98 unsigned long long boundary;
101 unsigned int rate_num;
102 unsigned int rate_den;
103 unsigned int hw_flags;
104 unsigned int fifo_size;
105 unsigned int buffer_size;
106 snd_interval_t buffer_time;
107 unsigned int sample_bits;
108 unsigned int frame_bits;
112 unsigned long long chn_mask;
115 } snd_pcm_direct_share_t;
117 typedef struct snd_pcm_direct snd_pcm_direct_t;
119 struct snd_pcm_direct {
120 snd_pcm_type_t type; /* type (dmix, dsnoop, dshare) */
121 key_t ipc_key; /* IPC key for semaphore and memory */
122 mode_t ipc_perm; /* IPC socket permissions */
123 int ipc_gid; /* IPC socket gid */
124 int semid; /* IPC global semaphore identification */
125 int shmid; /* IPC global shared memory identification */
126 snd_pcm_direct_share_t *shmptr; /* pointer to shared memory area */
127 snd_pcm_t *spcm; /* slave PCM handle */
128 snd_pcm_uframes_t appl_ptr;
129 snd_pcm_uframes_t last_appl_ptr;
130 snd_pcm_uframes_t hw_ptr;
131 snd_pcm_uframes_t avail_max;
132 snd_pcm_uframes_t slave_appl_ptr;
133 snd_pcm_uframes_t slave_hw_ptr;
134 snd_pcm_uframes_t slave_period_size;
135 snd_pcm_uframes_t slave_buffer_size;
136 snd_pcm_uframes_t slave_boundary;
137 int (*sync_ptr)(snd_pcm_t *pcm);
138 snd_pcm_state_t state;
139 snd_htimestamp_t trigger_tstamp;
140 snd_htimestamp_t update_tstamp;
142 int comm_fd; /* communication file descriptor (socket) */
143 int hw_fd; /* hardware file descriptor */
144 struct pollfd timer_fd;
147 int timer_need_poll: 1;
148 unsigned int timer_events;
151 snd_timer_t *timer; /* timer used as poll_fd */
152 int interleaved; /* we have interleaved buffer */
153 int slowptr; /* use slow but more precise ptr updates */
154 int max_periods; /* max periods (-1 = fixed periods, 0 = max buffer size) */
155 unsigned int channels; /* client's channels */
156 unsigned int *bindings;
159 int shmid_sum; /* IPC global sum ring buffer memory identification */
160 signed int *sum_buffer; /* shared sum buffer */
161 mix_areas_16_t *mix_areas_16;
162 mix_areas_32_t *mix_areas_32;
163 mix_areas_24_t *mix_areas_24;
164 mix_areas_u8_t *mix_areas_u8;
165 mix_areas_16_t *remix_areas_16;
166 mix_areas_32_t *remix_areas_32;
167 mix_areas_24_t *remix_areas_24;
168 mix_areas_u8_t *remix_areas_u8;
173 unsigned long long chn_mask;
176 void (*server_free)(snd_pcm_direct_t *direct);
179 /* make local functions really local */
180 #define snd_pcm_direct_semaphore_create_or_connect \
181 snd1_pcm_direct_semaphore_create_or_connect
182 #define snd_pcm_direct_shm_create_or_connect \
183 snd1_pcm_direct_shm_create_or_connect
184 #define snd_pcm_direct_shm_discard \
185 snd1_pcm_direct_shm_discard
186 #define snd_pcm_direct_server_create \
187 snd1_pcm_direct_server_create
188 #define snd_pcm_direct_server_discard \
189 snd1_pcm_direct_server_discard
190 #define snd_pcm_direct_client_connect \
191 snd1_pcm_direct_client_connect
192 #define snd_pcm_direct_client_discard \
193 snd1_pcm_direct_client_discard
194 #define snd_pcm_direct_initialize_slave \
195 snd1_pcm_direct_initialize_slave
196 #define snd_pcm_direct_initialize_secondary_slave \
197 snd1_pcm_direct_initialize_secondary_slave
198 #define snd_pcm_direct_initialize_poll_fd \
199 snd1_pcm_direct_initialize_poll_fd
200 #define snd_pcm_direct_check_interleave \
201 snd1_pcm_direct_check_interleave
202 #define snd_pcm_direct_parse_bindings \
203 snd1_pcm_direct_parse_bindings
204 #define snd_pcm_direct_nonblock \
205 snd1_pcm_direct_nonblock
206 #define snd_pcm_direct_async \
207 snd1_pcm_direct_async
208 #define snd_pcm_direct_poll_revents \
209 snd1_pcm_direct_poll_revents
210 #define snd_pcm_direct_info \
212 #define snd_pcm_direct_hw_refine \
213 snd1_pcm_direct_hw_refine
214 #define snd_pcm_direct_hw_params \
215 snd1_pcm_direct_hw_params
216 #define snd_pcm_direct_hw_free \
217 snd1_pcm_direct_hw_free
218 #define snd_pcm_direct_sw_params \
219 snd1_pcm_direct_sw_params
220 #define snd_pcm_direct_channel_info \
221 snd1_pcm_direct_channel_info
222 #define snd_pcm_direct_mmap \
224 #define snd_pcm_direct_munmap \
225 snd1_pcm_direct_munmap
226 #define snd_pcm_direct_resume \
227 snd1_pcm_direct_resume
228 #define snd_pcm_direct_timer_stop \
229 snd1_pcm_direct_timer_stop
230 #define snd_pcm_direct_clear_timer_queue \
231 snd1_pcm_direct_clear_timer_queue
232 #define snd_pcm_direct_set_timer_params \
233 snd1_pcm_direct_set_timer_params
234 #define snd_pcm_direct_open_secondary_client \
235 snd1_pcm_direct_open_secondary_client
236 #define snd_pcm_direct_parse_open_conf \
237 snd1_pcm_direct_parse_open_conf
239 int snd_pcm_direct_semaphore_create_or_connect(snd_pcm_direct_t *dmix);
241 static inline int snd_pcm_direct_semaphore_discard(snd_pcm_direct_t *dmix)
243 if (dmix->semid >= 0) {
244 if (semctl(dmix->semid, 0, IPC_RMID, NULL) < 0)
251 static inline int snd_pcm_direct_semaphore_down(snd_pcm_direct_t *dmix, int sem_num)
253 struct sembuf op[2] = { { sem_num, 0, 0 }, { sem_num, 1, SEM_UNDO } };
254 return semop(dmix->semid, op, 2);
257 static inline int snd_pcm_direct_semaphore_up(snd_pcm_direct_t *dmix, int sem_num)
259 struct sembuf op = { sem_num, -1, SEM_UNDO | IPC_NOWAIT };
260 return semop(dmix->semid, &op, 1);
263 int snd_pcm_direct_shm_create_or_connect(snd_pcm_direct_t *dmix);
264 int snd_pcm_direct_shm_discard(snd_pcm_direct_t *dmix);
265 int snd_pcm_direct_server_create(snd_pcm_direct_t *dmix);
266 int snd_pcm_direct_server_discard(snd_pcm_direct_t *dmix);
267 int snd_pcm_direct_client_connect(snd_pcm_direct_t *dmix);
268 int snd_pcm_direct_client_discard(snd_pcm_direct_t *dmix);
269 int snd_pcm_direct_initialize_slave(snd_pcm_direct_t *dmix, snd_pcm_t *spcm, struct slave_params *params);
270 int snd_pcm_direct_initialize_secondary_slave(snd_pcm_direct_t *dmix, snd_pcm_t *spcm, struct slave_params *params);
271 int snd_pcm_direct_initialize_poll_fd(snd_pcm_direct_t *dmix);
272 int snd_pcm_direct_check_interleave(snd_pcm_direct_t *dmix, snd_pcm_t *pcm);
273 int snd_pcm_direct_parse_bindings(snd_pcm_direct_t *dmix,
274 struct slave_params *params,
276 int snd_pcm_direct_nonblock(snd_pcm_t *pcm, int nonblock);
277 int snd_pcm_direct_async(snd_pcm_t *pcm, int sig, pid_t pid);
278 int snd_pcm_direct_poll_revents(snd_pcm_t *pcm, struct pollfd *pfds, unsigned int nfds, unsigned short *revents);
279 int snd_pcm_direct_info(snd_pcm_t *pcm, snd_pcm_info_t * info);
280 int snd_pcm_direct_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params);
281 int snd_pcm_direct_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params);
282 int snd_pcm_direct_hw_free(snd_pcm_t *pcm);
283 int snd_pcm_direct_sw_params(snd_pcm_t *pcm, snd_pcm_sw_params_t * params);
284 int snd_pcm_direct_channel_info(snd_pcm_t *pcm, snd_pcm_channel_info_t * info);
285 int snd_pcm_direct_mmap(snd_pcm_t *pcm);
286 int snd_pcm_direct_munmap(snd_pcm_t *pcm);
287 int snd_pcm_direct_resume(snd_pcm_t *pcm);
288 int snd_pcm_direct_timer_stop(snd_pcm_direct_t *dmix);
289 void snd_pcm_direct_clear_timer_queue(snd_pcm_direct_t *dmix);
290 int snd_pcm_direct_set_timer_params(snd_pcm_direct_t *dmix);
291 int snd_pcm_direct_open_secondary_client(snd_pcm_t **spcmp, snd_pcm_direct_t *dmix, const char *client_name);
293 int snd_timer_async(snd_timer_t *timer, int sig, pid_t pid);
294 struct timespec snd_pcm_hw_fast_tstamp(snd_pcm_t *pcm);
296 struct snd_pcm_direct_open_conf {
303 snd_config_t *bindings;
306 int snd_pcm_direct_parse_open_conf(snd_config_t *root, snd_config_t *conf, int stream, struct snd_pcm_direct_open_conf *rec);