Various stuff; mostly change to decoder scaling and adding subtitle; scaling test.
[dcpomatic.git] / src / wx / config_dialog.cc
1 /*
2     Copyright (C) 2012 Carl Hetherington <cth@carlh.net>
3
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13
14     You should have received a copy of the GNU General Public License
15     along with this program; if not, write to the Free Software
16     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
18 */
19
20 /** @file src/config_dialog.cc
21  *  @brief A dialogue to edit DCP-o-matic configuration.
22  */
23
24 #include <iostream>
25 #include <boost/lexical_cast.hpp>
26 #include <boost/filesystem.hpp>
27 #include <wx/stdpaths.h>
28 #include <wx/notebook.h>
29 #include "lib/config.h"
30 #include "lib/server.h"
31 #include "lib/ratio.h"
32 #include "lib/scaler.h"
33 #include "lib/filter.h"
34 #include "lib/dcp_content_type.h"
35 #include "config_dialog.h"
36 #include "wx_util.h"
37 #include "filter_dialog.h"
38 #include "server_dialog.h"
39 #include "dir_picker_ctrl.h"
40 #include "dci_metadata_dialog.h"
41
42 using namespace std;
43 using boost::bind;
44
45 ConfigDialog::ConfigDialog (wxWindow* parent)
46         : wxDialog (parent, wxID_ANY, _("DCP-o-matic Preferences"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER)
47 {
48         wxBoxSizer* s = new wxBoxSizer (wxVERTICAL);
49         _notebook = new wxNotebook (this, wxID_ANY);
50         s->Add (_notebook, 1);
51
52         make_misc_panel ();
53         _notebook->AddPage (_misc_panel, _("Miscellaneous"), true);
54         make_servers_panel ();
55         _notebook->AddPage (_servers_panel, _("Encoding servers"), false);
56         make_metadata_panel ();
57         _notebook->AddPage (_metadata_panel, _("Metadata"), false);
58         make_tms_panel ();
59         _notebook->AddPage (_tms_panel, _("TMS"), false);
60         make_ab_panel ();
61         _notebook->AddPage (_ab_panel, _("A/B mode"), false);
62
63         wxBoxSizer* overall_sizer = new wxBoxSizer (wxVERTICAL);
64         overall_sizer->Add (s, 1, wxEXPAND | wxALL, 6);
65
66         wxSizer* buttons = CreateSeparatedButtonSizer (wxOK);
67         if (buttons) {
68                 overall_sizer->Add (buttons, wxSizerFlags().Expand().DoubleBorder());
69         }
70
71         SetSizer (overall_sizer);
72         overall_sizer->Layout ();
73         overall_sizer->SetSizeHints (this);
74 }
75
76 void
77 ConfigDialog::make_misc_panel ()
78 {
79         _misc_panel = new wxPanel (_notebook);
80         wxBoxSizer* s = new wxBoxSizer (wxVERTICAL);
81         _misc_panel->SetSizer (s);
82
83         wxFlexGridSizer* table = new wxFlexGridSizer (3, 6, 6);
84         table->AddGrowableCol (1, 1);
85         s->Add (table, 1, wxALL | wxEXPAND, 8);
86
87         _set_language = new wxCheckBox (_misc_panel, wxID_ANY, _("Set language"));
88         table->Add (_set_language, 1, wxEXPAND);
89         _language = new wxChoice (_misc_panel, wxID_ANY);
90         _language->Append (wxT ("English"));
91         _language->Append (wxT ("Français"));
92         _language->Append (wxT ("Italiano"));
93         _language->Append (wxT ("Español"));
94         _language->Append (wxT ("Svenska"));
95         table->Add (_language, 1, wxEXPAND);
96         table->AddSpacer (0);
97
98         wxStaticText* restart = add_label_to_sizer (table, _misc_panel, _("(restart DCP-o-matic to see language changes)"));
99         wxFont font = restart->GetFont();
100         font.SetStyle (wxFONTSTYLE_ITALIC);
101         font.SetPointSize (font.GetPointSize() - 1);
102         restart->SetFont (font);
103         table->AddSpacer (0);
104         table->AddSpacer (0);
105
106         add_label_to_sizer (table, _misc_panel, _("Threads to use for encoding on this host"));
107         _num_local_encoding_threads = new wxSpinCtrl (_misc_panel);
108         table->Add (_num_local_encoding_threads, 1, wxEXPAND);
109         table->AddSpacer (0);
110
111         add_label_to_sizer (table, _misc_panel, _("Default duration of still images"));
112         _default_still_length = new wxSpinCtrl (_misc_panel);
113         table->Add (_default_still_length, 1, wxEXPAND);
114         add_label_to_sizer (table, _misc_panel, _("s"));
115
116         add_label_to_sizer (table, _misc_panel, _("Default directory for new films"));
117 #ifdef __WXMSW__
118         _default_directory = new DirPickerCtrl (_misc_panel);
119 #else   
120         _default_directory = new wxDirPickerCtrl (_misc_panel, wxDD_DIR_MUST_EXIST);
121 #endif
122         table->Add (_default_directory, 1, wxEXPAND);
123         table->AddSpacer (0);
124
125         add_label_to_sizer (table, _misc_panel, _("Default DCI name details"));
126         _default_dci_metadata_button = new wxButton (_misc_panel, wxID_ANY, _("Edit..."));
127         table->Add (_default_dci_metadata_button);
128         table->AddSpacer (1);
129
130         add_label_to_sizer (table, _misc_panel, _("Default container"));
131         _default_container = new wxChoice (_misc_panel, wxID_ANY);
132         table->Add (_default_container);
133         table->AddSpacer (1);
134
135         add_label_to_sizer (table, _misc_panel, _("Default content type"));
136         _default_dcp_content_type = new wxChoice (_misc_panel, wxID_ANY);
137         table->Add (_default_dcp_content_type);
138         table->AddSpacer (1);
139         
140         Config* config = Config::instance ();
141
142         _set_language->SetValue (config->language ());
143
144         if (config->language().get_value_or ("") == "fr") {
145                 _language->SetSelection (1);
146         } else if (config->language().get_value_or ("") == "it") {
147                 _language->SetSelection (2);
148         } else if (config->language().get_value_or ("") == "es") {
149                 _language->SetSelection (3);
150         } else if (config->language().get_value_or ("") == "sv") {
151                 _language->SetSelection (4);
152         } else {
153                 _language->SetSelection (0);
154         }
155
156         setup_language_sensitivity ();
157
158         _set_language->Connect (wxID_ANY, wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler (ConfigDialog::set_language_changed), 0, this);
159         _language->Connect (wxID_ANY, wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler (ConfigDialog::language_changed), 0, this);
160
161         _num_local_encoding_threads->SetRange (1, 128);
162         _num_local_encoding_threads->SetValue (config->num_local_encoding_threads ());
163         _num_local_encoding_threads->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (ConfigDialog::num_local_encoding_threads_changed), 0, this);
164
165         _default_still_length->SetRange (1, 3600);
166         _default_still_length->SetValue (config->default_still_length ());
167         _default_still_length->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (ConfigDialog::default_still_length_changed), 0, this);
168
169         _default_directory->SetPath (std_to_wx (config->default_directory_or (wx_to_std (wxStandardPaths::Get().GetDocumentsDir()))));
170         _default_directory->Connect (wxID_ANY, wxEVT_COMMAND_DIRPICKER_CHANGED, wxCommandEventHandler (ConfigDialog::default_directory_changed), 0, this);
171
172         _default_dci_metadata_button->Connect (wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (ConfigDialog::edit_default_dci_metadata_clicked), 0, this);
173
174         vector<Ratio const *> ratio = Ratio::all ();
175         int n = 0;
176         for (vector<Ratio const *>::iterator i = ratio.begin(); i != ratio.end(); ++i) {
177                 _default_container->Append (std_to_wx ((*i)->nickname ()));
178                 if (*i == config->default_container ()) {
179                         _default_container->SetSelection (n);
180                 }
181                 ++n;
182         }
183
184         _default_container->Connect (wxID_ANY, wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler (ConfigDialog::default_container_changed), 0, this);
185         
186         vector<DCPContentType const *> const ct = DCPContentType::all ();
187         n = 0;
188         for (vector<DCPContentType const *>::const_iterator i = ct.begin(); i != ct.end(); ++i) {
189                 _default_dcp_content_type->Append (std_to_wx ((*i)->pretty_name ()));
190                 if (*i == config->default_dcp_content_type ()) {
191                         _default_dcp_content_type->SetSelection (n);
192                 }
193                 ++n;
194         }
195
196         _default_dcp_content_type->Connect (wxID_ANY, wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler (ConfigDialog::default_dcp_content_type_changed), 0, this);
197 }
198
199 void
200 ConfigDialog::make_tms_panel ()
201 {
202         _tms_panel = new wxPanel (_notebook);
203         wxBoxSizer* s = new wxBoxSizer (wxVERTICAL);
204         _tms_panel->SetSizer (s);
205
206         wxFlexGridSizer* table = new wxFlexGridSizer (2, 6, 6);
207         table->AddGrowableCol (1, 1);
208         s->Add (table, 1, wxALL | wxEXPAND, 8);
209
210         add_label_to_sizer (table, _tms_panel, _("IP address"));
211         _tms_ip = new wxTextCtrl (_tms_panel, wxID_ANY);
212         table->Add (_tms_ip, 1, wxEXPAND);
213
214         add_label_to_sizer (table, _tms_panel, _("Target path"));
215         _tms_path = new wxTextCtrl (_tms_panel, wxID_ANY);
216         table->Add (_tms_path, 1, wxEXPAND);
217
218         add_label_to_sizer (table, _tms_panel, _("User name"));
219         _tms_user = new wxTextCtrl (_tms_panel, wxID_ANY);
220         table->Add (_tms_user, 1, wxEXPAND);
221
222         add_label_to_sizer (table, _tms_panel, _("Password"));
223         _tms_password = new wxTextCtrl (_tms_panel, wxID_ANY);
224         table->Add (_tms_password, 1, wxEXPAND);
225
226         Config* config = Config::instance ();
227         
228         _tms_ip->SetValue (std_to_wx (config->tms_ip ()));
229         _tms_ip->Connect (wxID_ANY, wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler (ConfigDialog::tms_ip_changed), 0, this);
230         _tms_path->SetValue (std_to_wx (config->tms_path ()));
231         _tms_path->Connect (wxID_ANY, wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler (ConfigDialog::tms_path_changed), 0, this);
232         _tms_user->SetValue (std_to_wx (config->tms_user ()));
233         _tms_user->Connect (wxID_ANY, wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler (ConfigDialog::tms_user_changed), 0, this);
234         _tms_password->SetValue (std_to_wx (config->tms_password ()));
235         _tms_password->Connect (wxID_ANY, wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler (ConfigDialog::tms_password_changed), 0, this);
236 }
237
238 void
239 ConfigDialog::make_ab_panel ()
240 {
241         _ab_panel = new wxPanel (_notebook);
242         wxBoxSizer* s = new wxBoxSizer (wxVERTICAL);
243         _ab_panel->SetSizer (s);
244
245         wxFlexGridSizer* table = new wxFlexGridSizer (3, 6, 6);
246         table->AddGrowableCol (1, 1);
247         s->Add (table, 1, wxALL, 8);
248         
249         add_label_to_sizer (table, _ab_panel, _("Reference scaler"));
250         _reference_scaler = new wxChoice (_ab_panel, wxID_ANY);
251         vector<Scaler const *> const sc = Scaler::all ();
252         for (vector<Scaler const *>::const_iterator i = sc.begin(); i != sc.end(); ++i) {
253                 _reference_scaler->Append (std_to_wx ((*i)->name ()));
254         }
255
256         table->Add (_reference_scaler, 1, wxEXPAND);
257         table->AddSpacer (0);
258
259         {
260                 add_label_to_sizer (table, _ab_panel, _("Reference filters"));
261                 wxSizer* s = new wxBoxSizer (wxHORIZONTAL);
262                 _reference_filters = new wxStaticText (_ab_panel, wxID_ANY, wxT (""));
263                 s->Add (_reference_filters, 1, wxEXPAND);
264                 _reference_filters_button = new wxButton (_ab_panel, wxID_ANY, _("Edit..."));
265                 s->Add (_reference_filters_button, 0);
266                 table->Add (s, 1, wxEXPAND);
267                 table->AddSpacer (0);
268         }
269 }
270
271 void
272 ConfigDialog::make_metadata_panel ()
273 {
274         _metadata_panel = new wxPanel (_notebook);
275         wxBoxSizer* s = new wxBoxSizer (wxVERTICAL);
276         _metadata_panel->SetSizer (s);
277
278         wxFlexGridSizer* table = new wxFlexGridSizer (2, 6, 6);
279         table->AddGrowableCol (1, 1);
280         s->Add (table, 1, wxALL | wxEXPAND, 8);
281
282         add_label_to_sizer (table, _metadata_panel, _("Issuer"));
283         _issuer = new wxTextCtrl (_metadata_panel, wxID_ANY);
284         table->Add (_issuer, 1, wxEXPAND);
285
286         add_label_to_sizer (table, _metadata_panel, _("Creator"));
287         _creator = new wxTextCtrl (_metadata_panel, wxID_ANY);
288         table->Add (_creator, 1, wxEXPAND);
289
290         Config* config = Config::instance ();
291
292         _issuer->SetValue (std_to_wx (config->dcp_metadata().issuer));
293         _issuer->Connect (wxID_ANY, wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler (ConfigDialog::issuer_changed), 0, this);
294         _creator->SetValue (std_to_wx (config->dcp_metadata().creator));
295         _creator->Connect (wxID_ANY, wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler (ConfigDialog::creator_changed), 0, this);
296 }
297
298 void
299 ConfigDialog::make_servers_panel ()
300 {
301         _servers_panel = new wxPanel (_notebook);
302         wxBoxSizer* s = new wxBoxSizer (wxVERTICAL);
303         _servers_panel->SetSizer (s);
304
305         wxFlexGridSizer* table = new wxFlexGridSizer (2, 6, 6);
306         table->AddGrowableCol (0, 1);
307         s->Add (table, 1, wxALL | wxEXPAND, 8);
308
309         Config* config = Config::instance ();
310
311         _servers = new wxListCtrl (_servers_panel, wxID_ANY, wxDefaultPosition, wxSize (220, 100), wxLC_REPORT | wxLC_SINGLE_SEL);
312         wxListItem ip;
313         ip.SetId (0);
314         ip.SetText (_("IP address"));
315         ip.SetWidth (120);
316         _servers->InsertColumn (0, ip);
317         ip.SetId (1);
318         ip.SetText (_("Threads"));
319         ip.SetWidth (80);
320         _servers->InsertColumn (1, ip);
321         table->Add (_servers, 1, wxEXPAND | wxALL);
322
323         {
324                 wxSizer* s = new wxBoxSizer (wxVERTICAL);
325                 _add_server = new wxButton (_servers_panel, wxID_ANY, _("Add"));
326                 s->Add (_add_server);
327                 _edit_server = new wxButton (_servers_panel, wxID_ANY, _("Edit"));
328                 s->Add (_edit_server);
329                 _remove_server = new wxButton (_servers_panel, wxID_ANY, _("Remove"));
330                 s->Add (_remove_server);
331                 table->Add (s, 0);
332         }
333
334         vector<ServerDescription*> servers = config->servers ();
335         for (vector<ServerDescription*>::iterator i = servers.begin(); i != servers.end(); ++i) {
336                 add_server_to_control (*i);
337         }
338         
339         _add_server->Connect (wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (ConfigDialog::add_server_clicked), 0, this);
340         _edit_server->Connect (wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (ConfigDialog::edit_server_clicked), 0, this);
341         _remove_server->Connect (wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (ConfigDialog::remove_server_clicked), 0, this);
342
343         _servers->Connect (wxID_ANY, wxEVT_COMMAND_LIST_ITEM_SELECTED, wxListEventHandler (ConfigDialog::server_selection_changed), 0, this);
344         _servers->Connect (wxID_ANY, wxEVT_COMMAND_LIST_ITEM_DESELECTED, wxListEventHandler (ConfigDialog::server_selection_changed), 0, this);
345         wxListEvent ev;
346         server_selection_changed (ev);
347 }
348
349 void
350 ConfigDialog::language_changed (wxCommandEvent &)
351 {
352         switch (_language->GetSelection ()) {
353         case 0:
354                 Config::instance()->set_language ("en");
355                 break;
356         case 1:
357                 Config::instance()->set_language ("fr");
358                 break;
359         case 2:
360                 Config::instance()->set_language ("it");
361                 break;
362         case 3:
363                 Config::instance()->set_language ("es");
364                 break;
365         case 4:
366                 Config::instance()->set_language ("sv");
367                 break;
368         }
369 }
370
371 void
372 ConfigDialog::tms_ip_changed (wxCommandEvent &)
373 {
374         Config::instance()->set_tms_ip (wx_to_std (_tms_ip->GetValue ()));
375 }
376
377 void
378 ConfigDialog::tms_path_changed (wxCommandEvent &)
379 {
380         Config::instance()->set_tms_path (wx_to_std (_tms_path->GetValue ()));
381 }
382
383 void
384 ConfigDialog::tms_user_changed (wxCommandEvent &)
385 {
386         Config::instance()->set_tms_user (wx_to_std (_tms_user->GetValue ()));
387 }
388
389 void
390 ConfigDialog::tms_password_changed (wxCommandEvent &)
391 {
392         Config::instance()->set_tms_password (wx_to_std (_tms_password->GetValue ()));
393 }
394
395 void
396 ConfigDialog::num_local_encoding_threads_changed (wxCommandEvent &)
397 {
398         Config::instance()->set_num_local_encoding_threads (_num_local_encoding_threads->GetValue ());
399 }
400
401 void
402 ConfigDialog::default_directory_changed (wxCommandEvent &)
403 {
404         Config::instance()->set_default_directory (wx_to_std (_default_directory->GetPath ()));
405 }
406
407 void
408 ConfigDialog::add_server_to_control (ServerDescription* s)
409 {
410         wxListItem item;
411         int const n = _servers->GetItemCount ();
412         item.SetId (n);
413         _servers->InsertItem (item);
414         _servers->SetItem (n, 0, std_to_wx (s->host_name ()));
415         _servers->SetItem (n, 1, std_to_wx (boost::lexical_cast<string> (s->threads ())));
416 }
417
418 void
419 ConfigDialog::add_server_clicked (wxCommandEvent &)
420 {
421         ServerDialog* d = new ServerDialog (this, 0);
422         d->ShowModal ();
423         ServerDescription* s = d->server ();
424         d->Destroy ();
425         
426         add_server_to_control (s);
427         vector<ServerDescription*> o = Config::instance()->servers ();
428         o.push_back (s);
429         Config::instance()->set_servers (o);
430 }
431
432 void
433 ConfigDialog::edit_server_clicked (wxCommandEvent &)
434 {
435         int i = _servers->GetNextItem (-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
436         if (i == -1) {
437                 return;
438         }
439
440         wxListItem item;
441         item.SetId (i);
442         item.SetColumn (0);
443         _servers->GetItem (item);
444
445         vector<ServerDescription*> servers = Config::instance()->servers ();
446         assert (i >= 0 && i < int (servers.size ()));
447
448         ServerDialog* d = new ServerDialog (this, servers[i]);
449         d->ShowModal ();
450         d->Destroy ();
451
452         _servers->SetItem (i, 0, std_to_wx (servers[i]->host_name ()));
453         _servers->SetItem (i, 1, std_to_wx (boost::lexical_cast<string> (servers[i]->threads ())));
454 }
455
456 void
457 ConfigDialog::remove_server_clicked (wxCommandEvent &)
458 {
459         int i = _servers->GetNextItem (-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
460         if (i >= 0) {
461                 _servers->DeleteItem (i);
462         }
463
464         vector<ServerDescription*> o = Config::instance()->servers ();
465         o.erase (o.begin() + i);
466         Config::instance()->set_servers (o);
467 }
468
469 void
470 ConfigDialog::server_selection_changed (wxListEvent &)
471 {
472         int const i = _servers->GetNextItem (-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
473         _edit_server->Enable (i >= 0);
474         _remove_server->Enable (i >= 0);
475 }
476
477 void
478 ConfigDialog::reference_scaler_changed (wxCommandEvent &)
479 {
480         int const n = _reference_scaler->GetSelection ();
481         if (n >= 0) {
482                 Config::instance()->set_reference_scaler (Scaler::from_index (n));
483         }
484 }
485
486 void
487 ConfigDialog::edit_reference_filters_clicked (wxCommandEvent &)
488 {
489         FilterDialog* d = new FilterDialog (this, Config::instance()->reference_filters ());
490         d->ActiveChanged.connect (boost::bind (&ConfigDialog::reference_filters_changed, this, _1));
491         d->ShowModal ();
492         d->Destroy ();
493 }
494
495 void
496 ConfigDialog::reference_filters_changed (vector<Filter const *> f)
497 {
498         Config::instance()->set_reference_filters (f);
499         pair<string, string> p = Filter::ffmpeg_strings (Config::instance()->reference_filters ());
500         _reference_filters->SetLabel (std_to_wx (p.first) + N_(" ") + std_to_wx (p.second));
501 }
502
503 void
504 ConfigDialog::edit_default_dci_metadata_clicked (wxCommandEvent &)
505 {
506         DCIMetadataDialog* d = new DCIMetadataDialog (this, Config::instance()->default_dci_metadata ());
507         d->ShowModal ();
508         Config::instance()->set_default_dci_metadata (d->dci_metadata ());
509         d->Destroy ();
510 }
511
512 void
513 ConfigDialog::set_language_changed (wxCommandEvent& ev)
514 {
515         setup_language_sensitivity ();
516         if (_set_language->GetValue ()) {
517                 language_changed (ev);
518         } else {
519                 Config::instance()->unset_language ();
520         }
521 }
522
523 void
524 ConfigDialog::setup_language_sensitivity ()
525 {
526         _language->Enable (_set_language->GetValue ());
527 }
528
529 void
530 ConfigDialog::default_still_length_changed (wxCommandEvent &)
531 {
532         Config::instance()->set_default_still_length (_default_still_length->GetValue ());
533 }
534
535 void
536 ConfigDialog::default_container_changed (wxCommandEvent &)
537 {
538         vector<Ratio const *> ratio = Ratio::all ();
539         Config::instance()->set_default_container (ratio[_default_container->GetSelection()]);
540 }
541
542 void
543 ConfigDialog::default_dcp_content_type_changed (wxCommandEvent &)
544 {
545         vector<DCPContentType const *> ct = DCPContentType::all ();
546         Config::instance()->set_default_dcp_content_type (ct[_default_dcp_content_type->GetSelection()]);
547 }
548
549 void
550 ConfigDialog::issuer_changed (wxCommandEvent &)
551 {
552         libdcp::XMLMetadata m = Config::instance()->dcp_metadata ();
553         m.issuer = wx_to_std (_issuer->GetValue ());
554         Config::instance()->set_dcp_metadata (m);
555 }
556
557 void
558 ConfigDialog::creator_changed (wxCommandEvent &)
559 {
560         libdcp::XMLMetadata m = Config::instance()->dcp_metadata ();
561         m.creator = wx_to_std (_creator->GetValue ());
562         Config::instance()->set_dcp_metadata (m);
563 }