2 * PCM - Direct Stream Mixing
3 * Copyright (c) 2003 by Jaroslav Kysela <perex@suse.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_areas1_t)(unsigned int size,
28 volatile signed short *dst, signed short *src,
29 volatile signed int *sum, size_t dst_step,
30 size_t src_step, size_t sum_step);
32 typedef void (mix_areas2_t)(unsigned int size,
33 volatile signed int *dst, signed int *src,
34 volatile signed int *sum, size_t dst_step,
35 size_t src_step, size_t sum_step);
37 typedef void (mix_areas3_t)(unsigned int size,
38 volatile unsigned char *dst, unsigned char *src,
39 volatile signed int *sum, size_t dst_step,
40 size_t src_step, size_t sum_step);
43 snd_pcm_format_t format;
48 snd_pcm_sframes_t period_size;
49 snd_pcm_sframes_t buffer_size;
54 char socket_name[256]; /* name of communication socket */
55 snd_pcm_type_t type; /* PCM type (currently only hw) */
59 snd_interval_t buffer_size;
60 snd_interval_t buffer_time;
61 snd_interval_t period_size;
62 snd_interval_t period_time;
63 snd_interval_t periods;
66 unsigned int buffer_size;
67 unsigned int period_size;
68 unsigned long long boundary;
69 unsigned int channels;
70 unsigned int sample_bits;
72 snd_pcm_format_t format;
78 unsigned long long chn_mask;
81 } snd_pcm_direct_share_t;
83 typedef struct snd_pcm_direct snd_pcm_direct_t;
85 struct snd_pcm_direct {
86 snd_pcm_type_t type; /* type (dmix, dsnoop, dshare) */
87 key_t ipc_key; /* IPC key for semaphore and memory */
88 mode_t ipc_perm; /* IPC socket permissions */
89 int ipc_gid; /* IPC socket gid */
90 int semid; /* IPC global semaphore identification */
91 int shmid; /* IPC global shared memory identification */
92 snd_pcm_direct_share_t *shmptr; /* pointer to shared memory area */
93 snd_pcm_t *spcm; /* slave PCM handle */
94 snd_pcm_uframes_t appl_ptr;
95 snd_pcm_uframes_t last_appl_ptr;
96 snd_pcm_uframes_t hw_ptr;
97 snd_pcm_uframes_t avail_max;
98 snd_pcm_uframes_t slave_appl_ptr;
99 snd_pcm_uframes_t slave_hw_ptr;
100 snd_pcm_uframes_t slave_period_size;
101 snd_pcm_uframes_t slave_buffer_size;
102 snd_pcm_uframes_t slave_boundary;
103 int (*sync_ptr)(snd_pcm_t *pcm);
104 snd_pcm_state_t state;
105 snd_htimestamp_t trigger_tstamp;
107 int comm_fd; /* communication file descriptor (socket) */
108 int hw_fd; /* hardware file descriptor */
109 struct pollfd timer_fd;
113 unsigned int timer_event_suspend;
114 unsigned int timer_event_resume;
117 snd_timer_t *timer; /* timer used as poll_fd */
118 int interleaved; /* we have interleaved buffer */
119 int slowptr; /* use slow but more precise ptr updates */
120 int variable_buffer_size; /* allow the variable buffer size */
121 unsigned int channels; /* client's channels */
122 unsigned int *bindings;
125 int shmid_sum; /* IPC global sum ring buffer memory identification */
126 signed int *sum_buffer; /* shared sum buffer */
127 mix_areas1_t *mix_areas1;
128 mix_areas2_t *mix_areas2;
129 mix_areas3_t *mix_areas3;
134 unsigned long long chn_mask;
137 void (*server_free)(snd_pcm_direct_t *direct);
140 int snd_pcm_direct_semaphore_create_or_connect(snd_pcm_direct_t *dmix);
142 static inline int snd_pcm_direct_semaphore_discard(snd_pcm_direct_t *dmix)
144 if (dmix->semid >= 0) {
145 if (semctl(dmix->semid, 0, IPC_RMID, NULL) < 0)
152 static inline int snd_pcm_direct_semaphore_down(snd_pcm_direct_t *dmix, int sem_num)
154 struct sembuf op[2] = { { sem_num, 0, 0 }, { sem_num, 1, SEM_UNDO } };
155 return semop(dmix->semid, op, 2);
158 static inline int snd_pcm_direct_semaphore_up(snd_pcm_direct_t *dmix, int sem_num)
160 struct sembuf op = { sem_num, -1, SEM_UNDO | IPC_NOWAIT };
161 return semop(dmix->semid, &op, 1);
164 int snd_pcm_direct_shm_create_or_connect(snd_pcm_direct_t *dmix);
165 int snd_pcm_direct_shm_discard(snd_pcm_direct_t *dmix);
166 int snd_pcm_direct_server_create(snd_pcm_direct_t *dmix);
167 int snd_pcm_direct_server_discard(snd_pcm_direct_t *dmix);
168 int snd_pcm_direct_client_connect(snd_pcm_direct_t *dmix);
169 int snd_pcm_direct_client_discard(snd_pcm_direct_t *dmix);
170 int snd_pcm_direct_initialize_slave(snd_pcm_direct_t *dmix, snd_pcm_t *spcm, struct slave_params *params);
171 int snd_pcm_direct_initialize_poll_fd(snd_pcm_direct_t *dmix);
172 int snd_pcm_direct_check_interleave(snd_pcm_direct_t *dmix, snd_pcm_t *pcm);
173 int snd_pcm_direct_parse_bindings(snd_pcm_direct_t *dmix, snd_config_t *cfg);
174 int snd_pcm_direct_nonblock(snd_pcm_t *pcm, int nonblock);
175 int snd_pcm_direct_async(snd_pcm_t *pcm, int sig, pid_t pid);
176 int snd_pcm_direct_poll_revents(snd_pcm_t *pcm, struct pollfd *pfds, unsigned int nfds, unsigned short *revents);
177 int snd_pcm_direct_info(snd_pcm_t *pcm, snd_pcm_info_t * info);
178 int snd_pcm_direct_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params);
179 int snd_pcm_direct_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params);
180 int snd_pcm_direct_hw_free(snd_pcm_t *pcm);
181 int snd_pcm_direct_sw_params(snd_pcm_t *pcm, snd_pcm_sw_params_t * params);
182 int snd_pcm_direct_channel_info(snd_pcm_t *pcm, snd_pcm_channel_info_t * info);
183 int snd_pcm_direct_mmap(snd_pcm_t *pcm);
184 int snd_pcm_direct_munmap(snd_pcm_t *pcm);
185 int snd_pcm_direct_resume(snd_pcm_t *pcm);
186 int snd_pcm_direct_timer_stop(snd_pcm_direct_t *dmix);
187 void snd_pcm_direct_clear_timer_queue(snd_pcm_direct_t *dmix);
188 int snd_pcm_direct_set_timer_params(snd_pcm_direct_t *dmix);
189 int snd_pcm_direct_open_secondary_client(snd_pcm_t **spcmp, snd_pcm_direct_t *dmix, const char *client_name);
190 int snd_pcm_direct_get_slave_ipc_offset(snd_config_t *root, snd_config_t *sconf, int direction);
192 int snd_timer_async(snd_timer_t *timer, int sig, pid_t pid);
193 struct timespec snd_pcm_hw_fast_tstamp(snd_pcm_t *pcm);
195 struct snd_pcm_direct_open_conf {
200 int variable_buffer_size;
202 snd_config_t *bindings;
205 int snd_pcm_direct_parse_open_conf(snd_config_t *conf, struct snd_pcm_direct_open_conf *rec);