mirror of
https://github.com/ultrasonic/ultrasonic
synced 2025-02-27 08:57:44 +01:00
Add years to album header, determine album name based on entries in album header, make thread collection in ImageLoader concurrent
This commit is contained in:
parent
4389698d7f
commit
36167e5ab9
@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout xmlns:a="http://schemas.android.com/apk/res/android"
|
||||
a:layout_width="fill_parent"
|
||||
a:layout_height="wrap_content" >
|
||||
a:layout_width="fill_parent"
|
||||
a:layout_height="wrap_content">
|
||||
|
||||
<ImageView
|
||||
a:id="@+id/select_album_art"
|
||||
@ -12,7 +12,7 @@
|
||||
a:layout_marginRight="10dip"
|
||||
a:contentDescription="@null"
|
||||
a:scaleType="fitCenter"
|
||||
a:src="@drawable/unknown_album_large" />
|
||||
a:src="@drawable/unknown_album_large"/>
|
||||
|
||||
<TextView
|
||||
a:id="@+id/select_album_title"
|
||||
@ -23,7 +23,7 @@
|
||||
a:paddingRight="4dip"
|
||||
a:paddingTop="10dip"
|
||||
a:singleLine="true"
|
||||
a:textAppearance="?android:attr/textAppearanceMedium" />
|
||||
a:textAppearance="?android:attr/textAppearanceMedium"/>
|
||||
|
||||
<TextView
|
||||
a:id="@+id/select_album_artist"
|
||||
@ -34,7 +34,7 @@
|
||||
a:ellipsize="end"
|
||||
a:paddingRight="4dip"
|
||||
a:singleLine="true"
|
||||
a:textAppearance="?android:attr/textAppearanceSmall" />
|
||||
a:textAppearance="?android:attr/textAppearanceSmall"/>
|
||||
|
||||
<TextView
|
||||
a:id="@+id/select_album_genre"
|
||||
@ -45,18 +45,29 @@
|
||||
a:ellipsize="end"
|
||||
a:paddingRight="4dip"
|
||||
a:singleLine="true"
|
||||
a:textAppearance="?android:attr/textAppearanceSmall" />
|
||||
a:textAppearance="?android:attr/textAppearanceSmall"/>
|
||||
|
||||
<TextView
|
||||
a:id="@+id/select_album_year"
|
||||
a:layout_width="wrap_content"
|
||||
a:layout_height="wrap_content"
|
||||
a:layout_below="@+id/select_album_genre"
|
||||
a:layout_toRightOf="@+id/select_album_art"
|
||||
a:ellipsize="end"
|
||||
a:paddingRight="4dip"
|
||||
a:singleLine="true"
|
||||
a:textAppearance="?android:attr/textAppearanceSmall"/>
|
||||
|
||||
<TextView
|
||||
a:id="@+id/select_album_song_count"
|
||||
a:layout_width="wrap_content"
|
||||
a:layout_height="wrap_content"
|
||||
a:layout_below="@+id/select_album_genre"
|
||||
a:layout_below="@+id/select_album_year"
|
||||
a:layout_toRightOf="@+id/select_album_art"
|
||||
a:ellipsize="none"
|
||||
a:paddingRight="4dip"
|
||||
a:singleLine="true"
|
||||
a:textAppearance="?android:attr/textAppearanceSmall" />
|
||||
a:textAppearance="?android:attr/textAppearanceSmall"/>
|
||||
|
||||
<TextView
|
||||
a:id="@+id/select_album_duration"
|
||||
@ -67,6 +78,6 @@
|
||||
a:ellipsize="none"
|
||||
a:paddingRight="4dip"
|
||||
a:singleLine="true"
|
||||
a:textAppearance="?android:attr/textAppearanceSmall" />
|
||||
a:textAppearance="?android:attr/textAppearanceSmall"/>
|
||||
|
||||
</RelativeLayout>
|
@ -388,6 +388,7 @@
|
||||
<string name="settings.image_loader_concurrency_11">11</string>
|
||||
<string name="settings.image_loader_concurrency_12">12</string>
|
||||
<string name="albumArt">albumArt</string>
|
||||
<string name="common_multiple_years">Multiple Years</string>
|
||||
|
||||
<plurals name="select_album_n_songs">
|
||||
<item quantity="zero">Aucun titre</item>
|
||||
|
@ -388,6 +388,7 @@
|
||||
<string name="settings.image_loader_concurrency_11">11</string>
|
||||
<string name="settings.image_loader_concurrency_12">12</string>
|
||||
<string name="albumArt">albumArt</string>
|
||||
<string name="common_multiple_years">Multiple Years</string>
|
||||
|
||||
<plurals name="select_album_n_songs">
|
||||
<item quantity="zero">Nincsenek dalok</item>
|
||||
|
@ -388,6 +388,7 @@
|
||||
<string name="settings.image_loader_concurrency_11">11</string>
|
||||
<string name="settings.image_loader_concurrency_12">12</string>
|
||||
<string name="albumArt">albumArt</string>
|
||||
<string name="common_multiple_years">Multiple Years</string>
|
||||
|
||||
<plurals name="select_album_n_songs">
|
||||
<item quantity="zero">No songs</item>
|
||||
|
@ -1325,7 +1325,7 @@ public class DownloadActivity extends SubsonicTabActivity implements OnGestureLi
|
||||
artistTextView.setText(null);
|
||||
downloadTrackTextView.setText(null);
|
||||
downloadTotalDurationTextView.setText(null);
|
||||
getImageLoader().loadImage(albumArtImageView, null, true, 0, false, false);
|
||||
getImageLoader().loadImage(albumArtImageView, null, true, 0, false, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1196,11 +1196,12 @@ public class SelectAlbumActivity extends SubsonicTabActivity
|
||||
int artworkSelection = random.nextInt(entries.size());
|
||||
getImageLoader().loadImage(coverArtView, entries.get(artworkSelection), false, Util.getAlbumImageSize(SelectAlbumActivity.this), false, true);
|
||||
|
||||
TextView titleView = (TextView) header.findViewById(R.id.select_album_title);
|
||||
titleView.setText(name != null ? name : getActionBarSubtitle());
|
||||
|
||||
AlbumHeader albumHeader = AlbumHeader.processEntries(SelectAlbumActivity.this, entries);
|
||||
|
||||
TextView titleView = (TextView) header.findViewById(R.id.select_album_title);
|
||||
name = albumHeader.getAlbumNames().size() == 1 ? albumHeader.getAlbumNames().iterator().next() : name;
|
||||
titleView.setText(name != null ? name : getActionBarSubtitle());
|
||||
|
||||
// Don't show a header if all entries are videos
|
||||
if (albumHeader.getIsAllVideo())
|
||||
{
|
||||
@ -1221,6 +1222,13 @@ public class SelectAlbumActivity extends SubsonicTabActivity
|
||||
|
||||
genreView.setText(genre);
|
||||
|
||||
TextView yearView = (TextView) header.findViewById(R.id.select_album_year);
|
||||
String year;
|
||||
|
||||
year = albumHeader.getYears().size() == 1 ? albumHeader.getYears().iterator().next().toString() : getResources().getString(R.string.common_multiple_years);
|
||||
|
||||
yearView.setText(year);
|
||||
|
||||
TextView songCountView = (TextView) header.findViewById(R.id.select_album_song_count);
|
||||
String songs = getResources().getQuantityString(R.plurals.select_album_n_songs, songCount, songCount);
|
||||
songCountView.setText(songs);
|
||||
|
@ -14,6 +14,8 @@ public class AlbumHeader
|
||||
private Set<String> artists;
|
||||
private Set<String> grandParents;
|
||||
private Set<String> genres;
|
||||
private Set<String> albumNames;
|
||||
private Set<Integer> years;
|
||||
|
||||
public boolean getIsAllVideo()
|
||||
{
|
||||
@ -40,11 +42,24 @@ public class AlbumHeader
|
||||
return this.genres;
|
||||
}
|
||||
|
||||
public Set<String> getAlbumNames()
|
||||
{
|
||||
return this.albumNames;
|
||||
}
|
||||
|
||||
public Set<Integer> getYears()
|
||||
{
|
||||
return this.years;
|
||||
}
|
||||
|
||||
public AlbumHeader()
|
||||
{
|
||||
this.artists = new HashSet<String>();
|
||||
this.grandParents = new HashSet<String>();
|
||||
this.genres = new HashSet<String>();
|
||||
this.albumNames = new HashSet<String>();
|
||||
this.years = new HashSet<Integer>();
|
||||
|
||||
this.isAllVideo = true;
|
||||
this.totalDuration = 0;
|
||||
}
|
||||
@ -83,6 +98,16 @@ public class AlbumHeader
|
||||
{
|
||||
albumHeader.genres.add(entry.getGenre());
|
||||
}
|
||||
|
||||
if (entry.getAlbum() != null)
|
||||
{
|
||||
albumHeader.albumNames.add(entry.getAlbum());
|
||||
}
|
||||
|
||||
if (entry.getYear() != null)
|
||||
{
|
||||
albumHeader.years.add(entry.getYear());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -77,11 +77,11 @@ public class CacheCleaner
|
||||
}
|
||||
}
|
||||
|
||||
private static void deleteEmptyDirs(Iterable<File> dirs, Collection<File> undeletable)
|
||||
private static void deleteEmptyDirs(Iterable<File> dirs, Collection<File> doNotDelete)
|
||||
{
|
||||
for (File dir : dirs)
|
||||
{
|
||||
if (undeletable.contains(dir))
|
||||
if (doNotDelete.contains(dir))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@ -114,8 +114,8 @@ public class CacheCleaner
|
||||
}
|
||||
|
||||
long cacheSizeBytes = Util.getCacheSizeMB(context) * 1024L * 1024L;
|
||||
|
||||
long bytesUsedBySubsonic = 0L;
|
||||
|
||||
for (File file : files)
|
||||
{
|
||||
bytesUsedBySubsonic += file.length();
|
||||
@ -140,7 +140,7 @@ public class CacheCleaner
|
||||
return bytesToDelete;
|
||||
}
|
||||
|
||||
private static void deleteFiles(Collection<File> files, Collection<File> undeletable, long bytesToDelete, boolean deletePartials)
|
||||
private static void deleteFiles(Collection<File> files, Collection<File> doNotDelete, long bytesToDelete, boolean deletePartials)
|
||||
{
|
||||
if (files.isEmpty())
|
||||
{
|
||||
@ -154,9 +154,10 @@ public class CacheCleaner
|
||||
|
||||
if (bytesToDelete > bytesDeleted || (deletePartials && (file.getName().endsWith(".partial") || file.getName().contains(".partial."))))
|
||||
{
|
||||
if (!undeletable.contains(file) && !file.getName().equals(Constants.ALBUM_ART_FILE))
|
||||
if (!doNotDelete.contains(file) && !file.getName().equals(Constants.ALBUM_ART_FILE))
|
||||
{
|
||||
long size = file.length();
|
||||
|
||||
if (Util.delete(file))
|
||||
{
|
||||
bytesDeleted += size;
|
||||
@ -174,6 +175,7 @@ public class CacheCleaner
|
||||
{
|
||||
String name = file.getName();
|
||||
boolean isCacheFile = name.endsWith(".partial") || name.contains(".partial.") || name.endsWith(".complete") || name.contains(".complete.");
|
||||
|
||||
if (isCacheFile)
|
||||
{
|
||||
files.add(file);
|
||||
@ -186,6 +188,7 @@ public class CacheCleaner
|
||||
{
|
||||
findCandidatesForDeletion(child, files, dirs);
|
||||
}
|
||||
|
||||
dirs.add(file);
|
||||
}
|
||||
}
|
||||
@ -212,18 +215,18 @@ public class CacheCleaner
|
||||
});
|
||||
}
|
||||
|
||||
private Set<File> findUndeletableFiles()
|
||||
private Set<File> findFilesToNotDelete()
|
||||
{
|
||||
Set<File> undeletable = new HashSet<File>(5);
|
||||
Set<File> filesToNotDelete = new HashSet<File>(5);
|
||||
|
||||
for (DownloadFile downloadFile : downloadService.getDownloads())
|
||||
{
|
||||
undeletable.add(downloadFile.getPartialFile());
|
||||
undeletable.add(downloadFile.getCompleteFile());
|
||||
filesToNotDelete.add(downloadFile.getPartialFile());
|
||||
filesToNotDelete.add(downloadFile.getCompleteFile());
|
||||
}
|
||||
|
||||
undeletable.add(FileUtil.getMusicDirectory(context));
|
||||
return undeletable;
|
||||
filesToNotDelete.add(FileUtil.getMusicDirectory(context));
|
||||
return filesToNotDelete;
|
||||
}
|
||||
|
||||
private class BackgroundCleanup extends AsyncTask<Void, Void, Void>
|
||||
@ -246,10 +249,10 @@ public class CacheCleaner
|
||||
findCandidatesForDeletion(FileUtil.getMusicDirectory(context), files, dirs);
|
||||
sortByAscendingModificationTime(files);
|
||||
|
||||
Set<File> undeletable = findUndeletableFiles();
|
||||
Set<File> filesToNotDelete = findFilesToNotDelete();
|
||||
|
||||
deleteFiles(files, undeletable, getMinimumDelete(files), true);
|
||||
deleteEmptyDirs(dirs, undeletable);
|
||||
deleteFiles(files, filesToNotDelete, getMinimumDelete(files), true);
|
||||
deleteEmptyDirs(dirs, filesToNotDelete);
|
||||
}
|
||||
catch (RuntimeException x)
|
||||
{
|
||||
@ -282,8 +285,8 @@ public class CacheCleaner
|
||||
if (bytesToDelete > 0L)
|
||||
{
|
||||
sortByAscendingModificationTime(files);
|
||||
Set<File> undeletable = findUndeletableFiles();
|
||||
deleteFiles(files, undeletable, bytesToDelete, false);
|
||||
Set<File> filesToNotDelete = findFilesToNotDelete();
|
||||
deleteFiles(files, filesToNotDelete, bytesToDelete, false);
|
||||
}
|
||||
}
|
||||
catch (RuntimeException x)
|
||||
|
@ -38,6 +38,7 @@ import com.thejoshwa.ultrasonic.androidapp.service.MusicServiceFactory;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
@ -98,7 +99,7 @@ public class ImageLoader implements Runnable
|
||||
{
|
||||
running.set(true);
|
||||
|
||||
threads = new ArrayList<Thread>(this.concurrency);
|
||||
threads = Collections.synchronizedCollection(new ArrayList<Thread>(this.concurrency));
|
||||
|
||||
for (int i = 0; i < this.concurrency; i++)
|
||||
{
|
||||
@ -209,9 +210,10 @@ public class ImageLoader implements Runnable
|
||||
|
||||
MusicDirectory.Entry tagEntry = (MusicDirectory.Entry) view.getTag();
|
||||
|
||||
// Only apply image to the view if the view is intended for this entry
|
||||
if (entry != null && tagEntry != null && !entry.equals(tagEntry))
|
||||
{
|
||||
Log.i(TAG, "Skipping entry");
|
||||
Log.i(TAG, "View is no longer valid, not setting ImageBitmap");
|
||||
return;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user