99#include < obs-frontend-api.h>
1010#include < QMainWindow>
1111#include < QAction>
12+ #include < QScreen>
13+
1214#include < util/util.hpp>
1315#include < util/platform.h>
1416#include " ASIOSettingsDialog.h"
@@ -74,21 +76,49 @@ void output_start()
7476 }
7577}
7678
79+ void callback ()
80+ {
81+ QMainWindow *mainWindow = (QMainWindow *)obs_frontend_get_main_window ();
82+ QWidget *obsSettingsDialog = nullptr ;
83+ const auto topLevels = QApplication::topLevelWidgets ();
84+ for (QWidget *widget : topLevels) {
85+ if (widget->isVisible () && QString (widget->metaObject ()->className ()).contains (" OBSBasicSettings" )) {
86+ obsSettingsDialog = widget;
87+ break ;
88+ }
89+ }
90+ if (!_settingsDialog) {
91+ if (!obsSettingsDialog)
92+ _settingsDialog = new ASIOSettingsDialog (mainWindow, context.output , context.settings );
93+ else
94+ _settingsDialog = new ASIOSettingsDialog (obsSettingsDialog, context.output , context.settings );
95+ _settingsDialog->setAttribute (Qt::WA_DeleteOnClose);
96+ QObject::connect (_settingsDialog, &QObject::destroyed, []() { _settingsDialog = nullptr ; });
97+ }
98+
99+ _settingsDialog->ShowHideDialog (context.enabled );
100+ if (obsSettingsDialog) {
101+ QRect settingsRect = obsSettingsDialog->geometry ();
102+ QRect asioRect = _settingsDialog->geometry ();
103+ QPoint newPos (settingsRect.right () + 100 , settingsRect.top ());
104+ QScreen *screen = obsSettingsDialog->screen ();
105+ QRect desktopRect = screen->availableGeometry ();
106+ if (newPos.x () + asioRect.width () > desktopRect.right ())
107+ newPos.setX (desktopRect.right () - asioRect.width ());
108+ _settingsDialog->move (newPos);
109+ }
110+ }
111+
77112void addOutputUI (void )
78113{
79114 QAction *action = (QAction *)obs_frontend_add_tools_menu_qaction (obs_module_text (" AsioOutput.Menu" ));
80-
81- QMainWindow *mainWindow = (QMainWindow *)obs_frontend_get_main_window ();
115+ action->setObjectName (" asioOutputSetupAction" );
82116
83117 obs_frontend_push_ui_translation (obs_module_get_string);
84- _settingsDialog = new ASIOSettingsDialog (mainWindow, context.output , context.settings );
85118 obs_frontend_pop_ui_translation ();
86-
87- auto cb = []() {
88- _settingsDialog->ShowHideDialog ();
89- };
90-
91- action->connect (action, &QAction::triggered, cb);
119+ // the UI is added through the callback
120+ action->connect (action, &QAction::triggered, callback);
121+ action->setVisible (false );
92122}
93123
94124static void OBSEvent (enum obs_frontend_event event, void *)
@@ -111,10 +141,15 @@ void obs_module_unload(void)
111141 if (output_running)
112142 output_stop ();
113143
114- obs_output_release (context.output );
115- context.output = nullptr ;
116- obs_data_release (context.settings );
117- context.settings = nullptr ;
144+ if (context.output ) {
145+ obs_output_release (context.output );
146+ context.output = nullptr ;
147+ }
148+
149+ if (context.settings ) {
150+ obs_data_release (context.settings );
151+ context.settings = nullptr ;
152+ }
118153 obs_frontend_remove_event_callback (OBSEvent, nullptr );
119154}
120155
@@ -124,8 +159,11 @@ void obs_module_post_load(void)
124159 return ;
125160
126161 context.settings = load_settings ();
162+
127163 obs_output_t *const output = obs_output_create (" asio_output" , " asio_output" , context.settings , NULL );
164+
128165 if (output != nullptr ) {
166+ context.enabled = true ;
129167 context.output = output;
130168 // if there is no json saved, we create a default json which uses the 1st asio device
131169 if (!context.settings ) {
@@ -136,5 +174,6 @@ void obs_module_post_load(void)
136174 obs_frontend_add_event_callback (OBSEvent, nullptr );
137175 } else {
138176 blog (LOG_INFO, " Failed to create ASIO output" );
177+ addOutputUI ();
139178 }
140179}
0 commit comments