Mercurial > mplayer.hg
comparison libao2/ao_alsa1x.c @ 6749:7f619a5d6eb8
added real mmap support
support for -abs opt, 4 different modes
author | joyping |
---|---|
date | Thu, 18 Jul 2002 16:09:54 +0000 |
parents | df3bf0f971d1 |
children | a5b2b377ab50 |
comparison
equal
deleted
inserted
replaced
6748:c0e8034d47e4 | 6749:7f619a5d6eb8 |
---|---|
12 #include <errno.h> | 12 #include <errno.h> |
13 #include <sys/time.h> | 13 #include <sys/time.h> |
14 #include <stdlib.h> | 14 #include <stdlib.h> |
15 #include <math.h> | 15 #include <math.h> |
16 #include <string.h> | 16 #include <string.h> |
17 #include <sys/poll.h> | |
17 | 18 |
18 #include "../config.h" | 19 #include "../config.h" |
19 | 20 |
20 #if HAVE_SYS_ASOUNDLIB_H | 21 #if HAVE_SYS_ASOUNDLIB_H |
21 #include <sys/asoundlib.h> | 22 #include <sys/asoundlib.h> |
46 static snd_pcm_format_t alsa_format; | 47 static snd_pcm_format_t alsa_format; |
47 static snd_pcm_hw_params_t *alsa_hwparams; | 48 static snd_pcm_hw_params_t *alsa_hwparams; |
48 static snd_pcm_sw_params_t *alsa_swparams; | 49 static snd_pcm_sw_params_t *alsa_swparams; |
49 static char *alsa_device; | 50 static char *alsa_device; |
50 | 51 |
51 /* possible 4096, original 8192, OUTBURST is set statically to 512 in config.h */ | 52 /* possible 4096, original 8192 |
52 static int alsa_fragsize = 4096; //OUTBURST | 53 * was only needed for calculating chunksize? */ |
53 static int alsa_fragcount = 8; | 54 static int alsa_fragsize = 4096; |
54 | 55 /* 16 sets buffersize to 16 * chunksize is as default 1024 |
55 static int chunk_size = -1; | 56 * which seems to be good avarge for most situations |
57 * so buffersize is 16384 frames by default */ | |
58 static int alsa_fragcount = 16; | |
59 static int chunk_size = 1024; //is alsa_fragsize / 4 | |
60 | |
56 static size_t bits_per_sample, bits_per_frame; | 61 static size_t bits_per_sample, bits_per_frame; |
57 static size_t chunk_bytes; | 62 static size_t chunk_bytes; |
58 | 63 |
59 int ao_mmap = 0; | 64 int ao_mmap = 0; |
60 int ao_noblock = 0; | 65 int ao_noblock = 0; |
66 int first = 1; | |
61 | 67 |
62 static int open_mode; | 68 static int open_mode; |
63 static int set_block_mode; | 69 static int set_block_mode; |
64 | 70 |
65 #define ALSA_DEVICE_SIZE 48 | 71 #define ALSA_DEVICE_SIZE 48 |
66 | 72 |
67 #undef BUFFERTIME | 73 #undef BUFFERTIME |
68 #define SET_CHUNKSIZE | 74 #define SET_CHUNKSIZE |
69 | 75 #undef USE_POLL |
70 snd_pcm_t * | 76 |
71 | 77 snd_pcm_t *spdif_init(char *pcm_name) |
72 spdif_init(char *pcm_name) | |
73 { | 78 { |
74 //char *pcm_name = "hw:0,2"; /* first card second device */ | 79 //char *pcm_name = "hw:0,2"; /* first card second device */ |
75 static snd_aes_iec958_t spdif; | 80 static snd_aes_iec958_t spdif; |
81 static snd_aes_iec958_t spdif_test; | |
76 snd_pcm_info_t *info; | 82 snd_pcm_info_t *info; |
77 snd_pcm_t *handler; | 83 snd_pcm_t *handler; |
78 snd_pcm_format_t format = SND_PCM_FORMAT_S16_LE; | 84 snd_pcm_format_t format = SND_PCM_FORMAT_S16_LE; |
79 unsigned int channels = 2; | 85 unsigned int channels = 2; |
80 unsigned int rate = 48000; | 86 unsigned int rate = 48000; |
94 return NULL; | 100 return NULL; |
95 } | 101 } |
96 printf("device: %d, subdevice: %d\n", snd_pcm_info_get_device(info), | 102 printf("device: %d, subdevice: %d\n", snd_pcm_info_get_device(info), |
97 snd_pcm_info_get_subdevice(info)); | 103 snd_pcm_info_get_subdevice(info)); |
98 { | 104 { |
105 | |
99 snd_ctl_elem_value_t *ctl; | 106 snd_ctl_elem_value_t *ctl; |
100 snd_ctl_t *ctl_handler; | 107 snd_ctl_t *ctl_handler; |
108 snd_ctl_elem_id_t *elem_id; | |
109 unsigned int elem_device; | |
110 const char *elem_name; | |
101 char ctl_name[12]; | 111 char ctl_name[12]; |
102 int ctl_card; | 112 int ctl_card; |
113 //elem_id = 36; | |
103 | 114 |
104 spdif.status[0] = IEC958_AES0_NONAUDIO | | 115 spdif.status[0] = IEC958_AES0_NONAUDIO | |
105 IEC958_AES0_CON_EMPHASIS_NONE; | 116 IEC958_AES0_CON_EMPHASIS_NONE; |
106 spdif.status[1] = IEC958_AES1_CON_ORIGINAL | | 117 spdif.status[1] = IEC958_AES1_CON_ORIGINAL | |
107 IEC958_AES1_CON_PCM_CODER; | 118 IEC958_AES1_CON_PCM_CODER; |
108 spdif.status[2] = 0; | 119 spdif.status[2] = 0; |
109 spdif.status[3] = IEC958_AES3_CON_FS_48000; | 120 spdif.status[3] = IEC958_AES3_CON_FS_48000; |
110 | 121 |
111 snd_ctl_elem_value_alloca(&ctl); | 122 snd_ctl_elem_value_alloca(&ctl); |
112 snd_ctl_elem_value_set_interface(ctl, SND_CTL_ELEM_IFACE_PCM); | 123 snd_ctl_elem_id_alloca(&elem_id); |
124 snd_ctl_elem_value_set_interface(ctl, SND_CTL_ELEM_IFACE_PCM); //SND_CTL_ELEM_IFACE_MIXER | |
113 snd_ctl_elem_value_set_device(ctl, snd_pcm_info_get_device(info)); | 125 snd_ctl_elem_value_set_device(ctl, snd_pcm_info_get_device(info)); |
114 snd_ctl_elem_value_set_subdevice(ctl, snd_pcm_info_get_subdevice(info)); | 126 snd_ctl_elem_value_set_subdevice(ctl, snd_pcm_info_get_subdevice(info)); |
115 snd_ctl_elem_value_set_name(ctl, SND_CTL_NAME_IEC958("", PLAYBACK,PCM_STREAM)); | 127 snd_ctl_elem_value_set_name(ctl,SND_CTL_NAME_IEC958("", PLAYBACK, PCM_STREAM)); //SWITCH |
116 snd_ctl_elem_value_set_iec958(ctl, &spdif); | 128 snd_ctl_elem_value_set_iec958(ctl, &spdif); |
117 ctl_card = snd_pcm_info_get_card(info); | 129 ctl_card = snd_pcm_info_get_card(info); |
118 if (ctl_card < 0) { | 130 if (ctl_card < 0) { |
119 fprintf(stderr, "Unable to setup the IEC958 (S/PDIF) interface - PCM has no assigned card"); | 131 fprintf(stderr, "Unable to setup the IEC958 (S/PDIF) interface - PCM has no assigned card"); |
120 goto __diga_end; | 132 goto __diga_end; |
121 } | 133 } |
134 | |
122 sprintf(ctl_name, "hw:%d", ctl_card); | 135 sprintf(ctl_name, "hw:%d", ctl_card); |
123 printf("hw:%d\n", ctl_card); | 136 printf("hw:%d\n", ctl_card); |
124 if ((err = snd_ctl_open(&ctl_handler, ctl_name, 0)) < 0) { | 137 if ((err = snd_ctl_open(&ctl_handler, ctl_name, 0)) < 0) { |
125 fprintf(stderr, "Unable to open the control interface '%s': %s\n", ctl_name, snd_strerror(err)); | 138 fprintf(stderr, "Unable to open the control interface '%s': %s\n", ctl_name, snd_strerror(err)); |
126 goto __diga_end; | 139 goto __diga_end; |
127 } | 140 } |
128 if ((err = snd_ctl_elem_write(ctl_handler, ctl)) < 0) { | 141 if ((err = snd_ctl_elem_write(ctl_handler, ctl)) < 0) { |
129 fprintf(stderr, "Unable to update the IEC958 control: %s\n", snd_strerror(err)); | 142 //fprintf(stderr, "Unable to update the IEC958 control: %s\n", snd_strerror(err)); |
143 printf("alsa-spdif-init: cant set spdif-trough automatically\n"); | |
130 goto __diga_end; | 144 goto __diga_end; |
131 } | 145 } |
146 //test area | |
147 /* elem_device = snd_ctl_elem_id_get_device(elem_id); */ | |
148 /* elem_name = snd_ctl_elem_value_get_name(ctl); */ | |
149 /* snd_ctl_elem_value_get_iec958(ctl, &spdif); */ | |
150 /* printf("spdif = %i, device = %i\n", &spdif, elem_device); */ | |
151 /* printf("name = %s\n", elem_name); */ | |
152 //end test area | |
153 | |
154 | |
132 snd_ctl_close(ctl_handler); | 155 snd_ctl_close(ctl_handler); |
133 __diga_end: | 156 __diga_end: |
134 | 157 |
135 } | 158 } |
136 | 159 |
316 ao_data.samplerate = rate_hz; | 339 ao_data.samplerate = rate_hz; |
317 ao_data.bps = channels; /* really this is bytes per frame so bad varname */ | 340 ao_data.bps = channels; /* really this is bytes per frame so bad varname */ |
318 ao_data.format = format; | 341 ao_data.format = format; |
319 ao_data.channels = channels; | 342 ao_data.channels = channels; |
320 ao_data.outburst = OUTBURST; | 343 ao_data.outburst = OUTBURST; |
321 ao_data.buffersize = MAX_OUTBURST; // was 16384 | 344 //ao_data.buffersize = MAX_OUTBURST; // was 16384 |
322 | 345 |
323 switch (format) | 346 switch (format) |
324 { | 347 { |
325 case AFMT_S8: | 348 case AFMT_S8: |
326 alsa_format = SND_PCM_FORMAT_S8; | 349 alsa_format = SND_PCM_FORMAT_S8; |
487 else { | 510 else { |
488 open_mode = 0; | 511 open_mode = 0; |
489 set_block_mode = 0; | 512 set_block_mode = 0; |
490 str_block_mode = "block-mode"; | 513 str_block_mode = "block-mode"; |
491 } | 514 } |
492 | 515 //cvs cosmetics fix |
516 //sets buff/chunksize if its set manually | |
517 if (ao_data.buffersize) { | |
518 switch (ao_data.buffersize) | |
519 { | |
520 case 1: | |
521 alsa_fragcount = 16; | |
522 chunk_size = 512; | |
523 if (verbose) { | |
524 printf("alsa-init: buffersize set manually to 8192\n"); | |
525 printf("alsa-init: chunksize set manually to 512\n"); | |
526 } | |
527 break; | |
528 case 2: | |
529 alsa_fragcount = 8; | |
530 chunk_size = 1024; | |
531 if (verbose) { | |
532 printf("alsa-init: buffersize set manually to 8192\n"); | |
533 printf("alsa-init: chunksize set manually to 1024\n"); | |
534 } | |
535 break; | |
536 case 3: | |
537 alsa_fragcount = 32; | |
538 chunk_size = 512; | |
539 if (verbose) { | |
540 printf("alsa-init: buffersize set manually to 16384\n"); | |
541 printf("alsa-init: chunksize set manually to 512\n"); | |
542 } | |
543 break; | |
544 case 4: | |
545 alsa_fragcount = 16; | |
546 chunk_size = 1024; | |
547 if (verbose) { | |
548 printf("alsa-init: buffersize set manually to 16384\n"); | |
549 printf("alsa-init: chunksize set manually to 1024\n"); | |
550 } | |
551 break; | |
552 default: | |
553 alsa_fragcount = 16; | |
554 if (ao_mmap) | |
555 chunk_size = 512; | |
556 else | |
557 chunk_size = 1024; | |
558 break; | |
559 } | |
560 } | |
561 | |
493 if (!alsa_handler) { | 562 if (!alsa_handler) { |
494 //modes = 0, SND_PCM_NONBLOCK, SND_PCM_ASYNC | 563 //modes = 0, SND_PCM_NONBLOCK, SND_PCM_ASYNC |
495 if ((err = snd_pcm_open(&alsa_handler, alsa_device, SND_PCM_STREAM_PLAYBACK, open_mode)) < 0) | 564 if ((err = snd_pcm_open(&alsa_handler, alsa_device, SND_PCM_STREAM_PLAYBACK, open_mode)) < 0) |
496 { | 565 { |
497 if (ao_noblock) { | 566 if (ao_noblock) { |
535 snd_pcm_access_mask_set(mask, SND_PCM_ACCESS_MMAP_COMPLEX); | 604 snd_pcm_access_mask_set(mask, SND_PCM_ACCESS_MMAP_COMPLEX); |
536 err = snd_pcm_hw_params_set_access_mask(alsa_handler, alsa_hwparams, mask); | 605 err = snd_pcm_hw_params_set_access_mask(alsa_handler, alsa_hwparams, mask); |
537 printf("alsa-init: mmap set\n"); | 606 printf("alsa-init: mmap set\n"); |
538 } else { | 607 } else { |
539 err = snd_pcm_hw_params_set_access(alsa_handler, alsa_hwparams,SND_PCM_ACCESS_RW_INTERLEAVED); | 608 err = snd_pcm_hw_params_set_access(alsa_handler, alsa_hwparams,SND_PCM_ACCESS_RW_INTERLEAVED); |
540 printf("alsa-init: interleave set\n"); | |
541 } | 609 } |
542 if (err < 0) { | 610 if (err < 0) { |
543 printf("alsa-init: unable to set access type: %s\n", snd_strerror(err)); | 611 printf("alsa-init: unable to set access type: %s\n", snd_strerror(err)); |
544 return (0); | 612 return (0); |
545 } | 613 } |
592 #endif | 660 #endif |
593 | 661 |
594 #ifdef SET_CHUNKSIZE | 662 #ifdef SET_CHUNKSIZE |
595 { | 663 { |
596 //set chunksize | 664 //set chunksize |
597 chunk_size = alsa_fragsize / 4; | |
598 | |
599 if ((err = snd_pcm_hw_params_set_period_size(alsa_handler, alsa_hwparams, chunk_size, 0)) < 0) | 665 if ((err = snd_pcm_hw_params_set_period_size(alsa_handler, alsa_hwparams, chunk_size, 0)) < 0) |
600 { | 666 { |
601 printf("alsa-init: unable to set periodsize: %s\n", snd_strerror(err)); | 667 printf("alsa-init: unable to set periodsize: %s\n", snd_strerror(err)); |
602 return(0); | 668 return(0); |
603 } | 669 } |
651 return(0); | 717 return(0); |
652 } | 718 } |
653 | 719 |
654 //set min available frames to consider pcm ready (4) | 720 //set min available frames to consider pcm ready (4) |
655 //increased for nonblock-mode should be set dynamically later | 721 //increased for nonblock-mode should be set dynamically later |
656 if ((err = snd_pcm_sw_params_set_avail_min(alsa_handler, alsa_swparams, chunk_size)) < 0) | 722 if ((err = snd_pcm_sw_params_set_avail_min(alsa_handler, alsa_swparams, 4)) < 0) |
657 { | 723 { |
658 printf("alsa-init: unable to set avail_min %s\n",snd_strerror(err)); | 724 printf("alsa-init: unable to set avail_min %s\n",snd_strerror(err)); |
659 return(0); | 725 return(0); |
660 } | 726 } |
661 | 727 |
773 if (verbose) | 839 if (verbose) |
774 printf("alsa-reset: reset nonblocked"); | 840 printf("alsa-reset: reset nonblocked"); |
775 return; | 841 return; |
776 } | 842 } |
777 } | 843 } |
844 | |
845 #ifdef USE_POLL | |
846 static int wait_for_poll(snd_pcm_t *handle, struct pollfd *ufds, unsigned int count) | |
847 { | |
848 unsigned short revents; | |
849 | |
850 while (1) { | |
851 poll(ufds, count, -1); | |
852 snd_pcm_poll_descriptors_revents(handle, ufds, count, &revents); | |
853 if (revents & POLLERR) | |
854 return -EIO; | |
855 if (revents & POLLOUT) | |
856 return 0; | |
857 } | |
858 } | |
859 #endif | |
778 | 860 |
779 #ifndef timersub | 861 #ifndef timersub |
780 #define timersub(a, b, result) \ | 862 #define timersub(a, b, result) \ |
781 do { \ | 863 do { \ |
782 (result)->tv_sec = (a)->tv_sec - (b)->tv_sec; \ | 864 (result)->tv_sec = (a)->tv_sec - (b)->tv_sec; \ |
817 } | 899 } |
818 | 900 |
819 return(1); /* ok, data should be accepted again */ | 901 return(1); /* ok, data should be accepted again */ |
820 } | 902 } |
821 | 903 |
904 static int play(void* data, int len, int flags) | |
905 { | |
906 int result; | |
907 if (ao_mmap) | |
908 result = play_mmap(data, len); | |
909 else | |
910 result = play_normal(data, len); | |
911 | |
912 return result; | |
913 } | |
914 | |
822 /* | 915 /* |
823 plays 'len' bytes of 'data' | 916 plays 'len' bytes of 'data' |
824 returns: number of bytes played | 917 returns: number of bytes played |
825 modified last at 29.06.02 by jp | 918 modified last at 29.06.02 by jp |
826 thanxs for marius <marius@rospot.com> for giving us the light ;) | 919 thanxs for marius <marius@rospot.com> for giving us the light ;) |
827 */ | 920 */ |
828 | 921 |
829 static int play(void* data, int len, int flags) | 922 static int play_normal(void* data, int len) |
830 { | 923 { |
831 | 924 |
832 //ao_data.bps is always 4 cause its set to channels * 2 by alsa_format?? | 925 //ao_data.bps is always 4 for 2 chn S16_LE |
833 int num_frames = len / ao_data.bps; | 926 int num_frames = len / ao_data.bps; |
834 signed short *output_samples=data; | 927 signed short *output_samples=data; |
835 snd_pcm_sframes_t res = 0; | 928 snd_pcm_sframes_t res = 0; |
836 | 929 |
837 //printf("alsa-play: frames=%i, len=%i",num_frames,len); | 930 //printf("alsa-play: frames=%i, len=%i",num_frames,len); |
841 return 0; | 934 return 0; |
842 } | 935 } |
843 | 936 |
844 while (num_frames > 0) { | 937 while (num_frames > 0) { |
845 | 938 |
846 if (ao_mmap) { | 939 res = snd_pcm_writei(alsa_handler, (void *)output_samples, num_frames); |
847 res = snd_pcm_mmap_writei(alsa_handler, (void *)output_samples, num_frames); | |
848 } else { | |
849 res = snd_pcm_writei(alsa_handler, (void *)output_samples, num_frames); | |
850 } | |
851 | 940 |
852 if (res == -EAGAIN) { | 941 if (res == -EAGAIN) { |
853 snd_pcm_wait(alsa_handler, 1000); | 942 snd_pcm_wait(alsa_handler, 1000); |
854 } | 943 } |
855 else if (res == -EPIPE) { /* underrun */ | 944 else if (res == -EPIPE) { /* underrun */ |
884 return 0; | 973 return 0; |
885 } | 974 } |
886 return res < 0 ? (int)res : len; | 975 return res < 0 ? (int)res : len; |
887 } | 976 } |
888 | 977 |
978 /* mmap-mode mainly based on descriptions by Joshua Haberman <joshua@haberman.com> | |
979 * 'An overview of the ALSA API' http://people.debian.org/~joshua/x66.html | |
980 * and some help by Paul Davis <pbd@op.net> */ | |
981 | |
982 static int play_mmap(void* data, int len) | |
983 { | |
984 snd_pcm_sframes_t commitres, frames_available; | |
985 snd_pcm_uframes_t frames_transmit, size, offset; | |
986 const snd_pcm_channel_area_t *area; | |
987 void *outbuffer; | |
988 int err, result; | |
989 | |
990 #ifdef USE_POLL //seems not really be needed | |
991 struct pollfd *ufds; | |
992 int count; | |
993 | |
994 count = snd_pcm_poll_descriptors_count (alsa_handler); | |
995 ufds = malloc(sizeof(struct pollfd) * count); | |
996 snd_pcm_poll_descriptors(alsa_handler, ufds, count); | |
997 | |
998 //first wait_for_poll | |
999 if (err = (wait_for_poll(alsa_handler, ufds, count) < 0)) { | |
1000 if (snd_pcm_state(alsa_handler) == SND_PCM_STATE_XRUN || | |
1001 snd_pcm_state(alsa_handler) == SND_PCM_STATE_SUSPENDED) { | |
1002 xrun("play"); | |
1003 } | |
1004 } | |
1005 #endif | |
1006 | |
1007 outbuffer = alloca(ao_data.buffersize); | |
1008 | |
1009 //don't trust get_space() ;) | |
1010 frames_available = snd_pcm_avail_update(alsa_handler) * ao_data.bps; | |
1011 if (frames_available < 0) | |
1012 xrun("play"); | |
1013 | |
1014 if (frames_available < 4) { | |
1015 if (first) { | |
1016 first = 0; | |
1017 snd_pcm_start(alsa_handler); | |
1018 } | |
1019 else { //FIXME should break and return 0? | |
1020 snd_pcm_wait(alsa_handler, -1); | |
1021 first = 1; | |
1022 } | |
1023 } | |
1024 | |
1025 /* len is simply the available bufferspace got by get_space() | |
1026 * but real avail_buffer in frames is ab/ao_data.bps */ | |
1027 size = len / ao_data.bps; | |
1028 | |
1029 //if (verbose) | |
1030 //printf("len: %i size %i, f_avail %i, bps %i ...\n", len, size, frames_available, ao_data.bps); | |
1031 | |
1032 frames_transmit = size; | |
1033 | |
1034 /* prepare areas and set sw-pointers | |
1035 * frames_transmit returns the real available buffer-size | |
1036 * sometimes != frames_available cause of ringbuffer 'emulation' */ | |
1037 snd_pcm_mmap_begin(alsa_handler, &area, &offset, &frames_transmit); | |
1038 | |
1039 /* this is specific to interleaved streams (or non-interleaved | |
1040 * streams with only one channel) */ | |
1041 outbuffer = ((char *) area->addr + (area->first + area->step * offset) / 8); //8 | |
1042 | |
1043 //write data | |
1044 memcpy(outbuffer, data, (frames_transmit * ao_data.bps)); | |
1045 | |
1046 commitres = snd_pcm_mmap_commit(alsa_handler, offset, frames_transmit); | |
1047 | |
1048 if (commitres < 0 || commitres != frames_transmit) { | |
1049 if (snd_pcm_state(alsa_handler) == SND_PCM_STATE_XRUN || | |
1050 snd_pcm_state(alsa_handler) == SND_PCM_STATE_SUSPENDED) { | |
1051 xrun("play"); | |
1052 } | |
1053 } | |
1054 | |
1055 //if (verbose) | |
1056 //printf("mmap ft: %i, cres: %i\n", frames_transmit, commitres); | |
1057 | |
1058 /* err = snd_pcm_area_copy(&area, offset, &data, offset, len, alsa_format); */ | |
1059 /* if (err < 0) { */ | |
1060 /* printf("area-copy-error\n"); */ | |
1061 /* return 0; */ | |
1062 /* } */ | |
1063 | |
1064 | |
1065 //calculate written frames! | |
1066 result = commitres * ao_data.bps; | |
1067 | |
1068 | |
1069 /* if (verbose) { */ | |
1070 /* if (len == result) */ | |
1071 /* printf("result: %i, frames written: %i ...\n", result, frames_transmit); */ | |
1072 /* else */ | |
1073 /* printf("result: %i, frames written: %i, result != len ...\n", result, frames_transmit); */ | |
1074 /* } */ | |
1075 | |
1076 //mplayer doesn't like -result | |
1077 if (result < 0) | |
1078 result = 0; | |
1079 | |
1080 #ifdef USE_POLL | |
1081 free(ufds); | |
1082 #endif | |
1083 | |
1084 return result; | |
1085 } | |
1086 | |
889 /* how many byes are free in the buffer */ | 1087 /* how many byes are free in the buffer */ |
890 static int get_space() | 1088 static int get_space() |
891 { | 1089 { |
892 snd_pcm_status_t *status; | 1090 snd_pcm_status_t *status; |
893 int ret; | 1091 int ret; |
910 switch(snd_pcm_status_get_state(status)) | 1108 switch(snd_pcm_status_get_state(status)) |
911 { | 1109 { |
912 case SND_PCM_STATE_OPEN: | 1110 case SND_PCM_STATE_OPEN: |
913 str_status = "open"; | 1111 str_status = "open"; |
914 case SND_PCM_STATE_PREPARED: | 1112 case SND_PCM_STATE_PREPARED: |
915 if (str_status != "open") | 1113 if (str_status != "open") { |
916 str_status = "prepared"; | 1114 str_status = "prepared"; |
1115 first = 1; | |
1116 ret = snd_pcm_status_get_avail(status) * ao_data.bps; | |
1117 if (ret == 0) //ugly workaround for hang in mmap-mode | |
1118 ret = 10; | |
1119 break; | |
1120 } | |
917 case SND_PCM_STATE_RUNNING: | 1121 case SND_PCM_STATE_RUNNING: |
918 ret = snd_pcm_status_get_avail(status) * ao_data.bps; | 1122 ret = snd_pcm_status_get_avail(status) * ao_data.bps; |
919 //avail_frames = snd_pcm_avail_update(alsa_handler) * ao_data.bps; | 1123 //avail_frames = snd_pcm_avail_update(alsa_handler) * ao_data.bps; |
920 if (str_status != "open" && str_status != "prepared") | 1124 if (str_status != "open" && str_status != "prepared") |
921 str_status = "running"; | 1125 str_status = "running"; |
926 ret = 0; | 1130 ret = 0; |
927 break; | 1131 break; |
928 case SND_PCM_STATE_XRUN: | 1132 case SND_PCM_STATE_XRUN: |
929 xrun("space"); | 1133 xrun("space"); |
930 str_status = "xrun"; | 1134 str_status = "xrun"; |
1135 first = 1; | |
931 ret = 0; | 1136 ret = 0; |
932 break; | 1137 break; |
933 default: | 1138 default: |
934 str_status = "undefined"; | 1139 str_status = "undefined"; |
935 ret = 0; | 1140 ret = snd_pcm_status_get_avail(status) * ao_data.bps; |
1141 if (ret <= 0) { | |
1142 xrun("space"); | |
1143 } | |
936 } | 1144 } |
937 | 1145 |
938 if (verbose && str_status != "running") | 1146 if (verbose && str_status != "running") |
939 printf("alsa-space: free space = %i, status=%i, %s --\n", ret, status, str_status); | 1147 printf("alsa-space: free space = %i, status=%i, %s --\n", ret, status, str_status); |
940 snd_pcm_status_free(status); | 1148 snd_pcm_status_free(status); |