Compare commits
38 Commits
e29fdaf850
...
76a55d862f
Author | SHA1 | Date | |
---|---|---|---|
76a55d862f | |||
e601a8213e | |||
50f1e42377 | |||
3b0cc12251 | |||
cf96579238 | |||
de28e83b0e | |||
eea7af0ee9 | |||
1e19fb64df | |||
ba56ee0e7c | |||
b17f15d582 | |||
ac1592097f | |||
72eb783fae | |||
ebf8743d78 | |||
fb80d99cad | |||
1d384cb185 | |||
0f56a0160e | |||
62e372b2d4 | |||
4b95e27b15 | |||
e92dcc54a8 | |||
ccff2dde9a | |||
5f28bb4dc6 | |||
02079a2baa | |||
a986d2f9bf | |||
e2cb3b872e | |||
d8a48c5396 | |||
d21a390d57 | |||
d2e9c9b2df | |||
|
6a0e41c393 | ||
|
46a6f8ab56 | ||
a2d65257da | |||
80a607a8fb | |||
|
6c125d6152 | ||
3fe1518325 | |||
ae45748724 | |||
a23503c3cc | |||
95bcc209f3 | |||
245e46a2a0 | |||
|
13ca3e81d1 |
32
.github/ISSUE_TEMPLATE/bug_report.md
vendored
32
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@ -1,32 +0,0 @@
|
|||||||
---
|
|
||||||
name: "[请按照此模板填写] 报告 Bug"
|
|
||||||
about: "创建一个 Bug 报告,不按照模板的 Issue 会被直接关闭,不予回复。"
|
|
||||||
title: "[Bug] 总结你的 Bug 报告"
|
|
||||||
labels: bug
|
|
||||||
assignees: taurusxin
|
|
||||||
---
|
|
||||||
|
|
||||||
**Bug 描述**
|
|
||||||
|
|
||||||
清晰地描述一下 Bug 的大致问题,例如无法转换,或者其他问题。
|
|
||||||
|
|
||||||
**复现方法**
|
|
||||||
|
|
||||||
复现此 Bug 的方法
|
|
||||||
|
|
||||||
1. 使用本项目处理文件 '...'
|
|
||||||
2. 发生报错
|
|
||||||
|
|
||||||
**屏幕截图**
|
|
||||||
|
|
||||||
如果可以,屏幕截图可以更好地阐述你的问题。
|
|
||||||
|
|
||||||
**环境**
|
|
||||||
|
|
||||||
- 操作系统: Windows / macOS / Linux
|
|
||||||
- 网易云版本(重要): [e.g. 3.0.1]
|
|
||||||
- 所选择的音质: 极高、无损等
|
|
||||||
|
|
||||||
**附加内容**
|
|
||||||
|
|
||||||
如果遇到无法转换的问题,请将样本附加到这里,便于分析。
|
|
101
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
Normal file
101
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
name: 报告 Bug
|
||||||
|
description: 创建一个 Bug 报告。
|
||||||
|
title: "[Bug]: "
|
||||||
|
labels: "bug"
|
||||||
|
assignees:
|
||||||
|
- taurusxin
|
||||||
|
body:
|
||||||
|
- type: markdown
|
||||||
|
attributes:
|
||||||
|
value: |
|
||||||
|
# taurusxin/ncmdump Bug 反馈须知
|
||||||
|
请__严格遵守该模板进行 Bug 反馈__,否则维护者有权直接关闭本 Issue 不予回复!
|
||||||
|
为了保证 Bug 追踪的顺利,请__务必提供详细信息,并接受来自维护者的提问__!
|
||||||
|
|
||||||
|
- type: checkboxes
|
||||||
|
attributes:
|
||||||
|
label: 该 Bug 是否针对 `libncmdump`?
|
||||||
|
description: 如果是命令行工具 `ncmdump` 请不要勾选。
|
||||||
|
options:
|
||||||
|
- label: 是的,此 Bug 是针对动态库 `libncmdump` 而不是命令行工具 `ncmdump`!
|
||||||
|
|
||||||
|
- type: dropdown
|
||||||
|
attributes:
|
||||||
|
label: 类型
|
||||||
|
options:
|
||||||
|
- 无法转换文件
|
||||||
|
- 转换成功但音频文件无法播放
|
||||||
|
- 功能失效
|
||||||
|
- 程序崩溃
|
||||||
|
- 其他
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
|
||||||
|
- type: textarea
|
||||||
|
attributes:
|
||||||
|
label: Bug 描述
|
||||||
|
description: 清晰地描述一下 Bug 的大致问题及表现,对上面的类型进行补充说明。
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
|
||||||
|
- type: textarea
|
||||||
|
attributes:
|
||||||
|
label: 复现方法
|
||||||
|
description: 复现此 Bug 的方法。
|
||||||
|
placeholder: |
|
||||||
|
1. 使用本项目处理文件 '...'
|
||||||
|
2. 发生报错
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
|
||||||
|
- type: textarea
|
||||||
|
attributes:
|
||||||
|
label: 屏幕截图或视频
|
||||||
|
description: 如果可以,屏幕截图可以更好地阐述你的问题。
|
||||||
|
placeholder: 将截图或视频文件拖入此处
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
|
||||||
|
- type: input
|
||||||
|
attributes:
|
||||||
|
label: 操作系统
|
||||||
|
description: 请提供您当前正在使用的操作系统,如果可以,请提供更多关于操作系统的版本信息,Linux 请提供发行版名称。
|
||||||
|
placeholder: 如:Windows / macOS / Debian
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
|
||||||
|
- type: input
|
||||||
|
attributes:
|
||||||
|
label: ncmdump 版本
|
||||||
|
description: 请提供您正在使用的 ncmdump 版本,如果是来自 Github Actions 的构建,请提供 commit 信息。
|
||||||
|
placeholder: 如:1.5.0
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
|
||||||
|
- type: input
|
||||||
|
attributes:
|
||||||
|
label: 网易云版本(重要)
|
||||||
|
description: 请提供您下载 ncm 文件的网易云客户端及版本,请写明客户端平台与版本号。
|
||||||
|
placeholder: 如:Windows 版 3.0.1
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
|
||||||
|
- type: dropdown
|
||||||
|
attributes:
|
||||||
|
label: 所下载的音质
|
||||||
|
options:
|
||||||
|
- 标准
|
||||||
|
- 极高
|
||||||
|
- 无损
|
||||||
|
- 高清臻音
|
||||||
|
- 超清母带
|
||||||
|
- 沉浸环绕声
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
|
||||||
|
- type: textarea
|
||||||
|
attributes:
|
||||||
|
label: 附加内容
|
||||||
|
placeholder: 如果遇到无法转换的问题,请将样本附加到这里,便于分析。
|
||||||
|
validations:
|
||||||
|
required: false
|
8
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
8
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
blank_issues_enabled: false
|
||||||
|
contact_links:
|
||||||
|
- name: 寻求帮助
|
||||||
|
url: https://github.com/taurusxin/ncmdump/discussions/categories/q-a
|
||||||
|
about: 有疑问?请转移到讨论的 Q&A 分区!
|
||||||
|
- name: 意见与新功能请求
|
||||||
|
url: https://github.com/taurusxin/ncmdump/discussions/categories/ideas
|
||||||
|
about: 需要什么新功能?请到讨论的 Ideas 分区!
|
210
.github/workflows/autobuild.yml
vendored
210
.github/workflows/autobuild.yml
vendored
@ -4,139 +4,123 @@ env:
|
|||||||
BUILD_PATH: build
|
BUILD_PATH: build
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches: [ main ]
|
branches: [ main, dev ]
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build_on_windows_msys2:
|
# ----------------------------------------------------------------------
|
||||||
runs-on: windows-latest
|
# 1. Linux Build
|
||||||
|
# ----------------------------------------------------------------------
|
||||||
steps:
|
job_linux:
|
||||||
- name: Checkout repository
|
name: Linux Build
|
||||||
uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
submodules: recursive
|
|
||||||
|
|
||||||
- name: Install dependencies
|
|
||||||
uses: msys2/setup-msys2@v2
|
|
||||||
with:
|
|
||||||
msystem: UCRT64
|
|
||||||
update: true
|
|
||||||
install: git mingw-w64-ucrt-x86_64-toolchain
|
|
||||||
|
|
||||||
- name: Configure build
|
|
||||||
run: cmake -G "MinGW Makefiles" -DCMAKE_BUILD_TYPE=${{ env.BUILD_TYPE }} -B ${{ env.BUILD_PATH }}
|
|
||||||
|
|
||||||
- name: Build
|
|
||||||
run: cmake --build ${{ env.BUILD_PATH }} -j 4
|
|
||||||
|
|
||||||
- name: Strip
|
|
||||||
run: strip ${{ env.BUILD_PATH }}/ncmdump.exe
|
|
||||||
|
|
||||||
- name: Upload artifact
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: windows_amd64_build_msys2_exe
|
|
||||||
path: ${{ env.BUILD_PATH }}/ncmdump.exe
|
|
||||||
|
|
||||||
build_on_windows_msvc:
|
|
||||||
runs-on: windows-latest
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Checkout repository
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
submodules: recursive
|
|
||||||
|
|
||||||
- name: Configure build
|
|
||||||
run: cmake -DCMAKE_BUILD_TYPE=${{ env.BUILD_TYPE }} -B ${{ env.BUILD_PATH }}
|
|
||||||
|
|
||||||
- name: Build
|
|
||||||
run: cmake --build ${{ env.BUILD_PATH }} -j 4 --config ${{ env.BUILD_TYPE }}
|
|
||||||
|
|
||||||
- name: Upload artifact executable
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: windows_amd64_build_msvc_exe
|
|
||||||
path: ${{ env.BUILD_PATH }}/${{ env.BUILD_TYPE }}/ncmdump.exe
|
|
||||||
|
|
||||||
- name: Upload artifact DLL
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: windows_amd64_build_msvc_dll
|
|
||||||
path: ${{ env.BUILD_PATH }}/${{ env.BUILD_TYPE }}/libncmdump.dll
|
|
||||||
|
|
||||||
build_on_linux_amd64:
|
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repository
|
- name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
submodules: recursive
|
submodules: true
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install Dependencies
|
||||||
run: |
|
run: |
|
||||||
sudo apt-get update
|
sudo apt-get update
|
||||||
sudo apt-get install -y build-essential cmake
|
sudo apt-get install -y build-essential cmake libtag1-dev zlib1g-dev
|
||||||
|
|
||||||
- name: Configure build
|
# ubuntu 24.04 does not contains taglib v2.x, which does not support cmake, built it manually
|
||||||
run: cmake -DCMAKE_BUILD_TYPE=${{ env.BUILD_TYPE }} -B ${{ env.BUILD_PATH }}
|
- name: Build TagLib v2.1.1
|
||||||
|
run: |
|
||||||
|
wget https://github.com/taglib/taglib/releases/download/v2.1.1/taglib-2.1.1.tar.gz
|
||||||
|
tar -xzf taglib-2.1.1.tar.gz
|
||||||
|
cd taglib-2.1.1
|
||||||
|
cmake -DCMAKE_INSTALL_PREFIX=/usr/local -DCMAKE_BUILD_TYPE=Release .
|
||||||
|
make -j$(nproc)
|
||||||
|
sudo make install
|
||||||
|
|
||||||
- name: Build
|
- name: Configure CMake
|
||||||
run: cmake --build ${{ env.BUILD_PATH }} -j 4
|
run: |
|
||||||
|
cmake -B ${{github.workspace}}/build \
|
||||||
|
-DCMAKE_BUILD_TYPE=Release \
|
||||||
|
-S ${{github.workspace}}
|
||||||
|
|
||||||
- name: Upload artifact
|
- name: Build
|
||||||
uses: actions/upload-artifact@v4
|
run: cmake --build ${{github.workspace}}/build --config Release
|
||||||
with:
|
|
||||||
name: linux_build_amd64
|
|
||||||
path: ${{ env.BUILD_PATH }}/ncmdump
|
|
||||||
|
|
||||||
build_on_macos_amd64:
|
- name: Upload Linux Artifact
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: ncmdump-linux
|
||||||
|
path: ${{github.workspace}}/build/ncmdump
|
||||||
|
|
||||||
|
# ----------------------------------------------------------------------
|
||||||
|
# 2. macOS Build
|
||||||
|
# ----------------------------------------------------------------------
|
||||||
|
job_macos:
|
||||||
|
name: macOS Build
|
||||||
runs-on: macos-latest
|
runs-on: macos-latest
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repository
|
- name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
submodules: recursive
|
submodules: true
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install Dependencies
|
||||||
run: |
|
run: |
|
||||||
brew install git cmake
|
brew install taglib
|
||||||
|
|
||||||
- name: Configure build
|
- name: Configure CMake
|
||||||
run: cmake -DCMAKE_BUILD_TYPE=${{ env.BUILD_TYPE }} -B ${{ env.BUILD_PATH }} -DCMAKE_OSX_ARCHITECTURES=x86_64
|
run: |
|
||||||
|
cmake -B ${{github.workspace}}/build \
|
||||||
|
-DCMAKE_BUILD_TYPE=Release \
|
||||||
|
-S ${{github.workspace}}
|
||||||
|
|
||||||
- name: Build
|
- name: Build
|
||||||
run: cmake --build ${{ env.BUILD_PATH }} -j 4
|
run: cmake --build ${{github.workspace}}/build --config Release
|
||||||
|
|
||||||
- name: Upload artifact
|
- name: Upload macOS Artifact
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: macOS_build_amd64
|
name: ncmdump-macos
|
||||||
path: ${{ env.BUILD_PATH }}/ncmdump
|
path: ${{github.workspace}}/build/ncmdump
|
||||||
|
|
||||||
build_on_macos_arm64:
|
# ----------------------------------------------------------------------
|
||||||
runs-on: macos-latest
|
# 3. Windows Build
|
||||||
|
# ----------------------------------------------------------------------
|
||||||
|
job_windows:
|
||||||
|
name: Windows Build
|
||||||
|
runs-on: windows-latest
|
||||||
|
env:
|
||||||
|
VCPKG_TRIPLET: x64-windows-static
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repository
|
- name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
submodules: recursive
|
submodules: true
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install Dependencies
|
||||||
run: |
|
uses: lukka/run-vcpkg@v11
|
||||||
brew install git cmake
|
id: vcpkg
|
||||||
|
with:
|
||||||
|
vcpkgJsonGlob: '**/vcpkg.json'
|
||||||
|
|
||||||
- name: Configure build
|
- name: Configure CMake
|
||||||
run: cmake -DCMAKE_BUILD_TYPE=${{ env.BUILD_TYPE }} -B ${{ env.BUILD_PATH }} -DCMAKE_OSX_ARCHITECTURES=arm64
|
run: |
|
||||||
|
cmake -B ${{github.workspace}}/build `
|
||||||
|
-DCMAKE_TOOLCHAIN_FILE=${{ github.workspace }}/vcpkg/scripts/buildsystems/vcpkg.cmake `
|
||||||
|
-DVCPKG_TARGET_TRIPLET=${{ env.VCPKG_TRIPLET }} `
|
||||||
|
-S ${{github.workspace}}
|
||||||
|
|
||||||
- name: Build
|
- name: Build
|
||||||
run: cmake --build ${{ env.BUILD_PATH }} -j 4
|
run: cmake --build ${{github.workspace}}/build --config Release
|
||||||
|
|
||||||
- name: Upload artifact
|
- name: Upload Windows Executable Artifact
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: macOS_build_arm64
|
name: ncmdump-windows
|
||||||
path: ${{ env.BUILD_PATH }}/ncmdump
|
path: ${{github.workspace}}/build/Release/ncmdump.exe
|
||||||
|
|
||||||
|
- name: Upload Windows Library Artifact
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: libncmdump-windows
|
||||||
|
path: ${{github.workspace}}/build/Release/libncmdump.dll
|
4
.gitignore
vendored
4
.gitignore
vendored
@ -6,4 +6,6 @@ ncmdump
|
|||||||
|
|
||||||
build
|
build
|
||||||
|
|
||||||
cmake-build-*
|
cmake-build-*
|
||||||
|
|
||||||
|
vcpkg_installed
|
3
.gitmodules
vendored
3
.gitmodules
vendored
@ -1,3 +0,0 @@
|
|||||||
[submodule "taglib"]
|
|
||||||
path = taglib
|
|
||||||
url = https://github.com/taglib/taglib.git
|
|
@ -5,10 +5,8 @@ project(ncmdump LANGUAGES CXX)
|
|||||||
set(CMAKE_CXX_STANDARD 17)
|
set(CMAKE_CXX_STANDARD 17)
|
||||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
|
|
||||||
set(CMAKE_POLICY_DEFAULT_CMP0077 NEW)
|
find_package(ZLIB)
|
||||||
set(WITH_ZLIB OFF)
|
find_package(TagLib REQUIRED)
|
||||||
set(BUILD_TESTING OFF)
|
|
||||||
add_subdirectory(taglib)
|
|
||||||
|
|
||||||
if(MSVC)
|
if(MSVC)
|
||||||
add_compile_options("$<$<CXX_COMPILER_ID:MSVC>:/execution-charset:utf-8>")
|
add_compile_options("$<$<CXX_COMPILER_ID:MSVC>:/execution-charset:utf-8>")
|
||||||
@ -22,12 +20,15 @@ FILE(GLOB LIBRARY_SOURCES src/lib/*.cpp)
|
|||||||
FILE(GLOB WIN_SOURCES src/platform/win32_init.cpp)
|
FILE(GLOB WIN_SOURCES src/platform/win32_init.cpp)
|
||||||
|
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
|
# windows executable
|
||||||
add_executable(ncmdump_exec
|
add_executable(ncmdump_exec
|
||||||
${COMMON_HEADERS}
|
${COMMON_HEADERS}
|
||||||
${COMMON_SOURCES}
|
${COMMON_SOURCES}
|
||||||
${EXECUTABLE_SOURCES}
|
${EXECUTABLE_SOURCES}
|
||||||
${WIN_SOURCES}
|
${WIN_SOURCES}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# windows library
|
||||||
add_library(ncmdump_lib SHARED
|
add_library(ncmdump_lib SHARED
|
||||||
${COMMON_HEADERS}
|
${COMMON_HEADERS}
|
||||||
${COMMON_SOURCES}
|
${COMMON_SOURCES}
|
||||||
@ -36,22 +37,27 @@ if(WIN32)
|
|||||||
${WIN_SOURCES}
|
${WIN_SOURCES}
|
||||||
)
|
)
|
||||||
|
|
||||||
set_target_properties(ncmdump_lib PROPERTIES OUTPUT_NAME "libncmdump")
|
|
||||||
|
|
||||||
target_include_directories(ncmdump_lib PRIVATE src/include)
|
target_include_directories(ncmdump_lib PRIVATE src/include)
|
||||||
|
set_target_properties(ncmdump_lib PROPERTIES OUTPUT_NAME "libncmdump")
|
||||||
|
target_link_libraries(ncmdump_lib TagLib::tag)
|
||||||
|
|
||||||
target_link_libraries(ncmdump_lib tag)
|
# msvc 需要额外调整编译选项
|
||||||
target_include_directories(ncmdump_lib PRIVATE taglib)
|
if(MSVC)
|
||||||
target_include_directories(ncmdump_lib PRIVATE taglib/taglib)
|
# 强制所有配置(Debug/Release 等)使用静态 C 运行时库
|
||||||
target_include_directories(ncmdump_lib PRIVATE taglib/taglib/toolkit)
|
foreach(flag_var
|
||||||
target_include_directories(ncmdump_lib PRIVATE taglib/taglib/mpeg/id3v2)
|
CMAKE_CXX_FLAGS
|
||||||
|
CMAKE_C_FLAGS
|
||||||
if(CMAKE_COMPILER_IS_GNUCXX)
|
CMAKE_CXX_FLAGS_DEBUG
|
||||||
# static link when using MinGW
|
CMAKE_CXX_FLAGS_RELEASE
|
||||||
target_link_options(ncmdump_exec PRIVATE -static)
|
)
|
||||||
target_link_options(ncmdump_lib PRIVATE -static)
|
if(${flag_var})
|
||||||
|
string(REPLACE "/MD" "/MT" ${flag_var} "${${flag_var}}")
|
||||||
|
endif()
|
||||||
|
endforeach()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
else()
|
else()
|
||||||
|
# linux / macOS executable
|
||||||
add_executable(ncmdump_exec
|
add_executable(ncmdump_exec
|
||||||
${COMMON_HEADERS}
|
${COMMON_HEADERS}
|
||||||
${COMMON_SOURCES}
|
${COMMON_SOURCES}
|
||||||
@ -63,11 +69,8 @@ endif()
|
|||||||
set_target_properties(ncmdump_exec PROPERTIES OUTPUT_NAME "ncmdump")
|
set_target_properties(ncmdump_exec PROPERTIES OUTPUT_NAME "ncmdump")
|
||||||
target_include_directories(ncmdump_exec PRIVATE src/include)
|
target_include_directories(ncmdump_exec PRIVATE src/include)
|
||||||
|
|
||||||
target_link_libraries(ncmdump_exec tag)
|
# executable link to taglib
|
||||||
target_include_directories(ncmdump_exec PRIVATE taglib)
|
target_link_libraries(ncmdump_exec TagLib::tag)
|
||||||
target_include_directories(ncmdump_exec PRIVATE taglib/taglib)
|
|
||||||
target_include_directories(ncmdump_exec PRIVATE taglib/taglib/toolkit)
|
|
||||||
target_include_directories(ncmdump_exec PRIVATE taglib/taglib/mpeg/id3v2)
|
|
||||||
|
|
||||||
include(GNUInstallDirs)
|
include(GNUInstallDirs)
|
||||||
|
|
||||||
@ -80,7 +83,6 @@ if(WIN32)
|
|||||||
else()
|
else()
|
||||||
install(TARGETS ncmdump_exec
|
install(TARGETS ncmdump_exec
|
||||||
BUNDLE DESTINATION .
|
BUNDLE DESTINATION .
|
||||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
|
||||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
91
README.md
91
README.md
@ -6,29 +6,19 @@
|
|||||||
|
|
||||||
该版本为最早的 C++ 版本,也是作者开发的市面上第一个支持 ncm 转换的程序
|
该版本为最早的 C++ 版本,也是作者开发的市面上第一个支持 ncm 转换的程序
|
||||||
|
|
||||||
源码复刻自 anonymous5l/ncmdump,感谢前辈的付出!做了 Windows 下的移植,修复了一些编译问题
|
源码复刻自 anonymous5l/ncmdump (2021年10月6日,原作者已经删库)
|
||||||
|
|
||||||
1.3.0 版本更新说明:因为之前有小伙伴反馈无法解密带有特殊字符的文件名,例如中文、日文、韩文或者是表情符号等,在1.3.0以及之后的版本彻底修复了这个问题,所有的 UTF-8 字符都可以正常解密。并且还自带了 dll 的构建,可以供其他应用程序(C#、Python、Java等)调用。
|
感谢前辈的付出!此版本做了全操作系统下的的跨平台编译移植,修复了一些内存溢出的问题。
|
||||||
|
|
||||||
## 传送门
|
1.3.0 版本更新说明:因为之前有较多 Issue 反馈无法解密带有特殊字符的文件名,例如中文、日文、韩文或者是表情符号等,在1.3.0以及之后的版本彻底修复了这个问题,所有的 UTF-8 字符都可以正常解密。并且还自带了 dll 的构建,可以供其他应用程序(C#、Python、Java等)调用。
|
||||||
|
|
||||||
2021年10月6日,原作者已经删库
|
|
||||||
|
|
||||||
## 使用
|
## 使用
|
||||||
|
|
||||||
注意:自网易云音乐 3.0 版本开始,下载的 ncm 文件均不内置歌曲专辑的封面图片,需要从网络获取,介于在一个小工具中嵌入庞大网络库的非必要性,可以移步我的另一个仓库(<https://git.taurusxin.com/taurusxin/ncmdump-go>),下载完全使用 Golang 重写的新版本,支持从网络自动获取封面图并嵌入到目标音乐文件。
|
注意:网易云音乐 3.0 之后的某些版本,下载的 ncm 文件会出现不内置歌曲专辑的封面图片的情况,所需的封面图数据需要从网络获取,介于在一个小工具中嵌入庞大网络库的非必要性,可以移步我的另一个仓库 [ncmdump-go](https://git.taurusxin.com/taurusxin/ncmdump-go) 或者使用基于此项目开发的可视化 GUI 程序 [ncmdump-gui](https://git.taurusxin.com/taurusxin/ncmdump-gui),其中后者基于前者,均完全使用 Golang 重写,并支持自动从元数据读取封面信息后从网络获取封面图并嵌入到目标音乐文件。
|
||||||
|
|
||||||
### 命令行工具
|
### 命令行工具
|
||||||
|
|
||||||
**[不推荐]** 你可以使用 Homebrew 来安装 Linux 或者 macOS 下的 ncmdump
|
从 [Release](https://github.com/taurusxin/ncmdump/releases) 下载最新版本的对应系统的已编译好的二进制文件
|
||||||
|
|
||||||
注意:由于本项目依赖的库 taglib 的 2.0 版本尚未发布到 homebrew-core(主要是因为 taglib 2.0 导致其他 brew 包存在版本兼容问题),目前的 cmake 构建链无法在 macOS 上正常使用。根据 brew 的要求,如果依赖库已有官方的 brew 包,构建时必须使用官方仓库中的包,不能从 git 获取。而 taglib 2.0 版本开始才支持 cmake 构建。因此,ncmdump 在 homebrew 上只能发布到 `1.2.1` 版本。建议直接通过二进制方式安装,`1.3.0` 后版本修复了许多 bug,使用体验会更好。
|
|
||||||
|
|
||||||
```shell
|
|
||||||
brew install ncmdump
|
|
||||||
```
|
|
||||||
|
|
||||||
或者从 [Release](https://github.com/taurusxin/ncmdump/releases) 下载最新版本的对应系统的已编译好的二进制文件
|
|
||||||
|
|
||||||
使用 `-h` 或 `--help` 参数来打印帮助
|
使用 `-h` 或 `--help` 参数来打印帮助
|
||||||
|
|
||||||
@ -60,6 +50,12 @@ ncmdump -d source_dir
|
|||||||
ncmdump -d source_dir -r
|
ncmdump -d source_dir -r
|
||||||
```
|
```
|
||||||
|
|
||||||
|
使用 `-m` 参数来删除源文件若正确处理
|
||||||
|
|
||||||
|
```shell
|
||||||
|
ncmdump -m
|
||||||
|
```
|
||||||
|
|
||||||
使用 `-o` 参数来指定输出目录,将转换后的文件输出到指定目录,该参数支持与 `-r` 参数一起使用
|
使用 `-o` 参数来指定输出目录,将转换后的文件输出到指定目录,该参数支持与 `-r` 参数一起使用
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
@ -87,40 +83,71 @@ ncmdump -d source_dir -o output_dir -r
|
|||||||
git clone https://github.com/taurusxin/ncmdump.git
|
git clone https://github.com/taurusxin/ncmdump.git
|
||||||
```
|
```
|
||||||
|
|
||||||
更新子模块
|
### Windows
|
||||||
|
|
||||||
|
安装 Visual Studio 2022 和 cmake,并安装 C++ 桌面开发环境,然后安装 [vcpkg](https://github.com/microsoft/vcpkg)
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
cd ncmdump
|
# 安装 vcpkg 并安装 taglib 的静态库
|
||||||
git submodule update --init --recursive
|
git clone https://github.com/microsoft/vcpkg.git
|
||||||
|
cd vcpkg
|
||||||
|
./bootstrap-vcpkg.bat
|
||||||
```
|
```
|
||||||
|
|
||||||
使用 CMake 配置项目。Windows 下若使用 GNU 套件,推荐使用 [msys2](https://www.msys2.org/) 或者 [winlibs](https://winlibs.com/)
|
配置项目
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
# Windows MinGW
|
# 使用 cmake 配置项目,替换 %VCPKG_ROOT% 为你的 vcpkg 安装路径
|
||||||
cmake -G "MinGW Makefiles" -DCMAKE_BUILD_TYPE=Release -B build
|
cmake -G "Visual Studio 17 2022" -DCMAKE_TOOLCHAIN_FILE=%VCPKG_ROOT%/scripts/buildsystems/vcpkg.cmake -DVCPKG_TARGET_TRIPLET=x64-windows-static -B build
|
||||||
|
|
||||||
# Windows MSVC
|
# 编译项目
|
||||||
cmake -G "Visual Studio 17 2022" -A x64 -B build
|
cmake --build build -j 8 --config Release
|
||||||
|
```
|
||||||
|
|
||||||
# Linux / macOS
|
### macOS
|
||||||
|
|
||||||
|
macOS 下,你可以方便地使用 Homebrew 来安装 taglib 库
|
||||||
|
|
||||||
|
```shell
|
||||||
|
# 安装 taglib 库
|
||||||
|
brew install taglib
|
||||||
|
|
||||||
|
# 配置项目
|
||||||
cmake -DCMAKE_BUILD_TYPE=Release -B build
|
cmake -DCMAKE_BUILD_TYPE=Release -B build
|
||||||
|
|
||||||
# 如果需要在 macOS 下交叉编译,可以指定 `CMAKE_OSX_ARCHITECTURES` 变量来指明目标系统架构
|
# 编译项目
|
||||||
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_OSX_ARCHITECTURES=arm64 -B build # arm64
|
cmake --build build -j$(nproc)
|
||||||
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_OSX_ARCHITECTURES=x86_64 -B build # Intel-based
|
|
||||||
```
|
```
|
||||||
|
|
||||||
编译项目
|
### Linux
|
||||||
|
|
||||||
|
Linux 下,由于 Ubuntu 24.04 的 taglib 仍然为 1.x 版本,不支持 CMake,所以需要手动编译安装 2.x 版本,目前 GitHub Actions 的 Linux 构建流程也是手动编译。
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
# Windows MSVC 需要在构建阶段指定 --config Release
|
# 拉取源码
|
||||||
cmake --build build -j 8 --config Release
|
wget https://github.com/taglib/taglib/releases/download/v2.1.1/taglib-2.1.1.tar.gz
|
||||||
|
|
||||||
# Windows MinGW / Linux / macOS
|
# 解压并进入
|
||||||
cmake --build build -j 8
|
tar -xzf taglib-2.1.1.tar.gz && cd taglib-2.1.1
|
||||||
|
|
||||||
|
# 配置、编译和安装
|
||||||
|
cmake -DCMAKE_INSTALL_PREFIX=/usr/local -DCMAKE_BUILD_TYPE=Release .
|
||||||
|
make -j$(nproc)
|
||||||
|
sudo make install
|
||||||
```
|
```
|
||||||
|
|
||||||
|
然后和 macOS 上一样,使用 CMake 配置项目并编译项目
|
||||||
|
|
||||||
|
```shell
|
||||||
|
# 配置项目
|
||||||
|
cmake -DCMAKE_BUILD_TYPE=Release -B build
|
||||||
|
|
||||||
|
# 编译项目
|
||||||
|
cmake --build build -j$(nproc)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
你可以在 `build` 文件夹下找到编译好的二进制文件,以及一个可供其它项目使用的动态库(Windows Only),使用方法见仓库的 `example` 文件夹
|
你可以在 `build` 文件夹下找到编译好的二进制文件,以及一个可供其它项目使用的动态库(Windows Only),使用方法见仓库的 `example` 文件夹
|
||||||
|
|
||||||
## Star History
|
## Star History
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
#define VERSION_MAJOR 1
|
#define VERSION_MAJOR 1
|
||||||
#define VERSION_MINOR 5
|
#define VERSION_MINOR 5
|
||||||
#define VERSION_PATCH 0
|
#define VERSION_PATCH 1
|
22
src/main.cpp
22
src/main.cpp
@ -15,7 +15,7 @@
|
|||||||
|
|
||||||
namespace fs = std::filesystem;
|
namespace fs = std::filesystem;
|
||||||
|
|
||||||
void processFile(const fs::path &filePath, const fs::path &outputFolder)
|
void processFile(const fs::path &filePath, const fs::path &outputFolder, bool isRequiredRemoved)
|
||||||
{
|
{
|
||||||
if (fs::exists(filePath) == false)
|
if (fs::exists(filePath) == false)
|
||||||
{
|
{
|
||||||
@ -35,7 +35,14 @@ void processFile(const fs::path &filePath, const fs::path &outputFolder)
|
|||||||
crypt.Dump(outputFolder.u8string());
|
crypt.Dump(outputFolder.u8string());
|
||||||
crypt.FixMetadata();
|
crypt.FixMetadata();
|
||||||
|
|
||||||
std::cout << BOLDGREEN << "[Done] " << RESET << "'" << filePath.u8string() << "' -> '" << crypt.dumpFilepath().u8string() << "'" << std::endl;
|
std::cout << BOLDGREEN << "[Done] " << RESET << "'" << filePath.u8string() << "' -> '" << crypt.dumpFilepath().u8string() << "'" ;
|
||||||
|
|
||||||
|
if (isRequiredRemoved)
|
||||||
|
{
|
||||||
|
fs::remove(filePath);
|
||||||
|
std::cout << " with removed as required.";
|
||||||
|
}
|
||||||
|
std::cout << std::endl;
|
||||||
}
|
}
|
||||||
catch (const std::invalid_argument &e)
|
catch (const std::invalid_argument &e)
|
||||||
{
|
{
|
||||||
@ -61,6 +68,7 @@ int main(int argc, char **argv)
|
|||||||
("r,recursive", "Process files recursively (requires -d option)", cxxopts::value<bool>()->default_value("false"))
|
("r,recursive", "Process files recursively (requires -d option)", cxxopts::value<bool>()->default_value("false"))
|
||||||
("o,output", "Output folder (default: original file folder)", cxxopts::value<std::string>())
|
("o,output", "Output folder (default: original file folder)", cxxopts::value<std::string>())
|
||||||
("v,version", "Print version information", cxxopts::value<bool>()->default_value("false"))
|
("v,version", "Print version information", cxxopts::value<bool>()->default_value("false"))
|
||||||
|
("m,remove", "Remove original file if done", cxxopts::value<bool>()->default_value("false"))
|
||||||
("filenames", "Input files", cxxopts::value<std::vector<std::string>>());
|
("filenames", "Input files", cxxopts::value<std::vector<std::string>>());
|
||||||
|
|
||||||
options.positional_help("<files>");
|
options.positional_help("<files>");
|
||||||
@ -165,7 +173,7 @@ int main(int argc, char **argv)
|
|||||||
fs::create_directories(destinationPath.parent_path());
|
fs::create_directories(destinationPath.parent_path());
|
||||||
|
|
||||||
// 处理文件
|
// 处理文件
|
||||||
processFile(path, destinationPath.parent_path());
|
processFile(path, destinationPath.parent_path(), result.count("remove"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -178,11 +186,11 @@ int main(int argc, char **argv)
|
|||||||
{
|
{
|
||||||
if (outputDirSpecified)
|
if (outputDirSpecified)
|
||||||
{
|
{
|
||||||
processFile(path, outputDir);
|
processFile(path, outputDir, result.count("remove"));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
processFile(path, "");
|
processFile(path, "", result.count("remove"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -204,11 +212,11 @@ int main(int argc, char **argv)
|
|||||||
|
|
||||||
if (outputDirSpecified)
|
if (outputDirSpecified)
|
||||||
{
|
{
|
||||||
processFile(filePathU8, outputDir);
|
processFile(filePathU8, outputDir, result.count("remove"));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
processFile(filePathU8, "");
|
processFile(filePathU8, "", result.count("remove"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,13 +4,12 @@
|
|||||||
#include "cJSON.h"
|
#include "cJSON.h"
|
||||||
#include "color.h"
|
#include "color.h"
|
||||||
|
|
||||||
#define TAGLIB_STATIC
|
#include <taglib/tfile.h>
|
||||||
#include "taglib/toolkit/tfile.h"
|
#include <taglib/mpegfile.h>
|
||||||
#include "taglib/mpeg/mpegfile.h"
|
#include <taglib/flacfile.h>
|
||||||
#include "taglib/flac/flacfile.h"
|
#include <taglib/attachedpictureframe.h>
|
||||||
#include "taglib/mpeg/id3v2/frames/attachedpictureframe.h"
|
#include <taglib/id3v2tag.h>
|
||||||
#include "taglib/mpeg/id3v2/id3v2tag.h"
|
#include <taglib/tag.h>
|
||||||
#include "taglib/tag.h"
|
|
||||||
|
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <string>
|
#include <string>
|
||||||
@ -26,8 +25,7 @@ const unsigned char NeteaseCrypt::mPng[8] = {0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A,
|
|||||||
|
|
||||||
static void aesEcbDecrypt(const unsigned char *key, std::string &src, std::string &dst)
|
static void aesEcbDecrypt(const unsigned char *key, std::string &src, std::string &dst)
|
||||||
{
|
{
|
||||||
int n, i;
|
int i, n;
|
||||||
|
|
||||||
unsigned char out[16];
|
unsigned char out[16];
|
||||||
|
|
||||||
n = src.length() >> 4;
|
n = src.length() >> 4;
|
||||||
@ -51,18 +49,6 @@ static void aesEcbDecrypt(const unsigned char *key, std::string &src, std::strin
|
|||||||
dst += std::string((char *)out, 16 - pad);
|
dst += std::string((char *)out, 16 - pad);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void replace(std::string &str, const std::string &from, const std::string &to)
|
|
||||||
{
|
|
||||||
if (from.empty())
|
|
||||||
return;
|
|
||||||
size_t start_pos = 0;
|
|
||||||
while ((start_pos = str.find(from, start_pos)) != std::string::npos)
|
|
||||||
{
|
|
||||||
str.replace(start_pos, from.length(), to);
|
|
||||||
start_pos += to.length(); // In case 'to' contains 'from', like replacing 'x' with 'yx'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
NeteaseMusicMetadata::~NeteaseMusicMetadata()
|
NeteaseMusicMetadata::~NeteaseMusicMetadata()
|
||||||
{
|
{
|
||||||
cJSON_Delete(mRaw);
|
cJSON_Delete(mRaw);
|
||||||
@ -241,7 +227,7 @@ void NeteaseCrypt::FixMetadata()
|
|||||||
|
|
||||||
if (!mImageData.empty())
|
if (!mImageData.empty())
|
||||||
{
|
{
|
||||||
TagLib::FLAC::Picture *cover = new TagLib::FLAC::Picture;
|
auto *cover = new TagLib::FLAC::Picture;
|
||||||
cover->setMimeType(mimeType(mImageData));
|
cover->setMimeType(mimeType(mImageData));
|
||||||
cover->setType(TagLib::FLAC::Picture::FrontCover);
|
cover->setType(TagLib::FLAC::Picture::FrontCover);
|
||||||
cover->setData(vector);
|
cover->setData(vector);
|
||||||
@ -250,7 +236,7 @@ void NeteaseCrypt::FixMetadata()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mMetaData != NULL)
|
if (mMetaData != nullptr)
|
||||||
{
|
{
|
||||||
tag->setTitle(TagLib::String(mMetaData->name(), TagLib::String::UTF8));
|
tag->setTitle(TagLib::String(mMetaData->name(), TagLib::String::UTF8));
|
||||||
tag->setArtist(TagLib::String(mMetaData->artist(), TagLib::String::UTF8));
|
tag->setArtist(TagLib::String(mMetaData->artist(), TagLib::String::UTF8));
|
||||||
|
@ -2142,7 +2142,7 @@ CJSON_PUBLIC(void) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newit
|
|||||||
{
|
{
|
||||||
cJSON *after_inserted = NULL;
|
cJSON *after_inserted = NULL;
|
||||||
|
|
||||||
if (which < 0)
|
if (which < 0 || newitem == NULL)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -2154,6 +2154,10 @@ CJSON_PUBLIC(void) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newit
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (after_inserted != array->child && newitem->prev == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
newitem->next = after_inserted;
|
newitem->next = after_inserted;
|
||||||
newitem->prev = after_inserted->prev;
|
newitem->prev = after_inserted->prev;
|
||||||
after_inserted->prev = newitem;
|
after_inserted->prev = newitem;
|
||||||
|
1
taglib
1
taglib
@ -1 +0,0 @@
|
|||||||
Subproject commit e3de03501ff66221d1f1f971022b248d5b38ba06
|
|
8
vcpkg.json
Normal file
8
vcpkg.json
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"name": "ncmdump",
|
||||||
|
"version": "1.6.0",
|
||||||
|
"builtin-baseline": "a62ce77d56ee07513b4b67de1ec2daeaebfae51a",
|
||||||
|
"dependencies": [
|
||||||
|
"taglib"
|
||||||
|
]
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user