Merge pull request #404 from jpcima/editor-cleanup

User interface update
This commit is contained in:
JP Cimalando 2020-09-11 16:25:17 +02:00 committed by GitHub
commit e8cc1fa2bd
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
36 changed files with 2744 additions and 479 deletions

View file

@ -1,5 +1,5 @@
version: build-{build}
image: Visual Studio 2017
image: Visual Studio 2019
configuration: Release
platform:
- Win32
@ -22,7 +22,7 @@ before_build:
- cmd: git submodule update --init
- cmd: mkdir CMakeBuild
- cmd: cd CMakeBuild
- cmd: cmake .. -G"Visual Studio 15 2017" -A"%platform%" -DSFIZZ_JACK=OFF -DSFIZZ_BENCHMARKS=OFF -DSFIZZ_TESTS=OFF -DSFIZZ_LV2=ON -DSFIZZ_VST=ON -DCMAKE_BUILD_TYPE=Release -DVCPKG_TARGET_TRIPLET=%VCPKG_TRIPLET% -DCMAKE_TOOLCHAIN_FILE=C:/Tools/vcpkg/scripts/buildsystems/vcpkg.cmake
- cmd: cmake .. -G"Visual Studio 16 2019" -A"%platform%" -DSFIZZ_JACK=OFF -DSFIZZ_BENCHMARKS=OFF -DSFIZZ_TESTS=OFF -DSFIZZ_LV2=ON -DSFIZZ_VST=ON -DCMAKE_BUILD_TYPE=Release -DVCPKG_TARGET_TRIPLET=%VCPKG_TRIPLET% -DCMAKE_TOOLCHAIN_FILE=C:/Tools/vcpkg/scripts/buildsystems/vcpkg.cmake
build_script:
- cmd: cmake --build . --config Release -j

View file

@ -3,8 +3,28 @@ include("cmake/Vstgui.cmake")
set(EDITOR_RESOURCES
logo.png
logo_text.png
logo_text_white.png
logo_text@2x.png
logo_text_white@2x.png
background.png
background@2x.png
icon_white.png
icon_white@2x.png
knob48.png
knob48@2x.png
Fonts/fluentui-system-regular-20.ttf
Fonts/Roboto-Regular.ttf
PARENT_SCOPE)
function(copy_editor_resources SOURCE_DIR DESTINATION_DIR)
foreach(res ${EDITOR_RESOURCES})
get_filename_component(_dir "${res}" DIRECTORY)
file(MAKE_DIRECTORY "${DESTINATION_DIR}/${_dir}")
file(COPY "${SOURCE_DIR}/${res}" DESTINATION "${DESTINATION_DIR}/${_dir}")
endforeach()
endfunction()
# editor
add_library(sfizz_editor STATIC EXCLUDE_FROM_ALL
src/editor/EditIds.h
@ -14,8 +34,53 @@ add_library(sfizz_editor STATIC EXCLUDE_FROM_ALL
src/editor/EditorController.h
src/editor/GUIComponents.h
src/editor/GUIComponents.cpp
src/editor/NativeHelpers.h
src/editor/NativeHelpers.cpp
src/editor/layout/main.hpp
src/editor/utility/vstgui_after.h
src/editor/utility/vstgui_before.h)
target_include_directories(sfizz_editor PUBLIC "src")
target_link_libraries(sfizz_editor PRIVATE sfizz-vstgui)
target_link_libraries(sfizz_editor PUBLIC absl::strings)
if(APPLE)
find_library(APPLE_APPKIT_LIBRARY "AppKit")
find_library(APPLE_CORESERVICES_LIBRARY "CoreServices")
find_library(APPLE_FOUNDATION_LIBRARY "Foundation")
target_sources(sfizz_editor PRIVATE
src/editor/NativeHelpers.mm)
target_link_libraries(sfizz_editor PRIVATE
"${APPLE_APPKIT_LIBRARY}"
"${APPLE_CORESERVICES_LIBRARY}"
"${APPLE_FOUNDATION_LIBRARY}")
target_compile_options(sfizz_editor PRIVATE "-fobjc-arc")
endif()
# dependencies
if(WIN32)
#
elseif(APPLE)
#
else()
find_package(PkgConfig REQUIRED)
pkg_check_modules(sfizz-gio "gio-2.0" REQUIRED)
target_include_directories(sfizz_editor PRIVATE ${sfizz-gio_INCLUDE_DIRS})
target_link_libraries(sfizz_editor PRIVATE ${sfizz-gio_LIBRARIES})
endif()
target_include_directories(sfizz_editor PRIVATE "../src/external") # ghc::filesystem
# layout tool
if(NOT CMAKE_CROSSCOMPILING)
add_executable(layout-maker
"tools/layout-maker/sources/layout.h"
"tools/layout-maker/sources/reader.cpp"
"tools/layout-maker/sources/reader.h"
"tools/layout-maker/sources/main.cpp")
target_link_libraries(layout-maker PRIVATE absl::strings)
add_custom_command(
OUTPUT "${CMAKE_CURRENT_SOURCE_DIR}/src/editor/layout/main.hpp"
COMMAND "$<TARGET_FILE:layout-maker>"
"${CMAKE_CURRENT_SOURCE_DIR}/layout/main.fl"
> "${CMAKE_CURRENT_SOURCE_DIR}/src/editor/layout/main.hpp"
DEPENDS layout-maker "${CMAKE_CURRENT_SOURCE_DIR}/layout/main.fl")
endif()

View file

@ -201,6 +201,8 @@ endif()
if(CMAKE_SYSTEM_NAME STREQUAL "Windows")
# higher C++ requirement on Windows
set_property(TARGET sfizz-vstgui PROPERTY CXX_STANDARD 14)
# Windows 10 RS2 DDI for custom fonts
target_compile_definitions(sfizz-vstgui PRIVATE "NTDDI_VERSION=0x0A000003")
endif()
if (CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")

@ -1 +1 @@
Subproject commit 7316f9fb2891b9f0e2a408cfbf4ec35aeec268bd
Subproject commit 104172476111a255a87d9853a4b6502071130b9d

316
editor/layout/main.fl Normal file
View file

@ -0,0 +1,316 @@
# data file for the Fltk User Interface Designer (fluid)
version 1.0305
header_name {.h}
code_name {.cxx}
widget_class mainView {open
xywh {572 266 800 475} type Double
class LogicalGroup visible
} {
Fl_Box {} {
image {../resources/background.png} xywh {190 110 600 280}
class Background
}
Fl_Group {} {
comment {theme=darkTheme}
xywh {0 0 800 110}
class LogicalGroup
} {
Fl_Group {} {open
xywh {5 4 175 101} box ROUNDED_BOX align 0
class RoundedGroup
} {
Fl_Box {} {
comment {tag=kTagFirstChangePanel+kPanelGeneral}
image {../resources/logo_text_white.png} xywh {35 9 120 60}
class SfizzMainButton
}
Fl_Button {} {
comment {tag=kTagFirstChangePanel+kPanelGeneral}
xywh {49 73 25 25} labelsize 24
class HomeButton
}
Fl_Button {} {
comment {tag=kTagFirstChangePanel+kPanelControls}
xywh {81 73 25 25} labelsize 24
class CCButton
}
Fl_Button {} {
comment {tag=kTagFirstChangePanel+kPanelSettings}
xywh {112 73 25 25} labelsize 24
class SettingsButton
}
}
Fl_Group {} {open
xywh {185 5 380 100} box ROUNDED_BOX
class RoundedGroup
} {
Fl_Box {} {
label {File:}
xywh {200 13 40 30} labelsize 16
class Label
}
Fl_Box {} {
label {KS:}
xywh {200 45 40 30} labelsize 16
class Label
}
Fl_Box {} {
label {Separator 1}
xywh {195 41 360 5} box BORDER_BOX labeltype NO_LABEL
class HLine
}
Fl_Box {} {
label {Separator 2}
xywh {195 73 360 5} box BORDER_BOX labeltype NO_LABEL
class HLine
}
Fl_Box sfzFileLabel_ {
label {DefaultInstrument.sfz}
xywh {265 12 230 30} labelsize 20
class Label
}
Fl_Box {} {
label {Key switch}
xywh {265 44 230 30} labelsize 20
class Label
}
Fl_Box {} {
label {Voices:}
xywh {195 76 60 25} labelsize 12 align 24
class Label
}
Fl_Button {} {
comment {tag=kTagLoadSfzFile}
xywh {500 14 25 25} labelsize 24
class LoadFileButton
}
Fl_Button {} {
comment {tag=kTagEditSfzFile}
xywh {525 14 25 25} labelsize 24
class EditFileButton
}
Fl_Box infoVoicesLabel_ {
xywh {260 76 50 25} labelsize 12 align 16
class Label
}
Fl_Box {} {
label {Max:}
xywh {315 76 60 25} labelsize 12 align 24
class Label
}
Fl_Box numVoicesLabel_ {
xywh {380 76 50 25} labelsize 12 align 16
class Label
}
Fl_Box {} {
label {Memory:}
xywh {435 76 60 25} labelsize 12 align 24
class Label
}
Fl_Box memoryLabel_ {
xywh {500 76 50 25} labelsize 12 align 16
class Label
}
}
Fl_Group {} {open
xywh {570 5 225 100} box ROUNDED_BOX
class RoundedGroup
} {
Fl_Dial {} {
xywh {615 20 48 48} value 0.5 hide
class Knob48
}
Fl_Box {} {
label Center
xywh {610 70 60 5} labelsize 12 hide
class ValueLabel
}
Fl_Dial volumeSlider_ {
comment {tag=kTagSetVolume}
xywh {680 20 48 48} value 0.5
class Knob48
}
Fl_Box volumeLabel_ {
label {0.0 dB}
xywh {675 70 60 22} labelsize 12
class ValueLabel
}
Fl_Box {} {
xywh {745 20 35 55} box BORDER_BOX
class VMeter
}
}
}
Fl_Group {subPanels_[kPanelGeneral]} {
xywh {5 110 791 285} hide
class LogicalGroup
} {
Fl_Group {} {open
xywh {5 110 175 280} box ROUNDED_BOX
class RoundedGroup
} {
Fl_Box {} {
label {Curves:}
xywh {20 120 60 25} align 20
class Label
}
Fl_Box {} {
label {Masters:}
xywh {20 145 60 25} align 20
class Label
}
Fl_Box {} {
label {Groups:}
xywh {20 170 60 25} align 20
class Label
}
Fl_Box {} {
label {Regions:}
xywh {20 195 60 25} align 20
class Label
}
Fl_Box {} {
label {Samples:}
xywh {20 220 60 25} align 20
class Label
}
Fl_Box infoCurvesLabel_ {
label 0
xywh {120 120 40 25} align 16
class Label
}
Fl_Box infoMastersLabel_ {
label 0
xywh {120 145 40 25} align 16
class Label
}
Fl_Box infoGroupsLabel_ {
label 0
xywh {120 170 40 25} align 16
class Label
}
Fl_Box infoRegionsLabel_ {
label 0
xywh {120 195 40 25} align 16
class Label
}
Fl_Box infoSamplesLabel_ {
label 0
xywh {120 220 40 25} align 16
class Label
}
}
}
Fl_Group {subPanels_[kPanelControls]} {
xywh {5 110 790 285} hide
class LogicalGroup
} {
Fl_Group {} {open
xywh {5 110 790 285} box ROUNDED_BOX
class RoundedGroup
} {
Fl_Box {} {
label {Controls not available}
xywh {5 110 790 285} labelsize 40
class Label
}
}
}
Fl_Group {subPanels_[kPanelSettings]} {open
xywh {5 109 790 286}
class LogicalGroup
} {
Fl_Group {} {
label Engine open selected
xywh {260 135 280 100} box ROUNDED_BOX labelsize 12 align 17
class TitleGroup
} {
Fl_Spinner numVoicesSlider_ {
comment {tag=kTagSetNumVoices}
xywh {285 195 60 25} labelsize 12 textsize 12
class ValueMenu
}
Fl_Box {} {
label Polyphony
xywh {275 155 80 25} labelsize 12
class ValueLabel
}
Fl_Spinner oversamplingSlider_ {
comment {tag=kTagSetOversampling}
xywh {370 195 60 25} labelsize 12 textsize 12
class ValueMenu
}
Fl_Box {} {
label Oversampling
xywh {360 155 80 25} labelsize 12
class ValueLabel
}
Fl_Box {} {
label {Preload size}
xywh {445 155 80 25} labelsize 12
class ValueLabel
}
Fl_Spinner preloadSizeSlider_ {
comment {tag=kTagSetPreloadSize}
xywh {455 195 60 25} labelsize 12 textsize 12
class ValueMenu
}
}
Fl_Group {} {
label Tuning open
xywh {205 270 390 100} box ROUNDED_BOX labelsize 12 align 17
class TitleGroup
} {
Fl_Box {} {
label {Root key}
xywh {330 290 80 25} labelsize 12
class ValueLabel
}
Fl_Spinner tuningFrequencySlider_ {
comment {tag=kTagSetTuningFrequency}
xywh {425 330 60 25} labelsize 12 textsize 12
class ValueMenu
}
Fl_Box {} {
label Frequency
xywh {415 290 80 25} labelsize 12
class ValueLabel
}
Fl_Dial stretchedTuningSlider_ {
comment {tag=kTagSetStretchedTuning}
xywh {515 315 48 48} value 0.5
class Knob48
}
Fl_Box {} {
label Stretch
xywh {500 290 80 25} labelsize 12
class ValueLabel
}
Fl_Box {} {
label {Scala file}
xywh {225 290 100 25} labelsize 12
class ValueLabel
}
Fl_Button scalaFileButton_ {
label DefaultScale
comment {tag=kTagLoadScalaFile}
xywh {225 330 100 25} labelsize 12
class ValueButton
}
Fl_Spinner scalaRootKeySlider_ {
comment {tag=kTagSetScalaRootKey}
xywh {340 330 35 25} labelsize 12 textsize 12
class ValueMenu
}
Fl_Spinner scalaRootOctaveSlider_ {
comment {tag=kTagSetScalaRootKey}
xywh {375 330 30 25} labelsize 12 textsize 12
class ValueMenu
}
}
}
Fl_Box {} {
xywh {5 400 790 70}
class Piano
}
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

BIN
editor/resources/knob.knob Normal file

Binary file not shown.

BIN
editor/resources/knob48.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 90 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

View file

@ -0,0 +1,252 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
inkscape:export-ydpi="192"
inkscape:export-xdpi="192"
inkscape:export-filename="/home/jpc/documents/projects/sfizz/editor/resources/logo_text@2x.png"
inkscape:version="1.0 (4035a4fb49, 2020-05-01)"
sodipodi:docname="logo_text.svg"
id="svg8"
version="1.1"
viewBox="0 0 105.83333 66.145836"
height="250"
width="400">
<title
id="title1469">sfizz logo</title>
<defs
id="defs2">
<linearGradient
id="linearGradient1445"
inkscape:collect="always">
<stop
id="stop1441"
offset="0"
style="stop-color:#646464;stop-opacity:1" />
<stop
id="stop1443"
offset="1"
style="stop-color:#000000;stop-opacity:1" />
</linearGradient>
<inkscape:path-effect
effect="fillet_chamfer"
id="path-effect1150"
is_visible="true"
lpeversion="1"
satellites_param="F,0,0,1,0,1,0,2 @ F,0,0,1,0,0,0,2 @ F,0,0,1,0,1,0,2 @ F,0,0,1,0,0,0,2 | F,0,0,1,0,0,0,2 @ F,0,0,1,0,0.47797039,0,2 @ F,0,0,1,0,0,0,2 @ F,0,0,1,0,0.51256137,0,2 | F,0,0,1,0,0,0,2 @ F,0,0,1,0,0.33778335,0,2 @ F,0,0,1,0,0,0,2 @ F,0,0,1,0,0.27944107,0,2 | F,0,0,1,0,0,0,2 @ F,0,0,1,0,0.25554572,0,2 @ F,0,0,1,0,0,0,2 @ F,0,0,1,0,0.29009315,0,2"
unit="mm"
method="auto"
mode="C"
radius="1"
chamfer_steps="2"
flexible="false"
use_knot_distance="true"
apply_no_radius="true"
apply_with_radius="true"
only_selected="false"
hide_knots="false" />
<inkscape:path-effect
hide_knots="false"
only_selected="false"
apply_with_radius="true"
apply_no_radius="true"
use_knot_distance="true"
flexible="false"
chamfer_steps="2"
radius="1"
mode="C"
method="auto"
unit="mm"
satellites_param="F,0,0,1,0,1,0,2 @ F,0,0,1,0,0,0,2 @ F,0,0,1,0,1,0,2 @ F,0,0,1,0,0,0,2 | F,0,0,1,0,0,0,2 @ F,0,0,1,0,0.47797039,0,2 @ F,0,0,1,0,0,0,2 @ F,0,0,1,0,0.51256137,0,2 | F,0,0,1,0,0,0,2 @ F,0,0,1,0,0.33778335,0,2 @ F,0,0,1,0,0,0,2 @ F,0,0,1,0,0.27944107,0,2 | F,0,0,1,0,0,0,2 @ F,0,0,1,0,0.25554572,0,2 @ F,0,0,1,0,0,0,2 @ F,0,0,1,0,0.29009315,0,2"
lpeversion="1"
is_visible="true"
id="path-effect1136"
effect="fillet_chamfer" />
<inkscape:path-effect
hide_knots="false"
only_selected="false"
apply_with_radius="true"
apply_no_radius="true"
use_knot_distance="true"
flexible="false"
chamfer_steps="2"
radius="1"
mode="C"
method="auto"
unit="mm"
satellites_param="F,0,0,1,0,1,0,2 @ F,0,0,1,0,0,0,2 @ F,0,0,1,0,1,0,2 @ F,0,0,1,0,0,0,2 | F,0,0,1,0,0,0,2 @ F,0,0,1,0,0.47797039,0,2 @ F,0,0,1,0,0,0,2 @ F,0,0,1,0,0.51256137,0,2 | F,0,0,1,0,0,0,2 @ F,0,0,1,0,0.33778335,0,2 @ F,0,0,1,0,0,0,2 @ F,0,0,1,0,0.27944107,0,2 | F,0,0,1,0,0,0,2 @ F,0,0,1,0,0.25554572,0,2 @ F,0,0,1,0,0,0,2 @ F,0,0,1,0,0.29009315,0,2"
lpeversion="1"
is_visible="true"
id="path-effect968"
effect="fillet_chamfer" />
<inkscape:path-effect
effect="fillet_chamfer"
id="path-effect921"
is_visible="true"
lpeversion="1"
satellites_param="F,0,0,1,0,1,0,2 @ F,0,0,1,0,0,0,2 @ F,0,0,1,0,1,0,2 @ F,0,0,1,0,0,0,2 | F,0,0,1,0,0,0,2 @ F,0,0,1,0,0.47797039,0,2 @ F,0,0,1,0,0,0,2 @ F,0,0,1,0,0.51256137,0,2 | F,0,0,1,0,0,0,2 @ F,0,0,1,0,0.33778335,0,2 @ F,0,0,1,0,0,0,2 @ F,0,0,1,0,0.27944107,0,2 | F,0,0,1,0,0,0,2 @ F,0,0,1,0,0.25554572,0,2 @ F,0,0,1,0,0,0,2 @ F,0,0,1,0,0.29009315,0,2"
unit="mm"
method="auto"
mode="C"
radius="1"
chamfer_steps="2"
flexible="false"
use_knot_distance="true"
apply_no_radius="true"
apply_with_radius="true"
only_selected="false"
hide_knots="false" />
<inkscape:path-effect
hide_knots="false"
only_selected="false"
apply_with_radius="true"
apply_no_radius="true"
use_knot_distance="true"
flexible="false"
chamfer_steps="2"
radius="1"
mode="C"
method="auto"
unit="mm"
satellites_param="F,0,0,1,0,1,0,2 @ F,0,0,1,0,0,0,2 @ F,0,0,1,0,1,0,2 @ F,0,0,1,0,0,0,2 | F,0,0,1,0,0,0,2 @ F,0,0,1,0,0.47797039,0,2 @ F,0,0,1,0,0,0,2 @ F,0,0,1,0,0.51256137,0,2 | F,0,0,1,0,0,0,2 @ F,0,0,1,0,0.33778335,0,2 @ F,0,0,1,0,0,0,2 @ F,0,0,1,0,0.27944107,0,2 | F,0,0,1,0,0,0,2 @ F,0,0,1,0,0.25554572,0,2 @ F,0,0,1,0,0,0,2 @ F,0,0,1,0,0.29009315,0,2"
lpeversion="1"
is_visible="true"
id="path-effect1183"
effect="fillet_chamfer" />
<inkscape:path-effect
end_linecap_type="zerowidth"
scale_width="1"
miter_limit="4"
linejoin_type="round"
start_linecap_type="zerowidth"
interpolator_beta="0.2"
interpolator_type="CubicBezierFit"
sort_points="true"
offset_points="0.19099662,0.36320029 | 0.41721681,0.40988822 | 0.9095762,0.070646707"
lpeversion="1"
is_visible="true"
id="path-effect1172"
effect="powerstroke" />
<clipPath
id="clipPath917"
clipPathUnits="userSpaceOnUse">
<rect
y="68.872978"
x="24.792475"
height="25.252825"
width="39.659527"
id="rect919"
style="fill:#ffffff;stroke:none;stroke-width:2;stroke-linecap:round;paint-order:markers stroke fill" />
</clipPath>
<linearGradient
gradientUnits="userSpaceOnUse"
y2="231.60674"
x2="539.22601"
y1="190.42654"
x1="539.22601"
id="linearGradient1447"
xlink:href="#linearGradient1445"
inkscape:collect="always"
gradientTransform="translate(34.589224,10.333824)" />
</defs>
<sodipodi:namedview
fit-margin-bottom="10"
fit-margin-right="10"
fit-margin-left="10"
fit-margin-top="10"
inkscape:snap-bbox-midpoints="true"
inkscape:snap-center="true"
inkscape:snap-bbox-edge-midpoints="true"
inkscape:bbox-paths="true"
inkscape:snap-bbox="true"
inkscape:guide-bbox="true"
inkscape:window-maximized="1"
inkscape:window-y="27"
inkscape:window-x="0"
inkscape:window-height="1008"
inkscape:window-width="1920"
showguides="false"
inkscape:snap-global="false"
showgrid="false"
inkscape:document-rotation="0"
inkscape:current-layer="layer1"
inkscape:document-units="px"
inkscape:cy="53.822531"
inkscape:cx="17.632385"
inkscape:zoom="1"
inkscape:pageshadow="2"
inkscape:pageopacity="0.0"
borderopacity="1.0"
bordercolor="#666666"
pagecolor="#ffffff"
id="base"
units="px">
<sodipodi:guide
id="guide899"
orientation="1,0"
position="-452.4563,176.31198" />
<sodipodi:guide
id="guide901"
orientation="0,-1"
position="-351.71366,154.32488" />
<sodipodi:guide
id="guide1008"
orientation="1,0"
position="-536.98274,156.82863" />
<sodipodi:guide
id="guide1185"
orientation="1,0"
position="-351.75629,154.33106" />
</sodipodi:namedview>
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title>sfizz logo</dc:title>
<dc:date>2020-05-16</dc:date>
<dc:creator>
<cc:Agent>
<dc:title>Tobiasz 'unfa' Karoń</dc:title>
</cc:Agent>
</dc:creator>
<dc:rights>
<cc:Agent>
<dc:title>CC-0</dc:title>
</cc:Agent>
</dc:rights>
<cc:license
rdf:resource="http://creativecommons.org/publicdomain/zero/1.0/" />
</cc:Work>
<cc:License
rdf:about="http://creativecommons.org/publicdomain/zero/1.0/">
<cc:permits
rdf:resource="http://creativecommons.org/ns#Reproduction" />
<cc:permits
rdf:resource="http://creativecommons.org/ns#Distribution" />
<cc:permits
rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
</cc:License>
</rdf:RDF>
</metadata>
<g
transform="translate(-495.92008,-191.91875)"
id="layer1"
inkscape:groupmode="layer"
inkscape:label="Layer 1">
<path
id="path1439"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:34.8154px;line-height:1.25;font-family:ABeeZee;-inkscape-font-specification:ABeeZee;letter-spacing:0px;word-spacing:0px;fill:url(#linearGradient1447);fill-opacity:1;stroke:none;stroke-width:0.264584"
d="m 569.95053,215.93967 h 13.61282 v 2.40226 l -9.9572,12.91651 h 10.13128 v 2.78523 h -13.99579 v -2.47189 l 9.99202,-12.91651 h -9.78313 z m -16.4328,0 h 13.61282 v 2.40226 l -9.9572,12.91651 h 10.13128 v 2.78523 h -13.99579 v -2.47189 l 9.99202,-12.91651 h -9.78313 z m -6.38378,18.104 h -3.13338 l 3.1682,-18.104 h 3.13339 z m 2.33264,-21.20257 c -0.64989,0 -1.14891,-0.18568 -1.49707,-0.55705 -0.32494,-0.39457 -0.48741,-0.84717 -0.48741,-1.3578 0,-0.74273 0.2321,-1.33459 0.69631,-1.77559 0.4642,-0.46421 1.04446,-0.69631 1.74077,-0.69631 0.64989,0 1.1373,0.19729 1.46224,0.59187 0.34815,0.37136 0.52223,0.81235 0.52223,1.32298 0,0.74273 -0.2321,1.34619 -0.6963,1.8104 -0.46421,0.441 -1.04446,0.6615 -1.74077,0.6615 z m -12.24537,3.76006 h 5.36157 l -0.48741,2.7156 h -5.36157 l -3.06376,17.23362 c -0.18568,1.02125 -0.4526,1.88003 -0.80075,2.57634 -0.34815,0.71952 -0.76594,1.29978 -1.25336,1.74077 -0.48741,0.44099 -1.04446,0.75433 -1.67114,0.94002 -0.62667,0.20889 -1.29977,0.31334 -2.01929,0.31334 -0.76594,0 -1.46225,-0.10445 -2.08892,-0.31334 -0.64989,-0.20889 -1.21854,-0.49902 -1.70596,-0.87039 l 1.25336,-2.57634 c 0.32494,0.32495 0.70791,0.58026 1.1489,0.76594 0.41779,0.18568 0.8936,0.27852 1.42744,0.27852 0.62667,0 1.16051,-0.2205 1.6015,-0.66149 0.46421,-0.44099 0.78915,-1.14891 0.97484,-2.12374 l 3.06375,-17.30325 h -2.78523 l 0.48741,-2.7156 h 2.78524 l 0.52223,-2.78523 c 0.39457,-2.13535 1.14891,-3.65562 2.263,-4.56082 1.11409,-0.92841 2.54152,-1.39262 4.28229,-1.39262 0.95162,0 1.83361,0.12766 2.64597,0.38297 0.81236,0.23211 1.54348,0.52224 2.19337,0.87039 l -1.21854,2.64597 c -0.53383,-0.27853 -1.09088,-0.53384 -1.67114,-0.76594 -0.55704,-0.23211 -1.21853,-0.34816 -1.98447,-0.34816 -0.85878,0 -1.5899,0.25531 -2.19337,0.76594 -0.60347,0.48742 -0.99804,1.25336 -1.18373,2.29782 z m -21.96217,13.36911 c 0.60347,0.53384 1.3578,0.96323 2.263,1.28817 0.92841,0.32495 1.91485,0.48742 2.95931,0.48742 1.29977,0 2.2746,-0.20889 2.92449,-0.62668 0.6731,-0.44099 1.00965,-0.99804 1.00965,-1.67114 0,-0.34815 -0.0696,-0.6731 -0.20889,-0.97483 -0.11605,-0.30173 -0.34816,-0.59186 -0.69631,-0.87039 -0.32495,-0.27852 -0.77755,-0.54544 -1.3578,-0.80075 -0.58026,-0.27852 -1.33459,-0.58025 -2.263,-0.9052 -1.71756,-0.58026 -2.99413,-1.26496 -3.8297,-2.05411 -0.83557,-0.81236 -1.25335,-1.92645 -1.25335,-3.34228 0,-0.69631 0.15087,-1.34619 0.4526,-1.94966 0.32495,-0.60347 0.77755,-1.1257 1.3578,-1.56669 0.60347,-0.46421 1.32299,-0.82397 2.15856,-1.07928 0.85878,-0.25531 1.83361,-0.38297 2.92449,-0.38297 1.18372,0 2.21658,0.12766 3.09857,0.38297 0.9052,0.2321 1.71756,0.53383 2.43708,0.9052 l -0.87039,2.57634 c -0.62667,-0.37137 -1.34619,-0.6731 -2.15855,-0.9052 -0.78915,-0.2321 -1.67114,-0.34815 -2.64597,-0.34815 -1.20693,0 -2.12374,0.24371 -2.75042,0.73112 -0.62668,0.48741 -0.94002,1.02125 -0.94002,1.60151 0,0.27852 0.0464,0.53383 0.13927,0.76594 0.11605,0.2321 0.31333,0.4526 0.59186,0.66149 0.27852,0.20889 0.64988,0.41779 1.11409,0.62668 0.46421,0.20889 1.04446,0.42938 1.74077,0.66149 1.13731,0.39457 2.10053,0.80075 2.88968,1.21854 0.78915,0.39457 1.42743,0.83557 1.91485,1.32298 0.48741,0.48742 0.83557,1.02126 1.04446,1.60151 0.20889,0.55705 0.31334,1.18372 0.31334,1.88003 0,0.81236 -0.17408,1.54348 -0.52223,2.19337 -0.34816,0.64989 -0.83558,1.20693 -1.46225,1.67114 -0.62668,0.44099 -1.39262,0.77754 -2.29782,1.00965 -0.88199,0.25531 -1.86842,0.38297 -2.95931,0.38297 -1.39261,0 -2.63436,-0.17408 -3.72524,-0.52223 -1.09089,-0.34815 -1.99609,-0.80075 -2.71561,-1.3578 z"
sodipodi:nodetypes="cccccccccccccccccccccccccccscscscscsccccccscsccccsccccccccsccccscccccscscccccscccsccccssscssccccssccsscc" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4 KiB

File diff suppressed because it is too large Load diff

View file

@ -5,34 +5,456 @@
// If not, contact the sfizz maintainers at https://github.com/sfztools/sfizz
#include "GUIComponents.h"
#include <cmath>
#include "utility/vstgui_before.h"
#include "vstgui/lib/cdrawcontext.h"
#include "vstgui/lib/cgraphicspath.h"
#include "vstgui/lib/cframe.h"
#include "utility/vstgui_after.h"
SimpleSlider::SimpleSlider(const CRect& bounds, IControlListener* listener, int32_t tag)
: CSliderBase(bounds, listener, tag)
///
SBoxContainer::SBoxContainer(const CRect& size)
: CViewContainer(size)
{
setStyle(kHorizontal|kLeft);
CPoint offsetHandle(2.0, 2.0);
setOffsetHandle(offsetHandle);
CCoord handleSize = 20.0;
setHandleSizePrivate(handleSize, bounds.bottom - bounds.top - 2 * offsetHandle.y);
setHandleRangePrivate(bounds.right - bounds.left - handleSize - 2 * offsetHandle.x);
CViewContainer::setBackgroundColor(CColor(0, 0, 0, 0));
}
void SimpleSlider::draw(CDrawContext* dc)
void SBoxContainer::setCornerRadius(CCoord radius)
{
cornerRadius_ = radius;
setDirty();
}
void SBoxContainer::setBackgroundColor(const CColor& color)
{
backgroundColor_ = color;
setDirty();
}
CColor SBoxContainer::getBackgroundColor() const
{
return backgroundColor_;
}
void SBoxContainer::drawRect(CDrawContext* dc, const CRect& updateRect)
{
CRect bounds = getViewSize();
CRect handle = calculateHandleRect(getValueNormalized());
dc->setDrawMode(kAntiAliasing);
dc->setFrameColor(_frame);
dc->drawRect(bounds, kDrawStroked);
SharedPointer<CGraphicsPath> path = owned(dc->createGraphicsPath());
path->addRoundRect(bounds, cornerRadius_);
dc->setFillColor(_fill);
dc->drawRect(handle, kDrawFilled);
dc->setFillColor(backgroundColor_);
dc->drawGraphicsPath(path.get(), CDrawContext::kPathFilled);
CViewContainer::drawRect(dc, updateRect);
}
///
STitleContainer::STitleContainer(const CRect& size, UTF8StringPtr text)
: SBoxContainer(size), text_(text ? text : ""), titleFont_(kNormalFont)
{
}
void STitleContainer::setTitleFont(CFontRef font)
{
titleFont_ = font;
setDirty();
}
void STitleContainer::setTitleFontColor(CColor color)
{
titleFontColor_ = color;
setDirty();
}
void STitleContainer::setTitleBackgroundColor(CColor color)
{
titleBackgroundColor_ = color;
setDirty();
}
void STitleContainer::drawRect(CDrawContext* dc, const CRect& updateRect)
{
SBoxContainer::drawRect(dc, updateRect);
CRect bounds = getViewSize();
CCoord cornerRadius = cornerRadius_;
dc->setDrawMode(kAntiAliasing);
CCoord fontHeight = titleFont_->getSize();
CCoord titleHeight = fontHeight + 8.0;
CRect titleBounds = bounds;
titleBounds.bottom = titleBounds.top + titleHeight;
SharedPointer<CGraphicsPath> path = owned(dc->createGraphicsPath());
path->beginSubpath(titleBounds.getBottomRight());
path->addLine(titleBounds.getBottomLeft());
path->addArc(CRect(titleBounds.left, titleBounds.top, titleBounds.left + 2.0 * cornerRadius, titleBounds.top + 2.0 * cornerRadius), 180., 270., true);
path->addArc(CRect(titleBounds.right - 2.0 * cornerRadius, titleBounds.top, titleBounds.right, titleBounds.top + 2.0 * cornerRadius), 270., 360., true);
path->closeSubpath();
dc->setFillColor(titleBackgroundColor_);
dc->drawGraphicsPath(path, CDrawContext::kPathFilled);
dc->setFont(titleFont_);
dc->setFontColor(titleFontColor_);
dc->drawString(text_.c_str(), titleBounds, kCenterText);
}
///
void SFileDropTarget::setFileDropFunction(FileDropFunction f)
{
dropFunction_ = std::move(f);
}
DragOperation SFileDropTarget::onDragEnter(DragEventData data)
{
op_ = isFileDrop(data.drag) ?
DragOperation::Copy : DragOperation::None;
return op_;
}
DragOperation SFileDropTarget::onDragMove(DragEventData data)
{
(void)data;
return op_;
}
void SFileDropTarget::onDragLeave(DragEventData data)
{
(void)data;
op_ = DragOperation::None;
}
bool SFileDropTarget::onDrop(DragEventData data)
{
if (op_ != DragOperation::Copy || !isFileDrop(data.drag))
return false;
IDataPackage::Type type;
const void* bytes;
uint32_t size = data.drag->getData(0, bytes, type);
std::string path(reinterpret_cast<const char*>(bytes), size);
if (dropFunction_)
dropFunction_(path);
return true;
}
bool SFileDropTarget::isFileDrop(IDataPackage* package)
{
return package->getCount() == 1 &&
package->getDataType(0) == IDataPackage::kFilePath;
}
///
SPiano::SPiano(const CRect& bounds)
: CView(bounds), font_(kNormalFont)
{
}
void SPiano::setFont(CFontRef font)
{
font_ = font;
setDirty();
}
void SPiano::clearKeyRanges()
{
keyInRange_.reset();
}
void SPiano::addKeyRange(int start, int end)
{
start = std::min(127, std::max(0, start));
end = std::min(127, std::max(0, end));
for (int x = start; x <= end; ++x)
keyInRange_.set(x);
}
CCoord SPiano::getKeyWidth()
{
return 6.0;
}
CCoord SPiano::getKeySwitchesHeight()
{
return 20.0;
}
CCoord SPiano::getKeyRangesHeight()
{
return 11.0;
}
CCoord SPiano::getKeysHeight() const
{
return getHeight() -
(getKeySwitchesHeight() + getKeyRangesHeight() + getOctavesHeight());
}
CCoord SPiano::getOctavesHeight() const
{
return font_->getSize();
}
void SPiano::getZoneDimensions(
CRect* pKeySwitches,
CRect* pKeyboard,
CRect* pKeyRanges,
CRect* pOctaves)
{
CRect bounds = getViewSize();
CRect keySwitches(bounds);
keySwitches.setHeight(getKeySwitchesHeight());
CRect keyboard(bounds);
keyboard.top = keySwitches.bottom;
keyboard.setHeight(getKeysHeight());
CRect keyRanges(bounds);
keyRanges.top = keyboard.bottom;
keyRanges.setHeight(getKeyRangesHeight());
CRect octaves(bounds);
octaves.top = keyRanges.bottom;
octaves.setHeight(getOctavesHeight());
// apply some paddings
keySwitches.extend(-2.0, -2.0);
keyboard.extend(-2.0, -2.0);
keyRanges.extend(-2.0, -4.0);
octaves.extend(-2.0, -2.0);
// offsets for centered keyboard
CCoord keyWidth = getKeyWidth();
CCoord offset = std::round((keyboard.getWidth() - (128.0 * keyWidth)) * 0.5);
if (offset > 0) {
keySwitches.extend(-offset, 0.0);
keyboard.extend(-offset, 0.0);
keyRanges.extend(-offset, 0.0);
octaves.extend(-offset, 0.0);
}
//
if (pKeySwitches)
*pKeySwitches = keySwitches;
if (pKeyboard)
*pKeyboard = keyboard;
if (pKeyRanges)
*pKeyRanges = keyRanges;
if (pOctaves)
*pOctaves = octaves;
}
void SPiano::draw(CDrawContext* dc)
{
CRect bounds = getViewSize();
dc->setDrawMode(kAntiAliasing);
SharedPointer<CGraphicsPath> path;
path = owned(dc->createGraphicsPath());
path->addRoundRect(bounds, 5.0);
dc->setFillColor(CColor(0xca, 0xca, 0xca));
dc->drawGraphicsPath(path, CDrawContext::kPathFilled);
//
CRect rectKeySwitches;
CRect rectKeyboard;
CRect rectKeyRanges;
CRect rectOctaves;
getZoneDimensions(&rectKeySwitches, &rectKeyboard, &rectKeyRanges, &rectOctaves);
//
path = owned(dc->createGraphicsPath());
path->addRoundRect(rectKeyboard, 1.0);
dc->setFillColor(CColor(0xff, 0xff, 0xff));
dc->drawGraphicsPath(path, CDrawContext::kPathFilled);
CCoord keyWidth = getKeyWidth();
for (int key = 0; key < 128; ++key) {
CCoord keyX = rectKeyboard.left + key * keyWidth;
int key12 = key % 12;
if (key12 == 1 || key12 == 3 ||
key12 == 6 || key12 == 8 || key12 == 10)
{
CRect blackRect(keyX, rectKeyboard.top + 2, keyX + keyWidth, rectKeyboard.bottom - 2);
path = owned(dc->createGraphicsPath());
path->addRoundRect(blackRect, 1.0);
dc->setFillColor(CColor(0x02, 0x02, 0x02));
dc->drawGraphicsPath(path, CDrawContext::kPathFilled);
}
if (key != 0 && key12 == 0) {
dc->setLineWidth(1.5);
dc->setFrameColor(CColor(0x63, 0x63, 0x63));
dc->drawLine(CPoint(keyX, rectKeyboard.top), CPoint(keyX, rectKeyboard.bottom));
}
if (key12 == 5) {
CCoord pad = rectKeyboard.getHeight() * 0.4;
dc->setLineWidth(1.0);
dc->setFrameColor(CColor(0x63, 0x63, 0x63));
dc->drawLine(CPoint(keyX, rectKeyboard.top + pad), CPoint(keyX, rectKeyboard.bottom - pad));
}
}
//
for (int rangeStart = 0; rangeStart < 128;)
{
if (!keyInRange_[rangeStart]) {
++rangeStart;
}
else {
int rangeEnd = rangeStart;
while (rangeEnd + 1 < 128 && keyInRange_[rangeEnd + 1])
++rangeEnd;
CCoord rangeStartX = rectKeyRanges.left + rangeStart * keyWidth;
CCoord rangeEndX = rectKeyRanges.left + (rangeEnd + 1.0) * keyWidth;
CRect rectRange(rangeStartX, rectKeyRanges.top, rangeEndX, rectKeyRanges.bottom);
path = owned(dc->createGraphicsPath());
path->addRoundRect(rectRange, 2.0);
dc->setFillColor(CColor(0x0f, 0x0f, 0x0f));
dc->drawGraphicsPath(path, CDrawContext::kPathFilled);
rangeStart = rangeEnd + 1;
}
}
//
for (int key = 0; key < 128; ++key) {
CCoord keyX = rectOctaves.left + key * keyWidth;
int key12 = key % 12;
if (key12 == 0) {
CRect textRect(keyX, rectOctaves.top, keyX + 12 * keyWidth, rectOctaves.bottom);
dc->setFont(font_);
dc->setFontColor(CColor(0x63, 0x63, 0x63));
dc->drawString(std::to_string(key / 12 - 1).c_str(), textRect, kLeftText);
}
}
//
}
///
SValueMenu::SValueMenu(const CRect& bounds, IControlListener* listener, int32_t tag)
: CParamDisplay(bounds), menuListener_(owned(new MenuListener(*this)))
{
setListener(listener);
setTag(tag);
}
CMenuItem* SValueMenu::addEntry(CMenuItem* item, float value, int32_t index)
{
if (index < 0 || index > getNbEntries()) {
menuItems_.emplace_back(owned(item));
menuItemValues_.emplace_back(value);
}
else
{
menuItems_.insert(menuItems_.begin() + index, owned(item));
menuItemValues_.insert(menuItemValues_.begin() + index, value);
}
return item;
}
CMenuItem* SValueMenu::addEntry(const UTF8String& title, float value, int32_t index, int32_t itemFlags)
{
if (title == "-")
return addSeparator(index);
CMenuItem* item = new CMenuItem(title, nullptr, 0, nullptr, itemFlags);
return addEntry(item, value, index);
}
CMenuItem* SValueMenu::addSeparator(int32_t index)
{
CMenuItem* item = new CMenuItem("", nullptr, 0, nullptr, CMenuItem::kSeparator);
return addEntry(item, 0.0f, index);
}
int32_t SValueMenu::getNbEntries() const
{
return static_cast<int32_t>(menuItems_.size());
}
CMouseEventResult SValueMenu::onMouseDown(CPoint& where, const CButtonState& buttons)
{
(void)where;
if (buttons & (kLButton|kRButton|kApple)) {
CFrame* frame = getFrame();
CRect bounds = getViewSize();
CPoint frameWhere = bounds.getBottomLeft();
this->localToFrame(frameWhere);
auto self = shared(this);
frame->doAfterEventProcessing([self, frameWhere]() {
if (CFrame* frame = self->getFrame()) {
SharedPointer<COptionMenu> menu = owned(new COptionMenu(CRect(), self->menuListener_, -1, nullptr, nullptr, COptionMenu::kPopupStyle));
for (const SharedPointer<CMenuItem>& item : self->menuItems_) {
menu->addEntry(item);
item->remember(); // above call does not increment refcount
}
menu->setFont(self->getFont());
menu->setFontColor(self->getFontColor());
menu->setBackColor(self->getBackColor());
menu->popup(frame, frameWhere + CPoint(0.0, 1.0));
}
});
return kMouseDownEventHandledButDontNeedMovedOrUpEvents;
}
return kMouseEventNotHandled;
}
void SValueMenu::onItemClicked(int32_t index)
{
float oldValue = getValue();
setValue(menuItemValues_[index]);
if (getValue() != oldValue)
valueChanged();
}
void STextButton::setHoverColor (const CColor& color)
{
hoverColor_ = color;
}
void STextButton::draw(CDrawContext* context)
{
CColor backupColor = textColor;
if (hovered) {
textColor = hoverColor_; // textColor is protected
}
CTextButton::draw(context);
if (hovered)
textColor = backupColor;
}
CMouseEventResult STextButton::onMouseEntered (CPoint& where, const CButtonState& buttons)
{
hovered = true;
setDirty();
return CTextButton::onMouseEntered(where, buttons);
}
CMouseEventResult STextButton::onMouseExited (CPoint& where, const CButtonState& buttons)
{
hovered = false;
setDirty();
return CTextButton::onMouseExited(where, buttons);
}

View file

@ -5,22 +5,160 @@
// If not, contact the sfizz maintainers at https://github.com/sfztools/sfizz
#pragma once
#include <bitset>
#include "utility/vstgui_before.h"
#include "vstgui/lib/controls/cslider.h"
#include "vstgui/lib/controls/cknob.h"
#include "vstgui/lib/controls/ctextlabel.h"
#include "vstgui/lib/controls/cbuttons.h"
#include "vstgui/lib/controls/coptionmenu.h"
#include "vstgui/lib/cviewcontainer.h"
#include "vstgui/lib/ccolor.h"
#include "vstgui/lib/dragging.h"
#include "utility/vstgui_after.h"
using namespace VSTGUI;
class SimpleSlider : public CSliderBase {
///
class SBoxContainer : public CViewContainer {
public:
SimpleSlider(const CRect& bounds, IControlListener* listener, int32_t tag);
void draw(CDrawContext* dc) override;
explicit SBoxContainer(const CRect& size);
virtual ~SBoxContainer() {}
void setCornerRadius(CCoord radius);
void setBackgroundColor(const CColor& color) override;
CColor getBackgroundColor() const override;
CLASS_METHODS(SimpleSlider, CSliderBase)
protected:
void drawRect(CDrawContext* dc, const CRect& updateRect) override;
protected:
CCoord cornerRadius_ = 0.0;
CColor backgroundColor_;
};
///
class STitleContainer : public SBoxContainer {
public:
explicit STitleContainer(const CRect& size, UTF8StringPtr text = nullptr);
~STitleContainer() {}
void setTitleFont(CFontRef font);
CFontRef getTitleFont() { return titleFont_; }
void setTitleFontColor(CColor color);
CColor getTitleFontColor() const { return titleFontColor_; }
void setTitleBackgroundColor(CColor color);
CColor getTitleBackgroundColor() const { return titleBackgroundColor_; }
protected:
void drawRect(CDrawContext* dc, const CRect& updateRect) override;
private:
CColor _frame = CColor(0x00, 0x00, 0x00);
CColor _fill = CColor(0x00, 0x00, 0x00);
std::string text_;
CColor titleFontColor_;
CColor titleBackgroundColor_;
SharedPointer<CFontDesc> titleFont_;
};
///
class SFileDropTarget : public IDropTarget,
public NonAtomicReferenceCounted {
public:
typedef std::function<void(const std::string&)> FileDropFunction;
void setFileDropFunction(FileDropFunction f);
protected:
DragOperation onDragEnter(DragEventData data) override;
DragOperation onDragMove(DragEventData data) override;
void onDragLeave(DragEventData data) override;
bool onDrop(DragEventData data) override;
private:
static bool isFileDrop(IDataPackage* package);
private:
DragOperation op_ = DragOperation::None;
FileDropFunction dropFunction_;
};
///
class SPiano : public CView {
public:
explicit SPiano(const CRect& bounds);
CFontRef getFont() const { return font_; }
void setFont(CFontRef font);
void clearKeyRanges();
void addKeyRange(int start, int end);
protected:
static CCoord getKeyWidth();
static CCoord getKeySwitchesHeight();
static CCoord getKeyRangesHeight();
CCoord getKeysHeight() const;
CCoord getOctavesHeight() const;
void getZoneDimensions(
CRect* pKeySwitches,
CRect* pKeyboard,
CRect* pKeyRanges,
CRect* pOctaves);
void draw(CDrawContext* dc) override;
private:
SharedPointer<CFontDesc> font_;
std::bitset<128> keyInRange_;
};
///
class SValueMenu : public CParamDisplay {
public:
explicit SValueMenu(const CRect& bounds, IControlListener* listener, int32_t tag);
CMenuItem* addEntry(CMenuItem* item, float value, int32_t index = -1);
CMenuItem* addEntry(const UTF8String& title, float value, int32_t index = -1, int32_t itemFlags = CMenuItem::kNoFlags);
CMenuItem* addSeparator(int32_t index = -1);
int32_t getNbEntries() const;
protected:
CMouseEventResult onMouseDown(CPoint& where, const CButtonState& buttons);
private:
class MenuListener;
//
void onItemClicked(int32_t index);
//
CMenuItemList menuItems_;
std::vector<float> menuItemValues_;
SharedPointer<MenuListener> menuListener_;
//
class MenuListener : public IControlListener, public NonAtomicReferenceCounted {
public:
explicit MenuListener(SValueMenu& menu) : menu_(menu) {}
void valueChanged(CControl* control) override
{
menu_.onItemClicked(static_cast<int32_t>(control->getValue()));
}
private:
SValueMenu& menu_;
};
};
///
class STextButton: public CTextButton {
public:
STextButton(const CRect& size, IControlListener* listener = nullptr, int32_t tag = -1, UTF8StringPtr title = nullptr)
: CTextButton(size, listener, tag, title) {}
void setHoverColor(const CColor& color);
CMouseEventResult onMouseEntered (CPoint& where, const CButtonState& buttons) override;
CMouseEventResult onMouseExited (CPoint& where, const CButtonState& buttons) override;
void draw(CDrawContext* context) override;
private:
CColor hoverColor_;
bool hovered { false };
};

View file

@ -0,0 +1,50 @@
// SPDX-License-Identifier: BSD-2-Clause
// This code is part of the sfizz library and is licensed under a BSD 2-clause
// license. You should have receive a LICENSE.md file along with the code.
// If not, contact the sfizz maintainers at https://github.com/sfztools/sfizz
#include "NativeHelpers.h"
#if defined(_WIN32)
#include "ghc/fs_std.hpp"
#include <windows.h>
#include <cstring>
bool openFileInExternalEditor(const char *filename)
{
std::wstring path = fs::u8path(filename).wstring();
SHELLEXECUTEINFOW info;
memset(&info, 0, sizeof(info));
info.cbSize = sizeof(info);
info.fMask = SEE_MASK_CLASSNAME;
info.lpVerb = L"open";
info.lpFile = path.c_str();
info.lpClass = L"txtfile";
info.nShow = SW_SHOW;
return ShellExecuteExW(&info);
}
#elif defined(__APPLE__)
// implemented in NativeHelpers.mm
#else
#include <gio/gio.h>
bool openFileInExternalEditor(const char *filename)
{
GAppInfo* appinfo = g_app_info_get_default_for_type("text/plain", FALSE);
if (!appinfo)
return 1;
GList* files = nullptr;
GFile* file = g_file_new_for_path(filename);
files = g_list_append(files, file);
gboolean success = g_app_info_launch(appinfo, files, nullptr, nullptr);
g_object_unref(file);
g_list_free(files);
g_object_unref(appinfo);
return success == TRUE;
}
#endif

View file

@ -0,0 +1,9 @@
// SPDX-License-Identifier: BSD-2-Clause
// This code is part of the sfizz library and is licensed under a BSD 2-clause
// license. You should have receive a LICENSE.md file along with the code.
// If not, contact the sfizz maintainers at https://github.com/sfztools/sfizz
#pragma once
bool openFileInExternalEditor(const char *filename);

View file

@ -0,0 +1,30 @@
// SPDX-License-Identifier: BSD-2-Clause
// This code is part of the sfizz library and is licensed under a BSD 2-clause
// license. You should have receive a LICENSE.md file along with the code.
// If not, contact the sfizz maintainers at https://github.com/sfztools/sfizz
#include "NativeHelpers.h"
#if defined(__APPLE__)
#import <AppKit/AppKit.h>
#import <CoreServices/CoreServices.h>
#import <Foundation/Foundation.h>
bool openFileInExternalEditor(const char *fileNameUTF8)
{
BOOL wasOpened = NO;
NSURL* applicationURL = (__bridge_transfer NSURL*)LSCopyDefaultApplicationURLForContentType(
kUTTypePlainText, kLSRolesEditor, nil);
if (!applicationURL)
return false;
if ([applicationURL isFileURL]) {
NSWorkspace* workspace = [NSWorkspace sharedWorkspace];
NSString* fileName = [NSString stringWithUTF8String:fileNameUTF8];
wasOpened = [workspace openFile:fileName withApplication:[applicationURL path]];
}
return wasOpened == YES;
}
#endif

View file

@ -0,0 +1,155 @@
/* This file is generated by the layout maker tool. */
LogicalGroup* const view__0 = createLogicalGroup(CRect(0, 0, 800, 475), -1, "", kCenterText, 14);
mainView = view__0;
Background* const view__1 = createBackground(CRect(190, 110, 790, 390), -1, "", kCenterText, 14);
view__0->addView(view__1);
enterTheme(darkTheme);
LogicalGroup* const view__2 = createLogicalGroup(CRect(0, 0, 800, 110), -1, "", kCenterText, 14);
view__0->addView(view__2);
RoundedGroup* const view__3 = createRoundedGroup(CRect(5, 4, 180, 105), -1, "", kCenterText, 14);
view__2->addView(view__3);
SfizzMainButton* const view__4 = createSfizzMainButton(CRect(30, 5, 150, 65), kTagFirstChangePanel+kPanelGeneral, "", kCenterText, 14);
view__3->addView(view__4);
HomeButton* const view__5 = createHomeButton(CRect(44, 69, 69, 94), kTagFirstChangePanel+kPanelGeneral, "", kCenterText, 24);
view__3->addView(view__5);
CCButton* const view__6 = createCCButton(CRect(76, 69, 101, 94), kTagFirstChangePanel+kPanelControls, "", kCenterText, 24);
view__3->addView(view__6);
SettingsButton* const view__7 = createSettingsButton(CRect(107, 69, 132, 94), kTagFirstChangePanel+kPanelSettings, "", kCenterText, 24);
view__3->addView(view__7);
RoundedGroup* const view__8 = createRoundedGroup(CRect(185, 5, 565, 105), -1, "", kCenterText, 14);
view__2->addView(view__8);
Label* const view__9 = createLabel(CRect(15, 8, 55, 38), -1, "File:", kCenterText, 16);
view__8->addView(view__9);
Label* const view__10 = createLabel(CRect(15, 40, 55, 70), -1, "KS:", kCenterText, 16);
view__8->addView(view__10);
HLine* const view__11 = createHLine(CRect(10, 36, 370, 41), -1, "", kCenterText, 14);
view__8->addView(view__11);
HLine* const view__12 = createHLine(CRect(10, 68, 370, 73), -1, "", kCenterText, 14);
view__8->addView(view__12);
Label* const view__13 = createLabel(CRect(80, 7, 310, 37), -1, "DefaultInstrument.sfz", kCenterText, 20);
sfzFileLabel_ = view__13;
view__8->addView(view__13);
Label* const view__14 = createLabel(CRect(80, 39, 310, 69), -1, "Key switch", kCenterText, 20);
view__8->addView(view__14);
Label* const view__15 = createLabel(CRect(10, 71, 70, 96), -1, "Voices:", kRightText, 12);
view__8->addView(view__15);
LoadFileButton* const view__16 = createLoadFileButton(CRect(315, 9, 340, 34), kTagLoadSfzFile, "", kCenterText, 24);
view__8->addView(view__16);
EditFileButton* const view__17 = createEditFileButton(CRect(340, 9, 365, 34), kTagEditSfzFile, "", kCenterText, 24);
view__8->addView(view__17);
Label* const view__18 = createLabel(CRect(75, 71, 125, 96), -1, "", kCenterText, 12);
infoVoicesLabel_ = view__18;
view__8->addView(view__18);
Label* const view__19 = createLabel(CRect(130, 71, 190, 96), -1, "Max:", kRightText, 12);
view__8->addView(view__19);
Label* const view__20 = createLabel(CRect(195, 71, 245, 96), -1, "", kCenterText, 12);
numVoicesLabel_ = view__20;
view__8->addView(view__20);
Label* const view__21 = createLabel(CRect(250, 71, 310, 96), -1, "Memory:", kRightText, 12);
view__8->addView(view__21);
Label* const view__22 = createLabel(CRect(315, 71, 365, 96), -1, "", kCenterText, 12);
memoryLabel_ = view__22;
view__8->addView(view__22);
RoundedGroup* const view__23 = createRoundedGroup(CRect(570, 5, 795, 105), -1, "", kCenterText, 14);
view__2->addView(view__23);
Knob48* const view__24 = createKnob48(CRect(45, 15, 93, 63), -1, "", kCenterText, 14);
view__23->addView(view__24);
view__24->setVisible(false);
ValueLabel* const view__25 = createValueLabel(CRect(40, 65, 100, 70), -1, "Center", kCenterText, 12);
view__23->addView(view__25);
view__25->setVisible(false);
Knob48* const view__26 = createKnob48(CRect(110, 15, 158, 63), kTagSetVolume, "", kCenterText, 14);
volumeSlider_ = view__26;
view__23->addView(view__26);
ValueLabel* const view__27 = createValueLabel(CRect(105, 65, 165, 87), -1, "0.0 dB", kCenterText, 12);
volumeLabel_ = view__27;
view__23->addView(view__27);
VMeter* const view__28 = createVMeter(CRect(175, 15, 210, 70), -1, "", kCenterText, 14);
view__23->addView(view__28);
enterTheme(defaultTheme);
LogicalGroup* const view__29 = createLogicalGroup(CRect(5, 110, 796, 395), -1, "", kCenterText, 14);
subPanels_[kPanelGeneral] = view__29;
view__0->addView(view__29);
view__29->setVisible(false);
RoundedGroup* const view__30 = createRoundedGroup(CRect(0, 0, 175, 280), -1, "", kCenterText, 14);
view__29->addView(view__30);
Label* const view__31 = createLabel(CRect(15, 10, 75, 35), -1, "Curves:", kLeftText, 14);
view__30->addView(view__31);
Label* const view__32 = createLabel(CRect(15, 35, 75, 60), -1, "Masters:", kLeftText, 14);
view__30->addView(view__32);
Label* const view__33 = createLabel(CRect(15, 60, 75, 85), -1, "Groups:", kLeftText, 14);
view__30->addView(view__33);
Label* const view__34 = createLabel(CRect(15, 85, 75, 110), -1, "Regions:", kLeftText, 14);
view__30->addView(view__34);
Label* const view__35 = createLabel(CRect(15, 110, 75, 135), -1, "Samples:", kLeftText, 14);
view__30->addView(view__35);
Label* const view__36 = createLabel(CRect(115, 10, 155, 35), -1, "0", kCenterText, 14);
infoCurvesLabel_ = view__36;
view__30->addView(view__36);
Label* const view__37 = createLabel(CRect(115, 35, 155, 60), -1, "0", kCenterText, 14);
infoMastersLabel_ = view__37;
view__30->addView(view__37);
Label* const view__38 = createLabel(CRect(115, 60, 155, 85), -1, "0", kCenterText, 14);
infoGroupsLabel_ = view__38;
view__30->addView(view__38);
Label* const view__39 = createLabel(CRect(115, 85, 155, 110), -1, "0", kCenterText, 14);
infoRegionsLabel_ = view__39;
view__30->addView(view__39);
Label* const view__40 = createLabel(CRect(115, 110, 155, 135), -1, "0", kCenterText, 14);
infoSamplesLabel_ = view__40;
view__30->addView(view__40);
LogicalGroup* const view__41 = createLogicalGroup(CRect(5, 110, 795, 395), -1, "", kCenterText, 14);
subPanels_[kPanelControls] = view__41;
view__0->addView(view__41);
view__41->setVisible(false);
RoundedGroup* const view__42 = createRoundedGroup(CRect(0, 0, 790, 285), -1, "", kCenterText, 14);
view__41->addView(view__42);
Label* const view__43 = createLabel(CRect(0, 0, 790, 285), -1, "Controls not available", kCenterText, 40);
view__42->addView(view__43);
LogicalGroup* const view__44 = createLogicalGroup(CRect(5, 109, 795, 395), -1, "", kCenterText, 14);
subPanels_[kPanelSettings] = view__44;
view__0->addView(view__44);
TitleGroup* const view__45 = createTitleGroup(CRect(255, 26, 535, 126), -1, "Engine", kCenterText, 12);
view__44->addView(view__45);
ValueMenu* const view__46 = createValueMenu(CRect(25, 60, 85, 85), kTagSetNumVoices, "", kCenterText, 12);
numVoicesSlider_ = view__46;
view__45->addView(view__46);
ValueLabel* const view__47 = createValueLabel(CRect(15, 20, 95, 45), -1, "Polyphony", kCenterText, 12);
view__45->addView(view__47);
ValueMenu* const view__48 = createValueMenu(CRect(110, 60, 170, 85), kTagSetOversampling, "", kCenterText, 12);
oversamplingSlider_ = view__48;
view__45->addView(view__48);
ValueLabel* const view__49 = createValueLabel(CRect(100, 20, 180, 45), -1, "Oversampling", kCenterText, 12);
view__45->addView(view__49);
ValueLabel* const view__50 = createValueLabel(CRect(185, 20, 265, 45), -1, "Preload size", kCenterText, 12);
view__45->addView(view__50);
ValueMenu* const view__51 = createValueMenu(CRect(195, 60, 255, 85), kTagSetPreloadSize, "", kCenterText, 12);
preloadSizeSlider_ = view__51;
view__45->addView(view__51);
TitleGroup* const view__52 = createTitleGroup(CRect(200, 161, 590, 261), -1, "Tuning", kCenterText, 12);
view__44->addView(view__52);
ValueLabel* const view__53 = createValueLabel(CRect(125, 20, 205, 45), -1, "Root key", kCenterText, 12);
view__52->addView(view__53);
ValueMenu* const view__54 = createValueMenu(CRect(220, 60, 280, 85), kTagSetTuningFrequency, "", kCenterText, 12);
tuningFrequencySlider_ = view__54;
view__52->addView(view__54);
ValueLabel* const view__55 = createValueLabel(CRect(210, 20, 290, 45), -1, "Frequency", kCenterText, 12);
view__52->addView(view__55);
Knob48* const view__56 = createKnob48(CRect(310, 45, 358, 93), kTagSetStretchedTuning, "", kCenterText, 14);
stretchedTuningSlider_ = view__56;
view__52->addView(view__56);
ValueLabel* const view__57 = createValueLabel(CRect(295, 20, 375, 45), -1, "Stretch", kCenterText, 12);
view__52->addView(view__57);
ValueLabel* const view__58 = createValueLabel(CRect(20, 20, 120, 45), -1, "Scala file", kCenterText, 12);
view__52->addView(view__58);
ValueButton* const view__59 = createValueButton(CRect(20, 60, 120, 85), kTagLoadScalaFile, "DefaultScale", kCenterText, 12);
scalaFileButton_ = view__59;
view__52->addView(view__59);
ValueMenu* const view__60 = createValueMenu(CRect(135, 60, 170, 85), kTagSetScalaRootKey, "", kCenterText, 12);
scalaRootKeySlider_ = view__60;
view__52->addView(view__60);
ValueMenu* const view__61 = createValueMenu(CRect(170, 60, 200, 85), kTagSetScalaRootKey, "", kCenterText, 12);
scalaRootOctaveSlider_ = view__61;
view__52->addView(view__61);
Piano* const view__62 = createPiano(CRect(5, 400, 795, 470), -1, "", kCenterText, 14);
view__0->addView(view__62);

View file

@ -0,0 +1,23 @@
Boost Software License - Version 1.0 - August 17th, 2003
Permission is hereby granted, free of charge, to any person or organization
obtaining a copy of the software and accompanying documentation covered by
this license (the "Software") to use, reproduce, display, distribute,
execute, and transmit the Software, and to prepare derivative works of the
Software, and to permit third-parties to whom the Software is furnished to
do so, all subject to the following:
The copyright notices in the Software and this entire statement, including
the above license grant, this restriction and the following disclaimer,
must be included in all copies of the Software, in whole or in part, and
all derivative works of the Software, unless such copies or derivative
works are solely in the form of machine-executable object code generated by
a source language processor.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.

View file

@ -0,0 +1,2 @@
This purpose of this tool is to accept UI designs make with Fluid, the FLTK
design editor, and convert these designs to music plugin interfaces.

View file

@ -0,0 +1,42 @@
#pragma once
#include <vector>
#include <string>
struct LayoutImage {
std::string filepath;
int x = 0;
int y = 0;
int w = 0;
int h = 0;
};
struct LayoutItem {
std::string id;
std::string classname;
std::string label;
int x = 0;
int y = 0;
int w = 0;
int h = 0;
std::string box;
std::string down_box;
int labelfont = 0;
int labelsize = 14;
std::string labeltype;
int textsize = 14;
int align = 0;
double value = 0;
double minimum = 0;
double maximum = 0;
double step = 0;
std::string type;
std::string callback;
LayoutImage image;
bool hidden = false;
std::string comment;
std::vector<LayoutItem> items;
};
struct Layout {
std::vector<LayoutItem> items;
};

View file

@ -0,0 +1,136 @@
#include "layout.h"
#include "reader.h"
#include <absl/strings/ascii.h>
#include <absl/strings/string_view.h>
#include <unordered_map>
#include <iostream>
///
typedef std::unordered_map<std::string, std::string> Metadata;
static Metadata metadata_from_comment(absl::string_view comment)
{
Metadata md;
while (!comment.empty()) {
absl::string_view line;
size_t pos = comment.find_first_of("\r\n");
if (pos != comment.npos) {
line = comment.substr(0, pos);
comment.remove_prefix(pos + 1);
}
else {
line = comment;
comment = {};
}
line = absl::StripAsciiWhitespace(line);
if (line.empty() || line[0] == '#')
continue;
std::string key, value;
pos = line.find_first_of('=');
if (pos != comment.npos) {
key = std::string(line.substr(0, pos));
value = std::string(line.substr(pos + 1));
}
else
key = std::string(line);
md.emplace(std::move(key), std::move(value));
}
return md;
}
///
static void codegen_item(int& idCounter, int parentId, int parentX, int parentY, const LayoutItem& item, absl::string_view oldTheme)
{
const Metadata md = metadata_from_comment(item.comment);
absl::string_view tag = "-1";
absl::string_view newTheme;
Metadata::const_iterator it;
it = md.find("tag");
if (it != md.end())
tag = it->second;
it = md.find("theme");
if (it != md.end())
newTheme = it->second;
absl::string_view currentTheme = newTheme.empty() ? oldTheme : newTheme;
int id = idCounter++;
int myX = item.x;
int myY = item.y;
if (parentId == -1) {
myX = 0;
myY = 0;
}
int relX = myX - parentX;
int relY = myY - parentY;
//std::cout << "// Begin " << id << " " << item.classname << " {" << item.label << "}" << "\n";
if (!newTheme.empty())
std::cout << "enterTheme(" << newTheme << ");\n";
absl::string_view label;
if (!item.label.empty() && item.labeltype != "NO_LABEL")
label = item.label;
absl::string_view align = "kCenterText";
if (item.align & 4)
align = "kLeftText";
else if (item.align & 8)
align = "kRightText";
std::cout << item.classname << "* const view__" << id << " = create" << item.classname << "(CRect(" << relX << ", " << relY << ", " << (relX + item.w) << ", " << (relY + item.h) << "), " << tag << ", \"" << label << "\", " << align << ", " << item.labelsize << ");\n";
if (!item.id.empty())
std::cout << item.id << " = view__" << id << ";\n";
if (parentId != -1)
std::cout << "view__" << parentId << "->addView(view__" << id << ");\n";
if (item.hidden)
std::cout << "view__" << id << "->setVisible(false);\n";
for (const LayoutItem& subItem : item.items)
codegen_item(idCounter, id, myX, myY, subItem, currentTheme);
if (!newTheme.empty())
std::cout << "enterTheme(" << oldTheme << ");\n";
//std::cout << "// End " << id << " " << item.classname << " {" << item.label << "}" << "\n";
}
static void codegen_layout(const LayoutItem& item)
{
int idCounter = 0;
codegen_item(idCounter, -1, 0, 0, item, "defaultTheme");
}
///
int main(int argc, char *argv[])
{
if (argc != 2) {
std::cerr << "Please indicate a fluid design file.\n";
return 1;
}
Layout layout = read_file_layout(argv[1]);
if (layout.items.size() != 1) {
std::cerr << "There must be exactly 1 top level component.";
return 1;
}
std::cout << "/* This file is generated by the layout maker tool. */\n";
codegen_layout(layout.items[0]);
return 0;
}

View file

@ -0,0 +1,359 @@
#include "reader.h"
#include <absl/strings/string_view.h>
#include <iostream>
#include <fstream>
typedef std::vector<std::string> TokenList;
static bool read_file_tokens(const char *filename, TokenList &tokens);
static Layout read_tokens_layout(TokenList::iterator &tok_it, TokenList::iterator tok_end);
Layout read_file_layout(const char *filename)
{
std::vector<std::string> tokens;
if (!read_file_tokens(filename, tokens))
throw std::runtime_error("Cannot read fluid design file.");
TokenList::iterator tok_it = tokens.begin();
TokenList::iterator tok_end = tokens.end();
return read_tokens_layout(tok_it, tok_end);
}
static std::string consume_next_token(TokenList::iterator &tok_it, TokenList::iterator tok_end)
{
if (tok_it == tok_end)
throw file_format_error("Premature end of tokens");
return *tok_it++;
}
static bool try_consume_next_token(const char *text, TokenList::iterator &tok_it, TokenList::iterator tok_end)
{
if (tok_it == tok_end)
return false;
if (*tok_it != text)
return false;
++tok_it;
return true;
}
static void ensure_next_token(const char *text, TokenList::iterator &tok_it, TokenList::iterator tok_end)
{
std::string tok = consume_next_token(tok_it, tok_end);
if (tok != text)
throw file_format_error("Unexpected token: " + tok);
}
static std::string consume_enclosed_string(TokenList::iterator &tok_it, TokenList::iterator tok_end)
{
ensure_next_token("{", tok_it, tok_end);
unsigned depth = 1;
std::string text;
for (;;) {
std::string part = consume_next_token(tok_it, tok_end);
if (part == "}") {
if (--depth == 0)
return text;
}
else if (part == "{")
++depth;
if (!text.empty())
text.push_back(' ');
text.append(part);
}
return text;
}
static std::string consume_any_string(TokenList::iterator &tok_it, TokenList::iterator tok_end)
{
if (tok_it != tok_end && *tok_it == "{")
return consume_enclosed_string(tok_it, tok_end);
else
return consume_next_token(tok_it, tok_end);
}
static int consume_int_token(TokenList::iterator &tok_it, TokenList::iterator tok_end)
{
std::string text = consume_next_token(tok_it, tok_end);
return std::stoi(text);
}
static int consume_real_token(TokenList::iterator &tok_it, TokenList::iterator tok_end)
{
std::string text = consume_next_token(tok_it, tok_end);
return std::stod(text);
}
static void consume_image_properties(LayoutImage &image, TokenList::iterator &tok_it, TokenList::iterator tok_end)
{
for (bool have = true; have;) {
if (try_consume_next_token("xywh", tok_it, tok_end)) {
ensure_next_token("{", tok_it, tok_end);
image.x = consume_int_token(tok_it, tok_end);
image.y = consume_int_token(tok_it, tok_end);
image.w = consume_int_token(tok_it, tok_end);
image.h = consume_int_token(tok_it, tok_end);
ensure_next_token("}", tok_it, tok_end);
}
else
have = false;
}
}
// static void consume_layout_item_properties(LayoutItem &item, TokenList::iterator &tok_it, TokenList::iterator tok_end)
// {
// ensure_next_token("{", tok_it, tok_end);
// for (std::string text; (text = consume_next_token(tok_it, tok_end)) != "}";) {
// if (text == "open" || text == "selected")
// ; // skip
// else if (text == "label")
// item.label = consume_any_string(tok_it, tok_end);
// else if (text == "xywh") {
// ensure_next_token("{", tok_it, tok_end);
// item.x = consume_int_token(tok_it, tok_end);
// item.y = consume_int_token(tok_it, tok_end);
// item.w = consume_int_token(tok_it, tok_end);
// item.h = consume_int_token(tok_it, tok_end);
// ensure_next_token("}", tok_it, tok_end);
// }
// else if (text == "box")
// item.box = consume_next_token(tok_it, tok_end);
// else if (text == "labelfont")
// item.labelfont = consume_int_token(tok_it, tok_end);
// else if (text == "labelsize")
// item.labelsize = consume_int_token(tok_it, tok_end);
// else if (text == "labeltype")
// item.labeltype = consume_any_string(tok_it, tok_end);
// else if (text == "align")
// item.align = consume_int_token(tok_it, tok_end);
// else if (text == "type")
// item.type = consume_any_string(tok_it, tok_end);
// else if (text == "callback")
// item.callback = consume_any_string(tok_it, tok_end);
// else if (text == "class")
// item.classname = consume_any_string(tok_it, tok_end);
// else if (text == "minimum")
// item.minimum = consume_real_token(tok_it, tok_end);
// else if (text == "maximum")
// item.maximum = consume_real_token(tok_it, tok_end);
// else if (text == "step")
// item.step = consume_real_token(tok_it, tok_end);
// else if (text == "image") {
// item.image.filepath = consume_any_string(tok_it, tok_end);
// consume_image_properties(item.image, tok_it, tok_end);
// }
// }
// }
static void consume_layout_item_properties(LayoutItem &item, TokenList::iterator &tok_it, TokenList::iterator tok_end)
{
ensure_next_token("{", tok_it, tok_end);
for (bool have = true; have;) {
if (try_consume_next_token("open", tok_it, tok_end))
; // skip
else if (try_consume_next_token("selected", tok_it, tok_end))
; // skip
else if (try_consume_next_token("label", tok_it, tok_end))
item.label = consume_any_string(tok_it, tok_end);
else if (try_consume_next_token("xywh", tok_it, tok_end)) {
ensure_next_token("{", tok_it, tok_end);
item.x = consume_int_token(tok_it, tok_end);
item.y = consume_int_token(tok_it, tok_end);
item.w = consume_int_token(tok_it, tok_end);
item.h = consume_int_token(tok_it, tok_end);
ensure_next_token("}", tok_it, tok_end);
}
else if (try_consume_next_token("box", tok_it, tok_end))
item.box = consume_next_token(tok_it, tok_end);
else if (try_consume_next_token("down_box", tok_it, tok_end))
item.down_box = consume_next_token(tok_it, tok_end);
else if (try_consume_next_token("labelfont", tok_it, tok_end))
item.labelfont = consume_int_token(tok_it, tok_end);
else if (try_consume_next_token("labelsize", tok_it, tok_end))
item.labelsize = consume_int_token(tok_it, tok_end);
else if (try_consume_next_token("labeltype", tok_it, tok_end))
item.labeltype = consume_any_string(tok_it, tok_end);
else if (try_consume_next_token("textsize", tok_it, tok_end))
item.textsize = consume_int_token(tok_it, tok_end);
else if (try_consume_next_token("align", tok_it, tok_end))
item.align = consume_int_token(tok_it, tok_end);
else if (try_consume_next_token("type", tok_it, tok_end))
item.type = consume_any_string(tok_it, tok_end);
else if (try_consume_next_token("callback", tok_it, tok_end))
item.callback = consume_any_string(tok_it, tok_end);
else if (try_consume_next_token("class", tok_it, tok_end))
item.classname = consume_any_string(tok_it, tok_end);
else if (try_consume_next_token("value", tok_it, tok_end))
item.value = consume_real_token(tok_it, tok_end);
else if (try_consume_next_token("minimum", tok_it, tok_end))
item.minimum = consume_real_token(tok_it, tok_end);
else if (try_consume_next_token("maximum", tok_it, tok_end))
item.maximum = consume_real_token(tok_it, tok_end);
else if (try_consume_next_token("step", tok_it, tok_end))
item.step = consume_real_token(tok_it, tok_end);
else if (try_consume_next_token("image", tok_it, tok_end))
item.image.filepath = consume_any_string(tok_it, tok_end);
else if (try_consume_next_token("hide", tok_it, tok_end))
item.hidden = true;
else if (try_consume_next_token("visible", tok_it, tok_end))
/* skip */;
else if (try_consume_next_token("comment", tok_it, tok_end))
item.comment = consume_any_string(tok_it, tok_end);
else
have = false;
}
ensure_next_token("}", tok_it, tok_end);
}
static LayoutItem consume_layout_item(const std::string &classname, TokenList::iterator &tok_it, TokenList::iterator tok_end, bool anonymous = false)
{
LayoutItem item;
item.classname = classname;
if (!anonymous)
item.id = consume_any_string(tok_it, tok_end);
consume_layout_item_properties(item, tok_it, tok_end);
if (tok_it != tok_end && *tok_it == "{") {
consume_next_token(tok_it, tok_end);
for (std::string text; (text = consume_next_token(tok_it, tok_end)) != "}";) {
if (text == "decl") {
consume_any_string(tok_it, tok_end);
consume_any_string(tok_it, tok_end);
}
else if (text == "Function") {
consume_any_string(tok_it, tok_end);
consume_any_string(tok_it, tok_end);
consume_any_string(tok_it, tok_end);
}
else
item.items.push_back(consume_layout_item(text, tok_it, tok_end));
}
}
return item;
}
static Layout read_tokens_layout(TokenList::iterator &tok_it, TokenList::iterator tok_end)
{
Layout layout;
std::string version_name;
std::string header_name;
std::string code_name;
while (tok_it != tok_end) {
std::string key = consume_next_token(tok_it, tok_end);
if (key == "version")
version_name = consume_next_token(tok_it, tok_end);
else if (key == "header_name") {
ensure_next_token("{", tok_it, tok_end);
header_name = consume_next_token(tok_it, tok_end);
ensure_next_token("}", tok_it, tok_end);
}
else if (key == "code_name") {
ensure_next_token("{", tok_it, tok_end);
code_name = consume_next_token(tok_it, tok_end);
ensure_next_token("}", tok_it, tok_end);
}
else if (key == "decl") {
consume_any_string(tok_it, tok_end);
consume_any_string(tok_it, tok_end);
}
else if (key == "widget_class") {
key = consume_next_token(tok_it, tok_end);
layout.items.push_back(consume_layout_item(key, tok_it, tok_end, true));
layout.items.back().id = key;
}
else
layout.items.push_back(consume_layout_item(key, tok_it, tok_end));
}
return layout;
}
///
class tokenizer {
public:
tokenizer(
absl::string_view text,
absl::string_view dropped_delims,
absl::string_view kept_delims);
absl::string_view next();
private:
absl::string_view text_;
absl::string_view dropped_delims_;
absl::string_view kept_delims_;
};
tokenizer::tokenizer(
absl::string_view text,
absl::string_view dropped_delims,
absl::string_view kept_delims)
: text_(text), dropped_delims_(dropped_delims), kept_delims_(kept_delims)
{
}
absl::string_view tokenizer::next()
{
auto is_dropped = [this](char c) -> bool {
return dropped_delims_.find(c) != dropped_delims_.npos;
};
auto is_kept = [this](char c) -> bool {
return kept_delims_.find(c) != kept_delims_.npos;
};
auto is_delim = [this](char c) -> bool {
return dropped_delims_.find(c) != dropped_delims_.npos ||
kept_delims_.find(c) != kept_delims_.npos;
};
absl::string_view text = text_;
while (!text.empty() && is_dropped(text[0]))
text.remove_prefix(1);
if (text.empty())
return {};
size_t pos;
{
auto it = std::find_if(text.begin(), text.end(), is_delim);
if (it == text.end())
pos = text.size();
else {
pos = std::distance(text.begin(), it);
pos += is_kept(text[0]);
}
}
absl::string_view token = text.substr(0, pos);
text_ = text.substr(pos);
return token;
}
///
static bool read_file_tokens(const char *filename, TokenList &tokens)
{
std::ifstream stream(filename);
std::string line;
std::string text;
while (std::getline(stream, line)) {
if (!line.empty() && line[0] != '#') {
text.append(line);
text.push_back('\n');
}
}
if (stream.bad())
return false;
tokenizer tok(text, " \t\r\n", "{}");
absl::string_view token;
while (!(token = tok.next()).empty())
tokens.emplace_back(token);
return !stream.bad();
}

View file

@ -0,0 +1,13 @@
#pragma once
#include "layout.h"
#include <string>
#include <stdexcept>
Layout read_file_layout(const char *filename);
///
struct file_format_error : public std::runtime_error {
public:
explicit file_format_error(const std::string &reason = "Format error")
: runtime_error(reason) {}
};

View file

@ -98,10 +98,9 @@ endforeach()
if (SFIZZ_LV2_UI)
execute_process (
COMMAND "${CMAKE_COMMAND}" -E make_directory "${PROJECT_BINARY_DIR}/Contents/Resources")
foreach(res ${EDITOR_RESOURCES})
file (COPY "${CMAKE_CURRENT_SOURCE_DIR}/../editor/resources/${res}"
DESTINATION "${PROJECT_BINARY_DIR}/Contents/Resources")
endforeach()
copy_editor_resources(
"${CMAKE_CURRENT_SOURCE_DIR}/../editor/resources"
"${PROJECT_BINARY_DIR}/Contents/Resources")
endif()
# Installation

View file

@ -50,9 +50,7 @@ Name: "vst3"; Description: "VST3 plugin"; Types: full custom;
[Files]
Source: "sfizz.lv2\Contents\Binary\sfizz.dll"; Components: lv2; DestDir: "{commoncf}\LV2\sfizz.lv2\Contents\Binary"; Flags: ignoreversion
Source: "sfizz.lv2\Contents\Binary\sfizz_ui.dll"; Components: lv2; DestDir: "{commoncf}\LV2\sfizz.lv2\Contents\Binary"; Flags: ignoreversion
Source: "sfizz.lv2\Contents\Resources\DefaultInstrument.sfz"; Components: lv2; DestDir: "{commoncf}\LV2\sfizz.lv2\Contents\Resources"
Source: "sfizz.lv2\Contents\Resources\DefaultScale.scl"; Components: lv2; DestDir: "{commoncf}\LV2\sfizz.lv2\Contents\Resources"
Source: "sfizz.lv2\Contents\Resources\logo.png"; Components: lv2; DestDir: "{commoncf}\LV2\sfizz.lv2\Contents\Resources"
Source: "sfizz.lv2\Contents\Resources\*"; Components: lv2; DestDir: "{commoncf}\LV2\sfizz.lv2\Contents\Resources"
Source: "sfizz.lv2\manifest.ttl"; Components: lv2; DestDir: "{commoncf}\LV2\sfizz.lv2"
Source: "sfizz.lv2\sfizz.ttl"; Components: lv2; DestDir: "{commoncf}\LV2\sfizz.lv2"
Source: "sfizz.lv2\sfizz_ui.ttl"; Components: lv2; DestDir: "{commoncf}\LV2\sfizz.lv2"
@ -60,7 +58,7 @@ Source: "sfizz.lv2\lgpl-3.0.txt"; Components: main; DestDir: "{app}"
Source: "sfizz.lv2\LICENSE.md"; Components: main; DestDir: "{app}"
Source: "sfizz.vst3\desktop.ini"; Components: vst3; DestDir: "{commoncf}\VST3\sfizz.vst3"
Source: "sfizz.vst3\Contents\@VST3_PACKAGE_ARCHITECTURE@-win\sfizz.vst3"; Components: vst3; DestDir: "{commoncf}\VST3\sfizz.vst3\Contents\@VST3_PACKAGE_ARCHITECTURE@-win"; Flags: ignoreversion
Source: "sfizz.vst3\Contents\Resources\logo.png"; Components: vst3; DestDir: "{commoncf}\VST3\sfizz.vst3\Contents\Resources"
Source: "sfizz.vst3\Contents\Resources\*"; Components: vst3; DestDir: "{commoncf}\VST3\sfizz.vst3\Contents\Resources"
Source: "sfizz.vst3\Plugin.ico"; Components: vst3; DestDir: "{commoncf}\VST3\sfizz.vst3"
Source: "sfizz.vst3\gpl-3.0.txt"; Components: main; DestDir: "{app}"
;Source: "setup\vc_redist.x64.exe"; DestDir: {tmp}; Flags: deleteafterinstall

View file

@ -68,10 +68,9 @@ endif()
# Create the bundle (see "VST 3 Locations / Format")
execute_process (
COMMAND "${CMAKE_COMMAND}" -E make_directory "${PROJECT_BINARY_DIR}/${VSTPLUGIN_BUNDLE_NAME}/Contents/Resources")
foreach(res ${EDITOR_RESOURCES})
file (COPY "${CMAKE_CURRENT_SOURCE_DIR}/../editor/resources/${res}"
DESTINATION "${PROJECT_BINARY_DIR}/${VSTPLUGIN_BUNDLE_NAME}/Contents/Resources")
endforeach()
copy_editor_resources(
"${CMAKE_CURRENT_SOURCE_DIR}/../editor/resources"
"${PROJECT_BINARY_DIR}/${VSTPLUGIN_BUNDLE_NAME}/Contents/Resources")
if(WIN32)
set_target_properties(${VSTPLUGIN_PRJ_NAME} PROPERTIES
SUFFIX ".vst3"