Freeciv-3.1
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 SDL2_PLAIN_INCLUDE
21#include <SDL.h>
22#include <SDL_mixer.h>
23#else /* SDL2_PLAIN_INCLUDE */
24#include <SDL2/SDL.h>
25#include <SDL2/SDL_mixer.h>
26#endif /* SDL2_PLAIN_INCLUDE */
27
28/* utility */
29#include "log.h"
30#include "support.h"
31
32/* client */
33#include "audio.h"
34
35#include "audio_sdl.h"
36
37struct sample {
38 Mix_Chunk *wave;
39 const char *tag;
40};
41
42/* Sounds don't sound good on Windows unless the buffer size is 4k,
43 * but this seems to cause strange behaviour on other systems,
44 * such as a delay before playing the sound. */
45#ifdef FREECIV_MSWINDOWS
46const size_t buf_size = 4096;
47#else
48const size_t buf_size = 1024;
49#endif
50
51static Mix_Music *mus = NULL;
52static struct sample samples[MIX_CHANNELS];
53static double sdl_audio_volume;
54
55/**********************************************************************/
58static void sdl_audio_set_volume(double volume)
59{
60 Mix_VolumeMusic(volume * MIX_MAX_VOLUME);
61 Mix_Volume(-1, volume * MIX_MAX_VOLUME);
62 sdl_audio_volume = volume;
63}
64
65/**********************************************************************/
68static double sdl_audio_get_volume(void)
69{
70 return sdl_audio_volume;
71}
72
73/**********************************************************************/
76static bool sdl_audio_play(const char *const tag, const char *const fullpath,
77 bool repeat, audio_finished_callback cb)
78{
79 int i, j;
80 Mix_Chunk *wave = NULL;
81
82 if (!fullpath) {
83 return FALSE;
84 }
85
86 if (repeat) {
87 /* unload previous */
88 Mix_HaltMusic();
89 Mix_FreeMusic(mus);
90
91 /* load music file */
92 mus = Mix_LoadMUS(fullpath);
93 if (mus == NULL) {
94 log_error("Can't open file \"%s\"", fullpath);
95 }
96
97 if (cb == NULL) {
98 Mix_PlayMusic(mus, -1); /* -1 means loop forever */
99 } else {
100 Mix_PlayMusic(mus, 0);
101 Mix_HookMusicFinished(cb);
102 }
103 log_verbose("Playing file \"%s\" on music channel", fullpath);
104 /* in case we did a sdl_audio_stop() recently; add volume controls later */
105 Mix_VolumeMusic(sdl_audio_volume * MIX_MAX_VOLUME);
106
107 } else {
108
109 /* see if we can cache on this one */
110 for (j = 0; j < MIX_CHANNELS; j++) {
111 if (samples[j].tag && (strcmp(samples[j].tag, tag) == 0)) {
112 log_debug("Playing file \"%s\" from cache (slot %d)", fullpath, j);
113 Mix_PlayChannel(-1, samples[j].wave, 0);
114 return TRUE;
115 }
116 } /* guess not */
117
118 /* load wave */
119 wave = Mix_LoadWAV(fullpath);
120 if (wave == NULL) {
121 log_error("Can't open file \"%s\"", fullpath);
122 }
123
124 /* play sound sample on first available channel, returns -1 if no
125 channel found */
126 i = Mix_PlayChannel(-1, wave, 0);
127 if (i < 0) {
128 log_verbose("No available sound channel to play %s.", tag);
129 Mix_FreeChunk(wave);
130 return FALSE;
131 }
132 log_verbose("Playing file \"%s\" on channel %d", fullpath, i);
133 /* free previous sample on this channel. it will by definition no
134 longer be playing by the time we get here */
135 if (samples[i].wave) {
136 Mix_FreeChunk(samples[i].wave);
137 samples[i].wave = NULL;
138 }
139 /* remember for caching */
140 samples[i].wave = wave;
141 samples[i].tag = tag;
142
143 }
144 return TRUE;
145}
146
147/**********************************************************************/
150static void sdl_audio_stop(void)
151{
152 /* Fade out over 2 sec */
153 Mix_FadeOutMusic(2000);
154}
155
156/**********************************************************************/
161static void sdl_audio_wait(void)
162{
163 while (Mix_Playing(-1) != 0) {
164 SDL_Delay(100);
165 }
166}
167
168/**********************************************************************/
174static void quit_sdl_audio(void)
175{
176 if (SDL_WasInit(SDL_INIT_VIDEO)) {
177 SDL_QuitSubSystem(SDL_INIT_AUDIO);
178 } else {
179 SDL_Quit();
180 }
181}
182
183/**********************************************************************/
189static int init_sdl_audio(void)
190{
191#if SDL_VERSION_ATLEAST(2, 0, 6)
192 SDL_SetHint(SDL_HINT_AUDIO_RESAMPLING_MODE, "medium");
193#endif
194
195 if (SDL_WasInit(SDL_INIT_VIDEO)) {
196 return SDL_InitSubSystem(SDL_INIT_AUDIO | SDL_INIT_NOPARACHUTE);
197 } else {
198 return SDL_Init(SDL_INIT_AUDIO | SDL_INIT_NOPARACHUTE);
199 }
200}
201
202/**********************************************************************/
206{
207 int i;
208
209 self->initialized = FALSE;
210
213
214 /* Remove all buffers */
215 for (i = 0; i < MIX_CHANNELS; i++) {
216 if (samples[i].wave) {
217 Mix_FreeChunk(samples[i].wave);
218 }
219 }
220 Mix_HaltMusic();
221 Mix_FreeMusic(mus);
222
223 Mix_CloseAudio();
225}
226
227/**********************************************************************/
230static bool sdl_audio_init(struct audio_plugin *self)
231{
232 /* Initialize variables */
233 const int audio_rate = MIX_DEFAULT_FREQUENCY;
234 const int audio_format = MIX_DEFAULT_FORMAT;
235 const int audio_channels = 2;
236 int i;
237
238 if (init_sdl_audio() < 0) {
239 return FALSE;
240 }
241
242 if (Mix_OpenAudio(audio_rate, audio_format, audio_channels, buf_size) < 0) {
243 log_error("Error calling Mix_OpenAudio");
244
245 /* Try something else */
247 return FALSE;
248 }
249
250 Mix_AllocateChannels(MIX_CHANNELS);
251 for (i = 0; i < MIX_CHANNELS; i++) {
252 samples[i].wave = NULL;
253 }
254
255 /* Sanity check, for now; add volume controls later */
257
258 self->initialized = TRUE;
259
260 return TRUE;
261}
262
263/**********************************************************************/
268{
269 struct audio_plugin self;
270
271 sz_strlcpy(self.name, "sdl");
272 sz_strlcpy(self.descr, "Simple DirectMedia Library (SDL) mixer plugin");
273 self.initialized = FALSE;
274 self.init = sdl_audio_init;
275 self.shutdown = sdl_audio_shutdown;
276 self.stop = sdl_audio_stop;
277 self.wait = sdl_audio_wait;
278 self.play = sdl_audio_play;
279 self.set_volume = sdl_audio_set_volume;
280 self.get_volume = sdl_audio_get_volume;
282 sdl_audio_volume = 1.0;
283}
void audio_add_plugin(struct audio_plugin *p)
Definition audio.c:135
void(* audio_finished_callback)(void)
Definition audio.h:27
static void sdl_audio_shutdown(struct audio_plugin *self)
Definition audio_sdl.c:205
void audio_sdl_init(void)
Definition audio_sdl.c:267
static void sdl_audio_wait(void)
Definition audio_sdl.c:161
static void quit_sdl_audio(void)
Definition audio_sdl.c:174
static void sdl_audio_set_volume(double volume)
Definition audio_sdl.c:58
static bool sdl_audio_play(const char *const tag, const char *const fullpath, bool repeat, audio_finished_callback cb)
Definition audio_sdl.c:76
static struct sample samples[MIX_CHANNELS]
Definition audio_sdl.c:52
static double sdl_audio_volume
Definition audio_sdl.c:53
static bool sdl_audio_init(struct audio_plugin *self)
Definition audio_sdl.c:230
static int init_sdl_audio(void)
Definition audio_sdl.c:189
static Mix_Music * mus
Definition audio_sdl.c:51
const size_t buf_size
Definition audio_sdl.c:48
static void sdl_audio_stop(void)
Definition audio_sdl.c:150
static double sdl_audio_get_volume(void)
Definition audio_sdl.c:68
static struct ai_type * self
Definition classicai.c:46
#define log_verbose(message,...)
Definition log.h:109
#define log_debug(message,...)
Definition log.h:115
#define log_error(message,...)
Definition log.h:103
char name[MAX_LEN_NAME]
Definition ai.h:51
Mix_Chunk * wave
Definition audio_sdl.c:38
const char * tag
Definition audio_sdl.c:39
#define sz_strlcpy(dest, src)
Definition support.h:167
#define TRUE
Definition support.h:46
#define FALSE
Definition support.h:47