diff options
Diffstat (limited to 'src/sound.c')
| -rw-r--r-- | src/sound.c | 413 |
1 files changed, 403 insertions, 10 deletions
diff --git a/src/sound.c b/src/sound.c index 0fbeceb4b9e..af2369040cc 100644 --- a/src/sound.c +++ b/src/sound.c | |||
| @@ -73,6 +73,10 @@ Boston, MA 02110-1301, USA. */ | |||
| 73 | #ifdef HAVE_SOUNDCARD_H | 73 | #ifdef HAVE_SOUNDCARD_H |
| 74 | #include <soundcard.h> | 74 | #include <soundcard.h> |
| 75 | #endif | 75 | #endif |
| 76 | #ifdef HAVE_ALSA | ||
| 77 | #include <asoundlib.h> | ||
| 78 | #endif | ||
| 79 | |||
| 76 | /* END: Non Windows Includes */ | 80 | /* END: Non Windows Includes */ |
| 77 | 81 | ||
| 78 | #else /* WINDOWSNT */ | 82 | #else /* WINDOWSNT */ |
| @@ -109,7 +113,8 @@ enum sound_attr | |||
| 109 | SOUND_ATTR_SENTINEL | 113 | SOUND_ATTR_SENTINEL |
| 110 | }; | 114 | }; |
| 111 | 115 | ||
| 112 | static void sound_perror P_ ((char *)); | 116 | static void alsa_sound_perror P_ ((char *, int)) NO_RETURN; |
| 117 | static void sound_perror P_ ((char *)) NO_RETURN; | ||
| 113 | static void sound_warning P_ ((char *)); | 118 | static void sound_warning P_ ((char *)); |
| 114 | static int parse_sound P_ ((Lisp_Object, Lisp_Object *)); | 119 | static int parse_sound P_ ((Lisp_Object, Lisp_Object *)); |
| 115 | 120 | ||
| @@ -121,6 +126,9 @@ static int parse_sound P_ ((Lisp_Object, Lisp_Object *)); | |||
| 121 | #ifndef DEFAULT_SOUND_DEVICE | 126 | #ifndef DEFAULT_SOUND_DEVICE |
| 122 | #define DEFAULT_SOUND_DEVICE "/dev/dsp" | 127 | #define DEFAULT_SOUND_DEVICE "/dev/dsp" |
| 123 | #endif | 128 | #endif |
| 129 | #ifndef DEFAULT_ALSA_SOUND_DEVICE | ||
| 130 | #define DEFAULT_ALSA_SOUND_DEVICE "default" | ||
| 131 | #endif | ||
| 124 | 132 | ||
| 125 | 133 | ||
| 126 | /* Structure forward declarations. */ | 134 | /* Structure forward declarations. */ |
| @@ -227,6 +235,10 @@ struct sound_device | |||
| 227 | void (* choose_format) P_ ((struct sound_device *sd, | 235 | void (* choose_format) P_ ((struct sound_device *sd, |
| 228 | struct sound *s)); | 236 | struct sound *s)); |
| 229 | 237 | ||
| 238 | /* Return a preferred data size in bytes to be sent to write (below) | ||
| 239 | each time. 2048 is used if this is NULL. */ | ||
| 240 | int (* period_size) P_ ((struct sound_device *sd)); | ||
| 241 | |||
| 230 | /* Write NYBTES bytes from BUFFER to device SD. */ | 242 | /* Write NYBTES bytes from BUFFER to device SD. */ |
| 231 | void (* write) P_ ((struct sound_device *sd, const char *buffer, | 243 | void (* write) P_ ((struct sound_device *sd, const char *buffer, |
| 232 | int nbytes)); | 244 | int nbytes)); |
| @@ -280,7 +292,7 @@ static void vox_open P_ ((struct sound_device *)); | |||
| 280 | static void vox_configure P_ ((struct sound_device *)); | 292 | static void vox_configure P_ ((struct sound_device *)); |
| 281 | static void vox_close P_ ((struct sound_device *sd)); | 293 | static void vox_close P_ ((struct sound_device *sd)); |
| 282 | static void vox_choose_format P_ ((struct sound_device *, struct sound *)); | 294 | static void vox_choose_format P_ ((struct sound_device *, struct sound *)); |
| 283 | static void vox_init P_ ((struct sound_device *)); | 295 | static int vox_init P_ ((struct sound_device *)); |
| 284 | static void vox_write P_ ((struct sound_device *, const char *, int)); | 296 | static void vox_write P_ ((struct sound_device *, const char *, int)); |
| 285 | static void find_sound_type P_ ((struct sound *)); | 297 | static void find_sound_type P_ ((struct sound *)); |
| 286 | static u_int32_t le2hl P_ ((u_int32_t)); | 298 | static u_int32_t le2hl P_ ((u_int32_t)); |
| @@ -604,7 +616,7 @@ wav_play (s, sd) | |||
| 604 | { | 616 | { |
| 605 | char *buffer; | 617 | char *buffer; |
| 606 | int nbytes; | 618 | int nbytes; |
| 607 | int blksize = 2048; | 619 | int blksize = sd->period_size ? sd->period_size (sd) : 2048; |
| 608 | 620 | ||
| 609 | buffer = (char *) alloca (blksize); | 621 | buffer = (char *) alloca (blksize); |
| 610 | lseek (s->fd, sizeof *header, SEEK_SET); | 622 | lseek (s->fd, sizeof *header, SEEK_SET); |
| @@ -633,7 +645,8 @@ enum au_encoding | |||
| 633 | AU_ENCODING_32, | 645 | AU_ENCODING_32, |
| 634 | AU_ENCODING_IEEE32, | 646 | AU_ENCODING_IEEE32, |
| 635 | AU_ENCODING_IEEE64, | 647 | AU_ENCODING_IEEE64, |
| 636 | AU_COMPRESSED = 23 | 648 | AU_COMPRESSED = 23, |
| 649 | AU_ENCODING_ALAW_8 = 27 | ||
| 637 | }; | 650 | }; |
| 638 | 651 | ||
| 639 | 652 | ||
| @@ -689,7 +702,7 @@ au_play (s, sd) | |||
| 689 | SBYTES (s->data) - header->data_offset); | 702 | SBYTES (s->data) - header->data_offset); |
| 690 | else | 703 | else |
| 691 | { | 704 | { |
| 692 | int blksize = 2048; | 705 | int blksize = sd->period_size ? sd->period_size (sd) : 2048; |
| 693 | char *buffer; | 706 | char *buffer; |
| 694 | int nbytes; | 707 | int nbytes; |
| 695 | 708 | ||
| @@ -868,16 +881,33 @@ vox_choose_format (sd, s) | |||
| 868 | /* Initialize device SD. Set up the interface functions in the device | 881 | /* Initialize device SD. Set up the interface functions in the device |
| 869 | structure. */ | 882 | structure. */ |
| 870 | 883 | ||
| 871 | static void | 884 | static int |
| 872 | vox_init (sd) | 885 | vox_init (sd) |
| 873 | struct sound_device *sd; | 886 | struct sound_device *sd; |
| 874 | { | 887 | { |
| 888 | char *file; | ||
| 889 | int fd; | ||
| 890 | |||
| 891 | /* Open the sound device. Default is /dev/dsp. */ | ||
| 892 | if (sd->file) | ||
| 893 | file = sd->file; | ||
| 894 | else | ||
| 895 | file = DEFAULT_SOUND_DEVICE; | ||
| 896 | fd = emacs_open (file, O_WRONLY, 0); | ||
| 897 | if (fd >= 0) | ||
| 898 | emacs_close (fd); | ||
| 899 | else | ||
| 900 | return 0; | ||
| 901 | |||
| 875 | sd->fd = -1; | 902 | sd->fd = -1; |
| 876 | sd->open = vox_open; | 903 | sd->open = vox_open; |
| 877 | sd->close = vox_close; | 904 | sd->close = vox_close; |
| 878 | sd->configure = vox_configure; | 905 | sd->configure = vox_configure; |
| 879 | sd->choose_format = vox_choose_format; | 906 | sd->choose_format = vox_choose_format; |
| 880 | sd->write = vox_write; | 907 | sd->write = vox_write; |
| 908 | sd->period_size = NULL; | ||
| 909 | |||
| 910 | return 1; | ||
| 881 | } | 911 | } |
| 882 | 912 | ||
| 883 | /* Write NBYTES bytes from BUFFER to device SD. */ | 913 | /* Write NBYTES bytes from BUFFER to device SD. */ |
| @@ -893,6 +923,368 @@ vox_write (sd, buffer, nbytes) | |||
| 893 | sound_perror ("Error writing to sound device"); | 923 | sound_perror ("Error writing to sound device"); |
| 894 | } | 924 | } |
| 895 | 925 | ||
| 926 | #ifdef HAVE_ALSA | ||
| 927 | /*********************************************************************** | ||
| 928 | ALSA Driver Interface | ||
| 929 | ***********************************************************************/ | ||
| 930 | |||
| 931 | /* This driver is available on GNU/Linux. */ | ||
| 932 | |||
| 933 | static void | ||
| 934 | alsa_sound_perror (msg, err) | ||
| 935 | char *msg; | ||
| 936 | int err; | ||
| 937 | { | ||
| 938 | error ("%s: %s", msg, snd_strerror (err)); | ||
| 939 | } | ||
| 940 | |||
| 941 | struct alsa_params | ||
| 942 | { | ||
| 943 | snd_pcm_t *handle; | ||
| 944 | snd_pcm_hw_params_t *hwparams; | ||
| 945 | snd_pcm_sw_params_t *swparams; | ||
| 946 | snd_pcm_uframes_t period_size; | ||
| 947 | }; | ||
| 948 | |||
| 949 | /* Open device SD. If SD->file is non-null, open that device, | ||
| 950 | otherwise use a default device name. */ | ||
| 951 | |||
| 952 | static void | ||
| 953 | alsa_open (sd) | ||
| 954 | struct sound_device *sd; | ||
| 955 | { | ||
| 956 | char *file; | ||
| 957 | struct alsa_params *p; | ||
| 958 | int err; | ||
| 959 | |||
| 960 | /* Open the sound device. Default is "default". */ | ||
| 961 | if (sd->file) | ||
| 962 | file = sd->file; | ||
| 963 | else | ||
| 964 | file = DEFAULT_ALSA_SOUND_DEVICE; | ||
| 965 | |||
| 966 | p = xmalloc (sizeof (*p)); | ||
| 967 | p->handle = NULL; | ||
| 968 | p->hwparams = NULL; | ||
| 969 | p->swparams = NULL; | ||
| 970 | |||
| 971 | sd->fd = -1; | ||
| 972 | sd->data = p; | ||
| 973 | |||
| 974 | |||
| 975 | err = snd_pcm_open (&p->handle, file, SND_PCM_STREAM_PLAYBACK, 0); | ||
| 976 | if (err < 0) | ||
| 977 | alsa_sound_perror (file, err); | ||
| 978 | } | ||
| 979 | |||
| 980 | static int | ||
| 981 | alsa_period_size (sd) | ||
| 982 | struct sound_device *sd; | ||
| 983 | { | ||
| 984 | struct alsa_params *p = (struct alsa_params *) sd->data; | ||
| 985 | return p->period_size; | ||
| 986 | } | ||
| 987 | |||
| 988 | static void | ||
| 989 | alsa_configure (sd) | ||
| 990 | struct sound_device *sd; | ||
| 991 | { | ||
| 992 | int val, err, dir; | ||
| 993 | struct alsa_params *p = (struct alsa_params *) sd->data; | ||
| 994 | snd_pcm_uframes_t buffer_size; | ||
| 995 | |||
| 996 | xassert (p->handle != 0); | ||
| 997 | |||
| 998 | err = snd_pcm_hw_params_malloc (&p->hwparams); | ||
| 999 | if (err < 0) | ||
| 1000 | alsa_sound_perror ("Could not allocate hardware parameter structure", err); | ||
| 1001 | |||
| 1002 | err = snd_pcm_sw_params_malloc (&p->swparams); | ||
| 1003 | if (err < 0) | ||
| 1004 | alsa_sound_perror ("Could not allocate software parameter structure", err); | ||
| 1005 | |||
| 1006 | err = snd_pcm_hw_params_any (p->handle, p->hwparams); | ||
| 1007 | if (err < 0) | ||
| 1008 | alsa_sound_perror ("Could not initialize hardware parameter structure", err); | ||
| 1009 | |||
| 1010 | err = snd_pcm_hw_params_set_access (p->handle, p->hwparams, | ||
| 1011 | SND_PCM_ACCESS_RW_INTERLEAVED); | ||
| 1012 | if (err < 0) | ||
| 1013 | alsa_sound_perror ("Could not set access type", err); | ||
| 1014 | |||
| 1015 | val = sd->format; | ||
| 1016 | err = snd_pcm_hw_params_set_format (p->handle, p->hwparams, val); | ||
| 1017 | if (err < 0) | ||
| 1018 | alsa_sound_perror ("Could not set sound format", err); | ||
| 1019 | |||
| 1020 | val = sd->sample_rate; | ||
| 1021 | err = snd_pcm_hw_params_set_rate_near (p->handle, p->hwparams, &val, 0); | ||
| 1022 | if (err < 0) | ||
| 1023 | alsa_sound_perror ("Could not set sample rate", err); | ||
| 1024 | |||
| 1025 | val = sd->channels; | ||
| 1026 | err = snd_pcm_hw_params_set_channels (p->handle, p->hwparams, val); | ||
| 1027 | if (err < 0) | ||
| 1028 | alsa_sound_perror ("Could not set channel count", err); | ||
| 1029 | |||
| 1030 | err = snd_pcm_hw_params (p->handle, p->hwparams); | ||
| 1031 | if (err < 0) | ||
| 1032 | alsa_sound_perror ("Could not set parameters", err); | ||
| 1033 | |||
| 1034 | |||
| 1035 | err = snd_pcm_hw_params_get_period_size (p->hwparams, &p->period_size, &dir); | ||
| 1036 | if (err < 0) | ||
| 1037 | alsa_sound_perror ("Unable to get period size for playback", err); | ||
| 1038 | |||
| 1039 | err = snd_pcm_hw_params_get_buffer_size (p->hwparams, &buffer_size); | ||
| 1040 | if (err < 0) | ||
| 1041 | alsa_sound_perror("Unable to get buffer size for playback", err); | ||
| 1042 | |||
| 1043 | err = snd_pcm_sw_params_current (p->handle, p->swparams); | ||
| 1044 | if (err < 0) | ||
| 1045 | alsa_sound_perror ("Unable to determine current swparams for playback", | ||
| 1046 | err); | ||
| 1047 | |||
| 1048 | /* Start the transfer when the buffer is almost full */ | ||
| 1049 | err = snd_pcm_sw_params_set_start_threshold (p->handle, p->swparams, | ||
| 1050 | (buffer_size / p->period_size) | ||
| 1051 | * p->period_size); | ||
| 1052 | if (err < 0) | ||
| 1053 | alsa_sound_perror ("Unable to set start threshold mode for playback", err); | ||
| 1054 | |||
| 1055 | /* Allow the transfer when at least period_size samples can be processed */ | ||
| 1056 | err = snd_pcm_sw_params_set_avail_min (p->handle, p->swparams, p->period_size); | ||
| 1057 | if (err < 0) | ||
| 1058 | alsa_sound_perror ("Unable to set avail min for playback", err); | ||
| 1059 | |||
| 1060 | /* Align all transfers to 1 period */ | ||
| 1061 | err = snd_pcm_sw_params_set_xfer_align (p->handle, p->swparams, | ||
| 1062 | p->period_size); | ||
| 1063 | if (err < 0) | ||
| 1064 | alsa_sound_perror ("Unable to set transfer align for playback", err); | ||
| 1065 | |||
| 1066 | err = snd_pcm_sw_params (p->handle, p->swparams); | ||
| 1067 | if (err < 0) | ||
| 1068 | alsa_sound_perror ("Unable to set sw params for playback\n", err); | ||
| 1069 | |||
| 1070 | snd_pcm_hw_params_free (p->hwparams); | ||
| 1071 | p->hwparams = NULL; | ||
| 1072 | snd_pcm_sw_params_free (p->swparams); | ||
| 1073 | p->swparams = NULL; | ||
| 1074 | |||
| 1075 | err = snd_pcm_prepare (p->handle); | ||
| 1076 | if (err < 0) | ||
| 1077 | alsa_sound_perror ("Could not prepare audio interface for use", err); | ||
| 1078 | |||
| 1079 | if (sd->volume > 0) | ||
| 1080 | { | ||
| 1081 | int chn; | ||
| 1082 | snd_mixer_t *handle; | ||
| 1083 | snd_mixer_elem_t *e; | ||
| 1084 | char *file = sd->file ? sd->file : DEFAULT_ALSA_SOUND_DEVICE; | ||
| 1085 | |||
| 1086 | if (snd_mixer_open (&handle, 0) >= 0) | ||
| 1087 | { | ||
| 1088 | if (snd_mixer_attach (handle, file) >= 0 | ||
| 1089 | && snd_mixer_load (handle) >= 0 | ||
| 1090 | && snd_mixer_selem_register (handle, NULL, NULL) >= 0) | ||
| 1091 | for (e = snd_mixer_first_elem (handle); | ||
| 1092 | e; | ||
| 1093 | e = snd_mixer_elem_next (e)) | ||
| 1094 | { | ||
| 1095 | if (snd_mixer_selem_has_playback_volume (e)) | ||
| 1096 | { | ||
| 1097 | long pmin, pmax; | ||
| 1098 | snd_mixer_selem_get_playback_volume_range (e, &pmin, &pmax); | ||
| 1099 | long vol = pmin + (sd->volume * (pmax - pmin)) / 100; | ||
| 1100 | |||
| 1101 | for (chn = 0; chn <= SND_MIXER_SCHN_LAST; chn++) | ||
| 1102 | snd_mixer_selem_set_playback_volume (e, chn, vol); | ||
| 1103 | } | ||
| 1104 | } | ||
| 1105 | snd_mixer_close(handle); | ||
| 1106 | } | ||
| 1107 | } | ||
| 1108 | } | ||
| 1109 | |||
| 1110 | |||
| 1111 | /* Close device SD if it is open. */ | ||
| 1112 | |||
| 1113 | static void | ||
| 1114 | alsa_close (sd) | ||
| 1115 | struct sound_device *sd; | ||
| 1116 | { | ||
| 1117 | struct alsa_params *p = (struct alsa_params *) sd->data; | ||
| 1118 | if (p) | ||
| 1119 | { | ||
| 1120 | if (p->hwparams) | ||
| 1121 | snd_pcm_hw_params_free (p->hwparams); | ||
| 1122 | if (p->swparams) | ||
| 1123 | snd_pcm_sw_params_free (p->swparams); | ||
| 1124 | if (p->handle) | ||
| 1125 | { | ||
| 1126 | snd_pcm_drain(p->handle); | ||
| 1127 | snd_pcm_close (p->handle); | ||
| 1128 | } | ||
| 1129 | free (p); | ||
| 1130 | } | ||
| 1131 | } | ||
| 1132 | |||
| 1133 | /* Choose device-dependent format for device SD from sound file S. */ | ||
| 1134 | |||
| 1135 | static void | ||
| 1136 | alsa_choose_format (sd, s) | ||
| 1137 | struct sound_device *sd; | ||
| 1138 | struct sound *s; | ||
| 1139 | { | ||
| 1140 | struct alsa_params *p = (struct alsa_params *) sd->data; | ||
| 1141 | if (s->type == RIFF) | ||
| 1142 | { | ||
| 1143 | struct wav_header *h = (struct wav_header *) s->header; | ||
| 1144 | if (h->precision == 8) | ||
| 1145 | sd->format = SND_PCM_FORMAT_U8; | ||
| 1146 | else if (h->precision == 16) | ||
| 1147 | sd->format = SND_PCM_FORMAT_S16_LE; | ||
| 1148 | else | ||
| 1149 | error ("Unsupported WAV file format"); | ||
| 1150 | } | ||
| 1151 | else if (s->type == SUN_AUDIO) | ||
| 1152 | { | ||
| 1153 | struct au_header *header = (struct au_header *) s->header; | ||
| 1154 | switch (header->encoding) | ||
| 1155 | { | ||
| 1156 | case AU_ENCODING_ULAW_8: | ||
| 1157 | sd->format = SND_PCM_FORMAT_MU_LAW; | ||
| 1158 | break; | ||
| 1159 | case AU_ENCODING_ALAW_8: | ||
| 1160 | sd->format = SND_PCM_FORMAT_A_LAW; | ||
| 1161 | break; | ||
| 1162 | case AU_ENCODING_IEEE32: | ||
| 1163 | sd->format = SND_PCM_FORMAT_FLOAT_BE; | ||
| 1164 | break; | ||
| 1165 | case AU_ENCODING_IEEE64: | ||
| 1166 | sd->format = SND_PCM_FORMAT_FLOAT64_BE; | ||
| 1167 | break; | ||
| 1168 | case AU_ENCODING_8: | ||
| 1169 | sd->format = SND_PCM_FORMAT_S8; | ||
| 1170 | break; | ||
| 1171 | case AU_ENCODING_16: | ||
| 1172 | sd->format = SND_PCM_FORMAT_S16_BE; | ||
| 1173 | break; | ||
| 1174 | case AU_ENCODING_24: | ||
| 1175 | sd->format = SND_PCM_FORMAT_S24_BE; | ||
| 1176 | break; | ||
| 1177 | case AU_ENCODING_32: | ||
| 1178 | sd->format = SND_PCM_FORMAT_S32_BE; | ||
| 1179 | break; | ||
| 1180 | |||
| 1181 | default: | ||
| 1182 | error ("Unsupported AU file format"); | ||
| 1183 | } | ||
| 1184 | } | ||
| 1185 | else | ||
| 1186 | abort (); | ||
| 1187 | } | ||
| 1188 | |||
| 1189 | |||
| 1190 | /* Write NBYTES bytes from BUFFER to device SD. */ | ||
| 1191 | |||
| 1192 | static void | ||
| 1193 | alsa_write (sd, buffer, nbytes) | ||
| 1194 | struct sound_device *sd; | ||
| 1195 | const char *buffer; | ||
| 1196 | int nbytes; | ||
| 1197 | { | ||
| 1198 | struct alsa_params *p = (struct alsa_params *) sd->data; | ||
| 1199 | |||
| 1200 | /* The the third parameter to snd_pcm_writei is frames, not bytes. */ | ||
| 1201 | int fact = snd_pcm_format_size (sd->format, 1) * sd->channels; | ||
| 1202 | int nwritten = 0; | ||
| 1203 | int err; | ||
| 1204 | |||
| 1205 | while (nwritten < nbytes) | ||
| 1206 | { | ||
| 1207 | err = snd_pcm_writei (p->handle, | ||
| 1208 | buffer + nwritten, | ||
| 1209 | (nbytes - nwritten)/fact); | ||
| 1210 | if (err < 0) | ||
| 1211 | { | ||
| 1212 | if (err == -EPIPE) | ||
| 1213 | { /* under-run */ | ||
| 1214 | err = snd_pcm_prepare (p->handle); | ||
| 1215 | if (err < 0) | ||
| 1216 | alsa_sound_perror ("Can't recover from underrun, prepare failed", | ||
| 1217 | err); | ||
| 1218 | } | ||
| 1219 | else if (err == -ESTRPIPE) | ||
| 1220 | { | ||
| 1221 | while ((err = snd_pcm_resume (p->handle)) == -EAGAIN) | ||
| 1222 | sleep(1); /* wait until the suspend flag is released */ | ||
| 1223 | if (err < 0) | ||
| 1224 | { | ||
| 1225 | err = snd_pcm_prepare (p->handle); | ||
| 1226 | if (err < 0) | ||
| 1227 | alsa_sound_perror ("Can't recover from suspend, " | ||
| 1228 | "prepare failed", | ||
| 1229 | err); | ||
| 1230 | } | ||
| 1231 | } | ||
| 1232 | else | ||
| 1233 | alsa_sound_perror ("Error writing to sound device", err); | ||
| 1234 | |||
| 1235 | } | ||
| 1236 | else | ||
| 1237 | nwritten += err * fact; | ||
| 1238 | } | ||
| 1239 | } | ||
| 1240 | |||
| 1241 | static void | ||
| 1242 | snd_error_quiet (file, line, function, err, fmt) | ||
| 1243 | const char *file; | ||
| 1244 | int line; | ||
| 1245 | const char *function; | ||
| 1246 | int err; | ||
| 1247 | const char *fmt; | ||
| 1248 | { | ||
| 1249 | } | ||
| 1250 | |||
| 1251 | /* Initialize device SD. Set up the interface functions in the device | ||
| 1252 | structure. */ | ||
| 1253 | |||
| 1254 | static int | ||
| 1255 | alsa_init (sd) | ||
| 1256 | struct sound_device *sd; | ||
| 1257 | { | ||
| 1258 | char *file; | ||
| 1259 | snd_pcm_t *handle; | ||
| 1260 | int err; | ||
| 1261 | |||
| 1262 | /* Open the sound device. Default is "default". */ | ||
| 1263 | if (sd->file) | ||
| 1264 | file = sd->file; | ||
| 1265 | else | ||
| 1266 | file = DEFAULT_ALSA_SOUND_DEVICE; | ||
| 1267 | |||
| 1268 | snd_lib_error_set_handler ((snd_lib_error_handler_t) snd_error_quiet); | ||
| 1269 | err = snd_pcm_open (&handle, file, SND_PCM_STREAM_PLAYBACK, 0); | ||
| 1270 | snd_lib_error_set_handler (NULL); | ||
| 1271 | if (err < 0) | ||
| 1272 | return 0; | ||
| 1273 | |||
| 1274 | sd->fd = -1; | ||
| 1275 | sd->open = alsa_open; | ||
| 1276 | sd->close = alsa_close; | ||
| 1277 | sd->configure = alsa_configure; | ||
| 1278 | sd->choose_format = alsa_choose_format; | ||
| 1279 | sd->write = alsa_write; | ||
| 1280 | sd->period_size = alsa_period_size; | ||
| 1281 | |||
| 1282 | return 1; | ||
| 1283 | } | ||
| 1284 | |||
| 1285 | #endif /* HAVE_ALSA */ | ||
| 1286 | |||
| 1287 | |||
| 896 | /* END: Non Windows functions */ | 1288 | /* END: Non Windows functions */ |
| 897 | #else /* WINDOWSNT */ | 1289 | #else /* WINDOWSNT */ |
| 898 | 1290 | ||
| @@ -1056,10 +1448,11 @@ Internal use only, use `play-sound' instead.\n */) | |||
| 1056 | args[1] = sound; | 1448 | args[1] = sound; |
| 1057 | Frun_hook_with_args (2, args); | 1449 | Frun_hook_with_args (2, args); |
| 1058 | 1450 | ||
| 1059 | /* There is only one type of device we currently support, the VOX | 1451 | #ifdef HAVE_ALSA |
| 1060 | sound driver. Set up the device interface functions for that | 1452 | if (!alsa_init (current_sound_device)) |
| 1061 | device. */ | 1453 | #endif |
| 1062 | vox_init (current_sound_device); | 1454 | if (!vox_init (current_sound_device)) |
| 1455 | error ("No usable sound device driver found"); | ||
| 1063 | 1456 | ||
| 1064 | /* Open the device. */ | 1457 | /* Open the device. */ |
| 1065 | current_sound_device->open (current_sound_device); | 1458 | current_sound_device->open (current_sound_device); |