update.
[chise/xemacs-chise.git.1] / src / esd.c
1 /* esd.c - play a sound over ESD
2
3 This file is part of XEmacs.
4
5 XEmacs is free software; you can redistribute it and/or modify it
6 under the terms of the GNU General Public License as published by the
7 Free Software Foundation; either version 2, or (at your option) any
8 later version.
9
10 XEmacs is distributed in the hope that it will be useful, but WITHOUT
11 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
13 for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with XEmacs; see the file COPYING.  If not, write to
17 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.  */
19
20 /* Synched up with: Not in FSF. */
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include "lisp.h"
27 #include "miscplay.h"
28
29 #include <esd.h>
30
31 #include <unistd.h>
32 #include <fcntl.h>
33 #include <stdio.h>
34 #include <errno.h>
35 #include <string.h>
36
37 /* the name given to ESD - I think this should identify ourselves */
38 #define ESD_NAME "xemacs"
39
40 int esd_play_sound_file(char *file, int vol);
41 int esd_play_sound_file(char *file, int vol)
42 {                              /* #### FIXME: vol is ignored */
43   return esd_play_file(ESD_NAME, file, 0);
44 }
45
46 int esd_play_sound_data(unsigned char *data, size_t length, int vol);
47 int esd_play_sound_data(unsigned char *data, size_t length, int vol)
48 {                              /* #### FIXME: vol is ignored */
49   size_t         (*parsesndfile)(void **dayta,size_t *sz,void **outbuf);
50   size_t         (*sndcnv)(void **dayta,size_t *sz,void **);
51   fmtType        ffmt;
52   int            fmt,speed,tracks;
53   unsigned char *pptr,*optr,*cptr,*sptr;
54   ssize_t        wrtn;
55   size_t         crtn;
56   size_t         prtn;
57   int flags, sock;
58
59   /* analyze_format needs at least this many bytes to work with */
60   if (length < HEADERSZ)
61     return 0;
62
63   ffmt = analyze_format(data,&fmt,&speed,&tracks,&parsesndfile);
64
65   if (ffmt != fmtRaw && ffmt != fmtSunAudio && ffmt != fmtWave) {
66     message(GETTEXT("audio: Unsupported file format (neither RAW, nor Sun/DECAudio, nor WAVE)"));
67       return 0;
68   }
69
70   /* convert header information into ESD flags */
71   flags = ESD_STREAM|ESD_PLAY;
72   sndcnv = sndcnvnop;
73   switch (fmt)
74     {
75     case AFMT_MU_LAW:
76       sndcnv = sndcnvULaw_2linear;
77       flags |= ESD_BITS8;
78       break;
79     case AFMT_S8:
80       sndcnv = sndcnv2unsigned;        /* ESD needs unsigned bytes */
81     case AFMT_U8:
82       flags |= ESD_BITS8;
83       break;
84     case AFMT_S16_BE:
85       sndcnv = sndcnv16swap;   /* ESD wants little endian */
86     case AFMT_S16_LE:
87       flags |= ESD_BITS16;
88       break;
89     default:
90       message(GETTEXT("audio: byte format %d unimplemented"), fmt);
91       return 0;
92     }
93   switch (tracks)
94     {
95     case 1: flags |= ESD_MONO; break;
96     case 2: flags |= ESD_STEREO; break;
97     default:
98       message(GETTEXT("audio: %d channels - only 1 or 2 supported"), tracks);
99       return 0;
100     }
101
102   sock = esd_play_stream(flags, speed, NULL, "xemacs");
103   if (sock < 0)
104     return 0;
105
106   reset_parsestate();
107
108   for (pptr = data; (prtn = parsesndfile((void **)&pptr,&length,
109                                         (void **)&optr)) > 0; )
110     for (cptr = optr; (crtn = sndcnv((void **)&cptr,&prtn,
111                                     (void **)&sptr)) > 0; ) {
112       if ((wrtn = write(sock,sptr,crtn)) < 0) {
113        message(GETTEXT("audio: write error (%s)"), strerror(errno));
114        goto END_OF_PLAY;
115       }
116       if (wrtn != crtn) {
117        message(GETTEXT("audio: only wrote %d of %d bytes"), wrtn, crtn);
118        goto END_OF_PLAY;
119       }
120     }
121
122   if (ffmt == fmtWave)
123     parse_wave_complete();
124
125 END_OF_PLAY:
126   /* Now cleanup all used resources */
127
128   close(sock);
129   return 1;
130 }