1/**
2 * Original code: automated SDL audio test written by Edgar Simo "bobbens"
3 * New/updated tests: aschiffler at ferzkopp dot net
4 */
5
6#include <stdio.h>
7#include <string.h>
8
9#include "SDL.h"
10#include "SDL_test.h"
11
12/* ================= Test Case Implementation ================== */
13
14/* Fixture */
15
16void
17_audioSetUp(void *arg)
18{
19    /* Start SDL audio subsystem */
20    int ret = SDL_InitSubSystem( SDL_INIT_AUDIO );
21        SDLTest_AssertPass("Call to SDL_InitSubSystem(SDL_INIT_AUDIO)");
22    SDLTest_AssertCheck(ret==0, "Check result from SDL_InitSubSystem(SDL_INIT_AUDIO)");
23    if (ret != 0) {
24           SDLTest_LogError("%s", SDL_GetError());
25        }
26}
27
28
29/* Test callback function */
30void _audio_testCallback(void *userdata, Uint8 *stream, int len)
31{
32   /* TODO: add tracking if callback was called */
33}
34
35
36/* Test case functions */
37
38/**
39 * \brief Stop and restart audio subsystem
40 *
41 * \sa http://wiki.libsdl.org/moin.cgi/SDL_QuitSubSystem
42 * \sa http://wiki.libsdl.org/moin.cgi/SDL_InitSubSystem
43 */
44int audio_quitInitAudioSubSystem()
45{
46    /* Stop SDL audio subsystem */
47    SDL_QuitSubSystem( SDL_INIT_AUDIO );
48        SDLTest_AssertPass("Call to SDL_QuitSubSystem(SDL_INIT_AUDIO)");
49
50        /* Restart audio again */
51        _audioSetUp(NULL);
52
53    return TEST_COMPLETED;
54}
55
56/**
57 * \brief Start and stop audio directly
58 *
59 * \sa http://wiki.libsdl.org/moin.cgi/SDL_InitAudio
60 * \sa http://wiki.libsdl.org/moin.cgi/SDL_QuitAudio
61 */
62int audio_initQuitAudio()
63{
64        int result;
65    int i, iMax;
66    const char* audioDriver;
67
68    /* Stop SDL audio subsystem */
69    SDL_QuitSubSystem( SDL_INIT_AUDIO );
70        SDLTest_AssertPass("Call to SDL_QuitSubSystem(SDL_INIT_AUDIO)");
71
72        /* Loop over all available audio drivers */
73        iMax = SDL_GetNumAudioDrivers();
74        SDLTest_AssertPass("Call to SDL_GetNumAudioDrivers");
75        SDLTest_AssertCheck(iMax > 0, "Validate number of audio drivers; expected: >0 got: %d", iMax);
76        for (i = 0; i < iMax; i++) {
77            audioDriver = SDL_GetAudioDriver(i);
78            SDLTest_AssertPass("Call to SDL_GetAudioDriver(%d)", i);
79            SDLTest_AssertCheck(audioDriver != NULL, "Audio driver name is not NULL");
80            SDLTest_AssertCheck(audioDriver[0] != '\0', "Audio driver name is not empty; got: %s", audioDriver);
81
82            /* Call Init */
83            result = SDL_AudioInit(audioDriver);
84            SDLTest_AssertPass("Call to SDL_AudioInit('%s')", audioDriver);
85            SDLTest_AssertCheck(result == 0, "Validate result value; expected: 0 got: %d", result);
86
87            /* Call Quit */
88            SDL_AudioQuit();
89            SDLTest_AssertPass("Call to SDL_AudioQuit()");
90    }
91
92    /* NULL driver specification */
93    audioDriver = NULL;
94
95    /* Call Init */
96    result = SDL_AudioInit(audioDriver);
97    SDLTest_AssertPass("Call to SDL_AudioInit(NULL)");
98    SDLTest_AssertCheck(result == 0, "Validate result value; expected: 0 got: %d", result);
99
100    /* Call Quit */
101    SDL_AudioQuit();
102    SDLTest_AssertPass("Call to SDL_AudioQuit()");
103
104        /* Restart audio again */
105        _audioSetUp(NULL);
106
107    return TEST_COMPLETED;
108}
109
110/**
111 * \brief Start, open, close and stop audio
112 *
113 * \sa http://wiki.libsdl.org/moin.cgi/SDL_InitAudio
114 * \sa http://wiki.libsdl.org/moin.cgi/SDL_OpenAudio
115 * \sa http://wiki.libsdl.org/moin.cgi/SDL_CloseAudio
116 * \sa http://wiki.libsdl.org/moin.cgi/SDL_QuitAudio
117 */
118int audio_initOpenCloseQuitAudio()
119{
120    int result;
121    int i, iMax, j;
122    const char* audioDriver;
123    SDL_AudioSpec desired;
124
125    /* Stop SDL audio subsystem */
126    SDL_QuitSubSystem( SDL_INIT_AUDIO );
127        SDLTest_AssertPass("Call to SDL_QuitSubSystem(SDL_INIT_AUDIO)");
128
129        /* Loop over all available audio drivers */
130        iMax = SDL_GetNumAudioDrivers();
131        SDLTest_AssertPass("Call to SDL_GetNumAudioDrivers");
132        SDLTest_AssertCheck(iMax > 0, "Validate number of audio drivers; expected: >0 got: %d", iMax);
133        for (i = 0; i < iMax; i++) {
134            audioDriver = SDL_GetAudioDriver(i);
135            SDLTest_AssertPass("Call to SDL_GetAudioDriver(%d)", i);
136            SDLTest_AssertCheck(audioDriver != NULL, "Audio driver name is not NULL");
137            SDLTest_AssertCheck(audioDriver[0] != '\0', "Audio driver name is not empty; got: %s", audioDriver);
138
139            /* Change specs */
140            for (j = 0; j < 2; j++) {
141
142                /* Call Init */
143                result = SDL_AudioInit(audioDriver);
144                SDLTest_AssertPass("Call to SDL_AudioInit('%s')", audioDriver);
145                SDLTest_AssertCheck(result == 0, "Validate result value; expected: 0 got: %d", result);
146
147                /* Set spec */
148                SDL_memset(&desired, 0, sizeof(desired));
149                switch (j) {
150                    case 0:
151                    /* Set standard desired spec */
152                    desired.freq = 22050;
153                    desired.format = AUDIO_S16SYS;
154                    desired.channels = 2;
155                    desired.samples = 4096;
156                    desired.callback = _audio_testCallback;
157                    desired.userdata = NULL;
158                    break;
159
160                    case 1:
161                    /* Set custom desired spec */
162                    desired.freq = 48000;
163                    desired.format = AUDIO_F32SYS;
164                    desired.channels = 2;
165                    desired.samples = 2048;
166                    desired.callback = _audio_testCallback;
167                    desired.userdata = NULL;
168                    break;
169            }
170
171            /* Call Open */
172            result = SDL_OpenAudio(&desired, NULL);
173            SDLTest_AssertPass("Call to SDL_OpenAudio(desired_spec_%d, NULL)", j);
174            SDLTest_AssertCheck(result == 0, "Verify return value; expected: 0 got: %d", result);
175
176            /* Call Close */
177                    SDL_CloseAudio();
178                    SDLTest_AssertPass("Call to SDL_CloseAudio()");
179
180            /* Call Quit */
181            SDL_AudioQuit();
182            SDLTest_AssertPass("Call to SDL_AudioQuit()");
183
184        } /* spec loop */
185    } /* driver loop */
186
187        /* Restart audio again */
188        _audioSetUp(NULL);
189
190    return TEST_COMPLETED;
191}
192
193/**
194 * \brief Enumerate and name available audio devices (output and capture).
195 *
196 * \sa http://wiki.libsdl.org/moin.cgi/SDL_GetNumAudioDevices
197 * \sa http://wiki.libsdl.org/moin.cgi/SDL_GetAudioDeviceName
198 */
199int audio_enumerateAndNameAudioDevices()
200{
201   int t, tt;
202   int i, n, nn;
203   const char *name, *nameAgain;
204
205   /* Iterate over types: t=0 output device, t=1 input/capture device */
206   for (t=0; t<2; t++) {
207
208      /* Get number of devices. */
209      n = SDL_GetNumAudioDevices(t);
210      SDLTest_AssertPass("Call to SDL_GetNumAudioDevices(%i)", t);
211      SDLTest_Log("Number of %s devices < 0, reported as %i", (t) ? "capture" : "output", n);
212      SDLTest_AssertCheck(n >= 0, "Validate result is >= 0, got: %i", n);
213
214      /* Variation of non-zero type */
215      if (t==1) {
216         tt = t + SDLTest_RandomIntegerInRange(1,10);
217         nn = SDL_GetNumAudioDevices(tt);
218         SDLTest_AssertCheck(n==nn, "Verify result from SDL_GetNumAudioDevices(%i), expected same number of audio devices %i, got %i", tt, n, nn);
219         nn = SDL_GetNumAudioDevices(-tt);
220         SDLTest_AssertCheck(n==nn, "Verify result from SDL_GetNumAudioDevices(%i), expected same number of audio devices %i, got %i", -tt, n, nn);
221      }
222
223      /* List devices. */
224      if (n>0) {
225         for (i=0; i<n; i++) {
226            name = SDL_GetAudioDeviceName(i, t);
227            SDLTest_AssertPass("Call to SDL_GetAudioDeviceName(%i, %i)", i, t);
228            SDLTest_AssertCheck(name != NULL, "Verify result from SDL_GetAudioDeviceName(%i, %i) is not NULL", i, t);
229            if (name != NULL) {
230              SDLTest_AssertCheck(name[0] != '\0', "verify result from SDL_GetAudioDeviceName(%i, %i) is not empty, got: '%s'", i, t, name);
231              if (t==1) {
232                  /* Also try non-zero type */
233                  tt = t + SDLTest_RandomIntegerInRange(1,10);
234                  nameAgain = SDL_GetAudioDeviceName(i, tt);
235                  SDLTest_AssertCheck(nameAgain != NULL, "Verify result from SDL_GetAudioDeviceName(%i, %i) is not NULL", i, tt);
236                  if (nameAgain != NULL) {
237                    SDLTest_AssertCheck(nameAgain[0] != '\0', "Verify result from SDL_GetAudioDeviceName(%i, %i) is not empty, got: '%s'", i, tt, nameAgain);
238                    SDLTest_AssertCheck(SDL_strcmp(name, nameAgain)==0,
239                      "Verify SDL_GetAudioDeviceName(%i, %i) and SDL_GetAudioDeviceName(%i %i) return the same string",
240                      i, t, i, tt);
241                  }
242               }
243            }
244         }
245      }
246   }
247
248   return TEST_COMPLETED;
249}
250
251/**
252 * \brief Negative tests around enumeration and naming of audio devices.
253 *
254 * \sa http://wiki.libsdl.org/moin.cgi/SDL_GetNumAudioDevices
255 * \sa http://wiki.libsdl.org/moin.cgi/SDL_GetAudioDeviceName
256 */
257int audio_enumerateAndNameAudioDevicesNegativeTests()
258{
259   int t;
260   int i, j, no, nc;
261   const char *name;
262
263   /* Get number of devices. */
264   no = SDL_GetNumAudioDevices(0);
265   SDLTest_AssertPass("Call to SDL_GetNumAudioDevices(0)");
266   nc = SDL_GetNumAudioDevices(1);
267   SDLTest_AssertPass("Call to SDL_GetNumAudioDevices(1)");
268
269   /* Invalid device index when getting name */
270   for (t=0; t<2; t++) {
271      /* Negative device index */
272      i = SDLTest_RandomIntegerInRange(-10,-1);
273      name = SDL_GetAudioDeviceName(i, t);
274      SDLTest_AssertPass("Call to SDL_GetAudioDeviceName(%i, %i)", i, t);
275      SDLTest_AssertCheck(name == NULL, "Check SDL_GetAudioDeviceName(%i, %i) result NULL, expected NULL, got: %s", i, t, (name == NULL) ? "NULL" : name);
276
277      /* Device index past range */
278      for (j=0; j<3; j++) {
279         i = (t) ? nc+j : no+j;
280         name = SDL_GetAudioDeviceName(i, t);
281         SDLTest_AssertPass("Call to SDL_GetAudioDeviceName(%i, %i)", i, t);
282         SDLTest_AssertCheck(name == NULL, "Check SDL_GetAudioDeviceName(%i, %i) result, expected: NULL, got: %s", i, t, (name == NULL) ? "NULL" : name);
283      }
284
285      /* Capture index past capture range but within output range */
286      if ((no>0) && (no>nc) && (t==1)) {
287         i = no-1;
288         name = SDL_GetAudioDeviceName(i, t);
289         SDLTest_AssertPass("Call to SDL_GetAudioDeviceName(%i, %i)", i, t);
290         SDLTest_AssertCheck(name == NULL, "Check SDL_GetAudioDeviceName(%i, %i) result, expected: NULL, got: %s", i, t, (name == NULL) ? "NULL" : name);
291      }
292   }
293
294   return TEST_COMPLETED;
295}
296
297
298/**
299 * \brief Checks available audio driver names.
300 *
301 * \sa http://wiki.libsdl.org/moin.cgi/SDL_GetNumAudioDrivers
302 * \sa http://wiki.libsdl.org/moin.cgi/SDL_GetAudioDriver
303 */
304int audio_printAudioDrivers()
305{
306   int i, n;
307   const char *name;
308
309   /* Get number of drivers */
310   n = SDL_GetNumAudioDrivers();
311   SDLTest_AssertPass("Call to SDL_GetNumAudioDrivers()");
312   SDLTest_AssertCheck(n>=0, "Verify number of audio drivers >= 0, got: %i", n);
313
314   /* List drivers. */
315   if (n>0)
316   {
317      for (i=0; i<n; i++) {
318         name = SDL_GetAudioDriver(i);
319         SDLTest_AssertPass("Call to SDL_GetAudioDriver(%i)", i);
320         SDLTest_AssertCheck(name != NULL, "Verify returned name is not NULL");
321         if (name != NULL) {
322            SDLTest_AssertCheck(name[0] != '\0', "Verify returned name is not empty, got: '%s'", name);
323         }
324      }
325   }
326
327   return TEST_COMPLETED;
328}
329
330
331/**
332 * \brief Checks current audio driver name with initialized audio.
333 *
334 * \sa http://wiki.libsdl.org/moin.cgi/SDL_GetCurrentAudioDriver
335 */
336int audio_printCurrentAudioDriver()
337{
338   /* Check current audio driver */
339   const char *name = SDL_GetCurrentAudioDriver();
340   SDLTest_AssertPass("Call to SDL_GetCurrentAudioDriver()");
341   SDLTest_AssertCheck(name != NULL, "Verify returned name is not NULL");
342   if (name != NULL) {
343      SDLTest_AssertCheck(name[0] != '\0', "Verify returned name is not empty, got: '%s'", name);
344   }
345
346   return TEST_COMPLETED;
347}
348
349/* Definition of all formats, channels, and frequencies used to test audio conversions */
350const int _numAudioFormats = 18;
351SDL_AudioFormat _audioFormats[] = { AUDIO_S8, AUDIO_U8, AUDIO_S16LSB, AUDIO_S16MSB, AUDIO_S16SYS, AUDIO_S16, AUDIO_U16LSB,
352                AUDIO_U16MSB, AUDIO_U16SYS, AUDIO_U16, AUDIO_S32LSB, AUDIO_S32MSB, AUDIO_S32SYS, AUDIO_S32,
353                                AUDIO_F32LSB, AUDIO_F32MSB, AUDIO_F32SYS, AUDIO_F32 };
354char *_audioFormatsVerbose[] = { "AUDIO_S8", "AUDIO_U8", "AUDIO_S16LSB", "AUDIO_S16MSB", "AUDIO_S16SYS", "AUDIO_S16", "AUDIO_U16LSB",
355                "AUDIO_U16MSB", "AUDIO_U16SYS", "AUDIO_U16", "AUDIO_S32LSB", "AUDIO_S32MSB", "AUDIO_S32SYS", "AUDIO_S32",
356                                "AUDIO_F32LSB", "AUDIO_F32MSB", "AUDIO_F32SYS", "AUDIO_F32" };
357const int _numAudioChannels = 4;
358Uint8 _audioChannels[] = { 1, 2, 4, 6 };
359const int _numAudioFrequencies = 4;
360int _audioFrequencies[] = { 11025, 22050, 44100, 48000 };
361
362
363/**
364 * \brief Builds various audio conversion structures
365 *
366 * \sa http://wiki.libsdl.org/moin.cgi/SDL_BuildAudioCVT
367 */
368int audio_buildAudioCVT()
369{
370  int result;
371  SDL_AudioCVT  cvt;
372  SDL_AudioSpec spec1;
373  SDL_AudioSpec spec2;
374  int i, ii, j, jj, k, kk;
375
376  /* No conversion needed */
377  spec1.format = AUDIO_S16LSB;
378  spec1.channels = 2;
379  spec1.freq = 22050;
380  result = SDL_BuildAudioCVT(&cvt, spec1.format, spec1.channels, spec1.freq,
381                                   spec1.format, spec1.channels, spec1.freq);
382  SDLTest_AssertPass("Call to SDL_BuildAudioCVT(spec1 ==> spec1)");
383  SDLTest_AssertCheck(result == 0, "Verify result value; expected: 0, got: %i", result);
384
385  /* Typical conversion */
386  spec1.format = AUDIO_S8;
387  spec1.channels = 1;
388  spec1.freq = 22050;
389  spec2.format = AUDIO_S16LSB;
390  spec2.channels = 2;
391  spec2.freq = 44100;
392  result = SDL_BuildAudioCVT(&cvt, spec1.format, spec1.channels, spec1.freq,
393                                   spec2.format, spec2.channels, spec2.freq);
394  SDLTest_AssertPass("Call to SDL_BuildAudioCVT(spec1 ==> spec2)");
395  SDLTest_AssertCheck(result == 1, "Verify result value; expected: 1, got: %i", result);
396
397  /* All source conversions with random conversion targets, allow 'null' conversions */
398  for (i = 0; i < _numAudioFormats; i++) {
399    for (j = 0; j < _numAudioChannels; j++) {
400      for (k = 0; k < _numAudioFrequencies; k++) {
401        spec1.format = _audioFormats[i];
402        spec1.channels = _audioChannels[j];
403        spec1.freq = _audioFrequencies[k];
404        ii = SDLTest_RandomIntegerInRange(0, _numAudioFormats - 1);
405        jj = SDLTest_RandomIntegerInRange(0, _numAudioChannels - 1);
406        kk = SDLTest_RandomIntegerInRange(0, _numAudioFrequencies - 1);
407        spec2.format = _audioFormats[ii];
408        spec2.channels = _audioChannels[jj];
409        spec2.freq = _audioFrequencies[kk];
410        result = SDL_BuildAudioCVT(&cvt, spec1.format, spec1.channels, spec1.freq,
411                                         spec2.format, spec2.channels, spec2.freq);
412        SDLTest_AssertPass("Call to SDL_BuildAudioCVT(format[%i]=%s(%i),channels[%i]=%i,freq[%i]=%i ==> format[%i]=%s(%i),channels[%i]=%i,freq[%i]=%i)",
413            i, _audioFormatsVerbose[i], spec1.format, j, spec1.channels, k, spec1.freq, ii, _audioFormatsVerbose[ii], spec2.format, jj, spec2.channels, kk, spec2.freq);
414        SDLTest_AssertCheck(result == 0 || result == 1, "Verify result value; expected: 0 or 1, got: %i", result);
415        if (result<0) {
416          SDLTest_LogError(SDL_GetError());
417        } else {
418          SDLTest_AssertCheck(cvt.len_mult > 0, "Verify that cvt.len_mult value; expected: >0, got: %i", cvt.len_mult);
419        }
420      }
421    }
422  }
423
424   return TEST_COMPLETED;
425}
426
427/**
428 * \brief Checkes calls with invalid input to SDL_BuildAudioCVT
429 *
430 * \sa http://wiki.libsdl.org/moin.cgi/SDL_BuildAudioCVT
431 */
432int audio_buildAudioCVTNegative()
433{
434  const char *expectedError = "Parameter 'cvt' is invalid";
435  const char *error;
436  int result;
437  SDL_AudioCVT  cvt;
438  SDL_AudioSpec spec1;
439  SDL_AudioSpec spec2;
440  int i;
441  char message[256];
442
443  /* Valid format */
444  spec1.format = AUDIO_S8;
445  spec1.channels = 1;
446  spec1.freq = 22050;
447  spec2.format = AUDIO_S16LSB;
448  spec2.channels = 2;
449  spec2.freq = 44100;
450
451  SDL_ClearError();
452  SDLTest_AssertPass("Call to SDL_ClearError()");
453
454  /* NULL input for CVT buffer */
455  result = SDL_BuildAudioCVT((SDL_AudioCVT *)NULL, spec1.format, spec1.channels, spec1.freq,
456                                                   spec2.format, spec2.channels, spec2.freq);
457  SDLTest_AssertPass("Call to SDL_BuildAudioCVT(NULL,...)");
458  SDLTest_AssertCheck(result == -1, "Verify result value; expected: -1, got: %i", result);
459  error = SDL_GetError();
460  SDLTest_AssertPass("Call to SDL_GetError()");
461  SDLTest_AssertCheck(error != NULL, "Validate that error message was not NULL");
462  if (error != NULL) {
463      SDLTest_AssertCheck(SDL_strcmp(error, expectedError) == 0,
464          "Validate error message, expected: '%s', got: '%s'", expectedError, error);
465  }
466
467  /* Invalid conversions */
468  for (i = 1; i < 64; i++) {
469    /* Valid format to start with */
470    spec1.format = AUDIO_S8;
471    spec1.channels = 1;
472    spec1.freq = 22050;
473    spec2.format = AUDIO_S16LSB;
474    spec2.channels = 2;
475    spec2.freq = 44100;
476
477    SDL_ClearError();
478    SDLTest_AssertPass("Call to SDL_ClearError()");
479
480    /* Set various invalid format inputs */
481    SDL_strlcpy(message, "Invalid: ", 256);
482    if (i & 1) {
483        SDL_strlcat(message, " spec1.format", 256);
484        spec1.format = 0;
485    }
486    if (i & 2) {
487        SDL_strlcat(message, " spec1.channels", 256);
488        spec1.channels = 0;
489    }
490    if (i & 4) {
491        SDL_strlcat(message, " spec1.freq", 256);
492        spec1.freq = 0;
493    }
494    if (i & 8) {
495        SDL_strlcat(message, " spec2.format", 256);
496        spec2.format = 0;
497    }
498    if (i & 16) {
499        SDL_strlcat(message, " spec2.channels", 256);
500        spec2.channels = 0;
501    }
502    if (i & 32) {
503        SDL_strlcat(message, " spec2.freq", 256);
504        spec2.freq = 0;
505    }
506    SDLTest_Log(message);
507    result = SDL_BuildAudioCVT(&cvt, spec1.format, spec1.channels, spec1.freq,
508                                   spec2.format, spec2.channels, spec2.freq);
509    SDLTest_AssertPass("Call to SDL_BuildAudioCVT(spec1 ==> spec2)");
510    SDLTest_AssertCheck(result == -1, "Verify result value; expected: -1, got: %i", result);
511    error = SDL_GetError();
512    SDLTest_AssertPass("Call to SDL_GetError()");
513    SDLTest_AssertCheck(error != NULL && error[0] != '\0', "Validate that error message was not NULL or empty");
514  }
515
516  SDL_ClearError();
517  SDLTest_AssertPass("Call to SDL_ClearError()");
518
519  return TEST_COMPLETED;
520}
521
522/**
523 * \brief Checks current audio status.
524 *
525 * \sa http://wiki.libsdl.org/moin.cgi/SDL_GetAudioStatus
526 */
527int audio_getAudioStatus()
528{
529   SDL_AudioStatus result;
530
531   /* Check current audio status */
532   result = SDL_GetAudioStatus();
533   SDLTest_AssertPass("Call to SDL_GetAudioStatus()");
534   SDLTest_AssertCheck(result == SDL_AUDIO_STOPPED || result == SDL_AUDIO_PLAYING || result == SDL_AUDIO_PAUSED,
535        "Verify returned value; expected: STOPPED (%i) | PLAYING (%i) | PAUSED (%i), got: %i",
536        SDL_AUDIO_STOPPED, SDL_AUDIO_PLAYING, SDL_AUDIO_PAUSED, result);
537
538   return TEST_COMPLETED;
539}
540
541
542
543/**
544 * \brief Opens, checks current audio status, and closes a device.
545 *
546 * \sa http://wiki.libsdl.org/moin.cgi/SDL_GetAudioStatus
547 */
548int audio_openCloseAndGetAudioStatus()
549{
550   SDL_AudioStatus result;
551   int i;
552   int count;
553   char *device;
554   SDL_AudioDeviceID id;
555   SDL_AudioSpec desired, obtained;
556
557   /* Get number of devices. */
558   count = SDL_GetNumAudioDevices(0);
559   SDLTest_AssertPass("Call to SDL_GetNumAudioDevices(0)");
560   if (count > 0) {
561     for (i = 0; i < count; i++) {
562       /* Get device name */
563       device = (char *)SDL_GetAudioDeviceName(i, 0);
564       SDLTest_AssertPass("SDL_GetAudioDeviceName(%i,0)", i);
565       SDLTest_AssertCheck(device != NULL, "Validate device name is not NULL; got: %s", (device != NULL) ? device : "NULL");
566       if (device == NULL) return TEST_ABORTED;
567
568       /* Set standard desired spec */
569       desired.freq=22050;
570       desired.format=AUDIO_S16SYS;
571       desired.channels=2;
572       desired.samples=4096;
573       desired.callback=_audio_testCallback;
574       desired.userdata=NULL;
575
576       /* Open device */
577       id = SDL_OpenAudioDevice((const char *)device, 0, &desired, &obtained, SDL_AUDIO_ALLOW_ANY_CHANGE);
578       SDLTest_AssertPass("SDL_OpenAudioDevice('%s',...)", device);
579       SDLTest_AssertCheck(id > 1, "Validate device ID; expected: >=2, got: %i", id);
580       if (id > 1) {
581
582         /* Check device audio status */
583         result = SDL_GetAudioDeviceStatus(id);
584         SDLTest_AssertPass("Call to SDL_GetAudioDeviceStatus()");
585         SDLTest_AssertCheck(result == SDL_AUDIO_STOPPED || result == SDL_AUDIO_PLAYING || result == SDL_AUDIO_PAUSED,
586            "Verify returned value; expected: STOPPED (%i) | PLAYING (%i) | PAUSED (%i), got: %i",
587            SDL_AUDIO_STOPPED, SDL_AUDIO_PLAYING, SDL_AUDIO_PAUSED, result);
588
589         /* Close device again */
590         SDL_CloseAudioDevice(id);
591         SDLTest_AssertPass("Call to SDL_CloseAudioDevice()");
592       }
593     }
594   } else {
595     SDLTest_Log("No devices to test with");
596   }
597
598   return TEST_COMPLETED;
599}
600
601/**
602 * \brief Locks and unlocks open audio device.
603 *
604 * \sa http://wiki.libsdl.org/moin.cgi/SDL_LockAudioDevice
605 * \sa http://wiki.libsdl.org/moin.cgi/SDL_UnlockAudioDevice
606 */
607int audio_lockUnlockOpenAudioDevice()
608{
609   int i;
610   int count;
611   char *device;
612   SDL_AudioDeviceID id;
613   SDL_AudioSpec desired, obtained;
614
615   /* Get number of devices. */
616   count = SDL_GetNumAudioDevices(0);
617   SDLTest_AssertPass("Call to SDL_GetNumAudioDevices(0)");
618   if (count > 0) {
619     for (i = 0; i < count; i++) {
620       /* Get device name */
621       device = (char *)SDL_GetAudioDeviceName(i, 0);
622       SDLTest_AssertPass("SDL_GetAudioDeviceName(%i,0)", i);
623       SDLTest_AssertCheck(device != NULL, "Validate device name is not NULL; got: %s", (device != NULL) ? device : "NULL");
624       if (device == NULL) return TEST_ABORTED;
625
626       /* Set standard desired spec */
627       desired.freq=22050;
628       desired.format=AUDIO_S16SYS;
629       desired.channels=2;
630       desired.samples=4096;
631       desired.callback=_audio_testCallback;
632       desired.userdata=NULL;
633
634       /* Open device */
635       id = SDL_OpenAudioDevice((const char *)device, 0, &desired, &obtained, SDL_AUDIO_ALLOW_ANY_CHANGE);
636       SDLTest_AssertPass("SDL_OpenAudioDevice('%s',...)", device);
637       SDLTest_AssertCheck(id > 1, "Validate device ID; expected: >=2, got: %i", id);
638       if (id > 1) {
639         /* Lock to protect callback */
640         SDL_LockAudioDevice(id);
641         SDLTest_AssertPass("SDL_LockAudioDevice(%i)", id);
642
643         /* Simulate callback processing */
644         SDL_Delay(10);
645         SDLTest_Log("Simulate callback processing - delay");
646
647         /* Unlock again */
648         SDL_UnlockAudioDevice(id);
649         SDLTest_AssertPass("SDL_UnlockAudioDevice(%i)", id);
650
651         /* Close device again */
652         SDL_CloseAudioDevice(id);
653         SDLTest_AssertPass("Call to SDL_CloseAudioDevice()");
654       }
655     }
656   } else {
657     SDLTest_Log("No devices to test with");
658   }
659
660   return TEST_COMPLETED;
661}
662
663
664/**
665 * \brief Convert audio using various conversion structures
666 *
667 * \sa http://wiki.libsdl.org/moin.cgi/SDL_BuildAudioCVT
668 * \sa http://wiki.libsdl.org/moin.cgi/SDL_ConvertAudio
669 */
670int audio_convertAudio()
671{
672  int result;
673  SDL_AudioCVT  cvt;
674  SDL_AudioSpec spec1;
675  SDL_AudioSpec spec2;
676  int c;
677  char message[128];
678  int i, ii, j, jj, k, kk, l, ll;
679
680  /* Iterate over bitmask that determines which parameters are modified in the conversion */
681  for (c = 1; c < 8; c++) {
682    SDL_strlcpy(message, "Changing:", 128);
683    if (c & 1) {
684      SDL_strlcat(message, " Format", 128);
685    }
686    if (c & 2) {
687      SDL_strlcat(message, " Channels", 128);
688    }
689    if (c & 4) {
690      SDL_strlcat(message, " Frequencies", 128);
691    }
692    SDLTest_Log(message);
693    /* All source conversions with random conversion targets */
694    for (i = 0; i < _numAudioFormats; i++) {
695      for (j = 0; j < _numAudioChannels; j++) {
696        for (k = 0; k < _numAudioFrequencies; k++) {
697          spec1.format = _audioFormats[i];
698          spec1.channels = _audioChannels[j];
699          spec1.freq = _audioFrequencies[k];
700
701          /* Ensure we have a different target format */
702          do {
703            if (c & 1) {
704              ii = SDLTest_RandomIntegerInRange(0, _numAudioFormats - 1);
705            } else {
706              ii = 1;
707            }
708            if (c & 2) {
709              jj = SDLTest_RandomIntegerInRange(0, _numAudioChannels - 1);
710            } else {
711              jj= j;
712            }
713            if (c & 4) {
714              kk = SDLTest_RandomIntegerInRange(0, _numAudioFrequencies - 1);
715            } else {
716              kk = k;
717            }
718          } while ((i == ii) && (j == jj) && (k == kk));
719          spec2.format = _audioFormats[ii];
720          spec2.channels = _audioChannels[jj];
721          spec2.freq = _audioFrequencies[kk];
722
723          result = SDL_BuildAudioCVT(&cvt, spec1.format, spec1.channels, spec1.freq,
724                                           spec2.format, spec2.channels, spec2.freq);
725          SDLTest_AssertPass("Call to SDL_BuildAudioCVT(format[%i]=%s(%i),channels[%i]=%i,freq[%i]=%i ==> format[%i]=%s(%i),channels[%i]=%i,freq[%i]=%i)",
726            i, _audioFormatsVerbose[i], spec1.format, j, spec1.channels, k, spec1.freq, ii, _audioFormatsVerbose[ii], spec2.format, jj, spec2.channels, kk, spec2.freq);
727          SDLTest_AssertCheck(result == 1, "Verify result value; expected: 1, got: %i", result);
728          if (result != 1) {
729            SDLTest_LogError(SDL_GetError());
730          } else {
731            SDLTest_AssertCheck(cvt.len_mult > 0, "Verify that cvt.len_mult value; expected: >0, got: %i", cvt.len_mult);
732            if (cvt.len_mult < 1) return TEST_ABORTED;
733
734            /* Create some random data to convert */
735            l = 64;
736            ll = l * cvt.len_mult;
737            SDLTest_Log("Creating dummy sample buffer of %i length (%i bytes)", l, ll);
738            cvt.len = l;
739            cvt.buf = (Uint8 *)SDL_malloc(ll);
740            SDLTest_AssertCheck(cvt.buf != NULL, "Check data buffer to convert is not NULL");
741            if (cvt.buf == NULL) return TEST_ABORTED;
742
743            /* Convert the data */
744            result = SDL_ConvertAudio(&cvt);
745            SDLTest_AssertPass("Call to SDL_ConvertAudio()");
746            SDLTest_AssertCheck(result == 0, "Verify result value; expected: 0; got: %i", result);
747            SDLTest_AssertCheck(cvt.buf != NULL, "Verify conversion buffer is not NULL");
748            SDLTest_AssertCheck(cvt.len_ratio > 0.0, "Verify conversion length ratio; expected: >0; got: %f", cvt.len_ratio);
749
750            /* Free converted buffer */
751            SDL_free(cvt.buf);
752            cvt.buf = NULL;
753          }
754        }
755      }
756    }
757  }
758
759   return TEST_COMPLETED;
760}
761
762
763/**
764 * \brief Opens, checks current connected status, and closes a device.
765 *
766 * \sa http://wiki.libsdl.org/moin.cgi/SDL_AudioDeviceConnected
767 */
768int audio_openCloseAudioDeviceConnected()
769{
770   int result = -1;
771   int i;
772   int count;
773   char *device;
774   SDL_AudioDeviceID id;
775   SDL_AudioSpec desired, obtained;
776
777   /* Get number of devices. */
778   count = SDL_GetNumAudioDevices(0);
779   SDLTest_AssertPass("Call to SDL_GetNumAudioDevices(0)");
780   if (count > 0) {
781     for (i = 0; i < count; i++) {
782       /* Get device name */
783       device = (char *)SDL_GetAudioDeviceName(i, 0);
784       SDLTest_AssertPass("SDL_GetAudioDeviceName(%i,0)", i);
785       SDLTest_AssertCheck(device != NULL, "Validate device name is not NULL; got: %s", (device != NULL) ? device : "NULL");
786       if (device == NULL) return TEST_ABORTED;
787
788       /* Set standard desired spec */
789       desired.freq=22050;
790       desired.format=AUDIO_S16SYS;
791       desired.channels=2;
792       desired.samples=4096;
793       desired.callback=_audio_testCallback;
794       desired.userdata=NULL;
795
796       /* Open device */
797       id = SDL_OpenAudioDevice((const char *)device, 0, &desired, &obtained, SDL_AUDIO_ALLOW_ANY_CHANGE);
798       SDLTest_AssertPass("SDL_OpenAudioDevice('%s',...)", device);
799       SDLTest_AssertCheck(id > 1, "Validate device ID; expected: >1, got: %i", id);
800       if (id > 1) {
801
802/* TODO: enable test code when function is available in SDL2 */
803
804#ifdef AUDIODEVICECONNECTED_DEFINED
805         /* Get connected status */
806         result = SDL_AudioDeviceConnected(id);
807         SDLTest_AssertPass("Call to SDL_AudioDeviceConnected()");
808#endif
809         SDLTest_AssertCheck(result == 1, "Verify returned value; expected: 1; got: %i", result);
810
811         /* Close device again */
812         SDL_CloseAudioDevice(id);
813         SDLTest_AssertPass("Call to SDL_CloseAudioDevice()");
814       }
815     }
816   } else {
817     SDLTest_Log("No devices to test with");
818   }
819
820   return TEST_COMPLETED;
821}
822
823
824
825/* ================= Test Case References ================== */
826
827/* Audio test cases */
828static const SDLTest_TestCaseReference audioTest1 =
829        { (SDLTest_TestCaseFp)audio_enumerateAndNameAudioDevices, "audio_enumerateAndNameAudioDevices", "Enumerate and name available audio devices (output and capture)", TEST_ENABLED };
830
831static const SDLTest_TestCaseReference audioTest2 =
832        { (SDLTest_TestCaseFp)audio_enumerateAndNameAudioDevicesNegativeTests, "audio_enumerateAndNameAudioDevicesNegativeTests", "Negative tests around enumeration and naming of audio devices.", TEST_ENABLED };
833
834static const SDLTest_TestCaseReference audioTest3 =
835        { (SDLTest_TestCaseFp)audio_printAudioDrivers, "audio_printAudioDrivers", "Checks available audio driver names.", TEST_ENABLED };
836
837static const SDLTest_TestCaseReference audioTest4 =
838        { (SDLTest_TestCaseFp)audio_printCurrentAudioDriver, "audio_printCurrentAudioDriver", "Checks current audio driver name with initialized audio.", TEST_ENABLED };
839
840static const SDLTest_TestCaseReference audioTest5 =
841        { (SDLTest_TestCaseFp)audio_buildAudioCVT, "audio_buildAudioCVT", "Builds various audio conversion structures.", TEST_ENABLED };
842
843static const SDLTest_TestCaseReference audioTest6 =
844        { (SDLTest_TestCaseFp)audio_buildAudioCVTNegative, "audio_buildAudioCVTNegative", "Checks calls with invalid input to SDL_BuildAudioCVT", TEST_ENABLED };
845
846static const SDLTest_TestCaseReference audioTest7 =
847        { (SDLTest_TestCaseFp)audio_getAudioStatus, "audio_getAudioStatus", "Checks current audio status.", TEST_ENABLED };
848
849static const SDLTest_TestCaseReference audioTest8 =
850        { (SDLTest_TestCaseFp)audio_openCloseAndGetAudioStatus, "audio_openCloseAndGetAudioStatus", "Opens and closes audio device and get audio status.", TEST_ENABLED };
851
852static const SDLTest_TestCaseReference audioTest9 =
853        { (SDLTest_TestCaseFp)audio_lockUnlockOpenAudioDevice, "audio_lockUnlockOpenAudioDevice", "Locks and unlocks an open audio device.", TEST_ENABLED };
854
855/* TODO: enable test when SDL_ConvertAudio segfaults on cygwin have been fixed.    */
856/* For debugging, test case can be run manually using --filter audio_convertAudio  */
857
858static const SDLTest_TestCaseReference audioTest10 =
859        { (SDLTest_TestCaseFp)audio_convertAudio, "audio_convertAudio", "Convert audio using available formats.", TEST_DISABLED };
860
861/* TODO: enable test when SDL_AudioDeviceConnected has been implemented.           */
862
863static const SDLTest_TestCaseReference audioTest11 =
864        { (SDLTest_TestCaseFp)audio_openCloseAudioDeviceConnected, "audio_openCloseAudioDeviceConnected", "Opens and closes audio device and get connected status.", TEST_DISABLED };
865
866static const SDLTest_TestCaseReference audioTest12 =
867        { (SDLTest_TestCaseFp)audio_quitInitAudioSubSystem, "audio_quitInitAudioSubSystem", "Quit and re-init audio subsystem.", TEST_ENABLED };
868
869/* TODO: enable when bugs 1343 and 1396 are fixed.                                          */
870/* For debugging, test case can be run manually using --filter audio_initQuitAudio */
871
872static const SDLTest_TestCaseReference audioTest13 =
873        { (SDLTest_TestCaseFp)audio_initQuitAudio, "audio_initQuitAudio", "Init and quit audio drivers directly.", TEST_DISABLED };
874
875/* TODO: enable when bugs 1343 and 1396 are fixed.                                          */
876/* For debugging, test case can be run manually using --filter audio_initOpenCloseQuitAudio */
877
878static const SDLTest_TestCaseReference audioTest14 =
879        { (SDLTest_TestCaseFp)audio_initOpenCloseQuitAudio, "audio_initOpenCloseQuitAudio", "Cycle through init, open, close and quit with various audio specs.", TEST_DISABLED };
880
881/* Sequence of Audio test cases */
882static const SDLTest_TestCaseReference *audioTests[] =  {
883    &audioTest1, &audioTest2, &audioTest3, &audioTest4, &audioTest5, &audioTest6,
884    &audioTest7, &audioTest8, &audioTest9, &audioTest10, &audioTest11,
885    &audioTest12, &audioTest13, &audioTest14, NULL
886};
887
888/* Audio test suite (global) */
889SDLTest_TestSuiteReference audioTestSuite = {
890    "Audio",
891    _audioSetUp,
892    audioTests,
893    NULL
894};
895