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