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