~ubuntu-branches/ubuntu/karmic/mpg123/karmic

« back to all changes in this revision

Viewing changes to audio_os2.c

  • Committer: Bazaar Package Importer
  • Author(s): Daniel Kobras
  • Date: 2004-10-26 23:48:41 UTC
  • Revision ID: james.westby@ubuntu.com-20041026234841-vyigddlv7kb52nxh
Tags: upstream-0.59r
ImportĀ upstreamĀ versionĀ 0.59r

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