diff --git a/3rdparty/foo_SDK/foobar2000/SDK/abort_callback.h b/3rdparty/foo_SDK/foobar2000/SDK/abort_callback.h index 37ba34f6..cfc772da 100644 --- a/3rdparty/foo_SDK/foobar2000/SDK/abort_callback.h +++ b/3rdparty/foo_SDK/foobar2000/SDK/abort_callback.h @@ -50,6 +50,9 @@ class NOVTABLE abort_callback void waitForEvent(pfc::eventHandle_t evtHandle); //! Waits for an event. Returns once the event became signaled; throw exception_aborted if abort occurred first. void waitForEvent(pfc::event& evt); + + abort_callback( const abort_callback & ) = delete; + void operator=( const abort_callback & ) = delete; protected: abort_callback() {} ~abort_callback() {} @@ -57,49 +60,49 @@ class NOVTABLE abort_callback -//! Implementation of abort_callback interface. +//! Standard implementation of abort_callback interface. class abort_callback_impl : public abort_callback { public: - abort_callback_impl() : m_aborting(false) {} + abort_callback_impl() {} inline void abort() {set_state(true);} inline void set() {set_state(true);} inline void reset() {set_state(false);} void set_state(bool p_state) {m_aborting = p_state; m_event.set_state(p_state);} - bool is_aborting() const {return m_aborting;} + bool is_aborting() const override {return m_aborting;} - abort_callback_event get_abort_event() const {return m_event.get_handle();} + abort_callback_event get_abort_event() const override {return m_event.get_handle();} private: abort_callback_impl(const abort_callback_impl &) = delete; const abort_callback_impl & operator=(const abort_callback_impl&) = delete; - volatile bool m_aborting; + volatile bool m_aborting = false; pfc::event m_event; }; - +//! Alternate abort_callback implementation, supply your own event handle to signal abort. \n +//! Slightly less efficient (is_aborting() polls the event instead of reading a bool variable). class abort_callback_usehandle : public abort_callback { public: abort_callback_usehandle( abort_callback_event handle ) : m_handle(handle) {} - bool is_aborting() const; - abort_callback_event get_abort_event() const { return m_handle; } + bool is_aborting() const override; + abort_callback_event get_abort_event() const override { return m_handle; } private: const abort_callback_event m_handle; }; //! Dummy abort_callback that never gets aborted. \n -//! Slightly more efficient than the regular one especially when you need to regularly create temporary instances of it. +//! Note that there's no need to create instances of it, use shared fb2k::noAbort object instead. class abort_callback_dummy : public abort_callback { public: - abort_callback_dummy() : m_event(GetInfiniteWaitEvent()) {} - bool is_aborting() const { return false; } + bool is_aborting() const override { return false; } - abort_callback_event get_abort_event() const { return m_event;} + abort_callback_event get_abort_event() const override { return m_event;} private: - const abort_callback_event m_event; + const abort_callback_event m_event = GetInfiniteWaitEvent(); }; } @@ -117,6 +120,7 @@ using namespace foobar2000_io; namespace fb2k { - // A shared abort_callback_dummy instance + //! A shared abort_callback_dummy instance. \n + //! Use when some function requires an abort_callback& and you don't have one: somefunc(fb2k::noAbort); extern abort_callback_dummy noAbort; } diff --git a/3rdparty/foo_SDK/foobar2000/SDK/advconfig.cpp b/3rdparty/foo_SDK/foobar2000/SDK/advconfig.cpp index 81509c68..1034d227 100644 --- a/3rdparty/foo_SDK/foobar2000/SDK/advconfig.cpp +++ b/3rdparty/foo_SDK/foobar2000/SDK/advconfig.cpp @@ -76,10 +76,6 @@ void advconfig_entry_checkbox_impl::set_data_raw(stream_reader* p_stream, t_size } #endif -pfc::string8 fb2k::advconfig_autoName(const GUID& id) { - return pfc::format("advconfig.unnamed.", pfc::print_guid(id)); -} - void advconfig_entry_string_impl::reset() { fb2k::configStore::get()->deleteConfigString(m_varName); } diff --git a/3rdparty/foo_SDK/foobar2000/SDK/advconfig.h b/3rdparty/foo_SDK/foobar2000/SDK/advconfig.h index 12da216a..616db76e 100644 --- a/3rdparty/foo_SDK/foobar2000/SDK/advconfig.h +++ b/3rdparty/foo_SDK/foobar2000/SDK/advconfig.h @@ -24,21 +24,22 @@ class NOVTABLE advconfig_entry : public service_base { static const GUID guid_root; static const GUID guid_branch_tagging,guid_branch_decoding,guid_branch_tools,guid_branch_playback,guid_branch_display,guid_branch_debug, guid_branch_tagging_general, guid_branch_converter; + // \since 2.0 - static const GUID guid_branch_vis; + static const GUID guid_branch_vis, guid_branch_general; FB2K_MAKE_SERVICE_INTERFACE_ENTRYPOINT(advconfig_entry); }; -//! Creates a new branch in Advanced Preferences. \n +//! Declares a new branch in Advanced Preferences. \n //! Implementation: see advconfig_branch_impl / advconfig_branch_factory. class NOVTABLE advconfig_branch : public advconfig_entry { public: FB2K_MAKE_SERVICE_INTERFACE(advconfig_branch,advconfig_entry); }; -//! Creates a checkbox/radiocheckbox entry in Advanced Preferences. \n +//! Declares a checkbox/radiocheckbox entry in Advanced Preferences. \n //! The difference between checkboxes and radiocheckboxes is different icon (obviously) and that checking a radiocheckbox unchecks all other radiocheckboxes in the same branch. \n //! Implementation: see advconfig_entry_checkbox_impl / advconfig_checkbox_factory_t. class NOVTABLE advconfig_entry_checkbox : public advconfig_entry { @@ -52,6 +53,7 @@ class NOVTABLE advconfig_entry_checkbox : public advconfig_entry { FB2K_MAKE_SERVICE_INTERFACE(advconfig_entry_checkbox,advconfig_entry); }; +//! Extension to advconfig_entry_checkbox, adds default state and preferences flags. class NOVTABLE advconfig_entry_checkbox_v2 : public advconfig_entry_checkbox { FB2K_MAKE_SERVICE_INTERFACE(advconfig_entry_checkbox_v2, advconfig_entry_checkbox) public: @@ -59,7 +61,7 @@ class NOVTABLE advconfig_entry_checkbox_v2 : public advconfig_entry_checkbox { virtual t_uint32 get_preferences_flags() {return 0;} //signals whether changing this setting should trigger playback restart or app restart; see: preferences_state::* constants }; -//! Creates a string/integer editbox entry in Advanced Preferences.\n +//! Declares a string/integer editbox entry in Advanced Preferences.\n //! Implementation: see advconfig_entry_string_impl / advconfig_string_factory. class NOVTABLE advconfig_entry_string : public advconfig_entry { public: @@ -77,6 +79,7 @@ class NOVTABLE advconfig_entry_string : public advconfig_entry { FB2K_MAKE_SERVICE_INTERFACE(advconfig_entry_string,advconfig_entry); }; +//! Extension to advconfig_entry_string, adds default state, validation and preferences flags. class NOVTABLE advconfig_entry_string_v2 : public advconfig_entry_string { FB2K_MAKE_SERVICE_INTERFACE(advconfig_entry_string_v2, advconfig_entry_string) public: @@ -84,16 +87,3 @@ class NOVTABLE advconfig_entry_string_v2 : public advconfig_entry_string { virtual void validate(pfc::string_base & val) {} virtual t_uint32 get_preferences_flags() {return 0;} //signals whether changing this setting should trigger playback restart or app restart; see: preferences_state::* constants }; - - -//! Not currently used, reserved for future use. -class NOVTABLE advconfig_entry_enum : public advconfig_entry { -public: - virtual t_size get_value_count() = 0; - virtual void enum_value(pfc::string_base & p_out,t_size p_index) = 0; - virtual t_size get_state() = 0; - virtual void set_state(t_size p_value) = 0; - - FB2K_MAKE_SERVICE_INTERFACE(advconfig_entry_enum,advconfig_entry); -}; - diff --git a/3rdparty/foo_SDK/foobar2000/SDK/advconfig_impl.h b/3rdparty/foo_SDK/foobar2000/SDK/advconfig_impl.h index 8079f813..fa456a43 100644 --- a/3rdparty/foo_SDK/foobar2000/SDK/advconfig_impl.h +++ b/3rdparty/foo_SDK/foobar2000/SDK/advconfig_impl.h @@ -1,5 +1,7 @@ #pragma once +// advconfig_impl.h : mainline (foobar2000 v2.0) implementation of advconfig objects + #include "advconfig.h" //! Standard implementation of advconfig_branch. \n @@ -138,6 +140,7 @@ class advconfig_string_factory : public service_factory_single_t(p_name, fb2k::advconfig_autoName(p_guid), p_guid, p_parent, p_priority, p_initialstate, p_prefFlags) {} void get(pfc::string_base& out) { get_static_instance().get_state(out); } + pfc::string8 get() { pfc::string8 temp; get(temp); return temp; } void set(const char* in) { get_static_instance().set_state(in); } }; diff --git a/3rdparty/foo_SDK/foobar2000/SDK/advconfig_impl_legacy.h b/3rdparty/foo_SDK/foobar2000/SDK/advconfig_impl_legacy.h index b20e2c09..ce136e4b 100644 --- a/3rdparty/foo_SDK/foobar2000/SDK/advconfig_impl_legacy.h +++ b/3rdparty/foo_SDK/foobar2000/SDK/advconfig_impl_legacy.h @@ -1,8 +1,22 @@ #pragma once +// advconfig_impl_legacy.h : legacy (foobar2000 v1.x compatible) implementation of advconfig objects + #include "cfg_var_legacy.h" using namespace cfg_var_legacy; +namespace fb2k { + pfc::string8 advconfig_autoName(const GUID&); +} + +#if FOOBAR2000_SUPPORT_CFG_VAR_DOWNGRADE +#define ADVCONFIG_DOWNGRADE { this->get_static_instance().downgrade_set_name(configStoreName); } +#define ADVCONFIG_DOWNGRADE_AUTO { this->get_static_instance().downgrade_set_name( fb2k::advconfig_autoName(p_guid) ); } +#else +#define ADVCONFIG_DOWNGRADE {(void)configStoreName;} +#define ADVCONFIG_DOWNGRADE_AUTO +#endif + //! Standard implementation of advconfig_entry_checkbox. \n class advconfig_entry_checkbox_impl : public advconfig_entry_checkbox_v2 { public: @@ -22,6 +36,9 @@ class advconfig_entry_checkbox_impl : public advconfig_entry_checkbox_v2 { bool get_state_() const { return m_state; } bool get_default_state_() const { return m_initialstate; } +#if FOOBAR2000_SUPPORT_CFG_VAR_DOWNGRADE + void downgrade_set_name(const char * arg) { m_state.downgrade_set_name(arg); } +#endif private: const pfc::string8 m_name; const bool m_initialstate; @@ -53,14 +70,26 @@ class advconfig_checkbox_factory_common : public service_factory_single_t class advconfig_checkbox_factory_t : public advconfig_checkbox_factory_common { public: advconfig_checkbox_factory_t(const char* p_name, const GUID& p_guid, const GUID& p_parent, double p_priority, bool p_initialstate) - : advconfig_checkbox_factory_common(p_name, p_guid, p_parent, p_priority, p_initialstate, p_is_radio, prefFlags) {} -}; - - -//! Standard advconfig_entry_string implementation. Use advconfig_string_factory to register your own string entries in Advanced Preferences instead of using this class directly. -class advconfig_entry_string_impl : public advconfig_entry_string_v2 { -public: - advconfig_entry_string_impl(const char* p_name, const GUID& p_guid, const GUID& p_parent, double p_priority, const char* p_initialstate, t_uint32 p_prefFlags) - : m_name(p_name), m_parent(p_parent), m_priority(p_priority), m_initialstate(p_initialstate), m_state(p_guid, p_initialstate), m_prefFlags(p_prefFlags) {} - void get_name(pfc::string_base& p_out) { p_out = m_name; } - GUID get_guid() { return m_state.get_guid(); } - GUID get_parent() { return m_parent; } - void reset() { core_api::ensure_main_thread(); m_state = m_initialstate; } - double get_sort_priority() { return m_priority; } - void get_state(pfc::string_base& p_out) { core_api::ensure_main_thread(); p_out = m_state; } - void set_state(const char* p_string, t_size p_length = ~0) { core_api::ensure_main_thread(); m_state.set_string(p_string, p_length); } - t_uint32 get_flags() { return 0; } - void get_default_state(pfc::string_base& out) { out = m_initialstate; } - t_uint32 get_preferences_flags() { return m_prefFlags; } -private: - const pfc::string8 m_initialstate, m_name; - cfg_string m_state; - const double m_priority; - const GUID m_parent; - const t_uint32 m_prefFlags; -}; - -//! Service factory helper around standard advconfig_entry_string implementation. Use this class to register your own string entries in Advanced Preferences. \n -//! Usage: static advconfig_string_factory mystring(name, itemID, branchID, priority, initialValue); -class advconfig_string_factory : public service_factory_single_t { -public: - advconfig_string_factory(const char* p_name, const GUID& p_guid, const GUID& p_parent, double p_priority, const char* p_initialstate, t_uint32 p_prefFlags = 0) - : service_factory_single_t(p_name, p_guid, p_parent, p_priority, p_initialstate, p_prefFlags) {} - - void get(pfc::string_base& out) { get_static_instance().get_state(out); } - void set(const char* in) { get_static_instance().set_state(in); } + : advconfig_checkbox_factory_common(p_name, p_guid, p_parent, p_priority, p_initialstate, p_is_radio, prefFlags) { + ADVCONFIG_DOWNGRADE_AUTO; + } + advconfig_checkbox_factory_t(const char* p_name, const char * configStoreName, const GUID& p_guid, const GUID& p_parent, double p_priority, bool p_initialstate) + : advconfig_checkbox_factory_common(p_name, p_guid, p_parent, p_priority, p_initialstate, p_is_radio, prefFlags) { + ADVCONFIG_DOWNGRADE; + } }; - //! Special advconfig_entry_string implementation - implements integer entries. Use advconfig_integer_factory to register your own integer entries in Advanced Preferences instead of using this class directly. template class advconfig_entry_integer_impl_ : public advconfig_entry_string_v2 { @@ -132,9 +131,12 @@ class advconfig_entry_integer_impl_ : public advconfig_entry_string_v2 { format(out, m_initval); } void validate(pfc::string_base& val) { - format(val, pfc::clip_t(myATOI(val, ~0), m_min, m_max)); + format(val, pfc::clip_t(myATOI(val, SIZE_MAX), m_min, m_max)); } t_uint32 get_preferences_flags() { return m_prefFlags; } +#if FOOBAR2000_SUPPORT_CFG_VAR_DOWNGRADE + void downgrade_set_name(const char * arg) { m_state.downgrade_set_name(arg); } +#endif private: static void format(pfc::string_base& out, int_t v) { if (is_signed()) out = pfc::format_int(v).get_ptr(); @@ -164,7 +166,14 @@ class advconfig_integer_factory_ : public service_factory_single_t >(p_name, p_guid, p_parent, p_priority, p_initialstate, p_min, p_max, p_prefFlags) {} + : service_factory_single_t >(p_name, p_guid, p_parent, p_priority, p_initialstate, p_min, p_max, p_prefFlags) { + ADVCONFIG_DOWNGRADE_AUTO; + } + + advconfig_integer_factory_(const char* p_name, const char * configStoreName, const GUID& p_guid, const GUID& p_parent, double p_priority, t_uint64 p_initialstate, t_uint64 p_min, t_uint64 p_max, t_uint32 p_prefFlags = 0) + : service_factory_single_t >(p_name, p_guid, p_parent, p_priority, p_initialstate, p_min, p_max, p_prefFlags) { + ADVCONFIG_DOWNGRADE; + } int_t get() const { return this->get_static_instance().get_state_int(); } void set(int_t val) { this->get_static_instance().set_state_int(val); } @@ -177,10 +186,10 @@ typedef advconfig_integer_factory_ advconfig_integer_factory; typedef advconfig_integer_factory_ advconfig_signed_integer_factory; -//! Special version if advconfig_entry_string_impl that allows the value to be retrieved from worker threads. -class advconfig_entry_string_impl_MT : public advconfig_entry_string_v2 { +//! Standard advconfig_entry_string implementation +class advconfig_entry_string_impl : public advconfig_entry_string_v2 { public: - advconfig_entry_string_impl_MT(const char* p_name, const GUID& p_guid, const GUID& p_parent, double p_priority, const char* p_initialstate, t_uint32 p_prefFlags) + advconfig_entry_string_impl(const char* p_name, const GUID& p_guid, const GUID& p_parent, double p_priority, const char* p_initialstate, t_uint32 p_prefFlags) : m_name(p_name), m_parent(p_parent), m_priority(p_priority), m_initialstate(p_initialstate), m_state(p_guid, p_initialstate), m_prefFlags(p_prefFlags) {} void get_name(pfc::string_base& p_out) { p_out = m_name; } GUID get_guid() { return m_state.get_guid(); } @@ -194,13 +203,16 @@ class advconfig_entry_string_impl_MT : public advconfig_entry_string_v2 { inReadSync(m_sync); p_out = m_state; } - void set_state(const char* p_string, t_size p_length = ~0) { + void set_state(const char* p_string, t_size p_length = SIZE_MAX) { inWriteSync(m_sync); m_state.set_string(p_string, p_length); } t_uint32 get_flags() { return 0; } void get_default_state(pfc::string_base& out) { out = m_initialstate; } t_uint32 get_preferences_flags() { return m_prefFlags; } +#if FOOBAR2000_SUPPORT_CFG_VAR_DOWNGRADE + void downgrade_set_name(const char * arg) { m_state.downgrade_set_name(arg); } +#endif private: const pfc::string8 m_initialstate, m_name; cfg_string m_state; @@ -210,17 +222,26 @@ class advconfig_entry_string_impl_MT : public advconfig_entry_string_v2 { const t_uint32 m_prefFlags; }; -//! Special version if advconfig_string_factory that allows the value to be retrieved from worker threads. -class advconfig_string_factory_MT : public service_factory_single_t { +//! Service factory helper around standard advconfig_entry_string implementation. Use this class to register your own string entries in Advanced Preferences. \n +//! Usage: static advconfig_string_factory mystring(name, itemID, branchID, priority, initialValue); +class advconfig_string_factory : public service_factory_single_t { public: - advconfig_string_factory_MT(const char* p_name, const GUID& p_guid, const GUID& p_parent, double p_priority, const char* p_initialstate, t_uint32 p_prefFlags = 0) - : service_factory_single_t(p_name, p_guid, p_parent, p_priority, p_initialstate, p_prefFlags) {} + advconfig_string_factory(const char* p_name, const GUID& p_guid, const GUID& p_parent, double p_priority, const char* p_initialstate, t_uint32 p_prefFlags = 0) + : service_factory_single_t(p_name, p_guid, p_parent, p_priority, p_initialstate, p_prefFlags) { + ADVCONFIG_DOWNGRADE_AUTO; + } + advconfig_string_factory(const char* p_name, const char * configStoreName, const GUID& p_guid, const GUID& p_parent, double p_priority, const char* p_initialstate, t_uint32 p_prefFlags = 0) + : service_factory_single_t(p_name, p_guid, p_parent, p_priority, p_initialstate, p_prefFlags) { + ADVCONFIG_DOWNGRADE; + } void get(pfc::string_base& out) { get_static_instance().get_state(out); } void set(const char* in) { get_static_instance().set_state(in); } }; - +// No more separate _MT versions, readWriteLock overhead is irrelevant +typedef advconfig_entry_string_impl advconfig_entry_string_impl_MT; +typedef advconfig_string_factory advconfig_string_factory_MT; /* @@ -235,3 +256,7 @@ class advconfig_string_factory_MT : public service_factory_single_t f) (void)taskref; // retain until here } ); } + +abort_callback& fb2k::mainAborter() { + return async_task_manager::get()->get_aborter(); +} + +app_close_blocking_task_impl::app_close_blocking_task_impl(const char * name) : m_name(name) { + PFC_ASSERT( core_api::is_main_thread() ); + app_close_blocking_task_manager::get()->register_task(this); +} + +app_close_blocking_task_impl::~app_close_blocking_task_impl() { + PFC_ASSERT( core_api::is_main_thread() ); + app_close_blocking_task_manager::get()->unregister_task(this); +} + +void app_close_blocking_task_impl::query_task_name(pfc::string_base & out) { + out = m_name; +} + +void app_close_blocking_task_impl_dynamic::toggle_blocking(bool state) { + PFC_ASSERT( core_api::is_main_thread() ); + if (state != m_taskActive) { + auto api = app_close_blocking_task_manager::get(); + if (state) api->register_task(this); + else api->unregister_task(this); + m_taskActive = state; + } +} + +void app_close_blocking_task_impl_dynamic::query_task_name(pfc::string_base& out) { + out = m_name; +} diff --git a/3rdparty/foo_SDK/foobar2000/SDK/app_close_blocker.h b/3rdparty/foo_SDK/foobar2000/SDK/app_close_blocker.h index 9c96122e..aed5bfd5 100644 --- a/3rdparty/foo_SDK/foobar2000/SDK/app_close_blocker.h +++ b/3rdparty/foo_SDK/foobar2000/SDK/app_close_blocker.h @@ -19,6 +19,9 @@ class NOVTABLE app_close_blocker : public service_base //! Implementation: it's recommended that you derive from app_close_blocking_task_impl class instead of deriving from app_close_blocking_task directly, it manages registration/unregistration behind-the-scenes. class NOVTABLE app_close_blocking_task { public: + //! Retrieves user-friendly name of the task to be shown to the user, should the user try to close foobar2000 while the task is active. \n + //! Implementation note: this will NOT be called from register_task() or unregister_task(), only in response to user attempting to close foobar2000. \n + //! Common helper implementations of app_close_blocking_task register from base class constructor while intended query_task_name() override is not yet in place. virtual void query_task_name(pfc::string_base & out) = 0; protected: @@ -28,42 +31,46 @@ class NOVTABLE app_close_blocking_task { PFC_CLASS_NOT_COPYABLE_EX(app_close_blocking_task); }; -//! Entrypoint class for registering app_close_blocking_task instances. Introduced in 0.9.5.1. \n -//! Usage: static_api_ptr_t(). May fail if user runs pre-0.9.5.1. It's recommended that you use app_close_blocking_task_impl class instead of calling app_close_blocking_task_manager directly. +//! Entrypoint class for registering app_close_blocking_task instances. \n +//! You can use app_close_blocking_task_impl to call this automatically with your object. class NOVTABLE app_close_blocking_task_manager : public service_base { FB2K_MAKE_SERVICE_COREAPI(app_close_blocking_task_manager); public: + //! Registers a task object. \n + //! Main thread only. virtual void register_task(app_close_blocking_task * task) = 0; + //! Unregisters a task object. \n + //! Main thread only. virtual void unregister_task(app_close_blocking_task * task) = 0; }; //! Helper; implements standard functionality required by app_close_blocking_task implementations - registers/unregisters the task on construction/destruction. class app_close_blocking_task_impl : public app_close_blocking_task { public: - app_close_blocking_task_impl() { app_close_blocking_task_manager::get()->register_task(this);} - ~app_close_blocking_task_impl() { app_close_blocking_task_manager::get()->unregister_task(this);} + app_close_blocking_task_impl(const char * name = ""); + ~app_close_blocking_task_impl(); - void query_task_name(pfc::string_base & out) { out = ""; } + //! Override me, or provide name to constructor + void query_task_name(pfc::string_base & out) override; + + app_close_blocking_task_impl( const app_close_blocking_task_impl & ) = delete; + void operator=(const app_close_blocking_task_impl & ) = delete; +private: + const char * const m_name; }; class app_close_blocking_task_impl_dynamic : public app_close_blocking_task { public: - app_close_blocking_task_impl_dynamic() : m_taskActive() {} + app_close_blocking_task_impl_dynamic(const char * name = "") : m_name(name) {} ~app_close_blocking_task_impl_dynamic() { toggle_blocking(false); } - void query_task_name(pfc::string_base & out) { out = ""; } + //! Override me, or provide name to constructor + void query_task_name(pfc::string_base & out) override; -protected: - void toggle_blocking(bool state) { - if (state != m_taskActive) { - auto api = app_close_blocking_task_manager::get(); - if (state) api->register_task(this); - else api->unregister_task(this); - m_taskActive = state; - } - } + void toggle_blocking(bool state); private: - bool m_taskActive; + bool m_taskActive = false; + const char * const m_name; }; diff --git a/3rdparty/foo_SDK/foobar2000/SDK/archive.h b/3rdparty/foo_SDK/foobar2000/SDK/archive.h index 7d88ec0b..d2ad63e7 100644 --- a/3rdparty/foo_SDK/foobar2000/SDK/archive.h +++ b/3rdparty/foo_SDK/foobar2000/SDK/archive.h @@ -5,6 +5,10 @@ namespace foobar2000_io { class archive; + //! Callback passed to archive listing methods. \n + //! For backwards compatibility, this inherits with abort_callback as well. \n + //! When implementiong, you must override abort_callback methods redirecting them to your abort_callback. \n + //! It is recommended to use lambda-based archive_list helper instead of implementing this interface. class NOVTABLE archive_callback : public abort_callback { public: virtual bool on_entry(archive * owner,const char * url,const t_filestats & p_stats,const service_ptr_t & p_reader) = 0; @@ -17,10 +21,11 @@ namespace foobar2000_io { typedef std::function list_func_t; //! Lists archive contents. \n - //! May be called with any path, not only path accepted by is_our_archive. + //! May be called with any path, not only path accepted by is_our_archive. \n + //! It is strongly recommended to use the lambda_based archive_list() helper instead of calling this directly. virtual void archive_list(const char * p_path,const service_ptr_t & p_reader,archive_callback & p_callback,bool p_want_readers) = 0; - //! Helper implemented on top of the other archive_list, uses lambda instead of callback. + //! Helper implemented on top of the other archive_list, uses lambda instead of callback, avoids having to implement archive_callback. void archive_list(const char * path, file::ptr, list_func_t, bool wantReaders, abort_callback&); //! Optional method to weed out unsupported formats prior to calling archive_list. \n @@ -50,9 +55,15 @@ namespace foobar2000_io { //! Returns a list of extensions, colon delimited, e.g.: "zip,rar,7z" virtual void list_extensions(pfc::string_base & out) = 0; }; + //! \since 2.1 + class NOVTABLE archive_v4 : public archive_v3 { + FB2K_MAKE_SERVICE_INTERFACE(archive_v4, archive_v3) + public: + virtual fb2k::arrayRef archive_list_v4( fsItemFilePtr item, file::ptr readerOptional, abort_callback & a) = 0; + }; //! Root class for archive implementations. Derive from this instead of from archive directly. - class NOVTABLE archive_impl : public service_multi_inherit { + class NOVTABLE archive_impl : public service_multi_inherit { protected: //do not override these bool get_canonical_path(const char * path,pfc::string_base & out) override; @@ -75,6 +86,9 @@ namespace foobar2000_io { void list_extensions(pfc::string_base & out) override { out = get_archive_type(); } bool supports_content_types() override { return false; } char pathSeparator() override { return '/'; } + void extract_filename_ext(const char * path, pfc::string_base & outFN) override; + bool get_display_name_short(const char* in, pfc::string_base& out) override; + fb2k::arrayRef archive_list_v4( fsItemFilePtr item, file::ptr readerOptional, abort_callback & a ) override; protected: //override these virtual const char * get_archive_type()=0;//eg. "zip", must be lowercase diff --git a/3rdparty/foo_SDK/foobar2000/SDK/audio_chunk.cpp b/3rdparty/foo_SDK/foobar2000/SDK/audio_chunk.cpp index d40bca2f..8210b7e0 100644 --- a/3rdparty/foo_SDK/foobar2000/SDK/audio_chunk.cpp +++ b/3rdparty/foo_SDK/foobar2000/SDK/audio_chunk.cpp @@ -2,17 +2,25 @@ #include "mem_block_container.h" #include "audio_chunk.h" -void audio_chunk::set_data(const audio_sample * src,t_size samples,unsigned nch,unsigned srate,unsigned channel_config) -{ - t_size size = samples * nch; +void audio_chunk::set_data(const audio_sample* src, size_t samples, spec_t const & spec) { + t_size size = samples * spec.chanCount; set_data_size(size); if (src) - pfc::memcpy_t(get_data(),src,size); + pfc::memcpy_t(get_data(), src, size); else - pfc::memset_t(get_data(),(audio_sample)0,size); + pfc::memset_t(get_data(), (audio_sample)0, size); set_sample_count(samples); - set_channels(nch,channel_config); - set_srate(srate); + set_spec(spec); +} + +void audio_chunk::set_data(const audio_sample* src, size_t samples, unsigned nch, unsigned srate, unsigned channel_config) +{ + set_data(src, samples, makeSpec(srate, nch, channel_config)); +} + +void audio_chunk::set_data(const audio_sample* src, size_t samples, unsigned nch, unsigned srate) { + + set_data(src, samples, makeSpec(srate, nch)); } inline bool check_exclusive(unsigned val, unsigned mask) @@ -280,25 +288,27 @@ static void process_float_multi_swap(audio_sample * p_out,const t_float * p_in,c } } -void audio_chunk::set_data_32(const float* src, t_size samples, unsigned nch, unsigned srate) { +void audio_chunk::set_data_32(const float* src, size_t samples, spec_t const& spec) { #if audio_sample_size == 32 - set_data(src, samples, nch, srate); + set_data(src, samples, spec); #else - t_size size = samples * nch; + t_size size = samples * spec.chanCount; set_data_size(size); if (src) audio_math::convert(src, get_data(), size); else pfc::memset_t(get_data(), (audio_sample)0, size); set_sample_count(samples); - set_channels(nch); - set_srate(srate); + set_spec(spec); #endif } +void audio_chunk::set_data_32(const float* src, size_t samples, unsigned nch, unsigned srate) { + set_data_32(src, samples, makeSpec(srate, nch) ); +} void audio_chunk::set_data_floatingpoint_ex(const void * ptr,t_size size,unsigned srate,unsigned nch,unsigned bps,unsigned flags,unsigned p_channel_config) { - PFC_ASSERT(bps==32 || bps==64 || bps == 16 || bps == 24); + PFC_ASSERT(is_supported_floatingpoint(bps)); PFC_ASSERT( check_exclusive(flags,FLAG_LITTLE_ENDIAN|FLAG_BIG_ENDIAN) ); PFC_ASSERT( ! (flags & (FLAG_SIGNED|FLAG_UNSIGNED) ) ); @@ -604,6 +614,7 @@ audio_chunk::spec_t audio_chunk::makeSpec(uint32_t rate, uint32_t channels) { } audio_chunk::spec_t audio_chunk::makeSpec(uint32_t rate, uint32_t channels, uint32_t mask) { + PFC_ASSERT(mask == 0 || pfc::countBits32(mask) == channels); spec_t spec = {}; spec.sampleRate = rate; spec.chanCount = channels; spec.chanMask = mask; return spec; diff --git a/3rdparty/foo_SDK/foobar2000/SDK/audio_chunk.h b/3rdparty/foo_SDK/foobar2000/SDK/audio_chunk.h index cded0766..073e632f 100644 --- a/3rdparty/foo_SDK/foobar2000/SDK/audio_chunk.h +++ b/3rdparty/foo_SDK/foobar2000/SDK/audio_chunk.h @@ -1,6 +1,7 @@ #pragma once #include +#include #include "exception_io.h" #ifdef _WIN32 @@ -12,6 +13,7 @@ PFC_DECLARE_EXCEPTION(exception_unexpected_audio_format_change, exception_io_dat //! Interface to container of a chunk of audio data. See audio_chunk_impl for an implementation. class NOVTABLE audio_chunk { public: + struct spec_t; // forward decl enum { sample_rate_min = 1000, sample_rate_max = 20000000 @@ -40,18 +42,22 @@ class NOVTABLE audio_chunk { channel_top_back_center = 1<<16, channel_top_back_right = 1<<17, + channels_back_left_right = channel_back_left | channel_back_right, + channels_side_left_right = channel_side_left | channel_side_right, + channel_config_mono = channel_front_center, channel_config_stereo = channel_front_left | channel_front_right, - channel_config_3point0 = channel_front_left | channel_front_right | channel_front_center, - channel_config_4point0 = channel_front_left | channel_front_right | channel_back_left | channel_back_right, - channel_config_4point1 = channel_front_left | channel_front_right | channel_back_left | channel_back_right | channel_lfe, - channel_config_5point0 = channel_front_left | channel_front_right | channel_front_center | channel_back_left | channel_back_right, - channel_config_5point1 = channel_front_left | channel_front_right | channel_front_center | channel_lfe | channel_back_left | channel_back_right, - channel_config_5point1_side = channel_front_left | channel_front_right | channel_front_center | channel_lfe | channel_side_left | channel_side_right, - channel_config_7point1 = channel_config_5point1 | channel_side_left | channel_side_right, + channel_config_2point1 = channel_config_stereo | channel_lfe, + channel_config_3point0 = channel_config_stereo | channel_front_center, + channel_config_4point0 = channel_config_stereo | channels_back_left_right, + channel_config_4point0_side = channel_config_stereo | channels_side_left_right, + channel_config_4point1 = channel_config_4point0 | channel_lfe, + channel_config_5point0 = channel_config_4point0 | channel_front_center, + channel_config_6point0 = channel_config_4point0 | channels_side_left_right, + channel_config_5point1 = channel_config_4point0 | channel_front_center | channel_lfe, + channel_config_5point1_side = channel_config_4point0_side | channel_front_center | channel_lfe, + channel_config_7point1 = channel_config_5point1 | channels_side_left_right, - channels_back_left_right = channel_back_left | channel_back_right, - channels_side_left_right = channel_side_left | channel_side_right, defined_channel_count = 18, }; @@ -62,14 +68,14 @@ class NOVTABLE audio_chunk { static unsigned g_guess_channel_config_xiph(unsigned count); //! Helper function; translates audio_chunk channel map to WAVEFORMATEXTENSIBLE channel map. - static uint32_t g_channel_config_to_wfx(unsigned p_config); + static constexpr uint32_t g_channel_config_to_wfx(unsigned p_config) { return p_config;} //! Helper function; translates WAVEFORMATEXTENSIBLE channel map to audio_chunk channel map. - static unsigned g_channel_config_from_wfx(uint32_t p_wfx); + static constexpr unsigned g_channel_config_from_wfx(uint32_t p_wfx) { return p_wfx;} //! Extracts flag describing Nth channel from specified map. Usable to figure what specific channel in a stream means. static unsigned g_extract_channel_flag(unsigned p_config,unsigned p_index); //! Counts channels specified by channel map. - static unsigned g_count_channels(unsigned p_config); + static constexpr unsigned g_count_channels(unsigned p_config) { return pfc::countBits32(p_config); } //! Calculates index of a channel specified by p_flag in a stream where channel map is described by p_config. static unsigned g_channel_index_from_flag(unsigned p_config,unsigned p_flag); @@ -78,6 +84,7 @@ class NOVTABLE audio_chunk { static unsigned g_find_channel_idx(unsigned p_flag); static void g_formatChannelMaskDesc(unsigned flags, pfc::string_base & out); static pfc::string8 g_formatChannelMaskDesc(unsigned flags); + static const char* g_channelMaskName(unsigned flags); @@ -169,10 +176,9 @@ class NOVTABLE audio_chunk { } //! Helper, sets chunk data to contents of specified buffer, with specified number of channels / sample rate / channel map. - void set_data(const audio_sample * src,t_size samples,unsigned nch,unsigned srate,unsigned channel_config); - - //! Helper, sets chunk data to contents of specified buffer, with specified number of channels / sample rate, using default channel map for specified channel count. - inline void set_data(const audio_sample * src,t_size samples,unsigned nch,unsigned srate) {set_data(src,samples,nch,srate,g_guess_channel_config(nch));} + void set_data(const audio_sample * src,size_t samples,unsigned nch,unsigned srate,unsigned channel_config); + void set_data(const audio_sample* src, size_t samples, spec_t const& spec); + void set_data(const audio_sample* src, t_size samples, unsigned nch, unsigned srate); void set_data_int16(const int16_t * src,t_size samples,unsigned nch,unsigned srate,unsigned channel_config); @@ -200,8 +206,10 @@ class NOVTABLE audio_chunk { void set_data_fixedpoint_ms(const void * ptr, size_t bytes, unsigned sampleRate, unsigned channels, unsigned bps, unsigned channelConfig); void set_data_floatingpoint_ex(const void * ptr,t_size bytes,unsigned p_sample_rate,unsigned p_channels,unsigned p_bits_per_sample,unsigned p_flags,unsigned p_channel_config);//signed/unsigned flags dont apply + static bool is_supported_floatingpoint(unsigned bps) { return bps == 32 || bps == 64 || bps == 16 || bps == 24; } void set_data_32(const float* src, t_size samples, unsigned nch, unsigned srate); + void set_data_32(const float* src, t_size samples, spec_t const & spec ); //! Appends silent samples at the end of the chunk. \n //! The chunk may be empty prior to this call, its sample rate & channel count will be set to the specified values then. \n @@ -213,10 +221,10 @@ class NOVTABLE audio_chunk { void pad_with_silence_ex(t_size samples,unsigned hint_nch,unsigned hint_srate); //! Appends silent samples at the end of the chunk. \n //! The chunk must have valid sample rate & channel count prior to this call. - //! @param Number of silent samples to append.s + //! @param samples Number of silent samples to append.s void pad_with_silence(t_size samples); //! Inserts silence at the beginning of the audio chunk. - //! @param Number of silent samples to insert. + //! @param samples Number of silent samples to insert. void insert_silence_fromstart(t_size samples); //! Helper; removes N first samples from the chunk. \n //! If the chunk contains fewer samples than requested, it becomes empty. @@ -232,7 +240,7 @@ class NOVTABLE audio_chunk { //! Any existing audio sdata will be discarded. \n //! Expects sample rate and channel count to be set first. \n //! Also allocates memory for the requested amount of data see: set_data_size(). - //! @param samples Desired duration in seconds. + //! @param seconds Desired duration in seconds. void set_silence_seconds( double seconds ); //! Helper; skips first samples of the chunk updating a remaining to-skip counter. diff --git a/3rdparty/foo_SDK/foobar2000/SDK/audio_chunk_channel_config.cpp b/3rdparty/foo_SDK/foobar2000/SDK/audio_chunk_channel_config.cpp index 4c2f3992..85a92cde 100644 --- a/3rdparty/foo_SDK/foobar2000/SDK/audio_chunk_channel_config.cpp +++ b/3rdparty/foo_SDK/foobar2000/SDK/audio_chunk_channel_config.cpp @@ -50,37 +50,9 @@ static struct {DWORD m_wfx; unsigned m_native; } const g_translation_table[] = #endif #endif -// foobar2000 channel flags are 1:1 identical to Windows WFX ones. -uint32_t audio_chunk::g_channel_config_to_wfx(unsigned p_config) -{ - return p_config; -#if 0 - DWORD ret = 0; - unsigned n; - for(n=0;n>= 1; ++idx; } -} \ No newline at end of file +} + +namespace { + struct maskDesc_t { + const char* name; + unsigned mask; + }; + static constexpr maskDesc_t maskDesc[] = { + {"mono", audio_chunk::channel_config_mono}, + {"stereo", audio_chunk::channel_config_stereo}, + {"stereo (rear)", audio_chunk::channel_back_left | audio_chunk::channel_back_right}, + {"stereo (side)", audio_chunk::channel_side_left | audio_chunk::channel_side_right}, + {"2.1", audio_chunk::channel_config_2point1}, + {"3.0", audio_chunk::channel_config_3point0}, + {"4.0", audio_chunk::channel_config_4point0}, + {"4.1", audio_chunk::channel_config_4point1}, + {"5.0", audio_chunk::channel_config_5point0}, + {"5.1", audio_chunk::channel_config_5point1}, + {"5.1 (side)", audio_chunk::channel_config_5point1_side}, + {"6.1", audio_chunk::channel_config_5point1 | audio_chunk::channel_back_center}, + {"6.1 (side)", audio_chunk::channel_config_5point1_side | audio_chunk::channel_back_center}, + {"7.1", audio_chunk::channel_config_7point1}, + }; +} + +const char* audio_chunk::g_channelMaskName(unsigned flags) { + for (auto& walk : maskDesc) { + if (flags == walk.mask) return walk.name; + } + return nullptr; +} + +static_assert( pfc::countBits32(audio_chunk::channel_config_mono) == 1 ); +static_assert( pfc::countBits32(audio_chunk::channel_config_stereo) == 2 ); +static_assert( pfc::countBits32(audio_chunk::channel_config_4point0) == 4 ); +static_assert( pfc::countBits32(audio_chunk::channel_config_4point0_side) == 4 ); +static_assert( pfc::countBits32(audio_chunk::channel_config_4point1) == 5 ); +static_assert( pfc::countBits32(audio_chunk::channel_config_5point0) == 5 ); +static_assert( pfc::countBits32(audio_chunk::channel_config_5point1) == 6 ); +static_assert( pfc::countBits32(audio_chunk::channel_config_5point1_side) == 6 ); +static_assert( pfc::countBits32(audio_chunk::channel_config_6point0) == 6); +static_assert( pfc::countBits32(audio_chunk::channel_config_7point1) == 8 ); diff --git a/3rdparty/foo_SDK/foobar2000/SDK/audio_postprocessor.h b/3rdparty/foo_SDK/foobar2000/SDK/audio_postprocessor.h index d70f6b3e..31af5dfb 100644 --- a/3rdparty/foo_SDK/foobar2000/SDK/audio_postprocessor.h +++ b/3rdparty/foo_SDK/foobar2000/SDK/audio_postprocessor.h @@ -4,7 +4,6 @@ #include "mem_block_container.h" //! This class handles conversion of audio data (audio_chunk) to various linear PCM types, with optional dithering. - class NOVTABLE audio_postprocessor : public service_base { public: diff --git a/3rdparty/foo_SDK/foobar2000/SDK/callback_merit.h b/3rdparty/foo_SDK/foobar2000/SDK/callback_merit.h new file mode 100644 index 00000000..ee651423 --- /dev/null +++ b/3rdparty/foo_SDK/foobar2000/SDK/callback_merit.h @@ -0,0 +1,24 @@ +#pragma once + +namespace fb2k { + // callback_merit_t controls in what order callbacks are executed. \n + // In specific corner cases, you want your callback executed before other callbacks of the same kind. + typedef double callback_merit_t; + + // Note REVERSE sort. HIGHER merit called first. + static constexpr callback_merit_t callback_merit_default = 0; + static constexpr callback_merit_t callback_merit_indexer = 1000; // indexer: does nothing else than updating internal state, called early before UI updates, in case UI updates might rely on indexed data. + static constexpr callback_merit_t callback_merit_serializer = 2000; // serializer: does nothing else than saving new state, called early. + + //! Special class that can be optionally implemented by 'static' callbacks, such as library_callback, to control callback merit. \n + //! See also: callback_merit_t \n + //! Some callback classes support get_callback_merit() natively, such as metadb_io_callback_v2. \n + //! With callbacks registered dynamically, other means of controlling merit are provided. + class callback_with_merit : public service_base { + FB2K_MAKE_SERVICE_INTERFACE(callback_with_merit, service_base); + public: + virtual callback_merit_t get_callback_merit() = 0; + }; + + callback_merit_t callback_merit_of(service_ptr obj); +} \ No newline at end of file diff --git a/3rdparty/foo_SDK/foobar2000/SDK/cfg_var.cpp b/3rdparty/foo_SDK/foobar2000/SDK/cfg_var.cpp index 633aa0df..8b0dd2cd 100644 --- a/3rdparty/foo_SDK/foobar2000/SDK/cfg_var.cpp +++ b/3rdparty/foo_SDK/foobar2000/SDK/cfg_var.cpp @@ -2,6 +2,14 @@ #include "cfg_var.h" #include "configStore.h" +namespace fb2k { + pfc::string8 formatCfgVarName(const GUID& guid) { + return pfc::format("cfg_var.", pfc::print_guid(guid)); + } + pfc::string8 advconfig_autoName(const GUID& id) { + return pfc::format("advconfig.unnamed.", pfc::print_guid(id)); + } +} namespace cfg_var_modern { #ifdef FOOBAR2000_HAVE_CFG_VAR_LEGACY @@ -88,7 +96,7 @@ namespace cfg_var_modern { pfc::string8 cfg_var_common::formatVarName(const GUID& guid) { - return pfc::format("cfg_var.", pfc::print_guid(guid)); + return fb2k::formatCfgVarName( guid ); } pfc::string8 cfg_var_common::formatName() const { diff --git a/3rdparty/foo_SDK/foobar2000/SDK/cfg_var_legacy.cpp b/3rdparty/foo_SDK/foobar2000/SDK/cfg_var_legacy.cpp index 58fbce64..c96f167b 100644 --- a/3rdparty/foo_SDK/foobar2000/SDK/cfg_var_legacy.cpp +++ b/3rdparty/foo_SDK/foobar2000/SDK/cfg_var_legacy.cpp @@ -1,9 +1,18 @@ #include "foobar2000-sdk-pch.h" #include "cfg_var_legacy.h" +#if FOOBAR2000_SUPPORT_CFG_VAR_DOWNGRADE +#include "configStore.h" +#include +#endif + #ifdef FOOBAR2000_HAVE_CFG_VAR_LEGACY +#if FOOBAR2000_SUPPORT_CFG_VAR_DOWNGRADE +namespace fb2k { + pfc::string8 formatCfgVarName(const GUID&); +} +#endif // FOOBAR2000_SUPPORT_CFG_VAR_DOWNGRADE namespace cfg_var_legacy { - cfg_var_reader* cfg_var_reader::g_list = NULL; cfg_var_writer* cfg_var_writer::g_list = NULL; @@ -22,11 +31,11 @@ namespace cfg_var_legacy { guid = pfc::byteswap_if_be_t(guid); p_stream->read_lendian_t(size, p_abort); - cfg_var_reader* var; - if (vars.query(guid, var)) { + auto iter = vars.find(guid); + if ( iter.is_valid() ) { stream_reader_limited_ref wrapper(p_stream, size); try { - var->set_data_raw(&wrapper, size, p_abort); + iter->m_value->set_data_raw(&wrapper, size, p_abort); } catch (exception_io_data) {} wrapper.flush_remaining(p_abort); } else { @@ -34,7 +43,19 @@ namespace cfg_var_legacy { } } } - +#if FOOBAR2000_SUPPORT_CFG_VAR_DOWNGRADE + static std::once_flag downgrade_once; + void cfg_var_reader::downgrade_main() { + std::call_once(downgrade_once, [] { + auto api = fb2k::configStore::tryGet(); + if (api.is_valid()) { + for (cfg_var_reader* walk = g_list; walk != NULL; walk = walk->m_next) { + walk->downgrade_check(api); + } + } + }); + } +#endif void cfg_var_writer::config_write_file(stream_writer* p_stream, abort_callback& p_abort) { cfg_var_writer* ptr; pfc::array_t temp; @@ -63,5 +84,74 @@ namespace cfg_var_legacy { set_string(temp); } + +#if FOOBAR2000_SUPPORT_CFG_VAR_DOWNGRADE + int64_t downgrade_this(fb2k::configStore::ptr api, const char * name, int64_t current) { + int64_t v = api->getConfigInt(name, INT64_MAX); + if (v == INT64_MAX) { + v = api->getConfigInt(name, INT64_MIN); + if ( v == INT64_MIN ) return current; + } + api->deleteConfigInt(name); + return v; + } + uint64_t downgrade_this(fb2k::configStore::ptr api, const char * name, uint64_t current) { + return (uint64_t) downgrade_this(api, name, (int64_t) current); + } + int32_t downgrade_this(fb2k::configStore::ptr api, const char * name, int32_t current) { + return (int32_t) downgrade_this(api, name, (int64_t) current); + } + uint32_t downgrade_this(fb2k::configStore::ptr api, const char * name, uint32_t current) { + return (uint32_t) downgrade_this(api, name, (int64_t) current); + } + bool downgrade_this(fb2k::configStore::ptr api, const char * name, bool current) { + return downgrade_this(api, name, (int64_t)(current?1:0)) != 0; + } + double downgrade_this(fb2k::configStore::ptr api, const char * name, double current) { + double v = api->getConfigFloat(name, -1); + if (v == -1) { + v = api->getConfigFloat(name, 0); + if ( v == 0 ) return current; + } + api->deleteConfigFloat(name); + return v; + } + GUID downgrade_this(fb2k::configStore::ptr api, const char * name, GUID current) { + auto blob = api->getConfigBlob( name ); + if (blob.is_valid() && blob->size() == sizeof(GUID)) { + GUID ret; + memcpy(&ret, blob->get_ptr(), sizeof(ret)); + api->deleteConfigBlob( name ); + return ret; + } + return current; + } + + void cfg_string::downgrade_check(fb2k::configStore::ptr api) { + const auto name = this->downgrade_name(); + auto v = api->getConfigString(name, nullptr); + if (v.is_valid()) { + this->set(v->c_str()); + api->deleteConfigString(name); + } + } + void cfg_string_mt::downgrade_check(fb2k::configStore::ptr api) { + const auto name = this->downgrade_name(); + auto v = api->getConfigString(name, nullptr); + if (v.is_valid()) { + this->set(v->c_str()); + api->deleteConfigString(name); + } + } + + pfc::string8 cfg_var_reader::downgrade_name() const { + if (m_downgrade_name.length() > 0) { + return m_downgrade_name; + } else { + return fb2k::formatCfgVarName(this->m_guid); + } + } +#endif + } #endif // FOOBAR2000_HAVE_CFG_VAR_LEGACY diff --git a/3rdparty/foo_SDK/foobar2000/SDK/cfg_var_legacy.h b/3rdparty/foo_SDK/foobar2000/SDK/cfg_var_legacy.h index f45c3dc4..943c86ea 100644 --- a/3rdparty/foo_SDK/foobar2000/SDK/cfg_var_legacy.h +++ b/3rdparty/foo_SDK/foobar2000/SDK/cfg_var_legacy.h @@ -4,6 +4,11 @@ #include #include "filesystem.h" // stream_reader, stream_writer +#if FOOBAR2000_SUPPORT_CFG_VAR_DOWNGRADE +#include "configStore.h" +#include "initquit.h" +#endif + namespace cfg_var_legacy { #define CFG_VAR_ASSERT_SAFEINIT PFC_ASSERT(!core_api::are_services_available());/*imperfect check for nonstatic instantiation*/ @@ -19,6 +24,22 @@ namespace cfg_var_legacy { //! @param p_sizehint Number of bytes contained in the stream; reading past p_sizehint bytes will fail (EOF). virtual void set_data_raw(stream_reader* p_stream, t_size p_sizehint, abort_callback& p_abort) = 0; +#if FOOBAR2000_SUPPORT_CFG_VAR_DOWNGRADE + private: + pfc::string8 m_downgrade_name; + public: + pfc::string8 downgrade_name() const; + void downgrade_set_name( const char * arg ) { m_downgrade_name = arg; } + + //! Implementation of config downgrade for this var, see FOOBAR2000_SUPPORT_CFG_VAR_DOWNGRADE for more info. \n + //! Most components should not use this. + virtual void downgrade_check(fb2k::configStore::ptr api) {} + //! Config downgrade main for your component, see FOOBAR2000_SUPPORT_CFG_VAR_DOWNGRADE for more info. \n + //! Put FOOBAR2000_IMPLEMENT_CFG_VAR_DOWNGRADE somewhere in your component to call on startup, or call from your code as early as possible after config read. \n + //! If you call it more than once, spurious calls will be ignored. + static void downgrade_main(); +#endif + //! For internal use only, do not call. static void config_read_file(stream_reader* p_stream, abort_callback& p_abort); @@ -62,6 +83,16 @@ namespace cfg_var_legacy { GUID get_guid() const { return cfg_var_reader::m_guid; } }; +#if FOOBAR2000_SUPPORT_CFG_VAR_DOWNGRADE + int64_t downgrade_this( fb2k::configStore::ptr api, const char*, int64_t current); + uint64_t downgrade_this( fb2k::configStore::ptr api, const char*, uint64_t current); + int32_t downgrade_this( fb2k::configStore::ptr api, const char*, int32_t current); + uint32_t downgrade_this( fb2k::configStore::ptr api, const char*, uint32_t current); + bool downgrade_this( fb2k::configStore::ptr api, const char*, bool current); + double downgrade_this( fb2k::configStore::ptr api, const char*, double current); + GUID downgrade_this( fb2k::configStore::ptr api, const char*, GUID current); +#endif + //! Generic integer config variable class. Template parameter can be used to specify integer type to use.\n //! Note that cfg_var class and its derivatives may be only instantiated statically (as static objects or members of other static objects), NEVER dynamically (operator new, local variables, members of objects instantiated as such). template @@ -69,13 +100,17 @@ namespace cfg_var_legacy { private: t_inttype m_val; protected: - void get_data_raw(stream_writer* p_stream, abort_callback& p_abort) { p_stream->write_lendian_t(m_val, p_abort); } - void set_data_raw(stream_reader* p_stream, t_size, abort_callback& p_abort) { + void get_data_raw(stream_writer* p_stream, abort_callback& p_abort) override { p_stream->write_lendian_t(m_val, p_abort); } + void set_data_raw(stream_reader* p_stream, t_size, abort_callback& p_abort) override { t_inttype temp; p_stream->read_lendian_t(temp, p_abort);//alter member data only on success, this will throw an exception when something isn't right m_val = temp; } - +#if FOOBAR2000_SUPPORT_CFG_VAR_DOWNGRADE + void downgrade_check(fb2k::configStore::ptr api) override { + m_val = downgrade_this(api, this->downgrade_name(), m_val); + } +#endif public: //! @param p_guid GUID of the variable, used to identify variable implementations owning specific configuration file entries when reading the configuration file back. You must generate a new GUID every time you declare a new cfg_var. //! @param p_default Default value of the variable. @@ -91,54 +126,59 @@ namespace cfg_var_legacy { typedef cfg_int_t cfg_int; typedef cfg_int_t cfg_uint; - //! Since relevant byteswapping functions also understand GUIDs, this can be used to declare a cfg_guid. - typedef cfg_int_t cfg_guid; - typedef cfg_int_t cfg_bool; - typedef cfg_int_t cfg_float; - typedef cfg_int_t cfg_double; + typedef cfg_int_t cfg_guid; // ANNOYING OLD DESIGN. THIS DOESN'T BELONG HERE BUT CANNOT BE CHANGED WITHOUT BREAKING PEOPLE'S STUFF. BLARFGH. + typedef cfg_int_t cfg_bool; // See above. + typedef cfg_int_t cfg_float; // See above %$!@#$ + typedef cfg_int_t cfg_double; // .... //! String config variable. Stored in the stream with int32 header containing size in bytes, followed by non-null-terminated UTF-8 data.\n //! Note that cfg_var class and its derivatives may be only instantiated statically (as static objects or members of other static objects), NEVER dynamically (operator new, local variables, members of objects instantiated as such). class cfg_string : public cfg_var, public pfc::string8 { protected: - void get_data_raw(stream_writer* p_stream, abort_callback& p_abort); - void set_data_raw(stream_reader* p_stream, t_size p_sizehint, abort_callback& p_abort); + void get_data_raw(stream_writer* p_stream, abort_callback& p_abort) override; + void set_data_raw(stream_reader* p_stream, t_size p_sizehint, abort_callback& p_abort) override; +#if FOOBAR2000_SUPPORT_CFG_VAR_DOWNGRADE + void downgrade_check(fb2k::configStore::ptr) override; +#endif public: //! @param p_guid GUID of the variable, used to identify variable implementations owning specific configuration file entries when reading the configuration file back. You must generate a new GUID every time you declare a new cfg_var. //! @param p_defaultval Default/initial value of the variable. explicit inline cfg_string(const GUID& p_guid, const char* p_defaultval) : cfg_var(p_guid), pfc::string8(p_defaultval) {} - inline const cfg_string& operator=(const cfg_string& p_val) { set_string(p_val); return *this; } - inline const cfg_string& operator=(const char* p_val) { set_string(p_val); return *this; } + const cfg_string& operator=(const cfg_string& p_val) { set_string(p_val); return *this; } + const cfg_string& operator=(const char* p_val) { set_string(p_val); return *this; } + const cfg_string& operator=(pfc::string8 && p_val) { set(std::move(p_val)); return *this; } + inline operator const char* () const { return get_ptr(); } const pfc::string8& get() const { return *this; } + void set( const char * arg ) { this->set_string(arg); } + void set(pfc::string8&& arg) { pfc::string8 * pThis = this; *pThis = std::move(arg); } }; class cfg_string_mt : public cfg_var { protected: - void get_data_raw(stream_writer* p_stream, abort_callback& p_abort) { + void get_data_raw(stream_writer* p_stream, abort_callback& p_abort) override { pfc::string8 temp; get(temp); p_stream->write_object(temp.get_ptr(), temp.length(), p_abort); } - void set_data_raw(stream_reader* p_stream, t_size, abort_callback& p_abort) { + void set_data_raw(stream_reader* p_stream, t_size, abort_callback& p_abort) override { pfc::string8_fastalloc temp; p_stream->read_string_raw(temp, p_abort); set(temp); } +#if FOOBAR2000_SUPPORT_CFG_VAR_DOWNGRADE + void downgrade_check(fb2k::configStore::ptr) override; +#endif public: cfg_string_mt(const GUID& id, const char* defVal) : cfg_var(id), m_val(defVal) {} - void get(pfc::string_base& out) const { - inReadSync(m_sync); - out = m_val; - } - void set(const char* val, t_size valLen = ~0) { - inWriteSync(m_sync); - m_val.set_string(val, valLen); - } + void get(pfc::string_base& out) const { inReadSync(m_sync); out = m_val; } + pfc::string8 get() const { inReadSync(m_sync); return m_val; } + void set(const char* val, t_size valLen = SIZE_MAX) { inWriteSync(m_sync); m_val.set_string(val, valLen); } + void set( pfc::string8 && val ) { inWriteSync(m_sync); m_val = std::move(val); } private: mutable pfc::readWriteLock m_sync; pfc::string8 m_val; @@ -315,7 +355,10 @@ namespace cfg_var_legacy { } } }; -} +#if FOOBAR2000_SUPPORT_CFG_VAR_DOWNGRADE +#define FOOBAR2000_IMPLEMENT_CFG_VAR_DOWNGRADE FB2K_RUN_ON_INIT(cfg_var_reader::downgrade_main) +#endif // FOOBAR2000_SUPPORT_CFG_VAR_DOWNGRADE +} // cfg_var_legacy #else namespace cfg_var_legacy { // Dummy class @@ -326,3 +369,7 @@ namespace cfg_var_legacy { }; } #endif + +#ifndef FOOBAR2000_IMPLEMENT_CFG_VAR_DOWNGRADE +#define FOOBAR2000_IMPLEMENT_CFG_VAR_DOWNGRADE +#endif \ No newline at end of file diff --git a/3rdparty/foo_SDK/foobar2000/SDK/chapterizer.h b/3rdparty/foo_SDK/foobar2000/SDK/chapterizer.h index b066d787..adc897a8 100644 --- a/3rdparty/foo_SDK/foobar2000/SDK/chapterizer.h +++ b/3rdparty/foo_SDK/foobar2000/SDK/chapterizer.h @@ -17,7 +17,7 @@ class NOVTABLE chapter_list { //! Sets number of chapters. virtual void set_chapter_count(t_size p_count) = 0; //! Modifies description of specified chapter. - //! @param p_chapter_index Index of chapter to modify, greater or equal zero and less than get_chapter_count() value. If p_chapter value is out of valid range, results are undefined (e.g. crash). + //! @param p_chapter Index of chapter to modify, greater or equal zero and less than get_chapter_count() value. If p_chapter value is out of valid range, results are undefined (e.g. crash). //! @param p_info New chapter description. Note that length part of file_info is used to calculate chapter marks. virtual void set_info(t_size p_chapter,const file_info & p_info) = 0; @@ -67,7 +67,6 @@ class NOVTABLE chapterizer : public service_base { FB2K_MAKE_SERVICE_INTERFACE_ENTRYPOINT(chapterizer); public: //! Tests whether specified path is supported by this implementation. - //! @param p_ext Extension of the file being processed. virtual bool is_our_path(const char * p_path) = 0; //! Writes new chapter list to specified file. diff --git a/3rdparty/foo_SDK/foobar2000/SDK/commandline.h b/3rdparty/foo_SDK/foobar2000/SDK/commandline.h index 5e230d2c..a2cb741f 100644 --- a/3rdparty/foo_SDK/foobar2000/SDK/commandline.h +++ b/3rdparty/foo_SDK/foobar2000/SDK/commandline.h @@ -1,4 +1,6 @@ #pragma once + +//! Service for handling commandline arguments passed to foobar2000.exe class NOVTABLE commandline_handler : public service_base { public: @@ -16,16 +18,18 @@ class NOVTABLE commandline_handler : public service_base FB2K_MAKE_SERVICE_INTERFACE_ENTRYPOINT(commandline_handler); }; -class commandline_handler_metadb_handle : public commandline_handler//helper -{ +//! Helper automatically turning passed file locations into metadb_handle objects (audio track references) +class commandline_handler_metadb_handle : public commandline_handler { protected: - virtual void on_file(const char * url); - virtual bool want_directories() {return true;} + void on_file(const char * url) override final; + bool want_directories() override {return true;} public: - virtual result on_token(const char * token)=0; - virtual void on_files_done() {}; - - virtual void on_file(const metadb_handle_ptr & ptr)=0; + //! Override me + virtual result on_token(const char * token) override = 0; + //! Override me + virtual void on_files_done() override {}; + //! Override me + virtual void on_file(const metadb_handle_ptr & ptr) = 0; }; /* diff --git a/3rdparty/foo_SDK/foobar2000/SDK/commonObjects-Apple.h b/3rdparty/foo_SDK/foobar2000/SDK/commonObjects-Apple.h new file mode 100644 index 00000000..2d36045e --- /dev/null +++ b/3rdparty/foo_SDK/foobar2000/SDK/commonObjects-Apple.h @@ -0,0 +1,21 @@ +#pragma once + +#ifdef __APPLE__ + +namespace fb2k { + class NSObjectWrapper : public service_base { + FB2K_MAKE_SERVICE_INTERFACE(NSObjectWrapper, service_base); + public: + virtual void * get_() = 0; +#ifdef __OBJC__ + id get() { return (__bridge id) get_(); } +#endif + + }; +#ifdef __OBJC__ + service_ptr wrapNSObject(id); + id unwrapNSObject(service_ptr); +#endif +} + +#endif diff --git a/3rdparty/foo_SDK/foobar2000/SDK/commonObjects-Apple.mm b/3rdparty/foo_SDK/foobar2000/SDK/commonObjects-Apple.mm new file mode 100644 index 00000000..2e6dac30 --- /dev/null +++ b/3rdparty/foo_SDK/foobar2000/SDK/commonObjects-Apple.mm @@ -0,0 +1,29 @@ +#include "foobar2000-sdk-pch.h" +#include "commonObjects-Apple.h" +#include + +namespace { + class NSObjectWrapperImpl : public fb2k::NSObjectWrapper { + public: + id obj; + void * get_() override { + return (__bridge void*) obj; + } + }; +} +namespace fb2k { + service_ptr wrapNSObject(id arg) { + if (!arg) return nullptr; + auto ret = fb2k::service_new(); + ret->obj = arg; + return ret; + } + id unwrapNSObject(service_ptr arg) { + id ret = nil; + fb2k::NSObjectWrapper::ptr obj; + if ( obj &= arg ) { + ret = obj->get(); + } + return ret; + } +} diff --git a/3rdparty/foo_SDK/foobar2000/SDK/componentversion.h b/3rdparty/foo_SDK/foobar2000/SDK/componentversion.h index ae3afa07..6edf038a 100644 --- a/3rdparty/foo_SDK/foobar2000/SDK/componentversion.h +++ b/3rdparty/foo_SDK/foobar2000/SDK/componentversion.h @@ -1,3 +1,5 @@ +#pragma once + //! Entrypoint interface for declaring component's version information. Instead of implementing this directly, use DECLARE_COMPONENT_VERSION(). class NOVTABLE componentversion : public service_base { public: @@ -66,7 +68,6 @@ class componentversion_impl_copy_factory : public __componentversion_impl_copy_f static componentversion_impl_copy_factory g_componentversion_service(NAME,VERSION,ABOUT); -#ifdef _WIN32 //! \since 1.0 //! Allows components to cleanly abort app startup in case the installation appears to have become corrupted. class component_installation_validator : public service_base { @@ -79,6 +80,7 @@ class component_installation_validator : public service_base { FB2K_MAKE_SERVICE_INTERFACE_ENTRYPOINT(component_installation_validator) }; +#ifdef _WIN32 //! Simple implementation of component_installation_validator that makes sure that our component DLL has not been renamed around by idiot users. class component_installation_validator_filename : public component_installation_validator { public: diff --git a/3rdparty/foo_SDK/foobar2000/SDK/configStore.h b/3rdparty/foo_SDK/foobar2000/SDK/configStore.h index c6eabc04..67829382 100644 --- a/3rdparty/foo_SDK/foobar2000/SDK/configStore.h +++ b/3rdparty/foo_SDK/foobar2000/SDK/configStore.h @@ -18,13 +18,17 @@ typedef void * configStoreNotifyHandle_t; //! Interface to access foobar2000's configuration store, backed by SQLite database. \n //! get* methods can be called at any time. set*/delete* \n //! set*/delete* methods will trigger immediate commit when invoked without a transaction scope. \n -//! Use acquireTransactionScope() to commit multiple operations together. \n -//! Transactions scope use a global reference counter; commit happens when all transaction scopes have exited. \n //! Use commitBlocking() to commit synchronously to be sure that the data has been flushed before continuing execution. class configStore : public service_base { FB2K_MAKE_SERVICE_COREAPI( configStore ); public: + //! Causes multiple writes to be chained together. \n + //! Use of this is no longer essential since late foobar2000 v2.0 betas, as delay-write cache is always used. \n + //! You can still use it to guarantee that multiple updates are written together, that is either all or none are saved, should the system or application crash. virtual fb2k::objRef acquireTransactionScope() = 0; + + //! Synchronously flushes changes to disk. Doesn't return until changes have actually been written. \n + //! Use of this is strongly recommended against. virtual void commitBlocking() = 0; virtual int64_t getConfigInt( const char * name, int64_t defVal = 0 ) = 0; diff --git a/3rdparty/foo_SDK/foobar2000/SDK/contextmenu.h b/3rdparty/foo_SDK/foobar2000/SDK/contextmenu.h index 563da75e..d7da1b0d 100644 --- a/3rdparty/foo_SDK/foobar2000/SDK/contextmenu.h +++ b/3rdparty/foo_SDK/foobar2000/SDK/contextmenu.h @@ -1,5 +1,6 @@ #pragma once #include "metadb_handle.h" +#include //! Reserved for future use. typedef void * t_glyph; @@ -340,3 +341,31 @@ class contextmenu_group_popup_factory : public service_factory_single_t(guid, parent, name, sortPriority) {} }; + + + +class contextmenu_item_lambda : public contextmenu_item_simple { +public: + typedef std::function func_t; + contextmenu_item_lambda(func_t f, const char* n, const GUID& g, const GUID& pg, const char* d = nullptr, double sp = 0) : m_func(f), m_name(n), m_guid(g), m_parentGuid(pg), m_desc(d), m_sortPriority(sp) {} + + unsigned get_num_items() override { return 1; } + void get_item_name(unsigned p_index, pfc::string_base& p_out) override { p_out = m_name; } + void context_command(unsigned p_index, metadb_handle_list_cref p_data, const GUID& p_caller) override { m_func(p_data); } + GUID get_item_guid(unsigned p_index) override { return m_guid; } + bool get_item_description(unsigned p_index, pfc::string_base& p_out) override { + if (m_desc == nullptr) return false; + p_out = m_desc; + return true; + } + double get_sort_priority() override { return m_sortPriority; } + GUID get_parent() override { return m_parentGuid; } +private: + const std::function m_func; + const char* const m_name; + const GUID m_guid, m_parentGuid; + const char* const m_desc; + const double m_sortPriority; +}; + +#define FB2K_DECLARE_CONTEXT_MENU_ITEM(func, name, guid, parent, desc, sort) FB2K_SERVICE_FACTORY_PARAMS(contextmenu_item_lambda, func, name, guid, parent, desc, sort) diff --git a/3rdparty/foo_SDK/foobar2000/SDK/core_api.h b/3rdparty/foo_SDK/foobar2000/SDK/core_api.h index afb42ff7..df75f882 100644 --- a/3rdparty/foo_SDK/foobar2000/SDK/core_api.h +++ b/3rdparty/foo_SDK/foobar2000/SDK/core_api.h @@ -10,7 +10,8 @@ namespace core_api { const char * get_my_file_name(); //! Retrieves full path of calling dll, e.g. c:\blah\foobar2000\foo_asdf.dll . No file:// prefix, this path can interop with win32 API calls. const char * get_my_full_path(); - //! Retrieves main app window. WARNING: this is provided for parent of dialog windows and such only; using it for anything else (such as hooking windowproc to alter app behaviors) is absolutely illegal. + //! Retrieves main app window. WARNING: this is provided for parent of dialog windows and such only; using it for anything else (such as hooking windowproc to alter app behaviors) is absolutely illegal. \n + //! Becomes valid when main window has been fully initialized. Returns NULL during creation of main window's embedded elements. fb2k::hwnd_t get_main_window(); //! Tests whether services are available at this time. They are not available only during DLL startup or shutdown (e.g. inside static object constructors or destructors). bool are_services_available(); @@ -39,10 +40,13 @@ namespace core_api { bool is_quiet_mode_enabled(); }; +#define FB2K_SUPPORT_LOW_MEM_MODE (SIZE_MAX <= UINT32_MAX) + namespace fb2k { -#ifdef _WIN32 - inline bool isDebugModeActive() { return !! PFC_DEBUG ;} -#else bool isDebugModeActive(); +#if FB2K_SUPPORT_LOW_MEM_MODE + bool isLowMemModeActive(); +#else + inline constexpr bool isLowMemModeActive() { return false; } #endif } diff --git a/3rdparty/foo_SDK/foobar2000/SDK/dsp.cpp b/3rdparty/foo_SDK/foobar2000/SDK/dsp.cpp index 98addd56..1d23b94c 100644 --- a/3rdparty/foo_SDK/foobar2000/SDK/dsp.cpp +++ b/3rdparty/foo_SDK/foobar2000/SDK/dsp.cpp @@ -119,10 +119,17 @@ bool dsp_entry_hidden::g_instantiate( dsp::ptr & out, const dsp_preset & preset return i->instantiate(out, preset); } -bool dsp_entry::g_instantiate(service_ptr_t & p_out,const dsp_preset & p_preset) +bool dsp_entry::g_instantiate(service_ptr_t & p_out,const dsp_preset & p_preset, unsigned flags ) { service_ptr_t ptr; if (!g_get_interface(ptr,p_preset.get_owner())) return false; + if ( flags != 0 ) { + dsp_entry_v4::ptr v4; + if (v4 &= ptr) { + p_out = v4->instantiate_v4(p_preset, flags); + return true; + } + } return ptr->instantiate(p_out,p_preset); } diff --git a/3rdparty/foo_SDK/foobar2000/SDK/dsp.h b/3rdparty/foo_SDK/foobar2000/SDK/dsp.h index 95d6e149..caf941f5 100644 --- a/3rdparty/foo_SDK/foobar2000/SDK/dsp.h +++ b/3rdparty/foo_SDK/foobar2000/SDK/dsp.h @@ -331,16 +331,20 @@ class NOVTABLE dsp_entry : public service_base { //! Blocks until done. Returns true if preset has been altered, false otherwise. virtual bool show_config_popup(dsp_preset & p_data,fb2k::hwnd_t p_parent) = 0; #else - //! Shows configuration popup. Main thread only! + //! Shows configuration popup. Main thread only! \n + //! Mac: returns NSObjectWrapper holding NSViewController virtual service_ptr show_config_popup( fb2k::hwnd_t parent, dsp_preset_edit_callback_v2::ptr callback ); #endif //! Obsolete method, hidden DSPs now use a different entry class. bool is_user_accessible() { return true; } + static constexpr unsigned flag_playback = 1 << 0, + flag_conversion = 1 << 1; + static bool g_get_interface(service_ptr_t & p_out,const GUID & p_guid); static service_ptr_t g_get_interface(const GUID&); - static bool g_instantiate(service_ptr_t & p_out,const dsp_preset & p_preset); + static bool g_instantiate(service_ptr_t & p_out,const dsp_preset & p_preset, unsigned flags = 0); static bool g_instantiate_default(service_ptr_t & p_out,const GUID & p_guid); static bool g_name_from_guid(pfc::string_base & p_out,const GUID & p_guid); static bool g_dsp_exists(const GUID & p_guid); @@ -389,6 +393,7 @@ class NOVTABLE dsp_entry_v2 : public dsp_entry { FB2K_MAKE_SERVICE_INTERFACE(dsp_entry_v2,dsp_entry); }; +//! \since Late 1.6.x class NOVTABLE dsp_entry_v3 : public dsp_entry_v2 { FB2K_MAKE_SERVICE_INTERFACE(dsp_entry_v3, dsp_entry_v2); public: @@ -397,7 +402,7 @@ class NOVTABLE dsp_entry_v3 : public dsp_entry_v2 { #ifdef _WIN32 //! Shows configuration popup, asynchronous version - creates dialog then returns immediately. \n - //! Since not every DSP implements this, caller must be prepated to call legacy blocking show_config_popup methods instead. \n + //! Since not every DSP implements this, caller must be prepared to call legacy blocking show_config_popup methods instead. \n //! show_config_popup_v3() may throw pfc::exception_not_implemented() to signal host that this DSP doesn't support this method yet. \n //! Main thread only! \n //! @returns Object to retain by host, to be released to request the dialog to be closed. @@ -405,6 +410,13 @@ class NOVTABLE dsp_entry_v3 : public dsp_entry_v2 { #endif }; +//! \since 2.1 +class NOVTABLE dsp_entry_v4 : public dsp_entry_v3 { + FB2K_MAKE_SERVICE_INTERFACE(dsp_entry_v4, dsp_entry_v3); +public: + virtual dsp::ptr instantiate_v4( const dsp_preset & arg, unsigned flags ) = 0; +}; + class NOVTABLE dsp_entry_hidden : public service_base { FB2K_MAKE_SERVICE_INTERFACE_ENTRYPOINT(dsp_entry_hidden); public: @@ -499,6 +511,15 @@ class dsp_entry_v3_impl_t : public dsp_entry_v2_impl_t { #endif }; +template +class dsp_entry_v4_impl_t : public dsp_entry_v3_impl_t< dsp_t, entry_t > { +public: + dsp::ptr instantiate_v4( const dsp_preset & arg, unsigned flags ) override { + PFC_ASSERT( arg.get_owner() == dsp_t::g_get_guid() ); + return new service_impl_t< dsp_t > ( arg, flags ); + } +}; + template class dsp_entry_hidden_t : public dsp_entry_hidden { public: @@ -646,4 +667,9 @@ class dsp_preset_builder : public stream_writer_formatter<> { stream_writer_buffer_simple _m_stream; }; +#ifdef __APPLE__ +// NSObjectWrapper +#include "commonObjects-Apple.h" +#endif + #endif diff --git a/3rdparty/foo_SDK/foobar2000/SDK/dsp_manager.cpp b/3rdparty/foo_SDK/foobar2000/SDK/dsp_manager.cpp index 9d0822d6..3567bcc8 100644 --- a/3rdparty/foo_SDK/foobar2000/SDK/dsp_manager.cpp +++ b/3rdparty/foo_SDK/foobar2000/SDK/dsp_manager.cpp @@ -96,9 +96,9 @@ double dsp_manager::run(dsp_chunk_list * p_list,const metadb_handle_ptr & p_cur_ } } - for(t_dsp_chain::iterator iter = newchain.first(); iter.is_valid(); ++iter) { - if (iter->m_dsp.is_empty()) { - if (!dsp_entry::g_instantiate(iter->m_dsp,iter->m_preset) && !dsp_entry_hidden::g_instantiate(iter->m_dsp, iter->m_preset)) uBugCheck(); + for( auto & iter : newchain ) { + if (iter.m_dsp.is_empty()) { + if (!dsp_entry::g_instantiate(iter.m_dsp,iter.m_preset, m_creationFlags) && !dsp_entry_hidden::g_instantiate(iter.m_dsp, iter.m_preset)) uBugCheck(); } } diff --git a/3rdparty/foo_SDK/foobar2000/SDK/dsp_manager.h b/3rdparty/foo_SDK/foobar2000/SDK/dsp_manager.h index 311ac494..e1976d67 100644 --- a/3rdparty/foo_SDK/foobar2000/SDK/dsp_manager.h +++ b/3rdparty/foo_SDK/foobar2000/SDK/dsp_manager.h @@ -6,7 +6,8 @@ //! Helper class for running audio data through a DSP chain. class dsp_manager { public: - dsp_manager() {} + //! @param creationFlags See dsp_entry::flag_* + dsp_manager(unsigned creationFlags = 0) : m_creationFlags(creationFlags) {} //! Alters the DSP chain configuration. Should be called before the first run() to set the configuration but can be also called anytime later between run() calls. void set_config( const dsp_chain_config & p_data ); @@ -24,6 +25,7 @@ class dsp_manager { bool need_track_change_mark() const; private: + const unsigned m_creationFlags; struct t_dsp_chain_entry { service_ptr_t m_dsp; dsp_preset_impl m_preset; diff --git a/3rdparty/foo_SDK/foobar2000/SDK/file.h b/3rdparty/foo_SDK/foobar2000/SDK/file.h index 9f04ed77..f889b73d 100644 --- a/3rdparty/foo_SDK/foobar2000/SDK/file.h +++ b/3rdparty/foo_SDK/foobar2000/SDK/file.h @@ -30,6 +30,9 @@ namespace foobar2000_io inline bool operator==(const t_filestats& param) const { return m_size == param.m_size && m_timestamp == param.m_timestamp; } inline bool operator!=(const t_filestats& param) const { return m_size != param.m_size || m_timestamp != param.m_timestamp; } + + pfc::string8 describe() const; + pfc::string8 debug() const { return describe(); } }; struct t_filestats2 { @@ -86,6 +89,11 @@ namespace foobar2000_io bool operator!=(const t_filestats2& other) const { return !equals(*this, other); } pfc::string8 describe() const; + pfc::string8 debug() const { return describe(); } + + bool haveSize() const { return m_size != filesize_invalid; } + bool haveTimestamp() const { return m_timestamp != filetimestamp_invalid; } + bool haveTimestampCreate() const { return m_timestampCreate != filetimestamp_invalid; } }; enum { stats2_size = 1 << 0, @@ -156,7 +164,7 @@ namespace foobar2000_io //! Helper function; reads a string (with a 32-bit header indicating length in bytes followed by UTF-8 encoded data without a null terminator). void read_string(pfc::string_base& p_out, abort_callback& p_abort); //! Helper function; alternate way of storing strings; assumes string takes space up to end of stream. - void read_string_raw(pfc::string_base& p_out, abort_callback& p_abort); + void read_string_raw(pfc::string_base& p_out, abort_callback& p_abort, size_t sanity = SIZE_MAX); //! Helper function; reads a string (with a 32-bit header indicating length in bytes followed by UTF-8 encoded data without a null terminator). pfc::string read_string(abort_callback& p_abort); @@ -283,6 +291,7 @@ namespace foobar2000_io //! Retrieves mime type of the file. //! @param p_out Receives content type string on success. virtual bool get_content_type(pfc::string_base& p_out) = 0; + pfc::string8 get_content_type(); //! Hint, returns whether the file is already fully buffered into memory. virtual bool is_in_memory() { return false; } @@ -324,6 +333,7 @@ namespace foobar2000_io //! Security helper; fails early with exception_io_data_truncation if it is not possible to read this amount of bytes from this file at this position. void probe_remaining(t_filesize bytes, abort_callback& p_abort); + bool probe_remaining_ex(t_filesize bytes, abort_callback& p_abort); //! Helper; throws exception_io_object_not_seekable if file is not seekable. void ensure_seekable(); @@ -368,9 +378,19 @@ namespace foobar2000_io //! file_v2 wrapper. t_filestats2 get_stats2_(uint32_t f, abort_callback& a); + //! file_v2 wrapper. + void set_stats(t_filestats2 const&, abort_callback&); + //! file_v2 wrapper. t_filetimestamp get_time_created(abort_callback& a); + //! Alternate version of read() intended for network resources.\n + //! See: stream_receive::receive(); \n + //! If not implemented by this object, uses plain read(). + size_t receive(void*, size_t, abort_callback&); + + void commit(abort_callback& a) {flushFileBuffers(a);} + FB2K_MAKE_SERVICE_INTERFACE(file, service_base); }; @@ -443,23 +463,11 @@ namespace foobar2000_io //! Implementation helper - contains dummy implementations of methods that modify the file template class file_readonly_t : public t_base { public: - void resize(t_filesize p_size, abort_callback& p_abort) { throw exception_io_denied(); } - void write(const void* p_buffer, t_size p_bytes, abort_callback& p_abort) { throw exception_io_denied(); } + void resize(t_filesize p_size, abort_callback& p_abort) override { throw exception_io_denied(); } + void write(const void* p_buffer, t_size p_bytes, abort_callback& p_abort) override { throw exception_io_denied(); } }; typedef file_readonly_t file_readonly; - class file_streamstub : public file_readonly { - public: - t_size read(void*, t_size, abort_callback&) { return 0; } - t_filesize get_size(abort_callback&) { return filesize_invalid; } - t_filesize get_position(abort_callback&) { return 0; } - bool get_content_type(pfc::string_base&) { return false; } - bool is_remote() { return true; } - void reopen(abort_callback&) {} - void seek(t_filesize, abort_callback&) { throw exception_io_object_not_seekable(); } - bool can_seek() { return false; } - }; - //! \since 2.0 class file_v2 : public file { FB2K_MAKE_SERVICE_INTERFACE(file_v2, file); @@ -474,8 +482,10 @@ namespace foobar2000_io virtual size_t lowLevelIO(const GUID& guid, size_t arg1, void* arg2, size_t arg2size, abort_callback& abort) { return 0; } - // Old method wrapped to get_stats2() + // Old methods wrapped to get_stats2() t_filetimestamp get_timestamp(abort_callback& p_abort) override; + bool is_remote() override; + t_filesize get_size(abort_callback& p_abort) override; }; //! \since 1.6.7 @@ -486,4 +496,14 @@ namespace foobar2000_io virtual void get_connected_path(pfc::string_base& out) = 0; }; -} \ No newline at end of file + + //! \since 2.1 + //! Extension to file object, implemented by network readers. Adds receive() method. + class stream_receive : public service_base { + FB2K_MAKE_SERVICE_INTERFACE(stream_receive, service_base); + public: + //! Alternate version of read() intended for network resources.\n + //! Returns as soon as any data is available (usually less than requested), or EOF has been reached (0 returned). + virtual size_t receive(void*, size_t, abort_callback&) = 0; + }; +} diff --git a/3rdparty/foo_SDK/foobar2000/SDK/fileDialog.h b/3rdparty/foo_SDK/foobar2000/SDK/fileDialog.h index ab3bfb17..87b0f24f 100644 --- a/3rdparty/foo_SDK/foobar2000/SDK/fileDialog.h +++ b/3rdparty/foo_SDK/foobar2000/SDK/fileDialog.h @@ -3,18 +3,21 @@ #include namespace fb2k { - + + typedef std::function fileDialogReply_t; + typedef std::function fileDialogGetPath_t; + class NOVTABLE fileDialogNotify : public service_base { FB2K_MAKE_SERVICE_INTERFACE( fileDialogNotify, service_base ); public: //! Called when user has cancelled the dialog. virtual void dialogCancelled() = 0; //! Called when the user has dismissed the dialog having selected some content. - //! @param fsItems Array of fsItemBase objects or strings, depending on the platform. Should accept either form. Typically, file dialogs will handle fsItems but Add Location will handle path strings. Special case: playlist format chooser sends chosen format name as a string (one array item). + //! @param items Array of fsItemBase objects or strings, depending on the platform. Should accept either form. Typically, file dialogs will handle fsItems but Add Location will handle path strings. Special case: playlist format chooser sends chosen format name as a string (one array item). virtual void dialogOK2( arrayRef items ) = 0; - static fileDialogNotify::ptr create( std::function recv ); - }; + static fileDialogNotify::ptr create( fileDialogReply_t recv ); + }; class NOVTABLE fileDialogSetup : public service_base { FB2K_MAKE_SERVICE_INTERFACE( fileDialogSetup, service_base ); @@ -52,6 +55,10 @@ namespace fb2k { //! For an example, on Windows most filedialogs work synchronously while on OSX all of them work asynchronously. //! @param notify Notify object invoked upon dialog completion. virtual void run(fileDialogNotify::ptr notify) = 0; + + //! Helper, creates fileDialogNotify for you. + void run (fileDialogReply_t reply); + void runSimple (fileDialogGetPath_t reply); }; class NOVTABLE fileDialog : public service_base { diff --git a/3rdparty/foo_SDK/foobar2000/SDK/file_info.cpp b/3rdparty/foo_SDK/foobar2000/SDK/file_info.cpp index 11179f08..d5c721d7 100644 --- a/3rdparty/foo_SDK/foobar2000/SDK/file_info.cpp +++ b/3rdparty/foo_SDK/foobar2000/SDK/file_info.cpp @@ -11,28 +11,25 @@ static constexpr char info_WAVEFORMATEXTENSIBLE_CHANNEL_MASK[] = "WAVEFORMATEXTENSIBLE_CHANNEL_MASK"; -const float replaygain_info::peak_invalid = -1; -const float replaygain_info::gain_invalid = -1000; - t_size file_info::meta_find_ex(const char * p_name,t_size p_name_length) const { t_size n, m = meta_get_count(); for(n=0;nmeta_find(name); + if ( idx != SIZE_MAX ) { + if (field_value_equals(*this, idx, source, walk)) continue; + } + + copy_meta_single(source, walk); + changed = true; + } + return changed; +} + void file_info::copy_meta_single(const file_info & p_source,t_size p_index) { copy_meta_single_rename(p_source,p_index,p_source.meta_enum_name(p_index)); @@ -109,7 +122,7 @@ void file_info::copy_meta_single_nocheck(const file_info & p_source,t_size p_ind { const char * name = p_source.meta_enum_name(p_index); t_size n, m = p_source.meta_enum_value_count(p_index); - t_size new_index = pfc_infinite; + t_size new_index = SIZE_MAX; for(n=0;n= max) return 0; return meta_enum_value(index,p_index); } const char * file_info::info_get_ex(const char * p_name,t_size p_name_length) const { - t_size index = info_find_ex(p_name,p_name_length); - if (index == pfc_infinite) return 0; + auto index = info_find_ex(p_name,p_name_length); + if (index == SIZE_MAX) return 0; return info_enum_value(index); } @@ -290,7 +303,24 @@ unsigned file_info::info_get_decoded_bps() const val = info_get_int("bitspersample"); if (is_valid_bps(val)) return (unsigned)val; return 0; +} +bool file_info::info_get_codec_long(pfc::string_base& out, const char * delim) const { + const char * codec; + codec = this->info_get("codec_long"); + if (codec != nullptr) { + out = codec; return true; + } + codec = this->info_get("codec"); + if (codec != nullptr) { + out = codec; + const char * profile = this->info_get("codec_profile"); + if (profile != nullptr) { + out << delim << profile; + } + return true; + } + return false; } void file_info::reset() @@ -311,19 +341,19 @@ void file_info::reset_replaygain() void file_info::copy_meta_single_rename_ex(const file_info & p_source,t_size p_index,const char * p_new_name,t_size p_new_name_length) { t_size n, m = p_source.meta_enum_value_count(p_index); - t_size new_index = pfc_infinite; + t_size new_index = SIZE_MAX; for(n=0;n 0 ) info_set_bitrate(b); } +void file_info::info_set_bitspersample(uint32_t val, bool isFloat) { + // Bits per sample semantics + // "bitspersample" is set to integer value of bits per sample + // "bitspersample_extra" is used for bps of 32 or 64, either "floating-point" or "fixed-point" + // bps other than 32 or 64 are implicitly fixed-point as floating-point for such makes no sense + + info_set_int("bitspersample", val); + if ( isFloat || val == 32 || val == 64 ) { + info_set("bitspersample_extra", isFloat ? "floating-point" : "fixed-point"); + } else { + info_remove("bitspersample_extra"); + } +} + bool file_info::is_encoding_float() const { auto bs = info_get_int("bitspersample"); auto extra = info_get("bitspersample_extra"); @@ -525,7 +569,7 @@ bool file_info::g_is_info_equal(const file_info & p_item1,const file_info & p_it } for(t_size n1=0; n1 0) FB2K_console_formatter() << "Duration: " << pfc::format_time_ex(get_length(), 6); pfc::string_formatter temp; - for(t_size metaWalk = 0; metaWalk < meta_get_count(); ++metaWalk) { + const auto numMeta = meta_get_count(), numInfo = info_get_count(); + if (numMeta == 0) { + FB2K_console_formatter() << "Meta is blank"; + } else for(t_size metaWalk = 0; metaWalk < numMeta; ++metaWalk) { const char * name = meta_enum_name( metaWalk ); const auto valCount = meta_enum_value_count( metaWalk ); for ( size_t valWalk = 0; valWalk < valCount; ++valWalk ) { @@ -601,7 +648,9 @@ void file_info::to_console() const { FB2K_console_formatter() << "Meta: " << meta_enum_name(metaWalk) << " = " << temp; */ } - for(t_size infoWalk = 0; infoWalk < info_get_count(); ++infoWalk) { + if (numInfo == 0) { + FB2K_console_formatter() << "Info is blank"; + } else for(t_size infoWalk = 0; infoWalk < numInfo; ++infoWalk) { FB2K_console_formatter() << "Info: " << info_enum_name(infoWalk) << " = " << info_enum_value(infoWalk); } } @@ -734,11 +783,11 @@ void file_info::from_stream( stream_reader * stream, abort_callback & abort ) { for(;;) { in.read_string_nullterm( tempName ); if (tempName.length() == 0) break; - size_t metaIndex = pfc_infinite; + size_t metaIndex = SIZE_MAX; for(;;) { in.read_string_nullterm( tempValue ); if (tempValue.length() == 0) break; - if (metaIndex == pfc_infinite) metaIndex = this->meta_add( tempName, tempValue ); + if (metaIndex == SIZE_MAX) metaIndex = this->meta_add( tempName, tempValue ); else this->meta_add_value( metaIndex, tempValue ); } } @@ -801,11 +850,11 @@ void file_info::from_mem( const void * memPtr, size_t memSize ) { for(;;) { const char * metaName = _readString( walk, remaining ); if (*metaName == 0) break; - size_t metaIndex = pfc_infinite; + size_t metaIndex = SIZE_MAX; for(;;) { const char * metaValue = _readString( walk, remaining ); if (*metaValue == 0) break; - if (metaIndex == pfc_infinite) metaIndex = this->meta_add( metaName, metaValue ); + if (metaIndex == SIZE_MAX) metaIndex = this->meta_add( metaName, metaValue ); else this->meta_add_value( metaIndex, metaName ); } } @@ -856,7 +905,6 @@ bool file_info::unicode_normalize_C() { const size_t total = this->meta_get_count(); bool changed = false; for (size_t mwalk = 0; mwalk < total; ++mwalk) { - const char* name = this->meta_enum_name(mwalk); const size_t totalV = this->meta_enum_value_count(mwalk); for (size_t vwalk = 0; vwalk < totalV; ++vwalk) { const char* val = this->meta_enum_value(mwalk, vwalk); @@ -870,4 +918,58 @@ bool file_info::unicode_normalize_C() { } } return changed; -} \ No newline at end of file +} + +void file_info::meta_enumerate(meta_enumerate_t cb) const { + const size_t nMeta = this->meta_get_count(); + for (size_t metaWalk = 0; metaWalk < nMeta; ++metaWalk) { + const char* name = this->meta_enum_name(metaWalk); + const size_t nValue = this->meta_enum_value_count(metaWalk); + for (size_t valueWalk = 0; valueWalk < nValue; ++valueWalk) { + const char* value = this->meta_enum_value(metaWalk, valueWalk); + cb(name, value); + } + } +} + +#ifdef FOOBAR2000_MOBILE +#include "album_art.h" +#include "hasher_md5.h" + +void file_info::info_set_pictures( const GUID * guids, size_t size ) { + this->info_set("pictures", album_art_ids::ids_to_string(guids, size) ); +} + +pfc::array_t file_info::info_get_pictures( ) const { + return album_art_ids::string_to_ids( this->info_get( "pictures" ) ); +} + +uint64_t file_info::makeMetaHash() const { + pfc::string_formatter temp; + + auto doMeta = [&] ( const char * meta ) { + const char * p = meta_get(meta, 0); + if (p != nullptr) temp << p; + temp << "\n"; + }; + auto doMetaInt = [&] ( const char * meta ) { + const char * p = meta_get(meta, 0); + if (p != nullptr) { + auto s = strchr(p, '/' ); if ( s != nullptr ) p = s+1; + while(*p == '0') ++p; + temp << p; + } + temp << "\n"; + }; + doMeta("title"); + doMeta("artist"); + doMeta("album"); + doMetaInt("tracknumber"); + doMetaInt("discnumber"); + + if (temp.length() == 5) return 0; + + return hasher_md5::get()->process_single( temp.c_str(), temp.length( ) ).xorHalve(); +} + +#endif // FOOBAR2000_MOBILE diff --git a/3rdparty/foo_SDK/foobar2000/SDK/file_info.h b/3rdparty/foo_SDK/foobar2000/SDK/file_info.h index 67a08a98..c4530cc0 100644 --- a/3rdparty/foo_SDK/foobar2000/SDK/file_info.h +++ b/3rdparty/foo_SDK/foobar2000/SDK/file_info.h @@ -1,16 +1,18 @@ #pragma once #include "audio_chunk.h" +#include //! Structure containing ReplayGain scan results from some playable object, also providing various helper methods to manipulate those results. struct replaygain_info { - float m_album_gain,m_track_gain; - float m_album_peak,m_track_peak; + static constexpr float peak_invalid = -1, gain_invalid = -1000; + + float m_album_gain = gain_invalid, m_track_gain = gain_invalid; + float m_album_peak = peak_invalid, m_track_peak = peak_invalid; enum {text_buffer_size = 16 }; typedef char t_text_buffer[text_buffer_size]; - static const float peak_invalid, gain_invalid; static bool g_format_gain(float p_value,char p_buffer[text_buffer_size]); static bool g_format_peak(float p_value,char p_buffer[text_buffer_size]); @@ -156,6 +158,8 @@ class NOVTABLE file_info { bool meta_format(const char * p_name,pfc::string_base & p_out, const char * separator = ", ") const; void meta_format_entry(t_size index, pfc::string_base & p_out, const char * separator = ", ") const;//same as meta_format but takes index instead of meta name. + typedef std::function meta_enumerate_t; + void meta_enumerate(meta_enumerate_t) const; bool info_exists_ex(const char * p_name,t_size p_name_length) const; void info_remove_index(t_size p_index); @@ -163,15 +167,15 @@ class NOVTABLE file_info { bool info_remove_ex(const char * p_name,t_size p_name_length); const char * info_get_ex(const char * p_name,t_size p_name_length) const; - inline t_size meta_find(const char * p_name) const {return meta_find_ex(p_name,SIZE_MAX);} - inline bool meta_exists(const char * p_name) const {return meta_exists_ex(p_name,SIZE_MAX);} - inline void meta_remove_field(const char * p_name) {meta_remove_field_ex(p_name,SIZE_MAX);} - inline t_size meta_set(const char * p_name,const char * p_value) {return meta_set_ex(p_name,SIZE_MAX,p_value,SIZE_MAX);} + inline t_size meta_find(const char* p_name) const { PFC_ASSERT(p_name != nullptr); return meta_find_ex(p_name, SIZE_MAX); } + inline bool meta_exists(const char* p_name) const { PFC_ASSERT(p_name != nullptr); return meta_exists_ex(p_name, SIZE_MAX); } + inline void meta_remove_field(const char* p_name) { PFC_ASSERT(p_name != nullptr); meta_remove_field_ex(p_name, SIZE_MAX); } + inline t_size meta_set(const char* p_name, const char* p_value) { PFC_ASSERT(p_name != nullptr && p_value != nullptr); return meta_set_ex(p_name, SIZE_MAX, p_value, SIZE_MAX); } inline void meta_insert_value(t_size p_index,t_size p_value_index,const char * p_value) {meta_insert_value_ex(p_index,p_value_index,p_value,SIZE_MAX);} inline void meta_add_value(t_size p_index,const char * p_value) {meta_add_value_ex(p_index,p_value,SIZE_MAX);} - inline const char* meta_get(const char * p_name,t_size p_index) const {return meta_get_ex(p_name,SIZE_MAX,p_index);} - inline t_size meta_get_count_by_name(const char * p_name) const {return meta_get_count_by_name_ex(p_name,SIZE_MAX);} - inline t_size meta_add(const char * p_name,const char * p_value) {return meta_add_ex(p_name,SIZE_MAX,p_value,SIZE_MAX);} + inline const char* meta_get(const char* p_name, t_size p_index) const { PFC_ASSERT(p_name != nullptr); return meta_get_ex(p_name, SIZE_MAX, p_index); } + inline t_size meta_get_count_by_name(const char* p_name) const { PFC_ASSERT(p_name != nullptr); return meta_get_count_by_name_ex(p_name, SIZE_MAX); } + inline t_size meta_add(const char* p_name, const char* p_value) { PFC_ASSERT(p_name != nullptr && p_value != nullptr); return meta_add_ex(p_name, SIZE_MAX, p_value, SIZE_MAX); } inline void meta_modify_value(t_size p_index,t_size p_value_index,const char * p_value) {meta_modify_value_ex(p_index,p_value_index,p_value,SIZE_MAX);} @@ -201,6 +205,7 @@ class NOVTABLE file_info { inline void copy_meta_single_rename(const file_info & p_source,t_size p_index,const char * p_new_name) {copy_meta_single_rename_ex(p_source,p_index,p_new_name,SIZE_MAX);} void overwrite_info(const file_info & p_source); void overwrite_meta(const file_info & p_source); + bool overwrite_meta_if_changed( const file_info & source ); t_int64 info_get_int(const char * name) const; t_int64 info_get_length_samples() const; @@ -213,9 +218,9 @@ class NOVTABLE file_info { void info_set_replaygain_album_peak(float value); inline t_int64 info_get_bitrate_vbr() const {return info_get_int("bitrate_dynamic");} - inline void info_set_bitrate_vbr(t_int64 val) {info_set_int("bitrate_dynamic",val);} + inline void info_set_bitrate_vbr(t_int64 val_kbps) {info_set_int("bitrate_dynamic",val_kbps);} inline t_int64 info_get_bitrate() const {return info_get_int("bitrate");} - inline void info_set_bitrate(t_int64 val) { PFC_ASSERT(val > 0); info_set_int("bitrate", val); } + inline void info_set_bitrate(t_int64 val_kbps) { PFC_ASSERT(val_kbps > 0); info_set_int("bitrate", val_kbps); } //! Set number of channels @@ -231,9 +236,15 @@ class NOVTABLE file_info { //! Returns channel mask value. 0 if not set, use default for the channel count then. uint32_t info_get_wfx_chanMask() const; + //! Is a lossy codec? bool is_encoding_lossy() const; + //! Is lossless/PCM that can't be sanely represented in this fb2k build due to audio_sample limitations? \n + //! Always returns false in 64-bit fb2k. bool is_encoding_overkill() const; + //! Floating-point PCM used? bool is_encoding_float() const; + //! Helper; sets bit depth of lossless/PCM format. + void info_set_bitspersample(uint32_t val, bool isFloat = false); //! Sets bitrate value using file size in bytes and duration. void info_calculate_bitrate(uint64_t p_filesize,double p_length); @@ -241,6 +252,9 @@ class NOVTABLE file_info { //! Returns decoder-output bit depth - what sample format is being converted to foobar2000 audio_sample. 0 if unknown. unsigned info_get_decoded_bps() const; + //! Foramts long codec name ( codec + profile ) + bool info_get_codec_long( pfc::string_base & out, const char * delim = " / ") const; + private: void merge(const pfc::list_base_const_t & p_sources); public: @@ -296,6 +310,13 @@ class NOVTABLE file_info { //! Normalize values to Unicode form C //! @returns true if changed, false otherwise bool unicode_normalize_C(); + + +#ifdef FOOBAR2000_MOBILE + void info_set_pictures( const GUID * guids, size_t size ); + pfc::array_t info_get_pictures( ) const; + uint64_t makeMetaHash() const; +#endif protected: file_info() {} ~file_info() {} diff --git a/3rdparty/foo_SDK/foobar2000/SDK/file_info_impl.cpp b/3rdparty/foo_SDK/foobar2000/SDK/file_info_impl.cpp index 430803eb..2ebbffd5 100644 --- a/3rdparty/foo_SDK/foobar2000/SDK/file_info_impl.cpp +++ b/3rdparty/foo_SDK/foobar2000/SDK/file_info_impl.cpp @@ -91,12 +91,12 @@ void file_info_impl::info_remove_mask(const bit_array & p_mask) } -file_info_impl::file_info_impl(const file_info & p_source) : m_length(0) +file_info_impl::file_info_impl(const file_info & p_source) { copy(p_source); } -file_info_impl::file_info_impl(const file_info_impl & p_source) : m_length(0) +file_info_impl::file_info_impl(const file_info_impl & p_source) { copy(p_source); } @@ -107,10 +107,7 @@ const file_info_impl & file_info_impl::operator=(const file_info_impl & p_source return *this; } -file_info_impl::file_info_impl() : m_length(0) -{ - m_replaygain.reset(); -} +file_info_impl::file_info_impl() {} double file_info_impl::get_length() const { @@ -156,11 +153,19 @@ void file_info_impl_utils::info_storage::remove_mask(const bit_array & p_mask) { } +size_t file_info_impl_utils::meta_storage::add_blank(const char* name) { + meta_entry e; + e.m_name = name; + const auto ret = m_data.size(); + m_data.add_item(std::move(e)); + return ret; +} t_size file_info_impl_utils::meta_storage::add_entry(const char * p_name,t_size p_name_length,const char * p_value,t_size p_value_length) { - meta_entry temp(p_name,p_name_length,p_value,p_value_length); - return pfc::append_swap_t(m_data,temp); + const auto ret = m_data.size(); + m_data.add_item(meta_entry(p_name, p_name_length, p_value, p_value_length)); + return ret; } void file_info_impl_utils::meta_storage::insert_value(t_size p_index,t_size p_value_index,const char * p_value,t_size p_value_length) diff --git a/3rdparty/foo_SDK/foobar2000/SDK/file_info_impl.h b/3rdparty/foo_SDK/foobar2000/SDK/file_info_impl.h index ed6fad68..0f10f246 100644 --- a/3rdparty/foo_SDK/foobar2000/SDK/file_info_impl.h +++ b/3rdparty/foo_SDK/foobar2000/SDK/file_info_impl.h @@ -71,6 +71,7 @@ namespace file_info_impl_utils { class meta_storage { public: + size_t add_blank(const char* name); t_size add_entry(const char * p_name,t_size p_name_length,const char * p_value,t_size p_value_length); void insert_value(t_size p_index,t_size p_value_index,const char * p_value,t_size p_value_length); void modify_value(t_size p_index,t_size p_value_index,const char * p_value,t_size p_value_length); @@ -131,14 +132,12 @@ class file_info_impl : public file_info protected: t_size meta_set_nocheck_ex(const char * p_name,t_size p_name_length,const char * p_value,t_size p_value_length); t_size info_set_nocheck_ex(const char * p_name,t_size p_name_length,const char * p_value,t_size p_value_length); -private: - file_info_impl_utils::meta_storage m_meta; file_info_impl_utils::info_storage m_info; - double m_length; + double m_length = 0; replaygain_info m_replaygain; }; diff --git a/3rdparty/foo_SDK/foobar2000/SDK/file_info_merge.cpp b/3rdparty/foo_SDK/foobar2000/SDK/file_info_merge.cpp index f1e424fe..d3c94625 100644 --- a/3rdparty/foo_SDK/foobar2000/SDK/file_info_merge.cpp +++ b/3rdparty/foo_SDK/foobar2000/SDK/file_info_merge.cpp @@ -164,6 +164,13 @@ void file_info::_set_tag(const file_info & tag) { this->info_set(n, tag.info_enum_value( iWalk ) ); } } + +#ifdef FOOBAR2000_FILE_INFO_PICTURES + { + auto p = tag.info_get("pictures"); + if ( p != nullptr ) this->info_set("pictures", p); + } +#endif } void file_info::_add_tag(const file_info & otherTag) { @@ -188,4 +195,11 @@ void file_info::_add_tag(const file_info & otherTag) { } } } + +#ifdef FOOBAR2000_FILE_INFO_PICTURES + if (this->info_get("pictures") == nullptr) { + auto p = otherTag.info_get("pictures"); + if ( p != nullptr ) info_set("pictures", p); + } +#endif } diff --git a/3rdparty/foo_SDK/foobar2000/SDK/filesystem.cpp b/3rdparty/foo_SDK/foobar2000/SDK/filesystem.cpp index 9736cdc9..baa2679e 100644 --- a/3rdparty/foo_SDK/foobar2000/SDK/filesystem.cpp +++ b/3rdparty/foo_SDK/foobar2000/SDK/filesystem.cpp @@ -350,6 +350,21 @@ bool archive::is_our_archive( const char * path ) { return true; // accept all files } +void archive_impl::extract_filename_ext(const char * path, pfc::string_base & outFN) { + pfc::string8 dummy, subpath; + if (archive_impl::g_parse_unpack_path(path, dummy, subpath)) { + outFN = pfc::filename_ext_v2( subpath ); + } else { + PFC_ASSERT(!"???"); + filesystem_v3::extract_filename_ext(path, outFN); + } +} + +bool archive_impl::get_display_name_short(const char* in, pfc::string_base& out) { + extract_filename_ext(in ,out); + return true; +} + bool archive_impl::get_canonical_path(const char * path,pfc::string_base & out) { if (is_our_path(path)) @@ -494,6 +509,27 @@ void archive_impl::g_make_unpack_path(pfc::string_base & path,const char * archi void archive_impl::make_unpack_path(pfc::string_base & path,const char * archive,const char * file) {g_make_unpack_path(path,archive,file,get_archive_type());} +fb2k::arrayRef archive_impl::archive_list_v4( fsItemFilePtr item, file::ptr readerOptional, abort_callback & a ) { + + const auto baseStats = item->getStatsOpportunist(); + PFC_ASSERT( ! baseStats.is_folder() ); + auto ret = fb2k::arrayMutable::arrayWithCapacity(256); + + auto reader = readerOptional; + if ( reader.is_empty() ) reader = item->openRead(a); + try { + this->archive_list( item->canonicalPath()->c_str(), reader, [&] ( const char * URL, t_filestats const & stats, file::ptr ) { + t_filestats2 stats2 = t_filestats2::from_legacy( stats ); + stats2.set_file(); stats2.set_remote( baseStats.is_remote() ); stats2.set_readonly(true); + archive * blah = this; // multi inheritance fix, more than one path to filesystem which has makeItemFileStd() + ret->add(blah->makeItemFileStd(URL, stats2)); + }, false, a); + } catch( exception_io_data ) { + if ( ret->count() == 0 ) throw; + } + return ret->makeConst(); + +} namespace { @@ -812,17 +848,20 @@ void stream_reader::read_string(pfc::string_base & p_out,abort_callback & p_abor read_string_ex(p_out,length,p_abort); } -void stream_reader::read_string_raw(pfc::string_base & p_out,abort_callback & p_abort) { - enum {delta = 256}; +void stream_reader::read_string_raw(pfc::string_base & p_out,abort_callback & p_abort, size_t sanity) { + enum {delta = 1024}; char buffer[delta]; p_out.reset(); + size_t didRead = 0; for(;;) { - t_size delta_done; - delta_done = read(buffer,delta,p_abort); + auto delta_done = read(buffer,delta,p_abort); p_out.add_string(buffer,delta_done); if (delta_done < delta) break; + didRead += delta; + if (didRead > sanity) throw exception_io_data(); } } + void stream_writer::write_string(const char * p_string,t_size p_len,abort_callback & p_abort) { t_uint32 len = pfc::downcast_guarded(pfc::strlen_max(p_string,p_len)); write_lendian_t(len,p_abort); @@ -965,6 +1004,10 @@ PFC_NORETURN void foobar2000_io::exception_io_from_win32(DWORD p_code) { case ERROR_INVALID_FUNCTION: // Happens when trying to link files on FAT32 etc throw exception_io_unsupported_feature(); +#if 0 + case ERROR_BAD_LENGTH: + FB2K_BugCheckEx("ERROR_BAD_LENGTH"); +#endif default: throw exception_io_win32_ex(p_code); } @@ -994,7 +1037,8 @@ PFC_NORETURN void foobar2000_io::exception_io_from_nix(int code) { // Should not actually get here PFC_ASSERT(!"Trying to seek a nonseekable stream"); throw exception_io_object_not_seekable(); - + case ENOTDIR: + throw exception_io_not_directory(); default: pfc::throw_exception_with_message< exception_io>( PFC_string_formatter() << "Unknown I/O error (#" << code << ")"); @@ -1034,14 +1078,18 @@ t_filesize file::get_remaining(abort_callback & p_abort) { return length - position; } -void file::probe_remaining(t_filesize bytes, abort_callback & p_abort) { +bool file::probe_remaining_ex(t_filesize bytes, abort_callback& p_abort) { t_filesize length = get_size(p_abort); - if (length != ~0) { + if (length != filesize_invalid) { t_filesize remaining = length - get_position(p_abort); - if (remaining < bytes) throw exception_io_data_truncation(); + if (remaining < bytes) return false; } + return true; } +void file::probe_remaining(t_filesize bytes, abort_callback & p_abort) { + if (!probe_remaining_ex(bytes, p_abort)) throw exception_io_data_truncation(); +} t_filesize file::g_transfer(service_ptr_t p_src,service_ptr_t p_dst,t_filesize p_bytes,abort_callback & p_abort) { return g_transfer(pfc::implicit_cast(p_src.get_ptr()),pfc::implicit_cast(p_dst.get_ptr()),p_bytes,p_abort); @@ -1124,8 +1172,13 @@ bool foobar2000_io::_extract_native_path_ptr(const char * & p_fspath) { return true; } bool foobar2000_io::extract_native_path(const char * p_fspath,pfc::string_base & p_native) { - if (!_extract_native_path_ptr(p_fspath)) return false; + if (strstr(p_fspath, "://") != nullptr) { + if (!_extract_native_path_ptr(p_fspath)) return false; + } p_native = p_fspath; +#ifndef _WIN32 + expandHomeDir( p_native ); +#endif return true; } @@ -1140,6 +1193,30 @@ bool foobar2000_io::extract_native_path_ex(const char * p_fspath, pfc::string_ba return true; } +static bool extract_native_path_fsv3(const char* in, pfc::string_base& out, abort_callback& a) { + if (foobar2000_io::extract_native_path(in, out)) return true; + filesystem_v3::ptr v3; + if (v3 &= filesystem::tryGet(in)) { + auto n = v3->getNativePath(in, a); + if ( n.is_valid() ) { + out = n->c_str(); return true; + } + } + return false; +} + +bool foobar2000_io::extract_native_path_archive_aware_ex(const char* in, pfc::string_base& out, abort_callback& a) { + if (extract_native_path_fsv3(in, out, a)) return true; + + if (archive_impl::g_is_unpack_path(in)) { + pfc::string8 arc, dummy; + if (archive_impl::g_parse_unpack_path(in, arc, dummy)) { + return extract_native_path_fsv3(arc, out, a); + } + } + return false; +} + bool foobar2000_io::extract_native_path_archive_aware(const char * in, pfc::string_base & out) { if (foobar2000_io::extract_native_path(in, out)) return true; if (archive_impl::g_is_unpack_path(in)) { @@ -1424,8 +1501,36 @@ bool filesystem::directory_exists(const char * path, abort_callback & abort) { directory_callback_dummy cb; list_directory(path, cb, abort); return true; - } catch (exception_io const &) { return false; } + } catch (exception_io) { return false; } } + +bool filesystem::exists(const char* path, abort_callback& a) { + // for rare cases of code test if EITHER FILE OR FOLDER exists at path + filesystem_v3::ptr v3; + if (v3 &= this) { + try { + v3->get_stats2(path, stats2_fileOrFolder, a); + return true; + } catch (exception_io_not_found) { return false; } + } + filesystem_v2::ptr v2; + if (v2 &= this) { + return v2->file_exists(path, a) || v2->directory_exists(path, a); + } + + try { + t_filestats stats; bool writable; + get_stats(path, stats, writable, a); + return true; + } catch (exception_io) { } + try { + directory_callback_dummy cb; + list_directory(path, cb, a); + return true; + } catch (exception_io) { } + return false; +} + bool filesystem::file_exists(const char * path, abort_callback & abort) { filesystem_v2::ptr v2; if ( v2 &= this ) { @@ -1540,8 +1645,12 @@ void filesystem::read_whole_file_fallback(const char * path, mem_block_container } bool filesystem::is_transacted() { +#if FB2K_SUPPORT_TRANSACTED_FILESYSTEM filesystem_transacted::ptr p; return ( p &= this ); +#else + return false; +#endif } void filesystem::rewrite_file(const char* path, abort_callback& abort, double opTimeout, const void* payload, size_t bytes) { @@ -1652,7 +1761,7 @@ bool filesystem_v2::make_directory_check(const char * path, abort_callback & abo return rv; } - +#if FB2K_SUPPORT_TRANSACTED_FILESYSTEM filesystem_transacted::ptr filesystem_transacted::create( const char * pathFor ) { service_enum_t e; filesystem_transacted_entry::ptr p; @@ -1664,13 +1773,16 @@ filesystem_transacted::ptr filesystem_transacted::create( const char * pathFor ) } return nullptr; } +#endif bool filesystem::commit_if_transacted(abort_callback &abort) { bool rv = false; +#if FB2K_SUPPORT_TRANSACTED_FILESYSTEM filesystem_transacted::ptr t; if ( t &= this ) { t->commit( abort ); rv = true; } +#endif return rv; } @@ -1782,7 +1894,20 @@ void filesystem_v3::get_stats(const char* p_path, t_filestats& p_stats, bool& p_ t_filetimestamp file_v2::get_timestamp(abort_callback& p_abort) { return this->get_stats2(stats2_timestamp, p_abort).m_timestamp; } +bool file_v2::is_remote() { + return this->get_stats2(stats2_remote, fb2k::noAbort).is_remote(); +} + +t_filesize file_v2::get_size(abort_callback& p_abort) { + return this->get_stats2(stats2_size, p_abort).m_size; +} + +pfc::string8 file::get_content_type() { + pfc::string8 ret; + if (!this->get_content_type(ret)) ret.clear(); + return ret; +} t_filestats2 file::get_stats2_(uint32_t f, abort_callback& a) { t_filestats2 ret; @@ -1974,18 +2099,13 @@ fsItemBase::ptr filesystem_v3::findItem(const char* path, abort_callback& p_abor try { #endif pfc::string8 canonical; - get_canonical_path(path, canonical); - - if (this->is_remote(canonical)) { - // Do not perform expensive checks for remote filesystems - return makeItemFileStd(canonical); - } - - if (this->file_exists(canonical, p_abort)) { - return makeItemFileStd(canonical); - } - if (this->directory_exists(canonical, p_abort)) { - return makeItemFolderStd(canonical); + if (get_canonical_path(path, canonical)) { + auto stats = this->get_stats2(path, stats2_all, p_abort); + if ( stats.is_folder() ) { + return makeItemFolderStd(canonical, stats); + } else { + return makeItemFileStd(canonical, stats ); + } } throw exception_io_not_found(); #if PFC_DEBUG @@ -2003,9 +2123,11 @@ fsItemFile::ptr filesystem_v3::findItemFile(const char* path, abort_callback& p_ try { #endif pfc::string8 canonical; - get_canonical_path(path, canonical); - if (this->is_remote(canonical) || this->file_exists(canonical, p_abort)) { - return makeItemFileStd(canonical); + if (get_canonical_path(path, canonical)) { + auto stats = this->get_stats2( canonical, stats2_all, p_abort); + if ( stats.is_file() ) { + return makeItemFileStd(canonical, stats ); + } } throw exception_io_not_found(); #if PFC_DEBUG @@ -2023,9 +2145,11 @@ fsItemFolder::ptr filesystem_v3::findItemFolder(const char* path, abort_callback try { #endif pfc::string8 canonical; - if (!get_canonical_path(path, canonical)) throw exception_io_not_found(); - if (this->is_remote(canonical) || this->directory_exists(canonical, p_abort)) { - return makeItemFolderStd(canonical); + if (get_canonical_path(path, canonical)) { + auto stats = this->get_stats2( canonical, stats2_all, p_abort); + if ( stats.is_folder() ) { + return makeItemFolderStd(canonical, stats ); + } } throw exception_io_not_found(); #if PFC_DEBUG @@ -2057,7 +2181,7 @@ fb2k::stringRef filesystem_v3::fileNameSanity(const char* fn) { return ret; } -void filesystem_v3::readStatsMulti(fb2k::arrayRef items, uint32_t s2flags, t_filestats2* outStats, abort_callback& abort) { +static void readStatsMultiStd(fb2k::arrayRef items, uint32_t s2flags, t_filestats2* outStats, abort_callback& abort) { const size_t count = items->size(); for (size_t w = 0; w < count; ++w) { abort.check(); @@ -2073,6 +2197,23 @@ void filesystem_v3::readStatsMulti(fb2k::arrayRef items, uint32_t s2flags, t_fil } } +void filesystem_v3::readStatsMulti(fb2k::arrayRef items, uint32_t s2flags, t_filestats2* outStats, abort_callback& abort) { + readStatsMultiStd(items, s2flags, outStats, abort); +} + +pfc::string8 t_filestats::describe() const { + pfc::string8 ret; + ret << "size: "; + if (m_size != filesize_invalid) ret << m_size; + else ret << "N/A"; + ret << "\n"; + ret << "last-modified: "; + if (m_timestamp != filetimestamp_invalid) ret << m_timestamp; + else ret << "N/A"; + ret << "\n"; + return ret; +} + pfc::string8 t_filestats2::describe() const { pfc::string8 ret; ret << "size: "; @@ -2097,13 +2238,10 @@ pfc::string8 t_filestats2::describe() const { t_filestats foobar2000_io::nixMakeFileStats(const struct stat & st) { t_filestats out = filestats_invalid; out.m_size = st.st_size; -#if defined(__ANDROID__) - out.m_timestamp = pfc::fileTimeUtoW(st.st_mtime /* + st.st_mtime_nsec / 1000000000 */ ); -#elif !defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE) - out.m_timestamp = pfc::fileTimeUtoW(st.st_mtimespec ); - // out.m_timestampCreate = pfc::fileTimeUtoW( st.st_birthtimespec ); -#else - out.m_timestamp = pfc::fileTimeUtoW(st.st_mtime); +#ifdef __APPLE__ + out.m_timestamp = pfc::fileTimeUtoW(st.st_mtimespec); +#else // Linux + out.m_timestamp = pfc::fileTimeUtoW(st.st_mtim); #endif return out; } @@ -2118,10 +2256,15 @@ bool foobar2000_io::nixQueryDirectory( const struct stat & st ) { t_filestats2 foobar2000_io::nixMakeFileStats2(const struct stat &st) { t_filestats2 ret = t_filestats2::from_legacy( nixMakeFileStats( st ) ); - ret.m_timestampCreate = pfc::fileTimeUtoW( st.st_birthtimespec ); +#ifdef __APPLE__ + ret.m_timestampCreate = pfc::fileTimeUtoW(st.st_birthtimespec); +#else // Linux + ret.m_timestampCreate = pfc::fileTimeUtoW(st.st_ctim); +#endif ret.set_readonly(nixQueryReadonly(st)); if ( nixQueryDirectory( st ) ) ret.set_folder(); else ret.set_file(); + ret.set_remote(false); return ret; } @@ -2176,3 +2319,85 @@ bool filesystem::g_get_display_name_short( const char * path, pfc::string_base & out = path; return false; } + + +bool filesystem::g_compare_paths(const char* p1, const char* p2, int& result) { + if (strcmp(p1, p2) == 0) { + result = 0; return true; + } + + { + auto s1 = strstr(p1, "://"); + auto s2 = strstr(p2, "://"); + if (s1 == nullptr || s2 == nullptr) { + PFC_ASSERT(!"Invalid arguments"); + return false; + } + size_t prefix = s1 - p1; + if (prefix != s2 - p2) return false; // protocol mismatch + if (memcmp(p1, p2, prefix) != 0) return false; // protocol mismatch + } + + filesystem::ptr fs; + if (!g_get_interface(fs, p1)) { + PFC_ASSERT(!"Invalid arguments"); + return false; + } + pfc::string8 temp1(p1), temp2(p2); + auto delim = fs->pathSeparator(); + temp1.end_with(delim); temp2.end_with(delim); + if (strcmp(temp1, temp2) == 0) { result = 0; return true; } + + //result 1 if p2 is a subpath of p1, -1 if p1 is a subpath of p2 + if (pfc::string_has_prefix(temp1, temp2)) { + // temp1 starts with temp2 + // p1 a subfolder of p2 + result = -1; + return true; + } else if (pfc::string_has_prefix(temp2, temp1)) { + // temp2 starts with temp1 + // p2 a subfolder of p1 + result = 1; + return true; + } else { + return false; + } +} + +size_t file::receive(void* ptr, size_t bytes, abort_callback& a) { + stream_receive::ptr obj; + if (obj &= this) return obj->receive(ptr, bytes, a); + else return this->read(ptr, bytes, a); +} + +void filesystem::g_readStatsMulti(fb2k::arrayRef items, uint32_t s2flags, t_filestats2* outStats, abort_callback& abort) { + if (items->size() == 0) return; + fsItemPtr aFile; aFile ^= items->itemAt(0); + filesystem_v3::ptr fs; + if (fs &= aFile->getFS()) { + fs->readStatsMulti(items, s2flags, outStats, abort); + } else { + readStatsMultiStd(items, s2flags, outStats, abort); + } +} + +void file::set_stats(t_filestats2 const& stats, abort_callback& a) { + if (stats.haveTimestamp() || stats.haveTimestampCreate()) { + filetimes_t ft; + ft.creation = stats.m_timestampCreate; + ft.lastWrite = stats.m_timestamp; + this->setFileTimes(ft, a); + } +} + +fb2k::stringRef filesystem::fileNameSanity_(const char* fn) { + filesystem_v3::ptr v3; + if (v3 &= this) return v3->fileNameSanity(fn); + throw pfc::exception_not_implemented(); +} + +drivespace_t filesystem::getDriveSpace_(const char* pathAt, abort_callback& abort) { + filesystem_v3::ptr v3; + if (v3 &= this) return v3->getDriveSpace(pathAt, abort); + throw pfc::exception_not_implemented(); +} diff --git a/3rdparty/foo_SDK/foobar2000/SDK/filesystem.h b/3rdparty/foo_SDK/foobar2000/SDK/filesystem.h index d6863879..74c55086 100644 --- a/3rdparty/foo_SDK/foobar2000/SDK/filesystem.h +++ b/3rdparty/foo_SDK/foobar2000/SDK/filesystem.h @@ -169,8 +169,13 @@ namespace foobar2000_io //! Bool retval version of make_directory(). bool make_directory_check( const char * path, abort_callback & abort ); + //! Returns whether a directory exists at path, false if doesn't exist or not a directory. bool directory_exists(const char * path, abort_callback & abort); + //! Returns whether a file exists at path, false if doesn't exist or not a file. bool file_exists( const char * path, abort_callback & abort ); + //! Returns whether either a file or a directory exists at path. Effectively directory_exists() || file_exists(), but somewhat more efficient. + bool exists(const char* path, abort_callback& a); + char pathSeparator(); //! Extracts the filename.ext portion of the path. \n //! The filename is ready to be presented to the user - URL decoding and such (similar to get_display_path()) is applied. @@ -220,11 +225,28 @@ namespace foobar2000_io fsItemFolder::ptr makeItemFolderStd(const char* pathCanonical, t_filestats2 const& stats = filestats2_invalid ); fsItemFile::ptr makeItemFileStd(const char* pathCanonical, t_filestats2 const& stats = filestats2_invalid ); + fsItemBase::ptr findItem_(const char* path, abort_callback& p_abort); + fsItemFile::ptr findItemFile_(const char* path, abort_callback& p_abort); + fsItemFolder::ptr findItemFolder_(const char* path, abort_callback& p_abort); typedef std::function list_callback_t; void list_directory_(const char* path, list_callback_t cb, unsigned listMode,abort_callback& a); + //! Compares two paths determining if one is a subpath of another, + //! Returns false if the paths are unrelated. + //! Returns true if the paths are related, and then: result is set 0 if they are equal, 1 if p2 is a subpath of p1, -1 if p1 is a subpath of p2 + static bool g_compare_paths(const char* p1, const char* p2, int& result); + + //! Batch file stats read. Some filesystems provide an optimized implementation of this. + static void g_readStatsMulti(fb2k::arrayRef items, uint32_t s2flags, t_filestats2* outStats, abort_callback& abort); + + //! See filesystem_v3::fileNameSanity(). Throws pfc::exception_not_implemented() if not available. + fb2k::stringRef fileNameSanity_(const char* fn); + + //! See filesystem_v3::getDriveSpace(). Throws pfc::exception_not_implemented() if not available. + drivespace_t getDriveSpace_(const char* pathAt, abort_callback& abort); + protected: static bool get_parent_helper(const char * path, char separator, pfc::string_base & out); void read_whole_file_fallback( const char * path, mem_block_container & out, pfc::string_base & outContentType, size_t maxBytes, abort_callback & abort ); @@ -418,6 +440,7 @@ namespace foobar2000_io bool extract_native_path_ex(const char * p_fspath, pfc::string_base & p_native);//prepends \\?\ where needed bool extract_native_path_archive_aware( const char * fspatch, pfc::string_base & out ); + bool extract_native_path_archive_aware_ex( const char * fspatch, pfc::string_base & out, abort_callback & a ); template pfc::string getPathDisplay(const T& source) { diff --git a/3rdparty/foo_SDK/foobar2000/SDK/filesystem_transacted.h b/3rdparty/foo_SDK/foobar2000/SDK/filesystem_transacted.h index 9574ecca..e93eaeef 100644 --- a/3rdparty/foo_SDK/foobar2000/SDK/filesystem_transacted.h +++ b/3rdparty/foo_SDK/foobar2000/SDK/filesystem_transacted.h @@ -2,42 +2,6 @@ #include "filesystem.h" -//! Object cannot be opened in transacted mode. -PFC_DECLARE_EXCEPTION(exception_io_transactions_unsupported, exception_io, "Transactions unsupported on this volume"); -PFC_DECLARE_EXCEPTION(exception_io_transactional_conflict, exception_io, "Transactional conflict"); -PFC_DECLARE_EXCEPTION(exception_io_transaction_aborted, exception_io, "Transaction aborted"); - -//! An instance of a filesystem transaction. Inherits from filesystem API and provides all the methods. \n -//! To perform a transacted filesystem update, you must call methods on this object specifically - not static methods of filesystem class, not methods of a filesystem instance obtained from someplace else. \n -//! Call commit() when done, then release the object. If you release the object without having called commit(), the update will be rolled back. \n -//! Please keep in mind that you must not explicitly rely on this API and always provide a fallback mechanism. \n -//! A transacted operation may be impossible for the following reasons: \n -//! Too old foobar2000 version - filesystem_transacted was first published at version 1.4 beta 7 - obtaining a filesystem_transacted instance will fail. \n -//! Too old Windows OS - transacted APIs are available starting from Vista, not available on XP - obtaining a filesystem_transacted instance will fail. \n -//! Functionality disabled by user - obtaining a filesystem_transacted instance will fail. \n -//! The volume you're trying to work with does not support transacted updates - network share, non-NTFS USB stick, etc - create() will succeed but operations will fail with exception_io_transactions_unsupported. \n -class filesystem_transacted : public filesystem_v2 { - FB2K_MAKE_SERVICE_INTERFACE(filesystem_transacted, filesystem_v2); -public: - //! Commits the transaction. You should release this filesystem_transacted object when done. \n - //! If you don't call commit, all operations made with this filesystem_transacted instance will be rolled back. - virtual void commit(abort_callback & abort) = 0; - - //! Helper to obtain a new instance. Will return null if filesystem_transacted is unavailable. - static filesystem_transacted::ptr create( const char * pathFor ); -}; - -//! \since 1.4 -//! An entrypoint interface to create filesystem_transacted instances. Use filesystem_transacted::create() instead of calling this directly. -class filesystem_transacted_entry : public service_base { - FB2K_MAKE_SERVICE_INTERFACE_ENTRYPOINT(filesystem_transacted_entry); -public: - //! May return null if transacted ops are not available in this location for one reason or another. - virtual filesystem_transacted::ptr create( const char * pathFor ) = 0; - - virtual bool is_our_path( const char * path ) = 0; -}; - // Since 1.5, transacted filesystem is no longer supported // as it adds extra complexity without actually solving any problems. // Even Microsoft recommends not to use this API. diff --git a/3rdparty/foo_SDK/foobar2000/SDK/foobar2000-versions.h b/3rdparty/foo_SDK/foobar2000/SDK/foobar2000-versions.h index 2e0bca57..31879d06 100644 --- a/3rdparty/foo_SDK/foobar2000/SDK/foobar2000-versions.h +++ b/3rdparty/foo_SDK/foobar2000/SDK/foobar2000-versions.h @@ -2,21 +2,40 @@ // foobar2000-versions.h // foobar2000 SDK version and target API levels are declared in this header +#ifdef _WIN32 +// Windows + // This SDK does NOT SUPPORT targets older than API 80 / foobar2000 v1.5 #define FOOBAR2000_TARGET_VERSION 80 // 1.5, 1.6 // #define FOOBAR2000_TARGET_VERSION 81 // 2.0 + #ifdef _M_IX86 #define FOOBAR2000_TARGET_VERSION_COMPATIBLE 72 #else // x64 & ARM64 targets -// Allow components made with new foobar2000 v1.6 SDK with x64 & ARM64 targets +// Allow components made with special foobar2000 v1.6 SDK with x64 & ARM64 targets #define FOOBAR2000_TARGET_VERSION_COMPATIBLE 80 #endif + +#else // _WIN32 +// Not Windows +#define FOOBAR2000_TARGET_VERSION 81 +#define FOOBAR2000_TARGET_VERSION_COMPATIBLE 81 +#endif // _WIN32 + // Can safely use foobar2000 v2.0 features? #define FOOBAR2020 (FOOBAR2000_TARGET_VERSION>=81) // Use this to determine what foobar2000 SDK version is in use, undefined for releases older than 2018 -#define FOOBAR2000_SDK_VERSION 20221116 \ No newline at end of file +#define FOOBAR2000_SDK_VERSION 20230913 + +// cfg_var downgrade support, experimental, intended for specific components only. +// Allows new style configStore data to be imported back to old foobar2000 friendly cfg_vars. +// Intended to retain config when reverting FOOBAR2000_TARGET_VERSION value of 81 or newer to 80. +// Takes effect with FOOBAR2000_TARGET_VERSION 80 only. +// Place FOOBAR2000_IMPLEMENT_CFG_VAR_DOWNGRADE somewhere in your code to declare init calls for cfg_var downgrade. Or, if you wish to call manually, call cfg_var_reader::downgrade_main() before accessing your cfg_vars. +// Spurious calls to cfg_var_reader::downgrade_main() will be ignored, only first one will take effect. +#define FOOBAR2000_SUPPORT_CFG_VAR_DOWNGRADE 0 \ No newline at end of file diff --git a/3rdparty/foo_SDK/foobar2000/SDK/foobar2000-winver.h b/3rdparty/foo_SDK/foobar2000/SDK/foobar2000-winver.h index c0c9bd73..7aab1d84 100644 --- a/3rdparty/foo_SDK/foobar2000/SDK/foobar2000-winver.h +++ b/3rdparty/foo_SDK/foobar2000/SDK/foobar2000-winver.h @@ -21,6 +21,9 @@ #define FOOBAR2000_HAVE_KEYBOARD_SHORTCUTS #endif +#ifdef __APPLE__ +#define FOOBAR2000_SUPPORT_DLLS 1 +#endif #ifndef FOOBAR2000_SUPPORT_DLLS #define FOOBAR2000_SUPPORT_DLLS 0 diff --git a/3rdparty/foo_SDK/foobar2000/SDK/foobar2000.h b/3rdparty/foo_SDK/foobar2000/SDK/foobar2000.h index 6e5796aa..9845c1f6 100644 --- a/3rdparty/foo_SDK/foobar2000/SDK/foobar2000.h +++ b/3rdparty/foo_SDK/foobar2000/SDK/foobar2000.h @@ -116,4 +116,7 @@ #include "ui_edit_context.h" #include "toolbarDropDown.h" +#include "commonObjects-Apple.h" + #endif //_FOOBAR2000_H_ + diff --git a/3rdparty/foo_SDK/foobar2000/SDK/foobar2000_SDK.vcxproj b/3rdparty/foo_SDK/foobar2000/SDK/foobar2000_SDK.vcxproj index b877aa9b..12ba8d37 100644 --- a/3rdparty/foo_SDK/foobar2000/SDK/foobar2000_SDK.vcxproj +++ b/3rdparty/foo_SDK/foobar2000/SDK/foobar2000_SDK.vcxproj @@ -135,7 +135,7 @@ MultiThreadedDebugDLL 4715 true - ..\..;$(SolutionDir)/../3rdparty/WTL10_10320_Release/Include + ..;..\.. true stdcpp17 @@ -159,7 +159,7 @@ MultiThreadedDebugDLL 4715 true - ..\..;$(SolutionDir)/../3rdparty/WTL10_10320_Release/Include + ..;..\.. true stdcpp17 @@ -238,7 +238,7 @@ true true NDEBUG;_UNICODE;UNICODE;%(PreprocessorDefinitions) - ..\..;$(SolutionDir)/../3rdparty/WTL10_10320_Release/Include + ..;..\.. true stdcpp17 @@ -269,7 +269,7 @@ true true NDEBUG;_UNICODE;UNICODE;%(PreprocessorDefinitions) - ..\..;$(SolutionDir)/../3rdparty/WTL10_10320_Release/Include + ..;..\.. true stdcpp17 @@ -347,6 +347,7 @@ + @@ -355,6 +356,7 @@ + diff --git a/3rdparty/foo_SDK/foobar2000/SDK/foobar2000_SDK.vcxproj.filters b/3rdparty/foo_SDK/foobar2000/SDK/foobar2000_SDK.vcxproj.filters index 73c200e4..aa813f52 100644 --- a/3rdparty/foo_SDK/foobar2000/SDK/foobar2000_SDK.vcxproj.filters +++ b/3rdparty/foo_SDK/foobar2000/SDK/foobar2000_SDK.vcxproj.filters @@ -401,6 +401,12 @@ Header Files + + Header Files + + + Header Files + diff --git a/3rdparty/foo_SDK/foobar2000/SDK/foobar2000_SDK.xcodeproj/project.pbxproj b/3rdparty/foo_SDK/foobar2000/SDK/foobar2000_SDK.xcodeproj/project.pbxproj new file mode 100644 index 00000000..5745ae3c --- /dev/null +++ b/3rdparty/foo_SDK/foobar2000/SDK/foobar2000_SDK.xcodeproj/project.pbxproj @@ -0,0 +1,1115 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 0F75F4942A6B1CA800A45078 /* foosort.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F75F3C82A6B1CA000A45078 /* foosort.cpp */; }; + 0F75F4952A6B1CA800A45078 /* genrand.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F3C92A6B1CA000A45078 /* genrand.h */; }; + 0F75F4962A6B1CA800A45078 /* ui_element_typable_window_manager.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F3CA2A6B1CA000A45078 /* ui_element_typable_window_manager.h */; }; + 0F75F4972A6B1CA800A45078 /* titleformat.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F75F3CB2A6B1CA000A45078 /* titleformat.cpp */; }; + 0F75F4982A6B1CA800A45078 /* file_info_merge.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F75F3CC2A6B1CA000A45078 /* file_info_merge.cpp */; }; + 0F75F4992A6B1CA800A45078 /* audio_chunk.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F3CD2A6B1CA000A45078 /* audio_chunk.h */; }; + 0F75F49A2A6B1CA800A45078 /* output.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F3CE2A6B1CA000A45078 /* output.h */; }; + 0F75F49B2A6B1CA800A45078 /* file_operation_callback.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F75F3CF2A6B1CA000A45078 /* file_operation_callback.cpp */; }; + 0F75F49C2A6B1CA800A45078 /* abort_callback.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F75F3D02A6B1CA000A45078 /* abort_callback.cpp */; }; + 0F75F49D2A6B1CA800A45078 /* playlist_loader.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F3D12A6B1CA000A45078 /* playlist_loader.h */; }; + 0F75F49E2A6B1CA800A45078 /* threaded_process.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F3D22A6B1CA000A45078 /* threaded_process.h */; }; + 0F75F49F2A6B1CA800A45078 /* service_impl.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F3D32A6B1CA000A45078 /* service_impl.h */; }; + 0F75F4A02A6B1CA800A45078 /* main_thread_callback.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F3D42A6B1CA000A45078 /* main_thread_callback.h */; }; + 0F75F4A12A6B1CA800A45078 /* filesystem.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F75F3D52A6B1CA000A45078 /* filesystem.cpp */; }; + 0F75F4A22A6B1CA800A45078 /* stdafx.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F75F3D62A6B1CA000A45078 /* stdafx.cpp */; }; + 0F75F4A32A6B1CA800A45078 /* progress_meter.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F3D72A6B1CA000A45078 /* progress_meter.h */; }; + 0F75F4A42A6B1CA800A45078 /* app_close_blocker.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F3D82A6B1CA000A45078 /* app_close_blocker.h */; }; + 0F75F4A52A6B1CA800A45078 /* mem_block_container.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F75F3D92A6B1CA000A45078 /* mem_block_container.cpp */; }; + 0F75F4A62A6B1CA800A45078 /* filesystem.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F3DA2A6B1CA000A45078 /* filesystem.h */; }; + 0F75F4A72A6B1CA800A45078 /* commonObjects.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F75F3DB2A6B1CA000A45078 /* commonObjects.cpp */; }; + 0F75F4A82A6B1CA800A45078 /* threadPool.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F3DC2A6B1CA000A45078 /* threadPool.h */; }; + 0F75F4A92A6B1CA800A45078 /* noInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F3DD2A6B1CA000A45078 /* noInfo.h */; }; + 0F75F4AA2A6B1CA800A45078 /* unpack.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F3DE2A6B1CA000A45078 /* unpack.h */; }; + 0F75F4AB2A6B1CA800A45078 /* output.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F75F3DF2A6B1CA000A45078 /* output.cpp */; }; + 0F75F4AC2A6B1CA800A45078 /* menu_helpers.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F75F3E02A6B1CA000A45078 /* menu_helpers.cpp */; }; + 0F75F4AD2A6B1CA800A45078 /* service.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F3E12A6B1CA000A45078 /* service.h */; }; + 0F75F4AE2A6B1CA800A45078 /* file_info_const_impl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F75F3E22A6B1CA100A45078 /* file_info_const_impl.cpp */; }; + 0F75F4AF2A6B1CA800A45078 /* chapterizer.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F3E32A6B1CA100A45078 /* chapterizer.h */; }; + 0F75F4B02A6B1CA800A45078 /* audio_chunk_impl.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F3E42A6B1CA100A45078 /* audio_chunk_impl.h */; }; + 0F75F4B12A6B1CA800A45078 /* audio_chunk_channel_config.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F75F3E52A6B1CA100A45078 /* audio_chunk_channel_config.cpp */; }; + 0F75F4B22A6B1CA800A45078 /* event_logger.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F3E62A6B1CA100A45078 /* event_logger.h */; }; + 0F75F4B32A6B1CA800A45078 /* foobar2000-pfc.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F3E72A6B1CA100A45078 /* foobar2000-pfc.h */; }; + 0F75F4B42A6B1CA800A45078 /* http_client.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F3E82A6B1CA100A45078 /* http_client.h */; }; + 0F75F4B52A6B1CA800A45078 /* hasher_md5.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F3E92A6B1CA100A45078 /* hasher_md5.h */; }; + 0F75F4B62A6B1CA800A45078 /* component.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F3EA2A6B1CA100A45078 /* component.h */; }; + 0F75F4B72A6B1CA800A45078 /* forward_types.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F3EB2A6B1CA100A45078 /* forward_types.h */; }; + 0F75F4B82A6B1CA800A45078 /* replaygain.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F3EC2A6B1CA100A45078 /* replaygain.h */; }; + 0F75F4B92A6B1CA800A45078 /* metadb.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F3ED2A6B1CA100A45078 /* metadb.h */; }; + 0F75F4BA2A6B1CA800A45078 /* menu_manager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F75F3EE2A6B1CA100A45078 /* menu_manager.cpp */; }; + 0F75F4BB2A6B1CA800A45078 /* resampler.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F3EF2A6B1CA100A45078 /* resampler.h */; }; + 0F75F4BC2A6B1CA800A45078 /* initquit.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F3F02A6B1CA100A45078 /* initquit.h */; }; + 0F75F4BD2A6B1CA800A45078 /* foobar2000-winver.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F3F12A6B1CA100A45078 /* foobar2000-winver.h */; }; + 0F75F4BE2A6B1CA800A45078 /* timer.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F3F22A6B1CA100A45078 /* timer.h */; }; + 0F75F4BF2A6B1CA800A45078 /* playlist.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F3F32A6B1CA100A45078 /* playlist.h */; }; + 0F75F4C02A6B1CA800A45078 /* track_property.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F75F3F42A6B1CA100A45078 /* track_property.cpp */; }; + 0F75F4C12A6B1CA800A45078 /* ui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F75F3F52A6B1CA100A45078 /* ui.cpp */; }; + 0F75F4C22A6B1CA800A45078 /* titleformat.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F3F62A6B1CA100A45078 /* titleformat.h */; }; + 0F75F4C32A6B1CA800A45078 /* file_info_impl.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F3F72A6B1CA100A45078 /* file_info_impl.h */; }; + 0F75F4C42A6B1CA800A45078 /* filesystem_helper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F75F3F82A6B1CA100A45078 /* filesystem_helper.cpp */; }; + 0F75F4C52A6B1CA800A45078 /* filesystem_helper.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F3F92A6B1CA100A45078 /* filesystem_helper.h */; }; + 0F75F4C62A6B1CA800A45078 /* audio_chunk.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F75F3FA2A6B1CA100A45078 /* audio_chunk.cpp */; }; + 0F75F4C72A6B1CA800A45078 /* console_manager.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F3FB2A6B1CA100A45078 /* console_manager.h */; }; + 0F75F4C82A6B1CA800A45078 /* filesystem_transacted.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F3FC2A6B1CA100A45078 /* filesystem_transacted.h */; }; + 0F75F4C92A6B1CA800A45078 /* service.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F75F3FD2A6B1CA100A45078 /* service.cpp */; }; + 0F75F4CA2A6B1CA800A45078 /* threaded_process.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F75F3FE2A6B1CA200A45078 /* threaded_process.cpp */; }; + 0F75F4CB2A6B1CA800A45078 /* coreDarkMode.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F3FF2A6B1CA200A45078 /* coreDarkMode.h */; }; + 0F75F4CC2A6B1CA800A45078 /* cfg_var_legacy.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F4002A6B1CA200A45078 /* cfg_var_legacy.h */; }; + 0F75F4CD2A6B1CA800A45078 /* menu.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F4012A6B1CA200A45078 /* menu.h */; }; + 0F75F4CE2A6B1CA800A45078 /* file_info_filter_impl.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F4022A6B1CA200A45078 /* file_info_filter_impl.h */; }; + 0F75F4CF2A6B1CA800A45078 /* advconfig.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F75F4032A6B1CA200A45078 /* advconfig.cpp */; }; + 0F75F4D02A6B1CA800A45078 /* packet_decoder.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F4042A6B1CA200A45078 /* packet_decoder.h */; }; + 0F75F4D12A6B1CA800A45078 /* decode_postprocessor.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F4052A6B1CA200A45078 /* decode_postprocessor.h */; }; + 0F75F4D22A6B1CA800A45078 /* exception_io.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F4062A6B1CA200A45078 /* exception_io.h */; }; + 0F75F4D32A6B1CA800A45078 /* search_tools.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F4072A6B1CA200A45078 /* search_tools.h */; }; + 0F75F4D42A6B1CA800A45078 /* metadb_callbacks.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F4082A6B1CA200A45078 /* metadb_callbacks.h */; }; + 0F75F4D52A6B1CA800A45078 /* configStore.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F75F4092A6B1CA200A45078 /* configStore.cpp */; }; + 0F75F4D62A6B1CA800A45078 /* modeless_dialog.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F40A2A6B1CA200A45078 /* modeless_dialog.h */; }; + 0F75F4D72A6B1CA800A45078 /* foosort.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F40B2A6B1CA200A45078 /* foosort.h */; }; + 0F75F4D82A6B1CA800A45078 /* console.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F75F40C2A6B1CA200A45078 /* console.cpp */; }; + 0F75F4D92A6B1CA800A45078 /* playback_control.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F40D2A6B1CA200A45078 /* playback_control.h */; }; + 0F75F4DA2A6B1CA800A45078 /* playback_stream_capture.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F40E2A6B1CA200A45078 /* playback_stream_capture.h */; }; + 0F75F4DB2A6B1CA800A45078 /* file_info.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F75F40F2A6B1CA200A45078 /* file_info.cpp */; }; + 0F75F4DC2A6B1CA800A45078 /* dsp.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F4102A6B1CA200A45078 /* dsp.h */; }; + 0F75F4DD2A6B1CA800A45078 /* library_callbacks.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F4112A6B1CA200A45078 /* library_callbacks.h */; }; + 0F75F4DE2A6B1CA800A45078 /* threadsLite.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F4122A6B1CA200A45078 /* threadsLite.h */; }; + 0F75F4DF2A6B1CA800A45078 /* mem_block_container.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F4132A6B1CA200A45078 /* mem_block_container.h */; }; + 0F75F4E02A6B1CA800A45078 /* foobar2000-all.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F4142A6B1CA200A45078 /* foobar2000-all.h */; }; + 0F75F4E12A6B1CA800A45078 /* image.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F75F4152A6B1CA200A45078 /* image.cpp */; }; + 0F75F4E22A6B1CA800A45078 /* utility.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F75F4162A6B1CA200A45078 /* utility.cpp */; }; + 0F75F4E32A6B1CA800A45078 /* track_property.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F4172A6B1CA200A45078 /* track_property.h */; }; + 0F75F4E42A6B1CA800A45078 /* cfg_var.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F75F4182A6B1CA200A45078 /* cfg_var.cpp */; }; + 0F75F4E52A6B1CA800A45078 /* shortcut_actions.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F4192A6B1CA200A45078 /* shortcut_actions.h */; }; + 0F75F4E62A6B1CA800A45078 /* foosortstring.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F75F41A2A6B1CA200A45078 /* foosortstring.cpp */; }; + 0F75F4E72A6B1CA800A45078 /* exceptions.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F41B2A6B1CA200A45078 /* exceptions.h */; }; + 0F75F4E82A6B1CA800A45078 /* component_client.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F41C2A6B1CA200A45078 /* component_client.h */; }; + 0F75F4E92A6B1CA800A45078 /* playable_location.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F75F41D2A6B1CA200A45078 /* playable_location.cpp */; }; + 0F75F4EA2A6B1CA800A45078 /* metadb.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F75F41E2A6B1CA200A45078 /* metadb.cpp */; }; + 0F75F4EB2A6B1CA800A45078 /* input_impl.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F41F2A6B1CA200A45078 /* input_impl.h */; }; + 0F75F4EC2A6B1CA800A45078 /* service_compat.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F4202A6B1CA200A45078 /* service_compat.h */; }; + 0F75F4ED2A6B1CA800A45078 /* keyValueIO.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F4212A6B1CA300A45078 /* keyValueIO.h */; }; + 0F75F4EE2A6B1CA800A45078 /* tracks.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F4222A6B1CA300A45078 /* tracks.h */; }; + 0F75F4EF2A6B1CA800A45078 /* playlistColumnProvider.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F4232A6B1CA300A45078 /* playlistColumnProvider.h */; }; + 0F75F4F02A6B1CA800A45078 /* imageLoaderLite.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F4242A6B1CA300A45078 /* imageLoaderLite.h */; }; + 0F75F4F12A6B1CA800A45078 /* playlist.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F75F4252A6B1CA300A45078 /* playlist.cpp */; }; + 0F75F4F22A6B1CA800A45078 /* preferences_page.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F75F4262A6B1CA300A45078 /* preferences_page.cpp */; }; + 0F75F4F32A6B1CA800A45078 /* config_io_callback.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F75F4272A6B1CA300A45078 /* config_io_callback.cpp */; }; + 0F75F4F42A6B1CA800A45078 /* packet_decoder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F75F4282A6B1CA300A45078 /* packet_decoder.cpp */; }; + 0F75F4F52A6B1CA800A45078 /* ole_interaction.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F4292A6B1CA300A45078 /* ole_interaction.h */; }; + 0F75F4F62A6B1CA800A45078 /* info_lookup_handler.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F42A2A6B1CA300A45078 /* info_lookup_handler.h */; }; + 0F75F4F72A6B1CA800A45078 /* library_index.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F42B2A6B1CA300A45078 /* library_index.h */; }; + 0F75F4F82A6B1CA800A45078 /* audioEncoder.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F42C2A6B1CA300A45078 /* audioEncoder.h */; }; + 0F75F4F92A6B1CA800A45078 /* commandline.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F75F42D2A6B1CA300A45078 /* commandline.cpp */; }; + 0F75F4FA2A6B1CA800A45078 /* image.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F42E2A6B1CA300A45078 /* image.h */; }; + 0F75F4FB2A6B1CA800A45078 /* link_resolver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F75F42F2A6B1CA300A45078 /* link_resolver.cpp */; }; + 0F75F4FC2A6B1CA800A45078 /* metadb_handle.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F4302A6B1CA300A45078 /* metadb_handle.h */; }; + 0F75F4FD2A6B1CA800A45078 /* advconfig_impl.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F4312A6B1CA300A45078 /* advconfig_impl.h */; }; + 0F75F4FE2A6B1CA800A45078 /* foobar2000-versions.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F4322A6B1CA300A45078 /* foobar2000-versions.h */; }; + 0F75F4FF2A6B1CA800A45078 /* componentversion.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F4332A6B1CA300A45078 /* componentversion.h */; }; + 0F75F5002A6B1CA800A45078 /* contextmenu.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F4342A6B1CA300A45078 /* contextmenu.h */; }; + 0F75F5012A6B1CA800A45078 /* advconfig_impl_legacy.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F4352A6B1CA300A45078 /* advconfig_impl_legacy.h */; }; + 0F75F5022A6B1CA800A45078 /* file.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F4362A6B1CA300A45078 /* file.h */; }; + 0F75F5032A6B1CA800A45078 /* ui_element.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F75F4372A6B1CA300A45078 /* ui_element.cpp */; }; + 0F75F5042A6B1CA800A45078 /* guids.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F75F4382A6B1CA300A45078 /* guids.cpp */; }; + 0F75F5052A6B1CA800A45078 /* tag_processor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F75F4392A6B1CA300A45078 /* tag_processor.cpp */; }; + 0F75F5062A6B1CA800A45078 /* config_object.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F43A2A6B1CA300A45078 /* config_object.h */; }; + 0F75F5072A6B1CA800A45078 /* config_object.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F75F43B2A6B1CA300A45078 /* config_object.cpp */; }; + 0F75F5082A6B1CA800A45078 /* ui.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F43C2A6B1CA300A45078 /* ui.h */; }; + 0F75F5092A6B1CA800A45078 /* link_resolver.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F43D2A6B1CA300A45078 /* link_resolver.h */; }; + 0F75F50A2A6B1CA800A45078 /* playable_location.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F43E2A6B1CA300A45078 /* playable_location.h */; }; + 0F75F50B2A6B1CA800A45078 /* file_lock_manager.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F43F2A6B1CA300A45078 /* file_lock_manager.h */; }; + 0F75F50C2A6B1CA800A45078 /* configStore.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F4402A6B1CA300A45078 /* configStore.h */; }; + 0F75F50D2A6B1CA800A45078 /* input.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F75F4412A6B1CA300A45078 /* input.cpp */; }; + 0F75F50E2A6B1CA800A45078 /* contextmenu_manager.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F4422A6B1CA300A45078 /* contextmenu_manager.h */; }; + 0F75F50F2A6B1CA800A45078 /* config_io_callback.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F4432A6B1CA400A45078 /* config_io_callback.h */; }; + 0F75F5102A6B1CA800A45078 /* menu_common.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F4442A6B1CA400A45078 /* menu_common.h */; }; + 0F75F5112A6B1CA800A45078 /* completion_notify.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F75F4452A6B1CA400A45078 /* completion_notify.cpp */; }; + 0F75F5122A6B1CA800A45078 /* metadb_info_container_impl.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F4462A6B1CA400A45078 /* metadb_info_container_impl.h */; }; + 0F75F5132A6B1CA800A45078 /* abort_callback.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F4472A6B1CA400A45078 /* abort_callback.h */; }; + 0F75F5142A6B1CA800A45078 /* completion_notify.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F4482A6B1CA400A45078 /* completion_notify.h */; }; + 0F75F5152A6B1CA800A45078 /* toolbarDropDown.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F4492A6B1CA400A45078 /* toolbarDropDown.h */; }; + 0F75F5162A6B1CA800A45078 /* dsp_manager.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F44A2A6B1CA400A45078 /* dsp_manager.h */; }; + 0F75F5172A6B1CA800A45078 /* messageBox.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F44B2A6B1CA400A45078 /* messageBox.h */; }; + 0F75F5182A6B1CA800A45078 /* ui_edit_context.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F44C2A6B1CA400A45078 /* ui_edit_context.h */; }; + 0F75F5192A6B1CA800A45078 /* ui_element.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F44D2A6B1CA400A45078 /* ui_element.h */; }; + 0F75F51A2A6B1CA800A45078 /* menu_item.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F75F44E2A6B1CA400A45078 /* menu_item.cpp */; }; + 0F75F51B2A6B1CA800A45078 /* callback_merit.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F44F2A6B1CA400A45078 /* callback_merit.h */; }; + 0F75F51C2A6B1CA800A45078 /* foosortstring.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F4502A6B1CA400A45078 /* foosortstring.h */; }; + 0F75F51D2A6B1CA800A45078 /* imageViewer.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F4512A6B1CA400A45078 /* imageViewer.h */; }; + 0F75F51E2A6B1CA800A45078 /* popup_message.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F75F4522A6B1CA400A45078 /* popup_message.cpp */; }; + 0F75F51F2A6B1CA800A45078 /* fsItem.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F75F4532A6B1CA400A45078 /* fsItem.cpp */; }; + 0F75F5202A6B1CA800A45078 /* cfg_var_legacy.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F75F4542A6B1CA400A45078 /* cfg_var_legacy.cpp */; }; + 0F75F5212A6B1CA800A45078 /* vis.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F4552A6B1CA500A45078 /* vis.h */; }; + 0F75F5222A6B1CA800A45078 /* console.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F4562A6B1CA500A45078 /* console.h */; }; + 0F75F5232A6B1CA800A45078 /* componentversion.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F75F4572A6B1CA500A45078 /* componentversion.cpp */; }; + 0F75F5242A6B1CA800A45078 /* chapterizer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F75F4582A6B1CA500A45078 /* chapterizer.cpp */; }; + 0F75F5252A6B1CA800A45078 /* components_menu.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F4592A6B1CA500A45078 /* components_menu.h */; }; + 0F75F5262A6B1CA800A45078 /* metadb_handle_list.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F75F45A2A6B1CA500A45078 /* metadb_handle_list.cpp */; }; + 0F75F5272A6B1CA800A45078 /* preferences_page.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F45B2A6B1CA500A45078 /* preferences_page.h */; }; + 0F75F5282A6B1CA800A45078 /* core_api.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F45C2A6B1CA500A45078 /* core_api.h */; }; + 0F75F5292A6B1CA800A45078 /* config_object_impl.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F45D2A6B1CA500A45078 /* config_object_impl.h */; }; + 0F75F52A2A6B1CA800A45078 /* configCache.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F45E2A6B1CA500A45078 /* configCache.h */; }; + 0F75F52B2A6B1CA800A45078 /* metadb_display_field_provider.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F45F2A6B1CA500A45078 /* metadb_display_field_provider.h */; }; + 0F75F52C2A6B1CA800A45078 /* dsp-frontend.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F4602A6B1CA500A45078 /* dsp-frontend.h */; }; + 0F75F52D2A6B1CA800A45078 /* foobar2000-sdk-pch.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F4612A6B1CA500A45078 /* foobar2000-sdk-pch.h */; }; + 0F75F52E2A6B1CA800A45078 /* file_cached_impl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F75F4622A6B1CA500A45078 /* file_cached_impl.cpp */; }; + 0F75F52F2A6B1CA800A45078 /* replaygain_info.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F75F4632A6B1CA500A45078 /* replaygain_info.cpp */; }; + 0F75F5302A6B1CA800A45078 /* metadb_index.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F4642A6B1CA500A45078 /* metadb_index.h */; }; + 0F75F5312A6B1CA800A45078 /* mainmenu.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F75F4652A6B1CA500A45078 /* mainmenu.cpp */; }; + 0F75F5322A6B1CA800A45078 /* app_close_blocker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F75F4662A6B1CA500A45078 /* app_close_blocker.cpp */; }; + 0F75F5332A6B1CA800A45078 /* file_info_impl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F75F4672A6B1CA500A45078 /* file_info_impl.cpp */; }; + 0F75F5342A6B1CA800A45078 /* tag_processor_id3v2.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F75F4682A6B1CA500A45078 /* tag_processor_id3v2.cpp */; }; + 0F75F5352A6B1CA800A45078 /* audio_postprocessor.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F4692A6B1CA500A45078 /* audio_postprocessor.h */; }; + 0F75F5362A6B1CA800A45078 /* file_info.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F46A2A6B1CA500A45078 /* file_info.h */; }; + 0F75F5372A6B1CA800A45078 /* replaygain.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F75F46B2A6B1CA500A45078 /* replaygain.cpp */; }; + 0F75F5382A6B1CA800A45078 /* input.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F46C2A6B1CA500A45078 /* input.h */; }; + 0F75F5392A6B1CA800A45078 /* file_format_sanitizer.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F46D2A6B1CA600A45078 /* file_format_sanitizer.h */; }; + 0F75F53A2A6B1CA800A45078 /* commonObjects.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F46E2A6B1CA600A45078 /* commonObjects.h */; }; + 0F75F53B2A6B1CA800A45078 /* powerManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F46F2A6B1CA600A45078 /* powerManager.h */; }; + 0F75F53C2A6B1CA800A45078 /* popup_message.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F4702A6B1CA600A45078 /* popup_message.h */; }; + 0F75F53D2A6B1CA800A45078 /* archive.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F4712A6B1CA600A45078 /* archive.h */; }; + 0F75F53E2A6B1CA800A45078 /* system_time_keeper.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F4722A6B1CA600A45078 /* system_time_keeper.h */; }; + 0F75F53F2A6B1CA800A45078 /* play_callback.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F4732A6B1CA600A45078 /* play_callback.h */; }; + 0F75F5402A6B1CA800A45078 /* file_info_const_impl.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F4742A6B1CA600A45078 /* file_info_const_impl.h */; }; + 0F75F5412A6B1CA800A45078 /* file_operation_callback.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F4752A6B1CA600A45078 /* file_operation_callback.h */; }; + 0F75F5422A6B1CA800A45078 /* album_art.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F75F4762A6B1CA600A45078 /* album_art.cpp */; }; + 0F75F5432A6B1CA800A45078 /* main_thread_callback.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F75F4772A6B1CA600A45078 /* main_thread_callback.cpp */; }; + 0F75F5442A6B1CA800A45078 /* replaygain_scanner.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F4782A6B1CA600A45078 /* replaygain_scanner.h */; }; + 0F75F5452A6B1CA800A45078 /* tag_processor.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F4792A6B1CA600A45078 /* tag_processor.h */; }; + 0F75F5462A6B1CA800A45078 /* input_file_type.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F75F47A2A6B1CA700A45078 /* input_file_type.cpp */; }; + 0F75F5472A6B1CA800A45078 /* album_art.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F47B2A6B1CA700A45078 /* album_art.h */; }; + 0F75F5482A6B1CA800A45078 /* advconfig.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F47C2A6B1CA700A45078 /* advconfig.h */; }; + 0F75F5492A6B1CA800A45078 /* fsitem.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F47D2A6B1CA700A45078 /* fsitem.h */; }; + 0F75F54A2A6B1CA800A45078 /* icon_remap.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F47E2A6B1CA700A45078 /* icon_remap.h */; }; + 0F75F54B2A6B1CA800A45078 /* keyValueIOimpl.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F47F2A6B1CA700A45078 /* keyValueIOimpl.h */; }; + 0F75F54C2A6B1CA800A45078 /* fileDialog.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F4802A6B1CA700A45078 /* fileDialog.h */; }; + 0F75F54D2A6B1CA800A45078 /* autoplaylist.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F4812A6B1CA700A45078 /* autoplaylist.h */; }; + 0F75F54E2A6B1CA800A45078 /* input_file_type.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F4822A6B1CA700A45078 /* input_file_type.h */; }; + 0F75F54F2A6B1CA800A45078 /* album_art_helpers.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F4832A6B1CA700A45078 /* album_art_helpers.h */; }; + 0F75F5502A6B1CA800A45078 /* hasher_md5.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F75F4842A6B1CA700A45078 /* hasher_md5.cpp */; }; + 0F75F5512A6B1CA800A45078 /* message_loop.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F4852A6B1CA700A45078 /* message_loop.h */; }; + 0F75F5522A6B1CA800A45078 /* playlist_loader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F75F4862A6B1CA700A45078 /* playlist_loader.cpp */; }; + 0F75F5532A6B1CA800A45078 /* service_by_guid.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F4872A6B1CA700A45078 /* service_by_guid.h */; }; + 0F75F5542A6B1CA800A45078 /* library_manager.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F4882A6B1CA700A45078 /* library_manager.h */; }; + 0F75F5552A6B1CA800A45078 /* foobar2000-lite.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F4892A6B1CA700A45078 /* foobar2000-lite.h */; }; + 0F75F5562A6B1CA800A45078 /* commandline.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F48A2A6B1CA700A45078 /* commandline.h */; }; + 0F75F5572A6B1CA800A45078 /* coreversion.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F48B2A6B1CA700A45078 /* coreversion.h */; }; + 0F75F5582A6B1CA800A45078 /* dsp_manager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F75F48C2A6B1CA700A45078 /* dsp_manager.cpp */; }; + 0F75F5592A6B1CA800A45078 /* playback_control.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F75F48D2A6B1CA700A45078 /* playback_control.cpp */; }; + 0F75F55A2A6B1CA800A45078 /* foobar2000.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F48E2A6B1CA700A45078 /* foobar2000.h */; }; + 0F75F55B2A6B1CA800A45078 /* file_info_filter.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F48F2A6B1CA700A45078 /* file_info_filter.h */; }; + 0F75F55C2A6B1CA800A45078 /* metadb_handle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F75F4902A6B1CA800A45078 /* metadb_handle.cpp */; }; + 0F75F55D2A6B1CA800A45078 /* dsp.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F75F4912A6B1CA800A45078 /* dsp.cpp */; }; + 0F75F55E2A6B1CA800A45078 /* cfg_var.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F4922A6B1CA800A45078 /* cfg_var.h */; }; + 0F75F55F2A6B1CA800A45078 /* menu_helpers.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F4932A6B1CA800A45078 /* menu_helpers.h */; }; + 0FCA711C2AA2210C001CB0F2 /* commonObjects-Apple.mm in Sources */ = {isa = PBXBuildFile; fileRef = 0FCA711A2AA2210C001CB0F2 /* commonObjects-Apple.mm */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 0F75F3C82A6B1CA000A45078 /* foosort.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = foosort.cpp; sourceTree = ""; }; + 0F75F3C92A6B1CA000A45078 /* genrand.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = genrand.h; sourceTree = ""; }; + 0F75F3CA2A6B1CA000A45078 /* ui_element_typable_window_manager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ui_element_typable_window_manager.h; sourceTree = ""; }; + 0F75F3CB2A6B1CA000A45078 /* titleformat.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = titleformat.cpp; sourceTree = ""; }; + 0F75F3CC2A6B1CA000A45078 /* file_info_merge.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = file_info_merge.cpp; sourceTree = ""; }; + 0F75F3CD2A6B1CA000A45078 /* audio_chunk.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = audio_chunk.h; sourceTree = ""; }; + 0F75F3CE2A6B1CA000A45078 /* output.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = output.h; sourceTree = ""; }; + 0F75F3CF2A6B1CA000A45078 /* file_operation_callback.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = file_operation_callback.cpp; sourceTree = ""; }; + 0F75F3D02A6B1CA000A45078 /* abort_callback.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = abort_callback.cpp; sourceTree = ""; }; + 0F75F3D12A6B1CA000A45078 /* playlist_loader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = playlist_loader.h; sourceTree = ""; }; + 0F75F3D22A6B1CA000A45078 /* threaded_process.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = threaded_process.h; sourceTree = ""; }; + 0F75F3D32A6B1CA000A45078 /* service_impl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = service_impl.h; sourceTree = ""; }; + 0F75F3D42A6B1CA000A45078 /* main_thread_callback.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = main_thread_callback.h; sourceTree = ""; }; + 0F75F3D52A6B1CA000A45078 /* filesystem.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = filesystem.cpp; sourceTree = ""; }; + 0F75F3D62A6B1CA000A45078 /* stdafx.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = stdafx.cpp; sourceTree = ""; }; + 0F75F3D72A6B1CA000A45078 /* progress_meter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = progress_meter.h; sourceTree = ""; }; + 0F75F3D82A6B1CA000A45078 /* app_close_blocker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = app_close_blocker.h; sourceTree = ""; }; + 0F75F3D92A6B1CA000A45078 /* mem_block_container.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = mem_block_container.cpp; sourceTree = ""; }; + 0F75F3DA2A6B1CA000A45078 /* filesystem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = filesystem.h; sourceTree = ""; }; + 0F75F3DB2A6B1CA000A45078 /* commonObjects.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = commonObjects.cpp; sourceTree = ""; }; + 0F75F3DC2A6B1CA000A45078 /* threadPool.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = threadPool.h; sourceTree = ""; }; + 0F75F3DD2A6B1CA000A45078 /* noInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = noInfo.h; sourceTree = ""; }; + 0F75F3DE2A6B1CA000A45078 /* unpack.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = unpack.h; sourceTree = ""; }; + 0F75F3DF2A6B1CA000A45078 /* output.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = output.cpp; sourceTree = ""; }; + 0F75F3E02A6B1CA000A45078 /* menu_helpers.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = menu_helpers.cpp; sourceTree = ""; }; + 0F75F3E12A6B1CA000A45078 /* service.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = service.h; sourceTree = ""; }; + 0F75F3E22A6B1CA100A45078 /* file_info_const_impl.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = file_info_const_impl.cpp; sourceTree = ""; }; + 0F75F3E32A6B1CA100A45078 /* chapterizer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = chapterizer.h; sourceTree = ""; }; + 0F75F3E42A6B1CA100A45078 /* audio_chunk_impl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = audio_chunk_impl.h; sourceTree = ""; }; + 0F75F3E52A6B1CA100A45078 /* audio_chunk_channel_config.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = audio_chunk_channel_config.cpp; sourceTree = ""; }; + 0F75F3E62A6B1CA100A45078 /* event_logger.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = event_logger.h; sourceTree = ""; }; + 0F75F3E72A6B1CA100A45078 /* foobar2000-pfc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "foobar2000-pfc.h"; sourceTree = ""; }; + 0F75F3E82A6B1CA100A45078 /* http_client.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = http_client.h; sourceTree = ""; }; + 0F75F3E92A6B1CA100A45078 /* hasher_md5.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = hasher_md5.h; sourceTree = ""; }; + 0F75F3EA2A6B1CA100A45078 /* component.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = component.h; sourceTree = ""; }; + 0F75F3EB2A6B1CA100A45078 /* forward_types.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = forward_types.h; sourceTree = ""; }; + 0F75F3EC2A6B1CA100A45078 /* replaygain.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = replaygain.h; sourceTree = ""; }; + 0F75F3ED2A6B1CA100A45078 /* metadb.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = metadb.h; sourceTree = ""; }; + 0F75F3EE2A6B1CA100A45078 /* menu_manager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = menu_manager.cpp; sourceTree = ""; }; + 0F75F3EF2A6B1CA100A45078 /* resampler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = resampler.h; sourceTree = ""; }; + 0F75F3F02A6B1CA100A45078 /* initquit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = initquit.h; sourceTree = ""; }; + 0F75F3F12A6B1CA100A45078 /* foobar2000-winver.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "foobar2000-winver.h"; sourceTree = ""; }; + 0F75F3F22A6B1CA100A45078 /* timer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = timer.h; sourceTree = ""; }; + 0F75F3F32A6B1CA100A45078 /* playlist.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = playlist.h; sourceTree = ""; }; + 0F75F3F42A6B1CA100A45078 /* track_property.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = track_property.cpp; sourceTree = ""; }; + 0F75F3F52A6B1CA100A45078 /* ui.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ui.cpp; sourceTree = ""; }; + 0F75F3F62A6B1CA100A45078 /* titleformat.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = titleformat.h; sourceTree = ""; }; + 0F75F3F72A6B1CA100A45078 /* file_info_impl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = file_info_impl.h; sourceTree = ""; }; + 0F75F3F82A6B1CA100A45078 /* filesystem_helper.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = filesystem_helper.cpp; sourceTree = ""; }; + 0F75F3F92A6B1CA100A45078 /* filesystem_helper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = filesystem_helper.h; sourceTree = ""; }; + 0F75F3FA2A6B1CA100A45078 /* audio_chunk.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = audio_chunk.cpp; sourceTree = ""; }; + 0F75F3FB2A6B1CA100A45078 /* console_manager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = console_manager.h; sourceTree = ""; }; + 0F75F3FC2A6B1CA100A45078 /* filesystem_transacted.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = filesystem_transacted.h; sourceTree = ""; }; + 0F75F3FD2A6B1CA100A45078 /* service.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = service.cpp; sourceTree = ""; }; + 0F75F3FE2A6B1CA200A45078 /* threaded_process.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = threaded_process.cpp; sourceTree = ""; }; + 0F75F3FF2A6B1CA200A45078 /* coreDarkMode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = coreDarkMode.h; sourceTree = ""; }; + 0F75F4002A6B1CA200A45078 /* cfg_var_legacy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cfg_var_legacy.h; sourceTree = ""; }; + 0F75F4012A6B1CA200A45078 /* menu.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = menu.h; sourceTree = ""; }; + 0F75F4022A6B1CA200A45078 /* file_info_filter_impl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = file_info_filter_impl.h; sourceTree = ""; }; + 0F75F4032A6B1CA200A45078 /* advconfig.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = advconfig.cpp; sourceTree = ""; }; + 0F75F4042A6B1CA200A45078 /* packet_decoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = packet_decoder.h; sourceTree = ""; }; + 0F75F4052A6B1CA200A45078 /* decode_postprocessor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = decode_postprocessor.h; sourceTree = ""; }; + 0F75F4062A6B1CA200A45078 /* exception_io.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = exception_io.h; sourceTree = ""; }; + 0F75F4072A6B1CA200A45078 /* search_tools.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = search_tools.h; sourceTree = ""; }; + 0F75F4082A6B1CA200A45078 /* metadb_callbacks.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = metadb_callbacks.h; sourceTree = ""; }; + 0F75F4092A6B1CA200A45078 /* configStore.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = configStore.cpp; sourceTree = ""; }; + 0F75F40A2A6B1CA200A45078 /* modeless_dialog.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = modeless_dialog.h; sourceTree = ""; }; + 0F75F40B2A6B1CA200A45078 /* foosort.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = foosort.h; sourceTree = ""; }; + 0F75F40C2A6B1CA200A45078 /* console.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = console.cpp; sourceTree = ""; }; + 0F75F40D2A6B1CA200A45078 /* playback_control.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = playback_control.h; sourceTree = ""; }; + 0F75F40E2A6B1CA200A45078 /* playback_stream_capture.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = playback_stream_capture.h; sourceTree = ""; }; + 0F75F40F2A6B1CA200A45078 /* file_info.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = file_info.cpp; sourceTree = ""; }; + 0F75F4102A6B1CA200A45078 /* dsp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dsp.h; sourceTree = ""; }; + 0F75F4112A6B1CA200A45078 /* library_callbacks.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = library_callbacks.h; sourceTree = ""; }; + 0F75F4122A6B1CA200A45078 /* threadsLite.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = threadsLite.h; sourceTree = ""; }; + 0F75F4132A6B1CA200A45078 /* mem_block_container.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mem_block_container.h; sourceTree = ""; }; + 0F75F4142A6B1CA200A45078 /* foobar2000-all.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "foobar2000-all.h"; sourceTree = ""; }; + 0F75F4152A6B1CA200A45078 /* image.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = image.cpp; sourceTree = ""; }; + 0F75F4162A6B1CA200A45078 /* utility.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = utility.cpp; sourceTree = ""; }; + 0F75F4172A6B1CA200A45078 /* track_property.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = track_property.h; sourceTree = ""; }; + 0F75F4182A6B1CA200A45078 /* cfg_var.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = cfg_var.cpp; sourceTree = ""; }; + 0F75F4192A6B1CA200A45078 /* shortcut_actions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = shortcut_actions.h; sourceTree = ""; }; + 0F75F41A2A6B1CA200A45078 /* foosortstring.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = foosortstring.cpp; sourceTree = ""; }; + 0F75F41B2A6B1CA200A45078 /* exceptions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = exceptions.h; sourceTree = ""; }; + 0F75F41C2A6B1CA200A45078 /* component_client.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = component_client.h; sourceTree = ""; }; + 0F75F41D2A6B1CA200A45078 /* playable_location.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = playable_location.cpp; sourceTree = ""; }; + 0F75F41E2A6B1CA200A45078 /* metadb.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = metadb.cpp; sourceTree = ""; }; + 0F75F41F2A6B1CA200A45078 /* input_impl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = input_impl.h; sourceTree = ""; }; + 0F75F4202A6B1CA200A45078 /* service_compat.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = service_compat.h; sourceTree = ""; }; + 0F75F4212A6B1CA300A45078 /* keyValueIO.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = keyValueIO.h; sourceTree = ""; }; + 0F75F4222A6B1CA300A45078 /* tracks.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tracks.h; sourceTree = ""; }; + 0F75F4232A6B1CA300A45078 /* playlistColumnProvider.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = playlistColumnProvider.h; sourceTree = ""; }; + 0F75F4242A6B1CA300A45078 /* imageLoaderLite.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imageLoaderLite.h; sourceTree = ""; }; + 0F75F4252A6B1CA300A45078 /* playlist.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = playlist.cpp; sourceTree = ""; }; + 0F75F4262A6B1CA300A45078 /* preferences_page.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = preferences_page.cpp; sourceTree = ""; }; + 0F75F4272A6B1CA300A45078 /* config_io_callback.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = config_io_callback.cpp; sourceTree = ""; }; + 0F75F4282A6B1CA300A45078 /* packet_decoder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = packet_decoder.cpp; sourceTree = ""; }; + 0F75F4292A6B1CA300A45078 /* ole_interaction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ole_interaction.h; sourceTree = ""; }; + 0F75F42A2A6B1CA300A45078 /* info_lookup_handler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = info_lookup_handler.h; sourceTree = ""; }; + 0F75F42B2A6B1CA300A45078 /* library_index.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = library_index.h; sourceTree = ""; }; + 0F75F42C2A6B1CA300A45078 /* audioEncoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = audioEncoder.h; sourceTree = ""; }; + 0F75F42D2A6B1CA300A45078 /* commandline.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = commandline.cpp; sourceTree = ""; }; + 0F75F42E2A6B1CA300A45078 /* image.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = image.h; sourceTree = ""; }; + 0F75F42F2A6B1CA300A45078 /* link_resolver.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = link_resolver.cpp; sourceTree = ""; }; + 0F75F4302A6B1CA300A45078 /* metadb_handle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = metadb_handle.h; sourceTree = ""; }; + 0F75F4312A6B1CA300A45078 /* advconfig_impl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = advconfig_impl.h; sourceTree = ""; }; + 0F75F4322A6B1CA300A45078 /* foobar2000-versions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "foobar2000-versions.h"; sourceTree = ""; }; + 0F75F4332A6B1CA300A45078 /* componentversion.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = componentversion.h; sourceTree = ""; }; + 0F75F4342A6B1CA300A45078 /* contextmenu.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = contextmenu.h; sourceTree = ""; }; + 0F75F4352A6B1CA300A45078 /* advconfig_impl_legacy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = advconfig_impl_legacy.h; sourceTree = ""; }; + 0F75F4362A6B1CA300A45078 /* file.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = file.h; sourceTree = ""; }; + 0F75F4372A6B1CA300A45078 /* ui_element.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ui_element.cpp; sourceTree = ""; }; + 0F75F4382A6B1CA300A45078 /* guids.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = guids.cpp; sourceTree = ""; }; + 0F75F4392A6B1CA300A45078 /* tag_processor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = tag_processor.cpp; sourceTree = ""; }; + 0F75F43A2A6B1CA300A45078 /* config_object.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = config_object.h; sourceTree = ""; }; + 0F75F43B2A6B1CA300A45078 /* config_object.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = config_object.cpp; sourceTree = ""; }; + 0F75F43C2A6B1CA300A45078 /* ui.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ui.h; sourceTree = ""; }; + 0F75F43D2A6B1CA300A45078 /* link_resolver.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = link_resolver.h; sourceTree = ""; }; + 0F75F43E2A6B1CA300A45078 /* playable_location.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = playable_location.h; sourceTree = ""; }; + 0F75F43F2A6B1CA300A45078 /* file_lock_manager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = file_lock_manager.h; sourceTree = ""; }; + 0F75F4402A6B1CA300A45078 /* configStore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = configStore.h; sourceTree = ""; }; + 0F75F4412A6B1CA300A45078 /* input.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = input.cpp; sourceTree = ""; }; + 0F75F4422A6B1CA300A45078 /* contextmenu_manager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = contextmenu_manager.h; sourceTree = ""; }; + 0F75F4432A6B1CA400A45078 /* config_io_callback.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = config_io_callback.h; sourceTree = ""; }; + 0F75F4442A6B1CA400A45078 /* menu_common.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = menu_common.h; sourceTree = ""; }; + 0F75F4452A6B1CA400A45078 /* completion_notify.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = completion_notify.cpp; sourceTree = ""; }; + 0F75F4462A6B1CA400A45078 /* metadb_info_container_impl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = metadb_info_container_impl.h; sourceTree = ""; }; + 0F75F4472A6B1CA400A45078 /* abort_callback.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = abort_callback.h; sourceTree = ""; }; + 0F75F4482A6B1CA400A45078 /* completion_notify.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = completion_notify.h; sourceTree = ""; }; + 0F75F4492A6B1CA400A45078 /* toolbarDropDown.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = toolbarDropDown.h; sourceTree = ""; }; + 0F75F44A2A6B1CA400A45078 /* dsp_manager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dsp_manager.h; sourceTree = ""; }; + 0F75F44B2A6B1CA400A45078 /* messageBox.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = messageBox.h; sourceTree = ""; }; + 0F75F44C2A6B1CA400A45078 /* ui_edit_context.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ui_edit_context.h; sourceTree = ""; }; + 0F75F44D2A6B1CA400A45078 /* ui_element.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ui_element.h; sourceTree = ""; }; + 0F75F44E2A6B1CA400A45078 /* menu_item.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = menu_item.cpp; sourceTree = ""; }; + 0F75F44F2A6B1CA400A45078 /* callback_merit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = callback_merit.h; sourceTree = ""; }; + 0F75F4502A6B1CA400A45078 /* foosortstring.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = foosortstring.h; sourceTree = ""; }; + 0F75F4512A6B1CA400A45078 /* imageViewer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imageViewer.h; sourceTree = ""; }; + 0F75F4522A6B1CA400A45078 /* popup_message.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = popup_message.cpp; sourceTree = ""; }; + 0F75F4532A6B1CA400A45078 /* fsItem.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = fsItem.cpp; sourceTree = ""; }; + 0F75F4542A6B1CA400A45078 /* cfg_var_legacy.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = cfg_var_legacy.cpp; sourceTree = ""; }; + 0F75F4552A6B1CA500A45078 /* vis.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vis.h; sourceTree = ""; }; + 0F75F4562A6B1CA500A45078 /* console.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = console.h; sourceTree = ""; }; + 0F75F4572A6B1CA500A45078 /* componentversion.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = componentversion.cpp; sourceTree = ""; }; + 0F75F4582A6B1CA500A45078 /* chapterizer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = chapterizer.cpp; sourceTree = ""; }; + 0F75F4592A6B1CA500A45078 /* components_menu.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = components_menu.h; sourceTree = ""; }; + 0F75F45A2A6B1CA500A45078 /* metadb_handle_list.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = metadb_handle_list.cpp; sourceTree = ""; }; + 0F75F45B2A6B1CA500A45078 /* preferences_page.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = preferences_page.h; sourceTree = ""; }; + 0F75F45C2A6B1CA500A45078 /* core_api.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = core_api.h; sourceTree = ""; }; + 0F75F45D2A6B1CA500A45078 /* config_object_impl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = config_object_impl.h; sourceTree = ""; }; + 0F75F45E2A6B1CA500A45078 /* configCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = configCache.h; sourceTree = ""; }; + 0F75F45F2A6B1CA500A45078 /* metadb_display_field_provider.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = metadb_display_field_provider.h; sourceTree = ""; }; + 0F75F4602A6B1CA500A45078 /* dsp-frontend.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "dsp-frontend.h"; sourceTree = ""; }; + 0F75F4612A6B1CA500A45078 /* foobar2000-sdk-pch.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "foobar2000-sdk-pch.h"; sourceTree = ""; }; + 0F75F4622A6B1CA500A45078 /* file_cached_impl.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = file_cached_impl.cpp; sourceTree = ""; }; + 0F75F4632A6B1CA500A45078 /* replaygain_info.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = replaygain_info.cpp; sourceTree = ""; }; + 0F75F4642A6B1CA500A45078 /* metadb_index.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = metadb_index.h; sourceTree = ""; }; + 0F75F4652A6B1CA500A45078 /* mainmenu.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = mainmenu.cpp; sourceTree = ""; }; + 0F75F4662A6B1CA500A45078 /* app_close_blocker.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = app_close_blocker.cpp; sourceTree = ""; }; + 0F75F4672A6B1CA500A45078 /* file_info_impl.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = file_info_impl.cpp; sourceTree = ""; }; + 0F75F4682A6B1CA500A45078 /* tag_processor_id3v2.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = tag_processor_id3v2.cpp; sourceTree = ""; }; + 0F75F4692A6B1CA500A45078 /* audio_postprocessor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = audio_postprocessor.h; sourceTree = ""; }; + 0F75F46A2A6B1CA500A45078 /* file_info.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = file_info.h; sourceTree = ""; }; + 0F75F46B2A6B1CA500A45078 /* replaygain.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = replaygain.cpp; sourceTree = ""; }; + 0F75F46C2A6B1CA500A45078 /* input.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = input.h; sourceTree = ""; }; + 0F75F46D2A6B1CA600A45078 /* file_format_sanitizer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = file_format_sanitizer.h; sourceTree = ""; }; + 0F75F46E2A6B1CA600A45078 /* commonObjects.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = commonObjects.h; sourceTree = ""; }; + 0F75F46F2A6B1CA600A45078 /* powerManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = powerManager.h; sourceTree = ""; }; + 0F75F4702A6B1CA600A45078 /* popup_message.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = popup_message.h; sourceTree = ""; }; + 0F75F4712A6B1CA600A45078 /* archive.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = archive.h; sourceTree = ""; }; + 0F75F4722A6B1CA600A45078 /* system_time_keeper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = system_time_keeper.h; sourceTree = ""; }; + 0F75F4732A6B1CA600A45078 /* play_callback.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = play_callback.h; sourceTree = ""; }; + 0F75F4742A6B1CA600A45078 /* file_info_const_impl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = file_info_const_impl.h; sourceTree = ""; }; + 0F75F4752A6B1CA600A45078 /* file_operation_callback.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = file_operation_callback.h; sourceTree = ""; }; + 0F75F4762A6B1CA600A45078 /* album_art.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = album_art.cpp; sourceTree = ""; }; + 0F75F4772A6B1CA600A45078 /* main_thread_callback.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = main_thread_callback.cpp; sourceTree = ""; }; + 0F75F4782A6B1CA600A45078 /* replaygain_scanner.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = replaygain_scanner.h; sourceTree = ""; }; + 0F75F4792A6B1CA600A45078 /* tag_processor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tag_processor.h; sourceTree = ""; }; + 0F75F47A2A6B1CA700A45078 /* input_file_type.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = input_file_type.cpp; sourceTree = ""; }; + 0F75F47B2A6B1CA700A45078 /* album_art.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = album_art.h; sourceTree = ""; }; + 0F75F47C2A6B1CA700A45078 /* advconfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = advconfig.h; sourceTree = ""; }; + 0F75F47D2A6B1CA700A45078 /* fsitem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fsitem.h; sourceTree = ""; }; + 0F75F47E2A6B1CA700A45078 /* icon_remap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = icon_remap.h; sourceTree = ""; }; + 0F75F47F2A6B1CA700A45078 /* keyValueIOimpl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = keyValueIOimpl.h; sourceTree = ""; }; + 0F75F4802A6B1CA700A45078 /* fileDialog.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fileDialog.h; sourceTree = ""; }; + 0F75F4812A6B1CA700A45078 /* autoplaylist.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = autoplaylist.h; sourceTree = ""; }; + 0F75F4822A6B1CA700A45078 /* input_file_type.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = input_file_type.h; sourceTree = ""; }; + 0F75F4832A6B1CA700A45078 /* album_art_helpers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = album_art_helpers.h; sourceTree = ""; }; + 0F75F4842A6B1CA700A45078 /* hasher_md5.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = hasher_md5.cpp; sourceTree = ""; }; + 0F75F4852A6B1CA700A45078 /* message_loop.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = message_loop.h; sourceTree = ""; }; + 0F75F4862A6B1CA700A45078 /* playlist_loader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = playlist_loader.cpp; sourceTree = ""; }; + 0F75F4872A6B1CA700A45078 /* service_by_guid.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = service_by_guid.h; sourceTree = ""; }; + 0F75F4882A6B1CA700A45078 /* library_manager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = library_manager.h; sourceTree = ""; }; + 0F75F4892A6B1CA700A45078 /* foobar2000-lite.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "foobar2000-lite.h"; sourceTree = ""; }; + 0F75F48A2A6B1CA700A45078 /* commandline.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = commandline.h; sourceTree = ""; }; + 0F75F48B2A6B1CA700A45078 /* coreversion.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = coreversion.h; sourceTree = ""; }; + 0F75F48C2A6B1CA700A45078 /* dsp_manager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = dsp_manager.cpp; sourceTree = ""; }; + 0F75F48D2A6B1CA700A45078 /* playback_control.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = playback_control.cpp; sourceTree = ""; }; + 0F75F48E2A6B1CA700A45078 /* foobar2000.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = foobar2000.h; sourceTree = ""; }; + 0F75F48F2A6B1CA700A45078 /* file_info_filter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = file_info_filter.h; sourceTree = ""; }; + 0F75F4902A6B1CA800A45078 /* metadb_handle.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = metadb_handle.cpp; sourceTree = ""; }; + 0F75F4912A6B1CA800A45078 /* dsp.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = dsp.cpp; sourceTree = ""; }; + 0F75F4922A6B1CA800A45078 /* cfg_var.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cfg_var.h; sourceTree = ""; }; + 0F75F4932A6B1CA800A45078 /* menu_helpers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = menu_helpers.h; sourceTree = ""; }; + 0FCA711A2AA2210C001CB0F2 /* commonObjects-Apple.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = "commonObjects-Apple.mm"; sourceTree = ""; }; + 0FCA711E2AA2715E001CB0F2 /* commonObjects-Apple.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "commonObjects-Apple.h"; sourceTree = ""; }; + B166962019ACC1450001728F /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; + B166962E19ACC1450001728F /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; }; + B166963119ACC1450001728F /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = Library/Frameworks/UIKit.framework; sourceTree = DEVELOPER_DIR; }; + B1DD3657198A721800EF7043 /* libfoobar2000_SDK.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libfoobar2000_SDK.a; sourceTree = BUILT_PRODUCTS_DIR; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + B1DD3654198A721800EF7043 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + B166961F19ACC1450001728F /* Frameworks */ = { + isa = PBXGroup; + children = ( + B166962019ACC1450001728F /* Foundation.framework */, + B166962E19ACC1450001728F /* XCTest.framework */, + B166963119ACC1450001728F /* UIKit.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + B1DD364E198A721800EF7043 = { + isa = PBXGroup; + children = ( + B1DD3670198A725100EF7043 /* Source */, + B166961F19ACC1450001728F /* Frameworks */, + B1DD3658198A721800EF7043 /* Products */, + ); + sourceTree = ""; + }; + B1DD3658198A721800EF7043 /* Products */ = { + isa = PBXGroup; + children = ( + B1DD3657198A721800EF7043 /* libfoobar2000_SDK.a */, + ); + name = Products; + sourceTree = ""; + }; + B1DD3670198A725100EF7043 /* Source */ = { + isa = PBXGroup; + children = ( + 0F75F3D02A6B1CA000A45078 /* abort_callback.cpp */, + 0F75F4472A6B1CA400A45078 /* abort_callback.h */, + 0F75F4352A6B1CA300A45078 /* advconfig_impl_legacy.h */, + 0F75F4312A6B1CA300A45078 /* advconfig_impl.h */, + 0F75F4032A6B1CA200A45078 /* advconfig.cpp */, + 0F75F47C2A6B1CA700A45078 /* advconfig.h */, + 0F75F4832A6B1CA700A45078 /* album_art_helpers.h */, + 0F75F4762A6B1CA600A45078 /* album_art.cpp */, + 0F75F47B2A6B1CA700A45078 /* album_art.h */, + 0F75F4662A6B1CA500A45078 /* app_close_blocker.cpp */, + 0F75F3D82A6B1CA000A45078 /* app_close_blocker.h */, + 0F75F4712A6B1CA600A45078 /* archive.h */, + 0F75F3E52A6B1CA100A45078 /* audio_chunk_channel_config.cpp */, + 0F75F3E42A6B1CA100A45078 /* audio_chunk_impl.h */, + 0F75F3FA2A6B1CA100A45078 /* audio_chunk.cpp */, + 0F75F3CD2A6B1CA000A45078 /* audio_chunk.h */, + 0F75F4692A6B1CA500A45078 /* audio_postprocessor.h */, + 0F75F42C2A6B1CA300A45078 /* audioEncoder.h */, + 0F75F4812A6B1CA700A45078 /* autoplaylist.h */, + 0F75F44F2A6B1CA400A45078 /* callback_merit.h */, + 0F75F4542A6B1CA400A45078 /* cfg_var_legacy.cpp */, + 0F75F4002A6B1CA200A45078 /* cfg_var_legacy.h */, + 0F75F4182A6B1CA200A45078 /* cfg_var.cpp */, + 0F75F4922A6B1CA800A45078 /* cfg_var.h */, + 0F75F4582A6B1CA500A45078 /* chapterizer.cpp */, + 0F75F3E32A6B1CA100A45078 /* chapterizer.h */, + 0F75F42D2A6B1CA300A45078 /* commandline.cpp */, + 0F75F48A2A6B1CA700A45078 /* commandline.h */, + 0F75F3DB2A6B1CA000A45078 /* commonObjects.cpp */, + 0F75F46E2A6B1CA600A45078 /* commonObjects.h */, + 0F75F4452A6B1CA400A45078 /* completion_notify.cpp */, + 0F75F4482A6B1CA400A45078 /* completion_notify.h */, + 0F75F41C2A6B1CA200A45078 /* component_client.h */, + 0F75F3EA2A6B1CA100A45078 /* component.h */, + 0F75F4592A6B1CA500A45078 /* components_menu.h */, + 0F75F4572A6B1CA500A45078 /* componentversion.cpp */, + 0F75F4332A6B1CA300A45078 /* componentversion.h */, + 0F75F4272A6B1CA300A45078 /* config_io_callback.cpp */, + 0F75F4432A6B1CA400A45078 /* config_io_callback.h */, + 0F75F45D2A6B1CA500A45078 /* config_object_impl.h */, + 0F75F43B2A6B1CA300A45078 /* config_object.cpp */, + 0F75F43A2A6B1CA300A45078 /* config_object.h */, + 0F75F45E2A6B1CA500A45078 /* configCache.h */, + 0F75F4092A6B1CA200A45078 /* configStore.cpp */, + 0F75F4402A6B1CA300A45078 /* configStore.h */, + 0F75F3FB2A6B1CA100A45078 /* console_manager.h */, + 0F75F40C2A6B1CA200A45078 /* console.cpp */, + 0F75F4562A6B1CA500A45078 /* console.h */, + 0F75F4422A6B1CA300A45078 /* contextmenu_manager.h */, + 0F75F4342A6B1CA300A45078 /* contextmenu.h */, + 0F75F45C2A6B1CA500A45078 /* core_api.h */, + 0F75F3FF2A6B1CA200A45078 /* coreDarkMode.h */, + 0F75F48B2A6B1CA700A45078 /* coreversion.h */, + 0F75F4052A6B1CA200A45078 /* decode_postprocessor.h */, + 0F75F48C2A6B1CA700A45078 /* dsp_manager.cpp */, + 0F75F44A2A6B1CA400A45078 /* dsp_manager.h */, + 0F75F4602A6B1CA500A45078 /* dsp-frontend.h */, + 0F75F4912A6B1CA800A45078 /* dsp.cpp */, + 0F75F4102A6B1CA200A45078 /* dsp.h */, + 0F75F3E62A6B1CA100A45078 /* event_logger.h */, + 0F75F4062A6B1CA200A45078 /* exception_io.h */, + 0F75F41B2A6B1CA200A45078 /* exceptions.h */, + 0F75F4622A6B1CA500A45078 /* file_cached_impl.cpp */, + 0F75F46D2A6B1CA600A45078 /* file_format_sanitizer.h */, + 0F75F3E22A6B1CA100A45078 /* file_info_const_impl.cpp */, + 0F75F4742A6B1CA600A45078 /* file_info_const_impl.h */, + 0F75F4022A6B1CA200A45078 /* file_info_filter_impl.h */, + 0F75F48F2A6B1CA700A45078 /* file_info_filter.h */, + 0F75F4672A6B1CA500A45078 /* file_info_impl.cpp */, + 0F75F3F72A6B1CA100A45078 /* file_info_impl.h */, + 0F75F3CC2A6B1CA000A45078 /* file_info_merge.cpp */, + 0F75F40F2A6B1CA200A45078 /* file_info.cpp */, + 0F75F46A2A6B1CA500A45078 /* file_info.h */, + 0F75F43F2A6B1CA300A45078 /* file_lock_manager.h */, + 0F75F3CF2A6B1CA000A45078 /* file_operation_callback.cpp */, + 0F75F4752A6B1CA600A45078 /* file_operation_callback.h */, + 0F75F4362A6B1CA300A45078 /* file.h */, + 0F75F4802A6B1CA700A45078 /* fileDialog.h */, + 0F75F3F82A6B1CA100A45078 /* filesystem_helper.cpp */, + 0F75F3F92A6B1CA100A45078 /* filesystem_helper.h */, + 0F75F3FC2A6B1CA100A45078 /* filesystem_transacted.h */, + 0F75F3D52A6B1CA000A45078 /* filesystem.cpp */, + 0F75F3DA2A6B1CA000A45078 /* filesystem.h */, + 0F75F4142A6B1CA200A45078 /* foobar2000-all.h */, + 0F75F4892A6B1CA700A45078 /* foobar2000-lite.h */, + 0F75F3E72A6B1CA100A45078 /* foobar2000-pfc.h */, + 0F75F4612A6B1CA500A45078 /* foobar2000-sdk-pch.h */, + 0F75F4322A6B1CA300A45078 /* foobar2000-versions.h */, + 0F75F3F12A6B1CA100A45078 /* foobar2000-winver.h */, + 0F75F48E2A6B1CA700A45078 /* foobar2000.h */, + 0F75F3C82A6B1CA000A45078 /* foosort.cpp */, + 0F75F40B2A6B1CA200A45078 /* foosort.h */, + 0F75F41A2A6B1CA200A45078 /* foosortstring.cpp */, + 0F75F4502A6B1CA400A45078 /* foosortstring.h */, + 0F75F3EB2A6B1CA100A45078 /* forward_types.h */, + 0F75F4532A6B1CA400A45078 /* fsItem.cpp */, + 0F75F47D2A6B1CA700A45078 /* fsitem.h */, + 0F75F3C92A6B1CA000A45078 /* genrand.h */, + 0F75F4382A6B1CA300A45078 /* guids.cpp */, + 0F75F4842A6B1CA700A45078 /* hasher_md5.cpp */, + 0F75F3E92A6B1CA100A45078 /* hasher_md5.h */, + 0F75F3E82A6B1CA100A45078 /* http_client.h */, + 0F75F47E2A6B1CA700A45078 /* icon_remap.h */, + 0F75F4152A6B1CA200A45078 /* image.cpp */, + 0F75F42E2A6B1CA300A45078 /* image.h */, + 0F75F4242A6B1CA300A45078 /* imageLoaderLite.h */, + 0F75F4512A6B1CA400A45078 /* imageViewer.h */, + 0F75F42A2A6B1CA300A45078 /* info_lookup_handler.h */, + 0F75F3F02A6B1CA100A45078 /* initquit.h */, + 0F75F47A2A6B1CA700A45078 /* input_file_type.cpp */, + 0F75F4822A6B1CA700A45078 /* input_file_type.h */, + 0F75F41F2A6B1CA200A45078 /* input_impl.h */, + 0F75F4412A6B1CA300A45078 /* input.cpp */, + 0F75F46C2A6B1CA500A45078 /* input.h */, + 0F75F4212A6B1CA300A45078 /* keyValueIO.h */, + 0F75F47F2A6B1CA700A45078 /* keyValueIOimpl.h */, + 0F75F4112A6B1CA200A45078 /* library_callbacks.h */, + 0F75F42B2A6B1CA300A45078 /* library_index.h */, + 0F75F4882A6B1CA700A45078 /* library_manager.h */, + 0F75F42F2A6B1CA300A45078 /* link_resolver.cpp */, + 0F75F43D2A6B1CA300A45078 /* link_resolver.h */, + 0F75F4772A6B1CA600A45078 /* main_thread_callback.cpp */, + 0F75F3D42A6B1CA000A45078 /* main_thread_callback.h */, + 0F75F4652A6B1CA500A45078 /* mainmenu.cpp */, + 0F75F3D92A6B1CA000A45078 /* mem_block_container.cpp */, + 0F75F4132A6B1CA200A45078 /* mem_block_container.h */, + 0F75F4442A6B1CA400A45078 /* menu_common.h */, + 0F75F3E02A6B1CA000A45078 /* menu_helpers.cpp */, + 0F75F4932A6B1CA800A45078 /* menu_helpers.h */, + 0F75F44E2A6B1CA400A45078 /* menu_item.cpp */, + 0F75F3EE2A6B1CA100A45078 /* menu_manager.cpp */, + 0F75F4012A6B1CA200A45078 /* menu.h */, + 0F75F4852A6B1CA700A45078 /* message_loop.h */, + 0F75F44B2A6B1CA400A45078 /* messageBox.h */, + 0F75F4082A6B1CA200A45078 /* metadb_callbacks.h */, + 0F75F45F2A6B1CA500A45078 /* metadb_display_field_provider.h */, + 0F75F45A2A6B1CA500A45078 /* metadb_handle_list.cpp */, + 0F75F4902A6B1CA800A45078 /* metadb_handle.cpp */, + 0F75F4302A6B1CA300A45078 /* metadb_handle.h */, + 0F75F4642A6B1CA500A45078 /* metadb_index.h */, + 0F75F4462A6B1CA400A45078 /* metadb_info_container_impl.h */, + 0F75F41E2A6B1CA200A45078 /* metadb.cpp */, + 0F75F3ED2A6B1CA100A45078 /* metadb.h */, + 0F75F40A2A6B1CA200A45078 /* modeless_dialog.h */, + 0F75F3DD2A6B1CA000A45078 /* noInfo.h */, + 0F75F4292A6B1CA300A45078 /* ole_interaction.h */, + 0F75F3DF2A6B1CA000A45078 /* output.cpp */, + 0F75F3CE2A6B1CA000A45078 /* output.h */, + 0F75F4282A6B1CA300A45078 /* packet_decoder.cpp */, + 0F75F4042A6B1CA200A45078 /* packet_decoder.h */, + 0F75F4732A6B1CA600A45078 /* play_callback.h */, + 0F75F41D2A6B1CA200A45078 /* playable_location.cpp */, + 0F75F43E2A6B1CA300A45078 /* playable_location.h */, + 0F75F48D2A6B1CA700A45078 /* playback_control.cpp */, + 0F75F40D2A6B1CA200A45078 /* playback_control.h */, + 0F75F40E2A6B1CA200A45078 /* playback_stream_capture.h */, + 0F75F4862A6B1CA700A45078 /* playlist_loader.cpp */, + 0F75F3D12A6B1CA000A45078 /* playlist_loader.h */, + 0F75F4252A6B1CA300A45078 /* playlist.cpp */, + 0F75F3F32A6B1CA100A45078 /* playlist.h */, + 0F75F4232A6B1CA300A45078 /* playlistColumnProvider.h */, + 0F75F4522A6B1CA400A45078 /* popup_message.cpp */, + 0F75F4702A6B1CA600A45078 /* popup_message.h */, + 0F75F46F2A6B1CA600A45078 /* powerManager.h */, + 0F75F4262A6B1CA300A45078 /* preferences_page.cpp */, + 0F75F45B2A6B1CA500A45078 /* preferences_page.h */, + 0F75F3D72A6B1CA000A45078 /* progress_meter.h */, + 0F75F4632A6B1CA500A45078 /* replaygain_info.cpp */, + 0F75F4782A6B1CA600A45078 /* replaygain_scanner.h */, + 0F75F46B2A6B1CA500A45078 /* replaygain.cpp */, + 0F75F3EC2A6B1CA100A45078 /* replaygain.h */, + 0F75F3EF2A6B1CA100A45078 /* resampler.h */, + 0F75F4072A6B1CA200A45078 /* search_tools.h */, + 0F75F4872A6B1CA700A45078 /* service_by_guid.h */, + 0F75F4202A6B1CA200A45078 /* service_compat.h */, + 0F75F3D32A6B1CA000A45078 /* service_impl.h */, + 0F75F3FD2A6B1CA100A45078 /* service.cpp */, + 0F75F3E12A6B1CA000A45078 /* service.h */, + 0F75F4192A6B1CA200A45078 /* shortcut_actions.h */, + 0F75F3D62A6B1CA000A45078 /* stdafx.cpp */, + 0F75F4722A6B1CA600A45078 /* system_time_keeper.h */, + 0F75F4682A6B1CA500A45078 /* tag_processor_id3v2.cpp */, + 0F75F4392A6B1CA300A45078 /* tag_processor.cpp */, + 0F75F4792A6B1CA600A45078 /* tag_processor.h */, + 0F75F3FE2A6B1CA200A45078 /* threaded_process.cpp */, + 0F75F3D22A6B1CA000A45078 /* threaded_process.h */, + 0F75F3DC2A6B1CA000A45078 /* threadPool.h */, + 0F75F4122A6B1CA200A45078 /* threadsLite.h */, + 0F75F3F22A6B1CA100A45078 /* timer.h */, + 0F75F3CB2A6B1CA000A45078 /* titleformat.cpp */, + 0F75F3F62A6B1CA100A45078 /* titleformat.h */, + 0F75F4492A6B1CA400A45078 /* toolbarDropDown.h */, + 0F75F3F42A6B1CA100A45078 /* track_property.cpp */, + 0F75F4172A6B1CA200A45078 /* track_property.h */, + 0F75F4222A6B1CA300A45078 /* tracks.h */, + 0F75F44C2A6B1CA400A45078 /* ui_edit_context.h */, + 0F75F3CA2A6B1CA000A45078 /* ui_element_typable_window_manager.h */, + 0F75F4372A6B1CA300A45078 /* ui_element.cpp */, + 0F75F44D2A6B1CA400A45078 /* ui_element.h */, + 0F75F3F52A6B1CA100A45078 /* ui.cpp */, + 0F75F43C2A6B1CA300A45078 /* ui.h */, + 0F75F3DE2A6B1CA000A45078 /* unpack.h */, + 0F75F4162A6B1CA200A45078 /* utility.cpp */, + 0F75F4552A6B1CA500A45078 /* vis.h */, + 0FCA711A2AA2210C001CB0F2 /* commonObjects-Apple.mm */, + 0FCA711E2AA2715E001CB0F2 /* commonObjects-Apple.h */, + ); + name = Source; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + B1DD3655198A721800EF7043 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 0F75F5092A6B1CA800A45078 /* link_resolver.h in Headers */, + 0F75F4D42A6B1CA800A45078 /* metadb_callbacks.h in Headers */, + 0F75F4D12A6B1CA800A45078 /* decode_postprocessor.h in Headers */, + 0F75F50E2A6B1CA800A45078 /* contextmenu_manager.h in Headers */, + 0F75F4D32A6B1CA800A45078 /* search_tools.h in Headers */, + 0F75F4C72A6B1CA800A45078 /* console_manager.h in Headers */, + 0F75F4C82A6B1CA800A45078 /* filesystem_transacted.h in Headers */, + 0F75F4CE2A6B1CA800A45078 /* file_info_filter_impl.h in Headers */, + 0F75F5222A6B1CA800A45078 /* console.h in Headers */, + 0F75F4EC2A6B1CA800A45078 /* service_compat.h in Headers */, + 0F75F4EF2A6B1CA800A45078 /* playlistColumnProvider.h in Headers */, + 0F75F4DF2A6B1CA800A45078 /* mem_block_container.h in Headers */, + 0F75F4D62A6B1CA800A45078 /* modeless_dialog.h in Headers */, + 0F75F5532A6B1CA800A45078 /* service_by_guid.h in Headers */, + 0F75F5182A6B1CA800A45078 /* ui_edit_context.h in Headers */, + 0F75F50B2A6B1CA800A45078 /* file_lock_manager.h in Headers */, + 0F75F54F2A6B1CA800A45078 /* album_art_helpers.h in Headers */, + 0F75F4D02A6B1CA800A45078 /* packet_decoder.h in Headers */, + 0F75F4B02A6B1CA800A45078 /* audio_chunk_impl.h in Headers */, + 0F75F4FD2A6B1CA800A45078 /* advconfig_impl.h in Headers */, + 0F75F53C2A6B1CA800A45078 /* popup_message.h in Headers */, + 0F75F4D22A6B1CA800A45078 /* exception_io.h in Headers */, + 0F75F52A2A6B1CA800A45078 /* configCache.h in Headers */, + 0F75F4992A6B1CA800A45078 /* audio_chunk.h in Headers */, + 0F75F4E72A6B1CA800A45078 /* exceptions.h in Headers */, + 0F75F4DC2A6B1CA800A45078 /* dsp.h in Headers */, + 0F75F54C2A6B1CA800A45078 /* fileDialog.h in Headers */, + 0F75F5102A6B1CA800A45078 /* menu_common.h in Headers */, + 0F75F4CB2A6B1CA800A45078 /* coreDarkMode.h in Headers */, + 0F75F5082A6B1CA800A45078 /* ui.h in Headers */, + 0F75F55B2A6B1CA800A45078 /* file_info_filter.h in Headers */, + 0F75F5292A6B1CA800A45078 /* config_object_impl.h in Headers */, + 0F75F54D2A6B1CA800A45078 /* autoplaylist.h in Headers */, + 0F75F4C32A6B1CA800A45078 /* file_info_impl.h in Headers */, + 0F75F4952A6B1CA800A45078 /* genrand.h in Headers */, + 0F75F4962A6B1CA800A45078 /* ui_element_typable_window_manager.h in Headers */, + 0F75F5062A6B1CA800A45078 /* config_object.h in Headers */, + 0F75F51C2A6B1CA800A45078 /* foosortstring.h in Headers */, + 0F75F55A2A6B1CA800A45078 /* foobar2000.h in Headers */, + 0F75F5002A6B1CA800A45078 /* contextmenu.h in Headers */, + 0F75F4CC2A6B1CA800A45078 /* cfg_var_legacy.h in Headers */, + 0F75F4BB2A6B1CA800A45078 /* resampler.h in Headers */, + 0F75F4DE2A6B1CA800A45078 /* threadsLite.h in Headers */, + 0F75F5282A6B1CA800A45078 /* core_api.h in Headers */, + 0F75F5152A6B1CA800A45078 /* toolbarDropDown.h in Headers */, + 0F75F5172A6B1CA800A45078 /* messageBox.h in Headers */, + 0F75F49E2A6B1CA800A45078 /* threaded_process.h in Headers */, + 0F75F4FA2A6B1CA800A45078 /* image.h in Headers */, + 0F75F4BF2A6B1CA800A45078 /* playlist.h in Headers */, + 0F75F4EB2A6B1CA800A45078 /* input_impl.h in Headers */, + 0F75F5012A6B1CA800A45078 /* advconfig_impl_legacy.h in Headers */, + 0F75F5412A6B1CA800A45078 /* file_operation_callback.h in Headers */, + 0F75F4B42A6B1CA800A45078 /* http_client.h in Headers */, + 0F75F4F82A6B1CA800A45078 /* audioEncoder.h in Headers */, + 0F75F4DA2A6B1CA800A45078 /* playback_stream_capture.h in Headers */, + 0F75F5512A6B1CA800A45078 /* message_loop.h in Headers */, + 0F75F55F2A6B1CA800A45078 /* menu_helpers.h in Headers */, + 0F75F4C22A6B1CA800A45078 /* titleformat.h in Headers */, + 0F75F4ED2A6B1CA800A45078 /* keyValueIO.h in Headers */, + 0F75F5212A6B1CA800A45078 /* vis.h in Headers */, + 0F75F51D2A6B1CA800A45078 /* imageViewer.h in Headers */, + 0F75F4F62A6B1CA800A45078 /* info_lookup_handler.h in Headers */, + 0F75F5302A6B1CA800A45078 /* metadb_index.h in Headers */, + 0F75F4B22A6B1CA800A45078 /* event_logger.h in Headers */, + 0F75F50A2A6B1CA800A45078 /* playable_location.h in Headers */, + 0F75F53E2A6B1CA800A45078 /* system_time_keeper.h in Headers */, + 0F75F4D92A6B1CA800A45078 /* playback_control.h in Headers */, + 0F75F4F02A6B1CA800A45078 /* imageLoaderLite.h in Headers */, + 0F75F5402A6B1CA800A45078 /* file_info_const_impl.h in Headers */, + 0F75F52C2A6B1CA800A45078 /* dsp-frontend.h in Headers */, + 0F75F5482A6B1CA800A45078 /* advconfig.h in Headers */, + 0F75F54B2A6B1CA800A45078 /* keyValueIOimpl.h in Headers */, + 0F75F53A2A6B1CA800A45078 /* commonObjects.h in Headers */, + 0F75F5492A6B1CA800A45078 /* fsitem.h in Headers */, + 0F75F4AF2A6B1CA800A45078 /* chapterizer.h in Headers */, + 0F75F5442A6B1CA800A45078 /* replaygain_scanner.h in Headers */, + 0F75F4A82A6B1CA800A45078 /* threadPool.h in Headers */, + 0F75F5142A6B1CA800A45078 /* completion_notify.h in Headers */, + 0F75F4A02A6B1CA800A45078 /* main_thread_callback.h in Headers */, + 0F75F5192A6B1CA800A45078 /* ui_element.h in Headers */, + 0F75F5272A6B1CA800A45078 /* preferences_page.h in Headers */, + 0F75F5542A6B1CA800A45078 /* library_manager.h in Headers */, + 0F75F4AA2A6B1CA800A45078 /* unpack.h in Headers */, + 0F75F4FE2A6B1CA800A45078 /* foobar2000-versions.h in Headers */, + 0F75F4A32A6B1CA800A45078 /* progress_meter.h in Headers */, + 0F75F5022A6B1CA800A45078 /* file.h in Headers */, + 0F75F4F52A6B1CA800A45078 /* ole_interaction.h in Headers */, + 0F75F5392A6B1CA800A45078 /* file_format_sanitizer.h in Headers */, + 0F75F5572A6B1CA800A45078 /* coreversion.h in Headers */, + 0F75F50C2A6B1CA800A45078 /* configStore.h in Headers */, + 0F75F53D2A6B1CA800A45078 /* archive.h in Headers */, + 0F75F4D72A6B1CA800A45078 /* foosort.h in Headers */, + 0F75F5122A6B1CA800A45078 /* metadb_info_container_impl.h in Headers */, + 0F75F4E32A6B1CA800A45078 /* track_property.h in Headers */, + 0F75F5162A6B1CA800A45078 /* dsp_manager.h in Headers */, + 0F75F53B2A6B1CA800A45078 /* powerManager.h in Headers */, + 0F75F4E82A6B1CA800A45078 /* component_client.h in Headers */, + 0F75F52D2A6B1CA800A45078 /* foobar2000-sdk-pch.h in Headers */, + 0F75F5562A6B1CA800A45078 /* commandline.h in Headers */, + 0F75F4B52A6B1CA800A45078 /* hasher_md5.h in Headers */, + 0F75F4A42A6B1CA800A45078 /* app_close_blocker.h in Headers */, + 0F75F4FF2A6B1CA800A45078 /* componentversion.h in Headers */, + 0F75F4B92A6B1CA800A45078 /* metadb.h in Headers */, + 0F75F54A2A6B1CA800A45078 /* icon_remap.h in Headers */, + 0F75F4FC2A6B1CA800A45078 /* metadb_handle.h in Headers */, + 0F75F4BD2A6B1CA800A45078 /* foobar2000-winver.h in Headers */, + 0F75F4BE2A6B1CA800A45078 /* timer.h in Headers */, + 0F75F4B72A6B1CA800A45078 /* forward_types.h in Headers */, + 0F75F4F72A6B1CA800A45078 /* library_index.h in Headers */, + 0F75F4EE2A6B1CA800A45078 /* tracks.h in Headers */, + 0F75F5552A6B1CA800A45078 /* foobar2000-lite.h in Headers */, + 0F75F49A2A6B1CA800A45078 /* output.h in Headers */, + 0F75F4CD2A6B1CA800A45078 /* menu.h in Headers */, + 0F75F4B32A6B1CA800A45078 /* foobar2000-pfc.h in Headers */, + 0F75F53F2A6B1CA800A45078 /* play_callback.h in Headers */, + 0F75F5132A6B1CA800A45078 /* abort_callback.h in Headers */, + 0F75F4BC2A6B1CA800A45078 /* initquit.h in Headers */, + 0F75F5472A6B1CA800A45078 /* album_art.h in Headers */, + 0F75F55E2A6B1CA800A45078 /* cfg_var.h in Headers */, + 0F75F49F2A6B1CA800A45078 /* service_impl.h in Headers */, + 0F75F4A62A6B1CA800A45078 /* filesystem.h in Headers */, + 0F75F4B62A6B1CA800A45078 /* component.h in Headers */, + 0F75F5352A6B1CA800A45078 /* audio_postprocessor.h in Headers */, + 0F75F52B2A6B1CA800A45078 /* metadb_display_field_provider.h in Headers */, + 0F75F5362A6B1CA800A45078 /* file_info.h in Headers */, + 0F75F4E52A6B1CA800A45078 /* shortcut_actions.h in Headers */, + 0F75F4C52A6B1CA800A45078 /* filesystem_helper.h in Headers */, + 0F75F4DD2A6B1CA800A45078 /* library_callbacks.h in Headers */, + 0F75F50F2A6B1CA800A45078 /* config_io_callback.h in Headers */, + 0F75F49D2A6B1CA800A45078 /* playlist_loader.h in Headers */, + 0F75F54E2A6B1CA800A45078 /* input_file_type.h in Headers */, + 0F75F5452A6B1CA800A45078 /* tag_processor.h in Headers */, + 0F75F5382A6B1CA800A45078 /* input.h in Headers */, + 0F75F4E02A6B1CA800A45078 /* foobar2000-all.h in Headers */, + 0F75F5252A6B1CA800A45078 /* components_menu.h in Headers */, + 0F75F51B2A6B1CA800A45078 /* callback_merit.h in Headers */, + 0F75F4AD2A6B1CA800A45078 /* service.h in Headers */, + 0F75F4B82A6B1CA800A45078 /* replaygain.h in Headers */, + 0F75F4A92A6B1CA800A45078 /* noInfo.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + B1DD3656198A721800EF7043 /* foobar2000_SDK */ = { + isa = PBXNativeTarget; + buildConfigurationList = B1DD365B198A721800EF7043 /* Build configuration list for PBXNativeTarget "foobar2000_SDK" */; + buildPhases = ( + B1DD3653198A721800EF7043 /* Sources */, + B1DD3654198A721800EF7043 /* Frameworks */, + B1DD3655198A721800EF7043 /* Headers */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = foobar2000_SDK; + productName = foobar2000_SDK; + productReference = B1DD3657198A721800EF7043 /* libfoobar2000_SDK.a */; + productType = "com.apple.product-type.library.static"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + B1DD364F198A721800EF7043 /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 1250; + ORGANIZATIONNAME = "___FULLUSERNAME___"; + }; + buildConfigurationList = B1DD3652198A721800EF7043 /* Build configuration list for PBXProject "foobar2000_SDK" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = B1DD364E198A721800EF7043; + productRefGroup = B1DD3658198A721800EF7043 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + B1DD3656198A721800EF7043 /* foobar2000_SDK */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXSourcesBuildPhase section */ + B1DD3653198A721800EF7043 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 0F75F5042A6B1CA800A45078 /* guids.cpp in Sources */, + 0F75F5242A6B1CA800A45078 /* chapterizer.cpp in Sources */, + 0F75F50D2A6B1CA800A45078 /* input.cpp in Sources */, + 0F75F5372A6B1CA800A45078 /* replaygain.cpp in Sources */, + 0F75F5462A6B1CA800A45078 /* input_file_type.cpp in Sources */, + 0FCA711C2AA2210C001CB0F2 /* commonObjects-Apple.mm in Sources */, + 0F75F5332A6B1CA800A45078 /* file_info_impl.cpp in Sources */, + 0F75F4C62A6B1CA800A45078 /* audio_chunk.cpp in Sources */, + 0F75F4D82A6B1CA800A45078 /* console.cpp in Sources */, + 0F75F4C02A6B1CA800A45078 /* track_property.cpp in Sources */, + 0F75F4BA2A6B1CA800A45078 /* menu_manager.cpp in Sources */, + 0F75F5322A6B1CA800A45078 /* app_close_blocker.cpp in Sources */, + 0F75F5112A6B1CA800A45078 /* completion_notify.cpp in Sources */, + 0F75F49B2A6B1CA800A45078 /* file_operation_callback.cpp in Sources */, + 0F75F5422A6B1CA800A45078 /* album_art.cpp in Sources */, + 0F75F5262A6B1CA800A45078 /* metadb_handle_list.cpp in Sources */, + 0F75F5072A6B1CA800A45078 /* config_object.cpp in Sources */, + 0F75F5432A6B1CA800A45078 /* main_thread_callback.cpp in Sources */, + 0F75F4A72A6B1CA800A45078 /* commonObjects.cpp in Sources */, + 0F75F51E2A6B1CA800A45078 /* popup_message.cpp in Sources */, + 0F75F52F2A6B1CA800A45078 /* replaygain_info.cpp in Sources */, + 0F75F5232A6B1CA800A45078 /* componentversion.cpp in Sources */, + 0F75F5592A6B1CA800A45078 /* playback_control.cpp in Sources */, + 0F75F4E22A6B1CA800A45078 /* utility.cpp in Sources */, + 0F75F4942A6B1CA800A45078 /* foosort.cpp in Sources */, + 0F75F5052A6B1CA800A45078 /* tag_processor.cpp in Sources */, + 0F75F4E12A6B1CA800A45078 /* image.cpp in Sources */, + 0F75F5202A6B1CA800A45078 /* cfg_var_legacy.cpp in Sources */, + 0F75F51F2A6B1CA800A45078 /* fsItem.cpp in Sources */, + 0F75F4C12A6B1CA800A45078 /* ui.cpp in Sources */, + 0F75F4CF2A6B1CA800A45078 /* advconfig.cpp in Sources */, + 0F75F4F32A6B1CA800A45078 /* config_io_callback.cpp in Sources */, + 0F75F4F42A6B1CA800A45078 /* packet_decoder.cpp in Sources */, + 0F75F4DB2A6B1CA800A45078 /* file_info.cpp in Sources */, + 0F75F4AC2A6B1CA800A45078 /* menu_helpers.cpp in Sources */, + 0F75F4CA2A6B1CA800A45078 /* threaded_process.cpp in Sources */, + 0F75F5032A6B1CA800A45078 /* ui_element.cpp in Sources */, + 0F75F4A12A6B1CA800A45078 /* filesystem.cpp in Sources */, + 0F75F4A52A6B1CA800A45078 /* mem_block_container.cpp in Sources */, + 0F75F5312A6B1CA800A45078 /* mainmenu.cpp in Sources */, + 0F75F49C2A6B1CA800A45078 /* abort_callback.cpp in Sources */, + 0F75F52E2A6B1CA800A45078 /* file_cached_impl.cpp in Sources */, + 0F75F5522A6B1CA800A45078 /* playlist_loader.cpp in Sources */, + 0F75F4AE2A6B1CA800A45078 /* file_info_const_impl.cpp in Sources */, + 0F75F4982A6B1CA800A45078 /* file_info_merge.cpp in Sources */, + 0F75F4F22A6B1CA800A45078 /* preferences_page.cpp in Sources */, + 0F75F4C92A6B1CA800A45078 /* service.cpp in Sources */, + 0F75F4EA2A6B1CA800A45078 /* metadb.cpp in Sources */, + 0F75F4A22A6B1CA800A45078 /* stdafx.cpp in Sources */, + 0F75F51A2A6B1CA800A45078 /* menu_item.cpp in Sources */, + 0F75F4FB2A6B1CA800A45078 /* link_resolver.cpp in Sources */, + 0F75F4AB2A6B1CA800A45078 /* output.cpp in Sources */, + 0F75F4F12A6B1CA800A45078 /* playlist.cpp in Sources */, + 0F75F4E42A6B1CA800A45078 /* cfg_var.cpp in Sources */, + 0F75F55D2A6B1CA800A45078 /* dsp.cpp in Sources */, + 0F75F4B12A6B1CA800A45078 /* audio_chunk_channel_config.cpp in Sources */, + 0F75F4D52A6B1CA800A45078 /* configStore.cpp in Sources */, + 0F75F5342A6B1CA800A45078 /* tag_processor_id3v2.cpp in Sources */, + 0F75F4E92A6B1CA800A45078 /* playable_location.cpp in Sources */, + 0F75F5502A6B1CA800A45078 /* hasher_md5.cpp in Sources */, + 0F75F55C2A6B1CA800A45078 /* metadb_handle.cpp in Sources */, + 0F75F5582A6B1CA800A45078 /* dsp_manager.cpp in Sources */, + 0F75F4E62A6B1CA800A45078 /* foosortstring.cpp in Sources */, + 0F75F4C42A6B1CA800A45078 /* filesystem_helper.cpp in Sources */, + 0F75F4F92A6B1CA800A45078 /* commandline.cpp in Sources */, + 0F75F4972A6B1CA800A45078 /* titleformat.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + B1DD3659198A721800EF7043 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_OBJC_EXCEPTIONS = YES; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "foobar2000-sdk-pch.h"; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + .., + ../.., + ); + IPHONEOS_DEPLOYMENT_TARGET = 12.1; + MACOSX_DEPLOYMENT_TARGET = 10.13; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + SKIP_INSTALL = YES; + }; + name = Debug; + }; + B1DD365A198A721800EF7043 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_ENABLE_OBJC_EXCEPTIONS = YES; + GCC_NO_COMMON_BLOCKS = YES; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "foobar2000-sdk-pch.h"; + GCC_PREPROCESSOR_DEFINITIONS = "NDEBUG=1"; + GCC_SYMBOLS_PRIVATE_EXTERN = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + .., + ../.., + ); + IPHONEOS_DEPLOYMENT_TARGET = 12.1; + MACOSX_DEPLOYMENT_TARGET = 10.13; + SDKROOT = macosx; + SKIP_INSTALL = YES; + }; + name = Release; + }; + B1DD365C198A721800EF7043 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + EXECUTABLE_PREFIX = lib; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + B1DD365D198A721800EF7043 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + EXECUTABLE_PREFIX = lib; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + B1DD3652198A721800EF7043 /* Build configuration list for PBXProject "foobar2000_SDK" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + B1DD3659198A721800EF7043 /* Debug */, + B1DD365A198A721800EF7043 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + B1DD365B198A721800EF7043 /* Build configuration list for PBXNativeTarget "foobar2000_SDK" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + B1DD365C198A721800EF7043 /* Debug */, + B1DD365D198A721800EF7043 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = B1DD364F198A721800EF7043 /* Project object */; +} diff --git a/3rdparty/foo_SDK/foobar2000/SDK/fsItem.cpp b/3rdparty/foo_SDK/foobar2000/SDK/fsItem.cpp index 83a65b06..21618482 100644 --- a/3rdparty/foo_SDK/foobar2000/SDK/fsItem.cpp +++ b/3rdparty/foo_SDK/foobar2000/SDK/fsItem.cpp @@ -119,6 +119,7 @@ namespace { public: fsItemFileStd(filesystem::ptr fs, stringRef canonicalPath, t_filestats2 const & opportunistStats) : m_fs(fs), m_path(canonicalPath), m_opportunistStats(opportunistStats) { m_opportunistStats.set_folder(false); + m_opportunistStats.set_remote(fs->is_remote(canonicalPath->c_str())); } filesystem::ptr getFS() override { return m_fs; } @@ -184,7 +185,9 @@ namespace { PFC_ASSERT(!"Should not get here"); break; } - return m_fs->makeItemFileStd(dst); + auto stats = m_opportunistStats; + stats.set_file(); + return m_fs->makeItemFileStd(dst, stats); } } private: @@ -196,6 +199,7 @@ namespace { public: fsItemFolderStd(filesystem::ptr fs, stringRef canonicalPath, t_filestats2 const & opportunistStats) : m_fs(fs), m_path(canonicalPath), m_opportunistStats(opportunistStats) { m_opportunistStats.set_folder(true); + m_opportunistStats.set_remote(fs->is_remote(canonicalPath->c_str())); } filesystem::ptr getFS() override { return m_fs; } @@ -239,7 +243,7 @@ namespace { fsItemFile::ptr findChildFile(const char* fileName, abort_callback& aborter) override { auto sub = subPath(fileName); - auto stats = m_fs->get_stats2_(sub->c_str(), stats2_fileOrFolder, aborter); + auto stats = m_fs->get_stats2_(sub->c_str(), stats2_fileOrFolder | foobar2000_io::stats2_remote, aborter); if (!stats.is_folder()) { return m_fs->makeItemFileStd(sub->c_str(), stats); } @@ -247,14 +251,15 @@ namespace { } fsItemFolder::ptr findChildFolder(const char* fileName, abort_callback& aborter) override { auto sub = subPath(fileName); - if (m_fs->directory_exists(sub->c_str(), aborter)) { - return m_fs->makeItemFolderStd(sub->c_str()); + auto stats = m_fs->get_stats2_(sub->c_str(), stats2_fileOrFolder | foobar2000_io::stats2_remote, aborter); + if (stats.is_folder()) { + return m_fs->makeItemFolderStd(sub->c_str(), stats); } throw exception_io_not_found(); } fsItemBase::ptr findChild(const char* fileName, abort_callback& aborter) override { auto sub = subPath(fileName); - auto stats = m_fs->get_stats2_(sub->c_str(), stats2_fileOrFolder, aborter); + auto stats = m_fs->get_stats2_(sub->c_str(), stats2_fileOrFolder | foobar2000_io::stats2_remote, aborter); if ( stats.is_folder() ) { return m_fs->makeItemFileStd(sub->c_str(), stats ); } else { @@ -266,7 +271,13 @@ namespace { pfc::string8 fn(fileName); uniqueFn(fn, add); auto sub = subPath(fn); - const bool bDidExist = m_fs->file_exists(sub->c_str(), aborter); + t_filestats2 stats; + + bool bDidExist = false; + try { + stats = m_fs->get_stats2_( sub->c_str(), stats2_all, aborter ); + bDidExist = stats.is_file(); + } catch(exception_io_not_found) {} switch (createMode) { case createMode::allowExisting: break; // OK @@ -287,9 +298,9 @@ namespace { // FIX ME this should be atomic with exists() check file::ptr creator; m_fs->open(creator, sub->c_str(), filesystem::open_mode_write_new, aborter); - // creator->commit(aborter); + stats = creator->get_stats2_( stats2_all, aborter ); } - return m_fs->makeItemFileStd(sub->c_str()); + return m_fs->makeItemFileStd(sub->c_str(), stats); } } fsItemFolder::ptr createFolder(const char* fileName, unsigned createMode, abort_callback& aborter) override { @@ -317,7 +328,8 @@ namespace { PFC_ASSERT(!"Should not get here"); break; } - return m_fs->makeItemFolderStd(sub->c_str()); + // Inherit opportunist stats + return m_fs->makeItemFolderStd(sub->c_str(), this->m_opportunistStats); } } fsItemPtr moveTo(fsItemFolderPtr folder, const char* desiredName, unsigned createMode, abort_callback& aborter) override { @@ -350,7 +362,7 @@ namespace { break; } - return m_fs->makeItemFolderStd(dst); + return m_fs->makeItemFolderStd(dst, m_opportunistStats); } } @@ -373,36 +385,46 @@ fsItemFolder::ptr filesystem::makeItemFolderStd(const char* pathCanonical, t_fil fsItemFile::ptr filesystem::makeItemFileStd(const char* pathCanonical, t_filestats2 const & opportunistStats) { return new service_impl_t(this, makeString(pathCanonical), opportunistStats); } - -fsItemBase::ptr fsItemBase::fromPath(const char* path, abort_callback& aborter) { - auto fs = filesystem::get(path); - +fsItemBase::ptr filesystem::findItem_(const char* path, abort_callback& p_abort) { filesystem_v3::ptr v3; - if (v3 &= fs) return v3->findItem(path, aborter); + if (v3 &= this) { + return v3->findItem(path, p_abort); + } + auto stats = this->get_stats2_(path, stats2_fileOrFolder, p_abort); + if (stats.is_folder()) return this->makeItemFolderStd(path, stats); + else return this->makeItemFileStd(path, stats); - auto stats = fs->get_stats2_(path, stats2_fileOrFolder, aborter); - if (stats.is_folder()) return fs->makeItemFolderStd(path, stats); - else return fs->makeItemFileStd(path, stats); } +fsItemFile::ptr filesystem::findItemFile_(const char* path, abort_callback& p_abort) { + filesystem_v3::ptr v3; + if (v3 &= this) return v3->findItemFile(path, p_abort); -fsItemFile::ptr fsItemFile::fromPath(const char* path, abort_callback& aborter) { - auto fs = filesystem::get(path); - + auto stats = this->get_stats2_(path, stats2_fileOrFolder, p_abort); + if (!stats.is_folder()) return this->makeItemFileStd(path, stats); + throw exception_io_not_found(); +} +fsItemFolder::ptr filesystem::findItemFolder_(const char* path, abort_callback& p_abort) { filesystem_v3::ptr v3; - if ( v3 &= fs ) return v3->findItemFile(path, aborter); + if (v3 &= this) return v3->findItemFolder(path, p_abort); - auto stats = fs->get_stats2_(path, stats2_fileOrFolder, aborter); - if (!stats.is_folder()) return fs->makeItemFileStd(path, stats); + auto stats = this->get_stats2_(path, stats2_fileOrFolder, p_abort); + if (stats.is_folder()) return this->makeItemFolderStd(path, stats); throw exception_io_not_found(); } -fsItemFolder::ptr fsItemFolder::fromPath(const char* path, abort_callback& aborter) { - auto fs = filesystem::get(path); - filesystem_v3::ptr v3; - if (v3 &= fs) return v3->findItemFolder(path, aborter); +fsItemBase::ptr fsItemBase::fromPath(const char* path, abort_callback& aborter) { + return filesystem::get(path)->findItem_(path, aborter); +} - auto stats = fs->get_stats2_(path, stats2_fileOrFolder, aborter); - if (stats.is_folder()) return fs->makeItemFolderStd(path, stats); - throw exception_io_not_found(); +fsItemFile::ptr fsItemFile::fromPath(const char* path, abort_callback& aborter) { + return filesystem::get(path)->findItemFile_(path, aborter); +} + +fsItemFolder::ptr fsItemFolder::fromPath(const char* path, abort_callback& aborter) { + return filesystem::get(path)->findItemFolder_(path, aborter); +} + +t_filestats fsItemBase::getStats(abort_callback& a) { + return getStats2(stats2_all, a).to_legacy(); } diff --git a/3rdparty/foo_SDK/foobar2000/SDK/fsitem.h b/3rdparty/foo_SDK/foobar2000/SDK/fsitem.h index ca9d498b..1fcc4af1 100644 --- a/3rdparty/foo_SDK/foobar2000/SDK/fsitem.h +++ b/3rdparty/foo_SDK/foobar2000/SDK/fsitem.h @@ -3,8 +3,14 @@ // fsItem API // Alternate, object-based way of accessing the local filesystem. // It is recommended to use fsItem methods to operate on user-specified media folders. -// In some cases, most notably Android and UWP, accessing user's documents/media over paths requires expensive resolving of objects representing them. +// In some cases, notably Android and WinPhone/UWP, accessing user's documents/media over paths requires expensive resolving of objects representing them. // fsItem can cache platform specific resources necessary to manipulate the files, allowing efficient opening of files returned by directory enumeration. +// +// Note that as of 2023, fsItem is just a convenience API. +// WinPhone/UWP has been dropped; slow and buggy Android DocumentFile (*) wrapper is being abandoned. On neither of these platforms foobar2000 supports loading components. +// Nothing in current-generation foobar2000 gains performance from using fsItem methods over plain filesystem with paths. +// +// (*) Android DocumentFile is slow and buggy, not the wrapper. Google sucks. #include "file.h" #include "commonObjects.h" @@ -84,6 +90,8 @@ namespace foobar2000_io { virtual service_ptr_t getFS() = 0; static fsItemBase::ptr fromPath(const char* path, abort_callback& aborter); + + t_filestats getStats(abort_callback& a); }; class fsItemFile : public fsItemBase { diff --git a/3rdparty/foo_SDK/foobar2000/SDK/genrand.h b/3rdparty/foo_SDK/foobar2000/SDK/genrand.h index 256668eb..70aae87c 100644 --- a/3rdparty/foo_SDK/foobar2000/SDK/genrand.h +++ b/3rdparty/foo_SDK/foobar2000/SDK/genrand.h @@ -3,6 +3,7 @@ class NOVTABLE genrand_service : public service_base { public: + void seedAuto() {seed( 0 ) ;} //! Seeds the PRNG with specified value. \n //! Default value of zero seeds automatically using available system functions. virtual void seed(unsigned val = 0) = 0; diff --git a/3rdparty/foo_SDK/foobar2000/SDK/guids.cpp b/3rdparty/foo_SDK/foobar2000/SDK/guids.cpp index 37e5ba76..26de10f9 100644 --- a/3rdparty/foo_SDK/foobar2000/SDK/guids.cpp +++ b/3rdparty/foo_SDK/foobar2000/SDK/guids.cpp @@ -50,6 +50,7 @@ FOOGUIDDECL const GUID dsp_v3::class_guid = { 0x3743c03a, 0xae20, 0x40e3, { 0x90 FOOGUIDDECL const GUID dsp_entry_v2::class_guid = { 0x9ec5d45e, 0x10f5, 0x46a7, { 0x95, 0x46, 0xf3, 0xac, 0xec, 0x68, 0xb1, 0x49 } }; FOOGUIDDECL const GUID dsp_entry_hidden::class_guid = { 0xe3f0c95f, 0x7a0b, 0x48bc, { 0x96, 0x58, 0x71, 0xa4, 0x69, 0x68, 0x88, 0x76 } }; FOOGUIDDECL const GUID dsp_entry_v3::class_guid = { 0xb4d5a127, 0x5e59, 0x466d, { 0x93, 0x6b, 0x39, 0x5e, 0xdf, 0xb9, 0x37, 0xa4 } }; +FOOGUIDDECL const GUID dsp_entry_v4::class_guid = { 0xf13a5ce9, 0xd6e8, 0x4ad8, { 0x9e, 0xba, 0x9d, 0x6a, 0x34, 0x84, 0x29, 0x61 } }; FOOGUIDDECL const GUID dsp_preset_edit_callback_v2::class_guid = { 0x904173f6, 0x345e, 0x47d0, { 0x88, 0x60, 0x63, 0xa2, 0xc9, 0xd0, 0x9, 0x52 } }; @@ -194,6 +195,10 @@ FOOGUIDDECL const GUID archive_v2::class_guid = FOOGUIDDECL const GUID archive_v3::class_guid = { 0x8d3f8b2d, 0xa866, 0x4f1f, { 0x9a, 0x4f, 0xff, 0x23, 0x92, 0x9e, 0xd6, 0xda } }; +// {FD3AE540-4C46-43AD-A331-2337737A64C6} +FOOGUIDDECL const GUID archive_v4::class_guid = +{ 0xfd3ae540, 0x4c46, 0x43ad, { 0xa3, 0x31, 0x23, 0x37, 0x73, 0x7a, 0x64, 0xc6 } }; + // {B2F9FC40-3E55-4b23-A2C9-22BAAD8795B1} FOOGUIDDECL const GUID file::class_guid = { 0xb2f9fc40, 0x3e55, 0x4b23, { 0xa2, 0xc9, 0x22, 0xba, 0xad, 0x87, 0x95, 0xb1 } }; @@ -233,10 +238,10 @@ FOOGUIDDECL const GUID titleformat_compiler::class_guid = FOOGUIDDECL const GUID titleformat_compiler_v2::class_guid = { 0xa81de54, 0x8131, 0x4c43, { 0x92, 0xef, 0x15, 0xc5, 0x8b, 0xd4, 0x72, 0x7a } }; -#ifdef _WIN32 FOOGUIDDECL const GUID user_interface::class_guid = { 0x1add4dc4, 0xb278, 0x4a0c, { 0xa1, 0x5, 0x26, 0x29, 0xf4, 0xb3, 0x12, 0xf4 } }; FOOGUIDDECL const GUID user_interface_v2::class_guid = { 0x5f5ac82b, 0x44a7, 0x4872,{ 0xb7, 0x86, 0x1c, 0x1f, 0xc6, 0x56, 0x6b, 0x60 } }; +#ifdef _WIN32 FOOGUIDDECL const GUID user_interface_v2::cap_suppress_core_shellhook = { 0xe5950632, 0x750d, 0x4265,{ 0x8c, 0xea, 0x6c, 0xf2, 0x77, 0x91, 0x44, 0x40 } }; FOOGUIDDECL const GUID user_interface_v2::cap_suppress_core_uvc = { 0xe35156b2, 0xfbac, 0x450d,{ 0xa3, 0xf7, 0xf1, 0xda, 0x46, 0xb6, 0xdf, 0x8d } }; @@ -843,8 +848,10 @@ FOOGUIDDECL const GUID preferences_page::guid_keyboard_shortcuts = { 0xa4dbfa19, FOOGUIDDECL const GUID preferences_page_v2::class_guid = { 0xce4ebc9e, 0xab20, 0x46f9, { 0x92, 0x5f, 0x88, 0x3b, 0x8, 0x4f, 0x5, 0x69 } }; FOOGUIDDECL const GUID preferences_branch_v2::class_guid = { 0x167ebeb9, 0x8334, 0x4b21, { 0xaf, 0x58, 0xa7, 0x40, 0xa5, 0xd5, 0xb6, 0x66 } }; +#ifdef _WIN32 FOOGUIDDECL const GUID preferences_page_callback::class_guid = { 0x3d26e08e, 0x861c, 0x4599, { 0x9c, 0x89, 0xaa, 0xa7, 0x19, 0xaf, 0x50, 0x70 } }; FOOGUIDDECL const GUID preferences_page_instance::class_guid = { 0x6893a996, 0xa816, 0x49fe, { 0x82, 0xce, 0xc, 0xb8, 0x4, 0xa4, 0xcf, 0xec } }; +#endif FOOGUIDDECL const GUID preferences_page_v3::class_guid = { 0xd6d0f741, 0x9f17, 0x4df8, { 0x9d, 0x5c, 0x87, 0xf2, 0x8b, 0x1f, 0xe, 0x64 } }; FOOGUIDDECL const GUID preferences_page_v4::class_guid = { 0x76227dab, 0xc740, 0x4d49, { 0xa2, 0xe2, 0x50, 0x80, 0x13, 0xe, 0xf6, 0xba } }; @@ -864,7 +871,6 @@ FOOGUIDDECL const GUID input_decoder_v4::class_guid = { 0x7bbf10b5, 0x2064, 0x4d FOOGUIDDECL const GUID input_params::seeking_expensive = { 0x10973582, 0x1aae, 0x4169, { 0xb9, 0x76, 0xb5, 0xbe, 0xf9, 0x4b, 0x7a, 0x71 } }; FOOGUIDDECL const GUID input_params::set_preferred_sample_rate = { 0x7dc7f926, 0x9b9f, 0x4a73, { 0xa2, 0x37, 0x83, 0xe9, 0x93, 0x38, 0x41, 0x75 } }; FOOGUIDDECL const GUID input_params::query_position = { 0xa9d79933, 0x5438, 0x480f, { 0x85, 0xf3, 0xb6, 0xb8, 0xee, 0x1e, 0xfa, 0xe9 } }; -FOOGUIDDECL const GUID input_params::continue_stream = { 0x673050df, 0x11f6, 0x4039, { 0x8b, 0x4, 0x6c, 0x31, 0x98, 0x91, 0x4b, 0x89 } }; FOOGUIDDECL const GUID input_params::is_tag_write_safe = { 0x9f44a346, 0x73f0, 0x459b, { 0x98, 0x47, 0xf4, 0x86, 0x9b, 0x29, 0xbc, 0x93 } }; FOOGUIDDECL const GUID input_info_reader::class_guid = { 0x8e9bb1d4, 0xa52b, 0x4df6, { 0xa9, 0x29, 0x1a, 0xae, 0x40, 0x75, 0x38, 0x8a } }; FOOGUIDDECL const GUID input_info_reader_v2::class_guid = { 0x42486bca, 0xd37, 0x4e02, { 0xb7, 0x72, 0x4d, 0x30, 0xd6, 0xf8, 0x50, 0xbe } }; @@ -901,6 +907,10 @@ FOOGUIDDECL const GUID playback_queue_callback::class_guid = FOOGUIDDECL const GUID main_thread_callback_manager::class_guid = { 0x1131d64b, 0x4cb, 0x43ee, { 0x95, 0xeb, 0x24, 0xd1, 0x8b, 0x75, 0x32, 0x48 } }; +// {38986E70-A333-456D-8FEE-0AFBDFD4F919} +FOOGUIDDECL const GUID main_thread_callback_manager_v2::class_guid = +{ 0x38986e70, 0xa333, 0x456d, { 0x8f, 0xee, 0xa, 0xfb, 0xdf, 0xd4, 0xf9, 0x19 } }; + // {87D2C583-7AFB-4e58-B21E-FBD3E6E8F5E7} FOOGUIDDECL const GUID main_thread_callback::class_guid = { 0x87d2c583, 0x7afb, 0x4e58, { 0xb2, 0x1e, 0xfb, 0xd3, 0xe6, 0xe8, 0xf5, 0xe7 } }; @@ -1095,6 +1105,7 @@ FOOGUIDDECL const GUID standard_commands::guid_seek_back_10min = FOOGUIDDECL const GUID standard_commands::guid_library_configure = { 0xa305602d, 0x4716, 0x4fc2, { 0x91, 0x57, 0xc6, 0x33, 0x9c, 0x4b, 0x1c, 0xe9 } }; FOOGUIDDECL const GUID standard_commands::guid_library_rescan = { 0xb21d432e, 0xb14d, 0x4c8d, { 0xaf, 0xda, 0xf, 0x45, 0xc7, 0xb6, 0x22, 0x26 } }; +FOOGUIDDECL const GUID standard_commands::guid_internet_radio = { 0x58712f87, 0x3d7b, 0x4f2e, { 0x88, 0xe5, 0x7d, 0xea, 0xe1, 0xa5, 0xf2, 0x3d } }; // {97215C5E-7228-4237-B52C-A2B5504EF726} FOOGUIDDECL const GUID playback_statistics_collector::class_guid = @@ -1112,6 +1123,7 @@ FOOGUIDDECL const GUID advconfig_entry::guid_branch_tools = { 0x35365484, 0xcc58 FOOGUIDDECL const GUID advconfig_entry::guid_branch_playback = { 0xc48d430d, 0x112, 0x4922, { 0x97, 0x23, 0x28, 0x38, 0xc7, 0xd9, 0x7d, 0xd7 } }; FOOGUIDDECL const GUID advconfig_entry::guid_branch_display = { 0x6c4bc1c8, 0xbaf4, 0x40c3, { 0x9d, 0xb1, 0x9, 0x50, 0x7f, 0xc, 0xc, 0xb9 } }; FOOGUIDDECL const GUID advconfig_entry::guid_branch_vis = { 0xea1017c6, 0x298, 0x446c, { 0xb6, 0xc7, 0xbd, 0xf9, 0x1e, 0xd8, 0x12, 0xee } }; +FOOGUIDDECL const GUID advconfig_entry::guid_branch_general = { 0x534dc6e3, 0x29a2, 0x42f4, { 0xab, 0x49, 0x5a, 0x2, 0x71, 0x9b, 0x1d, 0xa } }; FOOGUIDDECL const GUID advconfig_entry::guid_branch_debug = { 0xc375447d, 0x58e6, 0x4fd5, { 0xbd, 0xd8, 0x99, 0xfa, 0xef, 0x7b, 0x30, 0x9f } }; FOOGUIDDECL const GUID advconfig_entry::guid_branch_tagging_general = { 0x1a7757de, 0x55bd, 0x4c25, { 0xb2, 0xf9, 0xc6, 0x3a, 0x85, 0x0, 0xba, 0xed } }; FOOGUIDDECL const GUID advconfig_entry::guid_branch_converter = { 0x96ea6eae, 0xe848, 0x44d9, { 0x99, 0xd6, 0x4d, 0xa6, 0xeb, 0x39, 0x81, 0x8f } }; @@ -1120,10 +1132,6 @@ FOOGUIDDECL const GUID advconfig_entry::guid_branch_converter = { 0x96ea6eae, 0x FOOGUIDDECL const GUID playback_control_v2::class_guid = { 0x1eb67bda, 0x1345, 0x49ae, { 0x8e, 0x89, 0x50, 0x5, 0xd9, 0x1, 0x62, 0x89 } }; - - -FOOGUIDDECL const GUID advconfig_entry_enum::class_guid = { 0xb1451540, 0x98ec, 0x4d36, { 0x9f, 0x19, 0xe3, 0x10, 0xfb, 0xa7, 0xab, 0x5a } }; - FOOGUIDDECL const GUID info_lookup_handler::class_guid = { 0x4fcfdab7, 0x55b5, 0x47d6, { 0xb1, 0x9d, 0xa4, 0xdc, 0x9f, 0xd7, 0x69, 0x4c } }; FOOGUIDDECL const GUID info_lookup_handler_v2::class_guid = { 0x3c9728a5, 0x89e5, 0x4560, { 0xb6, 0x8b, 0x9b, 0x9b, 0x90, 0x1f, 0x0, 0x7b } }; @@ -1311,11 +1319,10 @@ FOOGUIDDECL const GUID mainmenu_node::class_guid = { 0xabba6512, 0x377d, 0x414f, FOOGUIDDECL const GUID system_time_keeper::class_guid = { 0xdc5d4938, 0x7927, 0x48ba, { 0xbf, 0x84, 0xda, 0x2f, 0xb1, 0xb, 0x36, 0xf2 } }; -#ifdef _WIN32 FOOGUIDDECL const GUID component_installation_validator::class_guid = { 0x639283e, 0x3004, 0x4e5c, { 0xb1, 0xb3, 0x6d, 0xff, 0x8, 0xa7, 0x92, 0x84 } }; -#endif FOOGUIDDECL const GUID playback_stream_capture::class_guid = { 0x9423439e, 0x8cd5, 0x45d7, { 0xaa, 0x6d, 0x4b, 0x98, 0xc, 0x22, 0x93, 0x3e } }; +FOOGUIDDECL const GUID playback_stream_capture_v2::class_guid = { 0x801e6865, 0x6040, 0x42a6, { 0x8c, 0x43, 0x57, 0x91, 0x8a, 0xdc, 0xee, 0xb7 } }; FOOGUIDDECL const GUID http_request::class_guid = { 0x48580056, 0x2c5f, 0x45a8, { 0xb8, 0x6e, 0x5, 0x83, 0x55, 0x3e, 0xaa, 0x4f } }; FOOGUIDDECL const GUID http_request_post::class_guid = { 0xe254b804, 0xeac5, 0x4be0, { 0x99, 0x4d, 0x53, 0x1c, 0x17, 0xea, 0xfd, 0x37 } }; @@ -1331,6 +1338,7 @@ FOOGUIDDECL const GUID metadb_index_transaction::class_guid = { 0xe4b7e77e, 0xbe FOOGUIDDECL const GUID init_stage_callback::class_guid = { 0xaf51c159, 0x6326, 0x4da5, { 0x90, 0xb0, 0xf1, 0x1f, 0x99, 0x64, 0xcc, 0x2e } }; FOOGUIDDECL const GUID metadb_io_edit_callback::class_guid = { 0x2388a50f, 0x33d, 0x4b7c, { 0x91, 0xf2, 0x51, 0x53, 0x69, 0x43, 0xe9, 0xed } }; +FOOGUIDDECL const GUID metadb_io_edit_callback_v2::class_guid = { 0x8a4ac70, 0xaf77, 0x4a73, { 0xa6, 0xe9, 0xd5, 0xbc, 0x6, 0x9e, 0x6, 0x15 } }; FOOGUIDDECL const GUID progress_meter_instance::class_guid = { 0x13915b24, 0xefef, 0x42b5, { 0xae, 0x1d, 0x55, 0x24, 0x5e, 0x22, 0x22, 0xc5 } }; FOOGUIDDECL const GUID progress_meter::class_guid = { 0x5e98da34, 0xa9c7, 0x4925, { 0xb0, 0xec, 0x90, 0x9d, 0xe0, 0x16, 0xfa, 0x68 } }; @@ -1388,6 +1396,7 @@ FOOGUIDDECL const GUID ui_element_instance_callback_v3::class_guid = { 0x6d15c0c FOOGUIDDECL const GUID ui_element_popup_host_v2::class_guid = { 0x8caac11e, 0x52b6, 0x47f7,{ 0x97, 0xc9, 0x2c, 0x87, 0xdb, 0xdb, 0x2e, 0x5b } }; FOOGUIDDECL const GUID ui_config_manager::class_guid = { 0x199050a6, 0xd0fe, 0x47af, { 0x9b, 0xd7, 0xfc, 0x74, 0x59, 0x9e, 0x47, 0xbd } }; +FOOGUIDDECL const GUID ui_config_manager_v2::class_guid = { 0x2ed12611, 0xda05, 0x4ab9, { 0x87, 0x5b, 0xfb, 0x1b, 0x5c, 0x39, 0xcd, 0xc2 } }; FOOGUIDDECL const GUID ui_edit_context::class_guid = { 0xf9ba651b, 0x52dd, 0x466f,{ 0xaa, 0x77, 0xa9, 0x7a, 0x74, 0x98, 0x80, 0x7e } }; @@ -1401,8 +1410,6 @@ FOOGUIDDECL const GUID file_format_sanitizer_v2::class_guid = { 0xe61986b7, 0x12 #endif // FOOBAR2000_HAVE_FILE_FORMAT_SANITIZER -FOOGUIDDECL const GUID filesystem_transacted::class_guid = { 0x35637f92, 0x6b65, 0x47b8,{ 0x9e, 0xe, 0x48, 0x47, 0x97, 0x62, 0x34, 0x3 } }; -FOOGUIDDECL const GUID filesystem_transacted_entry::class_guid = { 0xfd6e6849, 0x7006, 0x44db,{ 0x9b, 0x87, 0x45, 0x58, 0x3c, 0xf7, 0x5d, 0x18 } }; FOOGUIDDECL const GUID config_io_callback_v3::class_guid = { 0x8e633dd, 0x625e, 0x402c,{ 0xbe, 0xab, 0x74, 0x9, 0xd0, 0x1d, 0x41, 0xdf } }; FOOGUIDDECL const GUID filesystem_v2::class_guid = { 0xdaf04ce2, 0x36a5, 0x4346,{ 0x80, 0x7f, 0x77, 0x8c, 0x5b, 0x5c, 0x26, 0xaa } }; FOOGUIDDECL const GUID filesystem_v3::class_guid = { 0x7166094e, 0xbc64, 0x4c97, { 0xaa, 0x53, 0x62, 0xbd, 0x7a, 0x34, 0xb8, 0xf6 } }; @@ -1494,3 +1501,20 @@ FOOGUIDDECL const GUID contextmenu_manager_v2::class_guid = { 0x8e56ee90, 0x37fb FOOGUIDDECL const GUID fb2k::console_manager::class_guid = { 0x39c3406b, 0xe2f, 0x43f3, { 0x87, 0xf2, 0xa6, 0xa3, 0x79, 0x2a, 0x98, 0x8 } }; FOOGUIDDECL const GUID fb2k::toolbarDropDown::class_guid = { 0x59aabce2, 0xce9f, 0x428b, { 0x8f, 0x10, 0xe, 0x24, 0xf3, 0xb6, 0xc7, 0x6d } }; + +FOOGUIDDECL const GUID search_index_manager::class_guid = { 0x281b998c, 0xb379, 0x4533, { 0x95, 0xe0, 0x90, 0xa2, 0x89, 0x30, 0x2a, 0x4a } }; +FOOGUIDDECL const GUID search_index::class_guid = { 0x581f032e, 0x8e4c, 0x4a46, { 0xbb, 0xa4, 0xef, 0xc, 0xc6, 0x5c, 0x98, 0xfa } }; + + +FOOGUIDDECL const GUID fb2k::callback_with_merit::class_guid = { 0x27c64500, 0x5481, 0x477a, { 0x9b, 0x22, 0x5d, 0x4c, 0x4d, 0xa6, 0x2, 0x88 } }; +FOOGUIDDECL const GUID playlist_manager_v6::class_guid = { 0x8fd46228, 0x9ba3, 0x4bb1, { 0xa0, 0x9c, 0xe8, 0x5b, 0x9e, 0x45, 0x8a, 0x58 } }; +FOOGUIDDECL const GUID library_manager_v6::class_guid = { 0x92eea180, 0x93d0, 0x44ef, { 0xbc, 0x43, 0xb6, 0x88, 0xae, 0x41, 0xb7, 0xad } }; +FOOGUIDDECL const GUID play_callback_manager_v2::class_guid = { 0x7e59a4e6, 0x810d, 0x433b, { 0xb6, 0x9, 0x12, 0xf4, 0xde, 0x7f, 0x7f, 0x47 } }; +FOOGUIDDECL const GUID metadb_hint_list_v4::class_guid = { 0xe7908ec9, 0xa26a, 0x418e, { 0xac, 0x13, 0xb4, 0x17, 0x67, 0x8c, 0xa, 0x4 } }; +FOOGUIDDECL const GUID metadb_pre_update_callback::class_guid = { 0xc81865af, 0x1da2, 0x4361, { 0x92, 0x88, 0xac, 0xf7, 0x83, 0x89, 0xe1, 0x9c } }; + +FOOGUIDDECL const GUID stream_receive::class_guid = { 0x1d36b5af, 0xaa6b, 0x450d, { 0xa4, 0x1f, 0x58, 0x19, 0x13, 0x4e, 0xdb, 0x57 } }; + +#ifdef __APPLE__ +FOOGUIDDECL const GUID fb2k::NSObjectWrapper::class_guid = { 0x6ec55805, 0x96f7, 0x4a8f, { 0x92, 0xb3, 0xbd, 0x33, 0xee, 0x10, 0x53, 0x17 } }; +#endif diff --git a/3rdparty/foo_SDK/foobar2000/SDK/hasher_md5.h b/3rdparty/foo_SDK/foobar2000/SDK/hasher_md5.h index ad186f1a..dccf9228 100644 --- a/3rdparty/foo_SDK/foobar2000/SDK/hasher_md5.h +++ b/3rdparty/foo_SDK/foobar2000/SDK/hasher_md5.h @@ -11,9 +11,11 @@ struct hasher_md5_result { t_uint64 xorHalve() const; GUID asGUID() const; pfc::string8 asString() const; + pfc::string8 toString() const { return asString(); } GUID toGUID() const; static hasher_md5_result null() {hasher_md5_result h = {}; return h;} + static int compare(hasher_md5_result const & h1, hasher_md5_result const & h2) { return memcmp(&h1, &h2, sizeof(hasher_md5_result)); } }; FB2K_STREAM_READER_OVERLOAD(hasher_md5_result) { @@ -25,6 +27,8 @@ FB2K_STREAM_WRITER_OVERLOAD(hasher_md5_result) { inline bool operator==(const hasher_md5_result & p_item1,const hasher_md5_result & p_item2) {return memcmp(&p_item1,&p_item2,sizeof(hasher_md5_result)) == 0;} inline bool operator!=(const hasher_md5_result & p_item1,const hasher_md5_result & p_item2) {return memcmp(&p_item1,&p_item2,sizeof(hasher_md5_result)) != 0;} +inline bool operator>(const hasher_md5_result & p_item1, const hasher_md5_result & p_item2) { return memcmp(&p_item1, &p_item2, sizeof(hasher_md5_result)) > 0; } +inline bool operator<(const hasher_md5_result & p_item1, const hasher_md5_result & p_item2) { return memcmp(&p_item1, &p_item2, sizeof(hasher_md5_result)) < 0; } namespace pfc { template<> class traits_t : public traits_rawobject {}; diff --git a/3rdparty/foo_SDK/foobar2000/SDK/info_lookup_handler.h b/3rdparty/foo_SDK/foobar2000/SDK/info_lookup_handler.h index 56822aad..fdf194ae 100644 --- a/3rdparty/foo_SDK/foobar2000/SDK/info_lookup_handler.h +++ b/3rdparty/foo_SDK/foobar2000/SDK/info_lookup_handler.h @@ -16,9 +16,9 @@ class NOVTABLE info_lookup_handler : public service_base { virtual fb2k::hicon_t get_icon(int p_width, int p_height) = 0; //! Performs a lookup. Creates a modeless dialog and returns immediately. - //! @param p_items Items to look up. - //! @param p_notify Callback to notify caller when the operation has completed. Call on_completion with status code 0 to signal failure/abort, or with code 1 to signal success / new infos in metadb. - //! @param p_parent Parent window for the lookup dialog. Caller will typically disable the window while lookup is in progress and enable it back when completion is signaled. + //! @param items Items to look up. + //! @param notify Callback to notify caller when the operation has completed. Call on_completion with status code 0 to signal failure/abort, or with code 1 to signal success / new infos in metadb. + //! @param parent Parent window for the lookup dialog. Caller will typically disable the window while lookup is in progress and enable it back when completion is signaled. virtual void lookup(metadb_handle_list_cref items,completion_notify::ptr notify,fb2k::hwnd_t parent) = 0; FB2K_MAKE_SERVICE_INTERFACE_ENTRYPOINT(info_lookup_handler); diff --git a/3rdparty/foo_SDK/foobar2000/SDK/initquit.h b/3rdparty/foo_SDK/foobar2000/SDK/initquit.h index bc34b1f6..411f63ad 100644 --- a/3rdparty/foo_SDK/foobar2000/SDK/initquit.h +++ b/3rdparty/foo_SDK/foobar2000/SDK/initquit.h @@ -38,3 +38,41 @@ class NOVTABLE init_stage_callback : public service_base { static void dispatch(t_uint32 stage) {FB2K_FOR_EACH_SERVICE(init_stage_callback, on_init_stage(stage));} }; + +//! Helper for FB2K_RUN_ON_INIT_QUIT() +class initquit_lambda : public initquit { +public: + initquit_lambda(std::function i, std::function q) : m_init(i), m_quit(q) {} + void on_init() override { if (m_init) m_init(); } + void on_quit() override { if (m_quit) m_quit(); } +private: + const std::function m_init, m_quit; +}; + +//! Helper macros to skip implementing initquit.\n +//! Usage: \n +//! void myfunc() { ... } \n +//! FB2K_RUN_ON_INIT(myFunc); +#define FB2K_RUN_ON_INIT_QUIT(funcInit, funcQuit) FB2K_SERVICE_FACTORY_PARAMS(initquit_lambda, funcInit, funcQuit) +#define FB2K_RUN_ON_INIT(func) FB2K_RUN_ON_INIT_QUIT(func, nullptr) +#define FB2K_RUN_ON_QUIT(func) FB2K_RUN_ON_INIT_QUIT(nullptr, func) + +//! Helper for FB2K_ON_INIT_STAGE +class init_stage_callback_lambda : public init_stage_callback { +public: + init_stage_callback_lambda(std::function f, uint32_t stage) : m_func(f), m_stage(stage) {} + + void on_init_stage(t_uint32 stage) override { + PFC_ASSERT(m_func != nullptr); + if (stage == m_stage) m_func(); + } + + const std::function m_func; + const uint32_t m_stage; +}; + +//! Helper macro to skip implementing init_stage_callback.\n +//! Usage: \n +//! void myfunc() {...} \n +//! FB2K_ON_INIT_STAGE(myfunc, init_stages::after_ui_init); +#define FB2K_ON_INIT_STAGE(func, stage) FB2K_SERVICE_FACTORY_PARAMS(init_stage_callback_lambda, func, stage) diff --git a/3rdparty/foo_SDK/foobar2000/SDK/input.cpp b/3rdparty/foo_SDK/foobar2000/SDK/input.cpp index 9dbf0cd1..1452a6d1 100644 --- a/3rdparty/foo_SDK/foobar2000/SDK/input.cpp +++ b/3rdparty/foo_SDK/foobar2000/SDK/input.cpp @@ -350,13 +350,15 @@ void input_open_file_helper(service_ptr_t & p_file,const char * p_path,t_i } uint32_t input_entry::g_flags_for_path( const char * path, uint32_t mask ) { -#if FOOBAR2000_TARGET_VERSION >= 80 +#if defined(FOOBAR2000_DESKTOP) && FOOBAR2000_TARGET_VERSION >= 80 return input_manager_v3::get()->flags_for_path(path, mask); #else +#ifdef FOOBAR2000_DESKTOP input_manager_v3::ptr api; if ( input_manager_v3::tryGet(api) ) { return api->flags_for_path(path, mask); } +#endif uint32_t ret = 0; service_enum_t e; input_entry::ptr p; auto ext = pfc::string_extension(path); @@ -368,14 +370,16 @@ uint32_t input_entry::g_flags_for_path( const char * path, uint32_t mask ) { #endif } uint32_t input_entry::g_flags_for_content_type( const char * ct, uint32_t mask ) { -#if FOOBAR2000_TARGET_VERSION >= 80 +#if defined(FOOBAR2000_DESKTOP) && FOOBAR2000_TARGET_VERSION >= 80 return input_manager_v3::get()->flags_for_content_type(ct, mask); #else +#ifdef FOOBAR2000_DESKTOP input_manager_v3::ptr api; if ( input_manager_v3::tryGet(api) ) { return api->flags_for_content_type( ct, mask ); } - uint32_t ret = 0; +#endif + uint32_t ret = 0; service_enum_t e; input_entry::ptr p; while(e.next(p)) { uint32_t f = p->get_flags() & mask; @@ -428,4 +432,28 @@ t_filestats2 input_info_reader::get_stats2_(const char* fallbackPath, uint32_t f } catch (exception_io) {} } return ret; +} + +GUID input_entry::get_guid_() { + auto ret = pfc::guid_null; + input_entry_v2::ptr v2; + if ( v2 &= this ) ret = v2->get_guid(); + return ret; +} + +const char* input_entry::get_name_() { + const char * ret = ""; + input_entry_v2::ptr v2; + if ( v2 &= this ) ret = v2->get_name(); + return ret; +} + +input_entry::ptr input_entry::g_find_by_guid(const GUID& guid) { + for (auto ptr : enumerate()) { + input_entry_v2::ptr v2; + if (v2 &= ptr) { + if ( guid == v2->get_guid() ) return v2; + } + } + return nullptr; } \ No newline at end of file diff --git a/3rdparty/foo_SDK/foobar2000/SDK/input.h b/3rdparty/foo_SDK/foobar2000/SDK/input.h index be857e7c..f49dc156 100644 --- a/3rdparty/foo_SDK/foobar2000/SDK/input.h +++ b/3rdparty/foo_SDK/foobar2000/SDK/input.h @@ -97,8 +97,7 @@ class NOVTABLE input_decoder : public input_info_reader //! @returns false to keep old info, or true to indicate that changes have been made to p_info and those should be displayed. virtual bool get_dynamic_info_track(file_info & p_out, double & p_timestamp_delta) = 0; - //! Called from playback thread before sleeping. - //! @param p_abort abort_callback object signaling user aborting the operation. + //! Obsolete, do not use, do not rely on. virtual void on_idle(abort_callback & p_abort) = 0; @@ -154,17 +153,7 @@ class input_params { //! Return 1 if position was written to arg2, 0 if n/a. static const GUID query_position; - struct continue_stream_t { - file::ptr reader; - const char * path; - }; - //! Tells the decoder to continue decoding from another URL, without flushing etc. Mainly used by HLS streams. - //! arg2: continue_stream_t - //! Return 1 to acknowledge, 0 if unsupported. - //! A call to decode_initialize() will follow if you return 1; perform actual file open from there. - static const GUID continue_stream; - - //! Asks whether it is OK to externally rewrite tags on this file without closing and reopening the decoder. \n + //! Asks whether it is OK to externally rewrite tags on this file without closing and reopening the decoder. \n //! Return 1 if the decoder reads all relevant content in open() without leaving the file open afterwards, 0 otherwise (the default). static const GUID is_tag_write_safe; }; @@ -277,6 +266,10 @@ class NOVTABLE input_entry : public service_base { static uint32_t g_flags_for_path( const char * pathFor, uint32_t mask = UINT32_MAX ); static uint32_t g_flags_for_content_type( const char * ct, uint32_t mask = UINT32_MAX ); + + GUID get_guid_(); + const char * get_name_(); + static input_entry::ptr g_find_by_guid( const GUID & ); }; //! \since 1.4 diff --git a/3rdparty/foo_SDK/foobar2000/SDK/input_impl.h b/3rdparty/foo_SDK/foobar2000/SDK/input_impl.h index e131e629..69e0e6f5 100644 --- a/3rdparty/foo_SDK/foobar2000/SDK/input_impl.h +++ b/3rdparty/foo_SDK/foobar2000/SDK/input_impl.h @@ -28,7 +28,8 @@ class input_impl //! - input_open_info_read - info retrieval methods are valid; \n //! - input_open_decode - info retrieval and decoding methods are valid; \n //! - input_open_info_write - info retrieval and retagging methods are valid; \n - //! Note that info retrieval methods are valid in all cases, and they may be called at any point of decoding/retagging process. Results of info retrieval methods (other than get_subsong_count() / get_subsong()) between retag_set_info() and retag_commit() are undefined however; those should not be called during that period. + //! Note that info retrieval methods are valid in all cases, and they may be called at any point of decoding/retagging process. Results of info retrieval methods (other than get_subsong_count() / get_subsong()) between retag_set_info() and retag_commit() are undefined however; those should not be called during that period. \n + //! If your implementation does not support writing tags, throw exception_tagging_unsupported in response to input_open_info_write and do not implement other tag writing methods (they will not be called). //! @param p_abort abort_callback object signaling user aborting the operation. void open(service_ptr_t p_filehint,const char * p_path,t_input_open_reason p_reason,abort_callback & p_abort); @@ -53,13 +54,20 @@ class input_impl bool decode_get_dynamic_info(file_info & p_out, double & p_timestamp_delta); //! See: input_decoder::get_dynamic_info_track(). Valid after decode_initialize(). bool decode_get_dynamic_info_track(file_info & p_out, double & p_timestamp_delta); - //! See: input_decoder::on_idle(). Valid after decode_initialize(). + //! Obsolete, do not use, do not rely on. void decode_on_idle(abort_callback & p_abort); - //! See: input_info_writer::set_info(). Valid after open() with input_open_info_write reason. + //! See: input_info_writer::set_info(). Valid after open() with input_open_info_write reason. \n + //! If your implementation does not support writing tags, throw exception_tagging_unsupported from open() and retag_* methods will never be called. void retag_set_info(t_uint32 p_subsong,const file_info & p_info,abort_callback & p_abort); - //! See: input_info_writer::commit(). Valid after open() with input_open_info_write reason. - void retag_commit(abort_callback & p_abort); + //! See: input_info_writer::commit(). Valid after open() with input_open_info_write reason. \n + //! If your implementation does not support writing tags, throw exception_tagging_unsupported from open() and retag_* methods will never be called. + void retag_commit(abort_callback & p_abort); + + //! See: input_info_writer_v2::remove_tags(). Valid after open() with input_open_info_write reason. \n + //! If possible, entirely remove tags from the file (truncate ID3/APE tags away etc); otherwise set blank metadata. \n + //! If your implementation does not support writing tags, throw exception_tagging_unsupported from open() and remove_tags() will never be called. + void remove_tags(abort_callback & p_abort); //! See: input_entry::is_our_content_type(). static bool g_is_our_content_type(const char * p_content_type); @@ -121,7 +129,8 @@ class input_singletrack_impl //! - input_open_info_read - info retrieval methods are valid; \n //! - input_open_decode - info retrieval and decoding methods are valid; \n //! - input_open_info_write - info retrieval and retagging methods are valid; \n - //! Note that info retrieval methods are valid in all cases, and they may be called at any point of decoding/retagging process. Results of info retrieval methods (other than get_subsong_count() / get_subsong()) between retag_set_info() and retag_commit() are undefined however; those should not be called during that period. + //! Note that info retrieval methods are valid in all cases, and they may be called at any point of decoding/retagging process. Results of info retrieval methods (other than get_subsong_count() / get_subsong()) between retag_set_info() and retag_commit() are undefined however; those should not be called during that period. \n + //! If your implementation does not support writing tags, throw exception_tagging_unsupported in response to input_open_info_write and do not implement other tag writing methods (they will not be called). //! @param p_abort abort_callback object signaling user aborting the operation. void open(service_ptr_t p_filehint,const char * p_path,t_input_open_reason p_reason,abort_callback & p_abort); @@ -144,12 +153,18 @@ class input_singletrack_impl bool decode_get_dynamic_info(file_info & p_out, double & p_timestamp_delta); //! See: input_decoder::get_dynamic_info_track(). Valid after decode_initialize(). bool decode_get_dynamic_info_track(file_info & p_out, double & p_timestamp_delta); - //! See: input_decoder::on_idle(). Valid after decode_initialize(). + //! Obsolete, do not use, do not rely on. void decode_on_idle(abort_callback & p_abort); - //! See: input_info_writer::set_info(). Note that input_info_writer::commit() call isn't forwarded because it's useless in case of non-multitrack-enabled inputs. Valid after open() with input_open_info_write reason. + //! See: input_info_writer::set_info(). Note that input_info_writer::commit() call isn't forwarded because it's useless in case of non-multitrack-enabled inputs. Valid after open() with input_open_info_write reason. \n + //! If your implementation does not support writing tags, throw exception_tagging_unsupported from open() and retag() will never be called. void retag(const file_info & p_info,abort_callback & p_abort); + //! See: input_info_writer_v2::remove_tags(). Valid after open() with input_open_info_write reason. \n + //! If possible, entirely remove tags from the file (truncate ID3/APE tags away etc); otherwise set blank metadata. \n + //! If your implementation does not support writing tags, throw exception_tagging_unsupported from open() and remove_tags() will never be called. + void remove_tags(abort_callback & p_abort); + //! See: input_entry::is_our_content_type(). static bool g_is_our_content_type(const char * p_content_type); //! See: input_entry::is_our_path(). diff --git a/3rdparty/foo_SDK/foobar2000/SDK/library_callbacks.h b/3rdparty/foo_SDK/foobar2000/SDK/library_callbacks.h index a36c32b3..da455b3b 100644 --- a/3rdparty/foo_SDK/foobar2000/SDK/library_callbacks.h +++ b/3rdparty/foo_SDK/foobar2000/SDK/library_callbacks.h @@ -1,6 +1,7 @@ #pragma once #include "library_manager.h" #include "metadb_callbacks.h" +#include "callback_merit.h" //! Callback service receiving notifications about Media Library content changes. Methods called only from main thread.\n //! Use library_callback_factory_t template to register. @@ -30,7 +31,6 @@ class NOVTABLE library_callback_v2 : public library_callback { FB2K_MAKE_SERVICE_INTERFACE(library_callback_v2, library_callback); }; - template class library_callback_factory_t : public service_factory_single_t {}; @@ -88,6 +88,7 @@ class library_callback_v2_dynamic_impl_base : public library_callback_v2_dynamic void on_items_added(metadb_handle_list_cref) override {} void on_items_removed(metadb_handle_list_cref) override {} void on_items_modified_v2(metadb_handle_list_cref, metadb_io_callback_v2_data&) override {} + void on_library_initialized() override {} PFC_CLASS_NOT_COPYABLE_EX(library_callback_v2_dynamic_impl_base); }; diff --git a/3rdparty/foo_SDK/foobar2000/SDK/library_index.h b/3rdparty/foo_SDK/foobar2000/SDK/library_index.h index 52067e99..eec04fad 100644 --- a/3rdparty/foo_SDK/foobar2000/SDK/library_index.h +++ b/3rdparty/foo_SDK/foobar2000/SDK/library_index.h @@ -2,23 +2,16 @@ #include "search_tools.h" -//! \since 2.0 -//! Provides access to indexed searches of media library content, \n -//! which in typical scenarios are much faster than running whole library content via search filters. \n -//! Not every search query is supported by library index - in particular, queries relying on title formatting cannot be optimized. \n -//! In such cases, search() will fall through to legacy search filter use. \n -//! Note that if your query looks like: cond1 AND cond2 AND cond3 (...), and only some of the conditions cannot be searched using index, \n -//! search() will use the supported subset of your query to only feed relevant subset of your library to slow search filters. +//! OBSOLETE, DO NOT USE \n +//! Please use search_index instead. class NOVTABLE library_index : public service_base { FB2K_MAKE_SERVICE_COREAPI(library_index); public: - //! Same as using search filters, provided for consistency. Use search() instead. virtual void hit_test(search_filter::ptr pattern, metadb_handle_list_cref items, bool* out, abort_callback & a) = 0; enum { flag_sort = 1 << 0, }; - //! @returns list of metadb_handles. Safe to use arr->as_list_of() to get a pfc::list_base_const_t virtual fb2k::arrayRef search(search_filter::ptr pattern, uint32_t flags, abort_callback& abort) = 0; }; \ No newline at end of file diff --git a/3rdparty/foo_SDK/foobar2000/SDK/library_manager.h b/3rdparty/foo_SDK/foobar2000/SDK/library_manager.h index ba8b93c5..b7ceb83d 100644 --- a/3rdparty/foo_SDK/foobar2000/SDK/library_manager.h +++ b/3rdparty/foo_SDK/foobar2000/SDK/library_manager.h @@ -1,4 +1,5 @@ #pragma once +#include "callback_merit.h" class library_callback_dynamic; class library_callback_v2_dynamic; @@ -106,7 +107,7 @@ class NOVTABLE library_manager_v4 : public library_manager_v3 { FB2K_MAKE_SERVICE_COREAPI_EXTENSION(library_manager_v4, library_manager_v3); }; -//! \since 2.0 beta 13 +//! \since 2.0 class NOVTABLE library_manager_v5 : public library_manager_v4 { FB2K_MAKE_SERVICE_COREAPI_EXTENSION(library_manager_v5, library_manager_v4); public: @@ -115,6 +116,15 @@ class NOVTABLE library_manager_v5 : public library_manager_v4 { //! Extensible status query method. Returns 0 for unrecognized commands. virtual size_t library_status(const GUID& arg, size_t arg1, void* arg2, size_t arg2bytes) = 0; + + bool is_current_callback_from_hook() { return library_status(status_current_callback_from_hook, 0, nullptr, 0) != 0; } +}; + +//! \since 2.0 +class NOVTABLE library_manager_v6 : public library_manager_v5 { + FB2K_MAKE_SERVICE_COREAPI_EXTENSION(library_manager_v6, library_manager_v5); +public: + virtual void set_callback_merit(library_callback_v2_dynamic*, fb2k::callback_merit_t) = 0; }; //! Implement this service to appear on "library viewers" list in Media Library preferences page.\n diff --git a/3rdparty/foo_SDK/foobar2000/SDK/main_thread_callback.cpp b/3rdparty/foo_SDK/foobar2000/SDK/main_thread_callback.cpp index 77492f88..500ccb65 100644 --- a/3rdparty/foo_SDK/foobar2000/SDK/main_thread_callback.cpp +++ b/3rdparty/foo_SDK/foobar2000/SDK/main_thread_callback.cpp @@ -42,6 +42,11 @@ void fb2k::inMainThread2( std::function f ) { void fb2k::inMainThreadSynchronous(std::function f, abort_callback & abort) { abort.check(); + + if (core_api::is_main_thread()) { + f(); return; + } + auto evt = std::make_shared(); auto f2 = [f, evt] { f(); @@ -49,4 +54,15 @@ void fb2k::inMainThreadSynchronous(std::function f, abort_callback & ab }; inMainThread(f2); abort.waitForEvent(*evt); +} + +void fb2k::inMainThreadSynchronous2(std::function f) { + // Have new API? + auto api = main_thread_callback_manager_v2::tryGet(); + if (api.is_valid()) { + api->run_synchronously( fb2k::service_new(f) ); + return; + } + + inMainThreadSynchronous(f, fb2k::noAbort); } \ No newline at end of file diff --git a/3rdparty/foo_SDK/foobar2000/SDK/main_thread_callback.h b/3rdparty/foo_SDK/foobar2000/SDK/main_thread_callback.h index a7dd95c3..a350e7c8 100644 --- a/3rdparty/foo_SDK/foobar2000/SDK/main_thread_callback.h +++ b/3rdparty/foo_SDK/foobar2000/SDK/main_thread_callback.h @@ -28,12 +28,23 @@ There is no need to use this API directly - use fb2k::inMainThread() with a lamb */ class NOVTABLE main_thread_callback_manager : public service_base { public: - //! Queues a callback object. This can be called from any thread, implementation ensures multithread safety. Implementation will call p_callback->callback_run() once later. To get it called repeatedly, you would need to add your callback again. + //! Queues a callback object. This can be called from any thread, implementation ensures multithread safety. Implementation will call p_callback->callback_run() once later. To get it called repeatedly, you would need to add your callback again. \n + //! Queued callbacks will be called in the same order as they were queued (FIFO). virtual void add_callback(service_ptr_t p_callback) = 0; FB2K_MAKE_SERVICE_COREAPI(main_thread_callback_manager); }; +//! \since 2.0 +//! Additional method added to help recovering from method-called-in-wrong-thread scenarios. +class NOVTABLE main_thread_callback_manager_v2 : public main_thread_callback_manager { + FB2K_MAKE_SERVICE_COREAPI_EXTENSION(main_thread_callback_manager_v2, main_thread_callback_manager) +public: + //! Uses win32 SendMessage() to invoke your callback synchronously, blocks until done. \n + //! If multiple threads call this, order of callbacks is undefined. \n + //! Callbacks run_synchronously() callbacks take precedence over add_callback(). + virtual void run_synchronously( main_thread_callback::ptr ) = 0; +}; // ====================================================================================================== // Obsolete helpers - they still work, but it's easier to just use fb2k::inMainThread(). @@ -52,125 +63,4 @@ template static void mai main_thread_callback_add(new service_impl_t(p1, p2)); } -// Proxy class - friend this to allow callInMainThread to access your private methods -class callInMainThread { -public: - template - static void callThis(host_t * host, param_t & param) { - host->inMainThread(param); - } - template - static void callThis( host_t * host ) { - host->inMainThread(); - } -}; - -// Internal class, do not use. -template -class _callInMainThreadSvc_t : public main_thread_callback { -public: - _callInMainThreadSvc_t(service_t * host, param_t const & param) : m_host(host), m_param(param) {} - void callback_run() { - callInMainThread::callThis(m_host.get_ptr(), m_param); - } -private: - service_ptr_t m_host; - param_t m_param; -}; - - -// Main thread callback helper. You can use this to easily invoke inMainThread(someparam) on your class without writing any wrapper code. -// Requires myservice_t to be a fb2k service class with reference counting. -template -static void callInMainThreadSvc(myservice_t * host, param_t const & param) { - typedef _callInMainThreadSvc_t impl_t; - service_ptr_t obj = new service_impl_t(host, param); - main_thread_callback_manager::get()->add_callback( obj ); -} - - - - -//! Helper class to call methods of your class (host class) in main thread with convenience. \n -//! Deals with the otherwise ugly scenario of your class becoming invalid while a method is queued. \n -//! Have this as a member of your class, then use m_mthelper.add( this, somearg ) ; to defer a call to this->inMainThread(somearg). \n -//! If your class becomes invalid before inMainThread is executed, the pending callback is discarded. \n -//! You can optionally call shutdown() to invalidate all pending callbacks early (in a destructor of your class - without waiting for callInMainThreadHelper destructor to do the job. \n -//! In order to let callInMainThreadHelper access your private methods, declare friend class callInMainThread. \n -//! Note that callInMainThreadHelper is expected to be created and destroyed in main thread. -class callInMainThreadHelper { -public: - - typedef std::function< void () > func_t; - - typedef pfc::rcptr_t< bool > killswitch_t; - - class entryFunc : public main_thread_callback { - public: - entryFunc( func_t const & func, killswitch_t ks ) : m_ks(ks), m_func(func) {} - - void callback_run() { - if (!*m_ks) m_func(); - } - - private: - killswitch_t m_ks; - func_t m_func; - }; - - template - class entry : public main_thread_callback { - public: - entry( host_t * host, arg_t const & arg, killswitch_t ks ) : m_ks(ks), m_host(host), m_arg(arg) {} - void callback_run() { - if (!*m_ks) callInMainThread::callThis( m_host, m_arg ); - } - private: - killswitch_t m_ks; - host_t * m_host; - arg_t m_arg; - }; - template - class entryVoid : public main_thread_callback { - public: - entryVoid( host_t * host, killswitch_t ks ) : m_ks(ks), m_host(host) {} - void callback_run() { - if (!*m_ks) callInMainThread::callThis( m_host ); - } - private: - killswitch_t m_ks; - host_t * m_host; - }; - - void add(func_t f) { - add_( new service_impl_t< entryFunc > ( f, m_ks ) ); - } - - template - void add( host_t * host, arg_t const & arg) { - add_( new service_impl_t< entry >( host, arg, m_ks ) ); - } - template - void add( host_t * host ) { - add_( new service_impl_t< entryVoid >( host, m_ks ) ); - } - void add_( main_thread_callback::ptr cb ) { - main_thread_callback_add( cb ); - } - - callInMainThreadHelper() { - m_ks.new_t(); - * m_ks = false; - } - void shutdown() { - PFC_ASSERT( core_api::is_main_thread() ); - * m_ks = true; - } - ~callInMainThreadHelper() { - shutdown(); - } - -private: - killswitch_t m_ks; - -}; +// More legacy helper code moved to helpers/callInMainThreadHelper.h \ No newline at end of file diff --git a/3rdparty/foo_SDK/foobar2000/SDK/menu.h b/3rdparty/foo_SDK/foobar2000/SDK/menu.h index d9fa4942..66a33c7c 100644 --- a/3rdparty/foo_SDK/foobar2000/SDK/menu.h +++ b/3rdparty/foo_SDK/foobar2000/SDK/menu.h @@ -143,19 +143,22 @@ class mainmenu_group_popup_impl : public mainmenu_group_popup { GUID m_guid,m_parent; t_uint32 m_priority; pfc::string8 m_name; }; -typedef service_factory_single_t __mainmenu_group_factory; -typedef service_factory_single_t __mainmenu_group_popup_factory; +typedef service_factory_single_t _mainmenu_group_factory; +typedef service_factory_single_t _mainmenu_group_popup_factory; -class mainmenu_group_factory : public __mainmenu_group_factory { +class mainmenu_group_factory : public _mainmenu_group_factory { public: - mainmenu_group_factory(const GUID & p_guid,const GUID & p_parent,t_uint32 p_priority) : __mainmenu_group_factory(p_guid,p_parent,p_priority) {} + mainmenu_group_factory(const GUID & p_guid,const GUID & p_parent,t_uint32 p_priority) : _mainmenu_group_factory(p_guid,p_parent,p_priority) {} }; -class mainmenu_group_popup_factory : public __mainmenu_group_popup_factory { +class mainmenu_group_popup_factory : public _mainmenu_group_popup_factory { public: - mainmenu_group_popup_factory(const GUID & p_guid,const GUID & p_parent,t_uint32 p_priority,const char * p_name) : __mainmenu_group_popup_factory(p_guid,p_parent,p_priority,p_name) {} + mainmenu_group_popup_factory(const GUID & p_guid,const GUID & p_parent,t_uint32 p_priority,const char * p_name) : _mainmenu_group_popup_factory(p_guid,p_parent,p_priority,p_name) {} }; +#define FB2K_DECLARE_MAINMENU_GROUP( guid, parent, priority, name ) FB2K_SERVICE_FACTORY_PARAMS(mainmenu_group_impl, guid, parent, priority, name ); +#define FB2K_DECLARE_MAINMENU_GROUP_POPUP( guid, parent, priority, name ) FB2K_SERVICE_FACTORY_PARAMS(mainmenu_group_popup_impl, guid, parent, priority, name ); + template class mainmenu_commands_factory_t : public service_factory_single_t {}; diff --git a/3rdparty/foo_SDK/foobar2000/SDK/menu_helpers.h b/3rdparty/foo_SDK/foobar2000/SDK/menu_helpers.h index d944bbc7..ac3c7ba4 100644 --- a/3rdparty/foo_SDK/foobar2000/SDK/menu_helpers.h +++ b/3rdparty/foo_SDK/foobar2000/SDK/menu_helpers.h @@ -108,7 +108,8 @@ class standard_commands guid_seek_back_1s, guid_seek_back_5s, guid_seek_back_10s, guid_seek_back_30s, guid_seek_back_1min, guid_seek_back_2min, guid_seek_back_5min, guid_seek_back_10min, - guid_library_configure, guid_library_rescan + guid_library_configure, guid_library_rescan, + guid_internet_radio ; static bool run_main(const GUID & guid); diff --git a/3rdparty/foo_SDK/foobar2000/SDK/message_loop.h b/3rdparty/foo_SDK/foobar2000/SDK/message_loop.h index d6756fd0..04048ab7 100644 --- a/3rdparty/foo_SDK/foobar2000/SDK/message_loop.h +++ b/3rdparty/foo_SDK/foobar2000/SDK/message_loop.h @@ -1,17 +1,26 @@ #pragma once #ifdef _WIN32 -class NOVTABLE message_filter -{ +//! A message filter class. Allows you to filter incoming messages in main app loop. Use message_loop API to register/unregister, \n +//! or derive from message_filter_impl_base to have your class registered/deregistered automatically with lifetime. +//! //! Use with caution. Will not be executed during modal loops. +class NOVTABLE message_filter { public: + //! Notifies you about incoming message. \n + //! You can alter the message (not generally recommended), let others handle it (return false) \n + //! or signal that you've handled it (return true) to suppress further processing. virtual bool pretranslate_message(MSG * p_msg) = 0; }; +//! An idle handler class. Executed when main loop is about to enter idle state. \n +//! Use with caution. Will not be executed during modal loops. class NOVTABLE idle_handler { public: virtual bool on_idle() = 0; }; +//! Entrypoint API for registering message_filter and idle_handler objects. \n +//! Usage: message_loop::get()->add_message_filter(myfilter); class NOVTABLE message_loop : public service_base { public: @@ -33,35 +42,23 @@ class NOVTABLE message_loop_v2 : public message_loop { class message_filter_impl_base : public message_filter { public: - message_filter_impl_base() {message_loop::get()->add_message_filter(this);} - message_filter_impl_base(t_uint32 lowest, t_uint32 highest) { - message_loop_v2::get()->add_message_filter_ex(this, lowest, highest); - } - ~message_filter_impl_base() {message_loop::get()->remove_message_filter(this);} - bool pretranslate_message(MSG * p_msg) {return false;} + message_filter_impl_base(); + message_filter_impl_base(t_uint32 lowest, t_uint32 highest); + ~message_filter_impl_base(); + + bool pretranslate_message(MSG * p_msg) override {return false;} PFC_CLASS_NOT_COPYABLE(message_filter_impl_base,message_filter_impl_base); }; class message_filter_impl_accel : public message_filter_impl_base { protected: - bool pretranslate_message(MSG * p_msg) { - if (m_wnd != NULL) { - if (GetActiveWindow() == m_wnd) { - if (TranslateAccelerator(m_wnd,m_accel.get(),p_msg) != 0) { - return true; - } - } - } - return false; - } + bool pretranslate_message(MSG * p_msg) override; public: - message_filter_impl_accel(HINSTANCE p_instance,const TCHAR * p_accel) : m_wnd(NULL) { - m_accel.load(p_instance,p_accel); - } + message_filter_impl_accel(HINSTANCE p_instance,const TCHAR * p_accel); void set_wnd(HWND p_wnd) {m_wnd = p_wnd;} private: - HWND m_wnd; + HWND m_wnd = NULL; win32_accelerator m_accel; PFC_CLASS_NOT_COPYABLE(message_filter_impl_accel,message_filter_impl_accel); @@ -69,19 +66,13 @@ class message_filter_impl_accel : public message_filter_impl_base { class message_filter_remap_f1 : public message_filter_impl_base { public: - bool pretranslate_message(MSG * p_msg) { - if (IsOurMsg(p_msg) && m_wnd != NULL && GetActiveWindow() == m_wnd) { - ::PostMessage(m_wnd, WM_SYSCOMMAND, SC_CONTEXTHELP, -1); - return true; - } - return false; - } + bool pretranslate_message(MSG * p_msg) override; void set_wnd(HWND wnd) {m_wnd = wnd;} private: static bool IsOurMsg(const MSG * msg) { return msg->message == WM_KEYDOWN && msg->wParam == VK_F1; } - HWND m_wnd; + HWND m_wnd = NULL; }; class idle_handler_impl_base : public idle_handler { diff --git a/3rdparty/foo_SDK/foobar2000/SDK/metadb.cpp b/3rdparty/foo_SDK/foobar2000/SDK/metadb.cpp index bea4b5e6..fce8cd48 100644 --- a/3rdparty/foo_SDK/foobar2000/SDK/metadb.cpp +++ b/3rdparty/foo_SDK/foobar2000/SDK/metadb.cpp @@ -80,6 +80,7 @@ void metadb_io_v2::update_info_async_simple(const pfc::list_base_const_ton_files_rechaptered(local); @@ -115,23 +117,34 @@ metadb_hint_list_v3::ptr metadb_hint_list_v3::create() { return ret; } +metadb_hint_list_v4::ptr metadb_hint_list_v4::create() { + metadb_hint_list_v4::ptr ret; + ret ^= metadb_hint_list::create(); + return ret; +} + void metadb_io_callback_dynamic::register_callback() { + PFC_ASSERT(core_api::is_main_thread()); metadb_io_v3::get()->register_callback(this); } void metadb_io_callback_dynamic::unregister_callback() { + PFC_ASSERT(core_api::is_main_thread()); metadb_io_v3::get()->unregister_callback(this); } void metadb_io_callback_v2_dynamic::register_callback() { + PFC_ASSERT(core_api::is_main_thread()); metadb_io_v5::get()->register_callback_v2(this); } void metadb_io_callback_v2_dynamic::unregister_callback() { + PFC_ASSERT(core_api::is_main_thread()); metadb_io_v5::get()->unregister_callback_v2(this); } bool metadb_io_callback_v2_dynamic::try_register_callback() { + PFC_ASSERT(core_api::is_main_thread()); auto api = metadb_io_v5::tryGet(); if (api.is_empty()) return false; api->register_callback_v2(this); @@ -139,6 +152,23 @@ bool metadb_io_callback_v2_dynamic::try_register_callback() { } void metadb_io_callback_v2_dynamic::try_unregister_callback() { + PFC_ASSERT(core_api::is_main_thread()); auto api = metadb_io_v5::tryGet(); if (api.is_valid()) api->unregister_callback_v2(this); } + +metadb_io_callback_dynamic_impl_base::metadb_io_callback_dynamic_impl_base() { + register_callback(); +} + +metadb_io_callback_dynamic_impl_base::~metadb_io_callback_dynamic_impl_base() { + unregister_callback(); +} + +metadb_io_callback_v2_dynamic_impl_base::metadb_io_callback_v2_dynamic_impl_base() { + register_callback(); +} + +metadb_io_callback_v2_dynamic_impl_base::~metadb_io_callback_v2_dynamic_impl_base() { + unregister_callback(); +} diff --git a/3rdparty/foo_SDK/foobar2000/SDK/metadb.h b/3rdparty/foo_SDK/foobar2000/SDK/metadb.h index 5d5f5d4e..a0fd52c6 100644 --- a/3rdparty/foo_SDK/foobar2000/SDK/metadb.h +++ b/3rdparty/foo_SDK/foobar2000/SDK/metadb.h @@ -141,6 +141,18 @@ class NOVTABLE metadb_hint_list_v3 : public metadb_hint_list_v2 { virtual void add_hint_forced_reader(const char * p_path,service_ptr_t const & p_reader,abort_callback & p_abort) = 0; }; +//! \since 2.0 +//! Allows dispatching of metadb_io_edit_callback from your code. +class NOVTABLE metadb_hint_list_v4 : public metadb_hint_list_v3 { + FB2K_MAKE_SERVICE_INTERFACE( metadb_hint_list_v4, metadb_hint_list_v3 ); +public: + static metadb_hint_list_v4::ptr create(); + + virtual void before_edit( const char * path, service_ptr_t reader, abort_callback & a ) = 0; + virtual void after_edit( const char * path, service_ptr_t reader, abort_callback & a ) = 0; + +}; + //! New in 0.9.3. Extends metadb_io functionality with nonblocking versions of tag read/write functions, and some other utility features. class NOVTABLE metadb_io_v2 : public metadb_io { @@ -168,23 +180,27 @@ class NOVTABLE metadb_io_v2 : public metadb_io { op_flag_detect_rechapter = 1 << 5, }; - //! Preloads information from the specified tracks. + //! Preloads information from the specified tracks. \n + //! Use from main thread only (starts a threaded_process to show a progress dialog). //! @param p_list List of items to process. //! @param p_op_flags Can be null, or one or more of op_flag_* enum values combined, altering behaviors of the operation. //! @param p_notify Called when the task is completed. Status code is one of t_load_info_state values. Can be null if caller doesn't care. virtual void load_info_async(metadb_handle_list_cref p_list,t_load_info_type p_type,fb2k::hwnd_t p_parent_window,t_uint32 p_op_flags,completion_notify_ptr p_notify) = 0; - //! Updates tags of the specified tracks. + //! Updates tags of the specified tracks. \n + //! Use from main thread only (starts a threaded_process to show a progress dialog). //! @param p_list List of items to process. //! @param p_op_flags Can be null, or one or more of op_flag_* enum values combined, altering behaviors of the operation. //! @param p_notify Called when the task is completed. Status code is one of t_update_info values. Can be null if caller doesn't care. //! @param p_filter Callback handling actual file_info alterations. Typically used to replace entire meta part of file_info, or to alter something else such as ReplayGain while leaving meta intact. virtual void update_info_async(metadb_handle_list_cref p_list,service_ptr_t p_filter,fb2k::hwnd_t p_parent_window,t_uint32 p_op_flags,completion_notify_ptr p_notify) = 0; - //! Rewrites tags of the specified tracks; similar to update_info_async() but using last known/cached file_info values rather than values passed by caller. + //! Rewrites tags of the specified tracks; similar to update_info_async() but using last known/cached file_info values rather than values passed by caller. \n + //! Use from main thread only (starts a threaded_process to show a progress dialog). //! @param p_list List of items to process. //! @param p_op_flags Can be null, or one or more of op_flag_* enum values combined, altering behaviors of the operation. //! @param p_notify Called when the task is completed. Status code is one of t_update_info values. Can be null if caller doesn't care. virtual void rewrite_info_async(metadb_handle_list_cref p_list,fb2k::hwnd_t p_parent_window,t_uint32 p_op_flags,completion_notify_ptr p_notify) = 0; - //! Strips all tags / metadata fields from the specified tracks. + //! Strips all tags / metadata fields from the specified tracks. \n + //! Use from main thread only (starts a threaded_process to show a progress dialog). //! @param p_list List of items to process. //! @param p_op_flags Can be null, or one or more of op_flag_* enum values combined, altering behaviors of the operation. //! @param p_notify Called when the task is completed. Status code is one of t_update_info values. Can be null if caller doesn't care. @@ -194,7 +210,8 @@ class NOVTABLE metadb_io_v2 : public metadb_io { //! Contrary to other metadb_io methods, this can be safely called in a worker thread. You only need to call the hint list's on_done() method in main thread to finalize. virtual metadb_hint_list::ptr create_hint_list() = 0; - //! Updates tags of the specified tracks. Helper; uses update_info_async internally. + //! Updates tags of the specified tracks. Helper; uses update_info_async internally. \n + //! Use from main thread only (starts a threaded_process to show a progress dialog). //! @param p_list List of items to process. //! @param p_op_flags Can be null, or one or more of op_flag_* enum values combined, altering behaviors of the operation. //! @param p_notify Called when the task is completed. Status code is one of t_update_info values. Can be null if caller doesn't care. @@ -202,10 +219,12 @@ class NOVTABLE metadb_io_v2 : public metadb_io { void update_info_async_simple(metadb_handle_list_cref p_list,const pfc::list_base_const_t & p_new_info, fb2k::hwnd_t p_parent_window,t_uint32 p_op_flags,completion_notify_ptr p_notify); //! Helper to be called after a file has been rechaptered. \n - //! Forcibly reloads info then tells playlist_manager to update all affected playlists. + //! Forcibly reloads info then tells playlist_manager to update all affected playlists. \n + //! Call from main thread only. void on_file_rechaptered( const char * path, metadb_handle_list_cref newItems ); //! Helper to be called after a file has been rechaptered. \n - //! Forcibly reloads info then tells playlist_manager to update all affected playlists. + //! Forcibly reloads info then tells playlist_manager to update all affected playlists. \n + //! Call from main thread only. void on_files_rechaptered( metadb_handle_list_cref newHandles ); FB2K_MAKE_SERVICE_COREAPI_EXTENSION(metadb_io_v2,metadb_io); @@ -215,7 +234,13 @@ class NOVTABLE metadb_io_v2 : public metadb_io { //! \since 0.9.5 class NOVTABLE metadb_io_v3 : public metadb_io_v2 { public: + //! Registers a callback object to receive notifications about metadb_io operations. \n + //! See: metadb_io_callback_dynamic \n + //! Call from main thread only. virtual void register_callback(metadb_io_callback_dynamic * p_callback) = 0; + //! Unregisters a callback object to receive notifications about metadb_io operations. \n + //! See: metadb_io_callback_dynamic \n + //! Call from main thread only. virtual void unregister_callback(metadb_io_callback_dynamic * p_callback) = 0; FB2K_MAKE_SERVICE_COREAPI_EXTENSION(metadb_io_v3,metadb_io_v2); @@ -230,15 +255,18 @@ class NOVTABLE metadb_io_v4 : public metadb_io_v3 { public: //! Creates an update-info task, that can be either fed to threaded_process API, or invoked by yourself respecting threaded_process semantics. \n //! May return null pointer if the operation has been refused (by user settings or such). \n - //! Useful for performing the operation with your own in-dialog progress display instead of the generic progress popup. + //! Useful for performing the operation with your own in-dialog progress display instead of the generic progress popup. \n + //! Main thread only. virtual service_ptr_t spawn_update_info( metadb_handle_list_cref items, service_ptr_t p_filter, uint32_t opFlags, completion_notify_ptr reply ) = 0; //! Creates an remove-info task, that can be either fed to threaded_process API, or invoked by yourself respecting threaded_process semantics. \n //! May return null pointer if the operation has been refused (by user settings or such). \n - //! Useful for performing the operation with your own in-dialog progress display instead of the generic progress popup. + //! Useful for performing the operation with your own in-dialog progress display instead of the generic progress popup. \n + //! Main thread only. virtual service_ptr_t spawn_remove_info( metadb_handle_list_cref items, uint32_t opFlags, completion_notify_ptr reply) = 0; //! Creates an load-info task, that can be either fed to threaded_process API, or invoked by yourself respecting threaded_process semantics. \n //! May return null pointer if the operation has been refused (for an example no loading is needed for these items). \n - //! Useful for performing the operation with your own in-dialog progress display instead of the generic progress popup. + //! Useful for performing the operation with your own in-dialog progress display instead of the generic progress popup. \n + //! Main thread only. virtual service_ptr_t spawn_load_info( metadb_handle_list_cref items, t_load_info_type opType, uint32_t opFlags, completion_notify_ptr reply) = 0; }; @@ -246,7 +274,11 @@ class NOVTABLE metadb_io_v4 : public metadb_io_v3 { class NOVTABLE metadb_io_v5 : public metadb_io_v4 { FB2K_MAKE_SERVICE_COREAPI_EXTENSION(metadb_io_v5, metadb_io_v4); public: + //! Register a metadb_io_callback_v2_dynamic object to receive notifications about metadb_io events. \n + //! Main thread only. virtual void register_callback_v2(metadb_io_callback_v2_dynamic*) = 0; + //! Unregister a metadb_io_callback_v2_dynamic object. \n + //! Main thread only. virtual void unregister_callback_v2(metadb_io_callback_v2_dynamic*) = 0; }; diff --git a/3rdparty/foo_SDK/foobar2000/SDK/metadb_callbacks.h b/3rdparty/foo_SDK/foobar2000/SDK/metadb_callbacks.h index d14024cf..c184961d 100644 --- a/3rdparty/foo_SDK/foobar2000/SDK/metadb_callbacks.h +++ b/3rdparty/foo_SDK/foobar2000/SDK/metadb_callbacks.h @@ -1,9 +1,11 @@ #pragma once +#include "callback_merit.h" //! Callback service receiving notifications about metadb contents changes. class NOVTABLE metadb_io_callback : public service_base { public: - //! Called when metadb contents change. (Or, one of display hook component requests display update). + //! Called when metadb contents change. (Or, one of display hook component requests display update). \n + //! Main thread only. //! @param p_items_sorted List of items that have been updated. The list is always sorted by pointer value, to allow fast bsearch to test whether specific item has changed. //! @param p_fromhook Set to true when actual file contents haven't changed but one of metadb_display_field_provider implementations requested an update so output of metadb_handle::format_title() etc has changed. virtual void on_changed_sorted(metadb_handle_list_cref p_items_sorted, bool p_fromhook) = 0; @@ -14,6 +16,7 @@ class NOVTABLE metadb_io_callback : public service_base { //! Dynamically-registered version of metadb_io_callback. See metadb_io_callback for documentation, register instances using metadb_io_v3::register_callback(). It's recommended that you use the metadb_io_callback_dynamic_impl_base helper class to manage registration/unregistration. class NOVTABLE metadb_io_callback_dynamic { public: + //! See metadb_io_callback::on_changed_sorted() virtual void on_changed_sorted(metadb_handle_list_cref p_items_sorted, bool p_fromhook) = 0; void register_callback(); void unregister_callback(); @@ -25,8 +28,8 @@ class metadb_io_callback_dynamic_impl_base : public metadb_io_callback_dynamic { public: void on_changed_sorted(metadb_handle_list_cref p_items_sorted, bool p_fromhook) override {} - metadb_io_callback_dynamic_impl_base() { register_callback(); } - ~metadb_io_callback_dynamic_impl_base() { unregister_callback(); } + metadb_io_callback_dynamic_impl_base(); + ~metadb_io_callback_dynamic_impl_base(); PFC_CLASS_NOT_COPYABLE_EX(metadb_io_callback_dynamic_impl_base) }; @@ -42,6 +45,15 @@ class NOVTABLE metadb_io_edit_callback : public service_base { virtual void on_edited(metadb_handle_list_cref items, t_infosref before, t_infosref after) = 0; }; +//! \since 2.0 +class NOVTABLE metadb_io_edit_callback_v2 : public metadb_io_edit_callback { + FB2K_MAKE_SERVICE_INTERFACE(metadb_io_edit_callback_v2, metadb_io_edit_callback) +public: + //! With original on_edited(), the implementation could not tell what the info in metadb was before, 'before' parameter being actual infos freshly read from the file prior to writing. \n + //! on_edited_v2() clarifies this, additional argument passes old metadb state to deal with cases where it was different than file contents. + virtual void on_edited_v2(metadb_handle_list_cref items, t_infosref before, t_infosref after, t_infosref beforeInMetadb) = 0; +}; + //! \since 2.0 //! Parameter for on_changed_sorted_v2() class NOVTABLE metadb_io_callback_v2_data { @@ -51,20 +63,32 @@ class NOVTABLE metadb_io_callback_v2_data { }; //! \since 2.0 +//! Extended version of metadb_io_callback. class NOVTABLE metadb_io_callback_v2 : public metadb_io_callback { FB2K_MAKE_SERVICE_INTERFACE(metadb_io_callback_v2, metadb_io_callback); public: virtual void on_changed_sorted_v2(metadb_handle_list_cref itemsSorted, metadb_io_callback_v2_data & data, bool bFromHook) = 0; - //! Reserved for future use. - virtual double get_callback_merit() { return 0; } + //! Controls callback merit, see: fb2k::callback_merit_t + virtual fb2k::callback_merit_t get_callback_merit() { return fb2k::callback_merit_default; } }; +//! \since 2.0 +//! NEW interface introduced in late 2.0. \n +//! Invoked *BEFORE* actual update, with incoming info. \n +//! Note that incoming info may be partial (either main info or browse info not set), in such cases the info will remain unchanged. +class NOVTABLE metadb_pre_update_callback : public service_base { + FB2K_MAKE_SERVICE_INTERFACE_ENTRYPOINT( metadb_pre_update_callback ); +public: + virtual void will_update( metadb_handle_list_cref itemsSorted, metadb_io_callback_v2_data & data) = 0; +}; +//! \since 2.0 +//! Extended version of metadb_io_callback_dynamic. class NOVTABLE metadb_io_callback_v2_dynamic { public: virtual void on_changed_sorted_v2(metadb_handle_list_cref itemsSorted, metadb_io_callback_v2_data & data, bool bFromHook) = 0; - //! Reserved for future use. - virtual double get_callback_merit() { return 0; } + //! Controls callback merit, see: fb2k::callback_merit_t + virtual fb2k::callback_merit_t get_callback_merit() { return fb2k::callback_merit_default; } bool try_register_callback(); void try_unregister_callback(); void register_callback(); void unregister_callback(); @@ -74,8 +98,8 @@ class metadb_io_callback_v2_dynamic_impl_base : public metadb_io_callback_v2_dyn public: void on_changed_sorted_v2(metadb_handle_list_cref itemsSorted, metadb_io_callback_v2_data & data, bool bFromHook) override {} - metadb_io_callback_v2_dynamic_impl_base() { register_callback(); } - ~metadb_io_callback_v2_dynamic_impl_base() { unregister_callback(); } + metadb_io_callback_v2_dynamic_impl_base(); + ~metadb_io_callback_v2_dynamic_impl_base(); PFC_CLASS_NOT_COPYABLE_EX(metadb_io_callback_v2_dynamic_impl_base) }; diff --git a/3rdparty/foo_SDK/foobar2000/SDK/metadb_handle.h b/3rdparty/foo_SDK/foobar2000/SDK/metadb_handle.h index 45f35d8f..af11b762 100644 --- a/3rdparty/foo_SDK/foobar2000/SDK/metadb_handle.h +++ b/3rdparty/foo_SDK/foobar2000/SDK/metadb_handle.h @@ -185,6 +185,9 @@ class metadb_handle_v2 : public metadb_handle { virtual void formatTitle_v2(const rec_t& rec, titleformat_hook* p_hook, pfc::string_base& p_out, const service_ptr_t& p_script, titleformat_text_filter* p_filter) = 0; }; +typedef pfc::list_base_t* metadb_handle_list_ptr; +typedef pfc::list_base_const_t const * metadb_handle_list_cptr; + typedef pfc::list_base_t & metadb_handle_list_ref; typedef pfc::list_base_const_t const & metadb_handle_list_cref; @@ -221,6 +224,16 @@ namespace metadb_handle_list_helper { void sort_by_format_get_order_v2( metadb_handle_list_cref p_list, size_t * order, const service_ptr_t & script, titleformat_hook * hook, int direction, abort_callback & aborter ); void sort_by_format_v2(metadb_handle_list_ref p_list, const service_ptr_t & script, titleformat_hook * hook, int direction, abort_callback & aborter); + struct sorter_t { + service_ptr_t < titleformat_object > obj; + int direction = 1; + titleformat_hook* hook = nullptr; + }; + + //! Late-2023 addition (new fb2k not required) \n + //! Multilayer stablesort using single info query pass, with multiple sort objects that can have different directions. + //! @param inOutOrder input & output order, please set to a valid permutration (such as identity) on input. + void sort_by_format_get_order_v3(metadb_handle_list_cref p_list, size_t* inOutOrder, sorter_t const * sorters, size_t nSorters, abort_callback& aborter); }; template class t_alloc = pfc::alloc_fast > diff --git a/3rdparty/foo_SDK/foobar2000/SDK/metadb_handle_list.cpp b/3rdparty/foo_SDK/foobar2000/SDK/metadb_handle_list.cpp index c9c6c8e6..802b20f0 100644 --- a/3rdparty/foo_SDK/foobar2000/SDK/metadb_handle_list.cpp +++ b/3rdparty/foo_SDK/foobar2000/SDK/metadb_handle_list.cpp @@ -9,24 +9,35 @@ namespace { + struct custom_sort_data_multi { + static constexpr unsigned numLocal = 4; + void setup(size_t count) { + if (count > numLocal) texts2 = std::make_unique< fb2k::sortString_t[] >( count - numLocal ); + } + fb2k::sortString_t& operator[] (size_t which) { + return which < numLocal ? texts1[which] : texts2[which - numLocal]; + } + const fb2k::sortString_t& operator[] (size_t which) const { + return which < numLocal ? texts1[which] : texts2[which - numLocal]; + } + + fb2k::sortString_t texts1[numLocal]; + std::unique_ptr< fb2k::sortString_t[] > texts2; + size_t index; + }; struct custom_sort_data { fb2k::sortString_t text; - t_size index; + size_t index; }; -} + template + static int custom_sort_compare(const custom_sort_data& elem1, const custom_sort_data& elem2) { + int ret = direction * fb2k::sortStringCompare(elem1.text, elem2.text); + if (ret == 0) ret = pfc::sgn_t((t_ssize)elem1.index - (t_ssize)elem2.index); + return ret; + } -template -static int custom_sort_compare(const custom_sort_data & elem1, const custom_sort_data & elem2 ) { - int ret = direction * fb2k::sortStringCompare(elem1.text,elem2.text); - if (ret == 0) ret = pfc::sgn_t((t_ssize)elem1.index - (t_ssize)elem2.index); - return ret; } - -template -static int _custom_sort_compare(const void * v1, const void * v2) { - return custom_sort_compare(*reinterpret_cast(v1),*reinterpret_cast(v2)); -} void metadb_handle_list_helper::sort_by_format(metadb_handle_list_ref p_list,const char * spec,titleformat_hook * p_hook) { service_ptr_t script; @@ -319,14 +330,34 @@ void metadb_handle_list_helper::sort_by_format_v2(metadb_handle_list_ref p_list, } void metadb_handle_list_helper::sort_by_format_get_order_v2(metadb_handle_list_cref p_list, size_t * order, const service_ptr_t & p_script, titleformat_hook * p_hook, int p_direction, abort_callback & aborter) { + sorter_t s = { p_script, p_direction, p_hook }; + size_t total = p_list.get_count(); + for (size_t walk = 0; walk < total; ++walk) order[walk] = walk; + sort_by_format_get_order_v3(p_list, order, &s, 1, aborter); +} + +void metadb_handle_list_helper::sort_by_format_get_order_v3(metadb_handle_list_cref p_list, size_t* order,sorter_t const* sorters, size_t nSorters, abort_callback& aborter) { // pfc::hires_timer timer; timer.start(); + typedef custom_sort_data_multi data_t; + const t_size count = p_list.get_count(); if (count == 0) return; - auto data = std::make_unique< custom_sort_data[] >(count); + + PFC_ASSERT(pfc::permutation_is_valid(order, count)); + + auto data = std::make_unique< data_t[] >(count); #if FOOBAR2000_TARGET_VERSION >= 81 - if ( p_script->requires_metadb_info_()) { + bool need_info = false; + for (size_t iSorter = 0; iSorter < nSorters; ++iSorter) { + auto& s = sorters[iSorter]; + PFC_ASSERT(s.direction == -1 || s.direction == 1); + if (s.obj->requires_metadb_info_()) { + need_info = true; break; + } + } + if (need_info) { // FB2K_console_formatter() << "sorting with queryMultiParallelEx_<>"; struct qmpc_context { qmpc_context() { @@ -337,14 +368,22 @@ void metadb_handle_list_helper::sort_by_format_get_order_v2(metadb_handle_list_c }; metadb_v2::get()->queryMultiParallelEx_< qmpc_context >(p_list, [&](size_t idx, metadb_v2::rec_t const& rec, qmpc_context& ctx) { aborter.check(); - if (p_hook) { - titleformat_hook_impl_splitter hookSplitter(&ctx.myHook, p_hook); - p_list[idx]->formatTitle_v2_(rec, &hookSplitter, ctx.temp, p_script, nullptr); - } else { - p_list[idx]->formatTitle_v2_(rec, &ctx.myHook, ctx.temp, p_script, nullptr); + auto& out = data[idx]; + out.setup(nSorters); + out.index = order[idx]; + + auto h = p_list[idx]; + + for (size_t iSorter = 0; iSorter < nSorters; ++iSorter) { + auto& s = sorters[iSorter]; + if (s.hook) { + titleformat_hook_impl_splitter hookSplitter(&ctx.myHook, s.hook); + h->formatTitle_v2_(rec, &hookSplitter, ctx.temp, s.obj, nullptr); + } else { + h->formatTitle_v2_(rec, &ctx.myHook, ctx.temp, s.obj, nullptr); + } + out[iSorter] = fb2k::makeSortString(ctx.temp); } - data[idx].index = idx; - data[idx].text = fb2k::makeSortString(ctx.temp); }); } else { // FB2K_console_formatter() << "sorting with blank metadb info"; @@ -358,18 +397,25 @@ void metadb_handle_list_helper::sort_by_format_get_order_v2(metadb_handle_list_c aborter.check(); size_t idx = walk++; if (idx >= count) return; - - if (p_hook) { - titleformat_hook_impl_splitter hookSplitter(&myHook, p_hook); - p_list[idx]->formatTitle_v2_(rec, &hookSplitter, temp, p_script, nullptr); - } else { - p_list[idx]->formatTitle_v2_(rec, &myHook, temp, p_script, nullptr); + + auto& out = data[idx]; + out.setup(nSorters); + out.index = order[idx]; + + for (size_t iSorter = 0; iSorter < nSorters; ++iSorter) { + auto& s = sorters[iSorter]; + if (s.hook) { + titleformat_hook_impl_splitter hookSplitter(&myHook, s.hook); + p_list[idx]->formatTitle_v2_(rec, &hookSplitter, temp, s.obj, nullptr); + } else { + p_list[idx]->formatTitle_v2_(rec, &myHook, temp, s.obj, nullptr); + } + + out[iSorter] = fb2k::makeSortString(temp); } - data[idx].index = idx; - data[idx].text = fb2k::makeSortString(temp); } - }, api->numRunsSanity( (count + 1999)/2000 ) ); - + }, api->numRunsSanity((count + 1999) / 2000)); + } #else { @@ -377,17 +423,27 @@ void metadb_handle_list_helper::sort_by_format_get_order_v2(metadb_handle_list_c auto work = [&] { tfhook_sort myHook; - titleformat_hook_impl_splitter hookSplitter(&myHook, p_hook); - titleformat_hook * const hookPtr = p_hook ? pfc::implicit_cast(&hookSplitter) : &myHook; pfc::string8_fastalloc temp; temp.prealloc(512); - const t_size total = p_list.get_size(); - for ( ;; ) { + for (;; ) { const t_size index = (counter)++; - if (index >= total || aborter.is_set()) break; - data[index].index = index; - p_list[index]->format_title(hookPtr, temp, p_script, 0); - data[index].text = fb2k::makeSortString(temp); + if (index >= count || aborter.is_set()) break; + + auto& out = data[index]; + out.setup(nSorters); + out.index = order[index]; + + for (size_t iSorter = 0; iSorter < nSorters; ++iSorter) { + auto& s = sorters[iSorter]; + if (s.hook) { + titleformat_hook_impl_splitter hookSplitter(&myHook, s.hook); + p_list[index]->format_title(&hookSplitter, temp, s.obj, 0); + } else { + p_list[index]->format_title(&myHook, temp, s.obj, 0); + } + + out[iSorter] = fb2k::makeSortString(temp); + } } }; @@ -402,30 +458,37 @@ void metadb_handle_list_helper::sort_by_format_get_order_v2(metadb_handle_list_c aborter.check(); // console::formatter() << "metadb_handle sort: prepared in " << pfc::format_time_ex(timer.query(),6); - + { + auto compare = [&](data_t const& elem1, data_t const& elem2) -> int { + for (size_t iSorter = 0; iSorter < nSorters; ++iSorter) { + int v = fb2k::sortStringCompare(elem1[iSorter], elem2[iSorter]); + if (v) return v * sorters[iSorter].direction; + } + + return pfc::sgn_t((t_ssize)elem1.index - (t_ssize)elem2.index); + }; + typedef decltype(data) container_t; - auto compare = p_direction > 0 ? custom_sort_compare<1> : custom_sort_compare<-1>; typedef decltype(compare) compare_t; pfc::sort_callback_impl_simple_wrap_t cb(data, compare); - - //pfc::sort_t(data, p_direction > 0 ? custom_sort_compare<1> : custom_sort_compare<-1>, count); - size_t concurrency = pfc::getOptimalWorkerThreadCountEx( count / 4096 ); - fb2k::sort( cb, count, concurrency, aborter ); + size_t concurrency = pfc::getOptimalWorkerThreadCountEx(count / 4096); + fb2k::sort(cb, count, concurrency, aborter); } - + //qsort(data.get_ptr(),count,sizeof(custom_sort_data),p_direction > 0 ? _custom_sort_compare<1> : _custom_sort_compare<-1>); // console::formatter() << "metadb_handle sort: sorted in " << pfc::format_time_ex(timer.query(),6); - for (t_size n = 0; nsend_force_play(); } } size_t retCanWriteSamples = 0; @@ -98,8 +104,12 @@ size_t output_impl::update_v2() { t_size cw = can_write_samples() * m_incoming_spec.chanCount; t_size delta = pfc::min_t(m_incoming.get_size() - m_incoming_ptr,cw); if (delta > 0) { + PFC_ASSERT(!m_sent_force_play); write(audio_chunk_temp_impl(m_incoming.get_ptr()+m_incoming_ptr,delta / m_incoming_spec.chanCount,m_incoming_spec.sampleRate,m_incoming_spec.chanCount,m_incoming_spec.chanMask)); m_incoming_ptr += delta; + if ( m_eos && this->queue_empty() ) { + this->send_force_play(); + } } retCanWriteSamples = (cw - delta) / m_incoming_spec.chanCount; } else if ( m_incoming_ptr == m_incoming.get_size() ) { @@ -118,8 +128,21 @@ double output_impl::get_latency() { } return ret; } + +void output_impl::force_play() { + if ( m_eos ) return; + m_eos = true; + if (queue_empty()) send_force_play(); +} +void output_impl::send_force_play() { + if (m_sent_force_play) return; + m_sent_force_play = true; + this->on_force_play(); +} + void output_impl::process_samples(const audio_chunk & p_chunk) { - pfc::dynamic_assert(m_incoming_ptr == m_incoming.get_size()); + PFC_ASSERT(queue_empty()); + PFC_ASSERT( !m_eos ); auto spec = p_chunk.get_spec(); if (!spec.is_valid()) pfc::throw_exception_with_message< exception_io_data >("Invalid audio stream specifications"); m_incoming_spec = spec; diff --git a/3rdparty/foo_SDK/foobar2000/SDK/output.h b/3rdparty/foo_SDK/foobar2000/SDK/output.h index d7fe1b51..459edbd2 100644 --- a/3rdparty/foo_SDK/foobar2000/SDK/output.h +++ b/3rdparty/foo_SDK/foobar2000/SDK/output.h @@ -222,7 +222,7 @@ class output_factory_t : public service_factory_single_t class output_impl : public output_v5 { protected: - output_impl() : m_incoming_ptr(0) {} + output_impl() {} virtual void on_update() = 0; //! Will never get more input than as returned by can_write_samples(). virtual void write(const audio_chunk & p_data) = 0; @@ -232,22 +232,33 @@ class output_impl : public output_v5 { virtual void on_flush_changing_track() {on_flush();} virtual void open(audio_chunk::spec_t const & p_spec) = 0; - virtual void pause(bool p_state) = 0; - virtual void force_play() = 0; - virtual void volume_set(double p_val) = 0; + // base class virtual methods + // virtual void pause(bool p_state) = 0; + // virtual void volume_set(double p_val) = 0; + + //! Override this, not force_play(). \n + //! output_impl will defer call to on_force_play() until out of data in its buffer. + virtual void on_force_play() = 0; protected: void on_need_reopen() {m_active_spec.clear(); } private: - void flush(); - void flush_changing_track(); - void update(bool & p_ready); - size_t update_v2(); - double get_latency(); - void process_samples(const audio_chunk & p_chunk); + void flush() override final; + void flush_changing_track() override final; + void update(bool & p_ready) override final; + size_t update_v2() override final; + double get_latency() override final; + void process_samples(const audio_chunk & p_chunk) override final; + void force_play() override final; + void on_flush_internal(); + void send_force_play(); + + bool queue_empty() const { return m_incoming_ptr == m_incoming.get_size(); } pfc::array_t m_incoming; - t_size m_incoming_ptr; + t_size m_incoming_ptr = 0; audio_chunk::spec_t m_incoming_spec,m_active_spec; + bool m_eos = false; // EOS issued by caller / no more data expected until a flush + bool m_sent_force_play = false; // set if sent on_force_play() }; diff --git a/3rdparty/foo_SDK/foobar2000/SDK/play_callback.h b/3rdparty/foo_SDK/foobar2000/SDK/play_callback.h index 920bd7b1..8f60bbfa 100644 --- a/3rdparty/foo_SDK/foobar2000/SDK/play_callback.h +++ b/3rdparty/foo_SDK/foobar2000/SDK/play_callback.h @@ -1,4 +1,6 @@ #pragma once +#include "callback_merit.h" + /*! Class receiving notifications about playback events. Note that all methods are called only from app's main thread. Use play_callback_manager to register your dynamically created instances. Statically registered version is available too - see play_callback_static. @@ -65,6 +67,13 @@ class NOVTABLE play_callback_manager : public service_base { virtual void unregister_callback(play_callback * p_callback) = 0; }; +//! \since 2.0 +class NOVTABLE play_callback_manager_v2 : public play_callback_manager { + FB2K_MAKE_SERVICE_COREAPI_EXTENSION(play_callback_manager_v2, play_callback_manager); +public: + virtual void set_callback_merit(play_callback*, fb2k::callback_merit_t) = 0; +}; + //! Implementation helper. class play_callback_impl_base : public play_callback { public: diff --git a/3rdparty/foo_SDK/foobar2000/SDK/playback_stream_capture.h b/3rdparty/foo_SDK/foobar2000/SDK/playback_stream_capture.h index 45508110..bb147e44 100644 --- a/3rdparty/foo_SDK/foobar2000/SDK/playback_stream_capture.h +++ b/3rdparty/foo_SDK/foobar2000/SDK/playback_stream_capture.h @@ -6,7 +6,8 @@ class NOVTABLE playback_stream_capture_callback { public: //! Delivers a real-time chunk of audio data. \n //! Audio is roughly synchronized with what can currently be heard. This API is provided for utility purposes such as streaming; if you want to implement a visualisation, use the visualisation_manager API instead. \n - //! Called only from the main thread. + //! Contrary to visualisation methods, this guarantees that all played audio data is coming thru. \n + //! Called only from the main thread. \n virtual void on_chunk(const audio_chunk &) = 0; protected: playback_stream_capture_callback() {} @@ -18,8 +19,45 @@ class NOVTABLE playback_stream_capture_callback { class NOVTABLE playback_stream_capture : public service_base { FB2K_MAKE_SERVICE_COREAPI(playback_stream_capture) public: + //! Register a playback_stream_capture_callback. \n //! Possible to call only from the main thread. virtual void add_callback(playback_stream_capture_callback * ) = 0; + //! Un-register a playback_stream_capture_callback. \n //! Possible to call only from the main thread. virtual void remove_callback(playback_stream_capture_callback * ) = 0; }; + +//! \since 2.0. +//! Implemented by core. +class NOVTABLE playback_stream_capture_v2 : public playback_stream_capture { + FB2K_MAKE_SERVICE_COREAPI_EXTENSION(playback_stream_capture_v2, playback_stream_capture); +public: + //! @param requestInterval Interval, in seconds, in which the callback expects to be called. \n + //! Set to -1 to use defaults. \n + //! Note that if many callbacks are registered, they all get called at once; one callback requesting lower interval lowers the interval for all. + virtual void add_callback_v2(playback_stream_capture_callback* cb, double requestInterval = -1) = 0; +}; + +class playback_stream_capture_callback_impl : public playback_stream_capture_callback { +public: + void on_chunk(const audio_chunk&) override {} + + playback_stream_capture_callback_impl(double interval = -1) { + PFC_ASSERT(core_api::is_main_thread()); +#if FOOBAR2020 + playback_stream_capture_v2::get()->add_callback_v2(this, interval); +#else + auto api = playback_stream_capture::get(); + playback_stream_capture_v2::ptr v2; + if (v2 &= api) v2->add_callback_v2(this, interval); + else api->add_callback(this); +#endif + } + ~playback_stream_capture_callback_impl() { + PFC_ASSERT(core_api::is_main_thread()); + playback_stream_capture::get()->remove_callback(this); + } + + playback_stream_capture_callback_impl(const playback_stream_capture_callback_impl&) = delete; + void operator=(const playback_stream_capture_callback_impl&) = delete; +}; diff --git a/3rdparty/foo_SDK/foobar2000/SDK/playlist.cpp b/3rdparty/foo_SDK/foobar2000/SDK/playlist.cpp index 9ac2b345..e306c026 100644 --- a/3rdparty/foo_SDK/foobar2000/SDK/playlist.cpp +++ b/3rdparty/foo_SDK/foobar2000/SDK/playlist.cpp @@ -978,3 +978,21 @@ void playlist_manager::on_file_rechaptered(const char* path, metadb_handle_list_ // obsolete method on_files_rechaptered(newItems); } + +namespace { + class process_locations_notify_lambda : public process_locations_notify { + public: + process_locations_notify::func_t f; + void on_completion(metadb_handle_list_cref p_items) override { + PFC_ASSERT(f != nullptr); + f(p_items); + } + void on_aborted() override {} + }; +} +process_locations_notify::ptr process_locations_notify::create(func_t arg) { + PFC_ASSERT(arg != nullptr); + auto ret = fb2k::service_new< process_locations_notify_lambda >(); + ret->f = arg; + return ret; +} \ No newline at end of file diff --git a/3rdparty/foo_SDK/foobar2000/SDK/playlist.h b/3rdparty/foo_SDK/foobar2000/SDK/playlist.h index b3fb1865..13dc23d0 100644 --- a/3rdparty/foo_SDK/foobar2000/SDK/playlist.h +++ b/3rdparty/foo_SDK/foobar2000/SDK/playlist.h @@ -3,6 +3,7 @@ #include "titleformat.h" #include "playback_control.h" #include +#include "callback_merit.h" //! This interface allows filtering of playlist modification operations.\n //! Implemented by components "locking" playlists; use playlist_manager::playlist_lock_install() etc to takeover specific playlist with your instance of playlist_lock. @@ -538,7 +539,6 @@ class NOVTABLE playlist_manager_v4 : public playlist_manager_v3 { }; //! \since 2.0 -//! Internal, do not use class NOVTABLE playlist_manager_v5 : public playlist_manager_v4 { FB2K_MAKE_SERVICE_COREAPI_EXTENSION(playlist_manager_v5, playlist_manager_v4) public: @@ -546,6 +546,14 @@ class NOVTABLE playlist_manager_v5 : public playlist_manager_v4 { virtual size_t find_playlist_by_guid(const GUID&) = 0; }; +//! \since 2.0 beta 8 +class NOVTABLE playlist_manager_v6 : public playlist_manager_v5 { + FB2K_MAKE_SERVICE_COREAPI_EXTENSION(playlist_manager_v6, playlist_manager_v5); +public: + virtual void set_callback_merit(class playlist_callback*, fb2k::callback_merit_t) = 0; + virtual void set_callback_merit(class playlist_callback_single*, fb2k::callback_merit_t) = 0; + +}; class NOVTABLE playlist_callback { public: @@ -812,11 +820,13 @@ class NOVTABLE playlist_incoming_item_filter : public service_base { //! For use with playlist_incoming_item_filter_v2::process_locations_async(). //! \since 0.9.3 class NOVTABLE process_locations_notify : public service_base { + FB2K_MAKE_SERVICE_INTERFACE(process_locations_notify, service_base); public: - virtual void on_completion(const pfc::list_base_const_t & p_items) = 0; + virtual void on_completion(metadb_handle_list_cref p_items) = 0; virtual void on_aborted() = 0; - FB2K_MAKE_SERVICE_INTERFACE(process_locations_notify,service_base); + typedef std::function func_t; + static process_locations_notify::ptr create(func_t); }; typedef service_ptr_t process_locations_notify_ptr; diff --git a/3rdparty/foo_SDK/foobar2000/SDK/playlistColumnProvider.h b/3rdparty/foo_SDK/foobar2000/SDK/playlistColumnProvider.h index bb26bc9f..234c30ed 100644 --- a/3rdparty/foo_SDK/foobar2000/SDK/playlistColumnProvider.h +++ b/3rdparty/foo_SDK/foobar2000/SDK/playlistColumnProvider.h @@ -1,18 +1,28 @@ #pragma once namespace fb2k { + //! Declares a column to be made available in Default UI playlist view, \n + //! without user having to manually enter title formatting patterns. class playlistColumnProvider : public service_base { FB2K_MAKE_SERVICE_INTERFACE_ENTRYPOINT(playlistColumnProvider); public: + //! Number of columns published by this object. virtual size_t numColumns() = 0; + //! Unique identifier of a column. virtual GUID columnID(size_t col) = 0; + //! Formatting pattern used for displaying a column. virtual fb2k::stringRef columnFormatSpec(size_t col) = 0; + //! Optional; sorting pattern used for this column. Return null to use display pattern for sorting. virtual fb2k::stringRef columnSortScript(size_t col) = 0; + //! Name of the column shown to the user. virtual fb2k::stringRef columnName(size_t col) = 0; + //! Display flags (alignment). \n + //! See flag_* constants. virtual unsigned columnFlags(size_t col) = 0; static constexpr unsigned flag_alignLeft = 0; static constexpr unsigned flag_alignRight = 1 << 0; static constexpr unsigned flag_alignCenter = 1 << 1; + static constexpr unsigned flag_alignMask = (flag_alignLeft|flag_alignRight|flag_alignCenter); }; } diff --git a/3rdparty/foo_SDK/foobar2000/SDK/playlist_loader.cpp b/3rdparty/foo_SDK/foobar2000/SDK/playlist_loader.cpp index 6dab8500..ab14942c 100644 --- a/3rdparty/foo_SDK/foobar2000/SDK/playlist_loader.cpp +++ b/3rdparty/foo_SDK/foobar2000/SDK/playlist_loader.cpp @@ -5,27 +5,12 @@ #include "file_info_impl.h" #include "input.h" #include "advconfig.h" +#include +#include +#include -#if FOOBAR2000_TARGET_VERSION >= 76 static void process_path_internal(const char * p_path,const service_ptr_t & p_reader,playlist_loader_callback::ptr callback, abort_callback & abort,playlist_loader_callback::t_entry_type type,const t_filestats & p_stats); -namespace { - class archive_callback_impl : public archive_callback { - public: - archive_callback_impl(playlist_loader_callback::ptr p_callback, abort_callback & p_abort) : m_callback(p_callback), m_abort(p_abort) {} - bool on_entry(archive * owner,const char * p_path,const t_filestats & p_stats,const service_ptr_t & p_reader) - { - process_path_internal(p_path,p_reader,m_callback,m_abort,playlist_loader_callback::entry_directory_enumerated,p_stats); - return !m_abort.is_aborting(); - } - bool is_aborting() const {return m_abort.is_aborting();} - abort_callback_event get_abort_event() const {return m_abort.get_abort_event();} - private: - const playlist_loader_callback::ptr m_callback; - abort_callback & m_abort; - }; -} - bool playlist_loader::g_try_load_playlist(file::ptr fileHint,const char * p_path,playlist_loader_callback::ptr p_callback, abort_callback & p_abort) { // Determine if this file is a playlist or not (which usually means that it's a media file) pfc::string8 filepath; @@ -40,7 +25,9 @@ bool playlist_loader::g_try_load_playlist(file::ptr fileHint,const char * p_path filesystem::ptr fs; if (filesystem::g_get_interface(fs,filepath)) { if (fs->supports_content_types()) { - fs->open(l_file,filepath,filesystem::open_mode_read,p_abort); + try { + fs->open(l_file,filepath,filesystem::open_mode_read,p_abort); + } catch(exception_io) { return false; } // fall thru } } } @@ -216,61 +203,71 @@ namespace { return false; } - // SPECIAL HACK - // filesystem service does not present file hidden attrib but we want to weed files/folders out - // so check separately on all native paths (inefficient but meh) class directory_callback_myimpl : public directory_callback { public: - directory_callback_myimpl() : m_addHidden(queryAddHidden()) {} + void main(const char* folder, abort_callback& abort) { + visit(folder); + + abort.check(); + const uint32_t flags = listMode::filesAndFolders | (queryAddHidden() ? listMode::hidden : 0); + + auto workHere = [&] (folder_t const & f) { + filesystem_v2::ptr v2; + if (v2 &= f.m_fs) { + v2->list_directory_ex(f.m_folder.c_str(), *this, flags, abort); + } else { + f.m_fs->list_directory(f.m_folder.c_str(), *this, abort); + } + }; + + workHere( folder_t { folder, filesystem::get(folder) } ); + + for (;; ) { + abort.check(); + auto iter = m_foldersPending.begin(); + if ( iter == m_foldersPending.end() ) break; + auto f = std::move(*iter); m_foldersPending.erase(iter); + + try { + workHere( f ); + } catch (exception_io const & e) { + FB2K_console_formatter() << "Error walking directory (" << e << "): " << f.m_folder.c_str(); + } + } + } bool on_entry(filesystem * owner,abort_callback & p_abort,const char * url,bool is_subdirectory,const t_filestats & p_stats) { p_abort.check(); + if (!visit(url)) return true; filesystem_v2::ptr v2; v2 &= owner; if ( is_subdirectory ) { - try { - if (v2.is_valid()) { - v2->list_directory_ex(url, *this, flags(), p_abort); - } else { - owner->list_directory(url, *this, p_abort); - } - } catch (exception_io const & e) { - FB2K_console_formatter() << "Error walking directory (" << e << "): " << url; - } + m_foldersPending.emplace_back( folder_t { url, owner } ); } else { - // In fb2k 1.4 the default filesystem is v2 and performs hidden file checks -#if FOOBAR2000_TARGET_VERSION < 79 - if ( ! m_addHidden && v2.is_empty() ) { - const char * n = url; - if (_extract_native_path_ptr(n)) { - DWORD att = uGetFileAttributes(n); - if (att == ~0 || (att & FILE_ATTRIBUTE_HIDDEN) != 0) return true; - } - } -#endif - auto i = m_entries.insert_last(); - i->m_path = url; - i->m_stats = p_stats; + m_entries.emplace_back( entry_t { url, p_stats } ); } return true; } - uint32_t flags() const { - uint32_t flags = listMode::filesAndFolders; - if (m_addHidden) flags |= listMode::hidden; - return flags; - } - - const bool m_addHidden; struct entry_t { - pfc::string8 m_path; + std::string m_path; t_filestats m_stats; }; - pfc::chain_list_v2_t m_entries; + std::list m_entries; + bool visit(const char* path) { + return m_visited.insert( path ).second; + } + std::unordered_set m_visited; + + struct folder_t { + std::string m_folder; + filesystem::ptr m_fs; + }; + std::list m_foldersPending; }; } @@ -288,19 +285,16 @@ static void process_path_internal(const char * p_path,const service_ptr_t if (p_reader.is_empty() && type != playlist_loader_callback::entry_directory_enumerated) { try { directory_callback_myimpl results; - auto fs = filesystem::get(p_path); - filesystem_v2::ptr v2; - if ( v2 &= fs ) v2->list_directory_ex(p_path, results, results.flags(), abort ); - else fs->list_directory(p_path, results, abort); - for( auto i = results.m_entries.first(); i.is_valid(); ++i ) { + results.main( p_path, abort ); + for( auto & i : results.m_entries ) { try { - process_path_internal(i->m_path, 0, callback, abort, playlist_loader_callback::entry_directory_enumerated, i->m_stats); + process_path_internal(i.m_path.c_str(), 0, callback, abort, playlist_loader_callback::entry_directory_enumerated, i.m_stats); } catch (exception_aborted) { throw; } catch (std::exception const& e) { - FB2K_console_formatter() << "Error walking path (" << e << "): " << file_path_display(i->m_path); + FB2K_console_formatter() << "Error walking path (" << e << "): " << file_path_display(i.m_path.c_str()); } catch (...) { - FB2K_console_formatter() << "Error walking path (bad exception): " << file_path_display(i->m_path); + FB2K_console_formatter() << "Error walking path (bad exception): " << file_path_display(i.m_path.c_str()); } } return; // successfully enumerated directory - go no further @@ -318,7 +312,6 @@ static void process_path_internal(const char * p_path,const service_ptr_t } { - archive_callback_impl archive_results(callback, abort); for (auto f : filesystem::enumerate()) { abort.check(); service_ptr_t arch; @@ -326,7 +319,10 @@ static void process_path_internal(const char * p_path,const service_ptr_t if (p_reader.is_valid()) p_reader->reopen(abort); try { - TRACK_CODE("archive::archive_list",arch->archive_list(p_path,p_reader,archive_results,true)); + archive::list_func_t archive_results = [callback, &abort](const char* p_path, const t_filestats& p_stats, file::ptr p_reader) { + process_path_internal(p_path,p_reader,callback,abort,playlist_loader_callback::entry_directory_enumerated,p_stats); + }; + TRACK_CODE("archive::archive_list",arch->archive_list(p_path,p_reader,archive_results,/*want readers*/true, abort)); return; } catch(exception_aborted) {throw;} catch(...) { @@ -458,5 +454,3 @@ bool playlist_loader::g_process_path_ex(const char * filename,playlist_loader_ca g_process_path(filename,callback,abort,type); return false; } - -#endif \ No newline at end of file diff --git a/3rdparty/foo_SDK/foobar2000/SDK/playlist_loader.h b/3rdparty/foo_SDK/foobar2000/SDK/playlist_loader.h index c70a3a13..04d4e34f 100644 --- a/3rdparty/foo_SDK/foobar2000/SDK/playlist_loader.h +++ b/3rdparty/foo_SDK/foobar2000/SDK/playlist_loader.h @@ -1,6 +1,5 @@ #pragma once -#if FOOBAR2000_TARGET_VERSION >= 76 //! Callback interface receiving item locations from playlist loader. \n //! Typically, you call one of standard services such as playlist_incoming_item_filter instead of implementing this interface and calling playlist_loader methods directly. class NOVTABLE playlist_loader_callback : public service_base { @@ -133,5 +132,3 @@ class NOVTABLE playlist_loader : public service_base { template class playlist_loader_factory_t : public service_factory_single_t {}; - -#endif \ No newline at end of file diff --git a/3rdparty/foo_SDK/foobar2000/SDK/popup_message.cpp b/3rdparty/foo_SDK/foobar2000/SDK/popup_message.cpp index 3e4ec033..8682df8b 100644 --- a/3rdparty/foo_SDK/foobar2000/SDK/popup_message.cpp +++ b/3rdparty/foo_SDK/foobar2000/SDK/popup_message.cpp @@ -135,6 +135,7 @@ int popup_message_v3::messageBoxReply(uint32_t status) { return -1; } void popup_message_v3::messageBoxAsync(fb2k::hwnd_t parent, const char* msg, const char* title, unsigned flags, std::function reply) { + PFC_ASSERT( core_api::is_main_thread() ); auto q = setupMessageBox(parent, msg, title, flags); if (reply) { q.reply = fb2k::makeCompletionNotify([reply](unsigned code) { @@ -144,6 +145,7 @@ void popup_message_v3::messageBoxAsync(fb2k::hwnd_t parent, const char* msg, con this->show_query(q); } int popup_message_v3::messageBox(fb2k::hwnd_t parent, const char* msg, const char* title, unsigned flags) { + PFC_ASSERT( core_api::is_main_thread() ); auto q = setupMessageBox(parent, msg, title, flags); uint32_t status = this->show_query_modal(q); return messageBoxReply(status); diff --git a/3rdparty/foo_SDK/foobar2000/SDK/popup_message.h b/3rdparty/foo_SDK/foobar2000/SDK/popup_message.h index 72e69cf6..f6ca598f 100644 --- a/3rdparty/foo_SDK/foobar2000/SDK/popup_message.h +++ b/3rdparty/foo_SDK/foobar2000/SDK/popup_message.h @@ -6,8 +6,8 @@ //! This interface allows you to show generic nonmodal noninteractive dialog with a text message. This should be used instead of MessageBox where possible.\n //! Usage: use popup_message::g_show / popup_message::g_show_ex static helpers, or popup_message::get() to obtain an instance.\n +//! Thread safety: OK to call from worker threads (will delegate UI ops to main thread automatically). \n //! Note that all strings are UTF-8. - class NOVTABLE popup_message : public service_base { public: enum t_icon {icon_information, icon_error, icon_query}; @@ -46,6 +46,9 @@ class NOVTABLE popup_message : public service_base { #define EXCEPTION_TO_POPUP_MESSAGE(CODE,LABEL) try { CODE; } catch(std::exception const & e) {popup_message::g_complain(LABEL,e);} //! \since 1.1 +//! Extendsion to popup_message API. \n +//! Thread safety: OK to call from worker threads (will delegate UI ops to main thread automatically). \n +//! Note that all strings are UTF-8. class NOVTABLE popup_message_v2 : public service_base { FB2K_MAKE_SERVICE_COREAPI(popup_message_v2); public: @@ -58,6 +61,8 @@ class NOVTABLE popup_message_v2 : public service_base { }; namespace fb2k { + //! \since 2.0 + //! Not really implemented for Windows yet. class popup_toast : public service_base { FB2K_MAKE_SERVICE_COREAPI( popup_toast ); public: @@ -71,8 +76,10 @@ namespace fb2k { class toastFormatter : public pfc::string_formatter { public: - ~toastFormatter() { - if ( this->length() > 0 ) showToast( c_str() ); + ~toastFormatter() noexcept { + try { + if ( this->length() > 0 ) showToast( c_str() ); + } catch(...) {} } }; } @@ -81,6 +88,8 @@ namespace fb2k { //! \since 1.5 +//! MessageBox-like dialog, only non-blocking and with dark mode support under foobar2000 v2.0. \n +//! Call from main thread only (contrary to popup_message / popup_message_v2) !!! class NOVTABLE popup_message_v3 : public service_base { FB2K_MAKE_SERVICE_COREAPI(popup_message_v3); public: diff --git a/3rdparty/foo_SDK/foobar2000/SDK/powerManager.h b/3rdparty/foo_SDK/foobar2000/SDK/powerManager.h index 0d96e2a8..9ba99a05 100644 --- a/3rdparty/foo_SDK/foobar2000/SDK/powerManager.h +++ b/3rdparty/foo_SDK/foobar2000/SDK/powerManager.h @@ -1,6 +1,7 @@ #pragma once namespace fb2k { + //! \since 2.0 class powerManager : public service_base { public: enum { @@ -10,11 +11,13 @@ namespace fb2k { flagDisplay = flagStrong }; - //! Blocks device sleep for the duration of returned object's lifetime. - //! By default we ask politely but can be still put to sleep by the OS. Specify flagStrong to force the device into awake state (possibly at cost of keeping the screen up). + //! Blocks device sleep for the duration of returned object's lifetime. \n + //! By default we ask politely but can be still put to sleep by the OS. Specify flagStrong to force the device into awake state (possibly at cost of keeping the screen up). \n + //! Thread safety: OK to call from any thread. virtual objRef makeTask(const char* name, unsigned flags) = 0; - //! Returns whether we're running on AC power (not on battery). + //! Returns whether we're running on AC power (not on battery). \n + //! Thread safety: OK to call from any thread. virtual bool haveACPower() = 0; objRef makeTaskWeak(const char* name) { return makeTask(name, 0); } diff --git a/3rdparty/foo_SDK/foobar2000/SDK/preferences_page.h b/3rdparty/foo_SDK/foobar2000/SDK/preferences_page.h index 3a01e96a..b7e19d0b 100644 --- a/3rdparty/foo_SDK/foobar2000/SDK/preferences_page.h +++ b/3rdparty/foo_SDK/foobar2000/SDK/preferences_page.h @@ -26,18 +26,28 @@ class preferences_state { //! In 1.0 and newer you should always derive from preferences_page_v3 rather than from preferences_page directly. class NOVTABLE preferences_page : public service_base { public: +#ifdef _WIN32 //! Obsolete. virtual fb2k::hwnd_t create(fb2k::hwnd_t p_parent) { uBugCheck(); } +#endif + +#ifdef __APPLE__ + //! Returns fb2k::NSObjectWrapper holding your NSViewController + virtual service_ptr instantiate( ) = 0; +#endif + //! Retrieves name of the preferences page to be displayed in preferences tree (static string). virtual const char * get_name() = 0; //! Retrieves GUID of the page. virtual GUID get_guid() = 0; //! Retrieves GUID of parent page/branch of this page. See preferences_page::guid_* constants for list of standard parent GUIDs. Can also be a GUID of another page or a branch (see: preferences_branch). virtual GUID get_parent_guid() = 0; +#ifdef _WIN32 //! Obsolete. virtual bool reset_query() { return false; } //! Obsolete. virtual void reset() {} +#endif //! Retrieves help URL. Without overriding it, it will redirect to foobar2000 wiki. virtual bool get_help_url(pfc::string_base & p_out); @@ -108,6 +118,7 @@ class preferences_branch_factory : public _preferences_branch_factory { }; +#ifdef _WIN32 class preferences_page_callback : public service_base { FB2K_MAKE_SERVICE_INTERFACE(preferences_page_callback, service_base) public: @@ -132,13 +143,16 @@ class preferences_page_instance : public service_base { //! Resets this page's content to the default values. Does not apply any changes - lets user preview the changes before hitting "apply". virtual void reset() = 0; }; +#endif //! \since 1.0 //! Implements a preferences page. class preferences_page_v3 : public preferences_page_v2 { FB2K_MAKE_SERVICE_INTERFACE(preferences_page_v3, preferences_page_v2) public: +#ifdef _WIN32 virtual preferences_page_instance::ptr instantiate(fb2k::hwnd_t parent, preferences_page_callback::ptr callback) = 0; +#endif }; //! \since 1.5 diff --git a/3rdparty/foo_SDK/foobar2000/SDK/replaygain_info.cpp b/3rdparty/foo_SDK/foobar2000/SDK/replaygain_info.cpp index eeda9cb8..0d2f62c0 100644 --- a/3rdparty/foo_SDK/foobar2000/SDK/replaygain_info.cpp +++ b/3rdparty/foo_SDK/foobar2000/SDK/replaygain_info.cpp @@ -51,10 +51,7 @@ bool replaygain_info::g_format_peak(float p_value,char p_buffer[text_buffer_size void replaygain_info::reset() { - m_album_gain = gain_invalid; - m_track_gain = gain_invalid; - m_album_peak = peak_invalid; - m_track_peak = peak_invalid; + *this = replaygain_info(); } #define meta_album_gain "replaygain_album_gain" diff --git a/3rdparty/foo_SDK/foobar2000/SDK/search_tools.h b/3rdparty/foo_SDK/foobar2000/SDK/search_tools.h index 6e2e7400..4b7b232c 100644 --- a/3rdparty/foo_SDK/foobar2000/SDK/search_tools.h +++ b/3rdparty/foo_SDK/foobar2000/SDK/search_tools.h @@ -97,3 +97,49 @@ class search_filter_manager_v3 : public search_filter_manager_v2 { //! This method INVALIDATES passed objects. Do not try to use them afterwards. virtual search_filter_v4::ptr combine(pfc::list_base_const_t const & arg, combine_t how, completion_notify::ptr changeNotify, t_uint32 flags) = 0; }; + +//! \since 2.0 +class search_index : public service_base { + FB2K_MAKE_SERVICE_INTERFACE(search_index, service_base) +public: + enum { + flag_sort = 1 << 0, + }; + + //! Searches Tracks in this index for tracks matching criteria. + //! @returns list of metadb_handles. Safe to use arr->as_list_of() to get a pfc::list_base_const_t + //! @param subset Optional: pass subset of tracks in this index to search - whole index is searched if nullptr is passed. + //! @param flags Optional: set flag_sort to sort output + //! Thread safety: call from any thread. + virtual fb2k::arrayRef search(search_filter::ptr pattern, metadb_handle_list_cptr subset, uint32_t flags, abort_callback& abort) = 0; + //! Performs hit test on a group of tracks that are a subset of tracks in this index. \n + //! Thread safety: call from any thread. + virtual void test(search_filter::ptr pattern, metadb_handle_list_cref items, bool* out, abort_callback& abort) = 0; + + //! Add tracks to a custom index. \n + //! Illegal to call on library or playlist indexes. \n + //! Thread safety: call from any thread. + virtual void add_tracks(metadb_handle_list_cref, metadb_io_callback_v2_data* dataIfAvail) = 0; + //! Remove tracks from a custom index. \n + //! Illegal to call on library or playlist indexes. \n + //! Thread safety: call from any thread. + virtual void remove_tracks(metadb_handle_list_cref) = 0; +}; + +//! \since 2.0 +class search_index_manager : public service_base { + FB2K_MAKE_SERVICE_COREAPI(search_index_manager); +public: + //! Create a custom index on any data set. \n + //! OK to call from any thread. + virtual search_index::ptr create_index(metadb_handle_list_cref items, metadb_io_callback_v2_data* dataIfAvail) = 0; + + //! Create a search index referencing a playlist. \n + //! Specify null GUID to follow active playlist (typical playlist search). \n + //! Call from main thread to obtain index, then can use obtained object from any thread. + virtual search_index::ptr create_playlist_index(const GUID& playlistID = pfc::guid_null) = 0; + + //! Returns a shared object indexing user's media library. \n + //! Call from main thread to obtain index, then can use obtained object from any thread. + virtual search_index::ptr get_library_index() = 0; +}; \ No newline at end of file diff --git a/3rdparty/foo_SDK/foobar2000/SDK/service.h b/3rdparty/foo_SDK/foobar2000/SDK/service.h index 956b9038..76257883 100644 --- a/3rdparty/foo_SDK/foobar2000/SDK/service.h +++ b/3rdparty/foo_SDK/foobar2000/SDK/service.h @@ -774,6 +774,17 @@ class service_factory_t : public service_factory_base_t +class service_factory_singleton_t : public service_factory_base_t { +public: + void instance_create(service_ptr_t & p_out) override { + this->pass_instance(p_out, &FB2K_SERVICE_SINGLETON(T) ); + } + + inline T& get_static_instance() { return &FB2K_SERVICE_SINGLETON(T); } + inline const T& get_static_instance() const { return &FB2K_SERVICE_SINGLETON(T); } +}; + template class service_factory_single_t : public service_factory_base_t { service_impl_single_t g_instance; @@ -843,7 +854,7 @@ class service_factory_single_transparent_t : public service_factory_base_t _FB2K_UNIQUE_NAME(g_factory_) FB2K_SERVICE_FACTORY_ATTR; +#define FB2K_SERVICE_FACTORY( TYPE ) static ::service_factory_singleton_t< TYPE > _FB2K_UNIQUE_NAME(g_factory_) FB2K_SERVICE_FACTORY_ATTR; #define FB2K_SERVICE_FACTORY_LATEINIT( TYPE ) static ::service_factory_single_v2_t< TYPE > _FB2K_UNIQUE_NAME(g_factory_) FB2K_SERVICE_FACTORY_ATTR; #define FB2K_SERVICE_FACTORY_PARAMS( TYPE, ... ) static ::service_factory_single_t< TYPE > _FB2K_UNIQUE_NAME(g_factory_) ( __VA_ARGS__ ); #define FB2K_SERVICE_FACTORY_DYNAMIC( TYPE ) static ::service_factory_t< TYPE > _FB2K_UNIQUE_NAME(g_factory_) FB2K_SERVICE_FACTORY_ATTR; diff --git a/3rdparty/foo_SDK/foobar2000/SDK/service_impl.h b/3rdparty/foo_SDK/foobar2000/SDK/service_impl.h index 13046435..88415a0a 100644 --- a/3rdparty/foo_SDK/foobar2000/SDK/service_impl.h +++ b/3rdparty/foo_SDK/foobar2000/SDK/service_impl.h @@ -135,4 +135,6 @@ namespace fb2k { service_ptr_t service_new(arg_t && ... arg) { return new service_impl_t< obj_t > ( std::forward (arg) ... ); } -} \ No newline at end of file +} + +#define FB2K_SERVICE_SINGLETON(class_t) PFC_SINGLETON( service_impl_single_t< class_t> ) \ No newline at end of file diff --git a/3rdparty/foo_SDK/foobar2000/SDK/system_time_keeper.h b/3rdparty/foo_SDK/foobar2000/SDK/system_time_keeper.h index 27b9cec8..7f9860da 100644 --- a/3rdparty/foo_SDK/foobar2000/SDK/system_time_keeper.h +++ b/3rdparty/foo_SDK/foobar2000/SDK/system_time_keeper.h @@ -24,7 +24,7 @@ class system_time_keeper : public service_base { class system_time_callback_impl : public system_time_callback { public: - system_time_callback_impl() : m_registered() {} + system_time_callback_impl() {} ~system_time_callback_impl() {stop_timer();} void stop_timer() { @@ -40,10 +40,11 @@ class system_time_callback_impl : public system_time_callback { m_registered = true; } - void on_time_changed(t_filetimestamp newVal) {} + //! Override me + void on_time_changed(t_filetimestamp newVal) override {} PFC_CLASS_NOT_COPYABLE_EX(system_time_callback_impl) private: - bool m_registered; + bool m_registered = false; }; diff --git a/3rdparty/foo_SDK/foobar2000/SDK/tag_processor.cpp b/3rdparty/foo_SDK/foobar2000/SDK/tag_processor.cpp index 4e08483a..04b5884a 100644 --- a/3rdparty/foo_SDK/foobar2000/SDK/tag_processor.cpp +++ b/3rdparty/foo_SDK/foobar2000/SDK/tag_processor.cpp @@ -135,20 +135,15 @@ void tag_processor::read_id3v2_trailing(const service_ptr_t & p_file,file_ bool have_id3v2 = true, have_trailing = true; try { read_id3v2(p_file,id3v2,p_abort); - } catch(exception_io_data) { + } catch(exception_io_data const &) { have_id3v2 = false; } - if (have_id3v2) { - // Disregard empty ID3v2 - if (id3v2.meta_get_count() == 0 && id3v2.get_replaygain().get_value_count() == 0) { - have_id3v2 = false; - } - } - - if (!have_id3v2 || !p_file->is_remote()) try { + const bool have_id3v2_text = have_id3v2 && id3v2.meta_get_count() > 0; + + if (!have_id3v2_text || !p_file->is_remote()) try { read_trailing(p_file,trailing,p_abort); - } catch(exception_io_data) { + } catch(exception_io_data const &) { have_trailing = false; } @@ -157,6 +152,7 @@ void tag_processor::read_id3v2_trailing(const service_ptr_t & p_file,file_ if (have_id3v2) { p_info._set_tag(id3v2); if (have_trailing) p_info._add_tag(trailing); + if (! have_id3v2_text ) p_info.copy_meta(trailing); } else { p_info._set_tag(trailing); } @@ -166,6 +162,12 @@ void tag_processor::skip_id3v2(const service_ptr_t & p_file,t_filesize & p tag_processor_id3v2::g_skip(p_file,p_size_skipped,p_abort); } +t_filesize tag_processor::skip_id3v2(file::ptr const & f, abort_callback & a) { + t_filesize ret = 0; + skip_id3v2(f, ret, a); + return ret; +} + bool tag_processor::is_id3v1_sufficient(const file_info & p_info) { return tag_processor_trailing::get()->is_id3v1_sufficient(p_info); @@ -174,4 +176,4 @@ bool tag_processor::is_id3v1_sufficient(const file_info & p_info) void tag_processor::truncate_to_id3v1(file_info & p_info) { tag_processor_trailing::get()->truncate_to_id3v1(p_info); -} \ No newline at end of file +} diff --git a/3rdparty/foo_SDK/foobar2000/SDK/tag_processor.h b/3rdparty/foo_SDK/foobar2000/SDK/tag_processor.h index d90a3487..58b0409b 100644 --- a/3rdparty/foo_SDK/foobar2000/SDK/tag_processor.h +++ b/3rdparty/foo_SDK/foobar2000/SDK/tag_processor.h @@ -98,6 +98,7 @@ namespace tag_processor { void read_id3v2_trailing(const service_ptr_t & p_file,file_info & p_info,abort_callback & p_abort); void skip_id3v2(const service_ptr_t & p_file,t_filesize & p_size_skipped,abort_callback & p_abort); + t_filesize skip_id3v2(file::ptr const & f, abort_callback & a); bool is_id3v1_sufficient(const file_info & p_info); void truncate_to_id3v1(file_info & p_info); diff --git a/3rdparty/foo_SDK/foobar2000/SDK/threaded_process.cpp b/3rdparty/foo_SDK/foobar2000/SDK/threaded_process.cpp index 16796f62..b8fc8ef9 100644 --- a/3rdparty/foo_SDK/foobar2000/SDK/threaded_process.cpp +++ b/3rdparty/foo_SDK/foobar2000/SDK/threaded_process.cpp @@ -29,11 +29,13 @@ void threaded_process_status::set_progress_secondary_float(double p_state) bool threaded_process::g_run_modal(service_ptr_t p_callback,unsigned p_flags,fb2k::hwnd_t p_parent,const char * p_title,t_size p_title_len) { + PFC_ASSERT( core_api::is_main_thread() ); return threaded_process::get()->run_modal(p_callback,p_flags,p_parent,p_title,p_title_len); } bool threaded_process::g_run_modeless(service_ptr_t p_callback,unsigned p_flags,fb2k::hwnd_t p_parent,const char * p_title,t_size p_title_len) { + PFC_ASSERT( core_api::is_main_thread() ); return threaded_process::get()->run_modeless(p_callback,p_flags,p_parent,p_title,p_title_len); } diff --git a/3rdparty/foo_SDK/foobar2000/SDK/threaded_process.h b/3rdparty/foo_SDK/foobar2000/SDK/threaded_process.h index 3fd92cc4..16180178 100644 --- a/3rdparty/foo_SDK/foobar2000/SDK/threaded_process.h +++ b/3rdparty/foo_SDK/foobar2000/SDK/threaded_process.h @@ -96,14 +96,16 @@ class NOVTABLE threaded_process : public service_base { }; //! Runs a synchronous threaded_process operation - the function does not return until the operation has completed, though the app UI is not frozen and the operation is abortable. \n - //! This API is obsolete and should not be used. Please use run_modeless() instead if possible. + //! This API is obsolete and should not be used. Please use run_modeless() instead if possible. \n + //! Call from main thread only. //! @param p_callback Interface to your threaded_process client. //! @param p_flags Flags describing requested dialog functionality. See threaded_process::flag_* constants. //! @param p_parent Parent window for the progress dialog - typically core_api::get_main_window(). //! @param p_title Initial title of the dialog. //! @returns True if the operation has completed normally, false if the user has aborted the operation. In case of a catastrophic failure such as dialog creation failure, exceptions will be thrown. virtual bool run_modal(service_ptr_t p_callback,unsigned p_flags,fb2k::hwnd_t p_parent,const char * p_title,t_size p_title_len = SIZE_MAX) = 0; - //! Runs an asynchronous threaded_process operation. + //! Runs an asynchronous threaded_process operation. \n + //! Call from main thread only. //! @param p_callback Interface to your threaded_process client. //! @param p_flags Flags describing requested dialog functionality. See threaded_process::flag_* constants. //! @param p_parent Parent window for the progress dialog - typically core_api::get_main_window(). diff --git a/3rdparty/foo_SDK/foobar2000/SDK/threadsLite.h b/3rdparty/foo_SDK/foobar2000/SDK/threadsLite.h index 963a5d14..ca5ab187 100644 --- a/3rdparty/foo_SDK/foobar2000/SDK/threadsLite.h +++ b/3rdparty/foo_SDK/foobar2000/SDK/threadsLite.h @@ -3,6 +3,9 @@ namespace fb2k { //! pfc::splitThread() + async_task_manager::acquire void splitTask(std::function); void splitTask(pfc::thread::arg_t const&, std::function); + abort_callback& mainAborter(); + + void inCpuWorkerThread(std::function f); } @@ -13,11 +16,21 @@ namespace fb2k { // ====================================================================================================== namespace fb2k { //! Queue a call in main thread. Returns immediately. \n - //! You can call this from any thread, including main thread - to execute some code outside the current call stack / global fb2k callbacks / etc. + //! You can call this from any thread, including main thread - to execute some code outside the current call stack / global fb2k callbacks / etc. \n + //! Guaranteed FIFO order of execution. See also: main_thread_callback::add_callback(). void inMainThread(std::function f); //! Call f synchronously if called from main thread, queue call if called from another. void inMainThread2(std::function f); - //! Synchronous version. + //! Synchronous / abortable version. May exit *before* f() finishes, if abort becomes set. void inMainThreadSynchronous(std::function f, abort_callback& abort); + + //! Synchronous blocking version. \n + //! Uses new foobar2000 v2.0 methods if available, synchronizing to main thread via SendMessage(). \n + //! Introduced to help recovering from method-called-from-wrong-context scenarios. Does *not* guarentee FIFO execution order contrary to plain inMainThread(). + void inMainThreadSynchronous2(std::function f); + + //! Helper class for threads that call fb2k objects. Mainly needed for Android shims. You can safely ignore this. \n + //! Guaranteed to have startHere(), isActive() and waitTillDone() methods only. + typedef pfc::thread2 thread; } diff --git a/3rdparty/foo_SDK/foobar2000/SDK/ui.cpp b/3rdparty/foo_SDK/foobar2000/SDK/ui.cpp index 6532287e..cbca5980 100644 --- a/3rdparty/foo_SDK/foobar2000/SDK/ui.cpp +++ b/3rdparty/foo_SDK/foobar2000/SDK/ui.cpp @@ -19,6 +19,7 @@ bool ui_drop_item_callback::g_is_accepted_type(interface IDataObject * pDataObje } return false; } +#endif // _WIN32 bool user_interface::g_find(service_ptr_t & p_out,const GUID & p_guid) { @@ -30,7 +31,6 @@ bool user_interface::g_find(service_ptr_t & p_out,const GUID & p } return false; } -#endif // _WIN32 // ui_edit_context.h code diff --git a/3rdparty/foo_SDK/foobar2000/SDK/ui.h b/3rdparty/foo_SDK/foobar2000/SDK/ui.h index acc2c646..9454f45d 100644 --- a/3rdparty/foo_SDK/foobar2000/SDK/ui.h +++ b/3rdparty/foo_SDK/foobar2000/SDK/ui.h @@ -1,20 +1,25 @@ #pragma once -#ifdef _WIN32 //! Entrypoint service for user interface modules. Implement when registering an UI module. Do not call existing implementations; only core enumerates / dispatches calls. To control UI behaviors from other components, use ui_control API. \n //! Use user_interface_factory_t<> to register, e.g static user_interface_factory_t g_myclass_factory; class NOVTABLE user_interface : public service_base { FB2K_MAKE_SERVICE_INTERFACE_ENTRYPOINT(user_interface); public: +#ifdef _WIN32 //!HookProc usage: \n //! in your windowproc, call HookProc first, and if it returns true, return LRESULT value it passed to you typedef BOOL (WINAPI * HookProc_t)(HWND wnd,UINT msg,WPARAM wp,LPARAM lp,LRESULT * ret); - +#endif //! Retrieves name (UTF-8 null-terminated string) of the UI module. virtual const char * get_name()=0; - //! Initializes the UI module - creates the main app window, etc. Failure should be signaled by appropriate exception (std::exception or a derivative). - virtual HWND init(HookProc_t hook)=0; + //! Initializes the UI module - creates the main app window, etc. Failure should be signaled by appropriate exception (std::exception or a derivative). \n + //! Mac OS: return NSWindow cast to hwnd_t +#ifdef _WIN32 + virtual HWND init(HookProc_t hook)=0; +#else + virtual fb2k::hwnd_t init() = 0; +#endif //! Deinitializes the UI module - destroys the main app window, etc. virtual void shutdown()=0; //! Activates main app window. @@ -31,7 +36,7 @@ class NOVTABLE user_interface : public service_base { //! Disables statusbar text override. virtual void revert_statusbar_text() = 0; - //! Shows now-playing item somehow (e.g. system notification area popup). + //! Shows now-playing item somehow (e.g. system notification area popup). virtual void show_now_playing() = 0; static bool g_find(service_ptr_t & p_out,const GUID & p_guid); @@ -48,6 +53,7 @@ class NOVTABLE user_interface_v2 : public user_interface { //! Allows the core to ask the UI module about a specific feature. virtual bool query_capability( const GUID & cap ) = 0; +#ifdef _WIN32 //! Suppress core's shellhook window for intercepting systemwide WM_APPCOMMAND? \n //! Recommended: false - return true only if your UI does this on its own. static const GUID cap_suppress_core_shellhook; @@ -56,8 +62,10 @@ class NOVTABLE user_interface_v2 : public user_interface { //! Note that cap_suppress_core_shellhook is queried first, as core can't use UVC if this UI does global WM_APPCOMMAND handling on its own. \n //! Returning true from cap_suppress_core_shellhook implies the same from cap_suppress_core_uvc. static const GUID cap_suppress_core_uvc; +#endif }; +#ifdef _WIN32 class ui_config_manager; //! \since 2.0 class NOVTABLE user_interface_v3 : public user_interface_v2 { @@ -65,7 +73,7 @@ class NOVTABLE user_interface_v3 : public user_interface_v2 { public: virtual service_ptr_t< ui_config_manager > get_config_manager() = 0; }; -#endif // _WIN32 +#endif //! Interface class allowing you to override UI statusbar text. There may be multiple callers trying to override statusbar text; backend decides which one succeeds so you will not always get what you want. Statusbar text override is automatically cancelled when the object is released.\n //! Use ui_control::override_status_text_create() to instantiate. diff --git a/3rdparty/foo_SDK/foobar2000/SDK/ui_element.cpp b/3rdparty/foo_SDK/foobar2000/SDK/ui_element.cpp index e7ccbe12..51e9241d 100644 --- a/3rdparty/foo_SDK/foobar2000/SDK/ui_element.cpp +++ b/3rdparty/foo_SDK/foobar2000/SDK/ui_element.cpp @@ -239,17 +239,20 @@ ui_element_replace_dialog_notify::ptr ui_element_replace_dialog_notify::create(s } bool ui_config_manager::is_dark_mode() { + PFC_ASSERT(core_api::is_main_thread()); t_ui_color clr = 0xFFFFFF; if (this->query_color(ui_color_darkmode, clr)) return clr == 0; return false; } bool ui_config_manager::g_is_dark_mode() { + PFC_ASSERT(core_api::is_main_thread()); auto api = tryGet(); if (api.is_valid()) return api->is_dark_mode(); else return false; } #ifdef _WIN32 t_ui_color ui_config_manager::getSysColor(int sysColorIndex) { + PFC_ASSERT(core_api::is_main_thread()); GUID guid = ui_color_from_sys_color_index(sysColorIndex); if (guid != pfc::guid_null) { t_ui_color ret = 0; @@ -260,11 +263,13 @@ t_ui_color ui_config_manager::getSysColor(int sysColorIndex) { #endif ui_config_callback_impl::ui_config_callback_impl() { + PFC_ASSERT(core_api::is_main_thread()); auto api = ui_config_manager::tryGet(); if (api.is_valid()) api->add_callback(this); } ui_config_callback_impl::~ui_config_callback_impl() { + PFC_ASSERT(core_api::is_main_thread()); auto api = ui_config_manager::tryGet(); if (api.is_valid()) api->remove_callback(this); } diff --git a/3rdparty/foo_SDK/foobar2000/SDK/ui_element.h b/3rdparty/foo_SDK/foobar2000/SDK/ui_element.h index 85921cdc..49432d31 100644 --- a/3rdparty/foo_SDK/foobar2000/SDK/ui_element.h +++ b/3rdparty/foo_SDK/foobar2000/SDK/ui_element.h @@ -612,13 +612,19 @@ class NOVTABLE ui_config_callback { class NOVTABLE ui_config_manager : public service_base { FB2K_MAKE_SERVICE_COREAPI(ui_config_manager); public: + //! Registers a callback to receive notifications about colors/fonts change. \n + //! Main thread only! virtual void add_callback(ui_config_callback*) = 0; + //! Unregisters a callback to receive notifications about colors/fonts change. \n + //! Main thread only! virtual void remove_callback(ui_config_callback*) = 0; - //! Queries actual color to be used for the specified ui_color_* element. + //! Queries actual color to be used for the specified ui_color_* element. \n + //! Main thread only! \n //! @returns True if color is user-overridden, false if system-default color should be used. virtual bool query_color(const GUID& p_what, t_ui_color& p_out) = 0; //! Queries font to be used for the specified ui_font_* element. \n + //! Main thread only! \n //! The returned font handle is valid until the next font change callback cycle *completes*, that is, during a font change callback, both old and new handle are momentarily valid. virtual t_ui_font query_font(const GUID& p_what) = 0; @@ -629,13 +635,24 @@ class NOVTABLE ui_config_manager : public service_base { t_ui_color getSysColor(int sysColorIndex); #endif - //! Special method that's safe to call without checking if ui_config_manager exists, that is, it works on foobar2000 < 2.0. - //! Returns false if ui_conifg_manager doesn't exist and therefore dark mode isn't supported by this foobar2000 revision. + //! Special method that's safe to call without checking if ui_config_manager exists, that is, it works on foobar2000 < 2.0. \n + //! Returns false if ui_conifg_manager doesn't exist and therefore dark mode isn't supported by this foobar2000 revision. \n + //! Main thread only! static bool g_is_dark_mode(); }; //! \since 2.0 -//! Does nothing (fails to register quietly) if used in fb2k prior to 2.0 +class NOVTABLE ui_config_manager_v2 : public ui_config_manager { + FB2K_MAKE_SERVICE_COREAPI_EXTENSION(ui_config_manager_v2, ui_config_manager) +public: + //! Tells ui_config_manager about system theme having changed. \n + //! Intended for keeping track of live dark mode toggle when foo_ui_std is not the active UI. Do not use. + virtual void notify_system_theme_changed() = 0; +}; + +//! \since 2.0 +//! Does nothing (fails to register quietly) if used in fb2k prior to 2.0 \n +//! Use in main thread only! class ui_config_callback_impl : public ui_config_callback { public: ui_config_callback_impl(); diff --git a/3rdparty/foo_SDK/foobar2000/SDK/utility.cpp b/3rdparty/foo_SDK/foobar2000/SDK/utility.cpp index 9562186a..8218b877 100644 --- a/3rdparty/foo_SDK/foobar2000/SDK/utility.cpp +++ b/3rdparty/foo_SDK/foobar2000/SDK/utility.cpp @@ -132,6 +132,7 @@ namespace fb2k { namespace fb2k { void callLater(double timeAfter, std::function< void() > func) { + PFC_ASSERT( core_api::is_main_thread() ); auto releaseMe = std::make_shared(); *releaseMe = registerTimer(timeAfter, [=] { if (releaseMe->is_valid()) { @@ -141,6 +142,7 @@ namespace fb2k { }); } objRef registerTimer(double interval, std::function func) { + PFC_ASSERT( core_api::is_main_thread() ); return static_api_ptr_t()->addTimer(interval, makeCompletionNotify([func](unsigned) { func(); })); } } @@ -257,6 +259,7 @@ void fb2k::keyValueIO::putInt( const char * name, int val ) { // fileDialog.h functionality #include "fileDialog.h" +#include "fsitem.h" namespace { using namespace fb2k; @@ -277,6 +280,27 @@ fb2k::fileDialogNotify::ptr fb2k::fileDialogNotify::create( std::functionrun(fb2k::fileDialogNotify::create(reply)); +} +void fb2k::fileDialogSetup::runSimple(fileDialogGetPath_t reply) { + fb2k::fileDialogReply_t wrapper = [reply] (fb2k::arrayRef arg) { + if ( arg.is_empty() ) {PFC_ASSERT(!"???"); return; } + if ( arg->size() != 1 ) { PFC_ASSERT(!"???"); return; } + auto obj = arg->itemAt(0); + fsItemBase::ptr fsitem; + if ( fsitem &= obj ) { + reply( fsitem->canonicalPath() ); return; + } + fb2k::stringRef str; + if ( str &= obj ) { + reply(str); return; + } + PFC_ASSERT( !"???" ); + }; + this->run(wrapper); +} + #include "input_file_type.h" void fb2k::fileDialogSetup::setAudioFileTypes() { @@ -293,3 +317,87 @@ void search_filter_v2::test_multi_here(metadb_handle_list& ref, abort_callback& this->test_multi_ex(ref, mask.get_ptr(), abort); ref.filter_mask(mask.get_ptr()); } + + + +// core_api.h + +namespace fb2k { + bool isDebugModeActive() { +#if PFC_DEBUG + return true; +#else + auto api = fb2k::configStore::tryGet(); + if (api.is_empty()) return false; + return api->getConfigBool("core.debugMode"); +#endif + } + +#if FB2K_SUPPORT_LOW_MEM_MODE + static bool _isLowMemModeActive() { + auto api = fb2k::configStore::tryGet(); + if (api.is_empty()) return false; + return api->getConfigBool("core.lowMemMode"); + } + + bool isLowMemModeActive() { + static bool cached = _isLowMemModeActive(); + return cached; + } +#endif +} + +// callback_merit.h +namespace fb2k { + callback_merit_t callback_merit_of(service_ptr obj) { + { + callback_with_merit::ptr q; + if (q &= obj) return q->get_callback_merit(); + } + { + metadb_io_callback_v2::ptr q; + if (q &= obj) return q->get_callback_merit(); + } + return callback_merit_default; + } +} + +#ifdef _WIN32 +#include "message_loop.h" +message_filter_impl_base::message_filter_impl_base() { + PFC_ASSERT( core_api::is_main_thread() ); + message_loop::get()->add_message_filter(this); +} +message_filter_impl_base::message_filter_impl_base(t_uint32 lowest, t_uint32 highest) { + PFC_ASSERT( core_api::is_main_thread() ); + message_loop_v2::get()->add_message_filter_ex(this, lowest, highest); +} +message_filter_impl_base::~message_filter_impl_base() { + PFC_ASSERT( core_api::is_main_thread() ); + message_loop::get()->remove_message_filter(this); +} + +bool message_filter_impl_accel::pretranslate_message(MSG * p_msg) { + if (m_wnd != NULL) { + if (GetActiveWindow() == m_wnd) { + if (TranslateAccelerator(m_wnd,m_accel.get(),p_msg) != 0) { + return true; + } + } + } + return false; +} + +message_filter_impl_accel::message_filter_impl_accel(HINSTANCE p_instance,const TCHAR * p_accel) { + m_accel.load(p_instance,p_accel); +} + +bool message_filter_remap_f1::pretranslate_message(MSG * p_msg) { + if (IsOurMsg(p_msg) && m_wnd != NULL && GetActiveWindow() == m_wnd) { + ::PostMessage(m_wnd, WM_SYSCOMMAND, SC_CONTEXTHELP, -1); + return true; + } + return false; +} + +#endif diff --git a/3rdparty/foo_SDK/foobar2000/foo_sample/IO.cpp b/3rdparty/foo_SDK/foobar2000/foo_sample/IO.cpp index e1035383..febad041 100644 --- a/3rdparty/foo_SDK/foobar2000/foo_sample/IO.cpp +++ b/3rdparty/foo_SDK/foobar2000/foo_sample/IO.cpp @@ -1,12 +1,12 @@ #include "stdafx.h" #include #include +#include void RunIOTest() { try { - abort_callback_dummy noAbort; auto request = http_client::get()->create_request("GET"); - request->run("https://www.foobar2000.org", noAbort); + request->run("https://www.foobar2000.org", fb2k::noAbort); } catch (std::exception const & e) { popup_message::g_show( PFC_string_formatter() << "Network test failure:\n" << e, "Information"); return; @@ -21,7 +21,7 @@ namespace { // anon namespace local classes for good measure m_lstFiles.init_from_list( items ); } - void on_init(HWND p_wnd) override { + void on_init(ctx_t p_wnd) override { // Main thread, called before run() gets started } void run(threaded_process_status & p_status, abort_callback & p_abort) override { @@ -135,7 +135,7 @@ namespace { // anon namespace local classes for good measure // .. and delete the incomplete file try { - abort_callback_dummy noAbort; // we might be being aborted, don't let that prevent deletion + auto & noAbort = fb2k::noAbort; // we might be being aborted, don't let that prevent deletion m_outFS->remove( outPath, noAbort ); } catch(...) { // disregard errors - just report original copy error @@ -146,7 +146,7 @@ namespace { // anon namespace local classes for good measure } - void on_done(HWND p_wnd, bool p_was_aborted) override { + void on_done(ctx_t p_wnd, bool p_was_aborted) override { // All done, main thread again if (! p_was_aborted && m_errorLog.length() > 0 ) { @@ -171,8 +171,19 @@ namespace { // anon namespace local classes for good measure }; } +void RunCopyFilesHere(metadb_handle_list_cref data, const char * copyTo, fb2k::hwnd_t wndParent) { + + // Create worker object, a threaded_process_callback implementation. + auto worker = fb2k::service_new(data, copyTo); + const uint32_t flags = threaded_process::flag_show_abort | threaded_process::flag_show_progress | threaded_process::flag_show_item; + // Start the process asynchronously. + threaded_process::get()->run_modeless( worker, flags, wndParent, "Sample Component: Copying Files" ); + + // Our worker is now running. +} void RunCopyFiles(metadb_handle_list_cref data) { +#ifdef _WIN32 // Detect modal dialog wars. // If another modal dialog is active, bump it instead of allowing our modal dialog (uBrowseForFolder) to run. // Suppress this if the relevant code is intended to be launched by a modal dialog. @@ -183,18 +194,21 @@ void RunCopyFiles(metadb_handle_list_cref data) { // shared.dll method if (!uBrowseForFolder( wndParent, "Choose destination folder", copyTo )) return; - // shared.dll methods are win32 API wrappers and return plain paths with no protocol prepended - // Prefix with file:// before passing to fb2k filesystem methods. - // Actually the standard fb2k filesystem implementation recognizes paths even without the prefix, but we enforce it here as a good practice. - pfc::string8 copyTo2 = PFC_string_formatter() << "file://" << copyTo; - - // Create worker object, a threaded_process_callback implementation. - auto worker = fb2k::service_new(data, copyTo2); - const uint32_t flags = threaded_process::flag_show_abort | threaded_process::flag_show_progress | threaded_process::flag_show_item; - // Start the process asynchronously. - threaded_process::get()->run_modeless( worker, flags, wndParent, "Sample Component: Copying Files" ); - - // Our worker is now running. + // shared.dll methods are win32 API wrappers and return plain paths with no protocol prepended + // Prefix with file:// before passing to fb2k filesystem methods. + // Actually the standard fb2k filesystem implementation recognizes paths even without the prefix, but we enforce it here as a good practice. + pfc::string8 copyTo2 = PFC_string_formatter() << "file://" << copyTo; + + RunCopyFilesHere(data, copyTo2, wndParent); +#else + auto tracksCopy = std::make_shared( data ); + auto setup = fb2k::fileDialog::get()->setupOpenFolder(); + setup->setTitle("Choose destination folder"); + setup->runSimple( [tracksCopy] (fb2k::stringRef path) { + RunCopyFilesHere(*tracksCopy, path->c_str(), core_api::get_main_window()); + } ); + +#endif } @@ -278,7 +292,7 @@ namespace { // Touchy subject // Should we let the user abort an incomplete tag write? // Let's better not - abort_callback_dummy noAbort; + auto & noAbort = fb2k::noAbort; // This can be called many times for files with multiple subsongs writer->set_info( subsong, info, noAbort ); @@ -314,7 +328,7 @@ namespace { } void RunAlterTagsLL(metadb_handle_list_cref data) { - const HWND wndParent = core_api::get_main_window(); + const auto wndParent = core_api::get_main_window(); // Our worker object, a threaded_process_callback subclass. auto worker = fb2k::service_new< processLLtags > ( data ); diff --git a/3rdparty/foo_SDK/foobar2000/foo_sample/Mac/fooSampleDSPView.h b/3rdparty/foo_SDK/foobar2000/foo_sample/Mac/fooSampleDSPView.h new file mode 100644 index 00000000..1824b316 --- /dev/null +++ b/3rdparty/foo_SDK/foobar2000/foo_sample/Mac/fooSampleDSPView.h @@ -0,0 +1,12 @@ +// +// fooSampleDSPView.h +// foo_sample +// +// Created by P on 01/09/2023. +// + +#import + + +@interface fooSampleDSPView : NSViewController +@end diff --git a/3rdparty/foo_SDK/foobar2000/foo_sample/Mac/fooSampleDSPView.mm b/3rdparty/foo_SDK/foobar2000/foo_sample/Mac/fooSampleDSPView.mm new file mode 100644 index 00000000..b692d3b3 --- /dev/null +++ b/3rdparty/foo_SDK/foobar2000/foo_sample/Mac/fooSampleDSPView.mm @@ -0,0 +1,41 @@ +#import "stdafx.h" +#import "fooSampleDSPView.h" +#import "dsp_sample.h" + +@interface fooSampleDSPView () +@property (nonatomic) dsp_preset_edit_callback_v2::ptr callback; +@property (nonatomic) NSNumber * gain; +@end + +@implementation fooSampleDSPView + +- (instancetype)init { + // IMPORTANT: feed OUR NSBundle, bundleForClass works well for this + return [self initWithNibName: @"fooSampleDSPView" bundle:[NSBundle bundleForClass: [self class]]]; +} + +- (void)viewDidLoad { + [super viewDidLoad]; + // Do view setup here. + + dsp_preset_impl preset; + _callback->get_preset(preset); + self.gain = [NSNumber numberWithFloat: parse_preset(preset)]; +} + +- (IBAction)onEdit:(id)sender { + [self apply]; +} + +- (void) apply { + dsp_preset_impl preset; + make_preset( self.gain.floatValue , preset); + _callback->set_preset( preset ); +} +@end + +service_ptr ConfigureSampleDSP( fb2k::hwnd_t parent, dsp_preset_edit_callback_v2::ptr callback ) { + fooSampleDSPView * dialog = [fooSampleDSPView new]; + dialog.callback = callback; + return fb2k::wrapNSObject( dialog ); +} diff --git a/3rdparty/foo_SDK/foobar2000/foo_sample/Mac/fooSampleDSPView.xib b/3rdparty/foo_SDK/foobar2000/foo_sample/Mac/fooSampleDSPView.xib new file mode 100644 index 00000000..799f6e32 --- /dev/null +++ b/3rdparty/foo_SDK/foobar2000/foo_sample/Mac/fooSampleDSPView.xib @@ -0,0 +1,68 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/3rdparty/foo_SDK/foobar2000/foo_sample/Mac/fooSampleMacPreferences.h b/3rdparty/foo_SDK/foobar2000/foo_sample/Mac/fooSampleMacPreferences.h new file mode 100644 index 00000000..b8ac2084 --- /dev/null +++ b/3rdparty/foo_SDK/foobar2000/foo_sample/Mac/fooSampleMacPreferences.h @@ -0,0 +1,12 @@ +// +// fooSampleMacPreferences.h +// foo_sample +// +// Created by P on 01/09/2023. +// + +#import + +@interface fooSampleMacPreferences : NSViewController + +@end diff --git a/3rdparty/foo_SDK/foobar2000/foo_sample/Mac/fooSampleMacPreferences.mm b/3rdparty/foo_SDK/foobar2000/foo_sample/Mac/fooSampleMacPreferences.mm new file mode 100644 index 00000000..b0b80aa8 --- /dev/null +++ b/3rdparty/foo_SDK/foobar2000/foo_sample/Mac/fooSampleMacPreferences.mm @@ -0,0 +1,58 @@ +#import "stdafx.h" +#import "fooSampleMacPreferences.h" + +namespace foo_sample { + extern cfg_uint cfg_bogoSetting1, cfg_bogoSetting2; +} + +@interface fooSampleMacPreferences () +@property (nonatomic) NSNumber* bogo1; +@property (nonatomic) NSNumber* bogo2; +@end + +@implementation fooSampleMacPreferences + +- (void)viewDidLoad { + [super viewDidLoad]; + // Do view setup here. +} +- (instancetype)init { + // IMPORTANT: feed OUR NSBundle, bundleForClass works well for this + self = [self initWithNibName: @"fooSampleMacPreferences" bundle:[NSBundle bundleForClass: [self class]]]; + [self loadSettings]; + return self; +} +- (void) loadSettings { + self.bogo1 = [NSNumber numberWithUnsignedLong: foo_sample::cfg_bogoSetting1]; + self.bogo2 = [NSNumber numberWithUnsignedLong: foo_sample::cfg_bogoSetting2]; +} +- (IBAction)onBogo1:(id)sender { + foo_sample::cfg_bogoSetting1 = self.bogo1.unsignedLongValue; +} +- (IBAction)onBogo2:(id)sender { + foo_sample::cfg_bogoSetting2 = self.bogo2.unsignedLongValue; +} + + +@end + + + + + +namespace { +class preferences_page_sample : public preferences_page { + public: + service_ptr instantiate() override { + return fb2k::wrapNSObject( [ fooSampleMacPreferences new ] ); + } + const char * get_name() override {return "Sample Component";} + GUID get_guid() override { + // This is our GUID. Replace with your own when reusing the code. + return GUID { 0x7702c93e, 0x24dc, 0x48ed, { 0x8d, 0xb1, 0x3f, 0x27, 0xb3, 0x8c, 0x7c, 0xc9 } }; + } + GUID get_parent_guid() override {return guid_tools;} + }; + + FB2K_SERVICE_FACTORY(preferences_page_sample); +} diff --git a/3rdparty/foo_SDK/foobar2000/foo_sample/Mac/fooSampleMacPreferences.xib b/3rdparty/foo_SDK/foobar2000/foo_sample/Mac/fooSampleMacPreferences.xib new file mode 100644 index 00000000..82af6983 --- /dev/null +++ b/3rdparty/foo_SDK/foobar2000/foo_sample/Mac/fooSampleMacPreferences.xib @@ -0,0 +1,93 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/3rdparty/foo_SDK/foobar2000/foo_sample/contextmenu.cpp b/3rdparty/foo_SDK/foobar2000/foo_sample/contextmenu.cpp index dd788a84..f2ae310e 100644 --- a/3rdparty/foo_SDK/foobar2000/foo_sample/contextmenu.cpp +++ b/3rdparty/foo_SDK/foobar2000/foo_sample/contextmenu.cpp @@ -32,7 +32,7 @@ namespace { // anon namespace local classes for good measure static void RunAlterTags(metadb_handle_list_cref data) { // Simple alter-file-tags functionality - const HWND wndParent = core_api::get_main_window(); + const auto wndParent = core_api::get_main_window(); // Filter object that applies our edits to the file tags auto filter = fb2k::service_new(); @@ -51,6 +51,7 @@ static void RunAlterTags(metadb_handle_list_cref data) { // Simple context menu item class. class myitem : public contextmenu_item_simple { + typedef contextmenu_item_simple super_t; public: enum { cmd_test1 = 0, @@ -102,14 +103,14 @@ class myitem : public contextmenu_item_simple { bool context_get_display(unsigned p_index,metadb_handle_list_cref p_data,pfc::string_base & p_out,unsigned & p_displayflags,const GUID & p_caller) { switch(p_index) { case cmd_test1: - if (!__super::context_get_display(p_index, p_data, p_out, p_displayflags, p_caller)) return false; + if (!super_t::context_get_display(p_index, p_data, p_out, p_displayflags, p_caller)) return false; // Example context sensitive label: append the count of selected items to the label. p_out << " : " << p_data.get_count() << " item"; if (p_data.get_count() != 1) p_out << "s"; p_out << " selected"; return true; default: - return __super::context_get_display(p_index, p_data, p_out, p_displayflags, p_caller); + return super_t::context_get_display(p_index, p_data, p_out, p_displayflags, p_caller); } } GUID get_item_guid(unsigned p_index) { diff --git a/3rdparty/foo_SDK/foobar2000/foo_sample/decode.cpp b/3rdparty/foo_SDK/foobar2000/foo_sample/decode.cpp index 1f4ab1d9..c2536ec7 100644 --- a/3rdparty/foo_SDK/foobar2000/foo_sample/decode.cpp +++ b/3rdparty/foo_SDK/foobar2000/foo_sample/decode.cpp @@ -4,8 +4,8 @@ class calculate_peak_process : public threaded_process_callback { public: calculate_peak_process(metadb_handle_list_cref items) : m_items(items), m_peak() {} - void on_init(HWND p_wnd) {} - void run(threaded_process_status & p_status,abort_callback & p_abort) { + void on_init(ctx_t p_wnd) override {} + void run(threaded_process_status & p_status,abort_callback & p_abort) override { try { const t_uint32 decode_flags = input_flag_no_seeking | input_flag_no_looping; // tell the decoders that we won't seek and that we don't want looping on formats that support looping. input_helper input; // this object manages lowlevel input_decoder calls for us. @@ -41,7 +41,7 @@ class calculate_peak_process : public threaded_process_callback { m_failMsg = e.what(); } } - void on_done(HWND p_wnd,bool p_was_aborted) { + void on_done(ctx_t p_wnd,bool p_was_aborted) override { if (!p_was_aborted) { if (!m_failMsg.is_empty()) { popup_message::g_complain("Peak scan failure", m_failMsg); diff --git a/3rdparty/foo_SDK/foobar2000/foo_sample/dsp.cpp b/3rdparty/foo_SDK/foobar2000/foo_sample/dsp_sample.cpp similarity index 85% rename from 3rdparty/foo_SDK/foobar2000/foo_sample/dsp.cpp rename to 3rdparty/foo_SDK/foobar2000/foo_sample/dsp_sample.cpp index 2b49e3dc..9514ef5d 100644 --- a/3rdparty/foo_SDK/foobar2000/foo_sample/dsp.cpp +++ b/3rdparty/foo_SDK/foobar2000/foo_sample/dsp_sample.cpp @@ -1,13 +1,22 @@ #include "stdafx.h" +#include "dsp_sample.h" + +#ifdef _WIN32 +#include #include "resource.h" static void RunDSPConfigPopup(const dsp_preset & p_data,HWND p_parent,dsp_preset_edit_callback & p_callback); +#endif + +#ifdef __APPLE__ +// fooSampleDSPView.mm +service_ptr ConfigureSampleDSP( fb2k::hwnd_t parent, dsp_preset_edit_callback_v2::ptr callback ); +#endif class dsp_sample : public dsp_impl_base { public: - dsp_sample(dsp_preset const & in) : m_gain(0) { - parse_preset(m_gain, in); + dsp_sample(dsp_preset const & in) : m_gain(parse_preset(in)) { } static GUID g_get_guid() { @@ -62,18 +71,17 @@ class dsp_sample : public dsp_impl_base make_preset(0, p_out); return true; } +#ifdef _WIN32 static void g_show_config_popup(const dsp_preset & p_data,HWND p_parent,dsp_preset_edit_callback & p_callback) { ::RunDSPConfigPopup(p_data, p_parent, p_callback); } +#endif // _WIN32 +#ifdef __APPLE__ + static service_ptr g_show_config_popup( fb2k::hwnd_t parent, dsp_preset_edit_callback_v2::ptr callback ) { + return ConfigureSampleDSP( parent, callback ); + } +#endif // __APPLE__ static bool g_have_config_popup() {return true;} - static void make_preset(float gain, dsp_preset & out) { - dsp_preset_builder builder; builder << gain; builder.finish(g_get_guid(), out); - } - static void parse_preset(float & gain, const dsp_preset & in) { - try { - dsp_preset_parser parser(in); parser >> gain; - } catch(exception_io_data) {gain = 0;} - } private: float m_gain; }; @@ -81,6 +89,7 @@ class dsp_sample : public dsp_impl_base // Use dsp_factory_nopreset_t<> instead of dsp_factory_t<> if your DSP does not provide preset/configuration functionality. static dsp_factory_t g_dsp_sample_factory; +#ifdef _WIN32 class CMyDSPPopup : public CDialogImpl { public: @@ -105,12 +114,12 @@ class CMyDSPPopup : public CDialogImpl { private: BOOL OnInitDialog(CWindow, LPARAM) { + m_dark.AddDialogWithControls(m_hWnd); m_slider = GetDlgItem(IDC_SLIDER); m_slider.SetRange(0, RangeTotal); { - float val; - dsp_sample::parse_preset(val, m_initData); + float val = parse_preset(m_initData); m_slider.SetPos( pfc::clip_t( pfc::rint32(val), RangeMin, RangeMax ) - RangeMin ); RefreshLabel(val); } @@ -127,7 +136,7 @@ class CMyDSPPopup : public CDialogImpl { { dsp_preset_impl preset; - dsp_sample::make_preset(val, preset); + make_preset(val, preset); m_callback.on_preset_changed(preset); } RefreshLabel(val); @@ -142,6 +151,7 @@ class CMyDSPPopup : public CDialogImpl { dsp_preset_edit_callback & m_callback; CTrackBarCtrl m_slider; + fb2k::CDarkModeHooks m_dark; }; static void RunDSPConfigPopup(const dsp_preset & p_data,HWND p_parent,dsp_preset_edit_callback & p_callback) { @@ -152,3 +162,4 @@ static void RunDSPConfigPopup(const dsp_preset & p_data,HWND p_parent,dsp_preset p_callback.on_preset_changed(p_data); } } +#endif diff --git a/3rdparty/foo_SDK/foobar2000/foo_sample/dsp_sample.h b/3rdparty/foo_SDK/foobar2000/foo_sample/dsp_sample.h new file mode 100644 index 00000000..b0d6a2fc --- /dev/null +++ b/3rdparty/foo_SDK/foobar2000/foo_sample/dsp_sample.h @@ -0,0 +1,19 @@ +#pragma once + +namespace dsp_sample_common { + static constexpr GUID guid = { 0x890827b, 0x67df, 0x4c27, { 0xba, 0x1a, 0x4f, 0x95, 0x8d, 0xf, 0xb5, 0xd0 } }; + + static void make_preset(float gain, dsp_preset & out) { + dsp_preset_builder builder; builder << gain; builder.finish(guid, out); + } + static float parse_preset(const dsp_preset & in) { + try { + float gain; + dsp_preset_parser parser(in); parser >> gain; + return gain; + } catch(exception_io_data const &) {return 0;} + } + +} + +using namespace dsp_sample_common; diff --git a/3rdparty/foo_SDK/foobar2000/foo_sample/foo_sample.vcxproj b/3rdparty/foo_SDK/foobar2000/foo_sample/foo_sample.vcxproj index 7ac8e6da..dc4de5cf 100644 --- a/3rdparty/foo_SDK/foobar2000/foo_sample/foo_sample.vcxproj +++ b/3rdparty/foo_SDK/foobar2000/foo_sample/foo_sample.vcxproj @@ -191,7 +191,6 @@ true Windows - false ../shared/shared-$(Platform).lib @@ -214,7 +213,6 @@ true Windows - false ../shared/shared-$(Platform).lib @@ -299,7 +297,6 @@ Windows true true - false ../shared/shared-$(Platform).lib @@ -327,7 +324,6 @@ Windows true true - false ../shared/shared-$(Platform).lib @@ -336,7 +332,7 @@ - + @@ -365,6 +361,7 @@ + @@ -393,6 +390,5 @@ - - + \ No newline at end of file diff --git a/3rdparty/foo_SDK/foobar2000/foo_sample/foo_sample.vcxproj.filters b/3rdparty/foo_SDK/foobar2000/foo_sample/foo_sample.vcxproj.filters index c9aa4183..158409bd 100644 --- a/3rdparty/foo_SDK/foobar2000/foo_sample/foo_sample.vcxproj.filters +++ b/3rdparty/foo_SDK/foobar2000/foo_sample/foo_sample.vcxproj.filters @@ -21,9 +21,6 @@ Source Files - - Source Files - Source Files @@ -75,6 +72,9 @@ Source Files + + Source Files + @@ -86,6 +86,9 @@ Header Files + + Header Files + diff --git a/3rdparty/foo_SDK/foobar2000/foo_sample/foo_sample.xcodeproj/project.pbxproj b/3rdparty/foo_SDK/foobar2000/foo_sample/foo_sample.xcodeproj/project.pbxproj new file mode 100644 index 00000000..c52e3f3a --- /dev/null +++ b/3rdparty/foo_SDK/foobar2000/foo_sample/foo_sample.xcodeproj/project.pbxproj @@ -0,0 +1,447 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 54; + objects = { + +/* Begin PBXBuildFile section */ + 0F1FDDBA2AA0ADDF00DE8967 /* initquit.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F1FDDB62AA0ADDF00DE8967 /* initquit.cpp */; }; + 0F1FDDBB2AA0ADDF00DE8967 /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F1FDDB72AA0ADDF00DE8967 /* main.cpp */; }; + 0F1FDDC02AA0AE1E00DE8967 /* libfoobar2000_SDK.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 0F1FDDBD2AA0AE1E00DE8967 /* libfoobar2000_SDK.a */; }; + 0F1FDDC12AA0AE1E00DE8967 /* libfoobar2000_SDK_helpers.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 0F1FDDBE2AA0AE1E00DE8967 /* libfoobar2000_SDK_helpers.a */; }; + 0F1FDDC22AA0AE1E00DE8967 /* libpfc-Mac.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 0F1FDDBF2AA0AE1E00DE8967 /* libpfc-Mac.a */; }; + 0F1FDDC82AA0B1F800DE8967 /* libshared.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 0F1FDDC72AA0B1F800DE8967 /* libshared.a */; }; + 0F1FDDCA2AA0B1FE00DE8967 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0F1FDDC92AA0B1FE00DE8967 /* Cocoa.framework */; }; + 0F1FDDDE2AA0B34200DE8967 /* libfoobar2000_component_client.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 0F1FDDDD2AA0B34200DE8967 /* libfoobar2000_component_client.a */; }; + 0F62440A2AA1E59E004FEC96 /* preferences.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F6244072AA1E4F4004FEC96 /* preferences.cpp */; }; + 0F6D10F12AA3C35C00774EED /* fooDecibelFormatter.m in Sources */ = {isa = PBXBuildFile; fileRef = 0F6D10EF2AA3C35C00774EED /* fooDecibelFormatter.m */; }; + 0FBE14512AA1E85F00B1F71E /* NSView+embed.m in Sources */ = {isa = PBXBuildFile; fileRef = 0FBE14452AA1E85F00B1F71E /* NSView+embed.m */; }; + 0FBE14552AA1E8C800B1F71E /* fooSampleMacPreferences.mm in Sources */ = {isa = PBXBuildFile; fileRef = 0FBE14532AA1E8C800B1F71E /* fooSampleMacPreferences.mm */; }; + 0FBE14562AA1E8C800B1F71E /* fooSampleMacPreferences.xib in Resources */ = {isa = PBXBuildFile; fileRef = 0FBE14542AA1E8C800B1F71E /* fooSampleMacPreferences.xib */; }; + 0FBE14622AA1F74200B1F71E /* rating.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FBE14582AA1F74200B1F71E /* rating.cpp */; }; + 0FBE14632AA1F74200B1F71E /* contextmenu.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FBE14592AA1F74200B1F71E /* contextmenu.cpp */; }; + 0FBE14642AA1F74200B1F71E /* input_raw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FBE145A2AA1F74200B1F71E /* input_raw.cpp */; }; + 0FBE14652AA1F74200B1F71E /* decode.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FBE145B2AA1F74200B1F71E /* decode.cpp */; }; + 0FBE14662AA1F74200B1F71E /* dsp_sample.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FBE145C2AA1F74200B1F71E /* dsp_sample.cpp */; }; + 0FBE14672AA1F74200B1F71E /* mainmenu-dynamic.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FBE145D2AA1F74200B1F71E /* mainmenu-dynamic.cpp */; }; + 0FBE14692AA1F74200B1F71E /* IO.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FBE145F2AA1F74200B1F71E /* IO.cpp */; }; + 0FBE146A2AA1F74200B1F71E /* playback_stream_capture.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FBE14602AA1F74200B1F71E /* playback_stream_capture.cpp */; }; + 0FBE146C2AA1FF1500B1F71E /* ui_and_threads.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FBE146B2AA1FF1500B1F71E /* ui_and_threads.cpp */; }; + 0FCA71142AA21F69001CB0F2 /* fooSampleDSPView.mm in Sources */ = {isa = PBXBuildFile; fileRef = 0FCA71122AA21F69001CB0F2 /* fooSampleDSPView.mm */; }; + 0FCA71152AA21F69001CB0F2 /* fooSampleDSPView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 0FCA71132AA21F69001CB0F2 /* fooSampleDSPView.xib */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 0F1FDDAD2AA0AD9B00DE8967 /* foo_sample.component */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = foo_sample.component; sourceTree = BUILT_PRODUCTS_DIR; }; + 0F1FDDB42AA0ADDF00DE8967 /* mainmenu.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = mainmenu.cpp; sourceTree = ""; }; + 0F1FDDB52AA0ADDF00DE8967 /* playback_state.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = playback_state.cpp; sourceTree = ""; }; + 0F1FDDB62AA0ADDF00DE8967 /* initquit.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = initquit.cpp; sourceTree = ""; }; + 0F1FDDB72AA0ADDF00DE8967 /* main.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = main.cpp; sourceTree = ""; }; + 0F1FDDBD2AA0AE1E00DE8967 /* libfoobar2000_SDK.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; path = libfoobar2000_SDK.a; sourceTree = BUILT_PRODUCTS_DIR; }; + 0F1FDDBE2AA0AE1E00DE8967 /* libfoobar2000_SDK_helpers.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; path = libfoobar2000_SDK_helpers.a; sourceTree = BUILT_PRODUCTS_DIR; }; + 0F1FDDBF2AA0AE1E00DE8967 /* libpfc-Mac.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; path = "libpfc-Mac.a"; sourceTree = BUILT_PRODUCTS_DIR; }; + 0F1FDDC62AA0AF8400DE8967 /* stdafx.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = stdafx.h; sourceTree = ""; }; + 0F1FDDC72AA0B1F800DE8967 /* libshared.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; path = libshared.a; sourceTree = BUILT_PRODUCTS_DIR; }; + 0F1FDDC92AA0B1FE00DE8967 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; }; + 0F1FDDDD2AA0B34200DE8967 /* libfoobar2000_component_client.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; path = libfoobar2000_component_client.a; sourceTree = BUILT_PRODUCTS_DIR; }; + 0F6244072AA1E4F4004FEC96 /* preferences.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = preferences.cpp; sourceTree = ""; }; + 0F6D10EF2AA3C35C00774EED /* fooDecibelFormatter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = fooDecibelFormatter.m; sourceTree = ""; }; + 0F6D10F02AA3C35C00774EED /* fooDecibelFormatter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fooDecibelFormatter.h; sourceTree = ""; }; + 0FBE14402AA1E85F00B1F71E /* NSView+embed.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSView+embed.h"; sourceTree = ""; }; + 0FBE14452AA1E85F00B1F71E /* NSView+embed.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSView+embed.m"; sourceTree = ""; }; + 0FBE14522AA1E8C800B1F71E /* fooSampleMacPreferences.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = fooSampleMacPreferences.h; sourceTree = ""; }; + 0FBE14532AA1E8C800B1F71E /* fooSampleMacPreferences.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = fooSampleMacPreferences.mm; sourceTree = ""; }; + 0FBE14542AA1E8C800B1F71E /* fooSampleMacPreferences.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = fooSampleMacPreferences.xib; sourceTree = ""; }; + 0FBE14582AA1F74200B1F71E /* rating.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = rating.cpp; sourceTree = ""; }; + 0FBE14592AA1F74200B1F71E /* contextmenu.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = contextmenu.cpp; sourceTree = ""; }; + 0FBE145A2AA1F74200B1F71E /* input_raw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = input_raw.cpp; sourceTree = ""; }; + 0FBE145B2AA1F74200B1F71E /* decode.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = decode.cpp; sourceTree = ""; }; + 0FBE145C2AA1F74200B1F71E /* dsp_sample.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = dsp_sample.cpp; sourceTree = ""; }; + 0FBE145D2AA1F74200B1F71E /* mainmenu-dynamic.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "mainmenu-dynamic.cpp"; sourceTree = ""; }; + 0FBE145E2AA1F74200B1F71E /* readme.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = readme.txt; sourceTree = ""; }; + 0FBE145F2AA1F74200B1F71E /* IO.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = IO.cpp; sourceTree = ""; }; + 0FBE14602AA1F74200B1F71E /* playback_stream_capture.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = playback_stream_capture.cpp; sourceTree = ""; }; + 0FBE14612AA1F74200B1F71E /* playback_stream_capture.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = playback_stream_capture.h; sourceTree = ""; }; + 0FBE146B2AA1FF1500B1F71E /* ui_and_threads.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ui_and_threads.cpp; sourceTree = ""; }; + 0FCA71112AA21F69001CB0F2 /* fooSampleDSPView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = fooSampleDSPView.h; sourceTree = ""; }; + 0FCA71122AA21F69001CB0F2 /* fooSampleDSPView.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = fooSampleDSPView.mm; sourceTree = ""; }; + 0FCA71132AA21F69001CB0F2 /* fooSampleDSPView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = fooSampleDSPView.xib; sourceTree = ""; }; + 0FD323BF2AA3C45C00C0C2F7 /* dsp_sample.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = dsp_sample.h; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 0F1FDDAA2AA0AD9B00DE8967 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 0F1FDDDE2AA0B34200DE8967 /* libfoobar2000_component_client.a in Frameworks */, + 0F1FDDCA2AA0B1FE00DE8967 /* Cocoa.framework in Frameworks */, + 0F1FDDC82AA0B1F800DE8967 /* libshared.a in Frameworks */, + 0F1FDDC02AA0AE1E00DE8967 /* libfoobar2000_SDK.a in Frameworks */, + 0F1FDDC12AA0AE1E00DE8967 /* libfoobar2000_SDK_helpers.a in Frameworks */, + 0F1FDDC22AA0AE1E00DE8967 /* libpfc-Mac.a in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 0F1FDDA42AA0AD9B00DE8967 = { + isa = PBXGroup; + children = ( + 0FBE146B2AA1FF1500B1F71E /* ui_and_threads.cpp */, + 0FBE14592AA1F74200B1F71E /* contextmenu.cpp */, + 0FBE145B2AA1F74200B1F71E /* decode.cpp */, + 0FBE145C2AA1F74200B1F71E /* dsp_sample.cpp */, + 0FD323BF2AA3C45C00C0C2F7 /* dsp_sample.h */, + 0FBE145A2AA1F74200B1F71E /* input_raw.cpp */, + 0FBE145F2AA1F74200B1F71E /* IO.cpp */, + 0FBE145D2AA1F74200B1F71E /* mainmenu-dynamic.cpp */, + 0FBE14602AA1F74200B1F71E /* playback_stream_capture.cpp */, + 0FBE14612AA1F74200B1F71E /* playback_stream_capture.h */, + 0FBE14582AA1F74200B1F71E /* rating.cpp */, + 0FBE145E2AA1F74200B1F71E /* readme.txt */, + 0FBE14572AA1F41A00B1F71E /* Mac */, + 0F6244072AA1E4F4004FEC96 /* preferences.cpp */, + 0F1FDDC62AA0AF8400DE8967 /* stdafx.h */, + 0F1FDDB62AA0ADDF00DE8967 /* initquit.cpp */, + 0F1FDDB72AA0ADDF00DE8967 /* main.cpp */, + 0F1FDDB42AA0ADDF00DE8967 /* mainmenu.cpp */, + 0F1FDDB52AA0ADDF00DE8967 /* playback_state.cpp */, + 0FBE14362AA1E85F00B1F71E /* helpers-mac */, + 0F1FDDAE2AA0AD9B00DE8967 /* Products */, + 0F1FDDBC2AA0AE1E00DE8967 /* Frameworks */, + ); + sourceTree = ""; + }; + 0F1FDDAE2AA0AD9B00DE8967 /* Products */ = { + isa = PBXGroup; + children = ( + 0F1FDDAD2AA0AD9B00DE8967 /* foo_sample.component */, + ); + name = Products; + sourceTree = ""; + }; + 0F1FDDBC2AA0AE1E00DE8967 /* Frameworks */ = { + isa = PBXGroup; + children = ( + 0F1FDDDD2AA0B34200DE8967 /* libfoobar2000_component_client.a */, + 0F1FDDC92AA0B1FE00DE8967 /* Cocoa.framework */, + 0F1FDDC72AA0B1F800DE8967 /* libshared.a */, + 0F1FDDBD2AA0AE1E00DE8967 /* libfoobar2000_SDK.a */, + 0F1FDDBE2AA0AE1E00DE8967 /* libfoobar2000_SDK_helpers.a */, + 0F1FDDBF2AA0AE1E00DE8967 /* libpfc-Mac.a */, + ); + name = Frameworks; + sourceTree = ""; + }; + 0FBE14362AA1E85F00B1F71E /* helpers-mac */ = { + isa = PBXGroup; + children = ( + 0F6D10F02AA3C35C00774EED /* fooDecibelFormatter.h */, + 0F6D10EF2AA3C35C00774EED /* fooDecibelFormatter.m */, + 0FBE14402AA1E85F00B1F71E /* NSView+embed.h */, + 0FBE14452AA1E85F00B1F71E /* NSView+embed.m */, + ); + name = "helpers-mac"; + path = "../helpers-mac"; + sourceTree = ""; + }; + 0FBE14572AA1F41A00B1F71E /* Mac */ = { + isa = PBXGroup; + children = ( + 0FBE14522AA1E8C800B1F71E /* fooSampleMacPreferences.h */, + 0FBE14532AA1E8C800B1F71E /* fooSampleMacPreferences.mm */, + 0FBE14542AA1E8C800B1F71E /* fooSampleMacPreferences.xib */, + 0FCA71112AA21F69001CB0F2 /* fooSampleDSPView.h */, + 0FCA71122AA21F69001CB0F2 /* fooSampleDSPView.mm */, + 0FCA71132AA21F69001CB0F2 /* fooSampleDSPView.xib */, + ); + path = Mac; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 0F1FDDAC2AA0AD9B00DE8967 /* foo_sample */ = { + isa = PBXNativeTarget; + buildConfigurationList = 0F1FDDB12AA0AD9B00DE8967 /* Build configuration list for PBXNativeTarget "foo_sample" */; + buildPhases = ( + 0F1FDDA92AA0AD9B00DE8967 /* Sources */, + 0F1FDDAA2AA0AD9B00DE8967 /* Frameworks */, + 0F1FDDAB2AA0AD9B00DE8967 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = foo_sample; + productName = foo_sample; + productReference = 0F1FDDAD2AA0AD9B00DE8967 /* foo_sample.component */; + productType = "com.apple.product-type.bundle"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 0F1FDDA52AA0AD9B00DE8967 /* Project object */ = { + isa = PBXProject; + attributes = { + BuildIndependentTargetsInParallel = 1; + LastUpgradeCheck = 1500; + TargetAttributes = { + 0F1FDDAC2AA0AD9B00DE8967 = { + CreatedOnToolsVersion = 14.3.1; + }; + }; + }; + buildConfigurationList = 0F1FDDA82AA0AD9B00DE8967 /* Build configuration list for PBXProject "foo_sample" */; + compatibilityVersion = "Xcode 12.0"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 0F1FDDA42AA0AD9B00DE8967; + productRefGroup = 0F1FDDAE2AA0AD9B00DE8967 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 0F1FDDAC2AA0AD9B00DE8967 /* foo_sample */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 0F1FDDAB2AA0AD9B00DE8967 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 0FBE14562AA1E8C800B1F71E /* fooSampleMacPreferences.xib in Resources */, + 0FCA71152AA21F69001CB0F2 /* fooSampleDSPView.xib in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 0F1FDDA92AA0AD9B00DE8967 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 0FBE14692AA1F74200B1F71E /* IO.cpp in Sources */, + 0FBE14552AA1E8C800B1F71E /* fooSampleMacPreferences.mm in Sources */, + 0FBE14672AA1F74200B1F71E /* mainmenu-dynamic.cpp in Sources */, + 0FBE14512AA1E85F00B1F71E /* NSView+embed.m in Sources */, + 0FBE14632AA1F74200B1F71E /* contextmenu.cpp in Sources */, + 0FCA71142AA21F69001CB0F2 /* fooSampleDSPView.mm in Sources */, + 0FBE14652AA1F74200B1F71E /* decode.cpp in Sources */, + 0F6D10F12AA3C35C00774EED /* fooDecibelFormatter.m in Sources */, + 0FBE146C2AA1FF1500B1F71E /* ui_and_threads.cpp in Sources */, + 0FBE14662AA1F74200B1F71E /* dsp_sample.cpp in Sources */, + 0F1FDDBB2AA0ADDF00DE8967 /* main.cpp in Sources */, + 0FBE14642AA1F74200B1F71E /* input_raw.cpp in Sources */, + 0F62440A2AA1E59E004FEC96 /* preferences.cpp in Sources */, + 0F1FDDBA2AA0ADDF00DE8967 /* initquit.cpp in Sources */, + 0FBE14622AA1F74200B1F71E /* rating.cpp in Sources */, + 0FBE146A2AA1F74200B1F71E /* playback_stream_capture.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 0F1FDDAF2AA0AD9B00DE8967 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEAD_CODE_STRIPPING = YES; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = stdafx.h; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + HEADER_SEARCH_PATHS = ( + .., + ../.., + ); + MACOSX_DEPLOYMENT_TARGET = 10.13; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + }; + name = Debug; + }; + 0F1FDDB02AA0AD9B00DE8967 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEAD_CODE_STRIPPING = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = stdafx.h; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + HEADER_SEARCH_PATHS = ( + .., + ../.., + ); + MACOSX_DEPLOYMENT_TARGET = 10.13; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + SDKROOT = macosx; + }; + name = Release; + }; + 0F1FDDB22AA0AD9B00DE8967 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + "CODE_SIGN_IDENTITY[sdk=macosx*]" = "-"; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + CURRENT_PROJECT_VERSION = 1; + DEAD_CODE_STRIPPING = YES; + DEVELOPMENT_TEAM = ""; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_KEY_NSHumanReadableCopyright = ""; + INFOPLIST_KEY_NSPrincipalClass = ""; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Bundles"; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = "com.foobar2000.foo-sample"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = YES; + WRAPPER_EXTENSION = component; + }; + name = Debug; + }; + 0F1FDDB32AA0AD9B00DE8967 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + "CODE_SIGN_IDENTITY[sdk=macosx*]" = "-"; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + CURRENT_PROJECT_VERSION = 1; + DEAD_CODE_STRIPPING = YES; + DEVELOPMENT_TEAM = ""; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_KEY_NSHumanReadableCopyright = ""; + INFOPLIST_KEY_NSPrincipalClass = ""; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Bundles"; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = "com.foobar2000.foo-sample"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = YES; + WRAPPER_EXTENSION = component; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 0F1FDDA82AA0AD9B00DE8967 /* Build configuration list for PBXProject "foo_sample" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 0F1FDDAF2AA0AD9B00DE8967 /* Debug */, + 0F1FDDB02AA0AD9B00DE8967 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 0F1FDDB12AA0AD9B00DE8967 /* Build configuration list for PBXNativeTarget "foo_sample" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 0F1FDDB22AA0AD9B00DE8967 /* Debug */, + 0F1FDDB32AA0AD9B00DE8967 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 0F1FDDA52AA0AD9B00DE8967 /* Project object */; +} diff --git a/3rdparty/foo_SDK/foobar2000/foo_sample/foo_sample.xcworkspace/contents.xcworkspacedata b/3rdparty/foo_SDK/foobar2000/foo_sample/foo_sample.xcworkspace/contents.xcworkspacedata new file mode 100644 index 00000000..be803c31 --- /dev/null +++ b/3rdparty/foo_SDK/foobar2000/foo_sample/foo_sample.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + diff --git a/3rdparty/foo_SDK/foobar2000/foo_sample/initquit.cpp b/3rdparty/foo_SDK/foobar2000/foo_sample/initquit.cpp index bcd131b3..62ddeb85 100644 --- a/3rdparty/foo_SDK/foobar2000/foo_sample/initquit.cpp +++ b/3rdparty/foo_SDK/foobar2000/foo_sample/initquit.cpp @@ -1,15 +1,17 @@ #include "stdafx.h" -// Sample initquit implementation. See also: initquit class documentation in relevant header. +namespace { + // Sample initquit implementation. See also: initquit class documentation in relevant header. + class myinitquit : public initquit { + public: + void on_init() { + console::print("Sample component: on_init()"); + } + void on_quit() { + console::print("Sample component: on_quit()"); + } + }; -class myinitquit : public initquit { -public: - void on_init() { - console::print("Sample component: on_init()"); - } - void on_quit() { - console::print("Sample component: on_quit()"); - } -}; + FB2K_SERVICE_FACTORY( myinitquit ); -static initquit_factory_t g_myinitquit_factory; +} // namespace diff --git a/3rdparty/foo_SDK/foobar2000/foo_sample/main.cpp b/3rdparty/foo_SDK/foobar2000/foo_sample/main.cpp index 44a6e319..bd4c0ca4 100644 --- a/3rdparty/foo_SDK/foobar2000/foo_sample/main.cpp +++ b/3rdparty/foo_SDK/foobar2000/foo_sample/main.cpp @@ -9,3 +9,6 @@ DECLARE_COMPONENT_VERSION("Sample Component","1.0","about message goes here"); // This will prevent users from renaming your component around (important for proper troubleshooter behaviors) or loading multiple instances of it. VALIDATE_COMPONENT_FILENAME("foo_sample.dll"); + +// Activate cfg_var downgrade functionality if enabled. Relevant only when cycling from newer FOOBAR2000_TARGET_VERSION to older. +FOOBAR2000_IMPLEMENT_CFG_VAR_DOWNGRADE; diff --git a/3rdparty/foo_SDK/foobar2000/foo_sample/mainmenu-dynamic.cpp b/3rdparty/foo_SDK/foobar2000/foo_sample/mainmenu-dynamic.cpp index a3abad72..62432664 100644 --- a/3rdparty/foo_SDK/foobar2000/foo_sample/mainmenu-dynamic.cpp +++ b/3rdparty/foo_SDK/foobar2000/foo_sample/mainmenu-dynamic.cpp @@ -44,7 +44,7 @@ class sample_command : public mainmenu_node_command { // fb2k hasher_md5 API even provides a convenient method to return MD5 hashes cast to GUIDs for this. return api->get_result_guid( state ); } - bool get_description(pfc::string_base & out) { + bool get_description(pfc::string_base & out) override { out = PFC_string_formatter() << "This is a test menu item #" << m_index << "."; return true; } @@ -84,6 +84,7 @@ class sample_group : public mainmenu_node_group { }; class mainmenu_sample_dynamic : public mainmenu_commands_v2 { + typedef mainmenu_commands_v2 super_t; public: // mainmenu_commands_v2 methods t_uint32 get_command_count() override { return 1; } @@ -111,10 +112,10 @@ class mainmenu_sample_dynamic : public mainmenu_commands_v2 { // please implement it here. // ... or just skip implementing this method entirely. - return __super::dynamic_execute( index, subID, callback ); + return super_t::dynamic_execute( index, subID, callback ); } }; static service_factory_single_t g_mainmenu_sample_dynamic; -} // namespace \ No newline at end of file +} // namespace diff --git a/3rdparty/foo_SDK/foobar2000/foo_sample/mainmenu.cpp b/3rdparty/foo_SDK/foobar2000/foo_sample/mainmenu.cpp index da54fe7b..8ab8327c 100644 --- a/3rdparty/foo_SDK/foobar2000/foo_sample/mainmenu.cpp +++ b/3rdparty/foo_SDK/foobar2000/foo_sample/mainmenu.cpp @@ -106,7 +106,7 @@ class mainmenu_commands_sample : public mainmenu_commands { } bool get_display(t_uint32 p_index,pfc::string_base & p_text,t_uint32 & p_flags) override { // OPTIONAL method - bool rv = __super::get_display(p_index, p_text, p_flags); + bool rv = mainmenu_commands::get_display(p_index, p_text, p_flags); if (rv) switch(p_index) { case cmd_playback_stream_capture: // Add checkmark if capture is in progress diff --git a/3rdparty/foo_SDK/foobar2000/foo_sample/playback_stream_capture.cpp b/3rdparty/foo_SDK/foobar2000/foo_sample/playback_stream_capture.cpp index 51cf587a..30cf4713 100644 --- a/3rdparty/foo_SDK/foobar2000/foo_sample/playback_stream_capture.cpp +++ b/3rdparty/foo_SDK/foobar2000/foo_sample/playback_stream_capture.cpp @@ -27,9 +27,8 @@ namespace { if (!g_wav_writer.is_open() && ! core_api::is_shutting_down() ) { wav_writer_setup setup; setup.initialize(chunk, 16, false, false); - GUID g; CoCreateGuid(&g); pfc::string_formatter fn; - fn << "capture-" << pfc::print_guid(g) << ".wav"; + fn << "capture-" << pfc::print_guid(pfc::createGUID()) << ".wav"; pfc::string_formatter path = g_outputPath; path.add_filename( fn ); // pretty method to add file path components with auto inserted delimiter g_wav_writer.open(path, setup, abort); @@ -99,7 +98,25 @@ namespace { FB2K_SERVICE_FACTORY( play_callback_psc ); } +static void startCaptureDialogReply( fb2k::arrayRef location ) { + if ( g_active ) return; // already capturing + if ( location.is_empty() ) return; + if ( location->size() != 1 ) return; + auto obj = location->itemAt(0); + fsItemFolderPtr folder; + fb2k::stringRef strFolder; + if ( strFolder &= obj ) { + // OK + } else if ( folder &= obj ) { + strFolder = folder->canonicalPath(); + } + if ( strFolder.is_valid() ) { + g_outputPath = strFolder->c_str(); + StartCapture(); + } +} void ToggleCapture() { +#ifdef _WIN32 // Block modal dialog recursions. // Folder picker below is a modal dialog, don't ever call it if there's another modal dialog in progress. // Also prevents this function from recursing into itself if someone manages to hit the menu item while already picking folder. @@ -115,6 +132,16 @@ void ToggleCapture() { StartCapture(); } } +#else + if ( g_active ) { + StopCapture(); + } else { + auto dlg = fb2k::fileDialog::get()->setupOpenFolder(); + dlg->setTitle( "Choose output folder" ); + dlg->run( fb2k::fileDialogNotify::create( startCaptureDialogReply ) ); + } + +#endif } bool IsCaptureRunning() { diff --git a/3rdparty/foo_SDK/foobar2000/foo_sample/preferences.cpp b/3rdparty/foo_SDK/foobar2000/foo_sample/preferences.cpp index 97d68528..168a1647 100644 --- a/3rdparty/foo_SDK/foobar2000/foo_sample/preferences.cpp +++ b/3rdparty/foo_SDK/foobar2000/foo_sample/preferences.cpp @@ -1,9 +1,13 @@ #include "stdafx.h" -#include "resource.h" -#include + #include #include + +#ifdef _WIN32 +#include "resource.h" +#include #include +#endif // _WIN32 // Sample preferences interface: two meaningless configuration settings accessible through a preferences page and one accessible through advanced preferences. @@ -15,26 +19,58 @@ // These GUIDs identify the variables within our component's configuration file. -static const GUID guid_cfg_bogoSetting1 = { 0xbd5c777, 0x735c, 0x440d, { 0x8c, 0x71, 0x49, 0xb6, 0xac, 0xff, 0xce, 0xb8 } }; -static const GUID guid_cfg_bogoSetting2 = { 0x752f1186, 0x9f61, 0x4f91, { 0xb3, 0xee, 0x2f, 0x25, 0xb1, 0x24, 0x83, 0x5d } }; +static constexpr GUID guid_cfg_bogoSetting1 = { 0xbd5c777, 0x735c, 0x440d, { 0x8c, 0x71, 0x49, 0xb6, 0xac, 0xff, 0xce, 0xb8 } }; +static constexpr GUID guid_cfg_bogoSetting2 = { 0x752f1186, 0x9f61, 0x4f91, { 0xb3, 0xee, 0x2f, 0x25, 0xb1, 0x24, 0x83, 0x5d } }; // This GUID identifies our Advanced Preferences branch (replace with your own when reusing code). -static const GUID guid_advconfig_branch = { 0x28564ced, 0x4abf, 0x4f0c, { 0xa4, 0x43, 0x98, 0xda, 0x88, 0xe2, 0xcd, 0x39 } }; +static constexpr GUID guid_advconfig_branch = { 0x28564ced, 0x4abf, 0x4f0c, { 0xa4, 0x43, 0x98, 0xda, 0x88, 0xe2, 0xcd, 0x39 } }; // This GUID identifies our Advanced Preferences setting (replace with your own when reusing code) as well as this setting's storage within our component's configuration file. -static const GUID guid_cfg_bogoSetting3 = { 0xf7008963, 0xed60, 0x4084, { 0xa8, 0x5d, 0xd1, 0xcd, 0xc5, 0x51, 0x22, 0xca } }; +static constexpr GUID guid_cfg_bogoSetting3 = { 0xf7008963, 0xed60, 0x4084, { 0xa8, 0x5d, 0xd1, 0xcd, 0xc5, 0x51, 0x22, 0xca } }; +static constexpr GUID guid_cfg_bogoSetting4 = { 0x99e206f8, 0xd7be, 0x47e6, { 0xb5, 0xfe, 0xf4, 0x41, 0x5f, 0x6c, 0x16, 0xed } }; +static constexpr GUID guid_cfg_bogoSetting5 = { 0x7369ad25, 0x9e81, 0x4e2f, { 0x8b, 0xe7, 0x95, 0xcb, 0x81, 0x99, 0x9b, 0x1b } }; + +static constexpr GUID guid_cfg_bogoRadio = { 0x4c18b9ab, 0xf823, 0x4d05, { 0xb6, 0x18, 0x14, 0xb9, 0x4c, 0xad, 0xa2, 0xaa } }; +static constexpr GUID guid_cfg_bogoRadio1 = { 0xdd0a3a95, 0x1546, 0x4f25, { 0xa6, 0x8c, 0x23, 0xcf, 0x3d, 0xa5, 0x8f, 0x59 } }; +static constexpr GUID guid_cfg_bogoRadio2 = { 0xc35e1689, 0xb96f, 0x4bf4, { 0x95, 0xfb, 0xb7, 0x8e, 0x83, 0xc5, 0x2c, 0x7d } }; +static constexpr GUID guid_cfg_bogoRadio3 = { 0x790fe179, 0x9908, 0x47e2, { 0x9f, 0xde, 0xce, 0xe1, 0x3f, 0x9a, 0xfc, 0x5b } }; +// defaults +constexpr int default_cfg_bogo1 = 1337, + default_cfg_bogo2 = 666, + default_cfg_bogo3 = 42; +static constexpr char default_cfg_bogo4[] = "foobar"; +static constexpr bool default_cfg_bogo5 = false; + +// Advanced preferences order enum { - default_cfg_bogoSetting1 = 1337, - default_cfg_bogoSetting2 = 666, - default_cfg_bogoSetting3 = 42, + order_bogo3, + order_bogo4, + order_bogo5, + order_bogoRadio }; -static cfg_uint cfg_bogoSetting1(guid_cfg_bogoSetting1, default_cfg_bogoSetting1), cfg_bogoSetting2(guid_cfg_bogoSetting2, default_cfg_bogoSetting2); +enum { + order_bogoRadio1, + order_bogoRadio2, + order_bogoRadio3, +}; -static advconfig_branch_factory g_advconfigBranch("Sample Component", guid_advconfig_branch, advconfig_branch::guid_branch_tools, 0); -static advconfig_integer_factory cfg_bogoSetting3("Bogo setting 3", guid_cfg_bogoSetting3, guid_advconfig_branch, 0, default_cfg_bogoSetting3, 0 /*minimum value*/, 9999 /*maximum value*/); +namespace foo_sample { // accessed also from Mac specific code hence not static + cfg_uint cfg_bogoSetting1(guid_cfg_bogoSetting1, default_cfg_bogo1), cfg_bogoSetting2(guid_cfg_bogoSetting2, default_cfg_bogo2); +} +using namespace foo_sample; +static advconfig_branch_factory g_advconfigBranch("Sample Component", guid_advconfig_branch, advconfig_branch::guid_branch_tools, 0); +static advconfig_integer_factory cfg_bogoSetting3("Bogo setting 3","foo_sample.bogo3", guid_cfg_bogoSetting3, guid_advconfig_branch, order_bogo3, default_cfg_bogo3, 0 /*minimum value*/, 9999 /*maximum value*/); +static advconfig_string_factory cfg_bogoSetting4("Bogo setting 4", "foo_sample.bogo4", guid_cfg_bogoSetting4, guid_advconfig_branch, order_bogo4, default_cfg_bogo4); +static advconfig_checkbox_factory cfg_bogoSetting5("Bogo setting 5", "foo_sample.bogo5", guid_cfg_bogoSetting5, guid_advconfig_branch, order_bogo5, default_cfg_bogo5); +static advconfig_branch_factory cfg_bogoRadioBranch("Bogo radio", guid_cfg_bogoRadio, guid_advconfig_branch, order_bogoRadio); +static advconfig_radio_factory cfg_bogoRadio1("Radio 1", "foo_sample.bogoRaidio.1", guid_cfg_bogoRadio1, guid_cfg_bogoRadio, order_bogoRadio1, true); +static advconfig_radio_factory cfg_bogoRadio2("Radio 2", "foo_sample.bogoRaidio.2", guid_cfg_bogoRadio2, guid_cfg_bogoRadio, order_bogoRadio2, false); +static advconfig_radio_factory cfg_bogoRadio3("Radio 3", "foo_sample.bogoRaidio.3", guid_cfg_bogoRadio3, guid_cfg_bogoRadio, order_bogoRadio3, false); + +#ifdef _WIN32 class CMyPreferences : public CDialogImpl, public preferences_page_instance { public: //Constructor - invoked by preferences_page_impl helpers - don't do Create() in here, preferences_page_impl does this for us @@ -93,8 +129,8 @@ t_uint32 CMyPreferences::get_state() { } void CMyPreferences::reset() { - SetDlgItemInt(IDC_BOGO1, default_cfg_bogoSetting1, FALSE); - SetDlgItemInt(IDC_BOGO2, default_cfg_bogoSetting2, FALSE); + SetDlgItemInt(IDC_BOGO1, default_cfg_bogo1, FALSE); + SetDlgItemInt(IDC_BOGO2, default_cfg_bogo2, FALSE); OnChanged(); } @@ -120,10 +156,11 @@ class preferences_page_myimpl : public preferences_page_impl { const char * get_name() {return "Sample Component";} GUID get_guid() { // This is our GUID. Replace with your own when reusing the code. - static const GUID guid = { 0x7702c93e, 0x24dc, 0x48ed, { 0x8d, 0xb1, 0x3f, 0x27, 0xb3, 0x8c, 0x7c, 0xc9 } }; - return guid; + return GUID { 0x7702c93e, 0x24dc, 0x48ed, { 0x8d, 0xb1, 0x3f, 0x27, 0xb3, 0x8c, 0x7c, 0xc9 } }; } GUID get_parent_guid() {return guid_tools;} }; static preferences_page_factory_t g_preferences_page_myimpl_factory; +#endif // _WIN32 + diff --git a/3rdparty/foo_SDK/foobar2000/foo_sample/rating.cpp b/3rdparty/foo_SDK/foobar2000/foo_sample/rating.cpp index a57d9568..37b6912b 100644 --- a/3rdparty/foo_SDK/foobar2000/foo_sample/rating.cpp +++ b/3rdparty/foo_SDK/foobar2000/foo_sample/rating.cpp @@ -78,11 +78,10 @@ namespace { // Static cached ptr to metadb_index_manager // Cached because we'll be calling it a lot on per-track basis, let's not pass it everywhere to low level functions // Obtaining the pointer from core is reasonably efficient - log(n) to the number of known service classes, but not good enough for something potentially called hundreds of times - static metadb_index_manager::ptr g_cachedAPI; static metadb_index_manager::ptr theAPI() { - auto ret = g_cachedAPI; - if ( ret.is_empty() ) ret = metadb_index_manager::get(); // since fb2k SDK v1.4, core API interfaces have a static get() method - return ret; + // Raw ptr instead service_ptr, don't release on DLL unload, would cause issues + static metadb_index_manager * cached = metadb_index_manager::get().detach(); + return cached; } // An init_stage_callback to hook ourselves into the metadb @@ -91,8 +90,7 @@ namespace { public: void on_init_stage(t_uint32 stage) { if (stage == init_stages::before_config_read) { - auto api = metadb_index_manager::get(); - g_cachedAPI = api; + auto api = theAPI(); // Important, handle the exceptions here! // This will fail if the files holding our data are somehow corrupted. try { @@ -108,16 +106,8 @@ namespace { } } }; - class initquit_impl : public initquit { - public: - void on_quit() { - // Cleanly kill g_cachedAPI before reaching static object destructors or else - g_cachedAPI.release(); - } - }; static service_factory_single_t g_init_stage_callback_impl; - static service_factory_single_t g_initquit_impl; typedef uint32_t rating_t; static const rating_t rating_invalid = 0; diff --git a/3rdparty/foo_SDK/foobar2000/foo_sample/stdafx.h b/3rdparty/foo_SDK/foobar2000/foo_sample/stdafx.h index 46f3b55a..989b384e 100644 --- a/3rdparty/foo_SDK/foobar2000/foo_sample/stdafx.h +++ b/3rdparty/foo_SDK/foobar2000/foo_sample/stdafx.h @@ -1,2 +1,7 @@ +#ifdef __cplusplus #include +#endif +#ifdef __OBJC__ +#include +#endif diff --git a/3rdparty/foo_SDK/foobar2000/foo_sample/ui_and_threads.cpp b/3rdparty/foo_SDK/foobar2000/foo_sample/ui_and_threads.cpp index 970585b8..dcbf7bb8 100644 --- a/3rdparty/foo_SDK/foobar2000/foo_sample/ui_and_threads.cpp +++ b/3rdparty/foo_SDK/foobar2000/foo_sample/ui_and_threads.cpp @@ -4,6 +4,8 @@ // Modern multi threading with C++ // Or: how I learned to stop worrying and love the lambdas +#ifdef _WIN32 + #include // shared_ptr #include #include @@ -284,3 +286,11 @@ void RunUIAndThreads(metadb_handle_list_cref data) { // Equivalent to new CDemoDialog(data), with modeless registration and auto lifetime fb2k::newDialog( data ); } + +#else + +void RunUIAndThreads(metadb_handle_list_cref data) { + popup_message::g_showToast("Not implemented for Mac OS yet"); +} + +#endif diff --git a/3rdparty/foo_SDK/foobar2000/foobar2000_component_client/component_client.cpp b/3rdparty/foo_SDK/foobar2000/foobar2000_component_client/component_client.cpp index 6d0d6d89..7ad217a1 100644 --- a/3rdparty/foo_SDK/foobar2000/foobar2000_component_client/component_client.cpp +++ b/3rdparty/foo_SDK/foobar2000/foobar2000_component_client/component_client.cpp @@ -2,8 +2,9 @@ #include #include +#ifdef _WIN32 static HINSTANCE g_hIns; - +#endif static pfc::string_simple g_name,g_full_path; static bool g_services_available = false, g_initialized = false; @@ -13,12 +14,13 @@ static bool g_services_available = false, g_initialized = false; namespace core_api { +#ifdef _WIN32 HINSTANCE get_my_instance() { return g_hIns; } - - HWND get_main_window() +#endif + fb2k::hwnd_t get_main_window() { PFC_ASSERT( g_foobar2000_api != NULL ); return g_foobar2000_api->get_main_window(); @@ -79,43 +81,40 @@ namespace { class foobar2000_client_impl : public foobar2000_client, private foobar2000_component_globals { public: - t_uint32 get_version() {return FOOBAR2000_CLIENT_VERSION;} - pservice_factory_base get_service_list() {return service_factory_base::__internal__list;} + t_uint32 get_version() override {return FOOBAR2000_CLIENT_VERSION;} + pservice_factory_base get_service_list() override {return service_factory_base::__internal__list;} - void get_config(stream_writer * p_stream,abort_callback & p_abort) { + void get_config(stream_writer * p_stream,abort_callback & p_abort) override { #ifdef FOOBAR2000_HAVE_CFG_VAR_LEGACY cfg_var_legacy::cfg_var::config_write_file(p_stream,p_abort); #endif } - void set_config(stream_reader * p_stream,abort_callback & p_abort) { + void set_config(stream_reader * p_stream,abort_callback & p_abort) override { #ifdef FOOBAR2000_HAVE_CFG_VAR_LEGACY cfg_var_legacy::cfg_var::config_read_file(p_stream,p_abort); #endif } - void set_library_path(const char * path,const char * name) { + void set_library_path(const char * path,const char * name) override { g_full_path = path; g_name = name; } - void services_init(bool val) { + void services_init(bool val) override { if (val) g_initialized = true; g_services_available = val; } - bool is_debug() { -#ifdef _DEBUG - return true; -#else - return false; -#endif + bool is_debug() override { + return PFC_DEBUG != 0; } }; } static foobar2000_client_impl g_client; +#ifdef _WIN32 extern "C" { __declspec(dllexport) foobar2000_client * _cdecl foobar2000_get_interface(foobar2000_api * p_api,HINSTANCE hIns) @@ -126,3 +125,13 @@ extern "C" return &g_client; } } +#endif + +#ifdef __APPLE__ +extern "C" { + __attribute__ ((visibility ("default"))) foobar2000_client * foobar2000_get_interface(foobar2000_api * p_api, void * /*reserved*/) { + g_foobar2000_api = p_api; + return &g_client; + } +} +#endif diff --git a/3rdparty/foo_SDK/foobar2000/foobar2000_component_client/foobar2000_component_client.vcxproj b/3rdparty/foo_SDK/foobar2000/foobar2000_component_client/foobar2000_component_client.vcxproj index 73d2703a..86f86505 100644 --- a/3rdparty/foo_SDK/foobar2000/foobar2000_component_client/foobar2000_component_client.vcxproj +++ b/3rdparty/foo_SDK/foobar2000/foobar2000_component_client/foobar2000_component_client.vcxproj @@ -138,7 +138,7 @@ ProgramDatabase MultiThreadedDebugDLL 4715 - ../..;$(SolutionDir)/../3rdparty/foo_SDK/foobar2000;$(SolutionDir)/../3rdparty/WTL10_10320_Release/Include + ..;../.. true stdcpp17 @@ -161,7 +161,7 @@ ProgramDatabase MultiThreadedDebugDLL 4715 - ../..;$(SolutionDir)/../3rdparty/foo_SDK/foobar2000;$(SolutionDir)/../3rdparty/WTL10_10320_Release/Include + ..;../.. true stdcpp17 @@ -234,7 +234,7 @@ 4715 true NDEBUG;_UNICODE;UNICODE;%(PreprocessorDefinitions) - ../..;$(SolutionDir)/../3rdparty/foo_SDK/foobar2000;$(SolutionDir)/../3rdparty/WTL10_10320_Release/Include + ..;../.. true stdcpp17 @@ -261,7 +261,7 @@ 4715 true NDEBUG;_UNICODE;UNICODE;%(PreprocessorDefinitions) - ../..;$(SolutionDir)/../3rdparty/foo_SDK/foobar2000;$(SolutionDir)/../3rdparty/WTL10_10320_Release/Include + ..;../.. true stdcpp17 diff --git a/3rdparty/foo_SDK/foobar2000/foobar2000_component_client/foobar2000_component_client.xcodeproj/project.pbxproj b/3rdparty/foo_SDK/foobar2000/foobar2000_component_client/foobar2000_component_client.xcodeproj/project.pbxproj new file mode 100644 index 00000000..14f285ec --- /dev/null +++ b/3rdparty/foo_SDK/foobar2000/foobar2000_component_client/foobar2000_component_client.xcodeproj/project.pbxproj @@ -0,0 +1,282 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 54; + objects = { + +/* Begin PBXBuildFile section */ + 0F1FDDDC2AA0B33A00DE8967 /* component_client.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F1FDDDB2AA0B33A00DE8967 /* component_client.cpp */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 0F1FDDD42AA0B2FB00DE8967 /* libfoobar2000_component_client.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libfoobar2000_component_client.a; sourceTree = BUILT_PRODUCTS_DIR; }; + 0F1FDDDB2AA0B33A00DE8967 /* component_client.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = component_client.cpp; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 0F1FDDD22AA0B2FB00DE8967 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 0F1FDDCB2AA0B2FB00DE8967 = { + isa = PBXGroup; + children = ( + 0F1FDDDB2AA0B33A00DE8967 /* component_client.cpp */, + 0F1FDDD52AA0B2FB00DE8967 /* Products */, + ); + sourceTree = ""; + }; + 0F1FDDD52AA0B2FB00DE8967 /* Products */ = { + isa = PBXGroup; + children = ( + 0F1FDDD42AA0B2FB00DE8967 /* libfoobar2000_component_client.a */, + ); + name = Products; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + 0F1FDDD02AA0B2FB00DE8967 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + 0F1FDDD32AA0B2FB00DE8967 /* foobar2000_component_client */ = { + isa = PBXNativeTarget; + buildConfigurationList = 0F1FDDD82AA0B2FB00DE8967 /* Build configuration list for PBXNativeTarget "foobar2000_component_client" */; + buildPhases = ( + 0F1FDDD02AA0B2FB00DE8967 /* Headers */, + 0F1FDDD12AA0B2FB00DE8967 /* Sources */, + 0F1FDDD22AA0B2FB00DE8967 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = foobar2000_component_client; + productName = foobar2000_component_client; + productReference = 0F1FDDD42AA0B2FB00DE8967 /* libfoobar2000_component_client.a */; + productType = "com.apple.product-type.library.static"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 0F1FDDCC2AA0B2FB00DE8967 /* Project object */ = { + isa = PBXProject; + attributes = { + BuildIndependentTargetsInParallel = 1; + LastUpgradeCheck = 1430; + TargetAttributes = { + 0F1FDDD32AA0B2FB00DE8967 = { + CreatedOnToolsVersion = 14.3.1; + }; + }; + }; + buildConfigurationList = 0F1FDDCF2AA0B2FB00DE8967 /* Build configuration list for PBXProject "foobar2000_component_client" */; + compatibilityVersion = "Xcode 12.0"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 0F1FDDCB2AA0B2FB00DE8967; + productRefGroup = 0F1FDDD52AA0B2FB00DE8967 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 0F1FDDD32AA0B2FB00DE8967 /* foobar2000_component_client */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXSourcesBuildPhase section */ + 0F1FDDD12AA0B2FB00DE8967 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 0F1FDDDC2AA0B33A00DE8967 /* component_client.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 0F1FDDD62AA0B2FB00DE8967 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + HEADER_SEARCH_PATHS = ( + .., + ../.., + ); + MACOSX_DEPLOYMENT_TARGET = 10.13; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + }; + name = Debug; + }; + 0F1FDDD72AA0B2FB00DE8967 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + HEADER_SEARCH_PATHS = ( + .., + ../.., + ); + MACOSX_DEPLOYMENT_TARGET = 10.13; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + SDKROOT = macosx; + }; + name = Release; + }; + 0F1FDDD92AA0B2FB00DE8967 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = 4S876G9VCD; + EXECUTABLE_PREFIX = lib; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + }; + name = Debug; + }; + 0F1FDDDA2AA0B2FB00DE8967 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = 4S876G9VCD; + EXECUTABLE_PREFIX = lib; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 0F1FDDCF2AA0B2FB00DE8967 /* Build configuration list for PBXProject "foobar2000_component_client" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 0F1FDDD62AA0B2FB00DE8967 /* Debug */, + 0F1FDDD72AA0B2FB00DE8967 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 0F1FDDD82AA0B2FB00DE8967 /* Build configuration list for PBXNativeTarget "foobar2000_component_client" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 0F1FDDD92AA0B2FB00DE8967 /* Debug */, + 0F1FDDDA2AA0B2FB00DE8967 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 0F1FDDCC2AA0B2FB00DE8967 /* Project object */; +} diff --git a/3rdparty/foo_SDK/foobar2000/helpers-mac/CFObject.h b/3rdparty/foo_SDK/foobar2000/helpers-mac/CFObject.h new file mode 100644 index 00000000..0cc29b38 --- /dev/null +++ b/3rdparty/foo_SDK/foobar2000/helpers-mac/CFObject.h @@ -0,0 +1,57 @@ +#pragma once + +#include + +template +class CFObject { +public: + typedef CFObject self_t; + type_t p = NULL; + + ~CFObject() { + if ( p ) CFRelease(p); + } + + void Retain(type_t * arg) { + if ( p ) CFRelease(p); + p = arg; + if ( p ) CFRetain(p); + } + + void Attach(type_t * arg) { + if ( p ) CFRelease(p); + p = arg; + } + + void operator=( self_t const & arg ) { + if ( p ) CFRelease(p); + p = arg.p; + if ( p ) CFRetain(p); + } + CFObject() {} + CFObject( self_t const & arg ) { + p = arg.p; + if ( p ) CFRetain(p); + } + + CFObject(self_t && arg ) { + p = arg.p; arg.p = NULL; + } + void operator=(self_t && arg) { + if ( p ) CFRelease(p); + p = arg.p; arg.p = NULL; + } + + operator bool() const { return p != NULL; } + operator type_t() const { return p;} + + + void reset() { + if ( p ) CFRelease(p); + p = NULL; + } + + void operator=(nullptr_t) { + reset(); + } +}; diff --git a/3rdparty/foo_SDK/foobar2000/helpers-mac/NSAttributedString+ppaddons.h b/3rdparty/foo_SDK/foobar2000/helpers-mac/NSAttributedString+ppaddons.h new file mode 100644 index 00000000..3a0170ca --- /dev/null +++ b/3rdparty/foo_SDK/foobar2000/helpers-mac/NSAttributedString+ppaddons.h @@ -0,0 +1,9 @@ +#import + +@interface NSAttributedString (ppaddons) ++ (NSAttributedString*) attributedStringWithImage: (NSImage*) img; ++ (NSAttributedString*) attributedStringWithImageNamed: (NSString*) name; ++ (NSAttributedString*) attributedStringWithImageNamed:(NSString *)name size: (NSSize) size; ++ (NSAttributedString*) attributedStringWithImageNamed:(NSString *)name squareSize: (CGFloat) size; ++ (NSAttributedString*) hyperlinkFromString:(NSString*)inString withURL:(NSURL*)aURL; +@end diff --git a/3rdparty/foo_SDK/foobar2000/helpers-mac/NSAttributedString+ppaddons.m b/3rdparty/foo_SDK/foobar2000/helpers-mac/NSAttributedString+ppaddons.m new file mode 100644 index 00000000..a01aaf21 --- /dev/null +++ b/3rdparty/foo_SDK/foobar2000/helpers-mac/NSAttributedString+ppaddons.m @@ -0,0 +1,49 @@ +#import "NSAttributedString+ppaddons.h" +#import + +@implementation NSAttributedString (ppaddons) + ++ (NSAttributedString*) attributedStringWithImage: (NSImage*) img { + if (img == nil) return nil; + NSTextAttachment * attachment = [[NSTextAttachment alloc] init]; + NSTextAttachmentCell * cell = (NSTextAttachmentCell*) attachment.attachmentCell; + cell.image = img; + return [NSAttributedString attributedStringWithAttachment: attachment]; +} + ++ (NSAttributedString*) attributedStringWithImageNamed: (NSString*) name { + if (name == nil) return nil; + return [self attributedStringWithImage: [NSImage imageNamed: name]]; +} + ++ (NSAttributedString*) attributedStringWithImageNamed:(NSString *)name size: (NSSize) size { + NSImage * img = [NSImage imageNamed: name]; + if (img == nil) return nil; + img.size = size; + return [self attributedStringWithImage: img]; +} ++ (NSAttributedString*) attributedStringWithImageNamed:(NSString *)name squareSize: (CGFloat) size { + return [self attributedStringWithImageNamed: name size: NSMakeSize(size, size)]; +} + ++(NSAttributedString*)hyperlinkFromString:(NSString*)inString withURL:(NSURL*)aURL +{ + NSMutableAttributedString* attrString = [[NSMutableAttributedString alloc] initWithString: inString]; + NSRange range = NSMakeRange(0, [attrString length]); + + [attrString beginEditing]; + [attrString addAttribute:NSLinkAttributeName value:[aURL absoluteString] range:range]; + + // make the text appear in blue + [attrString addAttribute:NSForegroundColorAttributeName value:[NSColor linkColor] range:range]; + + // next make the text appear with an underline + [attrString addAttribute: + NSUnderlineStyleAttributeName value:[NSNumber numberWithInt:NSUnderlineStyleSingle] range:range]; + + [attrString endEditing]; + + return attrString; +} + +@end diff --git a/3rdparty/foo_SDK/foobar2000/helpers-mac/NSButton+checked.h b/3rdparty/foo_SDK/foobar2000/helpers-mac/NSButton+checked.h new file mode 100644 index 00000000..21dea567 --- /dev/null +++ b/3rdparty/foo_SDK/foobar2000/helpers-mac/NSButton+checked.h @@ -0,0 +1,7 @@ +#import + +@interface NSButton (checked) + +@property BOOL checked; + +@end diff --git a/3rdparty/foo_SDK/foobar2000/helpers-mac/NSButton+checked.m b/3rdparty/foo_SDK/foobar2000/helpers-mac/NSButton+checked.m new file mode 100644 index 00000000..d6ade1c6 --- /dev/null +++ b/3rdparty/foo_SDK/foobar2000/helpers-mac/NSButton+checked.m @@ -0,0 +1,13 @@ +#import "NSButton+checked.h" + +@implementation NSButton (checked) + +- (BOOL)checked { + return self.state == NSOnState; +} + +- (void)setChecked:(BOOL)checked { + self.state = checked ? NSOnState : NSOffState; +} + +@end diff --git a/3rdparty/foo_SDK/foobar2000/helpers-mac/NSComboBox+fb2k.h b/3rdparty/foo_SDK/foobar2000/helpers-mac/NSComboBox+fb2k.h new file mode 100644 index 00000000..589e7e47 --- /dev/null +++ b/3rdparty/foo_SDK/foobar2000/helpers-mac/NSComboBox+fb2k.h @@ -0,0 +1,9 @@ +#import + +#import +#import + +@interface NSComboBox (fb2k) +- (void) setupHistory: (cfg_dropdown_history&) var; +- (void) addToHistory: (cfg_dropdown_history&) var; +@end diff --git a/3rdparty/foo_SDK/foobar2000/helpers-mac/NSComboBox+fb2k.mm b/3rdparty/foo_SDK/foobar2000/helpers-mac/NSComboBox+fb2k.mm new file mode 100644 index 00000000..b7a875f8 --- /dev/null +++ b/3rdparty/foo_SDK/foobar2000/helpers-mac/NSComboBox+fb2k.mm @@ -0,0 +1,24 @@ +#import "NSComboBox+fb2k.h" +#import "NSMenu+ppaddons.h" + +@implementation NSComboBox (fb2k) +- (void) setupHistory: (cfg_dropdown_history&) var { + [self removeAllItems]; + pfc::string8 temp; var.get_state( temp ); + NSString * str = [NSString stringWithUTF8String: temp.c_str()]; + if ( str.length == 0 ) return; + NSArray * arr = [str componentsSeparatedByCharactersInSet: [NSCharacterSet newlineCharacterSet]]; + if ( arr.count == 0 ) return; + for( NSString * str in arr ) { + if ( str.length > 0 ) [self addItemWithObjectValue: str]; + } + self.stringValue = arr.firstObject; + + [self.menu addSeparator]; +} + +- (void)addToHistory:(cfg_dropdown_history &)var { + NSString * str = self.stringValue; + if ( str.length > 0 ) var.add_item( str.UTF8String ); +} +@end diff --git a/3rdparty/foo_SDK/foobar2000/helpers-mac/NSEvent+ppstuff.h b/3rdparty/foo_SDK/foobar2000/helpers-mac/NSEvent+ppstuff.h new file mode 100644 index 00000000..e713d29d --- /dev/null +++ b/3rdparty/foo_SDK/foobar2000/helpers-mac/NSEvent+ppstuff.h @@ -0,0 +1,13 @@ +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface NSEvent (ppstuff) + +@property (readonly) BOOL isKeyDown; +@property (readonly) BOOL isCmdKeyDown; +@property (readonly) BOOL isShiftKeyDown; +@property (readonly) NSEventModifierFlags modifierFlagsDI; +@end + +NS_ASSUME_NONNULL_END diff --git a/3rdparty/foo_SDK/foobar2000/helpers-mac/NSEvent+ppstuff.m b/3rdparty/foo_SDK/foobar2000/helpers-mac/NSEvent+ppstuff.m new file mode 100644 index 00000000..cf4b6e0b --- /dev/null +++ b/3rdparty/foo_SDK/foobar2000/helpers-mac/NSEvent+ppstuff.m @@ -0,0 +1,17 @@ +#import "NSEvent+ppstuff.h" + +@implementation NSEvent (ppstuff) + +- (BOOL)isKeyDown { + return self.type == NSEventTypeKeyDown; +} +- (BOOL)isCmdKeyDown { + return self.isKeyDown && self.modifierFlagsDI == NSEventModifierFlagCommand; +} +- (BOOL)isShiftKeyDown { + return self.isKeyDown && self.modifierFlagsDI == NSEventModifierFlagShift; +} +- (NSEventModifierFlags)modifierFlagsDI { + return self.modifierFlags & NSEventModifierFlagDeviceIndependentFlagsMask; +} +@end diff --git a/3rdparty/foo_SDK/foobar2000/helpers-mac/NSMenu+ppaddons.h b/3rdparty/foo_SDK/foobar2000/helpers-mac/NSMenu+ppaddons.h new file mode 100644 index 00000000..4383e314 --- /dev/null +++ b/3rdparty/foo_SDK/foobar2000/helpers-mac/NSMenu+ppaddons.h @@ -0,0 +1,18 @@ +#import + +@interface NSMenu (ppaddons) + +- (NSMenuItem*) addItemWithTitle: (NSString*) title action: (SEL) action target: (id) target; +- (void) addSeparator; +- (NSMenuItem*) addSubMenu: (NSMenu*) menu withTitle: (NSString*) title; +- (void)popUpForView:(NSView *)view; + +- (void) textToSeparators: (NSString*) text; +- (void) textToSeparators; +@end + +@interface NSMenuItem (ppaddons) + +@property BOOL checked; + +@end diff --git a/3rdparty/foo_SDK/foobar2000/helpers-mac/NSMenu+ppaddons.m b/3rdparty/foo_SDK/foobar2000/helpers-mac/NSMenu+ppaddons.m new file mode 100644 index 00000000..d67e2b10 --- /dev/null +++ b/3rdparty/foo_SDK/foobar2000/helpers-mac/NSMenu+ppaddons.m @@ -0,0 +1,63 @@ +#import "NSMenu+ppaddons.h" + +@implementation NSMenu (ppaddons) + +- (NSMenuItem*) addItemWithTitle: (NSString*) title action: (SEL) action target: (id) target { + NSMenuItem * item = [[NSMenuItem alloc] initWithTitle: title action: action keyEquivalent: @""]; + item.target = target; + [self addItem: item]; + return item; +} + +- (void) addSeparator { + [self addItem: [NSMenuItem separatorItem]]; +} + +- (NSMenuItem*) addSubMenu: (NSMenu*) menu withTitle: (NSString*) title { + NSMenuItem * item = [[NSMenuItem alloc] init]; + item.title = title; + item.submenu = menu; + [self addItem: item]; + return item; +} + +- (void)popUpForView:(NSView *)view { + BOOL pullsDown = YES; + NSMenu *popMenu = [self copy]; + NSRect frame = [view frame]; + frame.origin.x = 0.0; + frame.origin.y = 0.0; + + if (pullsDown) [popMenu insertItemWithTitle:@"" action:NULL keyEquivalent:@"" atIndex:0]; + + NSPopUpButtonCell *popUpButtonCell = [[NSPopUpButtonCell alloc] initTextCell:@"" pullsDown:pullsDown]; + [popUpButtonCell setMenu:popMenu]; + if (!pullsDown) [popUpButtonCell selectItem:nil]; + [popUpButtonCell performClickWithFrame:frame inView:view]; +} + +- (void)textToSeparators { + [self textToSeparators: @"-"]; +} + +- (void)textToSeparators:(NSString *)text { + for( size_t walk = 0; walk < self.numberOfItems; ++ walk ) { + NSMenuItem * fix = [self itemAtIndex: walk]; + if ( [fix.title isEqualToString: text] ) { + [self removeItemAtIndex: walk]; + [self insertItem: [NSMenuItem separatorItem] atIndex: walk]; + } + } +} + +@end + +@implementation NSMenuItem (ppaddons) + +- (void)setChecked:(BOOL)checked { + self.state = checked ? NSOnState : NSOffState; +} +- (BOOL)checked { + return self.state == NSOnState; +} +@end diff --git a/3rdparty/foo_SDK/foobar2000/helpers-mac/NSTextField+grayed.h b/3rdparty/foo_SDK/foobar2000/helpers-mac/NSTextField+grayed.h new file mode 100644 index 00000000..e3719de4 --- /dev/null +++ b/3rdparty/foo_SDK/foobar2000/helpers-mac/NSTextField+grayed.h @@ -0,0 +1,7 @@ +#import + +@interface NSTextField (grayed) + +@property BOOL grayed; + +@end diff --git a/3rdparty/foo_SDK/foobar2000/helpers-mac/NSTextField+grayed.m b/3rdparty/foo_SDK/foobar2000/helpers-mac/NSTextField+grayed.m new file mode 100644 index 00000000..93f14827 --- /dev/null +++ b/3rdparty/foo_SDK/foobar2000/helpers-mac/NSTextField+grayed.m @@ -0,0 +1,14 @@ +#import "NSTextField+grayed.h" + +@implementation NSTextField (grayed) + +- (void)setGrayed:(BOOL)grayed { + if (grayed) self.textColor = [NSColor disabledControlTextColor]; + else self.textColor = [NSColor labelColor]; +} + +- (BOOL)grayed { + return [self.textColor isEqualTo: [NSColor disabledControlTextColor]]; +} + +@end diff --git a/3rdparty/foo_SDK/foobar2000/helpers-mac/NSView+embed.h b/3rdparty/foo_SDK/foobar2000/helpers-mac/NSView+embed.h new file mode 100644 index 00000000..1a3c8e32 --- /dev/null +++ b/3rdparty/foo_SDK/foobar2000/helpers-mac/NSView+embed.h @@ -0,0 +1,6 @@ +#import + +@interface NSView (embed) +- (void) embedInView: (NSView*) superview; +- (void) embedInViewV2: (NSView*) superview; // adds autolayout constraints +@end diff --git a/3rdparty/foo_SDK/foobar2000/helpers-mac/NSView+embed.m b/3rdparty/foo_SDK/foobar2000/helpers-mac/NSView+embed.m new file mode 100644 index 00000000..53939145 --- /dev/null +++ b/3rdparty/foo_SDK/foobar2000/helpers-mac/NSView+embed.m @@ -0,0 +1,25 @@ +#import "NSView+embed.h" + +@implementation NSView (embed) + +- (void)embedInView:(NSView *)superview { + self.autoresizingMask = NSViewHeightSizable | NSViewWidthSizable; + self.frame = superview.bounds; + [superview addSubview: self]; +} + +- (void)embedInViewV2:(NSView *)superview { + + self.autoresizingMask = 0; + [superview addSubview: self]; + NSMutableArray * constraints = [NSMutableArray arrayWithCapacity: 4]; + static const NSLayoutAttribute params[4] = { NSLayoutAttributeLeft, NSLayoutAttributeRight, NSLayoutAttributeTop, NSLayoutAttributeBottom }; + for( unsigned i = 0; i < 4; ++ i) { + NSLayoutAttribute a = params[i]; + [constraints addObject: [NSLayoutConstraint constraintWithItem: self attribute:a relatedBy:NSLayoutRelationEqual toItem:superview attribute:a multiplier:1 constant:0]]; + } + + [superview addConstraints: constraints]; +} + +@end diff --git a/3rdparty/foo_SDK/foobar2000/helpers-mac/NSView+ppsubviews.h b/3rdparty/foo_SDK/foobar2000/helpers-mac/NSView+ppsubviews.h new file mode 100644 index 00000000..8fb9dc63 --- /dev/null +++ b/3rdparty/foo_SDK/foobar2000/helpers-mac/NSView+ppsubviews.h @@ -0,0 +1,11 @@ +#import + +@interface NSView (ppsubviews) +- (NSView*) recurFindSubViewOfClass: (Class) cls identifier: (NSString*) identifier; +- (NSView*) findSubViewOfClass: (Class) cls identifier: (NSString*) identifier; +- (NSView*) findSubViewOfClass: (Class) cls; +- (NSButton*) findButton; +- (NSTextView*) findTextView; +- (NSTextField*) findTextField; +- (NSImageView*) findImageView; +@end diff --git a/3rdparty/foo_SDK/foobar2000/helpers-mac/NSView+ppsubviews.m b/3rdparty/foo_SDK/foobar2000/helpers-mac/NSView+ppsubviews.m new file mode 100644 index 00000000..bbfc49e0 --- /dev/null +++ b/3rdparty/foo_SDK/foobar2000/helpers-mac/NSView+ppsubviews.m @@ -0,0 +1,52 @@ +#import "NSView+ppsubviews.h" + +@implementation NSView (ppsubviews) + +- (NSView*) recurFindSubViewOfClass: (Class) cls identifier: (NSString*) identifier { + @autoreleasepool { + NSMutableArray * arrAll = [NSMutableArray new]; + + [arrAll addObjectsFromArray: self.subviews]; + for ( NSUInteger w = 0; w < arrAll.count; ++ w ) { + NSView * thisView = [arrAll objectAtIndex: w]; + + if ( (cls == nil || [thisView isKindOfClass: cls]) && ( identifier == nil || [thisView.identifier isEqualToString: identifier] ) ) { + return thisView; + } + [arrAll addObjectsFromArray: thisView.subviews]; + + + if ( w >= 200 ) { + [arrAll removeObjectsInRange: NSMakeRange(0, w) ]; + w = 0; + } + } + return nil; + } +} + + +- (NSView*) findSubViewOfClass: (Class) cls identifier: (NSString*) identifier { + for (NSView * v in self.subviews) { + if ( (cls == nil || [v isKindOfClass: cls]) && ( identifier == nil || [ v.identifier isEqualToString: identifier ] ) ) { + return v; + } + } + return nil; +} +- (NSView *)findSubViewOfClass:(Class)cls { + return [self findSubViewOfClass: cls identifier: nil]; +} +- (NSButton *)findButton { + return (NSButton*) [self findSubViewOfClass: [NSButton class]]; +} +- (NSTextView *)findTextView { + return (NSTextView*) [self findSubViewOfClass: [NSTextView class]]; +} +- (NSTextField *) findTextField { + return (NSTextField*) [self findSubViewOfClass: [NSTextField class]]; +} +- (NSImageView*) findImageView { + return (NSImageView*) [self findSubViewOfClass: [NSImageView class]]; +} +@end diff --git a/3rdparty/foo_SDK/foobar2000/helpers-mac/fb2k-platform.h b/3rdparty/foo_SDK/foobar2000/helpers-mac/fb2k-platform.h new file mode 100644 index 00000000..f5a2ef1b --- /dev/null +++ b/3rdparty/foo_SDK/foobar2000/helpers-mac/fb2k-platform.h @@ -0,0 +1,28 @@ +#pragma once + +#import +#import + +namespace fb2k { + NSString * strToPlatform( const char * ); + NSString * strToPlatform( const char * , size_t ); + NSString * strToPlatform( stringRef ); + stringRef strFromPlatform( NSString * ); + + stringRef urlFromPlatform( id url /* can be NSString or NSURL */ ); + + typedef NSImage* platformImage_t; + platformImage_t imageToPlatform( fb2k::objRef ); + + + // These two functions do the same, openWebBrowser() was added for compatiblity with fb2k mobile + void openWebBrowser(const char * URL); + void openURL( const char * URL); +} + +namespace pfc { + string8 strFromPlatform(NSString*); + NSString * strToPlatform( const char * ); + NSString * strToPlatform(string8 const&); + string8 strFromPlatform(CFStringRef); +} diff --git a/3rdparty/foo_SDK/foobar2000/helpers-mac/fb2k-platform.mm b/3rdparty/foo_SDK/foobar2000/helpers-mac/fb2k-platform.mm new file mode 100644 index 00000000..fd6604bc --- /dev/null +++ b/3rdparty/foo_SDK/foobar2000/helpers-mac/fb2k-platform.mm @@ -0,0 +1,68 @@ +#include "fb2k-platform.h" + +namespace fb2k { + NSString * strToPlatform( const char * s, size_t len ) { + pfc::string8 temp( s, len ); + return strToPlatform( temp ); + } + + NSString * strToPlatform( const char * s ) { + return [NSString stringWithUTF8String: s]; + } + NSString * strToPlatform( stringRef s ) { + if ( s.is_empty( ) ) return nil; + return strToPlatform( s->c_str() ); + } + stringRef strFromPlatform( NSString * s ) { + return makeString( s.UTF8String ); + } + + stringRef urlFromPlatform( id obj ) { + if ( [obj isKindOfClass: [NSURL class] ] ) { + NSURL * URL = obj; + obj = URL.absoluteString; + if ([obj hasPrefix:@"file://"]) + obj = URL.path; + } + if ( [obj respondsToSelector: @selector(UTF8String)]) { + pfc::string8 temp; + filesystem::g_get_canonical_path( [obj UTF8String], temp ); + return makeString( temp ); + } + return nullptr; + } + + void openURL( const char * URL ) { + @autoreleasepool { + [[NSWorkspace sharedWorkspace] openURL: [NSURL URLWithString: [NSString stringWithUTF8String: URL]]]; + } + } + void openWebBrowser( const char * URL) { + openURL(URL); + } + + NSImage * imageToPlatform( fb2k::objRef obj ) { + fb2k::image::ptr img; + if ( img &= obj ) { + return (__bridge NSImage *) img->getNative(); + } + return nil; + } +} + +namespace pfc { + string8 strFromPlatform(NSString* str) { + string8 ret; + if ( str ) ret = str.UTF8String; + return ret; + } + NSString * strToPlatform( const char * str) { + return fb2k::strToPlatform( str ); + } + NSString * strToPlatform(string8 const& str) { + return fb2k::strToPlatform( str.c_str() ); + } + string8 strFromPlatform(CFStringRef str) { + return strFromPlatform( (__bridge NSString*) str ); + } +} diff --git a/3rdparty/foo_SDK/foobar2000/helpers-mac/fooDecibelFormatter.h b/3rdparty/foo_SDK/foobar2000/helpers-mac/fooDecibelFormatter.h new file mode 100644 index 00000000..f428dbb0 --- /dev/null +++ b/3rdparty/foo_SDK/foobar2000/helpers-mac/fooDecibelFormatter.h @@ -0,0 +1,8 @@ +#import + +@interface fooDecibelFormatter : NSFormatter + +@property (nonatomic) NSNumber * minValue; +@property (nonatomic) NSNumber * maxValue; +@property (nonatomic) BOOL showSignAlways; +@end diff --git a/3rdparty/foo_SDK/foobar2000/helpers-mac/fooDecibelFormatter.m b/3rdparty/foo_SDK/foobar2000/helpers-mac/fooDecibelFormatter.m new file mode 100644 index 00000000..06fb01f5 --- /dev/null +++ b/3rdparty/foo_SDK/foobar2000/helpers-mac/fooDecibelFormatter.m @@ -0,0 +1,58 @@ +#import "fooDecibelFormatter.h" + +@implementation fooDecibelFormatter + +- (NSString*) formatNumber: (id) obj { + + double v = [ obj doubleValue ]; + + if ( self.showSignAlways ) { + if (v == 0) return [NSString stringWithUTF8String: "\xc2\xb1" "0"]; + if ( v > 0 ) { + if (v == (double) (int) v) return [NSString stringWithFormat: @"+%i", (int)v]; + else return [NSString stringWithFormat: @"+%.02f", v]; + } + } + + if (v == (double) (int) v) return [NSString stringWithFormat: @"%i", (int)v]; + else return [NSString stringWithFormat: @"%.02f", v]; +} + +- (NSString *)stringForObjectValue:(id)obj { + return [NSString stringWithFormat: @"%@ dB", [self formatNumber: obj]]; +} + +- (NSAttributedString *)attributedStringForObjectValue:(id)obj withDefaultAttributes:(NSDictionary *)attrs { + return nil; +} + +- (NSString *)editingStringForObjectValue:(id)obj { + return [self stringForObjectValue: obj]; + // return [self formatNumber: obj]; +} + +- (BOOL)getObjectValue:(out __autoreleasing id *)obj forString:(NSString *)string errorDescription:(out NSString *__autoreleasing *)error { + if (error) *error = nil; + + { + NSMutableCharacterSet * trimMe = [NSMutableCharacterSet whitespaceAndNewlineCharacterSet]; + [trimMe addCharactersInString: [NSString stringWithUTF8String: "+\xc2\xb1" ]]; + string = [ string.lowercaseString stringByTrimmingCharactersInSet: trimMe ]; + } + + if ( [string hasSuffix: @"db"]) { + string = [ [string substringToIndex: string.length-2] stringByTrimmingCharactersInSet: [NSCharacterSet whitespaceCharacterSet] ]; + } + + double v = string.doubleValue; + if (self.minValue) { + if (v < self.minValue.doubleValue) v = self.minValue.doubleValue; + } + if (self.maxValue) { + if (v > self.maxValue.doubleValue) v = self.maxValue.doubleValue; + } + *obj = [NSNumber numberWithDouble: v]; + return YES; +} + +@end diff --git a/3rdparty/foo_SDK/foobar2000/helpers-mac/fooGenericDialog.h b/3rdparty/foo_SDK/foobar2000/helpers-mac/fooGenericDialog.h new file mode 100644 index 00000000..babba465 --- /dev/null +++ b/3rdparty/foo_SDK/foobar2000/helpers-mac/fooGenericDialog.h @@ -0,0 +1,5 @@ +#import + +@interface fooGenericDialog : NSWindowController +@property (nonatomic) NSViewController * theContent; +@end diff --git a/3rdparty/foo_SDK/foobar2000/helpers-mac/fooGenericDialog.mm b/3rdparty/foo_SDK/foobar2000/helpers-mac/fooGenericDialog.mm new file mode 100644 index 00000000..20fd2da1 --- /dev/null +++ b/3rdparty/foo_SDK/foobar2000/helpers-mac/fooGenericDialog.mm @@ -0,0 +1,31 @@ +#import "fooGenericDialog.h" + +@interface fooGenericDialog () + +@end + +@implementation fooGenericDialog { + __weak IBOutlet NSStackView *m_stack; +} + +- (instancetype)init { + return [self initWithWindowNibName:@"fooGenericDialog"]; +} +- (void)windowDidLoad { + [super windowDidLoad]; + + [m_stack setViews: @[_theContent.view] inGravity:NSStackViewGravityCenter]; +} +- (IBAction)onDone:(id)sender { + [self.window makeFirstResponder: self.window]; + [self endDialog: NSModalResponseOK]; +} +- (void)cancelOperation:(id)sender { + [self endDialog: NSModalResponseCancel]; +} + +- (void) endDialog: (NSModalResponse) response { + [self.window.sheetParent endSheet: self.window returnCode: response]; +} + +@end diff --git a/3rdparty/foo_SDK/foobar2000/helpers-mac/fooGenericDialog.xib b/3rdparty/foo_SDK/foobar2000/helpers-mac/fooGenericDialog.xib new file mode 100644 index 00000000..2daeb261 --- /dev/null +++ b/3rdparty/foo_SDK/foobar2000/helpers-mac/fooGenericDialog.xib @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/3rdparty/foo_SDK/foobar2000/helpers-mac/fooPreferencesCommon.h b/3rdparty/foo_SDK/foobar2000/helpers-mac/fooPreferencesCommon.h new file mode 100644 index 00000000..ba9af3df --- /dev/null +++ b/3rdparty/foo_SDK/foobar2000/helpers-mac/fooPreferencesCommon.h @@ -0,0 +1,12 @@ +#import +#import + +typedef NSViewController fooPreferencesCommon; + +template +class preferences_mac_common : public preferences_page_v4 { +public: + service_ptr instantiate() override { + return fb2k::wrapNSObject( [obj_t new] ); + } +}; diff --git a/3rdparty/foo_SDK/foobar2000/helpers-mac/fooTimeFormatter.h b/3rdparty/foo_SDK/foobar2000/helpers-mac/fooTimeFormatter.h new file mode 100644 index 00000000..23066053 --- /dev/null +++ b/3rdparty/foo_SDK/foobar2000/helpers-mac/fooTimeFormatter.h @@ -0,0 +1,16 @@ +// +// fooTimeFormatter.h +// foo_abx +// +// Created by P on 06/09/2023. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface fooTimeFormatter : NSFormatter +@property (nonatomic) NSNumber * digits; +@end + +NS_ASSUME_NONNULL_END diff --git a/3rdparty/foo_SDK/foobar2000/helpers-mac/fooTimeFormatter.mm b/3rdparty/foo_SDK/foobar2000/helpers-mac/fooTimeFormatter.mm new file mode 100644 index 00000000..38e29813 --- /dev/null +++ b/3rdparty/foo_SDK/foobar2000/helpers-mac/fooTimeFormatter.mm @@ -0,0 +1,37 @@ +// +// fooTimeFormatter.m +// foo_abx +// +// Created by P on 06/09/2023. +// + +#import "stdafx.h" +#import "fooTimeFormatter.h" + +@implementation fooTimeFormatter + +- (NSString *)stringForObjectValue:(id)obj { + double v = 0; + if ( [obj respondsToSelector: @selector(doubleValue)]) v = [obj doubleValue]; + else if ( [obj respondsToSelector: @selector(longValue)]) v = [obj longValue]; + else if ( [obj respondsToSelector: @selector(intValue)]) v = [obj intValue]; + + unsigned digits = 3; + if ( _digits ) digits = _digits.unsignedIntValue; + return [NSString stringWithUTF8String: pfc::format_time_ex(v, digits)]; +} + +- (NSString *)editingStringForObjectValue:(id)obj { + return [self stringForObjectValue: obj]; +} +- (BOOL)getObjectValue:(out id _Nullable __autoreleasing *)obj forString:(NSString *)string errorDescription:(out NSString * _Nullable __autoreleasing *)error { + if ( string == nil ) return NO; + try { + double v = pfc::parse_timecode( string.UTF8String ); + *obj = [NSNumber numberWithDouble: v]; + return YES; + } catch(...) { + return NO; + } +} +@end diff --git a/3rdparty/foo_SDK/foobar2000/helpers-mac/fooWindowWithCancel.h b/3rdparty/foo_SDK/foobar2000/helpers-mac/fooWindowWithCancel.h new file mode 100644 index 00000000..50de04d3 --- /dev/null +++ b/3rdparty/foo_SDK/foobar2000/helpers-mac/fooWindowWithCancel.h @@ -0,0 +1,9 @@ +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface fooWindowWithCancel : NSWindow + +@end + +NS_ASSUME_NONNULL_END diff --git a/3rdparty/foo_SDK/foobar2000/helpers-mac/fooWindowWithCancel.m b/3rdparty/foo_SDK/foobar2000/helpers-mac/fooWindowWithCancel.m new file mode 100644 index 00000000..8c70d8f2 --- /dev/null +++ b/3rdparty/foo_SDK/foobar2000/helpers-mac/fooWindowWithCancel.m @@ -0,0 +1,10 @@ +#import "fooWindowWithCancel.h" + +@implementation fooWindowWithCancel +- (void) cancelOperation: (id) sender { + id d = self.delegate; + if ( [d respondsToSelector: @selector(cancelOperation:)]) { + [d cancelOperation: sender]; + } +} +@end diff --git a/3rdparty/foo_SDK/foobar2000/helpers/CListControlFb2kColors.h b/3rdparty/foo_SDK/foobar2000/helpers/CListControlFb2kColors.h index d1f3290b..a5175fb9 100644 --- a/3rdparty/foo_SDK/foobar2000/helpers/CListControlFb2kColors.h +++ b/3rdparty/foo_SDK/foobar2000/helpers/CListControlFb2kColors.h @@ -3,6 +3,7 @@ // foobar2000 v2.0+ only #if FOOBAR2000_TARGET_VERSION >= 81 +// One-line fix for UI colors in CListControl, use CListControlFb2kColors< myCListControSubClass > to use fb2k colors template class CListControlFb2kColors : public parent_t, protected ui_config_callback_impl { public: @@ -22,3 +23,23 @@ class CListControlFb2kColors : public parent_t, protected ui_config_callback_imp }; #endif + +// For use in UI elements +// Not completely selfcontained, host must pass ui_element_instance_callback and call ui_colors_changed() +template +class CListControlFb2kColorsUIElem : public parent_t { +public: + template + CListControlFb2kColorsUIElem(ui_element_instance_callback::ptr callback, arg_t && ... args) : parent_t(std::forward(args) ...), m_callback(callback) { + this->SetDarkMode(m_callback->is_dark_mode()); + } + void ui_colors_changed() { // host must call this in response to notify() + this->SetDarkMode(m_callback->is_dark_mode()); + this->Invalidate(); + } +protected: + COLORREF GetSysColorHook(int colorIndex) const override { + return m_callback->getSysColor(colorIndex); + } + const ui_element_instance_callback_ptr m_callback; +}; diff --git a/3rdparty/foo_SDK/foobar2000/helpers/CallForwarder.h b/3rdparty/foo_SDK/foobar2000/helpers/CallForwarder.h index d1ed43f7..257458df 100644 --- a/3rdparty/foo_SDK/foobar2000/helpers/CallForwarder.h +++ b/3rdparty/foo_SDK/foobar2000/helpers/CallForwarder.h @@ -1,6 +1,5 @@ #pragma once -#include - +#include "callInMainThreadHelper.h" namespace CF { template class _inMainThread : public main_thread_callback { public: diff --git a/3rdparty/foo_SDK/foobar2000/helpers/DarkMode.h b/3rdparty/foo_SDK/foobar2000/helpers/DarkMode.h index 05a21f2e..1c6a3e83 100644 --- a/3rdparty/foo_SDK/foobar2000/helpers/DarkMode.h +++ b/3rdparty/foo_SDK/foobar2000/helpers/DarkMode.h @@ -11,6 +11,11 @@ // Keeps track of dark mode preference changes at runtime // Does nothing if used in foobar2000 older than 2.0 +// IMPORTANT +// See also: SDK/coreDarkMode.h +// Using CCoreDarkMode lets you invoke foobar2000's instance of this code instead of static linking it, resulting in much smaller component binary. +// Using CDarkModeHooks directly is good mainly for debugging or troubleshooting. + namespace fb2k { bool isDarkMode(); diff --git a/3rdparty/foo_SDK/foobar2000/helpers/ThreadUtils.h b/3rdparty/foo_SDK/foobar2000/helpers/ThreadUtils.h index eedad777..bb7ea9dc 100644 --- a/3rdparty/foo_SDK/foobar2000/helpers/ThreadUtils.h +++ b/3rdparty/foo_SDK/foobar2000/helpers/ThreadUtils.h @@ -19,10 +19,10 @@ namespace ThreadUtils { // Do not use, broken version of MultiWaitAbortable_MsgLoop2 retained for compatibility (returns 1 based index) t_size MultiWaitAbortable_MsgLoop(const HANDLE* ev, t_size evCount, abort_callback& abort); - void SleepAbortable_MsgLoop(abort_callback & abort, DWORD timeout /*must not be INFINITE*/); - bool WaitAbortable_MsgLoop(HANDLE ev, abort_callback & abort, DWORD timeout /*must not be INFINITE*/); + void SleepAbortable_MsgLoop(abort_callback & abort, DWORD timeoutMS); + bool WaitAbortable_MsgLoop(HANDLE ev, abort_callback & abort, DWORD timeoutMS); - DWORD MultiWait_MsgLoop(const HANDLE* ev, DWORD evCount, DWORD timeout); + DWORD MultiWait_MsgLoop(const HANDLE* ev, DWORD evCount, DWORD timeoutMS); DWORD MultiWait_MsgLoop(const HANDLE* ev, DWORD evCount); // Drop-in replacement for pfc::event::g_wait_for() diff --git a/3rdparty/foo_SDK/foobar2000/helpers/WindowPositionUtils.cpp b/3rdparty/foo_SDK/foobar2000/helpers/WindowPositionUtils.cpp index 5683ff8f..c04171ee 100644 --- a/3rdparty/foo_SDK/foobar2000/helpers/WindowPositionUtils.cpp +++ b/3rdparty/foo_SDK/foobar2000/helpers/WindowPositionUtils.cpp @@ -1,6 +1,7 @@ #include "StdAfx.h" #include "WindowPositionUtils.h" +#define FB2K_WPU_DEBUG 0 namespace { static BOOL GetParentWndRect(CWindow wndParent, CRect& rc) { if (!wndParent.IsIconic()) { @@ -49,8 +50,10 @@ namespace { bool cfgDialogPositionData::grabFrom(CWindow wnd) { CRect rc; - if (!GetClientRectAsSC(wnd, rc)) return false; - const CSize DPI = QueryScreenDPIEx(); + if (!GetClientRectAsSC(wnd, rc)) { + return false; + } + const CSize DPI = QueryScreenDPIEx(wnd); m_dpiX = DPI.cx; m_dpiY = DPI.cy; m_width = rc.Width(); m_height = rc.Height(); m_posX = m_posY = posInvalid; @@ -61,10 +64,23 @@ bool cfgDialogPositionData::grabFrom(CWindow wnd) { m_posX = rc.left - rcParent.left; m_posY = rc.top - rcParent.top; } + } else { + m_posX = rc.left; m_posY = rc.top; } return true; } +pfc::string8 cfgDialogPositionData::debug() const { + pfc::string_formatter ret; + if (m_width != sizeInvalid) ret << "W: " << m_width << "\n"; + if (m_height != sizeInvalid) ret << "H: " << m_height << "\n"; + if (m_posX != posInvalid) ret << "X: " << m_posX << "\n"; + if (m_posY != posInvalid) ret << "Y: " << m_posY << "\n"; + if (m_dpiX != dpiInvalid) ret << "DPI-X: " << m_dpiX << "\n"; + if (m_dpiY != dpiInvalid) ret << "DPI-Y: " << m_dpiY << "\n"; + return ret; +} + cfgDialogPositionData cfgDialogPositionData::reDPI( CSize screenDPI ) const { cfgDialogPositionData v = *this; if (screenDPI.cx == 0 || screenDPI.cy == 0) { @@ -96,7 +112,14 @@ bool cfgDialogPositionData::overrideDefaultSize(t_uint32 width, t_uint32 height) } bool cfgDialogPositionData::applyTo(CWindow wnd) const { - auto v = reDPI(QueryScreenDPIEx()); +#if FB2K_WPU_DEBUG + FB2K_console_formatter() << "cfgDialogPositionData::applyTo(0x" << pfc::format_window( wnd ) << ")"; + FB2K_console_formatter() << "data:\n" << this->debug(); +#endif + const auto v = reDPI(QueryScreenDPIEx(wnd)); +#if FB2K_WPU_DEBUG + FB2K_console_formatter() << "after reDPI:\n" << v.debug(); +#endif CWindow wndParent = wnd.GetParent(); UINT flags = SWP_NOACTIVATE | SWP_NOZORDER; CRect rc; @@ -117,6 +140,10 @@ bool cfgDialogPositionData::applyTo(CWindow wnd) const { rc.MoveToXY(center.x - rc.Width() / 2, center.y - rc.Height() / 2); } } + } else { + if (v.m_posX != v.posInvalid && v.m_posY != v.posInvalid ) { + rc.MoveToXY( v.m_posX, v.m_posY ); + } } if (!AdjustWindowRectHelper(wnd, rc)) return FALSE; @@ -135,12 +162,60 @@ bool cfgDialogPositionData::applyTo(CWindow wnd) const { return wnd.SetWindowPos(NULL, rc, flags); } -void cfgDialogPosition::AddWindow(CWindow wnd) { +void cfgDialogPosition::read_from_window(HWND wnd) { + cfgDialogPositionData data; + if (data.grabFrom(wnd)) this->set(data); +} + +bool cfgDialogPosition::apply_to_window(HWND wnd) { auto data = this->get(); - data.applyTo(wnd); + return data.applyTo(wnd); } -void cfgDialogPosition::RemoveWindow(CWindow wnd) { - cfgDialogPositionData data; - if (data.grabFrom(wnd)) this->set(data); +bool cfgWindowPositionData::grabFrom(CWindow wnd) { + WINDOWPLACEMENT wp = {sizeof(wp)}; + bool rv = !! wnd.GetWindowPlacement(&wp); + if (rv) { + if ( !wnd.IsWindowVisible() ) wp.showCmd = SW_HIDE; + this->m_wp = wp; + m_dpi = QueryScreenDPIEx(wnd); + PFC_ASSERT( m_dpi.cx > 0 && m_dpi.cy > 0 ); + } + return rv; +} + +static void reDPI(WINDOWPLACEMENT& wp, SIZE from, SIZE to) { + wp.rcNormalPosition.left = MulDiv(wp.rcNormalPosition.left, to.cx, from.cx); + wp.rcNormalPosition.right = MulDiv(wp.rcNormalPosition.right, to.cx, from.cx); + wp.rcNormalPosition.top = MulDiv(wp.rcNormalPosition.top, to.cy, from.cy); + wp.rcNormalPosition.bottom = MulDiv(wp.rcNormalPosition.bottom, to.cy, from.cy); +} + +bool applyWindowPlacement(HWND window, WINDOWPLACEMENT const& data, bool allowHidden); // window_placement_helper.cpp + +bool cfgWindowPositionData::applyTo(CWindow wnd, bool allowHidden) const { + WINDOWPLACEMENT wp = m_wp; + if ( wp.length == 0 ) return false; + auto dpi = QueryScreenDPIEx(wnd); + if (dpi.cx != m_dpi.cx || dpi.cy != m_dpi.cy) { + reDPI( wp, m_dpi, dpi ); + } + return applyWindowPlacement(wnd, wp, allowHidden); } + +void cfgWindowPosition::read_from_window(HWND wnd) { + // grabFrom might work partially, fail to obtain size due to window being hidden, use last values + cfgWindowPositionData data = get(); + if ( data.grabFrom( wnd ) ) set(data); +} + +bool cfgWindowPosition::apply_to_window(HWND wnd, bool allowHidden) { + auto data = get(); + return data.applyTo( wnd, allowHidden ); +} + +void cfgWindowPosition::windowCreated(HWND wnd, bool allowHidden) { + if (!apply_to_window(wnd, allowHidden)) { + ::ShowWindow( wnd, SW_SHOWDEFAULT ); + } +} \ No newline at end of file diff --git a/3rdparty/foo_SDK/foobar2000/helpers/WindowPositionUtils.h b/3rdparty/foo_SDK/foobar2000/helpers/WindowPositionUtils.h index 80fe227d..78b0b10b 100644 --- a/3rdparty/foo_SDK/foobar2000/helpers/WindowPositionUtils.h +++ b/3rdparty/foo_SDK/foobar2000/helpers/WindowPositionUtils.h @@ -102,21 +102,31 @@ class cfgDialogSizeTracker : public cfgWindowSizeTracker { }; struct cfgDialogPositionData { - enum { - posInvalid = 0x80000000, + static constexpr int32_t + posInvalid = 0x80000000; + static constexpr uint32_t sizeInvalid = 0xFFFFFFFF, - dpiInvalid = 0, - }; + dpiInvalid = 0; - uint32_t m_width = (uint32_t)sizeInvalid, m_height = (uint32_t)sizeInvalid; - int32_t m_posX = (int32_t)posInvalid, m_posY = (int32_t)posInvalid; - uint32_t m_dpiX = (uint32_t)dpiInvalid, m_dpiY = (uint32_t)dpiInvalid; + uint32_t m_width = sizeInvalid, m_height = sizeInvalid; + int32_t m_posX = posInvalid, m_posY = posInvalid; + uint32_t m_dpiX = dpiInvalid, m_dpiY = dpiInvalid; cfgDialogPositionData reDPI(CSize) const; bool grabFrom(CWindow wnd); bool applyTo(CWindow wnd) const; bool overrideDefaultSize(t_uint32 width, t_uint32 height); + + pfc::string8 debug() const; +}; + +struct cfgWindowPositionData { + WINDOWPLACEMENT m_wp = {}; + SIZE m_dpi = {}; + + bool grabFrom(CWindow wnd); + bool applyTo(CWindow wnd, bool allowHidden = false) const; }; FB2K_STREAM_READER_OVERLOAD(cfgDialogPositionData) { @@ -133,172 +143,29 @@ FB2K_STREAM_WRITER_OVERLOAD(cfgDialogPositionData) { return stream << value.m_width << value.m_height << value.m_posX << value.m_posY << value.m_dpiX << value.m_dpiY; } -#if 0 -class cfgDialogPositionData { +class cfgDialogPosition : public cfg_struct_t { public: - cfgDialogPositionData_ v; - cfgDialogPositionData() {} - - void OverrideDefaultSize(t_uint32 width, t_uint32 height) { - if (v.m_width == v.sizeInvalid && v.m_height == v.sizeInvalid) { - v.m_width = width; v.m_height = height; v.m_posX = v.m_posY = v.posInvalid; - v.m_dpiX = v.m_dpiY = 96; - } - } - - void AddWindow(CWindow wnd) { - TryFetchConfig(); - m_windows += wnd; - ApplyConfig(wnd); - } - void RemoveWindow(CWindow wnd) { - if (m_windows.contains(wnd)) { - StoreConfig(wnd); m_windows -= wnd; - } - } - void FetchConfig() {TryFetchConfig();} - -private: - BOOL ApplyConfig(CWindow wnd) { - ApplyDPI(); - CWindow wndParent = wnd.GetParent(); - UINT flags = SWP_NOACTIVATE | SWP_NOZORDER; - CRect rc; - if (!GetClientRectAsSC(wnd,rc)) return FALSE; - if (v.m_width != v.sizeInvalid && v.m_height != v.sizeInvalid && (wnd.GetWindowLong(GWL_STYLE) & WS_SIZEBOX) != 0) { - rc.right = rc.left + v.m_width; - rc.bottom = rc.top + v.m_height; - } else { - flags |= SWP_NOSIZE; - } - if (wndParent != NULL) { - CRect rcParent; - if (GetParentWndRect(wndParent, rcParent)) { - if (v.m_posX != v.posInvalid && v.m_posY != v.posInvalid) { - rc.MoveToXY( rcParent.TopLeft() + CPoint(v.m_posX, v.m_posY) ); - } else { - CPoint center = rcParent.CenterPoint(); - rc.MoveToXY( center.x - rc.Width() / 2, center.y - rc.Height() / 2); - } - } - } - if (!AdjustWindowRectHelper(wnd, rc)) return FALSE; - - DeOverlap(wnd, rc); - - { - CRect rcAdjust(0,0,1,1); - if (wndParent != NULL) { - CRect temp; - if (wndParent.GetWindowRect(temp)) rcAdjust = temp; - } - AdjustRectToScreenArea(rc, rcAdjust); - } - - - return wnd.SetWindowPos(NULL, rc, flags); - } - struct DeOverlapState { - CWindow m_thisWnd; - CPoint m_topLeft; - bool m_match; - }; - static BOOL CALLBACK MyEnumChildProc(HWND wnd, LPARAM param) { - DeOverlapState * state = reinterpret_cast(param); - if (wnd != state->m_thisWnd && IsWindowVisible(wnd) ) { - CRect rc; - if (GetWindowRect(wnd, rc)) { - if (rc.TopLeft() == state->m_topLeft) { - state->m_match = true; return FALSE; - } - } - } - return TRUE; - } - static bool DeOverlapTest(CWindow wnd, CPoint topLeft) { - DeOverlapState state = {}; - state.m_thisWnd = wnd; state.m_topLeft = topLeft; state.m_match = false; - EnumThreadWindows(GetCurrentThreadId(), MyEnumChildProc, reinterpret_cast(&state)); - return state.m_match; - } - static int DeOverlapDelta() { - return pfc::max_t(GetSystemMetrics(SM_CYCAPTION),1); - } - static void DeOverlap(CWindow wnd, CRect & rc) { - const int delta = DeOverlapDelta(); - for(;;) { - if (!DeOverlapTest(wnd, rc.TopLeft())) break; - rc.OffsetRect(delta,delta); - } - } - BOOL StoreConfig(CWindow wnd) { - CRect rc; - if (!GetClientRectAsSC(wnd, rc)) return FALSE; - const CSize DPI = QueryScreenDPIEx(); - v.m_dpiX = DPI.cx; v.m_dpiY = DPI.cy; - v.m_width = rc.Width(); v.m_height = rc.Height(); - v.m_posX = v.m_posY = v.posInvalid; - CWindow parent = wnd.GetParent(); - if (parent != NULL) { - CRect rcParent; - if (GetParentWndRect(parent, rcParent)) { - v.m_posX = rc.left - rcParent.left; - v.m_posY = rc.top - rcParent.top; - } - } - return TRUE; - } - void TryFetchConfig() { - for(auto walk = m_windows.cfirst(); walk.is_valid(); ++walk) { - if (StoreConfig(*walk)) break; - } - } - - void ApplyDPI() { - const CSize screenDPI = QueryScreenDPIEx(); - if (screenDPI.cx == 0 || screenDPI.cy == 0) { - PFC_ASSERT(!"Should not get here - something seriously wrong with the OS"); - return; - } - if (v.m_dpiX != v.dpiInvalid && v.m_dpiX != screenDPI.cx) { - if (v.m_width != v.sizeInvalid) v.m_width = MulDiv(v.m_width, screenDPI.cx, v.m_dpiX); - if (v.m_posX != v.posInvalid) v.m_posX = MulDiv(v.m_posX, screenDPI.cx, v.m_dpiX); - } - if (v.m_dpiY != v.dpiInvalid && v.m_dpiY != screenDPI.cy) { - if (v.m_height != v.sizeInvalid) v.m_height = MulDiv(v.m_height, screenDPI.cy, v.m_dpiY); - if (v.m_posY != v.posInvalid) v.m_posY = MulDiv(v.m_posY, screenDPI.cy, v.m_dpiY); - } - v.m_dpiX = screenDPI.cx; - v.m_dpiY = screenDPI.cy; - } - CSize GrabDPI() const { - CSize DPI(96,96); - if (v.m_dpiX != v.dpiInvalid) DPI.cx = v.m_dpiX; - if (v.m_dpiY != v.dpiInvalid) DPI.cy = v.m_dpiY; - return DPI; - } + cfgDialogPosition(const GUID& id) : cfg_struct_t(id) {} - static BOOL GetParentWndRect(CWindow wndParent, CRect & rc) { - if (!wndParent.IsIconic()) { - return wndParent.GetWindowRect(rc); - } - WINDOWPLACEMENT pl = {sizeof(pl)}; - if (!wndParent.GetWindowPlacement(&pl)) return FALSE; - rc = pl.rcNormalPosition; - return TRUE; - } + //! Read and save size data from HWND. + void read_from_window(HWND); + //! Apply saved size data to HWND. + bool apply_to_window(HWND); - pfc::avltree_t m_windows; -public: + void AddWindow(HWND wnd) { apply_to_window(wnd); } + void RemoveWindow(HWND wnd) { read_from_window(wnd); } }; -#endif -class cfgDialogPosition : public cfg_struct_t { +class cfgWindowPosition : public cfg_struct_t { public: - cfgDialogPosition(const GUID& id) : cfg_struct_t(id) {} - - void AddWindow(CWindow wnd); - void RemoveWindow(CWindow wnd); + cfgWindowPosition(const GUID & id) : cfg_struct_t(id) {} + + //! Read and save size data from HWND. + void read_from_window(HWND); + //! Apply saved size data to HWND. + bool apply_to_window(HWND, bool allowHidden = false); + //! New window created, show it with saved metrics. + void windowCreated(HWND, bool allowHidden = false); }; class cfgDialogPositionTracker { diff --git a/3rdparty/foo_SDK/foobar2000/helpers/atl-misc.h b/3rdparty/foo_SDK/foobar2000/helpers/atl-misc.h index 62a26e92..01be5fa7 100644 --- a/3rdparty/foo_SDK/foobar2000/helpers/atl-misc.h +++ b/3rdparty/foo_SDK/foobar2000/helpers/atl-misc.h @@ -1,8 +1,8 @@ #pragma once -#ifdef _WIN32 - #include "win32_misc.h" + +#ifdef _WIN32 #include #include #include diff --git a/3rdparty/foo_SDK/foobar2000/helpers/callInMainThreadHelper.h b/3rdparty/foo_SDK/foobar2000/helpers/callInMainThreadHelper.h new file mode 100644 index 00000000..c1399a67 --- /dev/null +++ b/3rdparty/foo_SDK/foobar2000/helpers/callInMainThreadHelper.h @@ -0,0 +1,127 @@ +#pragma once +#include + +// ====================================================================================================== +// Obsolete helpers - they still work, but it's easier to just use fb2k::inMainThread(). +// ====================================================================================================== + + +// Proxy class - friend this to allow callInMainThread to access your private methods +class callInMainThread { +public: + template + static void callThis(host_t * host, param_t & param) { + host->inMainThread(param); + } + template + static void callThis( host_t * host ) { + host->inMainThread(); + } +}; + +// Internal class, do not use. +template +class _callInMainThreadSvc_t : public main_thread_callback { +public: + _callInMainThreadSvc_t(service_t * host, param_t const & param) : m_host(host), m_param(param) {} + void callback_run() { + callInMainThread::callThis(m_host.get_ptr(), m_param); + } +private: + service_ptr_t m_host; + param_t m_param; +}; + + +// Main thread callback helper. You can use this to easily invoke inMainThread(someparam) on your class without writing any wrapper code. +// Requires myservice_t to be a fb2k service class with reference counting. +template +static void callInMainThreadSvc(myservice_t * host, param_t const & param) { + typedef _callInMainThreadSvc_t impl_t; + service_ptr_t obj = new service_impl_t(host, param); + main_thread_callback_manager::get()->add_callback( obj ); +} + +//! Helper class to call methods of your class (host class) in main thread with convenience. \n +//! Deals with the otherwise ugly scenario of your class becoming invalid while a method is queued. \n +//! Have this as a member of your class, then use m_mthelper.add( this, somearg ) ; to defer a call to this->inMainThread(somearg). \n +//! If your class becomes invalid before inMainThread is executed, the pending callback is discarded. \n +//! You can optionally call shutdown() to invalidate all pending callbacks early (in a destructor of your class - without waiting for callInMainThreadHelper destructor to do the job. \n +//! In order to let callInMainThreadHelper access your private methods, declare friend class callInMainThread. \n +//! Note that callInMainThreadHelper is expected to be created and destroyed in main thread. +class callInMainThreadHelper { +public: + + typedef std::function< void () > func_t; + + typedef pfc::rcptr_t< bool > killswitch_t; + + class entryFunc : public main_thread_callback { + public: + entryFunc( func_t const & func, killswitch_t ks ) : m_ks(ks), m_func(func) {} + + void callback_run() { + if (!*m_ks) m_func(); + } + + private: + killswitch_t m_ks; + func_t m_func; + }; + + template + class entry : public main_thread_callback { + public: + entry( host_t * host, arg_t const & arg, killswitch_t ks ) : m_ks(ks), m_host(host), m_arg(arg) {} + void callback_run() { + if (!*m_ks) callInMainThread::callThis( m_host, m_arg ); + } + private: + killswitch_t m_ks; + host_t * m_host; + arg_t m_arg; + }; + template + class entryVoid : public main_thread_callback { + public: + entryVoid( host_t * host, killswitch_t ks ) : m_ks(ks), m_host(host) {} + void callback_run() { + if (!*m_ks) callInMainThread::callThis( m_host ); + } + private: + killswitch_t m_ks; + host_t * m_host; + }; + + void add(func_t f) { + add_( new service_impl_t< entryFunc > ( f, m_ks ) ); + } + + template + void add( host_t * host, arg_t const & arg) { + add_( new service_impl_t< entry >( host, arg, m_ks ) ); + } + template + void add( host_t * host ) { + add_( new service_impl_t< entryVoid >( host, m_ks ) ); + } + void add_( main_thread_callback::ptr cb ) { + main_thread_callback_add( cb ); + } + + callInMainThreadHelper() { + m_ks.new_t(); + * m_ks = false; + } + void shutdown() { + PFC_ASSERT( core_api::is_main_thread() ); + * m_ks = true; + } + ~callInMainThreadHelper() { + shutdown(); + } + +private: + killswitch_t m_ks; + +}; diff --git a/3rdparty/foo_SDK/foobar2000/helpers/callback_merit.h b/3rdparty/foo_SDK/foobar2000/helpers/callback_merit.h new file mode 100644 index 00000000..a0a96855 --- /dev/null +++ b/3rdparty/foo_SDK/foobar2000/helpers/callback_merit.h @@ -0,0 +1,31 @@ +#pragma once +#include +#include +#include + +namespace fb2k { + // Call global callbacks in correct order + // INTENDED FOR CORE USE ONLY + // Not aware of dynamically registered callbacks, if there are such for the same event type + // Usage: for_each_callback_by_merit< metadb_io_edit_callback > ( [] ( metadb_io_edit_callback::ptr ) { ...} ); + template + void for_each_callback_by_merit(std::function)> f) { + struct rec_t { + class_t* obj; // non-autoptr INTENDED, avoid destruction order bugs on shutdown + fb2k::callback_merit_t merit; + }; + auto generator = [] { + std::vector ret; ret.reserve(64); + for (auto ptr : class_t::enumerate()) { + rec_t r; + r.merit = fb2k::callback_merit_of(ptr); + r.obj = ptr.detach(); + ret.push_back( std::move(r) ); + } + std::sort(ret.begin(), ret.end(), [](rec_t const& e1, rec_t const& e2) { return e1.merit > e2.merit; }); + return ret; + }; + static std::vector cache = generator(); + for (auto& walk : cache) f(walk.obj); + } +} diff --git a/3rdparty/foo_SDK/foobar2000/helpers/cfg_objList.h b/3rdparty/foo_SDK/foobar2000/helpers/cfg_objList.h index 293bd9a2..7da35a59 100644 --- a/3rdparty/foo_SDK/foobar2000/helpers/cfg_objList.h +++ b/3rdparty/foo_SDK/foobar2000/helpers/cfg_objList.h @@ -23,17 +23,20 @@ namespace cfg_var_modern { if (gone > 0) save(); return gone; } + //! Returns number of items removed. template size_t remove_if(pred_t&& p) { init(); PFC_INSYNC_WRITE(m_listGuard); - size_t gone = pfc::remove_if_t(m_list, std::forward(p)); + const auto nBefore = m_list.size(); + const size_t nAfter = pfc::remove_if_t(m_list, std::forward(p)); + const auto gone = nAfter - nBefore; if (gone > 0) save(); return gone; } bool remove_item(obj_t const& v) { return remove_if([&v](const obj_t& arg) { return v == arg; }) != 0; } - size_t size() { init(); return m_list.size(); } + size_t size() { init(); PFC_INSYNC_READ(m_listGuard);return m_list.size(); } size_t get_count() { return size(); } size_t get_size() { return size(); } @@ -110,16 +113,16 @@ namespace cfg_var_modern { void init() { std::call_once(m_init, [this] { auto blob = fb2k::configStore::get()->getConfigBlob(formatName(), nullptr); - if (blob.is_valid()) { + if (blob.is_valid()) try { stream_reader_formatter_simple<> reader(blob->data(), blob->size()); std::vector data; uint32_t count; reader >> count; data.resize(count); for (auto& v : data) reader >> v; set_(std::move(data), false); - } else { - set_(m_defaults, false); - } - }); + return; + } catch(...) {} // fall through, set defaults + set_(m_defaults, false); + }); } template void set_(arg_t&& arg, bool bSave = true) { diff --git a/3rdparty/foo_SDK/foobar2000/helpers/cuesheet_index_list.cpp b/3rdparty/foo_SDK/foobar2000/helpers/cuesheet_index_list.cpp index 5e777668..a851a512 100644 --- a/3rdparty/foo_SDK/foobar2000/helpers/cuesheet_index_list.cpp +++ b/3rdparty/foo_SDK/foobar2000/helpers/cuesheet_index_list.cpp @@ -34,7 +34,7 @@ void t_cuesheet_index_list::to_infos(file_info & p_out) const for(unsigned n=2;n 0) p_out.info_set(namebuffer,cuesheet_format_index_time(position)); @@ -63,7 +63,7 @@ bool t_cuesheet_index_list::from_infos(file_info const & p_in,double p_base) for(unsigned n=2;n ( std::move(work) ) ); kickWork(); } void flush() { @@ -30,7 +30,7 @@ namespace fb2k { } void kickWork() { PFC_ASSERT( core_api::is_main_thread() ); - if (!m_working && m_workQueue.size() > 0) { + if (!m_working && !m_workQueue.empty()) { m_working = true; auto iter = m_workQueue.begin(); auto work = std::move(*iter); m_workQueue.erase(iter); @@ -38,11 +38,13 @@ namespace fb2k { auto a = m_abort; fb2k::inCpuWorkerThread( [ work, pThis, a] { try { - if ( work.work ) work.work(); + // release lambdas early, synchronously from same context as they're executed + { auto f = std::move(work->work); if (f) f(); } a->check(); fb2k::inMainThread( [work, pThis, a] { if ( ! a->is_set() ) { - work.done(); + // release lambdas early, synchronously from same context as they're executed + { auto f = std::move(work->done); if (f) f(); } pThis->workDone(); } }); @@ -61,7 +63,7 @@ namespace fb2k { std::shared_ptr m_abort = std::make_shared(); bool m_working = false; - std::list m_workQueue; + std::list< std::shared_ptr > m_workQueue; }; } diff --git a/3rdparty/foo_SDK/foobar2000/helpers/file_readonly.h b/3rdparty/foo_SDK/foobar2000/helpers/file_readonly.h deleted file mode 100644 index 03cb87c4..00000000 --- a/3rdparty/foo_SDK/foobar2000/helpers/file_readonly.h +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once -// fb2k mobile compat - -#include "../SDK/filesystem_helper.h" \ No newline at end of file diff --git a/3rdparty/foo_SDK/foobar2000/helpers/file_streamstub.h b/3rdparty/foo_SDK/foobar2000/helpers/file_streamstub.h new file mode 100644 index 00000000..877eb0f3 --- /dev/null +++ b/3rdparty/foo_SDK/foobar2000/helpers/file_streamstub.h @@ -0,0 +1,19 @@ +#pragma once + +//! Stub implementation of file object, no file content, only info. +class file_streamstub : public file_readonly { +public: + t_size read(void*, t_size, abort_callback&) override { return 0; } + t_filesize get_size(abort_callback&) override { return filesize_invalid; } + t_filesize get_position(abort_callback&) override { return 0; } + bool get_content_type(pfc::string_base& out) override { + if (m_contentType.length() > 0) { out = m_contentType; return true; } else return false; + } + bool is_remote() override { return m_remote; } + void reopen(abort_callback&) override {} + void seek(t_filesize, abort_callback&) override { throw exception_io_object_not_seekable(); } + bool can_seek() override { return false; } + + pfc::string8 m_contentType; + bool m_remote = true; +}; diff --git a/3rdparty/foo_SDK/foobar2000/helpers/file_win32_wrapper.cpp b/3rdparty/foo_SDK/foobar2000/helpers/file_win32_wrapper.cpp index 9f65ea97..b79ae0df 100644 --- a/3rdparty/foo_SDK/foobar2000/helpers/file_win32_wrapper.cpp +++ b/3rdparty/foo_SDK/foobar2000/helpers/file_win32_wrapper.cpp @@ -6,16 +6,9 @@ namespace file_win32_helpers { t_filesize get_size(HANDLE p_handle) { - union { - t_uint64 val64; - t_uint32 val32[2]; - } u; - - u.val64 = 0; - SetLastError(NO_ERROR); - u.val32[0] = GetFileSize(p_handle,reinterpret_cast(&u.val32[1])); - if (GetLastError()!=NO_ERROR) exception_io_from_win32(GetLastError()); - return u.val64; + LARGE_INTEGER v = {}; + WIN32_IO_OP(GetFileSizeEx(p_handle, &v)); + return make_uint64(v); } void seek(HANDLE p_handle,t_sfilesize p_position,file::t_seek_mode p_mode) { union { @@ -225,6 +218,94 @@ namespace file_win32_helpers { return 0; } + t_filestats2 stats2_from_handle(HANDLE h, const wchar_t * fallbackPath, uint32_t flags, abort_callback& a) { + a.check(); + // Sadly GetFileInformationByHandle() is UNRELIABLE with certain net shares + BY_HANDLE_FILE_INFORMATION info = {}; + if (GetFileInformationByHandle(h, &info)) { + return file_win32_helpers::translate_stats2(info); + } + + a.check(); + t_filestats2 ret; + + // ALWAYS get size, fail if bad handle + ret.m_size = get_size(h); + + if (flags & (stats2_timestamp | stats2_timestampCreate)) { + static_assert(sizeof(t_filetimestamp) == sizeof(FILETIME), "struct sanity"); + FILETIME ftCreate = {}, ftWrite = {}; + if (GetFileTime(h, &ftCreate, nullptr, &ftWrite)) { + ret.m_timestamp = make_uint64(ftWrite); ret.m_timestampCreate = make_uint64(ftCreate); + } + } + if (flags & stats2_flags) { + // No other way to get this from handle? + if (fallbackPath != nullptr && *fallbackPath != 0) { + DWORD attr = GetFileAttributes(fallbackPath); + if (attr != INVALID_FILE_ATTRIBUTES) { + attribs_from_win32(ret, attr); + } + } + } + return ret; + } + void attribs_from_win32(t_filestats2& out, DWORD in) { + out.set_readonly((in & FILE_ATTRIBUTE_READONLY) != 0); + out.set_folder((in & FILE_ATTRIBUTE_DIRECTORY) != 0); + out.set_hidden((in & FILE_ATTRIBUTE_HIDDEN) != 0); + out.set_system((in & FILE_ATTRIBUTE_SYSTEM) != 0); + out.set_remote(false); + } + + + // Seek penalty query, effectively: is this an SSD? + // Credit: + // https://devblogs.microsoft.com/oldnewthing/20201023-00/?p=104395 + static bool queryVolumeSeekPenalty(HANDLE hVolume, bool& out) { + STORAGE_PROPERTY_QUERY query = {}; + query.PropertyId = StorageDeviceSeekPenaltyProperty; + query.QueryType = PropertyStandardQuery; + DWORD count = 1; + DEVICE_SEEK_PENALTY_DESCRIPTOR result = {}; + if (!DeviceIoControl(hVolume, IOCTL_STORAGE_QUERY_PROPERTY, &query, sizeof(query), &result, sizeof(result), &count, nullptr)) { + return false; + } + out = result.IncursSeekPenalty; + return true; + } + + static HANDLE GetVolumeHandleForFile(PCWSTR filePath) { + wchar_t volumePath[MAX_PATH] = {}; + WIN32_OP_D(GetVolumePathName(filePath, volumePath, ARRAYSIZE(volumePath))); + + wchar_t volumeName[MAX_PATH] = {}; + WIN32_OP_D(GetVolumeNameForVolumeMountPoint(volumePath, volumeName, ARRAYSIZE(volumeName))); + + auto length = wcslen(volumeName); + if ( length == 0 ) { + PFC_ASSERT(!"???"); + return NULL; + } + if (length && volumeName[length - 1] == L'\\') { + volumeName[length - 1] = L'\0'; + } + + HANDLE ret; + WIN32_OP_D( ret = CreateFile(volumeName, 0, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, nullptr) ); + return ret; + } + bool querySeekPenalty(const wchar_t* nativePath, bool& out) { + CHandle h; + h.Attach( GetVolumeHandleForFile( nativePath ) ); + if (!h) return false; + return queryVolumeSeekPenalty(h, out); + } + bool querySeekPenalty(const char* fb2k_path, bool& out) { + const char * path = fb2k_path; + if ( matchProtocol(path, "file")) path = afterProtocol(path); + return querySeekPenalty(pfc::wideFromUTF8(path), out); + } } #endif // _WIN32 diff --git a/3rdparty/foo_SDK/foobar2000/helpers/file_win32_wrapper.h b/3rdparty/foo_SDK/foobar2000/helpers/file_win32_wrapper.h index 27067ca1..8d8c6d46 100644 --- a/3rdparty/foo_SDK/foobar2000/helpers/file_win32_wrapper.h +++ b/3rdparty/foo_SDK/foobar2000/helpers/file_win32_wrapper.h @@ -1,6 +1,7 @@ #pragma once #include +#include #ifdef _WIN32 namespace file_win32_helpers { @@ -15,14 +16,18 @@ namespace file_win32_helpers { size_t readStreamOverlapped(HANDLE handle, HANDLE myEvent, void * out, size_t outBytes, abort_callback & abort); HANDLE createFile(LPCTSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile, abort_callback & abort); size_t lowLevelIO(HANDLE hFile, const GUID & guid, size_t arg1, void * arg2, size_t arg2size, bool canWrite, abort_callback & abort); + bool querySeekPenalty(const char * fb2k_path, bool & out); + bool querySeekPenalty(const wchar_t * nativePath, bool & out); - - static t_uint64 make_uint64(t_uint32 p_low, t_uint32 p_high) { + static uint64_t make_uint64(t_uint32 p_low, t_uint32 p_high) { return ((t_uint64)p_low) + ((t_uint64)p_high << 32); } - - static t_uint64 make_uint64(FILETIME const& ft) { - return make_uint64(ft.dwLowDateTime, ft.dwHighDateTime); + static uint64_t make_uint64(LARGE_INTEGER const& i) { + return reinterpret_cast(i); + } + static uint64_t make_uint64(FILETIME const& ft) { + return reinterpret_cast(ft); +// return make_uint64(ft.dwLowDateTime, ft.dwHighDateTime); } template @@ -33,44 +38,47 @@ namespace file_win32_helpers { return ret; } + void attribs_from_win32(t_filestats2& out, DWORD in); template static t_filestats2 translate_stats2(const t_info& p_info) { t_filestats2 ret; ret.m_size = make_uint64(p_info.nFileSizeLow, p_info.nFileSizeHigh); ret.m_timestamp = make_uint64(p_info.ftLastWriteTime); ret.m_timestampCreate = make_uint64(p_info.ftCreationTime); - ret.set_readonly((p_info.dwFileAttributes & FILE_ATTRIBUTE_READONLY) != 0); - ret.set_folder((p_info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0); - ret.set_hidden((p_info.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) != 0); - ret.set_system((p_info.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM) != 0); - ret.set_remote(false); + attribs_from_win32(ret, p_info.dwFileAttributes); return ret; } + + t_filestats2 stats2_from_handle(HANDLE, const wchar_t * fallbackPath, uint32_t flags, abort_callback &a); }; template class file_win32_wrapper_t : public service_multi_inherit { + typedef file_win32_wrapper_t self_t; public: - file_win32_wrapper_t(HANDLE p_handle) : m_handle(p_handle), m_position(0) - { - } + file_win32_wrapper_t(HANDLE handle, pfc::wstringLite && path) : m_handle(handle), m_path(std::move(path)) {} static file::ptr g_CreateFile(const char * p_path,DWORD p_access,DWORD p_sharemode,LPSECURITY_ATTRIBUTES p_security_attributes,DWORD p_createmode,DWORD p_flags,HANDLE p_template) { + auto pathW = pfc::wideFromUTF8(p_path); SetLastError(NO_ERROR); - HANDLE handle = uCreateFile(p_path,p_access,p_sharemode,p_security_attributes,p_createmode,p_flags,p_template); + HANDLE handle = CreateFile(pathW,p_access,p_sharemode,p_security_attributes,p_createmode,p_flags,p_template); if (handle == INVALID_HANDLE_VALUE) { const DWORD code = GetLastError(); if (p_access & GENERIC_WRITE) win32_file_write_failure(code, p_path); else exception_io_from_win32(code); } try { - return g_create_from_handle(handle); + return g_create_from_handle(handle, std::move(pathW)); } catch(...) {CloseHandle(handle); throw;} } - static service_ptr_t g_create_from_handle(HANDLE p_handle) { - return new service_impl_t >(p_handle); + static service_ptr_t g_create_from_handle(HANDLE handle, pfc::wstringLite && path) { + return new service_impl_t(handle, std::move(path)); + } + static service_ptr_t g_create_from_handle(HANDLE handle) { + pfc::wstringLite blank; + g_create_from_handle(handle, std::move(blank)); } @@ -175,18 +183,15 @@ class file_win32_wrapper_t : public service_multi_inherit class file_win32_wrapper_overlapped_t : public service_multi_inherit< file_v2, file_lowLevelIO > { + typedef file_win32_wrapper_overlapped_t self_t; public: - file_win32_wrapper_overlapped_t(HANDLE file) : m_handle(file), m_position() { + file_win32_wrapper_overlapped_t(HANDLE file, pfc::wstringLite && path) : m_handle(file), m_path(std::move(path)) { WIN32_OP( (m_event = CreateEvent(NULL, TRUE, FALSE, NULL)) != NULL ); } ~file_win32_wrapper_overlapped_t() {CloseHandle(m_event); CloseHandle(m_handle);} @@ -257,40 +264,42 @@ class file_win32_wrapper_overlapped_t : public service_multi_inherit< file_v2, f t_filestats2 get_stats2(uint32_t f, abort_callback& a) { a.check(); if (p_writeable) FlushFileBuffers(m_handle); - SetLastError(0); - BY_HANDLE_FILE_INFORMATION info = {}; - if (!GetFileInformationByHandle(m_handle, &info)) exception_io_from_win32(GetLastError()); - return file_win32_helpers::translate_stats2(info); + return file_win32_helpers::stats2_from_handle(m_handle, m_path, f, a); } t_filetimestamp get_timestamp(abort_callback & p_abort) { p_abort.check_e(); if (p_writeable) FlushFileBuffers(m_handle); SetLastError(ERROR_SUCCESS); - t_filetimestamp temp; - if (!GetFileTime(m_handle,0,0,(FILETIME*)&temp)) exception_io_from_win32(GetLastError()); - return temp; + FILETIME temp; + if (!GetFileTime(m_handle,0,0,&temp)) exception_io_from_win32(GetLastError()); + return file_win32_helpers::make_uint64(temp); } bool is_remote() {return false;} static file::ptr g_CreateFile(const char * p_path,DWORD p_access,DWORD p_sharemode,LPSECURITY_ATTRIBUTES p_security_attributes,DWORD p_createmode,DWORD p_flags,HANDLE p_template) { + auto pathW = pfc::wideFromUTF8(p_path); p_flags |= FILE_FLAG_OVERLAPPED; SetLastError(NO_ERROR); - HANDLE handle = uCreateFile(p_path,p_access,p_sharemode,p_security_attributes,p_createmode,p_flags,p_template); + HANDLE handle = CreateFile(pathW,p_access,p_sharemode,p_security_attributes,p_createmode,p_flags,p_template); if (handle == INVALID_HANDLE_VALUE) { const DWORD code = GetLastError(); if (p_access & GENERIC_WRITE) win32_file_write_failure(code, p_path); else exception_io_from_win32(code); } try { - return g_create_from_handle(handle); + return g_create_from_handle(handle, std::move(pathW)); } catch(...) {CloseHandle(handle); throw;} } + static file::ptr g_create_from_handle(HANDLE p_handle, pfc::wstringLite && path) { + return new service_impl_t(p_handle, std::move(path)); + } static file::ptr g_create_from_handle(HANDLE p_handle) { - return new service_impl_t >(p_handle); + pfc::wstringLite blank; + return g_create_from_handle(p_handle, std::move(blank)); } size_t lowLevelIO(const GUID & guid, size_t arg1, void * arg2, size_t arg2size, abort_callback & abort) override { @@ -299,7 +308,8 @@ class file_win32_wrapper_overlapped_t : public service_multi_inherit< file_v2, f protected: HANDLE m_event, m_handle; - t_filesize m_position; + t_filesize m_position = 0; + pfc::wstringLite m_path; }; #endif // _WIN32 diff --git a/3rdparty/foo_SDK/foobar2000/helpers/filetimetools.cpp b/3rdparty/foo_SDK/foobar2000/helpers/filetimetools.cpp index ec6ef448..21aec0a4 100644 --- a/3rdparty/foo_SDK/foobar2000/helpers/filetimetools.cpp +++ b/3rdparty/foo_SDK/foobar2000/helpers/filetimetools.cpp @@ -2,323 +2,27 @@ #include "filetimetools.h" -#include +#include -typedef exception_io_data exception_time_error; - -#ifndef _WIN32 -namespace { - typedef uint16_t WORD; - - typedef struct _SYSTEMTIME { - WORD wYear; - WORD wMonth; - WORD wDayOfWeek; - WORD wDay; - WORD wHour; - WORD wMinute; - WORD wSecond; - WORD wMilliseconds; - } SYSTEMTIME, * PSYSTEMTIME, * LPSYSTEMTIME; - -} -static void SystemTimeToNix(const SYSTEMTIME& st, struct tm& Time) { - memset(&Time, 0, sizeof(Time)); - Time.tm_sec = st.wSecond; - Time.tm_min = st.wMinute; - Time.tm_hour = st.wHour; - Time.tm_mday = st.wDay; - Time.tm_mon = st.wMonth - 1; - Time.tm_year = st.wYear - 1900; -} - -static t_filetimestamp ExportSystemTime(const SYSTEMTIME& st) { - struct tm Time; - SystemTimeToNix(st, Time); - return pfc::fileTimeUtoW(mktime(&Time)); -} - -static t_filetimestamp ExportSystemTimeLocal(const SYSTEMTIME& st) { - struct tm Time, Local; - SystemTimeToNix(st, Time); - time_t t = mktime(&Time); - localtime_r(&t, &Local); - return pfc::fileTimeUtoW(mktime(&Local)); -} -static void SystemTimeFromNix(SYSTEMTIME& st, struct tm const& Time) { - memset(&st, 0, sizeof(st)); - st.wSecond = Time.tm_sec; - st.wMinute = Time.tm_min; - st.wHour = Time.tm_hour; - st.wDay = Time.tm_mday; - st.wDayOfWeek = Time.tm_wday; - st.wMonth = Time.tm_mon + 1; - st.wYear = Time.tm_year + 1900; -} - -static bool MakeSystemTime(SYSTEMTIME& st, t_filetimestamp ts) { - time_t t = (time_t)pfc::fileTimeWtoU(ts); - struct tm Time; - if (gmtime_r(&t, &Time) == NULL) return false; - SystemTimeFromNix(st, Time); - return true; -} - -static bool MakeSystemTimeLocal(SYSTEMTIME& st, t_filetimestamp ts) { - time_t t = (time_t)pfc::fileTimeWtoU(ts); - struct tm Time; - if (localtime_r(&t, &Time) == NULL) return false; - SystemTimeFromNix(st, Time); - return true; -} - -#else -static t_filetimestamp ExportSystemTime(const SYSTEMTIME& st) { - t_filetimestamp base; - if (!SystemTimeToFileTime(&st, (FILETIME*)&base)) throw exception_time_error(); - return base; -} -static t_filetimestamp ExportSystemTimeLocal(const SYSTEMTIME& st) { -#ifdef FOOBAR2000_DESKTOP_WINDOWS - t_filetimestamp base, out; - if (!SystemTimeToFileTime(&st, (FILETIME*)&base)) throw exception_time_error(); - if (!LocalFileTimeToFileTime((const FILETIME*)&base, (FILETIME*)&out)) throw exception_time_error(); - return out; -#else - SYSTEMTIME UTC; - if (!TzSpecificLocalTimeToSystemTime(NULL, &st, &UTC)) throw exception_time_error(); - return ExportSystemTime(UTC); -#endif -} -static bool MakeSystemTime(SYSTEMTIME& st, t_filetimestamp ts) { - if (ts == filetimestamp_invalid) return false; - return !!FileTimeToSystemTime((const FILETIME*)&ts, &st); - -} -static bool MakeSystemTimeLocal(SYSTEMTIME& st, t_filetimestamp ts) { - if (ts == filetimestamp_invalid) return false; -#ifdef FOOBAR2000_DESKTOP_WINDOWS - FILETIME ft; - if (FileTimeToLocalFileTime((FILETIME*)&ts, &ft)) { - if (FileTimeToSystemTime(&ft, &st)) { - return true; - } - } - return false; -#else - SYSTEMTIME UTC; - if (FileTimeToSystemTime((FILETIME*)&ts, &UTC)) { - if (SystemTimeToTzSpecificLocalTime(NULL, &UTC, &st)) return true; - } - return false; -#endif -} -#endif // _WIN32 - -static bool is_spacing(char c) { return c == ' ' || c == 10 || c == 13 || c == '\t'; } - -static unsigned ParseDateElem(const char* ptr, t_size len) { - unsigned ret = 0; - for (t_size walk = 0; walk < len; ++walk) { - const char c = ptr[walk]; - if (c < '0' || c > '9') throw exception_time_error(); - ret = ret * 10 + (unsigned)(c - '0'); - } - return ret; -} - -static bool st_sanity(SYSTEMTIME const& st) { - return st.wYear >= 1601 && st.wMonth >= 1 && st.wMonth <= 12 && st.wDay >= 1 && st.wDay <= 31 && st.wHour < 24 && st.wMinute < 60 && st.wSecond < 60 && st.wMilliseconds < 1000; -} -static t_filetimestamp filetimestamp_from_string_internal(const char* date, bool local) { - // Accepted format - // YYYY-MM-DD HH:MM:SS - try { - SYSTEMTIME st = {}; - st.wDay = 1; st.wMonth = 1; - - unsigned walk = 0; - auto worker = [&](unsigned n) { - auto ret = ParseDateElem(date + walk, n); - walk += n; - if (ret > UINT16_MAX) throw exception_time_error(); - return (WORD)ret;; - }; - - auto skip = [&](char c) { - if (date[walk] == c) ++walk; - }; - - auto skipSpacing = [&] { - while (is_spacing(date[walk])) ++walk; - }; - skipSpacing(); - st.wYear = worker(4); - skip('-'); - st.wMonth = worker(2); - skip('-'); - st.wDay = worker(2); - skipSpacing(); - st.wHour = worker(2); - skip(':'); - st.wMinute = worker(2); - skip(':'); - st.wSecond = worker(2); - if (date[walk] == '.') { - double v = pfc::string_to_float(date + walk); - st.wMilliseconds = (WORD)floor(v * 1000.f); // don't ever round up, don't want to handle ms of 1000 - } - - if (!st_sanity(st)) throw exception_time_error(); - - if (local) { - return ExportSystemTimeLocal(st); - } else { - return ExportSystemTime(st); - } - } catch (exception_time_error) { - return filetimestamp_invalid; - } -} +// Stub - functionality moved to PFC namespace foobar2000_io { - t_filetimestamp filetimestamp_from_string(const char* date) { - return filetimestamp_from_string_internal(date, true); - } - - t_filetimestamp filetimestamp_from_string_utc(const char* date) { - return filetimestamp_from_string_internal(date, false); - } - - static constexpr char g_invalidMsg[] = ""; - - pfc::string_formatter format_filetimestamp(t_filetimestamp p_timestamp) { - try { - SYSTEMTIME st; - if (MakeSystemTimeLocal(st, p_timestamp)) { - pfc::string_formatter buffer; - buffer - << pfc::format_uint(st.wYear, 4) << "-" << pfc::format_uint(st.wMonth, 2) << "-" << pfc::format_uint(st.wDay, 2) << " " - << pfc::format_uint(st.wHour, 2) << ":" << pfc::format_uint(st.wMinute, 2) << ":" << pfc::format_uint(st.wSecond, 2); - return buffer; - } - } catch (...) {} - return g_invalidMsg; - } - - pfc::string_formatter format_filetimestamp_ms(t_filetimestamp p_timestamp) { - try { - SYSTEMTIME st; - if (MakeSystemTimeLocal(st, p_timestamp)) { - pfc::string_formatter buffer; - buffer - << pfc::format_uint(st.wYear, 4) << "-" << pfc::format_uint(st.wMonth, 2) << "-" << pfc::format_uint(st.wDay, 2) << " " - << pfc::format_uint(st.wHour, 2) << ":" << pfc::format_uint(st.wMinute, 2) << ":" << pfc::format_uint(st.wSecond, 2) << "." << pfc::format_uint(st.wMilliseconds, 3); - return buffer; - } - } catch (...) {} - return g_invalidMsg; - } - - pfc::string_formatter format_filetimestamp_utc(t_filetimestamp p_timestamp) { - try { - SYSTEMTIME st; - if (MakeSystemTime(st, p_timestamp)) { - pfc::string_formatter buffer; - buffer - << pfc::format_uint(st.wYear, 4) << "-" << pfc::format_uint(st.wMonth, 2) << "-" << pfc::format_uint(st.wDay, 2) << " " - << pfc::format_uint(st.wHour, 2) << ":" << pfc::format_uint(st.wMinute, 2) << ":" << pfc::format_uint(st.wSecond, 2); - return buffer; - } - } catch (...) {} - return g_invalidMsg; - } - -} // namespace foobar2000_io - -namespace { - struct dateISO_t { - unsigned Y, M, D; - unsigned h, m, s; - double sfrac; - int tzdelta; - }; - - dateISO_t read_ISO_8601(const char* dateISO) { - dateISO_t ret = {}; - // 2022-01-26T13:44:51.200000Z - // 2010-02-19T14:54:23.031+08:00 - // 2022-01-27T11:01:49+00:00 - // 2022-01-27T11:01:49Z - // 20220127T110149Z - - unsigned walk = 0; - auto worker = [&](unsigned n) { - auto ret = ParseDateElem(dateISO + walk, n); - walk += n; - return ret; - }; - auto skip = [&](char c) { - if (dateISO[walk] == c) ++walk; - }; - auto expect = [&](char c) { - if (dateISO[walk] != c) throw exception_time_error(); - ++walk; - }; - ret.Y = worker(4); - skip('-'); - ret.M = worker(2); - skip('-'); - ret.D = worker(2); - expect('T'); - ret.h = worker(2); - skip(':'); - ret.m = worker(2); - skip(':'); - ret.s = worker(2); - if (dateISO[walk] == '.') { - unsigned base = walk; - ++walk; - while (pfc::char_is_numeric(dateISO[walk])) ++walk; - ret.sfrac = pfc::string_to_float(dateISO + base, walk - base); - } - if (dateISO[walk] == '+' || dateISO[walk] == '-') { - bool neg = dateISO[walk] == '-'; - ++walk; - unsigned tz_h = worker(2); - if (tz_h >= 24) throw exception_time_error(); - skip(':'); - unsigned tz_m = worker(2); - if (tz_m >= 60) throw exception_time_error(); - tz_m += tz_h * 60; - ret.tzdelta = neg ? (int)tz_m : -(int)tz_m; // reversed! it's a timezone offset, have to *add* it if timezone has a minus - } - return ret; - } -} - -t_filetimestamp foobar2000_io::filetimestamp_from_string_ISO_8601(const char* dateISO) { - try { - auto elems = read_ISO_8601(dateISO); - - SYSTEMTIME st = {}; - st.wDay = 1; st.wMonth = 1; - st.wYear = elems.Y; - st.wMonth = elems.M; - st.wDay = elems.D; - st.wHour = elems.h; - st.wMinute = elems.m; - st.wSecond = elems.s; - st.wMilliseconds = (WORD)floor(elems.sfrac * 1000.f); - - if (!st_sanity(st)) throw exception_time_error(); - - auto ret = ExportSystemTime(st); - - ret += filetimestamp_1second_increment * elems.tzdelta * 60; - - return ret; - } catch (...) { - return filetimestamp_invalid; - } + t_filetimestamp filetimestamp_from_string(const char* date) { + return pfc::filetimestamp_from_string( date ); + } + t_filetimestamp filetimestamp_from_string_utc(const char* date) { + return pfc::filetimestamp_from_string_utc( date ); + } + + pfc::string_formatter format_filetimestamp(t_filetimestamp p_timestamp) { + return pfc::format_filetimestamp( p_timestamp ); + } + + pfc::string_formatter format_filetimestamp_utc(t_filetimestamp p_timestamp) { + return pfc::format_filetimestamp_utc( p_timestamp ); + } + + pfc::string_formatter format_filetimestamp_ms(t_filetimestamp p_timestamp) { + return pfc::format_filetimestamp_ms( p_timestamp ); + } } diff --git a/3rdparty/foo_SDK/foobar2000/helpers/filetimetools.h b/3rdparty/foo_SDK/foobar2000/helpers/filetimetools.h index 041ea832..3be36766 100644 --- a/3rdparty/foo_SDK/foobar2000/helpers/filetimetools.h +++ b/3rdparty/foo_SDK/foobar2000/helpers/filetimetools.h @@ -3,8 +3,6 @@ namespace foobar2000_io { t_filetimestamp filetimestamp_from_string(const char * date); t_filetimestamp filetimestamp_from_string_utc(const char* date); - // From ISO 8601 time - t_filetimestamp filetimestamp_from_string_ISO_8601(const char* date); //! Warning: this formats according to system timezone settings, created strings should be used for display only, never for storage. pfc::string_formatter format_filetimestamp(t_filetimestamp p_timestamp); @@ -12,5 +10,4 @@ namespace foobar2000_io { pfc::string_formatter format_filetimestamp_utc(t_filetimestamp p_timestamp); //! Local timestamp with milliseconds pfc::string_formatter format_filetimestamp_ms(t_filetimestamp p_timestamp); - } diff --git a/3rdparty/foo_SDK/foobar2000/helpers/foobar2000_SDK_helpers.xcodeproj/project.pbxproj b/3rdparty/foo_SDK/foobar2000/helpers/foobar2000_SDK_helpers.xcodeproj/project.pbxproj new file mode 100644 index 00000000..51bf0363 --- /dev/null +++ b/3rdparty/foo_SDK/foobar2000/helpers/foobar2000_SDK_helpers.xcodeproj/project.pbxproj @@ -0,0 +1,819 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 0F75F5EA2A6B1DB200A45078 /* dialog_resize_helper.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F5622A6B1DAE00A45078 /* dialog_resize_helper.h */; }; + 0F75F5EB2A6B1DB200A45078 /* input_logging.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F5632A6B1DAE00A45078 /* input_logging.h */; }; + 0F75F5EC2A6B1DB200A45078 /* cfg_var_import.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F75F5642A6B1DAE00A45078 /* cfg_var_import.cpp */; }; + 0F75F5ED2A6B1DB200A45078 /* readers.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F75F5652A6B1DAE00A45078 /* readers.cpp */; }; + 0F75F5EE2A6B1DB200A45078 /* text_file_loader_v2.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F75F5662A6B1DAE00A45078 /* text_file_loader_v2.cpp */; }; + 0F75F5EF2A6B1DB200A45078 /* VisUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F5672A6B1DAE00A45078 /* VisUtils.h */; }; + 0F75F5F02A6B1DB200A45078 /* file_move_helper.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F5682A6B1DAE00A45078 /* file_move_helper.h */; }; + 0F75F5F12A6B1DB200A45078 /* filetimetools.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F5692A6B1DAE00A45078 /* filetimetools.h */; }; + 0F75F5F22A6B1DB200A45078 /* create_directory_helper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F75F56A2A6B1DAE00A45078 /* create_directory_helper.cpp */; }; + 0F75F5F32A6B1DB200A45078 /* writer_wav.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F56B2A6B1DAE00A45078 /* writer_wav.h */; }; + 0F75F5F42A6B1DB200A45078 /* VisUtils.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F75F56C2A6B1DAE00A45078 /* VisUtils.cpp */; }; + 0F75F5F52A6B1DB200A45078 /* COM_utils.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F56D2A6B1DAE00A45078 /* COM_utils.h */; }; + 0F75F5F62A6B1DB200A45078 /* VolumeMap.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F56E2A6B1DAE00A45078 /* VolumeMap.h */; }; + 0F75F5F72A6B1DB200A45078 /* file_win32_wrapper.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F56F2A6B1DAE00A45078 /* file_win32_wrapper.h */; }; + 0F75F5F82A6B1DB200A45078 /* foobar2000-lite+atl.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F5702A6B1DAE00A45078 /* foobar2000-lite+atl.h */; }; + 0F75F5F92A6B1DB200A45078 /* metadb_handle_array.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F5712A6B1DAE00A45078 /* metadb_handle_array.h */; }; + 0F75F5FA2A6B1DB200A45078 /* atl-misc.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F5722A6B1DAE00A45078 /* atl-misc.h */; }; + 0F75F5FB2A6B1DB200A45078 /* CSingleThreadWrapper.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F5732A6B1DAE00A45078 /* CSingleThreadWrapper.h */; }; + 0F75F5FC2A6B1DB200A45078 /* image_load_save.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F5742A6B1DAE00A45078 /* image_load_save.h */; }; + 0F75F5FD2A6B1DB200A45078 /* reader_pretend_nonseekable.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F5752A6B1DAF00A45078 /* reader_pretend_nonseekable.h */; }; + 0F75F5FF2A6B1DB200A45078 /* meta_table_builder.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F5772A6B1DAF00A45078 /* meta_table_builder.h */; }; + 0F75F6002A6B1DB200A45078 /* fb2k_threads.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F5782A6B1DAF00A45078 /* fb2k_threads.h */; }; + 0F75F6012A6B1DB200A45078 /* playlist_position_reference_tracker.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F5792A6B1DAF00A45078 /* playlist_position_reference_tracker.h */; }; + 0F75F6022A6B1DB200A45078 /* file_list_helper.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F57A2A6B1DAF00A45078 /* file_list_helper.h */; }; + 0F75F6032A6B1DB200A45078 /* inplace_edit.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F57B2A6B1DAF00A45078 /* inplace_edit.h */; }; + 0F75F6042A6B1DB200A45078 /* album_art_helpers.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F75F57C2A6B1DAF00A45078 /* album_art_helpers.cpp */; }; + 0F75F6052A6B1DB200A45078 /* AutoComplete.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F57D2A6B1DAF00A45078 /* AutoComplete.h */; }; + 0F75F6062A6B1DB200A45078 /* ProfileCache.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F57E2A6B1DAF00A45078 /* ProfileCache.h */; }; + 0F75F6072A6B1DB200A45078 /* fileReadAhead.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F57F2A6B1DAF00A45078 /* fileReadAhead.h */; }; + 0F75F6082A6B1DB200A45078 /* cfg_dsp_chain_config.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F5802A6B1DAF00A45078 /* cfg_dsp_chain_config.h */; }; + 0F75F6092A6B1DB200A45078 /* metadb_io_callback_v2_data.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F5812A6B1DAF00A45078 /* metadb_io_callback_v2_data.h */; }; + 0F75F60A2A6B1DB200A45078 /* cue_parser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F75F5822A6B1DAF00A45078 /* cue_parser.cpp */; }; + 0F75F60C2A6B1DB200A45078 /* ui_element_helpers.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F5842A6B1DAF00A45078 /* ui_element_helpers.h */; }; + 0F75F60D2A6B1DB200A45078 /* CListControlFb2kColors.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F5852A6B1DAF00A45078 /* CListControlFb2kColors.h */; }; + 0F75F60E2A6B1DB200A45078 /* stream_buffer_helper.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F5862A6B1DAF00A45078 /* stream_buffer_helper.h */; }; + 0F75F60F2A6B1DB200A45078 /* advconfig_runtime.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F5872A6B1DAF00A45078 /* advconfig_runtime.h */; }; + 0F75F6102A6B1DB200A45078 /* readWriteLock.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F5882A6B1DAF00A45078 /* readWriteLock.h */; }; + 0F75F6112A6B1DB200A45078 /* writer_wav.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F75F5892A6B1DAF00A45078 /* writer_wav.cpp */; }; + 0F75F6122A6B1DB200A45078 /* fb2kWorkerTool.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F58A2A6B1DAF00A45078 /* fb2kWorkerTool.h */; }; + 0F75F6132A6B1DB200A45078 /* cfg_objList.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F58B2A6B1DAF00A45078 /* cfg_objList.h */; }; + 0F75F6142A6B1DB200A45078 /* CDialogResizeHelper.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F58C2A6B1DAF00A45078 /* CDialogResizeHelper.h */; }; + 0F75F6152A6B1DB200A45078 /* file_info_const_impl.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F58D2A6B1DAF00A45078 /* file_info_const_impl.h */; }; + 0F75F6162A6B1DB200A45078 /* file_list_helper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F75F58E2A6B1DAF00A45078 /* file_list_helper.cpp */; }; + 0F75F6172A6B1DB200A45078 /* albumArtCache.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F58F2A6B1DAF00A45078 /* albumArtCache.h */; }; + 0F75F6182A6B1DB200A45078 /* rethrow.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F5902A6B1DAF00A45078 /* rethrow.h */; }; + 0F75F6192A6B1DB200A45078 /* cfg_var_import.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F5912A6B1DAF00A45078 /* cfg_var_import.h */; }; + 0F75F61A2A6B1DB200A45078 /* album_art_helpers.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F5922A6B1DB000A45078 /* album_art_helpers.h */; }; + 0F75F61B2A6B1DB200A45078 /* create_directory_helper.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F5932A6B1DB000A45078 /* create_directory_helper.h */; }; + 0F75F61C2A6B1DB200A45078 /* input_helpers.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F5942A6B1DB000A45078 /* input_helpers.h */; }; + 0F75F61D2A6B1DB200A45078 /* notifyList.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F5952A6B1DB000A45078 /* notifyList.h */; }; + 0F75F6202A6B1DB200A45078 /* win-MulDiv.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F5982A6B1DB000A45078 /* win-MulDiv.h */; }; + 0F75F6212A6B1DB200A45078 /* metadb_info_container_impl.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F5992A6B1DB000A45078 /* metadb_info_container_impl.h */; }; + 0F75F6222A6B1DB200A45078 /* metadb_io_hintlist.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F59A2A6B1DB000A45078 /* metadb_io_hintlist.h */; }; + 0F75F6232A6B1DB200A45078 /* track_property_callback_impl.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F59B2A6B1DB000A45078 /* track_property_callback_impl.h */; }; + 0F75F6242A6B1DB200A45078 /* filetimetools.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F75F59C2A6B1DB000A45078 /* filetimetools.cpp */; }; + 0F75F6252A6B1DB200A45078 /* ProcessUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F59D2A6B1DB000A45078 /* ProcessUtils.h */; }; + 0F75F6262A6B1DB200A45078 /* readers.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F59E2A6B1DB000A45078 /* readers.h */; }; + 0F75F6272A6B1DB200A45078 /* VolumeMap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F75F59F2A6B1DB000A45078 /* VolumeMap.cpp */; }; + 0F75F6282A6B1DB200A45078 /* cfg_guidlist.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F75F5A02A6B1DB000A45078 /* cfg_guidlist.cpp */; }; + 0F75F6292A6B1DB200A45078 /* dropdown_helper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F75F5A12A6B1DB000A45078 /* dropdown_helper.cpp */; }; + 0F75F62A2A6B1DB200A45078 /* callback_merit.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F5A22A6B1DB000A45078 /* callback_merit.h */; }; + 0F75F62B2A6B1DB200A45078 /* cue_creator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F75F5A32A6B1DB000A45078 /* cue_creator.cpp */; }; + 0F75F62C2A6B1DB200A45078 /* CPropVariant.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F5A42A6B1DB000A45078 /* CPropVariant.h */; }; + 0F75F62D2A6B1DB200A45078 /* text_file_loader_v2.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F5A52A6B1DB000A45078 /* text_file_loader_v2.h */; }; + 0F75F62E2A6B1DB200A45078 /* helpers.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F5A62A6B1DB000A45078 /* helpers.h */; }; + 0F75F6302A6B1DB200A45078 /* dynamic_bitrate_helper.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F5A82A6B1DB000A45078 /* dynamic_bitrate_helper.h */; }; + 0F75F6312A6B1DB200A45078 /* packet_decoder_mp3_common.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F5A92A6B1DB000A45078 /* packet_decoder_mp3_common.h */; }; + 0F75F6322A6B1DB200A45078 /* foobar2000+atl.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F5AA2A6B1DB000A45078 /* foobar2000+atl.h */; }; + 0F75F6332A6B1DB200A45078 /* CallForwarder.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F5AB2A6B1DB000A45078 /* CallForwarder.h */; }; + 0F75F6342A6B1DB200A45078 /* StdAfx.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F75F5AC2A6B1DB000A45078 /* StdAfx.cpp */; }; + 0F75F6352A6B1DB200A45078 /* CTableEditHelper-Legacy.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F5AD2A6B1DB100A45078 /* CTableEditHelper-Legacy.h */; }; + 0F75F6362A6B1DB200A45078 /* window_placement_helper.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F5AE2A6B1DB100A45078 /* window_placement_helper.h */; }; + 0F75F6372A6B1DB200A45078 /* input_helper_cue.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F5AF2A6B1DB100A45078 /* input_helper_cue.h */; }; + 0F75F6382A6B1DB200A45078 /* cuesheet_index_list.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F75F5B02A6B1DB100A45078 /* cuesheet_index_list.cpp */; }; + 0F75F6392A6B1DB200A45078 /* win-systemtime.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F75F5B12A6B1DB100A45078 /* win-systemtime.cpp */; }; + 0F75F63A2A6B1DB200A45078 /* dynamic_bitrate_helper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F75F5B22A6B1DB100A45078 /* dynamic_bitrate_helper.cpp */; }; + 0F75F63B2A6B1DB200A45078 /* bitreader_helper.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F5B32A6B1DB100A45078 /* bitreader_helper.h */; }; + 0F75F63C2A6B1DB200A45078 /* StdAfx.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F5B42A6B1DB100A45078 /* StdAfx.h */; }; + 0F75F63D2A6B1DB200A45078 /* packet_decoder_aac_common.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F5B52A6B1DB100A45078 /* packet_decoder_aac_common.h */; }; + 0F75F63E2A6B1DB200A45078 /* CmdThread.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F5B62A6B1DB100A45078 /* CmdThread.h */; }; + 0F75F63F2A6B1DB200A45078 /* readers_lite.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F5B72A6B1DB100A45078 /* readers_lite.h */; }; + 0F75F6402A6B1DB200A45078 /* text_file_loader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F75F5B82A6B1DB100A45078 /* text_file_loader.cpp */; }; + 0F75F6412A6B1DB200A45078 /* cue_creator.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F5B92A6B1DB100A45078 /* cue_creator.h */; }; + 0F75F6422A6B1DB200A45078 /* ThreadUtils.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F75F5BA2A6B1DB100A45078 /* ThreadUtils.cpp */; }; + 0F75F6432A6B1DB200A45078 /* file_streamstub.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F5BB2A6B1DB100A45078 /* file_streamstub.h */; }; + 0F75F6442A6B1DB200A45078 /* tag_write_callback_impl.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F5BC2A6B1DB100A45078 /* tag_write_callback_impl.h */; }; + 0F75F6452A6B1DB200A45078 /* win32_misc.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F75F5BD2A6B1DB100A45078 /* win32_misc.cpp */; }; + 0F75F6462A6B1DB200A45078 /* WindowPositionUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F5BE2A6B1DB100A45078 /* WindowPositionUtils.h */; }; + 0F75F6472A6B1DB200A45078 /* packet_decoder_mp3_common.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F75F5BF2A6B1DB100A45078 /* packet_decoder_mp3_common.cpp */; }; + 0F75F6492A6B1DB200A45078 /* duration_counter.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F5C12A6B1DB100A45078 /* duration_counter.h */; }; + 0F75F64A2A6B1DB200A45078 /* cue_parser.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F5C22A6B1DB100A45078 /* cue_parser.h */; }; + 0F75F64B2A6B1DB200A45078 /* dialog_resize_helper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F75F5C32A6B1DB100A45078 /* dialog_resize_helper.cpp */; }; + 0F75F64C2A6B1DB200A45078 /* seekabilizer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F75F5C42A6B1DB100A45078 /* seekabilizer.cpp */; }; + 0F75F64D2A6B1DB200A45078 /* fullFileBuffer.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F5C52A6B1DB100A45078 /* fullFileBuffer.h */; }; + 0F75F64E2A6B1DB200A45078 /* win32_dialog.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F5C62A6B1DB100A45078 /* win32_dialog.h */; }; + 0F75F64F2A6B1DB200A45078 /* cuesheet_index_list.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F5C72A6B1DB100A45078 /* cuesheet_index_list.h */; }; + 0F75F6502A6B1DB200A45078 /* callInMainThreadHelper.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F5C82A6B1DB100A45078 /* callInMainThreadHelper.h */; }; + 0F75F6512A6B1DB200A45078 /* icon_remapping_wildcard.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F5C92A6B1DB100A45078 /* icon_remapping_wildcard.h */; }; + 0F75F6522A6B1DB200A45078 /* audio_render_float.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F5CA2A6B1DB100A45078 /* audio_render_float.h */; }; + 0F75F6542A6B1DB200A45078 /* advconfig_impl.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F5CC2A6B1DB100A45078 /* advconfig_impl.h */; }; + 0F75F6552A6B1DB200A45078 /* input_fix_seeking.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F5CD2A6B1DB100A45078 /* input_fix_seeking.h */; }; + 0F75F6562A6B1DB200A45078 /* win-systemtime.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F5CE2A6B1DB100A45078 /* win-systemtime.h */; }; + 0F75F6572A6B1DB200A45078 /* stream_buffer_helper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F75F5CF2A6B1DB100A45078 /* stream_buffer_helper.cpp */; }; + 0F75F6582A6B1DB200A45078 /* dsp_dialog.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F5D02A6B1DB100A45078 /* dsp_dialog.h */; }; + 0F75F6592A6B1DB200A45078 /* BumpableElem.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F5D12A6B1DB100A45078 /* BumpableElem.h */; }; + 0F75F65A2A6B1DB200A45078 /* cfg_obj.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F5D22A6B1DB100A45078 /* cfg_obj.h */; }; + 0F75F65B2A6B1DB200A45078 /* packet_decoder_aac_common.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F75F5D32A6B1DB200A45078 /* packet_decoder_aac_common.cpp */; }; + 0F75F65C2A6B1DB200A45078 /* mp3_utils.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F5D42A6B1DB200A45078 /* mp3_utils.h */; }; + 0F75F65D2A6B1DB200A45078 /* cue_parser_embedding.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F75F5D52A6B1DB200A45078 /* cue_parser_embedding.cpp */; }; + 0F75F65E2A6B1DB200A45078 /* input_helpers.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F75F5D62A6B1DB200A45078 /* input_helpers.cpp */; }; + 0F75F65F2A6B1DB200A45078 /* ThreadUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F5D72A6B1DB200A45078 /* ThreadUtils.h */; }; + 0F75F6602A6B1DB200A45078 /* track_property_callback_impl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F75F5D82A6B1DB200A45078 /* track_property_callback_impl.cpp */; }; + 0F75F6622A6B1DB200A45078 /* fb2k_wfx.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F5DA2A6B1DB200A45078 /* fb2k_wfx.h */; }; + 0F75F6632A6B1DB200A45078 /* DarkMode.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F5DB2A6B1DB200A45078 /* DarkMode.h */; }; + 0F75F6642A6B1DB200A45078 /* win32_misc.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F5DC2A6B1DB200A45078 /* win32_misc.h */; }; + 0F75F6652A6B1DB200A45078 /* winmm-types.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F5DD2A6B1DB200A45078 /* winmm-types.h */; }; + 0F75F6662A6B1DB200A45078 /* metadb_handle_set.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F5DE2A6B1DB200A45078 /* metadb_handle_set.h */; }; + 0F75F6672A6B1DB200A45078 /* mp3_utils.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F75F5DF2A6B1DB200A45078 /* mp3_utils.cpp */; }; + 0F75F6682A6B1DB200A45078 /* file_win32_wrapper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F75F5E02A6B1DB200A45078 /* file_win32_wrapper.cpp */; }; + 0F75F6692A6B1DB200A45078 /* seekabilizer.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F5E12A6B1DB200A45078 /* seekabilizer.h */; }; + 0F75F66A2A6B1DB200A45078 /* file_move_helper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F75F5E22A6B1DB200A45078 /* file_move_helper.cpp */; }; + 0F75F66B2A6B1DB200A45078 /* cfg_guidlist.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F5E32A6B1DB200A45078 /* cfg_guidlist.h */; }; + 0F75F66C2A6B1DB200A45078 /* input_helper_cue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F75F5E42A6B1DB200A45078 /* input_helper_cue.cpp */; }; + 0F75F66D2A6B1DB200A45078 /* text_file_loader.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F5E52A6B1DB200A45078 /* text_file_loader.h */; }; + 0F75F66E2A6B1DB200A45078 /* file_cached.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F5E62A6B1DB200A45078 /* file_cached.h */; }; + 0F75F66F2A6B1DB200A45078 /* input_stream_info_reader.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F5E72A6B1DB200A45078 /* input_stream_info_reader.h */; }; + 0F75F6712A6B1DB200A45078 /* dropdown_helper.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75F5E92A6B1DB200A45078 /* dropdown_helper.h */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 0F75F5622A6B1DAE00A45078 /* dialog_resize_helper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dialog_resize_helper.h; sourceTree = ""; }; + 0F75F5632A6B1DAE00A45078 /* input_logging.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = input_logging.h; sourceTree = ""; }; + 0F75F5642A6B1DAE00A45078 /* cfg_var_import.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = cfg_var_import.cpp; sourceTree = ""; }; + 0F75F5652A6B1DAE00A45078 /* readers.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = readers.cpp; sourceTree = ""; }; + 0F75F5662A6B1DAE00A45078 /* text_file_loader_v2.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = text_file_loader_v2.cpp; sourceTree = ""; }; + 0F75F5672A6B1DAE00A45078 /* VisUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VisUtils.h; sourceTree = ""; }; + 0F75F5682A6B1DAE00A45078 /* file_move_helper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = file_move_helper.h; sourceTree = ""; }; + 0F75F5692A6B1DAE00A45078 /* filetimetools.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = filetimetools.h; sourceTree = ""; }; + 0F75F56A2A6B1DAE00A45078 /* create_directory_helper.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = create_directory_helper.cpp; sourceTree = ""; }; + 0F75F56B2A6B1DAE00A45078 /* writer_wav.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = writer_wav.h; sourceTree = ""; }; + 0F75F56C2A6B1DAE00A45078 /* VisUtils.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = VisUtils.cpp; sourceTree = ""; }; + 0F75F56D2A6B1DAE00A45078 /* COM_utils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = COM_utils.h; sourceTree = ""; }; + 0F75F56E2A6B1DAE00A45078 /* VolumeMap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VolumeMap.h; sourceTree = ""; }; + 0F75F56F2A6B1DAE00A45078 /* file_win32_wrapper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = file_win32_wrapper.h; sourceTree = ""; }; + 0F75F5702A6B1DAE00A45078 /* foobar2000-lite+atl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "foobar2000-lite+atl.h"; sourceTree = ""; }; + 0F75F5712A6B1DAE00A45078 /* metadb_handle_array.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = metadb_handle_array.h; sourceTree = ""; }; + 0F75F5722A6B1DAE00A45078 /* atl-misc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "atl-misc.h"; sourceTree = ""; }; + 0F75F5732A6B1DAE00A45078 /* CSingleThreadWrapper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CSingleThreadWrapper.h; sourceTree = ""; }; + 0F75F5742A6B1DAE00A45078 /* image_load_save.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = image_load_save.h; sourceTree = ""; }; + 0F75F5752A6B1DAF00A45078 /* reader_pretend_nonseekable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = reader_pretend_nonseekable.h; sourceTree = ""; }; + 0F75F5762A6B1DAF00A45078 /* window_placement_helper.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = window_placement_helper.cpp; sourceTree = ""; }; + 0F75F5772A6B1DAF00A45078 /* meta_table_builder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = meta_table_builder.h; sourceTree = ""; }; + 0F75F5782A6B1DAF00A45078 /* fb2k_threads.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fb2k_threads.h; sourceTree = ""; }; + 0F75F5792A6B1DAF00A45078 /* playlist_position_reference_tracker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = playlist_position_reference_tracker.h; sourceTree = ""; }; + 0F75F57A2A6B1DAF00A45078 /* file_list_helper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = file_list_helper.h; sourceTree = ""; }; + 0F75F57B2A6B1DAF00A45078 /* inplace_edit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = inplace_edit.h; sourceTree = ""; }; + 0F75F57C2A6B1DAF00A45078 /* album_art_helpers.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = album_art_helpers.cpp; sourceTree = ""; }; + 0F75F57D2A6B1DAF00A45078 /* AutoComplete.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AutoComplete.h; sourceTree = ""; }; + 0F75F57E2A6B1DAF00A45078 /* ProfileCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ProfileCache.h; sourceTree = ""; }; + 0F75F57F2A6B1DAF00A45078 /* fileReadAhead.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fileReadAhead.h; sourceTree = ""; }; + 0F75F5802A6B1DAF00A45078 /* cfg_dsp_chain_config.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cfg_dsp_chain_config.h; sourceTree = ""; }; + 0F75F5812A6B1DAF00A45078 /* metadb_io_callback_v2_data.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = metadb_io_callback_v2_data.h; sourceTree = ""; }; + 0F75F5822A6B1DAF00A45078 /* cue_parser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = cue_parser.cpp; sourceTree = ""; }; + 0F75F5832A6B1DAF00A45078 /* ui_element_helpers.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ui_element_helpers.cpp; sourceTree = ""; }; + 0F75F5842A6B1DAF00A45078 /* ui_element_helpers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ui_element_helpers.h; sourceTree = ""; }; + 0F75F5852A6B1DAF00A45078 /* CListControlFb2kColors.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CListControlFb2kColors.h; sourceTree = ""; }; + 0F75F5862A6B1DAF00A45078 /* stream_buffer_helper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = stream_buffer_helper.h; sourceTree = ""; }; + 0F75F5872A6B1DAF00A45078 /* advconfig_runtime.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = advconfig_runtime.h; sourceTree = ""; }; + 0F75F5882A6B1DAF00A45078 /* readWriteLock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = readWriteLock.h; sourceTree = ""; }; + 0F75F5892A6B1DAF00A45078 /* writer_wav.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = writer_wav.cpp; sourceTree = ""; }; + 0F75F58A2A6B1DAF00A45078 /* fb2kWorkerTool.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fb2kWorkerTool.h; sourceTree = ""; }; + 0F75F58B2A6B1DAF00A45078 /* cfg_objList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cfg_objList.h; sourceTree = ""; }; + 0F75F58C2A6B1DAF00A45078 /* CDialogResizeHelper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CDialogResizeHelper.h; sourceTree = ""; }; + 0F75F58D2A6B1DAF00A45078 /* file_info_const_impl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = file_info_const_impl.h; sourceTree = ""; }; + 0F75F58E2A6B1DAF00A45078 /* file_list_helper.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = file_list_helper.cpp; sourceTree = ""; }; + 0F75F58F2A6B1DAF00A45078 /* albumArtCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = albumArtCache.h; sourceTree = ""; }; + 0F75F5902A6B1DAF00A45078 /* rethrow.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = rethrow.h; sourceTree = ""; }; + 0F75F5912A6B1DAF00A45078 /* cfg_var_import.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cfg_var_import.h; sourceTree = ""; }; + 0F75F5922A6B1DB000A45078 /* album_art_helpers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = album_art_helpers.h; sourceTree = ""; }; + 0F75F5932A6B1DB000A45078 /* create_directory_helper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = create_directory_helper.h; sourceTree = ""; }; + 0F75F5942A6B1DB000A45078 /* input_helpers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = input_helpers.h; sourceTree = ""; }; + 0F75F5952A6B1DB000A45078 /* notifyList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = notifyList.h; sourceTree = ""; }; + 0F75F5962A6B1DB000A45078 /* inplace_edit.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = inplace_edit.cpp; sourceTree = ""; }; + 0F75F5972A6B1DB000A45078 /* image_load_save.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = image_load_save.cpp; sourceTree = ""; }; + 0F75F5982A6B1DB000A45078 /* win-MulDiv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "win-MulDiv.h"; sourceTree = ""; }; + 0F75F5992A6B1DB000A45078 /* metadb_info_container_impl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = metadb_info_container_impl.h; sourceTree = ""; }; + 0F75F59A2A6B1DB000A45078 /* metadb_io_hintlist.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = metadb_io_hintlist.h; sourceTree = ""; }; + 0F75F59B2A6B1DB000A45078 /* track_property_callback_impl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = track_property_callback_impl.h; sourceTree = ""; }; + 0F75F59C2A6B1DB000A45078 /* filetimetools.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = filetimetools.cpp; sourceTree = ""; }; + 0F75F59D2A6B1DB000A45078 /* ProcessUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ProcessUtils.h; sourceTree = ""; }; + 0F75F59E2A6B1DB000A45078 /* readers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = readers.h; sourceTree = ""; }; + 0F75F59F2A6B1DB000A45078 /* VolumeMap.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = VolumeMap.cpp; sourceTree = ""; }; + 0F75F5A02A6B1DB000A45078 /* cfg_guidlist.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = cfg_guidlist.cpp; sourceTree = ""; }; + 0F75F5A12A6B1DB000A45078 /* dropdown_helper.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = dropdown_helper.cpp; sourceTree = ""; }; + 0F75F5A22A6B1DB000A45078 /* callback_merit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = callback_merit.h; sourceTree = ""; }; + 0F75F5A32A6B1DB000A45078 /* cue_creator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = cue_creator.cpp; sourceTree = ""; }; + 0F75F5A42A6B1DB000A45078 /* CPropVariant.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CPropVariant.h; sourceTree = ""; }; + 0F75F5A52A6B1DB000A45078 /* text_file_loader_v2.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = text_file_loader_v2.h; sourceTree = ""; }; + 0F75F5A62A6B1DB000A45078 /* helpers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = helpers.h; sourceTree = ""; }; + 0F75F5A72A6B1DB000A45078 /* WindowPositionUtils.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WindowPositionUtils.cpp; sourceTree = ""; }; + 0F75F5A82A6B1DB000A45078 /* dynamic_bitrate_helper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dynamic_bitrate_helper.h; sourceTree = ""; }; + 0F75F5A92A6B1DB000A45078 /* packet_decoder_mp3_common.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = packet_decoder_mp3_common.h; sourceTree = ""; }; + 0F75F5AA2A6B1DB000A45078 /* foobar2000+atl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "foobar2000+atl.h"; sourceTree = ""; }; + 0F75F5AB2A6B1DB000A45078 /* CallForwarder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CallForwarder.h; sourceTree = ""; }; + 0F75F5AC2A6B1DB000A45078 /* StdAfx.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StdAfx.cpp; sourceTree = ""; }; + 0F75F5AD2A6B1DB100A45078 /* CTableEditHelper-Legacy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "CTableEditHelper-Legacy.h"; sourceTree = ""; }; + 0F75F5AE2A6B1DB100A45078 /* window_placement_helper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = window_placement_helper.h; sourceTree = ""; }; + 0F75F5AF2A6B1DB100A45078 /* input_helper_cue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = input_helper_cue.h; sourceTree = ""; }; + 0F75F5B02A6B1DB100A45078 /* cuesheet_index_list.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = cuesheet_index_list.cpp; sourceTree = ""; }; + 0F75F5B12A6B1DB100A45078 /* win-systemtime.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "win-systemtime.cpp"; sourceTree = ""; }; + 0F75F5B22A6B1DB100A45078 /* dynamic_bitrate_helper.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = dynamic_bitrate_helper.cpp; sourceTree = ""; }; + 0F75F5B32A6B1DB100A45078 /* bitreader_helper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = bitreader_helper.h; sourceTree = ""; }; + 0F75F5B42A6B1DB100A45078 /* StdAfx.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StdAfx.h; sourceTree = ""; }; + 0F75F5B52A6B1DB100A45078 /* packet_decoder_aac_common.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = packet_decoder_aac_common.h; sourceTree = ""; }; + 0F75F5B62A6B1DB100A45078 /* CmdThread.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CmdThread.h; sourceTree = ""; }; + 0F75F5B72A6B1DB100A45078 /* readers_lite.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = readers_lite.h; sourceTree = ""; }; + 0F75F5B82A6B1DB100A45078 /* text_file_loader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = text_file_loader.cpp; sourceTree = ""; }; + 0F75F5B92A6B1DB100A45078 /* cue_creator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cue_creator.h; sourceTree = ""; }; + 0F75F5BA2A6B1DB100A45078 /* ThreadUtils.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ThreadUtils.cpp; sourceTree = ""; }; + 0F75F5BB2A6B1DB100A45078 /* file_streamstub.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = file_streamstub.h; sourceTree = ""; }; + 0F75F5BC2A6B1DB100A45078 /* tag_write_callback_impl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tag_write_callback_impl.h; sourceTree = ""; }; + 0F75F5BD2A6B1DB100A45078 /* win32_misc.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = win32_misc.cpp; sourceTree = ""; }; + 0F75F5BE2A6B1DB100A45078 /* WindowPositionUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WindowPositionUtils.h; sourceTree = ""; }; + 0F75F5BF2A6B1DB100A45078 /* packet_decoder_mp3_common.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = packet_decoder_mp3_common.cpp; sourceTree = ""; }; + 0F75F5C02A6B1DB100A45078 /* CTableEditHelper-Legacy.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "CTableEditHelper-Legacy.cpp"; sourceTree = ""; }; + 0F75F5C12A6B1DB100A45078 /* duration_counter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = duration_counter.h; sourceTree = ""; }; + 0F75F5C22A6B1DB100A45078 /* cue_parser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cue_parser.h; sourceTree = ""; }; + 0F75F5C32A6B1DB100A45078 /* dialog_resize_helper.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = dialog_resize_helper.cpp; sourceTree = ""; }; + 0F75F5C42A6B1DB100A45078 /* seekabilizer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = seekabilizer.cpp; sourceTree = ""; }; + 0F75F5C52A6B1DB100A45078 /* fullFileBuffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fullFileBuffer.h; sourceTree = ""; }; + 0F75F5C62A6B1DB100A45078 /* win32_dialog.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = win32_dialog.h; sourceTree = ""; }; + 0F75F5C72A6B1DB100A45078 /* cuesheet_index_list.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cuesheet_index_list.h; sourceTree = ""; }; + 0F75F5C82A6B1DB100A45078 /* callInMainThreadHelper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = callInMainThreadHelper.h; sourceTree = ""; }; + 0F75F5C92A6B1DB100A45078 /* icon_remapping_wildcard.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = icon_remapping_wildcard.h; sourceTree = ""; }; + 0F75F5CA2A6B1DB100A45078 /* audio_render_float.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = audio_render_float.h; sourceTree = ""; }; + 0F75F5CB2A6B1DB100A45078 /* win32_dialog.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = win32_dialog.cpp; sourceTree = ""; }; + 0F75F5CC2A6B1DB100A45078 /* advconfig_impl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = advconfig_impl.h; sourceTree = ""; }; + 0F75F5CD2A6B1DB100A45078 /* input_fix_seeking.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = input_fix_seeking.h; sourceTree = ""; }; + 0F75F5CE2A6B1DB100A45078 /* win-systemtime.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "win-systemtime.h"; sourceTree = ""; }; + 0F75F5CF2A6B1DB100A45078 /* stream_buffer_helper.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = stream_buffer_helper.cpp; sourceTree = ""; }; + 0F75F5D02A6B1DB100A45078 /* dsp_dialog.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dsp_dialog.h; sourceTree = ""; }; + 0F75F5D12A6B1DB100A45078 /* BumpableElem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BumpableElem.h; sourceTree = ""; }; + 0F75F5D22A6B1DB100A45078 /* cfg_obj.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cfg_obj.h; sourceTree = ""; }; + 0F75F5D32A6B1DB200A45078 /* packet_decoder_aac_common.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = packet_decoder_aac_common.cpp; sourceTree = ""; }; + 0F75F5D42A6B1DB200A45078 /* mp3_utils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mp3_utils.h; sourceTree = ""; }; + 0F75F5D52A6B1DB200A45078 /* cue_parser_embedding.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = cue_parser_embedding.cpp; sourceTree = ""; }; + 0F75F5D62A6B1DB200A45078 /* input_helpers.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = input_helpers.cpp; sourceTree = ""; }; + 0F75F5D72A6B1DB200A45078 /* ThreadUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ThreadUtils.h; sourceTree = ""; }; + 0F75F5D82A6B1DB200A45078 /* track_property_callback_impl.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = track_property_callback_impl.cpp; sourceTree = ""; }; + 0F75F5D92A6B1DB200A45078 /* AutoComplete.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AutoComplete.cpp; sourceTree = ""; }; + 0F75F5DA2A6B1DB200A45078 /* fb2k_wfx.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fb2k_wfx.h; sourceTree = ""; }; + 0F75F5DB2A6B1DB200A45078 /* DarkMode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DarkMode.h; sourceTree = ""; }; + 0F75F5DC2A6B1DB200A45078 /* win32_misc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = win32_misc.h; sourceTree = ""; }; + 0F75F5DD2A6B1DB200A45078 /* winmm-types.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "winmm-types.h"; sourceTree = ""; }; + 0F75F5DE2A6B1DB200A45078 /* metadb_handle_set.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = metadb_handle_set.h; sourceTree = ""; }; + 0F75F5DF2A6B1DB200A45078 /* mp3_utils.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = mp3_utils.cpp; sourceTree = ""; }; + 0F75F5E02A6B1DB200A45078 /* file_win32_wrapper.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = file_win32_wrapper.cpp; sourceTree = ""; }; + 0F75F5E12A6B1DB200A45078 /* seekabilizer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = seekabilizer.h; sourceTree = ""; }; + 0F75F5E22A6B1DB200A45078 /* file_move_helper.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = file_move_helper.cpp; sourceTree = ""; }; + 0F75F5E32A6B1DB200A45078 /* cfg_guidlist.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cfg_guidlist.h; sourceTree = ""; }; + 0F75F5E42A6B1DB200A45078 /* input_helper_cue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = input_helper_cue.cpp; sourceTree = ""; }; + 0F75F5E52A6B1DB200A45078 /* text_file_loader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = text_file_loader.h; sourceTree = ""; }; + 0F75F5E62A6B1DB200A45078 /* file_cached.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = file_cached.h; sourceTree = ""; }; + 0F75F5E72A6B1DB200A45078 /* input_stream_info_reader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = input_stream_info_reader.h; sourceTree = ""; }; + 0F75F5E82A6B1DB200A45078 /* DarkMode.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DarkMode.cpp; sourceTree = ""; }; + 0F75F5E92A6B1DB200A45078 /* dropdown_helper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dropdown_helper.h; sourceTree = ""; }; + B12D1DB11991061A0087CEF3 /* libfoobar2000_SDK_helpers.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libfoobar2000_SDK_helpers.a; sourceTree = BUILT_PRODUCTS_DIR; }; + B166964A19ACC1560001728F /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; + B166965819ACC1560001728F /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; }; + B166965B19ACC1560001728F /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = Library/Frameworks/UIKit.framework; sourceTree = DEVELOPER_DIR; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + B12D1DAE1991061A0087CEF3 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + B12D1DA81991061A0087CEF3 = { + isa = PBXGroup; + children = ( + B12D1DBE1991063D0087CEF3 /* Source */, + B166964919ACC1560001728F /* Frameworks */, + B12D1DB21991061A0087CEF3 /* Products */, + ); + sourceTree = ""; + }; + B12D1DB21991061A0087CEF3 /* Products */ = { + isa = PBXGroup; + children = ( + B12D1DB11991061A0087CEF3 /* libfoobar2000_SDK_helpers.a */, + ); + name = Products; + sourceTree = ""; + }; + B12D1DBE1991063D0087CEF3 /* Source */ = { + isa = PBXGroup; + children = ( + 0F75F5CC2A6B1DB100A45078 /* advconfig_impl.h */, + 0F75F5872A6B1DAF00A45078 /* advconfig_runtime.h */, + 0F75F57C2A6B1DAF00A45078 /* album_art_helpers.cpp */, + 0F75F5922A6B1DB000A45078 /* album_art_helpers.h */, + 0F75F58F2A6B1DAF00A45078 /* albumArtCache.h */, + 0F75F5722A6B1DAE00A45078 /* atl-misc.h */, + 0F75F5CA2A6B1DB100A45078 /* audio_render_float.h */, + 0F75F5D92A6B1DB200A45078 /* AutoComplete.cpp */, + 0F75F57D2A6B1DAF00A45078 /* AutoComplete.h */, + 0F75F5B32A6B1DB100A45078 /* bitreader_helper.h */, + 0F75F5D12A6B1DB100A45078 /* BumpableElem.h */, + 0F75F5A22A6B1DB000A45078 /* callback_merit.h */, + 0F75F5AB2A6B1DB000A45078 /* CallForwarder.h */, + 0F75F5C82A6B1DB100A45078 /* callInMainThreadHelper.h */, + 0F75F58C2A6B1DAF00A45078 /* CDialogResizeHelper.h */, + 0F75F5802A6B1DAF00A45078 /* cfg_dsp_chain_config.h */, + 0F75F5A02A6B1DB000A45078 /* cfg_guidlist.cpp */, + 0F75F5E32A6B1DB200A45078 /* cfg_guidlist.h */, + 0F75F5D22A6B1DB100A45078 /* cfg_obj.h */, + 0F75F58B2A6B1DAF00A45078 /* cfg_objList.h */, + 0F75F5642A6B1DAE00A45078 /* cfg_var_import.cpp */, + 0F75F5912A6B1DAF00A45078 /* cfg_var_import.h */, + 0F75F5852A6B1DAF00A45078 /* CListControlFb2kColors.h */, + 0F75F5B62A6B1DB100A45078 /* CmdThread.h */, + 0F75F56D2A6B1DAE00A45078 /* COM_utils.h */, + 0F75F5A42A6B1DB000A45078 /* CPropVariant.h */, + 0F75F56A2A6B1DAE00A45078 /* create_directory_helper.cpp */, + 0F75F5932A6B1DB000A45078 /* create_directory_helper.h */, + 0F75F5732A6B1DAE00A45078 /* CSingleThreadWrapper.h */, + 0F75F5C02A6B1DB100A45078 /* CTableEditHelper-Legacy.cpp */, + 0F75F5AD2A6B1DB100A45078 /* CTableEditHelper-Legacy.h */, + 0F75F5A32A6B1DB000A45078 /* cue_creator.cpp */, + 0F75F5B92A6B1DB100A45078 /* cue_creator.h */, + 0F75F5D52A6B1DB200A45078 /* cue_parser_embedding.cpp */, + 0F75F5822A6B1DAF00A45078 /* cue_parser.cpp */, + 0F75F5C22A6B1DB100A45078 /* cue_parser.h */, + 0F75F5B02A6B1DB100A45078 /* cuesheet_index_list.cpp */, + 0F75F5C72A6B1DB100A45078 /* cuesheet_index_list.h */, + 0F75F5E82A6B1DB200A45078 /* DarkMode.cpp */, + 0F75F5DB2A6B1DB200A45078 /* DarkMode.h */, + 0F75F5C32A6B1DB100A45078 /* dialog_resize_helper.cpp */, + 0F75F5622A6B1DAE00A45078 /* dialog_resize_helper.h */, + 0F75F5A12A6B1DB000A45078 /* dropdown_helper.cpp */, + 0F75F5E92A6B1DB200A45078 /* dropdown_helper.h */, + 0F75F5D02A6B1DB100A45078 /* dsp_dialog.h */, + 0F75F5C12A6B1DB100A45078 /* duration_counter.h */, + 0F75F5B22A6B1DB100A45078 /* dynamic_bitrate_helper.cpp */, + 0F75F5A82A6B1DB000A45078 /* dynamic_bitrate_helper.h */, + 0F75F5782A6B1DAF00A45078 /* fb2k_threads.h */, + 0F75F5DA2A6B1DB200A45078 /* fb2k_wfx.h */, + 0F75F58A2A6B1DAF00A45078 /* fb2kWorkerTool.h */, + 0F75F5E62A6B1DB200A45078 /* file_cached.h */, + 0F75F58D2A6B1DAF00A45078 /* file_info_const_impl.h */, + 0F75F58E2A6B1DAF00A45078 /* file_list_helper.cpp */, + 0F75F57A2A6B1DAF00A45078 /* file_list_helper.h */, + 0F75F5E22A6B1DB200A45078 /* file_move_helper.cpp */, + 0F75F5682A6B1DAE00A45078 /* file_move_helper.h */, + 0F75F5BB2A6B1DB100A45078 /* file_streamstub.h */, + 0F75F5E02A6B1DB200A45078 /* file_win32_wrapper.cpp */, + 0F75F56F2A6B1DAE00A45078 /* file_win32_wrapper.h */, + 0F75F57F2A6B1DAF00A45078 /* fileReadAhead.h */, + 0F75F59C2A6B1DB000A45078 /* filetimetools.cpp */, + 0F75F5692A6B1DAE00A45078 /* filetimetools.h */, + 0F75F5702A6B1DAE00A45078 /* foobar2000-lite+atl.h */, + 0F75F5AA2A6B1DB000A45078 /* foobar2000+atl.h */, + 0F75F5C52A6B1DB100A45078 /* fullFileBuffer.h */, + 0F75F5A62A6B1DB000A45078 /* helpers.h */, + 0F75F5C92A6B1DB100A45078 /* icon_remapping_wildcard.h */, + 0F75F5972A6B1DB000A45078 /* image_load_save.cpp */, + 0F75F5742A6B1DAE00A45078 /* image_load_save.h */, + 0F75F5962A6B1DB000A45078 /* inplace_edit.cpp */, + 0F75F57B2A6B1DAF00A45078 /* inplace_edit.h */, + 0F75F5CD2A6B1DB100A45078 /* input_fix_seeking.h */, + 0F75F5E42A6B1DB200A45078 /* input_helper_cue.cpp */, + 0F75F5AF2A6B1DB100A45078 /* input_helper_cue.h */, + 0F75F5D62A6B1DB200A45078 /* input_helpers.cpp */, + 0F75F5942A6B1DB000A45078 /* input_helpers.h */, + 0F75F5632A6B1DAE00A45078 /* input_logging.h */, + 0F75F5E72A6B1DB200A45078 /* input_stream_info_reader.h */, + 0F75F5772A6B1DAF00A45078 /* meta_table_builder.h */, + 0F75F5712A6B1DAE00A45078 /* metadb_handle_array.h */, + 0F75F5DE2A6B1DB200A45078 /* metadb_handle_set.h */, + 0F75F5992A6B1DB000A45078 /* metadb_info_container_impl.h */, + 0F75F5812A6B1DAF00A45078 /* metadb_io_callback_v2_data.h */, + 0F75F59A2A6B1DB000A45078 /* metadb_io_hintlist.h */, + 0F75F5DF2A6B1DB200A45078 /* mp3_utils.cpp */, + 0F75F5D42A6B1DB200A45078 /* mp3_utils.h */, + 0F75F5952A6B1DB000A45078 /* notifyList.h */, + 0F75F5D32A6B1DB200A45078 /* packet_decoder_aac_common.cpp */, + 0F75F5B52A6B1DB100A45078 /* packet_decoder_aac_common.h */, + 0F75F5BF2A6B1DB100A45078 /* packet_decoder_mp3_common.cpp */, + 0F75F5A92A6B1DB000A45078 /* packet_decoder_mp3_common.h */, + 0F75F5792A6B1DAF00A45078 /* playlist_position_reference_tracker.h */, + 0F75F59D2A6B1DB000A45078 /* ProcessUtils.h */, + 0F75F57E2A6B1DAF00A45078 /* ProfileCache.h */, + 0F75F5752A6B1DAF00A45078 /* reader_pretend_nonseekable.h */, + 0F75F5B72A6B1DB100A45078 /* readers_lite.h */, + 0F75F5652A6B1DAE00A45078 /* readers.cpp */, + 0F75F59E2A6B1DB000A45078 /* readers.h */, + 0F75F5882A6B1DAF00A45078 /* readWriteLock.h */, + 0F75F5902A6B1DAF00A45078 /* rethrow.h */, + 0F75F5C42A6B1DB100A45078 /* seekabilizer.cpp */, + 0F75F5E12A6B1DB200A45078 /* seekabilizer.h */, + 0F75F5AC2A6B1DB000A45078 /* StdAfx.cpp */, + 0F75F5B42A6B1DB100A45078 /* StdAfx.h */, + 0F75F5CF2A6B1DB100A45078 /* stream_buffer_helper.cpp */, + 0F75F5862A6B1DAF00A45078 /* stream_buffer_helper.h */, + 0F75F5BC2A6B1DB100A45078 /* tag_write_callback_impl.h */, + 0F75F5662A6B1DAE00A45078 /* text_file_loader_v2.cpp */, + 0F75F5A52A6B1DB000A45078 /* text_file_loader_v2.h */, + 0F75F5B82A6B1DB100A45078 /* text_file_loader.cpp */, + 0F75F5E52A6B1DB200A45078 /* text_file_loader.h */, + 0F75F5BA2A6B1DB100A45078 /* ThreadUtils.cpp */, + 0F75F5D72A6B1DB200A45078 /* ThreadUtils.h */, + 0F75F5D82A6B1DB200A45078 /* track_property_callback_impl.cpp */, + 0F75F59B2A6B1DB000A45078 /* track_property_callback_impl.h */, + 0F75F5832A6B1DAF00A45078 /* ui_element_helpers.cpp */, + 0F75F5842A6B1DAF00A45078 /* ui_element_helpers.h */, + 0F75F56C2A6B1DAE00A45078 /* VisUtils.cpp */, + 0F75F5672A6B1DAE00A45078 /* VisUtils.h */, + 0F75F59F2A6B1DB000A45078 /* VolumeMap.cpp */, + 0F75F56E2A6B1DAE00A45078 /* VolumeMap.h */, + 0F75F5982A6B1DB000A45078 /* win-MulDiv.h */, + 0F75F5B12A6B1DB100A45078 /* win-systemtime.cpp */, + 0F75F5CE2A6B1DB100A45078 /* win-systemtime.h */, + 0F75F5CB2A6B1DB100A45078 /* win32_dialog.cpp */, + 0F75F5C62A6B1DB100A45078 /* win32_dialog.h */, + 0F75F5BD2A6B1DB100A45078 /* win32_misc.cpp */, + 0F75F5DC2A6B1DB200A45078 /* win32_misc.h */, + 0F75F5762A6B1DAF00A45078 /* window_placement_helper.cpp */, + 0F75F5AE2A6B1DB100A45078 /* window_placement_helper.h */, + 0F75F5A72A6B1DB000A45078 /* WindowPositionUtils.cpp */, + 0F75F5BE2A6B1DB100A45078 /* WindowPositionUtils.h */, + 0F75F5DD2A6B1DB200A45078 /* winmm-types.h */, + 0F75F5892A6B1DAF00A45078 /* writer_wav.cpp */, + 0F75F56B2A6B1DAE00A45078 /* writer_wav.h */, + ); + name = Source; + sourceTree = ""; + }; + B166964919ACC1560001728F /* Frameworks */ = { + isa = PBXGroup; + children = ( + B166964A19ACC1560001728F /* Foundation.framework */, + B166965819ACC1560001728F /* XCTest.framework */, + B166965B19ACC1560001728F /* UIKit.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + B12D1DAF1991061A0087CEF3 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 0F75F6092A6B1DB200A45078 /* metadb_io_callback_v2_data.h in Headers */, + 0F75F62E2A6B1DB200A45078 /* helpers.h in Headers */, + 0F75F5F52A6B1DB200A45078 /* COM_utils.h in Headers */, + 0F75F6122A6B1DB200A45078 /* fb2kWorkerTool.h in Headers */, + 0F75F6082A6B1DB200A45078 /* cfg_dsp_chain_config.h in Headers */, + 0F75F6362A6B1DB200A45078 /* window_placement_helper.h in Headers */, + 0F75F61B2A6B1DB200A45078 /* create_directory_helper.h in Headers */, + 0F75F5FC2A6B1DB200A45078 /* image_load_save.h in Headers */, + 0F75F5F82A6B1DB200A45078 /* foobar2000-lite+atl.h in Headers */, + 0F75F61C2A6B1DB200A45078 /* input_helpers.h in Headers */, + 0F75F62D2A6B1DB200A45078 /* text_file_loader_v2.h in Headers */, + 0F75F6352A6B1DB200A45078 /* CTableEditHelper-Legacy.h in Headers */, + 0F75F6442A6B1DB200A45078 /* tag_write_callback_impl.h in Headers */, + 0F75F61A2A6B1DB200A45078 /* album_art_helpers.h in Headers */, + 0F75F6322A6B1DB200A45078 /* foobar2000+atl.h in Headers */, + 0F75F65F2A6B1DB200A45078 /* ThreadUtils.h in Headers */, + 0F75F6592A6B1DB200A45078 /* BumpableElem.h in Headers */, + 0F75F64D2A6B1DB200A45078 /* fullFileBuffer.h in Headers */, + 0F75F60C2A6B1DB200A45078 /* ui_element_helpers.h in Headers */, + 0F75F6252A6B1DB200A45078 /* ProcessUtils.h in Headers */, + 0F75F66D2A6B1DB200A45078 /* text_file_loader.h in Headers */, + 0F75F6072A6B1DB200A45078 /* fileReadAhead.h in Headers */, + 0F75F60D2A6B1DB200A45078 /* CListControlFb2kColors.h in Headers */, + 0F75F6132A6B1DB200A45078 /* cfg_objList.h in Headers */, + 0F75F6692A6B1DB200A45078 /* seekabilizer.h in Headers */, + 0F75F6562A6B1DB200A45078 /* win-systemtime.h in Headers */, + 0F75F6312A6B1DB200A45078 /* packet_decoder_mp3_common.h in Headers */, + 0F75F64A2A6B1DB200A45078 /* cue_parser.h in Headers */, + 0F75F6502A6B1DB200A45078 /* callInMainThreadHelper.h in Headers */, + 0F75F6652A6B1DB200A45078 /* winmm-types.h in Headers */, + 0F75F6662A6B1DB200A45078 /* metadb_handle_set.h in Headers */, + 0F75F6522A6B1DB200A45078 /* audio_render_float.h in Headers */, + 0F75F65A2A6B1DB200A45078 /* cfg_obj.h in Headers */, + 0F75F6182A6B1DB200A45078 /* rethrow.h in Headers */, + 0F75F5EA2A6B1DB200A45078 /* dialog_resize_helper.h in Headers */, + 0F75F6232A6B1DB200A45078 /* track_property_callback_impl.h in Headers */, + 0F75F6372A6B1DB200A45078 /* input_helper_cue.h in Headers */, + 0F75F6552A6B1DB200A45078 /* input_fix_seeking.h in Headers */, + 0F75F64F2A6B1DB200A45078 /* cuesheet_index_list.h in Headers */, + 0F75F5F02A6B1DB200A45078 /* file_move_helper.h in Headers */, + 0F75F6222A6B1DB200A45078 /* metadb_io_hintlist.h in Headers */, + 0F75F5F32A6B1DB200A45078 /* writer_wav.h in Headers */, + 0F75F6582A6B1DB200A45078 /* dsp_dialog.h in Headers */, + 0F75F6102A6B1DB200A45078 /* readWriteLock.h in Headers */, + 0F75F63C2A6B1DB200A45078 /* StdAfx.h in Headers */, + 0F75F6002A6B1DB200A45078 /* fb2k_threads.h in Headers */, + 0F75F65C2A6B1DB200A45078 /* mp3_utils.h in Headers */, + 0F75F66B2A6B1DB200A45078 /* cfg_guidlist.h in Headers */, + 0F75F6142A6B1DB200A45078 /* CDialogResizeHelper.h in Headers */, + 0F75F63E2A6B1DB200A45078 /* CmdThread.h in Headers */, + 0F75F5FB2A6B1DB200A45078 /* CSingleThreadWrapper.h in Headers */, + 0F75F6632A6B1DB200A45078 /* DarkMode.h in Headers */, + 0F75F5EF2A6B1DB200A45078 /* VisUtils.h in Headers */, + 0F75F6542A6B1DB200A45078 /* advconfig_impl.h in Headers */, + 0F75F6262A6B1DB200A45078 /* readers.h in Headers */, + 0F75F6032A6B1DB200A45078 /* inplace_edit.h in Headers */, + 0F75F5EB2A6B1DB200A45078 /* input_logging.h in Headers */, + 0F75F6202A6B1DB200A45078 /* win-MulDiv.h in Headers */, + 0F75F6062A6B1DB200A45078 /* ProfileCache.h in Headers */, + 0F75F6302A6B1DB200A45078 /* dynamic_bitrate_helper.h in Headers */, + 0F75F61D2A6B1DB200A45078 /* notifyList.h in Headers */, + 0F75F5FD2A6B1DB200A45078 /* reader_pretend_nonseekable.h in Headers */, + 0F75F6512A6B1DB200A45078 /* icon_remapping_wildcard.h in Headers */, + 0F75F5F12A6B1DB200A45078 /* filetimetools.h in Headers */, + 0F75F63B2A6B1DB200A45078 /* bitreader_helper.h in Headers */, + 0F75F6012A6B1DB200A45078 /* playlist_position_reference_tracker.h in Headers */, + 0F75F62C2A6B1DB200A45078 /* CPropVariant.h in Headers */, + 0F75F6622A6B1DB200A45078 /* fb2k_wfx.h in Headers */, + 0F75F60E2A6B1DB200A45078 /* stream_buffer_helper.h in Headers */, + 0F75F6462A6B1DB200A45078 /* WindowPositionUtils.h in Headers */, + 0F75F6412A6B1DB200A45078 /* cue_creator.h in Headers */, + 0F75F62A2A6B1DB200A45078 /* callback_merit.h in Headers */, + 0F75F6212A6B1DB200A45078 /* metadb_info_container_impl.h in Headers */, + 0F75F6172A6B1DB200A45078 /* albumArtCache.h in Headers */, + 0F75F66E2A6B1DB200A45078 /* file_cached.h in Headers */, + 0F75F6712A6B1DB200A45078 /* dropdown_helper.h in Headers */, + 0F75F5F92A6B1DB200A45078 /* metadb_handle_array.h in Headers */, + 0F75F63D2A6B1DB200A45078 /* packet_decoder_aac_common.h in Headers */, + 0F75F66F2A6B1DB200A45078 /* input_stream_info_reader.h in Headers */, + 0F75F6332A6B1DB200A45078 /* CallForwarder.h in Headers */, + 0F75F6642A6B1DB200A45078 /* win32_misc.h in Headers */, + 0F75F6192A6B1DB200A45078 /* cfg_var_import.h in Headers */, + 0F75F6052A6B1DB200A45078 /* AutoComplete.h in Headers */, + 0F75F64E2A6B1DB200A45078 /* win32_dialog.h in Headers */, + 0F75F5F62A6B1DB200A45078 /* VolumeMap.h in Headers */, + 0F75F5FA2A6B1DB200A45078 /* atl-misc.h in Headers */, + 0F75F60F2A6B1DB200A45078 /* advconfig_runtime.h in Headers */, + 0F75F6152A6B1DB200A45078 /* file_info_const_impl.h in Headers */, + 0F75F63F2A6B1DB200A45078 /* readers_lite.h in Headers */, + 0F75F6022A6B1DB200A45078 /* file_list_helper.h in Headers */, + 0F75F6432A6B1DB200A45078 /* file_streamstub.h in Headers */, + 0F75F6492A6B1DB200A45078 /* duration_counter.h in Headers */, + 0F75F5FF2A6B1DB200A45078 /* meta_table_builder.h in Headers */, + 0F75F5F72A6B1DB200A45078 /* file_win32_wrapper.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + B12D1DB01991061A0087CEF3 /* foobar2000_SDK_helpers */ = { + isa = PBXNativeTarget; + buildConfigurationList = B12D1DB51991061A0087CEF3 /* Build configuration list for PBXNativeTarget "foobar2000_SDK_helpers" */; + buildPhases = ( + B12D1DAD1991061A0087CEF3 /* Sources */, + B12D1DAE1991061A0087CEF3 /* Frameworks */, + B12D1DAF1991061A0087CEF3 /* Headers */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = foobar2000_SDK_helpers; + productName = foobar2000_SDK_helpers; + productReference = B12D1DB11991061A0087CEF3 /* libfoobar2000_SDK_helpers.a */; + productType = "com.apple.product-type.library.static"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + B12D1DA91991061A0087CEF3 /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 1250; + ORGANIZATIONNAME = "___FULLUSERNAME___"; + }; + buildConfigurationList = B12D1DAC1991061A0087CEF3 /* Build configuration list for PBXProject "foobar2000_SDK_helpers" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = B12D1DA81991061A0087CEF3; + productRefGroup = B12D1DB21991061A0087CEF3 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + B12D1DB01991061A0087CEF3 /* foobar2000_SDK_helpers */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXSourcesBuildPhase section */ + B12D1DAD1991061A0087CEF3 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 0F75F6672A6B1DB200A45078 /* mp3_utils.cpp in Sources */, + 0F75F63A2A6B1DB200A45078 /* dynamic_bitrate_helper.cpp in Sources */, + 0F75F62B2A6B1DB200A45078 /* cue_creator.cpp in Sources */, + 0F75F6292A6B1DB200A45078 /* dropdown_helper.cpp in Sources */, + 0F75F60A2A6B1DB200A45078 /* cue_parser.cpp in Sources */, + 0F75F6472A6B1DB200A45078 /* packet_decoder_mp3_common.cpp in Sources */, + 0F75F6422A6B1DB200A45078 /* ThreadUtils.cpp in Sources */, + 0F75F64B2A6B1DB200A45078 /* dialog_resize_helper.cpp in Sources */, + 0F75F6272A6B1DB200A45078 /* VolumeMap.cpp in Sources */, + 0F75F65E2A6B1DB200A45078 /* input_helpers.cpp in Sources */, + 0F75F6392A6B1DB200A45078 /* win-systemtime.cpp in Sources */, + 0F75F6112A6B1DB200A45078 /* writer_wav.cpp in Sources */, + 0F75F6682A6B1DB200A45078 /* file_win32_wrapper.cpp in Sources */, + 0F75F5ED2A6B1DB200A45078 /* readers.cpp in Sources */, + 0F75F5EC2A6B1DB200A45078 /* cfg_var_import.cpp in Sources */, + 0F75F6572A6B1DB200A45078 /* stream_buffer_helper.cpp in Sources */, + 0F75F6282A6B1DB200A45078 /* cfg_guidlist.cpp in Sources */, + 0F75F5F42A6B1DB200A45078 /* VisUtils.cpp in Sources */, + 0F75F5EE2A6B1DB200A45078 /* text_file_loader_v2.cpp in Sources */, + 0F75F6042A6B1DB200A45078 /* album_art_helpers.cpp in Sources */, + 0F75F6602A6B1DB200A45078 /* track_property_callback_impl.cpp in Sources */, + 0F75F64C2A6B1DB200A45078 /* seekabilizer.cpp in Sources */, + 0F75F65D2A6B1DB200A45078 /* cue_parser_embedding.cpp in Sources */, + 0F75F66C2A6B1DB200A45078 /* input_helper_cue.cpp in Sources */, + 0F75F6402A6B1DB200A45078 /* text_file_loader.cpp in Sources */, + 0F75F6242A6B1DB200A45078 /* filetimetools.cpp in Sources */, + 0F75F6382A6B1DB200A45078 /* cuesheet_index_list.cpp in Sources */, + 0F75F5F22A6B1DB200A45078 /* create_directory_helper.cpp in Sources */, + 0F75F66A2A6B1DB200A45078 /* file_move_helper.cpp in Sources */, + 0F75F6342A6B1DB200A45078 /* StdAfx.cpp in Sources */, + 0F75F6162A6B1DB200A45078 /* file_list_helper.cpp in Sources */, + 0F75F65B2A6B1DB200A45078 /* packet_decoder_aac_common.cpp in Sources */, + 0F75F6452A6B1DB200A45078 /* win32_misc.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + B12D1DB31991061A0087CEF3 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_OBJC_EXCEPTIONS = YES; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = StdAfx.h; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + ../.., + .., + ); + IPHONEOS_DEPLOYMENT_TARGET = 12.1; + MACOSX_DEPLOYMENT_TARGET = 10.13; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + SKIP_INSTALL = YES; + }; + name = Debug; + }; + B12D1DB41991061A0087CEF3 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_ENABLE_OBJC_EXCEPTIONS = YES; + GCC_NO_COMMON_BLOCKS = YES; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = StdAfx.h; + GCC_PREPROCESSOR_DEFINITIONS = "NDEBUG=1"; + GCC_SYMBOLS_PRIVATE_EXTERN = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + ../.., + .., + ); + IPHONEOS_DEPLOYMENT_TARGET = 12.1; + MACOSX_DEPLOYMENT_TARGET = 10.13; + SDKROOT = macosx; + SKIP_INSTALL = YES; + }; + name = Release; + }; + B12D1DB61991061A0087CEF3 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + EXECUTABLE_PREFIX = lib; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + B12D1DB71991061A0087CEF3 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + EXECUTABLE_PREFIX = lib; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + B12D1DAC1991061A0087CEF3 /* Build configuration list for PBXProject "foobar2000_SDK_helpers" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + B12D1DB31991061A0087CEF3 /* Debug */, + B12D1DB41991061A0087CEF3 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + B12D1DB51991061A0087CEF3 /* Build configuration list for PBXNativeTarget "foobar2000_SDK_helpers" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + B12D1DB61991061A0087CEF3 /* Debug */, + B12D1DB71991061A0087CEF3 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = B12D1DA91991061A0087CEF3 /* Project object */; +} diff --git a/3rdparty/foo_SDK/foobar2000/helpers/foobar2000_sdk_helpers.vcxproj b/3rdparty/foo_SDK/foobar2000/helpers/foobar2000_sdk_helpers.vcxproj index 870478c2..eee24271 100644 --- a/3rdparty/foo_SDK/foobar2000/helpers/foobar2000_sdk_helpers.vcxproj +++ b/3rdparty/foo_SDK/foobar2000/helpers/foobar2000_sdk_helpers.vcxproj @@ -136,7 +136,7 @@ true ProgramDatabase MultiThreadedDLL - ../..;..;$(SolutionDir)/../3rdparty/WTL10_10320_Release/Include + ../..;..;$(SolutionDir)\..\3rdparty\WTL10_10320_Release\Include /d2notypeopt %(AdditionalOptions) 4715 true @@ -166,7 +166,7 @@ true ProgramDatabase MultiThreadedDLL - ../..;..;$(SolutionDir)/../3rdparty/WTL10_10320_Release/Include + ../..;..;$(SolutionDir)\..\3rdparty\WTL10_10320_Release\Include /d2notypeopt %(AdditionalOptions) 4715 true @@ -253,7 +253,7 @@ true ProgramDatabase MultiThreadedDebugDLL - ../..;..;$(SolutionDir)/../3rdparty/WTL10_10320_Release/Include + ../..;..;$(SolutionDir)\..\3rdparty\WTL10_10320_Release\Include 4715 true true @@ -277,7 +277,7 @@ true ProgramDatabase MultiThreadedDebugDLL - ../..;..;$(SolutionDir)/../3rdparty/WTL10_10320_Release/Include + ../..;..;$(SolutionDir)\..\3rdparty\WTL10_10320_Release\Include 4715 true true @@ -507,6 +507,8 @@ + + @@ -520,10 +522,11 @@ + - + @@ -567,7 +570,9 @@ + + @@ -590,6 +595,5 @@ - - + \ No newline at end of file diff --git a/3rdparty/foo_SDK/foobar2000/helpers/foobar2000_sdk_helpers.vcxproj.filters b/3rdparty/foo_SDK/foobar2000/helpers/foobar2000_sdk_helpers.vcxproj.filters index d2efd9a9..5e32b964 100644 --- a/3rdparty/foo_SDK/foobar2000/helpers/foobar2000_sdk_helpers.vcxproj.filters +++ b/3rdparty/foo_SDK/foobar2000/helpers/foobar2000_sdk_helpers.vcxproj.filters @@ -352,9 +352,6 @@ Header Files - - Header Files - Header Files @@ -403,5 +400,23 @@ Header Files + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + \ No newline at end of file diff --git a/3rdparty/foo_SDK/foobar2000/helpers/input_helpers.cpp b/3rdparty/foo_SDK/foobar2000/helpers/input_helpers.cpp index 42f4028c..62d237b1 100644 --- a/3rdparty/foo_SDK/foobar2000/helpers/input_helpers.cpp +++ b/3rdparty/foo_SDK/foobar2000/helpers/input_helpers.cpp @@ -5,15 +5,19 @@ #include "file_list_helper.h" #include "fileReadAhead.h" #include +#include "readers_lite.h" - -input_helper::ioFilter_t input_helper::ioFilter_full_buffer(t_filesize val ) { +input_helper::ioFilter_t input_helper::ioFilter_full_buffer(t_filesize val) { if (val == 0) return nullptr; return [val] ( file_ptr & f, const char * path, abort_callback & aborter) { if (!filesystem::g_is_remote_or_unrecognized(path)) { - fullFileBuffer a; - f = a.open(path, aborter, f, val); - return true; + if (f.is_empty()) filesystem::g_open_read(f, path, aborter); + if (!f->is_in_memory() && !f->is_remote() && f->can_seek() && f->get_size(aborter) <= val) { + try { + f = createFileMemMirrorAsync(f, nullptr, aborter); + return true; + } catch (std::bad_alloc) {} // keep orig file object + } } return false; }; @@ -81,8 +85,7 @@ bool input_helper::test_if_lockless(abort_callback& a) { return false; } void input_helper::fileOpenTools(service_ptr_t & p_file,const char * p_path,input_helper::ioFilters_t const & filters, abort_callback & p_abort) { - for( auto walk = filters.begin(); walk != filters.end(); ++ walk ) { - auto f = *walk; + for( auto & f : filters ) { if (f) { if (f(p_file, p_path, p_abort)) break; } diff --git a/3rdparty/foo_SDK/foobar2000/helpers/metadb_handle_set.h b/3rdparty/foo_SDK/foobar2000/helpers/metadb_handle_set.h index 8cf19934..e59c2423 100644 --- a/3rdparty/foo_SDK/foobar2000/helpers/metadb_handle_set.h +++ b/3rdparty/foo_SDK/foobar2000/helpers/metadb_handle_set.h @@ -21,10 +21,8 @@ class metadb_handle_set { if (rv) p->service_release(); return rv; } - - size_t get_count() const { - return m_content.size(); - } + size_t size() const {return m_content.size();} + size_t get_count() const {return m_content.size(); } template bool contains(ptr_t const & item) const { return m_content.count(&*item) != 0; @@ -44,28 +42,40 @@ class metadb_handle_set { bool added = m_content.insert(p).second; if (!added) p->service_release(); } - void remove_all() { - for (auto iter = m_content.begin(); iter != m_content.end(); ++iter) { - metadb_handle * p = (*iter); - p->service_release(); - } + void clear() { + for (auto p : m_content) p->service_release(); m_content.clear(); } + void remove_all() { clear();} template void enumerate(callback_t & cb) const { - for (auto iter = m_content.begin(); iter != m_content.end(); ++iter) { - cb(*iter); - } + for (auto iter : m_content) cb(iter); } typedef std::set impl_t; typedef impl_t::const_iterator const_iterator; const_iterator begin() const { return m_content.begin(); } const_iterator end() const { return m_content.end(); } -private: - std::set m_content; + metadb_handle_list to_list() const { + metadb_handle_list ret; ret.prealloc(m_content.size()); + for (auto h : m_content) { + ret.add_item(h); + } + return ret; + } + metadb_handle_set(const metadb_handle_set& src) { _copy(src); } + void operator=(const metadb_handle_set& src) { _copy(src); } + metadb_handle_set(metadb_handle_set&& src) noexcept { _move(src); } + void operator=(metadb_handle_set&& src) noexcept { _move(src); } private: - metadb_handle_set(const metadb_handle_set &) = delete; - void operator=(const metadb_handle_set&) = delete; + void _copy(const metadb_handle_set& src) { + m_content = src.m_content; + for (auto h : m_content) h->service_add_ref(); + } + void _move(metadb_handle_set& src) { + m_content = std::move(src.m_content); src.m_content.clear(); + } + + impl_t m_content; }; diff --git a/3rdparty/foo_SDK/foobar2000/helpers/packet_decoder_aac_common.cpp b/3rdparty/foo_SDK/foobar2000/helpers/packet_decoder_aac_common.cpp index bb4ac285..1b1b9fcb 100644 --- a/3rdparty/foo_SDK/foobar2000/helpers/packet_decoder_aac_common.cpp +++ b/3rdparty/foo_SDK/foobar2000/helpers/packet_decoder_aac_common.cpp @@ -267,3 +267,46 @@ const char * packet_decoder_aac_common::objectTypeStr( unsigned ot ) { const char * packet_decoder_aac_common::audioSpecificConfig_t::objectTypeStr() const { return packet_decoder_aac_common::objectTypeStr( this->m_objectType ); } + +pfc::array_t packet_decoder_aac_common::buildASC(audioSpecificConfig_t const& arg) { + pfc::array_t ret; ret.resize(5); memset(ret.get_ptr(), 0, ret.get_size()); + unsigned pos = 0; + auto write = [&](unsigned v, unsigned bits) { + bitreader_helper::write_int(ret.get_ptr(), pos, bits, v); + pos += bits; + }; + + if (arg.m_objectType < 32) { + write(arg.m_objectType, 5); + } else { + write(31, 5); + write(arg.m_objectType - 32, 6); + } + + { + bool stdRate = false; + for (unsigned i = 0; i < std::size(aac_sample_rates); ++i) { + if (arg.m_sampleRate == aac_sample_rates[i]) { + write(i, 4); + stdRate = true; break; + } + } + if (!stdRate) { + write(arg.m_sampleRate, 24); + } + + write(arg.m_channels, 4); + } + + ret.set_size((pos + 7) / 8); + return ret; +} + +pfc::array_t packet_decoder_aac_common::buildSafeASC(unsigned rate) { + if (rate == 0) rate = 44100; + audioSpecificConfig_t info = {}; + info.m_sampleRate = rate; + info.m_objectType = 1; // 1 = main, 2 = LC + info.m_channels = 2; // stereo + return buildASC(info); +} \ No newline at end of file diff --git a/3rdparty/foo_SDK/foobar2000/helpers/packet_decoder_aac_common.h b/3rdparty/foo_SDK/foobar2000/helpers/packet_decoder_aac_common.h index b074dbcd..c8d13716 100644 --- a/3rdparty/foo_SDK/foobar2000/helpers/packet_decoder_aac_common.h +++ b/3rdparty/foo_SDK/foobar2000/helpers/packet_decoder_aac_common.h @@ -37,4 +37,10 @@ class packet_decoder_aac_common : public packet_decoder { static audioSpecificConfig_t parseASC(const void *, size_t); static unsigned get_ASC_object_type(const void *, size_t); + + static pfc::array_t buildASC(audioSpecificConfig_t const&); + + // If no sane ASC was provided by container, make something up to initialize decoder and attempt decoding. + static pfc::array_t buildSafeASC(unsigned rate = 0); + }; diff --git a/3rdparty/foo_SDK/foobar2000/helpers/readWriteLock.h b/3rdparty/foo_SDK/foobar2000/helpers/readWriteLock.h new file mode 100644 index 00000000..279fa396 --- /dev/null +++ b/3rdparty/foo_SDK/foobar2000/helpers/readWriteLock.h @@ -0,0 +1,77 @@ +#pragma once + + +namespace fb2k { + //! fb2k::readWriteLock: abortable readWriteLock, allowing multiple concurrent readers while not writing, or one writer while not reading. \n + //! Safe to release locks in different threads than obtained, contrary to system object such as SRW locks. + class readWriteLock { + pfc::mutex m_guard; + size_t m_readers = 0, m_writers = 0; + typedef std::shared_ptr < pfc::event> eventRef_t; + eventRef_t m_currentEvent; + public: + + void shutdown() { + for (;;) { + eventRef_t waitFor; + { + PFC_INSYNC(m_guard); + if (m_readers == 0 && m_writers == 0) return; + PFC_ASSERT(m_currentEvent); + waitFor = m_currentEvent; + } + waitFor->wait_for(-1); + } + } + + service_ptr beginRead(abort_callback& a) { + for (;;) { + a.check(); + eventRef_t waitFor; + { + PFC_INSYNC(m_guard); + if (m_writers == 0) { + if (!m_currentEvent) m_currentEvent = std::make_shared(); + ++m_readers; + return fb2k::callOnRelease([this] { + PFC_INSYNC(m_guard); + PFC_ASSERT(m_currentEvent); + PFC_ASSERT(m_readers > 0 && m_writers == 0); + if (--m_readers == 0) { + m_currentEvent->set_state(true); m_currentEvent = nullptr; + } + }); + } + PFC_ASSERT(m_currentEvent); + waitFor = m_currentEvent; + } + a.waitForEvent(*waitFor); + } + } + service_ptr beginWrite(abort_callback& a) { + for (;;) { + a.check(); + eventRef_t waitFor; + { + PFC_INSYNC(m_guard); + if (m_readers == 0 && m_writers == 0) { + m_currentEvent = std::make_shared(); + ++m_writers; + return fb2k::callOnRelease([this] { + PFC_INSYNC(m_guard); + PFC_ASSERT(m_currentEvent); + PFC_ASSERT(m_readers == 0 && m_writers > 0); + if (--m_writers == 0) { + m_currentEvent->set_state(true); m_currentEvent = nullptr; + } + }); + } + PFC_ASSERT(m_currentEvent); + waitFor = m_currentEvent; + } + a.waitForEvent(*waitFor); + } + } + + }; +} diff --git a/3rdparty/foo_SDK/foobar2000/helpers/readers.cpp b/3rdparty/foo_SDK/foobar2000/helpers/readers.cpp index 2c819dbf..dc54aad6 100644 --- a/3rdparty/foo_SDK/foobar2000/helpers/readers.cpp +++ b/3rdparty/foo_SDK/foobar2000/helpers/readers.cpp @@ -1,9 +1,11 @@ #include "StdAfx.h" #include "readers.h" +#include "readers_lite.h" #include "fullFileBuffer.h" #include "fileReadAhead.h" #include #include +#include t_size reader_membuffer_base::read(void * p_buffer, t_size p_bytes, abort_callback & p_abort) { p_abort.check_e(); @@ -85,7 +87,7 @@ namespace { }; typedef std::shared_ptr readAheadInstanceRef; static const t_filesize seek_reopen = (filesize_invalid-1); - class fileReadAhead : public file_readonly_t< service_multi_inherit > { + class fileReadAhead : public file_readonly_t< service_multi_inherit< service_multi_inherit, stream_receive > > { service_ptr m_metadata; public: readAheadInstanceRef m_instance; @@ -132,11 +134,17 @@ namespace { worker(*i); } ); } - t_size read(void * p_buffer,t_size p_bytes,abort_callback & p_abort) override { + t_size receive(void* p_buffer, t_size p_bytes, abort_callback& p_abort) override { + return read_internal(p_buffer, p_bytes, p_abort, true); + } + t_size read(void* p_buffer, t_size p_bytes, abort_callback& p_abort) override { + return read_internal(p_buffer, p_bytes, p_abort, false); + } + t_size read_internal(void * p_buffer,t_size p_bytes,abort_callback & p_abort, bool bReceive) { auto & i = * m_instance; size_t done = 0; bool initial = true; - while( done < p_bytes ) { + while( bReceive ? done == 0 : done < p_bytes ) { if ( !initial ) { // Do not invoke waiting with common case read with lots of data in the buffer pfc::event::g_twoEventWait( i.m_canRead.get_handle(), p_abort.get_abort_event(), -1); @@ -314,7 +322,7 @@ namespace { dynInfoEntry_t dynInfo; if ( readHowMuch > 0 ) { - readHowMuch = i.m_file->read( bufptr + readOffset, readHowMuch, i.m_abort ); + readHowMuch = i.m_file->receive( bufptr + readOffset, readHowMuch, i.m_abort ); if ( readHowMuch == 0 ) atEOF = true; @@ -383,3 +391,205 @@ file::ptr fileCreateReadAhead(file::ptr chain, size_t readAheadBytes, abort_call file_v2::ptr temp = std::move(obj); return std::move(temp); } + + + +namespace { + class CFileWithMemBlock : public reader_membuffer_base { + public: + CFileWithMemBlock(fb2k::memBlockRef mem, t_filestats const& stats, const char* contentType, bool remote) { + m_mem = mem; + m_stats = stats; + m_stats.m_size = mem->size(); + if (contentType != nullptr) m_contentType = contentType; + m_remote = remote; + } + const void* get_buffer() { + return m_mem->get_ptr(); + } + t_size get_buffer_size() { + return m_mem->get_size(); + } + t_filestats get_stats(abort_callback& p_abort) { + p_abort.check(); + return m_stats; + } + bool get_content_type(pfc::string_base& out) { + if (m_contentType.is_empty()) return false; + out = m_contentType; + return true; + } + bool is_remote() { + return m_remote; + } + private: + bool m_remote; + fb2k::memBlockRef m_mem; + pfc::string8 m_contentType; + t_filestats m_stats; + }; +} + +file::ptr createFileWithMemBlock(fb2k::memBlock::ptr mem, t_filestats stats, const char* contentType, bool remote) { + return new service_impl_t< CFileWithMemBlock >(mem, stats, contentType, remote); +} + +file::ptr createFileLimited(file::ptr base, t_filesize offset, t_filesize size, abort_callback& abort) { + return reader_limited::g_create(base, offset, size, abort); +} + +file::ptr createFileBigMemMirror(file::ptr source, abort_callback& abort) { + if (source->is_in_memory()) return source; + auto r = fb2k::service_new(); + r->init(source, abort); + return r; +} + +file::ptr createFileMemMirror(file::ptr source, abort_callback& abort) { + file::ptr ret; + if (!reader_membuffer_mirror::g_create(ret, source, abort)) ret = source; + return ret; +} + +namespace { + class file_memMirrorAsync : public file_readonly_t< file_v2 > { + struct shared_t { + abort_callback_impl m_abort; + size_t m_size; + pfc::mutex m_sync; + file::ptr m_file; + + pfc::bigmem m_data; + size_t m_dataAvailable = 0; + + size_t m_triggerOffset = SIZE_MAX; + pfc::event m_trigger; + }; + shared_t m_shared; + + static void worker(shared_t& s) { + + constexpr size_t tempSize = 256 * 1024; + auto temp = std::make_unique(tempSize); + + while (s.m_dataAvailable < s.m_size) { + size_t got = s.m_file->receive(temp.get(), tempSize, s.m_abort); + if (got == 0) break; + + PFC_INSYNC(s.m_sync); + s.m_data.write(temp.get(), got, s.m_dataAvailable); + + auto before = s.m_dataAvailable; + s.m_dataAvailable += got; + if (before < s.m_triggerOffset && s.m_dataAvailable >= s.m_triggerOffset) { + s.m_trigger.set_state(true); + } + } + } + t_filestats2 m_stats; + bool m_is_remote = false; + pfc::string8 m_contentType; + service_ptr m_metadata; + t_filesize m_position = 0; + fb2k::thread m_thread; + public: + ~file_memMirrorAsync() { + m_shared.m_abort.set(); + m_thread.waitTillDone(); + } + void open(file::ptr chain, completion_notify::ptr onDone, abort_callback& a) { + if ( chain->get_position(a) > 0 ) chain->reopen(a); + m_stats = chain->get_stats2_(stats2_all, a); + if (m_stats.m_size > SIZE_MAX) throw pfc::exception_overflow(); + m_is_remote = chain->is_remote(); + m_contentType = chain->get_content_type(); + m_metadata = chain->get_metadata_(a); + m_shared.m_size = (size_t)m_stats.m_size; + m_shared.m_file = chain; + m_shared.m_data.resize(m_shared.m_size); + auto work = [this, onDone] { + try { + worker(this->m_shared); + } catch (...) {} + this->m_shared.m_file.release(); + if (onDone.is_valid()) onDone->on_completion(this->m_shared.m_size == this->m_shared.m_dataAvailable ? 1 : 0); + }; + m_thread.startHere(work); + } + + + service_ptr get_metadata(abort_callback& a) override { + a.check(); + return m_metadata; + } + + t_filestats2 get_stats2(uint32_t, abort_callback& a) override { + a.check(); + return m_stats; + } + + t_filesize get_position(abort_callback& p_abort) override { + p_abort.check(); + return m_position; + } + + void seek(t_filesize p_position, abort_callback& p_abort) override { + if (p_position > get_size(p_abort)) throw exception_io_seek_out_of_range(); + m_position = p_position; + } + + bool can_seek() override { return true; } + + bool get_content_type(pfc::string_base& p_out) override { + bool rv = m_contentType.length() > 0; + if (rv) p_out = m_contentType; + return rv; + } + + void reopen(abort_callback& p_abort) override { seek(0, p_abort); } + + bool is_remote() override { return m_is_remote; } + + t_size read(void* p_buffer, t_size p_bytes, abort_callback& p_abort) override { + auto limit = get_size(p_abort); + auto left = limit - m_position; + if (p_bytes > left) p_bytes = (size_t)left; + + const auto upper = m_position + p_bytes; + + auto& shared = m_shared; + + { + PFC_INSYNC(shared.m_sync); + if (shared.m_dataAvailable >= upper) { + shared.m_data.read(p_buffer, p_bytes, m_position); + m_position += p_bytes; + return p_bytes; + } + shared.m_trigger.set_state(false); + shared.m_triggerOffset = upper; + } + p_abort.waitForEvent(shared.m_trigger); + + PFC_INSYNC(shared.m_sync); + PFC_ASSERT(shared.m_dataAvailable >= upper); + shared.m_data.read(p_buffer, p_bytes, m_position); + m_position += p_bytes; + return p_bytes; + } + t_filesize skip(t_filesize p_bytes, abort_callback& p_abort) override { + auto total = get_size(p_abort); + PFC_ASSERT(total >= m_position ); + auto left = total - m_position; + if (p_bytes > left) p_bytes = left; + m_position += p_bytes; + return p_bytes; + } + }; +} + +file::ptr createFileMemMirrorAsync(file::ptr source, completion_notify::ptr onDone, abort_callback & a) { + auto ret = fb2k::service_new(); + ret->open(source, onDone, a); + return ret; +} diff --git a/3rdparty/foo_SDK/foobar2000/helpers/readers_lite.h b/3rdparty/foo_SDK/foobar2000/helpers/readers_lite.h new file mode 100644 index 00000000..2db93e0d --- /dev/null +++ b/3rdparty/foo_SDK/foobar2000/helpers/readers_lite.h @@ -0,0 +1,7 @@ +#pragma once + +file::ptr createFileWithMemBlock(fb2k::memBlock::ptr mem, t_filestats stats = filestats_invalid, const char* contentType = nullptr, bool remote = false); +file::ptr createFileLimited(file::ptr base, t_filesize offset, t_filesize size, abort_callback& abort); +file::ptr createFileBigMemMirror(file::ptr source, abort_callback& abort); +file::ptr createFileMemMirror(file::ptr source, abort_callback& abort); +file::ptr createFileMemMirrorAsync(file::ptr source, completion_notify::ptr optionalDoneReading, abort_callback & a); diff --git a/3rdparty/foo_SDK/foobar2000/helpers/text_file_loader_v2.h b/3rdparty/foo_SDK/foobar2000/helpers/text_file_loader_v2.h index a4ecb68b..fe2e861b 100644 --- a/3rdparty/foo_SDK/foobar2000/helpers/text_file_loader_v2.h +++ b/3rdparty/foo_SDK/foobar2000/helpers/text_file_loader_v2.h @@ -8,7 +8,7 @@ class text_file_loader_v2 { void load(file::ptr f, abort_callback & abort); - std::vector< const char * > m_lines; + std::vector< char * > m_lines; pfc::string8 m_data; }; \ No newline at end of file diff --git a/3rdparty/foo_SDK/foobar2000/helpers/win32_dialog.cpp b/3rdparty/foo_SDK/foobar2000/helpers/win32_dialog.cpp index 2516388a..ab811f32 100644 --- a/3rdparty/foo_SDK/foobar2000/helpers/win32_dialog.cpp +++ b/3rdparty/foo_SDK/foobar2000/helpers/win32_dialog.cpp @@ -1,4 +1,4 @@ -#include "stdafx.h" +#include "StdAfx.h" #ifdef FOOBAR2000_DESKTOP_WINDOWS diff --git a/3rdparty/foo_SDK/foobar2000/helpers/win32_misc.cpp b/3rdparty/foo_SDK/foobar2000/helpers/win32_misc.cpp index d2d24cf0..e36170b9 100644 --- a/3rdparty/foo_SDK/foobar2000/helpers/win32_misc.cpp +++ b/3rdparty/foo_SDK/foobar2000/helpers/win32_misc.cpp @@ -1,4 +1,4 @@ -#include "stdafx.h" +#include "StdAfx.h" #include "win32_misc.h" #ifdef FOOBAR2000_MOBILE_WINDOWS diff --git a/3rdparty/foo_SDK/foobar2000/helpers/window_placement_helper.cpp b/3rdparty/foo_SDK/foobar2000/helpers/window_placement_helper.cpp index 45590202..f516e5a4 100644 --- a/3rdparty/foo_SDK/foobar2000/helpers/window_placement_helper.cpp +++ b/3rdparty/foo_SDK/foobar2000/helpers/window_placement_helper.cpp @@ -1,4 +1,4 @@ -#include "stdafx.h" +#include "StdAfx.h" #ifdef FOOBAR2000_DESKTOP_WINDOWS @@ -41,7 +41,7 @@ static bool test_rect(const RECT * rc) { } -bool cfg_window_placement_common::read_from_window(HWND window) +bool cfg_window_placement::read_from_window(HWND window) { WINDOWPLACEMENT wp = {}; if (g_is_enabled()) { @@ -63,35 +63,41 @@ bool cfg_window_placement_common::read_from_window(HWND window) }*/ } - set(wp); + try { set(wp); } catch(...) {} // this tends to be called often / we really couldn't care less about this failing return wp.length == sizeof(wp); } -bool cfg_window_placement_common::apply_to_window(HWND window, bool allowHidden) { +bool applyWindowPlacement(HWND window, WINDOWPLACEMENT const& data, bool allowHidden) { bool ret = false; - if (g_is_enabled()) + if (data.length == sizeof(data) && test_rect(&data.rcNormalPosition)) { - auto data = get(); - if (data.length == sizeof(data) && test_rect(&data.rcNormalPosition)) - { - if (allowHidden || data.showCmd != SW_HIDE) { - if (data.showCmd == SW_HIDE && (data.flags & WPF_RESTORETOMAXIMIZED)) { - // Special case of hidden-from-maximized - auto fix = data; - fix.showCmd = SW_SHOWMINIMIZED; - if (SetWindowPlacement(window, &fix)) { - ShowWindow(window, SW_HIDE); - ret = true; - } - } else { - if (SetWindowPlacement(window, &data)) { - ret = true; - } + if (allowHidden || data.showCmd != SW_HIDE) { + if (data.showCmd == SW_HIDE && (data.flags & WPF_RESTORETOMAXIMIZED)) { + // Special case of hidden-from-maximized + auto fix = data; + fix.showCmd = SW_SHOWMINIMIZED; + if (SetWindowPlacement(window, &fix)) { + ShowWindow(window, SW_HIDE); + ret = true; + } + } else { + if (SetWindowPlacement(window, &data)) { + ret = true; } } } } + return ret; +} + +bool cfg_window_placement::apply_to_window(HWND window, bool allowHidden) { + bool ret = false; + if (g_is_enabled()) + { + auto data = get(); + ret = applyWindowPlacement(window, data, allowHidden); + } return ret; } @@ -117,8 +123,7 @@ static BOOL SetWindowSize(HWND p_wnd,unsigned p_x,unsigned p_y) return FALSE; } -bool cfg_window_size::on_window_creation(HWND p_wnd) -{ +bool cfg_window_size::apply_to_window(HWND p_wnd) { bool ret = false; if (g_is_enabled()) @@ -127,11 +132,14 @@ bool cfg_window_size::on_window_creation(HWND p_wnd) if (v.cx > 0 && v.cy > 0) { if (SetWindowSize(p_wnd, v.cx, v.cy)) ret = true; } - - } + } return ret; } +bool cfg_window_size::on_window_creation(HWND p_wnd) +{ + return apply_to_window(p_wnd); +} void cfg_window_size::on_window_destruction(HWND p_wnd) { diff --git a/3rdparty/foo_SDK/foobar2000/helpers/window_placement_helper.h b/3rdparty/foo_SDK/foobar2000/helpers/window_placement_helper.h index 6f8dd2b9..20f0369f 100644 --- a/3rdparty/foo_SDK/foobar2000/helpers/window_placement_helper.h +++ b/3rdparty/foo_SDK/foobar2000/helpers/window_placement_helper.h @@ -1,39 +1,45 @@ #pragma once +// DEPRECATED, NOT DPI SAFE +// use cfgDialogPosition & cfgWindowSize2 instead #ifdef FOOBAR2000_DESKTOP_WINDOWS #include "../SDK/cfg_var.h" -class cfg_window_placement_common : public cfg_struct_t { +//! Window position management helpers +//! Usage: create a static instance, like with any cfg_var; access it on creation/reposition/destruction of your window. +class cfg_window_placement : public cfg_struct_t { public: - cfg_window_placement_common(const GUID& guid) : cfg_struct_t(guid) {} + cfg_window_placement(const GUID& guid) : cfg_struct_t(guid) {} + //! Read and save position data from HWND. bool read_from_window(HWND window); + //! Apply saved position data to HWND. bool apply_to_window(HWND window, bool allowHidden); -}; -class cfg_window_placement : public cfg_window_placement_common -{ -public: + // OLD methods tracking only destroy/create. + // Use of read_from_window() / apply_to_window() instead is preferred, so changes can be saved immediately. bool on_window_creation(HWND window, bool allowHidden = false);//returns true if window position has been changed, false if not void on_window_creation_silent(HWND window); void on_window_destruction(HWND window); - cfg_window_placement(const GUID& guid) : cfg_window_placement_common(guid) {} -}; - -class cfg_window_placement_v2 : public cfg_window_placement_common { -public: - cfg_window_placement_v2(const GUID& guid) : cfg_window_placement_common(guid) {} - // All already in cfg_window_placement_common }; +// At one point there was a separate cfg_window_placement_v2 without legacy methods +typedef cfg_window_placement cfg_window_placement_v2; - +//! Window size tracker \n +//! Usage: create a static instance, like with any cfg_var; access it on creation/reposition/destruction of your window. class cfg_window_size : public cfg_struct_t { public: + cfg_window_size(const GUID& id) : cfg_struct_t(id) {} + //! Read and save size data from HWND. + bool read_from_window(HWND window); + //! Apply saved size data to HWND. + bool apply_to_window(HWND); + + // OLD methods tracking only destroy/create. + // Use of read_from_window() / apply_to_window() instead is preferred, so changes can be saved immediately. bool on_window_creation(HWND window);//returns true if window position has been changed, false if not void on_window_destruction(HWND window); - bool read_from_window(HWND window); - cfg_window_size(const GUID& id) : cfg_struct_t(id) {} }; #endif // FOOBAR2000_DESKTOP_WINDOWS diff --git a/3rdparty/foo_SDK/foobar2000/shared/Utility.cpp b/3rdparty/foo_SDK/foobar2000/shared/Utility.cpp new file mode 100644 index 00000000..842bc2d8 --- /dev/null +++ b/3rdparty/foo_SDK/foobar2000/shared/Utility.cpp @@ -0,0 +1,138 @@ +#include "shared.h" + +#include + +static std::once_flag g_infinitWaitInit; +static HANDLE g_infinitWaitEvent = NULL; + +HANDLE SHARED_EXPORT GetInfiniteWaitEvent() { + std::call_once(g_infinitWaitInit, [] { + g_infinitWaitEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + } ); + return g_infinitWaitEvent; +} + +struct createFileRequest { + TCHAR * lpFileName; + DWORD dwDesiredAccess; + DWORD dwShareMode; + LPSECURITY_ATTRIBUTES lpSecurityAttributes; + DWORD dwCreationDisposition; + DWORD dwFlagsAndAttributes; + + HANDLE hResultHandle; + + DWORD dwErrorCode; + + volatile LONG refCounter; + + void Delete() { + free(lpFileName); + if (hResultHandle != INVALID_HANDLE_VALUE) CloseHandle(hResultHandle); + delete this; + } + + void Release() { + if (InterlockedDecrement(&refCounter) == 0) { + Delete(); + } + } +}; + +static unsigned CALLBACK createFileThread(void* p) { + createFileRequest * req = reinterpret_cast(p); + + SetLastError(0); + req->hResultHandle = CreateFile(req->lpFileName, req->dwDesiredAccess, req->dwShareMode, req->lpSecurityAttributes, req->dwCreationDisposition, req->dwFlagsAndAttributes, NULL); + req->dwErrorCode = GetLastError(); + + req->Release(); + return 0; +} + + +typedef BOOL (WINAPI * pCancelSynchronousIo_t)(HANDLE hThread); +static BOOL myCancelSynchronousIo(HANDLE hThread) { + pCancelSynchronousIo_t pCancelSynchronousIo = (pCancelSynchronousIo_t) GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "CancelSynchronousIo"); + if (pCancelSynchronousIo == NULL) {SetLastError(ERROR_CALL_NOT_IMPLEMENTED); return FALSE;} + return pCancelSynchronousIo(hThread); +} + +HANDLE SHARED_EXPORT CreateFileAbortable( __in LPCWSTR lpFileName, + __in DWORD dwDesiredAccess, + __in DWORD dwShareMode, + __in_opt LPSECURITY_ATTRIBUTES lpSecurityAttributes, + __in DWORD dwCreationDisposition, + __in DWORD dwFlagsAndAttributes, + __in_opt HANDLE hAborter + ) { + if (hAborter == NULL || hAborter == GetInfiniteWaitEvent()) { + return CreateFile(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, NULL); + } + switch(WaitForSingleObject(hAborter, 0)) { + case WAIT_TIMEOUT: + break; + case WAIT_OBJECT_0: + SetLastError(ERROR_OPERATION_ABORTED); + return INVALID_HANDLE_VALUE; + default: + return INVALID_HANDLE_VALUE; + } + + createFileRequest * req = new createFileRequest(); + req->lpFileName = _tcsdup(lpFileName); + req->dwDesiredAccess = dwDesiredAccess; + req->dwShareMode = dwShareMode; + req->lpSecurityAttributes = lpSecurityAttributes; + req->dwCreationDisposition = dwCreationDisposition; + req->dwFlagsAndAttributes = dwFlagsAndAttributes; + req->hResultHandle = INVALID_HANDLE_VALUE; + req->dwErrorCode = 0; + req->refCounter = 2; + + HANDLE hThread = (HANDLE) _beginthreadex(NULL, 0, createFileThread, req, CREATE_SUSPENDED, NULL); + if (hThread == NULL) { + req->Delete(); + return INVALID_HANDLE_VALUE; + } + SetThreadPriority(hThread, GetThreadPriority(GetCurrentThread())); + ResumeThread(hThread); + + DWORD waitStatus; + { + HANDLE waits[2] = {hThread, hAborter}; + waitStatus = WaitForMultipleObjects(2, waits, FALSE, INFINITE); + } + HANDLE hRetVal = INVALID_HANDLE_VALUE; + DWORD dwErrorCode = 0; + switch(waitStatus) { + case WAIT_OBJECT_0: // thread completed + hRetVal = req->hResultHandle; + req->hResultHandle = INVALID_HANDLE_VALUE; + dwErrorCode = req->dwErrorCode; + break; + case WAIT_OBJECT_0 + 1: // aborted + dwErrorCode = ERROR_OPERATION_ABORTED; + myCancelSynchronousIo(hThread); + break; + default: // unexpected, use last-error code from WFMO + dwErrorCode = GetLastError(); + myCancelSynchronousIo(hThread); + break; + } + req->Release(); + CloseHandle(hThread); + SetLastError(dwErrorCode); + return hRetVal; +} + +namespace pfc { + BOOL winFormatSystemErrorMessageImpl(pfc::string_base & p_out, DWORD p_code); + BOOL winFormatSystemErrorMessageHook(pfc::string_base & p_out, DWORD p_code) { + return winFormatSystemErrorMessageImpl(p_out, p_code); + } + + void crashHook() { + uBugCheck(); + } +} diff --git a/3rdparty/foo_SDK/foobar2000/shared/audio_math.cpp b/3rdparty/foo_SDK/foobar2000/shared/audio_math.cpp new file mode 100644 index 00000000..a9ad99a0 --- /dev/null +++ b/3rdparty/foo_SDK/foobar2000/shared/audio_math.cpp @@ -0,0 +1,137 @@ +#include "shared.h" + +//#define AUDIO_MATH_NOASM + +// NOTE: SSE4.1 int16 ops code determined MUCH SLOWER than SSE2 on Sandy Bridge era Xeon and therefore disabled for now +// #define SUPPORT_SSE41 + +#ifdef SUPPORT_SSE41 +static const bool g_have_sse41 = pfc::query_cpu_feature_set(pfc::CPU_HAVE_SSE41); + +inline static void convert_from_int16_noopt(const t_int16 * p_source,t_size p_count,audio_sample * p_output,float p_scale) +{ + t_size num = p_count; + for(;num;num--) + *(p_output++) = (audio_sample)*(p_source++) * p_scale; +} + +__declspec(naked) static void __fastcall convert_from_int16_sse41_8word(const t_int16 * p_source,t_size p_count,audio_sample * p_output,float p_scale) { + __asm { + // ecx = source, edx = count, [esp + 4] = output, [esp + 8] = scale + movss xmm7, [esp + 8] + test edx, edx + mov eax, [esp + 4] + pshufd xmm7, xmm7, 0 + jz loopend +loopbegin: + PMOVSXWD xmm0, mmword ptr [ecx] + PMOVSXWD xmm1, mmword ptr [ecx+8] + CVTDQ2PS xmm0, xmm0 + CVTDQ2PS xmm1, xmm1 + add ecx, 16 + mulps xmm0, xmm7 + mulps xmm1, xmm7 + dec edx + movups [eax], xmm0 + movups [eax + 16], xmm1 + lea eax, [eax + 32] + jnz loopbegin +loopend: + ret 8 + } +} + + +__declspec(naked) static void __fastcall convert_from_int16_sse41_8word_aligned(const t_int16 * p_source,t_size p_count,audio_sample * p_output,float p_scale) { + __asm { + // ecx = source, edx = count, [esp + 4] = output, [esp + 8] = scale + movss xmm7, [esp + 8] + test edx, edx + mov eax, [esp + 4] + pshufd xmm7, xmm7, 0 + jz loopend +loopbegin: + PMOVSXWD xmm0, mmword ptr [ecx] + PMOVSXWD xmm1, mmword ptr [ecx+8] + CVTDQ2PS xmm0, xmm0 + CVTDQ2PS xmm1, xmm1 + add ecx, 16 + mulps xmm0, xmm7 + mulps xmm1, xmm7 + dec edx + movaps [eax], xmm0 + movaps [eax + 16], xmm1 + lea eax, [eax + 32] + jnz loopbegin +loopend: + ret 8 + } +} +#endif + + + +#ifdef audio_math +#undef audio_math +#endif +namespace audio_math { + + void SHARED_EXPORT scale(const audio_sample * p_source,t_size p_count,audio_sample * p_output,audio_sample p_scale) + { + ::pfc::audio_math::scale(p_source, p_count, p_output, p_scale); + } + + void SHARED_EXPORT convert_to_int16(const audio_sample * p_source,t_size p_count,t_int16 * p_output,audio_sample p_scale) + { + ::pfc::audio_math::convert_to_int16(p_source, p_count, p_output, p_scale); + } + + audio_sample SHARED_EXPORT convert_to_int16_calculate_peak(const audio_sample * p_source,t_size p_count,t_int16 * p_output,audio_sample p_scale) + { + convert_to_int16(p_source,p_count,p_output,p_scale); + return p_scale * calculate_peak(p_source,p_count); + } + + void SHARED_EXPORT convert_from_int16(const t_int16 * p_source,t_size p_count,audio_sample * p_output,audio_sample p_scale) + { +#ifdef SUPPORT_SSE41 + if (g_have_sse41) { + audio_sample scale = (audio_sample)(p_scale / (double)0x8000); + convert_from_int16_sse41_8word(p_source, p_count >> 3, p_output, scale); + convert_from_int16_noopt(p_source + (p_count & ~7), p_count & 7, p_output + (p_count & ~7), scale); + return; + } +#endif + ::pfc::audio_math::convert_from_int16(p_source, p_count, p_output, p_scale); + } + + void SHARED_EXPORT convert_to_int32(const audio_sample * p_source,t_size p_count,t_int32 * p_output,audio_sample p_scale) + { + return ::pfc::audio_math::convert_to_int32(p_source, p_count, p_output, p_scale); + } + + audio_sample SHARED_EXPORT convert_to_int32_calculate_peak(const audio_sample * p_source,t_size p_count,t_int32 * p_output,audio_sample p_scale) + { + convert_to_int32(p_source,p_count,p_output,p_scale); + return p_scale * calculate_peak(p_source,p_count); + } + + void SHARED_EXPORT convert_from_int32(const t_int32 * p_source,t_size p_count,audio_sample * p_output,audio_sample p_scale) + { + ::pfc::audio_math::convert_from_int32(p_source, p_count, p_output, p_scale); + } + + + audio_sample SHARED_EXPORT calculate_peak(const audio_sample * p_source,t_size p_count) { + return ::pfc::audio_math::calculate_peak(p_source, p_count); + } + + void SHARED_EXPORT kill_denormal(audio_sample * p_buffer,t_size p_count) { + ::pfc::audio_math::remove_denormals(p_buffer, p_count); + } + + void SHARED_EXPORT add_offset(audio_sample * p_buffer,audio_sample p_delta,t_size p_count) { + ::pfc::audio_math::add_offset(p_buffer, p_delta, p_count); + } + +} diff --git a/3rdparty/foo_SDK/foobar2000/shared/crash_info.cpp b/3rdparty/foo_SDK/foobar2000/shared/crash_info.cpp new file mode 100644 index 00000000..e01f3abf --- /dev/null +++ b/3rdparty/foo_SDK/foobar2000/shared/crash_info.cpp @@ -0,0 +1,651 @@ +#include "shared.h" +#include +#include + +#if SIZE_MAX == UINT32_MAX +#define STACKSPEC "%08X" +#define PTRSPEC "%08Xh" +#define OFFSETSPEC "%Xh" +#elif SIZE_MAX == UINT64_MAX +#define STACKSPEC "%016llX" +#define PTRSPEC "%016llXh" +#define OFFSETSPEC "%llXh" +#else +#error WTF? +#endif + + +static volatile bool g_didSuppress = false; +static critical_section g_panicHandlersSync; +static std::forward_list g_panicHandlers; + +static void callPanicHandlers() { + insync(g_panicHandlersSync); + for( auto i = g_panicHandlers.begin(); i != g_panicHandlers.end(); ++ i ) { + try { + (*i)->onPanic(); + } catch(...) {} + } +} + +void SHARED_EXPORT uAddPanicHandler(fb2k::panicHandler* p) { + insync(g_panicHandlersSync); + g_panicHandlers.push_front(p); +} + +void SHARED_EXPORT uRemovePanicHandler(fb2k::panicHandler* p) { + insync(g_panicHandlersSync); + g_panicHandlers.remove(p); +} + + +enum { EXCEPTION_BUG_CHECK = 0xaa67913c }; + +#if FB2K_SUPPORT_CRASH_LOGS + +static const unsigned char utf8_header[3] = {0xEF,0xBB,0xBF}; + +static __declspec(thread) char g_thread_call_stack[1024]; +static __declspec(thread) t_size g_thread_call_stack_length; + +static critical_section g_lastEventsSync; +static pfc::chain_list_v2_t g_lastEvents; +static constexpr t_size KLastEventCount = 200; + +static pfc::string8 version_string; + +static pfc::array_t DumpPathBuffer; + +static long crash_no = 0; + +// Debug timer: GetTickCount() diff since app startup. +// Intentionally kept as dumb as possible (originally meant to format system time nicely). +// Do not want to do expensive preformat of every event that in >99% of scenarios isn't logged. +// Cannot do formatting & system calls in crash handler. +// So we just write amount of MS since app startup. +static const uint64_t debugTimerInit = GetTickCount64(); +static pfc::format_int_t queryDebugTimer() { return pfc::format_int( GetTickCount64() - debugTimerInit ); } + +static pfc::string8 g_components; + +static void WriteFileString_internal(HANDLE hFile,const char * ptr,t_size len) +{ + DWORD bah; + WriteFile(hFile,ptr,(DWORD)len,&bah,0); +} + +static HANDLE create_failure_log() +{ + bool rv = false; + if (DumpPathBuffer.get_size() == 0) return INVALID_HANDLE_VALUE; + + TCHAR * path = DumpPathBuffer.get_ptr(); + + t_size lenWalk = _tcslen(path); + + if (lenWalk == 0 || path[lenWalk-1] != '\\') {path[lenWalk++] = '\\';} + + _tcscpy(path + lenWalk, _T("crash reports")); + lenWalk += _tcslen(path + lenWalk); + + SetLastError(NO_ERROR); + if (!CreateDirectory(path, NULL)) { + if (GetLastError() != ERROR_ALREADY_EXISTS) return INVALID_HANDLE_VALUE; + } + path[lenWalk++] = '\\'; + + TCHAR * fn_out = path + lenWalk; + HANDLE hFile = INVALID_HANDLE_VALUE; + unsigned attempts = 0; + for(;;) { + wsprintf(fn_out,TEXT("failure_%08u.txt"),++attempts); + hFile = CreateFile(path,GENERIC_WRITE,0,0,CREATE_NEW,0,0); + if (hFile!=INVALID_HANDLE_VALUE) break; + if (attempts > 1000) break; + } + if (hFile!=INVALID_HANDLE_VALUE) WriteFileString_internal(hFile, (const char*)utf8_header, sizeof(utf8_header)); + return hFile; +} + + +static void WriteFileString(HANDLE hFile,const char * str) +{ + const char * ptr = str; + for(;;) + { + const char * start = ptr; + ptr = strchr(ptr,'\n'); + if (ptr) + { + if (ptr>start) { + t_size len = ptr-start; + if (ptr[-1] == '\r') --len; + WriteFileString_internal(hFile,start,len); + } + WriteFileString_internal(hFile,"\r\n",2); + ptr++; + } + else + { + WriteFileString_internal(hFile,start,strlen(start)); + break; + } + } +} + +static void WriteEvent(HANDLE hFile,const char * str) { + bool haveText = false; + const char * ptr = str; + bool isLineBreak = false; + while(*ptr) { + const char * base = ptr; + while(*ptr && *ptr != '\r' && *ptr != '\n') ++ptr; + if (ptr > base) { + if (isLineBreak) WriteFileString_internal(hFile,"\r\n",2); + WriteFileString_internal(hFile,base,ptr-base); + isLineBreak = false; haveText = true; + } + for(;;) { + if (*ptr == '\n') isLineBreak = haveText; + else if (*ptr != '\r') break; + ++ptr; + } + } + if (haveText) WriteFileString_internal(hFile,"\r\n",2); +} + +static bool read_int(t_size src, t_size* out) +{ + __try + { + *out = *(t_size*)src; + return true; + } __except (1) { return false; } +} + +static bool hexdump8(char * out,size_t address,const char * msg,int from,int to) +{ + unsigned max = (to-from)*16; + if (IsBadReadPtr((const void*)(address+(from*16)),max)) return false; + out += sprintf(out,"\n%s (" PTRSPEC "):",msg,address); + unsigned n; + const unsigned char * src = (const unsigned char*)(address)+(from*16); + + for(n=0;n(rptr); + t_size walk = 0; + for (; walk < 255; ++walk) { + char c = ptr[walk]; + if (c == 0) break; + if (c < 0x20) c = ' '; + temp[walk] = c; + } + temp[walk] = 0; + return true; + } __except (1) { return false; } +} + +static void DumpCPPExceptionData(HANDLE hFile, const ULONG_PTR* params, char* temp) { + t_size strPtr; + if (read_int(params[1] + sizeof(void*), &strPtr)) { + if (SalvageString(strPtr, temp)) { + WriteFileString(hFile, "Message: "); + WriteFileString(hFile, temp); + WriteFileString(hFile, "\n"); + } + } +} + +static void writeFailureTxt(LPEXCEPTION_POINTERS param, HANDLE hFile, DWORD lastError) { + char temp[2048]; + { + t_size address = (t_size)param->ExceptionRecord->ExceptionAddress; + sprintf(temp, "Illegal operation:\nCode: %08Xh, flags: %08Xh, address: " PTRSPEC "\n", param->ExceptionRecord->ExceptionCode, param->ExceptionRecord->ExceptionFlags, address); + WriteFileString(hFile, temp); + + if (param->ExceptionRecord->ExceptionCode == EXCEPTION_BUG_CHECK) { + WriteFileString(hFile, "Bug check\n"); + } else if (param->ExceptionRecord->ExceptionCode == EXCEPTION_ACCESS_VIOLATION && param->ExceptionRecord->NumberParameters >= 2) { + sprintf(temp, "Access violation, operation: %s, address: " PTRSPEC "\n", param->ExceptionRecord->ExceptionInformation[0] ? "write" : "read", param->ExceptionRecord->ExceptionInformation[1]); + WriteFileString(hFile, temp); + } else if (param->ExceptionRecord->NumberParameters > 0) { + WriteFileString(hFile, "Additional parameters:"); + for (DWORD walk = 0; walk < param->ExceptionRecord->NumberParameters; ++walk) { + sprintf(temp, " " PTRSPEC, param->ExceptionRecord->ExceptionInformation[walk]); + WriteFileString(hFile, temp); + } + WriteFileString(hFile, "\n"); + } + + if (param->ExceptionRecord->ExceptionCode == 0xE06D7363 && param->ExceptionRecord->NumberParameters >= 3) { //C++ exception + DumpCPPExceptionData(hFile, param->ExceptionRecord->ExceptionInformation, temp); + } + + if (lastError) { + sprintf(temp, "Last win32 error: %u\n", lastError); + WriteFileString(hFile, temp); + } + + if (g_thread_call_stack[0] != 0) { + WriteFileString(hFile, "\nCall path:\n"); + WriteFileString(hFile, g_thread_call_stack); + WriteFileString(hFile, "\n"); + } else { + WriteFileString(hFile, "\nCall path not available.\n"); + } + + + if (hexdump8(temp, address, "Code bytes", -4, +4)) WriteFileString(hFile, temp); +#ifdef _M_IX86 + if (hexdump_stack(temp, param->ContextRecord->Esp, "Stack", -2, +18)) WriteFileString(hFile, temp); + sprintf(temp, "\nRegisters:\nEAX: %08X, EBX: %08X, ECX: %08X, EDX: %08X\nESI: %08X, EDI: %08X, EBP: %08X, ESP: %08X\n", param->ContextRecord->Eax, param->ContextRecord->Ebx, param->ContextRecord->Ecx, param->ContextRecord->Edx, param->ContextRecord->Esi, param->ContextRecord->Edi, param->ContextRecord->Ebp, param->ContextRecord->Esp); + WriteFileString(hFile, temp); +#endif + +#ifdef _M_X64 + if (hexdump_stack(temp, param->ContextRecord->Rsp, "Stack", -2, +18)) WriteFileString(hFile, temp); + sprintf(temp, "\nRegisters:\nRAX: %016llX, RBX: %016llX, RCX: %016llX, RDX: %016llX\nRSI: %016llX, RDI: %016llX, RBP: %016llX, RSP: %016llX\n", param->ContextRecord->Rax, param->ContextRecord->Rbx, param->ContextRecord->Rcx, param->ContextRecord->Rdx, param->ContextRecord->Rsi, param->ContextRecord->Rdi, param->ContextRecord->Rbp, param->ContextRecord->Rsp); + WriteFileString(hFile, temp); +#endif + +#ifdef _M_ARM64 + if (hexdump_stack(temp, param->ContextRecord->Sp, "Stack", -2, +18)) WriteFileString(hFile, temp); +#endif + + WriteFileString(hFile, "\nTimestamp:\n"); + WriteFileString(hFile, queryDebugTimer() ); + WriteFileString(hFile, "ms\n"); + + { + const HANDLE hProcess = GetCurrentProcess(); + if (SymInitialize(hProcess, NULL, TRUE)) + { + { + IMAGEHLP_MODULE mod = {}; + mod.SizeOfStruct = sizeof(mod); + if (!IsBadCodePtr((FARPROC)address) && SymGetModuleInfo(hProcess, address, &mod)) + { + sprintf(temp, "\nCrash location:\nModule: %s\nOffset: " OFFSETSPEC "\n", mod.ModuleName, address - mod.BaseOfImage); + WriteFileString(hFile, temp); + } else + { + sprintf(temp, "\nUnable to identify crash location!\n"); + WriteFileString(hFile, temp); + } + } + + { + union + { + char buffer[128]; + IMAGEHLP_SYMBOL symbol; + }; + memset(buffer, 0, sizeof(buffer)); + symbol.SizeOfStruct = sizeof(symbol); + symbol.MaxNameLength = (DWORD)(buffer + sizeof(buffer) - symbol.Name); + DWORD_PTR offset = 0; + if (SymGetSymFromAddr(hProcess, address, &offset, &symbol)) + { + buffer[PFC_TABSIZE(buffer) - 1] = 0; + if (symbol.Name[0]) + { + sprintf(temp, "Symbol: \"%s\" (+" OFFSETSPEC ")\n", symbol.Name, offset); + WriteFileString(hFile, temp); + } + } + } + + WriteFileString(hFile, "\nLoaded modules:\n"); + SymEnumerateModules(hProcess, EnumModulesCallback, hFile); + +#ifdef _M_IX86 + call_stack_parse(param->ContextRecord->Esp, hFile, temp, hProcess); +#endif + +#ifdef _M_X64 + call_stack_parse(param->ContextRecord->Rsp, hFile, temp, hProcess); +#endif + + SymCleanup(hProcess); + } else { + WriteFileString(hFile, "\nFailed to get module/symbol info.\n"); + } + } + + WriteFileString(hFile, "\nEnvironment:\n"); + WriteFileString(hFile, version_string); + + WriteFileString(hFile, "\n"); + + if (!g_components.is_empty()) { + WriteFileString(hFile, "\nComponents:\n"); + WriteFileString(hFile, g_components); + } + + { + insync(g_lastEventsSync); + if (g_lastEvents.get_count() > 0) { + WriteFileString(hFile, "\nRecent events:\n"); + for( auto & walk : g_lastEvents) WriteEvent(hFile, walk); + } + } + } +} + +static bool GrabOSVersion(char * out) { + OSVERSIONINFO ver = {}; ver.dwOSVersionInfoSize = sizeof(ver); + if (!GetVersionEx(&ver)) return false; + *out = 0; + char temp[16]; + strcat(out,"Windows "); + _itoa(ver.dwMajorVersion,temp,10); strcat(out,temp); + strcat(out,"."); + _itoa(ver.dwMinorVersion,temp,10); strcat(out,temp); + return true; +} + +static void OnLogFileWritten() { + TCHAR exePath[MAX_PATH + 1] = {}; + TCHAR params[1024]; + GetModuleFileName(NULL, exePath, MAX_PATH); + exePath[MAX_PATH] = 0; + //unsafe... + wsprintf(params, _T("/crashed \"%s\""), DumpPathBuffer.get_ptr()); + ShellExecute(NULL, NULL, exePath, params, NULL, SW_SHOW); +} + +BOOL WriteMiniDumpHelper(HANDLE, LPEXCEPTION_POINTERS); //minidump.cpp + + +void SHARED_EXPORT uDumpCrashInfo(LPEXCEPTION_POINTERS param) +{ + if (g_didSuppress) return; + const DWORD lastError = GetLastError(); + if (InterlockedIncrement(&crash_no) > 1) {Sleep(10000);return;} + HANDLE hFile = create_failure_log(); + if (hFile == INVALID_HANDLE_VALUE) return; + + { + _tcscpy(_tcsrchr(DumpPathBuffer.get_ptr(), '.'), _T(".dmp")); + HANDLE hDump = CreateFile(DumpPathBuffer.get_ptr(), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL); + if (hDump != INVALID_HANDLE_VALUE) { + const BOOL written = WriteMiniDumpHelper(hDump, param); + CloseHandle(hDump); + if (!written) { //don't bother proceeding if we don't have a valid minidump + DeleteFile(DumpPathBuffer.get_ptr()); + CloseHandle(hFile); + _tcscpy(_tcsrchr(DumpPathBuffer.get_ptr(), '.'), _T(".txt")); + DeleteFile(DumpPathBuffer.get_ptr()); + return; + } + } + _tcscpy(_tcsrchr(DumpPathBuffer.get_ptr(), '.'), _T(".txt")); + } + + writeFailureTxt(param, hFile, lastError); + + CloseHandle(hFile); + + OnLogFileWritten(); +} + +//No longer used. +size_t SHARED_EXPORT uPrintCrashInfo(LPEXCEPTION_POINTERS param,const char * extra_info,char * outbase) { + *outbase = 0; + return 0; +} + + +LONG SHARED_EXPORT uExceptFilterProc(LPEXCEPTION_POINTERS param) { + if (g_didSuppress) return UnhandledExceptionFilter(param); + callPanicHandlers(); + if (IsDebuggerPresent()) { + return UnhandledExceptionFilter(param); + } else { + if ( param->ExceptionRecord->ExceptionCode == STATUS_STACK_OVERFLOW ) { + pfc::thread2 trd; + trd.startHere( [param] { + uDumpCrashInfo(param); + } ); + trd.waitTillDone(); + } else { + uDumpCrashInfo(param); + } + TerminateProcess(GetCurrentProcess(), 0); + return 0;// never reached + } +} + +void SHARED_EXPORT uPrintCrashInfo_Init(const char * name)//called only by exe on startup +{ + version_string = pfc::format( "App: ", name, "\nArch: ", pfc::cpuArch()); + + SetUnhandledExceptionFilter(uExceptFilterProc); +} +void SHARED_EXPORT uPrintCrashInfo_Suppress() { + g_didSuppress = true; +} + +void SHARED_EXPORT uPrintCrashInfo_AddEnvironmentInfo(const char * p_info) { + version_string << "\n" << p_info; +} + +void SHARED_EXPORT uPrintCrashInfo_SetComponentList(const char * p_info) { + g_components = p_info; +} + +void SHARED_EXPORT uPrintCrashInfo_SetDumpPath(const char * p_path) { + pfc::stringcvt::string_os_from_utf8 temp(p_path); + DumpPathBuffer.set_size(temp.length() + 256); + _tcscpy(DumpPathBuffer.get_ptr(), temp.get_ptr()); +} + +static HANDLE hLogFile = INVALID_HANDLE_VALUE; + +static void logEvent(const char* message) { + if ( hLogFile != INVALID_HANDLE_VALUE ) { + DWORD wrote = 0; + WriteFile(hLogFile, message, (DWORD) strlen(message), &wrote, NULL ); + WriteFile(hLogFile, "\r\n", 2, &wrote, NULL); + } +} + +void SHARED_EXPORT uPrintCrashInfo_StartLogging(const char * path) { + insync(g_lastEventsSync); + PFC_ASSERT(hLogFile == INVALID_HANDLE_VALUE); + hLogFile = CreateFile( pfc::stringcvt::string_wide_from_utf8(path), GENERIC_WRITE, 0, NULL, CREATE_NEW, 0, NULL); + PFC_ASSERT(hLogFile != INVALID_HANDLE_VALUE); + + for( auto & walk : g_lastEvents ) { + logEvent( walk.c_str() ); + } +} + +void SHARED_EXPORT uPrintCrashInfo_OnEvent(const char * message, t_size length) { + + pfc::string8 msg = pfc::format("[", queryDebugTimer(), "ms] "); + msg.add_string( message, length ); + + insync(g_lastEventsSync); + logEvent(msg); + while(g_lastEvents.get_count() >= KLastEventCount) g_lastEvents.remove(g_lastEvents.first()); + g_lastEvents.insert_last( std::move(msg) ); +} + +static void callstack_add(const char * param) +{ + enum { MAX = PFC_TABSIZE(g_thread_call_stack) - 1} ; + t_size len = strlen(param); + if (g_thread_call_stack_length + len > MAX) len = MAX - g_thread_call_stack_length; + if (len>0) + { + memcpy(g_thread_call_stack+g_thread_call_stack_length,param,len); + g_thread_call_stack_length += len; + g_thread_call_stack[g_thread_call_stack_length]=0; + } +} + +uCallStackTracker::uCallStackTracker(const char * name) +{ + param = g_thread_call_stack_length; + if (g_thread_call_stack_length>0) callstack_add("=>"); + callstack_add(name); +} + +uCallStackTracker::~uCallStackTracker() +{ + g_thread_call_stack_length = param; + g_thread_call_stack[param]=0; + +} + +extern "C" {LPCSTR SHARED_EXPORT uGetCallStackPath() {return g_thread_call_stack;} } + +#ifdef _DEBUG +extern "C" { + void SHARED_EXPORT fb2kDebugSelfTest() { + auto ptr = SetUnhandledExceptionFilter(NULL); + PFC_ASSERT( ptr == uExceptFilterProc ); + SetUnhandledExceptionFilter(ptr); + } +} +#endif + +#else + +void SHARED_EXPORT uDumpCrashInfo(LPEXCEPTION_POINTERS param) {} +void SHARED_EXPORT uPrintCrashInfo_OnEvent(const char * message, t_size length) {} +LONG SHARED_EXPORT uExceptFilterProc(LPEXCEPTION_POINTERS param) { + return UnhandledExceptionFilter(param); +} +uCallStackTracker::uCallStackTracker(const char * name) {} +uCallStackTracker::~uCallStackTracker() {} +extern "C" { + LPCSTR SHARED_EXPORT uGetCallStackPath() { return ""; } + void SHARED_EXPORT fb2kDebugSelfTest() {} +} +#endif + +PFC_NORETURN void SHARED_EXPORT uBugCheck() { + fb2k_instacrash_scope(RaiseException(EXCEPTION_BUG_CHECK, EXCEPTION_NONCONTINUABLE, 0, NULL); ); +} diff --git a/3rdparty/foo_SDK/foobar2000/shared/fb2kdebug.h b/3rdparty/foo_SDK/foobar2000/shared/fb2kdebug.h index 76e8a600..e4f5d261 100644 --- a/3rdparty/foo_SDK/foobar2000/shared/fb2kdebug.h +++ b/3rdparty/foo_SDK/foobar2000/shared/fb2kdebug.h @@ -37,7 +37,7 @@ extern "C" #endif #ifdef _WIN32 - static inline void uAddDebugEvent(const char * msg) {uPrintCrashInfo_OnEvent(msg, strlen(msg));} + static inline void uAddDebugEvent(const char * msg) {uPrintCrashInfo_OnEvent(msg, SIZE_MAX);} #else static inline void uAddDebugEvent( const char * msg ) { uOutputDebugString(pfc::format(msg, "\n")); } #endif diff --git a/3rdparty/foo_SDK/foobar2000/shared/filedialogs.cpp b/3rdparty/foo_SDK/foobar2000/shared/filedialogs.cpp new file mode 100644 index 00000000..9629ac8a --- /dev/null +++ b/3rdparty/foo_SDK/foobar2000/shared/filedialogs.cpp @@ -0,0 +1,317 @@ +#include "shared.h" +#include "filedialogs.h" +#include + +#define dTEXT(X) pfc::stringcvt::string_os_from_utf8(X) + +static UINT_PTR CALLBACK uGetOpenFileName_Hook(HWND wnd,UINT msg,WPARAM wp,LPARAM lp) +{ + switch(msg) { + case WM_INITDIALOG: + { + OPENFILENAME * ofn = reinterpret_cast(lp); + reinterpret_cast(ofn->lCustData)->initialize(FindOwningPopup(wnd)); + } + return 0; + default: + return 0; + } +} + +static void ImportExtMask(pfc::array_t & out, const char * in) { + { + pfc::stringcvt::string_os_from_utf8 temp(in); + out.set_size(temp.length()+2); + out.fill_null(); + pfc::memcpy_t(out.get_ptr(),temp.get_ptr(),temp.length()); + } + + for(t_size walk = 0; walk < out.get_size(); ++walk) { + if (out[walk] == '|') out[walk] = 0; + } +} + +BOOL Vista_GetOpenFileName(HWND parent,const char * p_ext_mask,unsigned def_ext_mask,const char * p_def_ext,const char * p_title,const char * p_directory,pfc::string_base & p_filename,BOOL b_save); +BOOL Vista_GetOpenFileNameMulti(HWND parent,const char * p_ext_mask,unsigned def_ext_mask,const char * p_def_ext,const char * p_title,const char * p_directory,pfc::ptrholder_t & out); +BOOL Vista_BrowseForFolder(HWND parent, const char * p_title, pfc::string_base & path); +puGetOpenFileNameMultiResult Vista_BrowseForFolderEx(HWND parent,const char * title, const char * initPath); + +static bool UseVistaDialogs() { +#if FB2K_TARGET_MICROSOFT_STORE || _WIN32_WINNT >= 0x600 + return true; +#else + return GetWindowsVersionCode() >= 0x600; +#endif +} + +BOOL SHARED_EXPORT uGetOpenFileName(HWND parent,const char * p_ext_mask,unsigned def_ext_mask,const char * p_def_ext,const char * p_title,const char * p_directory,pfc::string_base & p_filename,BOOL b_save) { + TRACK_CALL_TEXT("uGetOpenFileName"); + try { + if (UseVistaDialogs()) return Vista_GetOpenFileName(parent, p_ext_mask, def_ext_mask, p_def_ext, p_title, p_directory, p_filename, b_save); + } catch(pfc::exception_not_implemented) {} + + modal_dialog_scope scope; + + pfc::array_t ext_mask; + ImportExtMask(ext_mask,p_ext_mask); + + TCHAR buffer[4096]; + + pfc::stringToBuffer(buffer,pfc::stringcvt::string_os_from_utf8(p_filename)); + + pfc::stringcvt::string_os_from_utf8 def_ext(p_def_ext ? p_def_ext : ""),title(p_title ? p_title : ""), + directory(p_directory ? p_directory : ""); + + OPENFILENAME ofn = {}; + + ofn.lStructSize=sizeof(ofn); + ofn.hwndOwner = parent; + ofn.lpstrFilter = ext_mask.get_ptr(); + ofn.nFilterIndex = def_ext_mask + 1; + ofn.lpstrFile = buffer; + ofn.lpstrInitialDir = directory; + ofn.nMaxFile = _countof(buffer); + ofn.Flags = b_save ? OFN_NOCHANGEDIR|OFN_EXPLORER|OFN_HIDEREADONLY|OFN_PATHMUSTEXIST|OFN_OVERWRITEPROMPT|OFN_ENABLEHOOK|OFN_ENABLESIZING : OFN_NOCHANGEDIR|OFN_EXPLORER|OFN_FILEMUSTEXIST|OFN_HIDEREADONLY|OFN_PATHMUSTEXIST|OFN_ENABLEHOOK|OFN_ENABLESIZING; + ofn.lpstrDefExt = *(const TCHAR*)def_ext ? (const TCHAR*)def_ext : 0; + ofn.lpstrTitle = *(const TCHAR*)title ? (const TCHAR*)title : 0; + ofn.lCustData = reinterpret_cast(&scope); + ofn.lpfnHook = uGetOpenFileName_Hook; + if (b_save ? GetSaveFileName(&ofn) : GetOpenFileName(&ofn)) + { + buffer[_countof(buffer)-1]=0; + + { + t_size ptr = _tcslen(buffer); + while(ptr>0 && buffer[ptr-1]==' ') buffer[--ptr] = 0; + } + + p_filename = pfc::stringcvt::string_utf8_from_os(buffer,_countof(buffer)); + return TRUE; + } + else return FALSE; +} + + +puGetOpenFileNameMultiResult SHARED_EXPORT uGetOpenFileNameMulti(HWND parent,const char * p_ext_mask,unsigned def_ext_mask,const char * p_def_ext,const char * p_title,const char * p_directory) { + TRACK_CALL_TEXT("uGetOpenFileNameMulti"); + try { + if (UseVistaDialogs()) { + pfc::ptrholder_t result; + if (!Vista_GetOpenFileNameMulti(parent,p_ext_mask,def_ext_mask,p_def_ext,p_title,p_directory,result)) return NULL; + return result.detach(); + } + } catch(pfc::exception_not_implemented) {} + + modal_dialog_scope scope; + + pfc::array_t ext_mask; + ImportExtMask(ext_mask,p_ext_mask); + + TCHAR buffer[0x4000]; + buffer[0]=0; + + pfc::stringcvt::string_os_from_utf8 def_ext(p_def_ext ? p_def_ext : ""),title(p_title ? p_title : ""), + directory(p_directory ? p_directory : ""); + + OPENFILENAME ofn = {}; + + ofn.lStructSize=sizeof(ofn); + ofn.hwndOwner = parent; + ofn.lpstrFilter = ext_mask.get_ptr(); + ofn.nFilterIndex = def_ext_mask + 1; + ofn.lpstrFile = buffer; + ofn.lpstrInitialDir = directory; + ofn.nMaxFile = _countof(buffer); + ofn.Flags = OFN_NOCHANGEDIR|OFN_EXPLORER|OFN_FILEMUSTEXIST|OFN_HIDEREADONLY|OFN_PATHMUSTEXIST|OFN_ALLOWMULTISELECT|OFN_ENABLEHOOK|OFN_ENABLESIZING; + ofn.lpstrDefExt = *(const TCHAR*)def_ext ? (const TCHAR*)def_ext : 0; + ofn.lpstrTitle = *(const TCHAR*)title ? (const TCHAR*)title : 0; + ofn.lCustData = reinterpret_cast(&scope); + ofn.lpfnHook = uGetOpenFileName_Hook; + if (GetOpenFileName(&ofn)) + { + buffer[_countof(buffer)-1]=0; + buffer[_countof(buffer)-2]=0; + + pfc::ptrholder_t result = new uGetOpenFileNameMultiResult_impl; + + TCHAR * p=buffer; + while(*p) p++; + p++; + if (!*p) + { + { + t_size ptr = _tcslen(buffer); + while(ptr>0 && buffer[ptr-1]==' ') buffer[--ptr] = 0; + } + + result->AddItem(pfc::stringcvt::string_utf8_from_os(buffer)); + } + else + { + pfc::string_formatter s = (const char*) pfc::stringcvt::string_utf8_from_os(buffer,_countof(buffer)); + t_size ofs = s.length(); + if (ofs>0 && s[ofs-1]!='\\') {s.add_char('\\');ofs++;} + while(*p) + { + s.truncate(ofs); + s += pfc::stringcvt::string_utf8_from_os(p); + s.skip_trailing_char(' '); + result->AddItem(s); + while(*p) p++; + p++; + } + } + return result.detach(); + } + else return 0; +} + + + + + +struct browse_for_dir_struct +{ + const TCHAR * m_initval; + const TCHAR * m_tofind; + + modal_dialog_scope m_scope; +}; + +static bool file_exists(const TCHAR * p_path) +{ + DWORD val = GetFileAttributes(p_path); + if (val == (-1) || (val & FILE_ATTRIBUTE_DIRECTORY)) return false; + return true; +} + +static void browse_proc_check_okbutton(HWND wnd,const browse_for_dir_struct * p_struct,const TCHAR * p_path) +{ + TCHAR temp[MAX_PATH+1]; + pfc::stringToBuffer(temp, p_path); + + t_size len = _tcslen(temp); + if (len < MAX_PATH && len > 0) + { + if (temp[len-1] != '\\') + temp[len++] = '\\'; + } + t_size idx = 0; + while(p_struct->m_tofind[idx] && idx+len < MAX_PATH) + { + temp[len+idx] = p_struct->m_tofind[idx]; + idx++; + } + temp[len+idx] = 0; + + SendMessage(wnd,BFFM_ENABLEOK,0,!!file_exists(temp)); + +} + +static int _stdcall browse_proc(HWND wnd,UINT msg,LPARAM lp,LPARAM dat) +{ + browse_for_dir_struct * p_struct = reinterpret_cast(dat); + switch(msg) + { + case BFFM_INITIALIZED: + p_struct->m_scope.initialize(wnd); + SendMessage(wnd,BFFM_SETSELECTION,1,(LPARAM)p_struct->m_initval); + if (p_struct->m_tofind) browse_proc_check_okbutton(wnd,p_struct,p_struct->m_initval); + break; + case BFFM_SELCHANGED: + if (p_struct->m_tofind) + { + if (lp != 0) + { + TCHAR temp[MAX_PATH+1]; + if (SHGetPathFromIDList(reinterpret_cast(lp),temp)) + { + temp[MAX_PATH] = 0; + browse_proc_check_okbutton(wnd,p_struct,temp); + } + else + SendMessage(wnd,BFFM_ENABLEOK,0,FALSE); + } + else SendMessage(wnd,BFFM_ENABLEOK,0,FALSE); + } + break; + } + return 0; +} + +static BOOL BrowseForFolderHelper(HWND p_parent,const TCHAR * p_title,TCHAR (&p_out)[MAX_PATH],const TCHAR * p_file_to_find) +{ + pfc::com_ptr_t mallocptr; + + if (FAILED(SHGetMalloc(mallocptr.receive_ptr()))) return FALSE; + if (mallocptr.is_empty()) return FALSE; + + browse_for_dir_struct data; + data.m_initval = p_out; + data.m_tofind = p_file_to_find; + + + BROWSEINFO bi= + { + p_parent, + 0, + 0, + p_title, + BIF_RETURNONLYFSDIRS | BIF_NEWDIALOGSTYLE | BIF_EDITBOX, + browse_proc, + reinterpret_cast(&data), + 0 + }; + + LPITEMIDLIST li = SHBrowseForFolder(&bi); + if (li == NULL) return FALSE; + BOOL state = SHGetPathFromIDList(li,p_out); + mallocptr->Free(li); + return state; +} + +BOOL SHARED_EXPORT uBrowseForFolder(HWND parent,const char * p_title,pfc::string_base & out) { + TRACK_CALL_TEXT("uBrowseForFolder"); + try { + if (UseVistaDialogs()) { + return Vista_BrowseForFolder(parent,p_title,out); + } + } catch(pfc::exception_not_implemented) {} + + TCHAR temp[MAX_PATH]; + pfc::stringToBuffer(temp,dTEXT(out)); + BOOL rv = BrowseForFolderHelper(parent,dTEXT(p_title),temp,0); + if (rv) { + out = pfc::stringcvt::string_utf8_from_os(temp,_countof(temp)); + } + return rv; +} + +BOOL SHARED_EXPORT uBrowseForFolderWithFile(HWND parent,const char * title,pfc::string_base & out,const char * p_file_to_find) +{ + TRACK_CALL_TEXT("uBrowseForFolderWithFile"); + TCHAR temp[MAX_PATH]; + pfc::stringToBuffer(temp,dTEXT(out)); + BOOL rv = BrowseForFolderHelper(parent,dTEXT(title),temp,dTEXT(p_file_to_find)); + if (rv) { + out = pfc::stringcvt::string_utf8_from_os(temp,_countof(temp)); + } + return rv; +} + + +puGetOpenFileNameMultiResult SHARED_EXPORT uBrowseForFolderEx(HWND parent,const char * title, const char * initPath) { + TRACK_CALL_TEXT("uBrowseForFolderEx"); + try { + if (UseVistaDialogs()) { + return Vista_BrowseForFolderEx(parent,title, initPath); + } + } catch(pfc::exception_not_implemented) {} + + pfc::string8 temp; + if (initPath) temp = initPath; + if (!uBrowseForFolder(parent, title, temp)) return NULL; + pfc::ptrholder_t result = new uGetOpenFileNameMultiResult_impl; + result->AddItem(temp); + return result.detach(); +} diff --git a/3rdparty/foo_SDK/foobar2000/shared/filedialogs_vista.cpp b/3rdparty/foo_SDK/foobar2000/shared/filedialogs_vista.cpp new file mode 100644 index 00000000..a1b79767 --- /dev/null +++ b/3rdparty/foo_SDK/foobar2000/shared/filedialogs_vista.cpp @@ -0,0 +1,497 @@ +#include "shared.h" +#include "filedialogs.h" +#include +#include +#include +#include +#include + +#define dTEXT(X) pfc::stringcvt::string_os_from_utf8(X) + +class FilterSpec { +public: + void clear() { + m_types.set_size(0); m_strings.remove_all(); + } + void Sanity() { + if ( GetCount() > 200 ) SetAllFiles(); + } + void SetAllFiles() { + FromString( "All files|*.*" ); + } + void FromString(const char * in) { + clear(); + if (in == NULL) return; + pfc::chain_list_v2_t types; + + for(t_size inWalk = 0; ; ) { + + t_size base1 = inWalk; + t_size delta1 = ScanForSeparator(in+base1); + t_size base2 = base1 + delta1; + if (in[base2] == 0) break; + ++base2; + t_size delta2 = ScanForSeparator(in+base2); + if (delta1 > 0 && delta2 > 0) { + COMDLG_FILTERSPEC spec; + spec.pszName = MakeString(in+base1,delta1); + spec.pszSpec = MakeString(in+base2,delta2); + types.add_item(spec); + } + inWalk = base2 + delta2; + if (in[inWalk] == 0) break; + ++inWalk; + } + + pfc::list_to_array(m_types,types); + } + + t_size GetCount() const {return m_types.get_count();} + const COMDLG_FILTERSPEC * GetPtr() const {return m_types.get_ptr();} +private: + static t_size ScanForSeparator(const char * in) { + for(t_size walk = 0; ; ++walk) { + if (in[walk] == 0 || in[walk] == '|') return walk; + } + } + WCHAR * MakeString(const char * in, t_size inLen) { + t_size len = pfc::stringcvt::estimate_utf8_to_wide(in,inLen); + WCHAR* str = AllocString(len); + pfc::stringcvt::convert_utf8_to_wide(str,len,in,inLen); + return str; + } + WCHAR * AllocString(t_size size) { + auto iter = m_strings.insert_last(); + iter->set_size(size); + return iter->get_ptr(); + } + pfc::chain_list_v2_t > m_strings; + pfc::array_t m_types; +}; + +static HRESULT AddOptionsHelper(pfc::com_ptr_t dlg, DWORD opts) { + DWORD options; + HRESULT state; + if (FAILED(state = dlg->GetOptions(&options))) return state; + options |= opts; + if (FAILED(state = dlg->SetOptions( options ))) return state; + return S_OK; +} + +namespace { + + // SPECIAL + // Deal with slow or nonworking net shares, do not lockup the calling thread in such cases, just split away + // Particularly relevant to net shares referred by raw IP, these get us stuck for a long time + class PDNArg_t : public pfc::refcounted_object_root { + public: + CoTaskMemObject m_idList; + pfc::string8 m_path; + HRESULT m_result; + }; + + static unsigned CALLBACK PDNProc(void * arg) { + pfc::refcounted_object_ptr_t ptr; ptr.attach( reinterpret_cast( arg ) ); + CoInitialize(0); + + SFGAOF dummy; + ptr->m_result = SHParseDisplayName(dTEXT(ptr->m_path),NULL,&ptr->m_idList.m_ptr,0,&dummy); + + CoUninitialize(); + + return 0; + } +} + +static HRESULT SetFolderHelper(pfc::com_ptr_t dlg, const char * folderPath) { + CoTaskMemObject idList; + + // Do SHParseDisplayName() off-thread as it is known to lock up on bad net share references + pfc::refcounted_object_ptr_t ptr = new PDNArg_t(); + ptr->m_path = folderPath; + ptr->m_result = E_FAIL; + HANDLE hThread = (HANDLE)_beginthreadex(NULL, 0, PDNProc, reinterpret_cast(ptr._duplicate_ptr()), 0, NULL); + DWORD status = WaitForSingleObject( hThread, 3000 ); + CloseHandle(hThread); + if (status != WAIT_OBJECT_0) return E_FAIL; + if (FAILED(ptr->m_result)) return ptr->m_result; + + pfc::com_ptr_t item; + HRESULT state; + if (FAILED(state = SHCreateShellItem(NULL,NULL,ptr->m_idList.m_ptr,item.receive_ptr()))) return state; + return dlg->SetFolder(item.get_ptr()); +} + +namespace { + class _EH { + public: + void operator<<(HRESULT hr) { + if (FAILED(hr)) throw exception_com(hr); + } + }; + static _EH EH; +}; + +BOOL Vista_GetOpenFileName(HWND parent,const char * p_ext_mask,unsigned def_ext_mask,const char * p_def_ext,const char * p_title,const char * p_directory,pfc::string_base & p_filename,BOOL b_save) { + modal_dialog_scope modalScope(parent); + + pfc::com_ptr_t dlg; + + if (b_save) { + if (FAILED(CoCreateInstance(__uuidof(FileSaveDialog), NULL, CLSCTX_ALL, IID_IFileSaveDialog, (void**) dlg.receive_ptr()))) throw pfc::exception_not_implemented(); + } else { + if (FAILED(CoCreateInstance(__uuidof(FileOpenDialog), NULL, CLSCTX_ALL, IID_IFileOpenDialog, (void**) dlg.receive_ptr()))) throw pfc::exception_not_implemented(); + } + + { + FilterSpec spec; spec.FromString(p_ext_mask); + spec.Sanity(); + if (FAILED(dlg->SetFileTypes((UINT)spec.GetCount(),spec.GetPtr()))) return FALSE; + if (def_ext_mask < spec.GetCount()) { + if (FAILED(dlg->SetFileTypeIndex(def_ext_mask + 1))) return FALSE; + } + } + if (p_def_ext != NULL) { + if (FAILED(dlg->SetDefaultExtension(dTEXT(p_def_ext)))) return FALSE; + } + if (p_title != NULL) { + if (FAILED(dlg->SetTitle(dTEXT(p_title)))) return FALSE; + } + + if (!p_filename.is_empty()) { + pfc::string path(p_filename); + pfc::string fn = pfc::io::path::getFileName(path); + pfc::string parent = pfc::io::path::getParent(path); + if (!parent.isEmpty()) SetFolderHelper(dlg,parent.ptr()); + dlg->SetFileName(dTEXT(fn.ptr())); + } else if (p_directory != NULL) { + SetFolderHelper(dlg,p_directory); + } + + if (FAILED(AddOptionsHelper(dlg, FOS_FORCEFILESYSTEM))) return FALSE; + + if (FAILED( dlg->Show(parent) ) ) return FALSE; + + { + pfc::com_ptr_t result; + if (FAILED(dlg->GetResult(result.receive_ptr()))) return FALSE; + + CoTaskMemObject nameBuf; + if (FAILED(result->GetDisplayName(SIGDN_FILESYSPATH,&nameBuf.m_ptr))) return FALSE; + + p_filename = pfc::stringcvt::string_utf8_from_os_ex( nameBuf.m_ptr ); + } + return TRUE; +} + +BOOL Vista_GetOpenFileNameMulti(HWND parent,const char * p_ext_mask,unsigned def_ext_mask,const char * p_def_ext,const char * p_title,const char * p_directory,pfc::ptrholder_t & out) { + modal_dialog_scope modalScope(parent); + + pfc::com_ptr_t dlg; + if (FAILED(CoCreateInstance(__uuidof(FileOpenDialog), NULL, CLSCTX_ALL, IID_IFileOpenDialog, (void**) dlg.receive_ptr()))) throw pfc::exception_not_implemented(); + + { + FilterSpec spec; spec.FromString(p_ext_mask); + spec.Sanity(); + if (FAILED(dlg->SetFileTypes((UINT)spec.GetCount(),spec.GetPtr()))) return FALSE; + if (def_ext_mask < spec.GetCount()) { + if (FAILED(dlg->SetFileTypeIndex(def_ext_mask + 1))) return FALSE; + } + } + if (p_def_ext != NULL) { + if (FAILED(dlg->SetDefaultExtension(dTEXT(p_def_ext)))) return FALSE; + } + if (p_title != NULL) { + if (FAILED(dlg->SetTitle(dTEXT(p_title)))) return FALSE; + } + + if (p_directory != NULL) { + SetFolderHelper(dlg,p_directory); + } + + if (FAILED(AddOptionsHelper(dlg, FOS_ALLOWMULTISELECT | FOS_FORCEFILESYSTEM))) return FALSE; + + if (FAILED( dlg->Show(parent) ) ) return FALSE; + + { + pfc::ptrholder_t result = new uGetOpenFileNameMultiResult_impl; + pfc::com_ptr_t results; + if (FAILED(dlg->GetResults(results.receive_ptr()))) return FALSE; + DWORD total; + if (FAILED(results->GetCount(&total))) return FALSE; + for(DWORD itemWalk = 0; itemWalk < total; ++itemWalk) { + pfc::com_ptr_t item; + if (SUCCEEDED(results->GetItemAt(itemWalk,item.receive_ptr()))) { + CoTaskMemObject nameBuf; + if (FAILED(item->GetDisplayName(SIGDN_FILESYSPATH,&nameBuf.m_ptr))) return FALSE; + + result->AddItem(pfc::stringcvt::string_utf8_from_os_ex( nameBuf.m_ptr ) ); + + } + } + + if (result->get_count() == 0) return FALSE; + + out = result.detach(); + } + + return TRUE; +} +#if 0 +namespace { + class CFileDialogEvents_LocateFile : public IFileDialogEvents { + public: + CFileDialogEvents_LocateFile(pfc::stringp tofind) : m_tofind(tofind) {} + HRESULT STDMETHODCALLTYPE OnFileOk(IFileDialog *pfd) {return S_OK;} + + HRESULT STDMETHODCALLTYPE OnFolderChanging( IFileDialog *pfd, IShellItem *psiFolder) {return S_OK;} + + HRESULT STDMETHODCALLTYPE OnFolderChange( IFileDialog *pfd ) { + //pfd->GetFolder(); + return S_OK; + } + + HRESULT STDMETHODCALLTYPE OnSelectionChange( IFileDialog *pfd ) {return S_OK;} + + HRESULT STDMETHODCALLTYPE OnShareViolation( IFileDialog *pfd, IShellItem *psi, FDE_SHAREVIOLATION_RESPONSE *pResponse) { return S_OK; } + + HRESULT STDMETHODCALLTYPE OnTypeChange( IFileDialog *pfd ) {return S_OK; } + + HRESULT STDMETHODCALLTYPE OnOverwrite( IFileDialog *pfd, IShellItem *psi, FDE_OVERWRITE_RESPONSE *pResponse) {return S_OK; } + + private: + const pfc::string m_tofind; + }; + +} +#endif +BOOL Vista_BrowseForFolder(HWND parent, const char * p_title, pfc::string_base & path) { + modal_dialog_scope modalScope(parent); + pfc::com_ptr_t dlg; + if (FAILED(CoCreateInstance(__uuidof(FileOpenDialog), NULL, CLSCTX_ALL, IID_IFileOpenDialog, (void**) dlg.receive_ptr()))) throw pfc::exception_not_implemented(); + + if (p_title != NULL) { + if (FAILED(dlg->SetTitle(dTEXT(p_title)))) return FALSE; + } + + if (FAILED(AddOptionsHelper(dlg, FOS_PICKFOLDERS | FOS_FORCEFILESYSTEM))) return FALSE; + + if (!path.is_empty()) { + SetFolderHelper(dlg,path); + } + + if (FAILED( dlg->Show(parent) ) ) return FALSE; + + { + pfc::com_ptr_t result; + if (FAILED(dlg->GetResult(result.receive_ptr()))) return FALSE; + + CoTaskMemObject nameBuf; + if (FAILED(result->GetDisplayName(SIGDN_FILESYSPATH,&nameBuf.m_ptr))) return FALSE; + + path = pfc::stringcvt::string_utf8_from_os_ex( nameBuf.m_ptr ); + } + return TRUE; +} + + +__inline HRESULT mySHLoadLibraryFromItem( + __in IShellItem *psiLibrary, + __in DWORD grfMode, + __in REFIID riid, + __deref_out void **ppv +) +{ + *ppv = NULL; + IShellLibrary *plib; + + HRESULT hr = CoCreateInstance( + CLSID_ShellLibrary, + NULL, + CLSCTX_INPROC_SERVER, + IID_PPV_ARGS(&plib)); + + if (SUCCEEDED(hr)) + { + hr = plib->LoadLibraryFromItem (psiLibrary, grfMode); + if (SUCCEEDED(hr)) + { + hr = plib->QueryInterface (riid, ppv); + } + plib->Release(); + } + return hr; +} + +// +// from shobjidl.h +// +__inline HRESULT mySHLoadLibraryFromKnownFolder( + __in REFKNOWNFOLDERID kfidLibrary, + __in DWORD grfMode, + __in REFIID riid, + __deref_out void **ppv) +{ + *ppv = NULL; + IShellLibrary *plib; + HRESULT hr = CoCreateInstance( + CLSID_ShellLibrary, + NULL, + CLSCTX_INPROC_SERVER, + IID_PPV_ARGS(&plib)); + if (SUCCEEDED(hr)) + { + hr = plib->LoadLibraryFromKnownFolder(kfidLibrary, grfMode); + if (SUCCEEDED(hr)) + { + hr = plib->QueryInterface(riid, ppv); + } + plib->Release(); + } + return hr; +} + +puGetOpenFileNameMultiResult Vista_BrowseForFolderEx(HWND parent,const char * p_title, const char * initPath) { + try { + modal_dialog_scope modalScope(parent); + pfc::com_ptr_t dlg; + if (FAILED(CoCreateInstance(__uuidof(FileOpenDialog), NULL, CLSCTX_ALL, IID_IFileOpenDialog, (void**) dlg.receive_ptr()))) throw pfc::exception_not_implemented(); + + if (p_title != NULL) { + EH << dlg->SetTitle(dTEXT(p_title)); + } + + EH << AddOptionsHelper(dlg, FOS_ALLOWMULTISELECT | FOS_PICKFOLDERS); + + if (initPath && *initPath) { + SetFolderHelper(dlg,initPath); + } + + EH << dlg->Show(parent); + + pfc::ptrholder_t result = new uGetOpenFileNameMultiResult_impl; + pfc::com_ptr_t results; + EH << dlg->GetResults(results.receive_ptr()); + DWORD total; + EH << results->GetCount(&total); + CoTaskMemObject nameBuf; + for(DWORD itemWalk = 0; itemWalk < total; ++itemWalk) { + pfc::com_ptr_t item; + EH << results->GetItemAt(itemWalk,item.receive_ptr()); + if (SUCCEEDED(item->GetDisplayName(SIGDN_FILESYSPATH,nameBuf.Receive()))) { + result->AddItem(pfc::stringcvt::string_utf8_from_os_ex( nameBuf.m_ptr ) ); + } else { + pfc::com_ptr_t library; + if (SUCCEEDED(mySHLoadLibraryFromItem(item.get_ptr(), STGM_READ, IID_IShellLibrary, (void**)library.receive_ptr()))) { + pfc::com_ptr_t subFolders; + EH << library->GetFolders(LFF_FORCEFILESYSTEM, IID_IShellItemArray, (void**)subFolders.receive_ptr()); + DWORD subTotal; + EH << subFolders->GetCount(&subTotal); + for(DWORD subWalk = 0; subWalk < subTotal; ++subWalk) { + pfc::com_ptr_t subItem; + EH << subFolders->GetItemAt(subWalk,subItem.receive_ptr()); + EH << subItem->GetDisplayName(SIGDN_FILESYSPATH,nameBuf.Receive()); + result->AddItem(pfc::stringcvt::string_utf8_from_os_ex( nameBuf.m_ptr ) ); + } + } + } + } + if (result->GetCount() == 0) return NULL; + return result.detach(); + } catch(exception_com) { + return NULL; + } +} + +static bool GetLegacyKnownFolder(int & out, REFKNOWNFOLDERID id) { + if (id == FOLDERID_Music) { + out = CSIDL_MYMUSIC; + return true; + } else if (id == FOLDERID_Pictures) { + out = CSIDL_MYPICTURES; + return true; + } else if (id == FOLDERID_Videos) { + out = CSIDL_MYVIDEO; + return true; + } else if (id == FOLDERID_Documents) { + out = CSIDL_MYDOCUMENTS; + return true; + } else if (id == FOLDERID_Desktop) { + out = CSIDL_DESKTOP; + return true; + } else { + return false; + } +} + +puGetOpenFileNameMultiResult SHARED_EXPORT uEvalKnownFolder(REFKNOWNFOLDERID id) { + try { + pfc::com_ptr_t library; + EH << mySHLoadLibraryFromKnownFolder(id, STGM_READ, IID_IShellLibrary, (void**)library.receive_ptr()); + + pfc::com_ptr_t subFolders; + EH << library->GetFolders(LFF_FORCEFILESYSTEM, IID_IShellItemArray, (void**)subFolders.receive_ptr()); + + pfc::ptrholder_t result = new uGetOpenFileNameMultiResult_impl; + + DWORD subTotal; + EH << subFolders->GetCount(&subTotal); + CoTaskMemObject nameBuf; + for(DWORD subWalk = 0; subWalk < subTotal; ++subWalk) { + pfc::com_ptr_t subItem; + EH << subFolders->GetItemAt(subWalk,subItem.receive_ptr()); + EH << subItem->GetDisplayName(SIGDN_FILESYSPATH,nameBuf.Receive()); + result->AddItem(pfc::stringcvt::string_utf8_from_os_ex( nameBuf.m_ptr ) ); + } + if (result->get_count() == 0) return NULL; + return result.detach(); + } catch(exception_com) { + //failed + } + + + try { + CComPtr mgr; CComPtr folder; CoTaskMemObject path; + EH << CoCreateInstance(__uuidof(KnownFolderManager), nullptr, CLSCTX_ALL, IID_IKnownFolderManager, (void**)&mgr.p); + EH << mgr->GetFolder(id, &folder.p); + EH << folder->GetPath(0, &path.m_ptr); + + pfc::ptrholder_t result = new uGetOpenFileNameMultiResult_impl; + result->AddItem(pfc::stringcvt::string_utf8_from_os(path.m_ptr)); + return result.detach(); + } catch (exception_com) { + + } + + //FALLBACK + + + + { + int legacyID; + if (GetLegacyKnownFolder(legacyID, id)) { + try { + TCHAR path[MAX_PATH+16] = {}; + EH << SHGetFolderPath(NULL, legacyID, NULL, SHGFP_TYPE_CURRENT, path); + path[_countof(path)-1] = 0; + pfc::ptrholder_t result = new uGetOpenFileNameMultiResult_impl; + result->AddItem(pfc::stringcvt::string_utf8_from_os_ex( path ) ); + return result.detach(); + } catch(exception_com) { + //failed; + } + } + } +#if 0 // Vista code path - uninteresting, XP shit still needs to be supported, SHGetKnownFolderPath() does not exist on XP + try { + pfc::ptrholder_t result = new uGetOpenFileNameMultiResult_impl; + CoTaskMemObject nameBuf; + EH << SHGetKnownFolderPath(id, 0, NULL, nameBuf.Receive()); + result->AddItem(pfc::stringcvt::string_utf8_from_os_ex( nameBuf.m_ptr ) ); + return result.detach(); + } catch(exception_com) { + //failed + } +#endif + return NULL; //failure +} diff --git a/3rdparty/foo_SDK/foobar2000/shared/font_description.cpp b/3rdparty/foo_SDK/foobar2000/shared/font_description.cpp new file mode 100644 index 00000000..440930c8 --- /dev/null +++ b/3rdparty/foo_SDK/foobar2000/shared/font_description.cpp @@ -0,0 +1,126 @@ +#include "shared.h" + + +static unsigned query_dpi() +{ + unsigned ret; + HDC dc = GetDC(0); + ret = GetDeviceCaps(dc,LOGPIXELSY); + ReleaseDC(0,dc); + return ret; +} + + +#if 0 +struct t_font_description +{ + enum {m_facename_length = LF_FACESIZE*2}; + + t_uint32 m_height; + t_uint32 m_weight; + t_uint8 m_italic; + t_uint8 m_charset; + char m_facename[m_facename_length]; +} +#endif + +static void make_logfont(LOGFONT & p_logfont,const t_font_description & p_desc) +{ + p_logfont.lfHeight = - MulDiv(p_desc.m_height, query_dpi(), t_font_description::m_height_dpi); + p_logfont.lfWidth = 0; + p_logfont.lfEscapement = 0; + p_logfont.lfOrientation = 0; + p_logfont.lfWeight = p_desc.m_weight; + p_logfont.lfItalic = p_desc.m_italic; + p_logfont.lfUnderline = 0; + p_logfont.lfStrikeOut = 0; + p_logfont.lfCharSet = p_desc.m_charset; + p_logfont.lfOutPrecision = 3; + p_logfont.lfClipPrecision = 2; + p_logfont.lfQuality = 1; + p_logfont.lfPitchAndFamily = 34; + pfc::stringToBuffer(p_logfont.lfFaceName,pfc::stringcvt::string_os_from_utf8(p_desc.m_facename,tabsize(p_desc.m_facename))); +} + +static void make_description(t_font_description & p_desc,const LOGFONT & p_logfont) +{ + p_desc.m_height = MulDiv(pfc::abs_t(p_logfont.lfHeight), t_font_description::m_height_dpi, query_dpi()); + p_desc.m_weight = p_logfont.lfWeight; + p_desc.m_italic = p_logfont.lfItalic; + p_desc.m_charset = p_logfont.lfCharSet; + pfc::stringToBuffer(p_desc.m_facename,pfc::stringcvt::string_utf8_from_os(p_logfont.lfFaceName,tabsize(p_logfont.lfFaceName))); +} + +HFONT SHARED_EXPORT t_font_description::create() const +{ + LOGFONT temp; + make_logfont(temp,*this); + return CreateFontIndirect(&temp); +} + +static UINT_PTR CALLBACK choose_font_hook(HWND wnd,UINT msg,WPARAM wp,LPARAM lp) +{ + switch(msg) + { + case WM_INITDIALOG: + { + CHOOSEFONT * cf = reinterpret_cast(lp); + reinterpret_cast(cf->lCustData)->initialize(FindOwningPopup(wnd)); + } + return 0; + default: + return 0; + } +} + +bool SHARED_EXPORT t_font_description::popup_dialog(HWND p_parent) +{ + modal_dialog_scope scope; + + LOGFONT logfont; + make_logfont(logfont,*this); + + CHOOSEFONT cf = {}; + cf.lStructSize = sizeof(cf); + cf.hwndOwner = p_parent; + cf.lpLogFont = &logfont; + cf.Flags = CF_SCREENFONTS|CF_FORCEFONTEXIST|CF_INITTOLOGFONTSTRUCT|CF_ENABLEHOOK; + cf.nFontType = SCREEN_FONTTYPE; + cf.lCustData = reinterpret_cast(&scope); + cf.lpfnHook = choose_font_hook; + if (ChooseFont(&cf)) + { + make_description(*this,logfont); + return true; + } + else return false; +} + + +void SHARED_EXPORT t_font_description::from_font(HFONT p_font) +{ + LOGFONT logfont; + PFC_ASSERT_SUCCESS( GetObject((HGDIOBJ) p_font, sizeof(logfont), &logfont) != 0 ); + make_description(*this,logfont); +} + +t_font_description SHARED_EXPORT t_font_description::g_from_font(HFONT p_font) +{ + t_font_description temp; + temp.from_font(p_font); + return temp; +} + + +t_font_description SHARED_EXPORT t_font_description::g_from_logfont(LOGFONT const & lf) { + t_font_description ret; make_description(ret, lf); return ret; +} + +t_font_description SHARED_EXPORT t_font_description::g_from_system(int id) { + LOGFONT lf; + if (FAILED( GetThemeSysFont(NULL, id, &lf) ) ) { + PFC_ASSERT(!"Should not get here!"); + return g_from_font( (HFONT) GetStockObject(DEFAULT_GUI_FONT) ); + } + return g_from_logfont(lf); +} diff --git a/3rdparty/foo_SDK/foobar2000/shared/minidump.cpp b/3rdparty/foo_SDK/foobar2000/shared/minidump.cpp new file mode 100644 index 00000000..eec6d14b --- /dev/null +++ b/3rdparty/foo_SDK/foobar2000/shared/minidump.cpp @@ -0,0 +1,251 @@ +#include "shared.h" +#include + +#ifdef _M_ARM64EC +typedef ARM64EC_NT_CONTEXT myCONTEXT; +#else +typedef CONTEXT myCONTEXT; +#endif +struct DumpState { + int state; + myCONTEXT*context; +}; + +__declspec(noinline) static bool safeRead(volatile const void* addr, size_t& dest) +{ + __try { + dest = *(const volatile size_t*)addr; + return true; + } + __except (1) { + return false; + } +} + +__declspec(noinline) static bool safeTestReadAccess(volatile const void* addr) +{ + size_t dummy; + return safeRead(addr, dummy); +} + +#if defined(_M_ARM64) || defined(_M_ARM64EC) + +BOOL WINAPI MiniDumpCallback(PVOID CallbackParam, + const PMINIDUMP_CALLBACK_INPUT CallbackInput, + PMINIDUMP_CALLBACK_OUTPUT CallbackOutput) +{ + static const unsigned STACK_SEARCH_SIZE = 0x400; + static const unsigned MEM_BLOCK_SIZE = 0x400; + + if (CallbackInput->CallbackType == MemoryCallback) { + // Called to get user defined blocks of memory to write until + // callback returns FALSE or CallbackOutput->MemorySize == 0. + + DumpState* ds = (DumpState*)CallbackParam; + switch (ds->state) { + // Save memory referenced by registers. + case 0: CallbackOutput->MemoryBase = ds->context->X0; ds->state++; break; + case 1: CallbackOutput->MemoryBase = ds->context->X1; ds->state++; break; + case 2: CallbackOutput->MemoryBase = ds->context->X2; ds->state++; break; + case 3: CallbackOutput->MemoryBase = ds->context->X3; ds->state++; break; + case 4: CallbackOutput->MemoryBase = ds->context->X4; ds->state++; break; + case 5: CallbackOutput->MemoryBase = ds->context->X5; ds->state++; break; + case 6: CallbackOutput->MemoryBase = ds->context->X6; ds->state++; break; + case 7: CallbackOutput->MemoryBase = ds->context->X7; ds->state++; break; + case 8: CallbackOutput->MemoryBase = ds->context->X8; ds->state++; break; + case 9: CallbackOutput->MemoryBase = ds->context->X9; ds->state++; break; + case 10: CallbackOutput->MemoryBase = ds->context->X10; ds->state++; break; + case 11: CallbackOutput->MemoryBase = ds->context->X11; ds->state++; break; + case 12: CallbackOutput->MemoryBase = ds->context->X12; ds->state++; break; +#ifndef _M_ARM64EC + case 13: CallbackOutput->MemoryBase = ds->context->X13; ds->state++; break; + case 14: CallbackOutput->MemoryBase = ds->context->X14; ds->state++; break; + case 15: CallbackOutput->MemoryBase = ds->context->X15; ds->state++; break; + case 16: CallbackOutput->MemoryBase = ds->context->X16; ds->state++; break; + case 17: CallbackOutput->MemoryBase = ds->context->X17; ds->state++; break; + case 18: CallbackOutput->MemoryBase = ds->context->X18; ds->state++; break; + case 19: CallbackOutput->MemoryBase = ds->context->X19; ds->state++; break; + case 20: CallbackOutput->MemoryBase = ds->context->X20; ds->state++; break; + case 21: CallbackOutput->MemoryBase = ds->context->X21; ds->state++; break; + case 22: CallbackOutput->MemoryBase = ds->context->X22; ds->state++; break; + case 23: CallbackOutput->MemoryBase = ds->context->X23; ds->state++; break; + case 24: CallbackOutput->MemoryBase = ds->context->X24; ds->state++; break; + case 25: CallbackOutput->MemoryBase = ds->context->X25; ds->state++; break; + case 26: CallbackOutput->MemoryBase = ds->context->X26; ds->state++; break; + case 27: CallbackOutput->MemoryBase = ds->context->X27; ds->state++; break; + case 28: CallbackOutput->MemoryBase = ds->context->X28; ds->state++; break; +#endif + + // Save memory referenced by values in stack. + default: + if (ds->state < 0x1000) + ds->state = 0x1000; + + size_t addr; + do { + if (ds->state > 0x1000 + STACK_SEARCH_SIZE) + return FALSE; + + if (!safeRead((void*)((ds->context->Sp & ~7) + ds->state - 0x1000), addr)) + return FALSE; + + ds->state += 4; + } while (addr < 0x1000 || !safeTestReadAccess((void*)addr)); + + CallbackOutput->MemoryBase = addr; + break; + } + + if (CallbackOutput->MemoryBase >= MEM_BLOCK_SIZE / 2) + CallbackOutput->MemoryBase -= MEM_BLOCK_SIZE / 2; + CallbackOutput->MemorySize = MEM_BLOCK_SIZE; + + // No need to perform additional checks here, the minidump engine + // safely clips the addresses to valid memory pages only. + // Also seems to apply for overlapped areas etc. + } + + return TRUE; +} + +#elif defined(_M_IX86) + +BOOL WINAPI MiniDumpCallback(PVOID CallbackParam, + const PMINIDUMP_CALLBACK_INPUT CallbackInput, + PMINIDUMP_CALLBACK_OUTPUT CallbackOutput) +{ + static const unsigned STACK_SEARCH_SIZE = 0x400; + static const unsigned MEM_BLOCK_SIZE = 0x400; + + if (CallbackInput->CallbackType == MemoryCallback) { + // Called to get user defined blocks of memory to write until + // callback returns FALSE or CallbackOutput->MemorySize == 0. + + DumpState* ds = (DumpState*)CallbackParam; + switch (ds->state) { + // Save memory referenced by registers. + case 0: CallbackOutput->MemoryBase = ds->context->Eax; ds->state++; break; + case 1: CallbackOutput->MemoryBase = ds->context->Ebx; ds->state++; break; + case 2: CallbackOutput->MemoryBase = ds->context->Ecx; ds->state++; break; + case 3: CallbackOutput->MemoryBase = ds->context->Edx; ds->state++; break; + case 4: CallbackOutput->MemoryBase = ds->context->Esi; ds->state++; break; + case 5: CallbackOutput->MemoryBase = ds->context->Edi; ds->state++; break; + case 6: CallbackOutput->MemoryBase = ds->context->Ebp; ds->state++; break; + case 7: CallbackOutput->MemoryBase = ds->context->Esp; ds->state++; break; + case 8: CallbackOutput->MemoryBase = ds->context->Eip; ds->state++; break; + + // Save memory referenced by values in stack. + default: + if (ds->state < 0x1000) + ds->state = 0x1000; + + size_t addr; + do { + if (ds->state > 0x1000 + STACK_SEARCH_SIZE) + return FALSE; + + if (!safeRead((void*)((ds->context->Esp & ~3) + ds->state - 0x1000), addr)) + return FALSE; + + ds->state += 4; + } while (addr < 0x1000 || !safeTestReadAccess((void*)addr)); + + CallbackOutput->MemoryBase = addr; + break; + } + + if (CallbackOutput->MemoryBase >= MEM_BLOCK_SIZE / 2) + CallbackOutput->MemoryBase -= MEM_BLOCK_SIZE / 2; + CallbackOutput->MemorySize = MEM_BLOCK_SIZE; + + // No need to perform additional checks here, the minidump engine + // safely clips the addresses to valid memory pages only. + // Also seems to apply for overlapped areas etc. + } + + return TRUE; +} + +#elif defined(_M_X64) + +BOOL WINAPI MiniDumpCallback(PVOID CallbackParam, + const PMINIDUMP_CALLBACK_INPUT CallbackInput, + PMINIDUMP_CALLBACK_OUTPUT CallbackOutput) +{ + static const unsigned STACK_SEARCH_SIZE = 0x400; + static const unsigned MEM_BLOCK_SIZE = 0x400; + + if (CallbackInput->CallbackType == MemoryCallback) { + // Called to get user defined blocks of memory to write until + // callback returns FALSE or CallbackOutput->MemorySize == 0. + + DumpState* ds = (DumpState*)CallbackParam; + switch (ds->state) { + // Save memory referenced by registers. + case 0: CallbackOutput->MemoryBase = ds->context->Rax; ds->state++; break; + case 1: CallbackOutput->MemoryBase = ds->context->Rbx; ds->state++; break; + case 2: CallbackOutput->MemoryBase = ds->context->Rcx; ds->state++; break; + case 3: CallbackOutput->MemoryBase = ds->context->Rdx; ds->state++; break; + case 4: CallbackOutput->MemoryBase = ds->context->Rsi; ds->state++; break; + case 5: CallbackOutput->MemoryBase = ds->context->Rdi; ds->state++; break; + case 6: CallbackOutput->MemoryBase = ds->context->Rsp; ds->state++; break; + case 7: CallbackOutput->MemoryBase = ds->context->Rbp; ds->state++; break; + case 8: CallbackOutput->MemoryBase = ds->context->R8; ds->state++; break; + case 9: CallbackOutput->MemoryBase = ds->context->R9; ds->state++; break; + case 10: CallbackOutput->MemoryBase = ds->context->R10; ds->state++; break; + case 11: CallbackOutput->MemoryBase = ds->context->R11; ds->state++; break; + case 12: CallbackOutput->MemoryBase = ds->context->R12; ds->state++; break; + case 13: CallbackOutput->MemoryBase = ds->context->R13; ds->state++; break; + case 14: CallbackOutput->MemoryBase = ds->context->R14; ds->state++; break; + case 15: CallbackOutput->MemoryBase = ds->context->R15; ds->state++; break; + + // Save memory referenced by values in stack. + default: + if (ds->state < 0x1000) + ds->state = 0x1000; + + size_t addr; + do { + if (ds->state > 0x1000 + STACK_SEARCH_SIZE) + return FALSE; + + if (!safeRead((void*)((ds->context->Rsp & ~7) + ds->state - 0x1000), addr)) + return FALSE; + + ds->state += 4; + } while (addr < 0x1000 || !safeTestReadAccess((void*)addr)); + + CallbackOutput->MemoryBase = addr; + break; + } + + if (CallbackOutput->MemoryBase >= MEM_BLOCK_SIZE / 2) + CallbackOutput->MemoryBase -= MEM_BLOCK_SIZE / 2; + CallbackOutput->MemorySize = MEM_BLOCK_SIZE; + + // No need to perform additional checks here, the minidump engine + // safely clips the addresses to valid memory pages only. + // Also seems to apply for overlapped areas etc. + } + + return TRUE; +} + +#endif // _M_X64 + + + + +BOOL WriteMiniDumpHelper(HANDLE hDump, LPEXCEPTION_POINTERS param) { + MINIDUMP_EXCEPTION_INFORMATION exception = {}; + exception.ThreadId = GetCurrentThreadId(); + exception.ExceptionPointers = param; + exception.ClientPointers = FALSE; + DumpState ds; + ds.state = 0; + ds.context = reinterpret_cast(param->ContextRecord); + MINIDUMP_CALLBACK_INFORMATION mci; + mci.CallbackRoutine = &MiniDumpCallback; + mci.CallbackParam = (void*)&ds; + return MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), hDump, (MINIDUMP_TYPE)(MiniDumpWithUnloadedModules), &exception, NULL, &mci); +} diff --git a/3rdparty/foo_SDK/foobar2000/shared/modal_dialog.cpp b/3rdparty/foo_SDK/foobar2000/shared/modal_dialog.cpp new file mode 100644 index 00000000..84785794 --- /dev/null +++ b/3rdparty/foo_SDK/foobar2000/shared/modal_dialog.cpp @@ -0,0 +1,66 @@ +#include "shared.h" + +static DWORD g_main_thread = GetCurrentThreadId(); + +static t_modal_dialog_entry g_status = {0,false}; + +static bool TestMainThread() +{ + if (GetCurrentThreadId() == g_main_thread) return true; + OutputDebugString(TEXT("This function can be called only from main thread.\n")); + return false; +} + +HWND SHARED_EXPORT FindOwningPopup(HWND p_wnd) +{ + return pfc::findOwningPopup(p_wnd); +} + +void SHARED_EXPORT PokeWindow(HWND p_wnd) +{ + p_wnd = FindOwningPopup(p_wnd); + if (IsWindowEnabled(p_wnd)) + { +// SetForegroundWindow(p_wnd); + SetActiveWindow(p_wnd); + FlashWindow(p_wnd,FALSE); + } + else + { + HWND child = GetWindow(p_wnd,GW_ENABLEDPOPUP); + if (child != 0) + { +// SetForegroundWindow(child); + SetActiveWindow(child); + FlashWindow(child,FALSE); + } + } +} + +extern "C" { + void SHARED_EXPORT ModalDialog_Switch(t_modal_dialog_entry & p_entry) + { + if (TestMainThread()) + pfc::swap_t(p_entry,g_status); + } + + void SHARED_EXPORT ModalDialog_PokeExisting() + { + if (TestMainThread()) + { + if (g_status.m_in_use && g_status.m_wnd_to_poke != 0) + { + PokeWindow(g_status.m_wnd_to_poke); + MessageBeep(0); + } + } + } + + bool SHARED_EXPORT ModalDialog_CanCreateNew() + { + if (TestMainThread()) + return !g_status.m_in_use; + else + return false; + } +} \ No newline at end of file diff --git a/3rdparty/foo_SDK/foobar2000/shared/shared-ARM64.lib b/3rdparty/foo_SDK/foobar2000/shared/shared-ARM64.lib index 754a40aa..25737391 100644 Binary files a/3rdparty/foo_SDK/foobar2000/shared/shared-ARM64.lib and b/3rdparty/foo_SDK/foobar2000/shared/shared-ARM64.lib differ diff --git a/3rdparty/foo_SDK/foobar2000/shared/shared-ARM64EC.lib b/3rdparty/foo_SDK/foobar2000/shared/shared-ARM64EC.lib index 77043dcb..77fe8eaf 100644 Binary files a/3rdparty/foo_SDK/foobar2000/shared/shared-ARM64EC.lib and b/3rdparty/foo_SDK/foobar2000/shared/shared-ARM64EC.lib differ diff --git a/3rdparty/foo_SDK/foobar2000/shared/shared-Win32.lib b/3rdparty/foo_SDK/foobar2000/shared/shared-Win32.lib index c5cbee12..da0ccb0a 100644 Binary files a/3rdparty/foo_SDK/foobar2000/shared/shared-Win32.lib and b/3rdparty/foo_SDK/foobar2000/shared/shared-Win32.lib differ diff --git a/3rdparty/foo_SDK/foobar2000/shared/shared-apple.mm b/3rdparty/foo_SDK/foobar2000/shared/shared-apple.mm new file mode 100644 index 00000000..62236563 --- /dev/null +++ b/3rdparty/foo_SDK/foobar2000/shared/shared-apple.mm @@ -0,0 +1,31 @@ +#include "shared.h" +#include "shared-apple.h" + +#import + +bool uSetClipboardString(const char * str) { + @autoreleasepool { + @try { + NSPasteboard * pb = [NSPasteboard generalPasteboard]; + [pb clearContents]; + [pb setString: [NSString stringWithUTF8String: str] forType:NSPasteboardTypeString]; + return true; + } @catch (NSException *) { + + } + } + return false; +} + +bool uGetClipboardString(pfc::string_base & out) { + bool rv = false; + @autoreleasepool { + NSPasteboard * pb = [NSPasteboard generalPasteboard]; + NSString * str = [pb stringForType: NSPasteboardTypeString]; + if ( str != nil ) { + out = str.UTF8String; + rv = true; + } + } + return rv; +} diff --git a/3rdparty/foo_SDK/foobar2000/shared/shared-nix.cpp b/3rdparty/foo_SDK/foobar2000/shared/shared-nix.cpp new file mode 100644 index 00000000..e13f114f --- /dev/null +++ b/3rdparty/foo_SDK/foobar2000/shared/shared-nix.cpp @@ -0,0 +1,195 @@ +#include "shared.h" +#include +#include + +// foobar2000 SDK project method... bah +namespace foobar2000_io { + PFC_NORETURN void nix_io_op_fail(); +} +using namespace foobar2000_io; + +namespace { + class uFindFileImpl : public uFindFile { + public: + uFindFileImpl ( DIR * dir ) : m_dir(dir) {} + bool FindNext() override { + m_entry = readdir(m_dir); + return m_entry != NULL; + } + const char * GetFileName() override { + return m_entry->d_name; + } + bool IsDirectory() override { + return m_entry->d_type == DT_DIR; + } + ~uFindFileImpl() { + closedir(m_dir); + } + private: + dirent * m_entry; + + DIR * m_dir; + }; + + class uFindFileFiltered : public uFindFile { + public: + uFindFileFiltered( DIR * dir, const char * wc ) : m_impl(dir), m_wc(wc) {} + bool FindNext() override { + for( ;; ) { + if (!m_impl.FindNext()) return false; + if ( testWC() ) return true; + } + } + const char * GetFileName() override { + return m_impl.GetFileName(); + } + bool IsDirectory() override { + return m_impl.IsDirectory(); + } + bool testWC() { + return wildcard_helper::test(GetFileName(), m_wc); + } + + uFindFileImpl m_impl; + const pfc::string8 m_wc; + }; +} + +puFindFile uFindFirstFile(const char * path) { + + if ( wildcard_helper::has_wildcards( path ) ) { + size_t idx = pfc::scan_filename(path); + + try { + DIR * dir = opendir( pfc::string8(path, idx) ); + if (dir == NULL) nix_io_op_fail(); + try { + uFindFile * ff; + try { + ff = new uFindFileFiltered(dir, path + idx); + } catch(...) { closedir( dir ); throw; } + if (ff->FindNext()) return ff; + delete ff; + return NULL; + } catch(...) { closedir( dir ); throw; } + } catch(...) {return NULL;} + + } + + try { + DIR * dir = opendir( path ); + if (dir == NULL) nix_io_op_fail(); + try { + uFindFile * ff; + try { + ff = new uFindFileImpl(dir); + } catch(...) { closedir( dir ); throw; } + if (ff->FindNext()) return ff; + delete ff; + return NULL; + } catch(...) { closedir( dir ); throw; } + } catch(...) {return NULL;} +} + +pfc::string8 uStringPrintf(const char * fmt, ...) { + pfc::string8 ret; + va_list list; + va_start(list,fmt); + uPrintfV(ret,fmt,list); + va_end(list); + return ret; +} + +void uPrintfV(pfc::string_base & out,const char * fmt,va_list arglist) { + pfc::string_printf_here_va(out, fmt, arglist); +} + +void uPrintf(pfc::string_base & out,const char * fmt,...) { + va_list list;va_start(list,fmt);uPrintfV(out,fmt,list);va_end(list); +} + + +static int makeInfiniteWaitEvent() { + int fdPipe[2]; + pfc::createPipe(fdPipe); + return fdPipe[0]; // leak the other end +} + +int GetInfiniteWaitEvent() { + static int obj = makeInfiniteWaitEvent(); + return obj; +} + + +// DUMMY +void SHARED_EXPORT uAddPanicHandler(fb2k::panicHandler*) { + +} +void SHARED_EXPORT uRemovePanicHandler(fb2k::panicHandler*) { + +} + +void SHARED_EXPORT uOutputDebugString(const char * msg) { + // UGLY: underlying APIs want whole lines, calling code feeds lines terminated with \n or \r\n because Windows + pfc::string8 temp ( msg ); + if ( temp.endsWith('\n') ) temp.truncate( temp.length() - 1) ; + if ( temp.endsWith('\r') ) temp.truncate( temp.length() - 1) ; + pfc::outputDebugLine(temp); +} +namespace pfc { PFC_NORETURN void crashImpl(); } +PFC_NORETURN void SHARED_EXPORT uBugCheck() { + pfc::crashImpl(); +} + +int SHARED_EXPORT uStringCompare(const char * elem1, const char * elem2) { + return pfc::naturalSortCompareI(elem1, elem2); +} + +void fb2kDebugSelfTest() { + +} + +bool uGetTempPath(pfc::string_base & out) { + auto var = getenv("TMPDIR"); + if ( var == nullptr ) uBugCheck(); + out = var; + return true; +} +bool uGetTempFileName(const char * path_name,const char * prefix,unsigned unique,pfc::string_base & out) { +#if 0 // sample use + pfc::string8 temp_path, temp_file; + uGetTempPath(temp_path); + uGetTempFileName(temp_path, "img", 0, temp_file); +#endif + pfc::string8 ret; + if ( path_name == nullptr ) uGetTempPath( ret ); + else ret = path_name; + + pfc::chain_list_v2_t segments; + if ( prefix ) segments += prefix; + if ( unique ) segments += pfc::format(unique); + segments += pfc::print_guid(pfc::createGUID()); + + pfc::string8 fn; + for( auto & seg : segments ) { + if (seg.length() == 0) continue; + if ( fn.length() > 0 ) fn += "-"; + fn += seg; + } + + ret.add_filename( fn ); + out = ret; + return true; +} + +pfc::string8 uGetTempFileName() { + pfc::string8 ret; + uGetTempFileName(nullptr, nullptr, 0, ret); + return ret; +} + + +void fb2k::crashWithMessage [[noreturn]] ( const char * msg_ ) { + // there used to be code throwing Objective-C exceptions, but those were of no use, + pfc::crashWithMessageOnStack(msg_); +} diff --git a/3rdparty/foo_SDK/foobar2000/shared/shared-x64.lib b/3rdparty/foo_SDK/foobar2000/shared/shared-x64.lib index 26309ad8..ce643a80 100644 Binary files a/3rdparty/foo_SDK/foobar2000/shared/shared-x64.lib and b/3rdparty/foo_SDK/foobar2000/shared/shared-x64.lib differ diff --git a/3rdparty/foo_SDK/foobar2000/shared/shared.h b/3rdparty/foo_SDK/foobar2000/shared/shared.h index aac19119..b0b24946 100644 --- a/3rdparty/foo_SDK/foobar2000/shared/shared.h +++ b/3rdparty/foo_SDK/foobar2000/shared/shared.h @@ -89,8 +89,10 @@ BOOL SHARED_EXPORT uGetClipboardString(pfc::string_base & out); BOOL SHARED_EXPORT uSetClipboardRawData(UINT format,const void * ptr,t_size size);//does not empty the clipboard BOOL SHARED_EXPORT uGetClassName(HWND wnd,pfc::string_base & out); t_size SHARED_EXPORT uCharLength(const char * src); +#ifdef DragQueryFile // don't declare if relevant Windows #include has been omitted, breaks on HDROP BOOL SHARED_EXPORT uDragQueryFile(HDROP hDrop,UINT idx,pfc::string_base & out); UINT SHARED_EXPORT uDragQueryFileCount(HDROP hDrop); +#endif BOOL SHARED_EXPORT uGetTextExtentPoint32(HDC dc,const char * text,UINT cb,LPSIZE size);//note, cb is number of bytes, not actual unicode characters in the string (read: plain strlen() will do) BOOL SHARED_EXPORT uExtTextOut(HDC dc,int x,int y,UINT flags,const RECT * rect,const char * text,UINT cb,const int * lpdx); BOOL SHARED_EXPORT uTextOutColors(HDC dc,const char * src,UINT len,int x,int y,const RECT * clip,BOOL is_selected,DWORD default_color); @@ -278,6 +280,7 @@ UINT SHARED_EXPORT uGetMenuItemType(HMENU menu,UINT position); HMODULE SHARED_EXPORT LoadSystemLibrary(const TCHAR * name); void SHARED_EXPORT uPrintCrashInfo_OnEvent(const char * message, t_size length); +void SHARED_EXPORT uPrintCrashInfo_StartLogging(const char * path); }//extern "C" @@ -565,7 +568,7 @@ typedef HICON hicon_t; typedef HMENU hmenu_t; typedef HFONT hfont_t; #else -typedef void* hwnd_t; +typedef void* hwnd_t; // Mac: bridged NSObject, context specific (NSWindow, NSView, NSViewController) typedef void* hicon_t; typedef void* hmenu_t; typedef void* hfont_t; diff --git a/3rdparty/foo_SDK/foobar2000/shared/shared.vcxproj b/3rdparty/foo_SDK/foobar2000/shared/shared.vcxproj new file mode 100644 index 00000000..db8b6778 --- /dev/null +++ b/3rdparty/foo_SDK/foobar2000/shared/shared.vcxproj @@ -0,0 +1,420 @@ + + + + + Debug + ARM64 + + + Debug + ARM64EC + + + Debug + Win32 + + + Debug + x64 + + + Release + ARM64 + + + Release + ARM64EC + + + Release + Win32 + + + Release + x64 + + + + {054C606B-17BF-4540-AC4E-A9A7243628B8} + shared + Win32Proj + + + + DynamicLibrary + Unicode + true + v143 + + + DynamicLibrary + Unicode + true + v143 + + + DynamicLibrary + Unicode + true + v143 + + + DynamicLibrary + Unicode + true + v143 + + + DynamicLibrary + Unicode + v143 + + + DynamicLibrary + Unicode + v143 + + + DynamicLibrary + Unicode + v143 + + + DynamicLibrary + Unicode + v143 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + $(SolutionDir)$(Configuration)\ + $(Configuration)\ + true + true + true + true + $(SolutionDir)$(Configuration)\ + $(Configuration)\ + false + false + false + false + + + + Disabled + EnableFastChecks + Use + shared.h + Level3 + ProgramDatabase + MultiThreadedDebugDLL + 4715 + Fast + _CRT_SECURE_NO_WARNINGS;SHARED_EXPORTS;_WINDLL;%(PreprocessorDefinitions) + true + stdcpp20 + + + comctl32.lib;imagehlp.lib;uxtheme.lib;dbghelp.lib;%(AdditionalDependencies) + true + $(OutDir)shared.pdb + Windows + + + $(OutDir)shared.lib + MachineX86 + + + + + Disabled + EnableFastChecks + Use + shared.h + Level3 + ProgramDatabase + MultiThreadedDebugDLL + 4715 + Fast + _CRT_SECURE_NO_WARNINGS;SHARED_EXPORTS;_WINDLL;%(PreprocessorDefinitions) + true + stdcpp20 + + + comctl32.lib;imagehlp.lib;uxtheme.lib;dbghelp.lib;%(AdditionalDependencies) + true + $(OutDir)shared.pdb + Windows + + + $(OutDir)shared.lib + + + + + Disabled + EnableFastChecks + Use + shared.h + Level3 + ProgramDatabase + MultiThreadedDebugDLL + 4715 + Fast + _CRT_SECURE_NO_WARNINGS;SHARED_EXPORTS;_WINDLL;%(PreprocessorDefinitions) + true + stdcpp20 + + + comctl32.lib;imagehlp.lib;uxtheme.lib;dbghelp.lib;%(AdditionalDependencies) + true + $(OutDir)shared.pdb + Windows + + + $(OutDir)shared.lib + + + + + Disabled + EnableFastChecks + Use + shared.h + Level3 + ProgramDatabase + MultiThreadedDebugDLL + 4715 + Fast + _CRT_SECURE_NO_WARNINGS;SHARED_EXPORTS;_WINDLL;%(PreprocessorDefinitions) + true + stdcpp20 + + + comctl32.lib;imagehlp.lib;uxtheme.lib;dbghelp.lib;%(AdditionalDependencies) + true + $(OutDir)shared.pdb + Windows + + + $(OutDir)shared.lib + + + + + Full + true + false + Fast + false + Use + shared.h + Level3 + ProgramDatabase + MultiThreadedDLL + /d2notypeopt %(AdditionalOptions) + 4715 + true + _CRT_SECURE_NO_WARNINGS;SHARED_EXPORTS;_WINDLL;NDEBUG;%(PreprocessorDefinitions) + true + stdcpp20 + + + comctl32.lib;imagehlp.lib;uxtheme.lib;dbghelp.lib;%(AdditionalDependencies) + true + Windows + true + true + + + $(OutDir)shared.lib + MachineX86 + + + copy "$(OutDir)shared.lib" "$(ProjectDir)shared-$(Platform).lib" + + + + + Full + true + false + Fast + false + Use + shared.h + Level3 + ProgramDatabase + MultiThreadedDLL + /d2notypeopt %(AdditionalOptions) + 4715 + true + _CRT_SECURE_NO_WARNINGS;SHARED_EXPORTS;_WINDLL;NDEBUG;%(PreprocessorDefinitions) + true + stdcpp20 + + + comctl32.lib;imagehlp.lib;uxtheme.lib;dbghelp.lib;%(AdditionalDependencies) + true + Windows + true + true + + + $(OutDir)shared.lib + + + copy "$(OutDir)shared.lib" "$(ProjectDir)shared-$(Platform).lib" + + + + + Full + true + false + Fast + false + Use + shared.h + Level3 + ProgramDatabase + MultiThreadedDLL + /d2notypeopt %(AdditionalOptions) + 4715 + true + _CRT_SECURE_NO_WARNINGS;SHARED_EXPORTS;_WINDLL;NDEBUG;%(PreprocessorDefinitions) + true + stdcpp20 + + + comctl32.lib;imagehlp.lib;uxtheme.lib;dbghelp.lib;%(AdditionalDependencies) + true + Windows + true + true + + + $(OutDir)shared.lib + + + copy "$(OutDir)shared.lib" "$(ProjectDir)shared-$(Platform).lib" + + + + + Full + true + false + Fast + false + Use + shared.h + Level3 + ProgramDatabase + MultiThreadedDLL + /d2notypeopt %(AdditionalOptions) + 4715 + true + _CRT_SECURE_NO_WARNINGS;SHARED_EXPORTS;_WINDLL;NDEBUG;%(PreprocessorDefinitions) + true + stdcpp20 + + + comctl32.lib;imagehlp.lib;uxtheme.lib;dbghelp.lib;%(AdditionalDependencies) + true + Windows + true + true + + + $(OutDir)shared.lib + + + copy "$(OutDir)shared.lib" "$(ProjectDir)shared-$(Platform).lib" + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Create + Create + Create + Create + Create + Create + Create + Create + + + + + + + + + + + + + + + + + {ebfffb4e-261d-44d3-b89c-957b31a0bf9c} + + + + + + \ No newline at end of file diff --git a/3rdparty/foo_SDK/foobar2000/shared/shared.vcxproj.filters b/3rdparty/foo_SDK/foobar2000/shared/shared.vcxproj.filters new file mode 100644 index 00000000..0bad1ee2 --- /dev/null +++ b/3rdparty/foo_SDK/foobar2000/shared/shared.vcxproj.filters @@ -0,0 +1,75 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + \ No newline at end of file diff --git a/3rdparty/foo_SDK/foobar2000/shared/shared.xcodeproj/project.pbxproj b/3rdparty/foo_SDK/foobar2000/shared/shared.xcodeproj/project.pbxproj new file mode 100644 index 00000000..3eb996b6 --- /dev/null +++ b/3rdparty/foo_SDK/foobar2000/shared/shared.xcodeproj/project.pbxproj @@ -0,0 +1,352 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 50; + objects = { + +/* Begin PBXBuildFile section */ + 0F75F3A72A6B1A8C00A45078 /* stdafx.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F75F3932A6B1A8C00A45078 /* stdafx.cpp */; }; + 0F75F3AB2A6B1A8C00A45078 /* shared-apple.mm in Sources */ = {isa = PBXBuildFile; fileRef = 0F75F39A2A6B1A8C00A45078 /* shared-apple.mm */; }; + 0F75F3AC2A6B1A8C00A45078 /* utf8.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F75F39B2A6B1A8C00A45078 /* utf8.cpp */; }; + 0F75F3AE2A6B1A8C00A45078 /* shared-nix.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F75F39E2A6B1A8C00A45078 /* shared-nix.cpp */; }; + 0F75F3B02A6B1A8C00A45078 /* audio_math.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F75F3A02A6B1A8C00A45078 /* audio_math.cpp */; }; +/* End PBXBuildFile section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 0F75F3772A6B1A3900A45078 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = "include/$(PRODUCT_NAME)"; + dstSubfolderSpec = 16; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 0F75F3792A6B1A3900A45078 /* libshared.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libshared.a; sourceTree = BUILT_PRODUCTS_DIR; }; + 0F75F38C2A6B1A8C00A45078 /* modal_dialog.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = modal_dialog.cpp; sourceTree = ""; }; + 0F75F38D2A6B1A8C00A45078 /* minidump.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = minidump.cpp; sourceTree = ""; }; + 0F75F38E2A6B1A8C00A45078 /* font_description.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = font_description.cpp; sourceTree = ""; }; + 0F75F38F2A6B1A8C00A45078 /* filedialogs_vista.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = filedialogs_vista.cpp; sourceTree = ""; }; + 0F75F3902A6B1A8C00A45078 /* audio_math.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = audio_math.h; sourceTree = ""; }; + 0F75F3912A6B1A8C00A45078 /* text_drawing.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = text_drawing.cpp; sourceTree = ""; }; + 0F75F3922A6B1A8C00A45078 /* filedialogs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = filedialogs.h; sourceTree = ""; }; + 0F75F3932A6B1A8C00A45078 /* stdafx.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = stdafx.cpp; sourceTree = ""; }; + 0F75F3942A6B1A8C00A45078 /* crash_info.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = crash_info.cpp; sourceTree = ""; }; + 0F75F3952A6B1A8C00A45078 /* fb2kdebug.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fb2kdebug.h; sourceTree = ""; }; + 0F75F3962A6B1A8C00A45078 /* systray.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = systray.cpp; sourceTree = ""; }; + 0F75F3972A6B1A8C00A45078 /* win32_misc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = win32_misc.h; sourceTree = ""; }; + 0F75F3982A6B1A8C00A45078 /* shared-nix.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "shared-nix.h"; sourceTree = ""; }; + 0F75F3992A6B1A8C00A45078 /* filedialogs.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = filedialogs.cpp; sourceTree = ""; }; + 0F75F39A2A6B1A8C00A45078 /* shared-apple.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = "shared-apple.mm"; sourceTree = ""; }; + 0F75F39B2A6B1A8C00A45078 /* utf8.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = utf8.cpp; sourceTree = ""; }; + 0F75F39C2A6B1A8C00A45078 /* utf8api.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = utf8api.cpp; sourceTree = ""; }; + 0F75F39D2A6B1A8C00A45078 /* shared.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = shared.h; sourceTree = ""; }; + 0F75F39E2A6B1A8C00A45078 /* shared-nix.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "shared-nix.cpp"; sourceTree = ""; }; + 0F75F39F2A6B1A8C00A45078 /* Utility.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Utility.cpp; sourceTree = ""; }; + 0F75F3A02A6B1A8C00A45078 /* audio_math.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = audio_math.cpp; sourceTree = ""; }; + 0F75F3A12A6B1A8C00A45078 /* shared-apple.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "shared-apple.h"; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 0F75F3762A6B1A3900A45078 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 0F75F3702A6B1A3900A45078 = { + isa = PBXGroup; + children = ( + 0F75F38B2A6B1A7D00A45078 /* Source */, + 0F75F37A2A6B1A3900A45078 /* Products */, + ); + sourceTree = ""; + }; + 0F75F37A2A6B1A3900A45078 /* Products */ = { + isa = PBXGroup; + children = ( + 0F75F3792A6B1A3900A45078 /* libshared.a */, + ); + name = Products; + sourceTree = ""; + }; + 0F75F38B2A6B1A7D00A45078 /* Source */ = { + isa = PBXGroup; + children = ( + 0F75F3A02A6B1A8C00A45078 /* audio_math.cpp */, + 0F75F3902A6B1A8C00A45078 /* audio_math.h */, + 0F75F3942A6B1A8C00A45078 /* crash_info.cpp */, + 0F75F3952A6B1A8C00A45078 /* fb2kdebug.h */, + 0F75F38F2A6B1A8C00A45078 /* filedialogs_vista.cpp */, + 0F75F3992A6B1A8C00A45078 /* filedialogs.cpp */, + 0F75F3922A6B1A8C00A45078 /* filedialogs.h */, + 0F75F38E2A6B1A8C00A45078 /* font_description.cpp */, + 0F75F38D2A6B1A8C00A45078 /* minidump.cpp */, + 0F75F38C2A6B1A8C00A45078 /* modal_dialog.cpp */, + 0F75F3A12A6B1A8C00A45078 /* shared-apple.h */, + 0F75F39A2A6B1A8C00A45078 /* shared-apple.mm */, + 0F75F39E2A6B1A8C00A45078 /* shared-nix.cpp */, + 0F75F3982A6B1A8C00A45078 /* shared-nix.h */, + 0F75F39D2A6B1A8C00A45078 /* shared.h */, + 0F75F3932A6B1A8C00A45078 /* stdafx.cpp */, + 0F75F3962A6B1A8C00A45078 /* systray.cpp */, + 0F75F3912A6B1A8C00A45078 /* text_drawing.cpp */, + 0F75F39B2A6B1A8C00A45078 /* utf8.cpp */, + 0F75F39C2A6B1A8C00A45078 /* utf8api.cpp */, + 0F75F39F2A6B1A8C00A45078 /* Utility.cpp */, + 0F75F3972A6B1A8C00A45078 /* win32_misc.h */, + ); + name = Source; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 0F75F3782A6B1A3900A45078 /* shared */ = { + isa = PBXNativeTarget; + buildConfigurationList = 0F75F3822A6B1A3900A45078 /* Build configuration list for PBXNativeTarget "shared" */; + buildPhases = ( + 0F75F3752A6B1A3900A45078 /* Sources */, + 0F75F3762A6B1A3900A45078 /* Frameworks */, + 0F75F3772A6B1A3900A45078 /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = shared; + productName = shared; + productReference = 0F75F3792A6B1A3900A45078 /* libshared.a */; + productType = "com.apple.product-type.library.static"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 0F75F3712A6B1A3900A45078 /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 1250; + TargetAttributes = { + 0F75F3782A6B1A3900A45078 = { + CreatedOnToolsVersion = 12.5.1; + }; + }; + }; + buildConfigurationList = 0F75F3742A6B1A3900A45078 /* Build configuration list for PBXProject "shared" */; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 0F75F3702A6B1A3900A45078; + productRefGroup = 0F75F37A2A6B1A3900A45078 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 0F75F3782A6B1A3900A45078 /* shared */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXSourcesBuildPhase section */ + 0F75F3752A6B1A3900A45078 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 0F75F3B02A6B1A8C00A45078 /* audio_math.cpp in Sources */, + 0F75F3AE2A6B1A8C00A45078 /* shared-nix.cpp in Sources */, + 0F75F3AB2A6B1A8C00A45078 /* shared-apple.mm in Sources */, + 0F75F3A72A6B1A8C00A45078 /* stdafx.cpp in Sources */, + 0F75F3AC2A6B1A8C00A45078 /* utf8.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 0F75F3802A6B1A3900A45078 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = shared.h; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + HEADER_SEARCH_PATHS = ( + ../.., + .., + ); + IPHONEOS_DEPLOYMENT_TARGET = 14.5; + MACOSX_DEPLOYMENT_TARGET = 10.13; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + }; + name = Debug; + }; + 0F75F3812A6B1A3900A45078 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = shared.h; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + HEADER_SEARCH_PATHS = ( + ../.., + .., + ); + IPHONEOS_DEPLOYMENT_TARGET = 14.5; + MACOSX_DEPLOYMENT_TARGET = 10.13; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + SDKROOT = macosx; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 0F75F3832A6B1A3900A45078 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = 4S876G9VCD; + OTHER_LDFLAGS = "-ObjC"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 0F75F3842A6B1A3900A45078 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = 4S876G9VCD; + OTHER_LDFLAGS = "-ObjC"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 0F75F3742A6B1A3900A45078 /* Build configuration list for PBXProject "shared" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 0F75F3802A6B1A3900A45078 /* Debug */, + 0F75F3812A6B1A3900A45078 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 0F75F3822A6B1A3900A45078 /* Build configuration list for PBXNativeTarget "shared" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 0F75F3832A6B1A3900A45078 /* Debug */, + 0F75F3842A6B1A3900A45078 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 0F75F3712A6B1A3900A45078 /* Project object */; +} diff --git a/3rdparty/foo_SDK/foobar2000/shared/stdafx.cpp b/3rdparty/foo_SDK/foobar2000/shared/stdafx.cpp new file mode 100644 index 00000000..a036ba6b --- /dev/null +++ b/3rdparty/foo_SDK/foobar2000/shared/stdafx.cpp @@ -0,0 +1 @@ +#include "shared.h" \ No newline at end of file diff --git a/3rdparty/foo_SDK/foobar2000/shared/systray.cpp b/3rdparty/foo_SDK/foobar2000/shared/systray.cpp new file mode 100644 index 00000000..3c5e0478 --- /dev/null +++ b/3rdparty/foo_SDK/foobar2000/shared/systray.cpp @@ -0,0 +1,108 @@ +#include "shared.h" +#include + +void SHARED_EXPORT uFixAmpersandChars(const char * src,pfc::string_base & out) +{ + out.reset(); + while(*src) + { + if (*src=='&') + { + out.add_string("&&&"); + src++; + while(*src=='&') + { + out.add_string("&&"); + src++; + } + } + else out.add_byte(*(src++)); + } +} + +void SHARED_EXPORT uFixAmpersandChars_v2(const char * src,pfc::string_base & out) +{ + out.reset(); + while(*src) + { + if (*src=='&') + { + out.add_string("&&"); + src++; + } + else out.add_byte(*(src++)); + } +} + +static BOOL run_action(DWORD action,NOTIFYICONDATA * data) +{ + if (Shell_NotifyIcon(action,data)) return TRUE; + if (action==NIM_MODIFY) + { + if (Shell_NotifyIcon(NIM_ADD,data)) return TRUE; + } + return FALSE; +} + +extern "C" +{ + + BOOL SHARED_EXPORT uShellNotifyIcon(DWORD action,HWND wnd,UINT id,UINT callbackmsg,HICON icon,const char * tip) + { + NOTIFYICONDATA nid = {}; + nid.cbSize = sizeof(nid); + nid.hWnd = wnd; + nid.uID = id; + nid.uFlags = 0; + if (callbackmsg) + { + nid.uFlags |= NIF_MESSAGE; + nid.uCallbackMessage = callbackmsg; + } + if (icon) + { + nid.uFlags |= NIF_ICON; + nid.hIcon = icon; + } + if (tip) + { + nid.uFlags |= NIF_TIP; + pfc::stringToBuffer(nid.szTip,pfc::stringcvt::string_os_from_utf8(tip)); + } + + return run_action(action,&nid); + } + + BOOL SHARED_EXPORT uShellNotifyIconEx(DWORD action,HWND wnd,UINT id,UINT callbackmsg,HICON icon,const char * tip,const char * balloon_title,const char * balloon_msg) + { + NOTIFYICONDATA nid = {}; + nid.cbSize = sizeof(nid); + nid.hWnd = wnd; + nid.uID = id; + if (callbackmsg) + { + nid.uFlags |= NIF_MESSAGE; + nid.uCallbackMessage = callbackmsg; + } + if (icon) + { + nid.uFlags |= NIF_ICON; + nid.hIcon = icon; + } + if (tip) + { + nid.uFlags |= NIF_TIP; + pfc::stringToBuffer(nid.szTip,pfc::stringcvt::string_os_from_utf8(tip)); + } + + nid.dwInfoFlags = NIIF_INFO | NIIF_NOSOUND; + //if (balloon_title || balloon_msg) + { + nid.uFlags |= NIF_INFO; + if (balloon_title) pfc::stringToBuffer(nid.szInfoTitle,pfc::stringcvt::string_os_from_utf8(balloon_title)); + if (balloon_msg) pfc::stringToBuffer(nid.szInfo,pfc::stringcvt::string_os_from_utf8(balloon_msg)); + } + return run_action(action,&nid); + } + +}//extern "C" diff --git a/3rdparty/foo_SDK/foobar2000/shared/text_drawing.cpp b/3rdparty/foo_SDK/foobar2000/shared/text_drawing.cpp new file mode 100644 index 00000000..a728614a --- /dev/null +++ b/3rdparty/foo_SDK/foobar2000/shared/text_drawing.cpp @@ -0,0 +1,230 @@ +#include "shared.h" + + +static bool is_rect_null(const RECT * r) +{ + return r->right <= r->left || r->bottom <= r->top; +} + +UINT SHARED_EXPORT uGetTextHeight(HDC dc) +{ + TEXTMETRIC tm; + POINT pt[2]; + GetTextMetrics(dc,&tm); + pt[0].x = 0; + pt[0].y = tm.tmHeight; + pt[1].x = 0; + pt[1].y = 0; + LPtoDP(dc,pt,2); + + int ret = pt[0].y - pt[1].y; + return ret > 1 ? (unsigned)ret : 1; +} + +static int get_text_width(HDC dc,const TCHAR * src,int len) +{ + if (len<=0) return 0; + else + { + SIZE goatse; + GetTextExtentPoint32(dc,src,len,&goatse); + return goatse.cx; + } +} + +//GetTextExtentPoint32 wrapper, removes color marks +static int get_text_width_color(HDC dc,const TCHAR * src,int len) +{ + int ptr = 0; + int start = 0; + int rv = 0; + if (len<0) len = (int) _tcslen(src); + while(ptrright<=pos_x || clip->bottom<=pos_y) return TRUE; + } + SetTextAlign(dc,TA_LEFT); + SetBkMode(dc,TRANSPARENT); + SetTextColor(dc,selected ? 0xFFFFFF - default_color : default_color); + + int title_ptr = 0; + int textout_start = 0; + int position = pos_x;//item.left+BORDER; + + for(;;) + { + if (title_ptr>=len || src[title_ptr]==3) + { + if (title_ptr>textout_start) + { + int width = get_text_width(dc,src+textout_start,title_ptr-textout_start); + ExtTextOut(dc,position,pos_y,clip ? ETO_CLIPPED : 0,clip,src+textout_start,title_ptr-textout_start,0); + position += width; + textout_start = title_ptr; + } + if (title_ptr>=len) break; + } + if (src[title_ptr]==3) + { + DWORD new_color; + DWORD new_inverted; + bool have_inverted = false; + + if (src[title_ptr+1]==3) {new_color=default_color;title_ptr+=2;} + else + { + title_ptr++; + new_color = _tcstoul(src+title_ptr,0,16); + while(title_ptrtop + (item->bottom-item->top - (int)uGetTextHeight(dc)) / 2; + + int n_tabs = 0; + int total_width = 0; + { + int start = 0; + int n; + for(n=0;nright - item->left; + if (!columns) tab_total -= total_width; + int ptr = display_len; + int tab_ptr = 0; + int written = 0; + int clip_x = item->right; + do + { + int ptr_end = ptr; + while(ptr>0 && display[ptr-1]!='\t') ptr--; + const TCHAR * t_string = display + ptr; + int t_length = ptr_end - ptr; + if (t_length>0) + { + int t_width = get_text_width_color(dc,t_string,t_length) + border*2; + + int pos_x; + int pos_x_right; + + if (!columns) + { + pos_x_right = item->right - MulDiv(tab_ptr,tab_total,n_tabs) - written; + } + else + { + if (tab_ptr==0) pos_x_right = item->right; + else pos_x_right = item->right - MulDiv(tab_ptr,tab_total,n_tabs) + t_width; + } + + if (ptr==0) + { + pos_x = item->left; + } + else + { + pos_x = pos_x_right - t_width ; + if (pos_xleft) pos_x = item->left; + } + + RECT t_clip = clip; + + if (t_clip.right > clip_x) t_clip.right = clip_x; + + text_out_colors(dc,t_string,t_length,pos_x+border,pos_y,&t_clip,selected,default_color); + + if (clip_x>pos_x) clip_x = pos_x; + + written += t_width; + } + + if (ptr>0) + { + ptr--;//tab char + tab_ptr++; + } + } + while(ptr>0); + + return TRUE; +} + +extern "C" { + +BOOL SHARED_EXPORT uTextOutColors(HDC dc,const char * p_text,UINT len,int x,int y,const RECT * clip,BOOL is_selected,DWORD default_color) +{ + try { + pfc::stringcvt::string_os_from_utf8 temp(p_text); + return text_out_colors(dc,temp,pfc::downcast_guarded(temp.length()),x,y,clip,!!is_selected,default_color); + } catch(...) {return FALSE;} +} + +BOOL SHARED_EXPORT uTextOutColorsTabbed(HDC dc,const char * p_text,UINT len,const RECT * item,int border,const RECT * clip,BOOL selected,DWORD default_color,BOOL use_columns) +{ + try { + pfc::stringcvt::string_os_from_utf8 temp(p_text); + return text_out_colors_tab(dc,temp,pfc::downcast_guarded(temp.length()),item,border,clip,!!selected,default_color,!!use_columns); + } catch(...) {return FALSE;} +} + +} \ No newline at end of file diff --git a/3rdparty/foo_SDK/foobar2000/shared/utf8.cpp b/3rdparty/foo_SDK/foobar2000/shared/utf8.cpp new file mode 100644 index 00000000..18f87935 --- /dev/null +++ b/3rdparty/foo_SDK/foobar2000/shared/utf8.cpp @@ -0,0 +1,226 @@ +#include "shared.h" + +#include + +using namespace pfc; + +extern "C" { + +#if 0 +inline static unsigned q_tolower(unsigned c) +{ + if (c>='A' && c<='Z') c += 'a' - 'A'; + return c; +} +#else +static const t_uint8 ascii_tolower_table[128] = {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3A,0x3B,0x3C,0x3D,0x3E,0x3F,0x40,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6A,0x6B,0x6C,0x6D,0x6E,0x6F,0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7A,0x5B,0x5C,0x5D,0x5E,0x5F,0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6A,0x6B,0x6C,0x6D,0x6E,0x6F,0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7A,0x7B,0x7C,0x7D,0x7E,0x7F}; +#define q_tolower(c) ascii_tolower_table[(unsigned)c] +#endif + + +unsigned SHARED_EXPORT uCharLower(unsigned param) +{ + return pfc::charLower(param); +} + +unsigned SHARED_EXPORT uCharUpper(unsigned param) +{ + return pfc::charUpper(param); +} + +static inline int compare_wchar(unsigned c1,unsigned c2) throw() +{ + if (c1==c2) return 0; + c1 = pfc::charLower(c1); + c2 = pfc::charLower(c2); + if (c1c2) return 1; + else return 0; +} + + +int SHARED_EXPORT stricmp_utf8(const char * p1,const char * p2) throw() +{ + for(;;) + { + if (*p1>=0 && *p2>=0)//signed char + { + unsigned c1 = q_tolower(*p1), c2 = q_tolower(*p2); + if (c1c2) return 1; + else if (c1 == 0) return 0; + else + { + p1++; + p2++; + } + } + else + { + unsigned w1,w2; t_size d1,d2; + d1 = utf8_decode_char(p1,w1); + d2 = utf8_decode_char(p2,w2); + if (d1 == 0 && d2 == 0) return 0; + else if (d1==0) return -1; + else if (d2==0) return 1; + int rv = compare_wchar(w1,w2); + if (rv) return rv; + p1 += d1; + p2 += d2; + } + } +} + +int SHARED_EXPORT stricmp_utf8_stringtoblock(const char * p1,const char * p2,t_size p2_bytes) throw() +{ + return stricmp_utf8_ex(p1,-1,p2,p2_bytes); +} + +int SHARED_EXPORT stricmp_utf8_partial(const char * p1,const char * p2,t_size num) throw() +{ + for(;num;) + { + unsigned w1,w2; t_size d1,d2; + d1 = utf8_decode_char(p1,w1); + d2 = utf8_decode_char(p2,w2); + if (w2==0 || d2==0) return 0; + int rv = compare_wchar(w1,w2); + if (rv) return rv; + p1 += d1; + p2 += d2; + num--; + } + return 0; +} + +int SHARED_EXPORT stricmp_utf8_max(const char * p1,const char * p2,t_size p1_bytes) throw() +{ + return stricmp_utf8_ex(p1,p1_bytes,p2,-1); +} + +namespace { + typedef bool (*t_replace_test)(const char * src,const char * test,t_size len); + + static bool replace_test_i(const char * src,const char * test,t_size len) + { + return stricmp_utf8_max(src,test,len)==0; + } + + static bool replace_test(const char * src,const char * test,t_size len) + { + t_size ptr; + bool rv = true; + for(ptr=0;ptr0) + { + t_size ptr = 0; + while(ptr+len1<=len) + { + if (testfunc(src+ptr,s1,len1)) + { + count++; + out.add_string(s2,len2); + ptr += len1; + } + else out.add_byte(src[ptr++]); + } + if (ptr0); + assert(c2>0); + char s1[8],s2[8]; + t_size len1,len2; + len1 = utf8_encode_char(c1,s1); + len2 = utf8_encode_char(c2,s2); + return uReplaceString(out,src,src_len,s1,len1,s2,len2,casesens); +} + + +void SHARED_EXPORT uAddStringLower(string_base & out,const char * src,t_size len) +{ + while(len && *src) + { + unsigned c; t_size d; + d = utf8_decode_char(src,c,len); + if (d==0 || d>len) break; + out.add_char(uCharLower(c)); + src+=d; + len-=d; + } +} + +void SHARED_EXPORT uAddStringUpper(string_base & out,const char * src,t_size len) +{ + while(len && *src) + { + unsigned c; t_size d; + d = utf8_decode_char(src,c,len); + if (d==0 || d>len) break; + out.add_char(uCharUpper(c)); + src+=d; + len-=d; + } +} + +int SHARED_EXPORT stricmp_utf8_ex(const char * p1,t_size p1_bytes,const char * p2,t_size p2_bytes) throw() +{ + p1_bytes = strlen_max(p1,p1_bytes); + p2_bytes = strlen_max(p2,p2_bytes); + for(;;) + { + if (p1_bytes == 0 && p2_bytes == 0) return 0; + else if (p1_bytes == 0) return -1; + else if (p2_bytes == 0) return 1; + else if (*p1>0 && *p2>0)//signed char + { + unsigned c1 = q_tolower(*p1), c2 = q_tolower(*p2); + if (c1c2) return 1; + else + { + p1++; + p2++; + p1_bytes--; + p2_bytes--; + } + } + else + { + unsigned w1,w2; + auto d1 = utf8_decode_char(p1,w1,p1_bytes); + auto d2 = utf8_decode_char(p2,w2,p2_bytes); + if (d1==0) return -1; + if (d2==0) return 1; + int rv = compare_wchar(w1,w2); + if (rv) return rv; + p1 += d1; + p2 += d2; + p1_bytes -= d1; + p2_bytes -= d2; + } + } +} + +} diff --git a/3rdparty/foo_SDK/foobar2000/shared/utf8api.cpp b/3rdparty/foo_SDK/foobar2000/shared/utf8api.cpp new file mode 100644 index 00000000..2471b87d --- /dev/null +++ b/3rdparty/foo_SDK/foobar2000/shared/utf8api.cpp @@ -0,0 +1,1186 @@ +#include "shared.h" + + +#include + +#ifndef BIF_NEWDIALOGSTYLE +#define BIF_NEWDIALOGSTYLE 0x0040 +#endif + +using namespace pfc; + +class param_os_from_utf8 +{ + bool m_is_null; + WORD m_low_word; + stringcvt::string_os_from_utf8 m_cvt; +public: + param_os_from_utf8(const char * p) : + m_is_null(p==NULL), + m_low_word( ((t_size)p & ~0xFFFF) == 0 ? (WORD)((t_size)p & 0xFFFF) : 0), + m_cvt( p != NULL && ((t_size)p & ~0xFFFF) != 0 ? p : "") + {} + operator const TCHAR *() + { + return get_ptr(); + } + const TCHAR * get_ptr() + { + return m_low_word ? (const TCHAR*)(t_size)m_low_word : m_is_null ? 0 : m_cvt.get_ptr(); + } + +}; + + + +extern "C" { + +LRESULT SHARED_EXPORT uSendMessageText(HWND wnd,UINT msg,WPARAM wp,const char * p_text) +{ + if (p_text == NULL) + return SendMessage(wnd,msg,wp,0); + else { + stringcvt::string_os_from_utf8 temp; + temp.convert(p_text); + return SendMessage(wnd,msg,wp,(LPARAM)temp.get_ptr()); + } +} + +LRESULT SHARED_EXPORT uSendDlgItemMessageText(HWND wnd,UINT id,UINT msg,WPARAM wp,const char * text) +{ + return uSendMessageText(uGetDlgItem(wnd,id),msg,wp,text);//SendDlgItemMessage(wnd,id,msg,wp,(long)(const TCHAR*)string_os_from_utf8(text)); +} + +BOOL SHARED_EXPORT uGetWindowText(HWND wnd,string_base & out) +{ + PFC_ASSERT( wnd != NULL ); + int len = GetWindowTextLength(wnd); + if (len>0) + { + len++; + pfc::array_t temp; + temp.set_size(len); + temp[0]=0; + if (GetWindowText(wnd,temp.get_ptr(),len)>0) + { + out = stringcvt::string_utf8_from_os(temp.get_ptr(),len); + return TRUE; + } + else return FALSE; + } + else + { + out.reset(); + return TRUE; + } +} + +BOOL SHARED_EXPORT uSetWindowTextEx(HWND wnd,const char * p_text,size_t p_text_length) +{ + return SetWindowText(wnd,stringcvt::string_os_from_utf8(p_text, p_text_length)); +} + + +BOOL SHARED_EXPORT uGetDlgItemText(HWND wnd,UINT id,string_base & out) +{ + return uGetWindowText(GetDlgItem(wnd,id),out); +} + +BOOL SHARED_EXPORT uSetDlgItemTextEx(HWND wnd,UINT id,const char * p_text,size_t p_text_length) +{ + return SetDlgItemText(wnd,id,stringcvt::string_os_from_utf8(p_text,p_text_length)); +} + +int SHARED_EXPORT uMessageBox(HWND wnd,const char * text,const char * caption,UINT type) +{ + modal_dialog_scope scope(wnd); + return MessageBox(wnd,param_os_from_utf8(text),param_os_from_utf8(caption),type); +} + +void SHARED_EXPORT uOutputDebugString(const char * msg) {OutputDebugString(stringcvt::string_os_from_utf8(msg));} + +BOOL SHARED_EXPORT uAppendMenu(HMENU menu,UINT flags,UINT_PTR id,const char * content) +{ + return AppendMenu(menu,flags,id,param_os_from_utf8(content)); +} + +BOOL SHARED_EXPORT uInsertMenu(HMENU menu,UINT position,UINT flags,UINT_PTR id,const char * content) +{ + return InsertMenu(menu,position,flags,id,param_os_from_utf8(content)); +} + +int SHARED_EXPORT uCharCompare(t_uint32 p_char1,t_uint32 p_char2) { +#ifdef UNICODE + wchar_t temp1[4],temp2[4]; + temp1[utf16_encode_char(p_char1,temp1)]=0; + temp2[utf16_encode_char(p_char2,temp2)]=0; + return lstrcmpiW(temp1,temp2); +#else + wchar_t temp1[4],temp2[4]; + char ctemp1[20],ctemp2[20]; + temp1[utf16_encode_char(p_char1,temp1)]=0; + temp2[utf16_encode_char(p_char2,temp2)]=0; + WideCharToMultiByte(CP_ACP,0,temp1,-1,ctemp1,_countof(ctemp1),0,0); + WideCharToMultiByte(CP_ACP,0,temp2,-1,ctemp2,_countof(ctemp2),0,0); + return lstrcmpiA(ctemp1,ctemp2); +#endif +} + +int SHARED_EXPORT uStringCompare(const char * elem1, const char * elem2) { + for(;;) { + unsigned c1,c2; t_size l1,l2; + l1 = utf8_decode_char(elem1,c1); + l2 = utf8_decode_char(elem2,c2); + if (l1==0 && l2==0) return 0; + if (c1!=c2) { + int test = uCharCompare(c1,c2); + if (test) return test; + } + elem1 += l1; + elem2 += l2; + } +} + +int SHARED_EXPORT uStringCompare_ConvertNumbers(const char * elem1,const char * elem2) { + for(;;) { + if (pfc::char_is_numeric(*elem1) && pfc::char_is_numeric(*elem2)) { + t_size delta1 = 1, delta2 = 1; + while(pfc::char_is_numeric(elem1[delta1])) delta1++; + while(pfc::char_is_numeric(elem2[delta2])) delta2++; + int test = pfc::compare_t(pfc::atoui64_ex(elem1,delta1),pfc::atoui64_ex(elem2,delta2)); + if (test != 0) return test; + elem1 += delta1; + elem2 += delta2; + } else { + unsigned c1,c2; t_size l1,l2; + l1 = utf8_decode_char(elem1,c1); + l2 = utf8_decode_char(elem2,c2); + if (l1==0 && l2==0) return 0; + if (c1!=c2) { + int test = uCharCompare(c1,c2); + if (test) return test; + } + elem1 += l1; + elem2 += l2; + } + } +} + +HINSTANCE SHARED_EXPORT uLoadLibrary(const char * name) +{ + return LoadLibrary(param_os_from_utf8(name)); +} + +HANDLE SHARED_EXPORT uCreateEvent(LPSECURITY_ATTRIBUTES lpEventAttributes,BOOL bManualReset,BOOL bInitialState, const char * lpName) +{ + return CreateEvent(lpEventAttributes,bManualReset,bInitialState, param_os_from_utf8(lpName)); +} + +DWORD SHARED_EXPORT uGetModuleFileName(HMODULE hMod,string_base & out) +{ + try { + pfc::array_t buffer; buffer.set_size(256); + for(;;) { + DWORD ret = GetModuleFileName(hMod,buffer.get_ptr(), (DWORD)buffer.get_size()); + if (ret == 0) return 0; + if (ret < buffer.get_size()) break; + buffer.set_size(buffer.get_size() * 2); + } + out = stringcvt::string_utf8_from_os(buffer.get_ptr(),buffer.get_size()); + return (DWORD) out.length(); + } catch(...) { + return 0; + } +} + +BOOL SHARED_EXPORT uSetClipboardRawData(UINT format,const void * ptr,t_size size) { + try { + HANDLE buffer = GlobalAlloc(GMEM_DDESHARE,size); + if (buffer == NULL) throw std::bad_alloc(); + try { + CGlobalLockScope lock(buffer); + PFC_ASSERT(lock.GetSize() == size); + memcpy(lock.GetPtr(),ptr,size); + } catch(...) { + GlobalFree(buffer); throw; + } + + if (SetClipboardData(format,buffer) == NULL) throw pfc::exception_bug_check(); + return TRUE; + } catch(...) { + return FALSE; + } +} +BOOL SHARED_EXPORT uSetClipboardString(const char * ptr) +{ + try { + CClipboardOpenScope scope; + if (!scope.Open(NULL)) return FALSE; + EmptyClipboard(); + stringcvt::string_os_from_utf8 temp(ptr); + return uSetClipboardRawData( + #ifdef UNICODE + CF_UNICODETEXT + #else + CF_TEXT + #endif + ,temp.get_ptr(), (temp.length() + 1) * sizeof(TCHAR)); + } catch(...) { + return FALSE; + } +} + +BOOL SHARED_EXPORT uGetClipboardString(pfc::string_base & p_out) { + try { + CClipboardOpenScope scope; + if (!scope.Open(NULL)) return FALSE; + HANDLE data = GetClipboardData( + #ifdef UNICODE + CF_UNICODETEXT + #else + CF_TEXT + #endif + ); + if (data == NULL) return FALSE; + + CGlobalLockScope lock(data); + p_out = pfc::stringcvt::string_utf8_from_os( (const TCHAR*) lock.GetPtr(), lock.GetSize() / sizeof(TCHAR) ); + return TRUE; + } catch(...) { + return FALSE; + } +} + + +BOOL SHARED_EXPORT uGetClassName(HWND wnd,string_base & out) +{ + TCHAR temp[512]; + temp[0]=0; + if (GetClassName(wnd,temp,_countof(temp))>0) + { + out = stringcvt::string_utf8_from_os(temp,_countof(temp)); + return TRUE; + } + else return FALSE; +} + +t_size SHARED_EXPORT uCharLength(const char * src) {return utf8_char_len(src);} + +BOOL SHARED_EXPORT uDragQueryFile(HDROP hDrop,UINT idx,string_base & out) +{ + UINT len = DragQueryFile(hDrop,idx,0,0); + if (len>0 && len!=(UINT)(~0)) + { + len++; + array_t temp; + temp.set_size(len); + temp[0] =0 ; + if (DragQueryFile(hDrop,idx,temp.get_ptr(),len)>0) + { + out = stringcvt::string_utf8_from_os(temp.get_ptr(),len); + return TRUE; + } + } + return FALSE; +} + +UINT SHARED_EXPORT uDragQueryFileCount(HDROP hDrop) +{ + return DragQueryFile(hDrop,-1,0,0); +} + + + +BOOL SHARED_EXPORT uGetTextExtentPoint32(HDC dc,const char * text,UINT cb,LPSIZE size) +{ + stringcvt::string_os_from_utf8 temp(text,cb); + return GetTextExtentPoint32(dc,temp,pfc::downcast_guarded(temp.length()),size); +} + +BOOL SHARED_EXPORT uExtTextOut(HDC dc,int x,int y,UINT flags,const RECT * rect,const char * text,UINT cb,const int * lpdx) +{ + stringcvt::string_os_from_utf8 temp(text,cb); + return ExtTextOut(dc,x,y,flags,rect,temp,pfc::downcast_guarded(_tcslen(temp)),lpdx); +} + +static UINT_PTR CALLBACK choose_color_hook(HWND wnd,UINT msg,WPARAM wp,LPARAM lp) +{ + switch(msg) + { + case WM_INITDIALOG: + { + CHOOSECOLOR * cc = reinterpret_cast(lp); + reinterpret_cast(cc->lCustData)->initialize(FindOwningPopup(wnd)); + } + return 0; + default: + return 0; + } +} + +BOOL SHARED_EXPORT uChooseColor(DWORD * p_color,HWND parent,DWORD * p_custom_colors) +{ + modal_dialog_scope scope; + + CHOOSECOLOR cc = {}; + cc.lStructSize = sizeof(cc); + cc.hwndOwner = parent; + cc.rgbResult = *p_color; + cc.lpCustColors = p_custom_colors; + cc.Flags = CC_ANYCOLOR|CC_FULLOPEN|CC_RGBINIT|CC_ENABLEHOOK; + cc.lpfnHook = choose_color_hook; + cc.lCustData = reinterpret_cast(&scope); + BOOL rv = ChooseColor(&cc); + if (rv) + { + *p_color = cc.rgbResult; + return TRUE; + } + else return FALSE; +} + +HCURSOR SHARED_EXPORT uLoadCursor(HINSTANCE hIns,const char * name) +{ + return LoadCursor(hIns,param_os_from_utf8(name)); +} + +HICON SHARED_EXPORT uLoadIcon(HINSTANCE hIns,const char * name) +{ + return LoadIcon(hIns,param_os_from_utf8(name)); +} + +HMENU SHARED_EXPORT uLoadMenu(HINSTANCE hIns,const char * name) +{ + return LoadMenu(hIns,param_os_from_utf8(name)); +} + + + +BOOL SHARED_EXPORT uGetEnvironmentVariable(const char * name,string_base & out) +{ + stringcvt::string_os_from_utf8 name_t(name); + DWORD size = GetEnvironmentVariable(name_t,0,0); + if (size>0) + { + size++; + array_t temp; + temp.set_size(size); + temp[0]=0; + if (GetEnvironmentVariable(name_t,temp.get_ptr(),size)>0) + { + out = stringcvt::string_utf8_from_os(temp.get_ptr(),size); + return TRUE; + } + } + return FALSE; +} + +HMODULE SHARED_EXPORT uGetModuleHandle(const char * name) +{ + return GetModuleHandle(param_os_from_utf8(name)); +} + +UINT SHARED_EXPORT uRegisterWindowMessage(const char * name) +{ + return RegisterWindowMessage(stringcvt::string_os_from_utf8(name)); +} + +BOOL SHARED_EXPORT uMoveFile(const char * src,const char * dst) +{ + return MoveFile(stringcvt::string_os_from_utf8(src),stringcvt::string_os_from_utf8(dst)); +} + +BOOL SHARED_EXPORT uDeleteFile(const char * fn) +{ + return DeleteFile(stringcvt::string_os_from_utf8(fn)); +} + +DWORD SHARED_EXPORT uGetFileAttributes(const char * fn) +{ + PFC_ASSERT( ! pfc::string_has_prefix_i( fn, "file://" ) ); + return GetFileAttributes(stringcvt::string_os_from_utf8(fn)); +} + +BOOL SHARED_EXPORT uRemoveDirectory(const char * fn) +{ + return RemoveDirectory(stringcvt::string_os_from_utf8(fn)); +} + +HANDLE SHARED_EXPORT uCreateFile(const char * fn,DWORD access,DWORD share,LPSECURITY_ATTRIBUTES blah,DWORD creat,DWORD flags,HANDLE tmpl) +{ + return CreateFile(stringcvt::string_os_from_utf8(fn),access,share,blah,creat,flags,tmpl); +} + +BOOL SHARED_EXPORT uCreateDirectory(const char * fn,LPSECURITY_ATTRIBUTES blah) +{ + return CreateDirectory(stringcvt::string_os_from_utf8(fn),blah); +} + +HANDLE SHARED_EXPORT uCreateMutex(LPSECURITY_ATTRIBUTES blah,BOOL bInitialOwner,const char * name) +{ + return name ? CreateMutex(blah,bInitialOwner,stringcvt::string_os_from_utf8(name)) : CreateMutex(blah,bInitialOwner,0); +} + +BOOL SHARED_EXPORT uGetFullPathName(const char * name,string_base & out) +{ + stringcvt::string_os_from_utf8 name_os(name); + unsigned len = GetFullPathName(name_os,0,0,0); + if (len==0) return FALSE; + array_t temp; + temp.set_size(len+1); + TCHAR * blah; + if (GetFullPathName(name_os,len+1,temp.get_ptr(),&blah)==0) return FALSE; + out = stringcvt::string_utf8_from_os(temp.get_ptr(),len); + return TRUE; +} + +BOOL SHARED_EXPORT uGetLongPathName(const char * name,string_base & out) +{ + TCHAR temp[4096]; + temp[0]=0; + BOOL state = GetLongPathName(stringcvt::string_os_from_utf8(name),temp,_countof(temp)); + if (state) out = stringcvt::string_utf8_from_os(temp,_countof(temp)); + return state; +} + +void SHARED_EXPORT uGetCommandLine(string_base & out) +{ + out = stringcvt::string_utf8_from_os(GetCommandLine()); +} + +BOOL SHARED_EXPORT uGetTempPath(string_base & out) +{ + TCHAR temp[MAX_PATH+1]; + temp[0]=0; + if (GetTempPath(_countof(temp),temp)) + { + out = stringcvt::string_utf8_from_os(temp,_countof(temp)); + return TRUE; + } + return FALSE; + +} +BOOL SHARED_EXPORT uGetTempFileName(const char * path_name,const char * prefix,UINT unique,string_base & out) +{ + if (path_name==0 || prefix==0) return FALSE; + TCHAR temp[MAX_PATH+1]; + temp[0]=0; + if (GetTempFileName(stringcvt::string_os_from_utf8(path_name),stringcvt::string_os_from_utf8(prefix),unique,temp)) + { + out = stringcvt::string_utf8_from_os(temp,_countof(temp)); + return TRUE; + } + return FALSE; +} + +class uFindFile_i : public uFindFile +{ + string8 fn; + WIN32_FIND_DATA fd; + HANDLE hFF; +public: + uFindFile_i() {hFF = INVALID_HANDLE_VALUE;} + bool FindFirst(const char * path) + { + hFF = FindFirstFile(stringcvt::string_os_from_utf8(path),&fd); + if (hFF==INVALID_HANDLE_VALUE) return false; + fn = stringcvt::string_utf8_from_os(fd.cFileName,_countof(fd.cFileName)); + return true; + } + virtual BOOL FindNext() + { + if (hFF==INVALID_HANDLE_VALUE) return FALSE; + BOOL rv = FindNextFile(hFF,&fd); + if (rv) fn = stringcvt::string_utf8_from_os(fd.cFileName,_countof(fd.cFileName)); + return rv; + } + + virtual const char * GetFileName() + { + return fn; + } + + virtual t_uint64 GetFileSize() + { + union + { + t_uint64 val64; + struct + { + DWORD lo,hi; + }; + } ret; + + ret.hi = fd.nFileSizeHigh; + ret.lo = fd.nFileSizeLow; + return ret.val64; + + } + virtual DWORD GetAttributes() + { + return fd.dwFileAttributes; + } + + virtual FILETIME GetCreationTime() + { + return fd.ftCreationTime; + } + virtual FILETIME GetLastAccessTime() + { + return fd.ftLastAccessTime; + } + virtual FILETIME GetLastWriteTime() + { + return fd.ftLastWriteTime; + } + virtual ~uFindFile_i() + { + if (hFF!=INVALID_HANDLE_VALUE) FindClose(hFF); + } +}; + +puFindFile SHARED_EXPORT uFindFirstFile(const char * path) +{ + pfc::ptrholder_t ptr = new uFindFile_i; + if (!ptr->FindFirst(path)) { + ptr.release(); + return NULL; + } else { + return ptr.detach(); + } +} + +HINSTANCE SHARED_EXPORT uShellExecute(HWND wnd,const char * oper,const char * file,const char * params,const char * dir,int cmd) +{ + modal_dialog_scope modal; // IDIOCY - ShellExecute may spawn a modal dialog + if (wnd) modal.initialize(wnd); + return ShellExecute(wnd,param_os_from_utf8(oper),param_os_from_utf8(file),param_os_from_utf8(params),param_os_from_utf8(dir),cmd); +} + +HWND SHARED_EXPORT uCreateStatusWindow(LONG style,const char * text,HWND parent,UINT id) +{ + return CreateStatusWindow(style,param_os_from_utf8(text),parent,id); +} + +HWND SHARED_EXPORT uCreateWindowEx(DWORD dwExStyle,const char * lpClassName,const char * lpWindowName,DWORD dwStyle,int x,int y,int nWidth,int nHeight,HWND hWndParent,HMENU hMenu,HINSTANCE hInstance,LPVOID lpParam) +{ + return CreateWindowEx(dwExStyle,param_os_from_utf8(lpClassName),param_os_from_utf8(lpWindowName),dwStyle,x,y,nWidth,nHeight,hWndParent,hMenu,hInstance,lpParam); +} + +HANDLE SHARED_EXPORT uLoadImage(HINSTANCE hIns,const char * name,UINT type,int x,int y,UINT flags) +{ + return LoadImage(hIns,param_os_from_utf8(name),type,x,y,flags); +} + +BOOL SHARED_EXPORT uGetSystemDirectory(string_base & out) +{ + UINT len = GetSystemDirectory(0,0); + if (len==0) len = MAX_PATH; + len++; + array_t temp; + temp.set_size(len); + if (GetSystemDirectory(temp.get_ptr(),len)==0) return FALSE; + out = stringcvt::string_utf8_from_os(temp.get_ptr(),len); + return TRUE; +} + +BOOL SHARED_EXPORT uGetWindowsDirectory(string_base & out) +{ + UINT len = GetWindowsDirectory(0,0); + if (len==0) len = MAX_PATH; + len++; + array_t temp; + temp.set_size(len); + if (GetWindowsDirectory(temp.get_ptr(),len)==0) return FALSE; + out = stringcvt::string_utf8_from_os(temp.get_ptr(),len); + return TRUE; +} + +BOOL SHARED_EXPORT uSetCurrentDirectory(const char * path) +{ + return SetCurrentDirectory(stringcvt::string_os_from_utf8(path)); +} + +BOOL SHARED_EXPORT uGetCurrentDirectory(string_base & out) +{ + UINT len = GetCurrentDirectory(0,0); + if (len==0) len = MAX_PATH; + len++; + array_t temp; + temp.set_size(len); + if (GetCurrentDirectory(len,temp.get_ptr())==0) return FALSE; + out = stringcvt::string_utf8_from_os(temp.get_ptr(),len); + return TRUE; +} + +BOOL SHARED_EXPORT uExpandEnvironmentStrings(const char * src,string_base & out) +{ + stringcvt::string_os_from_utf8 src_os(src); + UINT len = ExpandEnvironmentStrings(src_os,0,0); + if (len==0) len = 256; + len++; + array_t temp; + temp.set_size(len); + if (ExpandEnvironmentStrings(src_os,temp.get_ptr(),len)==0) return FALSE; + out = stringcvt::string_utf8_from_os(temp.get_ptr(),len); + return TRUE; +} + +BOOL SHARED_EXPORT uGetUserName(string_base & out) +{ + TCHAR temp[UNLEN+1]; + DWORD len = _countof(temp); + if (GetUserName(temp,&len)) + { + out = stringcvt::string_utf8_from_os(temp,_countof(temp)); + return TRUE; + } + else return FALSE; +} + +BOOL SHARED_EXPORT uGetShortPathName(const char * src,string_base & out) +{ + stringcvt::string_os_from_utf8 src_os(src); + UINT len = GetShortPathName(src_os,0,0); + if (len==0) len = MAX_PATH; + len++; + array_t temp; temp.set_size(len); + if (GetShortPathName(src_os,temp.get_ptr(),len)) + { + out = stringcvt::string_utf8_from_os(temp.get_ptr(),len); + return TRUE; + } + else return FALSE; +} + + +#ifdef UNICODE +#define DDE_CODEPAGE CP_WINUNICODE +#else +#define DDE_CODEPAGE CP_WINANSI +#endif + + +HSZ SHARED_EXPORT uDdeCreateStringHandle(DWORD ins,const char * src) +{ + return DdeCreateStringHandle(ins,stringcvt::string_os_from_utf8(src),DDE_CODEPAGE); +} + +BOOL SHARED_EXPORT uDdeQueryString(DWORD ins,HSZ hsz,string_base & out) +{ + array_t temp; + UINT len = DdeQueryString(ins,hsz,0,0,DDE_CODEPAGE); + if (len==0) len = MAX_PATH; + len++; + temp.set_size(len); + if (DdeQueryString(ins,hsz,temp.get_ptr(),len,DDE_CODEPAGE)) + { + out = stringcvt::string_utf8_from_os(temp.get_ptr(),len); + return TRUE; + } + else return FALSE; +} + +UINT SHARED_EXPORT uDdeInitialize(LPDWORD pidInst,PFNCALLBACK pfnCallback,DWORD afCmd,DWORD ulRes) +{ + return DdeInitialize(pidInst,pfnCallback,afCmd,ulRes); +} + +BOOL SHARED_EXPORT uDdeAccessData_Text(HDDEDATA data,string_base & out) +{ + const TCHAR * ptr = (const TCHAR*) DdeAccessData(data,0); + if (ptr) + { + out = stringcvt::string_utf8_from_os(ptr); + return TRUE; + } + else return FALSE; +} + +uSortString_t SHARED_EXPORT uSortStringCreate(const char * src) { + t_size lenEst = pfc::stringcvt::estimate_utf8_to_wide(src,SIZE_MAX); + TCHAR * ret = pfc::__raw_malloc_t(lenEst); + pfc::stringcvt::convert_utf8_to_wide(ret,lenEst,src,SIZE_MAX); + return reinterpret_cast( ret ); +} + +int SHARED_EXPORT uSortStringCompareEx(uSortString_t string1, uSortString_t string2,uint32_t flags) { + return CompareString(LOCALE_USER_DEFAULT,flags,reinterpret_cast(string1),-1,reinterpret_cast(string2),-1); +} + +int SHARED_EXPORT uSortStringCompare(uSortString_t string1, uSortString_t string2) { + return lstrcmpi(reinterpret_cast(string1),reinterpret_cast(string2)); +} + +void SHARED_EXPORT uSortStringFree(uSortString_t string) { + pfc::__raw_free_t(reinterpret_cast(string)); +} + +HTREEITEM SHARED_EXPORT uTreeView_InsertItem(HWND wnd,const uTVINSERTSTRUCT * param) +{ + stringcvt::string_os_from_utf8 temp; + temp.convert(param->item.pszText); + + + TVINSERTSTRUCT l_param = {}; + l_param.hParent = param->hParent; + l_param.hInsertAfter = param->hInsertAfter; + l_param.item.mask = param->item.mask; + l_param.item.hItem = param->item.hItem; + l_param.item.state = param->item.state; + l_param.item.stateMask = param->item.stateMask; + l_param.item.pszText = const_cast(temp.get_ptr()); + l_param.item.cchTextMax = 0; + l_param.item.iImage = param->item.iImage; + l_param.item.iSelectedImage = param->item.iImage; + l_param.item.cChildren = param->item.cChildren; + l_param.item.lParam = param->item.lParam; + if (param->item.mask & TVIF_INTEGRAL) + { + l_param.itemex.iIntegral = param->itemex.iIntegral; + } + + return (HTREEITEM) uSendMessage(wnd,TVM_INSERTITEM,0,(LPARAM)&l_param); +} + +UINT SHARED_EXPORT uGetFontHeight(HFONT font) +{ + UINT ret; + HDC dc = CreateCompatibleDC(0); + SelectObject(dc,font); + ret = uGetTextHeight(dc); + DeleteDC(dc); + return ret; +} + + +HIMAGELIST SHARED_EXPORT uImageList_LoadImage(HINSTANCE hi, const char * lpbmp, int cx, int cGrow, COLORREF crMask, UINT uType, UINT uFlags) +{ + return ImageList_LoadImage(hi,param_os_from_utf8(lpbmp),cx,cGrow,crMask,uType,uFlags); +} + +int SHARED_EXPORT uTabCtrl_InsertItem(HWND wnd,t_size idx,const uTCITEM * item) +{ + param_os_from_utf8 text((item->mask & TCIF_TEXT) ? item->pszText : 0); + TCITEM l_item; + assert(sizeof(l_item)==sizeof(*item));//meh lazy + memcpy(&l_item,item,sizeof(l_item)); + l_item.pszText = const_cast(text.get_ptr()); + l_item.cchTextMax = 0; + return TabCtrl_InsertItem(wnd,idx,&l_item); +} + +int SHARED_EXPORT uTabCtrl_SetItem(HWND wnd,t_size idx,const uTCITEM * item) +{ + param_os_from_utf8 text((item->mask & TCIF_TEXT) ? item->pszText : 0); + TCITEM l_item; + PFC_STATIC_ASSERT(sizeof(l_item)==sizeof(*item));//meh lazy + memcpy(&l_item,item,sizeof(l_item)); + l_item.pszText = const_cast(text.get_ptr()); + l_item.cchTextMax = 0; + return TabCtrl_SetItem(wnd,idx,&l_item); +} + +int SHARED_EXPORT uGetKeyNameText(LONG lparam,string_base & out) +{ + TCHAR temp[256]; + temp[0]=0; + if (!GetKeyNameText(lparam,temp,_countof(temp))) return 0; + out = stringcvt::string_utf8_from_os(temp,_countof(temp)); + return 1; +} + +HANDLE SHARED_EXPORT uCreateFileMapping(HANDLE hFile,LPSECURITY_ATTRIBUTES lpFileMappingAttributes,DWORD flProtect,DWORD dwMaximumSizeHigh,DWORD dwMaximumSizeLow,const char * lpName) +{ + return CreateFileMapping(hFile,lpFileMappingAttributes,flProtect,dwMaximumSizeHigh,dwMaximumSizeLow,param_os_from_utf8(lpName)); +} + +BOOL SHARED_EXPORT uListBox_GetText(HWND listbox,UINT index,string_base & out) +{ + t_size len = uSendMessage(listbox,LB_GETTEXTLEN,index,0); + if (len==LB_ERR || len>16*1024*1024) return FALSE; + if (len==0) {out.reset();return TRUE;} + + array_t temp; temp.set_size(len+1); + pfc::memset_t(temp,(TCHAR)0); + len = uSendMessage(listbox,LB_GETTEXT,index,(LPARAM)temp.get_ptr()); + if (len==LB_ERR) return false; + out = stringcvt::string_utf8_from_os(temp.get_ptr()); + return TRUE; +} +/* +void SHARED_EXPORT uPrintf(string_base & out,const char * fmt,...) +{ + va_list list; + va_start(list,fmt); + uPrintfV(out,fmt,list); + va_end(list); +} +*/ +void SHARED_EXPORT uPrintfV(string_base & out,const char * fmt,va_list arglist) +{ + pfc::string_printf_here_va(out, fmt, arglist); +} + +int SHARED_EXPORT uCompareString(DWORD flags,const char * str1,size_t len1,const char * str2,size_t len2) +{ + return CompareString(LOCALE_USER_DEFAULT,flags,stringcvt::string_os_from_utf8(str1,len1),-1,stringcvt::string_os_from_utf8(str2,len2),-1); +} + +class uResource_i : public uResource +{ + unsigned size; + const void * ptr; +public: + inline uResource_i(const void * p_ptr,unsigned p_size) : ptr(p_ptr), size(p_size) + { + } + virtual const void * GetPointer() + { + return ptr; + } + virtual unsigned GetSize() + { + return size; + } + virtual ~uResource_i() + { + } +}; + +puResource SHARED_EXPORT uLoadResource(HMODULE hMod,const char * name,const char * type,WORD wLang) +{ + HRSRC res = uFindResource(hMod,name,type,wLang); + if (res==0) return 0; + HGLOBAL hglob = LoadResource(hMod,res); + if (hglob) + { + void * ptr = LockResource(hglob); + if (ptr) + { + return new uResource_i(ptr,SizeofResource(hMod,res)); + } + else return 0; + } + else return 0; +} + +puResource SHARED_EXPORT LoadResourceEx(HMODULE hMod,const TCHAR * name,const TCHAR * type,WORD wLang) +{ + HRSRC res = wLang ? FindResourceEx(hMod,type,name,wLang) : FindResource(hMod,name,type); + if (res==0) return 0; + HGLOBAL hglob = LoadResource(hMod,res); + if (hglob) + { + void * ptr = LockResource(hglob); + if (ptr) + { + return new uResource_i(ptr,SizeofResource(hMod,res)); + } + else return 0; + } + else return 0; +} + +HRSRC SHARED_EXPORT uFindResource(HMODULE hMod,const char * name,const char * type,WORD wLang) +{ + return wLang ? FindResourceEx(hMod,param_os_from_utf8(type),param_os_from_utf8(name),wLang) : FindResource(hMod,param_os_from_utf8(name),param_os_from_utf8(type)); +} + +BOOL SHARED_EXPORT uLoadString(HINSTANCE ins,UINT id,string_base & out) +{ + BOOL rv = FALSE; + uResource * res = uLoadResource(ins,uMAKEINTRESOURCE(id),(const char*)(RT_STRING)); + if (res) + { + unsigned size = res->GetSize(); + const WCHAR * ptr = (const WCHAR*)res->GetPointer(); + if (size>=4) + { + unsigned len = *(const WORD*)(ptr+1); + if (len * 2 + 4 <= size) + { + out = stringcvt::string_utf8_from_wide(ptr+2,len); + } + } + + delete res; + rv = TRUE; + } + return rv; +} + +BOOL SHARED_EXPORT uGetMenuString(HMENU menu,UINT id,string_base & out,UINT flag) +{ + unsigned len = GetMenuString(menu,id,0,0,flag); + if (len==0) + { + out.reset(); + return FALSE; + } + array_t temp; + temp.set_size(len+1); + if (GetMenuString(menu,id,temp.get_ptr(),len+1,flag)==0) { + out.reset(); + return FALSE; + } + out = stringcvt::string_utf8_from_os(temp.get_ptr()); + return TRUE; +} + +BOOL SHARED_EXPORT uModifyMenu(HMENU menu,UINT id,UINT flags,UINT newitem,const char * data) +{ + return ModifyMenu(menu,id,flags,newitem,param_os_from_utf8(data)); +} + +UINT SHARED_EXPORT uGetMenuItemType(HMENU menu,UINT position) +{ + MENUITEMINFO info = {}; + info.cbSize = sizeof(info); + info.fMask = MIIM_TYPE; + if (!GetMenuItemInfo(menu,position,TRUE,&info)) + return 0; + return info.fType; +} + +static inline bool i_is_path_separator(unsigned c) +{ + return c=='\\' || c=='/' || c=='|' || c==':'; +} + +int SHARED_EXPORT uSortPathCompare(HANDLE string1,HANDLE string2) +{ + const TCHAR * s1 = reinterpret_cast(string1); + const TCHAR * s2 = reinterpret_cast(string2); + const TCHAR * p1, * p2; + + while (*s1 || *s2) + { + if (*s1 == *s2) + { + s1++; + s2++; + continue; + } + + p1 = s1; while (*p1 && !i_is_path_separator(*p1)) p1++; + p2 = s2; while (*p2 && !i_is_path_separator(*p2)) p2++; + + if ((!*p1 && !*p2) || (*p1 && *p2)) + { + int test = CompareString(LOCALE_USER_DEFAULT, NORM_IGNORECASE | NORM_IGNOREKANATYPE | NORM_IGNOREWIDTH, s1, pfc::downcast_guarded(p1 - s1), s2, pfc::downcast_guarded(p2 - s2)); + if (test && test != 2) return test - 2; + if (!*p1) return 0; + } + else + { + if (*p1) return -1; + else return 1; + } + + s1 = p1 + 1; + s2 = p2 + 1; + } + + return 0; +} + +UINT SHARED_EXPORT uRegisterClipboardFormat(const char * name) +{ + return RegisterClipboardFormat(stringcvt::string_os_from_utf8(name)); +} + +BOOL SHARED_EXPORT uGetClipboardFormatName(UINT format,string_base & out) +{ + TCHAR temp[1024]; + if (!GetClipboardFormatName(format,temp,_countof(temp))) return FALSE; + out = stringcvt::string_utf8_from_os(temp,_countof(temp)); + return TRUE; +} + +}//extern "C" + +BOOL SHARED_EXPORT uSearchPath(const char * path, const char * filename, const char * extension, string_base & p_out) +{ + enum {temp_size = 1024}; + param_os_from_utf8 path_os(path), filename_os(filename), extension_os(extension); + array_t temp; temp.set_size(temp_size); + LPTSTR dummy; + unsigned len; + + len = SearchPath(path_os,filename_os,extension_os,temp_size,temp.get_ptr(),&dummy); + if (len == 0) return FALSE; + if (len >= temp_size) + { + unsigned len2; + temp.set_size(len + 1); + len2 = SearchPath(path_os,filename_os,extension_os,len+1,temp.get_ptr(),&dummy); + if (len2 == 0 || len2 > len) return FALSE; + len = len2; + } + + p_out = stringcvt::string_utf8_from_os(temp.get_ptr(),len); + + return TRUE; + +} + +static bool is_ascii_alpha(char c) +{ + return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); +} + +static char ascii_upper(char c) +{ + if (c >= 'a' && c <= 'z') c += 'A' - 'a'; + return c; +} + +static BOOL uFixPathCaps_Internal(const char * path,string_base & p_out, bool bQuick) { + pfc::string8_fastalloc temp, prependbuffer; + if (path[0] == '\\' && path[1] == '\\') + { + unsigned index = 2; + while(path[index] != '\\') + { + if (path[index] == 0) return FALSE; + index++; + } + index++; + if (path[index] == '\\' || path[index] == 0) return FALSE; + while(path[index] != '\\') + { + if (path[index] == 0) { + // \\host\share + uStringLower(p_out,path); + return TRUE; + } + index++; + } + index++; + if (path[index] == '\\') return FALSE; + uAddStringLower(temp,path,index); + path += index; + } + else if (is_ascii_alpha(path[0]) && path[1] == ':' && path[2] == '\\') + { + temp.add_char(ascii_upper(path[0])); + temp.add_string(":\\"); + path += 3; + } + else return FALSE; + + for(;;) + { + t_size truncat = temp.length(); + t_size delta = 0; + while(path[delta]!=0 && path[delta]!='\\') delta++; + if (delta == 0) break; + temp.add_string_nc(path,delta); + + bool found = false; + if (!bQuick) { +#ifdef UNICODE + pfc::winPrefixPath( prependbuffer, temp ); + pfc::ptrholder_t ff = uFindFirstFile(prependbuffer); +#else + pfc::ptrholder_t ff = uFindFirstFile(temp); +#endif + if (ff.is_valid()) { + do { + const char * fn = ff->GetFileName(); + if (!stricmp_utf8_ex(path,delta,fn,strlen(fn))) + { + found = true; + temp.truncate(truncat); + temp.add_string(fn); + break; + } + } while(ff->FindNext()); + } + } + if (!found) + { + temp.add_string(path + delta); + break; + } + path += delta; + if (*path == 0) break; + path ++; + temp.add_char('\\'); + } + + + p_out = temp; + + return TRUE; +} +/*BOOL SHARED_EXPORT uFixPathCapsQuick(const char * path,string_base & p_out) { + return uFixPathCaps_Internal(path, p_out, true); +}*/ +BOOL SHARED_EXPORT uFixPathCaps(const char * path,string_base & p_out) { + return uFixPathCaps_Internal(path, p_out, false); +} + +LPARAM SHARED_EXPORT uTreeView_GetUserData(HWND p_tree,HTREEITEM p_item) +{ + TVITEM item = {}; + item.mask = TVIF_PARAM; + item.hItem = p_item; + if (uSendMessage(p_tree,TVM_GETITEM,0,(LPARAM)&item)) + return item.lParam; + return 0; +} + +bool SHARED_EXPORT uTreeView_GetText(HWND p_tree,HTREEITEM p_item,string_base & p_out) +{ + TCHAR temp[1024];//changeme ? + TVITEM item = {}; + item.mask = TVIF_TEXT; + item.hItem = p_item; + item.pszText = temp; + item.cchTextMax = _countof(temp); + if (uSendMessage(p_tree,TVM_GETITEM,0,(LPARAM)&item)) + { + p_out = stringcvt::string_utf8_from_os(temp,_countof(temp)); + return true; + } + else return false; +} + +BOOL SHARED_EXPORT uSetWindowText(HWND wnd,const char * p_text) +{ + PFC_ASSERT( wnd != NULL ); + return SetWindowText(wnd,stringcvt::string_os_from_utf8(p_text)); +} + +BOOL SHARED_EXPORT uSetDlgItemText(HWND wnd,UINT id,const char * p_text) +{ + PFC_ASSERT( wnd != NULL ); + return SetDlgItemText(wnd, id, stringcvt::string_os_from_utf8(p_text)); +} + +BOOL SHARED_EXPORT uFileExists(const char * fn) +{ + DWORD attrib = uGetFileAttributes(fn); + if (attrib == 0xFFFFFFFF || (attrib & FILE_ATTRIBUTE_DIRECTORY)) return FALSE; + return TRUE; +} + +BOOL SHARED_EXPORT uFormatSystemErrorMessage(string_base & p_out,DWORD p_code) { + return pfc::winFormatSystemErrorMessage(p_out, p_code); +} + +HMODULE SHARED_EXPORT LoadSystemLibrary(const TCHAR * name) { + pfc::array_t buffer; buffer.set_size( MAX_PATH + _tcslen(name) + 2 ); + TCHAR * bufptr = buffer.get_ptr(); + if (GetSystemDirectory(bufptr, MAX_PATH) == 0) return NULL; + bufptr[MAX_PATH] = 0; + + size_t idx = _tcslen(bufptr); + if (idx > 0 && bufptr[idx-1] != '\\') bufptr[idx++] = '\\'; + + pfc::strcpy_t(bufptr+idx, name); + + return LoadLibrary(bufptr); +} \ No newline at end of file diff --git a/3rdparty/foo_SDK/libPPUI/CDialogResizeHelper.h b/3rdparty/foo_SDK/libPPUI/CDialogResizeHelper.h index 91932e29..1fe80d05 100644 --- a/3rdparty/foo_SDK/libPPUI/CDialogResizeHelper.h +++ b/3rdparty/foo_SDK/libPPUI/CDialogResizeHelper.h @@ -3,6 +3,17 @@ #include "CDialogResizeHelperCompat.h" #include +// ========================================================== +// CDialogResizeHelper +// ========================================================== +// Usage: +// Put CDialogResizeHelper member in your dialog class +// Initialize with controls sizing info table, array of CDialogResizeHelper::Param +// Put CHAIN_MSG_MAP_MEMBER(m_resizer) before your dialog message handlers +// CDialogResizeHelper will do its own message handling without marking messages as handled, that is, your handlers of the same messages will be allowed to run. +// CRect minMaxRange specifies allowed size min (left&top) and max (right&bottom) values, in DLU not pixels. +// ========================================================== + class CDialogResizeHelper : public CMessageMap { public: diff --git a/3rdparty/foo_SDK/libPPUI/CEditWithButtons.cpp b/3rdparty/foo_SDK/libPPUI/CEditWithButtons.cpp index bd6d7280..d119e5c3 100644 --- a/3rdparty/foo_SDK/libPPUI/CEditWithButtons.cpp +++ b/3rdparty/foo_SDK/libPPUI/CEditWithButtons.cpp @@ -171,7 +171,26 @@ void CEditWithButtons::Layout(CSize size, CFontHandle fontSetMe) { } unsigned CEditWithButtons::MeasureButton(Button_t const & button) { + if (m_fixedWidthAuto && m_fixedWidth == 0) { + CWindowDC dc(*this); + SelectObjectScope fontScope(dc, GetFont()); + SIZE sz = {}; + WIN32_OP_D( dc.GetTextExtent(L"#", 1, &sz) ); + m_fixedWidth = MulDiv(sz.cx, 3, 2); + } if (m_fixedWidth != 0) return m_fixedWidth; return button.wnd.Measure(); } + +void CEditWithButtons::OnSetFont(CFontHandle font, BOOL bRedraw) { + (void)bRedraw; + + if ( m_fixedWidthAuto ) m_fixedWidth = 0; // require re-calculation + + DefWindowProc(); + CRect rc; + if (GetClientRect(&rc)) { + Layout(rc.Size(), font); + } +} diff --git a/3rdparty/foo_SDK/libPPUI/CEditWithButtons.h b/3rdparty/foo_SDK/libPPUI/CEditWithButtons.h index c2df276d..1646bd7f 100644 --- a/3rdparty/foo_SDK/libPPUI/CEditWithButtons.h +++ b/3rdparty/foo_SDK/libPPUI/CEditWithButtons.h @@ -47,9 +47,12 @@ class CEditWithButtons : public CEditPPHooks { void AddClearButton( const wchar_t * clearVal = L"", bool bHandleEsc = false); void AddButton( const wchar_t * str, handler_t handler, condition_t condition = nullptr, const wchar_t * drawAlternateText = nullptr ); - static unsigned DefaultFixedWidth() {return GetSystemMetrics(SM_CXVSCROLL) * 3 / 4;} - void SetFixedWidth(unsigned fw = DefaultFixedWidth() ) { - m_fixedWidth = fw; + void SetFixedWidth(unsigned fw) { + m_fixedWidth = fw; m_fixedWidthAuto = false; + RefreshButtons(); + } + void SetFixedWidth() { + m_fixedWidth = 0; m_fixedWidthAuto = true; RefreshButtons(); } CRect RectOfButton( const wchar_t * text ); @@ -168,14 +171,8 @@ class CEditWithButtons : public CEditPPHooks { bool visible; condition_t condition; }; - void OnSetFont(CFontHandle font, BOOL bRedraw) { - (void)bRedraw; - CRect rc; - if (GetClientRect(&rc)) { - Layout(rc.Size(), font); - } - SetMsgHandled(FALSE); - } + + void OnSetFont(CFontHandle font, BOOL bRedraw); void RefreshButtons() { if ( m_hWnd != NULL && m_buttons.size() > 0 ) { @@ -208,6 +205,7 @@ class CEditWithButtons : public CEditPPHooks { unsigned MeasureButton(Button_t const & button ); unsigned m_fixedWidth = 0; + bool m_fixedWidthAuto = false; std::list< Button_t > m_buttons; bool m_hasAutoComplete = false; }; diff --git a/3rdparty/foo_SDK/libPPUI/CListAccessible.cpp b/3rdparty/foo_SDK/libPPUI/CListAccessible.cpp index 17bf374a..93a20e6a 100644 --- a/3rdparty/foo_SDK/libPPUI/CListAccessible.cpp +++ b/3rdparty/foo_SDK/libPPUI/CListAccessible.cpp @@ -146,8 +146,8 @@ void CListAccessible::AccCleanup() { } LRESULT CListAccessible::AccGetObject(WPARAM wp,LPARAM lp) { - const WPARAM dwFlags = wp; - const LPARAM dwObjId = lp; + const auto dwFlags = (DWORD) wp; + const auto dwObjId = (DWORD) lp; if (dwObjId == OBJID_CLIENT) { diff --git a/3rdparty/foo_SDK/libPPUI/CListControl.cpp b/3rdparty/foo_SDK/libPPUI/CListControl.cpp index 76850b74..1efe02a2 100644 --- a/3rdparty/foo_SDK/libPPUI/CListControl.cpp +++ b/3rdparty/foo_SDK/libPPUI/CListControl.cpp @@ -518,7 +518,7 @@ void CListControlImpl::MinGroupHeight2ChangedForGroup(groupID_t groupID, bool re void CListControlImpl::UpdateGroupOverlayByID(groupID_t groupID, int xFrom, int xTo) { t_size base, count; if (GetItemRangeAbs(GetVisibleRectAbs(), base, count)) { - bool on = false; // Have to walk whole range - there may be multiple groups with the same ID because fuck you + bool on = false; // Have to walk whole range - there may be multiple groups with the same ID for (size_t walk = 0; walk < count; ++walk) { bool test = (groupID == GetItemGroup(base + walk)); if (test && !on) { @@ -574,40 +574,44 @@ bool CListControlImpl::PrepLayoutCache(CPoint& ptOrigin, size_t indexLo, size_t #if PrepLayoutCache_Debug PFC_DEBUGLOG << "PrepLayoutCache entry"; PFC_DEBUGLOG << "PrepLayoutCache: count=" << count << " knownGroups=" << this->m_groupHeaders.size(); - PFC_DEBUGLOG << "PrepLayoutCache: indexLo=" << indexLo << " indexHi=" << indexHi; + PFC_DEBUGLOG << "PrepLayoutCache: indexLo=" << pfc::format_index(indexLo) << " indexHi=" << pfc::format_index(indexHi); #endif const int clientHeight = pfc::max_t(this->GetClientRectHook().Height(), 100); // Always walk 2*clientHeight, with area above and below int yMax = -1, yBase = 0; size_t baseItem = 0, endItem = SIZE_MAX; - if (indexLo == SIZE_MAX) { - yBase = pfc::max_t(ptOrigin.y - clientHeight / 2, 0); - yMax = yBase + clientHeight * 2; - baseItem = pfc::min_t(this->IndexFromPointAbs(yBase), count - 1); - } else { - auto itemHeight = GetItemHeight(); - size_t extraItems = (size_t)(clientHeight / itemHeight); + + if (!m_greedyGroupLayout) { + if (indexLo == SIZE_MAX) { + yBase = pfc::max_t(ptOrigin.y - clientHeight / 2, 0); + yMax = yBase + clientHeight * 2; + baseItem = pfc::min_t(this->IndexFromPointAbs(yBase), count - 1); + } else { + auto itemHeight = GetItemHeight(); + size_t extraItems = (size_t)(clientHeight / itemHeight); #if PrepLayoutCache_Debug - PFC_DEBUGLOG << "PrepLayoutCache: clientHeight=" << clientHeight << " itemHeight=" << itemHeight << " extraItems=" << extraItems; + PFC_DEBUGLOG << "PrepLayoutCache: clientHeight=" << clientHeight << " itemHeight=" << itemHeight << " extraItems=" << extraItems; #endif - if (indexLo < extraItems) baseItem = 0; - else baseItem = indexLo - extraItems; + if (indexLo < extraItems) baseItem = 0; + else baseItem = indexLo - extraItems; - if (indexHi == SIZE_MAX) { - endItem = baseItem + extraItems; - } else { - endItem = indexHi + extraItems; - } - if (endItem > count) endItem = count; + if (indexHi == SIZE_MAX) { + endItem = baseItem + extraItems; + } else { + endItem = indexHi + extraItems; + } + if (endItem > count) endItem = count; #if PrepLayoutCache_Debug - PFC_DEBUGLOG << "PrepLayoutCache: baseItem=" << baseItem << " endItem=" << endItem; + PFC_DEBUGLOG << "PrepLayoutCache: baseItem=" << baseItem << " endItem=" << endItem; #endif + } } + size_t item = baseItem; { const auto group = this->GetItemGroup(baseItem); @@ -634,7 +638,7 @@ bool CListControlImpl::PrepLayoutCache(CPoint& ptOrigin, size_t indexLo, size_t PFC_DEBUGLOG << "PrepLayoutCache: baseItem=" << baseItem; #endif - size_t anchorIdx = this->IndexFromPointAbs(ptOrigin.y); + size_t anchorIdx = m_greedyGroupLayout ? SIZE_MAX : this->IndexFromPointAbs(ptOrigin.y); int anchorDelta = 0; bool anchorIsFirstInGroup = IsItemFirstInGroupCached(anchorIdx); if (anchorIdx != SIZE_MAX) { @@ -642,7 +646,7 @@ bool CListControlImpl::PrepLayoutCache(CPoint& ptOrigin, size_t indexLo, size_t } #if PrepLayoutCache_Debug - PFC_DEBUGLOG << "PrepLayoutCache: anchorIdx=" << anchorIdx << " anchorDelta=" << anchorDelta << " anchorIsFirstInGroup=" << anchorIsFirstInGroup; + PFC_DEBUGLOG << "PrepLayoutCache: anchorIdx=" << pfc::format_index(anchorIdx) << " anchorDelta=" << anchorDelta << " anchorIsFirstInGroup=" << anchorIsFirstInGroup; #endif bool bChanged = false; diff --git a/3rdparty/foo_SDK/libPPUI/CListControl.h b/3rdparty/foo_SDK/libPPUI/CListControl.h index 7bffbef8..2b8b6f83 100644 --- a/3rdparty/foo_SDK/libPPUI/CListControl.h +++ b/3rdparty/foo_SDK/libPPUI/CListControl.h @@ -282,7 +282,7 @@ class CListControlImpl : public CWindowImpl m_varItemHeights; std::set m_groupHeaders; - + size_t FindGroupBaseCached(size_t itemFor) const; size_t FindGroupBase(size_t itemFor) const; size_t FindGroupBase(size_t itemFor, groupID_t group) const; protected: + // Grouped layout mode toggle + // Default mode is greedy, probes whole list layout in advance (no glitches when scrolling) + // In special conditions when probing is expensive, greedy mode should be turned off + bool m_greedyGroupLayout = true; + pfc::map_t m_themeCache; CTheme & themeFor( const char * what ); CTheme & theme() { return themeFor("LISTVIEW");} diff --git a/3rdparty/foo_SDK/libPPUI/CListControlHeaderImpl.cpp b/3rdparty/foo_SDK/libPPUI/CListControlHeaderImpl.cpp index fb44858a..d2c12c10 100644 --- a/3rdparty/foo_SDK/libPPUI/CListControlHeaderImpl.cpp +++ b/3rdparty/foo_SDK/libPPUI/CListControlHeaderImpl.cpp @@ -750,8 +750,8 @@ t_uint32 CListControlHeaderImpl::GetOptimalSubItemWidth(t_size item, t_size subI } t_uint32 CListControlHeaderImpl::GetOptimalWidth_Cache::GetStringTempWidth() { - if (m_stringTemp.replace_string_ex(m_stringTempUnfuckAmpersands, "&", "&&") > 0) { - m_convertTemp.convert(m_stringTempUnfuckAmpersands); + if (m_stringTemp.replace_string_ex(m_stringTempFixAmpersands, "&", "&&") > 0) { + m_convertTemp.convert(m_stringTempFixAmpersands); } else { m_convertTemp.convert(m_stringTemp); } diff --git a/3rdparty/foo_SDK/libPPUI/CListControlHeaderImpl.h b/3rdparty/foo_SDK/libPPUI/CListControlHeaderImpl.h index ad7abb29..166c5952 100644 --- a/3rdparty/foo_SDK/libPPUI/CListControlHeaderImpl.h +++ b/3rdparty/foo_SDK/libPPUI/CListControlHeaderImpl.h @@ -89,7 +89,7 @@ class CListControlHeaderImpl : public CListControlFontOps { struct GetOptimalWidth_Cache { //! For temporary use. - pfc::string8_fastalloc m_stringTemp, m_stringTempUnfuckAmpersands; + pfc::string8_fastalloc m_stringTemp, m_stringTempFixAmpersands; //! For temporary use. pfc::stringcvt::string_wide_from_utf8_t m_convertTemp; //! Our DC for measuring text. Correct font pre-selected. diff --git a/3rdparty/foo_SDK/libPPUI/CListControlOwnerData.h b/3rdparty/foo_SDK/libPPUI/CListControlOwnerData.h index 8f9f9d11..04488ad4 100644 --- a/3rdparty/foo_SDK/libPPUI/CListControlOwnerData.h +++ b/3rdparty/foo_SDK/libPPUI/CListControlOwnerData.h @@ -29,7 +29,8 @@ class IListControlOwnerDataSource { lineCount = 1; return listGetSubItemText( ctx, item, subItem); } virtual void listSetEditField(ctx_t ctx, size_t item, size_t subItem, const char * val) {} - virtual uint32_t listGetEditFlags(ctx_t ctx, size_t item, size_t subItem) {return 0;} + // Returns InPlaceEdit::KFlag* + virtual uint32_t listGetEditFlags(ctx_t ctx, size_t item, size_t subItem) {return 0;} typedef InPlaceEdit::CTableEditHelperV2::autoComplete_t autoComplete_t; typedef InPlaceEdit::CTableEditHelperV2::combo_t combo_t; virtual autoComplete_t listGetAutoComplete(ctx_t, size_t item, size_t subItem) {return autoComplete_t();} diff --git a/3rdparty/foo_SDK/libPPUI/CListControlTruncationTooltipImpl.cpp b/3rdparty/foo_SDK/libPPUI/CListControlTruncationTooltipImpl.cpp index de824efd..493e1742 100644 --- a/3rdparty/foo_SDK/libPPUI/CListControlTruncationTooltipImpl.cpp +++ b/3rdparty/foo_SDK/libPPUI/CListControlTruncationTooltipImpl.cpp @@ -1,6 +1,7 @@ #include "stdafx.h" #include "CListControl.h" #include "PaintUtils.h" +#include "DarkMode.h" LRESULT CListControlTruncationTooltipImpl::OnTTShow(int,LPNMHDR,BOOL&) { SetTimer(KTooltipTimer,KTooltipTimerDelay); @@ -206,4 +207,13 @@ void CListControlTruncationTooltipImpl::InitTooltip() { m_toolinfo.lpszText = LPSTR_TEXTCALLBACK; m_toolinfo.hinst = GetThisModuleHandle(); WIN32_OP_D( m_tooltip.AddTool(&m_toolinfo) ); + + if ( GetDarkMode() ) DarkMode::ApplyDarkThemeCtrl(m_tooltip, true ); +} + +void CListControlTruncationTooltipImpl::RefreshDarkMode() { + __super::RefreshDarkMode(); + if (m_tooltip) { + DarkMode::ApplyDarkThemeCtrl(m_tooltip, GetDarkMode() ); + } } diff --git a/3rdparty/foo_SDK/libPPUI/CListControlTruncationTooltipImpl.h b/3rdparty/foo_SDK/libPPUI/CListControlTruncationTooltipImpl.h index e53463ce..005b42cf 100644 --- a/3rdparty/foo_SDK/libPPUI/CListControlTruncationTooltipImpl.h +++ b/3rdparty/foo_SDK/libPPUI/CListControlTruncationTooltipImpl.h @@ -19,6 +19,7 @@ class CListControlTruncationTooltipImpl : public CListControlHeaderImpl { void OnViewOriginChange(CPoint p_delta) override {TParent::OnViewOriginChange(p_delta);TooltipRemove();} void TooltipRemove(); + virtual void RefreshDarkMode(); protected: virtual bool GetTooltipData( CPoint ptAbs, pfc::string_base & text, CRect & rc, CFontHandle & font) const; private: diff --git a/3rdparty/foo_SDK/libPPUI/CListControlWithSelection.cpp b/3rdparty/foo_SDK/libPPUI/CListControlWithSelection.cpp index 3d6a9964..436e4f72 100644 --- a/3rdparty/foo_SDK/libPPUI/CListControlWithSelection.cpp +++ b/3rdparty/foo_SDK/libPPUI/CListControlWithSelection.cpp @@ -1109,14 +1109,31 @@ bool CListControlWithSelectionBase::GetFocusRectAbs(CRect & p_rect) { return false; } +bool CListControlWithSelectionBase::GetContextMenuPoint2(CPoint& ptInOut) { + CPoint ptInvalid(-1,-1); + if (ptInOut == ptInvalid) { + ptInOut = GetContextMenuPointDefault(); + return ptInOut != ptInvalid; + } else { + CRect rc = this->GetClientRectHook(); + WIN32_OP_D( ClientToScreen(rc) ); + return !!rc.PtInRect(ptInOut); + } +} + +CPoint CListControlWithSelectionBase::GetContextMenuPointDefault() { + CRect rect; + if (!GetFocusRectAbs(rect)) return CPoint(-1,-1); + EnsureVisibleRectAbs(rect); + CPoint pt = rect.CenterPoint() - GetViewOffset(); + ClientToScreen(&pt); + return pt; +} + CPoint CListControlWithSelectionBase::GetContextMenuPoint(CPoint ptGot) { CPoint pt; if (ptGot.x == -1 && ptGot.y == -1) { - CRect rect; - if (!GetFocusRectAbs(rect)) return 0; - EnsureVisibleRectAbs(rect); - pt = rect.CenterPoint() - GetViewOffset(); - ClientToScreen(&pt); + pt = GetContextMenuPointDefault(); } else { pt = ptGot; } @@ -1126,11 +1143,7 @@ CPoint CListControlWithSelectionBase::GetContextMenuPoint(CPoint ptGot) { CPoint CListControlWithSelectionBase::GetContextMenuPoint(LPARAM lp) { CPoint pt; if (lp == -1) { - CRect rect; - if (!GetFocusRectAbs(rect)) return 0; - EnsureVisibleRectAbs(rect); - pt = rect.CenterPoint() - GetViewOffset(); - ClientToScreen(&pt); + pt = GetContextMenuPointDefault(); } else { pt = lp; } @@ -1444,7 +1457,7 @@ void CListControlWithSelectionBase::RunDragDrop(const CPoint & p_origin, bool p_ } pfc::com_ptr_t source = new CDropSourceImpl(); - source->wndOrigin = *this; + source->wndOrigin = m_hWnd; source->allowDragOutside = true; source->allowReorder = (flags & dragDrop_reorder) != 0; @@ -1474,7 +1487,7 @@ bool CListControlWithSelectionBase::RunReorderDragDrop(CPoint ptOrigin, CPoint & pfc::com_ptr_t source = new CDropSourceImpl(); pfc::com_ptr_t target = new CDropTargetImpl(); - source->wndOrigin = *this; + source->wndOrigin = m_hWnd; source->allowDragOutside = false; source->allowReorder = true; @@ -1537,9 +1550,11 @@ int CListControlWithSelectionBase::OnCreatePassThru(LPCREATESTRUCT) { }; target->HookLeave = [this] { this->ClearDropMark(); + this->ToggleDDScroll(false); }; target->Track = [this, dda](CPoint pt) { + this->ToggleDDScroll(true); if ( dda->showDropMark ) { WIN32_OP_D(this->ScreenToClient(&pt)); size_t idx = this->InsertIndexFromPoint(pt); diff --git a/3rdparty/foo_SDK/libPPUI/CListControlWithSelection.h b/3rdparty/foo_SDK/libPPUI/CListControlWithSelection.h index 73412297..6ce20d6f 100644 --- a/3rdparty/foo_SDK/libPPUI/CListControlWithSelection.h +++ b/3rdparty/foo_SDK/libPPUI/CListControlWithSelection.h @@ -124,6 +124,11 @@ class CListControlWithSelectionBase : public CListControl { //! Input & output in screen coordinates, per WM_CONTEXTMENU conventions. CPoint GetContextMenuPoint(LPARAM lp); CPoint GetContextMenuPoint(CPoint ptGot); + //! Import context menu point coordinates: turn (-1,-1) to something that makes sense; \n + //! Returns false if clicked point was outside client area so WM_CONTEXTMENU should be left unhandled. + bool GetContextMenuPoint2(CPoint & ptInOut); + //! Returns center-of-focused-item point for context menu, in screen coordinates. + CPoint GetContextMenuPointDefault(); protected: void ToggleDDScroll(bool p_state); diff --git a/3rdparty/foo_SDK/libPPUI/Controls.cpp b/3rdparty/foo_SDK/libPPUI/Controls.cpp index 68ce6585..ffdcaebc 100644 --- a/3rdparty/foo_SDK/libPPUI/Controls.cpp +++ b/3rdparty/foo_SDK/libPPUI/Controls.cpp @@ -2,6 +2,7 @@ #include #include "Controls.h" #include "PaintUtils.h" +#include "HyperLinkCtrl.h" void CStaticSeparator::OnPaint(CDCHandle) { PaintUtils::PaintSeparatorControl(*this); @@ -11,6 +12,7 @@ void CSeparator::OnPaint(CDCHandle dc) { PaintUtils::PaintSeparatorControl(*this); } +#if 0 // BROKEN WITH DARK MODE, DO NOT USE CStaticMainInstruction::CStaticMainInstruction() { SetThemePart(TEXT_MAININSTRUCTION); } @@ -48,3 +50,33 @@ void CStaticThemed::OnPaint(CDCHandle) { PFC_ASSERT(SUCCEEDED(retval)); } } +#endif + + +#include "DarkMode-CHyperLink.h" +#include "windowLifetime.h" + +void PP::createHyperLink(HWND wndReplaceMe) { + auto obj = PP::subclassThisWindow(wndReplaceMe); + obj->SetHyperLinkExtendedStyle(HLINK_NOTIFYBUTTON); +} + +namespace { + class CHyperLinkLambda : public DarkMode::CHyperLinkImpl { + public: + std::function f; + bool Navigate() { + f(); + return true; + } + }; +} +void PP::createHyperLink(HWND wndReplaceMe, std::function handler) { + auto obj = PP::subclassThisWindow(wndReplaceMe); + obj->f = handler; +} + +void PP::createHyperLink(HWND wndReplaceMe, const wchar_t* openURL) { + auto obj = PP::subclassThisWindow(wndReplaceMe); + obj->SetHyperLink(openURL); +} diff --git a/3rdparty/foo_SDK/libPPUI/Controls.h b/3rdparty/foo_SDK/libPPUI/Controls.h index 374c4888..b1ecf030 100644 --- a/3rdparty/foo_SDK/libPPUI/Controls.h +++ b/3rdparty/foo_SDK/libPPUI/Controls.h @@ -46,7 +46,9 @@ class CTextControl : public CWindowRegisteredT { CFontHandle m_font; }; - +// CStaticThemed BROKEN WITH DARK MODE, DO NOT USE +// CStaticMainInstruction = use 1.5x scaled font for non subclassed static instead +#if 0 // Static control subclass with override for theme part used for rendering class CStaticThemed : public CWindowImpl { public: @@ -78,7 +80,7 @@ class CStaticMainInstruction : public CStaticThemed { public: CStaticMainInstruction(); }; - +#endif class CSeparator : public CTextControl { diff --git a/3rdparty/foo_SDK/libPPUI/DarkMode-CHyperLink.h b/3rdparty/foo_SDK/libPPUI/DarkMode-CHyperLink.h new file mode 100644 index 00000000..66f86356 --- /dev/null +++ b/3rdparty/foo_SDK/libPPUI/DarkMode-CHyperLink.h @@ -0,0 +1,37 @@ +#pragma once +#include +#include "DarkMode.h" + +namespace DarkMode { + static constexpr COLORREF colorHyperLink = 0xCC6600; // taken from screenshot of syslink + + template class CHyperLinkImpl : public ::CHyperLinkImpl { + public: + BEGIN_MSG_MAP_EX(CDarkHyperLinkImpl) + MESSAGE_HANDLER_EX(DarkMode::msgSetDarkMode(), OnSetDarkMode) + CHAIN_MSG_MAP(::CHyperLinkImpl) + END_MSG_MAP() + private: + LRESULT OnSetDarkMode(UINT, WPARAM wp, LPARAM) { + const bool bDark = (wp != 0); + if ( m_clrLinkBackup == CLR_INVALID ) m_clrLinkBackup = this->m_clrLink; + + if (bDark != m_isDark) { + m_isDark = bDark; + this->m_clrLink = bDark ? colorHyperLink : m_clrLinkBackup; + this->Invalidate(); + } + + return 1; + } + COLORREF m_clrLinkBackup = CLR_INVALID; + bool m_isDark = false; + }; + + + class CHyperLink : public CHyperLinkImpl { + public: + DECLARE_WND_CLASS(_T("WTL_DarkHyperLink")) + }; + +} diff --git a/3rdparty/foo_SDK/libPPUI/DarkMode.cpp b/3rdparty/foo_SDK/libPPUI/DarkMode.cpp index 962c98dc..97f58305 100644 --- a/3rdparty/foo_SDK/libPPUI/DarkMode.cpp +++ b/3rdparty/foo_SDK/libPPUI/DarkMode.cpp @@ -15,6 +15,15 @@ // Allow scary undocumented ordinal-dll-export functions? #define DARKMODE_ALLOW_HAX 1 +#define DARKMODE_DEBUG 0 + +#if DARKMODE_DEBUG +#define DARKMODE_DEBUG_PRINT(...) PFC_DEBUG_PRINT("DarkMode: ", __VA_ARGS__) +#else +#define DARKMODE_DEBUG_PRINT(...) +#endif + + #include #pragma comment(lib, "dwmapi.lib") @@ -56,6 +65,9 @@ Set text/bk colors explicitly Text color: 0xdedede Background: 0x191919 +Label-editing: +Pass WM_CTLCOLOR* to parent, shim TVM_EDITLABEL to pass theme to the editbox (not really necessary tho) + == Rebar == Can be beaten into working to some extent with a combination of: @@ -97,9 +109,10 @@ Full custom draw SetWindowTheme(wnd, L"", L""); works but not 100% pretty, disabled text ugly in particular Full custom draw preferred -== Group box +== Group box === SetWindowTheme(wnd, L"", L""); works but not 100% pretty, disabled text ugly in particular -Full custom draw preferred +Full custom draw preferred (we don't do this). +Avoid disabling groupboxes / use something else. ==== NOTES ==== AllowDarkModeForWindow() needs SetPreferredAppMode() to take effect, hence we implicitly call it @@ -113,7 +126,6 @@ But the latter doesn't require undocumented function calls and doesn't infect al */ namespace { - // 1903 18362 enum class PreferredAppMode { Default, @@ -163,7 +175,7 @@ namespace { }; #if DARKMODE_ALLOW_HAX using fnAllowDarkModeForWindow = bool (WINAPI*)(HWND hWnd, bool allow); // ordinal 133 - using fnSetPreferredAppMode = PreferredAppMode(WINAPI*)(PreferredAppMode appMode); // ordinal 135, in 1903 + using fnSetPreferredAppMode = PreferredAppMode(WINAPI*)(PreferredAppMode appMode); // ordinal 135, since 1809 using fnFlushMenuThemes = void (WINAPI*)(); // ordinal 136 fnAllowDarkModeForWindow _AllowDarkModeForWindow = nullptr; fnSetPreferredAppMode _SetPreferredAppMode = nullptr; @@ -173,7 +185,7 @@ namespace { void InitImports() { if (ImportsInited) return; - if (IsWindows10OrGreater()) { + if (DarkMode::IsSupportedSystem()) { HMODULE hUxtheme = LoadLibraryEx(L"uxtheme.dll", nullptr, LOAD_LIBRARY_SEARCH_SYSTEM32); if (hUxtheme) { _AllowDarkModeForWindow = reinterpret_cast(GetProcAddress(hUxtheme, MAKEINTRESOURCEA(133))); @@ -189,9 +201,14 @@ namespace { namespace DarkMode { + UINT msgSetDarkMode() { + // No need to threadguard this, should be main thread only, not much harm even if it's not + static UINT val = 0; + if (val == 0) val = RegisterWindowMessage(L"libPPUI:msgSetDarkMode"); + return val; + } bool IsSupportedSystem() { - static bool ret = IsWindows10OrGreater(); - return ret; + return Win10BuildNumber() >= 17763; // require at least Win10 1809 / Server 2019 } bool IsWindows11() { return Win10BuildNumber() >= 22000; @@ -254,6 +271,7 @@ namespace DarkMode { } void ApplyDarkThemeCtrl(HWND ctrl, bool bDark, const wchar_t* ThemeID) { + if ( ctrl == NULL ) return; // Both ways work // DarkMode_Theme approach doesn't require evil undocumented MS API calls though AllowDarkModeForWindow(ctrl, bDark); @@ -362,17 +380,13 @@ namespace DarkMode { return false; } - static bool IsHighContrastImpl() - { + bool IsHighContrast() { HIGHCONTRASTW highContrast = { sizeof(highContrast) }; if (SystemParametersInfoW(SPI_GETHIGHCONTRAST, sizeof(highContrast), &highContrast, FALSE)) - return highContrast.dwFlags & HCF_HIGHCONTRASTON; + return (highContrast.dwFlags & HCF_HIGHCONTRASTON) != 0; return false; } - bool IsHighContrast() { - static bool v = IsHighContrastImpl(); - return v; - } + static void DrawTab(CTabCtrl& tabs, CDCHandle dc, int iTab, bool selected, bool focused, const RECT * rcPaint) { (void)focused; PFC_ASSERT((tabs.GetStyle() & TCS_VERTICAL) == 0); @@ -494,7 +508,7 @@ namespace DarkMode { class CToolbarHook { bool m_dark = false; const bool m_explorerTheme; - CWindow m_wnd; + CToolBarCtrl m_wnd; public: CToolbarHook(HWND wnd, bool initial, bool bExplorerTheme) : m_wnd(wnd), m_explorerTheme(bExplorerTheme) { SetDark(initial); @@ -511,6 +525,8 @@ namespace DarkMode { if (m_explorerTheme) ::SetWindowTheme(m_wnd, L"Explorer", NULL); } m_wnd.Invalidate(); + + ApplyDarkThemeCtrl(m_wnd.GetToolTips(), v); } ~CToolbarHook() { if (m_dark) lstDark_clear(m_wnd); @@ -564,8 +580,62 @@ namespace DarkMode { void CTabsHook::SetDark(bool v) { m_dark = v; if (m_hWnd != NULL) Invalidate(); + + ApplyDarkThemeCtrl(GetToolTips(), v); } + class CTreeViewHook : public CWindowImpl { + bool m_dark; + public: + CTreeViewHook(bool v) : m_dark(v) {} + + BEGIN_MSG_MAP_EX(CTreeViewHook) + MESSAGE_RANGE_HANDLER_EX(WM_CTLCOLORMSGBOX, WM_CTLCOLORSTATIC, OnCtlColor) + MESSAGE_HANDLER_EX(msgSetDarkMode(), OnSetDarkMode) + MESSAGE_HANDLER_EX(TVM_EDITLABEL, OnEditLabel) + END_MSG_MAP() + + LRESULT OnCtlColor(UINT uMsg, WPARAM wParam, LPARAM lParam) { + return GetParent().SendMessage(uMsg, wParam, lParam); + } + LRESULT OnEditLabel(UINT, WPARAM, LPARAM) { + LRESULT ret = DefWindowProc(); + if (ret != 0) { + HWND edit = (HWND) ret; + PFC_ASSERT( ::IsWindow(edit) ); + ApplyDarkThemeCtrl( edit, m_dark ); + } + return ret; + } + void SetDark(bool v) { + if (m_dark == v) return; + m_dark = v; + ApplyDark(); + } + void ApplyDark() { + ApplyDarkThemeCtrl(m_hWnd, m_dark); + COLORREF bk = m_dark ? GetSysColor(COLOR_WINDOW) : (COLORREF)(-1); + COLORREF tx = m_dark ? GetSysColor(COLOR_WINDOWTEXT) : (COLORREF)(-1); + this->SetTextColor(tx); this->SetLineColor(tx); + this->SetBkColor(bk); + + ApplyDarkThemeCtrl(GetToolTips(), m_dark); + } + + void SubclassWindow(HWND wnd) { + WIN32_OP_D( __super::SubclassWindow(wnd) ); + this->ApplyDark(); + } + + LRESULT OnSetDarkMode(UINT, WPARAM wp, LPARAM) { + switch (wp) { + case 0: SetDark(false); break; + case 1: SetDark(true); break; + } + return 1; + } + }; + class CDialogHook : public CWindowImpl { bool m_enabled; public: @@ -828,6 +898,9 @@ namespace DarkMode { } void Paint(CDCHandle dc) { + CRect rcClient; WIN32_OP_D(GetClientRect(rcClient)); + dc.FillSolidRect(rcClient, GetSysColor(COLOR_BTNFACE)); // Wine seems to not call our WM_ERASEBKGND handler, fill the background here too + dc.SelectFont(GetFont()); dc.SetBkMode(TRANSPARENT); dc.SetTextColor(GetSysColor(COLOR_WINDOWTEXT)); @@ -864,7 +937,8 @@ namespace DarkMode { ds.hDC = dc; ds.rcItem = rcPart; - GetParent().SendMessage(WM_DRAWITEM, (WPARAM)m_hWnd, (LPARAM)&ds); + DCStateScope scope(dc); + GetParent().SendMessage(WM_DRAWITEM, GetDlgCtrlID(), (LPARAM)&ds); } else { CRect rcText = rcPart; int defMargin = rcText.Height() / 4; @@ -875,7 +949,6 @@ namespace DarkMode { } if (GetStyle() & SBARS_SIZEGRIP) { - CRect rcClient; WIN32_OP_D(GetClientRect(rcClient)); CSize size; auto theme = OpenThemeData(*this, L"status"); PFC_ASSERT(theme != NULL); @@ -921,10 +994,15 @@ namespace DarkMode { MSG_WM_PRINTCLIENT(OnPaint) MSG_WM_ERASEBKGND(OnEraseBkgnd) MSG_WM_UPDATEUISTATE(OnUpdateUIState) + + // Note that checkbox implementation likes to paint on its own in response to events + // instead of invalidating and handling WM_PAINT + // We have to specifically trigger WM_PAINT to override their rendering with ours MESSAGE_HANDLER_EX(WM_SETFOCUS, OnMsgRedraw) MESSAGE_HANDLER_EX(WM_KILLFOCUS, OnMsgRedraw) MESSAGE_HANDLER_EX(WM_ENABLE, OnMsgRedraw) MESSAGE_HANDLER_EX(WM_SETTEXT, OnMsgRedraw) + MESSAGE_HANDLER_EX(msgSetDarkMode(), OnSetDarkMode) END_MSG_MAP() @@ -937,12 +1015,27 @@ namespace DarkMode { } LRESULT OnMsgRedraw(UINT, WPARAM, LPARAM) { - Invalidate(); SetMsgHandled(FALSE); return 0; + if ( m_dark ) { + // PROBLEM: + // Can't invalidate prior to their handling of the message + // Causes bugs with specific chains of events - EnableWindow() followed immediately SetWindowText() + LRESULT ret = DefWindowProc(); + Invalidate(); + return ret; + } + SetMsgHandled(FALSE); return 0; } void OnUpdateUIState(WORD nAction, WORD nState) { (void)nAction; - if (nState & (UISF_HIDEACCEL | UISF_HIDEFOCUS)) Invalidate(); + if ( m_dark && (nState & (UISF_HIDEACCEL | UISF_HIDEFOCUS)) != 0) { + // PROBLEM: + // Can't invalidate prior to their handling of the message + // Causes bugs with specific chains of events - EnableWindow() followed immediately SetWindowText() + DefWindowProc(); + Invalidate(); + return; + } SetMsgHandled(FALSE); } void PaintHandler(CDCHandle dc) { @@ -957,7 +1050,8 @@ namespace DarkMode { GetParent().SendMessage(WM_CTLCOLORBTN, (WPARAM)dc.m_hDC, (LPARAM)m_hWnd); if (bDisabled) dc.SetTextColor(DarkMode::GetSysColor(COLOR_GRAYTEXT)); // override WM_CTLCOLORBTN - const DWORD btnType = GetStyle() & BS_TYPEMASK; + const DWORD btnStyle = GetStyle(); + const DWORD btnType = btnStyle & BS_TYPEMASK; const bool bRadio = (btnType == BS_RADIOBUTTON || btnType == BS_AUTORADIOBUTTON); const int part = bRadio ? BP_RADIOBUTTON : BP_CHECKBOX; @@ -965,7 +1059,8 @@ namespace DarkMode { const DWORD uiState = (DWORD)SendMessage(WM_QUERYUISTATE); - const bool bPressed = (ctrlState & BST_CHECKED) != 0; + const bool bChecked = (ctrlState & BST_CHECKED) != 0; + const bool bMixed = (ctrlState & BST_INDETERMINATE) != 0; const bool bHot = (ctrlState & BST_HOT) != 0; const bool bFocus = (ctrlState & BST_FOCUS) != 0 && (uiState & UISF_HIDEFOCUS) == 0; @@ -977,11 +1072,17 @@ namespace DarkMode { if (theme != NULL && IsThemePartDefined(theme, part, 0)) { int state = 0; if (bDisabled) { - state = bPressed ? CBS_CHECKEDDISABLED : CBS_UNCHECKEDDISABLED; + if ( bChecked ) state = CBS_CHECKEDDISABLED; + else if ( bMixed ) state = CBS_MIXEDDISABLED; + else state = CBS_UNCHECKEDDISABLED; } else if (bHot) { - state = bPressed ? CBS_CHECKEDHOT : CBS_UNCHECKEDHOT; + if ( bChecked ) state = CBS_CHECKEDHOT; + else if ( bMixed ) state = CBS_MIXEDHOT; + else state = CBS_UNCHECKEDNORMAL; } else { - state = bPressed ? CBS_CHECKEDNORMAL : CBS_UNCHECKEDNORMAL; + if ( bChecked ) state = CBS_CHECKEDNORMAL; + else if ( bMixed ) state = CBS_MIXEDNORMAL; + else state = CBS_UNCHECKEDNORMAL; } CSize size; @@ -1001,7 +1102,8 @@ namespace DarkMode { if (theme != NULL) CloseThemeData(theme); if (!bDrawn) { int stateEx = bRadio ? DFCS_BUTTONRADIO : DFCS_BUTTONCHECK; - if (bPressed) stateEx |= DFCS_CHECKED; + if (bChecked) stateEx |= DFCS_CHECKED; + // FIX ME bMixed ? if (bDisabled) stateEx |= DFCS_INACTIVE; else if (bHot) stateEx |= DFCS_HOT; @@ -1020,7 +1122,12 @@ namespace DarkMode { if (!text.IsEmpty()) { CRect rcText = rcClient; rcText.left += margin; - UINT dtFlags = DT_VCENTER | DT_END_ELLIPSIS | DT_SINGLELINE; + UINT dtFlags = DT_VCENTER; + if (btnStyle & BS_MULTILINE) { + dtFlags |= DT_WORDBREAK; + } else { + dtFlags |= DT_END_ELLIPSIS | DT_SINGLELINE; + } dc.DrawText(text, text.GetLength(), rcText, dtFlags); if (bFocus) { dc.DrawText(text, text.GetLength(), rcText, DT_CALCRECT | dtFlags); @@ -1449,6 +1556,50 @@ namespace DarkMode { dc.DrawText(L"˅", 1, layout.lower, DT_SINGLELINE | DT_VCENTER | DT_CENTER | DT_NOPREFIX); } }; + + class CNCFrameHook : public CWindowImpl { + public: + CNCFrameHook(bool dark) : m_dark(dark) {} + + BEGIN_MSG_MAP_EX(CNCFrameHook) + MESSAGE_HANDLER_EX(msgSetDarkMode(), OnSetDarkMode) + MSG_WM_NCPAINT(OnNCPaint) + END_MSG_MAP() + + void SetDark(bool v) { + if (v != m_dark) { + m_dark = v; ApplyDark(); + } + } + BOOL SubclassWindow(HWND wnd) { + auto rv = __super::SubclassWindow(wnd); + if (rv) { + ApplyDark(); + } + return rv; + } + private: + void OnNCPaint(HRGN rgn) { + if (m_dark) { + NCPaintDarkFrame(m_hWnd, rgn); + return; + } + SetMsgHandled(FALSE); + } + void ApplyDark() { + ApplyDarkThemeCtrl(m_hWnd, m_dark); + Invalidate(); + } + LRESULT OnSetDarkMode(UINT, WPARAM wp, LPARAM) { + switch (wp) { + case 0: SetDark(false); break; + case 1: SetDark(true); break; + } + return 1; + } + + bool m_dark; + }; } void CHooks::AddPopup(HWND wnd) { @@ -1480,17 +1631,36 @@ namespace DarkMode { AddCtrlMsg(wnd); } void CHooks::AddComboBox(HWND wnd) { - addOp([wnd, this] { SetWindowTheme(wnd, m_dark ? L"DarkMode_CFD" : L"Explorer", NULL);}); + { + CComboBox combo = wnd; + COMBOBOXINFO info = {sizeof(info)}; + WIN32_OP_D( combo.GetComboBoxInfo(&info) ); + if (info.hwndList != NULL) { + AddListBox( info.hwndList ); + } + } + + addOp([wnd, this] { + SetWindowTheme(wnd, m_dark ? L"DarkMode_CFD" : L"Explorer", NULL); + }); } void CHooks::AddComboBoxEx(HWND wnd) { this->AddControls(wnd); // recurse to add the combo box } - void CHooks::AddEditBox(HWND wnd) { AddGeneric(wnd); } + void CHooks::AddEditBox(HWND wnd) { +#if 0 // Experimental + auto hook = new ImplementOnFinalMessage(m_dark); + hook->SubclassWindow( wnd ); + AddCtrlMsg( wnd ); +#else + AddGeneric(wnd); +#endif + } void CHooks::AddButton(HWND wnd) { CButton btn(wnd); auto style = btn.GetButtonStyle(); auto type = style & BS_TYPEMASK; - if ((type == BS_CHECKBOX || type == BS_AUTOCHECKBOX || type == BS_RADIOBUTTON || type == BS_AUTORADIOBUTTON) && (style & BS_PUSHLIKE) == 0) { + if ((type == BS_CHECKBOX || type == BS_AUTOCHECKBOX || type == BS_RADIOBUTTON || type == BS_AUTORADIOBUTTON || type == BS_3STATE || type == BS_AUTO3STATE) && (style & BS_PUSHLIKE) == 0) { // MS checkbox implementation is terminally retarded and won't draw text in correct color // Subclass it and draw our own content // Other button types seem OK @@ -1557,18 +1727,12 @@ namespace DarkMode { } void CHooks::AddTreeView(HWND wnd) { - this->addOp([wnd, this] { - CTreeViewCtrl tv(wnd); - ApplyDarkThemeCtrl(tv, m_dark); - COLORREF bk = m_dark ? GetSysColor(COLOR_WINDOW) : (COLORREF)(-1); - COLORREF tx = m_dark ? GetSysColor(COLOR_WINDOWTEXT) : (COLORREF)(-1); - tv.SetTextColor(tx); tv.SetLineColor(tx); - tv.SetBkColor(bk); - }); + auto hook = new ImplementOnFinalMessage(m_dark); + hook->SubclassWindow(wnd); + this->AddCtrlMsg(wnd); } void CHooks::AddListBox(HWND wnd) { - // Not needed! Yay! - // Handling WM_CTLCOLOR* is enough + this->AddGeneric( wnd ); #if 0 auto subst = CListControl_ReplaceListBox(wnd); if (subst) AddPPListControl(subst); @@ -1671,16 +1835,89 @@ namespace DarkMode { m_cleanup.clear(); } - UINT msgSetDarkMode() { - // No need to threadguard this, should be main thread only, not much harm even if it's not - static UINT val = 0; - if (val == 0) val = RegisterWindowMessage(L"libPPUI:msgSetDarkMode"); - return val; - } - void CHooks::AddApp() { addOp([this] { SetAppDarkMode(this->m_dark); }); } + + void NCPaintDarkFrame(HWND wnd_, HRGN rgn_) { + // rgn is in SCREEN COORDINATES, possibly (HRGN)1 to indicate no clipping / whole nonclient area redraw + // we're working with SCREEN COORDINATES until actual DC painting + CWindow wnd = wnd_; + + CRect rcWindow, rcClient; + WIN32_OP_D( wnd.GetWindowRect(rcWindow) ); + WIN32_OP_D( wnd.GetClientRect(rcClient) ); + WIN32_OP_D( wnd.ClientToScreen( rcClient ) ); // transform all to same coordinate system + + CRgn rgnClip; + WIN32_OP_D( rgnClip.CreateRectRgnIndirect(rcWindow) != NULL ); + if (rgn_ != NULL && rgn_ != (HRGN)1) { + // we have a valid HRGN from caller? + if (rgnClip.CombineRgn(rgn_, RGN_AND) == NULLREGION) return; // nothing to draw, exit early + } + + { + // Have scroll bars? Have DefWindowProc() them then exclude from our rgnClip. + SCROLLBARINFO si = { sizeof(si) }; + if (::GetScrollBarInfo(wnd, OBJID_VSCROLL, &si) && (si.rgstate[0] & STATE_SYSTEM_INVISIBLE) == 0 && si.rcScrollBar.left < si.rcScrollBar.right) { + CRect rc = si.rcScrollBar; + // rcClient.right = rc.right; + CRgn rgn; WIN32_OP_D( rgn.CreateRectRgnIndirect(rc) ); + int status = SIMPLEREGION; + if (rgnClip) { + status = rgn.CombineRgn(rgn, rgnClip, RGN_AND); + } + if (status != NULLREGION) { + DefWindowProc(wnd, WM_NCPAINT, (WPARAM)rgn.m_hRgn, 0); + rgnClip.CombineRgn(rgn, RGN_DIFF); // exclude from further drawing + } + } + if (::GetScrollBarInfo(wnd, OBJID_HSCROLL, &si) && (si.rgstate[0] & STATE_SYSTEM_INVISIBLE) == 0 && si.rcScrollBar.top < si.rcScrollBar.bottom) { + CRect rc = si.rcScrollBar; + // rcClient.bottom = rc.bottom; + CRgn rgn; WIN32_OP_D(rgn.CreateRectRgnIndirect(rc)); + int status = SIMPLEREGION; + if (rgnClip) { + status = rgn.CombineRgn(rgn, rgnClip, RGN_AND); + } + if (status != NULLREGION) { + DefWindowProc(wnd, WM_NCPAINT, (WPARAM)rgn.m_hRgn, 0); + rgnClip.CombineRgn(rgn, RGN_DIFF); // exclude from further drawing + } + } + } + + const auto colorLight = DarkMode::GetSysColor(COLOR_BTNHIGHLIGHT); + const auto colorDark = DarkMode::GetSysColor(COLOR_BTNSHADOW); + + CWindowDC dc( wnd ); + if (dc.IsNull()) { + PFC_ASSERT(!"???"); + return; + } + + + // Window DC has (0,0) in upper-left corner of our window (not screen, not client) + // Turn rcWindow to (0,0), (winWidth, winHeight) + CPoint origin = rcWindow.TopLeft(); + rcWindow.OffsetRect(-origin); + rcClient.OffsetRect(-origin); + + if (!rgnClip.IsNull()) { + // rgnClip is still in screen coordinates, fix this here + rgnClip.OffsetRgn(-origin); + dc.SelectClipRgn(rgnClip); + } + + // bottom + dc.FillSolidRect(CRect(rcClient.left, rcClient.bottom, rcWindow.right, rcWindow.bottom), colorLight); + // right + dc.FillSolidRect(CRect(rcClient.right, rcWindow.top, rcWindow.right, rcClient.bottom), colorLight); + // top + dc.FillSolidRect(CRect(rcWindow.left, rcWindow.top, rcWindow.right, rcClient.top), colorDark); + // left + dc.FillSolidRect(CRect(rcWindow.left, rcClient.top, rcClient.left, rcWindow.bottom), colorDark); + } } diff --git a/3rdparty/foo_SDK/libPPUI/DarkMode.h b/3rdparty/foo_SDK/libPPUI/DarkMode.h index 11454872..de6fbb10 100644 --- a/3rdparty/foo_SDK/libPPUI/DarkMode.h +++ b/3rdparty/foo_SDK/libPPUI/DarkMode.h @@ -3,10 +3,14 @@ #include namespace DarkMode { + // Is dark mode supported on this system or not? bool IsSupportedSystem(); + // Is system in dark mode or not? bool QueryUserOption(); + // Darken menus etc app-wide void SetAppDarkMode(bool bDark); + // Darken window title bar void UpdateTitleBar(HWND wnd, bool bDark ); void ApplyDarkThemeCtrl(HWND ctrl, bool bDark, const wchar_t * ThemeID = L"Explorer"); void AllowDarkModeForWindow(HWND wnd, bool bDark); @@ -31,6 +35,9 @@ namespace DarkMode { // Can be used with NOTIFY_CODE_HANDLER() directly LRESULT OnCustomDraw(int, NMHDR*, BOOL & bHandled); + // Handle WM_NCPAINT drawing dark frame + void NCPaintDarkFrame(HWND ctrl, HRGN rgn); + bool IsHighContrast(); // msgSetDarkMode diff --git a/3rdparty/foo_SDK/libPPUI/EditBoxFix.cpp b/3rdparty/foo_SDK/libPPUI/EditBoxFix.cpp new file mode 100644 index 00000000..b894b718 --- /dev/null +++ b/3rdparty/foo_SDK/libPPUI/EditBoxFix.cpp @@ -0,0 +1,19 @@ +#include "stdafx.h" +#include "EditBoxFixes.h" +#include "wtl-pp.h" +#include "windowLifetime.h" + +namespace PP { + void editBoxFix(HWND wndEdit) { + PFC_ASSERT( IsWindow(wndEdit) ); + PP::subclassThisWindow(wndEdit); + } + void comboBoxFix(HWND wndCombo) { + PFC_ASSERT( IsWindow(wndCombo) ); + CComboBox combo = wndCombo; + COMBOBOXINFO info = { sizeof(info) }; + if (combo.GetComboBoxInfo(&info)) { + if ( info.hwndItem != NULL ) editBoxFix( info.hwndItem ); + } + } +} \ No newline at end of file diff --git a/3rdparty/foo_SDK/libPPUI/EditBoxFixes.h b/3rdparty/foo_SDK/libPPUI/EditBoxFixes.h new file mode 100644 index 00000000..e3337438 --- /dev/null +++ b/3rdparty/foo_SDK/libPPUI/EditBoxFixes.h @@ -0,0 +1,7 @@ +#pragma once + +namespace PP { + // One-line methods to inject our edit box shims: Ctrl+A, Ctrl+Backspace, etc + void editBoxFix(HWND wndEdit); + void comboBoxFix(HWND wndCombo); +} \ No newline at end of file diff --git a/3rdparty/foo_SDK/libPPUI/HyperLinkCtrl.h b/3rdparty/foo_SDK/libPPUI/HyperLinkCtrl.h new file mode 100644 index 00000000..383c1ac5 --- /dev/null +++ b/3rdparty/foo_SDK/libPPUI/HyperLinkCtrl.h @@ -0,0 +1,8 @@ +#pragma once +#include +namespace PP { + // One-line method to turn static control to hyperlink firing WM_NOTIFY + void createHyperLink(HWND wndReplaceMe); + void createHyperLink(HWND wndReplaceMe, std::function handler); + void createHyperLink(HWND wndReplaceMe, const wchar_t * openURL); +} \ No newline at end of file diff --git a/3rdparty/foo_SDK/libPPUI/PaintUtils.cpp b/3rdparty/foo_SDK/libPPUI/PaintUtils.cpp index 913cf72c..15b15054 100644 --- a/3rdparty/foo_SDK/libPPUI/PaintUtils.cpp +++ b/3rdparty/foo_SDK/libPPUI/PaintUtils.cpp @@ -191,6 +191,7 @@ namespace PaintUtils { eh << graphics.DrawLine(&penSH, points[3], points[0]); } catch (std::exception const& e) { (void)e; + PFC_ASSERT(!"???"); // console::print(e.what()); } } @@ -218,6 +219,7 @@ namespace PaintUtils { eh << graphics.DrawLine(&penSH, points[2], points[0] + Gdiplus::Point(0, -1)); } catch (std::exception const& e) { (void)e; + PFC_ASSERT(!"???"); // console::print(e.what()); } } @@ -241,6 +243,7 @@ namespace PaintUtils { eh << graphics.DrawLine(&pen, points[0], points[1]); } catch(std::exception const & e) { (void) e; + PFC_ASSERT(!"???"); // console::print(e.what()); } } diff --git a/3rdparty/foo_SDK/libPPUI/libPPUI-license.txt b/3rdparty/foo_SDK/libPPUI/libPPUI-license.txt index 3f05fccd..0ab480d7 100644 --- a/3rdparty/foo_SDK/libPPUI/libPPUI-license.txt +++ b/3rdparty/foo_SDK/libPPUI/libPPUI-license.txt @@ -1,4 +1,4 @@ -Copyright (C) 2002-2022 Peter Pawlowski +Copyright (C) 2002-2023 Peter Pawlowski This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/3rdparty/foo_SDK/libPPUI/libPPUI.vcxproj b/3rdparty/foo_SDK/libPPUI/libPPUI.vcxproj index f0c5d68c..5ea353f6 100644 --- a/3rdparty/foo_SDK/libPPUI/libPPUI.vcxproj +++ b/3rdparty/foo_SDK/libPPUI/libPPUI.vcxproj @@ -154,7 +154,7 @@ Level3 Disabled false - ..;$(SolutionDir)/../3rdparty/WTL10_10320_Release/Include + ..;$(SolutionDir)\..\3rdparty\WTL10_10320_Release\Include ProgramDatabase true 4715 @@ -176,7 +176,7 @@ false true false - ..;$(SolutionDir)/../3rdparty/WTL10_10320_Release/Include + ..;$(SolutionDir)\..\3rdparty\WTL10_10320_Release\Include stdcpp17 true ProgramDatabase @@ -228,7 +228,7 @@ true true false - ..;$(SolutionDir)/../3rdparty/WTL10_10320_Release/Include + ..;$(SolutionDir)\..\3rdparty\WTL10_10320_Release\Include true 4715 false @@ -257,7 +257,7 @@ Fast true false - ..;$(SolutionDir)/../3rdparty/WTL10_10320_Release/Include + ..;$(SolutionDir)\..\3rdparty\WTL10_10320_Release\Include /d2notypeopt %(AdditionalOptions) NDEBUG;_UNICODE;UNICODE;%(PreprocessorDefinitions) stdcpp17 @@ -353,14 +353,17 @@ + + + @@ -398,6 +401,7 @@ + @@ -420,12 +424,12 @@ + - - + \ No newline at end of file diff --git a/3rdparty/foo_SDK/libPPUI/libPPUI.vcxproj.filters b/3rdparty/foo_SDK/libPPUI/libPPUI.vcxproj.filters index eba3ed57..3128d607 100644 --- a/3rdparty/foo_SDK/libPPUI/libPPUI.vcxproj.filters +++ b/3rdparty/foo_SDK/libPPUI/libPPUI.vcxproj.filters @@ -194,6 +194,15 @@ Header Files + + Header Files + + + Header Files + + + Header Files + @@ -283,6 +292,12 @@ Source Files + + Source Files + + + Source Files + diff --git a/3rdparty/foo_SDK/libPPUI/win32_utility.h b/3rdparty/foo_SDK/libPPUI/win32_utility.h index f03bfdb0..80ee2c0b 100644 --- a/3rdparty/foo_SDK/libPPUI/win32_utility.h +++ b/3rdparty/foo_SDK/libPPUI/win32_utility.h @@ -46,7 +46,7 @@ void SetDefaultMenuItem(HMENU p_menu, unsigned p_id); void GetOSVersionString(pfc::string_base & out); WORD GetOSVersionCode(); bool IsWine(); -DWORD Win10BuildNumber(); +DWORD Win10BuildNumber(); // See https://en.wikipedia.org/wiki/Windows_10_version_history for build number reference void EnumChildWindows(HWND, std::function); // Recursive void EnumChildWindowsHere(HWND, std::function); // Non-recursive \ No newline at end of file diff --git a/3rdparty/foo_SDK/libPPUI/windowLifetime.h b/3rdparty/foo_SDK/libPPUI/windowLifetime.h index 6a7e9bc5..a49be03c 100644 --- a/3rdparty/foo_SDK/libPPUI/windowLifetime.h +++ b/3rdparty/foo_SDK/libPPUI/windowLifetime.h @@ -1,5 +1,6 @@ #pragma once #include "ImplementOnFinalMessage.h" +#include "win32_op.h" #include namespace PP { @@ -15,8 +16,29 @@ namespace PP { //! OnFinalMessage() is automatically overridden to delete the window subclass object. template obj_t* subclassThisWindow(HWND wnd, arg_t && ... arg) { + PFC_ASSERT( wnd != NULL ); auto ret = newWindowObj(std::forward(arg) ...); WIN32_OP_D(ret->SubclassWindow(wnd)); return ret; } + + //! Creates a new window object, of ctrl_t typem with automatic lifetime management, + //! and replaces an existing control in a dialog. + template + ctrl_t * replaceDialogCtrl(CWindow wndDialog, UINT replaceControlID) { + CWindow wndReplace = wndDialog.GetDlgItem(replaceControlID); + ATLASSERT(wndReplace != NULL); + CRect rc; + CWindow wndPrev = wndDialog.GetNextDlgTabItem(wndReplace, TRUE); + WIN32_OP_D(wndReplace.GetWindowRect(&rc)); + WIN32_OP_D(wndDialog.ScreenToClient(rc)); + CString text; + wndReplace.GetWindowText(text); + WIN32_OP_D(wndReplace.DestroyWindow()); + auto ctrl = newWindowObj(); + WIN32_OP_D(ctrl->Create(wndDialog, &rc, text, 0, 0, replaceControlID)); + if (wndPrev != NULL) ctrl->SetWindowPos(wndPrev, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE); + ctrl->SetFont(wndDialog.GetFont()); + return ctrl; + } } \ No newline at end of file diff --git a/3rdparty/foo_SDK/libPPUI/wtl-pp.cpp b/3rdparty/foo_SDK/libPPUI/wtl-pp.cpp new file mode 100644 index 00000000..1b0baf23 --- /dev/null +++ b/3rdparty/foo_SDK/libPPUI/wtl-pp.cpp @@ -0,0 +1,47 @@ +#include "stdafx.h" +#include "wtl-pp.h" + +void CEditPPHooks::DeleteLastWord( CEdit wnd, bool bForward ) { + if ( wnd.GetWindowLong(GWL_STYLE) & ES_READONLY ) return; + CString buffer; + if ( wnd.GetWindowText(buffer) <= 0 ) return; + const int len = buffer.GetLength(); + int selStart = len, selEnd = len; + wnd.GetSel(selStart, selEnd); + if ( selStart < 0 || selStart > len ) selStart = len; // sanity + if ( selEnd < selStart ) selEnd = selStart; // sanity + int work = selStart; + if ( work == selEnd ) { + // Only do our stuff if there is nothing yet selected. Otherwise first delete selection. + if (bForward) { + // go forward (ctrl+del) + if (work < len && isSpecial(buffer[work])) { // linebreaks etc? + do ++ work; while( work < len && isSpecial(buffer[work])); + } else { + // delete apparent spacing + while ( work < len && isWordDelimiter(buffer[work])) ++ work; + // delete apparent word + while ( work < len && (!isWordDelimiter(buffer[work]) && !isSpecial(buffer[work]))) ++ work; + } + + if ( selEnd < work ) { + wnd.SetSel(selEnd, work, TRUE ); + wnd.ReplaceSel( TEXT(""), TRUE ); + } + } else { + // go backward (ctrl+backspace) + if ( work > 0 && isSpecial(buffer[work-1])) { // linebreaks etc? + do --work; while( work > 0 && isSpecial(buffer[work-1])); + } else { + // delete apparent spacing + while( work > 0 && isWordDelimiter(buffer[work-1]) ) --work; + // delete apparent word + while( work > 0 && (!isWordDelimiter(buffer[work-1]) && !isSpecial(buffer[work-1]))) --work; + } + if ( selEnd > work ) { + wnd.SetSel(work, selEnd, TRUE ); + wnd.ReplaceSel( TEXT(""), TRUE ); + } + } + } +} diff --git a/3rdparty/foo_SDK/libPPUI/wtl-pp.h b/3rdparty/foo_SDK/libPPUI/wtl-pp.h index 16c577a2..bf932d54 100644 --- a/3rdparty/foo_SDK/libPPUI/wtl-pp.h +++ b/3rdparty/foo_SDK/libPPUI/wtl-pp.h @@ -127,14 +127,14 @@ void InjectParentCtlColorHandler(HWND); } - +// Obsolete, use CImageListManaged instead class CImageListContainer : public CImageList { public: CImageListContainer() {} ~CImageListContainer() {Destroy();} -private: - const CImageListContainer & operator=(const CImageListContainer&); - CImageListContainer(const CImageListContainer&); + + void operator=(const CImageListContainer&) = delete; + CImageListContainer(const CImageListContainer&) = delete; }; @@ -174,7 +174,7 @@ class CCheckBox : public CButton { class CEditPPHooks : public CWindowImpl { public: - bool HandleCtrlA = true, NoEscSteal = false, NoEnterSteal = false; + bool HandleCtrlA = true, NoEscSteal = false, NoEnterSteal = false, WantAllKeys = false; std::function onEnterKey; std::function onEscKey; @@ -194,35 +194,13 @@ class CEditPPHooks : public CWindowImpl { END_MSG_MAP() - static void DeleteLastWord( CEdit wnd ) { - if ( wnd.GetWindowLong(GWL_STYLE) & ES_READONLY ) return; - int len = wnd.GetWindowTextLength(); - if ( len <= 0 ) return; - TCHAR * buffer = new TCHAR [ len + 1 ]; - if ( wnd.GetWindowText( buffer, len + 1 ) <= 0 ) { - delete[] buffer; - return; - } - buffer[len] = 0; - int selStart = len, selEnd = len; - wnd.GetSel(selStart, selEnd); - if ( selStart < 0 || selStart > len ) selStart = len; // sanity - if ( selEnd < selStart ) selEnd = selStart; // sanity - int work = selStart; - if ( work == selEnd ) { - // Only do our stuff if there is nothing yet selected. Otherwise first delete selection. - while( work > 0 && isWordDelimiter(buffer[work-1]) ) --work; - while( work > 0 && !isWordDelimiter(buffer[work-1] ) ) --work; - } - delete[] buffer; - if ( selEnd > work ) { - wnd.SetSel(work, selEnd, TRUE ); - wnd.ReplaceSel( TEXT(""), TRUE ); - } - } + static void DeleteLastWord( CEdit wnd, bool bForward = false ); private: - static bool isWordDelimiter( TCHAR c ) { - return (unsigned) c <= ' ' || c == ',' || c == '.' || c == ';' || c == ':'; + static bool isSpecial( wchar_t c ) { + return (unsigned) c < ' '; + } + static bool isWordDelimiter( wchar_t c ) { + return c == ' ' || c == ',' || c == '.' || c == ';' || c == ':'; } void OnChar(UINT nChar, UINT, UINT nFlags) { if (m_suppressChar != 0) { @@ -251,6 +229,12 @@ class CEditPPHooks : public CWindowImpl { DeleteLastWord( *this ) ; return; } } + if ( nChar == VK_DELETE ) { + if (GetHotkeyModifierFlags() == MOD_CONTROL) { + m_suppressScanCode = nFlags & 0xFF; + DeleteLastWord( *this, true ) ; return; + } + } if ( nChar == VK_RETURN && onEnterKey ) { m_suppressChar = nChar; onEnterKey(); return; @@ -263,6 +247,7 @@ class CEditPPHooks : public CWindowImpl { SetMsgHandled(FALSE); } UINT OnEditGetDlgCode(LPMSG lpMsg) { + if (WantAllKeys) return DLGC_WANTALLKEYS; if (lpMsg == NULL) { SetMsgHandled(FALSE); return 0; } else { @@ -430,23 +415,9 @@ class CWindowRegisteredT : public TBaseClass, public CMessageMap { class CSRWlock { public: - CSRWlock() : theLock() { -#if _WIN32_WINNT < 0x600 - auto dll = GetModuleHandle(_T("kernel32")); - Bind(AcquireSRWLockExclusive, dll, "AcquireSRWLockExclusive"); - Bind(AcquireSRWLockShared, dll, "AcquireSRWLockShared"); - Bind(ReleaseSRWLockExclusive, dll, "ReleaseSRWLockExclusive"); - Bind(ReleaseSRWLockShared, dll, "ReleaseSRWLockShared"); -#endif - } + CSRWlock() { } - bool HaveAPI() { -#if _WIN32_WINNT < 0x600 - return AcquireSRWLockExclusive != NULL; -#else - return true; -#endif - } + static bool HaveAPI() { return true; } void EnterShared() { AcquireSRWLockShared( & theLock ); @@ -465,51 +436,5 @@ class CSRWlock { CSRWlock(const CSRWlock&) = delete; void operator=(const CSRWlock&) = delete; - SRWLOCK theLock; -#if _WIN32_WINNT < 0x600 - template static void Bind(func_t & func, HMODULE dll, const char * name) { - func = reinterpret_cast(GetProcAddress( dll, name ) ); - } - - VOID (WINAPI * AcquireSRWLockExclusive)(PSRWLOCK SRWLock); - VOID (WINAPI * AcquireSRWLockShared)(PSRWLOCK SRWLock); - VOID (WINAPI * ReleaseSRWLockExclusive)(PSRWLOCK SRWLock); - VOID (WINAPI * ReleaseSRWLockShared)(PSRWLOCK SRWLock); -#endif + SRWLOCK theLock = {}; }; - -#if _WIN32_WINNT < 0x600 -class CSRWorCS { -public: - CSRWorCS() : cs() { - if (!srw.HaveAPI()) InitializeCriticalSection(&cs); - } - ~CSRWorCS() { - if (!srw.HaveAPI()) DeleteCriticalSection(& cs ); - } - void EnterShared() { - if (srw.HaveAPI()) srw.EnterShared(); - else EnterCriticalSection(&cs); - } - void EnterExclusive() { - if (srw.HaveAPI()) srw.EnterExclusive(); - else EnterCriticalSection(&cs); - } - void LeaveShared() { - if (srw.HaveAPI()) srw.LeaveShared(); - else LeaveCriticalSection(&cs); - } - void LeaveExclusive() { - if (srw.HaveAPI()) srw.LeaveExclusive(); - else LeaveCriticalSection(&cs); - } -private: - CSRWorCS(const CSRWorCS&) = delete; - void operator=(const CSRWorCS&) = delete; - - CSRWlock srw; - CRITICAL_SECTION cs; -}; -#else -typedef CSRWlock CSRWorCS; -#endif diff --git a/3rdparty/foo_SDK/pfc/SmartStrStr-twoCharMappings.h b/3rdparty/foo_SDK/pfc/SmartStrStr-twoCharMappings.h index 042d43bd..a9506362 100644 --- a/3rdparty/foo_SDK/pfc/SmartStrStr-twoCharMappings.h +++ b/3rdparty/foo_SDK/pfc/SmartStrStr-twoCharMappings.h @@ -5,21 +5,38 @@ static constexpr struct { const char* to; } twoCharMappings[] = { {0x00C6, "AE"}, + {0x00E6, "ae"}, + {0x00DF, "ss"}, + +#if 0 + // umlauts + // the problem with these is that changing them to two-letter represenatations prevents search by non-umlaut vowel from working. + {0x00C4, "AE"}, + {0x00E4, "ae"}, + {0x00D6, "OE"}, + {0x00F6, "oe"}, + {0x00DC, "UE"}, + {0x00FC, "ue"}, +#endif + +#if 0 + // Incomplete list, hence disabled. Nobody uses these. {0x01E2, "AE"}, {0x01FC, "AE"}, - {0x00E6, "ae"}, {0x01E3, "ae"}, {0x01FD, "ae"}, {0x0152, "OE"}, {0x0153, "oe"}, {0x0276, "oe"}, + {0x01C3, "dz"}, {0x01C4, "DZ"}, - {0x01F1, "DZ"}, + {0x01C5, "Dz"}, {0x01C6, "dz"}, + {0x01F1, "DZ"}, + {0x01F2, "Dz"}, {0x01F3, "dz"}, {0x02A3, "dz"}, {0x02A5, "dz"}, - {0x00DF, "ss"}, {0x01C7, "LJ"}, {0x01C8, "Lj"}, {0x01C9, "lj"}, @@ -28,13 +45,5 @@ static constexpr struct { {0x01CC, "nj"}, {0x0132, "IJ"}, {0x0133, "ij"}, - -#if 0 // umlauts - {0x00C4, "AE"}, - {0x00E4, "ae"}, - {0x00D6, "OE"}, - {0x00F6, "oe"}, - {0x00DC, "UE"}, - {0x00FC, "ue"}, #endif }; diff --git a/3rdparty/foo_SDK/pfc/SmartStrStr.cpp b/3rdparty/foo_SDK/pfc/SmartStrStr.cpp index b5b0bbd2..ee5cf312 100644 --- a/3rdparty/foo_SDK/pfc/SmartStrStr.cpp +++ b/3rdparty/foo_SDK/pfc/SmartStrStr.cpp @@ -7,6 +7,50 @@ #include "SmartStrStr-table.h" #include "SmartStrStr-twoCharMappings.h" +bool SmartStrStr::isWordChar(unsigned c) { + // FIX ME map Unicode ranges somehow + return c >= 128 || pfc::char_is_ascii_alphanumeric((char)c); +} + +bool SmartStrStr::isWordChar(const char* ptr) { + unsigned c; + size_t d = pfc::utf8_decode_char(ptr, c); + if (d == 0) return false; // bad UTF-8 + return isWordChar(c); +} + +bool SmartStrStr::isValidWord(const char* ptr) { + if (*ptr == 0) return false; + do { + unsigned c; + size_t d = pfc::utf8_decode_char(ptr, c); + if (d == 0) return false; // bad UTF-8 + if (!isWordChar(c)) return false; + ptr += d; + } while (*ptr != 0); + return true; +} + +void SmartStrStr::findWords(const char* str, std::function cb) { + size_t base = 0, walk = 0; + for (;; ) { + unsigned c = 0; + size_t d = pfc::utf8_decode_char(str + walk, c); + if (d == 0) break; + + if (!SmartStrStr::isWordChar(c)) { + if (walk > base) { + cb(pfc::string_part(str + base, walk - base)); + } + base = walk + d; + } + walk += d; + } + if (walk > base) { + cb(pfc::string_part(str + base, walk - base)); + } +} + SmartStrStr::SmartStrStr() { std::map > substitutions, substitutionsReverse; std::map downconvert; @@ -179,6 +223,32 @@ const char16_t * SmartStrStr::strStrEnd16(const char16_t * pString, const char16 } } +static bool wordBeginsHere(const char* base, size_t offset) { + if (offset == 0) return true; + for (size_t len = 1; len <= offset && len <= 6; --len) { + unsigned c; + if (pfc::utf8_decode_char(base + offset - len, c) == len) { + return !SmartStrStr::isWordChar(c); + } + } + return false; +} + +const char* SmartStrStr::strStrEndWord(const char* pString, const char* pSubString, size_t* outFoundAt) const { + size_t walk = 0; + for (;;) { + size_t foundAt = 0; + auto end = strStrEnd(pString + walk, pSubString, &foundAt); + if (end == nullptr) return nullptr; + foundAt += walk; + if (!isWordChar(end) && wordBeginsHere(pString, foundAt)) { + if (outFoundAt) *outFoundAt = foundAt; + return end; + } + walk = end - pString; + } +} + bool SmartStrStr::matchOneChar(uint32_t cInput, uint32_t cData) const { if (cInput == cData) return true; auto v = m_substitutions.query_ptr(cData); @@ -191,13 +261,17 @@ pfc::string8 SmartStrStr::transformStr(const char* str) const { } void SmartStrStr::transformStrHere(pfc::string8& out, const char* in) const { - out.prealloc(strlen(in)); + transformStrHere(out, in, strlen(in)); +} + +void SmartStrStr::transformStrHere(pfc::string8& out, const char* in, size_t inLen) const { + out.prealloc(inLen); out.clear(); - for (;; ) { + for (size_t walk = 0; walk < inLen; ) { unsigned c; - size_t d = pfc::utf8_decode_char(in, c); - if (d == 0) break; - in += d; + size_t d = pfc::utf8_decode_char(in + walk, c); + if (d == 0 || walk+d>inLen) break; + walk += d; const char* alt = m_twoCharMappings.query(c); if (alt != nullptr) { out << alt; continue; @@ -357,10 +431,24 @@ void SmartStrFilter::init(const char* ptr, size_t len) { bool SmartStrFilter::test_disregardCounts(const char* src) const { if (m_items.size() == 0) return false; - auto& dc = SmartStrStr::global(); + for (auto& walk : m_items) { + if (!dc->strStrEnd(src, walk.first.c_str())) return false; + } + return true; +} + +bool SmartStrFilter::testWords(const char* src) const { + if (m_items.size() == 0) return false; for (auto& walk : m_items) { - if (!dc.strStrEnd(src, walk.first.c_str())) return false; + const t_size count = walk.second; + const std::string& str = walk.first; + const char* strWalk = src; + for (t_size walk = 0; walk < count; ++walk) { + const char* next = dc->strStrEndWord(strWalk, str.c_str()); + if (next == nullptr) return false; + strWalk = next; + } } return true; } @@ -369,14 +457,18 @@ bool SmartStrFilter::test(const char* src) const { if (m_items.size() == 0) return false; - auto& dc = SmartStrStr::global(); - + // Use the faster routine first, it can't be used to count occurances but nobody really knows about this feature + for (auto& walk : m_items) { + if (!dc->testSubstring(src, walk.first.c_str())) return false; + } + // Have any items where specific number of occurances is wanted? for (auto & walk : m_items) { const t_size count = walk.second; + if (count == 1) continue; const std::string& str = walk.first; const char* strWalk = src; for (t_size walk = 0; walk < count; ++walk) { - const char* next = dc.strStrEnd(strWalk, str.c_str()); + const char* next = dc->strStrEnd(strWalk, str.c_str()); if (next == nullptr) return false; strWalk = next; } diff --git a/3rdparty/foo_SDK/pfc/SmartStrStr.h b/3rdparty/foo_SDK/pfc/SmartStrStr.h index 6a1fc19e..073a5721 100644 --- a/3rdparty/foo_SDK/pfc/SmartStrStr.h +++ b/3rdparty/foo_SDK/pfc/SmartStrStr.h @@ -9,8 +9,6 @@ //! Implementation of string matching for search purposes, such as media library search or typefind in list views. \n //! Inspired by Unicode asymetic search, but not strictly implementing the Unicode asymetric search specifications. \n -//! Bootstraps its character mapping data from various Win32 API methods, requires no externally provided character mapping data. \n -//! Windows-only code. \n //! \n //! Keeping a global instance of it is recommended, due to one time init overhead. \n //! Thread safety: safe to call concurrently once constructed. @@ -19,10 +17,17 @@ class SmartStrStr { public: SmartStrStr(); + static bool isWordChar(unsigned c); + static bool isWordChar(const char* ptr); + static bool isValidWord(const char*); + static void findWords(const char*, std::function); + //! Returns ptr to the end of the string if positive (for continuing search), nullptr if negative. const char * strStrEnd(const char * pString, const char * pSubString, size_t * outFoundAt = nullptr) const; const char16_t * strStrEnd16(const char16_t * pString, const char16_t * pSubString, size_t * outFoundAt = nullptr) const; + const char* strStrEndWord(const char* pString, const char* pSubString, size_t* outFoundAt = nullptr) const; + bool testSubstring( const char * str, const char * sub ) const; bool testSubstring16( const char16_t * str, const char16_t * sub ) const; #ifdef _WIN32 @@ -46,6 +51,7 @@ class SmartStrStr { pfc::string8 transformStr(const char * str) const; void transformStrHere(pfc::string8& out, const char* in) const; + void transformStrHere(pfc::string8& out, const char* in, size_t inLen) const; private: bool testSubString_prefix(const char* str, const char* sub, const char * prefix, size_t prefixLen) const; bool testSubString_prefix(const char* str, const char* sub, uint32_t c) const; @@ -67,11 +73,11 @@ class SmartStrStr { class SmartStrFilter { - typedef std::map t_stringlist; - t_stringlist m_items; - public: + typedef std::map t_stringlist; SmartStrFilter() { } + SmartStrFilter(t_stringlist const& arg) : m_items(arg) {} + SmartStrFilter(t_stringlist&& arg) : m_items(std::move(arg)) {} SmartStrFilter(const char* p) { init(p, strlen(p)); } SmartStrFilter(const char* p, size_t l) { init(p, l); } @@ -79,5 +85,13 @@ class SmartStrFilter { void init(const char* ptr, size_t len); bool test(const char* src) const; + bool testWords(const char* src) const; bool test_disregardCounts(const char* src) const; + + const t_stringlist& items() const { return m_items; } + operator bool() const { return !m_items.empty(); } + bool empty() const { return m_items.empty(); } +private: + t_stringlist m_items; + SmartStrStr * dc = &SmartStrStr::global(); }; diff --git a/3rdparty/foo_SDK/pfc/audio_math.cpp b/3rdparty/foo_SDK/pfc/audio_math.cpp index 1a731d28..46faaf34 100644 --- a/3rdparty/foo_SDK/pfc/audio_math.cpp +++ b/3rdparty/foo_SDK/pfc/audio_math.cpp @@ -28,11 +28,21 @@ static const bool haveAVX = pfc::query_cpu_feature_set(pfc::CPU_HAVE_AVX); #endif -#if defined( __aarch64__ ) || defined( __ARM_NEON__ ) || defined( _M_ARM64) || defined( _M_ARM64EC ) +#if defined( __aarch64__ ) || defined( _M_ARM64) || defined( _M_ARM64EC ) +#define AUDIO_MATH_ARM64 +#endif + +#if defined( AUDIO_MATH_ARM64 ) || defined( __ARM_NEON__ ) #define AUDIO_MATH_NEON #include #endif + +#if defined( AUDIO_MATH_ARM64 ) && !defined( __ANDROID__ ) +// Don't do Neon float64 on Android, crashes clang from NDK 25 +#define AUDIO_MATH_NEON_FLOAT64 +#endif + template inline static float_t noopt_calculate_peak(const float_t *p_src, t_size p_num) { float_t peak = 0; @@ -95,9 +105,9 @@ inline static void noopt_convert(const in_t* in, out_t* out, size_t count) { for (size_t walk = 0; walk < count; ++walk) out[walk] = (out_t)in[walk]; } -#if defined(AUDIO_MATH_NEON) +#ifdef AUDIO_MATH_NEON -#if defined(__aarch64__) || defined(_M_ARM64) || defined(_M_ARM64EC) +#ifdef AUDIO_MATH_ARM64 #define _vmaxvq_f32_wrap vmaxvq_f32 #else inline float _vmaxvq_f32_wrap( float32x4_t arg ) { @@ -229,7 +239,7 @@ inline static void neon_convert_from_int16(const t_int16 * __restrict p_source,t noopt_convert_from_int16( p_source, rem, p_output, p_scale ); } - +#ifdef AUDIO_MATH_NEON_FLOAT64 inline static void neon_convert_to_int16(const double* __restrict p_source, t_size p_count, int16_t* __restrict p_output, double p_scale) { size_t num = p_count / 4; @@ -255,8 +265,8 @@ inline static void neon_convert_to_int16(const double* __restrict p_source, t_si } noopt_convert_to_16bit(p_source, rem, p_output, p_scale); - } + inline static void neon_convert_from_int16(const t_int16* __restrict p_source, t_size p_count, double* __restrict p_output, double p_scale) { size_t num = p_count / 4; @@ -280,7 +290,9 @@ inline static void neon_convert_from_int16(const t_int16* __restrict p_source, t noopt_convert_from_int16(p_source, rem, p_output, p_scale); } -#endif +#endif // AUDIO_MATH_NEON_FLOAT64 + +#endif // AUDIO_MATH_NEON #if defined(AUDIO_MATH_SSE) @@ -776,7 +788,7 @@ namespace pfc { { convert_to_16bit_sse2(p_source, p_count, p_output, scale); } -#elif defined( AUDIO_MATH_NEON ) +#elif defined( AUDIO_MATH_NEON_FLOAT64 ) neon_convert_to_int16(p_source, p_count, p_output, scale); #else noopt_convert_to_16bit(p_source, p_count, p_output, scale); @@ -807,7 +819,7 @@ namespace pfc { { convert_from_int16_sse2(p_source, p_count, p_output, scale); } -#elif defined( AUDIO_MATH_NEON ) +#elif defined( AUDIO_MATH_NEON_FLOAT64 ) neon_convert_from_int16(p_source, p_count, p_output, scale); #else noopt_convert_from_int16(p_source, p_count, p_output, scale); diff --git a/3rdparty/foo_SDK/pfc/audio_sample.cpp b/3rdparty/foo_SDK/pfc/audio_sample.cpp index 36172e18..9753f43d 100644 --- a/3rdparty/foo_SDK/pfc/audio_sample.cpp +++ b/3rdparty/foo_SDK/pfc/audio_sample.cpp @@ -4,26 +4,26 @@ #include "byte_order.h" namespace pfc { - float audio_math::decodeFloat24ptr(const void * sourcePtr) { + float audio_math::decodeFloat24ptr(const void* sourcePtr) { PFC_STATIC_ASSERT(pfc::byte_order_is_little_endian); union { uint8_t bytes[4]; float v; } u; - const uint8_t * s = reinterpret_cast(sourcePtr); + const uint8_t* s = reinterpret_cast(sourcePtr); u.bytes[0] = 0; u.bytes[1] = s[0]; u.bytes[2] = s[1]; u.bytes[3] = s[2]; return u.v; } - float audio_math::decodeFloat24ptrbs(const void * sourcePtr) { + float audio_math::decodeFloat24ptrbs(const void* sourcePtr) { PFC_STATIC_ASSERT(pfc::byte_order_is_little_endian); union { uint8_t bytes[4]; float v; } u; - const uint8_t * s = reinterpret_cast(sourcePtr); + const uint8_t* s = reinterpret_cast(sourcePtr); u.bytes[0] = 0; u.bytes[1] = s[2]; u.bytes[2] = s[1]; @@ -36,36 +36,36 @@ namespace pfc { const unsigned widthBits = 16; typedef uint16_t source_t; - /* typedef uint64_t out_t; typedef double retval_t; - enum { - outExponent = 11, - outFraction = 52, - outExponentShift = (1 << (outExponent-1))-1 - };*/ + /* typedef uint64_t out_t; typedef double retval_t; + enum { + outExponent = 11, + outFraction = 52, + outExponentShift = (1 << (outExponent-1))-1 + };*/ typedef uint32_t out_t; typedef float retval_t; - enum { - outExponent = 8, - outFraction = 23, - outExponentShift = (1 << (outExponent-1))-1 + enum { + outExponent = 8, + outFraction = 23, + outExponentShift = (1 << (outExponent - 1)) - 1 }; const unsigned exponentBits = widthBits - fractionBits - 1; // 1 bit sign | exponent | fraction - source_t fraction = source & (((source_t)1 << fractionBits)-1); + source_t fraction = source & (((source_t)1 << fractionBits) - 1); source >>= fractionBits; - int exponent = (int)( source & (((source_t)1 << exponentBits)-1) ) - (int)((1 << (exponentBits-1))-1); + int exponent = (int)(source & (((source_t)1 << exponentBits) - 1)) - (int)((1 << (exponentBits - 1)) - 1); source >>= exponentBits; if (outExponent + outExponentShift <= 0) return 0; - out_t output = (out_t)( source&1 ); + out_t output = (out_t)(source & 1); output <<= outExponent; - output |= (unsigned) (exponent + outExponentShift) & ( (1<> -shift); - else output |= (out_t) (fraction << shift); + int shift = (int)outFraction - (int)fractionBits; + if (shift < 0) output |= (out_t)(fraction >> -shift); + else output |= (out_t)(fraction << shift); return *(retval_t*)&output / pfc::audio_math::float16scale; } diff --git a/3rdparty/foo_SDK/pfc/audio_sample.h b/3rdparty/foo_SDK/pfc/audio_sample.h index 5f4a5aec..bfcaf5c8 100644 --- a/3rdparty/foo_SDK/pfc/audio_sample.h +++ b/3rdparty/foo_SDK/pfc/audio_sample.h @@ -61,13 +61,13 @@ namespace pfc { static inline double gain_to_scale(double p_gain) { return pow(10.0, p_gain / 20.0); } static inline double scale_to_gain(double scale) { return 20.0*log10(scale); } + static unsigned bitrate_kbps( uint64_t fileSize, double duration ); + static constexpr float float16scale = 65536.f; - static float decodeFloat24ptr(const void * sourcePtr); - static float decodeFloat24ptrbs(const void * sourcePtr); + static float decodeFloat24ptr(const void* sourcePtr); + static float decodeFloat24ptrbs(const void* sourcePtr); static float decodeFloat16(uint16_t source); - - static unsigned bitrate_kbps( uint64_t fileSize, double duration ); }; // class audio_math } // namespace pfc diff --git a/3rdparty/foo_SDK/pfc/bigmem.cpp b/3rdparty/foo_SDK/pfc/bigmem.cpp index d7e79ae5..a9ebc17b 100644 --- a/3rdparty/foo_SDK/pfc/bigmem.cpp +++ b/3rdparty/foo_SDK/pfc/bigmem.cpp @@ -23,7 +23,7 @@ namespace pfc { m_data.set_size(0); m_size = 0; } - void bigmem::read(void* ptrOut, size_t bytes, size_t offset) { + void bigmem::read(void* ptrOut, size_t bytes, size_t offset) const { PFC_ASSERT(offset + bytes <= size()); uint8_t* outWalk = (uint8_t*)ptrOut; while (bytes > 0) { diff --git a/3rdparty/foo_SDK/pfc/bigmem.h b/3rdparty/foo_SDK/pfc/bigmem.h index 58d9481d..ff2392be 100644 --- a/3rdparty/foo_SDK/pfc/bigmem.h +++ b/3rdparty/foo_SDK/pfc/bigmem.h @@ -12,7 +12,7 @@ namespace pfc { void resize(size_t newSize); size_t size() const {return m_size;} void clear(); - void read(void * ptrOut, size_t bytes, size_t offset); + void read(void * ptrOut, size_t bytes, size_t offset) const; void write(const void * ptrIn, size_t bytes, size_t offset); uint8_t * _slicePtr(size_t which); size_t _sliceCount(); diff --git a/3rdparty/foo_SDK/pfc/charDownConvert.cpp b/3rdparty/foo_SDK/pfc/charDownConvert.cpp index a49f18d2..3ca39aba 100644 --- a/3rdparty/foo_SDK/pfc/charDownConvert.cpp +++ b/3rdparty/foo_SDK/pfc/charDownConvert.cpp @@ -81,44 +81,49 @@ namespace pfc { size_t CharDownConvert::numMappings() { return std::size(g_mappings); } CharDownConvert::CharDownConvert() { + std::map charConvertMap; + for (auto& l : g_mappings) { - m_charConvertMap[(uint32_t)l.from] = (uint32_t)l.to; + charConvertMap[(uint32_t)l.from] = (uint32_t)l.to; + } + for (auto& line : twoCharMappings) { + charConvertMap[line.from] = line.to; } - g_charConvertMapInit_AddBullshitExceptions(); + + m_charConvertMap.initialize(std::move(charConvertMap)); } void CharDownConvert::TransformCharCachedAppend(t_uint32 c, pfc::string_base& out) { - auto subst = m_charConvertMap.find(c); - if (subst != m_charConvertMap.end()) { - out << subst->second.ptr(); + auto subst = m_charConvertMap.query_ptr(c); + if (subst != nullptr) { + out << subst->ptr(); } else { out.add_char(c); } } + void CharDownConvert::TransformStringHere(pfc::string_base& out, const char* src, size_t len) { + out.reset(); this->TransformStringAppend(out, src, len); + } - void CharDownConvert::TransformStringAppend(pfc::string_base& out, const char* src) { - for (;;) { - char c = *src; + void CharDownConvert::TransformStringAppend(pfc::string_base& out, const char* src, size_t len) { + size_t walk = 0; + while(walk < len) { + char c = src[walk]; if (c > 0) { out.add_byte(pfc::ascii_tolower_lookup(c)); - ++src; + ++walk; } else if (c == 0) { break; } else { unsigned c; t_size d; - d = pfc::utf8_decode_char(src, c); + d = pfc::utf8_decode_char(src + walk, c, len - walk); if (d == 0) break; TransformCharCachedAppend(c, out); - src += d; + walk += d; } } } - void CharDownConvert::g_charConvertMapInit_AddBullshitExceptions() { - for (auto& line : twoCharMappings) { - m_charConvertMap[line.from] = line.to; - } - } CharDownConvert& CharDownConvert::instance() { static CharDownConvert obj; return obj; } diff --git a/3rdparty/foo_SDK/pfc/charDownConvert.h b/3rdparty/foo_SDK/pfc/charDownConvert.h index 1cf825d7..536acda4 100644 --- a/3rdparty/foo_SDK/pfc/charDownConvert.h +++ b/3rdparty/foo_SDK/pfc/charDownConvert.h @@ -1,10 +1,8 @@ #pragma once #include "string_base.h" -#include - -// This converts to ASCII *and* lowercases for matching -// Legacy feature, do not use in new code +#include "fixed_map.h" +// This converts to ASCII *and* lowercases for simplified search matching namespace pfc { class CharStorage { public: @@ -35,7 +33,8 @@ namespace pfc { CharDownConvert(); void TransformCharCachedAppend(t_uint32 c, pfc::string_base& out); - void TransformStringAppend(pfc::string_base& out, const char* src); + void TransformStringAppend(pfc::string_base& out, const char* src, size_t len = SIZE_MAX); + void TransformStringHere(pfc::string_base& out, const char* src, size_t len = SIZE_MAX); string8 TransformString(const char* src) { pfc::string8 ret; TransformStringAppend(ret, src); return ret; } void TransformString(pfc::string_base& out, const char* src) { out.reset(); TransformStringAppend(out, src); @@ -50,10 +49,6 @@ namespace pfc { static size_t numMappings(); private: - - void g_charConvertMapInit_AddBullshitExceptions(); - private: - std::map m_charConvertMap; + fixed_map m_charConvertMap; }; } - diff --git a/3rdparty/foo_SDK/pfc/cpuid.cpp b/3rdparty/foo_SDK/pfc/cpuid.cpp index 19d0eaee..9fff5c5f 100644 --- a/3rdparty/foo_SDK/pfc/cpuid.cpp +++ b/3rdparty/foo_SDK/pfc/cpuid.cpp @@ -64,16 +64,8 @@ namespace pfc { namespace pfc { const char* cpuArch() { -#ifdef _M_ARM64EC - return "ARM64EC"; -#elif defined(_M_X64) || defined(__x86_64__) - return "x64"; -#elif defined(_M_IX86) || defined(__i386__) - return "x86"; -#elif defined(_M_ARM64) || defined(__aarch64__) - return "ARM64"; -#elif defined(_M_ARM) || defined(__arm__) - return "ARM"; +#ifdef PFC_CPU_ARCH + return PFC_CPU_ARCH; #else return "Unknown"; #endif diff --git a/3rdparty/foo_SDK/pfc/cpuid.h b/3rdparty/foo_SDK/pfc/cpuid.h index 1c7bd8f7..4757cbd9 100644 --- a/3rdparty/foo_SDK/pfc/cpuid.h +++ b/3rdparty/foo_SDK/pfc/cpuid.h @@ -24,4 +24,16 @@ namespace pfc { namespace pfc { const char* cpuArch(); -} \ No newline at end of file +} + +#ifdef _M_ARM64EC +#define PFC_CPU_ARCH "ARM64EC" +#elif defined(_M_X64) || defined(__x86_64__) +#define PFC_CPU_ARCH "x64" +#elif defined(_M_IX86) || defined(__i386__) +#define PFC_CPU_ARCH "x86" +#elif defined(_M_ARM64) || defined(__aarch64__) +#define PFC_CPU_ARCH "ARM64" +#elif defined(_M_ARM) || defined(__arm__) +#define PFC_CPU_ARCH "ARM" +#endif diff --git a/3rdparty/foo_SDK/pfc/debug.h b/3rdparty/foo_SDK/pfc/debug.h index 6d014677..f7fb1ee8 100644 --- a/3rdparty/foo_SDK/pfc/debug.h +++ b/3rdparty/foo_SDK/pfc/debug.h @@ -42,3 +42,9 @@ namespace pfc { #define PFC_SET_THREAD_DESCRIPTION(X) { ::pfc::setCurrentThreadDescription(X); } #define PFC_SET_THREAD_DESCRIPTION_SUPPORTED + +#if PFC_DEBUG +#define PFC_DEBUG_PRINT(...) ::pfc::outputDebugLine(pfc::format(__VA_ARGS__)) +#else +#define PFC_DEBUG_PRINT(...) +#endif \ No newline at end of file diff --git a/3rdparty/foo_SDK/pfc/filetimetools.cpp b/3rdparty/foo_SDK/pfc/filetimetools.cpp new file mode 100644 index 00000000..810d7374 --- /dev/null +++ b/3rdparty/foo_SDK/pfc/filetimetools.cpp @@ -0,0 +1,330 @@ +#include "pfc-lite.h" + +#include "filetimetools.h" + +#include "timers.h" + +#include + +namespace { + class exception_time_error {}; +} + +using namespace pfc; + +#ifndef _WIN32 +namespace { + typedef uint16_t WORD; + + typedef struct _SYSTEMTIME { + WORD wYear; + WORD wMonth; + WORD wDayOfWeek; + WORD wDay; + WORD wHour; + WORD wMinute; + WORD wSecond; + WORD wMilliseconds; + } SYSTEMTIME, * PSYSTEMTIME, * LPSYSTEMTIME; + +} +static void SystemTimeToNix(const SYSTEMTIME& st, struct tm& Time) { + memset(&Time, 0, sizeof(Time)); + Time.tm_sec = st.wSecond; + Time.tm_min = st.wMinute; + Time.tm_hour = st.wHour; + Time.tm_mday = st.wDay; + Time.tm_mon = st.wMonth - 1; + Time.tm_year = st.wYear - 1900; +} + +static t_filetimestamp ExportSystemTime(const SYSTEMTIME& st) { + struct tm Time; + SystemTimeToNix(st, Time); + return pfc::fileTimeUtoW(mktime(&Time)); +} + +static t_filetimestamp ExportSystemTimeLocal(const SYSTEMTIME& st) { + struct tm Time, Local; + SystemTimeToNix(st, Time); + time_t t = mktime(&Time); + localtime_r(&t, &Local); + return pfc::fileTimeUtoW(mktime(&Local)); +} +static void SystemTimeFromNix(SYSTEMTIME& st, struct tm const& Time) { + memset(&st, 0, sizeof(st)); + st.wSecond = Time.tm_sec; + st.wMinute = Time.tm_min; + st.wHour = Time.tm_hour; + st.wDay = Time.tm_mday; + st.wDayOfWeek = Time.tm_wday; + st.wMonth = Time.tm_mon + 1; + st.wYear = Time.tm_year + 1900; +} + +static bool MakeSystemTime(SYSTEMTIME& st, t_filetimestamp ts) { + time_t t = (time_t)pfc::fileTimeWtoU(ts); + struct tm Time; + if (gmtime_r(&t, &Time) == NULL) return false; + SystemTimeFromNix(st, Time); + return true; +} + +static bool MakeSystemTimeLocal(SYSTEMTIME& st, t_filetimestamp ts) { + time_t t = (time_t)pfc::fileTimeWtoU(ts); + struct tm Time; + if (localtime_r(&t, &Time) == NULL) return false; + SystemTimeFromNix(st, Time); + return true; +} + +#else +static t_filetimestamp ExportSystemTime(const SYSTEMTIME& st) { + t_filetimestamp base; + if (!SystemTimeToFileTime(&st, (FILETIME*)&base)) throw exception_time_error(); + return base; +} +static t_filetimestamp ExportSystemTimeLocal(const SYSTEMTIME& st) { +#ifdef FOOBAR2000_DESKTOP_WINDOWS + t_filetimestamp base, out; + if (!SystemTimeToFileTime(&st, (FILETIME*)&base)) throw exception_time_error(); + if (!LocalFileTimeToFileTime((const FILETIME*)&base, (FILETIME*)&out)) throw exception_time_error(); + return out; +#else + SYSTEMTIME UTC; + if (!TzSpecificLocalTimeToSystemTime(NULL, &st, &UTC)) throw exception_time_error(); + return ExportSystemTime(UTC); +#endif +} +static bool MakeSystemTime(SYSTEMTIME& st, t_filetimestamp ts) { + if (ts == filetimestamp_invalid) return false; + return !!FileTimeToSystemTime((const FILETIME*)&ts, &st); + +} +static bool MakeSystemTimeLocal(SYSTEMTIME& st, t_filetimestamp ts) { + if (ts == filetimestamp_invalid) return false; +#ifdef FOOBAR2000_DESKTOP_WINDOWS + FILETIME ft; + if (FileTimeToLocalFileTime((FILETIME*)&ts, &ft)) { + if (FileTimeToSystemTime(&ft, &st)) { + return true; + } + } + return false; +#else + SYSTEMTIME UTC; + if (FileTimeToSystemTime((FILETIME*)&ts, &UTC)) { + if (SystemTimeToTzSpecificLocalTime(NULL, &UTC, &st)) return true; + } + return false; +#endif +} +#endif // _WIN32 + +static bool is_spacing(char c) { return c == ' ' || c == 10 || c == 13 || c == '\t'; } + +static unsigned ParseDateElem(const char* ptr, t_size len) { + unsigned ret = 0; + for (t_size walk = 0; walk < len; ++walk) { + const char c = ptr[walk]; + if (c < '0' || c > '9') throw exception_time_error(); + ret = ret * 10 + (unsigned)(c - '0'); + } + return ret; +} + +static bool st_sanity(SYSTEMTIME const& st) { + return st.wYear >= 1601 && st.wMonth >= 1 && st.wMonth <= 12 && st.wDay >= 1 && st.wDay <= 31 && st.wHour < 24 && st.wMinute < 60 && st.wSecond < 60 && st.wMilliseconds < 1000; +} +static t_filetimestamp filetimestamp_from_string_internal(const char* date, bool local) { + // Accepted format + // YYYY-MM-DD HH:MM:SS + try { + SYSTEMTIME st = {}; + st.wDay = 1; st.wMonth = 1; + + unsigned walk = 0; + auto worker = [&](unsigned n) { + auto ret = ParseDateElem(date + walk, n); + walk += n; + if (ret > UINT16_MAX) throw exception_time_error(); + return (WORD)ret;; + }; + + auto skip = [&](char c) { + if (date[walk] == c) ++walk; + }; + + auto skipSpacing = [&] { + while (is_spacing(date[walk])) ++walk; + }; + skipSpacing(); + st.wYear = worker(4); + skip('-'); + st.wMonth = worker(2); + skip('-'); + st.wDay = worker(2); + skipSpacing(); + st.wHour = worker(2); + skip(':'); + st.wMinute = worker(2); + skip(':'); + st.wSecond = worker(2); + if (date[walk] == '.') { + double v = pfc::string_to_float(date + walk); + st.wMilliseconds = (WORD)floor(v * 1000.f); // don't ever round up, don't want to handle ms of 1000 + } + + if (!st_sanity(st)) throw exception_time_error(); + + if (local) { + return ExportSystemTimeLocal(st); + } else { + return ExportSystemTime(st); + } + } catch (exception_time_error) { + return filetimestamp_invalid; + } +} + +namespace pfc { + t_filetimestamp filetimestamp_from_string(const char* date) { + return filetimestamp_from_string_internal(date, true); + } + + t_filetimestamp filetimestamp_from_string_utc(const char* date) { + return filetimestamp_from_string_internal(date, false); + } + + static constexpr char g_invalidMsg[] = ""; + + pfc::string_formatter format_filetimestamp(t_filetimestamp p_timestamp) { + try { + SYSTEMTIME st; + if (MakeSystemTimeLocal(st, p_timestamp)) { + pfc::string_formatter buffer; + buffer + << pfc::format_uint(st.wYear, 4) << "-" << pfc::format_uint(st.wMonth, 2) << "-" << pfc::format_uint(st.wDay, 2) << " " + << pfc::format_uint(st.wHour, 2) << ":" << pfc::format_uint(st.wMinute, 2) << ":" << pfc::format_uint(st.wSecond, 2); + return buffer; + } + } catch (...) {} + return g_invalidMsg; + } + + pfc::string_formatter format_filetimestamp_ms(t_filetimestamp p_timestamp) { + try { + SYSTEMTIME st; + if (MakeSystemTimeLocal(st, p_timestamp)) { + pfc::string_formatter buffer; + buffer + << pfc::format_uint(st.wYear, 4) << "-" << pfc::format_uint(st.wMonth, 2) << "-" << pfc::format_uint(st.wDay, 2) << " " + << pfc::format_uint(st.wHour, 2) << ":" << pfc::format_uint(st.wMinute, 2) << ":" << pfc::format_uint(st.wSecond, 2) << "." << pfc::format_uint(st.wMilliseconds, 3); + return buffer; + } + } catch (...) {} + return g_invalidMsg; + } + + pfc::string_formatter format_filetimestamp_utc(t_filetimestamp p_timestamp) { + try { + SYSTEMTIME st; + if (MakeSystemTime(st, p_timestamp)) { + pfc::string_formatter buffer; + buffer + << pfc::format_uint(st.wYear, 4) << "-" << pfc::format_uint(st.wMonth, 2) << "-" << pfc::format_uint(st.wDay, 2) << " " + << pfc::format_uint(st.wHour, 2) << ":" << pfc::format_uint(st.wMinute, 2) << ":" << pfc::format_uint(st.wSecond, 2); + return buffer; + } + } catch (...) {} + return g_invalidMsg; + } + +} // namespace foobar2000_io + +namespace { + struct dateISO_t { + unsigned Y, M, D; + unsigned h, m, s; + double sfrac; + int tzdelta; + }; + + dateISO_t read_ISO_8601(const char* dateISO) { + dateISO_t ret = {}; + // 2022-01-26T13:44:51.200000Z + // 2010-02-19T14:54:23.031+08:00 + // 2022-01-27T11:01:49+00:00 + // 2022-01-27T11:01:49Z + // 20220127T110149Z + + unsigned walk = 0; + auto worker = [&](unsigned n) { + auto ret = ParseDateElem(dateISO + walk, n); + walk += n; + return ret; + }; + auto skip = [&](char c) { + if (dateISO[walk] == c) ++walk; + }; + auto expect = [&](char c) { + if (dateISO[walk] != c) throw exception_time_error(); + ++walk; + }; + ret.Y = worker(4); + skip('-'); + ret.M = worker(2); + skip('-'); + ret.D = worker(2); + expect('T'); + ret.h = worker(2); + skip(':'); + ret.m = worker(2); + skip(':'); + ret.s = worker(2); + if (dateISO[walk] == '.') { + unsigned base = walk; + ++walk; + while (pfc::char_is_numeric(dateISO[walk])) ++walk; + ret.sfrac = pfc::string_to_float(dateISO + base, walk - base); + } + if (dateISO[walk] == '+' || dateISO[walk] == '-') { + bool neg = dateISO[walk] == '-'; + ++walk; + unsigned tz_h = worker(2); + if (tz_h >= 24) throw exception_time_error(); + skip(':'); + unsigned tz_m = worker(2); + if (tz_m >= 60) throw exception_time_error(); + tz_m += tz_h * 60; + ret.tzdelta = neg ? (int)tz_m : -(int)tz_m; // reversed! it's a timezone offset, have to *add* it if timezone has a minus + } + return ret; + } +} + +t_filetimestamp pfc::filetimestamp_from_string_ISO_8601(const char* dateISO) { + try { + auto elems = read_ISO_8601(dateISO); + + SYSTEMTIME st = {}; + st.wDay = 1; st.wMonth = 1; + st.wYear = elems.Y; + st.wMonth = elems.M; + st.wDay = elems.D; + st.wHour = elems.h; + st.wMinute = elems.m; + st.wSecond = elems.s; + st.wMilliseconds = (WORD)floor(elems.sfrac * 1000.f); + + if (!st_sanity(st)) throw exception_time_error(); + + auto ret = ExportSystemTime(st); + + ret += filetimestamp_1second_increment * elems.tzdelta * 60; + + return ret; + } catch (...) { + return filetimestamp_invalid; + } +} diff --git a/3rdparty/foo_SDK/pfc/filetimetools.h b/3rdparty/foo_SDK/pfc/filetimetools.h new file mode 100644 index 00000000..c7af5aa9 --- /dev/null +++ b/3rdparty/foo_SDK/pfc/filetimetools.h @@ -0,0 +1,20 @@ +#pragma once + +namespace pfc { + typedef uint64_t t_filetimestamp; + static constexpr t_filetimestamp filetimestamp_invalid = 0; + static constexpr t_filetimestamp filetimestamp_1second_increment = 10000000; + + t_filetimestamp filetimestamp_from_string(const char * date); + t_filetimestamp filetimestamp_from_string_utc(const char* date); + // From ISO 8601 time + t_filetimestamp filetimestamp_from_string_ISO_8601(const char* date); + + //! Warning: this formats according to system timezone settings, created strings should be used for display only, never for storage. + pfc::string_formatter format_filetimestamp(t_filetimestamp p_timestamp); + //! UTC timestamp + pfc::string_formatter format_filetimestamp_utc(t_filetimestamp p_timestamp); + //! Local timestamp with milliseconds + pfc::string_formatter format_filetimestamp_ms(t_filetimestamp p_timestamp); + +} diff --git a/3rdparty/foo_SDK/pfc/nix-objects.cpp b/3rdparty/foo_SDK/pfc/nix-objects.cpp index b3012a05..e35ed1c8 100644 --- a/3rdparty/foo_SDK/pfc/nix-objects.cpp +++ b/3rdparty/foo_SDK/pfc/nix-objects.cpp @@ -187,10 +187,11 @@ namespace pfc { return sel.Select( timeOutSeconds ) > 0; } - nix_event::nix_event() { + nix_event::nix_event(bool state) { createPipe( m_fd ); setNonBlocking( m_fd[0] ); setNonBlocking( m_fd[1] ); + if ( state ) set_state(true); } nix_event::~nix_event() { close( m_fd[0] ); diff --git a/3rdparty/foo_SDK/pfc/nix-objects.h b/3rdparty/foo_SDK/pfc/nix-objects.h index d7bc8e67..c795a648 100644 --- a/3rdparty/foo_SDK/pfc/nix-objects.h +++ b/3rdparty/foo_SDK/pfc/nix-objects.h @@ -77,7 +77,7 @@ namespace pfc { class nix_event { public: - nix_event(); + nix_event(bool state = false); ~nix_event(); void set_state( bool state ); diff --git a/3rdparty/foo_SDK/pfc/obj-c.mm b/3rdparty/foo_SDK/pfc/obj-c.mm index a1ca5046..529041f8 100644 --- a/3rdparty/foo_SDK/pfc/obj-c.mm +++ b/3rdparty/foo_SDK/pfc/obj-c.mm @@ -31,21 +31,21 @@ bool isShiftKeyPressed() { #if TARGET_OS_MAC && !TARGET_OS_IPHONE - return ( [NSEvent modifierFlags] & NSShiftKeyMask ) != 0; + return ( [NSEvent modifierFlags] & NSEventModifierFlagShift ) != 0; #else return false; #endif } bool isCtrlKeyPressed() { #if TARGET_OS_MAC && !TARGET_OS_IPHONE - return ( [NSEvent modifierFlags] & NSControlKeyMask ) != 0; + return ( [NSEvent modifierFlags] & NSEventModifierFlagControl ) != 0; #else return false; #endif } bool isAltKeyPressed() { #if TARGET_OS_MAC && !TARGET_OS_IPHONE - return ( [NSEvent modifierFlags] & NSAlternateKeyMask ) != 0; + return ( [NSEvent modifierFlags] & NSEventModifierFlagOption ) != 0; #else return false; #endif @@ -104,5 +104,21 @@ void appleSetThreadDescription( const char * str ) { return ret; } } + + int appleNaturalSortCompare(const char* s1, const char* s2) { + @autoreleasepool { + NSString * str1 = [NSString stringWithUTF8String: s1]; + NSString * str2 = [NSString stringWithUTF8String: s2]; + return (int) [str1 localizedCompare: str2]; + } + } + int appleNaturalSortCompareI(const char* s1, const char* s2) { + @autoreleasepool { + NSString * str1 = [NSString stringWithUTF8String: s1]; + NSString * str2 = [NSString stringWithUTF8String: s2]; + return (int) [str1 localizedCaseInsensitiveCompare: str2]; + } + } + } #endif diff --git a/3rdparty/foo_SDK/pfc/pathUtils.cpp b/3rdparty/foo_SDK/pfc/pathUtils.cpp index 7e9e8297..68db25af 100644 --- a/3rdparty/foo_SDK/pfc/pathUtils.cpp +++ b/3rdparty/foo_SDK/pfc/pathUtils.cpp @@ -80,23 +80,23 @@ const char * charReplaceDefault(char c) { const char * charReplaceModern(char c) { switch (c) { case '*': - return u8"∗"; + return reinterpret_cast( u8"∗" ); case '\"': - return u8"''"; + return reinterpret_cast( u8"''" ); case ':': - return u8"∶"; + return reinterpret_cast( u8"∶" ); case '/': - return u8"\u2215"; + return reinterpret_cast( u8"\u2215" ); case '\\': - return u8"⧵"; + return reinterpret_cast( u8"⧵" ); case '?': - return u8"?"; + return reinterpret_cast( u8"?" ); case '<': - return u8"˂"; + return reinterpret_cast( u8"˂" ); case '>': - return u8"˃"; + return reinterpret_cast( u8"˃" ); case '|': - return u8"∣"; + return reinterpret_cast( u8"∣" ); default: return "_"; } diff --git a/3rdparty/foo_SDK/pfc/pfc-license.txt b/3rdparty/foo_SDK/pfc/pfc-license.txt index 3f05fccd..0ab480d7 100644 --- a/3rdparty/foo_SDK/pfc/pfc-license.txt +++ b/3rdparty/foo_SDK/pfc/pfc-license.txt @@ -1,4 +1,4 @@ -Copyright (C) 2002-2022 Peter Pawlowski +Copyright (C) 2002-2023 Peter Pawlowski This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/3rdparty/foo_SDK/pfc/pfc.vcxproj b/3rdparty/foo_SDK/pfc/pfc.vcxproj index da745180..690992ac 100644 --- a/3rdparty/foo_SDK/pfc/pfc.vcxproj +++ b/3rdparty/foo_SDK/pfc/pfc.vcxproj @@ -666,6 +666,7 @@ + @@ -701,6 +702,7 @@ + @@ -772,6 +774,7 @@ + Disabled Disabled diff --git a/3rdparty/foo_SDK/pfc/pfc.vcxproj.filters b/3rdparty/foo_SDK/pfc/pfc.vcxproj.filters index 9ad32187..d1a820dc 100644 --- a/3rdparty/foo_SDK/pfc/pfc.vcxproj.filters +++ b/3rdparty/foo_SDK/pfc/pfc.vcxproj.filters @@ -97,6 +97,9 @@ Source Files + + Source Files + @@ -348,6 +351,12 @@ Header Files + + Header Files + + + Header Files + diff --git a/3rdparty/foo_SDK/pfc/pfc.xcodeproj/project.pbxproj b/3rdparty/foo_SDK/pfc/pfc.xcodeproj/project.pbxproj new file mode 100644 index 00000000..04e23137 --- /dev/null +++ b/3rdparty/foo_SDK/pfc/pfc.xcodeproj/project.pbxproj @@ -0,0 +1,885 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 0F0794D427C90AA4006BAD7F /* fixed_map.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F0794CF27C90AA4006BAD7F /* fixed_map.h */; }; + 0F0794D527C90AA4006BAD7F /* charDownConvert.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F0794D027C90AA4006BAD7F /* charDownConvert.h */; }; + 0F0794D627C90AA4006BAD7F /* SmartStrStr-table.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F0794D127C90AA4006BAD7F /* SmartStrStr-table.h */; }; + 0F0794D727C90AA4006BAD7F /* charDownConvert.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F0794D227C90AA4006BAD7F /* charDownConvert.cpp */; }; + 0F0794D827C90AA4006BAD7F /* SmartStrStr-twoCharMappings.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F0794D327C90AA4006BAD7F /* SmartStrStr-twoCharMappings.h */; }; + 0F0794D927C90AA8006BAD7F /* charDownConvert.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F0794D227C90AA4006BAD7F /* charDownConvert.cpp */; }; + 0F14904D242E44C300D0BD81 /* notifyList.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F14904C242E44C300D0BD81 /* notifyList.h */; }; + 0F14904F242E44ED00D0BD81 /* autoref.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F14904E242E44ED00D0BD81 /* autoref.h */; }; + 0F149051242E454C00D0BD81 /* weakRef.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F149050242E454C00D0BD81 /* weakRef.h */; }; + 0F2F4BF7250BFF660014812D /* pfc-fb2k-hooks.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F2F4BEF250BFF660014812D /* pfc-fb2k-hooks.h */; }; + 0F2F4BF8250BFF660014812D /* killswitch.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F2F4BF0250BFF660014812D /* killswitch.h */; }; + 0F2F4BF9250BFF660014812D /* pfc-fb2k-hooks.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F2F4BF1250BFF660014812D /* pfc-fb2k-hooks.cpp */; }; + 0F2F4BFA250BFF660014812D /* pfc-fb2k-hooks.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F2F4BF1250BFF660014812D /* pfc-fb2k-hooks.cpp */; }; + 0F2F4BFB250BFF660014812D /* stdsort.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F2F4BF2250BFF660014812D /* stdsort.h */; }; + 0F2F4BFC250BFF660014812D /* suppress_fb2k_hooks.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F2F4BF3250BFF660014812D /* suppress_fb2k_hooks.h */; }; + 0F2F4BFD250BFF660014812D /* platform-objects.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F2F4BF4250BFF660014812D /* platform-objects.h */; }; + 0F2F4BFE250BFF660014812D /* pocket_char_ops.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F2F4BF5250BFF660014812D /* pocket_char_ops.h */; }; + 0F2F4BFF250BFF660014812D /* cmd_thread.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F2F4BF6250BFF660014812D /* cmd_thread.h */; }; + 0F54079726C2964500A118C8 /* splitString2.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FB717E126C295370040D7FE /* splitString2.cpp */; }; + 0F643510253A250600D6335A /* string-conv-lite.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F64350D253A250600D6335A /* string-conv-lite.h */; }; + 0F643511253A250600D6335A /* pp-winapi.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F64350E253A250600D6335A /* pp-winapi.h */; }; + 0F643512253A250600D6335A /* string-conv-lite.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F64350F253A250600D6335A /* string-conv-lite.cpp */; }; + 0F643513253A250600D6335A /* string-conv-lite.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F64350F253A250600D6335A /* string-conv-lite.cpp */; }; + 0F65005525122FD5001B03BA /* string-compare.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F65005125122FD5001B03BA /* string-compare.cpp */; }; + 0F65005625122FD5001B03BA /* string-compare.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F65005125122FD5001B03BA /* string-compare.cpp */; }; + 0F65005725122FD5001B03BA /* string-compare.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F65005225122FD5001B03BA /* string-compare.h */; }; + 0F65005825122FD5001B03BA /* string-part.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F65005325122FD5001B03BA /* string-part.h */; }; + 0F65005925122FD5001B03BA /* string-lite.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F65005425122FD5001B03BA /* string-lite.cpp */; }; + 0F65005A25122FD5001B03BA /* string-lite.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F65005425122FD5001B03BA /* string-lite.cpp */; }; + 0F7A1B6A2A692C88004F89FB /* filetimetools.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F7A1B682A692C88004F89FB /* filetimetools.cpp */; }; + 0F7A1B6B2A692C88004F89FB /* filetimetools.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F7A1B682A692C88004F89FB /* filetimetools.cpp */; }; + 0F7A1B6C2A692C88004F89FB /* filetimetools.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F7A1B692A692C88004F89FB /* filetimetools.h */; }; + 0F7EDDAA27FAFDA5000996AA /* unicode-normalize.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F7EDDA827FAFDA5000996AA /* unicode-normalize.cpp */; }; + 0F7EDDAB27FAFDA5000996AA /* unicode-normalize.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F7EDDA827FAFDA5000996AA /* unicode-normalize.cpp */; }; + 0F7EDDAC27FAFDA5000996AA /* unicode-normalize.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F7EDDA927FAFDA5000996AA /* unicode-normalize.h */; }; + 0FAC031727C8EC6500BA9E97 /* SmartStrStr.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FAC031527C8EC6500BA9E97 /* SmartStrStr.cpp */; }; + 0FAC031827C8EC6500BA9E97 /* SmartStrStr.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FAC031627C8EC6500BA9E97 /* SmartStrStr.h */; }; + 0FAC031927C8EC6A00BA9E97 /* SmartStrStr.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FAC031527C8EC6500BA9E97 /* SmartStrStr.cpp */; }; + 0FB717E226C295370040D7FE /* splitString2.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FB717E026C295370040D7FE /* splitString2.h */; }; + 0FB717E326C295370040D7FE /* splitString2.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FB717E126C295370040D7FE /* splitString2.cpp */; }; + 0FFFAEAE23C9C9580023328B /* crashWithMessage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FFFAEAD23C9C9580023328B /* crashWithMessage.cpp */; }; + 0FFFAEAF23C9DB640023328B /* crashWithMessage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FFFAEAD23C9C9580023328B /* crashWithMessage.cpp */; }; + B10D405B19ADFADB004D2596 /* audio_math.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B1D8A0CD198FB83D00A23435 /* audio_math.cpp */; }; + B10D405C19ADFADB004D2596 /* audio_sample.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B1D8A0CE198FB83D00A23435 /* audio_sample.cpp */; }; + B10D405D19ADFADB004D2596 /* base64.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B1DD35C6198A702E00EF7043 /* base64.cpp */; }; + B10D405E19ADFADB004D2596 /* bit_array.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B1DD35CB198A702E00EF7043 /* bit_array.cpp */; }; + B10D405F19ADFADB004D2596 /* bsearch.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B1DD35CE198A702E00EF7043 /* bsearch.cpp */; }; + B10D406019ADFADB004D2596 /* cpuid.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B1DD35D3198A702E00EF7043 /* cpuid.cpp */; }; + B10D406119ADFADB004D2596 /* filehandle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B1C37D7E19922EF500EE6ABC /* filehandle.cpp */; }; + B10D406219ADFADB004D2596 /* guid.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B1DD35D6198A702E00EF7043 /* guid.cpp */; }; + B10D406319ADFADB004D2596 /* nix-objects.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B1DD35DF198A702E00EF7043 /* nix-objects.cpp */; }; + B10D406419ADFADB004D2596 /* other.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B1DD35E3198A702E00EF7043 /* other.cpp */; }; + B10D406519ADFADB004D2596 /* pathUtils.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B1DD35E5198A702E00EF7043 /* pathUtils.cpp */; }; + B10D406619ADFADB004D2596 /* printf.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B1DD35EA198A702E00EF7043 /* printf.cpp */; }; + B10D406719ADFADB004D2596 /* selftest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B1DD35F0198A702E00EF7043 /* selftest.cpp */; }; + B10D406819ADFADB004D2596 /* sort.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B1DD35F1198A702E00EF7043 /* sort.cpp */; }; + B10D406919ADFADB004D2596 /* stdafx.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B1DD35F3198A702E00EF7043 /* stdafx.cpp */; }; + B10D406A19ADFADB004D2596 /* string_base.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B1DD35F7198A702E00EF7043 /* string_base.cpp */; }; + B10D406B19ADFADB004D2596 /* string_conv.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B1DD35F4198A702E00EF7043 /* string_conv.cpp */; }; + B10D406D19ADFADB004D2596 /* synchro_nix.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B1DD35FD198A702E00EF7043 /* synchro_nix.cpp */; }; + B10D406E19ADFADB004D2596 /* threads.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B1DD3600198A702E00EF7043 /* threads.cpp */; }; + B10D406F19ADFADB004D2596 /* timers.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B1DD35EB198A702E00EF7043 /* timers.cpp */; }; + B10D407019ADFADB004D2596 /* utf8.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B1DD3603198A702E00EF7043 /* utf8.cpp */; }; + B10D407119ADFADB004D2596 /* wildcard.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B1B502D3198FF75000525EAF /* wildcard.cpp */; }; + B10D407219ADFADB004D2596 /* win-objects.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B1DD3604198A702E00EF7043 /* win-objects.cpp */; }; + B10D407319ADFE52004D2596 /* obj-c.mm in Sources */ = {isa = PBXBuildFile; fileRef = B1DD35E1198A702E00EF7043 /* obj-c.mm */; }; + B125C8AD1F46D9A900ADB97B /* once.h in Headers */ = {isa = PBXBuildFile; fileRef = B125C8AC1F46D9A900ADB97B /* once.h */; }; + B12CBBC81BD4D96A00952805 /* bigmem.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B12CBBC61BD4D96A00952805 /* bigmem.cpp */; }; + B12CBBC91BD4D96A00952805 /* bigmem.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B12CBBC61BD4D96A00952805 /* bigmem.cpp */; }; + B12CBBCA1BD4D96A00952805 /* bigmem.h in Headers */ = {isa = PBXBuildFile; fileRef = B12CBBC71BD4D96A00952805 /* bigmem.h */; }; + B16695F719ACC12A0001728F /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B16695F619ACC12A0001728F /* Foundation.framework */; }; + B17EB26E1E85358D0057E2A4 /* pool.h in Headers */ = {isa = PBXBuildFile; fileRef = B17EB26B1E85358D0057E2A4 /* pool.h */; }; + B17EB26F1E85358D0057E2A4 /* splitString.h in Headers */ = {isa = PBXBuildFile; fileRef = B17EB26C1E85358D0057E2A4 /* splitString.h */; }; + B17EB2701E85358D0057E2A4 /* wait_queue.h in Headers */ = {isa = PBXBuildFile; fileRef = B17EB26D1E85358D0057E2A4 /* wait_queue.h */; }; + B1B502D5198FF75000525EAF /* wildcard.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B1B502D3198FF75000525EAF /* wildcard.cpp */; }; + B1B502D6198FF75000525EAF /* wildcard.h in Headers */ = {isa = PBXBuildFile; fileRef = B1B502D4198FF75000525EAF /* wildcard.h */; }; + B1C37D7F19922EF500EE6ABC /* filehandle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B1C37D7E19922EF500EE6ABC /* filehandle.cpp */; }; + B1CF88B71BD6657F00F42F87 /* fpu.h in Headers */ = {isa = PBXBuildFile; fileRef = B1CF88B41BD6657F00F42F87 /* fpu.h */; }; + B1CF88B81BD6657F00F42F87 /* mem_block.h in Headers */ = {isa = PBXBuildFile; fileRef = B1CF88B51BD6657F00F42F87 /* mem_block.h */; }; + B1CF88B91BD6657F00F42F87 /* string-lite.h in Headers */ = {isa = PBXBuildFile; fileRef = B1CF88B61BD6657F00F42F87 /* string-lite.h */; }; + B1D8A0D0198FB83D00A23435 /* audio_math.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B1D8A0CD198FB83D00A23435 /* audio_math.cpp */; }; + B1D8A0D1198FB83D00A23435 /* audio_sample.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B1D8A0CE198FB83D00A23435 /* audio_sample.cpp */; }; + B1D8A0D2198FB83D00A23435 /* audio_sample.h in Headers */ = {isa = PBXBuildFile; fileRef = B1D8A0CF198FB83D00A23435 /* audio_sample.h */; }; + B1DD3606198A702E00EF7043 /* alloc.h in Headers */ = {isa = PBXBuildFile; fileRef = B1DD35C3198A702E00EF7043 /* alloc.h */; }; + B1DD3607198A702E00EF7043 /* array.h in Headers */ = {isa = PBXBuildFile; fileRef = B1DD35C4198A702E00EF7043 /* array.h */; }; + B1DD3608198A702E00EF7043 /* avltree.h in Headers */ = {isa = PBXBuildFile; fileRef = B1DD35C5198A702E00EF7043 /* avltree.h */; }; + B1DD3609198A702E00EF7043 /* base64.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B1DD35C6198A702E00EF7043 /* base64.cpp */; }; + B1DD360A198A702E00EF7043 /* base64.h in Headers */ = {isa = PBXBuildFile; fileRef = B1DD35C7198A702E00EF7043 /* base64.h */; }; + B1DD360B198A702E00EF7043 /* binary_search.h in Headers */ = {isa = PBXBuildFile; fileRef = B1DD35C8198A702E00EF7043 /* binary_search.h */; }; + B1DD360C198A702E00EF7043 /* bit_array_impl_part2.h in Headers */ = {isa = PBXBuildFile; fileRef = B1DD35C9198A702E00EF7043 /* bit_array_impl_part2.h */; }; + B1DD360D198A702E00EF7043 /* bit_array_impl.h in Headers */ = {isa = PBXBuildFile; fileRef = B1DD35CA198A702E00EF7043 /* bit_array_impl.h */; }; + B1DD360E198A702E00EF7043 /* bit_array.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B1DD35CB198A702E00EF7043 /* bit_array.cpp */; }; + B1DD360F198A702E00EF7043 /* bit_array.h in Headers */ = {isa = PBXBuildFile; fileRef = B1DD35CC198A702E00EF7043 /* bit_array.h */; }; + B1DD3610198A702E00EF7043 /* bsearch_inline.h in Headers */ = {isa = PBXBuildFile; fileRef = B1DD35CD198A702E00EF7043 /* bsearch_inline.h */; }; + B1DD3611198A702E00EF7043 /* bsearch.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B1DD35CE198A702E00EF7043 /* bsearch.cpp */; }; + B1DD3612198A702E00EF7043 /* bsearch.h in Headers */ = {isa = PBXBuildFile; fileRef = B1DD35CF198A702E00EF7043 /* bsearch.h */; }; + B1DD3613198A702E00EF7043 /* byte_order.h in Headers */ = {isa = PBXBuildFile; fileRef = B1DD35D0198A702E00EF7043 /* byte_order.h */; }; + B1DD3614198A702E00EF7043 /* chain_list_v2.h in Headers */ = {isa = PBXBuildFile; fileRef = B1DD35D1198A702E00EF7043 /* chain_list_v2.h */; }; + B1DD3615198A702E00EF7043 /* com_ptr_t.h in Headers */ = {isa = PBXBuildFile; fileRef = B1DD35D2198A702E00EF7043 /* com_ptr_t.h */; }; + B1DD3616198A702E00EF7043 /* cpuid.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B1DD35D3198A702E00EF7043 /* cpuid.cpp */; }; + B1DD3617198A702E00EF7043 /* cpuid.h in Headers */ = {isa = PBXBuildFile; fileRef = B1DD35D4198A702E00EF7043 /* cpuid.h */; }; + B1DD3618198A702E00EF7043 /* event.h in Headers */ = {isa = PBXBuildFile; fileRef = B1DD35D5198A702E00EF7043 /* event.h */; }; + B1DD3619198A702E00EF7043 /* guid.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B1DD35D6198A702E00EF7043 /* guid.cpp */; }; + B1DD361A198A702E00EF7043 /* guid.h in Headers */ = {isa = PBXBuildFile; fileRef = B1DD35D7198A702E00EF7043 /* guid.h */; }; + B1DD361C198A702E00EF7043 /* int_types.h in Headers */ = {isa = PBXBuildFile; fileRef = B1DD35D9198A702E00EF7043 /* int_types.h */; }; + B1DD361D198A702E00EF7043 /* iterators.h in Headers */ = {isa = PBXBuildFile; fileRef = B1DD35DA198A702E00EF7043 /* iterators.h */; }; + B1DD361E198A702E00EF7043 /* list.h in Headers */ = {isa = PBXBuildFile; fileRef = B1DD35DB198A702E00EF7043 /* list.h */; }; + B1DD361F198A702E00EF7043 /* map.h in Headers */ = {isa = PBXBuildFile; fileRef = B1DD35DC198A702E00EF7043 /* map.h */; }; + B1DD3621198A702E00EF7043 /* memalign.h in Headers */ = {isa = PBXBuildFile; fileRef = B1DD35DE198A702E00EF7043 /* memalign.h */; }; + B1DD3622198A702E00EF7043 /* nix-objects.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B1DD35DF198A702E00EF7043 /* nix-objects.cpp */; }; + B1DD3623198A702E00EF7043 /* nix-objects.h in Headers */ = {isa = PBXBuildFile; fileRef = B1DD35E0198A702E00EF7043 /* nix-objects.h */; }; + B1DD3624198A702E00EF7043 /* obj-c.mm in Sources */ = {isa = PBXBuildFile; fileRef = B1DD35E1198A702E00EF7043 /* obj-c.mm */; }; + B1DD3625198A702E00EF7043 /* order_helper.h in Headers */ = {isa = PBXBuildFile; fileRef = B1DD35E2198A702E00EF7043 /* order_helper.h */; }; + B1DD3626198A702E00EF7043 /* other.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B1DD35E3198A702E00EF7043 /* other.cpp */; }; + B1DD3627198A702E00EF7043 /* other.h in Headers */ = {isa = PBXBuildFile; fileRef = B1DD35E4198A702E00EF7043 /* other.h */; }; + B1DD3628198A702E00EF7043 /* pathUtils.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B1DD35E5198A702E00EF7043 /* pathUtils.cpp */; }; + B1DD3629198A702E00EF7043 /* pathUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = B1DD35E6198A702E00EF7043 /* pathUtils.h */; }; + B1DD362A198A702E00EF7043 /* pfc.h in Headers */ = {isa = PBXBuildFile; fileRef = B1DD35E7198A702E00EF7043 /* pfc.h */; }; + B1DD362B198A702E00EF7043 /* primitives_part2.h in Headers */ = {isa = PBXBuildFile; fileRef = B1DD35E8198A702E00EF7043 /* primitives_part2.h */; }; + B1DD362C198A702E00EF7043 /* primitives.h in Headers */ = {isa = PBXBuildFile; fileRef = B1DD35E9198A702E00EF7043 /* primitives.h */; }; + B1DD362D198A702E00EF7043 /* printf.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B1DD35EA198A702E00EF7043 /* printf.cpp */; }; + B1DD362E198A702E00EF7043 /* timers.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B1DD35EB198A702E00EF7043 /* timers.cpp */; }; + B1DD362F198A702E00EF7043 /* timers.h in Headers */ = {isa = PBXBuildFile; fileRef = B1DD35EC198A702E00EF7043 /* timers.h */; }; + B1DD3630198A702E00EF7043 /* ptr_list.h in Headers */ = {isa = PBXBuildFile; fileRef = B1DD35ED198A702E00EF7043 /* ptr_list.h */; }; + B1DD3631198A702E00EF7043 /* rcptr.h in Headers */ = {isa = PBXBuildFile; fileRef = B1DD35EE198A702E00EF7043 /* rcptr.h */; }; + B1DD3632198A702E00EF7043 /* ref_counter.h in Headers */ = {isa = PBXBuildFile; fileRef = B1DD35EF198A702E00EF7043 /* ref_counter.h */; }; + B1DD3633198A702E00EF7043 /* selftest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B1DD35F0198A702E00EF7043 /* selftest.cpp */; }; + B1DD3634198A702E00EF7043 /* sort.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B1DD35F1198A702E00EF7043 /* sort.cpp */; }; + B1DD3635198A702E00EF7043 /* sort.h in Headers */ = {isa = PBXBuildFile; fileRef = B1DD35F2198A702E00EF7043 /* sort.h */; }; + B1DD3636198A702E00EF7043 /* stdafx.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B1DD35F3198A702E00EF7043 /* stdafx.cpp */; }; + B1DD3637198A702E00EF7043 /* string_conv.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B1DD35F4198A702E00EF7043 /* string_conv.cpp */; }; + B1DD3638198A702E00EF7043 /* string_conv.h in Headers */ = {isa = PBXBuildFile; fileRef = B1DD35F5198A702E00EF7043 /* string_conv.h */; }; + B1DD3639198A702E00EF7043 /* string_list.h in Headers */ = {isa = PBXBuildFile; fileRef = B1DD35F6198A702E00EF7043 /* string_list.h */; }; + B1DD363A198A702E00EF7043 /* string_base.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B1DD35F7198A702E00EF7043 /* string_base.cpp */; }; + B1DD363B198A702E00EF7043 /* string_base.h in Headers */ = {isa = PBXBuildFile; fileRef = B1DD35F8198A702E00EF7043 /* string_base.h */; }; + B1DD363F198A702E00EF7043 /* syncd_storage.h in Headers */ = {isa = PBXBuildFile; fileRef = B1DD35FC198A702E00EF7043 /* syncd_storage.h */; }; + B1DD3640198A702E00EF7043 /* synchro_nix.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B1DD35FD198A702E00EF7043 /* synchro_nix.cpp */; }; + B1DD3641198A702E00EF7043 /* synchro_nix.h in Headers */ = {isa = PBXBuildFile; fileRef = B1DD35FE198A702E00EF7043 /* synchro_nix.h */; }; + B1DD3642198A702E00EF7043 /* synchro_win.h in Headers */ = {isa = PBXBuildFile; fileRef = B1DD35FF198A702E00EF7043 /* synchro_win.h */; }; + B1DD3643198A702E00EF7043 /* threads.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B1DD3600198A702E00EF7043 /* threads.cpp */; }; + B1DD3644198A702E00EF7043 /* threads.h in Headers */ = {isa = PBXBuildFile; fileRef = B1DD3601198A702E00EF7043 /* threads.h */; }; + B1DD3645198A702E00EF7043 /* traits.h in Headers */ = {isa = PBXBuildFile; fileRef = B1DD3602198A702E00EF7043 /* traits.h */; }; + B1DD3646198A702E00EF7043 /* utf8.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B1DD3603198A702E00EF7043 /* utf8.cpp */; }; + B1DD3647198A702E00EF7043 /* win-objects.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B1DD3604198A702E00EF7043 /* win-objects.cpp */; }; + B1DD3648198A702E00EF7043 /* win-objects.h in Headers */ = {isa = PBXBuildFile; fileRef = B1DD3605198A702E00EF7043 /* win-objects.h */; }; +/* End PBXBuildFile section */ + +/* Begin PBXCopyFilesBuildPhase section */ + B16695F219ACC12A0001728F /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = "include/$(PRODUCT_NAME)"; + dstSubfolderSpec = 16; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 0F0794CF27C90AA4006BAD7F /* fixed_map.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fixed_map.h; sourceTree = ""; }; + 0F0794D027C90AA4006BAD7F /* charDownConvert.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = charDownConvert.h; sourceTree = ""; }; + 0F0794D127C90AA4006BAD7F /* SmartStrStr-table.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "SmartStrStr-table.h"; sourceTree = ""; }; + 0F0794D227C90AA4006BAD7F /* charDownConvert.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = charDownConvert.cpp; sourceTree = ""; }; + 0F0794D327C90AA4006BAD7F /* SmartStrStr-twoCharMappings.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "SmartStrStr-twoCharMappings.h"; sourceTree = ""; }; + 0F14904C242E44C300D0BD81 /* notifyList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = notifyList.h; sourceTree = ""; }; + 0F14904E242E44ED00D0BD81 /* autoref.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = autoref.h; sourceTree = ""; }; + 0F149050242E454C00D0BD81 /* weakRef.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = weakRef.h; sourceTree = ""; }; + 0F2F4BEF250BFF660014812D /* pfc-fb2k-hooks.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "pfc-fb2k-hooks.h"; sourceTree = ""; }; + 0F2F4BF0250BFF660014812D /* killswitch.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = killswitch.h; sourceTree = ""; }; + 0F2F4BF1250BFF660014812D /* pfc-fb2k-hooks.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "pfc-fb2k-hooks.cpp"; sourceTree = ""; }; + 0F2F4BF2250BFF660014812D /* stdsort.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = stdsort.h; sourceTree = ""; }; + 0F2F4BF3250BFF660014812D /* suppress_fb2k_hooks.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = suppress_fb2k_hooks.h; sourceTree = ""; }; + 0F2F4BF4250BFF660014812D /* platform-objects.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "platform-objects.h"; sourceTree = ""; }; + 0F2F4BF5250BFF660014812D /* pocket_char_ops.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = pocket_char_ops.h; sourceTree = ""; }; + 0F2F4BF6250BFF660014812D /* cmd_thread.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cmd_thread.h; sourceTree = ""; }; + 0F64350D253A250600D6335A /* string-conv-lite.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "string-conv-lite.h"; sourceTree = ""; }; + 0F64350E253A250600D6335A /* pp-winapi.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "pp-winapi.h"; sourceTree = ""; }; + 0F64350F253A250600D6335A /* string-conv-lite.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "string-conv-lite.cpp"; sourceTree = ""; }; + 0F65005125122FD5001B03BA /* string-compare.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "string-compare.cpp"; sourceTree = ""; }; + 0F65005225122FD5001B03BA /* string-compare.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "string-compare.h"; sourceTree = ""; }; + 0F65005325122FD5001B03BA /* string-part.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "string-part.h"; sourceTree = ""; }; + 0F65005425122FD5001B03BA /* string-lite.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "string-lite.cpp"; sourceTree = ""; }; + 0F7A1B682A692C88004F89FB /* filetimetools.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = filetimetools.cpp; sourceTree = ""; }; + 0F7A1B692A692C88004F89FB /* filetimetools.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = filetimetools.h; sourceTree = ""; }; + 0F7EDDA827FAFDA5000996AA /* unicode-normalize.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = "unicode-normalize.cpp"; sourceTree = ""; }; + 0F7EDDA927FAFDA5000996AA /* unicode-normalize.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "unicode-normalize.h"; sourceTree = ""; }; + 0FAC031527C8EC6500BA9E97 /* SmartStrStr.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SmartStrStr.cpp; sourceTree = ""; }; + 0FAC031627C8EC6500BA9E97 /* SmartStrStr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SmartStrStr.h; sourceTree = ""; }; + 0FB717E026C295370040D7FE /* splitString2.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = splitString2.h; sourceTree = ""; }; + 0FB717E126C295370040D7FE /* splitString2.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = splitString2.cpp; sourceTree = ""; }; + 0FFFAEAD23C9C9580023328B /* crashWithMessage.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = crashWithMessage.cpp; sourceTree = ""; }; + B125C8AC1F46D9A900ADB97B /* once.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = once.h; sourceTree = ""; }; + B12CBBB61BD3F08800952805 /* pfc-lite.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "pfc-lite.h"; sourceTree = ""; }; + B12CBBB71BD3F0D100952805 /* string-interface.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "string-interface.h"; sourceTree = ""; }; + B12CBBB91BD4A01400952805 /* debug.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = debug.h; sourceTree = ""; }; + B12CBBC61BD4D96A00952805 /* bigmem.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = bigmem.cpp; sourceTree = ""; }; + B12CBBC71BD4D96A00952805 /* bigmem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = bigmem.h; sourceTree = ""; }; + B12CBBD01BD4DD4600952805 /* ptrholder.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ptrholder.h; sourceTree = ""; }; + B12CBBD11BD4DE8100952805 /* synchro.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = synchro.h; sourceTree = ""; }; + B16695F419ACC12A0001728F /* libpfc-iOS.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libpfc-iOS.a"; sourceTree = BUILT_PRODUCTS_DIR; }; + B16695F619ACC12A0001728F /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; + B166960419ACC12A0001728F /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; }; + B166960719ACC12A0001728F /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = Library/Frameworks/UIKit.framework; sourceTree = DEVELOPER_DIR; }; + B17EB26B1E85358D0057E2A4 /* pool.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = pool.h; sourceTree = ""; }; + B17EB26C1E85358D0057E2A4 /* splitString.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = splitString.h; sourceTree = ""; }; + B17EB26D1E85358D0057E2A4 /* wait_queue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = wait_queue.h; sourceTree = ""; }; + B1B502D3198FF75000525EAF /* wildcard.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = wildcard.cpp; sourceTree = ""; }; + B1B502D4198FF75000525EAF /* wildcard.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = wildcard.h; sourceTree = ""; }; + B1C37D7D19922EEB00EE6ABC /* filehandle.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = filehandle.h; sourceTree = ""; }; + B1C37D7E19922EF500EE6ABC /* filehandle.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = filehandle.cpp; sourceTree = ""; }; + B1CF88B41BD6657F00F42F87 /* fpu.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fpu.h; sourceTree = ""; }; + B1CF88B51BD6657F00F42F87 /* mem_block.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mem_block.h; sourceTree = ""; }; + B1CF88B61BD6657F00F42F87 /* string-lite.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "string-lite.h"; sourceTree = ""; }; + B1D8A0CD198FB83D00A23435 /* audio_math.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = audio_math.cpp; sourceTree = ""; }; + B1D8A0CE198FB83D00A23435 /* audio_sample.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = audio_sample.cpp; sourceTree = ""; }; + B1D8A0CF198FB83D00A23435 /* audio_sample.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = audio_sample.h; sourceTree = ""; }; + B1DD35AF198A6FAA00EF7043 /* libpfc-Mac.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libpfc-Mac.a"; sourceTree = BUILT_PRODUCTS_DIR; }; + B1DD35C3198A702E00EF7043 /* alloc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = alloc.h; sourceTree = ""; }; + B1DD35C4198A702E00EF7043 /* array.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = array.h; sourceTree = ""; }; + B1DD35C5198A702E00EF7043 /* avltree.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = avltree.h; sourceTree = ""; }; + B1DD35C6198A702E00EF7043 /* base64.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = base64.cpp; sourceTree = ""; }; + B1DD35C7198A702E00EF7043 /* base64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = base64.h; sourceTree = ""; }; + B1DD35C8198A702E00EF7043 /* binary_search.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = binary_search.h; sourceTree = ""; }; + B1DD35C9198A702E00EF7043 /* bit_array_impl_part2.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = bit_array_impl_part2.h; sourceTree = ""; }; + B1DD35CA198A702E00EF7043 /* bit_array_impl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = bit_array_impl.h; sourceTree = ""; }; + B1DD35CB198A702E00EF7043 /* bit_array.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = bit_array.cpp; sourceTree = ""; }; + B1DD35CC198A702E00EF7043 /* bit_array.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = bit_array.h; sourceTree = ""; }; + B1DD35CD198A702E00EF7043 /* bsearch_inline.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = bsearch_inline.h; sourceTree = ""; }; + B1DD35CE198A702E00EF7043 /* bsearch.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = bsearch.cpp; sourceTree = ""; }; + B1DD35CF198A702E00EF7043 /* bsearch.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = bsearch.h; sourceTree = ""; }; + B1DD35D0198A702E00EF7043 /* byte_order.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = byte_order.h; sourceTree = ""; }; + B1DD35D1198A702E00EF7043 /* chain_list_v2.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = chain_list_v2.h; sourceTree = ""; }; + B1DD35D2198A702E00EF7043 /* com_ptr_t.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = com_ptr_t.h; sourceTree = ""; }; + B1DD35D3198A702E00EF7043 /* cpuid.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = cpuid.cpp; sourceTree = ""; }; + B1DD35D4198A702E00EF7043 /* cpuid.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cpuid.h; sourceTree = ""; }; + B1DD35D5198A702E00EF7043 /* event.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = event.h; sourceTree = ""; }; + B1DD35D6198A702E00EF7043 /* guid.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = guid.cpp; sourceTree = ""; }; + B1DD35D7198A702E00EF7043 /* guid.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = guid.h; sourceTree = ""; }; + B1DD35D9198A702E00EF7043 /* int_types.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = int_types.h; sourceTree = ""; }; + B1DD35DA198A702E00EF7043 /* iterators.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = iterators.h; sourceTree = ""; }; + B1DD35DB198A702E00EF7043 /* list.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = list.h; sourceTree = ""; }; + B1DD35DC198A702E00EF7043 /* map.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = map.h; sourceTree = ""; }; + B1DD35DE198A702E00EF7043 /* memalign.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = memalign.h; sourceTree = ""; }; + B1DD35DF198A702E00EF7043 /* nix-objects.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "nix-objects.cpp"; sourceTree = ""; }; + B1DD35E0198A702E00EF7043 /* nix-objects.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "nix-objects.h"; sourceTree = ""; }; + B1DD35E1198A702E00EF7043 /* obj-c.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = "obj-c.mm"; sourceTree = ""; }; + B1DD35E2198A702E00EF7043 /* order_helper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = order_helper.h; sourceTree = ""; }; + B1DD35E3198A702E00EF7043 /* other.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = other.cpp; sourceTree = ""; }; + B1DD35E4198A702E00EF7043 /* other.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = other.h; sourceTree = ""; }; + B1DD35E5198A702E00EF7043 /* pathUtils.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = pathUtils.cpp; sourceTree = ""; }; + B1DD35E6198A702E00EF7043 /* pathUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = pathUtils.h; sourceTree = ""; }; + B1DD35E7198A702E00EF7043 /* pfc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = pfc.h; sourceTree = ""; }; + B1DD35E8198A702E00EF7043 /* primitives_part2.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = primitives_part2.h; sourceTree = ""; }; + B1DD35E9198A702E00EF7043 /* primitives.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = primitives.h; sourceTree = ""; }; + B1DD35EA198A702E00EF7043 /* printf.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = printf.cpp; sourceTree = ""; }; + B1DD35EB198A702E00EF7043 /* timers.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = timers.cpp; sourceTree = ""; }; + B1DD35EC198A702E00EF7043 /* timers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = timers.h; sourceTree = ""; }; + B1DD35ED198A702E00EF7043 /* ptr_list.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ptr_list.h; sourceTree = ""; }; + B1DD35EE198A702E00EF7043 /* rcptr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = rcptr.h; sourceTree = ""; }; + B1DD35EF198A702E00EF7043 /* ref_counter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ref_counter.h; sourceTree = ""; }; + B1DD35F0198A702E00EF7043 /* selftest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = selftest.cpp; sourceTree = ""; }; + B1DD35F1198A702E00EF7043 /* sort.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = sort.cpp; sourceTree = ""; }; + B1DD35F2198A702E00EF7043 /* sort.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sort.h; sourceTree = ""; }; + B1DD35F3198A702E00EF7043 /* stdafx.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = stdafx.cpp; sourceTree = ""; }; + B1DD35F4198A702E00EF7043 /* string_conv.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = string_conv.cpp; sourceTree = ""; }; + B1DD35F5198A702E00EF7043 /* string_conv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = string_conv.h; sourceTree = ""; }; + B1DD35F6198A702E00EF7043 /* string_list.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = string_list.h; sourceTree = ""; }; + B1DD35F7198A702E00EF7043 /* string_base.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = string_base.cpp; sourceTree = ""; }; + B1DD35F8198A702E00EF7043 /* string_base.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = string_base.h; sourceTree = ""; }; + B1DD35FC198A702E00EF7043 /* syncd_storage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = syncd_storage.h; sourceTree = ""; }; + B1DD35FD198A702E00EF7043 /* synchro_nix.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = synchro_nix.cpp; sourceTree = ""; }; + B1DD35FE198A702E00EF7043 /* synchro_nix.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = synchro_nix.h; sourceTree = ""; }; + B1DD35FF198A702E00EF7043 /* synchro_win.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = synchro_win.h; sourceTree = ""; }; + B1DD3600198A702E00EF7043 /* threads.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = threads.cpp; sourceTree = ""; }; + B1DD3601198A702E00EF7043 /* threads.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = threads.h; sourceTree = ""; }; + B1DD3602198A702E00EF7043 /* traits.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = traits.h; sourceTree = ""; }; + B1DD3603198A702E00EF7043 /* utf8.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = utf8.cpp; sourceTree = ""; }; + B1DD3604198A702E00EF7043 /* win-objects.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "win-objects.cpp"; sourceTree = ""; }; + B1DD3605198A702E00EF7043 /* win-objects.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "win-objects.h"; sourceTree = ""; }; + B1EFBAC51B90658600C2CE84 /* lockless.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = lockless.h; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + B16695F119ACC12A0001728F /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + B16695F719ACC12A0001728F /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + B1DD35AC198A6FAA00EF7043 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + B16695F519ACC12A0001728F /* Frameworks */ = { + isa = PBXGroup; + children = ( + B16695F619ACC12A0001728F /* Foundation.framework */, + B166960419ACC12A0001728F /* XCTest.framework */, + B166960719ACC12A0001728F /* UIKit.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + B1DD35A6198A6FAA00EF7043 = { + isa = PBXGroup; + children = ( + B1DD35C2198A701100EF7043 /* Source */, + B16695F519ACC12A0001728F /* Frameworks */, + B1DD35B0198A6FAA00EF7043 /* Products */, + ); + sourceTree = ""; + }; + B1DD35B0198A6FAA00EF7043 /* Products */ = { + isa = PBXGroup; + children = ( + B1DD35AF198A6FAA00EF7043 /* libpfc-Mac.a */, + B16695F419ACC12A0001728F /* libpfc-iOS.a */, + ); + name = Products; + sourceTree = ""; + }; + B1DD35C2198A701100EF7043 /* Source */ = { + isa = PBXGroup; + children = ( + 0F7A1B682A692C88004F89FB /* filetimetools.cpp */, + 0F7A1B692A692C88004F89FB /* filetimetools.h */, + 0F0794D227C90AA4006BAD7F /* charDownConvert.cpp */, + 0F0794D027C90AA4006BAD7F /* charDownConvert.h */, + 0F0794CF27C90AA4006BAD7F /* fixed_map.h */, + 0F0794D127C90AA4006BAD7F /* SmartStrStr-table.h */, + 0F0794D327C90AA4006BAD7F /* SmartStrStr-twoCharMappings.h */, + 0FAC031527C8EC6500BA9E97 /* SmartStrStr.cpp */, + 0FAC031627C8EC6500BA9E97 /* SmartStrStr.h */, + B1DD35C3198A702E00EF7043 /* alloc.h */, + B1DD35C4198A702E00EF7043 /* array.h */, + B1D8A0CD198FB83D00A23435 /* audio_math.cpp */, + B1D8A0CE198FB83D00A23435 /* audio_sample.cpp */, + B1D8A0CF198FB83D00A23435 /* audio_sample.h */, + 0F14904E242E44ED00D0BD81 /* autoref.h */, + B1DD35C5198A702E00EF7043 /* avltree.h */, + B1DD35C6198A702E00EF7043 /* base64.cpp */, + B1DD35C7198A702E00EF7043 /* base64.h */, + B12CBBC61BD4D96A00952805 /* bigmem.cpp */, + B12CBBC71BD4D96A00952805 /* bigmem.h */, + B1DD35C8198A702E00EF7043 /* binary_search.h */, + B1DD35C9198A702E00EF7043 /* bit_array_impl_part2.h */, + B1DD35CA198A702E00EF7043 /* bit_array_impl.h */, + B1DD35CB198A702E00EF7043 /* bit_array.cpp */, + B1DD35CC198A702E00EF7043 /* bit_array.h */, + B1DD35CD198A702E00EF7043 /* bsearch_inline.h */, + B1DD35CE198A702E00EF7043 /* bsearch.cpp */, + B1DD35CF198A702E00EF7043 /* bsearch.h */, + B1DD35D0198A702E00EF7043 /* byte_order.h */, + B1DD35D1198A702E00EF7043 /* chain_list_v2.h */, + 0F2F4BF6250BFF660014812D /* cmd_thread.h */, + B1DD35D2198A702E00EF7043 /* com_ptr_t.h */, + B1DD35D3198A702E00EF7043 /* cpuid.cpp */, + B1DD35D4198A702E00EF7043 /* cpuid.h */, + 0FFFAEAD23C9C9580023328B /* crashWithMessage.cpp */, + B12CBBB91BD4A01400952805 /* debug.h */, + B1DD35D5198A702E00EF7043 /* event.h */, + B1C37D7E19922EF500EE6ABC /* filehandle.cpp */, + B1C37D7D19922EEB00EE6ABC /* filehandle.h */, + B1CF88B41BD6657F00F42F87 /* fpu.h */, + B1DD35D6198A702E00EF7043 /* guid.cpp */, + B1DD35D7198A702E00EF7043 /* guid.h */, + B1DD35D9198A702E00EF7043 /* int_types.h */, + B1DD35DA198A702E00EF7043 /* iterators.h */, + 0F2F4BF0250BFF660014812D /* killswitch.h */, + B1DD35DB198A702E00EF7043 /* list.h */, + B1EFBAC51B90658600C2CE84 /* lockless.h */, + B1DD35DC198A702E00EF7043 /* map.h */, + B1CF88B51BD6657F00F42F87 /* mem_block.h */, + B1DD35DE198A702E00EF7043 /* memalign.h */, + B1DD35DF198A702E00EF7043 /* nix-objects.cpp */, + B1DD35E0198A702E00EF7043 /* nix-objects.h */, + 0F14904C242E44C300D0BD81 /* notifyList.h */, + B1DD35E1198A702E00EF7043 /* obj-c.mm */, + B125C8AC1F46D9A900ADB97B /* once.h */, + B1DD35E2198A702E00EF7043 /* order_helper.h */, + B1DD35E3198A702E00EF7043 /* other.cpp */, + B1DD35E4198A702E00EF7043 /* other.h */, + B1DD35E5198A702E00EF7043 /* pathUtils.cpp */, + B1DD35E6198A702E00EF7043 /* pathUtils.h */, + 0F2F4BF1250BFF660014812D /* pfc-fb2k-hooks.cpp */, + 0F2F4BEF250BFF660014812D /* pfc-fb2k-hooks.h */, + B12CBBB61BD3F08800952805 /* pfc-lite.h */, + B1DD35E7198A702E00EF7043 /* pfc.h */, + 0F2F4BF4250BFF660014812D /* platform-objects.h */, + 0F2F4BF5250BFF660014812D /* pocket_char_ops.h */, + B17EB26B1E85358D0057E2A4 /* pool.h */, + 0F64350E253A250600D6335A /* pp-winapi.h */, + B1DD35E8198A702E00EF7043 /* primitives_part2.h */, + B1DD35E9198A702E00EF7043 /* primitives.h */, + B1DD35EA198A702E00EF7043 /* printf.cpp */, + B1DD35ED198A702E00EF7043 /* ptr_list.h */, + B12CBBD01BD4DD4600952805 /* ptrholder.h */, + B1DD35EE198A702E00EF7043 /* rcptr.h */, + B1DD35EF198A702E00EF7043 /* ref_counter.h */, + B1DD35F0198A702E00EF7043 /* selftest.cpp */, + B1DD35F1198A702E00EF7043 /* sort.cpp */, + B1DD35F2198A702E00EF7043 /* sort.h */, + B17EB26C1E85358D0057E2A4 /* splitString.h */, + 0FB717E126C295370040D7FE /* splitString2.cpp */, + 0FB717E026C295370040D7FE /* splitString2.h */, + B1DD35F3198A702E00EF7043 /* stdafx.cpp */, + 0F2F4BF2250BFF660014812D /* stdsort.h */, + B1DD35F7198A702E00EF7043 /* string_base.cpp */, + B1DD35F8198A702E00EF7043 /* string_base.h */, + B1DD35F4198A702E00EF7043 /* string_conv.cpp */, + B1DD35F5198A702E00EF7043 /* string_conv.h */, + B1DD35F6198A702E00EF7043 /* string_list.h */, + 0F65005125122FD5001B03BA /* string-compare.cpp */, + 0F65005225122FD5001B03BA /* string-compare.h */, + 0F64350F253A250600D6335A /* string-conv-lite.cpp */, + 0F64350D253A250600D6335A /* string-conv-lite.h */, + B12CBBB71BD3F0D100952805 /* string-interface.h */, + 0F65005425122FD5001B03BA /* string-lite.cpp */, + B1CF88B61BD6657F00F42F87 /* string-lite.h */, + 0F65005325122FD5001B03BA /* string-part.h */, + 0F2F4BF3250BFF660014812D /* suppress_fb2k_hooks.h */, + B1DD35FC198A702E00EF7043 /* syncd_storage.h */, + B1DD35FD198A702E00EF7043 /* synchro_nix.cpp */, + B1DD35FE198A702E00EF7043 /* synchro_nix.h */, + B1DD35FF198A702E00EF7043 /* synchro_win.h */, + B12CBBD11BD4DE8100952805 /* synchro.h */, + B1DD3600198A702E00EF7043 /* threads.cpp */, + B1DD3601198A702E00EF7043 /* threads.h */, + B1DD35EB198A702E00EF7043 /* timers.cpp */, + B1DD35EC198A702E00EF7043 /* timers.h */, + B1DD3602198A702E00EF7043 /* traits.h */, + B1DD3603198A702E00EF7043 /* utf8.cpp */, + B17EB26D1E85358D0057E2A4 /* wait_queue.h */, + 0F149050242E454C00D0BD81 /* weakRef.h */, + B1B502D3198FF75000525EAF /* wildcard.cpp */, + B1B502D4198FF75000525EAF /* wildcard.h */, + B1DD3604198A702E00EF7043 /* win-objects.cpp */, + B1DD3605198A702E00EF7043 /* win-objects.h */, + 0F7EDDA827FAFDA5000996AA /* unicode-normalize.cpp */, + 0F7EDDA927FAFDA5000996AA /* unicode-normalize.h */, + ); + name = Source; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + B1DD35AD198A6FAA00EF7043 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + B1DD361E198A702E00EF7043 /* list.h in Headers */, + 0F2F4BF7250BFF660014812D /* pfc-fb2k-hooks.h in Headers */, + B12CBBCA1BD4D96A00952805 /* bigmem.h in Headers */, + B1DD3629198A702E00EF7043 /* pathUtils.h in Headers */, + B1DD3615198A702E00EF7043 /* com_ptr_t.h in Headers */, + B1DD360D198A702E00EF7043 /* bit_array_impl.h in Headers */, + 0F7EDDAC27FAFDA5000996AA /* unicode-normalize.h in Headers */, + B1DD3617198A702E00EF7043 /* cpuid.h in Headers */, + 0F643510253A250600D6335A /* string-conv-lite.h in Headers */, + B1DD3635198A702E00EF7043 /* sort.h in Headers */, + B1DD3648198A702E00EF7043 /* win-objects.h in Headers */, + B1DD3607198A702E00EF7043 /* array.h in Headers */, + B1DD360B198A702E00EF7043 /* binary_search.h in Headers */, + B1DD3621198A702E00EF7043 /* memalign.h in Headers */, + B1B502D6198FF75000525EAF /* wildcard.h in Headers */, + B1DD361A198A702E00EF7043 /* guid.h in Headers */, + B1DD362F198A702E00EF7043 /* timers.h in Headers */, + 0F0794D827C90AA4006BAD7F /* SmartStrStr-twoCharMappings.h in Headers */, + B1DD3638198A702E00EF7043 /* string_conv.h in Headers */, + B1DD3610198A702E00EF7043 /* bsearch_inline.h in Headers */, + 0F65005725122FD5001B03BA /* string-compare.h in Headers */, + 0F14904F242E44ED00D0BD81 /* autoref.h in Headers */, + 0F0794D527C90AA4006BAD7F /* charDownConvert.h in Headers */, + 0FAC031827C8EC6500BA9E97 /* SmartStrStr.h in Headers */, + B1DD3641198A702E00EF7043 /* synchro_nix.h in Headers */, + B1CF88B91BD6657F00F42F87 /* string-lite.h in Headers */, + B1DD360C198A702E00EF7043 /* bit_array_impl_part2.h in Headers */, + B1DD3645198A702E00EF7043 /* traits.h in Headers */, + 0F2F4BFB250BFF660014812D /* stdsort.h in Headers */, + B1DD361F198A702E00EF7043 /* map.h in Headers */, + 0F2F4BF8250BFF660014812D /* killswitch.h in Headers */, + B1DD3612198A702E00EF7043 /* bsearch.h in Headers */, + 0F2F4BFE250BFF660014812D /* pocket_char_ops.h in Headers */, + 0F149051242E454C00D0BD81 /* weakRef.h in Headers */, + B1CF88B81BD6657F00F42F87 /* mem_block.h in Headers */, + B1DD3614198A702E00EF7043 /* chain_list_v2.h in Headers */, + 0F0794D627C90AA4006BAD7F /* SmartStrStr-table.h in Headers */, + B1DD3627198A702E00EF7043 /* other.h in Headers */, + 0F2F4BFC250BFF660014812D /* suppress_fb2k_hooks.h in Headers */, + B17EB26E1E85358D0057E2A4 /* pool.h in Headers */, + B17EB26F1E85358D0057E2A4 /* splitString.h in Headers */, + 0F2F4BFF250BFF660014812D /* cmd_thread.h in Headers */, + B1DD362B198A702E00EF7043 /* primitives_part2.h in Headers */, + 0F2F4BFD250BFF660014812D /* platform-objects.h in Headers */, + B1DD3632198A702E00EF7043 /* ref_counter.h in Headers */, + B1DD3630198A702E00EF7043 /* ptr_list.h in Headers */, + B17EB2701E85358D0057E2A4 /* wait_queue.h in Headers */, + B1DD362C198A702E00EF7043 /* primitives.h in Headers */, + B1DD3639198A702E00EF7043 /* string_list.h in Headers */, + B1DD361C198A702E00EF7043 /* int_types.h in Headers */, + B1DD3618198A702E00EF7043 /* event.h in Headers */, + 0F7A1B6C2A692C88004F89FB /* filetimetools.h in Headers */, + B1DD3608198A702E00EF7043 /* avltree.h in Headers */, + B1DD3606198A702E00EF7043 /* alloc.h in Headers */, + 0F14904D242E44C300D0BD81 /* notifyList.h in Headers */, + B1DD3644198A702E00EF7043 /* threads.h in Headers */, + 0F65005825122FD5001B03BA /* string-part.h in Headers */, + B1DD3623198A702E00EF7043 /* nix-objects.h in Headers */, + B1DD363F198A702E00EF7043 /* syncd_storage.h in Headers */, + B1DD362A198A702E00EF7043 /* pfc.h in Headers */, + B1DD3613198A702E00EF7043 /* byte_order.h in Headers */, + B1DD3631198A702E00EF7043 /* rcptr.h in Headers */, + 0F0794D427C90AA4006BAD7F /* fixed_map.h in Headers */, + B1DD3642198A702E00EF7043 /* synchro_win.h in Headers */, + 0F643511253A250600D6335A /* pp-winapi.h in Headers */, + B1DD360F198A702E00EF7043 /* bit_array.h in Headers */, + B1DD360A198A702E00EF7043 /* base64.h in Headers */, + B1D8A0D2198FB83D00A23435 /* audio_sample.h in Headers */, + B125C8AD1F46D9A900ADB97B /* once.h in Headers */, + B1DD363B198A702E00EF7043 /* string_base.h in Headers */, + B1DD361D198A702E00EF7043 /* iterators.h in Headers */, + 0FB717E226C295370040D7FE /* splitString2.h in Headers */, + B1DD3625198A702E00EF7043 /* order_helper.h in Headers */, + B1CF88B71BD6657F00F42F87 /* fpu.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + B16695F319ACC12A0001728F /* pfc-iOS */ = { + isa = PBXNativeTarget; + buildConfigurationList = B166961819ACC12A0001728F /* Build configuration list for PBXNativeTarget "pfc-iOS" */; + buildPhases = ( + B16695F019ACC12A0001728F /* Sources */, + B16695F119ACC12A0001728F /* Frameworks */, + B16695F219ACC12A0001728F /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "pfc-iOS"; + productName = "pfc-iOS"; + productReference = B16695F419ACC12A0001728F /* libpfc-iOS.a */; + productType = "com.apple.product-type.library.static"; + }; + B1DD35AE198A6FAA00EF7043 /* pfc-Mac */ = { + isa = PBXNativeTarget; + buildConfigurationList = B1DD35B3198A6FAA00EF7043 /* Build configuration list for PBXNativeTarget "pfc-Mac" */; + buildPhases = ( + B1DD35AB198A6FAA00EF7043 /* Sources */, + B1DD35AC198A6FAA00EF7043 /* Frameworks */, + B1DD35AD198A6FAA00EF7043 /* Headers */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "pfc-Mac"; + productName = pfc; + productReference = B1DD35AF198A6FAA00EF7043 /* libpfc-Mac.a */; + productType = "com.apple.product-type.library.static"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + B1DD35A7198A6FAA00EF7043 /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 1320; + ORGANIZATIONNAME = "___FULLUSERNAME___"; + }; + buildConfigurationList = B1DD35AA198A6FAA00EF7043 /* Build configuration list for PBXProject "pfc" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = B1DD35A6198A6FAA00EF7043; + productRefGroup = B1DD35B0198A6FAA00EF7043 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + B1DD35AE198A6FAA00EF7043 /* pfc-Mac */, + B16695F319ACC12A0001728F /* pfc-iOS */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXSourcesBuildPhase section */ + B16695F019ACC12A0001728F /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + B10D405C19ADFADB004D2596 /* audio_sample.cpp in Sources */, + B10D406A19ADFADB004D2596 /* string_base.cpp in Sources */, + 0F643513253A250600D6335A /* string-conv-lite.cpp in Sources */, + B10D405B19ADFADB004D2596 /* audio_math.cpp in Sources */, + B10D406E19ADFADB004D2596 /* threads.cpp in Sources */, + B10D406619ADFADB004D2596 /* printf.cpp in Sources */, + 0F54079726C2964500A118C8 /* splitString2.cpp in Sources */, + 0FFFAEAF23C9DB640023328B /* crashWithMessage.cpp in Sources */, + 0F65005A25122FD5001B03BA /* string-lite.cpp in Sources */, + B10D406419ADFADB004D2596 /* other.cpp in Sources */, + B10D406519ADFADB004D2596 /* pathUtils.cpp in Sources */, + B10D406319ADFADB004D2596 /* nix-objects.cpp in Sources */, + B10D406219ADFADB004D2596 /* guid.cpp in Sources */, + B10D405F19ADFADB004D2596 /* bsearch.cpp in Sources */, + B10D406719ADFADB004D2596 /* selftest.cpp in Sources */, + 0F7A1B6B2A692C88004F89FB /* filetimetools.cpp in Sources */, + B10D406919ADFADB004D2596 /* stdafx.cpp in Sources */, + B10D406819ADFADB004D2596 /* sort.cpp in Sources */, + 0F65005625122FD5001B03BA /* string-compare.cpp in Sources */, + B12CBBC91BD4D96A00952805 /* bigmem.cpp in Sources */, + B10D406D19ADFADB004D2596 /* synchro_nix.cpp in Sources */, + B10D406019ADFADB004D2596 /* cpuid.cpp in Sources */, + 0F7EDDAB27FAFDA5000996AA /* unicode-normalize.cpp in Sources */, + B10D405D19ADFADB004D2596 /* base64.cpp in Sources */, + B10D406B19ADFADB004D2596 /* string_conv.cpp in Sources */, + 0F0794D927C90AA8006BAD7F /* charDownConvert.cpp in Sources */, + B10D407019ADFADB004D2596 /* utf8.cpp in Sources */, + B10D407319ADFE52004D2596 /* obj-c.mm in Sources */, + 0FAC031927C8EC6A00BA9E97 /* SmartStrStr.cpp in Sources */, + B10D407119ADFADB004D2596 /* wildcard.cpp in Sources */, + 0F2F4BFA250BFF660014812D /* pfc-fb2k-hooks.cpp in Sources */, + B10D405E19ADFADB004D2596 /* bit_array.cpp in Sources */, + B10D407219ADFADB004D2596 /* win-objects.cpp in Sources */, + B10D406119ADFADB004D2596 /* filehandle.cpp in Sources */, + B10D406F19ADFADB004D2596 /* timers.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + B1DD35AB198A6FAA00EF7043 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + B1DD3647198A702E00EF7043 /* win-objects.cpp in Sources */, + B1DD3611198A702E00EF7043 /* bsearch.cpp in Sources */, + 0F643512253A250600D6335A /* string-conv-lite.cpp in Sources */, + B1DD3609198A702E00EF7043 /* base64.cpp in Sources */, + B1DD363A198A702E00EF7043 /* string_base.cpp in Sources */, + B1DD362D198A702E00EF7043 /* printf.cpp in Sources */, + 0FB717E326C295370040D7FE /* splitString2.cpp in Sources */, + 0FFFAEAE23C9C9580023328B /* crashWithMessage.cpp in Sources */, + 0F65005925122FD5001B03BA /* string-lite.cpp in Sources */, + B1D8A0D1198FB83D00A23435 /* audio_sample.cpp in Sources */, + B1DD3637198A702E00EF7043 /* string_conv.cpp in Sources */, + B1C37D7F19922EF500EE6ABC /* filehandle.cpp in Sources */, + B1DD3643198A702E00EF7043 /* threads.cpp in Sources */, + B1DD3624198A702E00EF7043 /* obj-c.mm in Sources */, + B1D8A0D0198FB83D00A23435 /* audio_math.cpp in Sources */, + 0F7A1B6A2A692C88004F89FB /* filetimetools.cpp in Sources */, + B1DD3628198A702E00EF7043 /* pathUtils.cpp in Sources */, + B1DD3646198A702E00EF7043 /* utf8.cpp in Sources */, + 0F65005525122FD5001B03BA /* string-compare.cpp in Sources */, + B1DD3636198A702E00EF7043 /* stdafx.cpp in Sources */, + B12CBBC81BD4D96A00952805 /* bigmem.cpp in Sources */, + B1DD362E198A702E00EF7043 /* timers.cpp in Sources */, + 0F7EDDAA27FAFDA5000996AA /* unicode-normalize.cpp in Sources */, + B1DD3622198A702E00EF7043 /* nix-objects.cpp in Sources */, + B1DD3640198A702E00EF7043 /* synchro_nix.cpp in Sources */, + 0F0794D727C90AA4006BAD7F /* charDownConvert.cpp in Sources */, + B1DD3633198A702E00EF7043 /* selftest.cpp in Sources */, + B1DD3626198A702E00EF7043 /* other.cpp in Sources */, + 0FAC031727C8EC6500BA9E97 /* SmartStrStr.cpp in Sources */, + B1DD360E198A702E00EF7043 /* bit_array.cpp in Sources */, + B1DD3619198A702E00EF7043 /* guid.cpp in Sources */, + 0F2F4BF9250BFF660014812D /* pfc-fb2k-hooks.cpp in Sources */, + B1DD3634198A702E00EF7043 /* sort.cpp in Sources */, + B1DD3616198A702E00EF7043 /* cpuid.cpp in Sources */, + B1B502D5198FF75000525EAF /* wildcard.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + B166961419ACC12A0001728F /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + DSTROOT = /tmp/pfc_iOS.dst; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + OTHER_LDFLAGS = "-ObjC"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = iphoneos; + }; + name = Debug; + }; + B166961519ACC12A0001728F /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + DSTROOT = /tmp/pfc_iOS.dst; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + OTHER_LDFLAGS = "-ObjC"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = iphoneos; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + B1DD35B1198A6FAA00EF7043 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_OBJC_EXCEPTIONS = YES; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "pfc-lite.h"; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 12.1; + MACOSX_DEPLOYMENT_TARGET = 10.13; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + SKIP_INSTALL = YES; + }; + name = Debug; + }; + B1DD35B2198A6FAA00EF7043 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_ENABLE_OBJC_EXCEPTIONS = YES; + GCC_NO_COMMON_BLOCKS = YES; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "pfc-lite.h"; + GCC_PREPROCESSOR_DEFINITIONS = "NDEBUG=1"; + GCC_SYMBOLS_PRIVATE_EXTERN = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 12.1; + MACOSX_DEPLOYMENT_TARGET = 10.13; + SDKROOT = macosx; + SKIP_INSTALL = YES; + }; + name = Release; + }; + B1DD35B4198A6FAA00EF7043 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + EXECUTABLE_PREFIX = lib; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + B1DD35B5198A6FAA00EF7043 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + EXECUTABLE_PREFIX = lib; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + B166961819ACC12A0001728F /* Build configuration list for PBXNativeTarget "pfc-iOS" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + B166961419ACC12A0001728F /* Debug */, + B166961519ACC12A0001728F /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + B1DD35AA198A6FAA00EF7043 /* Build configuration list for PBXProject "pfc" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + B1DD35B1198A6FAA00EF7043 /* Debug */, + B1DD35B2198A6FAA00EF7043 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + B1DD35B3198A6FAA00EF7043 /* Build configuration list for PBXNativeTarget "pfc-Mac" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + B1DD35B4198A6FAA00EF7043 /* Debug */, + B1DD35B5198A6FAA00EF7043 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = B1DD35A7198A6FAA00EF7043 /* Project object */; +} diff --git a/3rdparty/foo_SDK/pfc/primitives.h b/3rdparty/foo_SDK/pfc/primitives.h index 71a13f92..dc9f675e 100644 --- a/3rdparty/foo_SDK/pfc/primitives.h +++ b/3rdparty/foo_SDK/pfc/primitives.h @@ -723,20 +723,22 @@ namespace pfc { t_int32 rint32(double p_val); t_int64 rint64(double p_val); - - + //! Returns amount of items left. template inline size_t remove_if_t( array_t & arr, pred_t pred ) { const size_t inCount = arr.size(); size_t walk = 0; - - for( walk = 0; walk < inCount; ++ walk ) { + for (;; ) { + if ( walk == inCount ) return inCount; if ( pred(arr[walk]) ) break; + ++ walk; } size_t total = walk; + ++ walk; // already know that at walk is pred() positive + for( ; walk < inCount; ++ walk ) { if ( !pred(arr[walk] ) ) { move_t(arr[total++], arr[walk]); @@ -747,8 +749,9 @@ namespace pfc { return total; } + //! Returns amount of items left. template - inline t_size remove_mask_t(t_array & p_array,const bit_array & p_mask)//returns amount of items left + inline t_size remove_mask_t(t_array & p_array,const bit_array & p_mask) { t_size n,count = p_array.size(), total = 0; @@ -882,7 +885,7 @@ namespace pfc { template incrementScope autoIncrement(obj_t& v) { return incrementScope(v); } - inline unsigned countBits32(uint32_t i) { + constexpr inline unsigned countBits32(uint32_t i) { const uint32_t mask = 0x11111111; uint32_t acc = i & mask; acc += (i >> 1) & mask; diff --git a/3rdparty/foo_SDK/pfc/sort.cpp b/3rdparty/foo_SDK/pfc/sort.cpp index 53299e6c..56da0bd4 100644 --- a/3rdparty/foo_SDK/pfc/sort.cpp +++ b/3rdparty/foo_SDK/pfc/sort.cpp @@ -1,5 +1,6 @@ #include "pfc-lite.h" #include "sort.h" +#include "sort2.h" #include "bit_array_impl.h" #include "ref_counter.h" @@ -267,5 +268,15 @@ void sort_stable(sort_callback & p_callback,t_size p_count) sort(cb,p_count); } + + +permutation_t make_identitiy(size_t count) { + permutation_t ret; ret.set_size_discard(count); + for (size_t walk = 0; walk < count; ++walk) { + ret[walk] = walk; + } + return ret; +} + } diff --git a/3rdparty/foo_SDK/pfc/sort2.h b/3rdparty/foo_SDK/pfc/sort2.h new file mode 100644 index 00000000..0ad1eb92 --- /dev/null +++ b/3rdparty/foo_SDK/pfc/sort2.h @@ -0,0 +1,34 @@ +#pragma once + +#include "sort.h" + +// 2023 additions + + +namespace pfc { + + typedef array_t permutation_t; + + permutation_t make_identitiy(size_t); + + template + permutation_t sort_get_permutation(container_t const& data, compare_t compare) { + const size_t count = std::size(data); + auto ret = make_identitiy( count ); + if ( count > 0 ) sort_get_permutation_t(data, compare, count, ret.get_ptr() ); + return ret; + } + template + permutation_t sort_stable_get_permutation(container_t const& data, compare_t compare) { + const size_t count = std::size(data); + auto ret = make_identitiy( count ); + if ( count > 0 ) sort_stable_get_permutation_t(data, compare, count, ret.get_ptr() ); + return ret; + } + + template + void reorder(container_t& data, permutation_t const& order) { + PFC_ASSERT( std::size(data) == std::size(order) ); + reorder_t( data, order.get_ptr(), order.get_size() ); + } +} \ No newline at end of file diff --git a/3rdparty/foo_SDK/pfc/string-compare.cpp b/3rdparty/foo_SDK/pfc/string-compare.cpp index 0b3c0e5c..246e8569 100644 --- a/3rdparty/foo_SDK/pfc/string-compare.cpp +++ b/3rdparty/foo_SDK/pfc/string-compare.cpp @@ -134,7 +134,32 @@ namespace pfc { int naturalSortCompareI(const char* s1, const char* s2) throw() { return naturalSortCompareInternal(s1, s2, true); } - +#ifdef _WIN32 + int winNaturalSortCompare(const char* s1, const char* s2); + int winNaturalSortCompareI(const char* s1, const char* s2); +#endif +#ifdef __APPLE__ + int appleNaturalSortCompare(const char* s1, const char* s2); + int appleNaturalSortCompareI(const char* s1, const char* s2); +#endif + int sysNaturalSortCompare(const char* s1, const char* s2) { +#ifdef _WIN32 + return winNaturalSortCompare(s1, s2); +#elif defined(__APPLE__) + return appleNaturalSortCompare(s1, s2); +#else + return naturalSortCompare(s1, s2); +#endif + } + int sysNaturalSortCompareI(const char* s1, const char* s2) { +#ifdef _WIN32 + return winNaturalSortCompareI(s1, s2); +#elif defined(__APPLE__) + return appleNaturalSortCompareI(s1, s2); +#else + return naturalSortCompareI(s1, s2); +#endif + } const char* _stringComparatorCommon::myStringToPtr(string_part_ref) { pfc::crash(); return nullptr; } diff --git a/3rdparty/foo_SDK/pfc/string-compare.h b/3rdparty/foo_SDK/pfc/string-compare.h index 551a108a..230d7d4a 100644 --- a/3rdparty/foo_SDK/pfc/string-compare.h +++ b/3rdparty/foo_SDK/pfc/string-compare.h @@ -6,9 +6,16 @@ namespace pfc { int wstricmp_ascii(const wchar_t* s1, const wchar_t* s2) throw(); int stricmp_ascii(const char* s1, const char* s2) throw(); int stricmp_ascii_ex(const char* s1, t_size len1, const char* s2, t_size len2) throw(); + + // Platform-independant lowlevel natural sort implementation int naturalSortCompare(const char* s1, const char* s2) throw(); int naturalSortCompareI(const char* s1, const char* s2) throw(); + // System-specialized natural sort compare, better ordering of Unicode text, specialized for Apple and MS platforms + // Falls back to naturalSortCompare/naturalSortCompareI where not available + int sysNaturalSortCompare(const char* s1, const char* s2); + int sysNaturalSortCompareI(const char* s1, const char* s2); + int strcmp_ex(const char* p1, t_size n1, const char* p2, t_size n2) throw(); int strcmp_nc(const char* p1, size_t n1, const char* p2, size_t n2) throw(); diff --git a/3rdparty/foo_SDK/pfc/string-lite.h b/3rdparty/foo_SDK/pfc/string-lite.h index 5f698e03..9d3fb715 100644 --- a/3rdparty/foo_SDK/pfc/string-lite.h +++ b/3rdparty/foo_SDK/pfc/string-lite.h @@ -124,7 +124,8 @@ namespace pfc { char firstChar() const; char lastChar() const; - bool isEmpty() const { return length() == 0; } + bool isEmpty() const { return empty(); } + bool empty() const { return length() == 0;} stringLite replace(stringp strOld, stringp strNew) const; stringLite trim(char c) const; diff --git a/3rdparty/foo_SDK/pfc/string_base.cpp b/3rdparty/foo_SDK/pfc/string_base.cpp index 15005b14..2c82abf7 100644 --- a/3rdparty/foo_SDK/pfc/string_base.cpp +++ b/3rdparty/foo_SDK/pfc/string_base.cpp @@ -337,9 +337,11 @@ static double pfc_string_to_float_internal(const char * src) noexcept return (double) val * exp_int(10, div); } +double string_to_float(const char * src) noexcept { + return pfc_string_to_float_internal(src); +} double string_to_float(const char * src,t_size max) noexcept { - //old function wants an oldstyle nullterminated string, and i don't currently care enough to rewrite it as it works appropriately otherwise - char blargh[128]; + char blargh[128]; if (max > 127) max = 127; t_size walk; for(walk = 0; walk < max && src[walk]; walk++) blargh[walk] = src[walk]; @@ -902,6 +904,15 @@ string8 format_time_ex(double p_seconds,unsigned p_extra) { return ret; } +void stringToUpperHere(string_base& p_out, const char* p_source, t_size p_sourceLen) { + p_out.clear(); + stringToUpperAppend(p_out, p_source, p_sourceLen); +} +void stringToLowerHere(string_base& p_out, const char* p_source, t_size p_sourceLen) { + p_out.clear(); + stringToLowerAppend(p_out, p_source, p_sourceLen); +} + void stringToUpperAppend(string_base & out, const char * src, t_size len) { while(len && *src) { unsigned c; t_size d; @@ -951,6 +962,29 @@ string8 format_file_size_short(uint64_t size, uint64_t * outUsedScale) { return ret; } +pfc::string8 format_index(size_t idx) { + return idx == SIZE_MAX ? "" : pfc::format_uint(idx); +} + +pfc::string8 format_permutation(const size_t* arg, size_t n) { + pfc::string_formatter ret; + for( size_t walk = 0; walk < n; ++ walk ) { + if (arg[walk] != walk) { + if ( !ret.is_empty() ) ret << ", "; + ret << arg[walk] << "->" << walk; + } + } + return ret; +} +pfc::string8 format_mask(pfc::bit_array const& mask, size_t n) { + pfc::string_formatter ret; + mask.for_each(true, 0, n, [&] (size_t idx) { + if (!ret.is_empty() ) ret << ", "; + ret << n; + }); + return ret; +} + bool string_base::truncate_eol(t_size start) { const char * ptr = get_ptr() + start; diff --git a/3rdparty/foo_SDK/pfc/string_base.h b/3rdparty/foo_SDK/pfc/string_base.h index df3148e5..c68793c4 100644 --- a/3rdparty/foo_SDK/pfc/string_base.h +++ b/3rdparty/foo_SDK/pfc/string_base.h @@ -222,7 +222,8 @@ namespace pfc { string8 string_directory(const char * p_path); void float_to_string(char * out,t_size out_max,double val,unsigned precision,bool force_sign = false);//doesnt add E+X etc, has internal range limits, useful for storing float numbers as strings without having to bother with international coma/dot settings BS - double string_to_float(const char * src,t_size len = SIZE_MAX) noexcept; + double string_to_float(const char * src,t_size len) noexcept; + double string_to_float(const char * src) noexcept; string8 format_float(double p_val,unsigned p_width = 0,unsigned p_prec = 7); @@ -258,6 +259,9 @@ namespace pfc { string8 format_file_size_short(uint64_t size, uint64_t * outScaleUsed = nullptr); + string8 format_index(size_t idx); + string8 format_permutation(const size_t* arg, size_t n); + string8 format_mask(bit_array const& mask, size_t n); } inline pfc::string_base & operator<<(pfc::string_base & p_fmt,const char * p_source) {p_fmt.add_string_(p_source); return p_fmt;} @@ -310,8 +314,10 @@ namespace pfc { namespace pfc { - void stringToUpperAppend(string_base & p_out, const char * p_source, t_size p_sourceLen); - void stringToLowerAppend(string_base & p_out, const char * p_source, t_size p_sourceLen); + void stringToUpperAppend(string_base & p_out, const char * p_source, t_size p_sourceLen = SIZE_MAX); + void stringToLowerAppend(string_base & p_out, const char * p_source, t_size p_sourceLen = SIZE_MAX); + void stringToUpperHere(string_base& p_out, const char* p_source, t_size p_sourceLen = SIZE_MAX); + void stringToLowerHere(string_base& p_out, const char* p_source, t_size p_sourceLen = SIZE_MAX); t_uint32 charLower(t_uint32 param); t_uint32 charUpper(t_uint32 param); char ascii_tolower_lookup(char c); diff --git a/3rdparty/foo_SDK/pfc/string_conv.h b/3rdparty/foo_SDK/pfc/string_conv.h index a45e7e17..e3f12e35 100644 --- a/3rdparty/foo_SDK/pfc/string_conv.h +++ b/3rdparty/foo_SDK/pfc/string_conv.h @@ -72,14 +72,14 @@ namespace pfc { template<> inline const char * null_string_t() {return "";} template<> inline const wchar_t * null_string_t() {return L"";} - template t_size strlen_t(const t_char * p_string,t_size p_string_size = ~0) { + template t_size strlen_t(const t_char * p_string,t_size p_string_size = SIZE_MAX) { for(t_size n=0;n bool string_is_empty_t(const t_char * p_string,t_size p_string_size = ~0) { + template bool string_is_empty_t(const t_char * p_string,t_size p_string_size = SIZE_MAX) { if (p_string_size == 0) return true; return p_string[0] == 0; } @@ -101,9 +101,9 @@ namespace pfc { class string_utf8_from_wide_t { public: string_utf8_from_wide_t() {} - string_utf8_from_wide_t(const wchar_t * p_source,t_size p_source_size = ~0) {convert(p_source,p_source_size);} + string_utf8_from_wide_t(const wchar_t * p_source,t_size p_source_size = SIZE_MAX) {convert(p_source,p_source_size);} - void convert(const wchar_t * p_source,t_size p_source_size = ~0) { + void convert(const wchar_t * p_source,t_size p_source_size = SIZE_MAX) { t_size size = estimate_wide_to_utf8(p_source,p_source_size); m_buffer.set_size(size); convert_wide_to_utf8( m_buffer.get_ptr_var(),size,p_source,p_source_size); @@ -173,9 +173,9 @@ namespace pfc { class string_wide_from_win1252_t { public: string_wide_from_win1252_t() {} - string_wide_from_win1252_t(const char * p_source,t_size p_source_size = ~0) {convert(p_source,p_source_size);} + string_wide_from_win1252_t(const char * p_source,t_size p_source_size = SIZE_MAX) {convert(p_source,p_source_size);} - void convert(const char * p_source,t_size p_source_size = ~0) { + void convert(const char * p_source,t_size p_source_size = SIZE_MAX) { t_size size = estimate_win1252_to_wide(p_source,p_source_size); m_buffer.set_size(size); convert_win1252_to_wide(m_buffer.get_ptr_var(),size,p_source,p_source_size); @@ -196,9 +196,9 @@ namespace pfc { class string_win1252_from_wide_t { public: string_win1252_from_wide_t() {} - string_win1252_from_wide_t(const wchar_t * p_source,t_size p_source_size = ~0) {convert(p_source,p_source_size);} + string_win1252_from_wide_t(const wchar_t * p_source,t_size p_source_size = SIZE_MAX) {convert(p_source,p_source_size);} - void convert(const wchar_t * p_source,t_size p_source_size = ~0) { + void convert(const wchar_t * p_source,t_size p_source_size = SIZE_MAX) { t_size size = estimate_wide_to_win1252(p_source,p_source_size); m_buffer.set_size(size); convert_wide_to_win1252(m_buffer.get_ptr_var(),size,p_source,p_source_size); @@ -219,9 +219,9 @@ namespace pfc { class string_utf8_from_win1252_t { public: string_utf8_from_win1252_t() {} - string_utf8_from_win1252_t(const char * p_source,t_size p_source_size = ~0) {convert(p_source,p_source_size);} + string_utf8_from_win1252_t(const char * p_source,t_size p_source_size = SIZE_MAX) {convert(p_source,p_source_size);} - void convert(const char * p_source,t_size p_source_size = ~0) { + void convert(const char * p_source,t_size p_source_size = SIZE_MAX) { t_size size = estimate_win1252_to_utf8(p_source,p_source_size); m_buffer.set_size(size); convert_win1252_to_utf8(m_buffer.get_ptr_var(),size,p_source,p_source_size); @@ -242,9 +242,9 @@ namespace pfc { class string_win1252_from_utf8_t { public: string_win1252_from_utf8_t() {} - string_win1252_from_utf8_t(const char * p_source,t_size p_source_size = ~0) {convert(p_source,p_source_size);} + string_win1252_from_utf8_t(const char * p_source,t_size p_source_size = SIZE_MAX) {convert(p_source,p_source_size);} - void convert(const char * p_source,t_size p_source_size = ~0) { + void convert(const char * p_source,t_size p_source_size = SIZE_MAX) { t_size size = estimate_utf8_to_win1252(p_source,p_source_size); m_buffer.set_size(size); convert_utf8_to_win1252(m_buffer.get_ptr_var(),size,p_source,p_source_size); @@ -263,9 +263,9 @@ namespace pfc { class string_ascii_from_utf8 { public: string_ascii_from_utf8() {} - string_ascii_from_utf8( const char * p_source, t_size p_source_size = ~0) { convert(p_source, p_source_size); } + string_ascii_from_utf8( const char * p_source, t_size p_source_size = SIZE_MAX) { convert(p_source, p_source_size); } - void convert( const char * p_source, t_size p_source_size = ~0) { + void convert( const char * p_source, t_size p_source_size = SIZE_MAX) { t_size size = estimate_utf8_to_ascii(p_source, p_source_size); m_buffer.set_size(size); convert_utf8_to_ascii(m_buffer.get_ptr_var(), size, p_source, p_source_size); @@ -283,9 +283,9 @@ namespace pfc { class string_utf8_from_utf16 { public: string_utf8_from_utf16() {} - string_utf8_from_utf16( const char16_t * p_source, size_t p_source_size = ~0) {convert(p_source, p_source_size);} + string_utf8_from_utf16( const char16_t * p_source, size_t p_source_size = SIZE_MAX) {convert(p_source, p_source_size);} - void convert( const char16_t * p_source, size_t p_source_size = ~0) { + void convert( const char16_t * p_source, size_t p_source_size = SIZE_MAX) { size_t size = estimate_utf16_to_utf8(p_source, p_source_size); m_buffer.set_size(size); convert_utf16_to_utf8(m_buffer.get_ptr_var(), size, p_source, p_source_size ); @@ -387,9 +387,9 @@ namespace pfc { public: string_wide_from_codepage_t() {} string_wide_from_codepage_t(const string_wide_from_codepage_t & p_source) : m_buffer(p_source.m_buffer) {} - string_wide_from_codepage_t(unsigned p_codepage,const char * p_source,t_size p_source_size = ~0) {convert(p_codepage,p_source,p_source_size);} + string_wide_from_codepage_t(unsigned p_codepage,const char * p_source,t_size p_source_size = SIZE_MAX) {convert(p_codepage,p_source,p_source_size);} - void convert(unsigned p_codepage,const char * p_source,t_size p_source_size = ~0) { + void convert(unsigned p_codepage,const char * p_source,t_size p_source_size = SIZE_MAX) { t_size size = estimate_codepage_to_wide(p_codepage,p_source,p_source_size); m_buffer.set_size(size); convert_codepage_to_wide(p_codepage, m_buffer.get_ptr_var(),size,p_source,p_source_size); @@ -411,9 +411,9 @@ namespace pfc { public: string_codepage_from_wide_t() {} string_codepage_from_wide_t(const string_codepage_from_wide_t & p_source) : m_buffer(p_source.m_buffer) {} - string_codepage_from_wide_t(unsigned p_codepage,const wchar_t * p_source,t_size p_source_size = ~0) {convert(p_codepage,p_source,p_source_size);} + string_codepage_from_wide_t(unsigned p_codepage,const wchar_t * p_source,t_size p_source_size = SIZE_MAX) {convert(p_codepage,p_source,p_source_size);} - void convert(unsigned p_codepage,const wchar_t * p_source,t_size p_source_size = ~0) { + void convert(unsigned p_codepage,const wchar_t * p_source,t_size p_source_size = SIZE_MAX) { t_size size = estimate_wide_to_codepage(p_codepage,p_source,p_source_size); m_buffer.set_size(size); convert_wide_to_codepage(p_codepage, m_buffer.get_ptr_var(),size,p_source,p_source_size); @@ -433,7 +433,7 @@ namespace pfc { public: string_codepage_from_utf8() {} string_codepage_from_utf8(const string_codepage_from_utf8 & p_source) : m_buffer(p_source.m_buffer) {} - string_codepage_from_utf8(unsigned p_codepage,const char * p_source,t_size p_source_size = ~0) {convert(p_codepage,p_source,p_source_size);} + string_codepage_from_utf8(unsigned p_codepage,const char * p_source,t_size p_source_size = SIZE_MAX) {convert(p_codepage,p_source,p_source_size);} void convert(unsigned p_codepage,const char * p_source,t_size p_source_size = SIZE_MAX) { string_wide_from_utf8 temp; @@ -456,9 +456,9 @@ namespace pfc { public: string_utf8_from_codepage() {} string_utf8_from_codepage(const string_utf8_from_codepage & p_source) : m_buffer(p_source.m_buffer) {} - string_utf8_from_codepage(unsigned p_codepage,const char * p_source,t_size p_source_size = ~0) {convert(p_codepage,p_source,p_source_size);} + string_utf8_from_codepage(unsigned p_codepage,const char * p_source,t_size p_source_size = SIZE_MAX) {convert(p_codepage,p_source,p_source_size);} - void convert(unsigned p_codepage,const char * p_source,t_size p_source_size = ~0) { + void convert(unsigned p_codepage,const char * p_source,t_size p_source_size = SIZE_MAX) { string_wide_from_codepage temp; temp.convert(p_codepage,p_source,p_source_size); t_size size = estimate_wide_to_utf8(temp,SIZE_MAX); @@ -480,13 +480,13 @@ namespace pfc { public: string_utf8_from_ansi() {} string_utf8_from_ansi(const string_utf8_from_ansi & p_source) : m_buffer(p_source.m_buffer) {} - string_utf8_from_ansi(const char * p_source,t_size p_source_size = ~0) : m_buffer(codepage_system,p_source,p_source_size) {} + string_utf8_from_ansi(const char * p_source,t_size p_source_size = SIZE_MAX) : m_buffer(codepage_system,p_source,p_source_size) {} operator const char * () const {return get_ptr();} const char * get_ptr() const {return m_buffer.get_ptr();} const char * toString() const {return get_ptr();} bool is_empty() const {return string_is_empty_t(get_ptr());} t_size length() const {return strlen_t(get_ptr());} - void convert(const char * p_source,t_size p_source_size = ~0) {m_buffer.convert(codepage_system,p_source,p_source_size);} + void convert(const char * p_source,t_size p_source_size = SIZE_MAX) {m_buffer.convert(codepage_system,p_source,p_source_size);} private: string_utf8_from_codepage m_buffer; @@ -496,13 +496,13 @@ namespace pfc { public: string_ansi_from_utf8() {} string_ansi_from_utf8(const string_ansi_from_utf8 & p_source) : m_buffer(p_source.m_buffer) {} - string_ansi_from_utf8(const char * p_source,t_size p_source_size = ~0) : m_buffer(codepage_system,p_source,p_source_size) {} + string_ansi_from_utf8(const char * p_source,t_size p_source_size = SIZE_MAX) : m_buffer(codepage_system,p_source,p_source_size) {} operator const char * () const {return get_ptr();} const char * get_ptr() const {return m_buffer.get_ptr();} bool is_empty() const {return string_is_empty_t(get_ptr());} t_size length() const {return strlen_t(get_ptr());} - void convert(const char * p_source,t_size p_source_size = ~0) {m_buffer.convert(codepage_system,p_source,p_source_size);} + void convert(const char * p_source,t_size p_source_size = SIZE_MAX) {m_buffer.convert(codepage_system,p_source,p_source_size);} private: string_codepage_from_utf8 m_buffer; @@ -512,13 +512,13 @@ namespace pfc { public: string_wide_from_ansi() {} string_wide_from_ansi(const string_wide_from_ansi & p_source) : m_buffer(p_source.m_buffer) {} - string_wide_from_ansi(const char * p_source,t_size p_source_size = ~0) : m_buffer(codepage_system,p_source,p_source_size) {} + string_wide_from_ansi(const char * p_source,t_size p_source_size = SIZE_MAX) : m_buffer(codepage_system,p_source,p_source_size) {} operator const wchar_t * () const {return get_ptr();} const wchar_t * get_ptr() const {return m_buffer.get_ptr();} bool is_empty() const {return string_is_empty_t(get_ptr());} t_size length() const {return strlen_t(get_ptr());} - void convert(const char * p_source,t_size p_source_size = ~0) {m_buffer.convert(codepage_system,p_source,p_source_size);} + void convert(const char * p_source,t_size p_source_size = SIZE_MAX) {m_buffer.convert(codepage_system,p_source,p_source_size);} private: string_wide_from_codepage m_buffer; @@ -528,13 +528,13 @@ namespace pfc { public: string_ansi_from_wide() {} string_ansi_from_wide(const string_ansi_from_wide & p_source) : m_buffer(p_source.m_buffer) {} - string_ansi_from_wide(const wchar_t * p_source,t_size p_source_size = ~0) : m_buffer(codepage_system,p_source,p_source_size) {} + string_ansi_from_wide(const wchar_t * p_source,t_size p_source_size = SIZE_MAX) : m_buffer(codepage_system,p_source,p_source_size) {} operator const char * () const {return get_ptr();} const char * get_ptr() const {return m_buffer.get_ptr();} bool is_empty() const {return string_is_empty_t(get_ptr());} t_size length() const {return strlen_t(get_ptr());} - void convert(const wchar_t * p_source,t_size p_source_size = ~0) {m_buffer.convert(codepage_system,p_source,p_source_size);} + void convert(const wchar_t * p_source,t_size p_source_size = SIZE_MAX) {m_buffer.convert(codepage_system,p_source,p_source_size);} private: string_codepage_from_wide m_buffer; @@ -552,14 +552,14 @@ namespace pfc { class string_utf8_from_os_ex { public: - template string_utf8_from_os_ex(const t_source * source, t_size sourceLen = ~0) { + template string_utf8_from_os_ex(const t_source * source, t_size sourceLen = SIZE_MAX) { convert(source,sourceLen); } - void convert(const char * source, t_size sourceLen = ~0) { + void convert(const char * source, t_size sourceLen = SIZE_MAX) { m_buffer = string_utf8_from_ansi(source,sourceLen); } - void convert(const wchar_t * source, t_size sourceLen = ~0) { + void convert(const wchar_t * source, t_size sourceLen = SIZE_MAX) { m_buffer = string_utf8_from_wide(source,sourceLen); } diff --git a/3rdparty/foo_SDK/pfc/synchro_win.h b/3rdparty/foo_SDK/pfc/synchro_win.h index c52a193b..70e44c8f 100644 --- a/3rdparty/foo_SDK/pfc/synchro_win.h +++ b/3rdparty/foo_SDK/pfc/synchro_win.h @@ -43,8 +43,7 @@ namespace pfc { // Warning, non-recursion proof class readWriteLock { public: - readWriteLock() : theLock() { - } + readWriteLock() {} void enterRead() { AcquireSRWLockShared( & theLock ); @@ -63,7 +62,7 @@ class readWriteLock { readWriteLock(const readWriteLock&) = delete; void operator=(const readWriteLock&) = delete; - SRWLOCK theLock; + SRWLOCK theLock = SRWLOCK_INIT; }; typedef ::_critical_section_base mutexBase_t; diff --git a/3rdparty/foo_SDK/pfc/threads.h b/3rdparty/foo_SDK/pfc/threads.h index dd3eccec..1338e348 100644 --- a/3rdparty/foo_SDK/pfc/threads.h +++ b/3rdparty/foo_SDK/pfc/threads.h @@ -59,7 +59,10 @@ namespace pfc { thread(); ~thread() {PFC_ASSERT(!isActive()); waitTillDone();} void start( arg_t const & arg = argCurrentThread() ); + //! Valid thread object (created and not joined)? bool isActive() const; + //! Joins the thread: blocks until complete, releases resources. \n + //! After waitTillDone() returns, isActive() becomes false. void waitTillDone() {close();} #ifdef _WIN32 void winStart(int priority, DWORD * outThreadID); diff --git a/3rdparty/foo_SDK/pfc/win-objects.cpp b/3rdparty/foo_SDK/pfc/win-objects.cpp index eb50c39f..0ed07bbe 100644 --- a/3rdparty/foo_SDK/pfc/win-objects.cpp +++ b/3rdparty/foo_SDK/pfc/win-objects.cpp @@ -421,6 +421,43 @@ namespace pfc { } #endif } + pfc::string8 format_window(HWND wnd) { + pfc::string_formatter ret; + ret << "0x" << format_hex( (size_t)wnd ); + auto title = getWindowText(wnd); + if (title.length() > 0) { + ret << " [" << title << "]"; + } + return ret; + } + +#define _(X) {X, #X} + struct winStyle_t { + DWORD v; const char * n; + }; + static const winStyle_t winStyles[] = { + _(WS_POPUP), _(WS_CHILD), _(WS_MINIMIZE), _(WS_VISIBLE), + _(WS_DISABLED), _(WS_CLIPSIBLINGS), _(WS_CLIPCHILDREN), _(WS_MAXIMIZE), + _(WS_BORDER), _(WS_DLGFRAME), _(WS_VSCROLL), _(WS_HSCROLL), + _(WS_SYSMENU), _(WS_THICKFRAME), _(WS_GROUP), _(WS_TABSTOP), + _(WS_MINIMIZEBOX), _(WS_MAXIMIZEBOX) + }; + + pfc::string8 format_windowStyle(DWORD style) { + pfc::string_formatter ret; + ret << "0x" << format_hex( style, 8 ); + if (style != 0) { + pfc::string_formatter label; + for (auto& s : winStyles) if (style & s.v) { + if ( label.length() > 0 ) label << "|"; + label << s.n; + } + if (label.length() > 0) { + ret << " [" << label << "]"; + } + } + return ret; + } } #else @@ -478,6 +515,19 @@ namespace pfc { pfc::string8 unicodeNormalizeC(const char* str) { return winUnicodeNormalize(str, NormalizationC); } + + int winNaturalSortCompare(const char* s1, const char* s2) { + return winNaturalSortCompare(wideFromUTF8(s1), wideFromUTF8(s2)); + } + int winNaturalSortCompare(const wchar_t* s1, const wchar_t* s2) { + return lstrcmp(s1, s2); + } + int winNaturalSortCompareI(const char* s1, const char* s2) { + return winNaturalSortCompareI(wideFromUTF8(s1), wideFromUTF8(s2)); + } + int winNaturalSortCompareI(const wchar_t* s1, const wchar_t* s2) { + return lstrcmpi(s1, s2); + } } #endif // _WIN32 diff --git a/3rdparty/foo_SDK/pfc/win-objects.h b/3rdparty/foo_SDK/pfc/win-objects.h index 3ca3aa52..c7a78e9a 100644 --- a/3rdparty/foo_SDK/pfc/win-objects.h +++ b/3rdparty/foo_SDK/pfc/win-objects.h @@ -168,7 +168,7 @@ namespace pfc { class event : public win32_event { public: - event() { create(true, false); } + event(bool initial = false) { create(true, initial); } HANDLE get_handle() const { return win32_event::get(); } }; @@ -333,5 +333,14 @@ namespace pfc { #ifdef PFC_WINDOWS_DESKTOP_APP void winSetThreadDescription(HANDLE hThread, const wchar_t * desc); + + pfc::string8 format_window(HWND wnd); + pfc::string8 format_windowStyle(DWORD); #endif // PFC_WINDOWS_DESKTOP_APP + + int winNaturalSortCompare(const char* s1, const char* s2); + int winNaturalSortCompare(const wchar_t* s1, const wchar_t* s2); + int winNaturalSortCompareI(const char* s1, const char* s2); + int winNaturalSortCompareI(const wchar_t* s1, const wchar_t* s2); + } diff --git a/3rdparty/foo_SDK/sdk-license.txt b/3rdparty/foo_SDK/sdk-license.txt index eac453f3..0824e77e 100644 --- a/3rdparty/foo_SDK/sdk-license.txt +++ b/3rdparty/foo_SDK/sdk-license.txt @@ -1,5 +1,5 @@ -foobar2000 1.6 SDK -Copyright (c) 2001-2021, Peter Pawlowski +foobar2000 2.0 SDK +Copyright (c) 2001-2023, Peter Pawlowski All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: diff --git a/3rdparty/foo_SDK/sdk-readme.html b/3rdparty/foo_SDK/sdk-readme.html index 69b897c1..3f7a7a5a 100644 --- a/3rdparty/foo_SDK/sdk-readme.html +++ b/3rdparty/foo_SDK/sdk-readme.html @@ -8,11 +8,11 @@

-foobar2000 SDK, version 2022-11-16 +foobar2000 SDK, version 2023-09-13

Documentation:
-SDK release notes
+SDK Change Log
foobar2000 Development Overview

diff --git a/build/foo_openlyrics.sln b/build/foo_openlyrics.sln index b8fce6e0..109d4b3c 100644 --- a/build/foo_openlyrics.sln +++ b/build/foo_openlyrics.sln @@ -35,110 +35,228 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "metrics", "metrics", "{0F97 EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenLyricsMetrics", "..\metrics\metrics_server\OpenLyricsMetrics.csproj", "{EF666738-04E0-4AAB-A269-058CDA62EDD0}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "shared", "..\3rdparty\foo_SDK\foobar2000\shared\shared.vcxproj", "{054C606B-17BF-4540-AC4E-A9A7243628B8}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|ARM64 = Debug|ARM64 + Debug|ARM64EC = Debug|ARM64EC Debug|x64 = Debug|x64 Debug|x86 = Debug|x86 + Release|ARM64 = Release|ARM64 + Release|ARM64EC = Release|ARM64EC Release|x64 = Release|x64 Release|x86 = Release|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution + {52512D36-B5D0-4883-837B-4B56FF5AD31F}.Debug|ARM64.ActiveCfg = Debug|x64 + {52512D36-B5D0-4883-837B-4B56FF5AD31F}.Debug|ARM64.Build.0 = Debug|x64 + {52512D36-B5D0-4883-837B-4B56FF5AD31F}.Debug|ARM64EC.ActiveCfg = Debug|x64 + {52512D36-B5D0-4883-837B-4B56FF5AD31F}.Debug|ARM64EC.Build.0 = Debug|x64 {52512D36-B5D0-4883-837B-4B56FF5AD31F}.Debug|x64.ActiveCfg = Debug|x64 {52512D36-B5D0-4883-837B-4B56FF5AD31F}.Debug|x64.Build.0 = Debug|x64 {52512D36-B5D0-4883-837B-4B56FF5AD31F}.Debug|x86.ActiveCfg = Debug|Win32 {52512D36-B5D0-4883-837B-4B56FF5AD31F}.Debug|x86.Build.0 = Debug|Win32 + {52512D36-B5D0-4883-837B-4B56FF5AD31F}.Release|ARM64.ActiveCfg = Release|x64 + {52512D36-B5D0-4883-837B-4B56FF5AD31F}.Release|ARM64.Build.0 = Release|x64 + {52512D36-B5D0-4883-837B-4B56FF5AD31F}.Release|ARM64EC.ActiveCfg = Release|x64 + {52512D36-B5D0-4883-837B-4B56FF5AD31F}.Release|ARM64EC.Build.0 = Release|x64 {52512D36-B5D0-4883-837B-4B56FF5AD31F}.Release|x64.ActiveCfg = Release|x64 {52512D36-B5D0-4883-837B-4B56FF5AD31F}.Release|x64.Build.0 = Release|x64 {52512D36-B5D0-4883-837B-4B56FF5AD31F}.Release|x86.ActiveCfg = Release|Win32 {52512D36-B5D0-4883-837B-4B56FF5AD31F}.Release|x86.Build.0 = Release|Win32 + {E8091321-D79D-4575-86EF-064EA1A4A20D}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {E8091321-D79D-4575-86EF-064EA1A4A20D}.Debug|ARM64.Build.0 = Debug|ARM64 + {E8091321-D79D-4575-86EF-064EA1A4A20D}.Debug|ARM64EC.ActiveCfg = Debug|ARM64EC + {E8091321-D79D-4575-86EF-064EA1A4A20D}.Debug|ARM64EC.Build.0 = Debug|ARM64EC {E8091321-D79D-4575-86EF-064EA1A4A20D}.Debug|x64.ActiveCfg = Debug|x64 {E8091321-D79D-4575-86EF-064EA1A4A20D}.Debug|x64.Build.0 = Debug|x64 {E8091321-D79D-4575-86EF-064EA1A4A20D}.Debug|x86.ActiveCfg = Debug|Win32 {E8091321-D79D-4575-86EF-064EA1A4A20D}.Debug|x86.Build.0 = Debug|Win32 + {E8091321-D79D-4575-86EF-064EA1A4A20D}.Release|ARM64.ActiveCfg = Release|ARM64 + {E8091321-D79D-4575-86EF-064EA1A4A20D}.Release|ARM64.Build.0 = Release|ARM64 + {E8091321-D79D-4575-86EF-064EA1A4A20D}.Release|ARM64EC.ActiveCfg = Release|ARM64EC + {E8091321-D79D-4575-86EF-064EA1A4A20D}.Release|ARM64EC.Build.0 = Release|ARM64EC {E8091321-D79D-4575-86EF-064EA1A4A20D}.Release|x64.ActiveCfg = Release|x64 {E8091321-D79D-4575-86EF-064EA1A4A20D}.Release|x64.Build.0 = Release|x64 {E8091321-D79D-4575-86EF-064EA1A4A20D}.Release|x86.ActiveCfg = Release|Win32 {E8091321-D79D-4575-86EF-064EA1A4A20D}.Release|x86.Build.0 = Release|Win32 + {EBFFFB4E-261D-44D3-B89C-957B31A0BF9C}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {EBFFFB4E-261D-44D3-B89C-957B31A0BF9C}.Debug|ARM64.Build.0 = Debug|ARM64 + {EBFFFB4E-261D-44D3-B89C-957B31A0BF9C}.Debug|ARM64EC.ActiveCfg = Debug|ARM64EC + {EBFFFB4E-261D-44D3-B89C-957B31A0BF9C}.Debug|ARM64EC.Build.0 = Debug|ARM64EC {EBFFFB4E-261D-44D3-B89C-957B31A0BF9C}.Debug|x64.ActiveCfg = Debug|x64 {EBFFFB4E-261D-44D3-B89C-957B31A0BF9C}.Debug|x64.Build.0 = Debug|x64 {EBFFFB4E-261D-44D3-B89C-957B31A0BF9C}.Debug|x86.ActiveCfg = Debug|Win32 {EBFFFB4E-261D-44D3-B89C-957B31A0BF9C}.Debug|x86.Build.0 = Debug|Win32 + {EBFFFB4E-261D-44D3-B89C-957B31A0BF9C}.Release|ARM64.ActiveCfg = Release|ARM64 + {EBFFFB4E-261D-44D3-B89C-957B31A0BF9C}.Release|ARM64.Build.0 = Release|ARM64 + {EBFFFB4E-261D-44D3-B89C-957B31A0BF9C}.Release|ARM64EC.ActiveCfg = Release|ARM64EC + {EBFFFB4E-261D-44D3-B89C-957B31A0BF9C}.Release|ARM64EC.Build.0 = Release|ARM64EC {EBFFFB4E-261D-44D3-B89C-957B31A0BF9C}.Release|x64.ActiveCfg = Release|x64 {EBFFFB4E-261D-44D3-B89C-957B31A0BF9C}.Release|x64.Build.0 = Release|x64 {EBFFFB4E-261D-44D3-B89C-957B31A0BF9C}.Release|x86.ActiveCfg = Release|Win32 {EBFFFB4E-261D-44D3-B89C-957B31A0BF9C}.Release|x86.Build.0 = Release|Win32 + {7729EB82-4069-4414-964B-AD399091A03F}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {7729EB82-4069-4414-964B-AD399091A03F}.Debug|ARM64.Build.0 = Debug|ARM64 + {7729EB82-4069-4414-964B-AD399091A03F}.Debug|ARM64EC.ActiveCfg = Debug|ARM64EC + {7729EB82-4069-4414-964B-AD399091A03F}.Debug|ARM64EC.Build.0 = Debug|ARM64EC {7729EB82-4069-4414-964B-AD399091A03F}.Debug|x64.ActiveCfg = Debug|x64 {7729EB82-4069-4414-964B-AD399091A03F}.Debug|x64.Build.0 = Debug|x64 {7729EB82-4069-4414-964B-AD399091A03F}.Debug|x86.ActiveCfg = Debug|Win32 {7729EB82-4069-4414-964B-AD399091A03F}.Debug|x86.Build.0 = Debug|Win32 + {7729EB82-4069-4414-964B-AD399091A03F}.Release|ARM64.ActiveCfg = Release|ARM64 + {7729EB82-4069-4414-964B-AD399091A03F}.Release|ARM64.Build.0 = Release|ARM64 + {7729EB82-4069-4414-964B-AD399091A03F}.Release|ARM64EC.ActiveCfg = Release|ARM64EC + {7729EB82-4069-4414-964B-AD399091A03F}.Release|ARM64EC.Build.0 = Release|ARM64EC {7729EB82-4069-4414-964B-AD399091A03F}.Release|x64.ActiveCfg = Release|x64 {7729EB82-4069-4414-964B-AD399091A03F}.Release|x64.Build.0 = Release|x64 {7729EB82-4069-4414-964B-AD399091A03F}.Release|x86.ActiveCfg = Release|Win32 {7729EB82-4069-4414-964B-AD399091A03F}.Release|x86.Build.0 = Release|Win32 + {71AD2674-065B-48F5-B8B0-E1F9D3892081}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {71AD2674-065B-48F5-B8B0-E1F9D3892081}.Debug|ARM64.Build.0 = Debug|ARM64 + {71AD2674-065B-48F5-B8B0-E1F9D3892081}.Debug|ARM64EC.ActiveCfg = Debug|ARM64EC + {71AD2674-065B-48F5-B8B0-E1F9D3892081}.Debug|ARM64EC.Build.0 = Debug|ARM64EC {71AD2674-065B-48F5-B8B0-E1F9D3892081}.Debug|x64.ActiveCfg = Debug|x64 {71AD2674-065B-48F5-B8B0-E1F9D3892081}.Debug|x64.Build.0 = Debug|x64 {71AD2674-065B-48F5-B8B0-E1F9D3892081}.Debug|x86.ActiveCfg = Debug|Win32 {71AD2674-065B-48F5-B8B0-E1F9D3892081}.Debug|x86.Build.0 = Debug|Win32 + {71AD2674-065B-48F5-B8B0-E1F9D3892081}.Release|ARM64.ActiveCfg = Release|ARM64 + {71AD2674-065B-48F5-B8B0-E1F9D3892081}.Release|ARM64.Build.0 = Release|ARM64 + {71AD2674-065B-48F5-B8B0-E1F9D3892081}.Release|ARM64EC.ActiveCfg = Release|ARM64EC + {71AD2674-065B-48F5-B8B0-E1F9D3892081}.Release|ARM64EC.Build.0 = Release|ARM64EC {71AD2674-065B-48F5-B8B0-E1F9D3892081}.Release|x64.ActiveCfg = Release|x64 {71AD2674-065B-48F5-B8B0-E1F9D3892081}.Release|x64.Build.0 = Release|x64 {71AD2674-065B-48F5-B8B0-E1F9D3892081}.Release|x86.ActiveCfg = Release|Win32 {71AD2674-065B-48F5-B8B0-E1F9D3892081}.Release|x86.Build.0 = Release|Win32 + {EE47764E-A202-4F85-A767-ABDAB4AFF35F}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {EE47764E-A202-4F85-A767-ABDAB4AFF35F}.Debug|ARM64.Build.0 = Debug|ARM64 + {EE47764E-A202-4F85-A767-ABDAB4AFF35F}.Debug|ARM64EC.ActiveCfg = Debug|ARM64EC + {EE47764E-A202-4F85-A767-ABDAB4AFF35F}.Debug|ARM64EC.Build.0 = Debug|ARM64EC {EE47764E-A202-4F85-A767-ABDAB4AFF35F}.Debug|x64.ActiveCfg = Debug|x64 {EE47764E-A202-4F85-A767-ABDAB4AFF35F}.Debug|x64.Build.0 = Debug|x64 {EE47764E-A202-4F85-A767-ABDAB4AFF35F}.Debug|x86.ActiveCfg = Debug|Win32 {EE47764E-A202-4F85-A767-ABDAB4AFF35F}.Debug|x86.Build.0 = Debug|Win32 + {EE47764E-A202-4F85-A767-ABDAB4AFF35F}.Release|ARM64.ActiveCfg = Release|ARM64 + {EE47764E-A202-4F85-A767-ABDAB4AFF35F}.Release|ARM64.Build.0 = Release|ARM64 + {EE47764E-A202-4F85-A767-ABDAB4AFF35F}.Release|ARM64EC.ActiveCfg = Release|ARM64EC + {EE47764E-A202-4F85-A767-ABDAB4AFF35F}.Release|ARM64EC.Build.0 = Release|ARM64EC {EE47764E-A202-4F85-A767-ABDAB4AFF35F}.Release|x64.ActiveCfg = Release|x64 {EE47764E-A202-4F85-A767-ABDAB4AFF35F}.Release|x64.Build.0 = Release|x64 {EE47764E-A202-4F85-A767-ABDAB4AFF35F}.Release|x86.ActiveCfg = Release|Win32 {EE47764E-A202-4F85-A767-ABDAB4AFF35F}.Release|x86.Build.0 = Release|Win32 + {07CF01C0-B887-499D-AD9C-799CB6A9FE64}.Debug|ARM64.ActiveCfg = Debug|x64 + {07CF01C0-B887-499D-AD9C-799CB6A9FE64}.Debug|ARM64.Build.0 = Debug|x64 + {07CF01C0-B887-499D-AD9C-799CB6A9FE64}.Debug|ARM64EC.ActiveCfg = Debug|x64 + {07CF01C0-B887-499D-AD9C-799CB6A9FE64}.Debug|ARM64EC.Build.0 = Debug|x64 {07CF01C0-B887-499D-AD9C-799CB6A9FE64}.Debug|x64.ActiveCfg = Debug|x64 {07CF01C0-B887-499D-AD9C-799CB6A9FE64}.Debug|x64.Build.0 = Debug|x64 {07CF01C0-B887-499D-AD9C-799CB6A9FE64}.Debug|x86.ActiveCfg = Debug|Win32 {07CF01C0-B887-499D-AD9C-799CB6A9FE64}.Debug|x86.Build.0 = Debug|Win32 + {07CF01C0-B887-499D-AD9C-799CB6A9FE64}.Release|ARM64.ActiveCfg = Release|x64 + {07CF01C0-B887-499D-AD9C-799CB6A9FE64}.Release|ARM64.Build.0 = Release|x64 + {07CF01C0-B887-499D-AD9C-799CB6A9FE64}.Release|ARM64EC.ActiveCfg = Release|x64 + {07CF01C0-B887-499D-AD9C-799CB6A9FE64}.Release|ARM64EC.Build.0 = Release|x64 {07CF01C0-B887-499D-AD9C-799CB6A9FE64}.Release|x64.ActiveCfg = Release|x64 {07CF01C0-B887-499D-AD9C-799CB6A9FE64}.Release|x64.Build.0 = Release|x64 {07CF01C0-B887-499D-AD9C-799CB6A9FE64}.Release|x86.ActiveCfg = Release|Win32 {07CF01C0-B887-499D-AD9C-799CB6A9FE64}.Release|x86.Build.0 = Release|Win32 + {3181FC06-B4ED-4609-8B4F-7220571C6992}.Debug|ARM64.ActiveCfg = Debug|x64 + {3181FC06-B4ED-4609-8B4F-7220571C6992}.Debug|ARM64.Build.0 = Debug|x64 + {3181FC06-B4ED-4609-8B4F-7220571C6992}.Debug|ARM64EC.ActiveCfg = Debug|x64 + {3181FC06-B4ED-4609-8B4F-7220571C6992}.Debug|ARM64EC.Build.0 = Debug|x64 {3181FC06-B4ED-4609-8B4F-7220571C6992}.Debug|x64.ActiveCfg = Debug|x64 {3181FC06-B4ED-4609-8B4F-7220571C6992}.Debug|x64.Build.0 = Debug|x64 {3181FC06-B4ED-4609-8B4F-7220571C6992}.Debug|x86.ActiveCfg = Debug|Win32 {3181FC06-B4ED-4609-8B4F-7220571C6992}.Debug|x86.Build.0 = Debug|Win32 + {3181FC06-B4ED-4609-8B4F-7220571C6992}.Release|ARM64.ActiveCfg = Release|x64 + {3181FC06-B4ED-4609-8B4F-7220571C6992}.Release|ARM64.Build.0 = Release|x64 + {3181FC06-B4ED-4609-8B4F-7220571C6992}.Release|ARM64EC.ActiveCfg = Release|x64 + {3181FC06-B4ED-4609-8B4F-7220571C6992}.Release|ARM64EC.Build.0 = Release|x64 {3181FC06-B4ED-4609-8B4F-7220571C6992}.Release|x64.ActiveCfg = Release|x64 {3181FC06-B4ED-4609-8B4F-7220571C6992}.Release|x64.Build.0 = Release|x64 {3181FC06-B4ED-4609-8B4F-7220571C6992}.Release|x86.ActiveCfg = Release|Win32 {3181FC06-B4ED-4609-8B4F-7220571C6992}.Release|x86.Build.0 = Release|Win32 + {7172CDEB-2391-41C4-883D-BD2C7B60C715}.Debug|ARM64.ActiveCfg = Debug|x64 + {7172CDEB-2391-41C4-883D-BD2C7B60C715}.Debug|ARM64.Build.0 = Debug|x64 + {7172CDEB-2391-41C4-883D-BD2C7B60C715}.Debug|ARM64EC.ActiveCfg = Debug|x64 + {7172CDEB-2391-41C4-883D-BD2C7B60C715}.Debug|ARM64EC.Build.0 = Debug|x64 {7172CDEB-2391-41C4-883D-BD2C7B60C715}.Debug|x64.ActiveCfg = Debug|x64 {7172CDEB-2391-41C4-883D-BD2C7B60C715}.Debug|x64.Build.0 = Debug|x64 {7172CDEB-2391-41C4-883D-BD2C7B60C715}.Debug|x86.ActiveCfg = Debug|Win32 {7172CDEB-2391-41C4-883D-BD2C7B60C715}.Debug|x86.Build.0 = Debug|Win32 + {7172CDEB-2391-41C4-883D-BD2C7B60C715}.Release|ARM64.ActiveCfg = Release|x64 + {7172CDEB-2391-41C4-883D-BD2C7B60C715}.Release|ARM64.Build.0 = Release|x64 + {7172CDEB-2391-41C4-883D-BD2C7B60C715}.Release|ARM64EC.ActiveCfg = Release|x64 + {7172CDEB-2391-41C4-883D-BD2C7B60C715}.Release|ARM64EC.Build.0 = Release|x64 {7172CDEB-2391-41C4-883D-BD2C7B60C715}.Release|x64.ActiveCfg = Release|x64 {7172CDEB-2391-41C4-883D-BD2C7B60C715}.Release|x64.Build.0 = Release|x64 {7172CDEB-2391-41C4-883D-BD2C7B60C715}.Release|x86.ActiveCfg = Release|Win32 {7172CDEB-2391-41C4-883D-BD2C7B60C715}.Release|x86.Build.0 = Release|Win32 + {1A6E6173-AF42-4A1A-B62C-2393476B5B4F}.Debug|ARM64.ActiveCfg = Debug|x64 + {1A6E6173-AF42-4A1A-B62C-2393476B5B4F}.Debug|ARM64.Build.0 = Debug|x64 + {1A6E6173-AF42-4A1A-B62C-2393476B5B4F}.Debug|ARM64EC.ActiveCfg = Debug|x64 + {1A6E6173-AF42-4A1A-B62C-2393476B5B4F}.Debug|ARM64EC.Build.0 = Debug|x64 {1A6E6173-AF42-4A1A-B62C-2393476B5B4F}.Debug|x64.ActiveCfg = Debug|x64 {1A6E6173-AF42-4A1A-B62C-2393476B5B4F}.Debug|x64.Build.0 = Debug|x64 {1A6E6173-AF42-4A1A-B62C-2393476B5B4F}.Debug|x86.ActiveCfg = Debug|Win32 {1A6E6173-AF42-4A1A-B62C-2393476B5B4F}.Debug|x86.Build.0 = Debug|Win32 + {1A6E6173-AF42-4A1A-B62C-2393476B5B4F}.Release|ARM64.ActiveCfg = Release|x64 + {1A6E6173-AF42-4A1A-B62C-2393476B5B4F}.Release|ARM64.Build.0 = Release|x64 + {1A6E6173-AF42-4A1A-B62C-2393476B5B4F}.Release|ARM64EC.ActiveCfg = Release|x64 + {1A6E6173-AF42-4A1A-B62C-2393476B5B4F}.Release|ARM64EC.Build.0 = Release|x64 {1A6E6173-AF42-4A1A-B62C-2393476B5B4F}.Release|x64.ActiveCfg = Release|x64 {1A6E6173-AF42-4A1A-B62C-2393476B5B4F}.Release|x64.Build.0 = Release|x64 {1A6E6173-AF42-4A1A-B62C-2393476B5B4F}.Release|x86.ActiveCfg = Release|Win32 {1A6E6173-AF42-4A1A-B62C-2393476B5B4F}.Release|x86.Build.0 = Release|Win32 + {9DBC980D-D0FB-4812-958D-8A077EF62450}.Debug|ARM64.ActiveCfg = Debug|x64 + {9DBC980D-D0FB-4812-958D-8A077EF62450}.Debug|ARM64.Build.0 = Debug|x64 + {9DBC980D-D0FB-4812-958D-8A077EF62450}.Debug|ARM64EC.ActiveCfg = Debug|x64 + {9DBC980D-D0FB-4812-958D-8A077EF62450}.Debug|ARM64EC.Build.0 = Debug|x64 {9DBC980D-D0FB-4812-958D-8A077EF62450}.Debug|x64.ActiveCfg = Debug|x64 {9DBC980D-D0FB-4812-958D-8A077EF62450}.Debug|x64.Build.0 = Debug|x64 {9DBC980D-D0FB-4812-958D-8A077EF62450}.Debug|x86.ActiveCfg = Debug|Win32 {9DBC980D-D0FB-4812-958D-8A077EF62450}.Debug|x86.Build.0 = Debug|Win32 + {9DBC980D-D0FB-4812-958D-8A077EF62450}.Release|ARM64.ActiveCfg = Release|x64 + {9DBC980D-D0FB-4812-958D-8A077EF62450}.Release|ARM64.Build.0 = Release|x64 + {9DBC980D-D0FB-4812-958D-8A077EF62450}.Release|ARM64EC.ActiveCfg = Release|x64 + {9DBC980D-D0FB-4812-958D-8A077EF62450}.Release|ARM64EC.Build.0 = Release|x64 {9DBC980D-D0FB-4812-958D-8A077EF62450}.Release|x64.ActiveCfg = Release|x64 {9DBC980D-D0FB-4812-958D-8A077EF62450}.Release|x64.Build.0 = Release|x64 {9DBC980D-D0FB-4812-958D-8A077EF62450}.Release|x86.ActiveCfg = Release|Win32 {9DBC980D-D0FB-4812-958D-8A077EF62450}.Release|x86.Build.0 = Release|Win32 + {EF666738-04E0-4AAB-A269-058CDA62EDD0}.Debug|ARM64.ActiveCfg = Debug|Any CPU + {EF666738-04E0-4AAB-A269-058CDA62EDD0}.Debug|ARM64.Build.0 = Debug|Any CPU + {EF666738-04E0-4AAB-A269-058CDA62EDD0}.Debug|ARM64EC.ActiveCfg = Debug|Any CPU + {EF666738-04E0-4AAB-A269-058CDA62EDD0}.Debug|ARM64EC.Build.0 = Debug|Any CPU {EF666738-04E0-4AAB-A269-058CDA62EDD0}.Debug|x64.ActiveCfg = Debug|Any CPU {EF666738-04E0-4AAB-A269-058CDA62EDD0}.Debug|x64.Build.0 = Debug|Any CPU {EF666738-04E0-4AAB-A269-058CDA62EDD0}.Debug|x86.ActiveCfg = Debug|Any CPU {EF666738-04E0-4AAB-A269-058CDA62EDD0}.Debug|x86.Build.0 = Debug|Any CPU + {EF666738-04E0-4AAB-A269-058CDA62EDD0}.Release|ARM64.ActiveCfg = Release|Any CPU + {EF666738-04E0-4AAB-A269-058CDA62EDD0}.Release|ARM64.Build.0 = Release|Any CPU + {EF666738-04E0-4AAB-A269-058CDA62EDD0}.Release|ARM64EC.ActiveCfg = Release|Any CPU + {EF666738-04E0-4AAB-A269-058CDA62EDD0}.Release|ARM64EC.Build.0 = Release|Any CPU {EF666738-04E0-4AAB-A269-058CDA62EDD0}.Release|x64.ActiveCfg = Release|Any CPU {EF666738-04E0-4AAB-A269-058CDA62EDD0}.Release|x64.Build.0 = Release|Any CPU {EF666738-04E0-4AAB-A269-058CDA62EDD0}.Release|x86.ActiveCfg = Release|Any CPU {EF666738-04E0-4AAB-A269-058CDA62EDD0}.Release|x86.Build.0 = Release|Any CPU + {054C606B-17BF-4540-AC4E-A9A7243628B8}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {054C606B-17BF-4540-AC4E-A9A7243628B8}.Debug|ARM64.Build.0 = Debug|ARM64 + {054C606B-17BF-4540-AC4E-A9A7243628B8}.Debug|ARM64EC.ActiveCfg = Debug|ARM64EC + {054C606B-17BF-4540-AC4E-A9A7243628B8}.Debug|ARM64EC.Build.0 = Debug|ARM64EC + {054C606B-17BF-4540-AC4E-A9A7243628B8}.Debug|x64.ActiveCfg = Debug|x64 + {054C606B-17BF-4540-AC4E-A9A7243628B8}.Debug|x64.Build.0 = Debug|x64 + {054C606B-17BF-4540-AC4E-A9A7243628B8}.Debug|x86.ActiveCfg = Debug|Win32 + {054C606B-17BF-4540-AC4E-A9A7243628B8}.Debug|x86.Build.0 = Debug|Win32 + {054C606B-17BF-4540-AC4E-A9A7243628B8}.Release|ARM64.ActiveCfg = Release|ARM64 + {054C606B-17BF-4540-AC4E-A9A7243628B8}.Release|ARM64.Build.0 = Release|ARM64 + {054C606B-17BF-4540-AC4E-A9A7243628B8}.Release|ARM64EC.ActiveCfg = Release|ARM64EC + {054C606B-17BF-4540-AC4E-A9A7243628B8}.Release|ARM64EC.Build.0 = Release|ARM64EC + {054C606B-17BF-4540-AC4E-A9A7243628B8}.Release|x64.ActiveCfg = Release|x64 + {054C606B-17BF-4540-AC4E-A9A7243628B8}.Release|x64.Build.0 = Release|x64 + {054C606B-17BF-4540-AC4E-A9A7243628B8}.Release|x86.ActiveCfg = Release|Win32 + {054C606B-17BF-4540-AC4E-A9A7243628B8}.Release|x86.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -153,6 +271,7 @@ Global {3181FC06-B4ED-4609-8B4F-7220571C6992} = {672374B4-6DE8-4A88-8A6A-30BCC1D9C9F9} {7172CDEB-2391-41C4-883D-BD2C7B60C715} = {672374B4-6DE8-4A88-8A6A-30BCC1D9C9F9} {EF666738-04E0-4AAB-A269-058CDA62EDD0} = {0F97C53B-0767-4B5E-B082-1C1E6A735895} + {054C606B-17BF-4540-AC4E-A9A7243628B8} = {672374B4-6DE8-4A88-8A6A-30BCC1D9C9F9} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {22D08569-C9E4-4F2E-BE8F-FE796300FAEB} diff --git a/build/test_foo_openlyrics.vcxproj b/build/test_foo_openlyrics.vcxproj index d5175992..9bfb6b16 100644 --- a/build/test_foo_openlyrics.vcxproj +++ b/build/test_foo_openlyrics.vcxproj @@ -23,7 +23,7 @@ Win32Proj {1a6e6173-af42-4a1a-b62c-2393476b5b4f} testfooopenlyrics - 10.0 + 10.0.19041.0 diff --git a/foo_pluginstall/foo_pluginstall.vcxproj b/foo_pluginstall/foo_pluginstall.vcxproj index 11684f68..2d9d7c16 100644 --- a/foo_pluginstall/foo_pluginstall.vcxproj +++ b/foo_pluginstall/foo_pluginstall.vcxproj @@ -23,7 +23,7 @@ Win32Proj {9dbc980d-d0fb-4812-958d-8a077ef62450} foopluginstall - 10.0 + 10.0.19041.0 diff --git a/src/main.cpp b/src/main.cpp index 378c8be8..6548b5f0 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,7 +1,7 @@ #include "stdafx.h" -// #define OPENLYRICS_VERSION "1.9-dev" -#define OPENLYRICS_VERSION "1.9" +#define OPENLYRICS_VERSION "1.10-dev" +// #define OPENLYRICS_VERSION "1.10" // Declaration of your component's version information // Since foobar2000 v1.0 having at least one of these in your DLL is mandatory to let the troubleshooter tell different versions of your component apart. @@ -28,7 +28,9 @@ void OpenLyricsVersion::get_about_message(pfc::string_base & out) out += "Source available at https://github.com/jacquesh/foo_openlyrics\n"; out += "You can support development at https://www.buymeacoffee.com/jacquesheunis\n"; out += "\nChangelog:\n"; - // out += "Version " OPENLYRICS_VERSION " (" __DATE__ "):\n" + out += "Version " OPENLYRICS_VERSION " (" __DATE__ "):\n" + "- Update the foobar2000 SDK to version 20230913\n" + "\n"; out += "Version 1.9 (2024-06-12):\n" "- Fix a crash when attempting to load lyrics for non-existent media files\n" "- Fix lyrics sometimes not updating when not all lyric panels are visible\n"