Signed-off-by: falkTX <falktx@falktx.com>tags/22.07
| @@ -31,7 +31,7 @@ endif | |||||
| # custom build flags | # custom build flags | ||||
| BASE_FLAGS += -I../include | BASE_FLAGS += -I../include | ||||
| BASE_FLAGS += -I../include/neon-compat | |||||
| BASE_FLAGS += -I../include/simd-compat | |||||
| ifeq ($(HEADLESS),true) | ifeq ($(HEADLESS),true) | ||||
| ifeq ($(WITH_LTO),true) | ifeq ($(WITH_LTO),true) | ||||
| @@ -43,11 +43,11 @@ ifneq ($(SYSDEPS),true) | |||||
| BASE_FLAGS += -DZSTDLIB_VISIBILITY= | BASE_FLAGS += -DZSTDLIB_VISIBILITY= | ||||
| endif | endif | ||||
| ifeq ($(WASM),true) | |||||
| BASE_FLAGS += -msse -msse2 -msse3 -msimd128 | |||||
| else ifneq ($(HAIKU),true) | |||||
| ifneq ($(HAIKU),true) | |||||
| ifneq ($(WASM),true) | |||||
| BASE_FLAGS += -pthread | BASE_FLAGS += -pthread | ||||
| endif | endif | ||||
| endif | |||||
| ifeq ($(WINDOWS),true) | ifeq ($(WINDOWS),true) | ||||
| BASE_FLAGS += -D_USE_MATH_DEFINES | BASE_FLAGS += -D_USE_MATH_DEFINES | ||||
| @@ -62,6 +62,10 @@ BUILD_CXX_FLAGS += -fno-finite-math-only -fno-strict-aliasing | |||||
| # Rack code is not tested for this flag, unset it | # Rack code is not tested for this flag, unset it | ||||
| BUILD_CXX_FLAGS += -U_GLIBCXX_ASSERTIONS -Wp,-U_GLIBCXX_ASSERTIONS | BUILD_CXX_FLAGS += -U_GLIBCXX_ASSERTIONS -Wp,-U_GLIBCXX_ASSERTIONS | ||||
| ifeq ($(WASM),true) | |||||
| BUILD_CXX_FLAGS += -fexceptions | |||||
| endif | |||||
| # -------------------------------------------------------------- | # -------------------------------------------------------------- | ||||
| # override VCV arch.mk stuff so we can build more architectures | # override VCV arch.mk stuff so we can build more architectures | ||||
| @@ -1 +1 @@ | |||||
| Subproject commit 614eeaf0ef0390d4956feb991e9038980cf50371 | |||||
| Subproject commit c2938c02994988bd5dde4c4cbba9951709789ee8 | |||||
| @@ -0,0 +1,27 @@ | |||||
| /* | |||||
| * DISTRHO Cardinal Plugin | |||||
| * Copyright (C) 2021-2022 Filipe Coelho <falktx@falktx.com> | |||||
| * | |||||
| * This program is free software; you can redistribute it and/or | |||||
| * modify it under the terms of the GNU General Public License as | |||||
| * published by the Free Software Foundation; either version 3 of | |||||
| * the License, or any later version. | |||||
| * | |||||
| * This program is distributed in the hope that it will be useful, | |||||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
| * GNU General Public License for more details. | |||||
| * | |||||
| * For a full copy of the GNU General Public License see the LICENSE file. | |||||
| */ | |||||
| #pragma once | |||||
| #if defined(__i386__) || defined(__x86_64__) | |||||
| # include_next <mmintrin.h> | |||||
| #elif defined(__EMSCRIPTEN__) | |||||
| # include <wasm_simd128.h> | |||||
| // # include_next <pmmintrin.h> | |||||
| #else | |||||
| # include "../sse2neon/sse2neon.h" | |||||
| #endif | |||||
| @@ -1,6 +1,6 @@ | |||||
| /* | /* | ||||
| * DISTRHO Cardinal Plugin | * DISTRHO Cardinal Plugin | ||||
| * Copyright (C) 2021 Filipe Coelho <falktx@falktx.com> | |||||
| * Copyright (C) 2021-2022 Filipe Coelho <falktx@falktx.com> | |||||
| * | * | ||||
| * This program is free software; you can redistribute it and/or | * This program is free software; you can redistribute it and/or | ||||
| * modify it under the terms of the GNU General Public License as | * modify it under the terms of the GNU General Public License as | ||||
| @@ -17,8 +17,28 @@ | |||||
| #pragma once | #pragma once | ||||
| #if defined(__i386__) || defined(__x86_64__) || defined(__EMSCRIPTEN__) | |||||
| #if defined(__i386__) || defined(__x86_64__) | |||||
| # include_next <pmmintrin.h> | # include_next <pmmintrin.h> | ||||
| #elif defined(__EMSCRIPTEN__) | |||||
| # include_next <pmmintrin.h> | |||||
| // NOTE these have been verified to be unused (included for ValleyAudio builds) | |||||
| // static inline | |||||
| // __m64 _mm_and_si64(__m64 a, __m64 b) { return a; } | |||||
| // | |||||
| // static inline | |||||
| // __m64 _mm_andnot_si64(__m64 a, __m64 b) { return a; } | |||||
| // | |||||
| // static inline | |||||
| // __m64 _mm_or_si64(__m64 a, __m64 b) { return a; } | |||||
| static inline | |||||
| __m64 _mm_set1_pi16(short w) | |||||
| { | |||||
| return __extension__ (__m64){ static_cast<float>(w), static_cast<float>(w) }; | |||||
| } | |||||
| #else | #else | ||||
| # include "../sse2neon/sse2neon.h" | # include "../sse2neon/sse2neon.h" | ||||
| @@ -490,12 +490,9 @@ BOGAUDIO_CUSTOM_PER_FILE = ARQuantity AttackMenuItem ReleaseMenuItem | |||||
| # -------------------------------------------------------------- | # -------------------------------------------------------------- | ||||
| # ChowDSP | # ChowDSP | ||||
| # FIXME | |||||
| ifneq ($(WASM),true) | |||||
| PLUGIN_FILES += $(wildcard ChowDSP/src/*/*.cpp) | PLUGIN_FILES += $(wildcard ChowDSP/src/*/*.cpp) | ||||
| PLUGIN_FILES += $(wildcard ChowDSP/src/*/*/*.cpp) | PLUGIN_FILES += $(wildcard ChowDSP/src/*/*/*.cpp) | ||||
| PLUGIN_FILES += $(wildcard ChowDSP/lib/r8lib/*.cpp) | PLUGIN_FILES += $(wildcard ChowDSP/lib/r8lib/*.cpp) | ||||
| endif | |||||
| # -------------------------------------------------------------- | # -------------------------------------------------------------- | ||||
| # CatroModulo | # CatroModulo | ||||
| @@ -828,8 +825,6 @@ UNLESS_MODULES_CUSTOM = Selection | |||||
| # -------------------------------------------------------------- | # -------------------------------------------------------------- | ||||
| # ValleyAudio | # ValleyAudio | ||||
| # FIXME | |||||
| ifneq ($(WASM),true) | |||||
| PLUGIN_FILES += $(filter-out ValleyAudio/src/Valley.cpp,$(wildcard ValleyAudio/src/*.cpp)) | PLUGIN_FILES += $(filter-out ValleyAudio/src/Valley.cpp,$(wildcard ValleyAudio/src/*.cpp)) | ||||
| PLUGIN_FILES += $(wildcard ValleyAudio/src/*/*.cpp) | PLUGIN_FILES += $(wildcard ValleyAudio/src/*/*.cpp) | ||||
| PLUGIN_FILES += $(wildcard ValleyAudio/src/*/*/*.cpp) | PLUGIN_FILES += $(wildcard ValleyAudio/src/*/*/*.cpp) | ||||
| @@ -902,7 +897,6 @@ PLUGIN_BINARIES += ValleyAudio/src/XFADE.bin | |||||
| # modules/types which are present in other plugins | # modules/types which are present in other plugins | ||||
| VALLEYAUDIO_CUSTOM = $(DRWAV) DigitalDisplay | VALLEYAUDIO_CUSTOM = $(DRWAV) DigitalDisplay | ||||
| VALLEYAUDIO_CUSTOM_PER_FILE = TempoKnob | VALLEYAUDIO_CUSTOM_PER_FILE = TempoKnob | ||||
| endif | |||||
| # -------------------------------------------------------------- | # -------------------------------------------------------------- | ||||
| # Voxglitch | # Voxglitch | ||||
| @@ -955,8 +949,8 @@ BASE_FLAGS += -I../dpf/dgl/src/nanovg | |||||
| BASE_FLAGS += -I../dpf/distrho | BASE_FLAGS += -I../dpf/distrho | ||||
| BASE_FLAGS += -I../include | BASE_FLAGS += -I../include | ||||
| BASE_FLAGS += -I../include/neon-compat | |||||
| BASE_FLAGS += -I../include/osdialog-stub | BASE_FLAGS += -I../include/osdialog-stub | ||||
| BASE_FLAGS += -I../include/simd-compat | |||||
| ifeq ($(HAVE_X11),true) | ifeq ($(HAVE_X11),true) | ||||
| BASE_FLAGS += -DHAVE_X11 | BASE_FLAGS += -DHAVE_X11 | ||||
| @@ -995,14 +989,16 @@ endif | |||||
| ifeq ($(BSD),true) | ifeq ($(BSD),true) | ||||
| BASE_FLAGS += -D'aligned_alloc_16(ptr)'='aligned_alloc(16,ptr)' | BASE_FLAGS += -D'aligned_alloc_16(ptr)'='aligned_alloc(16,ptr)' | ||||
| BASE_FLAGS += -D'aligned_free_16(ptr)'='free(ptr)' | BASE_FLAGS += -D'aligned_free_16(ptr)'='free(ptr)' | ||||
| else ifeq ($(WASM),true) | |||||
| BASE_FLAGS += -D'aligned_alloc_16(ptr)'='aligned_alloc(16,ptr)' | |||||
| BASE_FLAGS += -D'aligned_free_16(ptr)'='free(ptr)' | |||||
| endif | endif | ||||
| ifeq ($(WASM),true) | |||||
| BASE_FLAGS += -DNANOVG_GLES2=1 | |||||
| BASE_FLAGS += -msse -msse2 -msse3 -msimd128 | |||||
| else ifneq ($(HAIKU),true) | |||||
| ifneq ($(WASM),true) | |||||
| ifneq ($(HAIKU),true) | |||||
| BASE_FLAGS += -pthread | BASE_FLAGS += -pthread | ||||
| endif | endif | ||||
| endif | |||||
| ifeq ($(WINDOWS),true) | ifeq ($(WINDOWS),true) | ||||
| BASE_FLAGS += -D_USE_MATH_DEFINES | BASE_FLAGS += -D_USE_MATH_DEFINES | ||||
| @@ -1036,6 +1032,10 @@ endif | |||||
| # Rack code is not tested for this flag, unset it | # Rack code is not tested for this flag, unset it | ||||
| BUILD_CXX_FLAGS += -U_GLIBCXX_ASSERTIONS -Wp,-U_GLIBCXX_ASSERTIONS | BUILD_CXX_FLAGS += -U_GLIBCXX_ASSERTIONS -Wp,-U_GLIBCXX_ASSERTIONS | ||||
| ifeq ($(WASM),true) | |||||
| BUILD_CXX_FLAGS += -fexceptions | |||||
| endif | |||||
| # -------------------------------------------------------------- | # -------------------------------------------------------------- | ||||
| # lots of warnings from VCV side | # lots of warnings from VCV side | ||||
| @@ -1622,8 +1622,6 @@ static void initStatic__cf() | |||||
| } | } | ||||
| } | } | ||||
| // FIXME | |||||
| #ifndef DISTRHO_OS_WASM | |||||
| static void initStatic__ChowDSP() | static void initStatic__ChowDSP() | ||||
| { | { | ||||
| Plugin* const p = new Plugin; | Plugin* const p = new Plugin; | ||||
| @@ -1650,7 +1648,6 @@ static void initStatic__ChowDSP() | |||||
| p->addModel(modelChowChorus); | p->addModel(modelChowChorus); | ||||
| } | } | ||||
| } | } | ||||
| #endif | |||||
| static void initStatic__DrumKit() | static void initStatic__DrumKit() | ||||
| { | { | ||||
| @@ -2589,8 +2586,6 @@ static void initStatic__unless_modules() | |||||
| } | } | ||||
| } | } | ||||
| // FIXME | |||||
| #ifndef DISTRHO_OS_WASM | |||||
| static void initStatic__ValleyAudio() | static void initStatic__ValleyAudio() | ||||
| { | { | ||||
| Plugin* const p = new Plugin; | Plugin* const p = new Plugin; | ||||
| @@ -2609,7 +2604,6 @@ static void initStatic__ValleyAudio() | |||||
| p->addModel(modelTerrorform); | p->addModel(modelTerrorform); | ||||
| } | } | ||||
| } | } | ||||
| #endif | |||||
| static void initStatic__Voxglitch() | static void initStatic__Voxglitch() | ||||
| { | { | ||||
| @@ -2725,10 +2719,7 @@ void initStaticPlugins() | |||||
| initStatic__BogaudioModules(); | initStatic__BogaudioModules(); | ||||
| initStatic__CatroModulo(); | initStatic__CatroModulo(); | ||||
| initStatic__cf(); | initStatic__cf(); | ||||
| // FIXME | |||||
| #ifndef DISTRHO_OS_WASM | |||||
| initStatic__ChowDSP(); | initStatic__ChowDSP(); | ||||
| #endif | |||||
| initStatic__DrumKit(); | initStatic__DrumKit(); | ||||
| initStatic__ESeries(); | initStatic__ESeries(); | ||||
| initStatic__ExpertSleepersEncoders(); | initStatic__ExpertSleepersEncoders(); | ||||
| @@ -2768,10 +2759,7 @@ void initStaticPlugins() | |||||
| initStatic__sonusmodular(); | initStatic__sonusmodular(); | ||||
| initStatic__stocaudio(); | initStatic__stocaudio(); | ||||
| initStatic__unless_modules(); | initStatic__unless_modules(); | ||||
| // FIXME | |||||
| #ifndef DISTRHO_OS_WASM | |||||
| initStatic__ValleyAudio(); | initStatic__ValleyAudio(); | ||||
| #endif | |||||
| initStatic__Voxglitch(); | initStatic__Voxglitch(); | ||||
| initStatic__WhatTheRack(); | initStatic__WhatTheRack(); | ||||
| initStatic__ZetaCarinaeModules(); | initStatic__ZetaCarinaeModules(); | ||||
| @@ -44,7 +44,7 @@ struct AsyncDialog : OpaqueWidget | |||||
| Label* label; | Label* label; | ||||
| AsyncDialog(const char* const message) | AsyncDialog(const char* const message) | ||||
| { | |||||
| { | |||||
| setup(message); | setup(message); | ||||
| struct AsyncDismissButton : Button { | struct AsyncDismissButton : Button { | ||||
| @@ -61,7 +61,7 @@ struct AsyncDialog : OpaqueWidget | |||||
| } | } | ||||
| AsyncDialog(const char* const message, const std::function<void()> action) | AsyncDialog(const char* const message, const std::function<void()> action) | ||||
| { | |||||
| { | |||||
| setup(message); | setup(message); | ||||
| struct AsyncCancelButton : Button { | struct AsyncCancelButton : Button { | ||||
| @@ -131,7 +131,7 @@ struct AsyncDialog : OpaqueWidget | |||||
| } | } | ||||
| void draw(const DrawArgs& args) override | void draw(const DrawArgs& args) override | ||||
| { | |||||
| { | |||||
| bndMenuBackground(args.vg, 0.0, 0.0, box.size.x, box.size.y, 0); | bndMenuBackground(args.vg, 0.0, 0.0, box.size.x, box.size.y, 0); | ||||
| Widget::draw(args); | Widget::draw(args); | ||||
| } | } | ||||
| @@ -261,13 +261,13 @@ struct AsyncTextInput : OpaqueWidget | |||||
| } | } | ||||
| void step() override | void step() override | ||||
| { | |||||
| { | |||||
| OpaqueWidget::step(); | OpaqueWidget::step(); | ||||
| box.pos = parent->box.size.minus(box.size).div(2).round(); | box.pos = parent->box.size.minus(box.size).div(2).round(); | ||||
| } | } | ||||
| void draw(const DrawArgs& args) override | void draw(const DrawArgs& args) override | ||||
| { | |||||
| { | |||||
| bndMenuBackground(args.vg, 0.0, 0.0, box.size.x, box.size.y, 0); | bndMenuBackground(args.vg, 0.0, 0.0, box.size.x, box.size.y, 0); | ||||
| Widget::draw(args); | Widget::draw(args); | ||||
| } | } | ||||
| @@ -44,7 +44,7 @@ BASE_FLAGS += -DPRIVATE= | |||||
| BASE_FLAGS += -I../dpf/dgl/src/nanovg | BASE_FLAGS += -I../dpf/dgl/src/nanovg | ||||
| BASE_FLAGS += -I../dpf/distrho | BASE_FLAGS += -I../dpf/distrho | ||||
| BASE_FLAGS += -I../include | BASE_FLAGS += -I../include | ||||
| BASE_FLAGS += -I../include/neon-compat | |||||
| BASE_FLAGS += -I../include/simd-compat | |||||
| BASE_FLAGS += -IRack/include | BASE_FLAGS += -IRack/include | ||||
| ifeq ($(SYSDEPS),true) | ifeq ($(SYSDEPS),true) | ||||
| BASE_FLAGS += -DCARDINAL_SYSDEPS | BASE_FLAGS += -DCARDINAL_SYSDEPS | ||||
| @@ -81,14 +81,11 @@ ifeq ($(HAIKU),true) | |||||
| BASE_FLAGS += -DCLOCK_MONOTONIC_RAW=CLOCK_MONOTONIC | BASE_FLAGS += -DCLOCK_MONOTONIC_RAW=CLOCK_MONOTONIC | ||||
| endif | endif | ||||
| ifeq ($(WASM),true) | |||||
| BASE_FLAGS += -DNANOVG_GLES2=1 | |||||
| BASE_FLAGS += -msse -msse2 -msse3 -msimd128 | |||||
| # FIXME | |||||
| BASE_FLAGS += -DRTLD_DEEPBIND=0 | |||||
| else ifneq ($(HAIKU),true) | |||||
| ifneq ($(WASM),true) | |||||
| ifneq ($(HAIKU),true) | |||||
| BASE_FLAGS += -pthread | BASE_FLAGS += -pthread | ||||
| endif | endif | ||||
| endif | |||||
| ifeq ($(WINDOWS),true) | ifeq ($(WINDOWS),true) | ||||
| BASE_FLAGS += -D_USE_MATH_DEFINES | BASE_FLAGS += -D_USE_MATH_DEFINES | ||||
| @@ -117,6 +114,10 @@ BUILD_CXX_FLAGS += -DnsvgParseFromFile=nsvgParseFromFileCardinal | |||||
| # Rack code is not tested for this flag, unset it | # Rack code is not tested for this flag, unset it | ||||
| BUILD_CXX_FLAGS += -U_GLIBCXX_ASSERTIONS -Wp,-U_GLIBCXX_ASSERTIONS | BUILD_CXX_FLAGS += -U_GLIBCXX_ASSERTIONS -Wp,-U_GLIBCXX_ASSERTIONS | ||||
| ifeq ($(WASM),true) | |||||
| BUILD_CXX_FLAGS += -fexceptions | |||||
| endif | |||||
| # -------------------------------------------------------------- | # -------------------------------------------------------------- | ||||
| # Rack files to build | # Rack files to build | ||||
| @@ -143,7 +143,7 @@ BASE_FLAGS += -DPRIVATE= | |||||
| BASE_FLAGS += -I.. | BASE_FLAGS += -I.. | ||||
| BASE_FLAGS += -I../../dpf/dgl/src/nanovg | BASE_FLAGS += -I../../dpf/dgl/src/nanovg | ||||
| BASE_FLAGS += -I../../include | BASE_FLAGS += -I../../include | ||||
| BASE_FLAGS += -I../../include/neon-compat | |||||
| BASE_FLAGS += -I../../include/simd-compat | |||||
| BASE_FLAGS += -I../Rack/include | BASE_FLAGS += -I../Rack/include | ||||
| ifeq ($(SYSDEPS),true) | ifeq ($(SYSDEPS),true) | ||||
| BASE_FLAGS += -DCARDINAL_SYSDEPS | BASE_FLAGS += -DCARDINAL_SYSDEPS | ||||
| @@ -164,12 +164,11 @@ ifeq ($(MOD_BUILD),true) | |||||
| BASE_FLAGS += -DDISTRHO_PLUGIN_USES_MODGUI=1 -DDISTRHO_PLUGIN_MINIMUM_BUFFER_SIZE=0xffff | BASE_FLAGS += -DDISTRHO_PLUGIN_USES_MODGUI=1 -DDISTRHO_PLUGIN_MINIMUM_BUFFER_SIZE=0xffff | ||||
| endif | endif | ||||
| ifeq ($(WASM),true) | |||||
| BASE_FLAGS += -DNANOVG_GLES2=1 | |||||
| BASE_FLAGS += -msse -msse2 -msse3 -msimd128 | |||||
| else ifneq ($(HAIKU),true) | |||||
| ifneq ($(WASM),true) | |||||
| ifneq ($(HAIKU),true) | |||||
| BASE_FLAGS += -pthread | BASE_FLAGS += -pthread | ||||
| endif | endif | ||||
| endif | |||||
| ifeq ($(WINDOWS),true) | ifeq ($(WINDOWS),true) | ||||
| BASE_FLAGS += -D_USE_MATH_DEFINES | BASE_FLAGS += -D_USE_MATH_DEFINES | ||||
| @@ -195,6 +194,10 @@ endif | |||||
| # Rack code is not tested for this flag, unset it | # Rack code is not tested for this flag, unset it | ||||
| BUILD_CXX_FLAGS += -U_GLIBCXX_ASSERTIONS -Wp,-U_GLIBCXX_ASSERTIONS | BUILD_CXX_FLAGS += -U_GLIBCXX_ASSERTIONS -Wp,-U_GLIBCXX_ASSERTIONS | ||||
| ifeq ($(WASM),true) | |||||
| BUILD_CXX_FLAGS += -fexceptions | |||||
| endif | |||||
| # -------------------------------------------------------------- | # -------------------------------------------------------------- | ||||
| # FIXME lots of warnings from VCV side | # FIXME lots of warnings from VCV side | ||||
| @@ -205,8 +208,12 @@ BASE_FLAGS += -Wno-unused-variable | |||||
| # extra linker flags | # extra linker flags | ||||
| ifeq ($(WASM),true) | ifeq ($(WASM),true) | ||||
| LINK_FLAGS += --preload-file=./resources -sALLOW_MEMORY_GROWTH -sINITIAL_MEMORY=32Mb -sLZ4=1 --shell-file=../emscripten/shell.html | |||||
| # -sDISABLE_EXCEPTION_CATCHING=1 | |||||
| LINK_FLAGS += --preload-file=./resources | |||||
| LINK_FLAGS += -sALLOW_MEMORY_GROWTH | |||||
| LINK_FLAGS += -sEXPORTED_RUNTIME_METHODS=FS,ccall | |||||
| LINK_FLAGS += -sINITIAL_MEMORY=64Mb | |||||
| LINK_FLAGS += -sLZ4=1 | |||||
| LINK_FLAGS += --shell-file=../emscripten/shell.html | |||||
| else ifeq ($(HAIKU),true) | else ifeq ($(HAIKU),true) | ||||
| LINK_FLAGS += -lpthread | LINK_FLAGS += -lpthread | ||||
| else | else | ||||
| @@ -14,6 +14,11 @@ | |||||
| margin: 0; | margin: 0; | ||||
| } | } | ||||
| #canvas_file_open, | |||||
| #canvas_file_save { | |||||
| display: none; | |||||
| } | |||||
| #canvas_wrapper { | #canvas_wrapper { | ||||
| display: none; | display: none; | ||||
| width: 100vw; | width: 100vw; | ||||
| @@ -73,6 +78,8 @@ | |||||
| <progress value="0" max="100" id="progress" hidden=1></progress> | <progress value="0" max="100" id="progress" hidden=1></progress> | ||||
| </div> | </div> | ||||
| <div id="canvas_wrapper"> | <div id="canvas_wrapper"> | ||||
| <input type="file" id="canvas_file_open" ></input> | |||||
| <a href="#" id="canvas_file_save"></a> | |||||
| <canvas class="emscripten" id="canvas" oncontextmenu="event.preventDefault()" tabindex=-1></canvas> | <canvas class="emscripten" id="canvas" oncontextmenu="event.preventDefault()" tabindex=-1></canvas> | ||||
| </div> | </div> | ||||