├── EULA.md
├── Images
├── OverviewSurface.png
├── OverviewTable.png
└── PluginGui.png
├── README.md
├── RELEASE_NOTES.md
├── SoundscapePlugin
├── Images
│ ├── icon_hamburger_16x16.png
│ ├── icon_help_16x16.png
│ ├── logo_au_100x100.png
│ ├── logo_avid.svg
│ ├── logo_dbaudio_15x15.png
│ ├── logo_dbaudio_text.svg
│ ├── logo_juce.svg
│ └── logo_vst_200x83.png
├── README.md
├── SoundscapePlugin.jucer
└── Source
│ ├── About.cpp
│ ├── About.h
│ ├── Common.h
│ ├── Controller.cpp
│ ├── Controller.h
│ ├── Gui.cpp
│ ├── Gui.h
│ ├── Overview.cpp
│ ├── Overview.h
│ ├── Parameters.cpp
│ ├── Parameters.h
│ ├── PluginEditor.cpp
│ ├── PluginEditor.h
│ ├── PluginProcessor.cpp
│ ├── PluginProcessor.h
│ ├── SurfaceSlider.cpp
│ ├── SurfaceSlider.h
│ ├── Version.cpp
│ └── Version.h
├── db Soundscape Infos
├── dbaudio-osc-protocol-ds100-1.2.4-en.pdf
├── dbaudio_DS100_Manual_1.4_en.pdf
└── dbaudio_TI_501_dbSoundscape_1.6_en-2.pdf
└── dbsoundscape-DAW-plug-in-for-ds100.pdf
/EULA.md:
--------------------------------------------------------------------------------
1 | # End-User License Agreement ("Agreement") for d&b Soundscape DAW Plug-in ("Software")
2 |
3 | This is a legal Agreement between the end user ("you") and d&b audiotechnik GmbH & Co. KG, Eugen-Adolff-Strasse 134, 71522 Backnang, Germany ("d&b audiotechnik").
4 |
5 | 1. By downloading, installing or using the Software you agree to the terms of this Agreement. If you do not agree to the terms of this Agreement you must cease and desist from downloading, installing and/or using of the Software.
6 |
7 | 2. The Software is intended solely for use by Entrepreneurs. An "Entrepreneur" is every natural person or legal entity acting in his/her or its professional or self-employed capacity when entering into this Agreement. If you are not an Entrepreneur and still wish to use the Software, please contact d&b audiotechnik directly.
8 |
9 | 3. Please note, that the Software is not a stand-alone executable software. To use the Software third party software is necessary which is not part of the Software and which is subject to its own license terms and has to be provided for by you on your own expenses and responsibility.
10 |
11 | 4. d&b audiotechnik grants you for the duration of the protection of the Software a non-exclusive, non-sublicensable right to use the Software for your own purposes subject to the terms and conditions of this Agreement. All rights to the Software are owned by d&b audiotechnik or its respective licensors. You may NOT copy the documentation accompanying the Software.
12 |
13 | 5. Any such right to use does only apply to the object code of the Software, which means the Software in a form readable solely by machines. You do not have a claim to being provided with the source code or parts of the source code and will not receive any rights to use or otherwise exploit the source code. In this regard, source code means the Software's source text, written in a programming language in a human readable form.
14 |
15 | 6. Subject to the mandatory limitations according to applicable copyright law, you may NOT (i) reverse engineer, disassemble, decompile or otherwise reduce the Software to a human perceivable version, nor shall you permit others to do so, except and only to the extent that such activity is expressly permitted by applicable law notwithstanding this limitation, (ii) modify, adapt, rent, lease, resell, distribute, network or create derivative works based upon the Software or any part thereof.
16 |
17 | 7. This Agreement is immediately terminated if you violate the terms and conditions hereof. You agree upon such termination to cease and desist from using the Software and to destroy the Software together with all copies.
18 |
19 | 8. Limitations of Liability:
20 |
21 | * [a] d&b audiotechnik shall bear liability for material defects and defects in title in the Software and its content and information (warranty for defects) only if d&b audiotechnik has fraudulently concealed a defect and/or has assumed a guarantee.
22 |
23 | * [b] Outside of the warranty for defects, d&b audiotechnik shall be liable only in cases of intent (Vorsatz) and gross negligence (grobe Fahrlässigkeit), pursuant to the provisions of the Product Liability Act (Produkthaftungsgesetz) and in all other cases subject to statutory mandatory liability, in each case according to the statutory provisions.
24 |
25 | * [c] Otherwise, d&b audiotechnik's liability is hereby excluded.
26 |
27 | * [d] Where d&b audiotechnik's liability is restricted or excluded according to the provisions above, this shall also apply to the personal liability of the statutory representatives, employees and vicarious agents of d&b audiotechnik, as well as for indirect damages and consequential damages (e.g. loss of data, damage to your hardware or software, disruption of operations, stoppages in production, loss of profit).
28 |
29 | * [e] You bear sole responsibility for accuracy of the data and information entered for use of the Software, including interpretation of the results delivered by the Software.
30 |
31 | 9. You are entitled to provide a third party with the original version of the Software together with a copy of this Agreement if this third party is an Entrepreneur and expressly consents in writing to the application of this Agreement for any use of the Software. As soon as you pass on the Software to the third party you should immediately notify d&b audiotechnik. Notification should, at least, include the date of transfer of the Software and the contact details of the new user. When passing on the Software, you shall promptly and completely delete or otherwise destroy all of your other copies of the Software.
32 |
33 | 10. This Agreement shall be governed by the laws of Germany.
34 |
35 | If you have any questions concerning this Agreement, please contact d&b audiotechnik's support.
36 |
--------------------------------------------------------------------------------
/Images/OverviewSurface.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dbaudio-soundscape/db-Soundscape-DAW-Plugins/0068b42cdb0fd56fb18073d48e0d078bb8e05506/Images/OverviewSurface.png
--------------------------------------------------------------------------------
/Images/OverviewTable.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dbaudio-soundscape/db-Soundscape-DAW-Plugins/0068b42cdb0fd56fb18073d48e0d078bb8e05506/Images/OverviewTable.png
--------------------------------------------------------------------------------
/Images/PluginGui.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dbaudio-soundscape/db-Soundscape-DAW-Plugins/0068b42cdb0fd56fb18073d48e0d078bb8e05506/Images/PluginGui.png
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # d&b Soundscape Plug-in
2 |
3 | Copyright (C) 2017-2020, d&b audiotechnik GmbH & Co. KG
4 |
5 | By downloading software from this site, you agree to the terms and conditions described in the [End-User License Agreement](EULA.md). If you do not agree with such terms and conditions do not download the software.
6 |
7 | ## Latest binaries can be downloaded here: [LATEST RELEASE](../../releases/latest)
8 |
9 | ---
10 |
11 | ## What is the d&b Soundscape Plug-in?
12 |
13 | The d&b Soundscape Plug-in enables a Digital Audio Workstation (DAW), Avid VENUE S6L console, or any other Plug-in host to control the basic En-Scene and En-Space parameters of any desired sound object on the DS100 platform using the OSC protocol. It is designed to work with d&b Soundscape and the d&b DS100.
14 |
15 | For more information about the d&b Soundscape system, go to www.dbaudio.com and www.dbsoundscape.com.
16 |
17 | ## Features
18 |
19 | - Allows automated Soundscape parameters of any desired sound object to be transmitted in real time from a DAW to the DS100 via OSC.
20 | - Allows a DAW to record basic Soundscape parameters of any sound object in the DS100 as automation envelopes or as snapshots.
21 | - The d&b Soundscape Plug-in does not perform any audio processing or affect the DAW audio output in any way.
22 |
23 | ### En-Scene object parameters
24 | - X/Y position (relative to a selected coordinate mapping)
25 | - Spread
26 | - Delay mode
27 |
28 | ### En-Space object parameters
29 | - Reverb send level
30 |
31 | ## Requirements
32 | - Digital Audio Workstation (DAW), Avid VENUE S6L console, or any other host which supports one of the provided Plug-in formats.
33 | - d&b DS100 Signal Engine with active En-Scene and/or En-Space license.
34 | - Both the DS100 and the Plug-in host must be connected to the same Ethernet network.
35 |
36 | ## Available Plug-in formats
37 | - VST3 (Win64, Win32, and MacOS)
38 | - AAX (Win64 and MacOS)
39 | - AU (MacOS)
40 |
41 | ---
42 |
43 | # Quick start guide
44 |
45 | * [Getting started](#getting-started)
46 | * [Connecting with the d&b DS100 Signal Engine](#connecting-with-ds100)
47 | * [Plug-in configuration](#plugin-configuration)
48 | * [Troubleshooting](#troubleshooting)
49 |
50 |
51 |
52 | ## Getting started
53 |
54 | ### 1. Install the Plug-in
55 |
56 | * On Windows systems, please unpack and copy the d&b Soundscape Plug-in to the appropriate location depending on your DAW and Plug-in format. Common locations are as follows:
57 | * **AAX:** C:\Program Files\Common Files\Avid\Audio\Plug-Ins
58 | * **VST3:** C:\Program Files\Common Files\VST3
59 |
60 | * On MacOS systems, simply double-clicking the **pkg** file will install the Plug-in into the correct location. The default installation paths are as follows:
61 | * **VST3:** /Library/Audio/Plug-Ins/VST3
62 | * **AU:** /Library/Audio/Plug-Ins/Components
63 | * **AAX:** /Library/Application Support/Avid/Audio/Plug-Ins
64 |
65 | * On Avid VENUE S6L consoles, please install the Plug-in as follows:
66 | 1. Unpack the d&b Soundscape **AAX** Plug-in and copy the "SoundscapePlugin.aaxplugin" file into an USB drive, under a folder named "AAX Plug-Ins".
67 | 2. Set the Avid VENUE S6L console to configuration mode and insert the USB drive.
68 | 3. On the VENUE user interface, go to the "Options" page and select the "Plug-Ins" tab.
69 | 4. Under "Plug-ins to install" choose your USB drive from the available devices, select the d&b Soundscape Plug-in, and click on "Install".
70 | For more detailed info please refer to your Avid VENUE S6L documentation.
71 |
72 | ### 2. Insert the Plug-in
73 |
74 | * Open your DAW and insert a new track or choose an existing track.
75 | * Add the d&b En-Scene Plug-in to the effect chain of the track.
76 | You may need to let your DAW re-scan its Plug-in folders.
77 |
78 | ### 3. Use the Plug-in
79 |
80 | * Open the Plug-in's interface and enter the desired input number in the **«Input»** field.
81 | This is the matrix input number that will be used on the DS100 for the corresponding sound object of this track.
82 | * Add envelope tracks for the automation of the desired Plug-in parameters on your DAW.
83 | * Using these envelopes, you can now define detailed movements for each individual sound object at any point in your DAW's timeline.
84 | You can do this by drawing envelope points by hand or by recording your movements with the Plug-in's graphical interface.
85 |
86 | ---
87 |
88 |
89 |
90 | ## Connecting with the d&b DS100 Signal Engine
91 |
92 | 1. Ensure that the DS100 is connected to the same Ethernet network as your PC and their IP addresses and subnet masks are compatible.
93 | **Note:** On Avid VENUE S6L consoles, use the **«ECx»** port on the back panel. On the VENUE user interface, go to the "Options" page, select the "Interaction" tab, and configure the "Ethernet control" settings accordingly.
94 | 2. Enter the IP address of your DS100 into the Plug-in's **«IP address»** field.
95 | The **«Online»** indicator will turn blue to indicate that the connection has been established successfully.
96 | **Note:** The IP address of the DS100 can be obtained from the **«Info»** tab of the **«Device»** view in R1 V3.
97 | 3. Using R1 V3, ensure the desired DS100 Matrix inputs are set to **«En-Scene»**, and also configure the coordinate mapping settings for external control. Please also refer to **TI 501** featuring d&b Soundscape and the R1 Help for more information.
98 |
99 | ### OSC Send Mode
100 | 1. In the DAW, set the track's automation mode to **«Read»** so that the Plug-in parameters are determined by the points drawn in their automation envelopes.
101 | 2. Set the Plug-in to **«Tx»**.
102 | 3. Set the DAW to Play.
103 | The parameter values in your envelopes will be transmitted to the DS100 and the corresponding sound object will be positioned accordingly in real time.
104 |
105 | ### OSC Receive Mode
106 | 1. In the DAW, set the track's automation mode to **«Write»** or **«Touch»**.
107 | In this way, the automation envelopes for the desired parameters will be drawn as determined by the Plug-in.
108 | 2. Set the Plug-in to **«Rx»**.
109 | 3. Ensure the envelope tracks of the desired parameters are armed for recording.
110 | 4. Set the DAW to Play.
111 | The position of the corresponding sound object will be requested from the DS100 and will then be written to the automation envelopes accordingly in real time.
112 |
113 | ---
114 |
115 |
116 |
117 | ## Plug-in configuration
118 |
119 | The d&b Soundscape Plug-in user interface is divided in three different areas.
120 |
121 | 
122 |
123 | ### [A] Plug-in configuration parameters
124 |
125 | Configuration settings relevant for the DS100 project setup and for the OSC communication mode of the individual Plug-in instance.
126 |
127 | * **[1]** DS100 Matrix input number, corresponding to the sound object to be positioned.
128 |
129 | * **[2]** Selector for the DS100 Coordinate mapping setting.
130 | Allows you to choose between 4 possible mappings, which can be configured using R1 V3 (please refer to TI 501 and the R1 Help for more information).
131 |
132 | * **[3]** Selector for the Plug-in's OSC communication mode.
133 | * When **«Tx»** mode is enabled, this Plug-in transmits its parameter values from your DAW to the DS100.
134 | * While **«Rx»** mode is enabled, the Plug-in requests the parameter values from this sound object in the DS100 and passes them on to the DAW.
135 | * Both **«Tx»** and **«Rx»** can be enabled, resulting in bi-directional communication.
136 | * To bypass the Plug-in, both **«Tx»** and **«Rx»** can be turned off, thus disabling OSC communication for the individual Plug-in instance.
137 |
138 | ### [B] Soundscape parameters
139 |
140 | The user interface to control the d&b Soundscape parameters of an individual sound object. These parameters can be recorded and automated in different ways depending on the functionality of the hosting DAW.
141 |
142 | * En-Scene
143 | * **[4]** x/y slider surface used to set or display the position of the assigned sound object.
144 | * **[5]** Rotary knob used to set or display the Spread parameter of the desired sound object.
145 | * **[6]** Drop-down menu used to set or display the Delay Mode of the desired sound object.
146 | * En-Space
147 | * **[7]** Rotary knob used to set or display the En-Space Reverb send level parameter of the desired sound object or matrix input.
148 |
149 | ### [C] Global configuration parameters
150 |
151 | The settings at the bottom of the Plug-in's interface are global and are shared among all Plug-in instances in your DAW project.
152 |
153 | * **[8]** IP address of the DS100 Signal Engine.
154 | The IP address of the DS100 can be obtained from the **«Info»** tab of the **«Device»** view in R1 V3.
155 |
156 | * **[9]** Transmission interval, in milliseconds.
157 | Determines how frequently OSC messages are interchanged between the Plug-in and the DS100.
158 | A smaller interval will result in more fluent movements, but also in more network and processing load. The default and recommended setting is 50 milliseconds.
159 |
160 | * **[10] «Overview»** window button.
161 | Clicking on this button will pop up the **«Overview»**, an additional window containing a Plug-in configuration table and the multi-object surface.
162 |
163 | * **Plug-in configuration table.**
164 | This is a list of all Plug-In instances in the project and their configuration parameters, including the name of the track where each Plug-in is inserted, the Matrix input number, the selected coordinate mapping, and the OSC communication mode.
165 |
166 | 
167 |
168 | * **Multi-object surface.**
169 | This is an x/y slider similar to the one on the main Plug-in graphical interface, but displaying the positions of all Plug-in instances in the project.
170 | Clicking and dragging individual sound objects on this surface is also possible.
171 | **Note:** Only the sound objects assigned to the selected coordinate mapping will be displayed.
172 |
173 | 
174 |
175 | * **[11] «Online»** indicator.
176 | Turns blue when an OSC connection between the Plug-in and the DS100 has been successfully established.
177 |
178 | ---
179 |
180 |
181 |
182 | ## Troubleshooting
183 |
184 | #### The Soundscape Plug-in is not recognized by my DAW, or gets blacklisted by my DAW.
185 |
186 | * Ensure that you have let your DAW re-scan its Plug-in folders. You may need to restart your DAW after installing the Plug-in.
187 | * To work under Windows 10, the Soundscape Plug-in may require the Visual C++ Redistributable Packages for Visual Studio 2017. These packages are included in the latest Windows Updates, and are also included when installing d&b's R1V3 or ArrayCalc.
188 |
189 | #### My Plug-in's «Rx» mode is enabled, and I am moving a sound object in R1, but am still unable to record an automation envelope with my DAW.
190 |
191 | * Ensure that the DS100's IP address has been entered correctly in the Plug-in, and that the **«Online»** indicator is blue.
192 | The IP address of the DS100 can be obtained from the **«Info»** tab of the **«Device»** view in R1 V3.
193 | * Check that the envelope automation mode on your DAW is set to **«Write»**, **«Touch»**, or **«Latch»**. When set to **«Read»**, the envelope's current values may have priority over whatever the Plug-in is receiving from the DS100 via OSC.
194 |
195 | #### Reaper: Automation envelopes can only be recorded when the Plug-in's GUI window is open.
196 |
197 | * By default, when the plugin's window is closed, parameter automation envelopes will not get written to even though the parameter values may be changing.
198 | * To fix this, go into Reaper's Preferences > VST > VST compatibility > Parameter automation notifications, and set it to **«Process all notifications»**.
199 |
200 | #### The sound object on the Plug-in's GUI "jitters" or jumps constantly between two positions.
201 |
202 | * This may occur when the Plug-in's **«Rx»** mode is enabled, but the track's automation mode in the DAW is set to **«Read»**. If the sound object's position in the DS100 and the position given by the automation envelope conflict with each other, the Plug-in's GUI will attempt to display both conflicting positions at the same time.
203 | * To resolve this, ensure the Plug-in's OSC communication mode and the track's automation mode match your current workflow. Use **«Rx»** mode and **«Write»** automation for recording envelopes; use **«Tx»** mode and **«Read»** automation when playing them back during the show.
204 |
205 | ### Known Issues
206 |
207 | #### Avid S6L: Input and Mapping do not change reliably when loading showfiles or snapshots.
208 |
209 | * This can occur when only Input or Mapping have changed, but all other parameters (such as X/Y, Spread, etc.) in the showfile or snapshot being loaded are identical to the current values.
210 | * When storing a showfile or snapshot after having only changed the Input or Mapping, nudge one of the other parameters to ensure that a change is registered when loading it later.
211 |
--------------------------------------------------------------------------------
/RELEASE_NOTES.md:
--------------------------------------------------------------------------------
1 | # d&b Soundscape Plug-in: Release notes
2 |
3 | Copyright (C) 2017-2022, d&b audiotechnik GmbH & Co. KG
4 |
5 |
6 | ## V2.8.5
7 |
8 | ### Bugfixes
9 | * Fixed inadvertently using some outdated JUCE modules when building binaries for previous release.
10 |
11 | ---
12 |
13 | ## V2.8.4
14 |
15 | ### Features
16 | * MacOS binaries are now notarized.
17 |
18 | ---
19 |
20 | ## V2.8.3
21 |
22 | ### Bugfixes
23 | * Plugin input numbers no longer get changed when loading a second project on a new tab in the same DAW.
24 |
25 | ---
26 |
27 | ## V2.8.1
28 |
29 | ### Features
30 | * When opening the multi-source surface, the selected mapping is now automatically set to the active Plug-In's mapping.
31 |
32 | ### Bugfixes
33 | * The user's current IP address is no longer overwritten when loading showfiles or snapshots (Avid VENUE S6L) or recalling presets (DAW).
34 | * Avid VENUE S6L: The user's preferred Plug-In window size no longer gets reset when switching channels.
35 |
36 | ---
37 |
38 | ## V2.8.0
39 |
40 | ### Features
41 | * First open source release.
42 |
43 | ### Bugfixes
44 | * On Pro Tools, the Input number will now correctly increase automatically as Plug-in instances are added to the project.
45 |
46 | ---
47 |
48 | ## V2.7.1
49 |
50 | ### Features
51 | * Implemented multi-source surface for the overview window.
52 |
53 | ### Bugfixes
54 | * Fixed GUI stability issues.
55 |
56 | ---
57 |
58 | ## V2.6.1
59 |
60 | ### Features
61 | * Added support for Touch automation via OSC.
62 | * Added Info/License window.
63 |
64 | ---
65 |
66 | ## V2.6.0
67 |
68 | ### Features
69 |
70 | * Plug-in now also available as VST3.
71 | * New automation parameter **«OSCBypass»**.
72 | * Tx and Rx modes are no longer mutually exclusive.
73 |
74 | ### Bugfixes
75 |
76 | * Setting delay mode to **«Tight»** in R1 no longer shows as **«Full»** on the Plug-in.
77 | * On Pro Tools, the IP Address no longer resets when adding a new Plug-in instance to the project.
78 |
79 | ### Known issues
80 |
81 | * Touch automation via OSC may not work properly on some hosts
82 |
83 | ---
84 |
85 | ## V2.3.0
86 |
87 | * Initial release
88 |
--------------------------------------------------------------------------------
/SoundscapePlugin/Images/icon_hamburger_16x16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dbaudio-soundscape/db-Soundscape-DAW-Plugins/0068b42cdb0fd56fb18073d48e0d078bb8e05506/SoundscapePlugin/Images/icon_hamburger_16x16.png
--------------------------------------------------------------------------------
/SoundscapePlugin/Images/icon_help_16x16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dbaudio-soundscape/db-Soundscape-DAW-Plugins/0068b42cdb0fd56fb18073d48e0d078bb8e05506/SoundscapePlugin/Images/icon_help_16x16.png
--------------------------------------------------------------------------------
/SoundscapePlugin/Images/logo_au_100x100.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dbaudio-soundscape/db-Soundscape-DAW-Plugins/0068b42cdb0fd56fb18073d48e0d078bb8e05506/SoundscapePlugin/Images/logo_au_100x100.png
--------------------------------------------------------------------------------
/SoundscapePlugin/Images/logo_dbaudio_15x15.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dbaudio-soundscape/db-Soundscape-DAW-Plugins/0068b42cdb0fd56fb18073d48e0d078bb8e05506/SoundscapePlugin/Images/logo_dbaudio_15x15.png
--------------------------------------------------------------------------------
/SoundscapePlugin/Images/logo_dbaudio_text.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
8 |
10 |
11 |
--------------------------------------------------------------------------------
/SoundscapePlugin/Images/logo_juce.svg:
--------------------------------------------------------------------------------
1 |
2 |
18 |
20 |
21 |
23 | image/svg+xml
24 |
26 |
27 |
28 |
29 |
30 |
50 |
63 |
65 |
68 |
69 |
71 |
75 |
76 |
82 |
89 |
95 |
101 |
107 |
113 |
119 |
125 |
131 |
137 |
143 |
144 |
--------------------------------------------------------------------------------
/SoundscapePlugin/Images/logo_vst_200x83.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dbaudio-soundscape/db-Soundscape-DAW-Plugins/0068b42cdb0fd56fb18073d48e0d078bb8e05506/SoundscapePlugin/Images/logo_vst_200x83.png
--------------------------------------------------------------------------------
/SoundscapePlugin/README.md:
--------------------------------------------------------------------------------
1 | # d&b Soundscape Plug-in
2 |
3 | Copyright (C) 2017-2020, d&b audiotechnik GmbH & Co. KG
4 |
5 | By downloading software from this site, you agree to the terms and conditions described in the [End-User License Agreement](../EULA.md). If you do not agree with these terms and conditions, do not download the software.
6 |
7 | ## What is the d&b Soundscape Plug-in?
8 |
9 | The d&b Soundscape Plug-in enables a Digital Audio Workstation (DAW), AVID S6L Console, or any other Plug-in host to control the basic En-Scene and En-Space parameters of any desired sound object on the DS100 platform using the OSC protocol. It is designed to work with d&b Soundscape and the d&b DS100.
10 |
11 | For more information about the d&b Soundscape system, go to www.dbaudio.com and www.dbsoundscape.com.
12 |
13 | ## Building the Plug-in
14 |
15 | The d&b Soundscape Plug-in was developed using [JUCE](https://github.com/WeAreROLI/JUCE), a cross-platform C++ application framework. Download and install JUCE v5.4.5 and use the Projucer tool to open the provided SoundscapePlugin.jucer configuration file. This file defines export configurations for Microsoft Visual Studio 2017 and Apple Xcode.
16 |
17 | ### VST3 SDK
18 |
19 | To compile the Soundscape Plug-in as VST3, please go to steinberg.net to obtain the required VST3 SDK. Make sure you enter the path to the VST3 SDK correctly in the Projucer's settings.
20 |
21 | ### AAX SDK
22 |
23 | To compile the Soundscape Plug-in as AAX, please go to developer.avid.com to obtain the required AAX SDK. Make sure you enter the path to the AAX SDK correctly in the Projucer's settings.
24 |
25 | ### AU SDK
26 |
27 | The Core Audio SDK required to compile the Soundscape Plug-in as an Audio Units Plug-in (AU) is included in Xcode, which means no manual download is required.
28 |
29 | ### Windows
30 |
31 | To build the Soundscape Plug-in on Windows, first install Visual Studio 2017. Open the SoundscapePlugin.jucer file from this repository using JUCE's Projucer tool. In Projucer, select the exporter target "Visual Studio 2017" and click on "Save and open in IDE". This generates or updates the required build files and opens Visual Studio 2017, in which you can build the Plug-in.
32 |
33 | ## macOS
34 |
35 | To build the Soundscape Plug-in on macOS, first install Xcode. Open the SoundscapePlugin.jucer file from this repository using JUCE's Projucer tool. In Projucer, select the exporter target "Xcode" and click on "Save and open in IDE". This generates or updates the required build files and opens Xcode, in which you can build the Plug-in.
36 |
--------------------------------------------------------------------------------
/SoundscapePlugin/SoundscapePlugin.jucer:
--------------------------------------------------------------------------------
1 |
2 |
3 |
17 |
18 |
19 |
21 |
23 |
25 |
26 |
28 |
30 |
31 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
50 |
51 |
53 |
55 |
57 |
58 |
59 |
60 |
61 |
63 |
64 |
66 |
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 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
127 |
128 |
129 |
130 |
131 |
132 |
--------------------------------------------------------------------------------
/SoundscapePlugin/Source/About.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | ===============================================================================
3 |
4 | Copyright (C) 2019 d&b audiotechnik GmbH & Co. KG. All Rights Reserved.
5 |
6 | This file is part of the Soundscape VST, AU, and AAX Plug-in.
7 |
8 | Redistribution and use in source and binary forms, with or without
9 | modification, are permitted provided that the following conditions are met:
10 |
11 | 1. Redistributions of source code must retain the above copyright notice,
12 | this list of conditions and the following disclaimer.
13 |
14 | 2. Redistributions in binary form must reproduce the above copyright notice,
15 | this list of conditions and the following disclaimer in the documentation
16 | and/or other materials provided with the distribution.
17 |
18 | 3. The name of the author may not be used to endorse or promote products
19 | derived from this software without specific prior written permission.
20 |
21 | THIS SOFTWARE IS PROVIDED BY d&b audiotechnik GmbH & Co. KG "AS IS" AND ANY
22 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24 | DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
29 | OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
30 | ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 |
32 | ===============================================================================
33 | */
34 |
35 |
36 | #include "About.h"
37 | #include "Common.h"
38 |
39 |
40 | namespace dbaudio
41 | {
42 |
43 |
44 | /*
45 | ===============================================================================
46 | Class AAboutOverlay
47 | ===============================================================================
48 | */
49 |
50 | /**
51 | * Class constructor.
52 | */
53 | AAboutOverlay::AAboutOverlay()
54 | : AOverlay(OT_About)
55 | {
56 | // Plugin version label
57 | String versionString = String("Soundscape Plug-in V") + String(JUCE_STRINGIFY(JUCE_APP_VERSION));
58 | versionString += String("\nCopyright ") + String(CharPointer_UTF8("\xc2\xa9")) + String(" 2017-2019\nd&b audiotechnik GmbH & Co. KG,\nall rights reserved.");
59 | m_versionLabel = std::make_unique("PluginVersion", versionString);
60 | m_versionLabel->setJustificationType(Justification::topLeft);
61 | m_versionLabel->setFont(Font(13.0, Font::plain));
62 | addAndMakeVisible(m_versionLabel.get());
63 |
64 | // Hyperlink to dbaudio.com
65 | m_dbLink = std::make_unique(String("www.dbaudio.com"), URL("www.dbaudio.com"));
66 | m_dbLink->setFont(Font(13.0, Font::plain), false /* do not resize */);
67 | addAndMakeVisible(m_dbLink.get());
68 |
69 | String eula("End-User License Agreement (\"Agreement\") for d&b Soundscape DAW Plug-in (\"Software\")\n" \
70 | "======================================================================\n" \
71 | "This is a legal Agreement between the end user (\"you\") and d&b audiotechnik GmbH & Co. KG, Eugen-Adolff-Strasse 134, 71522 Backnang, Germany (\"d&b audiotechnik\"). \n" \
72 | "1. By downloading, installing or using the Software you agree to the terms of this Agreement. If you do not agree to the terms of this Agreement you must cease and desist from down-loading, installing and/or using of the Software.\n" \
73 | "2. The Software is intended solely for use by Entrepreneurs. An \"Entrepreneur\" is every natural person or legal entity acting in his/her or its professional or self-employed capacity when entering into this Agreement. If you are not an Entrepreneur and still wish to use the Software, please contact d&b audiotechnik directly.\n" \
74 | "3. Please note, that the Software is not a stand-alone executable software. To use the Soft-ware third party software is necessary which is not part of the Software and which is subject to its own license terms and has to be provided for by you on your own expenses and responsibility.\n" \
75 | "4. d&b audiotechnik grants you for the duration of the protection of the Software a non-exclusive, non-sublicensable right to use the Software for your own purposes subject to the terms and conditions of this Agreement. All rights to the Software are owned by d&b audiotechnik or its respective licensors. You may NOT copy the documentation accompanying the Software.\n" \
76 | "5. Any such right to use does only apply to the object code of the Software, which means the Software in a form readable solely by machines. You do not have a claim to being provided with the source code or parts of the source code and will not receive any rights to use or otherwise exploit the source code. In this regard, source code means the Software's source text, written in a programming language in a human readable form.\n" \
77 | "6. Subject to the mandatory limitations according to applicable copyright law, you may NOT (i) reverse engineer, disassemble, decompile or otherwise reduce the Software to a human perceivable version, nor shall you permit others to do so, except and only to the ex-tent that such activity is expressly permitted by applicable law notwithstanding this limitation, (ii) modify, adapt, rent, lease, resell, distribute, network or create derivative works based upon the Software or any part thereof.\n" \
78 | "7. This Agreement is immediately terminated if you violate the terms and conditions hereof. You agree upon such termination to cease and desist from using the Software and to destroy the Software together with all copies.\n" \
79 | "8. Limitations of Liability:\n" \
80 | " a. d&b audiotechnik shall bear liability for material defects and defects in title in the Software and its content and information (warranty for defects) only if d&b audiotechnik has fraudulently concealed a defect and/or has assumed a guarantee.\n" \
81 | " b. Outside of the warranty for defects, d&b audiotechnik shall be liable only in cases of intent (Vorsatz) and gross negligence (grobe Fahrlaessigkeit), pursuant to the provisions of the Product Liability Act (Produkthaftungsgesetz) and in all other cases subject to statutory mandatory liability, in each case according to the statutory provisions.\n" \
82 | " c. Otherwise, d&b audiotechnik's liability is hereby excluded.\n" \
83 | " d. Where d&b audiotechnik's liability is restricted or excluded according to the provisions above, this shall also apply to the personal liability of the statutory representatives, employees and vicarious agents of d&b audiotechnik, as well as for indirect damages and consequential damages (e.g. loss of data, damage to your hardware or software, disruption of operations, stoppages in production, loss of profit).\n" \
84 | " e. You bear sole responsibility for accuracy of the data and information entered for use of the Software, including interpretation of the results delivered by the Software.\n" \
85 | "9. You are entitled to provide a third party with the original version of the Software together with a copy of this Agreement if this third party is an Entrepreneur and expressly consents in writing to the application of this Agreement for any use of the Software. As soon as you pass on the Software to the third party you should immediately notify d&b audiotechnik. Notification should, at least, include the date of transfer of the Software and the contact details of the new user. When passing on the Software, you shall promptly and completely delete or otherwise destroy all of your other copies of the Software.\n" \
86 | "10. This Agreement shall be governed by the laws of Germany.\n" \
87 | "If you have any questions concerning this Agreement, please contact d&b audiotechnik's support.");
88 | m_eulaField = std::make_unique("eula");
89 | m_eulaField->setColour(TextEditor::backgroundColourId, CDbStyle::GetDbColor(CDbStyle::MidColor));
90 | m_eulaField->setColour(TextEditor::textColourId, CDbStyle::GetDbColor(CDbStyle::TextColor));
91 | m_eulaField->setColour(TextEditor::outlineColourId, CDbStyle::GetDbColor(CDbStyle::ButtonColor));
92 | m_eulaField->setReadOnly(true);
93 | m_eulaField->setFont(Font(13.0, Font::plain));
94 | m_eulaField->setCaretVisible(false);
95 | m_eulaField->setMultiLine(true, false /* no wrapping */);
96 | m_eulaField->setScrollbarsShown(true);
97 | m_eulaField->setText(eula, false);
98 | addAndMakeVisible(m_eulaField.get());
99 |
100 | // JUCE copyright label
101 | String juceLabelString = String("Made with JUCE.\nCopyright ") + String(CharPointer_UTF8("\xc2\xa9")) + String(" 2017 - ROLI Ltd.");
102 | m_juceLabel = std::make_unique("JuceLabel", juceLabelString);
103 | m_juceLabel->setJustificationType(Justification::topRight);
104 | m_juceLabel->setFont(Font(13.0, Font::plain));
105 | addAndMakeVisible(m_juceLabel.get());
106 | }
107 |
108 | /**
109 | * Class destructor.
110 | */
111 | AAboutOverlay::~AAboutOverlay()
112 | {
113 | }
114 |
115 | /**
116 | * If any relevant parameters have been marked as changed, update the table contents.
117 | * NOTE: this reimplementation does nothing, since these pages are static.
118 | * @param init True to ignore any changed flags and update the plugin parameters
119 | * in the GUI anyway. Good for when opening the Overview for the first time.
120 | */
121 | void AAboutOverlay::UpdateGui(bool init)
122 | {
123 | ignoreUnused(init);
124 | }
125 |
126 | /**
127 | * Reimplemented to paint the overlay's background.
128 | * @param g Graphics context that must be used to do the drawing operations.
129 | */
130 | void AAboutOverlay::paint(Graphics& g)
131 | {
132 | int w = getLocalBounds().getWidth();
133 | int h = getLocalBounds().getHeight();
134 |
135 | // Background
136 | g.setColour(CDbStyle::GetDbColor(CDbStyle::DarkColor));
137 | g.fillRect(Rectangle(8, 8, w - 16, h - 16));
138 |
139 | // d&b logo
140 | std::unique_ptr dbLogo = Drawable::createFromImageData(BinaryData::logo_dbaudio_text_svg, BinaryData::logo_dbaudio_text_svgSize);
141 | dbLogo->drawWithin(g, Rectangle(20.0f, 20.0f, 30.0f, 30.0f), RectanglePlacement::stretchToFit, 1.0f);
142 |
143 | // JUCE logo
144 | std::unique_ptr formatLogo = Drawable::createFromImageData(BinaryData::logo_juce_svg, BinaryData::logo_juce_svgSize);
145 | formatLogo->drawWithin(g, Rectangle(w - 120.0f, 10.0f, 100.0f, 35.0f), RectanglePlacement::stretchToFit, 1.0f);
146 | }
147 |
148 | /**
149 | * Reimplemented to resize and re-postion controls & labels.
150 | */
151 | void AAboutOverlay::resized()
152 | {
153 | int eulaVPos = 170;
154 | int eulaHeight = jmin((getLocalBounds().getHeight() - (eulaVPos + 20)), 270);
155 |
156 | m_versionLabel->setBounds(60, 12, 300, 55);
157 | m_eulaField->setBounds(20, (eulaVPos), getLocalBounds().getWidth() - 40, eulaHeight);
158 | m_dbLink->setBounds(60, 65, 110, 18);
159 | m_juceLabel->setBounds(getLocalBounds().getWidth() - 210, 48, 200, 50);
160 | }
161 |
162 |
163 | /*
164 | ===============================================================================
165 | Class CAboutOverlayVST
166 | ===============================================================================
167 | */
168 |
169 | /**
170 | * Class constructor.
171 | */
172 | CAboutOverlayVST::CAboutOverlayVST()
173 | {
174 | // Indicate whether VST2 or VST3
175 | String hostFormatName("VST2");
176 | if (PluginHostType::getPluginLoadedAs() == AudioProcessor::wrapperType_VST3)
177 | hostFormatName = "VST3";
178 |
179 | // Plugin version label
180 | String formatString = hostFormatName + String(" is a trademark of Steinberg Media Technologies GmbH, registered in Europe and other countries.\n") +
181 | String(CharPointer_UTF8("\xc2\xa9")) + String(" 2019 Steinberg Media Technologies GmbH, all rights reserved.");
182 | m_formatInfoLabel = std::make_unique("FormatInfo", formatString);
183 | m_formatInfoLabel->setJustificationType(Justification::topLeft);
184 | m_formatInfoLabel->setFont(Font(13.0, Font::plain));
185 | addAndMakeVisible(m_formatInfoLabel.get());
186 |
187 | }
188 |
189 | /**
190 | * Class destructor.
191 | */
192 | CAboutOverlayVST::~CAboutOverlayVST()
193 | {
194 | }
195 |
196 | /**
197 | * Reimplemented to paint the overlay's background.
198 | * @param g Graphics context that must be used to do the drawing operations.
199 | */
200 | void CAboutOverlayVST::paint(Graphics& g)
201 | {
202 | // First paint base class
203 | AAboutOverlay::paint(g);
204 |
205 | // VST logo
206 | Image formatLogo = ImageCache::getFromMemory(BinaryData::logo_vst_200x83_png, BinaryData::logo_vst_200x83_pngSize);
207 | g.setImageResamplingQuality(Graphics::highResamplingQuality);
208 | g.drawImage(formatLogo, 20, 100, 120, 50, 0, 0, 200, 83);
209 |
210 | // Frame around logo
211 | g.setColour(CDbStyle::GetDbColor(CDbStyle::DarkLineColor));
212 | g.drawRect(Rectangle(20, 100, 120, 50), 1);
213 | }
214 |
215 | /**
216 | * Reimplemented to resize and re-postion controls & labels.
217 | */
218 | void CAboutOverlayVST::resized()
219 | {
220 | // First resize base class components
221 | AAboutOverlay::resized();
222 |
223 | m_formatInfoLabel->setBounds(145, 100, getLocalBounds().getWidth() - 155, 80);
224 | }
225 |
226 |
227 | /*
228 | ===============================================================================
229 | Class CAboutOverlayAAX
230 | ===============================================================================
231 | */
232 |
233 | /**
234 | * Class constructor.
235 | */
236 | CAboutOverlayAAX::CAboutOverlayAAX()
237 | {
238 | // Plugin version label
239 | String formatString = String("AAX Plug-in format.\nCopyright ") +
240 | String(CharPointer_UTF8("\xc2\xa9")) + String(" 2014-2018 by Avid Technology, Inc.\nAll rights reserved.");
241 | m_formatInfoLabel = std::make_unique("FormatInfo", formatString);
242 | m_formatInfoLabel->setJustificationType(Justification::topLeft);
243 | m_formatInfoLabel->setFont(Font(13.0, Font::plain));
244 | addAndMakeVisible(m_formatInfoLabel.get());
245 | }
246 |
247 | /**
248 | * Class destructor.
249 | */
250 | CAboutOverlayAAX::~CAboutOverlayAAX()
251 | {
252 | }
253 |
254 | /**
255 | * Reimplemented to paint the overlay's background.
256 | * @param g Graphics context that must be used to do the drawing operations.
257 | */
258 | void CAboutOverlayAAX::paint(Graphics& g)
259 | {
260 | // First paint base class
261 | AAboutOverlay::paint(g);
262 |
263 | // AAX logo
264 | std::unique_ptr formatLogo = Drawable::createFromImageData(BinaryData::logo_avid_svg, BinaryData::logo_avid_svgSize);
265 | formatLogo->drawWithin(g, Rectangle(20.0f, 100.0f, 140.0f, 46.0f), RectanglePlacement::stretchToFit, 1.0f);
266 | }
267 |
268 | /**
269 | * Reimplemented to resize and re-postion controls & labels.
270 | */
271 | void CAboutOverlayAAX::resized()
272 | {
273 | // First resize base class components
274 | AAboutOverlay::resized();
275 |
276 | m_formatInfoLabel->setBounds(172, 101, getLocalBounds().getWidth() - 155, 80);
277 | }
278 |
279 |
280 | /*
281 | ===============================================================================
282 | Class CAboutOverlayAU
283 | ===============================================================================
284 | */
285 |
286 | /**
287 | * Class constructor.
288 | */
289 | CAboutOverlayAU::CAboutOverlayAU()
290 | {
291 | // Plugin version label
292 | String formatString = String("Audio Units (AU) Plug-in format. \nThe Audio Units logo is a trademark of Apple Computer, Inc. \nCopyright ") +
293 | String(CharPointer_UTF8("\xc2\xa9")) + String(" 2005 Apple Computer, Inc. All rights reserved.");
294 | m_formatInfoLabel = std::make_unique("FormatInfo", formatString);
295 | m_formatInfoLabel->setJustificationType(Justification::topLeft);
296 | m_formatInfoLabel->setFont(Font(13.0, Font::plain));
297 | addAndMakeVisible(m_formatInfoLabel.get());
298 | }
299 |
300 | /**
301 | * Class destructor.
302 | */
303 | CAboutOverlayAU::~CAboutOverlayAU()
304 | {
305 | }
306 |
307 | /**
308 | * Reimplemented to paint the overlay's background.
309 | * @param g Graphics context that must be used to do the drawing operations.
310 | */
311 | void CAboutOverlayAU::paint(Graphics& g)
312 | {
313 | // First paint base class
314 | AAboutOverlay::paint(g);
315 |
316 | // AU logo
317 | Image formatLogo = ImageCache::getFromMemory(BinaryData::logo_au_100x100_png, BinaryData::logo_au_100x100_pngSize);
318 | g.setImageResamplingQuality(Graphics::highResamplingQuality);
319 | g.drawImage(formatLogo, 20, 93, 66, 66, 0, 0, 101, 101);
320 | }
321 |
322 | /**
323 | * Reimplemented to resize and re-postion controls & labels.
324 | */
325 | void CAboutOverlayAU::resized()
326 | {
327 | // First resize base class components
328 | AAboutOverlay::resized();
329 |
330 | m_formatInfoLabel->setBounds(95, 105, getLocalBounds().getWidth() - 135, 70);
331 | }
332 |
333 |
334 | } // namespace dbaudio
335 |
--------------------------------------------------------------------------------
/SoundscapePlugin/Source/About.h:
--------------------------------------------------------------------------------
1 | /*
2 | ===============================================================================
3 |
4 | Copyright (C) 2019 d&b audiotechnik GmbH & Co. KG. All Rights Reserved.
5 |
6 | This file is part of the Soundscape VST, AU, and AAX Plug-in.
7 |
8 | Redistribution and use in source and binary forms, with or without
9 | modification, are permitted provided that the following conditions are met:
10 |
11 | 1. Redistributions of source code must retain the above copyright notice,
12 | this list of conditions and the following disclaimer.
13 |
14 | 2. Redistributions in binary form must reproduce the above copyright notice,
15 | this list of conditions and the following disclaimer in the documentation
16 | and/or other materials provided with the distribution.
17 |
18 | 3. The name of the author may not be used to endorse or promote products
19 | derived from this software without specific prior written permission.
20 |
21 | THIS SOFTWARE IS PROVIDED BY d&b audiotechnik GmbH & Co. KG "AS IS" AND ANY
22 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24 | DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
29 | OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
30 | ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 |
32 | ===============================================================================
33 | */
34 |
35 |
36 | #pragma once
37 |
38 | #include "Gui.h" // // m_versionLabel;
67 |
68 | /**
69 | * Hyperlink to dbaudio.com
70 | */
71 | std::unique_ptr m_dbLink;
72 |
73 | /**
74 | * JUCE copyright label
75 | */
76 | std::unique_ptr m_juceLabel;
77 |
78 | /**
79 | * Text field containing the d&b EULA.
80 | */
81 | std::unique_ptr m_eulaField;
82 |
83 |
84 | JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(AAboutOverlay)
85 | };
86 |
87 |
88 | /**
89 | * Class CAboutOverlayVST is a GUI overlay which provides copyright and licensing info, specific to VST2 and VST3.
90 | */
91 | class CAboutOverlayVST : public AAboutOverlay
92 | {
93 | public:
94 | CAboutOverlayVST();
95 | ~CAboutOverlayVST() override;
96 |
97 | protected:
98 | void paint(Graphics&) override;
99 | void resized() override;
100 |
101 | private:
102 | /**
103 | * Host format license into
104 | */
105 | std::unique_ptr m_formatInfoLabel;
106 |
107 | JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CAboutOverlayVST)
108 | };
109 |
110 |
111 | /**
112 | * Class CAboutOverlayAAX is a GUI overlay which provides copyright and licensing info, specific to AAX (ProTools and S6L).
113 | */
114 | class CAboutOverlayAAX : public AAboutOverlay
115 | {
116 | public:
117 | CAboutOverlayAAX();
118 | ~CAboutOverlayAAX() override;
119 |
120 | protected:
121 | void paint(Graphics&) override;
122 | void resized() override;
123 |
124 | private:
125 | /**
126 | * Host format license into
127 | */
128 | std::unique_ptr m_formatInfoLabel;
129 |
130 | JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CAboutOverlayAAX)
131 | };
132 |
133 |
134 | /**
135 | * Class CAboutOverlayAU is a GUI overlay which provides copyright and licensing info, specific to AAX (ProTools and S6L).
136 | */
137 | class CAboutOverlayAU : public AAboutOverlay
138 | {
139 | public:
140 | CAboutOverlayAU();
141 | ~CAboutOverlayAU() override;
142 |
143 | protected:
144 | void paint(Graphics&) override;
145 | void resized() override;
146 |
147 | private:
148 | /**
149 | * Host format license into
150 | */
151 | std::unique_ptr m_formatInfoLabel;
152 |
153 | JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CAboutOverlayAU)
154 | };
155 |
156 |
157 | } // namespace dbaudio
158 |
--------------------------------------------------------------------------------
/SoundscapePlugin/Source/Common.h:
--------------------------------------------------------------------------------
1 | /*
2 | ===============================================================================
3 |
4 | Copyright (C) 2019 d&b audiotechnik GmbH & Co. KG. All Rights Reserved.
5 |
6 | This file is part of the Soundscape VST, AU, and AAX Plug-in.
7 |
8 | Redistribution and use in source and binary forms, with or without
9 | modification, are permitted provided that the following conditions are met:
10 |
11 | 1. Redistributions of source code must retain the above copyright notice,
12 | this list of conditions and the following disclaimer.
13 |
14 | 2. Redistributions in binary form must reproduce the above copyright notice,
15 | this list of conditions and the following disclaimer in the documentation
16 | and/or other materials provided with the distribution.
17 |
18 | 3. The name of the author may not be used to endorse or promote products
19 | derived from this software without specific prior written permission.
20 |
21 | THIS SOFTWARE IS PROVIDED BY d&b audiotechnik GmbH & Co. KG "AS IS" AND ANY
22 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24 | DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
29 | OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
30 | ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 |
32 | ===============================================================================
33 | */
34 |
35 |
36 | #pragma once
37 |
38 | #include "../JuceLibraryCode/JuceHeader.h"
39 |
40 |
41 | namespace dbaudio
42 | {
43 |
44 |
45 | /**
46 | * Type definitions.
47 | */
48 | typedef juce::int32 SourceId;
49 | typedef juce::int32 PluginId;
50 | typedef juce::uint64 DataChangeTypes;
51 | typedef juce::uint8 ComsMode;
52 |
53 |
54 | /**
55 | * Data Change Source
56 | * Enum used to define where a parameter or property change has originated.
57 | */
58 | enum DataChangeSource
59 | {
60 | DCS_Gui = 0, //< Change was caused by the GUI, i.e. the user turning a knob to change a value.
61 | DCS_Host, //< Change was caused by the VST/AU/AAX host, i.e. a project was loaded or a DAW preset was recalled.
62 | DCS_Osc, //< Change was caused by an incoming OSC message, or caused by internal operations by the Controller.
63 | DCS_Overview, //< Change was caused by the Overview. Similar to DCS_Gui, but specific to the Overview window's GUI.
64 | DCS_Max //< Number of change cources.
65 | };
66 |
67 |
68 | /**
69 | * Automation parameter indeces
70 | */
71 | enum AutomationParameterIndex
72 | {
73 | ParamIdx_X = 0,
74 | ParamIdx_Y,
75 | ParamIdx_ReverbSendGain,
76 | ParamIdx_SourceSpread,
77 | ParamIdx_DelayMode,
78 | ParamIdx_Bypass,
79 | ParamIdx_MaxIndex
80 | };
81 |
82 |
83 | /**
84 | * Data Change Type
85 | * Bitfields used to flag parameter changes.
86 | */
87 | static constexpr DataChangeTypes DCT_None = 0x00000000; //< Nothing has changed.
88 | static constexpr DataChangeTypes DCT_NumPlugins = 0x00000001; //< The number of CPlugin instances in the project has changed.
89 | static constexpr DataChangeTypes DCT_IPAddress = 0x00000002; //< The user has entered a new IP address for the DS100.
90 | static constexpr DataChangeTypes DCT_MessageRate = 0x00000004; //< The user has entered a new interval for OSC messages.
91 | static constexpr DataChangeTypes DCT_Online = 0x00000008; //< The Plug-in's Online status has changed, based on the time since last response.
92 | static constexpr DataChangeTypes DCT_OscConfig = (DCT_IPAddress | DCT_MessageRate | DCT_Online); //< IP address, rate, and Online status.
93 | static constexpr DataChangeTypes DCT_SourceID = 0x00000010; //< The SourceID / Matrix input number of this Plug-in instance has been changed.
94 | static constexpr DataChangeTypes DCT_MappingID = 0x00000020; //< The user has selected a different coordinate mapping for this Plug-in.
95 | static constexpr DataChangeTypes DCT_ComsMode = 0x00000040; //< The Rx / Tx mode of this Plug-in has been changed.
96 | static constexpr DataChangeTypes DCT_PluginInstanceConfig = (DCT_SourceID | DCT_MappingID | DCT_ComsMode); //< SourceID, MappingID, and Rx/Tx.
97 | static constexpr DataChangeTypes DCT_SourcePosition = 0x00000080; //< The X/Y coordinates of this SourceID have changed.
98 | static constexpr DataChangeTypes DCT_ReverbSendGain = 0x00000100; //< The En-Space Gain for this SourceID has changed.
99 | static constexpr DataChangeTypes DCT_SourceSpread = 0x00000200; //< The En-Scene Spread factor for this SourceID has changed.
100 | static constexpr DataChangeTypes DCT_DelayMode = 0x00000400; //< The En-Scene Delay mode (Off/Tight/Full) of this SourceID has changed.
101 | static constexpr DataChangeTypes DCT_Bypass = 0x00000800; //< The OSC Bypass parameter has changed.
102 | static constexpr DataChangeTypes DCT_AutomationParameters = (DCT_SourcePosition | DCT_ReverbSendGain | DCT_SourceSpread | DCT_DelayMode | DCT_Bypass); //< All automation parameters.
103 | static constexpr DataChangeTypes DCT_DebugMessage = 0x00001000; //< There is a new debug message to be displayed on the GUI.
104 |
105 |
106 | /**
107 | * OSC Communication mode
108 | */
109 | static constexpr ComsMode CM_Off = 0x0000; //< OSC communication is inactive.
110 | static constexpr ComsMode CM_Rx = 0x0001; //< The Plug-in sends only requests, and accepts all responses, but sends no SET commands.
111 | static constexpr ComsMode CM_Tx = 0x0002; //< The Plug-in sends SET commands when necessary. It sends no requests, and ignores all responses.
112 | static constexpr ComsMode CM_PollOnce = 0x0004; //< The X/Y coordinates have been requested once after a MappingID change. This flag is removed once the response is received.
113 | static constexpr ComsMode CM_Sync = (CM_Rx | CM_Tx); //< The Plug-in sends SET commands when necessary, else sends requests, and accepts all responses.
114 |
115 |
116 | } // namespace dbaudio
117 |
--------------------------------------------------------------------------------
/SoundscapePlugin/Source/Controller.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | ===============================================================================
3 |
4 | Copyright (C) 2019 d&b audiotechnik GmbH & Co. KG. All Rights Reserved.
5 |
6 | This file is part of the Soundscape VST, AU, and AAX Plug-in.
7 |
8 | Redistribution and use in source and binary forms, with or without
9 | modification, are permitted provided that the following conditions are met:
10 |
11 | 1. Redistributions of source code must retain the above copyright notice,
12 | this list of conditions and the following disclaimer.
13 |
14 | 2. Redistributions in binary form must reproduce the above copyright notice,
15 | this list of conditions and the following disclaimer in the documentation
16 | and/or other materials provided with the distribution.
17 |
18 | 3. The name of the author may not be used to endorse or promote products
19 | derived from this software without specific prior written permission.
20 |
21 | THIS SOFTWARE IS PROVIDED BY d&b audiotechnik GmbH & Co. KG "AS IS" AND ANY
22 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24 | DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
29 | OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
30 | ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 |
32 | ===============================================================================
33 | */
34 |
35 |
36 | #include "Controller.h"
37 | #include "Overview.h"
38 | #include "PluginProcessor.h"
39 |
40 |
41 | namespace dbaudio
42 | {
43 |
44 |
45 | static constexpr int OSC_INTERVAL_MIN = 40; //< Minimum supported OSC messaging rate in milliseconds
46 | static constexpr int OSC_INTERVAL_MAX = 5000; //< Maximum supported OSC messaging rate in milliseconds
47 | static constexpr int OSC_INTERVAL_DEF = 50; //< Default OSC messaging rate in milliseconds
48 |
49 | static const String OSC_DEFAULT_IP("127.0.0.1"); //< Default IP Address
50 |
51 | static constexpr int RX_PORT_DS100 = 50010; //< UDP port which the DS100 is listening to for OSC
52 | static constexpr int RX_PORT_HOST = 50011; //< UDP port to which the DS100 will send OSC replies
53 |
54 | static constexpr int KEEPALIVE_TIMEOUT = 5000; //< Milliseconds without response after which we consider plugin "Offline"
55 | static constexpr int KEEPALIVE_INTERVAL = 1500; //< Interval at which keepalive (ping) messages are sent, in milliseconds
56 | static constexpr int MAX_HEARTBEAT_COUNT = 0xFFFF; //< No point counting beyond this number.
57 |
58 |
59 | /**
60 | * Pre-defined OSC command and response strings
61 | */
62 | static const String kOscDelimiterString("/");
63 | static const String kOscCommandString_ping("/ping");
64 | static const String kOscCommandString_source_position_xy("/dbaudio1/coordinatemapping/source_position_xy/%d/%d");
65 | static const String kOscCommandString_reverbsendgain("/dbaudio1/matrixinput/reverbsendgain/%d");
66 | static const String kOscCommandString_source_spread("/dbaudio1/positioning/source_spread/%d");
67 | static const String kOscCommandString_source_delaymode("/dbaudio1/positioning/source_delaymode/%d");
68 | static const String kOscResponseString_pong("/pong");
69 | static const String kOscResponseString_source_position_xy("/dbaudio1/coordinatemapping/source_position_xy");
70 | static const String kOscResponseString_reverbsendgain("/dbaudio1/matrixinput/reverbsendgain");
71 | static const String kOscResponseString_source_spread("/dbaudio1/positioning/source_spread");
72 | static const String kOscResponseString_source_delaymode("/dbaudio1/positioning/source_delaymode");
73 |
74 |
75 |
76 |
77 | /*
78 | ===============================================================================
79 | Class CController
80 | ===============================================================================
81 | */
82 |
83 | /**
84 | * The one and only instance of CController.
85 | */
86 | CController* CController::m_singleton = nullptr;
87 |
88 | /**
89 | * Constructs an CController object.
90 | * There can be only one instance of this class, see m_singleton. This is so that network traffic
91 | * is managed from a central point and only one UDP port is opened for all OSC communication.
92 | */
93 | CController::CController()
94 | {
95 | jassert(!m_singleton); // only one instnce allowed!!
96 | m_singleton = this;
97 |
98 | m_ipAddress = String("");
99 | m_oscMsgRate = 0;
100 |
101 | // Clear all changed flags initially
102 | for (int cs = 0; cs < DCS_Max; cs++)
103 | m_parametersChanged[cs] = DCT_None;
104 |
105 | // CController derives from OSCReceiver::Listener
106 | m_oscReceiver.addListener(this);
107 |
108 | // Default OSC server settings. These might become overwritten
109 | // by setStateInformation()
110 | SetRate(DCS_Osc, OSC_INTERVAL_DEF);
111 | SetIpAddress(DCS_Osc, OSC_DEFAULT_IP);
112 | }
113 |
114 | /**
115 | * Destroys the CController.
116 | */
117 | CController::~CController()
118 | {
119 | stopTimer();
120 | DisconnectOsc();
121 |
122 | // Destroy overView window and overView Manager
123 | COverviewManager* ovrMgr = COverviewManager::GetInstance();
124 | if (ovrMgr)
125 | ovrMgr->CloseOverview(true);
126 |
127 | const ScopedLock lock(m_mutex);
128 | m_processors.clearQuick();
129 |
130 | m_singleton = nullptr;
131 | }
132 |
133 | /**
134 | * Returns the one and only instance of CController. If it doesn't exist yet, it is created.
135 | * @return The CController singleton object.
136 | * @sa m_singleton, CController
137 | */
138 | CController* CController::GetInstance()
139 | {
140 | if (m_singleton == nullptr)
141 | {
142 | m_singleton = new CController();
143 | }
144 | return m_singleton;
145 | }
146 |
147 | /**
148 | * Method which will be called every time a parameter or property has been changed.
149 | * @param changeSource The application module which is causing the property change.
150 | * @param changeTypes Defines which parameter or property has been changed.
151 | */
152 | void CController::SetParameterChanged(DataChangeSource changeSource, DataChangeTypes changeTypes)
153 | {
154 | const ScopedLock lock(m_mutex);
155 |
156 | // Set the specified change flag for all DataChangeSources, except for the one causing the change.
157 | for (int cs = 0; cs < DCS_Max; cs++)
158 | {
159 | m_parametersChanged[cs] |= changeTypes;
160 | }
161 |
162 | // Forward the change to all plugin instances. This is needed, for example, so that all plugin's
163 | // GUIs update an IP address change.
164 | for (int i = 0; i < m_processors.size(); ++i)
165 | {
166 | m_processors[i]->SetParameterChanged(changeSource, changeTypes);
167 | }
168 | }
169 |
170 | /**
171 | * Get the state of the desired flag (or flags) for the desired change source.
172 | * @param changeSource The application module querying the change flag.
173 | * @param change The desired parameter (or parameters).
174 | * @return True if any of the given parameters has changed it's value
175 | * since the last time PopParameterChanged() was called.
176 | */
177 | bool CController::GetParameterChanged(DataChangeSource changeSource, DataChangeTypes change)
178 | {
179 | const ScopedLock lock(m_mutex);
180 | return ((m_parametersChanged[changeSource] & change) != 0);
181 | }
182 |
183 | /**
184 | * Reset the state of the desired flag (or flags) for the desired change source.
185 | * Will return the state of the flag before the resetting.
186 | * @param changeSource The application module querying the change flag.
187 | * @param change The desired parameter (or parameters).
188 | * @return The state of the flag before the resetting.
189 | */
190 | bool CController::PopParameterChanged(DataChangeSource changeSource, DataChangeTypes change)
191 | {
192 | const ScopedLock lock(m_mutex);
193 | bool ret((m_parametersChanged[changeSource] & change) != 0);
194 | m_parametersChanged[changeSource] &= ~change; // Reset flag.
195 | return ret;
196 | }
197 |
198 | /**
199 | * Register a plugin instance to the local list of processors.
200 | * @param p Pointer to newly crated plugin processor object.
201 | * @return The PluginId of the newly added Plug-in.
202 | */
203 | PluginId CController::AddProcessor(CPlugin* p)
204 | {
205 | const ScopedLock lock(m_mutex);
206 |
207 | // Get the highest Input number of all current Plugins.
208 | SourceId currentMaxSourceId = 0;
209 | for (int i = 0; i < m_processors.size(); ++i)
210 | {
211 | if (m_processors[i]->GetSourceId() > currentMaxSourceId)
212 | currentMaxSourceId = m_processors[i]->GetSourceId();
213 | }
214 |
215 | m_processors.add(p);
216 | SetParameterChanged(DCS_Osc, DCT_NumPlugins);
217 |
218 | // Set the new Plugin's InputID to the next in sequence.
219 | p->SetSourceId(DCS_Osc, currentMaxSourceId + 1);
220 |
221 | PluginId newPluginId = static_cast(m_processors.size() - 1);
222 | #ifdef DB_SHOW_DEBUG
223 | p->PushDebugMessage(String::formatted("++ CController::AddProcessor: pId=%d ++", newPluginId));
224 | #endif
225 |
226 | return newPluginId;
227 | }
228 |
229 | /**
230 | * Remove a plugin instance from the local list of processors.
231 | * @param p Pointer to plugin processor object which should be removed.
232 | */
233 | void CController::RemoveProcessor(CPlugin* p)
234 | {
235 | if (m_processors.size() > 1)
236 | {
237 | int idx = m_processors.indexOf(p);
238 | jassert(idx >= 0); // Tried to remove inexistent plugin object.
239 | if (idx >= 0)
240 | {
241 | const ScopedLock lock(m_mutex);
242 | m_processors.remove(idx);
243 |
244 | SetParameterChanged(DCS_Osc, DCT_NumPlugins);
245 | }
246 | }
247 |
248 | // If last plugin instance is being removed, delete CController singleton.
249 | else if (m_processors.size() == 1)
250 | {
251 | { // Scope for lock.
252 | const ScopedLock lock(m_mutex);
253 | m_processors.clearQuick();
254 | }
255 |
256 | delete this;
257 | }
258 | }
259 |
260 | /**
261 | * Number of registered plugin instances.
262 | * @return Number of registered plugin instances.
263 | */
264 | int CController::GetProcessorCount() const
265 | {
266 | const ScopedLock lock(m_mutex);
267 | return m_processors.size();
268 | }
269 |
270 | /**
271 | * Get a pointer to a specified processor.
272 | * @param idx The index of the desired processor.
273 | * @return The pointer to the desired processor.
274 | */
275 | CPlugin* CController::GetProcessor(PluginId idx) const
276 | {
277 | const ScopedLock lock(m_mutex);
278 | if ((idx >= 0) && (idx < m_processors.size()))
279 | return m_processors[idx];
280 |
281 | jassertfalse; // Index out of range!
282 | return nullptr;
283 | }
284 |
285 | /**
286 | * Getter function for the IP address to which m_oscSender and m_oscReceiver are connected.
287 | * @return Current IP address.
288 | */
289 | String CController::GetIpAddress() const
290 | {
291 | return m_ipAddress;
292 | }
293 |
294 | /**
295 | * Static methiod which returns the default IP address.
296 | * @return IP address to use as default.
297 | */
298 | String CController::GetDefaultIpAddress()
299 | {
300 | return OSC_DEFAULT_IP;
301 | }
302 |
303 | /**
304 | * Setter function for the IP address to which m_oscSender and m_oscReceiver are connected.
305 | * NOTE: changing ip address will disconnect m_oscSender and m_oscReceiver.
306 | * @param changeSource The application module which is causing the property change.
307 | * @param ipAddress New IP address.
308 | */
309 | void CController::SetIpAddress(DataChangeSource changeSource, String ipAddress)
310 | {
311 | if (m_ipAddress != ipAddress)
312 | {
313 | const ScopedLock lock(m_mutex);
314 |
315 | m_ipAddress = ipAddress;
316 |
317 | // Start "offline" after changing IP address
318 | m_heartBeatsRx = MAX_HEARTBEAT_COUNT;
319 | m_heartBeatsTx = 0;
320 |
321 | // Signal the change to all plugins.
322 | SetParameterChanged(changeSource, (DCT_IPAddress | DCT_Online));
323 |
324 | ReconnectOsc();
325 | }
326 | }
327 |
328 | /**
329 | * Getter function for the OSC communication state.
330 | * @return True if a valid OSC message was received and successfully processed recently.
331 | * False if no response was received for longer than the timeout threshold.
332 | */
333 | bool CController::GetOnline() const
334 | {
335 | return ((m_heartBeatsRx * m_oscMsgRate) < KEEPALIVE_TIMEOUT);
336 | }
337 |
338 | /**
339 | * Getter for the rate at which OSC messages are being sent out.
340 | * @return Messaging rate, in milliseconds.
341 | */
342 | int CController::GetRate() const
343 | {
344 | return m_oscMsgRate;
345 | }
346 |
347 | /**
348 | * Setter for the rate at which OSC messages are being sent out.
349 | * @param changeSource The application module which is causing the property change.
350 | * @param rate New messaging rate, in milliseconds.
351 | */
352 | void CController::SetRate(DataChangeSource changeSource, int rate)
353 | {
354 | if (rate != m_oscMsgRate)
355 | {
356 | const ScopedLock lock(m_mutex);
357 |
358 | // Clip rate to the allowed range.
359 | rate = jmin(OSC_INTERVAL_MAX, jmax(OSC_INTERVAL_MIN, rate));
360 |
361 | m_oscMsgRate = rate;
362 |
363 | // Signal the change to all plugins.
364 | SetParameterChanged(changeSource, DCT_MessageRate);
365 |
366 | // Reset timer to the new interval.
367 | startTimer(m_oscMsgRate);
368 | }
369 | }
370 |
371 | /**
372 | * Static methiod which returns the allowed minimum and maximum OSC message rates.
373 | * @return Returns a std::pair where the first number is the minimum supported rate,
374 | * and the second number is the maximum.
375 | */
376 | std::pair CController::GetSupportedRateRange()
377 | {
378 | return std::pair(OSC_INTERVAL_MIN, OSC_INTERVAL_MAX);
379 | }
380 |
381 | /**
382 | * Method to initialize IP address and polling rate.
383 | * @param changeSource The application module which is causing the property change.
384 | * @param ipAddress New IP address.
385 | * @param rate New messaging rate, in milliseconds.
386 | */
387 | void CController::InitGlobalSettings(DataChangeSource changeSource, String ipAddress, int rate)
388 | {
389 | SetIpAddress(changeSource, ipAddress);
390 | SetRate(changeSource, rate);
391 | }
392 |
393 | /**
394 | * Called when the OSCReceiver receives a new OSC message, since CController inherits from OSCReceiver::Listener.
395 | * It forwards the message to all registered plugin objects.
396 | * @param message The received OSC message.
397 | */
398 | void CController::oscMessageReceived(const OSCMessage &message)
399 | {
400 | const ScopedLock lock(m_mutex);
401 | jassert(m_processors.size() > 0);
402 |
403 | if (m_processors.size() > 0)
404 | {
405 | int i;
406 | bool resetHeartbeat = false;
407 |
408 | // Check if the incoming message is a response to a sent "ping".
409 | String addressString = message.getAddressPattern().toString();
410 | if (addressString.startsWith(kOscResponseString_pong))
411 | resetHeartbeat = true;
412 |
413 | // Check if the incoming message contains parameters.
414 | else if (message.size() > 0)
415 | {
416 | // Parse the Source ID
417 | SourceId sourceId = (addressString.fromLastOccurrenceOf(kOscDelimiterString, false, true)).getIntValue();
418 | jassert(sourceId > 0);
419 | if (sourceId > 0)
420 | {
421 | AutomationParameterIndex pIdx = ParamIdx_MaxIndex;
422 | DataChangeTypes change = DCT_None;
423 | int mappingId = 0;
424 |
425 | // Determine which parameter was changed depending on the incoming message's address pattern.
426 | if (addressString.startsWith(kOscResponseString_source_position_xy))
427 | {
428 | // Parse the Mapping ID
429 | addressString = addressString.upToLastOccurrenceOf(kOscDelimiterString, false, true);
430 | mappingId = (addressString.fromLastOccurrenceOf(kOscDelimiterString, false, true)).getIntValue();
431 | jassert(mappingId > 0);
432 |
433 | pIdx = ParamIdx_X;
434 | change = DCT_SourcePosition;
435 | }
436 | else if (addressString.startsWith(kOscResponseString_reverbsendgain))
437 | {
438 | pIdx = ParamIdx_ReverbSendGain;
439 | change = DCT_ReverbSendGain;
440 | }
441 | else if (addressString.startsWith(kOscResponseString_source_spread))
442 | {
443 | pIdx = ParamIdx_SourceSpread;
444 | change = DCT_SourceSpread;
445 | }
446 | else if (addressString.startsWith(kOscResponseString_source_delaymode))
447 | {
448 | pIdx = ParamIdx_DelayMode;
449 | change = DCT_DelayMode;
450 | }
451 |
452 | // Continue if the message's address pattern was recognized
453 | if (change != DCT_None)
454 | {
455 | // Check all plugin instances to see if any of them want the new coordinates.
456 | for (i = 0; i < m_processors.size(); ++i)
457 | {
458 | // Check for matching Input number.
459 | CPlugin* plugin = m_processors[i];
460 | if (sourceId == plugin->GetSourceId())
461 | {
462 | // Check if a SET command was recently sent out and might currently be on transit to the device.
463 | // If so, ignore the incoming message so that our local data does not jump back to a now outdated value.
464 | bool ignoreResponse = plugin->IsParamInTransit(change);
465 | ComsMode mode = plugin->GetComsMode();
466 |
467 | // Only pass on new positions to plugins that are in RX mode.
468 | // Also, ignore all incoming messages for properties which this plugin wants to send a set command.
469 | if (!ignoreResponse && ((mode & (CM_Rx | CM_PollOnce)) != 0) && (plugin->GetParameterChanged(DCS_Osc, change) == false))
470 | {
471 | // Special handling for X/Y position, since message contains two parameters and MappingID needs to match too.
472 | if (pIdx == ParamIdx_X)
473 | {
474 | if (mappingId == plugin->GetMappingId())
475 | {
476 | // Set the plugin's new position.
477 | plugin->SetParameterValue(DCS_Osc, ParamIdx_X, message[0].getFloat32());
478 | plugin->SetParameterValue(DCS_Osc, ParamIdx_Y, message[1].getFloat32());
479 |
480 | // A request was sent to the DS100 by the CController because this plugin was in CM_PollOnce mode.
481 | // Since the response was now processed, set the plugin back into it's original mode.
482 | if ((mode & CM_PollOnce) == CM_PollOnce)
483 | {
484 | mode &= ~CM_PollOnce;
485 | plugin->SetComsMode(DCS_Osc, mode);
486 | }
487 | }
488 | }
489 |
490 | // All other automation parameters.
491 | else
492 | {
493 | // DelayMode is an integer.
494 | float newValue;
495 | if ((pIdx == ParamIdx_DelayMode) && message[0].isInt32())
496 | newValue = static_cast(message[0].getInt32());
497 | else
498 | newValue = message[0].getFloat32();
499 |
500 | plugin->SetParameterValue(DCS_Osc, pIdx, newValue);
501 | }
502 | }
503 | }
504 | }
505 |
506 | // Since pIdx was set, we know the received OSC message has valid format.
507 | // -> Signal to reset the number of heartbeats since last response.
508 | resetHeartbeat = true;
509 | }
510 | }
511 | }
512 |
513 | // A valid OSC message was received and successfully processed
514 | // -> reset the number of heartbeats since last response.
515 | if (resetHeartbeat)
516 | {
517 | bool wasOnline = GetOnline();
518 | m_heartBeatsRx = 0;
519 |
520 | // If previous state was "Offline", force all plugins to
521 | // update their GUI, since we are now Online.
522 | if (!wasOnline)
523 | {
524 | SetParameterChanged(DCS_Osc, DCT_Online);
525 | }
526 | }
527 | }
528 | }
529 |
530 | /**
531 | * Send a OSCMessage out to the connected ip address.
532 | * @param message The OSC message to be sent.
533 | */
534 | bool CController::SendOSCMessage(OSCMessage message)
535 | {
536 | bool ret = (m_oscSender.send(message));
537 | if (ret)
538 | m_heartBeatsTx = 0;
539 | return ret;
540 | }
541 |
542 | /**
543 | * Disconnect the OSCSender from it's host.
544 | */
545 | void CController::DisconnectOsc()
546 | {
547 | m_oscSender.disconnect();
548 | m_oscReceiver.disconnect();
549 | }
550 |
551 | /**
552 | * Disconnect and re-connect the OSCSender to a host specified by the current ip settings.
553 | */
554 | void CController::ReconnectOsc()
555 | {
556 | DisconnectOsc();
557 |
558 | // Connect both sender and receiver
559 | bool ok = m_oscSender.connect(m_ipAddress, RX_PORT_DS100);
560 | jassert(ok);
561 |
562 | ok = m_oscReceiver.connect(RX_PORT_HOST);
563 | jassert(ok);
564 | }
565 |
566 | /**
567 | * Timer callback function, which will be called at regular intervals to
568 | * send out OSC messages.
569 | * Reimplemented from base class Timer.
570 | */
571 | void CController::timerCallback()
572 | {
573 | const ScopedLock lock(m_mutex);
574 | if (m_processors.size() > 0)
575 | {
576 | // Check that we don't flood the line with pings, only send them in small intervals.
577 | bool sendKeepAlive = (((m_heartBeatsRx * m_oscMsgRate) > KEEPALIVE_INTERVAL) ||
578 | ((m_heartBeatsTx * m_oscMsgRate) > KEEPALIVE_INTERVAL));
579 |
580 | int i;
581 | CPlugin* pro = nullptr;
582 | ComsMode mode;
583 | String messageString;
584 |
585 | for (i = 0; i < m_processors.size(); ++i)
586 | {
587 | pro = m_processors[i];
588 |
589 | // If the OscBypass parameter has changed since the last interval,
590 | // update the OSC Rx/Tx mode of each Plugin accordingly.
591 | bool oscBypassed = pro->GetBypass();
592 | if (pro->PopParameterChanged(DCS_Osc, DCT_Bypass))
593 | {
594 | if (oscBypassed)
595 | pro->SetComsMode(DCS_Osc, CM_Off);
596 | else
597 | pro->RestoreComsMode(DCS_Osc);
598 |
599 | // Changing ComsMode also sets the changed flag for Bypass.
600 | // Clear it so we don't come in here again unnecessarily.
601 | pro->PopParameterChanged(DCS_Osc, DCT_Bypass);
602 | }
603 | mode = pro->GetComsMode();
604 |
605 | // Signal every timer tick to each plugin instance.
606 | // This is used to trigger gestures for touch automation.
607 | pro->Tick();
608 |
609 | // If plugin is in Bypass, we can skip all of the stuff below.
610 | if (!oscBypassed)
611 | {
612 | bool msgSent;
613 | DataChangeTypes paramSetsInTransit = DCT_None;
614 |
615 | // Iterate through all automation parameters.
616 | for (int pIdx = ParamIdx_X; pIdx < ParamIdx_MaxIndex; ++pIdx)
617 | {
618 | msgSent = false;
619 |
620 | switch (pIdx)
621 | {
622 | case ParamIdx_X:
623 | {
624 | // SET command is only sent out while in CM_Tx mode, provided that
625 | // this parameter has been changed since the last timer tick.
626 | if (((mode & CM_Tx) == CM_Tx) && pro->GetParameterChanged(DCS_Osc, DCT_SourcePosition))
627 | {
628 | messageString = String::formatted(kOscCommandString_source_position_xy, pro->GetMappingId(), pro->GetSourceId());
629 | msgSent = SendOSCMessage(OSCMessage(messageString, pro->GetParameterValue(ParamIdx_X), pro->GetParameterValue(ParamIdx_Y)));
630 | paramSetsInTransit |= DCT_SourcePosition;
631 | }
632 |
633 | // GET command for x/y coordinates is only sent out while in CM_Rx or CM_PollOnce mode,
634 | // provided that we didn't already send a SET command. Get command is just the OSC address pattern without parameters.
635 | if ((!msgSent) && ((mode & (CM_Rx | CM_PollOnce)) != 0))
636 | {
637 | messageString = String::formatted(kOscCommandString_source_position_xy, pro->GetMappingId(), pro->GetSourceId());
638 | msgSent = SendOSCMessage(OSCMessage(messageString));
639 | }
640 | }
641 | break;
642 |
643 | case ParamIdx_Y:
644 | // Changes to ParamIdx_Y are handled together with ParamIdx_X, so skip it.
645 | continue;
646 | break;
647 |
648 | case ParamIdx_ReverbSendGain:
649 | {
650 | // SET command is only sent out while in CM_Tx mode, provided that
651 | // this parameter has been changed since the last timer tick.
652 | if (((mode & CM_Tx) == CM_Tx) && pro->GetParameterChanged(DCS_Osc, DCT_ReverbSendGain))
653 | {
654 | messageString = String::formatted(kOscCommandString_reverbsendgain, pro->GetSourceId());
655 | msgSent = SendOSCMessage(OSCMessage(messageString, pro->GetParameterValue(ParamIdx_ReverbSendGain)));
656 | paramSetsInTransit |= DCT_ReverbSendGain;
657 | }
658 |
659 | // GET command is only sent out while in CM_Rx mode, provided that we
660 | // didn't already send a SET command. Get command is just the OSC address pattern without parameters.
661 | if ((!msgSent) && ((mode & CM_Rx) == CM_Rx))
662 | {
663 | messageString = String::formatted(kOscCommandString_reverbsendgain, pro->GetSourceId());
664 | msgSent = SendOSCMessage(OSCMessage(messageString));
665 | }
666 | }
667 | break;
668 |
669 | case ParamIdx_SourceSpread:
670 | {
671 | // SET command is only sent out while in CM_Tx mode, provided that
672 | // this parameter has been changed since the last timer tick.
673 | if (((mode & CM_Tx) == CM_Tx) && pro->GetParameterChanged(DCS_Osc, DCT_SourceSpread))
674 | {
675 | messageString = String::formatted(kOscCommandString_source_spread, pro->GetSourceId());
676 | msgSent = SendOSCMessage(OSCMessage(messageString, pro->GetParameterValue(ParamIdx_SourceSpread)));
677 | paramSetsInTransit |= DCT_SourceSpread;
678 | }
679 |
680 | // GET command is only sent out while in CM_Rx mode, provided that we
681 | // didn't already send a SET command. Get command is just the OSC address pattern without parameters.
682 | if ((!msgSent) && ((mode & CM_Rx) == CM_Rx))
683 | {
684 | messageString = String::formatted(kOscCommandString_source_spread, pro->GetSourceId());
685 | msgSent = SendOSCMessage(OSCMessage(messageString));
686 | }
687 | }
688 | break;
689 |
690 | case ParamIdx_DelayMode:
691 | {
692 | // SET command is only sent out while in CM_Tx mode, provided that
693 | // this parameter has been changed since the last timer tick.
694 | if (((mode & CM_Tx) == CM_Tx) && pro->GetParameterChanged(DCS_Osc, DCT_DelayMode))
695 | {
696 | messageString = String::formatted(kOscCommandString_source_delaymode, pro->GetSourceId());
697 | msgSent = SendOSCMessage(OSCMessage(messageString, static_cast(pro->GetParameterValue(ParamIdx_DelayMode))));
698 | paramSetsInTransit |= DCT_DelayMode;
699 | }
700 |
701 | // GET command is only sent out while in CM_Rx mode, provided that we
702 | // didn't already send a SET command. Get command is just the OSC address pattern without parameters.
703 | if ((!msgSent) && ((mode & CM_Rx) == CM_Rx))
704 | {
705 | messageString = String::formatted(kOscCommandString_source_delaymode, pro->GetSourceId());
706 | msgSent = SendOSCMessage(OSCMessage(messageString));
707 | }
708 | }
709 | break;
710 |
711 | case ParamIdx_Bypass:
712 | // Nothing to do, this is not a parameter which will arrive per OSC.
713 | continue;
714 | break;
715 |
716 | default:
717 | jassertfalse;
718 | break;
719 | }
720 |
721 | if (msgSent)
722 | {
723 | // Since we are expecting at least one response from the DS100,
724 | // we can use that as heartbeat, no need to send an extra ping.
725 | sendKeepAlive = false;
726 | }
727 | }
728 |
729 | // Flag the parameters for which we just sent a SET command out.
730 | pro->SetParamInTransit(paramSetsInTransit);
731 | }
732 |
733 | // All changed parameters were sent out, so we can reset their flags now.
734 | pro->PopParameterChanged(DCS_Osc, DCT_AutomationParameters);
735 | }
736 |
737 | if (sendKeepAlive)
738 | {
739 | // If we aren't expecting any responses from the DS100, we need to at least send a "ping"
740 | // so that we can use the "pong" to check our connection status.
741 | // See handling of "pong" in oscMessageReceived()
742 | OSCMessage oscMessage(kOscCommandString_ping);
743 | SendOSCMessage(oscMessage);
744 | }
745 |
746 | bool wasOnline = GetOnline();
747 | if (m_heartBeatsRx < MAX_HEARTBEAT_COUNT)
748 | m_heartBeatsRx++;
749 | if (m_heartBeatsTx < MAX_HEARTBEAT_COUNT)
750 | m_heartBeatsTx++;
751 |
752 | // If we have just crossed the treshold, force all plugins to update their
753 | // GUI, since we are now Offline.
754 | if (wasOnline && (GetOnline() == false))
755 | SetParameterChanged(DCS_Osc, DCT_Online);
756 | }
757 | }
758 |
759 |
760 | } // namespace dbaudio
761 |
--------------------------------------------------------------------------------
/SoundscapePlugin/Source/Controller.h:
--------------------------------------------------------------------------------
1 | /*
2 | ===============================================================================
3 |
4 | Copyright (C) 2019 d&b audiotechnik GmbH & Co. KG. All Rights Reserved.
5 |
6 | This file is part of the Soundscape VST, AU, and AAX Plug-in.
7 |
8 | Redistribution and use in source and binary forms, with or without
9 | modification, are permitted provided that the following conditions are met:
10 |
11 | 1. Redistributions of source code must retain the above copyright notice,
12 | this list of conditions and the following disclaimer.
13 |
14 | 2. Redistributions in binary form must reproduce the above copyright notice,
15 | this list of conditions and the following disclaimer in the documentation
16 | and/or other materials provided with the distribution.
17 |
18 | 3. The name of the author may not be used to endorse or promote products
19 | derived from this software without specific prior written permission.
20 |
21 | THIS SOFTWARE IS PROVIDED BY d&b audiotechnik GmbH & Co. KG "AS IS" AND ANY
22 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24 | DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
29 | OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
30 | ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 |
32 | ===============================================================================
33 | */
34 |
35 |
36 | #pragma once
37 |
38 | #include "Common.h"
39 | #include //,
59 | private Timer
60 | {
61 | public:
62 | CController();
63 | ~CController() override;
64 | static CController* GetInstance();
65 |
66 | bool GetParameterChanged(DataChangeSource changeSource, DataChangeTypes change);
67 | bool PopParameterChanged(DataChangeSource changeSource, DataChangeTypes change);
68 | void SetParameterChanged(DataChangeSource changeSource, DataChangeTypes changeTypes);
69 |
70 | PluginId AddProcessor(CPlugin* p);
71 | void RemoveProcessor(CPlugin* p);
72 | int GetProcessorCount() const;
73 | CPlugin* GetProcessor(PluginId idx) const;
74 |
75 | String GetIpAddress() const;
76 | static String GetDefaultIpAddress();
77 | void SetIpAddress(DataChangeSource changeSource, String ipAddress);
78 |
79 | int GetRate() const;
80 | void SetRate(DataChangeSource changeSource, int rate);
81 | static std::pair GetSupportedRateRange();
82 |
83 | void InitGlobalSettings(DataChangeSource changeSource, String ipAddress, int rate);
84 |
85 | void DisconnectOsc();
86 | void ReconnectOsc();
87 | bool GetOnline() const;
88 |
89 | void oscMessageReceived(const OSCMessage &message) override;
90 | bool SendOSCMessage(OSCMessage message);
91 |
92 | private:
93 | void timerCallback() override;
94 |
95 | protected:
96 | /**
97 | * The one and only instance of CController.
98 | */
99 | static CController *m_singleton;
100 |
101 | /**
102 | * List of registered Plug-in processor instances.
103 | * Incoming OSC messages will be forwarded to all processors on the list.
104 | * When adding Plug-in instances to a project (i.e. one for each DAW track), this list will grow.
105 | * When removing Plug-in instances from a project, this list will shrink. When the list becomes empty,
106 | * The CController singleton object is no longer necessary and will destruct itself.
107 | */
108 | Array m_processors;
109 |
110 | /**
111 | * An OSCSender object can connect to a network port. It then can send OSC
112 | * messages and bundles to a specified host over an UDP socket.
113 | */
114 | OSCSender m_oscSender;
115 |
116 | /**
117 | * An OSCReceiver object can connect to a network port, receive incoming OSC packets from the network
118 | * via UDP, parse them, and forward the included OSCMessage and OSCBundle objects to its listeners.
119 | */
120 | OSCReceiver m_oscReceiver;
121 |
122 | /**
123 | * IP Address where OSC messages will be sent to / received from.
124 | */
125 | String m_ipAddress;
126 |
127 | /**
128 | * Interval at which OSC messages are sent to the host, in ms.
129 | */
130 | int m_oscMsgRate;
131 |
132 | /**
133 | * Keep track of which OSC parameters have changed recently.
134 | * The array has one entry for each application module (see enum DataChangeSource).
135 | */
136 | DataChangeTypes m_parametersChanged[DCS_Max];
137 |
138 | /**
139 | * Number of timer intervals since the last successful OSC message was received.
140 | */
141 | int m_heartBeatsRx;
142 |
143 | /**
144 | * Number of timer intervals since the last OSC message was sent out.
145 | */
146 | int m_heartBeatsTx;
147 |
148 | /**
149 | * A re-entrant mutex. Safety first.
150 | */
151 | CriticalSection m_mutex;
152 |
153 | JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CController)
154 | };
155 |
156 |
157 | } // namespace dbaudio
158 |
--------------------------------------------------------------------------------
/SoundscapePlugin/Source/Gui.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | ===============================================================================
3 |
4 | Copyright (C) 2019 d&b audiotechnik GmbH & Co. KG. All Rights Reserved.
5 |
6 | This file is part of the Soundscape VST, AU, and AAX Plug-in.
7 |
8 | Redistribution and use in source and binary forms, with or without
9 | modification, are permitted provided that the following conditions are met:
10 |
11 | 1. Redistributions of source code must retain the above copyright notice,
12 | this list of conditions and the following disclaimer.
13 |
14 | 2. Redistributions in binary form must reproduce the above copyright notice,
15 | this list of conditions and the following disclaimer in the documentation
16 | and/or other materials provided with the distribution.
17 |
18 | 3. The name of the author may not be used to endorse or promote products
19 | derived from this software without specific prior written permission.
20 |
21 | THIS SOFTWARE IS PROVIDED BY d&b audiotechnik GmbH & Co. KG "AS IS" AND ANY
22 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24 | DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
29 | OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
30 | ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 |
32 | ===============================================================================
33 | */
34 |
35 |
36 | #include "Gui.h"
37 |
38 |
39 | namespace dbaudio
40 | {
41 |
42 |
43 | /*
44 | ===============================================================================
45 | Class CDbStyle
46 | ===============================================================================
47 | */
48 |
49 | /**
50 | * Get the desired color.
51 | * @param color Desired color code.
52 | */
53 | Colour CDbStyle::GetDbColor(DbColor color)
54 | {
55 | switch (color)
56 | {
57 | case WindowColor:
58 | return Colour(27, 27, 27);
59 | case DarkLineColor:
60 | return Colour(49, 49, 49);
61 | case DarkColor:
62 | return Colour(67, 67, 67);
63 | case MidColor:
64 | return Colour(83, 83, 83);
65 | case ButtonColor:
66 | return Colour(125, 125, 125);
67 | case LightColor:
68 | return Colour(201, 201, 201);
69 | case TextColor:
70 | return Colour(238, 238, 238);
71 | case DarkTextColor:
72 | return Colour(180, 180, 180);
73 | case HighlightColor:
74 | return Colour(115, 140, 155);
75 | case FaderGreenColor:
76 | return Colour(140, 180, 90);
77 | case ButtonBlueColor:
78 | return Colour(27, 120, 163);
79 | default:
80 | break;
81 | }
82 |
83 | jassertfalse;
84 | return Colours::black;
85 | }
86 |
87 |
88 | /*
89 | ===============================================================================
90 | Class CSlider
91 | ===============================================================================
92 | */
93 |
94 | static constexpr int CSLIDER_THUMB_WIDTH = 17; //< The width or thickness of the slider's grabber or thumb.
95 | static constexpr int CSLIDER_THUMB_LENGTH = 23; //< The length of the slider's grabber or thumb.
96 | static constexpr int CSLIDER_SLIDER_WIDTH = 9; //< The width or thickness of the slider.
97 |
98 | /**
99 | * Object constructor.
100 | */
101 | CSlider::CSlider()
102 | {
103 | InitStyle();
104 | }
105 |
106 | /**
107 | * Object constructor.
108 | * @param name The component name.
109 | */
110 | CSlider::CSlider(const String& name)
111 | : Slider(name)
112 | {
113 | InitStyle();
114 | }
115 |
116 | /**
117 | * Object constructor.
118 | * @param style Component style.
119 | * @param textBoxPos Position of the slider's textbox.
120 | */
121 | CSlider::CSlider(SliderStyle style, TextEntryBoxPosition textBoxPos)
122 | : Slider(style, textBoxPos)
123 | {
124 | InitStyle();
125 | }
126 |
127 | /**
128 | * Object destructor.
129 | */
130 | CSlider::~CSlider()
131 | {
132 | }
133 |
134 | /**
135 | * Set custom colors.
136 | */
137 | void CSlider::InitStyle()
138 | {
139 | setColour(Slider::textBoxTextColourId, CDbStyle::GetDbColor(CDbStyle::TextColor));
140 | setColour(Slider::textBoxBackgroundColourId, CDbStyle::GetDbColor(CDbStyle::MidColor));
141 | setColour(Slider::thumbColourId, CDbStyle::GetDbColor(CDbStyle::ButtonColor));
142 | setColour(Slider::backgroundColourId, CDbStyle::GetDbColor(CDbStyle::MidColor));
143 | setColour(Slider::trackColourId, CDbStyle::GetDbColor(CDbStyle::FaderGreenColor));
144 | setColour(Slider::textBoxOutlineColourId, CDbStyle::GetDbColor(CDbStyle::WindowColor));
145 | setColour(Slider::textBoxHighlightColourId, CDbStyle::GetDbColor(CDbStyle::LightColor));
146 | }
147 |
148 | /**
149 | * Called when a mouse button is pressed.
150 | * @param e Details about the position and status of the mouse event, including the source component in which it occurred
151 | */
152 | void CSlider::mouseDown(const MouseEvent& e)
153 | {
154 | // Get mouse position and scale it between 0 and 1.
155 | Point pos = e.getMouseDownPosition();
156 |
157 | if (GetUpperSliderRect().contains(pos) ||
158 | GetLowerSliderRect().contains(pos) ||
159 | GetThumbPath().contains(static_cast(pos.getX()), static_cast(pos.getY())))
160 | {
161 | // Accept click -> pass on to base class implementation.
162 | Slider::mouseDown(e);
163 | }
164 | }
165 |
166 | /**
167 | * Reimplemented paint function.
168 | * @param g A graphics context, used for drawing a component or image.
169 | */
170 | void CSlider::paint(Graphics &g)
171 | {
172 | // Paint bounding rect just for testing.
173 | //Rectangle bounds = getLocalBounds();
174 | //g.setColour(CDbStyle::GetDbColor(ButtonBlueColor));
175 | //g.drawRect(bounds, 1);
176 |
177 | Rectangle lowerSliderRect = GetLowerSliderRect();
178 | Rectangle upperSliderRect = GetUpperSliderRect();
179 |
180 | // Slider areas
181 | g.setColour(CDbStyle::GetDbColor(CDbStyle::FaderGreenColor));
182 | g.fillRect(lowerSliderRect);
183 | g.setColour(CDbStyle::GetDbColor(CDbStyle::ButtonColor));
184 | g.fillRect(upperSliderRect);
185 | g.setColour(CDbStyle::GetDbColor(CDbStyle::WindowColor));
186 | g.drawRect(lowerSliderRect, 1);
187 | g.drawRect(upperSliderRect, 1);
188 |
189 | // Thumb (slider knob)
190 | Path thumbPath = GetThumbPath();
191 | g.setColour(CDbStyle::GetDbColor(CDbStyle::WindowColor));
192 | g.strokePath(thumbPath, PathStrokeType(2));
193 | g.setColour(CDbStyle::GetDbColor(CDbStyle::ButtonColor));
194 | g.fillPath(thumbPath);
195 |
196 | // Thumb arrows
197 | Path arrowPath = GetThumbArrowsPath();
198 | g.setColour(CDbStyle::GetDbColor(CDbStyle::TextColor));
199 | g.fillPath(arrowPath);
200 | }
201 |
202 | /**
203 | * Get the bounding rectangle of the lower section (i.e. the green part) of the slider area.
204 | * For higher slider values this rectangle will be longer / higher.
205 | * @return A rectangle representing the bounding area.
206 | */
207 | Rectangle CSlider::GetLowerSliderRect()
208 | {
209 | Rectangle ret;
210 | Rectangle bounds = getLocalBounds();
211 | double v = getValue();
212 |
213 | if (getSliderStyle() == Slider::LinearHorizontal)
214 | {
215 | ret = Rectangle(CSLIDER_THUMB_WIDTH / 2, 9,
216 | static_cast(v * (bounds.getWidth() - CSLIDER_THUMB_WIDTH)),
217 | CSLIDER_SLIDER_WIDTH);
218 | }
219 | else if (getSliderStyle() == Slider::LinearVertical)
220 | {
221 | int len = static_cast(v * (bounds.getHeight() - CSLIDER_THUMB_WIDTH));
222 | int pos = (bounds.getHeight() - len) - (CSLIDER_THUMB_WIDTH / 2);
223 | ret = Rectangle(bounds.getWidth() - 18, pos, CSLIDER_SLIDER_WIDTH, len);
224 | }
225 |
226 | return ret;
227 | }
228 |
229 | /**
230 | * Get the bounding rectangle of the higher section (i.e. the gray part) of the slider area.
231 | * For lower slider values this rectangle will be longer / higher.
232 | * @return A rectangle representing the bounding area.
233 | */
234 | Rectangle CSlider::GetUpperSliderRect()
235 | {
236 | Rectangle ret;
237 | Rectangle bounds = getLocalBounds();
238 | double v = getValue();
239 |
240 | if (getSliderStyle() == Slider::LinearHorizontal)
241 | {
242 | int len = static_cast((1.0 - v) * (bounds.getWidth() - CSLIDER_THUMB_WIDTH));
243 | int pos = (bounds.getWidth() - len) - (CSLIDER_THUMB_WIDTH / 2);
244 | ret = Rectangle(pos, 9, len, CSLIDER_SLIDER_WIDTH);
245 | }
246 | else if (getSliderStyle() == Slider::LinearVertical)
247 | {
248 | ret = Rectangle(bounds.getWidth() - 18, CSLIDER_THUMB_WIDTH / 2,
249 | CSLIDER_SLIDER_WIDTH, static_cast((1.0 - v) * (bounds.getHeight() - CSLIDER_THUMB_WIDTH)));
250 | }
251 |
252 | return ret;
253 | }
254 |
255 | /**
256 | * Get the drawing path for the slider's thumb grabber.
257 | * @return The path.
258 | */
259 | Path CSlider::GetThumbPath()
260 | {
261 | Path ret;
262 | Rectangle bounds = getLocalBounds();
263 | double v = getValue();
264 | float startX;
265 | float startY;
266 |
267 | if (getSliderStyle() == Slider::LinearHorizontal)
268 | {
269 | startX = 1.0f + static_cast(v * (bounds.getWidth() - CSLIDER_THUMB_WIDTH));
270 | startY = 3.0f;
271 |
272 | ret.startNewSubPath(startX, startY + 2);
273 | ret.lineTo(startX + static_cast(CSLIDER_THUMB_WIDTH / 2) - 0.5f, startY - 2);
274 | ret.lineTo(startX + CSLIDER_THUMB_WIDTH - 2, startY + 2);
275 | ret.lineTo(startX + CSLIDER_THUMB_WIDTH - 2, CSLIDER_THUMB_LENGTH);
276 | ret.lineTo(startX, CSLIDER_THUMB_LENGTH);
277 | ret.closeSubPath();
278 | }
279 | else if (getSliderStyle() == Slider::LinearVertical)
280 | {
281 | startX = static_cast(bounds.getWidth() - CSLIDER_THUMB_LENGTH);
282 | startY = 1.0f + static_cast((bounds.getHeight() - CSLIDER_THUMB_WIDTH) * (1.0 - v));
283 |
284 | ret.startNewSubPath(startX, startY);
285 | ret.lineTo(startX + CSLIDER_THUMB_LENGTH - 5, startY);
286 | ret.lineTo(startX + CSLIDER_THUMB_LENGTH - 1, startY + (CSLIDER_THUMB_WIDTH / 2));
287 | ret.lineTo(startX + CSLIDER_THUMB_LENGTH - 5, startY + CSLIDER_THUMB_WIDTH - 2);
288 | ret.lineTo(startX, startY + CSLIDER_THUMB_WIDTH - 2);
289 | ret.closeSubPath();
290 | }
291 |
292 | return ret;
293 | }
294 |
295 | /**
296 | * Get the drawing path for the slider's little thumb arrows.
297 | * @return The path.
298 | */
299 | Path CSlider::GetThumbArrowsPath()
300 | {
301 | Path ret;
302 | Rectangle bounds = getLocalBounds();
303 | double v = getValue();
304 | float startX;
305 | float startY;
306 |
307 | if (getSliderStyle() == Slider::LinearHorizontal)
308 | {
309 | startX = 1.0f + static_cast(v * (bounds.getWidth() - CSLIDER_THUMB_WIDTH));
310 | startY = 3.0f;
311 |
312 | ret.addTriangle( startX + 1.5f, startY + 10.5f, // P1
313 | startX + 6, startY + 7, // P2
314 | startX + 6, startY + 14); // P3
315 |
316 | ret.addTriangle( startX + 13.5f, startY + 10.5f, // P1
317 | startX + 9, startY + 14, // P2
318 | startX + 9, startY + 7); // P3
319 | }
320 | else if (getSliderStyle() == Slider::LinearVertical)
321 | {
322 | startX = static_cast(bounds.getWidth() - CSLIDER_THUMB_LENGTH);
323 | startY = 1.0f + static_cast((bounds.getHeight() - CSLIDER_THUMB_WIDTH) * (1.0 - v));
324 |
325 | ret.addTriangle( startX + 9.5f, startY + 1.5f, // P1
326 | startX + 13, startY + 6, // P2
327 | startX + 6, startY + 6); // P3
328 |
329 | ret.addTriangle( startX + 9.5f, startY + 13.5f, // P1
330 | startX + 6, startY + 9, // P2
331 | startX + 13, startY + 9); // P3
332 | }
333 |
334 | return ret;
335 | }
336 |
337 |
338 | /*
339 | ===============================================================================
340 | Class CKnob
341 | ===============================================================================
342 | */
343 |
344 | /**
345 | * Object constructor.
346 | */
347 | CKnob::CKnob()
348 | {
349 | InitStyle();
350 | }
351 |
352 | /**
353 | * Object constructor.
354 | * @param name The component name.
355 | */
356 | CKnob::CKnob(const String& name)
357 | : CSlider(name)
358 | {
359 | InitStyle();
360 | }
361 |
362 | /**
363 | * Object constructor.
364 | * @param style Component style.
365 | * @param textBoxPos Position of the slider's textbox.
366 | */
367 | CKnob::CKnob(SliderStyle style, TextEntryBoxPosition textBoxPos)
368 | : CSlider(style, textBoxPos)
369 | {
370 | InitStyle();
371 | }
372 |
373 | /**
374 | * Object destructor.
375 | */
376 | CKnob::~CKnob()
377 | {
378 | }
379 |
380 | /**
381 | * Set custom colors.
382 | */
383 | void CKnob::InitStyle()
384 | {
385 | setColour(Slider::textBoxTextColourId, CDbStyle::GetDbColor(CDbStyle::TextColor));
386 | setColour(Slider::textBoxBackgroundColourId, CDbStyle::GetDbColor(CDbStyle::MidColor));
387 | setColour(Slider::thumbColourId, CDbStyle::GetDbColor(CDbStyle::ButtonColor));
388 | setColour(Slider::backgroundColourId, CDbStyle::GetDbColor(CDbStyle::MidColor));
389 | setColour(Slider::trackColourId, CDbStyle::GetDbColor(CDbStyle::FaderGreenColor));
390 | setColour(Slider::textBoxOutlineColourId, CDbStyle::GetDbColor(CDbStyle::WindowColor));
391 | setColour(Slider::textBoxHighlightColourId, CDbStyle::GetDbColor(CDbStyle::LightColor));
392 | }
393 |
394 | /**
395 | * Called when a mouse button is pressed.
396 | * @param e Details about the position and status of the mouse event, including the source component in which it occurred
397 | */
398 | void CKnob::mouseDown(const MouseEvent& e)
399 | {
400 | // Skip the CSlider implementation.
401 | Slider::mouseDown(e);
402 | }
403 |
404 | /**
405 | * Reimplemented paint function.
406 | * @param g A graphics context, used for drawing a component or image.
407 | */
408 | void CKnob::paint(Graphics &g)
409 | {
410 | // Skip the CSlider implementation.
411 | Slider::paint(g);
412 | }
413 |
414 |
415 | /*
416 | ===============================================================================
417 | Class CTextEditor
418 | ===============================================================================
419 | */
420 |
421 | /**
422 | * Object constructor.
423 | * @param componentName The name to pass to the component for it to use as its name .
424 | * @param passwordCharacter Used as a replacement for all characters that are drawn on screen.
425 | */
426 | CTextEditor::CTextEditor(const String& componentName, juce_wchar passwordCharacter)
427 | : TextEditor(componentName, passwordCharacter)
428 | {
429 | m_suffix = "";
430 | InitStyle();
431 | }
432 |
433 | /**
434 | * Object destructor.
435 | */
436 | CTextEditor::~CTextEditor()
437 | {
438 | }
439 |
440 | /**
441 | * Reimplemented paint function to draw units.
442 | * @param g A graphics context, used for drawing a component or image.
443 | */
444 | void CTextEditor::paint(Graphics &g)
445 | {
446 | // First let base implementation paint the component.
447 | TextEditor::paint(g);
448 |
449 | // If a suffix has been defined (suffix string not empty), paint the units suffix.
450 | // Only display units while the TextEditor does NOT have keyboard focus.
451 | if (!hasKeyboardFocus(true) && m_suffix.isNotEmpty())
452 | {
453 | float suffixWidth = (m_suffix.length() * 7.0f) + 6.0f; // Width of strings in pixels.
454 | float contentWidth = (getText().length() * 7.0f) + 6.0f;
455 | Rectangle textArea(contentWidth, static_cast(getLocalBounds().getY()), suffixWidth, static_cast(getLocalBounds().getHeight()));
456 |
457 | g.setColour(CDbStyle::GetDbColor(CDbStyle::TextColor));
458 | g.drawText(m_suffix, textArea, Justification::centred);
459 | }
460 | }
461 |
462 | /**
463 | * Set custom colors and config.
464 | */
465 | void CTextEditor::InitStyle()
466 | {
467 | setMultiLine(false);
468 | setReturnKeyStartsNewLine(false);
469 | setCaretVisible(true);
470 | setInputRestrictions(16, ".0123456789");
471 | setColour(TextEditor::backgroundColourId, CDbStyle::GetDbColor(CDbStyle::DarkColor));
472 | setColour(TextEditor::textColourId, CDbStyle::GetDbColor(CDbStyle::TextColor));
473 | setColour(TextEditor::outlineColourId, CDbStyle::GetDbColor(CDbStyle::WindowColor));
474 | setColour(TextEditor::focusedOutlineColourId, CDbStyle::GetDbColor(CDbStyle::LightColor));
475 | setColour(TextEditor::highlightedTextColourId, CDbStyle::GetDbColor(CDbStyle::HighlightColor));
476 | }
477 |
478 | /**
479 | * Add a suffix. Per default no suffix is appended to the displayed text.
480 | * @param suffix Suffix to append to displayed text, such as units.
481 | */
482 | void CTextEditor::SetSuffix(String suffix)
483 | {
484 | m_suffix = suffix;
485 | }
486 |
487 |
488 | /*
489 | ===============================================================================
490 | Class CButton
491 | ===============================================================================
492 | */
493 |
494 | /**
495 | * Object constructor.
496 | * @param componentName The name to pass to the component for it to use as its name .
497 | */
498 | CButton::CButton(const String& componentName)
499 | : ToggleButton(componentName)
500 | {
501 | m_cornerRadius = 2;
502 | }
503 |
504 | /**
505 | * Object destructor.
506 | */
507 | CButton::~CButton()
508 | {
509 | }
510 |
511 | /**
512 | * Set the corner radius of the button. If this function is not used,
513 | * the default corner radius used is 2.
514 | * @param radius The new corner radius.
515 | */
516 | void CButton::SetCornerRadius(float radius)
517 | {
518 | m_cornerRadius = radius;
519 | repaint();
520 | }
521 |
522 | /**
523 | * Reimplemented paint function.
524 | * @param g A graphics context, used for drawing a component or image.
525 | * @param isMouseOverButton True if the mouse is over the button.
526 | * @param isButtonDown True if the button is being pressed.
527 | */
528 | void CButton::paintButton(Graphics &g, bool isMouseOverButton, bool isButtonDown)
529 | {
530 | Rectangle bounds = getLocalBounds();
531 | Rectangle buttonRectF = Rectangle(2.5f, 2.5f, bounds.getWidth() - 4.0f, bounds.getHeight() - 4.0f);
532 | bool on = getToggleState();
533 | bool enabled = isEnabled();
534 |
535 | // Button's main colour
536 | if (on)
537 | {
538 | Colour col = CDbStyle::GetDbColor(CDbStyle::ButtonBlueColor);
539 | if (isButtonDown)
540 | col = col.brighter(0.1f);
541 | else if (isMouseOverButton)
542 | col = col.brighter(0.05f);
543 | g.setColour(col);
544 | }
545 | else
546 | {
547 | Colour col = CDbStyle::GetDbColor(CDbStyle::ButtonColor);
548 | if (!enabled)
549 | col = col.darker(0.5f);
550 | else if (isButtonDown)
551 | col = CDbStyle::GetDbColor(CDbStyle::ButtonBlueColor).brighter(0.05f);
552 | else if (isMouseOverButton)
553 | col = col.brighter(0.05f);
554 | g.setColour(col);
555 | }
556 |
557 | g.fillRoundedRectangle(buttonRectF, m_cornerRadius);
558 | g.setColour(CDbStyle::GetDbColor(CDbStyle::WindowColor));
559 | g.drawRoundedRectangle(buttonRectF, m_cornerRadius, 1);
560 | g.setColour(CDbStyle::GetDbColor(CDbStyle::TextColor));
561 | g.drawText(getName(), bounds, Justification::centred, false);
562 | }
563 |
564 |
565 | /*
566 | ===============================================================================
567 | Class CPathButton
568 | ===============================================================================
569 | */
570 |
571 | /**
572 | * Object constructor.
573 | * @param path Path which will be drawn on the button.
574 | */
575 | CPathButton::CPathButton(const Path& path)
576 | : CButton(String()),
577 | m_path(path)
578 | {
579 | }
580 |
581 | /**
582 | * Object destructor.
583 | */
584 | CPathButton::~CPathButton()
585 | {
586 | }
587 |
588 | /**
589 | * Reimplemented paint function.
590 | * @param g A graphics context, used for drawing a component or image.
591 | * @param isMouseOverButton True if the mouse is over the button.
592 | * @param isButtonDown True if the button is being pressed.
593 | */
594 | void CPathButton::paintButton(Graphics &g, bool isMouseOverButton, bool isButtonDown)
595 | {
596 | // Actual button is painted by base class
597 | CButton::paintButton(g, isMouseOverButton, isButtonDown);
598 |
599 | // Use applyTransform to move the path so that it is centered within the button's area.
600 | // NOTE: Make a local copy of the path, since applyTransform modifies the original.
601 | Path tmpPath(m_path);
602 | float xOffset = ((getLocalBounds().getWidth() / 2) - (tmpPath.getBounds().getWidth() / 2)) + 1;
603 | float yOffset = ((getLocalBounds().getHeight() / 2) - (tmpPath.getBounds().getHeight() / 2)) + 1;
604 | tmpPath.applyTransform(AffineTransform::translation(xOffset, yOffset));
605 |
606 | // Draw the path
607 | g.setColour(CDbStyle::GetDbColor(CDbStyle::TextColor));
608 | g.strokePath(tmpPath, PathStrokeType(2.0f, PathStrokeType::curved, PathStrokeType::rounded));
609 | }
610 |
611 |
612 | /*
613 | ===============================================================================
614 | Class CImageButton
615 | ===============================================================================
616 | */
617 |
618 | /**
619 | * Object constructor.
620 | * @param image Image which will be place on the button.
621 | */
622 | CImageButton::CImageButton(const Image& image)
623 | : CButton(String()),
624 | m_image(image)
625 | {
626 | }
627 |
628 | /**
629 | * Object destructor.
630 | */
631 | CImageButton::~CImageButton()
632 | {
633 | }
634 |
635 | /**
636 | * Reimplemented paint function.
637 | * @param g A graphics context, used for drawing a component or image.
638 | * @param isMouseOverButton True if the mouse is over the button.
639 | * @param isButtonDown True if the button is being pressed.
640 | */
641 | void CImageButton::paintButton(Graphics &g, bool isMouseOverButton, bool isButtonDown)
642 | {
643 | // Actual button is painted by base class
644 | CButton::paintButton(g, isMouseOverButton, isButtonDown);
645 |
646 | // Paint image centered on buttons rectangle.
647 | int w = getLocalBounds().getWidth();
648 | int h = getLocalBounds().getHeight();
649 | int iw = m_image.getBounds().getWidth();
650 | int ih = m_image.getBounds().getHeight();
651 | g.drawImage(m_image, ((w - iw) / 2) + 1, ((h - ih) / 2) + 1, iw, ih, 0, 0, iw, ih);
652 | }
653 |
654 |
655 | /*
656 | ===============================================================================
657 | Class CDiscreteButton
658 | ===============================================================================
659 | */
660 |
661 | /**
662 | * Object constructor.
663 | * @param image Image which will be place on the button.
664 | */
665 | CDiscreteButton::CDiscreteButton(const Image& image)
666 | : CImageButton(image)
667 | {
668 | }
669 |
670 | /**
671 | * Object destructor.
672 | */
673 | CDiscreteButton::~CDiscreteButton()
674 | {
675 | }
676 |
677 | /**
678 | * Reimplemented paint function, to only show as a button when pressed, or mouseOver'ed.
679 | * @param g A graphics context, used for drawing a component or image.
680 | * @param isMouseOverButton True if the mouse is over the button.
681 | * @param isButtonDown True if the button is being pressed.
682 | */
683 | void CDiscreteButton::paintButton(Graphics &g, bool isMouseOverButton, bool isButtonDown)
684 | {
685 | Rectangle bounds = getLocalBounds();
686 | int w = bounds.getWidth();
687 | int h = bounds.getHeight();
688 |
689 | // Only draw the actual button if it is being pressed, toggled on, or with mouseOver.
690 | bool on = getToggleState();
691 | if (on || isButtonDown || isMouseOverButton)
692 | {
693 | Rectangle buttonRectF = Rectangle(2.5f, 2.5f, w - 4.0f, h - 4.0f);
694 | Colour col = CDbStyle::GetDbColor(CDbStyle::ButtonBlueColor);
695 |
696 | if (!on)
697 | {
698 | if (isButtonDown)
699 | col = col.brighter(0.05f);
700 | else if (isMouseOverButton)
701 | col = CDbStyle::GetDbColor(CDbStyle::ButtonColor).brighter(0.05f);
702 | }
703 | else
704 | {
705 | if (isButtonDown)
706 | col = col.brighter(0.1f);
707 | else if (isMouseOverButton)
708 | col = col.brighter(0.05f);
709 | }
710 |
711 | g.setColour(col);
712 | g.fillRoundedRectangle(buttonRectF, m_cornerRadius);
713 | g.setColour(CDbStyle::GetDbColor(CDbStyle::WindowColor));
714 | g.drawRoundedRectangle(buttonRectF, m_cornerRadius, 1);
715 | g.setColour(CDbStyle::GetDbColor(CDbStyle::TextColor));
716 | }
717 |
718 | // Paint image centered on buttons rectangle.
719 | int iw = m_image.getBounds().getWidth();
720 | int ih = m_image.getBounds().getHeight();
721 | g.drawImage(m_image, ((w - iw) / 2) + 1, ((h - ih) / 2) + 1, iw, ih, 0, 0, iw, ih);
722 | }
723 |
724 |
725 | /*
726 | ===============================================================================
727 | Class CDiscreteButton
728 | ===============================================================================
729 | */
730 |
731 | /**
732 | * Object constructor.
733 | * @param componentName The name to pass to the component for it to use as its name .
734 | * @param labelText The text to be shown on the label.
735 | */
736 | CLabel::CLabel(const String& componentName, const String& labelText)
737 | : Label(componentName, labelText)
738 | {
739 | InitStyle();
740 | }
741 |
742 | /**
743 | * Object destructor.
744 | */
745 | CLabel::~CLabel()
746 | {
747 | }
748 |
749 | /**
750 | * Set custom colors and config.
751 | */
752 | void CLabel::InitStyle()
753 | {
754 | setFont(Font(14, Font::plain));
755 | setColour(Label::textColourId, CDbStyle::GetDbColor(CDbStyle::TextColor));
756 | setJustificationType(Justification::centred);
757 | }
758 |
759 |
760 | /*
761 | ===============================================================================
762 | Class CDigital
763 | ===============================================================================
764 | */
765 |
766 | /**
767 | * Object constructor.
768 | */
769 | CDigital::CDigital(const String& componentName)
770 | : Component(componentName)
771 | {
772 | // Create and configure components inside this container.
773 | addAndMakeVisible(m_editor);
774 | m_plus.setName("+");
775 | m_plus.setEnabled(true);
776 | addAndMakeVisible(m_plus);
777 | m_minus.setName("-");
778 | m_minus.setEnabled(true);
779 | addAndMakeVisible(m_minus);
780 | }
781 |
782 | /**
783 | * Object destructor.
784 | */
785 | CDigital::~CDigital()
786 | {
787 | }
788 |
789 | /**
790 | * Set the allowed range of values.
791 | * @param min Min allowed value.
792 | * @param max Max allowed value.
793 | */
794 | void CDigital::SetRange(int min, int max)
795 | {
796 | m_min = min;
797 | m_max = max;
798 | }
799 |
800 | /**
801 | * Set the new value of the control. Depending on the new value, it may become
802 | * adjusted to the current allowed range.
803 | * @param newValue New value to set.
804 | */
805 | void CDigital::SetValue(int newValue)
806 | {
807 | if (newValue <= m_min)
808 | {
809 | // Can't go lower, disable "-" button.
810 | newValue = m_min;
811 | m_plus.setEnabled(true);
812 | m_minus.setEnabled(false);
813 | }
814 | else if (newValue >= m_max)
815 | {
816 | // Can't go higher, disable "+" button.
817 | newValue = m_max;
818 | m_plus.setEnabled(false);
819 | m_minus.setEnabled(true);
820 | }
821 | else
822 | {
823 | m_plus.setEnabled(true);
824 | m_minus.setEnabled(true);
825 | }
826 |
827 | m_editor.setText(String(newValue));
828 | }
829 |
830 | /**
831 | * Set listeners for the textfield and the buttons. These listeners will be automatically signalled when
832 | * any changes to the textField or the buttons take place, respectively.
833 | * @param textListener Pointer to the TextEditor::Listener.
834 | * @param buttonListener Pointer to the Button::Listener.
835 | */
836 | void CDigital::AddListeners(TextEditor::Listener* textListener, Button::Listener* buttonListener)
837 | {
838 | m_editor.addListener(textListener);
839 | m_plus.addListener(buttonListener);
840 | m_minus.addListener(buttonListener);
841 | }
842 |
843 | /**
844 | * Reimplemented from Component, gets called whenever the component is resized. Here we adjust the size
845 | * and position of sub-elements.
846 | */
847 | void CDigital::resized()
848 | {
849 | int w = getLocalBounds().getWidth();
850 | int h = getLocalBounds().getHeight();
851 | m_editor.setBounds(0, 2, static_cast((w * 0.45f) + 1.0f), h - 4);
852 | m_minus.setBounds(static_cast((w * 0.45f) - 2.0f), 0, static_cast((w * 0.275f) + 3.0f), h - 1);
853 | m_plus.setBounds(static_cast((w * 0.725f) - 3.0f), 0, static_cast((w * 0.275f) + 3.0f), h - 1);
854 | }
855 |
856 |
857 | /*
858 | ===============================================================================
859 | Class AOverlay
860 | ===============================================================================
861 | */
862 |
863 | /**
864 | * Class constructor.
865 | */
866 | AOverlay::AOverlay(OverlayType type)
867 | : Component()
868 | {
869 | m_overlayType = type;
870 | }
871 |
872 | /**
873 | * Class destructor.
874 | */
875 | AOverlay::~AOverlay()
876 | {
877 | }
878 |
879 | /**
880 | * Get this overlay's type.
881 | */
882 | AOverlay::OverlayType AOverlay::GetOverlayType() const
883 | {
884 | return m_overlayType;
885 | }
886 |
887 |
888 | } // namespace dbaudio
889 |
--------------------------------------------------------------------------------
/SoundscapePlugin/Source/Gui.h:
--------------------------------------------------------------------------------
1 | /*
2 | ===============================================================================
3 |
4 | Copyright (C) 2019 d&b audiotechnik GmbH & Co. KG. All Rights Reserved.
5 |
6 | This file is part of the Soundscape VST, AU, and AAX Plug-in.
7 |
8 | Redistribution and use in source and binary forms, with or without
9 | modification, are permitted provided that the following conditions are met:
10 |
11 | 1. Redistributions of source code must retain the above copyright notice,
12 | this list of conditions and the following disclaimer.
13 |
14 | 2. Redistributions in binary form must reproduce the above copyright notice,
15 | this list of conditions and the following disclaimer in the documentation
16 | and/or other materials provided with the distribution.
17 |
18 | 3. The name of the author may not be used to endorse or promote products
19 | derived from this software without specific prior written permission.
20 |
21 | THIS SOFTWARE IS PROVIDED BY d&b audiotechnik GmbH & Co. KG "AS IS" AND ANY
22 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24 | DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
29 | OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
30 | ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 |
32 | ===============================================================================
33 | */
34 |
35 |
36 | #pragma once
37 |
38 | #include "../JuceLibraryCode/JuceHeader.h"
39 |
40 |
41 | namespace dbaudio
42 | {
43 |
44 |
45 | /**
46 | * A style for d&b software look and feel.
47 | */
48 | class CDbStyle
49 | {
50 | public:
51 | /**
52 | * d&b Color codes
53 | */
54 | enum DbColor
55 | {
56 | WindowColor, // 27 27 27 - Window background
57 | DarkLineColor, // 49 49 49 - Dark lines between table rows
58 | DarkColor, // 67 67 67 - Dark
59 | MidColor, // 83 83 83 - Mid
60 | ButtonColor, // 125 125 125 - Button off
61 | LightColor, // 201 201 201 - Light
62 | TextColor, // 238 238 238 - Text
63 | DarkTextColor, // 180 180 180 - Dark text
64 | HighlightColor, // 115 140 155 - Highlighted text
65 | FaderGreenColor, // 140 180 90 - Green sliders
66 | ButtonBlueColor, // 28 122 166 - Button Blue
67 | };
68 |
69 | CDbStyle() {};
70 | virtual ~CDbStyle() = default;
71 |
72 | static Colour GetDbColor(DbColor color);
73 |
74 | JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CDbStyle)
75 | };
76 |
77 |
78 | /**
79 | * Class CSlider, a custom Slider
80 | */
81 | class CSlider : public Slider
82 | {
83 | public:
84 | CSlider();
85 | explicit CSlider(const String& componentName);
86 | CSlider(SliderStyle style, TextEntryBoxPosition textBoxPosition);
87 | ~CSlider() override;
88 |
89 | protected:
90 | void InitStyle();
91 | Rectangle GetUpperSliderRect();
92 | Rectangle GetLowerSliderRect();
93 | Rectangle GetThumbRect();
94 | Path GetThumbPath();
95 | Path GetThumbArrowsPath();
96 |
97 | void mouseDown(const MouseEvent &) override;
98 | void paint(Graphics &) override;
99 |
100 | JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CSlider)
101 | };
102 |
103 |
104 | /**
105 | * Class CKnob, a custom CSlider
106 | */
107 | class CKnob : public CSlider
108 | {
109 | public:
110 | CKnob();
111 | explicit CKnob(const String& componentName);
112 | CKnob(SliderStyle style, TextEntryBoxPosition textBoxPosition);
113 | ~CKnob() override;
114 |
115 | protected:
116 | void InitStyle();
117 |
118 | void mouseDown(const MouseEvent &) override;
119 | void paint(Graphics &) override;
120 |
121 | JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CKnob)
122 | };
123 |
124 |
125 | /**
126 | * class CTextEditor, a custom TextEditor
127 | */
128 | class CTextEditor : public TextEditor
129 | {
130 | public:
131 | explicit CTextEditor(const String& componentName = String(), juce_wchar passwordCharacter = 0);
132 | ~CTextEditor() override;
133 |
134 | void SetSuffix(String suffix);
135 |
136 | protected:
137 | void InitStyle();
138 | void paint(Graphics &) override;
139 |
140 | String m_suffix; /**< Suffix to append to displayed text, such as units. */
141 |
142 | JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CTextEditor)
143 | };
144 |
145 |
146 | /**
147 | * class CButton, a custom ToggleButton
148 | */
149 | class CButton : public ToggleButton
150 | {
151 | public:
152 | explicit CButton(const String& componentName = String());
153 | ~CButton() override;
154 | void SetCornerRadius(float radius);
155 |
156 | protected:
157 | void paintButton(Graphics &, bool isMouseOverButton, bool isButtonDown) override;
158 | float m_cornerRadius; /**< Determines the corner radius of the button. */
159 |
160 | JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CButton)
161 | };
162 |
163 |
164 | /**
165 | * class CPathButton, a custom CButton
166 | */
167 | class CPathButton : public CButton
168 | {
169 | public:
170 | explicit CPathButton(const Path& path = Path());
171 | ~CPathButton() override;
172 |
173 | protected:
174 | void paintButton(Graphics &, bool isMouseOverButton, bool isButtonDown) override;
175 | Path m_path; /**< Path to draw on top of the button. */
176 |
177 | JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CPathButton)
178 | };
179 |
180 |
181 | /**
182 | * class CImageButton, a custom CButton
183 | */
184 | class CImageButton : public CButton
185 | {
186 | public:
187 | explicit CImageButton(const Image& image = Image());
188 | ~CImageButton() override;
189 |
190 | protected:
191 | void paintButton(Graphics &, bool isMouseOverButton, bool isButtonDown) override;
192 | Image m_image; /**< Image to draw on top of the button. */
193 |
194 | JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CImageButton)
195 | };
196 |
197 |
198 | /**
199 | * class CDiscreteButton, a custom CImageButton which is more discrete
200 | * (Only looks like an actual button if it is being pressed, toggled on, or with mouseOver)
201 | */
202 | class CDiscreteButton : public CImageButton
203 | {
204 | public:
205 | explicit CDiscreteButton(const Image& image);
206 | ~CDiscreteButton() override;
207 |
208 | protected:
209 | void paintButton(Graphics &, bool isMouseOverButton, bool isButtonDown) override;
210 |
211 | JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CDiscreteButton)
212 | };
213 |
214 |
215 | /**
216 | * class CLabel, a custom Label
217 | */
218 | class CLabel : public Label
219 | {
220 | public:
221 | explicit CLabel(const String& componentName = String(), const String& labelText = String());
222 | ~CLabel() override;
223 |
224 | protected:
225 | void InitStyle();
226 |
227 | JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CLabel)
228 | };
229 |
230 |
231 | /**
232 | * Class CDigital, a custom component which behaves like a R1 RCT_Digital control.
233 | * It has an input text field and also a + and a - buttons to increase/decrease the value.
234 | */
235 | class CDigital : public Component
236 | {
237 | public:
238 | explicit CDigital(const String& componentName = String());
239 | ~CDigital() override;
240 |
241 | void SetRange(int min, int max);
242 | void SetValue(int newValue);
243 | void AddListeners(TextEditor::Listener*, Button::Listener*);
244 |
245 | void resized() override;
246 |
247 | private:
248 | /**
249 | * Text editor.
250 | */
251 | CTextEditor m_editor;
252 |
253 | /**
254 | * "+" button.
255 | */
256 | CImageButton m_plus;
257 |
258 | /**
259 | * "-" button.
260 | */
261 | CImageButton m_minus;
262 |
263 | /**
264 | * Minimum allowed value.
265 | */
266 | int m_min = -99;
267 |
268 | /**
269 | * Maximum allowed value.
270 | */
271 | int m_max = 99;
272 |
273 | JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CDigital)
274 | };
275 |
276 |
277 | /**
278 | * Abstract class AOverlay.
279 | * Must be reimplemented to provide a GUI overlay.
280 | */
281 | class AOverlay : public Component
282 | {
283 | public:
284 |
285 | /**
286 | * Overlay types. There can only be one active at the time.
287 | */
288 | enum OverlayType
289 | {
290 | OT_Unknown = 0,
291 | OT_Overview,
292 | OT_MultiSlide,
293 | OT_About
294 | };
295 |
296 | explicit AOverlay(OverlayType type);
297 | ~AOverlay() override;
298 |
299 | OverlayType GetOverlayType() const;
300 | virtual void UpdateGui(bool init) = 0;
301 |
302 | private:
303 | /**
304 | * Type of overlay as specified by the OverlayType enum.
305 | */
306 | OverlayType m_overlayType;
307 |
308 | JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(AOverlay)
309 | };
310 |
311 |
312 | } // namespace dbaudio
313 |
--------------------------------------------------------------------------------
/SoundscapePlugin/Source/Overview.h:
--------------------------------------------------------------------------------
1 | /*
2 | ===============================================================================
3 |
4 | Copyright (C) 2019 d&b audiotechnik GmbH & Co. KG. All Rights Reserved.
5 |
6 | This file is part of the Soundscape VST, AU, and AAX Plug-in.
7 |
8 | Redistribution and use in source and binary forms, with or without
9 | modification, are permitted provided that the following conditions are met:
10 |
11 | 1. Redistributions of source code must retain the above copyright notice,
12 | this list of conditions and the following disclaimer.
13 |
14 | 2. Redistributions in binary form must reproduce the above copyright notice,
15 | this list of conditions and the following disclaimer in the documentation
16 | and/or other materials provided with the distribution.
17 |
18 | 3. The name of the author may not be used to endorse or promote products
19 | derived from this software without specific prior written permission.
20 |
21 | THIS SOFTWARE IS PROVIDED BY d&b audiotechnik GmbH & Co. KG "AS IS" AND ANY
22 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24 | DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
29 | OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
30 | ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 |
32 | ===============================================================================
33 | */
34 |
35 |
36 | #pragma once
37 |
38 | #include "About.h"
39 | #include "Gui.h"
40 | #include "Common.h"
41 |
42 |
43 | namespace dbaudio
44 | {
45 |
46 |
47 | /**
48 | * Forward declarations
49 | */
50 | class COverview;
51 | class CTabbedComponent;
52 | class CTabBarButton;
53 | class COverviewComponent;
54 | class COverviewTableContainer;
55 | class COverviewMultiSurface;
56 | class CTableModelComponent;
57 | class CComboBoxContainer;
58 | class CTextEditorContainer;
59 | class CRadioButtonContainer;
60 | class CEditableLabelContainer;
61 |
62 |
63 | /**
64 | * Class COverviewManager which takes care of opening and closing the overview window.
65 | */
66 | class COverviewManager
67 | {
68 | public:
69 | COverviewManager();
70 | virtual ~COverviewManager();
71 | static COverviewManager* GetInstance();
72 |
73 | void OpenOverview();
74 | void CloseOverview(bool destroy);
75 | void SaveLastOverviewBounds(Rectangle bounds);
76 | Rectangle GetOverviewBounds() const;
77 |
78 | int GetActiveTab() const;
79 | void SetActiveTab(int tabIdx);
80 |
81 | int GetSelectedMapping() const;
82 | void SetSelectedMapping(int mapping);
83 |
84 | protected:
85 | /**
86 | * The one and only instance of COverviewManager.
87 | */
88 | static COverviewManager *m_singleton;
89 |
90 | /**
91 | * Pointer to the Overview winodw, if any.
92 | */
93 | COverview* m_overview;
94 |
95 | /**
96 | * Default position and size of the overview window.
97 | */
98 | Rectangle m_overviewBounds;
99 |
100 | /**
101 | * Remember the last active tab.
102 | */
103 | int m_selectedTab = 0;
104 |
105 | /**
106 | * Remember the last selected coordinate mapping for the multi-slider
107 | */
108 | int m_selectedMapping = 1;
109 |
110 | JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(COverviewManager)
111 | };
112 |
113 |
114 | /**
115 | * Class COverview inherits from DocumentWindow to provide a resizeable window with minimize, maximize and close buttons.
116 | */
117 | class COverview : public DocumentWindow
118 | {
119 | public:
120 | COverview();
121 | ~COverview() override;
122 |
123 | private:
124 | virtual void closeButtonPressed() override;
125 |
126 | /**
127 | * Component within the overview window, used as container for all other components.
128 | */
129 | std::unique_ptr m_contentComponent;
130 |
131 |
132 | JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(COverview)
133 | };
134 |
135 |
136 | /**
137 | * Class COverviewComponent is a simple container used to hold the GUI controls.
138 | */
139 | class COverviewComponent : public Component,
140 | public TextEditor::Listener,
141 | private Timer
142 | {
143 | public:
144 | COverviewComponent();
145 | ~COverviewComponent() override;
146 | void UpdateGui(bool init);
147 |
148 | private:
149 | void paint(Graphics&) override;
150 | void resized() override;
151 |
152 | void textEditorFocusLost(TextEditor &) override;
153 | void textEditorReturnKeyPressed(TextEditor &) override;
154 |
155 | void timerCallback() override;
156 |
157 | private:
158 | /**
159 | * App version label
160 | */
161 | std::unique_ptr m_versionLabel;
162 |
163 | /**
164 | * App name
165 | */
166 | std::unique_ptr m_nameLabel;
167 |
168 | /**
169 | * Overview title label
170 | */
171 | std::unique_ptr m_titleLabel;
172 |
173 | /*
174 | * Logo image.
175 | */
176 | Image m_dbLogo;
177 |
178 | /**
179 | * DS100 IP Address label
180 | */
181 | std::unique_ptr m_ipAddressLabel;
182 |
183 | /**
184 | * Text editor for the DS100 IP Address
185 | */
186 | std::unique_ptr m_ipAddressTextEdit;
187 |
188 | /**
189 | * Send/receive rate label
190 | */
191 | std::unique_ptr m_rateLabel;
192 |
193 | /**
194 | * Text editor for the OSC send/receive rate in ms.
195 | */
196 | std::unique_ptr m_rateTextEdit;
197 |
198 | /**
199 | * Button used as Online indicator LED.
200 | */
201 | std::unique_ptr m_onlineLed;
202 |
203 | /**
204 | * A container for tabs.
205 | */
206 | std::unique_ptr m_tabbedComponent;
207 |
208 | /**
209 | * The actual table container inside this component.
210 | */
211 | std::unique_ptr m_tableContainer;
212 |
213 | /**
214 | * Container for multi-slider.
215 | */
216 | std::unique_ptr m_multiSliderContainer;
217 |
218 | JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(COverviewComponent)
219 | };
220 |
221 |
222 | /**
223 | * Reimplemented TabbedComponent which overrides the createTabButton method in order
224 | * to provide custom tabBar buttons (See CTabBarButton).
225 | */
226 | class CTabbedComponent : public TabbedComponent
227 | {
228 | public:
229 |
230 | /**
231 | * Overview tab indeces
232 | */
233 | enum OverviewTabIndex
234 | {
235 | OTI_Table = 0,
236 | OTI_MultiSlider
237 | };
238 |
239 | CTabbedComponent();
240 | ~CTabbedComponent() override;
241 |
242 | static void GetIconPath(int tabIdx, Point iconSize, float strokeThickness, Path& p);
243 |
244 | protected:
245 | TabBarButton* createTabButton(const String& tabName, int tabIndex) override;
246 | void currentTabChanged(int newCurrentTabIndex, const String &newCurrentTabName) override;
247 | void resized() override;
248 |
249 | JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CTabbedComponent)
250 | };
251 |
252 |
253 | /**
254 | * Reimplemented TabBarButton which overrides the paintButton method
255 | * to show an icon instead of the standard tab name text.
256 | */
257 | class CTabBarButton : public TabBarButton
258 | {
259 | public:
260 | CTabBarButton(int tabIdx, TabbedButtonBar& ownerBar);
261 | ~CTabBarButton() override;
262 |
263 | protected:
264 | void paintButton(Graphics&, bool, bool) override;
265 |
266 | private:
267 | int m_tabIndex;
268 |
269 | JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CTabBarButton)
270 | };
271 |
272 |
273 | /**
274 | * Class COverviewTableContainer is just a component which contains the overview table
275 | * and it's quick selection buttons.
276 | */
277 | class COverviewTableContainer : public AOverlay,
278 | public Button::Listener
279 | {
280 | public:
281 | COverviewTableContainer();
282 | ~COverviewTableContainer() override;
283 |
284 | void UpdateGui(bool init) override;
285 | void buttonClicked(Button*) override;
286 |
287 | protected:
288 | void paint(Graphics&) override;
289 | void resized() override;
290 |
291 | private:
292 | /**
293 | * The actual table model / component inside this component.
294 | */
295 | std::unique_ptr m_overviewTable;
296 |
297 | /**
298 | * Quick select label
299 | */
300 | std::unique_ptr m_selectLabel;
301 |
302 | /**
303 | * Select all rows button.
304 | */
305 | std::unique_ptr m_selectAll;
306 |
307 | /**
308 | * Select no rows button.
309 | */
310 | std::unique_ptr m_selectNone;
311 |
312 | JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(COverviewTableContainer)
313 | };
314 |
315 |
316 | /**
317 | * Class COverviewMultiSurface is just a component which contains the multi-source slider
318 | * and the mapping selection control.
319 | */
320 | class COverviewMultiSurface : public AOverlay,
321 | public ComboBox::Listener
322 | {
323 | public:
324 | COverviewMultiSurface();
325 | ~COverviewMultiSurface() override;
326 |
327 | void UpdateGui(bool init) override;
328 |
329 | protected:
330 | void paint(Graphics&) override;
331 | void resized() override;
332 | void comboBoxChanged(ComboBox *comboBox) override;
333 |
334 | private:
335 | /**
336 | * Multi-source 2D-Slider.
337 | */
338 | std::unique_ptr m_multiSlider;
339 |
340 | /*
341 | * Mapping selector label
342 | */
343 | std::unique_ptr m_posAreaLabel;
344 |
345 | /**
346 | * ComboBox selector for the coordinate mapping area
347 | */
348 | std::unique_ptr m_areaSelector;
349 |
350 | JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(COverviewMultiSurface)
351 | };
352 |
353 |
354 | /**
355 | * Class CTableModelComponent acts as a table model and a component at the same time.
356 | */
357 | class CTableModelComponent : public Component,
358 | public TableListBoxModel
359 | {
360 | public:
361 |
362 | /**
363 | * Enum defininig the table columns used in the overview table.
364 | */
365 | enum OverviewColumn
366 | {
367 | OC_None = 0, //< Juce column IDs start at 1
368 | OC_TrackID,
369 | OC_SourceID,
370 | OC_Mapping,
371 | OC_ComsMode,
372 | OC_MAX_COLUMNS
373 | };
374 |
375 | CTableModelComponent();
376 | ~CTableModelComponent() override;
377 |
378 | static bool LessThanSourceId(PluginId pId1, PluginId pId2);
379 | static bool LessThanMapping(PluginId pId1, PluginId pId2);
380 | static bool LessThanComsMode(PluginId pId1, PluginId pId2);
381 |
382 | PluginId GetPluginIdForRow(int rowNumber);
383 | std::vector GetPluginIdsForRows(std::vector rowNumbers);
384 | std::vector GetSelectedRows() const;
385 | void SelectAllRows(bool all);
386 | void RecreateTableRowIds();
387 | void UpdateTable();
388 | TableListBox& GetTable() { return m_table; }
389 |
390 |
391 | // Overriden methods from TableListBoxModel
392 | void backgroundClicked(const MouseEvent &) override;
393 | int getNumRows() override;
394 | void paintRowBackground(Graphics& g, int rowNumber, int width, int height, bool rowIsSelected) override;
395 | void paintCell(Graphics& g, int rowNumber, int columnId, int width, int height, bool rowIsSelected) override;
396 | void sortOrderChanged(int newSortColumnId, bool isForwards) override;
397 | Component* refreshComponentForCell(int rowNumber, int columnId, bool isRowSelected, Component* existingComponentToUpdate) override;
398 | int getColumnAutoSizeWidth(int columnId) override;
399 |
400 |
401 | // Overriden methods from Component
402 | void resized() override;
403 |
404 | private:
405 | /**
406 | * The table component itself.
407 | */
408 | TableListBox m_table;
409 |
410 | /**
411 | * Local list of Plug-in instance IDs, one for each row in the table.
412 | */
413 | std::vector m_ids;
414 |
415 | JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CTableModelComponent)
416 | };
417 |
418 |
419 | /**
420 | * Class CComboBoxContainer is a container for the MappingId Combo box component used in the Overview table.
421 | */
422 | class CComboBoxContainer : public Component,
423 | public ComboBox::Listener
424 | {
425 | public:
426 | explicit CComboBoxContainer(CTableModelComponent& td);
427 | ~CComboBoxContainer() override;
428 |
429 | void comboBoxChanged(ComboBox *comboBox) override;
430 | void resized() override;
431 | void SetRow(int newRow);
432 |
433 | private:
434 | /**
435 | * Table where this component is contained.
436 | */
437 | CTableModelComponent& m_owner;
438 |
439 | /**
440 | * Actual combo box component.
441 | */
442 | ComboBox m_comboBox;
443 |
444 | /**
445 | * Row number where this component is located inside the table.
446 | */
447 | int m_row;
448 |
449 | JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CComboBoxContainer)
450 | };
451 |
452 |
453 | /**
454 | * Class CTextEditorContainer is a container for the SourceID CTextEditor component used in the Overview table.
455 | */
456 | class CTextEditorContainer : public Component,
457 | public TextEditor::Listener
458 | {
459 | public:
460 | explicit CTextEditorContainer(CTableModelComponent& td);
461 | ~CTextEditorContainer() override;
462 |
463 | void textEditorFocusLost(TextEditor &) override;
464 | void textEditorReturnKeyPressed(TextEditor &) override;
465 | void resized() override;
466 | void SetRow(int newRow);
467 |
468 | private:
469 | /**
470 | * Table where this component is contained.
471 | */
472 | CTableModelComponent& m_owner;
473 |
474 | /**
475 | * Actual text editor.
476 | */
477 | CTextEditor m_editor;
478 |
479 | /**
480 | * Row number where this component is located inside the table.
481 | */
482 | int m_row;
483 |
484 | JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CTextEditorContainer)
485 | };
486 |
487 |
488 | /**
489 | * Class CRadioButtonContainer is a container for the Tx/Rx buttons used in the Overview table.
490 | */
491 | class CRadioButtonContainer : public Component,
492 | public Button::Listener
493 | {
494 | public:
495 | explicit CRadioButtonContainer(CTableModelComponent& td);
496 | ~CRadioButtonContainer() override;
497 |
498 | void buttonClicked(Button*) override;
499 | void resized() override;
500 | void SetRow(int newRow);
501 |
502 | private:
503 | /**
504 | * Table where this component is contained.
505 | */
506 | CTableModelComponent& m_owner;
507 |
508 | /**
509 | * Actual Tx button.
510 | */
511 | CButton m_txButton;
512 |
513 | /**
514 | * Actual Rx button.
515 | */
516 | CButton m_rxButton;
517 |
518 | /**
519 | * Row number where this component is located inside the table.
520 | */
521 | int m_row;
522 |
523 | JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CRadioButtonContainer)
524 | };
525 |
526 |
527 | /**
528 | * Class CEditableLabelContainer is a container for editable labels used in the Overview table.
529 | */
530 | class CEditableLabelContainer : public Label
531 | {
532 | public:
533 | explicit CEditableLabelContainer(CTableModelComponent& td);
534 | ~CEditableLabelContainer() override;
535 |
536 | void mouseDown(const MouseEvent& event) override;
537 | void mouseDoubleClick(const MouseEvent &) override;
538 | void SetRow(int newRow);
539 |
540 | private:
541 | /**
542 | * Table where this component is contained.
543 | */
544 | CTableModelComponent& m_owner;
545 |
546 | /**
547 | * Row number where this component is located inside the table.
548 | */
549 | int m_row;
550 |
551 | JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CEditableLabelContainer)
552 | };
553 |
554 |
555 | } // namespace dbaudio
556 |
--------------------------------------------------------------------------------
/SoundscapePlugin/Source/Parameters.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | ===============================================================================
3 |
4 | Copyright (C) 2019 d&b audiotechnik GmbH & Co. KG. All Rights Reserved.
5 |
6 | This file is part of the Soundscape VST, AU, and AAX Plug-in.
7 |
8 | Redistribution and use in source and binary forms, with or without
9 | modification, are permitted provided that the following conditions are met:
10 |
11 | 1. Redistributions of source code must retain the above copyright notice,
12 | this list of conditions and the following disclaimer.
13 |
14 | 2. Redistributions in binary form must reproduce the above copyright notice,
15 | this list of conditions and the following disclaimer in the documentation
16 | and/or other materials provided with the distribution.
17 |
18 | 3. The name of the author may not be used to endorse or promote products
19 | derived from this software without specific prior written permission.
20 |
21 | THIS SOFTWARE IS PROVIDED BY d&b audiotechnik GmbH & Co. KG "AS IS" AND ANY
22 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24 | DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
29 | OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
30 | ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 |
32 | ===============================================================================
33 | */
34 |
35 |
36 | #include "Parameters.h"
37 |
38 |
39 | namespace dbaudio
40 | {
41 |
42 |
43 | /**
44 | * Number of CController::timerCallback() calls that are considered as the duration of a "gesture", when
45 | * modifying a parameter via OSC. This is relevant for Touch automation.
46 | */
47 | static constexpr int GESTURE_LENGTH_IN_TICKS = 8;
48 |
49 |
50 | /*
51 | ===============================================================================
52 | Class CAudioParameterFloat
53 | ===============================================================================
54 | */
55 |
56 | /**
57 | * Object constructor.
58 | * @param parameterID Parameter unique ID
59 | * @param name Parameter abbreviated name.
60 | * @param minValue Minimum value, usually 0.0 (except for example for En-Space gain, -120.0).
61 | * @param maxValue Maximum value, usually 1.0 (except for example for En-Space gain, +24.0).
62 | * @param stepSize Smallest change amount which signifies an actual value change.
63 | * @param defaultValue The parameter's default value when created.
64 | */
65 | CAudioParameterFloat::CAudioParameterFloat(String parameterID, String name, float minValue, float maxValue, float stepSize, float defaultValue)
66 | : AudioParameterFloat(parameterID, name, minValue, maxValue, defaultValue)
67 | {
68 | // A float parameter is considered unchanged if it moves withing this tolerance range.
69 | // Used in SetParameterValue() to deal with unfortunate rounding / precision errors caused by some DAWs.
70 | range.interval = stepSize;
71 |
72 | m_inGuiGesture = false;
73 | m_ticksSinceLastChange = GESTURE_LENGTH_IN_TICKS + 1;
74 | }
75 |
76 | /**
77 | * Object destructor.
78 | */
79 | CAudioParameterFloat::~CAudioParameterFloat()
80 | {
81 | }
82 |
83 | /**
84 | * Overriden from AudioParameterFloat. The base class implementation just calls AudioProcessor::getDefaultNumParameterSteps() which
85 | * returns 0x7fffffff. This results in a "Number of parameter steps exceeds limit" Error when analyzing the Plugin with Avid's
86 | * AAX-Validator tool DSH.
87 | * @return The number of steps this parameter has between 0.0f and 1.0f.
88 | */
89 | int CAudioParameterFloat::getNumSteps() const
90 | {
91 | return 0x7ff;
92 | }
93 |
94 | /**
95 | * Called by GUI components (such as sliders or rotary knobs) when a drag or turn gesture starts.
96 | * This will signal the host that a gesture has started, which is used for example for Touch automation.
97 | */
98 | void CAudioParameterFloat::BeginGuiGesture()
99 | {
100 | jassert(m_inGuiGesture == false);
101 | if (!m_inGuiGesture)
102 | {
103 | beginChangeGesture();
104 | m_inGuiGesture = true;
105 | }
106 | }
107 |
108 | /**
109 | * Called by GUI components (such as sliders or rotary knobs) when a drag or turn gesture ends.
110 | * This will signal the host that a gesture has ended, which is used for example for Touch automation.
111 | */
112 | void CAudioParameterFloat::EndGuiGesture()
113 | {
114 | jassert(m_inGuiGesture == true);
115 | if (m_inGuiGesture)
116 | {
117 | endChangeGesture();
118 | m_inGuiGesture = false;
119 |
120 | // Ensure that the next CController::timerCallback() call does not trigger a endChangeGesture() call.
121 | m_ticksSinceLastChange = GESTURE_LENGTH_IN_TICKS + 1;
122 | }
123 | }
124 |
125 | /**
126 | * Called at every CController::timerCallback() call.
127 | * Counts down the number of timer ticks that are considered as the duration of a "gesture", when
128 | * modifying a parameter via OSC. This is relevant for Touch automation.
129 | */
130 | void CAudioParameterFloat::Tick()
131 | {
132 | const ScopedLock lock(m_mutex);
133 |
134 | // Ensure that user ist'n dragging a GUI control and already in the middle of a gesture.
135 | if (!m_inGuiGesture && (m_ticksSinceLastChange <= GESTURE_LENGTH_IN_TICKS))
136 | {
137 | // Don't let counter grow unnecessarily into infinity,
138 | // we only need to know if maximum gesture length has been passed.
139 | m_ticksSinceLastChange++;
140 |
141 | // Once the tick counter passes the length of a gesture,
142 | // we consider the gesture ended.
143 | if (m_ticksSinceLastChange > GESTURE_LENGTH_IN_TICKS)
144 | endChangeGesture();
145 | }
146 | }
147 |
148 | /**
149 | * Callback which takes place after the parameter's value has been changed.
150 | * This reimplementation is used to remember the parameter's previous value.
151 | * @param newValue The new value, within the parameter's range (NOT normalized between 0.0f and 1.0f).
152 | */
153 | void CAudioParameterFloat::valueChanged(float newValue)
154 | {
155 | m_lastValue[1] = m_lastValue[0];
156 | m_lastValue[0] = newValue;
157 | }
158 |
159 | /**
160 | * Returns the value which was set before the current one.
161 | * @return The previous value, within the parameter's range (NOT normalized between 0.0f and 1.0f).
162 | */
163 | float CAudioParameterFloat::GetLastValue() const
164 | {
165 | return m_lastValue[1];
166 | }
167 |
168 | /**
169 | * Pass a parameter change to the host.
170 | * Will also trigger the start of a gesture, if not already in the middle of one.
171 | * @param newValue The new value, within the parameter's range (i.e. NOT normalized between 0.0f and 1.0f).
172 | */
173 | void CAudioParameterFloat::SetParameterValue(float newValue)
174 | {
175 | const ScopedLock lock(m_mutex);
176 |
177 | // Clip new value within allowed range for this parameter.
178 | newValue = jmax(jmin(newValue, range.end), range.start);
179 |
180 | // Check for an actual value change, taking precision errors into account.
181 | if ((newValue >= (get() + range.interval)) || (newValue <= (get() - range.interval)))
182 | {
183 | // If user ist'n dragging a GUI control and already in the middle of a gesture,
184 | // signal the start of a gesture now.
185 | if (!m_inGuiGesture)
186 | {
187 | if (m_ticksSinceLastChange > GESTURE_LENGTH_IN_TICKS)
188 | beginChangeGesture();
189 |
190 | // Change taking place so reset tick counter.
191 | m_ticksSinceLastChange = 0;
192 | }
193 |
194 | // Map the newValue to the 0.0 to 1.0 range, and then
195 | // pass the parameter value change to base class.
196 | setValueNotifyingHost(range.convertTo0to1(newValue));
197 | }
198 | }
199 |
200 |
201 | /*
202 | ===============================================================================
203 | Class CAudioParameterChoice
204 | ===============================================================================
205 | */
206 |
207 | /**
208 | * Object constructor.
209 | * @param parameterID Parameter unique ID
210 | * @param name Parameter abbreviated name.
211 | * @param choices The set of choices to use
212 | * @param defaultItemIndex The index of the default choice
213 | * @param label An optional label for the parameter's value
214 | * @param stringFromIndex An optional lambda function that converts a choice index to a string with a maximum length.
215 | * This may be used by hosts to display the parameter's value.
216 | * @param indexFromString An optional lambda function that parses a string and converts it into a choice index.
217 | * Some hosts use this to allow users to type in parameter values.
218 | */
219 | CAudioParameterChoice::CAudioParameterChoice( const String& parameterID,
220 | const String& name,
221 | const StringArray& choices,
222 | int defaultItemIndex,
223 | const String& label,
224 | std::function stringFromIndex,
225 | std::function indexFromString)
226 | : AudioParameterChoice(parameterID, name, choices, defaultItemIndex, label, stringFromIndex, indexFromString)
227 | {
228 | m_ticksSinceLastChange = GESTURE_LENGTH_IN_TICKS + 1;
229 | }
230 |
231 | /**
232 | * Object destructor.
233 | */
234 | CAudioParameterChoice::~CAudioParameterChoice()
235 | {
236 | }
237 |
238 | /**
239 | * Callback which takes place after the parameter's value has been changed.
240 | * This reimplementation is used to remember the parameter's previous value.
241 | * @param newValue The new choice index.
242 | */
243 | void CAudioParameterChoice::valueChanged(int newValue)
244 | {
245 | m_lastIndex[1] = m_lastIndex[0];
246 | m_lastIndex[0] = newValue;
247 | }
248 |
249 | /**
250 | * Returns the index which was set before the current one.
251 | * @return The previous choice index since the last valueChanged() call.
252 | */
253 | int CAudioParameterChoice::GetLastIndex() const
254 | {
255 | return m_lastIndex[1];
256 | }
257 |
258 | /**
259 | * Called at every CController::timerCallback() call.
260 | * Counts down the number of timer ticks that are considered as the duration of a "gesture", when
261 | * modifying a parameter via OSC. This is relevant for Touch automation.
262 | */
263 | void CAudioParameterChoice::Tick()
264 | {
265 | const ScopedLock lock(m_mutex);
266 |
267 | if (m_ticksSinceLastChange <= GESTURE_LENGTH_IN_TICKS)
268 | {
269 | // Don't let counter grow unnecessarily into infinity,
270 | // we only need to know if maximum gesture length has been passed.
271 | m_ticksSinceLastChange++;
272 |
273 | // Once the tick counter passes the length of a gesture,
274 | // we consider the gesture ended.
275 | if (m_ticksSinceLastChange > GESTURE_LENGTH_IN_TICKS)
276 | endChangeGesture();
277 | }
278 | }
279 |
280 | /**
281 | * Pass a parameter change to the host.
282 | * Will also trigger the start of a gesture, if not already in the middle of one.
283 | * @param newValue The new choice index as a float, from 0.0f, to N-1, where N is the number of choices.
284 | */
285 | void CAudioParameterChoice::SetParameterValue(float newValue)
286 | {
287 | const ScopedLock lock(m_mutex);
288 |
289 | int newChoice = static_cast(newValue);
290 |
291 | // AudioParameterChoice::getIndex() maps the internal 0.0f - 1.0f value to the 0 to N-1 range.
292 | if (getIndex() != newChoice)
293 | {
294 | // If user ist'n dragging a GUI control and already in the middle of a gesture,
295 | // signal the start of a gesture now.
296 | if (m_ticksSinceLastChange > GESTURE_LENGTH_IN_TICKS)
297 | beginChangeGesture();
298 |
299 | // Change taking place so reset tick counter.
300 | m_ticksSinceLastChange = 0;
301 |
302 | // Pass the parameter value change to base class.
303 | // NOTE: Need to map to 0.0f to 1.0f range again.
304 | float maxValue = static_cast(choices.size() - 1);
305 | setValueNotifyingHost(newChoice / maxValue);
306 | }
307 | }
308 |
309 |
310 | } // namespace dbaudio
311 |
--------------------------------------------------------------------------------
/SoundscapePlugin/Source/Parameters.h:
--------------------------------------------------------------------------------
1 | /*
2 | ===============================================================================
3 |
4 | Copyright (C) 2019 d&b audiotechnik GmbH & Co. KG. All Rights Reserved.
5 |
6 | This file is part of the Soundscape VST, AU, and AAX Plug-in.
7 |
8 | Redistribution and use in source and binary forms, with or without
9 | modification, are permitted provided that the following conditions are met:
10 |
11 | 1. Redistributions of source code must retain the above copyright notice,
12 | this list of conditions and the following disclaimer.
13 |
14 | 2. Redistributions in binary form must reproduce the above copyright notice,
15 | this list of conditions and the following disclaimer in the documentation
16 | and/or other materials provided with the distribution.
17 |
18 | 3. The name of the author may not be used to endorse or promote products
19 | derived from this software without specific prior written permission.
20 |
21 | THIS SOFTWARE IS PROVIDED BY d&b audiotechnik GmbH & Co. KG "AS IS" AND ANY
22 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24 | DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
29 | OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
30 | ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 |
32 | ===============================================================================
33 | */
34 |
35 |
36 | #pragma once
37 |
38 | #include "../JuceLibraryCode/JuceHeader.h"
39 |
40 |
41 | namespace dbaudio
42 | {
43 |
44 |
45 | /**
46 | * Class CAudioParameterFloat, a custom AudioParameterFloat which provides it's own implementation
47 | * of getNumSteps(), required for AAX. See this method's description for more info.
48 | *
49 | * This derivation supports automatic gesture management, which depends on the Tick() method
50 | * being called regular intervals.
51 | */
52 | class CAudioParameterFloat : public AudioParameterFloat
53 | {
54 | public:
55 | CAudioParameterFloat( String parameterID,
56 | String name,
57 | float minValue,
58 | float maxValue,
59 | float stepSize,
60 | float defaultValue);
61 |
62 | ~CAudioParameterFloat() override;
63 |
64 | void BeginGuiGesture();
65 | void EndGuiGesture();
66 |
67 | void SetParameterValue(float);
68 | float GetLastValue() const;
69 | void Tick();
70 |
71 | protected:
72 | int getNumSteps() const override;
73 | void valueChanged(float newValue) override;
74 |
75 | /**
76 | * Number of Tick() calls since the last value change.
77 | */
78 | int m_ticksSinceLastChange;
79 |
80 | /**
81 | * True if user is currently dragging or turning a GUI control, and thus in the middle of a gesture.
82 | */
83 | bool m_inGuiGesture;
84 |
85 | /**
86 | * SetParameterValue() and Tick() may be called from 2 different threads, so make sure
87 | * m_ticksSinceLastChange is handled in a tread-safe way.
88 | */
89 | CriticalSection m_mutex;
90 |
91 | /**
92 | * Since AudioParameterFloat::setValue() is unfortunately private, we use this to remember
93 | * the last two values in order to detect actual value changes in AudioProcessorParameter::Listener::parameterValueChanged().
94 | * These values are normalized between 0.0f and 1.0f.
95 | */
96 | float m_lastValue[2];
97 |
98 | JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CAudioParameterFloat)
99 | };
100 |
101 |
102 | /**
103 | * Class CAudioParameterChoice, a custom AudioParameterChoice.
104 | *
105 | * This derivation supports automatic gesture management, which depends on the Tick() method
106 | * being called regular intervals.
107 | */
108 | class CAudioParameterChoice : public AudioParameterChoice
109 | {
110 | public:
111 | CAudioParameterChoice( const String& parameterID,
112 | const String& name,
113 | const StringArray& choices,
114 | int defaultItemIndex,
115 | const String& label = String(),
116 | std::function stringFromIndex = nullptr,
117 | std::function indexFromString = nullptr);
118 |
119 | ~CAudioParameterChoice() override;
120 |
121 | void SetParameterValue(float);
122 | int GetLastIndex() const;
123 | void Tick();
124 |
125 | protected:
126 | void valueChanged(int newValue) override;
127 |
128 | /**
129 | * Number of Tick() calls since the last value change.
130 | */
131 | int m_ticksSinceLastChange;
132 |
133 | /**
134 | * SetParameterValue() and Tick() may be called from 2 different threads, so make sure
135 | * m_ticksSinceLastChange is handled in a tread-safe way.
136 | */
137 | CriticalSection m_mutex;
138 |
139 | /**
140 | * Since AudioParameterChoice::setValue() is unfortunately private, we use this to remember
141 | * the last two values in order to detect actual value changes in AudioProcessorParameter::Listener::parameterValueChanged().
142 | */
143 | int m_lastIndex[2];
144 |
145 | JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CAudioParameterChoice)
146 | };
147 |
148 |
149 | } // namespace dbaudio
150 |
--------------------------------------------------------------------------------
/SoundscapePlugin/Source/PluginEditor.h:
--------------------------------------------------------------------------------
1 | /*
2 | ===============================================================================
3 |
4 | Copyright (C) 2019 d&b audiotechnik GmbH & Co. KG. All Rights Reserved.
5 |
6 | This file is part of the Soundscape VST, AU, and AAX Plug-in.
7 |
8 | Redistribution and use in source and binary forms, with or without
9 | modification, are permitted provided that the following conditions are met:
10 |
11 | 1. Redistributions of source code must retain the above copyright notice,
12 | this list of conditions and the following disclaimer.
13 |
14 | 2. Redistributions in binary form must reproduce the above copyright notice,
15 | this list of conditions and the following disclaimer in the documentation
16 | and/or other materials provided with the distribution.
17 |
18 | 3. The name of the author may not be used to endorse or promote products
19 | derived from this software without specific prior written permission.
20 |
21 | THIS SOFTWARE IS PROVIDED BY d&b audiotechnik GmbH & Co. KG "AS IS" AND ANY
22 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24 | DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
29 | OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
30 | ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 |
32 | ===============================================================================
33 | */
34 |
35 |
36 | #pragma once
37 |
38 | #include "Gui.h"
39 | #include "SurfaceSlider.h"
40 | #include // m_xSlider;
82 |
83 | /**
84 | * Vertical slider for Y axis.
85 | */
86 | std::unique_ptr m_ySlider;
87 |
88 | /**
89 | * Slider for ReverbSendGain
90 | */
91 | std::unique_ptr m_reverbSendGainSlider;
92 |
93 | /**
94 | * Slider for SourceSpread
95 | */
96 | std::unique_ptr m_sourceSpreadSlider;
97 |
98 | /**
99 | * ComboBox for DelayMode
100 | */
101 | std::unique_ptr m_delayModeComboBox;
102 |
103 | /**
104 | * X axis slider label
105 | */
106 | std::unique_ptr m_xAxisLabel;
107 |
108 | /**
109 | * Y axis slider label
110 | */
111 | std::unique_ptr m_yAxisLabel;
112 |
113 | /**
114 | * ReverbSendGain slider label
115 | */
116 | std::unique_ptr m_reverbSendGainLabel;
117 |
118 | /**
119 | * SourceSpread slider label
120 | */
121 | std::unique_ptr m_sourceSpreadLabel;
122 |
123 | /**
124 | * DelayMode ComboBox label
125 | */
126 | std::unique_ptr m_delayModeLabel;
127 |
128 | /*
129 | * App version label
130 | */
131 | std::unique_ptr m_versionLabel;
132 |
133 | /*
134 | * App name
135 | */
136 | std::unique_ptr m_nameLabel;
137 |
138 | /*
139 | * Positioning Area label
140 | */
141 | std::unique_ptr m_posAreaLabel;
142 |
143 | /*
144 | * Source ID label
145 | */
146 | std::unique_ptr m_sourceIdLabel;
147 |
148 | /*
149 | * DS100 IP Address label
150 | */
151 | std::unique_ptr m_ipAddressLabel;
152 |
153 | /*
154 | * Send/receive rate label
155 | */
156 | std::unique_ptr m_rateLabel;
157 |
158 | /*
159 | * ComboBox selector for the positioning area
160 | */
161 | std::unique_ptr m_areaSelector;
162 |
163 | /*
164 | * Text editor for the source ID (matrix input)
165 | */
166 | std::unique_ptr m_sourceIdDigital;
167 |
168 | /*
169 | * Text editor for the DS100 IP Address
170 | */
171 | std::unique_ptr m_ipAddressTextEdit;
172 |
173 | /*
174 | * Text editor for the OSC send/receive rate in ms.
175 | */
176 | std::unique_ptr m_rateTextEdit;
177 |
178 | /*
179 | * Button used as Online indicator LED.
180 | */
181 | std::unique_ptr m_onlineLed;
182 |
183 | /*
184 | * Button for OSC Send mode (part of a radio button pair)
185 | */
186 | std::unique_ptr m_oscModeSend;
187 | /*
188 | * Button for OSC Receive mode (part of a radio button pair)
189 | */
190 | std::unique_ptr m_oscModeReceive;
191 |
192 | /*
193 | * 2D Slider component.
194 | */
195 | std::unique_ptr m_surfaceSlider;
196 |
197 | /*
198 | * Logo image.
199 | */
200 | Image m_dbLogo;
201 |
202 | /**
203 | * Button to open the overview window.
204 | */
205 | std::unique_ptr m_overviewButton;
206 |
207 | /**
208 | * Button to open the overview multi-slider overlay (Console-only).
209 | */
210 | std::unique_ptr m_overviewMultiSliderButton;
211 |
212 | /**
213 | * Pointer to the GUI overlay.
214 | * This can be an overview table, or an "about" overlay.
215 | */
216 | std::unique_ptr m_overlay;
217 |
218 | /**
219 | * Plug-in display name label. On the hosts which support updateTrackProperties or changeProgramName,
220 | * this will show the track's name where this Plug-in is located.
221 | */
222 | std::unique_ptr m_displayNameLabel;
223 |
224 | /**
225 | * Button to open the "About" overlay.
226 | */
227 | std::unique_ptr m_aboutButton;
228 |
229 | /**
230 | * Used to allow some tolerance when switching between fast and slow refresh rates for the GUI.
231 | * Once this counter reaches GUI_UPDATE_DELAY_TICKS, and no parameters have changed, the GUI will
232 | * switch to GUI_UPDATE_RATE_SLOW. Switches to GUI_UPDATE_RATE_FAST happen immediately after any change.
233 | */
234 | int m_ticksSinceLastChange = 0;
235 |
236 | /**
237 | * Keep track of the user's preferred Plug-In window size, and use it when opening a fresh window.
238 | */
239 | static Point m_pluginWindowSize;
240 |
241 | #ifdef DB_SHOW_DEBUG
242 | /**
243 | * Special textfield used for displaying debugging messages.
244 | */
245 | std::unique_ptr m_debugTextEdit;
246 | #endif
247 |
248 | JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CPluginEditor)
249 | };
250 |
251 |
252 | } // namespace dbaudio
253 |
--------------------------------------------------------------------------------
/SoundscapePlugin/Source/PluginProcessor.h:
--------------------------------------------------------------------------------
1 | /*
2 | ===============================================================================
3 |
4 | Copyright (C) 2019 d&b audiotechnik GmbH & Co. KG. All Rights Reserved.
5 |
6 | This file is part of the Soundscape VST, AU, and AAX Plug-in.
7 |
8 | Redistribution and use in source and binary forms, with or without
9 | modification, are permitted provided that the following conditions are met:
10 |
11 | 1. Redistributions of source code must retain the above copyright notice,
12 | this list of conditions and the following disclaimer.
13 |
14 | 2. Redistributions in binary form must reproduce the above copyright notice,
15 | this list of conditions and the following disclaimer in the documentation
16 | and/or other materials provided with the distribution.
17 |
18 | 3. The name of the author may not be used to endorse or promote products
19 | derived from this software without specific prior written permission.
20 |
21 | THIS SOFTWARE IS PROVIDED BY d&b audiotechnik GmbH & Co. KG "AS IS" AND ANY
22 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24 | DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
29 | OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
30 | ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 |
32 | ===============================================================================
33 | */
34 |
35 |
36 | #pragma once
37 |
38 | #include "Common.h"
39 |
40 |
41 | namespace dbaudio
42 | {
43 |
44 |
45 | /**
46 | * Forward declarations.
47 | */
48 | class CAudioParameterFloat;
49 | class CAudioParameterChoice;
50 |
51 |
52 | /**
53 | * Class CPlugin, a derived AudioProcessor which can be wrapped as VST, AU, or AAX.
54 | */
55 | class CPlugin :
56 | public AudioProcessor,
57 | public AudioProcessorParameter::Listener
58 | {
59 | public:
60 | /**
61 | * Target hosts or DAWs which require special handling of some kind.
62 | */
63 | enum TargetHost
64 | {
65 | TargetHost_Unknown = 0,
66 | TargetHost_ProTools,
67 | TargetHost_S6L
68 | };
69 |
70 | CPlugin();
71 | ~CPlugin() override;
72 |
73 | void InitializeSettings(SourceId sourceId, int mappingId, String ipAddress, int oscMsgRate, ComsMode newMode);
74 |
75 | SourceId GetSourceId() const;
76 | void SetSourceId(DataChangeSource changeSource, SourceId sourceId);
77 |
78 | int GetMappingId() const;
79 | void SetMappingId(DataChangeSource changeSource, int mappingId);
80 |
81 | String GetIpAddress() const;
82 | void SetIpAddress(DataChangeSource changeSource, String ipAddress);
83 |
84 | int GetMessageRate() const;
85 | void SetMessageRate(DataChangeSource changeSource, int oscMsgRate);
86 |
87 | ComsMode GetComsMode() const;
88 | void SetComsMode(DataChangeSource changeSource, ComsMode newMode);
89 | void RestoreComsMode(DataChangeSource changeSource);
90 | bool GetOnline() const;
91 | bool GetBypass() const;
92 |
93 | float GetParameterValue(AutomationParameterIndex paramIdx, bool normalized = false) const;
94 | void SetParameterValue(DataChangeSource changeSource, AutomationParameterIndex paramIdx, float newValue);
95 |
96 | bool GetParameterChanged(DataChangeSource changeSource, DataChangeTypes change);
97 | bool PopParameterChanged(DataChangeSource changeSource, DataChangeTypes change);
98 | void SetParameterChanged(DataChangeSource changeSource, DataChangeTypes changeTypes);
99 |
100 | void Tick();
101 | void SetParamInTransit(DataChangeTypes paramsChanged);
102 | bool IsParamInTransit(DataChangeTypes paramsChanged) const;
103 |
104 | void OnOverviewButtonClicked();
105 |
106 | #ifdef DB_SHOW_DEBUG
107 | void PushDebugMessage(String message);
108 | String GetDebugMessages();
109 | #endif
110 |
111 | bool IsTargetHostAvidConsole() const;
112 | TargetHost GetTargetHost() const;
113 |
114 | // Overriden functions of class AudioProcessor
115 |
116 | virtual void getStateInformation(MemoryBlock& destData) override;
117 | virtual void setStateInformation(const void* data, int sizeInBytes) override;
118 | virtual void updateTrackProperties(const TrackProperties& properties) override;
119 | virtual AudioProcessorParameter* getBypassParameter() const override;
120 |
121 | // Overriden functions of class AudioProcessorParameter::Listener
122 |
123 | virtual void parameterValueChanged(int parameterIndex, float newValue) override;
124 | virtual void parameterGestureChanged(int parameterIndex, bool gestureIsStarting) override;
125 |
126 | // Functions which need to be reimplemented from class AudioProcessor, but which
127 | // aren't relevant for our use.
128 |
129 | bool acceptsMidi() const override;
130 | void changeProgramName(int index, const String& newName) override;
131 | AudioProcessorEditor* createEditor() override;
132 | int getCurrentProgram() override;
133 | int getNumPrograms() override;
134 | const String getProgramName(int index) override;
135 | const String getName() const override;
136 | double getTailLengthSeconds() const override;
137 | bool hasEditor() const override;
138 | void prepareToPlay(double sampleRate, int samplesPerBlock) override;
139 | void processBlock(AudioSampleBuffer&, MidiBuffer&) override;
140 | bool producesMidi() const override;
141 | void releaseResources() override;
142 | void setCurrentProgram(int index) override;
143 | #ifndef JucePlugin_PreferredChannelConfigurations
144 | bool isBusesLayoutSupported(const BusesLayout& layouts) const override;
145 | #endif
146 |
147 | protected:
148 | /**
149 | * X coordinate in meters.
150 | * NOTE: not using std::unique_ptr here, see addParameter().
151 | */
152 | CAudioParameterFloat* m_xPos;
153 |
154 | /**
155 | * Y coordinate in meters.
156 | */
157 | CAudioParameterFloat* m_yPos;
158 |
159 | /**
160 | * Matrix input En-Space gain.
161 | */
162 | CAudioParameterFloat* m_reverbSendGain;
163 |
164 | /**
165 | * Sound object spread.
166 | */
167 | CAudioParameterFloat* m_sourceSpread;
168 |
169 | /**
170 | * Sound object delay mode (Off, Tight, Full).
171 | */
172 | CAudioParameterChoice* m_delayMode;
173 |
174 | /**
175 | * Bypass automation parameter: 1 for bypass, 0 for normal.
176 | */
177 | CAudioParameterChoice* m_bypassParam;
178 |
179 | /**
180 | * Current OSC communication mode, sending and/or receiving.
181 | */
182 | ComsMode m_comsMode;
183 |
184 | /**
185 | * Previous OSC communication mode, before going into Bypass.
186 | */
187 | ComsMode m_comsModeWhenNotBypassed;
188 |
189 | /*
190 | * Coordinate mapping index (1 to 4).
191 | */
192 | int m_mappingId;
193 |
194 | /*
195 | * SourceID, or matrix input number.
196 | */
197 | SourceId m_sourceId;
198 |
199 | /**
200 | * Unique ID of this Plug-in instance.
201 | * This is also this Plug-in's index within the CController::m_processors array.
202 | */
203 | PluginId m_pluginId;
204 |
205 | /**
206 | * Keep track of which automation parameters have changed recently.
207 | * The array has one entry for each application module (see enum DataChangeSource).
208 | */
209 | DataChangeTypes m_parametersChanged[DCS_Max];
210 |
211 | /**
212 | * Flags used to indicate when a SET command for a parameter is currently out on the network.
213 | * Until such a flag is cleared (in the Tick() method), calls to IsParamInTransit will return true.
214 | * This mechanism is used to ensure that parameters aren't overwritten right after having been
215 | * changed via the Gui or the host.
216 | */
217 | DataChangeTypes m_paramSetCommandsInTransit = DCT_None;
218 |
219 | /**
220 | * Name of this Plug-in instance. Some hosts (i.e. VST3) which support updateTrackProperties(..)
221 | * or changeProgramName(..) will set this to the DAW track name (i.e. "Guitar", or "Vocals", etc).
222 | * On other hosts this will remain empty.
223 | */
224 | String m_pluginDisplayName;
225 |
226 | /**
227 | * Member used to ensure that property changes are registered to the correct source.
228 | * See CPlugin::SetParameterValue().
229 | */
230 | DataChangeSource m_currentChangeSource = DCS_Host;
231 |
232 | #ifdef DB_SHOW_DEBUG
233 | /**
234 | * Temp buffer for debugging messages.
235 | */
236 | String m_debugMessageBuffer;
237 | #endif
238 |
239 | JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CPlugin)
240 | };
241 |
242 |
243 | } // namespace dbaudio
244 |
--------------------------------------------------------------------------------
/SoundscapePlugin/Source/SurfaceSlider.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | ===============================================================================
3 |
4 | Copyright (C) 2019 d&b audiotechnik GmbH & Co. KG. All Rights Reserved.
5 |
6 | This file is part of the Soundscape VST, AU, and AAX Plug-in.
7 |
8 | Redistribution and use in source and binary forms, with or without
9 | modification, are permitted provided that the following conditions are met:
10 |
11 | 1. Redistributions of source code must retain the above copyright notice,
12 | this list of conditions and the following disclaimer.
13 |
14 | 2. Redistributions in binary form must reproduce the above copyright notice,
15 | this list of conditions and the following disclaimer in the documentation
16 | and/or other materials provided with the distribution.
17 |
18 | 3. The name of the author may not be used to endorse or promote products
19 | derived from this software without specific prior written permission.
20 |
21 | THIS SOFTWARE IS PROVIDED BY d&b audiotechnik GmbH & Co. KG "AS IS" AND ANY
22 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24 | DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
29 | OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
30 | ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 |
32 | ===============================================================================
33 | */
34 |
35 |
36 | #include "SurfaceSlider.h"
37 | #include "Parameters.h"
38 | #include "PluginProcessor.h"
39 | #include "Controller.h"
40 | #include "Gui.h"
41 |
42 |
43 | namespace dbaudio
44 | {
45 |
46 |
47 | /**
48 | * Invalid PluginId used to signal when selection in CSurfaceMultiSlider is empty.
49 | */
50 | static constexpr PluginId INVALID_PLUGIN_ID = 0xFFFFFFFF;
51 |
52 |
53 | /*
54 | ===============================================================================
55 | Class CSurfaceSlider
56 | ===============================================================================
57 | */
58 |
59 | /**
60 | * Object constructor.
61 | * @param parent The audio processor object to act as parent.
62 | */
63 | CSurfaceSlider::CSurfaceSlider(AudioProcessor* parent)
64 | {
65 | m_parent = parent;
66 | }
67 |
68 | /**
69 | * Object destructor.
70 | */
71 | CSurfaceSlider::~CSurfaceSlider()
72 | {
73 | }
74 |
75 | /**
76 | * Reimplemented paint event function.
77 | * Components can override this method to draw their content. The paint() method gets called when
78 | * a region of a component needs redrawing, either because the component's repaint() method has
79 | * been called, or because something has happened on the screen that means a section of a window needs to be redrawn.
80 | * @param g The graphics context that must be used to do the drawing operations.
81 | */
82 | void CSurfaceSlider::paint(Graphics& g)
83 | {
84 | float w = static_cast(getLocalBounds().getWidth());
85 | float h = static_cast(getLocalBounds().getHeight());
86 |
87 | // Surface area
88 | Path outline;
89 | outline.addRectangle(0, 0, w, h);
90 |
91 | // X knob posiiton
92 | float x = 0;
93 | const Array& params = m_parent->getParameters();
94 | AudioParameterFloat* param = dynamic_cast (params[ParamIdx_X]);
95 | if (param)
96 | x = static_cast(*param) * w;
97 |
98 | // Y knob position
99 | float y = 0;
100 | param = dynamic_cast (params[ParamIdx_Y]);
101 | if (param)
102 | y = h - (static_cast(*param) * h);
103 |
104 | // Paint knob
105 | float knobSize = 10;
106 | outline.addEllipse(x - (knobSize / 2), y - (knobSize / 2), knobSize, knobSize);
107 |
108 | g.setColour(CDbStyle::GetDbColor(CDbStyle::MidColor));
109 | g.fillPath(outline);
110 | g.setColour(CDbStyle::GetDbColor(CDbStyle::ButtonColor));
111 | g.strokePath(outline, PathStrokeType(3)); // Stroke width
112 |
113 | }
114 |
115 | /**
116 | * Called when a mouse button is pressed.
117 | * @param e Details about the position and status of the mouse event, including the source component in which it occurred
118 | */
119 | void CSurfaceSlider::mouseDown(const MouseEvent& e)
120 | {
121 | float w = static_cast(getLocalBounds().getWidth());
122 | float h = static_cast(getLocalBounds().getHeight());
123 |
124 | // Get mouse position and scale it between 0 and 1.
125 | Point pos = e.getMouseDownPosition();
126 | float x = jmin(1.0, jmax(0.0, (static_cast(pos.getX()) / w)));
127 | float y = 1.0f - jmin(1.0, jmax(0.0, (static_cast(pos.getY()) / h)));
128 |
129 | CPlugin* plugin = dynamic_cast(m_parent);
130 | if (plugin)
131 | {
132 | // Set new X and Y values
133 | CAudioParameterFloat* param;
134 | param = dynamic_cast(m_parent->getParameters()[ParamIdx_X]);
135 | param->BeginGuiGesture();
136 | plugin->SetParameterValue(DCS_Gui, ParamIdx_X, x);
137 |
138 | param = dynamic_cast(m_parent->getParameters()[ParamIdx_Y]);
139 | param->BeginGuiGesture();
140 | plugin->SetParameterValue(DCS_Gui, ParamIdx_Y, y);
141 | }
142 | }
143 |
144 | /**
145 | * Called when the mouse is moved while a button is held down.
146 | * @param e Details about the position and status of the mouse event, including the source component in which it occurred
147 | */
148 | void CSurfaceSlider::mouseDrag(const MouseEvent& e)
149 | {
150 | float w = static_cast(getLocalBounds().getWidth());
151 | float h = static_cast(getLocalBounds().getHeight());
152 |
153 | // Get mouse position and scale it between 0 and 1.
154 | Point pos = e.getPosition();
155 | float x = jmin(1.0, jmax(0.0, (static_cast(pos.getX()) / w)));
156 | float y = 1.0f - jmin(1.0, jmax(0.0, (static_cast(pos.getY()) / h)));
157 |
158 | CPlugin* plugin = dynamic_cast(m_parent);
159 | if (plugin)
160 | {
161 | // Set new X and Y values
162 | plugin->SetParameterValue(DCS_Gui, ParamIdx_X, x);
163 | plugin->SetParameterValue(DCS_Gui, ParamIdx_Y, y);
164 | }
165 | }
166 |
167 | /**
168 | * Called when the mouse button is released.
169 | * Reimplemented just to call EndGuiGesture() to inform the host.
170 | * @param e Details about the position and status of the mouse event, including the source component in which it occurred
171 | */
172 | void CSurfaceSlider::mouseUp(const MouseEvent& e)
173 | {
174 | ignoreUnused(e);
175 |
176 | CAudioParameterFloat* param;
177 | param = dynamic_cast(m_parent->getParameters()[ParamIdx_X]);
178 | param->EndGuiGesture();
179 |
180 | param = dynamic_cast(m_parent->getParameters()[ParamIdx_Y]);
181 | param->EndGuiGesture();
182 | }
183 |
184 |
185 | /*
186 | ===============================================================================
187 | Class CSurfaceMultiSlider
188 | ===============================================================================
189 | */
190 |
191 | /**
192 | * Object constructor.
193 | */
194 | CSurfaceMultiSlider::CSurfaceMultiSlider()
195 | {
196 | m_selected = INVALID_PLUGIN_ID;
197 | }
198 |
199 | /**
200 | * Object destructor.
201 | */
202 | CSurfaceMultiSlider::~CSurfaceMultiSlider()
203 | {
204 | }
205 |
206 | /**
207 | * Reimplemented paint event function.
208 | * Components can override this method to draw their content. The paint() method gets called when
209 | * a region of a component needs redrawing, either because the component's repaint() method has
210 | * been called, or because something has happened on the screen that means a section of a window needs to be redrawn.
211 | * @param g The graphics context that must be used to do the drawing operations.
212 | */
213 | void CSurfaceMultiSlider::paint(Graphics& g)
214 | {
215 | float w = static_cast(getLocalBounds().getWidth());
216 | float h = static_cast(getLocalBounds().getHeight());
217 |
218 | // Surface background area
219 | g.setColour(CDbStyle::GetDbColor(CDbStyle::MidColor));
220 | g.fillRect(Rectangle(0.0f, 0.0f, w, h));
221 |
222 | // Draw grid
223 | const float dashLengths[2] = { 5.0f, 6.0f };
224 | const float lineThickness = 1.0f;
225 | g.setColour(CDbStyle::GetDbColor(CDbStyle::MidColor).brighter(0.15f));
226 | g.drawDashedLine(Line(w * 0.25f, 0.0f, w * 0.25f, h), dashLengths, 2, lineThickness);
227 | g.drawDashedLine(Line(w * 0.50f, 0.0f, w * 0.50f, h), dashLengths, 2, lineThickness);
228 | g.drawDashedLine(Line(w * 0.75f, 0.0f, w * 0.75f, h), dashLengths, 2, lineThickness);
229 | g.drawDashedLine(Line(0.0f, h * 0.25f, w, h * 0.25f), dashLengths, 2, lineThickness);
230 | g.drawDashedLine(Line(0.0f, h * 0.50f, w, h * 0.50f), dashLengths, 2, lineThickness);
231 | g.drawDashedLine(Line(0.0f, h * 0.75f, w, h * 0.75f), dashLengths, 2, lineThickness);
232 |
233 | // Surface frame
234 | g.setColour(CDbStyle::GetDbColor(CDbStyle::ButtonColor));
235 | g.drawRect(Rectangle(0.0f, 0.0f, w, h), 1.5f);
236 |
237 | float knobSize = 10.0f;
238 | for (auto iter = m_cachedPositions.cbegin(); iter != m_cachedPositions.cend(); ++iter)
239 | {
240 | int inputNo((*iter).second.first);
241 |
242 | // Map the x/y coordinates to the pixel-wise dimensions of the surface area.
243 | Point pt((*iter).second.second);
244 | float x = pt.x * w;
245 | float y = h - (pt.y * h);
246 |
247 | // Generate a color variant based on the input number, so make the nipples easier to tell from each other.
248 | Colour shade(juce::uint8(inputNo * 111), juce::uint8(inputNo * 222), juce::uint8(inputNo * 333));
249 | g.setColour(CDbStyle::GetDbColor(CDbStyle::DarkTextColor).interpolatedWith(shade, 0.3f));
250 |
251 | // Paint knob
252 | g.drawEllipse(Rectangle(x - (knobSize / 2.0f), y - (knobSize / 2.0f), knobSize, knobSize), 3.0f);
253 |
254 | // Input number label
255 | g.setFont(Font(11.0, Font::plain));
256 | g.drawText(String(inputNo), Rectangle(x - knobSize, y + 3, knobSize * 2.0f, knobSize * 2.0f), Justification::centred, true);
257 | }
258 | }
259 |
260 | /**
261 | * Called when a mouse button is pressed.
262 | * @param e Details about the position and status of the mouse event, including the source component in which it occurred
263 | */
264 | void CSurfaceMultiSlider::mouseDown(const MouseEvent& e)
265 | {
266 | float w = static_cast(getLocalBounds().getWidth());
267 | float h = static_cast(getLocalBounds().getHeight());
268 |
269 | // Mouse click position (in pixel units)
270 | Point mousePos(static_cast(e.getMouseDownPosition().x), static_cast(e.getMouseDownPosition().y));
271 | float knobSize = 15.0f;
272 |
273 | for (auto iter = m_cachedPositions.cbegin(); iter != m_cachedPositions.cend(); ++iter)
274 | {
275 | // Map the x/y coordinates to the pixel-wise dimensions of the surface area.
276 | Point pt((*iter).second.second);
277 | float x = pt.x * w;
278 | float y = h - (pt.y * h);
279 |
280 | Path knobPath;
281 | knobPath.addEllipse(Rectangle(x - (knobSize / 2.0f), y - (knobSize / 2.0f), knobSize, knobSize));
282 |
283 | // Check if the mouse click landed inside any of the knobs.
284 | if (knobPath.contains(mousePos))
285 | {
286 | // Set this source as "selected" and begin a drag gesture.
287 | m_selected = (*iter).first;
288 |
289 | CController* ctrl = CController::GetInstance();
290 | if (ctrl)
291 | {
292 | CPlugin* plugin = ctrl->GetProcessor(m_selected);
293 | jassert(plugin);
294 | if (plugin)
295 | {
296 | CAudioParameterFloat* param;
297 | param = dynamic_cast(plugin->getParameters()[ParamIdx_X]);
298 | param->BeginGuiGesture();
299 |
300 | param = dynamic_cast(plugin->getParameters()[ParamIdx_Y]);
301 | param->BeginGuiGesture();
302 | }
303 | }
304 |
305 | // Found a knob to select, skip the rest.
306 | break;
307 | }
308 | }
309 | }
310 |
311 | /**
312 | * Called when the mouse is moved while a button is held down.
313 | * @param e Details about the position and status of the mouse event, including the source component in which it occurred
314 | */
315 | void CSurfaceMultiSlider::mouseDrag(const MouseEvent& e)
316 | {
317 | if (m_selected != INVALID_PLUGIN_ID)
318 | {
319 | CController* ctrl = CController::GetInstance();
320 | if (ctrl)
321 | {
322 | CPlugin* plugin = ctrl->GetProcessor(m_selected);
323 | if (plugin)
324 | {
325 | // Get mouse pixel-wise position and scale it between 0 and 1.
326 | Point pos = e.getPosition();
327 | float x = jmin(1.0, jmax(0.0, (static_cast(pos.getX()) / getLocalBounds().getWidth())));
328 | float y = 1.0f - jmin(1.0, jmax(0.0, (static_cast(pos.getY()) / getLocalBounds().getHeight())));
329 |
330 | plugin->SetParameterValue(DCS_Overview, ParamIdx_X, x);
331 | plugin->SetParameterValue(DCS_Overview, ParamIdx_Y, y);
332 | }
333 | }
334 | }
335 | }
336 |
337 | /**
338 | * Called when the mouse button is released.
339 | * Reimplemented just to call EndGuiGesture() to inform the host.
340 | * @param e Details about the position and status of the mouse event, including the source component in which it occurred
341 | */
342 | void CSurfaceMultiSlider::mouseUp(const MouseEvent& e)
343 | {
344 | ignoreUnused(e);
345 |
346 | if (m_selected != INVALID_PLUGIN_ID)
347 | {
348 | CController* ctrl = CController::GetInstance();
349 | if (ctrl)
350 | {
351 | CPlugin* plugin = ctrl->GetProcessor(m_selected);
352 | if (plugin)
353 | {
354 | dynamic_cast(plugin->getParameters()[ParamIdx_X])->EndGuiGesture();
355 | dynamic_cast(plugin->getParameters()[ParamIdx_Y])->EndGuiGesture();
356 |
357 | // Get mouse pixel-wise position and scale it between 0 and 1.
358 | Point pos = e.getPosition();
359 | float x = jmin(1.0, jmax(0.0, (static_cast(pos.getX()) / getLocalBounds().getWidth())));
360 | float y = 1.0f - jmin(1.0, jmax(0.0, (static_cast(pos.getY()) / getLocalBounds().getHeight())));
361 |
362 | plugin->SetParameterValue(DCS_Overview, ParamIdx_X, x);
363 | plugin->SetParameterValue(DCS_Overview, ParamIdx_Y, y);
364 | }
365 | }
366 |
367 | // De-select knob.
368 | m_selected = INVALID_PLUGIN_ID;
369 | }
370 | }
371 |
372 | /**
373 | * Update the local hash of plugins and their current coordinates.
374 | * @param positions Map where the keys are the PluginIds of each source, while values are pairs of the corresponding
375 | * input number and position coordinates (0.0 to 1.0).
376 | */
377 | void CSurfaceMultiSlider::UpdatePositions(PositionCache positions)
378 | {
379 | m_cachedPositions = positions;
380 | }
381 |
382 |
383 | } // namespace dbaudio
384 |
--------------------------------------------------------------------------------
/SoundscapePlugin/Source/SurfaceSlider.h:
--------------------------------------------------------------------------------
1 | /*
2 | ===============================================================================
3 |
4 | Copyright (C) 2019 d&b audiotechnik GmbH & Co. KG. All Rights Reserved.
5 |
6 | This file is part of the Soundscape VST, AU, and AAX Plug-in.
7 |
8 | Redistribution and use in source and binary forms, with or without
9 | modification, are permitted provided that the following conditions are met:
10 |
11 | 1. Redistributions of source code must retain the above copyright notice,
12 | this list of conditions and the following disclaimer.
13 |
14 | 2. Redistributions in binary form must reproduce the above copyright notice,
15 | this list of conditions and the following disclaimer in the documentation
16 | and/or other materials provided with the distribution.
17 |
18 | 3. The name of the author may not be used to endorse or promote products
19 | derived from this software without specific prior written permission.
20 |
21 | THIS SOFTWARE IS PROVIDED BY d&b audiotechnik GmbH & Co. KG "AS IS" AND ANY
22 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24 | DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
29 | OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
30 | ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 |
32 | ===============================================================================
33 | */
34 |
35 |
36 | #pragma once
37 |
38 | #include "../JuceLibraryCode/JuceHeader.h"
39 | #include "Common.h"
40 | #include
41 |
42 |
43 | namespace dbaudio
44 | {
45 |
46 |
47 | /**
48 | * SurfaceSlider class provides a 2D-Slider or "X/Y controller".
49 | */
50 | class CSurfaceSlider : public Component
51 | {
52 | public:
53 | CSurfaceSlider(AudioProcessor* parent);
54 | ~CSurfaceSlider() override;
55 |
56 | void paint (Graphics& g) override;
57 | void mouseDown (const MouseEvent& e) override;
58 | void mouseDrag (const MouseEvent& e) override;
59 | void mouseUp (const MouseEvent& e) override;
60 |
61 | private:
62 | /**
63 | * AudioProcessor object to act as parent to this component.
64 | */
65 | AudioProcessor* m_parent = nullptr;
66 |
67 | JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (CSurfaceSlider)
68 | };
69 |
70 |
71 | /**
72 | * SurfaceSlider for displaying and controlling multiple sources.
73 | */
74 | class CSurfaceMultiSlider : public Component
75 | {
76 | public:
77 | typedef std::map>> PositionCache;
78 |
79 | CSurfaceMultiSlider();
80 | ~CSurfaceMultiSlider() override;
81 |
82 | void UpdatePositions(PositionCache positions);
83 |
84 | void paint (Graphics& g) override;
85 | void mouseDown (const MouseEvent& e) override;
86 | void mouseDrag (const MouseEvent& e) override;
87 | void mouseUp (const MouseEvent& e) override;
88 |
89 | private:
90 | /**
91 | * PluginId of the currently selected knob, if any.
92 | */
93 | PluginId m_selected;
94 |
95 | /**
96 | * To save us from iterating over all Plug-ins at every click, cache the source positions.
97 | * Keys are the PluginIds of each source, while values are pairs of the corresponding
98 | * input number and position coordinates (0.0 to 1.0).
99 | */
100 | PositionCache m_cachedPositions;
101 |
102 | JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CSurfaceMultiSlider)
103 | };
104 |
105 |
106 | } // namespace dbaudio
107 |
--------------------------------------------------------------------------------
/SoundscapePlugin/Source/Version.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | ===============================================================================
3 |
4 | Copyright (C) 2019 d&b audiotechnik GmbH & Co. KG. All Rights Reserved.
5 |
6 | This file is part of the Soundscape VST, AU, and AAX Plug-in.
7 |
8 | Redistribution and use in source and binary forms, with or without
9 | modification, are permitted provided that the following conditions are met:
10 |
11 | 1. Redistributions of source code must retain the above copyright notice,
12 | this list of conditions and the following disclaimer.
13 |
14 | 2. Redistributions in binary form must reproduce the above copyright notice,
15 | this list of conditions and the following disclaimer in the documentation
16 | and/or other materials provided with the distribution.
17 |
18 | 3. The name of the author may not be used to endorse or promote products
19 | derived from this software without specific prior written permission.
20 |
21 | THIS SOFTWARE IS PROVIDED BY d&b audiotechnik GmbH & Co. KG "AS IS" AND ANY
22 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24 | DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
29 | OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
30 | ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 |
32 | ===============================================================================
33 | */
34 |
35 |
36 | #include "Version.h"
37 |
38 |
39 | namespace dbaudio
40 | {
41 |
42 |
43 | /*
44 | ===============================================================================
45 | Class CVersion
46 | ===============================================================================
47 | */
48 |
49 | /**
50 | * Class standard constructor.
51 | */
52 | CVersion::CVersion()
53 | {
54 | m_version.all = 0; // Default initialization (invalid version);
55 | }
56 |
57 | /**
58 | * Class constructor.
59 | * @param major Major version number as uint16.
60 | * @param minor Minor version number as uint16.
61 | */
62 | CVersion::CVersion(juce::uint16 major, juce::uint16 minor)
63 | {
64 | m_version.v_struct.major = major;
65 | m_version.v_struct.minor = minor;
66 | }
67 |
68 | /**
69 | * Class constructor.
70 | * @param source A 32bit integer value containing the version's
71 | * major (msb 2 bytes) and minor (lsb 2 bytes) numbers.
72 | */
73 | CVersion::CVersion(juce::uint32 source)
74 | {
75 | m_version.all = source;
76 | }
77 |
78 | /**
79 | * Class constructor.
80 | * @param source A string containing the version's major (M) and minor (m) numbers
81 | * in the form MMM.mmm or also MMM.mmm.xxx where the debug part of the
82 | * version string (xxx) is ignored.
83 | */
84 | CVersion::CVersion(String source)
85 | {
86 | m_version.all = 0; // Default initialization (invalid version);
87 | if (source.length() > 0)
88 | {
89 | m_version.v_struct.major = static_cast((source.upToFirstOccurrenceOf(".", false, true)).getIntValue());
90 | source = (source.fromFirstOccurrenceOf(".", false, true)).upToFirstOccurrenceOf(".", false, true);
91 | m_version.v_struct.minor = static_cast(source.getIntValue());
92 | }
93 | }
94 |
95 | /**
96 | * Class copy constructor.
97 | * @param source CVersion object to copy from.
98 | */
99 | CVersion::CVersion(const CVersion &source)
100 | {
101 | *this = source;
102 | }
103 |
104 | /**
105 | * Class destructor.
106 | */
107 | CVersion::~CVersion()
108 | {
109 | }
110 |
111 | /**
112 | * Assignment operator.
113 | * @param r CVersion object to copy from.
114 | * @return Reference to this object.
115 | */
116 | CVersion& CVersion::operator=(const CVersion& r)
117 | {
118 | m_version.all = r.m_version.all;
119 | return *this;
120 | }
121 |
122 | /**
123 | * Is equal operator.
124 | * @param r CVersion object to compare to.
125 | * @return True if objects are equal.
126 | */
127 | bool CVersion::operator==(const CVersion& r)
128 | {
129 | return (m_version.all == r.m_version.all);
130 | }
131 |
132 | /**
133 | * Not equal operator.
134 | * @param r CVersion object to compare to.
135 | * @return True if objects are different.
136 | */
137 | bool CVersion::operator!=(const CVersion& r)
138 | {
139 | return (m_version.all != r.m_version.all);
140 | }
141 |
142 | /**
143 | * Less than operator.
144 | * @param r CVersion object to compare to.
145 | * @return True if this object is smaller than r.
146 | */
147 | bool CVersion::operator<(const CVersion& r)
148 | {
149 | if (m_version.v_struct.major == r.m_version.v_struct.major)
150 | return (m_version.v_struct.minor < r.m_version.v_struct.minor);
151 | return (m_version.v_struct.major < r.m_version.v_struct.major);
152 | }
153 |
154 | /**
155 | * Less or equal then operator.
156 | * @param r CVersion object to compare to.
157 | * @return True if this object is smaller or equal to r.
158 | */
159 | bool CVersion::operator<=(const CVersion& r)
160 | {
161 | return ((m_version.all == r.m_version.all) || (m_version.all < r.m_version.all));
162 | }
163 |
164 | /**
165 | * Larger than operator.
166 | * @param r CVersion object to compare to.
167 | * @return True if this object is larger than r.
168 | */
169 | bool CVersion::operator>(const CVersion& r)
170 | {
171 | if (m_version.v_struct.major == r.m_version.v_struct.major)
172 | return (m_version.v_struct.minor > r.m_version.v_struct.minor);
173 | return (m_version.v_struct.major > r.m_version.v_struct.major);
174 | }
175 |
176 | /**
177 | * Larger or equal then operator.
178 | * @param r CVersion object to compare to.
179 | * @return True if this object is larger or equal to r.
180 | */
181 | bool CVersion::operator>=(const CVersion& r)
182 | {
183 | return ((m_version.all == r.m_version.all) || (m_version.all > r.m_version.all));
184 | }
185 |
186 | /**
187 | * Check if this is a valid version number (non-zero).
188 | * @return True if the version is non-zero.
189 | */
190 | bool CVersion::IsValid() const
191 | {
192 | return (m_version.all > 0);
193 | }
194 |
195 | /**
196 | * Convert to string.
197 | * @return A string representing the version in the format [major].[minor]
198 | */
199 | String CVersion::ToString() const
200 | {
201 | return String::formatted("%d.%d", m_version.v_struct.major, m_version.v_struct.minor);
202 | }
203 |
204 | /**
205 | * Convert version to a 32bit integer.
206 | * @return A 32bit integer containing the complete version number.
207 | * Major version is in the msb 16 bits, and the minor version in the lsb 16 bits.
208 | */
209 | juce::uint32 CVersion::ToInt() const
210 | {
211 | return m_version.all;
212 | }
213 |
214 |
215 | } // namespace dbaudio
216 |
--------------------------------------------------------------------------------
/SoundscapePlugin/Source/Version.h:
--------------------------------------------------------------------------------
1 | /*
2 | ===============================================================================
3 |
4 | Copyright (C) 2019 d&b audiotechnik GmbH & Co. KG. All Rights Reserved.
5 |
6 | This file is part of the Soundscape VST, AU, and AAX Plug-in.
7 |
8 | Redistribution and use in source and binary forms, with or without
9 | modification, are permitted provided that the following conditions are met:
10 |
11 | 1. Redistributions of source code must retain the above copyright notice,
12 | this list of conditions and the following disclaimer.
13 |
14 | 2. Redistributions in binary form must reproduce the above copyright notice,
15 | this list of conditions and the following disclaimer in the documentation
16 | and/or other materials provided with the distribution.
17 |
18 | 3. The name of the author may not be used to endorse or promote products
19 | derived from this software without specific prior written permission.
20 |
21 | THIS SOFTWARE IS PROVIDED BY d&b audiotechnik GmbH & Co. KG "AS IS" AND ANY
22 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24 | DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
29 | OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
30 | ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 |
32 | ===============================================================================
33 | */
34 |
35 |
36 | #pragma once
37 |
38 | #include "../JuceLibraryCode/JuceHeader.h"
39 |
40 |
41 | namespace dbaudio
42 | {
43 |
44 |
45 | /**
46 | * Version management class
47 | */
48 | class CVersion
49 | {
50 | public:
51 |
52 | #pragma pack(push,1)
53 | typedef union version_t
54 | {
55 | struct
56 | {
57 | // for the little endian architectures you have to specify the
58 | // bitfields from the LSB to the MSB
59 | juce::uint32 minor : 16; //< Minor version number.
60 | juce::uint32 major : 16; //< Major version number.
61 | } v_struct;
62 | juce::uint32 all; //< All bits as 32bit integer value.
63 | } version_t;
64 | #pragma pack(pop)
65 |
66 | CVersion();
67 | CVersion(juce::uint16 major, juce::uint16 minor);
68 | CVersion(juce::uint32);
69 | CVersion(String);
70 | CVersion(const CVersion &r);
71 | virtual ~CVersion();
72 |
73 | CVersion& operator=(const CVersion& r);
74 | bool operator==(const CVersion& r);
75 | bool operator!=(const CVersion& r);
76 | bool operator<(const CVersion& r);
77 | bool operator<=(const CVersion& r);
78 | bool operator>(const CVersion& r);
79 | bool operator>=(const CVersion& r);
80 |
81 | bool IsValid() const;
82 | String ToString() const;
83 | juce::uint32 ToInt() const;
84 |
85 | protected:
86 | /**
87 | * Major and minor version struct.
88 | */
89 | version_t m_version;
90 | };
91 |
92 |
93 | } // namespace dbaudio
94 |
--------------------------------------------------------------------------------
/db Soundscape Infos/dbaudio-osc-protocol-ds100-1.2.4-en.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dbaudio-soundscape/db-Soundscape-DAW-Plugins/0068b42cdb0fd56fb18073d48e0d078bb8e05506/db Soundscape Infos/dbaudio-osc-protocol-ds100-1.2.4-en.pdf
--------------------------------------------------------------------------------
/db Soundscape Infos/dbaudio_DS100_Manual_1.4_en.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dbaudio-soundscape/db-Soundscape-DAW-Plugins/0068b42cdb0fd56fb18073d48e0d078bb8e05506/db Soundscape Infos/dbaudio_DS100_Manual_1.4_en.pdf
--------------------------------------------------------------------------------
/db Soundscape Infos/dbaudio_TI_501_dbSoundscape_1.6_en-2.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dbaudio-soundscape/db-Soundscape-DAW-Plugins/0068b42cdb0fd56fb18073d48e0d078bb8e05506/db Soundscape Infos/dbaudio_TI_501_dbSoundscape_1.6_en-2.pdf
--------------------------------------------------------------------------------
/dbsoundscape-DAW-plug-in-for-ds100.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dbaudio-soundscape/db-Soundscape-DAW-Plugins/0068b42cdb0fd56fb18073d48e0d078bb8e05506/dbsoundscape-DAW-plug-in-for-ds100.pdf
--------------------------------------------------------------------------------