~ubuntu-branches/ubuntu/lucid/mpg123/lucid

« back to all changes in this revision

Viewing changes to audio_os2.c

Tags: upstream-0.60
ImportĀ upstreamĀ versionĀ 0.60

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* OS/2 RealTime DART Engine for mpg123 (C) 1998 Samuel Audet <guardia@cam.org> */
2
 
 
3
 
#define INCL_OS2MM
4
 
#define INCL_DOS
5
 
#define INCL_VIO
6
 
#define INCL_KBD
7
 
#include <os2.h>
8
 
#include <os2me.h>
9
 
#include <stdlib.h>
10
 
#include <ctype.h>
11
 
 
12
 
#ifndef MPG123_INCLUDED
13
 
#include "mpg123.h"
14
 
#endif
15
 
 
16
 
/* complementary audio parameters */
17
 
int numbuffers = 32;     /* total audio buffers, _bare_ minimum = 4 (cuz of prio boost check) */
18
 
int lockdevice = FALSE;
19
 
USHORT volume = 100;
20
 
char *boostprio = NULL;
21
 
char *normalprio = NULL;
22
 
unsigned char boostclass = 3, normalclass = 2;
23
 
signed char   boostdelta = 0, normaldelta = 31;
24
 
unsigned char mmerror[160] = {0};
25
 
int playingframe;
26
 
 
27
 
/* audio buffers */
28
 
static ULONG ulMCIBuffers;
29
 
 
30
 
static MCI_AMP_OPEN_PARMS  maop = {0};
31
 
static MCI_MIXSETUP_PARMS  mmp = {0};
32
 
static MCI_BUFFER_PARMS    mbp = {0};
33
 
static MCI_GENERIC_PARMS   mgp = {0};
34
 
static MCI_SET_PARMS       msp = {0};
35
 
static MCI_STATUS_PARMS    mstatp = {0};
36
 
static MCI_MIX_BUFFER      *MixBuffers = NULL;
37
 
 
38
 
typedef struct
39
 
{
40
 
   MCI_MIX_BUFFER  *NextBuffer;
41
 
   int frameNum;
42
 
} BUFFERINFO;
43
 
 
44
 
BUFFERINFO *bufferinfo = NULL;
45
 
 
46
 
 
47
 
static HEV dataplayed = 0;
48
 
static ULONG resetcount;
49
 
static BOOL paused = FALSE;
50
 
 
51
 
static MCI_MIX_BUFFER *tobefilled, *playingbuffer = NULL, playedbuffer;
52
 
static void *pBufferplayed;
53
 
 
54
 
static BOOL nomoredata,nobuffermode,justflushed;
55
 
 
56
 
static TIB *mainthread; /* thread info to set thread priority */
57
 
 
58
 
ULONG keyboardtid;
59
 
 
60
 
 
61
 
static LONG APIENTRY DARTEvent(ULONG ulStatus, MCI_MIX_BUFFER *PlayedBuffer, ULONG ulFlags)
62
 
{
63
 
   switch(ulFlags)
64
 
   {
65
 
      case MIX_STREAM_ERROR | MIX_WRITE_COMPLETE:  /* error occur in device */
66
 
 
67
 
      if ( ulStatus == ERROR_DEVICE_UNDERRUN)
68
 
         /* Write buffers to rekick off the amp mixer. */
69
 
         mmp.pmixWrite( mmp.ulMixHandle,
70
 
                        MixBuffers,
71
 
                        ulMCIBuffers );
72
 
      break;
73
 
 
74
 
   case MIX_WRITE_COMPLETE:                     /* for playback  */
75
 
 
76
 
      playingbuffer = ((BUFFERINFO *) PlayedBuffer->ulUserParm)->NextBuffer;
77
 
 
78
 
      /* the next three lines are only useful to audio_playing_samples() */
79
 
      playedbuffer = *PlayedBuffer;
80
 
      playedbuffer.pBuffer = pBufferplayed;
81
 
      memcpy(playedbuffer.pBuffer, PlayedBuffer->pBuffer, PlayedBuffer->ulBufferLength);
82
 
 
83
 
      /* just too bad, the decoder fell behind... here we just keep the
84
 
         buffer to be filled in front of the playing one so that when the
85
 
         decoder kicks back in, we'll hear it in at the right time */
86
 
      if(tobefilled == playingbuffer)
87
 
      {
88
 
         tobefilled = ((BUFFERINFO *) playingbuffer->ulUserParm)->NextBuffer;
89
 
         nomoredata = TRUE;                                               
90
 
      }
91
 
      else
92
 
      {
93
 
         playingframe = ((BUFFERINFO *) playingbuffer->ulUserParm)->frameNum;
94
 
 
95
 
         /* if we're about to be short of decoder's data
96
 
            (2nd ahead buffer not filled), let's boost its priority! */
97
 
         if(tobefilled == ( (BUFFERINFO *) ((BUFFERINFO *) playingbuffer->ulUserParm)->NextBuffer->ulUserParm)->NextBuffer)
98
 
            DosSetPriority(PRTYS_THREAD,boostclass,boostdelta,mainthread->tib_ptib2->tib2_ultid);
99
 
      }
100
 
 
101
 
      /* empty the played buffer in case it doesn't get filled back */
102
 
      memset(PlayedBuffer->pBuffer,0,PlayedBuffer->ulBufferLength);
103
 
 
104
 
      DosPostEventSem(dataplayed);
105
 
 
106
 
      mmp.pmixWrite( mmp.ulMixHandle,
107
 
                     PlayedBuffer /* will contain new data */,
108
 
                     1 );
109
 
      break;
110
 
 
111
 
   } /* end switch */
112
 
 
113
 
   return( TRUE );
114
 
 
115
 
} /* end DARTEvent */
116
 
 
117
 
 
118
 
static void MciError(ULONG ulError)
119
 
{
120
 
   unsigned char buffer[128];
121
 
   ULONG rc;
122
 
 
123
 
   rc = mciGetErrorString(ulError, buffer, sizeof(buffer));
124
 
 
125
 
   if (rc == MCIERR_SUCCESS)
126
 
      sprintf(mmerror,"MCI Error %d: %s\n",ULONG_LOWD(ulError),buffer);
127
 
   else
128
 
      sprintf(mmerror,"MCI Error %d: Cannot query error message.\n",ULONG_LOWD(rc));
129
 
 
130
 
   fprintf(stderr,"%s",mmerror);
131
 
}
132
 
 
133
 
int audio_set_volume(struct audio_info_struct *ai, USHORT setvolume)
134
 
{
135
 
   if(setvolume > 100) setvolume = 100;
136
 
   volume = setvolume; /* useful when device is closed and reopened */
137
 
   if(maop.usDeviceID)
138
 
   {
139
 
     memset(&msp,0,sizeof(msp));
140
 
     msp.ulAudio = MCI_SET_AUDIO_ALL;
141
 
     msp.ulLevel = setvolume;
142
 
 
143
 
     mciSendCommand(maop.usDeviceID, MCI_SET,
144
 
                    MCI_WAIT | MCI_SET_AUDIO | MCI_SET_VOLUME,
145
 
                    &msp, 0);
146
 
   }
147
 
   return setvolume;
148
 
}
149
 
 
150
 
int audio_pause(struct audio_info_struct *ai, int pause)
151
 
{
152
 
   if(maop.usDeviceID)
153
 
   {
154
 
      if(pause)
155
 
         mciSendCommand(maop.usDeviceID, MCI_PAUSE,
156
 
                        MCI_WAIT,
157
 
                        &mgp, 0);
158
 
      else
159
 
         mciSendCommand(maop.usDeviceID, MCI_RESUME,
160
 
                        MCI_WAIT,
161
 
                        &mgp, 0);
162
 
   }
163
 
   return pause;
164
 
}
165
 
 
166
 
int audio_open(struct audio_info_struct *ai)
167
 
{
168
 
   ULONG rc,i;
169
 
   char *temp;
170
 
   ULONG openflags;
171
 
   PPIB ppib;
172
 
   USHORT bits;
173
 
 
174
 
   if(maop.usDeviceID) return (maop.usDeviceID);
175
 
 
176
 
   if(!ai) return -1;
177
 
 
178
 
   if(!ai->device) ai->device = "0";
179
 
 
180
 
   if(ai->rate < 0) ai->rate = 44100;
181
 
   if(ai->channels < 0) ai->channels = 2;
182
 
   if(ai->format < 0) ai->format = AUDIO_FORMAT_SIGNED_16;
183
 
 
184
 
   if(ai->format == AUDIO_FORMAT_SIGNED_16)
185
 
      bits = 16;
186
 
   else if(ai->format == AUDIO_FORMAT_UNSIGNED_8)
187
 
      bits = 8;
188
 
   else return -1;
189
 
 
190
 
   /* open the mixer device */
191
 
   memset (&maop, 0, sizeof(maop));
192
 
   maop.usDeviceID = 0;
193
 
   maop.pszDeviceType = (PSZ) MAKEULONG(MCI_DEVTYPE_AUDIO_AMPMIX, atoi(ai->device));
194
 
 
195
 
   openflags = MCI_WAIT | MCI_OPEN_TYPE_ID;
196
 
   if(!lockdevice) openflags |= MCI_OPEN_SHAREABLE;
197
 
 
198
 
   rc = mciSendCommand(0,
199
 
                       MCI_OPEN,
200
 
                       openflags,
201
 
                       &maop,
202
 
                       0);
203
 
 
204
 
   if (ULONG_LOWD(rc) != MCIERR_SUCCESS)
205
 
   {
206
 
      MciError(rc);
207
 
      maop.usDeviceID = 0;
208
 
      return(-1);
209
 
   }
210
 
 
211
 
   /* volume in ai->gain ?? */
212
 
 
213
 
   /* Set the MCI_MIXSETUP_PARMS data structure to match the audio stream. */
214
 
 
215
 
   memset(&mmp, 0, sizeof(mmp));
216
 
 
217
 
   mmp.ulBitsPerSample = bits;
218
 
   mmp.ulFormatTag = MCI_WAVE_FORMAT_PCM;
219
 
   mmp.ulSamplesPerSec = ai->rate;
220
 
   mmp.ulChannels = ai->channels;
221
 
 
222
 
   /* Setup the mixer for playback of wave data */
223
 
   mmp.ulFormatMode = MCI_PLAY;
224
 
   mmp.ulDeviceType = MCI_DEVTYPE_WAVEFORM_AUDIO;
225
 
   mmp.pmixEvent    = DARTEvent;
226
 
 
227
 
   rc = mciSendCommand( maop.usDeviceID,
228
 
                        MCI_MIXSETUP,
229
 
                        MCI_WAIT | MCI_MIXSETUP_INIT,
230
 
                        &mmp,
231
 
                        0 );
232
 
 
233
 
   if ( ULONG_LOWD(rc) != MCIERR_SUCCESS )
234
 
   {
235
 
      MciError(rc);
236
 
      maop.usDeviceID = 0;
237
 
      return(-1);
238
 
   }
239
 
 
240
 
   volume = audio_set_volume(ai,volume);
241
 
 
242
 
   /* Set up the BufferParms data structure and allocate
243
 
    * device buffers from the Amp-Mixer  */
244
 
 
245
 
   memset(&mbp, 0, sizeof(mbp));
246
 
   free(MixBuffers);
247
 
   free(bufferinfo);
248
 
   if(numbuffers < 5) numbuffers = 5;
249
 
   if(numbuffers > 200) numbuffers = 200;
250
 
   MixBuffers = calloc(numbuffers, sizeof(*MixBuffers));
251
 
   bufferinfo = calloc(numbuffers, sizeof(*bufferinfo));
252
 
 
253
 
   ulMCIBuffers = numbuffers;
254
 
   mbp.ulNumBuffers = ulMCIBuffers;
255
 
/*   mbp.ulBufferSize = mmp.ulBufferSize; */
256
 
   /* I don't like this... they must be smaller than 64KB or else the
257
 
      engine needs major rewrite */
258
 
   mbp.ulBufferSize = audiobufsize;
259
 
   mbp.pBufList = MixBuffers;
260
 
 
261
 
   rc = mciSendCommand( maop.usDeviceID,
262
 
                        MCI_BUFFER,
263
 
                        MCI_WAIT | MCI_ALLOCATE_MEMORY,
264
 
                        (PVOID) &mbp,
265
 
                        0 );
266
 
 
267
 
   if ( ULONG_LOWD(rc) != MCIERR_SUCCESS )
268
 
   {
269
 
      MciError(rc);
270
 
      maop.usDeviceID = 0;
271
 
      return(-1);
272
 
   }
273
 
 
274
 
   pBufferplayed = playedbuffer.pBuffer = calloc(1,audiobufsize);
275
 
 
276
 
   ulMCIBuffers = mbp.ulNumBuffers; /* never know! */
277
 
 
278
 
   /* Fill all device buffers with zeros and set linked list */
279
 
 
280
 
   for(i = 0; i < ulMCIBuffers; i++)
281
 
   {
282
 
      MixBuffers[i].ulFlags = 0;
283
 
      MixBuffers[i].ulBufferLength = mbp.ulBufferSize;
284
 
      memset(MixBuffers[i].pBuffer, 0, MixBuffers[i].ulBufferLength);
285
 
 
286
 
      MixBuffers[i].ulUserParm = (ULONG) &bufferinfo[i];
287
 
      bufferinfo[i].NextBuffer = &MixBuffers[i+1];
288
 
   }
289
 
 
290
 
   bufferinfo[i-1].NextBuffer = &MixBuffers[0];
291
 
 
292
 
   /* Create a semaphore to know when data has been played by the DART thread */
293
 
   DosCreateEventSem(NULL,&dataplayed,0,FALSE);
294
 
 
295
 
   playingbuffer = &MixBuffers[0];
296
 
   tobefilled = &MixBuffers[1];
297
 
   playingframe = 0;
298
 
   nomoredata = TRUE;
299
 
   nobuffermode = FALSE;
300
 
   justflushed = FALSE;
301
 
 
302
 
   if(boostprio)
303
 
   {
304
 
      temp = alloca(strlen(boostprio)+1);
305
 
      strcpy(temp,boostprio);
306
 
 
307
 
      boostdelta = atoi(temp+1);
308
 
      *(temp+1) = 0;
309
 
      boostclass = atoi(temp);
310
 
   }
311
 
   if(boostclass > 4) boostdelta = 3;
312
 
   if(boostdelta > 31) boostdelta = 31;
313
 
   if(boostdelta < -31) boostdelta = -31;
314
 
 
315
 
 
316
 
   if(normalprio)
317
 
   {
318
 
      temp = alloca(strlen(normalprio)+1);
319
 
      strcpy(temp,normalprio);
320
 
 
321
 
      normaldelta = atoi(temp+1);
322
 
      *(temp+1) = 0;
323
 
      normalclass = atoi(temp);
324
 
   }
325
 
   if(normalclass > 4) normaldelta = 3;
326
 
   if(normaldelta > 31) normaldelta = 31;
327
 
   if(normaldelta < -31) normaldelta = -31;
328
 
 
329
 
 
330
 
   DosGetInfoBlocks(&mainthread,&ppib); /* ppib not needed, but makes some DOSCALLS.DLL crash */
331
 
   DosSetPriority(PRTYS_THREAD,boostclass,boostdelta,mainthread->tib_ptib2->tib2_ultid);
332
 
 
333
 
   /* Write buffers to kick off the amp mixer. see DARTEvent() */
334
 
   rc = mmp.pmixWrite( mmp.ulMixHandle,
335
 
                       MixBuffers,
336
 
                       ulMCIBuffers );
337
 
 
338
 
   return maop.usDeviceID;
339
 
}
340
 
 
341
 
int audio_play_samples(struct audio_info_struct *ai,unsigned char *buf,int len)
342
 
{
343
 
   /* if we're too quick, let's wait */
344
 
   if(nobuffermode)
345
 
   {
346
 
      MCI_MIX_BUFFER *temp = playingbuffer;
347
 
 
348
 
      while(
349
 
         (tobefilled != (temp = ((BUFFERINFO *) temp->ulUserParm)->NextBuffer)) &&
350
 
         (tobefilled != (temp = ((BUFFERINFO *) temp->ulUserParm)->NextBuffer)) &&
351
 
         (tobefilled != (temp = ((BUFFERINFO *) temp->ulUserParm)->NextBuffer)) )
352
 
         {
353
 
            DosResetEventSem(dataplayed,&resetcount);
354
 
            DosWaitEventSem(dataplayed, -1);
355
 
            temp = playingbuffer;
356
 
         }
357
 
   }
358
 
   else
359
 
      while(tobefilled == playingbuffer)
360
 
      {
361
 
         DosResetEventSem(dataplayed,&resetcount);
362
 
         DosWaitEventSem(dataplayed, -1);
363
 
      }
364
 
 
365
 
   if(justflushed)
366
 
      justflushed = FALSE;
367
 
   else
368
 
   {
369
 
      nomoredata = FALSE;
370
 
 
371
 
      memcpy(tobefilled->pBuffer, buf, len);
372
 
      tobefilled->ulBufferLength = len;
373
 
//      ((BUFFERINFO *) tobefilled->ulUserParm)->frameNum = fr->frameNum;
374
 
 
375
 
      /* if we're out of the water (3rd ahead buffer filled),
376
 
         let's reduce our priority */
377
 
      if(tobefilled == ( (BUFFERINFO *) ( (BUFFERINFO *) ((BUFFERINFO *) playingbuffer->ulUserParm)->NextBuffer->ulUserParm)->NextBuffer->ulUserParm)->NextBuffer)
378
 
         DosSetPriority(PRTYS_THREAD,normalclass,normaldelta,mainthread->tib_ptib2->tib2_ultid);
379
 
 
380
 
      tobefilled = ((BUFFERINFO *) tobefilled->ulUserParm)->NextBuffer;
381
 
   }
382
 
 
383
 
   return len;
384
 
}
385
 
 
386
 
int audio_playing_samples(struct audio_info_struct *ai,unsigned char *buf,int len)
387
 
{
388
 
   if(len > audiobufsize || !playingbuffer) return -1;
389
 
 
390
 
   if(mmp.ulBitsPerSample == 16)
391
 
      ai->format = AUDIO_FORMAT_SIGNED_16;
392
 
   else if(mmp.ulBitsPerSample == 8)
393
 
      ai->format = AUDIO_FORMAT_UNSIGNED_8;
394
 
   else return -1;
395
 
 
396
 
   ai->rate = mmp.ulSamplesPerSec;
397
 
   ai->channels = mmp.ulChannels;
398
 
 
399
 
   if(buf && len)
400
 
   {
401
 
      ULONG rc;
402
 
      int upto;
403
 
 
404
 
      mstatp.ulItem = MCI_STATUS_POSITION;
405
 
 
406
 
      rc = mciSendCommand( maop.usDeviceID,
407
 
                           MCI_STATUS,
408
 
                           MCI_STATUS_ITEM | MCI_WAIT,
409
 
                           &mstatp,
410
 
                           0 );
411
 
 
412
 
      if ( ULONG_LOWD(rc) != MCIERR_SUCCESS )
413
 
      {
414
 
         MciError(rc);
415
 
         maop.usDeviceID = 0;
416
 
         return(-1);
417
 
      }
418
 
 
419
 
      /* this is hypocrite...
420
 
         DART returns the value in ulReturn instead of ulValue,
421
 
         also it returns in milliseconds and not MMTIME... arg */
422
 
 
423
 
      upto = (mstatp.ulReturn-playedbuffer.ulTime) * mmp.ulSamplesPerSec / 1000;
424
 
      upto *= mmp.ulChannels * (mmp.ulBitsPerSample>>3);
425
 
 
426
 
      /* if a timing problem occurs, let's at least not crash */
427
 
      if(upto > playingbuffer->ulBufferLength) upto = playingbuffer->ulBufferLength;
428
 
 
429
 
      if(len < upto)
430
 
         memcpy(buf,(char *) (playingbuffer->pBuffer)+upto-len, len);
431
 
      else
432
 
      {
433
 
         memcpy(buf,(char *) playedbuffer.pBuffer+playedbuffer.ulBufferLength-(len-upto),len-upto);
434
 
         memcpy(buf+(len-upto),playingbuffer->pBuffer,upto);
435
 
      }
436
 
   }
437
 
 
438
 
   return 0;
439
 
}
440
 
 
441
 
int audio_nobuffermode(struct audio_info_struct *ai, int setnobuffermode)
442
 
{
443
 
   nobuffermode = setnobuffermode;
444
 
   return TRUE;
445
 
}
446
 
 
447
 
int audio_trash_buffers(struct audio_info_struct *ai)
448
 
{
449
 
   int i;
450
 
 
451
 
   justflushed = TRUE;
452
 
 
453
 
   /* Fill all device buffers with zeros */
454
 
   for(i = 0; i < ulMCIBuffers; i++)
455
 
      memset(MixBuffers[i].pBuffer, 0, MixBuffers[i].ulBufferLength);
456
 
 
457
 
   tobefilled = ((BUFFERINFO *) playingbuffer->ulUserParm)->NextBuffer;
458
 
   nomoredata = TRUE;
459
 
 
460
 
   return TRUE;
461
 
}
462
 
 
463
 
int audio_close(struct audio_info_struct *ai)
464
 
{
465
 
   ULONG rc;
466
 
 
467
 
   if(!maop.usDeviceID)
468
 
      return 0;
469
 
 
470
 
   while(!nomoredata)
471
 
   {
472
 
      DosResetEventSem(dataplayed,&resetcount);
473
 
      DosWaitEventSem(dataplayed, -1);
474
 
   }
475
 
 
476
 
   playingbuffer = NULL;
477
 
 
478
 
   DosCloseEventSem(dataplayed);
479
 
   dataplayed = 0;
480
 
 
481
 
   free(pBufferplayed);
482
 
 
483
 
   rc = mciSendCommand( maop.usDeviceID,
484
 
                        MCI_BUFFER,
485
 
                        MCI_WAIT | MCI_DEALLOCATE_MEMORY,
486
 
                        &mbp,
487
 
                        0 );
488
 
 
489
 
   if ( ULONG_LOWD(rc) != MCIERR_SUCCESS )
490
 
   {
491
 
      MciError(rc);
492
 
      return(-1);
493
 
   }
494
 
 
495
 
   free(bufferinfo);
496
 
   free(MixBuffers);
497
 
   bufferinfo = NULL;
498
 
   MixBuffers = NULL;
499
 
 
500
 
   memset(&mbp, 0, sizeof(mbp));
501
 
 
502
 
   rc = mciSendCommand( maop.usDeviceID,
503
 
                        MCI_CLOSE,
504
 
                        MCI_WAIT ,
505
 
                        &mgp,
506
 
                        0 );
507
 
 
508
 
   if ( ULONG_LOWD(rc) != MCIERR_SUCCESS )
509
 
   {
510
 
      MciError(rc);
511
 
      return(-1);
512
 
   }
513
 
 
514
 
   memset(&maop, 0, sizeof(maop));
515
 
 
516
 
   return 0;
517
 
}
518
 
 
519
 
/*
520
 
 * get formats for specific channel/rate parameters
521
 
 */
522
 
int audio_get_formats(struct audio_info_struct *ai)
523
 
{
524
 
   int fmts = 0;
525
 
   ULONG rc;
526
 
   MCI_MIXSETUP_PARMS mmptemp = {0};
527
 
 
528
 
   mmp.ulDeviceType = MCI_DEVTYPE_WAVEFORM_AUDIO;
529
 
   mmp.pmixEvent    = DARTEvent;
530
 
 
531
 
   mmptemp.ulFormatMode = MCI_PLAY;
532
 
   mmptemp.ulSamplesPerSec = ai->rate;
533
 
   mmptemp.ulChannels = ai->channels;
534
 
 
535
 
   mmptemp.ulFormatTag = MCI_WAVE_FORMAT_PCM;
536
 
   mmptemp.ulBitsPerSample = 16;
537
 
   rc = mciSendCommand( maop.usDeviceID,
538
 
                        MCI_MIXSETUP,
539
 
                        MCI_WAIT | MCI_MIXSETUP_QUERYMODE,
540
 
                        &mmptemp,
541
 
                        0 );
542
 
   if((ULONG_LOWD(rc) == MCIERR_SUCCESS) && (rc != 0x4000)) /* undocumented */
543
 
      fmts = fmts | AUDIO_FORMAT_SIGNED_16;
544
 
 
545
 
   mmptemp.ulFormatTag = MCI_WAVE_FORMAT_PCM;
546
 
   mmptemp.ulBitsPerSample = 8;
547
 
   rc = mciSendCommand( maop.usDeviceID,
548
 
                        MCI_MIXSETUP,
549
 
                        MCI_WAIT | MCI_MIXSETUP_QUERYMODE,
550
 
                        &mmptemp,
551
 
                        0 );
552
 
   if((ULONG_LOWD(rc) == MCIERR_SUCCESS) && (rc != 0x4000)) /* undocumented */
553
 
      fmts = fmts | AUDIO_FORMAT_UNSIGNED_8;
554
 
 
555
 
   mmptemp.ulFormatTag = MCI_WAVE_FORMAT_ALAW;
556
 
   mmptemp.ulBitsPerSample = 8;
557
 
   rc = mciSendCommand( maop.usDeviceID,
558
 
                        MCI_MIXSETUP,
559
 
                        MCI_WAIT | MCI_MIXSETUP_QUERYMODE,
560
 
                        &mmptemp,
561
 
                        0 );
562
 
   if((ULONG_LOWD(rc) == MCIERR_SUCCESS) && (rc != 0x4000)) /* undocumented */
563
 
      fmts = fmts | AUDIO_FORMAT_ALAW_8;
564
 
 
565
 
   mmptemp.ulFormatTag = MCI_WAVE_FORMAT_MULAW;
566
 
   mmptemp.ulBitsPerSample = 8;
567
 
   rc = mciSendCommand( maop.usDeviceID,
568
 
                        MCI_MIXSETUP,
569
 
                        MCI_WAIT | MCI_MIXSETUP_QUERYMODE,
570
 
                        &mmptemp,
571
 
                        0 );
572
 
   if((ULONG_LOWD(rc) == MCIERR_SUCCESS) && (rc != 0x4000)) /* undocumented */
573
 
      fmts = fmts | AUDIO_FORMAT_ULAW_8;
574
 
 
575
 
   return fmts;
576
 
}
577
 
 
578
 
int audio_rate_best_match(struct audio_info_struct *ai)
579
 
{
580
 
   return 0;
581
 
}
582
 
 
583
 
int audio_get_devices(char *info, int deviceid)
584
 
{
585
 
   char buffer[128];
586
 
   MCI_SYSINFO_PARMS mip;
587
 
 
588
 
   if(deviceid && info)
589
 
   {
590
 
      MCI_SYSINFO_LOGDEVICE mid;
591
 
 
592
 
      mip.pszReturn = buffer;
593
 
      mip.ulRetSize = sizeof(buffer);
594
 
      mip.usDeviceType = MCI_DEVTYPE_AUDIO_AMPMIX;
595
 
      mip.ulNumber = deviceid;
596
 
 
597
 
      mciSendCommand(0,
598
 
                     MCI_SYSINFO,
599
 
                     MCI_WAIT | MCI_SYSINFO_INSTALLNAME,
600
 
                     &mip,
601
 
                     0);
602
 
 
603
 
      mip.ulItem = MCI_SYSINFO_QUERY_DRIVER;
604
 
      mip.pSysInfoParm = &mid;
605
 
      strcpy(mid.szInstallName,buffer);
606
 
 
607
 
      mciSendCommand(0,
608
 
                     MCI_SYSINFO,
609
 
                     MCI_WAIT | MCI_SYSINFO_ITEM,
610
 
                     &mip,
611
 
                     0);
612
 
 
613
 
      strcpy(info,mid.szProductInfo);
614
 
      return deviceid;
615
 
   }
616
 
   else
617
 
   {
618
 
      int number;
619
 
 
620
 
      mip.pszReturn = buffer;
621
 
      mip.ulRetSize = sizeof(buffer);
622
 
      mip.usDeviceType = MCI_DEVTYPE_AUDIO_AMPMIX;
623
 
 
624
 
      mciSendCommand(0,
625
 
                     MCI_SYSINFO,
626
 
                     MCI_WAIT | MCI_SYSINFO_QUANTITY,
627
 
                     &mip,
628
 
                     0);
629
 
 
630
 
      number = atoi(mip.pszReturn);
631
 
      return number;
632
 
   }
633
 
}
634