e8f036bfb7d63e3672237921404359ff7c43dcca
[dcpomatic.git] / src / wx / gpu_config_panel.cc
1 /*
2     Copyright (C) 2023 Grok Image Compression Inc.
3
4     This file is part of DCP-o-matic.
5
6     DCP-o-matic is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.
10
11     DCP-o-matic is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15
16     You should have received a copy of the GNU General Public License
17     along with DCP-o-matic.  If not, see <http://www.gnu.org/licenses/>.
18
19 */
20
21
22 #include "check_box.h"
23 #include "dir_picker_ctrl.h"
24 #include "gpu_config_panel.h"
25 #include "password_entry.h"
26 #include <wx/panel.h>
27 #include <wx/wx.h>
28
29
30 #include <fstream>
31 #include <string>
32 #include <vector>
33
34
35 static std::vector<std::string>
36 get_gpu_names(boost::filesystem::path binary, boost::filesystem::path filename)
37 {
38         // Execute the GPU listing program and redirect its output to a file
39         std::system((binary.string() + " > " + filename.string()).c_str());
40
41         std::vector<std::string> gpu_names;
42         std::ifstream file(filename.string());
43         if (file.is_open()) {
44                 std::string line;
45                 while (std::getline(file, line)) {
46                         gpu_names.push_back(line);
47                 }
48                 file.close();
49         }
50
51         return gpu_names;
52 }
53
54
55 class GPUList : public wxPanel
56 {
57 public:
58         GPUList(wxPanel* parent)
59                 : wxPanel(parent, wxID_ANY)
60                 , _selection(0)
61         {
62                 _combo_box = new wxComboBox(this, wxID_ANY, "", wxDefaultPosition, wxSize(400, -1));
63                 _combo_box->Bind(wxEVT_COMBOBOX, &GPUList::on_combo_box, this);
64                 update();
65
66                 wxBoxSizer* sizer = new wxBoxSizer(wxHORIZONTAL);
67
68                 sizer->Add(_combo_box, 0, wxALIGN_CENTER_VERTICAL); // Vertically center the comboBox
69
70                 this->SetSizerAndFit(sizer);
71         }
72
73         void update()
74         {
75                 auto binary = Config::instance()->gpu_binary_location();
76                 DCPOMATIC_ASSERT(binary);
77                 auto lister_binary = *binary / "gpu_lister";
78                 auto lister_file = *binary / "gpus.txt";
79                 if (boost::filesystem::exists(lister_binary)) {
80                         auto gpu_names = get_gpu_names(lister_binary, lister_file);
81
82                         _combo_box->Clear();
83                         for (const auto& name : gpu_names) {
84                                 _combo_box->Append(name);
85                         }
86                 }
87         }
88
89         int get_selection()
90         {
91                 return _selection;
92         }
93
94         void set_selection(int sel)
95         {
96                 if ((int)_combo_box->GetCount() > sel) {
97                         _combo_box->SetSelection(sel);
98                 }
99         }
100
101 private:
102         void on_combo_box([[maybe_unused]] wxCommandEvent& event)
103         {
104                 _selection = _combo_box->GetSelection();
105                 if (_selection != wxNOT_FOUND) {
106                         Config::instance()->set_selected_gpu(_selection);
107                 }
108         }
109
110         wxComboBox* _combo_box;
111         int _selection;
112 };
113
114
115 GPUPage::GPUPage(wxSize panel_size, int border)
116         : Page(panel_size, border)
117         , _enable_gpu(nullptr)
118         , _binary_location(nullptr)
119         , _gpu_list_control(nullptr)
120 {
121
122 }
123
124
125 wxString
126 GPUPage::GetName() const
127 {
128         return _("GPU");
129 }
130
131
132 #ifdef DCPOMATIC_OSX
133 wxBitmap
134 GPUPage::GetLargeIcon() const
135 {
136         return wxBitmap(icon_path("tms"), wxBITMAP_TYPE_PNG);
137 }
138 #endif
139
140
141 void
142 GPUPage::setup()
143 {
144         auto config = Config::instance();
145
146         _enable_gpu = new CheckBox(_panel, _("Enable GPU acceleration"));
147         _panel->GetSizer()->Add(_enable_gpu, 0, wxALL | wxEXPAND, _border);
148
149         wxFlexGridSizer* table = new wxFlexGridSizer(2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
150         table->AddGrowableCol(1, 1);
151         _panel->GetSizer()->Add(table, 1, wxALL | wxEXPAND, _border);
152
153         add_label_to_sizer(table, _panel, _("Acceleration binary folder"), true, 0, wxLEFT | wxLEFT | wxALIGN_CENTRE_VERTICAL);
154         _binary_location = new DirPickerCtrl(_panel);
155         table->Add(_binary_location, 1, wxEXPAND);
156
157         add_label_to_sizer(table, _panel, _("GPU selection"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
158         _gpu_list_control = new GPUList(_panel);
159         table->Add(_gpu_list_control, 1, wxEXPAND);
160
161         add_label_to_sizer(table, _panel, _("License server"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
162         _server = new wxTextCtrl(_panel, wxID_ANY);
163         table->Add(_server, 1, wxEXPAND | wxALL);
164
165         add_label_to_sizer(table, _panel, _("Port"), false, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
166         _port = new wxSpinCtrl(_panel, wxID_ANY);
167         _port->SetRange(0, 65535);
168         table->Add(_port);
169
170         add_label_to_sizer(table, _panel, _("License"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
171         _license = new PasswordEntry(_panel);
172         table->Add(_license->get_panel(), 1, wxEXPAND | wxALL);
173
174         _enable_gpu->bind(&GPUPage::enable_gpu_changed, this);
175         _binary_location->Bind(wxEVT_DIRPICKER_CHANGED, boost::bind(&GPUPage::binary_location_changed, this));
176         _server->Bind(wxEVT_TEXT, boost::bind(&GPUPage::server_changed, this));
177         _port->Bind(wxEVT_SPINCTRL, boost::bind(&GPUPage::port_changed, this));
178         _license->Changed.connect(boost::bind(&GPUPage::license_changed, this));
179
180         _binary_location->Enable(config->enable_gpu());
181         _gpu_list_control->Enable(config->enable_gpu());
182         _server->Enable(config->enable_gpu());
183         _port->Enable(config->enable_gpu());
184         _license->get_panel()->Enable(config->enable_gpu());
185 }
186
187
188 void GPUPage::config_changed()
189 {
190         auto config = Config::instance();
191
192         checked_set(_enable_gpu, config->enable_gpu());
193         if (auto binary = config->gpu_binary_location()) {
194                 _binary_location->SetPath(std_to_wx(binary->string()));
195         } else {
196                 _binary_location->SetPath(wxT(""));
197         }
198         _gpu_list_control->update();
199         _gpu_list_control->set_selection(config->selected_gpu());
200         checked_set(_server, config->gpu_license_server());
201         checked_set(_port, config->gpu_license_port());
202         checked_set(_license, config->gpu_license());
203 }
204
205
206 void GPUPage::enable_gpu_changed()
207 {
208         auto config = Config::instance();
209
210         config->set_enable_gpu(_enable_gpu->GetValue());
211         _binary_location->Enable(config->enable_gpu());
212         _gpu_list_control->Enable(config->enable_gpu());
213         _server->Enable(config->enable_gpu());
214         _port->Enable(config->enable_gpu());
215         _license->get_panel()->Enable(config->enable_gpu());
216 }
217
218
219 void GPUPage::binary_location_changed()
220 {
221         Config::instance()->set_gpu_binary_location(wx_to_std(_binary_location->GetPath()));
222         _gpu_list_control->update();
223 }
224
225
226 void GPUPage::server_changed()
227 {
228         Config::instance()->set_gpu_license_server(wx_to_std(_server->GetValue()));
229 }
230
231
232 void GPUPage::port_changed()
233 {
234         Config::instance()->set_gpu_license_port(_port->GetValue());
235 }
236
237
238 void GPUPage::license_changed()
239 {
240         Config::instance()->set_gpu_license(_license->get());
241 }
242