ACMX 2.136.0
Dual-Backend Real-Time GPU Video Synthesis
Loading...
Searching...
No Matches
ACMX2/interface/main_window.hpp
Go to the documentation of this file.
1// #define BUILD_BUNDLE
2// uncomment above if building BUNDLE
3
4#ifndef __APP_WINDOW_H_
5#define __APP_WINDOW_H_
6
7/**
8 * @file main_window.hpp
9 * @brief Main launcher window for ACMX2/ACMXVK shader selection and execution.
10 */
12#include "backend.hpp"
13#include "editor.hpp"
14#include "gpufilter.hpp"
15#include "midi-settings.hpp"
16#include "playlist.hpp"
17#include "prop.hpp"
18#include "shader.hpp"
19#include "shaderlibrary.hpp"
20#include "shaderpass.hpp"
21#include "version_info.hpp" //defines VERSION_INFO
22#include <QActionGroup>
23#include <QDateTime>
24#include <QFile>
25#include <QHash>
26#include <QMainWindow>
27#include <QMenuBar>
28#include <QPointer>
29#include <QProcess>
30#include <QSettings>
31#include <QTextEdit>
32#include <QTreeWidget>
33#include <random>
34
38class QDialog;
39class QTabWidget;
41
42/**
43 * @brief Primary ACMX desktop UI.
44 *
45 * Manages shader discovery, process launch arguments, and related option dialogs.
46 */
47class MainWindow : public QMainWindow {
48 Q_OBJECT
49 public:
50 MainWindow(QWidget *parent = 0) : QMainWindow(parent) {
52 }
53 /// @brief Build menus, actions, widgets, and signal wiring.
54 void initControls();
55 /// @brief Append timestamped text to the UI log output.
56 /// @param message Text to append to the launcher log.
57 void Log(const QString &message);
58 /// @brief Write raw text to the lower output pane.
59 /// @param message Text block to display.
60 void Write(const QString &message);
61 /// @brief Load shader names from index/cache for the provided path.
62 /// @param path Shader directory path to scan.
63 /// @param force When true, bypass index timestamp checks and reload.
64 /// @return true if shader list was loaded successfully.
65 bool loadShaders(const QString &path, bool force = false);
66 /// @brief Refresh shader index metadata timestamp.
67 void updateIndex();
68 QDateTime indexTimestamp;
70 public slots:
71 void fileOpenProp();
72 void menuLoadLibrary();
73 void fileExit();
74 void runSelected();
75 void runAll();
76 void copyCommand();
77 void cameraSettings();
78 /// @brief Handle shader list selection changes.
79 /// @param i Selected model index.
80 void listClicked(const QModelIndex &i);
81 void newList();
82 void newShader();
83 void menuUp();
84 void menuDown();
85 void menuRemove();
87 void menuAudioSettings();
88 void menuSort();
89 void menuShuffle();
90 void menuSearch();
91 void menuFindNext();
96 void menuLibraryBuilder();
98 void menuFixBuild();
99 void menuRunFromCache();
101 void menuRemoveBroken();
102 void menuMidiSettings();
103 void menuMetadataViewer();
105 void menuCustomUniforms();
107 void menuToggleDisplayFilter(bool checked);
109
110 protected:
111 /// @brief Add shader to list if it is valid and not already present.
112 /// @param shaderName Candidate shader identifier.
113 /// @return true if the shader was added.
114 bool addShaderToList(const QString &shaderName);
115
116 void closeEvent(QCloseEvent *event) override {
117 if (process->state() == QProcess::Running) {
118 process->terminate();
119 if (!process->waitForFinished(10000)) {
120 process->kill();
121 }
122 }
123 if (hdr10Process && hdr10Process->state() == QProcess::Running) {
124 hdr10Process->terminate();
125 if (!hdr10Process->waitForFinished(10000)) {
126 hdr10Process->kill();
127 }
128 }
130 liveShaderCompileProcess->state() == QProcess::Running) {
131 liveShaderCompileProcess->terminate();
132 if (!liveShaderCompileProcess->waitForFinished(5000)) {
134 }
135 }
137 editorPreviewProcess->state() == QProcess::Running) {
138 editorPreviewProcess->kill();
139 editorPreviewProcess->waitForFinished(2000);
140 }
141 for (const QString &path : editorPreviewTemporaryFiles)
142 QFile::remove(path);
144 QMainWindow::closeEvent(event);
145 }
146
147 private:
148 QTreeWidget *list_view;
149 QStringList items;
150 QTextEdit *bottomTextBox;
151 /// @brief Repopulate the shader tree widget from the current `items` list,
152 /// recomputing Last Modified, Compile Health, and Type columns.
153 void populateShaderTree();
154 /// @brief Compile-health status for a single shader.
155 enum class CompileHealth { Unknown,
156 Cached,
157 Failed,
158 Stale };
159 /// @brief Cached map of shader stem -> failed flag for the current library.
160 QHash<QString, bool> shaderCacheStatus;
161 /// @brief Modification time of the shader cache file when last read.
163 /// @brief Refresh `shaderCacheStatus` from the on-disk shader cache.
165 /// @brief Return the filename in the Name column for the current selection.
166 QString currentShaderName() const;
167 /// @brief Return the row index of the current selection, or -1.
168 int currentShaderRow() const;
169 /// @brief Select the row at @p row and scroll it into view.
170 void selectShaderRow(int row);
171 /// @brief Open or focus an editor for a shader source location.
172 void openShaderEditor(const QString &filePath, int lineNumber = 1,
173 int columnNumber = 0, int matchLength = 0);
174 /// @brief Validate, load, persist, and remember a shader library directory.
175 bool loadLibraryPath(const QString &path);
176 /// @brief Add a library directory to the persisted recent-libraries list.
177 void addRecentLibrary(const QString &path);
178 /// @brief Rebuild the File > Load Recent submenu from persisted settings.
180 /// @brief Select the active rendering backend and restore its paths.
181 void set_backend(acmx2::Backend backend, bool persist = true);
182 /// @brief Update title, actions, and status text for the active backend.
183 void update_backend_ui();
184 /// @brief Return whether the active backend can be launched.
185 bool backend_launch_available() const;
187 RunSelected,
188 RunAll,
189 CopyCommand };
190 enum class AcmxvkBuildMode { Strict,
191 Fix,
192 Prune };
193 /// @brief Offer to rebuild a stale or incomplete ACMXVK source library.
194 void prompt_acmxvk_rebuild(const QString &reason,
195 PendingAcmxvkAction resume_action);
196 /// @brief Start a strict, failure-tolerant, or destructive ACMXVK build.
197 void start_acmxvk_build(const QString &build_path, AcmxvkBuildMode mode);
198 QMenu *fileMenu = nullptr;
199 QMenu *loadRecentMenu = nullptr;
200 QMenu *backendMenu = nullptr;
201 QMenu *cameraMenu = nullptr;
202 QMenu *playbackMenu = nullptr;
203 QMenu *runMenu = nullptr;
204 QMenu *listMenu = nullptr;
205 QMenu *viewMenu = nullptr;
206 QMenu *helpMenu = nullptr;
207 QAction *fileMenu_loadLibrary = nullptr, *fileMenu_prop = nullptr,
208 *fileMenu_exit = nullptr;
209 QAction *cameraSet = nullptr, *audioSet = nullptr;
210 QAction *runMenu_select = nullptr, *runMenu_all = nullptr;
211 QAction *runMenu_copyCommand = nullptr;
212 QActionGroup *backendActionGroup = nullptr;
213 QAction *backendAcmx2Action = nullptr;
214 QAction *backendAcmxvkAction = nullptr;
215 QAction *play_repeat = nullptr, *play_stop = nullptr;
216 QAction *normalizedTimeAction = nullptr;
217 QAction *listMenu_new = nullptr, *listMenu_shader = nullptr, *listMenu_remove = nullptr, *listMenu_set_current = nullptr, *listMenu_up = nullptr, *listMenu_down = nullptr, *listMenu_shuffle = nullptr, *listMenu_sort = nullptr;
218 QAction *libraryBuilderAction = nullptr;
219 QAction *helpMenu_about = nullptr;
220 QAction *helpMenu_uniformReference = nullptr;
221 QAction *listMenu_findNext = nullptr;
222 QAction *listMenu_findInFiles = nullptr;
227 bool cuda_available = false;
229 bool audio_available = false;
230 bool midi_available = false;
231 bool dnn_available = false;
233 void detectCudaSupport();
235 QAction *listMenu_search = nullptr;
236 QString shader_path;
237 QProcess *process = nullptr;
238 QProcess *hdr10Process = nullptr;
239 bool convert_to_hdr10 = false;
241 unsigned int camera_index;
242 QString video_file;
244 QString prefix_path;
245 QString output_file;
246 double output_fps = 24.0f;
247 QString encode_preset = "medium";
248 QString encode_tune; // empty => "none"
249 int encode_crf = 18;
250 QString encode_rate_control = "quality";
251 QString encode_bitrate = "10M";
252 QString encode_codec = "auto";
254 bool encode_realtime = false;
255 bool encode_no_drop = false;
256 bool maximize_fps = false;
257 bool use_source_fps = false;
258 bool use_source_audio = false;
259 /// @brief Join list items into a comma-separated argument string.
260 /// @param lst Input list of values.
261 /// @return Concatenated string for command-line usage.
262 QString concatList(const QStringList lst);
263 /// @brief Build acmx2 command-line arguments from current UI state.
264 /// @param arguments Output list to populate with command-line tokens.
265 /// @param resume_action Action to resume after an ACMXVK build, if needed.
266 /// @return true if arguments were built, false on user-facing error.
268 QStringList &arguments,
270 /// @brief Run ffmpeg to convert the just-produced acmx2 output (assumed
271 /// HLG HDR) into HDR10 (HEVC NVENC, BT.2020 / SMPTE2084) and pipe
272 /// ffmpeg's stdout/stderr to the main log window.
273 void runHdr10Conversion();
274 QVector<QPointer<TextEditor>> open_files;
275 QPointer<QDialog> shaderEditorWorkspace;
276 QTabWidget *shaderEditorTabs = nullptr;
277 /// @brief Read an entire text file into memory.
278 /// @param filePath Path to source file.
279 /// @return File contents, or empty string on failure.
280 QString readFileContents(const QString &filePath);
281 /// @brief Normalize shader names for filesystem/process safety.
282 /// @param name Raw shader name.
283 /// @return Sanitized shader name.
284 QString sanitizeShaderName(const QString &name);
287 /// @brief Restore persisted Session Settings into the launcher's runtime state.
288 void loadSessionSettings();
289 bool audio_enabled = false;
290 unsigned int audio_channels = 2;
291 float audio_sense = 0.25f;
292 bool audio_passthrough = false;
293 bool record_audio = false;
294 double record_volume = 1.0;
295 bool cache_enabled = false;
296 int cache_delay = 1;
297 int cache_size = 8;
298 bool full_screen_value = false;
299 bool copy_audio = false;
300 bool enable_3d = false;
301 bool onnx_model_enabled = false;
302 QString onnx_model;
303 int audio_input = -1;
304 int audio_output = -1;
305 QString audio_file;
306 bool audio_trunc = false;
307 bool audio_repeat = false;
310 double audio_warm_rate = 0.5;
311 QString model_file;
312 bool gpu_filter_enabled = false;
316 QPointer<GPUFilterDialog> gpuFilterDialog;
317 bool deep_dream_enabled = false;
319 QString deep_dream_layer = "relu4_2";
321 double deep_dream_strength = 0.05;
323 double deep_dream_zoom = 1.01;
326 bool deep_dream_fp16 = false;
334 QAction *deepDreamAction = nullptr;
335 QPointer<DeepDreamSettingsDialog> deepDreamSettingsDialog;
337 QPointer<ShaderPassDialog> shaderPassDialog;
338 QPointer<PlaylistDialog> playlistDialog;
339 QPointer<LibraryBuilderDialog> libraryBuilderDialog;
348 void applyMainViewStyles(bool customStyleEnabled);
349 /// @brief Apply or remove the custom stylesheet override.
350 /// @param enable True to apply, false to revert.
351 void applyCustomStyleSheet(bool enable);
353 QStringList shader_pass_names;
354 /// @brief Map selected shader-pass names back to numeric indices.
355 /// @return Comma-separated list of indices used by CLI args.
357 int cuda_device = 0;
358 float time_speed = 1.0f;
359 bool normalized_time = false;
360 bool use_shader_cache = true;
361 bool use_yuv = false;
363 double max_duration = 0.0;
365 double max_size_mb = 0.0;
367 bool flip_enabled = false;
368 bool rotate_enabled = false;
369 QString rotation_mode = "clockwise";
370 bool png_output = false;
371 bool generate_enabled = false;
373 bool watermark_enabled = false;
375 int watermark_r = 255;
376 int watermark_g = 0;
377 int watermark_b = 150;
379 QAction *watermarkAction = nullptr;
380 QAction *displayFilterAction = nullptr;
381 bool midi_enabled = false;
383 int midi_device = -1;
386 QAction *customUniformsAction = nullptr;
388 QPointer<UniformReferenceDialog> uniformReferenceDialog;
389 bool playlist_enabled = false;
390 QStringList playlist_names;
391 QList<QPair<QString, QStringList>> playlist_tree_data;
394 bool autopilot_random = false;
397 /// @brief True while an ACMX2 cache rebuild or ACMXVK source build is running.
401 QProcess *liveShaderCompileProcess = nullptr;
409 QProcess *editorPreviewProcess = nullptr;
419
421 void handleSavedShader(const QString &filePath);
422 void queueAcmxvkLiveCompile(const QString &filePath);
424 void queueAcmxvkEditorPreview(const QString &filePath,
425 const QString &source);
426 bool publishAcmx2EditorPreview(const QString &filePath,
427 const QString &source);
429 void updateOpenEditorCompileStatus(const QString &sourcePath, bool pending,
430 bool success = false,
431 const QString &diagnostics = QString());
433 void publishAcmxvkCompiledShaderReload(const QString &sourcePath,
434 const QString &runtimePath);
436 void publishShaderReloadToRunningProcess(const QString &filePath);
440 [[nodiscard]] bool validateDeepDreamLaunch(QString &error) const;
441 void appendDeepDreamArguments(QStringList &arguments) const;
445#if defined(__linux__) || defined(__APPLE__) || defined(_WIN32)
446 acmx2::ipc::ShaderSelectionShmData *shaderSelectionShm = nullptr;
447#if defined(__linux__) || defined(__APPLE__)
448 int shaderSelectionShmFd = -1;
449 sem_t *shaderSelectionSemaphore = SEM_FAILED;
450#else
451 HANDLE shaderSelectionMapping = nullptr;
452 HANDLE shaderSelectionSemaphore = nullptr;
453#endif
454#endif
455};
456
457#endif
Dialog for building nested shader playlists.
Builds an ordered library from fragment and compute shader files.
Primary ACMX desktop UI.
QVector< QPointer< TextEditor > > open_files
void closeEvent(QCloseEvent *event) override
void prompt_acmxvk_rebuild(const QString &reason, PendingAcmxvkAction resume_action)
Offer to rebuild a stale or incomplete ACMXVK source library.
void listClicked(const QModelIndex &i)
Handle shader list selection changes.
QPointer< UniformReferenceDialog > uniformReferenceDialog
QString currentShaderName() const
Return the filename in the Name column for the current selection.
void applyCustomStyleSheet(bool enable)
Apply or remove the custom stylesheet override.
void menuToggleDisplayFilter(bool checked)
void handleSavedShader(const QString &filePath)
QActionGroup * backendActionGroup
void update_backend_ui()
Update title, actions, and status text for the active backend.
PendingAcmxvkAction pending_acmxvk_action
QHash< QString, bool > shaderCacheStatus
Cached map of shader stem -> failed flag for the current library.
void openShaderEditor(const QString &filePath, int lineNumber=1, int columnNumber=0, int matchLength=0)
Open or focus an editor for a shader source location.
void set_backend(acmx2::Backend backend, bool persist=true)
Select the active rendering backend and restore its paths.
CompileHealth
Compile-health status for a single shader.
void event(SDL_Event &e) override
Placeholder—SDL events are forwarded to ACView::event() by libmx2.
QPointer< PlaylistDialog > playlistDialog
void updateIndex()
Refresh shader index metadata timestamp.
bool addShaderToList(const QString &shaderName)
Add shader to list if it is valid and not already present.
void queueAcmxvkLiveCompile(const QString &filePath)
void populateShaderTree()
Repopulate the shader tree widget from the current items list, recomputing Last Modified,...
void updateOpenEditorCompileStatus(const QString &sourcePath, bool pending, bool success=false, const QString &diagnostics=QString())
QString sanitizeShaderName(const QString &name)
Normalize shader names for filesystem/process safety.
int currentShaderRow() const
Return the row index of the current selection, or -1.
QPointer< QDialog > shaderEditorWorkspace
void applyMainViewStyles(bool customStyleEnabled)
void appendDeepDreamArguments(QStringList &arguments) const
bool validateDeepDreamLaunch(QString &error) const
CustomUniformDialog * customUniformDialog
MainWindow(QWidget *parent=0)
void publishAcmxvkCompiledShaderReload(const QString &sourcePath, const QString &runtimePath)
void Write(const QString &message)
Write raw text to the lower output pane.
void publishSelectedShaderIndexToRunningProcess()
bool cacheBuildInProgress
True while an ACMX2 cache rebuild or ACMXVK source build is running.
void Log(const QString &message)
Append timestamped text to the UI log output.
void refreshShaderCacheStatus()
Refresh shaderCacheStatus from the on-disk shader cache.
QList< QPair< QString, QStringList > > playlist_tree_data
QPointer< DeepDreamSettingsDialog > deepDreamSettingsDialog
bool buildRunArguments(QStringList &arguments, PendingAcmxvkAction resume_action=PendingAcmxvkAction::None)
Build acmx2 command-line arguments from current UI state.
void publishShaderReloadToRunningProcess(const QString &filePath)
void loadSessionSettings()
Restore persisted Session Settings into the launcher's runtime state.
QString readFileContents(const QString &filePath)
Read an entire text file into memory.
QString getShaderPassIndicesFromNames()
Map selected shader-pass names back to numeric indices.
bool publishAcmx2EditorPreview(const QString &filePath, const QString &source)
void selectShaderRow(int row)
Select the row at row and scroll it into view.
QPointer< GPUFilterDialog > gpuFilterDialog
QPointer< ShaderPassDialog > shaderPassDialog
void addRecentLibrary(const QString &path)
Add a library directory to the persisted recent-libraries list.
void updateRecentLibrariesMenu()
Rebuild the File > Load Recent submenu from persisted settings.
void start_acmxvk_build(const QString &build_path, AcmxvkBuildMode mode)
Start a strict, failure-tolerant, or destructive ACMXVK build.
bool backend_launch_available() const
Return whether the active backend can be launched.
void initControls()
Build menus, actions, widgets, and signal wiring.
bool loadShaders(const QString &path, bool force=false)
Load shader names from index/cache for the provided path.
QStringList editorPreviewTemporaryFiles
QPointer< LibraryBuilderDialog > libraryBuilderDialog
void queueAcmxvkEditorPreview(const QString &filePath, const QString &source)
bool loadLibraryPath(const QString &path)
Validate, load, persist, and remember a shader library directory.
void runHdr10Conversion()
Run ffmpeg to convert the just-produced acmx2 output (assumed HLG HDR) into HDR10 (HEVC NVENC,...
QDateTime shaderCacheMTime
Modification time of the shader cache file when last read.
QString concatList(const QStringList lst)
Join list items into a comma-separated argument string.
Searchable reference for uniforms supplied by the ACMX2 runtime.
Shader text editor widgets with line numbers and GLSL highlighting.
UI dialog for configuring chained GPU filter indices.
Dialog for enabling MIDI control and selecting mapping/device settings.
Backend
Definition backend.hpp:8
Dialog for selecting executable and resource directories.
Dialog for creating a new shader file.
Dialog for generating a shader index from a selected folder.
Dialog for configuring ordered multi-pass shader execution.