├── config.osx.make ├── icon.ico ├── assets ├── icon.ico ├── icon-mac.icns ├── icons_source │ ├── dot.psd │ └── icon.psd ├── Images.xcassets │ └── AppIcon.appiconset │ │ ├── appicon-16.png │ │ ├── appicon-32.png │ │ ├── appicon-64.png │ │ ├── appicon-1024.png │ │ ├── appicon-128.png │ │ ├── appicon-256.png │ │ ├── appicon-512.png │ │ └── Contents.json ├── wix_db.txt ├── icon-mac ├── wix_config.wxi ├── wix_heat.xslt ├── wix_main.wxs └── wix_files.wxs ├── docs └── screenshot.png ├── bin └── data │ ├── konichiwa.wav │ └── shaders │ ├── osci.vert │ ├── osci.geom │ └── osci.frag ├── windows_dlls ├── msvcp140.dll ├── vcomp140.dll ├── vcruntime140.dll └── api-ms-win-crt-runtime-l1-1-0.dll ├── OscilloscopeM1Debug.entitlements ├── oscilloscope.xcodeproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ ├── IDEWorkspaceChecks.plist │ │ └── WorkspaceSettings.xcsettings └── xcshareddata │ └── xcschemes │ ├── oscilloscope Debug.xcscheme │ └── oscilloscope Release.xcscheme ├── addons.make ├── src ├── version.h ├── util │ ├── TexShare.h │ ├── TexShare.cpp │ ├── WickedLasers.h │ ├── OsciVideoWriter.hpp │ ├── ShaderLoader.h │ ├── Audio.h │ ├── Audio.cpp │ ├── OsciAvAudioPlayer.h │ └── WickedLasers.cpp ├── ui │ ├── FaButton.h │ ├── Dialogs.h │ ├── FaToggleButton.h │ ├── ExportScreen.h │ ├── ConfigView.h │ ├── Playlist.h │ ├── PlayerOverlay.h │ ├── Dialogs.cpp │ ├── FMenu.h │ ├── ExportScreen.cpp │ ├── ConfigView.cpp │ └── FMenu.cpp ├── OsciMesh.h ├── ofxIniSettings │ ├── ofxIniExtras.h │ ├── ofxIniSettings.h │ └── ofxIniExtras.cpp ├── globals.h ├── OsciMesh.cpp ├── ofApp.h ├── main.cpp └── globals.cpp ├── scripts ├── clean.sh ├── osx-config-template.sh ├── functions.sh ├── prepare.sh ├── osx-notarize.sh ├── osx-sign.sh ├── readme.md └── dist.sh ├── resource.h ├── Oscilloscope.entitlements ├── Makefile ├── Project.xcconfig ├── .github └── FUNDING.yml ├── openFrameworks-Info.plist ├── .gitmodules ├── LICENSE ├── Oscilloscope.sln ├── icon.rc ├── Oscilloscope.qbs ├── .gitignore ├── readme.md └── config.make /config.osx.make: -------------------------------------------------------------------------------- 1 | PLATFORM_CFLAGS=-DMA_MAX_CHANNELS=128 -------------------------------------------------------------------------------- /icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kritzikratzi/Oscilloscope/HEAD/icon.ico -------------------------------------------------------------------------------- /assets/icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kritzikratzi/Oscilloscope/HEAD/assets/icon.ico -------------------------------------------------------------------------------- /assets/icon-mac.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kritzikratzi/Oscilloscope/HEAD/assets/icon-mac.icns -------------------------------------------------------------------------------- /docs/screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kritzikratzi/Oscilloscope/HEAD/docs/screenshot.png -------------------------------------------------------------------------------- /bin/data/konichiwa.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kritzikratzi/Oscilloscope/HEAD/bin/data/konichiwa.wav -------------------------------------------------------------------------------- /windows_dlls/msvcp140.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kritzikratzi/Oscilloscope/HEAD/windows_dlls/msvcp140.dll -------------------------------------------------------------------------------- /windows_dlls/vcomp140.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kritzikratzi/Oscilloscope/HEAD/windows_dlls/vcomp140.dll -------------------------------------------------------------------------------- /assets/icons_source/dot.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kritzikratzi/Oscilloscope/HEAD/assets/icons_source/dot.psd -------------------------------------------------------------------------------- /assets/icons_source/icon.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kritzikratzi/Oscilloscope/HEAD/assets/icons_source/icon.psd -------------------------------------------------------------------------------- /windows_dlls/vcruntime140.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kritzikratzi/Oscilloscope/HEAD/windows_dlls/vcruntime140.dll -------------------------------------------------------------------------------- /windows_dlls/api-ms-win-crt-runtime-l1-1-0.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kritzikratzi/Oscilloscope/HEAD/windows_dlls/api-ms-win-crt-runtime-l1-1-0.dll -------------------------------------------------------------------------------- /assets/Images.xcassets/AppIcon.appiconset/appicon-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kritzikratzi/Oscilloscope/HEAD/assets/Images.xcassets/AppIcon.appiconset/appicon-16.png -------------------------------------------------------------------------------- /assets/Images.xcassets/AppIcon.appiconset/appicon-32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kritzikratzi/Oscilloscope/HEAD/assets/Images.xcassets/AppIcon.appiconset/appicon-32.png -------------------------------------------------------------------------------- /assets/Images.xcassets/AppIcon.appiconset/appicon-64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kritzikratzi/Oscilloscope/HEAD/assets/Images.xcassets/AppIcon.appiconset/appicon-64.png -------------------------------------------------------------------------------- /assets/Images.xcassets/AppIcon.appiconset/appicon-1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kritzikratzi/Oscilloscope/HEAD/assets/Images.xcassets/AppIcon.appiconset/appicon-1024.png -------------------------------------------------------------------------------- /assets/Images.xcassets/AppIcon.appiconset/appicon-128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kritzikratzi/Oscilloscope/HEAD/assets/Images.xcassets/AppIcon.appiconset/appicon-128.png -------------------------------------------------------------------------------- /assets/Images.xcassets/AppIcon.appiconset/appicon-256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kritzikratzi/Oscilloscope/HEAD/assets/Images.xcassets/AppIcon.appiconset/appicon-256.png -------------------------------------------------------------------------------- /assets/Images.xcassets/AppIcon.appiconset/appicon-512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kritzikratzi/Oscilloscope/HEAD/assets/Images.xcassets/AppIcon.appiconset/appicon-512.png -------------------------------------------------------------------------------- /OscilloscopeM1Debug.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /oscilloscope.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /addons.make: -------------------------------------------------------------------------------- 1 | addons/ofxAvCodec 2 | addons/ofxFontAwesome 3 | addons/ofxFontStash2 4 | addons/ofxMightyUI 5 | addons/ofxNative 6 | addons/ofxSyphon 7 | addons/ofxSpout 8 | addons/ofxLibsamplerate 9 | addons/ofxLiblaserdock 10 | -------------------------------------------------------------------------------- /src/version.h: -------------------------------------------------------------------------------- 1 | // 2 | // version.h 3 | // oscilloscope 4 | // 5 | // Created by Hansi on 21.09.20. 6 | // 7 | 8 | #ifndef version_h 9 | #define version_h 10 | 11 | const static string app_version = "1.1.0"; 12 | 13 | #endif /* version_h */ 14 | -------------------------------------------------------------------------------- /bin/data/shaders/osci.vert: -------------------------------------------------------------------------------- 1 | #version 110 2 | uniform mat4 uMatrix; 3 | varying vec4 color; 4 | varying float brightness; 5 | 6 | void main() 7 | { 8 | gl_Position = uMatrix*vec4(gl_Vertex.xy,0,gl_Vertex.w); 9 | brightness = min(max(0.0,gl_Vertex.z),1.0); 10 | 11 | color = gl_Color; 12 | } -------------------------------------------------------------------------------- /assets/wix_db.txt: -------------------------------------------------------------------------------- 1 | 1.0.10=27e537a7-c2d6-4000-99ef-60af66213a0c 2 | 1.0.11=c4e30d53-5c87-4e54-bb97-a9c8119ee30e 3 | 1.0.12=506dff4c-ce1d-489e-a370-b77795744aa9 4 | 1.0.13=e71bb848-089b-40e8-992a-83857e65f196 5 | 1.0.14=c50dae23-ae77-49e8-861b-4380ee9bc447 6 | 1.0.15=884f80b0-093e-431f-963f-caa8155af91e 7 | 1.1.0=42f454b6-bcae-4bd1-884b-e28e9b82b87d 8 | -------------------------------------------------------------------------------- /oscilloscope.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /oscilloscope.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | BuildSystemType 6 | Original 7 | 8 | 9 | -------------------------------------------------------------------------------- /scripts/clean.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | basedir=$(dirname $0) 3 | pushd $basedir/../bin 4 | echo "Cleaning out $basedir folder ... " 5 | 6 | echo "----------------------------" 7 | git clean -ndx . 8 | echo "----------------------------" 9 | 10 | echo "Delete all the above files? " 11 | read -p "Are you sure? [y/N] " -n 1 -r 12 | echo # (optional) move to a new line 13 | if [[ $REPLY =~ ^[Yy]$ ]] 14 | then 15 | echo " ... Cleaning up" 16 | git clean -fdx . 17 | else 18 | echo " ... skipped" 19 | fi 20 | popd -------------------------------------------------------------------------------- /resource.h: -------------------------------------------------------------------------------- 1 | //{{NO_DEPENDENCIES}} 2 | // Microsoft Visual C++ generated include file. 3 | // Used by icon.rc 4 | // 5 | #define MAIN_ICON 102 6 | 7 | // Next default values for new objects 8 | // 9 | #ifdef APSTUDIO_INVOKED 10 | #ifndef APSTUDIO_READONLY_SYMBOLS 11 | #define _APS_NEXT_RESOURCE_VALUE 102 12 | #define _APS_NEXT_COMMAND_VALUE 40001 13 | #define _APS_NEXT_CONTROL_VALUE 1000 14 | #define _APS_NEXT_SYMED_VALUE 101 15 | #endif 16 | #endif 17 | -------------------------------------------------------------------------------- /src/util/TexShare.h: -------------------------------------------------------------------------------- 1 | // 2 | // SharedTex.hpp 3 | // Oscilloscope 4 | // 5 | // Created by Hansi on 27/06/19. 6 | // 7 | // 8 | 9 | #ifndef SharedTex_hpp 10 | #define SharedTex_hpp 11 | 12 | #include 13 | #include 14 | class ofTexture; 15 | 16 | class TexShareImpl; 17 | class TexShare{ 18 | public: 19 | TexShare(); 20 | ~TexShare(); 21 | void setup(std::string name); 22 | void update(ofTexture & tex); 23 | 24 | private: 25 | std::unique_ptr impl; 26 | }; 27 | 28 | 29 | #endif /* SharedTex_hpp */ 30 | -------------------------------------------------------------------------------- /scripts/osx-config-template.sh: -------------------------------------------------------------------------------- 1 | # You can find the developer id in your keychain (i guess) 2 | # Team-Id and Asc-Provider are shown with this command: 3 | # xcrun altool --list-providers -u your@apple-account.com -p your-app-specific-password 4 | DEVELOPER_IDENTITY="Developer ID Application: hansi raber" 5 | DEVELOPER_TEAMID="ABCD12EF" 6 | ASC_PROVIDER="yourname12341234" 7 | 8 | # Apple account user (your email address) 9 | NOTARIZE_USER="your@apple-account.com" 10 | 11 | # An app specific password (generated in your apple account settings) 12 | NOTARIZE_PASSWORD="your-app-specific-password" 13 | -------------------------------------------------------------------------------- /src/ui/FaButton.h: -------------------------------------------------------------------------------- 1 | // 2 | // FAButton.h 3 | // OsciStudio 4 | // 5 | // Created by Hansi on 04.04.15. 6 | // 7 | // 20.12.2018: added optional fontName argument. this makes it easy to use with multiple versions of fontawesome 8 | 9 | #ifndef FaButton_h 10 | #define FaButton_h 11 | 12 | #include "ofxMightyUI.h" 13 | 14 | class FaButton : public mui::Button{ 15 | public: 16 | FaButton( string icon, float x = 0, float y = 0, float width = 100, float height = 20, const string & fontName = "fontawesome-webfont.ttf" ) : 17 | mui::Button(icon, x, y, width, height ){ 18 | this->label->fontName = fontName; 19 | this->label->commit(); 20 | } 21 | }; 22 | #endif 23 | -------------------------------------------------------------------------------- /Oscilloscope.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.app-sandbox 6 | 7 | com.apple.security.application-groups 8 | 9 | com.apple.security.device.audio-input 10 | 11 | com.apple.security.device.microphone 12 | 13 | com.apple.security.device.usb 14 | 15 | com.apple.security.files.user-selected.read-write 16 | 17 | com.apple.security.network.client 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # Attempt to load a config.make file. 2 | # If none is found, project defaults in config.project.make will be used. 3 | ifneq ($(wildcard config.make),) 4 | include config.make 5 | endif 6 | 7 | # make sure the the OF_ROOT location is defined 8 | ifndef OF_ROOT 9 | OF_ROOT=../../.. 10 | endif 11 | 12 | copy_osx_files: 13 | cp -r $(OF_ROOT)/addons/ofxMightyUI/bin/data/ bin/$(APPNAME).app/Contents/Resources/ 14 | cp -r $(OF_ROOT)/addons/ofxFontAwesome/bin/data/ bin/$(APPNAME).app/Contents/Resources/ 15 | 16 | 17 | PROJECT_AFTER_OSX=make copy_osx_files 18 | 19 | # call the project makefile! 20 | include $(OF_ROOT)/libs/openFrameworksCompiled/project/makefileCommon/compile.project.mk 21 | -------------------------------------------------------------------------------- /Project.xcconfig: -------------------------------------------------------------------------------- 1 | //THE PATH TO THE ROOT OF OUR OF PATH RELATIVE TO THIS PROJECT. 2 | //THIS NEEDS TO BE DEFINED BEFORE CoreOF.xcconfig IS INCLUDED 3 | OF_PATH = ../../.. 4 | 5 | //THIS HAS ALL THE HEADER AND LIBS FOR OF CORE 6 | #include "../../../libs/openFrameworksCompiled/project/osx/CoreOF.xcconfig" 7 | 8 | //ICONS - NEW IN 0072 9 | ICON_NAME_DEBUG = icon-mac.icns 10 | ICON_NAME_RELEASE = icon-mac.icns 11 | ICON_FILE_PATH = $(OF_PATH)/libs/openFrameworksCompiled/project/osx/ 12 | 13 | //IF YOU WANT AN APP TO HAVE A CUSTOM ICON - PUT THEM IN YOUR DATA FOLDER AND CHANGE ICON_FILE_PATH to: 14 | ICON_FILE_PATH = ./assets/ 15 | 16 | OTHER_CFLAGS = $(OF_CORE_CFLAGS) 17 | OTHER_LDFLAGS = $(OF_CORE_LIBS) $(OF_CORE_FRAMEWORKS) 18 | HEADER_SEARCH_PATHS = $(OF_CORE_HEADERS) 19 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: [kritzikratzi] # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] 4 | patreon: # Replace with a single Patreon username 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | otechie: # Replace with a single Otechie username 12 | custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] 13 | -------------------------------------------------------------------------------- /assets/icon-mac: -------------------------------------------------------------------------------- 1 | How to use this icon: 2 | 3 | Step 1: Copy the icon to the clipboard 4 | a) Click on this file from the Finder 5 | b) Choose 'Get Info' from the 'File' menu. 6 | c) In the info window that pops up, click on the icon 7 | d) Choose 'Copy' from the 'Edit' menu. 8 | e) Close the info window 9 | 10 | Step 2: Paste the icon to the desired item 11 | a) Go to the item in the Finder that you want a custom icon 12 | b) Click the item (file, folder, disk, etc) 13 | b) Choose 'Get Info' from the 'File' menu. 14 | c) In the info window that pops up, click on the icon 15 | d) Choose 'Paste' from the 'Edit' menu. 16 | e) Close the info window 17 | 18 | Step 3: 19 | Enjoy your newly customized icon! 20 | 21 | For more thorough directions, see Apple's website at: 22 | http://www.apple.com/support/mac101/customize/6/ 23 | -------------------------------------------------------------------------------- /src/ui/Dialogs.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "MuiCore.h" 4 | #include 5 | 6 | class Dialog : public mui::Container{ 7 | public: 8 | Dialog(); 9 | virtual ~Dialog(); 10 | 11 | void layout() override; 12 | void draw() override; 13 | 14 | void show(); 15 | void close(); 16 | 17 | mui::Label * addLabel(const std::string & text); 18 | mui::Button * addButton(const std::string & text, const std::function & on_choice); 19 | private: 20 | void buttonPressed(const void * sender, ofTouchEventArgs & args); 21 | 22 | mui::Label * label; 23 | std::vector buttons; 24 | std::vector labels; 25 | mui::Container * blocker; 26 | }; 27 | 28 | Dialog * show_yes_no_dialog(const std::string & message, const std::function & on_choice); 29 | Dialog * show_ok_dialog(const std::string & message, const std::function & on_choice); 30 | -------------------------------------------------------------------------------- /assets/wix_config.wxi: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /openFrameworks-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleIconFile 6 | icon-mac.icns 7 | CFBundleDevelopmentRegion 8 | English 9 | CFBundleExecutable 10 | ${EXECUTABLE_NAME} 11 | CFBundleIdentifier 12 | org.sd.oscilloscope 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundlePackageType 16 | APPL 17 | CFBundleSignature 18 | ???? 19 | CFBundleVersion 20 | 1.1.0 21 | LSApplicationCategoryType 22 | public.app-category.utilities 23 | NSHighResolutionCapable 24 | 25 | NSMicrophoneUsageDescription 26 | This app can display your microphone input as XY graph. 27 | NSServices 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "addons/ofxMightyUI"] 2 | path = addons/ofxMightyUI 3 | url = https://github.com/kritzikratzi/ofxMightyUI 4 | [submodule "addons/ofxAvCodec"] 5 | path = addons/ofxAvCodec 6 | url = https://github.com/kritzikratzi/ofxAvCodec 7 | [submodule "addons/ofxFontAwesome"] 8 | path = addons/ofxFontAwesome 9 | url = https://github.com/kritzikratzi/ofxFontAwesome 10 | [submodule "addons/ofxFontStash2"] 11 | path = addons/ofxFontStash2 12 | url = https://github.com/kritzikratzi/ofxFontStash2 13 | [submodule "addons/ofxNative"] 14 | path = addons/ofxNative 15 | url = https://github.com/kritzikratzi/ofxNative.git 16 | [submodule "addons/ofxSpout"] 17 | path = addons/ofxSpout 18 | url = https://github.com/elliotwoods/ofxSpout.git 19 | [submodule "addons/ofxSyphon"] 20 | path = addons/ofxSyphon 21 | url = https://github.com/astellato/ofxSyphon.git 22 | [submodule "addons/ofxLibsamplerate"] 23 | path = addons/ofxLibsamplerate 24 | url = https://github.com/kritzikratzi/ofxLibsamplerate.git 25 | [submodule "addons/ofxLiblaserdock"] 26 | path = addons/ofxLiblaserdock 27 | url = https://github.com/kritzikratzi/ofxLiblaserdock.git 28 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 hansi raber 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/util/TexShare.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // SharedTex.cpp 3 | // Oscilloscope 4 | // 5 | // Created by Hansi on 27/06/19. 6 | // 7 | // 8 | 9 | #include "TexShare.h" 10 | #include "ofMain.h" 11 | 12 | #ifdef TARGET_OSX 13 | #include "ofxSyphon.h" 14 | class TexShareImpl{ 15 | public: 16 | ofxSyphonServer server; 17 | 18 | void setup(string name){ 19 | server.setName(name); 20 | } 21 | 22 | void update(ofTexture &tex){ 23 | server.publishTexture(&tex); 24 | } 25 | }; 26 | 27 | #elif defined TARGET_WIN32 28 | #include "ofxSpout.h" 29 | class TexShareImpl{ 30 | public: 31 | ofxSpout::Sender spoutSender; 32 | 33 | void setup(string name){ 34 | spoutSender.init(name); 35 | } 36 | 37 | void update(ofTexture &tex){ 38 | spoutSender.send(tex); 39 | } 40 | }; 41 | #else 42 | class TexShareImpl{ 43 | public: 44 | void setup(string name){} 45 | void update(ofTexture & tex){}; 46 | }; 47 | #endif 48 | 49 | TexShare::TexShare(){ 50 | impl = make_unique(); 51 | } 52 | 53 | TexShare::~TexShare() = default; 54 | 55 | void TexShare::setup(string name){ 56 | impl->setup(name); 57 | } 58 | 59 | void TexShare::update(ofTexture &tex){ 60 | impl->update(tex); 61 | } 62 | -------------------------------------------------------------------------------- /src/OsciMesh.h: -------------------------------------------------------------------------------- 1 | // 2 | // OsciMesh.hpp 3 | // Oscilloscope 4 | // 5 | // Created by Hansi on 12.01.17. 6 | // 7 | // 8 | 9 | #ifndef OsciMesh_hpp 10 | #define OsciMesh_hpp 11 | 12 | #include "ofMain.h" 13 | #include "util/ShaderLoader.h" 14 | 15 | class OsciMesh{ 16 | public: 17 | OsciMesh(); 18 | 19 | static void init(); 20 | 21 | // adds a lot of lines. 22 | // left: x coordinates (ranged -1..1) 23 | // right: y coordinates (ranged -1..1) 24 | // zMod: brightness control (ranged 0..1), nullable 25 | // stride: stride for left and right (doesn't apply to bright!) 26 | void addLines( float * left, float * right, float * bright, int N, int stride); 27 | 28 | // adds a line from a to b (xy = -1..1), with the brightness bright (0..1) 29 | inline void addLine( ofVec2f a, ofVec2f b, const float bright ); 30 | 31 | void draw(ofMatrix4x4 & viewMatrix); 32 | void clear(); 33 | 34 | // shader parameters 35 | float uSize; 36 | ofVec3f uRgb; 37 | float uIntensity; 38 | float uIntensityBase; 39 | float uHue; 40 | 41 | // it's a mesh. can you believe it? 42 | ofMesh mesh; 43 | 44 | private: 45 | ShaderLoader shaderLoader; 46 | ofShader shader; 47 | ofVec2f last; 48 | }; 49 | 50 | #endif /* OsciMesh_hpp */ 51 | -------------------------------------------------------------------------------- /assets/wix_heat.xslt: -------------------------------------------------------------------------------- 1 | 2 | 3 | 11 | 12 | 18 | 19 | 20 | 21 | 22 | yes 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | *** DO NOT EDIT: Generated by heat.exe; transformed by wix_heat.xsl 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /bin/data/shaders/osci.geom: -------------------------------------------------------------------------------- 1 | #version 120 2 | #extension GL_EXT_geometry_shader4 : enable 3 | #define EPS 1E-6 4 | 5 | varying vec3 texcoord; 6 | varying vec2 pos; 7 | uniform float uSize; 8 | uniform mat4 uMatrix; 9 | 10 | void main() { 11 | mat4 tmatrix = uMatrix; 12 | vec2 p0 = (gl_PositionIn[0]).xy; 13 | vec2 p1 = (gl_PositionIn[1]).xy; 14 | vec2 dir = p1 - p0; 15 | texcoord.z = length(dir); 16 | 17 | if (texcoord.z > EPS) { 18 | dir = dir / texcoord.z; 19 | } else { 20 | dir = vec2(1.0, 0.0); 21 | } 22 | 23 | vec2 norm = vec2(-dir.y, dir.x); 24 | 25 | dir *= uSize; 26 | norm *= uSize; 27 | 28 | texcoord.xy = vec2(-uSize, -uSize); 29 | gl_Position = tmatrix * vec4(p0 - dir - norm, 0.0, 1.0); 30 | pos = p0; 31 | EmitVertex(); 32 | 33 | texcoord.xy = vec2(-uSize, uSize); 34 | gl_Position = tmatrix * vec4(p0 - dir + norm, 0.0, 1.0); 35 | EmitVertex(); 36 | 37 | texcoord.xy = vec2(texcoord.z + uSize, -uSize); 38 | gl_Position = tmatrix * vec4(p1 + dir - norm, 0.0, 1.0); 39 | EmitVertex(); 40 | 41 | texcoord.xy = vec2(texcoord.z + uSize, uSize); 42 | gl_Position = tmatrix * vec4(p1 + dir + norm, 0.0, 1.0); 43 | EmitVertex(); 44 | } 45 | -------------------------------------------------------------------------------- /scripts/functions.sh: -------------------------------------------------------------------------------- 1 | 2 | function readGlobal(){ 3 | var=$(cat src/global_config.h | sed -e "s/#define $1 \(.*\)\$/\\1/" -e 't' -e 'd' | sed "s/\"//g") 4 | [ -z "${var}" ] && var="0" 5 | echo $var 6 | return 0 7 | } 8 | 9 | function promptWithDefault(){ 10 | read -p "$1 [$2]: " var 11 | [ -z "${var}" ] && var="$2" 12 | echo "$var" 13 | return 0 14 | } 15 | 16 | function promptYesNo(){ 17 | read -p "$1 [y/N] " -n 1 -r 18 | if [[ $REPLY =~ ^[Yy]$ ]] 19 | then 20 | echo 21 | return 0 22 | elif [[ $REPLY = "" ]] 23 | then 24 | return 1 25 | else 26 | echo 27 | return 1 28 | fi 29 | } 30 | 31 | function copyDataFiles(){ 32 | dest=$1 33 | shift 34 | items=($@) 35 | for file in ${items[@]} 36 | do 37 | echo "- bin/data/$file -> $dest" 38 | cp -r bin/data/$file "$dest" 39 | done 40 | } 41 | 42 | function getOrCreateWixCode(){ 43 | version="$1" 44 | var="" 45 | if [[ -f "assets/wix_db.txt" ]] 46 | then 47 | var=$(cat assets/wix_db.txt | sed -e "s|$1=\(.*\)\$|\\1|" -e 't' -e 'd') 48 | fi 49 | 50 | if [ -z "${var}" ] 51 | then 52 | var=$(uuidgen) 53 | addWixCode "$version" "$var" 54 | fi 55 | echo $var 56 | return 0 57 | } 58 | 59 | function addWixCode(){ 60 | version="$1" 61 | code="$2" 62 | 63 | echo "$1=$2" >>assets/wix_db.txt 64 | return 0; 65 | } -------------------------------------------------------------------------------- /src/ui/FaToggleButton.h: -------------------------------------------------------------------------------- 1 | // 2 | // FAButton.h 3 | // OsciStudio 4 | // 5 | // Created by Hansi on 04.04.15. 6 | // 7 | // 20.12.2018: added optional fontName argument. this makes it easy to use with multiple versions of fontawesome 8 | 9 | 10 | #ifndef FaToggleButton_h 11 | #define FaToggleButton_h 12 | 13 | #include "ofxMightyUI.h" 14 | #include "ofMain.h" 15 | 16 | class FaToggleButton : public mui::ToggleButton{ 17 | public: 18 | FaToggleButton( string icon, string selectedIcon, float x = 0, float y = 0, float width = 100, float height = 20, const string & fontName = "fontawesome-webfont.ttf" ) : 19 | mui::ToggleButton(icon, x, y, width, height ), wasSelected(false){ 20 | this->icon = icon; 21 | this->selectedIcon = selectedIcon; 22 | this->label->fontName = fontName; 23 | this->label->commit(); 24 | this->fg = ofColor(255); 25 | 26 | ofAddListener( onPress, this, &FaToggleButton::onButtonPressed ); 27 | } 28 | 29 | string icon; 30 | string selectedIcon; 31 | 32 | bool wasSelected; 33 | 34 | void commit(){ 35 | if( wasSelected != selected ){ 36 | wasSelected = selected; 37 | label->text = selected? selectedIcon:icon; 38 | label->commit(); 39 | } 40 | } 41 | 42 | private: 43 | void onButtonPressed( const void * sender, ofTouchEventArgs &touch ){ 44 | commit(); 45 | } 46 | }; 47 | #endif 48 | -------------------------------------------------------------------------------- /bin/data/shaders/osci.frag: -------------------------------------------------------------------------------- 1 | #version 120 2 | #define EPS 1E-6 3 | #define TAU 6.283185307179586 4 | #define TAUR 2.5066282746310002 5 | #define SQRT2 1.4142135623730951 6 | uniform float uSize; 7 | uniform float uIntensity; 8 | uniform float uHue; 9 | uniform vec3 uRgb; 10 | uniform float uIntensityBase; 11 | varying vec4 color; 12 | varying float brightness; 13 | 14 | float erf(float x) { 15 | float s = sign(x), a = abs(x); 16 | x = 1.0 + (0.278393 + (0.230389 + (0.000972 + 0.078108 * a) * a) * a) * a; 17 | x *= x; 18 | return s - s / (x * x); 19 | } 20 | 21 | void main (void) 22 | { 23 | float len = color.z; // we pass in length ... 24 | vec2 xy = color.xy; // and xy through color 25 | float alpha; 26 | 27 | float sigma = uSize/(2.0+2.0*1000.0*uSize/50.0); 28 | /* if (len < EPS && ) { 29 | // If the beam segment is too short, just calculate intensity at the position. 30 | alpha = exp(-len*len/(2.0*sigma*sigma))/2.0/sqrt(uSize); 31 | alpha = 0.0; 32 | } else {*/ 33 | // Otherwise, use analytical integral for accumulated intensity. 34 | alpha = erf(xy.x/SQRT2/sigma) - erf((xy.x-len)/SQRT2/sigma); 35 | alpha *= exp(-xy.y*xy.y/(2.0*sigma*sigma))/2.0/len*uSize; 36 | // } 37 | 38 | alpha = pow(alpha,1.0-uIntensityBase)*(0.01+min(0.99,uIntensity*3.0)); 39 | gl_FragColor = vec4(uRgb, alpha*brightness); 40 | 41 | } 42 | -------------------------------------------------------------------------------- /src/util/WickedLasers.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ofxMightyUI.h" 4 | #include "util/Audio.h" 5 | #include "samplerate.h" 6 | #include "OsciMesh.h" 7 | 8 | class CircleBuffer; 9 | class LaserdockDevice; 10 | struct LaserdockSample; 11 | 12 | 13 | class WickedLasers { 14 | public: 15 | WickedLasers(); 16 | virtual ~WickedLasers(); 17 | 18 | void addBuffer(float* buffer, int bufferSize, int nChannels, int sampleRate); 19 | void die(); 20 | 21 | int bufferSize; 22 | MonoSample left; 23 | MonoSample right; 24 | 25 | float lx, ly; 26 | float s; 27 | 28 | void connect(); 29 | void disconnect(); 30 | bool isConnected(); 31 | void resetBuffers(); 32 | 33 | private: 34 | 35 | void processIncomming(); 36 | void laser_fill_samples(LaserdockSample* samples, const uint32_t count, float* left, float* right); 37 | void of_update(ofEventArgs& args); 38 | void of_exit(ofEventArgs& args); 39 | ofVec3f last; 40 | 41 | float intensity = 1.0; 42 | bool invertX = false; 43 | bool invertY = false; 44 | bool flipXY = false; 45 | 46 | shared_ptr laserDevice; 47 | LaserdockSample* laserSamples; // we leak this 48 | mutex laserDeviceMutex; 49 | 50 | int visualSampleRate = 60000; 51 | vector targetBuffer; 52 | 53 | thread resampleThread; 54 | MonoSample incomming; 55 | static const int chunkSize = 1024; 56 | int sampleRate = 44100; 57 | 58 | SRC_STATE* resampleState; 59 | SRC_DATA resampleData; 60 | 61 | bool connected = false; 62 | bool shouldResetBuffers = false; 63 | bool exiting = false; 64 | }; 65 | -------------------------------------------------------------------------------- /src/ui/ExportScreen.h: -------------------------------------------------------------------------------- 1 | // 2 | // ExportScreen.hpp 3 | // Oscilloscope 4 | // 5 | // Created by Hansi on 29.05.18. 6 | // 7 | // 8 | 9 | #ifndef ExportScreen_hpp 10 | #define ExportScreen_hpp 11 | 12 | #include "ofMain.h" 13 | #include "MuiCore.h" 14 | 15 | class ofxAvVideoWriter; 16 | 17 | enum class ExportFormat; 18 | 19 | struct ExportFileInfo{ 20 | ofFile file; 21 | bool exists; 22 | std::string error; 23 | int sampleRate; 24 | ExportFormat format; 25 | }; 26 | 27 | class ExportScreen : public mui::Container{ 28 | public: 29 | ExportScreen(); 30 | ~ExportScreen(); 31 | 32 | void show(const ofFile & file); 33 | void layout() override; 34 | 35 | void commit(); 36 | 37 | const std::filesystem::path getFile(); 38 | const ExportFileInfo getFileInfo(); 39 | ExportFormat getFormat(); 40 | private: 41 | 42 | void buttonPressed(const void * sender, ofTouchEventArgs & args ); 43 | void beginExport(); 44 | 45 | mui::Container * view; 46 | 47 | mui::Label * filePickerLabel; 48 | mui::Label * formatSelectLabel; 49 | mui::Label * sizeLabel; 50 | mui::Label * sizeXLabel; 51 | mui::Label * sizeAtLabel; 52 | mui::Label * sizeFpsLabel; 53 | 54 | mui::TextArea * widthText; 55 | mui::TextArea * heightText; 56 | mui::TextArea * fpsText; 57 | 58 | mui::SegmentedSelect * formatSelect; 59 | 60 | shared_ptr writer; 61 | mui::FilePicker * filePicker; 62 | mui::Button * exportButton; 63 | mui::Button * cancelButton; 64 | mui::Button * resetButton; 65 | 66 | string defaultName; 67 | }; 68 | 69 | 70 | 71 | #endif /* ExportScreen_hpp */ 72 | -------------------------------------------------------------------------------- /src/ui/ConfigView.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ofxMightyUI.h" 4 | #include "FMenu.h" 5 | 6 | class ConfigView : public mui::Container{ 7 | public: 8 | ConfigView(); 9 | 10 | void update() override; 11 | void draw() override; 12 | void layout() override; 13 | 14 | void touchDown( ofTouchEventArgs &touch ) override; 15 | void touchMoved( ofTouchEventArgs &touch ) override; 16 | void touchUp( ofTouchEventArgs &touch ) override; 17 | void touchDoubleTap( ofTouchEventArgs &touch ) override; 18 | 19 | 20 | FDropdown * outDevicePicker; 21 | mui::Label * emulationLabel; 22 | mui::SegmentedSelect * emulationMode; 23 | 24 | mui::Label* laserConnectLabel; 25 | mui::Button* laserConnect; 26 | mui::Label* laserSizeLabel; 27 | mui::SliderWithLabel* laserSize; 28 | mui::Label* laserIntensityLabel; 29 | mui::SliderWithLabel* laserIntensity; 30 | mui::Label* laserOffsetLabel; 31 | mui::SliderWithLabel* laserOffsetX; 32 | mui::SliderWithLabel* laserOffsetY; 33 | mui::Label* laserKeystoneLabel; 34 | mui::SliderWithLabel* laserKeystoneX; 35 | mui::SliderWithLabel* laserKeystoneY; 36 | 37 | void fromGlobals(); 38 | void toGlobals(); 39 | 40 | void buttonPressed( const void * sender, ofTouchEventArgs & args ); 41 | void emulationModeChanged(const void * sender, int & value); 42 | 43 | private: 44 | void pushLabel( string text ); 45 | void outDevicePickerChanged(const void * sender, string & value); 46 | void gotMessage(const void * sender, ofMessage & msg); 47 | void addDeviceOptions(); 48 | 49 | bool showLaserConfig{ false }; 50 | vector hiddenLaserUi; 51 | }; 52 | -------------------------------------------------------------------------------- /assets/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "16x16", 5 | "idiom" : "mac", 6 | "filename" : "appicon-16.png", 7 | "scale" : "1x" 8 | }, 9 | { 10 | "size" : "16x16", 11 | "idiom" : "mac", 12 | "filename" : "appicon-32.png", 13 | "scale" : "2x" 14 | }, 15 | { 16 | "size" : "32x32", 17 | "idiom" : "mac", 18 | "filename" : "appicon-32.png", 19 | "scale" : "1x" 20 | }, 21 | { 22 | "size" : "32x32", 23 | "idiom" : "mac", 24 | "filename" : "appicon-64.png", 25 | "scale" : "2x" 26 | }, 27 | { 28 | "size" : "128x128", 29 | "idiom" : "mac", 30 | "filename" : "appicon-128.png", 31 | "scale" : "1x" 32 | }, 33 | { 34 | "size" : "128x128", 35 | "idiom" : "mac", 36 | "filename" : "appicon-256.png", 37 | "scale" : "2x" 38 | }, 39 | { 40 | "size" : "256x256", 41 | "idiom" : "mac", 42 | "filename" : "appicon-256.png", 43 | "scale" : "1x" 44 | }, 45 | { 46 | "size" : "256x256", 47 | "idiom" : "mac", 48 | "filename" : "appicon-512.png", 49 | "scale" : "2x" 50 | }, 51 | { 52 | "size" : "512x512", 53 | "idiom" : "mac", 54 | "filename" : "appicon-512.png", 55 | "scale" : "1x" 56 | }, 57 | { 58 | "size" : "512x512", 59 | "idiom" : "mac", 60 | "filename" : "appicon-1024.png", 61 | "scale" : "2x" 62 | } 63 | ], 64 | "info" : { 65 | "version" : 1, 66 | "author" : "xcode" 67 | } 68 | } -------------------------------------------------------------------------------- /src/util/OsciVideoWriter.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // OsciVideoWriter.hpp 3 | // Oscilloscope 4 | // 5 | // Created by Hansi on 06.06.18. 6 | // 7 | // 8 | // 9 | 10 | /// \brief Class to write video (in sync, so it's very slow!) 11 | 12 | #ifndef OsciVideoWriter_hpp 13 | #define OsciVideoWriter_hpp 14 | 15 | #include 16 | #include "ofPixels.h" 17 | 18 | struct AVFormatContext; 19 | struct AVOutputFormat; 20 | struct AVStream; 21 | struct AVFrame; 22 | struct AVPacket; 23 | struct SwsContext; 24 | 25 | class OsciVideoWriter{ 26 | public: 27 | 28 | struct WorkData{ 29 | 30 | AVFormatContext* out_ctx = nullptr; 31 | AVOutputFormat* out_fmt = nullptr; 32 | AVStream* out_video_st = nullptr; 33 | AVStream* out_audio_st = nullptr; 34 | 35 | // temp audio buffers 36 | uint8_t out_audio_buffer[32 * 2048 * 8] = { 0 }; 37 | size_t out_audio_buffer_offset = 0; 38 | 39 | // number of written audio frames 40 | int64_t audio_pts = 0; 41 | int64_t audio_pts_pkt = 0; 42 | 43 | // temp video buffers 44 | SwsContext* sws_ctx; 45 | AVFrame* in_frame = nullptr; 46 | AVFrame* out_frame = nullptr; 47 | 48 | // number of written video frames 49 | int64_t video_frame_num = 0; 50 | }; 51 | 52 | struct OutputConfig{ 53 | int video_framerate; 54 | int video_width; 55 | int video_height; 56 | 57 | int audio_sample_rate; 58 | int audio_n_channels; 59 | }; 60 | 61 | OsciVideoWriter(); 62 | ~OsciVideoWriter(); 63 | 64 | /// \brief Adds the video file. Returns true on success 65 | bool open(std::string outputFile, const OutputConfig & config); 66 | 67 | /// \brief Adds a video frame from pixels. If the pixel size doesn't match, it fails. 68 | void addVideoFrame(const ofPixels & pixels); 69 | 70 | /// \brief Adds interleaved samples 71 | void addAudioFrame(float * samples, int numSamples); 72 | 73 | /// \brief Closes the file. Always call this, lots of file info must be written at the end. 74 | void close(); 75 | 76 | bool isOpen(); 77 | 78 | 79 | private: 80 | OutputConfig config; 81 | bool is_open = false; 82 | 83 | WorkData wd; 84 | }; 85 | 86 | #endif /* OsciVideoWriter_hpp */ 87 | -------------------------------------------------------------------------------- /Oscilloscope.sln: -------------------------------------------------------------------------------- 1 | Microsoft Visual Studio Solution File, Format Version 12.00 2 | # Visual Studio 15 3 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Oscilloscope", "Oscilloscope.vcxproj", "{7FD42DF7-442E-479A-BA76-D0022F99702A}" 4 | EndProject 5 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "openframeworksLib", "..\..\..\libs\openFrameworksCompiled\project\vs\openframeworksLib.vcxproj", "{5837595D-ACA9-485C-8E76-729040CE4B0B}" 6 | EndProject 7 | Global 8 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 9 | Debug|Win32 = Debug|Win32 10 | Debug|x64 = Debug|x64 11 | Release|Win32 = Release|Win32 12 | Release|x64 = Release|x64 13 | EndGlobalSection 14 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 15 | {7FD42DF7-442E-479A-BA76-D0022F99702A}.Debug|Win32.ActiveCfg = Debug|Win32 16 | {7FD42DF7-442E-479A-BA76-D0022F99702A}.Debug|Win32.Build.0 = Debug|Win32 17 | {7FD42DF7-442E-479A-BA76-D0022F99702A}.Debug|x64.ActiveCfg = Debug|x64 18 | {7FD42DF7-442E-479A-BA76-D0022F99702A}.Debug|x64.Build.0 = Debug|x64 19 | {7FD42DF7-442E-479A-BA76-D0022F99702A}.Release|Win32.ActiveCfg = Release|Win32 20 | {7FD42DF7-442E-479A-BA76-D0022F99702A}.Release|Win32.Build.0 = Release|Win32 21 | {7FD42DF7-442E-479A-BA76-D0022F99702A}.Release|x64.ActiveCfg = Release|x64 22 | {7FD42DF7-442E-479A-BA76-D0022F99702A}.Release|x64.Build.0 = Release|x64 23 | {5837595D-ACA9-485C-8E76-729040CE4B0B}.Debug|Win32.ActiveCfg = Debug|Win32 24 | {5837595D-ACA9-485C-8E76-729040CE4B0B}.Debug|Win32.Build.0 = Debug|Win32 25 | {5837595D-ACA9-485C-8E76-729040CE4B0B}.Debug|x64.ActiveCfg = Debug|x64 26 | {5837595D-ACA9-485C-8E76-729040CE4B0B}.Debug|x64.Build.0 = Debug|x64 27 | {5837595D-ACA9-485C-8E76-729040CE4B0B}.Release|Win32.ActiveCfg = Release|Win32 28 | {5837595D-ACA9-485C-8E76-729040CE4B0B}.Release|Win32.Build.0 = Release|Win32 29 | {5837595D-ACA9-485C-8E76-729040CE4B0B}.Release|x64.ActiveCfg = Release|x64 30 | {5837595D-ACA9-485C-8E76-729040CE4B0B}.Release|x64.Build.0 = Release|x64 31 | EndGlobalSection 32 | GlobalSection(SolutionProperties) = preSolution 33 | HideSolutionNode = FALSE 34 | EndGlobalSection 35 | EndGlobal 36 | -------------------------------------------------------------------------------- /scripts/prepare.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | # copies required libs/files to the bin/data folder. 3 | # it is suggested that you clean up first! 4 | 5 | pushd `dirname $0` 6 | echo "----------------------------" 7 | cd .. 8 | platform=$1 9 | 10 | if [ "$platform" == "" ]; then 11 | echo "Usage: scripts/prepare.sh " 12 | echo "" 13 | echo "Platform: One of the following: " 14 | echo " linux, linux64, win32, win64" 15 | elif [[ "$platform" == "osx" ]]; then 16 | echo XCode-build manages it all. Done! 17 | echo "----------------------------" 18 | elif [[ "$platform" == "linux" ]]; then 19 | echo "Linux (32bit)" 20 | echo "----------------------------" 21 | mkdir bin/libs 22 | echo Copying avcodec libs ... 23 | cp -R addons/ofxAvCodec/libs/avcodec/lib/linux/* bin/libs/ 24 | echo Copying mightyUI data ... 25 | cp -R addons/ofxMightyUI/bin/data/* bin/data/ 26 | echo Copying fontawsome data ... 27 | cp -R addons/ofxFontAwesome/bin/data/* bin/data/ 28 | elif [[ "$platform" == "linux64" ]]; then 29 | echo "Linux (64 bit)" 30 | echo "----------------------------" 31 | echo Copying avcodec libs ... 32 | mkdir bin/libs 33 | cp -R addons/ofxAvCodec/libs/avcodec/lib/linux64/* bin/libs/ 34 | echo Copying mightyUI data ... 35 | cp -R addons/ofxMightyUI/bin/data/* bin/data/ 36 | echo Copying fontawsome data ... 37 | cp -R addons/ofxFontAwesome/bin/data/* bin/data/ 38 | elif [[ "$platform" == "win32" ]]; then 39 | echo "Windows (32bit)" 40 | echo "----------------------------" 41 | echo Copying avcodec libs ... 42 | cp -R addons/ofxAvCodec/libs/avcodec/lib/vs/Win32/*.dll bin/ 43 | echo Copying mightyUI data ... 44 | cp -R addons/ofxMightyUI/bin/data/* bin/data/ 45 | echo Copying fontawsome data ... 46 | cp -R addons/ofxFontAwesome/bin/data/* bin/data/ 47 | elif [[ "$platform" == "win64" ]]; then 48 | echo "Windows (64bit)" 49 | echo "----------------------------" 50 | echo Copying avcodec libs ... 51 | cp -R addons/ofxAvCodec/libs/avcodec/lib/vs/x64/*.dll bin/ 52 | echo Copying mightyUI data ... 53 | cp -R addons/ofxMightyUI/bin/data/* bin/data/ 54 | echo Copying fontawsome data ... 55 | cp -R addons/ofxFontAwesome/bin/data/* bin/data/ 56 | else 57 | echo Unsupported platform: $platform 58 | fi 59 | 60 | popd -------------------------------------------------------------------------------- /scripts/osx-notarize.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # notarizes and zip a signed app 3 | # run this in the folder where your app sits! 4 | # otherwise you end up with things in weird places 5 | appFolder="$1" 6 | bundleId="$2" 7 | teamId="$3" 8 | ascProvider="$4" 9 | username="$5" 10 | password="$6" 11 | zipDest="$7" 12 | 13 | if [[ -z "$appFolder" || -z "$bundleId" || -z "$username" || -z "$password" || -z "$zipDest" || -z "$teamId" ]] 14 | then 15 | echo "Usage: $0 " 16 | exit 17 | fi 18 | 19 | appFolderName=$(basename "$appFolder") 20 | appDest="$distDir/$appFolderName" 21 | appName=${appFolderName%.app} 22 | me="$(dirname $0)" 23 | 24 | echo "Zipping it up..." 25 | if [ -f "$zipDest" ] 26 | then 27 | rm "$zipDest" 28 | fi 29 | ditto -c -k --keepParent "$appName.app" "$zipDest" 30 | 31 | echo "Uploading for notarization..." 32 | echo xcrun altool -asc-provider $ascProvider --team-id $teamId --notarize-app --primary-bundle-id "$bundleId" --username "$username" --password "$password" --file "$zipDest" 33 | uuid="$(xcrun altool -asc-provider $ascProvider --team-id $teamId --notarize-app --primary-bundle-id "$bundleId" --username "$username" --password "$password" --file "$zipDest" 2>&1 | grep RequestUUID | cut -d " " -f 3)" 34 | 35 | if [ -z "$uuid" ] 36 | then 37 | echo "Got no uuid ($uuid) as output of altool, exiting" 38 | exit 1 39 | else 40 | echo "Got uuid $uuid from altool" 41 | fi 42 | 43 | while true 44 | do 45 | output="$(xcrun altool --team-id $teamId --notarization-info "$uuid" -u "$username" -p "$password" 2>&1)" 46 | res=$(echo "$output" | grep "Status Message" | xargs | cut -d " " -f 3-99) 47 | if [ -z "$res" ] 48 | then 49 | echo " > waiting for notarization..." 50 | else 51 | if [ "$res" == "Package Approved" ] 52 | then 53 | echo " > Package check ok!" 54 | break 55 | else 56 | url=$(echo "$output" | grep "LogFileURL" | xargs | cut -d " " -f 2-99) 57 | curl $url 58 | echo " > Package not ok, got \"$output\"" 59 | exit 1 60 | fi 61 | fi 62 | done 63 | 64 | echo "Deleting zip" 65 | rm "$zipDest" 66 | echo "Running stapler on the app" 67 | xcrun stapler staple "$appName.app" 68 | echo "Recreating final zip" 69 | ditto -c -k --keepParent "$appName.app" "$zipDest" 70 | 71 | 72 | 73 | 74 | -------------------------------------------------------------------------------- /src/util/ShaderLoader.h: -------------------------------------------------------------------------------- 1 | // 2 | // ShaderLoader.h 3 | // Oscilloscope 4 | // 5 | // Created by Hansi on 21.08.15. 6 | // 7 | // 8 | 9 | #ifndef Oscilloscope_ShaderLoader_h 10 | #define Oscilloscope_ShaderLoader_h 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | #include 19 | #include "ofMain.h" 20 | #include "../globals.h" 21 | 22 | class ShaderLoader{ 23 | string fragFile; 24 | string vertFile; 25 | string geomFile; 26 | ofShader * shader; 27 | 28 | long fragTime = 0; 29 | long vertTime; 30 | long geomTime; 31 | 32 | 33 | public: 34 | 35 | ShaderLoader(){ 36 | 37 | } 38 | 39 | void setup( ofShader * shader, string baseName ){ 40 | this->shader = shader; 41 | fragFile = ofxToReadonlyDataPath(baseName + ".frag"); 42 | vertFile = ofxToReadonlyDataPath(baseName + ".vert"); 43 | geomFile = ofxToReadonlyDataPath(baseName + ".geom"); 44 | 45 | ofAddListener( ofEvents().update, this, &ShaderLoader::of_update, OF_EVENT_ORDER_BEFORE_APP ); 46 | ofAddListener( ofEvents().draw, this, &ShaderLoader::of_draw, OF_EVENT_ORDER_AFTER_APP ); 47 | } 48 | 49 | ~ShaderLoader(){ 50 | ofRemoveListener( ofEvents().update, this, &ShaderLoader::of_update, OF_EVENT_ORDER_BEFORE_APP ); 51 | ofRemoveListener( ofEvents().draw, this, &ShaderLoader::of_draw, OF_EVENT_ORDER_AFTER_APP ); 52 | } 53 | 54 | void of_update( ofEventArgs &args ){ 55 | if( ofGetFrameNum() % 50 == 0 || fragTime == 0){ 56 | time_t fragTimeNow = mtime(fragFile); 57 | time_t vertTimeNow = mtime(vertFile); 58 | time_t geomTimeNow = mtime(geomFile); 59 | if( fragTimeNow != fragTime || vertTimeNow != vertTime || geomTimeNow != geomTime ){ 60 | cout << "Reload ... " << endl; 61 | if( shader->isLoaded() ) shader->unload(); 62 | shader->load(vertFile, fragFile/*, geomFile*/); // don't use geometry shaders because intelhd3000? 63 | } 64 | 65 | fragTime = fragTimeNow; 66 | vertTime = vertTimeNow; 67 | geomTime = geomTimeNow; 68 | } 69 | } 70 | 71 | 72 | void of_draw( ofEventArgs &args ){ 73 | // TODO: 74 | // draw in case of compilation error! 75 | } 76 | 77 | 78 | 79 | 80 | 81 | // http://stackoverflow.com/a/10446821/347508 82 | static time_t mtime(string path) { 83 | struct stat attr; 84 | stat(path.c_str(), &attr); 85 | time_t res = attr.st_mtime; 86 | return res; 87 | } 88 | }; 89 | 90 | 91 | #endif 92 | -------------------------------------------------------------------------------- /src/ui/Playlist.h: -------------------------------------------------------------------------------- 1 | // 2 | // Playlist.hpp 3 | // Oscilloscope 4 | // 5 | // Created by Hansi on 05.08.17. 6 | // 7 | // 8 | 9 | #ifndef Playlist_hpp 10 | #define Playlist_hpp 11 | 12 | #include "ofxMightyUI.h" 13 | 14 | class PlaylistItem; 15 | class FaButton; 16 | class FaToggleButton; 17 | 18 | struct PlaylistItemRef{ 19 | PlaylistItemRef(){} 20 | PlaylistItemRef(size_t id, string filename) : id(id), filename(filename){} 21 | size_t id{0}; 22 | string filename{""}; 23 | }; 24 | 25 | class Playlist : public mui::Container{ 26 | public: 27 | Playlist(); 28 | ~Playlist(); 29 | 30 | void draw() override; 31 | void update() override; 32 | void layout() override; 33 | bool fileDragged(ofDragInfo & args) override; 34 | bool keyPressed(ofKeyEventArgs & args) override; 35 | 36 | PlaylistItemRef addFile(ofFile file, double duration = -2 ); 37 | void removeAllFiles(); 38 | 39 | void save(ostream & out); 40 | void load(istream & in); 41 | 42 | 43 | // finds the next item in the playlist 44 | // if id=0, the first item is returned. 45 | // returns: {0,""} if there is no further item, otherwise returns the thing you want. 46 | PlaylistItemRef getNextItemInPlaylist(size_t id); 47 | string getItemPath(size_t id); 48 | 49 | enum class LoopMode { all_once, all_repeat, one_repeat }; 50 | 51 | private: 52 | PlaylistItemRef getNextItem(size_t id); 53 | 54 | void setLoopMode(LoopMode mode); 55 | void buttonPressed(const void * sender, ofTouchEventArgs & args); 56 | 57 | mui::ScrollPane * scroller; 58 | bool checkNewFiles = false; 59 | size_t nextItemId = 1; 60 | map filenames; 61 | 62 | FaButton * loopModeButton; 63 | FaToggleButton * shuffleToggle; 64 | FaToggleButton * onlyOneButton; 65 | 66 | FaButton * clearButton; 67 | FaButton * addFileButton; 68 | }; 69 | 70 | 71 | class PlaylistItem : public mui::Label{ 72 | public: 73 | PlaylistItem(size_t itemId, ofFile file, double duration = -2); 74 | 75 | void touchDown(ofTouchEventArgs & args) override; 76 | void touchUp(ofTouchEventArgs & args) override; 77 | void touchUpOutside(ofTouchEventArgs & args) override; 78 | void mouseEnter(ofMouseEventArgs &args) override; 79 | void mouseExit(ofMouseEventArgs &args) override; 80 | void drawBackground() override; 81 | 82 | 83 | void updateDuration(bool & alreadyScanned, bool & shouldRemove ); 84 | 85 | size_t itemId; 86 | bool selected = false; 87 | bool hovering = false; 88 | ofFile file; 89 | double duration = -2; // -2 = didn't look, -1 = error, > 0 is okay 90 | }; 91 | 92 | #endif /* Playlist_hpp */ 93 | -------------------------------------------------------------------------------- /src/ofxIniSettings/ofxIniExtras.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "ofMain.h" 3 | 4 | // this is basically https://github.com/companje/ofxExtras 5 | // with lots things deleted. 6 | void ofxExit(string error ); 7 | bool ofxFileExists(string filename); 8 | bool ofxStringEndsWith(string str, string key); 9 | string ofxFormatString(string format, int number); 10 | string ofxFormatString(string format, string s); 11 | string ofxReplaceString(string input, string replace, string by); 12 | void ofxSaveString(string filename, string str); 13 | void ofxSaveStrings(string filename, vector lines); 14 | string ofxTrimStringRight(string str); 15 | string ofxTrimStringLeft(string str); 16 | string ofxTrimString(string str); 17 | string ofxStringBeforeFirst(string str, string key); 18 | string ofxStringAfterFirst(string str, string key); 19 | string ofxStringAfterLast(string str, string key); 20 | string ofxStringBeforeLast(string str, string key); 21 | bool ofxContains(vector keys, string key); 22 | float ofxDist(float ax, float ay, float az, float bx, float by, float bz); 23 | bool ofxColorMatch(ofColor a, ofColor b, int tolerance); 24 | void ofxScale(float scale); 25 | void ofxSetHexColor(int hexColor, int a); //alpha between 0..255 26 | void ofxSetColor(ofColor c); 27 | void ofxSetColorHSB(int h, int s, int b, int a); 28 | bool ofxToBoolean(string str); //rick 3-1-2008 29 | bool ofxToBoolean(float f); 30 | int ofxToInteger(string str); 31 | string ofxToString(char ch); 32 | string ofxToString(unsigned char ch); 33 | string ofxToString(string str); 34 | string ofxToString(float f); 35 | string ofxToString(bool value); 36 | string ofxToString(int value); 37 | string ofxToString(ofRectangle v); 38 | ofColor ofxToColor(int hexColor); 39 | ofColor ofxToColor(unsigned char r, unsigned char g, unsigned char b); 40 | ofColor ofxToColor(ofVec4f v); 41 | ofColor ofxToColor(ofVec3f v, int alpha); 42 | string ofxToHexString(int value, int digits=6); 43 | int ofxToInteger(ofColor c); 44 | string ofxToString(ofQuaternion q); 45 | ofQuaternion ofxToQuaternion(string str); 46 | string ofxToHex(char c); 47 | void ofxRotate(ofVec3f v); 48 | void ofxRotate(ofQuaternion q); 49 | void ofxRotate(float angle, ofVec3f v); 50 | void ofxTranslate(ofVec3f v); 51 | void ofxScale(ofVec3f v); 52 | ofVec2f ofxToVec2f(string str); 53 | ofVec3f ofxToVec3f(string str); 54 | ofVec3f ofxToVec3f(float *a); 55 | ofVec4f ofxToVec4f(string str); 56 | ofRectangle ofxToRectangle(ofVec4f v); 57 | ofRectangle ofxToRectangle(string str); 58 | string ofxToString(ofVec2f v); 59 | string ofxToString(ofVec3f v, int precision); 60 | string ofxToString(ofVec4f v); 61 | string ofxToString(ofMatrix4x4 m); 62 | ofMatrix4x4 ofxToMatrix4x4(string s); 63 | vector ofxToFloatVector(string s, string delimiter); 64 | -------------------------------------------------------------------------------- /assets/wix_main.wxs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 9 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 1 56 | 1 61 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /icon.rc: -------------------------------------------------------------------------------- 1 | // Microsoft Visual C++ generated resource script. 2 | // 3 | #include 4 | #include "resource.h" 5 | ///////////////////////////////////////////////////////////////////////////// 6 | // English (United States) resources 7 | 8 | #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) 9 | LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US 10 | #pragma code_page(1252) 11 | 12 | ///////////////////////////////////////////////////////////////////////////// 13 | // 14 | // Icon 15 | // 16 | 17 | // Icon with lowest ID value placed first to ensure application icon 18 | // remains consistent on all systems. 19 | MAIN_ICON ICON "icon.ico" 20 | 21 | 22 | #ifdef APSTUDIO_INVOKED 23 | ///////////////////////////////////////////////////////////////////////////// 24 | // 25 | // TEXTINCLUDE 26 | // 27 | 28 | 1 TEXTINCLUDE 29 | BEGIN 30 | "resource.h\0" 31 | END 32 | 33 | 2 TEXTINCLUDE 34 | BEGIN 35 | "\0" 36 | END 37 | 38 | 3 TEXTINCLUDE 39 | BEGIN 40 | "\r\n" 41 | "\0" 42 | END 43 | 44 | #endif // APSTUDIO_INVOKED 45 | 46 | 47 | ///////////////////////////////////////////////////////////////////////////// 48 | // 49 | // Version 50 | // 51 | 52 | VS_VERSION_INFO VERSIONINFO 53 | FILEVERSION 1,1,0,0 54 | PRODUCTVERSION 1,1,0,0 55 | FILEFLAGSMASK 0x3fL 56 | #ifdef _DEBUG 57 | FILEFLAGS 0x1L 58 | #else 59 | FILEFLAGS 0x0L 60 | #endif 61 | FILEOS 0x40004L 62 | FILETYPE 0x1L 63 | FILESUBTYPE 0x0L 64 | BEGIN 65 | BLOCK "StringFileInfo" 66 | BEGIN 67 | BLOCK "000904b0" 68 | BEGIN 69 | VALUE "CompanyName", "Hansi Raber" 70 | VALUE "FileDescription", "Oscilloscope" 71 | VALUE "FileVersion", "1.1.0" 72 | VALUE "InternalName", "Oscilloscope.exe" 73 | VALUE "LegalCopyright", "Copyleft 2020, https://github.com/kritzikratzi/Oscilloscope" 74 | VALUE "OriginalFilename", "Oscilloscope.exe" 75 | VALUE "ProductName", "Oscilloscope" 76 | VALUE "ProductVersion", "1.1.0" 77 | END 78 | END 79 | BLOCK "VarFileInfo" 80 | BEGIN 81 | VALUE "Translation", 0x9, 1200 82 | END 83 | END 84 | 85 | #endif // English (United States) resources 86 | ///////////////////////////////////////////////////////////////////////////// 87 | 88 | 89 | 90 | #ifndef APSTUDIO_INVOKED 91 | ///////////////////////////////////////////////////////////////////////////// 92 | // 93 | // Generated from the TEXTINCLUDE 3 resource. 94 | // 95 | 96 | 97 | ///////////////////////////////////////////////////////////////////////////// 98 | #endif // not APSTUDIO_INVOKED 99 | 100 | -------------------------------------------------------------------------------- /src/globals.h: -------------------------------------------------------------------------------- 1 | // 2 | // globals.h 3 | // Oscilloscope 4 | // 5 | // Created by Hansi on 26.07.15. 6 | // 7 | // 8 | 9 | #ifndef __Oscilloscope__globals__ 10 | #define __Oscilloscope__globals__ 11 | 12 | #include 13 | #include "OsciAvAudioPlayer.h" 14 | #include "ofxIniSettings.h" 15 | 16 | extern string ofxToReadWriteableDataPath( string filename ); 17 | extern string ofxToReadonlyDataPath( string filename ); 18 | extern void setWindowRepresentedFilename( string filename ); 19 | 20 | string ofxFormatTime(double seconds); 21 | 22 | enum class ExportFormat{H264=1,IMAGE_SEQUENCE_PNG=2,IMAGE_SEQUENCE_TIFF=3}; 23 | class WickedLasers; 24 | struct ma_context; 25 | 26 | #define globals (Globals::instance) 27 | class Globals{ 28 | public: 29 | Globals(){}; 30 | void init(); 31 | 32 | struct AudioConfig { 33 | string name; 34 | int bufferSize; 35 | int sampleRate; 36 | }; 37 | 38 | ma_context * context; 39 | 40 | // audio settings 41 | AudioConfig out_requested{ "",0, 0 }; 42 | AudioConfig out_actual{ "",512, 44100 }; 43 | 44 | bool micActive{ false }; 45 | AudioConfig in_requested{ "",0, 0 }; 46 | AudioConfig in_actual{ "",512, 44100 }; 47 | 48 | // display settings 49 | float scale{1.0}; 50 | bool invertX{false}; 51 | bool invertY{false}; 52 | bool flipXY{false}; 53 | bool zModulation{true}; 54 | 55 | float strokeWeight{10}; // 1...20 56 | float timeStretch{1}; // 0.1-2.0 57 | float blur{30}; // 0...255 58 | float intensity{0.4f}; // 0...1 59 | float afterglow{0.5f}; // 0...1 60 | int analogMode{0}; // 0=digital, 1=analog, 2=superanalog 61 | 62 | int numPts{20}; // 1...+inf? 63 | float hue{50}; // 0...360 64 | 65 | float outputVolume{1}; 66 | float inputVolume{1}; 67 | 68 | int exportWidth{1920}; 69 | int exportHeight{1080}; 70 | int exportFrameRate{60}; 71 | int exportSampleRate{96000}; 72 | ExportFormat exportFormat{ExportFormat::IMAGE_SEQUENCE_PNG}; 73 | 74 | float secondsBeforeHidingMenu{0.5}; 75 | 76 | bool alwaysOnTop{false}; 77 | 78 | // laser stuff. none of this is ever stored! 79 | shared_ptr laserPtr{nullptr}; 80 | bool laserConnected{ false }; 81 | float laserSize{ 0.5 }; 82 | float laserIntensity{ 0.0 }; 83 | float laserKeystoneX{ 0.0 }; 84 | float laserKeystoneY{ 0.0 }; 85 | float laserOffsetX{ 0.0 }; 86 | float laserOffsetY{ 0.0 }; 87 | 88 | void loadFromFile(string settingsFile = ofxToReadWriteableDataPath("settings.txt")); 89 | void saveToFile(string settingsFile = ofxToReadWriteableDataPath("settings.txt")); 90 | 91 | // runtime variables (not saved) 92 | OsciAvAudioPlayer player; 93 | size_t currentlyPlayingItem = 0; 94 | 95 | // the singleton thing 96 | static Globals instance; 97 | }; 98 | 99 | 100 | #endif /* defined(__Oscilloscope__globals__) */ 101 | -------------------------------------------------------------------------------- /src/OsciMesh.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // OsciMesh.cpp 3 | // Oscilloscope 4 | // 5 | // Created by Hansi on 12.01.17. 6 | // 7 | // 8 | 9 | #define EPS 1E-6 10 | 11 | #include "OsciMesh.h" 12 | 13 | void OsciMesh::init(){ 14 | } 15 | 16 | OsciMesh::OsciMesh(){ 17 | shaderLoader.setup(&shader, "shaders/osci"); 18 | } 19 | 20 | void OsciMesh::addLines( float * left, float * right, float * bright, int N, int stride ){ 21 | // no work? go home watch tv or something 22 | if(N==0) return; 23 | 24 | addLine(last,{left[0],right[0]}, bright==nullptr?1:bright[0]); 25 | last = {left[N-stride],right[N-stride]}; 26 | 27 | if(bright==nullptr){ 28 | for( int i = stride; i < N; i+= stride ){ 29 | ofVec2f p0(left[i-stride], right[i-stride]); 30 | ofVec2f p1(left[i ], right[i ]); 31 | addLine(p0,p1, 1); 32 | } 33 | } 34 | else{ 35 | for( int i = stride; i < N; i+= stride ){ 36 | ofVec2f p0(left[i-stride], right[i-stride]); 37 | ofVec2f p1(left[i ], right[i ]); 38 | addLine(p0,p1, bright[i]); 39 | } 40 | } 41 | } 42 | 43 | inline void OsciMesh::addLine(ofVec2f p0, ofVec2f p1, const float bright_){ 44 | float bright = bright_*2-1; 45 | ofVec2f dir = p1 - p0; 46 | float z = dir.length(); 47 | if (z > EPS) dir /= z; 48 | else dir = ofVec2f(1.0, 0.0); 49 | 50 | dir *= uSize; 51 | ofVec2f norm(-dir.y, dir.x); 52 | ofVec2f xy(-uSize, -uSize); 53 | 54 | //make vec3 from vec2+float 55 | const auto vec3 = [](const ofVec2f & xy, const float & z){ return ofVec3f(xy.x,xy.y,z); }; 56 | 57 | mesh.addVertex(vec3(p0-dir-norm, bright)); 58 | mesh.addColor(ofFloatColor(-uSize, -uSize, z)); 59 | 60 | mesh.addVertex(vec3(p0-dir+norm, bright)); 61 | mesh.addColor(ofFloatColor(-uSize, uSize, z)); 62 | 63 | mesh.addVertex(vec3(p1+dir-norm, bright)); 64 | mesh.addColor(ofFloatColor(z+uSize, -uSize, z)); 65 | 66 | 67 | mesh.addVertex(vec3(p0-dir+norm, bright)); 68 | mesh.addColor(ofFloatColor(-uSize, uSize, z)); 69 | 70 | mesh.addVertex(vec3(p1+dir-norm, bright)); 71 | mesh.addColor(ofFloatColor(z+uSize, -uSize, z)); 72 | 73 | mesh.addVertex(vec3(p1+dir+norm, bright)); 74 | mesh.addColor(ofFloatColor(z+uSize, +uSize, z)); 75 | }; 76 | 77 | 78 | void OsciMesh::draw(ofMatrix4x4 & viewMatrix){ 79 | glEnable(GL_BLEND); 80 | glBlendFunc(GL_SRC_ALPHA, GL_ONE); 81 | shader.begin(); 82 | shader.setUniform3f("uRgb", uRgb); 83 | shader.setUniform1f("uSize", uSize); 84 | shader.setUniform1f("uIntensity", uIntensity); 85 | shader.setUniform1f("uIntensityBase", uIntensityBase); 86 | shader.setUniformMatrix4f("uMatrix", viewMatrix); 87 | shader.setUniform1f("uHue", uHue ); 88 | ofSetColor(255); 89 | mesh.draw(); 90 | shader.end(); 91 | ofEnableAlphaBlending(); 92 | } 93 | 94 | 95 | void OsciMesh::clear(){ 96 | mesh.clear(); 97 | mesh.setMode(OF_PRIMITIVE_TRIANGLES); 98 | mesh.enableColors(); 99 | } 100 | -------------------------------------------------------------------------------- /src/ui/PlayerOverlay.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ofxMightyUI.h" 4 | #include "../globals.h" 5 | #include "FaButton.h" 6 | #include "FaToggleButton.h" 7 | #include "FMenu.h" 8 | #include "../util/miniaudio.h" 9 | 10 | class PlayerOverlay : public mui::Container{ 11 | public: 12 | PlayerOverlay( float x_ = 0, float y_ = 0, float width_ = ofGetWidth()/mui::MuiConfig::scaleFactor, float height_ = ofGetHeight()/mui::MuiConfig::scaleFactor ); 13 | 14 | virtual void fromGlobals(); 15 | 16 | virtual void update(); 17 | virtual void draw(); 18 | virtual void layout(); 19 | 20 | virtual void touchDown( ofTouchEventArgs &touch ); 21 | virtual void touchMoved( ofTouchEventArgs &touch ); 22 | virtual void touchUp( ofTouchEventArgs &touch ); 23 | virtual void touchDoubleTap( ofTouchEventArgs &touch ); 24 | 25 | void populateMicMenu(FMenu * menu); 26 | 27 | FaButton * loadFileButton; 28 | FaToggleButton * useMicButton; 29 | 30 | FaToggleButton * configButton; 31 | mui::SliderWithLabel * scaleSlider; 32 | 33 | mui::Label * filenameLabel; 34 | FaToggleButton * fullscreenToggle; // toggle fs 35 | FaToggleButton * flipXYToggle; // flip x with y axis 36 | FaToggleButton * invertXToggle; // mirror around x axis 37 | FaToggleButton * invertYToggle; // mirror around y axis 38 | FaToggleButton * sideBySideToggle; // for 3d: toggle side by side mode and anagylph3d mode 39 | FaToggleButton * flip3dToggle; // for 3d: swap left and right channels 40 | FaToggleButton * zModulationToggle; // enable variable brightness control in 3 channel files 41 | FaToggleButton * showPlaylistToggle; // show playlist 42 | 43 | FaToggleButton * playButton; 44 | mui::Slider * timeSlider; 45 | mui::Button * timeLabelButton; 46 | int timeLabelMode = 0; 47 | 48 | mui::Label currentTime; 49 | mui::Label * scaleLabel; 50 | 51 | mui::Label * outputVolumeLabel; 52 | mui::SliderWithLabel * outputVolumeSlider; 53 | 54 | mui::SliderWithLabel * strokeWeightSlider; 55 | mui::Label * strokeWeightLabel; 56 | 57 | mui::SliderWithLabel * timeStretchSlider; 58 | mui::Label * timeStretchLabel; 59 | 60 | mui::SliderWithLabel * blurSlider; 61 | mui::Label * blurLabel; 62 | 63 | mui::SliderWithLabel * numPtsSlider; 64 | mui::Label * numPtsLabel; 65 | 66 | mui::SliderWithLabel * hueSlider; 67 | mui::Label * hueLabel; 68 | 69 | mui::SliderWithLabel * intensitySlider; 70 | mui::Label * intensityLabel; 71 | 72 | mui::SliderWithLabel * afterglowSlider; 73 | mui::Label * afterglowLabel; 74 | 75 | mui::Button * updateButton; 76 | 77 | void buttonPressed(const void * sender, ofTouchEventArgs & args); 78 | void inputSelected(const void * sender, FMenu::Option & opt); 79 | void sliderChanged( const void * sender, float & value ); 80 | 81 | struct mic_info{ 82 | ma_device_info info; 83 | ma_device_type type; 84 | }; 85 | mic_info getSelectedMicDeviceInfo(); 86 | private: 87 | mui::Label * addLabel( string text ); 88 | mic_info selectedMicDeviceInfo; 89 | }; 90 | -------------------------------------------------------------------------------- /src/ofApp.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "util/miniaudio.h" 4 | 5 | #include "ofMain.h" 6 | #include "util/ShaderLoader.h" 7 | #include "ofxMightyUI.h" 8 | 9 | #include "ui/ConfigView.h" 10 | #include "ui/PlayerOverlay.h" 11 | #include "ui/Playlist.h" 12 | #include "util/Audio.h" 13 | #include "ofxAvAudioPlayer.h" 14 | #include "OsciMesh.h" 15 | #include "util/TexShare.h" 16 | #include "util/OsciVideoWriter.hpp" 17 | 18 | class ExportScreen; 19 | enum class ExportFormat; 20 | 21 | 22 | class ofApp : public ofBaseApp{ 23 | 24 | public: 25 | 26 | void setup(); 27 | void startApplication(); 28 | void stopApplication(); 29 | void update(); 30 | void draw(); 31 | void drawAbove(); 32 | void exit(); 33 | 34 | void keyPressed (int key); 35 | void keyReleased(int key); 36 | void mouseMoved(int x, int y ); 37 | void mouseDragged(int x, int y, int button); 38 | void mousePressed(int x, int y, int button); 39 | void mouseReleased(int x, int y, int button); 40 | void windowResized(int w, int h); 41 | void dragEvent(ofDragInfo dragInfo); 42 | void gotMessage(ofMessage msg); 43 | 44 | void audioIn(float * input, int bufferSize, int nChannels); 45 | void audioOut( float * output, int bufferSize, int nChannels ); 46 | 47 | void beginExport(const ofFile & file); 48 | void playlistItemEnded(); 49 | void updateSampleRate(); 50 | 51 | void startMic(); 52 | void stopMic(); 53 | ofMatrix4x4 getViewMatrix(int i, bool isQuad); 54 | 55 | void urlResponse(ofHttpResponse & response); 56 | 57 | 58 | mui::Root * root; 59 | ConfigView * configView; 60 | ExportScreen * exportScreen; 61 | 62 | PlayerOverlay * playerOverlay; 63 | Playlist * playlist; 64 | bool playlistEnable = false; 65 | OsciMesh mesh; 66 | OsciMesh mesh2; // for stereoscopic viewing 67 | 68 | ofFbo fbo; 69 | TexShare texSender; 70 | 71 | // storage for mic buffers 72 | int micChannels = 2; 73 | MonoSample micLeft; 74 | MonoSample micRight; 75 | MonoSample micZMod; 76 | 77 | ma_device_config playDeviceConfig; 78 | ma_device playDevice; 79 | 80 | ma_device_config micDeviceConfig; 81 | ma_device micDevice; 82 | 83 | bool changed; 84 | bool clearFbos; 85 | int dropped; 86 | bool showInfo; 87 | 88 | int exporting; 89 | int exportFrameNum; 90 | ExportFormat exportFormat; 91 | int exportSampleRate; 92 | string exportExt; 93 | string exportDir; 94 | 95 | uint64_t lastMouseMoved{0}; 96 | uint64_t lastUpdateTime{0}; 97 | ofVec2f mousePosBeforeHiding; 98 | bool forceHidden = false; 99 | string fileToLoad; 100 | string currentFilename{"Oscilloscope"}; 101 | string nextWindowTitle; 102 | 103 | ofVec2f last; 104 | bool hadWindowFocus = true; 105 | bool applicationRunning = false; 106 | bool initComplete = false; 107 | ofxFontStashStyle tooltipStyle; 108 | 109 | mutex mainThreadMutex; 110 | queue> mainThreadTasks; 111 | 112 | OsciVideoWriter video_writer; 113 | }; 114 | -------------------------------------------------------------------------------- /scripts/osx-sign.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | realpath() { 3 | OURPWD=$PWD 4 | cd "$(dirname "$1")" 5 | LINK=$(readlink "$(basename "$1")") 6 | while [ "$LINK" ]; do 7 | cd "$(dirname "$LINK")" 8 | LINK=$(readlink "$(basename "$1")") 9 | done 10 | REALPATH="$PWD/$(basename "$1")" 11 | cd "$OURPWD" 12 | echo "$REALPATH" 13 | } 14 | 15 | 16 | app="$1" 17 | signingIdentity="$2" 18 | entitlements="$3" 19 | 20 | if [[ -z "$1" || -z "$2" || -z "$3" ]] 21 | then 22 | echo "Usage: $0 " 23 | exit 24 | fi 25 | 26 | app="$1" 27 | signingIdentity="$2" 28 | entitlements="$3" 29 | me=$(dirname $0) 30 | 31 | # you might want extra_options="--options=runtime" 32 | # to sign an older binary which needs to be notarized 33 | #extra_options="--options=runtime --entitlements $entitlements " 34 | extra_options="--options=runtime --entitlements $entitlements " 35 | 36 | 37 | echo "Clearing strange file attributes" 38 | xattr -cr "$app" 39 | 40 | signdir() { 41 | pluginName=$1 42 | echo "Signing $app/$pluginName" 43 | # sign bundled jre 44 | find "$app/$pluginName" -type f -print | sort -r \ 45 | | ( while read FOO; do 46 | codesign -d "$FOO" 47 | if [ $? != 0 ]; then 48 | sudo codesign $extra_options -f -s "$signingIdentity" -vvvv "$FOO" 49 | fi 50 | done) 51 | # Sign most other files 52 | find "$app" -type f -print | sort -r \ 53 | | grep -v '_CodeSignature' \ 54 | | (while read FOO; do 55 | codesign -d "$FOO" 56 | if [ $? != 0 ]; then 57 | echo "Signing: $FOO" 58 | sudo codesign $extra_options -f -s "$signingIdentity" -vvvv "$FOO" 2>&1 59 | fi 60 | done) 61 | # Sanity check, this doesn't sign anything, because everything is signed 62 | find "$app/$pluginName" -type f -print | sort -r \ 63 | | ( while read FOO; do 64 | codesign -v "$FOO" 65 | if [ $? != 0 ]; then 66 | echo "Checking: $FOO" 67 | sudo codesign $extra_options -f -s "$signingIdentity" -vvvv "$FOO" 2>&1 68 | fi 69 | done) 70 | # Test sig 71 | codesign -dvvv "$app/$pluginName" 72 | # Next sign Java directory (must not use --force, as plist is modified) 73 | # This creates $app/Contents/Plugins/Java/Contents/_CodeSignature/{CodeDirectory,CodeRequirements,CodeResources,CodeSignature} 74 | sudo codesign -f -s "$signingIdentity" -vvvv "$app/$pluginName" 2>&1 75 | sudo codesign -f -s "$signingIdentity" "$app/$pluginName/Contents/_CodeSignature/CodeResources" 76 | # sign the new files 77 | find "$app/$pluginName" -type f -print | sort -r \ 78 | | ( while read FOO; do 79 | codesign -v "$FOO" 80 | if [ $? != 0 ]; then 81 | sudo codesign $extra_options -s "$signingIdentity" -vvvv "$FOO" 2>&1 82 | fi 83 | done) 84 | } 85 | 86 | find "$app" -name "*.dylib" -type f -print | sort -r \ 87 | | ( while read FOO; do 88 | echo "sign dylib: $FOO" 89 | sudo codesign $extra_options -f -s "$signingIdentity" -vvvv "$FOO" 90 | done) 91 | 92 | # finally sign $app 93 | sudo codesign $extra_options -s "$signingIdentity" -vvvv --force "$app" 94 | # Now the verification works 95 | codesign -vvvv --deep "$app" -------------------------------------------------------------------------------- /Oscilloscope.qbs: -------------------------------------------------------------------------------- 1 | import qbs 2 | import qbs.Process 3 | import qbs.File 4 | import qbs.FileInfo 5 | import qbs.TextFile 6 | import "../../../libs/openFrameworksCompiled/project/qtcreator/ofApp.qbs" as ofApp 7 | 8 | Project{ 9 | property string of_root: '../../..' 10 | 11 | ofApp { 12 | name: { return FileInfo.baseName(sourceDirectory) } 13 | 14 | files: [ 15 | 'src/**', 16 | ] 17 | 18 | // This project is using addons.make to include the addons 19 | // since it was imported from old code. To change it to include 20 | // the addons from the qbs file change the following lines to 21 | // the list of used addons in array format. eg: 22 | // 23 | of.addons: [ 24 | 'addons/ofxAvCodec', 25 | 'addons/ofxFontAwesome', 26 | 'addons/ofxFontStash2', 27 | 'addons/ofxMightyUI', 28 | 'addons/ofxNative', 29 | 'addons/ofxSyphon', 30 | 'addons/ofxSpout', 31 | 'addons/ofxLibsamplerate', 32 | ] 33 | 34 | // additional flags for the project. the of module sets some 35 | // flags by default to add the core libraries, search paths... 36 | // this flags can be augmented through the following properties: 37 | of.pkgConfigs: [] // list of additional system pkgs to include 38 | of.includePaths: [] // include search paths 39 | of.cFlags: [] // flags passed to the c compiler 40 | of.cxxFlags: [] // flags passed to the c++ compiler 41 | of.linkerFlags: [] // flags passed to the linker 42 | of.defines: [] // defines are passed as -D to the compiler 43 | // and can be checked with #ifdef or #if in the code 44 | of.frameworks: [] // osx only, additional frameworks to link with the project 45 | of.staticLibraries: [] // static libraries 46 | of.dynamicLibraries: [] // dynamic libraries 47 | 48 | // create a console window when the application start 49 | consoleApplication: false 50 | 51 | // other flags can be set through the cpp module: http://doc.qt.io/qbs/cpp-module.html 52 | // eg: this will enable ccache when compiling 53 | // 54 | // cpp.compilerWrapper: 'ccache' 55 | 56 | Depends{ 57 | name: "cpp" 58 | } 59 | 60 | // common rules that parse the include search paths, core libraries... 61 | Depends{ 62 | name: "of" 63 | } 64 | 65 | // dependency with the OF library 66 | Depends{ 67 | name: "openFrameworks" 68 | } 69 | } 70 | 71 | property bool makeOF: true // use makfiles to compile the OF library 72 | // will compile OF only once for all your projects 73 | // otherwise compiled per project with qbs 74 | 75 | property bool precompileOfMain: false // precompile ofMain.h 76 | // faster to recompile when including ofMain.h 77 | // but might use a lot of space per project 78 | 79 | references: [FileInfo.joinPaths(of_root, "/libs/openFrameworksCompiled/project/qtcreator/openFrameworks.qbs")] 80 | } 81 | -------------------------------------------------------------------------------- /src/ui/Dialogs.cpp: -------------------------------------------------------------------------------- 1 | #include "ofxMightyUI.h" 2 | #include "Dialogs.h" 3 | #include "MuiL.h" 4 | 5 | Dialog::Dialog() : mui::Container(0,0,400,100){ 6 | blocker = new mui::Container(); 7 | blocker->onLayout.add([&](){ 8 | blocker->x = 0; 9 | blocker->y = 0; 10 | blocker->width = blocker->parent->width; 11 | blocker->height = blocker->parent->height; 12 | }); 13 | blocker->bg = ofColor(0,200); 14 | blocker->opaque = true; 15 | 16 | bg = ofColor(0); 17 | opaque = true; 18 | } 19 | 20 | Dialog::~Dialog(){ 21 | if(blocker) MUI_ROOT->safeRemoveAndDelete(blocker); 22 | 23 | for(mui::Container * btn : buttons){ 24 | delete btn; 25 | } 26 | for(mui::Container * lbl : labels){ 27 | delete lbl; 28 | } 29 | 30 | buttons.clear(); 31 | labels.clear(); 32 | 33 | children.clear(); 34 | } 35 | 36 | void Dialog::layout(){ 37 | mui::L(labels).rows({10,10}).stretchToRightEdgeOfParent(10); 38 | 39 | float btn_y0 = 20 + (labels.size() == 0? 0:labels.back()->getBounds().getBottom()); 40 | 41 | mui::L(buttons).columns({10,btn_y0}); 42 | 43 | height = getChildBounds().getBottom() + 10; 44 | 45 | if(parent){ 46 | x = (parent->width - width)/2; 47 | y = (parent->height - height)/2; 48 | } 49 | } 50 | 51 | void Dialog::draw(){ 52 | ofNoFill(); 53 | ofDrawRectangle(0,0,width-1,height-1); 54 | ofFill(); 55 | } 56 | 57 | void Dialog::show(){ 58 | MUI_ROOT->add(blocker); 59 | blocker->handleLayout(); 60 | 61 | MUI_ROOT->add(this); 62 | layout(); 63 | } 64 | 65 | void Dialog::close(){ 66 | blocker->visible = false; 67 | MUI_ROOT->safeRemoveAndDelete(blocker); 68 | blocker = nullptr; 69 | 70 | visible = false; 71 | MUI_ROOT->safeRemoveAndDelete(this); 72 | } 73 | 74 | mui::Label * Dialog::addLabel(const std::string & text){ 75 | mui::Label * label = new mui::Label(text,0,0,380,20); 76 | add(label); 77 | labels.push_back(label); 78 | return label; 79 | } 80 | 81 | mui::Button * Dialog::addButton(const std::string & text, const std::function & on_choice){ 82 | mui::Button * button = new mui::Button(text,0,0,90,30); 83 | button->setProperty("on_choice", on_choice); 84 | ofAddListener(button->onPress, this, &Dialog::buttonPressed); 85 | add(button); 86 | buttons.push_back(button); 87 | return button; 88 | } 89 | 90 | void Dialog::buttonPressed(const void * sender, ofTouchEventArgs & args){ 91 | for(mui::Container * btn : buttons){ 92 | if(btn == sender){ 93 | std::function * func = btn->getProperty>("on_choice"); 94 | close(); 95 | if(func && *func) (*func)(); 96 | } 97 | } 98 | } 99 | 100 | 101 | Dialog * show_yes_no_dialog(const std::string & message, const std::function& on_choice){ 102 | Dialog * d = new Dialog(); 103 | d->addLabel(message); 104 | d->addButton("Yes", [on_choice](){ on_choice(true); }); 105 | d->addButton("No", [on_choice](){ on_choice(false); }); 106 | d->show(); 107 | return d; 108 | } 109 | 110 | Dialog * show_ok_dialog(const std::string & message, const std::function& on_choice){ 111 | Dialog * d = new Dialog(); 112 | d->addLabel(message); 113 | d->addButton("Ok", [on_choice](){ on_choice(); }); 114 | d->show(); 115 | return d; 116 | } 117 | -------------------------------------------------------------------------------- /oscilloscope.xcodeproj/xcshareddata/xcschemes/oscilloscope Debug.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 51 | 52 | 58 | 59 | 60 | 61 | 62 | 63 | 69 | 70 | 76 | 77 | 78 | 79 | 81 | 82 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /oscilloscope.xcodeproj/xcshareddata/xcschemes/oscilloscope Release.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 51 | 52 | 58 | 59 | 60 | 61 | 62 | 63 | 69 | 70 | 76 | 77 | 78 | 79 | 81 | 82 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | dist/ 2 | scripts/osx-config.sh 3 | ._* 4 | .DS_Store 5 | Thumbs.db 6 | .vs/ 7 | oscilloscope.VC.db 8 | 9 | # Created by https://www.gitignore.io 10 | 11 | ### Xcode ### 12 | build/ 13 | *.pbxuser 14 | !default.pbxuser 15 | *.mode1v3 16 | !default.mode1v3 17 | *.mode2v3 18 | !default.mode2v3 19 | *.perspectivev3 20 | !default.perspectivev3 21 | xcuserdata 22 | *.xccheckout 23 | *.moved-aside 24 | DerivedData 25 | *.xcuserstate 26 | 27 | 28 | ### VisualStudio ### 29 | ## Ignore Visual Studio temporary files, build results, and 30 | ## files generated by popular Visual Studio add-ons. 31 | 32 | # User-specific files 33 | *.suo 34 | *.user 35 | *.sln.docstates 36 | 37 | # Build results 38 | [Dd]ebug/ 39 | [Dd]ebugPublic/ 40 | [Rr]elease/ 41 | [Rr]eleases/ 42 | x64/ 43 | x86/ 44 | build/ 45 | bld/ 46 | [Bb]in/ 47 | [Oo]bj/ 48 | 49 | # Roslyn cache directories 50 | *.ide/ 51 | 52 | # MSTest test Results 53 | [Tt]est[Rr]esult*/ 54 | [Bb]uild[Ll]og.* 55 | 56 | #NUNIT 57 | *.VisualState.xml 58 | TestResult.xml 59 | 60 | # Build Results of an ATL Project 61 | [Dd]ebugPS/ 62 | [Rr]eleasePS/ 63 | dlldata.c 64 | 65 | *_i.c 66 | *_p.c 67 | *_i.h 68 | *.ilk 69 | *.meta 70 | *.obj 71 | *.pch 72 | *.pdb 73 | *.pgc 74 | *.pgd 75 | *.rsp 76 | *.sbr 77 | *.tlb 78 | *.tli 79 | *.tlh 80 | *.tmp 81 | *.tmp_proj 82 | *.log 83 | *.vspscc 84 | *.vssscc 85 | .builds 86 | *.pidb 87 | *.svclog 88 | *.scc 89 | 90 | # Chutzpah Test files 91 | _Chutzpah* 92 | 93 | # Visual C++ cache files 94 | ipch/ 95 | *.aps 96 | *.ncb 97 | *.opensdf 98 | *.sdf 99 | *.cachefile 100 | 101 | # Visual Studio profiler 102 | *.psess 103 | *.vsp 104 | *.vspx 105 | 106 | # TFS 2012 Local Workspace 107 | $tf/ 108 | 109 | # Guidance Automation Toolkit 110 | *.gpState 111 | 112 | # ReSharper is a .NET coding add-in 113 | _ReSharper*/ 114 | *.[Rr]e[Ss]harper 115 | *.DotSettings.user 116 | 117 | # JustCode is a .NET coding addin-in 118 | .JustCode 119 | 120 | # TeamCity is a build add-in 121 | _TeamCity* 122 | 123 | # DotCover is a Code Coverage Tool 124 | *.dotCover 125 | 126 | # NCrunch 127 | _NCrunch_* 128 | .*crunch*.local.xml 129 | 130 | # MightyMoose 131 | *.mm.* 132 | AutoTest.Net/ 133 | 134 | # Web workbench (sass) 135 | .sass-cache/ 136 | 137 | # Installshield output folder 138 | [Ee]xpress/ 139 | 140 | # DocProject is a documentation generator add-in 141 | DocProject/buildhelp/ 142 | DocProject/Help/*.HxT 143 | DocProject/Help/*.HxC 144 | DocProject/Help/*.hhc 145 | DocProject/Help/*.hhk 146 | DocProject/Help/*.hhp 147 | DocProject/Help/Html2 148 | DocProject/Help/html 149 | 150 | # Click-Once directory 151 | publish/ 152 | 153 | # Publish Web Output 154 | *.[Pp]ublish.xml 155 | *.azurePubxml 156 | # TODO: Comment the next line if you want to checkin your web deploy settings 157 | # but database connection strings (with potential passwords) will be unencrypted 158 | *.pubxml 159 | *.publishproj 160 | 161 | # NuGet Packages 162 | *.nupkg 163 | # The packages folder can be ignored because of Package Restore 164 | **/packages/* 165 | # except build/, which is used as an MSBuild target. 166 | !**/packages/build/ 167 | # If using the old MSBuild-Integrated Package Restore, uncomment this: 168 | #!**/packages/repositories.config 169 | 170 | # Windows Azure Build Output 171 | csx/ 172 | *.build.csdef 173 | 174 | # Windows Store app package directory 175 | AppPackages/ 176 | 177 | # Others 178 | sql/ 179 | *.Cache 180 | ClientBin/ 181 | [Ss]tyle[Cc]op.* 182 | ~$* 183 | *~ 184 | *.dbmdl 185 | *.dbproj.schemaview 186 | *.pfx 187 | *.publishsettings 188 | node_modules/ 189 | 190 | # RIA/Silverlight projects 191 | Generated_Code/ 192 | 193 | # Backup & report files from converting an old project file 194 | # to a newer Visual Studio version. Backup files are not needed, 195 | # because we have git ;-) 196 | _UpgradeReport_Files/ 197 | Backup*/ 198 | UpgradeLog*.XML 199 | UpgradeLog*.htm 200 | 201 | # SQL Server files 202 | *.mdf 203 | *.ldf 204 | 205 | # Business Intelligence projects 206 | *.rdl.data 207 | *.bim.layout 208 | *.bim_*.settings 209 | 210 | # Microsoft Fakes 211 | FakesAssemblies/ 212 | 213 | # SubWolf 2015-07-29 Settings Not Needed 214 | bin/data/settings.txt 215 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | Oscilloscope 2 | === 3 | 4 | A software oscilloscope attempting to mimic the aesthetic of old school ray oscilloscopes. 5 | 6 | 7 | 8 | # How to use 9 | 10 | After starting the oscilloscope a welcome message is already loaded, press ▶︎ play to make sure your audio setup works. If it doesn't, open ⚙ settings and try to choose another output device. 11 | 12 | To open files you can either click the folder icon, or drag a file from Explorer/Finder/Nautilus/... to the application. 13 | 14 | 15 | |Key |Action| 16 | |------|------| 17 | |Space |Play/Pause| 18 | |f |Fullscreen| 19 | |Tab |Hide interface| 20 | |e |Export to image sequence| 21 | 22 | 23 | 24 | For more information 25 | 26 | * either visit the user page at oscilloscopemusic.com/osci.php 27 | * [download the latest version](https://github.com/kritzikratzi/Oscilloscope/releases) 28 | 29 | 30 | # Programmer Documentation 31 | 32 | ## Project setup 33 | 34 | Things are moving around a bit sometimes. 35 | Make sure to read these instructions before each build. 36 | 37 | 1. Download and unzip Openframeworks 0.10.1 38 | 1. Open the folder apps/myApps/ (in the OpenFrameworks folder) 39 | 1. Clone the repository with submodules: `git clone --recursive https://github.com/kritzikratzi/Oscilloscope.git` 40 | 1. Download the binary release for ofxAvCodec from [https://github.com/kritzikratzi/ofxAvCodec/releases/tag/0.2](https://github.com/kritzikratzi/ofxAvCodec/releases/tag/0.2) 41 | 1. Replace the addons/ofxAvCodec/libs with the libs folder from the download 42 | 43 | 44 | ### Compiling with XCode (OSX11.5+) 45 | 46 | 1. Add the `--deep` value to the `Other Code Signing Flags` key in the Build Settings tab 47 | 1. Open apps/myApps/oscilloscope/Oscilloscope.xcodeproject and then Build&Run 48 | 1. (Optional) Sign&Notarize with apple: Copy `scripts/osx-config-template.sh` to `osx-config.sh`, then run `scripts/dist.sh osx 1.1.0` 49 | 50 | 51 | You can also build with `make && make run` on the command line. The resulting build will have no icon/no proper name/no retina support. 52 | 53 | ### Compiling with Visual studio 2017 54 | 55 | The shell commands can be run from a git bash, cygwin, msys, or any other shell emulator. 56 | 57 | 1. run `scripts/clean.sh` 58 | 1. run `scripts/prepare.sh win64` 59 | 1. Open oscilloscope.sln and Build&Run 60 | 61 | ### Compiling with make in Linux 62 | 63 | This is a full install including OF (thx rrolison68!) 64 | 65 | cd 66 | wget -c https://openframeworks.cc/versions/v0.10.1/of_v0.10.1_linux64gcc6_release.tar.gz 67 | tar -zxvf of_v0.10.1_linux64gcc6_release.tar.gz 68 | mv of_v0.10.1_linux64gcc6_release OF 69 | cd OF/scripts/linux/ubuntu 70 | sudo ./install_dependencies.sh 71 | cd 72 | cd OF/apps/myApps 73 | git clone --recursive https://github.com/kritzikratzi/Oscilloscope.git 74 | cd Oscilloscope 75 | scripts/clean.sh 76 | cp -R addons/ofxMightyUI/bin/data/* bin/data/ 77 | cp -R addons/ofxFontAwesome/bin/data/* bin/data/ 78 | make -j2 79 | bin/Oscilloscope 80 | See scripts/readme.md for the full distribution process. 81 | 82 | ### Package the software 83 | 84 | * for osx run `scripts/dist.sh $platform $version` 85 | * platform is one of `osx linux linux64 win64` 86 | * version is whatever version you want, e.g. `1.0.6` 87 | 88 | ### Contributors 89 | 90 | * [https://github.com/subwolf/](subwolf) Linux support 91 | * [https://github.com/s-ol/](s-ol) Linux support 92 | 93 | 94 | ## License/Source code 95 | 96 | * [Openframeworks](http://openframeworks.cc). A creative coding library. The larger part of it is licensed as MIT/BSD. 97 | * [FFmpeg](http://www.ffmpeg.org/) and [ofxAvCodec](https://github.com/kritzikratzi/ofxAvCodec). FFmpeg is _the_ encoder/decoder library and licensed under the gpl/lgpl 2.1. The binaries included here were compiled to comply with the lgpl. A copy of the LGPL together with instructions how the library was compiled for each platform can be found in the `legal` folder. 98 | * The sourcecode for this application is freely available on [github](https://github.com/kritzikratzi/Oscilloscope). 99 | -------------------------------------------------------------------------------- /src/main.cpp: -------------------------------------------------------------------------------- 1 | #include "ofMain.h" 2 | #include "ofApp.h" 3 | #include "ofxMightyUI.h" 4 | 5 | #if defined(TARGET_OSX) 6 | #import 7 | #elif defined(TARGET_WIN32) 8 | #include "../resource.h" 9 | #endif 10 | #include "version.h" 11 | 12 | #include "ofAppGLFWWindow.h" 13 | #include "ofxNative.h" 14 | #include 15 | 16 | 17 | //======================================================================== 18 | int main(){ 19 | globals.loadFromFile(); 20 | ofSetEscapeQuitsApp(false); 21 | 22 | ofAppGLFWWindow window; 23 | 24 | cout << "LAUNCH DESKTOP" << endl; 25 | ofSetupOpenGL(&window, 1024, 700, OF_WINDOW); 26 | window.setWindowTitle("Oscilloscope " + app_version); 27 | 28 | // go fullscreen in mac osx 29 | ofxNative::maximizeWindow(window); 30 | 31 | #if defined(TARGET_OSX) 32 | NSWindow * cocoaWindow = (NSWindow*)window.getCocoaWindow(); 33 | // [cocoaWindow setFrame:[[NSScreen mainScreen] visibleFrame] display:YES]; 34 | NSString * ver = [NSString stringWithUTF8String:app_version.c_str()]; 35 | NSString * title = [NSString stringWithFormat:@"Oscilloscope %@", ver]; 36 | [cocoaWindow setTitle:title]; 37 | if(globals.alwaysOnTop){ 38 | [cocoaWindow setLevel: NSFloatingWindowLevel]; 39 | } 40 | #endif 41 | 42 | #if defined(TARGET_WIN32) 43 | HWND hwnd = ofGetWin32Window(); 44 | HICON hMyIcon = LoadIcon(GetModuleHandle(NULL), MAKEINTRESOURCE(MAIN_ICON)); 45 | SendMessage(hwnd, WM_SETICON, ICON_BIG, (LPARAM)hMyIcon); 46 | #endif 47 | 48 | mui_init(); 49 | mui::MuiConfig::font = "mui/fonts/Lato-Regular.ttf"; 50 | ofRunApp(new ofApp); 51 | } 52 | 53 | #ifdef _WIN32 54 | // handle windows startup 55 | INT WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, 56 | PSTR lpCmdLine, INT nCmdShow) 57 | { 58 | return main(); 59 | } 60 | #endif 61 | 62 | 63 | void setWindowRepresentedFilename( string filename ){ 64 | #if defined(TARGET_OSX) 65 | NSWindow * cocoaWindow = (NSWindow*)(ofGetWindowPtr()->getCocoaWindow()); 66 | if(filename == ""){ 67 | [cocoaWindow setRepresentedFilename:@""]; 68 | NSString * ver = [NSString stringWithUTF8String:app_version.c_str()]; 69 | NSString * title = [NSString stringWithFormat:@"Oscilloscope %@", ver]; 70 | [cocoaWindow setTitle:title]; 71 | } 72 | else if(filename[0] != '/'){ 73 | [cocoaWindow setRepresentedFilename:@""]; 74 | [cocoaWindow setTitle:[NSString stringWithUTF8String:filename.c_str()]]; 75 | } 76 | else{ 77 | NSString * file = [NSString stringWithUTF8String:filename.c_str()]; 78 | NSString * filename = [file pathComponents].lastObject; 79 | [cocoaWindow setTitle:filename]; 80 | [cocoaWindow setRepresentedFilename:file]; 81 | } 82 | #else 83 | if(filename==""){ 84 | ofGetWindowPtr()->setWindowTitle("Oscilloscope " + app_version); 85 | } 86 | else{ 87 | ofGetWindowPtr()->setWindowTitle(filename); 88 | } 89 | #endif 90 | 91 | } 92 | 93 | 94 | // returns a path where the application can only read. 95 | // for osx this is the "resources" folder residing inside the application bundle, 96 | // for windows it is still the data folder. 97 | // if the file does not exist in the application bundle, the data folder is returned. 98 | string ofxToReadonlyDataPath( string filename ){ 99 | #ifdef TARGET_OSX 100 | // http://www.cocoabuilder.com/archive/cocoa/193451-finding-out-executable-location-from-c-program.html 101 | CFBundleRef bundle = CFBundleGetMainBundle(); 102 | CFURLRef url = CFBundleCopyResourcesDirectoryURL(bundle); 103 | CFURLRef absolute = CFURLCopyAbsoluteURL(url); 104 | Boolean abs; 105 | CFStringRef path = CFURLCopyFileSystemPath(absolute,kCFURLPOSIXPathStyle); 106 | CFIndex maxLength = CFStringGetMaximumSizeOfFileSystemRepresentation(path); 107 | char *result = (char*)malloc(maxLength); 108 | 109 | if(result) { 110 | if(!CFStringGetFileSystemRepresentation(path,result, maxLength)) { 111 | free(result); 112 | result = NULL; 113 | } 114 | } 115 | 116 | string realResult = string([[NSString stringWithUTF8String:result] stringByAppendingPathComponent:[NSString stringWithUTF8String:filename.c_str()]].UTF8String ); 117 | 118 | CFRelease(path); 119 | CFRelease(url); 120 | CFRelease(absolute); 121 | 122 | if( ofFile(realResult, ofFile::Reference).exists() ){ 123 | return realResult; 124 | } 125 | else{ 126 | return ofToDataPath(filename,true); 127 | } 128 | #else 129 | return ofToDataPath(filename,true); 130 | #endif 131 | } 132 | 133 | 134 | // returns a path where the application can safely read+write data. 135 | // this is great for settings files and the like. 136 | // for osx this is the application support directory (without sandboxing) 137 | // or ~/Library/Containers// 138 | // for windows this is in %APPDATA% 139 | string ofxToReadWriteableDataPath( string filename ){ 140 | return ofxNative::getSystemDataFolder() + "/" + filename; 141 | } 142 | -------------------------------------------------------------------------------- /src/globals.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // globals.cpp 3 | // Oscilloscope 4 | // 5 | // Created by Hansi on 26.07.15. 6 | // 7 | // 8 | 9 | #include "globals.h" 10 | #include "util/WickedLasers.h" 11 | #include "util/miniaudio.h" 12 | 13 | Globals Globals::instance; 14 | 15 | void Globals::init() { 16 | laserPtr = make_shared(); 17 | context = new ma_context(); 18 | if (ma_context_init(NULL, 0, NULL, context) != MA_SUCCESS) { 19 | ofSystemAlertDialog("Failed to initialize audio context :("); 20 | 21 | } 22 | } 23 | 24 | string ofxFormatTime(double seconds) { 25 | int total = seconds; 26 | int s = total % 60; 27 | 28 | total = total / 60; 29 | int m = total % 60; 30 | 31 | total = total / 60; 32 | int h = total; 33 | 34 | return ofToString(h, 2, '0') + ":" + ofToString(m, 2, '0') + ":" + ofToString(s, 2, '0'); 35 | } 36 | 37 | 38 | void Globals::loadFromFile(string settingsFile) { 39 | ofxIniSettings settings = ofxIniSettings(settingsFile); 40 | out_requested.bufferSize = settings.get("out_bufferSize", out_requested.bufferSize); 41 | out_requested.sampleRate = settings.get("out_sampleRate", out_requested.sampleRate); 42 | out_requested.name = settings.get("out_deviceName", out_requested.name); 43 | in_requested.bufferSize = settings.get("in_bufferSize", in_requested.sampleRate); 44 | in_requested.sampleRate = settings.get("in_sampleRate", in_requested.sampleRate); 45 | in_requested.name = settings.get("in_deviceName", in_requested.name); 46 | 47 | scale = settings.get("scale", scale); 48 | flipXY = settings.get("flipXY", flipXY); 49 | zModulation = settings.get("zModulation", zModulation); 50 | invertX = settings.get("invertX", invertX); 51 | invertY = settings.get("invertY", invertY); 52 | outputVolume = settings.get("outputVolume", outputVolume); 53 | inputVolume = settings.get("inputVolume", inputVolume); 54 | strokeWeight = settings.get("strokeWeight", strokeWeight); 55 | //timeStretch = settings.get( "timeStretch", timeStretch ); // never load timestretch! 56 | blur = settings.get("blur", blur); 57 | numPts = settings.get("numPts", numPts); 58 | hue = settings.get("hue", hue); 59 | intensity = settings.get("intensity", intensity); 60 | afterglow = settings.get("afterglow", afterglow); 61 | analogMode = settings.get("analogMode", analogMode); 62 | exportFrameRate = settings.get("exportFrameRate", exportFrameRate); 63 | exportWidth = settings.get("exportWidth", exportWidth); 64 | exportHeight = settings.get("exportHeight", exportHeight); 65 | exportFormat = (ExportFormat)settings.get("exportFormat", (int)exportFormat); 66 | exportSampleRate = settings.get("exportSampleRate", (int)exportSampleRate); 67 | 68 | laserOffsetX = settings.get("laserOffsetX", laserOffsetX); 69 | laserOffsetY = settings.get("laserOffsetY", laserOffsetY); 70 | laserKeystoneX = settings.get("laserKeystoneX", laserKeystoneX); 71 | laserKeystoneY = settings.get("laserKeystoneY", laserKeystoneY); 72 | 73 | //secondsBeforeHidingMenu = settings.get( "secondsBeforeHidingMenu", secondsBeforeHidingMenu ); 74 | } 75 | 76 | 77 | void Globals::saveToFile(string settingsFile) { 78 | if (!ofFile(settingsFile, ofFile::Reference).exists()) { 79 | ofFile file(settingsFile, ofFile::WriteOnly); 80 | file << endl; 81 | file.close(); 82 | } 83 | 84 | ofxIniSettings settings = ofxIniSettings(settingsFile); 85 | 86 | //settings.set("out_bufferSize", out_requested.bufferSize); 87 | //settings.set("out_sampleRate", out_requested.sampleRate); 88 | settings.set("out_deviceName", out_requested.name); 89 | //settings.set("in_bufferSize", in_requested.bufferSize); 90 | //settings.set("in_sampleRate", in_requested.sampleRate); 91 | settings.set("in_deviceName", in_requested.name); 92 | settings.set("scale", scale); 93 | settings.set("flipXY", flipXY); 94 | settings.set("zModulation", zModulation); 95 | settings.set("invertX", invertX); 96 | settings.set("invertY", invertY); 97 | settings.set("outputVolume", outputVolume); 98 | settings.set("inputVolume", inputVolume); 99 | settings.set("strokeWeight", strokeWeight); 100 | // settings.set( "timeStretch", timeStretch ); // never save timestretch! 101 | settings.set("blur", blur); 102 | settings.set("numPts", numPts); 103 | settings.set("hue", hue); 104 | settings.set("intensity", intensity); 105 | settings.set("afterglow", afterglow); 106 | settings.set("analogMode", analogMode); 107 | settings.set("exportFrameRate", exportFrameRate); 108 | settings.set("exportWidth", exportWidth); 109 | settings.set("exportHeight", exportHeight); 110 | settings.set("exportFormat", (int)exportFormat); 111 | settings.set("exportSampleRate", (int)exportSampleRate); 112 | 113 | settings.set("laserOffsetX", laserOffsetX); 114 | settings.set("laserOffsetY", laserOffsetY); 115 | settings.set("laserKeystoneX", laserKeystoneX); 116 | settings.set("laserKeystoneY", laserKeystoneY); 117 | 118 | // settings.set( "secondsBeforeHidingMenu", secondsBeforeHidingMenu ); 119 | } 120 | -------------------------------------------------------------------------------- /scripts/readme.md: -------------------------------------------------------------------------------- 1 | #Oscilloscope - Packaging notes 2 | 3 | === 4 | 5 | These are my own notes how to bundle up the app for each platform so that i don't forget. 6 | 7 | # OSX 8 | 9 | 10 | 1. Open apps/myApps/oscilloscope/Oscilloscope.xcodeproject 11 | 1. Select the binary target and update the version info 12 | 1. Delete oscilloscope.app in finder, to make sure you have a fresh build 13 | 1. Build&Run 14 | 1. Code sign: `scripts/sign-mac.sh bin/Oscilloscope.app "Developer ID Application: Name of your certificate"` (run `security find-identity -v -p codesigning` to get a list of installed certs) 15 | 1. Create a zip in finder (don't use terminal, that creates a different zip i think) 16 | 17 | You can also build with `make && make run` on the command line. The resulting build will have no icon/no proper name/no retina support. 18 | 19 | First patch OF to get rid of glut and fmodex: https://forum.openframeworks.cc/t/bundling-osx-app-without-glut-and-without-fmodex-nasty/23503 20 | 21 | ## Windows (Visual studio 2015) 22 | 23 | 1. run `scripts/clean.sh` 24 | 1. run `scripts/prepare.sh win32` 25 | 1. Open oscilloscope.sln 26 | 1. Open icon.rc, update the version info section 27 | 1. build 28 | 1. Run scripts/dist.sh win32 1.0.x 29 | 30 | At this point audio should play through Asio (first choice), or Wasapi. You can follow these instructions to patch OF so you can pick at startup: http://pastebin.com/ZZLZ3jUm 31 | 32 | 33 | ### VS Project file 34 | 35 | #### Delay Load DLLs 36 | 37 | Configuration: Win32 / Release 38 | Go to `Linker>All Options>Delay Load Dlls` and enter: 39 | 40 | 41 | assimp.dll 42 | glut32.dll 43 | libeay32.dll 44 | ssleay32.dll 45 | swscale-3.dll 46 | Zlib.dll 47 | FreeType.dll 48 | fmodex.dll 49 | fmodexL.dll 50 | 51 | None of these are actually used, ever. Specifying them as delay loaded allows you to just delete them. 52 | 53 | 54 | 55 | ### Compiling with make in Linux 56 | 57 | 1. run `scripts/clean.sh` 58 | 1. run `scripts/prepare.sh linux64` 59 | 1. run `make && make run` ? [subwolf knows, i haven't done this in ages!] 60 | 61 | See scripts/readme.md for the full distribution process. 62 | 63 | ### Package the software 64 | 65 | * for osx run `scripts/dist.sh $platform $version` 66 | * platform is one of `osx linux linux64 win32 win64` 67 | * version is whatever version you want, e.g. `1.0.6` 68 | 69 | 70 | Helper Scripts 71 | === 72 | 73 | 74 | These scripts help manage the build process. 75 | You'll need a bash shell to run the scripts. 76 | 77 | The scripts should all figure out the correct paths themselves. There's no need to worry about the working directory. 78 | 79 | 80 | clean.sh 81 | --- 82 | 83 | Cleans out the bin/ folder and removes files not in the repository. 84 | Changed files will not be reset. 85 | 86 | prepare.sh 87 | --- 88 | Prepares the bin folder for a platform. This also fixes some problems with the build process that (i believe) I'm currently too dumb to fix directly in the make files. 89 | 90 | The script requires one argument, the operating system. Possible options are: 91 | 92 | * osx 93 | * linux 94 | * linux64 95 | * win32 96 | * win64 97 | 98 | Depending on the parameter some dll files and other resources are copied to the bin folder. 99 | Use `clean.sh` to get rid of the mess again. 100 | 101 | 102 | dist.sh 103 | --- 104 | Assembles a zip file ready for binary distribution. This adds the ffmpeg license files, compilation instructions, and does a whole lot of other things. It takes two parameters, one for the version, the other for the platform. 105 | 106 | A typical distribution workflow looks like this: 107 | 108 | cd apps/myApps/Oscilloscope 109 | 110 | platform=osx 111 | version=1.0.3 112 | 113 | scripts/clean.sh 114 | scripts/prepare.sh $platform 115 | 116 | # now build & test (use xcode on mac, visual studio on windows, run make release on linux) 117 | 118 | scripts/dist.sh $platform $version 119 | 120 | 121 | 122 | # OSX: Getting rid of GLUT and Fmodex (optional) 123 | 124 | Those two libraries aren't needed. Removing them is done all at once, like this: 125 | 126 | 127 | Remove the setting `FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1 = "\"$(SRCROOT)/../../../libs/glut/lib/osx\""` (you can find it through xcode cmd+shift+f search) 128 | 129 | Then, in `CoreOF.xcconfig`, redefine LIB_FMODEX and change LIB_FMODEX: 130 | 131 | // disable fmodex! 132 | LIB_FMODEX = -Wl,-U,_FMOD_System_Close 133 | REMOVED_DEPS = yes 134 | 135 | OF_CORE_FRAMEWORKS = -framework Accelerate -framework AGL -framework AppKit -framework ApplicationServices -framework AudioToolbox -framework AVFoundation -framework Cocoa -framework CoreAudio -framework CoreFoundation -framework CoreMedia -framework CoreServices -framework CoreVideo -framework IOKit -framework OpenGL -framework QuartzCore -framework QuickTime -framework QTKit //-framework GLUT 136 | 137 | 138 | Now go into the project config, build phases, run scripts, and wrap the glut and fmodex entries in an if: 139 | 140 | if [ REMOVED_DEPS -ne "yes"] 141 | then 142 | # Copy libfmod and change install directory for fmod to run 143 | rsync -aved ../../../libs/fmodex/lib/osx/libfmodex.dylib "$TARGET_BUILD_DIR/$PRODUCT_NAME.app/Contents/Frameworks/"; 144 | install_name_tool -change @executable_path/libfmodex.dylib @executable_path/../Frameworks/libfmodex.dylib "$TARGET_BUILD_DIR/$PRODUCT_NAME.app/Contents/MacOS/$PRODUCT_NAME"; 145 | # Copy GLUT framework (must remove for AppStore submissions) 146 | rsync -aved ../../../libs/glut/lib/osx/GLUT.framework "$TARGET_BUILD_DIR/$PRODUCT_NAME.app/Contents/Frameworks/" 147 | fi 148 | 149 | This way the build should still work if someone hasn't tweaked their OF installation. -------------------------------------------------------------------------------- /src/ui/FMenu.h: -------------------------------------------------------------------------------- 1 | /* 2 | * FMenu.h 3 | * ofxMightyUI 4 | * 5 | * v1.14, add button with custom callback 6 | * v1.13, set minWidth on init 7 | * v1.12, removed highlightSelected option from dropdown 8 | * v1.11, add removeAllOptionsAndNotify() 9 | * v1.10, renamed dropdown::getOptionByName to dropdown::getOptionByValue (which is what was meant in the first place) 10 | * v1.9, added getOptionByValue(...), cleaned up a tiny bit 11 | * v1.8, undocumented.... minWidth, fixed layout issues, fontsize back to normal 12 | * v1.7, fdropdown: triangle scale, data display function, use mui_root->popup functions for dropdown 13 | * v1.6, merged 1.3a-1.5 from AL, merged 1.3-1.5 from OS 14 | * v1.5, allow multicolumn, rewrite layouting 15 | * v1.4, mouse over effect for buttons 16 | * v1.3a, add remove all options method 17 | * v1.5, 21.11.2016, removed funny dependency to soundythingie 18 | * v1.4, dropdown class now has a "datadelegate" 19 | * v1.3, added a dropdown button class with embedded menu 20 | * v1.2, it actually sortof works a bit, with the options. 21 | * v1.1, ability to attach data to an option 22 | * v1.0, 29.01.11. initial version 23 | * 24 | */ 25 | 26 | #pragma once 27 | 28 | #include "ofxMightyUI.h" 29 | 30 | enum class FMenuNotify{ 31 | always, if_changed, never 32 | }; 33 | 34 | template 35 | class FMenu : public mui::Container { 36 | public: 37 | struct Option { 38 | Option(mui::Button * b, const T & v, mui::EventHandler