src/audio/dummy/SDL_dummyaudio.c
author Ryan C. Gordon
Wed, 04 Oct 2006 19:54:23 +0000
branchSDL-ryan-multiple-audio-device
changeset 3796 b19680c84cdf
parent 3792 866c310e2cb5
child 3798 c8b3d3d13ed1
permissions -rw-r--r--
Bunch of 1.3 audio cleanups to remove FIXMEs, get driver specific crap out of
the core and into the drivers where it belongs, and push generic
responsibilities out of the drivers and into the core where they belong.
icculus@1532
     1
/*
icculus@1532
     2
    SDL - Simple DirectMedia Layer
icculus@1532
     3
    Copyright (C) 1997-2006 Sam Lantinga
icculus@1532
     4
icculus@1532
     5
    This library is free software; you can redistribute it and/or
icculus@1532
     6
    modify it under the terms of the GNU Lesser General Public
icculus@1532
     7
    License as published by the Free Software Foundation; either
icculus@1532
     8
    version 2.1 of the License, or (at your option) any later version.
icculus@1532
     9
icculus@1532
    10
    This library is distributed in the hope that it will be useful,
icculus@1532
    11
    but WITHOUT ANY WARRANTY; without even the implied warranty of
icculus@1532
    12
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
icculus@1532
    13
    Lesser General Public License for more details.
icculus@1532
    14
icculus@1532
    15
    You should have received a copy of the GNU Lesser General Public
icculus@1532
    16
    License along with this library; if not, write to the Free Software
icculus@1532
    17
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
icculus@1532
    18
icculus@1532
    19
    Sam Lantinga
icculus@1532
    20
    slouken@libsdl.org
icculus@1532
    21
icculus@1537
    22
    This file written by Ryan C. Gordon (icculus@icculus.org)
icculus@1532
    23
*/
icculus@1532
    24
#include "SDL_config.h"
icculus@1532
    25
slouken@1533
    26
/* Output audio to nowhere... */
icculus@1532
    27
icculus@1532
    28
#include "SDL_rwops.h"
icculus@1532
    29
#include "SDL_timer.h"
icculus@1532
    30
#include "SDL_audio.h"
icculus@1532
    31
#include "../SDL_audiomem.h"
icculus@1532
    32
#include "../SDL_audio_c.h"
icculus@1532
    33
#include "../SDL_audiodev_c.h"
icculus@1532
    34
#include "SDL_dummyaudio.h"
icculus@1532
    35
icculus@1532
    36
/* The tag name used by DUMMY audio */
icculus@1532
    37
#define DUMMYAUD_DRIVER_NAME         "dummy"
icculus@1532
    38
icculus@1532
    39
/* Audio driver functions */
icculus@3792
    40
static int DUMMYAUD_OpenDevice(_THIS, const char *devname, int iscapture);
icculus@3792
    41
static void DUMMYAUD_WaitDevice(_THIS);
icculus@3792
    42
static void DUMMYAUD_PlayDevice(_THIS);
icculus@3792
    43
static Uint8 *DUMMYAUD_GetDeviceBuf(_THIS);
icculus@3792
    44
static void DUMMYAUD_CloseDevice(_THIS);
icculus@1532
    45
icculus@1532
    46
/* Audio driver bootstrap functions */
slouken@1895
    47
static int
slouken@1895
    48
DUMMYAUD_Available(void)
icculus@1532
    49
{
icculus@3784
    50
    /* !!! FIXME: check this at a higher level... */
icculus@3784
    51
    /* only ever use this driver if explicitly requested. */
slouken@1895
    52
    const char *envr = SDL_getenv("SDL_AUDIODRIVER");
slouken@1895
    53
    if (envr && (SDL_strcmp(envr, DUMMYAUD_DRIVER_NAME) == 0)) {
slouken@1895
    54
        return (1);
slouken@1895
    55
    }
slouken@1895
    56
    return (0);
icculus@1532
    57
}
icculus@1532
    58
icculus@3784
    59
static int
icculus@3784
    60
DUMMYAUD_Init(SDL_AudioDriverImpl *impl)
icculus@1532
    61
{
icculus@3784
    62
    /* Set the function pointers */
icculus@3792
    63
    impl->OpenDevice = DUMMYAUD_OpenDevice;
icculus@3792
    64
    impl->WaitDevice = DUMMYAUD_WaitDevice;
icculus@3792
    65
    impl->PlayDevice = DUMMYAUD_PlayDevice;
icculus@3792
    66
    impl->GetDeviceBuf = DUMMYAUD_GetDeviceBuf;
icculus@3792
    67
    impl->CloseDevice = DUMMYAUD_CloseDevice;
icculus@3796
    68
    impl->OnlyHasDefaultOutputDevice = 1;
icculus@1532
    69
icculus@3784
    70
    return 1;
icculus@1532
    71
}
icculus@1532
    72
icculus@1532
    73
AudioBootStrap DUMMYAUD_bootstrap = {
slouken@1895
    74
    DUMMYAUD_DRIVER_NAME, "SDL dummy audio driver",
icculus@3784
    75
    DUMMYAUD_Available, DUMMYAUD_Init
icculus@1532
    76
};
icculus@1532
    77
icculus@1532
    78
/* This function waits until it is possible to write a full sound buffer */
slouken@1895
    79
static void
icculus@3792
    80
DUMMYAUD_WaitDevice(_THIS)
icculus@1532
    81
{
slouken@1895
    82
    /* Don't block on first calls to simulate initial fragment filling. */
slouken@1895
    83
    if (this->hidden->initial_calls)
slouken@1895
    84
        this->hidden->initial_calls--;
slouken@1895
    85
    else
slouken@1895
    86
        SDL_Delay(this->hidden->write_delay);
icculus@1532
    87
}
icculus@1532
    88
slouken@1895
    89
static void
icculus@3792
    90
DUMMYAUD_PlayDevice(_THIS)
icculus@1532
    91
{
slouken@1895
    92
    /* no-op...this is a null driver. */
icculus@1532
    93
}
icculus@1532
    94
slouken@1895
    95
static Uint8 *
icculus@3792
    96
DUMMYAUD_GetDeviceBuf(_THIS)
icculus@1532
    97
{
slouken@1895
    98
    return (this->hidden->mixbuf);
icculus@1532
    99
}
icculus@1532
   100
slouken@1895
   101
static void
icculus@3792
   102
DUMMYAUD_CloseDevice(_THIS)
icculus@1532
   103
{
slouken@1895
   104
    if (this->hidden->mixbuf != NULL) {
slouken@1895
   105
        SDL_FreeAudioMem(this->hidden->mixbuf);
slouken@1895
   106
        this->hidden->mixbuf = NULL;
slouken@1895
   107
    }
icculus@3784
   108
    SDL_free(this->hidden);
icculus@3784
   109
    this->hidden = NULL;
icculus@1532
   110
}
icculus@1532
   111
slouken@1895
   112
static int
icculus@3792
   113
DUMMYAUD_OpenDevice(_THIS, const char *devname, int iscapture)
icculus@1532
   114
{
slouken@1895
   115
    float bytes_per_sec = 0.0f;
icculus@1537
   116
icculus@3784
   117
    /* Initialize all variables that we clean on shutdown */
icculus@3784
   118
    this->hidden = (struct SDL_PrivateAudioData *)
icculus@3784
   119
                    SDL_malloc((sizeof *this->hidden));
icculus@3784
   120
    if (this->hidden == NULL) {
icculus@3784
   121
        SDL_OutOfMemory();
icculus@3784
   122
        return 0;
icculus@3784
   123
    }
icculus@3784
   124
    SDL_memset(this->hidden, 0, (sizeof *this->hidden));
icculus@3784
   125
slouken@1895
   126
    /* Allocate mixing buffer */
icculus@3784
   127
    this->hidden->mixlen = this->spec.size;
slouken@1895
   128
    this->hidden->mixbuf = (Uint8 *) SDL_AllocAudioMem(this->hidden->mixlen);
slouken@1895
   129
    if (this->hidden->mixbuf == NULL) {
icculus@3792
   130
        DUMMYAUD_CloseDevice(this);
icculus@3784
   131
        return 0;
slouken@1895
   132
    }
icculus@3784
   133
    SDL_memset(this->hidden->mixbuf, this->spec.silence, this->spec.size);
icculus@1532
   134
icculus@3784
   135
    bytes_per_sec = (float) (SDL_AUDIO_BITSIZE(this->spec.format) / 8) *
icculus@3784
   136
                             this->spec.channels * this->spec.freq;
icculus@1537
   137
slouken@1895
   138
    /*
slouken@1895
   139
     * We try to make this request more audio at the correct rate for
slouken@1895
   140
     *  a given audio spec, so timing stays fairly faithful.
slouken@1895
   141
     * Also, we have it not block at all for the first two calls, so
slouken@1895
   142
     *  it seems like we're filling two audio fragments right out of the
slouken@1895
   143
     *  gate, like other SDL drivers tend to do.
slouken@1895
   144
     */
slouken@1895
   145
    this->hidden->initial_calls = 2;
slouken@1895
   146
    this->hidden->write_delay =
icculus@3784
   147
        (Uint32) ((((float) this->spec.size) / bytes_per_sec) * 1000.0f);
icculus@1537
   148
slouken@1895
   149
    /* We're ready to rock and roll. :-) */
icculus@3784
   150
    return 1;
icculus@1532
   151
}
icculus@1532
   152
slouken@1895
   153
/* vi: set ts=4 sw=4 expandtab: */