Merge remote-tracking branch 'origin/main' into v2.17.x
[dcpomatic.git] / src / wx / grok / gpu_config_panel.h
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 #pragma once
23
24 static std::vector<std::string> get_gpu_names(boost::filesystem::path binary, boost::filesystem::path filename)
25 {
26     // Execute the GPU listing program and redirect its output to a file
27     if (std::system((binary.string() + " > " + filename.string()).c_str()) < 0) {
28             return {};
29     }
30
31     std::vector<std::string> gpu_names;
32     std::ifstream file(filename.c_str());
33     if (file.is_open())
34     {
35         std::string line;
36         while (std::getline(file, line))
37             gpu_names.push_back(line);
38         file.close();
39     }
40
41     return gpu_names;
42 }
43
44
45 class GpuList : public wxPanel
46 {
47 public:
48         GpuList(wxPanel* parent)
49                 : wxPanel(parent, wxID_ANY)
50         {
51                 _combo_box = new wxComboBox(this, wxID_ANY, "", wxDefaultPosition, wxSize(400, -1));
52                 _combo_box->Bind(wxEVT_COMBOBOX, &GpuList::OnComboBox, this);
53                 update();
54
55                 auto sizer = new wxBoxSizer(wxHORIZONTAL);
56                 sizer->Add(_combo_box, 0, wxALIGN_CENTER_VERTICAL);
57                 SetSizerAndFit(sizer);
58         }
59
60         void update()
61         {
62                 auto grok = Config::instance()->grok().get_value_or({});
63                 auto lister_binary = grok.binary_location / "gpu_lister";
64                 auto lister_file = grok.binary_location / "gpus.txt";
65                 if (boost::filesystem::exists(lister_binary)) {
66                         auto gpu_names = get_gpu_names(lister_binary, lister_file);
67
68                         _combo_box->Clear();
69                         for (auto const& name: gpu_names) {
70                                 _combo_box->Append(name);
71                         }
72                 }
73         }
74
75         void set_selection(int sel)
76         {
77                 if (sel < static_cast<int>(_combo_box->GetCount())) {
78                         _combo_box->SetSelection(sel);
79                 }
80         }
81
82 private:
83         void OnComboBox(wxCommandEvent&)
84         {
85                 auto selection = _combo_box->GetSelection();
86                 if (selection != wxNOT_FOUND) {
87                         auto grok = Config::instance()->grok().get_value_or({});
88                         grok.selected = selection;
89                         Config::instance()->set_grok(grok);
90                 }
91         }
92
93         wxComboBox* _combo_box;
94         int _selection = 0;
95 };
96
97
98 class GPUPage : public Page
99 {
100 public:
101         GPUPage(wxSize panel_size, int border)
102                 : Page(panel_size, border)
103         {}
104
105         wxString GetName() const override
106         {
107                 return _("GPU");
108         }
109
110 #ifdef DCPOMATIC_OSX
111         /* XXX: this icon does not exist */
112         wxBitmap GetLargeIcon() const override
113         {
114                 return wxBitmap(icon_path("gpu"), wxBITMAP_TYPE_PNG);
115         }
116 #endif
117
118 private:
119         void setup() override
120         {
121                 _enable_gpu = new CheckBox(_panel, _("Enable GPU acceleration"));
122                 _panel->GetSizer()->Add(_enable_gpu, 0, wxALL | wxEXPAND, _border);
123
124                 wxFlexGridSizer* table = new wxFlexGridSizer(2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
125                 table->AddGrowableCol(1, 1);
126                 _panel->GetSizer()->Add(table, 1, wxALL | wxEXPAND, _border);
127
128                 add_label_to_sizer(table, _panel, _("Acceleration binary folder"), true, 0, wxLEFT | wxLEFT | wxALIGN_CENTRE_VERTICAL);
129                 _binary_location = new wxDirPickerCtrl(_panel, wxDD_DIR_MUST_EXIST);
130                 table->Add(_binary_location, 1, wxEXPAND);
131
132                 add_label_to_sizer(table, _panel, _("GPU selection"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
133                 _gpu_list_control = new GpuList(_panel);
134                 table->Add(_gpu_list_control, 1, wxEXPAND);
135
136                 add_label_to_sizer(table, _panel, _("License server"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
137                 _server = new wxTextCtrl(_panel, wxID_ANY);
138                 table->Add(_server, 1, wxEXPAND | wxALL);
139
140                 add_label_to_sizer(table, _panel, _("Port"), false, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
141                 _port = new wxSpinCtrl(_panel, wxID_ANY);
142                 _port->SetRange(0, 65535);
143                 table->Add(_port);
144
145                 add_label_to_sizer(table, _panel, _("License"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
146                 _licence = new PasswordEntry(_panel);
147                 table->Add(_licence->get_panel(), 1, wxEXPAND | wxALL);
148
149                 _enable_gpu->bind(&GPUPage::enable_gpu_changed, this);
150                 _binary_location->Bind(wxEVT_DIRPICKER_CHANGED, boost::bind (&GPUPage::binary_location_changed, this));
151                 _server->Bind(wxEVT_TEXT, boost::bind(&GPUPage::server_changed, this));
152                 _port->Bind(wxEVT_SPINCTRL, boost::bind(&GPUPage::port_changed, this));
153                 _licence->Changed.connect(boost::bind(&GPUPage::licence_changed, this));
154
155                 setup_sensitivity();
156         }
157
158         void setup_sensitivity()
159         {
160                 auto grok = Config::instance()->grok().get_value_or({});
161
162                 _binary_location->Enable(grok.enable);
163                 _gpu_list_control->Enable(grok.enable);
164                 _server->Enable(grok.enable);
165                 _port->Enable(grok.enable);
166                 _licence->get_panel()->Enable(grok.enable);
167         }
168
169         void config_changed() override
170         {
171                 auto grok = Config::instance()->grok().get_value_or({});
172
173                 checked_set(_enable_gpu, grok.enable);
174                 _binary_location->SetPath(std_to_wx(grok.binary_location.string()));
175                 _gpu_list_control->update();
176                 _gpu_list_control->set_selection(grok.selected);
177                 checked_set(_server, grok.licence_server);
178                 checked_set(_port, grok.licence_port);
179                 checked_set(_licence, grok.licence);
180         }
181
182         void enable_gpu_changed()
183         {
184                 auto grok = Config::instance()->grok().get_value_or({});
185                 grok.enable = _enable_gpu->GetValue();
186                 Config::instance()->set_grok(grok);
187
188                 setup_sensitivity();
189         }
190
191         void binary_location_changed()
192         {
193                 auto grok = Config::instance()->grok().get_value_or({});
194                 grok.binary_location = wx_to_std(_binary_location->GetPath());
195                 Config::instance()->set_grok(grok);
196
197                 _gpu_list_control->update();
198         }
199
200         void server_changed()
201         {
202                 auto grok = Config::instance()->grok().get_value_or({});
203                 grok.licence_server = wx_to_std(_server->GetValue());
204                 Config::instance()->set_grok(grok);
205         }
206
207         void port_changed()
208         {
209                 auto grok = Config::instance()->grok().get_value_or({});
210                 grok.licence_port = _port->GetValue();
211                 Config::instance()->set_grok(grok);
212         }
213
214         void licence_changed()
215         {
216                 auto grok = Config::instance()->grok().get_value_or({});
217                 grok.licence = wx_to_std(_licence->get());
218                 Config::instance()->set_grok(grok);
219         }
220
221         CheckBox* _enable_gpu = nullptr;
222         wxDirPickerCtrl* _binary_location = nullptr;
223         GpuList* _gpu_list_control = nullptr;
224         wxTextCtrl* _server = nullptr;
225         wxSpinCtrl* _port = nullptr;
226         PasswordEntry* _licence = nullptr;
227 };