/* * Copyright 2013 MicaByte Systems * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except * in compliance with the License. You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express * or implied. See the License for the specific language governing permissions and limitations under * the License. */ package com.micabytes.media; import android.content.Context; import android.media.MediaPlayer; import android.util.SparseArray; import com.micabytes.GameApplication; /** * MusicHandler is a simple, dumb wrapper around the Android MediaPlayer. It plays music files * placed in the raw resource directory. <p/> General usage: Start it in the onResume of an * activity, and stop the music in the onPause. release should be called in onDestroy of the root * activity. */ @SuppressWarnings({"UtilityClass", "unused", "WeakerAccess"}) public final class MusicHandler { private static final int INVALID_NUMBER = 0; private static final SparseArray<MediaPlayer> PLAYERS = new SparseArray<>(); private static final float VOLUME_MAX = 1.0f; private static final float DEFAULT_VOLUME = 0.25f; private static float volume = DEFAULT_VOLUME; private static int currentMusic = INVALID_NUMBER; private static int nextMusic = INVALID_NUMBER; private static int pausedMusic = INVALID_NUMBER; private static boolean mutedMusic = false; private MusicHandler() { // NOOP } /** * Start playing a music resource * * @param music The resource id of the music file */ public static void start(int music) { start(music, false); } /** * Start playing a music resource * @param music The resource id of the music file * @param forced Force the player to the front */ public static void start(int music, boolean forced) { if (currentMusic == music) { // already playing this music return; } if (shouldQueue(forced)) { queueMusic(music); return; } if (currentMusic != INVALID_NUMBER) { // playing some other music, pause it and change pause(); } currentMusic = music; MediaPlayer mp = PLAYERS.get(music); if (mp != null) { if (!mp.isPlaying()) { // Note: This continues the piece where it last let off mp.setLooping(true); mp.setOnCompletionListener(null); mp.start(); } } else { Context context = GameApplication.getInstance(); MediaPlayer mediaPlayer = MediaPlayer.create(context, music); if (mediaPlayer != null) { mediaPlayer.setVolume(mutedMusic ? 0.0f : volume, mutedMusic ? 0.0f : volume); PLAYERS.put(music, mediaPlayer); mediaPlayer.setLooping(true); mediaPlayer.setOnCompletionListener(null); mediaPlayer.start(); } } } // already playing some music and not forced to change immediately private static void queueMusic(int music) { if (music != INVALID_NUMBER) { nextMusic = music; MediaPlayer mp = PLAYERS.get(music); if (mp == null) { MediaPlayer mediaPlayer = MediaPlayer.create(GameApplication.getInstance(), music); if (mediaPlayer != null) PLAYERS.put(music, mediaPlayer); } MediaPlayer cp = PLAYERS.get(currentMusic); if (cp != null) { cp.setOnCompletionListener(new MediaPlayer.OnCompletionListener() { @Override public void onCompletion(MediaPlayer mp) { next(); } }); cp.setLooping(false); } } } public static boolean shouldQueue(boolean forced) { return !forced && currentMusic != INVALID_NUMBER; } /** * Pause all media PLAYERS */ public static void pause() { for (int i = 0; i < PLAYERS.size(); i++) { MediaPlayer p = PLAYERS.valueAt(i); if (p != null && p.isPlaying()) { p.pause(); } } pausedMusic = currentMusic; currentMusic = INVALID_NUMBER; } /** * Pause all media players */ public static void resume() { start(pausedMusic); pausedMusic = INVALID_NUMBER; } /** * Stop all media players */ private static void stop() { for (int i = 0; i < PLAYERS.size(); i++) { MediaPlayer p = PLAYERS.valueAt(i); if (p.isPlaying()) { p.stop(); } } currentMusic = INVALID_NUMBER; } /** * Advance to the next resource */ private static void next() { if (nextMusic == INVALID_NUMBER) { return; } currentMusic = nextMusic; nextMusic = INVALID_NUMBER; MediaPlayer p = PLAYERS.get(currentMusic); if (p != null) { if (!p.isPlaying()) { p.setLooping(true); p.setOnCompletionListener(null); p.setVolume(mutedMusic ? 0.0f : volume, mutedMusic ? 0.0f : volume); p.start(); } } } /** * Release the media players. */ public static void release() { for (int i = 0; i < PLAYERS.size(); i++) { MediaPlayer p = PLAYERS.valueAt(i); if (p.isPlaying()) { p.stop(); } p.release(); } PLAYERS.clear(); currentMusic = INVALID_NUMBER; } public static void setVolume(float v) { volume = v >= VOLUME_MAX ? VOLUME_MAX : v; if (mutedMusic) return; for (int i = 0; i < PLAYERS.size(); i++) { MediaPlayer p = PLAYERS.valueAt(i); p.setVolume(volume, volume); } } public static void mute(boolean isChecked) { mutedMusic = isChecked; if (mutedMusic) { for (int i = 0; i < PLAYERS.size(); i++) { MediaPlayer p = PLAYERS.valueAt(i); p.setVolume(0.0f, 0.0f); } } else { for (int i = 0; i < PLAYERS.size(); i++) { MediaPlayer p = PLAYERS.valueAt(i); p.setVolume(volume, volume); } } } public static int getCurrentMusic() { return currentMusic; } }