2020#include < obs-frontend-api.h>
2121#include < QMainWindow>
2222#include < QAction>
23+ #include < QScreen>
24+
2325#include < util/util.hpp>
2426#include < util/platform.h>
2527#include " ASIOSettingsDialog.h"
@@ -86,21 +88,49 @@ void output_start()
8688 }
8789}
8890
91+ void callback ()
92+ {
93+ QMainWindow *mainWindow = (QMainWindow *)obs_frontend_get_main_window ();
94+ QWidget *obsSettingsDialog = nullptr ;
95+ const auto topLevels = QApplication::topLevelWidgets ();
96+ for (QWidget *widget : topLevels) {
97+ if (widget->isVisible () && QString (widget->metaObject ()->className ()).contains (" OBSBasicSettings" )) {
98+ obsSettingsDialog = widget;
99+ break ;
100+ }
101+ }
102+ if (!settingsDialog_) {
103+ if (!obsSettingsDialog)
104+ settingsDialog_ = new ASIOSettingsDialog (mainWindow, context.output , context.settings );
105+ else
106+ settingsDialog_ = new ASIOSettingsDialog (obsSettingsDialog, context.output , context.settings );
107+ settingsDialog_->setAttribute (Qt::WA_DeleteOnClose);
108+ QObject::connect (settingsDialog_, &QObject::destroyed, []() { settingsDialog_ = nullptr ; });
109+ }
110+
111+ settingsDialog_->ShowHideDialog (context.enabled );
112+ if (obsSettingsDialog) {
113+ QRect settingsRect = obsSettingsDialog->geometry ();
114+ QRect asioRect = settingsDialog_->geometry ();
115+ QPoint newPos (settingsRect.right () + 100 , settingsRect.top ());
116+ QScreen *screen = obsSettingsDialog->screen ();
117+ QRect desktopRect = screen->availableGeometry ();
118+ if (newPos.x () + asioRect.width () > desktopRect.right ())
119+ newPos.setX (desktopRect.right () - asioRect.width ());
120+ settingsDialog_->move (newPos);
121+ }
122+ }
123+
89124void addOutputUI (void )
90125{
91126 QAction *action = (QAction *)obs_frontend_add_tools_menu_qaction (obs_module_text (" AsioOutput.Menu" ));
92-
93- QMainWindow *mainWindow = (QMainWindow *)obs_frontend_get_main_window ();
127+ action->setObjectName (" asioOutputSetupAction" );
94128
95129 obs_frontend_push_ui_translation (obs_module_get_string);
96- settingsDialog_ = new ASIOSettingsDialog (mainWindow, context.output , context.settings );
97130 obs_frontend_pop_ui_translation ();
98-
99- auto cb = []() {
100- settingsDialog_->ShowHideDialog ();
101- };
102-
103- action->connect (action, &QAction::triggered, cb);
131+ // the UI is added through the callback, which is triggered in OBS Audio Settings
132+ action->connect (action, &QAction::triggered, callback);
133+ action->setVisible (false );
104134}
105135
106136static void OBSEvent (enum obs_frontend_event event, void *)
@@ -131,10 +161,15 @@ void obs_module_unload(void)
131161 if (output_running)
132162 output_stop ();
133163
134- obs_output_release (context.output );
135- context.output = nullptr ;
136- obs_data_release (context.settings );
137- context.settings = nullptr ;
164+ if (context.output ) {
165+ obs_output_release (context.output );
166+ context.output = nullptr ;
167+ }
168+
169+ if (context.settings ) {
170+ obs_data_release (context.settings );
171+ context.settings = nullptr ;
172+ }
138173 obs_frontend_remove_event_callback (OBSEvent, nullptr );
139174}
140175
@@ -144,8 +179,11 @@ void obs_module_post_load(void)
144179 return ;
145180
146181 context.settings = load_settings ();
182+
147183 obs_output_t *const output = obs_output_create (" asio_output" , " asio_output" , context.settings , NULL );
184+
148185 if (output != nullptr ) {
186+ context.enabled = true ;
149187 context.output = output;
150188
151189 if (!context.settings ) {
@@ -156,5 +194,7 @@ void obs_module_post_load(void)
156194 obs_frontend_add_event_callback (OBSEvent, nullptr );
157195 } else {
158196 blog (LOG_INFO, " Failed to create ASIO output" );
197+ // we add the UI even if there is no output to display a text saying ASIO is disabled
198+ addOutputUI ();
159199 }
160200}
0 commit comments