Implement shuffle radio feature (#145)

master
François-Xavier Thomas 8 years ago
parent a2deb0b779
commit 6d8df63a7e
No known key found for this signature in database
GPG Key ID: 64337406D2DD45CE
  1. 8
      libresonic-main/src/main/java/org/libresonic/player/ajax/PlayQueueInfo.java
  2. 22
      libresonic-main/src/main/java/org/libresonic/player/ajax/PlayQueueService.java
  3. 2
      libresonic-main/src/main/java/org/libresonic/player/controller/RandomPlayQueueController.java
  4. 9
      libresonic-main/src/main/java/org/libresonic/player/domain/PlayQueue.java
  5. 4
      libresonic-main/src/main/resources/org/libresonic/player/i18n/ResourceBundle_en.properties
  6. 15
      libresonic-main/src/main/webapp/WEB-INF/jsp/more.jsp
  7. 19
      libresonic-main/src/main/webapp/WEB-INF/jsp/playQueue.jsp

@ -33,15 +33,17 @@ public class PlayQueueInfo {
private final List<Entry> entries; private final List<Entry> entries;
private final boolean stopEnabled; private final boolean stopEnabled;
private final boolean repeatEnabled; private final boolean repeatEnabled;
private final boolean radioEnabled;
private final boolean sendM3U; private final boolean sendM3U;
private final float gain; private final float gain;
private int startPlayerAt = -1; private int startPlayerAt = -1;
private long startPlayerAtPosition; // millis private long startPlayerAtPosition; // millis
public PlayQueueInfo(List<Entry> entries, boolean stopEnabled, boolean repeatEnabled, boolean sendM3U, float gain) { public PlayQueueInfo(List<Entry> entries, boolean stopEnabled, boolean repeatEnabled, boolean radioEnabled, boolean sendM3U, float gain) {
this.entries = entries; this.entries = entries;
this.stopEnabled = stopEnabled; this.stopEnabled = stopEnabled;
this.repeatEnabled = repeatEnabled; this.repeatEnabled = repeatEnabled;
this.radioEnabled = radioEnabled;
this.sendM3U = sendM3U; this.sendM3U = sendM3U;
this.gain = gain; this.gain = gain;
} }
@ -72,6 +74,10 @@ public class PlayQueueInfo {
return repeatEnabled; return repeatEnabled;
} }
public boolean isRadioEnabled() {
return radioEnabled;
}
public float getGain() { public float getGain() {
return gain; return gain;
} }

@ -148,6 +148,18 @@ public class PlayQueueService {
return convert(request, player, serverSidePlaylist, offset); return convert(request, player, serverSidePlaylist, offset);
} }
public PlayQueueInfo reloadSearchCriteria() throws Exception {
HttpServletRequest request = WebContextFactory.get().getHttpServletRequest();
HttpServletResponse response = WebContextFactory.get().getHttpServletResponse();
String username = securityService.getCurrentUsername(request);
Player player = getCurrentPlayer(request, response);
PlayQueue playQueue = player.getPlayQueue();
if (playQueue.getRandomSearchCriteria() != null) {
playQueue.addFiles(true, mediaFileService.getRandomSongs(playQueue.getRandomSearchCriteria(), username));
}
return convert(request, player, false);
}
public void savePlayQueue(int currentSongIndex, long positionMillis) { public void savePlayQueue(int currentSongIndex, long positionMillis) {
HttpServletRequest request = WebContextFactory.get().getHttpServletRequest(); HttpServletRequest request = WebContextFactory.get().getHttpServletRequest();
HttpServletResponse response = WebContextFactory.get().getHttpServletResponse(); HttpServletResponse response = WebContextFactory.get().getHttpServletResponse();
@ -581,7 +593,13 @@ public class PlayQueueService {
HttpServletRequest request = WebContextFactory.get().getHttpServletRequest(); HttpServletRequest request = WebContextFactory.get().getHttpServletRequest();
HttpServletResponse response = WebContextFactory.get().getHttpServletResponse(); HttpServletResponse response = WebContextFactory.get().getHttpServletResponse();
Player player = getCurrentPlayer(request, response); Player player = getCurrentPlayer(request, response);
player.getPlayQueue().setRepeatEnabled(!player.getPlayQueue().isRepeatEnabled()); PlayQueue playQueue = player.getPlayQueue();
if (playQueue.isRadioEnabled()) {
playQueue.setRandomSearchCriteria(null);
playQueue.setRepeatEnabled(false);
} else {
playQueue.setRepeatEnabled(!player.getPlayQueue().isRepeatEnabled());
}
return convert(request, player, false); return convert(request, player, false);
} }
@ -668,7 +686,7 @@ public class PlayQueueService {
} }
boolean isStopEnabled = playQueue.getStatus() == PlayQueue.Status.PLAYING && !player.isExternalWithPlaylist(); boolean isStopEnabled = playQueue.getStatus() == PlayQueue.Status.PLAYING && !player.isExternalWithPlaylist();
float gain = jukeboxService.getGain(); float gain = jukeboxService.getGain();
return new PlayQueueInfo(entries, isStopEnabled, playQueue.isRepeatEnabled(), serverSidePlaylist, gain); return new PlayQueueInfo(entries, isStopEnabled, playQueue.isRepeatEnabled(), playQueue.isRadioEnabled(), serverSidePlaylist, gain);
} }
private String formatFileSize(Long fileSize, Locale locale) { private String formatFileSize(Long fileSize, Locale locale) {

@ -199,7 +199,7 @@ public class RandomPlayQueueController extends ParameterizableViewController {
List<MusicFolder> musicFolders = getMusicFolders(request); List<MusicFolder> musicFolders = getMusicFolders(request);
// Do we add to the current playlist or do we replace it? // Do we add to the current playlist or do we replace it?
boolean shouldAddToPlayList = ServletRequestUtils.getBooleanParameter(request, "addToPlaylist", false); boolean shouldAddToPlayList = request.getParameter("addToPlaylist") != null;
// Search the database using these criteria // Search the database using these criteria
RandomSearchCriteria criteria = new RandomSearchCriteria( RandomSearchCriteria criteria = new RandomSearchCriteria(

@ -368,6 +368,15 @@ public class PlayQueue {
this.repeatEnabled = repeatEnabled; this.repeatEnabled = repeatEnabled;
} }
/**
* Returns whether the playlist is a shuffle radio
*
* @return Whether the playlist is a shuffle radio.
*/
public synchronized boolean isRadioEnabled() {
return this.randomSearchCriteria != null;
}
/** /**
* Revert the last operation. * Revert the last operation.
*/ */

@ -100,6 +100,7 @@ playlist.clear = Clear
playlist.shuffle = Shuffle playlist.shuffle = Shuffle
playlist.repeat_on = Repeat is on playlist.repeat_on = Repeat is on
playlist.repeat_off = Repeat is off playlist.repeat_off = Repeat is off
playlist.repeat_radio = Stop shuffle radio
playlist.undo = Undo playlist.undo = Undo
playlist.settings = Settings playlist.settings = Settings
playlist.more = More actions... playlist.more = More actions...
@ -233,7 +234,8 @@ more.random.text = Shuffle play
more.random.songs = {0} songs more.random.songs = {0} songs
more.random.auto = Play more random songs when end of play queue is reached. more.random.auto = Play more random songs when end of play queue is reached.
more.random.ok = OK more.random.ok = OK
more.random.addtoplaylist = Add to current playlist more.random.add = Add to queue
more.random.radio = Shuffle radio
more.random.any = Any more.random.any = Any
more.random.format = Format more.random.format = Format
more.random.genre = Genre more.random.genre = Genre

@ -232,24 +232,13 @@
<option value="mp3">MP3</option> <option value="mp3">MP3</option>
</select> </select>
</td> </td>
<td><fmt:message key="more.random.addtoplaylist"/></td>
<td>
<input name="addToPlaylist" value="true" type="checkbox"/>
</td>
</tr> </tr>
<tr> <tr>
<td colspan="2"> <td colspan="2">
<input type="submit" value="<fmt:message key="more.random.ok"/>"> <input type="submit" name="addToPlaylist" value="<fmt:message key="more.random.add"/>">
</td> <input type="submit" name="autoRandom" value="<fmt:message key="more.random.radio"/>">
</tr>
<c:if test="${not model.clientSidePlaylist}">
<tr>
<td colspan="9">
<input type="checkbox" name="autoRandom" id="autoRandom" class="checkbox"/>
<label for="autoRandom"><fmt:message key="more.random.auto"/></label>
</td> </td>
</tr> </tr>
</c:if>
</table> </table>
</form> </form>
</c:if> </c:if>

@ -37,6 +37,7 @@
var songs = null; var songs = null;
var currentStreamUrl = null; var currentStreamUrl = null;
var repeatEnabled = false; var repeatEnabled = false;
var radioEnabled = false;
var isVisible = ${model.autoHide ? 'false' : 'true'}; var isVisible = ${model.autoHide ? 'false' : 'true'};
var CastPlayer = new CastPlayer(); var CastPlayer = new CastPlayer();
var ignore = false; var ignore = false;
@ -269,7 +270,13 @@
} }
function onNext(wrap) { function onNext(wrap) {
var index = parseInt(getCurrentSongIndex()) + 1; var index = parseInt(getCurrentSongIndex()) + 1;
if (wrap) { if (radioEnabled && index >= songs.length) {
playQueueService.reloadSearchCriteria(function(playQueue) {
playQueueCallback(playQueue);
onSkip(index);
});
return;
} else if (wrap) {
index = index % songs.length; index = index % songs.length;
} }
onSkip(index); onSkip(index);
@ -402,14 +409,20 @@
function playQueueCallback(playQueue) { function playQueueCallback(playQueue) {
songs = playQueue.entries; songs = playQueue.entries;
repeatEnabled = playQueue.repeatEnabled; repeatEnabled = playQueue.repeatEnabled;
radioEnabled = playQueue.radioEnabled;
if ($("#start")) { if ($("#start")) {
$("#start").toggle(!playQueue.stopEnabled); $("#start").toggle(!playQueue.stopEnabled);
$("#stop").toggle(playQueue.stopEnabled); $("#stop").toggle(playQueue.stopEnabled);
} }
if ($("#toggleRepeat")) { if ($("#toggleRepeat")) {
var text = repeatEnabled ? "<fmt:message key="playlist.repeat_on"/>" : "<fmt:message key="playlist.repeat_off"/>"; if (radioEnabled) {
$("#toggleRepeat").html(text); $("#toggleRepeat").html("<fmt:message key="playlist.repeat_radio"/>");
} else if (repeatEnabled) {
$("#toggleRepeat").html("<fmt:message key="playlist.repeat_on"/>");
} else {
$("#toggleRepeat").html("<fmt:message key="playlist.repeat_off"/>");
}
} }
if (songs.length == 0) { if (songs.length == 0) {

Loading…
Cancel
Save