package org.freemp.droid.playlist; import android.content.Context; import android.os.Environment; import android.preference.PreferenceManager; import android.text.TextUtils; import android.util.Log; import com.androidquery.util.AQUtility; import com.un4seen.bass.BASS; import com.un4seen.bass.TAGS; import org.freemp.droid.ClsTrack; import org.freemp.droid.FileUtils; import org.freemp.droid.FillMediaStoreTracks; import org.freemp.droid.StringUtils; import org.mozilla.universalchardet.UniversalDetector; import java.io.File; import java.nio.ByteBuffer; import java.nio.charset.Charset; import java.util.ArrayList; /** * Created by recoilme on 05/12/13. */ public class MakePlaylistFS extends MakePlaylistAbstract { //base tags for scan private static final int[] formats = {BASS.BASS_TAG_ID3V2, BASS.BASS_TAG_OGG, BASS.BASS_TAG_APE, BASS.BASS_TAG_MP4, BASS.BASS_TAG_ID3}; //encoding detector UniversalDetector detector; private ArrayList<ClsTrack> tempAllTracks, tempAllTracksMediaStore; private boolean refresh; private FillMediaStoreTracks fillMediaStoreTracks; public MakePlaylistFS(Context context, boolean refresh) { super(context, refresh); } @Override public void getAllTracks(Context context, boolean refresh) { this.refresh = refresh; t = System.currentTimeMillis(); String scanDir = PreferenceManager.getDefaultSharedPreferences(context).getString("scanDir", Environment.getExternalStorageDirectory().getAbsolutePath().toString()); File currentDir = new File(scanDir); tempAllTracks = (ArrayList<ClsTrack>) FileUtils.readObject("alltracksfs", context); tempAllTracksMediaStore = (ArrayList<ClsTrack>) FileUtils.readObject("alltracksms", context); if (refresh || tempAllTracksMediaStore == null || tempAllTracksMediaStore.size() == 0) { fillMediaStoreTracks = new FillMediaStoreTracks(context); tempAllTracksMediaStore = fillMediaStoreTracks.getTracks(); } if (!refresh && tempAllTracks != null && tempAllTracks.size() > 0) { allTracks = new ArrayList<ClsTrack>(tempAllTracks); } else { if (BASS.BASS_Init(-1, 44100, 0)) { String nativePath = context.getApplicationInfo().nativeLibraryDir; String[] listPlugins = new File(nativePath).list(); for (String s : listPlugins) { int plug = BASS.BASS_PluginLoad(nativePath + "/" + s, 0); } } detector = new UniversalDetector(null); walk(currentDir); FileUtils.writeObject("alltracksfs", context, allTracks); AQUtility.debug("time", "(ms):" + (System.currentTimeMillis() - t)); //5000 //81000 //7000 } } public void walk(File root) { File[] list = null; if (root.getAbsolutePath().toString().equals("/")) { list = new File[1]; list[0] = Environment.getExternalStorageDirectory(); File extSd = FileUtils.getExternalSdCardPath(); boolean needAdd = true; if (extSd != null) { for (File file : list) { if (file.getAbsolutePath().equals(extSd.getAbsolutePath())) { needAdd = false; break; } } } else { needAdd = false; } if (extSd != null && needAdd) { File[] extSdlist = new File[1]; extSdlist[0] = extSd; File[] newlist = new File[list.length + 1]; newlist = FileUtils.concatenate(extSdlist, list); list = newlist; } } else { list = root.listFiles(); } if (list == null) return; int chan = 0; for (File f : list) { if (f.isDirectory()) { walk(f); } else { String path = f.getAbsolutePath().toString(); if (path.contains("Richter")) { Log.w("Richter", path); } int lengthPath = path.length(); if (lengthPath < 4) continue;//file without extension String endOfPath = path.substring(lengthPath - 4).toLowerCase(); if (endOfPath.equals(".mp3") || endOfPath.equals("flac") || endOfPath.equals(".ogg") || endOfPath.equals(".oga") || endOfPath.equals(".aac") || endOfPath.equals(".m4a") || endOfPath.equals(".m4b") || endOfPath.equals(".m4p") || endOfPath.equals("opus") || endOfPath.equals(".wma") || endOfPath.equals(".wav") || endOfPath.equals(".mpc") || endOfPath.equals(".ape") ) { if (!this.refresh && tempAllTracks != null && tempAllTracks.size() > 0) { ClsTrack track = null; for (ClsTrack t : tempAllTracks) { if (t.getPath().equals(path)) { track = t; break; } } if (track != null) { allTracks.add(track); continue; } } String folder = ""; String[] pathArray = path.split( TextUtils.equals(System.getProperty("file.separator"), "") ? "/" : System.getProperty("file.separator") ); if (pathArray != null && pathArray.length > 1) { folder = pathArray[pathArray.length - 2]; } long lastModified = f.lastModified(); BASS.BASS_StreamFree(chan); chan = BASS.BASS_StreamCreateFile(path, 0, 0, 0); //check base tags and get encoding String tags = null; if (android.os.Build.VERSION.SDK_INT >= 9) { for (int format = 0; format < formats.length; format++) { final ByteBuffer byteBuffer = (ByteBuffer) TAGS.TAGS_ReadExByte(chan, "%ARTI@%YEAR@%TRCK@%TITL@%ALBM@%COMP" + " ", formats[format]); final int bufferSize = byteBuffer.capacity(); if (bufferSize < 10) { //so if no tags it return something strange, like this "??" - skip it for optimization continue; } //byteBuffer dont have array (direct access?), so copy it final ByteBuffer frameBuf = ByteBuffer.allocate(bufferSize); frameBuf.put(byteBuffer); detector.handleData(frameBuf.array(), 0, bufferSize); detector.dataEnd(); final String encoding = detector.getDetectedCharset(); boolean wrongencoding = false; try { tags = new String(frameBuf.array(), 0, bufferSize, Charset.forName(encoding)); } catch (Exception e) { wrongencoding = true; } finally { detector.reset(); } if (wrongencoding) { continue; } if (!TextUtils.isEmpty(tags)) { if (tags.split("@").length >= 4) { break; } } } } if (TextUtils.isEmpty(tags)) { //it may have tags from http forexample so handle it with default way (utf8 encoding) tags = TAGS.TAGS_Read(chan, "%UTF8(%ARTI)@%YEAR@%TRCK@%UTF8(%TITL)@%UTF8(%ALBM)@%UTF8(%COMP)" + " "); } if (TextUtils.isEmpty(tags)) { //check file without tags on exists in mediastore if (tempAllTracksMediaStore != null && tempAllTracksMediaStore.size() > 0) { for (ClsTrack t : tempAllTracksMediaStore) { if (t.getPath().equals(path)) { if (t != null) { allTracks.add(t); } break; } } } continue; } String[] tagsArray = tags.split("@"); if (tagsArray == null || tagsArray.length <= 4) { //это говно какое-то типа музыки из игры скорее всего continue; } tagsArray = tags.split("@"); int duration = 0; int albumId = 0; if (tempAllTracksMediaStore != null && tempAllTracksMediaStore.size() > 0) { ClsTrack track = null; for (ClsTrack t : tempAllTracksMediaStore) { if (t.getPath().equals(path)) { duration = t.getDuration(); albumId = t.getAlbumId(); break; } } } if (duration == 0) { duration = (int) (0.5d + BASS.BASS_ChannelBytes2Seconds(chan, BASS.BASS_ChannelGetLength(chan, BASS.BASS_POS_BYTE))); } if (pathArray.length > 0) { add2list(tagsArray[0], tagsArray[1], tagsArray[2], tagsArray[3], tagsArray[4], tagsArray[5].trim(), path, folder, lastModified, pathArray[pathArray.length - 1], duration, albumId); } } } } } public void add2list(String artist, String yearS, String trackS, String title, String album, String composer, String path, String folder, long lastModified, String filename, int duration, int albumId) { int year = 0; int track = 0; try { if (!yearS.equals("")) { if (yearS.length() > 3) { yearS = yearS.substring(0, 4); } year = Integer.parseInt(yearS.replaceAll("[^\\d.]", "")); } if (!trackS.equals("")) track = Integer.parseInt(trackS.replaceAll("[^\\d.]", "")); } catch (Exception e) { AQUtility.debug(e.toString()); } allTracks.add(new ClsTrack( artist.equals("") ? "unknown" : StringUtils.capitalizeFully(artist), title.equals("") ? filename : StringUtils.capitalizeFully(title), album, composer, year, track, duration, path, folder, lastModified, albumId)); } }