Merge remote-tracking branch 'origin/pr/807'
This commit is contained in:
@@ -87,6 +87,16 @@
|
|||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-starter-security</artifactId>
|
<artifactId>spring-boot-starter-security</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-test</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.security</groupId>
|
||||||
|
<artifactId>spring-security-test</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.security</groupId>
|
<groupId>org.springframework.security</groupId>
|
||||||
<artifactId>spring-security-ldap</artifactId>
|
<artifactId>spring-security-ldap</artifactId>
|
||||||
|
|||||||
+2
-2
@@ -1274,7 +1274,7 @@ public class SubsonicRESTController {
|
|||||||
child.setSuffix(suffix);
|
child.setSuffix(suffix);
|
||||||
child.setContentType(StringUtil.getMimeType(suffix));
|
child.setContentType(StringUtil.getMimeType(suffix));
|
||||||
child.setIsVideo(mediaFile.isVideo());
|
child.setIsVideo(mediaFile.isVideo());
|
||||||
child.setPath(getRelativePath(mediaFile));
|
child.setPath(getRelativePath(mediaFile, settingsService));
|
||||||
|
|
||||||
org.airsonic.player.domain.Bookmark bookmark = bookmarkCache.get(new BookmarkKey(username, mediaFile.getId()));
|
org.airsonic.player.domain.Bookmark bookmark = bookmarkCache.get(new BookmarkKey(username, mediaFile.getId()));
|
||||||
if (bookmark != null) {
|
if (bookmark != null) {
|
||||||
@@ -1329,7 +1329,7 @@ public class SubsonicRESTController {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getRelativePath(MediaFile musicFile) {
|
public static String getRelativePath(MediaFile musicFile, SettingsService settingsService) {
|
||||||
|
|
||||||
String filePath = musicFile.getPath();
|
String filePath = musicFile.getPath();
|
||||||
|
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ package org.airsonic.player.dao;
|
|||||||
import org.airsonic.player.domain.*;
|
import org.airsonic.player.domain.*;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.jdbc.core.RowMapper;
|
import org.springframework.jdbc.core.RowMapper;
|
||||||
import org.springframework.stereotype.Repository;
|
import org.springframework.stereotype.Repository;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
@@ -43,6 +44,9 @@ public class PlayerDao extends AbstractDao {
|
|||||||
"last_seen, cover_art_scheme, transcode_scheme, dynamic_ip, technology, client_id, mixer";
|
"last_seen, cover_art_scheme, transcode_scheme, dynamic_ip, technology, client_id, mixer";
|
||||||
private static final String QUERY_COLUMNS = "id, " + INSERT_COLUMNS;
|
private static final String QUERY_COLUMNS = "id, " + INSERT_COLUMNS;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private PlayerDaoPlayQueueFactory playerDaoPlayQueueFactory;
|
||||||
|
|
||||||
private PlayerRowMapper rowMapper = new PlayerRowMapper();
|
private PlayerRowMapper rowMapper = new PlayerRowMapper();
|
||||||
private Map<Integer, PlayQueue> playlists = Collections.synchronizedMap(new HashMap<Integer, PlayQueue>());
|
private Map<Integer, PlayQueue> playlists = Collections.synchronizedMap(new HashMap<Integer, PlayQueue>());
|
||||||
|
|
||||||
@@ -166,7 +170,7 @@ public class PlayerDao extends AbstractDao {
|
|||||||
private void addPlaylist(Player player) {
|
private void addPlaylist(Player player) {
|
||||||
PlayQueue playQueue = playlists.get(player.getId());
|
PlayQueue playQueue = playlists.get(player.getId());
|
||||||
if (playQueue == null) {
|
if (playQueue == null) {
|
||||||
playQueue = new PlayQueue();
|
playQueue = playerDaoPlayQueueFactory.createPlayQueue();
|
||||||
playlists.put(player.getId(), playQueue);
|
playlists.put(player.getId(), playQueue);
|
||||||
}
|
}
|
||||||
player.setPlayQueue(playQueue);
|
player.setPlayQueue(playQueue);
|
||||||
|
|||||||
@@ -0,0 +1,12 @@
|
|||||||
|
package org.airsonic.player.dao;
|
||||||
|
|
||||||
|
import org.airsonic.player.domain.PlayQueue;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class PlayerDaoPlayQueueFactory {
|
||||||
|
|
||||||
|
public PlayQueue createPlayQueue() {
|
||||||
|
return new PlayQueue();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
package org.airsonic.player.service;
|
package org.airsonic.player.service;
|
||||||
|
|
||||||
import com.github.biconou.AudioPlayer.JavaPlayer;
|
import com.github.biconou.AudioPlayer.api.PlayList;
|
||||||
import com.github.biconou.AudioPlayer.api.*;
|
import com.github.biconou.AudioPlayer.api.PlayerListener;
|
||||||
import org.airsonic.player.domain.*;
|
import org.airsonic.player.domain.*;
|
||||||
import org.airsonic.player.domain.Player;
|
import org.airsonic.player.service.jukebox.JavaPlayerFactory;
|
||||||
import org.airsonic.player.util.FileUtil;
|
import org.airsonic.player.util.FileUtil;
|
||||||
import org.apache.commons.lang.StringUtils;
|
import org.apache.commons.lang.StringUtils;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
@@ -19,23 +19,25 @@ import java.util.Map;
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author R??mi Cocula
|
* @author Rémi Cocula
|
||||||
*/
|
*/
|
||||||
@Service
|
@Service
|
||||||
public class JukeboxJavaService {
|
public class JukeboxJavaService {
|
||||||
|
|
||||||
private static final org.slf4j.Logger log = LoggerFactory.getLogger(JukeboxJavaService.class);
|
private static final org.slf4j.Logger log = LoggerFactory.getLogger(JukeboxJavaService.class);
|
||||||
|
|
||||||
|
private static final float DEFAULT_GAIN = 0.75f;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private AudioScrobblerService audioScrobblerService;
|
private AudioScrobblerService audioScrobblerService;
|
||||||
@Autowired
|
@Autowired
|
||||||
private StatusService statusService;
|
private StatusService statusService;
|
||||||
@Autowired
|
@Autowired
|
||||||
private SettingsService settingsService;
|
|
||||||
@Autowired
|
|
||||||
private SecurityService securityService;
|
private SecurityService securityService;
|
||||||
@Autowired
|
@Autowired
|
||||||
private MediaFileService mediaFileService;
|
private MediaFileService mediaFileService;
|
||||||
|
@Autowired
|
||||||
|
private JavaPlayerFactory javaPlayerFactory;
|
||||||
|
|
||||||
|
|
||||||
private TransferStatus status;
|
private TransferStatus status;
|
||||||
@@ -45,31 +47,32 @@ public class JukeboxJavaService {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Finds the corresponding active audio player for a given airsonic player.
|
* Finds the corresponding active audio player for a given airsonic player.
|
||||||
|
* If no player exists we create one.
|
||||||
* The JukeboxJavaService references all active audio players in a map indexed by airsonic player id.
|
* The JukeboxJavaService references all active audio players in a map indexed by airsonic player id.
|
||||||
*
|
*
|
||||||
* @param airsonicPlayer a given airsonic player.
|
* @param airsonicPlayer a given airsonic player.
|
||||||
* @return the corresponding active audio player of null if none exists.
|
* @return the corresponding active audio player.
|
||||||
*/
|
*/
|
||||||
private com.github.biconou.AudioPlayer.api.Player retrieveAudioPlayerForAirsonicPlayer(Player airsonicPlayer) {
|
private com.github.biconou.AudioPlayer.api.Player retrieveAudioPlayerForAirsonicPlayer(Player airsonicPlayer) {
|
||||||
com.github.biconou.AudioPlayer.api.Player foundPlayer = activeAudioPlayers.get(airsonicPlayer.getId());
|
com.github.biconou.AudioPlayer.api.Player foundPlayer = activeAudioPlayers.get(airsonicPlayer.getId());
|
||||||
if (foundPlayer == null) {
|
if (foundPlayer == null) {
|
||||||
synchronized (activeAudioPlayers) {
|
synchronized (activeAudioPlayers) {
|
||||||
foundPlayer = initAudioPlayer(airsonicPlayer);
|
com.github.biconou.AudioPlayer.api.Player newPlayer = initAudioPlayer(airsonicPlayer);
|
||||||
if (foundPlayer == null) {
|
if (newPlayer == null) {
|
||||||
throw new RuntimeException("Did not initialized a player");
|
throw new RuntimeException("Did not initialized a player");
|
||||||
} else {
|
|
||||||
activeAudioPlayers.put(airsonicPlayer.getId(), foundPlayer);
|
|
||||||
String mixer = airsonicPlayer.getJavaJukeboxMixer();
|
|
||||||
if (StringUtils.isBlank(mixer)) {
|
|
||||||
mixer = DEFAULT_MIXER_ENTRY_KEY;
|
|
||||||
}
|
|
||||||
List<com.github.biconou.AudioPlayer.api.Player> playersForMixer = activeAudioPlayersPerMixer.get(mixer);
|
|
||||||
if (playersForMixer == null) {
|
|
||||||
playersForMixer = new ArrayList<>();
|
|
||||||
activeAudioPlayersPerMixer.put(mixer, playersForMixer);
|
|
||||||
}
|
|
||||||
playersForMixer.add(foundPlayer);
|
|
||||||
}
|
}
|
||||||
|
activeAudioPlayers.put(airsonicPlayer.getId(), newPlayer);
|
||||||
|
String mixer = airsonicPlayer.getJavaJukeboxMixer();
|
||||||
|
if (StringUtils.isBlank(mixer)) {
|
||||||
|
mixer = DEFAULT_MIXER_ENTRY_KEY;
|
||||||
|
}
|
||||||
|
List<com.github.biconou.AudioPlayer.api.Player> playersForMixer = activeAudioPlayersPerMixer.get(mixer);
|
||||||
|
if (playersForMixer == null) {
|
||||||
|
playersForMixer = new ArrayList<>();
|
||||||
|
activeAudioPlayersPerMixer.put(mixer, playersForMixer);
|
||||||
|
}
|
||||||
|
playersForMixer.add(newPlayer);
|
||||||
|
foundPlayer = newPlayer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return foundPlayer;
|
return foundPlayer;
|
||||||
@@ -88,11 +91,12 @@ public class JukeboxJavaService {
|
|||||||
|
|
||||||
if (StringUtils.isNotBlank(airsonicPlayer.getJavaJukeboxMixer())) {
|
if (StringUtils.isNotBlank(airsonicPlayer.getJavaJukeboxMixer())) {
|
||||||
log.info("use mixer : {}", airsonicPlayer.getJavaJukeboxMixer());
|
log.info("use mixer : {}", airsonicPlayer.getJavaJukeboxMixer());
|
||||||
audioPlayer = new JavaPlayer(airsonicPlayer.getJavaJukeboxMixer());
|
audioPlayer = javaPlayerFactory.createJavaPlayer(airsonicPlayer.getJavaJukeboxMixer());
|
||||||
} else {
|
} else {
|
||||||
log.info("use default mixer");
|
log.info("use default mixer");
|
||||||
audioPlayer = new JavaPlayer();
|
audioPlayer = javaPlayerFactory.createJavaPlayer();
|
||||||
}
|
}
|
||||||
|
audioPlayer.setGain(DEFAULT_GAIN);
|
||||||
if (audioPlayer != null) {
|
if (audioPlayer != null) {
|
||||||
audioPlayer.registerListener(new PlayerListener() {
|
audioPlayer.registerListener(new PlayerListener() {
|
||||||
@Override
|
@Override
|
||||||
@@ -159,10 +163,7 @@ public class JukeboxJavaService {
|
|||||||
throw new RuntimeException("The player " + airsonicPlayer.getName() + " is not a java jukebox player");
|
throw new RuntimeException("The player " + airsonicPlayer.getName() + " is not a java jukebox player");
|
||||||
}
|
}
|
||||||
com.github.biconou.AudioPlayer.api.Player audioPlayer = retrieveAudioPlayerForAirsonicPlayer(airsonicPlayer);
|
com.github.biconou.AudioPlayer.api.Player audioPlayer = retrieveAudioPlayerForAirsonicPlayer(airsonicPlayer);
|
||||||
if (audioPlayer != null) {
|
return audioPlayer.getGain();
|
||||||
return audioPlayer.getGain();
|
|
||||||
}
|
|
||||||
return 0.5f;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setGain(final Player airsonicPlayer, final float gain) {
|
public void setGain(final Player airsonicPlayer, final float gain) {
|
||||||
@@ -271,20 +272,8 @@ public class JukeboxJavaService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void start(Player airsonicPlayer) throws Exception {
|
public void start(Player airsonicPlayer) {
|
||||||
log.debug("begin start jukebox : player = id:{};name:{}", airsonicPlayer.getId(), airsonicPlayer.getName());
|
play(airsonicPlayer);
|
||||||
|
|
||||||
com.github.biconou.AudioPlayer.api.Player audioPlayer = retrieveAudioPlayerForAirsonicPlayer(airsonicPlayer);
|
|
||||||
|
|
||||||
// Control user authorizations
|
|
||||||
User user = securityService.getUserByName(airsonicPlayer.getUsername());
|
|
||||||
if (!user.isJukeboxRole()) {
|
|
||||||
log.warn("{} is not authorized for jukebox playback.", user.getUsername());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
log.debug("PlayQueue.Status is {}", airsonicPlayer.getPlayQueue().getStatus());
|
|
||||||
audioPlayer.play();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void stop(Player airsonicPlayer) throws Exception {
|
public void stop(Player airsonicPlayer) throws Exception {
|
||||||
@@ -332,7 +321,6 @@ public class JukeboxJavaService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void setAudioScrobblerService(AudioScrobblerService audioScrobblerService) {
|
public void setAudioScrobblerService(AudioScrobblerService audioScrobblerService) {
|
||||||
this.audioScrobblerService = audioScrobblerService;
|
this.audioScrobblerService = audioScrobblerService;
|
||||||
}
|
}
|
||||||
@@ -342,7 +330,6 @@ public class JukeboxJavaService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void setSettingsService(SettingsService settingsService) {
|
public void setSettingsService(SettingsService settingsService) {
|
||||||
this.settingsService = settingsService;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setSecurityService(SecurityService securityService) {
|
public void setSecurityService(SecurityService securityService) {
|
||||||
|
|||||||
+4
-1
@@ -21,6 +21,7 @@ package org.airsonic.player.service;
|
|||||||
|
|
||||||
import org.airsonic.player.domain.*;
|
import org.airsonic.player.domain.*;
|
||||||
import org.airsonic.player.service.jukebox.AudioPlayer;
|
import org.airsonic.player.service.jukebox.AudioPlayer;
|
||||||
|
import org.airsonic.player.service.jukebox.AudioPlayerFactory;
|
||||||
import org.airsonic.player.util.FileUtil;
|
import org.airsonic.player.util.FileUtil;
|
||||||
import org.apache.commons.io.IOUtils;
|
import org.apache.commons.io.IOUtils;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
@@ -52,6 +53,8 @@ public class JukeboxLegacySubsonicService implements AudioPlayer.Listener {
|
|||||||
private SecurityService securityService;
|
private SecurityService securityService;
|
||||||
@Autowired
|
@Autowired
|
||||||
private MediaFileService mediaFileService;
|
private MediaFileService mediaFileService;
|
||||||
|
@Autowired
|
||||||
|
private AudioPlayerFactory audioPlayerFactory;
|
||||||
|
|
||||||
private AudioPlayer audioPlayer;
|
private AudioPlayer audioPlayer;
|
||||||
private Player player;
|
private Player player;
|
||||||
@@ -111,7 +114,7 @@ public class JukeboxLegacySubsonicService implements AudioPlayer.Listener {
|
|||||||
String command = settingsService.getJukeboxCommand();
|
String command = settingsService.getJukeboxCommand();
|
||||||
parameters.setTranscoding(new Transcoding(null, null, null, null, command, null, null, false));
|
parameters.setTranscoding(new Transcoding(null, null, null, null, command, null, null, false));
|
||||||
in = transcodingService.getTranscodedInputStream(parameters);
|
in = transcodingService.getTranscodedInputStream(parameters);
|
||||||
audioPlayer = new AudioPlayer(in, this);
|
audioPlayer = audioPlayerFactory.createAudioPlayer(in, this);
|
||||||
audioPlayer.setGain(gain);
|
audioPlayer.setGain(gain);
|
||||||
audioPlayer.play();
|
audioPlayer.play();
|
||||||
onSongStart(file);
|
onSongStart(file);
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ import org.apache.commons.lang3.StringUtils;
|
|||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.context.annotation.Lazy;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
@@ -61,6 +62,7 @@ public class TranscodingService {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private SettingsService settingsService;
|
private SettingsService settingsService;
|
||||||
@Autowired
|
@Autowired
|
||||||
|
@Lazy // used to deal with circular dependencies between PlayerService and TranscodingService
|
||||||
private PlayerService playerService;
|
private PlayerService playerService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
+14
@@ -0,0 +1,14 @@
|
|||||||
|
package org.airsonic.player.service.jukebox;
|
||||||
|
|
||||||
|
import org.airsonic.player.service.JukeboxLegacySubsonicService;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class AudioPlayerFactory {
|
||||||
|
|
||||||
|
public AudioPlayer createAudioPlayer(InputStream in, JukeboxLegacySubsonicService jukeboxLegacySubsonicService) throws Exception {
|
||||||
|
return new AudioPlayer(in, jukeboxLegacySubsonicService);
|
||||||
|
}
|
||||||
|
}
|
||||||
+17
@@ -0,0 +1,17 @@
|
|||||||
|
package org.airsonic.player.service.jukebox;
|
||||||
|
|
||||||
|
import com.github.biconou.AudioPlayer.JavaPlayer;
|
||||||
|
import com.github.biconou.AudioPlayer.api.Player;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class JavaPlayerFactory {
|
||||||
|
|
||||||
|
public Player createJavaPlayer() {
|
||||||
|
return new JavaPlayer();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Player createJavaPlayer(String mixerName) {
|
||||||
|
return new JavaPlayer(mixerName);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
package org.airsonic.player;
|
package org.airsonic.player;
|
||||||
|
|
||||||
|
import org.airsonic.player.controller.JAXBWriter;
|
||||||
import org.airsonic.player.dao.DaoHelper;
|
import org.airsonic.player.dao.DaoHelper;
|
||||||
import org.airsonic.player.service.MediaScannerService;
|
import org.airsonic.player.service.MediaScannerService;
|
||||||
import org.apache.commons.io.FileUtils;
|
import org.apache.commons.io.FileUtils;
|
||||||
@@ -37,6 +38,13 @@ public class TestCaseUtils {
|
|||||||
return airsonicHomeDirForTest.getAbsolutePath();
|
return airsonicHomeDirForTest.getAbsolutePath();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @return current REST api version.
|
||||||
|
*/
|
||||||
|
public static String restApiVersion() {
|
||||||
|
return new JAXBWriter().getRestProtocolVersion();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cleans the AIRSONIC_HOME directory used for tests.
|
* Cleans the AIRSONIC_HOME directory used for tests.
|
||||||
@@ -106,6 +114,7 @@ public class TestCaseUtils {
|
|||||||
* Scans the music library * @param mediaScannerService
|
* Scans the music library * @param mediaScannerService
|
||||||
*/
|
*/
|
||||||
public static void execScan(MediaScannerService mediaScannerService) {
|
public static void execScan(MediaScannerService mediaScannerService) {
|
||||||
|
// TODO create a synchronous scan
|
||||||
mediaScannerService.scanLibrary();
|
mediaScannerService.scanLibrary();
|
||||||
|
|
||||||
while (mediaScannerService.isScanning()) {
|
while (mediaScannerService.isScanning()) {
|
||||||
|
|||||||
@@ -0,0 +1,59 @@
|
|||||||
|
package org.airsonic.player.api;
|
||||||
|
|
||||||
|
import org.airsonic.player.TestCaseUtils;
|
||||||
|
import org.airsonic.player.util.HomeRule;
|
||||||
|
import org.junit.BeforeClass;
|
||||||
|
import org.junit.ClassRule;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
|
||||||
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
|
import org.springframework.http.MediaType;
|
||||||
|
import org.springframework.test.context.junit4.SpringRunner;
|
||||||
|
import org.springframework.test.web.servlet.MockMvc;
|
||||||
|
|
||||||
|
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||||
|
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
|
||||||
|
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
|
||||||
|
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||||
|
|
||||||
|
|
||||||
|
@RunWith(SpringRunner.class)
|
||||||
|
@SpringBootTest
|
||||||
|
@AutoConfigureMockMvc
|
||||||
|
public class AirsonicRestApiIntTest {
|
||||||
|
|
||||||
|
public static final String CLIENT_NAME = "airsonic";
|
||||||
|
public static final String AIRSONIC_USER = "admin";
|
||||||
|
public static final String AIRSONIC_PASSWORD = "admin";
|
||||||
|
public static final String EXPECTED_FORMAT = "json";
|
||||||
|
|
||||||
|
private static String AIRSONIC_API_VERSION;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private MockMvc mvc;
|
||||||
|
|
||||||
|
@ClassRule
|
||||||
|
public static final HomeRule classRule = new HomeRule(); // sets airsonic.home to a temporary dir
|
||||||
|
|
||||||
|
@BeforeClass
|
||||||
|
public static void setupClass() {
|
||||||
|
AIRSONIC_API_VERSION = TestCaseUtils.restApiVersion();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void pingTest() throws Exception {
|
||||||
|
mvc.perform(get("/rest/ping")
|
||||||
|
.param("v", AIRSONIC_API_VERSION)
|
||||||
|
.param("c", CLIENT_NAME)
|
||||||
|
.param("u", AIRSONIC_USER)
|
||||||
|
.param("p", AIRSONIC_PASSWORD)
|
||||||
|
.param("f", EXPECTED_FORMAT)
|
||||||
|
.contentType(MediaType.APPLICATION_JSON))
|
||||||
|
.andExpect(status().isOk())
|
||||||
|
.andExpect(jsonPath("$.subsonic-response.status").value("ok"))
|
||||||
|
.andExpect(jsonPath("$.subsonic-response.version").value(AIRSONIC_API_VERSION))
|
||||||
|
.andDo(print());
|
||||||
|
}
|
||||||
|
}
|
||||||
+279
@@ -0,0 +1,279 @@
|
|||||||
|
package org.airsonic.player.api.jukebox;
|
||||||
|
|
||||||
|
import org.airsonic.player.TestCaseUtils;
|
||||||
|
import org.airsonic.player.dao.*;
|
||||||
|
import org.airsonic.player.domain.*;
|
||||||
|
import org.airsonic.player.service.MediaScannerService;
|
||||||
|
import org.airsonic.player.service.PlayerService;
|
||||||
|
import org.airsonic.player.service.SettingsService;
|
||||||
|
import org.airsonic.player.util.HomeRule;
|
||||||
|
import org.junit.*;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
|
||||||
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
|
import org.springframework.boot.test.context.TestConfiguration;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.http.MediaType;
|
||||||
|
import org.springframework.security.test.context.support.WithMockUser;
|
||||||
|
import org.springframework.test.annotation.DirtiesContext;
|
||||||
|
import org.springframework.test.context.junit4.SpringRunner;
|
||||||
|
import org.springframework.test.web.servlet.MockMvc;
|
||||||
|
import org.springframework.test.web.servlet.ResultActions;
|
||||||
|
import org.springframework.test.web.servlet.ResultMatcher;
|
||||||
|
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.TimeZone;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
import static org.mockito.Mockito.*;
|
||||||
|
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||||
|
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
|
||||||
|
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
|
||||||
|
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||||
|
|
||||||
|
@RunWith(SpringRunner.class)
|
||||||
|
@SpringBootTest
|
||||||
|
@AutoConfigureMockMvc
|
||||||
|
@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD)
|
||||||
|
public abstract class AbstractAirsonicRestApiJukeboxIntTest {
|
||||||
|
|
||||||
|
@ClassRule
|
||||||
|
public static final HomeRule classRule = new HomeRule(); // sets airsonic.home to a temporary dir
|
||||||
|
|
||||||
|
@TestConfiguration
|
||||||
|
static class Config {
|
||||||
|
private static class SpiedPlayerDaoPlayQueueFactory extends PlayerDaoPlayQueueFactory {
|
||||||
|
@Override
|
||||||
|
public PlayQueue createPlayQueue() {
|
||||||
|
return spy(super.createPlayQueue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public PlayerDaoPlayQueueFactory playerDaoPlayQueueFactory() {
|
||||||
|
return new SpiedPlayerDaoPlayQueueFactory();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static final String CLIENT_NAME = "airsonic";
|
||||||
|
protected static final String JUKEBOX_PLAYER_NAME = CLIENT_NAME + "-jukebox";
|
||||||
|
private static final String EXPECTED_FORMAT = "json";
|
||||||
|
private static String AIRSONIC_API_VERSION;
|
||||||
|
|
||||||
|
private static boolean dataBasePopulated;
|
||||||
|
private static DaoHelper staticDaoHelper;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
protected PlayerService playerService;
|
||||||
|
@Autowired
|
||||||
|
private MockMvc mvc;
|
||||||
|
@Autowired
|
||||||
|
private MusicFolderDao musicFolderDao;
|
||||||
|
@Autowired
|
||||||
|
private SettingsService settingsService;
|
||||||
|
@Autowired
|
||||||
|
private MediaScannerService mediaScannerService;
|
||||||
|
@Autowired
|
||||||
|
private PlayerDao playerDao;
|
||||||
|
@Autowired
|
||||||
|
private MediaFileDao mediaFileDao;
|
||||||
|
@Autowired
|
||||||
|
private DaoHelper daoHelper;
|
||||||
|
@Autowired
|
||||||
|
private AlbumDao albumDao;
|
||||||
|
@Autowired
|
||||||
|
private ArtistDao artistDao;
|
||||||
|
|
||||||
|
private Player testJukeboxPlayer;
|
||||||
|
|
||||||
|
@BeforeClass
|
||||||
|
public static void setupClass() {
|
||||||
|
AIRSONIC_API_VERSION = TestCaseUtils.restApiVersion();
|
||||||
|
dataBasePopulated = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterClass
|
||||||
|
public static void cleanDataBase() {
|
||||||
|
staticDaoHelper.getJdbcTemplate().execute("DROP SCHEMA PUBLIC CASCADE");
|
||||||
|
staticDaoHelper = null;
|
||||||
|
dataBasePopulated = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Populate test datas in the database only once.
|
||||||
|
*
|
||||||
|
* <ul>
|
||||||
|
* <li>Creates 2 music folder</li>
|
||||||
|
* <li>Scans the music folders</li>
|
||||||
|
* <li>Creates a test jukebox player</li>
|
||||||
|
* </ul>
|
||||||
|
*/
|
||||||
|
private void populateDatabase() {
|
||||||
|
if (!dataBasePopulated) {
|
||||||
|
staticDaoHelper = daoHelper;
|
||||||
|
|
||||||
|
assertThat(musicFolderDao.getAllMusicFolders().size()).isEqualTo(1);
|
||||||
|
MusicFolderTestData.getTestMusicFolders().forEach(musicFolderDao::createMusicFolder);
|
||||||
|
settingsService.clearMusicFolderCache();
|
||||||
|
|
||||||
|
TestCaseUtils.execScan(mediaScannerService);
|
||||||
|
|
||||||
|
assertThat(playerDao.getAllPlayers().size()).isEqualTo(0);
|
||||||
|
createTestPlayer();
|
||||||
|
assertThat(playerDao.getAllPlayers().size()).isEqualTo(1);
|
||||||
|
|
||||||
|
dataBasePopulated = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setup() throws Exception {
|
||||||
|
populateDatabase();
|
||||||
|
|
||||||
|
testJukeboxPlayer = findTestJukeboxPlayer();
|
||||||
|
assertThat(testJukeboxPlayer).isNotNull();
|
||||||
|
reset(testJukeboxPlayer.getPlayQueue());
|
||||||
|
testJukeboxPlayer.getPlayQueue().clear();
|
||||||
|
assertThat(testJukeboxPlayer.getPlayQueue().size()).isEqualTo(0);
|
||||||
|
testJukeboxPlayer.getPlayQueue().addFiles(true,
|
||||||
|
mediaFileDao.getSongsForAlbum("_DIR_ Ravel", "Complete Piano Works"));
|
||||||
|
assertThat(testJukeboxPlayer.getPlayQueue().size()).isEqualTo(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract void createTestPlayer();
|
||||||
|
|
||||||
|
private Player findTestJukeboxPlayer() {
|
||||||
|
return playerDao.getAllPlayers().stream().filter(player -> player.getName().equals(JUKEBOX_PLAYER_NAME))
|
||||||
|
.findFirst().orElseThrow(() -> new RuntimeException("No player found in database"));
|
||||||
|
}
|
||||||
|
|
||||||
|
private String convertDateToString(Date date) {
|
||||||
|
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.000'Z'");
|
||||||
|
formatter.setTimeZone(TimeZone.getTimeZone("UTC"));
|
||||||
|
return formatter.format(date);
|
||||||
|
}
|
||||||
|
|
||||||
|
private ResultMatcher playListItem1isCorrect() {
|
||||||
|
MediaFile mediaFile = testJukeboxPlayer.getPlayQueue().getFile(0);
|
||||||
|
MediaFile parent = mediaFileDao.getMediaFile(mediaFile.getParentPath());
|
||||||
|
Album album = albumDao.getAlbum(mediaFile.getArtist(), mediaFile.getAlbumName());
|
||||||
|
Artist artist = artistDao.getArtist(mediaFile.getArtist());
|
||||||
|
assertThat(album).isNotNull();
|
||||||
|
return result -> {
|
||||||
|
jsonPath("$.subsonic-response.jukeboxPlaylist.entry[0].id").value(mediaFile.getId()).match(result);
|
||||||
|
jsonPath("$.subsonic-response.jukeboxPlaylist.entry[0].parent").value(parent.getId()).match(result);
|
||||||
|
jsonPath("$.subsonic-response.jukeboxPlaylist.entry[0].isDir").value(false).match(result);
|
||||||
|
jsonPath("$.subsonic-response.jukeboxPlaylist.entry[0].title").value("01 - Gaspard de la Nuit - i. Ondine").match(result);
|
||||||
|
jsonPath("$.subsonic-response.jukeboxPlaylist.entry[0].album").value("Complete Piano Works").match(result);
|
||||||
|
jsonPath("$.subsonic-response.jukeboxPlaylist.entry[0].artist").value("_DIR_ Ravel").match(result);
|
||||||
|
jsonPath("$.subsonic-response.jukeboxPlaylist.entry[0].coverArt").value(parent.getId()).match(result);
|
||||||
|
jsonPath("$.subsonic-response.jukeboxPlaylist.entry[0].size").value(45138).match(result);
|
||||||
|
jsonPath("$.subsonic-response.jukeboxPlaylist.entry[0].contentType").value("audio/mpeg").match(result);
|
||||||
|
jsonPath("$.subsonic-response.jukeboxPlaylist.entry[0].suffix").value("mp3").match(result);
|
||||||
|
jsonPath("$.subsonic-response.jukeboxPlaylist.entry[0].duration").value(2).match(result);
|
||||||
|
jsonPath("$.subsonic-response.jukeboxPlaylist.entry[0].bitRate").value(128).match(result);
|
||||||
|
jsonPath("$.subsonic-response.jukeboxPlaylist.entry[0].path").value("_DIR_ Ravel/_DIR_ Ravel - Complete Piano Works/01 - Gaspard de la Nuit - i. Ondine.mp3").match(result);
|
||||||
|
jsonPath("$.subsonic-response.jukeboxPlaylist.entry[0].isVideo").value(false).match(result);
|
||||||
|
jsonPath("$.subsonic-response.jukeboxPlaylist.entry[0].playCount").isNumber().match(result);
|
||||||
|
jsonPath("$.subsonic-response.jukeboxPlaylist.entry[0].created").value(convertDateToString(mediaFile.getCreated())).match(result);
|
||||||
|
jsonPath("$.subsonic-response.jukeboxPlaylist.entry[0].albumId").value(album.getId()).match(result);
|
||||||
|
jsonPath("$.subsonic-response.jukeboxPlaylist.entry[0].artistId").value(artist.getId()).match(result);
|
||||||
|
jsonPath("$.subsonic-response.jukeboxPlaylist.entry[0].type").value("music").match(result);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@WithMockUser(username = "admin")
|
||||||
|
public void jukeboxStartActionTest() throws Exception {
|
||||||
|
// Given
|
||||||
|
|
||||||
|
// When and Then
|
||||||
|
performStartAction();
|
||||||
|
performStatusAction("true");
|
||||||
|
performGetAction()
|
||||||
|
.andExpect(jsonPath("$.subsonic-response.jukeboxPlaylist.currentIndex").value("0"))
|
||||||
|
.andExpect(jsonPath("$.subsonic-response.jukeboxPlaylist.playing").value("true"))
|
||||||
|
.andExpect(jsonPath("$.subsonic-response.jukeboxPlaylist.gain").value("0.75"))
|
||||||
|
.andExpect(jsonPath("$.subsonic-response.jukeboxPlaylist.position").value("0"))
|
||||||
|
.andExpect(jsonPath("$.subsonic-response.jukeboxPlaylist.entry").isArray())
|
||||||
|
.andExpect(jsonPath("$.subsonic-response.jukeboxPlaylist.entry.length()").value(2))
|
||||||
|
.andExpect(playListItem1isCorrect())
|
||||||
|
.andDo(print());
|
||||||
|
|
||||||
|
verify(testJukeboxPlayer.getPlayQueue(), times(2)).setStatus(PlayQueue.Status.PLAYING);
|
||||||
|
assertThat(testJukeboxPlayer.getPlayQueue().getIndex()).isEqualTo(0);
|
||||||
|
assertThat(testJukeboxPlayer.getPlayQueue().getStatus()).isEqualTo(PlayQueue.Status.PLAYING);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@WithMockUser(username = "admin")
|
||||||
|
public void jukeboxStopActionTest() throws Exception {
|
||||||
|
// Given
|
||||||
|
|
||||||
|
// When and Then
|
||||||
|
performStartAction();
|
||||||
|
performStatusAction("true");
|
||||||
|
performStopAction();
|
||||||
|
performStatusAction("false");
|
||||||
|
|
||||||
|
verify(testJukeboxPlayer.getPlayQueue(), times(2)).setStatus(PlayQueue.Status.PLAYING);
|
||||||
|
verify(testJukeboxPlayer.getPlayQueue(), times(1)).setStatus(PlayQueue.Status.STOPPED);
|
||||||
|
assertThat(testJukeboxPlayer.getPlayQueue().getIndex()).isEqualTo(0);
|
||||||
|
assertThat(testJukeboxPlayer.getPlayQueue().getStatus()).isEqualTo(PlayQueue.Status.STOPPED);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void performStatusAction(String expectedPlayingValue) throws Exception {
|
||||||
|
mvc.perform(get("/rest/jukeboxControl.view")
|
||||||
|
.param("v", AIRSONIC_API_VERSION)
|
||||||
|
.param("c", CLIENT_NAME)
|
||||||
|
.param("f", EXPECTED_FORMAT)
|
||||||
|
.param("action", "status")
|
||||||
|
.contentType(MediaType.APPLICATION_JSON))
|
||||||
|
.andExpect(status().isOk())
|
||||||
|
.andExpect(jsonPath("$.subsonic-response.status").value("ok"))
|
||||||
|
.andExpect(jsonPath("$.subsonic-response.jukeboxStatus.currentIndex").value("0"))
|
||||||
|
.andExpect(jsonPath("$.subsonic-response.jukeboxStatus.playing").value(expectedPlayingValue))
|
||||||
|
.andExpect(jsonPath("$.subsonic-response.jukeboxStatus.position").value("0"));
|
||||||
|
}
|
||||||
|
|
||||||
|
private ResultActions performGetAction() throws Exception {
|
||||||
|
return mvc.perform(get("/rest/jukeboxControl.view")
|
||||||
|
.param("v", AIRSONIC_API_VERSION)
|
||||||
|
.param("c", CLIENT_NAME)
|
||||||
|
.param("f", EXPECTED_FORMAT)
|
||||||
|
.param("action", "get")
|
||||||
|
.contentType(MediaType.APPLICATION_JSON))
|
||||||
|
.andExpect(status().isOk())
|
||||||
|
.andExpect(jsonPath("$.subsonic-response.status").value("ok"));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void performStopAction() throws Exception {
|
||||||
|
mvc.perform(get("/rest/jukeboxControl.view")
|
||||||
|
.param("v", AIRSONIC_API_VERSION)
|
||||||
|
.param("c", CLIENT_NAME)
|
||||||
|
.param("f", EXPECTED_FORMAT)
|
||||||
|
.param("action", "stop")
|
||||||
|
.contentType(MediaType.APPLICATION_JSON))
|
||||||
|
.andExpect(status().isOk())
|
||||||
|
.andExpect(jsonPath("$.subsonic-response.status").value("ok"))
|
||||||
|
.andExpect(jsonPath("$.subsonic-response.jukeboxStatus.currentIndex").value("0"))
|
||||||
|
.andExpect(jsonPath("$.subsonic-response.jukeboxStatus.playing").value("false"))
|
||||||
|
.andExpect(jsonPath("$.subsonic-response.jukeboxStatus.position").value("0"));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void performStartAction() throws Exception {
|
||||||
|
mvc.perform(get("/rest/jukeboxControl.view")
|
||||||
|
.param("v", AIRSONIC_API_VERSION)
|
||||||
|
.param("c", CLIENT_NAME)
|
||||||
|
.param("f", EXPECTED_FORMAT)
|
||||||
|
.param("action", "start")
|
||||||
|
.contentType(MediaType.APPLICATION_JSON))
|
||||||
|
.andExpect(status().isOk())
|
||||||
|
.andExpect(jsonPath("$.subsonic-response.status").value("ok"))
|
||||||
|
.andExpect(jsonPath("$.subsonic-response.jukeboxStatus.currentIndex").value("0"))
|
||||||
|
.andExpect(jsonPath("$.subsonic-response.jukeboxStatus.playing").value("true"))
|
||||||
|
.andExpect(jsonPath("$.subsonic-response.jukeboxStatus.position").value("0"));
|
||||||
|
}
|
||||||
|
}
|
||||||
+38
@@ -0,0 +1,38 @@
|
|||||||
|
package org.airsonic.player.api.jukebox;
|
||||||
|
|
||||||
|
import com.github.biconou.AudioPlayer.JavaPlayer;
|
||||||
|
import org.airsonic.player.domain.Player;
|
||||||
|
import org.airsonic.player.domain.PlayerTechnology;
|
||||||
|
import org.airsonic.player.service.jukebox.JavaPlayerFactory;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.springframework.boot.test.mock.mockito.MockBean;
|
||||||
|
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
public class AirsonicRestApiJukeboxIntTest extends AbstractAirsonicRestApiJukeboxIntTest {
|
||||||
|
|
||||||
|
@MockBean
|
||||||
|
protected JavaPlayerFactory javaPlayerFactory;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
@Override
|
||||||
|
public void setup() throws Exception {
|
||||||
|
super.setup();
|
||||||
|
JavaPlayer mockJavaPlayer = mock(JavaPlayer.class);
|
||||||
|
when(mockJavaPlayer.getPlayingInfos()).thenReturn( () -> 0 );
|
||||||
|
when(mockJavaPlayer.getGain()).thenReturn(0.75f);
|
||||||
|
when(javaPlayerFactory.createJavaPlayer()).thenReturn(mockJavaPlayer);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void createTestPlayer() {
|
||||||
|
Player jukeBoxPlayer = new Player();
|
||||||
|
jukeBoxPlayer.setName(JUKEBOX_PLAYER_NAME);
|
||||||
|
jukeBoxPlayer.setUsername("admin");
|
||||||
|
jukeBoxPlayer.setClientId(CLIENT_NAME + "-jukebox");
|
||||||
|
jukeBoxPlayer.setTechnology(PlayerTechnology.JAVA_JUKEBOX);
|
||||||
|
playerService.createPlayer(jukeBoxPlayer);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+62
@@ -0,0 +1,62 @@
|
|||||||
|
package org.airsonic.player.api.jukebox;
|
||||||
|
|
||||||
|
import org.airsonic.player.domain.Player;
|
||||||
|
import org.airsonic.player.domain.PlayerTechnology;
|
||||||
|
import org.airsonic.player.service.TranscodingService;
|
||||||
|
import org.airsonic.player.service.jukebox.AudioPlayer;
|
||||||
|
import org.airsonic.player.service.jukebox.AudioPlayerFactory;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.springframework.boot.test.mock.mockito.MockBean;
|
||||||
|
import org.springframework.boot.test.mock.mockito.SpyBean;
|
||||||
|
import org.springframework.security.test.context.support.WithMockUser;
|
||||||
|
|
||||||
|
import static org.mockito.Matchers.any;
|
||||||
|
import static org.mockito.Mockito.*;
|
||||||
|
|
||||||
|
public class AirsonicRestApiJukeboxLegacyIntTest extends AirsonicRestApiJukeboxIntTest {
|
||||||
|
|
||||||
|
@SpyBean
|
||||||
|
private TranscodingService transcodingService;
|
||||||
|
@MockBean
|
||||||
|
protected AudioPlayerFactory audioPlayerFactory;
|
||||||
|
|
||||||
|
private AudioPlayer mockAudioPlayer;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
@Override
|
||||||
|
public void setup() throws Exception {
|
||||||
|
super.setup();
|
||||||
|
mockAudioPlayer = mock(AudioPlayer.class);
|
||||||
|
when(audioPlayerFactory.createAudioPlayer(any(), any())).thenReturn(mockAudioPlayer);
|
||||||
|
doReturn(null).when(transcodingService).getTranscodedInputStream(any());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected final void createTestPlayer() {
|
||||||
|
Player jukeBoxPlayer = new Player();
|
||||||
|
jukeBoxPlayer.setName(JUKEBOX_PLAYER_NAME);
|
||||||
|
jukeBoxPlayer.setUsername("admin");
|
||||||
|
jukeBoxPlayer.setClientId(CLIENT_NAME + "-jukebox");
|
||||||
|
jukeBoxPlayer.setTechnology(PlayerTechnology.JUKEBOX);
|
||||||
|
playerService.createPlayer(jukeBoxPlayer);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@WithMockUser(username = "admin")
|
||||||
|
@Override
|
||||||
|
public void jukeboxStartActionTest() throws Exception {
|
||||||
|
super.jukeboxStartActionTest();
|
||||||
|
verify(mockAudioPlayer).play();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@WithMockUser(username = "admin")
|
||||||
|
@Override
|
||||||
|
public void jukeboxStopActionTest() throws Exception {
|
||||||
|
super.jukeboxStopActionTest();
|
||||||
|
verify(mockAudioPlayer).play();
|
||||||
|
verify(mockAudioPlayer).pause();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+41
@@ -0,0 +1,41 @@
|
|||||||
|
package org.airsonic.player.service;
|
||||||
|
|
||||||
|
import org.airsonic.player.domain.Transcoding;
|
||||||
|
import org.airsonic.player.util.HomeRule;
|
||||||
|
import org.junit.ClassRule;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
|
import org.springframework.boot.test.mock.mockito.SpyBean;
|
||||||
|
import org.springframework.test.context.junit4.SpringRunner;
|
||||||
|
import static org.mockito.Mockito.*;
|
||||||
|
|
||||||
|
@RunWith(SpringRunner.class)
|
||||||
|
@SpringBootTest
|
||||||
|
public class TranscodingServiceIntTest {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private TranscodingService transcodingService;
|
||||||
|
@SpyBean
|
||||||
|
private PlayerService playerService;
|
||||||
|
|
||||||
|
@ClassRule
|
||||||
|
public static final HomeRule classRule = new HomeRule(); // sets airsonic.home to a temporary dir
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void createTranscodingTest() {
|
||||||
|
// Given
|
||||||
|
Transcoding transcoding = new Transcoding(null,
|
||||||
|
"test-transcoding",
|
||||||
|
"mp3",
|
||||||
|
"wav",
|
||||||
|
"step1",
|
||||||
|
"step2",
|
||||||
|
"step3",
|
||||||
|
true);
|
||||||
|
|
||||||
|
transcodingService.createTranscoding(transcoding);
|
||||||
|
verify(playerService).getAllPlayers();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
spring.mvc.view.prefix: /WEB-INF/jsp/
|
||||||
|
spring.mvc.view.suffix: .jsp
|
||||||
|
server.error.includeStacktrace: ALWAYS
|
||||||
|
logging.level.root=WARN
|
||||||
|
logging.level.org.airsonic=INFO
|
||||||
|
logging.level.liquibase=INFO
|
||||||
|
logging.pattern.console=%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(%5p){green} %clr(---){faint} %clr(%-40.40logger{32}){blue} %clr(:){faint} %m%n%wEx
|
||||||
|
logging.pattern.file=%d{yyyy-MM-dd HH:mm:ss.SSS} %5p --- %-40.40logger{32} : %m%n%wEx
|
||||||
|
DatabaseConfigType=embed
|
||||||
|
DatabaseConfigEmbedDriver=org.hsqldb.jdbcDriver
|
||||||
|
DatabaseConfigEmbedUrl=jdbc:hsqldb:mem:airsonic
|
||||||
|
DatabaseConfigEmbedUsername=sa
|
||||||
|
DatabaseConfigEmbedPassword=
|
||||||
@@ -255,6 +255,8 @@
|
|||||||
<ignoredUsedUndeclaredDependency>org.springframework:*</ignoredUsedUndeclaredDependency>
|
<ignoredUsedUndeclaredDependency>org.springframework:*</ignoredUsedUndeclaredDependency>
|
||||||
<ignoredUsedUndeclaredDependency>org.springframework.security:*</ignoredUsedUndeclaredDependency>
|
<ignoredUsedUndeclaredDependency>org.springframework.security:*</ignoredUsedUndeclaredDependency>
|
||||||
<ignoredUsedUndeclaredDependency>org.springframework.boot:*</ignoredUsedUndeclaredDependency>
|
<ignoredUsedUndeclaredDependency>org.springframework.boot:*</ignoredUsedUndeclaredDependency>
|
||||||
|
<ignoredUsedUndeclaredDependency>org.assertj:*</ignoredUsedUndeclaredDependency>
|
||||||
|
<ignoredUsedUndeclaredDependency>org.hamcrest:*</ignoredUsedUndeclaredDependency>
|
||||||
<ignoredUsedUndeclaredDependency>org.apache.tomcat.embed:tomcat-embed-core*</ignoredUsedUndeclaredDependency>
|
<ignoredUsedUndeclaredDependency>org.apache.tomcat.embed:tomcat-embed-core*</ignoredUsedUndeclaredDependency>
|
||||||
<ignoredUsedUndeclaredDependency>org.apache.tomcat:tomcat-annotations-api:*</ignoredUsedUndeclaredDependency>
|
<ignoredUsedUndeclaredDependency>org.apache.tomcat:tomcat-annotations-api:*</ignoredUsedUndeclaredDependency>
|
||||||
</ignoredUsedUndeclaredDependencies>
|
</ignoredUsedUndeclaredDependencies>
|
||||||
|
|||||||
Reference in New Issue
Block a user