Add config options for some of the DCP XML metadata (#122).
[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/format.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 directory for new films"));
112 #ifdef __WXMSW__
113         _default_directory = new DirPickerCtrl (_misc_panel);
114 #else   
115         _default_directory = new wxDirPickerCtrl (_misc_panel, wxDD_DIR_MUST_EXIST);
116 #endif
117         table->Add (_default_directory, 1, wxEXPAND);
118         table->AddSpacer (0);
119
120         add_label_to_sizer (table, _misc_panel, _("Default DCI name details"));
121         _default_dci_metadata_button = new wxButton (_misc_panel, wxID_ANY, _("Edit..."));
122         table->Add (_default_dci_metadata_button);
123         table->AddSpacer (1);
124
125         add_label_to_sizer (table, _misc_panel, _("Default format"));
126         _default_format = new wxChoice (_misc_panel, wxID_ANY);
127         table->Add (_default_format);
128         table->AddSpacer (1);
129
130         add_label_to_sizer (table, _misc_panel, _("Default content type"));
131         _default_dcp_content_type = new wxChoice (_misc_panel, wxID_ANY);
132         table->Add (_default_dcp_content_type);
133         table->AddSpacer (1);
134         
135         Config* config = Config::instance ();
136
137         _set_language->SetValue (config->language ());
138
139         if (config->language().get_value_or ("") == "fr") {
140                 _language->SetSelection (1);
141         } else if (config->language().get_value_or ("") == "it") {
142                 _language->SetSelection (2);
143         } else if (config->language().get_value_or ("") == "es") {
144                 _language->SetSelection (3);
145         } else if (config->language().get_value_or ("") == "sv") {
146                 _language->SetSelection (4);
147         } else {
148                 _language->SetSelection (0);
149         }
150
151         setup_language_sensitivity ();
152
153         _set_language->Connect (wxID_ANY, wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler (ConfigDialog::set_language_changed), 0, this);
154         _language->Connect (wxID_ANY, wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler (ConfigDialog::language_changed), 0, this);
155
156         _num_local_encoding_threads->SetRange (1, 128);
157         _num_local_encoding_threads->SetValue (config->num_local_encoding_threads ());
158         _num_local_encoding_threads->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (ConfigDialog::num_local_encoding_threads_changed), 0, this);
159
160         _default_directory->SetPath (std_to_wx (config->default_directory_or (wx_to_std (wxStandardPaths::Get().GetDocumentsDir()))));
161         _default_directory->Connect (wxID_ANY, wxEVT_COMMAND_DIRPICKER_CHANGED, wxCommandEventHandler (ConfigDialog::default_directory_changed), 0, this);
162
163         _default_dci_metadata_button->Connect (wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (ConfigDialog::edit_default_dci_metadata_clicked), 0, this);
164
165         vector<Format const *> fmt = Format::all ();
166         int n = 0;
167         for (vector<Format const *>::iterator i = fmt.begin(); i != fmt.end(); ++i) {
168                 _default_format->Append (std_to_wx ((*i)->name ()));
169                 if (*i == config->default_format ()) {
170                         _default_format->SetSelection (n);
171                 }
172                 ++n;
173         }
174
175         _default_format->Connect (wxID_ANY, wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler (ConfigDialog::default_format_changed), 0, this);
176         
177         vector<DCPContentType const *> const ct = DCPContentType::all ();
178         n = 0;
179         for (vector<DCPContentType const *>::const_iterator i = ct.begin(); i != ct.end(); ++i) {
180                 _default_dcp_content_type->Append (std_to_wx ((*i)->pretty_name ()));
181                 if (*i == config->default_dcp_content_type ()) {
182                         _default_dcp_content_type->SetSelection (n);
183                 }
184                 ++n;
185         }
186
187         _default_dcp_content_type->Connect (wxID_ANY, wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler (ConfigDialog::default_dcp_content_type_changed), 0, this);
188 }
189
190 void
191 ConfigDialog::make_tms_panel ()
192 {
193         _tms_panel = new wxPanel (_notebook);
194         wxBoxSizer* s = new wxBoxSizer (wxVERTICAL);
195         _tms_panel->SetSizer (s);
196
197         wxFlexGridSizer* table = new wxFlexGridSizer (2, 6, 6);
198         table->AddGrowableCol (1, 1);
199         s->Add (table, 1, wxALL | wxEXPAND, 8);
200
201         add_label_to_sizer (table, _tms_panel, _("IP address"));
202         _tms_ip = new wxTextCtrl (_tms_panel, wxID_ANY);
203         table->Add (_tms_ip, 1, wxEXPAND);
204
205         add_label_to_sizer (table, _tms_panel, _("Target path"));
206         _tms_path = new wxTextCtrl (_tms_panel, wxID_ANY);
207         table->Add (_tms_path, 1, wxEXPAND);
208
209         add_label_to_sizer (table, _tms_panel, _("User name"));
210         _tms_user = new wxTextCtrl (_tms_panel, wxID_ANY);
211         table->Add (_tms_user, 1, wxEXPAND);
212
213         add_label_to_sizer (table, _tms_panel, _("Password"));
214         _tms_password = new wxTextCtrl (_tms_panel, wxID_ANY);
215         table->Add (_tms_password, 1, wxEXPAND);
216
217         Config* config = Config::instance ();
218         
219         _tms_ip->SetValue (std_to_wx (config->tms_ip ()));
220         _tms_ip->Connect (wxID_ANY, wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler (ConfigDialog::tms_ip_changed), 0, this);
221         _tms_path->SetValue (std_to_wx (config->tms_path ()));
222         _tms_path->Connect (wxID_ANY, wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler (ConfigDialog::tms_path_changed), 0, this);
223         _tms_user->SetValue (std_to_wx (config->tms_user ()));
224         _tms_user->Connect (wxID_ANY, wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler (ConfigDialog::tms_user_changed), 0, this);
225         _tms_password->SetValue (std_to_wx (config->tms_password ()));
226         _tms_password->Connect (wxID_ANY, wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler (ConfigDialog::tms_password_changed), 0, this);
227 }
228
229 void
230 ConfigDialog::make_metadata_panel ()
231 {
232         _metadata_panel = new wxPanel (_notebook);
233         wxBoxSizer* s = new wxBoxSizer (wxVERTICAL);
234         _metadata_panel->SetSizer (s);
235
236         wxFlexGridSizer* table = new wxFlexGridSizer (2, 6, 6);
237         table->AddGrowableCol (1, 1);
238         s->Add (table, 1, wxALL | wxEXPAND, 8);
239
240         add_label_to_sizer (table, _metadata_panel, _("Issuer"));
241         _issuer = new wxTextCtrl (_metadata_panel, wxID_ANY);
242         table->Add (_issuer, 1, wxEXPAND);
243
244         add_label_to_sizer (table, _metadata_panel, _("Creator"));
245         _creator = new wxTextCtrl (_metadata_panel, wxID_ANY);
246         table->Add (_creator, 1, wxEXPAND);
247
248         Config* config = Config::instance ();
249
250         _issuer->SetValue (std_to_wx (config->dcp_metadata().issuer));
251         _issuer->Connect (wxID_ANY, wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler (ConfigDialog::issuer_changed), 0, this);
252         _creator->SetValue (std_to_wx (config->dcp_metadata().creator));
253         _creator->Connect (wxID_ANY, wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler (ConfigDialog::creator_changed), 0, this);
254 }
255
256 void
257 ConfigDialog::make_ab_panel ()
258 {
259         _ab_panel = new wxPanel (_notebook);
260         wxBoxSizer* s = new wxBoxSizer (wxVERTICAL);
261         _ab_panel->SetSizer (s);
262
263         wxFlexGridSizer* table = new wxFlexGridSizer (3, 6, 6);
264         table->AddGrowableCol (1, 1);
265         s->Add (table, 1, wxALL, 8);
266         
267         add_label_to_sizer (table, _ab_panel, _("Reference scaler"));
268         _reference_scaler = new wxChoice (_ab_panel, wxID_ANY);
269         vector<Scaler const *> const sc = Scaler::all ();
270         for (vector<Scaler const *>::const_iterator i = sc.begin(); i != sc.end(); ++i) {
271                 _reference_scaler->Append (std_to_wx ((*i)->name ()));
272         }
273
274         table->Add (_reference_scaler, 1, wxEXPAND);
275         table->AddSpacer (0);
276
277         {
278                 add_label_to_sizer (table, _ab_panel, _("Reference filters"));
279                 wxSizer* s = new wxBoxSizer (wxHORIZONTAL);
280                 _reference_filters = new wxStaticText (_ab_panel, wxID_ANY, wxT (""));
281                 s->Add (_reference_filters, 1, wxALIGN_CENTER_VERTICAL | wxEXPAND | wxALL, 6);
282                 _reference_filters_button = new wxButton (_ab_panel, wxID_ANY, _("Edit..."));
283                 s->Add (_reference_filters_button, 0);
284                 table->Add (s, 1, wxEXPAND);
285                 table->AddSpacer (0);
286         }
287
288         Config* config = Config::instance ();
289         
290         _reference_scaler->SetSelection (Scaler::as_index (config->reference_scaler ()));
291         _reference_scaler->Connect (wxID_ANY, wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler (ConfigDialog::reference_scaler_changed), 0, this);
292
293         pair<string, string> p = Filter::ffmpeg_strings (config->reference_filters ());
294         _reference_filters->SetLabel (std_to_wx (p.first) + N_(" ") + std_to_wx (p.second));
295         _reference_filters_button->Connect (wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (ConfigDialog::edit_reference_filters_clicked), 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_format_changed (wxCommandEvent &)
531 {
532         vector<Format const *> fmt = Format::all ();
533         Config::instance()->set_default_format (fmt[_default_format->GetSelection()]);
534 }
535
536 void
537 ConfigDialog::default_dcp_content_type_changed (wxCommandEvent &)
538 {
539         vector<DCPContentType const *> ct = DCPContentType::all ();
540         Config::instance()->set_default_dcp_content_type (ct[_default_dcp_content_type->GetSelection()]);
541 }
542
543 void
544 ConfigDialog::issuer_changed (wxCommandEvent &)
545 {
546         libdcp::XMLMetadata m = Config::instance()->dcp_metadata ();
547         m.issuer = wx_to_std (_issuer->GetValue ());
548         Config::instance()->set_dcp_metadata (m);
549 }
550
551 void
552 ConfigDialog::creator_changed (wxCommandEvent &)
553 {
554         libdcp::XMLMetadata m = Config::instance()->dcp_metadata ();
555         m.creator = wx_to_std (_creator->GetValue ());
556         Config::instance()->set_dcp_metadata (m);
557 }