naev 0.12.6
music.c
Go to the documentation of this file.
1/*
2 * See Licensing and Copyright notice in naev.h
3 */
9
11#include "SDL.h"
12#include "physfsrwops.h"
13
14#include "naev.h"
16
17#include "music.h"
18
19#include "conf.h"
20#include "log.h"
21#include "ndata.h"
22#include "nlua.h"
23#include "nlua_tk.h"
24#include "ntracing.h"
25#include "sound.h"
26
27#define MUSIC_SUFFIX ".ogg"
28
30static double music_vol = 0.;
31static double music_vol_lin = 0.;
32
33/*
34 * Handle if music should run Lua script. Must be locked to ensure same
35 * behaviour always.
36 */
37static int music_runchoose =
38 0;
39
40/*
41 * global music lua
42 */
43static nlua_env music_env = LUA_NOREF;
44static int music_lua_update = LUA_NOREF;
45static int music_lua_choose = LUA_NOREF;
46static int music_lua_play = LUA_NOREF;
47static int music_lua_stop = LUA_NOREF;
48static int music_lua_pause = LUA_NOREF;
49static int music_lua_resume = LUA_NOREF;
50static int music_lua_info = LUA_NOREF;
51static int music_lua_volume = LUA_NOREF;
52
53/* functions */
54static int music_runLua( const char *situation );
55
56/*
57 * prototypes
58 */
59/* music stuff */
60static int music_find( void );
61/* Lua stuff */
62static int music_luaInit( void );
63static void music_luaQuit( void );
64
68void music_update( double dt )
69{
70 if ( music_disabled )
71 return;
72
73 NTracingZone( _ctx, 1 );
74
75 /* Run the choose function in Lua. */
76 lua_rawgeti( naevL, LUA_REGISTRYINDEX, music_lua_update );
77 lua_pushnumber( naevL, dt );
78 if ( nlua_pcall( music_env, 1, 0 ) ) { /* error has occurred */
79 WARN( _( "Error while running music function '%s': %s" ), "update",
80 lua_tostring( naevL, -1 ) );
81 lua_pop( naevL, 1 );
82 }
83
84 NTracingZoneEnd( _ctx );
85}
86
93static int music_runLua( const char *situation )
94{
95 if ( music_disabled )
96 return 0;
97
98 /* Run the choose function in Lua. */
99 lua_rawgeti( naevL, LUA_REGISTRYINDEX, music_lua_choose );
100 if ( situation != NULL )
101 lua_pushstring( naevL, situation );
102 else
103 lua_pushnil( naevL );
104 if ( nlua_pcall( music_env, 1, 0 ) ) { /* error has occurred */
105 WARN( _( "Error while running music function '%s': %s" ), "choose",
106 lua_tostring( naevL, -1 ) );
107 lua_pop( naevL, 1 );
108 return -1;
109 }
110
111 return 0;
112}
113
119int music_init( void )
120{
121 if ( music_disabled )
122 return 0;
123
124 /* Load the music. */
125 music_find();
126
127 /* Start up Lua. */
128 if ( music_luaInit() < 0 )
129 return -1;
130
131 /* Set the volume. */
132 if ( ( conf.music > 1. ) || ( conf.music < 0. ) )
133 WARN( _( "Music has invalid value, clamping to [0:1]." ) );
134 music_volume( conf.music );
135
136 return 0;
137}
138
142void music_exit( void )
143{
144 if ( music_disabled )
145 return;
146
147 /* Clean up Lua. */
149}
150
156static int music_find( void )
157{
158 char **files;
159 int suflen;
160 int nmusic;
161
162 if ( music_disabled )
163 return 0;
164
165 /* get the file list */
166 files = PHYSFS_enumerateFiles( MUSIC_PATH );
167
168 /* load the profiles */
169 nmusic = 0;
170 suflen = strlen( MUSIC_SUFFIX );
171 for ( size_t i = 0; files[i] != NULL; i++ ) {
172 int flen = strlen( files[i] );
173 if ( ( flen > suflen ) &&
174 strncmp( &files[i][flen - suflen], MUSIC_SUFFIX, suflen ) == 0 ) {
175
176 /* grow the selection size */
177 nmusic++;
178 }
179 }
180
181 DEBUG( n_( "Loaded %d Song", "Loaded %d Songs", nmusic ), nmusic );
182
183 /* More clean up. */
184 PHYSFS_freeList( files );
185
186 return 0;
187}
188
195int music_volume( double vol )
196{
197 if ( music_disabled )
198 return 0;
199
200 music_vol_lin = vol;
201 if ( vol > 0. )
202 music_vol = 1. / pow( 2., ( 1. - vol ) * 8. );
203 else
204 music_vol = 0.;
205
206 /* Run the choose function in Lua. */
207 lua_rawgeti( naevL, LUA_REGISTRYINDEX, music_lua_volume );
208 lua_pushnumber( naevL, music_vol );
209 if ( nlua_pcall( music_env, 1, 0 ) ) { /* error has occurred */
210 WARN( _( "Error while running music function '%s': %s" ), "volume",
211 lua_tostring( naevL, -1 ) );
212 lua_pop( naevL, 1 );
213 return -1;
214 }
215 return 0;
216}
217
223double music_getVolume( void )
224{
225 return music_vol_lin;
226}
227
233double music_getVolumeLog( void )
234{
235 return music_vol;
236}
237
241int music_play( const char *filename )
242{
243 if ( music_disabled )
244 return 0;
245
246 /* Run the play function in Lua. */
247 lua_rawgeti( naevL, LUA_REGISTRYINDEX, music_lua_play );
248 if ( filename != NULL )
249 lua_pushstring( naevL, filename );
250 else
251 lua_pushnil( naevL );
252 if ( nlua_pcall( music_env, 1, 0 ) ) { /* error has occurred */
253 WARN( _( "Error while running music function '%s': %s" ), "play",
254 lua_tostring( naevL, -1 ) );
255 lua_pop( naevL, 1 );
256 return -1;
257 }
258 return 0;
259}
260
267int music_stop( int disable )
268{
269 if ( music_disabled )
270 return 0;
271
272 /* Run the stop function in Lua. */
273 lua_rawgeti( naevL, LUA_REGISTRYINDEX, music_lua_stop );
274 lua_pushboolean( naevL, disable );
275 if ( nlua_pcall( music_env, 1, 0 ) ) { /* error has occurred */
276 WARN( _( "Error while running music function '%s': %s" ), "stop",
277 lua_tostring( naevL, -1 ) );
278 lua_pop( naevL, 1 );
279 return -1;
280 }
281 return 0;
282}
283
287int music_pause( int disable )
288{
289 if ( music_disabled )
290 return 0;
291
292 /* Run the pause function in Lua. */
293 lua_rawgeti( naevL, LUA_REGISTRYINDEX, music_lua_pause );
294 lua_pushboolean( naevL, disable );
295 if ( nlua_pcall( music_env, 1, 0 ) ) { /* error has occurred */
296 WARN( _( "Error while running music function '%s': %s" ), "pause",
297 lua_tostring( naevL, -1 ) );
298 lua_pop( naevL, 1 );
299 return -1;
300 }
301 return 0;
302}
303
307int music_resume( void )
308{
309 if ( music_disabled )
310 return 0;
311
312 /* Run the resume function in Lua. */
313 lua_rawgeti( naevL, LUA_REGISTRYINDEX, music_lua_resume );
314 if ( nlua_pcall( music_env, 0, 0 ) ) { /* error has occurred */
315 WARN( _( "Error while running music function '%s': %s" ), "resume",
316 lua_tostring( naevL, -1 ) );
317 lua_pop( naevL, 1 );
318 return -1;
319 }
320 return 0;
321}
322
323static MusicInfo_t minfo;
328{
329 if ( minfo.name ) {
330 free( minfo.name );
331 minfo.name = NULL;
332 }
333
334 /* Run the info function in Lua. */
335 lua_rawgeti( naevL, LUA_REGISTRYINDEX, music_lua_info );
336 if ( nlua_pcall( music_env, 0, 3 ) ) { /* error has occurred */
337 WARN( _( "Error while running music function '%s': %s" ), "info",
338 lua_tostring( naevL, -1 ) );
339 lua_pop( naevL, 1 );
340 return NULL;
341 }
342
343 minfo.playing = lua_toboolean( naevL, -3 );
344 minfo.name = strdup( luaL_optstring( naevL, -2, "" ) );
345 minfo.pos = luaL_optnumber( naevL, -1, -1 );
346
347 lua_pop( naevL, 3 );
348
349 return &minfo;
350}
351
352/*
353 * music Lua stuff
354 */
360static int music_luaInit( void )
361{
362 char *buf;
363 size_t bufsize;
364
365 if ( music_disabled )
366 return 0;
367
368 if ( music_env != LUA_NOREF )
370
371 /* Reset the environment. */
372 music_env = nlua_newEnv( MUSIC_LUA_PATH );
375
376 /* load the actual Lua music code */
377 buf = ndata_read( MUSIC_LUA_PATH, &bufsize );
378 if ( nlua_dobufenv( music_env, buf, bufsize, MUSIC_LUA_PATH ) != 0 ) {
379 WARN( _( "Error loading music file: %s\n"
380 "%s\n"
381 "Most likely Lua file has improper syntax, please check" ),
382 MUSIC_LUA_PATH, lua_tostring( naevL, -1 ) );
383 return -1;
384 }
385 free( buf );
386
387 /* Set up comfort functions. */
388 music_lua_choose = nlua_refenvtype( music_env, "choose", LUA_TFUNCTION );
389 music_lua_update = nlua_refenvtype( music_env, "update", LUA_TFUNCTION );
390 music_lua_play = nlua_refenvtype( music_env, "play", LUA_TFUNCTION );
391 music_lua_stop = nlua_refenvtype( music_env, "stop", LUA_TFUNCTION );
392 music_lua_pause = nlua_refenvtype( music_env, "pause", LUA_TFUNCTION );
393 music_lua_resume = nlua_refenvtype( music_env, "resume", LUA_TFUNCTION );
394 music_lua_info = nlua_refenvtype( music_env, "info", LUA_TFUNCTION );
395 music_lua_volume = nlua_refenvtype( music_env, "volume", LUA_TFUNCTION );
396
397 return 0;
398}
399
403static void music_luaQuit( void )
404{
405 if ( music_disabled )
406 return;
407
408 nlua_freeEnv( music_env );
409 music_env = LUA_NOREF;
410 music_lua_choose = LUA_NOREF;
411 music_lua_update = LUA_NOREF;
412 music_lua_play = LUA_NOREF;
413 music_lua_stop = LUA_NOREF;
414 music_lua_pause = LUA_NOREF;
415 music_lua_resume = LUA_NOREF;
416 music_lua_info = LUA_NOREF;
417 music_lua_volume = LUA_NOREF;
418}
419
426int music_choose( const char *situation )
427{
429 return 0;
430
431 if ( music_runLua( situation ) )
432 return -1;
433
434 return 0;
435}
436
440void music_rechoose( void )
441{
442 if ( music_disabled )
443 return;
444
445 /* Lock so it doesn't run in between an update. */
446 music_runchoose = 1;
447}
MusicInfo_t * music_info(void)
Gets information about the current music state.
Definition music.c:327
static int music_runchoose
Definition music.c:37
static int music_find(void)
Internal music loading routines.
Definition music.c:156
int music_play(const char *filename)
Plays the loaded music.
Definition music.c:241
int music_disabled
Definition music.c:29
int music_pause(int disable)
Pauses the music.
Definition music.c:287
double music_getVolumeLog(void)
Gets the current music volume (logarithmic).
Definition music.c:233
double music_getVolume(void)
Gets the current music volume (linear).
Definition music.c:223
int music_choose(const char *situation)
Actually runs the music stuff, based on situation.
Definition music.c:426
int music_volume(double vol)
Sets the music volume from a linear value.
Definition music.c:195
int music_stop(int disable)
Stops the loaded music.
Definition music.c:267
static void music_luaQuit(void)
Quits the music Lua control system.
Definition music.c:403
#define MUSIC_SUFFIX
Definition music.c:27
void music_rechoose(void)
Attempts to rechoose the music.
Definition music.c:440
static int music_luaInit(void)
Initialize the music Lua control system.
Definition music.c:360
void music_exit(void)
Exits the music subsystem.
Definition music.c:142
static nlua_env music_env
Definition music.c:43
void music_update(double dt)
Updates the music.
Definition music.c:68
int music_init(void)
Initializes the music subsystem.
Definition music.c:119
static int music_runLua(const char *situation)
Runs the Lua music choose function.
Definition music.c:93
int music_resume(void)
Resumes the music.
Definition music.c:307
Header file with generic functions and naev-specifics.
void * ndata_read(const char *path, size_t *filesize)
Reads a file from the ndata (will be NUL terminated).
Definition ndata.c:207
int nlua_loadStandard(nlua_env env)
Loads the standard Naev Lua API.
Definition nlua.c:914
int nlua_refenvtype(nlua_env env, const char *name, int type)
Gets the reference of a global in a lua environment if it matches a type.
Definition nlua.c:1047
lua_State * naevL
Definition nlua.c:54
int nlua_loadTk(nlua_env env)
Loads the Toolkit Lua library.
Definition nlua_tk.c:98
int sound_disabled
Definition sound.c:130