Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package waylyrics for openSUSE:Factory 
checked in at 2024-02-09 23:53:43
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/waylyrics (Old)
 and      /work/SRC/openSUSE:Factory/.waylyrics.new.1815 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "waylyrics"

Fri Feb  9 23:53:43 2024 rev:3 rq:1145324 version:0.2.1

Changes:
--------
--- /work/SRC/openSUSE:Factory/waylyrics/waylyrics.changes      2024-02-07 
18:53:57.334737554 +0100
+++ /work/SRC/openSUSE:Factory/.waylyrics.new.1815/waylyrics.changes    
2024-02-09 23:54:04.694765549 +0100
@@ -1,0 +2,32 @@
+Fri Feb 09 03:42:14 UTC 2024 - [email protected]
+
+- Update to version 0.2.1:
+  * chore: release 0.2.1
+  * build: improve test build time
+  * test: move out doctest for `get_lrc_path`
+  * test: move unit tests to inside `src/`
+  * refactor: rename `get_lyric` to `parse_lyric` [ci skip]
+  * refactor: setup `QQMusic` with `init()` call
+  * doc(install): download pre-built executables [ci skip]
+  * doc(install): explain build environment variable
+  * ci: run real test in CI
+  * test: test LRC parsing
+  * doc: define `lrc_iter` behaviour
+  * refactor: impl into_owned for LyricLine
+  * test: test netease lyric get & parse
+  * refactor: remove `CONFIG_HOME`
+  * chore: remove unused import
+  * breaking(ui): drop `SIGUSR` control support
+  * refactor: make `init_dirs` a public method so we could write tests
+  * chore: release 0.2.0
+  * style: define `glib-macros` under `gtk`
+  * doc(readme): remove `lx-music` because it's dead [ci skip]
+  * chore(doc): add `musicfox`, a TUI based music player [ci skip]
+  * fix: hint support for musicfox
+  * chore(doc): update doc for youtube-music [ci skip]
+  * chore: drop support for ncm-gtk legacy name
+  * feat: add support for musicfox
+  * chore(doc): update translation [ci skip]
+  * chore(doc): update alternatives [ci skip]
+
+-------------------------------------------------------------------

Old:
----
  waylyrics-0~git486.obscpio

New:
----
  waylyrics-0.2.1.obscpio

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ waylyrics.spec ++++++
--- /var/tmp/diff_new_pack.LCmSuV/_old  2024-02-09 23:54:05.690801441 +0100
+++ /var/tmp/diff_new_pack.LCmSuV/_new  2024-02-09 23:54:05.694801585 +0100
@@ -17,7 +17,7 @@
 
 
 Name:           waylyrics
-Version:        0~git486
+Version:        0.2.1
 Release:        0
 Summary:        The furry way to show desktop lyrics
 License:        MIT

++++++ _service ++++++
--- /var/tmp/diff_new_pack.LCmSuV/_old  2024-02-09 23:54:05.738803171 +0100
+++ /var/tmp/diff_new_pack.LCmSuV/_new  2024-02-09 23:54:05.742803314 +0100
@@ -1,12 +1,12 @@
 <services>
     <service mode="manual" name="obs_scm">
         <param name="url">https://github.com/waylyrics/waylyrics.git</param>
-        <param name="versionformat">0~git@TAG_OFFSET@</param>
+        <param name="versionformat">@PARENT_TAG@</param>
         <param name="scm">git</param>
-        <param name="revision">master</param>
+        <param name="revision">v0.2.1</param>
         <param name="match-tag">*</param>
-        <param 
name="parent-tag">4c93d60a3c95ef2a8a3acc88a9ca11bbd70d2c5a</param>
-        <param name="versionrewrite-pattern">(0~git\d+)</param>
+        <!--<param 
name="parent-tag">4c93d60a3c95ef2a8a3acc88a9ca11bbd70d2c5a</param>-->
+        <param name="versionrewrite-pattern">v(\d+\.\d+\.\d+)</param>
         <param name="versionrewrite-replacement">\1</param>
         <param name="changesgenerate">enable</param>
     </service>
@@ -22,5 +22,4 @@
         <param name="update">true</param>
     </service>
 </services>
-(No newline at EOF)
 

++++++ _servicedata ++++++
--- /var/tmp/diff_new_pack.LCmSuV/_old  2024-02-09 23:54:05.766804180 +0100
+++ /var/tmp/diff_new_pack.LCmSuV/_new  2024-02-09 23:54:05.770804323 +0100
@@ -1,6 +1,6 @@
 <servicedata>
 <service name="tar_scm">
                 <param 
name="url">https://github.com/waylyrics/waylyrics.git</param>
-              <param 
name="changesrevision">d120999caa3a6b15dfcc35bd775b1df06882d20e</param></service></servicedata>
+              <param 
name="changesrevision">31335eb5f6e8ac4ad06ae908a8ec309677efb9d8</param></service></servicedata>
 (No newline at EOF)
 

++++++ vendor.tar.zst ++++++
Binary files /var/tmp/diff_new_pack.LCmSuV/_old and 
/var/tmp/diff_new_pack.LCmSuV/_new differ

++++++ waylyrics-0~git486.obscpio -> waylyrics-0.2.1.obscpio ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/waylyrics-0~git486/.github/workflows/smoketest.yml 
new/waylyrics-0.2.1/.github/workflows/smoketest.yml
--- old/waylyrics-0~git486/.github/workflows/smoketest.yml      2024-02-07 
12:12:22.000000000 +0100
+++ new/waylyrics-0.2.1/.github/workflows/smoketest.yml 1970-01-01 
01:00:00.000000000 +0100
@@ -1,67 +0,0 @@
-name: Smoke test
-
-on:
-  - push
-  - pull_request
-
-env:
-  CARGO_TERM_COLOR: always
-  WAYLYRICS_THEME_PRESETS_DIR: /usr/share/waylyrics/themes
-
-jobs:
-  build:
-
-    runs-on: ubuntu-latest
-
-    steps:
-    - uses: actions/checkout@v3
-    - run: rustup toolchain install nightly --profile minimal
-    - run: rustup default nightly
-    - name: Install deps
-      run: |
-        sudo apt update
-        sudo apt install -y --no-install-recommends libgtk-4-dev libdbus-1-dev 
pkg-config weston
-    - uses: Swatinem/rust-cache@v2
-    - name: Build
-      run: cargo build --release
-    - name: Installation
-      run: |
-        sudo mkdir -p /usr/share/waylyrics
-        sudo install -m644 io.poly000.waylyrics.gschema.xml 
/usr/share/glib-2.0/schemas/
-        sudo install -dm755 /usr/share/waylyrics/themes
-        sudo cp -r themes/* /usr/share/waylyrics/themes/
-
-        # install schema
-        sudo glib-compile-schemas /usr/share/glib-2.0/schemas/
-    - name: Start waylyrics
-      run: |
-        # init weston
-        weston --backend=headless-backend.so -Swayland-1 &
-        # let weston prepare for 1s
-        sleep 1
-        # start waylyrics
-        ret=-1
-        WAYLAND_DISPLAY=wayland-1 RUST_BACKTRACE=1 timeout 5s 
./target/release/waylyrics || ret=$?
-        if [ $ret -eq 124 ]; then
-          echo "waylyrics survived the smoke test"
-          exit 0
-        else
-          echo "waylyrics crashed during the smoke test (exit code $ret)"
-          exit 1
-        fi
-    - name: Prepare assets
-      shell: bash
-      run: |
-        tar -cvzf amd64-linux-gnu.tar.gz target/release/waylyrics \
-        LICENSE res io.poly000.waylyrics.gschema.xml
-        
-    - name: Declare some variables # https://stackoverflow.com/a/61699863
-      id: vars
-      shell: bash
-      run: |
-        echo "sha_short=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT
-
-    - uses: actions/upload-artifact@v3
-      with:
-        name: linux-x86_64
-        path: amd64-linux-gnu.tar.gz
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/waylyrics-0~git486/.github/workflows/test.yml 
new/waylyrics-0.2.1/.github/workflows/test.yml
--- old/waylyrics-0~git486/.github/workflows/test.yml   1970-01-01 
01:00:00.000000000 +0100
+++ new/waylyrics-0.2.1/.github/workflows/test.yml      2024-02-08 
19:25:55.000000000 +0100
@@ -0,0 +1,69 @@
+name: test
+
+on:
+  - push
+  - pull_request
+
+env:
+  CARGO_TERM_COLOR: always
+  WAYLYRICS_THEME_PRESETS_DIR: /usr/share/waylyrics/themes
+
+jobs:
+  build:
+
+    runs-on: ubuntu-latest
+
+    steps:
+    - uses: actions/checkout@v3
+    - run: rustup toolchain install nightly --profile minimal
+    - run: rustup default nightly
+    - name: Install deps
+      run: |
+        sudo apt update
+        sudo apt install -y --no-install-recommends libgtk-4-dev libdbus-1-dev 
pkg-config weston
+    - uses: Swatinem/rust-cache@v2
+    - name: Test
+      run: cargo test
+    - name: Build
+      run: cargo build --release
+    - name: Installation
+      run: |
+        sudo mkdir -p /usr/share/waylyrics
+        sudo install -m644 io.poly000.waylyrics.gschema.xml 
/usr/share/glib-2.0/schemas/
+        sudo install -dm755 ${WAYLYRICS_THEME_PRESETS_DIR}
+        sudo cp -r themes/* ${WAYLYRICS_THEME_PRESETS_DIR}/
+
+        # install schema
+        sudo glib-compile-schemas /usr/share/glib-2.0/schemas/
+    - name: Start waylyrics
+      run: |
+        # init weston
+        weston --backend=headless-backend.so -Swayland-1 &
+        # let weston prepare for 1s
+        sleep 1
+        # start waylyrics
+        ret=-1
+        WAYLAND_DISPLAY=wayland-1 RUST_BACKTRACE=1 timeout 5s 
./target/release/waylyrics || ret=$?
+        if [ $ret -eq 124 ]; then
+          echo "waylyrics survived the smoke test"
+          exit 0
+        else
+          echo "waylyrics crashed during the smoke test (exit code $ret)"
+          exit 1
+        fi
+    - name: Prepare assets
+      shell: bash
+      run: |
+        tar -cvzf amd64-linux-gnu.tar.gz target/release/waylyrics \
+        LICENSE res io.poly000.waylyrics.gschema.xml
+        
+    - name: Declare some variables # https://stackoverflow.com/a/61699863
+      id: vars
+      shell: bash
+      run: |
+        echo "sha_short=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT
+
+    - uses: actions/upload-artifact@v3
+      with:
+        name: linux-x86_64
+        path: amd64-linux-gnu.tar.gz
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/waylyrics-0~git486/Cargo.lock 
new/waylyrics-0.2.1/Cargo.lock
--- old/waylyrics-0~git486/Cargo.lock   2024-02-07 12:12:22.000000000 +0100
+++ new/waylyrics-0.2.1/Cargo.lock      2024-02-08 19:25:55.000000000 +0100
@@ -2664,7 +2664,7 @@
 
 [[package]]
 name = "waylyrics"
-version = "0.1.0"
+version = "0.2.1"
 dependencies = [
  "anyhow",
  "async-trait",
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/waylyrics-0~git486/Cargo.toml 
new/waylyrics-0.2.1/Cargo.toml
--- old/waylyrics-0~git486/Cargo.toml   2024-02-07 12:12:22.000000000 +0100
+++ new/waylyrics-0.2.1/Cargo.toml      2024-02-08 19:25:55.000000000 +0100
@@ -1,16 +1,24 @@
 [package]
 name = "waylyrics"
-version = "0.1.0"
+version = "0.2.1"
 edition = "2021"
 description = "Simple On Screen lyrics Display for linux/unix"
 authors = ["poly000"]
 license-file = "LICENSE"
 
 [profile.release]
-lto = true
+lto = "thin"
 strip = true
 panic = "abort"
 
+[profile.dev]
+panic = "abort"
+
+[profile.test]
+debug = "none"
+incremental = true
+lto = "off"
+
 [dependencies]
 mimalloc = { version = "0.1.39", optional = true, default-features = false }
 
@@ -26,6 +34,7 @@
 
 # ui
 gtk = { version = "0.7.3", package = "gtk4" }
+glib-macros = "0.18.5"
 
 # lyric providers + parse
 ncmapi = { git = "https://github.com/waylyrics/ncmapi-rs.git";, rev = "394e9c2" 
}
@@ -49,7 +58,6 @@
 # error handling
 anyhow = "1.0.79"
 thiserror = "1.0.56"
-glib-macros = "0.18.5"
 
 # networking
 async-trait = "0.1.77"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/waylyrics-0~git486/README.en.md 
new/waylyrics-0.2.1/README.en.md
--- old/waylyrics-0~git486/README.en.md 2024-02-07 12:12:22.000000000 +0100
+++ new/waylyrics-0.2.1/README.en.md    2024-02-08 19:25:55.000000000 +0100
@@ -16,11 +16,12 @@
         - [GTK+](#gtk)
         - [Qt](#qt)
         - [Electron](#electron)
+        - [TUI](#tui)
       - [local](#local)
         - [GTK+](#gtk-1)
         - [Native](#native)
         - [Qt](#qt-1)
-    - [MPRIS-unfriendly Players](#mpris-unfriendly-players)
+    - [Players with bad MPRIS support](#players-with-bad-mpris-support)
   - [Directories](#directories)
   - [Alternatives](#alternatives)
     - [Linux](#linux)
@@ -38,10 +39,6 @@
 
 
https://github.com/waylyrics/waylyrics/blob/d2132b42b135e0de09640de6a5a0b4797871c67e/src/config.rs#L67-L71
 
-SIGUSR1: disconnect from current player
-
-SIGUSR2: switch gtk decoration on/off
-
 ## Requirement
 
 - A player at least supports MPRIS PlaybackStatus, Position and Metadata(with 
title)
@@ -51,8 +48,6 @@
 
 #### online
 
-> For Qcm, Feeluown-{netease, qqmusic}, ElectronNCM, YesPlayMusic(OSD), we 
could get song id directly
-
 ##### GTK+
 
 - [netease-cloud-music-gtk](https://github.com/gmg137/netease-cloud-music-gtk)
@@ -66,10 +61,12 @@
 ##### Electron
 
 - [Electron-NCM](https://github.com/Rocket1184/electron-netease-cloud-music)
-- [lx-music-desktop](https://github.com/lyswhut/lx-music-desktop)
 - [YesPlayMusic](https://github.com/qier222/YesPlayMusic)
-- [youtube-music](https://github.com/th-ch/youtube-music), has lots of songs 
and MV support
+- [youtube-music](https://github.com/th-ch/youtube-music), enable ShortCut 
plugin
 
+##### TUI
+
+- [go-musicfox](https://github.com/go-musicfox/go-musicfox)
 
 #### local
 
@@ -85,9 +82,8 @@
 
 - [VLC](https://www.videolan.org)
 
-### MPRIS-unfriendly Players
+### Players with bad MPRIS support
 
-[netease-cloud-music-gtk]: https://github.com/gmg137/netease-cloud-music-gtk
 [flutter-netease-music]: https://github.com/boyan01/flutter-netease-music
 [youtube-music]: https://github.com/th-ch/youtube-music
 
@@ -111,35 +107,32 @@
 
 ## Alternatives
 
-[YesPlayMusicOSD]: https://github.com/shih-liang/YesPlayMusicOSD
 [waybar-netease-music-lyrics]: 
https://github.com/kangxiaoju/waybar-netease-music-lyrics
-[lx-music-desktop]: https://github.com/lyswhut/lx-music-desktop
 [Sunamu]: https://github.com/NyaomiDEV/Sunamu
 [lyricsSeeker]: https://github.com/BruceZhang1993/LyricsSeeker
 [caraoke-plasmoid]: https://github.com/Copay/caraoke-plasmoid
 [desktop-lyric]: https://github.com/tuberry/desktop-lyric
-[autolyric]: https://www.autolyric.com/
+[AutoLyric]: https://www.autolyric.com/
 [Lyricify]: https://github.com/WXRIW/Lyricify-App
 
 ### Linux
 
-For Sway users, you may want use [waybar-netease-music-lyrics].
-
-[lx-music-desktop] has great lyrics support
+| Name                          | Stack       | DE/WM      | Player Support    
                 | #   |
+| ----------------------------- | ----------- | ---------- | 
---------------------------------- | --- |
+| [waybar-netease-music-lyrics] | bash        | Sway       | Any NetEase Cloud 
Music Player[^0] |     |
+| [Sunamu]                      | Electron/TS | X/Xwayland | MPRIS             
                 |     |
+| [desktop-lyric]               | JavaScript  | GNOME      | MPRIS             
                 |     |
+| [lyricsSeeker]                | Python+QML  | Plasma     |                   
                 | WIP |
+| [caraoke-plasmoid]            | QML         | Plasma     | MPRIS             
                 |     |
 
-[Sunamu] could start web-server/launch electron app depends on your choice, 
and it has good-looking and it's much more feature rich than waylyrics.
-
-BruceZhang1993's [lyricsSeeker] is still WIP, but it may have better-looking 
and better integration with KDE.
-
-Copay's [caraoke-plasmoid] is currently Plasma-only, though it is easy to 
remove plasmoid components
-
-If you are using GNOME I will suggest you [desktop-lyric].
+[^0]: 
https://github.com/kangxiaoju/waybar-netease-music-lyrics/blob/f84810fe1628ca38fa36d88506152d88cf0e77e4/song.sh#L41-L59
 
 ### Windows
 
-[autolyric] supports few of local players
-
-[Lyricify] supports spotify only, while it's Version 3 supports way more 
online players
+| Name        | Stack                | Player Support                          
                                                            | #   |
+| ----------- | -------------------- | 
---------------------------------------------------------------------------------------------------
 | --- |
+| [AutoLyric] | Unknown              | Windows Media 
Player<br>Foobar2000<br>AIMP<br>Winamp                                          
      |     |
+| [Lyricify]  | UWP/C#(4+)<br>C#(3-) | Spotify<br>iTunes<br>Apple 
Music<br>Music Center<br>QQ Music<br>Netease Cloud Music<br>YesPlayMusic |     |
 
 ## Credit
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/waylyrics-0~git486/README.md 
new/waylyrics-0.2.1/README.md
--- old/waylyrics-0~git486/README.md    2024-02-07 12:12:22.000000000 +0100
+++ new/waylyrics-0.2.1/README.md       2024-02-08 19:25:55.000000000 +0100
@@ -16,6 +16,7 @@
         - [GTK+](#gtk)
         - [Qt](#qt)
         - [Electron](#electron)
+        - [TUI](#tui)
       - [本地](#本地)
         - [GTK+](#gtk-1)
         - [原生](#原生)
@@ -38,10 +39,6 @@
 
 
https://github.com/waylyrics/waylyrics/blob/d2132b42b135e0de09640de6a5a0b4797871c67e/src/config.rs#L67-L71
 
-SIGUSR1: 断开当前播放器
-
-SIGUSR2: 开关GTK CSD
-
 ## 依赖
 
 - 播放器需至少在MPRIS提供 
Position,Metadata(有title),PlaybackStatus
@@ -51,8 +48,6 @@
 
 #### 在线
 
-> Qcm, Feeluown-{netease, qqmusic}, ElectronNCM, 
YesPlayMusic(OSD),可以直接拿歌曲id
-
 ##### GTK+
 
 - [netease-cloud-music-gtk](https://github.com/gmg137/netease-cloud-music-gtk)
@@ -66,9 +61,12 @@
 ##### Electron
 
 - [Electron-NCM](https://github.com/Rocket1184/electron-netease-cloud-music)
-- [lx-music-desktop](https://github.com/lyswhut/lx-music-desktop)
 - [YesPlayMusic](https://github.com/qier222/YesPlayMusic)
-- [youtube-music](https://github.com/th-ch/youtube-music), 歌多,有mv
+- [youtube-music](https://github.com/th-ch/youtube-music), 启用 Shortcut 
插件
+
+##### TUI
+
+- [go-musicfox](https://github.com/go-musicfox/go-musicfox)
 
 #### 本地
 
@@ -86,7 +84,6 @@
 
 ### 无法使用的播放器
 
-[netease-cloud-music-gtk]: https://github.com/gmg137/netease-cloud-music-gtk
 [flutter-netease-music]: https://github.com/boyan01/flutter-netease-music
 [youtube-music]: https://github.com/th-ch/youtube-music
 
@@ -111,7 +108,6 @@
 ## 替代品
 
 [waybar-netease-music-lyrics]: 
https://github.com/kangxiaoju/waybar-netease-music-lyrics
-[lx-music-desktop]: https://github.com/lyswhut/lx-music-desktop
 [Sunamu]: https://github.com/NyaomiDEV/Sunamu
 [lyricsSeeker]: https://github.com/BruceZhang1993/LyricsSeeker
 [caraoke-plasmoid]: https://github.com/Copay/caraoke-plasmoid
@@ -121,23 +117,22 @@
 
 ### Linux
 
-Sway用户可以看看 [waybar-netease-music-lyrics].
+| 名称                          | 技术栈      | 桌面支持   | 
播放器支持 | 备注 |
+| ----------------------------- | ----------- | ---------- | ---------- | ---- 
|
+| [waybar-netease-music-lyrics] | bash        | Sway       | NCM[^0]    |      
|
+| [Sunamu]                      | Electron/TS | X/Xwayland | MPRIS      |      
|
+| [desktop-lyric]               | JavaScript  | GNOME      | MPRIS      |      
|
+| [lyricsSeeker]                | Python+QML  | Plasma     |            | WIP  
|
+| [caraoke-plasmoid]            | QML         | Plasma     | MPRIS      |      
|
 
-[lx-music-desktop] 多来源且带有桌面歌词支持
-
-[Sunamu] 
可以启动服务器或电子app,它的歌词显示效果更好,并且比waylyrics的功能更多
-
-如果你是 GNOME 用户,你可以看看 [desktop-lyric]
-
-BruceZhang1993's [lyricsSeeker] is still WIP, but it may have better-looking 
and better integration with KDE.
-
-Copay's [caraoke-plasmoid] is currently Plasma-only, though it is easy to 
remove plasmoid components
+[^0]: 
https://github.com/kangxiaoju/waybar-netease-music-lyrics/blob/f84810fe1628ca38fa36d88506152d88cf0e77e4/song.sh#L41-L59
 
 ### Windows
 
-[可道歌词] 只支持一些本地播放器
-
-[Lyricify] 支持一些在线播放器,4版只支持 Spotify
+| 名称       | 技术栈               | 播放器支持                     
                                                                     | 备注 |
+| ---------- | -------------------- | 
---------------------------------------------------------------------------------------------------
 | ---- |
+| [可道歌词] | Unknown              | Windows Media 
Player<br>Foobar2000<br>AIMP<br>Winamp                                          
      |      |
+| [Lyricify] | UWP/C#(4+)<br>C#(3-) | Spotify<br>iTunes<br>Apple 
Music<br>Music Center<br>QQ Music<br>Netease Cloud Music<br>YesPlayMusic |      
|
 
 ## Credit
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/waylyrics-0~git486/doc/INSTALLATION.en.md 
new/waylyrics-0.2.1/doc/INSTALLATION.en.md
--- old/waylyrics-0~git486/doc/INSTALLATION.en.md       2024-02-07 
12:12:22.000000000 +0100
+++ new/waylyrics-0.2.1/doc/INSTALLATION.en.md  2024-02-08 19:25:55.000000000 
+0100
@@ -1,4 +1,5 @@
 
+- [Download pre-built executable](#download-pre-built-executable)
 - [Install with package manager](#install-with-package-manager)
   - [Arch-based](#arch-based)
   - [openSUSE (Leap \>= 15.5)](#opensuse-leap--155)
@@ -15,6 +16,16 @@
 
 Releases are avaliable in 
[Actions](https://github.com/waylyrics/waylyrics/actions/workflows/smoketest.yml)
 
+# Download pre-built executable
+
+[builds]: https://github.com/waylyrics/waylyrics/actions/workflows/test.yml
+
+We provide builds in [github action][builds].
+
+Note that these build sets `WAYLYRICS_THEME_PRESETS_DIR` as 
`/usr/share/waylyrics/themes`,
+
+You could place themes to `${XDG_DATA_HOME}/_themes/`, waylyrics will try this 
first.
+
 # Install with package manager
 
 ## Arch-based
@@ -59,6 +70,8 @@
 
 # Build
 
+waylyrics will load themes from here, unless they were overridden by 
`${XDG_DATA_HOME}/_themes/<name>.css` 
+
 ```bash
 export WAYLYRICS_THEME_PRESETS_DIR=/usr/share/waylyrics/themes
 ```
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/waylyrics-0~git486/doc/INSTALLATION.md 
new/waylyrics-0.2.1/doc/INSTALLATION.md
--- old/waylyrics-0~git486/doc/INSTALLATION.md  2024-02-07 12:12:22.000000000 
+0100
+++ new/waylyrics-0.2.1/doc/INSTALLATION.md     2024-02-08 19:25:55.000000000 
+0100
@@ -1,4 +1,5 @@
 
+- [下载预编译二进制](#下载预编译二进制)
 - [通过包管理器安装](#通过包管理器安装)
   - [Arch-based](#arch-based)
   - [openSUSE (Leap \>= 15.5)](#opensuse-leap--155)
@@ -15,6 +16,16 @@
 
 可以在 
[Actions](https://github.com/waylyrics/waylyrics/actions/workflows/smoketest.yml)
 下载发布
 
+# 下载预编译二进制
+
+[builds]: https://github.com/waylyrics/waylyrics/actions/workflows/test.yml
+
+我们在 [github action][builds] 提供下载。
+
+这些构建将 `WAYLYRICS_THEME_PRESETS_DIR` 设置为 
`/usr/share/waylyrics/themes`,
+
+你可以把主题放在 `${XDG_DATA_HOME}/_themes/`,waylyrics 会å…
ˆå°è¯•从这里加载。
+
 # 通过包管理器安装
 
 ## Arch-based
@@ -59,6 +70,8 @@
 
 # 编译
 
+waylyrics 会从该位置加载主题,除非被 
`${XDG_DATA_HOME}/_themes/<name>.css` 覆盖
+
 ```bash
 export WAYLYRICS_THEME_PRESETS_DIR=/usr/share/waylyrics/themes
 ```
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/waylyrics-0~git486/src/lib.rs 
new/waylyrics-0.2.1/src/lib.rs
--- old/waylyrics-0~git486/src/lib.rs   2024-02-07 12:12:22.000000000 +0100
+++ new/waylyrics-0.2.1/src/lib.rs      2024-02-08 19:25:55.000000000 +0100
@@ -7,7 +7,6 @@
 use app::Window;
 use gtk::glib::once_cell::sync::Lazy;
 use lyric_providers::LyricProvider;
-use qqmusic_rs::QQMusicApi;
 use regex::RegexSet;
 
 pub mod app;
@@ -26,10 +25,7 @@
     pub static MAIN_WINDOW: RefCell<Option<Window>> = const { 
RefCell::new(None) };
 }
 
-pub static CONFIG_HOME: OnceLock<String> = OnceLock::new();
-
 pub static LYRIC_PROVIDERS: OnceLock<Vec<Arc<dyn LyricProvider>>> = 
OnceLock::new();
-pub static QQMUSIC_API_CLIENT: OnceLock<Option<QQMusicApi>> = OnceLock::new();
 
 pub const DEFAULT_TEXT: &str = "Waylyrics";
 
@@ -50,3 +46,6 @@
         $crate::TOKIO_RUNTIME.spawn($future)
     };
 }
+
+#[cfg(test)]
+mod tests;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/waylyrics-0~git486/src/lyric_providers/mod.rs 
new/waylyrics-0.2.1/src/lyric_providers/mod.rs
--- old/waylyrics-0~git486/src/lyric_providers/mod.rs   2024-02-07 
12:12:22.000000000 +0100
+++ new/waylyrics-0.2.1/src/lyric_providers/mod.rs      2024-02-08 
19:25:55.000000000 +0100
@@ -56,11 +56,12 @@
     ) -> Result<Vec<SongInfo>>;
     async fn search_song(&self, keyword: &str) -> Result<Vec<SongInfo>>;
     fn unique_name(&self) -> &'static str;
+    fn init(self, config: &str) -> Result<()>;
 }
 
 pub trait LyricParse {
-    fn get_lyric(&self, store: &LyricStore) -> LyricOwned;
-    fn get_translated_lyric(&self, store: &LyricStore) -> LyricOwned;
+    fn parse_lyric(&self, store: &LyricStore) -> LyricOwned;
+    fn parse_translated_lyric(&self, store: &LyricStore) -> LyricOwned;
 }
 
 pub fn provider_fmt(
@@ -75,22 +76,24 @@
         match self {
             Lyric::None => LyricOwned::None,
             Lyric::NoTimestamp => LyricOwned::NoTimestamp,
-            Lyric::LineTimestamp(line) => LyricOwned::LineTimestamp(
-                line.into_iter()
-                    .map(
-                        |LyricLine {
-                             text,
-                             start_time: time,
-                         }| LyricLineOwned {
-                            text: text.into(),
-                            start_time: time,
-                        },
-                    )
+            Lyric::LineTimestamp(lyrics) => LyricOwned::LineTimestamp(
+                lyrics
+                    .into_iter()
+                    .map(|l| LyricLine::<'_>::into_owned(l))
                     .collect(),
             ),
         }
     }
 }
+
+impl<'a> LyricLine<'a> {
+    pub fn into_owned(Self { text, start_time }: Self) -> LyricLineOwned {
+        LyricLineOwned {
+            text: text.into(),
+            start_time,
+        }
+    }
+}
 
 pub struct LyricStore {
     lyric: Option<String>,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/waylyrics-0~git486/src/lyric_providers/netease/mod.rs 
new/waylyrics-0.2.1/src/lyric_providers/netease/mod.rs
--- old/waylyrics-0~git486/src/lyric_providers/netease/mod.rs   2024-02-07 
12:12:22.000000000 +0100
+++ new/waylyrics-0.2.1/src/lyric_providers/netease/mod.rs      2024-02-08 
19:25:55.000000000 +0100
@@ -17,9 +17,14 @@
 
 #[async_trait::async_trait]
 impl super::LyricProvider for Netease {
+    fn init(self, _config: &str) -> Result<()> {
+        Ok(())
+    }
+
     fn unique_name(&self) -> &'static str {
         "网易云音乐"
     }
+
     async fn search_song_detailed(
         &self,
         album: &str,
@@ -33,12 +38,7 @@
     async fn query_lyric(&self, id: &str) -> Result<LyricStore> {
         let id = id.to_owned();
         tokio_spawn!(async move {
-            let cookie_path = crate::CONFIG_HOME
-                .get()
-                .expect("should set CONFIG_HOME")
-                .to_owned()
-                + "ncm-cookie";
-            let api = NcmApi::new(true, &cookie_path);
+            let api = NcmApi::new(false, "");
             let id = id.parse()?;
             let query_result = api.lyric(id).await?;
 
@@ -59,12 +59,7 @@
         tokio_spawn!(async move {
             crate::log::debug!("search keyword: {keyword}");
 
-            let cookie_path = crate::CONFIG_HOME
-                .get()
-                .expect("should set CONFIG_HOME")
-                .to_owned()
-                + "ncm-cookie";
-            let api = NcmApi::new(true, &cookie_path);
+            let api = NcmApi::new(false, "");
             let search_result = api.search(&keyword, None).await?;
             let resp: SearchSongResp = search_result.deserialize()?;
             crate::log::debug!("search result: {resp:?}");
@@ -106,12 +101,12 @@
 }
 
 impl super::LyricParse for Netease {
-    fn get_lyric(&self, store: &LyricStore) -> LyricOwned {
+    fn parse_lyric(&self, store: &LyricStore) -> LyricOwned {
         let lyric = store.lyric.as_deref();
         match_lyric(lyric).into_owned()
     }
 
-    fn get_translated_lyric(&self, store: &LyricStore) -> LyricOwned {
+    fn parse_translated_lyric(&self, store: &LyricStore) -> LyricOwned {
         let lyric = store.tlyric.as_deref();
         match_lyric(lyric).into_owned()
     }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/waylyrics-0~git486/src/lyric_providers/qqmusic/mod.rs 
new/waylyrics-0.2.1/src/lyric_providers/qqmusic/mod.rs
--- old/waylyrics-0~git486/src/lyric_providers/qqmusic/mod.rs   2024-02-07 
12:12:22.000000000 +0100
+++ new/waylyrics-0.2.1/src/lyric_providers/qqmusic/mod.rs      2024-02-08 
19:25:55.000000000 +0100
@@ -1,4 +1,4 @@
-use std::time::Duration;
+use std::{sync::OnceLock, time::Duration};
 
 use anyhow::Result;
 use qqmusic_rs::{
@@ -8,10 +8,11 @@
     QQMusicApi, SongId,
 };
 use reqwest::Client;
+use url::Url;
 
 use crate::{
     lyric_providers::{default_search_query, SongInfo},
-    tokio_spawn, QQMUSIC_API_CLIENT,
+    tokio_spawn,
 };
 
 use super::{Lyric, LyricOwned, LyricStore};
@@ -21,6 +22,14 @@
 
 #[async_trait::async_trait]
 impl super::LyricProvider for QQMusic {
+    fn init(self, base_url: &str) -> Result<()> {
+        let base_url: Url = base_url.parse()?;
+        QQMUSIC_API_CLIENT
+            .set(Some(QQMusicApi::new(base_url)))
+            .expect_err("QQMusicApi could only be init once");
+        Ok(())
+    }
+
     fn unique_name(&self) -> &'static str {
         "QQ音乐"
     }
@@ -124,12 +133,12 @@
 }
 
 impl super::LyricParse for QQMusic {
-    fn get_lyric(&self, store: &LyricStore) -> LyricOwned {
+    fn parse_lyric(&self, store: &LyricStore) -> LyricOwned {
         let lyric = store.lyric.as_deref();
         verify_lyric(lyric)
     }
 
-    fn get_translated_lyric(&self, store: &LyricStore) -> LyricOwned {
+    fn parse_translated_lyric(&self, store: &LyricStore) -> LyricOwned {
         let lyric = store.tlyric.as_deref();
         verify_lyric(lyric)
     }
@@ -162,3 +171,5 @@
     #[error("Not implemented")]
     NotImplemented,
 }
+
+pub static QQMUSIC_API_CLIENT: OnceLock<Option<QQMusicApi>> = OnceLock::new();
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/waylyrics-0~git486/src/lyric_providers/utils.rs 
new/waylyrics-0.2.1/src/lyric_providers/utils.rs
--- old/waylyrics-0~git486/src/lyric_providers/utils.rs 2024-02-07 
12:12:22.000000000 +0100
+++ new/waylyrics-0.2.1/src/lyric_providers/utils.rs    2024-02-08 
19:25:55.000000000 +0100
@@ -3,6 +3,11 @@
 
 use super::{LyricLine, LyricLineOwned, LyricProvider};
 
+/// parses lrc tags in each line
+/// ignores lines not started with '['
+/// returned `Vec` is sorted by it's Duration
+/// In the case multiple lyrics comes with the same start_time,
+/// they are not reordered between them
 pub fn lrc_iter<'a>(
     lyric_lines: impl Iterator<Item = &'a str>,
 ) -> Result<Vec<LyricLine<'a>>, LrcParseError> {
@@ -12,7 +17,7 @@
         .filter_map(|lrc_item| match lrc_item {
             lrc_nom::LrcItem::Metadata(_) => None,
             lrc_nom::LrcItem::Lyric(lyric, timestamp) => Some(LyricLine {
-                text: lyric,
+                text: lyric.trim(),
                 start_time: Duration::from_millis(timestamp as _),
             }),
         })
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/waylyrics-0~git486/src/main.rs 
new/waylyrics-0.2.1/src/main.rs
--- old/waylyrics-0~git486/src/main.rs  2024-02-07 12:12:22.000000000 +0100
+++ new/waylyrics-0.2.1/src/main.rs     2024-02-08 19:25:55.000000000 +0100
@@ -1,19 +1,18 @@
 use std::path::PathBuf;
-use std::str::FromStr;
 
 use gtk::prelude::*;
 use gtk::{glib, Application};
 
 use anyhow::Result;
 
-use qqmusic_rs::QQMusicApi;
 use regex::RegexSet;
 use waylyrics::app::{self, build_main_window};
 use waylyrics::config::{Config, Triggers};
+use waylyrics::lyric_providers::qqmusic::QQMusic;
 use waylyrics::lyric_providers::utils::get_provider;
-use waylyrics::{
-    utils, EXCLUDED_REGEXES, LYRIC_PROVIDERS, MAIN_WINDOW, QQMUSIC_API_CLIENT, 
THEME_PATH,
-};
+use waylyrics::lyric_providers::LyricProvider;
+use waylyrics::utils::init_dirs;
+use waylyrics::{utils, EXCLUDED_REGEXES, LYRIC_PROVIDERS, MAIN_WINDOW, 
THEME_PATH};
 
 use waylyrics::log;
 use waylyrics::sync::*;
@@ -26,7 +25,7 @@
 
 use utils::{
     register_action_reload_theme, register_action_switch_decoration,
-    register_action_switch_passthrough, register_sigusr2_decoration,
+    register_action_switch_passthrough,
 };
 
 fn main() -> Result<glib::ExitCode> {
@@ -115,8 +114,7 @@
     }
 
     if let Some(base_url) = qqmusic_api_base_url {
-        let base_url = url::Url::from_str(&base_url)?;
-        let _ = QQMUSIC_API_CLIENT.set(Some(QQMusicApi::new(base_url)));
+        QQMusic.init(&base_url)?;
     }
 
     setup_providers(lyric_search_source);
@@ -145,9 +143,6 @@
     register_action_search_lyric(app, wind, &search_lyric);
     register_action_remove_lyric(app, wind);
     register_action_refetch_lyric(app, wind, &refetch_lyric);
-
-    register_sigusr1_disconnect();
-    register_sigusr2_decoration(ObjectExt::downgrade(app));
 }
 
 fn setup_providers(providers_enabled: Vec<String>) {
@@ -160,38 +155,6 @@
     let _ = LYRIC_PROVIDERS.set(providers);
 }
 
-fn init_dirs() -> Result<(PathBuf, PathBuf)> {
-    let xdg_dirs = xdg::BaseDirectories::with_prefix("waylyrics")?;
-    let config_home = xdg_dirs.get_config_home();
-    let cache_dir = xdg_dirs.get_cache_home();
-    let _ = waylyrics::CONFIG_HOME.set(
-        config_home
-            .to_str()
-            .expect("xdg config home is not valid UTF-8")
-            .into(),
-    );
-    waylyrics::CACHE_DIR.set(
-        cache_dir
-            .to_str()
-            .expect("xdg config home is not valid UTF-8")
-            .into(),
-    );
-
-    std::fs::create_dir_all(&config_home)?;
-    std::fs::create_dir_all(&cache_dir)?;
-    let config_path = config_home.join("config.toml");
-    let user_theme_dir = xdg_dirs.get_data_home().join("_themes");
-
-    if !config_path.exists() {
-        std::fs::write(&config_path, toml::to_string(&Config::default())?)?;
-    }
-    if !user_theme_dir.exists() {
-        std::fs::create_dir_all(&user_theme_dir)?;
-    }
-
-    Ok((config_path, user_theme_dir))
-}
-
 #[cfg(feature = "mimalloc")]
 mod _alloc {
     use mimalloc::MiMalloc;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/waylyrics-0~git486/src/sync/acts/mod.rs 
new/waylyrics-0.2.1/src/sync/acts/mod.rs
--- old/waylyrics-0~git486/src/sync/acts/mod.rs 2024-02-07 12:12:22.000000000 
+0100
+++ new/waylyrics-0.2.1/src/sync/acts/mod.rs    2024-02-08 19:25:55.000000000 
+0100
@@ -34,13 +34,6 @@
     app.add_action(&action);
 }
 
-pub fn register_sigusr1_disconnect() {
-    glib::unix_signal_add_local(libc::SIGUSR1, move || {
-        clean_player();
-        glib::ControlFlow::Continue
-    });
-}
-
 // TODO: code cleanup
 pub fn register_action_search_lyric(app: &Application, wind: &app::Window, 
trigger: &str) {
     let action = SimpleAction::new("search-lyric", None);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/waylyrics-0~git486/src/sync/interop/mpris/hint.rs 
new/waylyrics-0.2.1/src/sync/interop/mpris/hint.rs
--- old/waylyrics-0~git486/src/sync/interop/mpris/hint.rs       2024-02-07 
12:12:22.000000000 +0100
+++ new/waylyrics-0.2.1/src/sync/interop/mpris/hint.rs  2024-02-08 
19:25:55.000000000 +0100
@@ -15,14 +15,10 @@
             .as_ref()
             .expect("player not exists in lyric fetching");
         let player_name = player.identity();
-        let player_bus_name = player
-            .bus_name()
-            .strip_prefix("org.mpris.MediaPlayer2.")
-            .unwrap();
+        let player_bus_name = player.bus_name_player_name_part();
 
         match (player_name, player_bus_name) {
-            ("ElectronNCM" | "Qcm", _)
-            | (_, "com.gitee.gmg137.NeteaseCloudMusicGtk4" | 
"NeteaseCloudMusicGtk4") => {
+            ("ElectronNCM" | "Qcm", _) | (_, "musicfox" | 
"NeteaseCloudMusicGtk4") => {
                 get_field_from_player(player, |meta| {
                     meta.get("mpris:trackid")
                         .and_then(mpris::MetadataValue::as_str)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/waylyrics-0~git486/src/sync/lyric/fetch/tricks.rs 
new/waylyrics-0.2.1/src/sync/lyric/fetch/tricks.rs
--- old/waylyrics-0~git486/src/sync/lyric/fetch/tricks.rs       2024-02-07 
12:12:22.000000000 +0100
+++ new/waylyrics-0.2.1/src/sync/lyric/fetch/tricks.rs  2024-02-08 
19:25:55.000000000 +0100
@@ -51,8 +51,8 @@
             crate::log::debug!("spawned query from get_accurate_lyric");
 
             let lyric = provider.query_lyric(&song_id).await.ok()?;
-            let olyric = provider.get_lyric(&lyric);
-            let tlyric = provider.get_translated_lyric(&lyric);
+            let olyric = provider.parse_lyric(&lyric);
+            let tlyric = provider.parse_translated_lyric(&lyric);
 
             Some(LyricHintResult::Lyric { olyric, tlyric })
         }
@@ -80,30 +80,6 @@
 ///
 /// `music_path` should be valid file if it's not empty
 ///
-/// ```rust
-/// use std::path::PathBuf;
-/// use waylyrics::sync::lyric::fetch::tricks::get_lrc_path as get_lyric_path;
-///
-/// // do not assert file extension length > 3
-/// assert_eq!(get_lyric_path(PathBuf::from("/xxx/yyy/test.ts")),
-///             Some(PathBuf::from("/xxx/yyy/test.lrc")));
-///
-/// // neither = 3
-/// assert_eq!(get_lyric_path(PathBuf::from("xxx/yyy/test.m3u8")),
-///             Some(PathBuf::from("xxx/yyy/test.lrc")));
-///
-/// // relative path
-/// assert_eq!(get_lyric_path(PathBuf::from("../test.m3u8")),
-///             Some(PathBuf::from("../test.lrc")));
-///
-/// // non-ASCII path
-/// assert_eq!(get_lyric_path(PathBuf::from("/测试/试试/你
好.诶木皮散")),
-///             Some(PathBuf::from("/测试/试试/你好.lrc")));
-///
-/// // empty string
-/// assert_eq!(get_lyric_path(PathBuf::from("")),
-///             None);
-/// ```
 pub fn get_lrc_path(music_path: PathBuf) -> Option<PathBuf> {
     let file_name = music_path.iter().last()?.as_encoded_bytes();
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/waylyrics-0~git486/src/sync/lyric/fetch.rs 
new/waylyrics-0.2.1/src/sync/lyric/fetch.rs
--- old/waylyrics-0~git486/src/sync/lyric/fetch.rs      2024-02-07 
12:12:22.000000000 +0100
+++ new/waylyrics-0.2.1/src/sync/lyric/fetch.rs 2024-02-08 19:25:55.000000000 
+0100
@@ -102,8 +102,8 @@
         let provider = &providers[platform_idx];
         match provider.query_lyric(&song_id).await {
             Ok(lyric) => {
-                let olyric = provider.get_lyric(&lyric);
-                let tlyric = provider.get_translated_lyric(&lyric);
+                let olyric = provider.parse_lyric(&lyric);
+                let tlyric = provider.parse_translated_lyric(&lyric);
 
                 info!(
                     "fetched {song_id} from {} with weight {weight}",
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/waylyrics-0~git486/src/sync/mod.rs 
new/waylyrics-0.2.1/src/sync/mod.rs
--- old/waylyrics-0~git486/src/sync/mod.rs      2024-02-07 12:12:22.000000000 
+0100
+++ new/waylyrics-0.2.1/src/sync/mod.rs 2024-02-08 19:25:55.000000000 +0100
@@ -45,7 +45,7 @@
 mod acts;
 pub use acts::{
     register_action_connect, register_action_disconnect, 
register_action_refetch_lyric,
-    register_action_remove_lyric, register_action_search_lyric, 
register_sigusr1_disconnect,
+    register_action_remove_lyric, register_action_search_lyric,
 };
 
 pub use interop::register_sync_task;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/waylyrics-0~git486/src/sync/search_window/mod.rs 
new/waylyrics-0.2.1/src/sync/search_window/mod.rs
--- old/waylyrics-0~git486/src/sync/search_window/mod.rs        2024-02-07 
12:12:22.000000000 +0100
+++ new/waylyrics-0.2.1/src/sync/search_window/mod.rs   2024-02-08 
19:25:55.000000000 +0100
@@ -247,8 +247,8 @@
                     let song_id = result.id();
                     match provider.query_lyric(&song_id).await {
                         Ok(lyric) => {
-                            let origin = provider.get_lyric(&lyric);
-                            let translation = 
provider.get_translated_lyric(&lyric);
+                            let origin = provider.parse_lyric(&lyric);
+                            let translation = 
provider.parse_translated_lyric(&lyric);
                             LYRIC.set(LyricState{ origin, translation });
 
                             if window.imp().use_cache.get() {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/waylyrics-0~git486/src/tests/lyric_parse.rs 
new/waylyrics-0.2.1/src/tests/lyric_parse.rs
--- old/waylyrics-0~git486/src/tests/lyric_parse.rs     1970-01-01 
01:00:00.000000000 +0100
+++ new/waylyrics-0.2.1/src/tests/lyric_parse.rs        2024-02-08 
19:25:55.000000000 +0100
@@ -0,0 +1,157 @@
+#[cfg(test)]
+mod lrc {
+    use std::time::Duration;
+
+    use crate::lyric_providers::{utils::lrc_iter, LyricLine, LyricLineOwned};
+    use anyhow::Result;
+
+    #[test]
+    fn simple_lrc_sorted_with_time() -> Result<()> {
+        let lrc = r#"
+[00:01.05] Hi friend...
+[45:05.64] Can you hear me?...
+"#;
+        let mut lyrics = lrc_iter(lrc.lines())?.into_iter();
+
+        assert_eq!(
+            lyrics.next().map(|l| LyricLine::<'_>::into_owned(l)),
+            Some(LyricLineOwned {
+                text: "Hi friend...".into(),
+                start_time: Duration::from_millis(1000 + 50),
+            })
+        );
+        assert_eq!(
+            lyrics.next().map(|l| LyricLine::<'_>::into_owned(l)),
+            Some(LyricLineOwned {
+                text: "Can you hear me?...".into(),
+                start_time: Duration::from_millis(640 + (45 * 60 + 5) * 1000),
+            })
+        );
+
+        Ok(())
+    }
+
+    #[test]
+    fn simple_lrc_unsorted() -> Result<()> {
+        let lrc = r#"
+[45:05.64] Can you hear me?...
+[00:01.05] Hi friend...
+"#;
+        let mut lyrics = lrc_iter(lrc.lines())?.into_iter();
+
+        assert_eq!(
+            lyrics.next().map(|l| LyricLine::<'_>::into_owned(l)),
+            Some(LyricLineOwned {
+                text: "Hi friend...".into(),
+                start_time: Duration::from_millis(1000 + 50),
+            })
+        );
+        assert_eq!(
+            lyrics.next().map(|l| LyricLine::<'_>::into_owned(l)),
+            Some(LyricLineOwned {
+                text: "Can you hear me?...".into(),
+                start_time: Duration::from_millis(640 + (45 * 60 + 5) * 1000),
+            })
+        );
+
+        Ok(())
+    }
+
+    #[test]
+    fn ill_formatted_time() -> Result<()> {
+        let lrc = r#"
+[00:01:05] Hi friend...
+"#;
+        let mut lyrics = lrc_iter(lrc.lines())?.into_iter();
+
+        assert_eq!(
+            lyrics.next().map(|l| LyricLine::<'_>::into_owned(l)),
+            Some(LyricLineOwned {
+                text: "Hi friend...".into(),
+                start_time: Duration::from_millis(1000 + 50),
+            })
+        );
+        Ok(())
+    }
+
+    #[test]
+    fn ill_formed_unexpected_line() -> Result<()> {
+        let lrc = r#"
+My first LRC Lyric!
+Author: poly000
+[00:01.05] Hi friend...
+"#;
+        let mut lyrics = lrc_iter(lrc.lines())?.into_iter();
+
+        assert_eq!(
+            lyrics.next().map(|l| LyricLine::<'_>::into_owned(l)),
+            Some(LyricLineOwned {
+                text: "Hi friend...".into(),
+                start_time: Duration::from_millis(1000 + 50),
+            })
+        );
+        Ok(())
+    }
+
+    #[test]
+    #[should_panic]
+    fn ill_formed_tag() {
+        let lrc = r#"
+[ Hello there ]
+"#;
+        lrc_iter(lrc.lines()).unwrap();
+    }
+
+    #[test]
+    fn elided_text() -> Result<()> {
+        let lrc = r#"
+[00:01.014][00:02.062] Hi friend...
+"#;
+        let mut lyrics = lrc_iter(lrc.lines())?.into_iter();
+
+        assert_eq!(
+            lyrics.next().map(|l| LyricLine::<'_>::into_owned(l)),
+            Some(LyricLineOwned {
+                text: "Hi friend...".into(),
+                start_time: Duration::from_millis(1014),
+            })
+        );
+
+        assert_eq!(
+            lyrics.next().map(|l| LyricLine::<'_>::into_owned(l)),
+            Some(LyricLineOwned {
+                text: "Hi friend...".into(),
+                start_time: Duration::from_millis(2062),
+            })
+        );
+
+        Ok(())
+    }
+
+    #[test]
+    fn empty_texts() -> Result<()> {
+        let lrc = r#"
+[00:01.014] Hi friend...
+[00:02.062]
+"#;
+        let mut lyrics = lrc_iter(lrc.lines())?.into_iter();
+
+        assert_eq!(
+            lyrics.next().map(|l| LyricLine::<'_>::into_owned(l)),
+            Some(LyricLineOwned {
+                text: "Hi friend...".into(),
+                start_time: Duration::from_millis(1014),
+            })
+        );
+
+        assert_eq!(
+            lyrics.next().map(|l| LyricLine::<'_>::into_owned(l)),
+            Some(LyricLineOwned {
+                text: "".into(),
+                start_time: Duration::from_millis(2062),
+            })
+        );
+
+        Ok(())
+    }
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/waylyrics-0~git486/src/tests/lyric_path.rs 
new/waylyrics-0.2.1/src/tests/lyric_path.rs
--- old/waylyrics-0~git486/src/tests/lyric_path.rs      1970-01-01 
01:00:00.000000000 +0100
+++ new/waylyrics-0.2.1/src/tests/lyric_path.rs 2024-02-08 19:25:55.000000000 
+0100
@@ -0,0 +1,33 @@
+use std::path::PathBuf;
+
+use crate::sync::lyric::fetch::tricks::get_lrc_path;
+
+#[test]
+fn shorter_extension() {
+    let result = get_lrc_path(PathBuf::from("/xx/yy/test.ts"));
+    assert_eq!(result, Some("/xx/yy/test.lrc".into()))
+}
+
+#[test]
+fn longer_extension() {
+    let result = get_lrc_path(PathBuf::from("/xx/yy/test.m3u8"));
+    assert_eq!(result, Some("/xx/yy/test.lrc".into()))
+}
+
+#[test]
+fn relative_path() {
+    let result = get_lrc_path(PathBuf::from("../test.mp3"));
+    assert_eq!(result, Some("../test.lrc".into()))
+}
+
+#[test]
+fn non_ascii() {
+    let result = get_lrc_path(PathBuf::from("/测试/中文/你
好.诶木披散"));
+    assert_eq!(result, Some("/测试/中文/你好.lrc".into()))
+}
+
+#[test]
+fn empty_string() {
+    let result = get_lrc_path(PathBuf::new());
+    assert_eq!(result, None)
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/waylyrics-0~git486/src/tests/mod.rs 
new/waylyrics-0.2.1/src/tests/mod.rs
--- old/waylyrics-0~git486/src/tests/mod.rs     1970-01-01 01:00:00.000000000 
+0100
+++ new/waylyrics-0.2.1/src/tests/mod.rs        2024-02-08 19:25:55.000000000 
+0100
@@ -0,0 +1,3 @@
+mod lyric_parse;
+mod lyric_path;
+mod netease_lyric;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/waylyrics-0~git486/src/tests/netease_lyric.rs 
new/waylyrics-0.2.1/src/tests/netease_lyric.rs
--- old/waylyrics-0~git486/src/tests/netease_lyric.rs   1970-01-01 
01:00:00.000000000 +0100
+++ new/waylyrics-0.2.1/src/tests/netease_lyric.rs      2024-02-08 
19:25:55.000000000 +0100
@@ -0,0 +1,27 @@
+use std::time::Duration;
+
+use crate::lyric_providers::netease::Netease;
+use crate::lyric_providers::{LyricLineOwned, LyricOwned, LyricParse, 
LyricProvider};
+
+use anyhow::Result;
+
+/// This test cannot be run from offline environment!
+#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
+async fn get_netease_lyric() -> Result<()> {
+    let provider = Netease;
+    let lyric_store = provider.query_lyric("708965").await?;
+    let lyric = provider.parse_lyric(&lyric_store);
+    let LyricOwned::LineTimestamp(lyrics) = lyric else {
+        panic!("cannot get lyric from netease");
+    };
+
+    assert_eq!(
+        lyrics.last(),
+        Some(&LyricLineOwned {
+            text: "纯音乐,请欣赏".into(),
+            start_time: Duration::from_secs(60 * 99),
+        })
+    );
+
+    Ok(())
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/waylyrics-0~git486/src/utils/mod.rs 
new/waylyrics-0.2.1/src/utils/mod.rs
--- old/waylyrics-0~git486/src/utils/mod.rs     2024-02-07 12:12:22.000000000 
+0100
+++ new/waylyrics-0.2.1/src/utils/mod.rs        2024-02-08 19:25:55.000000000 
+0100
@@ -1,13 +1,14 @@
 use anyhow::Result;
 use gtk::gio::SimpleAction;
-use gtk::glib::{ControlFlow, WeakRef};
 use gtk::{
     prelude::*, subclass::prelude::*, Application, NamedAction, Shortcut, 
ShortcutController,
     ShortcutTrigger,
 };
+use std::path::PathBuf;
 use std::time::Duration;
 
 use crate::app::{get_label, utils::set_click_pass_through, Window};
+use crate::config::Config;
 use crate::DEFAULT_TEXT;
 
 pub fn reset_lyric_labels(window: &Window) {
@@ -46,25 +47,6 @@
     IllFormed,
 }
 
-pub fn register_sigusr2_decoration(app: WeakRef<Application>) {
-    gtk::glib::unix_signal_add_local(libc::SIGUSR2, move || {
-        let Some(app) = app.upgrade() else {
-            return ControlFlow::Break;
-        };
-
-        let mut windows = app.windows();
-        if windows.is_empty() {
-            return ControlFlow::Continue;
-        }
-        let window = windows.remove(0);
-
-        let decorated = window.is_decorated();
-        window.set_decorated(!decorated);
-
-        ControlFlow::Continue
-    });
-}
-
 pub fn register_action_switch_decoration(wind: &Window, 
switch_decoration_trigger: &str) {
     let action = SimpleAction::new("switch-decoration", None);
     let _wind = Window::downgrade(wind);
@@ -105,6 +87,7 @@
     controller.add_shortcut(shortcut);
     wind.add_controller(controller);
 }
+
 pub fn register_action_switch_passthrough(wind: &Window, trigger: &str) {
     let action = SimpleAction::new("switch-passthrough", None);
     let _wind = Window::downgrade(wind);
@@ -127,3 +110,29 @@
     controller.add_shortcut(shortcut);
     wind.add_controller(controller);
 }
+
+pub fn init_dirs() -> Result<(PathBuf, PathBuf)> {
+    let xdg_dirs = xdg::BaseDirectories::with_prefix("waylyrics")?;
+    let config_home = xdg_dirs.get_config_home();
+    let cache_dir = xdg_dirs.get_cache_home();
+    crate::CACHE_DIR.set(
+        cache_dir
+            .to_str()
+            .expect("xdg config home is not valid UTF-8")
+            .into(),
+    );
+
+    std::fs::create_dir_all(&config_home)?;
+    std::fs::create_dir_all(&cache_dir)?;
+    let config_path = config_home.join("config.toml");
+    let user_theme_dir = xdg_dirs.get_data_home().join("_themes");
+
+    if !config_path.exists() {
+        std::fs::write(&config_path, toml::to_string(&Config::default())?)?;
+    }
+    if !user_theme_dir.exists() {
+        std::fs::create_dir_all(&user_theme_dir)?;
+    }
+
+    Ok((config_path, user_theme_dir))
+}

++++++ waylyrics.obsinfo ++++++
--- /var/tmp/diff_new_pack.LCmSuV/_old  2024-02-09 23:54:06.186819315 +0100
+++ /var/tmp/diff_new_pack.LCmSuV/_new  2024-02-09 23:54:06.202819891 +0100
@@ -1,5 +1,5 @@
 name: waylyrics
-version: 0~git486
-mtime: 1707304342
-commit: d120999caa3a6b15dfcc35bd775b1df06882d20e
+version: 0.2.1
+mtime: 1707416755
+commit: 31335eb5f6e8ac4ad06ae908a8ec309677efb9d8
 

Reply via email to