~ubuntu-branches/ubuntu/hoary/kdemultimedia/hoary

« back to all changes in this revision

Viewing changes to kmidi/sun_a.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Martin Schulze
  • Date: 2003-01-22 15:00:51 UTC
  • Revision ID: james.westby@ubuntu.com-20030122150051-uihwkdoxf15mi1tn
Tags: upstream-2.2.2
ImportĀ upstreamĀ versionĀ 2.2.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* 
 
2
 
 
3
    TiMidity -- Experimental MIDI to WAVE converter
 
4
    Copyright (C) 1995 Tuukka Toivonen <toivonen@clinet.fi>
 
5
 
 
6
    This program is free software; you can redistribute it and/or modify
 
7
    it under the terms of the GNU General Public License as published by
 
8
    the Free Software Foundation; either version 2 of the License, or
 
9
    (at your option) any later version.
 
10
 
 
11
    This program is distributed in the hope that it will be useful,
 
12
    but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
14
    GNU General Public License for more details.
 
15
 
 
16
    You should have received a copy of the GNU General Public License
 
17
    along with this program; if not, write to the Free Software
 
18
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
19
 
 
20
    sun_audio.c
 
21
 
 
22
    Functions to play sound on a Sun's /dev/audio. 
 
23
 
 
24
    THESE ARE UNTESTED -- If you need to make modifications to get
 
25
    them to work, please send me the diffs, preferrably with a brief 
 
26
    explanation of what was wrong. Thanks!
 
27
 
 
28
*/
 
29
 
 
30
#ifdef AU_SUN
 
31
/* #if defined(sun) */
 
32
 
 
33
#include <unistd.h>
 
34
#include <fcntl.h>
 
35
#include <errno.h>
 
36
 
 
37
#include <sys/ioctl.h> 
 
38
/* #include "../config.h" */
 
39
#include "config.h"
 
40
 
 
41
#ifdef HAVE_SYS_AUDIOIO_H
 
42
 #include <sys/audioio.h>
 
43
#else
 
44
 #include <sun/audioio.h>
 
45
#endif
 
46
#ifdef ADAGIO
 
47
#include <malloc.h>
 
48
#endif
 
49
 
 
50
#include "output.h"
 
51
#include "controls.h"
 
52
 
 
53
static int open_output(void); /* 0=success, 1=warning, -1=fatal error */
 
54
static void close_output(void);
 
55
static void output_data(int32 *buf, uint32 count);
 
56
static int driver_output_data(unsigned char *buf, uint32 count);
 
57
static void flush_output(void);
 
58
static void purge_output(void);
 
59
static int output_count(uint32 ct);
 
60
 
 
61
/* export the playback mode */
 
62
 
 
63
#define dpm sun_play_mode
 
64
 
 
65
PlayMode dpm = {
 
66
  DEFAULT_RATE, PE_16BIT|PE_SIGNED,
 
67
  -1,
 
68
  {0,0,0,0,0}, /* no extra parameters so far */
 
69
  "Sun audio device", 'd',
 
70
  "/dev/audio",
 
71
  open_output,
 
72
  close_output,
 
73
  output_data,
 
74
  driver_output_data,
 
75
  flush_output,
 
76
  purge_output,
 
77
  output_count
 
78
};
 
79
 
 
80
/*************************************************************************/
 
81
/*
 
82
   Encoding will be 16-bit linear signed, unless PE_ULAW is set, in
 
83
   which case it'll be 8-bit uLaw. I don't think it's worthwhile to
 
84
   implement any 8-bit linear modes as the sound quality is
 
85
   unrewarding. PE_MONO is honored.  */
 
86
 
 
87
static audio_info_t auinfo;
 
88
 
 
89
static int open_output(void)
 
90
{
 
91
  int fd, warnings=0;
 
92
  /* extern int ioctl(); */
 
93
 
 
94
  /* Open the audio device */
 
95
 
 
96
#ifdef SYSV
 
97
  fd=open(dpm.name, O_WRONLY );
 
98
#else
 
99
  fd=open(dpm.name, O_WRONLY | O_NDELAY);
 
100
#endif
 
101
 
 
102
  if (fd<0)
 
103
    {
 
104
      ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "%s: %s",
 
105
           dpm.name, sys_errlist[errno]);
 
106
      return -1;
 
107
    }
 
108
 
 
109
  fcntl(fd, F_SETFL, O_NDELAY);
 
110
 
 
111
 
 
112
  /* Does any device need byte-swapped data? Turn the bit off here. */
 
113
  dpm.encoding &= ~PE_BYTESWAP;
 
114
 
 
115
 
 
116
  AUDIO_INITINFO(&auinfo);
 
117
 
 
118
  if (ioctl(fd, AUDIO_GETINFO, &auinfo)<0)
 
119
    { 
 
120
      /* If it doesn't give info, it probably won't take requests
 
121
         either. Assume it's an old device that does 8kHz uLaw only.
 
122
 
 
123
         Disclaimer: I don't know squat about the various Sun audio
 
124
         devices, so if this is not what we should do, I'll gladly
 
125
         accept modifications. */
 
126
 
 
127
      ctl->cmsg(CMSG_WARNING, VERB_NORMAL, "Cannot inquire %s", dpm.name);
 
128
 
 
129
      dpm.encoding = PE_ULAW|PE_MONO;
 
130
      dpm.rate = 8000;
 
131
      warnings=1;
 
132
    }
 
133
  else
 
134
    {
 
135
      ctl->cmsg(CMSG_INFO,VERB_DEBUG, 
 
136
                "1. precision=%d  channels=%d  encoding=%d  sample_rate=%d",
 
137
                auinfo.play.precision, auinfo.play.channels,
 
138
                auinfo.play.encoding, auinfo.play.sample_rate);
 
139
      ctl->cmsg(CMSG_INFO,VERB_DEBUG, 
 
140
                "1. (dpm.encoding=0x%02x  dpm.rate=%d)",
 
141
                dpm.encoding, dpm.rate);
 
142
 
 
143
 
 
144
      /* Select 16-bit linear / 8-bit uLaw encoding */
 
145
 
 
146
      if (dpm.encoding & PE_ULAW)
 
147
        {
 
148
          auinfo.play.precision = 8;
 
149
          auinfo.play.encoding = AUDIO_ENCODING_ULAW;
 
150
        }
 
151
      else
 
152
        {
 
153
          auinfo.play.precision = 16;
 
154
          auinfo.play.encoding = AUDIO_ENCODING_LINEAR;
 
155
        }
 
156
      if (ioctl(fd, AUDIO_SETINFO, &auinfo)<0)
 
157
        {
 
158
          /* Try the other one instead */
 
159
          if (dpm.encoding & PE_ULAW)
 
160
            {
 
161
              auinfo.play.precision = 16;
 
162
              auinfo.play.encoding = AUDIO_ENCODING_LINEAR;
 
163
            }
 
164
          else
 
165
            {
 
166
              auinfo.play.precision = 8;
 
167
              auinfo.play.encoding = AUDIO_ENCODING_ULAW;
 
168
            }
 
169
          if (ioctl(fd, AUDIO_SETINFO, &auinfo)<0)
 
170
            {
 
171
              ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
 
172
                   "%s doesn't support 16-bit linear or 8-bit uLaw samples", 
 
173
                   dpm.name);
 
174
              close(fd);
 
175
              return -1;
 
176
            }
 
177
          dpm.encoding ^= PE_ULAW;
 
178
          ctl->cmsg(CMSG_WARNING, VERB_VERBOSE, "Encoding adjusted to %s",
 
179
                    (dpm.encoding & PE_ULAW) ? "uLaw" : "16-bit linear");
 
180
          warnings=1;
 
181
        }
 
182
      /* Set the other bits right. */
 
183
      if (dpm.encoding & PE_ULAW)
 
184
        dpm.encoding &= ~(PE_16BIT|PE_SIGNED);
 
185
      else
 
186
        dpm.encoding |= PE_16BIT|PE_SIGNED;
 
187
 
 
188
 
 
189
      /* Select stereo or mono samples */
 
190
 
 
191
      auinfo.play.channels = (dpm.encoding & PE_MONO) ? 1 : 2;
 
192
      if (ioctl(fd, AUDIO_SETINFO,&auinfo)<0)
 
193
        {
 
194
          auinfo.play.channels = (dpm.encoding & PE_MONO) ? 2 : 1;
 
195
          if ((dpm.encoding & PE_MONO) ||
 
196
              (ioctl(fd, AUDIO_SETINFO,&auinfo)<0))
 
197
            {
 
198
              ctl->cmsg(CMSG_ERROR, VERB_NORMAL, 
 
199
                   "%s doesn't support mono or stereo samples", dpm.name);
 
200
              close(fd);
 
201
              return -1;
 
202
            }
 
203
          dpm.encoding ^= PE_MONO;
 
204
          ctl->cmsg(CMSG_WARNING, VERB_VERBOSE, "Sound adjusted to %sphonic", 
 
205
                    (dpm.encoding & PE_MONO) ? "mono" : "stereo");
 
206
          warnings=1;
 
207
        }
 
208
 
 
209
 
 
210
      /* Select sampling rate */
 
211
 
 
212
      auinfo.play.sample_rate=dpm.rate;
 
213
      if (ioctl(fd, AUDIO_SETINFO,&auinfo)<0)
 
214
        {
 
215
          ctl->cmsg(CMSG_WARNING, VERB_VERBOSE,
 
216
                    "%s doesn't support a %d Hz sample rate",
 
217
                    dpm.name, dpm.rate);
 
218
          if (ioctl(fd, AUDIO_GETINFO, &auinfo)<0)
 
219
          {
 
220
            ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
 
221
                    "Can't output: %s doesn't support a %d Hz sample rate",
 
222
                    dpm.name, dpm.rate);
 
223
            close(fd);
 
224
            return -1;
 
225
          }
 
226
        }
 
227
      /* This may be pointless -- do the Sun devices give an error if
 
228
         the sampling rate can't be produced exactly? */
 
229
      if (auinfo.play.sample_rate != dpm.rate)
 
230
        {
 
231
          dpm.rate=auinfo.play.sample_rate;
 
232
          ctl->cmsg(CMSG_WARNING, VERB_VERBOSE,
 
233
                    "Output rate adjusted to %d Hz", dpm.rate);
 
234
          warnings=1;
 
235
        }
 
236
 
 
237
 
 
238
      ctl->cmsg(CMSG_INFO,VERB_DEBUG, 
 
239
                "2. precision=%d  channels=%d  encoding=%d  sample_rate=%d",
 
240
                auinfo.play.precision, auinfo.play.channels,
 
241
                auinfo.play.encoding, auinfo.play.sample_rate);
 
242
      ctl->cmsg(CMSG_INFO,VERB_DEBUG, 
 
243
                "2. (dpm.encoding=0x%02x  dpm.rate=%d)",
 
244
                dpm.encoding, dpm.rate);
 
245
    }
 
246
 
 
247
  dpm.fd=fd;
 
248
  
 
249
  return warnings;
 
250
}
 
251
 
 
252
static int output_count(uint32 ct)
 
253
{
 
254
  /* extern int ioctl(); */
 
255
  if (ioctl(dpm.fd, AUDIO_GETINFO, &auinfo)<0) return (int)ct;
 
256
  return auinfo.play.samples;
 
257
}
 
258
 
 
259
static int driver_output_data(unsigned char *buf, uint32 count)
 
260
{
 
261
  return write(dpm.fd,buf,count);
 
262
}
 
263
 
 
264
static void output_data(int32 *buf, uint32 count)
 
265
{
 
266
  int ocount;
 
267
 
 
268
  if (!(dpm.encoding & PE_MONO)) count*=2; /* Stereo samples */
 
269
  ocount = (int)count;
 
270
 
 
271
  if (ocount) {
 
272
    if (dpm.encoding & PE_ULAW)
 
273
      {
 
274
        /* Convert to 8-bit uLaw and write out. */
 
275
        s32toulaw(buf, count);
 
276
      }
 
277
    else
 
278
      {
 
279
        /* Convert data to signed 16-bit PCM */
 
280
        s32tos16(buf, count);
 
281
        ocount *= 2;
 
282
      }
 
283
  }
 
284
 
 
285
  b_out(dpm.id_character, dpm.fd, (int *)buf, ocount);
 
286
}
 
287
 
 
288
#if 0
 
289
static void output_data(int32 *buf, int32 count)
 
290
{
 
291
  if (!(dpm.encoding & PE_MONO)) count*=2; /* Stereo samples */
 
292
  
 
293
  if (dpm.encoding & PE_ULAW)
 
294
    {
 
295
      /* Convert to 8-bit uLaw and write out. */
 
296
      s32toulaw(buf, count);
 
297
      
 
298
      while ((-1==write(dpm.fd, buf, count)) && errno==EINTR)
 
299
        ;
 
300
    }
 
301
  else
 
302
    {
 
303
      /* Convert data to signed 16-bit PCM */
 
304
      s32tos16(buf, count);
 
305
      
 
306
      while ((-1==write(dpm.fd, buf, count * 2)) && errno==EINTR)
 
307
        ;
 
308
    }
 
309
}
 
310
#endif
 
311
 
 
312
static void close_output(void)
 
313
{
 
314
  close(dpm.fd);
 
315
}
 
316
 
 
317
static void flush_output(void)
 
318
{
 
319
  output_data(0, 0);
 
320
}
 
321
 
 
322
static void purge_output(void)
 
323
{
 
324
  b_out(dpm.id_character, dpm.fd, 0, -1);
 
325
}
 
326
#endif /* SUN */