Java tutorial
/******************************************************************************* * Copyright (C) 2014 xperia64 <xperiancedapps@gmail.com> * * Copyright (C) 1999-2008 Masanao Izumo <iz@onicos.co.jp> * * Copyright (C) 1995 Tuukka Toivonen <tt@cgs.fi> * All rights reserved. This program and the accompanying materials * are made available under the terms of the GNU Public License v3.0 * which accompanies this distribution, and is available at * http://www.gnu.org/licenses/gpl.html ******************************************************************************/ package com.xperia64.timidityae; import java.io.BufferedReader; import java.io.DataInputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.FileWriter; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.lang.reflect.Field; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; import java.util.ArrayList; import java.util.Locale; import javax.net.ssl.HttpsURLConnection; import com.xperia64.timidityae.R; import android.annotation.SuppressLint; import android.annotation.TargetApi; import android.app.Activity; import android.app.ProgressDialog; import android.content.Context; import android.content.DialogInterface; import android.content.SharedPreferences; import android.content.SharedPreferences.Editor; import android.content.res.AssetManager; import android.graphics.Bitmap; import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; import android.media.AudioFormat; import android.media.AudioTrack; import android.net.Uri; import android.os.AsyncTask; import android.os.Build; import android.os.Environment; import android.os.PowerManager; import android.preference.PreferenceManager; import android.support.v4.provider.DocumentFile; import android.util.Log; import android.util.SparseIntArray; import android.widget.TextView; import android.widget.Toast; public class Globals { public static boolean libLoaded = false; public static int isPlaying = 1; // Active low. public static ArrayList<String> plist; // Because arguments don't like big things. public static ArrayList<String> tmpplist; // I'm lazy. public static Bitmap currArt; public static boolean hardStop = false; public static final String autoSoundfontHeader = "#<--------Config Generated By Timidity AE (DO NOT MODIFY)-------->"; // Fragment Keys public static String currFoldKey = "CURRENT_FOLDER"; public static String currPlistDirectory = "CURRENT_PLIST_DIR"; public static boolean shouldRestore = false; // Resampling Algorithms public static String[] sampls = { "Cubic Spline", "Lagrange", "Gaussian", "Newton", "Linear", "None" }; // File filters public static String musicFiles = "*.mid*.smf*.kar*.mod*.xm*.s3m*.it*.669*.amf*.dsm*.far*.gdm*.imf*.med*.mtm*.stm*.stx*.ult*.uni*.mp3*.m4a*.wav*.ogg*.flac*"; public static String musicVideoFiles = musicFiles + ".mp4*.3gp*"; public static String playlistFiles = "*.tpl*"; public static String configFiles = "*.tcf*.tzf*"; public static String fontFiles = "*.sf2*.sfark*.sfark.exe*"; public static ArrayList<String> knownWritablePaths = new ArrayList<String>(); public static ArrayList<String> knownUnwritablePaths = new ArrayList<String>(); public static int defaultListColor = -1; @SuppressLint("NewApi") public static int getBackgroundColor(TextView textView) { Drawable drawable = textView.getBackground(); if (drawable instanceof ColorDrawable) { ColorDrawable colorDrawable = (ColorDrawable) drawable; if (Build.VERSION.SDK_INT >= 11) { return colorDrawable.getColor(); } try { Field field = colorDrawable.getClass().getDeclaredField("mState"); field.setAccessible(true); Object object = field.get(colorDrawable); field = object.getClass().getDeclaredField("mUseColor"); field.setAccessible(true); return field.getInt(object); } catch (NoSuchFieldException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } } return 0; } @SuppressLint({ "NewApi", "SdCardPath" }) public static File getExternalCacheDir(Context c) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.FROYO) { return c.getExternalCacheDir(); } else { return new File("/sdcard/Android/data/com.xperia64.timidityae/cache/"); } } @SuppressLint({ "NewApi", "SdCardPath" }) public static String getLibDir(Context c) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) { String s = c.getApplicationInfo().nativeLibraryDir; if (!s.endsWith(File.separator)) { s += "/"; } return s; } else { return "/data/data/com.xperia64.timidityae/lib/"; } } public static int[] validRates(boolean stereo, boolean sixteen) { ArrayList<Integer> valid = new ArrayList<Integer>(); for (int rate : new int[] { 8000, 11025, 16000, 22050, 44100, 48000, 88200, 96000 }) { int bufferSize = AudioTrack.getMinBufferSize(rate, (stereo) ? AudioFormat.CHANNEL_OUT_STEREO : AudioFormat.CHANNEL_OUT_MONO, (sixteen) ? AudioFormat.ENCODING_PCM_16BIT : AudioFormat.ENCODING_PCM_8BIT); if (bufferSize > 0) { //System.out.println(rate+" "+bufferSize); // buffer size is valid, Sample rate supported valid.add(rate); } } int[] rates = new int[valid.size()]; for (int i = 0; i < rates.length; i++) rates[i] = valid.get(i); return rates; } /*public static boolean canWrite(String path) { if(!path.endsWith("/")) { return false; } if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.LOLLIPOP) { Random r = new Random(); // Generate a random unique temporary file. File f = new File(path+r.nextInt(1000000)); while(f.exists()) { f = new File(path+r.nextInt(1000000)); try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } } try { f.createNewFile(); } catch (IOException e) { return false; } if(f.exists()) f.delete(); return true; }else{ return new File(path).canWrite(); } }*/ /*public static boolean canWrite(DocumentFile path) { return false; }*/ public static SparseIntArray validBuffers(int[] rates, boolean stereo, boolean sixteen) { SparseIntArray buffers = new SparseIntArray(); for (int rate : rates) { buffers.put(rate, AudioTrack.getMinBufferSize(rate, (stereo) ? AudioFormat.CHANNEL_OUT_STEREO : AudioFormat.CHANNEL_OUT_MONO, (sixteen) ? AudioFormat.ENCODING_PCM_16BIT : AudioFormat.ENCODING_PCM_8BIT)); } return buffers; /*HashMap<Integer, Integer> buffers = new HashMap<Integer, Integer>(); for(int rate : rates) { buffers.put(rate, AudioTrack.getMinBufferSize(rate, (stereo)?AudioFormat.CHANNEL_OUT_STEREO:AudioFormat.CHANNEL_OUT_MONO, (sixteen)?AudioFormat.ENCODING_PCM_16BIT:AudioFormat.ENCODING_PCM_8BIT)); } return buffers;*/ } public static int probablyFresh = 0; //---------SETTINGS STORAGE---------- public static SharedPreferences prefs; public static boolean firstRun; public static int theme; // 1 = Light, 2 = Dark public static boolean showHiddenFiles; public static String defaultFolder; public static String dataFolder; public static boolean manConfig; public static int defSamp; public static boolean shouldLolNag; //public static ArrayList<String> soundfonts; // this list should only be touched in SettingsActivity public static int mono; // 0 = stereo downsampled to mono, 1 = timidity-synthesized mono, 2 = stereo, 3 = downsampled to mono then copied to stereo? public static boolean sixteen; public static int aRate; public static int buff; public static boolean nativeMidi; public static boolean keepWav; public static boolean onlyNative = false; public static boolean showVideos; public static boolean useDefaultBack = false; public static boolean compressCfg = true; //public static AssetManager assets; public static boolean nukedWidgets = false; public static Uri theFold = null; public static boolean reShuffle = false; public static boolean preserveSilence = true; public static boolean freeInsts = true; public static void reloadSettings(Activity c, AssetManager assets) { prefs = PreferenceManager.getDefaultSharedPreferences(c); firstRun = prefs.getBoolean("tplusFirstRun", true); theme = Integer.parseInt(prefs.getString("fbTheme", "1")); showHiddenFiles = prefs.getBoolean("hiddenSwitch", false); defaultFolder = prefs.getString("defaultPath", Environment.getExternalStorageDirectory().getAbsolutePath()); dataFolder = prefs.getString("dataDir", Environment.getExternalStorageDirectory() + "/TimidityAE/"); manConfig = prefs.getBoolean("manualConfig", false); JNIHandler.currsamp = defSamp = Integer.parseInt(prefs.getString("tplusResamp", "0")); mono = Integer.parseInt(prefs.getString("sdlChanValue", "2")); sixteen = true;//prefs.getString("tplusBits", "16").equals("16"); aRate = Integer.parseInt(prefs.getString("tplusRate", Integer.toString(AudioTrack.getNativeOutputSampleRate(AudioTrack.MODE_STREAM)))); buff = Integer.parseInt(prefs.getString("tplusBuff", "192000")); showVideos = prefs.getBoolean("videoSwitch", true); shouldLolNag = prefs.getBoolean("shouldLolNag", true); keepWav = prefs.getBoolean("keepPartialWav", false); useDefaultBack = prefs.getBoolean("useDefBack", false); compressCfg = prefs.getBoolean("compressCfg", true); reShuffle = prefs.getBoolean("reShuffle", false); freeInsts = prefs.getBoolean("tplusUnload", true); preserveSilence = prefs.getBoolean("tplusSilKey", true); if (!onlyNative) nativeMidi = prefs.getBoolean("nativeMidiSwitch", false); else nativeMidi = true; } //----------------------------------- public static boolean isMidi(String songTitle) { return !(songTitle.toLowerCase(Locale.US).endsWith(".mp3") || songTitle.toLowerCase(Locale.US).endsWith(".m4a") || songTitle.toLowerCase(Locale.US).endsWith(".wav") || songTitle.toLowerCase(Locale.US).endsWith(".ogg") || songTitle.toLowerCase(Locale.US).endsWith(".flac") || songTitle.toLowerCase(Locale.US).endsWith(".mp4") || songTitle.toLowerCase(Locale.US).endsWith(".3gp") || (Globals.nativeMidi && (songTitle.toLowerCase(Locale.US).endsWith(".mid") || songTitle.toLowerCase(Locale.US).endsWith(".kar") || songTitle.toLowerCase(Locale.US).endsWith(".smf")))); } public static boolean initialize(final Activity a) { if (firstRun) { final File rootStorage = new File( Environment.getExternalStorageDirectory().getAbsolutePath() + "/TimidityAE/"); if (!rootStorage.exists()) { rootStorage.mkdir(); } File playlistDir = new File(rootStorage.getAbsolutePath() + "/playlists/"); if (!playlistDir.exists()) { playlistDir.mkdir(); } File tcfgDir = new File(rootStorage.getAbsolutePath() + "/timidity/"); if (!tcfgDir.exists()) { tcfgDir.mkdir(); } File sfDir = new File(rootStorage.getAbsolutePath() + "/soundfonts/"); if (!sfDir.exists()) { sfDir.mkdir(); } updateBuffers(updateRates()); aRate = Integer.parseInt(prefs.getString("tplusRate", Integer.toString(AudioTrack.getNativeOutputSampleRate(AudioTrack.MODE_STREAM)))); buff = Integer.parseInt(prefs.getString("tplusBuff", "192000")); // This is usually a safe number, but should probably do a test or something migrateFrom1X(rootStorage); final Editor eee = prefs.edit(); firstRun = false; eee.putBoolean("tplusFirstRun", false); eee.putString("dataDir", Environment.getExternalStorageDirectory().getAbsolutePath() + "/TimidityAE/"); if (new File(dataFolder + "/timidity/timidity.cfg").exists()) { if (manConfig = !cfgIsAuto(dataFolder + "/timidity/timidity.cfg")) { eee.putBoolean("manConfig", true); } else { eee.putBoolean("manConfig", false); ArrayList<String> soundfonts = new ArrayList<String>(); FileInputStream fstream = null; try { fstream = new FileInputStream(dataFolder + "/timidity/timidity.cfg"); } catch (FileNotFoundException e) { e.printStackTrace(); } // Get the object of DataInputStream DataInputStream in = new DataInputStream(fstream); BufferedReader br = new BufferedReader(new InputStreamReader(in)); //Read File Line By Line try { br.readLine(); // skip first line } catch (IOException e) { e.printStackTrace(); } String line; try { while ((line = br.readLine()) != null) { if (line.indexOf("soundfont \"") >= 0 && line.lastIndexOf('"') >= 0) { try { String st = line.substring(line.indexOf("soundfont \"") + 11, line.lastIndexOf('"')); soundfonts.add(st); } catch (ArrayIndexOutOfBoundsException e1) { e1.printStackTrace(); } } } } catch (IOException e) { e.printStackTrace(); } try { in.close(); } catch (IOException e) { e.printStackTrace(); } try { eee.putString("tplusSoundfonts", ObjectSerializer.serialize(soundfonts)); } catch (IOException e) { e.printStackTrace(); } } eee.commit(); return true; } else { // Should probably check if 8rock11e exists no matter what eee.putBoolean("manConfig", false); AsyncTask<Void, Void, Void> task = new AsyncTask<Void, Void, Void>() { ProgressDialog pd; @Override protected void onPreExecute() { pd = new ProgressDialog(a); pd.setTitle(a.getResources().getString(R.string.extract)); pd.setMessage(a.getResources().getString(R.string.extract_sum)); pd.setCancelable(false); pd.setIndeterminate(true); pd.show(); } @Override protected Void doInBackground(Void... arg0) { if (extract8Rock(a) != 777) { Toast.makeText(a, "Could not extrct default soundfont", Toast.LENGTH_SHORT).show(); } return null; } @Override protected void onPostExecute(Void result) { if (pd != null) pd.dismiss(); ArrayList<String> tmpConfig = new ArrayList<String>(); tmpConfig.add(rootStorage.getAbsolutePath() + "/soundfonts/8Rock11e.sf2"); try { eee.putString("tplusSoundfonts", ObjectSerializer.serialize(tmpConfig)); } catch (IOException e) { e.printStackTrace(); } eee.commit(); writeCfg(a, rootStorage.getAbsolutePath() + "/timidity/timidity.cfg", tmpConfig); ((TimidityActivity) a).initCallback(); } }; task.execute((Void[]) null); return false; } } else { return true; } } public static void migrateFrom1X(File newData) { File oldPlists = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/Android/data/com.xperia64.timidityae/playlists/"); if (oldPlists.exists()) { if (oldPlists.isDirectory()) { for (File f : oldPlists.listFiles()) { if (f.getName().toLowerCase(Locale.US).endsWith(".tpl")) { f.renameTo(new File(newData.getAbsolutePath() + "/playlists/" + f.getName())); } } } } File oldSoundfonts = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/Android/data/com.xperia64.timidityae/soundfonts/"); if (oldSoundfonts.exists()) { if (oldSoundfonts.isDirectory()) { for (File f : oldSoundfonts.listFiles()) { if (f.getName().toLowerCase(Locale.US).endsWith(".sf2") || f.getName().toLowerCase(Locale.US).endsWith(".sfark")) { f.renameTo(new File(newData.getAbsolutePath() + "/soundfonts/" + f.getName())); } } } } } public static void writeCfg(Context c, String path, ArrayList<String> soundfonts) { if (path == null) { Toast.makeText(c, "Configuration path null (3)", Toast.LENGTH_LONG).show(); return; } if (soundfonts == null) { Toast.makeText(c, "Soundfonts null (4)", Toast.LENGTH_LONG).show(); return; } if (path.contains("//")) { path = path.replace("//", "/"); } if (!manConfig) { String[] needLol = null; try { new FileOutputStream(path, true).close(); } catch (FileNotFoundException e) { needLol = getDocFilePaths(c, path); } catch (IOException e) { e.printStackTrace(); } if (needLol != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { if (theFold != null) { String probablyTheDirectory = needLol[0]; String probablyTheRoot = needLol[1]; String needRename = null; String value = null; if (probablyTheDirectory.length() > 1) { needRename = path.substring(path.indexOf(probablyTheRoot) + probablyTheRoot.length()); value = probablyTheDirectory + path.substring(path.lastIndexOf('/')); } else { return; } if (new File(path).exists()) { if (cfgIsAuto(path) || new File(path).length() <= 0) { Globals.tryToDeleteFile(c, path); } else { Toast.makeText(c, "Renaming manually edited cfg... (7)", Toast.LENGTH_LONG).show(); renameDocumentFile(c, path, needRename + ".manualTimidityCfg." + Long.toString(System.currentTimeMillis())); } } FileWriter fw = null; try { fw = new FileWriter(value, false); } catch (IOException e) { e.printStackTrace(); } try { fw.write(autoSoundfontHeader + "\n"); } catch (IOException e) { e.printStackTrace(); } for (String s : soundfonts) { try { fw.write((s.startsWith("#") ? "#" : "") + "soundfont \"" + s + "\"\n"); } catch (IOException e) { e.printStackTrace(); } } try { fw.close(); } catch (IOException e) { e.printStackTrace(); } Globals.renameDocumentFile(c, value, needRename); } else { Toast.makeText(c, "Could not write configuration file. Does Timidity AE have write access to the data folder? (1)", Toast.LENGTH_LONG).show(); } } else { File theConfig = new File(path); if (theConfig.exists()) // It should exist if we got here. { if (!theConfig.canWrite()) { Toast.makeText(c, "Could not write configuration file. Does Timidity AE have write access to the data folder? (2)", Toast.LENGTH_LONG).show(); return; } if (cfgIsAuto(path) || theConfig.length() <= 0) // Negative file length? Who knows. { theConfig.delete(); // Auto config, safe to delete } else { Toast.makeText(c, "Renaming manually edited cfg... (6)", Toast.LENGTH_LONG).show(); theConfig.renameTo( new File(path + ".manualTimidityCfg." + Long.toString(System.currentTimeMillis()))); // manual config, rename for later } } FileWriter fw = null; try { fw = new FileWriter(path, false); } catch (IOException e) { e.printStackTrace(); } try { fw.write(autoSoundfontHeader + "\n"); } catch (IOException e) { e.printStackTrace(); } for (String s : soundfonts) { if (s == null) continue; try { fw.write((s.startsWith("#") ? "#" : "") + "soundfont \"" + s + "\"\n"); } catch (IOException e) { e.printStackTrace(); } } try { fw.close(); } catch (IOException e) { e.printStackTrace(); } } } } @SuppressLint("NewApi") public static String[] getDocFilePaths(Context c, String parent) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) return null; // Error. parent = parent.replace("//", "/"); String probablyTheDirectory = ""; String probablyTheRoot = ""; File par = new File(parent); String absp = par.getAbsolutePath(); File[] x = c.getExternalFilesDirs(null); for (File f : x) { if (f != null) { String ex = f.getAbsolutePath(); String ss1; String ss2; int lastmatch = 1; while (lastmatch < absp.length() && lastmatch < ex.length()) { ss1 = ex.substring(0, lastmatch + 1); ss2 = absp.substring(0, lastmatch + 1); if (ss1.equals(ss2)) { lastmatch++; } else { break; } } String theRoot = absp.substring(0, lastmatch); if (theRoot.equals("/storage/") || theRoot.equals("/mnt/")) { continue; } else { probablyTheDirectory = ex; probablyTheRoot = theRoot; break; } } } String[] rets = new String[2]; rets[0] = probablyTheDirectory; rets[1] = probablyTheRoot; return rets; } public static boolean renameDocumentFile(Context c, String from, String subTo) { // From is the full path // subTo is the path without the device prefix. // So /storage/sdcard1/folder/file.mid should be folder/file.mid if (theFold == null) return false; from = from.replace("//", "/"); subTo = subTo.replace("//", "/"); DocumentFile df = DocumentFile.fromTreeUri(c, theFold); String split[] = from.split("/"); int i; for (i = 0; i < split.length; i++) { if (split[i].equals(df.getName())) { i++; break; } } DocumentFile xx = df; StringBuilder upper = new StringBuilder(); while (i < split.length) { xx = xx.findFile(split[i++]); upper.append("../"); if (xx == null) { Log.e("TimidityAE Globals", "Rename file error."); break; } } if (xx != null && upper.length() > 3) { return xx.renameTo(upper.substring(0, upper.length() - 3) + subTo); } return false; } public static void tryToDeleteFile(Context c, String filename) { filename = filename.replace("//", "/"); if (new File(filename).exists()) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && Globals.theFold != null) { DocumentFile df = DocumentFile.fromTreeUri(c, theFold); String split[] = filename.split("/"); int i; for (i = 0; i < split.length; i++) { if (split[i].equals(df.getName())) { i++; break; } } DocumentFile xx = df; while (i < split.length) { xx = xx.findFile(split[i++]); //upper.append("../"); if (xx == null) { Log.e("TimidityAE Globals", "Delete file error."); break; } } // Why on earth is DocumentFile's delete method recursive by default? // Seriously. I wiped my sd card twice because of this. if (xx != null && xx.isFile() && !xx.isDirectory()) { xx.delete(); } } else { new File(filename).delete(); } } } public static void tryToCreateFile(Context c, String filename) { filename = filename.replace("//", "/"); if (!(new File(filename).exists())) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && theFold != null) { DocumentFile df = DocumentFile.fromTreeUri(c, theFold); String split[] = filename.split("/"); int i; for (i = 0; i < split.length; i++) { if (split[i].equals(df.getName())) { i++; break; } } DocumentFile xx = df; while (i < split.length - 1) { xx = xx.findFile(split[i++]); if (xx == null) { Log.e("TimidityAE Globals", "Create file error."); break; } } if (xx != null) { xx.createFile("timidityae/tpl", split[split.length - 1]); } } else { try { new File(filename).createNewFile(); } catch (IOException e) { e.printStackTrace(); } } } } public static boolean cfgIsAuto(String path) { String firstLine = ""; try { FileInputStream fstream = new FileInputStream(path); DataInputStream in = new DataInputStream(fstream); BufferedReader br = new BufferedReader(new InputStreamReader(in)); firstLine = br.readLine(); in.close(); } catch (Exception e) { } if (firstLine != null) return firstLine.contains(autoSoundfontHeader); return false; } public static int[] updateRates() { if (prefs != null) { int[] values = Globals.validRates(prefs.getString("sdlChanValue", "2").equals("2"), /*prefs.getString("tplusBits", "16").equals("16")*/true); CharSequence[] hz = new CharSequence[values.length]; CharSequence[] hzItems = new CharSequence[values.length]; boolean validRate = false; for (int i = 0; i < values.length; i++) { hz[i] = Integer.toString(values[i]) + "Hz"; hzItems[i] = Integer.toString(values[i]); if (prefs .getString("tplusRate", Integer.toString(AudioTrack.getNativeOutputSampleRate(AudioTrack.MODE_STREAM))) .equals(hzItems[i])) { validRate = true; break; } } if (!validRate) prefs.edit() .putString("tplusRate", Integer.toString(AudioTrack.getNativeOutputSampleRate(AudioTrack.MODE_STREAM))) .commit(); return values; } return null; } public static boolean updateBuffers(int[] rata) { if (rata != null) { SparseIntArray buffMap = Globals.validBuffers(rata, prefs.getString("sdlChanValue", "2").equals("2"), true/*prefs.getString("tplusBits", "16").equals("16")*/); int realMin = buffMap.get(Integer.parseInt(prefs.getString("tplusRate", Integer.toString(AudioTrack.getNativeOutputSampleRate(AudioTrack.MODE_STREAM))))); if (buff < realMin) { prefs.edit().putString("tplusBuff", Integer.toString(buff = realMin)).commit(); return false; } } return true; } public static int extract8Rock(Context c) { InputStream in = null; try { in = c.getAssets().open("8Rock11e.sfArk"); } catch (IOException e) { e.printStackTrace(); } String[] needLol = null; try { new FileOutputStream(Globals.dataFolder + "/soundfonts/8Rock11e.sfArk", true).close(); } catch (FileNotFoundException e) { needLol = getDocFilePaths(c, Globals.dataFolder); } catch (IOException e) { e.printStackTrace(); } if (needLol != null) { File f = new File(Globals.dataFolder + "/soundfonts/8Rock11e.sfArk"); if (f != null) if (f.exists()) tryToDeleteFile(c, Globals.dataFolder + "/soundfonts/8Rock11e.sfArk"); OutputStream out = null; String probablyTheDirectory = needLol[0]; String probablyTheRoot = needLol[1]; String needRename; String value; String value2; if (probablyTheDirectory.length() > 1) { needRename = dataFolder.substring(dataFolder.indexOf(probablyTheRoot) + probablyTheRoot.length()) + "/soundfonts/8Rock11e.sf2"; value = probablyTheDirectory + '/' + "8Rock11e.sfArk"; value2 = probablyTheDirectory + '/' + "8Rock11e.sf2"; } else { return -9; } try { out = new FileOutputStream(value); } catch (FileNotFoundException e) { e.printStackTrace(); } if (out == null) return -1; byte buf[] = new byte[1024]; int len; try { while ((len = in.read(buf)) > 0) out.write(buf, 0, len); } catch (IOException e1) { e1.printStackTrace(); } try { out.close(); } catch (IOException e) { e.printStackTrace(); } try { in.close(); } catch (IOException e) { e.printStackTrace(); } JNIHandler.decompressSFArk(value, "8Rock11e.sf2"); renameDocumentFile(c, value2, needRename); tryToDeleteFile(c, value); } else { File f = new File(Globals.dataFolder + "/soundfonts/8Rock11e.sfArk"); if (f != null) if (f.exists()) f.delete(); OutputStream out = null; try { out = new FileOutputStream(Globals.dataFolder + "/soundfonts/8Rock11e.sfArk"); } catch (FileNotFoundException e) { e.printStackTrace(); } if (out == null) return -1; byte buf[] = new byte[1024]; int len; try { while ((len = in.read(buf)) > 0) out.write(buf, 0, len); } catch (IOException e1) { e1.printStackTrace(); } try { out.close(); } catch (IOException e) { e.printStackTrace(); } try { in.close(); } catch (IOException e) { e.printStackTrace(); } JNIHandler.decompressSFArk(Globals.dataFolder + "/soundfonts/8Rock11e.sfArk", "8Rock11e.sf2"); //System.out.println("decompresed sfark"); new File(Globals.dataFolder + "/soundfonts/8Rock11e.sfArk").delete(); } return 777; } @TargetApi(Build.VERSION_CODES.FROYO) public static class DownloadTask extends AsyncTask<String, Integer, String> { private Context context; private PowerManager.WakeLock mWakeLock; private ProgressDialog prog; private String theUrl = ""; private String theFilename = ""; public DownloadTask(Context context) { this.context = context; } @Override protected void onPreExecute() { super.onPreExecute(); // take CPU lock to prevent CPU from going off if the user // presses the power button during download PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE); mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, getClass().getName()); mWakeLock.acquire(); prog = new ProgressDialog(context); prog.setButton(DialogInterface.BUTTON_NEGATIVE, "Cancel", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); } }); prog.setOnCancelListener(new DialogInterface.OnCancelListener() { @Override public void onCancel(DialogInterface dialog) { DownloadTask.this.cancel(true); } }); prog.setTitle("Downloading file..."); prog.setMessage("Downloading..."); prog.setCancelable(false); prog.show(); } @Override protected void onProgressUpdate(Integer... progress) { super.onProgressUpdate(progress); prog.setIndeterminate(false); prog.setMax(100); prog.setProgress(progress[0]); } @Override protected void onPostExecute(String result) { mWakeLock.release(); prog.dismiss(); if (result != null) Toast.makeText(context, "Download error: " + result, Toast.LENGTH_LONG).show(); else ((TimidityActivity) context).downloadFinished(theUrl, theFilename); } @TargetApi(Build.VERSION_CODES.FROYO) @Override protected String doInBackground(String... sUrl) { InputStream input = null; OutputStream output = null; URL url = null; try { url = new URL(sUrl[0]); } catch (MalformedURLException e1) { e1.printStackTrace(); } theUrl = sUrl[0]; theFilename = sUrl[1]; if (theUrl.startsWith("http")) { HttpURLConnection connection = null; try { connection = (HttpURLConnection) url.openConnection(); connection.connect(); // expect HTTP 200 OK, so we don't mistakenly save error report // instead of the file if (connection.getResponseCode() != HttpURLConnection.HTTP_OK) { return "Server returned HTTP " + connection.getResponseCode() + " " + connection.getResponseMessage(); } // this will be useful to display download percentage // might be -1: server did not report the length int fileLength = connection.getContentLength(); // download the file input = connection.getInputStream(); output = new FileOutputStream( Globals.getExternalCacheDir(context).getAbsolutePath() + '/' + theFilename); byte[] data = new byte[4096]; long total = 0; int count; while ((count = input.read(data)) != -1) { // allow canceling with back button if (isCancelled()) { output.close(); input.close(); return null; } total += count; // publishing the progress.... if (fileLength > 0) // only if total length is known publishProgress((int) (total * 100 / fileLength)); output.write(data, 0, count); } } catch (Exception e) { return e.toString(); } finally { try { if (output != null) output.close(); if (input != null) input.close(); } catch (IOException ignored) { } if (connection != null) connection.disconnect(); } return null; } else { HttpsURLConnection connection = null; try { connection = (HttpsURLConnection) url.openConnection(); connection.connect(); // expect HTTP 200 OK, so we don't mistakenly save error report // instead of the file if (connection.getResponseCode() != HttpsURLConnection.HTTP_OK) { return "Server returned HTTPS " + connection.getResponseCode() + " " + connection.getResponseMessage(); } // this will be useful to display download percentage // might be -1: server did not report the length int fileLength = connection.getContentLength(); // download the file input = connection.getInputStream(); output = new FileOutputStream( Globals.getExternalCacheDir(context).getAbsolutePath() + '/' + theFilename); byte[] data = new byte[4096]; long total = 0; int count; while ((count = input.read(data)) != -1) { // allow canceling with back button if (isCancelled()) { input.close(); output.close(); return null; } total += count; // publishing the progress.... if (fileLength > 0) // only if total length is known publishProgress((int) (total * 100 / fileLength)); output.write(data, 0, count); } } catch (Exception e) { return e.toString(); } finally { try { if (output != null) output.close(); if (input != null) input.close(); } catch (IOException ignored) { } if (connection != null) connection.disconnect(); } return null; } } } // @formatter:off /* * RESAMPLE_CSPLINE, 0 RESAMPLE_LAGRANGE, 1 RESAMPLE_GAUSS, 2 RESAMPLE_NEWTON, 3 RESAMPLE_LINEAR, 4 RESAMPLE_NONE 5 /* * #define RC_ERROR -1 #ifdef RC_NONE #undef RC_NONE #endif #define RC_NONE 0 #define RC_QUIT 1 #define RC_NEXT 2 #define RC_PREVIOUS 3 // Restart this song at beginning, or the previous song if we're less than a second into this one. #define RC_FORWARD 4 #define RC_BACK 5 #define RC_JUMP 6 #define RC_TOGGLE_PAUSE 7 Pause/continue #define RC_RESTART 8 /* Restart song at beginning #define RC_PAUSE 9 /* Really pause playing #define RC_CONTINUE 10 /* Continue if paused #define RC_REALLY_PREVIOUS 11 /* Really go to the previous song #define RC_CHANGE_VOLUME 12 #define RC_LOAD_FILE 13 /* Load a new midifile #define RC_TUNE_END 14 /* The tune is over, play it again sam? #define RC_KEYUP 15 /* Key up #define RC_KEYDOWN 16 /* Key down #define RC_SPEEDUP 17 /* Speed up #define RC_SPEEDDOWN 18 /* Speed down #define RC_VOICEINCR 19 /* Increase voices #define RC_VOICEDECR 20 /* Decrease voices #define RC_TOGGLE_DRUMCHAN 21 /* Toggle drum channel #define RC_RELOAD 22 /* Reload & Play #define RC_TOGGLE_SNDSPEC 23 /* Open/Close Sound Spectrogram Window #define RC_CHANGE_REV_EFFB 24 #define RC_CHANGE_REV_TIME 25 #define RC_SYNC_RESTART 26 #define RC_TOGGLE_CTL_SPEANA 27 #define RC_CHANGE_RATE 28 #define RC_OUTPUT_CHANGED 29 #define RC_STOP 30 /* Stop to play #define RC_TOGGLE_MUTE 31 #define RC_SOLO_PLAY 32 #define RC_MUTE_CLEAR 33*/ //@formatter:on }