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