diff --git a/.gitignore b/.gitignore index b5f9d79fc..e3b9c153d 100644 --- a/.gitignore +++ b/.gitignore @@ -53,3 +53,8 @@ Xcode-config/SENTRY_SETTINGS.xcconfig /ThirdParty/vorbis/lib/libvorbisfile.3.dylib /ThirdParty/vorbis/lib/libvorbis.0.dylib /ThirdParty/soxr/lib/libsoxr.0.dylib +/ThirdParty/libprojectM/lib/libprojectM-4.4.dylib +/ThirdParty/libprojectM/lib/libprojectM-4-playlist.4.dylib +/ThirdParty/libprojectM/lib/libboost_system.dylib +/ThirdParty/libprojectM/lib/libboost_atomic.dylib +/ThirdParty/libprojectM/lib/libboost_filesystem.dylib diff --git a/.gitmodules b/.gitmodules index 8dd17702e..fd6f32235 100644 --- a/.gitmodules +++ b/.gitmodules @@ -19,3 +19,9 @@ [submodule "Frameworks/libsidplayfp/sidplayfp"] path = Frameworks/libsidplayfp/sidplayfp url = https://github.com/kode54/libsidplayfp.git +[submodule "ThirdParty/libprojectM/subprojects/presets-milkdrop-texture-pack"] + path = ThirdParty/libprojectM/subprojects/presets-milkdrop-texture-pack + url = https://github.com/projectM-visualizer/presets-milkdrop-texture-pack.git +[submodule "ThirdParty/libprojectM/subprojects/presets/presets-cream-of-the-crop"] + path = ThirdParty/libprojectM/subprojects/presets/presets-cream-of-the-crop + url = https://github.com/projectM-visualizer/presets-cream-of-the-crop.git diff --git a/Base.lproj/SpectrumWindow.xib b/Base.lproj/SpectrumWindow.xib index 4498c9ca6..c4d1739ac 100644 --- a/Base.lproj/SpectrumWindow.xib +++ b/Base.lproj/SpectrumWindow.xib @@ -1,8 +1,8 @@ - + - + diff --git a/Cog.xcodeproj/project.pbxproj b/Cog.xcodeproj/project.pbxproj index 273e7d4c6..0c36b26a1 100644 --- a/Cog.xcodeproj/project.pbxproj +++ b/Cog.xcodeproj/project.pbxproj @@ -97,6 +97,8 @@ 830C37A127B95E3000E02BB0 /* Equalizer.xib in Resources */ = {isa = PBXBuildFile; fileRef = 830C379F27B95E3000E02BB0 /* Equalizer.xib */; }; 830C37A527B95EB300E02BB0 /* EqualizerWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = 830C37A427B95EB300E02BB0 /* EqualizerWindowController.m */; }; 830C37FC27B9956C00E02BB0 /* analyzer.c in Sources */ = {isa = PBXBuildFile; fileRef = 830C37F227B9956C00E02BB0 /* analyzer.c */; }; + 830EDD1B2D813DEA00988EA8 /* libprojectM-4.4.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 83E9EEBA2D80634600F1D22D /* libprojectM-4.4.dylib */; }; + 830EDD1C2D813DF600988EA8 /* libprojectM-4-playlist.4.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 83E9EEB92D80634600F1D22D /* libprojectM-4-playlist.4.dylib */; }; 831B99BF27C23E88005A969B /* Cog.sdef in Resources */ = {isa = PBXBuildFile; fileRef = 831B99BE27C23E88005A969B /* Cog.sdef */; }; 83256B68286661FC0036D9C0 /* libmpg123.0.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 83256B672866617F0036D9C0 /* libmpg123.0.dylib */; }; 83256B69286661FC0036D9C0 /* libmpg123.0.dylib in CopyFiles */ = {isa = PBXBuildFile; fileRef = 83256B672866617F0036D9C0 /* libmpg123.0.dylib */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; }; @@ -181,6 +183,17 @@ 83BC5AC420E4CE9000631CD4 /* Feedback.xib in Resources */ = {isa = PBXBuildFile; fileRef = 17D1B1DA0F6330D400694C57 /* Feedback.xib */; }; 83BCB8DE17FC971300760340 /* FFMPEG.bundle in CopyFiles */ = {isa = PBXBuildFile; fileRef = B09E94350D747F7B0064F138 /* FFMPEG.bundle */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; }; 83D0380F24A40DFB004CF90F /* CogAssets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 83D0380E24A40DF2004CF90F /* CogAssets.xcassets */; }; + 83E9A0D02D804A1800F1D22D /* ProjectMView.m in Sources */ = {isa = PBXBuildFile; fileRef = 83E9A0CF2D804A1800F1D22D /* ProjectMView.m */; }; + 83E9EEB32D805C5300F1D22D /* textures in Copy Files */ = {isa = PBXBuildFile; fileRef = 83E9EEB22D805C5300F1D22D /* textures */; }; + 83E9EEB52D805C7B00F1D22D /* presets in Copy Files */ = {isa = PBXBuildFile; fileRef = 83E9EEB42D805C7B00F1D22D /* presets */; }; + 83E9EEBB2D80634600F1D22D /* libboost_atomic.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 83E9EEB62D80634600F1D22D /* libboost_atomic.dylib */; }; + 83E9EEBC2D80634600F1D22D /* libboost_system.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 83E9EEB82D80634600F1D22D /* libboost_system.dylib */; }; + 83E9EEBE2D80634600F1D22D /* libboost_filesystem.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 83E9EEB72D80634600F1D22D /* libboost_filesystem.dylib */; }; + 83E9EEC02D80639E00F1D22D /* libprojectM-4.4.dylib in CopyFiles */ = {isa = PBXBuildFile; fileRef = 83E9EEBA2D80634600F1D22D /* libprojectM-4.4.dylib */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; }; + 83E9EEC12D8063A100F1D22D /* libboost_system.dylib in CopyFiles */ = {isa = PBXBuildFile; fileRef = 83E9EEB82D80634600F1D22D /* libboost_system.dylib */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; }; + 83E9EEC22D8063A400F1D22D /* libboost_atomic.dylib in CopyFiles */ = {isa = PBXBuildFile; fileRef = 83E9EEB62D80634600F1D22D /* libboost_atomic.dylib */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; }; + 83E9EEC32D8063A700F1D22D /* libboost_filesystem.dylib in CopyFiles */ = {isa = PBXBuildFile; fileRef = 83E9EEB72D80634600F1D22D /* libboost_filesystem.dylib */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; }; + 83E9EEC42D8063AD00F1D22D /* libprojectM-4-playlist.4.dylib in CopyFiles */ = {isa = PBXBuildFile; fileRef = 83E9EEB92D80634600F1D22D /* libprojectM-4-playlist.4.dylib */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; }; 83F9D8071A884C54007ABEC2 /* SilenceDecoder.bundle in CopyFiles */ = {isa = PBXBuildFile; fileRef = 83F9D7F61A884B46007ABEC2 /* SilenceDecoder.bundle */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 83F9FFEF2D6EB75B00026576 /* Sentry in Frameworks */ = {isa = PBXBuildFile; productRef = 83F9FFEE2D6EB75B00026576 /* Sentry */; }; 8D11072B0486CEB800E47090 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 089C165CFE840E0CC02AAC07 /* InfoPlist.strings */; }; @@ -669,6 +682,8 @@ dstPath = ""; dstSubfolderSpec = 7; files = ( + 83E9EEB52D805C7B00F1D22D /* presets in Copy Files */, + 83E9EEB32D805C5300F1D22D /* textures in Copy Files */, ED69CA3B25BE2A390090B90D /* Preferences.preferencePane in Copy Files */, ); name = "Copy Files"; @@ -717,6 +732,11 @@ dstPath = ""; dstSubfolderSpec = 10; files = ( + 83E9EEC32D8063A700F1D22D /* libboost_filesystem.dylib in CopyFiles */, + 83E9EEC22D8063A400F1D22D /* libboost_atomic.dylib in CopyFiles */, + 83E9EEC12D8063A100F1D22D /* libboost_system.dylib in CopyFiles */, + 83E9EEC42D8063AD00F1D22D /* libprojectM-4-playlist.4.dylib in CopyFiles */, + 83E9EEC02D80639E00F1D22D /* libprojectM-4.4.dylib in CopyFiles */, 836DF617298F6F1700CD0580 /* libsoxr.0.dylib in CopyFiles */, 836EF0E127BB98AB00BF35B2 /* libopusfile.0.dylib in CopyFiles */, 836EF0E027BB98A800BF35B2 /* libopus.0.dylib in CopyFiles */, @@ -1044,6 +1064,15 @@ 83D0380E24A40DF2004CF90F /* CogAssets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = CogAssets.xcassets; sourceTree = ""; }; 83D3C5FC201C674D005564CB /* AdPlug.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = AdPlug.xcodeproj; path = Plugins/AdPlug/AdPlug.xcodeproj; sourceTree = ""; }; 83E5EFAC1FFEF78100659F0F /* OpenMPT.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = OpenMPT.xcodeproj; path = Plugins/OpenMPT/OpenMPT.xcodeproj; sourceTree = ""; }; + 83E9A0CE2D8049FA00F1D22D /* ProjectMView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = ProjectMView.h; path = Visualization/ProjectMView.h; sourceTree = ""; }; + 83E9A0CF2D804A1800F1D22D /* ProjectMView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = ProjectMView.m; path = Visualization/ProjectMView.m; sourceTree = ""; }; + 83E9EEB22D805C5300F1D22D /* textures */ = {isa = PBXFileReference; lastKnownFileType = folder; name = textures; path = "ThirdParty/libprojectM/subprojects/presets-milkdrop-texture-pack/textures"; sourceTree = ""; }; + 83E9EEB42D805C7B00F1D22D /* presets */ = {isa = PBXFileReference; lastKnownFileType = folder; name = presets; path = ThirdParty/libprojectM/subprojects/presets; sourceTree = ""; }; + 83E9EEB62D80634600F1D22D /* libboost_atomic.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libboost_atomic.dylib; path = ThirdParty/libprojectM/lib/libboost_atomic.dylib; sourceTree = ""; }; + 83E9EEB72D80634600F1D22D /* libboost_filesystem.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libboost_filesystem.dylib; path = ThirdParty/libprojectM/lib/libboost_filesystem.dylib; sourceTree = ""; }; + 83E9EEB82D80634600F1D22D /* libboost_system.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libboost_system.dylib; path = ThirdParty/libprojectM/lib/libboost_system.dylib; sourceTree = ""; }; + 83E9EEB92D80634600F1D22D /* libprojectM-4-playlist.4.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = "libprojectM-4-playlist.4.dylib"; path = "ThirdParty/libprojectM/lib/libprojectM-4-playlist.4.dylib"; sourceTree = ""; }; + 83E9EEBA2D80634600F1D22D /* libprojectM-4.4.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = "libprojectM-4.4.dylib"; path = "ThirdParty/libprojectM/lib/libprojectM-4.4.dylib"; sourceTree = ""; }; 83F9D7F11A884B44007ABEC2 /* SilenceDecoder.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = SilenceDecoder.xcodeproj; path = Plugins/SilenceDecoder/SilenceDecoder.xcodeproj; sourceTree = ""; }; 8D1107310486CEB800E47090 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist; path = Info.plist; sourceTree = ""; }; 8E07AB760AAC930B00A4B32F /* PreferencesController.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = PreferencesController.h; path = Preferences/PreferencesController.h; sourceTree = ""; }; @@ -1080,6 +1109,11 @@ 8355D6B8180613FB00D05687 /* Security.framework in Frameworks */, 8D11072F0486CEB800E47090 /* Cocoa.framework in Frameworks */, 83256B68286661FC0036D9C0 /* libmpg123.0.dylib in Frameworks */, + 830EDD1C2D813DF600988EA8 /* libprojectM-4-playlist.4.dylib in Frameworks */, + 830EDD1B2D813DEA00988EA8 /* libprojectM-4.4.dylib in Frameworks */, + 83E9EEBB2D80634600F1D22D /* libboost_atomic.dylib in Frameworks */, + 83E9EEBC2D80634600F1D22D /* libboost_system.dylib in Frameworks */, + 83E9EEBE2D80634600F1D22D /* libboost_filesystem.dylib in Frameworks */, 17BB5CED0B8A86010009ACB1 /* AudioToolbox.framework in Frameworks */, 835FAC7F27BCDF5B00BA8562 /* libavif.a in Frameworks */, 83922FBA286B1AA900A0B039 /* WebKit.framework in Frameworks */, @@ -1144,6 +1178,11 @@ 1058C7A2FEA54F0111CA2CBB /* Other Frameworks */ = { isa = PBXGroup; children = ( + 83E9EEB62D80634600F1D22D /* libboost_atomic.dylib */, + 83E9EEB72D80634600F1D22D /* libboost_filesystem.dylib */, + 83E9EEB82D80634600F1D22D /* libboost_system.dylib */, + 83E9EEB92D80634600F1D22D /* libprojectM-4-playlist.4.dylib */, + 83E9EEBA2D80634600F1D22D /* libprojectM-4.4.dylib */, 838A33732D06A9B100D0D770 /* librubberband.3.dylib */, 836DF616298F6EC400CD0580 /* libsoxr.0.dylib */, 83256B672866617F0036D9C0 /* libmpg123.0.dylib */, @@ -1468,6 +1507,8 @@ 29B97314FDCFA39411CA2CEA /* Cog */ = { isa = PBXGroup; children = ( + 83E9EEB42D805C7B00F1D22D /* presets */, + 83E9EEB22D805C5300F1D22D /* textures */, 0A1B412E286F6301008A6A44 /* Localizable.stringsdict */, 83D0380E24A40DF2004CF90F /* CogAssets.xcassets */, 83859520234FEB35004E9946 /* Cog.entitlements */, @@ -1800,6 +1841,8 @@ 838A33812D06CF4100D0D770 /* SpectrumWindowController.h */, 838A33822D06CF4100D0D770 /* SpectrumWindowController.m */, 8377C66427B8CF7A00E8BC0F /* VisualizationController.h */, + 83E9A0CE2D8049FA00F1D22D /* ProjectMView.h */, + 83E9A0CF2D804A1800F1D22D /* ProjectMView.m */, ); name = Visualization; sourceTree = ""; @@ -2545,6 +2588,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 83E9A0D02D804A1800F1D22D /* ProjectMView.m in Sources */, 83A3B734283AE89000CC6593 /* ColorToValueTransformer.m in Sources */, 8D11072D0486CEB800E47090 /* main.m in Sources */, 8E75757109F31D5A0080F1EE /* DNDArrayController.m in Sources */, @@ -2956,7 +3000,10 @@ GCC_DYNAMIC_NO_PIC = NO; GCC_ENABLE_OBJC_EXCEPTIONS = YES; GCC_OPTIMIZATION_LEVEL = 0; - HEADER_SEARCH_PATHS = ThirdParty/avif/include; + HEADER_SEARCH_PATHS = ( + ThirdParty/avif/include, + ThirdParty/libprojectM/include, + ); IBC_COMPILER_USE_NIBKEYEDARCHIVER_FOR_MACOS = YES; IBSC_COMPILER_USE_NIBKEYEDARCHIVER_FOR_MACOS = YES; INFOPLIST_FILE = Info.plist; @@ -2975,6 +3022,7 @@ "$(PROJECT_DIR)/ThirdParty/soxr/lib", "$(PROJECT_DIR)", "$(PROJECT_DIR)/ThirdParty/rubberband/lib", + "$(PROJECT_DIR)/ThirdParty/libprojectM/lib", ); OTHER_CFLAGS = ( "-D__MACOSX__", @@ -3015,7 +3063,10 @@ ENABLE_HARDENED_RUNTIME = YES; FRAMEWORK_SEARCH_PATHS = "$(PROJECT_DIR)/ThirdParty/Frameworks"; GCC_ENABLE_OBJC_EXCEPTIONS = YES; - HEADER_SEARCH_PATHS = ThirdParty/avif/include; + HEADER_SEARCH_PATHS = ( + ThirdParty/avif/include, + ThirdParty/libprojectM/include, + ); IBC_COMPILER_USE_NIBKEYEDARCHIVER_FOR_MACOS = YES; IBSC_COMPILER_USE_NIBKEYEDARCHIVER_FOR_MACOS = YES; INFOPLIST_FILE = Info.plist; @@ -3034,6 +3085,7 @@ "$(PROJECT_DIR)/ThirdParty/soxr/lib", "$(PROJECT_DIR)", "$(PROJECT_DIR)/ThirdParty/rubberband/lib", + "$(PROJECT_DIR)/ThirdParty/libprojectM/lib", ); OTHER_CFLAGS = ( "-D__MACOSX__", diff --git a/ThirdParty/libprojectM/include/projectM-4/audio.h b/ThirdParty/libprojectM/include/projectM-4/audio.h new file mode 100644 index 000000000..28e9d5e68 --- /dev/null +++ b/ThirdParty/libprojectM/include/projectM-4/audio.h @@ -0,0 +1,99 @@ +/** + * @file audio.h + * @copyright 2003-2023 projectM Team + * @brief Functions to pass in audio data to libprojectM. + * + * projectM -- Milkdrop-esque visualisation SDK + * Copyright (C)2003-2023 projectM Team + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * See 'LICENSE.txt' included within this release + * + */ + +#pragma once + +#include "projectM-4/types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Returns the maximum number of audio samples that can be stored. + * + * Each PCM data UpdateMeshSize should not exceed this number of samples. If more samples + * are added, only this number of samples is stored and the remainder discarded. + * + * @return The number of audio samples that are stored, per channel. + */ +PROJECTM_EXPORT unsigned int projectm_pcm_get_max_samples(); + +/** + * @brief Adds 32-bit floating-point audio samples. + * + * This function is used to add new audio data to projectM's internal audio buffer. It is internally converted + * to 2-channel float data, duplicating the channel. + * + * If stereo, the channel order in samples is LRLRLR. + * + * @param instance The projectM instance handle. + * @param samples An array of PCM samples. + * Each sample is expected to be within the range -1 to 1. + * @param count The number of audio samples in a channel. + * @param channels If the buffer is mono or stereo. + * Can be PROJECTM_MONO or PROJECTM_STEREO. + */ +PROJECTM_EXPORT void projectm_pcm_add_float(projectm_handle instance, const float* samples, + unsigned int count, projectm_channels channels); + +/** + * @brief Adds 16-bit integer audio samples. + * + * This function is used to add new audio data to projectM's internal audio buffer. It is internally converted + * to 2-channel float data, duplicating the channel. + * + * If stereo, the channel order in samples is LRLRLR. + * + * @param instance The projectM instance handle. + * @param samples An array of PCM samples. + * @param count The number of audio samples in a channel. + * @param channels If the buffer is mono or stereo. + * Can be PROJECTM_MONO or PROJECTM_STEREO. + */ +PROJECTM_EXPORT void projectm_pcm_add_int16(projectm_handle instance, const int16_t* samples, + unsigned int count, projectm_channels channels); + +/** + * @brief Adds 8-bit unsigned integer audio samples. + * + * This function is used to add new audio data to projectM's internal audio buffer. It is internally converted + * to 2-channel float data, duplicating the channel. + * + * If stereo, the channel order in samples is LRLRLR. + * + * @param instance The projectM instance handle. + * @param samples An array of PCM samples. + * @param count The number of audio samples in a channel. + * @param channels If the buffer is mono or stereo. + * Can be PROJECTM_MONO or PROJECTM_STEREO. + */ +PROJECTM_EXPORT void projectm_pcm_add_uint8(projectm_handle instance, const uint8_t* samples, + unsigned int count, projectm_channels channels); + +#ifdef __cplusplus +} // extern "C" +#endif + diff --git a/ThirdParty/libprojectM/include/projectM-4/callbacks.h b/ThirdParty/libprojectM/include/projectM-4/callbacks.h new file mode 100644 index 000000000..4a55c872a --- /dev/null +++ b/ThirdParty/libprojectM/include/projectM-4/callbacks.h @@ -0,0 +1,89 @@ +/** + * @file callbacks.h + * @copyright 2003-2023 projectM Team + * @brief Functions and prototypes for projectM callbacks. + * + * projectM -- Milkdrop-esque visualisation SDK + * Copyright (C)2003-2023 projectM Team + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * See 'LICENSE.txt' included within this release + * + */ + +#pragma once + +#include "projectM-4/types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Callback function that is executed whenever projectM wants to switch to a new preset. + * + * @param is_hard_cut If true, the transition was triggered by a beat-driven event. + * @param user_data A user-defined data pointer that was provided when registering the callback, +* e.g. context information. + */ +typedef void (*projectm_preset_switch_requested_event)(bool is_hard_cut, void* user_data); + +/** + * @brief Callback function that is executed if a preset change failed. + * + * The message and filename pointers are only valid inside the callback. Make a copy if these values + * need to be retained for later use. + * + * @param preset_filename The filename of the failed preset. + * @param message The error message. + * @param user_data A user-defined data pointer that was provided when registering the callback, + * e.g. context information. + */ +typedef void (*projectm_preset_switch_failed_event)(const char* preset_filename, + const char* message, void* user_data); + + +/** + * @brief Sets a callback function that will be called when a preset change is requested. + * + * Only one callback can be registered per projectM instance. To remove the callback, use NULL. + * + * @param instance The projectM instance handle. + * @param callback A pointer to the callback function. + * @param user_data A pointer to any data that will be sent back in the callback, e.g. context + * information. + */ +PROJECTM_EXPORT void projectm_set_preset_switch_requested_event_callback(projectm_handle instance, + projectm_preset_switch_requested_event callback, + void* user_data); + +/** + * @brief Sets a callback function that will be called when a preset change failed. + * + * Only one callback can be registered per projectM instance. To remove the callback, use NULL. + * + * @param instance The projectM instance handle. + * @param callback A pointer to the callback function. + * @param user_data A pointer to any data that will be sent back in the callback, e.g. context + * information. + */ +PROJECTM_EXPORT void projectm_set_preset_switch_failed_event_callback(projectm_handle instance, + projectm_preset_switch_failed_event callback, + void* user_data); + +#ifdef __cplusplus +} // extern "C" +#endif + diff --git a/ThirdParty/libprojectM/include/projectM-4/core.h b/ThirdParty/libprojectM/include/projectM-4/core.h new file mode 100644 index 000000000..59fc294a3 --- /dev/null +++ b/ThirdParty/libprojectM/include/projectM-4/core.h @@ -0,0 +1,135 @@ +/** + * @file core.h + * @copyright 2003-2023 projectM Team + * @brief Core functions to instantiate, destroy and control projectM. + * + * projectM -- Milkdrop-esque visualisation SDK + * Copyright (C)2003-2023 projectM Team + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * See 'LICENSE.txt' included within this release + * + */ + +#pragma once + +#include "projectM-4/types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Creates a new projectM instance. + * + * If this function returns NULL, in most cases the OpenGL context is not initialized, not made + * current or insufficient to render projectM visuals. + * + * @return A projectM handle for the newly created instance that must be used in subsequent API calls. + * NULL if the instance could not be created successfully. + */ +PROJECTM_EXPORT projectm_handle projectm_create(); + +/** + * @brief Destroys the given instance and frees the resources. + * + * After destroying the handle, it must not be used for any other calls to the API. + * + * @param instance A handle returned by projectm_create() or projectm_create_settings(). + */ +PROJECTM_EXPORT void projectm_destroy(projectm_handle instance); + +/** + * @brief Loads a preset from the given filename/URL. + * + * Ideally, the filename should be given as a standard local path. projectM also supports loading + * "file://" URLs. Additionally, the special filename "idle://" can be used to load the default + * idle preset, displaying the "M" logo. + * + * Other URL schemas aren't supported and will cause a loading error. + * + * If the preset can't be loaded, no switch takes place and the current preset will continue to + * be displayed. Note that if there's a transition in progress when calling this function, the + * transition will be finished immediately, even if the new preset can't be loaded. + * + * @param instance The projectM instance handle. + * @param filename The preset filename or URL to load. + * @param smooth_transition If true, the new preset is smoothly blended over. + */ +PROJECTM_EXPORT void projectm_load_preset_file(projectm_handle instance, const char* filename, + bool smooth_transition); + +/** + * @brief Loads a preset from the data pointer. + * + * Currently, the preset data is assumed to be in Milkdrop format. + * + * If the preset can't be loaded, no switch takes place and the current preset will continue to + * be displayed. Note that if there's a transition in progress when calling this function, the + * transition will be finished immediately, even if the new preset can't be loaded. + * + * @param instance The projectM instance handle. + * @param data The preset contents to load. + * @param smooth_transition If true, the new preset is smoothly blended over. + */ +PROJECTM_EXPORT void projectm_load_preset_data(projectm_handle instance, const char* data, + bool smooth_transition); + +/** + * @brief Reloads all textures. + * + * Calling this method will clear and reload all textures, including the main rendering texture. + * Can cause a small delay/lag in rendering. Only use if texture paths were changed. + * + * @param instance The projectM instance handle. + */ +PROJECTM_EXPORT void projectm_reset_textures(projectm_handle instance); + +/** + * @brief Returns the runtime library version components as individual integers. + * + * Components which aren't required can be set to NULL. + * + * @param major A pointer to an int that will be set to the major version. + * @param minor A pointer to an int that will be set to the minor version. + * @param patch A pointer to an int that will be set to the patch version. + */ +PROJECTM_EXPORT void projectm_get_version_components(int* major, int* minor, int* patch); + +/** + * @brief Returns the runtime library version as a string. + * + * Remember to call @a projectm_free_string() on the returned pointer if the data is no longer + * needed. + * + * @return The library version in the format major.minor.patch. + */ +PROJECTM_EXPORT char* projectm_get_version_string(); + +/** + * @brief Returns the VCS revision from which the projectM library was built. + * + * Can be any text, will mostly contain a Git commit hash. Useful to report bugs. + * + * Remember to call @a projectm_free_string() on the returned pointer if the data is no longer + * needed. + * + * @return The VCS revision number the projectM library was built from. + */ +PROJECTM_EXPORT char* projectm_get_vcs_version_string(); + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/ThirdParty/libprojectM/include/projectM-4/debug.h b/ThirdParty/libprojectM/include/projectM-4/debug.h new file mode 100644 index 000000000..fa0cd9350 --- /dev/null +++ b/ThirdParty/libprojectM/include/projectM-4/debug.h @@ -0,0 +1,55 @@ +/** + * @file debug.h + * @copyright 2003-2023 projectM Team + * @brief Debug functions for both libprojectM and preset developers. + * + * projectM -- Milkdrop-esque visualisation SDK + * Copyright (C)2003-2023 projectM Team + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * See 'LICENSE.txt' included within this release + * + */ + +#pragma once + +#include "projectM-4/types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Writes a .bmp main texture dump after rendering the next main texture, before shaders are applied. + * + * If no file name is given, the image is written to the current working directory + * and will be named named "frame_texture_contents-YYYY-mm-dd-HH:MM:SS-frame.bmp". + * + * Note this is the main texture contents, not the final rendering result. If the active preset + * uses a composite shader, the dumped image will not have it applied. The main texture is what is + * passed over to the next frame, the composite shader is only applied to the display framebuffer + * after updating the main texture. + * + * To capture the actual output, dump the contents of the main framebuffer after calling + * @a projectm_render_frame() on the application side. + * + * @param instance The projectM instance handle. + * @param output_file The filename to write the dump to or NULL. + */ +PROJECTM_EXPORT void projectm_write_debug_image_on_next_frame(projectm_handle instance, const char* output_file); + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/ThirdParty/libprojectM/include/projectM-4/memory.h b/ThirdParty/libprojectM/include/projectM-4/memory.h new file mode 100644 index 000000000..550dc5990 --- /dev/null +++ b/ThirdParty/libprojectM/include/projectM-4/memory.h @@ -0,0 +1,57 @@ +/** + * @file memory.h + * @copyright 2003-2023 projectM Team + * @brief Memory allocation/deallocation helpers. + * + * projectM -- Milkdrop-esque visualisation SDK + * Copyright (C)2003-2023 projectM Team + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * See 'LICENSE.txt' included within this release + * + */ + +#pragma once + +#include "projectM-4/types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Allocates memory for a string and returns the pointer. + * + * To free the allocated memory, call projectm_free_string(). Do not use free()! + * + * @return A pointer to a zero-initialized memory area. + */ +PROJECTM_EXPORT char* projectm_alloc_string(unsigned int length); + +/** + * @brief Frees the memory of an allocated string. + * + *

Frees the memory allocated by a call to projectm_alloc_string() or any + * (const) char* pointers returned by a projectM API call.

+ * + *

Do not use free() to delete the pointer!

+ * + * @param str A pointer returned by projectm_alloc_string(). + */ +PROJECTM_EXPORT void projectm_free_string(const char* str); + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/ThirdParty/libprojectM/include/projectM-4/parameters.h b/ThirdParty/libprojectM/include/projectM-4/parameters.h new file mode 100644 index 000000000..2d9c70c89 --- /dev/null +++ b/ThirdParty/libprojectM/include/projectM-4/parameters.h @@ -0,0 +1,278 @@ +/** + * @file parameters.h + * @copyright 2003-2023 projectM Team + * @brief Functions to set and retrieve all sorts of projectM parameters and setting. + * + * projectM -- Milkdrop-esque visualisation SDK + * Copyright (C)2003-2023 projectM Team + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * See 'LICENSE.txt' included within this release + * + */ + +#pragma once + +#include "projectM-4/types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Sets the texture search paths. + * + * Calling this method will clear and reload all textures, including the main rendering texture. + * Can cause a small delay/lag in rendering. Only use if texture paths were changed. + * + * @param instance The projectM instance handle. + * @param texture_search_paths A list of texture search paths. + * @param count The number of paths in the list. + */ +PROJECTM_EXPORT void projectm_set_texture_search_paths(projectm_handle instance, + const char** texture_search_paths, + size_t count); + +/** + * @brief Sets the beat sensitivity. + * + * The beat sensitivity to be used. + * + * @param instance The projectM instance handle. + * @param sensitivity The sensitivity setting. + */ +PROJECTM_EXPORT void projectm_set_beat_sensitivity(projectm_handle instance, float sensitivity); + +/** + * @brief Returns the beat sensitivity. + * @param instance The projectM instance handle. + * @return The current sensitivity setting. + */ +PROJECTM_EXPORT float projectm_get_beat_sensitivity(projectm_handle instance); + +/** + * @brief Sets the minimum display time before a hard cut can happen. + * + *

Hard cuts are beat-sensitive preset transitions, immediately changing from + * one preset to the next without a smooth blending period.

+ * + *

Set this to a higher value than preset duration to disable hard cuts.

+ * + * @param instance The projectM instance handle. + * @param seconds Minimum number of seconds the preset will be displayed before a hard cut. + */ +PROJECTM_EXPORT void projectm_set_hard_cut_duration(projectm_handle instance, double seconds); + +/** + * @brief Returns the minimum display time before a hard cut can happen. + * @param instance The projectM instance handle. + * @return The minimum number of seconds the preset will be displayed before a hard cut. + */ +PROJECTM_EXPORT double projectm_get_hard_cut_duration(projectm_handle instance); + +/** + * @brief Enables or disables hard cuts. + * + * Even if enabled, the hard cut duration must be set to a value lower than the preset duration + * to work properly. + * + * @param instance The projectM instance handle. + * @param enabled True to enable hard cuts, false to disable. + */ +PROJECTM_EXPORT void projectm_set_hard_cut_enabled(projectm_handle instance, bool enabled); + +/** + * @brief Returns whether hard cuts are enabled or not. + * @param instance The projectM instance handle. + * @return True if hard cuts are enabled, false otherwise. + */ +PROJECTM_EXPORT bool projectm_get_hard_cut_enabled(projectm_handle instance); + +/** + * @brief Sets the hard cut volume sensitivity. + * + * The beat detection volume difference that must be surpassed to trigger a hard cut. + * + * @param instance The projectM instance handle. + * @param sensitivity The volume threshold that triggers a hard cut if surpassed. + */ +PROJECTM_EXPORT void projectm_set_hard_cut_sensitivity(projectm_handle instance, float sensitivity); + +/** + * @brief Returns the current hard cut sensitivity. + * @param instance The projectM instance handle. + * @return The current hard cut sensitivity. + */ +PROJECTM_EXPORT float projectm_get_hard_cut_sensitivity(projectm_handle instance); + +/** + * @brief Sets the time in seconds for a soft transition between two presets. + * + * During a soft cut, both presets are rendered and slowly transitioned from one + * to the other. + * + * @param instance The projectM instance handle. + * @param seconds Time in seconds it takes to smoothly transition from one preset to another. + */ +PROJECTM_EXPORT void projectm_set_soft_cut_duration(projectm_handle instance, double seconds); + +/** + * @brief Returns the time in seconds for a soft transition between two presets. + * @param instance The projectM instance handle. + * @return Time in seconds it takes to smoothly transition from one preset to another. + */ +PROJECTM_EXPORT double projectm_get_soft_cut_duration(projectm_handle instance); + +/** + * @brief Sets the preset display duration before switching to the next using a soft cut. + * + * This can be considered as the maximum time a preset is displayed. If this time is reached, + * a smooth cut will be initiated. A hard cut, if any, will always happen before this time. + * + * @param instance The projectM instance handle. + * @param seconds The number of seconds a preset will be displayed before the next is shown. + */ +PROJECTM_EXPORT void projectm_set_preset_duration(projectm_handle instance, double seconds); + +/** + * @brief Returns the preset display duration before switching to the next using a soft cut. + * + * This can be considered as the maximum time a preset is displayed. If this time is reached, + * a smooth cut will be initiated. A hard cut, if any, will always happen before this time. + * + * @param instance The projectM instance handle. + * @return The currently set preset display duration in seconds. + */ +PROJECTM_EXPORT double projectm_get_preset_duration(projectm_handle instance); + +/** + * @brief Sets the per-pixel equation mesh size in units. + * Will internally be clamped to [8,300] in each axis. If any dimension is set to an odd value, it will be incremented by 1 + * so only multiples of two are used. + * @param instance The projectM instance handle. + * @param width The new width of the mesh. + * @param height The new height of the mesh. + */ +PROJECTM_EXPORT void projectm_set_mesh_size(projectm_handle instance, size_t width, size_t height); + +/** + * @brief Returns the per-pixel equation mesh size in units. + * @param instance The projectM instance handle. + * @param width The width of the mesh. + * @param height The height of the mesh. + */ +PROJECTM_EXPORT void projectm_get_mesh_size(projectm_handle instance, size_t* width, size_t* height); + +/** + * @brief Sets the current/average frames per second. + * + * Applications running projectM should UpdateMeshSize this value regularly and set it to the calculated + * (and possibly averaged) FPS value the output rendered with. The value is passed on to presets, + * which may choose to use it for calculations. It is not used in any other way by the library. + * + * @param instance The projectM instance handle. + * @param fps The current FPS value projectM is running with. + */ +PROJECTM_EXPORT void projectm_set_fps(projectm_handle instance, int32_t fps); + +/** + * @brief Returns the current/average frames per second. + * + * This value needs to be set by the application. If it wasn't set, a default value of 60 is used. + * + * @param instance The projectM instance handle. + * @return The current/average frames per second. + */ +PROJECTM_EXPORT int32_t projectm_get_fps(projectm_handle instance); + +/** + * @brief Enabled or disables aspect ratio correction in presets that support it. + * + * This sets a flag presets can use to aspect-correct rendered shapes, which otherwise would + * be distorted if the viewport isn't exactly square. + * + * @param instance The projectM instance handle. + * @param enabled True to enable aspect correction, false to disable it. + */ +PROJECTM_EXPORT void projectm_set_aspect_correction(projectm_handle instance, bool enabled); + +/** + * @brief Returns whether aspect ratio correction is enabled or not. + * @param instance The projectM instance handle. + * @return True if aspect ratio correction is enabled, false otherwise. + */ +PROJECTM_EXPORT bool projectm_get_aspect_correction(projectm_handle instance); + +/** + * @brief Sets the "easter egg" value. + * + *

This doesn't enable any fancy feature, it only influences the randomized display time of presets. It's + * passed as the "sigma" value of the gaussian random number generator used to determine the maximum display time, + * effectively multiplying the generated number of seconds by this amount.

+ * + *

See function sampledPresetDuration() of the TimeKeeper class on how it is used.

+ * + * @param instance The projectM instance handle. + * @param value The new "easter egg" value. Must be greater than zero, otherwise a default sigma value of 1.0 will be used. + */ +PROJECTM_EXPORT void projectm_set_easter_egg(projectm_handle instance, float value); + +/** + * @brief Returns the current "easter egg" value. + * @param instance The projectM instance handle. + * @return The current "easter egg" value. + */ +PROJECTM_EXPORT float projectm_get_easter_egg(projectm_handle instance); + +/** + * @brief Locks or unlocks the current preset. + * + * Locking effectively disables automatic preset transitions, both hard and soft cuts. Programmatic + * preset switches will still be executed. + * + * @param instance The projectM instance handle. + * @param lock True to lock the current preset, false to enable automatic transitions. + */ +PROJECTM_EXPORT void projectm_set_preset_locked(projectm_handle instance, bool lock); + +/** + * @brief Returns whether the current preset is locked or not. + * @param instance The projectM instance handle. + * @return True if the preset lock is enabled, false otherwise. + */ +PROJECTM_EXPORT bool projectm_get_preset_locked(projectm_handle instance); + +/** + * @brief Sets the current viewport size in pixels. + * + * Calling this function will reset the OpenGL renderer. + * + * @param instance The projectM instance handle. + * @param width New viewport width in pixels. + * @param height New viewport height in pixels. + */ +PROJECTM_EXPORT void projectm_set_window_size(projectm_handle instance, size_t width, size_t height); + +/** + * @brief Returns the current viewport size in pixels. + * @param instance The projectM instance handle. + * @param width Valid pointer to a size_t variable that will receive the window width value. + * @param height Valid pointer to a size_t variable that will receive the window height value. + */ +PROJECTM_EXPORT void projectm_get_window_size(projectm_handle instance, size_t* width, size_t* height); + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/ThirdParty/libprojectM/include/projectM-4/playlist.h b/ThirdParty/libprojectM/include/projectM-4/playlist.h new file mode 100644 index 000000000..54eb87d06 --- /dev/null +++ b/ThirdParty/libprojectM/include/projectM-4/playlist.h @@ -0,0 +1,34 @@ +/** + * @file playlist.h + * @copyright 2003-2023 projectM Team + * @brief Optional playlist API for libprojectM. + * + * projectM -- Milkdrop-esque visualisation SDK + * Copyright (C)2003-2023 projectM Team + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * See 'LICENSE.txt' included within this release + * + */ + +#pragma once + +#include "projectM-4/playlist_callbacks.h" +#include "projectM-4/playlist_core.h" +#include "projectM-4/playlist_filter.h" +#include "projectM-4/playlist_items.h" +#include "projectM-4/playlist_memory.h" +#include "projectM-4/playlist_playback.h" +#include "projectM-4/playlist_types.h" diff --git a/ThirdParty/libprojectM/include/projectM-4/playlist_callbacks.h b/ThirdParty/libprojectM/include/projectM-4/playlist_callbacks.h new file mode 100644 index 000000000..5f745ba9f --- /dev/null +++ b/ThirdParty/libprojectM/include/projectM-4/playlist_callbacks.h @@ -0,0 +1,104 @@ +/** + * @file playlist_callbacks.h + * @copyright 2003-2023 projectM Team + * @brief Functions and prototypes for projectM playlist callbacks. + * + * projectM -- Milkdrop-esque visualisation SDK + * Copyright (C)2003-2023 projectM Team + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * See 'LICENSE.txt' included within this release + * + */ + +#pragma once + +#include "projectM-4/playlist_types.h" +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Callback function that is executed on each preset change. + * + * Can be used for example to UpdateMeshSize the application window title. Applications must not + * switch presets inside this callback, as it can lead to infinite recursion. + * + * @param is_hard_cut True if the preset was switched using a hard cut via beat detection. + * @param index The playlist index of the new preset. + * @param user_data A user-defined data pointer that was provided when registering the callback, + * e.g. context information. + */ +typedef void (*projectm_playlist_preset_switched_event)(bool is_hard_cut, unsigned int index, + void* user_data); + +/** + * @brief Callback function that is executed if a preset change failed too often. + * + * Similar to the projectM API function, but will only be called if the preset switch failed + * multiple times in a row, e.g. due to missing files or broken presets. The application should + * decide what action to take. + * + * @note Do NOT call any functions that switch presets inside the callback, at it might + * lead to infinite recursion and thus a stack overflow! + * @note The message pointer is only valid inside the callback. Make a copy if it need to be + * retained for later use. + * @param preset_filename The filename of the failed preset. + * @param message The last error message. + * @param user_data A user-defined data pointer that was provided when registering the callback, + * e.g. context information. + */ +typedef void (*projectm_playlist_preset_switch_failed_event)(const char* preset_filename, + const char* message, void* user_data); + + +/** + * @brief Sets a callback function that will be called when a preset changes. + * + * Only one callback can be registered per playlist instance. To remove the callback, use NULL. + * + * @param instance The playlist manager instance. + * @param callback A pointer to the callback function. + * @param user_data A pointer to any data that will be sent back in the callback, e.g. context + * information. + */ +PROJECTM_PLAYLIST_EXPORT void projectm_playlist_set_preset_switched_event_callback(projectm_playlist_handle instance, + projectm_playlist_preset_switched_event callback, + void* user_data); + +/** + * @brief Sets a callback function that will be called when a preset change failed. + * + * Only one callback can be registered per projectM instance. To remove the callback, use NULL. + * + * If the application want to receive projectM's analogous callback directly, use the + * projectm_set_preset_switch_failed_event_callback() function after calling + * projectm_playlist_create() or projectm_playlist_connect(), respectively, as these will both + * override the callback set in projectM. + * + * @param instance The playlist manager instance. + * @param callback A pointer to the callback function. + * @param user_data A pointer to any data that will be sent back in the callback, e.g. context + * information. + */ +PROJECTM_PLAYLIST_EXPORT void projectm_playlist_set_preset_switch_failed_event_callback(projectm_playlist_handle instance, + projectm_playlist_preset_switch_failed_event callback, + void* user_data); + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/ThirdParty/libprojectM/include/projectM-4/playlist_core.h b/ThirdParty/libprojectM/include/projectM-4/playlist_core.h new file mode 100644 index 000000000..fe0b49c1a --- /dev/null +++ b/ThirdParty/libprojectM/include/projectM-4/playlist_core.h @@ -0,0 +1,79 @@ +/** + * @file playlist_core.h + * @copyright 2003-2023 projectM Team + * @brief Core functions to instantiate, destroy and connect a projectM playlist. + * + * projectM -- Milkdrop-esque visualisation SDK + * Copyright (C)2003-2023 projectM Team + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * See 'LICENSE.txt' included within this release + * + */ + +#pragma once + +#include "projectM-4/types.h" +#include "projectM-4/playlist_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Creates a playlist manager for the given projectM instance + * + * Only one active playlist manager is supported per projectM instance. If multiple playlists use + * the same projectM instance, only the last created playlist manager will receive preset change + * callbacks from the projectM instance. + * + * To switch to another playlist, use the projectm_playlist_connect() method. + * + * @param projectm_instance The projectM instance to connect to. Can be a null pointer to leave the newly + * created playlist instance unconnected. + * @return An opaque pointer to the newly created playlist manager instance. Null if creation failed. + */ +PROJECTM_PLAYLIST_EXPORT projectm_playlist_handle projectm_playlist_create(projectm_handle projectm_instance); + +/** + * @brief Destroys a previously created playlist manager. + * + * If the playlist manager is currently connected to a projectM instance, it will be disconnected. + * + * @param instance The playlist manager instance to destroy. + */ +PROJECTM_PLAYLIST_EXPORT void projectm_playlist_destroy(projectm_playlist_handle instance); + +/** + * @brief Connects the playlist manager to a projectM instance. + * + * Sets or removes the preset switch callbacks and stores the projectM instance handle for use with + * manual preset switches via the playlist API. + * + * When switching between multiple playlist managers, first call this method on the last used + * playlist manager with a null pointer for the projectM instance, then call this method with the + * actual projectM instance on the playlist manager that should be activated. It is also safe to + * call projectm_playlist_connect() with a null projectM handle on all playlist manager instances + * before activating a single one with a valid, non-null projectM handle. + * + * @param instance The playlist manager instance. + * @param projectm_instance The projectM instance to connect to. Can be a null pointer to remove + * an existing binding and clear the projectM preset switch callback. + */ +PROJECTM_PLAYLIST_EXPORT void projectm_playlist_connect(projectm_playlist_handle instance, projectm_handle projectm_instance); + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/ThirdParty/libprojectM/include/projectM-4/playlist_filter.h b/ThirdParty/libprojectM/include/projectM-4/playlist_filter.h new file mode 100644 index 000000000..2b098d8aa --- /dev/null +++ b/ThirdParty/libprojectM/include/projectM-4/playlist_filter.h @@ -0,0 +1,99 @@ +/** + * @file playlist_filter.h + * @copyright 2003-2023 projectM Team + * @brief Playlist filter functions. + * + * projectM -- Milkdrop-esque visualisation SDK + * Copyright (C)2003-2023 projectM Team + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * See 'LICENSE.txt' included within this release + * + */ + +#pragma once + +#include "projectM-4/playlist_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Sets a new filter list. + * + *

Does not immediately apply the new list to an existing playlist, only newly added files + * will be affected. If you need to filter the existing playlist after calling this method, + * additionally call projectm_playlist_apply_filter() afterwards.

+ * + *

The filter list consists of simple globbing expressions similar to the .gitignore syntax:

+ * + *
    + *
  • ?: Matches any single character except /.
  • + *
  • *: Matches 0 or more characters except /.
  • + *
  • /: When used at the begin of a glob, matches if + * pathname has no path separator.
  • + *
  • **‍/: Matches 0 or more directories.
  • + *
  • /‍**: When at the end of the glob, matches everything after the /.
  • + *
+ * + *

In globbing expressions, \\ can be used as path separator instead of /. The backslash can't + * be used to escape globbing patterns, so matching literal * and ? in filenames is not possible. + * This is not a huge issue as Windows doesn't allow those characters in filenames and Milkdrop + * files originate from the Windows world. Character classes like "[0-9]" are also not supported to + * keep the syntax simple.

+ * + *

Each line can be prefixed with either + or - to either include files matching the pattern + * or excluding them. Any other character is not interpreted as a prefix and the filter line is + * matching as an exclude filter. To match a literal + or - at the beginning, add the appropriate + * prefix in front. Empty filters never match anything, even if the filename is empty.

+ * + *

The filter list is checked in order. The first pattern that matches the filename determines + * the filter result (include or exclude). If no pattern matches, the file is included. In the case + * that a default exclude action is required, add a "-/‍**" filter at the end of the list.

+ * + * @param instance The playlist manager instance. + * @param filter_list An array with filter strings. + * @param count The size of the filter array. + */ +PROJECTM_PLAYLIST_EXPORT void projectm_playlist_set_filter(projectm_playlist_handle instance, const char** filter_list, + size_t count); + +/** + * @brief Returns the current filter list. + * + * Always call projectm_playlist_free_string_array() on the returned pointer if the data is + * no longer needed. + * + * @param instance The playlist manager instance. + * @param[out] count The size of the filter array. + * @return An array with filter strings. + */ +PROJECTM_PLAYLIST_EXPORT char** projectm_playlist_get_filter(projectm_playlist_handle instance, size_t* count); + +/** + * @brief Applies the current filter list to the existing playlist. + * + * Note this function only removes items. Previously filtered items are not added again. If items + * were removed, the playback history is cleared. + * + * @param instance The playlist manager instance. + * @return The number of removed items. + */ +PROJECTM_PLAYLIST_EXPORT size_t projectm_playlist_apply_filter(projectm_playlist_handle instance); + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/ThirdParty/libprojectM/include/projectM-4/playlist_items.h b/ThirdParty/libprojectM/include/projectM-4/playlist_items.h new file mode 100644 index 000000000..7f0fdd99a --- /dev/null +++ b/ThirdParty/libprojectM/include/projectM-4/playlist_items.h @@ -0,0 +1,241 @@ +/** + * @file playlist_items.h + * @copyright 2003-2023 projectM Team + * @brief Playlist item management functions. + * + * projectM -- Milkdrop-esque visualisation SDK + * Copyright (C)2003-2023 projectM Team + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * See 'LICENSE.txt' included within this release + * + */ + +#pragma once + +#include "projectM-4/playlist_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Returns the number of presets in the current playlist. + * @param instance The playlist manager instance. + * @return The number of presets in the current playlist. + */ +PROJECTM_PLAYLIST_EXPORT uint32_t projectm_playlist_size(projectm_playlist_handle instance); + +/** + * @brief Clears the playlist. + * @param instance The playlist manager instance to clear. + */ +PROJECTM_PLAYLIST_EXPORT void projectm_playlist_clear(projectm_playlist_handle instance); + +/** + * @brief Returns a list of preset files inside the given range of the current playlist, in order. + * + * This function can be used to return the whole playlist to save it to a file, or just a part of + * it for use in virtual lists. If less elements than given in @a count are available, only the + * remainder of items after the starting index are returned. If the starting index equals or exceeds + * the playlist size, an empty list is returned. + * + * @note Call projectm_playlist_free_string_array() when you're done using the list. + * @note Ideally, don't rely on the value provided as count to iterate over the filenames. + * Instead, look for the terminating null pointer to abort the loop. + * @param instance The playlist manager instance. + * @param start The zero-based starting index of the range to return. + * @param count The maximum number if items to return. + * @return A pointer to a list of char pointers, each containing a single preset. The last entry + * is denoted by a null pointer. + */ +PROJECTM_PLAYLIST_EXPORT char** projectm_playlist_items(projectm_playlist_handle instance, uint32_t start, uint32_t count); + +/** + * @brief Returns the name of a preset at the given index in the current playlist. + * @note Call projectm_playlist_free_string() when you're done using the return value. + * @note If you need to retrieve a major part of playlist filenames, use projectm_playlist_items() + * instead. + * @param instance The playlist manager instance. + * @param index The index to retrieve the filename for. + * @return The filename of the requested preset, or NULL if the index was out of bounds or the + * playlist is empty. + */ +PROJECTM_PLAYLIST_EXPORT char* projectm_playlist_item(projectm_playlist_handle instance, uint32_t index); + +/** + * @brief Appends presets from the given path to the end of the current playlist. + * + * This method will scan the given path for files with a ".milk" extension and add these to the + * playlist. + * + * Symbolic links are not followed. + * + * @param instance The playlist manager instance. + * @param path A local filesystem path to scan for presets. + * @param recurse_subdirs If true, subdirectories of the given path will also be scanned. If false, + * only the exact path given is searched for presets. + * @param allow_duplicates If true, files found will always be added. If false, only files are + * added that do not already exist in the current playlist. + * @return The number of files added. 0 may indicate issues scanning the path. + */ +PROJECTM_PLAYLIST_EXPORT uint32_t projectm_playlist_add_path(projectm_playlist_handle instance, const char* path, + bool recurse_subdirs, bool allow_duplicates); + + +/** + * @brief Inserts presets from the given path to the end of the current playlist. + * + * This method will scan the given path for files with a ".milk" extension and add these to the + * playlist. + * + * Symbolic links are not followed. + * + * @param instance The playlist manager instance. + * @param path A local filesystem path to scan for presets. + * @param index The index to insert the presets at. If it exceeds the playlist size, the presets are +* added at the end of the playlist. + * @param recurse_subdirs If true, subdirectories of the given path will also be scanned. If false, + * only the exact path given is searched for presets. + * @param allow_duplicates If true, files found will always be added. If false, only files are + * added that do not already exist in the current playlist. + * @return The number of files added. 0 may indicate issues scanning the path. + */ +PROJECTM_PLAYLIST_EXPORT uint32_t projectm_playlist_insert_path(projectm_playlist_handle instance, const char* path, + uint32_t index, bool recurse_subdirs, bool allow_duplicates); + +/** + * @brief Adds a single preset to the end of the playlist. + * + * @note The file is not checked for existence or for being readable. + * + * @param instance The playlist manager instance. + * @param filename A local preset filename. + * @param allow_duplicates If true, the preset filename will always be added. If false, the preset + * is only added to the playlist if the exact filename doesn't exist in the + * current playlist. + * @return True if the file was added to the playlist, false if the file was a duplicate and + * allow_duplicates was set to false. + */ +PROJECTM_PLAYLIST_EXPORT bool projectm_playlist_add_preset(projectm_playlist_handle instance, const char* filename, + bool allow_duplicates); + +/** + * @brief Adds a single preset to the playlist at the specified position. + * + * To always add a file at the end of the playlist, use projectm_playlist_add_preset() as it is + * performs better. + * + * @note The file is not checked for existence or for being readable. + * + * @param instance The playlist manager instance. + * @param filename A local preset filename. + * @param index The index to insert the preset at. If it exceeds the playlist size, the preset is + * added at the end of the playlist. + * @param allow_duplicates If true, the preset filename will always be added. If false, the preset + * is only added to the playlist if the exact filename doesn't exist in the + * current playlist. + * @return True if the file was added to the playlist, false if the file was a duplicate and + * allow_duplicates was set to false. + */ +PROJECTM_PLAYLIST_EXPORT bool projectm_playlist_insert_preset(projectm_playlist_handle instance, const char* filename, + uint32_t index, bool allow_duplicates); + +/** + * @brief Adds a list of presets to the end of the playlist. + * + * @note The files are not checked for existence or for being readable. + * + * @param instance The playlist manager instance. + * @param filenames A list of local preset filenames. + * @param count The number of files in the list. + * @param allow_duplicates If true, the preset filenames will always be added. If false, a preset + * is only added to the playlist if the exact filename doesn't exist in the + * current playlist. + * @return The number of files added to the playlist. Ranges between 0 and count. + */ +PROJECTM_PLAYLIST_EXPORT uint32_t projectm_playlist_add_presets(projectm_playlist_handle instance, const char** filenames, + uint32_t count, bool allow_duplicates); + +/** + * @brief Adds a single preset to the playlist at the specified position. + * + * To always add a file at the end of the playlist, use projectm_playlist_add_preset() as it is + * performs better. + * + * @note The files are not checked for existence or for being readable. + * + * @param instance The playlist manager instance. + * @param filenames A list of local preset filenames. + * @param count The number of files in the list. + * @param index The index to insert the presets at. If it exceeds the playlist size, the presets are + * added at the end of the playlist. + * @param allow_duplicates If true, the preset filenames will always be added. If false, a preset + * is only added to the playlist if the exact filename doesn't exist in the + * current playlist. + * @return The number of files added to the playlist. Ranges between 0 and count. + */ +PROJECTM_PLAYLIST_EXPORT uint32_t projectm_playlist_insert_presets(projectm_playlist_handle instance, const char** filenames, + uint32_t count, unsigned int index, bool allow_duplicates); + +/** + * @brief Removes a single preset from the playlist at the specified position. + * + * @param instance The playlist manager instance. + * @param index The preset index to remove. If it exceeds the playlist size, no preset will be + * removed. + * @return True if the preset was removed from the playlist, false if the index was out of range. + */ +PROJECTM_PLAYLIST_EXPORT bool projectm_playlist_remove_preset(projectm_playlist_handle instance, uint32_t index); + +/** + * @brief Removes a number of presets from the playlist from the specified position. + * + * @param instance The playlist manager instance. + * @param index The first preset index to remove. If it exceeds the playlist size, no preset will be + * removed. + * @param count The number of presets to remove from the given index. + * @return The number of presets removed from the playlist. + */ +PROJECTM_PLAYLIST_EXPORT uint32_t projectm_playlist_remove_presets(projectm_playlist_handle instance, uint32_t index, + uint32_t count); + +/** + * @brief Sorts part or the whole playlist according to the given predicate and order. + * + * It is safe to provide values in start_index and count that will exceed the number of items + * in the playlist. Only items that fall into an existing index range are sorted. If start_index + * is equal to or larger than the playlist size, no items are sorted. If start_index is inside the + * playlist, but adding count results in an index outside the playlist, items until the end are + * sorted. + * + * Sort order is lexicographical for both predicates and case-sensitive. + * + * If invalid values are provides as predicate or order, the defaults as mentioned in the parameter + * description are used. + * + * @param instance The playlist manager instance. + * @param start_index The starting index to begin sorting at. + * @param count The number of items, beginning at start_index, to sort. + * @param predicate The predicate to use for sorting. Default is SORT_PREDICATE_FULL_PATH. + * @param order The sort order. Default is SORT_ORDER_ASCENDING. + */ +PROJECTM_PLAYLIST_EXPORT void projectm_playlist_sort(projectm_playlist_handle instance, uint32_t start_index, uint32_t count, + projectm_playlist_sort_predicate predicate, projectm_playlist_sort_order order); + +#ifdef __cplusplus +} // extern "C" +#endif + diff --git a/ThirdParty/libprojectM/include/projectM-4/playlist_memory.h b/ThirdParty/libprojectM/include/projectM-4/playlist_memory.h new file mode 100644 index 000000000..e8fd4ba2d --- /dev/null +++ b/ThirdParty/libprojectM/include/projectM-4/playlist_memory.h @@ -0,0 +1,56 @@ +/** + * @file playlist_memory.h + * @copyright 2003-2023 projectM Team + * @brief Memory allocation/deallocation helpers. + * + * projectM -- Milkdrop-esque visualisation SDK + * Copyright (C)2003-2023 projectM Team + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * See 'LICENSE.txt' included within this release + * + */ + +#pragma once + +#include "projectM-4/playlist_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Frees a char pointer returned by any of the playlist API functions. + * + * Please only use this function with char pointers returned by the playlist library, and don't use + * other projectM memory management functions with pointers returned by the playlist library. + * + * @param string A pointer to a string that should be freed. + */ +PROJECTM_PLAYLIST_EXPORT void projectm_playlist_free_string(char* string); + +/** + * @brief Frees a string array returned by any of the playlist API functions. + * + * Please only use this function with pointers returned by the playlist library, and don't use + * other projectM memory management functions with pointers returned by the playlist library. + * + * @param array The pointer to the array of strings that should be freed. + */ +PROJECTM_PLAYLIST_EXPORT void projectm_playlist_free_string_array(char** array); + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/ThirdParty/libprojectM/include/projectM-4/playlist_playback.h b/ThirdParty/libprojectM/include/projectM-4/playlist_playback.h new file mode 100644 index 000000000..0f3507338 --- /dev/null +++ b/ThirdParty/libprojectM/include/projectM-4/playlist_playback.h @@ -0,0 +1,136 @@ +/** + * @file playlist_playback.h + * @copyright 2003-2023 projectM Team + * @brief Playback control functions. + * + * projectM -- Milkdrop-esque visualisation SDK + * Copyright (C)2003-2023 projectM Team + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * See 'LICENSE.txt' included within this release + * + */ + +#pragma once + +#include "projectM-4/playlist_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Enable or disable shuffle mode. + * @param instance The playlist manager instance. + * @param shuffle True to enable random shuffling, false to play presets in playlist order. + */ +PROJECTM_PLAYLIST_EXPORT void projectm_playlist_set_shuffle(projectm_playlist_handle instance, bool shuffle); + +/** + * @brief Retrieves the current state of shuffle mode. + * @param instance The playlist manager instance. + * @return True if shuffle mode is enabled, false otherwise. + */ +PROJECTM_PLAYLIST_EXPORT bool projectm_playlist_get_shuffle(projectm_playlist_handle instance); + +/** + * @brief Sets the number of retries after failed preset switches. + * @note Don't set this value too high, as each retry is done recursively. + * @param instance The playlist manager instance. + * @param retry_count The number of retries after failed preset switches. Default is 5. Set to 0 + * to simply forward the failure event from projectM. + */ +PROJECTM_PLAYLIST_EXPORT void projectm_playlist_set_retry_count(projectm_playlist_handle instance, uint32_t retry_count); + +/** + * @brief Returns the number of retries after failed preset switches. + * @param instance The playlist manager instance. + * @return The number of retries after failed preset switches. + */ +PROJECTM_PLAYLIST_EXPORT uint32_t projectm_playlist_get_retry_count(projectm_playlist_handle instance); + +/** + * @brief Plays the preset at the requested playlist position and returns the actual playlist index. + * + * If the requested position is out of bounds, the returned position will wrap to 0, effectively + * repeating the playlist as if shuffle was disabled. It has no effect if the playlist is empty. + * + * This method ignores the shuffle setting and will always jump to the requested index, given it is + * within playlist bounds. + * + * @param instance The playlist manager instance. + * @param new_position The new position to jump to. + * @param hard_cut If true, the preset transition is instant. If true, a smooth transition is played. + * @return The new playlist position. If the playlist is empty, 0 will be returned. + */ +PROJECTM_PLAYLIST_EXPORT uint32_t projectm_playlist_set_position(projectm_playlist_handle instance, uint32_t new_position, + bool hard_cut); + +/** + * @brief Returns the current playlist position. + * @param instance The playlist manager instance. + * @return The current playlist position. If the playlist is empty, 0 will be returned. + */ +PROJECTM_PLAYLIST_EXPORT uint32_t projectm_playlist_get_position(projectm_playlist_handle instance); + +/** + * @brief Plays the next playlist item and returns the index of the new preset. + * + * If shuffle is on, it will select a random preset, otherwise the next in the playlist. If the + * end of the playlist is reached in continuous mode, it will wrap back to 0. + * + * The old playlist item is added to the history. + * + * @param instance The playlist manager instance. + * @param hard_cut If true, the preset transition is instant. If true, a smooth transition is played. + * @return The new playlist position. If the playlist is empty, 0 will be returned. + */ +PROJECTM_PLAYLIST_EXPORT uint32_t projectm_playlist_play_next(projectm_playlist_handle instance, bool hard_cut); + +/** + * @brief Plays the previous playlist item and returns the index of the new preset. + * + * If shuffle is on, it will select a random preset, otherwise the next in the playlist. If the + * end of the playlist is reached in continuous mode, it will wrap back to 0. + * + * The old playlist item is added to the history. + * + * @param instance The playlist manager instance. + * @param hard_cut If true, the preset transition is instant. If true, a smooth transition is played. + * @return The new playlist position. If the playlist is empty, 0 will be returned. + */ +PROJECTM_PLAYLIST_EXPORT uint32_t projectm_playlist_play_previous(projectm_playlist_handle instance, bool hard_cut); + +/** + * @brief Plays the last preset played in the history and returns the index of the preset. + * + * The history keeps track of the last 1000 presets and will go back in the history. The + * playback history will be cleared whenever the playlist items are changed. + * + * If the history is empty, this call behaves identical to projectm_playlist_play_previous(), + * but the item is not added to the history. + * + * Presets which failed to load are not recorded in the history and thus will be skipped when + * calling this method. + * + * @param instance The playlist manager instance. + * @param hard_cut If true, the preset transition is instant. If true, a smooth transition is played. + * @return The new playlist position. If the playlist is empty, 0 will be returned. + */ +PROJECTM_PLAYLIST_EXPORT uint32_t projectm_playlist_play_last(projectm_playlist_handle instance, bool hard_cut); + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/ThirdParty/libprojectM/include/projectM-4/playlist_types.h b/ThirdParty/libprojectM/include/projectM-4/playlist_types.h new file mode 100644 index 000000000..34af58f19 --- /dev/null +++ b/ThirdParty/libprojectM/include/projectM-4/playlist_types.h @@ -0,0 +1,58 @@ +/** + * @file playlist_types.h + * @copyright 2003-2023 projectM Team + * @brief Types and enumerations used in the playlist API headers. + * + * projectM -- Milkdrop-esque visualisation SDK + * Copyright (C)2003-2023 projectM Team + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * See 'LICENSE.txt' included within this release + * + */ + +#pragma once + +#include "projectM-4/projectM_playlist_export.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct projectm_playlist; //!< Opaque projectM playlist instance type. +typedef struct projectm_playlist* projectm_playlist_handle; //!< A pointer to the opaque projectM playlist instance. + +/** + * Sort predicate for playlist sorting. + */ +typedef enum +{ + SORT_PREDICATE_FULL_PATH, //!< Sort by full path name + SORT_PREDICATE_FILENAME_ONLY //!< Sort only by preset filename +} projectm_playlist_sort_predicate; + + +/** + * Sort order for playlist sorting. + */ +typedef enum +{ + SORT_ORDER_ASCENDING, //!< Sort in alphabetically ascending order. + SORT_ORDER_DESCENDING //!< Sort in alphabetically descending order. +} projectm_playlist_sort_order; + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/ThirdParty/libprojectM/include/projectM-4/projectM.h b/ThirdParty/libprojectM/include/projectM-4/projectM.h new file mode 100644 index 000000000..72a31ce48 --- /dev/null +++ b/ThirdParty/libprojectM/include/projectM-4/projectM.h @@ -0,0 +1,35 @@ +/** + * @file projectM.h + * @copyright 2003-2023 projectM Team + * @brief Convenience include file that includes all other API headers. + * + * projectM -- Milkdrop-esque visualisation SDK + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * See 'LICENSE.txt' included within this release + * + */ + +#pragma once + +#include "projectM-4/audio.h" +#include "projectM-4/callbacks.h" +#include "projectM-4/core.h" +#include "projectM-4/debug.h" +#include "projectM-4/memory.h" +#include "projectM-4/parameters.h" +#include "projectM-4/render_opengl.h" +#include "projectM-4/touch.h" +#include "projectM-4/version.h" diff --git a/ThirdParty/libprojectM/include/projectM-4/projectM_export.h b/ThirdParty/libprojectM/include/projectM-4/projectM_export.h new file mode 100644 index 000000000..d8d9bf00e --- /dev/null +++ b/ThirdParty/libprojectM/include/projectM-4/projectM_export.h @@ -0,0 +1,42 @@ + +#ifndef PROJECTM_EXPORT_H +#define PROJECTM_EXPORT_H + +#ifdef PROJECTM_STATIC_DEFINE +# define PROJECTM_EXPORT +# define PROJECTM_NO_EXPORT +#else +# ifndef PROJECTM_EXPORT +# ifdef projectM_api_EXPORTS + /* We are building this library */ +# define PROJECTM_EXPORT __attribute__((visibility("default"))) +# else + /* We are using this library */ +# define PROJECTM_EXPORT __attribute__((visibility("default"))) +# endif +# endif + +# ifndef PROJECTM_NO_EXPORT +# define PROJECTM_NO_EXPORT __attribute__((visibility("hidden"))) +# endif +#endif + +#ifndef PROJECTM_DEPRECATED +# define PROJECTM_DEPRECATED __attribute__ ((__deprecated__)) +#endif + +#ifndef PROJECTM_DEPRECATED_EXPORT +# define PROJECTM_DEPRECATED_EXPORT PROJECTM_EXPORT PROJECTM_DEPRECATED +#endif + +#ifndef PROJECTM_DEPRECATED_NO_EXPORT +# define PROJECTM_DEPRECATED_NO_EXPORT PROJECTM_NO_EXPORT PROJECTM_DEPRECATED +#endif + +#if 0 /* DEFINE_NO_DEPRECATED */ +# ifndef PROJECTM_NO_DEPRECATED +# define PROJECTM_NO_DEPRECATED +# endif +#endif + +#endif /* PROJECTM_EXPORT_H */ diff --git a/ThirdParty/libprojectM/include/projectM-4/projectM_playlist_export.h b/ThirdParty/libprojectM/include/projectM-4/projectM_playlist_export.h new file mode 100644 index 000000000..0ba4dbdfd --- /dev/null +++ b/ThirdParty/libprojectM/include/projectM-4/projectM_playlist_export.h @@ -0,0 +1,42 @@ + +#ifndef PROJECTM_PLAYLIST_EXPORT_H +#define PROJECTM_PLAYLIST_EXPORT_H + +#ifdef PROJECTM_PLAYLIST_STATIC_DEFINE +# define PROJECTM_PLAYLIST_EXPORT +# define PROJECTM_PLAYLIST_NO_EXPORT +#else +# ifndef PROJECTM_PLAYLIST_EXPORT +# ifdef projectM_playlist_EXPORTS + /* We are building this library */ +# define PROJECTM_PLAYLIST_EXPORT __attribute__((visibility("default"))) +# else + /* We are using this library */ +# define PROJECTM_PLAYLIST_EXPORT __attribute__((visibility("default"))) +# endif +# endif + +# ifndef PROJECTM_PLAYLIST_NO_EXPORT +# define PROJECTM_PLAYLIST_NO_EXPORT __attribute__((visibility("hidden"))) +# endif +#endif + +#ifndef PROJECTM_PLAYLIST_DEPRECATED +# define PROJECTM_PLAYLIST_DEPRECATED __attribute__ ((__deprecated__)) +#endif + +#ifndef PROJECTM_PLAYLIST_DEPRECATED_EXPORT +# define PROJECTM_PLAYLIST_DEPRECATED_EXPORT PROJECTM_PLAYLIST_EXPORT PROJECTM_PLAYLIST_DEPRECATED +#endif + +#ifndef PROJECTM_PLAYLIST_DEPRECATED_NO_EXPORT +# define PROJECTM_PLAYLIST_DEPRECATED_NO_EXPORT PROJECTM_PLAYLIST_NO_EXPORT PROJECTM_PLAYLIST_DEPRECATED +#endif + +#if 0 /* DEFINE_NO_DEPRECATED */ +# ifndef PROJECTM_PLAYLIST_NO_DEPRECATED +# define PROJECTM_PLAYLIST_NO_DEPRECATED +# endif +#endif + +#endif /* PROJECTM_PLAYLIST_EXPORT_H */ diff --git a/ThirdParty/libprojectM/include/projectM-4/render_opengl.h b/ThirdParty/libprojectM/include/projectM-4/render_opengl.h new file mode 100644 index 000000000..0a061f765 --- /dev/null +++ b/ThirdParty/libprojectM/include/projectM-4/render_opengl.h @@ -0,0 +1,46 @@ +/** + * @file render_opengl.h + * @copyright 2003-2023 projectM Team + * @brief Functions to configure and render projectM visuals using OpenGL. + * + * projectM -- Milkdrop-esque visualisation SDK + * Copyright (C)2003-2023 projectM Team + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * See 'LICENSE.txt' included within this release + * + */ + +#pragma once + +#include "projectM-4/types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Renders a single frame. + * + * @note Separate two-pass frame rendering is currently not supported by the C API as it is rarely used + * and also depends on the loaded preset. + * + * @param instance The projectM instance handle. + */ +PROJECTM_EXPORT void projectm_opengl_render_frame(projectm_handle instance); + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/ThirdParty/libprojectM/include/projectM-4/touch.h b/ThirdParty/libprojectM/include/projectM-4/touch.h new file mode 100644 index 000000000..c0f488126 --- /dev/null +++ b/ThirdParty/libprojectM/include/projectM-4/touch.h @@ -0,0 +1,78 @@ +/** + * @file touch.h + * @copyright 2003-2023 projectM Team + * @brief Touch-related functions to add random waveforms. + * + * projectM -- Milkdrop-esque visualisation SDK + * Copyright (C)2003-2023 projectM Team + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * See 'LICENSE.txt' included within this release + * + */ + +#pragma once + +#include "projectM-4/types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Starts a touch event or moves an existing waveform. + * + * This will add or move waveforms in addition to the preset waveforms. If there is an existing waveform + * at the given coordinates, it will be centered on the new coordinates. If there is no waveform, a new one + * will be added. + * + * @param instance The projectM instance handle. + * @param x The x coordinate of the touch event. + * @param y The y coordinate of the touch event. + * @param pressure The amount of pressure applied in a range from 0.0 to 1.0. + * @param touch_type The waveform type that will be rendered on touch. + */ +PROJECTM_EXPORT void projectm_touch(projectm_handle instance, float x, float y, + int pressure, projectm_touch_type touch_type); + +/** + * @brief Centers any waveforms under the coordinates to simulate dragging. + * @param instance The projectM instance handle. + * @param x The x coordinate of the drag. + * @param y the y coordinate of the drag. + * @param pressure The amount of pressure applied in a range from 0.0 to 1.0. + */ +PROJECTM_EXPORT void projectm_touch_drag(projectm_handle instance, float x, float y, int pressure); + +/** + * @brief Removes any additional touch waveforms under the given coordinates. + * @param instance The projectM instance handle. + * @param x The last known x touch coordinate. + * @param y The last known y touch coordinate. + */ +PROJECTM_EXPORT void projectm_touch_destroy(projectm_handle instance, float x, float y); + +/** + * @brief Removes all touch waveforms from the screen. + * + * Preset-defined waveforms will still be displayed. + * + * @param instance The projectM instance handle. + */ +PROJECTM_EXPORT void projectm_touch_destroy_all(projectm_handle instance); + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/ThirdParty/libprojectM/include/projectM-4/types.h b/ThirdParty/libprojectM/include/projectM-4/types.h new file mode 100644 index 000000000..0c5b43137 --- /dev/null +++ b/ThirdParty/libprojectM/include/projectM-4/types.h @@ -0,0 +1,80 @@ +/** + * @file types.h + * @copyright 2003-2023 projectM Team + * @brief Types and enumerations used in the other API headers. + * + * projectM -- Milkdrop-esque visualisation SDK + * Copyright (C)2003-2023 projectM Team + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * See 'LICENSE.txt' included within this release + * + */ + +#pragma once + +#include "projectM-4/projectM_export.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include + +struct projectm; //!< Opaque projectM instance type. +typedef struct projectm* projectm_handle; //!< A pointer to the opaque projectM instance. + +/** + * For specifying audio data format. + */ +typedef enum +{ + PROJECTM_MONO = 1, + PROJECTM_STEREO = 2 +} projectm_channels; + +/** + * Placeholder values that can be used to address channel indices in PCM data arrays. + */ +typedef enum +{ + PROJECTM_CHANNEL_L = 0, //!< Left audio channel. + PROJECTM_CHANNEL_0 = 0, //!< Left audio channel. + PROJECTM_CHANNEL_R = 1, //!< Right audio channel. + PROJECTM_CHANNEL_1 = 1 //!< Right audio channel. +} projectm_pcm_channel; + +/** + * Waveform render types used in the touch start method. + */ +typedef enum +{ + PROJECTM_TOUCH_TYPE_RANDOM, //!< Random waveform type. + PROJECTM_TOUCH_TYPE_CIRCLE, //!< Draws a circular waveform. + PROJECTM_TOUCH_TYPE_RADIAL_BLOB, //!< Draws a radial blob waveform. + PROJECTM_TOUCH_TYPE_BLOB2, //!< Draws a blob-style waveform. + PROJECTM_TOUCH_TYPE_BLOB3, //!< Draws another blob-style waveform. + PROJECTM_TOUCH_TYPE_DERIVATIVE_LINE, //!< Draws a derivative-line waveform. + PROJECTM_TOUCH_TYPE_BLOB5, //!< Draws a five-blob waveform. + PROJECTM_TOUCH_TYPE_LINE, //!< Draws a single-line waveform. + PROJECTM_TOUCH_TYPE_DOUBLE_LINE //!< Draws a double-line waveform. +} projectm_touch_type; + +#ifdef __cplusplus +} // extern "C" +#endif + diff --git a/ThirdParty/libprojectM/include/projectM-4/version.h b/ThirdParty/libprojectM/include/projectM-4/version.h new file mode 100644 index 000000000..e91b57266 --- /dev/null +++ b/ThirdParty/libprojectM/include/projectM-4/version.h @@ -0,0 +1,11 @@ +#pragma once + +#define PROJECTM_VERSION_MAJOR 4 +#define PROJECTM_VERSION_MINOR 1 +#define PROJECTM_VERSION_PATCH 4 + +/* Full version number as a string literal */ +#define PROJECTM_VERSION_STRING "4.1.4" + +/* VCS version number, e.g. Git commit hash */ +#define PROJECTM_VERSION_VCS "Unknown" diff --git a/ThirdParty/libprojectM/subprojects/presets-milkdrop-texture-pack b/ThirdParty/libprojectM/subprojects/presets-milkdrop-texture-pack new file mode 160000 index 000000000..ff8edf2a8 --- /dev/null +++ b/ThirdParty/libprojectM/subprojects/presets-milkdrop-texture-pack @@ -0,0 +1 @@ +Subproject commit ff8edf2a8fa07e55ad562f1af97076526c484f7d diff --git a/ThirdParty/libprojectM/subprojects/presets/presets-cream-of-the-crop b/ThirdParty/libprojectM/subprojects/presets/presets-cream-of-the-crop new file mode 160000 index 000000000..4e0bf9f0c --- /dev/null +++ b/ThirdParty/libprojectM/subprojects/presets/presets-cream-of-the-crop @@ -0,0 +1 @@ +Subproject commit 4e0bf9f0ca92dcdf00b049701e20ef57b1d2c406 diff --git a/ThirdParty/libraries-debug-overlay.tar.xz b/ThirdParty/libraries-debug-overlay.tar.xz index aa6bae347..24ed4b259 100644 Binary files a/ThirdParty/libraries-debug-overlay.tar.xz and b/ThirdParty/libraries-debug-overlay.tar.xz differ diff --git a/ThirdParty/libraries.tar.xz b/ThirdParty/libraries.tar.xz index 23138970b..f4c702fc1 100644 Binary files a/ThirdParty/libraries.tar.xz and b/ThirdParty/libraries.tar.xz differ diff --git a/Visualization/ProjectMView.h b/Visualization/ProjectMView.h new file mode 100644 index 000000000..e20a2da84 --- /dev/null +++ b/Visualization/ProjectMView.h @@ -0,0 +1,25 @@ +// +// ProjectMView.h +// Cog +// +// Created by Christopher Snowhill on 3/11/25. +// + +#ifndef ProjectMView_h +#define ProjectMView_h + +#import + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface ProjectMView : NSOpenGLView + +-(id)initWithFrame:(NSRect)frame; + +@end + +NS_ASSUME_NONNULL_END + +#endif /* ProjectMView_h */ diff --git a/Visualization/ProjectMView.m b/Visualization/ProjectMView.m new file mode 100644 index 000000000..ed4d2a5bb --- /dev/null +++ b/Visualization/ProjectMView.m @@ -0,0 +1,174 @@ +// +// SpectrumViewPM.m +// Cog +// +// Created by Christopher Snowhill on 3/11/25. +// + +#import "ProjectMView.h" + +#import "NSView+Visibility.h" + +#include + +#import + +#import + +#import "Logging.h" + +static void *kProjectMViewContext = &kProjectMViewContext; + +extern NSString *CogPlaybackDidBeginNotificiation; +extern NSString *CogPlaybackDidPauseNotificiation; +extern NSString *CogPlaybackDidResumeNotificiation; +extern NSString *CogPlaybackDidStopNotificiation; + +@implementation ProjectMView { + VisualizationController *visController; + projectm_handle pm; + projectm_playlist_handle pl; + + float visAudio[4096]; + + NSTimer *timer; +} + +- (id)initWithFrame:(NSRect)frame { + NSOpenGLPixelFormatAttribute attr[] = { + NSOpenGLPFAAllowOfflineRenderers, + NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion3_2Core, + kCGLPFASupportsAutomaticGraphicsSwitching, + NSOpenGLPFAColorSize, 24, + NSOpenGLPFAAlphaSize, 8, + NSOpenGLPFAClosestPolicy, + NSOpenGLPFADoubleBuffer, + NSOpenGLPFAAccelerated, + 0 + }; + + NSOpenGLPixelFormat *fmt = [[NSOpenGLPixelFormat alloc] initWithAttributes:attr]; + if(!fmt) { + return nil; + } + + self = [super initWithFrame:frame pixelFormat:fmt]; + if(self) { + self.wantsBestResolutionOpenGLSurface = YES; + + visController = [NSClassFromString(@"VisualizationController") sharedController]; + + timer = [NSTimer timerWithTimeInterval:(1.0 / 60.0) repeats:YES block:^(NSTimer * _Nonnull timer) { + self.needsDisplay = YES; + }]; + [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes]; + } + + return self; +} + +- (void)dealloc { + [timer invalidate]; + timer = nil; + + if(pl) { + projectm_playlist_destroy(pl); + } + if(pm) { + projectm_destroy(pm); + } +} + +static void presetFailed(const char *preset_filename, const char *message, void *user_data) { + NSLog(@"ProjectM preset failed: %s - for reason: %s", preset_filename, message); +} + +- (void)initProjectM { + if(!pm && !pl) { + NSBundle* me = [NSBundle bundleForClass: self.class]; + NSLog(@"main bundle: %@", [me bundlePath]); + NSString* presetsPath = [me pathForResource:@"presets" ofType:nil]; + NSLog(@"presets path %@", presetsPath); + + NSString* texturesPath = [me pathForResource:@"textures" ofType:nil]; + NSLog(@"textures path %@", texturesPath); + + pm = projectm_create(); + if(!pm) { + return; + } + + char *_texturesPath = projectm_alloc_string((int)(strlen([texturesPath UTF8String]) + 1)); + if(!_texturesPath) { + return; + } + strcpy(_texturesPath, [texturesPath UTF8String]); + const char *texturesPaths[1] = { _texturesPath }; + + projectm_set_texture_search_paths(pm, texturesPaths, 1); + + projectm_free_string(_texturesPath); + + NSRect rect = [self.window convertRectToBacking:self.bounds]; + projectm_set_window_size(pm, rect.size.width, rect.size.height); + + projectm_set_fps(pm, 60); + projectm_set_mesh_size(pm, 48, 32); + projectm_set_aspect_correction(pm, true); + projectm_set_preset_locked(pm, false); + + projectm_set_preset_duration(pm, 30.0); + projectm_set_soft_cut_duration(pm, 3.0); + projectm_set_hard_cut_enabled(pm, false); + projectm_set_hard_cut_duration(pm, 20.0); + projectm_set_hard_cut_sensitivity(pm, 1.0); + projectm_set_beat_sensitivity(pm, 1.0); + + pl = projectm_playlist_create(pm); + if(!pl) { + return; + } + + projectm_playlist_set_preset_switch_failed_event_callback(pl, presetFailed, NULL); + + char *_presetsPath = projectm_alloc_string((int)(strlen([presetsPath UTF8String]) + 1)); + if(!_presetsPath) { + return; + } + strcpy(_presetsPath, [presetsPath UTF8String]); + + projectm_playlist_add_path(pl, _presetsPath, true, false); + + projectm_free_string(_presetsPath); + + projectm_playlist_sort(pl, 0, projectm_playlist_size(pl), SORT_PREDICATE_FILENAME_ONLY, SORT_ORDER_ASCENDING); + + projectm_playlist_set_shuffle(pl, true); + } +} + + +- (void)drawRect:(NSRect)dirtyRect { + [[self openGLContext] makeCurrentContext]; + + [self initProjectM]; + + glClearColor(0.0f, 0.0f, 0.0f, 0.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + NSRect rect = [self.window convertRectToBacking:self.bounds]; + projectm_set_window_size(pm, rect.size.width, rect.size.height); + + [self->visController copyVisPCM:&visAudio[0] visFFT:nil latencyOffset:0]; + + size_t maxSamples = projectm_pcm_get_max_samples(); + if(maxSamples > 4096) maxSamples = 4096; + + projectm_pcm_add_float(pm, &visAudio[0], (unsigned int)maxSamples, 1); + projectm_opengl_render_frame(pm); + + [[self openGLContext] flushBuffer]; + [NSOpenGLContext clearCurrentContext]; +} + +@end diff --git a/Visualization/SpectrumViewCG.h b/Visualization/SpectrumViewCG.h index d6731ef2a..347f169c9 100644 --- a/Visualization/SpectrumViewCG.h +++ b/Visualization/SpectrumViewCG.h @@ -14,6 +14,8 @@ NS_ASSUME_NONNULL_BEGIN @interface SpectrumViewCG : NSView @property(nonatomic) BOOL isListening; +- (id)initWithFrame:(NSRect)frame; + - (void)startPlayback; - (void)enableFullView; @end diff --git a/Visualization/SpectrumViewSK.h b/Visualization/SpectrumViewSK.h index 1f6390db3..f147fa77b 100644 --- a/Visualization/SpectrumViewSK.h +++ b/Visualization/SpectrumViewSK.h @@ -19,6 +19,8 @@ NS_ASSUME_NONNULL_BEGIN + (SpectrumViewSK *)createGuardWithFrame:(NSRect)frame; +- (id)initWithFrame:(NSRect)frame; + - (void)enableCameraControl; - (void)startPlayback; @end diff --git a/Visualization/SpectrumWindowController.m b/Visualization/SpectrumWindowController.m index 977db92ed..7545945c7 100644 --- a/Visualization/SpectrumWindowController.m +++ b/Visualization/SpectrumWindowController.m @@ -9,12 +9,14 @@ #import "SpectrumViewSK.h" #import "SpectrumViewCG.h" +#import "ProjectMView.h" static void *kSpectrumWindowContext = &kSpectrumWindowContext; @interface SpectrumWindowController () @property SpectrumViewSK *spectrumViewSK; @property SpectrumViewCG *spectrumViewCG; +@property ProjectMView *projectMView; @end @implementation SpectrumWindowController @@ -29,8 +31,6 @@ static void *kSpectrumWindowContext = &kSpectrumWindowContext; - (void)windowDidLoad { [super windowDidLoad]; - - [self startRunning]; } - (void)dealloc { @@ -53,6 +53,14 @@ static void *kSpectrumWindowContext = &kSpectrumWindowContext; } - (void)startRunning { + if(!self.projectMView) { + NSRect frame = [[self window] frame]; + self.projectMView = [[ProjectMView alloc] initWithFrame:frame]; + if(self.projectMView) { + [[self window] setContentView:self.projectMView]; + } + } +#if 0 if(!self.spectrumViewSK && !self.spectrumViewCG) { NSRect frame = [[self window] frame]; self.spectrumViewSK = [SpectrumViewSK createGuardWithFrame:frame]; @@ -76,12 +84,14 @@ static void *kSpectrumWindowContext = &kSpectrumWindowContext; else if(self.spectrumViewCG) [self.spectrumViewCG startPlayback]; } +#endif } - (void)stopRunning { [[self window] setContentView:nil]; self.spectrumViewSK = nil; self.spectrumViewCG = nil; + self.projectMView = nil; } - (void)windowWillClose:(NSNotification *)notification {