Initial Import
[profile/ivi/alsa-lib.git] / src / pcm / pcm_direct.h
1 /*
2  *  PCM - Direct Stream Mixing
3  *  Copyright (c) 2003 by Jaroslav Kysela <perex@perex.cz>
4  *
5  *
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.
10  *
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.
15  *
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
19  *
20  */
21
22 #include "pcm_local.h"  
23
24 #define DIRECT_IPC_SEMS         1
25 #define DIRECT_IPC_SEM_CLIENT   0
26
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);
31
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);
36
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);
41
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);
46
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);
51
52 struct slave_params {
53         snd_pcm_format_t format;
54         int rate;
55         int channels;
56         int period_time;
57         int buffer_time;
58         snd_pcm_sframes_t period_size;
59         snd_pcm_sframes_t buffer_size;
60         unsigned int periods;
61 };
62
63 /* shared among direct plugin clients - be careful to be 32/64bit compatible! */
64 typedef struct {
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) */
68         int use_server;
69         struct {
70                 unsigned int format;
71                 snd_interval_t rate;
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;
77         } hw;
78         struct {
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;
84                 unsigned int rate;
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;
99                 unsigned int info;
100                 unsigned int msbits;
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;
109         } s;
110         union {
111                 struct {
112                         unsigned long long chn_mask;
113                 } dshare;
114         } u;
115 } snd_pcm_direct_share_t;
116
117 typedef struct snd_pcm_direct snd_pcm_direct_t;
118
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;
141         int server, client;
142         int comm_fd;                    /* communication file descriptor (socket) */
143         int hw_fd;                      /* hardware file descriptor */
144         struct pollfd timer_fd;
145         int poll_fd;
146         int tread: 1;
147         int timer_need_poll: 1;
148         unsigned int timer_events;
149         int server_fd;
150         pid_t server_pid;
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;
157         union {
158                 struct {
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;
169                 } dmix;
170                 struct {
171                 } dsnoop;
172                 struct {
173                         unsigned long long chn_mask;
174                 } dshare;
175         } u;
176         void (*server_free)(snd_pcm_direct_t *direct);
177 };
178
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 \
211         snd1_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 \
223         snd1_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
238
239 int snd_pcm_direct_semaphore_create_or_connect(snd_pcm_direct_t *dmix);
240
241 static inline int snd_pcm_direct_semaphore_discard(snd_pcm_direct_t *dmix)
242 {
243         if (dmix->semid >= 0) {
244                 if (semctl(dmix->semid, 0, IPC_RMID, NULL) < 0)
245                         return -errno;
246                 dmix->semid = -1;
247         }
248         return 0;
249 }
250
251 static inline int snd_pcm_direct_semaphore_down(snd_pcm_direct_t *dmix, int sem_num)
252 {
253         struct sembuf op[2] = { { sem_num, 0, 0 }, { sem_num, 1, SEM_UNDO } };
254         return semop(dmix->semid, op, 2);
255 }
256
257 static inline int snd_pcm_direct_semaphore_up(snd_pcm_direct_t *dmix, int sem_num)
258 {
259         struct sembuf op = { sem_num, -1, SEM_UNDO | IPC_NOWAIT };
260         return semop(dmix->semid, &op, 1);
261 }
262
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,
275                                   snd_config_t *cfg);
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);
292
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);
295
296 struct snd_pcm_direct_open_conf {
297         key_t ipc_key;
298         mode_t ipc_perm;
299         int ipc_gid;
300         int slowptr;
301         int max_periods;
302         snd_config_t *slave;
303         snd_config_t *bindings;
304 };
305
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);