Mercurial > foo_out_sdl
diff foosdk/sdk/foobar2000/SDK/utility.cpp @ 1:20d02a178406 default tip
*: check in everything else
yay
| author | Paper <paper@tflc.us> |
|---|---|
| date | Mon, 05 Jan 2026 02:15:46 -0500 |
| parents | |
| children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/foosdk/sdk/foobar2000/SDK/utility.cpp Mon Jan 05 02:15:46 2026 -0500 @@ -0,0 +1,405 @@ +#include "foobar2000-sdk-pch.h" +#include "foosort.h" +#include <functional> + +namespace pfc { + /* + Redirect PFC methods to shared.dll + If you're getting linker multiple-definition errors on these, change build configuration of PFC from "Debug" / "Release" to "Debug FB2K" / "Release FB2K" + */ +#ifdef _WIN32 + BOOL winFormatSystemErrorMessageHook(pfc::string_base & p_out, DWORD p_code) { + return uFormatSystemErrorMessage(p_out, p_code); + } +#endif + void crashHook() { + uBugCheck(); + } +} + + +// file_lock_manager.h functionality +#include "file_lock_manager.h" +namespace { + class file_lock_interrupt_impl : public file_lock_interrupt { + public: + void interrupt( abort_callback & a ) { f(a); } + std::function<void (abort_callback&)> f; + }; +} + +file_lock_interrupt::ptr file_lock_interrupt::create( std::function< void (abort_callback&)> f ) { + service_ptr_t<file_lock_interrupt_impl> i = new service_impl_t<file_lock_interrupt_impl>(); + i->f = f; + return i; +} + +// file_info_filter.h functionality +#include "file_info_filter.h" +namespace { + class file_info_filter_lambda : public file_info_filter { + public: + bool apply_filter(trackRef p_track,t_filestats p_stats,file_info & p_info) override { + return f(p_track, p_stats, p_info); + } + func_t f; + }; +} + +file_info_filter::ptr file_info_filter::create(func_t f) { + auto o = fb2k::service_new<file_info_filter_lambda>(); + o->f = f; + return o; +} + +// threadPool.h functionality +#include "threadPool.h" +namespace fb2k { + void inWorkerThread(std::function<void()> f) { + fb2k::splitTask(f); + } + void inCpuWorkerThread(std::function<void()> f) { + cpuThreadPool::get()->runSingle(threadEntry::make(f)); + } +} +namespace { + class threadEntryImpl : public fb2k::threadEntry { + public: + void run() override { f(); } + std::function<void()> f; + }; +} +namespace fb2k { + threadEntry::ptr threadEntry::make(std::function<void()> f) { + auto ret = fb2k::service_new<threadEntryImpl>(); + ret->f = f; + return ret; + } + + void cpuThreadPool::runMulti_(std::function<void()> f, size_t numRuns) { + this->runMulti(threadEntry::make(f), numRuns, true); + } + + void cpuThreadPool::runMultiHelper(std::function<void()> f, size_t numRuns) { + if (numRuns == 0) return; +#if FOOBAR2000_TARGET_VERSION >= 81 + get()->runMulti_(f, numRuns); +#else + if (numRuns == 1) { + f(); + return; + } + + size_t numThreads = numRuns - 1; + struct rec_t { + pfc::thread2 trd; + std::exception_ptr ex; + }; + pfc::array_staticsize_t<rec_t> threads; + threads.set_size_discard(numThreads); + for (size_t walk = 0; walk < numThreads; ++walk) { + threads[walk].trd.startHere([f, &threads, walk] { + try { + f(); + } catch (...) { + threads[walk].ex = std::current_exception(); + } + }); + } + std::exception_ptr exMain; + try { + f(); + } catch (...) { + exMain = std::current_exception(); + } + + for (size_t walk = 0; walk < numThreads; ++walk) { + threads[walk].trd.waitTillDone(); + } + if (exMain) std::rethrow_exception(exMain); + for (size_t walk = 0; walk < numThreads; ++walk) { + auto & ex = threads[walk].ex; + if (ex) std::rethrow_exception(ex); + } +#endif + } +} + + +#if FOOBAR2020 +// timer.h functionality +#include "timer.h" +#include <memory> + +namespace fb2k { + void callLater(double timeAfter, std::function< void() > func) { + PFC_ASSERT( core_api::is_main_thread() ); + auto releaseMe = std::make_shared<objRef>(); + *releaseMe = registerTimer(timeAfter, [=] { + if (releaseMe->is_valid()) { // ensure we get here once + func(); + releaseMe->release(); // warning: this should destroy objects that called us, hence func() call must go first + } + }); + } + objRef registerTimer(double interval, std::function<void()> func) { + PFC_ASSERT( core_api::is_main_thread() ); + return static_api_ptr_t<timerManager>()->addTimer(interval, makeCompletionNotify([func](unsigned) { func(); })); + } +} +#endif // FOOBAR2020 + +// autoplaylist.h functionality +#include "autoplaylist.h" + +bool autoplaylist_client::supports_async_() { + autoplaylist_client_v3::ptr v3; + bool rv = false; + if (v3 &= this) { + rv = v3->supports_async(); + } + return rv; +} + +bool autoplaylist_client::supports_get_contents_() { + autoplaylist_client_v3::ptr v3; + bool rv = false; + if (v3 &= this) { + rv = v3->supports_get_contents(); + } + return rv; +} + +void autoplaylist_client_v3::filter(metadb_handle_list_cref data, bool * out) { + filter_v2(data, nullptr, out, fb2k::noAbort); +} +bool autoplaylist_client_v3::sort(metadb_handle_list_cref p_items,t_size * p_orderbuffer) { + return sort_v2(p_items, p_orderbuffer, fb2k::noAbort); +} + + +#include "noInfo.h" +namespace fb2k { + noInfo_t noInfo; +} + + +// library_callbacks.h functionality +#include "library_callbacks.h" + +bool library_callback::is_modified_from_hook() { + auto api = library_manager_v5::tryGet(); + if (api.is_valid()) return api->library_status(library_manager_v5::status_current_callback_from_hook, 0, nullptr, 0) != 0; + else return false; +} + +void library_callback_dynamic::register_callback() { + library_manager_v3::get()->register_callback(this); +} +void library_callback_dynamic::unregister_callback() { + library_manager_v3::get()->unregister_callback(this); +} + +void library_callback_v2_dynamic::register_callback() { + library_manager_v4::get()->register_callback_v2(this); +} + +void library_callback_v2_dynamic::unregister_callback() { + library_manager_v4::get()->unregister_callback_v2(this); +} + + + +// configCache.h functionality +#include "configCache.h" +#include "configStore.h" + +bool fb2k::configBoolCache::get() { + std::call_once(m_init, [this] { + auto api = fb2k::configStore::get(); + auto refresh = [this, api] { m_value = api->getConfigBool(m_var, m_def); }; + api->addPermanentNotify(m_var, refresh); + refresh(); + }); + return m_value; +} + +int64_t fb2k::configIntCache::get() { + std::call_once(m_init, [this] { + auto api = fb2k::configStore::get(); + auto refresh = [this, api] { m_value = api->getConfigInt(m_var, m_def); }; + api->addPermanentNotify(m_var, refresh); + refresh(); + }); + return m_value; +} + +void fb2k::configBoolCache::set(bool v) { + m_value = v; + fb2k::configStore::get()->setConfigBool(m_var, v); +} + +void fb2k::configIntCache::set(int64_t v) { + m_value = v; + fb2k::configStore::get()->setConfigBool(m_var, v); +} + + +// keyValueIO.h functionality +#include "keyValueIO.h" + +int fb2k::keyValueIO::getInt( const char * name ) { + auto str = get(name); + if ( str.is_empty() ) return 0; + return (int) pfc::atoi64_ex( str->c_str(), str->length() ); +} + +void fb2k::keyValueIO::putInt( const char * name, int val ) { + put( name, pfc::format_int(val) ); +} + + +// fileDialog.h functionality +#include "fileDialog.h" +#include "fsitem.h" + +namespace { + using namespace fb2k; + class fileDialogNotifyImpl : public fileDialogNotify { + public: + void dialogCancelled() {} + void dialogOK2(arrayRef fsItems) { + recv(fsItems); + } + + std::function< void (arrayRef) > recv; + }; +} + +fb2k::fileDialogNotify::ptr fb2k::fileDialogNotify::create( std::function<void (arrayRef) > recv ) { + service_ptr_t<fileDialogNotifyImpl> obj = new service_impl_t< fileDialogNotifyImpl >(); + obj->recv = recv; + return obj; +} + +void fb2k::fileDialogSetup::run(fileDialogReply_t reply) { + this->run(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() { + pfc::string8 temp; + input_file_type::build_openfile_mask(temp); + this->setFileTypes( temp ); +} + + +#include "search_tools.h" + +void search_filter_v2::test_multi_here(metadb_handle_list& ref, abort_callback& abort) { + pfc::array_t<bool> mask; mask.resize(ref.get_size()); + 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
