├── .appveyor.yml ├── .bandit ├── .codacy.yml ├── .gitattributes ├── .gitignore ├── .gitmodules ├── .license_index.txt ├── CHANGELOG.md ├── LICENSE ├── PropertyList └── include │ └── property_list │ ├── PropertyItem.h │ ├── PropertyItemEditors.h │ ├── PropertyItemImpl.h │ └── PropertyList.h ├── README.md ├── THIRD_PARTY_NOTICES.md ├── VERSION ├── component ├── docs │ ├── Callbacks.js │ ├── Codepages.js │ ├── Flags.js │ ├── Helpers.js │ ├── Notes & Hints.txt │ └── js │ │ ├── foo_spider_monkey_panel.js │ │ └── foo_ui_hacks.js ├── editor colour schemes │ ├── Bright.cfg │ ├── Dark.cfg │ ├── Ruby Blue.cfg │ └── readme.txt └── samples │ ├── basic │ ├── ApplyMask.js │ ├── ColourPicker.js │ ├── Custom Context Menu.js │ ├── DragnDrop.js │ ├── GetAlbumArtAsync.js │ ├── GetAlbumArtAsyncV2.js │ ├── GetAlbumArtV2.js │ ├── HtmlDialogWithCheckBox.js │ ├── LoadImageAsync.js │ ├── LoadImageAsyncV2.js │ ├── MainMenuManager All-In-One.js │ ├── SimpleThemedButton.js │ ├── StackBlur (image).js │ ├── StackBlur (text).js │ ├── Timer.js │ ├── Tooltip.js │ ├── TrackInfo Follows Cursor.js │ ├── Volbar with GdiDrawText.js │ ├── Watch Metadb Change.js │ ├── html │ │ ├── PopupWithCheckBox.html │ │ ├── styles10.css │ │ └── styles7.css │ └── images │ │ ├── Default.png │ │ ├── Random.png │ │ ├── Repeat (Playlist).png │ │ ├── Repeat (Track).png │ │ ├── Shuffle (albums).png │ │ ├── Shuffle (folders).png │ │ ├── Shuffle (tracks).png │ │ ├── cog.png │ │ ├── image.jpg │ │ ├── mask.png │ │ └── post.jpg │ ├── js-smooth │ ├── JS Smooth Browser.js │ ├── JS Smooth Playlist Manager.js │ ├── JS Smooth Playlist.js │ ├── images │ │ ├── default.png │ │ ├── genres │ │ │ ├── 60's.jpg │ │ │ ├── 70's.jpg │ │ │ ├── 80's.jpg │ │ │ └── 90's.jpg │ │ └── load.png │ └── js │ │ ├── JScommon.js │ │ ├── JSinputbox.js │ │ ├── jssb.js │ │ ├── jssp.js │ │ └── jsspm.js │ ├── jsplaylist-mod │ ├── images │ │ ├── default.jpg │ │ ├── load.png │ │ ├── logo.png │ │ ├── noartist.png │ │ ├── nocover.png │ │ └── stream.png │ ├── js │ │ ├── WSHcommon.js │ │ ├── WSHheaderbar.js │ │ ├── WSHinputbox.js │ │ ├── WSHplaylist.js │ │ ├── WSHplaylistmanager.js │ │ ├── WSHscrollbar.js │ │ ├── WSHsettings.js │ │ ├── WSHtopbar.js │ │ └── main.js │ └── jsplaylist main script.js │ ├── packages │ └── {A584FDEF-C88A-4849-94D5-F33C71649927} │ │ ├── assets │ │ └── text.txt │ │ ├── main.js │ │ ├── package.json │ │ └── scripts │ │ └── utils.js │ └── readme.md ├── foo_spider_monkey_panel ├── .clang-format ├── .clang-tidy ├── com_objects │ ├── com_interface.h │ ├── com_interface.idl │ ├── com_tools.cpp │ ├── com_tools.h │ ├── dispatch_ptr.h │ ├── drop_source_impl.cpp │ ├── drop_source_impl.h │ ├── drop_target_impl.cpp │ ├── drop_target_impl.h │ ├── file_drop_target.cpp │ ├── file_drop_target.h │ ├── host_external.cpp │ ├── host_external.h │ ├── internal │ │ ├── drag_image.cpp │ │ ├── drag_image.h │ │ ├── drag_utils.cpp │ │ ├── drag_utils.h │ │ └── handle.h │ ├── track_drop_target.cpp │ └── track_drop_target.h ├── com_utils │ ├── com_destruction_handler.cpp │ ├── com_destruction_handler.h │ ├── com_error_helpers.cpp │ └── com_error_helpers.h ├── component_defines.h ├── component_guids.h ├── component_paths.cpp ├── component_paths.h ├── config │ ├── basic_script_sources.h │ ├── default_script.cpp │ ├── default_script.h │ ├── module_package │ │ ├── module_specifier.cpp │ │ ├── module_specifier.h │ │ ├── package.cpp │ │ ├── package.h │ │ ├── package_manager.cpp │ │ └── package_manager.h │ ├── panel_config.cpp │ ├── panel_config.h │ ├── panel_config_formats.h │ ├── panel_properties.cpp │ ├── panel_properties.h │ ├── panel_settings.h │ ├── raw_panel_script_source.cpp │ ├── raw_panel_script_source.h │ ├── resolved_panel_script_settings.cpp │ ├── resolved_panel_script_settings.h │ ├── script_source_types.h │ ├── serializers │ │ ├── binary.cpp │ │ ├── binary.h │ │ ├── com.cpp │ │ ├── com.h │ │ ├── json.cpp │ │ └── json.h │ └── smp_package │ │ ├── delayed_package_actions.cpp │ │ ├── delayed_package_actions.h │ │ ├── package.cpp │ │ ├── package.h │ │ ├── package_manager.cpp │ │ └── package_manager.h ├── convert │ ├── com.cpp │ ├── com.h │ ├── js_to_native.cpp │ ├── js_to_native.h │ ├── native_to_js.cpp │ └── native_to_js.h ├── dllmain.cpp ├── events │ ├── event.cpp │ ├── event.h │ ├── event_basic.cpp │ ├── event_basic.h │ ├── event_dispatcher.cpp │ ├── event_dispatcher.h │ ├── event_drag.cpp │ ├── event_drag.h │ ├── event_js_callback.h │ ├── event_js_executor.cpp │ ├── event_js_executor.h │ ├── event_js_task.cpp │ ├── event_js_task.h │ ├── event_mouse.cpp │ ├── event_mouse.h │ ├── event_notify_others.cpp │ ├── event_notify_others.h │ ├── event_timer.cpp │ ├── event_timer.h │ ├── task_controller.cpp │ └── task_controller.h ├── fb2k │ ├── acfu_integration.cpp │ ├── advanced_config.cpp │ ├── advanced_config.h │ ├── config.cpp │ ├── config.h │ ├── fb2k_callbacks.cpp │ ├── mainmenu.cpp │ ├── mainmenu_dynamic.cpp │ ├── mainmenu_dynamic.h │ ├── playlist_lock.cpp │ ├── playlist_lock.h │ ├── selection_holder_helper.cpp │ ├── selection_holder_helper.h │ ├── stats.cpp │ └── stats.h ├── foo_spider_monkey_panel.vcxproj ├── foo_spider_monkey_panel.vcxproj.filters ├── js_backend │ ├── engine │ │ ├── heartbeat_window.cpp │ │ ├── heartbeat_window.h │ │ ├── js_container.cpp │ │ ├── js_container.h │ │ ├── js_engine.cpp │ │ ├── js_engine.h │ │ ├── js_gc.cpp │ │ ├── js_gc.h │ │ ├── js_monitor.cpp │ │ ├── js_monitor.h │ │ ├── js_realm_inner.cpp │ │ ├── js_realm_inner.h │ │ ├── js_script_cache.cpp │ │ ├── js_script_cache.h │ │ ├── js_to_native_invoker.h │ │ ├── native_to_js_invoker.cpp │ │ └── native_to_js_invoker.h │ ├── objects │ │ ├── core │ │ │ ├── global_heap_manager.cpp │ │ │ ├── global_heap_manager.h │ │ │ ├── global_object.cpp │ │ │ ├── global_object.h │ │ │ ├── object_base.h │ │ │ ├── object_traits.h │ │ │ ├── prototype_ids.h │ │ │ ├── script_loader.cpp │ │ │ └── script_loader.h │ │ ├── dom │ │ │ ├── active_x_object.cpp │ │ │ ├── active_x_object.h │ │ │ ├── active_x_object_iterator.cpp │ │ │ ├── active_x_object_iterator.h │ │ │ ├── console.cpp │ │ │ ├── console.h │ │ │ ├── context_menu_manager.cpp │ │ │ ├── context_menu_manager.h │ │ │ ├── drop_source_action.cpp │ │ │ ├── drop_source_action.h │ │ │ ├── enumerator.cpp │ │ │ ├── enumerator.h │ │ │ ├── event.cpp │ │ │ ├── event.h │ │ │ ├── event_target.cpp │ │ │ ├── event_target.h │ │ │ ├── main_menu_manager.cpp │ │ │ ├── main_menu_manager.h │ │ │ ├── menu_object.cpp │ │ │ └── menu_object.h │ │ ├── fb2k │ │ │ ├── fb_file_info.cpp │ │ │ ├── fb_file_info.h │ │ │ ├── fb_metadb_handle.cpp │ │ │ ├── fb_metadb_handle.h │ │ │ ├── fb_metadb_handle_list.cpp │ │ │ ├── fb_metadb_handle_list.h │ │ │ ├── fb_metadb_handle_list_iterator.cpp │ │ │ ├── fb_metadb_handle_list_iterator.h │ │ │ ├── fb_playback_queue_item.cpp │ │ │ ├── fb_playback_queue_item.h │ │ │ ├── fb_playing_item_location.cpp │ │ │ ├── fb_playing_item_location.h │ │ │ ├── fb_playlist_manager.cpp │ │ │ ├── fb_playlist_manager.h │ │ │ ├── fb_playlist_recycler.cpp │ │ │ ├── fb_playlist_recycler.h │ │ │ ├── fb_profiler.cpp │ │ │ ├── fb_profiler.h │ │ │ ├── fb_properties.cpp │ │ │ ├── fb_properties.h │ │ │ ├── fb_title_format.cpp │ │ │ ├── fb_title_format.h │ │ │ ├── fb_tooltip.cpp │ │ │ ├── fb_tooltip.h │ │ │ ├── fb_ui_selection_holder.cpp │ │ │ ├── fb_ui_selection_holder.h │ │ │ ├── fb_utils.cpp │ │ │ ├── fb_utils.h │ │ │ ├── fb_window.cpp │ │ │ └── fb_window.h │ │ ├── gdi │ │ │ ├── gdi_bitmap.cpp │ │ │ ├── gdi_bitmap.h │ │ │ ├── gdi_font.cpp │ │ │ ├── gdi_font.h │ │ │ ├── gdi_graphics.cpp │ │ │ ├── gdi_graphics.h │ │ │ ├── gdi_raw_bitmap.cpp │ │ │ ├── gdi_raw_bitmap.h │ │ │ ├── gdi_utils.cpp │ │ │ ├── gdi_utils.h │ │ │ ├── measure_string_info.cpp │ │ │ ├── measure_string_info.h │ │ │ ├── theme_manager.cpp │ │ │ └── theme_manager.h │ │ ├── utils.cpp │ │ ├── utils.h │ │ ├── window.cpp │ │ └── window.h │ └── utils │ │ ├── cached_utf8_paths_hack.cpp │ │ ├── cached_utf8_paths_hack.h │ │ ├── js_art_helpers.cpp │ │ ├── js_art_helpers.h │ │ ├── js_async_task.h │ │ ├── js_error_helper.cpp │ │ ├── js_error_helper.h │ │ ├── js_heap_helper.h │ │ ├── js_hwnd_helpers.cpp │ │ ├── js_hwnd_helpers.h │ │ ├── js_image_helpers.cpp │ │ ├── js_image_helpers.h │ │ ├── js_object_helper.cpp │ │ ├── js_object_helper.h │ │ ├── js_property_helper.h │ │ ├── js_prototype_helpers.cpp │ │ ├── js_prototype_helpers.h │ │ ├── scope_helper.h │ │ ├── serialized_value.cpp │ │ └── serialized_value.h ├── packages.config ├── panel │ ├── drag_action_params.h │ ├── edit_script.cpp │ ├── edit_script.h │ ├── modal_blocking_scope.cpp │ ├── modal_blocking_scope.h │ ├── panel_adaptor_cui.cpp │ ├── panel_adaptor_cui.h │ ├── panel_adaptor_dui.cpp │ ├── panel_adaptor_dui.h │ ├── panel_adaptor_iface.h │ ├── panel_window.cpp │ ├── panel_window.h │ └── user_message.h ├── resources │ ├── default_script.js │ ├── foo_spider_monkey_panel.rc │ ├── foo_spider_monkey_panel.rc2 │ ├── recovery_package_json.json │ ├── recovery_package_script.js │ ├── resource.h │ ├── scintilla_interface.api │ ├── scintilla_jscript.api │ └── version.rc ├── stdafx.cpp ├── stdafx.h ├── timeout │ ├── time_types.h │ ├── timeout.cpp │ ├── timeout.h │ ├── timeout_executor.cpp │ ├── timeout_executor.h │ ├── timeout_manager.cpp │ ├── timeout_manager.h │ ├── timer_custom.cpp │ ├── timer_custom.h │ ├── timer_interface.h │ ├── timer_interface_fwd.h │ ├── timer_manager_custom.cpp │ ├── timer_manager_custom.h │ ├── timer_manager_native.cpp │ ├── timer_manager_native.h │ ├── timer_native.cpp │ └── timer_native.h ├── ui │ ├── impl │ │ ├── ui_conf_tab_appearance.cpp │ │ ├── ui_conf_tab_appearance.h │ │ ├── ui_conf_tab_package.cpp │ │ ├── ui_conf_tab_package.h │ │ ├── ui_conf_tab_properties.cpp │ │ ├── ui_conf_tab_properties.h │ │ ├── ui_conf_tab_script_source.cpp │ │ ├── ui_conf_tab_script_source.h │ │ ├── ui_itab.h │ │ ├── ui_menu_edit_with.cpp │ │ └── ui_menu_edit_with.h │ ├── scintilla │ │ ├── sci_config.cpp │ │ ├── sci_config.h │ │ ├── sci_prop_sets.cpp │ │ ├── sci_prop_sets.h │ │ ├── ui_sci_editor.cpp │ │ ├── ui_sci_editor.h │ │ ├── ui_sci_find_replace.cpp │ │ ├── ui_sci_find_replace.h │ │ ├── ui_sci_goto.cpp │ │ ├── ui_sci_goto.h │ │ └── wtlscintilla.h │ ├── ui_conf.cpp │ ├── ui_conf.h │ ├── ui_edit_in_progress.cpp │ ├── ui_edit_in_progress.h │ ├── ui_editor.cpp │ ├── ui_editor.h │ ├── ui_editor_config.cpp │ ├── ui_editor_config.h │ ├── ui_html.cpp │ ├── ui_html.h │ ├── ui_input_box.cpp │ ├── ui_input_box.h │ ├── ui_name_value_edit.cpp │ ├── ui_name_value_edit.h │ ├── ui_package_manager.cpp │ ├── ui_package_manager.h │ ├── ui_slow_script.cpp │ └── ui_slow_script.h └── utils │ ├── app_info.cpp │ ├── app_info.h │ ├── art_helpers.cpp │ ├── art_helpers.h │ ├── art_loading_options.cpp │ ├── art_loading_options.h │ ├── colour_helpers.h │ ├── edit_text.cpp │ ├── edit_text.h │ ├── fmt_pfc_adaptor.h │ ├── gdi_error_helpers.cpp │ ├── gdi_error_helpers.h │ ├── gdi_helpers.cpp │ ├── gdi_helpers.h │ ├── guid_helpers.cpp │ ├── guid_helpers.h │ ├── image_helpers.cpp │ ├── image_helpers.h │ ├── js_exception.cpp │ ├── js_exception.h │ ├── json_std_extenders.h │ ├── kmeans.cpp │ ├── kmeans.h │ ├── location_processor.cpp │ ├── location_processor.h │ ├── logging.cpp │ ├── logging.h │ ├── make_unique_ptr.h │ ├── md5.cpp │ ├── md5.h │ ├── menu_helpers.cpp │ ├── menu_helpers.h │ ├── path_helpers.cpp │ ├── path_helpers.h │ ├── relative_filepath_trie.h │ ├── resource_helpers.cpp │ ├── resource_helpers.h │ ├── semantic_version.cpp │ ├── stackblur.cpp │ ├── stackblur.h │ ├── stacktrace.cpp │ ├── stacktrace.h │ ├── text_helpers.cpp │ ├── text_helpers.h │ ├── thread_pool_instance.cpp │ ├── thread_pool_instance.h │ ├── zip_utils.cpp │ └── zip_utils.h ├── licenses ├── AtlScintilla.txt ├── CPropertyList.txt ├── Columns UI SDK.txt ├── DispatchPtr.txt ├── JSON for Modern C++.txt ├── JScript Panel.txt ├── KMeans.txt ├── PFC.txt ├── Scintilla.txt ├── SpiderMonkey.txt ├── StackBlur.txt ├── UI Helpers.txt ├── WTL.txt ├── fmt.txt ├── foobar2000 SDK.txt ├── miniz.txt ├── range-v3.txt └── timsort-cpp.txt ├── miniz ├── LICENSE ├── miniz.c ├── miniz.vcxproj └── miniz │ └── miniz.h ├── package.json ├── props ├── local_dependencies │ ├── miniz.props │ ├── mozjs.props │ └── property_list.props └── submodules │ ├── fb2k_utils.props │ └── submodules.props ├── scripts ├── README.md ├── additional_files │ ├── lexilla.vcxproj │ ├── mozjs_debug.vcxitems │ ├── mozjs_release.vcxitems │ ├── scintilla.vcxproj │ └── wtl.vcxitems ├── call_wrapper.py ├── configure_scintilla.py ├── doc │ ├── README.md │ └── conf.json ├── download_submodules.py ├── generate_docs.py ├── generate_package_info.py ├── generate_project_filters.py ├── node_patches │ └── tui-jsdoc-template+1.2.2.patch ├── pack_component.py ├── patch_submodules.py ├── patches │ ├── cui.patch │ ├── mozjs-bug_1243367-wrong_free_call.patch │ ├── mozjs-pretty_function.patch │ ├── mozjs-result_of.patch │ ├── scintilla.patch │ └── smp_2003.patch ├── prepare_submodule_projects.py ├── setup.py ├── unpack_mozjs.py └── update_gh_pages.py └── workspaces └── foo_spider_monkey_panel.sln /.bandit: -------------------------------------------------------------------------------- 1 | skips: ['B101','B404','B602','B607'] 2 | -------------------------------------------------------------------------------- /.codacy.yml: -------------------------------------------------------------------------------- 1 | engines: 2 | prospector: 3 | enabled: true 4 | python_version: 3 5 | pylint: 6 | enabled: true 7 | python_version: 3 8 | exclude_paths: 9 | - "component/**" 10 | - "**.js" 11 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | # Custom for Visual Studio 4 | *.cs diff=csharp 5 | # Standard to msysgit 6 | *.doc diff=astextplain 7 | *.DOC diff=astextplain 8 | *.docx diff=astextplain 9 | *.DOCX diff=astextplain 10 | *.dot diff=astextplain 11 | *.DOT diff=astextplain 12 | *.pdf diff=astextplain 13 | *.PDF diff=astextplain 14 | *.rtf diff=astextplain 15 | *.RTF diff=astextplain 16 | *.zip filter=lfs diff=lfs merge=lfs -text 17 | 18 | component/** linguist-detectable=false 19 | miniz/** linguist-detectable=false 20 | scripts/** linguist-detectable=false 21 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "submodules/wtl"] 2 | path = submodules/wtl 3 | url = https://git.code.sf.net/p/wtl/git 4 | [submodule "submodules/columns_ui-sdk"] 5 | path = submodules/columns_ui-sdk 6 | url = https://github.com/reupen/columns_ui-sdk.git 7 | [submodule "submodules/foobar2000"] 8 | path = submodules/foobar2000 9 | url = https://github.com/TheQwertiest/foobar2000-sdk.git 10 | [submodule "submodules/smp_2003"] 11 | path = submodules/smp_2003 12 | url = https://github.com/TheQwertiest/smp_2003.git 13 | [submodule "submodules/scintilla"] 14 | path = submodules/scintilla 15 | url = https://github.com/theqwertiest/scintilla.git 16 | [submodule "submodules/pfc"] 17 | path = submodules/pfc 18 | url = https://github.com/TheQwertiest/pfc.git 19 | [submodule "submodules/mozjs"] 20 | path = submodules/mozjs 21 | url = https://bitbucket.org/TheQwertiest/mozjs.git 22 | [submodule "submodules/acfu-sdk"] 23 | path = submodules/acfu-sdk 24 | url = https://github.com/3dyd/acfu-sdk.git 25 | [submodule "submodules/json"] 26 | path = submodules/json 27 | url = https://github.com/nlohmann/json.git 28 | branch = master 29 | [submodule "submodules/timsort"] 30 | path = submodules/timsort 31 | url = https://github.com/tvanslyke/timsort-cpp.git 32 | [submodule "submodules/range"] 33 | path = submodules/range 34 | url = https://github.com/ericniebler/range-v3.git 35 | fetchRecurseSubmodules = false 36 | [submodule "submodules/fmt"] 37 | path = submodules/fmt 38 | url = https://github.com/fmtlib/fmt.git 39 | [submodule "submodules/fb2k_utils"] 40 | path = submodules/fb2k_utils 41 | url = https://github.com/TheQwertiest/fb2k_utils.git 42 | -------------------------------------------------------------------------------- /.license_index.txt: -------------------------------------------------------------------------------- 1 | AtlScintilla: zlib 2 | Columns UI SDK: other 3 | CPropertyList: other 4 | DispatchPtr: BSD 5 | foobar2000 SDK: other 6 | fmt: other 7 | JScript Panel: Unlicense 8 | JSON for Modern C++: MIT 9 | KMeans: MIT 10 | miniz: MIT 11 | range-v3: BSL-1.0 12 | PFC: zlib 13 | Scintilla: HPND 14 | SpiderMonkey: MPL 15 | StackBlur: MIT 16 | timsort-cpp: MIT 17 | UI Helpers: BSD 18 | WTL: MS-PL 19 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018-2021 Yuri Shutenko 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Spider Monkey Panel 2 | [![version][version_badge]][changelog] [![Build status][appveyor_badge]](https://ci.appveyor.com/project/TheQwertiest/foo-spider-monkey-panel/branch/master) [![CodeFactor][codefactor_badge]](https://www.codefactor.io/repository/github/theqwertiest/foo_spider_monkey_panel/overview/master) [![Codacy Badge][codacy_badge]](https://app.codacy.com/app/qwertiest/foo_spider_monkey_panel?utm_source=github.com&utm_medium=referral&utm_content=TheQwertiest/foo_spider_monkey_panel&utm_campaign=Badge_Grade_Dashboard) 3 | 4 | This is a component for the [foobar2000](https://www.foobar2000.org) audio player that allows to use JavaScript to create full-fledged CUI/DUI panels! 5 | 6 | Visit [component homepage](https://theqwertiest.github.io/foo_spider_monkey_panel/) for more info. 7 | 8 | [changelog]: CHANGELOG.md 9 | [version_badge]: https://img.shields.io/github/release/theqwertiest/foo_spider_monkey_panel.svg 10 | [appveyor_badge]: https://ci.appveyor.com/api/projects/status/4fg787ijr73u7mxc/branch/master?svg=true 11 | [codacy_badge]: https://api.codacy.com/project/badge/Grade/19c686bcf26d46e6a639bdece347ae3d 12 | [codefactor_badge]: https://www.codefactor.io/repository/github/theqwertiest/foo_spider_monkey_panel/badge/master 13 | -------------------------------------------------------------------------------- /THIRD_PARTY_NOTICES.md: -------------------------------------------------------------------------------- 1 | Spider Monkey Panel uses third-party libraries or other resources that may 2 | be distributed under licenses different than the Spider Monkey Panel software. 3 | The linked notices are provided for information only. 4 | 5 | - [AtlScintilla - zlib](licenses/AtlScintilla.txt) 6 | - [Columns UI SDK - other](licenses/Columns%20UI%20SDK.txt) 7 | - [CPropertyList - other](licenses/CPropertyList.txt) 8 | - [DispatchPtr - BSD](licenses/DispatchPtr.txt) 9 | - [foobar2000 SDK - other](licenses/foobar2000%20SDK.txt) 10 | - [fmt - other](licenses/fmt.txt) 11 | - [JScript Panel - Unlicense](licenses/JScript%20Panel.txt) 12 | - [JSON for Modern C++ - MIT](licenses/JSON%20for%20Modern%20C%2B%2B.txt) 13 | - [KMeans - MIT](licenses/KMeans.txt) 14 | - [miniz - MIT](licenses/miniz.txt) 15 | - [range-v3 - BSL-1.0](licenses/range-v3.txt) 16 | - [PFC - zlib](licenses/PFC.txt) 17 | - [Scintilla - HPND](licenses/Scintilla.txt) 18 | - [SpiderMonkey - MPL](licenses/SpiderMonkey.txt) 19 | - [StackBlur - MIT](licenses/StackBlur.txt) 20 | - [timsort-cpp - MIT](licenses/timsort-cpp.txt) 21 | - [UI Helpers - BSD](licenses/UI%20Helpers.txt) 22 | - [WTL - MS-PL](licenses/WTL.txt) 23 | -------------------------------------------------------------------------------- /VERSION: -------------------------------------------------------------------------------- 1 | 1.6.2-dev 2 | -------------------------------------------------------------------------------- /component/docs/Notes & Hints.txt: -------------------------------------------------------------------------------- 1 | 1 If anything goes wrong, check the popup window/console. It should tell you where the code is 2 | that caused the error. 3 | 2 Error handling is useful to create more stable scripts. 4 | 3 Do NOT call repaint functions such as window.Repaint() in callback function on_size() {}. 5 | 4 Do NOT assign parameter "gr" from function on_paint(gr) {} with other value, nor 6 | store "gr" in another variable. 7 | 5 Remember to retrieve window width and height in on_size() callback, because their values 8 | during startup is not reliable. 9 | 6 It's NOT recommended to create objects in callback function on_paint(), since it will be 10 | called frenquently. 11 | -------------------------------------------------------------------------------- /component/editor colour schemes/Bright.cfg: -------------------------------------------------------------------------------- 1 | # Generated by JScript Panel 2 | style.default=font:Courier New,size:10,fore:#000000,back:#ffffff 3 | style.comment=italics,fore:#666666 4 | style.keyword=fore:#000085 5 | style.indentifier=fore:#006600 6 | style.string=fore:#996633 7 | style.number=fore:#8b0000 8 | style.operator=fore:#781f87 9 | style.linenumber=font:Courier New,size:8,fore:#555555 10 | style.bracelight=bold,fore:#ff0000,back:#ffff99 11 | style.bracebad=bold,fore:#ff6666,back:#ffff66 12 | style.selection.fore= 13 | style.selection.back= 14 | style.selection.alpha=256 15 | style.caret.fore= 16 | style.caret.width=1 17 | style.caret.line.back= 18 | style.caret.line.back.alpha=256 19 | -------------------------------------------------------------------------------- /component/editor colour schemes/Dark.cfg: -------------------------------------------------------------------------------- 1 | # Generated by JScript Panel 2 | style.default=font:Courier New,size:10,fore:#ffffff,back:#000000 3 | style.comment=italics,fore:#adadad 4 | style.keyword=fore:#78e087 5 | style.indentifier=$(style.default) 6 | style.string=fore:#dcdc71 7 | style.number=fore:#74ffff 8 | style.operator=fore:#87e078 9 | style.linenumber=font:Courier New,size:8,fore:#777777 10 | style.bracelight=bold,fore:#379b9b 11 | style.bracebad=$(style.bracelight),back:#0000ff 12 | style.selection.fore= 13 | style.selection.back=#660000 14 | style.selection.alpha=256 15 | style.caret.fore=#ffffff 16 | style.caret.width=1 17 | style.caret.line.back=#003300 18 | style.caret.line.back.alpha=256 19 | -------------------------------------------------------------------------------- /component/editor colour schemes/Ruby Blue.cfg: -------------------------------------------------------------------------------- 1 | # Generated by JScript Panel 2 | style.default=font:Courier New,size:10,fore:#ffffff,back:#121e31 3 | style.comment=italics,fore:#428bdd 4 | style.keyword=fore:#f8bb00 5 | style.indentifier=$(style.default) 6 | style.string=fore:#1dc116 7 | style.number=fore:#eddd3d 8 | style.operator=fore:#8aa6c1 9 | style.linenumber=font:Courier New,size:8,fore:#2b91af 10 | style.bracelight=bold,fore:#000000,back:#ffee62 11 | style.bracebad=bold,fore:#ff0000 12 | style.selection.fore= 13 | style.selection.back=#38566f 14 | style.selection.alpha=256 15 | style.caret.fore=#ffffff 16 | style.caret.width=1 17 | style.caret.line.back=#253e5a 18 | style.caret.line.back.alpha=256 19 | -------------------------------------------------------------------------------- /component/editor colour schemes/readme.txt: -------------------------------------------------------------------------------- 1 | Colour schemes for built-in script editor. 2 | 3 | Use `Options > Editor properties` to import these. 4 | -------------------------------------------------------------------------------- /component/samples/basic/ColourPicker.js: -------------------------------------------------------------------------------- 1 | window.DefineScript('ColourPicker', { author: 'marc2003' }); 2 | include('docs/Flags.js'); 3 | include('docs/Helpers.js'); 4 | 5 | const font = gdi.Font('Segoe UI', 16, 1); 6 | 7 | let colour = RGB(255, 0, 0); 8 | 9 | function on_paint(gr) { 10 | gr.FillSolidRect(0, 0, window.Width, window.Height, colour); 11 | gr.FillSolidRect(0, 0, window.Width, 24, RGB(0, 0, 0)); 12 | gr.GdiDrawText('Click to open ColorPicker', font, RGB(255, 255, 255), 0, 0, window.Width, 24, DT_CENTER); 13 | } 14 | 15 | function on_mouse_lbtn_up() { 16 | colour = utils.ColourPicker(0, colour); 17 | window.Repaint(); 18 | } 19 | -------------------------------------------------------------------------------- /component/samples/basic/Custom Context Menu.js: -------------------------------------------------------------------------------- 1 | window.DefineScript('Custom context menu', { author: 'T.P Wang / marc2003' }); 2 | include('docs/Flags.js'); 3 | 4 | function on_mouse_lbtn_down(x, y) { 5 | let _context = fb.CreateContextMenuManager(); 6 | let _basemenu = window.CreatePopupMenu(); 7 | let _child = window.CreatePopupMenu(); 8 | 9 | // start index at 1, NOT 0 10 | _basemenu.AppendMenuItem(MF_STRING, 1, 'item1'); 11 | _basemenu.AppendMenuItem(MF_STRING, 2, 'item2'); 12 | if (fb.GetNowPlaying()) { 13 | _child.AppendTo(_basemenu, MF_STRING, 'Now Playing'); 14 | } 15 | 16 | _context.InitNowPlaying(); 17 | _context.BuildMenu(_child, 3); 18 | 19 | const idx = _basemenu.TrackPopupMenu(x, y); 20 | 21 | switch (idx) { 22 | case 0: //user dismissed menu by clicking elsewhere. that's why you can't use 0 when building menu items 23 | break; 24 | case 1: 25 | fb.ShowPopupMessage('You have chosen item1.'); 26 | break; 27 | case 2: 28 | fb.ShowPopupMessage('OK, item2 is clicked.'); 29 | break; 30 | default: 31 | _context.ExecuteByID(idx - 3); 32 | break; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /component/samples/basic/GetAlbumArtAsync.js: -------------------------------------------------------------------------------- 1 | window.DefineScript('GetAlbumArtAsync', { author: 'T.P Wang' }); 2 | include('docs/Flags.js'); 3 | include('docs/Helpers.js'); 4 | 5 | // Nothing will show until you start playing a new track 6 | 7 | let g_img = null; 8 | let path = ''; 9 | let ww = 0, wh = 0; 10 | 11 | function on_paint(gr) { 12 | gr.FillSolidRect(0, 0, ww, wh, RGB(255, 255, 255)); 13 | if (g_img) { 14 | // Keep aspect ratio 15 | let scale_w = ww / g_img.Width; 16 | let scale_h = wh / g_img.Height; 17 | let scale = Math.min(scale_w, scale_h); 18 | let pos_x = 0, pos_y = 0; 19 | if (scale_w < scale_h) { 20 | pos_y = (wh - g_img.Height * scale) / 2; 21 | } 22 | else if (scale_w > scale_h) { 23 | pos_x = (ww - g_img.Width * scale) / 2; 24 | } 25 | gr.DrawImage(g_img, pos_x, pos_y, g_img.Width * scale, g_img.Height * scale, 0, 0, g_img.Width, g_img.Height); 26 | } 27 | } 28 | 29 | function on_size() { 30 | ww = window.Width; 31 | wh = window.Height; 32 | } 33 | 34 | function on_playback_new_track(metadb) { 35 | if (!metadb) { 36 | return; 37 | } 38 | utils.GetAlbumArtAsync(0, metadb, AlbumArtId.front); 39 | g_img = null; 40 | path = null; 41 | } 42 | 43 | function on_get_album_art_done(metadb, art_id, image, image_path) { 44 | path = image_path; 45 | g_img = image; 46 | window.Repaint(); 47 | } 48 | 49 | function on_mouse_lbtn_dblclk(x, y) { 50 | //double click panel to show path in popup window 51 | if (path) { 52 | fb.ShowPopupMessage(path); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /component/samples/basic/GetAlbumArtV2.js: -------------------------------------------------------------------------------- 1 | window.DefineScript('GetAlbumArtV2', { author: 'T.P Wang' }); 2 | include('docs/Flags.js'); 3 | include('docs/Helpers.js'); 4 | 5 | // Nothing will show until you start playing a new track 6 | 7 | let g_img = null; 8 | let ww = 0, wh = 0; 9 | 10 | function on_paint(gr) { 11 | gr.FillSolidRect(0, 0, ww, wh, RGB(255, 255, 255)); 12 | if (!g_img) { 13 | return; 14 | } 15 | 16 | // Keep aspect ratio 17 | let scale_w = ww / g_img.Width; 18 | let scale_h = wh / g_img.Height; 19 | let scale = Math.min(scale_w, scale_h); 20 | let pos_x = 0, pos_y = 0; 21 | if (scale_w < scale_h) { 22 | pos_y = (wh - g_img.Height * scale) / 2; 23 | } 24 | else if (scale_w > scale_h) { 25 | pos_x = (ww - g_img.Width * scale) / 2; 26 | } 27 | gr.DrawImage(g_img, pos_x, pos_y, g_img.Width * scale, g_img.Height * scale, 0, 0, g_img.Width, g_img.Height); 28 | } 29 | 30 | function on_size() { 31 | ww = window.Width; 32 | wh = window.Height; 33 | } 34 | 35 | function on_playback_new_track(metadb) { 36 | if (!metadb) { 37 | return; 38 | } 39 | g_img = utils.GetAlbumArtV2(metadb, AlbumArtId.front); 40 | window.Repaint(); 41 | } 42 | -------------------------------------------------------------------------------- /component/samples/basic/LoadImageAsyncV2.js: -------------------------------------------------------------------------------- 1 | window.DefineScript('LoadImageAsyncV2', { author: 'TheQwertiest' }); 2 | 3 | // Get a list of jpg files from a folder 4 | const g_image_list = utils.Glob(`${fb.ComponentPath}samples/basic/images/*.jpg`); 5 | let ww = 0, wh = 0; 6 | let g_img = null; 7 | 8 | // Trigger every 5 seconds. 9 | let g_timer = window.SetInterval(function () { 10 | load_random_image_async(); 11 | }, 5000); 12 | 13 | const load_random_image_async = async (metadb, art_id) => 14 | { 15 | // Load a random image from the list 16 | let path = g_image_list[Math.floor(Math.random() * g_image_list.length)]; 17 | g_img = await gdi.LoadImageAsyncV2(0, path); 18 | window.Repaint(); 19 | }; 20 | 21 | load_random_image_async(); 22 | 23 | function on_size() { 24 | ww = window.Width; 25 | wh = window.Height; 26 | } 27 | 28 | function on_paint(gr) { 29 | if (!g_img) { 30 | return; 31 | } 32 | 33 | let scale_w = ww / g_img.Width; 34 | let scale_h = wh / g_img.Height; 35 | let scale = Math.min(scale_w, scale_h); 36 | let pos_x = 0, pos_y = 0; 37 | if (scale_w < scale_h) { 38 | pos_y = (wh - g_img.Height * scale) / 2; 39 | } 40 | else if (scale_w > scale_h) { 41 | pos_x = (ww - g_img.Width * scale) / 2; 42 | } 43 | gr.DrawImage(g_img, pos_x, pos_y, g_img.Width * scale, g_img.Height * scale, 0, 0, g_img.Width, g_img.Height); 44 | } 45 | -------------------------------------------------------------------------------- /component/samples/basic/StackBlur (image).js: -------------------------------------------------------------------------------- 1 | window.DefineScript('StackBlur', {author: 'marc2003'}); 2 | include('docs/Flags.js'); 3 | include('docs/Helpers.js'); 4 | 5 | const img = gdi.Image(`${fb.ComponentPath}samples/basic/images/post.jpg`); 6 | const font = gdi.Font('Segoe UI', 16, 1); 7 | const text_h = 24 8 | let blur_img = null; 9 | let radius = 20; 10 | let ww = 0; 11 | let wh = 0; 12 | 13 | StackBlur(radius); 14 | 15 | function StackBlur(radius) { 16 | blur_img = img.Clone(0, 0, img.Width, img.Height); 17 | blur_img.StackBlur(radius); 18 | } 19 | 20 | function on_paint(gr) { 21 | if (!ww || !wh) { 22 | return; 23 | } 24 | 25 | const min_dim = Math.min(ww,wh - text_h) 26 | gr.DrawImage(blur_img, 0, text_h, min_dim, min_dim, 0, 0, 600, 600); 27 | gr.DrawImage(img, 6, text_h + 5, min_dim/3, min_dim/3, 0, 0, 600, 600); 28 | // RGB function is defined in docs/Helpers.js 29 | gr.FillSolidRect(0, 0, ww, 24, RGB(0, 0, 0)); 30 | // DT_CENTER is defined in docs/Flags.js 31 | gr.GdiDrawText('Scroll mouse to change radius: ' + radius, font, RGB(255, 255, 255), 0, 0, ww, text_h, DT_CENTER); 32 | } 33 | 34 | function on_size(w,h) { 35 | ww = w; 36 | wh = h; 37 | } 38 | 39 | function on_mouse_wheel(step) { 40 | radius += step * 5; 41 | if (radius < 2) { 42 | radius = 2; 43 | } 44 | if (radius > 254) { 45 | radius = 254; 46 | } 47 | StackBlur(radius); 48 | window.Repaint(); 49 | } 50 | -------------------------------------------------------------------------------- /component/samples/basic/StackBlur (text).js: -------------------------------------------------------------------------------- 1 | window.DefineScript('StackBlur (text)', {author: 'T.P Wang / marc2003'}); 2 | include('docs/Flags.js'); 3 | include('docs/Helpers.js'); 4 | 5 | const g_font = gdi.Font('Segoe UI', 32, FontStyle.Bold); 6 | const text = '\'Stack Blur\' Sample'; 7 | 8 | let ww = 0, wh = 0; 9 | let img_to_blur; 10 | 11 | function on_paint(gr) { 12 | img_to_blur && gr.DrawImage(img_to_blur, 0, 0, ww, wh, 0, 0, ww, wh); 13 | gr.SetTextRenderingHint(TextRenderingHint.ClearTypeGridFit); 14 | gr.DrawString(text, g_font, RGB(0, 0, 255), 0, 0, ww, wh, StringFormat(StringAlignment.Center, StringAlignment.Center)); 15 | } 16 | 17 | function on_size() { 18 | ww = window.Width; 19 | wh = window.Height; 20 | if (ww <= 0 || wh <= 0) { 21 | return; 22 | } 23 | img_to_blur = gdi.CreateImage(ww, wh); 24 | let g = img_to_blur.GetGraphics(); 25 | g.SetTextRenderingHint(TextRenderingHint.AntiAlias); 26 | g.DrawString(text, g_font, RGB(0, 0, 255), 0, 0, ww, wh, StringFormat(StringAlignment.Center, StringAlignment.Center)); 27 | img_to_blur.ReleaseGraphics(g); 28 | // Make Stack Blur, radius value can be between 2 and 254 29 | img_to_blur.StackBlur(30); 30 | } 31 | -------------------------------------------------------------------------------- /component/samples/basic/Timer.js: -------------------------------------------------------------------------------- 1 | window.DefineScript('Timer', { author: 'T.P Wang' }); 2 | 3 | // This sample create two timers 4 | // Click the window to start the timer, and see the result after the console is shown. 5 | // Click the window again to kill all timers. 6 | 7 | let g_timer_started = false; 8 | let g_count = 0; 9 | let g_timer1_ID = 0, g_timer2_ID = 0; 10 | 11 | function print_to_console(msg) { 12 | console.log('Timer test:', msg); 13 | } 14 | 15 | function on_mouse_lbtn_up() { 16 | if (!g_timer_started) { 17 | // Timer are created here 18 | // 2s - one shot, happens after 2000 ms, only once 19 | g_timer1_ID = setTimeout(() => { 20 | // Print and show console 21 | fb.ShowConsole(); 22 | print_to_console('g_timer1: Show console now.'); 23 | }, 2000); 24 | 25 | // 500ms - periodic, happens every 500 ms 26 | g_timer2_ID = setInterval(() => { 27 | g_count++; 28 | print_to_console('g_timer2: ' + g_count + ' time(s).'); 29 | }, 500); 30 | 31 | g_timer_started = true; 32 | } 33 | else { 34 | // Kill all timers 35 | clearTimeout(g_timer2_ID); 36 | clearInterval(g_timer1_ID); 37 | g_timer_started = false; 38 | g_count = 0; 39 | print_to_console('Timers killed.'); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /component/samples/basic/TrackInfo Follows Cursor.js: -------------------------------------------------------------------------------- 1 | window.DefineScript('TrackInfo follows cursor'); 2 | include('docs/Flags.js'); 3 | include('docs/Helpers.js'); 4 | 5 | const font = gdi.Font('Segoe UI', 14, 0); 6 | const tfo = fb.TitleFormat('%title%[ - %artist%]'); 7 | let handle = fb.GetFocusItem(); 8 | 9 | function on_item_focus_change() { 10 | handle = fb.GetFocusItem(); 11 | window.Repaint(); 12 | } 13 | 14 | function on_playlist_switch() { 15 | //because on_item_focus_change isn't called when the user switches playlists 16 | //we must invoke it manually inside this callback 17 | on_item_focus_change(); 18 | } 19 | 20 | function on_paint(gr) { 21 | if (handle) { 22 | gr.GdiDrawText(tfo.EvalWithMetadb(handle), font, RGB(0, 0, 0), 0, 0, window.Width, window.Height, DT_VCENTER | DT_CENTER | DT_END_ELLIPSIS | DT_CALCRECT | DT_NOPREFIX); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /component/samples/basic/Volbar with GdiDrawText.js: -------------------------------------------------------------------------------- 1 | window.DefineScript('Volbar with GdiDrawText', {author: 'T.P Wang'}); 2 | include('docs/Flags.js'); 3 | include('docs/Helpers.js'); 4 | 5 | const g_font = gdi.Font('Segoe UI', 12, 0); 6 | let g_drag = false; 7 | let ww = 0, wh = 0; 8 | 9 | function on_size() { 10 | ww = window.Width; 11 | wh = window.Height; 12 | } 13 | 14 | function on_paint(gr) { 15 | let volume = fb.Volume; 16 | let pos = ww * vol2pos(volume); 17 | let txt = volume.toFixed(2) + 'dB'; 18 | if (pos) { 19 | gr.FillGradRect(0, 0, pos, wh, 90, RGB(240, 240, 240), RGB(100, 230, 100)); 20 | } 21 | if (ww > pos) { 22 | gr.FillGradRect(pos, 0, ww - pos, wh, 90, RGB(240, 240, 240), RGB(190, 190, 190)); 23 | } 24 | gr.GdiDrawText(txt, g_font, RGB(64, 64, 128), 0, 0, ww, wh, DT_CENTER | DT_VCENTER | DT_SINGLELINE); 25 | gr.DrawRect(0, 0, ww - 1, wh - 1, 1.0, RGB(150, 150, 150)); 26 | } 27 | 28 | function on_mouse_lbtn_down(x, y) { 29 | g_drag = true; 30 | } 31 | 32 | function on_mouse_lbtn_up(x, y) { 33 | on_mouse_move(x, y); 34 | g_drag = false; 35 | } 36 | 37 | function on_mouse_move(x, y) { 38 | if (g_drag) { 39 | let pos = (x < 0 ? 0 : (x > ww ? 1 : x / ww)); 40 | fb.Volume = pos2vol(pos); 41 | } 42 | } 43 | 44 | function on_mouse_wheel(delta) { 45 | if (delta > 0) { 46 | fb.VolumeUp(); 47 | } 48 | else { 49 | fb.VolumeDown(); 50 | } 51 | } 52 | 53 | function on_volume_change(val) { 54 | window.Repaint(); 55 | } 56 | -------------------------------------------------------------------------------- /component/samples/basic/Watch Metadb Change.js: -------------------------------------------------------------------------------- 1 | window.DefineScript('Watch Metadb Change', { author: 'T.P Wang' }); 2 | 3 | // Callback 4 | function on_metadb_changed(handle_list) { 5 | let count = handle_list.Count; 6 | // show how many files have been changed 7 | fb.ShowPopupMessage(count + (count === 1 ? ' file has' : ' files have') + ' been changed.'); 8 | } 9 | -------------------------------------------------------------------------------- /component/samples/basic/html/styles10.css: -------------------------------------------------------------------------------- 1 | body { color: WindowText; background-color: Menu; } 2 | input { font:caption; border: 1px solid #7A7A7A; width: 100%; } 3 | input:focus { outline: none !important; border:1px solid #0078D7; } 4 | input:hover:focus { outline: none !important; border:1px solid #0078D7; } 5 | input:hover { outline: none !important; border:1px solid #000000; } 6 | label { font:caption; } 7 | button { font:caption; background: #E1E1E1; color:ButtonText; border: 1px solid #ADADAD; margin: 5px; padding: 3px; width: 70px; } 8 | button:focus { outline: none !important; border:2px solid #0078D7; padding: 2px; } 9 | button:hover { background: #e5f1fb; outline: none !important; border:1px solid #0078D7; padding: 3px; }div { overflow: hidden; } 10 | button:focus:hover { background: #e5f1fb; outline: none !important; border:2px solid #0078D7; padding: 2px; }';span { display:block; overflow: hidden; padding-right:10px; } 11 | button[disabled] { background: #CCCCCC; color:#EBEBE4; } 12 | /* --Suppress button:hover manually, since not() is not working =( */ 13 | button[disabled]:hover { border: 1px solid #ADADAD; padding: 3px; } -------------------------------------------------------------------------------- /component/samples/basic/html/styles7.css: -------------------------------------------------------------------------------- 1 | body { color: WindowText; background-color: Menu; } 2 | input { font:caption; border: 1px solid #7A7A7A; width: 100%; } 3 | input:focus { outline: none !important; border:1px solid #0078D7; } 4 | input:hover:focus { outline: none !important; border:1px solid #0078D7; } 5 | input:hover { outline: none !important; border:1px solid #000000; } 6 | label { font:caption; } 7 | button { font:caption; background: #E1E1E1; color:ButtonText; border: 1px solid #ADADAD; margin: 5px; padding: 3px; width: 70px; } 8 | button:focus { border: 1px solid #0078D7; padding: 3px; } 9 | button:hover { background: #e5f1fb; border: 1px solid #0078D7; padding: 3px; } 10 | button:focus:hover { background: #e5f1fb; border:1px solid #0078D7; padding: 3px; } 11 | button[disabled] { background: #CCCCCC; color:#EBEBE4; } 12 | /* --Suppress button:hover manually, since not() is not working =( */ 13 | button[disabled]:hover { border: 1px solid #ADADAD; padding: 3px; } -------------------------------------------------------------------------------- /component/samples/basic/images/Default.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheQwertiest/foo_spider_monkey_panel/997ad85febd614d30949e85c8df2c126f58038ed/component/samples/basic/images/Default.png -------------------------------------------------------------------------------- /component/samples/basic/images/Random.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheQwertiest/foo_spider_monkey_panel/997ad85febd614d30949e85c8df2c126f58038ed/component/samples/basic/images/Random.png -------------------------------------------------------------------------------- /component/samples/basic/images/Repeat (Playlist).png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheQwertiest/foo_spider_monkey_panel/997ad85febd614d30949e85c8df2c126f58038ed/component/samples/basic/images/Repeat (Playlist).png -------------------------------------------------------------------------------- /component/samples/basic/images/Repeat (Track).png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheQwertiest/foo_spider_monkey_panel/997ad85febd614d30949e85c8df2c126f58038ed/component/samples/basic/images/Repeat (Track).png -------------------------------------------------------------------------------- /component/samples/basic/images/Shuffle (albums).png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheQwertiest/foo_spider_monkey_panel/997ad85febd614d30949e85c8df2c126f58038ed/component/samples/basic/images/Shuffle (albums).png -------------------------------------------------------------------------------- /component/samples/basic/images/Shuffle (folders).png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheQwertiest/foo_spider_monkey_panel/997ad85febd614d30949e85c8df2c126f58038ed/component/samples/basic/images/Shuffle (folders).png -------------------------------------------------------------------------------- /component/samples/basic/images/Shuffle (tracks).png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheQwertiest/foo_spider_monkey_panel/997ad85febd614d30949e85c8df2c126f58038ed/component/samples/basic/images/Shuffle (tracks).png -------------------------------------------------------------------------------- /component/samples/basic/images/cog.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheQwertiest/foo_spider_monkey_panel/997ad85febd614d30949e85c8df2c126f58038ed/component/samples/basic/images/cog.png -------------------------------------------------------------------------------- /component/samples/basic/images/image.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheQwertiest/foo_spider_monkey_panel/997ad85febd614d30949e85c8df2c126f58038ed/component/samples/basic/images/image.jpg -------------------------------------------------------------------------------- /component/samples/basic/images/mask.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheQwertiest/foo_spider_monkey_panel/997ad85febd614d30949e85c8df2c126f58038ed/component/samples/basic/images/mask.png -------------------------------------------------------------------------------- /component/samples/basic/images/post.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheQwertiest/foo_spider_monkey_panel/997ad85febd614d30949e85c8df2c126f58038ed/component/samples/basic/images/post.jpg -------------------------------------------------------------------------------- /component/samples/js-smooth/JS Smooth Playlist Manager.js: -------------------------------------------------------------------------------- 1 | window.DefinePanel("JS Smooth Playlist Manager", { author : "Br3tt aka Falstaff", features : { drag_n_drop : true }}); 2 | include(fb.ComponentPath + "samples\\js-smooth\\js\\JScommon.js"); 3 | include(fb.ComponentPath + "samples\\js-smooth\\js\\JSinputbox.js"); 4 | include(fb.ComponentPath + "samples\\js-smooth\\js\\jsspm.js"); 5 | 6 | 7 | /* 8 | [Features] 9 | * order playlists by dragging items with the mouse 10 | * presets autoplaylists available 11 | * True Smooth Scrolling 12 | * Screen Touch support 13 | * Header bar at Top (can be hidden with CTRL+T) 14 | * Vertical Scrollbar (can be hidden with CTRL+B) 15 | * Filter box 16 | * Custom or Cover art Wallpaper as background supported (including a blur effect) 17 | * Windows scaling compliant (you can adjust zoom size in real time with CTRL+mousewheel) 18 | * Custom Panel Colors (in Properties window) 19 | * ... and more! 20 | 21 | [Tips] 22 | * Hold SHIFT key + right click to display Configure script and panel Properties entries 23 | * Change colors and fonts in foobar2000 Preferences > DefaultUI or ColumsUI 24 | * Some minor settings can be changed in window Properties (SHIFT + right click > Properties), use it carefully 25 | * Right Click on items for contextual menu for the selection 26 | * CTRL+T to toggle the columns toolbar 27 | * CTRL+B to toggle the scrollbar 28 | * Hold CTRL + Mouse Wheel to scale elements (useful for 'retina' screens) 29 | * Hold SHIFT + Mouse Wheel to scale group header and so the cover art size 30 | * F2 key to rename selected/active playlist 31 | * ... etc 32 | */ 33 | -------------------------------------------------------------------------------- /component/samples/js-smooth/images/default.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheQwertiest/foo_spider_monkey_panel/997ad85febd614d30949e85c8df2c126f58038ed/component/samples/js-smooth/images/default.png -------------------------------------------------------------------------------- /component/samples/js-smooth/images/genres/60's.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheQwertiest/foo_spider_monkey_panel/997ad85febd614d30949e85c8df2c126f58038ed/component/samples/js-smooth/images/genres/60's.jpg -------------------------------------------------------------------------------- /component/samples/js-smooth/images/genres/70's.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheQwertiest/foo_spider_monkey_panel/997ad85febd614d30949e85c8df2c126f58038ed/component/samples/js-smooth/images/genres/70's.jpg -------------------------------------------------------------------------------- /component/samples/js-smooth/images/genres/80's.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheQwertiest/foo_spider_monkey_panel/997ad85febd614d30949e85c8df2c126f58038ed/component/samples/js-smooth/images/genres/80's.jpg -------------------------------------------------------------------------------- /component/samples/js-smooth/images/genres/90's.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheQwertiest/foo_spider_monkey_panel/997ad85febd614d30949e85c8df2c126f58038ed/component/samples/js-smooth/images/genres/90's.jpg -------------------------------------------------------------------------------- /component/samples/js-smooth/images/load.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheQwertiest/foo_spider_monkey_panel/997ad85febd614d30949e85c8df2c126f58038ed/component/samples/js-smooth/images/load.png -------------------------------------------------------------------------------- /component/samples/jsplaylist-mod/images/default.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheQwertiest/foo_spider_monkey_panel/997ad85febd614d30949e85c8df2c126f58038ed/component/samples/jsplaylist-mod/images/default.jpg -------------------------------------------------------------------------------- /component/samples/jsplaylist-mod/images/load.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheQwertiest/foo_spider_monkey_panel/997ad85febd614d30949e85c8df2c126f58038ed/component/samples/jsplaylist-mod/images/load.png -------------------------------------------------------------------------------- /component/samples/jsplaylist-mod/images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheQwertiest/foo_spider_monkey_panel/997ad85febd614d30949e85c8df2c126f58038ed/component/samples/jsplaylist-mod/images/logo.png -------------------------------------------------------------------------------- /component/samples/jsplaylist-mod/images/noartist.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheQwertiest/foo_spider_monkey_panel/997ad85febd614d30949e85c8df2c126f58038ed/component/samples/jsplaylist-mod/images/noartist.png -------------------------------------------------------------------------------- /component/samples/jsplaylist-mod/images/nocover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheQwertiest/foo_spider_monkey_panel/997ad85febd614d30949e85c8df2c126f58038ed/component/samples/jsplaylist-mod/images/nocover.png -------------------------------------------------------------------------------- /component/samples/jsplaylist-mod/images/stream.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheQwertiest/foo_spider_monkey_panel/997ad85febd614d30949e85c8df2c126f58038ed/component/samples/jsplaylist-mod/images/stream.png -------------------------------------------------------------------------------- /component/samples/packages/{A584FDEF-C88A-4849-94D5-F33C71649927}/assets/text.txt: -------------------------------------------------------------------------------- 1 | This is the content of an asset file that is included in and distributed with the package. -------------------------------------------------------------------------------- /component/samples/packages/{A584FDEF-C88A-4849-94D5-F33C71649927}/main.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | // include script from the package 4 | include('utils.js') 5 | 6 | let font = gdi.Font('Segoe UI', 12) 7 | let ww = 0; 8 | let wh = 0; 9 | 10 | 11 | function on_paint(gr) { 12 | gr.DrawRect(0, 0, ww, wh, 4, 0xFF000000); 13 | 14 | gr.GdiDrawText(`Click here to show package information`, font, 0xFF000000, 8, 8, ww, wh/3); 15 | 16 | gr.DrawLine(0, wh/3, ww, wh/3, 2, 0xFF000000); 17 | gr.GdiDrawText(`Click here to show asset content`, font, 0xFF000000, 8, wh/3 + 8, ww, wh/3 + 8); 18 | 19 | gr.DrawLine(0, 2*wh/3, ww, 2*wh/3, 2, 0xFF000000); 20 | gr.GdiDrawText('Quick-access all package scripts via `Edit script` submenu of context menu\n' + 21 | 'View and modify package configuration via `Package` tab - accessible through `Configure` in context menu\n' + 22 | '(right click to open it)', font, 0xFF000000, 8, 2*wh/3 + 8, ww, 2*wh/3 + 8); 23 | } 24 | 25 | function on_size(width, height) { 26 | ww = width; 27 | wh = height; 28 | } 29 | 30 | function on_mouse_lbtn_up(x, y) { 31 | if (y < wh/3) { 32 | // function from utils.js 33 | my_utils.showScriptInfo(); 34 | } 35 | else if (y >= wh/3 && y < 2*wh/3) { 36 | // function from utils.js 37 | my_utils.loadAndDisplayAsset('text.txt'); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /component/samples/packages/{A584FDEF-C88A-4849-94D5-F33C71649927}/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "author": "TheQwertiest", 3 | "description": "This is an example package that illustrates the package structure and basic features.", 4 | "enableDragDrop": false, 5 | "id": "{A584FDEF-C88A-4849-94D5-F33C71649927}", 6 | "name": "Example package", 7 | "shouldGrabFocus": true, 8 | "version": "1.0.0" 9 | } -------------------------------------------------------------------------------- /component/samples/packages/{A584FDEF-C88A-4849-94D5-F33C71649927}/scripts/utils.js: -------------------------------------------------------------------------------- 1 | let my_utils = {} 2 | 3 | my_utils.scriptInfo = window.ScriptInfo; 4 | my_utils.packageInfo = utils.GetPackageInfo(my_utils.scriptInfo.PackageId); 5 | my_utils.showScriptInfo = function() { 6 | let si = my_utils.scriptInfo; 7 | fb.ShowPopupMessage(`Package information: ${si.Name} v${si.Version} by ${si.Author}`); 8 | }; 9 | my_utils.loadAndDisplayAsset = function(assetFile) { 10 | let content = utils.ReadTextFile(`${my_utils.packageInfo.Directories.Assets}/${assetFile}`); 11 | fb.ShowPopupMessage(`Asset '${assetFile}' content:\n${content}`); 12 | }; 13 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/com_objects/com_interface.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // Generated from com_interface.idl 4 | #include 5 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/com_objects/drop_source_impl.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include 6 | 7 | #include 8 | 9 | _COM_SMARTPTR_TYPEDEF( IDragSourceHelper, IID_IDragSourceHelper ); 10 | 11 | namespace smp::com 12 | 13 | { 14 | 15 | class IDropSourceImpl : public IDropSource 16 | { 17 | public: 18 | /// @throw qwr::QwrException 19 | IDropSourceImpl( HWND hWnd, IDataObject* pDataObject, size_t itemCount, bool isThemed, bool showText, Gdiplus::Bitmap* pUserImage ); 20 | virtual ~IDropSourceImpl(); 21 | 22 | // IDropSource 23 | STDMETHODIMP QueryContinueDrag( BOOL fEscapePressed, DWORD grfKeyState ) override; 24 | STDMETHODIMP GiveFeedback( DWORD dwEffect ) override; 25 | ULONG STDMETHODCALLTYPE AddRef() override; 26 | ULONG STDMETHODCALLTYPE Release() override; 27 | 28 | private: 29 | IDragSourceHelperPtr pDragSourceHelper_; 30 | IDataObject* pDataObject_ = nullptr; 31 | SHDRAGIMAGE dragImage_ = {}; 32 | 33 | bool wasShowingLayered_ = false; 34 | 35 | std::atomic refCount_ = 0; 36 | DWORD lastEffect_ = DROPEFFECT_NONE; 37 | 38 | BEGIN_COM_QI_IMPL() 39 | COM_QI_ENTRY_MULTI( IUnknown, IDropSource ) 40 | COM_QI_ENTRY( IDropSource ) 41 | END_COM_QI_IMPL() 42 | }; 43 | 44 | } // namespace smp::com 45 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/com_objects/drop_target_impl.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace smp::com 6 | { 7 | 8 | class IDropTargetImpl : public IDropTarget 9 | { 10 | public: 11 | IDropTargetImpl( HWND hWnd ); 12 | 13 | virtual ~IDropTargetImpl(); 14 | 15 | HRESULT RegisterDragDrop(); 16 | HRESULT RevokeDragDrop(); 17 | 18 | // IDropTarget 19 | STDMETHODIMP DragEnter( IDataObject* pDataObj, DWORD grfKeyState, POINTL pt, DWORD* pdwEffect ) override; 20 | STDMETHODIMP DragOver( DWORD grfKeyState, POINTL pt, DWORD* pdwEffect ) override; 21 | STDMETHODIMP DragLeave() override; 22 | STDMETHODIMP Drop( IDataObject* pDataObj, DWORD grfKeyState, POINTL pt, DWORD* pdwEffect ) override; 23 | 24 | // Overrides 25 | virtual DWORD OnDragEnter( IDataObject* pDataObj, DWORD grfKeyState, POINTL pt, DWORD dwEffect ) = 0; 26 | virtual DWORD OnDragOver( DWORD grfKeyState, POINTL pt, DWORD dwEffect ) = 0; 27 | virtual DWORD OnDrop( IDataObject* pDataObj, DWORD grfKeyState, POINTL pt, DWORD dwEffect ) = 0; 28 | virtual void OnDragLeave() = 0; 29 | 30 | protected: 31 | HWND hWnd_; 32 | }; 33 | 34 | } // namespace smp::com 35 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/com_objects/host_external.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "host_external.h" 4 | 5 | namespace smp::com 6 | { 7 | 8 | HostExternal::HostExternal( _variant_t data ) 9 | : data_( data ) 10 | { 11 | } 12 | 13 | STDMETHODIMP HostExternal::get_dialogArguments( VARIANT* pData ) 14 | { 15 | if ( pData ) 16 | { 17 | return VariantCopy( pData, &data_ ); 18 | } 19 | else 20 | { 21 | return S_OK; 22 | } 23 | } 24 | 25 | } // namespace smp::com 26 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/com_objects/host_external.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include 7 | 8 | _COM_SMARTPTR_TYPEDEF( IHostExternal, __uuidof( IHostExternal ) ); 9 | 10 | namespace smp::com 11 | { 12 | 13 | class HostExternal : public IDispatchImpl3 14 | { 15 | protected: 16 | HostExternal( _variant_t data ); 17 | ~HostExternal() override = default; 18 | 19 | public: 20 | STDMETHODIMP get_dialogArguments( VARIANT* pData ) override; 21 | 22 | private: 23 | _variant_t data_; 24 | }; 25 | 26 | } // namespace smp::com 27 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/com_objects/internal/drag_image.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheQwertiest/foo_spider_monkey_panel/997ad85febd614d30949e85c8df2c126f58038ed/foo_spider_monkey_panel/com_objects/internal/drag_image.cpp -------------------------------------------------------------------------------- /foo_spider_monkey_panel/com_objects/internal/drag_image.h: -------------------------------------------------------------------------------- 1 | // Copied from https://github.com/reupen/ui_helpers 2 | // Copyright (c) Reupen Shah 2003-2017 3 | // All rights reserved. 4 | // See THIRD_PARTY_NOTICES.md for full license text. 5 | 6 | #pragma once 7 | 8 | namespace uih 9 | { 10 | 11 | void draw_drag_image_background( HWND wnd, bool isThemed, HTHEME theme, HDC dc, COLORREF selectionBackgroundColour, const RECT& rc ); 12 | void draw_drag_image_label( HWND wnd, bool isThemed, HTHEME theme, HDC dc, const RECT& rc, COLORREF selectionTextColour, const char* text ); 13 | void draw_drag_image_icon( HDC dc, const RECT& rc, HICON icon ); 14 | bool create_drag_image( HWND wnd, bool isThemed, HTHEME theme, COLORREF selectionBackgroundColour, 15 | COLORREF selectionTextColour, HICON icon, const LPLOGFONT font, const char* text, 16 | Gdiplus::Bitmap* pCustomImage, LPSHDRAGIMAGE lpsdi ); 17 | 18 | } // namespace uih 19 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/com_objects/internal/drag_utils.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define DDWM_SETCURSOR ( WM_USER + 2 ) 4 | #define DDWM_UPDATEWINDOW ( WM_USER + 3 ) 5 | 6 | namespace smp::com::drag 7 | { 8 | 9 | HRESULT SetDefaultImage( IDataObject* pdtobj ); 10 | HRESULT SetDropText( IDataObject* pdtobj, DROPIMAGETYPE dit, const wchar_t* msg, const wchar_t* insert ); 11 | bool RenderDragImage( HWND hWnd, size_t itemCount, bool isThemed, bool showText, Gdiplus::Bitmap* pCustomImage, SHDRAGIMAGE& dragImage ); 12 | HRESULT GetDragWindow( IDataObject* pDataObj, HWND& p_wnd ); 13 | HRESULT GetIsShowingLayered( IDataObject* pDataObj, BOOL& p_out ); 14 | 15 | } // namespace smp::com::drag 16 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/com_objects/track_drop_target.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | namespace smp::panel 9 | { 10 | 11 | class PanelWindow; 12 | 13 | } 14 | 15 | namespace smp::com 16 | { 17 | 18 | class TrackDropTarget 19 | : public IDropTargetImpl 20 | { 21 | protected: 22 | virtual void FinalRelease(); 23 | 24 | public: 25 | TrackDropTarget( panel::PanelWindow& panel ); 26 | ~TrackDropTarget() override = default; 27 | 28 | // IDropTargetImpl 29 | DWORD OnDragEnter( IDataObject* pDataObj, DWORD grfKeyState, POINTL pt, DWORD dwEffect ) override; 30 | DWORD OnDragOver( DWORD grfKeyState, POINTL pt, DWORD dwEffect ) override; 31 | DWORD OnDrop( IDataObject* pDataObj, DWORD grfKeyState, POINTL pt, DWORD dwEffect ) override; 32 | void OnDragLeave() override; 33 | 34 | static void ProcessDropEvent( IDataObjectPtr pDataObject, std::optional dragParamsOpt ); 35 | 36 | private: 37 | [[nodiscard]] std::optional 38 | PutDragEvent( EventId eventId, DWORD grfKeyState, POINTL pt, DWORD allowedEffects ); 39 | 40 | private: 41 | panel::PanelWindow* pPanel_ = nullptr; 42 | IDataObjectPtr pDataObject_; 43 | DWORD fb2kAllowedEffect_ = DROPEFFECT_NONE; 44 | 45 | BEGIN_COM_QI_IMPL() 46 | COM_QI_ENTRY_MULTI( IUnknown, IDropTarget ) 47 | COM_QI_ENTRY( IDropTarget ) 48 | END_COM_QI_IMPL() 49 | }; 50 | 51 | } // namespace smp::com 52 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/com_utils/com_destruction_handler.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // TLDR: This is needed to avoid message loop re-entrancy hell and consequent dead-locks. 4 | // Full story: 5 | // COM object might lock and return control to message loop when being destroyed. 6 | // JS GC acquires lock during it's operations. 7 | // If COM object locks during JS object's `finalize`, then it will cause a dead-lock 8 | // once GC is triggered again in re-entered message loop. 9 | 10 | namespace smp::com 11 | { 12 | 13 | struct StorageObject 14 | { 15 | IDispatch* pDispatch = nullptr; 16 | IUnknown* pUnknown = nullptr; 17 | ITypeInfo* pTypeInfo = nullptr; 18 | _variant_t variant; 19 | }; 20 | 21 | /// @remark Should be called only from the main thread 22 | [[nodiscard]] StorageObject* GetNewStoredObject(); 23 | 24 | /// @remark Should be called only from the main thread 25 | void MarkStoredObjectAsToBeDeleted( StorageObject* pObject ); 26 | 27 | /// @remark Should be called only from the main thread 28 | void DeleteMarkedObjects(); 29 | 30 | /// @remark Should be called only from the main thread 31 | void DeleteAllStoredObject(); 32 | 33 | } // namespace smp::com 34 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/com_utils/com_error_helpers.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace smp::com 6 | { 7 | 8 | void ReportActiveXError( HRESULT hresult, EXCEPINFO& exception, UINT& argerr ); 9 | 10 | } // namespace smp::com 11 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/component_paths.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace smp::path 6 | { 7 | 8 | std::filesystem::path JsDocsIndex(); 9 | 10 | std::filesystem::path ScriptSamples(); 11 | 12 | std::filesystem::path ModulePackages_Sample(); 13 | std::filesystem::path ModulePackages_Profile(); 14 | 15 | std::filesystem::path SmpPackages_Sample(); 16 | std::filesystem::path SmpPackages_Profile(); 17 | std::filesystem::path SmpPackages_Foobar2000(); 18 | 19 | std::filesystem::path SmpPackages_Storage(); 20 | 21 | std::filesystem::path TempFolder(); 22 | std::filesystem::path TempFolder_SmpPackageUnpack(); 23 | std::filesystem::path TempFolder_SmpPackageBackups(); 24 | std::filesystem::path TempFolder_SmpPackagesToInstall(); 25 | std::filesystem::path TempFolder_SmpPackagesToRemove(); 26 | std::filesystem::path TempFolder_SmpPackagesInUse(); 27 | 28 | } // namespace smp::path 29 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/config/basic_script_sources.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace smp::config 6 | { 7 | 8 | struct NonPackageScript 9 | { 10 | virtual ~NonPackageScript() = default; 11 | 12 | qwr::u8string name; 13 | qwr::u8string version; 14 | qwr::u8string author; 15 | qwr::u8string description; 16 | bool shouldGrabFocus = true; 17 | bool enableDragDrop = false; 18 | }; 19 | 20 | struct InMemoryScript : public NonPackageScript 21 | { 22 | qwr::u8string script; 23 | bool isModule = false; 24 | }; 25 | 26 | struct ScriptFile : public NonPackageScript 27 | { 28 | std::filesystem::path scriptPath; 29 | bool isModule = false; 30 | bool isSample = false; 31 | }; 32 | 33 | } // namespace smp::config 34 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/config/default_script.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "default_script.h" 4 | 5 | #include 6 | 7 | namespace smp::config 8 | { 9 | 10 | qwr::u8string GetDefaultScript() 11 | { 12 | puResource puRes = uLoadResource( core_api::get_my_instance(), uMAKEINTRESOURCE( IDR_DEFAULT_SCRIPT ), "SCRIPT" ); 13 | if ( puRes ) 14 | { 15 | return qwr::u8string{ static_cast( puRes->GetPointer() ), puRes->GetSize() }; 16 | } 17 | else 18 | { 19 | return qwr::u8string{}; 20 | } 21 | } 22 | 23 | } // namespace smp::config 24 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/config/default_script.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace smp::config 4 | { 5 | 6 | qwr::u8string GetDefaultScript(); 7 | 8 | } // namespace smp::config 9 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/config/module_package/module_specifier.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace smp::config 6 | { 7 | 8 | /// @throw qwr::QwrException 9 | void VerifyModulePackageName( const qwr::u8string& name ); 10 | 11 | /// @throw qwr::QwrException 12 | std::tuple ParseBareModuleSpecifier( const qwr::u8string& moduleSpecifier ); 13 | 14 | } // namespace smp::config 15 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/config/module_package/package.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include 6 | 7 | namespace smp::config 8 | { 9 | 10 | struct ModulePackage 11 | { 12 | // base 13 | qwr::u8string name; 14 | qwr::u8string author; 15 | qwr::SemVer version; 16 | qwr::u8string description; 17 | std::optional mainOpt; 18 | 19 | // extensions 20 | qwr::u8string displayedName; 21 | bool enableDragDrop = false; 22 | bool shouldGrabFocus = true; 23 | 24 | // convenience 25 | std::filesystem::path packageDir; 26 | qwr::u8string scope; 27 | bool isSample = false; 28 | 29 | std::filesystem::path GetEntryFile() const; 30 | 31 | /// @throw qwr::QwrException 32 | void ValidatePackagePath() const; 33 | 34 | /// @throw qwr::QwrException 35 | void ToFile( const std::filesystem::path& packageJson ); 36 | 37 | /// @throw qwr::QwrException 38 | [[nodiscard]] static ModulePackage FromFile( const std::filesystem::path& packageJson ); 39 | }; 40 | 41 | } // namespace smp::config 42 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/config/module_package/package_manager.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | namespace smp::config 8 | { 9 | 10 | class ModulePackageManager 11 | { 12 | public: 13 | [[nodiscard]] ModulePackageManager() = default; 14 | 15 | /// @throw qwr::QwrException 16 | [[nodiscard]] std::vector 17 | GetPackages( const std::optional& parentDir = std::nullopt ) const; 18 | 19 | /// @throw qwr::QwrException 20 | [[nodiscard]] std::optional 21 | GetPackage( const qwr::u8string& name ) const; 22 | 23 | void Refresh(); 24 | 25 | public: 26 | [[nodiscard]] static std::filesystem::path GetPathForNewPackage( const qwr::u8string& name ); 27 | [[nodiscard]] static bool IsSamplePackage( const std::filesystem::path& packageJson ); 28 | 29 | private: 30 | // TODO: add caching 31 | }; 32 | 33 | } // namespace smp::config 34 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/config/panel_config.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | namespace smp::config 8 | { 9 | 10 | struct PanelConfig 11 | { 12 | PanelProperties properties; 13 | PanelSettings panelSettings; 14 | RawScriptSourceVariant scriptSource; 15 | 16 | public: 17 | PanelConfig(); 18 | 19 | void ResetToDefault(); 20 | 21 | /// @throw qwr::QwrException 22 | [[nodiscard]] static PanelConfig Load( stream_reader& reader, size_t size, abort_callback& abort ); 23 | 24 | /// @throw qwr::QwrException 25 | void Save( stream_writer& writer, abort_callback& abort ) const; 26 | 27 | /// @throw qwr::QwrException 28 | static void SaveDefault( stream_writer& writer, abort_callback& abort ); 29 | }; 30 | 31 | } // namespace smp::config 32 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/config/panel_config_formats.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace smp::config 4 | { 5 | 6 | enum class SerializationFormat : uint8_t 7 | { 8 | Com, 9 | Binary, 10 | Json 11 | }; 12 | 13 | } // namespace smp::config 14 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/config/panel_properties.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "panel_properties.h" 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | namespace smp::config 10 | { 11 | 12 | PanelProperties PanelProperties::FromJson( const qwr::u8string& jsonString ) 13 | { 14 | return smp::config::json::DeserializeProperties( jsonString ); 15 | } 16 | 17 | qwr::u8string PanelProperties::ToJson() const 18 | { 19 | return smp::config::json::SerializeProperties( *this ); 20 | } 21 | 22 | PanelProperties PanelProperties::Load( stream_reader& reader, abort_callback& abort, SerializationFormat format ) 23 | { 24 | switch ( format ) 25 | { 26 | case smp::config::SerializationFormat::Com: 27 | return smp::config::com::LoadProperties( reader, abort ); 28 | case smp::config::SerializationFormat::Binary: 29 | return smp::config::binary::LoadProperties( reader, abort ); 30 | case smp::config::SerializationFormat::Json: 31 | return smp::config::json::LoadProperties( reader, abort ); 32 | default: 33 | { 34 | assert( false ); 35 | throw qwr::QwrException( "Internal error: unknown serialization format" ); 36 | } 37 | } 38 | } 39 | 40 | void PanelProperties::Save( stream_writer& writer, abort_callback& abort ) const 41 | { 42 | smp::config::json::SaveProperties( writer, abort, *this ); 43 | } 44 | 45 | } // namespace smp::config 46 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/config/panel_properties.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include 7 | #include 8 | 9 | namespace smp::config 10 | { 11 | 12 | struct PanelProperties 13 | { 14 | using PropertyMap = std::unordered_map>; 15 | PropertyMap values; 16 | 17 | public: 18 | /// @throw qwr::QwrException 19 | [[nodiscard]] static PanelProperties FromJson( const qwr::u8string& jsonString ); 20 | 21 | /// @throw qwr::QwrException 22 | [[nodiscard]] qwr::u8string ToJson() const; 23 | 24 | /// @throw qwr::QwrException 25 | [[nodiscard]] static PanelProperties Load( stream_reader& reader, abort_callback& abort, SerializationFormat format = SerializationFormat::Json ); 26 | 27 | /// @throw qwr::QwrException 28 | void Save( stream_writer& writer, abort_callback& abort ) const; 29 | }; 30 | 31 | } // namespace smp::config 32 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/config/panel_settings.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace smp::config 4 | { 5 | 6 | enum class EdgeStyle : uint8_t 7 | { 8 | NoEdge = 0, 9 | SunkenEdge, 10 | GreyEdge, 11 | Default = NoEdge, 12 | }; 13 | 14 | struct PanelSettings 15 | { 16 | qwr::u8string id; 17 | EdgeStyle edgeStyle = EdgeStyle::Default; 18 | bool isPseudoTransparent = false; 19 | }; 20 | 21 | } // namespace smp::config 22 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/config/raw_panel_script_source.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "raw_panel_script_source.h" 4 | 5 | #include 6 | 7 | namespace smp::config 8 | { 9 | 10 | ScriptSourceType GetSourceType( const RawScriptSourceVariant& source ) 11 | { 12 | return std::visit( 13 | qwr::Visitor{ 14 | []( const RawModulePackage& /*arg*/ ) { return ScriptSourceType::ModulePackage; }, 15 | []( const RawSmpPackage& /*arg*/ ) { return ScriptSourceType::SmpPackage; }, 16 | [&]( const RawScriptFile& /*arg*/ ) { return ScriptSourceType::File; }, 17 | [&]( const RawSampleFile& /*arg*/ ) { return ScriptSourceType::Sample; }, 18 | []( const RawInMemoryScript& /*arg*/ ) { return ScriptSourceType::InMemory; } }, 19 | source ); 20 | } 21 | 22 | } // namespace smp::config 23 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/config/raw_panel_script_source.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | namespace smp::config 10 | { 11 | 12 | struct RawModulePackage 13 | { 14 | qwr::u8string name; 15 | }; 16 | 17 | struct RawSmpPackage 18 | { 19 | qwr::u8string id; 20 | qwr::u8string name; 21 | qwr::u8string author; 22 | }; 23 | 24 | struct RawSampleFile 25 | { 26 | qwr::u8string name; 27 | bool isModule = false; 28 | }; 29 | 30 | struct RawScriptFile 31 | { 32 | std::filesystem::path scriptPath; 33 | bool isModule = false; 34 | }; 35 | 36 | struct RawInMemoryScript 37 | { 38 | qwr::u8string script; 39 | bool isModule = false; 40 | }; 41 | 42 | using RawScriptSourceVariant = std::variant; 43 | 44 | [[nodiscard]] ScriptSourceType GetSourceType( const RawScriptSourceVariant& source ); 45 | 46 | } // namespace smp::config 47 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/config/script_source_types.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace smp::config 4 | { 5 | 6 | enum class ScriptSourceType : uint8_t 7 | { 8 | SmpPackage, 9 | ModulePackage, 10 | Sample, 11 | File, 12 | InMemory 13 | }; 14 | 15 | } // namespace smp::config 16 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/config/serializers/binary.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace smp::config::binary 6 | { 7 | 8 | /// @throw qwr::QwrException 9 | [[nodiscard]] PanelConfig LoadSettings( stream_reader& reader, abort_callback& abort ); 10 | 11 | /// @throw qwr::QwrException 12 | [[nodiscard]] PanelProperties LoadProperties( stream_reader& reader, abort_callback& abort ); 13 | 14 | } // namespace smp::config::binary 15 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/config/serializers/com.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace smp::config::com 6 | { 7 | 8 | /// @throw qwr::QwrException 9 | [[nodiscard]] PanelProperties LoadProperties( stream_reader& reader, abort_callback& abort ); 10 | 11 | } // namespace smp::config::com 12 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/config/serializers/json.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace smp::config::json 6 | { 7 | 8 | /// @throw qwr::QwrException 9 | [[nodiscard]] PanelConfig LoadConfig( stream_reader& reader, abort_callback& abort ); 10 | 11 | /// @throw qwr::QwrException 12 | void SaveConfig( stream_writer& writer, abort_callback& abort, const PanelConfig& settings ); 13 | 14 | /// @throw qwr::QwrException 15 | [[nodiscard]] PanelProperties LoadProperties( stream_reader& reader, abort_callback& abort ); 16 | 17 | /// @throw qwr::QwrException 18 | void SaveProperties( stream_writer& writer, abort_callback& abort, const PanelProperties& properties ); 19 | 20 | /// @throw qwr::QwrException 21 | [[nodiscard]] PanelProperties DeserializeProperties( const qwr::u8string& str ); 22 | 23 | /// @throw qwr::QwrException 24 | [[nodiscard]] qwr::u8string SerializeProperties( const PanelProperties& properties ); 25 | 26 | } // namespace smp::config::json 27 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/config/smp_package/delayed_package_actions.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace smp::config 4 | { 5 | 6 | enum class PackageDelayStatus 7 | { 8 | ToBeRemoved, 9 | ToBeUpdated, 10 | NotDelayed 11 | }; 12 | 13 | /// @throw qwr::QwrException 14 | [[nodiscard]] bool IsPackageInUse( const qwr::u8string& packageId ); 15 | 16 | /// @throw qwr::QwrException 17 | [[nodiscard]] PackageDelayStatus GetPackageDelayStatus( const qwr::u8string& packageId ); 18 | 19 | /// @throw qwr::QwrException 20 | void ClearPackageDelayStatus( const qwr::u8string& packageId ); 21 | 22 | /// @throw qwr::QwrException 23 | void MarkPackageAsToBeRemoved( const qwr::u8string& packageId ); 24 | 25 | /// @throw qwr::QwrException 26 | void MarkPackageAsToBeInstalled( const qwr::u8string& packageId, const std::filesystem::path& packageContent ); 27 | 28 | /// @throw qwr::QwrException 29 | void MarkPackageAsInUse( const qwr::u8string& packageId ); 30 | 31 | /// @throw qwr::QwrException 32 | void ProcessDelayedPackages(); 33 | 34 | } // namespace smp::config 35 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/config/smp_package/package.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace smp::config 6 | { 7 | 8 | struct SmpPackage 9 | { 10 | qwr::u8string id; 11 | qwr::u8string name; 12 | qwr::u8string author; 13 | qwr::u8string version; 14 | qwr::u8string description; 15 | bool enableDragDrop = false; 16 | bool shouldGrabFocus = true; 17 | 18 | // convenience 19 | std::filesystem::path entryFile; 20 | std::filesystem::path packageDir; 21 | 22 | [[nodiscard]] std::filesystem::path GetScriptsDir() const; 23 | [[nodiscard]] std::filesystem::path GetAssetsDir() const; 24 | [[nodiscard]] std::filesystem::path GetStorageDir() const; 25 | 26 | /// @remark Result is sorted 27 | /// @throw qwr::QwrException 28 | [[nodiscard]] std::vector GetScriptFiles() const; 29 | 30 | /// @remark Result is sorted 31 | /// @throw qwr::QwrException 32 | [[nodiscard]] std::vector GetAllFiles() const; 33 | 34 | /// @throw qwr::QwrException 35 | void ValidatePackagePath() const; 36 | 37 | /// @throw qwr::QwrException 38 | void ToFile( const std::filesystem::path& packageJson ) const; 39 | 40 | /// @throw qwr::QwrException 41 | [[nodiscard]] static SmpPackage FromFile( const std::filesystem::path& packageJson ); 42 | 43 | /// @throw qwr::QwrException 44 | [[nodiscard]] static SmpPackage GenerateNewPackage( const qwr::u8string& name ); 45 | }; 46 | 47 | } // namespace smp::config 48 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/config/smp_package/package_manager.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | namespace smp::config 8 | { 9 | 10 | class SmpPackageManager 11 | { 12 | public: 13 | [[nodiscard]] SmpPackageManager() = default; 14 | 15 | /// @throw qwr::QwrException 16 | [[nodiscard]] const std::unordered_map& 17 | GetPackages( const std::optional& parentDir = std::nullopt ) const; 18 | 19 | /// @throw qwr::QwrException 20 | [[nodiscard]] std::optional 21 | GetPackage( const qwr::u8string& id ) const; 22 | 23 | void Refresh() const; 24 | 25 | public: 26 | [[nodiscard]] static std::filesystem::path GetPathForNewPackage( const qwr::u8string& id ); 27 | 28 | private: 29 | static std::unordered_map idToPackageJson_; 30 | }; 31 | 32 | } // namespace smp::config 33 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/convert/com.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | namespace mozjs::convert::com 4 | { 5 | 6 | void VariantToJs( JSContext* cx, VARIANTARG& var, JS::MutableHandleValue rval ); 7 | // assumes that variant arg is uninitialized 8 | void JsToVariant( JSContext* cx, JS::HandleValue rval, VARIANTARG& arg ); 9 | 10 | // assumes that obj is an array 11 | void JsArrayToVariantArray( JSContext* cx, JS::HandleObject obj, int elementVariantType, VARIANT& var ); 12 | 13 | } // namespace mozjs::convert::com 14 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/events/event.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "event.h" 4 | 5 | #include 6 | 7 | namespace smp 8 | { 9 | 10 | EventBase::EventBase( EventId id ) 11 | : id_( id ) 12 | { 13 | } 14 | 15 | std::unique_ptr EventBase::Clone() 16 | { 17 | return nullptr; 18 | } 19 | 20 | void EventBase::SetTarget( std::shared_ptr pTarget ) 21 | { 22 | pTarget_ = pTarget; 23 | } 24 | 25 | EventId EventBase::GetId() const 26 | { 27 | return id_; 28 | } 29 | 30 | const qwr::u8string& EventBase::GetType() const 31 | { 32 | // TODO: map id to string 33 | static qwr::u8string tmp; 34 | return tmp; 35 | } 36 | 37 | Event_Mouse* EventBase::AsMouseEvent() 38 | { 39 | return nullptr; 40 | } 41 | 42 | Event_Drag* EventBase::AsDragEvent() 43 | { 44 | return nullptr; 45 | } 46 | 47 | PanelTarget::PanelTarget( panel::PanelWindow& panel ) 48 | : pPanel_( &panel ) 49 | , hWnd_( panel.GetHWND() ) 50 | { 51 | } 52 | 53 | HWND PanelTarget::GetHwnd() 54 | { 55 | return hWnd_; 56 | } 57 | 58 | panel::PanelWindow* PanelTarget::GetPanel() 59 | { 60 | assert( core_api::is_main_thread() ); 61 | return pPanel_; 62 | } 63 | 64 | void PanelTarget::UnlinkPanel() 65 | { 66 | pPanel_ = nullptr; 67 | hWnd_ = nullptr; 68 | } 69 | 70 | } // namespace smp 71 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/events/event_basic.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "event_basic.h" 4 | 5 | #include 6 | 7 | namespace smp 8 | { 9 | 10 | Event_Basic::Event_Basic( EventId id ) 11 | : EventBase( id ) 12 | { 13 | } 14 | 15 | void Event_Basic::Run() 16 | { 17 | if ( !pTarget_ ) 18 | { 19 | return; 20 | } 21 | 22 | auto pPanel = pTarget_->GetPanel(); 23 | if ( !pPanel ) 24 | { 25 | return; 26 | } 27 | 28 | pPanel->ExecuteEvent_Basic( id_ ); 29 | } 30 | 31 | } // namespace smp 32 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/events/event_basic.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace smp 6 | { 7 | 8 | class Event_Basic : public EventBase 9 | { 10 | public: 11 | Event_Basic( EventId id ); 12 | 13 | void Run() override; 14 | }; 15 | 16 | } // namespace smp 17 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/events/event_drag.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | namespace mozjs 8 | { 9 | 10 | class JsContainer; 11 | 12 | } // namespace mozjs 13 | 14 | namespace smp::com 15 | { 16 | 17 | struct StorageObject; 18 | 19 | } 20 | 21 | namespace smp 22 | { 23 | 24 | class js_panel_window; 25 | 26 | class Event_Drag 27 | : public Event_Mouse 28 | { 29 | public: 30 | /// @remark Should be called only from the main thread 31 | Event_Drag( EventId id, int32_t x, int32_t y, uint32_t mask, uint32_t modifiers, const panel::DragActionParams& dragParams, IDataObjectPtr pData ); 32 | ~Event_Drag() override; 33 | 34 | [[nodiscard]] Event_Drag* AsDragEvent() override; 35 | 36 | std::optional JsExecute( mozjs::JsContainer& jsContainer ) override; 37 | 38 | [[nodiscard]] const panel::DragActionParams& GetDragParams() const; 39 | [[nodiscard]] IDataObjectPtr GetStoredData() const; 40 | 41 | /// @remark Should be called only from the main thread 42 | void DisposeStoredData(); 43 | 44 | private: 45 | const panel::DragActionParams dragParams_; 46 | IDataObjectPtr pDataObject_; 47 | com::StorageObject* pStorage_; 48 | }; 49 | 50 | } // namespace smp 51 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/events/event_js_executor.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "event_js_executor.h" 4 | 5 | #include 6 | 7 | namespace smp 8 | { 9 | 10 | Event_JsExecutor::Event_JsExecutor( EventId id ) 11 | : EventBase( id ) 12 | { 13 | } 14 | 15 | void Event_JsExecutor::Run() 16 | { 17 | if ( !pTarget_ ) 18 | { 19 | return; 20 | } 21 | 22 | auto pPanel = pTarget_->GetPanel(); 23 | if ( !pPanel ) 24 | { 25 | return; 26 | } 27 | 28 | pPanel->ExecuteEvent_JsTask( id_, *this ); 29 | } 30 | 31 | } // namespace smp 32 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/events/event_js_executor.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace mozjs 6 | { 7 | 8 | class JsContainer; 9 | 10 | } 11 | 12 | namespace smp 13 | { 14 | 15 | class Event_JsExecutor : public EventBase 16 | { 17 | public: 18 | Event_JsExecutor( EventId id ); 19 | ~Event_JsExecutor() override = default; 20 | 21 | void Run() final; 22 | virtual std::optional JsExecute( mozjs::JsContainer& jsContainer ) = 0; 23 | }; 24 | 25 | } // namespace smp 26 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/events/event_js_task.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "event_js_task.h" 4 | 5 | #include 6 | #include 7 | 8 | namespace smp 9 | { 10 | 11 | Event_JsTask::Event_JsTask( EventId id, std::shared_ptr pTask ) 12 | : Event_JsExecutor( id ) 13 | , pTask_( pTask ) 14 | { 15 | assert( pTask_ ); 16 | } 17 | 18 | std::optional Event_JsTask::JsExecute( mozjs::JsContainer& jsContainer ) 19 | { 20 | jsContainer.InvokeJsAsyncTask( *pTask_ ); 21 | return std::nullopt; 22 | } 23 | 24 | } // namespace smp 25 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/events/event_js_task.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | namespace mozjs 7 | { 8 | 9 | class JsAsyncTask; 10 | class JsContainer; 11 | 12 | } // namespace mozjs 13 | 14 | namespace smp 15 | { 16 | 17 | class js_panel_window; 18 | 19 | class Event_JsTask 20 | : public Event_JsExecutor 21 | { 22 | public: 23 | Event_JsTask( EventId id, std::shared_ptr pTask ); 24 | 25 | std::optional JsExecute( mozjs::JsContainer& jsContainer ) override; 26 | 27 | private: 28 | std::shared_ptr pTask_; 29 | }; 30 | 31 | } // namespace smp 32 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/events/event_mouse.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "event_mouse.h" 4 | 5 | #include 6 | #include 7 | 8 | namespace smp 9 | { 10 | 11 | Event_Mouse::Event_Mouse( EventId id, int32_t x, int32_t y, uint32_t mask, uint32_t modifiers ) 12 | : Event_JsExecutor( id ) 13 | , x_( x ) 14 | , y_( y ) 15 | , mask_( mask ) 16 | , modifiers_( modifiers ) 17 | { 18 | assert( kCallbackIdToName.contains( id_ ) ); 19 | } 20 | 21 | std::optional Event_Mouse::JsExecute( mozjs::JsContainer& jsContainer ) 22 | { 23 | const auto callbackName = fmt::format( "on_{}", kCallbackIdToName.at( id_ ) ); 24 | return jsContainer.InvokeJsCallback( callbackName, x_, y_, mask_ ); 25 | } 26 | 27 | Event_Mouse* Event_Mouse::AsMouseEvent() 28 | { 29 | return this; 30 | } 31 | 32 | int32_t Event_Mouse::GetX() const 33 | { 34 | return x_; 35 | } 36 | 37 | int32_t Event_Mouse::GetY() const 38 | { 39 | return y_; 40 | } 41 | 42 | uint32_t Event_Mouse::GetMask() const 43 | { 44 | return mask_; 45 | } 46 | 47 | uint32_t Event_Mouse::GetModifiers() const 48 | { 49 | return modifiers_; 50 | } 51 | 52 | bool Event_Mouse::IsAltPressed() const 53 | { 54 | return ( modifiers_ & MOD_ALT ); 55 | } 56 | 57 | bool Event_Mouse::IsCtrlPressed() const 58 | { 59 | return ( modifiers_ & MOD_CONTROL ); 60 | } 61 | 62 | bool Event_Mouse::IsShiftPressed() const 63 | { 64 | return ( modifiers_ & MOD_SHIFT ); 65 | } 66 | 67 | bool Event_Mouse::IsWinPressed() const 68 | { 69 | return ( modifiers_ & MOD_WIN ); 70 | } 71 | 72 | } // namespace smp 73 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/events/event_mouse.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | namespace smp 7 | { 8 | 9 | class js_panel_window; 10 | 11 | class Event_Mouse 12 | : public Event_JsExecutor 13 | { 14 | public: 15 | Event_Mouse( EventId id, int32_t x, int32_t y, uint32_t mask, uint32_t modifiers ); 16 | 17 | [[nodiscard]] Event_Mouse* AsMouseEvent() override; 18 | 19 | std::optional JsExecute( mozjs::JsContainer& jsContainer ) override; 20 | 21 | [[nodiscard]] int32_t GetX() const; 22 | [[nodiscard]] int32_t GetY() const; 23 | [[nodiscard]] uint32_t GetMask() const; 24 | [[nodiscard]] uint32_t GetModifiers() const; 25 | [[nodiscard]] bool IsAltPressed() const; 26 | [[nodiscard]] bool IsCtrlPressed() const; 27 | [[nodiscard]] bool IsShiftPressed() const; 28 | [[nodiscard]] bool IsWinPressed() const; 29 | 30 | private: 31 | const int32_t x_; 32 | const int32_t y_; 33 | const uint32_t mask_; 34 | const uint32_t modifiers_; 35 | }; 36 | 37 | } // namespace smp 38 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/events/event_notify_others.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "event_notify_others.h" 4 | 5 | #include 6 | #include 7 | 8 | namespace smp 9 | { 10 | 11 | Event_NotifyOthers::Event_NotifyOthers( JSContext* cx, const std::wstring& name, JS::HandleValue info ) 12 | : Event_JsExecutor( EventId::kNotifyOthers ) 13 | , pJsCtx_( cx ) 14 | , heapHelper_( cx ) 15 | , name_( name ) 16 | , jsInfoId_( heapHelper_.Store( info ) ) 17 | { 18 | } 19 | 20 | Event_NotifyOthers::~Event_NotifyOthers() 21 | { 22 | heapHelper_.Finalize(); 23 | } 24 | 25 | std::unique_ptr Event_NotifyOthers::Clone() 26 | { 27 | // Note: this clone operation might result in JS object being used in another panel/global 28 | assert( heapHelper_.IsJsAvailable() ); 29 | 30 | JS::RootedValue jsValue( pJsCtx_, heapHelper_.Get( jsInfoId_ ) ); 31 | return std::make_unique( pJsCtx_, name_, jsValue ); 32 | } 33 | 34 | std::optional Event_NotifyOthers::JsExecute( mozjs::JsContainer& jsContainer ) 35 | { 36 | if ( !heapHelper_.IsJsAvailable() ) 37 | { // This might happen if the original panel/global died 38 | return std::nullopt; 39 | } 40 | 41 | JS::RootedValue jsValue( pJsCtx_, heapHelper_.Get( jsInfoId_ ) ); 42 | jsContainer.InvokeOnNotify( name_, jsValue ); 43 | 44 | return std::nullopt; 45 | } 46 | 47 | } // namespace smp 48 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/events/event_notify_others.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | namespace smp 8 | { 9 | 10 | class Event_NotifyOthers final 11 | : public Event_JsExecutor 12 | { 13 | public: 14 | Event_NotifyOthers( JSContext* cx, const std::wstring& name, JS::HandleValue info ); 15 | ~Event_NotifyOthers() override; 16 | 17 | std::unique_ptr Clone() override; 18 | 19 | std::optional JsExecute( mozjs::JsContainer& jsContainer ) override; 20 | 21 | private: 22 | JSContext* pJsCtx_ = nullptr; 23 | 24 | mozjs::HeapHelper heapHelper_; 25 | 26 | const std::wstring name_; 27 | const uint32_t jsInfoId_; 28 | }; 29 | 30 | } // namespace smp 31 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/events/event_timer.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "event_timer.h" 4 | 5 | #include 6 | 7 | namespace smp 8 | { 9 | 10 | Event_Timer::Event_Timer( std::shared_ptr pTimer, uint64_t generation ) 11 | : EventBase( EventId::kTimer ) 12 | , pTimer_( pTimer ) 13 | , generation_( generation ) 14 | { 15 | assert( pTimer_ ); 16 | } 17 | 18 | void Event_Timer::Run() 19 | { 20 | pTimer_->Fire( generation_ ); 21 | } 22 | 23 | } // namespace smp 24 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/events/event_timer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include 7 | 8 | namespace smp 9 | { 10 | 11 | class Event_Timer 12 | : public EventBase 13 | { 14 | public: 15 | Event_Timer( std::shared_ptr pTimer, uint64_t generation ); 16 | 17 | void Run() override; 18 | 19 | private: 20 | std::shared_ptr pTimer_; 21 | uint64_t generation_; 22 | }; 23 | 24 | } // namespace smp 25 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/fb2k/acfu_integration.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | #include 6 | 7 | using namespace smp; 8 | 9 | namespace 10 | { 11 | 12 | class SmpSource 13 | : public qwr::acfu::QwrSource 14 | { 15 | public: 16 | // ::acfu::source 17 | [[nodiscard]] GUID get_guid() override; 18 | ::acfu::request::ptr create_request() override; 19 | 20 | // qwr::acfu::github_conf 21 | [[nodiscard]] static pfc::string8 get_owner(); 22 | [[nodiscard]] static pfc::string8 get_repo(); 23 | 24 | // qwr::acfu::QwrSource 25 | [[nodiscard]] std::string GetComponentName() const override; 26 | [[nodiscard]] std::string GetComponentFilename() const override; 27 | }; 28 | 29 | } // namespace 30 | 31 | namespace 32 | { 33 | 34 | GUID SmpSource::get_guid() 35 | { 36 | return guid::acfu_source; 37 | } 38 | 39 | ::acfu::request::ptr SmpSource::create_request() 40 | { 41 | return fb2k::service_new>(); 42 | } 43 | 44 | pfc::string8 SmpSource::get_owner() 45 | { 46 | return "TheQwertiest"; 47 | } 48 | 49 | pfc::string8 SmpSource::get_repo() 50 | { 51 | return SMP_UNDERSCORE_NAME; 52 | } 53 | 54 | std::string SmpSource::GetComponentName() const 55 | { 56 | return SMP_NAME; 57 | } 58 | 59 | std::string SmpSource::GetComponentFilename() const 60 | { 61 | return SMP_UNDERSCORE_NAME; 62 | } 63 | 64 | FB2K_SERVICE_FACTORY( SmpSource ); 65 | 66 | } // namespace 67 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/fb2k/advanced_config.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace smp::config::advanced 6 | { 7 | 8 | extern qwr::fb2k::AdvConfigUint32_MT gc_budget; 9 | extern qwr::fb2k::AdvConfigUint32_MT gc_delay; 10 | extern qwr::fb2k::AdvConfigUint32_MT gc_max_alloc_increase; 11 | extern qwr::fb2k::AdvConfigUint32_MT gc_max_heap; 12 | extern qwr::fb2k::AdvConfigUint32_MT gc_max_heap_growth; 13 | 14 | extern qwr::fb2k::AdvConfigUint32_MT performance_max_runtime; 15 | 16 | extern qwr::fb2k::AdvConfigBool_MT debug_log_extended_include_error; 17 | extern qwr::fb2k::AdvConfigBool_MT debug_use_custom_timer_engine; 18 | 19 | #ifdef SMP_ENABLE_CXX_STACKTRACE 20 | extern qwr::fb2k::AdvConfigBool_MT stacktrace; 21 | extern qwr::fb2k::AdvConfigUint32_MT stacktrace_max_depth; 22 | extern qwr::fb2k::AdvConfigUint32_MT stacktrace_max_recursion; 23 | #endif 24 | 25 | #ifdef _DEBUG 26 | extern qwr::fb2k::AdvConfigBool_MT zeal; 27 | extern qwr::fb2k::AdvConfigUint32_MT zeal_freq; 28 | extern qwr::fb2k::AdvConfigUint8_MT zeal_level; 29 | #endif 30 | 31 | } // namespace smp::config::advanced 32 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/fb2k/config.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "config.h" 4 | 5 | namespace smp::config 6 | { 7 | 8 | qwr::fb2k::ConfigString_MT default_editor( guid::default_editor, "" ); 9 | 10 | } // namespace smp::config 11 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/fb2k/config.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace smp::config 6 | { 7 | 8 | extern qwr::fb2k::ConfigString_MT default_editor; 9 | 10 | } // namespace smp::config 11 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/fb2k/mainmenu_dynamic.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | namespace smp 7 | { 8 | 9 | class DynamicMainMenuManager 10 | { 11 | public: 12 | struct CommandData 13 | { 14 | qwr::u8string name; 15 | std::optional description; 16 | }; 17 | 18 | struct PanelData 19 | { 20 | qwr::u8string name; 21 | std::unordered_map commands; 22 | }; 23 | 24 | public: 25 | static [[nodiscard]] DynamicMainMenuManager& Get(); 26 | 27 | void RegisterPanel( HWND hWnd, const qwr::u8string& panelName ); 28 | void UnregisterPanel( HWND hWnd ); 29 | 30 | /// @throw qwr::QwrException 31 | void RegisterCommand( HWND hWnd, uint32_t id, const qwr::u8string& name, const std::optional& description ); 32 | /// @throw qwr::QwrException 33 | void UnregisterCommand( HWND hWnd, uint32_t id ); 34 | 35 | const std::unordered_map& GetAllCommandData() const; 36 | 37 | private: 38 | DynamicMainMenuManager() = default; 39 | 40 | private: 41 | std::unordered_map panels_; 42 | }; 43 | 44 | } // namespace smp 45 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/fb2k/playlist_lock.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace smp 6 | { 7 | 8 | class PlaylistLockManager 9 | { 10 | public: 11 | static [[nodiscard]] PlaylistLockManager& Get(); 12 | 13 | /// @throw qwr::QwrException 14 | void InitializeLocks(); 15 | 16 | /// @throw qwr::QwrException 17 | void InstallLock( size_t playlistIndex, uint32_t flags ); 18 | 19 | /// @throw qwr::QwrException 20 | void RemoveLock( size_t playlistIndex ); 21 | 22 | [[nodiscard]] bool HasLock( size_t playlistIndex ); 23 | 24 | private: 25 | PlaylistLockManager() = default; 26 | 27 | private: 28 | std::unordered_map knownLocks_; 29 | }; 30 | 31 | } // namespace smp 32 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/fb2k/selection_holder_helper.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "selection_holder_helper.h" 4 | 5 | namespace 6 | { 7 | 8 | const auto guids = std::to_array( { &contextmenu_item::caller_undefined, 9 | &contextmenu_item::caller_active_playlist_selection, 10 | &contextmenu_item::caller_active_playlist, 11 | &contextmenu_item::caller_playlist_manager, 12 | &contextmenu_item::caller_now_playing, 13 | &contextmenu_item::caller_keyboard_shortcut_list, 14 | &contextmenu_item::caller_media_library_viewer } ); 15 | 16 | } 17 | 18 | namespace smp 19 | { 20 | 21 | std::optional GetSelectionHolderGuidFromType( uint8_t typeId ) 22 | { 23 | if ( typeId >= guids.size() ) 24 | { 25 | return std::nullopt; 26 | } 27 | 28 | return *guids[typeId]; 29 | } 30 | 31 | std::optional GetSelectionHolderTypeFromGuid( const GUID& typeGuid ) 32 | { 33 | const auto it = ranges::find_if( guids, [&typeGuid]( const auto pGuid ) { return typeGuid == *pGuid; } ); 34 | if ( ranges::end( guids ) == it ) 35 | { 36 | return std::nullopt; 37 | } 38 | 39 | return ranges::distance( ranges::begin( guids ), it ); 40 | } 41 | 42 | } // namespace smp 43 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/fb2k/selection_holder_helper.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace smp 6 | { 7 | 8 | std::optional GetSelectionHolderGuidFromType( uint8_t typeId ); 9 | std::optional GetSelectionHolderTypeFromGuid( const GUID& typeGuid ); 10 | 11 | } // namespace smp 12 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/fb2k/stats.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace smp::stats 4 | { 5 | 6 | struct Fields 7 | { 8 | uint32_t playcount = 0; 9 | uint32_t loved = 0; 10 | qwr::u8string first_played; 11 | qwr::u8string last_played; 12 | uint32_t rating = 0; 13 | }; 14 | 15 | [[nodiscard]] bool HashHandle( metadb_handle_ptr const& pMetadb, metadb_index_hash& hash ); 16 | [[nodiscard]] Fields GetStats( metadb_index_hash hash ); 17 | void SetStats( metadb_index_hash hash, const Fields& f ); 18 | void RefreshStats( const pfc::list_base_const_t& hashes ); 19 | void RefreshStats( const metadb_index_hash& hash ); 20 | 21 | } // namespace smp::stats 22 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/js_backend/engine/heartbeat_window.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace smp 4 | { 5 | 6 | class HeartbeatWindow 7 | { 8 | public: 9 | ~HeartbeatWindow(); 10 | HeartbeatWindow( HeartbeatWindow& ) = delete; 11 | HeartbeatWindow& operator=( HeartbeatWindow& ) = delete; 12 | 13 | /// @throw qwr::QwrException 14 | static [[nodiscard]] std::unique_ptr Create(); 15 | 16 | [[nodiscard]] HWND GetHwnd() const; 17 | 18 | private: 19 | HeartbeatWindow( HWND hWnd ); 20 | 21 | static LRESULT CALLBACK WndProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam ); 22 | 23 | private: 24 | HWND hWnd_ = nullptr; 25 | }; 26 | 27 | } // namespace smp 28 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/js_backend/engine/js_realm_inner.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace mozjs 6 | { 7 | 8 | class JsRealmInner final 9 | { 10 | public: 11 | JsRealmInner() = default; 12 | ~JsRealmInner() = default; 13 | JsRealmInner( const JsRealmInner& ) = delete; 14 | JsRealmInner& operator=( const JsRealmInner& ) = delete; 15 | 16 | public: 17 | void MarkForDeletion(); 18 | [[nodiscard]] bool IsMarkedForDeletion() const; 19 | 20 | void OnGcStart(); 21 | void OnGcDone(); 22 | [[nodiscard]] bool IsMarkedForGc() const; 23 | 24 | [[nodiscard]] uint64_t GetCurrentHeapBytes() const; 25 | [[nodiscard]] uint64_t GetLastHeapBytes() const; 26 | 27 | [[nodiscard]] uint32_t GetCurrentAllocCount() const; 28 | [[nodiscard]] uint32_t GetLastAllocCount() const; 29 | 30 | void OnHeapAllocate( uint32_t size ); 31 | void OnHeapDeallocate( uint32_t size ); 32 | 33 | private: 34 | bool isMarkedForDeletion_ = false; 35 | bool isMarkedForGc_ = false; 36 | mutable std::mutex gcDataLock_; 37 | uint64_t curHeapSize_ = 0; 38 | uint64_t lastHeapSize_ = 0; 39 | uint32_t curAllocCount_ = 0; 40 | uint32_t lastAllocCount_ = 0; 41 | }; 42 | 43 | } // namespace mozjs 44 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/js_backend/engine/js_script_cache.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | namespace js::frontend 12 | { 13 | struct CompilationStencil; 14 | }; 15 | 16 | namespace JS 17 | { 18 | using Stencil = js::frontend::CompilationStencil; 19 | } 20 | 21 | namespace mozjs 22 | { 23 | 24 | class JsScriptCache 25 | { 26 | public: 27 | JsScriptCache(); 28 | ~JsScriptCache(); 29 | 30 | /// @throw qwr::QwrException 31 | /// @throw smp::JsException 32 | [[nodiscard]] RefPtr GetCachedStencil( JSContext* pJsCtx, const std::filesystem::path& absolutePath, const JS::CompileOptions& compileOpts, bool isModule ); 33 | 34 | private: 35 | struct CachedStencil 36 | { 37 | RefPtr stencil; 38 | std::filesystem::file_time_type writeTime; 39 | }; 40 | 41 | std::unordered_map scriptCache_; 42 | std::unordered_map moduleCache_; 43 | }; 44 | 45 | } // namespace mozjs 46 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/js_backend/engine/native_to_js_invoker.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "native_to_js_invoker.h" 4 | 5 | #include 6 | 7 | namespace mozjs::internal 8 | { 9 | bool InvokeJsCallback_Impl( JSContext* cx, 10 | JS::HandleObject globalObject, 11 | JS::HandleValue functionValue, 12 | const JS::HandleValueArray& args, 13 | JS::MutableHandleValue rval ) 14 | { 15 | JS::RootedFunction func( cx, JS_ValueToFunction( cx, functionValue ) ); 16 | if ( !func ) 17 | { // Reports 18 | return false; 19 | } 20 | 21 | return JS::Call( cx, globalObject, func, args, rval ); // reports 22 | } 23 | 24 | } // namespace mozjs::internal 25 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/js_backend/objects/core/object_traits.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace mozjs::traits 4 | { 5 | 6 | template 7 | concept HasPostCreate = T::HasPostCreate || false; 8 | 9 | template 10 | concept HasProxy = T::HasProxy || false; 11 | 12 | template 13 | concept HasParentProto = T::HasParentProto || false; 14 | 15 | template 16 | concept IsExtendable = T::IsExtendable || false; 17 | 18 | template 19 | concept HasJsFunctionsMember = requires( T t ) 20 | { 21 | { 22 | t.JsFunctions 23 | } 24 | -> std::same_as; 25 | }; 26 | 27 | template 28 | concept HasJsFunctions = HasJsFunctionsMember || false; 29 | 30 | template 31 | concept HasJsStaticFunctionsMember = requires( T t ) 32 | { 33 | { 34 | t.JsStaticFunctions 35 | } 36 | -> std::same_as; 37 | }; 38 | 39 | template 40 | concept HasJsStaticFunctions = HasJsStaticFunctionsMember || false; 41 | 42 | template 43 | concept HasJsPropertiesMember = requires( T t ) 44 | { 45 | { 46 | t.JsProperties 47 | } 48 | -> std::same_as; 49 | }; 50 | 51 | template 52 | concept HasJsProperties = HasJsPropertiesMember || false; 53 | 54 | } // namespace mozjs::traits 55 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/js_backend/objects/core/prototype_ids.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace mozjs 6 | { 7 | 8 | enum class JsPrototypeId : uint32_t 9 | { 10 | ActiveX, 11 | ActiveX_Iterator, 12 | ContextMenuManager, 13 | DropSourceAction, 14 | Enumerator, 15 | Event, 16 | EventTarget, 17 | FbFileInfo, 18 | FbMetadbHandle, 19 | FbMetadbHandleList, 20 | FbMetadbHandleList_Iterator, 21 | FbPlaybackQueueItem, 22 | FbPlayingItemLocation, 23 | FbProfiler, 24 | FbTitleFormat, 25 | FbTooltip, 26 | FbUiSelectionHolder, 27 | GdiBitmap, 28 | GdiFont, 29 | GdiGraphics, 30 | GdiRawBitmap, 31 | HtmlWindow, 32 | MainMenuManager, 33 | MeasureStringInfo, 34 | MenuObject, 35 | ThemeManager, 36 | ProrototypeCount 37 | }; 38 | 39 | } 40 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/js_backend/objects/dom/console.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace mozjs 4 | { 5 | 6 | void DefineConsole( JSContext* cx, JS::HandleObject global ); 7 | 8 | } 9 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/js_backend/objects/dom/context_menu_manager.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include 6 | 7 | class JSObject; 8 | struct JSContext; 9 | struct JSClass; 10 | 11 | namespace mozjs 12 | { 13 | 14 | class JsMenuObject; 15 | class JsFbMetadbHandleList; 16 | 17 | class JsContextMenuManager 18 | : public JsObjectBase 19 | { 20 | public: 21 | static constexpr bool HasProto = true; 22 | static constexpr bool HasGlobalProto = false; 23 | 24 | static const JSClass JsClass; 25 | static const JSFunctionSpec* JsFunctions; 26 | static const JSPropertySpec* JsProperties; 27 | static const JsPrototypeId PrototypeId; 28 | 29 | public: 30 | ~JsContextMenuManager() override = default; 31 | 32 | static std::unique_ptr CreateNative( JSContext* cx ); 33 | [[nodiscard]] size_t GetInternalSize(); 34 | 35 | public: 36 | void BuildMenu( JsMenuObject* menuObject, int32_t base_id, int32_t max_id = -1 ); 37 | void BuildMenuWithOpt( size_t optArgCount, JsMenuObject* menuObject, int32_t base_id, int32_t max_id ); 38 | bool ExecuteByID( uint32_t id ); 39 | void InitContext( JsFbMetadbHandleList* handles ); 40 | void InitContextPlaylist(); 41 | void InitNowPlaying(); 42 | 43 | private: 44 | JsContextMenuManager( JSContext* cx ); 45 | 46 | private: 47 | [[maybe_unused]] JSContext* pJsCtx_ = nullptr; 48 | contextmenu_manager::ptr contextMenu_; 49 | }; 50 | 51 | } // namespace mozjs 52 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/js_backend/objects/dom/drop_source_action.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include 7 | 8 | class JSObject; 9 | struct JSContext; 10 | struct JSClass; 11 | 12 | namespace mozjs 13 | { 14 | 15 | class JsDropSourceAction 16 | : public JsObjectBase 17 | { 18 | public: 19 | static constexpr bool HasProto = true; 20 | static constexpr bool HasGlobalProto = false; 21 | 22 | static const JSClass JsClass; 23 | static const JSFunctionSpec* JsFunctions; 24 | static const JSPropertySpec* JsProperties; 25 | static const JsPrototypeId PrototypeId; 26 | 27 | public: 28 | ~JsDropSourceAction() override = default; 29 | 30 | static std::unique_ptr CreateNative( JSContext* cx ); 31 | [[nodiscard]] size_t GetInternalSize(); 32 | 33 | public: 34 | smp::panel::DragActionParams& AccessDropActionParams(); 35 | 36 | public: 37 | uint32_t get_Effect() const; 38 | void put_Base( uint32_t base ); 39 | void put_Effect( uint32_t effect ); 40 | void put_Playlist( int32_t id ); 41 | void put_Text( const std::wstring& text ); 42 | void put_ToSelect( bool toSelect ); 43 | bool get_IsInternal() const; 44 | 45 | private: 46 | JsDropSourceAction( JSContext* cx ); 47 | 48 | private: 49 | [[maybe_unused]] JSContext* pJsCtx_ = nullptr; 50 | 51 | smp::panel::DragActionParams actionParams_; 52 | }; 53 | 54 | } // namespace mozjs 55 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/js_backend/objects/dom/main_menu_manager.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include 6 | #include 7 | 8 | class JSObject; 9 | struct JSContext; 10 | struct JSClass; 11 | 12 | namespace mozjs 13 | { 14 | 15 | class JsMenuObject; 16 | 17 | class JsMainMenuManager 18 | : public JsObjectBase 19 | { 20 | public: 21 | static constexpr bool HasProto = true; 22 | static constexpr bool HasGlobalProto = false; 23 | 24 | static const JSClass JsClass; 25 | static const JSFunctionSpec* JsFunctions; 26 | static const JSPropertySpec* JsProperties; 27 | static const JsPrototypeId PrototypeId; 28 | 29 | public: 30 | ~JsMainMenuManager() override = default; 31 | 32 | static std::unique_ptr CreateNative( JSContext* cx ); 33 | [[nodiscard]] size_t GetInternalSize(); 34 | 35 | public: 36 | void BuildMenu( JsMenuObject* menu, int32_t base_id, int32_t count ); 37 | bool ExecuteByID( uint32_t id ); 38 | void Init( const qwr::u8string& root_name ); 39 | 40 | private: 41 | JsMainMenuManager( JSContext* cx ); 42 | 43 | private: 44 | [[maybe_unused]] JSContext* pJsCtx_ = nullptr; 45 | mainmenu_manager::ptr menuManager_; 46 | }; 47 | 48 | } // namespace mozjs 49 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/js_backend/objects/fb2k/fb_file_info.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include 6 | 7 | class JSObject; 8 | struct JSContext; 9 | struct JSClass; 10 | 11 | namespace mozjs 12 | { 13 | 14 | class JsFbFileInfo 15 | : public JsObjectBase 16 | { 17 | public: 18 | static constexpr bool HasProto = true; 19 | static constexpr bool HasGlobalProto = false; 20 | 21 | static const JSClass JsClass; 22 | static const JSFunctionSpec* JsFunctions; 23 | static const JSPropertySpec* JsProperties; 24 | static const JsPrototypeId PrototypeId; 25 | 26 | public: 27 | ~JsFbFileInfo() override = default; 28 | 29 | static std::unique_ptr CreateNative( JSContext* cx, metadb_info_container::ptr containerInfo ); 30 | [[nodiscard]] size_t GetInternalSize(); 31 | 32 | public: 33 | int32_t InfoFind( const qwr::u8string& name ); 34 | qwr::u8string InfoName( uint32_t index ); 35 | qwr::u8string InfoValue( uint32_t index ); 36 | int32_t MetaFind( const qwr::u8string& name ); 37 | qwr::u8string MetaName( uint32_t index ); 38 | qwr::u8string MetaValue( uint32_t index, uint32_t valueIndex ); 39 | uint32_t MetaValueCount( uint32_t index ); 40 | 41 | public: 42 | uint32_t get_InfoCount(); 43 | uint32_t get_MetaCount(); 44 | 45 | private: 46 | JsFbFileInfo( JSContext* cx, metadb_info_container::ptr containerInfo ); 47 | 48 | private: 49 | [[maybe_unused]] JSContext* pJsCtx_ = nullptr; 50 | metadb_info_container::ptr containerInfo_; 51 | const file_info& fileInfo_; 52 | }; 53 | 54 | } // namespace mozjs 55 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/js_backend/objects/fb2k/fb_metadb_handle_list_iterator.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include 7 | #include 8 | 9 | class JSObject; 10 | struct JSContext; 11 | struct JSClass; 12 | struct JSFunctionSpec; 13 | struct JSPropertySpec; 14 | 15 | namespace mozjs 16 | { 17 | 18 | class JsFbMetadbHandleList; 19 | 20 | class JsFbMetadbHandleList_Iterator 21 | : public JsObjectBase 22 | { 23 | public: 24 | static constexpr bool HasProto = true; 25 | static constexpr bool HasGlobalProto = false; 26 | 27 | static const JSClass JsClass; 28 | static const JSFunctionSpec* JsFunctions; 29 | static const JSPropertySpec* JsProperties; 30 | static const JsPrototypeId PrototypeId; 31 | 32 | public: 33 | ~JsFbMetadbHandleList_Iterator() override; 34 | 35 | static std::unique_ptr CreateNative( JSContext* cx, JsFbMetadbHandleList& handleList ); 36 | [[nodiscard]] size_t GetInternalSize(); 37 | 38 | public: 39 | JSObject* Next(); 40 | 41 | private: 42 | JsFbMetadbHandleList_Iterator( JSContext* cx, JsFbMetadbHandleList& handleList ); 43 | 44 | private: 45 | JSContext* pJsCtx_ = nullptr; 46 | JsFbMetadbHandleList& handleList_; 47 | 48 | HeapHelper heapHelper_; 49 | std::optional jsNextId_; 50 | 51 | uint32_t curPosition_ = 0; 52 | }; 53 | 54 | } // namespace mozjs 55 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/js_backend/objects/fb2k/fb_playback_queue_item.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include 6 | 7 | class JSObject; 8 | struct JSContext; 9 | struct JSClass; 10 | 11 | namespace mozjs 12 | { 13 | 14 | class JsFbPlaybackQueueItem 15 | : public JsObjectBase 16 | { 17 | public: 18 | static constexpr bool HasProto = true; 19 | static constexpr bool HasGlobalProto = false; 20 | 21 | static const JSClass JsClass; 22 | static const JSFunctionSpec* JsFunctions; 23 | static const JSPropertySpec* JsProperties; 24 | static const JsPrototypeId PrototypeId; 25 | 26 | public: 27 | ~JsFbPlaybackQueueItem() override = default; 28 | 29 | static std::unique_ptr CreateNative( JSContext* cx, const t_playback_queue_item& playbackQueueItem ); 30 | [[nodiscard]] size_t GetInternalSize(); 31 | 32 | public: 33 | JSObject* get_Handle(); 34 | uint32_t get_PlaylistIndex(); 35 | uint32_t get_PlaylistItemIndex(); 36 | 37 | private: 38 | JsFbPlaybackQueueItem( JSContext* cx, const t_playback_queue_item& playbackQueueItem ); 39 | 40 | private: 41 | JSContext* pJsCtx_ = nullptr; 42 | t_playback_queue_item playbackQueueItem_; 43 | }; 44 | 45 | } // namespace mozjs 46 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/js_backend/objects/fb2k/fb_playing_item_location.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include 6 | 7 | class JSObject; 8 | struct JSContext; 9 | struct JSClass; 10 | 11 | namespace mozjs 12 | { 13 | 14 | class JsFbPlayingItemLocation 15 | : public JsObjectBase 16 | { 17 | public: 18 | static constexpr bool HasProto = true; 19 | static constexpr bool HasGlobalProto = false; 20 | 21 | static const JSClass JsClass; 22 | static const JSFunctionSpec* JsFunctions; 23 | static const JSPropertySpec* JsProperties; 24 | static const JsPrototypeId PrototypeId; 25 | 26 | public: 27 | ~JsFbPlayingItemLocation() override = default; 28 | 29 | static std::unique_ptr CreateNative( JSContext* cx, bool isValid, uint32_t playlistIndex, uint32_t playlistItemIndex ); 30 | [[nodiscard]] size_t GetInternalSize(); 31 | 32 | public: 33 | bool get_IsValid(); 34 | uint32_t get_PlaylistIndex(); 35 | uint32_t get_PlaylistItemIndex(); 36 | 37 | private: 38 | JsFbPlayingItemLocation( JSContext* cx, bool isValid, uint32_t playlistIndex, uint32_t playlistItemIndex ); 39 | 40 | private: 41 | [[maybe_unused]] JSContext* pJsCtx_ = nullptr; 42 | bool isValid_; 43 | uint32_t playlistIndex_; 44 | uint32_t playlistItemIndex_; 45 | }; 46 | 47 | } // namespace mozjs 48 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/js_backend/objects/fb2k/fb_playlist_recycler.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include 6 | #include 7 | 8 | class JSObject; 9 | struct JSContext; 10 | struct JSClass; 11 | 12 | namespace mozjs 13 | { 14 | 15 | class JsFbPlaylistRecycler 16 | : public JsObjectBase 17 | { 18 | public: 19 | static constexpr bool HasProto = false; 20 | 21 | static const JSClass JsClass; 22 | static const JSFunctionSpec* JsFunctions; 23 | static const JSPropertySpec* JsProperties; 24 | 25 | public: 26 | ~JsFbPlaylistRecycler() override = default; 27 | 28 | static std::unique_ptr CreateNative( JSContext* cx ); 29 | [[nodiscard]] size_t GetInternalSize(); 30 | 31 | public: 32 | JSObject* GetContent( uint32_t index ); 33 | pfc::string8_fast GetName( uint32_t index ); 34 | void Purge( JS::HandleValue affectedItems ); 35 | void Restore( uint32_t index ); 36 | 37 | public: 38 | uint32_t get_Count(); 39 | 40 | private: 41 | JsFbPlaylistRecycler( JSContext* cx ); 42 | 43 | private: 44 | JSContext* pJsCtx_ = nullptr; 45 | }; 46 | 47 | } // namespace mozjs 48 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/js_backend/objects/fb2k/fb_profiler.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include 6 | #include 7 | 8 | class JSObject; 9 | struct JSContext; 10 | struct JSClass; 11 | 12 | namespace mozjs 13 | { 14 | 15 | class JsFbProfiler 16 | : public JsObjectBase 17 | { 18 | public: 19 | static constexpr bool HasProto = true; 20 | static constexpr bool HasGlobalProto = true; 21 | 22 | static const JSClass JsClass; 23 | static const JSFunctionSpec* JsFunctions; 24 | static const JSPropertySpec* JsProperties; 25 | static const JsPrototypeId PrototypeId; 26 | static const JSNative JsConstructor; 27 | 28 | public: 29 | ~JsFbProfiler() override = default; 30 | 31 | static std::unique_ptr CreateNative( JSContext* cx, const qwr::u8string& name ); 32 | [[nodiscard]] size_t GetInternalSize(); 33 | 34 | public: // ctor 35 | static JSObject* Constructor( JSContext* cx, const qwr::u8string& name = "" ); 36 | static JSObject* ConstructorWithOpt( JSContext* cx, size_t optArgCount, const qwr::u8string& name ); 37 | 38 | public: 39 | void Print( const qwr::u8string& additionalMsg = "", bool printComponentInfo = true ); 40 | void PrintWithOpt( size_t optArgCount, const qwr::u8string& additionalMsg, bool printComponentInfo ); 41 | void Reset(); 42 | 43 | public: 44 | uint32_t get_Time(); 45 | 46 | private: 47 | JsFbProfiler( JSContext* cx, const qwr::u8string& name ); 48 | 49 | private: 50 | [[maybe_unused]] JSContext* pJsCtx_ = nullptr; 51 | qwr::u8string name_; 52 | pfc::hires_timer timer_; 53 | }; 54 | 55 | } // namespace mozjs 56 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/js_backend/objects/fb2k/fb_properties.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | class JSObject; 8 | struct JSContext; 9 | struct JSClass; 10 | 11 | namespace smp::panel 12 | { 13 | class PanelWindow; 14 | } 15 | 16 | namespace mozjs 17 | { 18 | 19 | class FbProperties 20 | { 21 | public: 22 | FbProperties( const FbProperties& ) = delete; 23 | FbProperties& operator=( const FbProperties& ) = delete; 24 | ~FbProperties() = default; 25 | 26 | static [[nodiscard]] std::unique_ptr Create( JSContext* cx, smp::panel::PanelWindow& parentPanel ); 27 | 28 | public: 29 | void Trace( JSTracer* trc ); 30 | void PrepareForGc(); 31 | 32 | [[nodiscard]] JS::Value GetProperty( const std::wstring& propName, JS::HandleValue propDefaultValue ); 33 | void SetProperty( const std::wstring& propName, JS::HandleValue propValue ); 34 | 35 | private: 36 | FbProperties( JSContext* cx, smp::panel::PanelWindow& parentPanel ); 37 | 38 | private: 39 | JSContext* pJsCtx_ = nullptr; 40 | smp::panel::PanelWindow& parentPanel_; 41 | 42 | struct HeapElement 43 | { 44 | HeapElement( JS::HandleValue inValue ) 45 | : value( inValue ) 46 | { 47 | } 48 | 49 | JS::Heap value; 50 | }; 51 | 52 | std::unordered_map> properties_; 53 | }; 54 | 55 | } // namespace mozjs 56 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/js_backend/objects/fb2k/fb_title_format.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include 6 | #include 7 | 8 | class JSObject; 9 | struct JSContext; 10 | struct JSClass; 11 | 12 | namespace mozjs 13 | { 14 | 15 | class JsFbMetadbHandle; 16 | class JsFbMetadbHandleList; 17 | 18 | class JsFbTitleFormat 19 | : public JsObjectBase 20 | { 21 | public: 22 | static constexpr bool HasProto = true; 23 | static constexpr bool HasGlobalProto = true; 24 | 25 | static const JSClass JsClass; 26 | static const JSFunctionSpec* JsFunctions; 27 | static const JSPropertySpec* JsProperties; 28 | static const JsPrototypeId PrototypeId; 29 | static const JSNative JsConstructor; 30 | 31 | public: 32 | ~JsFbTitleFormat() override = default; 33 | 34 | static std::unique_ptr CreateNative( JSContext* cx, const qwr::u8string& expr ); 35 | [[nodiscard]] size_t GetInternalSize(); 36 | 37 | public: 38 | titleformat_object::ptr GetTitleFormat(); 39 | 40 | public: // ctor 41 | static JSObject* Constructor( JSContext* cx, const qwr::u8string& expr ); 42 | 43 | public: 44 | pfc::string8_fast Eval( bool force = false ); 45 | pfc::string8_fast EvalWithOpt( size_t optArgCount, bool force ); 46 | pfc::string8_fast EvalWithMetadb( JsFbMetadbHandle* handle ); 47 | JS::Value EvalWithMetadbs( JsFbMetadbHandleList* handles ); 48 | 49 | private: 50 | JsFbTitleFormat( JSContext* cx, const qwr::u8string& expr ); 51 | 52 | private: 53 | JSContext* pJsCtx_ = nullptr; 54 | titleformat_object::ptr titleFormatObject_; 55 | }; 56 | 57 | } // namespace mozjs 58 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/js_backend/objects/fb2k/fb_ui_selection_holder.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include 6 | 7 | class JSObject; 8 | struct JSContext; 9 | struct JSClass; 10 | 11 | namespace mozjs 12 | { 13 | 14 | class JsFbMetadbHandleList; 15 | 16 | class JsFbUiSelectionHolder 17 | : public JsObjectBase 18 | { 19 | public: 20 | static constexpr bool HasProto = true; 21 | static constexpr bool HasGlobalProto = false; 22 | 23 | static const JSClass JsClass; 24 | static const JSFunctionSpec* JsFunctions; 25 | static const JSPropertySpec* JsProperties; 26 | static const JsPrototypeId PrototypeId; 27 | 28 | public: 29 | ~JsFbUiSelectionHolder() override = default; 30 | 31 | static std::unique_ptr CreateNative( JSContext* cx, const ui_selection_holder::ptr& holder ); 32 | [[nodiscard]] size_t GetInternalSize(); 33 | 34 | public: 35 | void SetPlaylistSelectionTracking(); 36 | void SetPlaylistTracking(); 37 | void SetSelection( JsFbMetadbHandleList* handles, uint8_t type = 0 ); 38 | void SetSelectionWithOpt( size_t optArgCount, JsFbMetadbHandleList* handles, uint8_t type ); 39 | 40 | private: 41 | JsFbUiSelectionHolder( JSContext* cx, const ui_selection_holder::ptr& holder ); 42 | 43 | private: 44 | [[maybe_unused]] JSContext* pJsCtx_ = nullptr; 45 | ui_selection_holder::ptr holder_; 46 | }; 47 | 48 | } // namespace mozjs 49 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/js_backend/objects/gdi/gdi_utils.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include 6 | #include 7 | 8 | class JSObject; 9 | struct JSContext; 10 | struct JSClass; 11 | 12 | namespace mozjs 13 | { 14 | 15 | class JsGdiUtils 16 | : public JsObjectBase 17 | { 18 | public: 19 | static constexpr bool HasProto = false; 20 | 21 | static const JSClass JsClass; 22 | static const JSFunctionSpec* JsFunctions; 23 | static const JSPropertySpec* JsProperties; 24 | 25 | public: 26 | ~JsGdiUtils() override = default; 27 | 28 | static std::unique_ptr CreateNative( JSContext* cx ); 29 | [[nodiscard]] size_t GetInternalSize(); 30 | 31 | public: 32 | JSObject* CreateImage( uint32_t w, uint32_t h ); 33 | JSObject* Font( const std::wstring& fontName, uint32_t pxSize, uint32_t style = 0 ); 34 | JSObject* FontWithOpt( size_t optArgCount, const std::wstring& fontName, uint32_t pxSize, uint32_t style ); 35 | JSObject* Image( const std::wstring& path ); 36 | std::uint32_t LoadImageAsync( uint32_t hWnd, const std::wstring& path ); 37 | JSObject* LoadImageAsyncV2( uint32_t hWnd, const std::wstring& path ); 38 | 39 | private: 40 | JsGdiUtils( JSContext* cx ); 41 | 42 | private: 43 | JSContext* pJsCtx_ = nullptr; 44 | }; 45 | 46 | } // namespace mozjs 47 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/js_backend/objects/gdi/measure_string_info.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include 6 | 7 | class JSObject; 8 | struct JSContext; 9 | struct JSClass; 10 | 11 | namespace mozjs 12 | { 13 | 14 | class JsMeasureStringInfo 15 | : public JsObjectBase 16 | { 17 | public: 18 | static constexpr bool HasProto = true; 19 | static constexpr bool HasGlobalProto = false; 20 | 21 | static const JSClass JsClass; 22 | static const JSFunctionSpec* JsFunctions; 23 | static const JSPropertySpec* JsProperties; 24 | static const JsPrototypeId PrototypeId; 25 | 26 | public: 27 | ~JsMeasureStringInfo() override = default; 28 | 29 | static std::unique_ptr CreateNative( JSContext* cx, float x, float y, float w, float h, uint32_t l, uint32_t c ); 30 | [[nodiscard]] size_t GetInternalSize(); 31 | 32 | public: 33 | [[nodiscard]] uint32_t get_Chars() const; 34 | [[nodiscard]] float get_Height() const; 35 | [[nodiscard]] uint32_t get_Lines() const; 36 | [[nodiscard]] float get_Width() const; 37 | [[nodiscard]] float get_X() const; 38 | [[nodiscard]] float get_Y() const; 39 | 40 | private: 41 | JsMeasureStringInfo( JSContext* cx, float x, float y, float w, float h, uint32_t l, uint32_t c ); 42 | 43 | private: 44 | [[maybe_unused]] JSContext* pJsCtx_ = nullptr; 45 | 46 | float x_, y_, w_, h_; 47 | int lines_, characters_; 48 | }; 49 | 50 | } // namespace mozjs 51 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/js_backend/utils/cached_utf8_paths_hack.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "cached_utf8_paths_hack.h" 4 | 5 | #include 6 | 7 | #include 8 | 9 | namespace 10 | { 11 | 12 | std::unordered_map g_cachedPaths; 13 | 14 | } 15 | 16 | namespace mozjs::hack 17 | { 18 | 19 | std::string CacheUtf8Path( const std::filesystem::path& path ) 20 | { 21 | const auto u8path = path.lexically_normal().u8string(); 22 | const auto hash = smp::CalculateMd5( { reinterpret_cast( u8path.c_str() ), u8path.length() } ); 23 | g_cachedPaths.try_emplace( hash, path ); 24 | return hash; 25 | } 26 | 27 | std::optional GetCachedUtf8Path( const std::string_view& pathId ) 28 | { 29 | const auto it = g_cachedPaths.find( { pathId.data(), pathId.size() } ); 30 | if ( it == g_cachedPaths.end() ) 31 | { 32 | return std::nullopt; 33 | } 34 | 35 | return it->second; 36 | } 37 | 38 | const std::unordered_map& GetAllCachedUtf8Paths() 39 | { 40 | return g_cachedPaths; 41 | } 42 | 43 | } // namespace mozjs::hack 44 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/js_backend/utils/cached_utf8_paths_hack.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | // This is a workaround for 7 | // https://github.com/TheQwertiest/foo_spider_monkey_panel/issues/1 8 | 9 | namespace mozjs::hack 10 | { 11 | 12 | /// @brief This is a hack, don't use it unless it's REALLY necessary 13 | /// @throw qwr::QwrException 14 | /// @throw smp::JsException 15 | [[nodiscard]] std::string CacheUtf8Path( const std::filesystem::path& path ); 16 | 17 | /// @brief This is a hack, don't use it unless it's REALLY necessary 18 | [[nodiscard]] std::optional 19 | GetCachedUtf8Path( const std::string_view& pathId ); 20 | 21 | /// @brief This is a hack, don't use it unless it's REALLY necessary 22 | [[nodiscard]] const std::unordered_map& 23 | GetAllCachedUtf8Paths(); 24 | 25 | } // namespace mozjs::hack 26 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/js_backend/utils/js_art_helpers.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace mozjs::art 6 | { 7 | 8 | /// @throw smp::JsException 9 | [[nodiscard]] JSObject* GetAlbumArtPromise( JSContext* cx, 10 | HWND hWnd, 11 | const metadb_handle_ptr& handle, 12 | const smp::art::LoadingOptions& options ); 13 | 14 | } // namespace mozjs::art 15 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/js_backend/utils/js_hwnd_helpers.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "js_hwnd_helpers.h" 4 | 5 | #include 6 | 7 | namespace mozjs 8 | { 9 | 10 | HWND GetPanelHwndForCurrentGlobal( JSContext* cx ) 11 | { 12 | assert( cx ); 13 | 14 | JS::RootedObject jsGlobal( cx, JS::CurrentGlobalOrNull( cx ) ); 15 | assert( jsGlobal ); 16 | 17 | const auto pNativeGlobal = JsGlobalObject::ExtractNative( cx, jsGlobal ); 18 | assert( pNativeGlobal ); 19 | 20 | return pNativeGlobal->GetPanelHwnd(); 21 | } 22 | 23 | } // namespace mozjs 24 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/js_backend/utils/js_hwnd_helpers.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace mozjs 4 | { 5 | 6 | [[nodiscard]] HWND GetPanelHwndForCurrentGlobal( JSContext* cx ); 7 | 8 | } 9 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/js_backend/utils/js_image_helpers.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | class JSObject; 6 | struct JSContext; 7 | 8 | namespace mozjs::image 9 | { 10 | 11 | /// @throw qwr::QwrException 12 | /// @throw smp::JsException 13 | [[nodiscard]] JSObject* GetImagePromise( JSContext* cx, HWND hWnd, const std::wstring& imagePath ); 14 | 15 | } // namespace mozjs::image 16 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/js_backend/utils/js_object_helper.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "js_object_helper.h" 4 | 5 | namespace mozjs 6 | { 7 | 8 | bool DummyGetter( JSContext*, unsigned, JS::Value* vp ) 9 | { 10 | vp->setUndefined(); 11 | return true; 12 | } 13 | 14 | const void* GetSmpProxyFamily() 15 | { 16 | // family must contain unique pointer, so the value does not really matter 17 | static const char kProxyFamilyVar = 'Q'; 18 | return &kProxyFamilyVar; 19 | } 20 | 21 | } // namespace mozjs 22 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/js_backend/utils/js_object_helper.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | class JSFreeOp; 7 | struct JSContext; 8 | class JSObject; 9 | 10 | namespace mozjs 11 | { 12 | 13 | inline constexpr uint32_t kDefaultClassFlags = JSCLASS_HAS_PRIVATE | JSCLASS_BACKGROUND_FINALIZE; 14 | inline constexpr uint8_t kDefaultPropsFlags = JSPROP_ENUMERATE | JSPROP_PERMANENT; 15 | 16 | /// @details Used to define write-only property with JS_PSGS 17 | bool DummyGetter( JSContext* cx, unsigned argc, JS::Value* vp ); 18 | 19 | const void* GetSmpProxyFamily(); 20 | 21 | template 22 | void CreateAndInstallObject( JSContext* cx, JS::HandleObject parentObject, const qwr::u8string& propertyName, ArgsType&&... args ) 23 | { 24 | JS::RootedObject objectToInstall( cx, JsObjectBase::CreateJs( cx, args... ) ); 25 | assert( objectToInstall ); 26 | 27 | if ( !JS_DefineProperty( cx, parentObject, propertyName.c_str(), objectToInstall, kDefaultPropsFlags ) ) 28 | { 29 | throw smp::JsException(); 30 | } 31 | } 32 | 33 | } // namespace mozjs 34 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/js_backend/utils/js_prototype_helpers.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "js_prototype_helpers.h" 4 | 5 | namespace mozjs::utils 6 | { 7 | 8 | JSObject* GetPrototype( JSContext* cx, JsPrototypeId protoId ) 9 | { 10 | JS::RootedObject globalObject( cx, JS::CurrentGlobalOrNull( cx ) ); 11 | assert( globalObject ); 12 | 13 | uint32_t slotIdx = JSCLASS_GLOBAL_SLOT_COUNT + static_cast( protoId ); 14 | assert( slotIdx < JSCLASS_RESERVED_SLOTS( JS::GetClass( globalObject ) ) ); 15 | 16 | JS::Value protoVal = JS::GetReservedSlot( globalObject, slotIdx ); 17 | qwr::QwrException::ExpectTrue( protoVal.isObject(), 18 | "Internal error: Slot {}({}) does not contain a prototype", 19 | static_cast( protoId ), 20 | slotIdx ); 21 | 22 | return &protoVal.toObject(); 23 | } 24 | 25 | } // namespace mozjs::utils 26 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/js_backend/utils/scope_helper.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | struct JSContext; 6 | 7 | namespace mozjs 8 | { 9 | 10 | class JsAutoRealmWithErrorReport 11 | { 12 | public: 13 | [[nodiscard]] JsAutoRealmWithErrorReport( JSContext* cx, JS::HandleObject global ) 14 | : ac_( cx, global ) 15 | , are_( cx ) 16 | { 17 | } 18 | 19 | JsAutoRealmWithErrorReport( const JsAutoRealmWithErrorReport& ) = delete; 20 | JsAutoRealmWithErrorReport& operator=( const JsAutoRealmWithErrorReport& ) = delete; 21 | 22 | void DisableReport() 23 | { 24 | are_.Disable(); 25 | } 26 | 27 | private: 28 | JSAutoRealm ac_; 29 | mozjs::error::AutoJsReport are_; 30 | }; 31 | 32 | } // namespace mozjs 33 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/js_backend/utils/serialized_value.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "serialized_value.h" 4 | 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | namespace mozjs 11 | { 12 | 13 | SerializedJsValue SerializeJsValue( JSContext* cx, JS::HandleValue jsValue ) 14 | { 15 | SerializedJsValue serializedValue; 16 | 17 | if ( jsValue.isBoolean() ) 18 | { 19 | serializedValue = jsValue.toBoolean(); 20 | } 21 | else if ( jsValue.isInt32() ) 22 | { 23 | serializedValue = jsValue.toInt32(); 24 | } 25 | else if ( jsValue.isDouble() ) 26 | { 27 | serializedValue = jsValue.toDouble(); 28 | } 29 | else if ( jsValue.isString() ) 30 | { 31 | JS::RootedValue rVal( cx, jsValue ); 32 | serializedValue = convert::to_native::ToValue( cx, rVal ); 33 | } 34 | else 35 | { 36 | throw qwr::QwrException( "Unsupported value type" ); 37 | } 38 | 39 | return serializedValue; 40 | } 41 | 42 | void DeserializeJsValue( JSContext* cx, const SerializedJsValue& serializedValue, JS::MutableHandleValue jsValue ) 43 | { 44 | std::visit( 45 | qwr::Visitor{ 46 | [cx, &jsValue]( bool arg ) { jsValue.setBoolean( arg ); }, 47 | [cx, &jsValue]( int32_t arg ) { jsValue.setInt32( arg ); }, 48 | [cx, &jsValue]( double arg ) { jsValue.setDouble( arg ); }, 49 | [cx, &jsValue]( const qwr::u8string& arg ) { convert::to_js::ToValue( cx, arg, jsValue ); } }, 50 | serializedValue ); 51 | } 52 | 53 | } // namespace mozjs 54 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/js_backend/utils/serialized_value.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | namespace mozjs 7 | { 8 | 9 | using SerializedJsValue = std::variant; 10 | 11 | [[nodiscard]] SerializedJsValue SerializeJsValue( JSContext* cx, JS::HandleValue jsValue ); 12 | void DeserializeJsValue( JSContext* cx, const SerializedJsValue& serializedValue, JS::MutableHandleValue jsValue ); 13 | 14 | } // namespace mozjs 15 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/panel/drag_action_params.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace smp::panel 4 | { 5 | 6 | struct DragActionParams 7 | { 8 | int32_t playlistIdx = -1; // -1 means active playlist 9 | uint32_t base = 0; 10 | bool toSelect = true; 11 | uint32_t effect = DROPEFFECT_NONE; 12 | std::wstring text; 13 | bool isInternal = false; 14 | }; 15 | 16 | } // namespace smp::panel 17 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/panel/edit_script.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace smp::config 6 | { 7 | 8 | class ResolvedPanelScriptSettings; 9 | 10 | } 11 | 12 | namespace smp::panel 13 | { 14 | 15 | /// @throw qwr::QwrException 16 | void EditScript( HWND hParent, qwr::u8string& script ); 17 | 18 | /// @throw qwr::QwrException 19 | void EditScriptFile( HWND hParent, const config::ResolvedPanelScriptSettings& settings ); 20 | 21 | /// @throw qwr::QwrException 22 | void EditPackageScript( HWND hParent, const std::filesystem::path& script ); 23 | 24 | } // namespace smp::panel 25 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/panel/modal_blocking_scope.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace smp::modal 6 | { 7 | 8 | /// @remark For cases when modal might be called from another modal 9 | class ConditionalModalScope 10 | { 11 | public: 12 | /// @param isWhitelistedModal false, if should not be considered JS blocking 13 | [[nodiscard]] ConditionalModalScope( HWND hParent, bool isWhitelistedModal = false ); 14 | ~ConditionalModalScope(); 15 | 16 | private: 17 | modal_dialog_scope scope_; 18 | bool needsModalScope_; 19 | bool isWhitelistedModal_; 20 | }; 21 | 22 | class MessageBlockingScope 23 | { 24 | public: 25 | [[nodiscard]] MessageBlockingScope(); 26 | ~MessageBlockingScope(); 27 | }; 28 | 29 | class ModalBlockingScope 30 | { 31 | public: 32 | /// @param isWhitelistedModal false, if should not be considered JS blocking 33 | [[nodiscard]] ModalBlockingScope( HWND hParent, bool isWhitelistedModal = false ); 34 | ~ModalBlockingScope(); 35 | 36 | private: 37 | modal_dialog_scope scope_; 38 | bool isWhitelistedModal_; 39 | }; 40 | 41 | class WhitelistedScope 42 | { 43 | public: 44 | [[nodiscard]] WhitelistedScope(); 45 | ~WhitelistedScope(); 46 | }; 47 | 48 | /// @brief Works like `modal_dialog_scope::can_create()`, but takes pseudo-modals in account as well 49 | [[nodiscard]] bool IsModalBlocked(); 50 | [[nodiscard]] bool IsInWhitelistedModal(); 51 | 52 | } // namespace smp::modal 53 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/panel/panel_adaptor_iface.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace smp::panel 4 | { 5 | 6 | enum class PanelType : uint8_t 7 | { 8 | CUI = 0, 9 | DUI = 1 10 | }; 11 | 12 | class IPanelAdaptor 13 | { 14 | public: 15 | virtual ~IPanelAdaptor(){}; 16 | 17 | [[nodiscard]] virtual PanelType GetPanelType() const = 0; 18 | 19 | [[nodiscard]] virtual DWORD GetColour( unsigned type, const GUID& guid ) = 0; 20 | [[nodiscard]] virtual HFONT GetFont( unsigned type, const GUID& guid ) = 0; 21 | virtual void OnSizeLimitChanged( LPARAM lp ) = 0; 22 | virtual LRESULT OnMessage( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp ) = 0; 23 | }; 24 | 25 | } // namespace smp::panel 26 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/panel/user_message.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace smp 4 | { 5 | 6 | /// @details These messages are synchronous 7 | enum class InternalSyncMessage : UINT 8 | { 9 | first_message = WM_USER + 100, 10 | legacy_notify_others = first_message, 11 | prepare_for_exit, 12 | run_next_event, 13 | script_fail, 14 | ui_script_editor_saved, 15 | wnd_drag_drop, 16 | wnd_drag_enter, 17 | wnd_drag_leave, 18 | wnd_drag_over, 19 | wnd_internal_drag_start, 20 | wnd_internal_drag_stop, 21 | last_message = wnd_internal_drag_stop, 22 | }; 23 | 24 | /// @brief Message definitions that are not handled by the main panel window 25 | enum class MiscMessage : UINT 26 | { 27 | heartbeat = static_cast( InternalSyncMessage::last_message ) + 1, 28 | key_down, 29 | size_limit_changed 30 | }; 31 | 32 | template 33 | bool IsInEnumRange( UINT value ) 34 | { 35 | return ( value >= static_cast( T::first_message ) 36 | && value <= static_cast( T::last_message ) ); 37 | } 38 | 39 | } // namespace smp 40 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/resources/foo_spider_monkey_panel.rc2: -------------------------------------------------------------------------------- 1 | // 2 | // $rc2filename$ - resources Microsoft Visual C++ does not edit directly 3 | // 4 | 5 | #ifdef APSTUDIO_INVOKED 6 | #error this file is not editable by Microsoft Visual C++ 7 | #endif //APSTUDIO_INVOKED 8 | 9 | 10 | ///////////////////////////////////////////////////////////////////////////// 11 | // Add manually edited resources here... 12 | 13 | 1 typelib "foo_spider_monkey_panel\\tlb\\foo_spider_monkey_panel.tlb" 14 | 15 | ///////////////////////////////////////////////////////////////////////////// 16 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/resources/recovery_package_json.json: -------------------------------------------------------------------------------- 1 | { 2 | "author": "TheQwertiest", 3 | "description": "Follow displayed instructions to recover your package.", 4 | "enableDragDrop": false, 5 | "id": "", 6 | "name": "Recovery package", 7 | "shouldGrabFocus": true, 8 | "version": "1.0.0" 9 | } 10 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/stdafx.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/timeout/time_types.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace smp 6 | { 7 | 8 | using TimeStamp = std::chrono::time_point; 9 | using TimeDuration = TimeStamp::duration; 10 | 11 | } // namespace smp 12 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/timeout/timeout.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "timeout.h" 4 | 5 | namespace smp 6 | { 7 | 8 | Timeout::Timeout( uint32_t id, TimeDuration interval, bool isRepeated, std::shared_ptr task ) 9 | : id_( id ) 10 | , interval_( interval ) 11 | , task_( task ) 12 | , isRepeated_( isRepeated ) 13 | { 14 | } 15 | 16 | void Timeout::SetWhen( const TimeStamp& baseTime, const TimeDuration& delay ) 17 | { 18 | executeAt_ = baseTime + delay; 19 | } 20 | 21 | void Timeout::SetFiringId( uint32_t firingId ) 22 | { 23 | firingId_ = firingId; 24 | } 25 | 26 | void Timeout::DisableRepeat() 27 | { 28 | isRepeated_ = false; 29 | } 30 | 31 | void Timeout::MarkAsStopped() 32 | { 33 | isStopped_ = true; 34 | } 35 | 36 | void Timeout::SetRunningState( bool isRunning ) 37 | { 38 | isRunning_ = isRunning; 39 | } 40 | 41 | uint32_t Timeout::Id() const 42 | { 43 | return id_; 44 | } 45 | 46 | std::shared_ptr Timeout::Task() const 47 | { 48 | return task_; 49 | } 50 | 51 | const smp::TimeStamp& Timeout::When() const 52 | { 53 | return executeAt_; 54 | } 55 | 56 | bool Timeout::IsRunning() const 57 | { 58 | return isRunning_; 59 | } 60 | 61 | bool Timeout::IsRepeated() const 62 | { 63 | return isRepeated_; 64 | } 65 | 66 | TimeDuration Timeout::Interval() const 67 | { 68 | return interval_; 69 | } 70 | 71 | uint32_t Timeout::GetFiringId() 72 | { 73 | return firingId_; 74 | } 75 | 76 | } // namespace smp 77 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/timeout/timeout.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include 6 | #include 7 | 8 | namespace mozjs 9 | { 10 | 11 | class JsAsyncTask; 12 | 13 | } 14 | 15 | namespace smp 16 | { 17 | 18 | class Timeout; 19 | 20 | class Timeout 21 | { 22 | public: 23 | Timeout( uint32_t id, TimeDuration interval, bool isRepeated, std::shared_ptr task ); 24 | ~Timeout() = default; 25 | 26 | void SetWhen( const TimeStamp& baseTime, const TimeDuration& delay ); 27 | void SetFiringId( uint32_t firingId ); 28 | void DisableRepeat(); 29 | void MarkAsStopped(); 30 | void SetRunningState( bool isRunning ); 31 | 32 | [[nodiscard]] uint32_t Id() const; 33 | [[nodiscard]] std::shared_ptr Task() const; 34 | [[nodiscard]] const TimeStamp& When() const; 35 | [[nodiscard]] bool IsRunning() const; 36 | [[nodiscard]] bool IsRepeated() const; 37 | [[nodiscard]] TimeDuration Interval() const; 38 | [[nodiscard]] uint32_t GetFiringId(); 39 | 40 | private: 41 | const uint32_t id_; 42 | const TimeDuration interval_; 43 | const std::shared_ptr task_; 44 | bool isRepeated_; 45 | 46 | TimeStamp executeAt_; 47 | 48 | bool isRunning_ = false; 49 | bool isStopped_ = false; 50 | 51 | uint32_t firingId_ = 0; 52 | }; 53 | 54 | } // namespace smp 55 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/timeout/timer_interface.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | // 5 | #include 6 | #include 7 | #include 8 | #include 9 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/timeout/timer_interface_fwd.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace smp 6 | { 7 | 8 | class PanelTarget; 9 | 10 | class Timer_Native; 11 | class TimerManager_Native; 12 | 13 | class Timer_Custom; 14 | class TimerManager_Custom; 15 | 16 | struct TimerNotifyTask 17 | { 18 | virtual ~TimerNotifyTask() = default; 19 | virtual void Notify() = 0; 20 | }; 21 | 22 | class ITimer 23 | { 24 | public: 25 | virtual ~ITimer() = default; 26 | 27 | virtual void Start( TimerNotifyTask& task, const TimeStamp& when ) = 0; 28 | virtual void Cancel( bool waitForDestruction ) = 0; 29 | 30 | virtual void Fire( uint64_t generation ) = 0; 31 | 32 | virtual [[nodiscard]] PanelTarget& Target() const = 0; 33 | virtual [[nodiscard]] const TimeStamp& When() const = 0; 34 | virtual [[nodiscard]] uint64_t Generation() const = 0; 35 | }; 36 | 37 | } // namespace smp 38 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/timeout/timer_manager_custom.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | namespace smp 11 | { 12 | 13 | class PanelTarget; 14 | class Timer_Custom; 15 | class TimerHolder; 16 | 17 | /// @brief Actual timer implementation. 18 | class TimerManager_Custom 19 | { 20 | public: 21 | static [[nodiscard]] TimerManager_Custom& Get(); 22 | 23 | void Finalize(); 24 | 25 | [[nodiscard]] static const TimeDuration& GetAllowedEarlyFiringTime(); 26 | [[nodiscard]] std::unique_ptr CreateTimer( std::shared_ptr pTarget ); 27 | 28 | public: 29 | void AddTimer( std::shared_ptr pTimer ); 30 | void RemoveTimer( std::shared_ptr pTimer ); 31 | 32 | private: 33 | TimerManager_Custom(); 34 | 35 | void CreateThread(); 36 | void StopThread(); 37 | 38 | void ThreadMain(); 39 | 40 | void RemoveLeadingCanceledTimersInternal(); 41 | void RemoveFirstTimerInternal(); 42 | 43 | static bool TimerSorter( const std::unique_ptr& a, const std::unique_ptr& b ); 44 | 45 | private: 46 | std::atomic_bool isTimeToDie_{ false }; 47 | 48 | std::unique_ptr thread_; 49 | std::mutex threadMutex_; 50 | 51 | std::condition_variable cv_; 52 | std::vector> timers_; 53 | }; 54 | 55 | } // namespace smp 56 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/timeout/timer_manager_native.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include 6 | #include 7 | 8 | namespace smp 9 | { 10 | 11 | class PanelTarget; 12 | class Timer_Native; 13 | 14 | class TimerManager_Native 15 | { 16 | public: 17 | static [[nodiscard]] TimerManager_Native& Get(); 18 | 19 | void Finalize(); 20 | 21 | [[nodiscard]] static const TimeDuration& GetAllowedEarlyFiringTime(); 22 | [[nodiscard]] std::unique_ptr CreateTimer( std::shared_ptr pTarget ); 23 | 24 | public: 25 | [[nodiscard]] HANDLE CreateNativeTimer( std::shared_ptr pTimer ); 26 | void DestroyNativeTimer( HANDLE hTimer, bool waitForDestruction ); 27 | void PostTimerEvent( std::shared_ptr pTimer ); 28 | 29 | private: 30 | TimerManager_Native(); 31 | 32 | private: 33 | HANDLE hTimerQueue_; 34 | }; 35 | 36 | } // namespace smp 37 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/timeout/timer_native.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | namespace smp 13 | { 14 | 15 | class PanelTarget; 16 | class TimerManager_Native; 17 | 18 | /// @brief Timer information holder. 19 | /// 20 | /// Each SMP panel should hold no more than one timer. There are no technical limitations for this though. 21 | class Timer_Native final 22 | : public ITimer 23 | , public std::enable_shared_from_this 24 | { 25 | friend class TimerManager_Native; 26 | 27 | public: 28 | ~Timer_Native() = default; 29 | 30 | void Start( TimerNotifyTask& task, const TimeStamp& when ); 31 | void Cancel( bool waitForDestruction ); 32 | 33 | void Fire( uint64_t generation ); 34 | 35 | [[nodiscard]] PanelTarget& Target() const; 36 | [[nodiscard]] const TimeStamp& When() const; 37 | [[nodiscard]] uint64_t Generation() const; 38 | 39 | private: 40 | Timer_Native( TimerManager_Native& pParent, std::shared_ptr pTarget ); 41 | 42 | static VOID CALLBACK TimerProc( PVOID lpParameter, BOOLEAN TimerOrWaitFired ); 43 | 44 | private: 45 | TimerManager_Native& pParent_; 46 | std::shared_ptr pTarget_; 47 | HANDLE hTimer_ = nullptr; 48 | 49 | TimerNotifyTask* pTask_ = nullptr; 50 | TimeStamp executeAt_{}; 51 | int64_t generation_ = 0; 52 | }; 53 | 54 | } // namespace smp 55 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/ui/impl/ui_itab.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace smp::ui 4 | { 5 | 6 | class ITab 7 | { 8 | public: 9 | virtual ~ITab() = default; 10 | 11 | virtual HWND CreateTab( HWND hParent ) = 0; 12 | [[nodiscard]] virtual CDialogImplBase& Dialog() = 0; 13 | [[nodiscard]] virtual const wchar_t* Name() const = 0; 14 | 15 | [[nodiscard]] virtual bool HasChanged() = 0; 16 | virtual void Apply() = 0; 17 | virtual void Revert() = 0; 18 | virtual void Refresh() = 0; 19 | }; 20 | 21 | } // namespace smp::ui 22 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/ui/impl/ui_menu_edit_with.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace smp::ui 6 | { 7 | 8 | class CMenuEditWith 9 | : public CMenu 10 | { 11 | public: 12 | static BOOL ProcessWindowMessage( _In_ HWND hWnd, _In_ UINT uMsg, _In_ WPARAM wParam, _In_ LPARAM lParam, _Inout_ LRESULT& lResult, _In_ DWORD dwMsgMapID = 0 ); 13 | 14 | public: 15 | void InitMenu(); 16 | static void OnEditClick( UINT uNotifyCode, int nID, CWindow wndCtl ); 17 | 18 | private: 19 | std::vector currentBmps_; 20 | }; 21 | 22 | } // namespace smp::ui 23 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/ui/scintilla/sci_config.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "sci_config.h" 4 | 5 | namespace smp::config::sci 6 | { 7 | 8 | ScintillaPropsCfg props{ guid::scintilla_props }; 9 | 10 | } // namespace smp::config::sci 11 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/ui/scintilla/sci_config.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace smp::config::sci 6 | { 7 | 8 | extern ScintillaPropsCfg props; 9 | 10 | } // namespace smp::config::sci 11 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/ui/scintilla/sci_prop_sets.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | namespace smp::config::sci 7 | { 8 | 9 | struct ScintillaProp 10 | { 11 | qwr::u8string key; 12 | qwr::u8string defaultval; 13 | qwr::u8string val; 14 | }; 15 | 16 | using ScintillaPropList = std::vector; 17 | 18 | class ScintillaPropsCfg : public cfg_var 19 | { 20 | public: 21 | struct DefaultPropValue 22 | { 23 | const char* key; 24 | const char* defaultval; 25 | }; 26 | 27 | public: 28 | ScintillaPropsCfg( const GUID& p_guid ); 29 | 30 | [[nodiscard]] ScintillaPropList& val(); 31 | [[nodiscard]] const ScintillaPropList& val() const; 32 | 33 | // cfg_var 34 | void get_data_raw( stream_writer* p_stream, abort_callback& p_abort ) override; 35 | void set_data_raw( stream_reader* p_stream, t_size p_sizehint, abort_callback& p_abort ) override; 36 | 37 | void reset(); 38 | void export_to_file( const wchar_t* filename ); 39 | void import_from_file( const char* filename ); 40 | 41 | private: 42 | struct StriCmpAscii 43 | { 44 | bool operator()( const qwr::u8string& a, const qwr::u8string& b ) const; 45 | }; 46 | 47 | using ScintillaPropValues = std::map; 48 | 49 | private: 50 | void init_data( std::span p_default ); 51 | void merge_data( const ScintillaPropValues& data_map ); 52 | 53 | private: 54 | ScintillaPropList m_data; 55 | }; 56 | 57 | } // namespace smp::config::sci 58 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/ui/scintilla/ui_sci_goto.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace smp::ui::sci 6 | { 7 | 8 | class CScriptEditorCtrl; 9 | 10 | class CDialogGoto : public CDialogImpl 11 | { 12 | public: 13 | BEGIN_MSG_MAP( CDialogGoto ) 14 | MSG_WM_INITDIALOG( OnInitDialog ) 15 | MSG_WM_DESTROY( OnDestroy ) 16 | COMMAND_RANGE_HANDLER_EX( IDOK, IDCANCEL, OnCloseCmd ) 17 | END_MSG_MAP() 18 | 19 | enum 20 | { 21 | IDD = IDD_DIALOG_GOTO 22 | }; 23 | 24 | CDialogGoto( HWND hParent, int curLineNumber ); 25 | 26 | LRESULT OnInitDialog( HWND hwndFocus, LPARAM lParam ); 27 | void OnDestroy(); 28 | LRESULT OnCloseCmd( WORD wNotifyCode, WORD wID, HWND hWndCtl ); 29 | 30 | // CDialogImpl 31 | 32 | void OnFinalMessage( _In_ HWND /*hWnd*/ ) override; 33 | 34 | static void GetMsgProc( int code, WPARAM wParam, LPARAM lParam, HWND hParent ); 35 | 36 | private: 37 | HWND hParent_; 38 | const int curLineNumber_; 39 | 40 | uint32_t hookId_ = 0; 41 | }; 42 | 43 | class CScintillaGotoImpl 44 | { 45 | public: 46 | BEGIN_MSG_MAP( CScintillaGotoImpl ) 47 | MESSAGE_HANDLER( GetGotoMsg(), OnGotoCmd ) 48 | END_MSG_MAP() 49 | 50 | CScintillaGotoImpl( CScriptEditorCtrl& sciEdit ); 51 | 52 | static UINT GetGotoMsg(); 53 | 54 | void ShowGoTo(); 55 | 56 | private: 57 | LRESULT OnGotoCmd( UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/ ); 58 | 59 | private: 60 | CScriptEditorCtrl& sciEdit_; 61 | 62 | CDialogGoto* pGoto_ = nullptr; 63 | }; 64 | 65 | } // namespace smp::ui::sci 66 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/ui/ui_edit_in_progress.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | namespace smp::ui 10 | { 11 | 12 | class CEditInProgress : public CDialogImpl 13 | { 14 | public: 15 | enum 16 | { 17 | IDD = IDD_DIALOG_EDIT_IN_PROGRESS 18 | }; 19 | 20 | BEGIN_MSG_MAP( CEditInProgress ) 21 | MSG_WM_INITDIALOG( OnInitDialog ) 22 | COMMAND_ID_HANDLER_EX( IDC_EDIT_IN_PROGRESS_FOCUS, OnEditorFocusCmd ) 23 | COMMAND_RANGE_HANDLER_EX( IDOK, IDCANCEL, OnCloseCmd ) 24 | END_MSG_MAP() 25 | 26 | CEditInProgress( const std::filesystem::path& editor, const std::filesystem::path& file ); 27 | 28 | LRESULT OnInitDialog( HWND hwndFocus, LPARAM lParam ); 29 | LRESULT OnEditorFocusCmd( WORD wNotifyCode, WORD wID, HWND hWndCtl ); 30 | LRESULT OnCloseCmd( WORD wNotifyCode, WORD wID, HWND hWndCtl ); 31 | 32 | private: 33 | void EditorHandler(); 34 | 35 | private: 36 | const std::filesystem::path editor_; 37 | const std::filesystem::path file_; 38 | 39 | std::mutex mutex_; 40 | bool hasEditorLaunched_ = false; 41 | bool isClosing_ = false; 42 | HWND hEditorWnd_ = nullptr; 43 | HANDLE hEditorProcess_ = nullptr; 44 | std::thread editorThread_; 45 | std::string errorMessage_; 46 | }; 47 | 48 | } // namespace smp::ui 49 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/ui/ui_input_box.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace smp::ui 6 | { 7 | 8 | class CInputBox 9 | : public CDialogImpl 10 | , public CDialogResize 11 | { 12 | public: 13 | CInputBox( qwr::u8string_view prompt, qwr::u8string_view caption, qwr::u8string_view value = "" ); 14 | 15 | BEGIN_DLGRESIZE_MAP( CInputBox ) 16 | DLGRESIZE_CONTROL( IDC_INPUT_PROMPT, DLSZ_SIZE_X | DLSZ_SIZE_Y ) 17 | DLGRESIZE_CONTROL( IDC_INPUT_VALUE, DLSZ_SIZE_X | DLSZ_MOVE_Y ) 18 | DLGRESIZE_CONTROL( IDOK, DLSZ_MOVE_X | DLSZ_MOVE_Y ) 19 | DLGRESIZE_CONTROL( IDCANCEL, DLSZ_MOVE_X | DLSZ_MOVE_Y ) 20 | END_DLGRESIZE_MAP() 21 | 22 | BEGIN_MSG_MAP( CInputBox ) 23 | MSG_WM_INITDIALOG( OnInitDialog ) 24 | MSG_WM_COMMAND( OnCommand ) 25 | CHAIN_MSG_MAP( CDialogResize ) 26 | END_MSG_MAP() 27 | 28 | enum 29 | { 30 | IDD = IDD_DIALOG_INPUT 31 | }; 32 | 33 | LRESULT OnInitDialog( HWND hwndFocus, LPARAM lParam ); 34 | LRESULT OnCommand( UINT codeNotify, int id, HWND hwndCtl ); 35 | qwr::u8string GetValue(); 36 | 37 | private: 38 | void AdjustPromptControlToFit(); 39 | 40 | private: 41 | qwr::u8string prompt_; 42 | qwr::u8string caption_; 43 | qwr::u8string value_; 44 | }; 45 | 46 | } // namespace smp::ui 47 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/ui/ui_name_value_edit.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "ui_name_value_edit.h" 4 | 5 | #include 6 | 7 | namespace smp::ui 8 | { 9 | 10 | CNameValueEdit::CNameValueEdit( const char* name, const char* value, const char* caption ) 11 | : name_( name ) 12 | , value_( value ) 13 | , caption_( caption ) 14 | { 15 | } 16 | 17 | LRESULT CNameValueEdit::OnInitDialog( HWND, LPARAM ) 18 | { 19 | uSetWindowText( m_hWnd, caption_.c_str() ); 20 | uSendDlgItemMessageText( m_hWnd, IDC_EDIT_NAME, WM_SETTEXT, 0, name_.c_str() ); 21 | uSendDlgItemMessageText( m_hWnd, IDC_EDIT_VALUE, WM_SETTEXT, 0, value_.c_str() ); 22 | 23 | // Select all 24 | SendDlgItemMessage( IDC_EDIT_VALUE, EM_SETSEL, 0, -1 ); 25 | ::SetFocus( GetDlgItem( IDC_EDIT_VALUE ) ); 26 | 27 | return FALSE; 28 | } 29 | 30 | LRESULT CNameValueEdit::OnCommand( UINT, int id, HWND ) 31 | { 32 | switch ( id ) 33 | { 34 | case IDOK: 35 | { 36 | value_ = qwr::pfc_x::uGetWindowText( GetDlgItem( IDC_EDIT_VALUE ) ); 37 | EndDialog( id ); 38 | break; 39 | } 40 | case IDCANCEL: 41 | { 42 | EndDialog( id ); 43 | break; 44 | } 45 | default: 46 | break; 47 | } 48 | 49 | return 0; 50 | } 51 | 52 | qwr::u8string CNameValueEdit::GetValue() 53 | { 54 | return value_; 55 | } 56 | 57 | } // namespace smp::ui 58 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/ui/ui_name_value_edit.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace smp::ui 6 | { 7 | 8 | class CNameValueEdit : public CDialogImpl 9 | { 10 | public: 11 | BEGIN_MSG_MAP( CNameValueEdit ) 12 | MSG_WM_INITDIALOG( OnInitDialog ) 13 | MSG_WM_COMMAND( OnCommand ) 14 | END_MSG_MAP() 15 | 16 | enum 17 | { 18 | IDD = IDD_DIALOG_NAME_VALUE 19 | }; 20 | 21 | CNameValueEdit( const char* name, const char* value, const char* caption ); 22 | qwr::u8string GetValue(); 23 | 24 | private: 25 | LRESULT OnInitDialog( HWND hwndFocus, LPARAM lParam ); 26 | LRESULT OnCommand( UINT codeNotify, int id, HWND hwndCtl ); 27 | 28 | private: 29 | qwr::u8string name_; 30 | qwr::u8string value_; 31 | qwr::u8string caption_; 32 | }; 33 | 34 | } // namespace smp::ui 35 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/ui/ui_slow_script.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace smp::ui 6 | { 7 | 8 | class CDialogSlowScript : public CDialogImpl 9 | { 10 | public: 11 | struct Data 12 | { 13 | bool askAgain = true; 14 | bool stop = false; 15 | }; 16 | 17 | CDialogSlowScript( const qwr::u8string& panelName, const qwr::u8string& scriptInfo, CDialogSlowScript::Data& data ); 18 | 19 | BEGIN_MSG_MAP( CDialogSlowScript ) 20 | MSG_WM_INITDIALOG( OnInitDialog ) 21 | COMMAND_ID_HANDLER_EX( IDC_SLOWSCRIPT_CONTINUE, OnContinueScript ) 22 | COMMAND_ID_HANDLER_EX( IDC_SLOWSCRIPT_STOP, OnStopScript ) 23 | COMMAND_HANDLER_EX( IDC_SLOWSCRIPT_CHECK_DONTASK, BN_CLICKED, OnDontAskClick ) 24 | COMMAND_RANGE_HANDLER_EX( IDOK, IDCANCEL, OnCloseCmd ) 25 | END_MSG_MAP() 26 | 27 | enum 28 | { 29 | IDD = IDD_DIALOG_SLOWSCRIPT 30 | }; 31 | 32 | LRESULT OnInitDialog( HWND hwndFocus, LPARAM lParam ); 33 | LRESULT OnContinueScript( WORD wNotifyCode, WORD wID, HWND hWndCtl ); 34 | LRESULT OnStopScript( WORD wNotifyCode, WORD wID, HWND hWndCtl ); 35 | LRESULT OnDontAskClick( WORD wNotifyCode, WORD wID, HWND hWndCtl ); 36 | LRESULT OnCloseCmd( WORD wNotifyCode, WORD wID, HWND hWndCtl ); 37 | 38 | private: 39 | const qwr::u8string panelName_; 40 | const qwr::u8string scriptInfo_; 41 | CDialogSlowScript::Data& data_; 42 | }; 43 | 44 | } // namespace smp::ui 45 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/utils/app_info.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | namespace smp 7 | { 8 | 9 | struct AppInfo 10 | { 11 | std::filesystem::path appPath; 12 | std::wstring appName; 13 | }; 14 | 15 | /// @throw qwr::QwrException 16 | std::vector GetAppsAssociatedWithExtension( const std::wstring& ext ); 17 | 18 | CIcon GetAppIcon( const std::filesystem::path& appPath ); 19 | 20 | } // namespace smp 21 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/utils/art_helpers.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include 6 | #include 7 | 8 | namespace smp::art 9 | { 10 | 11 | class EmbedThread 12 | : public threaded_process_callback 13 | { 14 | public: 15 | enum class EmbedAction : uint32_t 16 | { 17 | embed, 18 | remove, 19 | removeAll 20 | }; 21 | 22 | public: 23 | EmbedThread( EmbedAction action, 24 | album_art_data_ptr data, 25 | const metadb_handle_list& handles, 26 | GUID what ); 27 | void run( threaded_process_status& p_status, abort_callback& p_abort ) override; 28 | 29 | private: 30 | EmbedAction action_; 31 | album_art_data_ptr data_; 32 | metadb_handle_list handles_; 33 | GUID what_; 34 | }; 35 | 36 | /// @throw qwr::QwrException 37 | const GUID& GetGuidForArtId( uint32_t art_id ); 38 | 39 | /// @throw smp::JsException 40 | std::unique_ptr GetBitmapFromEmbeddedData( const qwr::u8string& rawpath, uint32_t art_id ); 41 | 42 | /// @throw qwr::QwrException 43 | std::unique_ptr GetBitmapFromMetadb( const metadb_handle_ptr& handle, const LoadingOptions& options, qwr::u8string* pImagePath ); 44 | 45 | /// @details Validate art_id before calling this function! 46 | std::unique_ptr GetBitmapFromMetadbOrEmbed( const metadb_handle_ptr& handle, const LoadingOptions& options, qwr::u8string* pImagePath ); 47 | 48 | /// @throw qwr::QwrException 49 | /// @throw smp::JsException 50 | void GetAlbumArtAsync( HWND hWnd, const metadb_handle_ptr& handle, const LoadingOptions& options ); 51 | 52 | } // namespace smp::art 53 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/utils/art_loading_options.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "art_loading_options.h" 4 | 5 | #include 6 | 7 | namespace smp::art 8 | { 9 | 10 | LoadingOptions::LoadingOptions( uint32_t artId, bool fallbackToStubImage, bool loadOnlyEmbedded, bool onlyGetPath ) 11 | : artId( artId ) 12 | , fallbackToStubImage( fallbackToStubImage ) 13 | , loadOnlyEmbedded( loadOnlyEmbedded ) 14 | , onlyGetPath( onlyGetPath ) 15 | { 16 | (void)smp::art::GetGuidForArtId( artId ); 17 | } 18 | 19 | LoadingOptions::LoadingOptions( const LoadingOptions& other ) 20 | : artId( other.artId ) 21 | , fallbackToStubImage( other.fallbackToStubImage ) 22 | , loadOnlyEmbedded( other.loadOnlyEmbedded ) 23 | , onlyGetPath( other.onlyGetPath ) 24 | { 25 | } 26 | 27 | } // namespace smp::art 28 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/utils/art_loading_options.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace smp::art 6 | { 7 | 8 | struct LoadingOptions 9 | { 10 | /// @throw qwr::QwrException 11 | LoadingOptions( uint32_t artId, bool fallbackToStubImage, bool loadOnlyEmbedded, bool onlyGetPath ); 12 | LoadingOptions( const LoadingOptions& other ); 13 | 14 | const uint32_t artId; 15 | const bool fallbackToStubImage; 16 | const bool loadOnlyEmbedded; 17 | const bool onlyGetPath; 18 | }; 19 | 20 | } // namespace smp::art 21 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/utils/colour_helpers.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace smp::colour 4 | { 5 | 6 | constexpr [[nodiscard]] COLORREF ArgbToColorref( DWORD argb ) 7 | { 8 | return RGB( argb >> RED_SHIFT, argb >> GREEN_SHIFT, argb >> BLUE_SHIFT ); 9 | } 10 | 11 | constexpr [[nodiscard]] DWORD ColorrefToArgb( COLORREF color ) 12 | { 13 | // COLORREF : 0x00bbggrr 14 | // ARGB : 0xaarrggbb 15 | return ( GetRValue( color ) << RED_SHIFT ) 16 | | ( GetGValue( color ) << GREEN_SHIFT ) 17 | | ( GetBValue( color ) << BLUE_SHIFT ) 18 | | 0xff000000; 19 | } 20 | 21 | } // namespace smp::colour 22 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/utils/edit_text.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace smp 6 | { 7 | 8 | /// @throw qwr::QwrException 9 | void EditTextFile( HWND hParent, const std::filesystem::path& file, bool isPanelScript, bool isModal ); 10 | 11 | /// @throw qwr::QwrException 12 | void EditText( HWND hParent, qwr::u8string& text, bool isPanelScript ); 13 | 14 | } // namespace smp 15 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/utils/fmt_pfc_adaptor.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | template <> 4 | struct fmt::formatter : formatter 5 | { 6 | // parse is inherited from formatter. 7 | template 8 | auto format( const pfc::string8_fast& str, FormatContext& ctx ) 9 | { 10 | return formatter::format( string_view{ str.c_str(), str.length() }, ctx ); 11 | } 12 | }; 13 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/utils/gdi_error_helpers.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include 6 | 7 | namespace qwr::error 8 | { 9 | 10 | [[nodiscard]] const char* GdiErrorCodeToText( Gdiplus::Status errorCode ); 11 | 12 | /// @throw qwr::QwrException 13 | void CheckGdi( Gdiplus::Status gdiStatus, std::string_view functionName ); 14 | 15 | /// @throw qwr::QwrException 16 | template 17 | void CheckGdiPlusObject( const std::unique_ptr& obj, const T_Parent* pParentObj = nullptr ) 18 | { 19 | // GetLastStatus() resets status, so it needs to be saved here 20 | const auto status = [&obj, pParentObj]() -> std::optional { 21 | if ( obj ) 22 | { 23 | return obj->GetLastStatus(); 24 | } 25 | 26 | if ( pParentObj ) 27 | { 28 | return pParentObj->GetLastStatus(); 29 | } 30 | 31 | return std::nullopt; 32 | }(); 33 | 34 | if ( obj && Gdiplus::Status::Ok == status ) 35 | { 36 | return; 37 | } 38 | 39 | if ( status ) 40 | { 41 | throw qwr::QwrException( "Failed to create GdiPlus object ({:#x}): {}", static_cast( *status ), GdiErrorCodeToText( *status ) ); 42 | } 43 | else 44 | { 45 | throw qwr::QwrException( "Failed to create GdiPlus object" ); 46 | } 47 | } 48 | 49 | } // namespace qwr::error 50 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/utils/gdi_helpers.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "gdi_helpers.h" 4 | 5 | namespace smp::gdi 6 | { 7 | 8 | unique_gdi_ptr CreateHBitmapFromGdiPlusBitmap( Gdiplus::Bitmap& bitmap ) 9 | { 10 | const Gdiplus::Rect rect{ 0, 0, static_cast( bitmap.GetWidth() ), static_cast( bitmap.GetHeight() ) }; 11 | Gdiplus::BitmapData bmpdata{}; 12 | 13 | if ( bitmap.LockBits( &rect, Gdiplus::ImageLockModeRead, PixelFormat32bppPARGB, &bmpdata ) != Gdiplus::Ok ) 14 | { // Error 15 | return CreateUniquePtr( HBITMAP( nullptr ) ); 16 | } 17 | 18 | BITMAP bm{}; 19 | bm.bmType = 0; 20 | bm.bmWidth = bmpdata.Width; 21 | bm.bmHeight = bmpdata.Height; 22 | bm.bmWidthBytes = bmpdata.Stride; 23 | bm.bmPlanes = 1; 24 | bm.bmBitsPixel = 32; 25 | bm.bmBits = bmpdata.Scan0; 26 | 27 | HBITMAP hBitmap = CreateBitmapIndirect( &bm ); 28 | bitmap.UnlockBits( &bmpdata ); 29 | 30 | return CreateUniquePtr( hBitmap ); 31 | } 32 | 33 | } // namespace smp::gdi 34 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/utils/guid_helpers.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "guid_helpers.h" 4 | 5 | namespace smp::utils 6 | { 7 | 8 | GUID GenerateGuid() 9 | { 10 | GUID guid{}; 11 | (void)CoCreateGuid( &guid ); //< should not fail 12 | return guid; 13 | } 14 | 15 | std::wstring GuidToStr( const GUID& guid ) 16 | { 17 | std::wstring guidStr; 18 | 19 | guidStr.resize( 64 ); 20 | const auto strSizeWithTerminator = StringFromGUID2( guid, guidStr.data(), guidStr.size() ); 21 | guidStr.resize( strSizeWithTerminator - 1 ); 22 | 23 | return guidStr; 24 | } 25 | 26 | std::optional StrToGuid( const std::wstring& str ) 27 | { 28 | GUID guid; 29 | HRESULT hr = IIDFromString( str.c_str(), &guid ); 30 | if ( FAILED( hr ) ) 31 | { 32 | return std::nullopt; 33 | } 34 | 35 | return guid; 36 | } 37 | 38 | size_t GuidHasher::operator()( const GUID& guid ) const 39 | { 40 | const uint64_t guid64_1 = 41 | ( static_cast( guid.Data1 ) << 32 ) 42 | | ( static_cast( guid.Data2 ) << 16 ) 43 | | guid.Data3; 44 | uint64_t guid64_2; 45 | memcpy( &guid64_2, guid.Data4, sizeof( guid.Data4 ) ); 46 | 47 | std::hash hash; 48 | return hash( guid64_1 ) ^ hash( guid64_2 ); 49 | } 50 | 51 | } // namespace smp::utils 52 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/utils/guid_helpers.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace smp::utils 6 | { 7 | 8 | [[nodiscard]] GUID GenerateGuid(); 9 | [[nodiscard]] std::wstring GuidToStr( const GUID& guid ); 10 | [[nodiscard]] std::optional StrToGuid( const std::wstring& str ); 11 | 12 | struct GuidHasher 13 | { 14 | size_t operator()( const GUID& guid ) const; 15 | }; 16 | 17 | } // namespace smp::utils 18 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/utils/image_helpers.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | namespace smp::image 8 | { 9 | 10 | [[nodiscard]] std::tuple 11 | GetResizedImageSize( const std::tuple& currentDimension, 12 | const std::tuple& maxDimensions ) noexcept; 13 | 14 | /// @return 0 - error, task id - otherwise 15 | [[nodiscard]] uint32_t LoadImageAsync( HWND hWnd, const std::wstring& imagePath ); 16 | 17 | /// @return nullptr - error, pointer to loaded image - otherwise 18 | [[nodiscard]] std::unique_ptr 19 | LoadImage( const std::wstring& imagePath ); 20 | 21 | /// @remark WIC loads images 'eagerly' which makes loading operation slower by x100, so it should be used only as a last resort 22 | [[nodiscard]] std::unique_ptr 23 | LoadImageWithWIC( IStreamPtr pStream ); 24 | 25 | } // namespace smp::image 26 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/utils/js_exception.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "js_exception.h" 4 | 5 | namespace smp 6 | { 7 | 8 | _Post_satisfies_( checkValue ) void JsException::ExpectTrue( bool checkValue ) 9 | { 10 | if ( !checkValue ) 11 | { 12 | throw JsException(); 13 | } 14 | } 15 | 16 | void JsException::ExpectTrue( _Post_notnull_ void* checkValue ) 17 | { 18 | return ExpectTrue( static_cast( checkValue ) ); 19 | } 20 | 21 | } // namespace smp 22 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/utils/js_exception.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace smp 6 | { 7 | 8 | /// @brief This exception should be used when JS exception is set 9 | class JsException 10 | : public std::exception 11 | { 12 | public: 13 | JsException() = default; 14 | virtual ~JsException() = default; 15 | 16 | _Post_satisfies_( checkValue ) static void ExpectTrue( bool checkValue ); 17 | 18 | /// @details This overload is needed for SAL: it can't understand that `(bool)ptr == true` is the same as `ptr != null` 19 | static void ExpectTrue( _Post_notnull_ void* checkValue ); 20 | }; 21 | 22 | } // namespace smp 23 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/utils/location_processor.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "location_processor.h" 4 | 5 | namespace smp::utils 6 | { 7 | 8 | OnProcessLocationsNotify_InsertHandles::OnProcessLocationsNotify_InsertHandles( int playlistIdx, UINT baseIdx, bool shouldSelect ) 9 | : playlistIdx_( playlistIdx ) 10 | , baseIdx_( baseIdx ) 11 | , shouldSelect_( shouldSelect ) 12 | { 13 | } 14 | 15 | void OnProcessLocationsNotify_InsertHandles::on_completion( metadb_handle_list_cref items ) 16 | { 17 | auto api = playlist_manager::get(); 18 | const size_t adjustedPlIdx = ( playlistIdx_ == -1 ? api->get_active_playlist() : playlistIdx_ ); 19 | if ( adjustedPlIdx >= api->get_playlist_count() 20 | || ( api->playlist_lock_get_filter_mask( adjustedPlIdx ) & playlist_lock::filter_add ) ) 21 | { 22 | return; 23 | } 24 | 25 | pfc::bit_array_val selection( shouldSelect_ ); 26 | api->playlist_insert_items( adjustedPlIdx, baseIdx_, items, selection ); 27 | if ( shouldSelect_ ) 28 | { 29 | api->set_active_playlist( adjustedPlIdx ); 30 | api->playlist_set_focus_item( adjustedPlIdx, baseIdx_ ); 31 | } 32 | } 33 | 34 | void OnProcessLocationsNotify_InsertHandles::on_aborted() 35 | { 36 | } 37 | 38 | } // namespace smp::utils 39 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/utils/location_processor.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace smp::utils 4 | { 5 | 6 | class OnProcessLocationsNotify_InsertHandles 7 | : public process_locations_notify 8 | { 9 | public: 10 | OnProcessLocationsNotify_InsertHandles( int playlistIdx, UINT baseIdx, bool shouldSelect ); 11 | 12 | void on_completion( metadb_handle_list_cref items ) override; 13 | void on_aborted() override; 14 | 15 | private: 16 | const int playlistIdx_; 17 | const size_t baseIdx_; 18 | const bool shouldSelect_; 19 | }; 20 | 21 | } // namespace smp::utils 22 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/utils/logging.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "logging.h" 4 | 5 | namespace smp::utils 6 | { 7 | 8 | void LogError( const qwr::u8string& message ) 9 | { 10 | FB2K_console_formatter() << fmt::format( 11 | SMP_UNDERSCORE_NAME ":\n" 12 | "Error:\n" 13 | "{}\n ", 14 | message ); 15 | } 16 | 17 | void LogWarning( const qwr::u8string& message ) 18 | { 19 | FB2K_console_formatter() << fmt::format( 20 | SMP_UNDERSCORE_NAME ":\n" 21 | "Warning:\n" 22 | "{}\n", 23 | message ); 24 | } 25 | 26 | void LogDebug( const qwr::u8string& message ) 27 | { 28 | FB2K_console_formatter() << fmt::format( 29 | SMP_UNDERSCORE_NAME ":\n" 30 | "Debug:\n" 31 | "{}\n", 32 | message ); 33 | } 34 | 35 | } // namespace smp::utils 36 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/utils/logging.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace smp::utils 6 | { 7 | 8 | void LogError( const qwr::u8string& message ); 9 | void LogWarning( const qwr::u8string& message ); 10 | void LogDebug( const qwr::u8string& message ); 11 | 12 | } // namespace smp::utils 13 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/utils/make_unique_ptr.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | namespace smp::utils 4 | { 5 | 6 | template 7 | [[nodiscard]] std::unique_ptr make_unique_with_dtor( T* t, D d ) 8 | { 9 | return std::unique_ptr( t, d ); 10 | } 11 | 12 | } // namespace smp::utils 13 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/utils/md5.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | namespace smp 7 | { 8 | 9 | class MD5 10 | { 11 | static constexpr size_t kBlocksize = 64; 12 | 13 | public: 14 | MD5(); 15 | MD5( std::span input ); 16 | 17 | void Update( std::span input ); 18 | void Finalize(); 19 | 20 | [[nodiscard]] std::string HexDigest() const; 21 | 22 | private: 23 | void Init(); 24 | void Transform( const uint8_t block[kBlocksize] ); 25 | static void Decode( uint32_t output[], const uint8_t input[], size_t len ); 26 | static void Encode( uint8_t output[], const uint32_t input[], size_t len ); 27 | 28 | private: 29 | bool finalized = false; 30 | uint8_t buffer[kBlocksize]; // bytes that didn't fit in last 64 byte chunk 31 | uint32_t count[2]; // 64bit counter for number of bits (lo, hi) 32 | uint32_t state[4]; // digest so far 33 | uint8_t digest[16]; // the result 34 | }; 35 | 36 | [[nodiscard]] std::string CalculateMd5( std::span input ); 37 | 38 | } // namespace smp 39 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/utils/menu_helpers.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace smp::utils 6 | { 7 | 8 | /// @throw qwr::QwrException 9 | void ExecuteContextCommandByName( const qwr::u8string& name, const metadb_handle_list& p_handles, uint32_t flags ); 10 | 11 | /// @throw qwr::QwrException 12 | void ExecuteMainmenuCommandByName( const qwr::u8string& name ); 13 | 14 | /// @throw qwr::QwrException 15 | uint32_t GetMainmenuCommandStatusByName( const qwr::u8string& name ); 16 | 17 | } // namespace smp::utils 18 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/utils/path_helpers.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "path_helpers.h" 4 | 5 | namespace fs = std::filesystem; 6 | 7 | namespace smp::utils 8 | { 9 | 10 | std::vector GetFilesRecursive( const fs::path& path ) 11 | { 12 | try 13 | { 14 | assert( fs::is_directory( path ) ); 15 | 16 | std::vector files; 17 | 18 | for ( const auto& it: fs::recursive_directory_iterator( path ) ) 19 | { 20 | if ( it.is_directory() ) 21 | { 22 | continue; 23 | } 24 | files.emplace_back( it.path() ); 25 | } 26 | 27 | return files; 28 | } 29 | catch ( const fs::filesystem_error& e ) 30 | { 31 | throw qwr::QwrException( e ); 32 | } 33 | } 34 | 35 | } // namespace smp::utils 36 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/utils/path_helpers.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace smp::utils 6 | { 7 | 8 | /// @throw qwr::QwrException 9 | [[nodiscard]] std::vector 10 | GetFilesRecursive( const std::filesystem::path& path ); 11 | 12 | } // namespace smp::utils 13 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/utils/resource_helpers.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "resource_helpers.h" 4 | 5 | namespace smp 6 | { 7 | 8 | std::optional LoadStringResource( int resourceId, const char* resourceType ) 9 | { 10 | SMP_CLANG_WARNING_PUSH 11 | // suppress warning from uMAKEINTRESOURCE 12 | SMP_CLANG_SUPPRESS_WARNING( "-Wint-to-pointer-cast" ) 13 | puResource puRes = uLoadResource( core_api::get_my_instance(), uMAKEINTRESOURCE( resourceId ), resourceType ); 14 | SMP_CLANG_WARNING_POP 15 | if ( !puRes ) 16 | { 17 | return std::nullopt; 18 | } 19 | 20 | return qwr::u8string{ static_cast( puRes->GetPointer() ), puRes->GetSize() }; 21 | } 22 | 23 | } // namespace smp 24 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/utils/resource_helpers.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace smp 6 | { 7 | 8 | [[nodiscard]] std::optional 9 | LoadStringResource( int resourceId, const char* resourceType ); 10 | 11 | } // namespace smp 12 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/utils/stackblur.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace smp::utils 4 | { 5 | 6 | /* 7 | The Stack Blur Algorithm was invented by Mario Klingemann, 8 | mario@quasimondo.com and described here: 9 | http://incubator.quasimondo.com/processing/fast_blur_deluxe.php 10 | 11 | This is C++ RGBA (32 bit color) multi-threaded version 12 | by Victor Laskin (victor.laskin@gmail.com) 13 | More details: http://vitiy.info/stackblur-algorithm-multi-threaded-blur-for-cpp 14 | */ 15 | 16 | void stack_blur_filter( Gdiplus::Bitmap& img, int radius ); 17 | 18 | } // namespace smp::utils 19 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/utils/stacktrace.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | namespace smp 4 | { 5 | 6 | LONG WINAPI SehHandler_ConsoleStacktrace( EXCEPTION_POINTERS* pExp, DWORD dwExpCode ); 7 | 8 | void GetStackTrace( std::span stackTrace, 9 | HANDLE hProcess = nullptr, 10 | HANDLE hThread = nullptr, 11 | const CONTEXT* pContext = nullptr ); 12 | 13 | } // namespace smp 14 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/utils/text_helpers.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | namespace smp::utils 7 | { 8 | 9 | [[nodiscard]] size_t GetTextHeight( HDC hdc, std::wstring_view text ); 10 | [[nodiscard]] size_t GetTextWidth( HDC hdc, std::wstring_view text, bool accurate = false ); 11 | 12 | struct WrappedTextLine 13 | { 14 | std::wstring_view text; 15 | size_t width; 16 | }; 17 | [[nodiscard]] std::vector WrapText( HDC hdc, const std::wstring& text, size_t maxWidth ); 18 | 19 | struct StrCmpLogicalCmpData 20 | { 21 | StrCmpLogicalCmpData( const std::wstring& textId, size_t index ); 22 | StrCmpLogicalCmpData( const qwr::u8string_view& textId, size_t index ); 23 | 24 | std::wstring textId; ///< if set manually (not via ctor), must be prepended with ` ` for StrCmpLogicalW bug workaround 25 | size_t index; 26 | }; 27 | 28 | template 29 | bool StrCmpLogicalCmp( const StrCmpLogicalCmpData& a, const StrCmpLogicalCmpData& b ) 30 | { 31 | int ret = direction * StrCmpLogicalW( a.textId.c_str(), b.textId.c_str() ); 32 | if ( !ret ) 33 | { 34 | return ( a.index < b.index ); 35 | } 36 | else 37 | { 38 | return ( ret < 0 ); 39 | } 40 | } 41 | 42 | } // namespace smp::utils 43 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/utils/thread_pool_instance.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "thread_pool_instance.h" 4 | 5 | namespace smp 6 | { 7 | 8 | qwr::ThreadPool& GetThreadPoolInstance() 9 | { 10 | static qwr::ThreadPool tp; 11 | return tp; 12 | } 13 | 14 | } // namespace smp 15 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/utils/thread_pool_instance.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace smp 6 | { 7 | 8 | [[nodiscard]] qwr::ThreadPool& GetThreadPoolInstance(); 9 | 10 | } // namespace smp 11 | -------------------------------------------------------------------------------- /foo_spider_monkey_panel/utils/zip_utils.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | struct mz_zip_archive; 6 | 7 | namespace smp 8 | { 9 | 10 | class ZipPacker 11 | { 12 | public: 13 | /// @throw SmpException 14 | [[nodiscard]] ZipPacker( const std::filesystem::path& zipFile ); 15 | 16 | /// @remark Deletes zip file on error 17 | ~ZipPacker(); 18 | 19 | /// @throw SmpException 20 | void AddFile( const std::filesystem::path& srcFile, const qwr::u8string& destFileName ); 21 | /// @throw SmpException 22 | void AddFolder( const std::filesystem::path& srcFolder, const qwr::u8string& destFolderName = "" ); 23 | /// @throw SmpException 24 | void Finish(); 25 | 26 | private: 27 | std::unique_ptr pZip_; 28 | std::filesystem::path zipFile_; 29 | }; 30 | 31 | /// @throw SmpException 32 | void UnpackZip( const std::filesystem::path& zipFile, const std::filesystem::path& dstFolder ); 33 | 34 | } // namespace smp 35 | -------------------------------------------------------------------------------- /licenses/AtlScintilla.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2005 by Gilad Novik. 2 | Copyright (c) 2006 by Reece Dunn. 3 | 4 | This software is provided 'as-is', without any express or implied 5 | warranty. In no event will the authors be held liable for any damages 6 | arising from the use of this software. 7 | 8 | Permission is granted to anyone to use this software for any purpose, 9 | including commercial applications, and to alter it and redistribute it 10 | freely, subject to the following restrictions: 11 | 12 | 1. The origin of this software must not be misrepresented; you must not 13 | claim that you wrote the original software. If you use this software 14 | in a product, an acknowledgement in the product documentation would be 15 | appreciated but is not required. 16 | 2. Altered source versions must be plainly marked as such, and must not be 17 | misrepresented as being the original software. 18 | 3. This notice may not be removed or altered from any source distribution. -------------------------------------------------------------------------------- /licenses/CPropertyList.txt: -------------------------------------------------------------------------------- 1 | Written by Bjarke Viksoe (bjarke@viksoe.dk) 2 | Copyright (c) 2001-2003 Bjarke Viksoe. 3 | Thanks to Pascal Binggeli for fixing the disabled items. 4 | Column resize supplied by Remco Verhoef, thanks. 5 | Also thanks to Daniel Bowen, Alex Kamenev and others for fixes. 6 | 7 | This code may be used in compiled form in any way you desire. This 8 | source file may be redistributed by any means PROVIDING it is 9 | not sold for profit without the authors written consent, and 10 | providing that this notice and the authors name is included. 11 | 12 | This file is provided "as is" with no expressed or implied warranty. 13 | The author accepts no liability if it causes any damage to you or your 14 | computer whatsoever. It's free, so don't hassle me about it. 15 | -------------------------------------------------------------------------------- /licenses/Columns UI SDK.txt: -------------------------------------------------------------------------------- 1 | Columns UI SDK 2 | Copyright (c) musicmusic and contributors 2003-2015 -------------------------------------------------------------------------------- /licenses/DispatchPtr.txt: -------------------------------------------------------------------------------- 1 | [This is a BSD license] 2 | 3 | Copyright (c) 2000-2015, Mike Morearty 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | 1. Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | 2. Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | 3. Neither the name of the copyright holder nor the names of its contributors 17 | may be used to endorse or promote products derived from this software 18 | without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 21 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 22 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /licenses/JSON for Modern C++.txt: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2013-2018 Niels Lohmann 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /licenses/JScript Panel.txt: -------------------------------------------------------------------------------- 1 | This is free and unencumbered software released into the public domain. 2 | 3 | Anyone is free to copy, modify, publish, use, compile, sell, or 4 | distribute this software, either in source code form or as a compiled 5 | binary, for any purpose, commercial or non-commercial, and by any 6 | means. 7 | 8 | In jurisdictions that recognize copyright laws, the author or authors 9 | of this software dedicate any and all copyright interest in the 10 | software to the public domain. We make this dedication for the benefit 11 | of the public at large and to the detriment of our heirs and 12 | successors. We intend this dedication to be an overt act of 13 | relinquishment in perpetuity of all present and future rights to this 14 | software under copyright law. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | For more information, please refer to 25 | -------------------------------------------------------------------------------- /licenses/KMeans.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Marcos Castro de Souza 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /licenses/PFC.txt: -------------------------------------------------------------------------------- 1 | Copyright (C) 2002-2019 Peter Pawlowski 2 | 3 | This software is provided 'as-is', without any express or implied 4 | warranty. In no event will the authors be held liable for any damages 5 | arising from the use of this software. 6 | 7 | Permission is granted to anyone to use this software for any purpose, 8 | including commercial applications, and to alter it and redistribute it 9 | freely, subject to the following restrictions: 10 | 11 | 1. The origin of this software must not be misrepresented; you must not 12 | claim that you wrote the original software. If you use this software 13 | in a product, an acknowledgment in the product documentation would be 14 | appreciated but is not required. 15 | 2. Altered source versions must be plainly marked as such, and must not be 16 | misrepresented as being the original software. 17 | 3. This notice may not be removed or altered from any source distribution. -------------------------------------------------------------------------------- /licenses/Scintilla.txt: -------------------------------------------------------------------------------- 1 | Copyright 1998-2003 by Neil Hodgson 2 | 3 | All Rights Reserved 4 | 5 | Permission to use, copy, modify, and distribute this software and its 6 | documentation for any purpose and without fee is hereby granted, 7 | provided that the above copyright notice appear in all copies and that 8 | both that copyright notice and this permission notice appear in 9 | supporting documentation. 10 | 11 | NEIL HODGSON DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS 12 | SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 13 | AND FITNESS, IN NO EVENT SHALL NEIL HODGSON BE LIABLE FOR ANY 14 | SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 15 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 16 | WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 17 | TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE 18 | OR PERFORMANCE OF THIS SOFTWARE. 19 | -------------------------------------------------------------------------------- /licenses/StackBlur.txt: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2010 Mario Klingemann 4 | 5 | Permission is hereby granted, free of charge, to any person 6 | obtaining a copy of this software and associated documentation 7 | files (the "Software"), to deal in the Software without 8 | restriction, including without limitation the rights to use, 9 | copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the 11 | Software is furnished to do so, subject to the following 12 | conditions: 13 | 14 | The above copyright notice and this permission notice shall be 15 | included in all copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 19 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 20 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 21 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 22 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 23 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 24 | OTHER DEALINGS IN THE SOFTWARE. 25 | -------------------------------------------------------------------------------- /licenses/UI Helpers.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) Reupen Shah 2003-2017 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 5 | 6 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 7 | 8 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 9 | 10 | 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. 11 | 12 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /licenses/fmt.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2012 - present, Victor Zverovich 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | 22 | --- Optional exception to the license --- 23 | 24 | As an exception, if, as a result of your compiling your source code, portions 25 | of this Software are embedded into a machine-executable object form of such 26 | source code, you may redistribute such embedded portions in such object form 27 | without including the above copyright and permission notices. 28 | -------------------------------------------------------------------------------- /licenses/foobar2000 SDK.txt: -------------------------------------------------------------------------------- 1 | foobar2000 1.5 SDK 2 | Copyright (c) 2001-2019, Peter Pawlowski 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 6 | 7 | Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 8 | Neither the name of the author nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. 9 | 10 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 11 | 12 | Note that separate less restrictive licenses apply to the included 'pfc' and 'libPPUI' libraries. See license files included in respective folders for details. 13 | -------------------------------------------------------------------------------- /licenses/miniz.txt: -------------------------------------------------------------------------------- 1 | Copyright 2013-2014 RAD Game Tools and Valve Software 2 | Copyright 2010-2014 Rich Geldreich and Tenacious Software LLC 3 | 4 | All Rights Reserved. 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in 14 | all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /licenses/timsort-cpp.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2018 Timothy Van Slyke 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. 20 | -------------------------------------------------------------------------------- /miniz/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2013-2014 RAD Game Tools and Valve Software 2 | Copyright 2010-2014 Rich Geldreich and Tenacious Software LLC 3 | 4 | All Rights Reserved. 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in 14 | all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "devDependencies": { 3 | "jsdoc": "latest", 4 | "patch-package": "latest", 5 | "tui-jsdoc-template": "^1.2.2" 6 | }, 7 | "scripts": { 8 | "postinstall": "patch-package --patch-dir scripts/node_patches" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /props/local_dependencies/miniz.props: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | <_PropertySheetDisplayName>miniz 7 | 8 | 9 | $(SolutionDir)..\miniz\;$(IncludePath) 10 | 11 | 12 | -------------------------------------------------------------------------------- /props/local_dependencies/mozjs.props: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | <_PropertySheetDisplayName>mozjs 7 | 8 | 9 | $(MainDir)mozjs\ 10 | $(MozJsDirectory)$(Configuration)\bin\ 11 | $(MozJsDirectory)$(Configuration)\lib\ 12 | $(MozJsDirectory)$(Configuration)\include\ 13 | mozjs-91.lib 14 | js_static.lib;nspr4.lib;plc4.lib;plds4.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;wsock32.lib;advapi32.lib;mozglue.lib 15 | 16 | 17 | $(MozJsIncludeDirectory);$(IncludePath) 18 | 19 | 20 | 21 | $(MozJsLibDirectory);%(AdditionalLibraryDirectories) 22 | $(MozJsDependenciesDynamic);%(AdditionalDependencies) 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /props/local_dependencies/property_list.props: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | <_PropertySheetDisplayName>property_list 7 | 8 | 9 | $(SolutionDir)..\PropertyList\include\;$(IncludePath) 10 | 11 | 12 | -------------------------------------------------------------------------------- /props/submodules/fb2k_utils.props: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | <_PropertySheetDisplayName>fb2k_utils 7 | 8 | 9 | $(SolutionDir)..\submodules\fb2k_utils\ 10 | $(QwrFb2kUtilsRootDir)props\ 11 | 12 | 13 | $(QwrFb2kUtilsRootDir)src\;$(IncludePath) 14 | 15 | -------------------------------------------------------------------------------- /props/submodules/submodules.props: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | <_PropertySheetDisplayName>submodules 7 | 8 | 9 | $(SolutionDir)..\submodules\ 10 | 11 | 12 | $(SubmodulesDirectory);$(IncludePath) 13 | 14 | -------------------------------------------------------------------------------- /scripts/README.md: -------------------------------------------------------------------------------- 1 | ### Main scripts 2 | - setup.py - Set up everything, so that project can be built. 3 | - pack_component.py - Pack project binaries to .fb2k-component archive. 4 | - generate_docs.py - Generate HTML docs from JsDoc docs. 5 | 6 | ### Auxiliary scripts 7 | - update_submodules.py - Update submodules to their latest version. 8 | - update_gh_pages.py - Update gh-pages folder with latest generated content. 9 | -------------------------------------------------------------------------------- /scripts/additional_files/mozjs_debug.vcxitems: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | $(MSBuildAllProjects);$(MSBuildThisFileFullPath) 5 | true 6 | 7 | 8 | true 9 | {D8B31234-916F-43CD-A29A-1B121BB1D980} 10 | 11 | 12 | 13 | %(AdditionalIncludeDirectories);$(MSBuildThisFileDirectory) 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /scripts/additional_files/mozjs_release.vcxitems: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | $(MSBuildAllProjects);$(MSBuildThisFileFullPath) 5 | true 6 | 7 | 8 | true 9 | {F0DFCA92-260F-4729-92DD-77FCD6C12938} 10 | 11 | 12 | 13 | %(AdditionalIncludeDirectories);$(MSBuildThisFileDirectory) 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /scripts/additional_files/wtl.vcxitems: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | $(MSBuildAllProjects);$(MSBuildThisFileFullPath) 5 | true 6 | 7 | 8 | true 9 | {633A5B67-2FBD-4491-8B51-5F2C72784EAC} 10 | 11 | 12 | 13 | %(AdditionalIncludeDirectories);$(MSBuildThisFileDirectory) 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /scripts/call_wrapper.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import traceback 4 | import sys 5 | 6 | class SkippedError(Exception): 7 | def __init__(self): 8 | self.message = "Skipped error" 9 | 10 | def final_call_decorator(start_msg: str, 11 | success_msg: str, 12 | failure_msg: str): 13 | def f_decorator(f): 14 | def wrapper(*args, **kwds): 15 | print(start_msg) 16 | try: 17 | f(*args, **kwds) 18 | print(success_msg) 19 | sys.exit(0) 20 | except SkippedError: 21 | print(failure_msg, file=sys.stderr) 22 | sys.exit(1) 23 | except Exception: 24 | traceback.print_exc(file=sys.stderr) 25 | print(failure_msg, file=sys.stderr) 26 | sys.exit(1) 27 | 28 | return wrapper 29 | 30 | return f_decorator 31 | -------------------------------------------------------------------------------- /scripts/configure_scintilla.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import subprocess 4 | from pathlib import Path 5 | 6 | import call_wrapper 7 | 8 | def configure(): 9 | cur_dir = Path(__file__).parent.absolute() 10 | root_dir = cur_dir.parent 11 | scintilla_dir = root_dir/"submodules"/"scintilla" 12 | assert(scintilla_dir.exists() and scintilla_dir.is_dir()) 13 | lexers_dir = scintilla_dir/"lexers" 14 | 15 | for lexer in lexers_dir.glob("*"): 16 | if (lexer.name != "LexCPP.cxx" ): 17 | lexer.unlink() 18 | 19 | subprocess.check_call("py LexGen.py", cwd=scintilla_dir/"scripts", shell=True) 20 | subprocess.check_call("py LexillaGen.py", cwd=scintilla_dir/"lexilla"/"scripts", shell=True) 21 | 22 | if __name__ == '__main__': 23 | call_wrapper.final_call_decorator( 24 | "Configuring Scintilla", 25 | "Configuring Scintilla: success", 26 | "Configuring Scintilla: failure!" 27 | )(configure)() 28 | -------------------------------------------------------------------------------- /scripts/doc/conf.json: -------------------------------------------------------------------------------- 1 | { 2 | "opts": { 3 | "template": "C:/projects/foo-spider-monkey-panel/node_modules/tui-jsdoc-template" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /scripts/generate_package_info.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import json 4 | import subprocess 5 | from pathlib import Path 6 | 7 | import call_wrapper 8 | 9 | def generate(): 10 | cur_dir = Path(__file__).parent.absolute() 11 | root_dir = cur_dir.parent 12 | output_dir = root_dir/"_result"/"AllPlatforms"/"generated" 13 | output_dir.mkdir(parents=True, exist_ok=True) 14 | 15 | output_file = output_dir/'doc_package_info.json' 16 | output_file.unlink(missing_ok=True) 17 | 18 | tag = subprocess.check_output("git describe --tags", shell=True).decode('ascii').strip() 19 | if (tag.startswith('v')): 20 | # JsDoc template adds `v` to the version, hence the removal 21 | tag = tag[1:] 22 | 23 | data = { 24 | "name": "Spider Monkey Panel", 25 | "version": tag 26 | } 27 | 28 | with open(output_file, 'w') as output: 29 | json.dump(data, output) 30 | 31 | print(f"Generated file: {output_file}") 32 | 33 | if __name__ == '__main__': 34 | call_wrapper.final_call_decorator( 35 | "Generating package info for docs", 36 | "Generating package info: success", 37 | "Generating package info: failure!" 38 | )(generate)() 39 | -------------------------------------------------------------------------------- /scripts/node_patches/tui-jsdoc-template+1.2.2.patch: -------------------------------------------------------------------------------- 1 | diff --git a/node_modules/tui-jsdoc-template/static/styles/tui-doc.css b/node_modules/tui-jsdoc-template/static/styles/tui-doc.css 2 | index aec9ed9..5171a0c 100644 3 | --- a/node_modules/tui-jsdoc-template/static/styles/tui-doc.css 4 | +++ b/node_modules/tui-jsdoc-template/static/styles/tui-doc.css 5 | @@ -221,9 +221,9 @@ ul, ol, li {list-style:none; padding-left:0; margin-left:0;} 6 | .main section article table td.type, 7 | .main section article table td.attributes, 8 | .main section article table td.default { 9 | - max-width: 100px; 10 | + max-width: 150px; 11 | min-width: 80px; 12 | - word-break: break-all; 13 | + word-break: break-word; 14 | } 15 | .main section article table td.type, 16 | .main section article table td.attributes { 17 | @@ -483,3 +483,8 @@ span.arrow { 18 | font-size: 8pt; 19 | padding-right: 5px; 20 | } 21 | +span.signature-attributes { 22 | + vertical-align: super; 23 | + font-weight: normal; 24 | +} 25 | + 26 | \ No newline at end of file 27 | -------------------------------------------------------------------------------- /scripts/patch_submodules.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import subprocess 4 | from pathlib import Path 5 | 6 | import call_wrapper 7 | 8 | def patch(): 9 | cur_dir = Path(__file__).parent.absolute() 10 | root_dir = cur_dir.parent 11 | patches = [Path(p) for p in (cur_dir/"patches").glob('*.patch')] 12 | for p in patches: 13 | assert(p.exists() and p.is_file()) 14 | 15 | subprocess.check_call(f"git apply --ignore-whitespace {' '.join(str(p) for p in patches)}", cwd=root_dir, shell=True) 16 | 17 | if __name__ == '__main__': 18 | call_wrapper.final_call_decorator( 19 | "Patching submodules", 20 | "Patching submodules: success", 21 | "Patching submodules: failure!" 22 | )(patch)() 23 | -------------------------------------------------------------------------------- /scripts/patches/mozjs-bug_1243367-wrong_free_call.patch: -------------------------------------------------------------------------------- 1 | diff a/mozjs b/mozjs 2 | --- a/mozjs/Debug/include/js/Utility.h 3 | +++ b/mozjs/Debug/include/js/Utility.h 4 | @@ -408,8 +408,12 @@ static inline void js_free(void* p) { 5 | // TODO: This should call |moz_arena_free(js::MallocArena, p)| but we 6 | // currently can't enforce that all memory freed here was allocated by 7 | // js_malloc(). 8 | - free(p); 9 | + 10 | + // TheQwertiest: workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=1243367 11 | + // it's safe to do so, because `moz_arena_free` calls `free` when built with `--disable-je-malloc` 12 | + moz_arena_free(js::MallocArena, p); 13 | + // free(p); 14 | } 15 | #endif /* JS_USE_CUSTOM_ALLOCATOR */ 16 | 17 | #include 18 | 19 | --- a/mozjs/Release/include/js/Utility.h 20 | +++ b/mozjs/Release/include/js/Utility.h 21 | @@ -408,8 +408,12 @@ static inline void js_free(void* p) { 22 | // TODO: This should call |moz_arena_free(js::MallocArena, p)| but we 23 | // currently can't enforce that all memory freed here was allocated by 24 | // js_malloc(). 25 | - free(p); 26 | + 27 | + // TheQwertiest: workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=1243367 28 | + // it's safe to do so, because `moz_arena_free` calls `free` when built with `--disable-je-malloc` 29 | + moz_arena_free(js::MallocArena, p); 30 | + // free(p); 31 | } 32 | #endif /* JS_USE_CUSTOM_ALLOCATOR */ 33 | 34 | #include 35 | -------------------------------------------------------------------------------- /scripts/patches/mozjs-pretty_function.patch: -------------------------------------------------------------------------------- 1 | diff a/mozjs b/mozjs 2 | --- a/mozjs/Debug/include/mozilla/LinkedList.h 3 | +++ b/mozjs/Debug/include/mozilla/LinkedList.h 4 | @@ -441,7 +441,7 @@ class LinkedList { 5 | "%s has a buggy user: " 6 | "it should have removed all this list's elements before " 7 | "the list's destruction", 8 | - __PRETTY_FUNCTION__); 9 | + __FUNCSIG__); 10 | } 11 | # endif 12 | } 13 | 14 | --- a/mozjs/Release/include/mozilla/LinkedList.h 15 | +++ b/mozjs/Release/include/mozilla/LinkedList.h 16 | @@ -441,7 +441,7 @@ class LinkedList { 17 | "%s has a buggy user: " 18 | "it should have removed all this list's elements before " 19 | "the list's destruction", 20 | - __PRETTY_FUNCTION__); 21 | + __FUNCSIG__); 22 | } 23 | # endif 24 | } 25 | -------------------------------------------------------------------------------- /scripts/patches/smp_2003.patch: -------------------------------------------------------------------------------- 1 | diff --git a/submodules/smp_2003/README.md b/submodules/smp_2003/README.md 2 | deleted file mode 100644 3 | index d7f50c0..0000000 4 | --- a/submodules/smp_2003/README.md 5 | +++ /dev/null 6 | @@ -1,3 +0,0 @@ 7 | -A collection of JavaScript scripts for `foo_spider_monkey_panel` component by `marc2003`. 8 | - 9 | -Note: this is a reupload of `marc2003`'s repository. 10 | -------------------------------------------------------------------------------- /scripts/prepare_submodule_projects.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import shutil 4 | from pathlib import Path 5 | 6 | import call_wrapper 7 | import generate_project_filters 8 | 9 | def prepare(): 10 | cur_dir = Path(__file__).parent.absolute() 11 | root_dir = cur_dir.parent 12 | 13 | projects = [ 14 | ('mozjs_debug.vcxitems', root_dir/'mozjs'/'Debug'), 15 | ('mozjs_release.vcxitems', root_dir/'mozjs'/'Release'), 16 | ('scintilla.vcxproj', root_dir/'submodules'/'scintilla'/'win32'), 17 | ('lexilla.vcxproj', root_dir/'submodules'/'scintilla'/'lexilla'/'src'), 18 | ('wtl.vcxitems', root_dir/'submodules'/'WTL') 19 | ] 20 | 21 | for project_file, project_dir in projects: 22 | shutil.copy2(cur_dir/'additional_files'/project_file, str(project_dir) + '/') 23 | generate_project_filters.generate(project_dir/project_file) 24 | 25 | if __name__ == '__main__': 26 | call_wrapper.final_call_decorator( 27 | 'Preparing project files', 28 | 'Preparing: success', 29 | 'Preparing: failure!' 30 | )(prepare)() 31 | -------------------------------------------------------------------------------- /scripts/unpack_mozjs.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import os 4 | import time 5 | import zipfile 6 | from pathlib import Path 7 | from shutil import rmtree 8 | from zipfile import ZipFile 9 | 10 | import call_wrapper 11 | 12 | def restore_timestamps(zipname, extract_dir): 13 | for f in zipfile.ZipFile(zipname, 'r').infolist(): 14 | fullpath = extract_dir/f.filename 15 | # still need to adjust the dt o/w item will have the current dt 16 | date_time = time.mktime(f.date_time + (0, 0, -1)) 17 | # update dt 18 | os.utime(fullpath, (date_time, date_time)) 19 | 20 | def unpack(): 21 | cur_dir = Path(__file__).parent.absolute() 22 | root_dir = cur_dir.parent 23 | zip_dir = root_dir/"submodules"/"mozjs" 24 | assert(zip_dir.exists() and zip_dir.is_dir()) 25 | 26 | output_dir = root_dir/"mozjs" 27 | if (output_dir.exists()): 28 | rmtree(output_dir) 29 | output_dir.mkdir(parents=True) 30 | 31 | zip_arcs = list(zip_dir.glob("*.zip")) 32 | assert(len(zip_arcs) == 1) 33 | zip_arc = Path(zip_arcs[0]) 34 | assert(zipfile.is_zipfile(zip_arc)) 35 | 36 | with ZipFile(zip_arc) as z: 37 | z.extractall(output_dir) 38 | 39 | restore_timestamps(zip_arc, output_dir) 40 | 41 | if __name__ == '__main__': 42 | call_wrapper.final_call_decorator( 43 | "Unpacking mozjs", 44 | "Unpacking mozjs: success", 45 | "Unpacking mozjs: failure!" 46 | )(unpack)() 47 | --------------------------------------------------------------------------------