iPlug2 - C++ Audio Plug-in Framework
Loading...
Searching...
No Matches
IPlugAPP_dialog.cpp
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#include "IPlugAPP_host.h"
12#include "config.h"
13#include "resource.h"
14
15#ifdef OS_WIN
16#include "asio.h"
17extern float GetScaleForHWND(HWND hWnd);
18#define GET_MENU() GetMenu(gHWND)
19#elif defined OS_MAC
20#define GET_MENU() SWELL_GetCurrentMenu()
21#endif
22
23using namespace iplug;
24
25#if !defined NO_IGRAPHICS
26#include "IGraphics.h"
27using namespace igraphics;
28#endif
29
30
31// check the input and output devices, find matching srs
32void IPlugAPPHost::PopulateSampleRateList(HWND hwndDlg, RtAudio::DeviceInfo* inputDevInfo, RtAudio::DeviceInfo* outputDevInfo)
33{
34 WDL_String buf;
35
36 SendDlgItemMessage(hwndDlg,IDC_COMBO_AUDIO_SR,CB_RESETCONTENT,0,0);
37
38 std::vector<int> matchedSRs;
39
40 for (int i=0; i<inputDevInfo->sampleRates.size(); i++)
41 {
42 for (int j=0; j<outputDevInfo->sampleRates.size(); j++)
43 {
44 if (inputDevInfo->sampleRates[i] == outputDevInfo->sampleRates[j])
45 matchedSRs.push_back(inputDevInfo->sampleRates[i]);
46 }
47 }
48
49 for (int k=0; k<matchedSRs.size(); k++)
50 {
51 buf.SetFormatted(20, "%i", matchedSRs[k]);
52 SendDlgItemMessage(hwndDlg,IDC_COMBO_AUDIO_SR,CB_ADDSTRING,0,(LPARAM)buf.Get());
53 SendDlgItemMessage(hwndDlg,IDC_COMBO_AUDIO_SR,CB_SETITEMDATA,k,(LPARAM)matchedSRs[k]);
54 }
55
56 WDL_String str;
57 str.SetFormatted(32, "%i", mState.mAudioSR);
58
59 LRESULT sridx = SendDlgItemMessage(hwndDlg, IDC_COMBO_AUDIO_SR, CB_FINDSTRINGEXACT, -1, (LPARAM) str.Get());
60 SendDlgItemMessage(hwndDlg, IDC_COMBO_AUDIO_SR, CB_SETCURSEL, sridx, 0);
61}
62
63void IPlugAPPHost::PopulateAudioInputList(HWND hwndDlg, RtAudio::DeviceInfo* info)
64{
65 WDL_String buf;
66
67 SendDlgItemMessage(hwndDlg,IDC_COMBO_AUDIO_IN_L,CB_RESETCONTENT,0,0);
68 SendDlgItemMessage(hwndDlg,IDC_COMBO_AUDIO_IN_R,CB_RESETCONTENT,0,0);
69
70 int i;
71
72 for (i=0; i<info->inputChannels -1; i++)
73 {
74 buf.SetFormatted(20, "%i", i+1);
75 SendDlgItemMessage(hwndDlg,IDC_COMBO_AUDIO_IN_L,CB_ADDSTRING,0,(LPARAM)buf.Get());
76 SendDlgItemMessage(hwndDlg,IDC_COMBO_AUDIO_IN_R,CB_ADDSTRING,0,(LPARAM)buf.Get());
77 }
78
79 // TEMP
80 buf.SetFormatted(20, "%i", i+1);
81 SendDlgItemMessage(hwndDlg,IDC_COMBO_AUDIO_IN_R,CB_ADDSTRING,0,(LPARAM)buf.Get());
82
83 SendDlgItemMessage(hwndDlg,IDC_COMBO_AUDIO_IN_L,CB_SETCURSEL, mState.mAudioInChanL - 1, 0);
84 SendDlgItemMessage(hwndDlg,IDC_COMBO_AUDIO_IN_R,CB_SETCURSEL, mState.mAudioInChanR - 1, 0);
85}
86
87void IPlugAPPHost::PopulateAudioOutputList(HWND hwndDlg, RtAudio::DeviceInfo* info)
88{
89 WDL_String buf;
90
91 SendDlgItemMessage(hwndDlg,IDC_COMBO_AUDIO_OUT_L,CB_RESETCONTENT,0,0);
92 SendDlgItemMessage(hwndDlg,IDC_COMBO_AUDIO_OUT_R,CB_RESETCONTENT,0,0);
93
94 int i;
95
96 for (i=0; i<info->outputChannels -1; i++)
97 {
98 buf.SetFormatted(20, "%i", i+1);
99 SendDlgItemMessage(hwndDlg,IDC_COMBO_AUDIO_OUT_L,CB_ADDSTRING,0,(LPARAM)buf.Get());
100 SendDlgItemMessage(hwndDlg,IDC_COMBO_AUDIO_OUT_R,CB_ADDSTRING,0,(LPARAM)buf.Get());
101 }
102
103 // TEMP
104 buf.SetFormatted(20, "%i", i+1);
105 SendDlgItemMessage(hwndDlg,IDC_COMBO_AUDIO_OUT_R,CB_ADDSTRING,0,(LPARAM)buf.Get());
106
107 SendDlgItemMessage(hwndDlg,IDC_COMBO_AUDIO_OUT_L,CB_SETCURSEL, mState.mAudioOutChanL - 1, 0);
108 SendDlgItemMessage(hwndDlg,IDC_COMBO_AUDIO_OUT_R,CB_SETCURSEL, mState.mAudioOutChanR - 1, 0);
109}
110
111// This has to get called after any change to audio driver/in dev/out dev
112void IPlugAPPHost::PopulateDriverSpecificControls(HWND hwndDlg)
113{
114#ifdef OS_WIN
115 int driverType = (int) SendDlgItemMessage(hwndDlg, IDC_COMBO_AUDIO_DRIVER, CB_GETCURSEL, 0, 0);
116 if (driverType == kDeviceASIO)
117 {
118 ComboBox_Enable(GetDlgItem(hwndDlg, IDC_COMBO_AUDIO_IN_DEV), FALSE);
119 Button_Enable(GetDlgItem(hwndDlg, IDC_BUTTON_OS_DEV_SETTINGS), TRUE);
120 }
121 else
122 {
123 ComboBox_Enable(GetDlgItem(hwndDlg, IDC_COMBO_AUDIO_IN_DEV), TRUE);
124 Button_Enable(GetDlgItem(hwndDlg, IDC_BUTTON_OS_DEV_SETTINGS), FALSE);
125 }
126#endif
127
128 int indevidx = 0;
129 int outdevidx = 0;
130
131 SendDlgItemMessage(hwndDlg,IDC_COMBO_AUDIO_IN_DEV,CB_RESETCONTENT,0,0);
132 SendDlgItemMessage(hwndDlg,IDC_COMBO_AUDIO_OUT_DEV,CB_RESETCONTENT,0,0);
133
134 for (int i = 0; i<mAudioInputDevIDs.size(); i++)
135 {
136 SendDlgItemMessage(hwndDlg,IDC_COMBO_AUDIO_IN_DEV,CB_ADDSTRING,0,(LPARAM)GetAudioDeviceName(mAudioInputDevIDs[i]).c_str());
137
138 if (std::string_view(GetAudioDeviceName(mAudioInputDevIDs[i])) == mState.mAudioInDev.Get())
139 indevidx = i;
140 }
141
142 for (int i = 0; i<mAudioOutputDevIDs.size(); i++)
143 {
144 SendDlgItemMessage(hwndDlg,IDC_COMBO_AUDIO_OUT_DEV,CB_ADDSTRING,0,(LPARAM)GetAudioDeviceName(mAudioOutputDevIDs[i]).c_str());
145
146 if (std::string_view(GetAudioDeviceName(mAudioOutputDevIDs[i])) == mState.mAudioOutDev.Get())
147 outdevidx = i;
148 }
149
150#ifdef OS_WIN
151 if (driverType == kDeviceASIO)
152 SendDlgItemMessage(hwndDlg,IDC_COMBO_AUDIO_IN_DEV,CB_SETCURSEL, outdevidx, 0);
153 else
154#endif
155 SendDlgItemMessage(hwndDlg,IDC_COMBO_AUDIO_IN_DEV,CB_SETCURSEL, indevidx, 0);
156
157 SendDlgItemMessage(hwndDlg,IDC_COMBO_AUDIO_OUT_DEV,CB_SETCURSEL, outdevidx, 0);
158
159 RtAudio::DeviceInfo inputDevInfo;
160 RtAudio::DeviceInfo outputDevInfo;
161
162 if (mAudioInputDevIDs.size())
163 {
164 inputDevInfo = mDAC->getDeviceInfo(mAudioInputDevIDs[indevidx]);
165 PopulateAudioInputList(hwndDlg, &inputDevInfo);
166 }
167
168 if (mAudioOutputDevIDs.size())
169 {
170 outputDevInfo = mDAC->getDeviceInfo(mAudioOutputDevIDs[outdevidx]);
171 PopulateAudioOutputList(hwndDlg, &outputDevInfo);
172 }
173
174 PopulateSampleRateList(hwndDlg, &inputDevInfo, &outputDevInfo);
175}
176
177void IPlugAPPHost::PopulateAudioDialogs(HWND hwndDlg)
178{
179 PopulateDriverSpecificControls(hwndDlg);
180
181// if (mState.mAudioInIsMono)
182// {
183// SendDlgItemMessage(hwndDlg,IDC_CB_MONO_INPUT,BM_SETCHECK, BST_CHECKED,0);
184// }
185// else
186// {
187// SendDlgItemMessage(hwndDlg,IDC_CB_MONO_INPUT,BM_SETCHECK, BST_UNCHECKED,0);
188// }
189
190// Populate buffer size combobox
191 for (int i = 0; i< kNumBufferSizeOptions; i++)
192 {
193 SendDlgItemMessage(hwndDlg,IDC_COMBO_AUDIO_BUF_SIZE,CB_ADDSTRING,0,(LPARAM)kBufferSizeOptions[i].c_str());
194 }
195
196 WDL_String str;
197 str.SetFormatted(32, "%i", mState.mBufferSize);
198
199 LRESULT iovsidx = SendDlgItemMessage(hwndDlg, IDC_COMBO_AUDIO_BUF_SIZE, CB_FINDSTRINGEXACT, -1, (LPARAM) str.Get());
200 SendDlgItemMessage(hwndDlg, IDC_COMBO_AUDIO_BUF_SIZE, CB_SETCURSEL, iovsidx, 0);
201}
202
203bool IPlugAPPHost::PopulateMidiDialogs(HWND hwndDlg)
204{
205 if ( !mMidiIn || !mMidiOut )
206 return false;
207 else
208 {
209 for (int i=0; i<mMidiInputDevNames.size(); i++)
210 {
211 SendDlgItemMessage(hwndDlg,IDC_COMBO_MIDI_IN_DEV,CB_ADDSTRING,0,(LPARAM)mMidiInputDevNames[i].c_str());
212 }
213
214 LRESULT indevidx = SendDlgItemMessage(hwndDlg,IDC_COMBO_MIDI_IN_DEV,CB_FINDSTRINGEXACT, -1, (LPARAM)mState.mMidiInDev.Get());
215
216 // if the midi port name wasn't found update the ini file, and set to off
217 if (indevidx == -1)
218 {
219 mState.mMidiInDev.Set("off");
220 UpdateINI();
221 indevidx = 0;
222 }
223
224 SendDlgItemMessage(hwndDlg,IDC_COMBO_MIDI_IN_DEV,CB_SETCURSEL, indevidx, 0);
225
226 for (int i=0; i<mMidiOutputDevNames.size(); i++)
227 {
228 SendDlgItemMessage(hwndDlg,IDC_COMBO_MIDI_OUT_DEV,CB_ADDSTRING,0,(LPARAM)mMidiOutputDevNames[i].c_str());
229 }
230
231 LRESULT outdevidx = SendDlgItemMessage(hwndDlg,IDC_COMBO_MIDI_OUT_DEV,CB_FINDSTRINGEXACT, -1, (LPARAM)mState.mMidiOutDev.Get());
232
233 // if the midi port name wasn't found update the ini file, and set to off
234 if (outdevidx == -1)
235 {
236 mState.mMidiOutDev.Set("off");
237 UpdateINI();
238 outdevidx = 0;
239 }
240
241 SendDlgItemMessage(hwndDlg,IDC_COMBO_MIDI_OUT_DEV,CB_SETCURSEL, outdevidx, 0);
242
243 // Populate MIDI channel dialogs
244
245 SendDlgItemMessage(hwndDlg,IDC_COMBO_MIDI_IN_CHAN,CB_ADDSTRING,0,(LPARAM)"all");
246 SendDlgItemMessage(hwndDlg,IDC_COMBO_MIDI_OUT_CHAN,CB_ADDSTRING,0,(LPARAM)"all");
247
248 WDL_String buf;
249
250 for (int i=0; i<16; i++)
251 {
252 buf.SetFormatted(20, "%i", i+1);
253 SendDlgItemMessage(hwndDlg,IDC_COMBO_MIDI_IN_CHAN,CB_ADDSTRING,0,(LPARAM)buf.Get());
254 SendDlgItemMessage(hwndDlg,IDC_COMBO_MIDI_OUT_CHAN,CB_ADDSTRING,0,(LPARAM)buf.Get());
255 }
256
257 SendDlgItemMessage(hwndDlg,IDC_COMBO_MIDI_IN_CHAN,CB_SETCURSEL, (LPARAM)mState.mMidiInChan, 0);
258 SendDlgItemMessage(hwndDlg,IDC_COMBO_MIDI_OUT_CHAN,CB_SETCURSEL, (LPARAM)mState.mMidiOutChan, 0);
259
260 return true;
261 }
262}
263
264#ifdef OS_WIN
265void IPlugAPPHost::PopulatePreferencesDialog(HWND hwndDlg)
266{
267 SendDlgItemMessage(hwndDlg,IDC_COMBO_AUDIO_DRIVER,CB_ADDSTRING,0,(LPARAM)"DirectSound");
268 SendDlgItemMessage(hwndDlg,IDC_COMBO_AUDIO_DRIVER,CB_ADDSTRING,0,(LPARAM)"ASIO");
269 SendDlgItemMessage(hwndDlg,IDC_COMBO_AUDIO_DRIVER,CB_SETCURSEL, mState.mAudioDriverType, 0);
270
271 PopulateAudioDialogs(hwndDlg);
272 PopulateMidiDialogs(hwndDlg);
273}
274
275#elif defined OS_MAC
276void IPlugAPPHost::PopulatePreferencesDialog(HWND hwndDlg)
277{
278 SendDlgItemMessage(hwndDlg,IDC_COMBO_AUDIO_DRIVER,CB_ADDSTRING,0,(LPARAM)"CoreAudio");
279 //SendDlgItemMessage(hwndDlg,IDC_COMBO_AUDIO_DRIVER,CB_ADDSTRING,0,(LPARAM)"Jack");
280 SendDlgItemMessage(hwndDlg,IDC_COMBO_AUDIO_DRIVER,CB_SETCURSEL, mState.mAudioDriverType, 0);
281
282 PopulateAudioDialogs(hwndDlg);
283 PopulateMidiDialogs(hwndDlg);
284}
285#else
286 #error NOT IMPLEMENTED
287#endif
288
289WDL_DLGRET IPlugAPPHost::PreferencesDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
290{
291 IPlugAPPHost* _this = sInstance.get();
292 AppState& mState = _this->mState;
293 AppState& mTempState = _this->mTempState;
294 AppState& mActiveState = _this->mActiveState;
295
296 auto getComboString = [&](WDL_String& str, int item, WPARAM idx) {
297 std::string tempString;
298 long len = (long) SendDlgItemMessage(hwndDlg, item, CB_GETLBTEXTLEN, idx, 0) + 1;
299 tempString.reserve(len);
300 SendDlgItemMessage(hwndDlg, item, CB_GETLBTEXT, idx, (LPARAM) tempString.data());
301 str.Set(tempString.c_str());
302 };
303
304 int v = 0;
305 switch(uMsg)
306 {
307 case WM_INITDIALOG:
308 _this->PopulatePreferencesDialog(hwndDlg);
309 mTempState = mState;
310
311 return TRUE;
312
313 case WM_COMMAND:
314 switch (LOWORD(wParam))
315 {
316 case IDOK:
317 if (mActiveState != mState)
318 _this->TryToChangeAudio();
319
320 EndDialog(hwndDlg, IDOK); // INI file will be changed see MainDialogProc
321 break;
322 case IDAPPLY:
323 _this->TryToChangeAudio();
324 break;
325 case IDCANCEL:
326 EndDialog(hwndDlg, IDCANCEL);
327
328 // if state has been changed reset to previous state, INI file won't be changed
329 if (!_this->AudioSettingsInStateAreEqual(mState, mTempState)
330 || !_this->MIDISettingsInStateAreEqual(mState, mTempState))
331 {
332 mState = mTempState;
333
334 _this->TryToChangeAudioDriverType();
335 _this->ProbeAudioIO();
336 _this->TryToChangeAudio();
337 }
338
339 break;
340
341 case IDC_COMBO_AUDIO_DRIVER:
342 if (HIWORD(wParam) == CBN_SELCHANGE)
343 {
344 v = (int) SendDlgItemMessage(hwndDlg, IDC_COMBO_AUDIO_DRIVER, CB_GETCURSEL, 0, 0);
345
346 if (v != mState.mAudioDriverType)
347 {
348 mState.mAudioDriverType = v;
349
350 _this->TryToChangeAudioDriverType();
351 _this->ProbeAudioIO();
352
353 if (_this->mAudioInputDevIDs.size())
354 mState.mAudioInDev.Set(_this->GetAudioDeviceName(_this->mAudioInputDevIDs[0]).c_str());
355
356 if (_this->mAudioOutputDevIDs.size())
357 mState.mAudioOutDev.Set(_this->GetAudioDeviceName(_this->mAudioOutputDevIDs[0]).c_str());
358
359 // Reset IO
360 mState.mAudioOutChanL = 1;
361 mState.mAudioOutChanR = 2;
362
363 _this->PopulateAudioDialogs(hwndDlg);
364 }
365 }
366 break;
367
368 case IDC_COMBO_AUDIO_IN_DEV:
369 if (HIWORD(wParam) == CBN_SELCHANGE)
370 {
371 int idx = (int) SendDlgItemMessage(hwndDlg, IDC_COMBO_AUDIO_IN_DEV, CB_GETCURSEL, 0, 0);
372 getComboString(mState.mAudioInDev, IDC_COMBO_AUDIO_IN_DEV, idx);
373
374 // Reset IO
375 mState.mAudioInChanL = 1;
376 mState.mAudioInChanR = 2;
377
378 _this->PopulateDriverSpecificControls(hwndDlg);
379 }
380 break;
381
382 case IDC_COMBO_AUDIO_OUT_DEV:
383 if (HIWORD(wParam) == CBN_SELCHANGE)
384 {
385 int idx = (int) SendDlgItemMessage(hwndDlg, IDC_COMBO_AUDIO_OUT_DEV, CB_GETCURSEL, 0, 0);
386 getComboString(mState.mAudioOutDev, IDC_COMBO_AUDIO_OUT_DEV, idx);
387
388 // Reset IO
389 mState.mAudioOutChanL = 1;
390 mState.mAudioOutChanR = 2;
391
392 _this->PopulateDriverSpecificControls(hwndDlg);
393 }
394 break;
395
396 case IDC_COMBO_AUDIO_IN_L:
397 if (HIWORD(wParam) == CBN_SELCHANGE)
398 {
399 mState.mAudioInChanL = (int) SendDlgItemMessage(hwndDlg, IDC_COMBO_AUDIO_IN_L, CB_GETCURSEL, 0, 0) + 1;
400
401 //TEMP
402 mState.mAudioInChanR = mState.mAudioInChanL + 1;
403 SendDlgItemMessage(hwndDlg,IDC_COMBO_AUDIO_IN_R,CB_SETCURSEL, mState.mAudioInChanR - 1, 0);
404 //
405 }
406 break;
407
408 case IDC_COMBO_AUDIO_IN_R:
409 if (HIWORD(wParam) == CBN_SELCHANGE)
410 SendDlgItemMessage(hwndDlg,IDC_COMBO_AUDIO_IN_R,CB_SETCURSEL, mState.mAudioInChanR - 1, 0); // TEMP
411 mState.mAudioInChanR = (int) SendDlgItemMessage(hwndDlg, IDC_COMBO_AUDIO_IN_R, CB_GETCURSEL, 0, 0);
412 break;
413
414 case IDC_COMBO_AUDIO_OUT_L:
415 if (HIWORD(wParam) == CBN_SELCHANGE)
416 {
417 mState.mAudioOutChanL = (int) SendDlgItemMessage(hwndDlg, IDC_COMBO_AUDIO_OUT_L, CB_GETCURSEL, 0, 0) + 1;
418
419 //TEMP
420 mState.mAudioOutChanR = mState.mAudioOutChanL + 1;
421 SendDlgItemMessage(hwndDlg,IDC_COMBO_AUDIO_OUT_R,CB_SETCURSEL, mState.mAudioOutChanR - 1, 0);
422 //
423 }
424 break;
425
426 case IDC_COMBO_AUDIO_OUT_R:
427 if (HIWORD(wParam) == CBN_SELCHANGE)
428 SendDlgItemMessage(hwndDlg,IDC_COMBO_AUDIO_OUT_R,CB_SETCURSEL, mState.mAudioOutChanR - 1, 0); // TEMP
429 mState.mAudioOutChanR = (int) SendDlgItemMessage(hwndDlg, IDC_COMBO_AUDIO_OUT_R, CB_GETCURSEL, 0, 0);
430 break;
431
432// case IDC_CB_MONO_INPUT:
433// if (SendDlgItemMessage(hwndDlg,IDC_CB_MONO_INPUT, BM_GETCHECK, 0, 0) == BST_CHECKED)
434// mState.mAudioInIsMono = 1;
435// else
436// mState.mAudioInIsMono = 0;
437// break;
438
439 case IDC_COMBO_AUDIO_BUF_SIZE: // follow through
440 if (HIWORD(wParam) == CBN_SELCHANGE)
441 {
442 int iovsidx = (int) SendDlgItemMessage(hwndDlg, IDC_COMBO_AUDIO_BUF_SIZE, CB_GETCURSEL, 0, 0);
443 mState.mBufferSize = atoi(kBufferSizeOptions[iovsidx].c_str());
444 }
445 break;
446 case IDC_COMBO_AUDIO_SR:
447 if (HIWORD(wParam) == CBN_SELCHANGE)
448 {
449 int idx = (int) SendDlgItemMessage(hwndDlg, IDC_COMBO_AUDIO_SR, CB_GETCURSEL, 0, 0);
450 mState.mAudioSR = (uint32_t) SendDlgItemMessage(hwndDlg, IDC_COMBO_AUDIO_SR, CB_GETITEMDATA, idx, 0);
451 }
452 break;
453
454 case IDC_BUTTON_OS_DEV_SETTINGS:
455 if (HIWORD(wParam) == BN_CLICKED)
456 {
457 #ifdef OS_WIN
458 if ( (_this->mState.mAudioDriverType == kDeviceASIO) && (_this->mDAC->isStreamRunning() == true)) // TODO: still not right
459 ASIOControlPanel();
460 #elif defined OS_MAC
461 if (SWELL_GetOSXVersion() >= 0x1200)
462 {
463 system("open \"/System/Applications/Utilities/Audio MIDI Setup.app\"");
464 }
465 else
466 {
467 system("open \"/Applications/Utilities/Audio MIDI Setup.app\"");
468 }
469 #else
470 #error NOT IMPLEMENTED
471 #endif
472 }
473 break;
474
475 case IDC_COMBO_MIDI_IN_DEV:
476 if (HIWORD(wParam) == CBN_SELCHANGE)
477 {
478 int idx = (int) SendDlgItemMessage(hwndDlg, IDC_COMBO_MIDI_IN_DEV, CB_GETCURSEL, 0, 0);
479 getComboString(mState.mMidiInDev, IDC_COMBO_MIDI_IN_DEV, idx);
480 _this->SelectMIDIDevice(ERoute::kInput, mState.mMidiInDev.Get());
481 }
482 break;
483
484 case IDC_COMBO_MIDI_OUT_DEV:
485 if (HIWORD(wParam) == CBN_SELCHANGE)
486 {
487 int idx = (int) SendDlgItemMessage(hwndDlg, IDC_COMBO_MIDI_OUT_DEV, CB_GETCURSEL, 0, 0);
488 getComboString(mState.mMidiOutDev, IDC_COMBO_MIDI_OUT_DEV, idx);
489 _this->SelectMIDIDevice(ERoute::kOutput, mState.mMidiOutDev.Get());
490 }
491 break;
492
493 case IDC_COMBO_MIDI_IN_CHAN:
494 if (HIWORD(wParam) == CBN_SELCHANGE)
495 mState.mMidiInChan = (int) SendDlgItemMessage(hwndDlg, IDC_COMBO_MIDI_IN_CHAN, CB_GETCURSEL, 0, 0);
496 break;
497
498 case IDC_COMBO_MIDI_OUT_CHAN:
499 if (HIWORD(wParam) == CBN_SELCHANGE)
500 mState.mMidiOutChan = (int) SendDlgItemMessage(hwndDlg, IDC_COMBO_MIDI_OUT_CHAN, CB_GETCURSEL, 0, 0);
501 break;
502
503 default:
504 break;
505 }
506 break;
507 default:
508 return FALSE;
509 }
510 return TRUE;
511}
512
513static void ClientResize(HWND hWnd, int width, int height)
514{
515 RECT rcClient, rcWindow;
516 POINT ptDiff;
517 int screenwidth, screenheight;
518 int x, y;
519
520 screenwidth = GetSystemMetrics(SM_CXSCREEN);
521 screenheight = GetSystemMetrics(SM_CYSCREEN);
522 x = (screenwidth / 2) - (width / 2);
523 y = (screenheight / 2) - (height / 2);
524
525 GetClientRect(hWnd, &rcClient);
526 GetWindowRect(hWnd, &rcWindow);
527
528 ptDiff.x = (rcWindow.right - rcWindow.left) - rcClient.right;
529 ptDiff.y = (rcWindow.bottom - rcWindow.top) - rcClient.bottom;
530
531 SetWindowPos(hWnd, 0, x, y, width + ptDiff.x, height + ptDiff.y, 0);
532}
533
534//static
535WDL_DLGRET IPlugAPPHost::MainDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
536{
537 IPlugAPPHost* pAppHost = IPlugAPPHost::sInstance.get();
538
539 switch (uMsg)
540 {
541 case WM_INITDIALOG:
542 {
543 gHWND = hwndDlg;
544 IPlugAPP* pPlug = pAppHost->GetPlug();
545
546 if (!pAppHost->OpenWindow(gHWND))
547 {
548 DBGMSG("couldn't attach gui\n");
549 }
550
551 ClientResize(hwndDlg, pPlug->GetEditorWidth(), pPlug->GetEditorHeight());
552
553 ShowWindow(hwndDlg, SW_SHOW);
554 return 1;
555 }
556 case WM_DESTROY:
557 pAppHost->CloseWindow();
558 gHWND = NULL;
559 IPlugAPPHost::sInstance = nullptr;
560
561 #ifdef OS_WIN
562 PostQuitMessage(0);
563 #else
564 SWELL_PostQuitMessage(hwndDlg);
565 #endif
566
567 return 0;
568 case WM_CLOSE:
569 DestroyWindow(hwndDlg);
570 return 0;
571 case WM_COMMAND:
572 switch (LOWORD(wParam))
573 {
574 case ID_QUIT:
575 {
576 DestroyWindow(hwndDlg);
577 return 0;
578 }
579 case ID_ABOUT:
580 {
581 IPlugAPP* pPlug = pAppHost->GetPlug();
582
583 bool pluginOpensAboutBox = pPlug->OnHostRequestingAboutBox();
584
585 if (pluginOpensAboutBox == false)
586 {
587 WDL_String info;
588 info.Append(PLUG_COPYRIGHT_STR"\nBuilt on " __DATE__);
589 MessageBox(hwndDlg, info.Get(), PLUG_NAME, MB_OK);
590 }
591
592 return 0;
593 }
594 case ID_HELP:
595 {
596 IPlugAPP* pPlug = pAppHost->GetPlug();
597
598 bool pluginOpensHelp = pPlug->OnHostRequestingProductHelp();
599
600 if (pluginOpensHelp == false)
601 {
602 MessageBox(hwndDlg, "See the manual", PLUG_NAME, MB_OK);
603 }
604 return 0;
605 }
606 case ID_PREFERENCES:
607 {
608 INT_PTR ret = DialogBox(gHINSTANCE, MAKEINTRESOURCE(IDD_DIALOG_PREF), hwndDlg, IPlugAPPHost::PreferencesDlgProc);
609
610 if (ret == IDOK)
611 pAppHost->UpdateINI();
612
613 return 0;
614 }
615#if defined _DEBUG && !defined NO_IGRAPHICS
616 case ID_LIVE_EDIT:
617 {
618 IGEditorDelegate* pPlug = dynamic_cast<IGEditorDelegate*>(pAppHost->GetPlug());
619
620 if (pPlug)
621 {
622 IGraphics* pGraphics = pPlug->GetUI();
623
624 if (pGraphics)
625 {
626 bool enabled = pGraphics->LiveEditEnabled();
627 pGraphics->EnableLiveEdit(!enabled);
628 CheckMenuItem(GET_MENU(), ID_LIVE_EDIT, (MF_BYCOMMAND | enabled) ? MF_UNCHECKED : MF_CHECKED);
629 }
630 }
631
632 return 0;
633 }
634 case ID_SHOW_DRAWN:
635 {
636 IGEditorDelegate* pPlug = dynamic_cast<IGEditorDelegate*>(pAppHost->GetPlug());
637
638 if (pPlug)
639 {
640 IGraphics* pGraphics = pPlug->GetUI();
641
642 if (pGraphics)
643 {
644 bool enabled = pGraphics->ShowAreaDrawnEnabled();
645 pGraphics->ShowAreaDrawn(!enabled);
646 CheckMenuItem(GET_MENU(), ID_SHOW_DRAWN, (MF_BYCOMMAND | enabled) ? MF_UNCHECKED : MF_CHECKED);
647 }
648 }
649
650 return 0;
651 }
652 case ID_SHOW_BOUNDS:
653 {
654 IGEditorDelegate* pPlug = dynamic_cast<IGEditorDelegate*>(pAppHost->GetPlug());
655
656 if (pPlug)
657 {
658 IGraphics* pGraphics = pPlug->GetUI();
659
660 if (pGraphics)
661 {
662 bool enabled = pGraphics->ShowControlBoundsEnabled();
663 pGraphics->ShowControlBounds(!enabled);
664 CheckMenuItem(GET_MENU(), ID_SHOW_BOUNDS, (MF_BYCOMMAND | enabled) ? MF_UNCHECKED : MF_CHECKED);
665 }
666 }
667
668 return 0;
669 }
670 case ID_SHOW_FPS:
671 {
672 IGEditorDelegate* pPlug = dynamic_cast<IGEditorDelegate*>(pAppHost->GetPlug());
673
674 if (pPlug)
675 {
676 IGraphics* pGraphics = pPlug->GetUI();
677
678 if (pGraphics)
679 {
680 bool enabled = pGraphics->ShowingFPSDisplay();
681 pGraphics->ShowFPSDisplay(!enabled);
682 CheckMenuItem(GET_MENU(), ID_SHOW_FPS, (MF_BYCOMMAND | enabled) ? MF_UNCHECKED : MF_CHECKED);
683 }
684 }
685
686 return 0;
687 }
688#endif
689 }
690 return 0;
691 case WM_GETMINMAXINFO:
692 {
693 if (!pAppHost)
694 return 1;
695
696 IPlugAPP* pPlug = pAppHost->GetPlug();
697
698 MINMAXINFO* mmi = (MINMAXINFO*) lParam;
699 mmi->ptMinTrackSize.x = pPlug->GetMinWidth();
700 mmi->ptMinTrackSize.y = pPlug->GetMinHeight();
701 mmi->ptMaxTrackSize.x = pPlug->GetMaxWidth();
702 mmi->ptMaxTrackSize.y = pPlug->GetMaxHeight();
703
704#ifdef OS_WIN
705 float scale = GetScaleForHWND(hwndDlg);
706 mmi->ptMinTrackSize.x = static_cast<LONG>(static_cast<float>(mmi->ptMinTrackSize.x) * scale);
707 mmi->ptMinTrackSize.y = static_cast<LONG>(static_cast<float>(mmi->ptMinTrackSize.y) * scale);
708 mmi->ptMaxTrackSize.x = static_cast<LONG>(static_cast<float>(mmi->ptMaxTrackSize.x) * scale);
709 mmi->ptMaxTrackSize.y = static_cast<LONG>(static_cast<float>(mmi->ptMaxTrackSize.y) * scale);
710#endif
711
712 return 0;
713 }
714#ifdef OS_WIN
715 case WM_DPICHANGED:
716 {
717 WORD dpi = HIWORD(wParam);
718 RECT* rect = (RECT*)lParam;
719 float scale = GetScaleForHWND(hwndDlg);
720
721 POINT ptDiff;
722 RECT rcClient;
723 RECT rcWindow;
724
725 GetClientRect(hwndDlg, &rcClient);
726 GetWindowRect(hwndDlg, &rcWindow);
727
728 ptDiff.x = (rcWindow.right - rcWindow.left) - rcClient.right;
729 ptDiff.y = (rcWindow.bottom - rcWindow.top) - rcClient.bottom;
730
731#ifndef NO_IGRAPHICS
732 IGEditorDelegate* pPlug = dynamic_cast<IGEditorDelegate*>(pAppHost->GetPlug());
733
734 if (pPlug)
735 {
736 IGraphics* pGraphics = pPlug->GetUI();
737
738 if (pGraphics)
739 {
740 pGraphics->SetScreenScale(scale);
741 }
742 }
743#else
744 IEditorDelegate* pPlug = dynamic_cast<IEditorDelegate*>(pAppHost->GetPlug());
745#endif
746
747 int w = pPlug->GetEditorWidth();
748 int h = pPlug->GetEditorHeight();
749
750 SetWindowPos(hwndDlg, 0, rect->left, rect->top, w + ptDiff.x, h + ptDiff.y, 0);
751
752 return 0;
753 }
754#endif
755 case WM_SIZE:
756 {
757 IPlugAPP* pPlug = pAppHost->GetPlug();
758
759 switch (LOWORD(wParam))
760 {
761 case SIZE_RESTORED:
762 case SIZE_MAXIMIZED:
763 {
764 if (pPlug->GetHostResizeEnabled())
765 {
766 RECT r;
767 GetClientRect(hwndDlg, &r);
768 pPlug->OnParentWindowResize(static_cast<int>(r.right), static_cast<int>(r.bottom));
769 }
770 return 1;
771 }
772 default:
773 return 0;
774 }
775 }
776 }
777 return 0;
778}
This pure virtual interface delegates communication in both directions between a UI editor and someth...
int GetEditorHeight() const
int GetEditorWidth() const
An editor delegate base class that uses IGraphics for the UI.
IGraphics * GetUI()
Get a pointer to the IGraphics context.
The lowest level base class of an IGraphics context.
Definition: IGraphics.h:86
void ShowControlBounds(bool enable)
Definition: IGraphics.h:1190
void EnableLiveEdit(bool enable)
Live edit mode allows you to relocate controls at runtime in debug builds.
Definition: IGraphics.cpp:1549
bool ShowAreaDrawnEnabled() const
Definition: IGraphics.h:1196
bool LiveEditEnabled() const
Definition: IGraphics.h:1206
bool ShowControlBoundsEnabled() const
Definition: IGraphics.h:1199
void ShowFPSDisplay(bool enable)
Shows a control to display the frame rate of drawing.
Definition: IGraphics.cpp:437
bool ShowingFPSDisplay()
Definition: IGraphics.h:1363
void ShowAreaDrawn(bool enable)
Definition: IGraphics.h:1193
void SetScreenScale(float scale)
Called by the platform IGraphics class when moving to a new screen to set DPI.
Definition: IGraphics.cpp:75
A class that hosts an IPlug as a standalone app and provides Audio/Midi I/O.
Definition: IPlugAPP_host.h:83
std::string GetAudioDeviceName(uint32_t deviceID) const
Returns the name of the audio device with a given RTAudio device ID.
Standalone application base class for an IPlug plug-in.
Definition: IPlugAPP.h:37
bool GetHostResizeEnabled() const