From 2b3aea51faeacda81b56007dead357480753722a Mon Sep 17 00:00:00 2001 From: Tom Date: Tue, 4 Jun 2013 19:56:51 +0100 Subject: updated project files and keystore --- subsonic-android/ant.properties | 20 -------------------- subsonic-android/subsonic.keystore | Bin 1194 -> 2262 bytes 2 files changed, 20 deletions(-) delete mode 100644 subsonic-android/ant.properties (limited to 'subsonic-android') diff --git a/subsonic-android/ant.properties b/subsonic-android/ant.properties deleted file mode 100644 index de5f19ef..00000000 --- a/subsonic-android/ant.properties +++ /dev/null @@ -1,20 +0,0 @@ -# This file is used to override default values used by the Ant build system. -# -# This file must be checked in Version Control Systems, as it is -# integral to the build system of your project. - -# This file is only used by the Ant script. - -# You can use this to override default values such as -# 'source.dir' for the location of your java source folder and -# 'out.dir' for the location of your output folder. - -# You can also use it define how the release builds are signed by declaring -# the following properties: -# 'key.store' for the location of your keystore and -# 'key.alias' for the name of the key to use. -# The password will be asked during the build when you use the 'release' target. - -key.store=C:/Users/Scott/Documents/Subsonic/subsonic-android/subsonic.keystore -key.alias=subsonic - diff --git a/subsonic-android/subsonic.keystore b/subsonic-android/subsonic.keystore index 46996d4c..60d57868 100644 Binary files a/subsonic-android/subsonic.keystore and b/subsonic-android/subsonic.keystore differ -- cgit v1.2.3 From 96d6c306e75533423137a31b3cff378f7f916d8d Mon Sep 17 00:00:00 2001 From: Tom Date: Tue, 4 Jun 2013 20:02:56 +0100 Subject: Added Offline Scrobbling functionality: FileUtil: new function to return name of offline scrobbles file CachedMusicService: added code to scrobble() that appends to offline scrobbles file a search query made from song path and the millis time of that song play RESTMusicService: override scrobble function that also takes time in millis of scrobble RESTMusicService: new function to look for offline scrobbleis file and process it by using searchNew to get the song id using the cached query (needs putting on a thread) RESTMusicServer: Added call to processOfflineScrobbles in checkLicence --- .../dsub/service/OfflineMusicService.java | 23 +++++++- .../daneren2005/dsub/service/RESTMusicService.java | 67 +++++++++++++++++++++- .../github/daneren2005/dsub/util/Constants.java | 2 + .../src/github/daneren2005/dsub/util/FileUtil.java | 5 ++ .../src/github/daneren2005/dsub/util/Util.java | 4 +- 5 files changed, 96 insertions(+), 5 deletions(-) (limited to 'subsonic-android') diff --git a/subsonic-android/src/github/daneren2005/dsub/service/OfflineMusicService.java b/subsonic-android/src/github/daneren2005/dsub/service/OfflineMusicService.java index 9af58b16..83c7f960 100644 --- a/subsonic-android/src/github/daneren2005/dsub/service/OfflineMusicService.java +++ b/subsonic-android/src/github/daneren2005/dsub/service/OfflineMusicService.java @@ -36,6 +36,7 @@ import android.content.SharedPreferences; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.media.MediaMetadataRetriever; +import android.os.Environment; import android.util.Log; import github.daneren2005.dsub.domain.Artist; import github.daneren2005.dsub.domain.Genre; @@ -429,7 +430,27 @@ public class OfflineMusicService extends RESTMusicService { @Override public void scrobble(String id, boolean submission, Context context, ProgressListener progressListener) throws Exception { - throw new OfflineException("Scrobbling not available in offline mode"); + + if(!submission) + return; + + SharedPreferences prefs = Util.getPreferences(context); + String cacheLocn = prefs.getString(Constants.PREFERENCES_KEY_CACHE_LOCATION, null); + + File offlineScrobblesFile = FileUtil.getOfflineScrobblesFile(); + + String scrobbleSearchCriteria = id.replace(cacheLocn, ""); + if(scrobbleSearchCriteria.startsWith("/")) + scrobbleSearchCriteria = scrobbleSearchCriteria.substring(1); + + scrobbleSearchCriteria = scrobbleSearchCriteria.replace(".complete", "").replace(".partial", ""); + scrobbleSearchCriteria = scrobbleSearchCriteria.replace("/", " ").replace("-", "\\-").replace(".", "\\."); + + BufferedWriter bw = new BufferedWriter(new FileWriter(offlineScrobblesFile)); + bw.write(scrobbleSearchCriteria + "," + System.currentTimeMillis()); + bw.newLine(); + bw.flush(); + bw.close(); } @Override diff --git a/subsonic-android/src/github/daneren2005/dsub/service/RESTMusicService.java b/subsonic-android/src/github/daneren2005/dsub/service/RESTMusicService.java index f4f64046..be0763e7 100644 --- a/subsonic-android/src/github/daneren2005/dsub/service/RESTMusicService.java +++ b/subsonic-android/src/github/daneren2005/dsub/service/RESTMusicService.java @@ -163,6 +163,54 @@ public class RESTMusicService implements MusicService { return org.apache.http.conn.ssl.SSLSocketFactory.getSocketFactory(); } } + + public void processOfflineScrobbles(final Context context, final ProgressListener progressListener){ + File offlineScrobblesFile = FileUtil.getOfflineScrobblesFile(); + try{ + + BufferedReader br = new BufferedReader(new FileReader(offlineScrobblesFile)); + String line; + + ArrayList lines = new ArrayList(); + while ((line = br.readLine()) != null) { + lines.add(line); + } + br.close(); + offlineScrobblesFile.delete(); + + //TODO make a prompt: "Found " + lines.size() + " offline scrobbles. Scrobble? Ignore? Clear File?" + for(int i = 0; i < lines.size(); i++){ + line = lines.get(i); + String filename = line.substring(0, line.lastIndexOf(',')); + + Log.i(TAG, "Searching for id of file" + filename); + try{ + long time = Long.parseLong(line.substring(line.lastIndexOf(',')+1)); + SearchCritera critera = new SearchCritera(filename, 0, 0, 1); + SearchResult result = searchNew(critera, context, progressListener); + if(result.getSongs().size() == 1){ + Log.i(TAG, "Query '" + filename + "' returned song " + result.getSongs().get(0).getTitle() + " by " + result.getSongs().get(0).getArtist() + " with id " + result.getSongs().get(0).getId()); + Log.i(TAG, "Scrobbling " + result.getSongs().get(0).getId() + " with time " + time); + scrobble(result.getSongs().get(0).getId(), true, time, context, progressListener); + } + } + catch(Exception e){ + Log.e(TAG, e.toString()); + BufferedWriter bw = new BufferedWriter(new FileWriter(offlineScrobblesFile)); + bw.write(line); + bw.newLine(); + bw.flush(); + bw.close(); + } + } + } + catch(FileNotFoundException fnfe){ + //ignore, we dont care + } + catch(Exception e){ + Log.e(TAG, e.toString()); + } + } @Override public void ping(Context context, ProgressListener progressListener) throws Exception { @@ -176,7 +224,11 @@ public class RESTMusicService implements MusicService { @Override public boolean isLicenseValid(Context context, ProgressListener progressListener) throws Exception { - Reader reader = getReader(context, progressListener, "getLicense", null); + + //TODO run on a thread + processOfflineScrobbles(context, progressListener); + + Reader reader = getReader(context, progressListener, "getLicense", null); try { ServerInfo serverInfo = new LicenseParser(context).parse(reader); return serverInfo.isLicenseValid(); @@ -186,6 +238,7 @@ public class RESTMusicService implements MusicService { } public List getMusicFolders(boolean refresh, Context context, ProgressListener progressListener) throws Exception { + List cachedMusicFolders = readCachedMusicFolders(context); if (cachedMusicFolders != null && !refresh) { return cachedMusicFolders; @@ -464,8 +517,18 @@ public class RESTMusicService implements MusicService { @Override public void scrobble(String id, boolean submission, Context context, ProgressListener progressListener) throws Exception { + scrobble(id, submission, 0, context, progressListener); + } + + public void scrobble(String id, boolean submission, long time, Context context, ProgressListener progressListener) throws Exception { checkServerVersion(context, "1.5", "Scrobbling not supported."); - Reader reader = getReader(context, progressListener, "scrobble", null, Arrays.asList("id", "submission"), Arrays.asList(id, submission)); + Reader reader; + if(time > 0){ + checkServerVersion(context, "1.8", "Scrobbling with a time not supported."); + reader = getReader(context, progressListener, "scrobble", null, Arrays.asList("id", "submission", "time"), Arrays.asList(id, submission, time)); + } + else + reader = getReader(context, progressListener, "scrobble", null, Arrays.asList("id", "submission"), Arrays.asList(id, submission)); try { new ErrorParser(context).parse(reader); } finally { diff --git a/subsonic-android/src/github/daneren2005/dsub/util/Constants.java b/subsonic-android/src/github/daneren2005/dsub/util/Constants.java index 5de13e73..af5f7e08 100644 --- a/subsonic-android/src/github/daneren2005/dsub/util/Constants.java +++ b/subsonic-android/src/github/daneren2005/dsub/util/Constants.java @@ -125,6 +125,8 @@ public final class Constants { public static final String DONATION_URL = "http://subsonic.org/pages/android-donation.jsp"; public static final String ALBUM_ART_FILE = "albumart.jpg"; + + public static final String OFFLINE_SCROBBLES_FILE = "offline_scrobbles.log"; private Constants() { } diff --git a/subsonic-android/src/github/daneren2005/dsub/util/FileUtil.java b/subsonic-android/src/github/daneren2005/dsub/util/FileUtil.java index 7ead874c..ca06b55f 100644 --- a/subsonic-android/src/github/daneren2005/dsub/util/FileUtil.java +++ b/subsonic-android/src/github/daneren2005/dsub/util/FileUtil.java @@ -149,6 +149,11 @@ public class FileUtil { } return dir; } + + public static File getOfflineScrobblesFile(){ + File offlineScrobblesFile = new File(getSubsonicDirectory(), fileSystemSafe(Constants.OFFLINE_SCROBBLES_FILE)); + return offlineScrobblesFile; + } public static void createDirectoryForParent(File file) { File dir = file.getParentFile(); diff --git a/subsonic-android/src/github/daneren2005/dsub/util/Util.java b/subsonic-android/src/github/daneren2005/dsub/util/Util.java index a8918923..9d785212 100644 --- a/subsonic-android/src/github/daneren2005/dsub/util/Util.java +++ b/subsonic-android/src/github/daneren2005/dsub/util/Util.java @@ -147,9 +147,9 @@ public final class Util { } public static boolean isScrobblingEnabled(Context context) { - if (isOffline(context)) { + /*if (isOffline(context)) { return false; - } + }*/ SharedPreferences prefs = getPreferences(context); return prefs.getBoolean(Constants.PREFERENCES_KEY_SCROBBLE, false); } -- cgit v1.2.3 From 240f7521c82f693863b3ba398d2a75a2d3b67399 Mon Sep 17 00:00:00 2001 From: Tom Briden Date: Wed, 5 Jun 2013 08:30:25 +0100 Subject: open the offline scrobbles file in append mode, d'oh --- .../src/github/daneren2005/dsub/service/OfflineMusicService.java | 2 +- .../src/github/daneren2005/dsub/service/RESTMusicService.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'subsonic-android') diff --git a/subsonic-android/src/github/daneren2005/dsub/service/OfflineMusicService.java b/subsonic-android/src/github/daneren2005/dsub/service/OfflineMusicService.java index 83c7f960..b8050bb2 100644 --- a/subsonic-android/src/github/daneren2005/dsub/service/OfflineMusicService.java +++ b/subsonic-android/src/github/daneren2005/dsub/service/OfflineMusicService.java @@ -446,7 +446,7 @@ public class OfflineMusicService extends RESTMusicService { scrobbleSearchCriteria = scrobbleSearchCriteria.replace(".complete", "").replace(".partial", ""); scrobbleSearchCriteria = scrobbleSearchCriteria.replace("/", " ").replace("-", "\\-").replace(".", "\\."); - BufferedWriter bw = new BufferedWriter(new FileWriter(offlineScrobblesFile)); + BufferedWriter bw = new BufferedWriter(new FileWriter(offlineScrobblesFile, true)); bw.write(scrobbleSearchCriteria + "," + System.currentTimeMillis()); bw.newLine(); bw.flush(); diff --git a/subsonic-android/src/github/daneren2005/dsub/service/RESTMusicService.java b/subsonic-android/src/github/daneren2005/dsub/service/RESTMusicService.java index be0763e7..ce17754a 100644 --- a/subsonic-android/src/github/daneren2005/dsub/service/RESTMusicService.java +++ b/subsonic-android/src/github/daneren2005/dsub/service/RESTMusicService.java @@ -196,7 +196,7 @@ public class RESTMusicService implements MusicService { } catch(Exception e){ Log.e(TAG, e.toString()); - BufferedWriter bw = new BufferedWriter(new FileWriter(offlineScrobblesFile)); + BufferedWriter bw = new BufferedWriter(new FileWriter(offlineScrobblesFile, true)); bw.write(line); bw.newLine(); bw.flush(); -- cgit v1.2.3 From 24bb93ce26cbe60fb2de373ddc914b8a74fe8ea2 Mon Sep 17 00:00:00 2001 From: Tom Briden Date: Wed, 5 Jun 2013 08:33:40 +0100 Subject: Revert "Moved metadata parsing back to createEntry, added disc number parsing" This reverts commit 9e14459fb8691624febe20e9df3d35518c6ec422. This change made loading playlists while offline reallly slow --- .../dsub/service/OfflineMusicService.java | 21 --------------------- .../src/github/daneren2005/dsub/view/SongView.java | 17 +++++++++++++++++ 2 files changed, 17 insertions(+), 21 deletions(-) (limited to 'subsonic-android') diff --git a/subsonic-android/src/github/daneren2005/dsub/service/OfflineMusicService.java b/subsonic-android/src/github/daneren2005/dsub/service/OfflineMusicService.java index b8050bb2..d2f99d0b 100644 --- a/subsonic-android/src/github/daneren2005/dsub/service/OfflineMusicService.java +++ b/subsonic-android/src/github/daneren2005/dsub/service/OfflineMusicService.java @@ -172,27 +172,6 @@ public class OfflineMusicService extends RESTMusicService { // Failed parseInt, just means track filled out } } - - try { - MediaMetadataRetriever metadata = new MediaMetadataRetriever(); - metadata.setDataSource(file.getAbsolutePath()); - String discNumber = metadata.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DISC_NUMBER); - if(discNumber == null) { - discNumber = "1/1"; - } - int slashIndex = discNumber.indexOf("/"); - if(slashIndex > 0) { - discNumber = discNumber.substring(0, slashIndex); - } - entry.setDiscNumber(Integer.parseInt(discNumber)); - String bitrate = metadata.extractMetadata(MediaMetadataRetriever.METADATA_KEY_BITRATE); - entry.setBitRate(Integer.parseInt((bitrate != null) ? bitrate : "0") / 1000); - String length = metadata.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION); - entry.setDuration(Integer.parseInt(length) / 1000); - metadata.release(); - } catch(Exception e) { - Log.i(TAG, "Device doesn't properly support MediaMetadataRetreiver"); - } } entry.setTitle(title); diff --git a/subsonic-android/src/github/daneren2005/dsub/view/SongView.java b/subsonic-android/src/github/daneren2005/dsub/view/SongView.java index 40bedad6..51927304 100644 --- a/subsonic-android/src/github/daneren2005/dsub/view/SongView.java +++ b/subsonic-android/src/github/daneren2005/dsub/view/SongView.java @@ -72,6 +72,23 @@ public class SongView extends UpdateView implements Checkable { public void setSong(MusicDirectory.Entry song, boolean checkable) { this.song = song; + if(Util.isOffline(context)) { + DownloadFile downloadFile = new DownloadFile(context, song, false); + File file = downloadFile.getCompleteFile(); + if(file.exists()) { + try { + MediaMetadataRetriever metadata = new MediaMetadataRetriever(); + metadata.setDataSource(file.getAbsolutePath()); + String bitrate = metadata.extractMetadata(MediaMetadataRetriever.METADATA_KEY_BITRATE); + song.setBitRate(Integer.parseInt((bitrate != null) ? bitrate : "0") / 1000); + String length = metadata.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION); + song.setDuration(Integer.parseInt(length) / 1000); + } catch(Exception e) { + Log.i(TAG, "Device doesn't properly support MediaMetadataRetreiver"); + } + } + } + StringBuilder artist = new StringBuilder(40); String bitRate = null; -- cgit v1.2.3 From 081cd153f539a9b0627ec0ceac7fd8e68608f54d Mon Sep 17 00:00:00 2001 From: Tom Briden Date: Wed, 5 Jun 2013 08:55:17 +0100 Subject: readded discnumber parsing to SongView createEntry --- subsonic-android/src/github/daneren2005/dsub/view/SongView.java | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'subsonic-android') diff --git a/subsonic-android/src/github/daneren2005/dsub/view/SongView.java b/subsonic-android/src/github/daneren2005/dsub/view/SongView.java index 51927304..fc50ff79 100644 --- a/subsonic-android/src/github/daneren2005/dsub/view/SongView.java +++ b/subsonic-android/src/github/daneren2005/dsub/view/SongView.java @@ -79,6 +79,15 @@ public class SongView extends UpdateView implements Checkable { try { MediaMetadataRetriever metadata = new MediaMetadataRetriever(); metadata.setDataSource(file.getAbsolutePath()); + String discNumber = metadata.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DISC_NUMBER); + if(discNumber == null) { + discNumber = "1/1"; + } + int slashIndex = discNumber.indexOf("/"); + if(slashIndex > 0) { + discNumber = discNumber.substring(0, slashIndex); + } + song.setDiscNumber(Integer.parseInt(discNumber)); String bitrate = metadata.extractMetadata(MediaMetadataRetriever.METADATA_KEY_BITRATE); song.setBitRate(Integer.parseInt((bitrate != null) ? bitrate : "0") / 1000); String length = metadata.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION); -- cgit v1.2.3 From f313378bc3ddc4023b50c9e8fa0af4b72f34cc7c Mon Sep 17 00:00:00 2001 From: Tom Briden Date: Wed, 5 Jun 2013 14:21:24 +0100 Subject: changed to use a proper lucene query from using just artist/title parsed from filename --- .../github/daneren2005/dsub/service/OfflineMusicService.java | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'subsonic-android') diff --git a/subsonic-android/src/github/daneren2005/dsub/service/OfflineMusicService.java b/subsonic-android/src/github/daneren2005/dsub/service/OfflineMusicService.java index d2f99d0b..9b4dde92 100644 --- a/subsonic-android/src/github/daneren2005/dsub/service/OfflineMusicService.java +++ b/subsonic-android/src/github/daneren2005/dsub/service/OfflineMusicService.java @@ -422,8 +422,14 @@ public class OfflineMusicService extends RESTMusicService { if(scrobbleSearchCriteria.startsWith("/")) scrobbleSearchCriteria = scrobbleSearchCriteria.substring(1); - scrobbleSearchCriteria = scrobbleSearchCriteria.replace(".complete", "").replace(".partial", ""); - scrobbleSearchCriteria = scrobbleSearchCriteria.replace("/", " ").replace("-", "\\-").replace(".", "\\."); + scrobbleSearchCriteria = scrobbleSearchCriteria.replace(".complete", "").replace(".partial", "").replace(".mp3", ""); + String[] details = scrobbleSearchCriteria.split("/"); + + //last.fm only uses artist and track title so broaden the search by just using those. doesn't matter if it find the track on a different album + String artist = "artist:\""+details[0]+"\""; + String title = "title:\""+details[2].substring(details[2].indexOf('-')+1)+"\""; + + scrobbleSearchCriteria = artist + " AND " + title; BufferedWriter bw = new BufferedWriter(new FileWriter(offlineScrobblesFile, true)); bw.write(scrobbleSearchCriteria + "," + System.currentTimeMillis()); -- cgit v1.2.3 From e6413a84ece8dd70bf09b505da8a339b49a1ea5e Mon Sep 17 00:00:00 2001 From: Tom Briden Date: Wed, 5 Jun 2013 14:25:19 +0100 Subject: throw exception if song not found so it can be put back on the list removed unneeded log line --- .../src/github/daneren2005/dsub/service/RESTMusicService.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'subsonic-android') diff --git a/subsonic-android/src/github/daneren2005/dsub/service/RESTMusicService.java b/subsonic-android/src/github/daneren2005/dsub/service/RESTMusicService.java index ce17754a..e0bffc57 100644 --- a/subsonic-android/src/github/daneren2005/dsub/service/RESTMusicService.java +++ b/subsonic-android/src/github/daneren2005/dsub/service/RESTMusicService.java @@ -183,7 +183,6 @@ public class RESTMusicService implements MusicService { line = lines.get(i); String filename = line.substring(0, line.lastIndexOf(',')); - Log.i(TAG, "Searching for id of file" + filename); try{ long time = Long.parseLong(line.substring(line.lastIndexOf(',')+1)); SearchCritera critera = new SearchCritera(filename, 0, 0, 1); @@ -193,6 +192,9 @@ public class RESTMusicService implements MusicService { Log.i(TAG, "Scrobbling " + result.getSongs().get(0).getId() + " with time " + time); scrobble(result.getSongs().get(0).getId(), true, time, context, progressListener); } + else{ + throw new Exception("Song not found on server"); + } } catch(Exception e){ Log.e(TAG, e.toString()); -- cgit v1.2.3 From 43fa167ca8b9ffbcd73711a8853fe67ebf4a78a7 Mon Sep 17 00:00:00 2001 From: Tom Briden Date: Wed, 5 Jun 2013 14:38:27 +0100 Subject: Added hasOfflineScrobbles function to MusicService so the fragment can query and if the file exists can prompt to process ignore or delete --- .../dsub/fragments/SelectDirectoryFragment.java | 7 +- .../dsub/service/CachedMusicService.java | 8 ++ .../daneren2005/dsub/service/MusicService.java | 2 + .../dsub/service/OfflineMusicService.java | 13 ++- .../daneren2005/dsub/service/RESTMusicService.java | 108 +++++++++++---------- 5 files changed, 79 insertions(+), 59 deletions(-) (limited to 'subsonic-android') diff --git a/subsonic-android/src/github/daneren2005/dsub/fragments/SelectDirectoryFragment.java b/subsonic-android/src/github/daneren2005/dsub/fragments/SelectDirectoryFragment.java index 13f61625..65b11e21 100644 --- a/subsonic-android/src/github/daneren2005/dsub/fragments/SelectDirectoryFragment.java +++ b/subsonic-android/src/github/daneren2005/dsub/fragments/SelectDirectoryFragment.java @@ -347,6 +347,11 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Adapter protected Pair doInBackground() throws Throwable { MusicService musicService = MusicServiceFactory.getMusicService(context); MusicDirectory dir = load(musicService); + //this may be done better elsewhere but i'm guessing licence is checked infrequently enough for it to be ok here + if(musicService.hasOfflineScrobbles()){ + + } + boolean valid = musicService.isLicenseValid(context, this); return new Pair(dir, valid); } @@ -692,4 +697,4 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Adapter return null; } } -} \ No newline at end of file +} diff --git a/subsonic-android/src/github/daneren2005/dsub/service/CachedMusicService.java b/subsonic-android/src/github/daneren2005/dsub/service/CachedMusicService.java index 314f065e..24132bea 100644 --- a/subsonic-android/src/github/daneren2005/dsub/service/CachedMusicService.java +++ b/subsonic-android/src/github/daneren2005/dsub/service/CachedMusicService.java @@ -38,6 +38,7 @@ import github.daneren2005.dsub.domain.SearchResult; import github.daneren2005.dsub.domain.Share; import github.daneren2005.dsub.domain.Version; import github.daneren2005.dsub.util.CancellableTask; +import github.daneren2005.dsub.util.FileUtil; import github.daneren2005.dsub.util.LRUCache; import github.daneren2005.dsub.util.ProgressListener; import github.daneren2005.dsub.util.TimeLimitedCache; @@ -295,6 +296,13 @@ public class CachedMusicService implements MusicService { public MusicDirectory getSongsByGenre(String genre, int count, int offset, Context context, ProgressListener progressListener) throws Exception { return musicService.getSongsByGenre(genre, count, offset, context, progressListener); } + + @Override + public boolean hasOfflineScrobbles(){ + return musicService.hasOfflineScrobbles(); + } + + private void checkSettingsChanged(Context context) { String newUrl = Util.getRestUrl(context, null); diff --git a/subsonic-android/src/github/daneren2005/dsub/service/MusicService.java b/subsonic-android/src/github/daneren2005/dsub/service/MusicService.java index f69ebfb1..1b769fa6 100644 --- a/subsonic-android/src/github/daneren2005/dsub/service/MusicService.java +++ b/subsonic-android/src/github/daneren2005/dsub/service/MusicService.java @@ -115,4 +115,6 @@ public interface MusicService { List getGenres(boolean refresh, Context context, ProgressListener progressListener) throws Exception; public MusicDirectory getSongsByGenre(String genre, int count, int offset, Context context, ProgressListener progressListener) throws Exception; + + boolean hasOfflineScrobbles(); } \ No newline at end of file diff --git a/subsonic-android/src/github/daneren2005/dsub/service/OfflineMusicService.java b/subsonic-android/src/github/daneren2005/dsub/service/OfflineMusicService.java index 9b4dde92..4fa026c0 100644 --- a/subsonic-android/src/github/daneren2005/dsub/service/OfflineMusicService.java +++ b/subsonic-android/src/github/daneren2005/dsub/service/OfflineMusicService.java @@ -19,8 +19,6 @@ package github.daneren2005.dsub.service; import java.io.File; -import java.io.FileInputStream; -import java.io.InputStream; import java.io.Reader; import java.io.FileReader; import java.util.ArrayList; @@ -34,9 +32,6 @@ import java.util.Set; import android.content.Context; import android.content.SharedPreferences; import android.graphics.Bitmap; -import android.graphics.BitmapFactory; -import android.media.MediaMetadataRetriever; -import android.os.Environment; import android.util.Log; import github.daneren2005.dsub.domain.Artist; import github.daneren2005.dsub.domain.Genre; @@ -48,7 +43,6 @@ import github.daneren2005.dsub.domain.MusicFolder; import github.daneren2005.dsub.domain.Playlist; import github.daneren2005.dsub.domain.SearchCritera; import github.daneren2005.dsub.domain.SearchResult; -import github.daneren2005.dsub.service.parser.PlaylistParser; import github.daneren2005.dsub.util.Constants; import github.daneren2005.dsub.util.FileUtil; import github.daneren2005.dsub.util.ProgressListener; @@ -516,6 +510,11 @@ public class OfflineMusicService extends RESTMusicService { return result; } + + @Override + public boolean hasOfflineScrobbles(){ + return false; + } private void listFilesRecursively(File parent, List children) { for (File file : FileUtil.listMediaFiles(parent)) { @@ -526,4 +525,4 @@ public class OfflineMusicService extends RESTMusicService { } } } -} +} \ No newline at end of file diff --git a/subsonic-android/src/github/daneren2005/dsub/service/RESTMusicService.java b/subsonic-android/src/github/daneren2005/dsub/service/RESTMusicService.java index e0bffc57..e609e033 100644 --- a/subsonic-android/src/github/daneren2005/dsub/service/RESTMusicService.java +++ b/subsonic-android/src/github/daneren2005/dsub/service/RESTMusicService.java @@ -162,57 +162,7 @@ public class RESTMusicService implements MusicService { Log.e(TAG, "Failed to create custom SSL socket factory, using default.", x); return org.apache.http.conn.ssl.SSLSocketFactory.getSocketFactory(); } - } - - public void processOfflineScrobbles(final Context context, final ProgressListener progressListener){ - File offlineScrobblesFile = FileUtil.getOfflineScrobblesFile(); - try{ - - BufferedReader br = new BufferedReader(new FileReader(offlineScrobblesFile)); - String line; - - ArrayList lines = new ArrayList(); - while ((line = br.readLine()) != null) { - lines.add(line); - } - br.close(); - offlineScrobblesFile.delete(); - - //TODO make a prompt: "Found " + lines.size() + " offline scrobbles. Scrobble? Ignore? Clear File?" - for(int i = 0; i < lines.size(); i++){ - line = lines.get(i); - String filename = line.substring(0, line.lastIndexOf(',')); - - try{ - long time = Long.parseLong(line.substring(line.lastIndexOf(',')+1)); - SearchCritera critera = new SearchCritera(filename, 0, 0, 1); - SearchResult result = searchNew(critera, context, progressListener); - if(result.getSongs().size() == 1){ - Log.i(TAG, "Query '" + filename + "' returned song " + result.getSongs().get(0).getTitle() + " by " + result.getSongs().get(0).getArtist() + " with id " + result.getSongs().get(0).getId()); - Log.i(TAG, "Scrobbling " + result.getSongs().get(0).getId() + " with time " + time); - scrobble(result.getSongs().get(0).getId(), true, time, context, progressListener); - } - else{ - throw new Exception("Song not found on server"); - } - } - catch(Exception e){ - Log.e(TAG, e.toString()); - BufferedWriter bw = new BufferedWriter(new FileWriter(offlineScrobblesFile, true)); - bw.write(line); - bw.newLine(); - bw.flush(); - bw.close(); - } - } - } - catch(FileNotFoundException fnfe){ - //ignore, we dont care - } - catch(Exception e){ - Log.e(TAG, e.toString()); - } - } + } @Override public void ping(Context context, ProgressListener progressListener) throws Exception { @@ -891,6 +841,62 @@ public class RESTMusicService implements MusicService { Util.close(reader); } } + + @Override + public boolean hasOfflineScrobbles(){ + return FileUtil.getOfflineScrobblesFile().exists(); + } + + public void processOfflineScrobbles(final Context context, final ProgressListener progressListener){ + File offlineScrobblesFile = FileUtil.getOfflineScrobblesFile(); + try{ + + BufferedReader br = new BufferedReader(new FileReader(offlineScrobblesFile)); + String line; + + ArrayList lines = new ArrayList(); + while ((line = br.readLine()) != null) { + lines.add(line); + } + br.close(); + offlineScrobblesFile.delete(); + + for(int i = 0; i < lines.size(); i++){ + line = lines.get(i); + String filename = line.substring(0, line.lastIndexOf(',')); + + try{ + long time = Long.parseLong(line.substring(line.lastIndexOf(',')+1)); + SearchCritera critera = new SearchCritera(filename, 0, 0, 1); + SearchResult result = searchNew(critera, context, progressListener); + if(result.getSongs().size() == 1){ + Log.i(TAG, "Query '" + filename + "' returned song " + result.getSongs().get(0).getTitle() + " by " + result.getSongs().get(0).getArtist() + " with id " + result.getSongs().get(0).getId()); + Log.i(TAG, "Scrobbling " + result.getSongs().get(0).getId() + " with time " + time); + scrobble(result.getSongs().get(0).getId(), true, time, context, progressListener); + } + else{ + throw new Exception("Song not found on server"); + } + } + catch(Exception e){ + Log.e(TAG, e.toString()); + BufferedWriter bw = new BufferedWriter(new FileWriter(offlineScrobblesFile, true)); + bw.write(line); + bw.newLine(); + bw.flush(); + bw.close(); + } + } + } + catch(FileNotFoundException fnfe){ + //ignore, we dont care + } + catch(Exception e){ + Log.e(TAG, e.toString()); + } + } + + private Reader getReader(Context context, ProgressListener progressListener, String method, HttpParams requestParams) throws Exception { return getReader(context, progressListener, method, requestParams, Collections.emptyList(), Collections.emptyList()); -- cgit v1.2.3 From ad6c9503cbb56eda5b0ff3a0060b625f827e753c Mon Sep 17 00:00:00 2001 From: Tom Briden Date: Wed, 5 Jun 2013 15:45:37 +0100 Subject: Added dialog when offline scrobble file found to scrobble now, ignore or just delete it Made processOfflineScrobbles a musicservice function so it can be called from fragment --- subsonic-android/res/values/strings.xml | 5 ++ .../dsub/fragments/SelectDirectoryFragment.java | 66 +++++++++++++++++++--- .../dsub/service/CachedMusicService.java | 5 ++ .../daneren2005/dsub/service/MusicService.java | 2 + .../dsub/service/OfflineMusicService.java | 5 ++ .../daneren2005/dsub/service/RESTMusicService.java | 8 +-- 6 files changed, 79 insertions(+), 12 deletions(-) (limited to 'subsonic-android') diff --git a/subsonic-android/res/values/strings.xml b/subsonic-android/res/values/strings.xml index b5e8f3e1..5aa09d76 100644 --- a/subsonic-android/res/values/strings.xml +++ b/subsonic-android/res/values/strings.xml @@ -114,6 +114,11 @@ Now Later Trial period is over + Offline scrobbles file found. + Process offline scrobbles file? + Yes + No + Delete file No genres found diff --git a/subsonic-android/src/github/daneren2005/dsub/fragments/SelectDirectoryFragment.java b/subsonic-android/src/github/daneren2005/dsub/fragments/SelectDirectoryFragment.java index 65b11e21..c4da3070 100644 --- a/subsonic-android/src/github/daneren2005/dsub/fragments/SelectDirectoryFragment.java +++ b/subsonic-android/src/github/daneren2005/dsub/fragments/SelectDirectoryFragment.java @@ -27,6 +27,7 @@ import github.daneren2005.dsub.service.MusicServiceFactory; import github.daneren2005.dsub.service.OfflineException; import github.daneren2005.dsub.service.ServerTooOldException; import github.daneren2005.dsub.util.Constants; +import github.daneren2005.dsub.util.FileUtil; import github.daneren2005.dsub.util.LoadingTask; import github.daneren2005.dsub.util.Pair; import github.daneren2005.dsub.util.TabBackgroundTask; @@ -276,6 +277,12 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Adapter } else { getMusicDirectory(id, name, refresh); } + + //this may be done better elsewhere but it works for now :) + MusicService musicService = MusicServiceFactory.getMusicService(context); + if(musicService.hasOfflineScrobbles()){ + showOfflineScrobblesDialog(); + } } private void getMusicDirectory(final String id, final String name, final boolean refresh) { @@ -345,14 +352,9 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Adapter @Override protected Pair doInBackground() throws Throwable { - MusicService musicService = MusicServiceFactory.getMusicService(context); + MusicService musicService = MusicServiceFactory.getMusicService(context); MusicDirectory dir = load(musicService); - //this may be done better elsewhere but i'm guessing licence is checked infrequently enough for it to be ok here - if(musicService.hasOfflineScrobbles()){ - - } - - boolean valid = musicService.isLicenseValid(context, this); + boolean valid = musicService.isLicenseValid(context, this); return new Pair(dir, valid); } @@ -640,6 +642,56 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Adapter builder.create().show(); } + + private void showOfflineScrobblesDialog() { + + + AlertDialog.Builder builder = new AlertDialog.Builder(context); + builder.setIcon(android.R.drawable.ic_dialog_info); + + builder.setTitle(R.string.select_album_offline_scrobbles_dialog_title); + + builder.setMessage(R.string.select_album_offline_scrobbles_dialog_message); + + //want this on the left and delete on the right hence the backwards button types + builder.setNegativeButton(R.string.select_album_offline_scrobbles_dialog_yes, + + new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialogInterface, int i) { + new Thread("Scrobble offline") { + @Override + public void run() { + try { + MusicService musicService = MusicServiceFactory.getMusicService(context); + musicService.processOfflineScrobbles(context, null); + } catch (Exception x) { + Log.i(TAG, "Failed to process offline sc/robbles"); + } + } + }.start(); + } + }); + + builder.setPositiveButton(R.string.select_album_offline_scrobbles_dialog_delete, + new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialogInterface, int i) { + dialogInterface.dismiss(); + FileUtil.getOfflineScrobblesFile().delete(); + } + }); + + builder.setNeutralButton(R.string.select_album_offline_scrobbles_dialog_no, + new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialogInterface, int i) { + dialogInterface.dismiss(); + } + }); + + builder.create().show(); + } private View createHeader(List entries) { View header = entryList.findViewById(R.id.select_album_header); diff --git a/subsonic-android/src/github/daneren2005/dsub/service/CachedMusicService.java b/subsonic-android/src/github/daneren2005/dsub/service/CachedMusicService.java index 24132bea..49542045 100644 --- a/subsonic-android/src/github/daneren2005/dsub/service/CachedMusicService.java +++ b/subsonic-android/src/github/daneren2005/dsub/service/CachedMusicService.java @@ -301,6 +301,11 @@ public class CachedMusicService implements MusicService { public boolean hasOfflineScrobbles(){ return musicService.hasOfflineScrobbles(); } + + @Override + public void processOfflineScrobbles(final Context context, final ProgressListener progressListener) throws Exception{ + musicService.processOfflineScrobbles(context, progressListener); + } diff --git a/subsonic-android/src/github/daneren2005/dsub/service/MusicService.java b/subsonic-android/src/github/daneren2005/dsub/service/MusicService.java index 1b769fa6..c99551b4 100644 --- a/subsonic-android/src/github/daneren2005/dsub/service/MusicService.java +++ b/subsonic-android/src/github/daneren2005/dsub/service/MusicService.java @@ -117,4 +117,6 @@ public interface MusicService { public MusicDirectory getSongsByGenre(String genre, int count, int offset, Context context, ProgressListener progressListener) throws Exception; boolean hasOfflineScrobbles(); + + void processOfflineScrobbles(final Context context, final ProgressListener progressListener) throws Exception; } \ No newline at end of file diff --git a/subsonic-android/src/github/daneren2005/dsub/service/OfflineMusicService.java b/subsonic-android/src/github/daneren2005/dsub/service/OfflineMusicService.java index 4fa026c0..c2a85488 100644 --- a/subsonic-android/src/github/daneren2005/dsub/service/OfflineMusicService.java +++ b/subsonic-android/src/github/daneren2005/dsub/service/OfflineMusicService.java @@ -515,6 +515,11 @@ public class OfflineMusicService extends RESTMusicService { public boolean hasOfflineScrobbles(){ return false; } + + @Override + public void processOfflineScrobbles(final Context context, final ProgressListener progressListener) throws Exception{ + throw new OfflineException("Offline scrobble cached can not be processes while in offline mode"); + } private void listFilesRecursively(File parent, List children) { for (File file : FileUtil.listMediaFiles(parent)) { diff --git a/subsonic-android/src/github/daneren2005/dsub/service/RESTMusicService.java b/subsonic-android/src/github/daneren2005/dsub/service/RESTMusicService.java index e609e033..27a51145 100644 --- a/subsonic-android/src/github/daneren2005/dsub/service/RESTMusicService.java +++ b/subsonic-android/src/github/daneren2005/dsub/service/RESTMusicService.java @@ -177,10 +177,7 @@ public class RESTMusicService implements MusicService { @Override public boolean isLicenseValid(Context context, ProgressListener progressListener) throws Exception { - //TODO run on a thread - processOfflineScrobbles(context, progressListener); - - Reader reader = getReader(context, progressListener, "getLicense", null); + Reader reader = getReader(context, progressListener, "getLicense", null); try { ServerInfo serverInfo = new LicenseParser(context).parse(reader); return serverInfo.isLicenseValid(); @@ -847,7 +844,8 @@ public class RESTMusicService implements MusicService { return FileUtil.getOfflineScrobblesFile().exists(); } - public void processOfflineScrobbles(final Context context, final ProgressListener progressListener){ + @Override + public void processOfflineScrobbles(final Context context, final ProgressListener progressListener) throws Exception{ File offlineScrobblesFile = FileUtil.getOfflineScrobblesFile(); try{ -- cgit v1.2.3 From 1549d7f25c2ad8e3fe6ca63e6ff66c4e3ee99e1f Mon Sep 17 00:00:00 2001 From: Tom Briden Date: Wed, 5 Jun 2013 16:02:30 +0100 Subject: fix typo in strings.xml --- subsonic-android/res/values/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'subsonic-android') diff --git a/subsonic-android/res/values/strings.xml b/subsonic-android/res/values/strings.xml index 5aa09d76..5635a74e 100644 --- a/subsonic-android/res/values/strings.xml +++ b/subsonic-android/res/values/strings.xml @@ -118,7 +118,7 @@ Process offline scrobbles file? Yes No - Delete file + Delete file No genres found -- cgit v1.2.3 From 51cd59e90977f02317cc2b5d4b45dc78250b22b2 Mon Sep 17 00:00:00 2001 From: Tom Date: Fri, 7 Jun 2013 21:30:53 +0100 Subject: set ALBUMARTIST metadata as thats what the lockscreen uses put the album name into the album metadata --- .../github/daneren2005/dsub/util/compat/RemoteControlClientICS.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'subsonic-android') diff --git a/subsonic-android/src/github/daneren2005/dsub/util/compat/RemoteControlClientICS.java b/subsonic-android/src/github/daneren2005/dsub/util/compat/RemoteControlClientICS.java index a8fed63d..50989468 100644 --- a/subsonic-android/src/github/daneren2005/dsub/util/compat/RemoteControlClientICS.java +++ b/subsonic-android/src/github/daneren2005/dsub/util/compat/RemoteControlClientICS.java @@ -62,7 +62,8 @@ public class RemoteControlClientICS extends RemoteControlClientHelper { // Update the remote controls mRemoteControl.editMetadata(true) .putString(MediaMetadataRetriever.METADATA_KEY_ARTIST, (currentSong == null) ? null : currentSong.getArtist()) - .putString(MediaMetadataRetriever.METADATA_KEY_ALBUM, (currentSong == null) ? null : currentSong.getArtist()) + .putString(MediaMetadataRetriever.METADATA_KEY_ALBUMARTIST, (currentSong == null) ? null : currentSong.getArtist()) + .putString(MediaMetadataRetriever.METADATA_KEY_ALBUM, (currentSong == null) ? null : currentSong.getAlbum()) .putString(MediaMetadataRetriever.METADATA_KEY_TITLE, (currentSong) == null ? null : currentSong.getTitle()) .putLong(MediaMetadataRetriever.METADATA_KEY_DURATION, (currentSong == null) ? 0 : ((currentSong.getDuration() == null) ? 0 : currentSong.getDuration())) -- cgit v1.2.3