Lines Matching refs:dmix

64 int snd_pcm_direct_semaphore_create_or_connect(snd_pcm_direct_t *dmix)
70 dmix->semid = semget(dmix->ipc_key, DIRECT_IPC_SEMS,
71 IPC_CREAT | dmix->ipc_perm);
72 if (dmix->semid < 0)
74 if (dmix->ipc_gid < 0)
78 if (semctl(dmix->semid, i, IPC_STAT, s) < 0) {
80 snd_pcm_direct_semaphore_discard(dmix);
83 buf.sem_perm.gid = dmix->ipc_gid;
85 semctl(dmix->semid, i, IPC_SET, s);
90 static unsigned int snd_pcm_direct_magic(snd_pcm_direct_t *dmix)
92 if (!dmix->direct_memory_access)
102 int snd_pcm_direct_shm_create_or_connect(snd_pcm_direct_t *dmix)
108 dmix->shmid = shmget(dmix->ipc_key, sizeof(snd_pcm_direct_share_t),
109 dmix->ipc_perm);
110 if (dmix->shmid < 0 && errno == ENOENT) {
111 if ((dmix->shmid = shmget(dmix->ipc_key, sizeof(snd_pcm_direct_share_t),
112 IPC_CREAT | IPC_EXCL | dmix->ipc_perm)) != -1)
118 if (dmix->shmid < 0) {
120 if ((tmpid = shmget(dmix->ipc_key, 0, dmix->ipc_perm)) != -1)
128 dmix->shmptr = shmat(dmix->shmid, 0, 0);
129 if (dmix->shmptr == (void *) -1) {
131 snd_pcm_direct_shm_discard(dmix);
134 mlock(dmix->shmptr, sizeof(snd_pcm_direct_share_t));
135 if (shmctl(dmix->shmid, IPC_STAT, &buf) < 0) {
137 snd_pcm_direct_shm_discard(dmix);
141 memset(dmix->shmptr, 0, sizeof(snd_pcm_direct_share_t));
142 if (dmix->ipc_gid >= 0) {
143 buf.shm_perm.gid = dmix->ipc_gid;
144 shmctl(dmix->shmid, IPC_SET, &buf);
146 dmix->shmptr->magic = snd_pcm_direct_magic(dmix);
149 if (dmix->shmptr->magic != snd_pcm_direct_magic(dmix)) {
150 snd_pcm_direct_shm_discard(dmix);
164 static int _snd_pcm_direct_shm_discard(snd_pcm_direct_t *dmix)
169 if (dmix->shmid < 0)
171 if (dmix->shmptr != (void *) -1 && shmdt(dmix->shmptr) < 0)
173 dmix->shmptr = (void *) -1;
174 if (shmctl(dmix->shmid, IPC_STAT, &buf) < 0)
177 if (shmctl(dmix->shmid, IPC_RMID, NULL) < 0)
181 dmix->shmid = -1;
186 int snd_pcm_direct_shm_discard(snd_pcm_direct_t *dmix)
188 return _snd_pcm_direct_shm_discard(dmix);
200 snprintf(filename, size, TMPDIR "/alsa-dmix-%i-%li-%li", (int)getpid(), (long)tv.tv_sec, (long)tv.tv_usec);
270 static void server_cleanup(snd_pcm_direct_t *dmix)
272 close(dmix->server_fd);
273 close(dmix->hw_fd);
274 if (dmix->server_free)
275 dmix->server_free(dmix);
276 unlink(dmix->shmptr->socket_name);
277 _snd_pcm_direct_shm_discard(dmix);
278 snd_pcm_direct_semaphore_discard(dmix);
323 static void server_job(snd_pcm_direct_t *dmix)
329 server_job_dmix = dmix;
342 if (i != dmix->server_fd && i != dmix->hw_fd)
349 pfds[0].fd = dmix->server_fd;
364 snd_pcm_direct_semaphore_down(dmix, DIRECT_IPC_SEM_CLIENT);
365 if (shmctl(dmix->shmid, IPC_STAT, &buf) < 0) {
366 _snd_pcm_direct_shm_discard(dmix);
367 snd_pcm_direct_semaphore_up(dmix, DIRECT_IPC_SEM_CLIENT);
373 snd_pcm_direct_semaphore_up(dmix, DIRECT_IPC_SEM_CLIENT);
378 sck = accept(dmix->server_fd, 0, 0);
387 _snd_send_fd(sck, &buf, 1, dmix->hw_fd);
417 server_cleanup(dmix);
425 int snd_pcm_direct_server_create(snd_pcm_direct_t *dmix)
429 dmix->server_fd = -1;
431 ret = get_tmp_name(dmix->shmptr->socket_name, sizeof(dmix->shmptr->socket_name));
435 ret = make_local_socket(dmix->shmptr->socket_name, 1, dmix->ipc_perm, dmix->ipc_gid);
438 dmix->server_fd = ret;
440 ret = listen(dmix->server_fd, 4);
442 close(dmix->server_fd);
448 close(dmix->server_fd);
453 server_job(dmix);
458 dmix->server_pid = ret;
459 dmix->server = 1;
463 int snd_pcm_direct_server_discard(snd_pcm_direct_t *dmix)
465 if (dmix->server) {
466 //kill(dmix->server_pid, SIGTERM);
467 //waitpid(dmix->server_pid, NULL, 0);
468 dmix->server_pid = (pid_t)-1;
470 if (dmix->server_fd > 0) {
471 close(dmix->server_fd);
472 dmix->server_fd = -1;
474 dmix->server = 0;
482 int snd_pcm_direct_client_connect(snd_pcm_direct_t *dmix)
487 ret = make_local_socket(dmix->shmptr->socket_name, 0, -1, -1);
490 dmix->comm_fd = ret;
492 ret = snd_receive_fd(dmix->comm_fd, &buf, 1, &dmix->hw_fd);
494 close(dmix->comm_fd);
495 dmix->comm_fd = -1;
499 dmix->client = 1;
503 int snd_pcm_direct_client_discard(snd_pcm_direct_t *dmix)
505 if (dmix->client) {
506 close(dmix->comm_fd);
507 dmix->comm_fd = -1;
524 snd_pcm_direct_t *dmix = pcm->private_data;
525 return snd_timer_async(dmix->timer, sig, pid);
529 int snd_pcm_direct_clear_timer_queue(snd_pcm_direct_t *dmix)
532 if (dmix->timer_need_poll) {
533 while (poll(&dmix->timer_fd, 1, 0) > 0) {
536 if (dmix->tread) {
538 snd_timer_read(dmix->timer, rbuf, sizeof(rbuf));
541 snd_timer_read(dmix->timer, &rbuf, sizeof(rbuf));
545 if (dmix->tread) {
548 while ((len = snd_timer_read(dmix->timer, rbuf,
555 while (snd_timer_read(dmix->timer, &rbuf, sizeof(rbuf)) > 0)
562 int snd_pcm_direct_timer_stop(snd_pcm_direct_t *dmix)
564 snd_timer_stop(dmix->timer);
753 snd_pcm_direct_t *dmix = pcm->private_data;
774 if (snd_pcm_direct_check_xrun(dmix, pcm) < 0 ||
775 snd_pcm_state(dmix->spcm) == SND_PCM_STATE_SETUP) {
787 if (snd_pcm_direct_clear_timer_queue(dmix))
808 snd_pcm_direct_t *dmix = pcm->private_data;
810 if (dmix->spcm && !dmix->shmptr->use_server)
811 return snd_pcm_info(dmix->spcm, info);
1031 snd_pcm_direct_t *dmix = pcm->private_data;
1033 params->info = dmix->shmptr->s.info;
1034 params->rate_num = dmix->shmptr->s.rate;
1037 params->msbits = dmix->shmptr->s.msbits;
1073 snd_pcm_direct_t *dmix = pcm->private_data;
1077 if (dmix->bindings == NULL)
1078 return snd_pcm_query_chmaps(dmix->spcm);
1083 maps[0] = calloc(dmix->channels + 2, sizeof(int *));
1088 smaps = snd_pcm_query_chmaps(dmix->spcm);
1094 maps[0]->map.channels = dmix->channels;
1095 for (i = 0; i < dmix->channels; i++) {
1096 j = dmix->bindings[i];
1106 snd_pcm_direct_t *dmix = pcm->private_data;
1107 return snd_pcm_get_chmap(dmix->spcm);
1112 snd_pcm_direct_t *dmix = pcm->private_data;
1113 return snd_pcm_set_chmap(dmix->spcm, map);
1118 snd_pcm_direct_t *dmix = pcm->private_data;
1121 switch (snd_pcm_state(dmix->spcm)) {
1125 err = snd_pcm_prepare(dmix->spcm);
1128 snd_pcm_start(dmix->spcm);
1136 snd_pcm_direct_check_interleave(dmix, pcm);
1137 dmix->state = SND_PCM_STATE_PREPARED;
1138 dmix->appl_ptr = dmix->last_appl_ptr = 0;
1139 dmix->hw_ptr = 0;
1140 return snd_pcm_direct_set_timer_params(dmix);
1145 snd_pcm_direct_t *dmix = pcm->private_data;
1148 err = snd_pcm_direct_slave_recover(dmix);
1152 #define COPY_SLAVE(field) (dmix->shmptr->s.field = spcm->field)
1155 static void save_slave_setting(snd_pcm_direct_t *dmix, snd_pcm_t *spcm)
1187 dmix->shmptr->s.info &= ~SND_PCM_INFO_RESUME;
1197 int snd_pcm_direct_initialize_slave(snd_pcm_direct_t *dmix, snd_pcm_t *spcm, struct slave_params *params)
1253 if (ret < 0 && dmix->type != SND_PCM_TYPE_DMIX) {
1342 dmix->shmptr->hw.format =
1345 dmix->shmptr->hw.rate =
1347 dmix->shmptr->hw.buffer_size =
1349 dmix->shmptr->hw.buffer_time =
1351 dmix->shmptr->hw.period_size =
1353 dmix->shmptr->hw.period_time =
1355 dmix->shmptr->hw.periods =
1377 * the slave timestamp is copied appropriately in dsnoop/dmix/dshare
1387 if (dmix->tstamp_type != -1) {
1389 dmix->tstamp_type);
1396 if (dmix->type != SND_PCM_TYPE_DMIX &&
1397 dmix->type != SND_PCM_TYPE_DSHARE)
1419 if (dmix->type == SND_PCM_TYPE_DSHARE) {
1437 dmix->hw_fd = fd.fd;
1439 save_slave_setting(dmix, spcm);
1441 /* Currently, we assume that each dmix client has the same
1448 dmix->slave_buffer_size = spcm->buffer_size;
1449 dmix->slave_period_size = spcm->period_size;
1450 dmix->slave_boundary = spcm->boundary;
1458 dmix->shmptr->use_server = 1;
1469 int snd_pcm_direct_initialize_poll_fd(snd_pcm_direct_t *dmix)
1474 int capture = dmix->type == SND_PCM_TYPE_DSNOOP ? 1 : 0;
1476 dmix->tread = 1;
1477 dmix->timer_need_poll = 0;
1478 dmix->timer_ticks = 1;
1479 ret = snd_pcm_info(dmix->spcm, &info);
1489 ret = snd_timer_open(&dmix->timer, name,
1492 dmix->tread = 0;
1493 ret = snd_timer_open(&dmix->timer, name,
1501 if (snd_timer_poll_descriptors_count(dmix->timer) != 1) {
1505 snd_timer_poll_descriptors(dmix->timer, &dmix->timer_fd, 1);
1506 dmix->poll_fd = dmix->timer_fd.fd;
1508 dmix->timer_events = (1<<SND_TIMER_EVENT_MSUSPEND) |
1518 ioctl(dmix->poll_fd, SNDRV_TIMER_IOCTL_PVERSION, &ver);
1524 dmix->timer_need_poll = 1;
1530 dmix->timer_events &= ~((1<<SND_TIMER_EVENT_MSUSPEND) |
1532 dmix->timer_events |= (1<<SND_TIMER_EVENT_MPAUSE) |
1538 dmix->timer_events |= 1<<SND_TIMER_EVENT_START;
1553 #define COPY_SLAVE(field) (spcm->field = dmix->shmptr->s.field)
1556 static void copy_slave_setting(snd_pcm_direct_t *dmix, snd_pcm_t *spcm)
1587 spcm->boundary = recalc_boundary_size(dmix->shmptr->s.boundary, spcm->buffer_size);
1596 int snd_pcm_direct_open_secondary_client(snd_pcm_t **spcmp, snd_pcm_direct_t *dmix, const char *client_name)
1601 ret = snd_pcm_hw_open_fd(spcmp, client_name, dmix->hw_fd, 0);
1611 copy_slave_setting(dmix, spcm);
1614 dmix->slave_buffer_size = spcm->buffer_size;
1615 dmix->slave_period_size = dmix->shmptr->s.period_size;
1616 dmix->slave_boundary = spcm->boundary;
1617 dmix->recoveries = dmix->shmptr->s.recoveries;
1630 int snd_pcm_direct_initialize_secondary_slave(snd_pcm_direct_t *dmix,
1639 copy_slave_setting(dmix, spcm);
1642 dmix->slave_buffer_size = spcm->buffer_size;
1643 dmix->slave_period_size = dmix->shmptr->s.period_size;
1644 dmix->slave_boundary = spcm->boundary;
1654 int snd_pcm_direct_set_timer_params(snd_pcm_direct_t *dmix)
1661 if (dmix->type != SND_PCM_TYPE_DSNOOP)
1663 snd_timer_params_set_ticks(&params, dmix->timer_ticks);
1664 if (dmix->tread) {
1666 dmix->timer_events;
1669 ret = snd_timer_params(dmix->timer, &params);
1680 int snd_pcm_direct_check_interleave(snd_pcm_direct_t *dmix, snd_pcm_t *pcm)
1690 channels = dmix->channels;
1691 if (channels != dmix->spcm->channels)
1693 dst_areas = snd_pcm_mmap_areas(dmix->spcm);
1702 if (dmix->bindings && dmix->bindings[chn] != chn)
1711 return dmix->interleaved = 1;
1713 return dmix->interleaved = 0;
1721 int snd_pcm_direct_parse_bindings(snd_pcm_direct_t *dmix,
1730 dmix->channels = UINT_MAX;
1782 if (dmix->type == SND_PCM_TYPE_DSNOOP ||
1783 ! dmix->bindings)
1789 if (bindings[chn] == dmix->bindings[chn1]) {
1797 dmix->bindings = bindings;
1798 dmix->channels = count;
2128 void snd_pcm_direct_reset_slave_ptr(snd_pcm_t *pcm, snd_pcm_direct_t *dmix,
2131 dmix->slave_appl_ptr = dmix->slave_hw_ptr = hw_ptr;
2132 if (dmix->hw_ptr_alignment == SND_PCM_HW_PTR_ALIGNMENT_ROUNDUP ||
2133 (dmix->hw_ptr_alignment == SND_PCM_HW_PTR_ALIGNMENT_AUTO &&
2135 dmix->slave_appl_ptr =
2136 ((dmix->slave_appl_ptr + dmix->slave_period_size - 1) /
2137 dmix->slave_period_size) * dmix->slave_period_size;
2138 else if (dmix->hw_ptr_alignment == SND_PCM_HW_PTR_ALIGNMENT_ROUNDDOWN ||
2139 (dmix->hw_ptr_alignment == SND_PCM_HW_PTR_ALIGNMENT_AUTO &&
2140 ((dmix->slave_period_size * SEC_TO_MS) / pcm->rate) < LOW_LATENCY_PERIOD_TIME))
2141 dmix->slave_appl_ptr = dmix->slave_hw_ptr =
2142 ((dmix->slave_hw_ptr / dmix->slave_period_size) *
2143 dmix->slave_period_size);
2150 snd_pcm_direct_t *dmix;
2154 dmix = calloc(1, sizeof(snd_pcm_direct_t));
2155 if (!dmix)
2158 ret = snd_pcm_direct_parse_bindings(dmix, params, opts->bindings);
2160 free(dmix);
2164 dmix->ipc_key = opts->ipc_key;
2165 dmix->ipc_perm = opts->ipc_perm;
2166 dmix->ipc_gid = opts->ipc_gid;
2167 dmix->tstamp_type = opts->tstamp_type;
2168 dmix->semid = -1;
2169 dmix->shmid = -1;
2170 dmix->shmptr = (void *) -1;
2171 dmix->type = type;
2178 ret = snd_pcm_direct_semaphore_create_or_connect(dmix);
2183 ret = snd_pcm_direct_semaphore_down(dmix, DIRECT_IPC_SEM_CLIENT);
2185 snd_pcm_direct_semaphore_discard(dmix);
2193 ret = snd_pcm_direct_shm_create_or_connect(dmix);
2196 snd_pcm_direct_semaphore_up(dmix, DIRECT_IPC_SEM_CLIENT);
2199 *_dmix = dmix;
2207 free(dmix->bindings);
2208 free(dmix);