initial import
[dosrtxon] / libs / mikmod / drivers / drv_sdl.c
1 /*  MikMod sound library
2     (c) 1998-2005 Miodrag Vallat and others - see file AUTHORS for
3     complete list.
4
5     This library is free software; you can redistribute it and/or modify
6     it under the terms of the GNU Library General Public License as
7     published by the Free Software Foundation; either version 2 of
8     the License, or (at your option) any later version.
9
10     This program 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
13     GNU 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 Software
17     Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
18     02111-1307, USA.
19     */
20
21 /*==============================================================================
22
23   libmikmod driver for audio output on SDL-supported platforms.
24   Initially written by Paul Spark <sparkynz74@gmail.com>
25   Rewrite/major fixes by O. Sezer <sezero@users.sourceforge.net>
26
27   ==============================================================================*/
28
29 #ifdef HAVE_CONFIG_H
30 #include "config.h"
31 #endif
32
33 #include "mikmod_internals.h"
34
35 #ifdef DRV_SDL
36
37 #include <string.h>
38 #if defined(SDL_FRAMEWORK) || defined(NO_SDL_CONFIG)
39 #include <SDL/SDL.h>
40 #else
41 #include "SDL.h"
42 #endif
43
44 #define NUMSAMPLES 256 /* a fair default for md_mixfreq <= 11025 Hz */
45 static SDL_AudioSpec spec;
46 static int enabled = 0;
47
48 static void SDLSoundCallback(void *userdata, Uint8 *stream, int len)
49 {
50     if (!enabled) return;
51     if (enabled < 0) {
52         if (++enabled == 0)
53             enabled = 1;
54         return;
55     }
56
57     MUTEX_LOCK(vars);
58     if (Player_Paused_internal()) {
59         VC_SilenceBytes((SBYTE *) stream, (ULONG)len);
60     }
61     else
62     {
63         int got = (int) VC_WriteBytes((SBYTE *) stream, (ULONG)len);
64         if (got < len) {        /* fill the rest with silence, then */
65             VC_SilenceBytes((SBYTE *) &stream[got], (ULONG)(len-got));
66         }
67     }
68     MUTEX_UNLOCK(vars);
69 }
70
71 static BOOL SetupSDLAudio(void)
72 {
73     SDL_AudioSpec wanted;
74
75     wanted.freq     = md_mixfreq;
76     wanted.format   =
77 #if (SDL_MAJOR_VERSION >= 2)
78                       (md_mode & DMODE_FLOAT) ? AUDIO_F32SYS :
79 #endif
80                       (md_mode & DMODE_16BITS)? AUDIO_S16SYS : AUDIO_U8;
81     wanted.channels = (md_mode & DMODE_STEREO)? 2 : 1;
82     wanted.samples  = (md_mixfreq <= 11025)? (NUMSAMPLES    ) :
83                       (md_mixfreq <= 22050)? (NUMSAMPLES * 2) :
84                       (md_mixfreq <= 44100)? (NUMSAMPLES * 4) :
85                                              (NUMSAMPLES * 8);
86     wanted.userdata = NULL;
87     wanted.callback = SDLSoundCallback;
88
89     if (SDL_OpenAudio(&wanted, &spec) < 0) {
90         _mm_errno=MMERR_OPENING_AUDIO;
91         return 0;
92     }
93
94     return 1;
95 }
96
97 static BOOL SDLDrv_IsPresent(void)
98 {
99     if ((SDL_WasInit(SDL_INIT_AUDIO)) == 0) {
100         if (SDL_Init(SDL_INIT_AUDIO) < 0)
101             return 0;
102         SDL_QuitSubSystem(SDL_INIT_AUDIO);
103     }
104     return 1;
105 }
106
107 static int SDLDrv_Init(void)
108 {
109 #if (SDL_MAJOR_VERSION < 2)
110     if (md_mode & DMODE_FLOAT) {
111         _mm_errno=MMERR_NO_FLOAT32;
112         return 1;
113     }
114 #endif
115     if (SDL_Init(SDL_INIT_AUDIO) < 0) {
116         _mm_errno=MMERR_OPENING_AUDIO;
117         return 1;
118     }
119     if (!SetupSDLAudio()) {
120         return 1;
121     }
122
123     md_mode |= DMODE_SOFT_MUSIC;
124     if (VC_Init())
125         return 1;
126
127     enabled = -2; /* delay the callback 2 frames */
128     return 0;
129 }
130
131 static void SDLDrv_Exit(void)
132 {
133     SDL_LockAudio();
134     enabled = 0;
135     SDL_UnlockAudio();
136     SDL_CloseAudio();
137     VC_Exit();
138 }
139
140 static int SDLDrv_Reset(void)
141 {
142     SDLDrv_Exit();
143     return SDLDrv_Init();
144 }
145
146 static void SDLDrv_Update( void )
147 {
148 /* do nothing */
149 }
150
151 static void SDLDrv_PlayStop(void)
152 {
153     SDL_PauseAudio(1);
154     VC_PlayStop();
155 }
156
157 static int SDLDrv_PlayStart(void)
158 {
159     if (VC_PlayStart())
160         return 1;
161     SDL_PauseAudio(0);
162     return 0;
163 }
164
165 MIKMODAPI struct MDRIVER drv_sdl =
166 {
167     NULL,
168     "SDL",
169     "SDL Driver v1.3",
170     0,255,
171     "sdl",
172     NULL,
173     NULL,
174     SDLDrv_IsPresent,
175     VC_SampleLoad,
176     VC_SampleUnload,
177     VC_SampleSpace,
178     VC_SampleLength,
179     SDLDrv_Init,
180     SDLDrv_Exit,
181     SDLDrv_Reset,
182     VC_SetNumVoices,
183     SDLDrv_PlayStart,
184     SDLDrv_PlayStop,
185     SDLDrv_Update,
186     NULL,
187     VC_VoiceSetVolume,
188     VC_VoiceGetVolume,
189     VC_VoiceSetFrequency,
190     VC_VoiceGetFrequency,
191     VC_VoiceSetPanning,
192     VC_VoiceGetPanning,
193     VC_VoicePlay,
194     VC_VoiceStop,
195     VC_VoiceStopped,
196     VC_VoiceGetPosition,
197     VC_VoiceRealVolume
198 };
199
200 #else
201
202 MISSING(drv_sdl);
203
204 #endif
205