Lines Matching refs:dmix
4 * \brief PCM Direct Stream Mixing (dmix) Plugin Interface
63 static int shm_sum_discard(snd_pcm_direct_t *dmix);
68 static int shm_sum_create_or_connect(snd_pcm_direct_t *dmix)
74 size = dmix->shmptr->s.channels *
75 dmix->shmptr->s.buffer_size *
78 dmix->u.dmix.shmid_sum = shmget(dmix->ipc_key + 1, size,
79 IPC_CREAT | dmix->ipc_perm);
81 if (dmix->u.dmix.shmid_sum < 0) {
83 if ((tmpid = shmget(dmix->ipc_key + 1, 0, dmix->ipc_perm)) != -1)
91 if (shmctl(dmix->u.dmix.shmid_sum, IPC_STAT, &buf) < 0) {
93 shm_sum_discard(dmix);
96 if (dmix->ipc_gid >= 0) {
97 buf.shm_perm.gid = dmix->ipc_gid;
98 shmctl(dmix->u.dmix.shmid_sum, IPC_SET, &buf);
100 dmix->u.dmix.sum_buffer = shmat(dmix->u.dmix.shmid_sum, 0, 0);
101 if (dmix->u.dmix.sum_buffer == (void *) -1) {
103 shm_sum_discard(dmix);
106 mlock(dmix->u.dmix.sum_buffer, size);
110 static int shm_sum_discard(snd_pcm_direct_t *dmix)
115 if (dmix->u.dmix.shmid_sum < 0)
117 if (dmix->u.dmix.sum_buffer != (void *) -1 && shmdt(dmix->u.dmix.sum_buffer) < 0)
119 dmix->u.dmix.sum_buffer = (void *) -1;
120 if (shmctl(dmix->u.dmix.shmid_sum, IPC_STAT, &buf) < 0)
123 if (shmctl(dmix->u.dmix.shmid_sum, IPC_RMID, NULL) < 0)
127 dmix->u.dmix.shmid_sum = -1;
131 static void dmix_server_free(snd_pcm_direct_t *dmix)
134 shm_sum_create_or_connect(dmix);
135 shm_sum_discard(dmix);
155 static void mix_areas(snd_pcm_direct_t *dmix,
166 channels = dmix->channels;
167 switch (dmix->shmptr->s.format) {
171 do_mix_areas = (mix_areas_t *)dmix->u.dmix.mix_areas_16;
176 do_mix_areas = (mix_areas_t *)dmix->u.dmix.mix_areas_32;
180 do_mix_areas = (mix_areas_t *)dmix->u.dmix.mix_areas_24;
184 do_mix_areas = (mix_areas_t *)dmix->u.dmix.mix_areas_24;
188 do_mix_areas = (mix_areas_t *)dmix->u.dmix.mix_areas_u8;
193 if (dmix->interleaved) {
201 dmix->u.dmix.sum_buffer + dst_ofs * channels,
208 dchn = dmix->bindings ? dmix->bindings[chn] : chn;
209 if (dchn >= dmix->shmptr->s.channels)
216 dmix->u.dmix.sum_buffer + dmix->shmptr->s.channels * dst_ofs + dchn,
219 dmix->shmptr->s.channels * sizeof(signed int));
223 static void remix_areas(snd_pcm_direct_t *dmix,
234 channels = dmix->channels;
235 switch (dmix->shmptr->s.format) {
239 do_remix_areas = (mix_areas_t *)dmix->u.dmix.remix_areas_16;
244 do_remix_areas = (mix_areas_t *)dmix->u.dmix.remix_areas_32;
248 do_remix_areas = (mix_areas_t *)dmix->u.dmix.remix_areas_24;
252 do_remix_areas = (mix_areas_t *)dmix->u.dmix.remix_areas_24;
256 do_remix_areas = (mix_areas_t *)dmix->u.dmix.remix_areas_u8;
261 if (dmix->interleaved) {
269 dmix->u.dmix.sum_buffer + dst_ofs * channels,
276 dchn = dmix->bindings ? dmix->bindings[chn] : chn;
277 if (dchn >= dmix->shmptr->s.channels)
284 dmix->u.dmix.sum_buffer + dmix->shmptr->s.channels * dst_ofs + dchn,
287 dmix->shmptr->s.channels * sizeof(signed int));
296 static void dmix_down_sem(snd_pcm_direct_t *dmix)
298 if (dmix->u.dmix.use_sem)
299 snd_pcm_direct_semaphore_down(dmix, DIRECT_IPC_SEM_CLIENT);
302 static void dmix_up_sem(snd_pcm_direct_t *dmix)
304 if (dmix->u.dmix.use_sem)
305 snd_pcm_direct_semaphore_up(dmix, DIRECT_IPC_SEM_CLIENT);
314 snd_pcm_direct_t *dmix = pcm->private_data;
323 size = pcm_frame_diff2(dmix->appl_ptr, dmix->last_appl_ptr, pcm->boundary);
329 slave_size = pcm_frame_diff(dmix->slave_appl_ptr, dmix->slave_hw_ptr, dmix->slave_boundary);
330 if (slave_size > dmix->slave_buffer_size) {
331 transfer = dmix->slave_buffer_size - slave_size;
334 dmix->last_appl_ptr += transfer;
335 dmix->last_appl_ptr %= pcm->boundary;
336 dmix->slave_appl_ptr += transfer;
337 dmix->slave_appl_ptr %= dmix->slave_boundary;
338 size = pcm_frame_diff2(dmix->appl_ptr, dmix->last_appl_ptr, pcm->boundary);
344 slave_hw_ptr = dmix->slave_hw_ptr;
348 slave_hw_ptr -= slave_hw_ptr % dmix->slave_period_size;
349 slave_hw_ptr += dmix->slave_buffer_size;
350 if (slave_hw_ptr >= dmix->slave_boundary)
351 slave_hw_ptr -= dmix->slave_boundary;
352 slave_size = pcm_frame_diff(slave_hw_ptr, dmix->slave_appl_ptr, dmix->slave_boundary);
360 dst_areas = snd_pcm_mmap_areas(dmix->spcm);
361 appl_ptr = dmix->last_appl_ptr % pcm->buffer_size;
362 dmix->last_appl_ptr += size;
363 dmix->last_appl_ptr %= pcm->boundary;
364 slave_appl_ptr = dmix->slave_appl_ptr % dmix->slave_buffer_size;
365 dmix->slave_appl_ptr += size;
366 dmix->slave_appl_ptr %= dmix->slave_boundary;
367 dmix_down_sem(dmix);
372 if (slave_appl_ptr + transfer > dmix->slave_buffer_size)
373 transfer = dmix->slave_buffer_size - slave_appl_ptr;
374 mix_areas(dmix, src_areas, dst_areas, appl_ptr, slave_appl_ptr, transfer);
379 slave_appl_ptr %= dmix->slave_buffer_size;
383 dmix_up_sem(dmix);
391 snd_pcm_direct_t *dmix = pcm->private_data;
395 old_slave_hw_ptr = dmix->slave_hw_ptr;
396 dmix->slave_hw_ptr = slave_hw_ptr;
397 diff = pcm_frame_diff(slave_hw_ptr, old_slave_hw_ptr, dmix->slave_boundary);
400 if (dmix->state != SND_PCM_STATE_RUNNING &&
401 dmix->state != SND_PCM_STATE_DRAINING)
404 dmix->hw_ptr += diff;
405 dmix->hw_ptr %= pcm->boundary;
409 if (avail > dmix->avail_max)
410 dmix->avail_max = avail;
412 snd_timer_stop(dmix->timer);
413 gettimestamp(&dmix->trigger_tstamp, pcm->tstamp_type);
414 if (dmix->state == SND_PCM_STATE_RUNNING) {
415 dmix->state = SND_PCM_STATE_XRUN;
418 dmix->state = SND_PCM_STATE_SETUP;
420 snd_pcm_direct_clear_timer_queue(dmix);
427 snd_pcm_direct_t *dmix = pcm->private_data;
431 if (dmix->slowptr)
432 snd_pcm_hwsync(dmix->spcm);
433 slave_hw_ptr = *dmix->spcm->hw.ptr;
434 err = snd_pcm_direct_check_xrun(dmix, pcm);
447 snd_pcm_direct_t *dmix = pcm->private_data;
449 snd_pcm_direct_check_xrun(dmix, pcm);
450 if (dmix->state == STATE_RUN_PENDING)
452 return dmix->state;
457 snd_pcm_direct_t *dmix = pcm->private_data;
460 snd_pcm_status(dmix->spcm, status);
462 switch (dmix->state) {
475 status->trigger_tstamp = dmix->trigger_tstamp;
477 status->avail_max = status->avail > dmix->avail_max ? status->avail : dmix->avail_max;
478 dmix->avail_max = 0;
484 snd_pcm_direct_t *dmix = pcm->private_data;
487 switch(dmix->state) {
510 snd_pcm_direct_t *dmix = pcm->private_data;
512 switch(dmix->state) {
532 snd_pcm_direct_t *dmix = pcm->private_data;
533 dmix->hw_ptr %= pcm->period_size;
534 dmix->appl_ptr = dmix->last_appl_ptr = dmix->hw_ptr;
535 snd_pcm_direct_reset_slave_ptr(pcm, dmix, *dmix->spcm->hw.ptr);
539 static int snd_pcm_dmix_start_timer(snd_pcm_t *pcm, snd_pcm_direct_t *dmix)
543 snd_pcm_hwsync(dmix->spcm);
544 snd_pcm_direct_reset_slave_ptr(pcm, dmix, *dmix->spcm->hw.ptr);
545 err = snd_timer_start(dmix->timer);
548 dmix->state = SND_PCM_STATE_RUNNING;
554 snd_pcm_direct_t *dmix = pcm->private_data;
558 if (dmix->state != SND_PCM_STATE_PREPARED)
562 dmix->state = STATE_RUN_PENDING;
566 if ((err = snd_pcm_dmix_start_timer(pcm, dmix)) < 0)
570 gettimestamp(&dmix->trigger_tstamp, pcm->tstamp_type);
576 snd_pcm_direct_t *dmix = pcm->private_data;
577 if (dmix->state == SND_PCM_STATE_OPEN)
579 dmix->state = SND_PCM_STATE_SETUP;
580 snd_pcm_direct_timer_stop(dmix);
587 snd_pcm_direct_t *dmix = pcm->private_data;
591 switch (snd_pcm_state(dmix->spcm)) {
598 if (dmix->state == SND_PCM_STATE_OPEN)
600 if (dmix->state == SND_PCM_STATE_PREPARED) {
609 if (dmix->state == SND_PCM_STATE_XRUN) {
617 dmix->state = SND_PCM_STATE_DRAINING;
624 if (dmix->state == SND_PCM_STATE_DRAINING) {
628 snd_pcm_direct_clear_timer_queue(dmix); /* force poll to wait */
631 switch (snd_pcm_state(dmix->spcm)) {
640 if (dmix->state == SND_PCM_STATE_DRAINING) {
645 } while (dmix->state == SND_PCM_STATE_DRAINING);
673 snd_pcm_direct_t *dmix = pcm->private_data;
679 if (dmix->state == SND_PCM_STATE_RUNNING ||
680 dmix->state == SND_PCM_STATE_DRAINING) {
693 size = pcm_frame_diff(dmix->last_appl_ptr, dmix->appl_ptr, pcm->boundary);
705 size = pcm_frame_diff(dmix->appl_ptr, dmix->hw_ptr, pcm->boundary);
708 slave_size = pcm_frame_diff(dmix->slave_appl_ptr, dmix->slave_hw_ptr, pcm->boundary);
719 dst_areas = snd_pcm_mmap_areas(dmix->spcm);
720 dmix->last_appl_ptr -= size;
721 dmix->last_appl_ptr %= pcm->boundary;
722 appl_ptr = dmix->last_appl_ptr % pcm->buffer_size;
723 dmix->slave_appl_ptr -= size;
724 dmix->slave_appl_ptr %= dmix->slave_boundary;
725 slave_appl_ptr = dmix->slave_appl_ptr % dmix->slave_buffer_size;
726 dmix_down_sem(dmix);
731 if (slave_appl_ptr + transfer > dmix->slave_buffer_size)
732 transfer = dmix->slave_buffer_size - slave_appl_ptr;
733 remix_areas(dmix, src_areas, dst_areas, appl_ptr, slave_appl_ptr, transfer);
738 slave_appl_ptr %= dmix->slave_buffer_size;
742 dmix_up_sem(dmix);
781 snd_pcm_direct_t *dmix = pcm->private_data;
783 if (dmix->timer)
784 snd_timer_close(dmix->timer);
785 snd_pcm_direct_semaphore_down(dmix, DIRECT_IPC_SEM_CLIENT);
786 snd_pcm_close(dmix->spcm);
787 if (dmix->server)
788 snd_pcm_direct_server_discard(dmix);
789 if (dmix->client)
790 snd_pcm_direct_client_discard(dmix);
791 shm_sum_discard(dmix);
792 if (snd_pcm_direct_shm_discard(dmix)) {
793 if (snd_pcm_direct_semaphore_discard(dmix))
794 snd_pcm_direct_semaphore_final(dmix, DIRECT_IPC_SEM_CLIENT);
796 snd_pcm_direct_semaphore_final(dmix, DIRECT_IPC_SEM_CLIENT);
797 free(dmix->bindings);
799 free(dmix);
807 snd_pcm_direct_t *dmix = pcm->private_data;
810 err = snd_pcm_direct_check_xrun(dmix, pcm);
816 if (dmix->state == STATE_RUN_PENDING) {
817 if ((err = snd_pcm_dmix_start_timer(pcm, dmix)) < 0)
819 } else if (dmix->state == SND_PCM_STATE_RUNNING ||
820 dmix->state == SND_PCM_STATE_DRAINING) {
824 if (dmix->state == SND_PCM_STATE_RUNNING ||
825 dmix->state == SND_PCM_STATE_DRAINING) {
831 snd_pcm_direct_clear_timer_queue(dmix);
838 snd_pcm_direct_t *dmix = pcm->private_data;
841 if (dmix->state == SND_PCM_STATE_RUNNING ||
842 dmix->state == SND_PCM_STATE_DRAINING) {
846 if (dmix->state == SND_PCM_STATE_XRUN)
856 snd_pcm_direct_t *dmix = pcm->private_data;
861 if (dmix->state == SND_PCM_STATE_RUNNING ||
862 dmix->state == SND_PCM_STATE_DRAINING)
868 *tstamp = snd_pcm_hw_fast_tstamp(dmix->spcm);
876 snd_pcm_direct_t *dmix = pcm->private_data;
877 if (dmix->state == SND_PCM_STATE_RUNNING)
885 snd_pcm_direct_t *dmix = pcm->private_data;
892 if (dmix->spcm)
893 snd_pcm_dump(dmix->spcm, out);
946 * \brief Creates a new dmix PCM
967 snd_pcm_direct_t *dmix;
973 SNDERR("The dmix plugin supports only playback stream");
977 ret = _snd_pcm_direct_new(&pcm, &dmix, SND_PCM_TYPE_DMIX, name, opts, params, stream, mode);
984 pcm->private_data = dmix;
985 dmix->state = SND_PCM_STATE_OPEN;
986 dmix->slowptr = opts->slowptr;
987 dmix->max_periods = opts->max_periods;
988 dmix->var_periodsize = opts->var_periodsize;
989 dmix->hw_ptr_alignment = opts->hw_ptr_alignment;
990 dmix->sync_ptr = snd_pcm_dmix_sync_ptr;
991 dmix->direct_memory_access = opts->direct_memory_access;
1005 SNDERR("dmix plugin can be only connected to hw plugin");
1010 ret = snd_pcm_direct_initialize_slave(dmix, spcm, params);
1016 dmix->spcm = spcm;
1018 if (dmix->shmptr->use_server) {
1019 dmix->server_free = dmix_server_free;
1021 ret = snd_pcm_direct_server_create(dmix);
1028 dmix->shmptr->type = spcm->type;
1030 if (dmix->shmptr->use_server) {
1032 snd_pcm_direct_semaphore_up(dmix, DIRECT_IPC_SEM_CLIENT);
1033 ret = snd_pcm_direct_client_connect(dmix);
1039 snd_pcm_direct_semaphore_down(dmix, DIRECT_IPC_SEM_CLIENT);
1040 ret = snd_pcm_direct_open_secondary_client(&spcm, dmix, "dmix_client");
1061 SNDERR("dmix plugin can be only connected to hw plugin");
1066 ret = snd_pcm_direct_initialize_secondary_slave(dmix, spcm, params);
1073 dmix->spcm = spcm;
1076 ret = shm_sum_create_or_connect(dmix);
1082 ret = snd_pcm_direct_initialize_poll_fd(dmix);
1088 mix_select_callbacks(dmix);
1090 pcm->poll_fd = dmix->poll_fd;
1094 snd_pcm_set_hw_ptr(pcm, &dmix->hw_ptr, -1, 0);
1095 snd_pcm_set_appl_ptr(pcm, &dmix->appl_ptr, -1, 0);
1097 if (dmix->channels == UINT_MAX)
1098 dmix->channels = dmix->shmptr->s.channels;
1100 snd_pcm_direct_semaphore_up(dmix, DIRECT_IPC_SEM_CLIENT);
1106 if (dmix->timer)
1107 snd_timer_close(dmix->timer);
1108 if (dmix->server)
1109 snd_pcm_direct_server_discard(dmix);
1110 if (dmix->client)
1111 snd_pcm_direct_client_discard(dmix);
1114 if (dmix->u.dmix.shmid_sum >= 0)
1115 shm_sum_discard(dmix);
1116 if ((dmix->shmid >= 0) && (snd_pcm_direct_shm_discard(dmix))) {
1117 if (snd_pcm_direct_semaphore_discard(dmix))
1118 snd_pcm_direct_semaphore_final(dmix, DIRECT_IPC_SEM_CLIENT);
1120 snd_pcm_direct_semaphore_up(dmix, DIRECT_IPC_SEM_CLIENT);
1122 free(dmix->bindings);
1123 free(dmix);
1130 \section pcm_plugins_dmix Plugin: dmix
1138 type dmix # Direct mix
1176 This number must be unique for each different dmix definition,
1204 Note that the dmix plugin itself supports only a single configuration.
1216 type dmix
1226 You can hear 48000 Hz samples still using this dmix pcm via plug plugin
1232 For using the dmix plugin for OSS emulation device, you have to set
1236 type dmix
1259 so that only the first two channels are used by dmix.
1274 * \brief Creates a new dmix PCM
1278 * \param conf Configuration node with dmix PCM description