diff --git a/libresonic-main/src/main/java/org/libresonic/player/command/PlayerSettingsCommand.java b/libresonic-main/src/main/java/org/libresonic/player/command/PlayerSettingsCommand.java index 6ee0a32d..89260232 100644 --- a/libresonic-main/src/main/java/org/libresonic/player/command/PlayerSettingsCommand.java +++ b/libresonic-main/src/main/java/org/libresonic/player/command/PlayerSettingsCommand.java @@ -41,6 +41,7 @@ public class PlayerSettingsCommand { private Date lastSeen; private boolean isDynamicIp; private boolean isAutoControlEnabled; + private boolean isM3uBomEnabled; private String technologyName; private String transcodeSchemeName; private boolean transcodingSupported; @@ -109,6 +110,14 @@ public class PlayerSettingsCommand { isAutoControlEnabled = autoControlEnabled; } + public boolean isM3uBomEnabled() { + return isM3uBomEnabled; + } + + public void setM3uBomEnabled(boolean m3uBomEnabled) { + isM3uBomEnabled = m3uBomEnabled; + } + public String getTranscodeSchemeName() { return transcodeSchemeName; } diff --git a/libresonic-main/src/main/java/org/libresonic/player/controller/M3UController.java b/libresonic-main/src/main/java/org/libresonic/player/controller/M3UController.java index d41df2ec..e04cd4ad 100644 --- a/libresonic-main/src/main/java/org/libresonic/player/controller/M3UController.java +++ b/libresonic-main/src/main/java/org/libresonic/player/controller/M3UController.java @@ -74,6 +74,9 @@ public class M3UController implements Controller { } private void createClientSidePlaylist(PrintWriter out, Player player, String url) throws Exception { + if (player.isM3uBomEnabled()) { + out.print("\ufeff"); + } out.println("#EXTM3U"); List result; synchronized (player.getPlayQueue()) { @@ -99,6 +102,9 @@ public class M3UController implements Controller { url += "&suffix=." + suffix; } + if (player.isM3uBomEnabled()) { + out.print("\ufeff"); + } out.println("#EXTM3U"); out.println("#EXTINF:-1,Libresonic"); out.println(url); diff --git a/libresonic-main/src/main/java/org/libresonic/player/controller/PlayerSettingsController.java b/libresonic-main/src/main/java/org/libresonic/player/controller/PlayerSettingsController.java index 712aa6f0..2a6d5d28 100644 --- a/libresonic-main/src/main/java/org/libresonic/player/controller/PlayerSettingsController.java +++ b/libresonic-main/src/main/java/org/libresonic/player/controller/PlayerSettingsController.java @@ -72,6 +72,7 @@ public class PlayerSettingsController extends SimpleFormController { command.setLastSeen(player.getLastSeen()); command.setDynamicIp(player.isDynamicIp()); command.setAutoControlEnabled(player.isAutoControlEnabled()); + command.setM3uBomEnabled(player.isM3uBomEnabled()); command.setTranscodeSchemeName(player.getTranscodeScheme().name()); command.setTechnologyName(player.getTechnology().name()); command.setAllTranscodings(transcodingService.getAllTranscodings()); @@ -99,6 +100,7 @@ public class PlayerSettingsController extends SimpleFormController { Player player = playerService.getPlayerById(command.getPlayerId()); player.setAutoControlEnabled(command.isAutoControlEnabled()); + player.setM3uBomEnabled(command.isM3uBomEnabled()); player.setDynamicIp(command.isDynamicIp()); player.setName(StringUtils.trimToNull(command.getName())); player.setTranscodeScheme(TranscodeScheme.valueOf(command.getTranscodeSchemeName())); diff --git a/libresonic-main/src/main/java/org/libresonic/player/dao/HsqlDaoHelper.java b/libresonic-main/src/main/java/org/libresonic/player/dao/HsqlDaoHelper.java index 792a5ef1..43880551 100644 --- a/libresonic-main/src/main/java/org/libresonic/player/dao/HsqlDaoHelper.java +++ b/libresonic-main/src/main/java/org/libresonic/player/dao/HsqlDaoHelper.java @@ -53,6 +53,7 @@ import org.libresonic.player.dao.schema.hsql.Schema51; import org.libresonic.player.dao.schema.hsql.Schema52; import org.libresonic.player.dao.schema.hsql.Schema53; import org.libresonic.player.dao.schema.hsql.Schema61; +import org.libresonic.player.dao.schema.hsql.Schema62; import org.libresonic.player.service.SettingsService; /** @@ -68,7 +69,8 @@ public class HsqlDaoHelper implements DaoHelper { new Schema30(), new Schema31(), new Schema32(), new Schema33(), new Schema34(), new Schema35(), new Schema36(), new Schema37(), new Schema38(), new Schema40(), new Schema43(), new Schema45(), new Schema46(), new Schema47(), new Schema49(), - new Schema50(), new Schema51(), new Schema52(), new Schema53(), new Schema61()}; + new Schema50(), new Schema51(), new Schema52(), new Schema53(), new Schema61(), + new Schema62()}; private DataSource dataSource; private static boolean shutdownHookAdded; diff --git a/libresonic-main/src/main/java/org/libresonic/player/dao/PlayerDao.java b/libresonic-main/src/main/java/org/libresonic/player/dao/PlayerDao.java index be855e61..be484188 100644 --- a/libresonic-main/src/main/java/org/libresonic/player/dao/PlayerDao.java +++ b/libresonic-main/src/main/java/org/libresonic/player/dao/PlayerDao.java @@ -44,7 +44,7 @@ import org.libresonic.player.domain.TranscodeScheme; public class PlayerDao extends AbstractDao { private static final Logger LOG = Logger.getLogger(PlayerDao.class); - private static final String COLUMNS = "id, name, type, username, ip_address, auto_control_enabled, " + + private static final String COLUMNS = "id, name, type, username, ip_address, auto_control_enabled, m3u_bom_enabled, " + "last_seen, cover_art_scheme, transcode_scheme, dynamic_ip, technology, client_id"; private PlayerRowMapper rowMapper = new PlayerRowMapper(); @@ -99,7 +99,7 @@ public class PlayerDao extends AbstractDao { player.setId(String.valueOf(id)); String sql = "insert into player (" + COLUMNS + ") values (" + questionMarks(COLUMNS) + ")"; update(sql, player.getId(), player.getName(), player.getType(), player.getUsername(), - player.getIpAddress(), player.isAutoControlEnabled(), + player.getIpAddress(), player.isAutoControlEnabled(), player.isM3uBomEnabled(), player.getLastSeen(), CoverArtScheme.MEDIUM.name(), player.getTranscodeScheme().name(), player.isDynamicIp(), player.getTechnology().name(), player.getClientId()); @@ -148,6 +148,7 @@ public class PlayerDao extends AbstractDao { "username = ?," + "ip_address = ?," + "auto_control_enabled = ?," + + "m3u_bom_enabled = ?," + "last_seen = ?," + "transcode_scheme = ?, " + "dynamic_ip = ?, " + @@ -155,7 +156,7 @@ public class PlayerDao extends AbstractDao { "client_id = ? " + "where id = ?"; update(sql, player.getName(), player.getType(), player.getUsername(), - player.getIpAddress(), player.isAutoControlEnabled(), + player.getIpAddress(), player.isAutoControlEnabled(), player.isM3uBomEnabled(), player.getLastSeen(), player.getTranscodeScheme().name(), player.isDynamicIp(), player.getTechnology(), player.getClientId(), player.getId()); } @@ -179,6 +180,7 @@ public class PlayerDao extends AbstractDao { player.setUsername(rs.getString(col++)); player.setIpAddress(rs.getString(col++)); player.setAutoControlEnabled(rs.getBoolean(col++)); + player.setM3uBomEnabled(rs.getBoolean(col++)); player.setLastSeen(rs.getTimestamp(col++)); col++; // Ignore cover art scheme. player.setTranscodeScheme(TranscodeScheme.valueOf(rs.getString(col++))); diff --git a/libresonic-main/src/main/java/org/libresonic/player/dao/schema/hsql/Schema62.java b/libresonic-main/src/main/java/org/libresonic/player/dao/schema/hsql/Schema62.java new file mode 100644 index 00000000..0e945944 --- /dev/null +++ b/libresonic-main/src/main/java/org/libresonic/player/dao/schema/hsql/Schema62.java @@ -0,0 +1,48 @@ +/* + * This file is part of Libresonic. + * + * Libresonic is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Libresonic is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Libresonic. If not, see . + */ +package org.libresonic.player.dao.schema.hsql; + +import org.springframework.jdbc.core.JdbcTemplate; + +import org.libresonic.player.Logger; +import org.libresonic.player.dao.schema.Schema; + +/** + * Used for creating and evolving the database schema. + * This class implements the database schema for Libresonic version 6.1. + * + * @author Shen-Ta Hsieh + */ +public class Schema62 extends Schema { + + private static final Logger LOG = Logger.getLogger(Schema62.class); + + @Override + public void execute(JdbcTemplate template) { + + if (template.queryForInt("select count(*) from version where version = 27") == 0) { + LOG.info("Updating database schema to version 27."); + template.execute("insert into version values (27)"); + } + + if (!columnExists(template, "player", "m3u_bom_enabled")) { + LOG.info("Database column 'player.m3u_bom_enabled' not found. Creating it."); + template.execute("alter table player add m3u_bom_enabled boolean default false not null"); + LOG.info("Database column 'player.m3u_bom_enabled' was added successfully."); + } + } +} diff --git a/libresonic-main/src/main/java/org/libresonic/player/domain/Player.java b/libresonic-main/src/main/java/org/libresonic/player/domain/Player.java index 8a14ecdd..9ef3fa38 100644 --- a/libresonic-main/src/main/java/org/libresonic/player/domain/Player.java +++ b/libresonic-main/src/main/java/org/libresonic/player/domain/Player.java @@ -40,6 +40,7 @@ public class Player { private String ipAddress; private boolean isDynamicIp = true; private boolean isAutoControlEnabled = true; + private boolean isM3uBomEnabled = true; private Date lastSeen; private TranscodeScheme transcodeScheme = TranscodeScheme.OFF; private PlayQueue playQueue; @@ -188,6 +189,24 @@ public class Player { this.isAutoControlEnabled = isAutoControlEnabled; } + /** + * Returns whether apply BOM mark when generating a M3U file. + * + * @return Whether apply BOM mark when generating a M3U file. + */ + public boolean isM3uBomEnabled() { + return isM3uBomEnabled; + } + + /** + * Sets whether apply BOM mark when generating a M3U file. + * + * @param isM3uBomEnabled Whether apply BOM mark when generating a M3U file. + */ + public void setM3uBomEnabled(boolean isM3uBomEnabled) { + this.isM3uBomEnabled = isM3uBomEnabled; + } + /** * Returns the time when the player was last seen. * diff --git a/libresonic-main/src/main/resources/org/libresonic/player/i18n/ResourceBundle_en.properties b/libresonic-main/src/main/resources/org/libresonic/player/i18n/ResourceBundle_en.properties index 326aa05b..0d7f87c7 100644 --- a/libresonic-main/src/main/resources/org/libresonic/player/i18n/ResourceBundle_en.properties +++ b/libresonic-main/src/main/resources/org/libresonic/player/i18n/ResourceBundle_en.properties @@ -512,6 +512,7 @@ playersettings.name = Player name playersettings.maxbitrate = Max bitrate playersettings.notranscoder = Notice: Transcoders does not appear to be installed.
Click Help button for more information. playersettings.autocontrol = Control player automatically +playersettings.m3ubom = Apply BOM signature in the generated M3U file playersettings.dynamicip = Player has dynamic IP address playersettings.transcodings = Active transcodings playersettings.ok = Save diff --git a/libresonic-main/src/main/resources/org/libresonic/player/i18n/ResourceBundle_zh_TW.properties b/libresonic-main/src/main/resources/org/libresonic/player/i18n/ResourceBundle_zh_TW.properties index 1eb80892..e3ff6b3a 100644 --- a/libresonic-main/src/main/resources/org/libresonic/player/i18n/ResourceBundle_zh_TW.properties +++ b/libresonic-main/src/main/resources/org/libresonic/player/i18n/ResourceBundle_zh_TW.properties @@ -512,6 +512,7 @@ playersettings.name = \u64A5\u653E\u5668\u540D\u7A31 playersettings.maxbitrate = \u6700\u5927\u50B3\u8F38\u7387 playersettings.notranscoder = \u6CE8\u610F: \u8F49\u78BC\u5F15\u64CE\u5C1A\u672A\u5B89\u88DD\u3002
\u9EDE\u9078\u3010\u8AAA\u660E\u3011\u7372\u5F97\u66F4\u591A\u8CC7\u8A0A\u3002 playersettings.autocontrol = \u81EA\u52D5\u64AD\u653E +playersettings.m3ubom = \u70ba\u7522\u751f\u7684M3U\u6a94\u6848\u589e\u52a0BOM\u6a19\u8a18 playersettings.dynamicip = \u64A5\u653E\u5668\u4F7F\u7528\u52D5\u614BIP\u4F4D\u5740 playersettings.transcodings = \u555F\u52D5\u7684\u8F49\u78BC\u7A0B\u5F0F playersettings.ok = \u5132\u5B58 diff --git a/libresonic-main/src/main/webapp/WEB-INF/jsp/playerSettings.jsp b/libresonic-main/src/main/webapp/WEB-INF/jsp/playerSettings.jsp index fe16ef98..4d16c5f4 100644 --- a/libresonic-main/src/main/webapp/WEB-INF/jsp/playerSettings.jsp +++ b/libresonic-main/src/main/webapp/WEB-INF/jsp/playerSettings.jsp @@ -132,6 +132,14 @@ + + + + + + + +