diff options
11 files changed, 287 insertions, 74 deletions
diff --git a/tools/depends/native/TexturePacker/src/decoder/GIFDecoder.cpp b/tools/depends/native/TexturePacker/src/decoder/GIFDecoder.cpp index 3ddb6a575a..5bdfacd4eb 100644 --- a/tools/depends/native/TexturePacker/src/decoder/GIFDecoder.cpp +++ b/tools/depends/native/TexturePacker/src/decoder/GIFDecoder.cpp @@ -33,6 +33,8 @@ bool GIFDecoder::CanDecode(const std::string &filename) bool GIFDecoder::LoadFile(const std::string &filename, DecodedFrames &frames) { int n = 0; + bool result = false; + GifHelper *gifImage = new GifHelper(); if (gifImage->LoadGif(filename.c_str())) { @@ -55,33 +57,20 @@ bool GIFDecoder::LoadFile(const std::string &filename, DecodedFrames &frames) frame.rgbaImage.bbp = 32; frame.rgbaImage.pitch = pitch; frame.delay = extractedFrames[i]->m_delay; + frame.decoder = this; frames.frameList.push_back(frame); } } - frames.user = gifImage; - frames.destroyFN = &gifDestroyFN; - return true; - } - else - { - delete gifImage; - return false; + result = true; } + delete gifImage; + return result; } -void GIFDecoder::FreeDecodedFrames(DecodedFrames &frames) -{ - for (unsigned int i = 0; i < frames.frameList.size(); i++) - { - delete [] frames.frameList[i].rgbaImage.pixels; - } - delete (GifHelper *)frames.user; - frames.clear(); -} -void GIFDecoder::gifDestroyFN(void* user) +void GIFDecoder::FreeDecodedFrame(DecodedFrame &frame) { - delete (GifHelper *)user; + delete [] frame.rgbaImage.pixels; } void GIFDecoder::FillSupportedExtensions() diff --git a/tools/depends/native/TexturePacker/src/decoder/GIFDecoder.h b/tools/depends/native/TexturePacker/src/decoder/GIFDecoder.h index c311ddaa82..8f0b42d822 100644 --- a/tools/depends/native/TexturePacker/src/decoder/GIFDecoder.h +++ b/tools/depends/native/TexturePacker/src/decoder/GIFDecoder.h @@ -28,11 +28,9 @@ class GIFDecoder : public IDecoder ~GIFDecoder() override = default; bool CanDecode(const std::string &filename) override; bool LoadFile(const std::string &filename, DecodedFrames &frames) override; - void FreeDecodedFrames(DecodedFrames &frames) override; + void FreeDecodedFrame(DecodedFrame &frame) override; const char* GetImageFormatName() override { return "GIF"; } const char* GetDecoderName() override { return "libgif"; } protected: void FillSupportedExtensions() override; - private: - static void gifDestroyFN(void* user); }; diff --git a/tools/depends/native/TexturePacker/src/decoder/IDecoder.h b/tools/depends/native/TexturePacker/src/decoder/IDecoder.h index 6e68aba1f1..c9ac346514 100644 --- a/tools/depends/native/TexturePacker/src/decoder/IDecoder.h +++ b/tools/depends/native/TexturePacker/src/decoder/IDecoder.h @@ -23,6 +23,34 @@ #include <string> #include <vector> +/* forward declarations */ + +class DecodedFrame; +class DecodedFrames; + +class IDecoder +{ + public: + virtual ~IDecoder() = default; + virtual bool CanDecode(const std::string &filename) = 0; + virtual bool LoadFile(const std::string &filename, DecodedFrames &frames) = 0; + virtual void FreeDecodedFrame(DecodedFrame &frame) = 0; + virtual const char* GetImageFormatName() = 0; + virtual const char* GetDecoderName() = 0; + + const std::vector<std::string>& GetSupportedExtensions() + { + m_supportedExtensions.clear(); + FillSupportedExtensions(); + return m_supportedExtensions; + } + + protected: + virtual void FillSupportedExtensions() = 0; + //fill this with extensions in FillSupportedExtensions like ".png" + std::vector<std::string> m_supportedExtensions; +}; + class RGBAImage { public: @@ -41,6 +69,7 @@ public: DecodedFrame() = default; RGBAImage rgbaImage; /* rgbaimage for this frame */ int delay = 0; /* Frame delay in ms */ + IDecoder* decoder = nullptr; /* Pointer to decoder */ }; class DecodedFrames @@ -48,43 +77,22 @@ class DecodedFrames public: DecodedFrames() = default; std::vector<DecodedFrame> frameList; - void* user = nullptr; /* used internally*/ - void (*destroyFN)(void*) = nullptr; void clear() { for (auto f : frameList) { - delete[] f.rgbaImage.pixels; - } - if (destroyFN) - { - destroyFN(user); + if (f.decoder != NULL) + { + f.decoder->FreeDecodedFrame(f); + } + else + { + fprintf(stderr, + "ERROR: %s - can not determine decoder type for frame!\n", + __FUNCTION__); + } } frameList.clear(); - user = NULL; - } -}; - -class IDecoder -{ - public: - virtual ~IDecoder() = default; - virtual bool CanDecode(const std::string &filename) = 0; - virtual bool LoadFile(const std::string &filename, DecodedFrames &frames) = 0; - virtual void FreeDecodedFrames(DecodedFrames &frames) = 0; - virtual const char* GetImageFormatName() = 0; - virtual const char* GetDecoderName() = 0; - - const std::vector<std::string>& GetSupportedExtensions() - { - m_supportedExtensions.clear(); - FillSupportedExtensions(); - return m_supportedExtensions; } - - protected: - virtual void FillSupportedExtensions() = 0; - //fill this with extensions in FillSupportedExtensions like ".png" - std::vector<std::string> m_supportedExtensions; }; diff --git a/tools/depends/native/TexturePacker/src/decoder/JPGDecoder.cpp b/tools/depends/native/TexturePacker/src/decoder/JPGDecoder.cpp index c2d96a8fa9..ce06d28882 100644 --- a/tools/depends/native/TexturePacker/src/decoder/JPGDecoder.cpp +++ b/tools/depends/native/TexturePacker/src/decoder/JPGDecoder.cpp @@ -86,7 +86,6 @@ bool JPGDecoder::LoadFile(const std::string &filename, DecodedFrames &frames) // Image Size is calculated as (width * height * bytes per pixel = 4 ImageSize = cinfo.image_width * cinfo.image_height * 4; - frames.user = NULL; DecodedFrame frame; frame.rgbaImage.pixels = (char *)new char[ImageSize]; @@ -117,20 +116,18 @@ bool JPGDecoder::LoadFile(const std::string &filename, DecodedFrames &frames) frame.rgbaImage.width = cinfo.image_width; frame.rgbaImage.bbp = 32; frame.rgbaImage.pitch = 4 * cinfo.image_width; + + frame.decoder = this; + frames.frameList.push_back(frame); delete arq; return true; } -void JPGDecoder::FreeDecodedFrames(DecodedFrames &frames) +void JPGDecoder::FreeDecodedFrame(DecodedFrame &frame) { - for (unsigned int i = 0; i < frames.frameList.size(); i++) - { - delete [] frames.frameList[i].rgbaImage.pixels; - } - - frames.clear(); + delete [] frame.rgbaImage.pixels; } void JPGDecoder::FillSupportedExtensions() diff --git a/tools/depends/native/TexturePacker/src/decoder/JPGDecoder.h b/tools/depends/native/TexturePacker/src/decoder/JPGDecoder.h index 30430e79f9..bbf23ba7b3 100644 --- a/tools/depends/native/TexturePacker/src/decoder/JPGDecoder.h +++ b/tools/depends/native/TexturePacker/src/decoder/JPGDecoder.h @@ -28,7 +28,7 @@ class JPGDecoder : public IDecoder ~JPGDecoder() override = default; bool CanDecode(const std::string &filename) override; bool LoadFile(const std::string &filename, DecodedFrames &frames) override; - void FreeDecodedFrames(DecodedFrames &frames) override; + void FreeDecodedFrame(DecodedFrame &frame) override; const char* GetImageFormatName() override { return "JPG"; } const char* GetDecoderName() override { return "libjpeg"; } protected: diff --git a/tools/depends/native/TexturePacker/src/decoder/PNGDecoder.cpp b/tools/depends/native/TexturePacker/src/decoder/PNGDecoder.cpp index b12e55f426..f327400f6b 100644 --- a/tools/depends/native/TexturePacker/src/decoder/PNGDecoder.cpp +++ b/tools/depends/native/TexturePacker/src/decoder/PNGDecoder.cpp @@ -216,7 +216,6 @@ bool PNGDecoder::LoadFile(const std::string &filename, DecodedFrames &frames) // read the png into image_data through row_pointers png_read_image(png_ptr, row_pointers); - frames.user = NULL; DecodedFrame frame; frame.rgbaImage.pixels = (char *)image_data; @@ -224,6 +223,9 @@ bool PNGDecoder::LoadFile(const std::string &filename, DecodedFrames &frames) frame.rgbaImage.width = temp_width; frame.rgbaImage.bbp = 32; frame.rgbaImage.pitch = 4 * temp_width; + + frame.decoder = this; + frames.frameList.push_back(frame); // clean up png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); @@ -231,14 +233,9 @@ bool PNGDecoder::LoadFile(const std::string &filename, DecodedFrames &frames) return true; } -void PNGDecoder::FreeDecodedFrames(DecodedFrames &frames) +void PNGDecoder::FreeDecodedFrame(DecodedFrame &frame) { - for (unsigned int i = 0; i < frames.frameList.size(); i++) - { - delete [] frames.frameList[i].rgbaImage.pixels; - } - - frames.clear(); + delete [] frame.rgbaImage.pixels; } void PNGDecoder::FillSupportedExtensions() diff --git a/tools/depends/native/TexturePacker/src/decoder/PNGDecoder.h b/tools/depends/native/TexturePacker/src/decoder/PNGDecoder.h index 3b62a23e93..c7dba764cb 100644 --- a/tools/depends/native/TexturePacker/src/decoder/PNGDecoder.h +++ b/tools/depends/native/TexturePacker/src/decoder/PNGDecoder.h @@ -28,7 +28,7 @@ class PNGDecoder : public IDecoder ~PNGDecoder() override = default; bool CanDecode(const std::string &filename) override; bool LoadFile(const std::string &filename, DecodedFrames &frames) override; - void FreeDecodedFrames(DecodedFrames &frames) override; + void FreeDecodedFrame(DecodedFrame &frame) override; const char* GetImageFormatName() override { return "PNG"; } const char* GetDecoderName() override { return "libpng"; } protected: diff --git a/xbmc/addons/kodi-dev-kit/include/kodi/tools/CMakeLists.txt b/xbmc/addons/kodi-dev-kit/include/kodi/tools/CMakeLists.txt index 517ea9308e..16b83cb159 100644 --- a/xbmc/addons/kodi-dev-kit/include/kodi/tools/CMakeLists.txt +++ b/xbmc/addons/kodi-dev-kit/include/kodi/tools/CMakeLists.txt @@ -1,4 +1,5 @@ set(HEADERS DllHelper.h + EndTime.h StringUtils.h Thread.h Timer.h) diff --git a/xbmc/addons/kodi-dev-kit/include/kodi/tools/EndTime.h b/xbmc/addons/kodi-dev-kit/include/kodi/tools/EndTime.h new file mode 100644 index 0000000000..ac87cb9d86 --- /dev/null +++ b/xbmc/addons/kodi-dev-kit/include/kodi/tools/EndTime.h @@ -0,0 +1,215 @@ +/* + * Copyright (C) 2005-2020 Team Kodi + * https://kodi.tv + * + * SPDX-License-Identifier: GPL-2.0-or-later + * See LICENSE.md for more information. + */ + +#pragma once + +#ifdef __cplusplus + +#include <chrono> + +namespace kodi +{ +namespace tools +{ + +//============================================================================== +/// @defgroup cpp_kodi_tools_CEndTime class CEndTime +/// @ingroup cpp_kodi_tools +/// @brief **Timeout check**\n +/// Class which makes it easy to check if a specified amount of time has passed. +/// +/// This code uses the support of platform-independent chrono system introduced +/// with C++11. +/// +/// +/// ---------------------------------------------------------------------------- +/// +/// **Example:** +/// ~~~~~~~~~~~~~{.cpp} +/// #include <kodi/tools/EndTime.h> +/// +/// class ATTRIBUTE_HIDDEN CExample +/// { +/// public: +/// CExample() +/// { +/// TimerCall(); +/// } +/// +/// void TimerCall() +/// { +/// fprintf(stderr, "Hello World\n"); +/// CEndTime timer(1000); +/// +/// while (timer.MillisLeft()) +/// { +/// if (timer.IsTimePast()) +/// { +/// fprintf(stderr, "We timed out!\n"); +/// } +/// std::this_thread::sleep_for(std::chrono::milliseconds(10)); +/// } +/// } +/// +/// }; +/// ~~~~~~~~~~~~~ +/// +///@{ +class CEndTime +{ +public: + //============================================================================ + /// @ingroup cpp_kodi_tools_CEndTime + /// @brief Class constructor with no time to expiry set + /// + inline CEndTime() = default; + //============================================================================ + /// @ingroup cpp_kodi_tools_CEndTime + /// @brief Class constructor to set future time when timer has expired + /// + /// @param[in] millisecondsIntoTheFuture the time in the future we cosider this timer as expired + /// + inline explicit CEndTime(unsigned int millisecondsIntoTheFuture) + : m_startTime(std::chrono::system_clock::now().time_since_epoch()), + m_totalWaitTime(std::chrono::milliseconds(millisecondsIntoTheFuture)) + { + } + //---------------------------------------------------------------------------- + + //============================================================================ + /// @ingroup cpp_kodi_tools_CEndTime + /// @brief Set the time in the future we cosider this timer as expired + /// + /// @param[in] millisecondsIntoTheFuture the time in the future we cosider this timer as expired + /// + inline void Set(unsigned int millisecondsIntoTheFuture) + { + using namespace std::chrono; + + m_startTime = system_clock::now().time_since_epoch(); + m_totalWaitTime = milliseconds(millisecondsIntoTheFuture); + } + //---------------------------------------------------------------------------- + + //============================================================================ + /// @ingroup cpp_kodi_tools_CEndTime + /// @brief Check if the expiry time has been reached + /// + /// @return True if the expiry amount of time has past, false otherwise + /// + inline bool IsTimePast() const + { + using namespace std::chrono; + + // timer is infinite + if (m_totalWaitTime.count() == std::numeric_limits<unsigned int>::max()) + return false; + + if (m_totalWaitTime.count() == 0) + return true; + else + return (system_clock::now().time_since_epoch() - m_startTime) >= m_totalWaitTime; + } + //---------------------------------------------------------------------------- + + //============================================================================ + /// @ingroup cpp_kodi_tools_CEndTime + /// @brief The amount of time left till this timer expires + /// + /// @return 0 if the expiry amount of time has past, the numbe rof milliseconds remaining otherwise + /// + inline unsigned int MillisLeft() const + { + using namespace std::chrono; + + // timer is infinite + if (m_totalWaitTime.count() == std::numeric_limits<unsigned int>::max()) + return std::numeric_limits<unsigned int>::max(); + + if (m_totalWaitTime.count() == 0) + return 0; + + auto elapsed = system_clock::now().time_since_epoch() - m_startTime; + + unsigned int timeWaitedAlready = duration_cast<milliseconds>(elapsed).count(); + + if (timeWaitedAlready >= m_totalWaitTime.count()) + return 0; + + return m_totalWaitTime.count() - timeWaitedAlready; + } + //---------------------------------------------------------------------------- + + //============================================================================ + /// @ingroup cpp_kodi_tools_CEndTime + /// @brief Consider this timer expired + /// + inline void SetExpired() + { + using namespace std::chrono; + m_totalWaitTime = milliseconds(0); + } + //---------------------------------------------------------------------------- + + //============================================================================ + /// @ingroup cpp_kodi_tools_CEndTime + /// @brief Set this timer as never expiring + /// + inline void SetInfinite() + { + using namespace std::chrono; + m_totalWaitTime = milliseconds(std::numeric_limits<unsigned int>::max()); + } + //---------------------------------------------------------------------------- + + //============================================================================ + /// @ingroup cpp_kodi_tools_CEndTime + /// @brief Check if the timer has been set to infinite expiry + /// + /// @return True if the expiry has been set as infinite, false otherwise + /// + inline bool IsInfinite(void) const + { + return (m_totalWaitTime.count() == std::numeric_limits<unsigned int>::max()); + } + //---------------------------------------------------------------------------- + + //============================================================================ + /// @ingroup cpp_kodi_tools_CEndTime + /// @brief Get the initial timeout value this timer had + /// + /// @return The initial expiry amount of time this timer had in milliseconds + /// + inline unsigned int GetInitialTimeoutValue(void) const + { + auto value = std::chrono::duration_cast<std::chrono::milliseconds>(m_totalWaitTime); + return value.count(); + } + + //============================================================================ + /// @ingroup cpp_kodi_tools_CEndTime + /// @brief Get the time this timer started + /// + /// @return The time this timer started in milliseconds since epoch + /// + inline uint64_t GetStartTime(void) const + { + auto value = std::chrono::duration_cast<std::chrono::milliseconds>(m_startTime); + return value.count(); + } + //---------------------------------------------------------------------------- + +private: + std::chrono::system_clock::duration m_startTime; + std::chrono::system_clock::duration m_totalWaitTime; +}; + +} /* namespace tools */ +} /* namespace kodi */ + +#endif /* __cplusplus */ diff --git a/xbmc/addons/kodi-dev-kit/include/kodi/versions.h b/xbmc/addons/kodi-dev-kit/include/kodi/versions.h index 0908363884..9ffafab9c6 100644 --- a/xbmc/addons/kodi-dev-kit/include/kodi/versions.h +++ b/xbmc/addons/kodi-dev-kit/include/kodi/versions.h @@ -73,7 +73,7 @@ #define ADDON_GLOBAL_VERSION_NETWORK_DEPENDS "Network.h" \ "c-api/network.h" -#define ADDON_GLOBAL_VERSION_TOOLS "1.0.2" +#define ADDON_GLOBAL_VERSION_TOOLS "1.0.3" #define ADDON_GLOBAL_VERSION_TOOLS_MIN "1.0.0" #define ADDON_GLOBAL_VERSION_TOOLS_XML_ID "kodi.binary.global.tools" #define ADDON_GLOBAL_VERSION_TOOLS_DEPENDS "tools/DllHelper.h" \ diff --git a/xbmc/video/VideoDatabase.cpp b/xbmc/video/VideoDatabase.cpp index b3ae9348e3..41e25b08c7 100644 --- a/xbmc/video/VideoDatabase.cpp +++ b/xbmc/video/VideoDatabase.cpp @@ -8564,9 +8564,17 @@ void CVideoDatabase::GetMoviesByName(const std::string& strSearch, CFileItemList return; if (m_profileManager.GetMasterProfile().getLockMode() != LOCK_MODE_EVERYONE && !g_passwordManager.bMasterUser) - strSQL = PrepareSQL("SELECT movie.idMovie, movie.c%02d, path.strPath, movie.idSet FROM movie INNER JOIN files ON files.idFile=movie.idFile INNER JOIN path ON path.idPath=files.idPath WHERE movie.c%02d LIKE '%%%s%%'", VIDEODB_ID_TITLE, VIDEODB_ID_TITLE, strSearch.c_str()); + strSQL = PrepareSQL("SELECT movie.idMovie, movie.c%02d, path.strPath, movie.idSet FROM movie " + "INNER JOIN files ON files.idFile=movie.idFile INNER JOIN path ON " + "path.idPath=files.idPath " + "WHERE movie.c%02d LIKE '%%%s%%' OR movie.c%02d LIKE '%%%s%%'", + VIDEODB_ID_TITLE, VIDEODB_ID_TITLE, strSearch.c_str(), + VIDEODB_ID_ORIGINALTITLE, strSearch.c_str()); else - strSQL = PrepareSQL("select movie.idMovie,movie.c%02d, movie.idSet from movie where movie.c%02d like '%%%s%%'",VIDEODB_ID_TITLE,VIDEODB_ID_TITLE,strSearch.c_str()); + strSQL = PrepareSQL("SELECT movie.idMovie,movie.c%02d, movie.idSet FROM movie WHERE " + "movie.c%02d like '%%%s%%' OR movie.c%02d LIKE '%%%s%%'", + VIDEODB_ID_TITLE, VIDEODB_ID_TITLE, strSearch.c_str(), + VIDEODB_ID_ORIGINALTITLE, strSearch.c_str()); m_pDS->query( strSQL ); while (!m_pDS->eof()) |