diff --git a/examples/spectrogram/CMakeLists.txt b/examples/spectrogram/CMakeLists.txt index d574b50..952e187 100644 --- a/examples/spectrogram/CMakeLists.txt +++ b/examples/spectrogram/CMakeLists.txt @@ -1,16 +1,44 @@ set(TARGET spectrogram) -add_executable(${TARGET} main.cpp) +if (EMSCRIPTEN) + add_executable(${TARGET} main.cpp) -target_include_directories(${TARGET} PRIVATE - .. - ${SDL2_INCLUDE_DIRS} - ) + target_include_directories(${TARGET} PRIVATE + .. + ${SDL2_INCLUDE_DIRS} + ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TARGET}/ + ) -target_link_libraries(${TARGET} PRIVATE - ggwave - ggwave-common - ggwave-common-sdl2 - imgui-sdl2 - ${CMAKE_THREAD_LIBS_INIT} - ) + target_link_libraries(${TARGET} PRIVATE + ggwave + ggwave-common + ggwave-common-sdl2 + ggsock + imgui-sdl2 + ${CMAKE_THREAD_LIBS_INIT} + ) + + set_target_properties(${TARGET} PROPERTIES LINK_FLAGS " \ + -s FORCE_FILESYSTEM=1 \ + --preload-file ${CMAKE_CURRENT_SOURCE_DIR}/../assets/fonts@/ \ + ") + + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/build_timestamp-tmpl.h ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TARGET}/build_timestamp.h @ONLY) + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/index-tmpl.html ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TARGET}/index.html @ONLY) + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/style.css ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TARGET}/style.css COPYONLY) +else() + add_executable(${TARGET} main.cpp) + + target_include_directories(${TARGET} PRIVATE + .. + ${SDL2_INCLUDE_DIRS} + ) + + target_link_libraries(${TARGET} PRIVATE + ggwave + ggwave-common + ggwave-common-sdl2 + imgui-sdl2 + ${CMAKE_THREAD_LIBS_INIT} + ) +endif() diff --git a/examples/spectrogram/build_timestamp-tmpl.h b/examples/spectrogram/build_timestamp-tmpl.h new file mode 100644 index 0000000..63cb816 --- /dev/null +++ b/examples/spectrogram/build_timestamp-tmpl.h @@ -0,0 +1 @@ +static const char * BUILD_TIMESTAMP="@GIT_DATE@ (@GIT_SHA1@)"; diff --git a/examples/spectrogram/index-tmpl.html b/examples/spectrogram/index-tmpl.html new file mode 100644 index 0000000..f3bc390 --- /dev/null +++ b/examples/spectrogram/index-tmpl.html @@ -0,0 +1,187 @@ + + + + + Spectrogram + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+

Spectrogram

+ +
+ Loading WebAssembly module - please wait ... +
+
+
+ +
+
+ +
+ + +
+ View on GitHub + + +
+ + + + + + diff --git a/examples/spectrogram/main.cpp b/examples/spectrogram/main.cpp index 62a8a26..c9cc8cb 100644 --- a/examples/spectrogram/main.cpp +++ b/examples/spectrogram/main.cpp @@ -3,6 +3,13 @@ #include "ggwave/ggwave.h" #include "ggwave-common.h" +#ifdef __EMSCRIPTEN__ +#include "build_timestamp.h" +#include "emscripten/emscripten.h" +#else +#define EMSCRIPTEN_KEEPALIVE +#endif + #include #include @@ -326,7 +333,30 @@ void mainUpdate(void *) { g_mainUpdate(); } +// JS interface + +extern "C" { + EMSCRIPTEN_KEEPALIVE + int do_init() { + return g_doInit(); + } + + EMSCRIPTEN_KEEPALIVE + void set_window_size(int sizeX, int sizeY) { + g_setWindowSize(sizeX, sizeY); + } +} + int main(int argc, char** argv) { +#ifdef __EMSCRIPTEN__ + printf("Build time: %s\n", BUILD_TIMESTAMP); + printf("Press the Init button to start\n"); + + if (argv[1]) { + GGWave_setDefaultCaptureDeviceName(argv[1]); + } +#endif + auto argm = parseCmdArguments(argc, argv); int captureId = argm["c"].empty() ? 0 : std::stoi(argm["c"]); int playbackId = argm["p"].empty() ? 0 : std::stoi(argm["p"]); @@ -338,13 +368,19 @@ int main(int argc, char** argv) { ImGui_PreInit(); - int windowX = 1920; + int windowX = 1600; int windowY = 1200; const char * windowTitle = "spectrogram"; +#ifdef __EMSCRIPTEN__ + SDL_Renderer * renderer; + SDL_Window * window; + SDL_CreateWindowAndRenderer(windowX, windowY, SDL_WINDOW_OPENGL, &window, &renderer); +#else SDL_WindowFlags window_flags = (SDL_WindowFlags)(SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI); SDL_Window * window = SDL_CreateWindow(windowTitle, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, windowX, windowY, window_flags); +#endif void * gl_context = SDL_GL_CreateContext(window); @@ -403,6 +439,7 @@ int main(int argc, char** argv) { ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoResize | + ImGuiWindowFlags_NoScrollWithMouse | ImGuiWindowFlags_NoSavedSettings); auto & style = ImGui::GetStyle(); @@ -476,8 +513,8 @@ int main(int argc, char** argv) { if (g_showControls) { ImGui::SetNextWindowFocus(); - ImGui::SetNextWindowPos({ displaySize.x - 400 - 20, 20 }); - ImGui::SetNextWindowSize({ 400, 180 }); + ImGui::SetNextWindowPos({ std::max(20.0f, displaySize.x - 400.0f - 20.0f), 20.0f }); + ImGui::SetNextWindowSize({ std::min(displaySize.x - 40.0f, 400.0f), 180.0f }); ImGui::Begin("Controls", &g_showControls); ImGui::Text("Press 'c' to hide/show this window"); { @@ -516,6 +553,9 @@ int main(int argc, char** argv) { return true; }; +#ifdef __EMSCRIPTEN__ + emscripten_set_main_loop_arg(mainUpdate, NULL, 0, true); +#else if (g_doInit() == false) { printf("Error: failed to initialize audio\n"); return -2; @@ -535,6 +575,7 @@ int main(int argc, char** argv) { SDL_DestroyWindow(window); SDL_CloseAudio(); SDL_Quit(); +#endif return 0; } diff --git a/examples/spectrogram/style.css b/examples/spectrogram/style.css new file mode 100644 index 0000000..8708ff5 --- /dev/null +++ b/examples/spectrogram/style.css @@ -0,0 +1,323 @@ +body { + margin: 0; background-color: black; + -webkit-font-smoothing: subpixel-antialiased; + font-smoothing: subpixel-antialiased; +} +#screen { + margin: 0; + padding: 0; + font-size: 13px; + height: 100%; + font: sans-serif; +} +.no-sel { + -moz-user-select: none; + -webkit-user-select: none; + -webkit-touch-callout: none; + -ms-user-select:none; + user-select:none; + -o-user-select:none; +} +.cell { + pointer-events: none; +} +.cell-version { + padding-left: 4px; + padding-top: 0.5em; + text-align: left; + display: inline-block; + float: left; + color: rgba(0, 0, 0, 0.75); +} +.cell-about { + padding-right: 24px; + padding-top: 0.5em; + text-align: right; + display: inline-block; + float: right; +} +.nav-link { + text-decoration: none; + color: rgba(0, 0, 0, 1.0); +} + +#main-container { + font-size:12px; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; +} + +textarea { + font-size:12px; + font-family: monospace; +} + +.emscripten { padding-right: 0; margin-left: auto; margin-right: auto; display: block; } +div.emscripten_border { border: 1px solid black; } + +canvas.emscripten { + border: 0px none; + background-color: black; + text-shadow: 4px 4px #1f1f1fb4; +} + +.spinner { + height: 30px; + width: 30px; + margin: 0; + margin-top: 20px; + margin-left: 20px; + display: inline-block; + vertical-align: top; + + -webkit-animation: rotation .8s linear infinite; + -moz-animation: rotation .8s linear infinite; + -o-animation: rotation .8s linear infinite; + animation: rotation 0.8s linear infinite; + + border-left: 5px solid rgb(235, 235, 235); + border-right: 5px solid rgb(235, 235, 235); + border-bottom: 5px solid rgb(235, 235, 235); + border-top: 5px solid rgb(120, 120, 120); + + border-radius: 100%; + background-color: rgb(189, 215, 46); +} + +@-webkit-keyframes rotation { + from {-webkit-transform: rotate(0deg);} + to {-webkit-transform: rotate(360deg);} +} +@-moz-keyframes rotation { + from {-moz-transform: rotate(0deg);} + to {-moz-transform: rotate(360deg);} +} +@-o-keyframes rotation { + from {-o-transform: rotate(0deg);} + to {-o-transform: rotate(360deg);} +} +@keyframes rotation { + from {transform: rotate(0deg);} + to {transform: rotate(360deg);} +} + +#status { + display: inline-block; + vertical-align: top; + margin-top: 30px; + margin-left: 20px; + font-weight: bold; + color: rgb(120, 120, 120); +} + +#progress { + height: 20px; + width: 30px; +} + +#output { + width: 800px; + height: 200px; + margin: 0 auto; + margin-top: 10px; + border-left: 0px; + border-right: 0px; + padding-left: 0px; + padding-right: 0px; + background-color: black; + color: white; + font-size:10px; + font-family: 'Lucida Console', Monaco, monospace; + outline: none; +} + +.led-box { + height: 30px; + width: 25%; + margin: 10px 0; + float: left; +} + +.led-box p { + font-size: 12px; + text-align: center; + margin: 1em; +} + +.led-red { + margin: 0 auto; + width: 12px; + height: 12px; + background-color: #F00; + border-radius: 50%; + box-shadow: rgba(0, 0, 0, 0.2) 0 -1px 7px 1px, inset #441313 0 -1px 9px, rgba(255, 0, 0, 0.5) 0 2px 12px; + -webkit-animation: blinkRed 0.5s infinite; + -moz-animation: blinkRed 0.5s infinite; + -ms-animation: blinkRed 0.5s infinite; + -o-animation: blinkRed 0.5s infinite; + animation: blinkRed 0.5s infinite; +} + +@-webkit-keyframes blinkRed { + from { background-color: #F00; } + 50% { background-color: #A00; box-shadow: rgba(0, 0, 0, 0.2) 0 -1px 7px 1px, inset #441313 0 -1px 9px, rgba(255, 0, 0, 0.5) 0 2px 0;} + to { background-color: #F00; } +} +@-moz-keyframes blinkRed { + from { background-color: #F00; } + 50% { background-color: #A00; box-shadow: rgba(0, 0, 0, 0.2) 0 -1px 7px 1px, inset #441313 0 -1px 9px, rgba(255, 0, 0, 0.5) 0 2px 0;} + to { background-color: #F00; } +} +@-ms-keyframes blinkRed { + from { background-color: #F00; } + 50% { background-color: #A00; box-shadow: rgba(0, 0, 0, 0.2) 0 -1px 7px 1px, inset #441313 0 -1px 9px, rgba(255, 0, 0, 0.5) 0 2px 0;} + to { background-color: #F00; } +} +@-o-keyframes blinkRed { + from { background-color: #F00; } + 50% { background-color: #A00; box-shadow: rgba(0, 0, 0, 0.2) 0 -1px 7px 1px, inset #441313 0 -1px 9px, rgba(255, 0, 0, 0.5) 0 2px 0;} + to { background-color: #F00; } +} +@keyframes blinkRed { + from { background-color: #F00; } + 50% { background-color: #A00; box-shadow: rgba(0, 0, 0, 0.2) 0 -1px 7px 1px, inset #441313 0 -1px 9px, rgba(255, 0, 0, 0.5) 0 2px 0;} + to { background-color: #F00; } +} + +.led-yellow { + margin: 0 auto; + width: 12px; + height: 12px; + background-color: #FF0; + border-radius: 50%; + box-shadow: rgba(0, 0, 0, 0.2) 0 -1px 7px 1px, inset #808002 0 -1px 9px, #FF0 0 2px 12px; + -webkit-animation: blinkYellow 1s infinite; + -moz-animation: blinkYellow 1s infinite; + -ms-animation: blinkYellow 1s infinite; + -o-animation: blinkYellow 1s infinite; + animation: blinkYellow 1s infinite; +} + +@-webkit-keyframes blinkYellow { + from { background-color: #FF0; } + 50% { background-color: #AA0; box-shadow: rgba(0, 0, 0, 0.2) 0 -1px 7px 1px, inset #808002 0 -1px 9px, #FF0 0 2px 0; } + to { background-color: #FF0; } +} +@-moz-keyframes blinkYellow { + from { background-color: #FF0; } + 50% { background-color: #AA0; box-shadow: rgba(0, 0, 0, 0.2) 0 -1px 7px 1px, inset #808002 0 -1px 9px, #FF0 0 2px 0; } + to { background-color: #FF0; } +} +@-ms-keyframes blinkYellow { + from { background-color: #FF0; } + 50% { background-color: #AA0; box-shadow: rgba(0, 0, 0, 0.2) 0 -1px 7px 1px, inset #808002 0 -1px 9px, #FF0 0 2px 0; } + to { background-color: #FF0; } +} +@-o-keyframes blinkYellow { + from { background-color: #FF0; } + 50% { background-color: #AA0; box-shadow: rgba(0, 0, 0, 0.2) 0 -1px 7px 1px, inset #808002 0 -1px 9px, #FF0 0 2px 0; } + to { background-color: #FF0; } +} +@keyframes blinkYellow { + from { background-color: #FF0; } + 50% { background-color: #AA0; box-shadow: rgba(0, 0, 0, 0.2) 0 -1px 7px 1px, inset #808002 0 -1px 9px, #FF0 0 2px 0; } + to { background-color: #FF0; } +} + +.led-green { + margin: 0 auto; + width: 12px; + height: 12px; + background-color: #ABFF00; + border-radius: 50%; + box-shadow: rgba(0, 0, 0, 0.2) 0 -1px 7px 1px, inset #304701 0 -1px 9px, #89FF00 0 2px 12px; +} + +.led-blue { + margin: 0 auto; + width: 18px; + height: 18px; + background-color: #24E0FF; + border-radius: 50%; + box-shadow: rgba(0, 0, 0, 0.2) 0 -1px 7px 1px, inset #006 0 -1px 9px, #3F8CFF 0 2px 14px; +} + +table td { + border: 1px solid #e8e8e8; +} +table th, table td { + padding: 10px 10px; +} +table td { + border: 1px solid #e8e8e8; +} +table th, table td { + padding: 10px 10px; +} +td[Attributes Style] { + text-align: -webkit-center; +} +td { + display: table-cell; + vertical-align: inherit; +} +table { + margin-bottom: 30px; + width: 800px; + text-align: left; + color: #3f3f3f; + border-collapse: collapse; + border: 1px solid #e8e8e8; +} +table { + margin-bottom: 30px; + width: 800px; + text-align: left; + color: #3f3f3f; + border-collapse: collapse; + border: 1px solid #e8e8e8; +} +table { + border-collapse: separate; + border-spacing: 2px; +} + +#description { + margin: 10px; + padding: 10px; + color: rgba(255, 255, 255, 1.00); + text-shadow: 2px 2px #1f1f1fb4; +} +.text-body { + color: rgba(255, 255, 255, 1.00); + text-shadow: 2px 2px #1f1f1fb4; +} +.cell-version { + padding-left: 4px; + padding-top: 0.5em; + text-align: left; + display: inline-block; + float: left; + color: rgba(255, 255, 255, 0.75); + text-shadow: 2px 2px #1f1f1fb4; +} +.cell-about { + padding-right: 24px; + padding-top: 0.5em; + text-align: right; + display: inline-block; + float: right; +} +.nav-link { + text-decoration: none; + color: rgba(255, 255, 255, 1.0); + text-shadow: 2px 2px #1f1f1fb4; +} +.nav-link2 { + text-decoration: none; + color: rgba(0, 255, 0, 1.0); + text-shadow: 2px 2px #1f1f1fb4; +} +svg { + -webkit-filter: invert(100%); /* safari 6.0 - 9.0 */ + filter: invert(100%); +} diff --git a/examples/waver/CMakeLists.txt b/examples/waver/CMakeLists.txt index 99c0f50..226de48 100644 --- a/examples/waver/CMakeLists.txt +++ b/examples/waver/CMakeLists.txt @@ -19,9 +19,9 @@ if (EMSCRIPTEN) ) set_target_properties(${TARGET} PROPERTIES LINK_FLAGS " \ - -s FORCE_FILESYSTEM=1 \ - --preload-file ${CMAKE_CURRENT_SOURCE_DIR}/../assets/fonts@/ \ - ") + -s FORCE_FILESYSTEM=1 \ + --preload-file ${CMAKE_CURRENT_SOURCE_DIR}/../assets/fonts@/ \ + ") configure_file(${CMAKE_CURRENT_SOURCE_DIR}/build_timestamp-tmpl.h ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TARGET}/build_timestamp.h @ONLY) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/index-tmpl.html ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TARGET}/index.html @ONLY) diff --git a/examples/waver/index-tmpl.html b/examples/waver/index-tmpl.html index 84fdd91..5c76c41 100644 --- a/examples/waver/index-tmpl.html +++ b/examples/waver/index-tmpl.html @@ -115,7 +115,6 @@ window.addEventListener('keydown', onkeydown, true); setTimeout(checkLoop, 100); - //window.requestAnimationFrame(renderFrame); } function doInit() { @@ -142,10 +141,6 @@ x.hidden = false; } - //function renderFrame() { - // window.requestAnimationFrame(renderFrame); - //} - var Module = { arguments: [], preRun: [(function() {