package com.quran.labs.androidquran.service.util; import android.content.Context; import android.os.Parcel; import android.os.Parcelable; import com.quran.labs.androidquran.data.QuranInfo; import com.quran.labs.androidquran.data.SuraAyah; import java.util.Locale; import timber.log.Timber; public abstract class AudioRequest implements Parcelable { private String baseUrl = null; private String gaplessDatabasePath = null; // where we started from private int ayahsInThisSura = 0; // min and max sura/ayah private int minSura; private int minAyah; private int maxSura; private int maxAyah; // what we're currently playing private int currentSura = 0; private int currentAyah = 0; // range repeat info private RepeatInfo rangeRepeatInfo; private boolean enforceBounds; // did we just play the basmallah? private boolean justPlayedBasmallah = false; // repeat information private RepeatInfo repeatInfo; public abstract boolean haveSuraAyah(int sura, int ayah); AudioRequest(String baseUrl, SuraAyah verse) { this.baseUrl = baseUrl; final int startSura = verse.sura; final int startAyah = verse.ayah; if (startSura < 1 || startSura > 114 || startAyah < 1) { throw new IllegalArgumentException(); } currentSura = startSura; currentAyah = startAyah; ayahsInThisSura = QuranInfo.SURA_NUM_AYAHS[currentSura - 1]; repeatInfo = new RepeatInfo(0); repeatInfo.setCurrentVerse(currentSura, currentAyah); rangeRepeatInfo = new RepeatInfo(0); } AudioRequest(Parcel in) { this.baseUrl = in.readString(); this.gaplessDatabasePath = in.readString(); this.ayahsInThisSura = in.readInt(); this.minSura = in.readInt(); this.minAyah = in.readInt(); this.maxSura = in.readInt(); this.maxAyah = in.readInt(); this.currentSura = in.readInt(); this.currentAyah = in.readInt(); this.rangeRepeatInfo = in.readParcelable(RepeatInfo.class.getClassLoader()); this.enforceBounds = in.readByte() != 0; this.justPlayedBasmallah = in.readByte() != 0; this.repeatInfo = in.readParcelable(RepeatInfo.class.getClassLoader()); } public boolean needsIsti3athaAudio() { // TODO base this check on a boolean array in readers.xml return !isGapless() || gaplessDatabasePath.contains("minshawi_murattal"); } public void setGaplessDatabaseFilePath(String databaseFile) { gaplessDatabasePath = databaseFile; } public String getGaplessDatabaseFilePath() { return gaplessDatabasePath; } public boolean isGapless() { return gaplessDatabasePath != null; } public void setVerseRepeatCount(int count) { repeatInfo.setRepeatCount(count); } public int getVerseRepeatCount() { return repeatInfo.getRepeatCount(); } public void setRangeRepeatCount(int rangeRepeatCount) { rangeRepeatInfo.setRepeatCount(rangeRepeatCount); } public void setEnforceBounds(boolean enforceBounds) { this.enforceBounds = enforceBounds; } public boolean shouldEnforceBounds() { return enforceBounds; } public int getRangeRepeatCount() { return rangeRepeatInfo.getRepeatCount(); } public SuraAyah getRangeStart() { return new SuraAyah(minSura, minAyah); } public SuraAyah getRangeEnd() { return new SuraAyah(maxSura, maxAyah); } public RepeatInfo getRepeatInfo() { return repeatInfo; } public SuraAyah setCurrentAyah(int sura, int ayah) { Timber.d("got setCurrentAyah of: %d:%d", sura, ayah); if (repeatInfo.shouldRepeat()) { repeatInfo.incrementRepeat(); } else { currentSura = sura; currentAyah = ayah; if (enforceBounds && ((currentSura == maxSura && currentAyah > maxAyah) || (currentSura > maxSura))) { if (rangeRepeatInfo.shouldRepeat()) { rangeRepeatInfo.incrementRepeat(); currentSura = minSura; currentAyah = minAyah; } else { return null; } } if (currentSura >= 1 && currentSura <= 114) { ayahsInThisSura = QuranInfo.SURA_NUM_AYAHS[currentSura - 1]; } repeatInfo.setCurrentVerse(currentSura, currentAyah); } return repeatInfo.getCurrentAyah(); } public String getBaseUrl() { return baseUrl; } public void setPlayBounds(SuraAyah minVerse, SuraAyah maxVerse) { minSura = minVerse.sura; minAyah = minVerse.ayah; maxSura = maxVerse.sura; maxAyah = maxVerse.ayah; } public SuraAyah getMinAyah() { return new SuraAyah(minSura, minAyah); } public SuraAyah getMaxAyah() { return new SuraAyah(maxSura, maxAyah); } public String getUrl() { if (enforceBounds && ((maxSura > 0 && currentSura > maxSura) || (maxAyah > 0 && currentAyah > maxAyah && currentSura >= maxSura) || (minSura > 0 && currentSura < minSura) || (minAyah > 0 && currentAyah < minAyah && currentSura <= minSura))) { return null; } if (currentSura > 114 || currentSura < 1) { return null; } if (isGapless()) { String url = String.format(Locale.US, baseUrl, currentSura); Timber.d("isGapless, url: %s", url); return url; } int sura = currentSura; int ayah = currentAyah; if (ayah == 1 && sura != 1 && sura != 9 && !justPlayedBasmallah) { justPlayedBasmallah = true; sura = 1; ayah = 1; } else { justPlayedBasmallah = false; } if (justPlayedBasmallah) { // really if "about to play" bismillah... if (!haveSuraAyah(currentSura, currentAyah)) { // if we don't have the first ayah, don't play basmallah return null; } } return String.format(Locale.US, baseUrl, sura, ayah); } public String getTitle(Context context) { return QuranInfo.getSuraAyahString(context, currentSura, currentAyah); } public int getCurrentSura() { return currentSura; } public int getCurrentAyah() { return currentAyah; } public boolean gotoNextAyah(boolean force) { // don't go to next ayah if we haven't played basmallah yet if (justPlayedBasmallah) { return false; } if (!force && repeatInfo.shouldRepeat()) { repeatInfo.incrementRepeat(); if (currentAyah == 1 && currentSura != 1 && currentSura != 9) { justPlayedBasmallah = true; } return false; } if (enforceBounds && ((currentSura > maxSura) || (currentAyah >= maxAyah && currentSura == maxSura))) { if (rangeRepeatInfo.shouldRepeat()) { rangeRepeatInfo.incrementRepeat(); currentSura = minSura; currentAyah = minAyah; repeatInfo.setCurrentVerse(currentSura, currentAyah); return true; } } currentAyah++; if (ayahsInThisSura < currentAyah) { currentAyah = 1; currentSura++; if (currentSura <= 114) { ayahsInThisSura = QuranInfo.SURA_NUM_AYAHS[currentSura - 1]; repeatInfo.setCurrentVerse(currentSura, currentAyah); } } else { repeatInfo.setCurrentVerse(currentSura, currentAyah); } return true; } public void gotoPreviousAyah() { currentAyah--; if (currentAyah < 1) { currentSura--; if (currentSura > 0) { ayahsInThisSura = QuranInfo.SURA_NUM_AYAHS[currentSura - 1]; currentAyah = ayahsInThisSura; } } else if (currentAyah == 1 && !isGapless()) { justPlayedBasmallah = true; } if (currentSura > 0 && currentAyah > 0) { repeatInfo.setCurrentVerse(currentSura, currentAyah); } } @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel dest, int flags) { dest.writeString(this.baseUrl); dest.writeString(this.gaplessDatabasePath); dest.writeInt(this.ayahsInThisSura); dest.writeInt(this.minSura); dest.writeInt(this.minAyah); dest.writeInt(this.maxSura); dest.writeInt(this.maxAyah); dest.writeInt(this.currentSura); dest.writeInt(this.currentAyah); dest.writeParcelable(this.rangeRepeatInfo, 0); dest.writeByte(enforceBounds ? (byte) 1 : (byte) 0); dest.writeByte(justPlayedBasmallah ? (byte) 1 : (byte) 0); dest.writeParcelable(this.repeatInfo, 0); } }