src/audio/SDL_sysaudio.h
author Ryan C. Gordon
Wed, 18 Mar 2015 02:01:17 -0400
changeset 9394 bb28e5281770
parent 9393 ed79a66e57e5
child 9397 d72d2aa46341
permissions -rw-r--r--
Bunch of reworking to how we manage audio devices.

Device enumeration now happens at startup and then is managed exclusively
through hotplugging instead of full redetection. The device name list now has
a unique "handle" associated with each item and SDL will pass this to the
backend so they don't have to figure out how a human readable name maps to
real hardware for a second time.

Other cleanups, fixes, improvements, plus all the audio backends updated to
the new interface...largely untested at this point, though.
slouken@0
     1
/*
slouken@5535
     2
  Simple DirectMedia Layer
slouken@8149
     3
  Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
slouken@0
     4
slouken@5535
     5
  This software is provided 'as-is', without any express or implied
slouken@5535
     6
  warranty.  In no event will the authors be held liable for any damages
slouken@5535
     7
  arising from the use of this software.
slouken@0
     8
slouken@5535
     9
  Permission is granted to anyone to use this software for any purpose,
slouken@5535
    10
  including commercial applications, and to alter it and redistribute it
slouken@5535
    11
  freely, subject to the following restrictions:
slouken@0
    12
slouken@5535
    13
  1. The origin of this software must not be misrepresented; you must not
slouken@5535
    14
     claim that you wrote the original software. If you use this software
slouken@5535
    15
     in a product, an acknowledgment in the product documentation would be
slouken@5535
    16
     appreciated but is not required.
slouken@5535
    17
  2. Altered source versions must be plainly marked as such, and must not be
slouken@5535
    18
     misrepresented as being the original software.
slouken@5535
    19
  3. This notice may not be removed or altered from any source distribution.
slouken@0
    20
*/
icculus@8093
    21
#include "../SDL_internal.h"
slouken@0
    22
slouken@0
    23
#ifndef _SDL_sysaudio_h
slouken@0
    24
#define _SDL_sysaudio_h
slouken@0
    25
slouken@0
    26
#include "SDL_mutex.h"
slouken@0
    27
#include "SDL_thread.h"
slouken@0
    28
slouken@0
    29
/* The SDL audio driver */
slouken@0
    30
typedef struct SDL_AudioDevice SDL_AudioDevice;
slouken@7191
    31
#define _THIS   SDL_AudioDevice *_this
slouken@0
    32
icculus@9394
    33
/* Audio targets should call this as devices are added to the system (such as
icculus@9394
    34
   a USB headset being plugged in), and should also be called for
icculus@9394
    35
   for every device found during DetectDevices(). */
icculus@9394
    36
extern void SDL_AddAudioDevice(const int iscapture, const char *name, void *handle);
icculus@9393
    37
icculus@9394
    38
/* Audio targets should call this as devices are removed, so SDL can update
icculus@9394
    39
   its list of available devices. */
icculus@9394
    40
extern void SDL_RemoveAudioDevice(void *handle);
icculus@9393
    41
icculus@9394
    42
/* Audio targets should call this if an opened audio device is lost while
icculus@9394
    43
   being used. This can happen due to i/o errors, or a device being unplugged,
icculus@9394
    44
   etc. If the device is totally gone, please also call SDL_RemoveAudioDevice()
icculus@9394
    45
   as appropriate so SDL's list of devices is accurate. */
icculus@9394
    46
extern void SDL_OpenedAudioDeviceDisconnected(SDL_AudioDevice *device);
icculus@9393
    47
icculus@5593
    48
icculus@9012
    49
/* This is the size of a packet when using SDL_QueueAudio(). We allocate
icculus@9012
    50
   these as necessary and pool them, under the assumption that we'll
icculus@9012
    51
   eventually end up with a handful that keep recycling, meeting whatever
icculus@9012
    52
   the app needs. We keep packing data tightly as more arrives to avoid
icculus@9012
    53
   wasting space, and if we get a giant block of data, we'll split them
icculus@9012
    54
   into multiple packets behind the scenes. My expectation is that most
icculus@9012
    55
   apps will have 2-3 of these in the pool. 8k should cover most needs, but
icculus@9012
    56
   if this is crippling for some embedded system, we can #ifdef this.
icculus@9012
    57
   The system preallocates enough packets for 2 callbacks' worth of data. */
icculus@9012
    58
#define SDL_AUDIOBUFFERQUEUE_PACKETLEN (8 * 1024)
icculus@9012
    59
icculus@9012
    60
/* Used by apps that queue audio instead of using the callback. */
icculus@9012
    61
typedef struct SDL_AudioBufferQueue
icculus@9012
    62
{
icculus@9012
    63
    Uint8 data[SDL_AUDIOBUFFERQUEUE_PACKETLEN];  /* packet data. */
icculus@9012
    64
    Uint32 datalen;  /* bytes currently in use in this packet. */
icculus@9012
    65
    Uint32 startpos;  /* bytes currently consumed in this packet. */
icculus@9012
    66
    struct SDL_AudioBufferQueue *next;  /* next item in linked list. */
icculus@9012
    67
} SDL_AudioBufferQueue;
icculus@9012
    68
icculus@2049
    69
typedef struct SDL_AudioDriverImpl
icculus@2049
    70
{
icculus@9394
    71
    void (*DetectDevices) (void);
icculus@9394
    72
    int (*OpenDevice) (_THIS, void *handle, const char *devname, int iscapture);
icculus@2049
    73
    void (*ThreadInit) (_THIS); /* Called by audio thread at start */
icculus@2049
    74
    void (*WaitDevice) (_THIS);
icculus@2049
    75
    void (*PlayDevice) (_THIS);
icculus@9031
    76
    int (*GetPendingBytes) (_THIS);
icculus@2049
    77
    Uint8 *(*GetDeviceBuf) (_THIS);
icculus@2049
    78
    void (*WaitDone) (_THIS);
icculus@2049
    79
    void (*CloseDevice) (_THIS);
icculus@2049
    80
    void (*LockDevice) (_THIS);
icculus@2049
    81
    void (*UnlockDevice) (_THIS);
icculus@9394
    82
    void (*FreeDeviceHandle) (void *handle);  /**< SDL is done with handle from SDL_AddAudioDevice() */
icculus@2049
    83
    void (*Deinitialize) (void);
icculus@2049
    84
icculus@5590
    85
    /* !!! FIXME: add pause(), so we can optimize instead of mixing silence. */
icculus@5590
    86
icculus@2049
    87
    /* Some flags to push duplicate code into the core and reduce #ifdefs. */
icculus@9391
    88
    /* !!! FIXME: these should be SDL_bool */
icculus@5589
    89
    int ProvidesOwnCallbackThread;
icculus@5590
    90
    int SkipMixerLock;  /* !!! FIXME: do we need this anymore? */
icculus@5589
    91
    int HasCaptureSupport;
icculus@5589
    92
    int OnlyHasDefaultOutputDevice;
icculus@5589
    93
    int OnlyHasDefaultInputDevice;
icculus@9394
    94
    int AllowsArbitraryDeviceNames;
icculus@2049
    95
} SDL_AudioDriverImpl;
icculus@2049
    96
icculus@2049
    97
icculus@9394
    98
typedef struct SDL_AudioDeviceItem
icculus@9394
    99
{
icculus@9394
   100
    void *handle;
icculus@9394
   101
    struct SDL_AudioDeviceItem *next;
icculus@9394
   102
    char name[];
icculus@9394
   103
} SDL_AudioDeviceItem;
icculus@9394
   104
icculus@9394
   105
icculus@2049
   106
typedef struct SDL_AudioDriver
slouken@1895
   107
{
slouken@1895
   108
    /* * * */
slouken@1895
   109
    /* The name of this audio driver */
slouken@1895
   110
    const char *name;
slouken@0
   111
slouken@1895
   112
    /* * * */
slouken@1895
   113
    /* The description of this audio driver */
slouken@1895
   114
    const char *desc;
slouken@0
   115
icculus@2049
   116
    SDL_AudioDriverImpl impl;
icculus@5593
   117
icculus@9393
   118
    /* A mutex for device detection */
icculus@9394
   119
    SDL_mutex *detectionLock;
icculus@9394
   120
    SDL_bool captureDevicesRemoved;
icculus@9394
   121
    SDL_bool outputDevicesRemoved;
icculus@5593
   122
    int outputDeviceCount;
icculus@5593
   123
    int inputDeviceCount;
icculus@9394
   124
    SDL_AudioDeviceItem *outputDevices;
icculus@9394
   125
    SDL_AudioDeviceItem *inputDevices;
icculus@2049
   126
} SDL_AudioDriver;
icculus@2049
   127
slouken@0
   128
slouken@2716
   129
/* Streamer */
slouken@2716
   130
typedef struct
slouken@2716
   131
{
slouken@2716
   132
    Uint8 *buffer;
slouken@2716
   133
    int max_len;                /* the maximum length in bytes */
slouken@2716
   134
    int read_pos, write_pos;    /* the position of the write and read heads in bytes */
slouken@2716
   135
} SDL_AudioStreamer;
slouken@2716
   136
slouken@2716
   137
icculus@2049
   138
/* Define the SDL audio driver structure */
icculus@2049
   139
struct SDL_AudioDevice
icculus@2049
   140
{
slouken@1895
   141
    /* * * */
slouken@1895
   142
    /* Data common to all devices */
icculus@9393
   143
    SDL_AudioDeviceID id;
slouken@0
   144
slouken@1895
   145
    /* The current audio specification (shared with audio thread) */
slouken@1895
   146
    SDL_AudioSpec spec;
slouken@0
   147
slouken@1895
   148
    /* An audio conversion block for audio format emulation */
slouken@1895
   149
    SDL_AudioCVT convert;
slouken@0
   150
slouken@2716
   151
    /* The streamer, if sample rate conversion necessitates it */
slouken@2716
   152
    int use_streamer;
slouken@2716
   153
    SDL_AudioStreamer streamer;
slouken@2716
   154
slouken@1895
   155
    /* Current state flags */
icculus@9391
   156
    /* !!! FIXME: should be SDL_bool */
icculus@2049
   157
    int iscapture;
slouken@1895
   158
    int enabled;
slouken@1895
   159
    int paused;
slouken@1895
   160
    int opened;
slouken@0
   161
slouken@1895
   162
    /* Fake audio buffer for when the audio hardware is busy */
slouken@1895
   163
    Uint8 *fake_stream;
slouken@0
   164
icculus@9391
   165
    /* A mutex for locking the mixing buffers */
slouken@1895
   166
    SDL_mutex *mixer_lock;
slouken@0
   167
slouken@1895
   168
    /* A thread to feed the audio device */
slouken@1895
   169
    SDL_Thread *thread;
slouken@3578
   170
    SDL_threadID threadid;
slouken@0
   171
icculus@9012
   172
    /* Queued buffers (if app not using callback). */
icculus@9012
   173
    SDL_AudioBufferQueue *buffer_queue_head; /* device fed from here. */
icculus@9012
   174
    SDL_AudioBufferQueue *buffer_queue_tail; /* queue fills to here. */
icculus@9012
   175
    SDL_AudioBufferQueue *buffer_queue_pool; /* these are unused packets. */
icculus@9012
   176
    Uint32 queued_bytes;  /* number of bytes of audio data in the queue. */
icculus@9012
   177
slouken@1895
   178
    /* * * */
slouken@1895
   179
    /* Data private to this driver */
slouken@1895
   180
    struct SDL_PrivateAudioData *hidden;
slouken@0
   181
};
slouken@0
   182
#undef _THIS
slouken@0
   183
slouken@1895
   184
typedef struct AudioBootStrap
slouken@1895
   185
{
slouken@1895
   186
    const char *name;
slouken@1895
   187
    const char *desc;
slouken@2060
   188
    int (*init) (SDL_AudioDriverImpl * impl);
icculus@5578
   189
    int demand_only;  /* 1==request explicitly, or it won't be available. */
slouken@0
   190
} AudioBootStrap;
slouken@0
   191
icculus@2049
   192
#endif /* _SDL_sysaudio_h */
slouken@0
   193
slouken@1895
   194
/* vi: set ts=4 sw=4 expandtab: */