SDL_mixer: Implemented the master volume feature.

From 131cba9aa0135b2d00acbcb0083d7666b802412d Mon Sep 17 00:00:00 2001
From: Mykola Rubets <[EMAIL REDACTED]>
Date: Tue, 17 May 2022 12:59:35 +0300
Subject: [PATCH] Implemented the master volume feature.

---
 include/SDL_mixer.h |  6 ++++++
 src/mixer.c         | 20 ++++++++++++++++++--
 src/music.c         |  6 +++---
 3 files changed, 27 insertions(+), 5 deletions(-)

diff --git a/include/SDL_mixer.h b/include/SDL_mixer.h
index c508956a..025d11f4 100644
--- a/include/SDL_mixer.h
+++ b/include/SDL_mixer.h
@@ -590,6 +590,12 @@ extern DECLSPEC int SDLCALL Mix_VolumeMusic(int volume);
 /* Get the current volume value in the range of 0-128 of a music stream */
 extern DECLSPEC int SDLCALL Mix_GetMusicVolume(Mix_Music *music);
 
+/* Set the master volume.
+   This did not affect the member variables of music, channel or chunck volume.
+   If the specified volume is -1, just return the current master volume.
+*/
+extern DECLSPEC int SDLCALL Mix_MasterVolume(int volume);
+
 /* Halt playing of a particular channel */
 extern DECLSPEC int SDLCALL Mix_HaltChannel(int channel);
 extern DECLSPEC int SDLCALL Mix_HaltGroup(int tag);
diff --git a/src/mixer.c b/src/mixer.c
index cee3b31f..1ebf0cc1 100644
--- a/src/mixer.c
+++ b/src/mixer.c
@@ -110,6 +110,7 @@ static void *music_data = NULL;
 static const char **chunk_decoders = NULL;
 static int num_decoders = 0;
 
+static int master_volume = MIX_MAX_VOLUME;
 
 int Mix_GetNumChunkDecoders(void)
 {
@@ -277,7 +278,7 @@ static void SDLCALL
 mix_channels(void *udata, Uint8 *stream, int len)
 {
     Uint8 *mix_input;
-    int i, mixable, volume = MIX_MAX_VOLUME;
+    int i, mixable, volume = master_volume = Mix_MasterVolume(-1);
     Uint32 sdl_ticks;
 
     (void)udata;
@@ -326,7 +327,7 @@ mix_channels(void *udata, Uint8 *stream, int len)
                 int remaining = len;
                 while (mix_channel[i].playing > 0 && index < len) {
                     remaining = len - index;
-                    volume = (mix_channel[i].volume*mix_channel[i].chunk->volume) / MIX_MAX_VOLUME;
+                    volume = (master_volume * (mix_channel[i].volume * mix_channel[i].chunk->volume)) / (MIX_MAX_VOLUME * MIX_MAX_VOLUME);
                     mixable = mix_channel[i].playing;
                     if (mixable > remaining) {
                         mixable = remaining;
@@ -1640,6 +1641,21 @@ void Mix_UnlockAudio(void)
     SDL_UnlockAudioDevice(audio_device);
 }
 
+int Mix_MasterVolume(int volume)
+{
+    int prev_volume;
+
+    prev_volume = master_volume;
+    if (volume < 0) {
+        return prev_volume;
+    }
+    if (volume > SDL_MIX_MAXVOLUME) {
+        volume = SDL_MIX_MAXVOLUME;
+    }
+    master_volume = volume;
+    return(prev_volume);
+}
+
 /* end of mixer.c ... */
 
 /* vi: set ts=4 sw=4 expandtab: */
diff --git a/src/music.c b/src/music.c
index 881ca3cf..b3bddfdb 100644
--- a/src/music.c
+++ b/src/music.c
@@ -316,14 +316,14 @@ void SDLCALL music_mixer(void *udata, Uint8 *stream, int len)
         /* Handle fading */
         if (music_playing->fading != MIX_NO_FADING) {
             if (music_playing->fade_step++ < music_playing->fade_steps) {
-                int volume;
+                int volume = Mix_MasterVolume(-1);
                 int fade_step = music_playing->fade_step;
                 int fade_steps = music_playing->fade_steps;
 
                 if (music_playing->fading == MIX_FADING_OUT) {
-                    volume = (music_volume * (fade_steps-fade_step)) / fade_steps;
+                    volume = (volume * (music_volume * (fade_steps-fade_step))) / (fade_steps * MIX_MAX_VOLUME);
                 } else { /* Fading in */
-                    volume = (music_volume * fade_step) / fade_steps;
+                    volume = (volume * (music_volume * fade_step)) / (fade_steps * MIX_MAX_VOLUME);
                 }
                 music_internal_volume(volume);
             } else {