src/audio/mint/SDL_mintaudio_gsxb.c
author Sam Lantinga
Sat, 19 Sep 2009 13:29:40 +0000
changeset 3280 00cace2d9080
parent 2942 1e431c2631ee
permissions -rw-r--r--
Merged a cleaned up version of Jiang's code changes from Google Summer of Code 2009
patmandin@644
     1
/*
patmandin@644
     2
    SDL - Simple DirectMedia Layer
slouken@2859
     3
    Copyright (C) 1997-2009 Sam Lantinga
patmandin@644
     4
patmandin@644
     5
    This library is free software; you can redistribute it and/or
patmandin@644
     6
    modify it under the terms of the GNU Library General Public
patmandin@644
     7
    License as published by the Free Software Foundation; either
patmandin@644
     8
    version 2 of the License, or (at your option) any later version.
patmandin@644
     9
patmandin@644
    10
    This library is distributed in the hope that it will be useful,
patmandin@644
    11
    but WITHOUT ANY WARRANTY; without even the implied warranty of
patmandin@644
    12
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
patmandin@644
    13
    Library General Public License for more details.
patmandin@644
    14
patmandin@644
    15
    You should have received a copy of the GNU Library General Public
patmandin@644
    16
    License along with this library; if not, write to the Free
patmandin@644
    17
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
patmandin@644
    18
patmandin@644
    19
    Sam Lantinga
patmandin@644
    20
    slouken@libsdl.org
patmandin@644
    21
*/
slouken@1402
    22
#include "SDL_config.h"
patmandin@644
    23
patmandin@644
    24
/*
patmandin@644
    25
	MiNT audio driver
patmandin@644
    26
	using XBIOS functions (GSXB compatible driver)
patmandin@644
    27
patmandin@644
    28
	Patrice Mandin
patmandin@644
    29
*/
patmandin@644
    30
patmandin@644
    31
/* Mint includes */
patmandin@644
    32
#include <mint/osbind.h>
patmandin@644
    33
#include <mint/falcon.h>
patmandin@644
    34
#include <mint/cookie.h>
patmandin@644
    35
patmandin@644
    36
#include "SDL_audio.h"
slouken@1361
    37
#include "../SDL_audio_c.h"
slouken@1361
    38
#include "../SDL_sysaudio.h"
patmandin@644
    39
patmandin@1412
    40
#include "../../video/ataricommon/SDL_atarimxalloc_c.h"
patmandin@644
    41
patmandin@644
    42
#include "SDL_mintaudio.h"
patmandin@644
    43
#include "SDL_mintaudio_gsxb.h"
patmandin@644
    44
patmandin@644
    45
/*--- Defines ---*/
patmandin@644
    46
patmandin@644
    47
#define MINT_AUDIO_DRIVER_NAME "mint_gsxb"
patmandin@644
    48
patmandin@644
    49
/* Debug print info */
patmandin@644
    50
#define DEBUG_NAME "audio:gsxb: "
patmandin@962
    51
#if 0
patmandin@644
    52
#define DEBUG_PRINT(what) \
patmandin@644
    53
	{ \
patmandin@644
    54
		printf what; \
patmandin@644
    55
	}
patmandin@644
    56
#else
patmandin@644
    57
#define DEBUG_PRINT(what)
patmandin@644
    58
#endif
patmandin@644
    59
patmandin@644
    60
/*--- Static variables ---*/
patmandin@644
    61
patmandin@644
    62
static unsigned long cookie_snd, cookie_gsxb;
patmandin@644
    63
patmandin@644
    64
/*--- Audio driver functions ---*/
patmandin@644
    65
patmandin@1097
    66
/* GSXB callbacks */
icculus@2049
    67
static void MINTGSXB_GsxbInterrupt(void);
icculus@2049
    68
static void MINTGSXB_GsxbNullInterrupt(void);
patmandin@644
    69
slouken@1895
    70
static void
icculus@2049
    71
MINTGSXB_LockDevice(_THIS)
patmandin@644
    72
{
slouken@1895
    73
    /* Stop replay */
slouken@1895
    74
    Buffoper(0);
patmandin@644
    75
}
patmandin@644
    76
slouken@1895
    77
static void
icculus@2049
    78
MINTGSXB_UnlockDevice(_THIS)
patmandin@644
    79
{
slouken@1895
    80
    /* Restart replay */
slouken@1895
    81
    Buffoper(SB_PLA_ENA | SB_PLA_RPT);
patmandin@644
    82
}
patmandin@644
    83
slouken@1895
    84
static void
icculus@2049
    85
MINTGSXB_CloseDevice(_THIS)
patmandin@644
    86
{
icculus@2049
    87
    if (this->hidden != NULL) {
icculus@2049
    88
        /* Stop replay */
icculus@2049
    89
        Buffoper(0);
patmandin@644
    90
icculus@2049
    91
        /* Uninstall interrupt */
icculus@2049
    92
        if (NSetinterrupt(2, SI_NONE, MINTGSXB_GsxbNullInterrupt) < 0) {
icculus@2049
    93
            DEBUG_PRINT((DEBUG_NAME "NSetinterrupt() failed in close\n"));
icculus@2049
    94
        }
patmandin@644
    95
icculus@2049
    96
        /* Wait if currently playing sound */
slouken@2060
    97
        while (SDL_MintAudio_mutex != 0) {
slouken@2060
    98
        }
patmandin@644
    99
icculus@2049
   100
        /* Clear buffers */
icculus@2049
   101
        if (SDL_MintAudio_audiobuf[0]) {
icculus@2049
   102
            Mfree(SDL_MintAudio_audiobuf[0]);
icculus@2049
   103
            SDL_MintAudio_audiobuf[0] = SDL_MintAudio_audiobuf[1] = NULL;
icculus@2049
   104
        }
icculus@2049
   105
icculus@2049
   106
        /* Unlock sound system */
icculus@2049
   107
        Unlocksnd();
icculus@2049
   108
icculus@2049
   109
        SDL_free(this->hidden);
icculus@2049
   110
        this->hidden = NULL;
slouken@1895
   111
    }
patmandin@644
   112
}
patmandin@644
   113
slouken@1895
   114
static int
icculus@2049
   115
MINTGSXB_CheckAudio(_THIS)
patmandin@644
   116
{
slouken@1895
   117
    long snd_format;
slouken@1895
   118
    int i, resolution, format_signed, format_bigendian;
icculus@2049
   119
    SDL_AudioFormat test_format = SDL_FirstAudioFormat(this->spec.format);
icculus@2005
   120
    int valid_datatype = 0;
patmandin@644
   121
icculus@2049
   122
    resolution = SDL_AUDIO_BITSIZE(this->spec.format);
icculus@2049
   123
    format_signed = SDL_AUDIO_ISSIGNED(this->spec.format);
icculus@2049
   124
    format_bigendian = SDL_AUDIO_ISBIGENDIAN(this->spec.format);
patmandin@704
   125
icculus@2005
   126
    DEBUG_PRINT((DEBUG_NAME "asked: %d bits, ", resolution));
icculus@2049
   127
    DEBUG_PRINT(("float=%d, ", SDL_AUDIO_ISFLOAT(this->spec.format)));
icculus@2005
   128
    DEBUG_PRINT(("signed=%d, ", format_signed));
icculus@2005
   129
    DEBUG_PRINT(("big endian=%d, ", format_bigendian));
icculus@2049
   130
    DEBUG_PRINT(("channels=%d, ", this->spec.channels));
icculus@2049
   131
    DEBUG_PRINT(("freq=%d\n", this->spec.freq));
patmandin@644
   132
icculus@2049
   133
    if (this->spec.channels > 2) {
slouken@2060
   134
        this->spec.channels = 2;        /* no more than stereo! */
icculus@2005
   135
    }
icculus@2005
   136
icculus@2005
   137
    while ((!valid_datatype) && (test_format)) {
icculus@2044
   138
        /* Check formats available */
icculus@2044
   139
        snd_format = Sndstatus(SND_QUERYFORMATS);
icculus@2049
   140
        this->spec.format = test_format;
icculus@2049
   141
        resolution = SDL_AUDIO_BITSIZE(this->spec.format);
icculus@2049
   142
        format_signed = SDL_AUDIO_ISSIGNED(this->spec.format);
icculus@2049
   143
        format_bigendian = SDL_AUDIO_ISBIGENDIAN(this->spec.format);
icculus@2005
   144
        switch (test_format) {
slouken@2060
   145
        case AUDIO_U8:
slouken@2060
   146
        case AUDIO_S8:
slouken@2060
   147
            if (snd_format & SND_FORMAT8) {
slouken@2060
   148
                valid_datatype = 1;
slouken@2060
   149
                snd_format = Sndstatus(SND_QUERY8BIT);
slouken@2060
   150
            }
slouken@2060
   151
            break;
icculus@2044
   152
slouken@2060
   153
        case AUDIO_U16LSB:
slouken@2060
   154
        case AUDIO_S16LSB:
slouken@2060
   155
        case AUDIO_U16MSB:
slouken@2060
   156
        case AUDIO_S16MSB:
slouken@2060
   157
            if (snd_format & SND_FORMAT16) {
slouken@2060
   158
                valid_datatype = 1;
slouken@2060
   159
                snd_format = Sndstatus(SND_QUERY16BIT);
slouken@2060
   160
            }
slouken@2060
   161
            break;
icculus@2044
   162
slouken@2060
   163
        case AUDIO_S32LSB:
slouken@2060
   164
        case AUDIO_S32MSB:
slouken@2060
   165
            if (snd_format & SND_FORMAT32) {
slouken@2060
   166
                valid_datatype = 1;
slouken@2060
   167
                snd_format = Sndstatus(SND_QUERY32BIT);
slouken@2060
   168
            }
slouken@2060
   169
            break;
icculus@2044
   170
icculus@2044
   171
            /* no float support... */
icculus@2005
   172
slouken@2060
   173
        default:
slouken@2060
   174
            test_format = SDL_NextAudioFormat();
slouken@2060
   175
            break;
slouken@1895
   176
        }
icculus@2005
   177
    }
icculus@2005
   178
icculus@2005
   179
    if (!valid_datatype) {
icculus@2005
   180
        SDL_SetError("Unsupported audio format");
icculus@2005
   181
        return (-1);
slouken@1895
   182
    }
patmandin@644
   183
slouken@1895
   184
    /* Check signed/unsigned format */
slouken@1895
   185
    if (format_signed) {
slouken@1895
   186
        if (snd_format & SND_FORMATSIGNED) {
slouken@1895
   187
            /* Ok */
slouken@1895
   188
        } else if (snd_format & SND_FORMATUNSIGNED) {
slouken@1895
   189
            /* Give unsigned format */
icculus@2049
   190
            this->spec.format = this->spec.format & (~SDL_AUDIO_MASK_SIGNED);
slouken@1895
   191
        }
slouken@1895
   192
    } else {
slouken@1895
   193
        if (snd_format & SND_FORMATUNSIGNED) {
slouken@1895
   194
            /* Ok */
slouken@1895
   195
        } else if (snd_format & SND_FORMATSIGNED) {
slouken@1895
   196
            /* Give signed format */
icculus@2049
   197
            this->spec.format |= SDL_AUDIO_MASK_SIGNED;
slouken@1895
   198
        }
slouken@1895
   199
    }
patmandin@644
   200
slouken@1895
   201
    if (format_bigendian) {
slouken@1895
   202
        if (snd_format & SND_FORMATBIGENDIAN) {
slouken@1895
   203
            /* Ok */
slouken@1895
   204
        } else if (snd_format & SND_FORMATLITTLEENDIAN) {
slouken@1895
   205
            /* Give little endian format */
icculus@2049
   206
            this->spec.format = this->spec.format & (~SDL_AUDIO_MASK_ENDIAN);
slouken@1895
   207
        }
slouken@1895
   208
    } else {
slouken@1895
   209
        if (snd_format & SND_FORMATLITTLEENDIAN) {
slouken@1895
   210
            /* Ok */
slouken@1895
   211
        } else if (snd_format & SND_FORMATBIGENDIAN) {
slouken@1895
   212
            /* Give big endian format */
icculus@2049
   213
            this->spec.format |= SDL_AUDIO_MASK_ENDIAN;
slouken@1895
   214
        }
slouken@1895
   215
    }
slouken@1895
   216
slouken@1895
   217
    /* Calculate and select the closest frequency */
slouken@1895
   218
    MINTAUDIO_freqcount = 0;
slouken@1895
   219
    for (i = 1; i < 4; i++) {
slouken@1895
   220
        SDL_MintAudio_AddFrequency(this,
slouken@1895
   221
                                   MASTERCLOCK_44K / (MASTERPREDIV_MILAN *
slouken@1895
   222
                                                      (1 << i)),
slouken@1895
   223
                                   MASTERCLOCK_44K, (1 << i) - 1, -1);
slouken@1895
   224
    }
patmandin@644
   225
patmandin@961
   226
#if 1
slouken@1895
   227
    for (i = 0; i < MINTAUDIO_freqcount; i++) {
slouken@1895
   228
        DEBUG_PRINT((DEBUG_NAME "freq %d: %lu Hz, clock %lu, prediv %d\n",
slouken@1895
   229
                     i, MINTAUDIO_frequencies[i].frequency,
slouken@1895
   230
                     MINTAUDIO_frequencies[i].masterclock,
slouken@1895
   231
                     MINTAUDIO_frequencies[i].predivisor));
slouken@1895
   232
    }
patmandin@961
   233
#endif
patmandin@961
   234
icculus@2049
   235
    MINTAUDIO_numfreq = SDL_MintAudio_SearchFrequency(this, this->spec.freq);
icculus@2049
   236
    this->spec.freq = MINTAUDIO_frequencies[MINTAUDIO_numfreq].frequency;
slouken@1895
   237
slouken@2043
   238
    DEBUG_PRINT((DEBUG_NAME "obtained: %d bits, ",
icculus@2049
   239
                 SDL_AUDIO_BITSIZE(this->spec.format)));
icculus@2049
   240
    DEBUG_PRINT(("float=%d, ", SDL_AUDIO_ISFLOAT(this->spec.format)));
icculus@2049
   241
    DEBUG_PRINT(("signed=%d, ", SDL_AUDIO_ISSIGNED(this->spec.format)));
slouken@2060
   242
    DEBUG_PRINT(("big endian=%d, ",
slouken@2060
   243
                 SDL_AUDIO_ISBIGENDIAN(this->spec.format)));
icculus@2049
   244
    DEBUG_PRINT(("channels=%d, ", this->spec.channels));
icculus@2049
   245
    DEBUG_PRINT(("freq=%d\n", this->spec.freq));
slouken@1895
   246
slouken@1895
   247
    return 0;
slouken@1895
   248
}
slouken@1895
   249
slouken@1895
   250
static void
icculus@2049
   251
MINTGSXB_InitAudio(_THIS)
slouken@1895
   252
{
slouken@1895
   253
    int channels_mode, prediv;
slouken@1895
   254
    void *buffer;
slouken@1895
   255
slouken@1895
   256
    /* Stop currently playing sound */
slouken@1895
   257
    Buffoper(0);
slouken@1895
   258
slouken@1895
   259
    /* Set replay tracks */
slouken@1895
   260
    Settracks(0, 0);
slouken@1895
   261
    Setmontracks(0);
patmandin@644
   262
slouken@1895
   263
    /* Select replay format */
icculus@2049
   264
    switch (SDL_AUDIO_BITSIZE(this->spec.format)) {
slouken@1895
   265
    case 8:
icculus@2049
   266
        if (this->spec.channels == 2) {
slouken@1895
   267
            channels_mode = STEREO8;
slouken@1895
   268
        } else {
slouken@1895
   269
            channels_mode = MONO8;
slouken@1895
   270
        }
slouken@1895
   271
        break;
slouken@1895
   272
    case 16:
icculus@2049
   273
        if (this->spec.channels == 2) {
slouken@1895
   274
            channels_mode = STEREO16;
slouken@1895
   275
        } else {
slouken@1895
   276
            channels_mode = MONO16;
slouken@1895
   277
        }
slouken@1895
   278
        break;
icculus@2005
   279
    case 32:
icculus@2049
   280
        if (this->spec.channels == 2) {
icculus@2005
   281
            channels_mode = STEREO32;
icculus@2005
   282
        } else {
icculus@2005
   283
            channels_mode = MONO32;
icculus@2005
   284
        }
icculus@2005
   285
        break;
slouken@1895
   286
    default:
slouken@1895
   287
        channels_mode = STEREO16;
slouken@1895
   288
        break;
slouken@1895
   289
    }
slouken@1895
   290
    if (Setmode(channels_mode) < 0) {
slouken@1895
   291
        DEBUG_PRINT((DEBUG_NAME "Setmode() failed\n"));
slouken@1895
   292
    }
patmandin@644
   293
slouken@1895
   294
    prediv = MINTAUDIO_frequencies[MINTAUDIO_numfreq].predivisor;
slouken@1895
   295
    Devconnect(DMAPLAY, DAC, CLKEXT, prediv, 1);
slouken@1895
   296
slouken@1895
   297
    /* Set buffer */
slouken@1895
   298
    buffer = SDL_MintAudio_audiobuf[SDL_MintAudio_numbuf];
icculus@2049
   299
    if (Setbuffer(0, buffer, buffer + this->spec.size) < 0) {
slouken@1895
   300
        DEBUG_PRINT((DEBUG_NAME "Setbuffer() failed\n"));
slouken@1895
   301
    }
slouken@1895
   302
slouken@1895
   303
    /* Install interrupt */
icculus@2049
   304
    if (NSetinterrupt(2, SI_PLAY, MINTGSXB_GsxbInterrupt) < 0) {
slouken@1895
   305
        DEBUG_PRINT((DEBUG_NAME "NSetinterrupt() failed\n"));
slouken@1895
   306
    }
slouken@1895
   307
slouken@1895
   308
    /* Go */
slouken@1895
   309
    Buffoper(SB_PLA_ENA | SB_PLA_RPT);
slouken@1895
   310
    DEBUG_PRINT((DEBUG_NAME "hardware initialized\n"));
patmandin@644
   311
}
patmandin@644
   312
slouken@1895
   313
static int
icculus@2049
   314
MINTGSXB_OpenDevice(_THIS, const char *devname, int iscapture)
patmandin@644
   315
{
slouken@1895
   316
    /* Lock sound system */
slouken@1895
   317
    if (Locksnd() != 1) {
icculus@2049
   318
        SDL_SetError("MINTGSXB_OpenDevice: Audio system already in use");
icculus@2049
   319
        return 0;
slouken@1895
   320
    }
patmandin@644
   321
slouken@1895
   322
    SDL_MintAudio_device = this;
patmandin@644
   323
slouken@1895
   324
    /* Check audio capabilities */
icculus@2049
   325
    if (MINTGSXB_CheckAudio(this) == -1) {
icculus@2049
   326
        return 0;
slouken@1895
   327
    }
slouken@1895
   328
icculus@2049
   329
    /* Initialize all variables that we clean on shutdown */
icculus@2049
   330
    this->hidden = (struct SDL_PrivateAudioData *)
slouken@2060
   331
        SDL_malloc((sizeof *this->hidden));
icculus@2049
   332
    if (this->hidden == NULL) {
icculus@2049
   333
        SDL_OutOfMemory();
icculus@2049
   334
        return 0;
icculus@2049
   335
    }
icculus@2049
   336
    SDL_memset(this->hidden, 0, (sizeof *this->hidden));
icculus@2049
   337
icculus@2049
   338
    SDL_CalculateAudioSpec(&this->spec);
slouken@1895
   339
slouken@1895
   340
    /* Allocate memory for audio buffers in DMA-able RAM */
icculus@2049
   341
    DEBUG_PRINT((DEBUG_NAME "buffer size=%d\n", this->spec.size));
patmandin@644
   342
slouken@2060
   343
    SDL_MintAudio_audiobuf[0] =
slouken@2060
   344
        Atari_SysMalloc(this->spec.size * 2, MX_STRAM);
slouken@1895
   345
    if (SDL_MintAudio_audiobuf[0] == NULL) {
icculus@2049
   346
        SDL_free(this->hidden);
icculus@2049
   347
        this->hidden = NULL;
icculus@2049
   348
        SDL_OutOfMemory();
icculus@2049
   349
        return 0;
slouken@1895
   350
    }
icculus@2049
   351
    SDL_MintAudio_audiobuf[1] = SDL_MintAudio_audiobuf[0] + this->spec.size;
slouken@1895
   352
    SDL_MintAudio_numbuf = 0;
slouken@2060
   353
    SDL_memset(SDL_MintAudio_audiobuf[0], this->spec.silence,
slouken@2060
   354
               this->spec.size * 2);
icculus@2049
   355
    SDL_MintAudio_audiosize = this->spec.size;
slouken@1895
   356
    SDL_MintAudio_mutex = 0;
patmandin@644
   357
slouken@1895
   358
    DEBUG_PRINT((DEBUG_NAME "buffer 0 at 0x%08x\n",
slouken@1895
   359
                 SDL_MintAudio_audiobuf[0]));
slouken@1895
   360
    DEBUG_PRINT((DEBUG_NAME "buffer 1 at 0x%08x\n",
slouken@1895
   361
                 SDL_MintAudio_audiobuf[1]));
patmandin@644
   362
patmandin@2027
   363
    SDL_MintAudio_CheckFpu();
patmandin@2027
   364
slouken@1895
   365
    /* Setup audio hardware */
icculus@2049
   366
    MINTGSXB_InitAudio(this);
patmandin@644
   367
slouken@2060
   368
    return 1;                   /* good to go. */
patmandin@644
   369
}
patmandin@644
   370
slouken@1895
   371
static void
icculus@2049
   372
MINTGSXB_GsxbInterrupt(void)
patmandin@644
   373
{
slouken@1895
   374
    Uint8 *newbuf;
patmandin@644
   375
slouken@1895
   376
    if (SDL_MintAudio_mutex)
slouken@1895
   377
        return;
patmandin@644
   378
slouken@1895
   379
    SDL_MintAudio_mutex = 1;
patmandin@644
   380
slouken@1895
   381
    SDL_MintAudio_numbuf ^= 1;
slouken@1895
   382
    SDL_MintAudio_Callback();
slouken@1895
   383
    newbuf = SDL_MintAudio_audiobuf[SDL_MintAudio_numbuf];
slouken@1895
   384
    Setbuffer(0, newbuf, newbuf + SDL_MintAudio_audiosize);
patmandin@644
   385
slouken@1895
   386
    SDL_MintAudio_mutex = 0;
patmandin@644
   387
}
patmandin@1097
   388
slouken@1895
   389
static void
icculus@2049
   390
MINTGSXB_GsxbNullInterrupt(void)
patmandin@1097
   391
{
patmandin@1097
   392
}
patmandin@1097
   393
icculus@2049
   394
static int
slouken@2060
   395
MINTGSXB_Init(SDL_AudioDriverImpl * impl)
icculus@2049
   396
{
icculus@2049
   397
    /* Cookie _SND present ? if not, assume ST machine */
icculus@2049
   398
    if (Getcookie(C__SND, &cookie_snd) == C_NOTFOUND) {
icculus@2049
   399
        cookie_snd = SND_PSG;
icculus@2049
   400
    }
icculus@2049
   401
icculus@2049
   402
    /* Check if we have 16 bits audio */
icculus@2049
   403
    if ((cookie_snd & SND_16BIT) == 0) {
icculus@2049
   404
        SDL_SetError(DEBUG_NAME "no 16-bit sound");
icculus@2049
   405
        return 0;
icculus@2049
   406
    }
icculus@2049
   407
icculus@2049
   408
    /* Cookie GSXB present ? */
icculus@2049
   409
    cookie_gsxb = (Getcookie(C_GSXB, &cookie_gsxb) == C_FOUND);
icculus@2049
   410
icculus@2049
   411
    /* Is it GSXB ? */
icculus@2049
   412
    if (((cookie_snd & SND_GSXB) == 0) || (cookie_gsxb == 0)) {
icculus@2049
   413
        SDL_SetError(DEBUG_NAME "no GSXB audio");
icculus@2049
   414
        return 0;
icculus@2049
   415
    }
icculus@2049
   416
icculus@2049
   417
    /* Check if audio is lockable */
icculus@2049
   418
    if (Locksnd() != 1) {
icculus@2049
   419
        SDL_SetError(DEBUG_NAME "audio locked by other application");
icculus@2049
   420
        return 0;
icculus@2049
   421
    }
icculus@2049
   422
icculus@2049
   423
    Unlocksnd();
icculus@2049
   424
icculus@2049
   425
    DEBUG_PRINT((DEBUG_NAME "GSXB audio available!\n"));
icculus@2049
   426
icculus@2049
   427
    /* Set the function pointers */
icculus@2049
   428
    impl->OpenDevice = MINTGSXB_OpenDevice;
icculus@2049
   429
    impl->CloseDevice = MINTGSXB_CloseDevice;
patmandin@2191
   430
    impl->LockDevice = MINTGSXB_LockDevice;
patmandin@2191
   431
    impl->UnlockDevice = MINTGSXB_UnlockDevice;
icculus@2049
   432
    impl->OnlyHasDefaultOutputDevice = 1;
icculus@2049
   433
    impl->ProvidesOwnCallbackThread = 1;
icculus@2049
   434
    impl->SkipMixerLock = 1;
icculus@2049
   435
slouken@2942
   436
    return 2;                   /* 2 == definitely has an audio device. */
icculus@2049
   437
}
icculus@2049
   438
icculus@2049
   439
AudioBootStrap MINTAUDIO_GSXB_bootstrap = {
icculus@2049
   440
    MINT_AUDIO_DRIVER_NAME, "MiNT GSXB audio driver", MINTGSXB_Init, 0
icculus@2049
   441
};
icculus@2049
   442
slouken@1895
   443
/* vi: set ts=4 sw=4 expandtab: */