Add Haiku frontend
Some checks failed
Build / build-gentoo (push) Successful in 1m22s
Build / download-system-deps (push) Successful in 1m37s
Build / get-source-code (push) Successful in 4m30s
Build / build-appimage (push) Successful in 1m15s
Build / build-android (push) Failing after 4m34s
Build / build-windows (push) Failing after 4m33s

This commit is contained in:
Zachary Hall 2024-11-12 14:53:44 -08:00
parent 4c4481a9ba
commit 8fdf30878b
73 changed files with 2349 additions and 63 deletions

View file

@ -38,9 +38,15 @@ set(BUILD_STATIC_LIBS ON CACHE BOOL "" FORCE)
set(BUILD_SHARED_LIBS OFF CACHE BOOL "" FORCE)
set(JSONCPP_WITH_PKGCONFIG_SUPPORT OFF CACHE BOOL "" FORCE)
set(JSONCPP_WITH_CMAKE_PACKAGE OFF CACHE BOOL "" FORCE)
option(ENABLE_DBUS "Enables DBus support" ON)
option(USE_PORTALS "Enables libportal" ON)
if (UNIX AND NOT APPLE AND NOT ANDROID AND NOT HAIKU)
option(USE_PORTALS "Enables libportal" ON)
option(ENABLE_DBUS "Enables DBus support" ON)
endif()
option(BUILD_LIBFMT "Builds libfmt" OFF)
if(HAIKU)
set(USE_CELT OFF CACHE BOOL "" FORCE)
set(USE_SPEEX OFF CACHE BOOL "" FORCE)
endif()
if (DEFINED EMSCRIPTEN)
option(FOR_WASMER "Enables support for wasmer" OFF)
set(BUILD_STATIC ON CACHE BOOL "" FORCE)
@ -245,7 +251,10 @@ macro(run_protoc)
set(_run_protoc_incpath_expanded)
foreach (INCPATH_IDX ${PROTOC_INCPATH})
list(APPEND _run_protoc_incpath_expanded -I${INCPATH_IDX})
endforeach()
endforeach()
if (HAIKU)
list(APPEND _run_protoc_incpath_expanded -I/boot/system/develop/headers)
endif()
set(_run_protoc_output ${_run_protoc_dst_base}.cc ${_run_protoc_dst_base}.h)# ${_run_protoc_dst_base}-c.c ${_run_protoc_dst_base}-c.h)
unset(_run_protoc_dst_base)
add_custom_command(OUTPUT ${_run_protoc_output} COMMAND ${_PROTOBUF_PROTOC} --cpp_out ${PROTOC_OUTDIR} ${_run_protoc_incpath_expanded} ${PROTOC_SOURCE})# --plugin=${CMAKE_BINARY_DIR}/subprojects/protobuf-c/build-cmake/protoc-gen-c --c_out ${PROTOC_OUTDIR})
@ -275,17 +284,29 @@ function(grpc_proto)
endfunction()
prefix_all(LIBRARY_SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/
config.hpp
backend.hpp
backend.cpp
options.cpp
options.hpp
playback.cpp
playback.h
util.cpp
util.hpp
log.cpp
dbus.cpp
log.hpp
dbus.cpp
dbus.hpp
file_backend.cpp
file_backend.hpp
playback_backend.cpp
playback_backend.hpp
translation.cpp
playback_process.cpp
translation.hpp
playback_process.cpp
playback_process.hpp
base85.cpp
base85.h
)
run_protoc(OUTDIR ${CMAKE_BINARY_DIR}/google/protobuf SOURCE google/protobuf/any.proto OUTVAR _src)
add_library(liblooper STATIC ${LIBRARY_SOURCES})
@ -352,8 +373,24 @@ else()
pkg_check_modules(jsoncpp IMPORTED_TARGET jsoncpp)
endif()
if (NOT BUILD_SDL)
if (CMAKE_SYSTEM_NAME STREQUAL "Haiku")
pkg_check_modules(sdl2 sdl2)
list(REMOVE_ITEM SDL2main)
add_library(SDL2::SDL2 INTERFACE IMPORTED)
target_include_directories(SDL2::SDL2 INTERFACE /boot/system/develop/headers/SDL2 ${sdl2_INCLUDE_DIRS})
target_link_libraries(SDL2::SDL2 INTERFACE ${sdl2_LIBRARIES})
else()
find_package(SDL2 REQUIRED)
endif()
endif()
endif()
if (NOT BUILD_SDL_IMAGE)
if (CMAKE_SYSTEM_NAME STREQUAL "Haiku")
pkg_check_modules(sdl2_image SDL2_image)
add_library(SDL2_image::SDL2_image INTERFACE IMPORTED)
target_include_directories(SDL2_image::SDL2_image INTERFACE ${sdl2_image_INCLUDE_DIRS})
target_link_libraries(SDL2_image::SDL2_image INTERFACE ${sdl2_image_LIBRARIES})
endif()
endif()
if (ENABLE_DBUS)
find_package(sdbus-c++)
if(NOT ${sdbus-c++_FOUND})
@ -365,13 +402,17 @@ else()
if (TARGET SDL2-static)
set(SDL2_TARGET SDL2-static)
endif()
target_link_libraries(liblooper PUBLIC ${SDL2_TARGET} SDL2main ${SDL_MIXER_X_TARGET} ${SOUNDTOUCH_TARGET} libvgmstream libvgmstream_shared ${JSONCPP_TARGET})
target_link_libraries(liblooper PUBLIC ${SDL2_TARGET} ${SDL_MIXER_X_TARGET} ${SOUNDTOUCH_TARGET} libvgmstream libvgmstream_shared ${JSONCPP_TARGET})
endif()
if(BUILD_PROTOBUF)
add_subdirectory(subprojects/protobuf)
else()
if (CMAKE_SYSTEM_NAME STREQUAL "Haiku")
find_package(Protobuf REQUIRED)
else()
find_package(protobuf REQUIRED)
find_package(absl CONFIG REQUIRED)
endif()
endif()
if (${ENABLE_DBUS})
@ -394,7 +435,7 @@ macro(add_ui_backend)
set(USE_PORTALS OFF)
else()
info("Enabling libportal support...")
target_compile_definitions(imgui_ui PRIVATE "PORTALS")
target_compile_definitions(${target} PRIVATE "PORTALS")
endif()
endif()
endmacro()
@ -442,6 +483,9 @@ endmacro()
set(ENABLED_UIS )
set(ENABLED_PLAYBACK_BACKENDS )
ui_backend_subdir(NAME "IMGUI" READABLE_NAME "Dear ImGui" SUBDIR backends/ui/imgui)
if(CMAKE_SYSTEM_NAME STREQUAL "Haiku")
ui_backend_subdir(NAME "HAIKU" READABLE_NAME "Haiku Native" SUBDIR backends/ui/haiku)
endif()
if (NOT (DEFINED EMSCRIPTEN OR DEFINED ANDROID_NDK))
ui_backend_subdir(DEFAULT_OFF NAME "GTK" READABLE_NAME "GTK4" SUBDIR backends/ui/gtk)
endif()
@ -449,7 +493,7 @@ playback_backend_subdir(NAME "VGMSTREAM" READABLE_NAME "VgmStream" SUBDIR backen
playback_backend_subdir(NAME "SDL_MIXER_X" READABLE_NAME "SDL Mixer X" SUBDIR backends/playback/sdl_mixer_x)
playback_backend_subdir(NAME "ZSM" READABLE_NAME "ZSM" SUBDIR backends/playback/zsm)
execute_process(COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/gen_ui_backend_inc.py ${CMAKE_CURRENT_BINARY_DIR} --ui ${ENABLED_UIS} --playback ${ENABLED_PLAYBACK_BACKENDS})
prefix_all(SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/ main.cpp daemon_backend.cpp proxy_backend.cpp)
prefix_all(SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/ main.cpp daemon_backend.cpp daemon_backend.hpp proxy_backend.cpp proxy_backend.hpp)
list(APPEND SOURCES ${CMAKE_CURRENT_BINARY_DIR}/backend_glue.cpp)
if(DEFINED EMSCRIPTEN)
set(CMAKE_EXECUTABLE_SUFFIX ".html")
@ -465,8 +509,21 @@ endfunction()
if (DEFINED ANDROID_NDK OR SHARED_LIB)
add_library(${TARGET_NAME} SHARED ${SOURCES})
else()
if(HAIKU)
set(HAIKU_RES ${CMAKE_SOURCE_DIR}/haiku-res.rdef)
foreach (asset haiku-icon slider-mode text-mode media-playback-start media-playback-stop media-playback-pause view-refresh folder document-open configure application-exit help-contents help-about)
list(APPEND HAIKU_RES ${CMAKE_SOURCE_DIR}/assets/${asset}.rdef)
endforeach()
list(APPEND SOURCES ${CMAKE_BINARY_DIR}/haiku-res.rsrc)
add_custom_command(OUTPUT ${CMAKE_BINARY_DIR}/haiku-res.rsrc COMMAND rc -o ${CMAKE_BINARY_DIR}/haiku-res.rsrc ${HAIKU_RES} DEPENDS ${HAIKU_RES} COMMENT Compiling resources)
endif()
add_executable(${TARGET_NAME} ${SOURCES})
if(HAIKU)
# add_custom_command(TARGET ${TARGET_NAME} POST_BUILD COMMAND resattr -o ${TARGET_NAME} ${CMAKE_BINARY_DIR}/haiku-res.rsrc DEPENDS ${TARGET_NAME} ${CMAKE_BINARY_DIR}/haiku-res.rsrc COMMENT Adding resources to target attributes)
add_custom_command(TARGET ${TARGET_NAME} POST_BUILD COMMAND xres -o ${TARGET_NAME} ${CMAKE_BINARY_DIR}/haiku-res.rsrc DEPENDS ${TARGET_NAME} ${CMAKE_BINARY_DIR}/haiku-res.rsrc COMMENT Adding resources to target)
endif()
endif()
add_dependencies(${TARGET_NAME} looper_assets ${UI_BACKENDS})
if(DEFINED EMSCRIPTEN)

328
CMakeLists.txt.user Normal file
View file

@ -0,0 +1,328 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE QtCreatorProject>
<!-- Written by QtCreator 14.0.1, 2024-11-10T21:49:56. -->
<qtcreator>
<data>
<variable>EnvironmentId</variable>
<value type="QByteArray">{423a81c8-7465-41cf-ba38-7cdac117b05f}</value>
</data>
<data>
<variable>ProjectExplorer.Project.ActiveTarget</variable>
<value type="qlonglong">0</value>
</data>
<data>
<variable>ProjectExplorer.Project.EditorSettings</variable>
<valuemap type="QVariantMap">
<value type="bool" key="EditorConfiguration.AutoIndent">true</value>
<value type="bool" key="EditorConfiguration.AutoSpacesForTabs">false</value>
<value type="bool" key="EditorConfiguration.CamelCaseNavigation">true</value>
<valuemap type="QVariantMap" key="EditorConfiguration.CodeStyle.0">
<value type="QString" key="language">Cpp</value>
<valuemap type="QVariantMap" key="value">
<value type="QByteArray" key="CurrentPreferences">CppGlobal</value>
</valuemap>
</valuemap>
<valuemap type="QVariantMap" key="EditorConfiguration.CodeStyle.1">
<value type="QString" key="language">QmlJS</value>
<valuemap type="QVariantMap" key="value">
<value type="QByteArray" key="CurrentPreferences">QmlJSGlobal</value>
</valuemap>
</valuemap>
<value type="qlonglong" key="EditorConfiguration.CodeStyle.Count">2</value>
<value type="QByteArray" key="EditorConfiguration.Codec">UTF-8</value>
<value type="bool" key="EditorConfiguration.ConstrainTooltips">false</value>
<value type="int" key="EditorConfiguration.IndentSize">4</value>
<value type="bool" key="EditorConfiguration.KeyboardTooltips">false</value>
<value type="int" key="EditorConfiguration.MarginColumn">80</value>
<value type="bool" key="EditorConfiguration.MouseHiding">true</value>
<value type="bool" key="EditorConfiguration.MouseNavigation">true</value>
<value type="int" key="EditorConfiguration.PaddingMode">1</value>
<value type="int" key="EditorConfiguration.PreferAfterWhitespaceComments">0</value>
<value type="bool" key="EditorConfiguration.PreferSingleLineComments">false</value>
<value type="bool" key="EditorConfiguration.ScrollWheelZooming">true</value>
<value type="bool" key="EditorConfiguration.ShowMargin">false</value>
<value type="int" key="EditorConfiguration.SmartBackspaceBehavior">2</value>
<value type="bool" key="EditorConfiguration.SmartSelectionChanging">true</value>
<value type="bool" key="EditorConfiguration.SpacesForTabs">true</value>
<value type="int" key="EditorConfiguration.TabKeyBehavior">0</value>
<value type="int" key="EditorConfiguration.TabSize">8</value>
<value type="bool" key="EditorConfiguration.UseGlobal">true</value>
<value type="bool" key="EditorConfiguration.UseIndenter">false</value>
<value type="int" key="EditorConfiguration.Utf8BomBehavior">1</value>
<value type="bool" key="EditorConfiguration.addFinalNewLine">true</value>
<value type="bool" key="EditorConfiguration.cleanIndentation">true</value>
<value type="bool" key="EditorConfiguration.cleanWhitespace">true</value>
<value type="QString" key="EditorConfiguration.ignoreFileTypes">*.md, *.MD, Makefile</value>
<value type="bool" key="EditorConfiguration.inEntireDocument">false</value>
<value type="bool" key="EditorConfiguration.skipTrailingWhitespace">true</value>
<value type="bool" key="EditorConfiguration.tintMarginArea">true</value>
</valuemap>
</data>
<data>
<variable>ProjectExplorer.Project.PluginSettings</variable>
<valuemap type="QVariantMap">
<valuemap type="QVariantMap" key="AutoTest.ActiveFrameworks">
<value type="bool" key="AutoTest.Framework.Boost">true</value>
<value type="bool" key="AutoTest.Framework.CTest">false</value>
<value type="bool" key="AutoTest.Framework.Catch">true</value>
<value type="bool" key="AutoTest.Framework.GTest">true</value>
<value type="bool" key="AutoTest.Framework.QtQuickTest">true</value>
<value type="bool" key="AutoTest.Framework.QtTest">true</value>
</valuemap>
<value type="bool" key="AutoTest.ApplyFilter">false</value>
<valuemap type="QVariantMap" key="AutoTest.CheckStates"/>
<valuelist type="QVariantList" key="AutoTest.PathFilters"/>
<value type="int" key="AutoTest.RunAfterBuild">0</value>
<value type="bool" key="AutoTest.UseGlobal">true</value>
<valuemap type="QVariantMap" key="ClangTools">
<value type="bool" key="ClangTools.AnalyzeOpenFiles">true</value>
<value type="bool" key="ClangTools.BuildBeforeAnalysis">true</value>
<value type="QString" key="ClangTools.DiagnosticConfig">Builtin.DefaultTidyAndClazy</value>
<value type="int" key="ClangTools.ParallelJobs">1</value>
<value type="bool" key="ClangTools.PreferConfigFile">true</value>
<valuelist type="QVariantList" key="ClangTools.SelectedDirs"/>
<valuelist type="QVariantList" key="ClangTools.SelectedFiles"/>
<valuelist type="QVariantList" key="ClangTools.SuppressedDiagnostics"/>
<value type="bool" key="ClangTools.UseGlobalSettings">true</value>
</valuemap>
<valuemap type="QVariantMap" key="ClangdSettings">
<value type="bool" key="blockIndexing">true</value>
<value type="bool" key="useGlobalSettings">true</value>
</valuemap>
</valuemap>
</data>
<data>
<variable>ProjectExplorer.Project.Target.0</variable>
<valuemap type="QVariantMap">
<value type="QString" key="DeviceType">Desktop</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Default Config (CMake preset)</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Default Config (CMake preset)</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">{28867bdf-d8be-4243-8aa3-4dcf402f55e4}</value>
<value type="qlonglong" key="ProjectExplorer.Target.ActiveBuildConfiguration">0</value>
<value type="qlonglong" key="ProjectExplorer.Target.ActiveDeployConfiguration">0</value>
<value type="qlonglong" key="ProjectExplorer.Target.ActiveRunConfiguration">0</value>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.0">
<value type="QString" key="CMake.Build.Type">RelWithDebInfo</value>
<value type="int" key="CMake.Configure.BaseEnvironment">1</value>
<value type="bool" key="CMake.Configure.ClearSystemEnvironment">false</value>
<valuelist type="QVariantList" key="CMake.Configure.UserEnvironmentChanges">
<value type="QString">CMAKE_CXX_COMPILER_LAUNCHER=ccache</value>
<value type="QString">CMAKE_C_COMPILER_LAUNCHER=ccache</value>
</valuelist>
<value type="QString" key="CMake.Initial.Parameters">-DBUILD_SOUNDTOUCH:BOOL=ON
-DCMAKE_INTERPROCEDURAL_OPTIMIZATION:BOOL=ON
-DCMAKE_CXX_COMPILER:FILEPATH=%{Compiler:Executable:Cxx}
-DCMAKE_GENERATOR:STRING=Ninja
-DCMAKE_PREFIX_PATH:PATH=%{Qt:QT_INSTALL_PREFIX}
-DCMAKE_PROJECT_INCLUDE_BEFORE:FILEPATH=%{BuildConfig:BuildDirectory:NativeFilePath}/.qtc/package-manager/auto-setup.cmake
-DCMAKE_C_FLAGS:STRING=-O2 -march=native -g
-DCMAKE_BUILD_TYPE:STRING=RelWithDebInfo
-DDISABLE_GTK_UI:BOOL=ON
-DCMAKE_C_COMPILER:FILEPATH=%{Compiler:Executable:C}
-DQT_QMAKE_EXECUTABLE:FILEPATH=%{Qt:qmakeExecutable}
-DCMAKE_CXX_FLAGS:STRING=-O2 -march=native -g
-DCMAKE_POLICY_DEFAULT_CMP0069:STRING=NEW</value>
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">/boot/home/Desktop/looper/build/default</value>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="QString" key="CMakeProjectManager.MakeStep.BuildPreset">default</value>
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.BuildTargets">
<value type="QString">all</value>
</valuelist>
<value type="bool" key="CMakeProjectManager.MakeStep.ClearSystemEnvironment">false</value>
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.UserEnvironmentChanges">
<value type="QString">CMAKE_CXX_COMPILER_LAUNCHER=ccache</value>
<value type="QString">CMAKE_C_COMPILER_LAUNCHER=ccache</value>
</valuelist>
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Build</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.MakeStep</value>
</valuemap>
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Build</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="QString" key="CMakeProjectManager.MakeStep.BuildPreset"></value>
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.BuildTargets">
<value type="QString">clean</value>
</valuelist>
<value type="bool" key="CMakeProjectManager.MakeStep.ClearSystemEnvironment">false</value>
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.UserEnvironmentChanges"/>
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Build</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.MakeStep</value>
</valuemap>
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Clean</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Clean</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.CustomParsers"/>
<value type="bool" key="ProjectExplorer.BuildConfiguration.ParseStandardOutput">false</value>
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Release with Debug Information</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.CMakeBuildConfiguration</value>
</valuemap>
<value type="qlonglong" key="ProjectExplorer.Target.BuildConfigurationCount">1</value>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.DeployConfiguration.0">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">0</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Deploy</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Deploy</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Deploy</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">1</value>
<valuemap type="QVariantMap" key="ProjectExplorer.DeployConfiguration.CustomData"/>
<value type="bool" key="ProjectExplorer.DeployConfiguration.CustomDataEnabled">false</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.DefaultDeployConfiguration</value>
</valuemap>
<value type="qlonglong" key="ProjectExplorer.Target.DeployConfigurationCount">1</value>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.RunConfiguration.0">
<value type="bool" key="Analyzer.Perf.Settings.UseGlobalSettings">true</value>
<value type="bool" key="Analyzer.QmlProfiler.Settings.UseGlobalSettings">true</value>
<value type="int" key="Analyzer.Valgrind.Callgrind.CostFormat">0</value>
<value type="bool" key="Analyzer.Valgrind.Settings.UseGlobalSettings">true</value>
<valuelist type="QVariantList" key="CustomOutputParsers"/>
<value type="int" key="PE.EnvironmentAspect.Base">2</value>
<valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/>
<value type="bool" key="PE.EnvironmentAspect.PrintOnRun">false</value>
<value type="QString" key="PerfRecordArgsId">-e cpu-cycles --call-graph dwarf,4096 -F 250</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">looper</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.CMakeRunConfiguration.looper</value>
<value type="QString" key="ProjectExplorer.RunConfiguration.BuildKey">looper</value>
<value type="bool" key="ProjectExplorer.RunConfiguration.Customized">false</value>
<value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value>
<value type="bool" key="RunConfiguration.UseLibrarySearchPath">true</value>
<value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value>
<value type="QString" key="RunConfiguration.WorkingDirectory.default">/boot/home/Desktop/looper/build/default</value>
</valuemap>
<value type="qlonglong" key="ProjectExplorer.Target.RunConfigurationCount">1</value>
</valuemap>
</data>
<data>
<variable>ProjectExplorer.Project.Target.1</variable>
<valuemap type="QVariantMap">
<value type="QString" key="DeviceType">Desktop</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Fast building config (CMake preset)</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Fast building config (CMake preset)</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">{ed57fb1f-eec5-4800-be42-516744e4f7eb}</value>
<value type="qlonglong" key="ProjectExplorer.Target.ActiveBuildConfiguration">0</value>
<value type="qlonglong" key="ProjectExplorer.Target.ActiveDeployConfiguration">0</value>
<value type="qlonglong" key="ProjectExplorer.Target.ActiveRunConfiguration">0</value>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.0">
<value type="QString" key="CMake.Build.Type">RelWithDebInfo</value>
<value type="int" key="CMake.Configure.BaseEnvironment">1</value>
<value type="bool" key="CMake.Configure.ClearSystemEnvironment">false</value>
<valuelist type="QVariantList" key="CMake.Configure.UserEnvironmentChanges">
<value type="QString">CMAKE_CXX_COMPILER_LAUNCHER=ccache</value>
<value type="QString">CMAKE_C_COMPILER_LAUNCHER=ccache</value>
</valuelist>
<value type="QString" key="CMake.Initial.Parameters">-DBUILD_SOUNDTOUCH:BOOL=ON
-DCMAKE_INTERPROCEDURAL_OPTIMIZATION:BOOL=OFF
-DCMAKE_CXX_COMPILER:FILEPATH=%{Compiler:Executable:Cxx}
-DCMAKE_GENERATOR:STRING=Ninja
-DCMAKE_PREFIX_PATH:PATH=%{Qt:QT_INSTALL_PREFIX}
-DCMAKE_PROJECT_INCLUDE_BEFORE:FILEPATH=%{BuildConfig:BuildDirectory:NativeFilePath}/.qtc/package-manager/auto-setup.cmake
-DCMAKE_C_FLAGS:STRING=-O2 -march=native -g
-DCMAKE_BUILD_TYPE:STRING=RelWithDebInfo
-DDISABLE_GTK_UI:BOOL=ON
-DCMAKE_C_COMPILER:FILEPATH=%{Compiler:Executable:C}
-DQT_QMAKE_EXECUTABLE:FILEPATH=%{Qt:qmakeExecutable}
-DCMAKE_CXX_FLAGS:STRING=-O2 -march=native -g
-DCMAKE_POLICY_DEFAULT_CMP0069:STRING=NEW</value>
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">/boot/home/Desktop/looper/build/Fast_building_config_CMake_preset-RelWithDebInfo</value>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="QString" key="CMakeProjectManager.MakeStep.BuildPreset">fast</value>
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.BuildTargets">
<value type="QString">all</value>
</valuelist>
<value type="bool" key="CMakeProjectManager.MakeStep.ClearSystemEnvironment">false</value>
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.UserEnvironmentChanges">
<value type="QString">CMAKE_CXX_COMPILER_LAUNCHER=ccache</value>
<value type="QString">CMAKE_C_COMPILER_LAUNCHER=ccache</value>
</valuelist>
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.MakeStep</value>
</valuemap>
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Build</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="QString" key="CMakeProjectManager.MakeStep.BuildPreset"></value>
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.BuildTargets">
<value type="QString">clean</value>
</valuelist>
<value type="bool" key="CMakeProjectManager.MakeStep.ClearSystemEnvironment">false</value>
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.UserEnvironmentChanges"/>
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.MakeStep</value>
</valuemap>
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Clean</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Clean</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.CustomParsers"/>
<value type="bool" key="ProjectExplorer.BuildConfiguration.ParseStandardOutput">false</value>
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Release with Debug Information</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.CMakeBuildConfiguration</value>
</valuemap>
<value type="qlonglong" key="ProjectExplorer.Target.BuildConfigurationCount">1</value>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.DeployConfiguration.0">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">0</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Deploy</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Deploy</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Deploy</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">1</value>
<valuemap type="QVariantMap" key="ProjectExplorer.DeployConfiguration.CustomData"/>
<value type="bool" key="ProjectExplorer.DeployConfiguration.CustomDataEnabled">false</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.DefaultDeployConfiguration</value>
</valuemap>
<value type="qlonglong" key="ProjectExplorer.Target.DeployConfigurationCount">1</value>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.RunConfiguration.0">
<value type="bool" key="Analyzer.Perf.Settings.UseGlobalSettings">true</value>
<value type="bool" key="Analyzer.QmlProfiler.Settings.UseGlobalSettings">true</value>
<value type="int" key="Analyzer.Valgrind.Callgrind.CostFormat">0</value>
<value type="bool" key="Analyzer.Valgrind.Settings.UseGlobalSettings">true</value>
<valuelist type="QVariantList" key="CustomOutputParsers"/>
<value type="int" key="PE.EnvironmentAspect.Base">2</value>
<valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/>
<value type="bool" key="PE.EnvironmentAspect.PrintOnRun">false</value>
<value type="QString" key="PerfRecordArgsId">-e cpu-cycles --call-graph dwarf,4096 -F 250</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.CustomExecutableRunConfiguration</value>
<value type="QString" key="ProjectExplorer.RunConfiguration.BuildKey"></value>
<value type="bool" key="ProjectExplorer.RunConfiguration.Customized">false</value>
<value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value>
<value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value>
</valuemap>
<value type="qlonglong" key="ProjectExplorer.Target.RunConfigurationCount">1</value>
</valuemap>
</data>
<data>
<variable>ProjectExplorer.Project.TargetCount</variable>
<value type="qlonglong">2</value>
</data>
<data>
<variable>ProjectExplorer.Project.Updater.FileVersion</variable>
<value type="int">22</value>
</data>
<data>
<variable>Version</variable>
<value type="int">22</value>
</data>
</qtcreator>

View file

@ -1,11 +1,30 @@
{
"version": 10,
"version": 9,
"cmakeMinimumRequired": {
"major": 3,
"minor": 23,
"patch": 0
},
"configurePresets": [
{
"name": "fastbuild",
"displayName": "Fast building config",
"description": "Build with optimization for speed of building",
"generator": "Ninja",
"cacheVariables": {
"CMAKE_POLICY_DEFAULT_CMP0069": "NEW",
"CMAKE_INTERPROCEDURAL_OPTIMIZATION": "OFF",
"CMAKE_C_FLAGS": "-O2 -march=native -g",
"CMAKE_CXX_FLAGS": "-O2 -march=native -g",
"BUILD_SOUNDTOUCH": "ON",
"DISABLE_GTK_UI": "ON",
"CMAKE_BUILD_TYPE": "RelWithDebInfo"
},
"environment": {
"CMAKE_C_COMPILER_LAUNCHER": "ccache",
"CMAKE_CXX_COMPILER_LAUNCHER": "ccache"
}
},
{
"name": "default",
"displayName": "Default Config",
@ -31,6 +50,10 @@
{
"name": "default",
"configurePreset": "default"
},
{
"name": "fast",
"configurePreset": "fastbuild"
}
],
"testPresets": [
@ -41,4 +64,4 @@
"execution": {"noTestsAction": "error", "stopOnFailure": true}
}
]
}
}

BIN
assets/application-exit Normal file

Binary file not shown.

View file

@ -0,0 +1,29 @@
resource(1011) #'VICN' array {
$"6E63696606050004006603BF5000020006020000003AC2F3BAC2F30000004E5C"
$"5B49D87B00FFFF80FFFFD5000554020016020000003C9BA8BC9BA80000004E35"
$"1649D81000FFFFD9080606FF07B5F7B6F1B5F7B6F1B5F7BC7CB5F7C791B5F7C2"
$"06BA34C791C2AFC791BE72C791C2AFC206C2AFB6F1C2AFBC7CBE72B6F1B5F7B6"
$"F1BA34B6F1B5F7B6F1B6F10609FFFF01BEC5BEC4BEC5BEC4BEC5BFBEBEC5C1B3"
$"BEC5C0B9C0BAC1B3C4A4C1B3C2AFC1B3C4A4C2AEC4A4C4A3C4A4C3A8C646C32B"
$"C989C03CC7E7C1B3C7E7BEC4C4A4BBD5C646BD4DC4A4BCCFC4A4BEC4C4A4BDCA"
$"C2AFBEC4BEC5BEC4C0BABEC4BEC5BEC4BEC40609FFFF01BDCBBDC9BDCBBDC9BD"
$"CBBEC4BDCBC0B9BDCBBFBE40C0B9C3AAC0B9C1B5C0B9C3AAC1B3C3AAC3A8C3AA"
$"C2AEC54BC231C88EBF41C6EDC0B9C6EDBDCAC3AABADBC54BBC52C3AABBD5C3AA"
$"BDC9C3AABCCFC1B5BDC9BDCBBDC940BDC9BDCBBDC9BDC90609FFFF01BDCBBDC9"
$"BDCBBDC9BDCBBEC4BDCBC0B9BDCBBFBE40C0B9C3AAC0B9C1B5C0B9C3AAC1B3C3"
$"AAC3A8C3AAC2AEC54BC231C88EBF41C6EDC0B9C6EDBDCAC3AABADBC54BBC52C3"
$"AABBD5C3AABDC9C3AABCCFC1B5BDC9BDCBBDC940BDC9BDCBBDC9BDC90608FF7F"
$"B6F2B7EBB6F2B7EBB6F2BD76B6F2C88CB6F2C301B8E7C8DFBCD0C986BADBC933"
$"BD24C95CBDCBC909BD77C933BDCBC32BBDCBB76EBDCBBD4CBD77B744BCD0B6F1"
$"BD24B71BBADBB744B6F2B7EBB8E7B798B6F2B7EBB7EB0608FF7FB5F7B6F1B5F7"
$"B6F1B5F7BC7CB5F7C791B5F7C206B7ECC7E5BBD6C88CB9E1C838BC29C862BCD0"
$"C80EBC7DC838BCD0C230BCD0B674BCD0BC52BC7DB64ABBD6B5F6BC29B620B9E1"
$"B64AB5F7B6F1B7ECB69DB5F7B6F1B6F10606FF07B5F7B6F1B5F7B6F1B5F7BC7C"
$"B5F7C791B5F7C206B7ECC7E5BBD6C88CB9E1C838BBD6C25ABBD6B5F6BBD6BC28"
$"B9E1B64AB5F7B6F1B7ECB69DB5F7B6F1B6F10004BADBBEC4BADBBEC4BADBBF17"
$"BADBBFBEBADBBF6BBA34BFBEB8E7BFBEB98EBFBEB8E7BF6BB8E7BEC4B8E7BF17"
$"B8E7BEC4080A000100000A0101011001178422040A0201021001178422040A03"
$"0103000A0101041001178422040A0401051001178422040A050106000A040107"
$"00"
};

BIN
assets/configure vendored Normal file

Binary file not shown.

37
assets/configure.rdef Normal file
View file

@ -0,0 +1,37 @@
resource(1006) #'VICN' array {
$"6E63696603011A171B660554020016020000003CC4CBBCC4CB0000004E30CB49"
$"FD6400FFFFE5060606FF07C034BCC6C034BCC6BE4DBCC6BCC6C034BCC6BE4DBC"
$"C6C219C034C3A3BE4DC3A3C219C3A3C3A3C034C3A3C219C3A3BE4DC034BCC6C2"
$"19BCC6C034BCC6BCC60216C984C031C984C031C984C12CC90CC319C95BC227C7"
$"E3C348C590C3A6C6BAC377C50EC470C3A6C590C464C513C376C6BAC317C90EC3"
$"47C7E4C229C95EC02EC983C12CC983BFA6C877BE94C65EBF1DC76ABDACC621BC"
$"2BC523BCDBC5B3BB00C552B8ABC5B0B9D5C581B816C4E5B756C311B7A6C402B8"
$"2BC23BB9D6C090B901C166B9C9BFA1BA44BDE6B9F1BEBAB9BBBCD8B8A8BABCB9"
$"31BBCAB93BB9F1BABDB8A9B9EFB93EBBCAB932BDE3BA44BCD6B9BBBEC2B9ECC0"
$"8FB9D8BFACB9CAC165B902C311B756C23BB82CC400B7A4C5B0B8AEC4E2B819C5"
$"81B9D7C52337C552BB014FBCE4C65CBE94C621BDB8C769BF1EC984C031C877BF"
$"A7C984C031C984C031C984C031C984C0310216C88ABF36C88ABF36C88AC031C8"
$"11C21EC860C12CC6E8C24DC496C2ABC5BFC27CC413C375C2ABC494C36AC418C2"
$"7BC5BEC21BC813C24BC6E9C12DC862BF34C888C031C888BEABC77BBD99C562BE"
$"22C66FBCB1C526BB30C427BBE1C4B7BA05C456B7AFC4B5B8DAC485B71CC3EAB6"
$"5BC215B6AAC306B730C140B8DBBF96B806C06BB8CEBEA6B949BCEAB8F6BDBFB8"
$"BFBBDCB7ADB9C1B836BACFB840B8F6B9C2B7AEB8F5B844BACFB837BCE8B949BB"
$"DCB8C0BDC8B8F0BF94B8DCBEB1B8CEC06AB807C215B65BC13FB731C305B6A9C4"
$"B5B7B3C3E7B71EC486B8DCC427BB30C457BA06C4BFBBEAC561BD99C526BCBEC6"
$"6FBE22C88ABF36C77CBEACC88ABF36C88ABF36C88ABF36C88ABF360606FF07BF"
$"3ABBCBBF3ABBCBBD53BBCBBBCBBF3ABBCBBD53BBCBC11EBF3AC2A8BD53C2A8C1"
$"1EC2A8C2A8BF3AC2A8C11EC2A8BD53BF3ABBCBC11EBBCBBF3ABBCBBBCB0606FF"
$"07BF3ABBCBBF3ABBCBBD53BBCBBBCBBF3ABBCBBD53BBCBC11EBF3AC2A8BD53C2"
$"A8C11EC2A8C2A8BF3AC2A8C11EC2A8BD53BF3ABBCBC11EBBCBBF3ABBCBBBCB02"
$"16C88ABF36C88ABF36C88AC031C811C21EC860C12CC6E8C24DC496C2ABC5BFC2"
$"7CC413C375C2ABC494C36AC418C27BC5BEC21BC813C24BC6E9C12DC862BF34C8"
$"88C031C888BEABC77BBD99C562BE22C66FBCB1C526BB30C427BBE1C4B7BA05C4"
$"56B7AFC4B5B8DAC485B71CC3EAB65BC215B6AAC306B730C140B8DBBF96B806C0"
$"6BB8CEBEA6B949BCEAB8F6BDBFB8BFBBDCB7ADB9C1B836BACFB840B8F6B9C2B7"
$"AEB8F5B844BACFB837BCE8B949BBDCB8C0BDC8B8F0BF94B8DCBEB1B8CEC06AB8"
$"07C215B65BC13FB731C305B6A9C4B5B7B3C3E7B71EC486B8DCC427BB30C457BA"
$"06C4BFBBEAC561BD99C526BCBEC66FBE22C88ABF36C77CBEACC88ABF36C88ABF"
$"36C88ABF36C88ABF36030A000200011001178400040A01020203100117840004"
$"0A0202040500"
};

BIN
assets/document-edit Normal file

Binary file not shown.

BIN
assets/document-open Normal file

Binary file not shown.

28
assets/document-open.rdef Normal file
View file

@ -0,0 +1,28 @@
resource(1007) #'VICN' array {
$"6E6369660604006603BF500003FFC8000300008002000602000000387F5CB87F"
$"5C0000004E7480490F8500FFFFFFFFD9D9FF020006020000003A8000BA800000"
$"00004E607A4A9FAE00FFEA80FFFFBB0009060AFF7F05B7EAC8B4B7EAC8B4BD76"
$"C8B4C88CC8B4C301C8B4C839C310C7922CC7E5BD6CC6442CC3A82CC4F62CC354"
$"B871C2AD31C301B91BBF6B31B8E531BC2731B891BEBFB7EAC8B4B83EC3B9B7EA"
$"C8B4C8B4C8B4C8B40608FF57B7E9C8B4B7E9C8B4B796C60DB6EFC0BDB743C365"
$"BD21C0BDC987C0BDC354C0BDC933C365C88CC8B4C8DFC60DC301C8B4B7E9C8B4"
$"BD75C8B4B7E9C8B4C8B4C8B4C8B40004B7EABFBEB7EABFBEB7EABE6BB7EABBC2"
$"B7EABD16BD76BBC2C88CBBC2C301BBC2C88CBD16C88CBFBEC88CBE6BC88CBFBE"
$"060AFF7F05B6F0C7B5B6F0C7B5BC7CC7B5C792C7B5C207C7B5C73EC211C697B6"
$"C7C6EABC6CC549B6C7C2ADB6C7C3FCB6C7C25BB772C1B3B8C5C207B81BBE70B8"
$"C5B7EAB8C5BB2EB8C5B798BDC0B6F0C7B5B744C2BAB6F0C7B5C7B5C7B5C7B506"
$"0AFF7F05B6F0C7B5B6F0C7B5BC7CC7B5C792C7B5C207C7B5C73EC211C697B6C7"
$"C6EABC6CC549B6C7C2ADB6C7C3FCB6C7C25BB772C1B3B8C5C207B81BBE70B8C5"
$"B7EAB8C5BB2EB8C5B798BDC0B6F0C7B5B744C2BAB6F0C7B5C7B5C7B5C7B50004"
$"B6F0BEBEB6F0BEBEB6F0BD6BB6F0BAC3B6F0BC17BC7CBAC3C792BAC3C207BAC3"
$"C792BC17C792BEBEC792BD6BC792BEBE0004B6F0BEBEB6F0BEBEB6F0BD6BB6F0"
$"BAC3B6F0BC17BC7CBAC3C792BAC3C207BAC3C792BC17C792BEBEC792BD6BC792"
$"BEBE0608FF57B6EFC7B5B6EFC7B5B69CC50DB5F4BFBDB648C266BC27BFBDC88C"
$"BFBDC25ABFBDC839C266C792C7B5C7E5C50DC206C7B5B6EFC7B5BC7AC7B5B6EF"
$"C7B5C7B5C7B5C7B50608FF57B6EFC7B5B6EFC7B5B69CC50DB5F4BFBDB648C266"
$"BC27BFBDC88CBFBDC25ABFBDC839C266C792C7B5C7E5C50DC206C7B5B6EFC7B5"
$"BC7AC7B5B6EFC7B5C7B5C7B5C7B5070A00030001021001178422040A01010310"
$"01178422040A020104000A0301051001178422040A040106000A010107100117"
$"8422040A05010800"
};

BIN
assets/edit-emblem Normal file

Binary file not shown.

BIN
assets/folder Normal file

Binary file not shown.

22
assets/folder.rdef Normal file
View file

@ -0,0 +1,22 @@
resource(1008) #'VICN' array {
$"6E636966070401640500020006022C3D6F3C691EBC691E2C3D6F4C9B14497B5C"
$"00FACE79FFBC4105020016022C66683CAA8FBCAA8F2C66684C8FE14A215C00FF"
$"FF8E020016023AE3D73C7999BC79993AE3D74C30CC445999009AFF5002000602"
$"3841473C9B33BC9B333841474C41704A2F3300FFE2ACFFF4980603A03D030706"
$"08FF7F4A5D4A5D4C5D505D4E5DC6A7CAC65459C730CA3DC83F595859C8C8595A"
$"575E535C55C9D7C6CA504FC7FCC6414EC7964A5D4CC9714A5D5D020C232F232F"
$"B585BC6E2D49B6DABFE1BC084F4A5BBFE15550C4435C2C56BE0658B783502A54"
$"B740C598B7404C2CC50FB78346B7403A2840B6B7BD18B6DA382DBCD3B783BB80"
$"B7E9302BBA6FB7A6B95CB878B956BAA6B959B98FB79FBA17232FB5E8B988232F"
$"232F232F232F0608FF7F3A283A2836332E49323EBC4BC5984A5AC004C7D950C4"
$"005C2C56BDE358B783502A54B740C598B7404C2CC50FB78346B7403A2840B6B7"
$"3A28280606FF07302B302B30353049303FBCD4C5754A59C047C796C4A9C50F51"
$"36C598C06A46BA4E302B3BB8D8302B2B0606FF07302B302B3BB8D8513646BA4E"
$"C598C06A4A59C4A9C50FC50FC4D854BB1DC664BFFB48B9DF302B3CB8A0302B2B"
$"0606FF07232F232FB585BC6E2D49B6DABFE1BC084F4A5BBFE155C334C6A7463E"
$"C2ABC2CEBD7D39232FB8D834232F2F0606FF07232F232FB8D834463EBD7D39C2"
$"ABC2CE4A5BC334C6A7C389C664C3233C49C2453CBC6D232FB92DBAB4232F2F07"
$"0A000100000A0101011001178400040A020102000A030103000A040104000A05"
$"0105000A06010600"
};

BIN
assets/haiku-icon Normal file

Binary file not shown.

31
assets/haiku-icon.rdef Normal file
View file

@ -0,0 +1,31 @@
resource vector_icon array {
$"6E63696605050002010602C07FEC347267B45AEAC067ED4C37354C23A69AFFAA"
$"00FFFFBD3E0201040200FF0000FFFFE0A502000602BA3F2DA6FE6428A632BBF9"
$"FA47F3344870859AFFAA00FFFFBD3E0200060239D421B85A383A14EA3B6357C4"
$"D66E43223D9AFFAA00FFFFBD3E0702044030C34530BC3A30304030BC3A30C345"
$"4050BC3A50C34550504050C34550BC3A02044030C34530BC3A30304030BC3A30"
$"C3454050BC3A50C34550504050C34550BC3A0803273327272D2E0A0327332727"
$"2D2E02043432363231322F3A2F362F3E334330433643383A383E38360405EE02"
$"2E4A354E304E3A4E3B4B414E3C4E464E464B0802244A2F4A1A0A0001021A4155"
$"55000000000000415555C55555C6AAAA11FF01178222040A0001020A41555500"
$"0000000000415555C55555C6AAAA00100A0001000241C31700000000000041C2"
$"DDC9862EC985BB0A0101010A415FFF000000000000416000C8BFFFC8C00011FF"
$"0A0101000A417FFF000000000000418000C8FFFFC9000040FF0A0101000A4100"
$"0000000000000040FFFFC80000C7FFFF00100A0301020A422AAA000000000000"
$"41E666C51555C5533300100A0301020A415555000000000000410000C4D555C5"
$"C00011200A000102124110AD0000000000004108E8C46A0EC66EF30117812204"
$"0A0301020A415555000000000000410000C4D555C5C00020FF0A020102023E5F"
$"240000000000003D90FD444807462CA70A000102123E5F240000000000003D90"
$"FD444807462CA701178322040A0401020AC02B2F0000000000004086114B3D6E"
$"C433AC20FF0A020202030ABB81600000000000003B5A894AA5DE46C48820FF0A"
$"0001021ABD16050000000000003C57EF4AC889465F3320FF01178422040A0001"
$"021AC02B2F0000000000004030BC4B3D6EC33CAD21FF01178122040A0001021A"
$"C02B2F0000000000004030BC4B3D6EC33CAD112001178222040A000104000A00"
$"0104202E200A0001051001178200040A00010612400000000000000000420000"
$"000000CA980001178100040A000106123FD5FB3C44A6BC44A63FD5FB47130DC2"
$"F85301178100040A000106123FD3BABC53AC3C53AC3FD3BAC6F38945CA1A0117"
$"8100040A00010612C000000000000000004200004B5000CA980001178100040A"
$"00010612BFD5FB3C44A63C44A63FD5FB4A8B3CC2F85301178100040A00010612"
$"BFD3BABC53ACBC53AC3FD3BA4C067145CA1A0117810004"
};

BIN
assets/help-about Normal file

Binary file not shown.

37
assets/help-about.rdef Normal file
View file

@ -0,0 +1,37 @@
resource(1009) #'VICN' array {
$"6E636966040400660500020016020000003D0601BD06010000004E3AD149D6EE"
$"0080FF28020002033D7FD40000000000003D7FD449FFD3CB172600FF05052679"
$"FF060681FFFF040426160003C552C961C552C961C5A9C961C656C961C600C961"
$"C600C9B7C552CA65C5A9CA0EC552CA650003C144C961C144C961C19BC9B7C248"
$"CA65C1F1CA0EC248CA0EC248C961C248C9B7C248C9610003BE3ACA65BE3ACA65"
$"BDE3CA0EBD36C961BD8DC9B7BD36C9B7BD36CA65BD36CA0EBD36CA650003BA2B"
$"C961BA2BC961B9D4C9B7B928CA65B97ECA0EB97ECA65BA2BCA65B9D4CA65BA2B"
$"CA650606FF07C75AC656C75AC656C75AC0EEC75AB61CC75ABB85C703B61CC656"
$"B61CC6ADB61CC656BB85C656C656C656C0EEC6ADC656C75AC656C703C656C75A"
$"C656C6560002C248B61CC248B61CC248BB85C248C656C248C0EEC248C6560002"
$"CA65B61CCA65B61CCA65BCDFCA65CA65CA65C3A2CA65CA650606FF07BF3DC656"
$"BF3DC656BF3DC0EEBF3DB61CBF3DBB85BEE6B61CBE3AB61CBE90B61CBE3ABB85"
$"BE3AC656BE3AC0EEBE90C656BF3DC656BEE6C656BF3DC656C6560606FF07BB2E"
$"C656BB2EC656BB2EC0EEBB2EB61CBB2EBB85BA81B61CB928B61CB9D5B61CB928"
$"BB85B928C656B928C0EEB9D5C656BB2EC656BA81C656BB2EC656C6560002B61C"
$"B61CB61CB61CB61CBCDFB61CCA65B61CC3A2B61CCA650003C44FC85EC44FC85E"
$"C4A5C85EC552C85EC4FCC85EC4FCC8B4C44FC961C4A5C90AC44FC9610003C040"
$"C85EC040C85EC097C8B4C144C961C0EEC90AC144C90AC144C85EC144C8B4C144"
$"C85E0003BD36C961BD36C961BCDFC90ABC32C85EBC89C8B4BC32C8B4BC32C961"
$"BC32C90ABC32C9610003B928C85EB928C85EB8D1C8B4B824C961B87AC90AB87A"
$"C961B928C961B8D1C961B928C9610606FF07C656C552C656C552C656BFEAC656"
$"B518C656BA81C600B518C552B518C5A9B518C552BA81C552C552C552BFEAC5A9"
$"C552C656C552C600C552C656C552C5520002C144B518C144B518C144BA81C144"
$"C552C144BFEAC144C5520002C961B518C961B518C961BBDBC961C961C961C29E"
$"C961C9610606FF07BE3AC552BE3AC552BE3ABFEABE3AB518BE3ABA81BDE3B518"
$"BD36B518BD8DB518BD36BA81BD36C552BD36BFEABD8DC552BE3AC552BDE3C552"
$"BE3AC552C5520606FF07BA2BC552BA2BC552BA2BBFEABA2BB518BA2BBA81B97E"
$"B518B824B518B8D1B518B824BA81B824C552B824BFEAB8D1C552BA2BC552B97E"
$"C552BA2BC552C5520002B518B518B518B518B518BBDBB518C961B518C29EB518"
$"C9610606FF07BA2BC552BA2BC552BA2BBFEABA2BB518BA2BBA81B97EB518B824"
$"B518B8D1B518B824BA81B824C552B824BFEAB8D1C552BA2BC552B97EC552BA2B"
$"C552C5520002B518C040B518C040BC32BF93CA65BE3AC34BBEE7CA65BE3A040A"
$"000A000102030405060708091001178222040A010A0A0B0C0D0E0F1011121310"
$"01178222040A020114000A030115100117822204"
};

BIN
assets/help-contents Normal file

Binary file not shown.

17
assets/help-contents.rdef Normal file
View file

@ -0,0 +1,17 @@
resource(1010) #'VICN' array {
$"6E6369660504006603800000020006020000003CEA53BCEA530000004E2B0249"
$"D85700FFABABFFD900000554020016020000003CEA53BCEA530000004E2B0249"
$"D85700FFFFE50C0002C56BC56BC56BC56BC848C28DC56BBB0CC848BDE9C56BBB"
$"0C0002BB0CBB0CBB0CBB0CB82FBDE9BB0CC56BB82FC28DBB0CC56B0002BB0CC5"
$"6BBB0CC56BBDE9C848C56BC56BC28DC848C56BC56B0002C56BBB0CC56BBB0CC2"
$"8DB82FBB0CBB0CBDE9B82FBB0CBB0C0002BA11C470BA11C470BCEFC74EC470C4"
$"70C192C74EC470C4700002C470BA11C470BA11C192B734BA11BA11BCEFB734BA"
$"11BA110002BA11C470BA11C470BCEFC74EC470C470C192C74EC470C4700002C4"
$"70BA11C470BA11C192B734BA11BA11BCEFB734BA11BA110002BA11BA11BA11BA"
$"11B734BCEFBA11C470B734C192BA11C4700002C470C470C470C470C74EC192C4"
$"70BA11C74EBCEFC470BA110002BA11BA11BA11BA11B734BCEFBA11C470B734C1"
$"92BA11C4700002C470C470C470C470C74EC192C470BA11C74EBCEFC470BA1105"
$"0A0004000102031001178E00040A010204051001178E00040A02020607100117"
$"8900040A030208091001178E00040A04020A0B100117890004"
};

View file

@ -0,0 +1,22 @@
Copyright (c) 2008-2019 Adam Gashlin, Fastelbja, Ronny Elfert, bnnm,
Christopher Snowhill, NicknineTheEagle, bxaimc,
Thealexbarney, CyberBotX, et al
Portions Copyright (c) 2004-2008, Marko Kreen
Portions Copyright 2001-2007 jagarl / Kazunori Ueno <jagarl@creator.club.ne.jp>
Portions Copyright (c) 1998, Justin Frankel/Nullsoft Inc.
Portions Copyright (C) 2006 Nullsoft, Inc.
Portions Copyright (c) 2005-2007 Paul Hsieh
Portions Public Domain originating with Sun Microsystems
Permission to use, copy, modify, and distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

View file

@ -0,0 +1,9 @@
Copyright (c) 2019 Michael Steil
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
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.
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.

View file

@ -0,0 +1,19 @@
resource(1003) #'VICN' array {
$"6E6369660404006603005900020006020000003CEA27BCCA720000004E05DE49"
$"D8680080FF80FF00B200020006020000003CEA27BCCA720000004E68F249D868"
$"0080FF80FF00B200060606FF07BE27B6F2BE27B6F2BC5CB6F2B8C5B6F2BA90B6"
$"F2B8C5BD23B8C5C985B8C5C354BA90C985BE27C985BC5CC985BE27C354BE27B6"
$"F2BE27BD23BE27B6F2B6F20606FF07BD41B5F8BD41B5F8BB76B5F8B7DFB5F8B9"
$"AAB5F8B7DFBC29B7DFC88CB7DFC25AB9AAC88CBD41C88CBB76C88CBD41C25ABD"
$"41B5F8BD41BC29BD41B5F8B5F80606FF07BD41B5F8BD41B5F8BB76B5F8B7DFB5"
$"F8B9AAB5F8B7DFBC29B7DFC88CB7DFC25AB9AAC88CBD41C88CBB76C88CBD41C2"
$"5ABD41B5F8BD41BC29BD41B5F8B5F80606FF07C804B6F2C804B6F2C639B6F2C2"
$"A2B6F2C46EB6F2C2A2BD23C2A2C985C2A2C354C46EC985C804C985C639C985C8"
$"04C354C804B6F2C804BD23C804B6F2B6F20606FF07C71EB5F8C71EB5F84EB5F8"
$"45B5F8C389B5F845BC2945C88C45C25AC389C88CC71EC88C4EC88CC71EC25AC7"
$"1EB5F8C71EBC29C71EB5F8B5F80606FF07C71EB5F8C71EB5F84EB5F845B5F8C3"
$"89B5F845BC2945C88C45C25AC389C88CC71EC88C4EC88CC71EC25AC71EB5F8C7"
$"1EBC29C71EB5F8B5F8060A0001001001178422040A0101011001178422040A02"
$"0102000A0001031001178422040A0101041001178422040A03010500"
};

View file

@ -0,0 +1,11 @@
resource(1002) #'VICN' array {
$"6E6369660304006603005900020006020000003CEA3DBCEA3D0000004E387A49"
$"D7FF0080FF80FF00B200030605FF01C91AC03BC91AC03BC376BD222DB6EFBDD2"
$"BA082DBD212DC9862DC353BDD2C66DC91AC03BC376C354C91AC03BC03B0605FF"
$"01C81CBF40C81CBF40C278BC27B72FB5F5BCD3B90EB72FBC27B72FC88BB72FC2"
$"59BCD3C572C81CBF40C278C259C81CBF40BF400605FF01C81CBF40C81CBF40C2"
$"78BC27B72FB5F5BCD3B90EB72FBC27B72FC88BB72FC259BCD3C572C81CBF40C2"
$"78C259C81CBF40BF40030A0001001001178422040A0101011001178422040A02"
$"010200"
};

View file

@ -0,0 +1,12 @@
resource(1004) #'VICN' array {
$"6E636966030400660500020016020000003CEA53BCEA530000004E2AF949D85B"
$"0080FF28030606FF07C986C986C986C986C986C354C986B6F2C986BD23C354B6"
$"F2B6F2B6F2BD23B6F2B6F2BD23B6F2C986B6F2C354BD23C986C986C986C354C9"
$"86C986C986C9860606FF07C88CC88CC88CC88CC88CC25AC88CB5F7C88CBC29C2"
$"5AB5F7B5F7B5F7BC29B5F7B5F7BC29B5F7C88CB5F7C25ABC29C88CC88CC88CC2"
$"5AC88CC88CC88CC88C0606FF07C88CC88CC88CC88CC88CC25AC88CB5F7C88CBC"
$"29C25AB5F7B5F7B5F7BC29B5F7B5F7BC29B5F7C88CB5F7C25ABC29C88CC88CC8"
$"8CC25AC88CC88CC88CC88C030A0001001001178422040A010101100117842204"
$"0A02010200"
};

BIN
assets/slider-mode Normal file

Binary file not shown.

39
assets/slider-mode.rdef Normal file
View file

@ -0,0 +1,39 @@
resource(1001) #'VICN' array {
$"6E6369660D0501040066030059000200060200000038C5B0B8AED50000004EAB"
$"3E4B4EB70080FF80FF00B200057B0200160400000038C5B0BF55DA0000004BAC"
$"F8483D6F00FFB7DABADCFFA70200160400000038C5B0BF55DA0000004BACF848"
$"3D6F00FFB7DABADCFFFF0200160400000038C5B0BF55DA0000004BACF8483D6F"
$"00FFB7DABADCFFA7040082033C23000200060238466638370AB8370A3846664C"
$"5ECCC753D700FFB629FFD85A0502000602386EB837F999B7F999386EB84A1570"
$"4958F500FFEBCEFFD3B283054D0F0605FF01BB73C6FABB73C6FABE56C6FAC41E"
$"C6FAC13AC6FAC2ACC874BFC8CB66C13AC9EDBE56C9EDBB73C6FABCE5C874BB73"
$"C6FAC6FA0605FF01BA5DC5E0BA5DC5E0BD41C5E0C308C5E0C025C5E0C197C759"
$"BEB3CA4BC025C8D2BD41C8D2BA5DC5E0BBCFC759BA5DC5E0C5E00605FF01BA5D"
$"C5E0BA5DC5E0BD41C5E0C308C5E0C025C5E0C197C759BEB3CA4BC025C8D2BD41"
$"C8D2BA5DC5E0BBCFC759BA5DC5E0C5E00606B20C2739585B355B385B30582F27"
$"2434243024380A04382E383A483A482E0A04382D383B483B482D0A04382D383B"
$"483B482D0802403140370606FF07C67EB79BC67EB79BC253BBC7B9FDC41E3CBF"
$"F3BB61C582BE2AC849BCC5C6E6C254C41ECAAABBC8C67FBFF3C946BA63C67EB7"
$"9BC7E2B8FFC67EB79BB79B0606FF07B9FDC41EB9FDC41EB986C50CB89AC6E6B9"
$"10C5F9B987C7D3BB62C9ABBA74C8BFBC4FC935BE2AC849BD3CC8BFBCC5C6E6B9"
$"FDC41EBB61C582B9FDC41EC41E0605FF01B89AC6E6B89AC6E6B823C84AB735CB"
$"10B7ACC9ADB899CA99BB62C9ABB9FDCA22BA74C8BFB89AC6E6B987C7D3B89AC6"
$"E6C6E60607FF1FC54CB604C54CB604C121BA2FB8CCC286BCF7BE5BB7DEC4D7B6"
$"04C978B6F1C728B855C88BBCF8C6B1BAA6C79EC122C286C978BA30C54DBE5BC8"
$"14B8CCC54CB604C6B0B768C54CB604B6040606FF07C54CB604C54CB604C121BA"
$"2FB8CCC286BCF7BE5BBA30C3EABCF8C6B1BB94C54EC122C286C978BA30C54DBE"
$"5BC814B8CCC54CB604C6B0B768C54CB604B6040606FF07B8CCC286B8CCC286B8"
$"55C374B768C54EB7DEC461B855C63BBA30C813B942C727BB1DC79DBCF8C6B1BC"
$"0AC727BB94C54EB8CCC286BA30C3EAB8CCC286C2860605FF01B768C54EB768C5"
$"4EB6F1C6B2B604C978B67AC815B768C901BA30C813B8CCC88AB942C727B768C5"
$"4EB855C63BB768C54EC54E0F0A0102040330212F01178522040A040103201E2C"
$"0A000103301E2C01178200040A000103381E2C001001178300040A050104201D"
$"2C0A000104381D2C21FF01178222040A000105381D2C102001178222040A0001"
$"06381D2C001001178310040A010107301D2C01178200040A0803090A08023CE9"
$"E90000000000003CE9E94A5C404A666C0A09010B123CE9E90000000000003CE9"
$"E94A5C404A666C01178C02040A09010B1A3CE9E90000000000003CE9E94A5C40"
$"4A666C00100117A002040A0A010C023CE9E90000000000003CE9E94A5C404A66"
$"6C0A0B010D023CE9E90000000000003CE9E94A5C404A666C0A0C010E023CE9E9"
$"0000000000003CE9E94A5C404A666C"
};

BIN
assets/text-frame Normal file

Binary file not shown.

BIN
assets/text-mode Normal file

Binary file not shown.

37
assets/text-mode.rdef Normal file
View file

@ -0,0 +1,37 @@
resource(1000) #'VICN' array {
$"6E6369660B0400660500030059000200060200000038C5B0B8AED50000004EAB"
$"3E4B4EB70080FF80FF00B200050102001602B030EF3E6074BF5FC0B11C4B4BB3"
$"38432C6969D6FFF8040082033C23000200060238466638370AB8370A3846664C"
$"5ECCC753D700FFB629FFD85A0502000602386EB837F999B7F999386EB84A1570"
$"4958F500FFEBCEFFD3B283054D0A06043F254925BE4DBCAF495B49C2D0495BBE"
$"4D5B235BB93AC2D023250606FF07B67AC211B67AC211B67AC274B67AC33AB67A"
$"C2D7B6DDC33AB7A2C33AB740C33AB7A2C2D7B7A2C211B7A2C274B740C211B67A"
$"C211B6DDC211B67AC211C2110608FF7FC4F7B7A2C4F7B7A2C690B7A2C7DDBB1D"
$"C7DDB931C7DDBC45C7DDBE97C7DDBD6EC7DDC082C4F7C211C690C211C35DC211"
$"C211BE97C211C082C211BD6EC211BB1DC211BC45C211B931C4F7B7A2C35DB7A2"
$"C4F7B7A2B7A20606FF07C67EB79BC67EB79BC253BBC7B9FDC41E3CBFF3BB61C5"
$"82BE2AC849BCC5C6E6C254C41ECAAABBC8C67FBFF3C946BA63C67EB79BC7E2B8"
$"FFC67EB79BB79B0606FF07B9FDC41EB9FDC41EB986C50CB89AC6E6B910C5F9B9"
$"87C7D3BB62C9ABBA74C8BFBC4FC935BE2AC849BD3CC8BFBCC5C6E6B9FDC41EBB"
$"61C582B9FDC41EC41E0605FF01B89AC6E6B89AC6E6B823C84AB735CB10B7ACC9"
$"ADB899CA99BB62C9ABB9FDCA22BA74C8BFB89AC6E6B987C7D3B89AC6E6C6E606"
$"07FF1FC54CB604C54CB604C121BA2FB8CCC286BCF7BE5BB7DEC4D7B604C978B6"
$"F1C728B855C88BBCF8C6B1BAA6C79EC122C286C978BA30C54DBE5BC814B8CCC5"
$"4CB604C6B0B768C54CB604B6040606FF07C54CB604C54CB604C121BA2FB8CCC2"
$"86BCF7BE5BBA30C3EABCF8C6B1BB94C54EC122C286C978BA30C54DBE5BC814B8"
$"CCC54CB604C6B0B768C54CB604B6040606FF07B8CCC286B8CCC286B855C374B7"
$"68C54EB7DEC461B855C63BBA30C813B942C727BB1DC79DBCF8C6B1BC0AC727BB"
$"94C54EB8CCC286BA30C3EAB8CCC286C2860605FF01B768C54EB768C54EB6F1C6"
$"B2B604C978B67AC815B768C901BA30C813B8CCC88AB942C727B768C54EB855C6"
$"3BB768C54EC54E0F0A0601001240000000000000000040000041FFFF46800001"
$"178523040A0501000240000000000000000040000090987A45FFFF0A01010038"
$"2028001001178422040A01010038202810FF01178222040A04010128202511FF"
$"0A040102380B2511FF01178310040A04010238202511FF01178300040A040102"
$"380725001001178610040A040102381E25001001178700040A0603040503023C"
$"E9E90000000000003CE9E94A5C404A666C0A070106123CE9E90000000000003C"
$"E9E94A5C404A666C01178C02040A0701061A3CE9E90000000000003CE9E94A5C"
$"404A666C00100117A002040A080107023CE9E90000000000003CE9E94A5C404A"
$"666C0A090108023CE9E90000000000003CE9E94A5C404A666C0A0A0109023CE9"
$"E90000000000003CE9E94A5C404A666C"
};

View file

@ -88,6 +88,8 @@ add_license("licenses/lgpl-2.0.txt", "lgpl_2_0")
add_license("licenses/ForkAwesome.txt", "forkawesome")
add_license("licenses/cli11.txt", "cli11")
add_license("licenses/TomlPlusPlus.txt", "tomlplusplus")
add_license("licenses/x16emu.txt", "x16emu")
add_license("licenses/vgmstream.txt", "vgmstream")
add_license("../backends/ui/imgui/IconFontCppHeaders/licence.txt", "icnfntcpphdrs")
add_css("gtk-frontend.css", "gtk_frontend_css")
add_dbus('app.dbus.xml', 'dbus_stub')

24
assets/view-refresh.rdef Normal file
View file

@ -0,0 +1,24 @@
resource(1005) #'VICN' array {
$"6E6369660404006603004080020006020000003A74EDBA74FF0000004E60F448"
$"285300ABD5FFFF006CD902000602000000BA74ED3A74FF000000CCD5964AC45B"
$"00006CD9FFAAD4FF060608FF7FC986B6F2C986B6F2C986B98EC986BEC5C986BC"
$"29C6EABEC5C1B3BEC5C44FBEC5C284BDF4C425BC53C354BD23C1B3B8E6B6F2BA"
$"DBBB58B76FBA5EB6F2C714B963C1E3B52CC7E5B893C986B6F2C8B5B7C2C986B6"
$"F2B6F20608FF7FC88CB5F7C88CB5F7C88CB893C88CBDCAC88CBB2FC5F0BDCAC0"
$"B9BDCAC355BDCAC18ABCFAC32BBB58C25ABC29C0B9B7ECB5F7B9E0BA5EB675B9"
$"64B5F7C61AB869C0E9B433C6EBB798C88CB5F7C7BBB6C8C88CB5F7B5F70608FF"
$"7FC88CB5F7C88CB5F7C88CB893C88CBDCAC88CBB2FC5F0BDCAC0B9BDCAC355BD"
$"CAC18ABCFAC32BBB58C25ABC29C0B9B7ECB5F7B9E0BA5EB675B964B5F7C61AB8"
$"69C0E9B433C6EBB798C88CB5F7C7BBB6C8C88CB5F7B5F70608FF7FB6F2C986B6"
$"F2C986B6F2C6EBB6F2C1B3B6F2C44FB98DC1B3BEC5C1B3BC29C1B3BDF4C284BC"
$"53C426BD23C355BEC5C791C987C59DC520C909C61AC986B964C715BE95CB4BB8"
$"93C7E5B6F2C986B7C2C8B6B6F2C986C9860608FF7FB5F8C88CB5F8C88CB5F8C5"
$"F0B5F8C0B9B5F8C355B893C0B9BDCAC0B9BB2FC0B9BCFAC18ABB59C32BBC29C2"
$"5ABDCAC698C88CC4A3C426C80FC520C88CB869C61BBD9BCA52B799C6EBB5F8C8"
$"8CB6C8C7BBB5F8C88CC88C0608FF7FB5F8C88CB5F8C88CB5F8C5F0B5F8C0B9B5"
$"F8C355B893C0B9BDCAC0B9BB2FC0B9BCFAC18ABB59C32BBC29C25ABDCAC698C8"
$"8CC4A3C426C80FC520C88CB869C61BBD9BCA52B799C6EBB5F8C88CB6C8C7BBB5"
$"F8C88CC88C060A0001001001178422040A0101011001178422040A020102000A"
$"0001031001178422040A0101041001178422040A03010500"
};

View file

@ -6,6 +6,12 @@
#include <atomic>
#include "playback.h"
#include "dbus.hpp"
#define BACKEND_TYPE(type) \
public: \
inline int64_t default_priority() { \
return (int64_t)UIBackend::PriorityType::type; \
} \
private:
class UIBackend {
protected:
std::vector<std::string> args;
@ -19,6 +25,13 @@ class UIBackend {
bool pitch_set = false;
bool multi_instance = false;
bool daemon_found = false;
enum class PriorityType : int64_t {
Default = 0,
Native = 100,
MetaToolkit = 50,
NonNative = 0,
Fallback = -100
};
public:
DBusAPI *dbus_api;
inline virtual bool allow_multi_instance() {
@ -31,6 +44,9 @@ class UIBackend {
inline virtual void add_licenses() {
// Don't add any here, but leave this specified. That way, licenses specific to UI frontends are only added per UI frontend.
}
inline int64_t default_priority() {
return (int64_t)PriorityType::Default;
}
void init_libportal();
void init_playback();
void setup_playback_args();
@ -108,4 +124,4 @@ class UIBackend {
static UIBackend *running_ui_backend;
virtual ~UIBackend();
};
void init_backends();
void init_backends();

View file

@ -1,4 +1,5 @@
{
"class_name": "SDLMixerXBackend",
"include_path": "sdl_mixer_x.hpp"
"include_path": "sdl_mixer_x.hpp",
"mime_types": ["audio/x-wav", "audio/x-flac", "audio/mid", "audio/midi", "audio/ogg", "audio.x-midi", "audio/wav"]
}

View file

@ -0,0 +1,39 @@
# Install script for directory: /boot/home/Desktop/looper/backends/playback/sdl_mixer_x
# Set the install prefix
if(NOT DEFINED CMAKE_INSTALL_PREFIX)
set(CMAKE_INSTALL_PREFIX "/boot/system")
endif()
string(REGEX REPLACE "/$" "" CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}")
# Set the install configuration name.
if(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME)
if(BUILD_TYPE)
string(REGEX REPLACE "^[^A-Za-z0-9_]+" ""
CMAKE_INSTALL_CONFIG_NAME "${BUILD_TYPE}")
else()
set(CMAKE_INSTALL_CONFIG_NAME "RelWithDebInfo")
endif()
message(STATUS "Install configuration: \"${CMAKE_INSTALL_CONFIG_NAME}\"")
endif()
# Set the component getting installed.
if(NOT CMAKE_INSTALL_COMPONENT)
if(COMPONENT)
message(STATUS "Install component: \"${COMPONENT}\"")
set(CMAKE_INSTALL_COMPONENT "${COMPONENT}")
else()
set(CMAKE_INSTALL_COMPONENT)
endif()
endif()
# Is this installation the result of a crosscompile?
if(NOT DEFINED CMAKE_CROSSCOMPILING)
set(CMAKE_CROSSCOMPILING "FALSE")
endif()
# Set path to fallback-tool for dependency-resolution.
if(NOT DEFINED CMAKE_OBJDUMP)
set(CMAKE_OBJDUMP "/system/bin/objdump")
endif()

View file

@ -6,6 +6,8 @@
#include <log.hpp>
#include <util.hpp>
#include <string.h>
#include <license.hpp>
#include <assets/assets.h>
std::optional<uint64_t> SDLMixerXBackend::get_max_samples() {
return 4096;
}
@ -144,3 +146,9 @@ void SDLMixerXBackend::cleanup() {
open = false;
Mix_CloseAudio();
}
void SDLMixerXBackend::add_licenses() {
auto &license_data = get_license_data();
auto smx = LicenseData("SDL Mixer X", "Zlib");
LOAD_LICENSE(smx, sdl_mixer_x);
license_data.insert(smx);
}

View file

@ -21,6 +21,7 @@ class SDLMixerXBackend : public PlaybackBackend {
void switch_stream(int idx) override;
void cleanup() override;
size_t render(void *buf, size_t maxlen) override;
void add_licenses() override;
SDLMixerXBackend();
~SDLMixerXBackend() override;
};

View file

@ -0,0 +1,39 @@
# Install script for directory: /boot/home/Desktop/looper/backends/playback/vgmstream
# Set the install prefix
if(NOT DEFINED CMAKE_INSTALL_PREFIX)
set(CMAKE_INSTALL_PREFIX "/boot/system")
endif()
string(REGEX REPLACE "/$" "" CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}")
# Set the install configuration name.
if(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME)
if(BUILD_TYPE)
string(REGEX REPLACE "^[^A-Za-z0-9_]+" ""
CMAKE_INSTALL_CONFIG_NAME "${BUILD_TYPE}")
else()
set(CMAKE_INSTALL_CONFIG_NAME "RelWithDebInfo")
endif()
message(STATUS "Install configuration: \"${CMAKE_INSTALL_CONFIG_NAME}\"")
endif()
# Set the component getting installed.
if(NOT CMAKE_INSTALL_COMPONENT)
if(COMPONENT)
message(STATUS "Install component: \"${COMPONENT}\"")
set(CMAKE_INSTALL_COMPONENT "${COMPONENT}")
else()
set(CMAKE_INSTALL_COMPONENT)
endif()
endif()
# Is this installation the result of a crosscompile?
if(NOT DEFINED CMAKE_CROSSCOMPILING)
set(CMAKE_CROSSCOMPILING "FALSE")
endif()
# Set path to fallback-tool for dependency-resolution.
if(NOT DEFINED CMAKE_OBJDUMP)
set(CMAKE_OBJDUMP "/system/bin/objdump")
endif()

View file

@ -8,6 +8,8 @@ extern "C" {
#include "file_backend.hpp"
#include <stddef.h>
#include <string.h>
#include <license.hpp>
#include <assets/assets.h>
void VgmStreamBackend::load(const char *filename) {
spec.format = AUDIO_S16SYS;
file = open_file(filename);
@ -134,4 +136,10 @@ double VgmStreamBackend::get_position() {
}
int VgmStreamBackend::get_stream_idx() {
return vf->stream_index;
}
}
void VgmStreamBackend::add_licenses() {
auto &license_data = get_license_data();
auto vgmstream = LicenseData("VGMSTREAM", "ISC");
LOAD_LICENSE(vgmstream, vgmstream);
license_data.insert(vgmstream);
}

View file

@ -24,5 +24,6 @@ class VgmStreamBackend : public PlaybackBackend {
int get_stream_idx() override;
size_t render(void *buf, size_t maxlen) override;
double get_position() override;
void add_licenses() override;
inline ~VgmStreamBackend() override { }
};

View file

@ -1,4 +1,7 @@
{
"class_name": "ZsmBackend",
"include_path": "zsm_backend.hpp"
"include_path": "zsm_backend.hpp",
"mime_types": [
"audio/x-zsound"
]
}

View file

@ -0,0 +1,39 @@
# Install script for directory: /boot/home/Desktop/looper/backends/playback/zsm
# Set the install prefix
if(NOT DEFINED CMAKE_INSTALL_PREFIX)
set(CMAKE_INSTALL_PREFIX "/boot/system")
endif()
string(REGEX REPLACE "/$" "" CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}")
# Set the install configuration name.
if(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME)
if(BUILD_TYPE)
string(REGEX REPLACE "^[^A-Za-z0-9_]+" ""
CMAKE_INSTALL_CONFIG_NAME "${BUILD_TYPE}")
else()
set(CMAKE_INSTALL_CONFIG_NAME "RelWithDebInfo")
endif()
message(STATUS "Install configuration: \"${CMAKE_INSTALL_CONFIG_NAME}\"")
endif()
# Set the component getting installed.
if(NOT CMAKE_INSTALL_COMPONENT)
if(COMPONENT)
message(STATUS "Install component: \"${COMPONENT}\"")
set(CMAKE_INSTALL_COMPONENT "${COMPONENT}")
else()
set(CMAKE_INSTALL_COMPONENT)
endif()
endif()
# Is this installation the result of a crosscompile?
if(NOT DEFINED CMAKE_CROSSCOMPILING)
set(CMAKE_CROSSCOMPILING "FALSE")
endif()
# Set path to fallback-tool for dependency-resolution.
if(NOT DEFINED CMAKE_OBJDUMP)
set(CMAKE_OBJDUMP "/system/bin/objdump")
endif()

View file

@ -14,6 +14,8 @@ extern "C" {
#include <string.h>
#include <file_backend.hpp>
#include <util.hpp>
#include <license.hpp>
#include <assets/assets.h>
#define HZ (AUDIO_SAMPLERATE)
#define BUFFERS 32
#define _PROPERTY(name, type, default_value) \
@ -205,11 +207,18 @@ void ZsmBackend::tick(bool step) {
} break;
case FmWrite: {
for (uint8_t i = 0; i < cmd.fm_write.len; i++) {
DEBUG.writefln2("YM Pair index: {0}", ym_pairs.size());
reg_pair pair;
memcpy(&pair, cmd.fm_write.regs + i, sizeof(reg_pair));
ym_pairs.push(pair);
DEBUG.writefln2("Writing {1} to FM reg {0} later.", pair.reg, pair.val);
auto &pair = cmd.fm_write.regs[i];
YM_write_reg(pair.reg, pair.val);
while (YM_read_status()) {
size_t clocksToAddForYm = (size_t)std::ceil(((double)YM_FREQ)/((double)PSG_FREQ));
ticks_remaining -= clocksToAddForYm;
if (ticks_remaining < 0) {
delayTicks -= 1;
nextCpuClocks += ClocksPerTick;
ticks_remaining += ClocksPerTick;
}
audio_step(clocksToAddForYm);
}
}
} break;
case Delay: {
@ -258,17 +267,6 @@ void ZsmBackend::tick(bool step) {
}
while (ym_pairs.size() > 0) {
reg_pair pair = ym_pairs.pop();
YM_write_reg(pair.reg, pair.val);
while (YM_read_status()) {
size_t clocksToAddForYm = (size_t)std::ceil(((double)YM_FREQ)/((double)PSG_FREQ));
ticks_remaining -= clocksToAddForYm;
if (ticks_remaining < 0) {
delayTicks -= 1;
nextCpuClocks += ClocksPerTick;
ticks_remaining += ClocksPerTick;
}
audio_step(clocksToAddForYm);
}
}
size_t nextCpuClocksInt = std::floor(nextCpuClocks);
size_t prevCpuClocksInt = std::floor(prevCpuClocks);
@ -491,3 +489,9 @@ void ZsmBackend::audio_step(size_t samples) {
}
audio_buf.push(out_ptr, samples);
}
void ZsmBackend::add_licenses() {
auto &license_data = get_license_data();
auto x16emu = LicenseData("x16emu", "bsd-2-clause");
LOAD_LICENSE(x16emu, x16emu);
license_data.insert(x16emu);
}

View file

@ -134,6 +134,7 @@ class ZsmBackend : public PlaybackBackend {
inline std::string get_name() override {
return "ZSM player";
}
void add_licenses() override;
std::vector<Property> get_property_list() override;
void seek(double position) override;
void load(const char *filename) override;

View file

@ -0,0 +1,11 @@
set(BACKEND_HAIKU_SRC_BASE main.cpp main_window.cpp prefs.cpp slider.cpp slider.h main.h main_window.h aboutwindow.h aboutwindow.cpp prefs.h)
set(BACKEND_HAIKU_SRC )
foreach(SRC IN ITEMS ${BACKEND_HAIKU_SRC_BASE})
set(BACKEND_HAIKU_SRC ${BACKEND_HAIKU_SRC} ${CMAKE_CURRENT_SOURCE_DIR}/${SRC})
endforeach()
set(BACKEND_HAIKU_INC ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR})
add_ui_backend(haiku_ui ${BACKEND_HAIKU_SRC})
target_link_libraries(haiku_ui PRIVATE be tracker SDL2::SDL2 fmt::fmt liblooper)
#target_link_libraries(haiku_ui PRIVATE PkgConfig::GTK4 PkgConfig::gtkmm4)
#target_include_directories(haiku_ui PRIVATE ${BACKEND_HAIKU_INC})

View file

@ -0,0 +1,74 @@
#include "aboutwindow.h"
#include <SplitView.h>
#include <license.hpp>
#include <GroupLayout.h>
#include <SplitView.h>
#include <StringView.h>
#include <ScrollView.h>
#include "main_window.h"
#define CMD_LOAD_LICENSE 0x40
LicenseItem::LicenseItem(const LicenseData license) : BStringItem("") {
SetText(fmt::format("{} ({})", license.Project, license.Spdx).c_str());
this->license_text = license.LicenseContents;
}
AboutWindow::AboutWindow() : BWindow(BRect(100, 100, 600, 400), "About Looper", B_TITLED_WINDOW, B_AUTO_UPDATE_SIZE_LIMITS) {
BGroupLayout *root_layout = new BGroupLayout(B_VERTICAL);
float minW, minH, maxW, maxH;
GetSizeLimits(&minW, &maxW, &minH, &maxH);
SetLayout(root_layout);
root_layout->SetSpacing(0.0);
BFont *title_font = new BFont();
title_font->SetSize(title_font->Size() * 4.0);
BStringView *looper_title = new BStringView("about:title", "Looper");
looper_title->SetAlignment(B_ALIGN_HORIZONTAL_CENTER);
looper_title->SetFont(title_font);
float title_height, version_height;
looper_title->GetPreferredSize(NULL, &title_height);
looper_title->SetExplicitMaxSize(BSize(maxW, title_height));
looper_title->ResizeToPreferred();
BStringView *version_text = new BStringView("about:version_text", fmt::format("Version {}", TAG).c_str());
version_text->SetAlignment(B_ALIGN_HORIZONTAL_CENTER);
version_text->GetPreferredSize(NULL, &version_height);
version_text->SetExplicitMaxSize(BSize(maxW, version_height));
version_text->ResizeToPreferred();
BLayoutItem *title_item = root_layout->AddView(looper_title);
BLayoutItem *version_item = root_layout->AddView(version_text);
title_item->SetExplicitAlignment(BAlignment(B_ALIGN_HORIZONTAL_CENTER, B_ALIGN_VERTICAL_CENTER));
version_item->SetExplicitAlignment(BAlignment(B_ALIGN_HORIZONTAL_CENTER, B_ALIGN_VERTICAL_CENTER));
BSplitView *view = new BSplitView();
view->SetExplicitMaxSize(BSize(maxW, maxH));
root_layout->AddView(view);
license_list = new BListView();
license_list->SetTarget(this);
for (auto &license : get_license_data()) {
license_list->AddItem(new LicenseItem(license));
}
license_list->SetSelectionMessage(new BMessage(CMD_LOAD_LICENSE));
BScrollView *license_list_scroller = new BScrollView("about:license-list-scroller", license_list, B_FOLLOW_ALL_SIDES, B_SUPPORTS_LAYOUT|B_FRAME_EVENTS, false, true);
license_text = new BTextView("about:license-text");
license_text->MakeEditable(false);
BScrollView *license_text_scroller = new BScrollView("about:license-text-scroller", license_text, B_FOLLOW_ALL_SIDES, B_SUPPORTS_LAYOUT|B_FRAME_EVENTS, false, true);
view->AddChild(license_list_scroller);
view->AddChild(license_text_scroller);
license_list->Select(0);
InvalidateLayout(true);
UpdateIfNeeded();
}
void AboutWindow::Show() {
BWindow::Show();
}
bool AboutWindow::QuitRequested() {
Hide();
return quitting;
}
void AboutWindow::MessageReceived(BMessage *msg) {
if (msg->IsSystem()) return;
if (msg->what == CMD_LOAD_LICENSE) {
auto selection = license_list->ItemAt(msg->GetInt32("index", 0));
std::string str = ((LicenseItem*)selection)->license_text;
license_text->SetText(str.c_str());
}
}

View file

@ -0,0 +1,24 @@
#pragma once
#include <Window.h>
#include <Message.h>
#include <TextView.h>
#include <Handler.h>
#include <string>
#include <StringItem.h>
#include <ListView.h>
#include <license.hpp>
class LicenseItem : public BStringItem {
public:
std::string license_text;
LicenseItem(const LicenseData license);
};
class AboutWindow : public BWindow
{
BListView *license_list;
BTextView *license_text;
public:
bool QuitRequested() override;
void Show() override;
void MessageReceived(BMessage *msg) override;
AboutWindow();
};

View file

@ -0,0 +1,39 @@
# Install script for directory: /boot/home/Desktop/looper/backends/ui/haiku
# Set the install prefix
if(NOT DEFINED CMAKE_INSTALL_PREFIX)
set(CMAKE_INSTALL_PREFIX "/boot/system")
endif()
string(REGEX REPLACE "/$" "" CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}")
# Set the install configuration name.
if(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME)
if(BUILD_TYPE)
string(REGEX REPLACE "^[^A-Za-z0-9_]+" ""
CMAKE_INSTALL_CONFIG_NAME "${BUILD_TYPE}")
else()
set(CMAKE_INSTALL_CONFIG_NAME "RelWithDebInfo")
endif()
message(STATUS "Install configuration: \"${CMAKE_INSTALL_CONFIG_NAME}\"")
endif()
# Set the component getting installed.
if(NOT CMAKE_INSTALL_COMPONENT)
if(COMPONENT)
message(STATUS "Install component: \"${COMPONENT}\"")
set(CMAKE_INSTALL_COMPONENT "${COMPONENT}")
else()
set(CMAKE_INSTALL_COMPONENT)
endif()
endif()
# Is this installation the result of a crosscompile?
if(NOT DEFINED CMAKE_CROSSCOMPILING)
set(CMAKE_CROSSCOMPILING "FALSE")
endif()
# Set path to fallback-tool for dependency-resolution.
if(NOT DEFINED CMAKE_OBJDUMP)
set(CMAKE_OBJDUMP "/system/bin/objdump")
endif()

15
backends/ui/haiku/icons.h Normal file
View file

@ -0,0 +1,15 @@
#pragma once
enum LooperIcon {
ICON_EDIT_TEXT = 1000,
ICON_EDIT_SLIDER = 1001,
ICON_PLAY = 1002,
ICON_PAUSE = 1003,
ICON_STOP = 1004,
ICON_REFRESH = 1005,
ICON_CONFIGURE = 1006,
ICON_OPEN = 1007,
ICON_FOLDER = 1008,
ICON_ABOUT = 1009,
ICON_HELP = 1010,
ICON_QUIT = 1011
};

View file

@ -0,0 +1,38 @@
#include "main.h"
#include "main_window.h"
#include <chrono>
using namespace std::chrono_literals;
bool quitting = false;
std::string HaikuUIBackend::get_id() {
return "haiku";
}
std::string HaikuUIBackend::get_name() {
return "Haiku Native";
}
void HaikuUIBackend::QuitHandler() {
LooperWindow *app = (LooperWindow*)main_loop;
app->Hide();
}
static bool about_window_shown = false;
static bool prefs_window_shown = false;
int HaikuUIBackend::run(std::vector<std::string> realArgs, int argc, char **argv) {
int ret = UIBackend::run(realArgs, argc, argv);
if (ret != 0) return ret;
LooperWindow *app = new LooperWindow(playback);
main_loop = (void*)app;
app->Show();
while (!app->IsHidden()) {
for (auto *subwindow : Subwindow::windows) {
if (subwindow->Showing.exchange(false)) {
subwindow->window->Show();
subwindow->ShownEver.store(true);
}
}
std::this_thread::sleep_for(100ms);
}
quitting = true;
for (auto *subwindow : Subwindow::windows) {
if (!subwindow->ShownEver) subwindow->window->Run();
}
return 0;
}

14
backends/ui/haiku/main.h Normal file
View file

@ -0,0 +1,14 @@
#pragma once
#include <backend.hpp>
#include <string>
#include <vector>
class HaikuUIBackend : public UIBackend {
BACKEND_TYPE(Native);
public:
std::string get_id() override;
std::string get_name() override;
void QuitHandler() override;
void *main_loop;
int run(std::vector<std::string> realArgs, int argc, char **argv) override;
HaikuUIBackend() = default;
};

View file

@ -0,0 +1,385 @@
#include "main_window.h"
#include <Button.h>
#include <Slider.h>
#include <Message.h>
#include <GroupView.h>
#include <Messenger.h>
#include <MessageRunner.h>
#include <MenuBar.h>
#include <Path.h>
#include <Menu.h>
#include <MessageFilter.h>
#include <functional>
#include <util.hpp>
#include <MenuItem.h>
#include <thread>
#include <log.hpp>
#include <cmath>
#include <fmt/core.h>
#include <fmt/format.h>
#include <SDL.h>
#include "icons.h"
#include "utils.h"
#include "aboutwindow.h"
#define CMD_MOUSE_DOWN_KEY "catmeow:pressed"
#define CMD_PAUSE_RESUME 0x10
#define CMD_RESTART 0x11
#define CMD_STOP 0x12
#define CMD_OPEN 0x13
#define CMD_ABOUT 0x14
#define CMD_PREFS 0x15
#define CMD_SEEK 0x20
#define CMD_VOLUME 0x21
#define CMD_SPEED 0x22
#define CMD_PITCH 0x23
#define CMD_TEMPO 0x24
#define CMD_UPDATE 0x80
#define SLIDER_SCALE 1000
#define D(x) ((double)(x))
std::vector<Subwindow*> Subwindow::windows;
BMessage *make_slider_msg(uint32_t what, bool down) {
BMessage *msg = new BMessage(what);
msg->SetBool(CMD_MOUSE_DOWN_KEY, down);
return msg;
}
bool is_slider_down_msg(BMessage *msg) {
return msg->HasBool(CMD_MOUSE_DOWN_KEY) && msg->GetBool(CMD_MOUSE_DOWN_KEY);
}
void LooperWindow::UpdateViewFlags(BView *view) {
if (view == NULL) return;
view->SetFlags(view->Flags()|B_SUPPORTS_LAYOUT|B_FRAME_EVENTS);
view->SetResizingMode(B_FOLLOW_ALL_SIDES);
}
void LooperWindow::UpdateViewFlags(BLayout *layout) {
BView *owner = layout->Owner();
if (owner == NULL) {
owner = layout->View();
if (owner == NULL) {
return;
}
}
UpdateViewFlags(owner);
}
LooperWindow::LooperWindow(Playback *playback) : BWindow(BRect(100, 100, 500, 100), "Looper", B_TITLED_WINDOW, 0) {
pause_bitmap = load_icon(ICON_PAUSE);
resume_bitmap = load_icon(ICON_PLAY);
stop_bitmap = load_icon(ICON_STOP);
refresh_bitmap = load_icon(ICON_REFRESH);
ref_handler = new LooperRefHandler(this);
this->playback = playback;
float minW, minH, maxW, maxH;
GetSizeLimits(&minW, &maxW, &minH, &maxH);
minW = 600;
minH = 200;
SetSizeLimits(minW, maxW, minH, maxH);
ResizeTo(minW, minH);
DisableUpdates();
auto about_window = new AboutWindow();
layout = new BGroupLayout(B_VERTICAL);
SetLayout(layout);
layout->SetSpacing(0.0);
layout->SetInsets(0, 0, 0, 0);
BMenuBar *menu_bar = new BMenuBar("main_menu");
file_menu = new BMenu("File");
open_item = new BMenuItem("Open...", new BMessage(CMD_OPEN));
prefs_item = new BMenuItem("Preferences...", new BMessage(CMD_PREFS));
quit_item = new BMenuItem("Quit", new BMessage(B_QUIT_REQUESTED));
help_menu = new BMenu("Help");
about_item = new BMenuItem("About...", new BMessage(CMD_ABOUT));
file_menu->AddItem(open_item);
file_menu->AddItem(prefs_item);
file_menu->AddItem(quit_item);
help_menu->AddItem(about_item);
menu_bar->AddItem(file_menu);
menu_bar->AddItem(help_menu);
layout->AddView(menu_bar);
BView *spacer = new BView("spacer", B_SUPPORTS_LAYOUT|B_FRAME_EVENTS);
spacer->SetExplicitMinSize(BSize(0, 0));
layout->AddView(spacer);
BGroupView *top_row = new BGroupView(B_HORIZONTAL);
BGroupView *bottom_row = new BGroupView(B_HORIZONTAL);
BLayoutItem *top_item = layout->AddView(top_row);
BLayoutItem *bottom_item = layout->AddView(bottom_row);
pause_resume_btn = new BButton(NULL, new BMessage(CMD_PAUSE_RESUME));
pause_resume_btn->SetTarget(this);
top_row->AddChild(pause_resume_btn);
restart_btn = new BButton(NULL, new BMessage(CMD_RESTART));
restart_btn->SetTarget(this);
top_row->AddChild(restart_btn);
slider = new BSlider("seek_slider", "Seek", make_slider_msg(CMD_SEEK, false), 0, INT32_MAX, B_HORIZONTAL);
slider->SetModificationMessage(make_slider_msg(CMD_SEEK, true));
slider->SetTarget(this);
top_row->AddChild(slider);
stop_btn = new BButton(NULL, new BMessage(CMD_STOP));
stop_btn->SetTarget(this);
top_row->AddChild(stop_btn);
volume_slider = new LooperSlider("volume", "Volume", new BMessage(CMD_VOLUME), 0, 0, 100, 1, false);
volume_slider->SetLimitLabels("Muted", "Full Volume");
volume_slider->SetTarget(this);
top_row->AddChild(volume_slider);
speed_slider = new LooperSlider("speed", "Speed", new BMessage(CMD_SPEED), 0, 0.25, 4.0, 0.01, true);
speed_slider->SetLimitLabels("0.25x", "4.00x");
speed_slider->SetTarget(this);
bottom_row->AddChild(speed_slider);
tempo_slider = new LooperSlider("tempo", "Tempo", new BMessage(CMD_TEMPO), 0, 0.25, 4.0, 0.01, true);
tempo_slider->SetLimitLabels("0.25x", "4.00x");
tempo_slider->SetTarget(this);
bottom_row->AddChild(tempo_slider);
pitch_slider = new LooperSlider("pitch", "Pitch", new BMessage(CMD_PITCH), 0, 0.25, 4.0, 0.01, true);
pitch_slider->SetLimitLabels("0.25x", "4.00x");
pitch_slider->SetTarget(this);
bottom_row->AddChild(pitch_slider);
file_panel = new BFilePanel(B_OPEN_PANEL, new BMessenger(this));
auto prefs_window = new PrefsWindow(this);
prefs_subwindow = Subwindow::Add(prefs_window);
about_subwindow = Subwindow::Add(about_window);
EnableUpdates();
InvalidateLayout(true);
BRect top_rect = top_item->Frame();
top_item->SetExplicitMinSize(top_rect.Size());
BRect bottom_rect = bottom_item->Frame();
bottom_item->SetExplicitMinSize(bottom_rect.Size());
Pulse();
this->update_thread = new std::thread(std::mem_fn(&LooperWindow::ThreadFunc), this);
UpdateIfNeeded();
StartWatching(prefs_window, CMD_UPDATE_LABEL_SETTING);
auto *msg = new BMessage(CMD_UPDATE_LABEL_SETTING);
MessageReceived(msg);
delete msg;
}
LooperWindow::~LooperWindow() {
delete ref_handler;
delete pause_bitmap;
delete resume_bitmap;
delete stop_bitmap;
delete refresh_bitmap;
playback->Stop();
done = true;
update_thread->join();
delete update_thread;
}
void LooperWindow::MessageReceived(BMessage *msg) {
SDL_Event ev;
while (SDL_PollEvent(&ev)) {
if (ev.type == SDL_DROPFILE) {
playback->Start(ev.drop.file);
} else if (ev.type == SDL_QUIT) {
Hide();
return;
}
}
if (msg->what == B_REFS_RECEIVED) {
entry_ref ref;
if (msg->FindRef("refs", &ref) != B_OK) { // Don't crash when failing to get ref - This is probably an error in the system or another application
return;
}
BEntry entry(&ref, true);
BPath path;
if (entry.GetPath(&path) != B_OK) { // Don't know how this could cause an error, but don't crash if it does.
return;
}
playback->Start(path.Path());
return;
}
if (msg->IsSystem()) {
switch (msg->what) {
default: {
msg->PrintToStream();
} break;
}
return;
}
switch (msg->what) {
case CMD_PAUSE_RESUME: {
playback->Pause();
} break;
case CMD_RESTART: {
playback->Seek(0.0);
} break;
case CMD_VOLUME: {
playback->SetVolume(msg->GetDouble("be:value", 100));
volume_clicked = is_slider_down_msg(msg);
} break;
case CMD_SPEED: {
playback->SetSpeed(msg->GetDouble("be:value", 1.0));
speed_clicked = is_slider_down_msg(msg);
} break;
case CMD_TEMPO: {
playback->SetTempo(msg->GetDouble("be:value", 1.0));
tempo_clicked = is_slider_down_msg(msg);
} break;
case CMD_PITCH: {
playback->SetPitch(msg->GetDouble("be:value", 1.0));
pitch_clicked = is_slider_down_msg(msg);
} break;
case CMD_SEEK: {
playback->Seek((((double)msg->GetInt32("be:value", 0)) / INT32_MAX) * playback->GetLength());
seek_clicked = is_slider_down_msg(msg);
} break;
case CMD_UPDATE: {
Pulse();
} break;
case CMD_STOP: {
playback->Stop();
} break;
case CMD_OPEN: {
file_panel->Show();
} break;
case CMD_ABOUT: {
about_subwindow->Show();
} break;
case CMD_PREFS: {
prefs_subwindow->Show();
} break;
case CMD_UPDATE_LABEL_SETTING: {
volume_slider->MessageReceived(msg);
speed_slider->MessageReceived(msg);
tempo_slider->MessageReceived(msg);
pitch_slider->MessageReceived(msg);
if (show_labels) {
stop_btn->SetLabel("Stop");
restart_btn->SetLabel("Restart");
} else {
stop_btn->SetLabel("");
restart_btn->SetLabel("");
}
if (show_icons) {
stop_btn->SetIcon(stop_bitmap);
restart_btn->SetIcon(refresh_bitmap);
} else {
stop_btn->SetIcon(get_empty_icon());
restart_btn->SetIcon(get_empty_icon());
}
} break;
case 'DATA': {
status_t err = B_OK;
entry_ref ref;
if ((err = msg->FindRef("refs", &ref)) == B_OK) {
BEntry entry(&ref);
BPath path;
if ((err = entry.GetPath(&path)) == B_OK) {
playback->Start(path.Path());
} else {
WARNING.writefln("entry.GetPath(&path) == %d", (int32)(err));
msg->PrintToStream();
}
} else {
WARNING.writefln("msg->FindRef(\"refs\", &ref) == %d", (int32)(err));
msg->PrintToStream();
}
} break;
default: {
if (msg->HasPointer("catmeow:target")) {
BHandler *ptr = (BHandler*)msg->GetPointer("catmeow:target");
ptr->MessageReceived(msg);
} else {
WARNING.writeln("Unrecognized message type");
msg->PrintToStream();
}
} break;
};
}
LooperLogScaler::LooperLogScaler(double min, double max) {
update_min_max(min, max);
}
void LooperLogScaler::update_min_max(double min, double max) {
x0 = min;
x1 = (max - min) / (exp(1.0) - 1.0);
la = min;
lb = (max - min);
// x0 = scale_log(min);
// x1 = scale_log(max);
}
double LooperLogScaler::scale_log(double value) {
return (std::log(((value - x0) / x1) + 1.0) * lb) + la;
}
double LooperLogScaler::unscale_log(double value) {
return ((std::exp((value - la) / lb) - 1.0) * x1) + x0;
}
void LooperWindow::Pulse() {
auto len = playback->GetLength();
auto pos = playback->GetPosition();
auto pos_milliseconds = pos * 1000.0;
int32_t pos_int32 = (int32_t)((((int64_t)pos_milliseconds) * INT32_MAX) / 1000 / len);
if (!seek_clicked) slider->SetValue(pos_int32);
auto component_count = TimeToComponentCount(len);
bool enable_ui = !playback->IsStopped();
if (enable_ui) {
slider->SetLabel(fmt::format("Position: {}", TimeToString(pos, component_count)).c_str());
slider->SetLimitLabels(TimeToString(0, component_count).c_str(), TimeToString(len, component_count).c_str());
if (show_icons) pause_resume_btn->SetIcon(playback->IsPaused() ? resume_bitmap : pause_bitmap);
if (show_labels) pause_resume_btn->SetLabel(playback->IsPaused() ? "Resume" : "Pause");
} else {
slider->SetLabel("Position");
slider->SetLimitLabels("N/A", "N/A");
if (show_icons) pause_resume_btn->SetIcon(pause_bitmap);
if (show_labels) pause_resume_btn->SetLabel("Pause");
}
if (!show_icons) pause_resume_btn->SetIcon(get_empty_icon());
if (!show_labels) pause_resume_btn->SetLabel("");
slider->SetEnabled(enable_ui);
pause_resume_btn->SetEnabled(enable_ui);
auto volume = playback->GetVolume();
auto pitch = playback->GetPitch();
auto speed = playback->GetSpeed();
auto tempo = playback->GetTempo();
if (!volume_clicked) volume_slider->SetValue(volume);
volume_slider->SetLabel(fmt::format("Volume: {}%", (uint8_t)volume).c_str());
if (!pitch_clicked) pitch_slider->SetValueDouble(pitch);
pitch_slider->SetLabel(fmt::format("Pitch {:.02f}x", pitch).c_str());
if (!speed_clicked) speed_slider->SetValueDouble(speed);
speed_slider->SetLabel(fmt::format("Speed: {:.02f}x", speed).c_str());
if (!tempo_clicked) tempo_slider->SetValueDouble(tempo);
tempo_slider->SetLabel(fmt::format("Tempo: {:.02f}x", tempo).c_str());
UpdateIfNeeded();
}
void LooperWindow::FrameResized(float newWidth, float newHeight) {
InvalidateLayout(true);
Layout(true);
layout->SetExplicitSize(BSize(newWidth, newHeight));
}
void LooperWindow::ThreadFunc() {
while (true) {
if (done) return;
if (Lock()) {
if (!IsHidden()) {
Unlock();
break;
}
Unlock();
} else {
break;
}
}
while (true) {
if (done) return;
if (Lock()) {
if (IsHidden()) {
Unlock();
break;
}
PostMessage(CMD_UPDATE);
Unlock();
} else {
break;
}
std::this_thread::sleep_for(1s / 60.0);
}
}
LooperRefHandler::LooperRefHandler(LooperWindow *win) {
this->win = win;
be_app->Lock();
this->next_handler = be_app->PreferredHandler();
be_app->AddHandler(this);
be_app->SetPreferredHandler(this);
if (next_handler != NULL) {
SetNextHandler(next_handler);
}
AddFilter(new BMessageFilter(B_REFS_RECEIVED));
be_app->Unlock();
}
void LooperRefHandler::MessageReceived(BMessage *msg) {
if (msg->what == B_REFS_RECEIVED) {
win->PostMessage(msg);
}
}

View file

@ -0,0 +1,102 @@
#pragma once
#include <Window.h>
#include <Application.h>
#include <GroupLayout.h>
#include <Slider.h>
#include <playback.h>
#include <thread>
#include <FilePanel.h>
#include <Bitmap.h>
#include <Menu.h>
#include <MenuItem.h>
#include <vector>
#include "aboutwindow.h"
#include "slider.h"
#include "prefs.h"
#include <atomic>
#define CMD_UPDATE_LABEL_SETTING 0x1000
class LooperLogScaler {
double la;
double lb;
public:
double x0;
double x1;
void update_min_max(double min, double max);
LooperLogScaler(double min, double max);
double scale_log(double value);
double unscale_log(double value);
};
extern bool show_labels;
extern bool show_icons;
extern bool quitting;
class Subwindow {
public:
BWindow *window;
static std::vector<Subwindow*> windows;
std::atomic_bool Showing = false;
std::atomic_bool ShownEver = false;
private:
inline Subwindow(BWindow *window)
: window(window)
{ }
public:
inline static Subwindow *Add(BWindow *window) {
auto output = new Subwindow(window);
windows.push_back(output);
return output;
}
inline void Show() {
Showing.store(true);
}
};
class LooperRefHandler;
class LooperWindow : public BWindow {
BSlider *slider;
BBitmap *pause_bitmap;
BBitmap *resume_bitmap;
BBitmap *refresh_bitmap;
BBitmap *stop_bitmap;
BMenu *file_menu;
BMenuItem *open_item;
BMenuItem *prefs_item;
BMenuItem *quit_item;
BMenu *help_menu;
BMenuItem *about_item;
BGroupLayout *layout;
Playback *playback;
BButton *restart_btn;
BButton *stop_btn;
BButton *pause_resume_btn;
bool volume_clicked = false;
bool speed_clicked = false;
bool pitch_clicked = false;
bool tempo_clicked = false;
bool seek_clicked = false;
void UpdateViewFlags(BView *view);
void UpdateViewFlags(BLayout *layout);
LooperSlider *volume_slider;
LooperSlider *speed_slider;
BFilePanel *file_panel;
LooperSlider *pitch_slider;
LooperSlider *tempo_slider;
LooperRefHandler *ref_handler;
std::thread *update_thread = nullptr;
bool done = false;
void Pulse();
void ThreadFunc();
const char *file_to_play = nullptr;
public:
Subwindow *about_subwindow;
Subwindow *prefs_subwindow;
void FrameResized(float newWidth, float newHeight) override;
void MessageReceived(BMessage *msg) override;
LooperWindow(Playback *playback);
~LooperWindow();
};
class LooperRefHandler : public BHandler {
LooperWindow *win;
BHandler *next_handler;
public:
void MessageReceived(BMessage *msg) override;
LooperRefHandler(LooperWindow *win);
};

144
backends/ui/haiku/prefs.cpp Normal file
View file

@ -0,0 +1,144 @@
#include "prefs.h"
#include <OptionPopUp.h>
#include <options.hpp>
#include <backend.hpp>
#include <GroupView.h>
#include <RadioButton.h>
#include <Box.h>
#include <map>
#include "main_window.h"
using namespace Looper::Options;
#define CMD_UPDATE_LABEL_SETTING 0x1000
#define CMD_FRONTEND 0x1001
#define CMD_SET_SETTING 0x1002
#define CMD_REVERT 0x1003
#define CMD_APPLY 0x1004
bool show_icons, show_labels;
PrefsWindow::PrefsWindow(BLooper *next_handler) : BWindow(BRect(100, 100, 0, 0), "Preferences", B_TITLED_WINDOW, B_AUTO_UPDATE_SIZE_LIMITS) {
this->next_handler = next_handler;
auto *root_layout = new BGroupLayout(B_VERTICAL);
SetLayout(root_layout);
root_layout->SetSpacing(0.0);
restart_warning = new BStringView("prefs:restart_needed", "A restart is needed to apply some changes.");
root_layout->AddView(restart_warning);
restart_warning->Hide();
frontend_popup = new BOptionPopUp("prefs:frontend", "Frontend", new BMessage(CMD_FRONTEND));
auto frontend = get_option<std::string>("ui.frontend", "haiku");
for (auto &kv : UIBackend::backends) {
UIBackend *backend = kv.second;
const char *name = backend->get_name().c_str();
frontend_popup->AddOption(name, (int32)backend_ids.size());
std::string id = backend->get_id();
if (id == frontend) cur_option = (int32)backend_ids.size();
backend_ids.push_back(id);
}
BLayoutItem *frontend_item = root_layout->AddView(frontend_popup);
BAlignment align;
align.SetVertical(B_ALIGN_TOP);
frontend_item->SetExplicitAlignment(align);
BBox *box = new BBox("prefs:label_settings_box");
box->SetLabel("Labels and Icons");
auto *label_settings_group = new BGroupView(B_VERTICAL);
BGroupLayout *label_settings_layout = label_settings_group->GroupLayout();
BMessage *labels_only_msg = new BMessage(CMD_SET_SETTING);
labels_only_msg->AddString("pref_path", "ui.haiku.label_setting");
labels_only_msg->AddString("pref_value", "labels");
labels_only = new BRadioButton("prefs:labels_only", "Labels Only", labels_only_msg);
BMessage *icons_only_msg = new BMessage(CMD_SET_SETTING);
icons_only_msg->AddString("pref_path", "ui.haiku.label_setting");
icons_only_msg->AddString("pref_value", "icons");
icons_only = new BRadioButton("prefs:icons_only", "Icons Only", icons_only_msg);
BMessage *both_labels_icons_msg = new BMessage(CMD_SET_SETTING);
both_labels_icons_msg->AddString("pref_path", "ui.haiku.label_setting");
both_labels_icons_msg->AddString("pref_value", "both");
both_labels_icons = new BRadioButton("prefs:both_labels_and_icons", "Both", both_labels_icons_msg);
label_settings_layout->AddView(labels_only);
label_settings_layout->AddView(icons_only);
label_settings_layout->AddView(both_labels_icons);
box->AddChild(label_settings_group);
root_layout->AddView(box, 3.0);
BGroupView *btn_view = new BGroupView(B_HORIZONTAL);
BGroupLayout *btn_box = btn_view->GroupLayout();
revert_btn = new BButton("prefs:revert", "Revert", new BMessage(CMD_REVERT));
apply_btn = new BButton("prefs:apply", "Apply", new BMessage(CMD_APPLY));
root_layout->AddView(btn_view);
btn_box->AddView(revert_btn);
btn_box->AddView(apply_btn);
{
auto *msg = new BMessage(CMD_REVERT);
MessageReceived(msg);
delete msg;
}
}
bool PrefsWindow::QuitRequested() {
Hide();
return quitting;
}
void PrefsWindow::set_options_changed(bool changed) {
revert_btn->SetEnabled(changed);
apply_btn->SetEnabled(changed);
}
void PrefsWindow::update_label_setting() {
std::map<std::string, BRadioButton*> label_settings_map({{"labels", labels_only}, {"icons", icons_only}, {"both", both_labels_icons}});
auto cur_radio_btn = labels_only;
if (!label_settings_map.contains(new_label_setting)) {
new_label_setting = "icons";
}
cur_radio_btn = label_settings_map[new_label_setting];
show_icons = new_label_setting != "labels";
show_labels = new_label_setting != "icons";
cur_radio_btn->SetValue(B_CONTROL_ON);
}
void PrefsWindow::MessageReceived(BMessage *msg) {
if (msg->IsSystem()) return;
switch (msg->what) {
case CMD_APPLY: {
set_options_changed(false);
set_option<std::string>("ui.frontend", new_frontend);
if (new_frontend != "haiku") restart_warning->Show();
else restart_warning->Hide();
set_option<std::string>("ui.haiku.label_setting", new_label_setting);
update_label_setting();
next_handler->PostMessage(CMD_UPDATE_LABEL_SETTING);
} break;
case CMD_REVERT: {
set_options_changed(false);
new_label_setting = get_option<std::string>("ui.haiku.label_setting", "icons");
new_frontend = get_option<std::string>("ui.frontend", "haiki");
if (new_frontend != "haiku") restart_warning->Show();
else restart_warning->Hide();
for (size_t i = 0; i < backend_ids.size(); i++) {
int32 backend_id = (int32)i;
if (backend_ids[i] == new_frontend) {
frontend_popup->SetValue(backend_id);
break;
}
}
update_label_setting();
next_handler->PostMessage(CMD_UPDATE_LABEL_SETTING);
} break;
case CMD_FRONTEND: {
auto option = msg->GetInt32("be:value", cur_option);
if (backend_ids.size() < option && option >= 0) {
new_frontend = backend_ids[option];
}
set_options_changed(true);
} break;
case CMD_SET_SETTING: {
const char *setting;
if (msg->FindString("pref_path", &setting) == B_OK) {
const char *setting_value;
int32 setting_value_int32;
if (msg->FindString("pref_value", &setting_value) == B_OK) {
if (std::string(setting) == "ui.haiku.label_setting") {
new_label_setting = setting_value;
set_options_changed(true);
}
}
}
} break;
}
}

36
backends/ui/haiku/prefs.h Normal file
View file

@ -0,0 +1,36 @@
#pragma once
#include <Window.h>
#include <StringView.h>
#include <GroupLayout.h>
#include <Message.h>
#include <Control.h>
#include <SupportDefs.h>
#include <StringView.h>
#include <RadioButton.h>
#include <Button.h>
#include <OptionPopUp.h>
#include <CheckBox.h>
#include <vector>
#include <string>
#include <map>
class PrefsWindow : public BWindow {
std::vector<std::string> backend_ids;
int32 cur_option = 0;
BLooper *next_handler;
BStringView *restart_warning;
std::string new_label_setting;
std::string new_frontend;
BOptionPopUp *frontend_popup;
BCheckBox *menu_icons;
BRadioButton *labels_only;
BRadioButton *icons_only;
BRadioButton *both_labels_icons;
BButton *revert_btn;
BButton *apply_btn;
void update_label_setting();
void set_options_changed(bool changed);
public:
bool QuitRequested() override;
void MessageReceived(BMessage *msg) override;
PrefsWindow(BLooper *next_handler);
};

View file

@ -0,0 +1,273 @@
#include "slider.h"
#include "main_window.h"
#include <MessageFilter.h>
#include <fmt/core.h>
#include <fmt/format.h>
#include <Bitmap.h>
#include <IconUtils.h>
#include <Application.h>
#include "utils.h"
#include <interface/ControlLook.h>
#include "icons.h"
#define CMD_SLIDER_MOVED 0x90
#define CMD_TEXT_CHANGED 0x91
#define CMD_SLIDER_CHANGED 0x92
#define CMD_CHANGE_MODE 0x93
using namespace BPrivate;
void LooperSlider::UpdateLogScaler() {
scaler->update_min_max(min, max);
}
void LooperSlider::UpdateSlider(bool update_value) {
if (recreate_slider) {
if (slider != NULL) {
if (!text_edit_mode) text_layout->RemoveView(slider);
delete slider;
}
int32 min, max;
if (logarithmic) {
scaler->update_min_max(this->min, this->max);
}
min = std::floor(this->min / tick);
max = std::ceil(this->max / tick);
slider = new BSlider(NULL, NULL, make_self_msg(CMD_SLIDER_CHANGED), min, max, B_HORIZONTAL);
slider->SetModificationMessage(make_self_msg(CMD_SLIDER_MOVED));
BSize slider_min = slider->MinSize();
BSize text_min = text->MinSize();
BSize min_combined = BSize(std::max(slider_min.Width(), text_min.Width()), std::max(slider_min.Height(), text_min.Height()));
slider->SetExplicitMinSize(min_combined);
text->SetExplicitMinSize(min_combined);
slider->SetTarget(this);
if (!text_edit_mode) {
auto item = text_layout->AddView(1, slider);
item->SetExplicitAlignment(BAlignment(B_ALIGN_HORIZONTAL_CENTER, B_ALIGN_VERTICAL_CENTER));
}
}
if (update_value || recreate_slider) slider->SetValue((logarithmic ? scaler->scale_log(this->value) : this->value) / tick);
// slider->SetLimitLabels(min_label == NULL ? "" : min_label, max_label == NULL ? "" : max_label);
min_label_view->SetText(min_label == NULL ? "" : min_label);
max_label_view->SetText(max_label == NULL ? "" : max_label);
if (min_label != NULL || max_label != NULL) {
limits_view->Show();
} else {
limits_view->Hide();
}
recreate_slider = false;
}
void LooperSlider::set_min(double min) {
this->min = min;
recreate_slider = true;
}
void LooperSlider::set_max(double max) {
this->max = max;
recreate_slider = true;
}
void LooperSlider::SetMinLabel(const char *label) {
if (min_label != NULL) free((void*)min_label);
min_label = label == NULL ? NULL : strdup(label);
UpdateSlider();
}
void LooperSlider::SetMaxLabel(const char *label) {
if (max_label != NULL) free((void*)max_label);
max_label = label == NULL ? NULL : strdup(label);
UpdateSlider();
}
void LooperSlider::set_tick(double value) {
this->tick = value;
recreate_slider = true;
}
const char *LooperSlider::MinLabel() {
return min_label;
}
const char *LooperSlider::MaxLabel() {
return max_label;
}
void LooperSlider::SetLimitLabels(const char *min, const char *max) {
SetMinLabel(min);
SetMaxLabel(max);
}
LooperSlider::~LooperSlider() {
if (min_label != NULL) free((void*)min_label);
if (max_label != NULL) free((void*)max_label);
delete slider;
delete btn;
delete text;
delete scaler;
delete text_mode_bitmap;
delete slider_mode_bitmap;
}
void LooperSlider::SetMin(double min) {
set_min(min);
UpdateSlider();
}
void LooperSlider::SetMax(double max) {
set_max(max);
UpdateSlider();
}
double LooperSlider::Min() {
return min;
}
double LooperSlider::Max() {
return max;
}
void LooperSlider::SetLimits(double min, double max) {
set_min(min);
set_max(max);
UpdateSlider();
}
void LooperSlider::SetTick(double value) {
set_tick(value);
UpdateSlider();
}
double LooperSlider::Tick() {
return tick;
}
void LooperSlider::SetLogarithmic(bool logarithmic) {
this->logarithmic = logarithmic;
recreate_slider = true;
UpdateSlider(true);
}
bool LooperSlider::IsLogarithmic() {
return this->logarithmic;
}
void LooperSlider::MessageReceived(BMessage *msg) {
switch (msg->what) {
case CMD_SLIDER_MOVED:
case CMD_SLIDER_CHANGED: {
this->pressed = msg->what == CMD_SLIDER_MOVED;
if (logarithmic) {
SetValueDouble(scaler->unscale_log(((double)msg->GetInt32("be:value", 0) * tick)));
} else {
SetValueDouble(((double)msg->GetInt32("be:value", 0)) * tick);
}
SendChangeMsg();
} break;
case CMD_TEXT_CHANGED: {
bool text_valid = true;
double new_value;
try {
new_value = std::stod(text->Text());
} catch(std::out_of_range) {
text_valid = false;
} catch (std::invalid_argument) {
text_valid = false;
}
if (text_valid) {
SetValueDouble(new_value);
SendChangeMsg();
}
} break;
case CMD_CHANGE_MODE: {
text_edit_mode = !text_edit_mode;
{
auto update_label_msg = new BMessage(CMD_UPDATE_LABEL_SETTING);
MessageReceived(update_label_msg);
delete update_label_msg;
}
if (text_edit_mode) {
pressed = true;
text->SetText(fmt::to_string(ValueDouble()).c_str());
text_layout->RemoveView(slider);
auto item = text_layout->AddView(1, text);
item->SetExplicitAlignment(BAlignment(B_ALIGN_HORIZONTAL_CENTER, B_ALIGN_VERTICAL_CENTER));
} else {
pressed = false;
text_layout->RemoveView(text);
auto item = text_layout->AddView(1, slider);
item->SetExplicitAlignment(BAlignment(B_ALIGN_HORIZONTAL_CENTER, B_ALIGN_VERTICAL_CENTER));
}
} break;
case CMD_UPDATE_LABEL_SETTING: {
const char *precision_text[2] = {"Imprecise", "Precise"};
BBitmap *precision_bitmap[2] = {LooperSlider::slider_mode_bitmap, LooperSlider::text_mode_bitmap};
BBitmap *bitmap = precision_bitmap[text_edit_mode ? 0 : 1];
if (show_labels || bitmap == NULL) {
btn->SetLabel(precision_text[text_edit_mode ? 0 : 1]);
} else {
btn->SetLabel("");
}
if (show_icons && bitmap != NULL) {
btn->SetIcon(bitmap);
} else {
btn->SetIcon(get_empty_icon());
}
} break;
}
}
void LooperSlider::SendChangeMsg() {
BMessage *msg = change_msg;
msg->SetDouble("be:value", this->value);
msg->SetBool("catmeow:pressed", pressed);
Invoke(msg);
}
void LooperSlider::SetValue(int32 value) {
SetValueDouble(value * tick);
}
void LooperSlider::SetValueDouble(double value) {
this->value = value;
BControl::SetValue(std::round(value / tick));
UpdateSlider(true);
}
double LooperSlider::ValueDouble() {
return this->value;
}
void LooperSlider::SetLabel(const char *label) {
this->label = label;
text_label->SetText(label);
}
void LooperSlider::set_logarithmic(bool logarithmic) {
this->logarithmic = logarithmic;
recreate_slider = true;
}
void LooperSlider::SetValueChangedMsg(BMessage *msg) {
this->change_msg = msg;
}
LooperSlider::LooperSlider(const char *name, const char *label, BMessage *msg, uint32_t flags, double min, double max, double tick, bool logarithmic) : BControl(name, label, msg, flags) {
scaler = new LooperLogScaler(min, max);
text_mode_bitmap = load_icon(ICON_EDIT_TEXT);
slider_mode_bitmap = load_icon(ICON_EDIT_SLIDER);
auto *group_layout = new BGroupLayout(B_HORIZONTAL);
SetLayout(group_layout);
group_layout->SetSpacing(0.0);
text_layout_view = new BGroupView(B_VERTICAL);
text_layout = text_layout_view->GroupLayout();
text_layout->SetInsets(0, 0, 0, 0);
text_layout->SetSpacing(0.0);
text_label = new BStringView(NULL, "");
text = new BTextControl(NULL, "", make_self_msg(CMD_TEXT_CHANGED));
text->ResizeToPreferred();
text->SetModificationMessage(make_self_msg(CMD_TEXT_CHANGED));
text_layout->AddView(text_label);
limits_view = new BGroupView(B_HORIZONTAL);
auto limits_layout = limits_view->GroupLayout();
min_label_view = new BStringView(NULL, "");
max_label_view = new BStringView(NULL, "");
text_layout->AddView(limits_view);
auto min_label_item = limits_layout->AddView(min_label_view);
min_label_item->SetExplicitAlignment(BAlignment(B_ALIGN_LEFT, B_ALIGN_TOP));
auto max_label_item = limits_layout->AddView(max_label_view);
max_label_item->SetExplicitAlignment(BAlignment(B_ALIGN_RIGHT, B_ALIGN_TOP));
limits_view->Hide();
text->SetTarget(this);
btn = new BButton("", make_self_msg(CMD_CHANGE_MODE));
btn->SetTarget(this);
group_layout->AddView(0, text_layout_view);
group_layout->AddView(1, btn);
SetValueChangedMsg(msg);
set_min(min);
set_max(max);
set_tick(tick);
set_logarithmic(logarithmic);
UpdateSlider(true);
SetValueDouble(min);
SetLabel(label);
InvalidateLayout(true);
}
void LooperSlider::AttachedToWindow() {
{
BMessage *msg = make_self_msg(CMD_CHANGE_MODE);
MessageReceived(msg);
MessageReceived(msg);
delete msg;
}
}

View file

@ -0,0 +1,75 @@
#pragma once
#include <View.h>
#include <Slider.h>
#include <Button.h>
#include <TextControl.h>
#include <Message.h>
#include <Control.h>
#include <Button.h>
#include <GroupLayout.h>
#include <StringView.h>
#include <GroupView.h>
class LooperLogScaler;
class LooperSlider : public BControl {
inline BMessage *make_self_msg(int32 what) {
auto output = new BMessage(what);
output->AddPointer("catmeow:target", this);
return output;
}
BSlider *slider = NULL;
BButton *btn;
BStringView *text_label;
BStringView *min_label_view;
BStringView *max_label_view;
BGroupView *limits_view;
bool limits_visible = false;
BTextControl *text;
BBitmap *text_mode_bitmap = nullptr;
BBitmap *slider_mode_bitmap = nullptr;
double value;
BGroupView *text_layout_view;
bool pressed = false;
BGroupLayout *text_layout;
LooperLogScaler *scaler;
void UpdateLogScaler();
bool recreate_slider = false;
void UpdateSlider(bool update_value = false);
double min;
double max;
double tick;
bool text_edit_mode = false;
bool logarithmic;
const char *label = NULL;
const char *min_label = NULL;
const char *max_label = NULL;
BMessage *change_msg = NULL;
void set_tick(double value);
void set_min(double min);
void set_max(double max);
void set_logarithmic(bool logarithmic);
void SendChangeMsg();
public:
void SetMin(double min);
double Min();
void SetMax(double max);
double Max();
void SetLimits(double min, double max);
void SetMinLabel(const char *label);
void SetMaxLabel(const char *label);
const char *MinLabel();
const char *MaxLabel();
void SetLimitLabels(const char *min, const char *max);
void SetTick(double value);
void SetValue(int32 value) override;
double Tick();
double ValueDouble();
void SetValueDouble(double value);
void SetLogarithmic(bool logarithmic);
bool IsLogarithmic();
void SetLabel(const char *label) override;
void SetValueChangedMsg(BMessage *msg);
void MessageReceived(BMessage *msg) override;
void AttachedToWindow() override;
LooperSlider(const char *name, const char *label, BMessage *msg, uint32_t flags, double min, double max, double tick = 0.0001, bool logarithmic = false);
~LooperSlider();
};

View file

@ -0,0 +1,4 @@
{
"class_name": "HaikuUIBackend",
"include_path": "main.h"
}

32
backends/ui/haiku/utils.h Normal file
View file

@ -0,0 +1,32 @@
#pragma once
#include <Bitmap.h>
#include <Rect.h>
#include <Application.h>
#include <IconUtils.h>
#include <SupportDefs.h>
#include <TypeConstants.h>
#include <Resources.h>
inline BBitmap *load_icon(int32 id, BRect rect = BRect(0, 0, 16, 16)) {
const void *data = NULL;
size_t size = 0;
data = BApplication::AppResources()->LoadResource(B_VECTOR_ICON_TYPE, id, &size);
if (data != NULL) {
BBitmap *icon = new BBitmap(rect, B_RGBA32);
if (icon->InitCheck() == B_OK && BIconUtils::GetVectorIcon((const uint8 *)data, size, icon) == B_OK) {
return icon;
} else {
delete icon;
}
}
return nullptr;
}
inline BBitmap *make_empty_icon() {
return new BBitmap(BRect(0, 0, 0, 0), B_RGBA32);
}
inline BBitmap *get_empty_icon() {
static BBitmap *empty_icon = nullptr;
if (empty_icon == nullptr) {
empty_icon = make_empty_icon();
}
return empty_icon;
}

View file

@ -9,7 +9,7 @@ option(USE_GLES "Enable using OpenGL ES" ${GLES_NORMALLY_REQUIRED_FOR_ARCHITECTU
option(GLES_VERSION "Version of OpenGL ES" 3)
set(IMGUI_SRC imgui_demo.cpp imgui_draw.cpp imgui_tables.cpp imgui_widgets.cpp imgui.cpp misc/cpp/imgui_stdlib.cpp)
set(IMGUI_BACKEND_SRC imgui_impl_sdlrenderer2.cpp imgui_impl_sdl2.cpp)
set(BACKEND_IMGUI_SRC_BASE main.cpp file_browser.cpp main.cpp RendererBackend.cpp theme.cpp)
set(BACKEND_IMGUI_SRC_BASE main.cpp file_browser.cpp main.cpp RendererBackend.cpp theme.cpp base85.h file_browser.h main.h RendererBackend.h ui_backend.hpp theme.h)
foreach(SRC IN ITEMS ${IMGUI_BACKEND_SRC})
list(APPEND IMGUI_SRC backends/${SRC})
endforeach()
@ -54,6 +54,8 @@ if(DEFINED EMSCRIPTEN)
target_compile_options(imgui_ui PRIVATE "-sUSE_SDL_IMAGE=2")
target_link_options(imgui_ui PUBLIC "-sMAX_WEBGL_VERSION=2" "-sMIN_WEBGL_VERSION=2" "-sFULL_ES3")
target_link_libraries(imgui_ui PRIVATE ${LIBINTL_LIBRARY})
elseif(HAIKU)
target_link_libraries(imgui_ui PRIVATE OpenGL::${GLTarget} SDL2::SDL2 SDL2_image::SDL2_image ${LIBINTL_LIBRARY})
else()
find_package(SDL2 REQUIRED)
find_package(SDL2_image REQUIRED)

View file

@ -3,6 +3,7 @@
#include <string>
#include <vector>
class ImGuiUIBackend : public UIBackend {
BACKEND_TYPE(Fallback);
public:
std::string get_id() override;
std::string get_name() override;
@ -11,4 +12,4 @@ class ImGuiUIBackend : public UIBackend {
int run(std::vector<std::string> realArgs, int argc, char **argv) override;
void add_licenses() override;
ImGuiUIBackend() = default;
};
};

13
haiku-res.rdef Normal file
View file

@ -0,0 +1,13 @@
resource app_signature "application/x-vnd.com.complecwaft.Looper";
resource app_flags B_EXCLUSIVE_LAUNCH;
resource file_types message
{
"types" = "audio",
"types" = "audio/x-zsound",
"types" = "audio/midi",
"types" = "audio/mid",
"types" = "audio/wav",
"types" = "audio/x-wav",
"types" = "audio/x-flac",
"types" = "audio/ogg"
};

32
log.cpp
View file

@ -5,6 +5,8 @@
#ifdef __ANDROID__
#include <android/log.h>
#endif
#include <filesystem>
using namespace std::filesystem;
namespace Looper::Log {
const std::locale LogStream::c_locale = std::locale("C");
std::set<FILE*> LogStream::global_outputs;
@ -16,8 +18,11 @@ namespace Looper::Log {
#endif
std::set<FILE*> LogStream::get_used_outputs() {
std::set<FILE*> used_outputs;
for (auto my_output : outputs) {
used_outputs.insert(my_output);
if (my_log_level >= log_level) {
for (auto my_output : outputs) {
used_outputs.insert(my_output);
}
}
for (auto global_output : global_outputs) {
used_outputs.insert(global_output);
@ -44,15 +49,13 @@ namespace Looper::Log {
std::set<FILE*> used_outputs = get_used_outputs();
for (auto &file : used_outputs) {
fwrite(&chr, 1, 1, file);
fflush(file);
}
}
}
void LogStream::writec(const char chr) {
log_mutex_guard guard(log_mutex);
bool is_newline = (chr == '\n' || chr == '\r');
if (my_log_level < log_level) {
return;
}
writeprefix();
_writec(chr);
if (is_newline) {
@ -164,6 +167,13 @@ namespace Looper::Log {
nested(nested)
{
}
LogStream &LogStream::substream(std::string name) {
if (!this->substreams.contains(name)) {
this->substreams[name] = new LogStream({name}, {this}, my_log_level);
}
return *this->substreams[name];
}
LogStream::LogStream(std::initializer_list<std::string> names, std::initializer_list<LogStream*> streams, int log_level)
: LogStream(names, log_level, true, nullptr)
@ -227,6 +237,7 @@ namespace Looper::Log {
std::string name = get_log_name_by_idx(id);
#ifdef __ANDROID__
std::map<int, android_LogPriority> stream_files = {
{-2, ANDROID_LOG_DEBUG},
{-1, ANDROID_LOG_DEBUG},
{0, ANDROID_LOG_INFO},
{1, ANDROID_LOG_WARN},
@ -234,6 +245,7 @@ namespace Looper::Log {
};
#else
std::map<int, FILE*> stream_files = {
{-2, stderr},
{-1, stderr},
{0, stdout},
{1, stderr},
@ -253,8 +265,18 @@ namespace Looper::Log {
};
return stream_names[idx];
}
static FILE *log_file;
void deinit_logging() {
fclose(log_file);
}
void init_logging() {
path prefs_path(get_prefs_path());
path log_dir = prefs_path / path("looper") / path("logs");
create_directories(log_dir);
log_file = fopen((log_dir / path("looper.log")).c_str(), "a");
LogStream::global_outputs.insert(log_file);
init_logging_custom(_init_logging_normal);
atexit(deinit_logging);
}
LogStream &get_log_stream_by_level(int level) {
return *log_streams[level].top();

View file

@ -31,7 +31,7 @@ namespace Looper::Log {
#endif
std::string line;
LogStream(std::initializer_list<std::string> names, int log_level, bool nested, void* discriminator);
std::map<std::string, LogStream*> substreams;
public:
virtual void _writec(const char chr);
typedef std::lock_guard<std::recursive_mutex> log_mutex_guard;
@ -69,6 +69,7 @@ namespace Looper::Log {
inline void writefln2(fmt::format_string<T...> fmt, T&&... args) {
return vwritefln2(fmt::string_view(fmt), fmt::make_format_args(args...));
}
LogStream &substream(std::string name);
LogStream(std::initializer_list<std::string> names, std::initializer_list<LogStream*> streams, int log_level = 0);
#ifdef __ANDROID__
@ -85,6 +86,7 @@ namespace Looper::Log {
void init_logging_custom(log_stream_creation_function_t fn);
LogStream &get_log_stream_by_level(int level);
#define LOG(level) (Looper::Log::get_log_stream_by_level(level))
#define TRACE LOG(-2)
#define DEBUG LOG(-1)
#define INFO LOG(0)
#define WARNING LOG(1)

View file

@ -10,6 +10,9 @@
#ifdef __EMSCRIPTEN__
#include <emscripten.h>
#endif
#ifdef __HAIKU__
#include <os/AppKit.h>
#endif
#include "web_functions.hpp"
using namespace Looper;
using namespace Looper::Options;
@ -109,7 +112,6 @@ extern "C" int looper_run_as_executable(std::vector<std::string> args) {
auto looper_gpl = LicenseData("Looper (GPL)", "GPL-3.0-or-later");
auto looper = LicenseData("Looper", "MIT OR GPL-3.0-or-later");
auto tomlpp = LicenseData("TOML++", "MIT");
auto smx = LicenseData("SDL Mixer X", "Zlib");
auto cli11 = LicenseData("CLI11", "BSD-3-Clause");
auto jsoncpp = LicenseData("JsonCpp", "MIT");
auto soundtouch = LicenseData("SoundTouch", "LGPL-2.1-only");
@ -117,7 +119,6 @@ extern "C" int looper_run_as_executable(std::vector<std::string> args) {
LOAD_LICENSE(looper_gpl, looper_gpl);
LOAD_LICENSE(looper, looper);
LOAD_LICENSE(tomlpp, tomlplusplus);
LOAD_LICENSE(smx, sdl_mixer_x);
LOAD_LICENSE(cli11, cli11);
LOAD_LICENSE(jsoncpp, jsoncpp);
LOAD_LICENSE(soundtouch, lgpl_2_1);
@ -125,7 +126,6 @@ extern "C" int looper_run_as_executable(std::vector<std::string> args) {
license_data.insert(looper_gpl);
license_data.insert(looper_mit);
license_data.insert(tomlpp);
license_data.insert(smx);
license_data.insert(cli11);
license_data.insert(jsoncpp);
license_data.insert(soundtouch);
@ -160,6 +160,9 @@ extern "C" int looper_run_as_executable(std::vector<std::string> args) {
for (auto kv : UIBackend::backends) {
kv.second->add_licenses();
}
for (auto kv : PlaybackBackendHelper()) {
kv.second->add_licenses();
}
DEBUG.writeln("Loaded frontends: ");
for (auto kv : UIBackend::backends) {
DEBUG.writefln(" - '%s'", kv.first.c_str());
@ -239,6 +242,8 @@ int main(int argc, char **argv) {
executable_path = malloc(size);
size = GetModuleFileNameA(NULL, executable_path, size);
realloc(executable_path, size);
#elif defined(__HAIKU__)
executable_path = strdup(fs::canonical(argv[0]).c_str());
#else
executable_path = strdup(fs::canonical("/proc/self/exe").c_str());
#endif

View file

@ -342,11 +342,7 @@ void PlaybackInstance::LoopFunction() {
std::string file = current_file.value();
if (current_stream >= streams.size() || current_stream < 0 ||
streams[current_stream].name == "" || streams[current_stream].length <= 0) {
if (stream != nullptr) {
current_stream = stream->stream_index;
} else {
current_stream = 0;
}
current_stream = 0;
} else {
LockAudioDevice();
if (process && process->process_running()) process->set_stream_idx(current_stream);
@ -395,16 +391,16 @@ void PlaybackInstance::DeinitLoopFunction() {
playback_ready.store(false);
// ====
Unload();
#ifdef USE_SDL
SDL_CloseAudioDevice(device);
#elif defined(USE_OBOE)
#ifdef USE_OBOE
if (ostream && ostream->getState() != oboe::StreamState::Closed) {
ostream->stop();
ostream->close();
}
ostream.reset();
#elif defined(USE_SDL)
SDL_CloseAudioDevice(device);
SDL_QuitSubSystem(SDL_INIT_AUDIO);
#endif
SDL_QuitSubSystem(SDL_INIT_AUDIO);
delete st;
st = nullptr;
if (buf) free(buf);

View file

@ -1,8 +1,4 @@
#pragma once
#include <SDL_mixer.h>
extern "C" {
#include <vgmstream.h>
}
#ifdef __ANDROID__
#include <oboe/Oboe.h>
#endif
@ -284,8 +280,6 @@ private:
static void SDLCallback(void *userdata, Uint8 *stream, int len);
void Load(const char *file, int idx);
void Unload();
VGMSTREAM *stream;
Mix_Music *music;
std::vector<PlaybackStream> streams;
std::mutex stream_list_mutex;
double real_volume = 1.0;

View file

@ -59,6 +59,7 @@ class PlaybackBackend {
using const_iterator = map::const_iterator;
using reverse_iterator = map::reverse_iterator;
using const_reverse_iterator = map::const_reverse_iterator;
inline virtual void add_licenses() { }
inline virtual std::string get_id() {return "";}
inline virtual std::string get_name() {return "";}
inline virtual void seek(double position) { }

View file

@ -453,6 +453,7 @@ PlaybackProcess::PlaybackProcess(std::string filename, int idx) {
bool PlaybackProcess::process_running() {
if (is_playback_process) return true;
if (other_process != nullptr) return true;
if (!multi_process) return other_process != nullptr;
return kill(pid, 0) == 0;
}
RPCResponse PlaybackProcess::handle_command(RPCCall &call) {
@ -510,6 +511,7 @@ void PlaybackProcess::run_playback_process() {
uint64_t len;
blocking_read(recv_fd, &len, sizeof(len));
std::string in_bytes = std::string(' ', len, std::allocator<char>());
in_bytes.resize(len);
blocking_read(recv_fd, in_bytes.data(), len);
RPCCall call;
if (!call.ParseFromString(in_bytes)) {
@ -599,6 +601,7 @@ std::string PlaybackProcess::get_file_name() {
}
RPCResponse PlaybackProcess::SendCommand(RPCCall *call) {
if (multi_process) {
std::lock_guard guard(ipc_mutex);
uint64_t len;
std::string str = call->SerializeAsString();
len = str.length();
@ -683,7 +686,7 @@ AudioSpec *PlaybackProcess::get_audio_spec() {
return get_property_value<AudioSpec>(PropertyId::SpecProperty);
}
PlaybackProcess::~PlaybackProcess() {
if (init_failed || other_process == nullptr) {
if (init_failed || !process_running()) {
done = true;
return;
}
@ -692,6 +695,7 @@ PlaybackProcess::~PlaybackProcess() {
call.mutable_quit()->CopyFrom(quit_cmd);
SendCommand(&call);
done = true;
if (multi_process) kill(pid, SIGHUP);
}
void PlaybackProcess::threadfunc() {
while (!process_running()) {

View file

@ -46,6 +46,7 @@ class PlaybackProcess {
int pid;
bool init_failed = false;
std::mutex start_mutex;
std::mutex ipc_mutex;
std::condition_variable started;
bool is_playback_process = false;
std::atomic_bool done;

@ -1 +1 @@
Subproject commit 0379bf3a5d52d8542aec1874677c9df5ff9ba5f9
Subproject commit 720da57baba83b3b1829e20133575e57aa1a8a4f

@ -1 +1 @@
Subproject commit 6dae7eb4a5c3a169f3e298392bff4680224aa94a
Subproject commit d144031940543e15423a25ae5a8a74141044862f

View file

@ -1,4 +1,5 @@
#include "util.hpp"
#include "file_backend.hpp"
#ifdef __ANDROID__
#include <SDL.h>
#endif
@ -8,6 +9,36 @@
#include "log.hpp"
#include <fmt/core.h>
#include <fmt/format.h>
std::string _hexdump_line(uint8_t *ptr, size_t i, size_t len) {
std::string output = fmt::format("${:08x}: ", i);
for (size_t j = 0; j < len; j++) {
output += fmt::format("{:02x} ", ptr[j]);
}
size_t remainder = 8 - len;
for (size_t j = 0; j < remainder; j++) {
output += " ";
}
for (size_t j = 0; j < len; j++) {
if (ptr[j] >= ' ' && ptr[j] < 0x7F) {
output += *((char*)(ptr + j));
} else {
output += ".";
}
}
output += "\n";
return output;
}
std::string hexdump(void *ptr, size_t len) {
uint8_t *ptr8 = (uint8_t*)ptr;
size_t len_div_8 = len / 8;
size_t remainder = len % 8;
std::string output;
for (size_t i = 0; i < len_div_8; i++) {
output += _hexdump_line(ptr8 + (i * 8), i * 8, 8);
}
output += _hexdump_line(ptr8 + (len_div_8 * 8), len_div_8 * 8, remainder);
return output;
}
std::string PadZeros(std::string input, size_t required_length) {
return std::string(required_length - std::min(required_length, input.length()), '0') + input;
}
@ -117,7 +148,7 @@ void blocking_write(int fd, const void *buf, const size_t len) {
while (i < len) {
tmp = write(fd, ((uint8_t*)buf) + i, len - i);
if (tmp < 0) {
throw std::exception();
throw CustomException("Failed to write to fd!");
}
i += tmp;
}
@ -128,8 +159,8 @@ void blocking_read(int fd, void *buf, const size_t len) {
size_t i = 0;
while (i < len) {
tmp = read(fd, ((uint8_t*)buf) + i, len - i);
if (tmp < 0) {
throw std::exception();
if (tmp < 0) {
throw CustomException("Failed to read from fd!");
}
i += tmp;
}

View file

@ -23,6 +23,10 @@ std::string PadZeros(std::string input, size_t required_length);
uint8_t TimeToComponentCount(double time_code);
std::string TimeToString(double time_code, uint8_t min_components = 1);
std::string get_prefs_path();
std::string hexdump(void *ptr, size_t len);
inline std::string hexdump(std::string data) {
return hexdump(data.data(), data.length());
}
inline const char *vcformat(const char *format, va_list args) {
va_list args_copy;
va_copy(args_copy, args);