From 2cf2ae68b2130df6bcc64581aff12836696a4551 Mon Sep 17 00:00:00 2001 From: pnck Date: Mon, 6 May 2024 03:51:05 +0800 Subject: [PATCH] fix: edge cases --- .github/workflows/build-publish.yml | 1 + .github/workflows/build.yml | 1 + foo_input_ncm.vcxproj | 2 ++ foo_input_ncm.vcxproj.filters | 6 +++++ src/cipher/aes_win32.cpp | 5 ++-- src/common/helpers.hpp | 2 +- src/main.cpp | 5 ++++ src/meta_process.cpp | 16 ++++++++++- src/meta_process.hpp | 9 ++++--- src/ncm_file.cpp | 41 ++++++++++++++--------------- src/stdafx.h | 2 +- 11 files changed, 60 insertions(+), 30 deletions(-) mode change 100644 => 100755 src/cipher/aes_win32.cpp mode change 100644 => 100755 src/meta_process.hpp diff --git a/.github/workflows/build-publish.yml b/.github/workflows/build-publish.yml index 096f594..37ec3a2 100644 --- a/.github/workflows/build-publish.yml +++ b/.github/workflows/build-publish.yml @@ -81,6 +81,7 @@ jobs: run: | TAG=$(git describe --tags) VERSION=${TAG:1} + echo "" >> src/stdafx.h echo "#define CURRENT_VERSION $VERSION" >> src/stdafx.h echo "----------------------------" cat src/stdafx.h diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 2f09abb..24dd005 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -122,6 +122,7 @@ jobs: run: | TAG=$(git describe --long --all) VERSION=${TAG:6} + echo "" >> src/stdafx.h echo "#define CURRENT_VERSION $VERSION" >> src/stdafx.h echo "----------------------------" cat src/stdafx.h diff --git a/foo_input_ncm.vcxproj b/foo_input_ncm.vcxproj index 24da9d5..db11d43 100755 --- a/foo_input_ncm.vcxproj +++ b/foo_input_ncm.vcxproj @@ -199,6 +199,7 @@ copy $(TargetPath) $(ProjectDir)dist\$(Platform)\ + @@ -209,6 +210,7 @@ copy $(TargetPath) $(ProjectDir)dist\$(Platform)\ + diff --git a/foo_input_ncm.vcxproj.filters b/foo_input_ncm.vcxproj.filters index 0c7eac1..53c0683 100755 --- a/foo_input_ncm.vcxproj.filters +++ b/foo_input_ncm.vcxproj.filters @@ -72,6 +72,9 @@ Header Files\common + + Header Files + @@ -101,5 +104,8 @@ Source Files\ui + + Source Files + \ No newline at end of file diff --git a/src/cipher/aes_win32.cpp b/src/cipher/aes_win32.cpp old mode 100644 new mode 100755 index 971d4d4..10f64a8 --- a/src/cipher/aes_win32.cpp +++ b/src/cipher/aes_win32.cpp @@ -108,6 +108,7 @@ size_t AES_context_win32::do_crypt_universal( // -*- throw cipher_error("BCryptDecrypt failed", status_); } } else if (op == OP::ENC) { + auto padding_mode = (M == aes_chain_mode::ECB ? 0 : BCRYPT_BLOCK_PADDING); if (auto status_ = BCryptEncrypt( // -*- h_key, (PUCHAR)src, @@ -118,7 +119,7 @@ size_t AES_context_win32::do_crypt_universal( // -*- NULL, 0, &required_size, - BCRYPT_BLOCK_PADDING); + padding_mode); !SUCCESS(status_)) { throw cipher_error("Cannot get required size", status_); } @@ -135,7 +136,7 @@ size_t AES_context_win32::do_crypt_universal( // -*- (PUCHAR)dst, (ULONG)cb_dst, &required_size, - BCRYPT_BLOCK_PADDING); + padding_mode); !SUCCESS(status_)) { throw cipher_error("BCryptEncrypt failed", status_); } diff --git a/src/common/helpers.hpp b/src/common/helpers.hpp index 63763ac..13c999b 100755 --- a/src/common/helpers.hpp +++ b/src/common/helpers.hpp @@ -26,7 +26,7 @@ namespace struct decay_string : public std::string { using base_t = std::string; constexpr decay_string() : base_t() {} - decay_string(base_t &&str) noexcept : base_t(std::move(str)) {} + constexpr decay_string(base_t &&str) noexcept : base_t(std::move(str)) {} operator const char *() const noexcept { return this->data(); } operator std::string_view() const noexcept { return {this->data(), this->size()}; } }; diff --git a/src/main.cpp b/src/main.cpp index 402876f..dd1ff75 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4,6 +4,11 @@ Change Log + Version 0.5.0 + - Support of ReplayGain and retagging + - Tags in the audio content and the embedded JSON metainfo are left untouched. + Retagging works on top of them by introduce new overwrite fields. + Version 0.4.1 - Concurrency support for batch conversion - Add progress UI for batch conversion diff --git a/src/meta_process.cpp b/src/meta_process.cpp index 370e931..ebdee45 100644 --- a/src/meta_process.cpp +++ b/src/meta_process.cpp @@ -116,7 +116,21 @@ void meta_processor::update_by_json(const nlohmann::json &json, bool overwriting } }; -#define reflect_single(field, TYPE) [&](const json_t &j) { update_v(field, j.get()); }; + // NOTE: I found an abnormal case that albumPicId is a number instead of string. + // So I deside to test every possible numeric type and try to convert them. + +#define reflect_single(field, TYPE) \ + [&](const json_t &j) { \ + try { \ + update_v(field, j.get()); \ + } catch (const json_t::type_error &) { \ + if constexpr (std::is_same_v) { \ + update_v(field, std::to_string(j.get())); \ + } else if constexpr (std::is_same_v) { \ + update_v(field, std::stoull(j.get())); \ + } \ + } \ + } #define reflect_multi_string(field) \ [&](const json_t &j) { \ if (!j.is_array()) { \ diff --git a/src/meta_process.hpp b/src/meta_process.hpp old mode 100644 new mode 100755 index 56e898e..7d6cbfd --- a/src/meta_process.hpp +++ b/src/meta_process.hpp @@ -32,8 +32,7 @@ namespace fb2k_ncm template consteval static bool opt_is_multi() { - using CT = std::remove_cvref_t())>; - if constexpr (requires { CT{}.~unordered_set(); }) { + if constexpr (requires(T t) { t->~unordered_set(); }) { return true; } else { return false; @@ -47,9 +46,11 @@ namespace fb2k_ncm concept multiT = opt_is_multi(); consteval void traits_tests() { - static_assert(singleT, "check your template implementation"); - static_assert(multiT, "check your template implementation"); + using ST = decltype(uniform_meta_st{}.album); + using MT = decltype(uniform_meta_st{}.genre); using artistT = decltype(uniform_meta_st{}.artist); + static_assert(singleT, "check your template implementation"); + static_assert(multiT, "check your template implementation"); static_assert(!singleT && !multiT, "check your template implementation"); } } // namespace diff --git a/src/ncm_file.cpp b/src/ncm_file.cpp index f0c9f2a..15ff662 100755 --- a/src/ncm_file.cpp +++ b/src/ncm_file.cpp @@ -44,6 +44,21 @@ inline void ncm_file::throw_format_error(const std::string &extra) { throw_format_error(extra.c_str()); } +auto ncm_file::make_seek_guard(abort_callback &p_abort) { + auto defer = + [this, &p_abort, p = source_->get_position(p_abort), off = parsed_file_.audio_content_offset, &parsed = parsed_file_](...) { + // RAII guard, will seek back when function returns + if (p > off) { // lands in audio + source_->seek(parsed.audio_content_offset + (p - off), p_abort); + } else { + source_->seek(p, p_abort); + } + }; + // NOTE: std::unique_ptr doesn't work because of its special treatment of nullptr. + // defer function will not be called if a nullptr is being "deleted" + return std::shared_ptr(nullptr, defer); +} + t_size fb2k_ncm::ncm_file::read(void *p_buffer, t_size p_bytes, abort_callback &p_abort) { ensure_audio_offset(); ENSURE_DECRYPTOR(); @@ -64,7 +79,6 @@ t_size fb2k_ncm::ncm_file::read(void *p_buffer, t_size p_bytes, abort_callback & return total; } -/// @attention This function is not implemented / not in use void fb2k_ncm::ncm_file::write(const void *p_buffer, t_size p_bytes, abort_callback &p_abort) { ensure_audio_offset(); auto source_pos = source_->get_position(p_abort); @@ -128,21 +142,6 @@ t_filetimestamp fb2k_ncm::ncm_file::get_timestamp(abort_callback &p_abort) { return source_->get_timestamp(p_abort); } -auto ncm_file::make_seek_guard(abort_callback &p_abort) { - auto defer = - [this, &p_abort, p = source_->get_position(p_abort), off = parsed_file_.audio_content_offset, &parsed = parsed_file_](...) { - // RAII guard, will seek back when function returns - if (p > off) { // lands in audio - source_->seek(parsed.audio_content_offset + (p - off), p_abort); - } else { - source_->seek(p, p_abort); - } - }; - // NOTE: std::unique_ptr doesn't work because of its special treatment of nullptr. - // defer function will not be called if a nullptr is being "deleted" - return std::shared_ptr(nullptr, defer); -} - void ncm_file::parse(uint16_t to_parse /* = 0xff*/) { // NOTE: @@ -237,7 +236,7 @@ void ncm_file::parse(uint16_t to_parse /* = 0xff*/) { if (!meta_json_.is_object()) { WARN_LOG("Failed to parse meta info of ncm file: ", this->path()); } else { - DEBUG_LOG("Parsed NCM Meta: ", meta_json_.dump(2)); + // DEBUG_LOG("Parsed NCM Meta: ", meta_json_.dump(2)); // overwrite takes effect when get_info() => meta_processor::update() } } @@ -287,7 +286,7 @@ bool ncm_file::save_raw_audio(const char *to_dir, abort_callback &p_abort) { output.add_filename(pfc::string_filename(this->path())); output += ext(); - auto _seek_guard_ = make_seek_guard(p_abort); + auto _seek_guard_ = make_seek_guard(fb2k::noAbort); // NOTE: // If g_open_write_new() opens a file that is being played, the playback will be broken, and the file content will be truncated. @@ -299,8 +298,8 @@ bool ncm_file::save_raw_audio(const char *to_dir, abort_callback &p_abort) { try { file_ptr file_raw; filesystem::g_open_write_new(file_raw, output, p_abort); - - if (auto size = file_v2::g_transfer(this, file_raw.get_ptr(), get_size(p_abort), p_abort); size == get_size(p_abort)) { + this->seek(0, p_abort); + if (auto size = file_v2::g_transfer(this, file_raw.get_ptr(), this->get_size(p_abort), p_abort); size == this->get_size(p_abort)) { DEBUG_LOG("Extraction done: ", output); path_raw_saved_to_ = output; return true; @@ -351,7 +350,7 @@ void ncm_file::overwrite_meta(const nlohmann::json &meta, abort_callback &p_abor size_t meta_aligned_size = cipher::aligned(meta_str_to_write.size()); auto _step1_handle_padding = [&] { - uint8_t padding = meta_aligned_size - meta_str_to_write.size(); + uint8_t padding = static_cast(meta_aligned_size - meta_str_to_write.size()); meta_str_to_write.reserve(meta_aligned_size); for (auto i = meta_str_to_write.size(); i < meta_aligned_size; ++i) { meta_str_to_write.push_back(padding); diff --git a/src/stdafx.h b/src/stdafx.h index cddca09..a404bc9 100644 --- a/src/stdafx.h +++ b/src/stdafx.h @@ -10,4 +10,4 @@ #include "foobar2000/SDK/foobar2000.h" #endif -#define PEOJECT_HOST_REPO "https://github.com/pnck/foo_input_ncm" \ No newline at end of file +#define PEOJECT_HOST_REPO "https://github.com/pnck/foo_input_ncm"