Has stuff wait for the database to load.
A lot of stuff (CLI in particular) isn't particurally useful until the database loads. However, we still want a GUI, so we just use syncronization for stuff.
This commit is contained in:
@@ -16,6 +16,7 @@ import java.util.*;
|
|||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
import java.util.concurrent.Future;
|
import java.util.concurrent.Future;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
public class InternetSongProvider implements SongProvider<InternetSong>
|
public class InternetSongProvider implements SongProvider<InternetSong>
|
||||||
@@ -33,6 +34,8 @@ public class InternetSongProvider implements SongProvider<InternetSong>
|
|||||||
return INSTANCE;
|
return INSTANCE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private AtomicBoolean updating = new AtomicBoolean();
|
||||||
|
|
||||||
private final HashMap<URL, InternetSong> songs = new HashMap<>();
|
private final HashMap<URL, InternetSong> songs = new HashMap<>();
|
||||||
private final HashMap<String, Album> albums = new HashMap<>();
|
private final HashMap<String, Album> albums = new HashMap<>();
|
||||||
/**
|
/**
|
||||||
@@ -63,6 +66,7 @@ public class InternetSongProvider implements SongProvider<InternetSong>
|
|||||||
|
|
||||||
private void getSongCache()
|
private void getSongCache()
|
||||||
{
|
{
|
||||||
|
this.updating.set(true);
|
||||||
service.submit(new SongQuery());
|
service.submit(new SongQuery());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -74,6 +78,20 @@ public class InternetSongProvider implements SongProvider<InternetSong>
|
|||||||
@Override
|
@Override
|
||||||
public Collection<Album> getAlbums()
|
public Collection<Album> getAlbums()
|
||||||
{
|
{
|
||||||
|
synchronized (this.updating)
|
||||||
|
{
|
||||||
|
while (this.updating.get())
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
this.updating.wait();
|
||||||
|
}
|
||||||
|
catch (InterruptedException e)
|
||||||
|
{
|
||||||
|
logger.error("Error while waiting for update lock", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
return this.albums.values();
|
return this.albums.values();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -85,6 +103,20 @@ public class InternetSongProvider implements SongProvider<InternetSong>
|
|||||||
@Override
|
@Override
|
||||||
public Collection<InternetSong> getSongs()
|
public Collection<InternetSong> getSongs()
|
||||||
{
|
{
|
||||||
|
synchronized (this.updating)
|
||||||
|
{
|
||||||
|
while (this.updating.get())
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
this.updating.wait();
|
||||||
|
}
|
||||||
|
catch (InterruptedException e)
|
||||||
|
{
|
||||||
|
logger.error("Error while waiting for update lock", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
synchronized (this.songs)
|
synchronized (this.songs)
|
||||||
{
|
{
|
||||||
return Collections.unmodifiableCollection(this.songs.values());
|
return Collections.unmodifiableCollection(this.songs.values());
|
||||||
@@ -99,6 +131,20 @@ public class InternetSongProvider implements SongProvider<InternetSong>
|
|||||||
@Override
|
@Override
|
||||||
public Collection<String> getArtists()
|
public Collection<String> getArtists()
|
||||||
{
|
{
|
||||||
|
synchronized (this.updating)
|
||||||
|
{
|
||||||
|
while (this.updating.get())
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
this.updating.wait();
|
||||||
|
}
|
||||||
|
catch (InterruptedException e)
|
||||||
|
{
|
||||||
|
logger.error("Error while waiting for update lock", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
return this.artists;
|
return this.artists;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -110,6 +156,20 @@ public class InternetSongProvider implements SongProvider<InternetSong>
|
|||||||
@Override
|
@Override
|
||||||
public Collection<String> getAlbumArtists()
|
public Collection<String> getAlbumArtists()
|
||||||
{
|
{
|
||||||
|
synchronized (this.updating)
|
||||||
|
{
|
||||||
|
while (this.updating.get())
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
this.updating.wait();
|
||||||
|
}
|
||||||
|
catch (InterruptedException e)
|
||||||
|
{
|
||||||
|
logger.error("Error while waiting for update lock", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
return this.albumArtists;
|
return this.albumArtists;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -121,6 +181,20 @@ public class InternetSongProvider implements SongProvider<InternetSong>
|
|||||||
@Override
|
@Override
|
||||||
public Collection<String> getGenres()
|
public Collection<String> getGenres()
|
||||||
{
|
{
|
||||||
|
synchronized (this.updating)
|
||||||
|
{
|
||||||
|
while (this.updating.get())
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
this.updating.wait();
|
||||||
|
}
|
||||||
|
catch (InterruptedException e)
|
||||||
|
{
|
||||||
|
logger.error("Error while waiting for update lock", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
return this.genres;
|
return this.genres;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -132,6 +206,20 @@ public class InternetSongProvider implements SongProvider<InternetSong>
|
|||||||
@Override
|
@Override
|
||||||
public Collection<Integer> getYears()
|
public Collection<Integer> getYears()
|
||||||
{
|
{
|
||||||
|
synchronized (this.updating)
|
||||||
|
{
|
||||||
|
while (this.updating.get())
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
this.updating.wait();
|
||||||
|
}
|
||||||
|
catch (InterruptedException e)
|
||||||
|
{
|
||||||
|
logger.error("Error while waiting for update lock", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
return this.years;
|
return this.years;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -144,6 +232,20 @@ public class InternetSongProvider implements SongProvider<InternetSong>
|
|||||||
@Override
|
@Override
|
||||||
public Collection<InternetSong> getSongsFromAlbum(Album album)
|
public Collection<InternetSong> getSongsFromAlbum(Album album)
|
||||||
{
|
{
|
||||||
|
synchronized (this.updating)
|
||||||
|
{
|
||||||
|
while (this.updating.get())
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
this.updating.wait();
|
||||||
|
}
|
||||||
|
catch (InterruptedException e)
|
||||||
|
{
|
||||||
|
logger.error("Error while waiting for update lock", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
synchronized (this.songs)
|
synchronized (this.songs)
|
||||||
{
|
{
|
||||||
return this.songs.values().stream().filter(song -> song.album.equals(album)).collect(Collectors.toUnmodifiableSet());
|
return this.songs.values().stream().filter(song -> song.album.equals(album)).collect(Collectors.toUnmodifiableSet());
|
||||||
@@ -160,6 +262,20 @@ public class InternetSongProvider implements SongProvider<InternetSong>
|
|||||||
@Override
|
@Override
|
||||||
public Collection<InternetSong> getSongsFromArtist(String artist)
|
public Collection<InternetSong> getSongsFromArtist(String artist)
|
||||||
{
|
{
|
||||||
|
synchronized (this.updating)
|
||||||
|
{
|
||||||
|
while (this.updating.get())
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
this.updating.wait();
|
||||||
|
}
|
||||||
|
catch (InterruptedException e)
|
||||||
|
{
|
||||||
|
logger.error("Error while waiting for update lock", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
synchronized (this.songs)
|
synchronized (this.songs)
|
||||||
{
|
{
|
||||||
return this.songs.values().stream().filter(song -> Arrays.asList(song.artists).contains(artist)).collect(Collectors.toUnmodifiableSet());
|
return this.songs.values().stream().filter(song -> Arrays.asList(song.artists).contains(artist)).collect(Collectors.toUnmodifiableSet());
|
||||||
@@ -176,6 +292,20 @@ public class InternetSongProvider implements SongProvider<InternetSong>
|
|||||||
@Override
|
@Override
|
||||||
public Album getAlbumByName(String name)
|
public Album getAlbumByName(String name)
|
||||||
{
|
{
|
||||||
|
synchronized (this.updating)
|
||||||
|
{
|
||||||
|
while (this.updating.get())
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
this.updating.wait();
|
||||||
|
}
|
||||||
|
catch (InterruptedException e)
|
||||||
|
{
|
||||||
|
logger.error("Error while waiting for update lock", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
synchronized (this.albums)
|
synchronized (this.albums)
|
||||||
{
|
{
|
||||||
return this.albums.get(name);
|
return this.albums.get(name);
|
||||||
@@ -191,6 +321,20 @@ public class InternetSongProvider implements SongProvider<InternetSong>
|
|||||||
@Override
|
@Override
|
||||||
public Collection<Album> getAlbumsFromArtist(String artist)
|
public Collection<Album> getAlbumsFromArtist(String artist)
|
||||||
{
|
{
|
||||||
|
synchronized (this.updating)
|
||||||
|
{
|
||||||
|
while (this.updating.get())
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
this.updating.wait();
|
||||||
|
}
|
||||||
|
catch (InterruptedException e)
|
||||||
|
{
|
||||||
|
logger.error("Error while waiting for update lock", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
synchronized (this.albums)
|
synchronized (this.albums)
|
||||||
{
|
{
|
||||||
return this.albums.values().stream().filter(album -> Arrays.asList(album.artists).contains(artist)).collect(Collectors.toUnmodifiableSet());
|
return this.albums.values().stream().filter(album -> Arrays.asList(album.artists).contains(artist)).collect(Collectors.toUnmodifiableSet());
|
||||||
@@ -206,6 +350,20 @@ public class InternetSongProvider implements SongProvider<InternetSong>
|
|||||||
@Override
|
@Override
|
||||||
public Collection<Album> getAlbumsFromGenre(String genre)
|
public Collection<Album> getAlbumsFromGenre(String genre)
|
||||||
{
|
{
|
||||||
|
synchronized (this.updating)
|
||||||
|
{
|
||||||
|
while (this.updating.get())
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
this.updating.wait();
|
||||||
|
}
|
||||||
|
catch (InterruptedException e)
|
||||||
|
{
|
||||||
|
logger.error("Error while waiting for update lock", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
synchronized (this.albums)
|
synchronized (this.albums)
|
||||||
{
|
{
|
||||||
return this.albums.values().stream().filter(album -> Arrays.asList(album.genres).contains(genre)).collect(Collectors.toUnmodifiableSet());
|
return this.albums.values().stream().filter(album -> Arrays.asList(album.genres).contains(genre)).collect(Collectors.toUnmodifiableSet());
|
||||||
@@ -221,6 +379,20 @@ public class InternetSongProvider implements SongProvider<InternetSong>
|
|||||||
@Override
|
@Override
|
||||||
public Collection<Album> getAlbumsFromYear(int year)
|
public Collection<Album> getAlbumsFromYear(int year)
|
||||||
{
|
{
|
||||||
|
synchronized (this.updating)
|
||||||
|
{
|
||||||
|
while (this.updating.get())
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
this.updating.wait();
|
||||||
|
}
|
||||||
|
catch (InterruptedException e)
|
||||||
|
{
|
||||||
|
logger.error("Error while waiting for update lock", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
synchronized (this.albums)
|
synchronized (this.albums)
|
||||||
{
|
{
|
||||||
return this.albums.values().stream().filter(album -> album.year == year).collect(Collectors.toUnmodifiableSet());
|
return this.albums.values().stream().filter(album -> album.year == year).collect(Collectors.toUnmodifiableSet());
|
||||||
@@ -341,6 +513,9 @@ public class InternetSongProvider implements SongProvider<InternetSong>
|
|||||||
InternetSong song;
|
InternetSong song;
|
||||||
int numAlbums = 0, numSongs = 0;
|
int numAlbums = 0, numSongs = 0;
|
||||||
|
|
||||||
|
synchronized (updating)
|
||||||
|
{
|
||||||
|
updating.set(true);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
logger.debug("Querying database.");
|
logger.debug("Querying database.");
|
||||||
@@ -366,7 +541,8 @@ public class InternetSongProvider implements SongProvider<InternetSong>
|
|||||||
}
|
}
|
||||||
|
|
||||||
state = DatabaseManager.getDb().createStatement();
|
state = DatabaseManager.getDb().createStatement();
|
||||||
result = state.executeQuery("SELECT name FROM sqlite_master WHERE type='table' AND name='INTERNET_ALBUMS';");
|
result = state
|
||||||
|
.executeQuery("SELECT name FROM sqlite_master WHERE type='table' AND name='INTERNET_ALBUMS';");
|
||||||
if (!result.next())
|
if (!result.next())
|
||||||
{
|
{
|
||||||
logger.debug("Creating album table.");
|
logger.debug("Creating album table.");
|
||||||
@@ -383,7 +559,8 @@ public class InternetSongProvider implements SongProvider<InternetSong>
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
result = state.executeQuery("SELECT * FROM INTERNET_ALBUMS;");
|
result = state
|
||||||
|
.executeQuery("SELECT * FROM INTERNET_ALBUMS;");
|
||||||
while (result.next())
|
while (result.next())
|
||||||
{
|
{
|
||||||
album = albums.get(result.getString("album"));
|
album = albums.get(result.getString("album"));
|
||||||
@@ -393,15 +570,22 @@ public class InternetSongProvider implements SongProvider<InternetSong>
|
|||||||
album.name = result.getString("album");
|
album.name = result.getString("album");
|
||||||
albums.put(album.name, album);
|
albums.put(album.name, album);
|
||||||
}
|
}
|
||||||
album.artists = Optional.ofNullable(result.getString("artists")).map(s -> s.split(";")).orElse(new String[0]);
|
album.artists = Optional
|
||||||
|
.ofNullable(result.getString("artists"))
|
||||||
|
.map(s -> s.split(";"))
|
||||||
|
.orElse(new String[0]);
|
||||||
album.year = result.getInt("year");
|
album.year = result.getInt("year");
|
||||||
album.genres = Optional.ofNullable(result.getString("genres")).map(s -> s.split(";")).orElse(new String[0]);
|
album.genres = Optional
|
||||||
|
.ofNullable(result.getString("genres"))
|
||||||
|
.map(s -> s.split(";"))
|
||||||
|
.orElse(new String[0]);
|
||||||
album.totalTracks = result.getInt("tracks");
|
album.totalTracks = result.getInt("tracks");
|
||||||
album.totalDiscs = result.getInt("discs");
|
album.totalDiscs = result.getInt("discs");
|
||||||
numAlbums++;
|
numAlbums++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
result = state.executeQuery("SELECT name FROM sqlite_master WHERE type='table' AND name='INTERNET_SONGS';");
|
result = state
|
||||||
|
.executeQuery("SELECT name FROM sqlite_master WHERE type='table' AND name='INTERNET_SONGS';");
|
||||||
if (!result.next())
|
if (!result.next())
|
||||||
{
|
{
|
||||||
logger.debug("Creating song table.");
|
logger.debug("Creating song table.");
|
||||||
@@ -419,7 +603,8 @@ public class InternetSongProvider implements SongProvider<InternetSong>
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
result = state.executeQuery("SELECT * FROM INTERNET_SONGS;");
|
result = state
|
||||||
|
.executeQuery("SELECT * FROM INTERNET_SONGS;");
|
||||||
while (result.next())
|
while (result.next())
|
||||||
{
|
{
|
||||||
if (result.getString("url") == null)
|
if (result.getString("url") == null)
|
||||||
@@ -433,7 +618,8 @@ public class InternetSongProvider implements SongProvider<InternetSong>
|
|||||||
}
|
}
|
||||||
catch (MalformedURLException e)
|
catch (MalformedURLException e)
|
||||||
{
|
{
|
||||||
logger.error("Could not parse URL " + result.getString("url"), e);
|
logger.error("Could not parse URL " + result
|
||||||
|
.getString("url"), e);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
song = songs.get(url);
|
song = songs.get(url);
|
||||||
@@ -444,11 +630,17 @@ public class InternetSongProvider implements SongProvider<InternetSong>
|
|||||||
songs.put(song.location, song);
|
songs.put(song.location, song);
|
||||||
}
|
}
|
||||||
song.title = result.getString("title");
|
song.title = result.getString("title");
|
||||||
song.artists = Optional.ofNullable(result.getString("artists")).map(s -> s.split(";")).orElse(new String[0]);
|
song.artists = Optional
|
||||||
|
.ofNullable(result.getString("artists"))
|
||||||
|
.map(s -> s.split(";"))
|
||||||
|
.orElse(new String[0]);
|
||||||
song.trackNum = result.getInt("track");
|
song.trackNum = result.getInt("track");
|
||||||
song.disc = result.getInt("disc");
|
song.disc = result.getInt("disc");
|
||||||
song.duration = result.getLong("duration");
|
song.duration = result.getLong("duration");
|
||||||
song.album = Optional.ofNullable(result.getString("album")).map(albums::get).orElse(albums.get("Unknown"));
|
song.album = Optional
|
||||||
|
.ofNullable(result.getString("album"))
|
||||||
|
.map(albums::get)
|
||||||
|
.orElse(albums.get("Unknown"));
|
||||||
numSongs++;
|
numSongs++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -462,6 +654,9 @@ public class InternetSongProvider implements SongProvider<InternetSong>
|
|||||||
logger.debug("Query complete, retrieved {} albums and {} songs", numAlbums, numSongs);
|
logger.debug("Query complete, retrieved {} albums and {} songs", numAlbums, numSongs);
|
||||||
updatedSongs = 0;
|
updatedSongs = 0;
|
||||||
totalUpdate = 0;
|
totalUpdate = 0;
|
||||||
|
updating.set(false);
|
||||||
|
updating.notifyAll();
|
||||||
|
}
|
||||||
triggerUpdateListeners();
|
triggerUpdateListeners();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import java.io.IOException;
|
|||||||
import java.sql.*;
|
import java.sql.*;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.concurrent.*;
|
import java.util.concurrent.*;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
@@ -28,6 +29,7 @@ public class LocalSongProvider implements SongProvider<LocalSong>
|
|||||||
|
|
||||||
private final File source;
|
private final File source;
|
||||||
|
|
||||||
|
private final AtomicBoolean updating = new AtomicBoolean(false);
|
||||||
private final HashMap<File, LocalSong> songs = new HashMap<>();
|
private final HashMap<File, LocalSong> songs = new HashMap<>();
|
||||||
private final HashMap<String, Album> albums = new HashMap<>();
|
private final HashMap<String, Album> albums = new HashMap<>();
|
||||||
/**
|
/**
|
||||||
@@ -174,6 +176,7 @@ public class LocalSongProvider implements SongProvider<LocalSong>
|
|||||||
|
|
||||||
private void getSongCache()
|
private void getSongCache()
|
||||||
{
|
{
|
||||||
|
updating.set(true);
|
||||||
service.submit(new SongQuery(true));
|
service.submit(new SongQuery(true));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -185,6 +188,20 @@ public class LocalSongProvider implements SongProvider<LocalSong>
|
|||||||
@Override
|
@Override
|
||||||
public Collection<Album> getAlbums()
|
public Collection<Album> getAlbums()
|
||||||
{
|
{
|
||||||
|
synchronized (this.updating)
|
||||||
|
{
|
||||||
|
while (this.updating.get())
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
this.updating.wait();
|
||||||
|
}
|
||||||
|
catch (InterruptedException e)
|
||||||
|
{
|
||||||
|
logger.error("Error while waiting for update lock", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
return this.albums.values();
|
return this.albums.values();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -196,6 +213,20 @@ public class LocalSongProvider implements SongProvider<LocalSong>
|
|||||||
@Override
|
@Override
|
||||||
public Collection<LocalSong> getSongs()
|
public Collection<LocalSong> getSongs()
|
||||||
{
|
{
|
||||||
|
synchronized (this.updating)
|
||||||
|
{
|
||||||
|
while (this.updating.get())
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
this.updating.wait();
|
||||||
|
}
|
||||||
|
catch (InterruptedException e)
|
||||||
|
{
|
||||||
|
logger.error("Error while waiting for update lock", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
synchronized (this.songs)
|
synchronized (this.songs)
|
||||||
{
|
{
|
||||||
return Collections.unmodifiableCollection(this.songs.values());
|
return Collections.unmodifiableCollection(this.songs.values());
|
||||||
@@ -210,6 +241,20 @@ public class LocalSongProvider implements SongProvider<LocalSong>
|
|||||||
@Override
|
@Override
|
||||||
public Collection<String> getArtists()
|
public Collection<String> getArtists()
|
||||||
{
|
{
|
||||||
|
synchronized (this.updating)
|
||||||
|
{
|
||||||
|
while (this.updating.get())
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
this.updating.wait();
|
||||||
|
}
|
||||||
|
catch (InterruptedException e)
|
||||||
|
{
|
||||||
|
logger.error("Error while waiting for update lock", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
return this.artists;
|
return this.artists;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -221,6 +266,20 @@ public class LocalSongProvider implements SongProvider<LocalSong>
|
|||||||
@Override
|
@Override
|
||||||
public Collection<String> getAlbumArtists()
|
public Collection<String> getAlbumArtists()
|
||||||
{
|
{
|
||||||
|
synchronized (this.updating)
|
||||||
|
{
|
||||||
|
while (this.updating.get())
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
this.updating.wait();
|
||||||
|
}
|
||||||
|
catch (InterruptedException e)
|
||||||
|
{
|
||||||
|
logger.error("Error while waiting for update lock", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
return this.albumArtists;
|
return this.albumArtists;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -232,6 +291,20 @@ public class LocalSongProvider implements SongProvider<LocalSong>
|
|||||||
@Override
|
@Override
|
||||||
public Collection<String> getGenres()
|
public Collection<String> getGenres()
|
||||||
{
|
{
|
||||||
|
synchronized (this.updating)
|
||||||
|
{
|
||||||
|
while (this.updating.get())
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
this.updating.wait();
|
||||||
|
}
|
||||||
|
catch (InterruptedException e)
|
||||||
|
{
|
||||||
|
logger.error("Error while waiting for update lock", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
return this.genres;
|
return this.genres;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -243,6 +316,20 @@ public class LocalSongProvider implements SongProvider<LocalSong>
|
|||||||
@Override
|
@Override
|
||||||
public Collection<Integer> getYears()
|
public Collection<Integer> getYears()
|
||||||
{
|
{
|
||||||
|
synchronized (this.updating)
|
||||||
|
{
|
||||||
|
while (this.updating.get())
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
this.updating.wait();
|
||||||
|
}
|
||||||
|
catch (InterruptedException e)
|
||||||
|
{
|
||||||
|
logger.error("Error while waiting for update lock", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
return this.years;
|
return this.years;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -256,6 +343,20 @@ public class LocalSongProvider implements SongProvider<LocalSong>
|
|||||||
@Override
|
@Override
|
||||||
public Collection<LocalSong> getSongsFromAlbum(Album album)
|
public Collection<LocalSong> getSongsFromAlbum(Album album)
|
||||||
{
|
{
|
||||||
|
synchronized (this.updating)
|
||||||
|
{
|
||||||
|
while (this.updating.get())
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
this.updating.wait();
|
||||||
|
}
|
||||||
|
catch (InterruptedException e)
|
||||||
|
{
|
||||||
|
logger.error("Error while waiting for update lock", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
synchronized (this.songs)
|
synchronized (this.songs)
|
||||||
{
|
{
|
||||||
return this.songs.values().stream()
|
return this.songs.values().stream()
|
||||||
@@ -274,6 +375,20 @@ public class LocalSongProvider implements SongProvider<LocalSong>
|
|||||||
@Override
|
@Override
|
||||||
public Collection<LocalSong> getSongsFromArtist(String artist)
|
public Collection<LocalSong> getSongsFromArtist(String artist)
|
||||||
{
|
{
|
||||||
|
synchronized (this.updating)
|
||||||
|
{
|
||||||
|
while (this.updating.get())
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
this.updating.wait();
|
||||||
|
}
|
||||||
|
catch (InterruptedException e)
|
||||||
|
{
|
||||||
|
logger.error("Error while waiting for update lock", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
synchronized (this.songs)
|
synchronized (this.songs)
|
||||||
{
|
{
|
||||||
return this.songs.values().stream()
|
return this.songs.values().stream()
|
||||||
@@ -293,6 +408,20 @@ public class LocalSongProvider implements SongProvider<LocalSong>
|
|||||||
@Override
|
@Override
|
||||||
public Album getAlbumByName(String name)
|
public Album getAlbumByName(String name)
|
||||||
{
|
{
|
||||||
|
synchronized (this.updating)
|
||||||
|
{
|
||||||
|
while (this.updating.get())
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
this.updating.wait();
|
||||||
|
}
|
||||||
|
catch (InterruptedException e)
|
||||||
|
{
|
||||||
|
logger.error("Error while waiting for update lock", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
synchronized (this.albums)
|
synchronized (this.albums)
|
||||||
{
|
{
|
||||||
return this.albums.get(name);
|
return this.albums.get(name);
|
||||||
@@ -308,6 +437,20 @@ public class LocalSongProvider implements SongProvider<LocalSong>
|
|||||||
@Override
|
@Override
|
||||||
public Collection<Album> getAlbumsFromArtist(String artist)
|
public Collection<Album> getAlbumsFromArtist(String artist)
|
||||||
{
|
{
|
||||||
|
synchronized (this.updating)
|
||||||
|
{
|
||||||
|
while (this.updating.get())
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
this.updating.wait();
|
||||||
|
}
|
||||||
|
catch (InterruptedException e)
|
||||||
|
{
|
||||||
|
logger.error("Error while waiting for update lock", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
synchronized (this.albums)
|
synchronized (this.albums)
|
||||||
{
|
{
|
||||||
return this.albums.values().stream()
|
return this.albums.values().stream()
|
||||||
@@ -326,6 +469,20 @@ public class LocalSongProvider implements SongProvider<LocalSong>
|
|||||||
@Override
|
@Override
|
||||||
public Collection<Album> getAlbumsFromGenre(String genre)
|
public Collection<Album> getAlbumsFromGenre(String genre)
|
||||||
{
|
{
|
||||||
|
synchronized (this.updating)
|
||||||
|
{
|
||||||
|
while (this.updating.get())
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
this.updating.wait();
|
||||||
|
}
|
||||||
|
catch (InterruptedException e)
|
||||||
|
{
|
||||||
|
logger.error("Error while waiting for update lock", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
synchronized (this.albums)
|
synchronized (this.albums)
|
||||||
{
|
{
|
||||||
return this.albums.values().stream()
|
return this.albums.values().stream()
|
||||||
@@ -344,6 +501,20 @@ public class LocalSongProvider implements SongProvider<LocalSong>
|
|||||||
@Override
|
@Override
|
||||||
public Collection<Album> getAlbumsFromYear(int year)
|
public Collection<Album> getAlbumsFromYear(int year)
|
||||||
{
|
{
|
||||||
|
synchronized (this.updating)
|
||||||
|
{
|
||||||
|
while (this.updating.get())
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
this.updating.wait();
|
||||||
|
}
|
||||||
|
catch (InterruptedException e)
|
||||||
|
{
|
||||||
|
logger.error("Error while waiting for update lock", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
synchronized (this.albums)
|
synchronized (this.albums)
|
||||||
{
|
{
|
||||||
return this.albums.values().stream()
|
return this.albums.values().stream()
|
||||||
@@ -962,6 +1133,9 @@ public class LocalSongProvider implements SongProvider<LocalSong>
|
|||||||
LocalSong song;
|
LocalSong song;
|
||||||
int numAlbums = 0, numSongs = 0;
|
int numAlbums = 0, numSongs = 0;
|
||||||
|
|
||||||
|
updating.set(true);
|
||||||
|
synchronized (updating)
|
||||||
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
logger.debug("Querying database.");
|
logger.debug("Querying database.");
|
||||||
@@ -1061,11 +1235,13 @@ public class LocalSongProvider implements SongProvider<LocalSong>
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
song = songs
|
song = songs
|
||||||
.get(new File(result.getString("file")));
|
.get(new File(result
|
||||||
|
.getString("file")));
|
||||||
if (song == null)
|
if (song == null)
|
||||||
{
|
{
|
||||||
song = new LocalSong();
|
song = new LocalSong();
|
||||||
song.file = new File(result.getString("file"));
|
song.file = new File(result
|
||||||
|
.getString("file"));
|
||||||
songs.put(song.file, song);
|
songs.put(song.file, song);
|
||||||
}
|
}
|
||||||
song.codec = result.getString("codec");
|
song.codec = result.getString("codec");
|
||||||
@@ -1095,8 +1271,11 @@ public class LocalSongProvider implements SongProvider<LocalSong>
|
|||||||
logger.debug("Query complete, retrieved {} albums and {} songs", numAlbums, numSongs);
|
logger.debug("Query complete, retrieved {} albums and {} songs", numAlbums, numSongs);
|
||||||
updatedSongs = 0;
|
updatedSongs = 0;
|
||||||
totalUpdate = 0;
|
totalUpdate = 0;
|
||||||
triggerUpdateListeners();
|
|
||||||
|
|
||||||
|
updating.set(false);
|
||||||
|
updating.notifyAll();
|
||||||
|
}
|
||||||
|
triggerUpdateListeners();
|
||||||
if (scan)
|
if (scan)
|
||||||
{
|
{
|
||||||
LinkedList<SongScanner> scanners = new LinkedList<>();
|
LinkedList<SongScanner> scanners = new LinkedList<>();
|
||||||
|
|||||||
@@ -102,7 +102,7 @@ public class Interface extends JFrame implements SongDisplayListener, ComponentL
|
|||||||
this.constructWindow();
|
this.constructWindow();
|
||||||
this.setFocusManager();
|
this.setFocusManager();
|
||||||
|
|
||||||
this.updateSongs(SongProvider.INSTANCE.getSongs());
|
// this.updateSongs(SongProvider.INSTANCE.getSongs());
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void initActions()
|
protected void initActions()
|
||||||
@@ -575,7 +575,6 @@ public class Interface extends JFrame implements SongDisplayListener, ComponentL
|
|||||||
{
|
{
|
||||||
this.songList.listAlbums(songs);
|
this.songList.listAlbums(songs);
|
||||||
this.centerView.setViewportView(this.songList);
|
this.centerView.setViewportView(this.songList);
|
||||||
this.songList.revalidate();
|
|
||||||
this.centerView.revalidate();
|
this.centerView.revalidate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -82,7 +82,26 @@ public class SongList extends ScrollablePanel
|
|||||||
*
|
*
|
||||||
* @param songs - The songs to display.
|
* @param songs - The songs to display.
|
||||||
*/
|
*/
|
||||||
public void listAlbums(Collection<? extends Song> songs)
|
public SwingWorker listAlbums(Collection<? extends Song> songs)
|
||||||
|
{
|
||||||
|
SwingWorker worker = new SwingWorker<>()
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Computes a result, or throws an exception if unable
|
||||||
|
* to do so.
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* Note that this method is executed only once.
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* Note: this method is executed in a background
|
||||||
|
* thread.
|
||||||
|
*
|
||||||
|
* @return the computed result
|
||||||
|
* @throws Exception if unable to compute a result
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected Object doInBackground() throws Exception
|
||||||
{
|
{
|
||||||
logger.debug("Sorting {} songs...", songs.size());
|
logger.debug("Sorting {} songs...", songs.size());
|
||||||
Map<Album, List<Song>> albums = songs.stream().sorted().collect(Collectors
|
Map<Album, List<Song>> albums = songs.stream().sorted().collect(Collectors
|
||||||
@@ -94,11 +113,15 @@ public class SongList extends ScrollablePanel
|
|||||||
c.fill = GridBagConstraints.HORIZONTAL;
|
c.fill = GridBagConstraints.HORIZONTAL;
|
||||||
AtomicInteger i = new AtomicInteger(0);
|
AtomicInteger i = new AtomicInteger(0);
|
||||||
|
|
||||||
this.labelMap.clear();
|
SwingUtilities.invokeLater(() -> {
|
||||||
this.artMap.clear();
|
labelMap.clear();
|
||||||
this.removeAll();
|
artMap.clear();
|
||||||
this.currentAlbums = albums;
|
removeAll();
|
||||||
|
currentAlbums = albums;
|
||||||
|
});
|
||||||
|
|
||||||
|
LinkedHashMap<JComponent, GridBagConstraints> albumInfos =
|
||||||
|
new LinkedHashMap<>();
|
||||||
albums.keySet().stream().sorted().forEach((album) -> {
|
albums.keySet().stream().sorted().forEach((album) -> {
|
||||||
List<Song> songCollection = albums.get(album);
|
List<Song> songCollection = albums.get(album);
|
||||||
|
|
||||||
@@ -120,7 +143,7 @@ public class SongList extends ScrollablePanel
|
|||||||
albumInfo.albumName.addMouseListener((ClickListener) e -> {
|
albumInfo.albumName.addMouseListener((ClickListener) e -> {
|
||||||
if (e.getClickCount() == 2)
|
if (e.getClickCount() == 2)
|
||||||
{
|
{
|
||||||
Container inter = this;
|
Container inter = SongList.this;
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
inter = inter.getParent();
|
inter = inter.getParent();
|
||||||
@@ -137,7 +160,7 @@ public class SongList extends ScrollablePanel
|
|||||||
albumInfo.artists.addMouseListener((ClickListener) e -> {
|
albumInfo.artists.addMouseListener((ClickListener) e -> {
|
||||||
if (e.getClickCount() == 2)
|
if (e.getClickCount() == 2)
|
||||||
{
|
{
|
||||||
Container inter = this;
|
Container inter = SongList.this;
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
inter = inter.getParent();
|
inter = inter.getParent();
|
||||||
@@ -159,7 +182,7 @@ public class SongList extends ScrollablePanel
|
|||||||
albumInfo.genres.addMouseListener((ClickListener) e -> {
|
albumInfo.genres.addMouseListener((ClickListener) e -> {
|
||||||
if (e.getClickCount() == 2)
|
if (e.getClickCount() == 2)
|
||||||
{
|
{
|
||||||
Container inter = this;
|
Container inter = SongList.this;
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
inter = inter.getParent();
|
inter = inter.getParent();
|
||||||
@@ -180,7 +203,7 @@ public class SongList extends ScrollablePanel
|
|||||||
albumInfo.year.addMouseListener((ClickListener) e -> {
|
albumInfo.year.addMouseListener((ClickListener) e -> {
|
||||||
if (e.getClickCount() == 2)
|
if (e.getClickCount() == 2)
|
||||||
{
|
{
|
||||||
Container inter = this;
|
Container inter = SongList.this;
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
inter = inter.getParent();
|
inter = inter.getParent();
|
||||||
@@ -195,13 +218,14 @@ public class SongList extends ScrollablePanel
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
this.add(albumInfo, c);
|
albumInfos.put(albumInfo, (GridBagConstraints) c.clone());
|
||||||
this.artMap.put(albumInfo, album);
|
artMap.put(albumInfo, album);
|
||||||
|
|
||||||
JButton firstSong = null;
|
JButton firstSong = null;
|
||||||
|
|
||||||
JLabel songNum;
|
JLabel songNum;
|
||||||
JButton songTitle;
|
JButton songTitle;
|
||||||
|
AtomicInteger numSongs = new AtomicInteger();
|
||||||
for (Song song : songCollection)
|
for (Song song : songCollection)
|
||||||
{
|
{
|
||||||
songNum = new JLabel(String.valueOf(song.trackNum));
|
songNum = new JLabel(String.valueOf(song.trackNum));
|
||||||
@@ -212,8 +236,8 @@ public class SongList extends ScrollablePanel
|
|||||||
c.weightx = 0;
|
c.weightx = 0;
|
||||||
c.anchor = GridBagConstraints.NORTHEAST;
|
c.anchor = GridBagConstraints.NORTHEAST;
|
||||||
c.insets = new Insets(0, 0, 0, 0);
|
c.insets = new Insets(0, 0, 0, 0);
|
||||||
this.add(songNum, c);
|
albumInfos.put(songNum, (GridBagConstraints) c.clone());
|
||||||
this.labelMap.put(songNum, song);
|
labelMap.put(songNum, song);
|
||||||
|
|
||||||
songTitle = new JButton(song.title);
|
songTitle = new JButton(song.title);
|
||||||
if (song.title == null || song.title.isEmpty())
|
if (song.title == null || song.title.isEmpty())
|
||||||
@@ -244,8 +268,8 @@ public class SongList extends ScrollablePanel
|
|||||||
c.weightx = 1.0;
|
c.weightx = 1.0;
|
||||||
c.anchor = GridBagConstraints.NORTHWEST;
|
c.anchor = GridBagConstraints.NORTHWEST;
|
||||||
c.insets = new Insets(0, 10, 0, 0);
|
c.insets = new Insets(0, 10, 0, 0);
|
||||||
this.add(songTitle, c);
|
albumInfos.put(songTitle, (GridBagConstraints) c.clone());
|
||||||
this.labelMap.put(songTitle, song);
|
labelMap.put(songTitle, song);
|
||||||
// TODO - Add song length or something
|
// TODO - Add song length or something
|
||||||
|
|
||||||
if (firstSong == null)
|
if (firstSong == null)
|
||||||
@@ -275,6 +299,7 @@ public class SongList extends ScrollablePanel
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
i.getAndIncrement();
|
i.getAndIncrement();
|
||||||
|
this.setProgress((int) (numSongs.incrementAndGet() / (float) songs.size() * 100F));
|
||||||
}
|
}
|
||||||
// this.add(new JLabel(new ImageIcon(this.getClass().getResource("/gui/icons/defaultart.png"), "Default")), c);
|
// this.add(new JLabel(new ImageIcon(this.getClass().getResource("/gui/icons/defaultart.png"), "Default")), c);
|
||||||
|
|
||||||
@@ -282,11 +307,25 @@ public class SongList extends ScrollablePanel
|
|||||||
c.gridy = i.getAndIncrement();
|
c.gridy = i.getAndIncrement();
|
||||||
c.gridwidth = 3;
|
c.gridwidth = 3;
|
||||||
c.anchor = GridBagConstraints.NORTH;
|
c.anchor = GridBagConstraints.NORTH;
|
||||||
this.add(new JSeparator(SwingConstants.HORIZONTAL), c);
|
albumInfos.put(new JSeparator(SwingConstants.HORIZONTAL),
|
||||||
|
(GridBagConstraints) c.clone());
|
||||||
|
|
||||||
i.getAndIncrement();
|
i.getAndIncrement();
|
||||||
});
|
});
|
||||||
logger.debug("Song list built");
|
logger.debug("Song list built {} components",
|
||||||
|
albumInfos.size());
|
||||||
|
SwingUtilities.invokeLater(() -> {
|
||||||
|
albumInfos.forEach((component, c1) -> {
|
||||||
|
add(component, c1);
|
||||||
|
});
|
||||||
|
revalidate();
|
||||||
|
logger.debug("Components added");
|
||||||
|
});
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
worker.execute();
|
||||||
|
return worker;
|
||||||
}
|
}
|
||||||
|
|
||||||
private class SongListPolicy extends FocusTraversalPolicy
|
private class SongListPolicy extends FocusTraversalPolicy
|
||||||
|
|||||||
Reference in New Issue
Block a user