iPlug2 - C++ Audio Plug-in Framework
IPlugAPP_host.h
1 /*
2  ==============================================================================
3 
4  This file is part of the iPlug 2 library. Copyright (C) the iPlug 2 developers.
5 
6  See LICENSE.txt for more info.
7 
8  ==============================================================================
9 */
10 
11 #pragma once
12 
31 #include <cstdlib>
32 #include <string>
33 #include <vector>
34 #include <limits>
35 #include <memory>
36 
37 #include "wdltypes.h"
38 #include "wdlstring.h"
39 
40 #include "IPlugPlatform.h"
41 #include "IPlugConstants.h"
42 
43 #include "IPlugAPP.h"
44 
45 #include "config.h"
46 
47 #ifdef OS_WIN
48  #include <WindowsX.h>
49  #include <commctrl.h>
50  #include <shlobj.h>
51  #define DEFAULT_INPUT_DEV "Default Device"
52  #define DEFAULT_OUTPUT_DEV "Default Device"
53 #elif defined(OS_MAC)
54  #include "IPlugSWELL.h"
55  #define SLEEP( milliseconds ) usleep( (unsigned long) (milliseconds * 1000.0) )
56  #define DEFAULT_INPUT_DEV "Built-in Input"
57  #define DEFAULT_OUTPUT_DEV "Built-in Output"
58 #elif defined(OS_LINUX)
59  #include "IPlugSWELL.h"
60 #endif
61 
62 #include "RtAudio.h"
63 #include "RtMidi.h"
64 
65 #define OFF_TEXT "off"
66 
67 extern HWND gHWND;
68 extern HINSTANCE gHINSTANCE;
69 
70 BEGIN_IPLUG_NAMESPACE
71 
72 const int kNumBufferSizeOptions = 11;
73 const std::string kBufferSizeOptions[kNumBufferSizeOptions] = {"32", "64", "96", "128", "192", "256", "512", "1024", "2048", "4096", "8192" };
74 const int kDeviceDS = 0; const int kDeviceCoreAudio = 0; const int kDeviceAlsa = 0;
75 const int kDeviceASIO = 1; const int kDeviceJack = 1;
76 extern UINT gSCROLLMSG;
77 
78 class IPlugAPP;
79 
82 {
83 public:
84 
86  struct AppState
87  {
88  WDL_String mAudioInDev;
89  WDL_String mAudioOutDev;
90  WDL_String mMidiInDev;
91  WDL_String mMidiOutDev;
92  uint32_t mAudioDriverType;
93  uint32_t mAudioSR;
94  uint32_t mBufferSize;
95  uint32_t mMidiInChan;
96  uint32_t mMidiOutChan;
97 
98  uint32_t mAudioInChanL;
99  uint32_t mAudioInChanR;
100  uint32_t mAudioOutChanL;
101  uint32_t mAudioOutChanR;
102 
103  AppState()
104  : mAudioInDev(DEFAULT_INPUT_DEV)
105  , mAudioOutDev(DEFAULT_OUTPUT_DEV)
106  , mMidiInDev(OFF_TEXT)
107  , mMidiOutDev(OFF_TEXT)
108  , mAudioDriverType(0) // DirectSound / CoreAudio by default
109  , mBufferSize(512)
110  , mAudioSR(44100)
111  , mMidiInChan(0)
112  , mMidiOutChan(0)
113 
114  , mAudioInChanL(1)
115  , mAudioInChanR(2)
116  , mAudioOutChanL(1)
117  , mAudioOutChanR(2)
118  {
119  }
120 
121  AppState (const AppState& obj)
122  : mAudioInDev(obj.mAudioInDev.Get())
123  , mAudioOutDev(obj.mAudioOutDev.Get())
124  , mMidiInDev(obj.mMidiInDev.Get())
125  , mMidiOutDev(obj.mMidiOutDev.Get())
126  , mAudioDriverType(obj.mAudioDriverType)
127  , mBufferSize(obj.mBufferSize)
128  , mAudioSR(obj.mAudioSR)
129  , mMidiInChan(obj.mMidiInChan)
130  , mMidiOutChan(obj.mMidiOutChan)
131 
132  , mAudioInChanL(obj.mAudioInChanL)
133  , mAudioInChanR(obj.mAudioInChanR)
134  , mAudioOutChanL(obj.mAudioInChanL)
135  , mAudioOutChanR(obj.mAudioInChanR)
136  {
137  }
138 
139  bool operator==(const AppState& rhs) const {
140  return (rhs.mAudioDriverType == mAudioDriverType &&
141  rhs.mBufferSize == mBufferSize &&
142  rhs.mAudioSR == mAudioSR &&
143  rhs.mMidiInChan == mMidiInChan &&
144  rhs.mMidiOutChan == mMidiOutChan &&
145  (strcmp(rhs.mAudioInDev.Get(), mAudioInDev.Get()) == 0) &&
146  (strcmp(rhs.mAudioOutDev.Get(), mAudioOutDev.Get()) == 0) &&
147  (strcmp(rhs.mMidiInDev.Get(), mMidiInDev.Get()) == 0) &&
148  (strcmp(rhs.mMidiOutDev.Get(), mMidiOutDev.Get()) == 0) &&
149 
150  rhs.mAudioInChanL == mAudioInChanL &&
151  rhs.mAudioInChanR == mAudioInChanR &&
152  rhs.mAudioOutChanL == mAudioOutChanL &&
153  rhs.mAudioOutChanR == mAudioOutChanR
154 
155  );
156  }
157  bool operator!=(const AppState& rhs) const { return !operator==(rhs); }
158  };
159 
160  static IPlugAPPHost* Create();
161  static std::unique_ptr<IPlugAPPHost> sInstance;
162 
163  void PopulateSampleRateList(HWND hwndDlg, RtAudio::DeviceInfo* pInputDevInfo, RtAudio::DeviceInfo* pOutputDevInfo);
164  void PopulateAudioInputList(HWND hwndDlg, RtAudio::DeviceInfo* pInfo);
165  void PopulateAudioOutputList(HWND hwndDlg, RtAudio::DeviceInfo* pInfo);
166  void PopulateDriverSpecificControls(HWND hwndDlg);
167  void PopulateAudioDialogs(HWND hwndDlg);
168  bool PopulateMidiDialogs(HWND hwndDlg);
169  void PopulatePreferencesDialog(HWND hwndDlg);
170 
171  IPlugAPPHost();
172  ~IPlugAPPHost();
173 
174  bool OpenWindow(HWND pParent);
175  void CloseWindow();
176 
177  bool Init();
178  bool InitState();
179  void UpdateINI();
180 
184  std::string GetAudioDeviceName(int idx) const;
185  // returns the rtaudio device ID, based on the (truncated) device name
186 
190  int GetAudioDeviceIdx(const char* name) const;
191 
195  int GetMIDIPortNumber(ERoute direction, const char* name) const;
196 
198  void ProbeAudioIO();
199  void ProbeMidiIO();
200  bool InitMidi();
201  void CloseAudio();
202  bool InitAudio(uint32_t inId, uint32_t outId, uint32_t sr, uint32_t iovs);
203  bool AudioSettingsInStateAreEqual(AppState& os, AppState& ns);
204  bool MIDISettingsInStateAreEqual(AppState& os, AppState& ns);
205 
206  bool TryToChangeAudioDriverType();
207  bool TryToChangeAudio();
208  bool SelectMIDIDevice(ERoute direction, const char* portName);
209 
210  static int AudioCallback(void* pOutputBuffer, void* pInputBuffer, uint32_t nFrames, double streamTime, RtAudioStreamStatus status, void* pUserData);
211  static void MIDICallback(double deltatime, std::vector<uint8_t>* pMsg, void* pUserData);
212  static void ErrorCallback(RtAudioError::Type type, const std::string& errorText);
213 
214  static WDL_DLGRET PreferencesDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
215  static WDL_DLGRET MainDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
216 
217  IPlugAPP* GetPlug() { return mIPlug.get(); }
218 private:
219  std::unique_ptr<IPlugAPP> mIPlug = nullptr;
220  std::unique_ptr<RtAudio> mDAC = nullptr;
221  std::unique_ptr<RtMidiIn> mMidiIn = nullptr;
222  std::unique_ptr<RtMidiOut> mMidiOut = nullptr;
223  int mMidiOutChannel = -1;
224  int mMidiInChannel = -1;
225 
227  AppState mState;
229  AppState mTempState;
231  AppState mActiveState;
232 
233  double mSampleRate = 44100.;
234  uint32_t mSamplesElapsed = 0;
235  uint32_t mVecWait = 0;
236  uint32_t mBufferSize = 512;
237  uint32_t mBufIndex = 0; // index for signal vector, loops from 0 to mSigVS
238  bool mExiting = false;
239  bool mAudioEnding = false;
240  bool mAudioDone = false;
241 
243  int32_t mDefaultInputDev = -1;
245  int32_t mDefaultOutputDev = -1;
246 
247  WDL_String mINIPath;
248 
249  std::vector<uint32_t> mAudioInputDevs;
250  std::vector<uint32_t> mAudioOutputDevs;
251  std::vector<std::string> mAudioIDDevNames;
252  std::vector<std::string> mMidiInputDevNames;
253  std::vector<std::string> mMidiOutputDevNames;
254 
255  WDL_PtrList<double> mInputBufPtrs;
256  WDL_PtrList<double> mOutputBufPtrs;
257 
258  friend class IPlugAPP;
259 };
260 
261 END_IPLUG_NAMESPACE
Standalone application base class for an IPlug plug-in.
std::string GetAudioDeviceName(int idx) const
Returns the name of the audio device at idx.
int GetMIDIPortNumber(ERoute direction, const char *name) const
Include to get consistently named preprocessor macros for different platforms and logging functionali...
Standalone application base class for an IPlug plug-in.
Definition: IPlugAPP.h:35
void ProbeAudioIO()
find out which devices have input channels & which have output channels, add their ids to the lists ...
IPlug Constant definitions, Types, magic numbers.
ERoute
Used to identify whether a bus/channel connection is an input or an output.
int GetAudioDeviceIdx(const char *name) const
Returns the audio device index linked to a particular name.
Used to manage changes to app i/o.
Definition: IPlugAPP_host.h:86
A class that hosts an IPlug as a standalone app and provides Audio/Midi I/O.
Definition: IPlugAPP_host.h:81