Mercurial > sdl-ios-xcode
comparison src/audio/disk/SDL_diskaudio.c @ 68:ac6645260d31
Added an audio driver that writes to disk (thanks Ryan!)
author | Sam Lantinga <slouken@lokigames.com> |
---|---|
date | Sat, 16 Jun 2001 01:51:42 +0000 |
parents | |
children | 13e4c612098d |
comparison
equal
deleted
inserted
replaced
67:3647c809813d | 68:ac6645260d31 |
---|---|
1 /* | |
2 SDL - Simple DirectMedia Layer | |
3 Copyright (C) 1997, 1998, 1999, 2000, 2001 Sam Lantinga | |
4 | |
5 This library is free software; you can redistribute it and/or | |
6 modify it under the terms of the GNU Library General Public | |
7 License as published by the Free Software Foundation; either | |
8 version 2 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 Library General Public License for more details. | |
14 | |
15 You should have received a copy of the GNU Library General Public | |
16 License along with this library; if not, write to the Free | |
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
18 | |
19 Sam Lantinga | |
20 slouken@devolution.com | |
21 | |
22 This file hacked^H^H^H^H^H^Hwritten by Ryan C. Gordon | |
23 (icculus@linuxgames.com) | |
24 */ | |
25 | |
26 #ifdef SAVE_RCSID | |
27 static char rcsid = | |
28 "@(#) $Id$"; | |
29 #endif | |
30 | |
31 /* Output raw audio data to a file. */ | |
32 | |
33 #include <stdlib.h> | |
34 #include <stdio.h> | |
35 #include <string.h> | |
36 #include <errno.h> | |
37 #include <unistd.h> | |
38 #include <sys/stat.h> | |
39 #include <sys/types.h> | |
40 #include <sys/stat.h> | |
41 #include <fcntl.h> | |
42 | |
43 | |
44 #include "SDL_audio.h" | |
45 #include "SDL_error.h" | |
46 #include "SDL_audiomem.h" | |
47 #include "SDL_audio_c.h" | |
48 #include "SDL_timer.h" | |
49 #include "SDL_audiodev_c.h" | |
50 #include "SDL_diskaudio.h" | |
51 | |
52 /* The tag name used by DISK audio */ | |
53 #define DISKAUD_DRIVER_NAME "disk" | |
54 | |
55 /* environment variables and defaults. */ | |
56 #define DISKENVR_OUTFILE "SDL_DISKAUDIOFILE" | |
57 #define DISKDEFAULT_OUTFILE "sdlaudio.raw" | |
58 #define DISKENVR_WRITEDELAY "SDL_DISKAUDIODELAY" | |
59 #define DISKDEFAULT_WRITEDELAY 150 | |
60 | |
61 /* Audio driver functions */ | |
62 static int DISKAUD_OpenAudio(_THIS, SDL_AudioSpec *spec); | |
63 static void DISKAUD_WaitAudio(_THIS); | |
64 static void DISKAUD_PlayAudio(_THIS); | |
65 static Uint8 *DISKAUD_GetAudioBuf(_THIS); | |
66 static void DISKAUD_CloseAudio(_THIS); | |
67 | |
68 static const char *DISKAUD_GetOutputFilename(void) | |
69 { | |
70 const char *envr = getenv(DISKENVR_OUTFILE); | |
71 return((envr != NULL) ? envr : DISKDEFAULT_OUTFILE); | |
72 } | |
73 | |
74 /* Audio driver bootstrap functions */ | |
75 static int DISKAUD_Available(void) | |
76 { | |
77 #if 0 | |
78 int fd; | |
79 int available; | |
80 int exists = 0; | |
81 struct stat statbuf; | |
82 const char *fname = DISKAUD_GetOutputFilename(); | |
83 | |
84 available = 0; | |
85 | |
86 if (stat(fname, &statbuf) == 0) | |
87 exists = 1; | |
88 | |
89 fd = open(fname, O_WRONLY | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR); | |
90 if ( fd != -1 ) { | |
91 available = 1; | |
92 close(fd); | |
93 if (!exists) { | |
94 unlink(fname); | |
95 } | |
96 } | |
97 return(available); | |
98 #else | |
99 return(1); | |
100 #endif | |
101 } | |
102 | |
103 static void DISKAUD_DeleteDevice(SDL_AudioDevice *device) | |
104 { | |
105 free(device->hidden); | |
106 free(device); | |
107 } | |
108 | |
109 static SDL_AudioDevice *DISKAUD_CreateDevice(int devindex) | |
110 { | |
111 SDL_AudioDevice *this; | |
112 const char *envr; | |
113 | |
114 /* Initialize all variables that we clean on shutdown */ | |
115 this = (SDL_AudioDevice *)malloc(sizeof(SDL_AudioDevice)); | |
116 if ( this ) { | |
117 memset(this, 0, (sizeof *this)); | |
118 this->hidden = (struct SDL_PrivateAudioData *) | |
119 malloc((sizeof *this->hidden)); | |
120 } | |
121 if ( (this == NULL) || (this->hidden == NULL) ) { | |
122 SDL_OutOfMemory(); | |
123 if ( this ) { | |
124 free(this); | |
125 } | |
126 return(0); | |
127 } | |
128 memset(this->hidden, 0, (sizeof *this->hidden)); | |
129 | |
130 envr = getenv(DISKENVR_WRITEDELAY); | |
131 this->hidden->write_delay = (envr) ? atoi(envr) : DISKDEFAULT_WRITEDELAY; | |
132 | |
133 /* Set the function pointers */ | |
134 this->OpenAudio = DISKAUD_OpenAudio; | |
135 this->WaitAudio = DISKAUD_WaitAudio; | |
136 this->PlayAudio = DISKAUD_PlayAudio; | |
137 this->GetAudioBuf = DISKAUD_GetAudioBuf; | |
138 this->CloseAudio = DISKAUD_CloseAudio; | |
139 | |
140 this->free = DISKAUD_DeleteDevice; | |
141 | |
142 return this; | |
143 } | |
144 | |
145 AudioBootStrap DISKAUD_bootstrap = { | |
146 DISKAUD_DRIVER_NAME, "direct-to-disk audio", | |
147 DISKAUD_Available, DISKAUD_CreateDevice | |
148 }; | |
149 | |
150 /* This function waits until it is possible to write a full sound buffer */ | |
151 static void DISKAUD_WaitAudio(_THIS) | |
152 { | |
153 SDL_Delay(this->hidden->write_delay); | |
154 } | |
155 | |
156 static void DISKAUD_PlayAudio(_THIS) | |
157 { | |
158 int written; | |
159 | |
160 /* Write the audio data, checking for EAGAIN on broken audio drivers */ | |
161 do { | |
162 written = write(this->hidden->audio_fd, | |
163 this->hidden->mixbuf, | |
164 this->hidden->mixlen); | |
165 if ( (written < 0) && ((errno == 0) || (errno == EAGAIN)) ) { | |
166 SDL_Delay(1); /* Let a little CPU time go by */ | |
167 } | |
168 } while ( (written < 0) && | |
169 ((errno == 0) || (errno == EAGAIN) || (errno == EINTR)) ); | |
170 | |
171 /* If we couldn't write, assume fatal error for now */ | |
172 if ( written < 0 ) { | |
173 this->enabled = 0; | |
174 } | |
175 #ifdef DEBUG_AUDIO | |
176 fprintf(stderr, "Wrote %d bytes of audio data\n", written); | |
177 #endif | |
178 } | |
179 | |
180 static Uint8 *DISKAUD_GetAudioBuf(_THIS) | |
181 { | |
182 return(this->hidden->mixbuf); | |
183 } | |
184 | |
185 static void DISKAUD_CloseAudio(_THIS) | |
186 { | |
187 if ( this->hidden->mixbuf != NULL ) { | |
188 SDL_FreeAudioMem(this->hidden->mixbuf); | |
189 this->hidden->mixbuf = NULL; | |
190 } | |
191 if ( this->hidden->audio_fd >= 0 ) { | |
192 close(this->hidden->audio_fd); | |
193 this->hidden->audio_fd = -1; | |
194 } | |
195 } | |
196 | |
197 static int DISKAUD_OpenAudio(_THIS, SDL_AudioSpec *spec) | |
198 { | |
199 const char *fname = DISKAUD_GetOutputFilename(); | |
200 | |
201 /* Open the audio device */ | |
202 this->hidden->audio_fd = open(fname, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR); | |
203 if ( this->hidden->audio_fd < 0 ) { | |
204 SDL_SetError("Couldn't open %s: %s", fname, strerror(errno)); | |
205 return(-1); | |
206 } | |
207 | |
208 fprintf(stderr, "WARNING: You are using the SDL disk writer" | |
209 " audio driver!\n Writing to file [%s].\n", fname); | |
210 | |
211 /* Allocate mixing buffer */ | |
212 this->hidden->mixlen = spec->size; | |
213 this->hidden->mixbuf = (Uint8 *) SDL_AllocAudioMem(this->hidden->mixlen); | |
214 if ( this->hidden->mixbuf == NULL ) { | |
215 return(-1); | |
216 } | |
217 memset(this->hidden->mixbuf, spec->silence, spec->size); | |
218 | |
219 /* We're ready to rock and roll. :-) */ | |
220 return(0); | |
221 } | |
222 |