Numerous fixes from DSub, other changes for stability

This commit is contained in:
Joshua Bahnsen 2013-07-17 01:59:58 -07:00
parent e60085f398
commit c79fef891d
10 changed files with 343 additions and 239 deletions

View File

@ -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>

View File

@ -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;

View File

@ -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;

View File

@ -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();
}

View File

@ -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);
}
}
}
}

View File

@ -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.");

View File

@ -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;
}
}

View File

@ -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);

View File

@ -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";

View File

@ -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);