src/audio/disk/SDL_diskaudio.c
author Sam Lantinga
Sat, 19 Sep 2009 13:29:40 +0000
changeset 3280 00cace2d9080
parent 3253 5d7ef5970073
child 3697 f7b03b6838cb
permissions -rw-r--r--
Merged a cleaned up version of Jiang's code changes from Google Summer of Code 2009
slouken@68
     1
/*
slouken@68
     2
    SDL - Simple DirectMedia Layer
slouken@2859
     3
    Copyright (C) 1997-2009 Sam Lantinga
slouken@68
     4
slouken@68
     5
    This library is free software; you can redistribute it and/or
slouken@1312
     6
    modify it under the terms of the GNU Lesser General Public
slouken@68
     7
    License as published by the Free Software Foundation; either
slouken@1312
     8
    version 2.1 of the License, or (at your option) any later version.
slouken@68
     9
slouken@68
    10
    This library is distributed in the hope that it will be useful,
slouken@68
    11
    but WITHOUT ANY WARRANTY; without even the implied warranty of
slouken@68
    12
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
slouken@1312
    13
    Lesser General Public License for more details.
slouken@68
    14
slouken@1312
    15
    You should have received a copy of the GNU Lesser General Public
slouken@1312
    16
    License along with this library; if not, write to the Free Software
slouken@1312
    17
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
slouken@68
    18
slouken@68
    19
    Sam Lantinga
slouken@252
    20
    slouken@libsdl.org
slouken@68
    21
icculus@1594
    22
    This file written by Ryan C. Gordon (icculus@icculus.org)
slouken@68
    23
*/
slouken@1402
    24
#include "SDL_config.h"
slouken@68
    25
slouken@68
    26
/* Output raw audio data to a file. */
slouken@68
    27
slouken@1465
    28
#if HAVE_STDIO_H
slouken@68
    29
#include <stdio.h>
slouken@1465
    30
#endif
slouken@68
    31
slouken@1465
    32
#include "SDL_rwops.h"
slouken@1358
    33
#include "SDL_timer.h"
slouken@68
    34
#include "SDL_audio.h"
slouken@1361
    35
#include "../SDL_audiomem.h"
slouken@1361
    36
#include "../SDL_audio_c.h"
slouken@68
    37
#include "SDL_diskaudio.h"
slouken@68
    38
slouken@68
    39
/* The tag name used by DISK audio */
slouken@68
    40
#define DISKAUD_DRIVER_NAME         "disk"
slouken@68
    41
slouken@68
    42
/* environment variables and defaults. */
slouken@68
    43
#define DISKENVR_OUTFILE         "SDL_DISKAUDIOFILE"
slouken@68
    44
#define DISKDEFAULT_OUTFILE      "sdlaudio.raw"
slouken@68
    45
#define DISKENVR_WRITEDELAY      "SDL_DISKAUDIODELAY"
slouken@68
    46
#define DISKDEFAULT_WRITEDELAY   150
slouken@68
    47
slouken@1895
    48
static const char *
icculus@2049
    49
DISKAUD_GetOutputFilename(const char *devname)
slouken@68
    50
{
icculus@2049
    51
    if (devname == NULL) {
icculus@2049
    52
        devname = SDL_getenv(DISKENVR_OUTFILE);
icculus@2049
    53
        if (devname == NULL) {
icculus@2049
    54
            devname = DISKDEFAULT_OUTFILE;
slouken@1895
    55
        }
slouken@1895
    56
    }
icculus@2049
    57
    return devname;
slouken@68
    58
}
slouken@68
    59
slouken@68
    60
/* This function waits until it is possible to write a full sound buffer */
slouken@1895
    61
static void
icculus@2049
    62
DISKAUD_WaitDevice(_THIS)
slouken@68
    63
{
slouken@1895
    64
    SDL_Delay(this->hidden->write_delay);
slouken@68
    65
}
slouken@68
    66
slouken@1895
    67
static void
icculus@2049
    68
DISKAUD_PlayDevice(_THIS)
slouken@68
    69
{
slouken@3253
    70
    size_t written;
slouken@68
    71
slouken@1895
    72
    /* Write the audio data */
slouken@1895
    73
    written = SDL_RWwrite(this->hidden->output,
slouken@1895
    74
                          this->hidden->mixbuf, 1, this->hidden->mixlen);
slouken@68
    75
slouken@1895
    76
    /* If we couldn't write, assume fatal error for now */
slouken@3253
    77
    if (written != this->hidden->mixlen) {
slouken@1895
    78
        this->enabled = 0;
slouken@1895
    79
    }
slouken@68
    80
#ifdef DEBUG_AUDIO
slouken@1895
    81
    fprintf(stderr, "Wrote %d bytes of audio data\n", written);
slouken@68
    82
#endif
slouken@68
    83
}
slouken@68
    84
slouken@1895
    85
static Uint8 *
icculus@2049
    86
DISKAUD_GetDeviceBuf(_THIS)
slouken@68
    87
{
slouken@1895
    88
    return (this->hidden->mixbuf);
slouken@68
    89
}
slouken@68
    90
slouken@1895
    91
static void
icculus@2049
    92
DISKAUD_CloseDevice(_THIS)
slouken@68
    93
{
icculus@2049
    94
    if (this->hidden != NULL) {
icculus@2049
    95
        if (this->hidden->mixbuf != NULL) {
icculus@2049
    96
            SDL_FreeAudioMem(this->hidden->mixbuf);
icculus@2049
    97
            this->hidden->mixbuf = NULL;
icculus@2049
    98
        }
icculus@2049
    99
        if (this->hidden->output != NULL) {
icculus@2049
   100
            SDL_RWclose(this->hidden->output);
icculus@2049
   101
            this->hidden->output = NULL;
icculus@2049
   102
        }
icculus@2049
   103
        SDL_free(this->hidden);
icculus@2049
   104
        this->hidden = NULL;
slouken@1895
   105
    }
slouken@68
   106
}
slouken@68
   107
slouken@1895
   108
static int
icculus@2049
   109
DISKAUD_OpenDevice(_THIS, const char *devname, int iscapture)
slouken@68
   110
{
icculus@2049
   111
    const char *envr = SDL_getenv(DISKENVR_WRITEDELAY);
icculus@2049
   112
    const char *fname = DISKAUD_GetOutputFilename(devname);
icculus@2049
   113
icculus@2049
   114
    this->hidden = (struct SDL_PrivateAudioData *)
slouken@2060
   115
        SDL_malloc(sizeof(*this->hidden));
icculus@2049
   116
    if (this->hidden == NULL) {
icculus@2049
   117
        SDL_OutOfMemory();
icculus@2049
   118
        return 0;
icculus@2049
   119
    }
slouken@2060
   120
    SDL_memset(this->hidden, 0, sizeof(*this->hidden));
slouken@68
   121
slouken@1895
   122
    /* Open the audio device */
slouken@1895
   123
    this->hidden->output = SDL_RWFromFile(fname, "wb");
slouken@1895
   124
    if (this->hidden->output == NULL) {
icculus@2049
   125
        DISKAUD_CloseDevice(this);
icculus@2049
   126
        return 0;
slouken@1895
   127
    }
slouken@68
   128
slouken@1895
   129
    /* Allocate mixing buffer */
slouken@1895
   130
    this->hidden->mixbuf = (Uint8 *) SDL_AllocAudioMem(this->hidden->mixlen);
slouken@1895
   131
    if (this->hidden->mixbuf == NULL) {
icculus@2049
   132
        DISKAUD_CloseDevice(this);
icculus@2049
   133
        return 0;
slouken@1895
   134
    }
icculus@2049
   135
    SDL_memset(this->hidden->mixbuf, this->spec.silence, this->spec.size);
icculus@2049
   136
icculus@2049
   137
    this->hidden->mixlen = this->spec.size;
icculus@2049
   138
    this->hidden->write_delay =
icculus@2049
   139
        (envr) ? SDL_atoi(envr) : DISKDEFAULT_WRITEDELAY;
icculus@2049
   140
icculus@2049
   141
#if HAVE_STDIO_H
icculus@2049
   142
    fprintf(stderr,
icculus@2049
   143
            "WARNING: You are using the SDL disk writer audio driver!\n"
icculus@2049
   144
            " Writing to file [%s].\n", fname);
icculus@2049
   145
#endif
slouken@68
   146
slouken@1895
   147
    /* We're ready to rock and roll. :-) */
icculus@2049
   148
    return 1;
slouken@68
   149
}
slouken@68
   150
icculus@2049
   151
static int
slouken@2060
   152
DISKAUD_Init(SDL_AudioDriverImpl * impl)
icculus@2049
   153
{
icculus@2049
   154
    /* Set the function pointers */
icculus@2049
   155
    impl->OpenDevice = DISKAUD_OpenDevice;
icculus@2049
   156
    impl->WaitDevice = DISKAUD_WaitDevice;
icculus@2049
   157
    impl->PlayDevice = DISKAUD_PlayDevice;
icculus@2049
   158
    impl->GetDeviceBuf = DISKAUD_GetDeviceBuf;
icculus@2049
   159
    impl->CloseDevice = DISKAUD_CloseDevice;
icculus@2049
   160
icculus@2049
   161
    return 1;
icculus@2049
   162
}
icculus@2049
   163
icculus@2049
   164
AudioBootStrap DISKAUD_bootstrap = {
icculus@2049
   165
    DISKAUD_DRIVER_NAME, "direct-to-disk audio", DISKAUD_Init, 1
icculus@2049
   166
};
icculus@2049
   167
slouken@1895
   168
/* vi: set ts=4 sw=4 expandtab: */