Freeciv-3.4
Loading...
Searching...
No Matches
audio_sdl.c
Go to the documentation of this file.
1/***********************************************************************
2 Freeciv - Copyright (C) 1996 - A Kjeldberg, L Gregersen, P Unold
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2, or (at your option)
6 any later version.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12***********************************************************************/
13
14#ifdef HAVE_CONFIG_H
15#include <fc_config.h>
16#endif
17
18#include <string.h>
19
20#ifdef AUDIO_SDL3
21#include <SDL3/SDL.h>
22#include <SDL3_mixer/SDL_mixer.h>
23#else
24#ifdef SDL2_PLAIN_INCLUDE
25#include <SDL.h>
26#include <SDL_mixer.h>
27#else /* SDL2_PLAIN_INCLUDE */
28#include <SDL2/SDL.h>
29#include <SDL2/SDL_mixer.h>
30#endif /* SDL2_PLAIN_INCLUDE */
31#endif /* AUDIO_SDL3 */
32
33/* utility */
34#include "log.h"
35#include "support.h"
36
37/* client */
38#include "audio.h"
39
40#include "audio_sdl.h"
41
42struct sample {
43#ifdef AUDIO_SDL3
45#else /* AUDIO_SDL3 */
47#endif /* AUDIO_SDL3 */
48 const char *tag;
49};
50
51/* Sounds don't sound good on Windows unless the buffer size is 4k,
52 * but this seems to cause strange behavior on other systems,
53 * such as a delay before playing the sound. */
54#ifdef FREECIV_MSWINDOWS
55const size_t buf_size = 4096;
56#else
57const size_t buf_size = 1024;
58#endif
59
60#ifdef AUDIO_SDL3
61#define MIX_CHANNELS 8
62static MIX_Audio *mus = NULL;
63static MIX_Mixer *mixer = NULL;
66#else /* AUDIO_SDL3 */
67static Mix_Music *mus = NULL;
68#endif /* AUDIO_SDL3 */
69
71static double sdl_audio_volume;
72
73/**********************************************************************/
76static void sdl_audio_set_volume(double volume)
77{
78#ifdef AUDIO_SDL3
79 int i;
80
81 for (i = 0; i < MIX_CHANNELS; i++) {
83 }
84#else /* AUDIO_SDL3 */
87#endif /* AUDIO_SDL3 */
88
90}
91
92/**********************************************************************/
95static double sdl_audio_get_volume(void)
96{
97 return sdl_audio_volume;
98}
99
100#ifdef AUDIO_SDL3
101/**********************************************************************/
104static void audio_callback_wrapper(void *cb, MIX_Track *track)
105{
107}
108#endif /* AUDIO_SDL3 */
109
110/**********************************************************************/
113static bool sdl_audio_play(const char *const tag, const char *const fullpath,
114 bool repeat, bool music, audio_finished_callback cb)
115{
116 int j;
117#ifdef AUDIO_SDL3
119 int channel;
120 static int channel_turn = 1; /* Channel 0 is music */
121#else /* AUDIO_SDL3 */
122 int i;
124#endif /* AUDIO_SDL3 */
125
126 if (!fullpath) {
127 return FALSE;
128 }
129
130#ifdef AUDIO_SDL3
131 if (music) {
132 channel = 0;
133 } else {
135 if (channel_turn >= MIX_CHANNELS) {
136 channel_turn = 1;
137 }
138 }
139#endif /* AUDIO_SDL3 */
140
141 if (repeat) {
142 /* Unload previous */
143#ifdef AUDIO_SDL3
146#else /* AUDIO_SDL3 */
149#endif /* AUDIO_SDL3 */
150
151 /* Load music file */
152#ifdef AUDIO_SDL3
154#else /* AUDIO_SDL3 */
156#endif /* AUDIO_SDL3 */
157 if (mus == NULL) {
158 log_error("Can't open file \"%s\": %s",
160 }
161
162 if (cb == NULL) {
163#ifdef AUDIO_SDL3
166#else /* AUDIO_SDL3 */
167 Mix_PlayMusic(mus, -1); /* -1 means loop forever */
168#endif /* AUDIO_SDL3 */
169 } else {
170#ifdef AUDIO_SDL3
175#else /* AUDIO_SDL3 */
176 Mix_PlayMusic(mus, 0);
178#endif /* AUDIO_SDL3 */
179 }
180 log_verbose("Playing file \"%s\" on music channel", fullpath);
181 /* In case we did a sdl_audio_stop() recently; add volume controls later */
182#ifdef AUDIO_SDL3
184#else /* AUDIO_SDL3 */
186#endif /* AUDIO_SDL3 */
187
188 } else {
189
190 /* See if we can cache on this one */
191 for (j = 0; j < MIX_CHANNELS; j++) {
192 if (samples[j].tag && (strcmp(samples[j].tag, tag) == 0)) {
193 log_debug("Playing file \"%s\" from cache (slot %d)", fullpath, j);
194
195#ifdef AUDIO_SDL3
198#else /* AUDIO_SDL3 */
199 Mix_PlayChannel(-1, samples[j].wave, 0);
200#endif /* AUDIO_SDL3 */
201
202 return TRUE;
203 }
204 } /* Guess not */
205
206 /* Load wave */
207#ifdef AUDIO_SDL3
209#else /* AUDIO_SDL3 */
211#endif /* AUDIO_SDL3 */
212 if (wave == NULL) {
213 log_error("Can't open file \"%s\"", fullpath);
214 }
215
216 /* Play sound sample on first available channel, returns -1 if no
217 channel found */
218#ifdef AUDIO_SDL3
221
222 log_verbose("Playing file \"%s\" on channel %d", fullpath, channel);
223 /* Free previous sample on this channel. it will by definition no
224 longer be playing by the time we get here */
225 if (samples[channel].wave) {
228 }
229
230 /* Remember for caching */
233#else /* AUDIO_SDL3 */
234 i = Mix_PlayChannel(-1, wave, 0);
235
236 if (i < 0) {
237 log_verbose("No available sound channel to play %s.", tag);
239 return FALSE;
240 }
241 log_verbose("Playing file \"%s\" on channel %d", fullpath, i);
242 /* Free previous sample on this channel. it will by definition no
243 longer be playing by the time we get here */
244 if (samples[i].wave) {
246 samples[i].wave = NULL;
247 }
248
249 /* Remember for caching */
250 samples[i].wave = wave;
251 samples[i].tag = tag;
252#endif /* AUDIO_SDL3 */
253
254 }
255 return TRUE;
256}
257
258/**********************************************************************/
261static void sdl_audio_pause(void)
262{
263#ifdef AUDIO_SDL3
264 int i;
265
266 for (i = 0; i < MIX_CHANNELS; i++) {
268 }
269#else /* AUDIO_SDL3 */
271#endif /* AUDIO_SDL3 */
272}
273
274/**********************************************************************/
277static void sdl_audio_resume(void)
278{
279#ifdef AUDIO_SDL3
280 int i;
281
282 for (i = 0; i < MIX_CHANNELS; i++) {
284 }
285#else /* AUDIO_SDL3 */
287#endif /* AUDIO_SDL3 */
288}
289
290/**********************************************************************/
293static void sdl_audio_stop(void)
294{
295 /* Fade out over 2 sec */
296#ifdef AUDIO_SDL3
297 int i;
298
299 for (i = 0; i < MIX_CHANNELS; i++) {
302 }
303#else /* AUDIO_SDL3 */
304 Mix_FadeOutMusic(2000);
305#endif /* AUDIO_SDL3 */
306}
307
308/**********************************************************************/
313static void sdl_audio_wait(void)
314{
315#ifdef AUDIO_SDL3
316 bool wait = TRUE;
317 while (wait) {
318 int i;
319
320 wait = FALSE;
321 for (i = 0; i < MIX_CHANNELS && !wait; i++) {
322 if (MIX_TrackPlaying(tracks[i])) {
323 wait = TRUE;
324 }
325 }
326
327 if (wait) {
328 SDL_Delay(100);
329 }
330 }
331#else /* AUDIO_SDL3 */
332 while (Mix_Playing(-1) != 0) {
333 SDL_Delay(100);
334 }
335#endif /* AUDIO_SDL3 */
336}
337
338/**********************************************************************/
344static void quit_sdl_audio(void)
345{
346#ifdef AUDIO_SDL3
347 MIX_Quit();
348#else /* AUDIO_SDL3 */
351 } else {
352 SDL_Quit();
353 }
354#endif /* AUDIO_SDL3 */
355}
356
357/**********************************************************************/
363static bool init_sdl_audio(void)
364{
365#ifdef AUDIO_SDL3
366 return MIX_Init();
367#else /* AUDIO_SDL3 */
369
372 } else {
374 }
375#endif /* AUDIO_SDL3 */
376}
377
378/**********************************************************************/
382{
383 int i;
384
385 self->initialized = FALSE;
386
389
390 /* Remove all buffers */
391 for (i = 0; i < MIX_CHANNELS; i++) {
392 if (samples[i].wave) {
393#ifdef AUDIO_SDL3
396#else /* AUDIO_SDL3 */
398#endif /* AUDIO_SDL3 */
399 }
400 }
401
402#ifdef AUDIO_SDL3
405#else /* AUDIO_SDL3 */
408
410#endif /* AUDIO_SDL3 */
411
413
414#ifdef AUDIO_SDL3
416#endif /* AUDIO_SDL3 */
417}
418
419/**********************************************************************/
422static bool sdl_audio_init(struct audio_plugin *self)
423{
424 int i;
425
426 if (!init_sdl_audio()) {
427 return FALSE;
428 }
429
430#ifdef AUDIO_SDL3
432 if (mixer == NULL) {
433 log_error("Error calling MIX_CreateMixerDevice()");
434#else /* AUDIO_SDL3 */
435 /* Initialize variables */
438 const int audio_channels = 2;
439
441 log_error("Error calling Mix_OpenAudio");
442#endif /* AUDIO_SDL3 */
443
444 /* Try something else */
446 return FALSE;
447 }
448
449#ifdef AUDIO_SDL3
452 "MIX_PROP_PLAY_LOOPS_NUMBER", -1);
453#else /* AUDIO_SDL3 */
455#endif /* AUDIO_SDL3 */
456 for (i = 0; i < MIX_CHANNELS; i++) {
457#ifdef AUDIO_SDL3
459#endif /* AUDIO_SDL3 */
460 samples[i].wave = NULL;
461 }
462
463 /* Sanity check, for now; add volume controls later */
465
466 self->initialized = TRUE;
467
468 return TRUE;
469}
470
471/**********************************************************************/
476{
477 struct audio_plugin self;
478
479 sz_strlcpy(self.name, "sdl");
480 sz_strlcpy(self.descr, "Simple DirectMedia Library (SDL) mixer plugin");
481 self.initialized = FALSE;
482 self.init = sdl_audio_init;
483 self.shutdown = sdl_audio_shutdown;
484 self.stop = sdl_audio_stop;
485 self.wait = sdl_audio_wait;
486 self.play = sdl_audio_play;
487 self.pause = sdl_audio_pause;
488 self.resume = sdl_audio_resume;
489 self.set_volume = sdl_audio_set_volume;
490 self.get_volume = sdl_audio_get_volume;
492 sdl_audio_volume = 1.0;
493}
void audio_add_plugin(struct audio_plugin *p)
Definition audio.c:136
void(* audio_finished_callback)(void)
Definition audio.h:28
static void sdl_audio_shutdown(struct audio_plugin *self)
Definition audio_sdl.c:381
void audio_sdl_init(void)
Definition audio_sdl.c:475
static void sdl_audio_wait(void)
Definition audio_sdl.c:313
static void quit_sdl_audio(void)
Definition audio_sdl.c:344
static void sdl_audio_set_volume(double volume)
Definition audio_sdl.c:76
static bool sdl_audio_play(const char *const tag, const char *const fullpath, bool repeat, bool music, audio_finished_callback cb)
Definition audio_sdl.c:113
static void sdl_audio_resume(void)
Definition audio_sdl.c:277
static struct sample samples[MIX_CHANNELS]
Definition audio_sdl.c:70
static bool init_sdl_audio(void)
Definition audio_sdl.c:363
static double sdl_audio_volume
Definition audio_sdl.c:71
static bool sdl_audio_init(struct audio_plugin *self)
Definition audio_sdl.c:422
static Mix_Music * mus
Definition audio_sdl.c:67
const size_t buf_size
Definition audio_sdl.c:57
static void sdl_audio_pause(void)
Definition audio_sdl.c:261
static void sdl_audio_stop(void)
Definition audio_sdl.c:293
static double sdl_audio_get_volume(void)
Definition audio_sdl.c:95
static struct ai_type * self
Definition classicai.c:46
char * incite_cost
Definition comments.c:77
#define log_verbose(message,...)
Definition log.h:110
#define log_debug(message,...)
Definition log.h:116
#define log_error(message,...)
Definition log.h:104
char name[MAX_LEN_NAME]
Definition ai.h:51
Mix_Chunk * wave
Definition audio_sdl.c:46
const char * tag
Definition audio_sdl.c:48
#define sz_strlcpy(dest, src)
Definition support.h:195
#define TRUE
Definition support.h:46
#define FALSE
Definition support.h:47