diff --git a/src/common/defaultSetting.js b/src/common/defaultSetting.js index 22e08246..f2a463ca 100644 --- a/src/common/defaultSetting.js +++ b/src/common/defaultSetting.js @@ -2,7 +2,7 @@ const path = require('path') const os = require('os') const defaultSetting = { - version: '1.0.39', + version: '1.0.40', player: { togglePlayMethod: 'listLoop', highQuality: false, @@ -11,7 +11,8 @@ const defaultSetting = { isMute: false, mediaDeviceId: 'default', isMediaDeviceRemovedStopPlay: false, - isShowLyricTransition: true, + isShowLyricTransition: false, + isPlayLxlrc: true, isSavePlayTime: false, }, desktopLyric: { diff --git a/src/main/modules/winLyric/event.js b/src/main/modules/winLyric/event.js index 43de0f63..4997dfff 100644 --- a/src/main/modules/winLyric/event.js +++ b/src/main/modules/winLyric/event.js @@ -14,6 +14,7 @@ const setLrcConfig = () => { config: desktopLyric, languageId: global.appSetting.langId, isShowLyricTransition: global.appSetting.player.isShowLyricTransition, + isPlayLxlrc: global.appSetting.player.isPlayLxlrc, }) if (isLock != desktopLyric.isLock) { isLock = desktopLyric.isLock diff --git a/src/main/modules/winLyric/rendererEvent.js b/src/main/modules/winLyric/rendererEvent.js index ce8721a8..091e81f8 100644 --- a/src/main/modules/winLyric/rendererEvent.js +++ b/src/main/modules/winLyric/rendererEvent.js @@ -24,7 +24,12 @@ mainOn(ipcWinLyricNames.set_lyric_config, (event, config) => { }) mainHandle(ipcWinLyricNames.get_lyric_config, async() => { - return { config: global.appSetting.desktopLyric, languageId: global.appSetting.langId, isShowLyricTransition: global.appSetting.player.isShowLyricTransition } + return { + config: global.appSetting.desktopLyric, + languageId: global.appSetting.langId, + isShowLyricTransition: global.appSetting.player.isShowLyricTransition, + isPlayLxlrc: global.appSetting.player.isPlayLxlrc, + } }) mainOn(ipcWinLyricNames.set_win_bounds, (event, options) => { diff --git a/src/renderer-lyric/App.vue b/src/renderer-lyric/App.vue index d77e9c38..0bbc1532 100644 --- a/src/renderer-lyric/App.vue +++ b/src/renderer-lyric/App.vue @@ -4,7 +4,7 @@ transition(enter-active-class="animated-fast fadeIn" leave-active-class="animated-fast fadeOut") .control-bar(v-show="!lrcConfig.isLock") core-control-bar(:lrcConfig="lrcConfig" :themes="themeList") - core-lyric(:lrcConfig="lrcConfig" :isShowLyricTransition="isShowLyricTransition") + core-lyric(:lrcConfig="lrcConfig" :isPlayLxlrc="isPlayLxlrc" :isShowLyricTransition="isShowLyricTransition") div.resize-left(@mousedown.self="handleMouseDown('left', $event)") div.resize-top(@mousedown.self="handleMouseDown('top', $event)") div.resize-right(@mousedown.self="handleMouseDown('right', $event)") @@ -45,6 +45,7 @@ export default { }, }, isShowLyricTransition: true, + isPlayLxlrc: true, themeList: [ { id: 0, @@ -118,9 +119,10 @@ export default { document.removeEventListener('mouseup', this.handleMouseUp) }, methods: { - handleUpdateConfig({ config, languageId, isShowLyricTransition }) { + handleUpdateConfig({ config, languageId, isShowLyricTransition, isPlayLxlrc }) { this.lrcConfig = config this.isShowLyricTransition = isShowLyricTransition + this.isPlayLxlrc = isPlayLxlrc if (this.$i18n.locale !== languageId && languageId != null) this.$i18n.locale = languageId }, handleMouseDown(origin, event) { diff --git a/src/renderer-lyric/components/core/Lyric.vue b/src/renderer-lyric/components/core/Lyric.vue index d3dd6a82..46bb65e7 100644 --- a/src/renderer-lyric/components/core/Lyric.vue +++ b/src/renderer-lyric/components/core/Lyric.vue @@ -28,6 +28,10 @@ export default { } }, }, + isPlayLxlrc: { + type: Boolean, + default: true, + }, isShowLyricTransition: { type: Boolean, default: true, @@ -122,8 +126,11 @@ export default { }, immediate: true, }, - isShowLyricTransition(n) { - console.log(n) + isShowLyricTransition() { + this.setLyric() + rendererSend(NAMES.winLyric.get_lyric_info, 'status') + }, + isPlayLxlrc() { this.setLyric() rendererSend(NAMES.winLyric.get_lyric_info, 'status') }, @@ -226,8 +233,10 @@ export default { cancelScrollFn = scrollTo(this.$refs.dom_lyric, dom_p ? (dom_p.offsetTop - this.$refs.dom_lyric.clientHeight * 0.5 + dom_p.clientHeight / 2) : 0) }, handleLyricMouseDown(e) { - console.log(e.target) - if (e.target.classList.contains('font') || e.target.parentNode.classList.contains('font')) { + if (e.target.classList.contains('font') || + e.target.parentNode.classList.contains('font') || + e.target.classList.contains('translation') || + e.target.parentNode.classList.contains('translation')) { this.lyricEvent.isMsDown = true this.lyricEvent.msDownY = e.clientY this.lyricEvent.msDownScrollY = this.$refs.dom_lyric.scrollTop @@ -296,7 +305,8 @@ export default { }, setLyric() { window.lrc.setLyric( - this.lyrics.lxlyric ? this.lyrics.lxlyric : this.lyrics.lyric, + this.isPlayLxlrc && this.lyrics.lxlyric ? this.lyrics.lxlyric : this.lyrics.lyric, + this.isShowLyricTransition && this.lyrics.tlyric ? this.lyrics.tlyric : '', // (this.isShowLyricTransition && this.lyrics.tlyric ? (this.lyrics.tlyric + '\n') : '') + (this.lyrics.lyric || ''), ) }, @@ -327,6 +337,13 @@ export default { display: inline-block; } + .translation { + transition: @transition-theme !important; + transition-property: font-size, color; + font-size: 0.8em; + margin-top: 5px; + } + .line { transition-property: font-size, color !important; background: none !important; @@ -337,6 +354,10 @@ export default { .line { color: @color-theme; } + .translation { + font-size: 1em; + color: @color-theme; + } span { // color: @color-theme; font-size: 1.2em; diff --git a/src/renderer/components/core/Player.vue b/src/renderer/components/core/Player.vue index af89eee6..842e476c 100644 --- a/src/renderer/components/core/Player.vue +++ b/src/renderer/components/core/Player.vue @@ -275,6 +275,9 @@ export default { 'setting.player.isShowLyricTransition'() { this.setLyric() }, + 'setting.player.isPlayLxlrc'() { + this.setLyric() + }, async list(n, o) { if (n === o && this.musicInfo.songmid) { let index = this.listId == 'download' @@ -856,7 +859,8 @@ export default { }, setLyric() { window.lrc.setLyric( - this.musicInfo.lxlrc ? this.musicInfo.lxlrc : this.musicInfo.lrc, + this.setting.player.isPlayLxlrc && this.musicInfo.lxlrc ? this.musicInfo.lxlrc : this.musicInfo.lrc, + this.setting.player.isShowLyricTransition && this.musicInfo.tlrc ? this.musicInfo.tlrc : '', // ( // this.setting.player.isShowLyricTransition && this.musicInfo.tlrc // ? (this.musicInfo.tlrc + '\n') diff --git a/src/renderer/components/core/PlayerDetail.vue b/src/renderer/components/core/PlayerDetail.vue index 04f35a53..08f1e136 100644 --- a/src/renderer/components/core/PlayerDetail.vue +++ b/src/renderer/components/core/PlayerDetail.vue @@ -589,6 +589,12 @@ export default { margin: 16px 0; overflow-wrap: break-word; + .translation { + transition: @transition-theme !important; + transition-property: font-size, color; + font-size: 1em; + margin-top: 5px; + } .line { transition-property: font-size, color !important; background: none !important; @@ -599,6 +605,10 @@ export default { .line { color: @color-theme; } + .translation { + font-size: 1.2em; + color: @color-theme; + } span { // color: @color-theme; font-size: 1.2em; diff --git a/src/renderer/lang/en-us/view/setting.json b/src/renderer/lang/en-us/view/setting.json index 468256e0..8609af7c 100644 --- a/src/renderer/lang/en-us/view/setting.json +++ b/src/renderer/lang/en-us/view/setting.json @@ -30,6 +30,7 @@ "play": "Play", "play_save_play_time": "Remember playback progress", "play_lyric_transition": "Show lyrics translation", + "play_lyric_lxlrc": "Use Karaoke-style lyrics playback (if supported)", "play_quality": "Play 320K quality songs first (if supported)", "play_task_bar": "Show playing progress on the taskbar", "play_mediaDevice_title": "Select a media device for audio output", diff --git a/src/renderer/lang/zh-cn/view/setting.json b/src/renderer/lang/zh-cn/view/setting.json index 5ea41c74..84c06b8f 100644 --- a/src/renderer/lang/zh-cn/view/setting.json +++ b/src/renderer/lang/zh-cn/view/setting.json @@ -30,6 +30,7 @@ "play": "播放设置", "play_save_play_time": "记住播放进度", "play_lyric_transition": "显示歌词翻译", + "play_lyric_lxlrc": "使用卡拉OK式歌词播放(如果支持)", "play_quality": "优先播放320K品质的歌曲(如果支持)", "play_task_bar": "在任务栏上显示当前歌曲播放进度", "play_mediaDevice_title": "选择声音输出的媒体设备", diff --git a/src/renderer/lang/zh-tw/view/setting.json b/src/renderer/lang/zh-tw/view/setting.json index f4129d29..f13c823f 100644 --- a/src/renderer/lang/zh-tw/view/setting.json +++ b/src/renderer/lang/zh-tw/view/setting.json @@ -30,6 +30,7 @@ "play": "播放設置", "play_save_play_time": "記住播放進度", "play_lyric_transition": "顯示歌詞翻譯", + "play_lyric_lxlrc": "使用卡拉OK式歌詞播放(如果支持)", "play_quality": "優先播放320K品質的歌曲(如果支持)", "play_task_bar": "在任務欄上顯示當前歌曲播放進度", "play_mediaDevice_title": "選擇聲音輸出的媒體設備", diff --git a/src/renderer/utils/lyric-font-player/font-player.js b/src/renderer/utils/lyric-font-player/font-player.js index 6ca40a97..fbdfbab8 100644 --- a/src/renderer/utils/lyric-font-player/font-player.js +++ b/src/renderer/utils/lyric-font-player/font-player.js @@ -20,11 +20,13 @@ const createAnimation = (dom, duration) => new window.Animation(new window.Keyfr // https://jsfiddle.net/ceqpnbky/1/ module.exports = class FontPlayer { - constructor({ lyric = '', lineClassName = '', fontClassName = '', lineModeClassName = '', shadowContent = false, shadowClassName = '' }) { + constructor({ lyric = '', translationLyric = '', lineClassName = '', fontClassName = '', translationClassName = '', lineModeClassName = '', shadowContent = false, shadowClassName = '' }) { this.lyric = lyric + this.translationLyric = translationLyric this.lineClassName = lineClassName this.fontClassName = fontClassName + this.translationClassName = translationClassName this.lineModeClassName = lineModeClassName this.shadowContent = shadowContent this.shadowClassName = shadowClassName @@ -49,17 +51,33 @@ module.exports = class FontPlayer { this.isLineMode = false this.lineContent = document.createElement('div') - this.lineContent.style = 'position:relative;' if (this.lineClassName) this.lineContent.classList.add(this.lineClassName) this.fontContent = document.createElement('div') + this.fontContent.style = 'position:relative;display:inline-block;' if (this.fontClassName) this.fontContent.classList.add(this.fontClassName) if (this.shadowContent) { this.fontShadowContent = document.createElement('div') this.fontShadowContent.style = 'position:absolute;top:0;left:0;width:100%;z-index:-1;' this.fontShadowContent.className = this.shadowClassName - this.lineContent.appendChild(this.fontShadowContent) + this.fontContent.appendChild(this.fontShadowContent) } this.lineContent.appendChild(this.fontContent) + if (this.translationLyric) { + this.translationContent = document.createElement('div') + this.translationContent.style = 'position:relative;display:inline-block;' + this.translationContent.className = this.translationClassName + this.translationContent.textContent = this.translationLyric + this.lineContent.appendChild(document.createElement('br')) + this.lineContent.appendChild(this.translationContent) + + if (this.shadowContent) { + this.translationShadowContent = document.createElement('div') + this.translationShadowContent.style = 'position:absolute;top:0;left:0;width:100%;z-index:-1;' + this.translationShadowContent.className = this.shadowClassName + this.translationShadowContent.textContent = this.translationLyric + this.translationContent.appendChild(this.translationShadowContent) + } + } this._parseLyric() } diff --git a/src/renderer/utils/lyric-font-player/index.js b/src/renderer/utils/lyric-font-player/index.js index c19e8575..b855e667 100644 --- a/src/renderer/utils/lyric-font-player/index.js +++ b/src/renderer/utils/lyric-font-player/index.js @@ -6,9 +6,11 @@ const fontTimeExp = /<(\d+),(\d+)>/g module.exports = class Lyric { constructor({ lyric = '', + translationLyric = '', offset = 150, lineClassName = '', fontClassName = 'font', + translationClassName = 'translation', activeLineClassName = 'active', lineModeClassName = 'line', shadowClassName = '', @@ -17,12 +19,14 @@ module.exports = class Lyric { onSetLyric = function() { }, }) { this.lyric = lyric + this.translationLyric = translationLyric this.offset = offset this.onPlay = onPlay this.onSetLyric = onSetLyric this.lineClassName = lineClassName this.fontClassName = fontClassName + this.translationClassName = translationClassName this.activeLineClassName = activeLineClassName this.lineModeClassName = lineModeClassName this.shadowClassName = shadowClassName @@ -37,10 +41,11 @@ module.exports = class Lyric { this.isLineMode = false if (this.linePlayer) { - this.linePlayer.setLyric(this.lyric) + this.linePlayer.setLyric(this.lyric, this.translationLyric) } else { this.linePlayer = new LinePlayer({ lyric: this.lyric, + translationLyric: this.translationLyric, offset: this.offset, onPlay: this._handleLinePlayerOnPlay, onSetLyric: this._handleLinePlayerOnSetLyric, @@ -93,6 +98,7 @@ module.exports = class Lyric { } _handleLinePlayerOnSetLyric = lyricLines => { + // console.log(lyricLines) // this._lines = lyricsLines this.isLineMode = lyricLines.length && !/^<\d+,\d+>/.test(lyricLines[0].text) @@ -101,8 +107,10 @@ module.exports = class Lyric { this._lines = lyricLines.map(line => { const fontPlayer = new FontPlayer({ lyric: line.text, + translationLyric: line.translation, lineClassName: this.lineClassName, fontClassName: this.fontClassName, + translationClassName: this.translationClassName, lineModeClassName: this.lineModeClassName, shadowClassName: this.shadowClassName, shadowContent: this.shadowContent, @@ -119,8 +127,10 @@ module.exports = class Lyric { this._lines = lyricLines.map(line => { const fontPlayer = new FontPlayer({ lyric: line.text, + translationLyric: line.translation, lineClassName: this.lineClassName, fontClassName: this.fontClassName, + translationClassName: this.translationClassName, shadowClassName: this.shadowClassName, shadowContent: this.shadowContent, }) @@ -148,8 +158,9 @@ module.exports = class Lyric { if (this.playingLineNum > -1) this._lineFonts[this.playingLineNum].pause() } - setLyric(lyric) { + setLyric(lyric, translationLyric) { this.lyric = lyric + this.translationLyric = translationLyric this._init() } } diff --git a/src/renderer/utils/lyric-font-player/line-player.js b/src/renderer/utils/lyric-font-player/line-player.js index 8655d5b1..eb66d201 100644 --- a/src/renderer/utils/lyric-font-player/line-player.js +++ b/src/renderer/utils/lyric-font-player/line-player.js @@ -12,10 +12,12 @@ const tagRegMap = { const timeoutTools = new TimeoutTools() module.exports = class LinePlayer { - constructor({ lyric = '', offset = 0, onPlay = function() { }, onSetLyric = function() { } } = {}) { + constructor({ lyric = '', translationLyric = '', offset = 0, onPlay = function() { }, onSetLyric = function() { } } = {}) { this.lyric = lyric + this.translationLyric = translationLyric this.tags = {} this.lines = null + this.translationLines = null this.onPlay = onPlay this.onSetLyric = onSetLyric this.isPlay = false @@ -30,6 +32,7 @@ module.exports = class LinePlayer { _init() { if (this.lyric == null) this.lyric = '' + if (this.translationLyric == null) this.translationLyric = '' this._initTag() this._initLines() this.onSetLyric(this.lines) @@ -44,26 +47,45 @@ module.exports = class LinePlayer { _initLines() { this.lines = [] + this.translationLines = [] const lines = this.lyric.split('\n') + const linesMap = {} + // const translationLines = this.translationLyric.split('\n') for (let i = 0; i < lines.length; i++) { const line = lines[i].trim() let result = timeExp.exec(line) if (result) { const text = line.replace(timeExp, '').trim() if (text) { - const timeArr = RegExp.$1.split(':') + const timeStr = RegExp.$1 + const timeArr = timeStr.split(':') if (timeArr.length < 3) timeArr.unshift(0) if (timeArr[2].indexOf('.') > -1) { timeArr.push(...timeArr[2].split('.')) timeArr.splice(2, 1) } - this.lines.push({ + linesMap[timeStr] = { time: parseInt(timeArr[0]) * 60 * 60 * 1000 + parseInt(timeArr[1]) * 60 * 1000 + parseInt(timeArr[2]) * 1000 + parseInt(timeArr[3] || 0), text, - }) + } } } } + + const translationLines = this.translationLyric.split('\n') + for (let i = 0; i < translationLines.length; i++) { + const line = translationLines[i].trim() + let result = timeExp.exec(line) + if (result) { + const text = line.replace(timeExp, '').trim() + if (text) { + const timeStr = RegExp.$1 + const targetLine = linesMap[timeStr] + if (targetLine) targetLine.translation = text + } + } + } + this.lines = Object.values(linesMap) this.lines.sort((a, b) => { return a.time - b.time }) @@ -145,9 +167,11 @@ module.exports = class LinePlayer { } } - setLyric(lyric) { + setLyric(lyric, translationLyric) { + console.log(translationLyric) if (this.isPlay) this.pause() this.lyric = lyric + this.translationLyric = translationLyric this._init() } } diff --git a/src/renderer/views/Setting.vue b/src/renderer/views/Setting.vue index 10ed1d08..92caf033 100644 --- a/src/renderer/views/Setting.vue +++ b/src/renderer/views/Setting.vue @@ -67,6 +67,8 @@ div.scroll(:class="$style.setting" ref="dom_setting") material-checkbox(id="setting_player_save_play_time" v-model="current_setting.player.isSavePlayTime" :label="$t('view.setting.play_save_play_time')") div(:class="$style.gapTop") material-checkbox(id="setting_player_lyric_transition" v-model="current_setting.player.isShowLyricTransition" :label="$t('view.setting.play_lyric_transition')") + div(:class="$style.gapTop") + material-checkbox(id="setting_player_lyric_play_lxlrc" v-model="current_setting.player.isPlayLxlrc" :label="$t('view.setting.play_lyric_lxlrc')") div(:class="$style.gapTop") material-checkbox(id="setting_player_highQuality" v-model="current_setting.player.highQuality" :label="$t('view.setting.play_quality')") div(:class="$style.gapTop") @@ -606,6 +608,9 @@ export default { 'setting.player.togglePlayMethod'(n) { this.current_setting.player.togglePlayMethod = n }, + // 'setting.player.isPlayLxlrc'(n) { + // this.current_setting.player.isPlayLxlrc = n + // }, 'current_setting.player.isShowTaskProgess'(n) { if (n) return this.$nextTick(() => {