1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450
|
#pragma once
#undef LoadString //undo some junk from a windows define
#include <limits>
#include "SynthGlobals.h"
#include "IDrawableModule.h"
#include "TextEntry.h"
#include "RollingBuffer.h"
#include "NamedMutex.h"
#include "ofxJSONElement.h"
#include "ModuleFactory.h"
#include "LocationZoomer.h"
#include "EffectFactory.h"
#include "ModuleContainer.h"
#include "Minimap.h"
#include <thread>
#ifdef BESPOKE_LINUX
#include <climits>
#endif
namespace juce
{
class AudioDeviceManager;
class AudioFormatManager;
class Component;
class OpenGLContext;
class String;
class MouseInputSource;
class AudioPluginFormatManager;
class KnownPluginList;
}
class IAudioSource;
class IAudioReceiver;
class INoteReceiver;
class MidiDevice;
class Sample;
class PatchCable;
class MidiController;
class NVGcontext;
class QuickSpawnMenu;
class ADSRDisplay;
class UserPrefsEditor;
class Minimap;
class ScriptWarningPopup;
class NoteOutputQueue;
enum LogEventType
{
kLogEventType_Verbose,
kLogEventType_Warning,
kLogEventType_Error
};
class ConsoleListener : public IDrawableModule, public ITextEntryListener
{
public:
void GetModuleDimensions(float& width, float& height) override
{
width = 1;
height = 1;
}
void TextEntryActivated(TextEntry* entry) override;
void TextEntryComplete(TextEntry* entry) override;
bool IsEnabled() const override { return false; }
private:
void DrawModule() override {}
};
class ModularSynth
{
public:
ModularSynth();
virtual ~ModularSynth();
void Setup(juce::AudioDeviceManager* globalAudioDeviceManager, juce::AudioFormatManager* globalAudioFormatManager, juce::Component* mainComponent, juce::OpenGLContext* openGLContext);
void LoadResources(void* nanoVG, void* fontBoundsNanoVG);
void InitIOBuffers(int inputChannelCount, int outputChannelCount);
void Poll();
void Draw(void* vg);
void PostRender();
void Exit();
void Focus();
void KeyPressed(int key, bool isRepeat);
void KeyReleased(int key);
void MouseMoved(int x, int y);
void MouseDragged(int x, int y, int button, const juce::MouseInputSource& source);
void MousePressed(int x, int y, int button, const juce::MouseInputSource& source);
void MouseReleased(int x, int y, int button, const juce::MouseInputSource& source);
void MouseScrolled(float xScroll, float yScroll, bool isSmoothScroll, bool isInvertedScroll, bool canZoomCanvas);
void MouseMagnify(int x, int y, float scaleFactor, const juce::MouseInputSource& source);
void FilesDropped(std::vector<std::string> files, int x, int y);
void AddExtraPoller(IPollable* poller);
void RemoveExtraPoller(IPollable* poller);
void AudioOut(float* const* output, int bufferSize, int nChannels);
void AudioIn(const float* const* input, int bufferSize, int nChannels);
void OnConsoleInput(std::string command = "");
void ClearConsoleInput();
bool IsReady();
bool IsAudioPaused() const { return mAudioPaused; }
void SetAudioPaused(bool paused) { mAudioPaused = paused; }
void AddMidiDevice(MidiDevice* device);
void ArrangeAudioSourceDependencies();
IDrawableModule* SpawnModuleOnTheFly(ModuleFactory::Spawnable spawnable, float x, float y, bool addToContainer = true, std::string name = "");
void SetMoveModule(IDrawableModule* module, float offsetX, float offsetY, bool canStickToCursor);
int GetNumInputChannels() const { return (int)mInputBuffers.size(); }
int GetNumOutputChannels() const { return (int)mOutputBuffers.size(); }
float* GetInputBuffer(int channel);
float* GetOutputBuffer(int channel);
IDrawableModule* FindModule(std::string name, bool fail = false);
IAudioReceiver* FindAudioReceiver(std::string name, bool fail = false);
INoteReceiver* FindNoteReceiver(std::string name, bool fail = false);
IUIControl* FindUIControl(std::string path);
MidiController* FindMidiController(std::string name, bool fail = false);
void MoveToFront(IDrawableModule* module);
bool InMidiMapMode();
void GetAllModules(std::vector<IDrawableModule*>& out) { mModuleContainer.GetAllModules(out); }
void PushModalFocusItem(IDrawableModule* item);
void PopModalFocusItem();
IDrawableModule* GetTopModalFocusItem() const;
std::vector<IDrawableModule*> GetModalFocusItemStack() const { return mModalFocusItemStack; }
bool IsModalFocusItem(IDrawableModule* item) const;
void LogEvent(std::string event, LogEventType type);
void SetNextDrawTooltip(std::string tooltip) { mNextDrawTooltip = tooltip; }
bool LoadLayoutFromFile(std::string jsonFile, bool makeDefaultLayout = true);
bool LoadLayoutFromString(std::string jsonString);
void LoadLayout(ofxJSONElement json);
std::string GetLoadedLayout() const { return mLoadedLayoutPath; }
void ReloadInitialLayout() { mWantReloadInitialLayout = true; }
bool HasFatalError() { return mFatalError != ""; }
void AddLissajousDrawer(IDrawableModule* module) { mLissajousDrawers.push_back(module); }
bool IsLissajousDrawer(IDrawableModule* module) { return VectorContains(module, mLissajousDrawers); }
void GrabSample(ChannelBuffer* data, std::string name, bool window = false, int numBars = -1);
void GrabSample(std::string filePath);
Sample* GetHeldSample() const { return mHeldSample; }
void ClearHeldSample();
float GetRawMouseX() { return mMousePos.x; }
float GetRawMouseY() { return mMousePos.y; }
float GetMouseX(ModuleContainer* context, float rawX = FLT_MAX);
float GetMouseY(ModuleContainer* context, float rawY = FLT_MAX);
void SetMousePosition(ModuleContainer* context, float x, float y);
bool IsMouseButtonHeld(int button) const;
ofVec2f& GetDrawOffset() { return mModuleContainer.GetDrawOffsetRef(); }
void SetDrawOffset(ofVec2f offset) { mModuleContainer.SetDrawOffset(offset); }
const ofRectangle& GetDrawRect() const { return mDrawRect; }
void SetPixelRatio(double ratio) { mPixelRatio = ratio; }
double GetPixelRatio() const { return mPixelRatio; }
long GetFrameCount() { return mFrameCount; }
void SetUIScale(float scale) { mUILayerModuleContainer.SetDrawScale(scale); }
float GetUIScale() { return mUILayerModuleContainer.GetDrawScale(); }
ModuleContainer* GetRootContainer() { return &mModuleContainer; }
ModuleContainer* GetUIContainer() { return &mUILayerModuleContainer; }
bool ShouldShowGridSnap() const;
bool MouseMovedSignificantlySincePressed() const { return mMouseMovedSignificantlySincePressed; }
void ZoomView(float zoomAmount, bool fromMouse);
void SetZoomLevel(float zoomLevel);
void PanView(float x, float y);
void PanTo(float x, float y);
void SetRawSpaceMouseTwist(float twist, bool isUsing)
{
mSpaceMouseInfo.mTwist = twist;
mSpaceMouseInfo.mUsingTwist = isUsing;
}
void SetRawSpaceMouseZoom(float zoom, bool isUsing)
{
mSpaceMouseInfo.mZoom = zoom;
mSpaceMouseInfo.mUsingZoom = isUsing;
}
void SetRawSpaceMousePan(float x, float y, bool isUsing)
{
mSpaceMouseInfo.mPan.set(x, y);
mSpaceMouseInfo.mUsingPan = isUsing;
}
void SetResizeModule(IDrawableModule* module) { mResizeModule = module; }
void SetGroupSelectContext(ModuleContainer* context) { mGroupSelectContext = context; }
bool IsGroupSelecting() const { return mGroupSelectContext != nullptr; }
IDrawableModule* GetMoveModule() { return mMoveModule; }
ModuleFactory* GetModuleFactory() { return &mModuleFactory; }
juce::AudioDeviceManager& GetAudioDeviceManager() { return *mGlobalAudioDeviceManager; }
juce::AudioFormatManager& GetAudioFormatManager() { return *mGlobalAudioFormatManager; }
juce::AudioPluginFormatManager& GetAudioPluginFormatManager() { return *mAudioPluginFormatManager.get(); }
juce::KnownPluginList& GetKnownPluginList() { return *mKnownPluginList.get(); }
juce::Component* GetMainComponent() { return mMainComponent; }
juce::OpenGLContext* GetOpenGLContext() { return mOpenGLContext; }
IDrawableModule* GetLastClickedModule() const;
EffectFactory* GetEffectFactory() { return &mEffectFactory; }
const std::vector<IDrawableModule*>& GetGroupSelectedModules() const { return mGroupSelectedModules; }
bool ShouldAccentuateActiveModules() const;
bool ShouldDimModule(IDrawableModule* module);
LocationZoomer* GetLocationZoomer() { return &mZoomer; }
IDrawableModule* GetModuleAtCursor(int offsetX = 0, int offsetY = 0);
void RegisterPatchCable(PatchCable* cable);
void UnregisterPatchCable(PatchCable* cable);
template <class T>
std::vector<std::string> GetModuleNames() { return mModuleContainer.GetModuleNames<T>(); }
void LockRender(bool lock)
{
if (lock)
{
mRenderLock.lock();
}
else
{
mRenderLock.unlock();
}
}
void UpdateFrameRate(float fps) { mFrameRate = fps; }
float GetFrameRate() const { return mFrameRate; }
std::recursive_mutex& GetRenderLock() { return mRenderLock; }
NamedMutex* GetAudioMutex() { return &mAudioThreadMutex; }
static std::thread::id GetAudioThreadID() { return sAudioThreadId; }
NoteOutputQueue* GetNoteOutputQueue() { return mNoteOutputQueue; }
IDrawableModule* CreateModule(const ofxJSONElement& moduleInfo);
void SetUpModule(IDrawableModule* module, const ofxJSONElement& moduleInfo);
void OnModuleAdded(IDrawableModule* module);
void OnModuleDeleted(IDrawableModule* module);
void AddDynamicModule(IDrawableModule* module);
void ScheduleEnvelopeEditorSpawn(ADSRDisplay* adsrDisplay);
bool IsLoadingState() const { return mIsLoadingState; }
bool IsLoadingModule() const { return mIsLoadingModule; }
bool IsDuplicatingModule() const { return mIsDuplicatingModule; }
void SetIsLoadingState(bool loading) { mIsLoadingState = loading; }
static std::string GetUserPrefsPath();
static void CrashHandler(void*);
static void DumpStats(bool isCrash, void* crashContext);
void SaveLayout(std::string jsonFile = "", bool makeDefaultLayout = true);
ofxJSONElement GetLayout();
void SaveLayoutAsPopup();
void SaveOutput();
void SaveState(std::string file, bool autosave);
void LoadState(std::string file);
void SetStartupSaveStateFile(std::string bskPath);
void SaveCurrentState();
void SaveStatePopup();
void LoadStatePopup();
void ToggleQuickSpawn();
QuickSpawnMenu* GetQuickSpawn() { return mQuickSpawn; }
std::string GetLastSavePath() { return mCurrentSaveStatePath; }
UserPrefsEditor* GetUserPrefsEditor() { return mUserPrefsEditor; }
juce::Component* GetFileChooserParent() const;
const juce::String& GetTextFromClipboard() const;
void CopyTextToClipboard(const juce::String& text);
void SetFatalError(std::string error);
static bool sShouldAutosave;
static float sBackgroundLissajousR;
static float sBackgroundLissajousG;
static float sBackgroundLissajousB;
static float sBackgroundR;
static float sBackgroundG;
static float sBackgroundB;
static float sCableAlpha;
static int sLoadingFileSaveStateRev;
static int sLastLoadedFileSaveStateRev;
static constexpr int kSaveStateRev = 426;
private:
void ResetLayout();
void ReconnectMidiDevices();
void DrawConsole();
void CheckClick(IDrawableModule* clickedModule, float x, float y, bool rightButton);
void UpdateUserPrefsLayout();
void LoadStatePopupImp();
IDrawableModule* DuplicateModule(IDrawableModule* module);
void DeleteAllModules();
void TriggerClapboard();
void DoAutosave();
void FindCircularDependencies();
bool FindCircularDependencySearch(std::list<IAudioSource*> chain, IAudioSource* searchFrom);
void ClearCircularDependencyMarkers();
bool IsCurrentSaveStateATemplate() const;
void ReadClipboardTextFromSystem();
int mIOBufferSize{ 0 };
std::vector<IAudioSource*> mSources;
std::vector<IDrawableModule*> mLissajousDrawers;
std::vector<IDrawableModule*> mDeletedModules;
bool mHasCircularDependency{ false };
std::vector<IDrawableModule*> mModalFocusItemStack;
IDrawableModule* mMoveModule{ nullptr };
int mMoveModuleOffsetX{ 0 };
int mMoveModuleOffsetY{ 0 };
bool mMoveModuleCanStickToCursor{ false }; //if the most current mMoveModule can stick to the cursor if you release the mouse button before moving it
ofVec2f mLastMoveMouseScreenPos;
ofVec2f mLastMouseDragPos;
bool mIsMousePanning{ false };
std::array<bool, 5> mIsMouseButtonHeld{ false };
struct SpaceMouseInfo
{
float mTwist{ 0 };
float mZoom{ 0 };
ofVec2f mPan{ 0, 0 };
bool mUsingTwist{ false };
bool mUsingZoom{ false };
bool mUsingPan{ false };
};
SpaceMouseInfo mSpaceMouseInfo;
char mConsoleText[MAX_TEXTENTRY_LENGTH]{ 0 };
TextEntry* mConsoleEntry{ nullptr };
ConsoleListener* mConsoleListener{ nullptr };
std::vector<MidiDevice*> mMidiDevices;
LocationZoomer mZoomer;
QuickSpawnMenu* mQuickSpawn{ nullptr };
std::unique_ptr<Minimap> mMinimap{ nullptr };
UserPrefsEditor* mUserPrefsEditor{ nullptr };
RollingBuffer* mGlobalRecordBuffer{ nullptr };
int mRecordingLength{ 0 };
struct LogEventItem
{
LogEventItem(double _time, std::string _text, LogEventType _type)
: time(_time)
, text(_text)
, type(_type)
{}
double time{ 0 };
std::string text;
LogEventType type{ LogEventType::kLogEventType_Verbose };
};
std::list<LogEventItem> mEvents;
std::list<std::string> mErrors;
NamedMutex mAudioThreadMutex;
static std::thread::id sAudioThreadId;
NoteOutputQueue* mNoteOutputQueue{ nullptr };
bool mAudioPaused{ false };
bool mIsLoadingState{ false };
bool mArrangeDependenciesWhenLoadCompletes{ false };
ModuleFactory mModuleFactory;
EffectFactory mEffectFactory;
int mClickStartX{ std::numeric_limits<int>::max() }; //to detect click and release in place
int mClickStartY{ std::numeric_limits<int>::max() };
bool mMouseMovedSignificantlySincePressed{ true };
bool mLastClickWasEmptySpace{ false };
bool mIsShiftPressed{ false };
double mLastShiftPressTime{ -9999 };
ofVec2f mLastShiftPressMousePos{};
std::string mLoadedLayoutPath;
bool mWantReloadInitialLayout{ false };
std::string mCurrentSaveStatePath;
std::string mStartupSaveStateFile;
Sample* mHeldSample{ nullptr };
IDrawableModule* mLastClickedModule{ nullptr };
bool mInitialized{ false };
ofRectangle mDrawRect;
std::vector<IDrawableModule*> mGroupSelectedModules;
ModuleContainer* mGroupSelectContext{ nullptr };
bool mHasDuplicatedDuringDrag{ false };
bool mHasAutopatchedToTargetDuringDrag{ false };
IDrawableModule* mResizeModule{ nullptr };
bool mShowLoadStatePopup{ false };
std::vector<PatchCable*> mPatchCables;
ofMutex mKeyInputMutex;
std::vector<std::pair<int, bool> > mQueuedKeyInput;
ofVec2f mMousePos;
std::string mNextDrawTooltip;
bool mHideTooltipsUntilMouseMove{ false };
juce::AudioDeviceManager* mGlobalAudioDeviceManager{ nullptr };
juce::AudioFormatManager* mGlobalAudioFormatManager{ nullptr };
juce::Component* mMainComponent{ nullptr };
juce::OpenGLContext* mOpenGLContext{ nullptr };
std::recursive_mutex mRenderLock;
float mFrameRate{ 0 };
long mFrameCount{ 0 };
ModuleContainer mModuleContainer;
ModuleContainer mUILayerModuleContainer;
ADSRDisplay* mScheduledEnvelopeEditorSpawnDisplay{ nullptr };
bool mIsLoadingModule{ false };
bool mIsDuplicatingModule{ false };
std::list<IPollable*> mExtraPollers;
std::string mFatalError;
double mLastClapboardTime{ -9999 };
double mPixelRatio{ 1 };
std::vector<float*> mInputBuffers;
std::vector<float*> mOutputBuffers;
std::unique_ptr<juce::AudioPluginFormatManager> mAudioPluginFormatManager;
std::unique_ptr<juce::KnownPluginList> mKnownPluginList;
};
extern ModularSynth* TheSynth;
|