1 module d2d.audio.music; 2 3 version(BindSDL_Mixer): 4 5 import d2d; 6 7 /// 1.0 / MIX_MAX_VOLUME 8 enum INV_MIX_MAX_VOLUME = 1.0f / MIX_MAX_VOLUME; 9 10 /// 11 enum FadingStatus : ubyte 12 { 13 /// 14 NoFading = MIX_NO_FADING, 15 /// 16 FadingOut = MIX_FADING_OUT, 17 /// 18 FadingIn = MIX_FADING_IN, 19 } 20 21 /// 22 enum MusicType : ubyte 23 { 24 /// 25 CommandBased = MUS_CMD, 26 /// 27 Wav = MUS_WAV, 28 /// 29 Mod = MUS_MOD, 30 /// 31 ModPlug = MUS_MODPLUG, 32 /// 33 Mid = MUS_MID, 34 /// 35 Ogg = MUS_OGG, 36 /// 37 Mp3 = MUS_MP3, 38 /// 39 Mp3Mad = MUS_MP3_MAD, 40 /// 41 None = MUS_NONE, 42 } 43 44 /// Thin wrap around Mix_Music including loading [FLAC, MikMod, Ogg Vorbis, MP3, Wav] using SDL_Mixer. 45 class Music : IVerifiable, IDisposable 46 { 47 private Mix_Music* _handle; 48 49 /// Handle to the `Mix_Music*`. 50 public @property Mix_Music* handle() 51 { 52 return _handle; 53 } 54 55 /// Checks if the handle is not null. 56 public @property bool valid() 57 { 58 return _handle !is null; 59 } 60 61 private this(Mix_Music * handle) 62 { 63 _handle = handle; 64 } 65 66 /// Loads a music file 67 public this(string path) 68 { 69 _handle = Mix_LoadMUS(path.toStringz()); 70 } 71 72 public ~this() 73 { 74 dispose(); 75 } 76 77 /// Creates music from a `Mix_Music*`. 78 public static Music fromMusic(Mix_Music* handle) 79 { 80 return new Music(handle); 81 } 82 83 public static bool load() 84 { 85 return Mix_OpenAudio(44_100, MIX_DEFAULT_FORMAT, 2, 4096) == 0; 86 } 87 88 /// Returns the latest sound related error 89 public static @property string error() 90 { 91 return cast(string) Mix_GetError().fromStringz(); 92 } 93 94 /// Deallocates the memory and invalidates `this`. 95 public void dispose() 96 { 97 if (valid) 98 { 99 stop(); 100 Mix_FreeMusic(_handle); 101 _handle = null; 102 } 103 } 104 105 /// Plays this music, will stop other musics. -1 loops will play forever. 106 /// Returns: true on success, or false on errors 107 public bool play(int loops = 1) 108 { 109 return Mix_PlayMusic(_handle, loops) == 0; 110 } 111 112 /// Starts this music by fading in over `ms` milliseconds, will stop other musics. -1 loops will play forever. 113 /// Params: 114 /// ms = Milliseconds for the fade-in effect to complete. 115 /// loops = -1 loops will play forever. 0 plays the music zero times. 116 /// Returns: true on success, or false on errors 117 public bool fadeIn(int ms, int loops = 1) 118 { 119 return Mix_FadeInMusic(_handle, loops, ms) == 0; 120 } 121 122 /// Starts this music by fading in over `ms` milliseconds, will stop other musics. 123 /// Params: 124 /// ms = Milliseconds for the fade-in effect to complete. 125 /// loops = -1 loops will play forever. 0 plays the music zero times. 126 /// position = Set the position of the currently playing music. The position takes different meanings for different music sources. It only works on the music sources listed below. 127 /// <b>MOD</b> 128 /// The double is cast to Uint16 and used for a pattern number in the module. Passing zero is similar to rewinding the song. 129 /// <b>OGG/MP3</b> 130 /// Jumps to position seconds from the beginning of the song. 131 /// Returns: true on success, or false on errors 132 public bool fadeIn(int ms, int loops, double position) 133 { 134 return Mix_FadeInMusicPos(_handle, loops, ms, position) == 0; 135 } 136 137 /// 138 public @property MusicType type() 139 { 140 return cast(MusicType) Mix_GetMusicType(_handle); 141 } 142 143 /// Modifies the position where currently playing. 144 /// Params: 145 /// value = Set the position of the currently playing music. The position takes different meanings for different music sources. It only works on the music sources listed below. Will automatically rewind before setting. 146 /// <b>MOD</b> 147 /// The double is cast to Uint16 and used for a pattern number in the module. Passing zero is similar to rewinding the song. 148 /// <b>OGG/MP3</b> 149 /// Jumps to position seconds from the beginning of the song. 150 /// Returns: true on success, or false if the codec doesn't support this function 151 public static @property bool position(double value) 152 { 153 Mix_RewindMusic(); 154 return Mix_SetMusicPosition(value) == 0; 155 } 156 157 /// Rewinds music to the start. This is safe to use on halted, paused, and already playing music. It is not useful to rewind the music immediately after starting playback, because it starts at the beginning by default. 158 public static void rewind() 159 { 160 Mix_RewindMusic(); 161 } 162 163 /// Halt playback of music. This interrupts music fader effects. 164 public static void stop() 165 { 166 Mix_RewindMusic(); 167 } 168 169 /// Pause the music playback. You may halt paused music. 170 /// Note: Music can only be paused if it is actively playing. 171 public static void pause() 172 { 173 Mix_PauseMusic(); 174 } 175 176 /// Unpause the music. This is safe to use on halted, paused, and already playing music. 177 public static void resume() 178 { 179 Mix_ResumeMusic(); 180 } 181 182 /// Returns the current volume as float in range 0.0 to 1.0 183 public static @property float volume() 184 { 185 return Mix_VolumeMusic(-1) * INV_MIX_MAX_VOLUME; 186 } 187 188 /// Sets the current volume as float in range 0.0 to 1.0 189 public static @property void volume(float value) 190 { 191 Mix_VolumeMusic(cast(int) (value * MIX_MAX_VOLUME)); 192 } 193 194 /// 195 public static @property bool isPlaying() 196 { 197 return Mix_PlayingMusic() == 1; 198 } 199 200 /// 201 public static @property bool isPaused() 202 { 203 return Mix_PausedMusic() == 1; 204 } 205 206 /// 207 public static @property FadingStatus fadingStatus() 208 { 209 return cast(FadingStatus) Mix_FadingMusic(); 210 } 211 }