mirror of
https://github.com/ultrasonic/ultrasonic
synced 2025-02-16 11:41:16 +01:00
Numerous fixes from DSub, other changes for stability
This commit is contained in:
parent
e60085f398
commit
c79fef891d
2
.idea/compiler.xml
generated
2
.idea/compiler.xml
generated
@ -34,8 +34,6 @@
|
||||
</annotationProcessing>
|
||||
<bytecodeTargetLevel>
|
||||
<module name="menudrawer" target="1.6" />
|
||||
<module name="menudrawer-parent" target="1.6" />
|
||||
<module name="samples" target="1.6" />
|
||||
</bytecodeTargetLevel>
|
||||
</component>
|
||||
</project>
|
||||
|
@ -37,6 +37,7 @@ import com.thejoshwa.ultrasonic.androidapp.util.CacheCleaner;
|
||||
|
||||
import org.apache.http.HttpResponse;
|
||||
import org.apache.http.HttpStatus;
|
||||
import org.apache.http.Header;
|
||||
|
||||
/**
|
||||
* @author Sindre Mehus
|
||||
@ -59,6 +60,7 @@ public class DownloadFile {
|
||||
private volatile boolean isPlaying = false;
|
||||
private volatile boolean saveWhenDone = false;
|
||||
private volatile boolean completeWhenDone = false;
|
||||
private Integer contentLength = null;
|
||||
|
||||
public DownloadFile(Context context, MusicDirectory.Entry song, boolean save) {
|
||||
this.context = context;
|
||||
@ -91,6 +93,10 @@ public class DownloadFile {
|
||||
return song.getBitRate() == null ? 160 : song.getBitRate();
|
||||
}
|
||||
|
||||
public Integer getContentLength() {
|
||||
return contentLength;
|
||||
}
|
||||
|
||||
public synchronized void download() {
|
||||
FileUtil.createDirectoryForParent(saveFile);
|
||||
failed = false;
|
||||
@ -281,6 +287,17 @@ public class DownloadFile {
|
||||
if (compare) {
|
||||
// Attempt partial HTTP GET, appending to the file if it exists.
|
||||
HttpResponse response = musicService.getDownloadInputStream(context, song, partialFile.length(), bitRate, DownloadTask.this);
|
||||
Header contentLengthHeader = response.getFirstHeader("Content-Length");
|
||||
|
||||
if (contentLengthHeader != null) {
|
||||
String contentLengthString = contentLengthHeader.getValue();
|
||||
|
||||
if (contentLengthString != null) {
|
||||
Log.i(TAG, "Content Length: " + contentLengthString);
|
||||
contentLength = Integer.parseInt(contentLengthString);
|
||||
}
|
||||
}
|
||||
|
||||
in = response.getEntity().getContent();
|
||||
boolean partial = response.getStatusLine().getStatusCode() == HttpStatus.SC_PARTIAL_CONTENT;
|
||||
|
||||
|
@ -191,21 +191,6 @@ public class DownloadServiceImpl extends Service implements DownloadService {
|
||||
|
||||
audioManager = (AudioManager) this.getSystemService(Context.AUDIO_SERVICE);
|
||||
|
||||
if (mediaPlayer != null) {
|
||||
mediaPlayer.release();
|
||||
}
|
||||
|
||||
mediaPlayer = new MediaPlayer();
|
||||
mediaPlayer.setWakeMode(this, PowerManager.PARTIAL_WAKE_LOCK);
|
||||
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
|
||||
mediaPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() {
|
||||
@Override
|
||||
public boolean onError(MediaPlayer mediaPlayer, int what, int more) {
|
||||
handleError(new Exception("MediaPlayer error: " + what + " (" + more + ")"));
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
notification.flags |= Notification.FLAG_NO_CLEAR | Notification.FLAG_ONGOING_EVENT;
|
||||
notification.contentView = new RemoteViews(this.getPackageName(), R.layout.notification);
|
||||
Util.linkButtons(this, notification.contentView, false);
|
||||
@ -251,6 +236,8 @@ public class DownloadServiceImpl extends Service implements DownloadService {
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
|
||||
instance = null;
|
||||
lifecycleSupport.onDestroy();
|
||||
mediaPlayer.release();
|
||||
|
||||
@ -287,7 +274,6 @@ public class DownloadServiceImpl extends Service implements DownloadService {
|
||||
|
||||
audioManager.unregisterRemoteControlClient(remoteControlClient);
|
||||
notification = null;
|
||||
instance = null;
|
||||
}
|
||||
|
||||
public static DownloadService getInstance() {
|
||||
@ -321,14 +307,21 @@ public class DownloadServiceImpl extends Service implements DownloadService {
|
||||
DownloadFile downloadFile = new DownloadFile(this, song, save);
|
||||
downloadList.add(getCurrentPlayingIndex() + offset, downloadFile);
|
||||
offset++;
|
||||
}
|
||||
}
|
||||
|
||||
revision++;
|
||||
} else {
|
||||
int size = size();
|
||||
int index = getCurrentPlayingIndex();
|
||||
|
||||
for (MusicDirectory.Entry song : songs) {
|
||||
DownloadFile downloadFile = new DownloadFile(this, song, save);
|
||||
downloadList.add(downloadFile);
|
||||
}
|
||||
|
||||
if(!autoplay && (size - 1) == index) {
|
||||
setNextPlaying();
|
||||
}
|
||||
|
||||
revision++;
|
||||
}
|
||||
@ -357,6 +350,8 @@ public class DownloadServiceImpl extends Service implements DownloadService {
|
||||
DownloadFile downloadFile = new DownloadFile(this, song, save);
|
||||
backgroundDownloadList.add(downloadFile);
|
||||
}
|
||||
|
||||
revision++;
|
||||
|
||||
checkDownloads();
|
||||
lifecycleSupport.serializeDownloadQueue();
|
||||
@ -373,6 +368,10 @@ public class DownloadServiceImpl extends Service implements DownloadService {
|
||||
download(songs, false, false, false, false, newPlaylist);
|
||||
|
||||
if (currentPlayingIndex != -1) {
|
||||
while (mediaPlayer == null) {
|
||||
Util.sleepQuietly(50L);
|
||||
}
|
||||
|
||||
play(currentPlayingIndex, autoPlayStart);
|
||||
|
||||
if (currentPlaying != null) {
|
||||
@ -607,6 +606,14 @@ public class DownloadServiceImpl extends Service implements DownloadService {
|
||||
}
|
||||
|
||||
synchronized void setNextPlaying() {
|
||||
boolean gaplessPlayback = Util.getGaplessPlaybackPreference(DownloadServiceImpl.this);
|
||||
|
||||
if (!gaplessPlayback) {
|
||||
nextPlaying = null;
|
||||
nextPlayerState = IDLE;
|
||||
return;
|
||||
}
|
||||
|
||||
int index = getCurrentPlayingIndex();
|
||||
if (index != -1) {
|
||||
switch (getRepeatMode()) {
|
||||
@ -1312,9 +1319,7 @@ public class DownloadServiceImpl extends Service implements DownloadService {
|
||||
try {
|
||||
setNextPlayerState(PREPARED);
|
||||
|
||||
boolean gaplessPlayback = Util.getGaplessPlaybackPreference(DownloadServiceImpl.this);
|
||||
|
||||
if (gaplessPlayback && Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN && (playerState == PlayerState.STARTED || playerState == PlayerState.PAUSED)) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN && (playerState == PlayerState.STARTED || playerState == PlayerState.PAUSED)) {
|
||||
mediaPlayer.setNextMediaPlayer(nextMediaPlayer);
|
||||
nextSetup = true;
|
||||
}
|
||||
@ -1506,7 +1511,8 @@ public class DownloadServiceImpl extends Service implements DownloadService {
|
||||
DownloadFile downloadFile = backgroundDownloadList.get(i);
|
||||
if (downloadFile.isWorkDone() && (!downloadFile.shouldSave() || downloadFile.isSaved())) {
|
||||
// Don't need to keep list like active song list
|
||||
backgroundDownloadList.remove(downloadFile);
|
||||
backgroundDownloadList.remove(i);
|
||||
revision++;
|
||||
i--;
|
||||
} else {
|
||||
currentDownloading = downloadFile;
|
||||
|
@ -24,6 +24,7 @@ import java.util.List;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
@ -56,6 +57,7 @@ public class DownloadServiceLifecycleSupport {
|
||||
private PhoneStateListener phoneStateListener;
|
||||
private boolean externalStorageAvailable= true;
|
||||
private ReentrantLock lock = new ReentrantLock();
|
||||
private final AtomicBoolean setup = new AtomicBoolean(false);
|
||||
|
||||
/**
|
||||
* This receiver manages the intent that could come from other applications.
|
||||
@ -186,6 +188,10 @@ public class DownloadServiceLifecycleSupport {
|
||||
}
|
||||
|
||||
public void serializeDownloadQueue() {
|
||||
if(!setup.get()) {
|
||||
return;
|
||||
}
|
||||
|
||||
new SerializeTask().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||
}
|
||||
|
||||
@ -307,6 +313,7 @@ public class DownloadServiceLifecycleSupport {
|
||||
try {
|
||||
lock.lock();
|
||||
deserializeDownloadQueueNow();
|
||||
setup.set(true);
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
|
@ -30,6 +30,7 @@ import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import java.util.Set;
|
||||
import java.util.SortedSet;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import android.content.Context;
|
||||
@ -47,6 +48,7 @@ import com.thejoshwa.ultrasonic.androidapp.domain.Playlist;
|
||||
import com.thejoshwa.ultrasonic.androidapp.domain.SearchCriteria;
|
||||
import com.thejoshwa.ultrasonic.androidapp.domain.SearchResult;
|
||||
import com.thejoshwa.ultrasonic.androidapp.util.Constants;
|
||||
import com.thejoshwa.ultrasonic.androidapp.util.EntryByDiscAndTrackComparator;
|
||||
import com.thejoshwa.ultrasonic.androidapp.util.FileUtil;
|
||||
import com.thejoshwa.ultrasonic.androidapp.util.ProgressListener;
|
||||
import com.thejoshwa.ultrasonic.androidapp.util.Util;
|
||||
@ -62,64 +64,89 @@ public class OfflineMusicService extends RESTMusicService {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Indexes getIndexes(String musicFolderId, boolean refresh, Context context, ProgressListener progressListener) throws Exception {
|
||||
List<Artist> artists = new ArrayList<Artist>();
|
||||
File root = FileUtil.getMusicDirectory(context);
|
||||
for (File file : FileUtil.listFiles(root)) {
|
||||
if (file.isDirectory()) {
|
||||
Artist artist = new Artist();
|
||||
artist.setId(file.getPath());
|
||||
artist.setName(file.getName());
|
||||
|
||||
String artistIndex = "";
|
||||
|
||||
try {
|
||||
artistIndex = file.getName().substring(0, 1);
|
||||
}
|
||||
catch (Exception ignored) { }
|
||||
|
||||
artist.setIndex(artistIndex);
|
||||
|
||||
artists.add(artist);
|
||||
}
|
||||
}
|
||||
return new Indexes(0L, Collections.<Artist>emptyList(), artists);
|
||||
}
|
||||
@Override
|
||||
public Indexes getIndexes(String musicFolderId, boolean refresh, Context context, ProgressListener progressListener) throws Exception {
|
||||
List<Artist> artists = new ArrayList<Artist>();
|
||||
File root = FileUtil.getMusicDirectory(context);
|
||||
for (File file : FileUtil.listFiles(root)) {
|
||||
if (file.isDirectory()) {
|
||||
Artist artist = new Artist();
|
||||
artist.setId(file.getPath());
|
||||
artist.setIndex(file.getName().substring(0, 1));
|
||||
artist.setName(file.getName());
|
||||
artists.add(artist);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public MusicDirectory getMusicDirectory(String id, String artistName, boolean refresh, Context context, ProgressListener progressListener) throws Exception {
|
||||
File dir = new File(id);
|
||||
MusicDirectory result = new MusicDirectory();
|
||||
result.setName(dir.getName());
|
||||
String ignoredArticlesString = "The El La Los Las Le Les";
|
||||
final String[] ignoredArticles = ignoredArticlesString.split(" ");
|
||||
|
||||
Set<String> names = new HashSet<String>();
|
||||
Collections.sort(artists, new Comparator<Artist>() {
|
||||
public int compare(Artist lhsArtist, Artist rhsArtist) {
|
||||
String lhs = lhsArtist.getName().toLowerCase();
|
||||
String rhs = rhsArtist.getName().toLowerCase();
|
||||
|
||||
for (File file : FileUtil.listMediaFiles(dir)) {
|
||||
String name = getName(file);
|
||||
if (name != null & !names.contains(name)) {
|
||||
names.add(name);
|
||||
result.addChild(createEntry(context, file, name));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
char lhs1 = lhs.charAt(0);
|
||||
char rhs1 = rhs.charAt(0);
|
||||
|
||||
private String getName(File file) {
|
||||
String name = file.getName();
|
||||
if (file.isDirectory()) {
|
||||
return name;
|
||||
}
|
||||
if(Character.isDigit(lhs1) && !Character.isDigit(rhs1)) {
|
||||
return 1;
|
||||
} else if(Character.isDigit(rhs1) && !Character.isDigit(lhs1)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (name.endsWith(".partial") || name.contains(".partial.") || name.equals(Constants.ALBUM_ART_FILE)) {
|
||||
return null;
|
||||
}
|
||||
for(String article: ignoredArticles) {
|
||||
int index = lhs.indexOf(article.toLowerCase() + " ");
|
||||
if(index == 0) {
|
||||
lhs = lhs.substring(article.length() + 1);
|
||||
}
|
||||
index = rhs.indexOf(article.toLowerCase() + " ");
|
||||
if(index == 0) {
|
||||
rhs = rhs.substring(article.length() + 1);
|
||||
}
|
||||
}
|
||||
|
||||
name = name.replace(".complete", "");
|
||||
return FileUtil.getBaseName(name);
|
||||
}
|
||||
return lhs.compareTo(rhs);
|
||||
}
|
||||
});
|
||||
|
||||
private MusicDirectory.Entry createEntry(Context context, File file, String name) {
|
||||
return new Indexes(0L, Collections.<Artist>emptyList(), artists);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MusicDirectory getMusicDirectory(String id, String artistName, boolean refresh, Context context, ProgressListener progressListener) throws Exception {
|
||||
File dir = new File(id);
|
||||
MusicDirectory result = new MusicDirectory();
|
||||
result.setName(dir.getName());
|
||||
|
||||
Set<String> names = new HashSet<String>();
|
||||
|
||||
for (File file : FileUtil.listMediaFiles(dir)) {
|
||||
String name = getName(file);
|
||||
if (name != null & !names.contains(name)) {
|
||||
names.add(name);
|
||||
result.addChild(createEntry(context, file, name));
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private String getName(File file) {
|
||||
String name = file.getName();
|
||||
if (file.isDirectory()) {
|
||||
return name;
|
||||
}
|
||||
|
||||
if (name.endsWith(".partial") || name.contains(".partial.") || name.equals(Constants.ALBUM_ART_FILE)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
name = name.replace(".complete", "");
|
||||
return FileUtil.getBaseName(name);
|
||||
}
|
||||
|
||||
private MusicDirectory.Entry createEntry(Context context, File file, String name) {
|
||||
MusicDirectory.Entry entry = new MusicDirectory.Entry();
|
||||
entry.setIsDirectory(file.isDirectory());
|
||||
entry.setId(file.getPath());
|
||||
@ -277,18 +304,17 @@ public class OfflineMusicService extends RESTMusicService {
|
||||
throw new OfflineException("Music folders not available in offline mode");
|
||||
}
|
||||
|
||||
@Override
|
||||
public SearchResult search(SearchCriteria criteria, Context context, ProgressListener progressListener) throws Exception {
|
||||
@Override
|
||||
public SearchResult search(SearchCriteria criteria, Context context, ProgressListener progressListener) throws Exception {
|
||||
List<Artist> artists = new ArrayList<Artist>();
|
||||
List<MusicDirectory.Entry> albums = new ArrayList<MusicDirectory.Entry>();
|
||||
List<MusicDirectory.Entry> songs = new ArrayList<MusicDirectory.Entry>();
|
||||
File root = FileUtil.getMusicDirectory(context);
|
||||
int closeness;
|
||||
|
||||
for (File artistFile : FileUtil.listFiles(root)) {
|
||||
File root = FileUtil.getMusicDirectory(context);
|
||||
int closeness = 0;
|
||||
for (File artistFile : FileUtil.listFiles(root)) {
|
||||
String artistName = artistFile.getName();
|
||||
if (artistFile.isDirectory()) {
|
||||
if ((closeness = matchCriteria(criteria, artistName)) > 0) {
|
||||
if (artistFile.isDirectory()) {
|
||||
if((closeness = matchCriteria(criteria, artistName)) > 0) {
|
||||
Artist artist = new Artist();
|
||||
artist.setId(artistFile.getPath());
|
||||
artist.setIndex(artistFile.getName().substring(0, 1));
|
||||
@ -296,11 +322,11 @@ public class OfflineMusicService extends RESTMusicService {
|
||||
artist.setCloseness(closeness);
|
||||
artists.add(artist);
|
||||
}
|
||||
|
||||
|
||||
recursiveAlbumSearch(artistName, artistFile, criteria, context, albums, songs);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Collections.sort(artists, new Comparator<Artist>() {
|
||||
public int compare(Artist lhs, Artist rhs) {
|
||||
if(lhs.getCloseness() == rhs.getCloseness()) {
|
||||
@ -340,10 +366,10 @@ public class OfflineMusicService extends RESTMusicService {
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
return new SearchResult(artists, albums, songs);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void recursiveAlbumSearch(String artistName, File file, SearchCriteria criteria, Context context, List<MusicDirectory.Entry> albums, List<MusicDirectory.Entry> songs) {
|
||||
int closeness;
|
||||
for(File albumFile : FileUtil.listMediaFiles(file)) {
|
||||
@ -382,11 +408,12 @@ public class OfflineMusicService extends RESTMusicService {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private int matchCriteria(SearchCriteria criteria, String name) {
|
||||
String query = criteria.getQuery().toLowerCase();
|
||||
String[] queryParts = query.split(" ");
|
||||
String[] nameParts = name.toLowerCase().split(" ");
|
||||
|
||||
|
||||
int closeness = 0;
|
||||
for(String queryPart : queryParts) {
|
||||
for(String namePart : nameParts) {
|
||||
@ -395,50 +422,76 @@ public class OfflineMusicService extends RESTMusicService {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return closeness;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Playlist> getPlaylists(boolean refresh, Context context, ProgressListener progressListener) throws Exception {
|
||||
List<Playlist> playlists = new ArrayList<Playlist>();
|
||||
File root = FileUtil.getPlaylistDirectory();
|
||||
for (File file : FileUtil.listFiles(root)) {
|
||||
if(FileUtil.isPlaylistFile(file)) {
|
||||
String id = file.getName();
|
||||
String filename = FileUtil.getBaseName(id);
|
||||
Playlist playlist = new Playlist(id, filename);
|
||||
playlists.add(playlist);
|
||||
@Override
|
||||
public List<Playlist> getPlaylists(boolean refresh, Context context, ProgressListener progressListener) throws Exception {
|
||||
List<Playlist> playlists = new ArrayList<Playlist>();
|
||||
File root = FileUtil.getPlaylistDirectory();
|
||||
String lastServer = null;
|
||||
boolean removeServer = true;
|
||||
for (File folder : FileUtil.listFiles(root)) {
|
||||
if(folder.isDirectory()) {
|
||||
String server = folder.getName();
|
||||
SortedSet<File> fileList = FileUtil.listFiles(folder);
|
||||
for(File file: fileList) {
|
||||
if(FileUtil.isPlaylistFile(file)) {
|
||||
String id = file.getName();
|
||||
String filename = server + ": " + FileUtil.getBaseName(id);
|
||||
Playlist playlist = new Playlist(server, filename);
|
||||
playlists.add(playlist);
|
||||
}
|
||||
}
|
||||
|
||||
if(!server.equals(lastServer) && fileList.size() > 0) {
|
||||
if(lastServer != null) {
|
||||
removeServer = false;
|
||||
}
|
||||
lastServer = server;
|
||||
}
|
||||
} else {
|
||||
// Delete legacy playlist files
|
||||
try {
|
||||
file.delete();
|
||||
folder.delete();
|
||||
} catch(Exception e) {
|
||||
Log.w(TAG, "Failed to delete old playlist file: " + file.getName());
|
||||
Log.w(TAG, "Failed to delete old playlist file: " + folder.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
return playlists;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public MusicDirectory getPlaylist(String id, String name, Context context, ProgressListener progressListener) throws Exception {
|
||||
if(removeServer) {
|
||||
for(Playlist playlist: playlists) {
|
||||
playlist.setName(playlist.getName().substring(playlist.getId().length() + 2));
|
||||
}
|
||||
}
|
||||
return playlists;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MusicDirectory getPlaylist(String id, String name, Context context, ProgressListener progressListener) throws Exception {
|
||||
DownloadService downloadService = DownloadServiceImpl.getInstance();
|
||||
if (downloadService == null) {
|
||||
return new MusicDirectory();
|
||||
}
|
||||
|
||||
Reader reader = null;
|
||||
if (downloadService == null) {
|
||||
return new MusicDirectory();
|
||||
}
|
||||
|
||||
Reader reader = null;
|
||||
BufferedReader buffer = null;
|
||||
try {
|
||||
File playlistFile = FileUtil.getPlaylistFile(name);
|
||||
int firstIndex = name.indexOf(id);
|
||||
if(firstIndex != -1) {
|
||||
name = name.substring(id.length() + 2);
|
||||
}
|
||||
|
||||
File playlistFile = FileUtil.getPlaylistFile(id, name);
|
||||
reader = new FileReader(playlistFile);
|
||||
buffer = new BufferedReader(reader);
|
||||
|
||||
|
||||
MusicDirectory playlist = new MusicDirectory();
|
||||
String line = buffer.readLine();
|
||||
if(!"#EXTM3U".equals(line)) return playlist;
|
||||
|
||||
if(!"#EXTM3U".equals(line)) return playlist;
|
||||
|
||||
while( (line = buffer.readLine()) != null ){
|
||||
File entryFile = new File(line);
|
||||
String entryName = getName(entryFile);
|
||||
@ -446,13 +499,13 @@ public class OfflineMusicService extends RESTMusicService {
|
||||
playlist.addChild(createEntry(context, entryFile, entryName));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return playlist;
|
||||
} finally {
|
||||
Util.close(buffer);
|
||||
Util.close(reader);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void createPlaylist(String id, String name, List<MusicDirectory.Entry> entries, Context context, ProgressListener progressListener) throws Exception {
|
||||
@ -568,13 +621,13 @@ public class OfflineMusicService extends RESTMusicService {
|
||||
throw new OfflineException("Getting Genres not available in offline mode");
|
||||
}
|
||||
|
||||
private void listFilesRecursively(File parent, List<File> children) {
|
||||
for (File file : FileUtil.listMediaFiles(parent)) {
|
||||
if (file.isFile()) {
|
||||
children.add(file);
|
||||
} else {
|
||||
listFilesRecursively(file, children);
|
||||
}
|
||||
}
|
||||
}
|
||||
private void listFilesRecursively(File parent, List<File> children) {
|
||||
for (File file : FileUtil.listMediaFiles(parent)) {
|
||||
if (file.isFile()) {
|
||||
children.add(file);
|
||||
} else {
|
||||
listFilesRecursively(file, children);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -469,16 +469,16 @@ public class RESTMusicService implements MusicService {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public MusicDirectory getPlaylist(String id, String name, Context context, ProgressListener progressListener) throws Exception {
|
||||
HttpParams params = new BasicHttpParams();
|
||||
HttpConnectionParams.setSoTimeout(params, SOCKET_READ_TIMEOUT_GET_PLAYLIST);
|
||||
@Override
|
||||
public MusicDirectory getPlaylist(String id, String name, Context context, ProgressListener progressListener) throws Exception {
|
||||
HttpParams params = new BasicHttpParams();
|
||||
HttpConnectionParams.setSoTimeout(params, SOCKET_READ_TIMEOUT_GET_PLAYLIST);
|
||||
|
||||
Reader reader = getReader(context, progressListener, "getPlaylist", params, "id", id);
|
||||
try {
|
||||
Reader reader = getReader(context, progressListener, "getPlaylist", params, "id", id);
|
||||
try {
|
||||
MusicDirectory playlist = new PlaylistParser(context).parse(reader, progressListener);
|
||||
|
||||
File playlistFile = FileUtil.getPlaylistFile(name);
|
||||
|
||||
File playlistFile = FileUtil.getPlaylistFile(Util.getServerName(context), name);
|
||||
FileWriter fw = new FileWriter(playlistFile);
|
||||
BufferedWriter bw = new BufferedWriter(fw);
|
||||
try {
|
||||
@ -488,7 +488,7 @@ public class RESTMusicService implements MusicService {
|
||||
if(! new File(filePath).exists()){
|
||||
String ext = FileUtil.getExtension(filePath);
|
||||
String base = FileUtil.getBaseName(filePath);
|
||||
filePath = base + ".complete." + ext;
|
||||
filePath = base + ".complete." + ext;
|
||||
}
|
||||
fw.write(filePath + "\n");
|
||||
}
|
||||
@ -498,67 +498,63 @@ public class RESTMusicService implements MusicService {
|
||||
bw.close();
|
||||
fw.close();
|
||||
}
|
||||
|
||||
|
||||
return playlist;
|
||||
} finally {
|
||||
Util.close(reader);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Playlist> getPlaylists(boolean refresh, Context context, ProgressListener progressListener) throws Exception {
|
||||
Reader reader = getReader(context, progressListener, "getPlaylists", null);
|
||||
try {
|
||||
return new PlaylistsParser(context).parse(reader, progressListener);
|
||||
} finally {
|
||||
Util.close(reader);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
Util.close(reader);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void createPlaylist(String id, String name, List<MusicDirectory.Entry> entries, Context context, ProgressListener progressListener) throws Exception {
|
||||
checkServerVersion(context, "1.2", "Creating playlist not supported.");
|
||||
|
||||
List<String> parameterNames = new LinkedList<String>();
|
||||
List<Object> parameterValues = new LinkedList<Object>();
|
||||
@Override
|
||||
public List<Playlist> getPlaylists(boolean refresh, Context context, ProgressListener progressListener) throws Exception {
|
||||
Reader reader = getReader(context, progressListener, "getPlaylists", null);
|
||||
try {
|
||||
return new PlaylistsParser(context).parse(reader, progressListener);
|
||||
} finally {
|
||||
Util.close(reader);
|
||||
}
|
||||
}
|
||||
|
||||
if (id != null) {
|
||||
parameterNames.add("playlistId");
|
||||
parameterValues.add(id);
|
||||
}
|
||||
if (name != null) {
|
||||
parameterNames.add("name");
|
||||
parameterValues.add(name);
|
||||
}
|
||||
for (MusicDirectory.Entry entry : entries) {
|
||||
parameterNames.add("songId");
|
||||
parameterValues.add(entry.getId());
|
||||
}
|
||||
@Override
|
||||
public void createPlaylist(String id, String name, List<MusicDirectory.Entry> entries, Context context, ProgressListener progressListener) throws Exception {
|
||||
List<String> parameterNames = new LinkedList<String>();
|
||||
List<Object> parameterValues = new LinkedList<Object>();
|
||||
|
||||
if (id != null) {
|
||||
parameterNames.add("playlistId");
|
||||
parameterValues.add(id);
|
||||
}
|
||||
if (name != null) {
|
||||
parameterNames.add("name");
|
||||
parameterValues.add(name);
|
||||
}
|
||||
for (MusicDirectory.Entry entry : entries) {
|
||||
parameterNames.add("songId");
|
||||
parameterValues.add(entry.getId());
|
||||
}
|
||||
|
||||
Reader reader = getReader(context, progressListener, "createPlaylist", null, parameterNames, parameterValues);
|
||||
try {
|
||||
new ErrorParser(context).parse(reader);
|
||||
} finally {
|
||||
Util.close(reader);
|
||||
}
|
||||
}
|
||||
|
||||
Reader reader = getReader(context, progressListener, "createPlaylist", null, parameterNames, parameterValues);
|
||||
try {
|
||||
new ErrorParser(context).parse(reader);
|
||||
} finally {
|
||||
Util.close(reader);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deletePlaylist(String id, Context context, ProgressListener progressListener) throws Exception {
|
||||
checkServerVersion(context, "1.2", "Deleting playlist not supported.");
|
||||
|
||||
Reader reader = getReader(context, progressListener, "deletePlaylist", null, "id", id);
|
||||
try {
|
||||
new ErrorParser(context).parse(reader);
|
||||
} finally {
|
||||
Util.close(reader);
|
||||
}
|
||||
new ErrorParser(context).parse(reader);
|
||||
} finally {
|
||||
Util.close(reader);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void updatePlaylist(String id, List<MusicDirectory.Entry> toAdd, Context context, ProgressListener progressListener) throws Exception {
|
||||
checkServerVersion(context, "1.8", "Updating playlist not supported.");
|
||||
|
||||
|
||||
List<String> names = new ArrayList<String>();
|
||||
List<Object> values = new ArrayList<Object>();
|
||||
names.add("playlistId");
|
||||
@ -568,17 +564,16 @@ public class RESTMusicService implements MusicService {
|
||||
values.add(song.getId());
|
||||
}
|
||||
Reader reader = getReader(context, progressListener, "updatePlaylist", null, names, values);
|
||||
try {
|
||||
new ErrorParser(context).parse(reader);
|
||||
} finally {
|
||||
Util.close(reader);
|
||||
}
|
||||
try {
|
||||
new ErrorParser(context).parse(reader);
|
||||
} finally {
|
||||
Util.close(reader);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void removeFromPlaylist(String id, List<Integer> toRemove, Context context, ProgressListener progressListener) throws Exception {
|
||||
checkServerVersion(context, "1.8", "Removing from playlist not supported.");
|
||||
|
||||
checkServerVersion(context, "1.8", "Updating playlists is not supported.");
|
||||
List<String> names = new ArrayList<String>();
|
||||
List<Object> values = new ArrayList<Object>();
|
||||
names.add("playlistId");
|
||||
@ -588,16 +583,16 @@ public class RESTMusicService implements MusicService {
|
||||
values.add(song);
|
||||
}
|
||||
Reader reader = getReader(context, progressListener, "updatePlaylist", null, names, values);
|
||||
try {
|
||||
new ErrorParser(context).parse(reader);
|
||||
} finally {
|
||||
Util.close(reader);
|
||||
}
|
||||
try {
|
||||
new ErrorParser(context).parse(reader);
|
||||
} finally {
|
||||
Util.close(reader);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void updatePlaylist(String id, String name, String comment, boolean pub, Context context, ProgressListener progressListener) throws Exception {
|
||||
checkServerVersion(context, "1.8", "Updating playlist not supported.");
|
||||
checkServerVersion(context, "1.8", "Updating playlists is not supported.");
|
||||
Reader reader = getReader(context, progressListener, "updatePlaylist", null, Arrays.asList("playlistId", "name", "comment", "public"), Arrays.<Object>asList(id, name, comment, pub));
|
||||
try {
|
||||
new ErrorParser(context).parse(reader);
|
||||
@ -606,7 +601,7 @@ public class RESTMusicService implements MusicService {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Override
|
||||
public Lyrics getLyrics(String artist, String title, Context context, ProgressListener progressListener) throws Exception {
|
||||
checkServerVersion(context, "1.2", "Lyrics not supported.");
|
||||
|
||||
|
@ -165,7 +165,7 @@ public class CacheCleaner {
|
||||
undeletable.add(FileUtil.getMusicDirectory(context));
|
||||
return undeletable;
|
||||
}
|
||||
|
||||
|
||||
private class BackgroundCleanup extends AsyncTask<Void, Void, Void> {
|
||||
@Override
|
||||
protected Void doInBackground(Void... params) {
|
||||
@ -188,11 +188,11 @@ public class CacheCleaner {
|
||||
} catch (RuntimeException x) {
|
||||
Log.e(TAG, "Error in cache cleaning.", x);
|
||||
}
|
||||
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private class BackgroundSpaceCleanup extends AsyncTask<Void, Void, Void> {
|
||||
@Override
|
||||
protected Void doInBackground(Void... params) {
|
||||
@ -205,7 +205,7 @@ public class CacheCleaner {
|
||||
List<File> files = new ArrayList<File>();
|
||||
List<File> dirs = new ArrayList<File>();
|
||||
findCandidatesForDeletion(FileUtil.getMusicDirectory(context), files, dirs);
|
||||
|
||||
|
||||
long bytesToDelete = getMinimumDelete(files);
|
||||
if(bytesToDelete > 0L) {
|
||||
sortByAscendingModificationTime(files);
|
||||
@ -215,28 +215,29 @@ public class CacheCleaner {
|
||||
} catch (RuntimeException x) {
|
||||
Log.e(TAG, "Error in cache cleaning.", x);
|
||||
}
|
||||
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private class BackgroundPlaylistsCleanup extends AsyncTask<List<Playlist>, Void, Void> {
|
||||
@Override
|
||||
protected Void doInBackground(List<Playlist>... params) {
|
||||
try {
|
||||
SortedSet<File> playlistFiles = FileUtil.listFiles(FileUtil.getPlaylistDirectory());
|
||||
String server = Util.getServerName(context);
|
||||
SortedSet<File> playlistFiles = FileUtil.listFiles(FileUtil.getPlaylistDirectory(server));
|
||||
List<Playlist> playlists = params[0];
|
||||
for (Playlist playlist : playlists) {
|
||||
playlistFiles.remove(FileUtil.getPlaylistFile(playlist.getName()));
|
||||
playlistFiles.remove(FileUtil.getPlaylistFile(server, playlist.getName()));
|
||||
}
|
||||
|
||||
for(File playlist : playlistFiles) {
|
||||
playlist.delete();
|
||||
}
|
||||
|
||||
for (File playlist : playlistFiles) {
|
||||
playlist.delete();
|
||||
}
|
||||
} catch (RuntimeException x) {
|
||||
Log.e(TAG, "Error in playlist cache cleaning.", x);
|
||||
}
|
||||
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -52,40 +52,46 @@ public class FileUtil {
|
||||
private static final List<String> PLAYLIST_FILE_EXTENSIONS = Arrays.asList("m3u");
|
||||
private static final File DEFAULT_MUSIC_DIR = createDirectory("music");
|
||||
|
||||
public static File getSongFile(Context context, MusicDirectory.Entry song) {
|
||||
File dir = getAlbumDirectory(context, song);
|
||||
public static File getSongFile(Context context, MusicDirectory.Entry song) {
|
||||
File dir = getAlbumDirectory(context, song);
|
||||
|
||||
StringBuilder fileName = new StringBuilder();
|
||||
Integer track = song.getTrack();
|
||||
if (track != null) {
|
||||
if (track < 10) {
|
||||
fileName.append("0");
|
||||
}
|
||||
fileName.append(track).append("-");
|
||||
}
|
||||
StringBuilder fileName = new StringBuilder();
|
||||
Integer track = song.getTrack();
|
||||
if (track != null) {
|
||||
if (track < 10) {
|
||||
fileName.append("0");
|
||||
}
|
||||
fileName.append(track).append("-");
|
||||
}
|
||||
|
||||
fileName.append(fileSystemSafe(song.getTitle())).append(".");
|
||||
fileName.append(fileSystemSafe(song.getTitle())).append(".");
|
||||
|
||||
if (song.getTranscodedSuffix() != null) {
|
||||
fileName.append(song.getTranscodedSuffix());
|
||||
} else {
|
||||
fileName.append(song.getSuffix());
|
||||
}
|
||||
if (song.getTranscodedSuffix() != null) {
|
||||
fileName.append(song.getTranscodedSuffix());
|
||||
} else {
|
||||
fileName.append(song.getSuffix());
|
||||
}
|
||||
|
||||
return new File(dir, fileName.toString());
|
||||
}
|
||||
return new File(dir, fileName.toString());
|
||||
}
|
||||
|
||||
public static File getPlaylistFile(String name) {
|
||||
File playlistDir = getPlaylistDirectory();
|
||||
public static File getPlaylistFile(String server, String name) {
|
||||
File playlistDir = getPlaylistDirectory(server);
|
||||
return new File(playlistDir, fileSystemSafe(name) + ".m3u");
|
||||
}
|
||||
|
||||
public static File getPlaylistDirectory() {
|
||||
public static File getPlaylistDirectory() {
|
||||
File playlistDir = new File(getUltraSonicDirectory(), "playlists");
|
||||
ensureDirectoryExistsAndIsReadWritable(playlistDir);
|
||||
return playlistDir;
|
||||
}
|
||||
|
||||
|
||||
public static File getPlaylistDirectory(String server) {
|
||||
File playlistDir = new File(getPlaylistDirectory(), server);
|
||||
ensureDirectoryExistsAndIsReadWritable(playlistDir);
|
||||
return playlistDir;
|
||||
}
|
||||
|
||||
public static File getAlbumArtFile(Context context, MusicDirectory.Entry entry) {
|
||||
File albumDir = getAlbumDirectory(context, entry);
|
||||
return getAlbumArtFile(albumDir);
|
||||
|
@ -157,12 +157,22 @@ public class StreamProxy implements Runnable {
|
||||
Log.i(TAG, "Streaming song in background");
|
||||
DownloadFile downloadFile = downloadService.getCurrentPlaying();
|
||||
MusicDirectory.Entry song = downloadFile.getSong();
|
||||
long fileSize = downloadFile.getBitRate() * ((song.getDuration() != null) ? song.getDuration() : 0) * 1000 / 8;
|
||||
Log.i(TAG, "Streaming fileSize: " + fileSize);
|
||||
|
||||
// Create HTTP header
|
||||
String headers = "HTTP/1.0 200 OK\r\n";
|
||||
headers += "Content-Type: " + "application/octet-stream" + "\r\n";
|
||||
|
||||
Integer contentLength = downloadFile.getContentLength();
|
||||
long fileSize;
|
||||
|
||||
if (contentLength == null) {
|
||||
fileSize = downloadFile.getBitRate() * ((song.getDuration() != null) ? song.getDuration() : 0) * 1000 / 8;
|
||||
} else {
|
||||
fileSize = contentLength;
|
||||
headers += "Content-Length: " + fileSize + "\r\n";
|
||||
}
|
||||
|
||||
Log.i(TAG, "Streaming fileSize: " + fileSize);
|
||||
|
||||
headers += "Connection: close\r\n";
|
||||
headers += "\r\n";
|
||||
|
@ -189,6 +189,17 @@ public class Util extends DownloadActivity {
|
||||
return settings.getInt(Constants.PREFERENCES_KEY_ACTIVE_SERVERS, 3);
|
||||
}
|
||||
|
||||
public static String getServerName(Context context) {
|
||||
int instance = getActiveServer(context);
|
||||
|
||||
if (instance == 0) {
|
||||
return context.getResources().getString(R.string.main_offline);
|
||||
}
|
||||
|
||||
SharedPreferences preferences = getPreferences(context);
|
||||
return preferences.getString(Constants.PREFERENCES_KEY_SERVER_NAME + instance, null);
|
||||
}
|
||||
|
||||
public static String getServerName(Context context, int instance) {
|
||||
if (instance == 0) {
|
||||
return context.getResources().getString(R.string.main_offline);
|
||||
|
Loading…
x
Reference in New Issue
Block a user