From e774bc406535cb90896c1370dc67c8cf8ee491f0 Mon Sep 17 00:00:00 2001 From: Scott Jackson Date: Wed, 14 Sep 2016 22:08:08 -0700 Subject: #172 Implement playback of internet radio stations + hide UI elements which don't make sense on streams --- .../dsub/activity/SubsonicFragmentActivity.java | 31 +++++++--- .../dsub/fragments/NowPlayingFragment.java | 62 +++++++++++++++---- .../SelectInternetRadioStationFragment.java | 22 ++++++- .../daneren2005/dsub/service/DownloadFile.java | 14 +++++ .../daneren2005/dsub/service/DownloadService.java | 72 ++++++++++++++++------ .../daneren2005/dsub/util/Notifications.java | 28 ++++++++- 6 files changed, 184 insertions(+), 45 deletions(-) (limited to 'app') diff --git a/app/src/main/java/github/daneren2005/dsub/activity/SubsonicFragmentActivity.java b/app/src/main/java/github/daneren2005/dsub/activity/SubsonicFragmentActivity.java index 33b7d033..c7190046 100644 --- a/app/src/main/java/github/daneren2005/dsub/activity/SubsonicFragmentActivity.java +++ b/app/src/main/java/github/daneren2005/dsub/activity/SubsonicFragmentActivity.java @@ -925,7 +925,13 @@ public class SubsonicFragmentActivity extends SubsonicActivity implements Downlo if (currentPlaying != null) { song = currentPlaying.getSong(); trackView.setText(song.getTitle()); - artistView.setText(song.getArtist()); + + if(song.getArtist() != null) { + artistView.setVisibility(View.VISIBLE); + artistView.setText(song.getArtist()); + } else { + artistView.setVisibility(View.GONE); + } } else { trackView.setText(R.string.main_title); artistView.setText(R.string.main_artist); @@ -942,18 +948,25 @@ public class SubsonicFragmentActivity extends SubsonicActivity implements Downlo getImageLoader().loadImage(coverArtView, song, false, height, false); } - if(currentPlaying != null && currentPlaying.getSong() != null && (currentPlaying.getSong().isPodcast() || currentPlaying.getSong().isAudioBook())) { + if(getDownloadService().isCurrentPlayingSingle()) { previousButton.setVisibility(View.GONE); nextButton.setVisibility(View.GONE); - - rewindButton.setVisibility(View.VISIBLE); - fastforwardButton.setVisibility(View.VISIBLE); - } else { - previousButton.setVisibility(View.VISIBLE); - nextButton.setVisibility(View.VISIBLE); - rewindButton.setVisibility(View.GONE); fastforwardButton.setVisibility(View.GONE); + } else { + if (currentPlaying != null && currentPlaying.getSong() != null && (currentPlaying.getSong().isPodcast() || currentPlaying.getSong().isAudioBook())) { + previousButton.setVisibility(View.GONE); + nextButton.setVisibility(View.GONE); + + rewindButton.setVisibility(View.VISIBLE); + fastforwardButton.setVisibility(View.VISIBLE); + } else { + previousButton.setVisibility(View.VISIBLE); + nextButton.setVisibility(View.VISIBLE); + + rewindButton.setVisibility(View.GONE); + fastforwardButton.setVisibility(View.GONE); + } } } diff --git a/app/src/main/java/github/daneren2005/dsub/fragments/NowPlayingFragment.java b/app/src/main/java/github/daneren2005/dsub/fragments/NowPlayingFragment.java index 9eddbc89..985b7bec 100644 --- a/app/src/main/java/github/daneren2005/dsub/fragments/NowPlayingFragment.java +++ b/app/src/main/java/github/daneren2005/dsub/fragments/NowPlayingFragment.java @@ -535,6 +535,15 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis mediaRouteButton.setDialogFactory(new CustomMediaRouteDialogFactory()); mediaRouteButton.setRouteSelector(downloadService.getRemoteSelector()); } + + if(downloadService.isCurrentPlayingSingle()) { + if(!Util.isOffline(context)) { + menu.removeItem(R.id.menu_save_playlist); + } + + menu.removeItem(R.id.menu_batch_mode); + menu.removeItem(R.id.menu_remove_played); + } } if(Util.getPreferences(context).getBoolean(Constants.PREFERENCES_KEY_BATCH_MODE, false)) { @@ -867,6 +876,11 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis } private void setControlsVisible(boolean visible) { + DownloadService downloadService = getDownloadService(); + if(downloadService != null && downloadService.isCurrentPlayingSingle()) { + return; + } + try { long duration = 1700L; FadeOutAnimation.createAndStart(rootView.findViewById(R.id.download_overlay_buttons), !visible, duration); @@ -1242,18 +1256,25 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis this.currentPlaying = currentPlaying; setupSubtitle(currentPlayingIndex); - if(currentPlaying != null && !currentPlaying.isSong()) { + if(getDownloadService().isCurrentPlayingSingle()) { previousButton.setVisibility(View.GONE); nextButton.setVisibility(View.GONE); - - rewindButton.setVisibility(View.VISIBLE); - fastforwardButton.setVisibility(View.VISIBLE); - } else { - previousButton.setVisibility(View.VISIBLE); - nextButton.setVisibility(View.VISIBLE); - rewindButton.setVisibility(View.GONE); fastforwardButton.setVisibility(View.GONE); + } else { + if (currentPlaying != null && !currentPlaying.isSong()) { + previousButton.setVisibility(View.GONE); + nextButton.setVisibility(View.GONE); + + rewindButton.setVisibility(View.VISIBLE); + fastforwardButton.setVisibility(View.VISIBLE); + } else { + previousButton.setVisibility(View.VISIBLE); + nextButton.setVisibility(View.VISIBLE); + + rewindButton.setVisibility(View.GONE); + fastforwardButton.setVisibility(View.GONE); + } } updateTitle(); } @@ -1265,7 +1286,9 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis getImageLoader().loadImage(albumArtImageView, song, true, true); DownloadService downloadService = getDownloadService(); - if(downloadService.isShufflePlayEnabled()) { + if(downloadService.isCurrentPlayingSingle()) { + setSubtitle(null); + } else if(downloadService.isShufflePlayEnabled()) { setSubtitle(context.getResources().getString(R.string.download_playerstate_playing_shuffle)); } else if(downloadService.isArtistRadio()) { setSubtitle(context.getResources().getString(R.string.download_playerstate_playing_artist_radio)); @@ -1314,6 +1337,14 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis } else { setupSubtitle(currentPlayingIndex); } + + if(downloadService.isCurrentPlayingSingle()) { + toggleListButton.setVisibility(View.GONE); + repeatButton.setVisibility(View.GONE); + } else { + toggleListButton.setVisibility(View.VISIBLE); + repeatButton.setVisibility(View.VISIBLE); + } } @Override @@ -1368,11 +1399,16 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis break; default: if(currentPlaying != null) { - String artist = ""; - if(currentPlaying.getSong().getArtist() != null) { - artist = currentPlaying.getSong().getArtist() + " - "; + Entry entry = currentPlaying.getSong(); + if(entry.getAlbum() != null) { + String artist = ""; + if (entry.getArtist() != null) { + artist = currentPlaying.getSong().getArtist() + " - "; + } + statusTextView.setText(artist + entry.getAlbum()); + } else { + statusTextView.setText(null); } - statusTextView.setText(artist + currentPlaying.getSong().getAlbum()); } else { statusTextView.setText(null); } diff --git a/app/src/main/java/github/daneren2005/dsub/fragments/SelectInternetRadioStationFragment.java b/app/src/main/java/github/daneren2005/dsub/fragments/SelectInternetRadioStationFragment.java index 94c0f1e2..16082cbd 100644 --- a/app/src/main/java/github/daneren2005/dsub/fragments/SelectInternetRadioStationFragment.java +++ b/app/src/main/java/github/daneren2005/dsub/fragments/SelectInternetRadioStationFragment.java @@ -29,8 +29,10 @@ import github.daneren2005.dsub.R; import github.daneren2005.dsub.adapter.InternetRadioStationAdapter; import github.daneren2005.dsub.adapter.SectionAdapter; import github.daneren2005.dsub.domain.InternetRadioStation; +import github.daneren2005.dsub.service.DownloadService; import github.daneren2005.dsub.service.MusicService; import github.daneren2005.dsub.util.ProgressListener; +import github.daneren2005.dsub.util.TabBackgroundTask; import github.daneren2005.dsub.util.Util; import github.daneren2005.dsub.view.UpdateView; @@ -56,8 +58,24 @@ public class SelectInternetRadioStationFragment extends SelectRecyclerFragment updateView, InternetRadioStation item) { - + public void onItemClicked(UpdateView updateView, final InternetRadioStation item) { + new TabBackgroundTask(this) { + @Override + protected Void doInBackground() throws Throwable { + DownloadService downloadService = getDownloadService(); + if(downloadService == null) { + return null; + } + + downloadService.download(item); + return null; + } + + @Override + protected void done(Void result) { + context.openNowPlaying(); + } + }.execute(); } @Override diff --git a/app/src/main/java/github/daneren2005/dsub/service/DownloadFile.java b/app/src/main/java/github/daneren2005/dsub/service/DownloadFile.java index e4bab798..d1c594ce 100644 --- a/app/src/main/java/github/daneren2005/dsub/service/DownloadFile.java +++ b/app/src/main/java/github/daneren2005/dsub/service/DownloadFile.java @@ -29,6 +29,8 @@ import android.content.Context; import android.net.wifi.WifiManager; import android.os.PowerManager; import android.util.Log; + +import github.daneren2005.dsub.domain.InternetRadioStation; import github.daneren2005.dsub.domain.MusicDirectory; import github.daneren2005.dsub.util.Constants; import github.daneren2005.dsub.util.SilentBackgroundTask; @@ -377,6 +379,18 @@ public class DownloadFile implements BufferFile { } } + public boolean isStream() { + return song != null && song instanceof InternetRadioStation; + } + public String getStream() { + if(song != null && song instanceof InternetRadioStation) { + InternetRadioStation station = (InternetRadioStation) song; + return station.getStreamUrl(); + } else { + return null; + } + } + @Override public String toString() { return "DownloadFile (" + song + ")"; diff --git a/app/src/main/java/github/daneren2005/dsub/service/DownloadService.java b/app/src/main/java/github/daneren2005/dsub/service/DownloadService.java index cec98865..915906c8 100644 --- a/app/src/main/java/github/daneren2005/dsub/service/DownloadService.java +++ b/app/src/main/java/github/daneren2005/dsub/service/DownloadService.java @@ -35,6 +35,7 @@ import github.daneren2005.dsub.activity.SubsonicActivity; import github.daneren2005.dsub.audiofx.AudioEffectsController; import github.daneren2005.dsub.audiofx.EqualizerController; import github.daneren2005.dsub.domain.Bookmark; +import github.daneren2005.dsub.domain.InternetRadioStation; import github.daneren2005.dsub.domain.MusicDirectory; import github.daneren2005.dsub.domain.PlayerState; import github.daneren2005.dsub.domain.PodcastEpisode; @@ -60,6 +61,7 @@ import github.daneren2005.serverproxy.BufferProxy; import java.io.File; import java.io.IOException; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.Date; import java.util.Iterator; @@ -123,7 +125,7 @@ public class DownloadService extends Service { private RemoteControlClientBase mRemoteControl; - private final IBinder binder = new SimpleServiceBinder(this); + private final IBinder binder = new SimpleServiceBinder<>(this); private Looper mediaPlayerLooper; private MediaPlayer mediaPlayer; private MediaPlayer nextMediaPlayer; @@ -382,6 +384,10 @@ public class DownloadService extends Service { handler.postDelayed(r, millis); } + public synchronized void download(InternetRadioStation station) { + clear(); + download(Arrays.asList((MusicDirectory.Entry) station), false, true, false, false); + } public synchronized void download(List songs, boolean save, boolean autoplay, boolean playNext, boolean shuffle) { download(songs, save, autoplay, playNext, shuffle, 0, 0); } @@ -394,7 +400,10 @@ public class DownloadService extends Service { if (songs.isEmpty()) { return; + } else if(isCurrentPlayingSingle()) { + clear(); } + if (playNext) { if (autoplay && getCurrentPlayingIndex() >= 0) { offset = 0; @@ -996,6 +1005,21 @@ public class DownloadService extends Service { public List getToDelete() { return toDelete; } + public boolean isCurrentPlayingSingle() { + if(currentPlaying != null && currentPlaying.getSong() instanceof InternetRadioStation) { + return true; + } else { + return false; + } + } + public boolean isCurrentPlayingStream() { + if(currentPlaying != null) { + return currentPlaying.isStream(); + } else { + return false; + } + } + public synchronized List getDownloads() { List temp = new ArrayList(); temp.addAll(downloadList); @@ -1819,7 +1843,7 @@ public class DownloadService extends Service { bufferAndPlay(position, true); } private synchronized void bufferAndPlay(int position, boolean start) { - if(!currentPlaying.isCompleteFileAvailable()) { + if(!currentPlaying.isCompleteFileAvailable() && !currentPlaying.isStream()) { if(Util.isAllowedToDownload(this)) { reset(); @@ -1835,11 +1859,6 @@ public class DownloadService extends Service { private synchronized void doPlay(final DownloadFile downloadFile, final int position, final boolean start) { try { - downloadFile.setPlaying(true); - final File file = downloadFile.isCompleteFileAvailable() ? downloadFile.getCompleteFile() : downloadFile.getPartialFile(); - boolean isPartial = file.equals(downloadFile.getPartialFile()); - downloadFile.updateModificationDate(); - subtractPosition = 0; mediaPlayer.setOnCompletionListener(null); mediaPlayer.setOnPreparedListener(null); @@ -1851,19 +1870,33 @@ public class DownloadService extends Service { } catch(Throwable e) { mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC); } - String dataSource = file.getAbsolutePath(); - if(isPartial && !Util.isOffline(this)) { - if (proxy == null) { - proxy = new BufferProxy(this); - proxy.start(); - } - proxy.setBufferFile(downloadFile); - dataSource = proxy.getPrivateAddress(dataSource); + + String dataSource; + boolean isPartial = false; + if(downloadFile.isStream()) { + dataSource = downloadFile.getStream(); Log.i(TAG, "Data Source: " + dataSource); - } else if(proxy != null) { - proxy.stop(); - proxy = null; + } else { + downloadFile.setPlaying(true); + final File file = downloadFile.isCompleteFileAvailable() ? downloadFile.getCompleteFile() : downloadFile.getPartialFile(); + isPartial = file.equals(downloadFile.getPartialFile()); + downloadFile.updateModificationDate(); + + dataSource = file.getAbsolutePath(); + if (isPartial && !Util.isOffline(this)) { + if (proxy == null) { + proxy = new BufferProxy(this); + proxy.start(); + } + proxy.setBufferFile(downloadFile); + dataSource = proxy.getPrivateAddress(dataSource); + Log.i(TAG, "Data Source: " + dataSource); + } else if (proxy != null) { + proxy.stop(); + proxy = null; + } } + mediaPlayer.setDataSource(dataSource); setPlayerState(PREPARING); @@ -2167,6 +2200,9 @@ public class DownloadService extends Service { if (downloadList.isEmpty() && backgroundDownloadList.isEmpty()) { return; } + if(currentPlaying != null && currentPlaying.isStream()) { + return; + } // Need to download current playing and not casting? if (currentPlaying != null && remoteState == LOCAL && currentPlaying != currentDownloading && !currentPlaying.isWorkDone()) { diff --git a/app/src/main/java/github/daneren2005/dsub/util/Notifications.java b/app/src/main/java/github/daneren2005/dsub/util/Notifications.java index 2948844b..0d4a0f9c 100644 --- a/app/src/main/java/github/daneren2005/dsub/util/Notifications.java +++ b/app/src/main/java/github/daneren2005/dsub/util/Notifications.java @@ -67,9 +67,10 @@ public final class Notifications { notification.flags |= Notification.FLAG_NO_CLEAR | Notification.FLAG_ONGOING_EVENT; } boolean remote = downloadService.isRemoteEnabled(); + boolean isSingle = downloadService.isCurrentPlayingSingle(); if (Build.VERSION.SDK_INT>= Build.VERSION_CODES.JELLY_BEAN){ RemoteViews expandedContentView = new RemoteViews(context.getPackageName(), R.layout.notification_expanded); - setupViews(expandedContentView ,context, song, true, playing, remote); + setupViews(expandedContentView ,context, song, true, playing, remote, isSingle); notification.bigContentView = expandedContentView; notification.priority = Notification.PRIORITY_HIGH; } @@ -82,7 +83,7 @@ public final class Notifications { } RemoteViews smallContentView = new RemoteViews(context.getPackageName(), R.layout.notification); - setupViews(smallContentView, context, song, false, playing, remote); + setupViews(smallContentView, context, song, false, playing, remote, isSingle); notification.contentView = smallContentView; Intent notificationIntent = new Intent(context, SubsonicFragmentActivity.class); @@ -122,7 +123,7 @@ public final class Notifications { DSubWidgetProvider.notifyInstances(context, downloadService, playing); } - private static void setupViews(RemoteViews rv, Context context, MusicDirectory.Entry song, boolean expanded, boolean playing, boolean remote) { + private static void setupViews(RemoteViews rv, Context context, MusicDirectory.Entry song, boolean expanded, boolean playing, boolean remote, boolean isSingleFile) { boolean isLongFile = song.isAudioBook() || song.isPodcast(); // Use the same text for the ticker and the expanded notification @@ -209,6 +210,27 @@ public final class Notifications { close = R.id.notification_close; rv.setViewVisibility(close, View.VISIBLE); } + + if(isSingleFile) { + if(previous > 0) { + rv.setViewVisibility(previous, View.GONE); + previous = 0; + } + if(rewind > 0) { + rv.setViewVisibility(rewind, View.GONE); + rewind = 0; + } + + if(next > 0) { + rv.setViewVisibility(next, View.GONE); + next = 0; + } + + if(fastForward > 0) { + rv.setViewVisibility(fastForward, View.GONE); + fastForward = 0; + } + } if(previous > 0) { Intent prevIntent = new Intent("KEYCODE_MEDIA_PREVIOUS"); -- cgit v1.2.3