1
0
mirror of https://github.com/ultrasonic/ultrasonic synced 2025-01-31 09:27:04 +01:00

Hide jukebox option when user is not enabled for it (caching), fix crashes

This commit is contained in:
Joshua Bahnsen 2013-12-06 19:43:13 -07:00
parent 975dafed47
commit 58ecfcb724
14 changed files with 219 additions and 63 deletions

View File

@ -2,8 +2,8 @@
<manifest xmlns:a="http://schemas.android.com/apk/res/android"
package="com.thejoshwa.ultrasonic.androidapp"
a:installLocation="auto"
a:versionCode="35"
a:versionName="1.2.0.8" >
a:versionCode="36"
a:versionName="1.2.0.9" >
<uses-permission a:name="android.permission.INTERNET" />
<uses-permission a:name="android.permission.READ_PHONE_STATE" />

View File

@ -95,6 +95,7 @@ public class DownloadActivity extends SubsonicTabActivity implements OnGestureLi
private VisualizerView visualizerView;
private boolean visualizerAvailable;
private boolean equalizerAvailable;
private boolean jukeboxAvailable;
private SilentBackgroundTask<Void> onProgressChangedTask;
LinearLayout visualizerViewLayout;
@ -595,6 +596,23 @@ public class DownloadActivity extends SubsonicTabActivity implements OnGestureLi
visualizerAvailable = (downloadService != null) && (downloadService.getVisualizerController() != null);
equalizerAvailable = (downloadService != null) && (downloadService.getEqualizerController() != null);
new Thread(new Runnable()
{
@Override
public void run()
{
try
{
DownloadService downloadService = getDownloadService();
jukeboxAvailable = (downloadService != null) && (downloadService.isJukeboxAvailable());
}
catch (Exception e)
{
Log.e(TAG, e.getMessage(), e);
}
}
}).start();
final View nowPlayingMenuItem = findViewById(R.id.menu_now_playing);
menuDrawer.setActiveView(nowPlayingMenuItem);
@ -841,18 +859,25 @@ public class DownloadActivity extends SubsonicTabActivity implements OnGestureLi
}
}
if (downloadService.isJukeboxEnabled())
if (jukeboxOption != null)
{
if (jukeboxOption != null)
jukeboxOption.setEnabled(jukeboxAvailable);
jukeboxOption.setVisible(jukeboxAvailable);
if (downloadService.isJukeboxEnabled())
{
jukeboxOption.setTitle(R.string.download_menu_jukebox_off);
if (jukeboxOption != null)
{
jukeboxOption.setTitle(R.string.download_menu_jukebox_off);
}
}
}
else
{
if (jukeboxOption != null)
else
{
jukeboxOption.setTitle(R.string.download_menu_jukebox_on);
if (jukeboxOption != null)
{
jukeboxOption.setTitle(R.string.download_menu_jukebox_on);
}
}
}
}
@ -1321,13 +1346,20 @@ public class DownloadActivity extends SubsonicTabActivity implements OnGestureLi
final DownloadService downloadService = getDownloadService();
if (downloadService == null)
if (downloadService == null || e1 == null || e2 == null)
{
return false;
}
float e1X = e1.getX();
float e2X = e2.getX();
float e1Y = e1.getY();
float e2Y = e2.getY();
float absX = Math.abs(velocityX);
float absY = Math.abs(velocityY);
// Right to Left swipe
if (e1.getX() - e2.getX() > swipeDistance && Math.abs(velocityX) > swipeVelocity)
if (e1X - e2X > swipeDistance && absX > swipeVelocity)
{
warnIfNetworkOrStorageUnavailable();
if (downloadService.getCurrentPlayingIndex() < downloadService.size() - 1)
@ -1340,7 +1372,7 @@ public class DownloadActivity extends SubsonicTabActivity implements OnGestureLi
}
// Left to Right swipe
if (e2.getX() - e1.getX() > swipeDistance && Math.abs(velocityX) > swipeVelocity)
if (e2X - e1X > swipeDistance && absX > swipeVelocity)
{
warnIfNetworkOrStorageUnavailable();
downloadService.previous();
@ -1350,7 +1382,7 @@ public class DownloadActivity extends SubsonicTabActivity implements OnGestureLi
}
// Top to Bottom swipe
if (e2.getY() - e1.getY() > swipeDistance && Math.abs(velocityY) > swipeVelocity)
if (e2Y - e1Y > swipeDistance && absY > swipeVelocity)
{
warnIfNetworkOrStorageUnavailable();
downloadService.seekTo(downloadService.getPlayerPosition() + 30000);
@ -1359,7 +1391,7 @@ public class DownloadActivity extends SubsonicTabActivity implements OnGestureLi
}
// Bottom to Top swipe
if (e1.getY() - e2.getY() > swipeDistance && Math.abs(velocityY) > swipeVelocity)
if (e1Y - e2Y > swipeDistance && absY > swipeVelocity)
{
warnIfNetworkOrStorageUnavailable();
downloadService.seekTo(downloadService.getPlayerPosition() - 8000);

View File

@ -18,9 +18,6 @@
*/
package com.thejoshwa.ultrasonic.androidapp.activity;
import java.util.HashMap;
import java.util.Map;
import android.app.Activity;
import android.media.audiofx.Equalizer;
import android.os.Bundle;
@ -38,6 +35,9 @@ import com.thejoshwa.ultrasonic.androidapp.R;
import com.thejoshwa.ultrasonic.androidapp.audiofx.EqualizerController;
import com.thejoshwa.ultrasonic.androidapp.service.DownloadServiceImpl;
import java.util.HashMap;
import java.util.Map;
/**
* Equalizer controls.
*
@ -136,14 +136,20 @@ public class EqualizerActivity extends Activity
private void updateBars()
{
for (Map.Entry<Short, SeekBar> entry : bars.entrySet())
try
{
short band = entry.getKey();
SeekBar bar = entry.getValue();
bar.setEnabled(equalizer.getEnabled());
short minEQLevel = equalizer.getBandLevelRange()[0];
bar.setProgress(equalizer.getBandLevel(band) - minEQLevel);
for (Map.Entry<Short, SeekBar> entry : bars.entrySet())
{
short band = entry.getKey();
SeekBar bar = entry.getValue();
bar.setEnabled(equalizer.getEnabled());
short minEQLevel = equalizer.getBandLevelRange()[0];
bar.setProgress(equalizer.getBandLevel(band) - minEQLevel);
}
}
catch (Exception ex)
{
}
}
@ -189,7 +195,13 @@ public class EqualizerActivity extends Activity
short level = (short) (progress + minEQLevel);
if (fromUser)
{
equalizer.setBandLevel(band, level);
try
{
equalizer.setBandLevel(band, level);
}
catch (Exception ex)
{
}
}
updateLevelText(levelTextView, level);
}
@ -204,6 +216,7 @@ public class EqualizerActivity extends Activity
{
}
});
layout.addView(bandBar);
}
}
@ -216,7 +229,9 @@ public class EqualizerActivity extends Activity
private static void updateLevelText(TextView levelTextView, short level)
{
levelTextView.setText((level > 0 ? "+" : "") + level / 100 + " dB");
if (levelTextView != null)
{
levelTextView.setText(String.format("%s%d dB", level > 0 ? "+" : "", level / 100));
}
}
}

View File

@ -321,7 +321,6 @@ public class MainActivity extends SubsonicTabActivity
private boolean getActiveServerEnabled()
{
final int activeServer = Util.getActiveServer(this);
boolean activeServerEnabled = false;

View File

@ -454,7 +454,10 @@ public class SubsonicTabActivity extends Activity implements OnClickListener
return;
}
nowPlayingView = findViewById(R.id.now_playing);
if (nowPlayingView == null)
{
nowPlayingView = findViewById(R.id.now_playing);
}
if (nowPlayingView != null)
{
@ -549,8 +552,22 @@ public class SubsonicTabActivity extends Activity implements OnClickListener
public void hideNowPlaying()
{
nowPlayingView = findViewById(R.id.now_playing);
setVisibilityOnUiThread(nowPlayingView, View.GONE);
try
{
if (nowPlayingView == null)
{
nowPlayingView = findViewById(R.id.now_playing);
}
if (nowPlayingView != null)
{
setVisibilityOnUiThread(nowPlayingView, View.GONE);
}
}
catch (Exception ex)
{
Log.w(String.format("Exception in hideNowPlaying: %s", ex), ex);
}
}
public void setTextViewTextOnUiThread(final RemoteViews view, final int id, final String text)

View File

@ -33,6 +33,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.domain.Share;
import com.thejoshwa.ultrasonic.androidapp.domain.UserInfo;
import com.thejoshwa.ultrasonic.androidapp.domain.Version;
import com.thejoshwa.ultrasonic.androidapp.util.CancellableTask;
import com.thejoshwa.ultrasonic.androidapp.util.Constants;
@ -58,6 +59,7 @@ public class CachedMusicService implements MusicService
private final LRUCache<String, TimeLimitedCache<MusicDirectory>> cachedMusicDirectories;
private final LRUCache<String, TimeLimitedCache<MusicDirectory>> cachedArtist;
private final LRUCache<String, TimeLimitedCache<MusicDirectory>> cachedAlbum;
private final LRUCache<String, TimeLimitedCache<UserInfo>> cachedUserInfo;
private final TimeLimitedCache<Boolean> cachedLicenseValid = new TimeLimitedCache<Boolean>(120, TimeUnit.SECONDS);
private final TimeLimitedCache<Indexes> cachedIndexes = new TimeLimitedCache<Indexes>(60 * 60, TimeUnit.SECONDS);
private final TimeLimitedCache<Indexes> cachedArtists = new TimeLimitedCache<Indexes>(60 * 60, TimeUnit.SECONDS);
@ -73,6 +75,7 @@ public class CachedMusicService implements MusicService
cachedMusicDirectories = new LRUCache<String, TimeLimitedCache<MusicDirectory>>(MUSIC_DIR_CACHE_SIZE);
cachedArtist = new LRUCache<String, TimeLimitedCache<MusicDirectory>>(MUSIC_DIR_CACHE_SIZE);
cachedAlbum = new LRUCache<String, TimeLimitedCache<MusicDirectory>>(MUSIC_DIR_CACHE_SIZE);
cachedUserInfo = new LRUCache<String, TimeLimitedCache<UserInfo>>(MUSIC_DIR_CACHE_SIZE);
}
@Override
@ -378,6 +381,10 @@ public class CachedMusicService implements MusicService
cachedLicenseValid.clear();
cachedIndexes.clear();
cachedPlaylists.clear();
cachedGenres.clear();
cachedAlbum.clear();
cachedArtist.clear();
cachedUserInfo.clear();
restUrl = newUrl;
}
}
@ -470,4 +477,24 @@ public class CachedMusicService implements MusicService
return dir;
}
@Override
public UserInfo getUser(String username, Context context, ProgressListener progressListener) throws Exception
{
checkSettingsChanged(context);
TimeLimitedCache<UserInfo> cache = cachedUserInfo.get(username);
UserInfo userInfo = cache == null ? null : cache.get();
if (userInfo == null)
{
userInfo = musicService.getUser(username, context, progressListener);
cache = new TimeLimitedCache<UserInfo>(Util.getDirectoryCacheTime(context), TimeUnit.SECONDS);
cache.set(userInfo);
cachedUserInfo.put(username, cache);
}
return userInfo;
}
}

View File

@ -125,6 +125,8 @@ public interface DownloadService
boolean isJukeboxEnabled();
boolean isJukeboxAvailable();
void setJukeboxEnabled(boolean b);
void adjustJukeboxVolume(boolean up);

View File

@ -49,6 +49,7 @@ import com.thejoshwa.ultrasonic.androidapp.domain.MusicDirectory;
import com.thejoshwa.ultrasonic.androidapp.domain.MusicDirectory.Entry;
import com.thejoshwa.ultrasonic.androidapp.domain.PlayerState;
import com.thejoshwa.ultrasonic.androidapp.domain.RepeatMode;
import com.thejoshwa.ultrasonic.androidapp.domain.UserInfo;
import com.thejoshwa.ultrasonic.androidapp.provider.UltraSonicAppWidgetProvider4x1;
import com.thejoshwa.ultrasonic.androidapp.provider.UltraSonicAppWidgetProvider4x2;
import com.thejoshwa.ultrasonic.androidapp.provider.UltraSonicAppWidgetProvider4x3;
@ -896,18 +897,8 @@ public class DownloadServiceImpl extends Service implements DownloadService
lifecycleSupport.serializeDownloadQueue();
}
private synchronized void playNext(boolean start)
private synchronized void playNext()
{
// Swap the media players since nextMediaPlayer is ready to play
if (start)
{
//nextMediaPlayer.start();
}
else
{
Log.i(TAG, "nextMediaPlayer already playing");
}
MediaPlayer tmp = mediaPlayer;
mediaPlayer = nextMediaPlayer;
nextMediaPlayer = tmp;
@ -1362,6 +1353,25 @@ public class DownloadServiceImpl extends Service implements DownloadService
return jukeboxEnabled;
}
@Override
public boolean isJukeboxAvailable()
{
MusicService musicService = MusicServiceFactory.getMusicService(DownloadServiceImpl.this);
try
{
String username = Util.getUserName(DownloadServiceImpl.this, Util.getActiveServer(DownloadServiceImpl.this));
UserInfo user = musicService.getUser(username, DownloadServiceImpl.this, null);
return user.getJukeboxRole();
}
catch (Exception e)
{
Log.w("Error getting user information", e);
}
return false;
}
@Override
public void setJukeboxEnabled(boolean jukeboxEnabled)
{
@ -1689,21 +1699,13 @@ public class DownloadServiceImpl extends Service implements DownloadService
setPlayerStateCompleted();
int pos = cachedPosition;
Log.i(TAG, "Ending position " + pos + " of " + duration);
Log.i(TAG, String.format("Ending position %d of %d", pos, duration));
if (!isPartial || (downloadFile.isWorkDone() && (Math.abs(duration - pos) < 10000)))
{
if (nextPlaying != null && nextPlayerState == PlayerState.PREPARED)
{
if (!nextSetup)
{
playNext(true);
}
else
{
nextSetup = false;
playNext(false);
}
playNext();
}
else
{
@ -1777,14 +1779,23 @@ public class DownloadServiceImpl extends Service implements DownloadService
private void handleError(Exception x)
{
Log.w(TAG, "Media player error: " + x, x);
mediaPlayer.reset();
Log.w(TAG, String.format("Media player error: %s", x), x);
try
{
mediaPlayer.reset();
}
catch (Exception ex)
{
Log.w(TAG, String.format("Exception encountered when resetting media player: %s", ex), ex);
}
setPlayerState(IDLE);
}
private void handleErrorNext(Exception x)
{
Log.w(TAG, "Next Media player error: " + x, x);
Log.w(TAG, String.format("Next Media player error: %s", x), x);
nextMediaPlayer.reset();
setNextPlayerState(IDLE);
}

View File

@ -33,6 +33,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.domain.Share;
import com.thejoshwa.ultrasonic.androidapp.domain.UserInfo;
import com.thejoshwa.ultrasonic.androidapp.domain.Version;
import com.thejoshwa.ultrasonic.androidapp.util.CancellableTask;
import com.thejoshwa.ultrasonic.androidapp.util.ProgressListener;
@ -138,4 +139,6 @@ public interface MusicService
void createBookmark(String id, int position, Context context, ProgressListener progressListener) throws Exception;
MusicDirectory getVideos(boolean refresh, Context context, ProgressListener progressListener) throws Exception;
UserInfo getUser(String username, Context context, ProgressListener progressListener) throws Exception;
}

View File

@ -33,6 +33,7 @@ import com.thejoshwa.ultrasonic.androidapp.domain.MusicFolder;
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.domain.UserInfo;
import com.thejoshwa.ultrasonic.androidapp.util.Constants;
import com.thejoshwa.ultrasonic.androidapp.util.FileUtil;
import com.thejoshwa.ultrasonic.androidapp.util.ProgressListener;
@ -742,6 +743,12 @@ public class OfflineMusicService extends RESTMusicService
throw new OfflineException("Getting Genres not available in offline mode");
}
@Override
public UserInfo getUser(String username, Context context, ProgressListener progressListener) throws Exception
{
throw new OfflineException("Getting user info not available in offline mode");
}
private static void listFilesRecursively(File parent, List<File> children)
{
for (File file : FileUtil.listMediaFiles(parent))

View File

@ -39,6 +39,7 @@ import com.thejoshwa.ultrasonic.androidapp.domain.SearchCriteria;
import com.thejoshwa.ultrasonic.androidapp.domain.SearchResult;
import com.thejoshwa.ultrasonic.androidapp.domain.ServerInfo;
import com.thejoshwa.ultrasonic.androidapp.domain.Share;
import com.thejoshwa.ultrasonic.androidapp.domain.UserInfo;
import com.thejoshwa.ultrasonic.androidapp.domain.Version;
import com.thejoshwa.ultrasonic.androidapp.service.parser.AlbumListParser;
import com.thejoshwa.ultrasonic.androidapp.service.parser.BookmarkParser;
@ -57,6 +58,7 @@ import com.thejoshwa.ultrasonic.androidapp.service.parser.RandomSongsParser;
import com.thejoshwa.ultrasonic.androidapp.service.parser.SearchResult2Parser;
import com.thejoshwa.ultrasonic.androidapp.service.parser.SearchResultParser;
import com.thejoshwa.ultrasonic.androidapp.service.parser.ShareParser;
import com.thejoshwa.ultrasonic.androidapp.service.parser.UserInfoParser;
import com.thejoshwa.ultrasonic.androidapp.service.parser.VersionParser;
import com.thejoshwa.ultrasonic.androidapp.service.ssl.SSLSocketFactory;
import com.thejoshwa.ultrasonic.androidapp.service.ssl.TrustSelfSignedStrategy;
@ -1411,6 +1413,32 @@ public class RESTMusicService implements MusicService
}
}
@Override
public UserInfo getUser(String username, Context context, ProgressListener progressListener) throws Exception
{
checkServerVersion(context, "1.3", "getUser not supported.");
HttpParams params = new BasicHttpParams();
HttpConnectionParams.setSoTimeout(params, SOCKET_READ_TIMEOUT_GET_RANDOM_SONGS);
List<String> parameterNames = new ArrayList<String>();
List<Object> parameterValues = new ArrayList<Object>();
parameterNames.add("username");
parameterValues.add(username);
Reader reader = getReader(context, progressListener, "getUser", params, parameterNames, parameterValues);
try
{
return new UserInfoParser(context).parse(reader, progressListener);
}
finally
{
Util.close(reader);
}
}
@Override
public List<ChatMessage> getChatMessages(Long since, Context context, ProgressListener progressListener) throws Exception
{

View File

@ -102,7 +102,15 @@ public abstract class ModalBackgroundTask<T> extends BackgroundTask<T>
@Override
public void run()
{
progressDialog.dismiss();
try
{
progressDialog.dismiss();
}
catch (Exception e)
{
// nothing
}
done(result);
}
});

View File

@ -750,7 +750,7 @@ public class Util extends DownloadActivity
{
int slashIndex = path.indexOf('/');
if (slashIndex != 0)
if (slashIndex > 0)
{
return path.substring(0, slashIndex);
}

View File

@ -129,7 +129,11 @@ public class SongView extends UpdateView implements Checkable
updateBackground();
this.song = song;
this.downloadFile = downloadService.forSong(song);
if (downloadService != null)
{
this.downloadFile = downloadService.forSong(song);
}
inflater.inflate(song.isVideo() ? R.layout.video_list_item : R.layout.song_list_item, this, true);
@ -307,11 +311,14 @@ public class SongView extends UpdateView implements Checkable
this.rightImageType = ImageType.none;
this.rightImage = null;
CharSequence statusText = this.statusTextView.getText();
if (statusText != "" || statusText != null)
if (this.statusTextView != null)
{
this.statusTextView.setText(null);
CharSequence statusText = this.statusTextView.getText();
if (statusText != "" || statusText != null)
{
this.statusTextView.setText(null);
}
}
}