aboutsummaryrefslogtreecommitdiffstats
path: root/src/sound.c
diff options
context:
space:
mode:
authorMiles Bader2006-06-07 18:05:10 +0000
committerMiles Bader2006-06-07 18:05:10 +0000
commitb883cdb2fefa8ea9c3b0d82eba7a9ee792f871bb (patch)
treede3804210a8cd955e0d3b9abc15679480930bc82 /src/sound.c
parent885b7d0991bd4b4b8f4bd1d3cd21c18a697bbce2 (diff)
parent26c9afc3239e18b03537faaea33e3e82e28099e6 (diff)
downloademacs-b883cdb2fefa8ea9c3b0d82eba7a9ee792f871bb.tar.gz
emacs-b883cdb2fefa8ea9c3b0d82eba7a9ee792f871bb.zip
Merge from emacs--devo--0
Patches applied: * emacs--devo--0 (patch 285-296) - Update from CVS - Merge from gnus--rel--5.10 - Update from CVS: admin/FOR-RELEASE: Update refcard section. * gnus--rel--5.10 (patch 102-104) - Update from CVS Revision: emacs@sv.gnu.org/emacs--unicode--0--patch-64
Diffstat (limited to 'src/sound.c')
-rw-r--r--src/sound.c413
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
112static void sound_perror P_ ((char *)); 116static void alsa_sound_perror P_ ((char *, int)) NO_RETURN;
117static void sound_perror P_ ((char *)) NO_RETURN;
113static void sound_warning P_ ((char *)); 118static void sound_warning P_ ((char *));
114static int parse_sound P_ ((Lisp_Object, Lisp_Object *)); 119static 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 *));
280static void vox_configure P_ ((struct sound_device *)); 292static void vox_configure P_ ((struct sound_device *));
281static void vox_close P_ ((struct sound_device *sd)); 293static void vox_close P_ ((struct sound_device *sd));
282static void vox_choose_format P_ ((struct sound_device *, struct sound *)); 294static void vox_choose_format P_ ((struct sound_device *, struct sound *));
283static void vox_init P_ ((struct sound_device *)); 295static int vox_init P_ ((struct sound_device *));
284static void vox_write P_ ((struct sound_device *, const char *, int)); 296static void vox_write P_ ((struct sound_device *, const char *, int));
285static void find_sound_type P_ ((struct sound *)); 297static void find_sound_type P_ ((struct sound *));
286static u_int32_t le2hl P_ ((u_int32_t)); 298static 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
871static void 884static int
872vox_init (sd) 885vox_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
933static void
934alsa_sound_perror (msg, err)
935 char *msg;
936 int err;
937{
938 error ("%s: %s", msg, snd_strerror (err));
939}
940
941struct 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
952static void
953alsa_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
980static int
981alsa_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
988static void
989alsa_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
1113static void
1114alsa_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
1135static void
1136alsa_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
1192static void
1193alsa_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
1241static void
1242snd_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
1254static int
1255alsa_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);