2020-01-01 21:29:24 +01:00
|
|
|
#ifndef MUSIC_H
|
|
|
|
#define MUSIC_H
|
|
|
|
|
|
|
|
#include <vector>
|
|
|
|
|
2020-07-19 21:43:29 +02:00
|
|
|
#include "BinaryBlob.h"
|
|
|
|
#include "SoundSystem.h"
|
|
|
|
|
2020-01-01 21:29:24 +01:00
|
|
|
#define musicroom(rx, ry) ((rx) + ((ry) * 20))
|
|
|
|
|
|
|
|
class musicclass
|
|
|
|
{
|
|
|
|
public:
|
Explicitly declare void for all void parameter functions (#628)
Apparently in C, if you have `void test();`, it's completely okay to do
`test(2);`. The function will take in the argument, but just discard it
and throw it away. It's like a trash can, and a rude one at that. If you
declare it like `void test(void);`, this is prevented.
This is not a problem in C++ - doing `void test();` and `test(2);` is
guaranteed to result in a compile error (this also means that right now,
at least in all `.cpp` files, nobody is ever calling a void parameter
function with arguments and having their arguments be thrown away).
However, we may not be using C++ in the future, so I just want to lay
down the precedent that if a function takes in no arguments, you must
explicitly declare it as such.
I would've added `-Wstrict-prototypes`, but it produces an annoying
warning message saying it doesn't work in C++ mode if you're compiling
in C++ mode. So it can be added later.
2021-02-25 23:23:59 +01:00
|
|
|
musicclass(void);
|
|
|
|
void init(void);
|
|
|
|
void destroy(void);
|
2020-01-01 21:29:24 +01:00
|
|
|
|
Fix resumemusic/musicfadein not working
It seems like they were unfinished. This commit makes them properly
work.
When a track is stopped with stopmusic() or musicfadeout(),
resumemusic() will resume from where the track stopped. musicfadein()
does the same but does it with a gradual fade instead of suddenly
playing it at full volume.
I changed several interfaces around for this. First, setting currentsong
to -1 when music is stopped is handled in the hook callback that gets
called by SDL_mixer whenever the music stops. Otherwise, it'd be
problematic if currentsong was set to -1 when the song starts fading out
instead of when the song actually ends.
Also, music.play() has a few optional arguments now, to reduce the
copying-and-pasting of music code.
Lastly, we have to roll our own tracker of music length by using
SDL_GetPerformanceCounter(), because there's no way to get the music
position if a song fades out. (We could implicitly keep the music
position if we abruptly stopped the song using Mix_PauseMusic(), and
resume it using Mix_ResumeMusic(), but ignoring the fact that those two
functions are also used on the unfocus-pause (which, as it turns out, is
basically a non-issue because the unfocus-pause can use some other
functions), there's no equivalent for fading out, i.e. there's no
"fade out and pause when it fully fades out" function in SDL_mixer.) And
then we have to account for the unfocus-pause in our manual tracker.
Other than that, these commands are now fully functional.
2020-06-27 10:31:09 +02:00
|
|
|
void play(int t, const double position_sec = 0.0, const int fadein_ms = 3000);
|
|
|
|
void resume(const int fadein_ms = 0);
|
Explicitly declare void for all void parameter functions (#628)
Apparently in C, if you have `void test();`, it's completely okay to do
`test(2);`. The function will take in the argument, but just discard it
and throw it away. It's like a trash can, and a rude one at that. If you
declare it like `void test(void);`, this is prevented.
This is not a problem in C++ - doing `void test();` and `test(2);` is
guaranteed to result in a compile error (this also means that right now,
at least in all `.cpp` files, nobody is ever calling a void parameter
function with arguments and having their arguments be thrown away).
However, we may not be using C++ in the future, so I just want to lay
down the precedent that if a function takes in no arguments, you must
explicitly declare it as such.
I would've added `-Wstrict-prototypes`, but it produces an annoying
warning message saying it doesn't work in C++ mode if you're compiling
in C++ mode. So it can be added later.
2021-02-25 23:23:59 +01:00
|
|
|
void haltdasmusik(void);
|
|
|
|
void silencedasmusik(void);
|
2020-01-01 21:29:24 +01:00
|
|
|
void fadeMusicVolumeIn(int ms);
|
2020-11-06 09:51:04 +01:00
|
|
|
void fadeout(const bool quick_fade_ = true);
|
Explicitly declare void for all void parameter functions (#628)
Apparently in C, if you have `void test();`, it's completely okay to do
`test(2);`. The function will take in the argument, but just discard it
and throw it away. It's like a trash can, and a rude one at that. If you
declare it like `void test(void);`, this is prevented.
This is not a problem in C++ - doing `void test();` and `test(2);` is
guaranteed to result in a compile error (this also means that right now,
at least in all `.cpp` files, nobody is ever calling a void parameter
function with arguments and having their arguments be thrown away).
However, we may not be using C++ in the future, so I just want to lay
down the precedent that if a function takes in no arguments, you must
explicitly declare it as such.
I would've added `-Wstrict-prototypes`, but it produces an annoying
warning message saying it doesn't work in C++ mode if you're compiling
in C++ mode. So it can be added later.
2021-02-25 23:23:59 +01:00
|
|
|
void fadein(void);
|
|
|
|
void processmusicfadein(void);
|
|
|
|
void processmusic(void);
|
2020-01-01 21:29:24 +01:00
|
|
|
void niceplay(int t);
|
|
|
|
|
|
|
|
void changemusicarea(int x, int y);
|
|
|
|
|
2020-06-27 10:40:58 +02:00
|
|
|
int currentsong;
|
2020-01-01 21:29:24 +01:00
|
|
|
int resumesong;
|
|
|
|
|
2020-04-02 01:36:35 +02:00
|
|
|
void playef(int t);
|
2020-01-01 21:29:24 +01:00
|
|
|
|
|
|
|
std::vector<SoundTrack> soundTracks;
|
|
|
|
std::vector<MusicTrack> musicTracks;
|
|
|
|
SoundSystem soundSystem;
|
|
|
|
bool safeToProcessMusic;
|
|
|
|
|
2020-11-06 09:36:25 +01:00
|
|
|
int nicechange; // -1 if no song queued
|
2020-11-06 09:20:58 +01:00
|
|
|
bool nicefade;
|
2020-01-01 21:29:24 +01:00
|
|
|
|
|
|
|
bool m_doFadeInVol;
|
|
|
|
int FadeVolAmountPerFrame;
|
|
|
|
int musicVolume;
|
|
|
|
|
2020-11-06 09:51:04 +01:00
|
|
|
bool quick_fade;
|
2020-01-13 04:33:58 +01:00
|
|
|
|
2020-01-01 21:29:24 +01:00
|
|
|
// MMMMMM mod settings
|
|
|
|
bool mmmmmm;
|
|
|
|
bool usingmmmmmm;
|
2020-06-07 22:11:35 +02:00
|
|
|
|
Separate musicReadBlob into mmmmmm_blob and pppppp_blob
musicReadBlob was used for both MMMMMM and PPPPPP soundtracks. This
causes a memory leak if you have mmmmmm.vvv installed, because the
pointers holding each allocated block of MMMMMM would be lost when
PPPPPP got loaded. Valgrind complains about this memory leak.
This is in contrast to 2.2 and previous behavior, where musicReadBlob
was only a temporary object instead of being held in musicclass.
However, this wasn't really a memory leak (moreso something that just
didn't get cleaned up when closing the game), but it did get turned into
a leak when per-level assets mounting and unmounting got introduced in
2.3 (loading a level with custom assets after starting the game with an
mmmmmm.vvv, or exiting out of a level that had an mmmmmm.vvv, would
cause the game to leak memory). Leo recognized this, and moved
musicReadBlob onto musicclass in a separate 2.3 PR, but either he didn't
think about what was happening here too closely, or he didn't use
Valgrind, because he forgot about the memory leak caused by re-using the
same binaryBlob for PPPPPP and MMMMMM.
So instead, just use two different binaryBlob objects for MMMMMM and
PPPPPP. That way, no memory leaks happen.
2021-02-16 01:42:58 +01:00
|
|
|
binaryBlob pppppp_blob;
|
|
|
|
binaryBlob mmmmmm_blob;
|
2020-07-01 02:08:37 +02:00
|
|
|
int num_pppppp_tracks;
|
|
|
|
int num_mmmmmm_tracks;
|
Fix resumemusic/musicfadein not working
It seems like they were unfinished. This commit makes them properly
work.
When a track is stopped with stopmusic() or musicfadeout(),
resumemusic() will resume from where the track stopped. musicfadein()
does the same but does it with a gradual fade instead of suddenly
playing it at full volume.
I changed several interfaces around for this. First, setting currentsong
to -1 when music is stopped is handled in the hook callback that gets
called by SDL_mixer whenever the music stops. Otherwise, it'd be
problematic if currentsong was set to -1 when the song starts fading out
instead of when the song actually ends.
Also, music.play() has a few optional arguments now, to reduce the
copying-and-pasting of music code.
Lastly, we have to roll our own tracker of music length by using
SDL_GetPerformanceCounter(), because there's no way to get the music
position if a song fades out. (We could implicitly keep the music
position if we abruptly stopped the song using Mix_PauseMusic(), and
resume it using Mix_ResumeMusic(), but ignoring the fact that those two
functions are also used on the unfocus-pause (which, as it turns out, is
basically a non-issue because the unfocus-pause can use some other
functions), there's no equivalent for fading out, i.e. there's no
"fade out and pause when it fully fades out" function in SDL_mixer.) And
then we have to account for the unfocus-pause in our manual tracker.
Other than that, these commands are now fully functional.
2020-06-27 10:31:09 +02:00
|
|
|
|
|
|
|
Uint64 songStart;
|
|
|
|
Uint64 songEnd;
|
2020-01-01 21:29:24 +01:00
|
|
|
};
|
|
|
|
|
2020-09-28 04:15:06 +02:00
|
|
|
#ifndef MUSIC_DEFINITION
|
Allow using help/graphics/music/game/key/map/obj everywhere
This commit makes `help`, `graphics`, `music`, `game`, `key`, `map`, and
`obj` essentially static global objects that can be used everywhere.
This is useful in case we ever need to add a new function in the future,
so we don't have to bother with passing a new argument in which means we
have to pass a new argument in to the function that calls that function
which means having to pass a new argument into the function that calls
THAT function, etc. which is a real headache when working on fan mods of
the source code.
Note that this changes NONE of the existing function signatures, it
merely just makes those variables accessible everywhere in the same way
`script` and `ed` are.
Also note that some classes had to be initialized after the filesystem
was initialized, but C++ would keep initializing them before the
filesystem got initialized, because I *had* to put them at the top of
`main.cpp`, or else they wouldn't be global variables.
The only way to work around this was to use entityclass's initialization
style (which I'm pretty sure entityclass of all things doesn't need to
be initialized this way), where you actually initialize the class in an
`init()` function, and so then you do `graphics.init()` after the
filesystem initialization, AFTER doing `Graphics graphics` up at the
top.
I've had to do this for `graphics` (but only because its child
GraphicsResources `grphx` needs to be initialized this way), `music`,
and `game`. I don't think this will affect anything. Other than that,
`help`, `key`, and `map` are still using the C++-intended method of
having ClassName::ClassName() functions.
2020-01-29 08:35:03 +01:00
|
|
|
extern musicclass music;
|
2020-09-28 04:15:06 +02:00
|
|
|
#endif
|
2020-01-01 21:29:24 +01:00
|
|
|
|
|
|
|
#endif /* MUSIC_H */
|