1 /*
2  * Spectral Analyzer audio effect based on DISTRHO Plugin Framework (DPF)
3  *
4  * SPDX-License-Identifier: MIT
5  *
6  * Copyright (C) 2019 Jean Pierre Cimalando <jpcima@protonmail.com>
7  *
8  * Permission is hereby granted, free of charge, to any person obtaining a copy
9  * of this software and associated documentation files (the "Software"), to
10  * deal in the Software without restriction, including without limitation the
11  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
12  * sell copies of the Software, and to permit persons to whom the Software is
13  * furnished to do so, subject to the following conditions:
14  *
15  * The above copyright notice and this permission notice shall be included in
16  * all copies or substantial portions of the Software.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
24  * IN THE SOFTWARE.
25  */
26 
27 #pragma once
28 #include "DistrhoUI.hpp"
29 #include "PluginSpectralAnalyzer.hpp"
30 #include "ui/components/MainToolBar.h"
31 #include "SimpleIni.h"
32 #include <string>
33 #include <vector>
34 #include <memory>
35 #include <sys/time.h> // timespec
36 class SpectrumView;
37 class FloatingWindow;
38 class SpinBoxChooser;
39 class Slider;
40 class TextLabel;
41 class SelectionRectangle;
42 class ResizeHandle;
43 class ColorPalette;
44 
45 class UISpectralAnalyzer : public UI, MainToolBar::Listener {
46 public:
47     UISpectralAnalyzer();
48     ~UISpectralAnalyzer();
49 
50     PluginSpectralAnalyzer *getPluginInstance();
51 
52 protected:
53     void parameterChanged(uint32_t, float value) override;
54     void programLoaded(uint32_t index) override;
55     void sampleRateChanged(double newSampleRate) override;
56 
57     void uiIdle() override;
58     void uiReshape(uint width, uint height) override;
59 
60     void onNanoDisplay() override;
61     bool onMouse(const MouseEvent &ev) override;
62     bool onMotion(const MotionEvent &ev) override;
63 
64 protected:
65     void onToolBarItemClicked(int id) override;
66 
67 private:
68     void switchMode(int mode);
69 
70     void setNewSelectionPositionByMouse(DGL::Point<int> pos);
71 
72     void updateSpectrum();
73     void updateSelectModeDisplays();
74 
75     template <class W, class... A>
76     W *makeSubwidget(A &&... args)
77     {
78         W *w = new W(std::forward<A>(args)...);
79         fSubWidgets.push_back(std::unique_ptr<Widget>(w));
80         return w;
81     }
82 
83     void loadTheme(const char *theme);
84     void reloadThemeList();
85 
86 private:
87     enum { kNumChannels = DISTRHO_PLUGIN_NUM_INPUTS };
88 
89     SpectrumView *fSpectrumView = nullptr;
90 
91     MainToolBar *fMainToolBar = nullptr;
92 
93     FloatingWindow *fSetupWindow = nullptr;
94     SpinBoxChooser *fAlgorithmChooser = nullptr;
95     SpinBoxChooser *fFftSizeChooser = nullptr;
96     SpinBoxChooser *fStepSizeChooser = nullptr;
97     Slider *fAttackTimeSlider = nullptr;
98     Slider *fReleaseTimeSlider = nullptr;
99 
100     FloatingWindow *fScaleWindow = nullptr;
101     SelectionRectangle *fSelectionRectangle = nullptr;
102     ::Point fSelectionOrigin;
103 
104     FloatingWindow *fSelectWindow = nullptr;
105     TextLabel *fSelectLabelX = nullptr;
106     TextLabel *fSelectLabelY = nullptr;
107     TextLabel *fSelectChannelY[kNumChannels] = {};
108     TextLabel *fSelectNearPeakX[kNumChannels] = {};
109     TextLabel *fSelectNearPeakY[kNumChannels] = {};
110     bool fSelectPositionFixed = false;
111     double fSelectLastCursorKey = 0.0;
112     double fSelectLastCursorFreq = 0.0;
113     double fSelectLastCursorMag = 0.0;
114 
115     FloatingWindow *fColorWindow = nullptr;
116     SpinBoxChooser *fThemeChooser = nullptr;
117     SpinBoxChooser *fThemeEditChooser = nullptr;
118 
119     ResizeHandle *fResizeHandle = nullptr;
120 
121     std::vector<std::unique_ptr<Widget>> fSubWidgets;
122 
123     std::vector<float> fFrequencies;
124     std::vector<float> fMagnitudes;
125     uint32_t fSize = 0;
126 
127     enum {
128         kModeNormal,
129         kModeSetup,
130         kModeScale,
131         kModeSelect,
132         kModeHide,
133         kModeColor,
134     };
135 
136     int fMode = kModeNormal;
137 
138     bool fScaleRectDragging = false;
139 
140     bool fInitializedFloatingWindowPos = false;
141 
142     std::unique_ptr<ColorPalette> fPalette;
143 
144     std::unique_ptr<CSimpleIniA> fUiConfig;
145     std::string fCurrentTheme = "default";
146 #if !defined(_WIN32)
147     timespec fCurrentThemeMtime {};
148 #else
149     int64_t fCurrentThemeMtime {};
150 #endif
151     bool fThemeEditMode = false;
152 
153 private:
154     DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(UISpectralAnalyzer)
155 };
156