2 * See Licensing and Copyright notice in naev.h
8 * @brief Controls all the music playing.
18 #include "music_sdlmix.h"
19 #include "music_openal.h"
23 #include "nlua_music.h"
29 #define MUSIC_PREFIX "snd/music/" /**< Prefix of where tho find musics. */
30 #define MUSIC_SUFFIX ".ogg" /**< Suffix of musics. */
32 #define MUSIC_LUA_PATH "snd/music.lua" /**< Lua music control file. */
35 #define CHUNK_SIZE 32 /**< Size of a chunk to allocate. */
38 int music_disabled
= 0; /**< Whether or not music is disabled. */
42 * Handle if music should run Lua script. Must be locked to ensure same
45 static SDL_mutex
*music_lock
= NULL
; /**< lock for music_runLua so it doesn't
46 run twice in a row with weird
48 DO NOT CALL MIX_* FUNCTIONS WHEN
50 static int music_runchoose
= 0; /**< Whether or not music should run the choose function. */
51 static char music_situation
[PATH_MAX
]; /**< What situation music is in. */
57 static lua_State
*music_lua
= NULL
; /**< The Lua music control state. */
59 static int music_runLua( const char *situation
);
65 static char** music_selection
= NULL
; /**< Available music selection. */
66 static int nmusic_selection
= 0; /**< Size of available music selection. */
72 static char *music_name
= NULL
; /**< Current music name. */
73 static unsigned int music_start
= 0; /**< Music start playing time. */
74 static double music_timer
= 0.; /**< Music timer. */
78 * Function pointers for backend.
81 int (*music_sys_init
) (void) = NULL
;
82 void (*music_sys_exit
) (void) = NULL
;
84 int (*music_sys_load
) ( const char* name
, SDL_RWops
*rw
) = NULL
;
85 void (*music_sys_free
) (void) = NULL
;
87 int (*music_sys_volume
)( const double vol
) = NULL
;
88 double (*music_sys_getVolume
) (void) = NULL
;
89 void (*music_sys_play
) (void) = NULL
;
90 void (*music_sys_stop
) (void) = NULL
;
91 void (*music_sys_pause
) (void) = NULL
;
92 void (*music_sys_resume
) (void) = NULL
;
93 void (*music_sys_setPos
) ( double sec
) = NULL
;
94 int (*music_sys_isPlaying
) (void) = NULL
;
101 static int music_find (void);
102 static void music_free (void);
104 static int music_luaInit (void);
105 static void music_luaQuit (void);
109 * @brief Updates the music.
111 void music_update( double dt
)
119 if (music_timer
> 0.) {
121 if (music_timer
<= 0.)
125 /* Lock music and see if needs to update. */
126 SDL_mutexP(music_lock
);
127 if (music_runchoose
== 0) {
128 SDL_mutexV(music_lock
);
132 strncpy(buf
, music_situation
, PATH_MAX
);
133 SDL_mutexV(music_lock
);
136 /* Make sure music is playing. */
137 if (!music_isPlaying())
138 music_choose("idle");
143 * @brief Runs the Lua music choose function.
145 * @param situation Situation in to choose music for.
146 * @return 0 on success.
148 static int music_runLua( const char *situation
)
153 /* Run the choose function in Lua. */
154 lua_getglobal( music_lua
, "choose" );
155 if (situation
!= NULL
)
156 lua_pushstring( music_lua
, situation
);
158 lua_pushnil( music_lua
);
159 if (lua_pcall(music_lua
, 1, 0, 0)) /* error has occured */
160 WARN("Error while choosing music: %s", lua_tostring(music_lua
,-1));
167 * @brief Initializes the music subsystem.
169 * @return 0 on success.
171 int music_init (void)
176 if ((conf
.sound_backend
!= NULL
) &&
177 (strcmp(conf
.sound_backend
,"sdlmix")==0)) {
183 music_sys_init
= music_mix_init
;
184 music_sys_exit
= music_mix_exit
;
186 music_sys_load
= music_mix_load
;
187 music_sys_free
= music_mix_free
;
189 music_sys_volume
= music_mix_volume
;
190 music_sys_getVolume
= music_mix_getVolume
;
191 music_sys_load
= music_mix_load
;
192 music_sys_play
= music_mix_play
;
193 music_sys_stop
= music_mix_stop
;
194 music_sys_pause
= music_mix_pause
;
195 music_sys_resume
= music_mix_resume
;
196 music_sys_setPos
= music_mix_setPos
;
197 music_sys_isPlaying
= music_mix_isPlaying
;
198 #else /* USE_SDLMIX */
199 WARN("SDL_mixer support not compiled in!");
201 #endif /* USE_SDLMIX */
203 else if ((conf
.sound_backend
!= NULL
) &&
204 (strcmp(conf
.sound_backend
,"openal")==0)) {
210 music_sys_init
= music_al_init
;
211 music_sys_exit
= music_al_exit
;
213 music_sys_load
= music_al_load
;
214 music_sys_free
= music_al_free
;
216 music_sys_volume
= music_al_volume
;
217 music_sys_getVolume
= music_al_getVolume
;
218 music_sys_load
= music_al_load
;
219 music_sys_play
= music_al_play
;
220 music_sys_stop
= music_al_stop
;
221 music_sys_pause
= music_al_pause
;
222 music_sys_resume
= music_al_resume
;
223 music_sys_setPos
= music_al_setPos
;
224 music_sys_isPlaying
= music_al_isPlaying
;
225 #else /* USE_OPENAL */
226 WARN("OpenAL support not compiled in!");
228 #endif /* USE_OPENAL*/
231 WARN("Unknown sound backend '%s'.", conf
.sound_backend
);
235 /* Start the subsystem. */
236 if (music_sys_init())
239 /* Load the music. */
240 if (music_find() < 0)
244 if (music_luaInit() < 0)
247 /* Set the volume. */
248 if ((conf
.music
> 1.) || (conf
.music
< 0.))
249 WARN("Music has invalid value, clamping to [0:1].");
250 music_volume(conf
.music
);
252 /* Create the lock. */
253 music_lock
= SDL_CreateMutex();
260 * @brief Exits the music subsystem.
262 void music_exit (void)
267 /* Free the music. */
270 /* Exit the subsystem. */
273 /* Destroy the lock. */
274 if (music_lock
!= NULL
) {
275 SDL_DestroyMutex(music_lock
);
282 * @brief Frees the current playing music.
284 static void music_free (void)
289 if (music_name
!= NULL
) {
300 * @brief Internal music loading routines.
302 * @return 0 on success.
304 static int music_find (void)
309 int len
, suflen
, flen
;
315 /* get the file list */
316 files
= ndata_list( MUSIC_PREFIX
, &nfiles
);
318 /* load the profiles */
320 suflen
= strlen(MUSIC_SUFFIX
);
321 for (i
=0; i
<nfiles
; i
++) {
322 flen
= strlen(files
[i
]);
323 if ((flen
> suflen
) &&
324 strncmp( &files
[i
][flen
- suflen
], MUSIC_SUFFIX
, suflen
)==0) {
326 /* grow the selection size */
328 if (nmusic_selection
> mem
) {
330 music_selection
= realloc( music_selection
, sizeof(char*)*mem
);
333 /* remove the prefix and suffix */
335 strncpy( tmp
, files
[i
], len
);
336 tmp
[MIN(len
,64-1)] = '\0';
338 /* give it the new name */
339 music_selection
[nmusic_selection
-1] = strdup(tmp
);
345 music_selection
= realloc( music_selection
, sizeof(char*)*nmusic_selection
);
347 DEBUG("Loaded %d song%c", nmusic_selection
, (nmusic_selection
==1)?' ':'s');
357 * @brief Sets the music volume.
359 * @param vol Volume to set to (between 0 and 1).
360 * @return 0 on success.
362 int music_volume( const double vol
)
367 return music_sys_volume( vol
);
372 * @brief Gets the current music volume.
374 * @return The current music volume.
376 double music_getVolume (void)
381 return music_sys_getVolume();
386 * @brief Loads the music by name.
388 * @param name Name of the file to load.
390 int music_load( const char* name
)
393 char filename
[PATH_MAX
];
398 /* Free current music if needed. */
401 /* Load new music. */
402 music_name
= strdup(name
);
403 music_start
= SDL_GetTicks();
404 snprintf( filename
, PATH_MAX
, MUSIC_PREFIX
"%s"MUSIC_SUFFIX
, name
);
405 rw
= ndata_rwops( filename
);
407 WARN("Music '%s' not found.", filename
);
410 music_sys_load( name
, rw
);
417 * @brief Plays the loaded music.
419 void music_play (void)
421 if (music_disabled
) return;
428 * @brief Stops the loaded music.
430 void music_stop (void)
432 if (music_disabled
) return;
439 * @brief Pauses the music.
441 void music_pause (void)
443 if (music_disabled
) return;
450 * @brief Resumes the music.
452 void music_resume (void)
454 if (music_disabled
) return;
461 * @brief Checks to see if the music is playing.
463 * @return 0 if music isn't playing, 1 if is playing.
465 int music_isPlaying (void)
468 return 0; /* Always not playing when music is off. */
470 return music_sys_isPlaying();
475 * @brief Gets the name of the current playing song.
477 * @return Name of the current playing song.
479 const char *music_playingName (void)
489 * @brief Gets the time since the music started playing.
491 * @return The time since the music started playing.
493 double music_playingTime (void)
498 return (double)(SDL_GetTicks() - music_start
) / 1000.;
503 * @brief Sets the music to a position in seconds.
505 * @param sec Position to go to in seconds.
507 void music_setPos( double sec
)
512 music_sys_setPos( sec
);
520 * @brief Initialize the music Lua control system.
522 * @return 0 on success.
524 static int music_luaInit (void)
532 if (music_lua
!= NULL
)
535 music_lua
= nlua_newState();
536 nlua_loadBasic(music_lua
);
537 nlua_loadStandard(music_lua
,1);
538 nlua_loadMusic(music_lua
,0); /* write it */
540 /* load the actual lua music code */
541 buf
= ndata_read( MUSIC_LUA_PATH
, &bufsize
);
542 if (luaL_dobuffer(music_lua
, buf
, bufsize
, MUSIC_LUA_PATH
) != 0) {
543 ERR("Error loading music file: %s\n"
545 "Most likely Lua file has improper syntax, please check",
546 MUSIC_LUA_PATH
, lua_tostring(music_lua
,-1) );
556 * @brief Quits the music Lua contrtol system.
558 static void music_luaQuit (void)
563 if (music_lua
== NULL
)
566 lua_close(music_lua
);
572 * @brief Actually runs the music stuff, based on situation.
574 * @param situation Choose a new music to play.
575 * @return 0 on success.
577 int music_choose( const char* situation
)
583 music_runLua( situation
);
591 * @brief Actually runs the music stuff, based on situation after a delay.
593 * @param situation Choose a new music to play after delay.
594 * @param delay Delay in seconds to delay the rechoose.
595 * @return 0 on success.
597 int music_chooseDelay( const char* situation
, double delay
)
602 /* Lock so it doesn't run in between an update. */
603 SDL_mutexP(music_lock
);
606 strncpy(music_situation
, situation
, PATH_MAX
);
607 SDL_mutexV(music_lock
);
614 * @brief Attempts to rechoose the music.
616 * DO NOT CALL MIX_* FUNCTIONS FROM WITHIN THE CALLBACKS!
618 void music_rechoose (void)
623 /* Lock so it doesn't run in between an update. */
624 SDL_mutexP(music_lock
);
627 strncpy(music_situation
, "idle", PATH_MAX
);
628 SDL_mutexV(music_lock
);